diff --git a/.config/admin_java_and_deps.winget b/.config/admin_java_and_deps.winget index e32d73230870..af3a089e4757 100644 --- a/.config/admin_java_and_deps.winget +++ b/.config/admin_java_and_deps.winget @@ -68,9 +68,9 @@ properties: securityContext: elevated settings: DestinationPath: C:/Users/Public/Downloads - Uri: https://dlcdn.apache.org/ant/binaries/apache-ant-1.10.15-bin.zip + Uri: https://archive.apache.org/dist/ant/binaries/apache-ant-1.10.18-bin.zip ChecksumType: SHA256 - Checksum: e59baf898dc5b6d1aa6cd57544715f7e0060b1fdc9e56f24f9898d56612a9e0b + Checksum: d3d2009bc815e8fe4808e3af2f2aa7019cd666a26d112a3d9ea5a45345edf236 - resource: xPSDesiredStateConfiguration/xRemoteFile id: junit directives: diff --git a/.config/user_steps.winget b/.config/user_steps.winget index 5ae444618b59..5ad1099a3a3f 100644 --- a/.config/user_steps.winget +++ b/.config/user_steps.winget @@ -18,7 +18,7 @@ properties: # the empty string element is so that each file can be specified with trailing comma TestScript: | $files = @( - "apache-ant-1.10.15-bin.zip", + "apache-ant-1.10.18-bin.zip", "clang-format-5.0.0-win.exe", "jom_1_1_4.zip", "junit-4.10.jar", @@ -112,9 +112,9 @@ properties: directives: description: extract ant to the ~/lo directory settings: - TestScript: Test-Path -Path "$env:USERPROFILE/lo/apache-ant-1.10.15/bin/ant" - GetScript: Test-Path -Path "$env:USERPROFILE/lo/apache-ant-1.10.15/bin/ant" - SetScript: Expand-Archive -LiteralPath "$env:PUBLIC/Downloads/apache-ant-1.10.15-bin.zip" -Destination "$env:USERPROFILE/lo/" + TestScript: Test-Path -Path "$env:USERPROFILE/lo/apache-ant-1.10.18/bin/ant" + GetScript: Test-Path -Path "$env:USERPROFILE/lo/apache-ant-1.10.18/bin/ant" + SetScript: Expand-Archive -LiteralPath "$env:PUBLIC/Downloads/apache-ant-1.10.18-bin.zip" -Destination "$env:USERPROFILE/lo/" - resource: xPSDesiredStateConfiguration/xScript id: spp-extract dependsOn: @@ -181,7 +181,7 @@ properties: --disable-online-update --with-external-tar=$env:USERPROFILE\lo\lo-externaltar --with-strawberry-perl-portable=$env:USERPROFILE\lo\spp - --with-ant-home=$env:USERPROFILE\lo\apache-ant-1.10.15 + --with-ant-home=$env:USERPROFILE\lo\apache-ant-1.10.18 --with-junit=$env:USERPROFILE\lo\junit-4.10.jar --with-doxygen=$env:USERPROFILE\lo\spp\c\bin\doxygen.exe #--enable-odk diff --git a/.cspell/libreoffice.txt b/.cspell/libreoffice.txt index fa7674986492..37a0622f9c56 100644 --- a/.cspell/libreoffice.txt +++ b/.cspell/libreoffice.txt @@ -48,7 +48,6 @@ libwebp libwps libzxing loplugin -lpsolve MAKEFLAGS mergelibs msgfmt diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 725c287d9caa..1d67b65b49aa 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -132,3 +132,5 @@ b53fa6344d033f8b8f03b9274dbdd811251c2c1a e02a7a55c23d23dd7afa2627a7e10c70e1cba001 1c235c1343ed7b88a3e6b923b9b0d6e567054f1c 5159de5febd02cd5a509e97c93df8ea26af0c65d +05ba63c6fce1954e52399e01ffbde2ff4f55f19e +ddb95685dda6b0935322c36fc648e3f4f46a62fe diff --git a/Makefile.fetch b/Makefile.fetch index 29a9fc6e4b14..04d38de2172c 100644 --- a/Makefile.fetch +++ b/Makefile.fetch @@ -107,6 +107,7 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S $(call fetch_Optional,BOOST,BOOST_TARBALL) \ $(call fetch_Optional,BOX2D,BOX2D_TARBALL) \ $(call fetch_Optional,BREAKPAD,BREAKPAD_TARBALL) \ + $(call fetch_Optional,BROTLI,BROTLI_TARBALL) \ $(call fetch_Optional,BSH,BSH_TARBALL) \ $(call fetch_Optional,BZIP2,BZIP2_TARBALL) \ $(call fetch_Optional,CAIRO,CAIRO_TARBALL) \ @@ -134,6 +135,7 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S $(call fetch_Optional,GPGMEPP,GPGME_TARBALL) \ $(call fetch_Optional,GRAPHITE,GRAPHITE_TARBALL) \ $(call fetch_Optional,HARFBUZZ,HARFBUZZ_TARBALL) \ + $(call fetch_Optional,HIGHWAY,HIGHWAY_TARBALL) \ $(call fetch_Optional,HSQLDB,HSQLDB_TARBALL) \ $(call fetch_Optional,HUNSPELL,HUNSPELL_TARBALL) \ $(call fetch_Optional,HYPHEN,HYPHEN_TARBALL) \ @@ -160,6 +162,7 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S $(call fetch_Optional,LIBEXTTEXTCAT,LIBEXTTEXTCAT_TARBALL) \ $(call fetch_Optional,LIBFFI,LIBFFI_TARBALL) \ $(call fetch_Optional,LIBGPGERROR,LIBGPGERROR_TARBALL) \ + $(call fetch_Optional,LIBJXL,LIBJXL_TARBALL) \ $(call fetch_Optional,LIBLANGTAG,LANGTAGREG_TARBALL) \ $(call fetch_Optional,LIBLANGTAG,LIBLANGTAG_TARBALL) \ $(call fetch_Optional,LIBNUMBERTEXT,LIBNUMBERTEXT_TARBALL) \ @@ -170,7 +173,6 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S $(call fetch_Optional,LIBXML2,LIBXML_TARBALL) \ $(call fetch_Optional,XMLSEC,XMLSEC_TARBALL) \ $(call fetch_Optional,LIBXSLT,LIBXSLT_TARBALL) \ - $(call fetch_Optional,LPSOLVE,LPSOLVE_TARBALL) \ $(call fetch_Optional,LXML,LXML_TARBALL) \ $(call fetch_Optional,LZMA,LZMA_TARBALL) \ $(call fetch_Optional,MARIADB_CONNECTOR_C,MARIADB_CONNECTOR_C_TARBALL) \ @@ -205,13 +207,6 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S $(call fetch_Optional,MORE_FONTS,FONT_AMIRI_TARBALL) \ $(call fetch_Optional,MORE_FONTS,FONT_REEM_TARBALL) \ $(call fetch_Optional,MORE_FONTS,FONT_SCHEHERAZADE_TARBALL) \ - $(call fetch_Optional,MORE_FONTS,FONT_AGDASIMA_TARBALL) \ - $(call fetch_Optional,MORE_FONTS,FONT_BACASIME_ANTIQUE_TARBALL) \ - $(call fetch_Optional,MORE_FONTS,FONT_BELANOSIMA_TARBALL) \ - $(call fetch_Optional,MORE_FONTS,FONT_CAPRASIMO_TARBALL) \ - $(call fetch_Optional,MORE_FONTS,FONT_LUGRASIMO_TARBALL) \ - $(call fetch_Optional,MORE_FONTS,FONT_LUMANOSIMO_TARBALL) \ - $(call fetch_Optional,MORE_FONTS,FONT_LUNASIMA_TARBALL) \ $(call fetch_Optional,MESON,MESON_TARBALL) \ $(call fetch_Optional,MSPUB,MSPUB_TARBALL) \ $(call fetch_Optional,MWAW,MWAW_TARBALL) \ @@ -228,6 +223,8 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S $(call fetch_Optional,POPPLER,POPPLER_DATA_TARBALL) \ $(call fetch_Optional,POSTGRESQL,POSTGRESQL_TARBALL) \ $(call fetch_Optional,PYTHON,PYTHON_TARBALL) \ + $(if $(filter WNT,$(OS)),PYTHON_BOOTSTRAP_TARBALL) \ + $(call fetch_Optional,QUICKJS,QUICKJS_TARBALL) \ $(call fetch_Optional,QXP,QXP_TARBALL) \ $(call fetch_Optional,REDLAND,RAPTOR_TARBALL) \ $(call fetch_Optional,REDLAND,RASQAL_TARBALL) \ diff --git a/Makefile.in b/Makefile.in index 17671ce8f820..39b00f69a15d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -207,10 +207,10 @@ ifneq ($(CROSS_COMPILING),) ifeq ($(OS),ANDROID) rm -fr $(BUILDDIR)/android/obj rm -fr $(BUILDDIR)/android/jniLibs - rm -fr $(SRCDIR)/android/source/build - rm -fr $(SRCDIR)/android/source/assets - rm -fr $(SRCDIR)/android/source/assets_strippedUI - rm -fr $(SRCDIR)/android/source/res_generated + rm -fr $(SRCDIR)/android/app/build + rm -fr $(SRCDIR)/android/app/assets + rm -fr $(SRCDIR)/android/app/assets_strippedUI + rm -fr $(SRCDIR)/android/app/res_generated endif endif diff --git a/README.cross b/README.cross index e416469fce1b..b5b53fc226cc 100644 --- a/README.cross +++ b/README.cross @@ -165,7 +165,7 @@ And here is an (quite old) autogen.input for Android on X86: --with-distro=LibreOfficeAndroidX86 A LibreOffice app for Android is being developed progress in the -android/source directory. +android/app directory. To run the app, do "make install" followed by either "make run" or starting it from Android itself. You most likely want to have an "adb logcat" diff --git a/README.md b/README.md index cbb4cd688a04..74b093e49644 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ run and compile LibreOffice, also used by the TDF builds: * Build: 13 or later + Xcode 14.3 or later (using latest version available for a given version of macOS) * Linux: * Runtime: RHEL 9 or CentOS 9 and comparable - * Build: either GCC 12; or Clang 18 with libstdc++ 11 + * Build: either GCC 13; or Clang 18 with libstdc++ 11 * iOS (only for LibreOfficeKit): * Runtime: 14.5 (only support for newer i devices == 64 bit) * Build: Xcode 12.5 and iPhone SDK 14.5 diff --git a/Repository.mk b/Repository.mk index 295e24404a4a..f9002d087c2a 100644 --- a/Repository.mk +++ b/Repository.mk @@ -168,7 +168,6 @@ $(eval $(call gb_Helper_register_executables_for_install,OOO,brand, \ $(call gb_Helper_optional,FUZZERS,mmlfuzzer) \ $(call gb_Helper_optional,FUZZERS,mtpfuzzer) \ $(call gb_Helper_optional,FUZZERS,htmlfuzzer) \ - $(call gb_Helper_optional,FUZZERS,sftfuzzer) \ $(call gb_Helper_optional,FUZZERS,eotfuzzer) \ $(call gb_Helper_optional,FUZZERS,dbffuzzer) \ $(call gb_Helper_optional,FUZZERS,webpfuzzer) \ @@ -364,7 +363,6 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \ $(if $(filter WNT,$(OS)),directx9canvas) \ $(if $(ENABLE_OPENGL_CANVAS),oglcanvas) \ $(if $(filter WNT,$(OS)),gdipluscanvas) \ - simplecanvas \ vclcanvas \ )) endif @@ -436,12 +434,14 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \ i18npool \ i18nsearch \ $(if $(ENABLE_JAVA),jdbc) \ + $(if $(ENABLE_QUICKJS),jsuno) \ $(if $(filter WNT,$(OS)),jumplist) \ $(if $(ENABLE_LDAP),ldapbe2) \ $(if $(filter WNT,$(OS)),WinUserInfoBe) \ localebe1 \ log \ lng \ + $(call gb_Helper_optional,SCRIPTING,$(if $(ENABLE_QUICKJS),jsprov)) \ $(if $(filter $(OS),MACOSX),macbe1) \ $(if $(MERGELIBS),merged) \ migrationoo2 \ @@ -470,6 +470,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \ sd \ sdd \ sfx \ + singleprov \ slideshow \ sot \ $(if $(or $(DISABLE_GUI),$(ENABLE_WASM_STRIP_SPLASH)),,spl) \ @@ -846,7 +847,7 @@ $(eval $(call gb_Helper_register_jars,NONE,\ )) endif -# 'test_unittest' is only package delivering to workdir. +# 'test_unittest' is the only package delivering to workdir. # Other packages could be potentially autoinstalled. $(eval $(call gb_Helper_register_packages, \ test_unittest \ @@ -918,6 +919,9 @@ $(eval $(call gb_Helper_register_packages_for_install,sdk,\ odk_javadoc \ odk_uno_loader_classes \ ) \ + $(if $(ENABLE_DOTNET), \ + odk_dotnet \ + ) \ odk_scripts \ )) @@ -1048,7 +1052,7 @@ $(eval $(call gb_Helper_register_packages_for_install,ooo,\ $(eval $(call gb_Helper_register_packages_for_install,ooo_fonts,\ extras_fonts \ - $(if $(USING_X11)$(DISABLE_GUI)$(filter FONTCONFIG,$(BUILD_TYPE))$(filter ANDROID EMSCRIPTEN,$(OS)), \ + $(if $(USE_HEADLESS_CODE)$(USING_X11)$(DISABLE_GUI)$(filter FONTCONFIG,$(BUILD_TYPE))$(filter ANDROID EMSCRIPTEN,$(OS)), \ postprocess_fontconfig) \ $(call gb_Helper_optional,MORE_FONTS,\ fonts_alef \ @@ -1077,13 +1081,6 @@ $(eval $(call gb_Helper_register_packages_for_install,ooo_fonts,\ fonts_noto_serif_lao \ fonts_reem \ fonts_scheherazade \ - $(if $(WITH_DOCREPAIR_FONTS),fonts_agdasima,) \ - $(if $(WITH_DOCREPAIR_FONTS),fonts_bacasime_antique,) \ - $(if $(WITH_DOCREPAIR_FONTS),fonts_belanosima,) \ - $(if $(WITH_DOCREPAIR_FONTS),fonts_caprasimo,) \ - $(if $(WITH_DOCREPAIR_FONTS),fonts_lugrasimo,) \ - $(if $(WITH_DOCREPAIR_FONTS),fonts_lumanosimo,) \ - $(if $(WITH_DOCREPAIR_FONTS),fonts_lunasima,) \ ) \ )) @@ -1211,7 +1208,6 @@ $(eval $(call gb_Helper_register_mos,\ $(call gb_Helper_optional,SCRIPTING,sb) \ sc \ sca \ - scc \ sd \ sdext \ sfx \ diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk index 51f2e711177f..fa7288206da6 100644 --- a/RepositoryExternal.mk +++ b/RepositoryExternal.mk @@ -137,7 +137,7 @@ $(call gb_LinkTarget_set_include,$(1),\ ) $(call gb_LinkTarget_use_libraries,$(1),skia) $(call gb_LinkTarget_add_defs,$(1),\ - -DSK_USER_CONFIG_HEADER="<$(BUILDDIR)/config_host/config_skia.h>" \ + -DSK_USER_CONFIG_HEADER="" \ -DSKIA_DLL \ ) endef @@ -513,6 +513,42 @@ else endef endif +ifneq ($(filter HIGHWAY,$(BUILD_TYPE)),) + +define gb_LinkTarget__use_highway +$(call gb_LinkTarget_set_include,$(1),\ + -I$(gb_UnpackedTarball_workdir)/highway \ + $$(INCLUDE) \ +) +$(call gb_LinkTarget_use_static_libraries,$(1),highway) + +endef + +define gb_ExternalProject__use_highway +$(call gb_ExternalProject_use_static_libraries,$(1),highway) + +endef + +endif # HIGHWAY + +ifneq ($(filter BROTLI,$(BUILD_TYPE)),) + +define gb_LinkTarget__use_brotli +$(call gb_LinkTarget_set_include,$(1),\ + -I$(gb_UnpackedTarball_workdir)/brotli/c \ + -I$(gb_UnpackedTarball_workdir)/brotli/c/include \ + $$(INCLUDE) \ +) +$(call gb_LinkTarget_use_static_libraries,$(1),brotli) + +endef + +define gb_ExternalProject__use_brotli +$(call gb_ExternalProject_use_static_libraries,$(1),brotli) + +endef + +endif # BROTLI ifneq ($(SYSTEM_LIBJPEG),) @@ -548,6 +584,48 @@ endef endif # SYSTEM_LIBJPEG +ifneq ($(SYSTEM_LIBJXL),) + +define gb_LinkTarget__use_libjxl +$(call gb_LinkTarget_set_include,$(1),\ + $$(INCLUDE) \ + $(LIBJXL_CFLAGS) \ +) +$(call gb_LinkTarget_add_libs,$(1),$(LIBJXL_LIBS)) + +endef + +gb_ExternalProject__use_libjxl := + +else # !SYSTEM_LIBJXL + +define gb_LinkTarget__use_libjxl +$(call gb_LinkTarget_add_defs,$(1),\ + -DJXL_INTERNAL_LIBRARY_BUILD \ + -DJXL_THREADS_INTERNAL_LIBRARY_BUILD \ + -Djxl_cms_EXPORTS \ +) + +$(call gb_LinkTarget_set_include,$(1),\ + -I$(gb_UnpackedTarball_workdir)/libjxl/lib/include \ + $$(INCLUDE) \ +) +$(call gb_LinkTarget_use_static_libraries,$(1),libjxl) +$(call gb_LinkTarget_use_externals,$(1),\ + highway \ + brotli \ + lcms2 \ +) + +endef + +define gb_ExternalProject__use_libjxl +$(call gb_ExternalProject_use_static_libraries,$(1),libjxl) + +endef + +endif # SYSTEM_LIBJXL + ifneq ($(SYSTEM_MYTHES),) define gb_LinkTarget__use_mythes @@ -2534,50 +2612,6 @@ endef endif # ANDROID endif # SYSTEM_LCMS2 -ifneq ($(ENABLE_LPSOLVE),) - -ifneq ($(SYSTEM_LPSOLVE),) - -define gb_LinkTarget__use_lpsolve -$(call gb_LinkTarget_add_libs,$(1),-llpsolve55) -$(call gb_LinkTarget_add_defs,$(1),\ - -DSYSTEM_LPSOLVE \ -) - -endef - -else # !SYSTEM_LPSOLVE - -define gb_LinkTarget__use_lpsolve -$(call gb_LinkTarget_use_package,$(1),lpsolve) -ifeq ($(COM),MSC) -$(call gb_LinkTarget_add_libs,$(1),\ - $(gb_UnpackedTarball_workdir)/lpsolve/lpsolve55/lpsolve55.lib \ -) -else -$(call gb_LinkTarget_add_libs,$(1),\ - -L$(gb_UnpackedTarball_workdir)/lpsolve/lpsolve55 -llpsolve55 \ -) -endif -$(call gb_LinkTarget_set_include,$(1),\ - -I$(gb_UnpackedTarball_workdir)/lpsolve \ - $$(INCLUDE) \ -) - -endef - -$(eval $(call gb_Helper_register_packages_for_install,ooo,\ - lpsolve \ -)) - -endif # SYSTEM_LPSOLVE - -else - -gb_LinkTarget__use_lpsolve := - -endif # ENABLE_LPSOLVE - ifneq ($(ENABLE_COINMP),) ifneq ($(SYSTEM_COINMP),TRUE) @@ -3363,6 +3397,28 @@ endef endif # ENABLE_QT6 +# QuickJS +ifeq ($(SYSTEM_QUICKJS),TRUE) +define gb_LinkTarget__use_quickjs +$(call gb_LinkTarget_set_include,$(1),\ + $(QUICKJS_CFLAGS) \ + $$(INCLUDE) \ +) +$(call gb_LinkTarget_add_libs,$(1),$(QUICKJS_LIBS)) +endef +else +define gb_LinkTarget__use_quickjs +$(call gb_LinkTarget_use_external_project,$(1),quickjs,full) +$(call gb_LinkTarget_set_include,$(1),\ + -I$(gb_UnpackedTarball_workdir)/quickjs \ + $$(INCLUDE) \ +) +$(call gb_LinkTarget_use_static_libraries,$(1),\ + quickjs \ +) +endef +endif + # PYTHON # extra python_headers external because pyuno wrapper must not link python ifneq ($(SYSTEM_PYTHON),) @@ -3415,15 +3471,8 @@ $(call gb_LinkTarget_use_package,$(1),python3) endif ifeq ($(OS),WNT) -ifeq ($(CPUNAME),X86_64) -python_arch_subdir=amd64/ -else ifeq ($(CPUNAME),AARCH64) -python_arch_subdir=arm64/ -else -python_arch_subdir=win32/ -endif $(call gb_LinkTarget_add_libs,$(1),\ - $(gb_UnpackedTarball_workdir)/python3/PCbuild/$(python_arch_subdir)python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR)$(if $(MSVC_USE_DEBUG_RUNTIME),_d).lib \ + $(gb_UnpackedTarball_workdir)/python3/PCbuild/$(if $(filter AARCH64,$(CPUNAME)),arm64,$(if $(filter X86_64,$(CPUNAME)),amd64,win32))/python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR)$(if $(MSVC_USE_DEBUG_RUNTIME),_d).lib \ ) else ifeq ($(OS),MACOSX) $(call gb_LinkTarget_add_libs,$(1),\ @@ -4395,8 +4444,8 @@ $(call gb_LinkTarget_use_unpacked,$(1),afdko) $(call gb_LinkTarget_set_include,$(1),\ -I$(gb_UnpackedTarball_workdir)/afdko/c/shared/include \ -I$(gb_UnpackedTarball_workdir)/afdko/c/shared/resource \ - -I$(gb_UnpackedTarball_workdir)/afdko/c/makeotf/include \ - -I$(gb_UnpackedTarball_workdir)/afdko/c/makeotf/source \ + -I$(gb_UnpackedTarball_workdir)/afdko/c/addfeatures/include \ + -I$(gb_UnpackedTarball_workdir)/afdko/c/addfeatures \ $$(INCLUDE) \ ) $(call gb_LinkTarget_use_static_libraries,$(1),afdko) @@ -4492,6 +4541,7 @@ define gb_LinkTarget__use_zxcvbn-c $(call gb_LinkTarget_set_include,$(1),\ -DSYSTEM_ZXCVBN \ $$(INCLUDE) \ + $(ZXCVBN_CFLAGS) \ ) $(call gb_LinkTarget_add_libs,$(1),-lzxcvbn) endef diff --git a/RepositoryModule_host.mk b/RepositoryModule_host.mk index efd7b45d2d67..11d0f98dd307 100644 --- a/RepositoryModule_host.mk +++ b/RepositoryModule_host.mk @@ -53,7 +53,6 @@ $(eval $(call gb_Module_add_moduledirs,libreoffice,\ )) endif - $(eval $(call gb_Module_add_moduledirs,libreoffice,\ android \ $(if $(ENABLE_WASM_STRIP_BASIC_DRAW_MATH_IMPRESS),, \ @@ -104,6 +103,7 @@ $(eval $(call gb_Module_add_moduledirs,libreoffice,\ instsetoo_native \ io \ javaunohelper \ + $(if $(ENABLE_QUICKJS),jsuno) \ jurt \ jvmaccess \ jvmfwk \ @@ -140,7 +140,6 @@ $(eval $(call gb_Module_add_moduledirs,libreoffice,\ $(if $(ENABLE_WASM_STRIP_CALC),, \ sc \ scaddins \ - sccomp \ ) \ $(call gb_Helper_optional,DESKTOP,scp2) \ scripting \ diff --git a/UnoControls/source/inc/OConnectionPointHelper.hxx b/UnoControls/source/inc/OConnectionPointHelper.hxx index 96529b20e795..c0e7681b74f4 100644 --- a/UnoControls/source/inc/OConnectionPointHelper.hxx +++ b/UnoControls/source/inc/OConnectionPointHelper.hxx @@ -96,7 +96,7 @@ private: ::osl::Mutex& m_aSharedMutex; css::uno::WeakReference< css::lang::XConnectionPointContainer > m_oContainerWeakReference; // Reference to container-class!. Don't use Reference<...> - // It is a ring-reference => and must be a wekreference! + // It is a ring-reference => and must be a weak-reference! OConnectionPointContainerHelper* m_pContainerImplementation; css::uno::Type m_aInterfaceType; css::uno::Reference< css::uno::XInterface > m_xLock; diff --git a/android/.gitignore b/android/.gitignore index a06252d55ab3..6705814bddc7 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -2,14 +2,14 @@ /.gradle /.idea /local.properties -/source/assets/ -/source/assets_strippedUI/ -/source/build/ -/source/captures/ -/source/jni/Application.mk -/source/res_generated +/app/assets/ +/app/assets_strippedUI/ +/app/build/ +/app/captures/ +/app/jni/Application.mk +/app/res_generated /jniLibs/ -/source/liboSettings.gradle.kts -/source/native-code.cxx +/app/liboSettings.gradle.kts +/app/native-code.cxx /obj/ -/source/source.iml +/app/source.iml diff --git a/android/CustomTarget_lo_android.mk b/android/CustomTarget_lo_android.mk index 920945b0df7e..89b2d00b0426 100644 --- a/android/CustomTarget_lo_android.mk +++ b/android/CustomTarget_lo_android.mk @@ -8,7 +8,7 @@ $(eval $(call gb_CustomTarget_CustomTarget,android/loandroid3)) -loandroid3_DIR := $(gb_CustomTarget_workdir)/android/source +loandroid3_DIR := $(gb_CustomTarget_workdir)/android/app $(call gb_CustomTarget_get_target,android/loandroid3) : \ $(loandroid3_DIR)/done @@ -17,18 +17,18 @@ $(loandroid3_DIR)/done : $(call gb_Postprocess_get_target,AllModulesButInstsetNa $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),MAK,2) $(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),MAK) cd $(SRCDIR)/android && $(MAKE) local.properties - cd $(SRCDIR)/android/source && $(MAKE) all + cd $(SRCDIR)/android/app && $(MAKE) all ifeq ($(ENABLE_JAVA),TRUE) # Copy to $(BUILDDIR)/instsetoo_native as that is where the tinderbox build script # still looks for the .apk, and we want fresh daily builds to be uploaded. # Us "foo" instead of the old INPATH mkdir -p $(BUILDDIR)/instsetoo_native/foo/bin; \ - if test "$$ENABLE_ANDROID_LOK" != "TRUE" ; then cp $(SRCDIR)/android/source/build/outputs/apk/strippedUI$(if $(ENABLE_ANDROID_EDITING),Editing)/$(if $(ENABLE_RELEASE_BUILD),release/*-release-unsigned.apk,debug/*-debug.apk) $(BUILDDIR)/instsetoo_native/foo/bin ; fi + if test "$$ENABLE_ANDROID_LOK" != "TRUE" ; then cp $(SRCDIR)/android/app/build/outputs/apk/strippedUI$(if $(ENABLE_ANDROID_EDITING),Editing)/$(if $(ENABLE_RELEASE_BUILD),release/*-release-unsigned.apk,debug/*-debug.apk) $(BUILDDIR)/instsetoo_native/foo/bin ; fi $(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),MAK) endif $(call gb_CustomTarget_get_clean_target,android/loandroid3) : $(call gb_Output_announce,$(subst $(WORKDIR)/Clean/,,$@),$(false),MAK,2) - cd $(SRCDIR)/android/source && $(MAKE) clean + cd $(SRCDIR)/android/app && $(MAKE) clean # vim: set noet sw=4 ts=4: diff --git a/android/Makefile b/android/Makefile index fb64e5bfac3b..cb5c3fc30292 100644 --- a/android/Makefile +++ b/android/Makefile @@ -12,7 +12,7 @@ include $(module_directory)/../solenv/gbuild/partial_build.mk .PHONY: sign -SIGNED_APK := $(BUILDDIR)/android/source/bin/LibreOfficeViewer.apk +SIGNED_APK := $(BUILDDIR)/android/app/bin/LibreOfficeViewer.apk RELEASE_APK_USAGE := echo; echo "Usage: make versionCode= key= release-apk" local.properties: $(BUILDDIR)/config_host.mk @@ -26,8 +26,8 @@ release-apk: build rm -f $(SIGNED_APK) # the actual signing - jarsigner --verbose -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ~/.keystore $(BUILDDIR)/android/source/build/outputs/apk/LibreOfficeViewer-strippedUI-release-unsigned.apk $(key) - $(ANDROID_SDK_DIR)/build-tools/*/zipalign -v 4 $(BUILDDIR)/android/source/build/outputs/apk/LibreOfficeViewer-strippedUI-release-unsigned.apk $(SIGNED_APK) + jarsigner --verbose -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ~/.keystore $(BUILDDIR)/android/app/build/outputs/apk/LibreOfficeViewer-strippedUI-release-unsigned.apk $(key) + $(ANDROID_SDK_DIR)/build-tools/*/zipalign -v 4 $(BUILDDIR)/android/app/build/outputs/apk/LibreOfficeViewer-strippedUI-release-unsigned.apk $(SIGNED_APK) @echo @echo "Resulting signed apk: $(SIGNED_APK)" diff --git a/android/README.md b/android/README.md index 12039a89c16e..17331b5ef7a3 100644 --- a/android/README.md +++ b/android/README.md @@ -6,7 +6,7 @@ Contains common code for all projects on Android to bootstrap LibreOffice. In addition it is a home to `LibreOfficeKit` (LOK - see `libreofficekit/README.md`) JNI classes. -## Stuff in Source Directory +## Stuff in App Directory LibreOffice Android application - the code is based on Fennec (Firefox for Android). It uses OpenGL ES 2 for rendering of the document tiles which are gathered from @@ -163,7 +163,7 @@ For instructions on how to build for Android, see `README.cross`. Attach your device, so 'adb devices' shows it. Then run: - cd android/source + cd android/app make install adb logcat @@ -236,7 +236,7 @@ Using `lldb` from within Android Studio is more comfortable though and works lik - open `android` directory in Android Studio via File|Open... - make sure you select the right build variant (`strippedUIDebug` is what you want) - use Run|Edit Configurations to create a new configuration of type "Android Native" - - on tab "General" pick module "source" + - on tab "General" pick module "app" - on tab "Native Debugger" add `android/obj/local/` to the Symbol directories - on the LLDB startup commands tab add @@ -323,7 +323,7 @@ heavy lifting. ## Triple-T metadata for F-Droid -The subdirectory `source/src/main/play` contains data in the Triple-T +The subdirectory `app/src/main/play` contains data in the Triple-T structure that F-Droid evaluates to extract metadata. More information: diff --git a/android/source/AndroidManifest.xml b/android/app/AndroidManifest.xml similarity index 99% rename from android/source/AndroidManifest.xml rename to android/app/AndroidManifest.xml index 69319072ceca..098f7e6abba7 100644 --- a/android/source/AndroidManifest.xml +++ b/android/app/AndroidManifest.xml @@ -1,6 +1,6 @@ + android:installLocation="auto"> diff --git a/android/source/AndroidManifest_quest.xml b/android/app/AndroidManifest_quest.xml similarity index 100% rename from android/source/AndroidManifest_quest.xml rename to android/app/AndroidManifest_quest.xml diff --git a/android/source/Makefile b/android/app/Makefile similarity index 100% rename from android/source/Makefile rename to android/app/Makefile diff --git a/android/source/ReleaseManifest.xml b/android/app/ReleaseManifest.xml similarity index 100% rename from android/source/ReleaseManifest.xml rename to android/app/ReleaseManifest.xml diff --git a/android/source/build.gradle.kts b/android/app/build.gradle.kts similarity index 97% rename from android/source/build.gradle.kts rename to android/app/build.gradle.kts index 98877ce9629b..400861cba927 100644 --- a/android/source/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -46,7 +46,7 @@ base { android { namespace = "org.libreoffice" - compileSdk = 35 + compileSdk = 36 ndkPath = androidNdkPath ndkVersion = androidNdkVersion @@ -84,7 +84,7 @@ android { defaultConfig { // minSdkVersion is set in liboSettings.gradle.kts - targetSdk = 35 + targetSdk = 36 vectorDrawables.useSupportLibrary = true } @@ -92,11 +92,8 @@ android { debug { // make android studio happy... isJniDebuggable = true - // would work just fine with external, but setting emulator up is a little more work - manifestPlaceholders["installLocation"] = "auto" } release { - manifestPlaceholders["installLocation"] = "preferExternal" } } @@ -152,7 +149,7 @@ android/qa/desktop/Makefile (mmeeks's desktop demo, also works to some extent) */ // Assets that are unpacked at run-time into the app's data directory. These -// are files read by non-LO code, fontconfig and freetype for now, that doesn't +// are files read by non-LO code, fontconfig and freetype for now, that don't // understand "/assets" paths. tasks.register("copyUnpackAssets") { description = "copies assets that need to be extracted on the device" diff --git a/android/source/fonts.conf b/android/app/fonts.conf similarity index 100% rename from android/source/fonts.conf rename to android/app/fonts.conf diff --git a/android/source/ic_launcher-web.png b/android/app/ic_launcher-web.png similarity index 100% rename from android/source/ic_launcher-web.png rename to android/app/ic_launcher-web.png diff --git a/android/source/lint-baseline.xml b/android/app/lint-baseline.xml similarity index 100% rename from android/source/lint-baseline.xml rename to android/app/lint-baseline.xml diff --git a/android/source/lint.xml b/android/app/lint.xml similarity index 100% rename from android/source/lint.xml rename to android/app/lint.xml diff --git a/android/source/proguard-project.txt b/android/app/proguard-project.txt similarity index 100% rename from android/source/proguard-project.txt rename to android/app/proguard-project.txt diff --git a/android/source/res/anim/fab_close.xml b/android/app/res/anim/fab_close.xml similarity index 100% rename from android/source/res/anim/fab_close.xml rename to android/app/res/anim/fab_close.xml diff --git a/android/source/res/anim/fab_open.xml b/android/app/res/anim/fab_open.xml similarity index 100% rename from android/source/res/anim/fab_open.xml rename to android/app/res/anim/fab_open.xml diff --git a/android/source/res/drawable-hdpi/handle_alias_end.xml b/android/app/res/drawable-hdpi/handle_alias_end.xml similarity index 100% rename from android/source/res/drawable-hdpi/handle_alias_end.xml rename to android/app/res/drawable-hdpi/handle_alias_end.xml diff --git a/android/source/res/drawable-hdpi/handle_alias_middle.xml b/android/app/res/drawable-hdpi/handle_alias_middle.xml similarity index 100% rename from android/source/res/drawable-hdpi/handle_alias_middle.xml rename to android/app/res/drawable-hdpi/handle_alias_middle.xml diff --git a/android/source/res/drawable-hdpi/handle_alias_start.xml b/android/app/res/drawable-hdpi/handle_alias_start.xml similarity index 100% rename from android/source/res/drawable-hdpi/handle_alias_start.xml rename to android/app/res/drawable-hdpi/handle_alias_start.xml diff --git a/android/source/res/drawable-hdpi/ic_folder_48dp.xml b/android/app/res/drawable-hdpi/ic_folder_48dp.xml similarity index 100% rename from android/source/res/drawable-hdpi/ic_folder_48dp.xml rename to android/app/res/drawable-hdpi/ic_folder_48dp.xml diff --git a/android/source/res/drawable-hdpi/ic_format_bold.xml b/android/app/res/drawable-hdpi/ic_format_bold.xml similarity index 100% rename from android/source/res/drawable-hdpi/ic_format_bold.xml rename to android/app/res/drawable-hdpi/ic_format_bold.xml diff --git a/android/source/res/drawable-hdpi/ic_format_italic.xml b/android/app/res/drawable-hdpi/ic_format_italic.xml similarity index 100% rename from android/source/res/drawable-hdpi/ic_format_italic.xml rename to android/app/res/drawable-hdpi/ic_format_italic.xml diff --git a/android/source/res/drawable-hdpi/ic_format_strikethrough.xml b/android/app/res/drawable-hdpi/ic_format_strikethrough.xml similarity index 100% rename from android/source/res/drawable-hdpi/ic_format_strikethrough.xml rename to android/app/res/drawable-hdpi/ic_format_strikethrough.xml diff --git a/android/source/res/drawable-hdpi/ic_format_underlined.xml b/android/app/res/drawable-hdpi/ic_format_underlined.xml similarity index 100% rename from android/source/res/drawable-hdpi/ic_format_underlined.xml rename to android/app/res/drawable-hdpi/ic_format_underlined.xml diff --git a/android/source/res/drawable-hdpi/ic_keyboard.xml b/android/app/res/drawable-hdpi/ic_keyboard.xml similarity index 100% rename from android/source/res/drawable-hdpi/ic_keyboard.xml rename to android/app/res/drawable-hdpi/ic_keyboard.xml diff --git a/android/source/res/drawable-hdpi/ic_menu.xml b/android/app/res/drawable-hdpi/ic_menu.xml similarity index 100% rename from android/source/res/drawable-hdpi/ic_menu.xml rename to android/app/res/drawable-hdpi/ic_menu.xml diff --git a/android/source/res/drawable-hdpi/ic_text_format.xml b/android/app/res/drawable-hdpi/ic_text_format.xml similarity index 100% rename from android/source/res/drawable-hdpi/ic_text_format.xml rename to android/app/res/drawable-hdpi/ic_text_format.xml diff --git a/android/source/res/drawable-hdpi/light_view_as_grid.png b/android/app/res/drawable-hdpi/light_view_as_grid.png similarity index 100% rename from android/source/res/drawable-hdpi/light_view_as_grid.png rename to android/app/res/drawable-hdpi/light_view_as_grid.png diff --git a/android/source/res/drawable-hdpi/light_view_as_list.png b/android/app/res/drawable-hdpi/light_view_as_list.png similarity index 100% rename from android/source/res/drawable-hdpi/light_view_as_list.png rename to android/app/res/drawable-hdpi/light_view_as_list.png diff --git a/android/source/res/drawable-mdpi/background.png b/android/app/res/drawable-mdpi/background.png similarity index 100% rename from android/source/res/drawable-mdpi/background.png rename to android/app/res/drawable-mdpi/background.png diff --git a/android/source/res/drawable-mdpi/shadow.png b/android/app/res/drawable-mdpi/shadow.png similarity index 100% rename from android/source/res/drawable-mdpi/shadow.png rename to android/app/res/drawable-mdpi/shadow.png diff --git a/android/source/res/drawable-xhdpi/handle_image_end.png b/android/app/res/drawable-xhdpi/handle_image_end.png similarity index 100% rename from android/source/res/drawable-xhdpi/handle_image_end.png rename to android/app/res/drawable-xhdpi/handle_image_end.png diff --git a/android/source/res/drawable-xhdpi/handle_image_middle.png b/android/app/res/drawable-xhdpi/handle_image_middle.png similarity index 100% rename from android/source/res/drawable-xhdpi/handle_image_middle.png rename to android/app/res/drawable-xhdpi/handle_image_middle.png diff --git a/android/source/res/drawable-xhdpi/handle_image_start.png b/android/app/res/drawable-xhdpi/handle_image_start.png similarity index 100% rename from android/source/res/drawable-xhdpi/handle_image_start.png rename to android/app/res/drawable-xhdpi/handle_image_start.png diff --git a/android/source/res/drawable-xxxhdpi/decrementindent.png b/android/app/res/drawable-xxxhdpi/decrementindent.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/decrementindent.png rename to android/app/res/drawable-xxxhdpi/decrementindent.png diff --git a/android/source/res/drawable-xxxhdpi/ic_check_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_check_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_check_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_check_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_align_center_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_align_center_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_align_center_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_align_center_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_align_justify_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_align_justify_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_align_justify_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_align_justify_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_align_left_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_align_left_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_align_left_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_align_left_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_align_right_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_align_right_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_align_right_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_align_right_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_bold_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_bold_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_bold_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_bold_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_italic_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_italic_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_italic_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_italic_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_list_bulleted_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_list_bulleted_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_list_bulleted_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_list_bulleted_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_list_numbered_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_list_numbered_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_list_numbered_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_list_numbered_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_strikethrough_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_strikethrough_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_strikethrough_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_strikethrough_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_format_underlined_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_format_underlined_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_format_underlined_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_format_underlined_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_keyboard_black__24dp.png b/android/app/res/drawable-xxxhdpi/ic_keyboard_black__24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_keyboard_black__24dp.png rename to android/app/res/drawable-xxxhdpi/ic_keyboard_black__24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_menu_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_menu_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_menu_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_menu_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_redo_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_redo_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_redo_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_redo_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_search_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_search_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_search_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_search_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_search_direction_down_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_search_direction_down_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_search_direction_down_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_search_direction_down_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_search_direction_up_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_search_direction_up_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_search_direction_up_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_search_direction_up_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_text_format_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_text_format_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_text_format_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_text_format_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/ic_undo_black_24dp.png b/android/app/res/drawable-xxxhdpi/ic_undo_black_24dp.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/ic_undo_black_24dp.png rename to android/app/res/drawable-xxxhdpi/ic_undo_black_24dp.png diff --git a/android/source/res/drawable-xxxhdpi/image_button_background.xml b/android/app/res/drawable-xxxhdpi/image_button_background.xml similarity index 100% rename from android/source/res/drawable-xxxhdpi/image_button_background.xml rename to android/app/res/drawable-xxxhdpi/image_button_background.xml diff --git a/android/source/res/drawable-xxxhdpi/incrementindent.png b/android/app/res/drawable-xxxhdpi/incrementindent.png similarity index 100% rename from android/source/res/drawable-xxxhdpi/incrementindent.png rename to android/app/res/drawable-xxxhdpi/incrementindent.png diff --git a/android/source/res/drawable/calc.png b/android/app/res/drawable/calc.png similarity index 100% rename from android/source/res/drawable/calc.png rename to android/app/res/drawable/calc.png diff --git a/android/source/res/drawable/draw.png b/android/app/res/drawable/draw.png similarity index 100% rename from android/source/res/drawable/draw.png rename to android/app/res/drawable/draw.png diff --git a/android/source/res/drawable/dummy_page.png b/android/app/res/drawable/dummy_page.png similarity index 100% rename from android/source/res/drawable/dummy_page.png rename to android/app/res/drawable/dummy_page.png diff --git a/android/source/res/drawable/ic_add_24dp.xml b/android/app/res/drawable/ic_add_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_add_24dp.xml rename to android/app/res/drawable/ic_add_24dp.xml diff --git a/android/source/res/drawable/ic_arrow_back_24dp.xml b/android/app/res/drawable/ic_arrow_back_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_arrow_back_24dp.xml rename to android/app/res/drawable/ic_arrow_back_24dp.xml diff --git a/android/source/res/drawable/ic_auto_color.xml b/android/app/res/drawable/ic_auto_color.xml similarity index 100% rename from android/source/res/drawable/ic_auto_color.xml rename to android/app/res/drawable/ic_auto_color.xml diff --git a/android/source/res/drawable/ic_check.xml b/android/app/res/drawable/ic_check.xml similarity index 100% rename from android/source/res/drawable/ic_check.xml rename to android/app/res/drawable/ic_check.xml diff --git a/android/source/res/drawable/ic_content_copy_24dp.xml b/android/app/res/drawable/ic_content_copy_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_content_copy_24dp.xml rename to android/app/res/drawable/ic_content_copy_24dp.xml diff --git a/android/source/res/drawable/ic_content_cut_24dp.xml b/android/app/res/drawable/ic_content_cut_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_content_cut_24dp.xml rename to android/app/res/drawable/ic_content_cut_24dp.xml diff --git a/android/source/res/drawable/ic_content_paste_24dp.xml b/android/app/res/drawable/ic_content_paste_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_content_paste_24dp.xml rename to android/app/res/drawable/ic_content_paste_24dp.xml diff --git a/android/source/res/drawable/ic_decrementindent.xml b/android/app/res/drawable/ic_decrementindent.xml similarity index 100% rename from android/source/res/drawable/ic_decrementindent.xml rename to android/app/res/drawable/ic_decrementindent.xml diff --git a/android/source/res/drawable/ic_done_all_white_12dp.xml b/android/app/res/drawable/ic_done_all_white_12dp.xml similarity index 100% rename from android/source/res/drawable/ic_done_all_white_12dp.xml rename to android/app/res/drawable/ic_done_all_white_12dp.xml diff --git a/android/source/res/drawable/ic_done_white_12dp.xml b/android/app/res/drawable/ic_done_white_12dp.xml similarity index 100% rename from android/source/res/drawable/ic_done_white_12dp.xml rename to android/app/res/drawable/ic_done_white_12dp.xml diff --git a/android/source/res/drawable/ic_filter_list_24dp.xml b/android/app/res/drawable/ic_filter_list_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_filter_list_24dp.xml rename to android/app/res/drawable/ic_filter_list_24dp.xml diff --git a/android/source/res/drawable/ic_folder_24dp.xml b/android/app/res/drawable/ic_folder_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_folder_24dp.xml rename to android/app/res/drawable/ic_folder_24dp.xml diff --git a/android/source/res/drawable/ic_format_align_center.xml b/android/app/res/drawable/ic_format_align_center.xml similarity index 100% rename from android/source/res/drawable/ic_format_align_center.xml rename to android/app/res/drawable/ic_format_align_center.xml diff --git a/android/source/res/drawable/ic_format_align_justify.xml b/android/app/res/drawable/ic_format_align_justify.xml similarity index 100% rename from android/source/res/drawable/ic_format_align_justify.xml rename to android/app/res/drawable/ic_format_align_justify.xml diff --git a/android/source/res/drawable/ic_format_align_left.xml b/android/app/res/drawable/ic_format_align_left.xml similarity index 100% rename from android/source/res/drawable/ic_format_align_left.xml rename to android/app/res/drawable/ic_format_align_left.xml diff --git a/android/source/res/drawable/ic_format_align_right.xml b/android/app/res/drawable/ic_format_align_right.xml similarity index 100% rename from android/source/res/drawable/ic_format_align_right.xml rename to android/app/res/drawable/ic_format_align_right.xml diff --git a/android/source/res/drawable/ic_format_bullets.xml b/android/app/res/drawable/ic_format_bullets.xml similarity index 100% rename from android/source/res/drawable/ic_format_bullets.xml rename to android/app/res/drawable/ic_format_bullets.xml diff --git a/android/source/res/drawable/ic_format_clear_24dp.xml b/android/app/res/drawable/ic_format_clear_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_format_clear_24dp.xml rename to android/app/res/drawable/ic_format_clear_24dp.xml diff --git a/android/source/res/drawable/ic_format_numbering.xml b/android/app/res/drawable/ic_format_numbering.xml similarity index 100% rename from android/source/res/drawable/ic_format_numbering.xml rename to android/app/res/drawable/ic_format_numbering.xml diff --git a/android/source/res/drawable/ic_grid_off_24dp.xml b/android/app/res/drawable/ic_grid_off_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_grid_off_24dp.xml rename to android/app/res/drawable/ic_grid_off_24dp.xml diff --git a/android/source/res/drawable/ic_grid_on_24dp.xml b/android/app/res/drawable/ic_grid_on_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_grid_on_24dp.xml rename to android/app/res/drawable/ic_grid_on_24dp.xml diff --git a/android/source/res/drawable/ic_grow.xml b/android/app/res/drawable/ic_grow.xml similarity index 100% rename from android/source/res/drawable/ic_grow.xml rename to android/app/res/drawable/ic_grow.xml diff --git a/android/source/res/drawable/ic_incrementindent.xml b/android/app/res/drawable/ic_incrementindent.xml similarity index 100% rename from android/source/res/drawable/ic_incrementindent.xml rename to android/app/res/drawable/ic_incrementindent.xml diff --git a/android/source/res/drawable/ic_line.xml b/android/app/res/drawable/ic_line.xml similarity index 100% rename from android/source/res/drawable/ic_line.xml rename to android/app/res/drawable/ic_line.xml diff --git a/android/source/res/drawable/ic_rect.xml b/android/app/res/drawable/ic_rect.xml similarity index 100% rename from android/source/res/drawable/ic_rect.xml rename to android/app/res/drawable/ic_rect.xml diff --git a/android/source/res/drawable/ic_redo.xml b/android/app/res/drawable/ic_redo.xml similarity index 100% rename from android/source/res/drawable/ic_redo.xml rename to android/app/res/drawable/ic_redo.xml diff --git a/android/source/res/drawable/ic_search.xml b/android/app/res/drawable/ic_search.xml similarity index 100% rename from android/source/res/drawable/ic_search.xml rename to android/app/res/drawable/ic_search.xml diff --git a/android/source/res/drawable/ic_search_direction_down.xml b/android/app/res/drawable/ic_search_direction_down.xml similarity index 100% rename from android/source/res/drawable/ic_search_direction_down.xml rename to android/app/res/drawable/ic_search_direction_down.xml diff --git a/android/source/res/drawable/ic_search_direction_up.xml b/android/app/res/drawable/ic_search_direction_up.xml similarity index 100% rename from android/source/res/drawable/ic_search_direction_up.xml rename to android/app/res/drawable/ic_search_direction_up.xml diff --git a/android/source/res/drawable/ic_settings_24dp.xml b/android/app/res/drawable/ic_settings_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_settings_24dp.xml rename to android/app/res/drawable/ic_settings_24dp.xml diff --git a/android/source/res/drawable/ic_shrink.xml b/android/app/res/drawable/ic_shrink.xml similarity index 100% rename from android/source/res/drawable/ic_shrink.xml rename to android/app/res/drawable/ic_shrink.xml diff --git a/android/source/res/drawable/ic_sort_24dp.xml b/android/app/res/drawable/ic_sort_24dp.xml similarity index 100% rename from android/source/res/drawable/ic_sort_24dp.xml rename to android/app/res/drawable/ic_sort_24dp.xml diff --git a/android/source/res/drawable/ic_subscript.xml b/android/app/res/drawable/ic_subscript.xml similarity index 100% rename from android/source/res/drawable/ic_subscript.xml rename to android/app/res/drawable/ic_subscript.xml diff --git a/android/source/res/drawable/ic_superscript.xml b/android/app/res/drawable/ic_superscript.xml similarity index 100% rename from android/source/res/drawable/ic_superscript.xml rename to android/app/res/drawable/ic_superscript.xml diff --git a/android/source/res/drawable/ic_undo.xml b/android/app/res/drawable/ic_undo.xml similarity index 100% rename from android/source/res/drawable/ic_undo.xml rename to android/app/res/drawable/ic_undo.xml diff --git a/android/source/res/drawable/impress.png b/android/app/res/drawable/impress.png similarity index 100% rename from android/source/res/drawable/impress.png rename to android/app/res/drawable/impress.png diff --git a/android/source/res/drawable/label_background.xml b/android/app/res/drawable/label_background.xml similarity index 100% rename from android/source/res/drawable/label_background.xml rename to android/app/res/drawable/label_background.xml diff --git a/android/source/res/drawable/writer.png b/android/app/res/drawable/writer.png similarity index 100% rename from android/source/res/drawable/writer.png rename to android/app/res/drawable/writer.png diff --git a/android/source/res/layout/about.xml b/android/app/res/layout/about.xml similarity index 100% rename from android/source/res/layout/about.xml rename to android/app/res/layout/about.xml diff --git a/android/source/res/layout/activity_document_browser.xml b/android/app/res/layout/activity_document_browser.xml similarity index 99% rename from android/source/res/layout/activity_document_browser.xml rename to android/app/res/layout/activity_document_browser.xml index bb5e62cf7831..d8db5122a321 100644 --- a/android/source/res/layout/activity_document_browser.xml +++ b/android/app/res/layout/activity_document_browser.xml @@ -11,6 +11,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:fitsSystemWindows="true" android:orientation="vertical"> @@ -47,6 +48,7 @@ diff --git a/android/source/res/layout/activity_main.xml b/android/app/res/layout/activity_main.xml similarity index 99% rename from android/source/res/layout/activity_main.xml rename to android/app/res/layout/activity_main.xml index 6734240d515e..6ec40073c836 100644 --- a/android/source/res/layout/activity_main.xml +++ b/android/app/res/layout/activity_main.xml @@ -6,6 +6,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#fff" + android:fitsSystemWindows="true" tools:context=".LibreOfficeMainActivity"> Achustar altaria Achustar amplaria Eliminar + Norma de privacidat + Cancelar + Ficar tabla + Se ye alzando lo documento… + Cancelar + Cancelar diff --git a/android/source/res/values-ast/strings.xml b/android/app/res/values-ast/strings.xml similarity index 100% rename from android/source/res/values-ast/strings.xml rename to android/app/res/values-ast/strings.xml diff --git a/android/source/res/values-be/strings.xml b/android/app/res/values-be/strings.xml similarity index 100% rename from android/source/res/values-be/strings.xml rename to android/app/res/values-be/strings.xml diff --git a/android/source/res/values-brh/strings.xml b/android/app/res/values-brh/strings.xml similarity index 100% rename from android/source/res/values-brh/strings.xml rename to android/app/res/values-brh/strings.xml diff --git a/android/source/res/values-ca/strings.xml b/android/app/res/values-ca/strings.xml similarity index 100% rename from android/source/res/values-ca/strings.xml rename to android/app/res/values-ca/strings.xml diff --git a/android/source/res/values-cs/strings.xml b/android/app/res/values-cs/strings.xml similarity index 100% rename from android/source/res/values-cs/strings.xml rename to android/app/res/values-cs/strings.xml diff --git a/android/source/res/values-cy/strings.xml b/android/app/res/values-cy/strings.xml similarity index 100% rename from android/source/res/values-cy/strings.xml rename to android/app/res/values-cy/strings.xml diff --git a/android/source/res/values-de/strings.xml b/android/app/res/values-de/strings.xml similarity index 100% rename from android/source/res/values-de/strings.xml rename to android/app/res/values-de/strings.xml diff --git a/android/source/res/values-dsb/strings.xml b/android/app/res/values-dsb/strings.xml similarity index 100% rename from android/source/res/values-dsb/strings.xml rename to android/app/res/values-dsb/strings.xml diff --git a/android/source/res/values-el/strings.xml b/android/app/res/values-el/strings.xml similarity index 100% rename from android/source/res/values-el/strings.xml rename to android/app/res/values-el/strings.xml diff --git a/android/source/res/values-eo/strings.xml b/android/app/res/values-eo/strings.xml similarity index 100% rename from android/source/res/values-eo/strings.xml rename to android/app/res/values-eo/strings.xml diff --git a/android/source/res/values-es/strings.xml b/android/app/res/values-es/strings.xml similarity index 100% rename from android/source/res/values-es/strings.xml rename to android/app/res/values-es/strings.xml diff --git a/android/source/res/values-eu/strings.xml b/android/app/res/values-eu/strings.xml similarity index 100% rename from android/source/res/values-eu/strings.xml rename to android/app/res/values-eu/strings.xml diff --git a/android/source/res/values-fa/strings.xml b/android/app/res/values-fa/strings.xml similarity index 100% rename from android/source/res/values-fa/strings.xml rename to android/app/res/values-fa/strings.xml diff --git a/android/source/res/values-fi/strings.xml b/android/app/res/values-fi/strings.xml similarity index 100% rename from android/source/res/values-fi/strings.xml rename to android/app/res/values-fi/strings.xml diff --git a/android/source/res/values-fr/strings.xml b/android/app/res/values-fr/strings.xml similarity index 100% rename from android/source/res/values-fr/strings.xml rename to android/app/res/values-fr/strings.xml diff --git a/android/source/res/values-gl/strings.xml b/android/app/res/values-gl/strings.xml similarity index 100% rename from android/source/res/values-gl/strings.xml rename to android/app/res/values-gl/strings.xml diff --git a/android/source/res/values-hsb/strings.xml b/android/app/res/values-hsb/strings.xml similarity index 100% rename from android/source/res/values-hsb/strings.xml rename to android/app/res/values-hsb/strings.xml diff --git a/android/source/res/values-hu/strings.xml b/android/app/res/values-hu/strings.xml similarity index 100% rename from android/source/res/values-hu/strings.xml rename to android/app/res/values-hu/strings.xml diff --git a/android/source/res/values-hy/strings.xml b/android/app/res/values-hy/strings.xml similarity index 100% rename from android/source/res/values-hy/strings.xml rename to android/app/res/values-hy/strings.xml diff --git a/android/source/res/values-ia/strings.xml b/android/app/res/values-ia/strings.xml similarity index 100% rename from android/source/res/values-ia/strings.xml rename to android/app/res/values-ia/strings.xml diff --git a/android/source/res/values-in/strings.xml b/android/app/res/values-in/strings.xml similarity index 100% rename from android/source/res/values-in/strings.xml rename to android/app/res/values-in/strings.xml diff --git a/android/source/res/values-is/strings.xml b/android/app/res/values-is/strings.xml similarity index 100% rename from android/source/res/values-is/strings.xml rename to android/app/res/values-is/strings.xml diff --git a/android/source/res/values-it/strings.xml b/android/app/res/values-it/strings.xml similarity index 100% rename from android/source/res/values-it/strings.xml rename to android/app/res/values-it/strings.xml diff --git a/android/source/res/values-iw/strings.xml b/android/app/res/values-iw/strings.xml similarity index 100% rename from android/source/res/values-iw/strings.xml rename to android/app/res/values-iw/strings.xml diff --git a/android/source/res/values-ja/strings.xml b/android/app/res/values-ja/strings.xml similarity index 100% rename from android/source/res/values-ja/strings.xml rename to android/app/res/values-ja/strings.xml diff --git a/android/source/res/values-ka/strings.xml b/android/app/res/values-ka/strings.xml similarity index 100% rename from android/source/res/values-ka/strings.xml rename to android/app/res/values-ka/strings.xml diff --git a/android/source/res/values-kk/strings.xml b/android/app/res/values-kk/strings.xml similarity index 100% rename from android/source/res/values-kk/strings.xml rename to android/app/res/values-kk/strings.xml diff --git a/android/app/res/values-kmr/strings.xml b/android/app/res/values-kmr/strings.xml new file mode 100644 index 000000000000..a6b3daec9354 --- /dev/null +++ b/android/app/res/values-kmr/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/android/source/res/values-ne/strings.xml b/android/app/res/values-ne/strings.xml similarity index 100% rename from android/source/res/values-ne/strings.xml rename to android/app/res/values-ne/strings.xml diff --git a/android/source/res/values-night/colors.xml b/android/app/res/values-night/colors.xml similarity index 100% rename from android/source/res/values-night/colors.xml rename to android/app/res/values-night/colors.xml diff --git a/android/source/res/values-nl/strings.xml b/android/app/res/values-nl/strings.xml similarity index 100% rename from android/source/res/values-nl/strings.xml rename to android/app/res/values-nl/strings.xml diff --git a/android/source/res/values-pa/strings.xml b/android/app/res/values-pa/strings.xml similarity index 100% rename from android/source/res/values-pa/strings.xml rename to android/app/res/values-pa/strings.xml diff --git a/android/source/res/values-pl/strings.xml b/android/app/res/values-pl/strings.xml similarity index 100% rename from android/source/res/values-pl/strings.xml rename to android/app/res/values-pl/strings.xml diff --git a/android/source/res/values-pt-rBR/strings.xml b/android/app/res/values-pt-rBR/strings.xml similarity index 100% rename from android/source/res/values-pt-rBR/strings.xml rename to android/app/res/values-pt-rBR/strings.xml diff --git a/android/source/res/values-pt/strings.xml b/android/app/res/values-pt/strings.xml similarity index 100% rename from android/source/res/values-pt/strings.xml rename to android/app/res/values-pt/strings.xml diff --git a/android/app/res/values-ro/strings.xml b/android/app/res/values-ro/strings.xml new file mode 100644 index 000000000000..73383de1df06 --- /dev/null +++ b/android/app/res/values-ro/strings.xml @@ -0,0 +1,119 @@ + + + Setări pentru LibreOffice Viewer + LibreOffice Viewer + Versiunea: %1$s<br>ID-ul subversiunii: <a href=https://hub.libreoffice.org/git-core/%2$s>%2$s</a> + https://www.libreoffice.org + Această versiune a fost furnizată de $VENDOR. + Acest fișier este în modul doar citire. + LibreOffice Viewer este un vizualizator de documente bazat pe LibreOffice. + Afișează licența + Afișează notificarea + Politica de confidențialitate + Crează un fișier nou + Document text nou + Prezentare nouă + Foaie de calcul nouă + Desen nou + fără titlu + Selectează fișierul pentru deschidere + Găsește următorul + Găsește anteriorul + iconiță de fișiere + Fișiere recente + Toate fișierele + General + Mod experimental + Activează modul experimental de editare. Folosește-l pe riscul propriu. + Modul de dezvoltare + Activează modul dezvoltator, unde poți trimite comenzi UNO în cadrul aplicației. Folosește-l pe propriul risc. + Despre + Părți + Setări + Afișează tastatura + Salvează + Salvează ca… + Activează formatul + Caută + Trimite comandă UNO + Salvarea a fost finalizată + Se salvează documentul… + Salvarea documentului a eșuat. + Parolă + Anulează + Refă + Salvezi documentul înainte de a-l închide? + SALVEAZĂ + Anulează + NU + Prezentare de diapozitive (de slide-uri) + Adaugă un diapozitiv (un slide) + Înapoi + Inserează + Șterge + Ascunde + Afișează + Lungime optimă + Ajustează lungimea + Ajustează înălțimea + Ajustează lățimea + Înălțimea optimă + Lățimea optimă + OK + Introdu lungimea suplimentară în sutimi/mm + Sugestie: Dacă atingi de două ori un antet se setează lățimea/înălțimea optimă. + Adaugă o foaie de lucru + OK + Anulează + Te rugăm să introduci parola + Fă o poză + Selectează fotografia + Selectează poza + Nu a fost găsită nicio cameră + Cea mai mică dimensiune + Dimensiune medie + Calitate maximă + Nu comprima + Vrei să comprimi fotografia? + Copiază + Lipește + Taie + Înapoi + Textul a fost copiat în clipboard + Inserează un tabel + Selectează opțiunile de inserare: + Selectează opțiunile de ștergere: + Redenumește foaia de lucru + Șterge foaia de lucru + Șterge diapozitivul (slide-ul) + Numele ales este deja folosit. + Numele părții a fost schimbat. + Partea a fost ștearsă. + Comandă UNO + Tipul + Valoarea + Valoarea părintelui + Exportă în PDF + Tipărește + Caracter + Paragraf + Inserare + Stil + OK + Anulează + Comanda UNO actuală + S-a finalizat exportarea PDF-ului + Nu s-a putut exporta în pdf + Nu s-a putut salva fișierul + Eroare + Introdu numele părții + Fișierul BMP e gol! + Pagină + Foaie + Diapozitiv (Slide) + Parte + Culoare de evidențiere + Culoarea fontului (scrisului) + Redenumește diapozitivul (slide-ul) + Automat + diff --git a/android/source/res/values-sk/strings.xml b/android/app/res/values-sk/strings.xml similarity index 100% rename from android/source/res/values-sk/strings.xml rename to android/app/res/values-sk/strings.xml diff --git a/android/source/res/values-sl/strings.xml b/android/app/res/values-sl/strings.xml similarity index 100% rename from android/source/res/values-sl/strings.xml rename to android/app/res/values-sl/strings.xml diff --git a/android/source/res/values-tl/strings.xml b/android/app/res/values-tl/strings.xml similarity index 100% rename from android/source/res/values-tl/strings.xml rename to android/app/res/values-tl/strings.xml diff --git a/android/source/res/values-tr/strings.xml b/android/app/res/values-tr/strings.xml similarity index 100% rename from android/source/res/values-tr/strings.xml rename to android/app/res/values-tr/strings.xml diff --git a/android/source/res/values-ug/strings.xml b/android/app/res/values-ug/strings.xml similarity index 100% rename from android/source/res/values-ug/strings.xml rename to android/app/res/values-ug/strings.xml diff --git a/android/source/res/values-uk/strings.xml b/android/app/res/values-uk/strings.xml similarity index 100% rename from android/source/res/values-uk/strings.xml rename to android/app/res/values-uk/strings.xml diff --git a/android/source/res/values-zh-rCN/strings.xml b/android/app/res/values-zh-rCN/strings.xml similarity index 100% rename from android/source/res/values-zh-rCN/strings.xml rename to android/app/res/values-zh-rCN/strings.xml diff --git a/android/source/res/values-zh-rTW/strings.xml b/android/app/res/values-zh-rTW/strings.xml similarity index 100% rename from android/source/res/values-zh-rTW/strings.xml rename to android/app/res/values-zh-rTW/strings.xml diff --git a/android/source/res/values/colors.xml b/android/app/res/values/colors.xml similarity index 100% rename from android/source/res/values/colors.xml rename to android/app/res/values/colors.xml diff --git a/android/source/res/values/dimens.xml b/android/app/res/values/dimens.xml similarity index 100% rename from android/source/res/values/dimens.xml rename to android/app/res/values/dimens.xml diff --git a/android/source/res/values/ids.xml b/android/app/res/values/ids.xml similarity index 100% rename from android/source/res/values/ids.xml rename to android/app/res/values/ids.xml diff --git a/android/source/res/values/strings.xml b/android/app/res/values/strings.xml similarity index 100% rename from android/source/res/values/strings.xml rename to android/app/res/values/strings.xml diff --git a/android/source/res/values/themes.xml b/android/app/res/values/themes.xml similarity index 100% rename from android/source/res/values/themes.xml rename to android/app/res/values/themes.xml diff --git a/android/source/res/xml/file_paths.xml b/android/app/res/xml/file_paths.xml similarity index 100% rename from android/source/res/xml/file_paths.xml rename to android/app/res/xml/file_paths.xml diff --git a/android/source/res/xml/libreoffice_preferences.xml b/android/app/res/xml/libreoffice_preferences.xml similarity index 100% rename from android/source/res/xml/libreoffice_preferences.xml rename to android/app/res/xml/libreoffice_preferences.xml diff --git a/android/source/src/java/org/libreoffice/AboutDialogFragment.java b/android/app/src/java/org/libreoffice/AboutDialogFragment.java similarity index 100% rename from android/source/src/java/org/libreoffice/AboutDialogFragment.java rename to android/app/src/java/org/libreoffice/AboutDialogFragment.java diff --git a/android/source/src/java/org/libreoffice/ColorPaletteAdapter.java b/android/app/src/java/org/libreoffice/ColorPaletteAdapter.java similarity index 100% rename from android/source/src/java/org/libreoffice/ColorPaletteAdapter.java rename to android/app/src/java/org/libreoffice/ColorPaletteAdapter.java diff --git a/android/source/src/java/org/libreoffice/ColorPaletteListener.java b/android/app/src/java/org/libreoffice/ColorPaletteListener.java similarity index 100% rename from android/source/src/java/org/libreoffice/ColorPaletteListener.java rename to android/app/src/java/org/libreoffice/ColorPaletteListener.java diff --git a/android/source/src/java/org/libreoffice/ColorPickerAdapter.java b/android/app/src/java/org/libreoffice/ColorPickerAdapter.java similarity index 100% rename from android/source/src/java/org/libreoffice/ColorPickerAdapter.java rename to android/app/src/java/org/libreoffice/ColorPickerAdapter.java diff --git a/android/source/src/java/org/libreoffice/DocumentPartView.java b/android/app/src/java/org/libreoffice/DocumentPartView.java similarity index 100% rename from android/source/src/java/org/libreoffice/DocumentPartView.java rename to android/app/src/java/org/libreoffice/DocumentPartView.java diff --git a/android/source/src/java/org/libreoffice/DocumentPartViewListAdapter.java b/android/app/src/java/org/libreoffice/DocumentPartViewListAdapter.java similarity index 100% rename from android/source/src/java/org/libreoffice/DocumentPartViewListAdapter.java rename to android/app/src/java/org/libreoffice/DocumentPartViewListAdapter.java diff --git a/android/source/src/java/org/libreoffice/FontController.java b/android/app/src/java/org/libreoffice/FontController.java similarity index 100% rename from android/source/src/java/org/libreoffice/FontController.java rename to android/app/src/java/org/libreoffice/FontController.java diff --git a/android/source/src/java/org/libreoffice/FormattingController.java b/android/app/src/java/org/libreoffice/FormattingController.java similarity index 100% rename from android/source/src/java/org/libreoffice/FormattingController.java rename to android/app/src/java/org/libreoffice/FormattingController.java diff --git a/android/source/src/java/org/libreoffice/InvalidationHandler.java b/android/app/src/java/org/libreoffice/InvalidationHandler.java similarity index 100% rename from android/source/src/java/org/libreoffice/InvalidationHandler.java rename to android/app/src/java/org/libreoffice/InvalidationHandler.java diff --git a/android/source/src/java/org/libreoffice/LOEvent.java b/android/app/src/java/org/libreoffice/LOEvent.java similarity index 100% rename from android/source/src/java/org/libreoffice/LOEvent.java rename to android/app/src/java/org/libreoffice/LOEvent.java diff --git a/android/source/src/java/org/libreoffice/LOKitInputConnectionHandler.java b/android/app/src/java/org/libreoffice/LOKitInputConnectionHandler.java similarity index 100% rename from android/source/src/java/org/libreoffice/LOKitInputConnectionHandler.java rename to android/app/src/java/org/libreoffice/LOKitInputConnectionHandler.java diff --git a/android/source/src/java/org/libreoffice/LOKitShell.java b/android/app/src/java/org/libreoffice/LOKitShell.java similarity index 100% rename from android/source/src/java/org/libreoffice/LOKitShell.java rename to android/app/src/java/org/libreoffice/LOKitShell.java diff --git a/android/source/src/java/org/libreoffice/LOKitThread.java b/android/app/src/java/org/libreoffice/LOKitThread.java similarity index 100% rename from android/source/src/java/org/libreoffice/LOKitThread.java rename to android/app/src/java/org/libreoffice/LOKitThread.java diff --git a/android/source/src/java/org/libreoffice/LOKitTileProvider.java b/android/app/src/java/org/libreoffice/LOKitTileProvider.java similarity index 100% rename from android/source/src/java/org/libreoffice/LOKitTileProvider.java rename to android/app/src/java/org/libreoffice/LOKitTileProvider.java diff --git a/android/source/src/java/org/libreoffice/LibreOfficeApplication.java b/android/app/src/java/org/libreoffice/LibreOfficeApplication.java similarity index 100% rename from android/source/src/java/org/libreoffice/LibreOfficeApplication.java rename to android/app/src/java/org/libreoffice/LibreOfficeApplication.java diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/app/src/java/org/libreoffice/LibreOfficeMainActivity.java similarity index 100% rename from android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java rename to android/app/src/java/org/libreoffice/LibreOfficeMainActivity.java diff --git a/android/source/src/java/org/libreoffice/PDFDocumentAdapter.java b/android/app/src/java/org/libreoffice/PDFDocumentAdapter.java similarity index 100% rename from android/source/src/java/org/libreoffice/PDFDocumentAdapter.java rename to android/app/src/java/org/libreoffice/PDFDocumentAdapter.java diff --git a/android/source/src/java/org/libreoffice/PasswordDialogFragment.java b/android/app/src/java/org/libreoffice/PasswordDialogFragment.java similarity index 100% rename from android/source/src/java/org/libreoffice/PasswordDialogFragment.java rename to android/app/src/java/org/libreoffice/PasswordDialogFragment.java diff --git a/android/source/src/java/org/libreoffice/PresentationActivity.java b/android/app/src/java/org/libreoffice/PresentationActivity.java similarity index 86% rename from android/source/src/java/org/libreoffice/PresentationActivity.java rename to android/app/src/java/org/libreoffice/PresentationActivity.java index ede7c0c40101..19264e62232d 100644 --- a/android/source/src/java/org/libreoffice/PresentationActivity.java +++ b/android/app/src/java/org/libreoffice/PresentationActivity.java @@ -4,6 +4,10 @@ import android.content.Intent; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.core.view.GestureDetectorCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.core.graphics.Insets; import androidx.appcompat.app.AppCompatActivity; import android.view.GestureDetector; import android.view.KeyEvent; @@ -22,13 +26,24 @@ public class PresentationActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + WindowCompat.setDecorFitsSystemWindows(getWindow(), true); View decorView = getWindow().getDecorView(); // Hide the status bar. int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN; decorView.setSystemUiVisibility(uiOptions); setContentView(R.layout.presentation_mode); + ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView(), (v, windowInsets) -> { + WindowInsetsCompat compat = WindowInsetsCompat.toWindowInsetsCompat(windowInsets.toWindowInsets(), v); + Insets systemBars = compat.getInsets(WindowInsetsCompat.Type.systemBars()); + Insets displayCutout = compat.getInsets(WindowInsetsCompat.Type.displayCutout()); + int top = Math.max(systemBars.top, displayCutout.top); + int bottom = Math.max(systemBars.bottom, displayCutout.bottom); + int left = Math.max(systemBars.left, displayCutout.left); + int right = Math.max(systemBars.right, displayCutout.right); + v.setPadding(left, top, right, bottom); + return windowInsets; + }); // get intent and url Intent intent = getIntent(); diff --git a/android/source/src/java/org/libreoffice/SearchController.java b/android/app/src/java/org/libreoffice/SearchController.java similarity index 100% rename from android/source/src/java/org/libreoffice/SearchController.java rename to android/app/src/java/org/libreoffice/SearchController.java diff --git a/android/source/src/java/org/libreoffice/SettingsActivity.java b/android/app/src/java/org/libreoffice/SettingsActivity.java similarity index 55% rename from android/source/src/java/org/libreoffice/SettingsActivity.java rename to android/app/src/java/org/libreoffice/SettingsActivity.java index c37cdec3f9b5..cda545dfa956 100644 --- a/android/source/src/java/org/libreoffice/SettingsActivity.java +++ b/android/app/src/java/org/libreoffice/SettingsActivity.java @@ -8,7 +8,14 @@ */ package org.libreoffice; +import android.os.Build; import android.os.Bundle; +import android.view.View; +import android.view.Window; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.core.graphics.Insets; import androidx.fragment.app.FragmentActivity; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceGroup; @@ -17,11 +24,29 @@ public class SettingsActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + WindowCompat.setDecorFitsSystemWindows(getWindow(), true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Window window = getWindow(); + View decorView = window.getDecorView(); + int systemUiVisibility = decorView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + decorView.setSystemUiVisibility(systemUiVisibility); + } // Display the fragment as the main content. getSupportFragmentManager().beginTransaction() .replace(android.R.id.content, new SettingsFragment()) .commit(); + ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView().findViewById(android.R.id.content), (v, windowInsets) -> { + WindowInsetsCompat compat = WindowInsetsCompat.toWindowInsetsCompat(windowInsets.toWindowInsets(), v); + Insets systemBars = compat.getInsets(WindowInsetsCompat.Type.systemBars()); + Insets displayCutout = compat.getInsets(WindowInsetsCompat.Type.displayCutout()); + int top = Math.max(systemBars.top, displayCutout.top); + int bottom = Math.max(systemBars.bottom, displayCutout.bottom); + int left = Math.max(systemBars.left, displayCutout.left); + int right = Math.max(systemBars.right, displayCutout.right); + v.setPadding(left, top, right, bottom); + return windowInsets; + }); } public static class SettingsFragment extends PreferenceFragmentCompat { diff --git a/android/source/src/java/org/libreoffice/ThumbnailCreator.java b/android/app/src/java/org/libreoffice/ThumbnailCreator.java similarity index 100% rename from android/source/src/java/org/libreoffice/ThumbnailCreator.java rename to android/app/src/java/org/libreoffice/ThumbnailCreator.java diff --git a/android/source/src/java/org/libreoffice/TileIdentifier.java b/android/app/src/java/org/libreoffice/TileIdentifier.java similarity index 100% rename from android/source/src/java/org/libreoffice/TileIdentifier.java rename to android/app/src/java/org/libreoffice/TileIdentifier.java diff --git a/android/source/src/java/org/libreoffice/TileProvider.java b/android/app/src/java/org/libreoffice/TileProvider.java similarity index 100% rename from android/source/src/java/org/libreoffice/TileProvider.java rename to android/app/src/java/org/libreoffice/TileProvider.java diff --git a/android/source/src/java/org/libreoffice/TileProviderFactory.java b/android/app/src/java/org/libreoffice/TileProviderFactory.java similarity index 100% rename from android/source/src/java/org/libreoffice/TileProviderFactory.java rename to android/app/src/java/org/libreoffice/TileProviderFactory.java diff --git a/android/source/src/java/org/libreoffice/ToolbarController.java b/android/app/src/java/org/libreoffice/ToolbarController.java similarity index 100% rename from android/source/src/java/org/libreoffice/ToolbarController.java rename to android/app/src/java/org/libreoffice/ToolbarController.java diff --git a/android/source/src/java/org/libreoffice/UNOCommandsController.java b/android/app/src/java/org/libreoffice/UNOCommandsController.java similarity index 100% rename from android/source/src/java/org/libreoffice/UNOCommandsController.java rename to android/app/src/java/org/libreoffice/UNOCommandsController.java diff --git a/android/source/src/java/org/libreoffice/UnitConverter.java b/android/app/src/java/org/libreoffice/UnitConverter.java similarity index 100% rename from android/source/src/java/org/libreoffice/UnitConverter.java rename to android/app/src/java/org/libreoffice/UnitConverter.java diff --git a/android/source/src/java/org/libreoffice/canvas/AdjustLengthLine.java b/android/app/src/java/org/libreoffice/canvas/AdjustLengthLine.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/AdjustLengthLine.java rename to android/app/src/java/org/libreoffice/canvas/AdjustLengthLine.java diff --git a/android/source/src/java/org/libreoffice/canvas/BitmapHandle.java b/android/app/src/java/org/libreoffice/canvas/BitmapHandle.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/BitmapHandle.java rename to android/app/src/java/org/libreoffice/canvas/BitmapHandle.java diff --git a/android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java b/android/app/src/java/org/libreoffice/canvas/CalcHeaderCell.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java rename to android/app/src/java/org/libreoffice/canvas/CalcHeaderCell.java diff --git a/android/source/src/java/org/libreoffice/canvas/CalcSelectionBox.java b/android/app/src/java/org/libreoffice/canvas/CalcSelectionBox.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/CalcSelectionBox.java rename to android/app/src/java/org/libreoffice/canvas/CalcSelectionBox.java diff --git a/android/source/src/java/org/libreoffice/canvas/CanvasElement.java b/android/app/src/java/org/libreoffice/canvas/CanvasElement.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/CanvasElement.java rename to android/app/src/java/org/libreoffice/canvas/CanvasElement.java diff --git a/android/source/src/java/org/libreoffice/canvas/CanvasElementImplRequirement.java b/android/app/src/java/org/libreoffice/canvas/CanvasElementImplRequirement.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/CanvasElementImplRequirement.java rename to android/app/src/java/org/libreoffice/canvas/CanvasElementImplRequirement.java diff --git a/android/source/src/java/org/libreoffice/canvas/CommonCanvasElement.java b/android/app/src/java/org/libreoffice/canvas/CommonCanvasElement.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/CommonCanvasElement.java rename to android/app/src/java/org/libreoffice/canvas/CommonCanvasElement.java diff --git a/android/source/src/java/org/libreoffice/canvas/Cursor.java b/android/app/src/java/org/libreoffice/canvas/Cursor.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/Cursor.java rename to android/app/src/java/org/libreoffice/canvas/Cursor.java diff --git a/android/source/src/java/org/libreoffice/canvas/GraphicSelection.java b/android/app/src/java/org/libreoffice/canvas/GraphicSelection.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/GraphicSelection.java rename to android/app/src/java/org/libreoffice/canvas/GraphicSelection.java diff --git a/android/source/src/java/org/libreoffice/canvas/GraphicSelectionHandle.java b/android/app/src/java/org/libreoffice/canvas/GraphicSelectionHandle.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/GraphicSelectionHandle.java rename to android/app/src/java/org/libreoffice/canvas/GraphicSelectionHandle.java diff --git a/android/source/src/java/org/libreoffice/canvas/ImageUtils.java b/android/app/src/java/org/libreoffice/canvas/ImageUtils.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/ImageUtils.java rename to android/app/src/java/org/libreoffice/canvas/ImageUtils.java diff --git a/android/source/src/java/org/libreoffice/canvas/PageNumberRect.java b/android/app/src/java/org/libreoffice/canvas/PageNumberRect.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/PageNumberRect.java rename to android/app/src/java/org/libreoffice/canvas/PageNumberRect.java diff --git a/android/source/src/java/org/libreoffice/canvas/SelectionHandle.java b/android/app/src/java/org/libreoffice/canvas/SelectionHandle.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/SelectionHandle.java rename to android/app/src/java/org/libreoffice/canvas/SelectionHandle.java diff --git a/android/source/src/java/org/libreoffice/canvas/SelectionHandleEnd.java b/android/app/src/java/org/libreoffice/canvas/SelectionHandleEnd.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/SelectionHandleEnd.java rename to android/app/src/java/org/libreoffice/canvas/SelectionHandleEnd.java diff --git a/android/source/src/java/org/libreoffice/canvas/SelectionHandleMiddle.java b/android/app/src/java/org/libreoffice/canvas/SelectionHandleMiddle.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/SelectionHandleMiddle.java rename to android/app/src/java/org/libreoffice/canvas/SelectionHandleMiddle.java diff --git a/android/source/src/java/org/libreoffice/canvas/SelectionHandleStart.java b/android/app/src/java/org/libreoffice/canvas/SelectionHandleStart.java similarity index 100% rename from android/source/src/java/org/libreoffice/canvas/SelectionHandleStart.java rename to android/app/src/java/org/libreoffice/canvas/SelectionHandleStart.java diff --git a/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java b/android/app/src/java/org/libreoffice/overlay/CalcHeadersController.java similarity index 100% rename from android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java rename to android/app/src/java/org/libreoffice/overlay/CalcHeadersController.java diff --git a/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java b/android/app/src/java/org/libreoffice/overlay/CalcHeadersView.java similarity index 100% rename from android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java rename to android/app/src/java/org/libreoffice/overlay/CalcHeadersView.java diff --git a/android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java b/android/app/src/java/org/libreoffice/overlay/DocumentOverlay.java similarity index 100% rename from android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java rename to android/app/src/java/org/libreoffice/overlay/DocumentOverlay.java diff --git a/android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java b/android/app/src/java/org/libreoffice/overlay/DocumentOverlayView.java similarity index 100% rename from android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java rename to android/app/src/java/org/libreoffice/overlay/DocumentOverlayView.java diff --git a/android/source/src/java/org/libreoffice/ui/FileUtilities.java b/android/app/src/java/org/libreoffice/ui/FileUtilities.java similarity index 100% rename from android/source/src/java/org/libreoffice/ui/FileUtilities.java rename to android/app/src/java/org/libreoffice/ui/FileUtilities.java diff --git a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/app/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java similarity index 86% rename from android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java rename to android/app/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java index 8dfd9b3f63c3..a6fa8fe44af2 100644 --- a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java +++ b/android/app/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java @@ -17,11 +17,15 @@ import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.graphics.drawable.Icon; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import com.google.android.material.floatingactionbutton.FloatingActionButton; import androidx.activity.OnBackPressedCallback; import androidx.core.view.ViewCompat; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.core.graphics.Insets; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.GridLayoutManager; @@ -34,6 +38,8 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; +import android.view.Window; +import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.OvershootInterpolator; @@ -49,6 +55,7 @@ import org.libreoffice.SettingsActivity; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; public class LibreOfficeUIActivity extends AppCompatActivity implements View.OnClickListener{ public enum DocumentType { @@ -128,13 +135,25 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements View.OnC private LinearLayout writerLayout; private LinearLayout impressLayout; private LinearLayout calcLayout; + private Toolbar toolbar; + private View rootView; + private View drawerLayout; + private View nestedScrollView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + WindowCompat.setDecorFitsSystemWindows(getWindow(), true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Window window = getWindow(); + View decorView = window.getDecorView(); + int systemUiVisibility = decorView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + decorView.setSystemUiVisibility(systemUiVisibility); + } // init UI createUI(); + fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open); fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close); @@ -156,8 +175,11 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements View.OnC public void createUI() { setContentView(R.layout.activity_document_browser); - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); + toolbar = findViewById(R.id.toolbar); + rootView = findViewById(android.R.id.content); + drawerLayout = findViewById(R.id.drawer_layout); + nestedScrollView = findViewById(R.id.nestedScrollView); + setSupportActionBar((Toolbar) toolbar); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { @@ -204,6 +226,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements View.OnC recentRecyclerView.setLayoutManager(new GridLayoutManager(this, 2)); recentRecyclerView.setAdapter(new RecentFilesAdapter(this, recentFiles)); + setupWindowInsetsListener(); } private void expandFabMenu() { @@ -219,6 +242,29 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements View.OnC isFabMenuOpen = true; } + private void setupWindowInsetsListener() { + ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, windowInsets) -> { + WindowInsetsCompat compat = WindowInsetsCompat.toWindowInsetsCompat(Objects.requireNonNull(windowInsets.toWindowInsets()), v); + Insets systemBars = compat.getInsets(WindowInsetsCompat.Type.systemBars()); + Insets displayCutout = compat.getInsets(WindowInsetsCompat.Type.displayCutout()); + int top = Math.max(systemBars.top, displayCutout.top); + v.setPadding(v.getPaddingLeft(), top, v.getPaddingRight(), v.getPaddingBottom()); + return windowInsets; + }); + + ViewCompat.setOnApplyWindowInsetsListener(nestedScrollView, (v, windowInsets) -> { + WindowInsetsCompat compat = WindowInsetsCompat.toWindowInsetsCompat(Objects.requireNonNull(windowInsets.toWindowInsets()), v); + Insets systemBars = compat.getInsets(WindowInsetsCompat.Type.systemBars()); + Insets displayCutout = compat.getInsets(WindowInsetsCompat.Type.displayCutout()); + int top = Math.max(systemBars.top, displayCutout.top); + int bottom = Math.max(systemBars.bottom, displayCutout.bottom); + int left = Math.max(systemBars.left, displayCutout.left); + int right = Math.max(systemBars.right, displayCutout.right); + v.setPadding(left, top, right, bottom); + return windowInsets; + }); + } + private void collapseFabMenu() { ViewCompat.animate(editFAB).rotation(0.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start(); writerLayout.startAnimation(fabCloseAnimation); @@ -320,7 +366,10 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements View.OnC protected void onResume() { super.onResume(); Log.d(LOGTAG, "onResume"); + WindowCompat.setDecorFitsSystemWindows(getWindow(), true); createUI(); + ViewCompat.requestApplyInsets(toolbar); + ViewCompat.requestApplyInsets(nestedScrollView); } private void addDocumentToRecents(Uri fileUri) { diff --git a/android/source/src/java/org/libreoffice/ui/PageView.java b/android/app/src/java/org/libreoffice/ui/PageView.java similarity index 100% rename from android/source/src/java/org/libreoffice/ui/PageView.java rename to android/app/src/java/org/libreoffice/ui/PageView.java diff --git a/android/source/src/java/org/libreoffice/ui/RecentFile.java b/android/app/src/java/org/libreoffice/ui/RecentFile.java similarity index 100% rename from android/source/src/java/org/libreoffice/ui/RecentFile.java rename to android/app/src/java/org/libreoffice/ui/RecentFile.java diff --git a/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java b/android/app/src/java/org/libreoffice/ui/RecentFilesAdapter.java similarity index 100% rename from android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java rename to android/app/src/java/org/libreoffice/ui/RecentFilesAdapter.java diff --git a/android/source/src/java/org/mozilla/gecko/OnInterceptTouchListener.java b/android/app/src/java/org/mozilla/gecko/OnInterceptTouchListener.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/OnInterceptTouchListener.java rename to android/app/src/java/org/mozilla/gecko/OnInterceptTouchListener.java diff --git a/android/source/src/java/org/mozilla/gecko/OnSlideSwipeListener.java b/android/app/src/java/org/mozilla/gecko/OnSlideSwipeListener.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/OnSlideSwipeListener.java rename to android/app/src/java/org/mozilla/gecko/OnSlideSwipeListener.java diff --git a/android/source/src/java/org/mozilla/gecko/ZoomConstraints.java b/android/app/src/java/org/mozilla/gecko/ZoomConstraints.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/ZoomConstraints.java rename to android/app/src/java/org/mozilla/gecko/ZoomConstraints.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/Axis.java b/android/app/src/java/org/mozilla/gecko/gfx/Axis.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/Axis.java rename to android/app/src/java/org/mozilla/gecko/gfx/Axis.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/BufferedCairoImage.java b/android/app/src/java/org/mozilla/gecko/gfx/BufferedCairoImage.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/BufferedCairoImage.java rename to android/app/src/java/org/mozilla/gecko/gfx/BufferedCairoImage.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/CairoGLInfo.java b/android/app/src/java/org/mozilla/gecko/gfx/CairoGLInfo.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/CairoGLInfo.java rename to android/app/src/java/org/mozilla/gecko/gfx/CairoGLInfo.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/CairoImage.java b/android/app/src/java/org/mozilla/gecko/gfx/CairoImage.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/CairoImage.java rename to android/app/src/java/org/mozilla/gecko/gfx/CairoImage.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/CairoUtils.java b/android/app/src/java/org/mozilla/gecko/gfx/CairoUtils.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/CairoUtils.java rename to android/app/src/java/org/mozilla/gecko/gfx/CairoUtils.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java b/android/app/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java rename to android/app/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java b/android/app/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java rename to android/app/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/DisplayPortMetrics.java b/android/app/src/java/org/mozilla/gecko/gfx/DisplayPortMetrics.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/DisplayPortMetrics.java rename to android/app/src/java/org/mozilla/gecko/gfx/DisplayPortMetrics.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java b/android/app/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java rename to android/app/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/FixedZoomTileLayer.java b/android/app/src/java/org/mozilla/gecko/gfx/FixedZoomTileLayer.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/FixedZoomTileLayer.java rename to android/app/src/java/org/mozilla/gecko/gfx/FixedZoomTileLayer.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/FloatSize.java b/android/app/src/java/org/mozilla/gecko/gfx/FloatSize.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/FloatSize.java rename to android/app/src/java/org/mozilla/gecko/gfx/FloatSize.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/GLController.java b/android/app/src/java/org/mozilla/gecko/gfx/GLController.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/GLController.java rename to android/app/src/java/org/mozilla/gecko/gfx/GLController.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/app/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java rename to android/app/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/ImmutableViewportMetrics.java b/android/app/src/java/org/mozilla/gecko/gfx/ImmutableViewportMetrics.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/ImmutableViewportMetrics.java rename to android/app/src/java/org/mozilla/gecko/gfx/ImmutableViewportMetrics.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/InputConnectionHandler.java b/android/app/src/java/org/mozilla/gecko/gfx/InputConnectionHandler.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/InputConnectionHandler.java rename to android/app/src/java/org/mozilla/gecko/gfx/InputConnectionHandler.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/IntSize.java b/android/app/src/java/org/mozilla/gecko/gfx/IntSize.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/IntSize.java rename to android/app/src/java/org/mozilla/gecko/gfx/IntSize.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java b/android/app/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java rename to android/app/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/Layer.java b/android/app/src/java/org/mozilla/gecko/gfx/Layer.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/Layer.java rename to android/app/src/java/org/mozilla/gecko/gfx/Layer.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/LayerRenderer.java b/android/app/src/java/org/mozilla/gecko/gfx/LayerRenderer.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/LayerRenderer.java rename to android/app/src/java/org/mozilla/gecko/gfx/LayerRenderer.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/LayerView.java b/android/app/src/java/org/mozilla/gecko/gfx/LayerView.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/LayerView.java rename to android/app/src/java/org/mozilla/gecko/gfx/LayerView.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/NinePatchTileLayer.java b/android/app/src/java/org/mozilla/gecko/gfx/NinePatchTileLayer.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/NinePatchTileLayer.java rename to android/app/src/java/org/mozilla/gecko/gfx/NinePatchTileLayer.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/PanZoomTarget.java b/android/app/src/java/org/mozilla/gecko/gfx/PanZoomTarget.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/PanZoomTarget.java rename to android/app/src/java/org/mozilla/gecko/gfx/PanZoomTarget.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/PointUtils.java b/android/app/src/java/org/mozilla/gecko/gfx/PointUtils.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/PointUtils.java rename to android/app/src/java/org/mozilla/gecko/gfx/PointUtils.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/RectUtils.java b/android/app/src/java/org/mozilla/gecko/gfx/RectUtils.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/RectUtils.java rename to android/app/src/java/org/mozilla/gecko/gfx/RectUtils.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java b/android/app/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java rename to android/app/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java b/android/app/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java rename to android/app/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java b/android/app/src/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java rename to android/app/src/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java b/android/app/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java rename to android/app/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/SubTile.java b/android/app/src/java/org/mozilla/gecko/gfx/SubTile.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/SubTile.java rename to android/app/src/java/org/mozilla/gecko/gfx/SubTile.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/TextureGenerator.java b/android/app/src/java/org/mozilla/gecko/gfx/TextureGenerator.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/TextureGenerator.java rename to android/app/src/java/org/mozilla/gecko/gfx/TextureGenerator.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/TextureReaper.java b/android/app/src/java/org/mozilla/gecko/gfx/TextureReaper.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/TextureReaper.java rename to android/app/src/java/org/mozilla/gecko/gfx/TextureReaper.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/TileLayer.java b/android/app/src/java/org/mozilla/gecko/gfx/TileLayer.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/TileLayer.java rename to android/app/src/java/org/mozilla/gecko/gfx/TileLayer.java diff --git a/android/source/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java b/android/app/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java rename to android/app/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java diff --git a/android/source/src/java/org/mozilla/gecko/util/FloatUtils.java b/android/app/src/java/org/mozilla/gecko/util/FloatUtils.java similarity index 100% rename from android/source/src/java/org/mozilla/gecko/util/FloatUtils.java rename to android/app/src/java/org/mozilla/gecko/util/FloatUtils.java diff --git a/android/source/src/main/play/listings/en-US/graphics/icon/icon.png b/android/app/src/main/play/listings/en-US/graphics/icon/icon.png similarity index 100% rename from android/source/src/main/play/listings/en-US/graphics/icon/icon.png rename to android/app/src/main/play/listings/en-US/graphics/icon/icon.png diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index c0afc269c4cb..4829d80d5481 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] constraintlayout_version = "2.2.1" -gradle_version = "9.1.0" +gradle_version = "9.3.1" material_version = "1.13.0" preference_version = "1.2.1" diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 63aceb22d9e1..22e55d385d22 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=17f277867f6914d61b1aa02efab1ba7bb439ad652ca485cd8ca6842fccec6e43 -distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip +distributionSha256Sum=a3c4ba4aca8f0075688b9c5b18939fd28e8cb4357c227da5c1d9f38343791439 +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-all.zip validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index 0e746d3ac596..99901b64d71b 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -26,4 +26,4 @@ dependencyResolutionManagement { } } -include(":source") +include(":app") diff --git a/android/source/res/values-ro/strings.xml b/android/source/res/values-ro/strings.xml deleted file mode 100644 index b78bd635eccf..000000000000 --- a/android/source/res/values-ro/strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - Setări pentru LibreOffice Viewer - LibreOffice Viewer - Versiunea: %1$s<br>ID-ul subversiunii: <a href=https://hub.libreoffice.org/git-core/%2$s>%2$s</a> - https://www.libreoffice.org - Această versiune a fost furnizată de $VENDOR. - Acest fișier este în modul doar citire. - LibreOffice Viewer este un vizualizator de documente bazat pe LibreOffice. - Afișează licența - Afișează notificarea - Politica de confidențialitate - diff --git a/android/source/res/values-v35/themes.xml b/android/source/res/values-v35/themes.xml deleted file mode 100644 index 6b92655a2a93..000000000000 --- a/android/source/res/values-v35/themes.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/apple_remote/source/AppleRemote.h b/apple_remote/source/AppleRemote.h index a4d6337a641b..4f0e7545f29d 100644 --- a/apple_remote/source/AppleRemote.h +++ b/apple_remote/source/AppleRemote.h @@ -1,6 +1,6 @@ /* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /***************************************************************************** - * RemoteControlWrapper.h + * AppleRemote.h * RemoteControlWrapper * * Created by Martin Kahr on 11.03.06 under a MIT-style license. diff --git a/apple_remote/source/MultiClickRemoteBehavior.h b/apple_remote/source/MultiClickRemoteBehavior.h index a6d671d5285d..89a06df0680a 100644 --- a/apple_remote/source/MultiClickRemoteBehavior.h +++ b/apple_remote/source/MultiClickRemoteBehavior.h @@ -33,7 +33,7 @@ /** A behavior that adds multiclick and hold events on top of a device. - Events are generated and send to a delegate + Events are generated and sent to a delegate */ @interface MultiClickRemoteBehavior : NSObject { @@ -69,7 +69,7 @@ // click counting does delay each event as it has to wait if there is another event (second click) // therefore there is a slight time difference (maximumClickCountTimeDifference) between a single click // of the user and the call of your delegate method -// click counting can be enabled individually for specific buttons. Use the property clickCountEnableButtons to +// click counting can be enabled individually for specific buttons. Use the property clickCountEnabledButtons to // set the buttons for which click counting shall be enabled - (BOOL)clickCountingEnabled; - (void)setClickCountingEnabled:(BOOL)value; diff --git a/avmedia/inc/mediacontrol.hxx b/avmedia/inc/mediacontrol.hxx index c249fbccf680..f4501c7740a3 100644 --- a/avmedia/inc/mediacontrol.hxx +++ b/avmedia/inc/mediacontrol.hxx @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include constexpr sal_Int32 AVMEDIA_CONTROLOFFSET = 6; diff --git a/avmedia/source/framework/mediacontrol.cxx b/avmedia/source/framework/mediacontrol.cxx index f7e65ee5e209..6945462d611c 100644 --- a/avmedia/source/framework/mediacontrol.cxx +++ b/avmedia/source/framework/mediacontrol.cxx @@ -22,7 +22,6 @@ #include #include #include -#include #include #include diff --git a/avmedia/source/framework/mediaplayer.cxx b/avmedia/source/framework/mediaplayer.cxx index b4acad37c741..84d0dc7a2f5a 100644 --- a/avmedia/source/framework/mediaplayer.cxx +++ b/avmedia/source/framework/mediaplayer.cxx @@ -33,11 +33,12 @@ namespace avmedia { -MediaPlayer::MediaPlayer( vcl::Window* _pParent, sal_uInt16 nId, SfxBindings* _pBindings, SfxChildWinInfo* pInfo ) : - SfxChildWindow( _pParent, nId ) +MediaPlayer::MediaPlayer(vcl::Window* _pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo) + : SfxChildWindow(_pParent, nId) { - SetWindow( VclPtr::Create( _pBindings, this, _pParent ) ); - static_cast< MediaFloater* >( GetWindow() )->Initialize( pInfo ); + SetWindow(VclPtr::Create(rBindings, this, _pParent)); + static_cast(GetWindow())->Initialize(rInfo); }; @@ -48,10 +49,10 @@ MediaPlayer::~MediaPlayer() SFX_IMPL_DOCKINGWINDOW_WITHID( MediaPlayer, SID_AVMEDIA_PLAYER ) - -MediaFloater::MediaFloater( SfxBindings* _pBindings, SfxChildWindow* pCW, vcl::Window* pParent ) : - SfxDockingWindow( _pBindings, pCW, pParent, WB_CLOSEABLE | WB_MOVEABLE | WB_SIZEABLE | WB_DOCKABLE ), - mpMediaWindow( new MediaWindow( this, true ) ) +MediaFloater::MediaFloater(SfxBindings& rBindings, SfxChildWindow* pCW, vcl::Window* pParent) + : SfxDockingWindow(rBindings, pCW, pParent, + WB_CLOSEABLE | WB_MOVEABLE | WB_SIZEABLE | WB_DOCKABLE) + , mpMediaWindow(new MediaWindow(this, true)) { const Size aSize( mpMediaWindow->getPreferredSize() ); diff --git a/avmedia/source/framework/mediatoolbox.cxx b/avmedia/source/framework/mediatoolbox.cxx index 490ba08ac65a..e3959b8f48c8 100644 --- a/avmedia/source/framework/mediatoolbox.cxx +++ b/avmedia/source/framework/mediatoolbox.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include diff --git a/avmedia/source/gstreamer/gstplayer.cxx b/avmedia/source/gstreamer/gstplayer.cxx index 48622c5b8c02..de56a4084ba4 100644 --- a/avmedia/source/gstreamer/gstplayer.cxx +++ b/avmedia/source/gstreamer/gstplayer.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -329,6 +330,38 @@ Player::Player() : mbInitialized = gst_init_check( &argc, &argv, &pError ); + if (mbInitialized) + { + // Drop the "Adaptive" ones to rank none as a crude but simple way to + // drop the cases that take a manifest to further resources that it + // names. Otherwise an option is to follow more closely what browsers + // probably do here and register a handler for fetching data. + GstRegistry* pRegistry = gst_registry_get(); + GList* pFactories = gst_registry_get_feature_list(pRegistry, GST_TYPE_ELEMENT_FACTORY); + for (GList* pItem = pFactories; pItem; pItem = pItem->next) + { + GstElementFactory* pFactory = GST_ELEMENT_FACTORY(pItem->data); + const gchar* pKlass = gst_element_factory_get_metadata(pFactory, GST_ELEMENT_METADATA_KLASS); + if (!pKlass) + continue; + + OString aKlass(pKlass); + bool bAdaptive = false; + for (sal_Int32 nIndex = 0; nIndex >= 0;) + { + if (o3tl::getToken(aKlass, 0, '/', nIndex) == "Adaptive") + { + bAdaptive = true; + break; + } + } + + if (bAdaptive) + gst_plugin_feature_set_rank(GST_PLUGIN_FEATURE(pFactory), GST_RANK_NONE); + } + gst_plugin_feature_list_free(pFactories); + } + SAL_INFO( "avmedia.gstreamer", AVVERSION << this << " Player::Player" ); if (pError != nullptr) diff --git a/avmedia/source/qt6/QtPlayer.cxx b/avmedia/source/qt6/QtPlayer.cxx index 177edabdd971..6c8e752aeb99 100644 --- a/avmedia/source/qt6/QtPlayer.cxx +++ b/avmedia/source/qt6/QtPlayer.cxx @@ -41,6 +41,66 @@ using namespace ::com::sun::star; namespace avmedia::qt { +namespace playerhelper +{ +VideoResolutionHelperTaskWorker::VideoResolutionHelperTaskWorker(const QUrl& url, + std::atomic_bool& re) + : QObject(nullptr) + , m_url(url) + , m_readyRef(re) +{ +} + +QSize VideoResolutionHelperTaskWorker::getVideoResolution() +{ + auto res = m_preloaderMediaPlayer->metaData().value(QMediaMetaData::Resolution); + if (res.canConvert()) + { + return res.value(); + } + return { 0, 0 }; +} + +void VideoResolutionHelperTaskWorker::start() +{ + m_preloaderMediaPlayer = std::make_unique(); + connect(m_preloaderMediaPlayer.get(), &QMediaPlayer::mediaStatusChanged, this, + [this](const QMediaPlayer::MediaStatus& status) { + if (status != QMediaPlayer::MediaStatus::LoadingMedia) + { + m_readyRef = true; + m_readyRef.notify_one(); + } + }); + m_preloaderMediaPlayer->setSource(m_url); +} + +VideoResolutionHelper::VideoResolutionHelper(const QUrl& url) + : QObject(nullptr) +{ + m_worker = new VideoResolutionHelperTaskWorker(url, m_ready); + m_worker->moveToThread(&m_resolutionHelperThread); + + QObject::connect(&m_resolutionHelperThread, &QThread::started, m_worker, + &VideoResolutionHelperTaskWorker::start); + QObject::connect(&m_resolutionHelperThread, &QThread::finished, m_worker, + &QObject::deleteLater); +} + +QSize VideoResolutionHelper::loadResolution() +{ + m_resolutionHelperThread.start(); + m_ready.wait(false); + return m_worker->getVideoResolution(); +} + +VideoResolutionHelper::~VideoResolutionHelper() +{ + m_resolutionHelperThread.quit(); + m_resolutionHelperThread.wait(); +} +} + QtPlayer::QtPlayer() : QtPlayer_BASE(m_aMutex) , m_pMediaWidgetParent(nullptr) @@ -181,27 +241,23 @@ awt::Size SAL_CALL QtPlayer::getPreferredPlayerWindowSize() assert(m_xMediaPlayer); - // if media hasn't been loaded yet, ensure this happens, since - // retrieving resolution doesn't work reliably otherwise + QSize aResolution{ 0, 0 }; + if (m_xMediaPlayer->mediaStatus() == QMediaPlayer::LoadingMedia) + { //still loading, using helper + playerhelper::VideoResolutionHelper ph(m_xMediaPlayer->source()); + aResolution = ph.loadResolution(); + } + else { - m_xMediaPlayer->play(); - - while (m_xMediaPlayer->mediaStatus() == QMediaPlayer::LoadingMedia) - QCoreApplication::processEvents(); - - m_xMediaPlayer->stop(); + QVariant res = m_xMediaPlayer->metaData().value(QMediaMetaData::Resolution); + if (res.canConvert()) + { + aResolution = res.value(); + } } - const QMediaMetaData aMetaData = m_xMediaPlayer->metaData(); - const QVariant aResolutionVariant = aMetaData.value(QMediaMetaData::Resolution); - if (aResolutionVariant.canConvert()) - { - const QSize aResolution = aResolutionVariant.value(); - return awt::Size(aResolution.width(), aResolution.height()); - } - - return awt::Size(0, 0); + return awt::Size(aResolution.width(), aResolution.height()); } uno::Reference<::media::XPlayerWindow> diff --git a/avmedia/source/qt6/QtPlayer.hxx b/avmedia/source/qt6/QtPlayer.hxx index 02f9cf015bf2..86a7e593eaa6 100644 --- a/avmedia/source/qt6/QtPlayer.hxx +++ b/avmedia/source/qt6/QtPlayer.hxx @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -26,6 +27,35 @@ namespace avmedia::qt { typedef cppu::WeakComponentImplHelper QtPlayer_BASE; +namespace playerhelper +{ +class VideoResolutionHelperTaskWorker : public QObject +{ +public: + explicit VideoResolutionHelperTaskWorker(const QUrl& url, std::atomic_bool& re); + QSize getVideoResolution(); + void start(); + +private: + std::unique_ptr m_preloaderMediaPlayer; + QUrl m_url; + std::atomic_bool& m_readyRef; +}; + +class VideoResolutionHelper : public QObject +{ +public: + explicit VideoResolutionHelper(const QUrl& url); + QSize loadResolution(); + ~VideoResolutionHelper(); + +private: + VideoResolutionHelperTaskWorker* m_worker; + QThread m_resolutionHelperThread; + std::atomic_bool m_ready{ false }; +}; +} + class QtPlayer final : public QObject, public cppu::BaseMutex, public QtPlayer_BASE { Q_OBJECT diff --git a/avmedia/source/viewer/mediawindow.cxx b/avmedia/source/viewer/mediawindow.cxx index e8caedb34217..5f853697428d 100644 --- a/avmedia/source/viewer/mediawindow.cxx +++ b/avmedia/source/viewer/mediawindow.cxx @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/basctl/inc/pch/precompiled_basctl.hxx b/basctl/inc/pch/precompiled_basctl.hxx index 47883a945c83..eaf01c1d8e4c 100644 --- a/basctl/inc/pch/precompiled_basctl.hxx +++ b/basctl/inc/pch/precompiled_basctl.hxx @@ -169,7 +169,6 @@ #include #include #include -#include #include #include #include @@ -393,7 +392,6 @@ #include #include #include -#include #include #include #include diff --git a/basctl/inc/strings.hrc b/basctl/inc/strings.hrc index f4ff665ac009..08c3da3a935c 100644 --- a/basctl/inc/strings.hrc +++ b/basctl/inc/strings.hrc @@ -21,6 +21,7 @@ #define BASCTL_INC_BASIDESH_HRC #define NC_(Context, String) TranslateId(Context, u8##String) +#define NNC_(Context, StringSingular, StringPlural) TranslateNId(Context, reinterpret_cast(u8##StringSingular), reinterpret_cast(u8##StringPlural)) #define RID_STR_FILTER_ALLFILES NC_("RID_STR_FILTER_ALLFILES", "") #define RID_STR_NOMODULE NC_("RID_STR_NOMODULE", "< No Module >") @@ -37,7 +38,6 @@ #define RID_STR_SBXNAMEALLREADYUSED NC_("RID_STR_SBXNAMEALLREADYUSED", "Name already exists") #define RID_STR_SIGNED NC_("RID_STR_SIGNED", "(Signed)") #define RID_STR_SBXNAMEALLREADYUSED2 NC_("RID_STR_SBXNAMEALLREADYUSED2", "Object with same name already exists") -#define RID_STR_CANNOTRUNMACRO NC_("RID_STR_CANNOTRUNMACRO", "For security reasons, you cannot run this macro.\n\nFor more information, check the security settings.") #define RID_STR_SEARCHNOTFOUND NC_("RID_STR_SEARCHNOTFOUND", "Search key not found") #define RID_STR_SEARCHFROMSTART NC_("RID_STR_SEARCHFROMSTART", "Search to last module complete. Continue at first module?") #define RID_STR_SEARCHREPLACES NC_("RID_STR_SEARCHREPLACES", "Search key replaced XX times") @@ -119,12 +119,8 @@ #define RID_STR_OB_BACK_BUTTON NC_("RID_STR_OB_BACK_BUTTON", "Back") #define RID_STR_OB_FORWARD_BUTTON NC_("RID_STR_OB_FORWARD_BUTTON", "Forward") // For Details Pane Formatting and Symbol Types -#define RID_STR_OB_AS NC_("RID_STR_OB_AS", " As ") -#define RID_STR_OB_OPTIONAL NC_("RID_STR_OB_OPTIONAL", "Optional") -#define RID_STR_OB_BYREF NC_("RID_STR_OB_BYREF", "ByRef") -#define RID_STR_OB_OUT_PARAM NC_("RID_STR_OB_OUT_PARAM", "[out]") -#define RID_STR_OB_INOUT_PARAM NC_("RID_STR_OB_INOUT_PARAM", "[inout]") #define RID_STR_OB_ACCESS NC_("RID_STR_OB_ACCESS", "Access: ") +// This a verb as if it was short for “This function returns: ” #define RID_STR_OB_RETURNS NC_("RID_STR_OB_RETURNS", "Returns: ") #define RID_STR_OB_TYPE NC_("RID_STR_OB_TYPE", "Type: ") #define RID_STR_OB_PARAMETERS NC_("RID_STR_OB_PARAMETERS", "\nParameters:\n") @@ -136,14 +132,15 @@ #define RID_STR_OB_FULLNAME_HEADER NC_("RID_STR_OB_FULLNAME_HEADER", "\nFull Name\n") #define RID_STR_OB_CONTENTS_HEADER NC_("RID_STR_OB_CONTENTS_HEADER", "Contents\n") #define RID_STR_OB_TOTAL_MEMBERS NC_("RID_STR_OB_TOTAL_MEMBERS", "Total members: ") -#define RID_STR_OB_CONTAINS_ITEMS NC_("RID_STR_OB_CONTAINS_ITEMS", "Contains %1 items") +#define RID_STR_OB_CONTAINS_ITEMS NNC_("RID_STR_OB_CONTAINS_ITEMS", "Contains 1 item", "Contains %1 items") // For Access Modifiers #define RID_STR_OB_ACCESS_PUBLIC NC_("RID_STR_OB_ACCESS_PUBLIC", "Public") #define RID_STR_OB_ACCESS_PRIVATE NC_("RID_STR_OB_ACCESS_PRIVATE", "Private") // For Status Bar -#define RID_STR_OB_MEMBERS_COUNT NC_("RID_STR_OB_MEMBERS_COUNT", "%1 members") -#define RID_STR_OB_ITEMS_COUNT NC_("RID_STR_OB_ITEMS_COUNT", "%1 items") +#define RID_STR_OB_MEMBERS_COUNT NNC_("RID_STR_OB_MEMBERS_COUNT", "1 member", "%1 members") +#define RID_STR_OB_ITEMS_COUNT NNC_("RID_STR_OB_ITEMS_COUNT", "1 item", "%1 items") #define RID_STR_OB_READY NC_("RID_STR_OB_READY", "Ready") +// %1 will be replaced with a fractional number of seconds, eg, “1.456s” #define RID_STR_OB_READY_LOADED NC_("RID_STR_OB_READY_LOADED", "✅ Ready (loaded in %1s)") // For Symbol Type Names #define RID_STR_OB_TYPE_UNO_APIS_ROOT NC_("RID_STR_OB_TYPE_UNO_APIS_ROOT", "UNO APIs Root") diff --git a/basctl/source/accessibility/accessibledialogcontrolshape.cxx b/basctl/source/accessibility/accessibledialogcontrolshape.cxx index 04a83949c2c9..934393d46d57 100644 --- a/basctl/source/accessibility/accessibledialogcontrolshape.cxx +++ b/basctl/source/accessibility/accessibledialogcontrolshape.cxx @@ -154,7 +154,7 @@ awt::Rectangle AccessibleDialogControlShape::GetBounds() const void AccessibleDialogControlShape::SetBounds( const awt::Rectangle& aBounds ) { - if ( m_aBounds.X != aBounds.X || m_aBounds.Y != aBounds.Y || m_aBounds.Width != aBounds.Width || m_aBounds.Height != aBounds.Height ) + if (m_aBounds != aBounds) { m_aBounds = aBounds; NotifyAccessibleEvent( AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any() ); diff --git a/basctl/source/accessibility/accessibledialogwindow.cxx b/basctl/source/accessibility/accessibledialogwindow.cxx index f1a786cee3d3..86c6cf3796f2 100644 --- a/basctl/source/accessibility/accessibledialogwindow.cxx +++ b/basctl/source/accessibility/accessibledialogwindow.cxx @@ -502,22 +502,6 @@ void AccessibleDialogWindow::disposing() m_aAccessibleChildren.clear(); } -// XServiceInfo -OUString AccessibleDialogWindow::getImplementationName() -{ - return u"com.sun.star.comp.basctl.AccessibleWindow"_ustr; -} - -sal_Bool AccessibleDialogWindow::supportsService( const OUString& rServiceName ) -{ - return cppu::supportsService(this, rServiceName); -} - -Sequence< OUString > AccessibleDialogWindow::getSupportedServiceNames() -{ - return { u"com.sun.star.awt.AccessibleWindow"_ustr }; -} - // XAccessibleContext sal_Int64 AccessibleDialogWindow::getAccessibleChildCount() { diff --git a/basctl/source/basicide/BasicColorConfig.cxx b/basctl/source/basicide/BasicColorConfig.cxx index d5baf956d9eb..f4b6d5e5fc21 100644 --- a/basctl/source/basicide/BasicColorConfig.cxx +++ b/basctl/source/basicide/BasicColorConfig.cxx @@ -19,6 +19,7 @@ #include #include +#include namespace basctl { @@ -59,10 +60,7 @@ ColorScheme BasicColorConfig::GetColorScheme(const OUString& rScheme) css::uno::Sequence aPropNames(aVecPropNames.size()); OUString* pPropNames = aPropNames.getArray(); - for (size_t i = 0; i < aVecPropNames.size(); i++) - { - pPropNames[i] = aVecPropNames[i]; - } + std::copy(aVecPropNames.begin(), aVecPropNames.end(), pPropNames); css::uno::Sequence aColors = GetProperties(aPropNames); ColorScheme aColorScheme; diff --git a/basctl/source/basicide/ColorSchemeDialog.cxx b/basctl/source/basicide/ColorSchemeDialog.cxx index f2cf62d97c04..bd6725cfbf20 100644 --- a/basctl/source/basicide/ColorSchemeDialog.cxx +++ b/basctl/source/basicide/ColorSchemeDialog.cxx @@ -23,7 +23,6 @@ #include #include #include -#include #include "baside2.hxx" #include #include @@ -119,7 +118,7 @@ IMPL_LINK_NOARG(ColorSchemeDialog, OptionHdl, weld::Toggleable&, void) if (m_xUseScheme->get_active()) { m_xSchemeList->set_sensitive(true); - // Always select a item to avoid having nothing selected + // Always select an item to avoid having nothing selected if (m_sSelectedSchemeId == DEFAULT_SCHEME) { // If the default color scheme was selected, then choose first entry in the list @@ -138,7 +137,7 @@ IMPL_LINK_NOARG(ColorSchemeDialog, OptionHdl, weld::Toggleable&, void) IMPL_LINK_NOARG(ColorSchemeDialog, SelectHdl, weld::ItemView&, void) { // Apply the selected scheme only for the current ModulWinLayout for preview - // Only if the user presses OK the scheme will be applied to all ModulWinLayout(s) + // Only if the user presses OK will the scheme be applied to all ModulWinLayout(s) m_sSelectedSchemeId = m_xSchemeList->get_selected_id(); m_pModulWinLayout->ApplyColorSchemeToCurrentWindow(m_sSelectedSchemeId); } diff --git a/basctl/source/basicide/IDEComboBox.cxx b/basctl/source/basicide/IDEComboBox.cxx index 879cb6a88696..191c1e738a1a 100644 --- a/basctl/source/basicide/IDEComboBox.cxx +++ b/basctl/source/basicide/IDEComboBox.cxx @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include namespace basctl diff --git a/basctl/source/basicide/basdoc.cxx b/basctl/source/basicide/basdoc.cxx index 15642a83bea4..fec8a531adbb 100644 --- a/basctl/source/basicide/basdoc.cxx +++ b/basctl/source/basicide/basdoc.cxx @@ -62,8 +62,8 @@ DocShell::~DocShell() SfxPrinter* DocShell::GetPrinter( bool bCreate ) { if ( !pPrinter && bCreate ) - pPrinter.disposeAndReset(VclPtr::Create(std::make_unique>(GetPool()) + pPrinter.disposeAndReset(VclPtr::Create(std::make_unique(SfxItemSet::makeFixedSfxItemSet + (GetPool())) )); return pPrinter.get(); diff --git a/basctl/source/basicide/baside2.cxx b/basctl/source/basicide/baside2.cxx index 8699f9e16203..d4b1d070bc67 100644 --- a/basctl/source/basicide/baside2.cxx +++ b/basctl/source/basicide/baside2.cxx @@ -51,6 +51,8 @@ #include #include #include +#include +#include #include #include #include @@ -70,7 +72,6 @@ #include #include #include -#include #include #include #include @@ -325,7 +326,7 @@ void ModulWindow::BasicExecute() { std::unique_ptr xBox( Application::CreateMessageDialog(GetFrameWeld(), VclMessageType::Warning, - VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO))); + VclButtonsType::Ok, SfxResId(STR_CANNOTRUNMACRO))); xBox->run(); return; } diff --git a/basctl/source/basicide/baside2.hxx b/basctl/source/basicide/baside2.hxx index ed8f562e5e6f..4aea41bde2db 100644 --- a/basctl/source/basicide/baside2.hxx +++ b/basctl/source/basicide/baside2.hxx @@ -29,10 +29,12 @@ #include #include #include +#include +#include #include +#include #include #include -#include #include #include @@ -229,8 +231,7 @@ private: DECL_LINK(ActivateHdl, weld::Entry&, bool); DECL_LINK(KeyInputHdl, const KeyEvent&, bool); DECL_LINK(EditingEntryHdl, const weld::TreeIter&, bool); - typedef std::pair IterString; - DECL_LINK(EditedEntryHdl, const IterString&, bool); + DECL_LINK(EditedEntryHdl, const weld::TreeView::IterColText&, bool); DECL_LINK(ExecuteUpdateWatches, void*, void); public: @@ -403,7 +404,6 @@ public: virtual bool HasActiveEditor () const override; void UpdateModule (); - const OUString & GetEditorColorScheme() { return m_sWinColorScheme; } void SetEditorColorScheme(const OUString& rColorScheme); }; diff --git a/basctl/source/basicide/baside2b.cxx b/basctl/source/basicide/baside2b.cxx index dcf364f573fe..73f765e71f16 100644 --- a/basctl/source/basicide/baside2b.cxx +++ b/basctl/source/basicide/baside2b.cxx @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,6 @@ #include #include #include -#include #include #include #include @@ -122,7 +122,7 @@ std::u16string_view const cSuffixes = u"%&!#@$"; * Helper functions to get/set text in TextEngine using * the stream interface. * - * get/setText() only supports tools Strings limited to 64K). + * get/setText() only supports tools Strings limited to 64K. */ OUString getTextEngineText (ExtTextEngine& rEngine) { @@ -784,7 +784,7 @@ void EditorWindow::HandleAutoCloseParen() if( aLine.getLength() > 0 && aLine[aSel.GetEnd().GetIndex()-1] != '(' ) { GetEditView()->InsertText(u")"_ustr); - //leave the cursor on its place: inside the parenthesis + //leave the cursor in its place: inside the parenthesis TextPaM aEnd(nLine, aSel.GetEnd().GetIndex()); GetEditView()->SetSelection( TextSelection( aEnd, aEnd ) ); } @@ -805,7 +805,7 @@ void EditorWindow::HandleAutoCloseDoubleQuotes() if( aLine.getLength() > 0 && !aLine.endsWith("\"") && (aPortions.back().tokenType != TokenType::String) ) { GetEditView()->InsertText(u"\""_ustr); - //leave the cursor on its place: inside the two double quotes + //leave the cursor in its place: inside the two double quotes TextPaM aEnd(nLine, aSel.GetEnd().GetIndex()); GetEditView()->SetSelection( TextSelection( aEnd, aEnd ) ); } @@ -1048,18 +1048,6 @@ void EditorWindow::SetSourceInBasic() } } -// Returns the position of the last character of any of the following -// EOL char combinations: CR, CR/LF, LF, return -1 if no EOL is found -sal_Int32 searchEOL( std::u16string_view rStr, sal_Int32 fromIndex ) -{ - size_t iLF = rStr.find( LINE_SEP, fromIndex ); - if( iLF != std::u16string_view::npos ) - return iLF; - - size_t iCR = rStr.find( LINE_SEP_CR, fromIndex ); - return iCR == std::u16string_view::npos ? -1 : iCR; -} - void EditorWindow::CreateEditEngine() { if (pEditEngine) @@ -1083,7 +1071,7 @@ void EditorWindow::CreateEditEngine() do { nLines++; - nIndex = searchEOL( aOUSource, nIndex+1 ); + nIndex = sb::searchEOL( aOUSource, nIndex+1 ); } while (nIndex >= 0); @@ -1209,7 +1197,7 @@ void EditorWindow::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) } else if( rHint.GetId() == SfxHintId::TextViewCaretChanged ) { - // Check whether the line number where the caret is has changed and the + // Check whether the line number where the caret is, has changed and the // highlight needs to be redrawn sal_uInt32 nStartPara = pEditView->GetSelection().GetStart().GetPara(); sal_uInt32 nEndPara = pEditView->GetSelection().GetEnd().GetPara(); @@ -1510,11 +1498,10 @@ void BreakPointWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Re Point const aBmpOff((aOutSz.Width() - aBmpSz.Width()) / 2, (nLineHeight - aBmpSz.Height()) / 2); - for (size_t i = 0, n = GetBreakPoints().size(); i < n; ++i) + for (const BreakPoint& rBrk : GetBreakPoints()) { - BreakPoint& rBrk = GetBreakPoints().at(i); sal_uInt16 const nLine = rBrk.nLine - 1; - size_t const nY = nLine*nLineHeight - nCurYOffset; + size_t const nY = nLine * nLineHeight - nCurYOffset; rRenderContext.DrawImage(Point(0, nY) + aBmpOff, aBrk[rBrk.bEnabled]); } @@ -1572,11 +1559,10 @@ BreakPoint* BreakPointWindow::FindBreakPoint( const Point& rMousePos ) nLineHeight = nLineHeight > 0 ? nLineHeight : 1; size_t nYPos = rMousePos.Y() + nCurYOffset; - for ( size_t i = 0, n = GetBreakPoints().size(); i < n ; ++i ) + for (BreakPoint& rBrk : GetBreakPoints()) { - BreakPoint& rBrk = GetBreakPoints().at( i ); - sal_uInt16 nLine = rBrk.nLine-1; - size_t nY = nLine*nLineHeight; + sal_uInt16 nLine = rBrk.nLine - 1; + size_t nY = nLine * nLineHeight; if ( ( nYPos > nY ) && ( nYPos < ( nY + nLineHeight ) ) ) return &rBrk; } @@ -2359,10 +2345,10 @@ IMPL_LINK(WatchWindow, EditingEntryHdl, const weld::TreeIter&, rIter, bool) return bEdit; } -IMPL_LINK(WatchWindow, EditedEntryHdl, const IterString&, rIterString, bool) +IMPL_LINK(WatchWindow, EditedEntryHdl, const weld::TreeView::IterColText&, rIterColText, bool) { - const weld::TreeIter& rIter = rIterString.first; - OUString aResult = comphelper::string::strip(rIterString.second, ' '); + const weld::TreeIter& rIter = rIterColText.m_rIter; + OUString aResult = comphelper::string::strip(rIterColText.m_sText, ' '); sal_uInt16 nResultLen = aResult.getLength(); sal_Unicode cFirst = aResult[0]; @@ -2985,7 +2971,7 @@ std::vector< OUString > UnoTypeCodeCompletetor::GetXIdlClassMethods() const aRetVect.push_back( rMethod->getName() ); } } - return aRetVect;//this is empty when cannot code complete + return aRetVect;//this is empty when it cannot code complete } std::vector< OUString > UnoTypeCodeCompletetor::GetXIdlClassFields() const @@ -2999,7 +2985,7 @@ std::vector< OUString > UnoTypeCodeCompletetor::GetXIdlClassFields() const aRetVect.push_back( rxField->getName() ); } } - return aRetVect;//this is empty when cannot code complete + return aRetVect;//this is empty when it cannot code complete } diff --git a/basctl/source/basicide/baside3.cxx b/basctl/source/basicide/baside3.cxx index b5988476b39f..762df53c119b 100644 --- a/basctl/source/basicide/baside3.cxx +++ b/basctl/source/basicide/baside3.cxx @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -55,7 +56,6 @@ #include #include #include -#include #include #include #include diff --git a/basctl/source/basicide/basides1.cxx b/basctl/source/basicide/basides1.cxx index d5e2c169a456..ff1fc8159d61 100644 --- a/basctl/source/basicide/basides1.cxx +++ b/basctl/source/basicide/basides1.cxx @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -145,7 +144,7 @@ void Shell::ExecuteSearch( SfxRequest& rReq ) } bool bAllModules = nActModWindows <= 1; - if (!bAllModules) + if (!bAllModules && !mpSearchItem->GetSelection()) { std::unique_ptr xQueryBox(Application::CreateMessageDialog(pCurWin ? pCurWin->GetFrameWeld() : nullptr, VclMessageType::Question, VclButtonsType::YesNo, @@ -1143,7 +1142,7 @@ void Shell::GetState(SfxItemSet &rSet) mpSearchItem->SetSearchString( GetSelectionText( true )); } - if ( mbJustOpened && HasSelection() ) + if (mbJustOpened && HasSelection(/*MustHaveText=*/true)) { OUString aText = GetSelectionText( true ); diff --git a/basctl/source/basicide/basidesh.cxx b/basctl/source/basicide/basidesh.cxx index 8760a318e0fe..a6917a22752e 100644 --- a/basctl/source/basicide/basidesh.cxx +++ b/basctl/source/basicide/basidesh.cxx @@ -44,8 +44,8 @@ #include #include #include +#include #include -#include #include #if defined(DISABLE_DYNLOADING) || ENABLE_MERGELIBS @@ -73,7 +73,6 @@ #include #include #include -#include #include #include #include diff --git a/basctl/source/basicide/basobj2.cxx b/basctl/source/basicide/basobj2.cxx index ed13753ea38e..e621fdb98b71 100644 --- a/basctl/source/basicide/basobj2.cxx +++ b/basctl/source/basicide/basobj2.cxx @@ -39,7 +39,6 @@ #include #include #include -#include #include #include @@ -235,9 +234,6 @@ OUString ChooseMacro(weld::Window* pParent, GetExtraData()->ChoosingMacro() = true; - OUString aScriptURL; - SbMethod* pMethod = nullptr; - MacroChooser aChooser(pParent, xDocFrame); if (bChooseOnly || !SvtModuleOptions::IsBasicIDEInstalled()) aChooser.SetMode(MacroChooser::Mode::ChooseOnly); @@ -252,103 +248,100 @@ OUString ChooseMacro(weld::Window* pParent, GetExtraData()->ChoosingMacro() = false; - switch ( nRetValue ) + if (nRetValue != RET_OK) + return {}; + + bool bError = false; + + SbMethod* pMethod = aChooser.GetMacro(); + if ( !pMethod && aChooser.GetMode() == MacroChooser::Mode::Recording ) + pMethod = aChooser.CreateMacro(); + + if ( !pMethod ) + return {}; + + SbModule* pModule = pMethod->GetModule(); + if ( !pModule ) { - case static_cast(MacroExitCode::Macro_OkRun): + SAL_WARN( "basctl.basicide", "basctl::ChooseMacro: No Module found!" ); + return {}; + } + + StarBASIC* pBasic = dynamic_cast(pModule->GetParent()); + if ( !pBasic ) + { + SAL_WARN( "basctl.basicide", "basctl::ChooseMacro: No Basic found!" ); + return {}; + } + + BasicManager* pBasMgr = FindBasicManager( pBasic ); + if ( !pBasMgr ) + { + SAL_WARN( "basctl.basicide", "basctl::ChooseMacro: No BasicManager found!" ); + return {}; + } + + // name + OUString aName = pBasic->GetName() + "." + pModule->GetName() + "." + pMethod->GetName(); + + // location + OUString aLocation; + ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) ); + if ( aDocument.isDocument() ) + { + // document basic + aLocation = "document" ; + + if ( rxLimitToDocument.is() ) { - bool bError = false; + uno::Reference< frame::XModel > xLimitToDocument( rxLimitToDocument ); - pMethod = aChooser.GetMacro(); - if ( !pMethod && aChooser.GetMode() == MacroChooser::Mode::Recording ) - pMethod = aChooser.CreateMacro(); - - if ( !pMethod ) - break; - - SbModule* pModule = pMethod->GetModule(); - if ( !pModule ) - { - SAL_WARN( "basctl.basicide", "basctl::ChooseMacro: No Module found!" ); - break; - } - - StarBASIC* pBasic = dynamic_cast(pModule->GetParent()); - if ( !pBasic ) - { - SAL_WARN( "basctl.basicide", "basctl::ChooseMacro: No Basic found!" ); - break; - } - - BasicManager* pBasMgr = FindBasicManager( pBasic ); - if ( !pBasMgr ) - { - SAL_WARN( "basctl.basicide", "basctl::ChooseMacro: No BasicManager found!" ); - break; - } - - // name - OUString aName = pBasic->GetName() + "." + pModule->GetName() + "." + pMethod->GetName(); - - // location - OUString aLocation; - ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) ); - if ( aDocument.isDocument() ) - { - // document basic - aLocation = "document" ; - - if ( rxLimitToDocument.is() ) - { - uno::Reference< frame::XModel > xLimitToDocument( rxLimitToDocument ); - - uno::Reference< document::XEmbeddedScripts > xScripts( rxLimitToDocument, UNO_QUERY ); - if ( !xScripts.is() ) - { // the document itself does not support embedding scripts - uno::Reference< document::XScriptInvocationContext > xContext( rxLimitToDocument, UNO_QUERY ); - if ( xContext.is() ) - xScripts = xContext->getScriptContainer(); - if ( xScripts.is() ) - { // but it is able to refer to a document which actually does support this - xLimitToDocument.set( xScripts, UNO_QUERY ); - if ( !xLimitToDocument.is() ) - { - SAL_WARN_IF(!xLimitToDocument.is(), "basctl.basicide", "basctl::ChooseMacro: a script container which is no document!?" ); - xLimitToDocument = rxLimitToDocument; - } - } - } - - if ( xLimitToDocument != aDocument.getDocument() ) + uno::Reference< document::XEmbeddedScripts > xScripts( rxLimitToDocument, UNO_QUERY ); + if ( !xScripts.is() ) + { // the document itself does not support embedding scripts + uno::Reference< document::XScriptInvocationContext > xContext( rxLimitToDocument, UNO_QUERY ); + if ( xContext.is() ) + xScripts = xContext->getScriptContainer(); + if ( xScripts.is() ) + { // but it is able to refer to a document which actually does support this + xLimitToDocument.set( xScripts, UNO_QUERY ); + if ( !xLimitToDocument.is() ) { - // error - bError = true; - std::unique_ptr xError(Application::CreateMessageDialog(nullptr, - VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_ERRORCHOOSEMACRO))); - xError->run(); + SAL_WARN_IF(!xLimitToDocument.is(), "basctl.basicide", "basctl::ChooseMacro: a script container which is no document!?" ); + xLimitToDocument = rxLimitToDocument; } } } - else - { - // application basic - aLocation = "application" ; - } - // script URL - if ( !bError ) + if ( xLimitToDocument != aDocument.getDocument() ) { - aScriptURL = "vnd.sun.star.script:" + aName + "?language=Basic&location=" + aLocation; - } - - if ( !rxLimitToDocument.is() ) - { - MacroExecutionData* pExecData = new MacroExecutionData; - pExecData->aDocument = std::move(aDocument); - pExecData->xMethod = pMethod; // keep alive until the event has been processed - Application::PostUserEvent( LINK( nullptr, MacroExecution, ExecuteMacroEvent ), pExecData ); + // error + bError = true; + std::unique_ptr xError(Application::CreateMessageDialog(nullptr, + VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_ERRORCHOOSEMACRO))); + xError->run(); } } - break; + } + else + { + // application basic + aLocation = "application" ; + } + + // script URL + OUString aScriptURL; + if ( !bError ) + { + aScriptURL = "vnd.sun.star.script:" + aName + "?language=Basic&location=" + aLocation; + } + + if ( !rxLimitToDocument.is() ) + { + MacroExecutionData* pExecData = new MacroExecutionData; + pExecData->aDocument = std::move(aDocument); + pExecData->xMethod = pMethod; // keep alive until the event has been processed + Application::PostUserEvent( LINK( nullptr, MacroExecution, ExecuteMacroEvent ), pExecData ); } return aScriptURL; diff --git a/basctl/source/basicide/basobj3.cxx b/basctl/source/basicide/basobj3.cxx index 28e3f416d1e6..f6181f6193a3 100644 --- a/basctl/source/basicide/basobj3.cxx +++ b/basctl/source/basicide/basobj3.cxx @@ -19,8 +19,8 @@ #include #include +#include #include -#include #include #include #include @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -285,6 +286,46 @@ void RunMethod( SbMethod const * pMethod ) pMethod->Get( aRes ); } +void DeleteMacro(SbMethod& rMethod) +{ + SfxDispatcher* pDispatcher = GetDispatcher(); + + if (pDispatcher) + pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES ); + + // mark current doc as modified: + StarBASIC* pBasic = FindBasic(&rMethod); + assert(pBasic && "Basic?!"); + BasicManager* pBasMgr = FindBasicManager( pBasic ); + DBG_ASSERT( pBasMgr, "BasMgr?" ); + ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) ); + if ( aDocument.isDocument() ) + { + aDocument.setDocumentModified(); + if (SfxBindings* pBindings = GetBindingsPtr()) + pBindings->Invalidate( SID_SAVEDOC ); + } + + SbModule* pModule = rMethod.GetModule(); + assert(pModule && "DeleteMacro: No Module?!"); + OUString aSource( pModule->GetSourceWithoutMethod(rMethod) ); + pModule->GetMethods()->Remove( &rMethod ); + pModule->SetSource( aSource ); + + // update module in library + OUString aLibName = pBasic->GetName(); + OUString aModName = pModule->GetName(); + OSL_VERIFY( aDocument.updateModule( aLibName, aModName, aSource ) ); + + if (pDispatcher) + { + SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLibName, aModName, + OUString(), OUString() ); + pDispatcher->ExecuteList( SID_BASICIDE_UPDATEMODULESOURCE, + SfxCallMode::SYNCHRON, { &aInfoItem }); + } +} + void StopBasic() { StarBASIC::Stop(); diff --git a/basctl/source/basicide/bastype2.cxx b/basctl/source/basicide/bastype2.cxx index 1df660b1c5a4..e462d651cb5e 100644 --- a/basctl/source/basicide/bastype2.cxx +++ b/basctl/source/basicide/bastype2.cxx @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/basctl/source/basicide/bastype3.cxx b/basctl/source/basicide/bastype3.cxx index 0f3004dc7f2e..841ecea48eb3 100644 --- a/basctl/source/basicide/bastype3.cxx +++ b/basctl/source/basicide/bastype3.cxx @@ -30,6 +30,8 @@ #include #include #include +#include +#include namespace basctl { diff --git a/basctl/source/basicide/bastypes.cxx b/basctl/source/basicide/bastypes.cxx index b17eadc13002..328c5fa4d106 100644 --- a/basctl/source/basicide/bastypes.cxx +++ b/basctl/source/basicide/bastypes.cxx @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -49,8 +50,8 @@ #include #include #include +#include #include -#include #include #include @@ -613,53 +614,6 @@ void TabBar::Sort() } } -void CutLines( OUString& rStr, sal_Int32 nStartLine, sal_Int32 nLines ) -{ - sal_Int32 nStartPos = 0; - sal_Int32 nLine = 0; - while ( nLine < nStartLine ) - { - nStartPos = searchEOL( rStr, nStartPos ); - if( nStartPos == -1 ) - break; - nStartPos++; // not the \n. - nLine++; - } - - SAL_WARN_IF( nStartPos == -1, "basctl.basicide", "CutLines: Start line not found!" ); - - if ( nStartPos == -1 ) - return; - - sal_Int32 nEndPos = nStartPos; - - for ( sal_Int32 i = 0; i < nLines; i++ ) - nEndPos = searchEOL( rStr, nEndPos+1 ); - - if ( nEndPos == -1 ) // might happen at the last line - nEndPos = rStr.getLength(); - else - nEndPos++; - - rStr = OUString::Concat(rStr.subView( 0, nStartPos )) + rStr.subView( nEndPos ); - - // erase trailing empty lines - { - sal_Int32 n = nStartPos; - sal_Int32 nLen = rStr.getLength(); - while ( ( n < nLen ) && ( rStr[ n ] == LINE_SEP || - rStr[ n ] == LINE_SEP_CR ) ) - { - n++; - } - - if ( n > nStartPos ) - { - rStr = OUString::Concat(rStr.subView( 0, nStartPos )) + rStr.subView( n ); - } - } -} - sal_uInt32 CalcLineCount( SvStream& rStream ) { sal_uInt32 nLFs = 0; @@ -757,6 +711,7 @@ static bool QueryDel(std::u16string_view rName, const OUString &rStr, weld::Widg bool QueryDelMacro( std::u16string_view rName, weld::Widget* pParent ) { + EnsureIde(); return QueryDel( rName, IDEResId( RID_STR_QUERYDELMACRO ), pParent ); } diff --git a/basctl/source/basicide/breakpoint.hxx b/basctl/source/basicide/breakpoint.hxx index 324564aaa72e..e8677dfd4b3f 100644 --- a/basctl/source/basicide/breakpoint.hxx +++ b/basctl/source/basicide/breakpoint.hxx @@ -70,6 +70,13 @@ public: size_t size() const; BreakPoint& at(size_t i); const BreakPoint& at(size_t i) const; + + // Iterator support + auto begin() { return maBreakPoints.begin(); } + auto end() { return maBreakPoints.end(); } + auto cbegin() const { return maBreakPoints.cbegin(); } + auto cend() const { return maBreakPoints.cend(); } + void remove(const BreakPoint* ptr); void remove(size_t i); }; diff --git a/basctl/source/basicide/brkdlg.hxx b/basctl/source/basicide/brkdlg.hxx index 61241ce4ac0e..71850d0e2add 100644 --- a/basctl/source/basicide/brkdlg.hxx +++ b/basctl/source/basicide/brkdlg.hxx @@ -19,11 +19,13 @@ #pragma once +#include +#include #include #include #include #include -#include +#include #include "breakpoint.hxx" namespace basctl diff --git a/basctl/source/basicide/idecodecompletiontypes.cxx b/basctl/source/basicide/idecodecompletiontypes.cxx index 22779828e520..84d703f0d095 100644 --- a/basctl/source/basicide/idecodecompletiontypes.cxx +++ b/basctl/source/basicide/idecodecompletiontypes.cxx @@ -12,21 +12,6 @@ namespace basctl { -IdeParamInfo::IdeParamInfo(OUString sName_, OUString sTypeName_, bool bOut, bool bIn) - : sName(std::move(sName_)) - , sTypeName(std::move(sTypeName_)) - , bIsOut(bOut) - , bIsIn(bIn) -{ -} - -IdeDimensionInfo::IdeDimensionInfo(sal_Int32 lower, sal_Int32 upper, bool dynamic) - : nLowerBound(lower) - , nUpperBound(upper) - , bIsDynamic(dynamic) -{ -} - IdeSymbolInfo::IdeSymbolInfo(std::u16string_view rName, IdeSymbolKind eTheKind, std::u16string_view rParentIdentifier) : sName(rName) @@ -43,39 +28,6 @@ IdeSymbolInfo::IdeSymbolInfo(std::u16string_view rName, IdeSymbolKind eTheKind, } } -void IdeSymbolInfo::AddMember(std::shared_ptr pMember) -{ - if (!pMember) - return; - - mapMembers.insert_or_assign(pMember->sName, std::move(pMember)); -} - -OUString CreateRootIdentifier(IdeSymbolKind eKind, std::u16string_view sOptionalPayload) -{ - OUStringBuffer sId(u"root:"); - - switch (eKind) - { - case IdeSymbolKind::ROOT_UNO_APIS: - sId.append(u"uno_apis"); - break; - case IdeSymbolKind::ROOT_APPLICATION_LIBS: - sId.append(u"app_macros"); - break; - case IdeSymbolKind::ROOT_DOCUMENT_LIBS: - sId.append(OUString::Concat(u"doc:") + sOptionalPayload); - break; - case IdeSymbolKind::ROOT_BASIC_BUILTINS: - sId.append(u"builtins"); - break; - default: - sId.append(u"unknown"); - break; - } - return sId.makeStringAndClear(); -} - } // namespace basctl /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basctl/source/basicide/idedataprovider.cxx b/basctl/source/basicide/idedataprovider.cxx index ce55c5fe734e..80ae8f330369 100644 --- a/basctl/source/basicide/idedataprovider.cxx +++ b/basctl/source/basicide/idedataprovider.cxx @@ -335,6 +335,8 @@ void ImplGetChildrenOfBasicLibrary(SymbolInfoList& rChildren, const IdeSymbolInf BasicManager* pBasMgr = aDoc.getBasicManager(); if (aDoc.hasLibrary(E_SCRIPTS, rParent.sName)) { + aDoc.loadLibraryIfExists(E_SCRIPTS, rParent.sName); + StarBASIC* pLib = pBasMgr->GetLib(rParent.sName); if (pLib) { @@ -374,81 +376,6 @@ void IdeDataProvider::Initialize() SAL_INFO("basctl", "Performing full synchronous UNO scan..."); performFullUnoScan(); - // Preload all BASIC Libraries - IdeTimer aBasicTimer(u"IdeDataProvider::Initialize (Basic Library Preload)"_ustr); - SAL_INFO("basctl", "Starting BASIC library preload..."); - - try - { - ScriptDocument aAppDoc = ScriptDocument::getApplicationScriptDocument(); - if (aAppDoc.isAlive()) - { - Reference xLibContainer - = aAppDoc.getLibraryContainer(E_SCRIPTS); - if (xLibContainer.is()) - { - for (const OUString& rLibName : xLibContainer->getElementNames()) - { - try - { - if (xLibContainer->hasByName(rLibName) - && !xLibContainer->isLibraryLoaded(rLibName)) - { - xLibContainer->loadLibrary(rLibName); - } - } - catch (const Exception& e) - { - SAL_WARN("basctl", "Exception while preloading application library '" - << rLibName << "': " << e.Message); - } - } - } - } - } - catch (const Exception& e) - { - SAL_WARN("basctl", "Could not retrieve Application library container: " << e.Message); - } - - // Preload from any open documents - try - { - for (const auto& rDoc : - ScriptDocument::getAllScriptDocuments(ScriptDocument::DocumentsSorted)) - { - if (rDoc.isAlive()) - { - auto xDocLibContainer = rDoc.getLibraryContainer(E_SCRIPTS); - if (xDocLibContainer.is()) - { - for (const OUString& rLibName : xDocLibContainer->getElementNames()) - { - try - { - if (xDocLibContainer->hasByName(rLibName) - && !xDocLibContainer->isLibraryLoaded(rLibName)) - { - xDocLibContainer->loadLibrary(rLibName); - } - } - catch (const Exception& e) - { - SAL_WARN("basctl", "Exception while preloading document library '" - << rLibName << "' in document '" - << rDoc.getTitle() << "': " << e.Message); - } - } - } - } - } - } - catch (const Exception& e) - { - SAL_WARN("basctl", "Could not iterate through document libraries: " << e.Message); - } - SAL_INFO("basctl", "BASIC library preload finished."); - m_aAllTopLevelNodes.clear(); m_aAllTopLevelNodes.push_back( std::make_shared(u"UNO APIs", IdeSymbolKind::ROOT_UNO_APIS, u"root")); @@ -461,16 +388,6 @@ void IdeDataProvider::Initialize() SAL_INFO("basctl", "Synchronous data provider initialization complete."); } -void IdeDataProvider::Reset() -{ - SAL_INFO("basctl", "IdeDataProvider: Resetting state."); - m_bInitialized = false; - m_aAllTopLevelNodes.clear(); - m_aMembersCache.clear(); - - m_pUnoHierarchy = std::make_unique(); -} - void IdeDataProvider::performFullUnoScan() { IdeTimer aScanTimer(u"IdeDataProvider::performFullUnoScan"_ustr); diff --git a/basctl/source/basicide/iderdll.cxx b/basctl/source/basicide/iderdll.cxx index b9ca566e2f51..d01e51a3f31f 100644 --- a/basctl/source/basicide/iderdll.cxx +++ b/basctl/source/basicide/iderdll.cxx @@ -111,6 +111,12 @@ OUString IDEResId(TranslateId aId) return Translate::get(aId, SfxApplication::GetModule(SfxToolsModule::Basic)->GetResLocale()); } +OUString IDEResId(TranslateNId aContextSingularPlural, int nCardinality) +{ + return Translate::nget(aContextSingularPlural, nCardinality, + SfxApplication::GetModule(SfxToolsModule::Basic)->GetResLocale()); +} + namespace { diff --git a/basctl/source/basicide/macrodlg.cxx b/basctl/source/basicide/macrodlg.cxx index c7a2b6dc4076..e5b8be550890 100644 --- a/basctl/source/basicide/macrodlg.cxx +++ b/basctl/source/basicide/macrodlg.cxx @@ -40,13 +40,14 @@ #include #include #include +#include #include +#include #include #include #include #include #include -#include #include namespace basctl @@ -264,35 +265,7 @@ void MacroChooser::DeleteMacro() if (!(pMethod && QueryDelMacro(pMethod->GetName(), m_xDialog.get()))) return; - if (SfxDispatcher* pDispatcher = GetDispatcher()) - pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES ); - - // mark current doc as modified: - StarBASIC* pBasic = FindBasic(pMethod); - assert(pBasic && "Basic?!"); - BasicManager* pBasMgr = FindBasicManager( pBasic ); - DBG_ASSERT( pBasMgr, "BasMgr?" ); - ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) ); - if ( aDocument.isDocument() ) - { - aDocument.setDocumentModified(); - if (SfxBindings* pBindings = GetBindingsPtr()) - pBindings->Invalidate( SID_SAVEDOC ); - } - - SbModule* pModule = pMethod->GetModule(); - assert(pModule && "DeleteMacro: No Module?!"); - OUString aSource( pModule->GetSource() ); - sal_uInt16 nStart, nEnd; - pMethod->GetLineRange( nStart, nEnd ); - pModule->GetMethods()->Remove( pMethod ); - CutLines( aSource, nStart-1, nEnd-nStart+1 ); - pModule->SetSource( aSource ); - - // update module in library - OUString aLibName = pBasic->GetName(); - OUString aModName = pModule->GetName(); - OSL_VERIFY( aDocument.updateModule( aLibName, aModName, aSource ) ); + basctl::DeleteMacro(*pMethod); std::unique_ptr pSelected = m_xMacroBox->get_selected(); assert(pSelected && "DeleteMacro: Entry ?!"); @@ -467,7 +440,7 @@ IMPL_LINK_NOARG(MacroChooser, MacroDoubleClickHdl, const weld::TreeIter&, bool) { std::unique_ptr xError( Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, - VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO))); + VclButtonsType::Ok, SfxResId(STR_CANNOTRUNMACRO))); xError->run(); return true; } @@ -479,7 +452,7 @@ IMPL_LINK_NOARG(MacroChooser, MacroDoubleClickHdl, const weld::TreeIter&, bool) return true; } - m_xDialog->response(static_cast(MacroExitCode::Macro_OkRun)); + m_xDialog->response(RET_OK); return true; } @@ -521,7 +494,7 @@ IMPL_LINK_NOARG(MacroChooser, BasicSelectHdl, weld::ItemView&, void) CheckButtons(); } -IMPL_LINK_NOARG(MacroChooser, EditModifyHdl, weld::Entry&, void) +IMPL_LINK_NOARG(MacroChooser, EditModifyHdl, weld::TextWidget&, void) { // select the module in which the macro is put at "new", // if BasicManager or Lib is selecting @@ -600,7 +573,7 @@ IMPL_LINK(MacroChooser, ButtonHdl, weld::Button&, rButton, void) if ( aDocument.isDocument() && !aDocument.allowMacros() ) { std::unique_ptr xError(Application::CreateMessageDialog(m_xDialog.get(), - VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO))); + VclMessageType::Warning, VclButtonsType::Ok, SfxResId(STR_CANNOTRUNMACRO))); xError->run(); return; } @@ -623,12 +596,12 @@ IMPL_LINK(MacroChooser, ButtonHdl, weld::Button&, rButton, void) return; } - m_xDialog->response(static_cast(MacroExitCode::Macro_OkRun)); + m_xDialog->response(RET_OK); } else if (&rButton == m_xCloseButton.get()) { StoreMacroDescription(); - m_xDialog->response(static_cast(MacroExitCode::Macro_Close)); + m_xDialog->response(RET_CLOSE); } else if (&rButton == m_xEditButton.get() || &rButton == m_xDelButton.get() || &rButton == m_xNewButton.get()) { @@ -674,52 +647,44 @@ IMPL_LINK(MacroChooser, ButtonHdl, weld::Button&, rButton, void) pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO, SfxCallMode::ASYNCHRON, { &aInfoItem }); } - m_xDialog->response(static_cast(MacroExitCode::Macro_Close)); + m_xDialog->response(RET_CLOSE); + } + else if (&rButton == m_xDelButton.get()) + { + DeleteMacro(); + CheckButtons(); + UpdateFields(); + //if ( m_xMacroBox->GetCurEntry() ) // OV-Bug ? + // m_xMacroBox->Select( m_xMacroBox->GetCurEntry() ); } else { - if (&rButton == m_xDelButton.get()) + if ( !IsValidSbxName(m_xMacroNameEdit->get_text()) ) { - DeleteMacro(); + std::unique_ptr xError(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME))); + xError->run(); + m_xMacroNameEdit->select_region(0, -1); + m_xMacroNameEdit->grab_focus(); + return; + } + SbMethod* pMethod = CreateMacro(); + if ( pMethod ) + { + aInfoItem.SetMethod( pMethod->GetName() ); + aInfoItem.SetModule( pMethod->GetModule()->GetName() ); + aInfoItem.SetLib( pMethod->GetModule()->GetParent()->GetName() ); + SfxAllItemSet aArgs( SfxGetpApp()->GetPool() ); + SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs ); + SfxGetpApp()->ExecuteSlot( aRequest ); + if (SfxDispatcher* pDispatcher = GetDispatcher()) { - pDispatcher->ExecuteList( SID_BASICIDE_UPDATEMODULESOURCE, - SfxCallMode::SYNCHRON, { &aInfoItem }); - } - CheckButtons(); - UpdateFields(); - //if ( m_xMacroBox->GetCurEntry() ) // OV-Bug ? - // m_xMacroBox->Select( m_xMacroBox->GetCurEntry() ); - } - else - { - if ( !IsValidSbxName(m_xMacroNameEdit->get_text()) ) - { - std::unique_ptr xError(Application::CreateMessageDialog(m_xDialog.get(), - VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME))); - xError->run(); - m_xMacroNameEdit->select_region(0, -1); - m_xMacroNameEdit->grab_focus(); - return; - } - SbMethod* pMethod = CreateMacro(); - if ( pMethod ) - { - aInfoItem.SetMethod( pMethod->GetName() ); - aInfoItem.SetModule( pMethod->GetModule()->GetName() ); - aInfoItem.SetLib( pMethod->GetModule()->GetParent()->GetName() ); - SfxAllItemSet aArgs( SfxGetpApp()->GetPool() ); - SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs ); - SfxGetpApp()->ExecuteSlot( aRequest ); - - if (SfxDispatcher* pDispatcher = GetDispatcher()) - { - pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO, - SfxCallMode::ASYNCHRON, { &aInfoItem }); - } - StoreMacroDescription(); - m_xDialog->response(static_cast(MacroExitCode::Macro_New)); + pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO, + SfxCallMode::ASYNCHRON, { &aInfoItem }); } + StoreMacroDescription(); + m_xDialog->response(RET_CLOSE); } } } @@ -800,7 +765,7 @@ IMPL_LINK(MacroChooser, ButtonHdl, weld::Button&, rButton, void) weld::DialogController::runAsync(xDlg, [this](sal_Int32 nRet) { if (nRet == RET_OK) // not only closed { - m_xDialog->response(static_cast(MacroExitCode::Macro_Close)); + m_xDialog->response(RET_CLOSE); return; } diff --git a/basctl/source/basicide/macrodlg.hxx b/basctl/source/basicide/macrodlg.hxx index 3073c2cf35e6..646454b1bf26 100644 --- a/basctl/source/basicide/macrodlg.hxx +++ b/basctl/source/basicide/macrodlg.hxx @@ -23,20 +23,14 @@ #include #include #include +#include #include +#include #include -#include namespace basctl { -enum class MacroExitCode { - Macro_Close = 110, - Macro_OkRun = 111, - Macro_New = 112, - Macro_Edit = 114, -}; - class MacroChooser : public SfxDialogController { public: @@ -59,7 +53,7 @@ private: DECL_LINK(MacroSelectHdl, weld::ItemView&, void); DECL_LINK(MacroDoubleClickHdl, const weld::TreeIter&, bool); DECL_LINK(BasicSelectHdl, weld::ItemView&, void); - DECL_LINK(EditModifyHdl, weld::Entry&, void); + DECL_LINK(EditModifyHdl, weld::TextWidget&, void); DECL_LINK(ContextMenuHdl, const CommandEvent&, bool); DECL_LINK(ButtonHdl, weld::Button&, void); diff --git a/basctl/source/basicide/moduldl2.cxx b/basctl/source/basicide/moduldl2.cxx index 9cd98baa4a38..b768ad9d4ce8 100644 --- a/basctl/source/basicide/moduldl2.cxx +++ b/basctl/source/basicide/moduldl2.cxx @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include @@ -308,10 +308,10 @@ IMPL_LINK(LibPage, EditingEntryHdl, const weld::TreeIter&, rIter, bool) return true; } -IMPL_LINK(LibPage, EditedEntryHdl, const IterString&, rIterString, bool) +IMPL_LINK(LibPage, EditedEntryHdl, const weld::TreeView::IterColText&, rIterColText, bool) { - const weld::TreeIter& rIter = rIterString.first; - OUString sNewName = rIterString.second; + const weld::TreeIter& rIter = rIterColText.m_rIter; + OUString sNewName = rIterColText.m_sText; bool bValid = sNewName.getLength() <= 30 && IsValidSbxName(sNewName); OUString aOldName(m_xLibBox->get_text(rIter, 0)); diff --git a/basctl/source/basicide/moduldlg.cxx b/basctl/source/basicide/moduldlg.cxx index b23a703d7de9..a96b838a40df 100644 --- a/basctl/source/basicide/moduldlg.cxx +++ b/basctl/source/basicide/moduldlg.cxx @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include #include @@ -81,10 +81,10 @@ IMPL_LINK(ObjectPage, EditingEntryHdl, const weld::TreeIter&, rEntry, bool) return bRet; } -IMPL_LINK(ObjectPage, EditedEntryHdl, const IterString&, rIterString, bool) +IMPL_LINK(ObjectPage, EditedEntryHdl, const weld::TreeView::IterColText&, rIterColText, bool) { - const weld::TreeIter& rEntry = rIterString.first; - OUString sNewText = rIterString.second; + const weld::TreeIter& rEntry = rIterColText.m_rIter; + OUString sNewText = rIterColText.m_sText; if ( !IsValidSbxName(sNewText) ) { @@ -927,7 +927,7 @@ LibDialog::LibDialog(weld::Window* pParent) { m_xLibBox->set_size_request(m_xLibBox->get_approximate_digit_width() * 28, m_xLibBox->get_height_rows(8)); - m_xLibBox->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xLibBox->enable_toggle_buttons(); // tdf#93476 The libraries should be listed alphabetically m_xLibBox->make_sorted(); } diff --git a/basctl/source/basicide/moduldlg.hxx b/basctl/source/basicide/moduldlg.hxx index e6d6893004d9..9616074caf17 100644 --- a/basctl/source/basicide/moduldlg.hxx +++ b/basctl/source/basicide/moduldlg.hxx @@ -25,14 +25,19 @@ #include #include +#include +#include #include +#include #include #include #include +#include +#include #include +#include #include #include -#include #include class SvxPasswordDialog; @@ -148,8 +153,7 @@ class ObjectPage final : public OrganizePage DECL_LINK(BasicBoxHighlightHdl, weld::ItemView&, void); DECL_LINK( ButtonHdl, weld::Button&, void ); DECL_LINK( EditingEntryHdl, const weld::TreeIter&, bool ); - typedef std::pair IterString; - DECL_LINK( EditedEntryHdl, const IterString&, bool ); + DECL_LINK(EditedEntryHdl, const weld::TreeView::IterColText&, bool); void CheckButtons(); bool GetSelection( ScriptDocument& rDocument, OUString& rLibName ); @@ -186,8 +190,7 @@ class LibPage final : public OrganizePage DECL_LINK( ButtonHdl, weld::Button&, void ); DECL_LINK( CheckPasswordHdl, SvxPasswordDialog *, bool ); DECL_LINK( EditingEntryHdl, const weld::TreeIter&, bool ); - typedef std::pair IterString; - DECL_LINK( EditedEntryHdl, const IterString&, bool ); + DECL_LINK(EditedEntryHdl, const weld::TreeView::IterColText&, bool); void CheckButtons(); void DeleteCurrent(); diff --git a/basctl/source/basicide/objectbrowser.cxx b/basctl/source/basicide/objectbrowser.cxx index 720d7ffbeef9..e4e02cb0f2cc 100644 --- a/basctl/source/basicide/objectbrowser.cxx +++ b/basctl/source/basicide/objectbrowser.cxx @@ -29,11 +29,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include @@ -224,22 +225,22 @@ void FormatMethodSignature(rtl::OUStringBuffer& rBuffer, const basctl::IdeSymbol const auto& param = rSymbol.aParameters[i]; if (param.bIsOptional) { - rBuffer.append(IDEResId(RID_STR_OB_OPTIONAL) + u" "); + rBuffer.append(u"Optional "); } if (!param.bIsByVal) { - rBuffer.append(IDEResId(RID_STR_OB_BYREF) + u" "); + rBuffer.append(u"ByRef "); } if (param.bIsOut && !param.bIsIn) { - rBuffer.append(IDEResId(RID_STR_OB_OUT_PARAM) + u" "); + rBuffer.append(u"[out] "); } else if (param.bIsOut && param.bIsIn) { - rBuffer.append(IDEResId(RID_STR_OB_INOUT_PARAM) + u" "); + rBuffer.append(u"[inout] "); } - rBuffer.append(param.sName + IDEResId(RID_STR_OB_AS) + param.sTypeName); + rBuffer.append(param.sName + u" As " + param.sTypeName); if (i < rSymbol.aParameters.size() - 1) { rBuffer.append(u", "); @@ -249,7 +250,7 @@ void FormatMethodSignature(rtl::OUStringBuffer& rBuffer, const basctl::IdeSymbol rBuffer.append(u")"); if (!rSymbol.sReturnTypeName.isEmpty() && rSymbol.sReturnTypeName != "Void") { - rBuffer.append(IDEResId(RID_STR_OB_AS) + rSymbol.sReturnTypeName); + rBuffer.append(u" As " + rSymbol.sReturnTypeName); } } @@ -259,7 +260,7 @@ void FormatPropertySignature(rtl::OUStringBuffer& rBuffer, const basctl::IdeSymb OUString sType = !rSymbol.sTypeName.isEmpty() ? rSymbol.sTypeName : rSymbol.sReturnTypeName; if (!sType.isEmpty()) { - rBuffer.append(IDEResId(RID_STR_OB_AS) + sType); + rBuffer.append(u" As " + sType); } } @@ -325,22 +326,19 @@ OUString FormatSymbolSignature(const IdeSymbolInfo& rSymbol) rtl::OUStringBuffer sModifiers; if (param.bIsOptional) { - sModifiers.append(IDEResId(RID_STR_OB_OPTIONAL)); + sModifiers.append(u"Optional"); } if (param.bIsOut && !param.bIsIn) { - OUString sOut = IDEResId(RID_STR_OB_OUT_PARAM); - sModifiers.append(sModifiers.getLength() ? (u", "_ustr + sOut) : sOut); + sModifiers.append(sModifiers.getLength() ? u", [out]" : u"[out]"); } else if (param.bIsOut && param.bIsIn) { - OUString sInOut = IDEResId(RID_STR_OB_INOUT_PARAM); - sModifiers.append(sModifiers.getLength() ? (u", "_ustr + sInOut) : sInOut); + sModifiers.append(sModifiers.getLength() ? u", [inout]" : u"[inout]"); } if (!param.bIsByVal) { - OUString sByRef = IDEResId(RID_STR_OB_BYREF); - sModifiers.append(sModifiers.getLength() ? (u", "_ustr + sByRef) : sByRef); + sModifiers.append(sModifiers.getLength() ? u", ByRef" : u"ByRef"); } if (sModifiers.getLength() > 0) { @@ -418,9 +416,9 @@ OUString FormatContainerSignature(const IdeSymbolInfo& rSymbol, { auto aChildren = pDataProvider->GetChildNodes(rSymbol); sal_Int64 nChildren = static_cast(aChildren.size()); - sInfo.append( - IDEResId(RID_STR_OB_CONTENTS_HEADER) - + IDEResId(RID_STR_OB_CONTAINS_ITEMS).replaceFirst(u"%1", OUString::number(nChildren))); + sInfo.append(IDEResId(RID_STR_OB_CONTENTS_HEADER) + + IDEResId(RID_STR_OB_CONTAINS_ITEMS, nChildren) + .replaceFirst(u"%1", OUString::number(nChildren))); } if (!rSymbol.sQualifiedName.isEmpty() && rSymbol.sQualifiedName != rSymbol.sName) @@ -790,10 +788,13 @@ void ObjectBrowser::Show(bool bVisible) if (!m_bFirstLoadComplete) { + const LocaleDataWrapper& rLocaleData + = Application::GetSettings().GetUILocaleDataWrapper(); + OUString sElapsedSeconds + = rLocaleData.getNum(aTotalInitTimer.getElapsedTimeMs(), 3, false); m_bFirstLoadComplete = true; - double fElapsedSeconds = aTotalInitTimer.getElapsedTimeMs() / 1000.0; - OUString sStatus = IDEResId(RID_STR_OB_READY_LOADED) - .replaceFirst(u"%1", OUString::number(fElapsedSeconds)); + OUString sStatus + = IDEResId(RID_STR_OB_READY_LOADED).replaceFirst(u"%1", sElapsedSeconds); m_xStatusLabel->set_label(sStatus); } } @@ -1007,16 +1008,15 @@ void ObjectBrowser::UpdateStatusBar(const IdeSymbolInfo* pLeftSymbol, for (const auto& pair : aMembers) nTotalMembers += pair.second.size(); sStatusText - = IDEResId(RID_STR_OB_MEMBERS_COUNT) + = IDEResId(RID_STR_OB_MEMBERS_COUNT, nTotalMembers) .replaceFirst(u"%1", OUString::number(static_cast(nTotalMembers))); } else if (IsExpandable(*pLeftSymbol)) { - auto aChildren = m_pDataProvider->GetChildNodes(*pLeftSymbol); + size_t nChildren = m_pDataProvider->GetChildNodes(*pLeftSymbol).size(); sStatusText - = IDEResId(RID_STR_OB_ITEMS_COUNT) - .replaceFirst(u"%1", - OUString::number(static_cast(aChildren.size()))); + = IDEResId(RID_STR_OB_ITEMS_COUNT, nChildren) + .replaceFirst(u"%1", OUString::number(static_cast(nChildren))); } else { diff --git a/basctl/source/basicide/objectbrowsersearch.cxx b/basctl/source/basicide/objectbrowsersearch.cxx index 6efb2df034da..5d735eff4b3f 100644 --- a/basctl/source/basicide/objectbrowsersearch.cxx +++ b/basctl/source/basicide/objectbrowsersearch.cxx @@ -42,7 +42,7 @@ void ObjectBrowserSearch::Initialize() } } -IMPL_STATIC_LINK(basctl::ObjectBrowserSearch, OnFilterChanged, weld::Entry&, /*rBox*/, void) +IMPL_STATIC_LINK(basctl::ObjectBrowserSearch, OnFilterChanged, weld::TextWidget&, /*rBox*/, void) { // STUB } diff --git a/basctl/source/dlged/managelang.cxx b/basctl/source/dlged/managelang.cxx index dc32332aff37..740eca2a04c9 100644 --- a/basctl/source/dlged/managelang.cxx +++ b/basctl/source/dlged/managelang.cxx @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include @@ -226,7 +226,7 @@ SetDefaultLanguageDialog::SetDefaultLanguageDialog(weld::Window* pParent, std::s { m_xLanguageLB->set_size_request(-1, m_xLanguageLB->get_height_rows(10)); m_xCheckLangLB->set_size_request(-1, m_xCheckLangLB->get_height_rows(10)); - m_xCheckLangLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xCheckLangLB->enable_toggle_buttons(); if (m_xLocalizationMgr->isLibraryLocalized()) { diff --git a/basctl/source/dlged/propbrw.cxx b/basctl/source/dlged/propbrw.cxx index 686fe51d5595..2509870c23d0 100644 --- a/basctl/source/dlged/propbrw.cxx +++ b/basctl/source/dlged/propbrw.cxx @@ -40,7 +40,6 @@ #include #include #include -#include #include diff --git a/basctl/source/inc/ColorSchemeDialog.hxx b/basctl/source/inc/ColorSchemeDialog.hxx index 94628c40029b..7c889ca95cfa 100644 --- a/basctl/source/inc/ColorSchemeDialog.hxx +++ b/basctl/source/inc/ColorSchemeDialog.hxx @@ -19,9 +19,11 @@ #pragma once +#include #include +#include #include -#include +#include namespace basctl { diff --git a/basctl/source/inc/ObjectCatalog.hxx b/basctl/source/inc/ObjectCatalog.hxx index ede8e8670ec5..539e62b0f108 100644 --- a/basctl/source/inc/ObjectCatalog.hxx +++ b/basctl/source/inc/ObjectCatalog.hxx @@ -22,7 +22,7 @@ #include "bastype2.hxx" #include "bastypes.hxx" -#include +#include namespace basctl { diff --git a/basctl/source/inc/accessibledialogcontrolshape.hxx b/basctl/source/inc/accessibledialogcontrolshape.hxx index 5639df8a6737..05fa32b5efd9 100644 --- a/basctl/source/inc/accessibledialogcontrolshape.hxx +++ b/basctl/source/inc/accessibledialogcontrolshape.hxx @@ -20,7 +20,6 @@ #pragma once #include -#include #include #include #include diff --git a/basctl/source/inc/accessibledialogwindow.hxx b/basctl/source/inc/accessibledialogwindow.hxx index af177b69b02f..1696d2e8afbd 100644 --- a/basctl/source/inc/accessibledialogwindow.hxx +++ b/basctl/source/inc/accessibledialogwindow.hxx @@ -20,7 +20,6 @@ #pragma once #include -#include #include #include #include @@ -40,8 +39,7 @@ class DlgEdObj; class AccessibleDialogWindow final : public cppu::ImplInheritanceHelper, + css::accessibility::XAccessibleSelection>, public SfxListener { private: @@ -94,11 +92,6 @@ public: // SfxListener virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; - // XServiceInfo - virtual OUString SAL_CALL getImplementationName() override; - virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) override; - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; - // XAccessibleContext virtual sal_Int64 SAL_CALL getAccessibleChildCount( ) override; virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int64 i ) override; diff --git a/basctl/source/inc/basidesh.hxx b/basctl/source/inc/basidesh.hxx index 427d0636d879..b9c302ecdb3e 100644 --- a/basctl/source/inc/basidesh.hxx +++ b/basctl/source/inc/basidesh.hxx @@ -184,7 +184,7 @@ public: virtual SfxPrinter* GetPrinter( bool bCreate = false ) override; virtual sal_uInt16 SetPrinter( SfxPrinter *pNewPrinter, SfxPrinterChangeFlags nDiffFlags = SFX_PRINTER_ALL ) override; virtual OUString GetSelectionText( bool bCompleteWords = false, bool bOnlyASample = false ) override; - virtual bool HasSelection( bool bText = true ) const override; + virtual bool HasSelection(bool bMustHaveText) const override; void GetState( SfxItemSet& ); void ExecuteGlobal( SfxRequest& rReq ); diff --git a/basctl/source/inc/bastype2.hxx b/basctl/source/inc/bastype2.hxx index 6d0b2d642887..221629bc2fce 100644 --- a/basctl/source/inc/bastype2.hxx +++ b/basctl/source/inc/bastype2.hxx @@ -26,7 +26,7 @@ #include "doceventnotifier.hxx" #include -#include +#include #include #include #include @@ -267,7 +267,7 @@ public: int get_height_rows(int nRows) const { return m_xControl->get_height_rows(nRows); } int get_iter_index_in_parent(const weld::TreeIter& rIter) const { return m_xControl->get_iter_index_in_parent(rIter); } void connect_editing(const Link& rStartLink, - const Link&, bool>& rEndLink) + const Link& rEndLink) { m_xControl->connect_editing(rStartLink, rEndLink); } diff --git a/basctl/source/inc/bastypes.hxx b/basctl/source/inc/bastypes.hxx index d709997cd237..ae24f8532fdd 100644 --- a/basctl/source/inc/bastypes.hxx +++ b/basctl/source/inc/bastypes.hxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -49,9 +48,6 @@ class Layout; constexpr auto LINE_SEP_CR = 0x0D; constexpr auto LINE_SEP = 0x0A; -// Implementation: baside2b.cxx -sal_Int32 searchEOL( std::u16string_view rStr, sal_Int32 fromIndex ); - // Meaning of bToBeKilled: // While being in a reschedule-loop, I may not destroy the window. // It must first break from the reschedule-loop to self-destroy then. @@ -287,12 +283,10 @@ private: Map m_aMap; }; -void CutLines( OUString& rStr, sal_Int32 nStartLine, sal_Int32 nLines ); OUString CreateMgrAndLibStr( std::u16string_view rMgrName, std::u16string_view rLibName ); sal_uInt32 CalcLineCount( SvStream& rStream ); bool QueryReplaceMacro( std::u16string_view rName, weld::Widget* pParent ); -bool QueryDelMacro( std::u16string_view rName, weld::Widget* pParent ); class ModuleInfoHelper { diff --git a/basctl/source/inc/docsignature.hxx b/basctl/source/inc/docsignature.hxx index ef68f31382c3..4a67b4d01012 100644 --- a/basctl/source/inc/docsignature.hxx +++ b/basctl/source/inc/docsignature.hxx @@ -19,7 +19,7 @@ #pragma once #include -#include +#include class SfxObjectShell; diff --git a/basctl/source/inc/idedataprovider.hxx b/basctl/source/inc/idedataprovider.hxx index fef8ae40b7db..5dad781f1ec2 100644 --- a/basctl/source/inc/idedataprovider.hxx +++ b/basctl/source/inc/idedataprovider.hxx @@ -44,7 +44,6 @@ public: virtual void Initialize() = 0; virtual bool IsInitialized() const = 0; - virtual void Reset() = 0; // Data Access Methods virtual SymbolInfoList GetTopLevelNodes() = 0; @@ -61,7 +60,6 @@ public: void Initialize() override; bool IsInitialized() const override { return m_bInitialized; } - void Reset() override; void AddDocumentNodesWithModules(); void RefreshDocumentNodes(); @@ -72,7 +70,6 @@ public: private: void performFullUnoScan(); - void addDocumentNodes(); // Core data std::unique_ptr m_pUnoHierarchy; diff --git a/basctl/source/inc/iderid.hxx b/basctl/source/inc/iderid.hxx index 83cbc3d0c4aa..c74d62624081 100644 --- a/basctl/source/inc/iderid.hxx +++ b/basctl/source/inc/iderid.hxx @@ -25,6 +25,7 @@ namespace basctl { OUString IDEResId(TranslateId aId); +OUString IDEResId(TranslateNId aContextSingularPlural, int nCardinality); } // namespace basctl diff --git a/basctl/source/inc/managelang.hxx b/basctl/source/inc/managelang.hxx index 24b9b2b6c190..e1ae5be316e7 100644 --- a/basctl/source/inc/managelang.hxx +++ b/basctl/source/inc/managelang.hxx @@ -20,9 +20,12 @@ #pragma once #include + +#include #include +#include #include -#include +#include class SvxLanguageBox; diff --git a/basctl/source/inc/objectbrowser.hxx b/basctl/source/inc/objectbrowser.hxx index b9cbabc84079..01f08c03e7b8 100644 --- a/basctl/source/inc/objectbrowser.hxx +++ b/basctl/source/inc/objectbrowser.hxx @@ -20,11 +20,12 @@ #include #include #include +#include #include #include +#include #include #include -#include #include #include diff --git a/basctl/source/inc/objectbrowsersearch.hxx b/basctl/source/inc/objectbrowsersearch.hxx index 0f3329ad2174..2d2e6f14f7df 100644 --- a/basctl/source/inc/objectbrowsersearch.hxx +++ b/basctl/source/inc/objectbrowsersearch.hxx @@ -10,6 +10,7 @@ #pragma once #include +#include #include namespace basctl @@ -26,7 +27,7 @@ public: private: // Event handlers for the UI widgets - DECL_STATIC_LINK(ObjectBrowserSearch, OnFilterChanged, weld::Entry&, void); + DECL_STATIC_LINK(ObjectBrowserSearch, OnFilterChanged, weld::TextWidget&, void); DECL_STATIC_LINK(ObjectBrowserSearch, OnClearSearchClicked, weld::Button&, void); DECL_STATIC_LINK(ObjectBrowserSearch, DebounceTimerHandler, Timer*, void); diff --git a/basctl/uiconfig/basicide/menubar/menubar.xml b/basctl/uiconfig/basicide/menubar/menubar.xml index 8221f4d9ba23..481526cd6b36 100644 --- a/basctl/uiconfig/basicide/menubar/menubar.xml +++ b/basctl/uiconfig/basicide/menubar/menubar.xml @@ -22,30 +22,30 @@ - - - - - + + + + + - + - - - + + + - - - - + + + + - + - + - + @@ -57,28 +57,28 @@ - - + + - - + + - - - + + + - - - - - - + + + + + + - + @@ -86,73 +86,73 @@ - - - + + + - - + + - + - + - - + + - + - - - - - - + + + + + + - - + + - - + + - - - - - + + + + + - + - - - + + + - - + + - - + + - - + + - - + + - - - - + + + + @@ -165,20 +165,19 @@ - + - - + - + - + diff --git a/basctl/uiconfig/basicide/statusbar/statusbar.xml b/basctl/uiconfig/basicide/statusbar/statusbar.xml index a5bde3ad0a17..8cdcdb7a3f28 100644 --- a/basctl/uiconfig/basicide/statusbar/statusbar.xml +++ b/basctl/uiconfig/basicide/statusbar/statusbar.xml @@ -18,8 +18,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . --> - + diff --git a/basctl/uiconfig/basicide/ui/defaultlanguage.ui b/basctl/uiconfig/basicide/ui/defaultlanguage.ui index 6403de84ab92..e0c3cbe7e3bb 100644 --- a/basctl/uiconfig/basicide/ui/defaultlanguage.ui +++ b/basctl/uiconfig/basicide/ui/defaultlanguage.ui @@ -194,11 +194,6 @@ 0 - - - - - 6 diff --git a/basctl/uiconfig/basicide/ui/importlibdialog.ui b/basctl/uiconfig/basicide/ui/importlibdialog.ui index 94e26e5f0676..21818ce3ad7b 100644 --- a/basctl/uiconfig/basicide/ui/importlibdialog.ui +++ b/basctl/uiconfig/basicide/ui/importlibdialog.ui @@ -1,5 +1,5 @@ - + @@ -17,31 +17,31 @@ - False - 6 + False + 6 Import Libraries False True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -54,8 +54,8 @@ _Cancel True - True - True + True + True True @@ -68,8 +68,8 @@ _Help True - True - True + True + True True @@ -83,40 +83,40 @@ False True - end + end 0 - + True - False + False True True - 12 + 12 True - False - 0 - none + False + 0 + none - + True - False - 6 + False 12 6 + 6 Insert as reference (read-only) True - True - False - True - True + True + False + True + True Adds the selected library as a read-only file. The library is reloaded each time you start the office suite. @@ -124,18 +124,18 @@ - 0 - 0 + 0 + 0 Replace existing libraries True - True - False - True - True + True + False + True + True Replaces a library that has the same name with the current library. @@ -143,8 +143,8 @@ - 0 - 1 + 0 + 1 @@ -152,7 +152,7 @@ True - False + False Options @@ -161,38 +161,38 @@ - 0 - 1 + 0 + 1 True - False + False True True - 0 - none + 0 + none True - True - True - True - in + True 12 6 + True + True + in True - True - True + True + True True True liststore1 - False - 0 - False + False + 0 + False @@ -208,12 +208,6 @@ 0 - - - - - True - 6 @@ -229,7 +223,7 @@ True - False + False @@ -237,8 +231,8 @@ - 0 - 0 + 0 + 0 @@ -255,9 +249,6 @@ cancel help - - - Enter a name or the path to the library that you want to append. You can also select a library from the list. diff --git a/basctl/uiconfig/basicide/ui/objectbrowser.ui b/basctl/uiconfig/basicide/ui/objectbrowser.ui index 4eef6d0a2016..155c528fad24 100644 --- a/basctl/uiconfig/basicide/ui/objectbrowser.ui +++ b/basctl/uiconfig/basicide/ui/objectbrowser.ui @@ -58,6 +58,7 @@ True True True + True Search objects and members... @@ -172,6 +173,7 @@ True Forward in Navigation History NextImage + True Go to the next entry in navigation history. diff --git a/basegfx/source/color/bcolortools.cxx b/basegfx/source/color/bcolortools.cxx index 160b48328966..70812a747bb8 100644 --- a/basegfx/source/color/bcolortools.cxx +++ b/basegfx/source/color/bcolortools.cxx @@ -190,6 +190,49 @@ namespace basegfx::utils } } + BColor interpolateInHSL(const BColor& rStartRGB, const BColor& rEndRGB, const double fFact, + const bool bInc) + { + // This function is primarily designed for use with Microsoft Office SmartArt diagrams. For + // compatibility reasons, no gamma correction is applied. + + if (fFact <= 0.0 || rStartRGB.equal(rEndRGB)) + return BColor(rStartRGB.getRed(), rStartRGB.getGreen(), rStartRGB.getBlue()); + if (fFact >= 1.0) + return BColor(rEndRGB.getRed(), rEndRGB.getGreen(), rEndRGB.getBlue()); + + // The hue is undefined for Gray, the rgb2hsl conversion sets it to 0 degrees. Thus Gray needs + // some special treatment in interpolating. + const bool bIsStartGray = rStartRGB.getRed() == rStartRGB.getGreen() + && rStartRGB.getGreen() == rStartRGB.getBlue(); + const bool bIsEndGray = rEndRGB.getRed() == rEndRGB.getGreen() + && rEndRGB.getGreen() == rEndRGB.getBlue(); + if (bIsStartGray && bIsEndGray) + return BColor(interpolate(rStartRGB, rEndRGB, fFact)); + + BColor aStartHSL(rgb2hsl(rStartRGB)); + BColor aEndHSL(rgb2hsl(rEndRGB)); + if (bIsStartGray) + aStartHSL[0] = aEndHSL[0]; + if (bIsEndGray) + aEndHSL[0] = aStartHSL[0]; + + double fInterpolatedSaturation = std::lerp(aStartHSL[1], aEndHSL[1], fFact); + double fInterpolatedLightness = std::lerp(aStartHSL[2], aEndHSL[2], fFact); + + double fInterpolatedHue = aStartHSL[0]; + double fColorSwing = aEndHSL[0] - aStartHSL[0]; + if (bInc && fColorSwing < 0) + fColorSwing += 360; + if (!bInc && fColorSwing > 0) + fColorSwing -= 360; + fInterpolatedHue += fFact * fColorSwing; + + // hsl2rgb handles out of range hue values. There is no need to take action here. + + return hsl2rgb(BColor(fInterpolatedHue, fInterpolatedSaturation, fInterpolatedLightness)); + } + } // end of namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basegfx/source/curve/b2dcubicbezier.cxx b/basegfx/source/curve/b2dcubicbezier.cxx index 39aeda7fbe40..fe7297d9ef38 100644 --- a/basegfx/source/curve/b2dcubicbezier.cxx +++ b/basegfx/source/curve/b2dcubicbezier.cxx @@ -191,7 +191,7 @@ namespace basegfx if(nMaxRecursionDepth) { - // divide at 0.5 ad test both edges for angle criteria + // divide at 0.5 and test both edges for angle criteria const B2DPoint aS1L(average(rfPA, rfEA)); const B2DPoint aS1C(average(rfEA, rfEB)); const B2DPoint aS1R(average(rfEB, rfPB)); @@ -378,7 +378,7 @@ namespace basegfx const B2DVector aEdge(maEndPoint - maStartPoint); // controls parallel to edge can be trivial. No edge -> not parallel -> control can - // still not be trivial (e.g. ballon loop) + // still not be trivial (e.g. balloon loop) if(aEdge.equalZero()) return; diff --git a/basegfx/source/matrix/b2dhommatrix.cxx b/basegfx/source/matrix/b2dhommatrix.cxx index 50cc340096ec..4b85161b566f 100644 --- a/basegfx/source/matrix/b2dhommatrix.cxx +++ b/basegfx/source/matrix/b2dhommatrix.cxx @@ -18,15 +18,12 @@ */ #include -#include #include #include #include namespace basegfx { - constexpr int RowSize = 3; - void B2DHomMatrix::set3x2(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2) { mfValues[0][0] = f_0x0; @@ -39,30 +36,22 @@ namespace basegfx bool B2DHomMatrix::isIdentity() const { - for(sal_uInt16 a(0); a < RowSize - 1; a++) - { - for(sal_uInt16 b(0); b < RowSize; b++) - { - const double fDefault(internal::implGetDefaultValue(a, b)); - const double fValueAB(get(a, b)); - - if(!::basegfx::fTools::equal(fDefault, fValueAB)) - { - return false; - } - } - } - - return true; + return fTools::equal(1.0, mfValues[0][0]) + && fTools::equal(0.0, mfValues[0][1]) + && fTools::equal(0.0, mfValues[0][2]) + && fTools::equal(0.0, mfValues[1][0]) + && fTools::equal(1.0, mfValues[1][1]) + && fTools::equal(0.0, mfValues[1][2]); } void B2DHomMatrix::identity() { - for(sal_uInt16 a(0); a < RowSize - 1; a++) - { - for(sal_uInt16 b(0); b < RowSize; b++) - mfValues[a][b] = internal::implGetDefaultValue(a, b); - } + mfValues[0][0] = 1.0; + mfValues[0][1] = 0.0; + mfValues[0][2] = 0.0; + mfValues[1][0] = 0.0; + mfValues[1][1] = 1.0; + mfValues[1][2] = 0.0; } bool B2DHomMatrix::isInvertible() const @@ -143,22 +132,19 @@ namespace basegfx void B2DHomMatrix::doMulMatrix(const B2DHomMatrix& rMat) { - // create a copy as source for the original values - const B2DHomMatrix aCopy(*this); + double r0 = mfValues[0][0]; + double r1 = mfValues[0][1]; + double r2 = mfValues[0][2]; + double r3 = mfValues[1][0]; + double r4 = mfValues[1][1]; + double r5 = mfValues[1][2]; - for(sal_uInt16 a(0); a < 2; ++a) - { - for(sal_uInt16 b(0); b < 3; ++b) - { - double fValue = 0.0; - - for(sal_uInt16 c(0); c < 2; ++c) - fValue += aCopy.mfValues[c][b] * rMat.mfValues[a][c]; - - mfValues[a][b] = fValue; - } - mfValues[a][2] += rMat.mfValues[a][2]; - } + mfValues[0][0] = rMat.mfValues[0][0] * r0 + rMat.mfValues[0][1] * r3; + mfValues[0][1] = rMat.mfValues[0][0] * r1 + rMat.mfValues[0][1] * r4; + mfValues[0][2] = rMat.mfValues[0][0] * r2 + rMat.mfValues[0][1] * r5 + rMat.mfValues[0][2]; + mfValues[1][0] = rMat.mfValues[1][0] * r0 + rMat.mfValues[1][1] * r3; + mfValues[1][1] = rMat.mfValues[1][0] * r1 + rMat.mfValues[1][1] * r4; + mfValues[1][2] = rMat.mfValues[1][0] * r2 + rMat.mfValues[1][1] * r5 + rMat.mfValues[1][2]; } bool B2DHomMatrix::operator==(const B2DHomMatrix& rMat) const @@ -190,26 +176,21 @@ namespace basegfx double fCos(1.0); utils::createSinCosOrthogonal(fSin, fCos, fRadiant); - B2DHomMatrix aRotMat; - aRotMat.set(0, 0, fCos); - aRotMat.set(1, 1, fCos); - aRotMat.set(1, 0, fSin); - aRotMat.set(0, 1, -fSin); - - doMulMatrix(aRotMat); + for(sal_uInt16 j = 0; j < 3; ++j) + { + double fValue = fCos * mfValues[0][j] - fSin * mfValues[1][j]; + mfValues[1][j] = fSin * mfValues[0][j] + fCos * mfValues[1][j]; + mfValues[0][j] = fValue; + } } void B2DHomMatrix::translate(double fX, double fY) { if(!fTools::equalZero(fX) || !fTools::equalZero(fY)) { - B2DHomMatrix aTransMat; - - aTransMat.set(0, 2, fX); - aTransMat.set(1, 2, fY); - - doMulMatrix(aTransMat); + mfValues[0][2] += fX; + mfValues[1][2] += fY; } } @@ -224,12 +205,12 @@ namespace basegfx if(!fTools::equal(fOne, fX) || !fTools::equal(fOne, fY)) { - B2DHomMatrix aScaleMat; - - aScaleMat.set(0, 0, fX); - aScaleMat.set(1, 1, fY); - - doMulMatrix(aScaleMat); + mfValues[0][0] *= fX; + mfValues[0][1] *= fX; + mfValues[0][2] *= fX; + mfValues[1][0] *= fY; + mfValues[1][1] *= fY; + mfValues[1][2] *= fY; } } @@ -243,11 +224,9 @@ namespace basegfx // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) if(!fTools::equalZero(fSx)) { - B2DHomMatrix aShearXMat; - - aShearXMat.set(0, 1, fSx); - - doMulMatrix(aShearXMat); + mfValues[0][0] += fSx * mfValues[1][0]; + mfValues[0][1] += fSx * mfValues[1][1]; + mfValues[0][2] += fSx * mfValues[1][2]; } } @@ -256,11 +235,9 @@ namespace basegfx // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) if(!fTools::equalZero(fSy)) { - B2DHomMatrix aShearYMat; - - aShearYMat.set(1, 0, fSy); - - doMulMatrix(aShearYMat); + mfValues[1][0] += fSy * mfValues[0][0]; + mfValues[1][1] += fSy * mfValues[0][1]; + mfValues[1][2] += fSy * mfValues[0][2]; } } diff --git a/basegfx/source/numeric/ftools.cxx b/basegfx/source/numeric/ftools.cxx index d603d4e6df45..8e83989847e9 100644 --- a/basegfx/source/numeric/ftools.cxx +++ b/basegfx/source/numeric/ftools.cxx @@ -71,32 +71,6 @@ namespace basegfx } } - double snapToRange(double v, double fLow, double fHigh) - { - if(fTools::equal(fLow, fHigh)) - { - // with no range all snaps to range bound - return 0.0; - } - else - { - if(fLow > fHigh) - { - // correct range order. Evtl. assert this (?) - std::swap(fLow, fHigh); - } - - if(v < fLow || v > fHigh) - { - return snapToZeroRange(v - fLow, fHigh - fLow) + fLow; - } - else - { - return v; - } - } - } - double normalizeToRange(double v, const double fRange) { if(fRange <= 0.0) diff --git a/basegfx/source/polygon/b2dlinegeometry.cxx b/basegfx/source/polygon/b2dlinegeometry.cxx index 83ed8a5dfb9e..2f1d66a642b1 100644 --- a/basegfx/source/polygon/b2dlinegeometry.cxx +++ b/basegfx/source/polygon/b2dlinegeometry.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include +#include #include #include #include @@ -89,7 +91,66 @@ namespace basegfx::utils aArrowTransform.translate(0.0, -fArrowYLength * fDockingPosition + fShift); // get the polygon vector we want to plant this arrow on - const double fConsumedLength(fArrowYLength * (1.0 - fDockingPosition) - fShift); + double fConsumedLength(fArrowYLength * (1.0 - fDockingPosition) - fShift); + + // Detect arrow polygons with a concave back (e.g., notched arrowheads): + // the polygon's centerline along X=fCenterX may exit the polygon interior + // before reaching the polygon's full Y extent. In that case, shorten the + // consumed line length so the line stroke meets the polygon at the centerline + // rather than ending in a V-cut behind the notch. + { + B2DPolyPolygon aTransformed(rArrow); + aTransformed.transform(aArrowTransform); + const double fCenterX(0.0); + std::vector aYCrossings; + for (sal_uInt32 nP = 0; nP < aTransformed.count(); ++nP) + { + const B2DPolygon& aSub(aTransformed.getB2DPolygon(nP)); + const sal_uInt32 nN(aSub.count()); + if (nN < 2) + continue; + for (sal_uInt32 i = 0; i < nN; ++i) + { + const B2DPoint aP1(aSub.getB2DPoint(i)); + const B2DPoint aP2(aSub.getB2DPoint((i + 1) % nN)); + const double x1(aP1.getX() - fCenterX); + const double x2(aP2.getX() - fCenterX); + if ((x1 < 0.0 && x2 > 0.0) || (x1 > 0.0 && x2 < 0.0)) + { + const double t(-x1 / (x2 - x1)); + aYCrossings.push_back(aP1.getY() + + t * (aP2.getY() - aP1.getY())); + } + else if (x1 == 0.0 && x2 != 0.0) + { + const B2DPoint aPrev(aSub.getB2DPoint((i + nN - 1) % nN)); + const double xPrev(aPrev.getX() - fCenterX); + if ((xPrev < 0.0 && x2 > 0.0) || (xPrev > 0.0 && x2 < 0.0)) + aYCrossings.push_back(aP1.getY()); + } + } + } + std::sort(aYCrossings.begin(), aYCrossings.end()); + constexpr double EPS(1e-9); + sal_uInt32 nBelow(0); + for (double y : aYCrossings) + if (y < EPS) + ++nBelow; + if (nBelow % 2 != 0) + { + for (double y : aYCrossings) + { + if (y > EPS) + { + const double fAdjusted(y - fShift); + if (fAdjusted < fConsumedLength) + fConsumedLength = fAdjusted; + break; + } + } + } + } + const B2DVector aHead(rCandidate.getB2DPoint(bStart ? 0 : rCandidate.count() - 1)); const B2DVector aTail(getPositionAbsolute(rCandidate, bStart ? fConsumedLength : fCandidateLength - fConsumedLength, fCandidateLength)); diff --git a/basegfx/source/polygon/b2dpolygon.cxx b/basegfx/source/polygon/b2dpolygon.cxx index c7a334a85776..015cdf69d76f 100644 --- a/basegfx/source/polygon/b2dpolygon.cxx +++ b/basegfx/source/polygon/b2dpolygon.cxx @@ -154,12 +154,12 @@ public: sal_uInt32 nIndex(0); // test as long as there are at least two points and as long as the index - // is smaller or equal second last point + // is smaller than or equal second last point while((maVector.size() > 1) && (nIndex <= maVector.size() - 2)) { if(maVector[nIndex] == maVector[nIndex + 1]) { - // if next is same as index, delete next + // if next is the same as index, delete next maVector.erase(maVector.begin() + (nIndex + 1)); } else @@ -172,9 +172,19 @@ public: void transform(const basegfx::B2DHomMatrix& rMatrix) { + const double m00 = rMatrix.get(0, 0); + const double m01 = rMatrix.get(0, 1); + const double m02 = rMatrix.get(0, 2); + const double m10 = rMatrix.get(1, 0); + const double m11 = rMatrix.get(1, 1); + const double m12 = rMatrix.get(1, 2); + for (auto& point : maVector) { - point *= rMatrix; + const double x = point.getX(); + const double y = point.getY(); + point.setX(m00 * x + m01 * y + m02); + point.setY(m10 * x + m11 * y + m12); } } @@ -452,7 +462,7 @@ public: if(aStart == aEnd) { - // swap Prev and Next at middle element (if exists) + // swap Prev and Next at middle element (if it exists) aStart->flip(); } @@ -528,17 +538,17 @@ public: // inside the current range without control points. Expand current range by // subdividing the bezier segment. // Ideal here is a subdivision at the extreme values, so use - // getAllExtremumPositions to get all extremas in one run - std::vector< double > aExtremas; + // getAllExtremumPositions to get all extrema in one run + std::vector< double > aExtrema; - aExtremas.reserve(4); - aEdge.getAllExtremumPositions(aExtremas); + aExtrema.reserve(4); + aEdge.getAllExtremumPositions(aExtrema); - const sal_uInt32 nExtremaCount(aExtremas.size()); + const sal_uInt32 nExtremaCount(aExtrema.size()); for(sal_uInt32 c(0); c < nExtremaCount; c++) { - aNewRange.expand(aEdge.interpolatePoint(aExtremas[c])); + aNewRange.expand(aEdge.interpolatePoint(aExtrema[c])); } } } @@ -562,11 +572,11 @@ public: class ImplB2DPolygon { private: - // The point vector. This vector exists always and defines the + // The point vector. This vector always exists and defines the // count of members. CoordinateDataArray2D maPoints; - // The control point vectors. This vectors are created on demand + // The control point vectors. These vectors are created on demand // and may be zero. std::optional< ControlVectorArray2D > moControlVector; @@ -575,7 +585,7 @@ private: // but add buffered data that is valid for all referencing instances mutable std::unique_ptr mpBufferedData; - // flag which decides if this polygon is opened or closed + // flag which decides if this polygon is open or closed bool mbIsClosed; public: @@ -626,7 +636,7 @@ public: : maPoints(rToBeCopied.maPoints, nIndex, nCount), mbIsClosed(rToBeCopied.mbIsClosed) { - // complete initialization using partly copy + // complete initialization using partial copy if(rToBeCopied.moControlVector && rToBeCopied.moControlVector->isUsed()) { moControlVector.emplace( *rToBeCopied.moControlVector, nIndex, nCount ); @@ -918,7 +928,7 @@ public: { if(mbIsClosed) { - // check for same start and end point + // check for identical start and end points const sal_uInt32 nIndex(maPoints.count() - 1); if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex)) @@ -1066,6 +1076,13 @@ public: if(moControlVector) { + const double m00 = rMatrix.get(0, 0); + const double m01 = rMatrix.get(0, 1); + const double m02 = rMatrix.get(0, 2); + const double m10 = rMatrix.get(1, 0); + const double m11 = rMatrix.get(1, 1); + const double m12 = rMatrix.get(1, 2); + for(sal_uInt32 a(0); a < maPoints.count(); a++) { basegfx::B2DPoint aCandidate = maPoints.getCoordinate(a); @@ -1077,19 +1094,22 @@ public: if(!rPrevVector.equalZero()) { - basegfx::B2DVector aPrevVector(rMatrix * rPrevVector); - moControlVector->setPrevVector(a, aPrevVector); + const double x = rPrevVector.getX(); + const double y = rPrevVector.getY(); + moControlVector->setPrevVector(a, basegfx::B2DVector(m00 * x + m01 * y, m10 * x + m11 * y)); } if(!rNextVector.equalZero()) { - basegfx::B2DVector aNextVector(rMatrix * rNextVector); - moControlVector->setNextVector(a, aNextVector); + const double x = rNextVector.getX(); + const double y = rNextVector.getY(); + moControlVector->setNextVector(a, basegfx::B2DVector(m00 * x + m01 * y, m10 * x + m11 * y)); } } - aCandidate *= rMatrix; - maPoints.setCoordinate(a, aCandidate); + const double x = aCandidate.getX(); + const double y = aCandidate.getY(); + maPoints.setCoordinate(a, basegfx::B2DPoint(m00 * x + m01 * y + m02, m10 * x + m11 * y + m12)); } if(!moControlVector->isUsed()) @@ -1524,7 +1544,7 @@ namespace basegfx mpPolygon->addOrReplaceSystemDependentData(rData); } - SystemDependentData_SharedPtr B2DPolygon::getSystemDependantDataInternal(SDD_Type aType) const + SystemDependentData_SharedPtr B2DPolygon::getSystemDependentDataInternal(SDD_Type aType) const { return mpPolygon->getSystemDependentData(aType); } diff --git a/basegfx/source/polygon/b2dpolypolygon.cxx b/basegfx/source/polygon/b2dpolypolygon.cxx index 35a801684a86..f7614f7a0f78 100644 --- a/basegfx/source/polygon/b2dpolypolygon.cxx +++ b/basegfx/source/polygon/b2dpolypolygon.cxx @@ -353,7 +353,7 @@ public: bool B2DPolyPolygon::isClosed() const { - // PolyPOlygon is closed when all contained Polygons are closed or + // PolyPolygon is closed when all contained Polygons are closed or // no Polygon exists. for(sal_uInt32 a(0); a < count(); a++) { @@ -436,7 +436,7 @@ public: mpPolyPolygon->addOrReplaceSystemDependentData(rData); } - SystemDependentData_SharedPtr B2DPolyPolygon::getSystemDependantDataInternal(SDD_Type aType) const + SystemDependentData_SharedPtr B2DPolyPolygon::getSystemDependentDataInternal(SDD_Type aType) const { return mpPolyPolygon->getSystemDependentData(aType); } diff --git a/basegfx/source/range/b2drange.cxx b/basegfx/source/range/b2drange.cxx index d43c6d6e12ec..da2bec524f68 100644 --- a/basegfx/source/range/b2drange.cxx +++ b/basegfx/source/range/b2drange.cxx @@ -37,15 +37,54 @@ namespace basegfx void B2DRange::transform(const B2DHomMatrix& rMatrix) { - if(!isEmpty() && !rMatrix.isIdentity()) + if(isEmpty() || rMatrix.isIdentity()) + return; + + // Compute the AABB of the transformed box directly from matrix + // coefficients, instead of transforming all four corners and + // expanding. For an affine transform the extremes of each output + // coordinate are reached at corners chosen per coefficient: a + // non-negative coefficient pairs the input min with the output min, + // a negative coefficient pairs the input max with the output min. + // Translation is the same constant offset for min and max, so it + // is folded into the initial value below. + // (Arvo, Graphics Gems I, 1990.) + + const double oldMinX = getMinX(); + const double oldMaxX = getMaxX(); + const double oldMinY = getMinY(); + const double oldMaxY = getMaxY(); + + const double m00 = rMatrix.get(0, 0); + const double m01 = rMatrix.get(0, 1); + const double m10 = rMatrix.get(1, 0); + const double m11 = rMatrix.get(1, 1); + + double newMinX = rMatrix.get(0, 2); + double newMaxX = newMinX; + double newMinY = rMatrix.get(1, 2); + double newMaxY = newMinY; + + auto axis = [](const double matrixValue, const double inLow, const double inHigh, double& outLow, double& outHigh) { - const B2DRange aSource(*this); - reset(); - expand(rMatrix * B2DPoint(aSource.getMinX(), aSource.getMinY())); - expand(rMatrix * B2DPoint(aSource.getMaxX(), aSource.getMinY())); - expand(rMatrix * B2DPoint(aSource.getMinX(), aSource.getMaxY())); - expand(rMatrix * B2DPoint(aSource.getMaxX(), aSource.getMaxY())); - } + if (matrixValue >= 0.0) + { + outLow += matrixValue * inLow; + outHigh += matrixValue * inHigh; + } + else + { + outLow += matrixValue * inHigh; + outHigh += matrixValue * inLow; + } + }; + + axis(m00, oldMinX, oldMaxX, newMinX, newMaxX); + axis(m01, oldMinY, oldMaxY, newMinX, newMaxX); + axis(m10, oldMinX, oldMaxX, newMinY, newMaxY); + axis(m11, oldMinY, oldMaxY, newMinY, newMaxY); + + *this = B2DRange(newMinX, newMinY, newMaxX, newMaxY); } void B2DRange::translate(double fTranslateX, double fTranslateY) diff --git a/basegfx/source/range/b3drange.cxx b/basegfx/source/range/b3drange.cxx index 89bb98a1e1a5..dd984cf78456 100644 --- a/basegfx/source/range/b3drange.cxx +++ b/basegfx/source/range/b3drange.cxx @@ -45,13 +45,6 @@ namespace basegfx return *this; } - const B3DRange& B3DRange::getUnitB3DRange() - { - static const B3DRange aUnitB3DRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0); - - return aUnitB3DRange; - } - B3DRange operator*( const ::basegfx::B3DHomMatrix& rMat, const B3DRange& rB3DRange ) { B3DRange aRes( rB3DRange ); diff --git a/basegfx/source/raster/rasterconvert3d.cxx b/basegfx/source/raster/rasterconvert3d.cxx index 17af9c4cddb5..58172bda33fc 100644 --- a/basegfx/source/raster/rasterconvert3d.cxx +++ b/basegfx/source/raster/rasterconvert3d.cxx @@ -110,7 +110,7 @@ namespace basegfx // sort current scanline using comparator. Only X is used there // since all entries are already in one processed line. This needs to be done - // every time since not only new spans may have benn added or old removed, + // every time since not only new spans may have been added or old removed, // but incrementing may also have changed the order std::sort(aCurrentLine.begin(), aCurrentLine.end(), lineComparator()); diff --git a/basegfx/source/tools/gradienttools.cxx b/basegfx/source/tools/gradienttools.cxx index d3383953cbe3..85b1ade668a4 100644 --- a/basegfx/source/tools/gradienttools.cxx +++ b/basegfx/source/tools/gradienttools.cxx @@ -111,7 +111,12 @@ namespace basegfx aTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); // prepare aspect for texture - const double fAspectRatio(fTools::equalZero(fTargetSizeY) ? 1.0 : fTargetSizeX / fTargetSizeY); + double fAspectRatio(1.0); + if(!fTools::equalZero(fTargetSizeY)) + { + assert(fTargetSizeY != 0.0 && "help coverity see it's not zero"); + fAspectRatio = fTargetSizeX / fTargetSizeY; + } return ODFGradientInfo(aTextureTransform, fAspectRatio, nSteps); } diff --git a/basegfx/source/tools/systemdependentdata.cxx b/basegfx/source/tools/systemdependentdata.cxx index c32be27ac945..a2f66c06332c 100644 --- a/basegfx/source/tools/systemdependentdata.cxx +++ b/basegfx/source/tools/systemdependentdata.cxx @@ -43,53 +43,48 @@ namespace basegfx return 0; #endif - if(0 == mnCalculatedCycles) - { - const sal_Int64 nBytes(estimateUsageInBytes()); + // already set, use it + if(0 != mnCalculatedCycles) + return mnCalculatedCycles; - // tdf#129845 as indicator for no need to buffer trivial data, stay at and - // return zero. As border, use 450 bytes. For polygons, this means to buffer - // starting with ca. 50 points (GDIPLUS uses 9 bytes per coordinate). For - // Bitmap data this means to more or less always buffer (as it was before). - // For the future, a more sophisticated differentiation may be added - if(nBytes > 450) - { - // HoldCyclesInSeconds - const sal_uInt32 nSeconds = 60; + // get size in bytes as base for estimation + const sal_Int64 nBytes(estimateUsageInBytes()); - // default is Seconds (minimal is one) - sal_uInt32 nResult(0 == nSeconds ? 1 : nSeconds); + // tdf#129845 as indicator for no need to buffer trivial data, stay at and + // return zero. As border, use 450 bytes. For polygons, this means to buffer + // starting with ca. 50 points (GDIPLUS uses 9 bytes per coordinate). For + // Bitmap data this means to more or less always buffer (as it was before). + // Note that this is the method for all Buffered data, independent of + // graphic target, so it is possible to refine that if needed in the + // system-dependent parts of impl (see getOrCreateCairoSurfaceHelper). It + // is also possible to make calculateCombinedHoldCyclesInSeconds virtual + // and override for your needs. + if (nBytes < 450) + return mnCalculatedCycles; - if(0 != nBytes) - { - // use sqrt to get some curved shape. With a default of 60s we get - // a single second at 3600 byte. To get close to 10mb, multiply by - // a corresponding scaling factor - const double fScaleToMB(3600.0 / (1024.0 * 1024.0 * 10.0)); + // We have seen that for very huge images the hold time was too short, e.g. + // for a very huge bitmap (see fHugeDataInBytes below) it was about 20s. This + // is not enough, we have learned that we need to hold huge data longer. + // In the impl before I took the memory aspect more into account, so I used + // sqrt() to have less HoldTime the bigger the nBytes gets by using a flattening + // curve. With having identified that remain time is important for those cases, + // we can go back to linear. This means that we can explicitly choose a + // HoldTime, get a factor and simply apply that to all buffered data. + // Setup: + // fHugeDataInBytes -> 300000000 + // fHugeTimeToHoldInSeconds -> 1200 + // fTimeToHoldInSecondsPerByte -> 0.000004 + // Example outcome (for implied raw BitmapData): + // 320x200 -> 1.024s + // 800x600 -> 7.68s + // 1600x1200 -> 30.72s + // 15000x5000 -> 1200s (as targeted) + constexpr double fHugeDataInBytes(15000*5000*4); + constexpr double fHugeTimeToHoldInSeconds(20 * 60); + constexpr double fTimeToHoldInSecondsPerByte(fHugeTimeToHoldInSeconds/fHugeDataInBytes); - // also use a multiplier to move the start point higher - const double fMultiplierSeconds(10.0); - - // calculate - nResult = static_cast((fMultiplierSeconds * nSeconds) / sqrt(nBytes * fScaleToMB)); - - // minimal value is 1 - if(nResult < 1) - { - nResult = 1; - } - - // maximal value is nSeconds - if(nResult > nSeconds) - { - nResult = nSeconds; - } - } - - // set locally (once, on-demand created, non-zero) - const_cast(this)->mnCalculatedCycles = nResult; - } - } + // set locally (once, on-demand created, non-zero) + mnCalculatedCycles = static_cast(1.0 + nBytes * fTimeToHoldInSecondsPerByte); return mnCalculatedCycles; } diff --git a/basegfx/test/B2DHomMatrixTest.cxx b/basegfx/test/B2DHomMatrixTest.cxx index aace816d3e3a..51bca7dcf61c 100644 --- a/basegfx/test/B2DHomMatrixTest.cxx +++ b/basegfx/test/B2DHomMatrixTest.cxx @@ -219,7 +219,7 @@ public: B2DHomMatrix mat; mat.shearX(3.0); mat.shearY(7.0); - CPPUNIT_ASSERT_EQUAL_MESSAGE("translate", maShear, mat); + CPPUNIT_ASSERT_EQUAL_MESSAGE("shear", maShear, mat); } void multiply() @@ -481,7 +481,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b2dhommatrix); CPPUNIT_TEST(equal); diff --git a/basegfx/test/B2DPolyPolygonTest.cxx b/basegfx/test/B2DPolyPolygonTest.cxx index 5319e6b46967..50fd4caff815 100644 --- a/basegfx/test/B2DPolyPolygonTest.cxx +++ b/basegfx/test/B2DPolyPolygonTest.cxx @@ -74,7 +74,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b2dpolypolygon); CPPUNIT_TEST(testTrapezoidHelper); diff --git a/basegfx/test/B2DPolyRangeTest.cxx b/basegfx/test/B2DPolyRangeTest.cxx index 174a56a898d1..b3cab06613bf 100644 --- a/basegfx/test/B2DPolyRangeTest.cxx +++ b/basegfx/test/B2DPolyRangeTest.cxx @@ -53,7 +53,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b2dpolyrange); CPPUNIT_TEST(check); diff --git a/basegfx/test/B2DPolygonTest.cxx b/basegfx/test/B2DPolygonTest.cxx index eadbdca93699..db9b5812edcf 100644 --- a/basegfx/test/B2DPolygonTest.cxx +++ b/basegfx/test/B2DPolygonTest.cxx @@ -97,7 +97,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b2dpolygon); CPPUNIT_TEST(testCubicBezier); diff --git a/basegfx/test/B2DPolygonToolsTest.cxx b/basegfx/test/B2DPolygonToolsTest.cxx index 19a4ee99be5c..92bd50c46b71 100644 --- a/basegfx/test/B2DPolygonToolsTest.cxx +++ b/basegfx/test/B2DPolygonToolsTest.cxx @@ -21,8 +21,11 @@ #include #include +#include #include #include +#include +#include namespace basegfx { @@ -69,12 +72,58 @@ public: !utils::isRectangle(aNonRect5)); } + // tdf#143031 EMF+ notched arrow caps left a visible gap between the line + // shaft and the cap because the line was shortened by the cap polygon's + // full Y extent (out to the back wings) even though the centerline exits + // the polygon at the notch. createAreaGeometryForLineStartEnd should now + // detect that and shorten the line only to the notch depth. + void testCreateAreaGeometryForLineStartEndNotchedArrow() + { + // Notched arrow: tip at (0,0), back wings at (+/-1.5, 3), notch at (0, 2). + B2DPolygon aArrow{ { 0, 2 }, { -1.5, 3 }, { 0, 0 }, { 1.5, 3 } }; + aArrow.setClosed(true); + B2DPolyPolygon aArrowPP(aArrow); + + // A horizontal line of length 1000. + B2DPolygon aLine{ { 0, 0 }, { 1000, 0 } }; + + const double fWidth = 300.0; + double fConsumed = 0.0; + utils::createAreaGeometryForLineStartEnd(aLine, aArrowPP, false /* end */, fWidth, + 1000.0 /* fCandidateLength */, + 0.0 /* fDockingPosition */, &fConsumed); + + // fArrowYLength == fWidth == 300; notch is at Y=2 of 3, so consumed + // length should be 200, not 300. + CPPUNIT_ASSERT_DOUBLES_EQUAL(200.0, fConsumed, 0.001); + } + + // Backward-compatibility check: a simple triangle (no concave back) should + // still consume the full polygon Y length, as before. + void testCreateAreaGeometryForLineStartEndSimpleTriangle() + { + B2DPolygon aArrow{ { 0, 0 }, { -1.5, 3 }, { 1.5, 3 } }; + aArrow.setClosed(true); + B2DPolyPolygon aArrowPP(aArrow); + + B2DPolygon aLine{ { 0, 0 }, { 1000, 0 } }; + + const double fWidth = 300.0; + double fConsumed = 0.0; + utils::createAreaGeometryForLineStartEnd(aLine, aArrowPP, false, fWidth, 1000.0, 0.0, + &fConsumed); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(300.0, fConsumed, 0.001); + } + // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b2dpolygontools); CPPUNIT_TEST(testIsRectangle); + CPPUNIT_TEST(testCreateAreaGeometryForLineStartEndNotchedArrow); + CPPUNIT_TEST(testCreateAreaGeometryForLineStartEndSimpleTriangle); CPPUNIT_TEST_SUITE_END(); }; // class b2dpolygontools diff --git a/basegfx/test/B2IBoxTest.cxx b/basegfx/test/B2IBoxTest.cxx index f236308aeafd..285830477419 100644 --- a/basegfx/test/B2IBoxTest.cxx +++ b/basegfx/test/B2IBoxTest.cxx @@ -49,7 +49,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b2ibox); CPPUNIT_TEST(TestBox); CPPUNIT_TEST_SUITE_END(); diff --git a/basegfx/test/B2XRangeTest.cxx b/basegfx/test/B2XRangeTest.cxx index 0a7c9930e782..7530feb996ca 100644 --- a/basegfx/test/B2XRangeTest.cxx +++ b/basegfx/test/B2XRangeTest.cxx @@ -55,7 +55,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b2Xrange); CPPUNIT_TEST(check); diff --git a/basegfx/test/BColorTest.cxx b/basegfx/test/BColorTest.cxx index 647078f338da..fc3ee124d3a3 100644 --- a/basegfx/test/BColorTest.cxx +++ b/basegfx/test/BColorTest.cxx @@ -137,9 +137,35 @@ public: utils::rgb2hsv(BColor(.5, .25, .25))); } + void interpolateInHSL_Test() + { + // arc with increasing angles + CPPUNIT_ASSERT_EQUAL_MESSAGE("red to green, inc", maYellow, + utils::interpolateInHSL(maRed, maGreen, 0.5, true)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("red to cyan, inc", maYellow, + utils::interpolateInHSL(maRed, maCyan, 1.0 / 3.0, true)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("magenta to cyan, inc via red", maGreen, + utils::interpolateInHSL(maMagenta, maCyan, 0.75, true)); + + // arc with decreasing angles + CPPUNIT_ASSERT_EQUAL_MESSAGE("red to green, dec", maCyan, + utils::interpolateInHSL(maRed, maGreen, 0.75, false)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("magenta to green, dec", maCyan, + utils::interpolateInHSL(maMagenta, maGreen, 2.0 / 3.0, false)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("yellow to cyan, dec via red", maMagenta, + utils::interpolateInHSL(maYellow, maCyan, 0.5, false)); + + // interpolate with Gray + CPPUNIT_ASSERT_EQUAL_MESSAGE("white to blue, inc", BColor(27.0 / 32, 27.0 / 32, 29.0 / 32), + utils::interpolateInHSL(maWhite, maBlue, 0.25, true)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("yellow to black, dec", BColor(0.375, 0.375, 0.125), + utils::interpolateInHSL(maYellow, maBlack, 0.5, true)); + } + CPPUNIT_TEST_SUITE(bcolor); CPPUNIT_TEST(hslTest); CPPUNIT_TEST(hsvTest); + CPPUNIT_TEST(interpolateInHSL_Test); CPPUNIT_TEST_SUITE_END(); }; diff --git a/basegfx/test/SvgPathImportExport.cxx b/basegfx/test/SvgPathImportExport.cxx index b51da1b0dcfb..08d666252e7c 100644 --- a/basegfx/test/SvgPathImportExport.cxx +++ b/basegfx/test/SvgPathImportExport.cxx @@ -136,7 +136,7 @@ public: // which gets exported now correctly as 'l' and also a point (#4, index 3) // with C2 continuity which produces a 's' statement now. - // The old SVGexport identified nun-used ControlVectors erroneously as Bezier segments + // The old SVGexport identified non-used ControlVectors erroneously as Bezier segments // because the 2nd vector at the start point was used, even when added // with start point was identical to end point. Exactly for that reason // i reworked the B2DPolygon to use prev, next control points. @@ -227,7 +227,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(SvgPathImportExport); CPPUNIT_TEST(testImportExport); diff --git a/basegfx/test/basegfx3d.cxx b/basegfx/test/basegfx3d.cxx index b03560d6588e..d9346a55e85a 100644 --- a/basegfx/test/basegfx3d.cxx +++ b/basegfx/test/basegfx3d.cxx @@ -34,7 +34,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b3dhommatrix); CPPUNIT_TEST(EmptyMethod); @@ -53,7 +53,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b3dpoint); CPPUNIT_TEST(EmptyMethod); @@ -68,7 +68,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b3drange); CPPUNIT_TEST(EmptyMethod); @@ -87,7 +87,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b3dtuple); CPPUNIT_TEST(EmptyMethod); @@ -102,7 +102,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(b3dvector); CPPUNIT_TEST(EmptyMethod); @@ -116,8 +116,8 @@ CPPUNIT_TEST_SUITE_REGISTRATION(basegfx3d::b3dtuple); CPPUNIT_TEST_SUITE_REGISTRATION(basegfx3d::b3dvector); } // namespace basegfx3d -// this macro creates an empty function, which will called by the RegisterAllFunctions() -// to let the user the possibility to also register some functions by hand. +// this macro creates an empty function, which will be called by the RegisterAllFunctions() +// to give the user the possibility to also register some functions by hand. // NOADDITIONAL; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basegfx/test/basegfxtools.cxx b/basegfx/test/basegfxtools.cxx index 9c6075919333..5602840b4af4 100644 --- a/basegfx/test/basegfxtools.cxx +++ b/basegfx/test/basegfxtools.cxx @@ -66,17 +66,17 @@ public: CPPUNIT_ASSERT_MESSAGE("0.51", fTools::equal(fAlpha, 0.025)); std::tie(nIndex, fAlpha) = maKeyStops.lerp(0.9); - CPPUNIT_ASSERT_EQUAL_MESSAGE("0.51", std::ptrdiff_t(1), nIndex); - CPPUNIT_ASSERT_MESSAGE("0.51", fTools::equal(fAlpha, 1.0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("0.9", std::ptrdiff_t(1), nIndex); + CPPUNIT_ASSERT_MESSAGE("0.9", fTools::equal(fAlpha, 1.0)); std::tie(nIndex, fAlpha) = maKeyStops.lerp(1.0); - CPPUNIT_ASSERT_EQUAL_MESSAGE("0.51", std::ptrdiff_t(1), nIndex); - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("0.51", 1.0, fAlpha, 1E-12); + CPPUNIT_ASSERT_EQUAL_MESSAGE("1.0", std::ptrdiff_t(1), nIndex); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("1.0", 1.0, fAlpha, 1E-12); } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(KeyStopLerpTest); CPPUNIT_TEST(test); diff --git a/basegfx/test/boxclipper.cxx b/basegfx/test/boxclipper.cxx index 35ae0c886e80..a6b7b255bdd1 100644 --- a/basegfx/test/boxclipper.cxx +++ b/basegfx/test/boxclipper.cxx @@ -382,7 +382,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(boxclipper); CPPUNIT_TEST(validatePoly); diff --git a/basegfx/test/genericclipper.cxx b/basegfx/test/genericclipper.cxx index af88a66ba342..e1fc80316b5a 100644 --- a/basegfx/test/genericclipper.cxx +++ b/basegfx/test/genericclipper.cxx @@ -171,7 +171,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(genericclipper); CPPUNIT_TEST(validateOr); diff --git a/basic/CppunitTest_basic_util.mk b/basic/CppunitTest_basic_util.mk new file mode 100644 index 000000000000..880030be5ab1 --- /dev/null +++ b/basic/CppunitTest_basic_util.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,basic_util)) + +$(eval $(call gb_CppunitTest_add_exception_objects,basic_util, \ + basic/qa/cppunit/test_util \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,basic_util, \ + sb \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/basic/Library_sb.mk b/basic/Library_sb.mk index aa1de14b01f8..7dd6fbecf58f 100644 --- a/basic/Library_sb.mk +++ b/basic/Library_sb.mk @@ -100,6 +100,7 @@ $(eval $(call gb_Library_add_exception_objects,sb,\ basic/source/runtime/stdobj \ basic/source/runtime/stdobj1 \ basic/source/classes/errobject \ + basic/source/util/sbutil \ )) endif diff --git a/basic/Module_basic.mk b/basic/Module_basic.mk index a01c883268bc..2a73d270c55f 100644 --- a/basic/Module_basic.mk +++ b/basic/Module_basic.mk @@ -18,6 +18,7 @@ $(eval $(call gb_Module_add_l10n_targets,basic,\ $(eval $(call gb_Module_add_check_targets,basic,\ CppunitTest_basic_scanner \ CppunitTest_basic_macros \ + CppunitTest_basic_util \ )) endif diff --git a/basic/inc/pch/precompiled_sb.hxx b/basic/inc/pch/precompiled_sb.hxx index 940acd01f2e0..a352d36c3934 100644 --- a/basic/inc/pch/precompiled_sb.hxx +++ b/basic/inc/pch/precompiled_sb.hxx @@ -57,7 +57,6 @@ #include #include #include -#include #include #endif // PCH_LEVEL >= 2 #if PCH_LEVEL >= 3 diff --git a/basic/qa/basic_coverage/test_ismissing_basic.bas b/basic/qa/basic_coverage/test_ismissing_basic.bas index 0996da0f82a4..ee515c6c8540 100644 --- a/basic/qa/basic_coverage/test_ismissing_basic.bas +++ b/basic/qa/basic_coverage/test_ismissing_basic.bas @@ -109,6 +109,15 @@ Sub verify_testIsMissingBasic() TestUtil.AssertEqual(TestOptArrayByRefByVal(, aB), IsMissingA, "TestOptArrayByRefByVal(, B)") TestUtil.AssertEqual(TestOptArrayByRefByVal(aA, aB), IsMissingNone, "TestOptArrayByRefByVal(A, B)") + ' tdf#143706 - optionals with named arguments (:= syntax) + ' Without the fix in place, this test would have failed with: + ' - Expected: 0 (IsMissingA) + ' - Actual : -1 (IsMissingNone) + TestUtil.AssertEqual(TestOptVariant(B := 456), IsMissingA, "TestOptVariant(B := 456)") + TestUtil.AssertEqual(TestOptVariant(A := 123), IsMissingB, "TestOptVariant(A := 123)") + TestUtil.AssertEqual(TestOptVariant(A := 123, B := 456), IsMissingNone, "TestOptVariant(A := 123, B := 456)") + TestUtil.AssertEqual(TestOptVariant(B := 456, A := 123), IsMissingNone, "TestOptVariant(B := 456, A := 123)") + Exit Sub errorHandler: TestUtil.ReportErrorHandler("verify_testIsMissingBasic", Err, Error$, Erl) diff --git a/basic/qa/basic_coverage/test_ismissing_compatible.bas b/basic/qa/basic_coverage/test_ismissing_compatible.bas index 6d11ab0902be..792418b927b2 100644 --- a/basic/qa/basic_coverage/test_ismissing_compatible.bas +++ b/basic/qa/basic_coverage/test_ismissing_compatible.bas @@ -109,6 +109,15 @@ Sub verify_testIsMissingCompatible() TestUtil.AssertEqual(TestOptArrayByRefByVal(, aB), IsMissingA, "TestOptArrayByRefByVal(, B)") TestUtil.AssertEqual(TestOptArrayByRefByVal(aA, aB), IsMissingNone, "TestOptArrayByRefByVal(A, B)") + ' tdf#143706 - optionals with named arguments (:= syntax) + ' Without the fix in place, this test would have failed with: + ' - Expected: 0 (IsMissingA) + ' - Actual : -1 (IsMissingNone) + TestUtil.AssertEqual(TestOptVariant(B := 456), IsMissingA, "TestOptVariant(B := 456)") + TestUtil.AssertEqual(TestOptVariant(A := 123), IsMissingNone, "TestOptVariant(A := 123)") + TestUtil.AssertEqual(TestOptVariant(A := 123, B := 456), IsMissingNone, "TestOptVariant(A := 123, B := 456)") + TestUtil.AssertEqual(TestOptVariant(B := 456, A := 123), IsMissingNone, "TestOptVariant(B := 456, A := 123)") + Exit Sub errorHandler: TestUtil.ReportErrorHandler("verify_testIsMissingCompatible", Err, Error$, Erl) diff --git a/basic/qa/basic_coverage/test_space_method.bas b/basic/qa/basic_coverage/test_space_method.bas index 6c44482de128..79d91969e9fa 100644 --- a/basic/qa/basic_coverage/test_space_method.bas +++ b/basic/qa/basic_coverage/test_space_method.bas @@ -7,11 +7,24 @@ Option Explicit -Function doUnitTest as String - ' SPACE - If ( Space(3) <> " " ) Then - doUnitTest = "FAIL" - Else - doUnitTest = "OK" - End If +Function doUnitTest As String + TestUtil.Testinit + verify_testSpace + doUnitTest = TestUtil.GetResult() End Function + +Sub verify_testSpace() + On Error Goto errorHandler + + TestUtil.AssertEqual(Space(3), " ", "Space(3)") + TestUtil.AssertEqual(Space(2), " ", "Space(2)") + TestUtil.AssertEqual(Space(0), "", "Space(0)") + + ' Negative values generate an empty string + TestUtil.AssertEqual(Space(-1), "", "Space(-1)") + TestUtil.AssertEqual(Space(-4), "", "Space(-4)") + + Exit Sub +errorHandler: + TestUtil.ReportErrorHandler("verify_testSpace", Err, Error$, Erl) +End Sub diff --git a/basic/qa/basic_coverage/test_split_method.bas b/basic/qa/basic_coverage/test_split_method.bas index e53dfd9705f1..adf74283fcb8 100644 --- a/basic/qa/basic_coverage/test_split_method.bas +++ b/basic/qa/basic_coverage/test_split_method.bas @@ -53,6 +53,33 @@ Sub verify_testSplit TestUtil.AssertEqual(VarType(splitArr(i)), 8200, "VarType(splitArr(i))") Next + ' tdf#146873 - CoreReflection.getType() must not error after Split() elements are wrapped in Array() + splitArr = Split("a-b-c", "-") + For i = 0 To UBound(splitArr) + splitArr(i) = Array(splitArr(i)) + Next + Dim oReflection As Object : oReflection = CreateUnoService("com.sun.star.reflection.CoreReflection") + ' Without the fix in place, this assignment would have failed + Dim oObject As Object : oObject = oReflection.GetType(splitArr) + ' Without the fix in place, this test would have failed with: + ' - Expected: 20 (20 for typelib_TypeClass_SEQUENCE) + ' - Actual : Object variable not set + TestUtil.AssertEqual(oObject.TypeClass, 20, "CoreReflection.getType() for oObject.TypeClass after Split() + Array()") + + ' cid#1700598 - guard the element probe against empty arrays + Dim aEmpty() As Integer + ' Without the fix in place, this assignment would have failed with + ' "Inadmissible value or data type. Index out of defined range" + oObject = oReflection.GetType(aEmpty) + TestUtil.AssertEqual(oObject.Name, "[]short", "CoreReflection.getType() for an empty Integer array") + + ' cid#1700598 - the element probe must use the dimension and not the flat storage index + Dim aNegative(-5 To -1) As Integer + ' Without the fix in place, this assignment would have failed with + ' "Inadmissible value or data type. Index out of defined range" + oObject = oReflection.GetType(aNegative) + TestUtil.AssertEqual(oObject.Name, "[]short", "CoreReflection.getType() for an array with a negative lower bound") + ' tdf#141474 keyword names need to match that of VBA TestUtil.AssertEqual(Split(expression:="LibreOffice StarOffice")(1), "StarOffice", "Split with 1 keyword name" ) Dim txt As String : txt = "Libre_Office_Star_Office" diff --git a/basic/qa/basic_coverage/test_tdf160321_gosub_goto.bas b/basic/qa/basic_coverage/test_tdf160321_gosub_goto.bas index 79f886fa179d..9c4cde3e26d8 100644 --- a/basic/qa/basic_coverage/test_tdf160321_gosub_goto.bas +++ b/basic/qa/basic_coverage/test_tdf160321_gosub_goto.bas @@ -24,19 +24,29 @@ Sub verify_GoSub_GoTo iVar = iVar + 1 TestUtil.AssertEqual(iVar, 1, "iVar incremented incorrectly") + ' tdf#173360 - On...GoSub target must push a return address for the Return statement + On 1 GoSub Sub3, Sub4 + TestUtil.AssertEqual(iVar, 2, "Return after On...GoSub did not resume execution correctly") + ' tdf#160321 - check the correct functionality of the GoTo statement On 1 GoTo Sub1, Sub2 iVar = iVar + 1 Exit Sub Sub1: - TestUtil.AssertEqual(iVar, 1, "iVar incremented incorrectly") + TestUtil.AssertEqual(iVar, 2, "iVar incremented incorrectly") On 2 GoTo Sub1, Sub2 iVar = iVar + 1 Exit Sub Sub2: - TestUtil.AssertEqual(iVar, 1, "iVar incremented incorrectly") + TestUtil.AssertEqual(iVar, 2, "iVar incremented incorrectly") Exit Sub +Sub3: + iVar = iVar + 1 + Return +Sub4: + iVar = iVar + 1 + Return errorHandler: TestUtil.ReportErrorHandler("verify_GoSub_GoTo", Err, Error$, Erl) Exit Sub diff --git a/basic/qa/basic_coverage/test_tdf171370.bas b/basic/qa/basic_coverage/test_tdf171370.bas new file mode 100644 index 000000000000..bf1f12f5b5f8 --- /dev/null +++ b/basic/qa/basic_coverage/test_tdf171370.bas @@ -0,0 +1,32 @@ +' +' 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/. +' + +Option Explicit + +Function doUnitTest() As String + TestUtil.TestInit + verify_tdf171370 + doUnitTest = TestUtil.GetResult() +End Function + +Sub verify_tdf171370() + On Error GoTo errorHandler + + Dim aEvent As New com.sun.star.awt.KeyEvent ' KeyChar is a UNO char + aEvent.KeyChar = 87 + + TestUtil.AssertEqual(TypeName(aEvent.KeyChar), "Char", "TypeName(aEvent.KeyChar)") + TestUtil.AssertEqual(CStr(aEvent.KeyChar), "W", "CStr(aEvent.KeyChar)") + TestUtil.AssertEqual("" & aEvent.KeyChar, "W", "concatenated aEvent.KeyChar") + TestUtil.AssertEqual(Len(aEvent.KeyChar), 1, "Len(aEvent.KeyChar)") + TestUtil.AssertEqual(Asc(aEvent.KeyChar), 87, "Asc(aEvent.KeyChar)") + + Exit Sub +errorHandler: + TestUtil.ReportErrorHandler("verify_tdf171370", Err, Error$, Erl) +End Sub diff --git a/basic/qa/cppunit/test_compiler_checks.cxx b/basic/qa/cppunit/test_compiler_checks.cxx index 2180a8adb1da..2e2830a9ec9b 100644 --- a/basic/qa/cppunit/test_compiler_checks.cxx +++ b/basic/qa/cppunit/test_compiler_checks.cxx @@ -285,4 +285,24 @@ CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testMissingEndIf) } } +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testVbaOptionalArrayParameterIsSyntaxError) +{ + MacroSnippet aMacro(u"Option VBASupport 1\n" + "Function doUnitTest(Optional A() As Integer) As Integer\n" + " doUnitTest = 0\n" + "End Function\n"_ustr); + aMacro.Compile(); + CPPUNIT_ASSERT(aMacro.HasError()); + CPPUNIT_ASSERT_EQUAL(ERRCODE_BASIC_SYNTAX, aMacro.getError().GetCode()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testArrayArgumentWithSize) +{ + MacroSnippet aMacro(u"Sub doUnitTest(A(12) As Integer)\n" + "End Sub\n"_ustr); + aMacro.Compile(); + CPPUNIT_ASSERT(aMacro.HasError()); + CPPUNIT_ASSERT_EQUAL(ERRCODE_BASIC_EXPECTED, aMacro.getError().GetCode()); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basic/qa/cppunit/test_util.cxx b/basic/qa/cppunit/test_util.cxx new file mode 100644 index 000000000000..da098e3e6ef0 --- /dev/null +++ b/basic/qa/cppunit/test_util.cxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include + +namespace +{ +class TestUtil : public CppUnit::TestFixture +{ +private: + void testSearchEOL(); + + CPPUNIT_TEST_SUITE(TestUtil); + CPPUNIT_TEST(testSearchEOL); + CPPUNIT_TEST_SUITE_END(); +}; + +void TestUtil::testSearchEOL() +{ + // Find the ending when \n is the first one + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), sb::searchEOL(u"one\ntwo\r\three\r\n")); + // Find the ending when \r\n is the first one + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), sb::searchEOL(u"one\r\ntwo\r\three\n")); + // Find the ending when \r is the first one + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), sb::searchEOL(u"one\rtwo\n\three\r\n")); + + // The three types of ending at the end of the string + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), sb::searchEOL(u"one\n")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), sb::searchEOL(u"one\r")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), sb::searchEOL(u"one\r\n")); + + // No ending + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), sb::searchEOL(u"")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), sb::searchEOL(u"unending string")); + + // Skip an ending + CPPUNIT_ASSERT_EQUAL(sal_Int32(7), sb::searchEOL(u"one\ntwo\n", 4)); + + // Start at an ending + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), sb::searchEOL(u"one\ntwo\n", 3)); +} +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestUtil); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basic/qa/vba_tests/gosub_goto.vb b/basic/qa/vba_tests/gosub_goto.vb index 523f15ac94c9..01a94325a08e 100644 --- a/basic/qa/vba_tests/gosub_goto.vb +++ b/basic/qa/vba_tests/gosub_goto.vb @@ -25,19 +25,29 @@ Sub verify_GoSub_GoTo iVar = iVar + 1 TestUtil.AssertEqual(iVar, 1, "iVar incremented incorrectly") + ' tdf#173360 - On...GoSub target must push a return address for the Return statement + On 1 GoSub Sub3, Sub4 + TestUtil.AssertEqual(iVar, 2, "Return after On...GoSub did not resume execution correctly") + ' tdf#160321 - check the correct functionality of the GoTo statement On 1 GoTo Sub1, Sub2 iVar = iVar + 1 Exit Sub Sub1: - TestUtil.AssertEqual(iVar, 1, "iVar incremented incorrectly") + TestUtil.AssertEqual(iVar, 2, "iVar incremented incorrectly") On 2 GoTo Sub1, Sub2 iVar = iVar + 1 Exit Sub Sub2: - TestUtil.AssertEqual(iVar, 1, "iVar incremented incorrectly") + TestUtil.AssertEqual(iVar, 2, "iVar incremented incorrectly") Exit Sub +Sub3: + iVar = iVar + 1 + Return +Sub4: + iVar = iVar + 1 + Return errorHandler: TestUtil.ReportErrorHandler("verify_GoSub_GoTo", Err, Error$, Erl) Exit Sub diff --git a/basic/qa/vba_tests/ismissing.vb b/basic/qa/vba_tests/ismissing.vb index febe0339f68a..1642a6dca240 100644 --- a/basic/qa/vba_tests/ismissing.vb +++ b/basic/qa/vba_tests/ismissing.vb @@ -95,26 +95,6 @@ Sub verify_testIsMissingVba() TestUtil.AssertEqual(TestOptObjectByRefByVal(, cB), IsMissingA, "TestOptObjectByRefByVal(, B)") TestUtil.AssertEqual(TestOptObjectByRefByVal(cA, cB), IsMissingNone, "TestOptObjectByRefByVal(A, B)") - ' optionals with array datatypes - Dim aA(0 To 1) As Integer - aA(0) = 123 - aA(1) = 456 - Dim aB(0 To 1) As Variant - aB(0) = 123.4 - aB(1) = 567.8 - ' TODO - New bug report? Scanner initializes variable not as an array - ' TestUtil.AssertEqual(TestOptArray(), IsMissingAB, "TestOptArray()") - ' TestUtil.AssertEqual(TestOptArray(aA), IsMissingB, "TestOptArray(A)") - ' TestUtil.AssertEqual(TestOptArray(, aB), IsMissingA, "TestOptArray(, B)") - TestUtil.AssertEqual(TestOptArray(aA, aB), IsMissingNone, "TestOptArray(A, B)") - - ' optionals with array datatypes (ByRef and ByVal) - ' TODO - New bug report? Scanner initializes variable not as an array - ' TestUtil.AssertEqual(TestOptArrayByRefByVal(), IsMissingAB, "TestOptArrayByRefByVal()") - ' TestUtil.AssertEqual(TestOptArrayByRefByVal(aA), IsMissingB, "TestOptArrayByRefByVal(A)") - ' TestUtil.AssertEqual(TestOptArrayByRefByVal(, aB), IsMissingA, "TestOptArrayByRefByVal(, B)") - TestUtil.AssertEqual(TestOptArrayByRefByVal(aA, aB), IsMissingNone, "TestOptArrayByRefByVal(A, B)") - Exit Sub errorHandler: TestUtil.ReportErrorHandler("verify_testIsMissingVba", Err, Error$, Erl) @@ -160,14 +140,6 @@ Function TestOptObjectByRefByVal(Optional ByRef A As Collection, Optional ByVal TestOptObjectByRefByVal = WhatIsMissing(IsNull(A), IsNull(B)) End Function -Function TestOptArray(Optional A() As Integer, Optional B() As Variant) - TestOptArray = WhatIsMissing(IsEmpty(A), IsEmpty(B)) -End Function - -Function TestOptArrayByRefByVal(Optional ByRef A() As Integer, Optional ByVal B() As Variant) - TestOptArrayByRefByVal = WhatIsMissing(IsEmpty(A), IsEmpty(B)) -End Function - Function WhatIsMissing(is_missingA, is_missingB) If is_missingA And is_missingB Then WhatIsMissing = IsMissingAB diff --git a/basic/qa/vba_tests/optional_paramters.vb b/basic/qa/vba_tests/optional_paramters.vb index d47854d2fb69..20465ccd4c2f 100644 --- a/basic/qa/vba_tests/optional_paramters.vb +++ b/basic/qa/vba_tests/optional_paramters.vb @@ -22,12 +22,6 @@ End Function Sub verify_testOptionalsVba() On Error GoTo errorHandler - ' tdf#143707 - check correct initialization of default value for optionals - ' Without the fix in place, this test would have failed with - ' - Expected: 123 - ' - Actual : 123% - TestUtil.AssertEqual(TestOptVariantInit(), 123, "TestOptVariantInit()") - ' optionals with variant datatypes TestUtil.AssertEqual(TestOptVariant(), 123, "TestOptVariant()") TestUtil.AssertEqual(TestOptVariant(123), 246, "TestOptVariant(123)") @@ -94,26 +88,6 @@ Sub verify_testOptionalsVba() TestUtil.AssertEqualApprox(TestOptObjectByRefByVal(, cB), 691.2, 1E-5, "TestOptObjectByRefByVal(, B)") TestUtil.AssertEqualApprox(TestOptObjectByRefByVal(cA, cB), 1270.2, 1E-5, "TestOptObjectByRefByVal(A, B)") - ' optionals with array datatypes - Dim aA(0 To 1) As Integer - aA(0) = 123 - aA(1) = 456 - Dim aB(0 To 1) As Variant - aB(0) = 123.4 - aB(1) = 567.8 - ' TODO - New bug report? Scanner initializes variable not as an array - ' TestUtil.AssertEqual(TestOptArray(), 0, "TestOptArray()") - ' TestUtil.AssertEqual(TestOptArray(aA), 579, "TestOptArray(A)") - ' TestUtil.AssertEqualApprox(TestOptArray(, aB), 691.2, 1E-5, "TestOptArray(, B)") - TestUtil.AssertEqualApprox(TestOptArray(aA, aB), 1270.2, 1E-5, "TestOptArray(A, B)") - - ' optionals with array datatypes (ByRef and ByVal) - ' TODO - New bug report? Scanner initializes variable not as an array - ' TestUtil.AssertEqual(TestOptArrayByRefByVal(), 0, "TestOptArrayByRefByVal()") - ' TestUtil.AssertEqual(TestOptArrayByRefByVal(aA), 579, "TestOptArrayByRefByVal(A)") - ' TestUtil.AssertEqualApprox(TestOptArrayByRefByVal(, aB), 691.2, 1E-5, "TestOptArrayByRefByVal(, B)") - TestUtil.AssertEqualApprox(TestOptArrayByRefByVal(aA, aB), 1270.2, 1E-5, "TestOptArrayByRefByVal(A, B)") - Exit Sub errorHandler: TestUtil.ReportErrorHandler("verify_testOptionalsVba", Err, Error$, Erl) @@ -169,14 +143,6 @@ Function TestOptObjectByRefByVal(Optional ByRef A As Collection, Optional ByVal If Not IsNull(B) Then TestOptObjectByRefByVal = TestOptObjectByRefByVal + CollectionSum(B) End Function -Function TestOptArray(Optional A() As Integer, Optional B() As Variant) - TestOptArray = ArraySum(IsMissing(A), A) + ArraySum(IsMissing(B), B) -End Function - -Function TestOptArrayByRefByVal(Optional ByRef A() As Integer, Optional ByVal B() As Variant) - TestOptArrayByRefByVal = ArraySum(IsMissing(A), A) + ArraySum(IsMissing(B), B) -End Function - Function OptNumberSum(is_missingA As Boolean, A, is_missingB As Boolean, B) OptNumberSum = 0 If Not is_missingA Then OptNumberSum = A diff --git a/basic/qa/vba_tests/space.vb b/basic/qa/vba_tests/space.vb index 70d09c3ea74e..abd3f3ddc47d 100644 --- a/basic/qa/vba_tests/space.vb +++ b/basic/qa/vba_tests/space.vb @@ -18,9 +18,24 @@ End Function Sub verify_testSpace() On Error GoTo errorHandler - TestUtil.AssertEqual(Space(2), " ", "Space(2)") + TestUtil.AssertEqual(Space(3), " ", "Space(3)") + TestUtil.AssertEqual(Space(2), " ", "Space(2)") + TestUtil.AssertEqual(Space(0), "", "Space(0)") + + ' in VBA it must throw when used with negative values + TestUtil.AssertEqual(GetNegativeSpaceError(-1), 5, "GetNegativeSpaceError(-1)") + TestUtil.AssertEqual(GetNegativeSpaceError(-4), 5, "GetNegativeSpaceError(-4)") Exit Sub errorHandler: TestUtil.ReportErrorHandler("verify_testSpace", Err, Error$, Erl) End Sub + +Function GetNegativeSpaceError(negativeValue) As Long +On Error GoTo errorHandler + Space(negativeValue) + GetNegativeSpaceError = 0 + Exit Function +errorHandler: + GetNegativeSpaceError = Err +End Function diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx index ccc6674bcdba..36e6fe6beba9 100644 --- a/basic/source/classes/sbunoobj.cxx +++ b/basic/source/classes/sbunoobj.cxx @@ -880,12 +880,23 @@ static Type getUnoTypeForSbxValue( const SbxValue* pVal ) sal_Int32 nLower, nUpper; if (nDims == 1 && pArray->GetDim(1, nLower, nUpper)) { - if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) + // tdf#146873 - inspect elements when they are non-fixed + bool bNeedsInit + = eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY; + bool bInspectElements = bNeedsInit; + // cid#1700598 - guard the element probe against empty arrays + if (!bInspectElements && nLower <= nUpper) + { + sal_Int32 nFirstIdx = nLower; + SbxVariableRef xFirstVar = pArray->Get(&nFirstIdx); + if (xFirstVar && !xFirstVar->IsFixed()) + bInspectElements = true; + } + + if (bInspectElements) { // If all elements of the arrays are from the same type, take // this one - otherwise the whole will be considered as Any-Sequence - bool bNeedsInit = true; - for (sal_Int32 aIdx[1] = { nLower }; aIdx[0] <= nUpper; ++aIdx[0]) { SbxVariableRef xVar = pArray->Get(aIdx); @@ -917,12 +928,22 @@ static Type getUnoTypeForSbxValue( const SbxValue* pVal ) // #i33795 Map also multi dimensional arrays to corresponding sequences else if( nDims > 1 ) { - if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) + // tdf#146873 - inspect elements when they are non-fixed + bool bNeedsInit = eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY; + bool bInspectElements = bNeedsInit; + // cid#1700598 - guard the element probe against empty arrays + if (!bInspectElements && pArray->Count() > 0) + { + SbxVariableRef xFirstVar = pArray->SbxArray::Get(0); + if (xFirstVar && !xFirstVar->IsFixed()) + bInspectElements = true; + } + + if (bInspectElements) { // For this check the array's dim structure does not matter sal_uInt32 nFlatArraySize = pArray->Count(); - bool bNeedsInit = true; for( sal_uInt32 i = 0 ; i < nFlatArraySize ; i++ ) { SbxVariableRef xVar = pArray->SbxArray::Get(i); diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx index 6e502ceffbf1..bbcb382d6c07 100644 --- a/basic/source/classes/sbxmod.cxx +++ b/basic/source/classes/sbxmod.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1901,6 +1902,62 @@ void SbModule::handleProcedureProperties( SfxBroadcaster& rBC, const SfxHint& rH SbModule::Notify( rBC, rHint ); } +OUString SbModule::GetSourceWithoutMethod(const SbMethod& rMethod) const +{ + sal_uInt16 nStartRange, nEndRange; + rMethod.GetLineRange(nStartRange, nEndRange); + + sal_Int32 nStartLine = nStartRange - 1; + sal_Int32 nLines = nEndRange - nStartRange + 1; + + sal_Int32 nStartPos = 0; + sal_Int32 nLine = 0; + while ( nLine < nStartLine ) + { + nStartPos = sb::searchEOL( aOUSource, nStartPos ); + if( nStartPos == -1 ) + break; + nStartPos++; // not the \n. + nLine++; + } + + SAL_WARN_IF( nStartPos == -1, "basic.sbx", + "GetSourceWithoutMethod: Start line not found!" ); + + if ( nStartPos == -1 ) + return aOUSource; + + sal_Int32 nEndPos = nStartPos; + + for ( sal_Int32 i = 0; i < nLines; i++ ) + nEndPos = sb::searchEOL( aOUSource, nEndPos+1 ); + + if ( nEndPos == -1 ) // might happen at the last line + nEndPos = aOUSource.getLength(); + else + nEndPos++; + + OUString sRet = OUString::Concat(aOUSource.subView( 0, nStartPos )) + + aOUSource.subView( nEndPos ); + + // erase trailing empty lines + { + sal_Int32 n = nStartPos; + sal_Int32 nLen = sRet.getLength(); + while ( ( n < nLen ) && ( sRet[ n ] == '\n' || sRet[ n ] == '\r' ) ) + { + n++; + } + + if ( n > nStartPos ) + { + sRet = OUString::Concat(sRet.subView( 0, nStartPos )) + sRet.subView( n ); + } + } + + return sRet; +} + // Implementation SbJScriptModule (Basic module for JavaScript source code) SbJScriptModule::SbJScriptModule() @@ -2038,7 +2095,7 @@ std::pair SbMethod::StoreData( SvStream& rStrm ) const return { true, nVersion }; } -void SbMethod::GetLineRange( sal_uInt16& l1, sal_uInt16& l2 ) +void SbMethod::GetLineRange( sal_uInt16& l1, sal_uInt16& l2 ) const { l1 = nLine1; l2 = nLine2; } diff --git a/basic/source/comp/dim.cxx b/basic/source/comp/dim.cxx index 16429d1b523f..d9cf854fdc01 100644 --- a/basic/source/comp/dim.cxx +++ b/basic/source/comp/dim.cxx @@ -961,6 +961,12 @@ SbiProcDef* SbiParser::ProcDecl( bool bDecl ) { break; } + if( bVBASupportOn && bOptional && pPar->IsWithBrackets() ) + { + Error( ERRCODE_BASIC_SYNTAX ); + delete pPar; + break; + } if( bByVal ) { pPar->SetByVal(true); diff --git a/basic/source/comp/sbcomp.cxx b/basic/source/comp/sbcomp.cxx index 1a6a52b22850..c79b87e22094 100644 --- a/basic/source/comp/sbcomp.cxx +++ b/basic/source/comp/sbcomp.cxx @@ -53,14 +53,14 @@ bool SbModule::Compile() GetSbData()->pCompMod = pOld; - // compiling a module, the module-global + // When compiling a module, the module-global // variables of all modules become invalid bool bRet = IsCompiled(); if( bRet ) { if( dynamic_cast( this) == nullptr ) pBasic->ClearAllModuleVars(); - RemoveVars(); // remove 'this' Modules variables + RemoveVars(); // remove 'this' Module's variables // clear all method statics for (sal_uInt32 i = 0; i < pMethods->Count(); i++) { diff --git a/basic/source/comp/token.cxx b/basic/source/comp/token.cxx index ec5f7df16eb0..d576144aa8e2 100644 --- a/basic/source/comp/token.cxx +++ b/basic/source/comp/token.cxx @@ -31,7 +31,7 @@ struct TokenTable { SbiToken t; const char *s; }; } -const TokenTable aTokTable_Basic [] = { +constexpr TokenTable aTokTable_Basic [] = { { CAT, "&" }, { MUL, "*" }, { PLUS, "+" }, @@ -199,7 +199,7 @@ TokenLabelInfo::TokenLabelInfo() m_pTokenCanBeLabelTab.fill(false); // Token accepted as label by VBA - static const SbiToken eLabelToken[] = { ACCESS, ALIAS, APPEND, BASE, BINARY, CLASSMODULE, + static constexpr SbiToken eLabelToken[] = { ACCESS, ALIAS, APPEND, BASE, BINARY, CLASSMODULE, COMPARE, COMPATIBLE, DEFERR, ERROR_, BASIC_EXPLICIT, LIB, LINE, LPRINT, NAME, TOBJECT, OUTPUT, PROPERTY, RANDOM, READ, STEP, STOP, TEXT, VBASUPPORT }; for( SbiToken eTok : eLabelToken ) diff --git a/basic/source/inc/namecont.hxx b/basic/source/inc/namecont.hxx index 48d8bb950263..09f5d40a22b0 100644 --- a/basic/source/inc/namecont.hxx +++ b/basic/source/inc/namecont.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include #include #include #include @@ -58,9 +59,11 @@ class NameContainer final cppu::OWeakObject& rOwner; std::unordered_map maMap; + // Enumeration must keep insertion order: it drives the on-disk order of the + // library index file and module streams, which macro signatures sign over. + std::vector maNamesOrder; css::uno::Type mType; - css::uno::XInterface* mpxEventSource; ::comphelper::OInterfaceContainerHelper4 maContainerListeners; ::comphelper::OInterfaceContainerHelper4 maChangesListeners; @@ -69,12 +72,8 @@ public: NameContainer(const css::uno::Type& rType, cppu::OWeakObject& owner) : rOwner(owner) , mType( rType ) - , mpxEventSource( nullptr ) {} - void setEventSource( css::uno::XInterface* pxEventSource ) - { mpxEventSource = pxEventSource; } - /// @throws css::lang::IllegalArgumentException /// @throws css::lang::WrappedTargetException /// @throws css::uno::RuntimeException diff --git a/basic/source/runtime/basrdll.cxx b/basic/source/runtime/basrdll.cxx index fb177349f802..109eb9f76641 100644 --- a/basic/source/runtime/basrdll.cxx +++ b/basic/source/runtime/basrdll.cxx @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/basic/source/runtime/inputbox.cxx b/basic/source/runtime/inputbox.cxx index ae9e64e13f6a..01956168bbd8 100644 --- a/basic/source/runtime/inputbox.cxx +++ b/basic/source/runtime/inputbox.cxx @@ -24,10 +24,12 @@ #include #include #include +#include #include #include #include -#include +#include + #include #include diff --git a/basic/source/runtime/iosys.cxx b/basic/source/runtime/iosys.cxx index 39aaf4a9e8cc..8d3ef7cf24e2 100644 --- a/basic/source/runtime/iosys.cxx +++ b/basic/source/runtime/iosys.cxx @@ -21,11 +21,12 @@ #include #include #include +#include #include #include #include +#include #include -#include #include #include diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx index d83b4bcee60b..a061a434109e 100644 --- a/basic/source/runtime/methods.cxx +++ b/basic/source/runtime/methods.cxx @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -221,13 +220,8 @@ void SbRtl_Error(StarBASIC * pBasic, SbxArray & rPar, bool) { nCode = rPar.Get(1)->GetLong(); if( nCode > 65535 ) - { - StarBASIC::Error( ERRCODE_BASIC_CONVERSION ); - } - else - { - nErr = StarBASIC::GetSfxFromVBError( static_cast(nCode) ); - } + return StarBASIC::Error( ERRCODE_BASIC_CONVERSION ); + nErr = StarBASIC::GetSfxFromVBError( static_cast(nCode) ); } bool bVBA = SbiRuntime::isVBAEnabled(); OUString tmpErrMsg; @@ -468,8 +462,7 @@ void implStepRenameUCB( const OUString& aSource, const OUString& aDest ) OUString aSourceFullPath = getFullPath( aSource ); if( !xSFI->exists( aSourceFullPath ) ) { - StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND ); - return; + return StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND ); } OUString aDestFullPath = getFullPath( aDest ); @@ -547,8 +540,7 @@ void SbRtl_Kill(StarBASIC *, SbxArray & rPar, bool) OUString aFullPath = getFullPath( aFileSpec ); if( !xSFI->exists( aFullPath ) || xSFI->isFolder( aFullPath ) ) { - StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND ); - return; + return StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND ); } try { @@ -957,7 +949,7 @@ void SbRtl_Int(StarBASIC *, SbxArray & rPar, bool) void SbRtl_Fix(StarBASIC *, SbxArray & rPar, bool) { - if (rPar.Count() < 2) + if (rPar.Count() != 2) return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); SbxVariableRef pArg = rPar.Get(1); @@ -1279,7 +1271,7 @@ void SbRtl_RTrim(StarBASIC *, SbxArray & rPar, bool) void SbRtl_Sgn(StarBASIC *, SbxArray & rPar, bool) { - if (rPar.Count() < 2) + if (rPar.Count() != 2) return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); double aDouble = rPar.Get(1)->GetDouble(); @@ -1302,7 +1294,18 @@ void SbRtl_Space(StarBASIC *, SbxArray & rPar, bool) return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT); } - const sal_Int32 nCount = rPar.Get(1)->GetLong(); + sal_Int32 nCount = rPar.Get(1)->GetLong(); + + if (nCount < 0) + { + if (SbiRuntime::isVBAEnabled()) + { + return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT); + } + + nCount = 0; + } + rPar.Get(0)->PutString(OUString::Concat(RepeatedUChar(' ', nCount))); } @@ -1937,19 +1940,16 @@ void SbRtl_TimeValue(StarBASIC *, SbxArray & rPar, bool) bool bSuccess = pFormatter->IsNumberFormat(rPar.Get(1)->GetOUString(), nIndex, fResult ); SvNumFormatType nType = pFormatter->GetType(nIndex); - if(bSuccess && (nType==SvNumFormatType::TIME||nType==SvNumFormatType::DATETIME)) + if (!bSuccess || (nType != SvNumFormatType::TIME && nType != SvNumFormatType::DATETIME)) { - if ( nType == SvNumFormatType::DATETIME ) - { - // cut days - fResult = fmod( fResult, 1 ); - } - rPar.Get(0)->PutDate(fResult); + return StarBASIC::Error( ERRCODE_BASIC_CONVERSION ); } - else + if ( nType == SvNumFormatType::DATETIME ) { - StarBASIC::Error( ERRCODE_BASIC_CONVERSION ); + // cut days + fResult = fmod( fResult, 1 ); } + rPar.Get(0)->PutDate(fResult); } void SbRtl_Day(StarBASIC *, SbxArray & rPar, bool) @@ -2681,18 +2681,16 @@ void SbRtl_GetAttr(StarBASIC *, SbxArray & rPar, bool) OUString aPath; FileBase::getSystemPathFromFileURL( aPathURL, aPath ); DWORD nRealFlags = GetFileAttributesW (o3tl::toW(aPath.getStr())); - if (nRealFlags != 0xffffffff) - { - if (nRealFlags == FILE_ATTRIBUTE_NORMAL) - { - nRealFlags = 0; - } - nFlags = static_cast(nRealFlags); - } - else + if (nRealFlags == 0xffffffff) { StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND ); + return; } + if (nRealFlags == FILE_ATTRIBUTE_NORMAL) + { + nRealFlags = 0; + } + nFlags = static_cast(nRealFlags); rPar.Get(0)->PutInteger(nFlags); return; @@ -2859,36 +2857,32 @@ void SbRtl_EOF(StarBASIC *, SbxArray & rPar, bool) { // No changes for UCB if (rPar.Count() != 2) + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + + sal_Int16 nChannel = rPar.Get(1)->GetInteger(); + SbiIoSystem* pIO = GetSbData()->pInst->GetIoSystem(); + SbiStream* pSbStrm = pIO->GetStream( nChannel ); + if ( !pSbStrm ) { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + return StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL ); + } + bool beof; + SvStream* pSvStrm = pSbStrm->GetStrm(); + if ( pSbStrm->IsText() ) + { + char cBla; + (*pSvStrm).ReadChar( cBla ); // can we read another character? + beof = pSvStrm->eof(); + if ( !beof ) + { + pSvStrm->SeekRel( -1 ); + } } else { - sal_Int16 nChannel = rPar.Get(1)->GetInteger(); - SbiIoSystem* pIO = GetSbData()->pInst->GetIoSystem(); - SbiStream* pSbStrm = pIO->GetStream( nChannel ); - if ( !pSbStrm ) - { - return StarBASIC::Error( ERRCODE_BASIC_BAD_CHANNEL ); - } - bool beof; - SvStream* pSvStrm = pSbStrm->GetStrm(); - if ( pSbStrm->IsText() ) - { - char cBla; - (*pSvStrm).ReadChar( cBla ); // can we read another character? - beof = pSvStrm->eof(); - if ( !beof ) - { - pSvStrm->SeekRel( -1 ); - } - } - else - { - beof = pSvStrm->eof(); // for binary data! - } - rPar.Get(0)->PutBool(beof); + beof = pSvStrm->eof(); // for binary data! } + rPar.Get(0)->PutBool(beof); } void SbRtl_FileAttr(StarBASIC *, SbxArray & rPar, bool) @@ -3600,12 +3594,10 @@ void SbRtl_DDEInitiate(StarBASIC *, SbxArray & rPar, bool) ErrCode nDdeErr = pDDE->Initiate( aApp, aTopic, nChannel ); if( nDdeErr ) { - StarBASIC::Error( nDdeErr ); - } - else - { - rPar.Get(0)->PutInteger(static_cast(nChannel)); + return StarBASIC::Error( nDdeErr ); } + + rPar.Get(0)->PutInteger(static_cast(nChannel)); } void SbRtl_DDETerminate(StarBASIC *, SbxArray & rPar, bool) @@ -3614,8 +3606,7 @@ void SbRtl_DDETerminate(StarBASIC *, SbxArray & rPar, bool) int nArgs = static_cast(rPar.Count()); if ( nArgs != 2 ) { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); - return; + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); } size_t nChannel = rPar.Get(1)->GetInteger(); SbiDdeControl* pDDE = GetSbData()->pInst->GetDdeControl(); @@ -4118,7 +4109,7 @@ void SbRtl_MsgBox(StarBASIC *, SbxArray & rPar, bool) } std::unique_ptr xBox(Application::CreateMessageDialog(pParent, - eType, VclButtonsType::NONE, aMsg, GetpApp())); + eType, VclButtonsType::NONE, aMsg)); std::vector> buttons; switch (nType & 0x0F) // delete bits 4-16 diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx index 6e4d0a361b0a..b2d3e3b04d75 100644 --- a/basic/source/runtime/methods1.cxx +++ b/basic/source/runtime/methods1.cxx @@ -212,45 +212,30 @@ void SbRtl_CallByName(StarBASIC *, SbxArray & rPar, bool) void SbRtl_CBool(StarBASIC *, SbxArray & rPar, bool) // JSM { bool bVal = false; - if (rPar.Count() == 2) - { - SbxVariable* pSbxVariable = rPar.Get(1); - bVal = pSbxVariable->GetBool(); - } - else - { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); - } + if (rPar.Count() != 2) + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + SbxVariable* pSbxVariable = rPar.Get(1); + bVal = pSbxVariable->GetBool(); rPar.Get(0)->PutBool(bVal); } void SbRtl_CByte(StarBASIC *, SbxArray & rPar, bool) // JSM { sal_uInt8 nByte = 0; - if (rPar.Count() == 2) - { - SbxVariable* pSbxVariable = rPar.Get(1); - nByte = pSbxVariable->GetByte(); - } - else - { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); - } + if (rPar.Count() != 2) + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + SbxVariable* pSbxVariable = rPar.Get(1); + nByte = pSbxVariable->GetByte(); rPar.Get(0)->PutByte(nByte); } void SbRtl_CCur(StarBASIC *, SbxArray & rPar, bool) { sal_Int64 nCur = 0; - if (rPar.Count() == 2) - { - SbxVariable* pSbxVariable = rPar.Get(1); - nCur = pSbxVariable->GetCurrency(); - } - else - { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); - } + if (rPar.Count() != 2) + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + SbxVariable* pSbxVariable = rPar.Get(1); + nCur = pSbxVariable->GetCurrency(); rPar.Get(0)->PutCurrency(nCur); } @@ -258,15 +243,11 @@ void SbRtl_CDec(StarBASIC *, SbxArray & rPar, bool) { #ifdef _WIN32 SbxDecimal* pDec = nullptr; - if (rPar.Count() == 2) - { - SbxVariable* pSbxVariable = rPar.Get(1); - pDec = pSbxVariable->GetDecimal(); - } - else - { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); - } + if (rPar.Count() != 2) + return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT); + + SbxVariable* pSbxVariable = rPar.Get(1); + pDec = pSbxVariable->GetDecimal(); rPar.Get(0)->PutDecimal(pDec); #else rPar.Get(0)->PutEmpty(); @@ -288,27 +269,23 @@ void SbRtl_CDate(StarBASIC *, SbxArray & rPar, bool) // JSM void SbRtl_CDbl(StarBASIC *, SbxArray & rPar, bool) // JSM { double nVal = 0.0; - if (rPar.Count() == 2) + if (rPar.Count() != 2) + return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT); + + SbxVariable* pSbxVariable = rPar.Get(1); + if( pSbxVariable->GetType() == SbxSTRING ) { - SbxVariable* pSbxVariable = rPar.Get(1); - if( pSbxVariable->GetType() == SbxSTRING ) + // #41690 + OUString aScanStr = pSbxVariable->GetOUString(); + ErrCode Error = SbxValue::ScanNumIntnl( aScanStr, nVal ); + if( Error != ERRCODE_NONE ) { - // #41690 - OUString aScanStr = pSbxVariable->GetOUString(); - ErrCode Error = SbxValue::ScanNumIntnl( aScanStr, nVal ); - if( Error != ERRCODE_NONE ) - { - StarBASIC::Error( Error ); - } - } - else - { - nVal = pSbxVariable->GetDouble(); + StarBASIC::Error( Error ); } } else { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + nVal = pSbxVariable->GetDouble(); } rPar.Get(0)->PutDouble(nVal); @@ -339,30 +316,27 @@ void SbRtl_CLng(StarBASIC *, SbxArray & rPar, bool) // JSM void SbRtl_CSng(StarBASIC *, SbxArray & rPar, bool) // JSM { float nVal = float(0.0); - if (rPar.Count() == 2) + if (rPar.Count() != 2) + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + + SbxVariable* pSbxVariable = rPar.Get(1); + if( pSbxVariable->GetType() == SbxSTRING ) { - SbxVariable* pSbxVariable = rPar.Get(1); - if( pSbxVariable->GetType() == SbxSTRING ) + // #41690 + double dVal = 0.0; + OUString aScanStr = pSbxVariable->GetOUString(); + ErrCode Error = SbxValue::ScanNumIntnl( aScanStr, dVal, /*bSingle=*/true ); + if( SbxBase::GetError() == ERRCODE_NONE && Error != ERRCODE_NONE ) { - // #41690 - double dVal = 0.0; - OUString aScanStr = pSbxVariable->GetOUString(); - ErrCode Error = SbxValue::ScanNumIntnl( aScanStr, dVal, /*bSingle=*/true ); - if( SbxBase::GetError() == ERRCODE_NONE && Error != ERRCODE_NONE ) - { - StarBASIC::Error( Error ); - } - nVal = static_cast(dVal); - } - else - { - nVal = pSbxVariable->GetSingle(); + StarBASIC::Error( Error ); } + nVal = static_cast(dVal); } else { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + nVal = pSbxVariable->GetSingle(); } + rPar.Get(0)->PutSingle(nVal); } @@ -565,8 +539,9 @@ void SbRtl_Choose(StarBASIC *, SbxArray & rPar, bool) { if (rPar.Count() < 2) { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); } + sal_Int16 nIndex = rPar.Get(1)->GetInteger(); sal_uInt32 nCount = rPar.Count(); nCount--; @@ -628,8 +603,9 @@ void SbRtl_FreeLibrary(StarBASIC *, SbxArray & rPar, bool) { if (rPar.Count() != 2) { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); } + GetSbData()->pInst->GetDllMgr()->FreeDll(rPar.Get(1)->GetOUString()); } bool IsBaseIndexOne() @@ -1636,22 +1612,18 @@ void SbRtl_Weekday(StarBASIC *, SbxArray & rPar, bool) sal_uInt32 nParCount = rPar.Count(); if ( nParCount < 2 || nParCount > 3 ) { - StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); + return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); } - else + double aDate = rPar.Get(1)->GetDate(); + bool bFirstDay = false; + sal_Int16 nFirstDay = 0; + if ( nParCount > 2 ) { - double aDate = rPar.Get(1)->GetDate(); - - bool bFirstDay = false; - sal_Int16 nFirstDay = 0; - if ( nParCount > 2 ) - { - nFirstDay = rPar.Get(2)->GetInteger(); - bFirstDay = true; - } - sal_Int16 nDay = implGetWeekDay( aDate, bFirstDay, nFirstDay ); - rPar.Get(0)->PutInteger(nDay); + nFirstDay = rPar.Get(2)->GetInteger(); + bFirstDay = true; } + sal_Int16 nDay = implGetWeekDay( aDate, bFirstDay, nFirstDay ); + rPar.Get(0)->PutInteger(nDay); } namespace { diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx index b625b928bc2d..4675d52cff0c 100644 --- a/basic/source/runtime/runtime.cxx +++ b/basic/source/runtime/runtime.cxx @@ -628,6 +628,15 @@ void SbiRuntime::SetIsMissing( SbxVariable* pVar ) pVar->SetInfo( pInfo ); } +// tdf#102381 - turns a variable into the representation of a missing argument +void SbxSetMissingParameter(SbxVariable& rVar) +{ + // #57915 The semantics of a missing argument is represented by the value 448 + // (ERRCODE_BASIC_NAMED_NOT_FOUND) of the type error in VB. + rVar.PutErr(448); + SbiRuntime::SetIsMissing(&rVar); +} + // tdf#79426, tdf#125180 - checks if a variable contains the information about a missing parameter bool SbiRuntime::IsMissing( SbxVariable* pVar, sal_uInt16 nIdx ) { @@ -708,7 +717,7 @@ void SbiRuntime::SetParameters( SbxArray* pParams ) } SbxVariable* v2 = new SbxVariable( t ); v2->SetFlag( SbxFlagBits::ReadWrite ); - // tdf#79426, tdf#125180 - if parameter was missing, readd additional information about a missing parameter + // tdf#79426, tdf#125180 - if parameter was missing, re-add additional information about a missing parameter if ( IsMissing( v, 1 ) ) { SetIsMissing( v2 ); @@ -2788,13 +2797,10 @@ void SbiRuntime::StepRESTART() void SbiRuntime::StepEMPTY() { // #57915 The semantics of StepEMPTY() is the representation of a missing argument. - // This is represented by the value 448 (ERRCODE_BASIC_NAMED_NOT_FOUND) of the type error - // in VB. StepEmpty should now rather be named StepMISSING() but the name is kept - // to simplify matters. + // StepEmpty should now rather be named StepMISSING() but the name is kept to simplify matters. SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); - xVar->PutErr( 448 ); // tdf#79426, tdf#125180 - add additional information about a missing parameter - SetIsMissing( xVar.get() ); + SbxSetMissingParameter(*xVar); PushVar( xVar.get() ); } @@ -3057,14 +3063,14 @@ void SbiRuntime::StepONJUMP( sal_uInt32 nOp1 ) SbxVariableRef p = PopVar(); sal_Int16 n = p->GetInteger(); - if (nOp1 & 0x8000) - nOp1 &= 0x7FFF; + sal_uInt32 nMax = nOp1 & 0x7FFF; // tdf#160321 - do not execute the jump statement if the expression is out of range - if (n < 1 || o3tl::make_unsigned(n) > nOp1) - n = static_cast(nOp1 + 1); + if (n < 1 || o3tl::make_unsigned(n) > nMax) + n = static_cast(nMax + 1); + // tdf#173360 - only push a return address for a valid On...GoSub target else if (nOp1 & 0x8000) - PushGosub(pCode + 5 * nOp1); + PushGosub(pCode + 5 * nMax); nOp1 = static_cast(pCode - pImg->GetCode()) + 5 * --n; StepJUMP( nOp1 ); @@ -3923,6 +3929,26 @@ void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 ) } pArg->Put(pVar, nCurPar++); } + // tdf#143706 - mark skipped named optional parameters as missing/empty + SbxMethod* pSbxMeth = dynamic_cast(p); + const bool bIsRuntimeFunction = pSbxMeth && pSbxMeth->IsRuntimeFunction(); + for (sal_uInt32 j = 1; j < pArg->Count(); j++) + { + if (!pArg->GetRef(j)) + { + SbxVariableRef xVar; + if (bIsRuntimeFunction) + xVar = new SbxVariable(SbxEMPTY); + else + { + // Same as in SbiRuntime::StepEMPTY(), because the compiler does not + // generate a StepEMPTY for StepPARAM when there is no COMMA token + xVar = new SbxVariable(SbxVARIANT); + SbxSetMissingParameter(*xVar); + } + pArg->Put(xVar.get(), j); + } + } refArgv = pArg; } } @@ -4221,9 +4247,8 @@ void SbiRuntime::StepPARAM( sal_uInt32 nOp1, sal_uInt32 nOp2 ) while( iLoop >= nParamCount ) { pVar = new SbxVariable(); - pVar->PutErr( 448 ); // like in VB: Error-Code 448 (ERRCODE_BASIC_NAMED_NOT_FOUND) // tdf#79426, tdf#125180 - add additional information about a missing parameter - SetIsMissing( pVar ); + SbxSetMissingParameter(*pVar); refParams->Put(pVar, iLoop); iLoop--; } diff --git a/basic/source/runtime/stdobj.cxx b/basic/source/runtime/stdobj.cxx index f30a633dccfb..a8abaa3c5ea6 100644 --- a/basic/source/runtime/stdobj.cxx +++ b/basic/source/runtime/stdobj.cxx @@ -31,7 +31,7 @@ // enough, if not we need to increase the size of nArgs member in the Methods // struct below. // note: the limitation of 63 args is only for RTL functions defined here and -// does NOT impose a limit on User defined procedures ). This changes is to +// does NOT impose a limit on User defined procedures ). This change is to // allow us space for a flag to denylist some functions in vba mode namespace { @@ -772,9 +772,9 @@ constexpr Method aMethods[] = { arg(u"number", SbxDOUBLE), { u"SLN", SbxDOUBLE, 3 | FUNCTION_ | COMPATONLY_, SbRtl_SLN }, - arg(u"Cost", SbxDOUBLE), - arg(u"Double", SbxDOUBLE), - arg(u"Life", SbxDOUBLE), + arg(u"Cost", SbxDOUBLE), + arg(u"Salvage", SbxDOUBLE), + arg(u"Life", SbxDOUBLE), { u"SYD", SbxDOUBLE, 4 | FUNCTION_ | COMPATONLY_, SbRtl_SYD }, arg(u"Cost", SbxDOUBLE), @@ -983,7 +983,7 @@ SbiStdObject::~SbiStdObject() // Finding an element: // It runs linearly through the method table here until an -// adequate method is has been found. Because of the bits in +// adequate method is found. Because of the bits in // the nArgs-field the adequate instance of an SbxObjElement // is created then. If the method/property hasn't been found, // return NULL without error code, so that a whole chain of diff --git a/basic/source/sbx/sbxint.cxx b/basic/source/sbx/sbxint.cxx index 396de01037ed..95b5db9418b3 100644 --- a/basic/source/sbx/sbxint.cxx +++ b/basic/source/sbx/sbxint.cxx @@ -136,6 +136,8 @@ template <> void assignTo(SbxDecimal& dest, double n) { dest.setWithOver template <> void assignTo(SbxDecimal& dest, float n) { dest.setWithOverflow(n); } template void assignTo(OUString& dest, I n, bool) { dest = OUString::number(n); } +// tdf#171370: a character stringifies to itself, not to its numeric code +void assignTo(OUString& dest, sal_Unicode n, bool) { dest = OUString(n); } void assignTo(OUString& dest, double n, bool bCoreString) { // tdf#107953 - show 17 significant digits diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx index 839135d8f387..a1535c5dd1fb 100644 --- a/basic/source/sbx/sbxscan.cxx +++ b/basic/source/sbx/sbxscan.cxx @@ -282,7 +282,7 @@ ErrCode SbxValue::ScanNumIntnl( const OUString& rSrc, double& nVal, bool bSingle return nRetError; } -// The number is prepared unformattedly with the given number of +// The number is prepared without formatting with the given number of // NK-positions. A leading minus is added if applicable. // This routine is public because it's also used by the Put-functions // in the class SbxImpSTRING. @@ -401,7 +401,7 @@ void BasicFormatNum(double d, const OUString& rFmt, OUString& rRes) sal_Unicode c1000 = rData.getNumThousandSep()[0]; const OUString& aCurrencyStrg = rData.getCurrSymbol(); - // initialize the Basic-formater help object: + // initialize the Basic-formatter help object: // get resources for predefined output // of the Format()-command, e. g. for "On/Off" OUString aOnStrg = BasResId(STR_BASICKEY_FORMAT_ON); diff --git a/basic/source/sbx/sbxstr.cxx b/basic/source/sbx/sbxstr.cxx index 4e447bb600bb..7e04d802ad14 100644 --- a/basic/source/sbx/sbxstr.cxx +++ b/basic/source/sbx/sbxstr.cxx @@ -26,7 +26,7 @@ #include #include -// The conversion of an item onto String was handled via the Put-Methods +// The conversion of an item to a String was handled via the Put-Methods // of the several data types to avoid duplicated code. OUString ImpGetString( const SbxValues* p ) @@ -262,7 +262,7 @@ void ImpPutString( SbxValues* p, const OUString* n ) } -// Convert string to an array of bytes, preserving unicode (2bytes per character) +// Convert string to an array of bytes, preserving unicode (2 bytes per character) SbxArray* StringToByteArray(const OUString& rStr) { sal_Int32 nArraySize = rStr.getLength() * 2; @@ -298,7 +298,7 @@ SbxArray* StringToByteArray(const OUString& rStr) return pArray; } -// Convert an array of bytes to string (2bytes per character) +// Convert an array of bytes to string (2 bytes per character) OUString ByteArrayToString(SbxArray* pArr) { sal_uInt32 nCount = pArr->Count(); diff --git a/basic/source/uno/namecont.cxx b/basic/source/uno/namecont.cxx index 33ac0dee21af..e116b65dcb35 100644 --- a/basic/source/uno/namecont.cxx +++ b/basic/source/uno/namecont.cxx @@ -65,6 +65,8 @@ #include #include #include +#include +#include #include #include @@ -93,6 +95,21 @@ using com::sun::star::uno::Reference; // #i34411: Flag for error handling during migration static bool GbMigrationSuppressErrors = false; +#ifndef NDEBUG +namespace +{ +// The name->value map and the insertion-order vector are redundant views of the +// same set of names; verify they list exactly the same names, once each. +bool mapAndOrderConsistent(const std::unordered_map& rMap, + const std::vector& rOrder) +{ + if (rMap.size() != rOrder.size()) + return false; + return std::all_of(rMap.begin(), rMap.end(), [&rOrder](const auto& rEntry) + { return std::find(rOrder.begin(), rOrder.end(), rEntry.first) != rOrder.end(); }); +} +} +#endif // Implementation class NameContainer @@ -120,7 +137,8 @@ Any NameContainer::getByName( const OUString& aName ) Sequence< OUString > NameContainer::getElementNames() { - return comphelper::mapKeysToSequence(maMap); + // Return the names in insertion order. + return comphelper::containerToSequence(maNamesOrder); } sal_Bool NameContainer::hasByName( const OUString& aName ) @@ -150,7 +168,7 @@ void NameContainer::replaceByName(const OUString& aName, const Any& aElement, if (maContainerListeners.getLength(guard) > 0) { ContainerEvent aEvent; - aEvent.Source = mpxEventSource; + aEvent.Source = rOwner.getXWeak(); aEvent.Accessor <<= aName; aEvent.Element = aElement; aEvent.ReplacedElement = aOldElement; @@ -163,7 +181,7 @@ void NameContainer::replaceByName(const OUString& aName, const Any& aElement, if (maChangesListeners.getLength(guard) > 0) { ChangesEvent aEvent; - aEvent.Source = mpxEventSource; + aEvent.Source = rOwner.getXWeak(); aEvent.Base <<= aEvent.Source; aEvent.Changes = { { Any(aName), aElement, aOldElement } }; maChangesListeners.notifyEach(guard, &XChangesListener::changesOccurred, aEvent); @@ -179,13 +197,16 @@ void NameContainer::insertNoCheck(const OUString& aName, const Any& aElement, throw IllegalArgumentException(u"types do not match"_ustr, rOwner, 2); } + assert(!maMap.contains(aName) && "insertNoCheck: name already present"); maMap[aName] = aElement; + maNamesOrder.push_back(aName); + assert(mapAndOrderConsistent(maMap, maNamesOrder)); // Fire event if (maContainerListeners.getLength(guard) > 0) { ContainerEvent aEvent; - aEvent.Source = mpxEventSource; + aEvent.Source = rOwner.getXWeak(); aEvent.Accessor <<= aName; aEvent.Element = aElement; maContainerListeners.notifyEach(guard, &XContainerListener::elementInserted, aEvent); @@ -197,7 +218,7 @@ void NameContainer::insertNoCheck(const OUString& aName, const Any& aElement, if (maChangesListeners.getLength(guard) > 0) { ChangesEvent aEvent; - aEvent.Source = mpxEventSource; + aEvent.Source = rOwner.getXWeak(); aEvent.Base <<= aEvent.Source; aEvent.Changes = { { Any(aName), aElement, {} } }; maChangesListeners.notifyEach(guard, &XChangesListener::changesOccurred, aEvent); @@ -223,12 +244,14 @@ void NameContainer::removeByName(const OUString& aName, std::unique_locksecond; maMap.erase(aIt); + std::erase(maNamesOrder, aName); + assert(mapAndOrderConsistent(maMap, maNamesOrder)); // Fire event if (maContainerListeners.getLength(guard) > 0) { ContainerEvent aEvent; - aEvent.Source = mpxEventSource; + aEvent.Source = rOwner.getXWeak(); aEvent.Accessor <<= aName; aEvent.Element = aOldElement; maContainerListeners.notifyEach(guard, &XContainerListener::elementRemoved, aEvent); @@ -240,7 +263,7 @@ void NameContainer::removeByName(const OUString& aName, std::unique_lock 0) { ChangesEvent aEvent; - aEvent.Source = mpxEventSource; + aEvent.Source = rOwner.getXWeak(); aEvent.Base <<= aEvent.Source; aEvent.Changes = { { Any(aName), {}, // Element remains empty (meaning "replaced with nothing") @@ -2667,7 +2690,6 @@ void SAL_CALL SfxLibraryContainer::addContainerListener( const Reference< XConta { LibraryContainerMethodGuard aGuard( *this ); std::unique_lock guard(m_aMutex); - maNameContainer.setEventSource( getXWeak() ); maNameContainer.addContainerListener(xListener, guard); } @@ -3087,7 +3109,6 @@ void SfxLibrary::removeByName( const OUString& Name ) // Methods XContainer void SAL_CALL SfxLibrary::addContainerListener( const Reference< XContainerListener >& xListener ) { - maNameContainer.setEventSource( getXWeak() ); maNameContainer.addContainerListener(xListener, o3tl::temporary(std::unique_lock(m_aMutex))); } @@ -3099,7 +3120,6 @@ void SAL_CALL SfxLibrary::removeContainerListener( const Reference< XContainerLi // Methods XChangesNotifier void SAL_CALL SfxLibrary::addChangesListener( const Reference< XChangesListener >& xListener ) { - maNameContainer.setEventSource( getXWeak() ); maNameContainer.addChangesListener(xListener, o3tl::temporary(std::unique_lock(m_aMutex))); } diff --git a/basic/source/uno/scriptcont.cxx b/basic/source/uno/scriptcont.cxx index a12476a255e1..ee0c1ea45361 100644 --- a/basic/source/uno/scriptcont.cxx +++ b/basic/source/uno/scriptcont.cxx @@ -492,7 +492,7 @@ void SAL_CALL SfxScriptLibraryContainer::changeLibraryPassword( const OUString& if( !bStorage && !pImplLib->mbDoc50Password ) { - // Store application basic crypted + // Store application basic encrypted uno::Reference< embed::XStorage > xStorage; storeLibraries_Impl(xStorage, false, guard); bKillUnencryptedFiles = true; diff --git a/basic/source/util/sbutil.cxx b/basic/source/util/sbutil.cxx new file mode 100644 index 000000000000..221a0f2cbefb --- /dev/null +++ b/basic/source/util/sbutil.cxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * 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 + +#include + +namespace sb +{ +sal_Int32 searchEOL(std::u16string_view rStr, sal_Int32 fromIndex) +{ + size_t nPos = rStr.find_first_of(u"\r\n", fromIndex); + + if (nPos == std::u16string_view::npos) + return -1; + + if (rStr.substr(nPos).starts_with(u"\r\n")) + return nPos + 1; + else + return nPos; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/bean/com/sun/star/comp/beans/OOoBean.java b/bean/com/sun/star/comp/beans/OOoBean.java index 05b5288ea528..4d55ec21fab3 100644 --- a/bean/com/sun/star/comp/beans/OOoBean.java +++ b/bean/com/sun/star/comp/beans/OOoBean.java @@ -440,7 +440,7 @@ public class OOoBean If no document is loaded and the instance is added to a Java container that is showing, then this method needs not to be called. If later one of the methods - {@link #loadFromURL loadFromURL}, {@link #loadFromStream loadFromStream1}, + {@link #loadFromURL loadFromURL}, {@link #loadFromStream loadFromStream}, or {@link #loadFromByteArray loadFromByteArray} is called, then the document is automatically displayed. @@ -787,7 +787,7 @@ public class OOoBean /** Stores a document to the given URL.

- Due due a bug (50651) calling this method may cause the office to crash, + Due to a bug (50651) calling this method may cause the office to crash, when at the same time the office writes a backup of the document. This bug also affects {@link #storeToByteArray storeToByteArray} and {@link #storeToStream storeToStream}. The workaround diff --git a/bin/check-sid-slots.py b/bin/check-sid-slots.py new file mode 100755 index 000000000000..aa7cff88bc25 --- /dev/null +++ b/bin/check-sid-slots.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +# +# 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/. +# +# the main idea is from an Hossein's script in https://gerrit.libreoffice.org/c/core/+/207697 +# then I tried to improve it a bit with Chatgpt GPT-5.5 + +# Example to call the script +# ./bin/check-sid-slots.py SID_SVX_START + +# Here's the initial Hossein's command: + +r''' +git grep -h "SID_SFX_START[ ]*+" "*.hrc" | grep -Ev '^\s*//' \ + | awk -F\( {'print $2'} | awk -F\) {'print $1'} \ + | awk '{gsub(/^ +| +$/,"")}1' | sort | uniq -c | grep " 2" +''' + + +import collections +import re +import subprocess +import sys + + +def check_sid(sid_type): + try: + result = subprocess.run( + ["git", "grep", "-h", f"{sid_type}", "*.hrc"], + check=True, + capture_output=True, + text=True, + ) + except subprocess.CalledProcessError as e: + print(e.stderr, file=sys.stderr) + return 1 + + slots = collections.defaultdict(list) + + for line in result.stdout.splitlines(): + # Remove C++ comments + code = line.split("//", 1)[0].strip() + + if not code: + continue + + # Ignore comments of this type: + # # SID_SVX_START + 123 + # but keep real #define + if re.match(r"^#\s+", code): + continue + + # Boundaries are not slots which are used + if "FIRSTFREE" in code: + continue + + # Only keep : + # SID_SVX_START + 123 + # but not : + # SID_SVX_START + 123 + 1 + match = re.search( + re.escape(sid_type) + r"\s*\+\s*(\d+)(?!\s*\+)", + code, + ) + + if match: + slot = int(match.group(1)) + slots[slot].append(code) + + found = False + + for slot, lines in sorted(slots.items()): + if len(lines) > 1: + found = True + print(f"Duplicate {sid_type} + {slot}:") + for line in lines: + print(f" {line}") + print() + + return 1 if found else 0 + +def main(): + for sid_type in sys.argv[1:]: + check_sid(sid_type) + +if __name__ == "__main__": + sys.exit(main()) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/bin/checkExternalLibraries.py b/bin/checkExternalLibraries.py index 9b29a5982215..9f262e316454 100755 --- a/bin/checkExternalLibraries.py +++ b/bin/checkExternalLibraries.py @@ -35,7 +35,8 @@ libraryIds = { "libwebp": 1, "libffi": 1, "xz": 1, - "zstd": 1 + "zstd": 1, + "brotli": 1 } libraryNames = { @@ -53,18 +54,18 @@ libraryNames = { "liborcus": "orcus", "ltm": "libtommath", "clucene-core": "clucene-core", - "lp_solve": "lp_solve", "hsqldb": "hsqldb", "y-crdt": "y-crdt", "sqlite": "sqlite", "reemkufi": "aliftype-reem-kufi-fonts", "culmus": "culmus-fonts", + "quickjs": "quickjs-ng", } def get_current_version(libName): if "sqlite" in libName: # 3XXYYZZ -> 3.X.Y.Z - s = re.search(r"(\d{7})", libName ) + s = re.search(r"(\d{7})", libName) if s: num = str(s.group(1)) return parse("{}.{}.{}.{}".format(num[0], num[1:3], num[3:5], num[6:7])) @@ -78,8 +79,8 @@ def get_current_version(libName): return Version("0.0.0") def get_library_list(fileName): - inputProces = "include " + fileName + "\nall:\n\t$(foreach v,$(sort $(filter %TARBALL,$(.VARIABLES))),$(info export $(v)=$($(v))))" - process = subprocess.run(["make", "-q", "-f", "-"], input=bytes(inputProces, 'UTF-8'), stdout=subprocess.PIPE) + inputProcess = "include " + fileName + "\nall:\n\t$(foreach v,$(sort $(filter %TARBALL,$(.VARIABLES))),$(info export $(v)=$($(v))))" + process = subprocess.run(["make", "-q", "-f", "-"], input=bytes(inputProcess, 'UTF-8'), stdout=subprocess.PIPE) libraryList = [] for lib in process.stdout.splitlines(): @@ -106,6 +107,17 @@ def get_library_list(fileName): libraryList.append(libraryName.lower()) return libraryList +def get_language_subtag_registry(libName): + url = "https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry" + pattern = r"\d{4}-\d{2}-\d{2}" + currentVersion = re.search(pattern, libName).group(0).replace("-", ".") + res = requests.get(url) + if res.status_code != 200: + return Version("0.0.0"), "", Version("0.0.0") + latestVersion = re.search(pattern, next(res.iter_lines()).decode("utf-8")).group(0).replace("-", ".") + + return Version(latestVersion), url, Version(currentVersion) + def get_latest_version(libNameOrig): libName = libNameOrig bFound = False @@ -170,10 +182,10 @@ if __name__ == '__main__': for lib in libraryList: if lib.startswith("language-subtag-registry"): - print("CHECK https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry") - continue - latestVersion, website = get_latest_version(lib) - currentVersion = get_current_version(lib) + latestVersion, website, currentVersion = get_language_subtag_registry(lib) + else: + latestVersion, website = get_latest_version(lib) + currentVersion = get_current_version(lib) if latestVersion == Version("0.0.0"): print("FAIL: " + lib + " not found in https://release-monitoring.org") elif currentVersion == Version("0.0.0"): diff --git a/bin/find-can-be-private-symbols.functions.results b/bin/find-can-be-private-symbols.functions.results index 68e63af4ba4f..c663ec28e974 100644 --- a/bin/find-can-be-private-symbols.functions.results +++ b/bin/find-can-be-private-symbols.functions.results @@ -543,7 +543,6 @@ FixedHyperlink::set_property(rtl::OUString const&, rtl::OUString const&) FixedLine::ApplySettings(OutputDevice&) FixedLine::DataChanged(DataChangedEvent const&) FixedLine::Draw(OutputDevice*, Point const&, SystemTextColorFlags) -FixedLine::DumpAsPropertyTree(tools::JsonWriter&) FixedLine::FillLayoutData() const FixedLine::GetCanonicalFont(StyleSettings const&) const FixedLine::GetCanonicalTextColor(StyleSettings const&) const @@ -666,7 +665,6 @@ FontSizeBox::format_number(int) const FontSizeNames::Name2Size(std::basic_string_view >) const FontSizeNames::Size2Name(int) const FormattedField::Down() -FormattedField::DumpAsPropertyTree(tools::JsonWriter&) FormattedField::EventNotify(NotifyEvent&) FormattedField::First() FormattedField::GetUITestFactory() const @@ -1313,7 +1311,6 @@ MenuBarUpdateIconManager::SetShowMenuIcon(bool) MenuBarUpdateIconManager::~MenuBarUpdateIconManager() MenuButton::Activate() MenuButton::CancelMenu() -MenuButton::DumpAsPropertyTree(tools::JsonWriter&) MenuButton::ExecuteMenu() MenuButton::GetUITestFactory() const MenuButton::InPopupMode() const @@ -1547,7 +1544,6 @@ PptSlidePersistList::PptSlidePersistList() PptSlidePersistList::~PptSlidePersistList() ProcessData::NotifyFreeObj(SdrObject*) ProgressBar::DataChanged(DataChangedEvent const&) -ProgressBar::DumpAsPropertyTree(tools::JsonWriter&) ProgressBar::GetOptimalSize() const ProgressBar::Paint(OutputDevice&, tools::Rectangle const&) ProgressBar::Resize() @@ -3596,7 +3592,6 @@ SfxDispatcher::GetSlot(rtl::OUString const&) SfxDispatcher::HideUI(bool) SfxDispatcher::IsActive(SfxShell const&) SfxDispatcher::IsAppDispatcher() const -SfxDispatcher::IsCommandAllowedInLokReadOnlyViewMode(rtl::OUString) SfxDispatcher::IsFlushed() const SfxDispatcher::PostMsgHandler(std::unique_ptr >) SfxDispatcher::SfxDispatcher() @@ -6018,7 +6013,6 @@ SvHeaderTabListBox::CreateAccessibleCell(int, unsigned short) SvHeaderTabListBox::CreateAccessibleColumnHeader(unsigned short) SvHeaderTabListBox::CreateAccessibleControl(int) SvHeaderTabListBox::CreateAccessibleRowHeader(int) -SvHeaderTabListBox::DumpAsPropertyTree(tools::JsonWriter&) SvHeaderTabListBox::FillAccessibleStateSet(long&, AccessibleBrowseBoxObjType) const SvHeaderTabListBox::FillAccessibleStateSetForCell(long&, int, unsigned short) const SvHeaderTabListBox::GetAccessible() @@ -6184,7 +6178,6 @@ SvStream::FlushData() SvStream::GetData(void*, unsigned long) SvStream::PutData(void const*, unsigned long) SvStream::SeekPos(unsigned long) -SvTabListBox::DumpAsPropertyTree(tools::JsonWriter&) SvTabListBox::GetCellText(unsigned int, unsigned short) const SvTabListBox::GetChildOnPos(SvTreeListEntry*, unsigned int, unsigned int&) const SvTabListBox::GetEntryOnPos(unsigned int) const @@ -8195,9 +8188,6 @@ SwFileNameField::Copy() const SwFileNameField::ExpandImpl(SwRootFrame const*) const SwFileNameField::PutValue(com::sun::star::uno::Any const&, unsigned short) SwFileNameField::QueryValue(com::sun::star::uno::Any&, unsigned short) const -SwFilterOptions::GetValues(unsigned short, char const**, unsigned long*) -SwFilterOptions::ImplCommit() -SwFilterOptions::Notify(com::sun::star::uno::Sequence const&) SwFltAnchor::Clone(SfxItemPool*) const SwFltAnchor::SetFrameFormat(SwFrameFormat*) SwFltAnchor::SwFltAnchor(SwFltAnchor const&) @@ -9534,13 +9524,11 @@ VclButtonBox::addSpacing(Size const&, unsigned short) const VclButtonBox::calculatePrimarySecondaryRequisitions() const VclContainer::setLayoutPosSize(vcl::Window&, Point const&, Size const&) VclDrawingArea::DeleteSurroundingText(Selection const&) -VclDrawingArea::DumpAsPropertyTree(tools::JsonWriter&) VclDrawingArea::GetSurroundingText() const VclDrawingArea::GetSurroundingTextSelection() const VclDrawingArea::GetUITestFactory() const VclDrawingArea::RequestHelp(HelpEvent const&) VclDrawingArea::StartDrag(signed char, Point const&) -VclGrid::DumpAsPropertyTree(tools::JsonWriter&) VclGrid::calculateRequisition() const VclGrid::calculateRequisitionForSpacings(int, int) const VclGrid::setAllocation(Size const&) @@ -11098,7 +11086,6 @@ com_sun_star_comp_extensions_FileHandler com_sun_star_comp_extensions_LoggerPool com_sun_star_comp_extensions_PlainTextFormatter com_sun_star_comp_extensions_SimpleTextFormatter -com_sun_star_comp_rendering_SimpleCanvas com_sun_star_comp_task_OfficeRestartManager com_sun_star_comp_util_OfficeInstallationDirectories com_sun_star_comp_xmlscript_XMLBasicExporter @@ -14921,7 +14908,6 @@ sfx2::SafeMode::getFilePath(rtl::OUString const&) sfx2::SfxNotebookBar::CloseMethod(SystemWindow*) sfx2::SfxNotebookBar::RemoveCurrentLOKWrapper() sfx2::SfxNotebookBar::RemoveListeners(SystemWindow const*) -sfx2::SfxNotebookBar::ResetActiveToolbarModeToDefault(vcl::EnumContext::Application) sfx2::SfxNotebookBar::ShowMenubar(SfxViewFrame const*, bool) sfx2::SfxNotebookBar::ShowMenubar(bool) sfx2::SfxNotebookBar::StateMethod(SystemWindow*, com::sun::star::uno::Reference const&, std::basic_string_view >, bool) diff --git a/bin/find-german-comments b/bin/find-german-comments index de1ed9481fca..a219ddf98d26 100755 --- a/bin/find-german-comments +++ b/bin/find-german-comments @@ -316,7 +316,6 @@ class Parser: "sax" : 1, "sc" : 1, "scaddins" : 1, - "sccomp" : 1, "scripting" : 1, "sd" : 1, "sdext" : 1, diff --git a/bin/find-mergedlib-can-be-private-symbols.functions.results b/bin/find-mergedlib-can-be-private-symbols.functions.results index ec603f82ca4c..da284d38fed4 100644 --- a/bin/find-mergedlib-can-be-private-symbols.functions.results +++ b/bin/find-mergedlib-can-be-private-symbols.functions.results @@ -3767,7 +3767,6 @@ SfxDispatcher::GetSlot(rtl::OUString const&) SfxDispatcher::HideUI(bool) SfxDispatcher::IsActive(SfxShell const&) SfxDispatcher::IsAppDispatcher() const -SfxDispatcher::IsCommandAllowedInLokReadOnlyViewMode(rtl::OUString) SfxDispatcher::IsFlushed() const SfxDispatcher::PostMsgHandler(std::unique_ptr >) SfxDispatcher::SfxDispatcher() @@ -8620,9 +8619,6 @@ SwFileNameField::Copy() const SwFileNameField::ExpandImpl(SwRootFrame const*) const SwFileNameField::PutValue(com::sun::star::uno::Any const&, unsigned short) SwFileNameField::QueryValue(com::sun::star::uno::Any&, unsigned short) const -SwFilterOptions::GetValues(unsigned short, char const**, unsigned long*) -SwFilterOptions::ImplCommit() -SwFilterOptions::Notify(com::sun::star::uno::Sequence const&) SwFltAnchor::Clone(SfxItemPool*) const SwFltAnchor::SetFrameFormat(SwFrameFormat*) SwFltAnchor::SwFltAnchor(SwFltAnchor const&) @@ -10047,13 +10043,11 @@ VclContainer::getLayoutRequisition(vcl::Window const&) VclContainer::setLayoutAllocation(vcl::Window&, Point const&, Size const&) VclContainer::setLayoutPosSize(vcl::Window&, Point const&, Size const&) VclDrawingArea::DeleteSurroundingText(Selection const&) -VclDrawingArea::DumpAsPropertyTree(tools::JsonWriter&) VclDrawingArea::GetSurroundingText() const VclDrawingArea::GetSurroundingTextSelection() const VclDrawingArea::GetUITestFactory() const VclDrawingArea::RequestHelp(HelpEvent const&) VclDrawingArea::StartDrag(signed char, Point const&) -VclGrid::DumpAsPropertyTree(tools::JsonWriter&) VclGrid::calculateRequisition() const VclGrid::calculateRequisitionForSpacings(int, int) const VclGrid::setAllocation(Size const&) @@ -10922,7 +10916,7 @@ basegfx::B2DHomMatrix::scale(basegfx::B2DTuple const&) basegfx::B2DHomMatrix::set3x2(double, double, double, double, double, double) basegfx::B2DPolyPolygon::addOrReplaceSystemDependentDataInternal(std::shared_ptr&) const basegfx::B2DPolyPolygon::getDefaultAdaptiveSubdivision() const -basegfx::B2DPolyPolygon::getSystemDependantDataInternal(unsigned long) const +basegfx::B2DPolyPolygon::getSystemDependentDataInternal(unsigned long) const basegfx::B2DPolyPolygon::hasDoublePoints() const basegfx::B2DPolyPolygon::makeUnique() basegfx::B2DPolyRange::B2DPolyRange(basegfx::B2DPolyRange const&) @@ -10931,7 +10925,7 @@ basegfx::B2DPolyRange::transform(basegfx::B2DHomMatrix const&) basegfx::B2DPolygon::addOrReplaceSystemDependentDataInternal(std::shared_ptr&) const basegfx::B2DPolygon::getNextControlVector(unsigned int) const basegfx::B2DPolygon::getPrevControlVector(unsigned int) const -basegfx::B2DPolygon::getSystemDependantDataInternal(unsigned long) const +basegfx::B2DPolygon::getSystemDependentDataInternal(unsigned long) const basegfx::B2DPolygon::hasDoublePoints() const basegfx::B2DPolygon::makeUnique() basegfx::B2DRange::getUnitB2DRange() @@ -11333,7 +11327,6 @@ com_sun_star_comp_extensions_FileHandler com_sun_star_comp_extensions_LoggerPool com_sun_star_comp_extensions_PlainTextFormatter com_sun_star_comp_extensions_SimpleTextFormatter -com_sun_star_comp_rendering_SimpleCanvas com_sun_star_comp_task_OfficeRestartManager com_sun_star_comp_util_OfficeInstallationDirectories com_sun_star_comp_xmlscript_XMLBasicExporter @@ -15169,7 +15162,6 @@ sfx2::SfxNotebookBar::CloseMethod(SystemWindow*) sfx2::SfxNotebookBar::ReloadNotebookBar(std::basic_string_view >) sfx2::SfxNotebookBar::RemoveCurrentLOKWrapper() sfx2::SfxNotebookBar::RemoveListeners(SystemWindow const*) -sfx2::SfxNotebookBar::ResetActiveToolbarModeToDefault(vcl::EnumContext::Application) sfx2::SfxNotebookBar::ShowMenubar(SfxViewFrame const*, bool) sfx2::SfxNotebookBar::ShowMenubar(bool) sfx2::SfxNotebookBar::StateMethod(SystemWindow*, com::sun::star::uno::Reference const&, std::basic_string_view >, bool) diff --git a/bin/gen-boost-headers b/bin/gen-boost-headers index 50e51ebfd0b4..e4e223402119 100755 --- a/bin/gen-boost-headers +++ b/bin/gen-boost-headers @@ -62,7 +62,9 @@ cat <(cd ${SRCDIR} && git grep -h '^# *include') \ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Woverloaded-virtual" #include_next <${HEADER}> #pragma GCC diagnostic pop _EOF diff --git a/bin/oss-fuzz-build.sh b/bin/oss-fuzz-build.sh index c7c5133bbf01..12494b1255a3 100755 --- a/bin/oss-fuzz-build.sh +++ b/bin/oss-fuzz-build.sh @@ -21,7 +21,9 @@ echo git: `git -C $SRC/libreoffice log -1 --pretty=reference` #shuffle CXXFLAGS -stdlib=libc++ arg into CXX as well because we use #the CXX as the linker and need to pass -stdlib=libc++ to build -export CXX="$CXX -stdlib=libc++ -fsanitize-blacklist=$SRC/libreoffice/bin/sanitize-excludelist.txt" +#enable libc++ fast hardening so an out-of-range operator[] aborts instead +#of reading adjacent live memory that the redzone sanitizers don't flag +export CXX="$CXX -stdlib=libc++ -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST -fsanitize-blacklist=$SRC/libreoffice/bin/sanitize-excludelist.txt" export CXX_FOR_BUILD="$CXX" export CC="$CC -fsanitize-blacklist=$SRC/libreoffice/bin/sanitize-excludelist.txt" export CC_FOR_BUILD="$CC" @@ -69,7 +71,7 @@ EOF done popd -#starting corpuses +#starting corpora for zip_file in $SRC/*_seed_corpus.zip; do cp $zip_file $OUT done diff --git a/bin/oss-fuzz-setup.sh b/bin/oss-fuzz-setup.sh index caddb5ef9a8a..f9e19d537e60 100755 --- a/bin/oss-fuzz-setup.sh +++ b/bin/oss-fuzz-setup.sh @@ -95,17 +95,24 @@ curl --no-progress-meter -S \ -C - -O https://raw.githubusercontent.com/google/fuzzing/master/dictionaries/webp.dict \ -C - -O https://raw.githubusercontent.com/google/fuzzing/master/dictionaries/zip.dict \ -C - -O https://raw.githubusercontent.com/google/fuzzing/master/dictionaries/mathml.dict +# Every backslash in rtf.dict stands for the backslash that starts an RTF control +# word, and libFuzzer wants each one written as a pair. A few entries are written +# with a single backslash, which libFuzzer rejects. First turn every run of +# backslashes into one backslash, then write each one as a pair. +sed -i -e 's/\\\\*/\\/g' rtf.dict +sed -i -e 's/\\/\\\\/g' rtf.dict # build our own fuzz dict for odf, following the pattern of svg.dict echo "# Keywords taken from libreoffice/schema/odf1.3/OpenDocument-v1.3-schema.rng" > odf.dict +echo "# and libreoffice/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng" >> odf.dict echo "# tags" >> odf.dict -grep "rng:element name=" libreoffice/schema/odf1.3/OpenDocument-v1.3-schema.rng | sed 's#]*$##' >> odf.dict +grep -h "rng:element name=" libreoffice/schema/odf1.3/OpenDocument-v1.3-schema.rng libreoffice/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng | sed -n 's#.*> odf.dict echo "# attributes " >> odf.dict -grep "rng:attribute name=" libreoffice/schema/odf1.3/OpenDocument-v1.3-schema.rng | sed 's#]*$##' >> odf.dict +grep -h "rng:attribute name=" libreoffice/schema/odf1.3/OpenDocument-v1.3-schema.rng libreoffice/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng | sed -n 's#.*> odf.dict echo "# attributes' values" >> odf.dict -grep "rng:value" libreoffice/schema/odf1.3/OpenDocument-v1.3-schema.rng | sed 's##"#;s##"#;s#^[[:blank:]]*##;s#[[:blank:]>]*$##' | sort | uniq >> odf.dict +grep -h "rng:value" libreoffice/schema/odf1.3/OpenDocument-v1.3-schema.rng libreoffice/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng | sed -n 's#.*\([^<]*\).*#"\1"#p' | sort | uniq >> odf.dict -#fuzzing corpuses -#afl jpeg, gif, bmp, png, webp +# fuzzing corpora +# afl jpeg, gif, bmp, png, webp curl --no-progress-meter -S -C - -O https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz mkdir -p afl-testcases && cd afl-testcases/ && tar xf $SRC/afl_testcases.tgz && cd .. && \ zip -q $SRC/jpgfuzzer_seed_corpus.zip afl-testcases/jpeg*/full/images/* && \ @@ -115,16 +122,18 @@ mkdir -p afl-testcases && cd afl-testcases/ && tar xf $SRC/afl_testcases.tgz && zip -q $SRC/webpfuzzer_seed_corpus.zip afl-testcases/webp*/full/images/* # TTF/OTF/SFT -# using github's svn view to use svn export as a hack to just export part of the git repo -# svn support turned off now: https://github.blog/2023-01-20-sunsetting-subversion-support/ -# and git sparse checkout is a total pain -#svn export --force -q https://github.com/khaledhosny/ots/trunk/tests/fonts $SRC/sample-sft-fonts/ots -#svn export --force -q https://github.com/unicode-org/text-rendering-tests/trunk/fonts/ $SRC/sample-sft-fonts/unicode-org -#svn export --force -q https://github.com/harfbuzz/harfbuzz/trunk/test/shape/data/in-house/fonts $SRC/sample-sft-fonts/harfbuzz mkdir -p $SRC/sample-sft-fonts/adobe curl --no-progress-meter -S \ -C - -o $SRC/sample-sft-fonts/adobe/AdobeVFPrototype.otf https://github.com/adobe-fonts/adobe-variable-font-prototype/releases/download/1.005a/AdobeVFPrototype.otf -zip -qr $SRC/sftfuzzer_seed_corpus.zip $SRC/sample-sft-fonts +git clone --depth 1 --filter=blob:none --sparse https://github.com/khaledhosny/ots.git && \ + cd ots && git sparse-checkout set tests/fonts && cd .. && \ + cp -r ots/tests/fonts $SRC/sample-sft-fonts/ots && rm -rf ots +git clone --depth 1 --filter=blob:none --sparse https://github.com/harfbuzz/harfbuzz.git && \ + cd harfbuzz && git sparse-checkout set test/shape/data/in-house/fonts && cd .. && \ + cp -r harfbuzz/test/shape/data/in-house/fonts $SRC/sample-sft-fonts/harfbuzz && rm -rf harfbuzz +# exclude very large fonts that are slow to process under sanitizers +find $SRC/sample-sft-fonts -size +1M -delete +zip -qr $SRC/eotfuzzer_seed_corpus.zip $SRC/sample-sft-fonts # PDF git clone --depth 1 https://github.com/strongcourage/fuzzing-corpus.git && \ @@ -183,7 +192,6 @@ cp fodtfuzzer_seed_corpus.zip fodt2pdffuzzer_seed_corpus.zip cp rtffuzzer_seed_corpus.zip rtf2pdffuzzer_seed_corpus.zip cp fodsfuzzer_seed_corpus.zip fods2xlsfuzzer_seed_corpus.zip cp htmlfuzzer_seed_corpus.zip schtmlfuzzer_seed_corpus.zip -cp sftfuzzer_seed_corpus.zip eotfuzzer_seed_corpus.zip cp pdffuzzer_seed_corpus.zip pdf2fodgfuzzer_seed_corpus.zip echo end downloading dependencies at `date -u` diff --git a/bin/ui-rules-enforcer.py b/bin/ui-rules-enforcer.py index da5e35f6e017..3e4fa505ca6c 100755 --- a/bin/ui-rules-enforcer.py +++ b/bin/ui-rules-enforcer.py @@ -623,6 +623,52 @@ def enforce_menuitem_id(current): if not child.attrib.get("id"): raise Exception(sys.argv[1] + ': menu item does not have an id set' , child.text) +def collect_treeview_cell_renderers(element): + renderers = [] + for child in element: + child_class = child.get("class") + if child_class and child_class.startswith("GtkCellRenderer"): + renderers.append(child_class) + renderers = renderers + collect_treeview_cell_renderers(child) + return renderers + +def collect_treeview_columns(element): + """Returns a nested list, containing a list of renderers used in each treeview column.""" + columns = [] + for child in element: + child_class = child.get("class") + if child_class and child_class == "GtkTreeViewColumn": + columns.append(collect_treeview_cell_renderers(child)) + columns = columns + collect_treeview_columns(child) + return columns + +def enforce_treeview_column_rules(current): + # skip "vcl/uiconfig/ui/combobox.ui", only used by gtk3 vcl plugin for a custom combobox implementation + if sys.argv[1] == "vcl/uiconfig/ui/combobox.ui": + return + + if not current.get("class") == "GtkTreeView": + for child in current: + enforce_treeview_column_rules(child) + return + + columns = collect_treeview_columns(current) + # Ensure that the treeview has at least one column + if not columns: + raise Exception(sys.argv[1] + ": treeview has no columns: ", current.attrib.get("id")) + + # If the first column makes use of special toggle and pixbuf columns + # to be accessed with column index -1 at the same time (see also doc in + # GtkInstanceTreeView ctor), make sure that the toggle column comes first, + # to match behavior of the vcl implementation + if len(columns[0]) >= 2 and columns[0][0] == "GtkCellRendererPixbuf" and columns[0][1] == "GtkCellRendererToggle": + raise Exception(sys.argv[1] + ": treeview has special toggle and pixbuf columns/renderers in wrong order: ", current.attrib.get("id")) + + # ensure that column don't contain multiple cell renderers of the same type + for col in columns: + if len(col) != len(set(col)): + raise Exception(sys.argv[1] + ": Multiple cell renderers of the same type not supported in one column: ", current.attrib.get("id")) + with open(sys.argv[1], encoding="utf-8") as f: header = f.readline() f.seek(0) @@ -656,6 +702,7 @@ remove_expander_spacing(root) enforce_menubutton_indicator_consistency(root) enforce_label_child_is_label(root) enforce_menuitem_id(root) +enforce_treeview_column_rules(root) enforce_active_in_group_consistency(root) enforce_entry_text_column_id_column_for_gtkcombobox(root) remove_entry_shadow_type(root) diff --git a/binaryurp/source/unmarshal.cxx b/binaryurp/source/unmarshal.cxx index 10eb4e780f3f..0bf97d34fdb5 100644 --- a/binaryurp/source/unmarshal.cxx +++ b/binaryurp/source/unmarshal.cxx @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -317,13 +318,9 @@ BinaryAny Unmarshal::readValue(css::uno::TypeDescription const & type) { type.makeComplete(); typelib_EnumTypeDescription * etd = reinterpret_cast< typelib_EnumTypeDescription * >(type.get()); - bool bFound = false; - for (sal_Int32 i = 0; i != etd->nEnumValues; ++i) { - if (etd->pEnumValues[i] == v) { - bFound = true; - break; - } - } + bool bFound = std::any_of( + etd->pEnumValues, etd->pEnumValues + etd->nEnumValues, + [v](sal_Int32 nValue) { return nValue == v; }); if (!bFound) { throw css::io::IOException( u"binaryurp::Unmarshal: unknown enum value"_ustr); diff --git a/bridges/source/cpp_uno/gcc3_ios/unwind-cxx.h b/bridges/source/cpp_uno/gcc3_ios/unwind-cxx.h index 762053062259..9bc668f4e0f6 100644 --- a/bridges/source/cpp_uno/gcc3_ios/unwind-cxx.h +++ b/bridges/source/cpp_uno/gcc3_ios/unwind-cxx.h @@ -28,7 +28,7 @@ // the GNU General Public License. // This is derived from the C++ ABI for IA-64. Where we diverge -// for cross-architecture compatibility are noted with "@@@". +// for cross-architecture compatibility is noted with "@@@". #pragma once @@ -43,7 +43,6 @@ typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); -typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); #if !defined __IPHONE_16_4 || __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_16_4 typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__))); @@ -117,7 +116,7 @@ struct __cxa_exception #if !__LP64__ // This is a new field to support C++ 0x exception_ptr. // For binary compatibility it is placed where the compiler - // previously adding padded to 64-bit align unwindHeader. + // previously added padding to 64-bit align unwindHeader. size_t referenceCount; #endif diff --git a/bridges/source/cpp_uno/gcc3_linux_hppa/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_hppa/uno2cpp.cxx index 43e9aabac8b1..958ae4063e57 100644 --- a/bridges/source/cpp_uno/gcc3_linux_hppa/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_hppa/uno2cpp.cxx @@ -220,7 +220,7 @@ static void cpp_call( static_assert(sizeof(void *) == sizeof(sal_Int32), "### unexpected size!"); // args void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); - // indices of values this have to be converted (interface conversion cpp<=>uno) + // indices of values that have to be converted (interface conversion cpp<=>uno) sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams); // type descriptions for reconversions typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/call.s b/bridges/source/cpp_uno/gcc3_linux_x86-64/call.s index e7ff106244a8..4228389e0eca 100644 --- a/bridges/source/cpp_uno/gcc3_linux_x86-64/call.s +++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/call.s @@ -50,7 +50,7 @@ privateSnippetExecutor: movsd %xmm7, -8(%rbp) leaq -144(%rbp), %r9 # 6th param: sal_uInt64 * pRegisterReturn - leaq 16(%rbp), %r8 # 5rd param: void ** ovrflw + leaq 16(%rbp), %r8 # 5th param: void ** ovrflw leaq -64(%rbp), %rcx # 4th param: void ** fpreg leaq -112(%rbp), %rdx # 3rd param: void ** gpreg movl -148(%rbp), %esi # 2nd param: sal_int32 nVtableOffset diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx index 2c7332a16a2b..3d864763ad24 100644 --- a/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx +++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx @@ -47,7 +47,7 @@ void privateSnippetExecutor() " movsd %xmm7, -8(%rbp)\n" " leaq -144(%rbp), %r9 # 6th param: sal_uInt64 * pRegisterReturn\n" - " leaq 16(%rbp), %r8 # 5rd param: void ** ovrflw\n" + " leaq 16(%rbp), %r8 # 5th param: void ** ovrflw\n" " leaq -64(%rbp), %rcx # 4th param: void ** fpreg\n" " leaq -112(%rbp), %rdx # 3rd param: void ** gpreg\n" " movl -148(%rbp), %esi # 2nd param: sal_int32 nVtableOffset\n" diff --git a/bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx index f864e193c729..b37ae17ee9e8 100644 --- a/bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx @@ -357,7 +357,7 @@ struct ProxyRtti // The following vtable RTTI data is based on how the code at // computes // such data, and on how -// "Accessing the current module’s HINSTANCE from a static library" obtians __ImageBase: +// "Accessing the current module’s HINSTANCE from a static library" obtains __ImageBase: struct RttiClassHierarchyDescriptor; diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx index 974a4a94d48b..a9fa3b8fc28d 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx @@ -166,7 +166,7 @@ struct ProxyRtti {}; // The following vtable RTTI data is based on how the code at // computes // such data, and on how -// "Accessing the current module’s HINSTANCE from a static library" obtians __ImageBase: +// "Accessing the current module’s HINSTANCE from a static library" obtains __ImageBase: struct RttiClassHierarchyDescriptor; diff --git a/canvas/Library_canvastools.mk b/canvas/Library_canvastools.mk index f810cab5cc50..d6415e9a5acb 100644 --- a/canvas/Library_canvastools.mk +++ b/canvas/Library_canvastools.mk @@ -46,6 +46,7 @@ $(eval $(call gb_Library_use_libraries,canvastools,\ )) $(eval $(call gb_Library_add_exception_objects,canvastools,\ + canvas/source/tools/CanvasFontBase \ canvas/source/tools/cachedprimitivebase \ canvas/source/tools/canvascustomspritehelper \ canvas/source/tools/canvastools \ diff --git a/canvas/Library_simplecanvas.mk b/canvas/Library_simplecanvas.mk deleted file mode 100644 index e4762ae82487..000000000000 --- a/canvas/Library_simplecanvas.mk +++ /dev/null @@ -1,46 +0,0 @@ -# -*- 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/. -# -# 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 . -# - -$(eval $(call gb_Library_Library,simplecanvas)) - -$(eval $(call gb_Library_set_include,simplecanvas,\ - $$(INCLUDE) \ - -I$(SRCDIR)/canvas/inc \ -)) - -$(eval $(call gb_Library_set_componentfile,simplecanvas,canvas/source/simplecanvas/simplecanvas,services)) - -$(eval $(call gb_Library_use_external,simplecanvas,boost_headers)) - -$(eval $(call gb_Library_use_sdk_api,simplecanvas)) - -$(eval $(call gb_Library_use_libraries,simplecanvas,\ - basegfx \ - canvastools \ - comphelper \ - cppu \ - cppuhelper \ - sal \ -)) - -$(eval $(call gb_Library_add_exception_objects,simplecanvas,\ - canvas/source/simplecanvas/simplecanvasimpl \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/canvas/Module_canvas.mk b/canvas/Module_canvas.mk index 79165c4976e7..d6c7f1b721b7 100644 --- a/canvas/Module_canvas.mk +++ b/canvas/Module_canvas.mk @@ -22,7 +22,6 @@ $(eval $(call gb_Module_Module,canvas)) $(eval $(call gb_Module_add_targets,canvas,\ Library_canvasfactory \ Library_canvastools \ - Library_simplecanvas \ Library_vclcanvas \ $(if $(filter DESKTOP,$(BUILD_TYPE)), \ $(if $(or $(DISABLE_GUI),$(DISABLE_DYNLOADING)),,Executable_canvasdemo)) \ diff --git a/canvas/inc/CanvasFontBase.hxx b/canvas/inc/CanvasFontBase.hxx new file mode 100644 index 000000000000..6f14ed76b133 --- /dev/null +++ b/canvas/inc/CanvasFontBase.hxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include + +#include + +class CANVASTOOLS_DLLPUBLIC CanvasFontBase + : public comphelper::WeakComponentImplHelper +{ +public: + virtual css::rendering::FontMetrics SAL_CALL getFontMetrics() override; + virtual css::uno::Sequence SAL_CALL getAvailableSizes() override; + virtual css::uno::Sequence + SAL_CALL getExtraFontProperties() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/canvas/source/cairo/cairo_canvasfont.cxx b/canvas/source/cairo/cairo_canvasfont.cxx index e5448c933616..41ca1df57348 100644 --- a/canvas/source/cairo/cairo_canvasfont.cxx +++ b/canvas/source/cairo/cairo_canvasfont.cxx @@ -85,7 +85,7 @@ namespace cairocanvas const tools::Long nNewWidth = ::basegfx::fround( aSize.Width() * fStretch ); - maFont->SetAverageFontWidth( nNewWidth ); + maFont->SetFontWidth( nNewWidth ); pOutDev->EnableMapMode(bOldMapState); } @@ -119,24 +119,6 @@ namespace cairocanvas return maFontRequest; } - rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( ) - { - // TODO(F1) - return rendering::FontMetrics(); - } - - uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) - { - // TODO(F1) - return uno::Sequence< double >(); - } - - uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) - { - // TODO(F1) - return uno::Sequence< beans::PropertyValue >(); - } - OUString SAL_CALL CanvasFont::getImplementationName() { return u"CairoCanvas::CanvasFont"_ustr; diff --git a/canvas/source/cairo/cairo_canvasfont.hxx b/canvas/source/cairo/cairo_canvasfont.hxx index d5e015006c98..8fbf562b7afd 100644 --- a/canvas/source/cairo/cairo_canvasfont.hxx +++ b/canvas/source/cairo/cairo_canvasfont.hxx @@ -19,15 +19,13 @@ #pragma once -#include - #include #include #include -#include #include +#include #include #include "cairo_surfaceprovider.hxx" @@ -37,10 +35,7 @@ namespace cairocanvas { - typedef ::comphelper::WeakComponentImplHelper< css::rendering::XCanvasFont, - css::lang::XServiceInfo > CanvasFont_Base; - - class CanvasFont : public CanvasFont_Base + class CanvasFont : public cppu::ImplInheritanceHelper { public: typedef rtl::Reference Reference; @@ -59,9 +54,6 @@ namespace cairocanvas // XCanvasFont virtual css::uno::Reference< css::rendering::XTextLayout > SAL_CALL createTextLayout( const css::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) override; virtual css::rendering::FontRequest SAL_CALL getFontRequest( ) override; - virtual css::rendering::FontMetrics SAL_CALL getFontMetrics( ) override; - virtual css::uno::Sequence< double > SAL_CALL getAvailableSizes( ) override; - virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getExtraFontProperties( ) override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; diff --git a/canvas/source/cairo/cairo_canvashelper_text.cxx b/canvas/source/cairo/cairo_canvashelper_text.cxx index 8fa086830f85..3629cb1a59bb 100644 --- a/canvas/source/cairo/cairo_canvashelper_text.cxx +++ b/canvas/source/cairo/cairo_canvashelper_text.cxx @@ -79,7 +79,7 @@ namespace cairocanvas if( !::rtl::math::approxEqual(aScale.getX(), aScale.getY()) ) { // retrieve true font width - const sal_Int32 nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetAverageFontWidth() ); + const sal_Int32 nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetFontWidth() ); const sal_Int32 nScaledFontWidth( ::basegfx::fround(nFontWidth * aScale.getX()) ); @@ -90,7 +90,7 @@ namespace cairocanvas return false; } - io_rVCLFont.SetAverageFontWidth( nScaledFontWidth ); + io_rVCLFont.SetFontWidth( nScaledFontWidth ); } if( !::rtl::math::approxEqual(aScale.getY(), 1.0) ) diff --git a/canvas/source/cairo/cairo_devicehelper.cxx b/canvas/source/cairo/cairo_devicehelper.cxx index 3e899c03e199..f8086ba3fa66 100644 --- a/canvas/source/cairo/cairo_devicehelper.cxx +++ b/canvas/source/cairo/cairo_devicehelper.cxx @@ -59,8 +59,8 @@ namespace cairocanvas implInit(rSurfaceProvider, rRefDevice); OutputDevice* pOutDev = getOutputDevice(); - mpSurface = pOutDev->CreateSurface(pOutDev->GetOutOffXPixel(), - pOutDev->GetOutOffYPixel(), + mpSurface = pOutDev->CreateSurface(pOutDev->GetDeviceOriginX(), + pOutDev->GetDeviceOriginY(), pOutDev->GetOutputWidthPixel(), pOutDev->GetOutputHeightPixel()); } @@ -86,14 +86,14 @@ namespace cairocanvas // X11 only bool bReuseSurface = mpSurface && - mpSurface->Resize(rSize.getWidth() + pOutDev->GetOutOffXPixel(), - rSize.getHeight() + pOutDev->GetOutOffYPixel()); + mpSurface->Resize(rSize.getWidth() + pOutDev->GetDeviceOriginX(), + rSize.getHeight() + pOutDev->GetDeviceOriginY()); if (!bReuseSurface) { mpSurface = pOutDev->CreateSurface( - pOutDev->GetOutOffXPixel(), - pOutDev->GetOutOffYPixel(), + pOutDev->GetDeviceOriginX(), + pOutDev->GetDeviceOriginY(), rSize.getWidth(), rSize.getHeight() ); } } diff --git a/canvas/source/directx/dx_canvasfont.cxx b/canvas/source/directx/dx_canvasfont.cxx index a38581856ed0..76e24509e6cd 100644 --- a/canvas/source/directx/dx_canvasfont.cxx +++ b/canvas/source/directx/dx_canvasfont.cxx @@ -87,7 +87,7 @@ namespace dxcanvas { ::osl::MutexGuard aGuard( m_aMutex ); - return new TextLayout( aText, nDirection, nRandomSeed, ImplRef( this ) ); + return new TextLayout(aText, nDirection, nRandomSeed, rtl::Reference(this)); } uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) diff --git a/canvas/source/directx/dx_canvasfont.hxx b/canvas/source/directx/dx_canvasfont.hxx index c5f369d00f5e..b507e3a350d7 100644 --- a/canvas/source/directx/dx_canvasfont.hxx +++ b/canvas/source/directx/dx_canvasfont.hxx @@ -48,7 +48,6 @@ namespace dxcanvas public CanvasFont_Base { public: - typedef rtl::Reference ImplRef; /// make noncopyable CanvasFont(const CanvasFont&) = delete; const CanvasFont& operator=(const CanvasFont&) = delete; diff --git a/canvas/source/directx/dx_canvashelper.cxx b/canvas/source/directx/dx_canvashelper.cxx index 7cad6691fb77..0e0c6514b840 100644 --- a/canvas/source/directx/dx_canvashelper.cxx +++ b/canvas/source/directx/dx_canvashelper.cxx @@ -527,8 +527,7 @@ namespace dxcanvas Gdiplus::Color( dxcanvastools::sequenceToArgb(renderState.DeviceColor))); - CanvasFont::ImplRef pFont( - dxcanvastools::canvasFontFromXFont(xFont) ); + rtl::Reference pFont(dxcanvastools::canvasFontFromXFont(xFont)); // Move glyphs up, such that output happens at the font // baseline. @@ -754,7 +753,7 @@ namespace dxcanvas { GraphicsPathSharedPtr aClipPath( dxcanvastools::graphicsPathFromXPolyPolygon2D( viewState.Clip ) ); - // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+. + // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abysmally on GDI+. // Try SetClip( Rect ) or similar for simple clip paths (need some support in // LinePolyPolygon, then) ENSURE_OR_THROW( @@ -787,7 +786,7 @@ namespace dxcanvas { GraphicsPathSharedPtr aClipPath( dxcanvastools::graphicsPathFromXPolyPolygon2D( renderState.Clip ) ); - // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+. + // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abysmally on GDI+. // Try SetClip( Rect ) or similar for simple clip paths (need some support in // LinePolyPolygon, then) ENSURE_OR_THROW( @@ -800,7 +799,7 @@ namespace dxcanvas const Gdiplus::CompositingMode eCompositing( calcCompositingMode( renderState.CompositeOperation ) ); ENSURE_OR_THROW( Gdiplus::Ok == rGraphics->SetCompositingMode( eCompositing ), - "CanvasHelper::setupGraphicsState(): Cannot set GDI* compositing mode)" ); + "CanvasHelper::setupGraphicsState(): Cannot set GDI+ compositing mode" ); } void CanvasHelper::flush() const diff --git a/canvas/source/directx/dx_canvashelper_texturefill.cxx b/canvas/source/directx/dx_canvashelper_texturefill.cxx index d9f3489997e8..7e8fea2eefd4 100644 --- a/canvas/source/directx/dx_canvashelper_texturefill.cxx +++ b/canvas/source/directx/dx_canvashelper_texturefill.cxx @@ -231,7 +231,7 @@ namespace dxcanvas // gradients ever: SetFocusScales completely ignores // transformations, both when set at the PathGradientBrush // and for the world coordinate system. Thus, to correctly - // display anisotrophic path gradients, we have to render + // display anisotropic path gradients, we have to render // them by hand. WTF. // TODO(F2): This does not yet support other repeat modes @@ -268,7 +268,7 @@ namespace dxcanvas ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform, texture.AffineTransform ); // determine overall transformation for inner polygon (might - // have to be prefixed by anisotrophic scaling) + // have to be prefixed by anisotropic scaling) ::basegfx::B2DHomMatrix aInnerPolygonTransformMatrix; // For performance reasons, we create a temporary VCL polygon @@ -287,7 +287,7 @@ namespace dxcanvas aOuterPoly.transform(aTextureTransform); - // apply scaling (possibly anisotrophic) to inner polygon + // apply scaling (possibly anisotropic) to inner polygon // scale inner polygon according to aspect ratio: for @@ -310,7 +310,7 @@ namespace dxcanvas } else { - // isotrophic case + // isotropic case aInnerPolygonTransformMatrix.scale( 0.0, 0.0 ); } diff --git a/canvas/source/directx/dx_impltools.cxx b/canvas/source/directx/dx_impltools.cxx index 12a1aa2b5634..bea95813d012 100644 --- a/canvas/source/directx/dx_impltools.cxx +++ b/canvas/source/directx/dx_impltools.cxx @@ -570,14 +570,14 @@ namespace dxcanvastools } } - CanvasFont::ImplRef canvasFontFromXFont( const uno::Reference< rendering::XCanvasFont >& xFont ) + rtl::Reference canvasFontFromXFont(const uno::Reference& xFont) { CanvasFont* pCanvasFont = dynamic_cast< CanvasFont* >(xFont.get()); ENSURE_ARG_OR_THROW( pCanvasFont, "canvasFontFromXFont(): Invalid XFont (or incompatible font for this XCanvas)" ); - return CanvasFont::ImplRef( pCanvasFont ); + return rtl::Reference(pCanvasFont); } void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr, diff --git a/canvas/source/directx/dx_impltools.hxx b/canvas/source/directx/dx_impltools.hxx index 3bc5ec65ca27..73f9a46dec0b 100644 --- a/canvas/source/directx/dx_impltools.hxx +++ b/canvas/source/directx/dx_impltools.hxx @@ -37,7 +37,7 @@ namespace basegfx class B2DHomMatrix; class B2IRange; class B2DPolyPolygon; -}; +} namespace com::sun::star::geometry { @@ -113,7 +113,7 @@ using namespace dxcanvas; BitmapSharedPtr bitmapFromXBitmap( const css::uno::Reference< css::rendering::XBitmap >& xBitmap ); - CanvasFont::ImplRef canvasFontFromXFont( const css::uno::Reference< css::rendering::XCanvasFont >& xFont ); + rtl::Reference canvasFontFromXFont(const css::uno::Reference& xFont); void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr, double nRedModulation, diff --git a/canvas/source/directx/dx_textlayout.cxx b/canvas/source/directx/dx_textlayout.cxx index e64dde596693..2600d3736026 100644 --- a/canvas/source/directx/dx_textlayout.cxx +++ b/canvas/source/directx/dx_textlayout.cxx @@ -36,7 +36,7 @@ namespace dxcanvas TextLayout::TextLayout( const rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 /*nRandomSeed*/, - const CanvasFont::ImplRef& rFont ) : + const rtl::Reference& rFont) : TextLayout_Base( m_aMutex ), maText( aText ), maLogicalAdvancements(), diff --git a/canvas/source/directx/dx_textlayout.hxx b/canvas/source/directx/dx_textlayout.hxx index f0ae523e7b6a..88867aa2be6d 100644 --- a/canvas/source/directx/dx_textlayout.hxx +++ b/canvas/source/directx/dx_textlayout.hxx @@ -47,7 +47,7 @@ namespace dxcanvas TextLayout( const css::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed, - const CanvasFont::ImplRef& rFont ); + const rtl::Reference& rFont); /// make noncopyable TextLayout(const TextLayout&) = delete; const TextLayout& operator=(const TextLayout&) = delete; @@ -98,7 +98,7 @@ namespace dxcanvas css::rendering::StringContext maText; css::uno::Sequence< double > maLogicalAdvancements; css::uno::Sequence< sal_Bool > maKashidaPositions; - CanvasFont::ImplRef mpFont; + rtl::Reference mpFont; sal_Int8 mnTextDirection; }; diff --git a/canvas/source/directx/dx_textlayout_drawhelper.cxx b/canvas/source/directx/dx_textlayout_drawhelper.cxx index cb9de68275a0..17f5faa20d6c 100644 --- a/canvas/source/directx/dx_textlayout_drawhelper.cxx +++ b/canvas/source/directx/dx_textlayout_drawhelper.cxx @@ -130,7 +130,7 @@ namespace dxcanvas aFont.SetColor( aColor ); aFont.SetFillColor( aColor ); - CanvasFont::ImplRef pFont(dxcanvastools::canvasFontFromXFont(rCanvasFont)); + rtl::Reference pFont(dxcanvastools::canvasFontFromXFont(rCanvasFont)); if (pFont.is() && pFont->getEmphasisMark()) aFont.SetEmphasisMark(FontEmphasisMark(pFont->getEmphasisMark())); @@ -146,7 +146,7 @@ namespace dxcanvas const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch ); - aFont.SetAverageFontWidth( nNewWidth ); + aFont.SetFontWidth( nNewWidth ); } // set font @@ -275,10 +275,10 @@ namespace dxcanvas const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch ); - aFont.SetAverageFontWidth( nNewWidth ); + aFont.SetFontWidth( nNewWidth ); } - CanvasFont::ImplRef pFont(dxcanvastools::canvasFontFromXFont(rCanvasFont)); + rtl::Reference pFont(dxcanvastools::canvasFontFromXFont(rCanvasFont)); if (pFont.is() && pFont->getEmphasisMark()) aFont.SetEmphasisMark(FontEmphasisMark(pFont->getEmphasisMark())); diff --git a/canvas/source/opengl/ogl_canvasfont.cxx b/canvas/source/opengl/ogl_canvasfont.cxx index e6385617c015..82314b7440ed 100644 --- a/canvas/source/opengl/ogl_canvasfont.cxx +++ b/canvas/source/opengl/ogl_canvasfont.cxx @@ -36,32 +36,13 @@ namespace oglcanvas { std::unique_lock aGuard( m_aMutex ); - return new TextLayout( aText, nDirection, nRandomSeed, ImplRef( this ) ); - } - - uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) - { - // TODO - return uno::Sequence< double >(); - } - - uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) - { - // TODO - return uno::Sequence< beans::PropertyValue >(); + return new TextLayout(aText, nDirection, nRandomSeed, rtl::Reference(this)); } rendering::FontRequest SAL_CALL CanvasFont::getFontRequest( ) { return maFontRequest; } - - rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( ) - { - // TODO - return rendering::FontMetrics(); - } - } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/opengl/ogl_canvasfont.hxx b/canvas/source/opengl/ogl_canvasfont.hxx index 8212d1f7759b..74b2b53ad640 100644 --- a/canvas/source/opengl/ogl_canvasfont.hxx +++ b/canvas/source/opengl/ogl_canvasfont.hxx @@ -9,6 +9,8 @@ #pragma once +#include + #include #include @@ -21,14 +23,9 @@ namespace oglcanvas { - - typedef ::comphelper::WeakComponentImplHelper< css::rendering::XCanvasFont > CanvasFontBaseT; - - class CanvasFont : public CanvasFontBaseT + class CanvasFont : public CanvasFontBase { public: - typedef rtl::Reference ImplRef; - /// make noncopyable CanvasFont(const CanvasFont&) = delete; const CanvasFont& operator=(const CanvasFont&) = delete; @@ -40,9 +37,6 @@ namespace oglcanvas // XCanvasFont virtual css::uno::Reference< css::rendering::XTextLayout > SAL_CALL createTextLayout( const css::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) override; virtual css::rendering::FontRequest SAL_CALL getFontRequest( ) override; - virtual css::rendering::FontMetrics SAL_CALL getFontMetrics( ) override; - virtual css::uno::Sequence< double > SAL_CALL getAvailableSizes( ) override; - virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getExtraFontProperties( ) override; const css::geometry::Matrix2D& getFontMatrix() const { return maFontMatrix; } diff --git a/canvas/source/opengl/ogl_canvashelper.cxx b/canvas/source/opengl/ogl_canvashelper.cxx index 6d7e2aa764e2..1574aa1389d7 100644 --- a/canvas/source/opengl/ogl_canvashelper.cxx +++ b/canvas/source/opengl/ogl_canvashelper.cxx @@ -748,7 +748,7 @@ namespace oglcanvas const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch ); - aFont.SetAverageFontWidth( nNewWidth ); + aFont.SetFontWidth( nNewWidth ); } // set font diff --git a/canvas/source/opengl/ogl_spritecanvas.cxx b/canvas/source/opengl/ogl_spritecanvas.cxx index 9bec462f96e2..e8d1c770daa8 100644 --- a/canvas/source/opengl/ogl_spritecanvas.cxx +++ b/canvas/source/opengl/ogl_spritecanvas.cxx @@ -24,9 +24,8 @@ using namespace ::com::sun::star; namespace oglcanvas { - SpriteCanvas::SpriteCanvas( const uno::Sequence< uno::Any >& aArguments, - const uno::Reference< uno::XComponentContext >& /*rxContext*/ ) : - maArguments(aArguments) + SpriteCanvas::SpriteCanvas(const uno::Sequence& aArguments) + : maArguments(aArguments) { } @@ -151,14 +150,13 @@ namespace oglcanvas } - extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* com_sun_star_comp_rendering_SpriteCanvas_OGL_get_implementation( - css::uno::XComponentContext* context, css::uno::Sequence const& args) + css::uno::XComponentContext*, css::uno::Sequence const& args) { if( !OpenGLHelper::supportsOpenGL()) return nullptr; - rtl::Reference p = new oglcanvas::SpriteCanvas(args, context); + rtl::Reference p = new oglcanvas::SpriteCanvas(args); p->initialize(); return cppu::acquire(p.get()); } diff --git a/canvas/source/opengl/ogl_spritecanvas.hxx b/canvas/source/opengl/ogl_spritecanvas.hxx index 33948b2d0cd2..3cc12b2a218a 100644 --- a/canvas/source/opengl/ogl_spritecanvas.hxx +++ b/canvas/source/opengl/ogl_spritecanvas.hxx @@ -66,10 +66,7 @@ namespace oglcanvas class SpriteCanvas : public SpriteCanvasBaseT { public: - SpriteCanvas( const css::uno::Sequence< - css::uno::Any >& aArguments, - const css::uno::Reference< - css::uno::XComponentContext >& rxContext ); + SpriteCanvas(const css::uno::Sequence& aArguments); void initialize(); diff --git a/canvas/source/opengl/ogl_textlayout.cxx b/canvas/source/opengl/ogl_textlayout.cxx index 1bcf1a9fbaf7..c4483c2f29c4 100644 --- a/canvas/source/opengl/ogl_textlayout.cxx +++ b/canvas/source/opengl/ogl_textlayout.cxx @@ -22,7 +22,7 @@ namespace oglcanvas TextLayout::TextLayout( rendering::StringContext aText, sal_Int8 nDirection, sal_Int64 /*nRandomSeed*/, - CanvasFont::ImplRef rFont ) : + rtl::Reference rFont) : maText(std::move( aText )), mpFont(std::move( rFont )), mnTextDirection( nDirection ) diff --git a/canvas/source/opengl/ogl_textlayout.hxx b/canvas/source/opengl/ogl_textlayout.hxx index d913ec3fb368..07d2a79c44dd 100644 --- a/canvas/source/opengl/ogl_textlayout.hxx +++ b/canvas/source/opengl/ogl_textlayout.hxx @@ -28,7 +28,7 @@ namespace oglcanvas TextLayout( css::rendering::StringContext aText, sal_Int8 nDirection, sal_Int64 nRandomSeed, - CanvasFont::ImplRef rFont ); + rtl::Reference rFont); /// make noncopyable TextLayout(const TextLayout&) = delete; @@ -62,7 +62,7 @@ namespace oglcanvas css::rendering::StringContext maText; css::uno::Sequence< double > maLogicalAdvancements; css::uno::Sequence< sal_Bool > maKashidaPositions; - CanvasFont::ImplRef mpFont; + rtl::Reference mpFont; sal_Int8 mnTextDirection; }; diff --git a/canvas/source/simplecanvas/simplecanvasimpl.cxx b/canvas/source/simplecanvas/simplecanvasimpl.cxx deleted file mode 100644 index d99da93a8ee1..000000000000 --- a/canvas/source/simplecanvas/simplecanvasimpl.cxx +++ /dev/null @@ -1,365 +0,0 @@ -/* -*- 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -#include - -using namespace ::com::sun::star; - -namespace -{ - uno::Sequence< double > color2Sequence( sal_Int32 nColor ) - { - // TODO(F3): Color management - uno::Sequence< double > aRes{ - static_cast( (nColor&0xFF000000U) >> 24U ) / 255.0, - static_cast( (nColor&0x00FF0000U) >> 16U ) / 255.0, - static_cast( (nColor&0x0000FF00U) >> 8U ) / 255.0, - static_cast( (nColor&0x000000FFU) ) / 255.0 - }; - return aRes; - } - - uno::Reference< rendering::XPolyPolygon2D > rect2Poly( uno::Reference const& xDevice, - geometry::RealRectangle2D const& rRect ) - { - uno::Sequence< geometry::RealPoint2D > rectSequence{ - geometry::RealPoint2D( rRect.X1, rRect.Y1 ), - geometry::RealPoint2D( rRect.X2, rRect.Y1 ), - geometry::RealPoint2D( rRect.X2, rRect.Y2 ), - geometry::RealPoint2D( rRect.X1, rRect.Y2 ) - }; - uno::Sequence< uno::Sequence< geometry::RealPoint2D > > sequenceSequence{ rectSequence }; - uno::Reference< rendering::XPolyPolygon2D > xRes = - xDevice->createCompatibleLinePolyPolygon( sequenceSequence ); - if( xRes.is() ) - xRes->setClosed( 0, true ); - return xRes; - } - - struct SimpleRenderState - { - o3tl::LazyUpdate, - decltype(&color2Sequence)> m_aPenColor; - o3tl::LazyUpdate, - decltype(&color2Sequence)> m_aFillColor; - o3tl::LazyUpdate, - std::function (geometry::RealRectangle2D)> > m_aRectClip; - geometry::AffineMatrix2D m_aTransformation; - - explicit SimpleRenderState( uno::Reference const& xDevice ) : - m_aPenColor( &color2Sequence), - m_aFillColor( &color2Sequence ), - m_aRectClip( [&xDevice](geometry::RealRectangle2D const& rRect) { return rect2Poly(xDevice, rRect); } ) - { - canvastools::setIdentityAffineMatrix2D( m_aTransformation ); - } - }; - - - typedef ::comphelper::WeakComponentImplHelper< css::rendering::XSimpleCanvas, - css::lang::XServiceName > SimpleCanvasBase; - - class SimpleCanvasImpl : public SimpleCanvasBase - { - private: - bool isStrokingEnabled() const - { - return maRenderState.m_aPenColor.getInValue() % 0x100 != 0; - } - - rendering::RenderState createStrokingRenderState() const - { - return rendering::RenderState(maRenderState.m_aTransformation, - *maRenderState.m_aRectClip, - *maRenderState.m_aPenColor, - rendering::CompositeOperation::OVER); - } - - bool isFillingEnabled() const - { - return maRenderState.m_aFillColor.getInValue() % 0x100 != 0; - } - - rendering::RenderState createFillingRenderState() const - { - return rendering::RenderState(maRenderState.m_aTransformation, - *maRenderState.m_aRectClip, - *maRenderState.m_aFillColor, - rendering::CompositeOperation::OVER); - } - - static uno::Reference grabCanvas( uno::Sequence const& rArgs ) - { - uno::Reference xRet; - - // can't do much without an XCanvas, can't we? - if( !rArgs.hasElements() ) - throw lang::IllegalArgumentException(); - - xRet.set( rArgs[0], uno::UNO_QUERY ); - - // can't do much without an XCanvas, can't we? - if( !xRet.is() ) - throw lang::IllegalArgumentException(); - - return xRet; - } - - public: - SimpleCanvasImpl( const uno::Sequence< uno::Any >& aArguments, - const uno::Reference< uno::XComponentContext >& ) : - mxCanvas( grabCanvas(aArguments) ), - maFont([this](rendering::FontRequest const& rFontRequest) { - return mxCanvas->createFont(rFontRequest, - uno::Sequence< beans::PropertyValue >(), - geometry::Matrix2D()); } ), - maRenderState( mxCanvas->getDevice() ) - { - canvastools::initViewState(maViewState); - } - - - private: - // Ifc XServiceName - virtual OUString SAL_CALL getServiceName( ) override - { - return u"com.sun.star.rendering.SimpleCanvas"_ustr; - } - - // Ifc XSimpleCanvas - virtual void SAL_CALL selectFont( const OUString& sFontName, - double size, - sal_Bool bold, - sal_Bool italic ) override - { - std::unique_lock aGuard( m_aMutex ); - - maFont->FontDescription.FamilyName = sFontName; - maFont->CellSize = size; - maFont->FontDescription.FontDescription.Weight = - bold ? rendering::PanoseWeight::BOLD : rendering::PanoseWeight::MEDIUM; - maFont->FontDescription.FontDescription.Letterform = - italic ? rendering::PanoseLetterForm::OBLIQUE_CONTACT : rendering::PanoseLetterForm::ANYTHING; - } - - virtual void SAL_CALL setPenColor( ::sal_Int32 nsRgbaColor ) override - { - std::unique_lock aGuard( m_aMutex ); - *(maRenderState.m_aPenColor) = nsRgbaColor; - } - - virtual void SAL_CALL setFillColor( ::sal_Int32 nsRgbaColor ) override - { - std::unique_lock aGuard( m_aMutex ); - *(maRenderState.m_aFillColor) = nsRgbaColor; - } - - virtual void SAL_CALL setRectClip( const geometry::RealRectangle2D& aRect ) override - { - std::unique_lock aGuard( m_aMutex ); - *(maRenderState.m_aRectClip) = aRect; - } - - virtual void SAL_CALL setTransformation( const geometry::AffineMatrix2D& aTransform ) override - { - std::unique_lock aGuard( m_aMutex ); - maRenderState.m_aTransformation = aTransform; - } - - virtual void SAL_CALL drawPixel( const geometry::RealPoint2D& aPoint ) override - { - std::unique_lock aGuard( m_aMutex ); - mxCanvas->drawPoint(aPoint, - maViewState, - createFillingRenderState()); - } - - virtual void SAL_CALL drawLine( const geometry::RealPoint2D& aStartPoint, - const geometry::RealPoint2D& aEndPoint ) override - { - std::unique_lock aGuard( m_aMutex ); - mxCanvas->drawLine(aStartPoint, - aEndPoint, - maViewState, - createStrokingRenderState()); - } - - virtual void SAL_CALL drawRect( const geometry::RealRectangle2D& aRect ) override - { - std::unique_lock aGuard( m_aMutex ); - uno::Reference< rendering::XPolyPolygon2D > xPoly( - rect2Poly( mxCanvas->getDevice(), - aRect)); - - if( isFillingEnabled() ) - mxCanvas->drawPolyPolygon(xPoly, - maViewState, - createFillingRenderState()); - if( isStrokingEnabled() ) - mxCanvas->drawPolyPolygon(xPoly, - maViewState, - createStrokingRenderState()); - } - - virtual void SAL_CALL drawPolyPolygon( const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon ) override - { - std::unique_lock aGuard( m_aMutex ); - - if( isFillingEnabled() ) - mxCanvas->drawPolyPolygon(xPolyPolygon, - maViewState, - createFillingRenderState()); - if( isStrokingEnabled() ) - mxCanvas->drawPolyPolygon(xPolyPolygon, - maViewState, - createStrokingRenderState()); - } - - virtual void SAL_CALL drawText( const rendering::StringContext& aText, - const geometry::RealPoint2D& aOutPos, - ::sal_Int8 nTextDirection ) override - { - std::unique_lock aGuard( m_aMutex ); - const basegfx::B2DHomMatrix offsetTransform(basegfx::utils::createTranslateB2DHomMatrix(aOutPos.X,aOutPos.Y)); - rendering::RenderState aRenderState( createStrokingRenderState() ); - canvastools::appendToRenderState(aRenderState, offsetTransform); - - mxCanvas->drawText(aText, - maFont.getOutValue(), - maViewState, - aRenderState, - nTextDirection); - } - - virtual void SAL_CALL drawBitmap( const uno::Reference< rendering::XBitmap >& xBitmap, - const geometry::RealPoint2D& aLeftTop ) override - { - std::unique_lock aGuard( m_aMutex ); - const basegfx::B2DHomMatrix offsetTransform(basegfx::utils::createTranslateB2DHomMatrix(aLeftTop.X,aLeftTop.Y)); - rendering::RenderState aRenderState( createStrokingRenderState() ); - canvastools::appendToRenderState(aRenderState, offsetTransform); - - mxCanvas->drawBitmap(xBitmap,maViewState,aRenderState); - } - - virtual uno::Reference< rendering::XGraphicDevice > SAL_CALL getDevice( ) override - { - std::unique_lock aGuard( m_aMutex ); - return mxCanvas->getDevice(); - } - - virtual uno::Reference< rendering::XCanvas > SAL_CALL getCanvas( ) override - { - std::unique_lock aGuard( m_aMutex ); - return mxCanvas; - } - - virtual rendering::FontMetrics SAL_CALL getFontMetrics( ) override - { - std::unique_lock aGuard( m_aMutex ); - return maFont.getOutValue()->getFontMetrics(); - } - - virtual uno::Reference< rendering::XCanvasFont > SAL_CALL getCurrentFont( ) override - { - std::unique_lock aGuard( m_aMutex ); - return maFont.getOutValue(); - } - - virtual ::sal_Int32 SAL_CALL getCurrentPenColor( ) override - { - std::unique_lock aGuard( m_aMutex ); - return maRenderState.m_aPenColor.getInValue(); - } - - virtual ::sal_Int32 SAL_CALL getCurrentFillColor( ) override - { - std::unique_lock aGuard( m_aMutex ); - return maRenderState.m_aFillColor.getInValue(); - } - - virtual geometry::RealRectangle2D SAL_CALL getCurrentClipRect( ) override - { - std::unique_lock aGuard( m_aMutex ); - return maRenderState.m_aRectClip.getInValue(); - } - - virtual geometry::AffineMatrix2D SAL_CALL getCurrentTransformation( ) override - { - std::unique_lock aGuard( m_aMutex ); - return maRenderState.m_aTransformation; - } - - virtual rendering::ViewState SAL_CALL getCurrentViewState( ) override - { - std::unique_lock aGuard( m_aMutex ); - return maViewState; - } - - virtual rendering::RenderState SAL_CALL getCurrentRenderState( sal_Bool bUseFillColor ) override - { - std::unique_lock aGuard( m_aMutex ); - if( bUseFillColor ) - return createFillingRenderState(); - else - return createStrokingRenderState(); - } - - - typedef o3tl::LazyUpdate< - rendering::FontRequest, - uno::Reference< rendering::XCanvasFont >, - std::function (rendering::FontRequest)> > SimpleFont; - - uno::Reference mxCanvas; - SimpleFont maFont; - rendering::ViewState maViewState; - SimpleRenderState maRenderState; - }; - -} - -extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* -com_sun_star_comp_rendering_SimpleCanvas( - css::uno::XComponentContext* context, css::uno::Sequence const& args) -{ - return cppu::acquire(new SimpleCanvasImpl(args, context)); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/tools/CanvasFontBase.cxx b/canvas/source/tools/CanvasFontBase.cxx new file mode 100644 index 000000000000..beb368f37577 --- /dev/null +++ b/canvas/source/tools/CanvasFontBase.cxx @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +css::rendering::FontMetrics SAL_CALL CanvasFontBase::getFontMetrics() +{ + // TODO + return css::rendering::FontMetrics(); +} + +css::uno::Sequence SAL_CALL CanvasFontBase::getAvailableSizes() +{ + // TODO + return {}; +} + +css::uno::Sequence SAL_CALL CanvasFontBase::getExtraFontProperties() +{ + // TODO + return {}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/canvas/source/tools/spriteredrawmanager.cxx b/canvas/source/tools/spriteredrawmanager.cxx index 26a1d67f8836..2338518e8396 100644 --- a/canvas/source/tools/spriteredrawmanager.cxx +++ b/canvas/source/tools/spriteredrawmanager.cxx @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -27,7 +28,6 @@ #include #include -#include #include namespace canvas @@ -437,7 +437,7 @@ namespace canvas // this object, is the owner of the sprites. After all, a // sprite without a canvas to render into makes not terribly // much sense. - for( const auto& rCurr : boost::adaptors::reverse(maSprites) ) + for( const auto& rCurr : std::views::reverse(maSprites) ) rCurr->dispose(); maSprites.clear(); diff --git a/canvas/source/vcl/canvasfont.cxx b/canvas/source/vcl/canvasfont.cxx index f21c137e61bf..df9ba9ecac04 100644 --- a/canvas/source/vcl/canvasfont.cxx +++ b/canvas/source/vcl/canvasfont.cxx @@ -123,18 +123,6 @@ namespace vclcanvas aMetric.GetAscent() / 2.0); } - uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) - { - // TODO(F1) - return uno::Sequence< double >(); - } - - uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) - { - // TODO(F1) - return uno::Sequence< beans::PropertyValue >(); - } - OUString SAL_CALL CanvasFont::getImplementationName() { return u"VCLCanvas::CanvasFont"_ustr; diff --git a/canvas/source/vcl/canvasfont.hxx b/canvas/source/vcl/canvasfont.hxx index 3e64d3d9f60d..f549be0e591a 100644 --- a/canvas/source/vcl/canvasfont.hxx +++ b/canvas/source/vcl/canvasfont.hxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -33,15 +32,13 @@ #include "outdevprovider.hxx" +#include /* Definition of CanvasFont class */ namespace vclcanvas { - typedef ::comphelper::WeakComponentImplHelper< css::rendering::XCanvasFont, - css::lang::XServiceInfo > CanvasFont_Base; - - class CanvasFont : public CanvasFont_Base + class CanvasFont : public cppu::ImplInheritanceHelper { public: typedef rtl::Reference Reference; @@ -63,8 +60,6 @@ namespace vclcanvas virtual css::uno::Reference< css::rendering::XTextLayout > SAL_CALL createTextLayout( const css::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) override; virtual css::rendering::FontRequest SAL_CALL getFontRequest( ) override; virtual css::rendering::FontMetrics SAL_CALL getFontMetrics( ) override; - virtual css::uno::Sequence< double > SAL_CALL getAvailableSizes( ) override; - virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getExtraFontProperties( ) override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; diff --git a/canvas/source/vcl/canvashelper_texturefill.cxx b/canvas/source/vcl/canvashelper_texturefill.cxx index 4d62b1b0d2c0..ff84b71f5942 100644 --- a/canvas/source/vcl/canvashelper_texturefill.cxx +++ b/canvas/source/vcl/canvashelper_texturefill.cxx @@ -329,11 +329,11 @@ namespace vclcanvas aOuterPoly.transform( rTextureTransform ); // determine overall transformation for inner polygon (might - // have to be prefixed by anisotrophic scaling) + // have to be prefixed by anisotropic scaling) ::basegfx::B2DHomMatrix aInnerPolygonTransformMatrix; - // apply scaling (possibly anisotrophic) to inner polygon + // apply scaling (possibly anisotropic) to inner polygon // scale inner polygon according to aspect ratio: for @@ -356,7 +356,7 @@ namespace vclcanvas } else { - // isotrophic case + // isotropic case aInnerPolygonTransformMatrix.scale( 0.0, 0.0 ); } @@ -863,7 +863,7 @@ namespace vclcanvas // (extended, because shrinking might leave some // inner polygon areas unfilled). // Finally, the bound rect is transformed back to - // device coordinate space, were we determine the + // device coordinate space, where we determine the // start point from it. ::basegfx::B2DRectangle aTextureSpacePolygonRect = ::canvastools::calcTransformedRectBounds( vcl::unotools::b2DRectangleFromRectangle(aPolygonDeviceRect), diff --git a/canvas/source/vcl/impltools.cxx b/canvas/source/vcl/impltools.cxx index 844bdd0f6eff..ea61ebd13292 100644 --- a/canvas/source/vcl/impltools.cxx +++ b/canvas/source/vcl/impltools.cxx @@ -106,7 +106,7 @@ using namespace vclcanvas; if( !::rtl::math::approxEqual(aScale.getX(), aScale.getY()) ) { // retrieve true font width - const sal_Int32 nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetAverageFontWidth() ); + const sal_Int32 nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetFontWidth() ); const sal_Int32 nScaledFontWidth( ::basegfx::fround(nFontWidth * aScale.getX()) ); @@ -117,7 +117,7 @@ using namespace vclcanvas; return false; } - io_rVCLFont.SetAverageFontWidth( nScaledFontWidth ); + io_rVCLFont.SetFontWidth( nScaledFontWidth ); } if( !::rtl::math::approxEqual(aScale.getY(), 1.0) ) @@ -156,7 +156,7 @@ using namespace vclcanvas; const ::tools::Long nNewWidth = ::basegfx::fround<::tools::Long>(aSize.Width() * fStretch); - rFont.SetAverageFontWidth(nNewWidth); + rFont.SetFontWidth(nNewWidth); rOutDev.EnableMapMode(bOldMapState); } diff --git a/chart2/CppunitTest_chart2_correlation_coefficient.mk b/chart2/CppunitTest_chart2_correlation_coefficient.mk new file mode 100644 index 000000000000..71476366d55e --- /dev/null +++ b/chart2/CppunitTest_chart2_correlation_coefficient.mk @@ -0,0 +1,28 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# Copyright the LibreOffice contributors. +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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,chart2_correlation_coefficient)) + +$(eval $(call gb_CppunitTest_add_exception_objects,chart2_correlation_coefficient, \ + chart2/qa/unit/correlation_coefficient_test \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,chart2_correlation_coefficient, \ + sal \ +)) + +$(eval $(call gb_CppunitTest_set_include,chart2_correlation_coefficient,\ + -I$(SRCDIR)/chart2/inc \ + -I$(SRCDIR)/chart2/source/inc \ + $$(INCLUDE) \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/chart2/CppunitTest_chart2_splines.mk b/chart2/CppunitTest_chart2_splines.mk new file mode 100644 index 000000000000..c5b82af98df3 --- /dev/null +++ b/chart2/CppunitTest_chart2_splines.mk @@ -0,0 +1,43 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,chart2_splines)) + +$(eval $(call gb_CppunitTest_add_exception_objects,chart2_splines, \ + chart2/qa/unit/splines_test \ +)) + +$(eval $(call gb_CppunitTest_use_externals,chart2_splines, \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,chart2_splines, \ + chart2 \ + sal \ + subsequenttest \ + tl \ + test \ + unotest \ + utl \ + cppu \ + cppuhelper \ +)) + +$(eval $(call gb_CppunitTest_set_include,chart2_splines,\ + -I$(SRCDIR)/chart2/source/view/charttypes \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,chart2_splines)) +$(eval $(call gb_CppunitTest_use_ure,chart2_splines)) +$(eval $(call gb_CppunitTest_use_vcl,chart2_splines)) +$(eval $(call gb_CppunitTest_use_rdb,chart2_splines,services)) +$(eval $(call gb_CppunitTest_use_configuration,chart2_splines)) + +# vim: set noet sw=4 ts=4: diff --git a/chart2/Library_chart2.mk b/chart2/Library_chart2.mk index b8d7057cdcf9..1236f3e74ff4 100644 --- a/chart2/Library_chart2.mk +++ b/chart2/Library_chart2.mk @@ -22,6 +22,7 @@ $(eval $(call gb_Library_set_precompiled_header,chart2,chart2/inc/pch/precompile $(eval $(call gb_Library_use_externals,chart2,\ boost_headers \ + frozen \ libxml2 \ )) @@ -248,10 +249,13 @@ $(eval $(call gb_Library_add_exception_objects,chart2,\ chart2/source/view/axes/VPolarRadiusAxis \ chart2/source/view/charttypes/AreaChart \ chart2/source/view/charttypes/BarChart \ + chart2/source/view/charttypes/HistogramChart \ chart2/source/view/charttypes/BarPositionHelper \ chart2/source/view/charttypes/BubbleChart \ chart2/source/view/charttypes/CandleStickChart \ + chart2/source/view/charttypes/CorrelationCircleChart \ chart2/source/view/charttypes/CategoryPositionHelper \ + chart2/source/view/charttypes/FunnelChart \ chart2/source/view/charttypes/NetChart \ chart2/source/view/charttypes/PieChart \ chart2/source/view/charttypes/UnsupportedChart \ @@ -309,6 +313,10 @@ $(eval $(call gb_Library_add_exception_objects,chart2,\ chart2/source/model/template/AreaChartTypeTemplate \ chart2/source/model/template/BarChartType \ chart2/source/model/template/BarChartTypeTemplate \ + chart2/source/model/template/HistogramChartType \ + chart2/source/model/template/HistogramChartTypeTemplate \ + chart2/source/model/template/HistogramDataInterpreter \ + chart2/source/model/template/HistogramCalculator \ chart2/source/model/template/BoxWhiskerChartType \ chart2/source/model/template/BoxWhiskerChartTypeTemplate \ chart2/source/model/template/BubbleChartType \ @@ -323,6 +331,9 @@ $(eval $(call gb_Library_add_exception_objects,chart2,\ chart2/source/model/template/ColumnChartType \ chart2/source/model/template/ColumnLineChartTypeTemplate \ chart2/source/model/template/ColumnLineDataInterpreter \ + chart2/source/model/template/CorrelationCircleChartType \ + chart2/source/model/template/CorrelationCircleChartTypeTemplate \ + chart2/source/model/template/CorrelationCircleDataInterpreter \ chart2/source/model/template/DataInterpreter \ chart2/source/model/template/FilledNetChartType \ chart2/source/model/template/FunnelChartType \ @@ -374,6 +385,7 @@ $(eval $(call gb_Library_add_exception_objects,chart2,\ chart2/source/tools/ExponentialRegressionCurveCalculator \ chart2/source/tools/FillProperties \ chart2/source/tools/FormattedStringHelper \ + chart2/source/tools/HistogramDataSequence \ chart2/source/tools/InternalData \ chart2/source/tools/InternalDataProvider \ chart2/source/tools/LabeledDataSequence \ diff --git a/chart2/Module_chart2.mk b/chart2/Module_chart2.mk index 909e11e4bfc9..7a73312ba720 100644 --- a/chart2/Module_chart2.mk +++ b/chart2/Module_chart2.mk @@ -25,6 +25,8 @@ $(eval $(call gb_Module_add_l10n_targets,chart2,\ ifneq ($(OS),iOS) $(eval $(call gb_Module_add_check_targets,chart2,\ CppunitTest_chart2_common_functors \ + CppunitTest_chart2_correlation_coefficient \ + CppunitTest_chart2_splines \ )) $(eval $(call gb_Module_add_slowcheck_targets,chart2,\ diff --git a/chart2/inc/bitmaps.hlst b/chart2/inc/bitmaps.hlst index b4b5e77e2730..d0ee611dc676 100644 --- a/chart2/inc/bitmaps.hlst +++ b/chart2/inc/bitmaps.hlst @@ -11,6 +11,7 @@ inline constexpr OUString BMP_TYPE_COLUMN = u"chart2/res/typecolumn_16.png"_ustr; inline constexpr OUString BMP_TYPE_BAR = u"chart2/res/typebar_16.png"_ustr; +inline constexpr OUString BMP_TYPE_HISTOGRAM = u"chart2/res/typehistogram_16.png"_ustr; inline constexpr OUString BMP_TYPE_PIE = u"chart2/res/typepie_16.png"_ustr; inline constexpr OUString BMP_TYPE_OFPIE = u"chart2/res/typeofpie_16.png"_ustr; inline constexpr OUString BMP_TYPE_LINE = u"chart2/res/typepointline_16.png"_ustr; @@ -21,6 +22,10 @@ inline constexpr OUString BMP_TYPE_STOCK = u"chart2/res/typestock_16.png"_ustr; inline constexpr OUString BMP_TYPE_COLUMN_LINE = u"chart2/res/typecolumnline_16.png"_ustr; inline constexpr OUString BMP_TYPE_BUBBLE = u"chart2/res/typebubble_16.png"_ustr; inline constexpr OUString BMP_BUBBLE_1 = u"chart2/res/bubble_52x60.png"_ustr; +inline constexpr OUString BMP_TYPE_CORRELATION_CIRCLE + = u"chart2/res/typecorrelationcircle_16.png"_ustr; +inline constexpr OUString BMP_CORRELATION_CIRCLE + = u"chart2/res/correlationcircle_52x60.png"_ustr; inline constexpr OUString BMP_AREAS_2D = u"chart2/res/areas_52x60.png"_ustr; inline constexpr OUString BMP_AREAS_2D_1 = u"chart2/res/areaspiled_52x60.png"_ustr; inline constexpr OUString BMP_AREAS_2D_3 = u"chart2/res/areasfull_52x60.png"_ustr; @@ -52,6 +57,7 @@ inline constexpr OUString BMP_COLUMNS_3D = u"chart2/res/columns3ddeep_52x60.png" inline constexpr OUString BMP_COLUMNS_3D_1 = u"chart2/res/columns3d_52x60.png"_ustr; inline constexpr OUString BMP_COLUMNS_3D_2 = u"chart2/res/columnstack3d_52x60.png"_ustr; inline constexpr OUString BMP_COLUMNS_3D_3 = u"chart2/res/columnpercent3d_52x60.png"_ustr; +inline constexpr OUString BMP_HISTOGRAM = u"chart2/res/histogram_52x60.png"_ustr; inline constexpr OUString BMP_KEGELQ_3D_1 = u"chart2/res/conehori_52x60.png"_ustr; inline constexpr OUString BMP_KEGELQ_3D_2 = u"chart2/res/conehoristack_52x60.png"_ustr; inline constexpr OUString BMP_KEGELQ_3D_3 = u"chart2/res/conehoripercent_52x60.png"_ustr; diff --git a/chart2/inc/pch/precompiled_chart2.hxx b/chart2/inc/pch/precompiled_chart2.hxx index 164b4096bf0d..f34804aa731b 100644 --- a/chart2/inc/pch/precompiled_chart2.hxx +++ b/chart2/inc/pch/precompiled_chart2.hxx @@ -162,7 +162,6 @@ #include #include #include -#include #include #include #include @@ -394,7 +393,6 @@ #include #include #include -#include #include #include #include diff --git a/chart2/inc/strings.hrc b/chart2/inc/strings.hrc index b8a0e8f9c9cc..9d09aef45c36 100644 --- a/chart2/inc/strings.hrc +++ b/chart2/inc/strings.hrc @@ -27,6 +27,7 @@ #define STR_DLG_REMOVE_DATA_TABLE NC_("STR_DLG_REMOVE_DATA_TABLE", "This chart currently contains an internal data table. Do you want to proceed, deleting the internal data table, and set a new data range?") #define STR_PAGE_CHARTTYPE NC_("STR_PAGE_CHARTTYPE", "Chart Type") #define STR_PAGE_DATA_RANGE NC_("STR_PAGE_DATA_RANGE", "Data Range") +#define STR_RANGE_NOTE_DIMENSIONS NC_("STR_RANGE_NOTE_DIMENSIONS", "The last two columns hold the dimensions; the columns before them are the features.") #define STR_PAGE_CHART_ELEMENTS NC_("STR_PAGE_CHART_ELEMENTS", "Chart Elements") #define STR_OBJECT_AVERAGE_LINE_WITH_PARAMETERS NC_("STR_OBJECT_AVERAGE_LINE_WITH_PARAMETERS", "Mean value line with value %AVERAGE_VALUE and standard deviation %STD_DEVIATION") #define STR_OBJECT_AXIS NC_("STR_OBJECT_AXIS", "Axis") @@ -103,6 +104,7 @@ #define STR_DATA_ROLE_X NC_("STR_DATA_ROLE_X", "X-Values") #define STR_DATA_ROLE_Y NC_("STR_DATA_ROLE_Y", "Y-Values") #define STR_DATA_ROLE_SIZE NC_("STR_DATA_ROLE_SIZE", "Bubble Sizes") +#define STR_DATA_ROLE_FEATURE NC_("STR_DATA_ROLE_FEATURE", "Feature Values") #define STR_DATA_ROLE_X_ERROR NC_("STR_DATA_ROLE_X_ERROR", "X-Error-Bars") #define STR_DATA_ROLE_X_ERROR_POSITIVE NC_("STR_DATA_ROLE_X_ERROR_POSITIVE", "Positive X-Error-Bars") #define STR_DATA_ROLE_X_ERROR_NEGATIVE NC_("STR_DATA_ROLE_X_ERROR_NEGATIVE", "Negative X-Error-Bars") @@ -138,9 +140,13 @@ #define STR_TYPE_COLUMN NC_("STR_TYPE_COLUMN", "Column") #define STR_TYPE_BAR NC_("STR_TYPE_BAR", "Bar") +#define STR_TYPE_HISTOGRAM NC_("STR_TYPE_HISTOGRAM", "Histogram") +#define STR_HISTOGRAM NC_("STR_HISTOGRAM", "Histogram Chart") +#define STR_HISTOGRAM_BIN_WIDTH_GT_ZERO NC_("STR_HISTOGRAM_BIN_WIDTH_GT_ZERO", "The bin width requires a positive number. Check your input.") +#define STR_HISTOGRAM_INVALID_OVERFLOW_UNDERFLOW NC_("STR_HISTOGRAM_INVALID_OVERFLOW_UNDERFLOW", "The underflow value must be lower than the overflow value. Check your input.") #define STR_TYPE_AREA NC_("STR_TYPE_AREA", "Area") #define STR_TYPE_PIE NC_("STR_TYPE_PIE", "Pie") -#define STR_TYPE_OFPIE NC_("STR_TYPE_PIE", "Of-Pie") +#define STR_TYPE_OFPIE NC_("STR_TYPE_OFPIE", "Of-Pie") #define STR_PIE_EXPLODED NC_("STR_PIE_EXPLODED", "Exploded Pie Chart") #define STR_BAR_OF_PIE NC_("STR_BAR_OF_PIE", "Bar-of-pie Chart") #define STR_PIE_OF_PIE NC_("STR_PIE_OF_PIE", "Pie-of-pie Chart") @@ -168,6 +174,8 @@ #define STR_FILLED NC_("STR_FILLED", "Filled") #define STR_TYPE_BUBBLE NC_("STR_TYPE_BUBBLE", "Bubble") #define STR_BUBBLE_1 NC_("STR_BUBBLE_1", "Bubble Chart") +#define STR_TYPE_CORRELATION_CIRCLE NC_("STR_TYPE_CORRELATION_CIRCLE", "Correlation Circle") +#define STR_CORRELATION_CIRCLE NC_("STR_CORRELATION_CIRCLE", "Correlation Circle Plot") #define STR_INVALID_NUMBER NC_("STR_INVALID_NUMBER", "Numbers are required. Check your input.") #define STR_STEP_GT_ZERO NC_("STR_STEP_GT_ZERO", "The major interval requires a positive number. Check your input.") diff --git a/chart2/qa/extras/chart2dump/chart2dump.cxx b/chart2/qa/extras/chart2dump/chart2dump.cxx index 26a4207b79f2..4accb90d0b17 100644 --- a/chart2/qa/extras/chart2dump/chart2dump.cxx +++ b/chart2/qa/extras/chart2dump/chart2dump.cxx @@ -184,7 +184,7 @@ protected: aExpectedTransform.Line3.Column2 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); aExpectedTransform.Line3.Column3 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); - // Check the equality of the two transformation + // Check the equality of the two transformations return (std::abs(aExpectedTransform.Line1.Column1 - rTransform.Line1.Column1) < fEPS && std::abs(aExpectedTransform.Line1.Column2 - rTransform.Line1.Column2) < fEPS && std::abs(aExpectedTransform.Line1.Column3 - rTransform.Line1.Column3) < fEPS && @@ -653,7 +653,7 @@ CPPUNIT_TEST_FIXTURE(Chart2DumpTest, testAxisPercentStackedColumnChart) testAxisLabel(u"percent_stacked_column_chart.odp"_ustr); } -CPPUNIT_TEST_FIXTURE(Chart2DumpTest, testTdf118150) +CPPUNIT_TEST_FIXTURE(Chart2DumpTest, testTdf118150ChartWidthXlsx) { testAxisLabel(u"tdf118150.xlsx"_ustr); } diff --git a/chart2/qa/extras/chart2export2.cxx b/chart2/qa/extras/chart2export2.cxx index 2eab83be1633..71a9b0e40ee5 100644 --- a/chart2/qa/extras/chart2export2.cxx +++ b/chart2/qa/extras/chart2export2.cxx @@ -47,7 +47,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testSetSeriesToSecondaryAxisXLSX) save(TestFilter::XLSX); xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chart1.xml"_ustr); CPPUNIT_ASSERT(pXmlDoc); - // Check there are only two tag in the XML, one for the primary and one for the secondary axis. + // Check there are only two tags in the XML, one for the primary and one for the secondary axis. assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart", 2); } @@ -152,17 +152,35 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCrossBetweenODS) u"between"); } -CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_boxWhisker) +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexElementsXLSX_boxWhisker) { loadFromFile(u"xlsx/boxWhisker.xlsx"); save(TestFilter::XLSX); xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); CPPUNIT_ASSERT(pXmlDoc); + // Check title assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series", 3, 0, "layoutId", u"boxWhisker"); assertXPathContent(pXmlDoc, "/cx:chartSpace/cx:chart/cx:title/cx:tx/cx:txData/cx:v", u"BoxWhisker"); + + // Check visibility + // + // boxWhisker.xlsx has 3 series, each with visibility attributes. + // Verify the first series's visibility attributes round-trip correctly. + OString sSeriesPath = "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series[1]"_ostr; + + assertXPathNoAttribute(pXmlDoc, sSeriesPath + "/cx:layoutPr/cx:visibility", "connectorLines"); + assertXPath(pXmlDoc, sSeriesPath + "/cx:layoutPr/cx:visibility", "meanLine", u"0"); + assertXPath(pXmlDoc, sSeriesPath + "/cx:layoutPr/cx:visibility", "meanMarker", u"1"); + assertXPath(pXmlDoc, sSeriesPath + "/cx:layoutPr/cx:visibility", "nonoutliers", u"0"); + assertXPath(pXmlDoc, sSeriesPath + "/cx:layoutPr/cx:visibility", "outliers", u"1"); + assertXPath(pXmlDoc, sSeriesPath + "/cx:layoutPr/cx:statistics", "quartileMethod", + u"exclusive"); + + // There should not be a dataLabels tag + assertXPath(pXmlDoc, sSeriesPath + "/cx:dataLabels", 0); } CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_clusteredColumn) @@ -194,6 +212,8 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_funnel1) "val", u"c55a11"); assertXPathContent(pXmlDoc, "/cx:chartSpace/cx:chart/cx:title/cx:tx/cx:txData/cx:v", u"Funnel chart!"); + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis/cx:catScaling", "gapWidth", + u"0.06"); } CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_paretoLine) @@ -203,12 +223,20 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_paretoLine) xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); CPPUNIT_ASSERT(pXmlDoc); + OString sSeriesBase = "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series"_ostr; // A pareto chart from MSO really consists of two subcharts: a pareto line // and a clustered column chart. - assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series", 2, 0, - "layoutId", u"clusteredColumn"); - assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series", 2, 1, - "layoutId", u"paretoLine"); + + // First series: clusteredColumn with its own dataId, no ownerIdx. + assertXPath(pXmlDoc, sSeriesBase, 2, 0, "layoutId", u"clusteredColumn"); + assertXPathNoAttribute(pXmlDoc, sSeriesBase + "[1]", "ownerIdx"); + assertXPath(pXmlDoc, sSeriesBase + "[1]/cx:dataId", "val", u"0"); + + // Second series: paretoLine sharing the first series's data. + assertXPath(pXmlDoc, sSeriesBase, 2, 1, "layoutId", u"paretoLine"); + assertXPath(pXmlDoc, sSeriesBase + "[2]", "ownerIdx", u"0"); + assertXPath(pXmlDoc, sSeriesBase + "[2]/cx:dataId", 0); + assertXPathContent(pXmlDoc, "/cx:chartSpace/cx:chart/cx:title/cx:tx/cx:txData/cx:v", u"ParetoLine"); } @@ -224,6 +252,11 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_regionMap) "layoutId", u"regionMap"); assertXPathContent(pXmlDoc, "/cx:chartSpace/cx:chart/cx:title/cx:tx/cx:txData/cx:v", u"RegionMap"); + + assertXPath(pXmlDoc, + "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:layoutPr/" + "cx:regionLabelLayout", + "val", u"bestFitOnly"); } CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_sunburst) @@ -237,6 +270,11 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_sunburst) "layoutId", u"sunburst"); assertXPathContent(pXmlDoc, "/cx:chartSpace/cx:chart/cx:title/cx:tx/cx:txData/cx:v", u"Sunburst"); + + assertXPath(pXmlDoc, + "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:layoutPr/" + "cx:parentLabelLayout", + "val", u"overlapping"); } CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_treemap) @@ -265,6 +303,67 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexTitleXLSX_waterfall) u"Waterfall"); } +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexPerPointDataLabelXLSX) +{ + loadFromFile(u"xlsx/funnel1.xlsx"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + Reference xPoint(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW); + chart2::DataPointLabel aLabel; + xPoint->getPropertyValue(u"Label"_ustr) >>= aLabel; + aLabel.ShowNumber = true; + xPoint->setPropertyValue(u"Label"_ustr, uno::Any(aLabel)); + xPoint->setPropertyValue(u"LabelPlacement"_ustr, uno::Any(chart::DataLabelPlacement::CENTER)); + + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + OString sDataLabelPath = "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/" + "cx:dataLabels/cx:dataLabel"_ostr; + assertXPath(pXmlDoc, sDataLabelPath, "idx", u"0"); + assertXPath(pXmlDoc, sDataLabelPath, "pos", u"ctr"); + // Group-level label properties must precede the cx:dataLabel elements + assertXPath(pXmlDoc, + sDataLabelPath + + "/following-sibling::*[not(self::cx:dataLabel or " + "self::cx:dataLabelHidden or self::cx:extLst)]", + 0); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexDataLabelsRoundTrip) +{ + loadFromFile(u"xlsx/funnel-label-options.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + OString sLabelsPath = "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/" + "cx:dataLabels"_ostr; + + // Group-level position and separator + assertXPath(pXmlDoc, sLabelsPath, "pos", u"ctr"); + assertXPathContent(pXmlDoc, sLabelsPath + "/cx:separator", u", "); + + // Individual label positions + assertXPath(pXmlDoc, sLabelsPath + "/cx:dataLabel[@idx='0']", "pos", u"t"); + assertXPath(pXmlDoc, sLabelsPath + "/cx:dataLabel[@idx='3']", "pos", u"b"); + assertXPath(pXmlDoc, sLabelsPath + "/cx:dataLabel[@idx='7']", "pos", u"inEnd"); + + // Individual label number format and separator + assertXPath(pXmlDoc, sLabelsPath + "/cx:dataLabel[@idx='0']/cx:numFmt", "formatCode", u"0.00%"); + assertXPathContent(pXmlDoc, sLabelsPath + "/cx:dataLabel[@idx='0']/cx:separator", u";"); + + // Hidden labels, after the cx:dataLabel elements + assertXPath(pXmlDoc, sLabelsPath + "/cx:dataLabelHidden", 2); + assertXPath(pXmlDoc, sLabelsPath + "/cx:dataLabelHidden[@idx='4']", 1); + assertXPath(pXmlDoc, sLabelsPath + "/cx:dataLabelHidden[@idx='8']", 1); + assertXPath(pXmlDoc, sLabelsPath + "/cx:dataLabelHidden/following-sibling::cx:dataLabel", 0); +} + CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexPPTX) { loadFromFile(u"pptx/funnel-pp1.pptx"); @@ -274,6 +373,47 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexPPTX) assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series", 3, 0, "layoutId", u"funnel"); + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis/cx:catScaling", "gapWidth", + u"2.19"); + // Ensure no fictitious legend shape props gets inserted + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:legend/cx:spPr", 0); + + static constexpr OString sCat + = "/cx:chartSpace/cx:chartData/cx:data[@id='0']/cx:strDim[@type='cat']"_ostr; + static constexpr OString sVal + = "/cx:chartSpace/cx:chartData/cx:data[@id='0']/cx:numDim[@type='val']"_ostr; + // tdf#165742: the category strDim must contain the category labels, not + // the series values. + assertXPathContent(pXmlDoc, sCat + "/cx:lvl/cx:pt[@idx='0']", u"Thing 1"); + assertXPathContent(pXmlDoc, sCat + "/cx:lvl/cx:pt[@idx='1']", u"Thing 2"); + assertXPathContent(pXmlDoc, sCat + "/cx:lvl/cx:pt[@idx='2']", u"Thing 3"); + assertXPathContent(pXmlDoc, sCat + "/cx:lvl/cx:pt[@idx='3']", u"Thing 4"); + + // Verify the data formulas round-trip properly + assertXPathContent(pXmlDoc, sCat + "/cx:f", u"Sheet1!$A$2:$A$5"); + assertXPathContent(pXmlDoc, sVal + "/cx:f", u"Sheet1!$B$2:$B$5"); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexGapWidth) +{ + loadFromFile(u"xlsx/box-whisker-gapwidth.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis/cx:catScaling", "gapWidth", + u"2.47"); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexGapWidth2) +{ + loadFromFile(u"xlsx/pareto-gapwidth.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis/cx:catScaling", "gapWidth", + u"2.55"); } CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexAxes) @@ -286,6 +426,11 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexAxes) // Should be two axes assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis", 2); assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis/cx:tickLabels", 2); + + // There should *not* be a fill in the series shape properties + assertXPath( + pXmlDoc, + "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:spPr/a:solidFill", 0); } CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexBinningXLSX) @@ -301,6 +446,118 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexBinningXLSX) "intervalClosed", u"r"); } +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexNoSpPr) +{ + loadFromFile(u"xlsx/regionMap.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + // Verify that the series is there but that it has no spPr child + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series"); + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:spPr", + 0); + + // chartSpace, title, and plotArea each take an optional cx:spPr child + // in the chartex schema. Make sure we're not making up default values for + // these. + assertXPath(pXmlDoc, "/cx:chartSpace/cx:spPr", 0); + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:title/cx:spPr", 0); + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:spPr", 0); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexExplicitSpPr) +{ + // waterfall2.xlsx has explicit on chartSpace and title (but + // not plotArea). Make sure these are round-tripping properly (both + // existence and nonexistence). + loadFromFile(u"xlsx/waterfall2.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/cx:chartSpace/cx:spPr", 1); + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:title/cx:spPr", 1); + // The source has no plotArea-level spPr; suppression must hold here too. + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:spPr", 0); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexAxisRoundTrip) +{ + // paretoLine.xlsx has three axes identified by @id: + // id=0 cx:catScaling axis (category) + // id=1 empty cx:valScaling + empty cx:majorGridlines + // id=2 cx:valScaling min="0" max="1" + cx:units unit="percentage" + // Round-trip via the chart2 model must preserve all of these. + loadFromFile(u"xlsx/paretoLine.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + OString sAxisId1 = "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis[@id='1']"_ostr; + OString sAxisId2 = "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis[@id='2']"_ostr; + + // axis id=2: cx:valScaling preserves min/max. + assertXPath(pXmlDoc, sAxisId2 + "/cx:valScaling", "min", u"0"); + assertXPath(pXmlDoc, sAxisId2 + "/cx:valScaling", "max", u"1"); + + // axis id=2: cx:units uses the flat chartex form with a "unit" + // attribute, not a c-namespace style unitsLabel child. + assertXPath(pXmlDoc, sAxisId2 + "/cx:units", "unit", u"percentage"); + assertXPath(pXmlDoc, sAxisId2 + "/cx:units/cx:unitsLabel", 0); + + // axis id=1: source has no cx:spPr; we must not + // invent one on export. + assertXPath(pXmlDoc, sAxisId1 + "/cx:majorGridlines", 1); + assertXPath(pXmlDoc, sAxisId1 + "/cx:majorGridlines/cx:spPr", 0); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexAxisIdPerSeries) +{ + // Waterfall charts have two axes. Each series should reference both via + // cx:axisId, and the plot area should contain exactly two cx:axis + // elements. + loadFromFile(u"xlsx/waterfall2.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, + "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series[1]/cx:axisId", 2); + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis", 2); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testFunnelCharts) +{ + // Funnel charts have one axis. (At least as MSO produces them -- arguably + // there are two dimensions, but we'll stick with the MSO convention for + // now.) The series should reference it via + // cx:axisId, and the plot area should contain exactly one cx:axis + // elements. + loadFromFile(u"xlsx/funnel1.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, + "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:axisId", 1); + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis", 1); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testRegionMap) +{ + // RegionMap charts have no axes. The series should have no cx:axisId and the plot + // area should have no cx:axis. + loadFromFile(u"xlsx/regionMap.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, + "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:axisId", 0); + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis", 0); +} + CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testAxisTitleRotationXLSX) { loadFromFile(u"xlsx/axis_title_rotation.xlsx"); @@ -1840,6 +2097,86 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf166249) "val", u"128"); } +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexGeography) +{ + loadFromFile(u"xlsx/regionMap.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + static constexpr OString sSeriesBase + = "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series"_ostr; + OString sLayoutPr = sSeriesBase + "/cx:layoutPr"_ostr; + OString sGeo = sLayoutPr + "/cx:geography"_ostr; + + // geography element with correct attributes + assertXPath(pXmlDoc, sGeo, "cultureLanguage", u"en-US"); + assertXPath(pXmlDoc, sGeo, "cultureRegion", u"GB"); + + // geoCache with provider + OString sCache = sGeo + "/cx:geoCache"_ostr; + assertXPath(pXmlDoc, sCache, "provider", u"{E9337A44-BEBE-4D9F-B70C-5C5E7DAFC167}"); + + // binary element exists and starts with the expected base64 prefix + OString sBinary = sCache + "/cx:binary"_ostr; + assertXPath(pXmlDoc, sBinary, 1); + OUString sBinaryContent = getXPathContent(pXmlDoc, sBinary); + CPPUNIT_ASSERT(sBinaryContent.startsWith(u"7HvJkt24kuWvpOWm")); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexDimRoundTrip_regionMap) +{ + // regionMap.xlsx has strDim type="cat" and numDim type="colorVal", + // each with and formulas. Verify they round-trip. + loadFromFile(u"xlsx/regionMap.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + static constexpr OString sData = "/cx:chartSpace/cx:chartData/cx:data"_ostr; + + // strDim with type="cat" + assertXPath(pXmlDoc, sData + "/cx:strDim", "type", u"cat"); + assertXPathContent(pXmlDoc, sData + "/cx:strDim/cx:f", u"_xlchart.v5.1"); + assertXPathContent(pXmlDoc, sData + "/cx:strDim/cx:nf", u"_xlchart.v5.0"); + + // numDim with type="colorVal" + assertXPath(pXmlDoc, sData + "/cx:numDim", "type", u"colorVal"); + assertXPathContent(pXmlDoc, sData + "/cx:numDim/cx:f", u"_xlchart.v5.3"); + assertXPathContent(pXmlDoc, sData + "/cx:numDim/cx:nf", u"_xlchart.v5.2"); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexDimRoundTrip_boxWhisker) +{ + // boxWhisker.xlsx has 3 numDim type="val" elements, one per data series. + loadFromFile(u"xlsx/boxWhisker.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + // data id=0 + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data[@id='0']/cx:numDim", "type", u"val"); + assertXPathContent(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data[@id='0']/cx:numDim/cx:f", + u"_xlchart.v1.0"); +} + +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexDimRoundTrip_sunburst) +{ + // sunburst.xlsx has strDim type="cat" and numDim type="size". + loadFromFile(u"xlsx/sunburst.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + static constexpr OString sData = "/cx:chartSpace/cx:chartData/cx:data"_ostr; + + assertXPath(pXmlDoc, sData + "/cx:strDim", "type", u"cat"); + assertXPathContent(pXmlDoc, sData + "/cx:strDim/cx:f", u"_xlchart.v1.0"); + + assertXPath(pXmlDoc, sData + "/cx:numDim", "type", u"size"); + assertXPathContent(pXmlDoc, sData + "/cx:numDim/cx:f", u"_xlchart.v1.1"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/qa/extras/chart2import2.cxx b/chart2/qa/extras/chart2import2.cxx index 60431a6b036a..04e0770dd143 100644 --- a/chart2/qa/extras/chart2import2.cxx +++ b/chart2/qa/extras/chart2import2.cxx @@ -15,9 +15,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -158,7 +160,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf128634) CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf130657) { loadFromFile(u"xlsx/tdf130657.xlsx"); - // Test ShiftedCategoryPosition for charts which is not contain a "crossbetween" OOXML tag. + // Test ShiftedCategoryPosition for charts which do not contain a "crossbetween" OOXML tag. uno::Reference xChartDoc = getChartDocFromSheet(0); CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); @@ -397,7 +399,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf125444PercentageCustomLabel) Reference xDp = xDataSeries->getDataPointByIndex(1); Sequence> aLabelFields; CPPUNIT_ASSERT(xDp->getPropertyValue(u"CustomLabelFields"_ustr) >>= aLabelFields); - // There are three label field: a value label, a newline and a percentage label. We want + // There are three label fields: a value label, a newline and a percentage label. We want // to assert the latter. CPPUNIT_ASSERT_EQUAL(static_cast(3), aLabelFields.getLength()); CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType_PERCENTAGE, @@ -496,6 +498,119 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testStockChartShiftedCategoryPosition) CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition); } +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testFunnelChartShiftedCategoryPosition) +{ + loadFromFile(u"xlsx/color_funnel.xlsx"); + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is()); + + Reference xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xAxis.is()); + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testChartexDataLabelOptions) +{ + loadFromFile(u"xlsx/funnel-label-options.xlsx"); + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xDataSeries = getDataSeriesFromDoc(xChartDoc, 0); + CPPUNIT_ASSERT(xDataSeries.is()); + + // Series-level label settings from + Reference xSeriesProp(xDataSeries, UNO_QUERY_THROW); + chart2::DataPointLabel aLabel; + CPPUNIT_ASSERT(xSeriesProp->getPropertyValue(u"Label"_ustr) >>= aLabel); + CPPUNIT_ASSERT(aLabel.ShowNumber); + CPPUNIT_ASSERT(aLabel.ShowCategoryName); + CPPUNIT_ASSERT(!aLabel.ShowSeriesName); + CPPUNIT_ASSERT(!aLabel.ShowLegendSymbol); + OUString sSeparator; + CPPUNIT_ASSERT(xSeriesProp->getPropertyValue(u"LabelSeparator"_ustr) >>= sSeparator); + CPPUNIT_ASSERT_EQUAL(u", "_ustr, sSeparator); + sal_Int32 nPlacement = -1; + CPPUNIT_ASSERT(xSeriesProp->getPropertyValue(u"LabelPlacement"_ustr) >>= nPlacement); + CPPUNIT_ASSERT_EQUAL(chart::DataLabelPlacement::CENTER, nPlacement); + + // : value only, with a percentage number format + Reference xPoint(xDataSeries->getDataPointByIndex(0), UNO_SET_THROW); + CPPUNIT_ASSERT(xPoint->getPropertyValue(u"Label"_ustr) >>= aLabel); + CPPUNIT_ASSERT(aLabel.ShowNumber); + CPPUNIT_ASSERT(!aLabel.ShowCategoryName); + CPPUNIT_ASSERT(!aLabel.ShowSeriesName); + CPPUNIT_ASSERT(xPoint->getPropertyValue(u"LabelPlacement"_ustr) >>= nPlacement); + CPPUNIT_ASSERT_EQUAL(chart::DataLabelPlacement::TOP, nPlacement); + sal_Int32 nNumFmt = -1; + CPPUNIT_ASSERT(xPoint->getPropertyValue(u"NumberFormat"_ustr) >>= nNumFmt); + Reference xNFS(xChartDoc, uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(xNFS->getNumberFormats()->queryKey(u"0.00%"_ustr, lang::Locale(), false), + nNumFmt); + + // : series name only + xPoint.set(xDataSeries->getDataPointByIndex(1), UNO_SET_THROW); + CPPUNIT_ASSERT(xPoint->getPropertyValue(u"Label"_ustr) >>= aLabel); + CPPUNIT_ASSERT(!aLabel.ShowNumber); + CPPUNIT_ASSERT(!aLabel.ShowCategoryName); + CPPUNIT_ASSERT(aLabel.ShowSeriesName); + + // + xPoint.set(xDataSeries->getDataPointByIndex(7), UNO_SET_THROW); + CPPUNIT_ASSERT(xPoint->getPropertyValue(u"LabelPlacement"_ustr) >>= nPlacement); + CPPUNIT_ASSERT_EQUAL(chart::DataLabelPlacement::INSIDE, nPlacement); + + // : category name only + xPoint.set(xDataSeries->getDataPointByIndex(11), UNO_SET_THROW); + CPPUNIT_ASSERT(xPoint->getPropertyValue(u"Label"_ustr) >>= aLabel); + CPPUNIT_ASSERT(!aLabel.ShowNumber); + CPPUNIT_ASSERT(aLabel.ShowCategoryName); + CPPUNIT_ASSERT(!aLabel.ShowSeriesName); + + // : no label parts are shown + xPoint.set(xDataSeries->getDataPointByIndex(4), UNO_SET_THROW); + CPPUNIT_ASSERT(xPoint->getPropertyValue(u"Label"_ustr) >>= aLabel); + CPPUNIT_ASSERT(!aLabel.ShowNumber); + CPPUNIT_ASSERT(!aLabel.ShowNumberInPercent); + CPPUNIT_ASSERT(!aLabel.ShowCategoryName); + CPPUNIT_ASSERT(!aLabel.ShowLegendSymbol); + CPPUNIT_ASSERT(!aLabel.ShowSeriesName); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testFunnelRendering) +{ + loadFromFile(u"pptx/funnel-pp1.pptx"); + Reference xChartDoc = getChartDocFromDrawImpress(0, 0); + Reference xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW); + Reference xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW); + Reference xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW); + Reference xSeries(getShapeByName(xShapes, u"CID/D=0:CS=0:CT=0:Series=0"_ustr), + UNO_SET_THROW); + + Reference xIndexAccess(xSeries, UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xIndexAccess->getCount()); + + // Data values of the first series + const double aValues[] = { 4.3, 2.5, 3.5, 4.5 }; + + Reference xBar0(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); + const double fWidth0 = xBar0->getSize().Width; + const double fCenter0 = xBar0->getPosition().X + fWidth0 / 2.0; + CPPUNIT_ASSERT(fWidth0 > 0); + + for (sal_Int32 i = 1; i < 4; ++i) + { + Reference xBar(xIndexAccess->getByIndex(i), UNO_QUERY_THROW); + const double fWidth = xBar->getSize().Width; + const double fCenter = xBar->getPosition().X + fWidth / 2.0; + // All bars share a common vertical center line + CPPUNIT_ASSERT_DOUBLES_EQUAL(fCenter0, fCenter, 30); + // Bar lengths are proportional to the data values + CPPUNIT_ASSERT_DOUBLES_EQUAL(aValues[i] / aValues[0], fWidth / fWidth0, 0.02); + } +} + CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf133376) { // FIXME: the DPI check should be removed when either (1) the test is fixed to work with @@ -882,6 +997,32 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testChartDataTableWithMultipleLegendEntr CPPUNIT_ASSERT(xDataTableShape.is()); } +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf159450AxisTitleWithDataTable) +{ + // The chart has a vertical axis title and a data table below the plot area. + // The axis title must stay centered on the plot area, not on the whole + // diagram including the data table below it (which used to shift it down). + loadFromFile(u"xlsx/tdf159450.xlsx"); + auto xDrawPage + = getChartDocFromSheet(0).queryThrow()->getDrawPage(); + auto xShapes = xDrawPage->getByIndex(0).queryThrow(); + + // The chart has a data table, drawn below the plot area. + CPPUNIT_ASSERT(getShapeByName(xShapes, u"CID/D=0:DataTable="_ustr).is()); + Reference xPlotArea = getShapeByName(xShapes, u"PlotAreaExcludingAxes"_ustr); + CPPUNIT_ASSERT(xPlotArea.is()); + Reference xAxisTitle + = getShapeByName(xShapes, u"CID/D=0:CS=0:Axis=1,0:Title="_ustr); + CPPUNIT_ASSERT(xAxisTitle.is()); + + // The vertical axis title is centered on the plot area. Before the fix it was + // centered on the plot area plus the data table below it, so its center sat + // about half the data table height lower. + sal_Int32 nTitleCenterY = xAxisTitle->getPosition().Y + xAxisTitle->getSize().Height / 2; + sal_Int32 nPlotCenterY = xPlotArea->getPosition().Y + xPlotArea->getSize().Height / 2; + CPPUNIT_ASSERT_DOUBLES_EQUAL(nPlotCenterY, nTitleCenterY, 20); +} + namespace { void lcl_assertAngles(const Reference& rAxis, const double& rExpectedLabelAngle, @@ -941,7 +1082,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf166428) // The file was generated in ODF 1.3 by LO 24.8 loadFromFile(u"ods/tdf166428_Low_High_StockChart_LO248.ods"); - // The attribute table:cell-range-address does not exist in ODF 1.4. and therefore may not be + // The attribute table:cell-range-address does not exist in ODF 1.4. and therefore may not // be written. saveAndReload(TestFilter::ODS); xmlDocUniquePtr pXmlDoc = parseExport(u"Object 1/content.xml"_ustr); @@ -960,6 +1101,829 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf166428) CPPUNIT_ASSERT(xDataSeq.is()); } +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramODSRoundtrip) +{ + // See tdf#163727 + loadFromFile(u"fods/tdf163727_histogram_roundtrip.fods"); + + // Round trip 1: chart type identity, raw data unchanged + saveAndReload(TestFilter::ODS); + + xmlDocUniquePtr pXmlDoc = parseExport(u"Object 1/content.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/office:document-content/office:body/office:chart/chart:chart" + "[@chart:class='chart:bar']"); + assertXPath(pXmlDoc, "/office:document-content/office:body/office:chart/chart:chart" + "[@loext:class='loext:histogram']"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.chart2.HistogramChartType"_ustr, + xChartType->getChartType()); + + // Raw values-y preserved, calculated-y not persisted. + Reference xValuesY + = getDataSequenceFromDocByRole(xChartDoc, u"values-y"); + CPPUNIT_ASSERT(xValuesY.is()); + + Reference xCalculatedY + = getDataSequenceFromDocByRole(xChartDoc, u"calculated-y"); + CPPUNIT_ASSERT(!xCalculatedY.is()); + + // After reload the series must carry a categories sequence with bin range + // labels, not just the raw values-y. + Reference xCategories + = getDataSequenceFromDocByRole(xChartDoc, u"categories"); + CPPUNIT_ASSERT(xCategories.is()); + Reference xCategoriesText(xCategories, uno::UNO_QUERY); + CPPUNIT_ASSERT(xCategoriesText.is()); + const Sequence aBinLabels = xCategoriesText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"[10-13.94]"_ustr, aBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(13.94-17.87]"_ustr, aBinLabels[1]); + + // Round trip 2: non-default binning parameters survive + Reference xProps(xChartType, uno::UNO_QUERY_THROW); + xProps->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(1))); + xProps->setPropertyValue(u"BinWidth"_ustr, uno::Any(3.5)); + + saveAndReload(TestFilter::ODS); + + pXmlDoc = parseExport(u"Object 1/content.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + static constexpr char sHistogramProps[] + = "/office:document-content/office:automatic-styles/style:style[@style:family='chart']/" + "style:chart-properties[@loext:frequency-type]"; + assertXPath(pXmlDoc, sHistogramProps, "frequency-type", u"1"); + assertXPath(pXmlDoc, sHistogramProps, "bin-width", u"3.5"); + + xChartDoc = getChartDocFromSheet(0); + xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + Reference xReloadedProps(xChartType, uno::UNO_QUERY_THROW); + + sal_Int32 nFrequencyType = -1; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), nFrequencyType); + + double fBinWidth = 0.0; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"BinWidth"_ustr) >>= fBinWidth); + CPPUNIT_ASSERT_EQUAL(3.5, fBinWidth); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testCorrelationCircleODSRoundtrip) +{ + loadFromFile(u"fods/correlation-circle.fods"); + + saveAndReload(TestFilter::ODS); + + xmlDocUniquePtr pXmlDoc = parseExport(u"Object 1/content.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + // A reader that knows nothing of this chart type is left with points in a + // plane, and the name of the type itself rides in the loext namespace. + assertXPath(pXmlDoc, "/office:document-content/office:body/office:chart/chart:chart" + "[@chart:class='chart:scatter']"); + assertXPath(pXmlDoc, "/office:document-content/office:body/office:chart/chart:chart" + "[@loext:class='loext:correlation-circle']"); + + // Each series keeps its feature column as the series range and the two + // dimension columns as a domain each. + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:chart/chart:chart" + "/chart:plot-area/chart:series", + 3); + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:chart/chart:chart" + "/chart:plot-area/chart:series[1]/chart:domain", + 2); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.chart2.CorrelationCircleChartType"_ustr, + xChartType->getChartType()); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc)); + + // One series per feature column, every one of them against the same two + // dimension columns. + const OUString aFeatureRanges[] + = { u"$Sheet1.$A$2:$A$6"_ustr, u"$Sheet1.$B$2:$B$6"_ustr, u"$Sheet1.$C$2:$C$6"_ustr }; + for (sal_Int32 nSeries = 0; nSeries < 3; ++nSeries) + { + Reference xFeature + = getDataSequenceFromDocByRole(xChartDoc, u"values-feature", nSeries); + CPPUNIT_ASSERT(xFeature.is()); + CPPUNIT_ASSERT_EQUAL(aFeatureRanges[nSeries], xFeature->getSourceRangeRepresentation()); + + Reference xFirstDimension + = getDataSequenceFromDocByRole(xChartDoc, u"values-x", nSeries); + CPPUNIT_ASSERT(xFirstDimension.is()); + CPPUNIT_ASSERT_EQUAL(u"$Sheet1.$D$2:$D$6"_ustr, + xFirstDimension->getSourceRangeRepresentation()); + + Reference xSecondDimension + = getDataSequenceFromDocByRole(xChartDoc, u"values-y", nSeries); + CPPUNIT_ASSERT(xSecondDimension.is()); + CPPUNIT_ASSERT_EQUAL(u"$Sheet1.$E$2:$E$6"_ustr, + xSecondDimension->getSourceRangeRepresentation()); + } +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramXLSXRoundtrip) +{ + // See tdf#163727 + // OOXML chartex represents histograms as + // with a child. + // On import that should be detected as a HistogramChartType and on export the binning + // markup should stay preserved. + + loadFromFile(u"xlsx/SimpleHistogram.xlsx"); + + // Round trip 1: chart type identity + binning element preserved. + saveAndReload(TestFilter::XLSX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series", + "layoutId", u"clusteredColumn"); + assertXPath(pXmlDoc, + "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:layoutPr/" + "cx:binning", + "intervalClosed", u"r"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.chart2.HistogramChartType"_ustr, + xChartType->getChartType()); + + // Raw values-y must remain the source data; calculated-y is regenerated. + Reference xValuesY + = getDataSequenceFromDocByRole(xChartDoc, u"values-y"); + CPPUNIT_ASSERT(xValuesY.is()); + + Reference xCalculatedY + = getDataSequenceFromDocByRole(xChartDoc, u"calculated-y"); + CPPUNIT_ASSERT(!xCalculatedY.is()); + + // The X axis carries the bin range labels from the histogram template, not the generic + // "1", "2", ... labels that the OOXML axis converter produces by default. The axis and the + // series read the same sequence, so the labels match the ones asserted for the series. + Reference xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xXAxis.is()); + chart2::ScaleData aScaleData = xXAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + Reference xAxisCatText(aScaleData.Categories->getValues(), + uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisCatText.is()); + const Sequence aAxisBinLabels = xAxisCatText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aAxisBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"[10-13.94]"_ustr, aAxisBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(13.94-17.87]"_ustr, aAxisBinLabels[1]); + + // Round trip 2: non-default binning parameters survive save + reload. + Reference xProperties(xChartType, uno::UNO_QUERY_THROW); + xProperties->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(1))); + xProperties->setPropertyValue(u"BinWidth"_ustr, uno::Any(2.5)); + + saveAndReload(TestFilter::XLSX); + + pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, + "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:layoutPr/" + "cx:binning/cx:binSize", + "val", u"2.5"); + + xChartDoc = getChartDocFromSheet(0); + xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + Reference xReloadedProperties(xChartType, uno::UNO_QUERY_THROW); + + sal_Int32 nFrequencyType = -1; + CPPUNIT_ASSERT(xReloadedProperties->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), nFrequencyType); + + double fBinWidth = 0.0; + CPPUNIT_ASSERT(xReloadedProperties->getPropertyValue(u"BinWidth"_ustr) >>= fBinWidth); + CPPUNIT_ASSERT_EQUAL(2.5, fBinWidth); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramBinCountLiveUpdate) +{ + loadFromFile(u"fods/tdf163727_histogram_roundtrip.fods"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + // Keep the category sequence currently held by the X axis. Changing the + // bin count must update this same sequence instead of leaving it stale + Reference xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xXAxis.is()); + + chart2::ScaleData aScaleData = xXAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + + Reference xAxisCategories( + aScaleData.Categories->getValues(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisCategories.is()); + + const Sequence aOriginalLabels = xAxisCategories->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aOriginalLabels.getLength()); + + Reference xProperties(xChartType, uno::UNO_QUERY_THROW); + + // Switching to fixed-count mode initially uses the stored default of ten bins. + xProperties->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(2))); + + const Sequence aFixedCountLabels = xAxisCategories->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(10), aFixedCountLabels.getLength()); + + // Changing the count must update the same sequence without save/reload. + xProperties->setPropertyValue(u"BinCount"_ustr, uno::Any(sal_Int32(3))); + + const Sequence aUpdatedLabels = xAxisCategories->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aUpdatedLabels.getLength()); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramBinWidthFarBelowRangeIsBounded) +{ + loadFromFile(u"fods/tdf163727_histogram_roundtrip.fods"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xXAxis.is()); + + chart2::ScaleData aScaleData = xXAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + + Reference xAxisCategories( + aScaleData.Categories->getValues(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisCategories.is()); + + Reference xProperties(xChartType, uno::UNO_QUERY_THROW); + xProperties->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(1))); + + // The values span roughly eight units, so bins a millionth wide would number in the + // millions. The count stays within the limit the calculator caps it at. + xProperties->setPropertyValue(u"BinWidth"_ustr, uno::Any(0.000001)); + + const Sequence aLabels = xAxisCategories->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(10000), aLabels.getLength()); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramBinCountRoundtrip_ODS) +{ + // ODF: fixed number of bins survives export/reload at the model level. + loadFromFile(u"fods/tdf163727_histogram_roundtrip.fods"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xProps(xChartType, uno::UNO_QUERY_THROW); + xProps->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(2))); + xProps->setPropertyValue(u"BinCount"_ustr, uno::Any(sal_Int32(3))); + + saveAndReload(TestFilter::ODS); + + xmlDocUniquePtr pXmlDoc = parseExport(u"Object 1/content.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + static constexpr char sHistogramProps[] + = "/office:document-content/office:automatic-styles/style:style[@style:family='chart']/" + "style:chart-properties[@loext:frequency-type]"; + assertXPath(pXmlDoc, sHistogramProps, "frequency-type", u"2"); + assertXPath(pXmlDoc, sHistogramProps, "bin-count", u"3"); + + xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xReloadedProps(xChartType, uno::UNO_QUERY_THROW); + + sal_Int32 nFrequencyType = -1; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), nFrequencyType); + + sal_Int32 nBinCount = -1; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"BinCount"_ustr) >>= nBinCount); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), nBinCount); + + Reference xCategories + = getDataSequenceFromDocByRole(xChartDoc, u"categories"); + CPPUNIT_ASSERT(xCategories.is()); + + Reference xCategoriesText(xCategories, uno::UNO_QUERY); + CPPUNIT_ASSERT(xCategoriesText.is()); + + const Sequence aBinLabels = xCategoriesText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"[10-11.67]"_ustr, aBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(11.67-13.33]"_ustr, aBinLabels[1]); + CPPUNIT_ASSERT_EQUAL(u"(13.33-15]"_ustr, aBinLabels[2]); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogram_COExt) +{ + loadFromFile(u"fods/tdf163727_histogram_COExt.fods"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xCategories + = getDataSequenceFromDocByRole(xChartDoc, u"categories"); + CPPUNIT_ASSERT(xCategories.is()); + + Reference xCategoriesText(xCategories, uno::UNO_QUERY); + CPPUNIT_ASSERT(xCategoriesText.is()); + + const Sequence aBinLabels = xCategoriesText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"[10-13.94]"_ustr, aBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(13.94-17.87]"_ustr, aBinLabels[1]); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramBinCountRoundtrip_XLSX) +{ + // XLSX: fixed number of bins is written as cx:binCount and survives reload. + loadFromFile(u"xlsx/SimpleHistogram.xlsx"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xXlsxProps(xChartType, uno::UNO_QUERY_THROW); + xXlsxProps->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(2))); + xXlsxProps->setPropertyValue(u"BinCount"_ustr, uno::Any(sal_Int32(3))); + + saveAndReload(TestFilter::XLSX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, + "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:layoutPr/" + "cx:binning/cx:binCount", + "val", u"3"); + + xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xXAxis.is()); + + chart2::ScaleData aScaleData = xXAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + + Reference xAxisCatText(aScaleData.Categories->getValues(), + uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisCatText.is()); + + const Sequence aAxisBinLabels = xAxisCatText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aAxisBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"[10-11.67]"_ustr, aAxisBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(11.67-13.33]"_ustr, aAxisBinLabels[1]); + CPPUNIT_ASSERT_EQUAL(u"(13.33-15]"_ustr, aAxisBinLabels[2]); + + Reference xReloadedXlsxProps(xChartType, uno::UNO_QUERY_THROW); + + sal_Int32 nFrequencyType = -1; + CPPUNIT_ASSERT(xReloadedXlsxProps->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), nFrequencyType); + + sal_Int32 nBinCount = -1; + CPPUNIT_ASSERT(xReloadedXlsxProps->getPropertyValue(u"BinCount"_ustr) >>= nBinCount); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), nBinCount); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramUnderflowOverflowBins) +{ + loadFromFile(u"fods/tdf163727_histogram_roundtrip.fods"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xProps(xChartType, uno::UNO_QUERY_THROW); + xProps->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(1))); + xProps->setPropertyValue(u"BinWidth"_ustr, uno::Any(2.0)); + xProps->setPropertyValue(u"UseUnderflowBin"_ustr, uno::Any(true)); + xProps->setPropertyValue(u"UnderflowBinValue"_ustr, uno::Any(11.0)); + xProps->setPropertyValue(u"UseOverflowBin"_ustr, uno::Any(true)); + xProps->setPropertyValue(u"OverflowBinValue"_ustr, uno::Any(14.0)); + + Reference xCategories + = getDataSequenceFromDocByRole(xChartDoc, u"categories"); + CPPUNIT_ASSERT(xCategories.is()); + + Reference xCategoriesText(xCategories, uno::UNO_QUERY); + CPPUNIT_ASSERT(xCategoriesText.is()); + + const Sequence aBinLabels = xCategoriesText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"<= 11"_ustr, aBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(11-13]"_ustr, aBinLabels[1]); + CPPUNIT_ASSERT_EQUAL(u"(13-14]"_ustr, aBinLabels[2]); + CPPUNIT_ASSERT_EQUAL(u"> 14"_ustr, aBinLabels[3]); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramAutomaticODSToXLSXRoundtrip) +{ + loadFromFile(u"fods/tdf163727_histogram_roundtrip.fods"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + Reference xProperties(xChartType, uno::UNO_QUERY_THROW); + + sal_Int32 nFrequencyType = -1; + CPPUNIT_ASSERT(xProperties->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nFrequencyType); + + saveAndReload(TestFilter::XLSX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + static constexpr OString sBinning + = "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/" + "cx:layoutPr/cx:binning"_ostr; + + assertXPath(pXmlDoc, sBinning, 1); + assertXPath(pXmlDoc, sBinning + "/cx:binSize", 0); + assertXPath(pXmlDoc, sBinning + "/cx:binCount", 0); + + xChartDoc = getChartDocFromSheet(0); + xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + xProperties.set(xChartType, uno::UNO_QUERY_THROW); + + nFrequencyType = -1; + CPPUNIT_ASSERT(xProperties->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nFrequencyType); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramODSToXLSXExport) +{ + // Exporting an ODF-origin histogram to XLSX must write the raw + // cell range, not an _xlchart.v1.N alias with no matching definedName. + loadFromFile(u"fods/tdf163727_histogram_roundtrip.fods"); + saveAndReload(TestFilter::XLSX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data/cx:numDim", "type", u"val"); + + OUString aFormula + = getXPathContent(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data/cx:numDim/cx:f"); + OString aMessage = "got formula: " + OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), !aFormula.startsWith("_xlchart")); + // The FODS series points at Sheet1.A1:A5. After conversion to XLSX + // notation the range should look like Sheet1!$A$1:$A$5. + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), aFormula.indexOf(u"Sheet1") >= 0); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), aFormula.indexOf(u"$A$1") >= 0); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), aFormula.indexOf(u"$A$5") >= 0); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramMultiChartODSToXLSXExport) +{ + // Multi-chart export must not reuse the same ChartEx formula for all histograms. + loadFromFile(u"fods/tdf163727_histogram_roundtrip_multi_chart.fods"); + saveAndReload(TestFilter::XLSX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + CPPUNIT_ASSERT_EQUAL( + u"Sheet1!$A$1:$A$6"_ustr, + getXPathContent(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data/cx:numDim/cx:f")); + + pXmlDoc = parseExport(u"xl/charts/chartEx2.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + CPPUNIT_ASSERT_EQUAL( + u"Sheet1!$B$1:$B$5"_ustr, + getXPathContent(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data/cx:numDim/cx:f")); + + pXmlDoc = parseExport(u"xl/charts/chartEx3.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + CPPUNIT_ASSERT_EQUAL( + u"Sheet1!$C$1:$C$6"_ustr, + getXPathContent(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data/cx:numDim/cx:f")); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramMultiChartXLSXRoundtrip) +{ + // Native ChartEx roundtrip must keep each histogram bound to its own source range. + loadFromFile(u"xlsx/tdf163727_histogram_roundtrip_multi_chart.xlsx"); + saveAndReload(TestFilter::XLSX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + CPPUNIT_ASSERT_EQUAL( + u"Sheet1!$A$1:$A$6"_ustr, + getXPathContent(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data/cx:numDim/cx:f")); + + pXmlDoc = parseExport(u"xl/charts/chartEx2.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + CPPUNIT_ASSERT_EQUAL( + u"Sheet1!$B$1:$B$5"_ustr, + getXPathContent(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data/cx:numDim/cx:f")); + + pXmlDoc = parseExport(u"xl/charts/chartEx3.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + CPPUNIT_ASSERT_EQUAL( + u"Sheet1!$C$1:$C$6"_ustr, + getXPathContent(pXmlDoc, "/cx:chartSpace/cx:chartData/cx:data/cx:numDim/cx:f")); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramODFUnderflowOverflowRoundtrip) +{ + loadFromFile(u"fods/tdf163727_histogram_roundtrip.fods"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xProps(xChartType, uno::UNO_QUERY_THROW); + xProps->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(1))); + xProps->setPropertyValue(u"BinWidth"_ustr, uno::Any(2.0)); + xProps->setPropertyValue(u"UseUnderflowBin"_ustr, uno::Any(true)); + xProps->setPropertyValue(u"UnderflowBinValue"_ustr, uno::Any(11.0)); + xProps->setPropertyValue(u"UseOverflowBin"_ustr, uno::Any(true)); + xProps->setPropertyValue(u"OverflowBinValue"_ustr, uno::Any(14.0)); + + saveAndReload(TestFilter::ODS); + + xmlDocUniquePtr pXmlDoc = parseExport(u"Object 1/content.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + static constexpr char sHistogramProps[] + = "/office:document-content/office:automatic-styles/style:style[@style:family='chart']/" + "style:chart-properties[@loext:frequency-type]"; + + assertXPath(pXmlDoc, sHistogramProps, "frequency-type", u"1"); + assertXPath(pXmlDoc, sHistogramProps, "bin-width", u"2"); + assertXPath(pXmlDoc, sHistogramProps, "use-underflow-bin", u"true"); + assertXPath(pXmlDoc, sHistogramProps, "underflow-bin-value", u"11"); + assertXPath(pXmlDoc, sHistogramProps, "use-overflow-bin", u"true"); + assertXPath(pXmlDoc, sHistogramProps, "overflow-bin-value", u"14"); + + xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xCategories + = getDataSequenceFromDocByRole(xChartDoc, u"categories"); + CPPUNIT_ASSERT(xCategories.is()); + + Reference xCategoriesText(xCategories, uno::UNO_QUERY); + CPPUNIT_ASSERT(xCategoriesText.is()); + + const Sequence aBinLabels = xCategoriesText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"<= 11"_ustr, aBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(11-13]"_ustr, aBinLabels[1]); + CPPUNIT_ASSERT_EQUAL(u"(13-14]"_ustr, aBinLabels[2]); + CPPUNIT_ASSERT_EQUAL(u"> 14"_ustr, aBinLabels[3]); + + Reference xReloadedProps(xChartType, uno::UNO_QUERY_THROW); + + bool bUseUnderflowBin = false; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"UseUnderflowBin"_ustr) >>= bUseUnderflowBin); + CPPUNIT_ASSERT(bUseUnderflowBin); + + double fUnderflowBinValue = 0.0; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"UnderflowBinValue"_ustr) + >>= fUnderflowBinValue); + CPPUNIT_ASSERT_EQUAL(11.0, fUnderflowBinValue); + + bool bUseOverflowBin = false; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"UseOverflowBin"_ustr) >>= bUseOverflowBin); + CPPUNIT_ASSERT(bUseOverflowBin); + + double fOverflowBinValue = 0.0; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"OverflowBinValue"_ustr) + >>= fOverflowBinValue); + CPPUNIT_ASSERT_EQUAL(14.0, fOverflowBinValue); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramODFUnderflowOverflowImport) +{ + loadFromFile(u"fods/tdf163727_histogram_underflow_overflow.fods"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xProps(xChartType, uno::UNO_QUERY_THROW); + + sal_Int32 nFrequencyType = -1; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), nFrequencyType); + + double fBinWidth = 0.0; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"BinWidth"_ustr) >>= fBinWidth); + CPPUNIT_ASSERT_EQUAL(2.0, fBinWidth); + + bool bUseUnderflowBin = false; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"UseUnderflowBin"_ustr) >>= bUseUnderflowBin); + CPPUNIT_ASSERT(bUseUnderflowBin); + + double fUnderflowBinValue = 0.0; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"UnderflowBinValue"_ustr) >>= fUnderflowBinValue); + CPPUNIT_ASSERT_EQUAL(11.0, fUnderflowBinValue); + + bool bUseOverflowBin = false; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"UseOverflowBin"_ustr) >>= bUseOverflowBin); + CPPUNIT_ASSERT(bUseOverflowBin); + + double fOverflowBinValue = 0.0; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"OverflowBinValue"_ustr) >>= fOverflowBinValue); + CPPUNIT_ASSERT_EQUAL(14.0, fOverflowBinValue); + + Reference xCategories + = getDataSequenceFromDocByRole(xChartDoc, u"categories"); + CPPUNIT_ASSERT(xCategories.is()); + + Reference xCategoriesText(xCategories, uno::UNO_QUERY); + CPPUNIT_ASSERT(xCategoriesText.is()); + + const Sequence aBinLabels = xCategoriesText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"<= 11"_ustr, aBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(11-13]"_ustr, aBinLabels[1]); + CPPUNIT_ASSERT_EQUAL(u"(13-14]"_ustr, aBinLabels[2]); + CPPUNIT_ASSERT_EQUAL(u"> 14"_ustr, aBinLabels[3]); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramOOXMLUnderflowOverflowRoundtrip) +{ + loadFromFile(u"fods/tdf163727_histogram_roundtrip.fods"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xProps(xChartType, uno::UNO_QUERY_THROW); + xProps->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(1))); + xProps->setPropertyValue(u"BinWidth"_ustr, uno::Any(2.0)); + xProps->setPropertyValue(u"UseUnderflowBin"_ustr, uno::Any(true)); + xProps->setPropertyValue(u"UnderflowBinValue"_ustr, uno::Any(11.0)); + xProps->setPropertyValue(u"UseOverflowBin"_ustr, uno::Any(true)); + xProps->setPropertyValue(u"OverflowBinValue"_ustr, uno::Any(14.0)); + + saveAndReload(TestFilter::XLSX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + static constexpr char sBinSize[] + = "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:layoutPr/" + "cx:binning/cx:binSize"; + + assertXPath(pXmlDoc, sBinSize, "val", u"2"); + + static constexpr char sBinning[] + = "/cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series/cx:layoutPr/" + "cx:binning"; + + assertXPath(pXmlDoc, sBinning, "underflow", u"11"); + assertXPath(pXmlDoc, sBinning, "overflow", u"14"); + + xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xXAxis.is()); + + chart2::ScaleData aScaleData = xXAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + + Reference xAxisCatText(aScaleData.Categories->getValues(), + uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisCatText.is()); + + const Sequence aAxisBinLabels = xAxisCatText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aAxisBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"<= 11"_ustr, aAxisBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(11-13]"_ustr, aAxisBinLabels[1]); + CPPUNIT_ASSERT_EQUAL(u"(13-14]"_ustr, aAxisBinLabels[2]); + CPPUNIT_ASSERT_EQUAL(u"> 14"_ustr, aAxisBinLabels[3]); + + Reference xReloadedProps(xChartType, uno::UNO_QUERY_THROW); + + bool bUseUnderflowBin = false; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"UseUnderflowBin"_ustr) >>= bUseUnderflowBin); + CPPUNIT_ASSERT(bUseUnderflowBin); + + double fUnderflowBinValue = 0.0; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"UnderflowBinValue"_ustr) + >>= fUnderflowBinValue); + CPPUNIT_ASSERT_EQUAL(11.0, fUnderflowBinValue); + + bool bUseOverflowBin = false; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"UseOverflowBin"_ustr) >>= bUseOverflowBin); + CPPUNIT_ASSERT(bUseOverflowBin); + + double fOverflowBinValue = 0.0; + CPPUNIT_ASSERT(xReloadedProps->getPropertyValue(u"OverflowBinValue"_ustr) + >>= fOverflowBinValue); + CPPUNIT_ASSERT_EQUAL(14.0, fOverflowBinValue); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testHistogramOOXMLUnderflowOverflowImport) +{ + loadFromFile(u"xlsx/tdf163727_histogram_underflow_overflow.xlsx"); + + uno::Reference xChartDoc = getChartDocFromSheet(0); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference xChartType = getChartTypeFromDoc(xChartDoc, 0, 0); + CPPUNIT_ASSERT(xChartType.is()); + + Reference xProps(xChartType, uno::UNO_QUERY_THROW); + + bool bUseUnderflowBin = false; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"UseUnderflowBin"_ustr) >>= bUseUnderflowBin); + CPPUNIT_ASSERT(bUseUnderflowBin); + + double fUnderflowBinValue = 0.0; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"UnderflowBinValue"_ustr) >>= fUnderflowBinValue); + CPPUNIT_ASSERT_EQUAL(11.0, fUnderflowBinValue); + + bool bUseOverflowBin = false; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"UseOverflowBin"_ustr) >>= bUseOverflowBin); + CPPUNIT_ASSERT(bUseOverflowBin); + + double fOverflowBinValue = 0.0; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"OverflowBinValue"_ustr) >>= fOverflowBinValue); + CPPUNIT_ASSERT_EQUAL(14.0, fOverflowBinValue); + + sal_Int32 nFrequencyType = -1; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), nFrequencyType); + + double fBinWidth = 0.0; + CPPUNIT_ASSERT(xProps->getPropertyValue(u"BinWidth"_ustr) >>= fBinWidth); + CPPUNIT_ASSERT_EQUAL(2.0, fBinWidth); + + Reference xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0); + CPPUNIT_ASSERT(xXAxis.is()); + + chart2::ScaleData aScaleData = xXAxis->getScaleData(); + CPPUNIT_ASSERT(aScaleData.Categories.is()); + + Reference xAxisCatText(aScaleData.Categories->getValues(), + uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisCatText.is()); + + const Sequence aAxisBinLabels = xAxisCatText->getTextualData(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aAxisBinLabels.getLength()); + CPPUNIT_ASSERT_EQUAL(u"<= 11"_ustr, aAxisBinLabels[0]); + CPPUNIT_ASSERT_EQUAL(u"(11-13]"_ustr, aAxisBinLabels[1]); + CPPUNIT_ASSERT_EQUAL(u"(13-14]"_ustr, aAxisBinLabels[2]); + CPPUNIT_ASSERT_EQUAL(u"> 14"_ustr, aAxisBinLabels[3]); +} + CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf60316) { loadFromFile(u"pptx/tdf60316.pptx"); diff --git a/chart2/qa/extras/data/fods/correlation-circle.fods b/chart2/qa/extras/data/fods/correlation-circle.fods new file mode 100644 index 000000000000..3dea685046f8 --- /dev/null +++ b/chart2/qa/extras/data/fods/correlation-circle.fods @@ -0,0 +1,359 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Column D + + + Column E + + + length + + Sheet1.A1:Sheet1.A1 + + + width + + Sheet1.B1:Sheet1.B1 + + + mass + + Sheet1.C1:Sheet1.C1 + + + + + + + 1 + + + -0.6 + + Sheet1.D2:Sheet1.D6 + + + 0.1 + + Sheet1.E2:Sheet1.E6 + + + 1 + + Sheet1.A2:Sheet1.A6 + + + 5 + + Sheet1.B2:Sheet1.B6 + + + 40 + + Sheet1.C2:Sheet1.C6 + + + + + 2 + + + -0.3 + + + -0.4 + + + 2 + + + 4 + + + 38 + + + + + 3 + + + 0 + + + 0.5 + + + 3 + + + 3.5 + + + 39 + + + + + 4 + + + 0.3 + + + -0.3 + + + 4 + + + 2 + + + 36 + + + + + 5 + + + 0.6 + + + 0.1 + + + 5 + + + 1 + + + 35 + + + + + + + + + + + + + + length + + + width + + + mass + + + dim 1 + + + dim 2 + + + + + 1 + + + 5 + + + 40 + + + -0.6 + + + 0.1 + + + + + 2 + + + 4 + + + 38 + + + -0.3 + + + -0.4 + + + + + 3 + + + 3.5 + + + 39 + + + 0 + + + 0.5 + + + + + 4 + + + 2 + + + 36 + + + 0.3 + + + -0.3 + + + + + 5 + + + 1 + + + 35 + + + 0.6 + + + 0.1 + + + + + + + diff --git a/chart2/qa/extras/data/fods/tdf163727_histogram_COExt.fods b/chart2/qa/extras/data/fods/tdf163727_histogram_COExt.fods new file mode 100644 index 000000000000..00672c4a5f1a --- /dev/null +++ b/chart2/qa/extras/data/fods/tdf163727_histogram_COExt.fods @@ -0,0 +1,754 @@ + + + + 2026-04-18T18:19:48.2943590002026-04-18T18:21:10.321688000PT1M22S1LibreOffice/25.8.6.2$Linux_X86_64 LibreOffice_project/580$Build-2 + + + 0 + 0 + 20320 + 9483 + + + true + true + true + 0 + true + true + false + true + false + 12632256 + true + true + 0 + false + false + true + true + false + 3 + false + Generic Printer + false + uAH+/0dlbmVyaWMgUHJpbnRlcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU0dFTlBSVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAMApAAAAAAA//8IAFZUAAAkbQAASm9iRGF0YSAxCnByaW50ZXI9R2VuZXJpYyBQcmludGVyCm9yaWVudGF0aW9uPVBvcnRyYWl0CmNvcGllcz0xCmNvbGxhdGU9ZmFsc2UKbWFyZ2luYWRqdXN0bWVudD0wLDAsJzAsMApjb2xvcmRlcHRoPTI0CmNvbG9yZGV2aWNlPTAKUFBEQ29udGV4dERhdGEKUGFnZVNpemU6TGV0dGVyAAASAENPTVBBVF9EVVBMRVhfTU9ERQ8ARHVwbGV4TW9kZTo6T2ZmDABQUklOVEVSX05BTUUPAEdlbmVyaWMgUHJpbnRlcgsARFJJVkVSX05BTUUHAFNHRU5QUlQ= + false + 1270 + 1270 + 1 + 1 + true + false + false + true + true + true + true + true + 7 + true + + + Sheet1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + Collabora_Office/26.04.0.1$Linux_X86_64 LibreOffice_project/c18477369a95ac938f42671f850f4a970e17ca7c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Column A + + + + + + + [10-13.94] + + + 12 + + Sheet1.A1:Sheet1.A5 + + + + + (13.94-17.87] + + + 10 + + + + + + 11 + + + + + + 13 + + + + + + 15 + + + + + + + + + + VkNMTVRGAQAxAAAAAAAAAAEAGwAAAAAAAAAAAAAAAACfCng8AMqaO2EAAABkAAAAAIA+AAAo + IwAAHQIAAIsAAQACAAAA//+BAAEAEAAAAAAAAAAAAAAAfz4AACcjAACLAAEAAgAAACAAggAB + ACEAAAACABsAAAACAAIAAAAAAAAAJyMAAAEAAAAAAH8+AAACAACVAAEABAAAAAAAAACWAAEA + AgAAAAkAiwABAAIAAAADAIUAAQAFAAAA////AAGEAAEABQAAAAAAAAAAbwACADYAAAABAAYA + QB8AACgjAAAAAAAAKCMAAAAAAAAAAAAAgD4AAAAAAACAPgAAKCMAAEAfAAAoIwAAAACMAAEA + AAAAAIsAAQACAAAAAwCEAAEABQAAALOzswABAAIBAI4AAAAVAFhQQVRIU1RST0tFX1NFUV9C + RUdJTgAAAABvAAAAAQBpAAAAAQAzAAAABgAyHAAA9x8AACYEAAD3HwAAJgQAAHcBAAA+NAAA + dwEAAD40AAD3HwAAMhwAAPcfAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAAAAAAAAAAAAAAAhAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAcwAAAAYAMhwA + APcfAAAmBAAA9x8AACYEAAB3AQAAPjQAAHcBAAA+NAAA9x8AADIcAAD3HwAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAPjQAAPYfAAAmBAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgA+NAAA9h8AACYEAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAJIc + AAAmBAAAkhwAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAkhwAACYEAACS + HAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAC4ZAAAmBAAALhkAAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAALhkAACYEAAAuGQAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIAPjQAAMsVAAAmBAAAyxUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+ + NAAAyxUAACYEAADLFQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAGcSAAAmBAAAZxIA + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAZxIAACYEAABnEgAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIAPjQAAAQPAAAmBAAABA8AAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgA+NAAABA8AACYEAAAEDwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQA + AKALAAAmBAAAoAsAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAoAsAACYE + AACgCwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAD0IAAAmBAAAPQgAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAPQgAACYEAAA9CAAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIAPjQAANkEAAAmBAAA2QQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgA+NAAA2QQAACYEAADZBAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAHYBAAAmBAAA + dgEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAdgEAACYEAAB2AQAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIAJgQAAIwgAAAmBAAA9h8AAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgAmBAAAjCAAACYEAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + JgQAAIwgAAAmBAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAmBAAAjCAA + ACYEAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAMhwAAIwgAAAyHAAA9h8AAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAyHAAAjCAAADIcAAD2HwAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIAMhwAAIwgAAAyHAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgAyHAAAjCAAADIcAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAIwgAAA+ + NAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAjCAAAD40AAD2HwAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAIwgAAA+NAAA9h8AAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgA+NAAAjCAAAD40AAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIAJgQAAPYfAAA+NAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAmBAAA + 9h8AAD40AAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAPYfAAAmBAAA9h8AAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAA9h8AACYEAAD2HwAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAkAMAAPYfAAAmBAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgCQAwAA9h8AACYEAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAJIc + AAAmBAAAkhwAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAkhwAACYEAACS + HAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAJIcAAAmBAAAkhwAAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAkhwAACYEAACSHAAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIAkAMAAC4ZAAAmBAAALhkAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQ + AwAALhkAACYEAAAuGQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAC4ZAAAmBAAALhkA + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAALhkAACYEAAAuGQAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIAkAMAAMsVAAAmBAAAyxUAAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgCQAwAAyxUAACYEAADLFQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMA + AMsVAAAmBAAAyxUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAyxUAACYE + AADLFQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAGcSAAAmBAAAZxIAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAZxIAACYEAABnEgAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIAkAMAAGcSAAAmBAAAZxIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgCQAwAAZxIAACYEAABnEgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAAQPAAAmBAAA + BA8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAABA8AACYEAAAEDwAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAAQPAAAmBAAABA8AAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgCQAwAABA8AACYEAAAEDwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + kAMAAKALAAAmBAAAoAsAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAoAsA + ACYEAACgCwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAKALAAAmBAAAoAsAAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAoAsAACYEAACgCwAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIAkAMAAD0IAAAmBAAAPQgAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgCQAwAAPQgAACYEAAA9CAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAD0IAAAm + BAAAPQgAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAPQgAACYEAAA9CAAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAANkEAAAmBAAA2QQAAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgCQAwAA2QQAACYEAADZBAAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIAkAMAANkEAAAmBAAA2QQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAA + 2QQAACYEAADZBAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAHYBAAAmBAAAdgEAAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAdgEAACYEAAB2AQAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAkAMAAHYBAAAmBAAAdgEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgCQAwAAdgEAACYEAAB2AQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJgQAAPYf + AAAmBAAAdgEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAmBAAA9h8AACYEAAB2 + AQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhQABAAUAAACGRQAAAYQAAQAFAAAAAAAAAABvAAIALgAAAAEABQAm + BAAA9h8AADIcAAD2HwAAMhwAANkEAAAmBAAA2QQAACYEAAD2HwAAAACMAAEAAAAAAIsAAQAC + AAAAAwCFAAEABQAAAIZFAAABhAABAAUAAAAAAAAAAG8AAgAuAAAAAQAFADIcAAD2HwAAPjQA + APYfAAA+NAAALhkAADIcAAAuGQAAMhwAAPYfAAAAAIwAAQAAAAAAAAIBACAAAAAWAFhURVhU + X1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBM + aWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAA + AAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEABABrAAAAEQ0A + ADAiAAAKAAAAWwAxADAALQAxADMALgA5ADQAXQAAAAoACgAAAGIAAAAmAQAA6wEAAGACAAAl + AwAA6QMAAEsEAAAQBQAA1AUAADYGAAAKAFsAMQAwAC0AMQAzAC4AOQA0AF0AAAAAAACVAAEA + BAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + AQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9XAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + AgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9X + AwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DBAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + BQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DBgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + BwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DCAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + CQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9XCQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9M + AAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJ + TlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAA + AAAAAACVAAEABAAAAAAAAACKAAEARwAAAAUAQQAAAA8ATGliZXJhdGlvbiBTYW5zAAAAAAAA + YQEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAAAAAAAAAAAAAAiAABAAIAAAABAIcA + AQAFAAAA/////wCGAAEABAAAAAAAAABxAAQAgwAAAB4kAAAwIgAADQAAACgAMQAzAC4AOQA0 + AC0AMQA3AC4AOAA4AF0AAAANAA0AAAB1AAAAOgEAAP4BAABgAgAAJQMAAOkDAABfBAAAIwUA + AOgFAABKBgAADgcAANMHAAA1CAAADQAoADEAMwAuADkANAAtADEANwAuADgAOABdAAAAAAAA + lQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwEAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwMAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwUAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwYAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwYAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwcAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwgAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwkAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwoAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwsAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwwAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPVwwAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEA + IAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcA + AAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAA + AAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAA + cQAEACMAAABoAgAAdiAAAAEAAAAwAAAAAQABAAAAxAAAAAEAMAAAAAAAAJUAAQAEAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBF + X0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUA + AQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8A + AAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/ + ////AIYAAQAEAAAAAAAAAHEABAAzAAAAQQEAABIdAAADAAAAMAAuADUAAAADAAMAAADEAAAA + JgEAAOsBAAADADAALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAA + AAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYA + WFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEA + AAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA + /wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAAcQAEACMA + AABoAgAArhkAAAEAAAAxAAAAAQABAAAAxAAAAAEAMQAAAAAAAJUAAQAEAAAAAAAAAAACAQAT + AAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQAT + AAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAA + AAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAA + AAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAA + AAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYA + AQAEAAAAAAAAAHEABAAzAAAAQQEAAEsWAAADAAAAMQAuADUAAAADAAMAAADEAAAAJgEAAOsB + AAADADEALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAA + AAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAA + AAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAA + AAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRf + UEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExp + YmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAA + AAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAAcQAEACMAAABoAgAA + 5xIAAAEAAAAyAAAAAQABAAAAxAAAAAEAMgAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBY + VEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBY + VEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAA + AAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoA + AQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJ + BAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAA + AAAAAHEABAAzAAAAQQEAAIQPAAADAAAAMgAuADUAAAADAAMAAADEAAAAJgEAAOsBAAADADIA + LgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4A + AAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRT + SEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExpYmVyYXRp + b24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAA + AIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAAcQAEACMAAABoAgAAIAwAAAEA + AAAzAAAAAQABAAAAxAAAAAEAMwAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9F + T0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9F + T1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAA + AAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAA + BQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAA + AAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEA + BAAzAAAAQQEAAL0IAAADAAAAMwAuADUAAAADAAMAAADEAAAAJgEAAOsBAAADADMALgA1AAAA + AAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhU + RVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhU + RVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhU + RVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9C + RUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExpYmVyYXRpb24gU2Fu + cwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQAC + AAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAAcQAEACMAAABoAgAAWQUAAAEAAAA0AAAA + AQABAAAAxAAAAAEANAAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MAAAAA + AAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAA + AAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhU + RVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAA + DwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8D + AAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEABAAzAAAA + QQEAAPYBAAADAAAANAAuADUAAAADAAMAAADEAAAAJgEAAOsBAAADADQALgA1AAAAAAAAlQAB + AAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + QwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + TAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BB + SU5UU0hBUEVfRU5EAAAAAAAAAACLAAEAAgAAAAMAhQABAAUAAACGRQAAAYQAAQAFAAAAAAAA + AABvAAIANgAAAAEABgBcNgAA/REAAPI1AAD9EQAA8jUAACoRAADFNgAAKhEAAMU2AAD9EQAA + XDYAAP0RAAAAAIwAAQAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAA + AAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABh + AQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwAB + AAUAAAD/////AIYAAQAEAAAAAAAAAHEABABbAAAAKTcAABISAAAIAAAAQwBvAGwAdQBtAG4A + IABBAAAACAAIAAAA/wAAAMMBAAASAgAA1gIAAPwDAADBBAAAIwUAAA4GAAAIAEMAbwBsAHUA + bQBuACAAQQAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MEAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT0MFAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MGAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT1cGAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MHAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAAC + AQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAjAABAAAAAACMAAEAAAAAAA== + + + + + + + 12 + + + + + 10 + + + + + 11 + + + + + 13 + + + + + 15 + + + + + + + diff --git a/chart2/qa/extras/data/fods/tdf163727_histogram_roundtrip.fods b/chart2/qa/extras/data/fods/tdf163727_histogram_roundtrip.fods new file mode 100644 index 000000000000..7a8d24b8b6bd --- /dev/null +++ b/chart2/qa/extras/data/fods/tdf163727_histogram_roundtrip.fods @@ -0,0 +1,754 @@ + + + + 2026-04-18T18:19:48.2943590002026-04-18T18:21:10.321688000PT1M22S1LibreOffice/25.8.6.2$Linux_X86_64 LibreOffice_project/580$Build-2 + + + 0 + 0 + 20320 + 9483 + + + true + true + true + 0 + true + true + false + true + false + 12632256 + true + true + 0 + false + false + true + true + false + 3 + false + Generic Printer + false + uAH+/0dlbmVyaWMgUHJpbnRlcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU0dFTlBSVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAMApAAAAAAA//8IAFZUAAAkbQAASm9iRGF0YSAxCnByaW50ZXI9R2VuZXJpYyBQcmludGVyCm9yaWVudGF0aW9uPVBvcnRyYWl0CmNvcGllcz0xCmNvbGxhdGU9ZmFsc2UKbWFyZ2luYWRqdXN0bWVudD0wLDAsJzAsMApjb2xvcmRlcHRoPTI0CmNvbG9yZGV2aWNlPTAKUFBEQ29udGV4dERhdGEKUGFnZVNpemU6TGV0dGVyAAASAENPTVBBVF9EVVBMRVhfTU9ERQ8ARHVwbGV4TW9kZTo6T2ZmDABQUklOVEVSX05BTUUPAEdlbmVyaWMgUHJpbnRlcgsARFJJVkVSX05BTUUHAFNHRU5QUlQ= + false + 1270 + 1270 + 1 + 1 + true + false + false + true + true + true + true + true + 7 + true + + + Sheet1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + Collabora_Office/26.04.0.1$Linux_X86_64 LibreOffice_project/c18477369a95ac938f42671f850f4a970e17ca7c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Column A + + + + + + + [10-13.94] + + + 12 + + Sheet1.A1:Sheet1.A5 + + + + + (13.94-17.87] + + + 10 + + + + + + 11 + + + + + + 13 + + + + + + 15 + + + + + + + + + + VkNMTVRGAQAxAAAAAAAAAAEAGwAAAAAAAAAAAAAAAACfCng8AMqaO2EAAABkAAAAAIA+AAAo + IwAAHQIAAIsAAQACAAAA//+BAAEAEAAAAAAAAAAAAAAAfz4AACcjAACLAAEAAgAAACAAggAB + ACEAAAACABsAAAACAAIAAAAAAAAAJyMAAAEAAAAAAH8+AAACAACVAAEABAAAAAAAAACWAAEA + AgAAAAkAiwABAAIAAAADAIUAAQAFAAAA////AAGEAAEABQAAAAAAAAAAbwACADYAAAABAAYA + QB8AACgjAAAAAAAAKCMAAAAAAAAAAAAAgD4AAAAAAACAPgAAKCMAAEAfAAAoIwAAAACMAAEA + AAAAAIsAAQACAAAAAwCEAAEABQAAALOzswABAAIBAI4AAAAVAFhQQVRIU1RST0tFX1NFUV9C + RUdJTgAAAABvAAAAAQBpAAAAAQAzAAAABgAyHAAA9x8AACYEAAD3HwAAJgQAAHcBAAA+NAAA + dwEAAD40AAD3HwAAMhwAAPcfAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAAAAAAAAAAAAAAAhAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAcwAAAAYAMhwA + APcfAAAmBAAA9x8AACYEAAB3AQAAPjQAAHcBAAA+NAAA9x8AADIcAAD3HwAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAPjQAAPYfAAAmBAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgA+NAAA9h8AACYEAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAJIc + AAAmBAAAkhwAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAkhwAACYEAACS + HAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAC4ZAAAmBAAALhkAAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAALhkAACYEAAAuGQAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIAPjQAAMsVAAAmBAAAyxUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+ + NAAAyxUAACYEAADLFQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAGcSAAAmBAAAZxIA + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAZxIAACYEAABnEgAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIAPjQAAAQPAAAmBAAABA8AAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgA+NAAABA8AACYEAAAEDwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQA + AKALAAAmBAAAoAsAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAoAsAACYE + AACgCwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAD0IAAAmBAAAPQgAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAPQgAACYEAAA9CAAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIAPjQAANkEAAAmBAAA2QQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgA+NAAA2QQAACYEAADZBAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAHYBAAAmBAAA + dgEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAdgEAACYEAAB2AQAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIAJgQAAIwgAAAmBAAA9h8AAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgAmBAAAjCAAACYEAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + JgQAAIwgAAAmBAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAmBAAAjCAA + ACYEAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAMhwAAIwgAAAyHAAA9h8AAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAyHAAAjCAAADIcAAD2HwAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIAMhwAAIwgAAAyHAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgAyHAAAjCAAADIcAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAIwgAAA+ + NAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA+NAAAjCAAAD40AAD2HwAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIAPjQAAIwgAAA+NAAA9h8AAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgA+NAAAjCAAAD40AAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIAJgQAAPYfAAA+NAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAmBAAA + 9h8AAD40AAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAPYfAAAmBAAA9h8AAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAA9h8AACYEAAD2HwAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAkAMAAPYfAAAmBAAA9h8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgCQAwAA9h8AACYEAAD2HwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAJIc + AAAmBAAAkhwAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAkhwAACYEAACS + HAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAJIcAAAmBAAAkhwAAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAkhwAACYEAACSHAAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIAkAMAAC4ZAAAmBAAALhkAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQ + AwAALhkAACYEAAAuGQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAC4ZAAAmBAAALhkA + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAALhkAACYEAAAuGQAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIAkAMAAMsVAAAmBAAAyxUAAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgCQAwAAyxUAACYEAADLFQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMA + AMsVAAAmBAAAyxUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAyxUAACYE + AADLFQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAGcSAAAmBAAAZxIAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAZxIAACYEAABnEgAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIAkAMAAGcSAAAmBAAAZxIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgCQAwAAZxIAACYEAABnEgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAAQPAAAmBAAA + BA8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAABA8AACYEAAAEDwAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAAQPAAAmBAAABA8AAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgCQAwAABA8AACYEAAAEDwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + kAMAAKALAAAmBAAAoAsAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAoAsA + ACYEAACgCwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAKALAAAmBAAAoAsAAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAoAsAACYEAACgCwAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIAkAMAAD0IAAAmBAAAPQgAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgCQAwAAPQgAACYEAAA9CAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAD0IAAAm + BAAAPQgAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAPQgAACYEAAA9CAAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAANkEAAAmBAAA2QQAAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgCQAwAA2QQAACYEAADZBAAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIAkAMAANkEAAAmBAAA2QQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAA + 2QQAACYEAADZBAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAkAMAAHYBAAAmBAAAdgEAAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCQAwAAdgEAACYEAAB2AQAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAkAMAAHYBAAAmBAAAdgEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgCQAwAAdgEAACYEAAB2AQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJgQAAPYf + AAAmBAAAdgEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAmBAAA9h8AACYEAAB2 + AQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhQABAAUAAACGRQAAAYQAAQAFAAAAAAAAAABvAAIALgAAAAEABQAm + BAAA9h8AADIcAAD2HwAAMhwAANkEAAAmBAAA2QQAACYEAAD2HwAAAACMAAEAAAAAAIsAAQAC + AAAAAwCFAAEABQAAAIZFAAABhAABAAUAAAAAAAAAAG8AAgAuAAAAAQAFADIcAAD2HwAAPjQA + APYfAAA+NAAALhkAADIcAAAuGQAAMhwAAPYfAAAAAIwAAQAAAAAAAAIBACAAAAAWAFhURVhU + X1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBM + aWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAA + AAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEABABrAAAAEQ0A + ADAiAAAKAAAAWwAxADAALQAxADMALgA5ADQAXQAAAAoACgAAAGIAAAAmAQAA6wEAAGACAAAl + AwAA6QMAAEsEAAAQBQAA1AUAADYGAAAKAFsAMQAwAC0AMQAzAC4AOQA0AF0AAAAAAACVAAEA + BAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + AQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9XAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + AgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9X + AwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DBAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + BQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DBgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + BwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DCAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + CQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9XCQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9M + AAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJ + TlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAA + AAAAAACVAAEABAAAAAAAAACKAAEARwAAAAUAQQAAAA8ATGliZXJhdGlvbiBTYW5zAAAAAAAA + YQEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAAAAAAAAAAAAAAiAABAAIAAAABAIcA + AQAFAAAA/////wCGAAEABAAAAAAAAABxAAQAgwAAAB4kAAAwIgAADQAAACgAMQAzAC4AOQA0 + AC0AMQA3AC4AOAA4AF0AAAANAA0AAAB1AAAAOgEAAP4BAABgAgAAJQMAAOkDAABfBAAAIwUA + AOgFAABKBgAADgcAANMHAAA1CAAADQAoADEAMwAuADkANAAtADEANwAuADgAOABdAAAAAAAA + lQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwEAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwMAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwUAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwYAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwYAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwcAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwgAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwkAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwoAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwsAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwwAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPVwwAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEA + IAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcA + AAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAA + AAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAA + cQAEACMAAABoAgAAdiAAAAEAAAAwAAAAAQABAAAAxAAAAAEAMAAAAAAAAJUAAQAEAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBF + X0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUA + AQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8A + AAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/ + ////AIYAAQAEAAAAAAAAAHEABAAzAAAAQQEAABIdAAADAAAAMAAuADUAAAADAAMAAADEAAAA + JgEAAOsBAAADADAALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAA + AAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYA + WFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEA + AAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA + /wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAAcQAEACMA + AABoAgAArhkAAAEAAAAxAAAAAQABAAAAxAAAAAEAMQAAAAAAAJUAAQAEAAAAAAAAAAACAQAT + AAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQAT + AAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAA + AAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAA + AAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAA + AAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYA + AQAEAAAAAAAAAHEABAAzAAAAQQEAAEsWAAADAAAAMQAuADUAAAADAAMAAADEAAAAJgEAAOsB + AAADADEALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAA + AAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAA + AAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAA + AAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRf + UEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExp + YmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAA + AAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAAcQAEACMAAABoAgAA + 5xIAAAEAAAAyAAAAAQABAAAAxAAAAAEAMgAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBY + VEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBY + VEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAA + AAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoA + AQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJ + BAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAA + AAAAAHEABAAzAAAAQQEAAIQPAAADAAAAMgAuADUAAAADAAMAAADEAAAAJgEAAOsBAAADADIA + LgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4A + AAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRT + SEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExpYmVyYXRp + b24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAA + AIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAAcQAEACMAAABoAgAAIAwAAAEA + AAAzAAAAAQABAAAAxAAAAAEAMwAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9F + T0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9F + T1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAA + AAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAA + BQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAA + AAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEA + BAAzAAAAQQEAAL0IAAADAAAAMwAuADUAAAADAAMAAADEAAAAJgEAAOsBAAADADMALgA1AAAA + AAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhU + RVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhU + RVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhU + RVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9C + RUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExpYmVyYXRpb24gU2Fu + cwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQAC + AAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAAcQAEACMAAABoAgAAWQUAAAEAAAA0AAAA + AQABAAAAxAAAAAEANAAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MAAAAA + AAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAA + AAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhU + RVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAA + DwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8D + AAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEABAAzAAAA + QQEAAPYBAAADAAAANAAuADUAAAADAAMAAADEAAAAJgEAAOsBAAADADQALgA1AAAAAAAAlQAB + AAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + QwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + TAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BB + SU5UU0hBUEVfRU5EAAAAAAAAAACLAAEAAgAAAAMAhQABAAUAAACGRQAAAYQAAQAFAAAAAAAA + AABvAAIANgAAAAEABgBcNgAA/REAAPI1AAD9EQAA8jUAACoRAADFNgAAKhEAAMU2AAD9EQAA + XDYAAP0RAAAAAIwAAQAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAA + AAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABh + AQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwAB + AAUAAAD/////AIYAAQAEAAAAAAAAAHEABABbAAAAKTcAABISAAAIAAAAQwBvAGwAdQBtAG4A + IABBAAAACAAIAAAA/wAAAMMBAAASAgAA1gIAAPwDAADBBAAAIwUAAA4GAAAIAEMAbwBsAHUA + bQBuACAAQQAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MEAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT0MFAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MGAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT1cGAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MHAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAAC + AQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAjAABAAAAAACMAAEAAAAAAA== + + + + + + + 12 + + + + + 10 + + + + + 11 + + + + + 13 + + + + + 15 + + + + + + + diff --git a/chart2/qa/extras/data/fods/tdf163727_histogram_roundtrip_multi_chart.fods b/chart2/qa/extras/data/fods/tdf163727_histogram_roundtrip_multi_chart.fods new file mode 100644 index 000000000000..1cf20561bed8 --- /dev/null +++ b/chart2/qa/extras/data/fods/tdf163727_histogram_roundtrip_multi_chart.fods @@ -0,0 +1,1950 @@ + + + + 2026-03-31T14:46:03en-US2026-05-25T16:01:37.09744471546PT40M11SCollabora_Office/26.04.2.0$MacOSX_AARCH64 LibreOffice_project/d7639ee07afbba07078670b0062f4a94edf3617915.0000 + + + 0 + 0 + 22578 + 12644 + + + view1 + + + 8 + 3 + 2 + 0 + 0 + 0 + 0 + 0 + 100 + 60 + true + false + false + false + false + false + + + Sheet1 + 1377 + 0 + 100 + 60 + false + true + true + true + false + true + -1 + true + true + true + true + false + false + false + 1270 + 1270 + 1 + 1 + true + 1 + 180,71,1440,904;1;,,,; + false + false + false + false + false + + + + + true + true + true + 0 + true + true + false + true + false + -1 + true + true + 0 + false + false + true + true + false + 3 + false + Default printer + false + FQH+/0RlZmF1bHQgcHJpbnRlcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAQABAAAAAAAAAAEAAhSAAAEdAAAAAAAABIAQ09NUEFUX0RVUExFWF9NT0RFEwBEdXBsZXhNb2RlOjpVbmtub3duDABQUklOVEVSX05BTUUPAERlZmF1bHQgcHJpbnRlcgsARFJJVkVSX05BTUUAAA== + false + 1270 + 1270 + 1 + 1 + true + false + false + true + true + true + true + true + 7 + true + + + Sheet1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + : + + + + + : + + : + + + + + : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + ??? + + + + + Page 1 + + + + + + + + + + + + + + + + Collabora_Office/26.04.2.0$MacOSX_AARCH64 LibreOffice_project/d7639ee07afbba07078670b0062f4a94edf36179 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Column A + + + + + + + [10-13.94] + + + 12 + + Sheet1.A1:Sheet1.A6 + + + + + (13.94-17.87] + + + 10 + + + + + + 11 + + + + + + 13 + + + + + + 15 + + + + + + NaN + + + + + + + + + + VkNMTVRGAQAxAAAAAAAAAAEAGwAAAAAAAAAAAAAAAABNj4A8AMqaO72C9RwAZc0dANEmAAC2 + FQAAIwIAAIsAAQACAAAA//+BAAEAEAAAAAAAAAAAAAAA0CYAALUVAACLAAEAAgAAACAAggAB + ACEAAAACABsAAAACAAIAAAAAAAAAtRUAAAEAAAAAANAmAAACAACVAAEABAAAAAAAAACWAAEA + AgAAAAkAiwABAAIAAAADAIUAAQAFAAAAHBwcAAGEAAEABQAAAAAAAAAAbwACADYAAAABAAYA + aRMAALYVAAAAAAAAthUAAAAAAAAAAAAA0SYAAAAAAADRJgAAthUAAGkTAAC2FQAAAACMAAEA + AAAAAIsAAQACAAAAAwCEAAEABQAAALOzswABAAIBAI4AAAAVAFhQQVRIU1RST0tFX1NFUV9C + RUdJTgAAAABvAAAAAQBpAAAAAQAzAAAABgBbEAAAyhIAAKwDAADKEgAArAMAADEBAAAJHQAA + MQEAAAkdAADKEgAAWxAAAMoSAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAAAAAAAAAAAAAAAhAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAcwAAAAYAWxAA + AMoSAACsAwAAyhIAAKwDAAAxAQAACR0AADEBAAAJHQAAyhIAAFsQAADKEgAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIACR0AAMkSAACsAwAAyRIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgAJHQAAyRIAAKwDAADJEgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIACR0AANQQ + AACsAwAA1BAAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAJHQAA1BAAAKwDAADU + EAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIACR0AAN8OAACsAwAA3w4AAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgAJHQAA3w4AAKwDAADfDgAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIACR0AAOsMAACsAwAA6wwAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAJ + HQAA6wwAAKwDAADrDAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIACR0AAPYKAACsAwAA9goA + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAJHQAA9goAAKwDAAD2CgAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIACR0AAAIJAACsAwAAAgkAAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgAJHQAAAgkAAKwDAAACCQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIACR0A + AA0HAACsAwAADQcAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAJHQAADQcAAKwD + AAANBwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIACR0AABkFAACsAwAAGQUAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgAJHQAAGQUAAKwDAAAZBQAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIACR0AACQDAACsAwAAJAMAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgAJHQAAJAMAAKwDAAAkAwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIACR0AADABAACsAwAA + MAEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAJHQAAMAEAAKwDAAAwAQAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIArAMAAF8TAACsAwAAyRIAAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgCsAwAAXxMAAKwDAADJEgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + rAMAAF8TAACsAwAAyRIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCsAwAAXxMA + AKwDAADJEgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAWhAAAF8TAABaEAAAyRIAAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgBaEAAAXxMAAFoQAADJEgAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIAWhAAAF8TAABaEAAAyRIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgBaEAAAXxMAAFoQAADJEgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIACR0AAF8TAAAJ + HQAAyRIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAJHQAAXxMAAAkdAADJEgAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIACR0AAF8TAAAJHQAAyRIAAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgAJHQAAXxMAAAkdAADJEgAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIArAMAAMkSAAAJHQAAyRIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCsAwAA + yRIAAAkdAADJEgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAAMkSAACsAwAAyRIAAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAAyRIAAKwDAADJEgAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAFgMAAMkSAACsAwAAyRIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgAWAwAAyRIAAKwDAADJEgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAANQQ + AACsAwAA1BAAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAA1BAAAKwDAADU + EAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAANQQAACsAwAA1BAAAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAA1BAAAKwDAADUEAAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIAFgMAAN8OAACsAwAA3w4AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAW + AwAA3w4AAKwDAADfDgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAAN8OAACsAwAA3w4A + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAA3w4AAKwDAADfDgAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIAFgMAAOsMAACsAwAA6wwAAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgAWAwAA6wwAAKwDAADrDAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMA + AOsMAACsAwAA6wwAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAA6wwAAKwD + AADrDAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAAPYKAACsAwAA9goAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAA9goAAKwDAAD2CgAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIAFgMAAPYKAACsAwAA9goAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgAWAwAA9goAAKwDAAD2CgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAAAIJAACsAwAA + AgkAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAAAgkAAKwDAAACCQAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIAFgMAAAIJAACsAwAAAgkAAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgAWAwAAAgkAAKwDAAACCQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + FgMAAA0HAACsAwAADQcAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAADQcA + AKwDAAANBwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAAA0HAACsAwAADQcAAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAADQcAAKwDAAANBwAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIAFgMAABkFAACsAwAAGQUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgAWAwAAGQUAAKwDAAAZBQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAABkFAACs + AwAAGQUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAAGQUAAKwDAAAZBQAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAACQDAACsAwAAJAMAAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgAWAwAAJAMAAKwDAAAkAwAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIAFgMAACQDAACsAwAAJAMAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAA + JAMAAKwDAAAkAwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAFgMAADABAACsAwAAMAEAAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAWAwAAMAEAAKwDAAAwAQAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAFgMAADABAACsAwAAMAEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgAWAwAAMAEAAKwDAAAwAQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIArAMAAMkS + AACsAwAAMAEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCsAwAAyRIAAKwDAAAw + AQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAACAAgAABADoAAAACADMAAAACAAMAAgABAQAFAAkdAADJEgAACR0AADAB + AACsAwAAMAEAAKwDAADJEgAACR0AAMkSAAABiwABAAIAAAADAIUAAQAFAAAAhkUAAAGEAAEA + BQAAAAAAAAAAbwACAC4AAAABAAUArAMAAMkSAABaEAAAyRIAAFoQAAAkAwAArAMAACQDAACs + AwAAyRIAAAAAjAABAAAAAACMAAEAAAAAAIsAAQACAAAAIACAAAEAOgAAAAIAMwAAAAIAAwAC + AAEBAAUACR0AAMkSAAAJHQAAMAEAAKwDAAAwAQAArAMAAMkSAAAJHQAAyRIAAAGLAAEAAgAA + AAMAhQABAAUAAACGRQAAAYQAAQAFAAAAAAAAAABvAAIALgAAAAEABQBaEAAAyRIAAAkdAADJ + EgAACR0AAN8OAABaEAAA3w4AAFoQAADJEgAAAACMAAEAAAAAAIwAAQAAAAAAAAIBACAAAAAW + AFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBB + AAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAAB + AP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAA////AHEABABr + AAAA6AYAAAMVAAAKAAAAWwAxADAALQAxADMALgA5ADQAXQAAAAoACgAAAGIAAAAmAQAA6wEA + AGACAAAlAwAA6QMAAEsEAAAQBQAA1AUAADYGAAAKAFsAMQAwAC0AMQAzAC4AOQA0AF0AAAAA + AACVAAEABAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRF + WFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9XAQAAAAAAAAAAAgEAEwAAAAkAWFRF + WFRfRU9DAgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAwAAAAAAAAAAAgEAEwAAAAkAWFRF + WFRfRU9XAwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DBAAAAAAAAAAAAgEAEwAAAAkAWFRF + WFRfRU9DBQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DBgAAAAAAAAAAAgEAEwAAAAkAWFRF + WFRfRU9DBwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DCAAAAAAAAAAAAgEAEwAAAAkAWFRF + WFRfRU9DCQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9XCQAAAAAAAAAAAgEAEwAAAAkAWFRF + WFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRF + WFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JF + R0lOAAAAAAAAAACVAAEABAAAAAAAAACKAAEARwAAAAUAQQAAAA8ATGliZXJhdGlvbiBTYW5z + AAAAAAAAYQEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAAAAAAAAAAAAAAiAABAAIA + AAABAIcAAQAFAAAA/////wCGAAEABAAAAP///wBxAAQAgwAAAJcSAAADFQAADQAAACgAMQAz + AC4AOQA0AC0AMQA3AC4AOAA3AF0AAAANAA0AAAB1AAAAOgEAAP4BAABgAgAAJQMAAOkDAABf + BAAAIwUAAOgFAABKBgAADgcAANMHAAA1CAAADQAoADEAMwAuADkANAAtADEANwAuADgANwBd + AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwEAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwMAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwUAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwYAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwYAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwcAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwgAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwkAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwoAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwsAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwwAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPVwwAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAA + AAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAA + igABAEcAAAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAA + AAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQA + AAD///8AcQAEACMAAADuAQAASRMAAAEAAAAwAAAAAQABAAAAxAAAAAEAMAAAAAAAAJUAAQAE + AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wA + AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlO + VFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAA + AAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABh + AQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwAB + AAUAAAD/////AIYAAQAEAAAA////AHEABAAzAAAAxwAAAFQRAAADAAAAMAAuADUAAAADAAMA + AADEAAAAJgEAAOsBAAADADAALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEA + IAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcA + AAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAA + AAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8A + cQAEACMAAADuAQAAXw8AAAEAAAAxAAAAAQABAAAAxAAAAAEAMQAAAAAAAJUAAQAEAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBF + X0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUA + AQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8A + AAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/ + ////AIYAAQAEAAAA////AHEABAAzAAAAxwAAAGsNAAADAAAAMQAuADUAAAADAAMAAADEAAAA + JgEAAOsBAAADADEALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAA + AAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYA + WFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEA + AAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA + /wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAEACMA + AADuAQAAdgsAAAEAAAAyAAAAAQABAAAAxAAAAAEAMgAAAAAAAJUAAQAEAAAAAAAAAAACAQAT + AAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQAT + AAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAA + AAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAA + AAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAA + AAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYA + AQAEAAAA////AHEABAAzAAAAxwAAAIIJAAADAAAAMgAuADUAAAADAAMAAADEAAAAJgEAAOsB + AAADADIALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAA + AAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAA + AAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAA + AAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRf + UEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExp + YmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAA + AAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAEACMAAADuAQAA + jQcAAAEAAAAzAAAAAQABAAAAxAAAAAEAMwAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBY + VEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBY + VEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAA + AAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoA + AQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJ + BAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAA + ////AHEABAAzAAAAxwAAAJkFAAADAAAAMwAuADUAAAADAAMAAADEAAAAJgEAAOsBAAADADMA + LgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4A + AAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRT + SEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExpYmVyYXRp + b24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAA + AIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAEACMAAADuAQAApAMAAAEA + AAA0AAAAAQABAAAAxAAAAAEANAAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9F + T0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9F + T1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAA + AAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAA + BQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAA + AAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAA////AHEA + BAAzAAAAxwAAALABAAADAAAANAAuADUAAAADAAMAAADEAAAAJgEAAOsBAAADADQALgA1AAAA + AAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhU + RVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhU + RVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhU + RVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAACLAAEAAgAAAAMAhQABAAUAAACGRQAAAYQAAQAF + AAAAAAAAAABvAAIANgAAAAEABgCtHgAARAsAAEMeAABECwAAQx4AAHEKAAAWHwAAcQoAABYf + AABECwAArR4AAEQLAAAAAIwAAQAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVH + SU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMA + AAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAA + AAEAhwABAAUAAAD/////AIYAAQAEAAAA////AHEABABbAAAAeh8AAFkLAAAIAAAAQwBvAGwA + dQBtAG4AIABBAAAACAAIAAAA/wAAAMMBAAASAgAA1gIAAPwDAADBBAAAIwUAAA4GAAAIAEMA + bwBsAHUAbQBuACAAQQAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MAAAAA + AAAAAAACAQATAAAACQBYVEVYVF9FT0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAA + AAAAAAACAQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MEAAAA + AAAAAAACAQATAAAACQBYVEVYVF9FT0MFAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MGAAAA + AAAAAAACAQATAAAACQBYVEVYVF9FT1cGAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MHAAAA + AAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAA + AAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAjAABAAAAAACMAAEA + AAAAAA== + + + + + + + + Collabora_Office/26.04.2.0$MacOSX_AARCH64 LibreOffice_project/d7639ee07afbba07078670b0062f4a94edf36179 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Column B + + + + + + + [9-37] + + + 45 + + Sheet1.B1:Sheet1.B5 + + + + + (37-65.1] + + + 32 + + + + + + 18 + + + + + + 9 + + + + + + 25 + + + + + + + + + + VkNMTVRGAQAxAAAAAAAAAAEAGwAAAAAAAAAAAAAAAAA7Rnw8AMqaOw+UeA6AsuYOAMQpAABp + FwAAGwIAAIsAAQACAAAA//+BAAEAEAAAAAAAAAAAAAAAwykAAGgXAACLAAEAAgAAACAAggAB + ACEAAAACABsAAAACAAIAAAAAAAAAaBcAAAEAAAAAAMMpAAACAACVAAEABAAAAAAAAACWAAEA + AgAAAAkAiwABAAIAAAADAIUAAQAFAAAAHBwcAAGEAAEABQAAAAAAAAAAbwACADYAAAABAAYA + 4hQAAGkXAAAAAAAAaRcAAAAAAAAAAAAAxCkAAAAAAADEKQAAaRcAAOIUAABpFwAAAACMAAEA + AAAAAIsAAQACAAAAAwCEAAEABQAAALOzswABAAIBAI4AAAAVAFhQQVRIU1RST0tFX1NFUV9C + RUdJTgAAAABvAAAAAQBpAAAAAQAzAAAABgDUEQAAdRQAALsDAAB1FAAAuwMAADkBAADtHwAA + OQEAAO0fAAB1FAAA1BEAAHUUAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAAAAAAAAAAAAAAAhAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAcwAAAAYA1BEA + AHUUAAC7AwAAdRQAALsDAAA5AQAA7R8AADkBAADtHwAAdRQAANQRAAB1FAAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIA7R8AAHQUAAC7AwAAdBQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgDtHwAAdBQAALsDAAB0FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA7R8AAFAS + AAC7AwAAUBIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDtHwAAUBIAALsDAABQ + EgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA7R8AAC0QAAC7AwAALRAAAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgDtHwAALRAAALsDAAAtEAAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIA7R8AAAoOAAC7AwAACg4AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDt + HwAACg4AALsDAAAKDgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA7R8AAOcLAAC7AwAA5wsA + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDtHwAA5wsAALsDAADnCwAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIA7R8AAMQJAAC7AwAAxAkAAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgDtHwAAxAkAALsDAADECQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA7R8A + AKEHAAC7AwAAoQcAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDtHwAAoQcAALsD + AAChBwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA7R8AAH4FAAC7AwAAfgUAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgDtHwAAfgUAALsDAAB+BQAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIA7R8AAFsDAAC7AwAAWwMAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgDtHwAAWwMAALsDAABbAwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA7R8AADgBAAC7AwAA + OAEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDtHwAAOAEAALsDAAA4AQAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIAuwMAAAoVAAC7AwAAdBQAAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgC7AwAAChUAALsDAAB0FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + uwMAAAoVAAC7AwAAdBQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgC7AwAAChUA + ALsDAAB0FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA1BEAAAoVAADUEQAAdBQAAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDUEQAAChUAANQRAAB0FAAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIA1BEAAAoVAADUEQAAdBQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgDUEQAAChUAANQRAAB0FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA7R8AAAoVAADt + HwAAdBQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDtHwAAChUAAO0fAAB0FAAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIA7R8AAAoVAADtHwAAdBQAAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgDtHwAAChUAAO0fAAB0FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIAuwMAAHQUAADtHwAAdBQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgC7AwAA + dBQAAO0fAAB0FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAHQUAAC7AwAAdBQAAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAAdBQAALsDAAB0FAAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAJQMAAHQUAAC7AwAAdBQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgAlAwAAdBQAALsDAAB0FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAFAS + AAC7AwAAUBIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAAUBIAALsDAABQ + EgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAFASAAC7AwAAUBIAAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAAUBIAALsDAABQEgAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIAJQMAAC0QAAC7AwAALRAAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAl + AwAALRAAALsDAAAtEAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAC0QAAC7AwAALRAA + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAALRAAALsDAAAtEAAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIAJQMAAAoOAAC7AwAACg4AAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgAlAwAACg4AALsDAAAKDgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMA + AAoOAAC7AwAACg4AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAACg4AALsD + AAAKDgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAOcLAAC7AwAA5wsAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAA5wsAALsDAADnCwAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIAJQMAAOcLAAC7AwAA5wsAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgAlAwAA5wsAALsDAADnCwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAMQJAAC7AwAA + xAkAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAAxAkAALsDAADECQAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAMQJAAC7AwAAxAkAAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgAlAwAAxAkAALsDAADECQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + JQMAAKEHAAC7AwAAoQcAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAAoQcA + ALsDAAChBwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAKEHAAC7AwAAoQcAAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAAoQcAALsDAAChBwAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIAJQMAAH4FAAC7AwAAfgUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgAlAwAAfgUAALsDAAB+BQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAH4FAAC7 + AwAAfgUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAAfgUAALsDAAB+BQAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAAFsDAAC7AwAAWwMAAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgAlAwAAWwMAALsDAABbAwAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIAJQMAAFsDAAC7AwAAWwMAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAA + WwMAALsDAABbAwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAJQMAADgBAAC7AwAAOAEAAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAlAwAAOAEAALsDAAA4AQAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAJQMAADgBAAC7AwAAOAEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgAlAwAAOAEAALsDAAA4AQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAuwMAAHQU + AAC7AwAAOAEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgC7AwAAdBQAALsDAAA4 + AQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAACAAgAABADoAAAACADMAAAACAAMAAgABAQAFAO0fAAB0FAAA7R8AADgB + AAC7AwAAOAEAALsDAAB0FAAA7R8AAHQUAAABiwABAAIAAAADAIUAAQAFAAAAhkUAAAGEAAEA + BQAAAAAAAAAAbwACAC4AAAABAAUAuwMAAHQUAADUEQAAdBQAANQRAABbAwAAuwMAAFsDAAC7 + AwAAdBQAAAAAjAABAAAAAACMAAEAAAAAAIsAAQACAAAAIACAAAEAOgAAAAIAMwAAAAIAAwAC + AAEBAAUA7R8AAHQUAADtHwAAOAEAALsDAAA4AQAAuwMAAHQUAADtHwAAdBQAAAGLAAEAAgAA + AAMAhQABAAUAAACGRQAAAYQAAQAFAAAAAAAAAABvAAIALgAAAAEABQDUEQAAdBQAAO0fAAB0 + FAAA7R8AAC0QAADUEQAALRAAANQRAAB0FAAAAACMAAEAAAAAAIwAAQAAAAAAAAIBACAAAAAW + AFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBB + AAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAAB + AP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAA////AHEABABL + AAAABAkAAK4WAAAGAAAAWwA5AC0AMwA3AF0AAAAGAAYAAABiAAAAJgEAAJwBAABgAgAAJQMA + AIcDAAAGAFsAOQAtADMANwBdAAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + QwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + VwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + QwMAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwMAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + QwQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwUAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + VwUAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + UAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAA + ABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAF + AEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAA + AAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAE + AGMAAAAeFgAArhYAAAkAAAAoADMANwAtADYANQAuADEAXQAAAAkACQAAAHUAAAA6AQAA/gEA + AHQCAAA4AwAA/QMAAF8EAAAjBQAAhQUAAAkAKAAzADcALQA2ADUALgAxAF0AAAAAAACVAAEA + BAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + AQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9XAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + AgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9X + AwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DBAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + BQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DBgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + BwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DCAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9X + CAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9Q + AAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAA + FgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAAAAAAAACVAAEABAAAAAAAAACKAAEARwAAAAUA + QQAAAA8ATGliZXJhdGlvbiBTYW5zAAAAAAAAYQEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAA + AQD/AwAAAAAAAAAAAAAAiAABAAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAP///wBxAAQA + IwAAAP0BAAD0FAAAAQAAADAAAAABAAEAAADEAAAAAQAwAAAAAAAAlQABAAQAAAAAAAAAAAIB + ABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIB + ABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5E + AAAAAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQA + AAAAAAAAigABAEcAAAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAF + AAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8A + hgABAAQAAAD///8AcQAEADMAAADWAAAA0BIAAAMAAAAwAC4ANQAAAAMAAwAAAMQAAAAmAQAA + 6wEAAAMAMAAuADUAAAAAAACVAAEABAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAA + AAAAAgEAEwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAgAAAAAA + AAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAA + AAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAAFgBYVEVY + VF9QQUlOVFNIQVBFX0JFR0lOAAAAAAAAAACVAAEABAAAAAAAAACKAAEARwAAAAUAQQAAAA8A + TGliZXJhdGlvbiBTYW5zAAAAAAAAYQEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAA + AAAAAAAAAAAAiAABAAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAP///wBxAAQAIwAAAP0B + AACtEAAAAQAAADEAAAABAAEAAADEAAAAAQAxAAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAA + AAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAA + igABAEcAAAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAA + AAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQA + AAD///8AcQAEADMAAADWAAAAig4AAAMAAAAxAC4ANQAAAAMAAwAAAMQAAAAmAQAA6wEAAAMA + MQAuADUAAAAAAACVAAEABAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEA + EwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAgAAAAAAAAAAAgEA + EwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEA + HgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlO + VFNIQVBFX0JFR0lOAAAAAAAAAACVAAEABAAAAAAAAACKAAEARwAAAAUAQQAAAA8ATGliZXJh + dGlvbiBTYW5zAAAAAAAAYQEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAAAAAAAAAA + AAAAiAABAAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAP///wBxAAQAIwAAAP0BAABnDAAA + AQAAADIAAAABAAEAAADEAAAAAQAyAAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhU + X0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEA + IAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcA + AAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAA + AAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8A + cQAEADMAAADWAAAARAoAAAMAAAAyAC4ANQAAAAMAAwAAAMQAAAAmAQAA6wEAAAMAMgAuADUA + AAAAAACVAAEABAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkA + WFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAgAAAAAAAAAAAgEAEwAAAAkA + WFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEAHgAAABQA + WFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBF + X0JFR0lOAAAAAAAAAACVAAEABAAAAAAAAACKAAEARwAAAAUAQQAAAA8ATGliZXJhdGlvbiBT + YW5zAAAAAAAAYQEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAAAAAAAAAAAAAAiAAB + AAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAP///wBxAAQAIwAAAP0BAAAhCAAAAQAAADMA + AAABAAEAAADEAAAAAQAzAAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAA + AAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYA + WFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEA + AAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA + /wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAEADMA + AADWAAAA/gUAAAMAAAAzAC4ANQAAAAMAAwAAAMQAAAAmAQAA6wEAAAMAMwAuADUAAAAAAACV + AAEABAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRf + RU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRf + RU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRf + UEFJTlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lO + AAAAAAAAAACVAAEABAAAAAAAAACKAAEARwAAAAUAQQAAAA8ATGliZXJhdGlvbiBTYW5zAAAA + AAAAYQEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAAAAAAAAAAAAAAiAABAAIAAAAB + AIcAAQAFAAAA/////wCGAAEABAAAAP///wBxAAQAIwAAAP0BAADbAwAAAQAAADQAAAABAAEA + AADEAAAAAQA0AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAA + AAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAA + AAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRf + UEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExp + YmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAA + AAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAEADMAAADWAAAA + uAEAAAMAAAA0AC4ANQAAAAMAAwAAAMQAAAAmAQAA6wEAAAMANAAuADUAAAAAAACVAAEABAAA + AAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAQAA + AAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAA + AAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRT + SEFQRV9FTkQAAAAAAAAAAIsAAQACAAAAAwCFAAEABQAAAIZFAAABhAABAAUAAAAAAAAAAG8A + AgA2AAAAAQAGAKAhAAAdDAAANiEAAB0MAAA2IQAASgsAAAkiAABKCwAACSIAAB0MAACgIQAA + HQwAAAAAjAABAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAA + lQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD/ + /wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAA + AP////8AhgABAAQAAAD///8AcQAEAFsAAABtIgAAMgwAAAgAAABDAG8AbAB1AG0AbgAgAEIA + AAAIAAgAAAD/AAAAwwEAABICAADWAgAA/AMAAMEEAAAjBQAADgYAAAgAQwBvAGwAdQBtAG4A + IABCAAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwMAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwQAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwUAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwYAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPVwYAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwcAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4A + AAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAACMAAEAAAAAAIwAAQAAAAAA + + + + + + + + Collabora_Office/26.04.2.0$MacOSX_AARCH64 LibreOffice_project/d7639ee07afbba07078670b0062f4a94edf36179 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Column C + + + + + + + [11-50.9] + + + 33 + + Sheet1.C1:Sheet1.C6 + + + + + (50.9-90.9] + + + 11 + + + + + + 55 + + + + + + 47 + + + + + + 63 + + + + + + 18 + + + + + + + + + + VkNMTVRGAQAxAAAAAAAAAAEAGwAAAAAAAAAAAAAAAACfCng8AMqaO2EAAABkAAAAAJsqAAD3 + FwAAIAIAAIsAAQACAAAA//+BAAEAEAAAAAAAAAAAAAAAmioAAPYXAACLAAEAAgAAACAAggAB + ACEAAAACABsAAAACAAIAAAAAAAAA9hcAAAEAAAAAAJoqAAACAACVAAEABAAAAAAAAACWAAEA + AgAAAAkAiwABAAIAAAADAIUAAQAFAAAAHBwcAAGEAAEABQAAAAAAAAAAbwACADYAAAABAAYA + ThUAAPcXAAAAAAAA9xcAAAAAAAAAAAAAmyoAAAAAAACbKgAA9xcAAE4VAAD3FwAAAACMAAEA + AAAAAIsAAQACAAAAAwCEAAEABQAAALOzswABAAIBAI4AAAAVAFhQQVRIU1RST0tFX1NFUV9C + RUdJTgAAAABvAAAAAQBpAAAAAQAzAAAABgA2EgAAABUAAMADAAAAFQAAwAMAADwBAACsIAAA + PAEAAKwgAAAAFQAANhIAAAAVAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAAAAAAAAAAAAAAAhAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAcwAAAAYANhIA + AAAVAADAAwAAABUAAMADAAA8AQAArCAAADwBAACsIAAAABUAADYSAAAAFQAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAqyAAAP8UAADAAwAA/xQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgCrIAAA/xQAAMADAAD/FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAqyAAAMwS + AADAAwAAzBIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCrIAAAzBIAAMADAADM + EgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAqyAAAJoQAADAAwAAmhAAAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgCrIAAAmhAAAMADAACaEAAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIAqyAAAGgOAADAAwAAaA4AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCr + IAAAaA4AAMADAABoDgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAqyAAADYMAADAAwAANgwA + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCrIAAANgwAAMADAAA2DAAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIAqyAAAAMKAADAAwAAAwoAAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgCrIAAAAwoAAMADAAADCgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAqyAA + ANEHAADAAwAA0QcAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCrIAAA0QcAAMAD + AADRBwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAqyAAAJ8FAADAAwAAnwUAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgCrIAAAnwUAAMADAACfBQAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIAqyAAAG0DAADAAwAAbQMAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgCrIAAAbQMAAMADAABtAwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAqyAAADsBAADAAwAA + OwEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCrIAAAOwEAAMADAAA7AQAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIAwAMAAJUVAADAAwAA/xQAAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgDAAwAAlRUAAMADAAD/FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + wAMAAJUVAADAAwAA/xQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDAAwAAlRUA + AMADAAD/FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIANRIAAJUVAAA1EgAA/xQAAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgA1EgAAlRUAADUSAAD/FAAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIANRIAAJUVAAA1EgAA/xQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgA1EgAAlRUAADUSAAD/FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAqyAAAJUVAACr + IAAA/xQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgCrIAAAlRUAAKsgAAD/FAAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIAqyAAAJUVAACrIAAA/xQAAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgCrIAAAlRUAAKsgAAD/FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIAwAMAAP8UAACrIAAA/xQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDAAwAA + /xQAAKsgAAD/FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAAP8UAADAAwAA/xQAAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAA/xQAAMADAAD/FAAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAKgMAAP8UAADAAwAA/xQAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgAqAwAA/xQAAMADAAD/FAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAAMwS + AADAAwAAzBIAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAAzBIAAMADAADM + EgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFf + QkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAAMwSAADAAwAAzBIAAAABAAIAAAAAAAEA + AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQAB + AAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAAzBIAAMADAADMEgAABQA6AAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAA + ABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUA + AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA + EwAAAAIAKgMAAJoQAADAAwAAmhAAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAq + AwAAmhAAAMADAACaEAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO + RAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFU + SFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAAJoQAADAAwAAmhAA + AAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEA + BQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAAmhAAAMADAACaEAAABQA6AAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEA + AgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA + TwAAAAEASQAAAAEAEwAAAAIAKgMAAGgOAADAAwAAaA4AAAABAAIAAAAAAAEAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA + AG0AAwBTAAAAAgAqAwAAaA4AAMADAABoDgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhT + VFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQAC + AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMA + AGgOAADAAwAAaA4AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA + AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAAaA4AAMAD + AABoDgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA + jAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9T + RVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAADYMAADAAwAANgwAAAABAAIAAAAA + AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB + hQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAANgwAAMADAAA2DAAABQA6AAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEA + HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAAB + AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA + AAEAEwAAAAIAKgMAADYMAADAAwAANgwAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAA + AgAqAwAANgwAAMADAAA2DAAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VR + X0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBY + UEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAAAMKAADAAwAA + AwoAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACE + AAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAAAwoAAMADAAADCgAABQA6 + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACL + AAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4A + AAAATwAAAAEASQAAAAEAEwAAAAIAKgMAAAMKAADAAwAAAwoAAAABAAIAAAAAAAEAAgAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAA + AAAAAG0AAwBTAAAAAgAqAwAAAwoAAMADAAADCgAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAA + AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBB + VEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MA + AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA + KgMAANEHAADAAwAA0QcAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAA0QcA + AMADAADRBwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA + AAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9L + RV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAANEHAADAAwAA0QcAAAABAAIA + AAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOz + swABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAA0QcAAMADAADRBwAABQA6AAAAAQAAAAAA + AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMA + hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA + SQAAAAEAEwAAAAIAKgMAAJ8FAADAAwAAnwUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBT + AAAAAgAqAwAAnwUAAMADAACfBQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0Vf + U0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAA + FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAAJ8FAADA + AwAAnwUAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA + AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAAnwUAAMADAACfBQAA + BQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAA + AACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVH + SU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAAG0DAADAAwAAbQMAAAABAAIAAAAAAAEAAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUA + AAAAAAAAAG0AAwBTAAAAAgAqAwAAbQMAAMADAABtAwAABQA6AAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMA + WFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACz + s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA + AAIAKgMAAG0DAADAAwAAbQMAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAA + bQMAAMADAABtAwAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA + AAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNU + Uk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAKgMAADsBAADAAwAAOwEAAAAB + AAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAA + ALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgAqAwAAOwEAAMADAAA7AQAABQA6AAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA + AAEASQAAAAEAEwAAAAIAKgMAADsBAADAAwAAOwEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A + AwBTAAAAAgAqAwAAOwEAAMADAAA7AQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJP + S0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAAAAMAhAABAAUAAACzs7MAAQACAQBu + AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAwAMAAP8U + AADAAwAAOwEAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA + AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwBTAAAAAgDAAwAA/xQAAMADAAA7 + AQAABQA6AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAAB + AAAAAACLAAEAAgAAACAAgAABADoAAAACADMAAAACAAMAAgABAQAFAKsgAAD/FAAAqyAAADsB + AADAAwAAOwEAAMADAAD/FAAAqyAAAP8UAAABiwABAAIAAAADAIUAAQAFAAAAhkUAAAGEAAEA + BQAAAAAAAAAAbwACAC4AAAABAAUAwAMAAP8UAAA2EgAA/xQAADYSAABtAwAAwAMAAG0DAADA + AwAA/xQAAAAAjAABAAAAAACMAAEAAAAAAIsAAQACAAAAIACAAAEAOgAAAAIAMwAAAAIAAwAC + AAEBAAUAqyAAAP8UAACrIAAAOwEAAMADAAA7AQAAwAMAAP8UAACrIAAA/xQAAAGLAAEAAgAA + AAMAhQABAAUAAACGRQAAAYQAAQAFAAAAAAAAAABvAAIALgAAAAEABQA2EgAA/xQAAKsgAAD/ + FAAAqyAAADYMAAA2EgAANgwAADYSAAD/FAAAAACMAAEAAAAAAIwAAQAAAAAAAAIBACAAAAAW + AFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBB + AAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAAB + AP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAA////AHEABABj + AAAAQggAADkXAAAJAAAAWwAxADEALQA1ADAALgA5AF0AAAAJAAkAAABiAAAAJgEAAOsBAABg + AgAAJQMAAOkDAABLBAAAEAUAAHIFAAAJAFsAMQAxAC0ANQAwAC4AOQBdAAAAAAAAlQABAAQA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwMAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwMA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwUA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwYAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwcA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwgAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwgA + AAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAA + AAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYA + WFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEA + AAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA + /wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAEAHMA + AAAbFgAAORcAAAsAAAAoADUAMAAuADkALQA5ADAALgA5AF0AAAALAAsAAAB1AAAAOgEAAP4B + AABgAgAAJQMAAJoDAABfBAAAIwUAAIUFAABKBgAArAYAAAsAKAA1ADAALgA5AC0AOQAwAC4A + OQBdAAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwEAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwMAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwUAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPVwUAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwYAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwcAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwgAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPQwkAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwoAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPVwoAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAA + AAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAA + AAAAigABAEcAAAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAA + AAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgAB + AAQAAAD///8AcQAEACMAAAACAgAAfxUAAAEAAAAwAAAAAQABAAAAxAAAAAEAMAAAAAAAAJUA + AQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9F + T0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9Q + QUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4A + AAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAA + AABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEA + hwABAAUAAAD/////AIYAAQAEAAAA////AHEABAAzAAAA2wAAAEwTAAADAAAAMAAuADUAAAAD + AAMAAADEAAAAJgEAAOsBAAADADAALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhU + RVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhU + RVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhU + RVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAA + AgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigAB + AEcAAAAFAEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkE + AAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD/ + //8AcQAEACMAAAACAgAAGhEAAAEAAAAxAAAAAQABAAAAxAAAAAEAMQAAAAAAAJUAAQAEAAAA + AAAAAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAA + AAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNI + QVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAA + AJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA + //8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUA + AAD/////AIYAAQAEAAAA////AHEABAAzAAAA2wAAAOgOAAADAAAAMQAuADUAAAADAAMAAADE + AAAAJgEAAOsBAAADADEALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + QwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + QwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VP + UAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAA + ABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAF + AEEAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAA + AAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAE + ACMAAAACAgAAtgwAAAEAAAAyAAAAAQABAAAAxAAAAAEAMgAAAAAAAJUAAQAEAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAAC + AQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VO + RAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAE + AAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIA + BQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD///// + AIYAAQAEAAAA////AHEABAAzAAAA2wAAAIMKAAADAAAAMgAuADUAAAADAAMAAADEAAAAJgEA + AOsBAAADADIALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAA + AAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRF + WFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAP + AExpYmVyYXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMA + AAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAEACMAAAAC + AgAAUQgAAAEAAAAzAAAAAQABAAAAxAAAAAEAMwAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAA + CQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAA + CQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAA + AAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAA + AIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAA + AAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAE + AAAA////AHEABAAzAAAA2wAAAB8GAAADAAAAMwAuADUAAAADAAMAAADEAAAAJgEAAOsBAAAD + ADMALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIB + ABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIB + ABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIB + AB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJ + TlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAEcAAAAFAEEAAAAPAExpYmVy + YXRpb24gU2FucwAAAAAAAGEBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAA + AAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAD///8AcQAEACMAAAACAgAA7QMA + AAEAAAA0AAAAAQABAAAAxAAAAAEANAAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVY + VF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVY + VF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIB + ACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBH + AAAABQBBAAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAA + AAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAA//// + AHEABAAzAAAA2wAAALsBAAADAAAANAAuADUAAAADAAMAAADEAAAAJgEAAOsBAAADADQALgA1 + AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAU + AFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAACLAAEAAgAAAAMAhQABAAUAAACGRQAAAYQA + AQAFAAAAAAAAAABvAAIANgAAAAEABgBkIgAAZAwAAPohAABkDAAA+iEAAJELAADNIgAAkQsA + AM0iAABkDAAAZCIAAGQMAAAAAIwAAQAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVf + QkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQBHAAAABQBBAAAADwBMaWJlcmF0aW9uIFNh + bnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEA + AgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAA////AHEABABbAAAAMSMAAHkMAAAIAAAAQwBv + AGwAdQBtAG4AIABDAAAACAAIAAAA/wAAAMMBAAASAgAA1gIAAPwDAADBBAAAIwUAACIGAAAI + AEMAbwBsAHUAbQBuACAAQwAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MA + AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MC + AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0ME + AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MFAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MG + AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1cGAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MH + AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AA + AAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAjAABAAAAAACM + AAEAAAAAAA== + + + + + + + 12 + + + 45 + + + 33 + + + + + + 10 + + + 32 + + + 11 + + + + + + 11 + + + 18 + + + 55 + + + + + + 13 + + + 9 + + + 47 + + + + + + 15 + + + 25 + + + 63 + + + + + + + 18 + + + + + + + + + + d + + + + + + + diff --git a/chart2/qa/extras/data/fods/tdf163727_histogram_underflow_overflow.fods b/chart2/qa/extras/data/fods/tdf163727_histogram_underflow_overflow.fods new file mode 100644 index 000000000000..58220bd65513 --- /dev/null +++ b/chart2/qa/extras/data/fods/tdf163727_histogram_underflow_overflow.fods @@ -0,0 +1,980 @@ + + + + 2026-06-11T09:14:532026-06-11T09:19:03Collabora_Office/26.04.2.0$MacOSX_AARCH64 LibreOffice_project/3bd3d3482342c24b3ea7aad6194e28b7b896493116.0300 + + + 0 + 0 + 16510 + 7938 + + + view1 + + + 12 + 10 + 2 + 0 + 0 + 0 + 0 + 0 + 100 + 60 + true + false + false + false + false + false + + + Sheet1 + 1377 + 0 + 100 + 60 + false + true + true + true + false + true + -1 + true + true + true + true + false + false + false + 1270 + 1270 + 1 + 1 + true + 1 + -1479,600,1440,904;1;,,,; + false + false + false + false + false + + + + + true + true + true + 0 + true + true + false + true + false + -1 + true + true + 0 + false + false + true + true + false + 3 + false + + false + + false + 1270 + 1270 + 1 + 1 + true + false + false + true + true + true + true + true + 2 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + : + + + + + : + + : + + + + + : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + + + + + + + + + + + 12 + + + + + + + Collabora_Office/26.04.2.0$MacOSX_AARCH64 LibreOffice_project/3bd3d3482342c24b3ea7aad6194e28b7b8964931 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Chart Title + + + + + + + + + + + + + + + + + + + + + + + + + + + Column A + + + + + + + <= 11 + + + 12 + + Sheet1.A1:Sheet1.A5 + + + + + (11-13] + + + 10 + + + + + (13-14] + + + 11 + + + + + > 14 + + + 13 + + + + + + 15 + + + + + + + + + + VkNMTVRGAQAxAAAAAAAAAAEAGwAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAF0wAADE + HQAAQwIAAIsAAQACAAAA//+BAAEAEAAAAAAAAAAAAAAAXDAAAMMdAACLAAEAAgAAACAAggAB + ACEAAAACABsAAAACAAIAAAAAAAAAwx0AAAEAAAAAAFwwAAACAACVAAEABAAAAAAAAACWAAEA + AgAAAAkAiwABAAIAAAADAIUAAQAFAAAA////AAGEAAEABQAAAAAAAAAAbwACADYAAAABAAYA + LxgAAMQdAAAAAAAAxB0AAAAAAAAAAAAAXTAAAAAAAABdMAAAxB0AAC8YAADEHQAAAACMAAEA + AAAAAIsAAQACAAAAAwCEAAEABQAAANnZ2QABAAIBAI4AAAAVAFhQQVRIU1RST0tFX1NFUV9C + RUdJTgAAAABvAAAAAQBpAAAAAQAzAAAABgAvGAAAxB0AAAAAAADEHQAAAAAAAAAAAABdMAAA + AAAAAF0wAADEHQAALxgAAMQdAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAOkAA + AAEAAAAAAAAAOkAAAAAAhAABAAUAAADZ2dkAAYUAAQAFAAAAAAAAAABtAAMAcwAAAAYALxgA + AMQdAAAAAAAAxB0AAAAAAAAAAAAAXTAAAAAAAABdMAAAxB0AAC8YAADEHQAABQA6AAAAAQAa + AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAA6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAjAABAAAAAACLAAEAAgAA + AAMAhQABAAUAAAD///8AAYQAAQAFAAAAAAAAAABvAAIANgAAAAEABgC2GQAAKBoAAAYEAAAo + GgAABgQAABoGAABmLwAAGgYAAGYvAAAoGgAAthkAACgaAAAAAIwAAQAAAAAAiwABAAIAAAAD + AIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAAB + AEkAAAABABMAAAACAGYvAAAnGgAABgQAACcaAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAA + AAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMA + UwAAAAIAZi8AACcaAAAGBAAAJxoAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA + AAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tF + X1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAA + ABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAGYvAAAkFgAA + BgQAACQWAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAA + AAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAZi8AACQWAAAGBAAAJBYA + AAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAA + AAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JF + R0lOAAAAAE8AAAABAEkAAAABABMAAAACAGYvAAAhEgAABgQAACESAAAAAQACAAAAAAABAAIA + AAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAF + AAAAAAAAAABtAAMAUwAAAAIAZi8AACESAAAGBAAAIRIAAAUAOgAAAAEAEgAAAAAAAAAAAAAA + AAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAAT + AFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAA + i4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMA + AAACAGYvAAAeDgAABgQAAB4OAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAA + AAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAZi8A + AB4OAAAGBAAAHg4AAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQA + AAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhT + VFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAGYvAAAbCgAABgQAABsKAAAA + AQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUA + AACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAZi8AABsKAAAGBAAAGwoAAAUAOgAAAAEA + EgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIA + AAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8A + AAABAEkAAAABABMAAAACAGYvAAAZBgAABgQAABkGAAAAAQACAAAAAAABAAIAAAAAAAAAAAAA + AAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABt + AAMAUwAAAAIAZi8AABkGAAAGBAAAGQYAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAE + AAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RS + T0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEA + bgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAAYEAAC9 + GgAABgQAAJEZAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAA + MkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIABgQAAL0aAAAGBAAA + kRkAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwA + AQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VR + X0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAN4OAAC9GgAA3g4AAJEZAAAAAQACAAAAAAAB + AAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUA + AQAFAAAAAAAAAABtAAMAUwAAAAIA3g4AAL0aAADeDgAAkRkAAAUAOgAAAAEAEgAAAAAAAAAA + AAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0A + AAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAF + AAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAAB + ABMAAAACALYZAAC9GgAAthkAAJEZAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAA + MkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIA + thkAAL0aAAC2GQAAkRkAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAA + MkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9F + TkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBB + VEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAI4kAAC9GgAAjiQAAJEZ + AAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAAB + AAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAjiQAAL0aAACOJAAAkRkAAAUAOgAA + AAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwAB + AAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAA + AE8AAAABAEkAAAABABMAAAACAGYvAAC9GgAAZi8AAJEZAAAAAQACAAAAAAABAAIAAAAAAAAA + AAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAA + AABtAAMAUwAAAAIAZi8AAL0aAABmLwAAkRkAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAA + AAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRI + U1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEA + AgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAHIJ + AACXGgAAcgkAALYZAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAA + AAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAcgkAAJcaAABy + CQAAthkAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAA + AIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0Vf + U0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAEoUAACXGgAAShQAALYZAAAAAQACAAAA + AAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sA + AYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAShQAAJcaAABKFAAAthkAAAUAOgAAAAEAEgAAAAAA + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB + AB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQA + AQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkA + AAABABMAAAACACIfAACXGgAAIh8AALYZAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAA + AAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAA + AAIAIh8AAJcaAAAiHwAAthkAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAA + AAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NF + UV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUA + WFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAPopAACXGgAA+ikA + ALYZAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAA + hAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIA+ikAAJcaAAD6KQAAthkAAAUA + OgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAA + iwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lO + AAAAAE8AAAABAEkAAAABABMAAAACAAYEAAAnGgAAZi8AACcaAAAAAQACAAAAAAABAAIAAAAA + AAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAA + AAAAAABtAAMAUwAAAAIABgQAACcaAABmLwAAJxoAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAA + AAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQ + QVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uL + AAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAAC + AHADAAAnGgAAnAQAACcaAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEA + AAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAcAMAACca + AACcBAAAJxoAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAA + AAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJP + S0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAHADAAAkFgAAnAQAACQWAAAAAQAC + AAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACL + i4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAcAMAACQWAACcBAAAJBYAAAUAOgAAAAEAEgAA + AAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAAD + AIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAAB + AEkAAAABABMAAAACAHADAAAhEgAAnAQAACESAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAA + AAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMA + UwAAAAIAcAMAACESAACcBAAAIRIAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA + AAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tF + X1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAA + ABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAHADAAAeDgAA + nAQAAB4OAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAA + AAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAcAMAAB4OAACcBAAAHg4A + AAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAA + AAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JF + R0lOAAAAAE8AAAABAEkAAAABABMAAAACAHADAAAbCgAAnAQAABsKAAAAAQACAAAAAAABAAIA + AAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAF + AAAAAAAAAABtAAMAUwAAAAIAcAMAABsKAACcBAAAGwoAAAUAOgAAAAEAEgAAAAAAAAAAAAAA + AAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAAT + AFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAA + i4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMA + AAACAHADAAAZBgAAnAQAABkGAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAA + AAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAcAMA + ABkGAACcBAAAGQYAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQA + AAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhT + VFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAABZGQAAdwQAAFkZAAAA + AQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUA + AACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAAFkZAAB3BAAAWRkAAAUAOgAAAAEA + EgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIA + AAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8A + AAABAEkAAAABABMAAAACAJYDAACMGAAAdwQAAIwYAAAAAQACAAAAAAABAAIAAAAAAAAAAAAA + AAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABt + AAMAUwAAAAIAlgMAAIwYAAB3BAAAjBgAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAE + AAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RS + T0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEA + bgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAAC+ + FwAAdwQAAL4XAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAA + MkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAAL4XAAB3BAAA + vhcAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwA + AQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VR + X0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAADxFgAAdwQAAPEWAAAAAQACAAAAAAAB + AAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUA + AQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAAPEWAAB3BAAA8RYAAAUAOgAAAAEAEgAAAAAAAAAA + AAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0A + AAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAF + AAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAAB + ABMAAAACAJYDAABWFQAAdwQAAFYVAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAA + MkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIA + lgMAAFYVAAB3BAAAVhUAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAA + MkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9F + TkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBB + VEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAACJFAAAdwQAAIkU + AAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAAB + AAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAAIkUAAB3BAAAiRQAAAUAOgAA + AAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwAB + AAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAA + AE8AAAABAEkAAAABABMAAAACAJYDAAC8EwAAdwQAALwTAAAAAQACAAAAAAABAAIAAAAAAAAA + AAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAA + AABtAAMAUwAAAAIAlgMAALwTAAB3BAAAvBMAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAA + AAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRI + U1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEA + AgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYD + AADuEgAAdwQAAO4SAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAA + AAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAAO4SAAB3 + BAAA7hIAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAA + AIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0Vf + U0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAABUEQAAdwQAAFQRAAAAAQACAAAA + AAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sA + AYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAAFQRAAB3BAAAVBEAAAUAOgAAAAEAEgAAAAAA + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB + AB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQA + AQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkA + AAABABMAAAACAJYDAACGEAAAdwQAAIYQAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAA + AAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAA + AAIAlgMAAIYQAAB3BAAAhhAAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAA + AAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NF + UV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUA + WFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAAC5DwAAdwQA + ALkPAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAA + hAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAALkPAAB3BAAAuQ8AAAUA + OgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAA + iwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lO + AAAAAE8AAAABAEkAAAABABMAAAACAJYDAADrDgAAdwQAAOsOAAAAAQACAAAAAAABAAIAAAAA + AAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAA + AAAAAABtAAMAUwAAAAIAlgMAAOsOAAB3BAAA6w4AAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAA + AAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQ + QVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uL + AAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAAC + AJYDAABRDQAAdwQAAFENAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEA + AAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAAFEN + AAB3BAAAUQ0AAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAA + AAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJP + S0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAACDDAAAdwQAAIMMAAAAAQAC + AAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACL + i4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAAIMMAAB3BAAAgwwAAAUAOgAAAAEAEgAA + AAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAAD + AIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAAB + AEkAAAABABMAAAACAJYDAAC2CwAAdwQAALYLAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAA + AAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMA + UwAAAAIAlgMAALYLAAB3BAAAtgsAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA + AAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tF + X1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAA + ABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAADpCgAA + dwQAAOkKAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAA + AAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAAOkKAAB3BAAA6QoA + AAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAA + AAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JF + R0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAABOCQAAdwQAAE4JAAAAAQACAAAAAAABAAIA + AAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAF + AAAAAAAAAABtAAMAUwAAAAIAlgMAAE4JAAB3BAAATgkAAAUAOgAAAAEAEgAAAAAAAAAAAAAA + AAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAAT + AFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAA + i4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMA + AAACAJYDAACBCAAAdwQAAIEIAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAA + AAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMA + AIEIAAB3BAAAgQgAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQA + AAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhT + VFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAJYDAACzBwAAdwQAALMHAAAA + AQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUA + AACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIAlgMAALMHAAB3BAAAswcAAAUAOgAAAAEA + EgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIA + AAADAIQAAQAFAAAAi4uLAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8A + AAABAEkAAAABABMAAAACAJYDAADmBgAAdwQAAOYGAAAAAQACAAAAAAABAAIAAAAAAAAAAAAA + AAAAAAAAAAAAMkAAAAEAAAAAAAAAMkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABt + AAMAUwAAAAIAlgMAAOYGAAB3BAAA5gYAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAE + AAAAAAAAAAAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RS + T0tFX1NFUV9FTkQAAAAAAAAAAIwAAQAAAAAAiwABAAIAAAADAIQAAQAFAAAAi4uLAAEAAgEA + bgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAAYEAAAn + GgAABgQAABkGAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAMkAAAAEAAAAAAAAA + MkAAAAAAhAABAAUAAACLi4sAAYUAAQAFAAAAAAAAAABtAAMAUwAAAAIABgQAACcaAAAGBAAA + GQYAAAUAOgAAAAEAEgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMkAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIwA + AQAAAAAAiwABAAIAAAAgAIAAAQA6AAAAAgAzAAAAAgADAAIAAQEABQBmLwAAJxoAAGYvAAAZ + BgAABgQAABkGAAAGBAAAJxoAAGYvAAAnGgAAAYsAAQACAAAAAwCFAAEABQAAAMRyRAABhAAB + AAUAAAAAAAAAAG8AAgAuAAAAAQAFAAYEAAAnGgAA3g4AACcaAADeDgAAGwoAAAYEAAAbCgAA + BgQAACcaAAAAAIwAAQAAAAAAjAABAAAAAACLAAEAAgAAACAAgAABADoAAAACADMAAAACAAMA + AgABAQAFAGYvAAAnGgAAZi8AABkGAAAGBAAAGQYAAAYEAAAnGgAAZi8AACcaAAABiwABAAIA + AAADAIUAAQAFAAAAxHJEAAGEAAEABQAAAAAAAAAAbwACAC4AAAABAAUA3g4AACcaAAC2GQAA + JxoAALYZAAAbCgAA3g4AABsKAADeDgAAJxoAAAAAjAABAAAAAACMAAEAAAAAAIsAAQACAAAA + IACAAAEAOgAAAAIAMwAAAAIAAwACAAEBAAUAZi8AACcaAABmLwAAJxoAAAYEAAAnGgAABgQA + ACcaAABmLwAAJxoAAAGLAAEAAgAAAAMAhQABAAUAAADEckQAAYQAAQAFAAAAAAAAAABvAAIA + JgAAAAEABAC2GQAAJxoAAI4kAAAnGgAAjiQAACcaAAC2GQAAJxoAAAAAjAABAAAAAACMAAEA + AAAAAIsAAQACAAAAIACAAAEAOgAAAAIAMwAAAAIAAwACAAEBAAUAZi8AACcaAABmLwAAGQYA + AAYEAAAZBgAABgQAACcaAABmLwAAJxoAAAGLAAEAAgAAAAMAhQABAAUAAADEckQAAYQAAQAF + AAAAAAAAAABvAAIALgAAAAEABQCOJAAAJxoAAGYvAAAnGgAAZi8AACESAACOJAAAIRIAAI4k + AAAnGgAAAACMAAEAAAAAAIwAAQAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVH + SU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQA/AAAABQA5AAAABwBDYWxpYnJpAAAAAAAApwEA + AP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAAAAAAAAAAAAAAiAABAAIAAAABAIcAAQAF + AAAA/////wCGAAEABAAAAAAAAABxAAQAQwAAAJ0HAAC1HAAABQAAADwAPQAgADEAMQAAAAUA + BQAAANEAAACiAQAAAQIAANcCAACsAwAABQA8AD0AIAAxADEAAAAAAACVAAEABAAAAAAAAAAA + AgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAA + AgEAEwAAAAkAWFRFWFRfRU9XAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAgAAAAAAAAAA + AgEAEwAAAAkAWFRFWFRfRU9DAwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9XAwAAAAAAAAAA + AgEAEwAAAAkAWFRFWFRfRU9DBAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAA + AgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9F + TkQAAAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAAAAAAAACVAAEA + BAAAAAAAAACKAAEAPwAAAAUAOQAAAAcAQ2FsaWJyaQAAAAAAAKcBAAD//wAAAgAFAAAAAAAA + AAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQA + AAAAAAAAcQAEAFMAAADgEQAAtRwAAAcAAAAoADEAMQAtADEAMwBdAAAABwAHAAAAfwAAAFQB + AAApAgAAqgIAAH8DAABUBAAA1QQAAAcAKAAxADEALQAxADMAXQAAAAAAAJUAAQAEAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MBAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT1cBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1cDAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT0MEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MFAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT0MGAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1cGAAAAAAAA + AAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAA + AAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhU + X1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQA/AAAABQA5AAAABwBD + YWxpYnJpAAAAAAAApwEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAAAAAAAAAAAAAA + iAABAAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAAAAAABxAAQAUwAAALgcAAC1HAAABwAA + ACgAMQAzAC0AMQA0AF0AAAAHAAcAAAB/AAAAVAEAACkCAACqAgAAfwMAAFQEAADVBAAABwAo + ADEAMwAtADEANABdAAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPVwEAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwMAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPVwMAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwQAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPQwUAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwYAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPVwYAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hB + UEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAA + lQABAAQAAAAAAAAAigABAD8AAAAFADkAAAAHAENhbGlicmkAAAAAAACnAQAA//8AAAIABQAA + AAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYA + AQAEAAAAAAAAAHEABAA7AAAAjSgAALUcAAAEAAAAPgAgADEANAAAAAQABAAAANEAAAAwAQAA + BQIAANoCAAAEAD4AIAAxADQAAAAAAACVAAEABAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + AAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9X + AQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D + AwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9Q + AAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAA + FgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAAAAAAAACVAAEABAAAAAAAAACKAAEAPwAAAAUA + OQAAAAcAQ2FsaWJyaQAAAAAAAKcBAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAA + AAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQAAAAAAAAAcQAEACMAAAA3AgAA + txoAAAEAAAAwAAAAAQABAAAA1QAAAAEAMAAAAAAAAJUAAQAEAAAAAAAAAAACAQATAAAACQBY + VEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBY + VEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAA + AAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoA + AQA/AAAABQA5AAAABwBDYWxpYnJpAAAAAAAApwEAAP//AAACAAUAAAAAAAAACQQAAAAAAAAA + AQD/AwAAAAAAAAAAAAAAiAABAAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAAAAAABxAAQA + MwAAAPgAAAC0FgAAAwAAADAALgA1AAAAAwADAAAA1QAAAD8BAAAUAgAAAwAwAC4ANQAAAAAA + AJUAAQAEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVY + VF9FT0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAAAAACAQATAAAACQBYVEVY + VF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVY + VF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVH + SU4AAAAAAAAAAJUAAQAEAAAAAAAAAIoAAQA/AAAABQA5AAAABwBDYWxpYnJpAAAAAAAApwEA + AP//AAACAAUAAAAAAAAACQQAAAAAAAAAAQD/AwAAAAAAAAAAAAAAiAABAAIAAAABAIcAAQAF + AAAA/////wCGAAEABAAAAAAAAABxAAQAIwAAADcCAACxEgAAAQAAADEAAAABAAEAAADVAAAA + AQAxAAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMA + AAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAAAAAAAAIBAB4A + AAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRT + SEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAAigABAD8AAAAFADkAAAAHAENhbGlicmkA + AAAAAACnAQAA//8AAAIABQAAAAAAAAAJBAAAAAAAAAABAP8DAAAAAAAAAAAAAACIAAEAAgAA + AAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEABAAzAAAA+AAAAK4OAAADAAAAMQAuADUA + AAADAAMAAADVAAAAPwEAABQCAAADADEALgA1AAAAAAAAlQABAAQAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJ + AFhURVhUX0VPUAAAAAAAAAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAA + AAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQRV9CRUdJTgAAAAAAAAAAlQABAAQAAAAAAAAA + igABAD8AAAAFADkAAAAHAENhbGlicmkAAAAAAACnAQAA//8AAAIABQAAAAAAAAAJBAAAAAAA + AAABAP8DAAAAAAAAAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEA + BAAjAAAANwIAAKsKAAABAAAAMgAAAAEAAQAAANUAAAABADIAAAAAAACVAAEABAAAAAAAAAAA + AgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAA + AgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9F + TkQAAAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAAAAAAAACVAAEA + BAAAAAAAAACKAAEAPwAAAAUAOQAAAAcAQ2FsaWJyaQAAAAAAAKcBAAD//wAAAgAFAAAAAAAA + AAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQACAAAAAQCHAAEABQAAAP////8AhgABAAQA + AAAAAAAAcQAEADMAAAD4AAAAqQYAAAMAAAAyAC4ANQAAAAMAAwAAANUAAAA/AQAAFAIAAAMA + MgAuADUAAAAAAACVAAEABAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEA + EwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAgAAAAAAAAAAAgEA + EwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEA + HgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlO + VFNIQVBFX0JFR0lOAAAAAAAAAACVAAEABAAAAAAAAACKAAEAPwAAAAUAOQAAAAcAQ2FsaWJy + aQAAAAAAAO4BAAD//wAAAgAFAAAAAAAAAAkEAAAAAAAAAAEA/wMAAAAAAAAAAAAAAIgAAQAC + AAAAAQCHAAEABQAAAP////8AhgABAAQAAAB/f38AcQAEAHMAAAAoFAAAdgMAAAsAAABDAGgA + YQByAHQAIABUAGkAdABsAGUAAAALAAsAAAAEAQAABAIAAO4CAACYAwAAOwQAAKkEAACXBQAA + BwYAAKoGAAAaBwAADQgAAAsAQwBoAGEAcgB0ACAAVABpAHQAbABlAAAAAAAAlQABAAQAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPQwAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwEAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPQwIAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwMAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPQwQAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwUAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPVwUAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwYAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPQwcAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwgAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPQwkAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPQwoAAAAA + AAAAAAIBABMAAAAJAFhURVhUX0VPTAAAAAAAAAAAAAIBABMAAAAJAFhURVhUX0VPUAAAAAAA + AAAAAAIBAB4AAAAUAFhURVhUX1BBSU5UU0hBUEVfRU5EAAAAAAAAAACMAAEAAAAAAIwAAQAA + AAAA + + + + + + + + + 10 + + + + + + 11 + + + + + + 13 + + + + + + 15 + + + + + + + + + + \ No newline at end of file diff --git a/chart2/qa/extras/data/xlsx/SimpleHistogram.xlsx b/chart2/qa/extras/data/xlsx/SimpleHistogram.xlsx new file mode 100644 index 000000000000..5fb7e33b7a4c Binary files /dev/null and b/chart2/qa/extras/data/xlsx/SimpleHistogram.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/box-whisker-gapwidth.xlsx b/chart2/qa/extras/data/xlsx/box-whisker-gapwidth.xlsx new file mode 100644 index 000000000000..152e05b0d985 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/box-whisker-gapwidth.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/color_funnel.xlsx b/chart2/qa/extras/data/xlsx/color_funnel.xlsx index 80d16d5d1b84..80b1a746343d 100644 Binary files a/chart2/qa/extras/data/xlsx/color_funnel.xlsx and b/chart2/qa/extras/data/xlsx/color_funnel.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/funnel-label-options.xlsx b/chart2/qa/extras/data/xlsx/funnel-label-options.xlsx new file mode 100644 index 000000000000..87242df22387 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/funnel-label-options.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/pareto-gapwidth.xlsx b/chart2/qa/extras/data/xlsx/pareto-gapwidth.xlsx new file mode 100644 index 000000000000..419ef725ae49 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/pareto-gapwidth.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/regionMap.xlsx b/chart2/qa/extras/data/xlsx/regionMap.xlsx index 55ff2b005e89..c79e150399b8 100644 Binary files a/chart2/qa/extras/data/xlsx/regionMap.xlsx and b/chart2/qa/extras/data/xlsx/regionMap.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/sunburst.xlsx b/chart2/qa/extras/data/xlsx/sunburst.xlsx index 010ea1054a17..9faced488a6e 100644 Binary files a/chart2/qa/extras/data/xlsx/sunburst.xlsx and b/chart2/qa/extras/data/xlsx/sunburst.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf159450.xlsx b/chart2/qa/extras/data/xlsx/tdf159450.xlsx new file mode 100644 index 000000000000..011bc9778d47 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf159450.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf163727_histogram_roundtrip_multi_chart.xlsx b/chart2/qa/extras/data/xlsx/tdf163727_histogram_roundtrip_multi_chart.xlsx new file mode 100644 index 000000000000..70b7910b1642 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf163727_histogram_roundtrip_multi_chart.xlsx differ diff --git a/chart2/qa/extras/data/xlsx/tdf163727_histogram_underflow_overflow.xlsx b/chart2/qa/extras/data/xlsx/tdf163727_histogram_underflow_overflow.xlsx new file mode 100644 index 000000000000..9eb2ff956883 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/tdf163727_histogram_underflow_overflow.xlsx differ diff --git a/chart2/qa/extras/xshape/chart2xshape.cxx b/chart2/qa/extras/xshape/chart2xshape.cxx index 4ee8edad96f6..1c90d4358758 100644 --- a/chart2/qa/extras/xshape/chart2xshape.cxx +++ b/chart2/qa/extras/xshape/chart2xshape.cxx @@ -27,8 +27,8 @@ public: } void testTdf150832_dump_chart_shapes_from_xls(); - void testTdf149204(); - void testTdf151424(); + void testTdf149204_chart_shape_size_from_pptx_import(); + void testTdf151424_radar_chart_shape_position_from_ods(); void testFdo75075(); void testPropertyMappingBarChart(); void testPieChartLabels1(); @@ -41,8 +41,8 @@ public: CPPUNIT_TEST_SUITE(Chart2XShapeTest); CPPUNIT_TEST(testTdf150832_dump_chart_shapes_from_xls); - CPPUNIT_TEST(testTdf149204); - CPPUNIT_TEST(testTdf151424); + CPPUNIT_TEST(testTdf149204_chart_shape_size_from_pptx_import); + CPPUNIT_TEST(testTdf151424_radar_chart_shape_position_from_ods); CPPUNIT_TEST(testFdo75075); CPPUNIT_TEST(testPropertyMappingBarChart); CPPUNIT_TEST(testPieChartLabels1); @@ -98,10 +98,21 @@ xmlDocUniquePtr Chart2XShapeTest::getXShapeDumpXmlDoc() void Chart2XShapeTest::compareAgainstReference(std::u16string_view rDump, std::u16string_view rReferenceFile) { + OUString aReference = m_directories.getPathFromSrc(u"/chart2/qa/extras/xshape/data/reference/") + + rReferenceFile; + + // Set UPDATE_XSHAPE_REFERENCE=1 to overwrite the reference dumps + // with the live output instead of comparing. + if (getenv("UPDATE_XSHAPE_REFERENCE")) + { + std::ofstream aStream(OUStringToOString(aReference, RTL_TEXTENCODING_UTF8).getStr(), + std::ios::trunc | std::ios::binary); + aStream << OUStringToOString(rDump, RTL_TEXTENCODING_UTF8); + return; + } + checkDumpAgainstFile( - rDump, - Concat2View(m_directories.getPathFromSrc(u"/chart2/qa/extras/xshape/data/reference/") - + rReferenceFile), + rDump, aReference, OUStringToOString( m_directories.getPathFromSrc(u"/chart2/qa/extras/xshape/data/reference/tolerance.xml"), RTL_TEXTENCODING_UTF8) @@ -122,7 +133,7 @@ void Chart2XShapeTest::testTdf150832_dump_chart_shapes_from_xls() compareAgainstReference(getXShapeDumpString(), u"tdf150832.xml"); } -void Chart2XShapeTest::testTdf149204() +void Chart2XShapeTest::testTdf149204_chart_shape_size_from_pptx_import() { // FIXME: the DPI check should be removed when either (1) the test is fixed to work with // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. @@ -139,7 +150,7 @@ void Chart2XShapeTest::testTdf149204() compareAgainstReference(getShapeDump(xChartDoc), u"tdf149204.xml"); } -void Chart2XShapeTest::testTdf151424() +void Chart2XShapeTest::testTdf151424_radar_chart_shape_position_from_ods() { // FIXME: the DPI check should be removed when either (1) the test is fixed to work with // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. diff --git a/chart2/qa/extras/xshape/data/reference/tolerance.xml b/chart2/qa/extras/xshape/data/reference/tolerance.xml index 17ec7220fc77..7e6ed3659c64 100644 --- a/chart2/qa/extras/xshape/data/reference/tolerance.xml +++ b/chart2/qa/extras/xshape/data/reference/tolerance.xml @@ -12,4 +12,5 @@ + diff --git a/chart2/qa/unit/correlation_coefficient_test.cxx b/chart2/qa/unit/correlation_coefficient_test.cxx new file mode 100644 index 000000000000..6d0b703b2181 --- /dev/null +++ b/chart2/qa/unit/correlation_coefficient_test.cxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 +#include + +#include +#include +#include +#include + +#include +#include + +#include + +namespace +{ +constexpr double fTolerance = 1e-12; + +const double fNotANumber = std::numeric_limits::quiet_NaN(); + +std::optional lclCoefficientOf(const std::vector& rFirst, + const std::vector& rSecond) +{ + return chart::calculateCorrelationCoefficient(rFirst, rSecond); +} + +} // anonymous namespace + +class CorrelationCoefficientTest : public CppUnit::TestFixture +{ +public: + CPPUNIT_TEST_SUITE(CorrelationCoefficientTest); + CPPUNIT_TEST(testValuesThatRiseTogether); + CPPUNIT_TEST(testValuesThatMoveApart); + CPPUNIT_TEST(testValuesWithoutARelation); + CPPUNIT_TEST(testMissingValuesAreLeftOut); + CPPUNIT_TEST(testRunsOfDifferentLength); + CPPUNIT_TEST(testAnswerlessInput); + CPPUNIT_TEST_SUITE_END(); + + void testValuesThatRiseTogether(); + void testValuesThatMoveApart(); + void testValuesWithoutARelation(); + void testMissingValuesAreLeftOut(); + void testRunsOfDifferentLength(); + void testAnswerlessInput(); +}; + +// Values that rise together, whatever their scale and offset, are perfectly +// related. +void CorrelationCoefficientTest::testValuesThatRiseTogether() +{ + std::optional oCoefficient + = lclCoefficientOf({ 1.0, 2.0, 3.0, 4.0 }, { 11.0, 13.0, 15.0, 17.0 }); + CPPUNIT_ASSERT(oCoefficient.has_value()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, *oCoefficient, fTolerance); +} + +void CorrelationCoefficientTest::testValuesThatMoveApart() +{ + std::optional oCoefficient + = lclCoefficientOf({ 1.0, 2.0, 3.0, 4.0 }, { 8.0, 6.0, 4.0, 2.0 }); + CPPUNIT_ASSERT(oCoefficient.has_value()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.0, *oCoefficient, fTolerance); +} + +// Uncorrelated sequences +void CorrelationCoefficientTest::testValuesWithoutARelation() +{ + std::optional oCoefficient + = lclCoefficientOf({ 1.0, 2.0, 3.0, 4.0 }, { 1.0, -1.0, -1.0, 1.0 }); + CPPUNIT_ASSERT(oCoefficient.has_value()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, *oCoefficient, fTolerance); +} + +// The instances where one side is missing count for nothing, so the answer +// matches the one for the pairs that are left. +void CorrelationCoefficientTest::testMissingValuesAreLeftOut() +{ + std::optional oWithGaps = lclCoefficientOf({ 1.0, fNotANumber, 2.0, 3.0, 4.0 }, + { 8.0, 100.0, 6.0, fNotANumber, 2.0 }); + std::optional oWithoutGaps = lclCoefficientOf({ 1.0, 2.0, 4.0 }, { 8.0, 6.0, 2.0 }); + CPPUNIT_ASSERT(oWithGaps.has_value()); + CPPUNIT_ASSERT(oWithoutGaps.has_value()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(*oWithoutGaps, *oWithGaps, fTolerance); +} + +// The shorter run says how many instances there are to compare. +void CorrelationCoefficientTest::testRunsOfDifferentLength() +{ + std::optional oCoefficient + = lclCoefficientOf({ 1.0, 2.0, 3.0 }, { 2.0, 4.0, 6.0, 8.0, 10.0 }); + CPPUNIT_ASSERT(oCoefficient.has_value()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, *oCoefficient, fTolerance); +} + +// A singleton pair, empty pair, and a run that holds one value throughout all +// leave the coefficient undefined. +void CorrelationCoefficientTest::testAnswerlessInput() +{ + CPPUNIT_ASSERT(!lclCoefficientOf({ 1.0 }, { 2.0 }).has_value()); + CPPUNIT_ASSERT(!lclCoefficientOf({}, {}).has_value()); + CPPUNIT_ASSERT(!lclCoefficientOf({ 1.0, fNotANumber }, { 2.0, 3.0 }).has_value()); + CPPUNIT_ASSERT(!lclCoefficientOf({ 5.0, 5.0, 5.0 }, { 1.0, 2.0, 3.0 }).has_value()); + CPPUNIT_ASSERT(!lclCoefficientOf({ 1.0, 2.0, 3.0 }, { 5.0, 5.0, 5.0 }).has_value()); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(CorrelationCoefficientTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/qa/unit/splines_test.cxx b/chart2/qa/unit/splines_test.cxx new file mode 100644 index 000000000000..f8692bd0f4a5 --- /dev/null +++ b/chart2/qa/unit/splines_test.cxx @@ -0,0 +1,260 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#include + +#include + +#include +#include + +#include +#include + +namespace +{ +class SplinesTest : public UnoApiTest +{ +public: + SplinesTest() + : UnoApiTest(u""_ustr) + { + } + + static constexpr double fAssertDelta = 1e-4; +}; + +CPPUNIT_TEST_FIXTURE(SplinesTest, bSplinesLinear1) +{ + std::vector> aPoints; + + //Input points: (0,0), (2,2) + aPoints.push_back(std::vector()); + aPoints[0].push_back(css::drawing::Position3D(0, 0, 0)); + aPoints[0].push_back(css::drawing::Position3D(2, 2, 0)); + sal_uInt32 nResolution = 2; + sal_uInt32 nDegree = 1; + + std::vector> aResult; + + chart::SplineCalculator::CalculateBSplines(aPoints, aResult, nResolution, nDegree); + + //Expected: result points form a line + CPPUNIT_ASSERT_EQUAL(1, static_cast(aResult.size())); + CPPUNIT_ASSERT_EQUAL(3, static_cast(aResult[0].size())); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][1].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][1].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][1].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult[0][2].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult[0][2].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][2].PositionZ, SplinesTest::fAssertDelta); +} + +CPPUNIT_TEST_FIXTURE(SplinesTest, bSplinesLinear2) +{ + std::vector> aPoints; + + //Input points: (0,0), (3,3) + aPoints.push_back(std::vector()); + aPoints[0].push_back(css::drawing::Position3D(0, 0, 0)); + aPoints[0].push_back(css::drawing::Position3D(3, 3, 0)); + sal_uInt32 nResolution = 3; + sal_uInt32 nDegree = 1; + + std::vector> aResult; + + chart::SplineCalculator::CalculateBSplines(aPoints, aResult, nResolution, nDegree); + + //Expected: result points form a line + CPPUNIT_ASSERT_EQUAL(1, static_cast(aResult.size())); + CPPUNIT_ASSERT_EQUAL(4, static_cast(aResult[0].size())); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][1].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][1].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][1].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult[0][2].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult[0][2].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][2].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aResult[0][3].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aResult[0][3].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][3].PositionZ, SplinesTest::fAssertDelta); +} + +CPPUNIT_TEST_FIXTURE(SplinesTest, bSplinesArch) +{ + std::vector> aPoints; + + //Input points: (0,0), (1,1), (2,0) + aPoints.push_back(std::vector()); + aPoints[0].push_back(css::drawing::Position3D(0, 0, 0)); + aPoints[0].push_back(css::drawing::Position3D(1, 1, 0)); + aPoints[0].push_back(css::drawing::Position3D(2, 0, 0)); + sal_uInt32 nResolution = 3; + sal_uInt32 nDegree = 2; + + std::vector> aResult; + + chart::SplineCalculator::CalculateBSplines(aPoints, aResult, nResolution, nDegree); + + //Expected: result points form an arch shape + CPPUNIT_ASSERT_EQUAL(1, static_cast(aResult.size())); + CPPUNIT_ASSERT_EQUAL(7, static_cast(aResult[0].size())); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(1 / 3.0, aResult[0][1].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.555555555555556, aResult[0][1].PositionY, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][1].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(2 / 3.0, aResult[0][2].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.888888888888889, aResult[0][2].PositionY, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][2].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][3].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][3].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][3].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(4 / 3.0, aResult[0][4].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.888888888888889, aResult[0][4].PositionY, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][4].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(5 / 3.0, aResult[0][5].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.555555555555556, aResult[0][5].PositionY, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][5].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult[0][6].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][6].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][6].PositionZ, SplinesTest::fAssertDelta); +} + +CPPUNIT_TEST_FIXTURE(SplinesTest, bSplinesLoop) +{ + std::vector> aPoints; + + //Input points: (0,0), (1,1), (2,0), (0,0) + aPoints.push_back(std::vector()); + aPoints[0].push_back(css::drawing::Position3D(0, 0, 0)); + aPoints[0].push_back(css::drawing::Position3D(1, 1, 0)); + aPoints[0].push_back(css::drawing::Position3D(2, 0, 0)); + aPoints[0].push_back(css::drawing::Position3D(0, 0, 0)); + sal_uInt32 nResolution = 2; + sal_uInt32 nDegree = 2; + + std::vector> aResult; + + chart::SplineCalculator::CalculateBSplines(aPoints, aResult, nResolution, nDegree); + + //Expected: result points form a loop shape + CPPUNIT_ASSERT_EQUAL(1, static_cast(aResult.size())); + CPPUNIT_ASSERT_EQUAL(7, static_cast(aResult[0].size())); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.449682859897576, aResult[0][1].PositionX, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.809837501016391, aResult[0][1].PositionY, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][1].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][2].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][2].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][2].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.65095142030727, aResult[0][3].PositionX, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.570487496950826, aResult[0][3].PositionY, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][3].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult[0][4].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][4].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][4].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.49811427366873, aResult[0][5].PositionX, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.238807647737986, aResult[0][5].PositionY, + SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][5].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][6].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][6].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][6].PositionZ, SplinesTest::fAssertDelta); +} + +CPPUNIT_TEST_FIXTURE(SplinesTest, bSplines2SeriesLinear) +{ + //Two (rather than just one) series of input points + std::vector> aPoints; + + aPoints.push_back(std::vector()); + aPoints[0].push_back(css::drawing::Position3D(0, 0, 0)); + aPoints[0].push_back(css::drawing::Position3D(2, 2, 0)); + + aPoints.push_back(std::vector()); + aPoints[1].push_back(css::drawing::Position3D(0, 0, 0)); + aPoints[1].push_back(css::drawing::Position3D(-2, 2, 0)); + sal_uInt32 nResolution = 2; + sal_uInt32 nDegree = 1; + + std::vector> aResult; + + chart::SplineCalculator::CalculateBSplines(aPoints, aResult, nResolution, nDegree); + + //Expected: Two results series, each with three points along a line + CPPUNIT_ASSERT_EQUAL(2, static_cast(aResult.size())); + CPPUNIT_ASSERT_EQUAL(3, static_cast(aResult[0].size())); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][0].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][1].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[0][1].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][1].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult[0][2].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult[0][2].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[0][2].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_EQUAL(3, static_cast(aResult[1].size())); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[1][0].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[1][0].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[1][0].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.0, aResult[1][1].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aResult[1][1].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[1][1].PositionZ, SplinesTest::fAssertDelta); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(-2.0, aResult[1][2].PositionX, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult[1][2].PositionY, SplinesTest::fAssertDelta); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult[1][2].PositionZ, SplinesTest::fAssertDelta); +} + +} //namespace + +CPPUNIT_PLUGIN_IMPLEMENT(); +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/chart2.component b/chart2/source/chart2.component index 4f1fcb92ed0d..d8b78510d451 100644 --- a/chart2/source/chart2.component +++ b/chart2/source/chart2.component @@ -127,6 +127,12 @@ + + + + + @@ -147,6 +153,11 @@ + + + + diff --git a/chart2/source/controller/accessibility/AccessibleBase.cxx b/chart2/source/controller/accessibility/AccessibleBase.cxx index c22c02055933..46f758b34350 100644 --- a/chart2/source/controller/accessibility/AccessibleBase.cxx +++ b/chart2/source/controller/accessibility/AccessibleBase.cxx @@ -395,7 +395,6 @@ sal_Int64 AccessibleBase::ImplGetAccessibleChildCount() const Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleChild( sal_Int64 i ) { ensureAlive(); - Reference< XAccessible > xResult; ClearableMutexGuard aGuard( m_aMutex ); bool bMustUpdateChildren = ( m_bMayHaveChildren && @@ -406,15 +405,11 @@ Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleChild( sal_Int64 if( bMustUpdateChildren ) UpdateChildren(); - xResult.set( ImplGetAccessibleChildById( i )); - - return xResult; + return ImplGetAccessibleChildById(i); } Reference< XAccessible > AccessibleBase::ImplGetAccessibleChildById( sal_Int64 i ) const { - rtl::Reference xResult; - MutexGuard aGuard( m_aMutex); if( ! m_bMayHaveChildren || i < 0 || @@ -428,10 +423,8 @@ Reference< XAccessible > AccessibleBase::ImplGetAccessibleChildById( sal_Int64 i static_cast< const ::cppu::OWeakObject * >( this ))); throw aEx; } - else - xResult = m_aChildList[i]; - return xResult; + return m_aChildList[i]; } Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleParent() diff --git a/chart2/source/controller/accessibility/AccessibleChartShape.cxx b/chart2/source/controller/accessibility/AccessibleChartShape.cxx index cbebfd8da775..6d20846275f3 100644 --- a/chart2/source/controller/accessibility/AccessibleChartShape.cxx +++ b/chart2/source/controller/accessibility/AccessibleChartShape.cxx @@ -40,12 +40,12 @@ AccessibleChartShape::AccessibleChartShape( return; Reference< drawing::XShape > xShape( rAccInfo.m_aOID.getAdditionalShape() ); - Reference< XAccessible > xParent; + rtl::Reference pParent; if ( rAccInfo.m_pParent ) { - xParent.set( rAccInfo.m_pParent ); + pParent.set(rAccInfo.m_pParent); } - ::accessibility::AccessibleShapeInfo aShapeInfo( xShape, xParent ); + ::accessibility::AccessibleShapeInfo aShapeInfo(xShape, pParent); m_aShapeTreeInfo.SetSdrView( rAccInfo.m_pSdrView ); m_aShapeTreeInfo.SetController( nullptr ); diff --git a/chart2/source/controller/accessibility/AccessibleChartView.cxx b/chart2/source/controller/accessibility/AccessibleChartView.cxx index d8431b4e55c0..d084e43aba43 100644 --- a/chart2/source/controller/accessibility/AccessibleChartView.cxx +++ b/chart2/source/controller/accessibility/AccessibleChartView.cxx @@ -103,7 +103,7 @@ OUString SAL_CALL AccessibleChartView::getAccessibleDescription() Reference< XAccessible > SAL_CALL AccessibleChartView::getAccessibleParent() { - return Reference< XAccessible >( m_xParent ); + return m_pParent.get(); } sal_Int64 SAL_CALL AccessibleChartView::getAccessibleIndexInParent() @@ -120,16 +120,12 @@ sal_Int16 SAL_CALL AccessibleChartView::getAccessibleRole() awt::Rectangle AccessibleChartView::implGetBounds() { awt::Rectangle aResult( GetWindowPosSize()); - Reference< XAccessible > xParent( m_xParent ); - if( xParent.is()) + rtl::Reference pParent(m_pParent); + if (pParent.is()) { - Reference< XAccessibleComponent > xContext( xParent->getAccessibleContext(), uno::UNO_QUERY ); - if( xContext.is()) - { - awt::Point aParentPosition = xContext->getLocationOnScreen(); - aResult.X -= aParentPosition.X; - aResult.Y -= aParentPosition.Y; - } + awt::Point aParentPosition = pParent->getLocationOnScreen(); + aResult.X -= aParentPosition.X; + aResult.Y -= aParentPosition.Y; } return aResult; } @@ -142,11 +138,11 @@ void SAL_CALL AccessibleChartView::disposing() AccessibleBase::disposing(); } -void AccessibleChartView::initialize( ChartController& rNewChartController, - const rtl::Reference<::chart::ChartModel>& xNewChartModel, - const rtl::Reference<::chart::ChartView>& xNewChartView, - const uno::Reference< XAccessible >& xNewParent, - ChartWindow* pNewChartWindow) +void AccessibleChartView::initialize(ChartController& rNewChartController, + const rtl::Reference<::chart::ChartModel>& xNewChartModel, + const rtl::Reference<::chart::ChartView>& xNewChartView, + const rtl::Reference& rpNewParent, + ChartWindow* pNewChartWindow) { //0: view::XSelectionSupplier offers notifications for selection changes and access to the selection itself //1: frame::XModel representing the chart model - offers access to object data @@ -160,14 +156,14 @@ void AccessibleChartView::initialize( ChartController& rNewChartController, rtl::Reference< ::chart::ChartController > xChartController; rtl::Reference<::chart::ChartModel> xChartModel; rtl::Reference<::chart::ChartView> xChartView; - Reference< XAccessible > xParent; + rtl::Reference pParent; VclPtr pChartWindow; { MutexGuard aGuard( m_aMutex); xChartController = m_xChartController; xChartModel = m_xChartModel; xChartView = m_xChartView; - xParent.set( m_xParent ); + pParent = m_pParent.get(); pChartWindow = m_pChartWindow; } @@ -188,9 +184,9 @@ void AccessibleChartView::initialize( ChartController& rNewChartController, bChanged = true; } - if( xNewParent != xParent ) + if (rpNewParent != pParent) { - xParent = xNewParent; + pParent = rpNewParent; bChanged = true; } @@ -218,7 +214,7 @@ void AccessibleChartView::initialize( ChartController& rNewChartController, } xChartModel.clear(); xChartView.clear(); - xParent.clear(); + pParent.clear(); pChartWindow.reset(); bNewInvalid = true; @@ -229,7 +225,7 @@ void AccessibleChartView::initialize( ChartController& rNewChartController, m_xChartController = xChartController.get(); m_xChartModel = xChartModel.get(); m_xChartView = xChartView.get(); - m_xParent = xParent; + m_pParent = pParent.get(); m_pChartWindow = std::move(pChartWindow); } @@ -241,7 +237,7 @@ void AccessibleChartView::initialize( ChartController& rNewChartController, { //before notification we prepare for creation of new context - //the old context will be deleted after notification than + //the old context will be deleted after notification then MutexGuard aGuard( m_aMutex); if( xChartModel.is()) m_spObjectHierarchy = @@ -316,7 +312,7 @@ void AccessibleChartView::initialize() m_xChartController = xChartController.get(); m_xChartModel = xChartModel.get(); m_xChartView = xChartView.get(); - m_xParent.clear(); + m_pParent.clear(); m_pChartWindow.reset(); } @@ -328,7 +324,7 @@ void AccessibleChartView::initialize() { //before notification we prepare for creation of new context - //the old context will be deleted after notification than + //the old context will be deleted after notification then MutexGuard aGuard( m_aMutex); if( xChartModel.is()) m_spObjectHierarchy = diff --git a/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx b/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx index 407a8f9098c1..302eff427040 100644 --- a/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx +++ b/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx @@ -39,7 +39,7 @@ AccessibleViewForwarder::~AccessibleViewForwarder() { } -// ________ IAccessibleViewforwarder ________ +// ________ IAccessibleViewForwarder ________ tools::Rectangle AccessibleViewForwarder::GetVisibleArea() const { diff --git a/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx b/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx index 020e8124818f..2888ee9b0672 100644 --- a/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx +++ b/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx @@ -78,6 +78,7 @@ enum eServiceType { SERVICE_NAME_AREA_DIAGRAM = 0, SERVICE_NAME_BAR_DIAGRAM, + SERVICE_NAME_HISTOGRAM_DIAGRAM, SERVICE_NAME_DONUT_DIAGRAM, SERVICE_NAME_LINE_DIAGRAM, SERVICE_NAME_NET_DIAGRAM, @@ -86,6 +87,7 @@ enum eServiceType SERVICE_NAME_STOCK_DIAGRAM, SERVICE_NAME_XY_DIAGRAM, SERVICE_NAME_BUBBLE_DIAGRAM, + SERVICE_NAME_CORRELATION_CIRCLE_DIAGRAM, SERVICE_NAME_DASH_TABLE, SERVICE_NAME_GRADIENT_TABLE, @@ -106,6 +108,7 @@ tServiceNameMap & lcl_getStaticServiceNameMap() static tServiceNameMap aServiceNameMap { {"com.sun.star.chart.AreaDiagram", SERVICE_NAME_AREA_DIAGRAM}, {"com.sun.star.chart.BarDiagram", SERVICE_NAME_BAR_DIAGRAM}, + {"com.sun.star.chart.HistogramDiagram", SERVICE_NAME_HISTOGRAM_DIAGRAM}, {"com.sun.star.chart.DonutDiagram", SERVICE_NAME_DONUT_DIAGRAM}, {"com.sun.star.chart.LineDiagram", SERVICE_NAME_LINE_DIAGRAM}, {"com.sun.star.chart.NetDiagram", SERVICE_NAME_NET_DIAGRAM}, @@ -114,6 +117,7 @@ tServiceNameMap & lcl_getStaticServiceNameMap() {"com.sun.star.chart.StockDiagram", SERVICE_NAME_STOCK_DIAGRAM}, {"com.sun.star.chart.XYDiagram", SERVICE_NAME_XY_DIAGRAM}, {"com.sun.star.chart.BubbleDiagram", SERVICE_NAME_BUBBLE_DIAGRAM}, + {"com.sun.star.chart.CorrelationCircleDiagram", SERVICE_NAME_CORRELATION_CIRCLE_DIAGRAM}, {"com.sun.star.drawing.DashTable", SERVICE_NAME_DASH_TABLE}, {"com.sun.star.drawing.GradientTable", SERVICE_NAME_GRADIENT_TABLE}, @@ -143,7 +147,8 @@ enum PROP_DOCUMENT_UPDATE_ADDIN, PROP_DOCUMENT_NULL_DATE, PROP_DOCUMENT_ENABLE_COMPLEX_CHARTTYPES, - PROP_DOCUMENT_ENABLE_DATATABLE_DIALOG + PROP_DOCUMENT_ENABLE_DATATABLE_DIALOG, + PROP_DOCUMENT_DISABLE_DATATABLE_DIALOG }; void lcl_AddPropertiesToVector( @@ -216,6 +221,10 @@ void lcl_AddPropertiesToVector( cppu::UnoType::get(), //#i112666# no PropertyChangeEvent is fired on change so far beans::PropertyAttribute::MAYBEDEFAULT ); + rOutProperties.emplace_back( "DisableDataTableDialog", + PROP_DOCUMENT_DISABLE_DATATABLE_DIALOG, + cppu::UnoType::get(), + beans::PropertyAttribute::MAYBEDEFAULT ); } const Sequence< Property > & StaticChartDocumentWrapperPropertyArray() @@ -969,7 +978,7 @@ void ChartDocumentWrapper::impl_resetAddIn() try { - //make sure that the add-in does not hold a references to us anymore: + //make sure that the add-in does not hold a reference to us anymore: Reference< lang::XComponent > xComp( xAddIn, uno::UNO_QUERY ); if( xComp.is()) xComp->dispose(); @@ -1151,6 +1160,13 @@ uno::Reference< uno::XInterface > SAL_CALL ChartDocumentWrapper::createInstance( bCreateDiagram = true; } break; + case SERVICE_NAME_HISTOGRAM_DIAGRAM: + if (xChartTypeManager.is()) + { + xTemplate = xChartTypeManager->createTemplate(u"com.sun.star.chart2.template.Histogram"_ustr); + bCreateDiagram = true; + } + break; case SERVICE_NAME_DONUT_DIAGRAM: if( xChartTypeManager.is()) { @@ -1216,6 +1232,14 @@ uno::Reference< uno::XInterface > SAL_CALL ChartDocumentWrapper::createInstance( bCreateDiagram = true; } break; + case SERVICE_NAME_CORRELATION_CIRCLE_DIAGRAM: + if( xChartTypeManager.is()) + { + xTemplate = xChartTypeManager->createTemplate( + u"com.sun.star.chart2.template.CorrelationCircle"_ustr); + bCreateDiagram = true; + } + break; case SERVICE_NAME_DASH_TABLE: case SERVICE_NAME_GRADIENT_TABLE: @@ -1470,6 +1494,7 @@ std::vector< std::unique_ptr > ChartDocumentWrapper::createWrap aWrappedProperties.emplace_back( new WrappedNullDateProperty( m_spChart2ModelContact ) ); aWrappedProperties.emplace_back( new WrappedIgnoreProperty(u"EnableComplexChartTypes"_ustr, uno::Any(true) ) ); aWrappedProperties.emplace_back( new WrappedIgnoreProperty(u"EnableDataTableDialog"_ustr, uno::Any(true) ) ); + aWrappedProperties.emplace_back( new WrappedIgnoreProperty(u"DisableDataTableDialog"_ustr, uno::Any(false) ) ); return aWrappedProperties; } diff --git a/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx b/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx index 255727bfafb6..2e3eab91f693 100644 --- a/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx +++ b/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx @@ -70,6 +70,10 @@ #include #include +#include +#include +#include + using namespace ::com::sun::star; using namespace ::chart::wrapper; using namespace ::chart::DataSeriesProperties; @@ -141,7 +145,17 @@ enum PROP_DIAGRAM_AUTOMATIC_SIZE, PROP_DIAGRAM_EXTERNALDATA, - PROP_DIAGRAM_STYLE_INDEX + PROP_DIAGRAM_STYLE_INDEX, + + // Histogram chart type properties. + // Exposed here so the ODF/OOXML exporters can pick them up via the chart property map + PROP_DIAGRAM_BIN_WIDTH, + PROP_DIAGRAM_BIN_COUNT, + PROP_DIAGRAM_FREQUENCY_TYPE, + PROP_DIAGRAM_USE_UNDERFLOW_BIN, + PROP_DIAGRAM_UNDERFLOW_BIN_VALUE, + PROP_DIAGRAM_USE_OVERFLOW_BIN, + PROP_DIAGRAM_OVERFLOW_BIN_VALUE }; void lcl_AddPropertiesToVector( @@ -218,6 +232,36 @@ void lcl_AddPropertiesToVector( beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT ); + // Histogram chart type properties + rOutProperties.emplace_back("BinWidth", + PROP_DIAGRAM_BIN_WIDTH, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + rOutProperties.emplace_back("BinCount", + PROP_DIAGRAM_BIN_COUNT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + rOutProperties.emplace_back("FrequencyType", + PROP_DIAGRAM_FREQUENCY_TYPE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + rOutProperties.emplace_back("UseUnderflowBin", + PROP_DIAGRAM_USE_UNDERFLOW_BIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + rOutProperties.emplace_back("UnderflowBinValue", + PROP_DIAGRAM_UNDERFLOW_BIN_VALUE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + rOutProperties.emplace_back("UseOverflowBin", + PROP_DIAGRAM_USE_OVERFLOW_BIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + rOutProperties.emplace_back("OverflowBinValue", + PROP_DIAGRAM_OVERFLOW_BIN_VALUE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + //new for XY charts rOutProperties.emplace_back( CHART_UNONAME_SORT_BY_XVALUES, PROP_DIAGRAM_SORT_BY_X_VALUES, @@ -526,6 +570,9 @@ OUString lcl_getDiagramType( std::u16string_view rTemplateServiceName ) if( aName.find( u"Bubble" ) != std::u16string_view::npos ) return u"com.sun.star.chart.BubbleDiagram"_ustr; + if( aName.find( u"CorrelationCircle" ) != std::u16string_view::npos ) + return u"com.sun.star.chart.CorrelationCircleDiagram"_ustr; + // Note: this must be checked after Bar, Net and Scatter // "Symbol" "StackedSymbol" "PercentStackedSymbol" "Line" "StackedLine" @@ -535,38 +582,43 @@ OUString lcl_getDiagramType( std::u16string_view rTemplateServiceName ) if( aName.find( u"Line" ) != std::u16string_view::npos || aName.find( u"Symbol" ) != std::u16string_view::npos ) return u"com.sun.star.chart.LineDiagram"_ustr; + if (aName.find(u"Histogram") != std::u16string_view::npos) + return u"com.sun.star.chart.HistogramDiagram"_ustr; + OSL_FAIL( "unknown template" ); } return OUString(); } -typedef std::map< OUString, OUString > tMakeStringStringMap; - -const tMakeStringStringMap& lcl_getChartTypeNameMap() -{ - static tMakeStringStringMap g_aChartTypeNameMap{ - {"com.sun.star.chart2.LineChartType", "com.sun.star.chart.LineDiagram"}, - {"com.sun.star.chart2.AreaChartType", "com.sun.star.chart.AreaDiagram"}, - {"com.sun.star.chart2.ColumnChartType", "com.sun.star.chart.BarDiagram"}, - {"com.sun.star.chart2.PieChartType", "com.sun.star.chart.PieDiagram"}, - {"com.sun.star.chart2.DonutChartType", "com.sun.star.chart.DonutDiagram"}, - {"com.sun.star.chart2.ScatterChartType", "com.sun.star.chart.XYDiagram"}, - {"com.sun.star.chart2.FilledNetChartType", "com.sun.star.chart.FilledNetDiagram"}, - {"com.sun.star.chart2.NetChartType", "com.sun.star.chart.NetDiagram"}, - {"com.sun.star.chart2.CandleStickChartType", "com.sun.star.chart.StockDiagram"}, - {"com.sun.star.chart2.BubbleChartType", "com.sun.star.chart.BubbleDiagram"} - }; - return g_aChartTypeNameMap; -} - OUString lcl_getOldChartTypeName( const OUString & rNewChartTypeName ) { OUString aOld(rNewChartTypeName); - - const tMakeStringStringMap& rMap = lcl_getChartTypeNameMap(); - tMakeStringStringMap::const_iterator aIt( rMap.find( rNewChartTypeName )); - if( aIt != rMap.end()) +#ifdef _MSC_VER + static const auto aChartNameMap = frozen::make_unordered_map({ +#else + static constexpr auto aChartNameMap = frozen::make_unordered_map({ +#endif + {u"com.sun.star.chart2.LineChartType", u"com.sun.star.chart.LineDiagram"_ustr}, + {u"com.sun.star.chart2.AreaChartType", u"com.sun.star.chart.AreaDiagram"_ustr}, + {u"com.sun.star.chart2.ColumnChartType", u"com.sun.star.chart.BarDiagram"_ustr}, + {u"com.sun.star.chart2.HistogramChartType", u"com.sun.star.chart.HistogramDiagram"_ustr}, + {u"com.sun.star.chart2.PieChartType", u"com.sun.star.chart.PieDiagram"_ustr}, + {u"com.sun.star.chart2.DonutChartType", u"com.sun.star.chart.DonutDiagram"_ustr}, + {u"com.sun.star.chart2.ScatterChartType", u"com.sun.star.chart.XYDiagram"_ustr}, + {u"com.sun.star.chart2.FilledNetChartType", u"com.sun.star.chart.FilledNetDiagram"_ustr}, + {u"com.sun.star.chart2.NetChartType", u"com.sun.star.chart.NetDiagram"_ustr}, + {u"com.sun.star.chart2.CandleStickChartType", u"com.sun.star.chart.StockDiagram"_ustr}, + {u"com.sun.star.chart2.BubbleChartType", u"com.sun.star.chart.BubbleDiagram"_ustr}, + {u"com.sun.star.chart2.CorrelationCircleChartType", u"com.sun.star.chart.CorrelationCircleDiagram"_ustr}, + {u"com.sun.star.chart2.FunnelChartType", u"com.sun.star.chart.FunnelDiagram"_ustr}, + {u"com.sun.star.chart2.BoxWhiskerChartType", u"com.sun.star.chart.BoxWhiskerDiagram"_ustr}, + {u"com.sun.star.chart2.ClusteredColumnChartType", u"com.sun.star.chart.ClusteredColumnDiagram"_ustr}, + {u"com.sun.star.chart2.SunburstChartType", u"com.sun.star.chart.SunburstDiagram"_ustr}, + {u"com.sun.star.chart2.TreemapChartType", u"com.sun.star.chart.TreemapDiagram"_ustr} + }); + auto aIt( aChartNameMap.find( rNewChartTypeName )); + if( aIt != aChartNameMap.end()) { aOld = aIt->second; } @@ -1501,7 +1553,7 @@ void WrappedNumberOfLinesProperty::setPropertyValue( const Any& rOuterValue, con { sal_Int32 nNewValue; if( ! (rOuterValue >>= nNewValue) ) - throw lang::IllegalArgumentException( u"property NumberOfLines requires sal_Int32 value"_ustr, nullptr, 0 ); + throw lang::IllegalArgumentException( u"Property NumberOfLines requires sal_Int32 value"_ustr, nullptr, 0 ); m_aOuterValue = rOuterValue; @@ -1842,6 +1894,56 @@ Any WrappedIncludeHiddenCellsProperty::getPropertyValue( const Reference< beans: return uno::Any(bValue); } +namespace +{ +class WrappedHistogramProperty final : public WrappedProperty +{ +public: + WrappedHistogramProperty(const OUString& rPropertyName, + uno::Any aDefaultValue, + std::shared_ptr spChart2ModelContact) + : WrappedProperty(rPropertyName, OUString()) + , m_aDefaultValue(std::move(aDefaultValue)) + , m_spChart2ModelContact(std::move(spChart2ModelContact)) + { + } + + void setPropertyValue(const uno::Any& rOuterValue, + const Reference& /*xInnerPropertySet*/) const override + { + rtl::Reference<::chart::ChartType> xHistogramType = lcl_getHistogramChartType(); + if (xHistogramType.is()) + xHistogramType->setPropertyValue(getOuterName(), rOuterValue); + } + + Any getPropertyValue(const Reference& /*xInnerPropertySet*/) const override + { + rtl::Reference<::chart::ChartType> xHistogramType = lcl_getHistogramChartType(); + if (xHistogramType.is()) + return xHistogramType->getPropertyValue(getOuterName()); + return m_aDefaultValue; + } + +private: + rtl::Reference<::chart::ChartType> lcl_getHistogramChartType() const + { + rtl::Reference<::chart::Diagram> xDiagram(m_spChart2ModelContact->getDiagram()); + if (!xDiagram.is()) + return nullptr; + for (const rtl::Reference<::chart::ChartType>& xType : xDiagram->getChartTypes()) + { + if (xType.is() && xType->getChartType() == "com.sun.star.chart2.HistogramChartType") + return xType; + } + return nullptr; + } + + uno::Any m_aDefaultValue; + std::shared_ptr m_spChart2ModelContact; +}; + +} + // ____ XDiagramProvider ____ Reference< chart2::XDiagram > SAL_CALL DiagramWrapper::getDiagram() { @@ -1900,6 +2002,21 @@ std::vector< std::unique_ptr > DiagramWrapper::createWrappedPro aWrappedProperties.emplace_back( new WrappedAutomaticSizeProperty() ); aWrappedProperties.emplace_back( new WrappedIncludeHiddenCellsProperty( m_spChart2ModelContact ) ); + aWrappedProperties.emplace_back(new WrappedHistogramProperty( + u"BinWidth"_ustr, uno::Any(0.0), m_spChart2ModelContact)); + aWrappedProperties.emplace_back(new WrappedHistogramProperty( + u"BinCount"_ustr, uno::Any(sal_Int32(0)), m_spChart2ModelContact)); + aWrappedProperties.emplace_back(new WrappedHistogramProperty( + u"FrequencyType"_ustr, uno::Any(sal_Int32(0)), m_spChart2ModelContact)); + aWrappedProperties.emplace_back(new WrappedHistogramProperty( + u"UseUnderflowBin"_ustr, uno::Any(false), m_spChart2ModelContact)); + aWrappedProperties.emplace_back(new WrappedHistogramProperty( + u"UnderflowBinValue"_ustr, uno::Any(0.0), m_spChart2ModelContact)); + aWrappedProperties.emplace_back(new WrappedHistogramProperty( + u"UseOverflowBin"_ustr, uno::Any(false), m_spChart2ModelContact)); + aWrappedProperties.emplace_back(new WrappedHistogramProperty( + u"OverflowBinValue"_ustr, uno::Any(0.0), m_spChart2ModelContact)); + return aWrappedProperties; } diff --git a/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx index 8c60b611adff..6b3972aa9fa3 100644 --- a/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx +++ b/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx @@ -276,7 +276,7 @@ Any WrappedSymbolTypeProperty::getPropertyValue( const Reference< beans::XProper beans::PropertyState WrappedSymbolTypeProperty::getPropertyState( const Reference< beans::XPropertyState >& xInnerPropertyState ) const { //the special situation for this property here is that the diagram default can be - //different from the normal default and different from all singles series values + //different from the normal default and different from all single series values //so we need to return PropertyState_DIRECT_VALUE for more cases if( m_ePropertyType == DATA_SERIES && //single series or point diff --git a/chart2/source/controller/dialogs/ChartTypeDialogController.cxx b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx index 85ebcd9e0ebc..22f063a3dc97 100644 --- a/chart2/source/controller/dialogs/ChartTypeDialogController.cxx +++ b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx @@ -259,7 +259,7 @@ rtl::Reference< ChartTypeTemplate > ChartTypeDialogController::getCurrentTemplat rtl::Reference< ChartTypeTemplate > xTemplate; OUString aServiceName( getServiceNameForParameter( rParameter ) ); - if(!aServiceName.isEmpty()) + if(!aServiceName.isEmpty() && xTemplateManager.is()) { xTemplate = xTemplateManager->createTemplate( aServiceName ); if(xTemplate.is()) @@ -555,6 +555,53 @@ void BarChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const Ch rSubTypeList.SetItemText( 4, SchResId( STR_DEEP ) ); } +//========= +// HistogramChartDialogController +//========= + +HistogramChartDialogController::HistogramChartDialogController() +{ + bSupports3D = false; +} + +HistogramChartDialogController::~HistogramChartDialogController() +{ +} + +OUString HistogramChartDialogController::getName() +{ + return SchResId(STR_TYPE_HISTOGRAM); +} + +OUString HistogramChartDialogController::getImage() +{ + return BMP_TYPE_HISTOGRAM; +} + +const tTemplateServiceChartTypeParameterMap& HistogramChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.Histogram" , ChartTypeParameter(1, false, false, GlobalStackMode_NONE)} + }; + return s_aTemplateMap; +} + +void HistogramChartDialogController::fillSubTypeList(ValueSet& rSubTypeList, + const ChartTypeParameter& /*rParameter*/) +{ + rSubTypeList.Clear(); + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_HISTOGRAM)); + rSubTypeList.SetItemText(1, SchResId(STR_HISTOGRAM)); +} + + +void HistogramChartDialogController::adjustParameterToSubType(ChartTypeParameter& rParameter) +{ + rParameter.b3DLook = false; + rParameter.eStackMode = GlobalStackMode_NONE; + rParameter.bXAxisWithValues = false; +} + //========= // PieChartDialogController //========= @@ -1384,6 +1431,56 @@ void CombiColumnLineChartDialogController::adjustParameterToSubType( ChartTypePa } } +//========= +// CorrelationCircleChartDialogController +//========= + +CorrelationCircleChartDialogController::CorrelationCircleChartDialogController() +{ + bSupports3D = false; +} + +CorrelationCircleChartDialogController::~CorrelationCircleChartDialogController() +{ +} + +OUString CorrelationCircleChartDialogController::getName() +{ + return SchResId(STR_TYPE_CORRELATION_CIRCLE); +} + +OUString CorrelationCircleChartDialogController::getImage() +{ + return BMP_TYPE_CORRELATION_CIRCLE; +} + +const tTemplateServiceChartTypeParameterMap& + CorrelationCircleChartDialogController::getTemplateMap() const +{ + static const tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.CorrelationCircle" , ChartTypeParameter(1,true)}}; + return s_aTemplateMap; +} + +void CorrelationCircleChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/ ) +{ + rSubTypeList.Clear(); + + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_CORRELATION_CIRCLE)); + rSubTypeList.SetItemText(1, SchResId(STR_CORRELATION_CIRCLE)); +} + +void CorrelationCircleChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + rParameter.b3DLook = false; + rParameter.eStackMode = GlobalStackMode_NONE; + rParameter.bXAxisWithValues = true; +} + +//========= +// BubbleChartDialogController +//========= + BubbleChartDialogController::BubbleChartDialogController() { } diff --git a/chart2/source/controller/dialogs/DataBrowser.cxx b/chart2/source/controller/dialogs/DataBrowser.cxx index 454bc33c1d80..cc624a3a2407 100644 --- a/chart2/source/controller/dialogs/DataBrowser.cxx +++ b/chart2/source/controller/dialogs/DataBrowser.cxx @@ -36,8 +36,8 @@ #include #include +#include #include -#include #include #include #include @@ -109,7 +109,7 @@ public: void SetGetFocusHdl(const Link& rLink) { m_aFocusInHdl = rLink; } private: - DECL_LINK(NameEdited, weld::Entry&, void); + DECL_LINK(NameEdited, weld::TextWidget&, void); DECL_LINK(NameFocusIn, weld::Widget&, void); DECL_LINK(MousePressHdl, const MouseEvent&, bool); @@ -133,7 +133,7 @@ SeriesHeaderEdit::SeriesHeaderEdit(std::unique_ptr xControl, sal_In m_xControl->set_buildable_name(m_xControl->get_buildable_name() + OUString::number(nHeader)); } -IMPL_LINK_NOARG(SeriesHeaderEdit, NameEdited, weld::Entry&, void) +IMPL_LINK_NOARG(SeriesHeaderEdit, NameEdited, weld::TextWidget&, void) { m_aModifyHdl.Call(*this); } @@ -427,6 +427,10 @@ OUString SeriesHeader::GetChartTypeImage( { aResult = BMP_TYPE_BUBBLE; } + else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE ) + { + aResult = BMP_TYPE_CORRELATION_CIRCLE; + } return aResult; } diff --git a/chart2/source/controller/dialogs/DataBrowser.hxx b/chart2/source/controller/dialogs/DataBrowser.hxx index 7ee912f1877f..47f1e2dae5af 100644 --- a/chart2/source/controller/dialogs/DataBrowser.hxx +++ b/chart2/source/controller/dialogs/DataBrowser.hxx @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include #include diff --git a/chart2/source/controller/dialogs/DialogModel.cxx b/chart2/source/controller/dialogs/DialogModel.cxx index 74468cc422a6..aeca8d51b851 100644 --- a/chart2/source/controller/dialogs/DialogModel.cxx +++ b/chart2/source/controller/dialogs/DialogModel.cxx @@ -79,6 +79,7 @@ OUString lcl_ConvertRole( const OUString & rRoleString ) { "values-x", ::chart::SchResId( STR_DATA_ROLE_X ) }, { "values-y", ::chart::SchResId( STR_DATA_ROLE_Y ) }, { "values-size", ::chart::SchResId( STR_DATA_ROLE_SIZE ) }, + { "values-feature", ::chart::SchResId( STR_DATA_ROLE_FEATURE ) }, { "FillColor", ::chart::SchResId( STR_PROPERTY_ROLE_FILLCOLOR ) }, { "BorderColor", ::chart::SchResId( STR_PROPERTY_ROLE_BORDERCOLOR ) }, }; @@ -113,6 +114,7 @@ lcl_tRoleIndexMap lcl_createRoleIndexMap() aMap[ u"values-max"_ustr ] = ++nIndex; aMap[ u"values-last"_ustr ] = ++nIndex; aMap[ u"values-size"_ustr ] = ++nIndex; + aMap[ u"values-feature"_ustr ] = ++nIndex; return aMap; } diff --git a/chart2/source/controller/dialogs/ObjectNameProvider.cxx b/chart2/source/controller/dialogs/ObjectNameProvider.cxx index ef9893ca7ddb..31feddf647e6 100644 --- a/chart2/source/controller/dialogs/ObjectNameProvider.cxx +++ b/chart2/source/controller/dialogs/ObjectNameProvider.cxx @@ -190,6 +190,33 @@ OUString lcl_getDataPointValueText( const rtl::Reference< DataSeries >& xSeries, } } + if (xSeries.is()) + { + uno::Reference xCalculatedSeq = xSeries->getCalculatedYSequence(); + if (xCalculatedSeq.is() && xCalculatedSeq->getValues().is()) + { + try + { + uno::Sequence aCalcData = xCalculatedSeq->getValues()->getData(); + if (nPointIndex >= 0 && nPointIndex < aCalcData.getLength()) + { + double fCalculatedValue = 0.0; + if (aCalcData[nPointIndex] >>= fCalculatedValue) + { + sal_Int32 nNumberFormatKey + = xCalculatedSeq->getValues()->getNumberFormatKeyByIndex(nPointIndex); + aY = aNumberFormatterWrapper.getFormattedString( + nNumberFormatKey, fCalculatedValue, nLabelColor, bColorChanged); + } + } + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } + } + } + if( aX.isEmpty() ) { ChartModel& rModel = dynamic_cast(*xChartModel); diff --git a/chart2/source/controller/dialogs/RangeSelectionListener.cxx b/chart2/source/controller/dialogs/RangeSelectionListener.cxx index fc61dbcef101..a852a18c9318 100644 --- a/chart2/source/controller/dialogs/RangeSelectionListener.cxx +++ b/chart2/source/controller/dialogs/RangeSelectionListener.cxx @@ -22,7 +22,7 @@ #include #include #include -#include + #include using namespace ::com::sun::star; @@ -71,8 +71,12 @@ void RangeSelectionListenerParent::enableRangeChoosing(bool bEnable, weld::Dialo weld::Assistant* pAss = dynamic_cast(pDlg); if (pAss && bEnable) m_sRestorePageIdent = pAss->get_current_page_ident(); + if (bEnable) + pDlg->hide(); + // set modality while the dialog is hidden pDlg->set_modal(!bEnable); - pDlg->set_visible(!bEnable); + if (!bEnable) + pDlg->show(); if (pAss && !bEnable) pAss->set_current_page(m_sRestorePageIdent); } diff --git a/chart2/source/controller/dialogs/TitleDialogData.cxx b/chart2/source/controller/dialogs/TitleDialogData.cxx index 75d59bbb43b4..8afe7dc46613 100644 --- a/chart2/source/controller/dialogs/TitleDialogData.cxx +++ b/chart2/source/controller/dialogs/TitleDialogData.cxx @@ -53,7 +53,7 @@ void TitleDialogData::readFromModel( const rtl::Reference<::chart::ChartModel>& sal_Bool* pExistenceList = aExistenceList.getArray(); auto pTextList = aTextList.getArray(); - //find out which title exists and get their text + //find out which title exists and get its text //main title: for( auto nTitleIndex = +TitleHelper::TITLE_BEGIN; nTitleIndex < +TitleHelper::NORMAL_TITLE_END; diff --git a/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx b/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx index 801a64e6c5fa..9e09f42c4302 100644 --- a/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx +++ b/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx b/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx index d7fc58fc04e5..bb9d8799ec9d 100644 --- a/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx +++ b/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx @@ -49,7 +49,7 @@ SchAxisDlg::SchAxisDlg(weld::Window* pWindow, { if (bAxisDlg) { - //todo: remove if secondary z axis are possible somewhere + //todo: remove if secondary z axis is possible somewhere m_xCbSecondaryZ->hide(); } diff --git a/chart2/source/controller/dialogs/dlg_NumberFormat.hxx b/chart2/source/controller/dialogs/dlg_NumberFormat.hxx index 2bb84696ac57..8a067503a972 100644 --- a/chart2/source/controller/dialogs/dlg_NumberFormat.hxx +++ b/chart2/source/controller/dialogs/dlg_NumberFormat.hxx @@ -19,6 +19,7 @@ #pragma once #include +#include class SfxItemSet; class SfxItemPool; diff --git a/chart2/source/controller/dialogs/res_DataLabel.hxx b/chart2/source/controller/dialogs/res_DataLabel.hxx index 49324fdd7274..c5be5442ac32 100644 --- a/chart2/source/controller/dialogs/res_DataLabel.hxx +++ b/chart2/source/controller/dialogs/res_DataLabel.hxx @@ -21,8 +21,12 @@ #include #include #include +#include +#include #include +#include #include +#include #include #include diff --git a/chart2/source/controller/dialogs/res_DataTableProperties.cxx b/chart2/source/controller/dialogs/res_DataTableProperties.cxx index 493be52ea5bc..781979acfac3 100644 --- a/chart2/source/controller/dialogs/res_DataTableProperties.cxx +++ b/chart2/source/controller/dialogs/res_DataTableProperties.cxx @@ -46,7 +46,7 @@ void DataTablePropertiesResources::initFromItemSet(const SfxItemSet& rInAttrs) { if (aState == SfxItemState::SET) m_xCbHorizontalBorder->set_active( - static_cast(pPoolItem)->GetValue()); + pPoolItem->StaticWhichCast(SCHATTR_DATA_TABLE_HORIZONTAL_BORDER).GetValue()); } aState = rInAttrs.GetItemState(SCHATTR_DATA_TABLE_VERTICAL_BORDER, false, &pPoolItem); @@ -57,7 +57,8 @@ void DataTablePropertiesResources::initFromItemSet(const SfxItemSet& rInAttrs) else { if (aState == SfxItemState::SET) - m_xCbVerticalBorder->set_active(static_cast(pPoolItem)->GetValue()); + m_xCbVerticalBorder->set_active( + pPoolItem->StaticWhichCast(SCHATTR_DATA_TABLE_VERTICAL_BORDER).GetValue()); } aState = rInAttrs.GetItemState(SCHATTR_DATA_TABLE_OUTLINE, false, &pPoolItem); @@ -68,7 +69,8 @@ void DataTablePropertiesResources::initFromItemSet(const SfxItemSet& rInAttrs) else { if (aState == SfxItemState::SET) - m_xCbOutilne->set_active(static_cast(pPoolItem)->GetValue()); + m_xCbOutilne->set_active( + pPoolItem->StaticWhichCast(SCHATTR_DATA_TABLE_OUTLINE).GetValue()); } aState = rInAttrs.GetItemState(SCHATTR_DATA_TABLE_KEYS, false, &pPoolItem); @@ -79,7 +81,7 @@ void DataTablePropertiesResources::initFromItemSet(const SfxItemSet& rInAttrs) else { if (aState == SfxItemState::SET) - m_xCbKeys->set_active(static_cast(pPoolItem)->GetValue()); + m_xCbKeys->set_active(pPoolItem->StaticWhichCast(SCHATTR_DATA_TABLE_KEYS).GetValue()); } } diff --git a/chart2/source/controller/dialogs/res_ErrorBar.cxx b/chart2/source/controller/dialogs/res_ErrorBar.cxx index 749ef1eebc14..bff00279ba28 100644 --- a/chart2/source/controller/dialogs/res_ErrorBar.cxx +++ b/chart2/source/controller/dialogs/res_ErrorBar.cxx @@ -23,9 +23,15 @@ #include #include #include +#include +#include #include +#include +#include +#include #include -#include +#include + #include #include @@ -449,7 +455,7 @@ IMPL_LINK(ErrorBarResources, ChooseRange, weld::Button&, rButton, void) aUIString, *this ); } -IMPL_LINK( ErrorBarResources, RangeChanged, weld::Entry&, rEdit, void ) +IMPL_LINK(ErrorBarResources, RangeChanged, weld::TextWidget&, rEdit, void) { if( &rEdit == m_xEdRangePositive.get() ) { @@ -461,7 +467,7 @@ IMPL_LINK( ErrorBarResources, RangeChanged, weld::Entry&, rEdit, void ) m_bRangeNegUnique = true; } - isRangeFieldContentValid( rEdit ); + isRangeFieldContentValid(dynamic_cast(rEdit)); } void ErrorBarResources::Reset(const SfxItemSet& rInAttrs) @@ -474,7 +480,7 @@ void ErrorBarResources::Reset(const SfxItemSet& rInAttrs) m_bErrorKindUnique = ( aState != SfxItemState::INVALID ); if( aState == SfxItemState::SET ) - m_eErrorKind = static_cast(pPoolItem)->GetValue(); + m_eErrorKind = pPoolItem->StaticWhichCast(SCHATTR_STAT_KIND_ERROR).GetValue(); m_xLbFunction->set_active( lcl_getLbEntryPosByErrorKind( m_eErrorKind )); @@ -529,7 +535,7 @@ void ErrorBarResources::Reset(const SfxItemSet& rInAttrs) aState = rInAttrs.GetItemState( SCHATTR_STAT_INDICATE, true, &pPoolItem ); m_bIndicatorUnique = ( aState != SfxItemState::INVALID ); if( aState == SfxItemState::SET) - m_eIndicate = static_cast(pPoolItem)->GetValue(); + m_eIndicate = pPoolItem->StaticWhichCast(SCHATTR_STAT_INDICATE).GetValue(); if( m_bIndicatorUnique ) { @@ -559,7 +565,7 @@ void ErrorBarResources::Reset(const SfxItemSet& rInAttrs) m_bRangePosUnique = ( aState != SfxItemState::INVALID ); if( aState == SfxItemState::SET ) { - OUString sRangePositive = static_cast< const SfxStringItem * >( pPoolItem )->GetValue(); + OUString sRangePositive = pPoolItem->StaticWhichCast(SCHATTR_STAT_RANGE_POS).GetValue(); m_xEdRangePositive->set_text( sRangePositive ); } @@ -567,7 +573,7 @@ void ErrorBarResources::Reset(const SfxItemSet& rInAttrs) m_bRangeNegUnique = ( aState != SfxItemState::INVALID ); if( aState == SfxItemState::SET ) { - OUString sRangeNegative = static_cast< const SfxStringItem * >( pPoolItem )->GetValue(); + OUString sRangeNegative = pPoolItem->StaticWhichCast(SCHATTR_STAT_RANGE_NEG).GetValue(); m_xEdRangeNegative->set_text( sRangeNegative ); if( m_eErrorKind == SvxChartKindError::Range && !sRangeNegative.isEmpty() && diff --git a/chart2/source/controller/dialogs/res_LegendPosition.cxx b/chart2/source/controller/dialogs/res_LegendPosition.cxx index 3f1237135054..ce6f72eb17ad 100644 --- a/chart2/source/controller/dialogs/res_LegendPosition.cxx +++ b/chart2/source/controller/dialogs/res_LegendPosition.cxx @@ -33,7 +33,8 @@ #include #include #include -#include +#include +#include namespace chart { diff --git a/chart2/source/controller/dialogs/res_Titles.cxx b/chart2/source/controller/dialogs/res_Titles.cxx index e7be6f53e773..3e4ab0dd2719 100644 --- a/chart2/source/controller/dialogs/res_Titles.cxx +++ b/chart2/source/controller/dialogs/res_Titles.cxx @@ -21,7 +21,7 @@ #include #include #include -#include +#include namespace chart { @@ -49,7 +49,7 @@ TitleResources::TitleResources(weld::Builder& rBuilder, bool bShowSecondaryAxesT TitleResources::~TitleResources() {} -void TitleResources::connect_changed(const Link& rLink) +void TitleResources::connect_changed(const Link& rLink) { m_xEd_Main->connect_changed(rLink); m_xEd_Sub->connect_changed(rLink); diff --git a/chart2/source/controller/dialogs/res_Trendline.cxx b/chart2/source/controller/dialogs/res_Trendline.cxx index bf9f18dbfdf7..7e15d2550238 100644 --- a/chart2/source/controller/dialogs/res_Trendline.cxx +++ b/chart2/source/controller/dialogs/res_Trendline.cxx @@ -28,9 +28,11 @@ #include #include #include +#include #include #include -#include +#include +#include using namespace css::chart2; @@ -222,7 +224,7 @@ void TrendlineResources::Reset( const SfxItemSet& rInAttrs ) else { if( aState == SfxItemState::SET ) - m_xCB_SetIntercept->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue()); + m_xCB_SetIntercept->set_active(pPoolItem->StaticWhichCast(SCHATTR_REGRESSION_SET_INTERCEPT).GetValue()); } aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SHOW_EQUATION, true, &pPoolItem ); @@ -233,7 +235,7 @@ void TrendlineResources::Reset( const SfxItemSet& rInAttrs ) else { if( aState == SfxItemState::SET ) - m_xCB_ShowEquation->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue()); + m_xCB_ShowEquation->set_active(pPoolItem->StaticWhichCast(SCHATTR_REGRESSION_SHOW_EQUATION).GetValue()); } aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SHOW_COEFF, true, &pPoolItem ); @@ -244,7 +246,7 @@ void TrendlineResources::Reset( const SfxItemSet& rInAttrs ) else { if( aState == SfxItemState::SET ) - m_xCB_ShowCorrelationCoeff->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue()); + m_xCB_ShowCorrelationCoeff->set_active(pPoolItem->StaticWhichCast(SCHATTR_REGRESSION_SHOW_COEFF).GetValue()); } if( const SfxInt32Item* pMovingTypeItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_MOVING_TYPE ) ) diff --git a/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx index 4d8f10fdf51f..7ecdcc441cbe 100644 --- a/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx +++ b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx @@ -19,8 +19,9 @@ #pragma once #include +#include #include -#include +#include namespace chart { class ControllerLockHelper; } diff --git a/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx index 5aa4cecf50ef..dece16b9de40 100644 --- a/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx +++ b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx @@ -20,8 +20,10 @@ #include #include +#include +#include +#include #include -#include #include namespace chart { class ControllerLockHelper; } diff --git a/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx index bf1fe2767887..b7ce73f17bbb 100644 --- a/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx +++ b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx @@ -21,7 +21,8 @@ #include #include #include -#include +#include +#include #include #include diff --git a/chart2/source/controller/dialogs/tp_AxisLabel.cxx b/chart2/source/controller/dialogs/tp_AxisLabel.cxx index 81daf1e936a4..0007145056c2 100644 --- a/chart2/source/controller/dialogs/tp_AxisLabel.cxx +++ b/chart2/source/controller/dialogs/tp_AxisLabel.cxx @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include namespace chart { @@ -144,7 +147,7 @@ void SchAxisLabelTabPage::Reset( const SfxItemSet* rInAttrs ) { bool bCheck = false; if( aState == SfxItemState::SET ) - bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + bCheck = pPoolItem->StaticWhichCast(SCHATTR_AXIS_SHOWDESCR).GetValue(); m_xCbShowDescription->set_active( bCheck ); if( aState != SfxItemState::DEFAULT && aState != SfxItemState::SET ) @@ -157,7 +160,7 @@ void SchAxisLabelTabPage::Reset( const SfxItemSet* rInAttrs ) m_nInitialDegrees = 0_deg100; aState = rInAttrs->GetItemState( SCHATTR_TEXT_DEGREES, false, &pPoolItem ); if( aState == SfxItemState::SET ) - m_nInitialDegrees = static_cast< const SdrAngleItem * >( pPoolItem )->GetValue(); + m_nInitialDegrees = pPoolItem->StaticWhichCast(SCHATTR_TEXT_DEGREES).GetValue(); m_bHasInitialDegrees = aState != SfxItemState::INVALID; if( m_bHasInitialDegrees ) @@ -169,7 +172,7 @@ void SchAxisLabelTabPage::Reset( const SfxItemSet* rInAttrs ) m_bInitialStacking = false; aState = rInAttrs->GetItemState( SCHATTR_TEXT_STACKED, false, &pPoolItem ); if( aState == SfxItemState::SET ) - m_bInitialStacking = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_bInitialStacking = pPoolItem->StaticWhichCast(SCHATTR_TEXT_STACKED).GetValue(); m_bHasInitialStacking = aState != SfxItemState::INVALID; if( m_bHasInitialDegrees ) @@ -191,7 +194,7 @@ void SchAxisLabelTabPage::Reset( const SfxItemSet* rInAttrs ) { bool bCheck = false; if( aState == SfxItemState::SET ) - bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + bCheck = pPoolItem->StaticWhichCast(SCHATTR_AXIS_LABEL_OVERLAP).GetValue(); m_xCbTextOverlap->set_active( bCheck ); if( aState != SfxItemState::DEFAULT && aState != SfxItemState::SET ) @@ -208,7 +211,7 @@ void SchAxisLabelTabPage::Reset( const SfxItemSet* rInAttrs ) { bool bCheck = false; if( aState == SfxItemState::SET ) - bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + bCheck = pPoolItem->StaticWhichCast(SCHATTR_AXIS_LABEL_BREAK).GetValue(); m_xCbTextBreak->set_active( bCheck ); if( aState != SfxItemState::DEFAULT && aState != SfxItemState::SET ) diff --git a/chart2/source/controller/dialogs/tp_AxisLabel.hxx b/chart2/source/controller/dialogs/tp_AxisLabel.hxx index 300a5644a10b..af2a317b619a 100644 --- a/chart2/source/controller/dialogs/tp_AxisLabel.hxx +++ b/chart2/source/controller/dialogs/tp_AxisLabel.hxx @@ -25,11 +25,13 @@ #include #include -namespace weld { - class CheckButton; - class CustomWeld; - class Label; - class RadioButton; +namespace weld +{ +class CheckButton; +class CustomWeld; +class Label; +class RadioButton; +class Toggleable; } namespace chart diff --git a/chart2/source/controller/dialogs/tp_AxisPositions.hxx b/chart2/source/controller/dialogs/tp_AxisPositions.hxx index c902bdda5374..14cf0bdfb096 100644 --- a/chart2/source/controller/dialogs/tp_AxisPositions.hxx +++ b/chart2/source/controller/dialogs/tp_AxisPositions.hxx @@ -19,8 +19,13 @@ #pragma once #include +#include #include #include +#include +#include + +#include class SvNumberFormatter; diff --git a/chart2/source/controller/dialogs/tp_ChartType.cxx b/chart2/source/controller/dialogs/tp_ChartType.cxx index 49ef2d996069..17229e5b0f36 100644 --- a/chart2/source/controller/dialogs/tp_ChartType.cxx +++ b/chart2/source/controller/dialogs/tp_ChartType.cxx @@ -33,9 +33,9 @@ #include #include #include -#include #include #include +#include namespace chart { @@ -101,6 +101,8 @@ ChartTypeTabPage::ChartTypeTabPage(weld::Container* pPage, weld::DialogControlle m_aChartTypeDialogControllerList.push_back(std::make_unique()); m_aChartTypeDialogControllerList.push_back(std::make_unique()); + if (officecfg::Office::Common::Misc::ExperimentalMode::get()) + m_aChartTypeDialogControllerList.push_back(std::make_unique()); m_aChartTypeDialogControllerList.push_back(std::make_unique()); m_aChartTypeDialogControllerList.push_back(std::make_unique()); m_aChartTypeDialogControllerList.push_back(std::make_unique()); @@ -110,6 +112,8 @@ ChartTypeTabPage::ChartTypeTabPage(weld::Container* pPage, weld::DialogControlle m_aChartTypeDialogControllerList.push_back(std::make_unique()); m_aChartTypeDialogControllerList.push_back( std::make_unique()); + m_aChartTypeDialogControllerList.push_back( + std::make_unique()); } m_aChartTypeDialogControllerList.push_back(std::make_unique()); if (bEnableComplexChartTypes) @@ -188,13 +192,17 @@ void ChartTypeTabPage::stateChanged() //detect the new ThreeDLookScheme rtl::Reference< Diagram > xDiagram = m_xChartModel->getFirstChartDiagram(); // tdf#124295 - select always a 3D scheme - if (ThreeDLookScheme aThreeDLookScheme = xDiagram->detectScheme(); - aThreeDLookScheme != ThreeDLookScheme::ThreeDLookScheme_Unknown) - aParameter.eThreeDLookScheme = aThreeDLookScheme; + if (xDiagram) + { + if (ThreeDLookScheme aThreeDLookScheme = xDiagram->detectScheme(); + aThreeDLookScheme != ThreeDLookScheme::ThreeDLookScheme_Unknown) + aParameter.eThreeDLookScheme = aThreeDLookScheme; + } try { - xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues; + if (xDiagram) + xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues; } catch ( const uno::Exception& ) { diff --git a/chart2/source/controller/dialogs/tp_DataPointOption.cxx b/chart2/source/controller/dialogs/tp_DataPointOption.cxx index 6febd4cf86d0..40a9fdec2cac 100644 --- a/chart2/source/controller/dialogs/tp_DataPointOption.cxx +++ b/chart2/source/controller/dialogs/tp_DataPointOption.cxx @@ -22,6 +22,7 @@ #include #include #include +#include namespace chart { diff --git a/chart2/source/controller/dialogs/tp_DataSource.cxx b/chart2/source/controller/dialogs/tp_DataSource.cxx index c51eb4d508cc..2206e89c7f1f 100644 --- a/chart2/source/controller/dialogs/tp_DataSource.cxx +++ b/chart2/source/controller/dialogs/tp_DataSource.cxx @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -660,10 +661,10 @@ IMPL_LINK_NOARG(DataSourceTabPage, DownButtonClickedHdl, weld::Button&, void) } } -IMPL_LINK(DataSourceTabPage, RangeModifiedHdl, weld::Entry&, rEdit, void) +IMPL_LINK(DataSourceTabPage, RangeModifiedHdl, weld::TextWidget&, rEdit, void) { // note: isValid sets the color of the edit field - if( isRangeFieldContentValid( rEdit )) + if (isRangeFieldContentValid(dynamic_cast(rEdit))) { setDirty(); updateModelFromControl( &rEdit ); @@ -722,7 +723,7 @@ void DataSourceTabPage::disposingRangeSelection() m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false ); } -bool DataSourceTabPage::updateModelFromControl(const weld::Entry* pField) +bool DataSourceTabPage::updateModelFromControl(const weld::TextWidget* pField) { if (!m_bIsDirty) return true; diff --git a/chart2/source/controller/dialogs/tp_DataSource.hxx b/chart2/source/controller/dialogs/tp_DataSource.hxx index e391cb674ffc..0ecb3dffd2bc 100644 --- a/chart2/source/controller/dialogs/tp_DataSource.hxx +++ b/chart2/source/controller/dialogs/tp_DataSource.hxx @@ -22,13 +22,20 @@ #include #include +#include #include #include +#include #include namespace chart { class TabPageNotifiable; } +namespace weld +{ +class TreeView; +} + namespace chart { class ChartTypeTemplateProvider; @@ -76,7 +83,7 @@ private: DECL_LINK( CategoriesRangeButtonClickedHdl, weld::Button&, void ); DECL_LINK( AddButtonClickedHdl, weld::Button&, void ); DECL_LINK( RemoveButtonClickedHdl, weld::Button&, void ); - DECL_LINK( RangeModifiedHdl, weld::Entry&, void ); + DECL_LINK(RangeModifiedHdl, weld::TextWidget&, void); DECL_LINK( UpButtonClickedHdl, weld::Button&, void ); DECL_LINK( DownButtonClickedHdl, weld::Button&, void ); @@ -95,7 +102,7 @@ private: if the text from the field is a valid format to the internal data was valid */ - bool updateModelFromControl(const weld::Entry* pField = nullptr); + bool updateModelFromControl(const weld::TextWidget* pField = nullptr); /** @return , if the edit field contains a valid range entry. If no XCellRangesAccess can be obtained, is returned. diff --git a/chart2/source/controller/dialogs/tp_LegendPosition.hxx b/chart2/source/controller/dialogs/tp_LegendPosition.hxx index 4534501b5209..aac9a62fcf8d 100644 --- a/chart2/source/controller/dialogs/tp_LegendPosition.hxx +++ b/chart2/source/controller/dialogs/tp_LegendPosition.hxx @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include diff --git a/chart2/source/controller/dialogs/tp_PolarOptions.cxx b/chart2/source/controller/dialogs/tp_PolarOptions.cxx index 6799bf7d7300..7084c7975fe4 100644 --- a/chart2/source/controller/dialogs/tp_PolarOptions.cxx +++ b/chart2/source/controller/dialogs/tp_PolarOptions.cxx @@ -25,6 +25,7 @@ #include #include #include +#include namespace chart { diff --git a/chart2/source/controller/dialogs/tp_PolarOptions.hxx b/chart2/source/controller/dialogs/tp_PolarOptions.hxx index 656879f3c896..b8d88ed27b8a 100644 --- a/chart2/source/controller/dialogs/tp_PolarOptions.hxx +++ b/chart2/source/controller/dialogs/tp_PolarOptions.hxx @@ -20,6 +20,7 @@ #include #include +#include #include namespace weld { diff --git a/chart2/source/controller/dialogs/tp_RangeChooser.cxx b/chart2/source/controller/dialogs/tp_RangeChooser.cxx index f7dc2ba6a303..aa322eb1bb26 100644 --- a/chart2/source/controller/dialogs/tp_RangeChooser.cxx +++ b/chart2/source/controller/dialogs/tp_RangeChooser.cxx @@ -19,6 +19,8 @@ #include "tp_RangeChooser.hxx" #include +#include +#include #include #include #include "DialogModel.hxx" @@ -63,6 +65,7 @@ RangeChooserTabPage::RangeChooserTabPage(weld::Container* pPage, weld::DialogCon , m_xFT_Caption(m_xBuilder->weld_label(u"FT_CAPTION_FOR_WIZARD"_ustr)) , m_xED_Range(m_xBuilder->weld_entry(u"ED_RANGE"_ustr)) , m_xIB_Range(m_xBuilder->weld_button(u"IB_RANGE"_ustr)) + , m_xFT_RangeNote(m_xBuilder->weld_label(u"FT_RANGE_NOTE"_ustr)) , m_xRB_Rows(m_xBuilder->weld_radio_button(u"RB_DATAROWS"_ustr)) , m_xRB_Columns(m_xBuilder->weld_radio_button(u"RB_DATACOLS"_ustr)) , m_xCB_FirstRowAsLabel(m_xBuilder->weld_check_button(u"CB_FIRST_ROW_ASLABELS"_ustr)) @@ -76,6 +79,7 @@ RangeChooserTabPage::RangeChooserTabPage(weld::Container* pPage, weld::DialogCon , m_xEd_TimeEnd(m_xBuilder->weld_entry(u"ED_TIME_BASED_END"_ustr)) { m_xFT_Caption->set_visible(!bHideDescription); + m_xFT_RangeNote->set_label(SchResId(STR_RANGE_NOTE_DIMENSIONS)); SetPageTitle(m_xFTTitle->get_label());// OH:remove later with dialog @@ -141,6 +145,11 @@ void RangeChooserTabPage::initControlsFromModel() m_xED_Range->set_text( m_aLastValidRangeString ); + // Only a chart type that reads the ends of its range differently needs the + // note under the entry. + m_xFT_RangeNote->set_visible( m_xCurrentChartTypeTemplate.is() + && m_xCurrentChartTypeTemplate->usesLastTwoColumnsAsDimensions() ); + m_xRB_Rows->set_active( !bUseColumns ); m_xRB_Columns->set_active( bUseColumns ); @@ -301,7 +310,7 @@ bool RangeChooserTabPage::isValid() return bIsValid; } -IMPL_LINK_NOARG(RangeChooserTabPage, ControlEditedHdl, weld::Entry&, void) +IMPL_LINK_NOARG(RangeChooserTabPage, ControlEditedHdl, weld::TextWidget&, void) { setDirty(); isValid(); @@ -317,7 +326,7 @@ IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedCheckBoxHdl, weld::Toggleable ControlChangedHdl(*m_xED_Range); } -IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedHdl, weld::Entry&, void) +IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedHdl, weld::TextWidget&, void) { setDirty(); if( isValid()) diff --git a/chart2/source/controller/dialogs/tp_RangeChooser.hxx b/chart2/source/controller/dialogs/tp_RangeChooser.hxx index 98b7983187c5..a877e4cdf3c3 100644 --- a/chart2/source/controller/dialogs/tp_RangeChooser.hxx +++ b/chart2/source/controller/dialogs/tp_RangeChooser.hxx @@ -21,7 +21,11 @@ #include +#include +#include #include +#include +#include #include namespace chart { class TabPageNotifiable; } @@ -63,10 +67,10 @@ private: void setDirty(); DECL_LINK( ChooseRangeHdl, weld::Button&, void ); - DECL_LINK( ControlChangedHdl, weld::Entry&, void ); + DECL_LINK(ControlChangedHdl, weld::TextWidget&, void); DECL_LINK( ControlChangedCheckBoxHdl, weld::Toggleable&, void ); DECL_LINK( ControlChangedRadioHdl, weld::Toggleable&, void ); - DECL_LINK( ControlEditedHdl, weld::Entry&, void ); + DECL_LINK(ControlEditedHdl, weld::TextWidget&, void); sal_Int32 m_nChangingControlCalls; bool m_bIsDirty; @@ -81,6 +85,7 @@ private: std::unique_ptr m_xFT_Caption; std::unique_ptr m_xED_Range; std::unique_ptr m_xIB_Range; + std::unique_ptr m_xFT_RangeNote; std::unique_ptr m_xRB_Rows; std::unique_ptr m_xRB_Columns; std::unique_ptr m_xCB_FirstRowAsLabel; diff --git a/chart2/source/controller/dialogs/tp_Scale.cxx b/chart2/source/controller/dialogs/tp_Scale.cxx index 72532c2e573a..12bd83094e32 100644 --- a/chart2/source/controller/dialogs/tp_Scale.cxx +++ b/chart2/source/controller/dialogs/tp_Scale.cxx @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -71,6 +70,7 @@ ScaleTabPage::ScaleTabPage(weld::Container* pPage, weld::DialogController* pCont , m_bAllowDateAxis(false) , pNumFormatter(nullptr) , m_bShowAxisOrigin(false) + , m_bShowHistogramBinning(false) , m_xCbxReverse(m_xBuilder->weld_check_button(u"CBX_REVERSE"_ustr)) , m_xCbxLogarithm(m_xBuilder->weld_check_button(u"CBX_LOGARITHM"_ustr)) , m_xBxType(m_xBuilder->weld_widget(u"boxTYPE"_ustr)) @@ -96,6 +96,16 @@ ScaleTabPage::ScaleTabPage(weld::Container* pPage, weld::DialogController* pCont , m_xFmtFldOrigin(m_xBuilder->weld_formatted_spin_button(u"EDT_ORIGIN"_ustr)) , m_xCbxAutoOrigin(m_xBuilder->weld_check_button(u"CBX_AUTO_ORIGIN"_ustr)) , m_xBxOrigin(m_xBuilder->weld_widget(u"boxORIGIN"_ustr)) + , m_xBxHistogramBinning(m_xBuilder->weld_widget(u"boxHISTOGRAM_BINNING"_ustr)) + , m_xRbtHistogramAutomatic(m_xBuilder->weld_radio_button(u"RB_HISTOGRAM_AUTOMATIC"_ustr)) + , m_xRbtHistogramBinWidth(m_xBuilder->weld_radio_button(u"RB_HISTOGRAM_BIN_WIDTH"_ustr)) + , m_xFmtFldHistogramBinWidth(m_xBuilder->weld_formatted_spin_button(u"EDT_HISTOGRAM_BIN_WIDTH"_ustr)) + , m_xRbtHistogramBinCount(m_xBuilder->weld_radio_button(u"RB_HISTOGRAM_BIN_COUNT"_ustr)) + , m_xMtHistogramBinCount(m_xBuilder->weld_spin_button(u"MT_HISTOGRAM_BIN_COUNT"_ustr)) + , m_xCbxHistogramOverflow(m_xBuilder->weld_check_button(u"CBX_HISTOGRAM_OVERFLOW"_ustr)) + , m_xFmtFldHistogramOverflow(m_xBuilder->weld_formatted_spin_button(u"EDT_HISTOGRAM_OVERFLOW"_ustr)) + , m_xCbxHistogramUnderflow(m_xBuilder->weld_check_button(u"CBX_HISTOGRAM_UNDERFLOW"_ustr)) + , m_xFmtFldHistogramUnderflow(m_xBuilder->weld_formatted_spin_button(u"EDT_HISTOGRAM_UNDERFLOW"_ustr)) { m_xCbxAutoMin->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); m_xCbxAutoMax->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); @@ -103,6 +113,20 @@ ScaleTabPage::ScaleTabPage(weld::Container* pPage, weld::DialogController* pCont m_xCbxAutoStepHelp->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); m_xCbxAutoOrigin->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); m_xCbx_AutoTimeResolution->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); + m_xRbtHistogramAutomatic->connect_toggled(LINK(this, ScaleTabPage, HistogramToggleHdl)); + m_xRbtHistogramBinWidth->connect_toggled(LINK(this, ScaleTabPage, HistogramToggleHdl)); + m_xRbtHistogramBinCount->connect_toggled(LINK(this, ScaleTabPage, HistogramToggleHdl)); + m_xCbxHistogramOverflow->connect_toggled(LINK(this, ScaleTabPage, HistogramToggleHdl)); + m_xCbxHistogramUnderflow->connect_toggled(LINK(this, ScaleTabPage, HistogramToggleHdl)); + + for (weld::FormattedSpinButton* pField : + { m_xFmtFldHistogramBinWidth.get(), + m_xFmtFldHistogramOverflow.get(), + m_xFmtFldHistogramUnderflow.get() }) + { + pField->GetFormatter().ClearMinValue(); + pField->GetFormatter().ClearMaxValue(); + } Formatter& rFmtFldMax = m_xFmtFldMax->GetFormatter(); rFmtFldMax.ClearMinValue(); @@ -155,7 +179,10 @@ void ScaleTabPage::EnableControls() { //transport value from one to other control if( bWasDateAxis ) - lcl_setValue( *m_xFmtFldStepMain, m_xMt_MainDateStep->get_value() ); + { + double nValue(static_cast(m_xMt_MainDateStep->get_value()) / weld::SpinButton::Power10(m_xMt_MainDateStep->get_digits())); + lcl_setValue( *m_xFmtFldStepMain, nValue ); + } else m_xMt_MainDateStep->set_value(m_xFmtFldStepMain->GetFormatter().GetValue()); } @@ -172,6 +199,27 @@ void ScaleTabPage::EnableControls() EnableValueHdl(*m_xCbxAutoStepHelp); EnableValueHdl(*m_xCbxAutoOrigin); EnableValueHdl(*m_xCbx_AutoTimeResolution); + EnableHistogramControls(); +} + +void ScaleTabPage::EnableHistogramControls() +{ + m_xBxHistogramBinning->set_visible( + m_bShowHistogramBinning); + + if (!m_bShowHistogramBinning) + { + return; + } + + m_xFmtFldHistogramBinWidth->set_sensitive( + m_xRbtHistogramBinWidth->get_active()); + m_xMtHistogramBinCount->set_sensitive( + m_xRbtHistogramBinCount->get_active()); + m_xFmtFldHistogramOverflow->set_sensitive( + m_xCbxHistogramOverflow->get_active()); + m_xFmtFldHistogramUnderflow->set_sensitive( + m_xCbxHistogramUnderflow->get_active()); } IMPL_LINK( ScaleTabPage, EnableValueHdl, weld::Toggleable&, rCbx, void ) @@ -206,6 +254,11 @@ IMPL_LINK( ScaleTabPage, EnableValueHdl, weld::Toggleable&, rCbx, void ) } } +IMPL_LINK_NOARG(ScaleTabPage, HistogramToggleHdl, weld::Toggleable&, void) +{ + EnableHistogramControls(); +} + namespace { enum AxisTypeListBoxEntry @@ -267,6 +320,27 @@ bool ScaleTabPage::FillItemSet(SfxItemSet* rOutAttrs) rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_MAIN_TIME_UNIT,m_nMainTimeUnit)); rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_HELP_TIME_UNIT,m_nHelpTimeUnit)); + if (m_bShowHistogramBinning) + { + sal_Int32 nFrequencyType = 0; + if (m_xRbtHistogramBinWidth->get_active()) + { + nFrequencyType = 1; + } + else if (m_xRbtHistogramBinCount->get_active()) + { + nFrequencyType = 2; + } + + rOutAttrs->Put(SfxInt32Item(SCHATTR_HISTOGRAM_FREQUENCY_TYPE, nFrequencyType)); + rOutAttrs->Put(SvxDoubleItem(m_xFmtFldHistogramBinWidth->GetFormatter().GetValue(),SCHATTR_HISTOGRAM_BIN_WIDTH)); + rOutAttrs->Put(SfxInt32Item(SCHATTR_HISTOGRAM_BIN_COUNT,m_xMtHistogramBinCount->get_value())); + rOutAttrs->Put(SfxBoolItem(SCHATTR_HISTOGRAM_USE_OVERFLOW_BIN,m_xCbxHistogramOverflow->get_active())); + rOutAttrs->Put(SvxDoubleItem(m_xFmtFldHistogramOverflow->GetFormatter().GetValue(),SCHATTR_HISTOGRAM_OVERFLOW_BIN_VALUE)); + rOutAttrs->Put(SfxBoolItem(SCHATTR_HISTOGRAM_USE_UNDERFLOW_BIN,m_xCbxHistogramUnderflow->get_active())); + rOutAttrs->Put(SvxDoubleItem(m_xFmtFldHistogramUnderflow->GetFormatter().GetValue(),SCHATTR_HISTOGRAM_UNDERFLOW_BIN_VALUE)); + } + return true; } @@ -377,6 +451,53 @@ void ScaleTabPage::Reset(const SfxItemSet* rInAttrs) m_xLB_HelpTimeUnit->set_active( m_nHelpTimeUnit ); } + + const SfxInt32Item* pFrequencyType = rInAttrs->GetItemIfSet(SCHATTR_HISTOGRAM_FREQUENCY_TYPE); + m_bShowHistogramBinning = pFrequencyType != nullptr; + + if (m_bShowHistogramBinning) + { + const sal_Int32 nFrequencyType = pFrequencyType->GetValue(); + + m_xRbtHistogramAutomatic->set_active(nFrequencyType != 1 && nFrequencyType != 2); + m_xRbtHistogramBinWidth->set_active(nFrequencyType == 1); + m_xRbtHistogramBinCount->set_active(nFrequencyType == 2); + + if (const SvxDoubleItem* pItem = rInAttrs->GetItemIfSet(SCHATTR_HISTOGRAM_BIN_WIDTH)) + { + lcl_setValue(*m_xFmtFldHistogramBinWidth, pItem->GetValue()); + m_xFmtFldHistogramBinWidth->save_value(); + } + + if (const SfxInt32Item* pItem = rInAttrs->GetItemIfSet(SCHATTR_HISTOGRAM_BIN_COUNT)) + { + m_xMtHistogramBinCount->set_value(pItem->GetValue()); + m_xMtHistogramBinCount->save_value(); + } + + if (const SfxBoolItem* pItem = rInAttrs->GetItemIfSet(SCHATTR_HISTOGRAM_USE_OVERFLOW_BIN)) + { + m_xCbxHistogramOverflow->set_active(pItem->GetValue()); + } + + if (const SvxDoubleItem* pItem = rInAttrs->GetItemIfSet(SCHATTR_HISTOGRAM_OVERFLOW_BIN_VALUE)) + { + lcl_setValue(*m_xFmtFldHistogramOverflow, pItem->GetValue()); + m_xFmtFldHistogramOverflow->save_value(); + } + + if (const SfxBoolItem* pItem = rInAttrs->GetItemIfSet(SCHATTR_HISTOGRAM_USE_UNDERFLOW_BIN)) + { + m_xCbxHistogramUnderflow->set_active(pItem->GetValue()); + } + + if (const SvxDoubleItem* pItem = rInAttrs->GetItemIfSet(SCHATTR_HISTOGRAM_UNDERFLOW_BIN_VALUE)) + { + lcl_setValue(*m_xFmtFldHistogramUnderflow, pItem->GetValue()); + m_xFmtFldHistogramUnderflow->save_value(); + } + } + EnableControls(); SetNumFormat(); } @@ -394,7 +515,7 @@ DeactivateRC ScaleTabPage::DeactivatePage(SfxItemSet* pItemSet) sal_uInt32 nMinMaxOriginFmt = m_xFmtFldMax->GetFormatter().GetFormatKey(); if (pNumFormatter->GetType(nMinMaxOriginFmt) == SvNumFormatType::TEXT) nMinMaxOriginFmt = 0; - // numberformat_text cause numbers to fail being numbers... Shouldn't happen, but can. + // numberformat_text causes numbers to fail being numbers... Shouldn't happen, but can. sal_uInt32 nStepFmt = m_xFmtFldStepMain->GetFormatter().GetFormatKey(); if (pNumFormatter->GetType(nStepFmt) == SvNumFormatType::TEXT) nStepFmt = 0; @@ -412,6 +533,10 @@ DeactivateRC ScaleTabPage::DeactivatePage(SfxItemSet* pItemSet) m_nMainTimeUnit = m_xLB_MainTimeUnit->get_active(); m_nHelpTimeUnit = m_xLB_HelpTimeUnit->get_active(); + const double fHistogramBinWidth = m_xFmtFldHistogramBinWidth->GetFormatter().GetValue(); + const double fHistogramUnderflow = m_xFmtFldHistogramUnderflow->GetFormatter().GetValue(); + const double fHistogramOverflow = m_xFmtFldHistogramOverflow->GetFormatter().GetValue(); + if( m_nAxisType != chart2::AxisType::REALNUMBER ) m_xCbxLogarithm->hide(); @@ -452,6 +577,41 @@ DeactivateRC ScaleTabPage::DeactivatePage(SfxItemSet* pItemSet) pControl = m_xFmtFldOrigin.get(); pErrStrId = STR_INVALID_NUMBER; } + else if (m_bShowHistogramBinning && m_xRbtHistogramBinWidth->get_active() + && m_xFmtFldHistogramBinWidth->get_value_changed_from_saved() + && !pNumFormatter->IsNumberFormat(m_xFmtFldHistogramBinWidth->get_text(), nStepFmt, + fDummy)) + { + pControl = m_xFmtFldHistogramBinWidth.get(); + pErrStrId = STR_INVALID_NUMBER; + } + else if (m_bShowHistogramBinning && m_xCbxHistogramOverflow->get_active() + && m_xFmtFldHistogramOverflow->get_value_changed_from_saved() + && !pNumFormatter->IsNumberFormat(m_xFmtFldHistogramOverflow->get_text(), + nMinMaxOriginFmt, fDummy)) + { + pControl = m_xFmtFldHistogramOverflow.get(); + pErrStrId = STR_INVALID_NUMBER; + } + else if (m_bShowHistogramBinning && m_xCbxHistogramUnderflow->get_active() + && m_xFmtFldHistogramUnderflow->get_value_changed_from_saved() + && !pNumFormatter->IsNumberFormat(m_xFmtFldHistogramUnderflow->get_text(), + nMinMaxOriginFmt, fDummy)) + { + pControl = m_xFmtFldHistogramUnderflow.get(); + pErrStrId = STR_INVALID_NUMBER; + } + else if (m_bShowHistogramBinning && m_xRbtHistogramBinWidth->get_active() + && fHistogramBinWidth <= 0.0) + { + pControl = m_xFmtFldHistogramBinWidth.get(); + pErrStrId = STR_HISTOGRAM_BIN_WIDTH_GT_ZERO; + } + else if (m_bShowHistogramBinning && m_xCbxHistogramUnderflow->get_active() && m_xCbxHistogramOverflow->get_active() && fHistogramUnderflow >= fHistogramOverflow) + { + pControl = m_xFmtFldHistogramUnderflow.get(); + pErrStrId = STR_HISTOGRAM_INVALID_OVERFLOW_UNDERFLOW; + } else if (!m_xCbxAutoStepMain->get_active() && fStepMain <= 0.0) { pControl = m_xFmtFldStepMain.get(); @@ -509,11 +669,19 @@ void ScaleTabPage::SetNumFormatter( SvNumberFormatter* pFormatter ) Formatter& rFmtFldStepMain = m_xFmtFldStepMain->GetFormatter(); Formatter& rFmtFldOrigin = m_xFmtFldOrigin->GetFormatter(); + Formatter& rHistogramBinWidth = m_xFmtFldHistogramBinWidth->GetFormatter(); + Formatter& rHistogramOverflow = m_xFmtFldHistogramOverflow->GetFormatter(); + Formatter& rHistogramUnderflow = m_xFmtFldHistogramUnderflow->GetFormatter(); + rFmtFldMax.SetFormatter( pNumFormatter ); rFmtFldMin.SetFormatter( pNumFormatter ); rFmtFldStepMain.SetFormatter( pNumFormatter ); rFmtFldOrigin.SetFormatter( pNumFormatter ); + rHistogramBinWidth.SetFormatter(pNumFormatter); + rHistogramOverflow.SetFormatter(pNumFormatter); + rHistogramUnderflow.SetFormatter(pNumFormatter); + // #i6278# allow more decimal places than the output format. As // the numbers shown in the edit fields are used for input, it makes more // sense to display the values in the input format rather than the output @@ -523,6 +691,10 @@ void ScaleTabPage::SetNumFormatter( SvNumberFormatter* pFormatter ) rFmtFldStepMain.UseInputStringForFormatting(); rFmtFldOrigin.UseInputStringForFormatting(); + rHistogramBinWidth.UseInputStringForFormatting(); + rHistogramOverflow.UseInputStringForFormatting(); + rHistogramUnderflow.UseInputStringForFormatting(); + SetNumFormat(); } @@ -584,6 +756,13 @@ void ScaleTabPage::SetNumFormat() } } + // The bin width spans a distance along the axis, so it takes the interval format that the + // main step uses. The overflow and underflow boundaries are positions on the axis, so they + // take the same format as Minimum, Maximum and Origin. + const sal_uInt32 nAxisValueFormat = rFmtFldMax.GetFormatKey(); + m_xFmtFldHistogramBinWidth->GetFormatter().SetFormatKey(nFmt); + m_xFmtFldHistogramOverflow->GetFormatter().SetFormatKey(nAxisValueFormat); + m_xFmtFldHistogramUnderflow->GetFormatter().SetFormatKey(nAxisValueFormat); m_xFmtFldStepMain->GetFormatter().SetFormatKey(nFmt); } @@ -617,7 +796,7 @@ void ScaleTabPage::HideAllControls() { // We need to set these controls invisible when the class is instantiated // since some code in EnableControls() depends on that logic. The real - // visibility of these controls depend on axis data type, and are + // visibility of these controls depends on axis data type, and are // set in EnableControls(). m_xBxType->hide(); @@ -634,6 +813,7 @@ void ScaleTabPage::HideAllControls() m_xCbxAutoStepHelp->hide(); m_xBxOrigin->hide(); m_xBxResolution->hide(); + m_xBxHistogramBinning->hide(); } } //namespace chart diff --git a/chart2/source/controller/dialogs/tp_Scale.hxx b/chart2/source/controller/dialogs/tp_Scale.hxx index db776a9ea2c9..23d43ee2313a 100644 --- a/chart2/source/controller/dialogs/tp_Scale.hxx +++ b/chart2/source/controller/dialogs/tp_Scale.hxx @@ -20,8 +20,12 @@ #include #include +#include #include +#include #include +#include +#include #include class SvNumberFormatter; @@ -59,6 +63,7 @@ private: SvNumberFormatter* pNumFormatter; bool m_bShowAxisOrigin; + bool m_bShowHistogramBinning; std::unique_ptr m_xCbxReverse; std::unique_ptr m_xCbxLogarithm; @@ -85,11 +90,23 @@ private: std::unique_ptr m_xFmtFldOrigin; std::unique_ptr m_xCbxAutoOrigin; std::unique_ptr m_xBxOrigin; + std::unique_ptr m_xBxHistogramBinning; + std::unique_ptr m_xRbtHistogramAutomatic; + std::unique_ptr m_xRbtHistogramBinWidth; + std::unique_ptr m_xFmtFldHistogramBinWidth; + std::unique_ptr m_xRbtHistogramBinCount; + std::unique_ptr m_xMtHistogramBinCount; + std::unique_ptr m_xCbxHistogramOverflow; + std::unique_ptr m_xFmtFldHistogramOverflow; + std::unique_ptr m_xCbxHistogramUnderflow; + std::unique_ptr m_xFmtFldHistogramUnderflow; void EnableControls(); + void EnableHistogramControls(); DECL_LINK(SelectAxisTypeHdl, weld::ComboBox&, void); DECL_LINK(EnableValueHdl, weld::Toggleable&, void); + DECL_LINK(HistogramToggleHdl, weld::Toggleable&, void); /** shows a warning window due to an invalid input. @@ -102,7 +119,7 @@ private: erroneous value was in. This method gives this control the focus and selects its content. - @return false, if nResIdMessage was 0, true otherwise + @return false, if pResIdMessage was 0, true otherwise */ bool ShowWarning(TranslateId pResIdMessage, weld::Widget* pControl); diff --git a/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx b/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx index ab14c5cd26d6..5fa95e58b8ce 100644 --- a/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx +++ b/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include @@ -167,7 +169,14 @@ void SchOptionTabPage::Reset(const SfxItemSet* rInAttrs) { std::vector< sal_Int32 > aMissingValueTreatments; if (const SfxIntegerListItem* pValueTreatmentsItem = rInAttrs->GetItemIfSet(SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS)) +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 17 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wrestrict" +#endif aMissingValueTreatments = pValueTreatmentsItem->GetList(); +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 17 +#pragma GCC diagnostic pop +#endif const SfxInt32Item* pMissingValueTreatmentItem; if ( aMissingValueTreatments.size()>1 && diff --git a/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx b/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx index 9b8b46a1392f..3e190cf0918f 100644 --- a/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx +++ b/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx @@ -21,11 +21,13 @@ #include #include -namespace weld { - class CheckButton; - class MetricSpinButton; - class RadioButton; - class Widget; +namespace weld +{ +class CheckButton; +class MetricSpinButton; +class RadioButton; +class Toggleable; +class Widget; } namespace chart diff --git a/chart2/source/controller/dialogs/tp_TitleRotation.cxx b/chart2/source/controller/dialogs/tp_TitleRotation.cxx index c9f4e9e91123..d4fabed07ea8 100644 --- a/chart2/source/controller/dialogs/tp_TitleRotation.cxx +++ b/chart2/source/controller/dialogs/tp_TitleRotation.cxx @@ -27,6 +27,8 @@ #include #include #include +#include +#include namespace chart { diff --git a/chart2/source/controller/dialogs/tp_TitleRotation.hxx b/chart2/source/controller/dialogs/tp_TitleRotation.hxx index ae34d8a4d0f1..4ebc4a6ded64 100644 --- a/chart2/source/controller/dialogs/tp_TitleRotation.hxx +++ b/chart2/source/controller/dialogs/tp_TitleRotation.hxx @@ -23,10 +23,12 @@ #include #include -namespace weld { - class CheckButton; - class CustomWeld; - class Label; +namespace weld +{ +class CheckButton; +class CustomWeld; +class Label; +class Toggleable; } namespace chart diff --git a/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx index f43fca973622..4e4efcfe2c0c 100644 --- a/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx +++ b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx @@ -137,7 +137,7 @@ IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeCheckBoxHdl, weld::Toggleable&, v ChangeHdl(nullptr); } -IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeEditHdl, weld::Entry&, void) +IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeEditHdl, weld::TextWidget&, void) { ChangeHdl(nullptr); } diff --git a/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx index f5bf414c8c7d..e9ab2cfa77eb 100644 --- a/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx +++ b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include @@ -50,7 +52,7 @@ public: private: void commitToModel(); DECL_LINK( ChangeHdl, LinkParamNone*, void ); - DECL_LINK( ChangeEditHdl, weld::Entry&, void ); + DECL_LINK(ChangeEditHdl, weld::TextWidget&, void); DECL_LINK( ChangeCheckBoxHdl, weld::Toggleable&, void ); std::unique_ptr< TitleResources > m_xTitleResources; diff --git a/chart2/source/controller/inc/AccessibleChartView.hxx b/chart2/source/controller/inc/AccessibleChartView.hxx index 9a973f80843a..fd1d6966ec20 100644 --- a/chart2/source/controller/inc/AccessibleChartView.hxx +++ b/chart2/source/controller/inc/AccessibleChartView.hxx @@ -21,7 +21,7 @@ #include "AccessibleBase.hxx" #include "ChartWindow.hxx" #include -#include +#include #include #include @@ -52,14 +52,14 @@ public: // 0: view::XSelectionSupplier offers notifications for selection changes and access to the selection itself // 1: frame::XModel representing the chart model - offers access to object data // 2: lang::XInterface representing the normal chart view - offers access to some extra object data - // 3: accessibility::XAccessible representing the parent accessible + // 3: OAccessible representing the parent accessible // 4: ChartWindow representing the view's window // all arguments are only valid until next initialization - don't keep them longer - void initialize( ChartController& rChartController, - const rtl::Reference<::chart::ChartModel>& xChartModel, - const rtl::Reference<::chart::ChartView>& xChartView, - const css::uno::Reference< css::accessibility::XAccessible >& xParent, - ChartWindow* pNewChartWindow); + void initialize(ChartController& rChartController, + const rtl::Reference<::chart::ChartModel>& xChartModel, + const rtl::Reference<::chart::ChartView>& xChartView, + const rtl::Reference& rpNewParent, + ChartWindow* pNewChartWindow); // used to disconnect from view void initialize(); @@ -97,7 +97,7 @@ private: // members unotools::WeakReference< ::chart::ChartModel > m_xChartModel; unotools::WeakReference< ChartView > m_xChartView; VclPtr m_pChartWindow; - css::uno::WeakReference< css::accessibility::XAccessible > m_xParent; + unotools::WeakReference m_pParent; std::shared_ptr< ObjectHierarchy > m_spObjectHierarchy; AccessibleUniqueId m_aCurrentSelectionOID; diff --git a/chart2/source/controller/inc/dlg_ChartType.hxx b/chart2/source/controller/inc/dlg_ChartType.hxx index ffe1cf6b7763..9b62a97c1ab6 100644 --- a/chart2/source/controller/inc/dlg_ChartType.hxx +++ b/chart2/source/controller/inc/dlg_ChartType.hxx @@ -18,8 +18,9 @@ */ #pragma once +#include #include -#include +#include #include namespace chart diff --git a/chart2/source/controller/inc/dlg_DataEditor.hxx b/chart2/source/controller/inc/dlg_DataEditor.hxx index 1dfcf992dc10..ac92822bb799 100644 --- a/chart2/source/controller/inc/dlg_DataEditor.hxx +++ b/chart2/source/controller/inc/dlg_DataEditor.hxx @@ -20,9 +20,12 @@ #pragma once #include +#include +#include +#include #include #include -#include +#include #include namespace com::sun::star::uno { class XComponentContext; } diff --git a/chart2/source/controller/inc/dlg_DataSource.hxx b/chart2/source/controller/inc/dlg_DataSource.hxx index f761ca47ae10..16d8d3f033ee 100644 --- a/chart2/source/controller/inc/dlg_DataSource.hxx +++ b/chart2/source/controller/inc/dlg_DataSource.hxx @@ -19,9 +19,12 @@ #pragma once #include "TabPageNotifiable.hxx" + +#include #include #include -#include +#include + #include namespace chart diff --git a/chart2/source/controller/inc/dlg_InsertAxis_Grid.hxx b/chart2/source/controller/inc/dlg_InsertAxis_Grid.hxx index 5c7bbfc21670..d8e6395e9e44 100644 --- a/chart2/source/controller/inc/dlg_InsertAxis_Grid.hxx +++ b/chart2/source/controller/inc/dlg_InsertAxis_Grid.hxx @@ -18,8 +18,9 @@ */ #pragma once +#include #include -#include +#include #include namespace chart diff --git a/chart2/source/controller/inc/dlg_InsertDataLabel.hxx b/chart2/source/controller/inc/dlg_InsertDataLabel.hxx index 3bf6f0bb7fc5..75acfcbcf17e 100644 --- a/chart2/source/controller/inc/dlg_InsertDataLabel.hxx +++ b/chart2/source/controller/inc/dlg_InsertDataLabel.hxx @@ -19,7 +19,7 @@ #pragma once #include -#include +#include #include #include diff --git a/chart2/source/controller/inc/dlg_InsertDataTable.hxx b/chart2/source/controller/inc/dlg_InsertDataTable.hxx index af6ea5c58860..68cf3c0ff6d8 100644 --- a/chart2/source/controller/inc/dlg_InsertDataTable.hxx +++ b/chart2/source/controller/inc/dlg_InsertDataTable.hxx @@ -9,8 +9,9 @@ #pragma once +#include #include -#include +#include #include "res_DataTableProperties.hxx" namespace chart diff --git a/chart2/source/controller/inc/dlg_InsertErrorBars.hxx b/chart2/source/controller/inc/dlg_InsertErrorBars.hxx index 7e652ef61f21..bfb2c32258a6 100644 --- a/chart2/source/controller/inc/dlg_InsertErrorBars.hxx +++ b/chart2/source/controller/inc/dlg_InsertErrorBars.hxx @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include "res_ErrorBar.hxx" diff --git a/chart2/source/controller/inc/dlg_InsertLegend.hxx b/chart2/source/controller/inc/dlg_InsertLegend.hxx index 4892e7247013..66bc8cfb2d83 100644 --- a/chart2/source/controller/inc/dlg_InsertLegend.hxx +++ b/chart2/source/controller/inc/dlg_InsertLegend.hxx @@ -19,7 +19,7 @@ #pragma once #include -#include +#include #include #include diff --git a/chart2/source/controller/inc/dlg_InsertTitle.hxx b/chart2/source/controller/inc/dlg_InsertTitle.hxx index f10a6ca44425..6320d2ae2eab 100644 --- a/chart2/source/controller/inc/dlg_InsertTitle.hxx +++ b/chart2/source/controller/inc/dlg_InsertTitle.hxx @@ -20,7 +20,7 @@ #include "res_Titles.hxx" #include -#include +#include #include namespace chart diff --git a/chart2/source/controller/inc/dlg_ShapeFont.hxx b/chart2/source/controller/inc/dlg_ShapeFont.hxx index cfeb002fb92d..8b2a42bc1a8a 100644 --- a/chart2/source/controller/inc/dlg_ShapeFont.hxx +++ b/chart2/source/controller/inc/dlg_ShapeFont.hxx @@ -19,6 +19,7 @@ #pragma once #include +#include namespace chart { diff --git a/chart2/source/controller/inc/dlg_ShapeParagraph.hxx b/chart2/source/controller/inc/dlg_ShapeParagraph.hxx index 15d0c014d848..aa23d16717ab 100644 --- a/chart2/source/controller/inc/dlg_ShapeParagraph.hxx +++ b/chart2/source/controller/inc/dlg_ShapeParagraph.hxx @@ -19,6 +19,7 @@ #pragma once #include +#include namespace chart { diff --git a/chart2/source/controller/inc/dlg_View3D.hxx b/chart2/source/controller/inc/dlg_View3D.hxx index 53dc482a1c14..371c8480f20f 100644 --- a/chart2/source/controller/inc/dlg_View3D.hxx +++ b/chart2/source/controller/inc/dlg_View3D.hxx @@ -20,7 +20,7 @@ #include #include -#include +#include #include namespace chart diff --git a/chart2/source/controller/inc/res_DataTableProperties.hxx b/chart2/source/controller/inc/res_DataTableProperties.hxx index a7f60fa510c2..a276b42a3f7e 100644 --- a/chart2/source/controller/inc/res_DataTableProperties.hxx +++ b/chart2/source/controller/inc/res_DataTableProperties.hxx @@ -11,7 +11,7 @@ #include #include -#include +#include namespace chart { diff --git a/chart2/source/controller/inc/res_ErrorBar.hxx b/chart2/source/controller/inc/res_ErrorBar.hxx index 4fcd21226261..b52631dc4544 100644 --- a/chart2/source/controller/inc/res_ErrorBar.hxx +++ b/chart2/source/controller/inc/res_ErrorBar.hxx @@ -25,19 +25,23 @@ #include #include -namespace weld { class Builder; } -namespace weld { class Button; } -namespace weld { class CheckButton; } -namespace weld { class ComboBox; } -namespace weld { class DialogController; } -namespace weld { class Entry; } -namespace weld { class Frame; } -namespace weld { class Image; } -namespace weld { class Label; } -namespace weld { class MetricSpinButton; } -namespace weld { class RadioButton; } -namespace weld { class Toggleable; } -namespace weld { class Widget; } +namespace weld +{ +class Builder; +class Button; +class CheckButton; +class ComboBox; +class DialogController; +class Entry; +class Frame; +class Image; +class Label; +class MetricSpinButton; +class RadioButton; +class TextWidget; +class Toggleable; +class Widget; +} namespace chart { @@ -130,7 +134,7 @@ private: DECL_LINK( PosValueChanged, weld::MetricSpinButton&, void ); DECL_LINK( IndicatorChanged, weld::Toggleable&, void ); DECL_LINK( ChooseRange, weld::Button&, void ); - DECL_LINK( RangeChanged, weld::Entry&, void ); + DECL_LINK(RangeChanged, weld::TextWidget&, void); void UpdateControlStates(); void isRangeFieldContentValid(weld::Entry& rEdit); diff --git a/chart2/source/controller/inc/res_Titles.hxx b/chart2/source/controller/inc/res_Titles.hxx index a7a2eba57277..094059a5cb44 100644 --- a/chart2/source/controller/inc/res_Titles.hxx +++ b/chart2/source/controller/inc/res_Titles.hxx @@ -24,14 +24,9 @@ template class Link; namespace weld { class Builder; -} -namespace weld -{ class Entry; -} -namespace weld -{ class Label; +class TextWidget; } namespace chart @@ -45,7 +40,7 @@ public: void writeToResources(const TitleDialogData& rInput); void readFromResources(TitleDialogData& rOutput); - void connect_changed(const Link& rLink); + void connect_changed(const Link& rLink); bool get_value_changed_from_saved() const; void save_value(); diff --git a/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx b/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx index f6a7fc528140..e87959b056d7 100644 --- a/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx +++ b/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,29 @@ ItemPropertyMapType & lcl_GetAxisPropertyMap() return aAxisPropertyMap; }; +OUString lcl_getHistogramPropertyName(sal_uInt16 nWhichId) +{ + switch (nWhichId) + { + case SCHATTR_HISTOGRAM_FREQUENCY_TYPE: + return u"FrequencyType"_ustr; + case SCHATTR_HISTOGRAM_BIN_WIDTH: + return u"BinWidth"_ustr; + case SCHATTR_HISTOGRAM_BIN_COUNT: + return u"BinCount"_ustr; + case SCHATTR_HISTOGRAM_USE_UNDERFLOW_BIN: + return u"UseUnderflowBin"_ustr; + case SCHATTR_HISTOGRAM_UNDERFLOW_BIN_VALUE: + return u"UnderflowBinValue"_ustr; + case SCHATTR_HISTOGRAM_USE_OVERFLOW_BIN: + return u"UseOverflowBin"_ustr; + case SCHATTR_HISTOGRAM_OVERFLOW_BIN_VALUE: + return u"OverflowBinValue"_ustr; + default: + return OUString(); + } +} + } // anonymous namespace AxisItemConverter::AxisItemConverter( @@ -159,6 +183,30 @@ void AxisItemConverter::FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutI if( !m_xAxis.is() ) return; + const OUString aHistogramProperty = lcl_getHistogramPropertyName(nWhichId); + + if (!aHistogramProperty.isEmpty()) + { + rtl::Reference<::chart::ChartType> xHistogramType + = AxisHelper::getHistogramChartTypeOfAxis(m_xAxis, m_xChartDoc); + + if (!xHistogramType.is()) + { + return; + } + + std::unique_ptr pItem( + GetItemPool().GetUserOrPoolDefaultItem(nWhichId).Clone()); + + if (pItem + && pItem->PutValue(xHistogramType->getPropertyValue(aHistogramProperty), 0)) + { + pItem->SetWhich(nWhichId); + rOutItemSet.Put(std::move(pItem)); + } + return; + } + const chart2::ScaleData aScale( m_xAxis->getScaleData() ); const chart2::IncrementData& rIncrement( aScale.IncrementData ); const uno::Sequence< chart2::SubIncrement >& rSubIncrements( aScale.IncrementData.SubIncrements ); @@ -349,7 +397,7 @@ void AxisItemConverter::FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutI case SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT: { //read only item - //necessary tp display the crossing value with an appropriate format + //necessary to display the crossing value with an appropriate format rtl::Reference< BaseCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( m_xAxis, m_xChartDoc->getFirstChartDiagram() ) ); @@ -465,6 +513,32 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet if( !m_xAxis.is() ) return false; + const OUString aHistogramProperty = lcl_getHistogramPropertyName(nWhichId); + + if (!aHistogramProperty.isEmpty()) + { + rtl::Reference<::chart::ChartType> xHistogramType + = AxisHelper::getHistogramChartTypeOfAxis(m_xAxis, m_xChartDoc); + + if (!xHistogramType.is()) + { + return false; + } + + uno::Any aNewValue; + rItemSet.Get(nWhichId).QueryValue(aNewValue); + + if (xHistogramType->getPropertyValue(aHistogramProperty) + == aNewValue) + { + return false; + } + + xHistogramType->setPropertyValue( + aHistogramProperty, aNewValue); + return true; + } + chart2::ScaleData aScale( m_xAxis->getScaleData() ); bool bSetScale = false; @@ -475,7 +549,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet switch( nWhichId ) { case SCHATTR_AXIS_AUTO_MAX: - if( static_cast< const SfxBoolItem & >(rItemSet.Get( nWhichId )).GetValue() ) + if( rItemSet.Get( SCHATTR_AXIS_AUTO_MAX ).GetValue() ) { aScale.Maximum.clear(); bSetScale = true; @@ -484,7 +558,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet break; case SCHATTR_AXIS_MAX: - // only if auto if false + // only if auto is false if( ! (rItemSet.Get( SCHATTR_AXIS_AUTO_MAX ).GetValue() )) { rItemSet.Get( nWhichId ).QueryValue( aValue ); @@ -498,7 +572,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet break; case SCHATTR_AXIS_AUTO_MIN: - if( static_cast< const SfxBoolItem & >(rItemSet.Get( nWhichId )).GetValue() ) + if( rItemSet.Get( SCHATTR_AXIS_AUTO_MIN ).GetValue() ) { aScale.Minimum.clear(); bSetScale = true; @@ -507,7 +581,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet break; case SCHATTR_AXIS_MIN: - // only if auto if false + // only if auto is false if( ! (rItemSet.Get( SCHATTR_AXIS_AUTO_MIN ).GetValue() )) { rItemSet.Get( nWhichId ).QueryValue( aValue ); @@ -524,7 +598,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet { bool bWasLogarithm = AxisHelper::isLogarithmic( aScale.Scaling ); - if( static_cast< const SfxBoolItem & >(rItemSet.Get( nWhichId )).GetValue() ) + if( rItemSet.Get( SCHATTR_AXIS_LOGARITHM ).GetValue() ) { // logarithm is true if( ! bWasLogarithm ) @@ -548,8 +622,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SCHATTR_AXIS_REVERSE: { bool bWasReverse = ( aScale.Orientation == AxisOrientation_REVERSE ); - bool bNewReverse = static_cast< const SfxBoolItem & >( - rItemSet.Get( nWhichId )).GetValue(); + bool bNewReverse = rItemSet.Get( SCHATTR_AXIS_REVERSE ).GetValue(); if( bWasReverse != bNewReverse ) { aScale.Orientation = bNewReverse ? AxisOrientation_REVERSE : AxisOrientation_MATHEMATICAL; @@ -584,7 +657,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet break; case SCHATTR_AXIS_STEP_MAIN: - // only if auto if false + // only if auto is false if( !lcl_isAutoMajor(rItemSet) ) { rItemSet.Get( nWhichId ).QueryValue( aValue ); @@ -624,7 +697,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet bSetScale = true; } } - // else SCHATTR_AXIS_STEP_MAIN must have some value + // else SCHATTR_AXIS_STEP_HELP must have some value break; case SCHATTR_AXIS_HELP_TIME_UNIT: @@ -668,7 +741,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet break; case SCHATTR_AXIS_AUTO_TIME_RESOLUTION: - if( static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId )).GetValue() ) + if( rItemSet.Get(SCHATTR_AXIS_AUTO_TIME_RESOLUTION).GetValue() ) { aScale.TimeIncrement.TimeResolution.clear(); bSetScale = true; @@ -690,7 +763,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SCHATTR_AXIS_AUTO_ORIGIN: { - if( static_cast< const SfxBoolItem & >(rItemSet.Get( nWhichId )).GetValue() ) + if( rItemSet.Get( SCHATTR_AXIS_AUTO_ORIGIN ).GetValue() ) { aScale.Origin.clear(); bSetScale = true; @@ -742,7 +815,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SCHATTR_AXIS_POSITION: { css::chart::ChartAxisPosition eAxisPos = - static_cast(static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue()); + static_cast( rItemSet.Get( SCHATTR_AXIS_POSITION ).GetValue()); css::chart::ChartAxisPosition eOldAxisPos( css::chart::ChartAxisPosition_ZERO ); bool bPropExisted = ( GetPropertySet()->getPropertyValue( u"CrossoverPosition"_ustr ) >>= eOldAxisPos ); @@ -779,7 +852,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SCHATTR_AXIS_POSITION_VALUE: { - double fValue = static_cast< const SvxDoubleItem & >( rItemSet.Get( nWhichId )).GetValue(); + double fValue = rItemSet.Get( SCHATTR_AXIS_POSITION_VALUE ).GetValue(); double fOldValue = 0.0; bool bPropExisted = ( GetPropertySet()->getPropertyValue( u"CrossoverValue"_ustr ) >>= fOldValue ); @@ -813,7 +886,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION: { - bool bNewValue = static_cast (rItemSet.Get(nWhichId)).GetValue(); + bool bNewValue = rItemSet.Get(SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION).GetValue(); bool bOldValue = aScale.ShiftedCategoryPosition; if (bOldValue != bNewValue) { @@ -826,7 +899,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SCHATTR_AXIS_LABEL_POSITION: { css::chart::ChartAxisLabelPosition ePos = - static_cast(static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue()); + static_cast(rItemSet.Get( SCHATTR_AXIS_LABEL_POSITION ).GetValue()); css::chart::ChartAxisLabelPosition eOldPos( css::chart::ChartAxisLabelPosition_NEAR_AXIS ); bool bPropExisted = ( GetPropertySet()->getPropertyValue( u"LabelPosition"_ustr ) >>= eOldPos ); @@ -864,7 +937,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SCHATTR_AXIS_MARK_POSITION: { css::chart::ChartAxisMarkPosition ePos = - static_cast(static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue()); + static_cast( rItemSet.Get( SCHATTR_AXIS_MARK_POSITION ).GetValue()); css::chart::ChartAxisMarkPosition eOldPos( css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ); bool bPropExisted = ( GetPropertySet()->getPropertyValue( u"MarkPosition"_ustr ) >>= eOldPos ); @@ -901,9 +974,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet if( ! bUseSourceFormat ) { - sal_Int32 nFmt = static_cast< sal_Int32 >( - static_cast< const SfxUInt32Item & >( - rItemSet.Get( nWhichId )).GetValue()); + sal_Int32 nFmt = static_cast< sal_Int32 >( rItemSet.Get( SID_ATTR_NUMBERFORMAT_VALUE ).GetValue()); aValue <<= nFmt; if (GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT) != aValue) @@ -918,9 +989,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SID_ATTR_NUMBERFORMAT_SOURCE: { - bool bUseSourceFormat = - static_cast< const SfxBoolItem & >( - rItemSet.Get( nWhichId )).GetValue(); + bool bUseSourceFormat = rItemSet.Get( SID_ATTR_NUMBERFORMAT_SOURCE ).GetValue(); GetPropertySet()->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(bUseSourceFormat)); bool bNumberFormatIsSet = GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT).hasValue(); @@ -957,7 +1026,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SCHATTR_AXISTYPE: { - sal_Int32 nNewAxisType = static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue();//css::chart2::AxisType + sal_Int32 nNewAxisType = rItemSet.Get( SCHATTR_AXISTYPE ).GetValue();//css::chart2::AxisType aScale.AxisType = nNewAxisType; bSetScale = true; } @@ -965,7 +1034,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet case SCHATTR_AXIS_AUTO_DATEAXIS: { - bool bNewValue = static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId )).GetValue(); + bool bNewValue = rItemSet.Get( SCHATTR_AXIS_AUTO_DATEAXIS ).GetValue(); bool bOldValue = aScale.AutoDateAxis; if( bOldValue != bNewValue ) { diff --git a/chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx b/chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx index a924d6db1803..cbdacb47c762 100644 --- a/chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx +++ b/chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx @@ -322,9 +322,7 @@ bool CharacterPropertyItemConverter::ApplySpecialItem( else if( nWhichId == EE_CHAR_FONTINFO_CTL ) aPostfix = "Complex"; - const SvxFontItem & rItem = - static_cast< const SvxFontItem & >( - rItemSet.Get( nWhichId )); + const SvxFontItem & rItem = rItemSet.Get( nWhichId ).StaticWhichCast(EE_CHAR_FONTINFO); if( rItem.QueryValue( aValue, MID_FONT_FAMILY_NAME )) { @@ -371,9 +369,7 @@ bool CharacterPropertyItemConverter::ApplySpecialItem( case EE_CHAR_UNDERLINE: { - const SvxUnderlineItem & rItem = - static_cast< const SvxUnderlineItem & >( - rItemSet.Get( nWhichId )); + const SvxUnderlineItem & rItem = rItemSet.Get( nWhichId ).StaticWhichCast(EE_CHAR_UNDERLINE); if( rItem.QueryValue( aValue, MID_TL_STYLE )) { @@ -406,7 +402,7 @@ bool CharacterPropertyItemConverter::ApplySpecialItem( case EE_CHAR_OVERLINE: { - const SvxOverlineItem& rItem = static_cast< const SvxOverlineItem & >( rItemSet.Get( nWhichId ) ); + const SvxOverlineItem & rItem = rItemSet.Get( nWhichId ).StaticWhichCast(EE_CHAR_OVERLINE); if ( rItem.QueryValue( aValue, MID_TL_STYLE ) ) { @@ -447,9 +443,7 @@ bool CharacterPropertyItemConverter::ApplySpecialItem( else if( nWhichId == EE_CHAR_ITALIC_CTL ) aPostfix = "Complex"; - const SvxPostureItem & rItem = - static_cast< const SvxPostureItem & >( - rItemSet.Get( nWhichId )); + const SvxPostureItem & rItem = rItemSet.Get( nWhichId ).StaticWhichCast(EE_CHAR_ITALIC); if( rItem.QueryValue( aValue, MID_POSTURE )) { @@ -472,9 +466,7 @@ bool CharacterPropertyItemConverter::ApplySpecialItem( else if( nWhichId == EE_CHAR_WEIGHT_CTL ) aPostfix = "Complex"; - const SvxWeightItem & rItem = - static_cast< const SvxWeightItem & >( - rItemSet.Get( nWhichId )); + const SvxWeightItem & rItem = rItemSet.Get( nWhichId ).StaticWhichCast(EE_CHAR_WEIGHT); if( rItem.QueryValue( aValue, MID_WEIGHT )) { @@ -497,9 +489,7 @@ bool CharacterPropertyItemConverter::ApplySpecialItem( else if( nWhichId == EE_CHAR_FONTHEIGHT_CTL ) aPostfix = "Complex"; - const SvxFontHeightItem & rItem = - static_cast< const SvxFontHeightItem & >( - rItemSet.Get( nWhichId )); + const SvxFontHeightItem & rItem = rItemSet.Get( nWhichId ).StaticWhichCast(EE_CHAR_FONTHEIGHT); try { diff --git a/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx index ae4ac1033f64..e2cd3c4d8da4 100644 --- a/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx +++ b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx @@ -373,7 +373,7 @@ bool DataPointItemConverter::ApplySpecialItem( case SCHATTR_DATADESCR_SEPARATOR: { - OUString aNewValue = static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue(); + OUString aNewValue = rItemSet.Get( SCHATTR_DATADESCR_SEPARATOR ).GetValue(); try { OUString aOldValue; @@ -406,7 +406,7 @@ bool DataPointItemConverter::ApplySpecialItem( try { - bool bNew = static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId )).GetValue(); + bool bNew = rItemSet.Get( SCHATTR_DATADESCR_WRAP_TEXT ).GetValue(); bool bOld = false; GetPropertySet()->getPropertyValue( u"TextWordWrap"_ustr ) >>= bOld; if( m_bOverwriteLabelsForAttributedDataPointsAlso ) @@ -437,7 +437,7 @@ bool DataPointItemConverter::ApplySpecialItem( try { - sal_Int32 nNew = static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue(); + sal_Int32 nNew = rItemSet.Get( SCHATTR_DATADESCR_PLACEMENT ).GetValue(); sal_Int32 nOld = -1; RelativePosition aCustomLabelPosition; GetPropertySet()->getPropertyValue(u"LabelPlacement"_ustr) >>= nOld; @@ -468,9 +468,7 @@ bool DataPointItemConverter::ApplySpecialItem( case SCHATTR_STYLE_SYMBOL: { - sal_Int32 nStyle = - static_cast< const SfxInt32Item & >( - rItemSet.Get( nWhichId )).GetValue(); + sal_Int32 nStyle = rItemSet.Get( SCHATTR_STYLE_SYMBOL ).GetValue(); chart2::Symbol aSymbol; GetPropertySet()->getPropertyValue( u"Symbol"_ustr ) >>= aSymbol; @@ -510,8 +508,7 @@ bool DataPointItemConverter::ApplySpecialItem( case SCHATTR_SYMBOL_SIZE: { - Size aSize = static_cast< const SvxSizeItem & >( - rItemSet.Get( nWhichId )).GetSize(); + Size aSize = rItemSet.Get( SCHATTR_SYMBOL_SIZE ).GetSize(); chart2::Symbol aSymbol; GetPropertySet()->getPropertyValue( u"Symbol"_ustr ) >>= aSymbol; diff --git a/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx b/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx index 8216c4b32337..d3b2f10a937d 100644 --- a/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx +++ b/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx @@ -38,6 +38,7 @@ const WhichRangesContainer nTitleWhichPairs(svl::Items< const WhichRangesContainer nAxisWhichPairs(svl::Items< SCHATTR_TEXT_START, SCHATTR_TEXT_END, SCHATTR_AXIS_START, SCHATTR_AXIS_END, + SCHATTR_HISTOGRAM_BINNING_START, SCHATTR_HISTOGRAM_BINNING_END, XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx EE_ITEMS_START, EE_ITEMS_END, // Characters SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_VALUE, // 10585 - 10585 svx/svxids.hrc diff --git a/chart2/source/controller/main/ChartController.cxx b/chart2/source/controller/main/ChartController.cxx index cf24954a6447..ffd4683dd9b4 100644 --- a/chart2/source/controller/main/ChartController.cxx +++ b/chart2/source/controller/main/ChartController.cxx @@ -69,7 +69,6 @@ #include #include #include -#include #include #include @@ -611,7 +610,10 @@ rtl::Reference<::chart::ChartModel> ChartController::getChartModel() rtl::Reference<::chart::Diagram> ChartController::getFirstDiagram() { - return getChartModel()->getFirstChartDiagram(); + rtl::Reference<::chart::ChartModel> xModel = getChartModel(); + if (!xModel) + return nullptr; + return xModel->getFirstChartDiagram(); } uno::Any SAL_CALL ChartController::getViewData() @@ -1641,13 +1643,13 @@ void ChartController::impl_initializeAccessible( AccessibleChartView& rAccChartV { SolarMutexGuard aGuard; - uno::Reference< XAccessible > xParent; + rtl::Reference pAccParent; ChartWindow* pChartWindow = GetChartWindow(); if( pChartWindow ) - xParent.set(pChartWindow->GetAccessibleParent()); + pAccParent = pChartWindow->GetAccessibleParent(); - rAccChartView.initialize(*this, getChartModel(), m_xChartView, xParent, pChartWindow); + rAccChartView.initialize(*this, getChartModel(), m_xChartView, pAccParent, pChartWindow); } #else void ChartController::impl_initializeAccessible( AccessibleChartView& /* rAccChartView */) {} diff --git a/chart2/source/controller/main/ChartController_Window.cxx b/chart2/source/controller/main/ChartController_Window.cxx index 3ef1b08e9ca1..e08d57adb3b6 100644 --- a/chart2/source/controller/main/ChartController_Window.cxx +++ b/chart2/source/controller/main/ChartController_Window.cxx @@ -78,7 +78,6 @@ #include #include #include -#include #include #include #include @@ -100,6 +99,11 @@ using ::com::sun::star::uno::Reference; namespace chart { +constexpr int DEFAULT_CHART_VIEW_WIDTH = 1000; +constexpr int DEFAULT_CHART_VIEW_HEIGHT = 1000; +constexpr int DEFAULT_CAPTION_WIDTH = 2268; +constexpr int DEFAULT_CAPTION_HEIGHT = 1134; + namespace { bool lcl_GrowAndShiftLogic( @@ -418,7 +422,7 @@ void ChartController::execute_Paint(vcl::RenderContext& rRenderContext, const to //better performance for big data if (m_xChartView.is()) { - awt::Size aResolution(1000, 1000); + awt::Size aResolution( DEFAULT_CHART_VIEW_WIDTH, DEFAULT_CHART_VIEW_HEIGHT ); { SolarMutexGuard aGuard; auto pChartWindow(GetChartWindow()); @@ -587,7 +591,7 @@ void ChartController::execute_MouseButtonDown( const MouseEvent& rMEvt ) { if ( pDrawViewWrapper->GetCurrentObjIdentifier() == SdrObjKind::Caption ) { - Size aCaptionSize( 2268, 1134 ); + Size aCaptionSize( DEFAULT_CAPTION_WIDTH, DEFAULT_CAPTION_HEIGHT ); pDrawViewWrapper->BegCreateCaptionObj( aMPos, aCaptionSize ); } else @@ -884,7 +888,7 @@ void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt ) void ChartController::execute_DoubleClick( const Point* pMousePixel, bool &bEditText ) { const SfxViewShell* pViewShell = SfxViewShell::Current(); - bool notAllowed = pViewShell && (pViewShell->isLOKMobilePhone() || pViewShell->IsLokReadOnlyView()); + bool notAllowed = pViewShell && (pViewShell->IsLokReadOnlyView()); if (notAllowed) return; diff --git a/chart2/source/controller/main/CommandDispatchContainer.cxx b/chart2/source/controller/main/CommandDispatchContainer.cxx index b1adafced570..4a945945d844 100644 --- a/chart2/source/controller/main/CommandDispatchContainer.cxx +++ b/chart2/source/controller/main/CommandDispatchContainer.cxx @@ -54,7 +54,7 @@ CommandDispatchContainer::~CommandDispatchContainer() = default; void CommandDispatchContainer::setModel( const rtl::Reference<::chart::ChartModel> & xModel ) { - // remove all existing dispatcher that base on the old model + // remove all existing dispatchers that are based on the old model m_aCachedDispatches.clear(); DisposeHelper::DisposeAllElements( m_aToBeDisposedDispatches ); m_aToBeDisposedDispatches.clear(); @@ -65,7 +65,7 @@ void CommandDispatchContainer::setChartDispatch( const rtl::Reference< ControllerCommandDispatch >& rChartDispatch, const o3tl::sorted_vector< std::u16string_view > & rChartCommands ) { - OSL_ENSURE(rChartDispatch.is(),"Invalid fall back dispatcher!"); + OSL_ENSURE(rChartDispatch.is(),"Invalid fallback dispatcher!"); m_xChartDispatcher = rChartDispatch; m_aAdditionalChartCommands = rChartCommands; m_aToBeDisposedDispatches.push_back( m_xChartDispatcher ); @@ -126,9 +126,9 @@ Reference< frame::XDispatch > CommandDispatchContainer::getDispatchForURL( return cacheIt(m_xChartDispatcher); // #i12587# support for shapes in chart - // Note, that the chart dispatcher must be queried first, because - // the chart dispatcher is the default dispatcher for all context - // sensitive commands. + // Note that the chart dispatcher must be queried first, because + // the chart dispatcher is the default dispatcher for all + // context-sensitive commands. if (m_pDrawCommandDispatch && m_pDrawCommandDispatch->isFeatureSupported(rURL.Complete)) return cacheIt(m_pDrawCommandDispatch); diff --git a/chart2/source/controller/main/ElementSelector.cxx b/chart2/source/controller/main/ElementSelector.cxx index 7839e180150e..e6550c6aea03 100644 --- a/chart2/source/controller/main/ElementSelector.cxx +++ b/chart2/source/controller/main/ElementSelector.cxx @@ -33,7 +33,7 @@ #include #include #include -#include +#include namespace chart { diff --git a/chart2/source/controller/main/ObjectHierarchy.cxx b/chart2/source/controller/main/ObjectHierarchy.cxx index 182b8328a589..186e868e92fd 100644 --- a/chart2/source/controller/main/ObjectHierarchy.cxx +++ b/chart2/source/controller/main/ObjectHierarchy.cxx @@ -136,14 +136,14 @@ void ObjectHierarchy::createTree( const rtl::Reference<::chart::ChartModel>& xCh if( xDiagram.is()) { - // Sub Title. Note: This is interpreted of being top level + // Sub Title. Note: This is interpreted as being top level Reference< XTitle > xSubTitle( xDiagram->getTitleObject()); if( xSubTitle.is()) aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xChartDocument ) ); if( !m_bOrderingForElementSelector ) { - // Axis Titles. Note: These are interpreted of being top level + // Axis Titles. Note: These are interpreted as being top level const std::vector< rtl::Reference< Axis > > aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram ); for( rtl::Reference< Axis > const & axis : aAxes ) lcl_addAxisTitle( axis, aTopLevelContainer, xChartDocument ); @@ -392,7 +392,7 @@ void ObjectHierarchy::createDataSeriesTree( } // Data Points - // iterate over child shapes of legend and search for matching CIDs + // iterate over child shapes of series and search for matching CIDs if( m_pExplicitValueProvider ) { rtl::Reference< SvxShapeGroupAnyD > xSeriesShapeContainer = diff --git a/chart2/source/controller/main/ShapeController.cxx b/chart2/source/controller/main/ShapeController.cxx index e60b1f728f3a..8c1fbc24fb72 100644 --- a/chart2/source/controller/main/ShapeController.cxx +++ b/chart2/source/controller/main/ShapeController.cxx @@ -541,9 +541,9 @@ void ShapeController::executeDispatch_ParagraphDialog() SfxItemSet aAttr( rPool ); pDrawViewWrapper->GetAttributes( aAttr ); - SfxItemSetFixed< + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet< EE_ITEMS_START, EE_ITEMS_END, - SID_ATTR_PARA_PAGEBREAK, SID_ATTR_PARA_WIDOWS> aNewAttr(rPool); + SID_ATTR_PARA_PAGEBREAK, SID_ATTR_PARA_WIDOWS> (rPool)); aNewAttr.Put( aAttr ); aNewAttr.Put( SvxHyphenZoneItem( false, SID_ATTR_PARA_HYPHENZONE ) ); aNewAttr.Put( SvxFormatBreakItem( SvxBreak::NONE, SID_ATTR_PARA_PAGEBREAK ) ); diff --git a/chart2/source/controller/main/UndoGuard.cxx b/chart2/source/controller/main/UndoGuard.cxx index 4e870c36d07d..f6cdd6d431ea 100644 --- a/chart2/source/controller/main/UndoGuard.cxx +++ b/chart2/source/controller/main/UndoGuard.cxx @@ -58,7 +58,7 @@ void UndoGuard::commit() try { const Reference< document::XUndoAction > xAction( new impl::UndoElement( m_aUndoString, m_xChartModel, m_pDocumentSnapshot ) ); - m_pDocumentSnapshot.reset(); // don't dispose, it's data went over to the UndoElement + m_pDocumentSnapshot.reset(); // don't dispose, its data went over to the UndoElement m_xUndoManager->addUndoAction( xAction ); } catch( const uno::Exception& ) diff --git a/chart2/source/controller/sidebar/Chart2PanelFactory.cxx b/chart2/source/controller/sidebar/Chart2PanelFactory.cxx index e545b9c277ae..34b26fd21375 100644 --- a/chart2/source/controller/sidebar/Chart2PanelFactory.cxx +++ b/chart2/source/controller/sidebar/Chart2PanelFactory.cxx @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "ChartElementsPanel.hxx" #include "ChartTypePanel.hxx" diff --git a/chart2/source/controller/sidebar/ChartAxisPanel.cxx b/chart2/source/controller/sidebar/ChartAxisPanel.cxx index 387f6b18dff9..f637b885ff7b 100644 --- a/chart2/source/controller/sidebar/ChartAxisPanel.cxx +++ b/chart2/source/controller/sidebar/ChartAxisPanel.cxx @@ -20,14 +20,18 @@ #include #include +#include #include #include #include +#include +#include +#include #include "ChartAxisPanel.hxx" #include #include -#include +#include using namespace css; using namespace css::uno; @@ -196,6 +200,18 @@ double getAxisRotation(const rtl::Reference<::chart::ChartModel>& xModel, return nVal; } +rtl::Reference<::chart::ChartType> getHistogramChartType( + const rtl::Reference<::chart::ChartModel>& xModel, std::u16string_view rCID) +{ + if (!xModel.is()) + { + return nullptr; + } + + return AxisHelper::getHistogramChartTypeOfAxis(ObjectIdentifier::getAxisForCID(rCID, xModel), + xModel); +} + } ChartAxisPanel::ChartAxisPanel( @@ -207,10 +223,21 @@ ChartAxisPanel::ChartAxisPanel( , mxLBLabelPos(m_xBuilder->weld_combo_box(u"comboboxtext_label_position"_ustr)) , mxGridLabel(m_xBuilder->weld_widget(u"label_props"_ustr)) , mxNFRotation(m_xBuilder->weld_metric_spin_button(u"spinbutton1"_ustr, FieldUnit::DEGREE)) + , mxBxHistogramBinning(m_xBuilder->weld_widget(u"boxHISTOGRAM_BINNING"_ustr)) + , mxRBHistogramAutomatic(m_xBuilder->weld_radio_button(u"RB_HISTOGRAM_AUTOMATIC"_ustr)) + , mxRBHistogramBinWidth(m_xBuilder->weld_radio_button(u"RB_HISTOGRAM_BIN_WIDTH"_ustr)) + , mxHistogramBinWidth(m_xBuilder->weld_formatted_spin_button(u"EDT_HISTOGRAM_BIN_WIDTH"_ustr)) + , mxRBHistogramBinCount(m_xBuilder->weld_radio_button(u"RB_HISTOGRAM_BIN_COUNT"_ustr)) + , mxHistogramBinCount(m_xBuilder->weld_spin_button(u"MT_HISTOGRAM_BIN_COUNT"_ustr)) + , mxCBHistogramOverflow(m_xBuilder->weld_check_button(u"CBX_HISTOGRAM_OVERFLOW"_ustr)) + , mxHistogramOverflow(m_xBuilder->weld_formatted_spin_button(u"EDT_HISTOGRAM_OVERFLOW"_ustr)) + , mxCBHistogramUnderflow(m_xBuilder->weld_check_button(u"CBX_HISTOGRAM_UNDERFLOW"_ustr)) + , mxHistogramUnderflow(m_xBuilder->weld_formatted_spin_button(u"EDT_HISTOGRAM_UNDERFLOW"_ustr)) , mxModel(pController->getChartModel()) , mxModifyListener(new ChartSidebarModifyListener(this)) , mxSelectionListener(new ChartSidebarSelectionListener(this, OBJECTTYPE_AXIS)) , mbModelValid(true) + , mbUpdating(false) { Initialize(); } @@ -236,6 +263,13 @@ void ChartAxisPanel::Initialize() if (xSelectionSupplier.is()) xSelectionSupplier->addSelectionChangeListener(mxSelectionListener); + for (weld::FormattedSpinButton* pField : { mxHistogramBinWidth.get(), mxHistogramOverflow.get(), + mxHistogramUnderflow.get() }) + { + pField->GetFormatter().ClearMinValue(); + pField->GetFormatter().ClearMaxValue(); + } + updateData(); Link aLink = LINK(this, ChartAxisPanel, CheckBoxHdl); @@ -246,6 +280,19 @@ void ChartAxisPanel::Initialize() mxNFRotation->connect_value_changed(aSpinButtonLink); mxLBLabelPos->connect_changed(LINK(this, ChartAxisPanel, ListBoxHdl)); + + Link aHistogramToggle = LINK(this, ChartAxisPanel, HistogramToggleHdl); + mxRBHistogramAutomatic->connect_toggled(aHistogramToggle); + mxRBHistogramBinWidth->connect_toggled(aHistogramToggle); + mxRBHistogramBinCount->connect_toggled(aHistogramToggle); + mxCBHistogramOverflow->connect_toggled(aHistogramToggle); + mxCBHistogramUnderflow->connect_toggled(aHistogramToggle); + + Link aHistogramValue = LINK(this, ChartAxisPanel, HistogramValueHdl); + mxHistogramBinWidth->connect_value_changed(aHistogramValue); + mxHistogramOverflow->connect_value_changed(aHistogramValue); + mxHistogramUnderflow->connect_value_changed(aHistogramValue); + mxHistogramBinCount->connect_value_changed(LINK(this, ChartAxisPanel, HistogramBinCountHdl)); } void ChartAxisPanel::updateData() @@ -260,11 +307,50 @@ void ChartAxisPanel::updateData() SolarMutexGuard aGuard; + mbUpdating = true; + const comphelper::ScopeGuard aUpdateGuard([this]() { mbUpdating = false; }); + mxCBShowLabel->set_active(isLabelShown(mxModel, aCID)); mxCBReverse->set_active(isReverse(mxModel, aCID)); mxLBLabelPos->set_active(getLabelPosition(mxModel, aCID)); mxNFRotation->set_value(getAxisRotation(mxModel, aCID), FieldUnit::DEGREE); + + rtl::Reference<::chart::ChartType> xHistogramType = getHistogramChartType(mxModel, aCID); + mxBxHistogramBinning->set_visible(xHistogramType.is()); + + if (!xHistogramType.is()) + { + return; + } + + sal_Int32 nFrequencyType = 0; + double fBinWidth = 0.0; + sal_Int32 nBinCount = 1; + bool bUseOverflow = false; + double fOverflow = 0.0; + bool bUseUnderflow = false; + double fUnderflow = 0.0; + + xHistogramType->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType; + xHistogramType->getPropertyValue(u"BinWidth"_ustr) >>= fBinWidth; + xHistogramType->getPropertyValue(u"BinCount"_ustr) >>= nBinCount; + xHistogramType->getPropertyValue(u"UseOverflowBin"_ustr) >>= bUseOverflow; + xHistogramType->getPropertyValue(u"OverflowBinValue"_ustr) >>= fOverflow; + xHistogramType->getPropertyValue(u"UseUnderflowBin"_ustr) >>= bUseUnderflow; + xHistogramType->getPropertyValue(u"UnderflowBinValue"_ustr) >>= fUnderflow; + + mxRBHistogramAutomatic->set_active(nFrequencyType != 1 && nFrequencyType != 2); + mxRBHistogramBinWidth->set_active(nFrequencyType == 1); + mxRBHistogramBinCount->set_active(nFrequencyType == 2); + mxHistogramBinWidth->GetFormatter().SetValue(fBinWidth); + mxHistogramBinCount->set_value(nBinCount); + mxCBHistogramOverflow->set_active(bUseOverflow); + mxHistogramOverflow->GetFormatter().SetValue(fOverflow); + mxCBHistogramUnderflow->set_active(bUseUnderflow); + mxHistogramUnderflow->GetFormatter().SetValue(fUnderflow); + + updateHistogramControlSensitivity(); } std::unique_ptr ChartAxisPanel::Create ( @@ -326,6 +412,14 @@ void ChartAxisPanel::doUpdateModel(const rtl::Reference<::chart::ChartModel>& xM xSelectionSupplier->addSelectionChangeListener(mxSelectionListener); } +void ChartAxisPanel::updateHistogramControlSensitivity() +{ + mxHistogramBinWidth->set_sensitive(mxRBHistogramBinWidth->get_active()); + mxHistogramBinCount->set_sensitive(mxRBHistogramBinCount->get_active()); + mxHistogramOverflow->set_sensitive(mxCBHistogramOverflow->get_active()); + mxHistogramUnderflow->set_sensitive(mxCBHistogramUnderflow->get_active()); +} + void ChartAxisPanel::updateModel(css::uno::Reference xModel) { ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get()); @@ -368,6 +462,107 @@ IMPL_LINK(ChartAxisPanel, TextRotationHdl, weld::MetricSpinButton&, rMetricField setAxisRotation(mxModel, aCID, nVal); } +IMPL_LINK(ChartAxisPanel, HistogramToggleHdl, weld::Toggleable&, rToggle, void) +{ + if (mbUpdating) + { + return; + } + + rtl::Reference<::chart::ChartType> xHistogramType = getHistogramChartType(mxModel, getCID(mxModel)); + if (!xHistogramType.is()) + { + return; + } + + updateHistogramControlSensitivity(); + + if (&rToggle == mxRBHistogramAutomatic.get() && rToggle.get_active()) + { + xHistogramType->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(0))); + } + else if (&rToggle == mxRBHistogramBinWidth.get() && rToggle.get_active()) + { + xHistogramType->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(1))); + } + else if (&rToggle == mxRBHistogramBinCount.get() && rToggle.get_active()) + { + xHistogramType->setPropertyValue(u"FrequencyType"_ustr, uno::Any(sal_Int32(2))); + } + else if (&rToggle == mxCBHistogramOverflow.get()) + { + xHistogramType->setPropertyValue(u"UseOverflowBin"_ustr, uno::Any(rToggle.get_active())); + } + else if (&rToggle == mxCBHistogramUnderflow.get()) + { + xHistogramType->setPropertyValue(u"UseUnderflowBin"_ustr, uno::Any(rToggle.get_active())); + } +} + +IMPL_LINK(ChartAxisPanel, HistogramValueHdl, weld::FormattedSpinButton&, rField, void) +{ + if (mbUpdating) + { + return; + } + + rtl::Reference<::chart::ChartType> xHistogramType = getHistogramChartType(mxModel, getCID(mxModel)); + if (!xHistogramType.is()) + { + return; + } + + const double fValue = rField.GetFormatter().GetValue(); + + // While both special bins are on, the underflow boundary has to stay below the overflow + // one. A pair that crosses is dropped when the bins are computed, so the edit is refused + // here and the field goes back to the value the model holds. + const bool bBothSpecialBins + = mxCBHistogramUnderflow->get_active() && mxCBHistogramOverflow->get_active(); + + if (&rField == mxHistogramBinWidth.get()) + { + if (fValue <= 0.0) + { + updateData(); + return; + } + xHistogramType->setPropertyValue(u"BinWidth"_ustr, uno::Any(fValue)); + } + else if (&rField == mxHistogramOverflow.get()) + { + if (bBothSpecialBins && mxHistogramUnderflow->GetFormatter().GetValue() >= fValue) + { + updateData(); + return; + } + xHistogramType->setPropertyValue(u"OverflowBinValue"_ustr, uno::Any(fValue)); + } + else if (&rField == mxHistogramUnderflow.get()) + { + if (bBothSpecialBins && fValue >= mxHistogramOverflow->GetFormatter().GetValue()) + { + updateData(); + return; + } + xHistogramType->setPropertyValue(u"UnderflowBinValue"_ustr, uno::Any(fValue)); + } +} + +IMPL_LINK(ChartAxisPanel, HistogramBinCountHdl, weld::SpinButton&, rField, void) +{ + if (mbUpdating || rField.get_value() <= 0) + { + return; + } + + rtl::Reference<::chart::ChartType> xHistogramType = getHistogramChartType(mxModel, getCID(mxModel)); + if (xHistogramType.is()) + { + xHistogramType->setPropertyValue(u"BinCount"_ustr, uno::Any(sal_Int32(rField.get_value()))); + } +} + } // end of namespace ::chart::sidebar /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/sidebar/ChartAxisPanel.hxx b/chart2/source/controller/sidebar/ChartAxisPanel.hxx index f655526d3b85..cc8c120ee4c9 100644 --- a/chart2/source/controller/sidebar/ChartAxisPanel.hxx +++ b/chart2/source/controller/sidebar/ChartAxisPanel.hxx @@ -14,8 +14,11 @@ #include #include #include +#include #include +#include #include +#include #include "ChartSidebarModifyListener.hxx" #include "ChartSidebarSelectionListener.hxx" @@ -76,18 +79,35 @@ private: std::unique_ptr mxGridLabel; std::unique_ptr mxNFRotation; + std::unique_ptr mxBxHistogramBinning; + std::unique_ptr mxRBHistogramAutomatic; + std::unique_ptr mxRBHistogramBinWidth; + std::unique_ptr mxHistogramBinWidth; + std::unique_ptr mxRBHistogramBinCount; + std::unique_ptr mxHistogramBinCount; + std::unique_ptr mxCBHistogramOverflow; + std::unique_ptr mxHistogramOverflow; + std::unique_ptr mxCBHistogramUnderflow; + std::unique_ptr mxHistogramUnderflow; + rtl::Reference<::chart::ChartModel> mxModel; css::uno::Reference mxModifyListener; css::uno::Reference mxSelectionListener; bool mbModelValid; + // True while the panel is writing widget values from the model. + bool mbUpdating; void Initialize(); void doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel); + void updateHistogramControlSensitivity(); DECL_LINK(CheckBoxHdl, weld::Toggleable&, void); DECL_LINK(ListBoxHdl, weld::ComboBox&, void); DECL_LINK(TextRotationHdl, weld::MetricSpinButton&, void); + DECL_LINK(HistogramToggleHdl, weld::Toggleable&, void); + DECL_LINK(HistogramValueHdl, weld::FormattedSpinButton&, void); + DECL_LINK(HistogramBinCountHdl, weld::SpinButton&, void); }; } } // end of namespace ::chart::sidebar diff --git a/chart2/source/controller/sidebar/ChartColorPaletteControl.cxx b/chart2/source/controller/sidebar/ChartColorPaletteControl.cxx index 1f2a8c2e2d44..511fe9fe3125 100644 --- a/chart2/source/controller/sidebar/ChartColorPaletteControl.cxx +++ b/chart2/source/controller/sidebar/ChartColorPaletteControl.cxx @@ -18,11 +18,13 @@ */ #include +#include #include #include #include #include #include +#include #include #include "ChartColorPaletteControl.hxx" @@ -161,7 +163,7 @@ void ChartColorPaletteControl::renderSelectedColorPalette(const VclPtrgetColorPalette(getColorPaletteType(), getColorPaletteIndex()); - ChartColorPaletteHelper::renderColorPalette(pDev, aDrawArea, aColorPalette, true); + ChartColorPaletteHelper::renderColorPalette(*pDev, aDrawArea, aColorPalette, true); } void ChartColorPaletteControl::setColorPaletteHandler( @@ -360,28 +362,30 @@ ChartColorPalettePopup::SelectPaletteHdl(const std::unique_ptr(-1); } -IMPL_LINK_NOARG(ChartColorPalettePopup, ColorfulMouseMoveHdl, const MouseEvent&, bool) +IMPL_LINK(ChartColorPalettePopup, ColorfulMouseMoveHdl, const OUString&, rHighlightedId, bool) { - MouseMoveHdl(mxColorfulPalettes, ChartColorPaletteType::Colorful); + MouseMoveHdl(*mxColorfulPalettes, ChartColorPaletteType::Colorful, rHighlightedId); return true; } -IMPL_LINK_NOARG(ChartColorPalettePopup, MonoMouseMoveHdl, const MouseEvent&, bool) +IMPL_LINK(ChartColorPalettePopup, MonoMouseMoveHdl, const OUString&, rHighlightedId, bool) { - MouseMoveHdl(mxMonoPalettes, ChartColorPaletteType::Monochromatic); + MouseMoveHdl(*mxMonoPalettes, ChartColorPaletteType::Monochromatic, rHighlightedId); return true; } -void ChartColorPalettePopup::MouseMoveHdl(const std::unique_ptr& xPalettes, - const ChartColorPaletteType eHlItemType) +void ChartColorPalettePopup::MouseMoveHdl(ChartColorPalettes& rPalettes, + const ChartColorPaletteType eHlItemType, + std::u16string_view sHighlightedId) { - const sal_uInt16 nHlId = xPalettes->GetHighlightedItemId(); + const sal_uInt16 nHlId + = sHighlightedId.empty() ? 0 : static_cast(o3tl::toUInt32(sHighlightedId)); if (eHlItemType == meHighlightedItemType && nHlId == mnHighlightedItemId) return; if (nHlId > 0) { - if (const ChartColorPalette* pPalette = xPalettes->getPalette(nHlId - 1)) + if (const ChartColorPalette* pPalette = rPalettes.getPalette(nHlId - 1)) { mxControl->applyColorPalette(pPalette); } diff --git a/chart2/source/controller/sidebar/ChartColorPaletteControl.hxx b/chart2/source/controller/sidebar/ChartColorPaletteControl.hxx index e0c25be3ef47..47a0304445a9 100644 --- a/chart2/source/controller/sidebar/ChartColorPaletteControl.hxx +++ b/chart2/source/controller/sidebar/ChartColorPaletteControl.hxx @@ -88,10 +88,10 @@ class ChartColorPalettePopup final : public WeldToolbarPopup DECL_LINK(SelectMonoPaletteHdl, const weld::TreeIter&, bool); sal_uInt32 SelectPaletteHdl(const std::unique_ptr& xPalettes); - DECL_LINK(ColorfulMouseMoveHdl, const MouseEvent&, bool); - DECL_LINK(MonoMouseMoveHdl, const MouseEvent&, bool); - void MouseMoveHdl(const std::unique_ptr& xPalettes, - ChartColorPaletteType eHlItemType); + DECL_LINK(ColorfulMouseMoveHdl, const OUString&, bool); + DECL_LINK(MonoMouseMoveHdl, const OUString&, bool); + void MouseMoveHdl(ChartColorPalettes& rPalettes, ChartColorPaletteType eHlItemType, + std::u16string_view sHighlightedId); void GrabFocus() override; diff --git a/chart2/source/controller/sidebar/ChartElementsPanel.cxx b/chart2/source/controller/sidebar/ChartElementsPanel.cxx index 6a7ff5df12e2..b36d720e8382 100644 --- a/chart2/source/controller/sidebar/ChartElementsPanel.cxx +++ b/chart2/source/controller/sidebar/ChartElementsPanel.cxx @@ -396,7 +396,7 @@ void ChartElementsPanel::Initialize() mxLBLegendPosition->connect_changed(LINK(this, ChartElementsPanel, LegendPosHdl)); - Link aEditLink = LINK(this, ChartElementsPanel, EditHdl); + Link aEditLink = LINK(this, ChartElementsPanel, EditHdl); mxEditTitle->connect_changed(aEditLink); mxEditSubtitle->connect_changed(aEditLink); } @@ -625,7 +625,7 @@ IMPL_LINK(ChartElementsPanel, CheckBoxHdl, weld::Toggleable&, rCheckBox, void) updateData(); } -IMPL_LINK(ChartElementsPanel, EditHdl, weld::Entry&, rEdit, void) +IMPL_LINK(ChartElementsPanel, EditHdl, weld::TextWidget&, rEdit, void) { // title or subtitle? TitleHelper::eTitleType aTitleType = TitleHelper::MAIN_TITLE; diff --git a/chart2/source/controller/sidebar/ChartElementsPanel.hxx b/chart2/source/controller/sidebar/ChartElementsPanel.hxx index 3a4f735d674a..d15a15ad9459 100644 --- a/chart2/source/controller/sidebar/ChartElementsPanel.hxx +++ b/chart2/source/controller/sidebar/ChartElementsPanel.hxx @@ -22,8 +22,10 @@ #include #include #include +#include #include #include +#include #include "ChartSidebarModifyListener.hxx" #include @@ -109,7 +111,7 @@ private: void setTitleVisible(TitleHelper::eTitleType eTitle, bool bVisible); DECL_LINK(CheckBoxHdl, weld::Toggleable&, void); - DECL_LINK(EditHdl, weld::Entry&, void); + DECL_LINK(EditHdl, weld::TextWidget&, void); DECL_LINK(LegendPosHdl, weld::ComboBox&, void); }; diff --git a/chart2/source/controller/sidebar/ChartErrorBarPanel.hxx b/chart2/source/controller/sidebar/ChartErrorBarPanel.hxx index 38b76ff28eba..0faf5bb545c8 100644 --- a/chart2/source/controller/sidebar/ChartErrorBarPanel.hxx +++ b/chart2/source/controller/sidebar/ChartErrorBarPanel.hxx @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "ChartSidebarModifyListener.hxx" diff --git a/chart2/source/controller/sidebar/ChartSeriesPanel.hxx b/chart2/source/controller/sidebar/ChartSeriesPanel.hxx index dcc71ec06c78..627116458a07 100644 --- a/chart2/source/controller/sidebar/ChartSeriesPanel.hxx +++ b/chart2/source/controller/sidebar/ChartSeriesPanel.hxx @@ -22,7 +22,10 @@ #include #include #include +#include #include +#include +#include #include "ChartSidebarModifyListener.hxx" #include "ChartSidebarSelectionListener.hxx" diff --git a/chart2/source/inc/AxisHelper.hxx b/chart2/source/inc/AxisHelper.hxx index 288b9a0d2026..a4845ca4ac6d 100644 --- a/chart2/source/inc/AxisHelper.hxx +++ b/chart2/source/inc/AxisHelper.hxx @@ -191,6 +191,12 @@ public: getChartTypeByIndex( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys, sal_Int32 nIndex ); + /** The histogram chart type the given axis carries the bin settings for, or an empty + reference when the axis is not the primary X axis of a histogram chart. */ + static rtl::Reference<::chart::ChartType> + getHistogramChartTypeOfAxis(const rtl::Reference<::chart::Axis>& xAxis, + const rtl::Reference<::chart::ChartModel>& xChartDoc); + static void setRTLAxisLayout( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys ); static rtl::Reference< ::chart::ChartType > diff --git a/chart2/source/inc/CachedDataSequence.hxx b/chart2/source/inc/CachedDataSequence.hxx index 513907c2429d..93aa5ae61057 100644 --- a/chart2/source/inc/CachedDataSequence.hxx +++ b/chart2/source/inc/CachedDataSequence.hxx @@ -19,10 +19,7 @@ #pragma once // helper classes -#include -#include -#include -#include +#include // interfaces and types #include @@ -37,27 +34,22 @@ namespace com::sun::star::uno { class XComponentContext; } namespace chart { - -namespace impl -{ -typedef ::comphelper::WeakComponentImplHelper< - css::chart2::data::XDataSequence, - css::chart2::data::XNumericalDataSequence, - css::chart2::data::XTextualDataSequence, - css::util::XCloneable, - css::util::XModifyBroadcaster, - css::lang::XInitialization, - css::lang::XServiceInfo > - CachedDataSequence_Base; -} +using CachedDataSequence_Base = comphelper::OPropertyContainerImplHelper< + comphelper::WeakComponentImplHelper< + css::chart2::data::XDataSequence, + css::chart2::data::XNumericalDataSequence, + css::chart2::data::XTextualDataSequence, + css::util::XCloneable, + css::util::XModifyBroadcaster, + css::lang::XInitialization, + css::lang::XServiceInfo>, + class CachedDataSequence>; /** * This sequence object does store actual values within, hence "cached". */ -class CachedDataSequence final : - public ::comphelper::OPropertyContainer2, - public ::comphelper::OPropertyArrayUsageHelper< CachedDataSequence >, - public impl::CachedDataSequence_Base +class CachedDataSequence final + : public CachedDataSequence_Base { public: /** constructs an empty sequence @@ -81,17 +73,7 @@ public: virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; - /// merge XInterface implementations - DECLARE_XINTERFACE() - /// merge XTypeProvider implementations - DECLARE_XTYPEPROVIDER() - private: - // ____ XPropertySet ____ - /// @see css::beans::XPropertySet - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override; - /// @see ::comphelper::OPropertySetHelper - virtual ::cppu::IPropertyArrayHelper& getInfoHelper() override; /// @see ::comphelper::OPropertyArrayUsageHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override; diff --git a/chart2/source/inc/ChartColorPaletteHelper.hxx b/chart2/source/inc/ChartColorPaletteHelper.hxx index 073559a77332..4fc370b6e463 100644 --- a/chart2/source/inc/ChartColorPaletteHelper.hxx +++ b/chart2/source/inc/ChartColorPaletteHelper.hxx @@ -26,7 +26,7 @@ public: explicit ChartColorPaletteHelper(const std::shared_ptr& pTheme); ChartColorPalette getColorPalette(ChartColorPaletteType eType, sal_uInt32 nIndex) const; - static void renderColorPalette(OutputDevice* pDev, const tools::Rectangle& rDrawArea, + static void renderColorPalette(OutputDevice& rDev, const tools::Rectangle& rDrawArea, const ChartColorPalette& rColorSet, bool bDrawItemBorder = false); static void renderNoPalette(OutputDevice* pDev, const tools::Rectangle& rDrawArea); diff --git a/chart2/source/inc/ChartColorPalettes.hxx b/chart2/source/inc/ChartColorPalettes.hxx index 35e96e1bfca7..91004c01892b 100644 --- a/chart2/source/inc/ChartColorPalettes.hxx +++ b/chart2/source/inc/ChartColorPalettes.hxx @@ -23,21 +23,16 @@ namespace chart { class ChartColorPalettes final { -public: - typedef Link MouseEventHandler; - private: std::unique_ptr mxIconView; std::unique_ptr mxWindow; std::vector maColorSets; - sal_uInt16 mnHighlightedItemId; - MouseEventHandler maMouseMoveHdl; + Link maMouseMoveHdl; public: ChartColorPalettes(weld::Builder& rBuilder, const OUString& id, const OUString& winId); sal_uInt16 GetSelectedItemId(); - sal_uInt16 GetHighlightedItemId(); void SetSelectHdl(const Link& rLink); void SetNoSelection(); void SelectItem(sal_uInt16 nItemId); @@ -46,12 +41,11 @@ public: void insert(ChartColorPalette const& rColorSet); const ChartColorPalette* getPalette(sal_uInt32 nItem) const; - void setMouseMoveHdl(const MouseEventHandler& rLink); + void setMouseMoveHdl(const Link& rLink); void Fill(); private: - DECL_LINK(OnQueryTooltip, const weld::TreeIter&, OUString); DECL_LINK(OnMouseMove, const MouseEvent&, bool); }; diff --git a/chart2/source/inc/ChartResourceGroupDlgs.hxx b/chart2/source/inc/ChartResourceGroupDlgs.hxx index 0335e5f51179..7f86553bf966 100644 --- a/chart2/source/inc/ChartResourceGroupDlgs.hxx +++ b/chart2/source/inc/ChartResourceGroupDlgs.hxx @@ -21,8 +21,10 @@ #include #include +#include +#include #include -#include +#include namespace chart { diff --git a/chart2/source/inc/ChartResourceGroups.hxx b/chart2/source/inc/ChartResourceGroups.hxx index 18a1301ccf9e..f8ca543eea92 100644 --- a/chart2/source/inc/ChartResourceGroups.hxx +++ b/chart2/source/inc/ChartResourceGroups.hxx @@ -24,6 +24,9 @@ #include "ChartTypeDialogController.hxx" #include "ChartResourceGroupDlgs.hxx" +#include +#include + namespace chart { class SplinePropertiesDialog; diff --git a/chart2/source/inc/ChartType.hxx b/chart2/source/inc/ChartType.hxx index b9e5d625c719..2ae78395e30e 100644 --- a/chart2/source/inc/ChartType.hxx +++ b/chart2/source/inc/ChartType.hxx @@ -114,7 +114,7 @@ public: virtual rtl::Reference< ::chart::BaseCoordinateSystem > createCoordinateSystem2( sal_Int32 DimensionCount ); - static void createCalculatedDataSeries(); + virtual void createCalculatedDataSeries(); void deleteSeries( const rtl::Reference< ::chart::DataSeries > & xSeries ); diff --git a/chart2/source/inc/ChartTypeDialogController.hxx b/chart2/source/inc/ChartTypeDialogController.hxx index 33e4bcdfe8ad..8343ac9b81b6 100644 --- a/chart2/source/inc/ChartTypeDialogController.hxx +++ b/chart2/source/inc/ChartTypeDialogController.hxx @@ -28,8 +28,8 @@ #include #include +#include #include -#include namespace com::sun::star::beans { @@ -175,6 +175,20 @@ public: const ChartTypeParameter& rParameter) override; }; +class HistogramChartDialogController final : public ChartTypeDialogController +{ +public: + HistogramChartDialogController(); + virtual ~HistogramChartDialogController() override; + + virtual OUString getName() override; + virtual OUString getImage() override; + virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override; + virtual void fillSubTypeList(ValueSet& rSubTypeList, + const ChartTypeParameter& rParameter) override; + virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override; +}; + class PieChartDialogController final : public ChartTypeDialogController { public: @@ -334,6 +348,20 @@ private: std::unique_ptr m_xMF_NumberOfLines; }; +class CorrelationCircleChartDialogController final : public ChartTypeDialogController +{ +public: + CorrelationCircleChartDialogController(); + virtual ~CorrelationCircleChartDialogController() override; + + virtual OUString getName() override; + virtual OUString getImage() override; + virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override; + virtual void fillSubTypeList(ValueSet& rSubTypeList, + const ChartTypeParameter& rParameter) override; + virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override; +}; + class BubbleChartDialogController final : public ChartTypeDialogController { public: diff --git a/chart2/source/inc/ChartTypeTemplate.hxx b/chart2/source/inc/ChartTypeTemplate.hxx index e90f7c306f4b..57bd42092b3d 100644 --- a/chart2/source/inc/ChartTypeTemplate.hxx +++ b/chart2/source/inc/ChartTypeTemplate.hxx @@ -159,6 +159,13 @@ public: virtual bool isSwapXAndY() const; + /** True for a template that reads the last two columns of its range as the + two dimensions its points are placed against, and every column before + them as one of the features. False for a template whose range reads the + way a reader expects without being told. + */ + virtual bool usesLastTwoColumnsAsDimensions() const; + // Methods for creating the diagram piecewise /** Allows derived classes to manipulate the diagrams whole, like changing @@ -171,7 +178,7 @@ public: /** Creates a 2d or 3d cartesian coordinate system with mathematically oriented, linear scales with auto-min/max. If the given - CoordinateSystemContainer is not empty, those coordinate system should + CoordinateSystemContainer is not empty, those coordinate systems should be reused.

The dimension depends on the value returned by getDimension().

@@ -228,9 +235,9 @@ public: compatible axes in the container these should be maintained.

As default, this method creates as many axes as there are dimensions - in the given first coordinate system. Each of the axis + in the given first coordinate system. Each of the axes represents one of the dimensions of the coordinate systems. If there are series - requesting a secondary axes a secondary y axes is added

+ requesting a secondary axis a secondary y axis is added

*/ void createAxes( const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > & rCoordSys ); diff --git a/chart2/source/inc/CorrelationCoefficient.hxx b/chart2/source/inc/CorrelationCoefficient.hxx new file mode 100644 index 000000000000..dd50d1a25bf9 --- /dev/null +++ b/chart2/source/inc/CorrelationCoefficient.hxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include +#include +#include +#include +#include + +namespace chart +{ +/** The Pearson correlation coefficient of two runs of values, paired up by + position. + + A position where either side is not a finite number counts for nothing, and + so does a position past the end of the shorter run. The answer is empty when + fewer than two positions are left, or when one of the two runs holds the + same value throughout, because then there is no coefficient to give. The + answer otherwise lies between minus one and one. + */ +inline std::optional calculateCorrelationCoefficient(std::span aFirst, + std::span aSecond) +{ + const std::size_t nLength = std::min(aFirst.size(), aSecond.size()); + + auto lclIsPair = [&aFirst, &aSecond](std::size_t nIndex) { + return std::isfinite(aFirst[nIndex]) && std::isfinite(aSecond[nIndex]); + }; + + std::size_t nCount = 0; + double fSumFirst = 0.0; + double fSumSecond = 0.0; + for (std::size_t nIndex = 0; nIndex < nLength; ++nIndex) + { + if (lclIsPair(nIndex)) + { + ++nCount; + fSumFirst += aFirst[nIndex]; + fSumSecond += aSecond[nIndex]; + } + } + + if (nCount < 2) + return {}; + + const double fMeanFirst = fSumFirst / nCount; + const double fMeanSecond = fSumSecond / nCount; + + // Subtracting the means before multiplying keeps the answer accurate for + // values that are large next to how far they spread. + double fProductSum = 0.0; + double fSquareSumFirst = 0.0; + double fSquareSumSecond = 0.0; + for (std::size_t nIndex = 0; nIndex < nLength; ++nIndex) + { + if (lclIsPair(nIndex)) + { + const double fDeltaFirst = aFirst[nIndex] - fMeanFirst; + const double fDeltaSecond = aSecond[nIndex] - fMeanSecond; + fProductSum += fDeltaFirst * fDeltaSecond; + fSquareSumFirst += fDeltaFirst * fDeltaFirst; + fSquareSumSecond += fDeltaSecond * fDeltaSecond; + } + } + + if (fSquareSumFirst <= 0.0 || fSquareSumSecond <= 0.0) + return {}; + + const double fCoefficient = fProductSum / std::sqrt(fSquareSumFirst * fSquareSumSecond); + + // Rounding can carry the division a little past one, so hold the answer + // inside the range a coefficient has. + return std::clamp(fCoefficient, -1.0, 1.0); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/inc/DataSeries.hxx b/chart2/source/inc/DataSeries.hxx index 373a50fbff85..4317051664cc 100644 --- a/chart2/source/inc/DataSeries.hxx +++ b/chart2/source/inc/DataSeries.hxx @@ -190,6 +190,12 @@ public: sal_Int32 getExplicitNumberFormatKeyForDataLabel(); + void setCalculatedYSequence(css::uno::Reference const& xSequence); + + css::uno::Reference getCalculatedYSequence() const; + + void clearCalculatedYSequence(); + private: // late initialization to call after copy-constructing @@ -220,6 +226,8 @@ private: tRegressionCurveContainerType m_aRegressionCurves; rtl::Reference m_xModifyEventForwarder; + + css::uno::Reference m_xCalculatedYSequence; }; const tPropertyValueMap & StaticDataSeriesDefaults(); diff --git a/chart2/source/inc/DataSeriesProperties.hxx b/chart2/source/inc/DataSeriesProperties.hxx index c0aa83e317b6..cf27c5db4bcc 100644 --- a/chart2/source/inc/DataSeriesProperties.hxx +++ b/chart2/source/inc/DataSeriesProperties.hxx @@ -37,7 +37,29 @@ namespace chart::DataSeriesProperties PROP_DATASERIES_DELETED_LEGEND_ENTRIES, PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES, PROP_DATASERIES_INVERT_NEGATIVE, - PROP_DATASERIES_INTERVAL_CLOSED + PROP_DATASERIES_INTERVAL_CLOSED, + PROP_DATASERIES_CONNECTOR_LINES, + PROP_DATASERIES_MEAN_LINE, + PROP_DATASERIES_MEAN_MARKER, + PROP_DATASERIES_NONOUTLIERS, + PROP_DATASERIES_OUTLIERS, + PROP_DATASERIES_PARENT_LABEL_LAYOUT, + PROP_DATASERIES_REGION_LABEL_LAYOUT, + PROP_DATASERIES_QUARTILE_METHOD, + PROP_DATASERIES_SUBTOTAL_INDICES, + PROP_DATASERIES_HAS_GEOGRAPHY, + PROP_DATASERIES_GEOGRAPHY_PROJECTION_TYPE, + PROP_DATASERIES_GEOGRAPHY_VIEWED_REGION_TYPE, + PROP_DATASERIES_GEOGRAPHY_CULTURE_LANGUAGE, + PROP_DATASERIES_GEOGRAPHY_CULTURE_REGION, + PROP_DATASERIES_GEOGRAPHY_ATTRIBUTION, + PROP_DATASERIES_GEOCACHE_PROVIDER, + PROP_DATASERIES_GEOCACHE_BINARY, + PROP_DATASERIES_GEOCACHE_CLEAR_DATA, + PROP_DATASERIES_HAS_EXPLICIT_FILL, + PROP_DATASERIES_HAS_DATA_LABELS, + PROP_DATASERIES_CHARTEX_AXIS_IDS, + PROP_DATASERIES_CHARTEX_OWNER_IDX }; void AddPropertiesToVector( diff --git a/chart2/source/inc/HistogramCalculator.hxx b/chart2/source/inc/HistogramCalculator.hxx new file mode 100644 index 000000000000..d63e36d164fc --- /dev/null +++ b/chart2/source/inc/HistogramCalculator.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace chart +{ +/** Largest number of bins a histogram is partitioned into. Higher counts are capped. */ +constexpr sal_Int32 MAX_HISTOGRAM_BINS = 10000; + +enum class HistogramBinType +{ + Normal, + Underflow, + Overflow +}; + +/** Partitions a data set into histogram bins and counts per-bin frequencies. + Binning can be automatic, by fixed bin width, or by fixed bin count. */ +class HistogramCalculator +{ + sal_Int32 mnBins = 1; + double mfBinWidth = 1.0; + + std::vector> maBinRanges; + std::vector maBinFrequencies; + std::vector maBinTypes; + +public: + HistogramCalculator(); + + // nFrequencyType: 0 = auto (Scott's Rule), 1 = fixed bin width, 2 = fixed bin count. + // fFixedBinWidth / nFixedBinCount are consulted only when their mode is selected; + // invalid values (<= 0) fall back to auto. + void computeBinFrequencyHistogram(const std::vector& dataPoints, + sal_Int32 nFrequencyType = 0, double fFixedBinWidth = 0.0, + sal_Int32 nFixedBinCount = 0, bool bUseUnderflowBin = false, + double fUnderflowBinValue = 0.0, bool bUseOverflowBin = false, + double fOverflowBinValue = 0.0); + + const std::vector>& getBinRanges() const { return maBinRanges; } + const std::vector& getBinFrequencies() const { return maBinFrequencies; } + const std::vector& getBinTypes() const { return maBinTypes; } +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/inc/HistogramDataSequence.hxx b/chart2/source/inc/HistogramDataSequence.hxx new file mode 100644 index 000000000000..192bb394b88b --- /dev/null +++ b/chart2/source/inc/HistogramDataSequence.hxx @@ -0,0 +1,134 @@ +/* -*- 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/. + */ + +#pragma once + +#include "ModifyListenerHelper.hxx" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chart +{ +class ModifyEventForwarder; + +typedef ::comphelper::WeakComponentImplHelper< + css::chart2::data::XDataSequence, css::chart2::data::XNumericalDataSequence, + css::chart2::data::XTextualDataSequence, css::util::XCloneable, css::util::XModifyBroadcaster, + css::lang::XServiceInfo, css::util::XModifyListener> + HistogramDataSequence_Base; + +/** Lazy XDataSequence that yields either bin labels or bin frequencies derived + from a raw data source. Recomputes when the source changes. */ +class HistogramDataSequence final + : public HistogramDataSequence_Base, + public ::comphelper::OMutexAndBroadcastHelper, + public ::comphelper::OPropertyContainer, + public ::comphelper::OPropertyArrayUsageHelper +{ +public: + using ::comphelper::WeakComponentImplHelperBase::disposing; + explicit HistogramDataSequence( + const css::uno::Reference& xRawData, bool bIsCategory, + sal_Int32 nFrequencyType = 0, double fBinWidth = 0.0, sal_Int32 nBinCount = 0, + bool bUseUnderflowBin = false, double fUnderflowBinValue = 0.0, + bool bUseOverflowBin = false, double fOverflowBinValue = 0.0); + virtual ~HistogramDataSequence() override; + + void setBinningParameters(sal_Int32 nFrequencyType, double fBinWidth, sal_Int32 nBinCount, + bool bUseUnderflowBin, double fUnderflowBinValue, + bool bUseOverflowBin, double fOverflowBinValue); + + /// declare XServiceInfo methods + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + + /// declare XInterface methods + DECLARE_XINTERFACE() + + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + + /// declare property methods + /// @see css::beans::XPropertySet + virtual css::uno::Reference + SAL_CALL getPropertySetInfo() override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override; + + // XDataSequence + css::uno::Sequence SAL_CALL getData() override; + OUString SAL_CALL getSourceRangeRepresentation() override; + css::uno::Sequence + SAL_CALL generateLabel(css::chart2::data::LabelOrigin nLabelOrigin) override; + sal_Int32 SAL_CALL getNumberFormatKeyByIndex(sal_Int32 nIndex) override; + + // XNumericalDataSequence + /// @see css::chart::data::XNumericalDataSequence + virtual css::uno::Sequence SAL_CALL getNumericalData() override; + + // XTextualDataSequence + /// @see css::chart::data::XTextualDataSequence + virtual css::uno::Sequence SAL_CALL getTextualData() override; + + // XCloneable + /// @see css::util::XCloneable + virtual css::uno::Reference SAL_CALL createClone() override; + + // XModifyListener + /// @see css::util::XModifyListener + virtual void SAL_CALL + addModifyListener(const css::uno::Reference& aListener) override; + virtual void SAL_CALL + removeModifyListener(const css::uno::Reference& aListener) override; + virtual void SAL_CALL modified(const css::lang::EventObject& aEvent) override; + virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override; + +private: + void ensureCalculated(); + + rtl::Reference m_xModifyEventForwarder; + OUString m_sRole; + css::uno::Sequence mxLabels; + css::uno::Sequence mxValues; + css::uno::Reference m_xRawData; + bool m_bIsCategory; + bool m_bIsDirty; + + // Binning parameters captured at construction (from the owning HistogramChartType). + sal_Int32 m_nFrequencyType; + double m_fBinWidth; + sal_Int32 m_nBinCount; + bool m_bUseUnderflowBin; + double m_fUnderflowBinValue; + bool m_bUseOverflowBin; + double m_fOverflowBinValue; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file diff --git a/chart2/source/inc/UncachedDataSequence.hxx b/chart2/source/inc/UncachedDataSequence.hxx index b2f6930faaaf..dd178667a5dd 100644 --- a/chart2/source/inc/UncachedDataSequence.hxx +++ b/chart2/source/inc/UncachedDataSequence.hxx @@ -19,10 +19,7 @@ #pragma once // helper classes -#include -#include -#include -#include +#include #include // interfaces and types @@ -40,19 +37,17 @@ namespace chart class InternalDataProvider; class ModifyEventForwarder; -namespace impl -{ -typedef ::comphelper::WeakComponentImplHelper< - css::chart2::data::XDataSequence, - css::chart2::data::XNumericalDataSequence, - css::chart2::data::XTextualDataSequence, - css::util::XCloneable, - css::util::XModifiable, // contains util::XModifyBroadcaster - css::container::XIndexReplace, - css::container::XNamed, // for setting a new range representation - css::lang::XServiceInfo > - UncachedDataSequence_Base; -} +using UncachedDataSequence_Base = comphelper::OPropertyContainerImplHelper< + comphelper::WeakComponentImplHelper< + css::chart2::data::XDataSequence, + css::chart2::data::XNumericalDataSequence, + css::chart2::data::XTextualDataSequence, + css::util::XCloneable, + css::util::XModifiable, + css::container::XIndexReplace, + css::container::XNamed, + css::lang::XServiceInfo>, + class UncachedDataSequence>; /** * This sequence object does NOT store actual sequence data. Instead, it @@ -64,10 +59,8 @@ typedef ::comphelper::WeakComponentImplHelper< *

A range representation can be either '0', '1', '2', ..., or 'label 1', * 'label 2', ...

*/ -class UncachedDataSequence final : - public ::comphelper::OPropertyContainer2, - public ::comphelper::OPropertyArrayUsageHelper< UncachedDataSequence >, - public impl::UncachedDataSequence_Base +class UncachedDataSequence final + : public UncachedDataSequence_Base { public: /** The referring data provider is held as uno reference to ensure its @@ -88,17 +81,7 @@ public: virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; - /// merge XInterface implementations - DECLARE_XINTERFACE() - /// merge XTypeProvider implementations - DECLARE_XTYPEPROVIDER() - private: - // ____ XPropertySet ____ - /// @see css::beans::XPropertySet - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override; - /// @see ::comphelper::OPropertySetHelper - virtual ::cppu::IPropertyArrayHelper& getInfoHelper() override; /// @see ::comphelper::OPropertyArrayUsageHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override; @@ -151,6 +134,9 @@ private: sal_Int32 m_nNumberFormatKey; OUString m_sRole; OUString m_aXMLRange; + OUString m_aChartExFormula; + OUString m_aChartExNFormula; + sal_Int32 m_nChartExDimType; // /** This method registers all properties. It should be called by all diff --git a/chart2/source/inc/chartview/ChartSfxItemIds.hxx b/chart2/source/inc/chartview/ChartSfxItemIds.hxx index e01165611772..83db5b3e388f 100644 --- a/chart2/source/inc/chartview/ChartSfxItemIds.hxx +++ b/chart2/source/inc/chartview/ChartSfxItemIds.hxx @@ -206,7 +206,17 @@ inline constexpr sal_uInt16 SCHATTR_COLOR_PALETTE_ST inline constexpr TypedWhichId SCHATTR_COLOR_PALETTE (SCHATTR_COLOR_PALETTE_START); inline constexpr sal_uInt16 SCHATTR_COLOR_PALETTE_END (SCHATTR_COLOR_PALETTE); -inline constexpr sal_uInt16 SCHATTR_END (SCHATTR_COLOR_PALETTE_END); +inline constexpr sal_uInt16 SCHATTR_HISTOGRAM_BINNING_START (SCHATTR_COLOR_PALETTE_END + 1); +inline constexpr TypedWhichId SCHATTR_HISTOGRAM_FREQUENCY_TYPE (SCHATTR_HISTOGRAM_BINNING_START); +inline constexpr TypedWhichId SCHATTR_HISTOGRAM_BIN_WIDTH (SCHATTR_HISTOGRAM_BINNING_START + 1); +inline constexpr TypedWhichId SCHATTR_HISTOGRAM_BIN_COUNT (SCHATTR_HISTOGRAM_BINNING_START + 2); +inline constexpr TypedWhichId SCHATTR_HISTOGRAM_USE_UNDERFLOW_BIN (SCHATTR_HISTOGRAM_BINNING_START + 3); +inline constexpr TypedWhichId SCHATTR_HISTOGRAM_UNDERFLOW_BIN_VALUE(SCHATTR_HISTOGRAM_BINNING_START + 4); +inline constexpr TypedWhichId SCHATTR_HISTOGRAM_USE_OVERFLOW_BIN (SCHATTR_HISTOGRAM_BINNING_START + 5); +inline constexpr TypedWhichId SCHATTR_HISTOGRAM_OVERFLOW_BIN_VALUE (SCHATTR_HISTOGRAM_BINNING_START + 6); +inline constexpr sal_uInt16 SCHATTR_HISTOGRAM_BINNING_END (SCHATTR_HISTOGRAM_OVERFLOW_BIN_VALUE); + +inline constexpr sal_uInt16 SCHATTR_END (SCHATTR_HISTOGRAM_BINNING_END); // values for Items @@ -259,7 +269,6 @@ struct AxisFlags{ static T toNum (const U&& fl){ return static_cast(fl);} bool operator==(const T& val){return val == static_cast(m);} bool operator==(const U& fl){return fl == m;} - bool operator==(const AxisFlags& other){return other==this;} private: U m; }; diff --git a/chart2/source/inc/res_BarGeometry.hxx b/chart2/source/inc/res_BarGeometry.hxx index 65d42ec88f0c..5c9e93c0f6b3 100644 --- a/chart2/source/inc/res_BarGeometry.hxx +++ b/chart2/source/inc/res_BarGeometry.hxx @@ -19,8 +19,8 @@ #pragma once #include +#include #include -#include namespace chart { diff --git a/chart2/source/inc/servicenames_charttypes.hxx b/chart2/source/inc/servicenames_charttypes.hxx index 22e9f446a996..c107190793e5 100644 --- a/chart2/source/inc/servicenames_charttypes.hxx +++ b/chart2/source/inc/servicenames_charttypes.hxx @@ -26,6 +26,8 @@ inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_BAR = u"com.sun.star.chart2.BarChartType"_ustr; inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_COLUMN = u"com.sun.star.chart2.ColumnChartType"_ustr; +inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM + = u"com.sun.star.chart2.HistogramChartType"_ustr; inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_LINE = u"com.sun.star.chart2.LineChartType"_ustr; inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_SCATTER @@ -44,6 +46,8 @@ inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_BOXWHISKER = u"com.sun.star.chart2.BoxWhiskerChartType"_ustr; inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_CLUSTEREDCOLUMN = u"com.sun.star.chart2.ClusteredColumnChartType"_ustr; +inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE + = u"com.sun.star.chart2.CorrelationCircleChartType"_ustr; inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_FUNNEL = u"com.sun.star.chart2.FunnelChartType"_ustr; inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_PARETOLINE diff --git a/chart2/source/model/main/Axis.cxx b/chart2/source/model/main/Axis.cxx index f8f0068fb1fe..3e55bd36827a 100644 --- a/chart2/source/model/main/Axis.cxx +++ b/chart2/source/model/main/Axis.cxx @@ -77,7 +77,16 @@ enum PROP_AXIS_BUILTINUNIT, PROP_AXIS_TRY_STAGGERING_FIRST, - PROP_AXIS_MAJOR_ORIGIN + PROP_AXIS_MAJOR_ORIGIN, + PROP_AXIS_HAS_EXPLICIT_SPPR, + PROP_AXIS_HAS_EXPLICIT_TXPR, + PROP_AXIS_ID, + PROP_AXIS_CAT_NOT_VAL, + PROP_AXIS_CHARTEX_VAL_MIN, + PROP_AXIS_CHARTEX_VAL_MAX, + PROP_AXIS_CHARTEX_MAJOR_UNIT, + PROP_AXIS_CHARTEX_MINOR_UNIT, + PROP_AXIS_CHARTEX_UNIT }; void lcl_AddPropertiesToVector( @@ -203,6 +212,66 @@ void lcl_AddPropertiesToVector( beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "HasExplicitSpPr", + PROP_AXIS_HAS_EXPLICIT_SPPR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "HasExplicitTxPr", + PROP_AXIS_HAS_EXPLICIT_TXPR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // Chartex only: the cx:axis id attribute value from import, preserved + // so export can reuse the same id and so series-to-axis links survive + // round-trip. + rOutProperties.emplace_back( "AxisId", + PROP_AXIS_ID, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "CatNotVal", + PROP_AXIS_CAT_NOT_VAL, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // Chartex round-trip: cx:valScaling attributes preserved verbatim, so + // export does not have to rebuild them from the chart2 ScaleData (where + // Auto* flags and explicit calc-style defaults can mask the original + // intent). + rOutProperties.emplace_back( "ChartexValMin", + PROP_AXIS_CHARTEX_VAL_MIN, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "ChartexValMax", + PROP_AXIS_CHARTEX_VAL_MAX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "ChartexMajorUnit", + PROP_AXIS_CHARTEX_MAJOR_UNIT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "ChartexMinorUnit", + PROP_AXIS_CHARTEX_MINOR_UNIT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // Chartex round-trip: cx:units/@unit value. Stored alongside the + // existing BuiltInUnit/DisplayUnits properties because the chartex + // flat form only uses this single string and we want the same string + // to come back on export. + rOutProperties.emplace_back( "ChartexUnit", + PROP_AXIS_CHARTEX_UNIT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); } } // namespace @@ -240,7 +309,7 @@ const ::chart::tPropertyValueMap & StaticAxisDefaults() return aMap; }(); return aStaticDefaults; -}; +} } // namespace chart namespace @@ -261,7 +330,7 @@ namespace return comphelper::containerToSequence( aProperties ); }(); return aPropHelper; -}; +} std::vector< rtl::Reference< ::chart::GridProperties > > lcl_CloneSubGrids( const std::vector< rtl::Reference< ::chart::GridProperties > > & rSource ) diff --git a/chart2/source/model/main/DataSeries.cxx b/chart2/source/model/main/DataSeries.cxx index 04526adea5ad..1239ae0e59fb 100644 --- a/chart2/source/model/main/DataSeries.cxx +++ b/chart2/source/model/main/DataSeries.cxx @@ -161,6 +161,19 @@ DataSeries::DataSeries( const DataSeries & rOther ) : if( ( aValue >>= xPropertySet ) && xPropertySet.is()) ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder ); + + if (rOther.m_xCalculatedYSequence.is()) + { + uno::Reference xCloneable(rOther.m_xCalculatedYSequence, uno::UNO_QUERY); + if (xCloneable.is()) + { + m_xCalculatedYSequence.set(xCloneable->createClone(), uno::UNO_QUERY); + } + else + { + m_xCalculatedYSequence = rOther.m_xCalculatedYSequence; + } + } } // late initialization to call after copy-constructing @@ -392,10 +405,7 @@ void SAL_CALL DataSeries::setData( const uno::Sequence< Reference< chart2::data: MutexGuard aGuard( m_aMutex ); xModifyEventForwarder = m_xModifyEventForwarder; std::swap( aOldDataSequences, m_aDataSequences ); - for (const auto & i : aData) - { - aNewDataSequences.push_back(i); - } + aNewDataSequences.insert(aNewDataSequences.end(), aData.begin(), aData.end()); m_aDataSequences = aNewDataSequences; } ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder ); @@ -1035,6 +1045,21 @@ sal_Int32 DataSeries::getExplicitNumberFormatKeyForDataLabel() } +void DataSeries::setCalculatedYSequence(css::uno::Reference const& xSequence) +{ + m_xCalculatedYSequence = xSequence; +} + +css::uno::Reference DataSeries::getCalculatedYSequence() const +{ + return m_xCalculatedYSequence; +} + +void DataSeries::clearCalculatedYSequence() +{ + m_xCalculatedYSequence.clear(); +} + } // namespace chart extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * diff --git a/chart2/source/model/main/DataSeriesProperties.cxx b/chart2/source/model/main/DataSeriesProperties.cxx index 4734c22f8fda..6705a8ac4ec9 100644 --- a/chart2/source/model/main/DataSeriesProperties.cxx +++ b/chart2/source/model/main/DataSeriesProperties.cxx @@ -20,6 +20,7 @@ #include #include "DataPointProperties.hxx" #include +#include #include using namespace ::com::sun::star; @@ -87,6 +88,143 @@ void DataSeriesProperties::AddPropertiesToVector( beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "ConnectorLines", + PROP_DATASERIES_CONNECTOR_LINES, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "HasExplicitFill", + PROP_DATASERIES_HAS_EXPLICIT_FILL, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "HasDataLabels", + PROP_DATASERIES_HAS_DATA_LABELS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "MeanLine", + PROP_DATASERIES_MEAN_LINE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "MeanMarker", + PROP_DATASERIES_MEAN_MARKER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "Nonoutliers", + PROP_DATASERIES_NONOUTLIERS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "Outliers", + PROP_DATASERIES_OUTLIERS, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "ParentLabelLayout", + PROP_DATASERIES_PARENT_LABEL_LAYOUT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "RegionLabelLayout", + PROP_DATASERIES_REGION_LABEL_LAYOUT, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "QuartileMethod", + PROP_DATASERIES_QUARTILE_METHOD, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "SubtotalIndices", + PROP_DATASERIES_SUBTOTAL_INDICES, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "HasGeography", + PROP_DATASERIES_HAS_GEOGRAPHY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GeographyProjectionType", + PROP_DATASERIES_GEOGRAPHY_PROJECTION_TYPE, + cppu::UnoType::get(), // Actually enum GeoProjectionType + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GeographyViewedRegionType", + PROP_DATASERIES_GEOGRAPHY_VIEWED_REGION_TYPE, + cppu::UnoType::get(), // Actually enum GeoMappingLevel + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GeographyCultureLanguage", + PROP_DATASERIES_GEOGRAPHY_CULTURE_LANGUAGE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GeographyCultureRegion", + PROP_DATASERIES_GEOGRAPHY_CULTURE_REGION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GeographyAttribution", + PROP_DATASERIES_GEOGRAPHY_ATTRIBUTION, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GeoCacheProvider", + PROP_DATASERIES_GEOCACHE_PROVIDER, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GeoCacheBinary", + PROP_DATASERIES_GEOCACHE_BINARY, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "GeoCacheClearData", + PROP_DATASERIES_GEOCACHE_CLEAR_DATA, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // Chartex only: the cx:axisId values listed on the cx:series element at + // import. Empty for axis-less chartex types (regionMap, sunburst, treemap). + rOutProperties.emplace_back( "ChartexAxisIds", + PROP_DATASERIES_CHARTEX_AXIS_IDS, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + + // Chartex only: cx:series/@ownerIdx. When present, this series shares + // data with the series at this zero-based index in the same + // plotAreaRegion, and no cx:dataId is emitted. + rOutProperties.emplace_back( "ChartexOwnerIdx", + PROP_DATASERIES_CHARTEX_OWNER_IDX, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); + // add properties of service DataPointProperties DataPointProperties::AddPropertiesToVector( rOutProperties ); } @@ -100,6 +238,7 @@ void DataSeriesProperties::AddDefaultsToMap( PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_SHOW_LEGEND_ENTRY, true ); PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES, true ); PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_INVERT_NEGATIVE, false ); + PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_HAS_EXPLICIT_FILL, false ); // PROP_DATASERIES_ATTRIBUTED_DATA_POINTS has no default diff --git a/chart2/source/model/main/GridProperties.cxx b/chart2/source/model/main/GridProperties.cxx index 2c1cacf86cf3..d9c3ea88c144 100644 --- a/chart2/source/model/main/GridProperties.cxx +++ b/chart2/source/model/main/GridProperties.cxx @@ -39,7 +39,8 @@ namespace enum { - PROP_GRID_SHOW + PROP_GRID_SHOW, + PROP_GRID_HAS_EXPLICIT_SPPR }; void lcl_AddPropertiesToVector( @@ -50,6 +51,16 @@ void lcl_AddPropertiesToVector( cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT ); + + // Chartex round-trip: tracks whether the imported cx:majorGridlines / + // cx:minorGridlines carried an explicit child. When false or + // unset, export must not emit a default spPr, since an empty gridlines + // element means "use default formatting". + rOutProperties.emplace_back( "HasExplicitSpPr", + PROP_GRID_HAS_EXPLICIT_SPPR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); } const ::chart::tPropertyValueMap & StaticGridDefaults() @@ -67,7 +78,7 @@ const ::chart::tPropertyValueMap & StaticGridDefaults() return aTmp; }(); return aStaticDefaults; -}; +} ::cppu::OPropertyArrayHelper& StaticGridInfoHelper() { @@ -84,7 +95,7 @@ const ::chart::tPropertyValueMap & StaticGridDefaults() return comphelper::containerToSequence( aProperties ); }(); return aPropHelper; -}; +} } // anonymous namespace diff --git a/chart2/source/model/main/Legend.cxx b/chart2/source/model/main/Legend.cxx index 5f6ee67ccaa0..67504e1df6b2 100644 --- a/chart2/source/model/main/Legend.cxx +++ b/chart2/source/model/main/Legend.cxx @@ -55,7 +55,8 @@ enum PROP_LEGEND_OVERLAY, PROP_LEGEND_REF_PAGE_SIZE, PROP_LEGEND_REL_POS, - PROP_LEGEND_REL_SIZE + PROP_LEGEND_REL_SIZE, + PROP_LEGEND_HAS_EXPLICIT_SPPR }; void lcl_AddPropertiesToVector( @@ -103,6 +104,11 @@ void lcl_AddPropertiesToVector( beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEVOID ); + rOutProperties.emplace_back( "HasExplicitSpPr", + PROP_LEGEND_HAS_EXPLICIT_SPPR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); } } // namespace @@ -130,7 +136,7 @@ const ::chart::tPropertyValueMap& StaticLegendDefaults() return aTmp; }(); return aStaticDefaults; -}; +} } // namespace chart namespace @@ -152,7 +158,7 @@ namespace return comphelper::containerToSequence( aProperties ); }(); return aPropHelper; -}; +} } // anonymous namespace diff --git a/chart2/source/model/main/PageBackground.cxx b/chart2/source/model/main/PageBackground.cxx index 2bddc6214ca1..c615b41575b7 100644 --- a/chart2/source/model/main/PageBackground.cxx +++ b/chart2/source/model/main/PageBackground.cxx @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -42,6 +43,21 @@ using ::com::sun::star::beans::Property; namespace { +enum +{ + PROP_PAGE_BACKGROUND_HAS_EXPLICIT_SPPR +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "HasExplicitSpPr", + PROP_PAGE_BACKGROUND_HAS_EXPLICIT_SPPR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + const ::chart::tPropertyValueMap& StaticPageBackgroundDefaults() { static ::chart::tPropertyValueMap aStaticDefaults = []() @@ -66,13 +82,14 @@ const ::chart::tPropertyValueMap& StaticPageBackgroundDefaults() return aTmp; }(); return aStaticDefaults; -}; +} ::cppu::OPropertyArrayHelper& StaticPageBackgroundInfoHelper() { static ::cppu::OPropertyArrayHelper aPropHelper = []() { std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties ); ::chart::FillProperties::AddPropertiesToVector( aProperties ); ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); @@ -83,7 +100,7 @@ const ::chart::tPropertyValueMap& StaticPageBackgroundDefaults() return comphelper::containerToSequence( aProperties ); }(); return aPropHelper; -}; +} } // anonymous namespace diff --git a/chart2/source/model/main/Title.cxx b/chart2/source/model/main/Title.cxx index d882304d43d3..d4b8d35ec6a5 100644 --- a/chart2/source/model/main/Title.cxx +++ b/chart2/source/model/main/Title.cxx @@ -61,7 +61,8 @@ enum PROP_TITLE_TEXT_STACKED, PROP_TITLE_REL_POS, - PROP_TITLE_REF_PAGE_SIZE + PROP_TITLE_REF_PAGE_SIZE, + PROP_TITLE_HAS_EXPLICIT_SPPR }; void lcl_AddPropertiesToVector( @@ -138,6 +139,12 @@ void lcl_AddPropertiesToVector( cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEVOID ); + + rOutProperties.emplace_back( "HasExplicitSpPr", + PROP_TITLE_HAS_EXPLICIT_SPPR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); } const ::chart::tPropertyValueMap& StaticTitleDefaults() @@ -172,7 +179,7 @@ const ::chart::tPropertyValueMap& StaticTitleDefaults() return aTmp; }(); return aStaticDefaults; -}; +} ::cppu::OPropertyArrayHelper& StaticTitleInfoHelper() { @@ -190,7 +197,7 @@ const ::chart::tPropertyValueMap& StaticTitleDefaults() return comphelper::containerToSequence( aProperties ); }(); return aPropHelper; -}; +} } // anonymous namespace diff --git a/chart2/source/model/main/Wall.cxx b/chart2/source/model/main/Wall.cxx index 1bbe133de905..5a959dcdcbbe 100644 --- a/chart2/source/model/main/Wall.cxx +++ b/chart2/source/model/main/Wall.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -35,11 +36,27 @@ using ::com::sun::star::beans::Property; namespace { +enum +{ + PROP_WALL_HAS_EXPLICIT_SPPR +}; + +void lcl_AddPropertiesToVector( + std::vector< Property > & rOutProperties ) +{ + rOutProperties.emplace_back( "HasExplicitSpPr", + PROP_WALL_HAS_EXPLICIT_SPPR, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEVOID ); +} + ::cppu::OPropertyArrayHelper& StaticWallInfoHelper() { static ::cppu::OPropertyArrayHelper aPropHelper = []() { std::vector< css::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties ); ::chart::FillProperties::AddPropertiesToVector( aProperties ); ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties ); @@ -50,9 +67,9 @@ namespace return comphelper::containerToSequence( aProperties ); }(); return aPropHelper; -}; +} -} // anonymous namespace +} // namespace namespace chart { diff --git a/chart2/source/model/template/BoxWhiskerChartType.cxx b/chart2/source/model/template/BoxWhiskerChartType.cxx index 02847c668107..feca8ed4069c 100644 --- a/chart2/source/model/template/BoxWhiskerChartType.cxx +++ b/chart2/source/model/template/BoxWhiskerChartType.cxx @@ -9,6 +9,8 @@ #include "BoxWhiskerChartType.hxx" #include +#include +#include #include namespace com::sun::star::uno @@ -18,6 +20,46 @@ class XComponentContext; using namespace ::com::sun::star; +using namespace ::com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ +enum +{ + PROP_BOXWHISKERCHARTTYPE_OVERLAP_SEQUENCE, + PROP_BOXWHISKERCHARTTYPE_GAPWIDTH_SEQUENCE +}; + +void lcl_AddPropertiesToVector(std::vector& rOutProperties) +{ + rOutProperties.emplace_back("OverlapSequence", PROP_BOXWHISKERCHARTTYPE_OVERLAP_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back("GapwidthSequence", PROP_BOXWHISKERCHARTTYPE_GAPWIDTH_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); +} + +::cppu::OPropertyArrayHelper& StaticBoxWhiskerChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() { + std::vector aProperties; + lcl_AddPropertiesToVector(aProperties); + + std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess()); + + return comphelper::containerToSequence(aProperties); + }(); + return aPropHelper; +}; + +} // anonymous namespace + namespace chart { BoxWhiskerChartType::BoxWhiskerChartType() {} @@ -51,6 +93,39 @@ uno::Sequence BoxWhiskerChartType::getSupportedPropertyRoles() return { "FillColor", "BorderColor" }; } +// ____ OPropertySet ____ +void BoxWhiskerChartType::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const +{ + static const ::chart::tPropertyValueMap aStaticDefaults = []() { + ::chart::tPropertyValueMap aTmp; + Sequence aSeq{ 0, 0 }; + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_BOXWHISKERCHARTTYPE_OVERLAP_SEQUENCE, aSeq); + aSeq = { 100, 100 }; + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_BOXWHISKERCHARTTYPE_GAPWIDTH_SEQUENCE, aSeq); + return aTmp; + }(); + tPropertyValueMap::const_iterator aFound(aStaticDefaults.find(nHandle)); + if (aFound == aStaticDefaults.end()) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper& SAL_CALL BoxWhiskerChartType::getInfoHelper() +{ + return StaticBoxWhiskerChartTypeInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference SAL_CALL BoxWhiskerChartType::getPropertySetInfo() +{ + static uno::Reference xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticBoxWhiskerChartTypeInfoHelper())); + return xPropertySetInfo; +} + OUString SAL_CALL BoxWhiskerChartType::getImplementationName() { return "com.sun.star.comp.chart.BoxWhiskerChartType"; diff --git a/chart2/source/model/template/BoxWhiskerChartType.hxx b/chart2/source/model/template/BoxWhiskerChartType.hxx index 76a25d3fba0f..0b6413008869 100644 --- a/chart2/source/model/template/BoxWhiskerChartType.hxx +++ b/chart2/source/model/template/BoxWhiskerChartType.hxx @@ -31,6 +31,14 @@ private: virtual OUString SAL_CALL getChartType() override; virtual css::uno::Sequence SAL_CALL getSupportedPropertyRoles() override; + // ____ OPropertySet ____ + virtual void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference + SAL_CALL getPropertySetInfo() override; + // ____ XCloneable ____ virtual css::uno::Reference SAL_CALL createClone() override; }; diff --git a/chart2/source/model/template/BoxWhiskerChartTypeTemplate.cxx b/chart2/source/model/template/BoxWhiskerChartTypeTemplate.cxx index 116321b53dd4..692081f6edcd 100644 --- a/chart2/source/model/template/BoxWhiskerChartTypeTemplate.cxx +++ b/chart2/source/model/template/BoxWhiskerChartTypeTemplate.cxx @@ -32,7 +32,8 @@ namespace enum { PROP_BOXWHISKER_TEMPLATE_DIMENSION, - PROP_BOXWHISKER_TEMPLATE_GEOMETRY3D + PROP_BOXWHISKER_TEMPLATE_GEOMETRY3D, + PROP_BOXWHISKER_TEMPLATE_GAPWIDTH_SEQUENCE }; void lcl_AddPropertiesToVector(std::vector& rOutProperties) @@ -43,6 +44,10 @@ void lcl_AddPropertiesToVector(std::vector& rOutProperties) rOutProperties.emplace_back( "Geometry3D", PROP_BOXWHISKER_TEMPLATE_GEOMETRY3D, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + rOutProperties.emplace_back("GapwidthSequence", PROP_BOXWHISKER_TEMPLATE_GAPWIDTH_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); } ::cppu::OPropertyArrayHelper& StaticBoxWhiskerChartTypeTemplateInfoHelper() diff --git a/chart2/source/model/template/ChartType.cxx b/chart2/source/model/template/ChartType.cxx index f8157b4f945a..390a032c14b0 100644 --- a/chart2/source/model/template/ChartType.cxx +++ b/chart2/source/model/template/ChartType.cxx @@ -150,6 +150,7 @@ void ChartType::addDataSeries( const rtl::Reference< DataSeries >& xDataSeries ) SolarMutexGuard g; impl_addDataSeriesWithoutNotification( xDataSeries ); + createCalculatedDataSeries(); fireModifyEvent(); } @@ -223,9 +224,8 @@ void ChartType::setDataSeries( const std::vector< rtl::Reference< DataSeries > > throw; } m_bNotifyChanges = true; - fireModifyEvent(); - createCalculatedDataSeries(); + fireModifyEvent(); } void ChartType::createCalculatedDataSeries() @@ -344,6 +344,11 @@ bool ChartType::isSupportingStatisticProperties(sal_Int32 nDimensionCount) if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE)) //todo: BubbleChart support error bars and trend lines return false; + // The points of a correlation circle plot are worked out from the data + // rather than taken from it, so there is nothing to put a spread on. + if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE)) + return false; + return true; } @@ -386,6 +391,9 @@ bool ChartType::isSupportingAreaProperties(sal_Int32 nDimensionCount) if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK)) return false; + + if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE)) + return false; } return true; } @@ -407,6 +415,9 @@ bool ChartType::isSupportingSymbolProperties(sal_Int32 nDimensionCount) if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET)) return true; + if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE)) + return true; + return false; } @@ -439,16 +450,17 @@ bool ChartType::isSupportingRightAngledAxes() bool ChartType::isSupportingOverlapAndGapWidthProperties(sal_Int32 nDimensionCount) { - //2D bar charts do support a this special properties + //2D bar charts do support these special properties if (nDimensionCount == 3) return false; OUString aChartTypeName = getChartType(); - if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN)) - return true; - - if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR)) + if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FUNNEL) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM)) { return true; + } return false; } @@ -504,7 +516,8 @@ bool ChartType::isSupportingBaseValue() return aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) - || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA); + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM); } bool ChartType::isSupportingAxisPositioning(sal_Int32 nDimensionCount, sal_Int32 nDimensionIndex ) @@ -625,7 +638,8 @@ sal_Int32 ChartType::getAxisType(sal_Int32 nDimensionIndex) if (nDimensionIndex == 0) //x-axis { if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) - || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE)) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE)) return chart2::AxisType::REALNUMBER; return chart2::AxisType::CATEGORY; } @@ -649,9 +663,8 @@ void ChartType::deleteSeries( const rtl::Reference< ::chart::DataSeries > & xSer ModifyListenerHelper::removeListener( *it, m_xModifyEventForwarder ); m_aDataSeries.erase(it); - fireModifyEvent(); - createCalculatedDataSeries(); + fireModifyEvent(); } catch( const uno::Exception & ) { diff --git a/chart2/source/model/template/ChartTypeManager.cxx b/chart2/source/model/template/ChartTypeManager.cxx index 89cb3518ff3f..b67720449dbf 100644 --- a/chart2/source/model/template/ChartTypeManager.cxx +++ b/chart2/source/model/template/ChartTypeManager.cxx @@ -23,12 +23,14 @@ #include "LineChartTypeTemplate.hxx" #include "BarChartTypeTemplate.hxx" #include "ColumnLineChartTypeTemplate.hxx" +#include "HistogramChartTypeTemplate.hxx" #include "AreaChartTypeTemplate.hxx" #include "PieChartTypeTemplate.hxx" #include "ScatterChartTypeTemplate.hxx" #include "StockChartTypeTemplate.hxx" #include "NetChartTypeTemplate.hxx" #include "BubbleChartTypeTemplate.hxx" +#include "CorrelationCircleChartTypeTemplate.hxx" #include "FunnelChartTypeTemplate.hxx" #include "BoxWhiskerChartTypeTemplate.hxx" #include "ClusteredColumnChartTypeTemplate.hxx" @@ -87,6 +89,7 @@ enum TemplateId TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT, TEMPLATE_COLUMNWITHLINE, TEMPLATE_STACKEDCOLUMNWITHLINE, + TEMPLATE_HISTOGRAM, TEMPLATE_AREA, TEMPLATE_STACKEDAREA, TEMPLATE_PERCENTSTACKEDAREA, @@ -124,6 +127,7 @@ enum TemplateId TEMPLATE_STOCKVOLUMELOWHIGHCLOSE, TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE, TEMPLATE_BUBBLE, + TEMPLATE_CORRELATIONCIRCLE, TEMPLATE_FUNNEL, TEMPLATE_BOXWHISKER, TEMPLATE_CLUSTEREDCOLUMN, @@ -171,6 +175,7 @@ const tTemplateMapType & lcl_DefaultChartTypeMap() {"com.sun.star.chart2.template.PercentStackedThreeDBarFlat", TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT}, {"com.sun.star.chart2.template.ColumnWithLine", TEMPLATE_COLUMNWITHLINE}, {"com.sun.star.chart2.template.StackedColumnWithLine", TEMPLATE_STACKEDCOLUMNWITHLINE}, + {"com.sun.star.chart2.template.Histogram", TEMPLATE_HISTOGRAM}, {"com.sun.star.chart2.template.Area", TEMPLATE_AREA}, {"com.sun.star.chart2.template.StackedArea", TEMPLATE_STACKEDAREA}, {"com.sun.star.chart2.template.PercentStackedArea", TEMPLATE_PERCENTSTACKEDAREA}, @@ -209,6 +214,7 @@ const tTemplateMapType & lcl_DefaultChartTypeMap() {"com.sun.star.chart2.template.StockVolumeLowHighClose", TEMPLATE_STOCKVOLUMELOWHIGHCLOSE}, {"com.sun.star.chart2.template.StockVolumeOpenLowHighClose", TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE}, {"com.sun.star.chart2.template.Bubble", TEMPLATE_BUBBLE}, + {"com.sun.star.chart2.template.CorrelationCircle", TEMPLATE_CORRELATIONCIRCLE}, {"com.sun.star.chart2.template.Funnel", TEMPLATE_FUNNEL}, {"com.sun.star.chart2.template.BoxWhisker", TEMPLATE_BOXWHISKER}, {"com.sun.star.chart2.template.ClusteredColumn", TEMPLATE_CLUSTEREDCOLUMN}, @@ -389,6 +395,11 @@ rtl::Reference< ::chart::ChartTypeTemplate > ChartTypeManager::createTemplate( } break; + // Histogram + case TEMPLATE_HISTOGRAM: + xTemplate.set(new HistogramChartTypeTemplate(m_xContext, aServiceSpecifier, StackMode::NONE)); + break; + // Area case TEMPLATE_AREA: xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::NONE )); @@ -548,6 +559,11 @@ rtl::Reference< ::chart::ChartTypeTemplate > ChartTypeManager::createTemplate( xTemplate.set( new BubbleChartTypeTemplate( m_xContext, aServiceSpecifier )); break; + // Correlation circle plot + case TEMPLATE_CORRELATIONCIRCLE: + xTemplate.set( new CorrelationCircleChartTypeTemplate( m_xContext, aServiceSpecifier )); + break; + // Funnel chart case TEMPLATE_FUNNEL: xTemplate.set( new FunnelChartTypeTemplate( m_xContext, diff --git a/chart2/source/model/template/ChartTypeTemplate.cxx b/chart2/source/model/template/ChartTypeTemplate.cxx index 6549f26f02da..2243b05e2c2d 100644 --- a/chart2/source/model/template/ChartTypeTemplate.cxx +++ b/chart2/source/model/template/ChartTypeTemplate.cxx @@ -188,6 +188,15 @@ void ChartTypeTemplate::changeDiagram( const rtl::Reference< Diagram >& xDiagram std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq )); const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.size(); + // Clear all calculated sequences before changing chart type + for (auto const & xOldSeries : aFlatSeriesSeq) + { + if (xOldSeries.is()) + { + xOldSeries->clearCalculatedYSequence(); + } + } + // chart-type specific interpretation of existing data series rtl::Reference< DataInterpreter > xInterpreter( getDataInterpreter2()); InterpretedData aData; @@ -228,9 +237,12 @@ void ChartTypeTemplate::changeDiagram( const rtl::Reference< Diagram >& xDiagram std::vector< rtl::Reference< ChartType > > aOldChartTypesSeq = xDiagram->getChartTypes(); - for( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() ) + for (rtl::Reference const& rCoords : xDiagram->getBaseCoordinateSystems()) { - coords->setChartTypes( Sequence< Reference< XChartType > >() ); + if (rCoords.is()) + { + rCoords->setChartTypes(uno::Sequence>()); + } } FillDiagram( xDiagram, aSeriesSeq, aData.Categories, aOldChartTypesSeq ); @@ -358,7 +370,7 @@ void ChartTypeTemplate::applyStyle2( ::sal_Int32 /* nSeriesIndex */, ::sal_Int32 /* nSeriesCount */ ) { - // sset stacking mode + // set stacking mode if( !xSeries.is()) return; @@ -477,6 +489,11 @@ bool ChartTypeTemplate::isSwapXAndY() const return false; } +bool ChartTypeTemplate::usesLastTwoColumnsAsDimensions() const +{ + return false; +} + void ChartTypeTemplate::createCoordinateSystems( const rtl::Reference< ::chart::Diagram > & xDiagram ) { @@ -573,6 +590,7 @@ void ChartTypeTemplate::adaptScales( m_aServiceName.indexOf("Column") != -1 || (m_aServiceName.indexOf("Bar") != -1 && !m_aServiceName.indexOf("BarOfPie")) || + m_aServiceName.indexOf("Funnel") != -1 || m_aServiceName.endsWith("Close"); } bool bSupportsDates = xChartType.is() ? xChartType->isSupportingDateAxis(nDimensionX) : true; diff --git a/chart2/source/model/template/ClusteredColumnChartType.cxx b/chart2/source/model/template/ClusteredColumnChartType.cxx index 618286b894f8..6dd8c80cbd77 100644 --- a/chart2/source/model/template/ClusteredColumnChartType.cxx +++ b/chart2/source/model/template/ClusteredColumnChartType.cxx @@ -9,6 +9,8 @@ #include "ClusteredColumnChartType.hxx" #include +#include +#include #include namespace com::sun::star::uno @@ -18,6 +20,46 @@ class XComponentContext; using namespace ::com::sun::star; +using namespace ::com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ +enum +{ + PROP_CLUSTEREDCOLUMNCHARTTYPE_OVERLAP_SEQUENCE, + PROP_CLUSTEREDCOLUMNCHARTTYPE_GAPWIDTH_SEQUENCE +}; + +void lcl_AddPropertiesToVector(std::vector& rOutProperties) +{ + rOutProperties.emplace_back("OverlapSequence", PROP_CLUSTEREDCOLUMNCHARTTYPE_OVERLAP_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back("GapwidthSequence", PROP_CLUSTEREDCOLUMNCHARTTYPE_GAPWIDTH_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); +} + +::cppu::OPropertyArrayHelper& StaticClusteredColumnChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() { + std::vector aProperties; + lcl_AddPropertiesToVector(aProperties); + + std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess()); + + return comphelper::containerToSequence(aProperties); + }(); + return aPropHelper; +}; + +} // anonymous namespace + namespace chart { ClusteredColumnChartType::ClusteredColumnChartType() {} @@ -51,6 +93,40 @@ uno::Sequence ClusteredColumnChartType::getSupportedPropertyRoles() return { "FillColor", "BorderColor" }; } +// ____ OPropertySet ____ +void ClusteredColumnChartType::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const +{ + static const ::chart::tPropertyValueMap aStaticDefaults = []() { + ::chart::tPropertyValueMap aTmp; + Sequence aSeq{ 0, 0 }; + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_CLUSTEREDCOLUMNCHARTTYPE_OVERLAP_SEQUENCE, aSeq); + aSeq = { 100, 100 }; + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_CLUSTEREDCOLUMNCHARTTYPE_GAPWIDTH_SEQUENCE, aSeq); + return aTmp; + }(); + tPropertyValueMap::const_iterator aFound(aStaticDefaults.find(nHandle)); + if (aFound == aStaticDefaults.end()) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper& SAL_CALL ClusteredColumnChartType::getInfoHelper() +{ + return StaticClusteredColumnChartTypeInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference SAL_CALL ClusteredColumnChartType::getPropertySetInfo() +{ + static uno::Reference xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo( + StaticClusteredColumnChartTypeInfoHelper())); + return xPropertySetInfo; +} + OUString SAL_CALL ClusteredColumnChartType::getImplementationName() { return "com.sun.star.comp.chart.ClusteredColumnChartType"; diff --git a/chart2/source/model/template/ClusteredColumnChartType.hxx b/chart2/source/model/template/ClusteredColumnChartType.hxx index d60d7753afa5..ff8ccb00ebd5 100644 --- a/chart2/source/model/template/ClusteredColumnChartType.hxx +++ b/chart2/source/model/template/ClusteredColumnChartType.hxx @@ -31,6 +31,14 @@ private: virtual OUString SAL_CALL getChartType() override; virtual css::uno::Sequence SAL_CALL getSupportedPropertyRoles() override; + // ____ OPropertySet ____ + virtual void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference + SAL_CALL getPropertySetInfo() override; + // ____ XCloneable ____ virtual css::uno::Reference SAL_CALL createClone() override; }; diff --git a/chart2/source/model/template/ClusteredColumnChartTypeTemplate.cxx b/chart2/source/model/template/ClusteredColumnChartTypeTemplate.cxx index 355c14e1ce05..87e66fd93ec4 100644 --- a/chart2/source/model/template/ClusteredColumnChartTypeTemplate.cxx +++ b/chart2/source/model/template/ClusteredColumnChartTypeTemplate.cxx @@ -32,7 +32,8 @@ namespace enum { PROP_CLUSTEREDCOLUMN_TEMPLATE_DIMENSION, - PROP_CLUSTEREDCOLUMN_TEMPLATE_GEOMETRY3D + PROP_CLUSTEREDCOLUMN_TEMPLATE_GEOMETRY3D, + PROP_CLUSTEREDCOLUMN_TEMPLATE_GAPWIDTH_SEQUENCE }; void lcl_AddPropertiesToVector(std::vector& rOutProperties) @@ -43,6 +44,10 @@ void lcl_AddPropertiesToVector(std::vector& rOutProperties) rOutProperties.emplace_back( "Geometry3D", PROP_CLUSTEREDCOLUMN_TEMPLATE_GEOMETRY3D, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + rOutProperties.emplace_back("GapwidthSequence", PROP_CLUSTEREDCOLUMN_TEMPLATE_GAPWIDTH_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); } ::cppu::OPropertyArrayHelper& StaticClusteredColumnChartTypeTemplateInfoHelper() diff --git a/chart2/source/model/template/CorrelationCircleChartType.cxx b/chart2/source/model/template/CorrelationCircleChartType.cxx new file mode 100644 index 000000000000..ab6bbff5ea1c --- /dev/null +++ b/chart2/source/model/template/CorrelationCircleChartType.cxx @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 "CorrelationCircleChartType.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +namespace +{ +::cppu::OPropertyArrayHelper& StaticCorrelationCircleChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() { + std::vector aProperties; + std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess()); + return comphelper::containerToSequence(aProperties); + }(); + return aPropHelper; +}; + +} // anonymous namespace + +namespace chart +{ +CorrelationCircleChartType::CorrelationCircleChartType() {} + +CorrelationCircleChartType::CorrelationCircleChartType(const CorrelationCircleChartType& rOther) + : ChartType(rOther) +{ +} + +CorrelationCircleChartType::~CorrelationCircleChartType() {} + +// ____ XCloneable ____ +uno::Reference CorrelationCircleChartType::createClone() +{ + return uno::Reference(new CorrelationCircleChartType(*this)); +} + +rtl::Reference CorrelationCircleChartType::cloneChartType() const +{ + return new CorrelationCircleChartType(*this); +} + +// ____ XChartType ____ +rtl::Reference<::chart::BaseCoordinateSystem> +CorrelationCircleChartType::createCoordinateSystem2(sal_Int32 DimensionCount) +{ + rtl::Reference xResult + = new CartesianCoordinateSystem(DimensionCount); + + for (sal_Int32 i = 0; i < DimensionCount; ++i) + { + rtl::Reference xAxis = xResult->getAxisByDimension2(i, MAIN_AXIS_INDEX); + if (!xAxis.is()) + { + OSL_FAIL("a created coordinate system should have an axis for each dimension"); + continue; + } + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + aScaleData.Scaling = AxisHelper::createLinearScaling(); + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + + xAxis->setScaleData(aScaleData); + } + + return xResult; +} + +OUString CorrelationCircleChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE; +} + +css::uno::Sequence CorrelationCircleChartType::getSupportedMandatoryRoles() +{ + return { u"label"_ustr, u"values-feature"_ustr, u"values-x"_ustr, u"values-y"_ustr }; +} + +css::uno::Sequence CorrelationCircleChartType::getSupportedPropertyRoles() +{ + return { u"FillColor"_ustr, u"BorderColor"_ustr }; +} + +OUString CorrelationCircleChartType::getRoleOfSequenceForSeriesLabel() +{ + return u"values-feature"_ustr; +} + +// ____ OPropertySet ____ +void CorrelationCircleChartType::GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const +{ + static ::chart::tPropertyValueMap aStaticDefaults; + tPropertyValueMap::const_iterator aFound(aStaticDefaults.find(nHandle)); + if (aFound == aStaticDefaults.end()) + rAny.clear(); + else + rAny = (*aFound).second; +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper& CorrelationCircleChartType::getInfoHelper() +{ + return StaticCorrelationCircleChartTypeInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference CorrelationCircleChartType::getPropertySetInfo() +{ + static uno::Reference xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo( + StaticCorrelationCircleChartTypeInfoHelper())); + return xPropertySetInfo; +} + +OUString CorrelationCircleChartType::getImplementationName() +{ + return u"com.sun.star.comp.chart.CorrelationCircleChartType"_ustr; +} + +sal_Bool CorrelationCircleChartType::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence CorrelationCircleChartType::getSupportedServiceNames() +{ + return { CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE, u"com.sun.star.chart2.ChartType"_ustr, + u"com.sun.star.beans.PropertySet"_ustr }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_chart_CorrelationCircleChartType_get_implementation( + css::uno::XComponentContext* /*context*/, css::uno::Sequence const&) +{ + return cppu::acquire(new ::chart::CorrelationCircleChartType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/CorrelationCircleChartType.hxx b/chart2/source/model/template/CorrelationCircleChartType.hxx new file mode 100644 index 000000000000..74b0e87906e0 --- /dev/null +++ b/chart2/source/model/template/CorrelationCircleChartType.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include + +namespace chart +{ +/** A correlation circle plot. One series per feature, each holding the feature + column under the role values-feature and the two dimension columns under + values-x and values-y. + */ +class CorrelationCircleChartType final : public ChartType +{ +public: + explicit CorrelationCircleChartType(); + virtual ~CorrelationCircleChartType() override; + + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override; + virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + + virtual rtl::Reference cloneChartType() const override; + +private: + explicit CorrelationCircleChartType(const CorrelationCircleChartType& rOther); + + // ____ XChartType ____ + virtual OUString SAL_CALL getChartType() override; + virtual css::uno::Sequence SAL_CALL getSupportedMandatoryRoles() override; + virtual css::uno::Sequence SAL_CALL getSupportedPropertyRoles() override; + virtual OUString SAL_CALL getRoleOfSequenceForSeriesLabel() override; + + // ____ OPropertySet ____ + virtual void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference + SAL_CALL getPropertySetInfo() override; + + // ____ XCloneable ____ + virtual css::uno::Reference SAL_CALL createClone() override; + + virtual rtl::Reference<::chart::BaseCoordinateSystem> + createCoordinateSystem2(sal_Int32 DimensionCount) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/CorrelationCircleChartTypeTemplate.cxx b/chart2/source/model/template/CorrelationCircleChartTypeTemplate.cxx new file mode 100644 index 000000000000..7f0bb60ce9a3 --- /dev/null +++ b/chart2/source/model/template/CorrelationCircleChartTypeTemplate.cxx @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 "CorrelationCircleChartTypeTemplate.hxx" +#include "CorrelationCircleChartType.hxx" +#include "CorrelationCircleDataInterpreter.hxx" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; + +namespace +{ +::cppu::OPropertyArrayHelper& StaticCorrelationCircleChartTypeTemplateInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() { + std::vector aProperties; + std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess()); + return comphelper::containerToSequence(aProperties); + }(); + return aPropHelper; +}; + +} // anonymous namespace + +namespace chart +{ +CorrelationCircleChartTypeTemplate::CorrelationCircleChartTypeTemplate( + Reference const& xContext, const OUString& rServiceName) + : ChartTypeTemplate(xContext, rServiceName) +{ +} + +CorrelationCircleChartTypeTemplate::~CorrelationCircleChartTypeTemplate() {} + +// ____ OPropertySet ____ +void CorrelationCircleChartTypeTemplate::GetDefaultValue(sal_Int32 nHandle, + css::uno::Any& rAny) const +{ + static ::chart::tPropertyValueMap aStaticDefaults; + tPropertyValueMap::const_iterator aFound(aStaticDefaults.find(nHandle)); + if (aFound == aStaticDefaults.end()) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper& CorrelationCircleChartTypeTemplate::getInfoHelper() +{ + return StaticCorrelationCircleChartTypeTemplateInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference CorrelationCircleChartTypeTemplate::getPropertySetInfo() +{ + static const uno::Reference xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo( + StaticCorrelationCircleChartTypeTemplateInfoHelper())); + return xPropertySetInfo; +} + +sal_Int32 CorrelationCircleChartTypeTemplate::getDimension() const { return 2; } + +StackMode CorrelationCircleChartTypeTemplate::getStackMode(sal_Int32 /* nChartTypeIndex */) const +{ + return StackMode::NONE; +} + +void CorrelationCircleChartTypeTemplate::adaptAxes( + const std::vector>& rCoordSys) +{ + ChartTypeTemplate::adaptAxes(rCoordSys); + + // The circle and the two lines through the origin are the frame the arrows + // are read against, so the plot starts with neither grid. + for (rtl::Reference const& xCooSys : rCoordSys) + { + if (!xCooSys.is()) + continue; + + for (sal_Int32 nDimension = 0; nDimension < xCooSys->getDimension(); ++nDimension) + { + rtl::Reference xAxis = AxisHelper::getAxis(nDimension, MAIN_AXIS_INDEX, xCooSys); + if (xAxis.is()) + AxisHelper::makeGridInvisible(xAxis->getGridProperties2()); + } + } +} + +sal_Bool CorrelationCircleChartTypeTemplate::supportsCategories() { return false; } + +bool CorrelationCircleChartTypeTemplate::usesLastTwoColumnsAsDimensions() const { return true; } + +void CorrelationCircleChartTypeTemplate::applyStyle2(const rtl::Reference& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount) +{ + ChartTypeTemplate::applyStyle2(xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount); + + try + { + // The line is the arrow from the origin and the symbol marks its tip. A + // thin line keeps a crowd of arrows apart. + xSeries->switchSymbolsOnOrOff(true, nSeriesIndex); + xSeries->switchLinesOnOrOff(true); + xSeries->makeLinesThickOrThin(false); + + // One point stands for a whole feature, so its name says more than the + // number behind it. + chart2::DataPointLabel aLabel(false, false, false, false, false, true); + xSeries->setPropertyAlsoToAllAttributedDataPoints(CHART_UNONAME_LABEL, + css::uno::Any(aLabel)); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +rtl::Reference + CorrelationCircleChartTypeTemplate::getChartTypeForIndex(sal_Int32 /*nChartTypeIndex*/) +{ + return new CorrelationCircleChartType(); +} + +rtl::Reference CorrelationCircleChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector>& aFormerlyUsedChartTypes) +{ + rtl::Reference xResult(getChartTypeForIndex(0)); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem(aFormerlyUsedChartTypes, xResult); + return xResult; +} + +rtl::Reference CorrelationCircleChartTypeTemplate::getDataInterpreter2() +{ + if (!m_xDataInterpreter.is()) + m_xDataInterpreter.set(new CorrelationCircleDataInterpreter); + + return m_xDataInterpreter; +} + +IMPLEMENT_FORWARD_XINTERFACE2(CorrelationCircleChartTypeTemplate, ChartTypeTemplate, OPropertySet) +IMPLEMENT_FORWARD_XTYPEPROVIDER2(CorrelationCircleChartTypeTemplate, ChartTypeTemplate, + OPropertySet) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/CorrelationCircleChartTypeTemplate.hxx b/chart2/source/model/template/CorrelationCircleChartTypeTemplate.hxx new file mode 100644 index 000000000000..2d4d02412073 --- /dev/null +++ b/chart2/source/model/template/CorrelationCircleChartTypeTemplate.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include +#include +#include + +namespace chart +{ +class CorrelationCircleChartTypeTemplate : public ChartTypeTemplate, public ::property::OPropertySet +{ +public: + explicit CorrelationCircleChartTypeTemplate( + css::uno::Reference const& xContext, + const OUString& rServiceName); + virtual ~CorrelationCircleChartTypeTemplate() override; + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference + SAL_CALL getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual sal_Bool SAL_CALL supportsCategories() override; + virtual bool usesLastTwoColumnsAsDimensions() const override; + virtual rtl::Reference<::chart::ChartType> + getChartTypeForIndex(sal_Int32 nChartTypeIndex) override; + virtual rtl::Reference<::chart::ChartType> getChartTypeForNewSeries2( + const std::vector>& aFormerlyUsedChartTypes) override; + virtual rtl::Reference<::chart::DataInterpreter> getDataInterpreter2() override; + virtual void applyStyle2(const rtl::Reference<::chart::DataSeries>& xSeries, + ::sal_Int32 nChartTypeGroupIndex, ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount) override; + virtual sal_Int32 getDimension() const override; + virtual StackMode getStackMode(sal_Int32 nChartTypeIndex) const override; + virtual void + adaptAxes(const std::vector>& rCoordSys) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/CorrelationCircleDataInterpreter.cxx b/chart2/source/model/template/CorrelationCircleDataInterpreter.cxx new file mode 100644 index 000000000000..18c0192c7ae8 --- /dev/null +++ b/chart2/source/model/template/CorrelationCircleDataInterpreter.cxx @@ -0,0 +1,218 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 "CorrelationCircleDataInterpreter.hxx" +#include +#include +#include + +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ +/** The dimension columns belong to every series, so each series past the first + gets a copy of them. + */ +uno::Reference +lcl_shareWithSeries(const uno::Reference& rShared, + const OUString& rRole, std::size_t nSeriesIndex) +{ + uno::Reference xResult(rShared); + + if (rShared.is() && nSeriesIndex > 0) + { + uno::Reference xCloneable(rShared, uno::UNO_QUERY); + if (xCloneable.is()) + xResult.set(xCloneable->createClone(), uno::UNO_QUERY); + } + + if (xResult.is()) + ::chart::DataInterpreter::SetRole(xResult->getValues(), rRole); + + return xResult; +} + +} // anonymous namespace + +namespace chart +{ +CorrelationCircleDataInterpreter::CorrelationCircleDataInterpreter() {} + +CorrelationCircleDataInterpreter::~CorrelationCircleDataInterpreter() {} + +// ____ XDataInterpreter ____ +InterpretedData CorrelationCircleDataInterpreter::interpretDataSource( + const Reference& xSource, + const Sequence& aArguments, + const std::vector>& aSeriesToReUse) +{ + if (!xSource.is()) + return InterpretedData(); + + std::vector> aData + = DataInterpreter::getDataSequences(xSource); + + uno::Reference xCategories; + if (HasCategories(aArguments, aData) && !aData.empty()) + { + xCategories = aData.front(); + aData.erase(aData.begin()); + if (xCategories.is()) + SetRole(xCategories->getValues(), u"categories"_ustr); + } + + std::vector> aSeriesVec; + + // Two dimension columns and one feature column are the smallest input that + // yields a single point. + if (aData.size() >= 3) + { + uno::Reference xValuesX(aData[aData.size() - 2]); + uno::Reference xValuesY(aData[aData.size() - 1]); + aData.resize(aData.size() - 2); + + aSeriesVec.reserve(aData.size()); + + for (std::size_t nIndex = 0; nIndex < aData.size(); ++nIndex) + { + try + { + std::vector> aNewData{ + lcl_shareWithSeries(xValuesX, u"values-x"_ustr, nIndex), + lcl_shareWithSeries(xValuesY, u"values-y"_ustr, nIndex) + }; + + if (aData[nIndex].is()) + SetRole(aData[nIndex]->getValues(), u"values-feature"_ustr); + aNewData.push_back(aData[nIndex]); + + rtl::Reference xSeries; + if (nIndex < aSeriesToReUse.size()) + xSeries = aSeriesToReUse[nIndex]; + else + xSeries = new DataSeries; + assert(xSeries.is()); + xSeries->setData(aNewData); + + aSeriesVec.push_back(xSeries); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + + return { { std::move(aSeriesVec) }, xCategories }; +} + +InterpretedData +CorrelationCircleDataInterpreter::reinterpretDataSeries(const InterpretedData& aInterpretedData) +{ + InterpretedData aResult(aInterpretedData); + + std::vector> aSeries(FlattenSequence(aInterpretedData.Series)); + for (auto const& xSeries : aSeries) + { + try + { + uno::Reference xValuesFeature( + DataSeriesHelper::getDataSequenceByRole(xSeries, u"values-feature"_ustr)); + uno::Reference xValuesY( + DataSeriesHelper::getDataSequenceByRole(xSeries, u"values-y"_ustr)); + uno::Reference xValuesX( + DataSeriesHelper::getDataSequenceByRole(xSeries, u"values-x"_ustr)); + + if (!xValuesFeature.is() || !xValuesY.is() || !xValuesX.is()) + { + // Sequences the roles above did not claim fill the empty roles + // in turn, so that a series coming from another chart type with + // three sequences keeps all of them. + std::vector> aValueSeqVec( + DataSeriesHelper::getAllDataSequencesByRole(xSeries->getDataSequences2(), + u"values"_ustr)); + for (auto const& xUsed : { xValuesFeature, xValuesY, xValuesX }) + { + if (xUsed.is()) + { + auto aIt = std::find(aValueSeqVec.begin(), aValueSeqVec.end(), xUsed); + if (aIt != aValueSeqVec.end()) + aValueSeqVec.erase(aIt); + } + } + + std::size_t nNextFree = 0; + auto lclTakeNext + = [&aValueSeqVec, + &nNextFree](uno::Reference& rSequence, + const OUString& rRole) { + if (!rSequence.is() && nNextFree < aValueSeqVec.size()) + { + rSequence = aValueSeqVec[nNextFree++]; + if (rSequence.is()) + SetRole(rSequence->getValues(), rRole); + } + }; + + lclTakeNext(xValuesFeature, u"values-feature"_ustr); + lclTakeNext(xValuesY, u"values-y"_ustr); + lclTakeNext(xValuesX, u"values-x"_ustr); + } + + if (xValuesFeature.is() && xValuesX.is() && xValuesY.is()) + { + std::vector> aNewSequences{ + xValuesX, xValuesY, xValuesFeature + }; + if (xSeries->getDataSequences2() != aNewSequences) + xSeries->setData(aNewSequences); + } + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +bool CorrelationCircleDataInterpreter::isDataCompatible(const InterpretedData& aInterpretedData) +{ + const std::vector> aSeries(FlattenSequence(aInterpretedData.Series)); + for (rtl::Reference const& xSeries : aSeries) + { + try + { + if (xSeries->getDataSequences2().size() != 3) + return false; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return true; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/CorrelationCircleDataInterpreter.hxx b/chart2/source/model/template/CorrelationCircleDataInterpreter.hxx new file mode 100644 index 000000000000..778beb08e8d3 --- /dev/null +++ b/chart2/source/model/template/CorrelationCircleDataInterpreter.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include + +namespace chart +{ +/** Reads a flat list of columns as a feature table followed by two dimension + columns: the last two columns become the dimensions, shared by every series, + and each column before them becomes the feature column of one series. + */ +class CorrelationCircleDataInterpreter : public DataInterpreter +{ +public: + explicit CorrelationCircleDataInterpreter(); + virtual ~CorrelationCircleDataInterpreter() override; + +protected: + // ____ DataInterpreter ____ + virtual InterpretedData interpretDataSource( + const css::uno::Reference& xSource, + const css::uno::Sequence& aArguments, + const std::vector>& aSeriesToReUse) override; + virtual InterpretedData reinterpretDataSeries(const InterpretedData& aInterpretedData) override; + virtual bool isDataCompatible(const InterpretedData& aInterpretedData) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/FunnelChartType.cxx b/chart2/source/model/template/FunnelChartType.cxx index d9ffe231063f..fde6a4c0c75b 100644 --- a/chart2/source/model/template/FunnelChartType.cxx +++ b/chart2/source/model/template/FunnelChartType.cxx @@ -9,6 +9,15 @@ #include "FunnelChartType.hxx" #include +#include +#include +#include +#include +#include + +#include +#include + #include namespace com::sun::star::uno @@ -17,6 +26,44 @@ class XComponentContext; } using namespace ::com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::Property; + +namespace +{ +enum +{ + PROP_FUNNELCHARTTYPE_OVERLAP_SEQUENCE, + PROP_FUNNELCHARTTYPE_GAPWIDTH_SEQUENCE +}; + +void lcl_AddPropertiesToVector(std::vector& rOutProperties) +{ + rOutProperties.emplace_back("OverlapSequence", PROP_FUNNELCHARTTYPE_OVERLAP_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back("GapwidthSequence", PROP_FUNNELCHARTTYPE_GAPWIDTH_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); +} + +::cppu::OPropertyArrayHelper& StaticFunnelChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() { + std::vector aProperties; + lcl_AddPropertiesToVector(aProperties); + + std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess()); + + return comphelper::containerToSequence(aProperties); + }(); + return aPropHelper; +}; + +} // anonymous namespace namespace chart { @@ -48,6 +95,79 @@ uno::Sequence FunnelChartType::getSupportedPropertyRoles() return { "FillColor", "BorderColor" }; } +// ____ OPropertySet ____ +void FunnelChartType::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const +{ + static const ::chart::tPropertyValueMap aStaticDefaults = []() { + ::chart::tPropertyValueMap aTmp; + Sequence aSeq{ 0, 0 }; + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_FUNNELCHARTTYPE_OVERLAP_SEQUENCE, aSeq); + aSeq = { 100, 100 }; + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_FUNNELCHARTTYPE_GAPWIDTH_SEQUENCE, aSeq); + return aTmp; + }(); + tPropertyValueMap::const_iterator aFound(aStaticDefaults.find(nHandle)); + if (aFound == aStaticDefaults.end()) + rAny.clear(); + else + rAny = (*aFound).second; +} + +rtl::Reference<::chart::BaseCoordinateSystem> +FunnelChartType::createCoordinateSystem2(sal_Int32 DimensionCount) +{ + rtl::Reference xResult + = new CartesianCoordinateSystem(DimensionCount); + + for (sal_Int32 i = 0; i < DimensionCount; i++) + { + rtl::Reference xAxis = xResult->getAxisByDimension2(i, MAIN_AXIS_INDEX); + if (!xAxis.is()) + continue; + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + + if (i == 0) // X-axis + { + // Set up X-axis specifically for histogram bins + aScaleData.AxisType = chart2::AxisType::CATEGORY; + aScaleData.AutoDateAxis = false; + aScaleData.ShiftedCategoryPosition = true; + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + + // Clear any existing scaling/categories + AxisHelper::removeExplicitScaling(aScaleData); + aScaleData.Categories.clear(); + } + else if (i == 1) // Y-axis + { + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + aScaleData.ShiftedCategoryPosition = false; + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + aScaleData.Scaling = AxisHelper::createLinearScaling(); + } + + xAxis->setScaleData(aScaleData); + } + + return xResult; +} + +::cppu::IPropertyArrayHelper& SAL_CALL FunnelChartType::getInfoHelper() +{ + return StaticFunnelChartTypeInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference SAL_CALL FunnelChartType::getPropertySetInfo() +{ + static uno::Reference xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticFunnelChartTypeInfoHelper())); + return xPropertySetInfo; +} + OUString SAL_CALL FunnelChartType::getImplementationName() { return "com.sun.star.comp.chart.FunnelChartType"; diff --git a/chart2/source/model/template/FunnelChartType.hxx b/chart2/source/model/template/FunnelChartType.hxx index fbaa3f46354d..f67a9a8561a0 100644 --- a/chart2/source/model/template/FunnelChartType.hxx +++ b/chart2/source/model/template/FunnelChartType.hxx @@ -8,7 +8,9 @@ */ #pragma once +#include #include +#include namespace chart { @@ -27,10 +29,21 @@ public: private: explicit FunnelChartType(const FunnelChartType& rOther); + virtual rtl::Reference<::chart::BaseCoordinateSystem> + createCoordinateSystem2(sal_Int32 DimensionCount) override; + // ____ XChartType ____ virtual OUString SAL_CALL getChartType() override; virtual css::uno::Sequence SAL_CALL getSupportedPropertyRoles() override; + // ____ OPropertySet ____ + virtual void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference + SAL_CALL getPropertySetInfo() override; + // ____ XCloneable ____ virtual css::uno::Reference SAL_CALL createClone() override; }; diff --git a/chart2/source/model/template/FunnelChartTypeTemplate.cxx b/chart2/source/model/template/FunnelChartTypeTemplate.cxx index a262b8ab23bf..1dff397bccd2 100644 --- a/chart2/source/model/template/FunnelChartTypeTemplate.cxx +++ b/chart2/source/model/template/FunnelChartTypeTemplate.cxx @@ -32,7 +32,8 @@ namespace enum { PROP_FUNNEL_TEMPLATE_DIMENSION, - PROP_FUNNEL_TEMPLATE_GEOMETRY3D + PROP_FUNNEL_TEMPLATE_GEOMETRY3D, + PROP_FUNNEL_TEMPLATE_GAPWIDTH_SEQUENCE }; void lcl_AddPropertiesToVector(std::vector& rOutProperties) @@ -43,6 +44,10 @@ void lcl_AddPropertiesToVector(std::vector& rOutProperties) rOutProperties.emplace_back( "Geometry3D", PROP_FUNNEL_TEMPLATE_GEOMETRY3D, cppu::UnoType::get(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + rOutProperties.emplace_back("GapwidthSequence", PROP_FUNNEL_TEMPLATE_GAPWIDTH_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); } ::cppu::OPropertyArrayHelper& StaticFunnelChartTypeTemplateInfoHelper() diff --git a/chart2/source/model/template/HistogramCalculator.cxx b/chart2/source/model/template/HistogramCalculator.cxx new file mode 100644 index 000000000000..c8d51e90a3a4 --- /dev/null +++ b/chart2/source/model/template/HistogramCalculator.cxx @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include + +namespace chart +{ +namespace +{ +/** Bins of the given width needed to span the given range, capped at MAX_HISTOGRAM_BINS and + at least one. Dividing in double saturates at the cap instead of overflowing the cast. */ +sal_Int32 lcl_binCountForWidth(double fRange, double fBinWidth) +{ + if (!(fRange > 0.0) || !(fBinWidth > 0.0)) + return 1; + + const double fBins = std::ceil(fRange / fBinWidth); + if (!(fBins >= 1.0)) + return 1; + + return sal_Int32(std::min(fBins, double(MAX_HISTOGRAM_BINS))); +} +} + +HistogramCalculator::HistogramCalculator() = default; + +void HistogramCalculator::computeBinFrequencyHistogram( + const std::vector& rDataPoints, sal_Int32 nFrequencyType, double fFixedBinWidth, + sal_Int32 nFixedBinCount, bool bUseUnderflowBin, double fUnderflowBinValue, + bool bUseOverflowBin, double fOverflowBinValue) +{ + if (rDataPoints.empty()) + return; + + mnBins = 1; + mfBinWidth = 1.0; + maBinRanges.clear(); + maBinFrequencies.clear(); + maBinTypes.clear(); + + // Calculate statistics + double fSum = 0.0; + double fSquareSum = 0.0; + double fMinValue = rDataPoints[0]; + double fMaxValue = rDataPoints[0]; + sal_Int32 nValidCount = 0; + + // Compute min and max values, ignoring non-finite values + for (const auto& rValue : rDataPoints) + { + if (std::isfinite(rValue)) + { + if (nValidCount == 0) + { + fMinValue = rValue; + fMaxValue = rValue; + } + else + { + fMinValue = std::min(fMinValue, rValue); + fMaxValue = std::max(fMaxValue, rValue); + } + + fSum += rValue; + fSquareSum += rValue * rValue; + ++nValidCount; + } + } + + if (nValidCount == 0) + return; + + const bool bHasUnderflow = bUseUnderflowBin && std::isfinite(fUnderflowBinValue); + const bool bHasOverflow = bUseOverflowBin && std::isfinite(fOverflowBinValue); + + // Ignore both special bins if their boundaries cross; otherwise normal bins + // would have an invalid range. + const bool bUseSpecialBins + = !(bHasUnderflow && bHasOverflow && fUnderflowBinValue >= fOverflowBinValue); + + const bool bEffectiveUnderflow = bHasUnderflow && bUseSpecialBins; + const bool bEffectiveOverflow = bHasOverflow && bUseSpecialBins; + + double fEffectiveMin = bEffectiveUnderflow ? fUnderflowBinValue : fMinValue; + double fEffectiveMax = bEffectiveOverflow ? fOverflowBinValue : fMaxValue; + + if (fEffectiveMin >= fEffectiveMax) + { + fEffectiveMin = fMinValue; + fEffectiveMax = fMaxValue; + } + + if (nValidCount < 2 || fEffectiveMin == fEffectiveMax) // Need at least two points for variance + { + mnBins = 1; + mfBinWidth = 1.0; + + if (bEffectiveUnderflow) + { + maBinTypes.push_back(HistogramBinType::Underflow); + maBinRanges.emplace_back(fUnderflowBinValue, fUnderflowBinValue); + } + + maBinTypes.push_back(HistogramBinType::Normal); + maBinRanges.emplace_back(std::floor(fEffectiveMin), std::ceil(fEffectiveMin + 1.0)); + + if (bEffectiveOverflow) + { + maBinTypes.push_back(HistogramBinType::Overflow); + maBinRanges.emplace_back(fOverflowBinValue, fOverflowBinValue); + } + + maBinFrequencies.assign(maBinRanges.size(), 0); + } + else + { + // Pick bin width / count based on frequency-type mode. Invalid fixed values + // fall back to auto so stale or unset properties cannot produce a degenerate histogram. + bool bResolved = false; + if (nFrequencyType == 1 && fFixedBinWidth > 0.0) + { + mfBinWidth = fFixedBinWidth; + mnBins = lcl_binCountForWidth(fEffectiveMax - fEffectiveMin, mfBinWidth); + bResolved = true; + } + else if (nFrequencyType == 2 && nFixedBinCount > 0) + { + mnBins = std::min(nFixedBinCount, MAX_HISTOGRAM_BINS); + mfBinWidth = (fEffectiveMax - fEffectiveMin) / mnBins; + bResolved = true; + } + + if (!bResolved) + { + // Auto: Scott's rule. + double fMean = fSum / nValidCount; + double fVariance = (fSquareSum - fSum * fMean) / (nValidCount - 1); + double fStdDev = std::sqrt(fVariance); + + mfBinWidth = (3.5 * fStdDev) / std::cbrt(nValidCount); + mnBins = lcl_binCountForWidth(fEffectiveMax - fEffectiveMin, mfBinWidth); + } + + // A capped count or a zero width no longer spans the range, so divide it evenly. + if (!(mfBinWidth > 0.0) || mnBins == MAX_HISTOGRAM_BINS) + mfBinWidth = (fEffectiveMax - fEffectiveMin) / mnBins; + + maBinRanges.reserve(mnBins + (bEffectiveUnderflow ? 1 : 0) + (bEffectiveOverflow ? 1 : 0)); + maBinTypes.reserve(mnBins + (bEffectiveUnderflow ? 1 : 0) + (bEffectiveOverflow ? 1 : 0)); + + if (bEffectiveUnderflow) + { + maBinTypes.push_back(HistogramBinType::Underflow); + maBinRanges.emplace_back(fUnderflowBinValue, fUnderflowBinValue); + } + + double fBinStart = fEffectiveMin; + for (sal_Int32 i = 0; i < mnBins; ++i) + { + double fBinEnd = fBinStart + mfBinWidth; + + maBinTypes.push_back(HistogramBinType::Normal); + maBinRanges.emplace_back(fBinStart, fBinEnd); + + fBinStart = fBinEnd; + } + + // With an overflow bin, values above the overflow boundary belong to the overflow bin + if (!maBinRanges.empty()) + { + size_t nLastNormal = maBinRanges.size() - 1; + if (bEffectiveOverflow) + maBinRanges[nLastNormal].second = fEffectiveMax; + else + maBinRanges[nLastNormal].second + = std::max(maBinRanges[nLastNormal].second, fEffectiveMax); + } + + if (bEffectiveOverflow) + { + maBinTypes.push_back(HistogramBinType::Overflow); + maBinRanges.emplace_back(fOverflowBinValue, fOverflowBinValue); + } + + maBinFrequencies.assign(maBinRanges.size(), 0); + } + + // Calculate frequencies. Underflow is <= boundary, overflow is > boundary. + // Normal bins are [start,end] for the first bin unless an underflow bin exists; + // otherwise they are (start,end]. + for (double fValue : rDataPoints) + { + if (!std::isfinite(fValue)) + continue; + + for (size_t i = 0; i < maBinRanges.size(); ++i) + { + if (maBinTypes[i] == HistogramBinType::Underflow) + { + if (fValue <= maBinRanges[i].second) + { + maBinFrequencies[i]++; + break; + } + continue; + } + + if (maBinTypes[i] == HistogramBinType::Overflow) + { + if (fValue > maBinRanges[i].first) + { + maBinFrequencies[i]++; + break; + } + continue; + } + + const bool bPreviousIsUnderflow + = i > 0 && maBinTypes[i - 1] == HistogramBinType::Underflow; + const bool bFirstNormalBin = i == 0 || bPreviousIsUnderflow; + + const bool bInBin + = bFirstNormalBin && !bPreviousIsUnderflow + ? fValue >= maBinRanges[i].first && fValue <= maBinRanges[i].second + : fValue > maBinRanges[i].first && fValue <= maBinRanges[i].second; + + if (bInBin) + { + maBinFrequencies[i]++; + break; + } + } + } +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramChartType.cxx b/chart2/source/model/template/HistogramChartType.cxx new file mode 100644 index 000000000000..a4b512785dd7 --- /dev/null +++ b/chart2/source/model/template/HistogramChartType.cxx @@ -0,0 +1,392 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "HistogramChartType.hxx" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +using namespace ::com::sun::star; + +namespace +{ +enum +{ + PROP_HISTOGRAMCHARTTYPE_BINWIDTH, + PROP_HISTOGRAMCHARTTYPE_BINCOUNT, + PROP_HISTOGRAMCHARTTYPE_FREQUENCYTYPE, + PROP_HISTOGRAMCHARTTYPE_OVERLAP_SEQUENCE, + PROP_HISTOGRAMCHARTTYPE_GAPWIDTH_SEQUENCE, + PROP_HISTOGRAMCHARTTYPE_USEUNDERFLOWBIN, + PROP_HISTOGRAMCHARTTYPE_UNDERFLOWBINVALUE, + PROP_HISTOGRAMCHARTTYPE_USEOVERFLOWBIN, + PROP_HISTOGRAMCHARTTYPE_OVERFLOWBINVALUE +}; + +void lcl_AddPropertiesToVector(std::vector& rOutProperties) +{ + rOutProperties.emplace_back( + "BinWidth", PROP_HISTOGRAMCHARTTYPE_BINWIDTH, cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back( + "BinCount", PROP_HISTOGRAMCHARTTYPE_BINCOUNT, cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back( + "FrequencyType", PROP_HISTOGRAMCHARTTYPE_FREQUENCYTYPE, cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back("OverlapSequence", PROP_HISTOGRAMCHARTTYPE_OVERLAP_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back("GapwidthSequence", PROP_HISTOGRAMCHARTTYPE_GAPWIDTH_SEQUENCE, + cppu::UnoType>::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back( + "UseUnderflowBin", PROP_HISTOGRAMCHARTTYPE_USEUNDERFLOWBIN, cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back("UnderflowBinValue", PROP_HISTOGRAMCHARTTYPE_UNDERFLOWBINVALUE, + cppu::UnoType::get(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back( + "UseOverflowBin", PROP_HISTOGRAMCHARTTYPE_USEOVERFLOWBIN, cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); + + rOutProperties.emplace_back( + "OverflowBinValue", PROP_HISTOGRAMCHARTTYPE_OVERFLOWBINVALUE, cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); +} + +::cppu::OPropertyArrayHelper& StaticHistogramChartTypeInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() { + std::vector aProperties; + lcl_AddPropertiesToVector(aProperties); + + std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess()); + + return comphelper::containerToSequence(aProperties); + }(); + return aPropHelper; +}; + +} // anonymous namespace + +namespace chart +{ +HistogramChartType::HistogramChartType() {} + +HistogramChartType::HistogramChartType(const HistogramChartType& rOther) + : ChartType(rOther) +{ +} + +HistogramChartType::~HistogramChartType() {} + +// ____ XCloneable ____ +uno::Reference SAL_CALL HistogramChartType::createClone() +{ + return uno::Reference(new HistogramChartType(*this)); +} + +rtl::Reference HistogramChartType::cloneChartType() const +{ + return new HistogramChartType(*this); +} + +// ____ XChartType ____ +rtl::Reference<::chart::BaseCoordinateSystem> +HistogramChartType::createCoordinateSystem2(sal_Int32 DimensionCount) +{ + rtl::Reference xResult + = new CartesianCoordinateSystem(DimensionCount); + + for (sal_Int32 i = 0; i < DimensionCount; i++) + { + rtl::Reference xAxis = xResult->getAxisByDimension2(i, MAIN_AXIS_INDEX); + if (!xAxis.is()) + continue; + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + + if (i == 0) // X-axis + { + // Set up X-axis specifically for histogram bins + aScaleData.AxisType = chart2::AxisType::CATEGORY; + aScaleData.AutoDateAxis = false; + aScaleData.ShiftedCategoryPosition = true; + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + + // Clear any existing scaling/categories + AxisHelper::removeExplicitScaling(aScaleData); + aScaleData.Categories.clear(); + } + else if (i == 1) // Y-axis + { + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + aScaleData.ShiftedCategoryPosition = false; + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + aScaleData.Scaling = AxisHelper::createLinearScaling(); + } + + xAxis->setScaleData(aScaleData); + } + + return xResult; +} + +void HistogramChartType::createCalculatedDataSeries() +{ + if (m_aDataSeries.empty()) + { + return; + } + + // Snapshot the current binning parameters so each new HistogramDataSequence + // runs the calculator in the correct mode (auto / fixed width / fixed count). + sal_Int32 nFrequencyType = 0; + double fBinWidth = 0.0; + sal_Int32 nBinCount = 0; + bool bUseUnderflowBin = false; + double fUnderflowBinValue = 0.0; + bool bUseOverflowBin = false; + double fOverflowBinValue = 0.0; + try + { + getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType; + getPropertyValue(u"BinWidth"_ustr) >>= fBinWidth; + getPropertyValue(u"BinCount"_ustr) >>= nBinCount; + getPropertyValue(u"UseUnderflowBin"_ustr) >>= bUseUnderflowBin; + getPropertyValue(u"UnderflowBinValue"_ustr) >>= fUnderflowBinValue; + getPropertyValue(u"UseOverflowBin"_ustr) >>= bUseOverflowBin; + getPropertyValue(u"OverflowBinValue"_ustr) >>= fOverflowBinValue; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + for (const auto& xSeries : m_aDataSeries) + { + if (!xSeries.is()) + { + continue; + } + + // 1. Find the raw values-y + uno::Reference xValuesY; + auto aSeqs = xSeries->getDataSequences2(); + for (const auto& seq : aSeqs) + { + if (seq.is() && seq->getValues().is() && DataSeriesHelper::getRole(seq) == "values-y") + { + xValuesY = seq->getValues(); + break; + } + } + + if (!xValuesY.is()) + { + continue; + } + + // 2. Regenerate the calculated-y frequencies + rtl::Reference xCalcSeq = new HistogramDataSequence( + xValuesY, false, nFrequencyType, fBinWidth, nBinCount, bUseUnderflowBin, + fUnderflowBinValue, bUseOverflowBin, fOverflowBinValue); + uno::Reference xLabeledCalc + = new LabeledDataSequence(xCalcSeq); + xSeries->setCalculatedYSequence(xLabeledCalc); + + auto createCategorySequence = [&]() { + rtl::Reference xCatSeq = new HistogramDataSequence( + xValuesY, true, nFrequencyType, fBinWidth, nBinCount, bUseUnderflowBin, + fUnderflowBinValue, bUseOverflowBin, fOverflowBinValue); + + uno::Reference xCatDataSeq(xCatSeq); + uno::Reference xCatProp(xCatDataSeq, uno::UNO_QUERY); + if (xCatProp.is()) + { + xCatProp->setPropertyValue(u"Role"_ustr, uno::Any(u"categories"_ustr)); + } + + return uno::Reference( + new LabeledDataSequence(xCatSeq)); + }; + + // 3. Update existing histogram categories in place. The X axis and the DataSeries hold + // the same sequence, so new bin parameters reach the axis labels through it. + bool bHasCategories = false; + for (auto& seq : aSeqs) + { + if (!seq.is() || DataSeriesHelper::getRole(seq) != u"categories"_ustr) + continue; + + rtl::Reference xHistogramSequence + = dynamic_cast(seq->getValues().get()); + + if (xHistogramSequence.is()) + { + xHistogramSequence->setBinningParameters(nFrequencyType, fBinWidth, nBinCount, + bUseUnderflowBin, fUnderflowBinValue, + bUseOverflowBin, fOverflowBinValue); + } + else + { + seq = createCategorySequence(); + } + + bHasCategories = true; + break; + } + + // 4. Attach generated categories when the series does not have them yet + if (!bHasCategories) + aSeqs.push_back(createCategorySequence()); + + xSeries->setData(aSeqs); + } +} + +OUString SAL_CALL HistogramChartType::getChartType() +{ + return CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM; +} + +uno::Sequence SAL_CALL HistogramChartType::getSupportedMandatoryRoles() +{ + return { u"label"_ustr, u"values-y"_ustr }; +} + +uno::Sequence SAL_CALL HistogramChartType::getSupportedOptionalRoles() { return {}; } + +uno::Sequence HistogramChartType::getSupportedPropertyRoles() +{ + return { u"FillColor"_ustr, u"BorderColor"_ustr }; +} + +::cppu::IPropertyArrayHelper& SAL_CALL HistogramChartType::getInfoHelper() +{ + return StaticHistogramChartTypeInfoHelper(); +} + +// ____ OPropertySet ____ +void HistogramChartType::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const +{ + static const ::chart::tPropertyValueMap aStaticDefaults = []() { + ::chart::tPropertyValueMap aTmp; + uno::Sequence aSeq{ 0 }; // No gap for histogram + + ::chart::PropertyHelper::setPropertyValueDefault(aTmp, PROP_HISTOGRAMCHARTTYPE_BINWIDTH, + 2.0); + ::chart::PropertyHelper::setPropertyValueDefault(aTmp, PROP_HISTOGRAMCHARTTYPE_BINCOUNT, + sal_Int32(10)); + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAMCHARTTYPE_FREQUENCYTYPE, sal_Int32(0)); + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAMCHARTTYPE_OVERLAP_SEQUENCE, aSeq); + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAMCHARTTYPE_GAPWIDTH_SEQUENCE, aSeq); + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAMCHARTTYPE_USEUNDERFLOWBIN, false); + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAMCHARTTYPE_UNDERFLOWBINVALUE, 0.0); + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAMCHARTTYPE_USEOVERFLOWBIN, false); + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAMCHARTTYPE_OVERFLOWBINVALUE, 0.0); + + return aTmp; + }(); + + tPropertyValueMap::const_iterator aFound(aStaticDefaults.find(nHandle)); + if (aFound == aStaticDefaults.end()) + rAny.clear(); + else + rAny = (*aFound).second; +} + +// HistogramDataSequence snapshots binning settings, so changing histogram +// bin properties must rebuild the derived frequency and category sequences. +void HistogramChartType::firePropertyChangeEvent() +{ + createCalculatedDataSeries(); + ChartType::firePropertyChangeEvent(); +} + +// ____ XPropertySet ____ +uno::Reference SAL_CALL HistogramChartType::getPropertySetInfo() +{ + static uno::Reference xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo(StaticHistogramChartTypeInfoHelper())); + return xPropertySetInfo; +} + +OUString SAL_CALL HistogramChartType::getImplementationName() +{ + return "com.sun.star.comp.chart.HistogramChartType"; +} + +sal_Bool SAL_CALL HistogramChartType::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence SAL_CALL HistogramChartType::getSupportedServiceNames() +{ + return { CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM, "com.sun.star.chart2.ChartType" }; +} + +} // namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_chart_HistogramChartType_get_implementation( + css::uno::XComponentContext* /*context*/, css::uno::Sequence const&) +{ + return cppu::acquire(new ::chart::HistogramChartType()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramChartType.hxx b/chart2/source/model/template/HistogramChartType.hxx new file mode 100644 index 000000000000..6eadee5e151b --- /dev/null +++ b/chart2/source/model/template/HistogramChartType.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +namespace chart +{ +class HistogramChartType : public ChartType +{ +public: + explicit HistogramChartType(); + virtual ~HistogramChartType() override; + + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + + virtual rtl::Reference cloneChartType() const override; + +protected: + explicit HistogramChartType(const HistogramChartType& rOther); + + // ____ XChartType ____ + rtl::Reference<::chart::BaseCoordinateSystem> + createCoordinateSystem2(sal_Int32 DimensionCount) override; + + virtual void createCalculatedDataSeries() override; + + OUString SAL_CALL getChartType() override; + css::uno::Sequence SAL_CALL getSupportedPropertyRoles() override; + css::uno::Sequence SAL_CALL getSupportedMandatoryRoles() override; + css::uno::Sequence SAL_CALL getSupportedOptionalRoles() override; + + // ____ OPropertySet ____ + void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override; + ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + virtual void firePropertyChangeEvent() override; + + // ____ XPropertySet ____ + css::uno::Reference SAL_CALL getPropertySetInfo() override; + + // ____ XCloneable ____ + css::uno::Reference SAL_CALL createClone() override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ \ No newline at end of file diff --git a/chart2/source/model/template/HistogramChartTypeTemplate.cxx b/chart2/source/model/template/HistogramChartTypeTemplate.cxx new file mode 100644 index 000000000000..4e58fd435555 --- /dev/null +++ b/chart2/source/model/template/HistogramChartTypeTemplate.cxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "HistogramChartType.hxx" +#include "HistogramChartTypeTemplate.hxx" +#include "HistogramDataInterpreter.hxx" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace +{ +enum +{ + PROP_HISTOGRAM_TEMPLATE_DIMENSION, +}; + +void lcl_AddPropertiesToVector(std::vector& rOutProperties) +{ + rOutProperties.emplace_back( + "Dimension", PROP_HISTOGRAM_TEMPLATE_DIMENSION, cppu::UnoType::get(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT); +} + +::cppu::OPropertyArrayHelper& StaticHistogramChartTypeTemplateInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aPropHelper = []() { + std::vector aProperties; + lcl_AddPropertiesToVector(aProperties); + + std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess()); + + return comphelper::containerToSequence(aProperties); + }(); + return aPropHelper; +}; + +} // anonymous namespace + +namespace chart +{ +HistogramChartTypeTemplate::HistogramChartTypeTemplate( + uno::Reference const& xContext, const OUString& rServiceName, + StackMode eStackMode, sal_Int32 nDim /* = 2 */) + : ChartTypeTemplate(xContext, rServiceName) + , m_eStackMode(eStackMode) + , m_nDim(nDim) +{ +} + +sal_Int32 HistogramChartTypeTemplate::getDimension() const { return m_nDim; } + +StackMode HistogramChartTypeTemplate::getStackMode(sal_Int32 /* nChartTypeIndex */) const +{ + return m_eStackMode; +} + +rtl::Reference + HistogramChartTypeTemplate::getChartTypeForIndex(sal_Int32 /*nChartTypeIndex*/) +{ + return new HistogramChartType(); +} + +rtl::Reference HistogramChartTypeTemplate::getChartTypeForNewSeries2( + const std::vector>& aFormerlyUsedChartTypes) +{ + rtl::Reference xResult(getChartTypeForIndex(0)); + ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem(aFormerlyUsedChartTypes, xResult); + return xResult; +} + +// ____ OPropertySet ____ +void HistogramChartTypeTemplate::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const +{ + static ::chart::tPropertyValueMap aStaticDefaults = []() { + ::chart::tPropertyValueMap aTmp; + ::chart::PropertyHelper::setPropertyValueDefault( + aTmp, PROP_HISTOGRAM_TEMPLATE_DIMENSION, 2); + return aTmp; + }(); + tPropertyValueMap::const_iterator aFound(aStaticDefaults.find(nHandle)); + if (aFound == aStaticDefaults.end()) + rAny.clear(); + else + rAny = (*aFound).second; +} + +::cppu::IPropertyArrayHelper& SAL_CALL HistogramChartTypeTemplate::getInfoHelper() +{ + return StaticHistogramChartTypeTemplateInfoHelper(); +} + +// ____ XPropertySet ____ +uno::Reference SAL_CALL HistogramChartTypeTemplate::getPropertySetInfo() +{ + static uno::Reference xPropertySetInfo( + ::cppu::OPropertySetHelper::createPropertySetInfo( + StaticHistogramChartTypeTemplateInfoHelper())); + return xPropertySetInfo; +} + +void HistogramChartTypeTemplate::applyStyle2(const rtl::Reference& xSeries, + ::sal_Int32 nChartTypeIndex, ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount) +{ + ChartTypeTemplate::applyStyle2(xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount); + xSeries->setPropertyAlsoToAllAttributedDataPoints("BorderStyle", + uno::Any(drawing::LineStyle_NONE)); +} + +void HistogramChartTypeTemplate::resetStyles2(const rtl::Reference<::chart::Diagram>& xDiagram) +{ + ChartTypeTemplate::resetStyles2(xDiagram); + std::vector> aSeriesVec(xDiagram->getDataSeries()); + uno::Any aLineStyleAny(drawing::LineStyle_NONE); + for (auto const& series : aSeriesVec) + { + if (series->getPropertyValue("BorderStyle") == aLineStyleAny) + { + series->setPropertyToDefault("BorderStyle"); + } + } + + xDiagram->setVertical(false); +} + +rtl::Reference HistogramChartTypeTemplate::getDataInterpreter2() +{ + if (!m_xDataInterpreter.is()) + m_xDataInterpreter.set(new HistogramDataInterpreter); + + return m_xDataInterpreter; +} + +IMPLEMENT_FORWARD_XINTERFACE2(HistogramChartTypeTemplate, ChartTypeTemplate, OPropertySet) +IMPLEMENT_FORWARD_XTYPEPROVIDER2(HistogramChartTypeTemplate, ChartTypeTemplate, OPropertySet) + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ \ No newline at end of file diff --git a/chart2/source/model/template/HistogramChartTypeTemplate.hxx b/chart2/source/model/template/HistogramChartTypeTemplate.hxx new file mode 100644 index 000000000000..bee25d545484 --- /dev/null +++ b/chart2/source/model/template/HistogramChartTypeTemplate.hxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include +#include +#include + +#include + +namespace chart +{ +class HistogramChartTypeTemplate : public ChartTypeTemplate, public ::property::OPropertySet +{ +public: + explicit HistogramChartTypeTemplate( + css::uno::Reference const& xContext, + const OUString& rServiceName, StackMode eStackMode, sal_Int32 nDim = 2); + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + + // ____ XPropertySet ____ + virtual css::uno::Reference + SAL_CALL getPropertySetInfo() override; + + // ____ ChartTypeTemplate ____ + virtual rtl::Reference<::chart::ChartType> getChartTypeForNewSeries2( + const std::vector>& aFormerlyUsedChartTypes) override; + + virtual sal_Bool SAL_CALL supportsCategories() override { return true; } + + virtual void applyStyle2(const rtl::Reference<::chart::DataSeries>& xSeries, + ::sal_Int32 nChartTypeGroupIndex, ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount) override; + + virtual void resetStyles2(const rtl::Reference<::chart::Diagram>& xDiagram) override; + + virtual rtl::Reference<::chart::ChartType> + getChartTypeForIndex(sal_Int32 nChartTypeIndex) override; + + virtual sal_Int32 getDimension() const override; + virtual StackMode getStackMode(sal_Int32 nChartTypeIndex) const override; + rtl::Reference getDataInterpreter2() override; + +private: + StackMode m_eStackMode; + sal_Int32 m_nDim; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ \ No newline at end of file diff --git a/chart2/source/model/template/HistogramDataInterpreter.cxx b/chart2/source/model/template/HistogramDataInterpreter.cxx new file mode 100644 index 000000000000..13beb7d52940 --- /dev/null +++ b/chart2/source/model/template/HistogramDataInterpreter.cxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include "HistogramDataInterpreter.hxx" +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +using namespace css; + +namespace chart +{ +InterpretedData HistogramDataInterpreter::interpretDataSource( + const uno::Reference& xSource, + const uno::Sequence& /*aArguments*/, + const std::vector>& aSeriesToReUse) +{ + if (!xSource.is()) + { + return InterpretedData(); + } + + std::vector> sourceSequences + = DataInterpreter::getDataSequences(xSource); + + uno::Reference valuesYSeqLabeled; + uno::Reference valuesYSeqData; + + for (const auto& seq : sourceSequences) + { + if (seq.is() && seq->getValues().is() && DataSeriesHelper::getRole(seq) == u"values-y") + { + valuesYSeqLabeled = seq; + valuesYSeqData = seq->getValues(); + break; + } + } + + if (!valuesYSeqData.is()) + return InterpretedData(); + + // True = Categories (Bins), False = Frequencies (Heights) + rtl::Reference xCategoryValuesSeq + = new HistogramDataSequence(valuesYSeqData, true); + rtl::Reference xCalcSequenceImpl + = new HistogramDataSequence(valuesYSeqData, false); + + uno::Reference xCategoryDataSeq(xCategoryValuesSeq); + uno::Reference xCategoryProp(xCategoryDataSeq, uno::UNO_QUERY); + if (xCategoryProp.is()) + xCategoryProp->setPropertyValue(u"Role"_ustr, uno::Any(u"categories"_ustr)); + + uno::Reference xLabeledCategorySeq + = new LabeledDataSequence(xCategoryValuesSeq); + uno::Reference xLabeledFreqSeq + = new LabeledDataSequence(xCalcSequenceImpl); + + InterpretedData result; + result.Categories = xLabeledCategorySeq; + + rtl::Reference resultSeries; + if (!aSeriesToReUse.empty() && aSeriesToReUse[0].is()) + { + resultSeries = aSeriesToReUse[0]; + resultSeries->setData(DataSeries::tDataSequenceContainer{}); + } + else + { + resultSeries = new DataSeries(); + } + + // The diagram axis and the DataSeries hold the same generated category sequence, so new + // bin settings reach the X axis labels through it. + resultSeries->setData( + DataSeries::tDataSequenceContainer{ valuesYSeqLabeled, xLabeledCategorySeq }); + resultSeries->setCalculatedYSequence(xLabeledFreqSeq); + + // Structure the result: one group, one series for a standard histogram + // When multiple data columns are selected, only the first values-y series is used to build the histogram. + result.Series.resize(1); + result.Series[0].resize(1); + result.Series[0][0] = resultSeries; + + return result; +} + +InterpretedData +HistogramDataInterpreter::reinterpretDataSeries(const InterpretedData& rInterpretedData) +{ + rtl::Reference xSource = DataInterpreter::mergeInterpretedData(rInterpretedData); + std::vector> aSeriesToReUse + = FlattenSequence(rInterpretedData.Series); + + uno::Sequence aArguments; + return interpretDataSource(xSource, aArguments, aSeriesToReUse); +} + +bool HistogramDataInterpreter::isDataCompatible(const InterpretedData& aInterpretedData) +{ + // We need at least one numerical data series for histogram + const std::vector> aSeries(FlattenSequence(aInterpretedData.Series)); + + if (aSeries.empty()) + return false; + + // Check if we have valid numerical data + for (const auto& xSeries : aSeries) + { + if (!xSeries.is()) + continue; + + bool bFoundValidData = false; + const auto& sequences = xSeries->getDataSequences2(); + + for (const auto& seq : sequences) + { + if (!seq.is() || !seq->getValues().is()) + continue; + + OUString role = DataSeriesHelper::getRole(seq); + if (role == u"values-y") + { + try + { + uno::Sequence data = seq->getValues()->getData(); + if (!data.hasElements()) + continue; + + // Check first element is numerical + double dummy; + if (data[0] >>= dummy) + { + bFoundValidData = true; + break; + } + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + + if (!bFoundValidData) + return false; + } + + return true; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/model/template/HistogramDataInterpreter.hxx b/chart2/source/model/template/HistogramDataInterpreter.hxx new file mode 100644 index 000000000000..d995578bfed1 --- /dev/null +++ b/chart2/source/model/template/HistogramDataInterpreter.hxx @@ -0,0 +1,37 @@ +/* -*- 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/. + */ + +#pragma once + +#include + +namespace chart +{ +/** DataInterpreter for histogram charts. + * Preserves the input column as values-y and attaches derived HistogramDataSequence + * sidecars for bin labels and frequencies. */ +class HistogramDataInterpreter : public DataInterpreter +{ +public: + explicit HistogramDataInterpreter() = default; + +protected: + virtual InterpretedData interpretDataSource( + const css::uno::Reference& xSource, + const css::uno::Sequence& aArguments, + const std::vector>& aSeriesToReUse) override; + + virtual InterpretedData reinterpretDataSeries(const InterpretedData& aInterpretedData) override; + + virtual bool isDataCompatible(const InterpretedData& aInterpretedData) override; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/model/template/LineChartType.cxx b/chart2/source/model/template/LineChartType.cxx index 4d75a029b944..fa0cf6cdccd1 100644 --- a/chart2/source/model/template/LineChartType.cxx +++ b/chart2/source/model/template/LineChartType.cxx @@ -52,7 +52,7 @@ enum ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_LINECHARTTYPE_CURVE_STYLE, ::chart2::CurveStyle_LINES ); ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_CURVE_RESOLUTION, 20 ); - // todo: check whether order 3 means polygons of order 3 or 2. (see + // todo: check whether order 3 means polynomials of order 3 or 2. (see // http://www.people.nnov.ru/fractal/Splines/Basis.htm ) ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_SPLINE_ORDER, 3 ); return aOutMap; diff --git a/chart2/source/tools/AxisHelper.cxx b/chart2/source/tools/AxisHelper.cxx index 52979751186d..082a306790b4 100644 --- a/chart2/source/tools/AxisHelper.cxx +++ b/chart2/source/tools/AxisHelper.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1011,6 +1012,33 @@ rtl::Reference< ChartType > AxisHelper::getChartTypeByIndex( const rtl::Referenc return xChartType; } +rtl::Reference AxisHelper::getHistogramChartTypeOfAxis( + const rtl::Reference< Axis >& xAxis, const rtl::Reference< ChartModel >& xChartDoc) +{ + if (!xAxis.is() || !xChartDoc.is()) + return nullptr; + + rtl::Reference xCooSys( + AxisHelper::getCoordinateSystemOfAxis(xAxis, xChartDoc->getFirstChartDiagram())); + if (!xCooSys.is()) + return nullptr; + + // The bin settings sit on the chart type, and the primary X axis is the one that shows them. + sal_Int32 nDimensionIndex = -1; + sal_Int32 nAxisIndex = -1; + if (!AxisHelper::getIndicesForAxis(xAxis, xCooSys, nDimensionIndex, nAxisIndex) + || nDimensionIndex != 0 || nAxisIndex != 0) + { + return nullptr; + } + + rtl::Reference xChartType(AxisHelper::getChartTypeByIndex(xCooSys, 0)); + if (!xChartType.is() || xChartType->getChartType() != CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM) + return nullptr; + + return xChartType; +} + void AxisHelper::setRTLAxisLayout( const rtl::Reference< BaseCoordinateSystem >& xCooSys ) { if( !xCooSys.is() ) diff --git a/chart2/source/tools/CachedDataSequence.cxx b/chart2/source/tools/CachedDataSequence.cxx index 5aa39175c327..7f5e4b9736f7 100644 --- a/chart2/source/tools/CachedDataSequence.cxx +++ b/chart2/source/tools/CachedDataSequence.cxx @@ -30,9 +30,6 @@ using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Any; -// necessary for MS compiler -using ::chart::impl::CachedDataSequence_Base; - namespace { constexpr OUString lcl_aServiceName = u"com.sun.star.comp.chart.CachedDataSequence"_ustr; @@ -70,7 +67,8 @@ CachedDataSequence::CachedDataSequence( const OUString & rSingleText ) } CachedDataSequence::CachedDataSequence( const CachedDataSequence & rSource ) - : m_nNumberFormatKey( rSource.m_nNumberFormatKey ), + : CachedDataSequence_Base(), + m_nNumberFormatKey( rSource.m_nNumberFormatKey ), m_sRole( rSource.m_sRole ), m_eCurrentDataType( rSource.m_eCurrentDataType ), m_xModifyEventForwarder( new ModifyEventForwarder() ) @@ -145,22 +143,6 @@ Sequence< Any > CachedDataSequence::Impl_getMixedData() const return CommonFunctors::convertToSequence(m_aTextualSequence, CommonFunctors::makeAny()); } -IMPLEMENT_FORWARD_XINTERFACE2( CachedDataSequence, CachedDataSequence_Base, comphelper::OPropertyContainer2 ) -IMPLEMENT_FORWARD_XTYPEPROVIDER2( CachedDataSequence, CachedDataSequence_Base, comphelper::OPropertyContainer2 ) - -// ____ XPropertySet ____ -Reference< beans::XPropertySetInfo > SAL_CALL CachedDataSequence::getPropertySetInfo() -{ - return createPropertySetInfo( getInfoHelper() ); -} - -// ____ ::comphelper::OPropertySetHelper ____ -::cppu::IPropertyArrayHelper& CachedDataSequence::getInfoHelper() -{ - return *getArrayHelper(); -} - -// ____ ::comphelper::OPropertyArrayHelper ____ ::cppu::IPropertyArrayHelper* CachedDataSequence::createArrayHelper() const { Sequence< beans::Property > aProps; diff --git a/chart2/source/tools/ChartColorPaletteHelper.cxx b/chart2/source/tools/ChartColorPaletteHelper.cxx index bfaf3ef82279..d82775a5f81b 100644 --- a/chart2/source/tools/ChartColorPaletteHelper.cxx +++ b/chart2/source/tools/ChartColorPaletteHelper.cxx @@ -147,7 +147,7 @@ ChartColorPalette ChartColorPaletteHelper::createMonotonicPalette(sal_uInt32 nIn return colorPalette; } -void ChartColorPaletteHelper::renderColorPalette(OutputDevice* pDev, +void ChartColorPaletteHelper::renderColorPalette(OutputDevice& rDev, const tools::Rectangle& rDrawArea, const ChartColorPalette& rColorSet, const bool bDrawItemBorder) @@ -164,22 +164,22 @@ void ChartColorPaletteHelper::renderColorPalette(OutputDevice* pDev, static constexpr tools::Long y1 = BORDER; static constexpr tools::Long y2 = y1 + SIZE + BORDER; - pDev->SetFillColor(); + rDev.SetFillColor(); if (bDrawItemBorder) { - pDev->SetLineColor(COL_BLACK); - pDev->DrawRect(tools::Rectangle(aPosition, aSize)); + rDev.SetLineColor(COL_BLACK); + rDev.DrawRect(tools::Rectangle(aPosition, aSize)); } for (sal_uInt32 i = 0; i < ChartColorPaletteSize / 2; i += 1) { - pDev->SetFillColor(rColorSet[i]); - pDev->DrawRect(tools::Rectangle( + rDev.SetFillColor(rColorSet[i]); + rDev.DrawRect(tools::Rectangle( Point(aPosition.X() + x + startX, aPosition.Y() + startY + y1), Size(SIZE, SIZE))); - pDev->SetFillColor(rColorSet[i + ChartColorPaletteSize / 2]); - pDev->DrawRect(tools::Rectangle( + rDev.SetFillColor(rColorSet[i + ChartColorPaletteSize / 2]); + rDev.DrawRect(tools::Rectangle( Point(aPosition.X() + x + startX, aPosition.Y() + startY + y2), Size(SIZE, SIZE))); x += SIZE + BORDER; diff --git a/chart2/source/tools/ChartColorPalettes.cxx b/chart2/source/tools/ChartColorPalettes.cxx index 1ac1c16745f4..28628e0a5129 100644 --- a/chart2/source/tools/ChartColorPalettes.cxx +++ b/chart2/source/tools/ChartColorPalettes.cxx @@ -21,10 +21,8 @@ ChartColorPalettes::ChartColorPalettes(weld::Builder& rBuilder, const OUString& const OUString& winId) : mxIconView(rBuilder.weld_icon_view(id)) , mxWindow(rBuilder.weld_scrolled_window(winId)) - , mnHighlightedItemId(0) { mxIconView->connect_mouse_move(LINK(this, ChartColorPalettes, OnMouseMove)); - mxIconView->connect_query_tooltip(LINK(this, ChartColorPalettes, OnQueryTooltip)); } void ChartColorPalettes::SetSelectHdl(const Link& rLink) @@ -62,20 +60,15 @@ const ChartColorPalette* ChartColorPalettes::getPalette(const sal_uInt32 nItem) return nullptr; } -sal_uInt16 ChartColorPalettes::GetHighlightedItemId() { return mnHighlightedItemId; } - -void ChartColorPalettes::setMouseMoveHdl(const MouseEventHandler& rLink) { maMouseMoveHdl = rLink; } +void ChartColorPalettes::setMouseMoveHdl(const Link& rLink) +{ + maMouseMoveHdl = rLink; +} void ChartColorPalettes::Fill() { - const sal_uInt32 nColumns = 2; const Size aSize(BORDER * 6 + SIZE * ChartColorPaletteSize / 2, BORDER * 5 + SIZE * 2); - const sal_uInt32 nRows = maColorSets.size() / nColumns; - mxIconView->set_item_width(aSize.getWidth()); - mxIconView->set_size_request(nColumns * (aSize.getWidth() + 8), - nRows * (aSize.getHeight() + 8)); - mxIconView->clear(); mxIconView->freeze(); @@ -88,7 +81,7 @@ void ChartColorPalettes::Fill() { const ChartColorPalette& rColorSet = maColorSets[i]; pVDev->Erase(); - ChartColorPaletteHelper::renderColorPalette(pVDev, aDrawArea, rColorSet, false); + ChartColorPaletteHelper::renderColorPalette(*pVDev, aDrawArea, rColorSet, false); OUString sId = OUString::number(i + 1); OUString sName = "Palette " + OUString::number(i + 1); @@ -98,24 +91,22 @@ void ChartColorPalettes::Fill() } mxIconView->thaw(); - mnHighlightedItemId = 0; -} - -IMPL_LINK(ChartColorPalettes, OnQueryTooltip, const weld::TreeIter&, rIter, OUString) -{ - OUString sId = mxIconView->get_id(rIter); - mnHighlightedItemId = sId.isEmpty() ? 0 : static_cast(sId.toUInt32()); - - // Suppress actual tooltip text. - return {}; } IMPL_LINK(ChartColorPalettes, OnMouseMove, const MouseEvent&, rMouseEvent, bool) { - if (rMouseEvent.IsLeaveWindow()) - mnHighlightedItemId = 0; + OUString sHighlightedId; + if (!rMouseEvent.IsLeaveWindow()) + { + if (std::unique_ptr pItem + = mxIconView->get_item_at_pos(rMouseEvent.GetPosPixel())) + { + sHighlightedId = mxIconView->get_id(*pItem); + } + } + if (maMouseMoveHdl.IsSet()) - return maMouseMoveHdl.Call(rMouseEvent); + return maMouseMoveHdl.Call(sHighlightedId); return false; } diff --git a/chart2/source/tools/ChartColorScheme.cxx b/chart2/source/tools/ChartColorScheme.cxx index 5fbea2aa5b40..1dec01d98af1 100644 --- a/chart2/source/tools/ChartColorScheme.cxx +++ b/chart2/source/tools/ChartColorScheme.cxx @@ -18,6 +18,7 @@ */ #include +#include namespace chart { @@ -28,10 +29,8 @@ ChartColorScheme::ChartColorScheme(const ChartColorPalette& rPalette) m_nNumberOfColors = rPalette.size(); m_aColorSequence.realloc(m_nNumberOfColors); sal_Int64* pColors = m_aColorSequence.getArray(); - for (size_t i = 0; i < rPalette.size(); ++i) - { - pColors[i] = static_cast(rPalette[i]); - } + std::transform(rPalette.begin(), rPalette.end(), pColors, + [](Color const& rColor) { return static_cast(rColor); }); } ::sal_Int32 SAL_CALL ChartColorScheme::getColorByIndex(::sal_Int32 nIndex) diff --git a/chart2/source/tools/ChartTypeHelper.cxx b/chart2/source/tools/ChartTypeHelper.cxx index bbae50787ac6..c6354ca9f597 100644 --- a/chart2/source/tools/ChartTypeHelper.cxx +++ b/chart2/source/tools/ChartTypeHelper.cxx @@ -70,12 +70,7 @@ uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedLabelPlacements( const else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) - || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BOXWHISKER) - || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PARETOLINE) - || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_REGIONMAP) - || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SUNBURST) - || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_TREEMAP) - || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FUNNEL) // TODO: check this + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE) ) { aRet.realloc(5); @@ -86,6 +81,28 @@ uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedLabelPlacements( const *pSeq++ = css::chart::DataLabelPlacement::RIGHT; *pSeq++ = css::chart::DataLabelPlacement::CENTER; } + else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BOXWHISKER) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PARETOLINE) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_REGIONMAP) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SUNBURST) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_TREEMAP) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FUNNEL) + ) + { + // chartex chart types: support every value the chartex pos attribute + // can carry, so imported placements survive + aRet.realloc(9); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = css::chart::DataLabelPlacement::CENTER; + *pSeq++ = css::chart::DataLabelPlacement::TOP; + *pSeq++ = css::chart::DataLabelPlacement::BOTTOM; + *pSeq++ = css::chart::DataLabelPlacement::LEFT; + *pSeq++ = css::chart::DataLabelPlacement::RIGHT; + *pSeq++ = css::chart::DataLabelPlacement::OUTSIDE; + *pSeq++ = css::chart::DataLabelPlacement::INSIDE; + *pSeq++ = css::chart::DataLabelPlacement::NEAR_ORIGIN; + *pSeq++ = css::chart::DataLabelPlacement::AVOID_OVERLAP; + } else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ) { @@ -118,6 +135,18 @@ uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedLabelPlacements( const *pSeq++ = css::chart::DataLabelPlacement::INSIDE; *pSeq++ = css::chart::DataLabelPlacement::NEAR_ORIGIN; } + else if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM)) + { + aRet.realloc(6); + sal_Int32* pSequence = aRet.getArray(); + + *pSequence++ = css::chart::DataLabelPlacement::TOP; + *pSequence++ = css::chart::DataLabelPlacement::BOTTOM; + *pSequence++ = css::chart::DataLabelPlacement::CENTER; + *pSequence++ = css::chart::DataLabelPlacement::OUTSIDE; + *pSequence++ = css::chart::DataLabelPlacement::INSIDE; + *pSequence++ = css::chart::DataLabelPlacement::NEAR_ORIGIN; + } else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ) { bool bStacked = false; @@ -178,6 +207,7 @@ bool ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault( const rtl::Reference< C OUString aChartTypeName = xChartType->getChartType(); if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM) || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) return true; } @@ -313,6 +343,21 @@ uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedMissingValueTreatments( *pSeq++ = css::chart::MissingValueTreatment::LEAVE_GAP; *pSeq++ = css::chart::MissingValueTreatment::USE_ZERO; } + else if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM)) + { + // Assuming histograms typically use zero for missing values + aRet.realloc(1); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = css::chart::MissingValueTreatment::USE_ZERO; + } + else if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE)) + { + // A correlation leaves out the instances where one of the two values is + // missing, and there is no other interpretation of a gap that makes sense. + aRet.realloc(1); + sal_Int32* pSeq = aRet.getArray(); + *pSeq++ = css::chart::MissingValueTreatment::LEAVE_GAP; + } else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ) { aRet.realloc( bStacked ? 1 : 2 ); diff --git a/chart2/source/tools/ControllerLockGuard.cxx b/chart2/source/tools/ControllerLockGuard.cxx index 5373d44f4090..c1fcffd49eaf 100644 --- a/chart2/source/tools/ControllerLockGuard.cxx +++ b/chart2/source/tools/ControllerLockGuard.cxx @@ -27,12 +27,14 @@ namespace chart ControllerLockGuardUNO::ControllerLockGuardUNO( rtl::Reference<::chart::ChartModel> xModel ) : mxModel(std::move( xModel )) { - mxModel->lockControllers(); + if( mxModel.is()) + mxModel->lockControllers(); } ControllerLockGuardUNO::~ControllerLockGuardUNO() { - mxModel->unlockControllers(); + if( mxModel.is()) + mxModel->unlockControllers(); } ControllerLockGuard::ControllerLockGuard( ChartModel& rModel ) : diff --git a/chart2/source/tools/DataSourceHelper.cxx b/chart2/source/tools/DataSourceHelper.cxx index c0bd10b65543..4bb5b8266130 100644 --- a/chart2/source/tools/DataSourceHelper.cxx +++ b/chart2/source/tools/DataSourceHelper.cxx @@ -230,7 +230,7 @@ rtl::Reference< DataSource > DataSourceHelper::pressUsedDataIntoRectangularForma DataSeriesHelper::getDataSource( aSeriesVector ); const Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xSeriesSource->getDataSequences() ); - //the first x-values is always the next sequence //todo ... other x-values get lost for old format + //the first x-values are always the next sequence //todo ... other x-values get lost for old format Reference< chart2::data::XLabeledDataSequence > xXValues( DataSeriesHelper::getDataSequenceByRole( xSeriesSource, u"values-x"_ustr ) ); if( xXValues.is() ) diff --git a/chart2/source/tools/HistogramDataSequence.cxx b/chart2/source/tools/HistogramDataSequence.cxx new file mode 100644 index 000000000000..ca190c2b24fd --- /dev/null +++ b/chart2/source/tools/HistogramDataSequence.cxx @@ -0,0 +1,321 @@ +/* -*- 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 +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace css; + +namespace +{ +constexpr OUString lcl_aServiceName = u"com.sun.star.chart2.data.HistogramDataSequence"_ustr; + +enum +{ + PROP_PROPOSED_ROLE +}; + +} // anonymous namespace + +namespace chart +{ +HistogramDataSequence::HistogramDataSequence( + const uno::Reference& xRawData, bool bIsCategory, + sal_Int32 nFrequencyType, double fBinWidth, sal_Int32 nBinCount, bool bUseUnderflowBin, + double fUnderflowBinValue, bool bUseOverflowBin, double fOverflowBinValue) + : ::comphelper::OPropertyContainer(GetBroadcastHelper()) + , m_xModifyEventForwarder(new ModifyEventForwarder()) + , m_xRawData(xRawData) + , m_bIsCategory(bIsCategory) + , m_bIsDirty(true) + , m_nFrequencyType(nFrequencyType) + , m_fBinWidth(fBinWidth) + , m_nBinCount(nBinCount) + , m_bUseUnderflowBin(bUseUnderflowBin) + , m_fUnderflowBinValue(fUnderflowBinValue) + , m_bUseOverflowBin(bUseOverflowBin) + , m_fOverflowBinValue(fOverflowBinValue) +{ + registerProperty(u"Role"_ustr, PROP_PROPOSED_ROLE, + 0, // PropertyAttributes + &m_sRole, cppu::UnoType::get()); + + if (m_xRawData.is()) + { + // Listen for changes in the raw spreadsheet data + uno::Reference xBroadcaster(m_xRawData, uno::UNO_QUERY); + if (xBroadcaster.is()) + xBroadcaster->addModifyListener(this); + } +} + +HistogramDataSequence::~HistogramDataSequence() +{ + if (m_xRawData.is()) + { + uno::Reference xBroadcaster(m_xRawData, uno::UNO_QUERY); + if (xBroadcaster.is()) + xBroadcaster->removeModifyListener(this); + } +} + +void HistogramDataSequence::setBinningParameters(sal_Int32 nFrequencyType, double fBinWidth, + sal_Int32 nBinCount, bool bUseUnderflowBin, + double fUnderflowBinValue, bool bUseOverflowBin, + double fOverflowBinValue) +{ + { + osl::MutexGuard aGuard(GetMutex()); + + // Recomputing the bins is expensive, so parameters that repeat the ones already held + // leave the cached bins and the modified state alone. + if (m_nFrequencyType == nFrequencyType && m_fBinWidth == fBinWidth + && m_nBinCount == nBinCount && m_bUseUnderflowBin == bUseUnderflowBin + && m_fUnderflowBinValue == fUnderflowBinValue && m_bUseOverflowBin == bUseOverflowBin + && m_fOverflowBinValue == fOverflowBinValue) + { + return; + } + + m_nFrequencyType = nFrequencyType; + m_fBinWidth = fBinWidth; + m_nBinCount = nBinCount; + m_bUseUnderflowBin = bUseUnderflowBin; + m_fUnderflowBinValue = fUnderflowBinValue; + m_bUseOverflowBin = bUseOverflowBin; + m_fOverflowBinValue = fOverflowBinValue; + m_bIsDirty = true; + } + + m_xModifyEventForwarder->modified(lang::EventObject(static_cast(this))); +} + +IMPLEMENT_FORWARD_XINTERFACE2(HistogramDataSequence, HistogramDataSequence_Base, + ::comphelper::OPropertyContainer) + +IMPLEMENT_FORWARD_XTYPEPROVIDER2(HistogramDataSequence, HistogramDataSequence_Base, + ::comphelper::OPropertyContainer) + +uno::Reference SAL_CALL HistogramDataSequence::getPropertySetInfo() +{ + return comphelper::OPropertyStateHelper::createPropertySetInfo(getInfoHelper()); +} + +::cppu::IPropertyArrayHelper& SAL_CALL HistogramDataSequence::getInfoHelper() +{ + return *getArrayHelper(); +} + +::cppu::IPropertyArrayHelper* HistogramDataSequence::createArrayHelper() const +{ + uno::Sequence aProperties; + describeProperties(aProperties); + return new ::cppu::OPropertyArrayHelper(aProperties); +} + +OUString SAL_CALL HistogramDataSequence::getImplementationName() { return lcl_aServiceName; } + +sal_Bool SAL_CALL HistogramDataSequence::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence SAL_CALL HistogramDataSequence::getSupportedServiceNames() +{ + return { lcl_aServiceName, u"com.sun.star.chart2.data.DataSequence"_ustr, + u"com.sun.star.chart2.data.NumericalDataSequence"_ustr, + u"com.sun.star.chart2.data.TextualDataSequence"_ustr }; +} + +uno::Sequence SAL_CALL HistogramDataSequence::getNumericalData() +{ + ::osl::MutexGuard aGuard(GetMutex()); + ensureCalculated(); + return CommonFunctors::convertToSequence(mxValues, CommonFunctors::ToDouble()); +} + +uno::Sequence SAL_CALL HistogramDataSequence::getTextualData() +{ + ::osl::MutexGuard aGuard(GetMutex()); + ensureCalculated(); + return CommonFunctors::convertToSequence(mxValues, CommonFunctors::ToString()); +} + +uno::Sequence SAL_CALL HistogramDataSequence::getData() +{ + ::osl::MutexGuard aGuard(GetMutex()); + ensureCalculated(); + return mxValues; +} + +OUString SAL_CALL HistogramDataSequence::getSourceRangeRepresentation() +{ + // synthesized sequence — no underlying cell range + return OUString(); +} + +uno::Sequence + SAL_CALL HistogramDataSequence::generateLabel(css::chart2::data::LabelOrigin) +{ + ::osl::MutexGuard aGuard(GetMutex()); + return mxLabels; +} + +sal_Int32 SAL_CALL HistogramDataSequence::getNumberFormatKeyByIndex(sal_Int32) +{ + return 0; // TODO - NumberFormat support +} + +void SAL_CALL +HistogramDataSequence::addModifyListener(const uno::Reference& aListener) +{ + m_xModifyEventForwarder->addModifyListener(aListener); +} + +void SAL_CALL +HistogramDataSequence::removeModifyListener(const uno::Reference& aListener) +{ + m_xModifyEventForwarder->removeModifyListener(aListener); +} + +void SAL_CALL HistogramDataSequence::modified(const lang::EventObject& /* aEvent */) +{ + // The raw data changed! Mark ourselves dirty and tell the chart to redraw + { + ::osl::MutexGuard aGuard(GetMutex()); + m_bIsDirty = true; + } + m_xModifyEventForwarder->modified(lang::EventObject(static_cast(this))); +} + +void SAL_CALL HistogramDataSequence::disposing(const lang::EventObject& /* Source */) +{ + m_xRawData.clear(); +} + +uno::Reference SAL_CALL HistogramDataSequence::createClone() +{ + rtl::Reference pClone(new HistogramDataSequence( + m_xRawData, m_bIsCategory, m_nFrequencyType, m_fBinWidth, m_nBinCount, m_bUseUnderflowBin, + m_fUnderflowBinValue, m_bUseOverflowBin, m_fOverflowBinValue)); + + ::osl::MutexGuard aGuard(GetMutex()); + pClone->mxLabels = mxLabels; + pClone->mxValues = mxValues; + pClone->m_sRole = m_sRole; + pClone->m_bIsDirty = m_bIsDirty; + + return pClone; +} + +void HistogramDataSequence::ensureCalculated() +{ + if (!m_bIsDirty || !m_xRawData.is()) + return; + + std::vector rawData; + try + { + uno::Sequence aRawAnyValues = m_xRawData->getData(); + for (const auto& aAny : aRawAnyValues) + { + double fValue = 0.0; + if (aAny >>= fValue) + rawData.push_back(fValue); + } + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + HistogramCalculator aCalculator; + aCalculator.computeBinFrequencyHistogram(rawData, m_nFrequencyType, m_fBinWidth, m_nBinCount, + m_bUseUnderflowBin, m_fUnderflowBinValue, + m_bUseOverflowBin, m_fOverflowBinValue); + + std::vector aNewValues; + + if (m_bIsCategory) + { + const auto& binRanges = aCalculator.getBinRanges(); + const auto& binTypes = aCalculator.getBinTypes(); + + // keep ~3 significant figures relative to the bin width, so typical + // widths (~1) get 2 decimals and small widths (~0.002) get 5 + int labelDigits = 2; + if (!binRanges.empty()) + { + double firstBinWidth = binRanges.front().second - binRanges.front().first; + if (firstBinWidth > 0.0) + labelDigits + = std::max(1, 2 - static_cast(std::floor(std::log10(firstBinWidth)))); + } + const double roundingScale = std::pow(10.0, labelDigits); + auto formatBoundary = [roundingScale](double value) { + return OUString::number(std::round(value * roundingScale) / roundingScale); + }; + + for (size_t i = 0; i < binRanges.size(); ++i) + { + OUString aLabel; + if (binTypes[i] == HistogramBinType::Underflow) + { + aLabel = u"<= "_ustr + formatBoundary(binRanges[i].second); + } + else if (binTypes[i] == HistogramBinType::Overflow) + { + aLabel = u"> "_ustr + formatBoundary(binRanges[i].first); + } + else + { + const bool bPreviousIsUnderflow + = i > 0 && binTypes[i - 1] == HistogramBinType::Underflow; + const bool bUseClosedStart = i == 0 && !bPreviousIsUnderflow; + + aLabel = (bUseClosedStart ? u"["_ustr : u"("_ustr) + + formatBoundary(binRanges[i].first) + u"-"_ustr + + formatBoundary(binRanges[i].second) + u"]"_ustr; + } + aNewValues.push_back(uno::Any(aLabel)); + } + } + else + { + const auto& binFrequencies = aCalculator.getBinFrequencies(); + for (sal_Int32 freq : binFrequencies) + { + aNewValues.push_back(uno::Any(static_cast(freq))); + } + } + + mxValues = comphelper::containerToSequence(aNewValues); + m_bIsDirty = false; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file diff --git a/chart2/source/tools/InternalData.cxx b/chart2/source/tools/InternalData.cxx index a0f5f087d09c..a1d4d8d488ba 100644 --- a/chart2/source/tools/InternalData.cxx +++ b/chart2/source/tools/InternalData.cxx @@ -132,7 +132,7 @@ void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows ) m_aColumnLabels.resize( m_nColumnCount ); m_aData.resize( m_nRowCount * m_nColumnCount ); - // set all values to Nan + // set all values to NaN m_aData = std::numeric_limits::quiet_NaN(); for( sal_Int32 nRow=0; nRow SAL_CALL InternalDataProvider::getDataByRangeRepresentation } else { - // Maybe this 'else' part and the functions is not necessary anymore. + // Maybe this 'else' part and the functions are not necessary anymore. const Sequence< OUString > aLabels = m_bDataInColumns ? getRowDescriptions() : getColumnDescriptions(); aResult = CommonFunctors::convertToSequence(aLabels, CommonFunctors::makeAny()); } diff --git a/chart2/source/tools/RangeHighlighter.cxx b/chart2/source/tools/RangeHighlighter.cxx index 69a2951108a4..7c8589a0968b 100644 --- a/chart2/source/tools/RangeHighlighter.cxx +++ b/chart2/source/tools/RangeHighlighter.cxx @@ -35,6 +35,7 @@ #include #include #include +#include using namespace ::com::sun::star; @@ -53,14 +54,12 @@ void lcl_fillRanges( sal_Int32 nIndex = -1 ) { rOutRanges.realloc( aRangeStrings.size()); - auto pOutRanges = rOutRanges.getArray(); - for( size_t i=0; i & x { std::vector< OUString > aSelectedRanges( DataSourceHelper::getUsedDataRanges( xDiagram )); m_aSelectedRanges.realloc( aSelectedRanges.size()); - auto pSelectedRanges = m_aSelectedRanges.getArray(); // @todo: merge ranges - for( size_t i=0; i & xSeries ) diff --git a/chart2/source/tools/TitleHelper.cxx b/chart2/source/tools/TitleHelper.cxx index 4a2bfa4f0315..c7cf8ed709d6 100644 --- a/chart2/source/tools/TitleHelper.cxx +++ b/chart2/source/tools/TitleHelper.cxx @@ -262,7 +262,7 @@ rtl::Reference< Title > TitleHelper::createTitle( xTitled->setTitleObject( xTitle ); - //default rotation 90 degree for y axis title in normal coordinatesystems or for x axis title for swapped coordinatesystems + //default rotation 90 degree for y axis title in normal coordinate systems or for x axis title for swapped coordinate systems if( eTitleType == TitleHelper::X_AXIS_TITLE || eTitleType == TitleHelper::Y_AXIS_TITLE || eTitleType == TitleHelper::SECONDARY_X_AXIS_TITLE || @@ -373,16 +373,16 @@ void TitleHelper::setCompleteString( const OUString& rNewText const OUString aFullString = getCompleteString(xTitle); if (bDialogTitle && aNewText.equals(getUnstackedStr(aFullString))) { - // If the new title setted from a dialog window to a new string + // If the new title is set from a dialog window to a new string // the first old text portion will be maintained if it's a new string, // otherwise we use the original one. aNewStringList = std::move(aOldStringList); } else { - // If the new title setted from a dialog to a new string the first + // If the new title is set from a dialog to a new string the first // old text portion will be maintained if there was any. Also in case of ODF - // import which still not support non-uniform formatted titles + // import which still does not support non-uniform formatted titles aNewStringList = { aOldStringList[0] }; aNewStringList[0]->setString(aNewText); } diff --git a/chart2/source/tools/UncachedDataSequence.cxx b/chart2/source/tools/UncachedDataSequence.cxx index c1377266080a..be3b45026504 100644 --- a/chart2/source/tools/UncachedDataSequence.cxx +++ b/chart2/source/tools/UncachedDataSequence.cxx @@ -33,9 +33,6 @@ using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Any; -// necessary for MS compiler -using ::chart::impl::UncachedDataSequence_Base; - namespace { constexpr OUString lcl_aServiceName = u"com.sun.star.comp.chart.UncachedDataSequence"_ustr; @@ -44,7 +41,10 @@ enum { PROP_NUMBERFORMAT_KEY, PROP_PROPOSED_ROLE, - PROP_XML_RANGE + PROP_XML_RANGE, + PROP_CHARTEX_FORMULA, + PROP_CHARTEX_NFORMULA, + PROP_CHARTEX_DIM_TYPE }; } // anonymous namespace @@ -55,6 +55,7 @@ UncachedDataSequence::UncachedDataSequence( rtl::Reference< InternalDataProvider > xIntDataProv, OUString aRangeRepresentation ) : m_nNumberFormatKey(0), + m_nChartExDimType(0), m_xDataProvider(std::move( xIntDataProv )), m_aSourceRepresentation(std::move( aRangeRepresentation )), m_xModifyEventForwarder( new ModifyEventForwarder() ) @@ -67,6 +68,7 @@ UncachedDataSequence::UncachedDataSequence( OUString aRangeRepresentation, const OUString & rRole ) : m_nNumberFormatKey(0), + m_nChartExDimType(0), m_xDataProvider(std::move( xIntDataProv )), m_aSourceRepresentation(std::move( aRangeRepresentation )), m_xModifyEventForwarder( new ModifyEventForwarder() ) @@ -77,8 +79,12 @@ UncachedDataSequence::UncachedDataSequence( } UncachedDataSequence::UncachedDataSequence( const UncachedDataSequence & rSource ) - : m_nNumberFormatKey( rSource.m_nNumberFormatKey ), + : UncachedDataSequence_Base(), + m_nNumberFormatKey( rSource.m_nNumberFormatKey ), m_sRole( rSource.m_sRole ), + m_aChartExFormula( rSource.m_aChartExFormula ), + m_aChartExNFormula( rSource.m_aChartExNFormula ), + m_nChartExDimType( rSource.m_nChartExDimType ), m_xDataProvider( rSource.m_xDataProvider ), m_aSourceRepresentation( rSource.m_aSourceRepresentation ), m_xModifyEventForwarder( new ModifyEventForwarder() ) @@ -108,24 +114,26 @@ void UncachedDataSequence::registerProperties() 0, // PropertyAttributes & m_aXMLRange, cppu::UnoType::get() ); + + registerProperty( u"ChartExFormula"_ustr, + PROP_CHARTEX_FORMULA, + 0, + & m_aChartExFormula, + cppu::UnoType::get() ); + + registerProperty( u"ChartExNFormula"_ustr, + PROP_CHARTEX_NFORMULA, + 0, + & m_aChartExNFormula, + cppu::UnoType::get() ); + + registerProperty( u"ChartExDimType"_ustr, + PROP_CHARTEX_DIM_TYPE, + 0, + & m_nChartExDimType, + cppu::UnoType::get() ); } -IMPLEMENT_FORWARD_XINTERFACE2( UncachedDataSequence, UncachedDataSequence_Base, comphelper::OPropertyContainer2 ) -IMPLEMENT_FORWARD_XTYPEPROVIDER2( UncachedDataSequence, UncachedDataSequence_Base, comphelper::OPropertyContainer2 ) - -// ____ XPropertySet ____ -Reference< beans::XPropertySetInfo > SAL_CALL UncachedDataSequence::getPropertySetInfo() -{ - return createPropertySetInfo( getInfoHelper() ); -} - -// ____ ::comphelper::OPropertySetHelper ____ -::cppu::IPropertyArrayHelper& UncachedDataSequence::getInfoHelper() -{ - return *getArrayHelper(); -} - -// ____ ::comphelper::OPropertyArrayHelper ____ ::cppu::IPropertyArrayHelper* UncachedDataSequence::createArrayHelper() const { Sequence< beans::Property > aProps; diff --git a/chart2/source/tools/WrappedPropertySet.cxx b/chart2/source/tools/WrappedPropertySet.cxx index ae7ff6467c05..5a0b2969d9fd 100644 --- a/chart2/source/tools/WrappedPropertySet.cxx +++ b/chart2/source/tools/WrappedPropertySet.cxx @@ -89,7 +89,7 @@ void SAL_CALL WrappedPropertySet::setPropertyValue( const OUString& rPropertyNam xInnerPropertySet->setPropertyValue( rPropertyName, rValue ); else { - SAL_WARN("chart2.tools", "found no inner property set to map to"); + SAL_INFO("chart2.tools", "found no inner property set to map to"); } } catch( const beans::UnknownPropertyException& ) @@ -134,7 +134,7 @@ Any SAL_CALL WrappedPropertySet::getPropertyValue( const OUString& rPropertyName aRet = xInnerPropertySet->getPropertyValue( rPropertyName ); else { - SAL_WARN("chart2.tools", "found no inner property set to map to"); + SAL_INFO("chart2.tools", "found no inner property set to map to"); } } catch( const beans::UnknownPropertyException& ) diff --git a/chart2/source/view/axes/VAxisBase.hxx b/chart2/source/view/axes/VAxisBase.hxx index ee5748e48370..8e36c77c3ed4 100644 --- a/chart2/source/view/axes/VAxisBase.hxx +++ b/chart2/source/view/axes/VAxisBase.hxx @@ -69,8 +69,6 @@ public: rtl::Reference<::chart::ChartModel> const& xChartDoc, css::uno::Reference const& rComponentContext); - const std::shared_ptr & getDataTableView() { return m_pDataTableView; } - protected: //methods static size_t getIndexOfLongestLabel( const css::uno::Sequence& rLabels ); void removeTextShapesFromTicks(); diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx index 639adc811d3d..9cb58a9a87e5 100644 --- a/chart2/source/view/axes/VAxisProperties.cxx +++ b/chart2/source/view/axes/VAxisProperties.cxx @@ -316,13 +316,13 @@ void AxisProperties::init( bool bCartesian ) m_xAxisModel->getPropertyValue( u"MinorTickmarks"_ustr ) >>= m_nMinorTickmarks; sal_Int32 nMaxDepth = 0; - if(m_nMinorTickmarks!=0) + if (m_nMinorTickmarks !=0 ) nMaxDepth=2; - else if(m_nMajorTickmarks!=0) + else if (m_nMajorTickmarks !=0 ) nMaxDepth=1; m_aTickmarkPropertiesList.clear(); - for( sal_Int32 nDepth=0; nDepth= nSlotPoints ) continue; - double fMinimumY = 0.0, fMaximumY = 0.0; + // Min and max for the category + double fCatMinY = 0.0, fCatMaxY = 0.0; rXSlot.calculateYMinAndMaxForCategory( nPointIndex - , isSeparateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex ); + , isSeparateStackingForDifferentSigns( 1 ), fCatMinY, fCatMaxY, nAttachedAxisIndex ); - if( !std::isnan( fMaximumY ) && fMaximumY > 0) - aLogicYSumMap[nAttachedAxisIndex] += fMaximumY; - if( !std::isnan( fMinimumY ) && fMinimumY < 0) - aLogicYSumMap[nAttachedAxisIndex] += fabs(fMinimumY); + if( !std::isnan( fCatMaxY ) && fCatMaxY > 0) + aLogicYSumMap[nAttachedAxisIndex] += fCatMaxY; + if( !std::isnan( fCatMinY ) && fCatMinY < 0) + aLogicYSumMap[nAttachedAxisIndex] += fabs(fCatMinY); } } @@ -619,7 +621,8 @@ void BarChart::doZSlot( doXSlot(rXSlot, bDrawConnectionLines, bDrawConnectionLinesInited, nZ, nPointIndex, nStartIndex, xSeriesTarget, xRegressionCurveTarget, xRegressionCurveEquationTarget, xTextTarget, aShapeSet, aSeriesFormerPointMap, aLogicYSumMap, - fLogicBaseWidth, fSlotX, pPosHelper, fLogicPositiveYSum, fLogicNegativeYSum, nAttachedAxisIndex); + fLogicBaseWidth, fSlotX, pPosHelper, fLogicPositiveYSum, + fLogicNegativeYSum, nAttachedAxisIndex); fSlotX+=1.0; }//next x slot @@ -786,12 +789,14 @@ void BarChart::doXSlot( double fUnclippedUpperYValue = fUpperYValue; //apply clipping to Y - if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) ) - { - if( bDrawConnectionLines ) - bOnlyConnectionLinesForThisPoint = true; - else - continue; + if (!m_bAlignCenter) { + if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) ) + { + if( bDrawConnectionLines ) + bOnlyConnectionLinesForThisPoint = true; + else + continue; + } } //@todo clipping of X and Z is not fully integrated so far, as there is a need to create different objects @@ -869,6 +874,18 @@ void BarChart::doXSlot( //pPosHelper->isSameForGivenResolution( fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ // , fLogicX+fLogicBarWidth/2.0, fLowerYValue, fLogicZ ); + if (m_bAlignCenter) { + // Center the bar around the middle of the value axis range, as + // for funnel charts. + double fScaledMinY = pPosHelper->getLogicMinY(); + double fScaledMaxY = pPosHelper->getLogicMaxY(); + pPosHelper->doLogicScaling(nullptr, &fScaledMinY, nullptr); + pPosHelper->doLogicScaling(nullptr, &fScaledMaxY, nullptr); + double fShift = (fScaledMinY + fScaledMaxY - fLowerYValue - fUpperYValue) / 2.0; + fLowerYValue += fShift; + fUpperYValue += fShift; + } + //create partial point if( !approxEqual(fLowerYValue,fUpperYValue) ) { @@ -913,16 +930,13 @@ void BarChart::doXSlot( } else //m_nDimension!=3 { - drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ ); - drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ ); std::vector> aPoly { { // inner vector - drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ), - drawing::Position3D( fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ), - aRightUpperPoint, - aLeftUpperPoint, - drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) + drawing::Position3D( fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ), + drawing::Position3D( fLogicX+fLogicBarWidth/2.0, fLowerYValue, fLogicZ), + drawing::Position3D( fLogicX+fLogicBarWidth/2.0, fUpperYValue, fLogicZ), + drawing::Position3D( fLogicX-fLogicBarWidth/2.0, fUpperYValue, fLogicZ ) } }; pPosHelper->transformScaledLogicToScene( aPoly ); diff --git a/chart2/source/view/charttypes/BarChart.hxx b/chart2/source/view/charttypes/BarChart.hxx index ca13872a2baf..6d8cd945e20d 100644 --- a/chart2/source/view/charttypes/BarChart.hxx +++ b/chart2/source/view/charttypes/BarChart.hxx @@ -107,6 +107,9 @@ private: //methods double fLogicPositiveYSum, double fLogicNegativeYSum, sal_Int32 nAttachedAxisIndex); +protected: + bool m_bAlignCenter = false; // Center the bars, as for funnel charts + private: //member BarPositionHelper m_aMainPosHelper; css::uno::Sequence< sal_Int32 > m_aOverlapSequence; diff --git a/chart2/source/view/charttypes/CorrelationCircleChart.cxx b/chart2/source/view/charttypes/CorrelationCircleChart.cxx new file mode 100644 index 000000000000..621a2ef24056 --- /dev/null +++ b/chart2/source/view/charttypes/CorrelationCircleChart.cxx @@ -0,0 +1,313 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 "CorrelationCircleChart.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +namespace +{ +// The circle and the two lines through the origin are the frame the arrows are +// read against, so they are drawn in a colour that stays behind the data. +constexpr sal_Int32 nGuideColor = 0x808080; + +// The dimensions sit at a depth of one, as elsewhere in the two dimensional +// plotters. +constexpr double fLogicZ = 1.0; + +std::span lclAsSpan(const uno::Sequence& rValues) +{ + return std::span(rValues.getConstArray(), rValues.getLength()); +} + +} // anonymous namespace + +CorrelationCircleChart::CorrelationCircleChart(const rtl::Reference& xChartTypeModel, + sal_Int32 nDimensionCount) + : VSeriesPlotter(xChartTypeModel, nDimensionCount, false) +{ + // A correlation circle plot has two dimensions and no more. + assert(nDimensionCount == 2); + + if (!m_pMainPosHelper) + m_pMainPosHelper = new PlottingPositionHelper(); + PlotterBase::m_pPosHelper = m_pMainPosHelper; +} + +CorrelationCircleChart::~CorrelationCircleChart() { delete m_pMainPosHelper; } + +double CorrelationCircleChart::getMinimumX() { return -1.0; } + +double CorrelationCircleChart::getMaximumX() { return 1.0; } + +std::pair +CorrelationCircleChart::getMinimumAndMaximumYInRange(double /*fMinimumX*/, double /*fMaximumX*/, + sal_Int32 /*nAxisIndex*/) +{ + return { -1.0, 1.0 }; +} + +bool CorrelationCircleChart::isExpandBorderToIncrementRhythm(sal_Int32 /*nDimensionIndex*/) +{ + return false; +} + +bool CorrelationCircleChart::isExpandIfValuesCloseToBorder(sal_Int32 /*nDimensionIndex*/) +{ + return false; +} + +bool CorrelationCircleChart::isExpandWideValuesToZero(sal_Int32 /*nDimensionIndex*/) +{ + return false; +} + +bool CorrelationCircleChart::isExpandNarrowValuesTowardZero(sal_Int32 /*nDimensionIndex*/) +{ + return false; +} + +bool CorrelationCircleChart::isSeparateStackingForDifferentSigns(sal_Int32 /*nDimensionIndex*/) +{ + return false; +} + +LegendSymbolStyle CorrelationCircleChart::getLegendSymbolStyle() { return LegendSymbolStyle::Line; } + +uno::Any CorrelationCircleChart::getExplicitSymbol(const VDataSeries& rSeries, + sal_Int32 nPointIndex) +{ + uno::Any aRet; + + Symbol* pSymbolProperties = rSeries.getSymbolProperties(nPointIndex); + if (pSymbolProperties) + aRet <<= *pSymbolProperties; + + return aRet; +} + +drawing::Direction3D CorrelationCircleChart::getPreferredDiagramAspectRatio() const +{ + // Equal width and height keep the circle round and the two correlations at + // the same scale. + return drawing::Direction3D(1, 1, 1); +} + +void CorrelationCircleChart::createUnitCircleAndAxisLines( + const rtl::Reference& xTarget) +{ + PlottingPositionHelper& rPosHelper = getPlottingPositionHelper(MAIN_AXIS_INDEX); + + const drawing::Position3D aOrigin(rPosHelper.transformLogicToScene(0.0, 0.0, fLogicZ, false)); + const drawing::Position3D aLowerLeft( + rPosHelper.transformLogicToScene(-1.0, -1.0, fLogicZ, false)); + const drawing::Position3D aUpperRight( + rPosHelper.transformLogicToScene(1.0, 1.0, fLogicZ, false)); + + const drawing::Direction3D aCircleSize(std::abs(aUpperRight.PositionX - aLowerLeft.PositionX), + std::abs(aUpperRight.PositionY - aLowerLeft.PositionY), + 0.0); + + rtl::Reference xCircle + = ShapeFactory::createCircle2D(xTarget, aOrigin, aCircleSize); + if (xCircle.is()) + { + xCircle->SvxShape::setPropertyValue(u"FillStyle"_ustr, uno::Any(drawing::FillStyle_NONE)); + xCircle->SvxShape::setPropertyValue(u"LineStyle"_ustr, uno::Any(drawing::LineStyle_SOLID)); + xCircle->SvxShape::setPropertyValue(u"LineColor"_ustr, uno::Any(nGuideColor)); + } + + VLineProperties aLineProperties; + aLineProperties.Color <<= nGuideColor; + aLineProperties.LineStyle <<= drawing::LineStyle_SOLID; + + // The two lines span the whole plot area, which may be wider than the + // circle when the axis rounds its range outwards. + const double fMinX = rPosHelper.getLogicMinX(); + const double fMaxX = rPosHelper.getLogicMaxX(); + const double fMinY = rPosHelper.getLogicMinY(); + const double fMaxY = rPosHelper.getLogicMaxY(); + + std::vector> aHorizontalLine{ + { rPosHelper.transformLogicToScene(fMinX, 0.0, fLogicZ, false), + rPosHelper.transformLogicToScene(fMaxX, 0.0, fLogicZ, false) } + }; + ShapeFactory::createLine2D(xTarget, aHorizontalLine, &aLineProperties); + + std::vector> aVerticalLine{ + { rPosHelper.transformLogicToScene(0.0, fMinY, fLogicZ, false), + rPosHelper.transformLogicToScene(0.0, fMaxY, fLogicZ, false) } + }; + ShapeFactory::createLine2D(xTarget, aVerticalLine, &aLineProperties); +} + +void CorrelationCircleChart::createSeriesShapes( + const std::unique_ptr& pSeries, + const rtl::Reference& xSeriesTarget, + const rtl::Reference& xTextTarget) +{ + const std::span aFeatureValues(lclAsSpan(pSeries->getAllFeatureValues())); + const std::optional oCorrelationX( + calculateCorrelationCoefficient(aFeatureValues, lclAsSpan(pSeries->getAllX()))); + const std::optional oCorrelationY( + calculateCorrelationCoefficient(aFeatureValues, lclAsSpan(pSeries->getAllY()))); + + // A feature that does not vary, or that has fewer than two instances to + // compare, has no place in the circle. + if (!oCorrelationX.has_value() || !oCorrelationY.has_value()) + return; + + PlottingPositionHelper& rPosHelper = getPlottingPositionHelper(pSeries->getAttachedAxisIndex()); + m_pPosHelper = &rPosHelper; + + const drawing::Position3D aOrigin(rPosHelper.transformLogicToScene(0.0, 0.0, fLogicZ, false)); + const drawing::Position3D aTip( + rPosHelper.transformLogicToScene(*oCorrelationX, *oCorrelationY, fLogicZ, false)); + + rtl::Reference xSeriesGroupShape_Shapes + = getSeriesGroupShape(pSeries.get(), xSeriesTarget); + + // The single point of the series stands for the whole feature. + const sal_Int32 nPointIndex = 0; + const OUString aPointCID + = ObjectIdentifier::createPointCID(pSeries->getPointCID_Stub(), nPointIndex); + rtl::Reference xPointGroupShape_Shapes( + createGroupShape(xSeriesGroupShape_Shapes, aPointCID)); + + uno::Reference xPointProperties( + pSeries->getPropertiesOfPoint(nPointIndex)); + + VLineProperties aLineProperties; + aLineProperties.initFromPropertySet(xPointProperties); + if (aLineProperties.isLineVisible()) + { + std::vector> aArrow{ { aOrigin, aTip } }; + rtl::Reference xArrow + = ShapeFactory::createLine2D(xPointGroupShape_Shapes, aArrow); + PropertyMapper::setMappedProperties( + *xArrow, xPointProperties, PropertyMapper::getPropertyNameMapForLineSeriesProperties()); + } + + drawing::Direction3D aSymbolSize(0, 0, 0); + Symbol* pSymbolProperties = pSeries->getSymbolProperties(nPointIndex); + if (pSymbolProperties && pSymbolProperties->Style != SymbolStyle_NONE) + { + aSymbolSize.DirectionX = pSymbolProperties->Size.Width; + aSymbolSize.DirectionY = pSymbolProperties->Size.Height; + + if (pSymbolProperties->Style == SymbolStyle_STANDARD) + ShapeFactory::createSymbol2D( + xPointGroupShape_Shapes, aTip, aSymbolSize, pSymbolProperties->StandardSymbol, + pSymbolProperties->BorderColor, pSymbolProperties->FillColor); + else if (pSymbolProperties->Style == SymbolStyle_GRAPHIC) + ShapeFactory::createGraphic2D(xPointGroupShape_Shapes, aTip, aSymbolSize, + pSymbolProperties->Graphic); + } + + if (pSeries->getDataPointLabelIfLabel(nPointIndex)) + { + drawing::Position3D aLabelPosition(aTip.PositionX, aTip.PositionY, + aTip.PositionZ + getTransformedDepth()); + LabelAlignment eAlignment = LABEL_ALIGN_TOP; + + switch ( + pSeries->getLabelPlacement(nPointIndex, m_xChartTypeModel, rPosHelper.isSwapXAndY())) + { + case css::chart::DataLabelPlacement::BOTTOM: + aLabelPosition.PositionY += (aSymbolSize.DirectionY / 2 + 1); + eAlignment = LABEL_ALIGN_BOTTOM; + break; + case css::chart::DataLabelPlacement::LEFT: + aLabelPosition.PositionX -= (aSymbolSize.DirectionX / 2 + 1); + eAlignment = LABEL_ALIGN_LEFT; + break; + case css::chart::DataLabelPlacement::RIGHT: + aLabelPosition.PositionX += (aSymbolSize.DirectionX / 2 + 1); + eAlignment = LABEL_ALIGN_RIGHT; + break; + case css::chart::DataLabelPlacement::CENTER: + eAlignment = LABEL_ALIGN_CENTER; + break; + default: + aLabelPosition.PositionY -= (aSymbolSize.DirectionY / 2 + 1); + eAlignment = LABEL_ALIGN_TOP; + break; + } + + const awt::Point aScreenPosition2D(LabelPositionHelper(m_nDimension, m_xLogicTarget) + .transformSceneToScreenPosition(aLabelPosition)); + const sal_Int32 nOffset = (eAlignment == LABEL_ALIGN_CENTER) ? 0 : 100; + + // The correlation with the second dimension is the number the point + // stands at, and one is the whole a correlation can be. + createDataLabel(xTextTarget, *pSeries, nPointIndex, *oCorrelationY, 1.0, aScreenPosition2D, + eAlignment, nOffset); + } + + if (!xPointGroupShape_Shapes->getCount()) + xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shapes); +} + +void CorrelationCircleChart::createShapes() +{ + if (m_aZSlots.empty()) //no series + return; + + OSL_ENSURE(m_xLogicTarget.is() && m_xFinalTarget.is(), + "CorrelationCircleChart is not proper initialized"); + if (!(m_xLogicTarget.is() && m_xFinalTarget.is())) + return; + + // The guides go into their own group first, so that the arrows and the + // labels are drawn over them. + rtl::Reference xGuideTarget = createGroupShape(m_xLogicTarget); + rtl::Reference xSeriesTarget = createGroupShape(m_xLogicTarget); + rtl::Reference xTextTarget = ShapeFactory::createGroup2D(m_xFinalTarget); + + createUnitCircleAndAxisLines(xGuideTarget); + + for (auto const& rZSlot : m_aZSlots) + { + for (auto const& rXSlot : rZSlot) + { + for (std::unique_ptr const& pSeries : rXSlot.m_aSeriesVector) + { + if (!pSeries) + continue; + + createSeriesShapes(pSeries, xSeriesTarget, xTextTarget); + } + } + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/view/charttypes/CorrelationCircleChart.hxx b/chart2/source/view/charttypes/CorrelationCircleChart.hxx new file mode 100644 index 000000000000..6852fc0fbd9f --- /dev/null +++ b/chart2/source/view/charttypes/CorrelationCircleChart.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include +#include + +namespace chart +{ +/** Draws a correlation circle plot: one arrow per series, from the origin to + the point whose coordinates are the correlation of that series' feature + column with each of the two dimension columns. Both axes cover minus one to + one, the range a correlation has. + */ +class CorrelationCircleChart final : public VSeriesPlotter +{ +public: + CorrelationCircleChart() = delete; + + CorrelationCircleChart(const rtl::Reference<::chart::ChartType>& xChartTypeModel, + sal_Int32 nDimensionCount); + virtual ~CorrelationCircleChart() override; + + virtual void createShapes() override; + + virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override; + + // MinimumAndMaximumSupplier + virtual double getMinimumX() override; + virtual double getMaximumX() override; + virtual std::pair + getMinimumAndMaximumYInRange(double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex) override; + virtual bool isExpandBorderToIncrementRhythm(sal_Int32 nDimensionIndex) override; + virtual bool isExpandIfValuesCloseToBorder(sal_Int32 nDimensionIndex) override; + virtual bool isExpandWideValuesToZero(sal_Int32 nDimensionIndex) override; + virtual bool isExpandNarrowValuesTowardZero(sal_Int32 nDimensionIndex) override; + virtual bool isSeparateStackingForDifferentSigns(sal_Int32 nDimensionIndex) override; + + virtual LegendSymbolStyle getLegendSymbolStyle() override; + virtual css::uno::Any getExplicitSymbol(const VDataSeries& rSeries, + sal_Int32 nPointIndex) override; + +private: + void createUnitCircleAndAxisLines(const rtl::Reference& xTarget); + void createSeriesShapes(const std::unique_ptr& pSeries, + const rtl::Reference& xSeriesTarget, + const rtl::Reference& xTextTarget); +}; + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/view/charttypes/FunnelChart.cxx b/chart2/source/view/charttypes/FunnelChart.cxx new file mode 100644 index 000000000000..17e5f3f713b3 --- /dev/null +++ b/chart2/source/view/charttypes/FunnelChart.cxx @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "FunnelChart.hxx" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +namespace chart +{ +using namespace ::com::sun::star; + +FunnelChart::FunnelChart(const rtl::Reference& xChartTypeModel, + sal_Int32 nDimensionCount) + : BarChart(xChartTypeModel, nDimensionCount) +{ + // We only support 2 dimensional funnel charts + assert(nDimensionCount == 2 && "FunnelChart only supports 2D charts"); + + // Runtime check for all builds + if (nDimensionCount != 2) + { + // Log a warning or throw an exception if appropriate + SAL_WARN("chart2", "FunnelChart created with invalid dimension count. Forcing 2D."); + } + + PlotterBase::m_pPosHelper = &m_aMainPosHelper; + VSeriesPlotter::m_pMainPosHelper = &m_aMainPosHelper; + + try + { + if (m_xChartTypeModel.is()) + m_xChartTypeModel->getPropertyValue(u"GapwidthSequence"_ustr) >>= m_aGapwidthSequence; + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } + + m_bAlignCenter = true; +} + +FunnelChart::~FunnelChart() {} + +#if 0 +PlottingPositionHelper& FunnelChart::getPlottingPositionHelper(sal_Int32 nAxisIndex) const +{ + PlottingPositionHelper& rPosHelper = VSeriesPlotter::getPlottingPositionHelper(nAxisIndex); + BarPositionHelper* pFunnelPosHelper = dynamic_cast(&rPosHelper); + if (pFunnelPosHelper && nAxisIndex >= 0) + { + if (nAxisIndex < m_aGapwidthSequence.getLength()) + pFunnelPosHelper->setOuterDistance(m_aGapwidthSequence[nAxisIndex] / 100.0); + } + + return rPosHelper; +} + +css::awt::Point FunnelChart::getLabelScreenPositionAndAlignment( + LabelAlignment& rAlignment, sal_Int32 nLabelPlacement, double fScaledX, + double fScaledLowerYValue, double fScaledUpperYValue, double fBaseValue, + BarPositionHelper const* pPosHelper) const +{ + double fY = fScaledUpperYValue; + bool bReverse = !pPosHelper->isMathematicalOrientationY(); + bool bNormalOutside = (!bReverse == (fBaseValue < fScaledUpperYValue)); + + switch (nLabelPlacement) + { + case css::chart::DataLabelPlacement::TOP: + fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue; + rAlignment = LABEL_ALIGN_TOP; + break; + case css::chart::DataLabelPlacement::BOTTOM: + fY = bReverse ? fScaledUpperYValue : fScaledLowerYValue; + rAlignment = LABEL_ALIGN_BOTTOM; + break; + case css::chart::DataLabelPlacement::OUTSIDE: + fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue; + rAlignment = bNormalOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM; + break; + case css::chart::DataLabelPlacement::INSIDE: + fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue; + rAlignment = bNormalOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP; + break; + case css::chart::DataLabelPlacement::CENTER: + fY -= (fScaledUpperYValue - fScaledLowerYValue) / 2.0; + rAlignment = LABEL_ALIGN_CENTER; + break; + default: + OSL_FAIL("this label alignment is not implemented yet"); + break; + } + + css::drawing::Position3D aScenePosition3D( + pPosHelper->transformScaledLogicToScene(fScaledX, fY, 0.0, true)); + return LabelPositionHelper(2, m_xLogicTarget).transformSceneToScreenPosition(aScenePosition3D); +} +#endif + +void FunnelChart::createShapes() +{ + if (m_aZSlots.empty()) //No data series Available + return; + + OSL_ENSURE(m_xLogicTarget.is() && m_xFinalTarget.is(), + "FunnelChart is not properly initialized"); // Ensuring chart is properly initialized + if (!(m_xLogicTarget.is() && m_xFinalTarget.is())) + return; + + if (!m_pMainPosHelper) + m_pMainPosHelper = new BarPositionHelper(); + + BarChart::createShapes(); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/view/charttypes/FunnelChart.hxx b/chart2/source/view/charttypes/FunnelChart.hxx new file mode 100644 index 000000000000..73dec3868732 --- /dev/null +++ b/chart2/source/view/charttypes/FunnelChart.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "BarChart.hxx" +#include "BarPositionHelper.hxx" + +#include + +namespace chart +{ +class FunnelChart : public BarChart +{ +public: + FunnelChart() = delete; + + FunnelChart(const rtl::Reference& xChartTypeModel, sal_Int32 nDimensionCount); + virtual ~FunnelChart() override; + + virtual void createShapes() override; + +private: +#if 0 + virtual PlottingPositionHelper& getPlottingPositionHelper(sal_Int32 nAxisIndex) const override; + + css::awt::Point getLabelScreenPositionAndAlignment(LabelAlignment& rAlignment, + sal_Int32 nLabelPlacement, double fScaledX, + double fScaledLowerYValue, + double fScaledUpperYValue, double fBaseValue, + BarPositionHelper const* pPosHelper) const; +#endif + +private: + BarPositionHelper m_aMainPosHelper; + css::uno::Sequence m_aGapwidthSequence; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/view/charttypes/HistogramChart.cxx b/chart2/source/view/charttypes/HistogramChart.cxx new file mode 100644 index 000000000000..bc24c746d31e --- /dev/null +++ b/chart2/source/view/charttypes/HistogramChart.cxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "HistogramChart.hxx" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +namespace chart +{ +HistogramChart::HistogramChart(const rtl::Reference& xChartTypeModel, + sal_Int32 nDimensionCount) + : BarChart(xChartTypeModel, nDimensionCount) +{ + // We only support 2 dimensional histogram charts + assert(nDimensionCount == 2 && "HistogramChart only supports 2D charts"); + + // Runtime check for all builds + if (nDimensionCount != 2) + { + // Log a warning or throw an exception if appropriate + SAL_WARN("chart2", "HistogramChart created with invalid dimension count. Forcing 2D."); + } + + PlotterBase::m_pPosHelper = &m_aMainPosHelper; + VSeriesPlotter::m_pMainPosHelper = &m_aMainPosHelper; + + try + { + if (m_xChartTypeModel.is()) + m_xChartTypeModel->getPropertyValue(u"GapwidthSequence"_ustr) >>= m_aGapwidthSequence; + } + catch (const css::uno::Exception&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } +} + +HistogramChart::~HistogramChart() {} + +css::drawing::Direction3D HistogramChart::getPreferredDiagramAspectRatio() const +{ + // Return the preferred aspect ratio for the histogram chart + return css::drawing::Direction3D(-1, -1, -1); +} + +PlottingPositionHelper& HistogramChart::getPlottingPositionHelper(sal_Int32 nAxisIndex) const +{ + PlottingPositionHelper& rPosHelper = VSeriesPlotter::getPlottingPositionHelper(nAxisIndex); + BarPositionHelper* pHistogramPosHelper = dynamic_cast(&rPosHelper); + if (pHistogramPosHelper && nAxisIndex >= 0) + { + if (nAxisIndex < m_aGapwidthSequence.getLength()) + pHistogramPosHelper->setOuterDistance(m_aGapwidthSequence[nAxisIndex] / 100.0); + } + + return rPosHelper; +} + +void HistogramChart::addSeries(std::unique_ptr pSeries, sal_Int32 zSlot, + sal_Int32 xSlot, sal_Int32 ySlot) +{ + if (!pSeries) + return; + + if (m_nDimension == 2) + { + sal_Int32 nAxisIndex = pSeries->getAttachedAxisIndex(); + zSlot = nAxisIndex; + + // Plot the calculated bin frequencies rather than the raw input data. + pSeries->useCalculatedYForRendering(); + pSeries->setCategoryXAxis(); + + if (!pSeries->getGroupBarsPerAxis()) + zSlot = 0; + if (zSlot >= static_cast(m_aZSlots.size())) + m_aZSlots.resize(zSlot + 1); + } + + VSeriesPlotter::addSeries(std::move(pSeries), zSlot, xSlot, ySlot); +} + +void HistogramChart::adaptGapWidthForHistogram() +{ + VDataSeries* pFirstSeries = getFirstSeries(); + if (!pFirstSeries) + return; + + sal_Int32 nAxisIndex = pFirstSeries->getAttachedAxisIndex(); + sal_Int32 nUseThisIndex = nAxisIndex; + if (nUseThisIndex < 0 || nUseThisIndex >= m_aGapwidthSequence.getLength()) + nUseThisIndex = 0; + + auto aGapwidthSequenceRange = asNonConstRange(m_aGapwidthSequence); + for (sal_Int32 nN = 0; nN < m_aGapwidthSequence.getLength(); nN++) + { + aGapwidthSequenceRange[nN] = 0; // Set gap width to 0 + } +} + +void HistogramChart::createShapes() +{ + if (m_aZSlots.empty()) //No data series Available + return; + + OSL_ENSURE( + m_xLogicTarget.is() && m_xFinalTarget.is(), + "HistogramChart is not properly initialized"); // Ensuring chart is properly initialized + if (!(m_xLogicTarget.is() && m_xFinalTarget.is())) + return; + + adaptGapWidthForHistogram(); + + if (!m_pMainPosHelper) + m_pMainPosHelper = new BarPositionHelper(); + + BarChart::createShapes(); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/view/charttypes/HistogramChart.hxx b/chart2/source/view/charttypes/HistogramChart.hxx new file mode 100644 index 000000000000..a5bcabf79b45 --- /dev/null +++ b/chart2/source/view/charttypes/HistogramChart.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "BarChart.hxx" +#include "BarPositionHelper.hxx" + +#include + +namespace chart +{ +/** Renders a histogram: bin frequencies drawn as gap-less bars. */ +class HistogramChart : public BarChart +{ +public: + HistogramChart() = delete; + + HistogramChart(const rtl::Reference& xChartTypeModel, sal_Int32 nDimensionCount); + virtual ~HistogramChart() override; + + virtual void createShapes() override; + virtual void addSeries(std::unique_ptr pSeries, sal_Int32 zSlot, sal_Int32 xSlot, + sal_Int32 ySlot) override; + + virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override; + +private: + virtual PlottingPositionHelper& getPlottingPositionHelper(sal_Int32 nAxisIndex) const override; + + void adaptGapWidthForHistogram(); + +private: + BarPositionHelper m_aMainPosHelper; + css::uno::Sequence m_aGapwidthSequence; +}; + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/chart2/source/view/charttypes/Splines.cxx b/chart2/source/view/charttypes/Splines.cxx index ca0280fd64a7..fe2c67792ad5 100644 --- a/chart2/source/view/charttypes/Splines.cxx +++ b/chart2/source/view/charttypes/Splines.cxx @@ -297,7 +297,7 @@ void lcl_SplineCalculation::CalculatePeriodic() Aupper[ n ] = xDiff_i; u [ n ] = 3 * (yDiff_i - yDiff_im1); - // decomposite A=(R transpose)*D*R + // decompose A=(R transpose)*D*R Ddiag[1] = Adiag[1]; Rupper[1] = Aupper[1] / Ddiag[1]; Rright[1] = Aupper[n] / Ddiag[1]; @@ -631,7 +631,7 @@ void SplineCalculator::CalculateBSplines( , sal_uInt32 nDegree ) { // nResolution is ODF1.2 file format attribute chart:spline-resolution and - // ODF1.2 spec variable k. Causion, k is used as index in the spec in addition. + // ODF1.2 spec variable k. Caution, k is used as index in the spec in addition. // nDegree is ODF1.2 file format attribute chart:spline-order and // ODF1.2 spec variable p OSL_ASSERT( nResolution > 1 ); diff --git a/chart2/source/view/charttypes/Splines.hxx b/chart2/source/view/charttypes/Splines.hxx index bbd189909083..766718bc9f70 100644 --- a/chart2/source/view/charttypes/Splines.hxx +++ b/chart2/source/view/charttypes/Splines.hxx @@ -35,7 +35,7 @@ public: , std::vector>& rResult , sal_uInt32 nGranularity ); - static void CalculateBSplines( + SAL_DLLPUBLIC_EXPORT static void CalculateBSplines( const std::vector>& rPoints , std::vector>& rResult , sal_uInt32 nGranularity diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index 3d9d61080258..70a8a7021424 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -53,11 +53,14 @@ //only for creation: @todo remove if all plotter are uno components and instantiated via servicefactory #include "BarChart.hxx" +#include "HistogramChart.hxx" #include "PieChart.hxx" #include "AreaChart.hxx" #include "CandleStickChart.hxx" #include "BubbleChart.hxx" +#include "CorrelationCircleChart.hxx" #include "NetChart.hxx" +#include "FunnelChart.hxx" #include "UnsupportedChart.hxx" #include #include @@ -1925,7 +1928,7 @@ public: { SeriesMinMaxType& rStore = m_SeriesGroup[fX]; // get storage for given X value. if (rStore.empty()) - rStore.resize(mnNumSeries, { std::numeric_limits::max(), std::numeric_limits::min() }); + rStore.resize(mnNumSeries, { std::numeric_limits::max(), std::numeric_limits::lowest() }); MinMaxType& r = rStore[mnCurSeries]; if (fY < r.first) @@ -1944,10 +1947,10 @@ public: } rfMin = std::numeric_limits::max(); - rfMax = std::numeric_limits::min(); + rfMax = std::numeric_limits::lowest(); /** - * For each, X value, calculate Y value range + * For each X value, calculate Y value range */ for (auto const& it : m_SeriesGroup) { @@ -2223,7 +2226,7 @@ OUString VSeriesPlotter::getCategoryName( sal_Int32 nPointIndex ) const } namespace { -// The following it to support rendering order for combo charts. A chart type +// The following is to support rendering order for combo charts. A chart type // with a lower rendering order is rendered before (i.e., behind) a chart with a // higher rendering order. The rendering orders are based on rough guesses about // how much one chart (type) will obscure another chart (type). The intent is to @@ -2242,13 +2245,15 @@ const ROrderPair pairList[] = { ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_AREA, 0), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_BAR, 6), // bar & column are same ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN, 6), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM, 9), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_LINE, 8), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER, 5), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_PIE, 1), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_NET, 3), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET, 2), ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK, 7), - ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE, 4) + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE, 4), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE, 5) }; } // unnamed @@ -2881,6 +2886,8 @@ VSeriesPlotter* VSeriesPlotter::createSeriesPlotter( pRet = new BarChart(xChartTypeModel,nDimensionCount); else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_BAR ) ) pRet = new BarChart(xChartTypeModel,nDimensionCount); + else if (aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM)) + pRet = new HistogramChart(xChartTypeModel, nDimensionCount); else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_AREA ) ) pRet = new AreaChart(xChartTypeModel,nDimensionCount,true); else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_LINE ) ) @@ -2889,6 +2896,8 @@ VSeriesPlotter* VSeriesPlotter::createSeriesPlotter( pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) pRet = new BubbleChart(xChartTypeModel,nDimensionCount); + else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CORRELATIONCIRCLE) ) + pRet = new CorrelationCircleChart(xChartTypeModel,nDimensionCount); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) pRet = new PieChart(xChartTypeModel,nDimensionCount, bExcludingPositioning ); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) @@ -2897,8 +2906,8 @@ VSeriesPlotter* VSeriesPlotter::createSeriesPlotter( pRet = new NetChart(xChartTypeModel,nDimensionCount,false,std::make_unique()); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) pRet = new CandleStickChart(xChartTypeModel,nDimensionCount); - else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ) - pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true); + else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_FUNNEL) ) + pRet = new FunnelChart(xChartTypeModel,nDimensionCount); else pRet = new UnsupportedChart(xChartTypeModel); return pRet; diff --git a/chart2/source/view/inc/VDataSeries.hxx b/chart2/source/view/inc/VDataSeries.hxx index 572645565e5e..5d32f07a5ede 100644 --- a/chart2/source/view/inc/VDataSeries.hxx +++ b/chart2/source/view/inc/VDataSeries.hxx @@ -94,6 +94,7 @@ public: css::uno::Sequence< double > const & getAllX() const; css::uno::Sequence< double > const & getAllY() const; + css::uno::Sequence< double > const & getAllFeatureValues() const; double getXMeanValue() const; double getYMeanValue() const; @@ -172,6 +173,11 @@ public: void setOldTimeBased( VDataSeries* pOldSeries, double nPercent ); VDataSeries* createCopyForTimeBased() const; + // Chart types that calculate the resulting values use this once during addSeries + // to promote the calculated Y sidecar into the primary Y values, so the rendering + // path plots the frequencies instead of the raw data. + void useCalculatedYForRendering(); + private: //methods css::chart2::DataPointLabel* getDataPointLabel( sal_Int32 index ) const; void adaptPointCache( sal_Int32 nNewPointIndex ) const; @@ -194,19 +200,22 @@ private: //member rtl::Reference<::chart::DataSeries> m_xDataSeries; css::uno::Reference m_xDataSeriesProps; // cached - //all points given by the model data (here are not only the visible points meant) + //all points given by the model data (not only the visible points) sal_Int32 m_nPointCount; VDataSequence m_aValues_X; VDataSequence m_aValues_Y; VDataSequence m_aValues_Z; + VDataSequence m_aCalculatedValues_Y; + VDataSequence m_aValues_Y_Min; VDataSequence m_aValues_Y_Max; VDataSequence m_aValues_Y_First; VDataSequence m_aValues_Y_Last; VDataSequence m_aValues_Bubble_Size; + VDataSequence m_aValues_Feature; VDataSequence* m_pValueSequenceForDataLabelNumberFormatDetection; diff --git a/chart2/source/view/main/ChartItemPool.cxx b/chart2/source/view/main/ChartItemPool.cxx index 9b03bf429ea5..ca114b1a64e5 100644 --- a/chart2/source/view/main/ChartItemPool.cxx +++ b/chart2/source/view/main/ChartItemPool.cxx @@ -173,8 +173,14 @@ static ItemInfoPackage& getItemInfoPackageChart() { SCHATTR_DATA_TABLE_VERTICAL_BORDER, new SfxBoolItem(SCHATTR_DATA_TABLE_VERTICAL_BORDER, false), 0, SFX_ITEMINFOFLAG_NONE }, { SCHATTR_DATA_TABLE_OUTLINE, new SfxBoolItem(SCHATTR_DATA_TABLE_OUTLINE, false), 0, SFX_ITEMINFOFLAG_NONE }, { SCHATTR_DATA_TABLE_KEYS, new SfxBoolItem(SCHATTR_DATA_TABLE_KEYS, false), 0, SFX_ITEMINFOFLAG_NONE }, - { SCHATTR_COLOR_PALETTE, new SvxChartColorPaletteItem(ChartColorPaletteType::Unknown, 0, SCHATTR_COLOR_PALETTE), 0, SFX_ITEMINFOFLAG_NONE } - + { SCHATTR_COLOR_PALETTE, new SvxChartColorPaletteItem(ChartColorPaletteType::Unknown, 0, SCHATTR_COLOR_PALETTE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_HISTOGRAM_FREQUENCY_TYPE, new SfxInt32Item(SCHATTR_HISTOGRAM_FREQUENCY_TYPE, 0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_HISTOGRAM_BIN_WIDTH, new SvxDoubleItem(0.0, SCHATTR_HISTOGRAM_BIN_WIDTH), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_HISTOGRAM_BIN_COUNT, new SfxInt32Item(SCHATTR_HISTOGRAM_BIN_COUNT, 0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_HISTOGRAM_USE_UNDERFLOW_BIN, new SfxBoolItem(SCHATTR_HISTOGRAM_USE_UNDERFLOW_BIN, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_HISTOGRAM_UNDERFLOW_BIN_VALUE, new SvxDoubleItem(0.0, SCHATTR_HISTOGRAM_UNDERFLOW_BIN_VALUE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_HISTOGRAM_USE_OVERFLOW_BIN, new SfxBoolItem(SCHATTR_HISTOGRAM_USE_OVERFLOW_BIN, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_HISTOGRAM_OVERFLOW_BIN_VALUE, new SvxDoubleItem(0.0, SCHATTR_HISTOGRAM_OVERFLOW_BIN_VALUE), 0, SFX_ITEMINFOFLAG_NONE } }}; virtual const ItemInfoStatic& getItemInfoStatic(size_t nIndex) const override { return maItemInfos[nIndex]; } @@ -223,7 +229,7 @@ rtl::Reference ChartItemPool::CreateChartItemPool() // UNO methods which may get called from out of process, this // happens on a thread that does not take the SolarMutex, which // causes trouble in ImplFontCache. - // Trying to take the SolarMutex when initialising these default + // Trying to take the SolarMutex when initialising these defaults // leads to ABBA deadlocks. // So rather just trigger the initialisation of these things here. StaticDataSeriesDefaults(); diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx index 28e4333da5b9..9f6739f2ed11 100644 --- a/chart2/source/view/main/ChartView.cxx +++ b/chart2/source/view/main/ChartView.cxx @@ -993,7 +993,8 @@ bool getAvailablePosAndSizeForDiagram( enum class TitleAlignment { ALIGN_LEFT, ALIGN_TOP, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_Z }; void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment - , awt::Rectangle const & rDiagramPlusAxesRect, const awt::Size & rPageSize ) + , awt::Rectangle const & rDiagramPlusAxesRect, sal_Int32 nDiagramVerticalCenter + , const awt::Size & rPageSize ) { if(!pVTitle) return; @@ -1013,12 +1014,14 @@ void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height + aTitleSize.Height/2 + nYDistance ); break; case TitleAlignment::ALIGN_LEFT: + // Center on the plot area (the axis), not on the plot area plus axes, + // so a data table drawn below the plot area does not shift the title down. aNewPosition = awt::Point( rDiagramPlusAxesRect.X - aTitleSize.Width/2 - nXDistance - , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 ); + , nDiagramVerticalCenter ); break; case TitleAlignment::ALIGN_RIGHT: aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance - , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 ); + , nDiagramVerticalCenter ); break; case TitleAlignment::ALIGN_Z: aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance @@ -1986,16 +1989,20 @@ void ChartView::createShapes2D( const awt::Size& rPageSize ) //correct axis title position awt::Rectangle aDiagramPlusAxesRect( aUsedOuterRect ); + // The vertical (left/right) axis titles are centered on the plot area, + // which excludes a data table drawn below it. + sal_Int32 nDiagramVerticalCenter = m_aResultingDiagramRectangleExcludingAxes.Y + + m_aResultingDiagramRectangleExcludingAxes.Height / 2; if (aParam.mbAutoPosTitleX) - changePositionOfAxisTitle(aParam.mpVTitleX.get(), TitleAlignment::ALIGN_BOTTOM, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleX.get(), TitleAlignment::ALIGN_BOTTOM, aDiagramPlusAxesRect, nDiagramVerticalCenter, rPageSize); if (aParam.mbAutoPosTitleY) - changePositionOfAxisTitle(aParam.mpVTitleY.get(), TitleAlignment::ALIGN_LEFT, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleY.get(), TitleAlignment::ALIGN_LEFT, aDiagramPlusAxesRect, nDiagramVerticalCenter, rPageSize); if (aParam.mbAutoPosTitleZ) - changePositionOfAxisTitle(aParam.mpVTitleZ.get(), TitleAlignment::ALIGN_Z, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleZ.get(), TitleAlignment::ALIGN_Z, aDiagramPlusAxesRect, nDiagramVerticalCenter, rPageSize); if (aParam.mbAutoPosSecondTitleX) - changePositionOfAxisTitle(aParam.mpVTitleSecondX.get(), bIsVertical? TitleAlignment::ALIGN_RIGHT : TitleAlignment::ALIGN_TOP, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleSecondX.get(), bIsVertical? TitleAlignment::ALIGN_RIGHT : TitleAlignment::ALIGN_TOP, aDiagramPlusAxesRect, nDiagramVerticalCenter, rPageSize); if (aParam.mbAutoPosSecondTitleY) - changePositionOfAxisTitle(aParam.mpVTitleSecondY.get(), bIsVertical? TitleAlignment::ALIGN_TOP : TitleAlignment::ALIGN_RIGHT, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleSecondY.get(), bIsVertical? TitleAlignment::ALIGN_TOP : TitleAlignment::ALIGN_RIGHT, aDiagramPlusAxesRect, nDiagramVerticalCenter, rPageSize); } //cleanup: remove all empty group shapes to avoid grey border lines: diff --git a/chart2/source/view/main/DataTableView.cxx b/chart2/source/view/main/DataTableView.cxx index 312c441ce975..337eb77309a6 100644 --- a/chart2/source/view/main/DataTableView.cxx +++ b/chart2/source/view/main/DataTableView.cxx @@ -571,7 +571,13 @@ void DataTableView::initializeValues( for (int i = 0; i < pSeries->getTotalPointCount(); i++) { double nValue = pSeries->getYValue(i); - rValues.push_back(rSeriesPlotter->getLabelTextForValue(*pSeries, i, nValue, false)); + // Skip missing/error data points (NaN, +/-Inf); a date or time number format would + // otherwise propagate the bizarre value into the formatter and trigger an assert + if (!std::isfinite(nValue)) + rValues.push_back(OUString()); + else + rValues.push_back( + rSeriesPlotter->getLabelTextForValue(*pSeries, i, nValue, false)); } } } diff --git a/chart2/source/view/main/PlotterBase.cxx b/chart2/source/view/main/PlotterBase.cxx index d09bba64aeef..a52c05531d5e 100644 --- a/chart2/source/view/main/PlotterBase.cxx +++ b/chart2/source/view/main/PlotterBase.cxx @@ -52,7 +52,7 @@ void PlotterBase::setScales( std::vector< ExplicitScaleData >&& rScales, bool bS if (!m_pPosHelper) return; - OSL_PRECOND(m_nDimension<=static_cast(rScales.size()),"Dimension of Plotter does not fit two dimension of given scale sequence"); + OSL_PRECOND(m_nDimension<=static_cast(rScales.size()),"Dimension of Plotter does not fit the dimension of given scale sequence"); m_pPosHelper->setScales( std::move(rScales), bSwapXAndYAxis ); } @@ -78,7 +78,7 @@ rtl::Reference PlotterBase::createGroupShape( } else { - //create and added to target + //create and add to target return ShapeFactory::createGroup3D( xTarget, rName ); } } diff --git a/chart2/source/view/main/PolarLabelPositionHelper.cxx b/chart2/source/view/main/PolarLabelPositionHelper.cxx index d59ee7c111b1..b1562b113714 100644 --- a/chart2/source/view/main/PolarLabelPositionHelper.cxx +++ b/chart2/source/view/main/PolarLabelPositionHelper.cxx @@ -81,7 +81,7 @@ awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCi if(m_nDimensionCount==3 && nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE) { - //check whether the upper or the downer edge is more distant from the center + //check whether the upper or the lower edge is more distant from the center //take the farthest point to put the label to awt::Point aP0( transformSceneToScreenPosition( diff --git a/chart2/source/view/main/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx index 1d5fd9ce755c..2fabffb6acc9 100644 --- a/chart2/source/view/main/ShapeFactory.cxx +++ b/chart2/source/view/main/ShapeFactory.cxx @@ -312,7 +312,7 @@ static uno::Any createPolyPolygon_Cone( double fHeight, double fRadius, double f OSL_PRECOND(fRadius>0, "The radius of a cone needs to be > 0"); //for stacked charts we need cones without top -> fTopHeight != 0 resp. bTopless == true - //fTopHeight indicates the high of the cutted top only (not the full height) + //fTopHeight indicates the height of the cut top only (not the full height) bool bTopless = !::rtl::math::approxEqual( fHeight, fHeight + fTopHeight ); double r1= 0.0, r2 = fRadius; @@ -800,7 +800,7 @@ static drawing::PolyPolygonBezierCoords getCircularArcBezierCoords( for(sal_Int32 nSegment=0; nSegment& xDataSeries ) for(sal_Int32 nN = aDataSequences.size();nN--;) { uno::Reference xDataSequence( aDataSequences[nN]->getValues()); + + if (!xDataSequence.is()) + { + continue; + } + uno::Reference xProp(xDataSequence, uno::UNO_QUERY ); if( xProp.is()) { @@ -195,6 +201,8 @@ VDataSeries::VDataSeries( const rtl::Reference< DataSeries >& xDataSeries ) m_aValues_Y_Last.init( xDataSequence ); else if (aRole == "values-size") m_aValues_Bubble_Size.init( xDataSequence ); + else if (aRole == "values-feature") + m_aValues_Feature.init( xDataSequence ); else { VDataSequence aSequence; @@ -224,6 +232,13 @@ VDataSeries::VDataSeries( const rtl::Reference< DataSeries >& xDataSeries ) m_nPointCount = m_aValues_Y_Last.getLength(); } + // populated by chart types that render derived values + if (auto xCalculatedSequence = m_xDataSeries->getCalculatedYSequence()) + { + if (xCalculatedSequence->getValues().is()) + m_aCalculatedValues_Y.init(xCalculatedSequence->getValues()); + } + if( !xDataSeries.is()) return; @@ -248,6 +263,15 @@ VDataSeries::~VDataSeries() { } +void VDataSeries::useCalculatedYForRendering() +{ + if (!m_aCalculatedValues_Y.is()) + return; + + m_aValues_Y = m_aCalculatedValues_Y; + m_nPointCount = m_aValues_Y.getLength(); +} + void VDataSeries::doSortByXValues() { if( !(m_aValues_X.is() && m_aValues_X.m_aValues.hasElements()) ) @@ -444,12 +468,12 @@ double VDataSeries::getXValue( sal_Int32 index ) const double VDataSeries::getYValue( sal_Int32 index ) const { double fRet = std::numeric_limits::quiet_NaN(); - if(m_aValues_Y.is()) + if (m_aValues_Y.is()) { - if( 0<=index && indexm_aValues_Y.getLength()) + if (mpOldSeries && index < mpOldSeries->m_aValues_Y.getLength()) { double nOldVal = mpOldSeries->m_aValues_Y.m_aValues[index]; fRet = nOldVal + (fRet - nOldVal) * mnPercent; @@ -459,8 +483,8 @@ double VDataSeries::getYValue( sal_Int32 index ) const else { // #i70133# always return correct X position - needed for short data series - if( 0<=index /*&& index < m_nPointCount*/ ) - fRet = index+1;//first category (index 0) matches with real number 1.0 + if (0 <= index /*&& index < m_nPointCount*/) + fRet = index + 1; //first category (index 0) matches with real number 1.0 } lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() ); return fRet; @@ -669,9 +693,9 @@ double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const { double fMin = std::numeric_limits::infinity(); - if( !m_aValues_Y.is() && + if (!m_aValues_Y.is() && (m_aValues_Y_Min.is() || m_aValues_Y_Max.is() - || m_aValues_Y_First.is() || m_aValues_Y_Last.is() ) ) + || m_aValues_Y_First.is() || m_aValues_Y_Last.is())) { double fY_Min = getY_Min( index ); double fY_Max = getY_Max( index ); @@ -704,9 +728,9 @@ double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const { double fMax = -std::numeric_limits::infinity(); - if( !m_aValues_Y.is() && + if (!m_aValues_Y.is() && (m_aValues_Y_Min.is() || m_aValues_Y_Max.is() - || m_aValues_Y_First.is() || m_aValues_Y_Last.is() ) ) + || m_aValues_Y_First.is() || m_aValues_Y_Last.is())) { double fY_Min = getY_Min( index ); double fY_Max = getY_Max( index ); @@ -749,6 +773,11 @@ uno::Sequence< double > const & VDataSeries::getAllX() const return m_aValues_X.m_aValues; } +uno::Sequence< double > const & VDataSeries::getAllFeatureValues() const +{ + return m_aValues_Feature.m_aValues; +} + uno::Sequence< double > const & VDataSeries::getAllY() const { if(!m_aValues_Y.is() && !m_aValues_Y.getLength() && m_nPointCount) @@ -1092,11 +1121,13 @@ VDataSeries* VDataSeries::createCopyForTimeBased() const pNew->m_aValues_X = m_aValues_X; pNew->m_aValues_Y = m_aValues_Y; pNew->m_aValues_Z = m_aValues_Z; + pNew->m_aCalculatedValues_Y = m_aCalculatedValues_Y; pNew->m_aValues_Y_Min = m_aValues_Y_Min; pNew->m_aValues_Y_Max = m_aValues_Y_Max; pNew->m_aValues_Y_First = m_aValues_Y_First; pNew->m_aValues_Y_Last = m_aValues_Y_Last; pNew->m_aValues_Bubble_Size = m_aValues_Bubble_Size; + pNew->m_aValues_Feature = m_aValues_Feature; pNew->m_PropertyMap = m_PropertyMap; pNew->m_nPointCount = m_nPointCount; diff --git a/chart2/uiconfig/menubar/menubar.xml b/chart2/uiconfig/menubar/menubar.xml index 1c0304f6da6c..7a06e7521f5f 100644 --- a/chart2/uiconfig/menubar/menubar.xml +++ b/chart2/uiconfig/menubar/menubar.xml @@ -23,12 +23,12 @@ - + - + - + @@ -43,7 +43,7 @@ - + @@ -51,62 +51,62 @@ - - - - - + + + + + - - - - - + + + + + - + - - + + - - - + + + - - + + - + - + - - - + + + - - + + - + - + - - - + + + - - - + + + - + @@ -114,37 +114,37 @@ - - - + + + - - + + - + - + - - - - + + + + - + - + @@ -152,7 +152,7 @@ - + @@ -160,20 +160,19 @@ - + - - + - + - + diff --git a/chart2/uiconfig/statusbar/statusbar.xml b/chart2/uiconfig/statusbar/statusbar.xml index 4f718b8d1de3..9b80cc6b0fca 100644 --- a/chart2/uiconfig/statusbar/statusbar.xml +++ b/chart2/uiconfig/statusbar/statusbar.xml @@ -18,6 +18,6 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . --> - + diff --git a/chart2/uiconfig/ui/attributedialog.ui b/chart2/uiconfig/ui/attributedialog.ui index 65d060f56386..d31d0ded920b 100644 --- a/chart2/uiconfig/ui/attributedialog.ui +++ b/chart2/uiconfig/ui/attributedialog.ui @@ -103,7 +103,7 @@
- reset + reset ok cancel help diff --git a/chart2/uiconfig/ui/chardialog.ui b/chart2/uiconfig/ui/chardialog.ui index 92bc21b8e686..4d0128b685b0 100644 --- a/chart2/uiconfig/ui/chardialog.ui +++ b/chart2/uiconfig/ui/chardialog.ui @@ -103,7 +103,7 @@
- reset + reset ok cancel help diff --git a/chart2/uiconfig/ui/chartcolorpalettepopup.ui b/chart2/uiconfig/ui/chartcolorpalettepopup.ui index 746e3793b3dd..cf40dede6534 100644 --- a/chart2/uiconfig/ui/chartcolorpalettepopup.ui +++ b/chart2/uiconfig/ui/chartcolorpalettepopup.ui @@ -62,6 +62,8 @@ True True in + True + True True @@ -109,6 +111,8 @@ True True in + True + True True diff --git a/chart2/uiconfig/ui/datarangedialog.ui b/chart2/uiconfig/ui/datarangedialog.ui index 82658511a23b..59299d46c5d5 100644 --- a/chart2/uiconfig/ui/datarangedialog.ui +++ b/chart2/uiconfig/ui/datarangedialog.ui @@ -1,36 +1,33 @@ - + - False - 6 + False + 6 Data Ranges False True - 0 - 0 - dialog - - - + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -43,8 +40,8 @@ _Cancel True - True - True + True + True True @@ -57,8 +54,8 @@ _Help True - True - True + True + True True @@ -72,47 +69,23 @@ False True - end + end 0 True - True + True True True True - True + True True - False - - - - - - - - - - - - - - - - - - - - - - - - + False @@ -121,42 +94,18 @@ True - False + False Data Range - False + False True - False - - - - - - - - - - - - - - - - - - - - - - - - + False @@ -168,12 +117,12 @@ True - False + False Data Series 1 - False + False diff --git a/chart2/uiconfig/ui/dlg_InsertDataTable.ui b/chart2/uiconfig/ui/dlg_InsertDataTable.ui index f3358d5cf31f..ab59483063ed 100644 --- a/chart2/uiconfig/ui/dlg_InsertDataTable.ui +++ b/chart2/uiconfig/ui/dlg_InsertDataTable.ui @@ -148,6 +148,7 @@ + Show outline True True diff --git a/chart2/uiconfig/ui/paradialog.ui b/chart2/uiconfig/ui/paradialog.ui index 6f8a98f753ac..946845d0c1a0 100644 --- a/chart2/uiconfig/ui/paradialog.ui +++ b/chart2/uiconfig/ui/paradialog.ui @@ -103,7 +103,7 @@ - reset + reset ok cancel help diff --git a/chart2/uiconfig/ui/sidebaraxis.ui b/chart2/uiconfig/ui/sidebaraxis.ui index f939d4d75bb3..ec67b5534ad2 100644 --- a/chart2/uiconfig/ui/sidebaraxis.ui +++ b/chart2/uiconfig/ui/sidebaraxis.ui @@ -6,6 +6,24 @@ 359 5 + + 0.1 + 1 + + + 1 + 10000 + 1 + 10 + + + 1 + 10 + + + 1 + 10 + True @@ -127,5 +145,191 @@ 0 + + + True + False + 0 + none + + + True + False + 12 + 6 + 6 + 12 + + + + _Automatic + True + True + True + True + + + 0 + 0 + + + + + + Bin _width + True + True + True + True + RB_HISTOGRAM_AUTOMATIC + + + 0 + 1 + + + + + + True + True + 10 + adjustmentHISTOGRAM_BIN_WIDTH + 2 + + + Bin width + Sets the width of each histogram bin. + + + + + 1 + 1 + + + + + + _Number of bins + True + True + True + True + RB_HISTOGRAM_AUTOMATIC + + + 0 + 2 + + + + + + True + True + 10 + adjustmentHISTOGRAM_BIN_COUNT + True + + + Number of bins + Sets the number of bins used by the histogram. + + + + + 1 + 2 + + + + + + _Overflow bin + True + True + True + True + + + 0 + 3 + + + + + + True + True + 10 + adjustmentHISTOGRAM_OVERFLOW + 2 + + + Overflow bin value + Sets the overflow bin value. + + + + + 1 + 3 + + + + + + _Underflow bin + True + True + True + True + + + 0 + 4 + + + + + + True + True + 10 + adjustmentHISTOGRAM_UNDERFLOW + 2 + + + Underflow bin value + Sets the underflow bin value. + + + + + 1 + 4 + + + + + + + + True + False + Bins + 0 + + + + + + + + 0 + 1 + + diff --git a/chart2/uiconfig/ui/sidebarcolors.ui b/chart2/uiconfig/ui/sidebarcolors.ui index 90d6c8e94dcb..db9253e6986d 100644 --- a/chart2/uiconfig/ui/sidebarcolors.ui +++ b/chart2/uiconfig/ui/sidebarcolors.ui @@ -26,7 +26,7 @@ True - Allow to select a color palette to apply to current chart data series. + Allows selecting a color palette to apply to current chart data series. start start True diff --git a/chart2/uiconfig/ui/sidebartype.ui b/chart2/uiconfig/ui/sidebartype.ui index 6379fec63620..1576b88922c9 100644 --- a/chart2/uiconfig/ui/sidebartype.ui +++ b/chart2/uiconfig/ui/sidebartype.ui @@ -298,6 +298,11 @@ 2 + + + Chart Type + + 0 diff --git a/chart2/uiconfig/ui/smoothlinesdlg.ui b/chart2/uiconfig/ui/smoothlinesdlg.ui index f32205d9cf62..3ba985cfa1cf 100644 --- a/chart2/uiconfig/ui/smoothlinesdlg.ui +++ b/chart2/uiconfig/ui/smoothlinesdlg.ui @@ -1,52 +1,49 @@ - + 1 15 3 - 1 - 10 + 1 + 10 1 100 20 - 1 - 10 + 1 + 10 - False - 6 + False + 6 Smooth Lines True - -1 - -1 - dialog - - - + -1 + -1 + dialog - False + False True True vertical 12 - False + False True - end + end _OK True - True - True - True - True + True + True + True + True True @@ -59,8 +56,8 @@ _Cancel True - True - True + True + True True @@ -73,8 +70,8 @@ _Help True - True - True + True + True 6 True @@ -89,14 +86,14 @@ False True - end + end 0 True - False + False True True vertical @@ -104,15 +101,16 @@ True - False + False True 12 True - False + False Line _Type: - True + True + SplineTypeComboBox 0 @@ -124,7 +122,7 @@ True - False + False True 0 @@ -151,49 +149,49 @@ - + True - False - 3 - 6 + False 12 6 + 3 + 6 True - False + False start _Resolution: - True - ResolutionSpinbutton + True + ResolutionSpinbutton - 0 - 0 + 0 + 0 True - False + False start _Degree of polynomials: - True - PolynomialsSpinButton + True + PolynomialsSpinButton - 0 - 1 + 0 + 1 True - True - True - ResolutionAdjustment + True + True True + ResolutionAdjustment Set the resolution. @@ -201,17 +199,17 @@ - 1 - 0 + 1 + 0 True - True - True - PolynomialsAdjustment + True + True True + PolynomialsAdjustment Set the degree of the polynomials. @@ -219,8 +217,8 @@ - 1 - 1 + 1 + 1 diff --git a/chart2/uiconfig/ui/steppedlinesdlg.ui b/chart2/uiconfig/ui/steppedlinesdlg.ui index 0e6d1940cc2b..6e66a2e734ae 100644 --- a/chart2/uiconfig/ui/steppedlinesdlg.ui +++ b/chart2/uiconfig/ui/steppedlinesdlg.ui @@ -1,35 +1,32 @@ - + - False - 6 + False + 6 True - 0 - 0 - dialog - - - + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -42,8 +39,8 @@ _Cancel True - True - True + True + True True @@ -56,8 +53,8 @@ _Help True - True - True + True + True True @@ -71,67 +68,67 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 3 - 6 + False 12 6 + 3 + 6 True - False - chart2/res/step_center_x_30.png + False + chart2/res/step_center_x_30.png - 0 - 2 + 0 + 2 True - False - chart2/res/step_end_30.png + False + chart2/res/step_end_30.png - 0 - 1 + 0 + 1 True - False - chart2/res/step_center_y_30.png + False + chart2/res/step_center_y_30.png - 0 - 3 + 0 + 3 _Start with horizontal line True - True - False - True + True + False + True True - True + True Start with horizontal line and step up vertically at the end. @@ -139,18 +136,18 @@ - 1 - 0 + 1 + 0 Step at the _horizontal mean True - True - False - True - True + True + False + True + True step_start_rb @@ -159,18 +156,18 @@ - 1 - 2 + 1 + 2 _End with horizontal line True - True - False - True - True + True + False + True + True step_start_rb @@ -179,18 +176,18 @@ - 1 - 1 + 1 + 1 Step to the _vertical mean True - True - False - True - True + True + False + True + True step_start_rb @@ -199,19 +196,19 @@ - 1 - 3 + 1 + 3 True - False - chart2/res/step_start_30.png + False + chart2/res/step_start_30.png - 0 - 0 + 0 + 0 @@ -219,7 +216,7 @@ True - False + False Type of Stepping diff --git a/chart2/uiconfig/ui/titlerotationtabpage.ui b/chart2/uiconfig/ui/titlerotationtabpage.ui index 042b72e1c67b..f8a2f741e127 100644 --- a/chart2/uiconfig/ui/titlerotationtabpage.ui +++ b/chart2/uiconfig/ui/titlerotationtabpage.ui @@ -1,43 +1,43 @@ - + 359 - 5 + 5 True - False + False True - 6 - 0 - none + 6 + 0 + none - + True - False - True - 6 - 12 + False 12 6 + True + 6 + 12 - + True - False - 6 - 12 + False + 6 + 12 True - True - 40 + True + 40 + True adjustmentSpinDegrees True - True Allows you to manually enter the orientation angle. @@ -45,21 +45,21 @@ - 0 - 2 + 0 + 2 True - False - 40 + False + 40 _Degrees - True + True - 1 - 2 + 1 + 2 @@ -76,26 +76,26 @@ - 1 - 0 + 1 + 0 - + True - False - 6 - 12 + False + 6 + 12 Ve_rtically stacked True - True - False - True + True + False + True True - True + True Assigns vertical text orientation for cell contents. @@ -103,42 +103,42 @@ - 0 - 0 + 0 + 0 - False + False ABCD - 0 - 1 + 0 + 1 - 2 - 0 + 2 + 0 True - False + False Te_xt direction: - True + True - 0 - 1 + 0 + 1 True - False + False Specify the text direction for a paragraph that uses complex text layout (CTL). This feature is only available if complex text layout support is enabled. @@ -146,15 +146,15 @@ - 1 - 1 + 1 + 1 2 True - False + False GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK center center @@ -165,8 +165,8 @@ - 0 - 0 + 0 + 0 @@ -174,7 +174,7 @@ True - False + False Text Orientation diff --git a/chart2/uiconfig/ui/tp_AxisPositions.ui b/chart2/uiconfig/ui/tp_AxisPositions.ui index e6de6bad58c3..d78141d7e826 100644 --- a/chart2/uiconfig/ui/tp_AxisPositions.ui +++ b/chart2/uiconfig/ui/tp_AxisPositions.ui @@ -1,49 +1,49 @@ - + 100 - 1 - 10 + 1 + 10 100 - 1 - 10 + 1 + 10 True - False - 6 + False + 6 vertical 6 True - False - 0 - none + False + 0 + none True - False - vertical - 6 + False 12 6 + vertical + 6 True - False + False 12 True - False + False _Cross other axis at - True - LB_CROSSES_OTHER_AXIS_AT + True + LB_CROSSES_OTHER_AXIS_AT 0 @@ -55,7 +55,7 @@ True - False + False Start End @@ -77,10 +77,10 @@ True - True - True - adjustment1 + True + True True + adjustment1 Enter the value where the axis line should cross the other axis. @@ -96,13 +96,13 @@ True - False - True + False + True - True + True + True True - True @@ -127,10 +127,10 @@ Axis _between categories - True - False - True - True + True + False + True + True False @@ -143,7 +143,7 @@ True - False + False Axis Line 0 @@ -161,26 +161,26 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 + False 12 6 + 6 _On tick marks - True True - True - False - True - True + True + False + True + True + True Specifies that the axis is positioned on the first/last tickmarks. This makes the data points visual representation begin/end at the value axis. @@ -188,18 +188,18 @@ - 0 - 0 + 0 + 0 _Between tick marks True - True - False - True - True + True + False + True + True RB_ON @@ -208,8 +208,8 @@ - 0 - 1 + 0 + 1 @@ -217,7 +217,7 @@ True - False + False Position Axis 0 @@ -235,29 +235,29 @@ True - False - 0 - none + False + 0 + none True - False - vertical - 6 + False 12 6 + vertical + 6 True - False + False 12 True - False + False _Place labels - True - LB_PLACE_LABELS + True + LB_PLACE_LABELS 0 @@ -269,7 +269,7 @@ True - False + False Near axis Near axis (other side) @@ -298,14 +298,14 @@ True - False + False 12 - False + False _Distance - True - EDT_AXIS_LABEL_DISTANCE + True + EDT_AXIS_LABEL_DISTANCE 0 @@ -316,8 +316,8 @@ - True - True + True + True True adjustment2 @@ -339,7 +339,7 @@ True - False + False Labels 0 @@ -357,28 +357,28 @@ True - False - 0 - none + False + 0 + none True - False - vertical - 6 + False 12 6 + vertical + 6 - + True - False - 6 - 12 + False + 6 + 12 True - False + False Major: 0 @@ -387,14 +387,14 @@ - 0 - 0 + 0 + 0 True - False + False Minor: 0 @@ -403,18 +403,18 @@ - 0 - 1 + 0 + 1 _Inner True - True - False - True - True + True + False + True + True @@ -425,18 +425,18 @@ - 1 - 0 + 1 + 0 _Outer True - True - False - True - True + True + False + True + True @@ -447,18 +447,18 @@ - 2 - 0 + 2 + 0 I_nner True - True - False - True - True + True + False + True + True @@ -469,18 +469,18 @@ - 1 - 1 + 1 + 1 O_uter True - True - False - True - True + True + False + True + True @@ -491,8 +491,8 @@ - 2 - 1 + 2 + 1 @@ -505,15 +505,15 @@ True - False + False 12 True - False + False Place _marks - True - LB_PLACE_TICKS + True + LB_PLACE_TICKS 0 @@ -525,7 +525,7 @@ True - False + False At labels At axis @@ -555,7 +555,7 @@ True - False + False Interval Marks 0 @@ -572,70 +572,70 @@ - False - 0 - none + False + 0 + none - + True - False - 12 - 6 + False 12 6 + 12 + 6 Show major _grid True - True - False - True - True + True + False + True + True - 0 - 0 + 0 + 0 _Show minor grid True - True - False - True - True + True + False + True + True - 0 - 1 + 0 + 1 Mo_re... True - True - True - True + True + True + True - 1 - 0 + 1 + 0 Mor_e... True - True - True - True + True + True + True - 1 - 1 + 1 + 1 @@ -643,7 +643,7 @@ True - False + False Grids 0 diff --git a/chart2/uiconfig/ui/tp_ChartColorPalette.ui b/chart2/uiconfig/ui/tp_ChartColorPalette.ui index 093b155a9a14..3fea01279fca 100644 --- a/chart2/uiconfig/ui/tp_ChartColorPalette.ui +++ b/chart2/uiconfig/ui/tp_ChartColorPalette.ui @@ -23,6 +23,7 @@ False 4 4 + True 16 @@ -31,20 +32,21 @@ 4 4 3 + True 0 none True True - start + True in + True True True 0 - True True liststore1 0 @@ -83,20 +85,21 @@ 4 4 3 + True 0 none True True - start + True in + True True True 0 - True True liststore2 0 diff --git a/chart2/uiconfig/ui/tp_DataSource.ui b/chart2/uiconfig/ui/tp_DataSource.ui index c0132ba52be8..3794fb73f5a7 100644 --- a/chart2/uiconfig/ui/tp_DataSource.ui +++ b/chart2/uiconfig/ui/tp_DataSource.ui @@ -1,28 +1,28 @@ - + True - False + False go-up True - False + False go-down True - False - Select data range - chart2/res/selectrange.png + False + Select data range + chart2/res/selectrange.png True - False - Select data range - chart2/res/selectrange.png + False + Select data range + chart2/res/selectrange.png @@ -42,62 +42,62 @@ - + True - False + False True True - 6 - 6 + 6 + 6 - + True - False + False True True - 12 + 12 - + True - False + False True vertical - 6 + 6 True - False + False Data _series: - True - LB_SERIES + True + LB_SERIES 0 - 0 - 0 + 0 + 0 True - False + False True True - in + in True - True + True True True liststore1 - False - False - 0 - False + False + False + 0 + False @@ -120,26 +120,26 @@ - 0 - 1 + 0 + 1 - + True - False + False True - 6 - 12 + 6 + 12 _Add True - True - True + True + True True - True + True Adds a new entry below the current entry in the Data Series list. If an entry is selected, the new data series gets the same chart type. @@ -147,17 +147,17 @@ - 0 - 0 + 0 + 0 True - True - True + True + True image1 - True + True Up @@ -166,18 +166,18 @@ - 1 - 0 + 1 + 0 _Remove True - True - True + True + True True - True + True Removes the selected entry from the Data Series list. @@ -185,17 +185,17 @@ - 0 - 1 + 0 + 1 True - True - True + True + True image2 - True + True Down @@ -204,71 +204,71 @@ - 1 - 1 + 1 + 1 - 0 - 2 + 0 + 2 - 0 - 0 + 0 + 0 True - False + False True True - + True - False + False start True True vertical - 6 + 6 True - False + False _Data ranges: - True - LB_ROLE + True + LB_ROLE 0 - 0 - 0 + 0 + 0 True - True + True True True - in + in True - True + True True True liststore2 - False - False - 0 - False + False + False + 0 + False @@ -301,37 +301,37 @@ - 0 - 1 + 0 + 1 True - False + False Ran_ge for %VALUETYPE - True - EDT_RANGE + True + EDT_RANGE 0 - 0 - 2 + 0 + 2 - + True - False + False True - 6 + 6 True - True + True True - True + True True @@ -340,15 +340,15 @@ - 0 - 0 + 0 + 0 True - True - True + True + True imageIMB_RANGE_MAIN True @@ -358,69 +358,69 @@ - 1 - 0 + 1 + 0 - 0 - 3 + 0 + 3 - + True - False + False vertical True - False + False _Categories - True - EDT_CATEGORIES + True + EDT_CATEGORIES 0 - 0 - 0 + 0 + 0 True - False + False Data _labels - True - EDT_CATEGORIES + True + EDT_CATEGORIES 0 - 0 - 1 + 0 + 1 - 0 - 4 + 0 + 4 - + True - False + False True - 6 + 6 True - True + True True - True + True True @@ -429,15 +429,15 @@ - 0 - 0 + 0 + 0 True - True - True + True + True imageIMB_RANGE_CAT True @@ -447,38 +447,38 @@ - 1 - 0 + 1 + 0 - 0 - 5 + 0 + 5 - 0 - 0 + 0 + 0 - 1 - 0 + 1 + 0 - 0 - 0 + 0 + 0 True - False + False Customize Data Ranges for Individual Data Series 0 @@ -486,8 +486,8 @@ - 0 - 1 + 0 + 1 diff --git a/chart2/uiconfig/ui/tp_DataTable.ui b/chart2/uiconfig/ui/tp_DataTable.ui index c405827799a8..f7171a561df5 100644 --- a/chart2/uiconfig/ui/tp_DataTable.ui +++ b/chart2/uiconfig/ui/tp_DataTable.ui @@ -62,6 +62,7 @@ + Show outline True True diff --git a/chart2/uiconfig/ui/tp_LegendPosition.ui b/chart2/uiconfig/ui/tp_LegendPosition.ui index 713528564bc4..30dad054cc0e 100644 --- a/chart2/uiconfig/ui/tp_LegendPosition.ui +++ b/chart2/uiconfig/ui/tp_LegendPosition.ui @@ -1,36 +1,36 @@ - + True - False - 6 + False + 6 vertical 12 True - False - 0 - none + False + 0 + none - + True - False - 6 + False 12 6 + 6 _Left - True True - True - False - True - True + True + False + True + True + True Positions the legend at the left of the chart. @@ -38,18 +38,18 @@ - 0 - 0 + 0 + 0 _Right True - True - False - True - True + True + False + True + True left @@ -58,18 +58,18 @@ - 0 - 1 + 0 + 1 _Top True - True - False - True - True + True + False + True + True left @@ -78,18 +78,18 @@ - 0 - 2 + 0 + 2 _Bottom True - True - False - True - True + True + False + True + True left @@ -98,8 +98,8 @@ - 0 - 3 + 0 + 3 @@ -107,7 +107,7 @@ True - False + False Position 0 @@ -125,22 +125,22 @@ True - False - 0 - none + False + 0 + none True - False - 12 + False 12 6 + 12 True - False + False Te_xt direction - True + True 0 @@ -152,7 +152,7 @@ True - False + False Specify the text direction for a paragraph that uses complex text layout (CTL). This feature is only available if complex text layout support is enabled. @@ -170,7 +170,7 @@ True - False + False Text Orientation 0 @@ -188,24 +188,24 @@ True - False - 0 - none + False + 0 + none True - False - 12 + False 12 6 + 12 Show the legend without overlapping the chart True - False - False - True - True + False + False + True + True Specifies whether the legend should overlap the chart. @@ -223,7 +223,7 @@ True - False + False Overlay 0 diff --git a/chart2/uiconfig/ui/tp_RangeChooser.ui b/chart2/uiconfig/ui/tp_RangeChooser.ui index e301b456c16f..94e35b9bed5d 100644 --- a/chart2/uiconfig/ui/tp_RangeChooser.ui +++ b/chart2/uiconfig/ui/tp_RangeChooser.ui @@ -1,30 +1,30 @@ - + True - False - Select data range - chart2/res/selectrange.png + False + Select data range + chart2/res/selectrange.png True - False + False True - 6 + 6 - + True - False + False True - 6 + 6 True - False + False Choose a Data Range 0 @@ -32,37 +32,37 @@ - 0 - 0 + 0 + 0 - + True - False + False True - 6 + 6 True - False + False _Data range: - True - ED_RANGE + True + ED_RANGE 0 - 0 - 0 + 0 + 0 True - True + True True - True + True True @@ -71,16 +71,16 @@ - 1 - 0 + 1 + 0 True - True - True - Select data range + True + True + Select data range imageIB_RANGE True @@ -90,25 +90,37 @@ - 2 - 0 + 2 + 0 + + + + + False + True + 0 + + + 1 + 1 + 2 - 0 - 1 + 0 + 1 Data series in _rows True - True - False - True + True + False + True True - True + True Data series get their data from consecutive rows in the selected range. For scatter charts, the first data series will contain x-values for all series. All other data series are used as y-values, one for each series. @@ -116,18 +128,18 @@ - 0 - 2 + 0 + 2 Data series in _columns True - True - False - True - True + True + False + True + True RB_DATAROWS @@ -136,18 +148,18 @@ - 0 - 3 + 0 + 3 _First row as label True - True - False - True - True + True + False + True + True For data series in columns: The first row in the range is used as names for data series. For data series in rows: The first row in the range is used as categories. The remaining rows comprise the data series. If this check box is not selected, all rows are data series. @@ -155,18 +167,18 @@ - 0 - 4 + 0 + 4 F_irst column as label True - True - False - True - True + True + False + True + True For data series in columns: The first column in the range is used as names for data series. For data series in rows: The first column in the range is used as categories. The remaining columns comprise the data columns. If this check box is not selected, all columns are data columns. @@ -174,115 +186,115 @@ - 0 - 5 + 0 + 5 True - False + False - 0 - 6 + 0 + 6 Time based charting True - True - False - True - True + True + False + True + True - 0 - 7 + 0 + 7 - + True - False - 12 + False + 12 True - True - True - 5 + True + True + 5 0 True - number + number - 1 - 0 + 1 + 0 True - True - True - 5 - True + True + True + 5 0 + True - 3 - 0 + 3 + 0 True - False + False Start Table Index - True - ED_TIME_BASED_START + True + ED_TIME_BASED_START - 0 - 0 + 0 + 0 True - False + False End Table Index - True - ED_TIME_BASED_END + True + ED_TIME_BASED_END - 2 - 0 + 2 + 0 - 0 - 8 + 0 + 8 - False + False Data Range - 0 - 9 + 0 + 9 - 0 - 0 + 0 + 0 diff --git a/chart2/uiconfig/ui/tp_Scale.ui b/chart2/uiconfig/ui/tp_Scale.ui index 3edf90eca38b..5c6e8366d86a 100644 --- a/chart2/uiconfig/ui/tp_Scale.ui +++ b/chart2/uiconfig/ui/tp_Scale.ui @@ -1,63 +1,81 @@ - + - 1 - 10 + 1 + 10 - 1 - 10 + 1 + 10 - 1 - 10 + 1 + 10 - 1 - 10 + 1 + 10 1 100 - 1 - 10 + 1 + 10 1 100 + 1 + 10 + + + 0.1 + 1 + + + 1 + 10000 + 1 + 10 + + + 1 + 10 + + 1 10 True - False - 6 - 0 - none + False + 6 + 0 + none True - False - vertical - 6 + False 12 6 + vertical + 6 True - False + False vertical 6 _Reverse direction True - True - False - True - True + True + False + True + True Defines where the lower and where the higher values are displayed at the axis. The unchecked state is the mathematical direction. @@ -74,10 +92,10 @@ _Logarithmic scale True - True - False - True - True + True + False + True + True Specifies that you want the axis to be subdivided logarithmically. @@ -93,15 +111,15 @@ True - False + False 12 True - False + False T_ype - True - LB_AXIS_TYPE + True + LB_AXIS_TYPE 0 @@ -113,7 +131,7 @@ True - False + False Automatic Text @@ -146,76 +164,76 @@ - + True - False - 6 - 12 + False + 6 + 12 True - False + False _Minimum - True - EDT_MIN + True + EDT_MIN 0 - 0 - 0 + 0 + 0 True - False + False Ma_ximum - True - EDT_MAX + True + EDT_MAX 0 - 0 - 1 + 0 + 1 _Automatic True - True - False - True - True + True + False + True + True - 2 - 0 + 2 + 0 A_utomatic True - True - False - True - True + True + False + True + True - 2 - 1 + 2 + 1 True - True - True - 10 - adjustment1 + True + True + 10 True + adjustment1 Defines the minimum value for the beginning of the axis. @@ -223,18 +241,18 @@ - 1 - 0 + 1 + 0 True - True - True - 10 - adjustment2 + True + True + 10 True + adjustment2 Defines the maximum value for the end of the axis. @@ -242,8 +260,8 @@ - 1 - 1 + 1 + 1 @@ -256,15 +274,15 @@ True - False + False 12 True - False + False R_esolution - True - LB_TIME_RESOLUTION + True + LB_TIME_RESOLUTION 0 @@ -276,7 +294,7 @@ True - False + False Days Months @@ -298,10 +316,10 @@ Automat_ic True - True - False - True - True + True + False + True + True False @@ -319,14 +337,14 @@ True - False + False 12 True - False + False Ma_jor interval - True + True 0 @@ -338,21 +356,21 @@ True - False + False vertical True - False + False 12 True - True - True - 10 - adjustmentINTERVAL + True + True + 10 True + adjustmentINTERVAL Major interval can be set to show a certain number of days, months, or years. @@ -368,7 +386,7 @@ True - False + False Days Months @@ -396,11 +414,11 @@ True - True - True - 10 - adjustment4 + True + True + 10 True + adjustment4 Defines the interval for the main division of the axes. @@ -424,10 +442,10 @@ Au_tomatic True - True - False - True - True + True + False + True + True False @@ -445,19 +463,19 @@ True - False + False 12 True - False + False vertical True - False + False Minor inter_val - True + True 0 @@ -469,9 +487,9 @@ True - False + False Minor inter_val count - True + True 0 @@ -490,11 +508,11 @@ True - True - True - 10 - adjustmentINTERVAL1 + True + True + 10 True + adjustmentINTERVAL1 Defines the interval for the subdivision of the axes. @@ -510,7 +528,7 @@ True - False + False Days Months @@ -532,10 +550,10 @@ Aut_omatic True - True - False - True - True + True + False + True + True False @@ -551,16 +569,203 @@ - + True False + 0 + none + + + True + False + 12 + 6 + 6 + 12 + + + + Auto_matic + True + True + True + True + + + 0 + 0 + + + + + + Bin _width + True + True + True + True + RB_HISTOGRAM_AUTOMATIC + + + 0 + 1 + + + + + + True + True + 10 + adjustmentHISTOGRAM_BIN_WIDTH + 2 + + + Bin width + Sets the width of each histogram bin. + + + + + 1 + 1 + + + + + + _Number of bins + True + True + True + True + RB_HISTOGRAM_AUTOMATIC + + + 0 + 2 + + + + + + True + True + 10 + adjustmentHISTOGRAM_BIN_COUNT + True + + + Number of bins + Sets the number of bins used by the histogram. + + + + + 1 + 2 + + + + + + _Overflow bin + True + True + True + True + + + 0 + 3 + + + + + + True + True + 10 + adjustmentHISTOGRAM_OVERFLOW + 2 + + + Overflow bin value + Sets the overflow bin value. + + + + + 1 + 3 + + + + + + _Underflow bin + True + True + True + True + + + 0 + 4 + + + + + + True + True + 10 + adjustmentHISTOGRAM_UNDERFLOW + 2 + + + Underflow bin value + Sets the underflow bin value. + + + + + 1 + 4 + + + + + + + + True + False + Bins + 0 + + + + + + + + False + True + 5 + + + + + True + False 12 True - False + False Re_ference value - True + True 0 @@ -572,11 +777,11 @@ True - True - True - 10 - adjustment3 + True + True + 10 True + adjustment3 Specifies at which position to display the values along the axis. @@ -593,10 +798,10 @@ Automat_ic True - True - False - True - True + True + False + True + True You must first deselect the Automatic option in order to modify the values. @@ -613,7 +818,7 @@ False True - 5 + 6 @@ -621,7 +826,7 @@ True - False + False Scale 0 diff --git a/chart2/uiconfig/ui/tp_axisLabel.ui b/chart2/uiconfig/ui/tp_axisLabel.ui index 656856aa2eeb..eff055e8cbb3 100644 --- a/chart2/uiconfig/ui/tp_axisLabel.ui +++ b/chart2/uiconfig/ui/tp_axisLabel.ui @@ -1,28 +1,28 @@ - + 359 - 5 + 5 True - False + False True True - 6 + 6 vertical 12 Sho_w labels True - True - False - True + True + False + True True - True + True Specifies whether to show or hide the axis labels. @@ -38,34 +38,34 @@ True - False + False 18 True True - False - 0 - none + False + 0 + none True - False - vertical - 6 - True - True + False 12 6 + True + True + vertical + 6 _Tile True - True - False - True + True + False + True True - True + True Arranges numbers on the axis side by side. @@ -82,10 +82,10 @@ St_agger odd True - True - False - True - True + True + False + True + True tile @@ -103,10 +103,10 @@ Stagger _even True - True - False - True - True + True + False + True + True tile @@ -124,10 +124,10 @@ A_utomatic True - True - False - True - True + True + False + True + True tile @@ -146,7 +146,7 @@ True - False + False Order @@ -163,27 +163,27 @@ True - False - 0 - none + False + 0 + none True - False - vertical - 6 - True - True + False 12 6 + True + True + vertical + 6 O_verlap True - True - False - True - True + True + False + True + True Specifies that the text in cells may overlap other cells. @@ -200,10 +200,10 @@ _Break True - True - False - True - True + True + False + True + True Allows a text break. @@ -221,7 +221,7 @@ True - False + False Text Flow @@ -245,37 +245,37 @@ True - False + False True - 6 - 0 - none + 6 + 0 + none - + True - False - True - 6 - 12 + False 12 6 + True + 6 + 12 - + True - False - 6 - 12 + False + 6 + 12 True - True - 40 - True + True + 40 + True + True adjustmentSpinDegrees True - True Allows you to manually enter the orientation angle. @@ -283,21 +283,21 @@ - 0 - 2 + 0 + 2 True - False - 40 + False + 40 _Degrees - True + True - 1 - 2 + 1 + 2 @@ -314,26 +314,26 @@ - 1 - 0 + 1 + 0 - + True - False - 6 - 12 + False + 6 + 12 Ve_rtically stacked True - True - False - True + True + False + True True - True + True Assigns vertical text orientation for cell contents. @@ -341,42 +341,42 @@ - 0 - 0 + 0 + 0 - False + False ABCD - 0 - 1 + 0 + 1 - 2 - 0 + 2 + 0 True - False + False Te_xt direction: - True + True - 0 - 1 + 0 + 1 True - False + False Specify the text direction for a paragraph that uses complex text layout (CTL). This feature is only available if complex text layout support is enabled. @@ -384,15 +384,15 @@ - 1 - 1 + 1 + 1 2 True - False + False GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK center center @@ -403,8 +403,8 @@ - 0 - 0 + 0 + 0 @@ -412,7 +412,7 @@ True - False + False Text Orientation diff --git a/cli_ure/source/basetypes/uno/PolymorphicType.cs b/cli_ure/source/basetypes/uno/PolymorphicType.cs index 4dbea1bbbfc6..b366a5fb30d1 100644 --- a/cli_ure/source/basetypes/uno/PolymorphicType.cs +++ b/cli_ure/source/basetypes/uno/PolymorphicType.cs @@ -28,14 +28,14 @@ namespace uno { /** represents a polymorphic type. This class is used to carry type information for polymorphic struct types - and arrays of polymorphic struct types. These types would be easiest represented + and arrays of polymorphic struct types. These types would be most easily represented with type templates, which are not available in .NET 1.1. Therefore the System.Type cannot contain information about template parameters. To retain this information we use PolymorphicType which directly inherits from System.Type. The additional information about type parameters are passed - as simple string when creating an instance of PolymorphicType. Usually one + as a simple string when creating an instance of PolymorphicType. Usually one only needs a PolymorphicType when a polymorphic type is put into an - uno.Any. For example, let's assume there is a idl type PolyStruct: + uno.Any. For example, let's assume there is an idl type PolyStruct: module test { struct PolyStruct< T > @@ -62,7 +62,7 @@ namespace uno { for each distinct name. For example, if GetType is called multiple times with the name "unoidl.test.PolyStruct" then the same instance of PolymorphicType is returned. This makes it possible to compare the instances - by reference, thas is using the operator "==". + by reference, that is using the operator "==". The polymorphic name, which is passed as second argument to PolymorphicType.GetType, contains a list of type names. Only type names common @@ -90,7 +90,7 @@ public class PolymorphicType: Type /** provides a unique instance of this class. - This function returns null if the specified type is no polymorphic struct. + This function returns null if the specified type is not a polymorphic struct. @param type the type of the polymorphic struct. For example, created by @@ -98,7 +98,7 @@ public class PolymorphicType: Type @param name the full name of the struct (including the type list). @return - null - the argument type is no valid polymorphic struct or
+ null - the argument type is not a valid polymorphic struct or
an instance of this class. @exception System.ArgumentNullException The argument was null. diff --git a/cli_ure/source/uno_bridge/README.txt b/cli_ure/source/uno_bridge/README.txt index 39b3ce3648fe..85a74e4659f2 100644 --- a/cli_ure/source/uno_bridge/README.txt +++ b/cli_ure/source/uno_bridge/README.txt @@ -1,5 +1,5 @@ Because of the LoaderLock bug in .NET Framework 1.0 and 1.1 the cli_uno.dll is linked -with the /NOENTRY switch, which prevent that the C-runtime is initialized when loading +with the /NOENTRY switch, which prevents the C-runtime from being initialized when loading the dll. Also I removed all static c++ objects which need construction by the CRT, @@ -11,10 +11,10 @@ this had to be called. If we would do that we would have to implement that the bridge can be disposed. -Sell also: +See also: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vcconmixeddllloadingproblem.asp http://support.microsoft.com/?id=814472 http://www.ddj.com/dept/windows/184416689 http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx -http://msdn2.microsoft.com/en-US/library/ms172219.aspx \ No newline at end of file +http://msdn2.microsoft.com/en-US/library/ms172219.aspx diff --git a/cli_ure/source/uno_bridge/cli_bridge.h b/cli_ure/source/uno_bridge/cli_bridge.h index 95ddb03943d4..8a0a7d35e810 100644 --- a/cli_ure/source/uno_bridge/cli_bridge.h +++ b/cli_ure/source/uno_bridge/cli_bridge.h @@ -44,14 +44,14 @@ struct Mapping : public uno_Mapping }; // The environment will be created in uno_initEnvironment. See also the remarks there -//Managed cli environment for cli objects a UNO proxies (which are cli -//objects. The uno_Environment is not used for cli objects. +//Managed cli environment for cli objects and UNO proxies (which are cli +//objects). The uno_Environment is not used for cli objects. ref struct CliEnvHolder { static Cli_environment ^ g_cli_env = nullptr; }; -/** An instance of Bridge represents exactly one mapping therefore either +/** An instance of Bridge represents exactly one mapping, therefore either m_cli2uno or m_uno2cli is valid. */ struct Bridge diff --git a/cli_ure/source/uno_bridge/cli_environment.h b/cli_ure/source/uno_bridge/cli_environment.h index 3828d971c503..937c6bdbd991 100644 --- a/cli_ure/source/uno_bridge/cli_environment.h +++ b/cli_ure/source/uno_bridge/cli_environment.h @@ -59,7 +59,7 @@ public: /** Registers a UNO object as being mapped by this bridge. The resulting - cli object is represents all interfaces of the UNO object. Therefore the + cli object represents all interfaces of the UNO object. Therefore the object can be registered only with its OID; a type is not necessary. */ Object ^ registerInterface(Object ^ obj, System::String ^ oid); diff --git a/cli_ure/source/uno_bridge/cli_proxy.h b/cli_ure/source/uno_bridge/cli_proxy.h index 25f7d2801314..df980a848faa 100644 --- a/cli_ure/source/uno_bridge/cli_proxy.h +++ b/cli_ure/source/uno_bridge/cli_proxy.h @@ -68,7 +68,7 @@ public ref class UnoInterfaceProxy: public srrp::RealProxy, to the number of elements in m_listIfaces. */ int m_numUnoIfaces; - /** The list is filled with additional UnoInterfaceProxy object due + /** The list is filled with additional UnoInterfaceProxy objects due to aggregation via bridges. Though the latter is strongly discouraged, this has to be supported. */ @@ -242,7 +242,7 @@ struct CliProxy: public uno_Interface typelib_TypeDescription const * TD, OUString const & usOid ); - /** Prepares an array (m_arMethoInfos) containing MethodInfo object of the + /** Prepares an array (m_arMethodInfos) containing MethodInfo objects of the interface and all inherited interfaces. At index null is the first method of the base interface and at the last position is the last method of the furthest derived interface. @@ -256,7 +256,7 @@ struct CliProxy: public uno_Interface /**Obtains a MethodInfo which can be used to invoke the cli object. Internally it maps nUnoFunctionPos to an index that is used to get the - corresponding MethodInfo object from m_arMethoInfos. The mapping table + corresponding MethodInfo object from m_arMethodInfos. The mapping table is dynamically initialized. If the cli interface has no base interface or exactly one then the mapping table is initialized in one go at the first call. In all ensuing calls the MethodInfo object is immediately diff --git a/codemaker/source/cppumaker/cpputype.cxx b/codemaker/source/cppumaker/cpputype.cxx index afe3c0b14de4..152dbf476955 100644 --- a/codemaker/source/cppumaker/cpputype.cxx +++ b/codemaker/source/cppumaker/cpputype.cxx @@ -184,7 +184,7 @@ public: virtual void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) = 0; - OUString dumpHeaderDefine(FileStream& o, std::u16string_view extension) const; + static void dumpPragmaOnce(FileStream& o); void dumpGetCppuType(FileStream & out); @@ -477,14 +477,9 @@ void CppuType::dumpDependedTypes( } } -OUString CppuType::dumpHeaderDefine( - FileStream & out, std::u16string_view extension) const +void CppuType::dumpPragmaOnce(FileStream & out) { - OUString def( - "INCLUDED_" + name_.replace('.', '_').toAsciiUpperCase() + "_" - + extension); - out << "#ifndef " << def << "\n#define " << def << "\n"; - return def; + out << "#pragma once\n"; } void CppuType::addDefaultHIncludes(codemaker::cppumaker::Includes & includes) @@ -563,7 +558,7 @@ void CppuType::dumpHFileContent( FileStream & out, codemaker::cppumaker::Includes & includes) { addDefaultHIncludes(includes); - dumpHeaderDefine(out, u"HDL"); + dumpPragmaOnce(out); out << "\n"; includes.dump(out, nullptr, false); // 'exceptions = false' would be wrong for services/singletons, but @@ -591,7 +586,7 @@ void CppuType::dumpHFileContent( out << "SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL getCppuType("; dumpType(out, name_, true); dumpTemplateParameters(out); - out << " *);\n\n#endif\n"; + out << " *);\n\n"; } void CppuType::dumpGetCppuType(FileStream & out) @@ -1192,7 +1187,7 @@ void InterfaceType::dumpDeclaration(FileStream & out) void InterfaceType::dumpHppFile( FileStream & out, codemaker::cppumaker::Includes & includes) { - OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + dumpPragmaOnce(out); out << "\n"; addDefaultHxxIncludes(includes); includes.dump(out, &name_, !(m_cppuTypeLeak || m_cppuTypeDynamic)); @@ -1214,7 +1209,7 @@ void InterfaceType::dumpHppFile( } out << "template<> struct IsUnoInterfaceType<"; dumpType(out, name_, false, false, true); - out << ">: ::std::true_type {};\n}\n#endif\n\n#endif // "<< headerDefine << "\n"; + out << ">: ::std::true_type {};\n}\n#endif\n\n"; } void InterfaceType::dumpAttributes(FileStream & out) const @@ -1669,7 +1664,7 @@ private: void ConstantGroup::dumpHdlFile( FileStream & out, codemaker::cppumaker::Includes & includes) { - OUString headerDefine(dumpHeaderDefine(out, u"HDL")); + dumpPragmaOnce(out); out << "\n"; addDefaultHIncludes(includes); includes.dump(out, nullptr, true); @@ -1683,16 +1678,14 @@ void ConstantGroup::dumpHdlFile( if (codemaker::cppumaker::dumpNamespaceClose(out, name_, true)) { out << "\n"; } - out << "\n#endif // "<< headerDefine << "\n"; } void ConstantGroup::dumpHppFile( FileStream & out, codemaker::cppumaker::Includes &) { - OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + dumpPragmaOnce(out); out << "\n"; codemaker::cppumaker::Includes::dumpInclude(out, u2b(name_), false); - out << "\n#endif // "<< headerDefine << "\n"; } void ConstantGroup::dumpDeclaration(FileStream & out) @@ -1889,7 +1882,7 @@ void PlainStructType::dumpDeclaration(FileStream & out) void PlainStructType::dumpHppFile( FileStream & out, codemaker::cppumaker::Includes & includes) { - OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + dumpPragmaOnce(out); out << "\n"; includes.dump(out, &name_, true); out << "\n"; @@ -1974,7 +1967,6 @@ void PlainStructType::dumpHppFile( } out << "\n"; dumpGetCppuType(out); - out << "\n#endif // "<< headerDefine << "\n"; } void PlainStructType::dumpLightGetCppuType(FileStream & out) @@ -2283,7 +2275,7 @@ void PolyStructType::dumpDeclaration(FileStream & out) void PolyStructType::dumpHppFile( FileStream & out, codemaker::cppumaker::Includes & includes) { - OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + dumpPragmaOnce(out); out << "\n"; includes.dump(out, &name_, true); out << "\n"; @@ -2413,7 +2405,6 @@ void PolyStructType::dumpHppFile( } out << "\n"; dumpGetCppuType(out); - out << "\n#endif // "<< headerDefine << "\n"; } void PolyStructType::dumpLightGetCppuType(FileStream & out) @@ -2834,7 +2825,7 @@ void ExceptionType::addComprehensiveGetCppuTypeIncludes( void ExceptionType::dumpHppFile( FileStream & out, codemaker::cppumaker::Includes & includes) { - OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + dumpPragmaOnce(out); out << "\n"; addDefaultHxxIncludes(includes); includes.dump(out, &name_, true); @@ -3007,7 +2998,6 @@ void ExceptionType::dumpHppFile( out << "\n"; dumpGetCppuType(out); - out << "\n#endif // "<< headerDefine << "\n"; } void ExceptionType::dumpLightGetCppuType(FileStream & out) @@ -3349,7 +3339,7 @@ void EnumType::dumpDeclaration(FileStream& o) void EnumType::dumpHppFile( FileStream& o, codemaker::cppumaker::Includes & includes) { - OUString headerDefine(dumpHeaderDefine(o, u"HPP")); + dumpPragmaOnce(o); o << "\n"; addDefaultHxxIncludes(includes); @@ -3357,8 +3347,6 @@ void EnumType::dumpHppFile( o << "\n"; dumpGetCppuType(o); - - o << "\n#endif // "<< headerDefine << "\n"; } void EnumType::dumpNormalGetCppuType(FileStream& o) @@ -3483,7 +3471,7 @@ private: void Typedef::dumpHdlFile( FileStream& o, codemaker::cppumaker::Includes & includes) { - OUString headerDefine(dumpHeaderDefine(o, u"HDL")); + dumpPragmaOnce(o); o << "\n"; addDefaultHIncludes(includes); @@ -3499,8 +3487,6 @@ void Typedef::dumpHdlFile( if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) { o << "\n"; } - - o << "#endif // "<< headerDefine << "\n"; } void Typedef::dumpDeclaration(FileStream& o) @@ -3513,14 +3499,12 @@ void Typedef::dumpDeclaration(FileStream& o) void Typedef::dumpHppFile( FileStream& o, codemaker::cppumaker::Includes & includes) { - OUString headerDefine(dumpHeaderDefine(o, u"HPP")); + dumpPragmaOnce(o); o << "\n"; addDefaultHxxIncludes(includes); includes.dump(o, &name_, true); o << "\n"; - - o << "\n#endif // "<< headerDefine << "\n"; } class ConstructiveType: public CppuType @@ -3635,7 +3619,7 @@ void ServiceType::dumpHppFile( OString cppName( codemaker::cpp::translateUnoToCppIdentifier( u2b(id_), "service", isGlobal())); - OUString headerDefine(dumpHeaderDefine(o, u"HPP")); + dumpPragmaOnce(o); o << "\n"; includes.dump(o, nullptr, true); if (!entity_->getConstructors().empty()) { @@ -3889,7 +3873,6 @@ void ServiceType::dumpHppFile( if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) { o << "\n"; } - o << "\n#endif // "<< headerDefine << "\n"; } void ServiceType::dumpCatchClauses( @@ -3934,7 +3917,7 @@ void SingletonType::dumpHppFile( u2b(id_), "singleton", isGlobal())); OString baseName(u2b(entity_->getBase())); OString scopedBaseName(codemaker::cpp::scopedCppName(baseName)); - OUString headerDefine(dumpHeaderDefine(o, u"HPP")); + dumpPragmaOnce(o); o << "\n"; //TODO: Decide whether the types added to includes should rather be added to // m_dependencies (and thus be generated during dumpDependedTypes): @@ -4013,7 +3996,6 @@ void SingletonType::dumpHppFile( if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) { o << "\n"; } - o << "\n#endif // "<< headerDefine << "\n"; } } diff --git a/codemaker/source/netmaker/csharpfile.hxx b/codemaker/source/netmaker/csharpfile.hxx index 56ba30429435..40bc59770e3e 100644 --- a/codemaker/source/netmaker/csharpfile.hxx +++ b/codemaker/source/netmaker/csharpfile.hxx @@ -25,7 +25,14 @@ public: } public: - std::string getPath() const { return m_filePath.string(); } + std::string getPath() const + { +#if defined __cpp_lib_format_path && __cpp_lib_format_path >= 202506L + return m_filePath.display_string(); +#else + return m_filePath.string(); +#endif + } void openFile() { diff --git a/codemaker/source/rustmaker/cpp_include_manager.cxx b/codemaker/source/rustmaker/cpp_include_manager.cxx index e2a63d0f7a13..2288aecc955c 100644 --- a/codemaker/source/rustmaker/cpp_include_manager.cxx +++ b/codemaker/source/rustmaker/cpp_include_manager.cxx @@ -151,7 +151,7 @@ OString CppIncludeManager::calculateRelativeIncludePath(const CppFile& file, // If they're in the same directory, just use the filename if (target.parent_path() == currentDir) { - std::string result = target.filename().string(); + std::string result = target.filename().string(); return OString("\"" + result + "\""); } @@ -167,7 +167,7 @@ OString CppIncludeManager::calculateRelativeIncludePath(const CppFile& file, rel = fs::relative(target, baseDir); } - std::string result = rel.generic_string(); + std::string result = rel.generic_string(); return OString("\"" + result + "\""); } diff --git a/codemaker/source/rustmaker/rustfile.cxx b/codemaker/source/rustmaker/rustfile.cxx index 0b2b863d87ed..eb9625f94575 100644 --- a/codemaker/source/rustmaker/rustfile.cxx +++ b/codemaker/source/rustmaker/rustfile.cxx @@ -23,7 +23,14 @@ RustFile::RustFile(std::string_view directory, std::string_view typeName) { } -std::string RustFile::getPath() const { return m_filePath.string(); } +std::string RustFile::getPath() const +{ +#if defined __cpp_lib_format_path && __cpp_lib_format_path >= 202506L + return m_filePath.display_string(); +#else + return m_filePath.string(); +#endif +} void RustFile::openFile() { @@ -255,7 +262,7 @@ void RustFile::addFileToModDeclaration() { std::filesystem::path parentDir = m_filePath.parent_path(); std::filesystem::path modFile = parentDir / "mod.rs"; - std::string fileName = m_filePath.stem().string(); // Get filename without extension + std::string fileName = m_filePath.stem().string(); // Get filename without extension if (std::filesystem::exists(modFile)) { @@ -294,12 +301,12 @@ void RustFile::ensureModFileExists(const std::filesystem::path& dirPath) { if (entry.is_directory()) { - std::string dirName = entry.path().filename().string(); + std::string dirName = entry.path().filename().string(); childModules.push_back(dirName); } else if (entry.is_regular_file() && entry.path().extension() == ".rs") { - std::string fileName = entry.path().stem().string(); + std::string fileName = entry.path().stem().string(); if (fileName != "mod") // Don't include mod.rs itself { childModules.push_back(fileName); @@ -327,7 +334,7 @@ void RustFile::ensureModFileExists(const std::filesystem::path& dirPath) if (parentDir >= outputRoot) { - std::string moduleName = dirPath.filename().string(); + std::string moduleName = dirPath.filename().string(); if (parentDir.filename() == "src") { @@ -452,9 +459,16 @@ CppFile::CppFile(std::string_view directory, std::string_view typeName, std::str { } -std::string CppFile::getPathString() const { return m_filePath.string(); } +std::string CppFile::getPathString() const +{ +#if defined __cpp_lib_format_path && __cpp_lib_format_path >= 202506L + return m_filePath.display_string(); +#else + return m_filePath.string(); +#endif +} std::filesystem::path CppFile::getPath() const { return m_filePath; } -std::string CppFile::getExtension() const { return m_filePath.extension().string(); } +std::string CppFile::getExtension() const { return m_filePath.extension().string(); } void CppFile::openFile() { @@ -619,14 +633,14 @@ void RustFile::processDirectoryRecursively(const std::filesystem::path& currentD { if (entry.is_directory()) { - std::string dirName = entry.path().filename().string(); + std::string dirName = entry.path().filename().string(); childModules.push_back(dirName); // Recursively process subdirectory processDirectoryRecursively(entry.path()); } else if (entry.is_regular_file() && entry.path().extension() == ".rs") { - std::string fileName = entry.path().stem().string(); + std::string fileName = entry.path().stem().string(); if (fileName != "mod" && fileName != "lib") // Don't include mod.rs or lib.rs { childModules.push_back(fileName); diff --git a/codemaker/source/rustmaker/rustproduce.cxx b/codemaker/source/rustmaker/rustproduce.cxx index b6da46888a16..88e2d21002bd 100644 --- a/codemaker/source/rustmaker/rustproduce.cxx +++ b/codemaker/source/rustmaker/rustproduce.cxx @@ -613,6 +613,7 @@ void RustProducer::generateInterfaceWrapper( .endLine() .beginLine() .append("#[allow(non_camel_case_types)]") + .append("#[repr(transparent)]") .endLine() .beginLine() .append("pub struct ") diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk index 0eae798fda71..4939cda63aba 100644 --- a/comphelper/Library_comphelper.mk +++ b/comphelper/Library_comphelper.mk @@ -35,7 +35,6 @@ $(eval $(call gb_Library_use_externals,comphelper,\ gpgmepp \ boost_headers \ frozen \ - icui18n \ icuuc \ icu_headers \ zlib \ @@ -120,7 +119,6 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/misc/interaction \ comphelper/source/misc/logging \ comphelper/source/misc/lok \ - comphelper/source/misc/markdown \ comphelper/source/misc/mimeconfighelper \ comphelper/source/misc/namedvaluecollection \ comphelper/source/misc/numberedcollection \ @@ -129,6 +127,7 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/misc/traceevent \ comphelper/source/misc/random \ comphelper/source/misc/SelectionMultiplex \ + comphelper/source/misc/scriptbrowse \ comphelper/source/misc/sequenceashashmap \ comphelper/source/misc/sharedmutex \ comphelper/source/misc/simplefileaccessinteraction \ @@ -153,7 +152,6 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/property/propagg \ comphelper/source/property/propertybag \ comphelper/source/property/propertycontainer \ - comphelper/source/property/propertycontainer2 \ comphelper/source/property/propertycontainerhelper \ comphelper/source/property/property \ comphelper/source/property/propertysethelper \ diff --git a/comphelper/qa/complex/comphelper/Map.java b/comphelper/qa/complex/comphelper/Map.java index 51f731732071..8e963d82b5b5 100644 --- a/comphelper/qa/complex/comphelper/Map.java +++ b/comphelper/qa/complex/comphelper/Map.java @@ -190,7 +190,7 @@ public class Map { components[i] = getMSF().createInstance( "com.sun.star.form.component." + serviceNames[i] ); } - // "normalize" the first component, so it has the property type + // "normalize" the first component, so it has the proper type Type formComponentType = new Type( XFormComponent.class ); components[0] = UnoRuntime.queryInterface( formComponentType.getZClass(), components[0] ); impl_checkMappings( components, serviceNames, "XFormComponent->string" ); @@ -309,7 +309,7 @@ public class Map /* ContainerEvent */ new Integer[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }, /* any */ new Integer[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, }; - // several asects are checked with this compatibility matrix: + // several aspects are checked with this compatibility matrix: // - if a map's value type is a scalar type, or a string, then nothing but this // type should be accepted // - if a map's value type is an interface type, then values should be accepted if @@ -378,7 +378,7 @@ public class Map private void impl_verifyEnumerationContent( XEnumeration _enum, final Object[] _expectedElements, final String _context ) throws com.sun.star.uno.Exception { - // since we cannot assume the map to preserve the ordering in which the elements where inserted, + // since we cannot assume the map to preserve the ordering in which the elements were inserted, // we can only verify that all elements exist as expected, plus *no more* elements than expected // are provided by the enumeration Set set = new HashSet(); diff --git a/comphelper/qa/string/test_string.cxx b/comphelper/qa/string/test_string.cxx index f4c473230a7f..230715bd946e 100644 --- a/comphelper/qa/string/test_string.cxx +++ b/comphelper/qa/string/test_string.cxx @@ -46,6 +46,7 @@ public: void testReverseCodePoints(); void testSplit(); void testRemoveAny(); + void testBufferReplaceAt(); CPPUNIT_TEST_SUITE(TestString); CPPUNIT_TEST(testStripStart); @@ -59,6 +60,7 @@ public: CPPUNIT_TEST(testReverseCodePoints); CPPUNIT_TEST(testSplit); CPPUNIT_TEST(testRemoveAny); + CPPUNIT_TEST(testBufferReplaceAt); CPPUNIT_TEST_SUITE_END(); }; @@ -233,6 +235,44 @@ void TestString::testRemoveAny() CPPUNIT_ASSERT_EQUAL(OUString(), removeAny(in, test7)); } +void TestString::testBufferReplaceAt() +{ + using namespace ::comphelper::string; + using namespace std::string_view_literals; + + OUStringBuffer aIn; + + replaceAt(aIn, /*index*/ 0, /*count*/ 0, u""sv); + CPPUNIT_ASSERT_EQUAL(u""_ustr, aIn.makeStringAndClear()); + + replaceAt(aIn, /*index*/ 0, /*count*/ 0, u"abc"sv); + CPPUNIT_ASSERT_EQUAL(u"abc"_ustr, aIn.makeStringAndClear()); + + aIn.append(u"abc"sv); + replaceAt(aIn, /*index*/ 0, /*count*/ 0, u"xyz"sv); + CPPUNIT_ASSERT_EQUAL(u"xyzabc"_ustr, aIn.makeStringAndClear()); + + aIn.append(u"abc"sv); + replaceAt(aIn, /*index*/ 2, /*count*/ 0, u"xyz"sv); + CPPUNIT_ASSERT_EQUAL(u"abxyzc"_ustr, aIn.makeStringAndClear()); + + aIn.append(u"abpqc"sv); + replaceAt(aIn, /*index*/ 2, /*count*/ 2, u"xyz"sv); + CPPUNIT_ASSERT_EQUAL(u"abxyzc"_ustr, aIn.makeStringAndClear()); + + aIn.append(u"abpqrstc"sv); + replaceAt(aIn, /*index*/ 2, /*count*/ 5, u"xyz"sv); + CPPUNIT_ASSERT_EQUAL(u"abxyzc"_ustr, aIn.makeStringAndClear()); + + aIn.append(u"abpqrstc"sv); + replaceAt(aIn, /*index*/ 2, /*count*/ 5, u""sv); + CPPUNIT_ASSERT_EQUAL(u"abc"_ustr, aIn.makeStringAndClear()); + + aIn.append(u"abc"sv); + replaceAt(aIn, /*index*/ 3, /*count*/ 0, u"xyz"sv); + CPPUNIT_ASSERT_EQUAL(u"abcxyz"_ustr, aIn.makeStringAndClear()); +} + CPPUNIT_TEST_SUITE_REGISTRATION(TestString); } diff --git a/comphelper/qa/unit/test_guards.cxx b/comphelper/qa/unit/test_guards.cxx index 48a1f2cd0992..92982c56e42c 100644 --- a/comphelper/qa/unit/test_guards.cxx +++ b/comphelper/qa/unit/test_guards.cxx @@ -106,7 +106,7 @@ CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testValueRestorationGuard) } CPPUNIT_ASSERT_EQUAL(199, value); - // set value, manually setto another value and restore after scope ends + // set value, manually set to another value and restore after scope ends { CPPUNIT_ASSERT_EQUAL(199, value); comphelper::ValueRestorationGuard aGuard(value, 100); diff --git a/comphelper/source/container/embeddedobjectcontainer.cxx b/comphelper/source/container/embeddedobjectcontainer.cxx index 327af79b504f..f95b9d4e0d75 100644 --- a/comphelper/source/container/embeddedobjectcontainer.cxx +++ b/comphelper/source/container/embeddedobjectcontainer.cxx @@ -254,7 +254,7 @@ bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::X bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rName ) { // allows to detect whether the object was already instantiated - // currently the filter instantiate it on loading, so this method allows + // currently the filter instantiates it on loading, so this method allows // to avoid objects pointing to the same persistence return pImpl->maNameToObjectMap.contains(rName); } @@ -390,7 +390,7 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbedde AddEmbeddedObject( xObj, rNewName ); OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED, - "A freshly create object should be running always!" ); + "A freshly created object should be running always!" ); } catch (uno::Exception const& e) { @@ -408,7 +408,7 @@ void EmbeddedObjectContainer::AddEmbeddedObject( uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY ); uno::Reference < embed::XEmbedPersist > xEmb( xObj, uno::UNO_QUERY ); uno::Reference < embed::XLinkageSupport > xLink( xEmb, uno::UNO_QUERY ); - // if the object has a persistence and the object is not a link than it must have persistence entry in the storage + // if the object has a persistence and the object is not a link then it must have persistence entry in the storage OSL_ENSURE( !( xEmb.is() && ( !xLink.is() || !xLink->isLink() ) ) || xAccess->hasByName(rName), "Added element not in storage!" ); #endif @@ -612,7 +612,7 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbedde uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED, - "A freshly create object should be running always!" ); + "A freshly created object should be running always!" ); // possible optimization: store later! if ( xPersist.is()) @@ -645,7 +645,7 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbedde uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); OSL_ENSURE( !xObj.is() || xObj->getCurrentState() != embed::EmbedStates::LOADED, - "A freshly create object should be running always!" ); + "A freshly created object should be running always!" ); // possible optimization: store later! if ( xPersist.is()) @@ -904,7 +904,7 @@ bool EmbeddedObjectContainer::RemoveEmbeddedObject( uno::Reference < embed::XLinkageSupport > xLink( xPersist, uno::UNO_QUERY ); sal_Bool bIsNotEmbedded = !xPersist.is() || ( xLink.is() && xLink->isLink() ); - // if the object has a persistence and the object is not a link than it must have persistence entry in the storage + // if the object has a persistence and the object is not a link then it must have persistence entry in the storage OSL_ENSURE( bIsNotEmbedded || xAccess->hasByName(aName), "Removing element not present in storage!" ); #endif @@ -989,7 +989,7 @@ bool EmbeddedObjectContainer::RemoveEmbeddedObject( try { #if OSL_DEBUG_LEVEL > 1 - // if the object has a persistence and the object is not a link than it must have persistence entry in storage + // if the object has a persistence and the object is not a link then it must have persistence entry in storage OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" ); #endif if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) ) @@ -1355,8 +1355,8 @@ bool EmbeddedObjectContainer::StoreChildren(bool _bOasisFormat,bool _bObjectsOnl //xPersist->storeOwn(); //commented, i120168 // begin:all charts will be persisted as xml format on disk when saving, which is time consuming. - // '_bObjectsOnly' mean we are storing to alien formats. - // 'isStorageElement' mean current object is NOT a MS OLE format. (may also include in future), i120168 + // '_bObjectsOnly' means we are storing to alien formats. + // 'isStorageElement' means current object is NOT an MS OLE format. (may also include in future), i120168 if (_bObjectsOnly && (nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING) && (pImpl->mxStorage->isStorageElement(name))) { @@ -1370,7 +1370,7 @@ bool EmbeddedObjectContainer::StoreChildren(bool _bOasisFormat,bool _bObjectsOnl //do nothing. Embedded model is not modified, no need to persist. } } - else //the embedded object is in active status, always store back it. + else //the embedded object is in active status, always store it back. { xPersist->storeOwn(); } diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx index 50212ab0bad3..d36af091ce85 100644 --- a/comphelper/source/misc/backupfilehelper.cxx +++ b/comphelper/source/misc/backupfilehelper.cxx @@ -205,7 +205,7 @@ namespace namespace { - enum PackageRepository { USER, SHARED, BUNDLED }; + enum class PackageRepository: sal_uInt32 { USER, SHARED, BUNDLED }; class ExtensionInfoEntry { @@ -216,21 +216,21 @@ namespace public: ExtensionInfoEntry() - : maRepository(USER), + : maRepository(PackageRepository::USER), mbEnabled(false) { } ExtensionInfoEntry(OString aName, bool bEnabled) : maName(std::move(aName)), - maRepository(USER), + maRepository(PackageRepository::USER), mbEnabled(bEnabled) { } ExtensionInfoEntry(const uno::Reference< deployment::XPackage >& rxPackage) : maName(OUStringToOString(rxPackage->getName(), RTL_TEXTENCODING_ASCII_US)), - maRepository(USER), + maRepository(PackageRepository::USER), mbEnabled(false) { // check maRepository @@ -238,11 +238,11 @@ namespace if (aRepName == "shared") { - maRepository = SHARED; + maRepository = PackageRepository::SHARED; } else if (aRepName == "bundled") { - maRepository = BUNDLED; + maRepository = PackageRepository::BUNDLED; } // check mbEnabled @@ -327,7 +327,7 @@ namespace } // write maRepository - sal_uInt32 nState(maRepository); + sal_uInt32 nState(static_cast(maRepository)); if (!write_sal_uInt32(rHandle, nState)) { @@ -1888,7 +1888,7 @@ namespace comphelper xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/VCL"_ustr, u"ForceSkia"_ustr, u"false"_ustr)); xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/VCL"_ustr, - u"ForceSkiaRaster"_ustr, u"true"_ustr)); + u"ForceSkiaGPU"_ustr, u"false"_ustr)); OUString aTempURL; { diff --git a/comphelper/source/misc/configuration.cxx b/comphelper/source/misc/configuration.cxx index 88e6a7c6f658..1561115b5d7b 100644 --- a/comphelper/source/misc/configuration.cxx +++ b/comphelper/source/misc/configuration.cxx @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -134,7 +134,7 @@ css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue(std::u1 // Note that this cache is only used by the officecfg:: auto-generated code, using it for anything // else would be unwise because the cache could end up containing stale entries. static std::mutex gMutex; - static std::map> gAccessMap; + static std::unordered_map> gAccessMap; sal_Int32 idx = path.rfind('/'); assert(idx!=-1); diff --git a/comphelper/source/misc/documentinfo.cxx b/comphelper/source/misc/documentinfo.cxx index 21425524e64e..c9eea2ba286f 100644 --- a/comphelper/source/misc/documentinfo.cxx +++ b/comphelper/source/misc/documentinfo.cxx @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -120,12 +121,8 @@ namespace comphelper { Reference< XStorable > xDocStorable( _rxDocument, UNO_QUERY_THROW ); sDocURL = xDocStorable->getLocation(); } + sDocURL.endsWith(u"/", &sDocURL); sal_Int32 nLastSepPos = sDocURL.lastIndexOf( '/' ); - if ( ( nLastSepPos != -1 ) && ( nLastSepPos == sDocURL.getLength() - 1 ) ) - { - sDocURL = sDocURL.copy( 0, nLastSepPos ); - nLastSepPos = sDocURL.lastIndexOf( '/' ); - } sTitle = sDocURL.copy( nLastSepPos + 1 ); if ( !sTitle.isEmpty() ) @@ -171,6 +168,55 @@ namespace comphelper { rModel->attachResource(rModel->getURL(), aMedDescr); } + void DocumentInfo::notifyRemoteContentFound( + const css::uno::Reference& rModel, + const css::uno::Reference& rxControl, + const OUString& rURL) + { + if (!rModel.is()) + return; + + // Build a sequence of (control, URL) pairs. If RemoteContentFound + // already exists, append to the existing sequence. + css::uno::Sequence aMedDescr = rModel->getArgs(); + + css::uno::Sequence aExisting; + for (const auto& rProp : aMedDescr) + { + if (rProp.Name == "RemoteContentFound") + rProp.Value >>= aExisting; + } + + sal_Int32 nOldLen = aExisting.getLength(); + aExisting.realloc(nOldLen + 1); + auto pEntries = aExisting.getArray(); + pEntries[nOldLen].Name = rURL; + pEntries[nOldLen].Value <<= rxControl; + + // Find and update or append RemoteContentFound + bool bFound = false; + sal_Int32 nNewLen = aMedDescr.getLength(); + auto pMedDescr = aMedDescr.getArray(); + for (sal_Int32 i = 0; i < nNewLen; ++i) + { + if (pMedDescr[i].Name == "RemoteContentFound") + { + pMedDescr[i].Value <<= aExisting; + bFound = true; + break; + } + } + if (!bFound) + { + aMedDescr.realloc(nNewLen + 1); + pMedDescr = aMedDescr.getArray(); + pMedDescr[nNewLen].Name = "RemoteContentFound"; + pMedDescr[nNewLen].Value <<= aExisting; + } + + rModel->attachResource(rModel->getURL(), aMedDescr); + } + } // namespace comphelper diff --git a/comphelper/source/misc/emscriptenthreading.cxx b/comphelper/source/misc/emscriptenthreading.cxx index 3c33fc47b5f5..730503d1eef2 100644 --- a/comphelper/source/misc/emscriptenthreading.cxx +++ b/comphelper/source/misc/emscriptenthreading.cxx @@ -12,7 +12,8 @@ #include #include -#if defined EMSCRIPTEN && ENABLE_QT6 && HAVE_EMSCRIPTEN_JSPI && !HAVE_EMSCRIPTEN_PROXY_TO_PTHREAD +#if defined __EMSCRIPTEN__ && ENABLE_QT6 && HAVE_EMSCRIPTEN_JSPI \ + && !HAVE_EMSCRIPTEN_PROXY_TO_PTHREAD #include diff --git a/comphelper/source/misc/instancelocker.cxx b/comphelper/source/misc/instancelocker.cxx index a1e6b5b85e59..905daf581b3b 100644 --- a/comphelper/source/misc/instancelocker.cxx +++ b/comphelper/source/misc/instancelocker.cxx @@ -113,7 +113,7 @@ void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArg throw lang::DisposedException(); // TODO if ( !m_refCount ) - throw uno::RuntimeException(); // the object must be refcounted already! + throw uno::RuntimeException(u"OInstanceLocker::initialize() called on an object without any UNO references"_ustr); // the object must be refcounted already! uno::Reference< uno::XInterface > xInstance; uno::Reference< embed::XActionsApproval > xApproval; @@ -150,7 +150,7 @@ void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArg if ( nLen == 3 && !( aArguments[2] >>= xApproval ) ) throw lang::IllegalArgumentException( - u"If the third argument is provided, it must be XActionsApproval implementation!"_ustr, + u"If the third argument is provided, it must be an XActionsApproval implementation!"_ustr, uno::Reference< uno::XInterface >(), 0 ); diff --git a/comphelper/source/misc/markdown.cxx b/comphelper/source/misc/markdown.cxx deleted file mode 100644 index b2d1bbdc491c..000000000000 --- a/comphelper/source/misc/markdown.cxx +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include - -#include - -constexpr sal_Int32 MAX_SEARCH_CHARS = 2000; - -namespace comphelper -{ -bool IsMarkdownData(const OUString& rData) -{ - icu::UnicodeString ustr(rData.getStr(), std::min(rData.getLength(), MAX_SEARCH_CHARS)); - - UErrorCode status = U_ZERO_ERROR; - - static std::unique_ptr patternHeadings( - icu::RegexPattern::compile(uR"(^\s*#{1,6}\s+.*)", UREGEX_MULTILINE, status)); - - static std::unique_ptr patternLinks( - icu::RegexPattern::compile(uR"(\[.*?\]\(.*?\))", 0, status)); - - static std::unique_ptr patternCode( - icu::RegexPattern::compile(uR"(```[\s\S]*?```)", 0, status)); - - static std::unique_ptr patternItalic( - icu::RegexPattern::compile(uR"(([*_])(?!\s)(.+?)(? patternBold( - icu::RegexPattern::compile(uR"(([*_])\1(?!\s)(.+?)(? patternStrikethrough( - icu::RegexPattern::compile(uR"(~~(?!\s)(.+?)(? patternHorizontalRule( - icu::RegexPattern::compile(uR"(^(?:-{3,}|\*{3,}|_{3,})$)", UREGEX_MULTILINE, status)); - - static std::unique_ptr patternBlockQuotes( - icu::RegexPattern::compile(uR"(^\s*>+.*$)", UREGEX_MULTILINE, status)); - - static std::unique_ptr patternTables(icu::RegexPattern::compile( - uR"(^\s*\|?(?:[^|\n]+?\|)+[^|\n]*\|?\s*$)", UREGEX_MULTILINE, status)); - - if (U_FAILURE(status)) - return false; - - return patternHeadings->matcher(ustr, status)->find() - || patternLinks->matcher(ustr, status)->find() - || patternCode->matcher(ustr, status)->find() - || patternItalic->matcher(ustr, status)->find() - || patternBold->matcher(ustr, status)->find() - || patternStrikethrough->matcher(ustr, status)->find() - || patternHorizontalRule->matcher(ustr, status)->find() - || patternBlockQuotes->matcher(ustr, status)->find() - || patternTables->matcher(ustr, status)->find(); -} -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/comphelper/source/misc/scriptbrowse.cxx b/comphelper/source/misc/scriptbrowse.cxx new file mode 100644 index 000000000000..d3e7e3c53bd4 --- /dev/null +++ b/comphelper/source/misc/scriptbrowse.cxx @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +bool getBoolProperty(const css::uno::Reference& xNode, + const OUString& sName) +{ + css::uno::Reference xPropertySet(xNode, css::uno::UNO_QUERY); + + if (!xPropertySet.is()) + return false; + + css::uno::Any xResult; + + try + { + xResult = xPropertySet->getPropertyValue(sName); + } + catch (css::beans::UnknownPropertyException&) + { + return false; + } + + bool bResult; + + if (!(xResult >>= bResult)) + return false; + + return bResult; +} + +css::uno::Any invokeMethod(const css::uno::Reference& xNode, + const OUString& sName, const css::uno::Sequence& aParams) +{ + css::uno::Reference xInvocation(xNode, css::uno::UNO_QUERY_THROW); + + css::uno::Sequence aOutParamIndex; + css::uno::Sequence aOutParam; + + return xInvocation->invoke(sName, aParams, aOutParamIndex, aOutParam); +} + +css::uno::Any invokeMethod(const css::uno::Reference& xNode, + const OUString& sName) +{ + return invokeMethod(xNode, sName, css::uno::Sequence()); +} + +css::uno::Any invokeMethod(const css::uno::Reference& xNode, + const OUString& sName, const OUString& sOtherName) +{ + css::uno::Sequence aParams{ css::uno::Any(sOtherName) }; + + return invokeMethod(xNode, sName, aParams); +} +} + +namespace comphelper::scriptbrowse +{ +bool isEditable(const css::uno::Reference& xNode) +{ + css::uno::Reference xEditable(xNode, + css::uno::UNO_QUERY); + + if (xEditable.is()) + return xEditable->isEditableNode(); + else + return getBoolProperty(xNode, u"Editable"_ustr); +} + +bool editNode(const css::uno::Reference& xNode) +{ + css::uno::Reference xEditable(xNode, + css::uno::UNO_QUERY); + + if (xEditable.is()) + { + return xEditable->editNode(); + } + else + { + bool bResult = false; + + invokeMethod(xNode, u"Editable"_ustr) >>= bResult; + + return bResult; + } +} + +bool isDeletable(const css::uno::Reference& xNode) +{ + css::uno::Reference xDeletable(xNode, + css::uno::UNO_QUERY); + + if (xDeletable.is()) + return xDeletable->isDeletableNode(); + else + return getBoolProperty(xNode, u"Deletable"_ustr); +} + +bool deleteNode(const css::uno::Reference& xNode) +{ + css::uno::Reference xDeletable(xNode, + css::uno::UNO_QUERY); + + if (xDeletable.is()) + { + return xDeletable->deleteNode(); + } + else + { + bool bResult = false; + + invokeMethod(xNode, u"Deletable"_ustr) >>= bResult; + + return bResult; + } +} + +bool isCreatable(const css::uno::Reference& xNode) +{ + css::uno::Reference xCreatable(xNode, + css::uno::UNO_QUERY); + + if (xCreatable.is()) + return xCreatable->isCreatableNode(); + else + return getBoolProperty(xNode, u"Creatable"_ustr); +} + +css::uno::Reference +createNode(const css::uno::Reference& xNode, + const OUString& sName) +{ + css::uno::Reference xCreatable(xNode, + css::uno::UNO_QUERY); + + if (xCreatable.is()) + { + return xCreatable->createNode(sName); + } + else + { + css::uno::Reference xResult; + + invokeMethod(xNode, u"Creatable"_ustr, sName) >>= xResult; + + return xResult; + } +} + +bool isRenamable(const css::uno::Reference& xNode) +{ + css::uno::Reference xRenamable(xNode, + css::uno::UNO_QUERY); + + if (xRenamable.is()) + return xRenamable->isRenamableNode(); + else + return getBoolProperty(xNode, u"Renamable"_ustr); +} + +css::uno::Reference +renameNode(const css::uno::Reference& xNode, + const OUString& sName) +{ + css::uno::Reference xRenamable(xNode, + css::uno::UNO_QUERY); + + if (xRenamable.is()) + { + return xRenamable->renameNode(sName); + } + else + { + css::uno::Reference xResult; + + invokeMethod(xNode, u"Renamable"_ustr, sName) >>= xResult; + + return xResult; + } +} + +std::vector> +getChildNodes(const css::uno::Reference& xNode) +{ + std::vector> aNodes; + + if (!xNode->hasChildNodes()) + { + // no nodes + return aNodes; + } + + const css::uno::Sequence> aNodeSequence + = xNode->getChildNodes(); + + aNodes.reserve(aNodeSequence.getLength()); + std::copy_if(aNodeSequence.begin(), aNodeSequence.end(), std::back_inserter(aNodes), + [](const auto& xChild) { + OSL_ENSURE(xChild.is(), + "comphelper::scriptbrowse::getChildNodes(): Invalid BrowseNode"); + return xChild.is(); + }); + + return aNodes; +} + +void sortNodes(std::vector>& aNodes) +{ + std::sort(aNodes.begin(), aNodes.end(), [](const auto& a, const auto& b) { + return a->getName().compareTo(b->getName()) < 0; + }); +} + +std::vector> +getSortedChildNodes(const css::uno::Reference& xNode) +{ + std::vector> aNodes + = getChildNodes(xNode); + + sortNodes(aNodes); + + return aNodes; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/comphelper/source/misc/string.cxx b/comphelper/source/misc/string.cxx index 2da3eb444c39..02c5ccb0a6b0 100644 --- a/comphelper/source/misc/string.cxx +++ b/comphelper/source/misc/string.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -671,9 +672,19 @@ void replaceAt(OUStringBuffer& rIn, sal_Int32 nIndex, sal_Int32 nCount, std::u16 if (newStr.size() > o3tl::make_unsigned(nCount)) rIn.ensureCapacity(nOldLength + newStr.size() - nCount); - sal_Unicode* pStr = const_cast(rIn.getStr()); - memmove(pStr + nIndex + newStr.size(), pStr + nIndex + nCount, nOldLength - nIndex + nCount); - memcpy(pStr + nIndex, newStr.data(), newStr.size()); + std::span pOldSpan{ const_cast(rIn.getStr()), + static_cast(nOldLength) }; + std::span pNewSpan{ const_cast(rIn.getStr()), + static_cast(nNewLength) }; + + // Move tail to the end of the new string + auto pSrcTail = pOldSpan.subspan(nIndex + nCount); + auto pDstTail = pNewSpan.subspan(nIndex + newStr.size()); + std::copy_backward(pSrcTail.begin(), pSrcTail.end(), pDstTail.end()); + + // Copy inserted string into position + auto pInsert = pNewSpan.subspan(nIndex); + std::copy_n(newStr.data(), newStr.size(), pInsert.begin()); rIn.setLength(nNewLength); } diff --git a/comphelper/source/misc/traceevent.cxx b/comphelper/source/misc/traceevent.cxx index a1bf09246065..d1aaa7438049 100644 --- a/comphelper/source/misc/traceevent.cxx +++ b/comphelper/source/misc/traceevent.cxx @@ -83,12 +83,6 @@ void TraceEvent::startRecording() void TraceEvent::stopRecording() { s_bRecording = false; } -void TraceEvent::setBufferSizeAndCallback(std::size_t bufferSize, void (*bufferFullCallback)()) -{ - s_nBufferSize = bufferSize; - s_pBufferFullCallback = bufferFullCallback; -} - std::vector TraceEvent::getEventVectorAndClear() { bool bRecording; diff --git a/comphelper/source/property/propertycontainer2.cxx b/comphelper/source/property/propertycontainer2.cxx deleted file mode 100644 index aaac2e9707bf..000000000000 --- a/comphelper/source/property/propertycontainer2.cxx +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- 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 - -namespace comphelper -{ -using namespace ::com::sun::star::uno; - -OPropertyContainer2::OPropertyContainer2() {} - -OPropertyContainer2::~OPropertyContainer2() {} - -Sequence OPropertyContainer2::getBaseTypes() -{ - // just the types from our one and only base class - return comphelper::OPropertySetHelper::getTypes(); -} - -bool OPropertyContainer2::convertFastPropertyValue(std::unique_lock& /*rGuard*/, - Any& _rConvertedValue, Any& _rOldValue, - sal_Int32 _nHandle, const Any& _rValue) -{ - return OPropertyContainerHelper::convertFastPropertyValue(_rConvertedValue, _rOldValue, - _nHandle, _rValue); -} - -void OPropertyContainer2::setFastPropertyValue_NoBroadcast(std::unique_lock& /*rGuard*/, - sal_Int32 _nHandle, const Any& _rValue) -{ - OPropertyContainerHelper::setFastPropertyValue(_nHandle, _rValue); -} - -void OPropertyContainer2::getFastPropertyValue(std::unique_lock& /*rGuard*/, - Any& _rValue, sal_Int32 _nHandle) const -{ - OPropertyContainerHelper::getFastPropertyValue(_rValue, _nHandle); -} - -} // namespace comphelper - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propertysetinfo.cxx b/comphelper/source/property/propertysetinfo.cxx index fbd2618b2a1f..c2786d858076 100644 --- a/comphelper/source/property/propertysetinfo.cxx +++ b/comphelper/source/property/propertysetinfo.cxx @@ -38,7 +38,7 @@ PropertySetInfo::PropertySetInfo( std::span pMap ) noexc // check for duplicates assert(!maPropertyMap.contains(rEntry.maName)); // Make sure there are no accidental empty entries left at the end of the array from - // when this method used to take a empty-terminated array. + // when this method used to take an empty-terminated array. assert(!rEntry.maName.isEmpty()); maPropertyMap.emplace(rEntry.maName, &rEntry); @@ -57,7 +57,7 @@ void PropertySetInfo::add( std::span pMap ) noexcept // check for duplicates assert(!maPropertyMap.contains(rEntry.maName)); // Make sure there are no accidental empty entries left at the end of the array from - // when this method used to take a empty-terminated array. + // when this method used to take an empty-terminated array. assert(!rEntry.maName.isEmpty()); maPropertyMap.emplace(rEntry.maName, &rEntry); diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx index 6ed8582940d3..18e106918ad5 100644 --- a/compilerplugins/clang/badstatics.cxx +++ b/compilerplugins/clang/badstatics.cxx @@ -209,10 +209,6 @@ public: || (loplugin::DeclCheck(pVarDecl).Var("maThreadSpecific") .Class("ScDocument").GlobalNamespace()) // not owning || name == "s_aLOKWindowsMap" // LOK only, guarded by assert, and LOK never tries to perform a VCL cleanup - // vcl/inc/jsdialog/jsdialogbuilder.hxx - || name == "m_aWidgetRegister" // LOK only, similar case as above - // - || name == "gNotebookBarManager" // LOK only case, when notebookbar is closed - VclPtr instance is removed || name == "gStaticManager" // vcl/source/graphic/Manager.cxx - stores non-owning pointers || name == "aThreadedInterpreterPool" // ScInterpreterContext(Pool), not owning || name == "aNonThreadedInterpreterPool" // ScInterpreterContext(Pool), not owning diff --git a/compilerplugins/clang/conditionalstring.cxx b/compilerplugins/clang/conditionalstring.cxx index cf858601ea0a..c08aa24a8119 100644 --- a/compilerplugins/clang/conditionalstring.cxx +++ b/compilerplugins/clang/conditionalstring.cxx @@ -17,7 +17,7 @@ // Find uses of OUString in conditional expressions that could be rewritten as std::u16string_view, // as in // -// s += (b ? OUString("xy") : OUString(z"); +// s += (b ? OUString("xy") : OUString("z")); namespace { @@ -189,7 +189,7 @@ public: } if (dc.Operator(OO_EqualEqual) .Namespace("rtl") - .GlobalNamespace()) //TODO: more precicse check + .GlobalNamespace()) //TODO: more precise check { assert(fn->getNumParams() == 2); assert(expr->getNumArgs() == 2); @@ -199,7 +199,7 @@ public: } if (dc.Operator(OO_ExclaimEqual) .Namespace("rtl") - .GlobalNamespace()) //TODO: more precicse check + .GlobalNamespace()) //TODO: more precise check { assert(fn->getNumParams() == 2); assert(expr->getNumArgs() == 2); @@ -207,7 +207,7 @@ public: check(expr->getArg(1)); return true; } - if (dc.Operator(OO_Less).Namespace("rtl").GlobalNamespace()) //TODO: more precicse check + if (dc.Operator(OO_Less).Namespace("rtl").GlobalNamespace()) //TODO: more precise check { assert(fn->getNumParams() == 2); assert(expr->getNumArgs() == 2); @@ -215,9 +215,7 @@ public: check(expr->getArg(1)); return true; } - if (dc.Operator(OO_LessEqual) - .Namespace("rtl") - .GlobalNamespace()) //TODO: more precicse check + if (dc.Operator(OO_LessEqual).Namespace("rtl").GlobalNamespace()) //TODO: more precise check { assert(fn->getNumParams() == 2); assert(expr->getNumArgs() == 2); @@ -225,7 +223,7 @@ public: check(expr->getArg(1)); return true; } - if (dc.Operator(OO_Greater).Namespace("rtl").GlobalNamespace()) //TODO: more precicse check + if (dc.Operator(OO_Greater).Namespace("rtl").GlobalNamespace()) //TODO: more precise check { assert(fn->getNumParams() == 2); assert(expr->getNumArgs() == 2); @@ -235,7 +233,7 @@ public: } if (dc.Operator(OO_GreaterEqual) .Namespace("rtl") - .GlobalNamespace()) //TODO: more precicse check + .GlobalNamespace()) //TODO: more precise check { assert(fn->getNumParams() == 2); assert(expr->getNumArgs() == 2); @@ -288,7 +286,7 @@ public: return true; } if (dc.Operator(OO_Plus).Namespace("rtl").GlobalNamespace() - && fn->getNumParams() == 2) //TODO: more precicse check + && fn->getNumParams() == 2) //TODO: more precise check { assert(expr->getNumArgs() == 2); check(expr->getArg(0)); diff --git a/compilerplugins/clang/constantparam.booleans.results b/compilerplugins/clang/constantparam.booleans.results index 5472567fae3e..5dd9a2161fe1 100644 --- a/compilerplugins/clang/constantparam.booleans.results +++ b/compilerplugins/clang/constantparam.booleans.results @@ -4414,46 +4414,6 @@ vcl/inc/impgraph.hxx:169 void ImpGraphic::ImpGraphic(_Bool) _Bool bDefault 0 -vcl/inc/jsdialog/jsdialogbuilder.hxx:286 - void JSWidget::JSWidget(class JSDialogSender *,type-parameter-?-? *,class SalInstanceBuilder *,const class com::sun::star::uno::Reference &,class std::function (class vcl::Window *)>,void *,_Bool) - _Bool bTakeOwnership - 0 -vcl/inc/jsdialog/jsdialogbuilder.hxx:413 - void JSDialog::JSDialog(class JSDialogSender *,class Dialog *,class SalInstanceBuilder *,_Bool) - _Bool bTakeOwnership - 0 -vcl/inc/jsdialog/jsdialogbuilder.hxx:430 - void JSAssistant::JSAssistant(class JSDialogSender *,class vcl::RoadmapWizard *,class SalInstanceBuilder *,_Bool) - _Bool bTakeOwnership - 0 -vcl/inc/jsdialog/jsdialogbuilder.hxx:485 - void JSButton::JSButton(class JSDialogSender *,class Button *,class SalInstanceBuilder *,_Bool) - class SalInstanceBuilder * pBuilder - 0 -vcl/inc/jsdialog/jsdialogbuilder.hxx:485 - void JSButton::JSButton(class JSDialogSender *,class Button *,class SalInstanceBuilder *,_Bool) - _Bool bTakeOwnership - 0 -vcl/inc/jsdialog/jsdialogbuilder.hxx:599 - void JSMessageDialog::JSMessageDialog(class JSDialogSender *,class MessageDialog *,class SalInstanceBuilder *,_Bool) - _Bool bTakeOwnership - 0 -vcl/inc/jsdialog/jsdialogbuilder.hxx:601 - void JSMessageDialog::JSMessageDialog(class MessageDialog *,class SalInstanceBuilder *,_Bool) - class SalInstanceBuilder * pBuilder - 0 -vcl/inc/jsdialog/jsdialogbuilder.hxx:601 - void JSMessageDialog::JSMessageDialog(class MessageDialog *,class SalInstanceBuilder *,_Bool) - _Bool bTakeOwnership - 1 -vcl/inc/jsdialog/jsdialogbuilder.hxx:777 - void JSMenu::JSMenu(class JSDialogSender *,class PopupMenu *,class SalInstanceBuilder *,_Bool) - _Bool bTakeOwnership - 0 -vcl/inc/jsdialog/jsdialogbuilder.hxx:789 - void JSPopover::JSPopover(class JSDialogSender *,class DockingWindow *,class SalInstanceBuilder *,_Bool) - _Bool bTakeOwnership - 0 vcl/inc/listbox.hxx:145 class rtl::OUString ImplEntryList::GetSelectedEntry(int) const int nIndex diff --git a/compilerplugins/clang/constantparam.numbers.results b/compilerplugins/clang/constantparam.numbers.results index b3ef1f8da5af..f33450c759fb 100644 --- a/compilerplugins/clang/constantparam.numbers.results +++ b/compilerplugins/clang/constantparam.numbers.results @@ -2922,10 +2922,6 @@ sw/inc/ndtxt.hxx:465 class SwTextAttr * SwTextNode::GetTextAttrForEndCharAt(int,unsigned short) const unsigned short nWhich 56 -sw/inc/swfltopt.hxx:31 - void SwFilterOptions::SwFilterOptions(unsigned short,const class rtl::OUString *,unsigned long *) - unsigned short nCnt - 13 sw/inc/swregion.hxx:46 void SwRegionRects::SwRegionRects(unsigned short) unsigned short nInit diff --git a/compilerplugins/clang/fieldcast.results b/compilerplugins/clang/fieldcast.results index 7be14a330da5..c8b715eb1186 100644 --- a/compilerplugins/clang/fieldcast.results +++ b/compilerplugins/clang/fieldcast.results @@ -49,9 +49,6 @@ configmgr/source/xcsparser.hxx:80 cppu/source/uno/lbenv.cxx:72 (anonymous namespace)::InterfaceEntry pTypeDescr typelib_InterfaceTypeDescription * _typelib_TypeDescription -cui/source/inc/cfg.hxx:407 - SvxConfigPage m_xContentsListBox std::unique_ptr - SvxNotebookbarEntriesListBox cui/source/inc/cuitabline.hxx:321 SvxLineEndDefTabPage pPolyObj const SdrObject * SdrPathObj diff --git a/compilerplugins/clang/implicitboolconversion.cxx b/compilerplugins/clang/implicitboolconversion.cxx index 2b39525bc9ba..a73d3694334b 100644 --- a/compilerplugins/clang/implicitboolconversion.cxx +++ b/compilerplugins/clang/implicitboolconversion.cxx @@ -79,7 +79,7 @@ QualType reconstructTemplateArgumentType( } bool areSameTypedef(QualType type1, QualType type2) { - // type1.getTypePtr() == typ2.getTypePtr() fails for e.g. ::sal_Bool vs. + // type1.getTypePtr() == type2.getTypePtr() fails for e.g. ::sal_Bool vs. // sal_Bool: auto t1 = type1->getAs(); auto t2 = type2->getAs(); @@ -241,7 +241,15 @@ public: FilteringPlugin(data) {} virtual void run() override - { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/soltools/cpp") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/soltools/mkdepend")) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } bool TraverseCallExpr(CallExpr * expr); diff --git a/compilerplugins/clang/mergeclasses.results b/compilerplugins/clang/mergeclasses.results index c08a2c7fa3cf..57a344276b75 100644 --- a/compilerplugins/clang/mergeclasses.results +++ b/compilerplugins/clang/mergeclasses.results @@ -54,7 +54,6 @@ maybe merge DocumentSettingsSerializer with sd::(anonymous namespace)::DocumentS merge DownloadInteractionHandler with UpdateCheck merge E3DObjGeoData with E3DSceneGeoData merge E3dUndoAction with E3dRotateUndoAction -merge EditTextObject with EditTextObjectImpl maybe merge ErrorContext with SfxErrorContext, in modules vcl and svtools maybe merge EscherExClientAnchor_Base with XclExpDffAnchorBase, in modules filter and sc merge EscherPersistTable with EscherEx diff --git a/compilerplugins/clang/narrow.cxx b/compilerplugins/clang/narrow.cxx index b08fb2979c3b..3cecde25bc67 100644 --- a/compilerplugins/clang/narrow.cxx +++ b/compilerplugins/clang/narrow.cxx @@ -78,8 +78,8 @@ bool Narrow::VisitBinaryOperator(const BinaryOperator* binaryOp) if (tc.Typedef("sal_UCS4").GlobalNamespace() || lhsType->isSpecificBuiltinType(BuiltinType::UInt)) return true; - report(DiagnosticsEngine::Warning, - "loosing information assigning a sal_UCS4 value to a %0 type", binaryOp->getBeginLoc()) + report(DiagnosticsEngine::Warning, "losing information assigning a sal_UCS4 value to a %0 type", + binaryOp->getBeginLoc()) << lhsType << binaryOp->getSourceRange(); return true; } @@ -95,8 +95,8 @@ bool Narrow::VisitVarDecl(const VarDecl* decl) return true; if (loplugin::TypeCheck(decl->getType()).Typedef("sal_UCS4").GlobalNamespace()) return true; - report(DiagnosticsEngine::Warning, - "loosing information assigning a sal_UCS4 value to a %0 type", decl->getBeginLoc()) + report(DiagnosticsEngine::Warning, "losing information assigning a sal_UCS4 value to a %0 type", + decl->getBeginLoc()) << decl->getType() << decl->getSourceRange(); return true; } diff --git a/compilerplugins/clang/nestedunnamed.cxx b/compilerplugins/clang/nestedunnamed.cxx index adc4f81a8130..8c09db254b05 100644 --- a/compilerplugins/clang/nestedunnamed.cxx +++ b/compilerplugins/clang/nestedunnamed.cxx @@ -13,7 +13,7 @@ #include "plugin.hxx" // Warn about unnamed namespaces nested (directly) within unnamed namespaces. (It can be hard to -// keep track whether a certain spot in a source file is already in an unnamed namespace, so it +// keep track of whether a certain spot in a source file is already in an unnamed namespace, so it // happens that additions to the source add redundant, nested unnamed namespaces.) namespace diff --git a/compilerplugins/clang/pointerbool.cxx b/compilerplugins/clang/pointerbool.cxx index 6225286a3dff..f5c2dfd4951b 100644 --- a/compilerplugins/clang/pointerbool.cxx +++ b/compilerplugins/clang/pointerbool.cxx @@ -78,6 +78,12 @@ bool PointerBool::TraverseFunctionDecl(FunctionDecl* decl) bool PointerBool::VisitCallExpr(CallExpr const* callExpr) { + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + if (loplugin::hasPathnamePrefix(fn, SRCDIR "/soltools/cpp") + || loplugin::hasPathnamePrefix(fn, SRCDIR "/soltools/mkdepend")) + return true; + if (ignoreLocation(callExpr)) return true; // TODO this doesn't currently work, the args and the params don't seem to line up diff --git a/compilerplugins/clang/refcounting.cxx b/compilerplugins/clang/refcounting.cxx index 8eab3ff7f751..b2b73c0a93d9 100644 --- a/compilerplugins/clang/refcounting.cxx +++ b/compilerplugins/clang/refcounting.cxx @@ -634,7 +634,7 @@ bool RefCounting::VisitReturnStmt(const ReturnStmt * returnStmt) { if (containsOWeakObjectSubclass(qt)) { report( DiagnosticsEngine::Warning, - "new object of cppu::OWeakObject subclass %0 being returned via raw pointer, should be returned by via rtl::Reference", + "new object of cppu::OWeakObject subclass %0 being returned via raw pointer, should be returned via rtl::Reference", returnStmt->getBeginLoc()) << qt << returnStmt->getSourceRange(); diff --git a/compilerplugins/clang/reservedid.cxx b/compilerplugins/clang/reservedid.cxx index 03adeea87976..7f22f9e58bb0 100644 --- a/compilerplugins/clang/reservedid.cxx +++ b/compilerplugins/clang/reservedid.cxx @@ -198,7 +198,7 @@ bool ReservedId::VisitNamedDecl(NamedDecl const * decl) { // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h && s != "_CustomCellRenderer" // vcl/unx/gtk3/customcellrenderer.hxx && s != "_CustomCellRendererClass" // vcl/unx/gtk3/customcellrenderer.cxx - && s != "_FcPattern" // vcl/inc/unx/fc_fontoptions.hxx + && s != "_FcPattern" // vcl/inc/unx/font/fc_fontoptions.hxx && s != "_GdkDisplay" // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c && s != "_GdkEvent" // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c diff --git a/compilerplugins/clang/returnconstval.cxx b/compilerplugins/clang/returnconstval.cxx index 4f8b0ac34348..8cdf98ff8999 100644 --- a/compilerplugins/clang/returnconstval.cxx +++ b/compilerplugins/clang/returnconstval.cxx @@ -14,7 +14,7 @@ #include "plugin.hxx" /** - Find code where we are return a const value type from a function. + Find code where we return a const value type from a function. Which makes no sense. Either we should return by non-const value, or by const ref. e.g. diff --git a/compilerplugins/clang/scpatternownership.cxx b/compilerplugins/clang/scpatternownership.cxx new file mode 100644 index 000000000000..b75b1d3a6417 --- /dev/null +++ b/compilerplugins/clang/scpatternownership.cxx @@ -0,0 +1,138 @@ +/* -*- 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/. + */ + +// ScPatternAttr ownership rules (canonical source). +// +// ScPatternAttr is the cell-pattern value object owned by a +// CellAttributeHelper. Each ScDocument creates its helper lazily via +// getCellAttributeHelper(); clipboard/undo documents share the helper +// through ScDocument::SharePooledResources. The helper holds a registry +// keyed by style name; each registered ScPatternAttr has a refcount +// tracked by the helper. CellAttributeHolder is the smart-pointer +// wrapper around an ScPatternAttr that bumps the refcount on assign and +// drops it on destruction; doUnregister destroys the pattern when its +// refcount reaches zero. +// +// The rule: any long-lived reference to an ScPatternAttr is held by +// CellAttributeHolder, not by raw pointer. A short-lived raw const +// ScPatternAttr* in a single function scope is fine if no operation +// that can apply a new pattern to a cell (formula interpretation, +// conditional-format evaluation, style change, SetNumberFormat, +// ApplyAttr, broadcasts on cells, ...) happens between the GetPattern() +// call and the use. A raw pointer stored in a class member, or held in +// a loop variable across such an operation, is a use after free waiting +// to happen; for the chain of prior per-call-site workarounds see +// git log --grep='ScPatternAttr.*use-after-free' -- engine/sc/ +// +// This plugin enforces the rule on class member fields: any class field +// of type (const) ScPatternAttr* is flagged. Allow-listed exceptions, +// named individually below: +// - CellAttributeHelper and CellAttributeHolder themselves +// - default-pattern cache fields that point at the helper's default +// ScPatternAttr (lives for the helper's full lifetime) +// - paint-pipeline structs whose lifetime is bounded to one paint +// call: DrawEditParam and the file-local ScDrawStringsVars in +// output2.cxx +// Additions to the allow list need an explicit entry. +// +// Not flagged: function-scope locals and function parameters. The +// plugin is declaration-AST only; flow-sensitive analysis is out of +// scope. Don't reintroduce raw class fields and don't hold raw locals +// across the operations listed above. + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include +#include + +#include "config_clang.h" + +#include "check.hxx" +#include "compat.hxx" +#include "plugin.hxx" + +namespace +{ +class ScPatternOwnership final : public loplugin::FilteringPlugin +{ +public: + explicit ScPatternOwnership(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + void run() override + { + if (preRun()) + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + + bool VisitFieldDecl(FieldDecl const* decl) + { + if (ignoreLocation(decl)) + return true; + + // The enclosing class + auto const* parent = dyn_cast(decl->getParent()); + if (!parent) + return true; + + // Skip our two owner-ish classes; they implement the model. + std::string const parentName = parent->getNameAsString(); + if (parentName == "CellAttributeHelper" || parentName == "CellAttributeHolder") + return true; + + std::string const fieldName = decl->getNameAsString(); + + // Default-pattern cache fields whose target is the helper's default + // ScPatternAttr, which lives for the helper's full lifetime. + if (parentName == "ScAttrIterator" && fieldName == "pDefPattern") + return true; + if (parentName == "AttrList" && fieldName == "mpDefPattern") // oox::xls + return true; + + // Paint-pipeline structs whose lifetime is bounded to the call that + // builds them; the pattern is set once, used immediately, and the + // struct goes out of scope long before the document does. The same + // applies to the file-local ScDrawStringsVars in output2.cxx. + if (parentName == "DrawEditParam" + && (fieldName == "mpPattern" || fieldName == "mpOldPattern")) + return true; + if (parentName == "ScDrawStringsVars" && fieldName == "pPattern") + return true; + + // Is it ScPatternAttr* or const ScPatternAttr*? + QualType qt = decl->getType(); + if (!qt->isPointerType()) + return true; + QualType pt = qt->getPointeeType().getUnqualifiedType().getCanonicalType(); + auto* rt = pt->getAs(); + if (!rt) + return true; + std::string const pointeeName = rt->getDecl()->getNameAsString(); + if (pointeeName != "ScPatternAttr") + return true; + + report(DiagnosticsEngine::Warning, + "class member of type %0 in %1; long-lived references to " + "ScPatternAttr must be held by CellAttributeHolder", + decl->getLocation()) + << qt << parentName; + return true; + } +}; + +loplugin::Plugin::Registration scpatternownership("scpatternownership"); +} + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/singlevalfields.results b/compilerplugins/clang/singlevalfields.results index 839ee36d0060..0548c39363b1 100644 --- a/compilerplugins/clang/singlevalfields.results +++ b/compilerplugins/clang/singlevalfields.results @@ -1174,7 +1174,7 @@ vcl/source/font/font.cxx:777 vcl/source/outdev/textline.cxx:97 (anonymous namespace)::WavyLineCache m_aItems 10 -vcl/unx/generic/fontmanager/fontconfig.cxx:119 +vcl/unx/generic/font/fontconfig.cxx:119 (anonymous namespace)::CachedFontConfigFontOptions lru_options_cache 10 vcl/unx/gtk3/a11y/atkutil.cxx:618 diff --git a/compilerplugins/clang/staticmethods.cxx b/compilerplugins/clang/staticmethods.cxx index 7769d47e6493..f4f9750722a7 100644 --- a/compilerplugins/clang/staticmethods.cxx +++ b/compilerplugins/clang/staticmethods.cxx @@ -214,8 +214,7 @@ bool StaticMethods::TraverseCXXMethodDecl(const CXXMethodDecl * pCXXMethodDecl) return true; } // depends on config options - if ((fdc.Function("autoInstallFontLangSupport").Class("PrintFontManager") - .Namespace("psp").GlobalNamespace()) + if (fdc.Function("autoInstallFontLangSupport").Class("FontConfigManager").GlobalNamespace() || fdc.Function("AllocateFrame").Class("GtkSalFrame").GlobalNamespace() || (fdc.Function("TriggerPaintEvent").Class("GtkSalFrame") .GlobalNamespace())) diff --git a/compilerplugins/clang/stringloop.cxx b/compilerplugins/clang/stringloop.cxx index 92d8a1d395d0..5b6cb2fa3519 100644 --- a/compilerplugins/clang/stringloop.cxx +++ b/compilerplugins/clang/stringloop.cxx @@ -63,8 +63,6 @@ void StringLoop::run() return; if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/pdf/pdfwriter_impl.cxx")) return; - if (loplugin::isSamePathname(fn, SRCDIR "/vcl/jsdialog/jsdialogregister.cxx")) - return; if (loplugin::hasPathnamePrefix(fn, SRCDIR "/idl/source/prj/command.cxx")) return; if (loplugin::hasPathnamePrefix(fn, SRCDIR "/framework/source/accelerators/storageholder.cxx")) diff --git a/compilerplugins/clang/stringstatic.cxx b/compilerplugins/clang/stringstatic.cxx index 1cc99e2a175a..862c05a94b85 100644 --- a/compilerplugins/clang/stringstatic.cxx +++ b/compilerplugins/clang/stringstatic.cxx @@ -13,7 +13,7 @@ #include "compat.hxx" #include "plugin.hxx" -/** Look for static O*String and O*String[] which can be constepxr. +/** Look for static O*String and O*String[] which can be constexpr. */ namespace { diff --git a/compilerplugins/clang/test/narrow.cxx b/compilerplugins/clang/test/narrow.cxx index 9c3127fab127..f0797cabb5a6 100644 --- a/compilerplugins/clang/test/narrow.cxx +++ b/compilerplugins/clang/test/narrow.cxx @@ -16,13 +16,13 @@ namespace test1 sal_UCS4 GetChar(); void f() { - // expected-error@+1 {{loosing information assigning a sal_UCS4 value to a 'sal_Unicode' (aka 'char16_t') type [loplugin:narrow]}} + // expected-error@+1 {{losing information assigning a sal_UCS4 value to a 'sal_Unicode' (aka 'char16_t') type [loplugin:narrow]}} sal_Unicode cChar = GetChar(); (void)cChar; // no error expected sal_UCS4 cChar2 = GetChar(); (void)cChar2; - // expected-error@+1 {{loosing information assigning a sal_UCS4 value to a 'sal_Unicode' (aka 'char16_t') type [loplugin:narrow]}} + // expected-error@+1 {{losing information assigning a sal_UCS4 value to a 'sal_Unicode' (aka 'char16_t') type [loplugin:narrow]}} cChar = GetChar(); } } diff --git a/compilerplugins/clang/test/refcounting.cxx b/compilerplugins/clang/test/refcounting.cxx index fc2e5fa2d8e8..47f5ed4407e5 100644 --- a/compilerplugins/clang/test/refcounting.cxx +++ b/compilerplugins/clang/test/refcounting.cxx @@ -92,7 +92,7 @@ void foo4() UnoObject* foo5() { - // expected-error@+1 {{new object of cppu::OWeakObject subclass 'UnoObject' being returned via raw pointer, should be returned by via rtl::Reference [loplugin:refcounting]}} + // expected-error@+1 {{new object of cppu::OWeakObject subclass 'UnoObject' being returned via raw pointer, should be returned via rtl::Reference [loplugin:refcounting]}} return new UnoObject; } rtl::Reference foo6() diff --git a/compilerplugins/clang/unnecessaryvirtual.results b/compilerplugins/clang/unnecessaryvirtual.results index 4426a27d35e5..c2803a285321 100644 --- a/compilerplugins/clang/unnecessaryvirtual.results +++ b/compilerplugins/clang/unnecessaryvirtual.results @@ -294,8 +294,6 @@ include/vbahelper/vbareturntypes.hxx:37 void ooo::vba::DefaultReturnHelper::setValue(type-parameter-0-0,) include/vbahelper/vbareturntypes.hxx:38 type-parameter-0-0 ooo::vba::DefaultReturnHelper::getValue() -include/vcl/menu.hxx:404 - void Menu::DumpAsPropertyTree(class tools::JsonWriter &,)const include/vcl/weld/customweld.hxx:40 _Bool weld::CustomWidgetController::KeyUp(const class KeyEvent &,) include/vcl/weld/customweld.hxx:44 @@ -410,22 +408,6 @@ toolkit/inc/controls/geometrycontrolmodel.hxx:185 void OGeometryControlModel::fillProperties(class com::sun::star::uno::Sequence &,class com::sun::star::uno::Sequence &,)const vcl/inc/font/LogicalFontInstance.hxx:128 void LogicalFontInstance::ImplInitHbFont(struct hb_font_t *,) -vcl/inc/jsdialog/jsdialogbuilder.hxx:322 - void JSWidget::show() -vcl/inc/jsdialog/jsdialogbuilder.hxx:335 - void JSWidget::hide() -vcl/inc/jsdialog/jsdialogbuilder.hxx:349 - void JSWidget::set_sensitive(_Bool,) -vcl/inc/jsdialog/jsdialogbuilder.hxx:362 - class com::sun::star::uno::Reference JSWidget::get_drop_target() -vcl/inc/jsdialog/jsdialogbuilder.hxx:370 - void JSWidget::freeze() -vcl/inc/jsdialog/jsdialogbuilder.hxx:376 - void JSWidget::thaw() -vcl/inc/jsdialog/jsdialogbuilder.hxx:385 - void JSWidget::grab_focus() -vcl/inc/jsdialog/jsdialogbuilder.hxx:430 - void JSWidget::set_buildable_name(const class rtl::OUString &,) vcl/inc/salframe.hxx:146 void SalFrame::SetRepresentedURL(const class rtl::OUString &,) vcl/inc/salframe.hxx:198 diff --git a/compilerplugins/clang/unusedenumconstants.py b/compilerplugins/clang/unusedenumconstants.py index ea5502a5e91e..6f5beed9a9a7 100755 --- a/compilerplugins/clang/unusedenumconstants.py +++ b/compilerplugins/clang/unusedenumconstants.py @@ -184,7 +184,6 @@ def is_ignore(srcLoc): "vcl/unx/gtk/xid_fullscreen_on_all_monitors.c", "vcl/unx/gtk/salnativewidgets-gtk.cxx", "sc/inc/callform.hxx", # ParamType - "include/i18nlangtag/applelangid.hxx", # AppleLanguageId "connectivity/source/drivers/firebird/Util.hxx", # firebird::BlobSubtype "include/xmloff/xmltoken.hxx", "sw/source/writerfilter/rtftok/rtfcontrolwords.hxx", diff --git a/compilerplugins/clang/unusedenumconstants.writeonly.results b/compilerplugins/clang/unusedenumconstants.writeonly.results index a5416adbffd5..2fb8ae6035c4 100644 --- a/compilerplugins/clang/unusedenumconstants.writeonly.results +++ b/compilerplugins/clang/unusedenumconstants.writeonly.results @@ -2,12 +2,6 @@ basctl/source/basicide/baside3.cxx:843 enum NameClashMode NO_CLASH basctl/source/basicide/doceventnotifier.cxx:55 enum basctl::(anonymous namespace)::ListenerAction RemoveListener -basctl/source/basicide/macrodlg.hxx:32 - enum basctl::MacroExitCode Macro_Close -basctl/source/basicide/macrodlg.hxx:34 - enum basctl::MacroExitCode Macro_New -basctl/source/basicide/macrodlg.hxx:35 - enum basctl::MacroExitCode Macro_Edit basctl/source/inc/bastype2.hxx:40 enum BrowseMode All basctl/source/inc/dlged.hxx:99 @@ -1316,9 +1310,9 @@ desktop/source/lib/init.cxx:8046 enum (unnamed at /home/noel/libo-plugin/desktop/source/lib/init.cxx:8043:5) FULL_INIT desktop/source/migration/services/oo3extensionmigration.hxx:62 enum migration::OO3ExtensionMigration::ScanResult SCANRESULT_DONTMIGRATE_EXTENSION -desktop/unx/source/start.c:178 +desktop/unx/source/start.cxx:178 int ProgressExit -desktop/unx/source/start.c:178 +desktop/unx/source/start.cxx:178 int ProgressRestart drawinglayer/source/tools/emfphelperdata.hxx:250 enum emfplushelper::EmfPlusHelperData::Direction vertical diff --git a/compilerplugins/clang/unusedfields.only-used-in-constructor.results b/compilerplugins/clang/unusedfields.only-used-in-constructor.results index 281ea2f970d8..7292bfda42f1 100644 --- a/compilerplugins/clang/unusedfields.only-used-in-constructor.results +++ b/compilerplugins/clang/unusedfields.only-used-in-constructor.results @@ -544,8 +544,6 @@ sccomp/source/solver/ParticelSwarmOptimization.hxx:55 ParticleSwarmOptimizationAlgorithm maRandomDevice std::random_device scripting/source/stringresource/stringresource.cxx:1246 stringresource::(anonymous namespace)::BinaryInput m_aData Sequence -sd/inc/anminfo.hxx:51 - SdAnimationInfo maSecondSoundFile OUString sd/qa/inc/sdtiledrenderingtest.hxx:79 SdTestViewCallback m_callbackWrapper TestLokCallbackWrapper sd/qa/unit/tiledrendering/tiledrendering.cxx:2830 @@ -912,8 +910,6 @@ vcl/inc/graphic/Manager.hxx:38 vcl::graphic::MemoryManager mnTimeout sal_Int32 vcl/inc/headless/BitmapHelper.hxx:32 BitmapHelper aTmpBmp SvpSalBitmap -vcl/inc/jsdialog/jsdialogbuilder.hxx:652 - JSToolbar m_pPopovers std::map vcl/inc/pdf/COSWriter.hxx:27 vcl::pdf::COSWriter maLine OStringBuffer vcl/inc/pdf/pdfbuildin_fonts.hxx:34 diff --git a/compilerplugins/clang/unusedfields.untouched.results b/compilerplugins/clang/unusedfields.untouched.results index b7eaa8155065..e1f8944db2f5 100644 --- a/compilerplugins/clang/unusedfields.untouched.results +++ b/compilerplugins/clang/unusedfields.untouched.results @@ -594,8 +594,6 @@ vcl/inc/font/TTFStructure.hxx:114 font::HeadTable nGlyphDataFormat o3tl::sal_uInt16_BE vcl/inc/font/TTFStructure.hxx:126 font::NameTable nVersion o3tl::sal_uInt16_BE -vcl/inc/jsdialog/jsdialogbuilder.hxx:652 - JSToolbar m_pPopovers std::map vcl/inc/pdf/pdfbuildin_fonts.hxx:34 vcl::pdf::BuildinFont m_nAscent const int vcl/inc/pdf/pdfbuildin_fonts.hxx:35 diff --git a/compilerplugins/clang/unusedmethods.results b/compilerplugins/clang/unusedmethods.results index 68670d274b4b..4c9c104a43f4 100644 --- a/compilerplugins/clang/unusedmethods.results +++ b/compilerplugins/clang/unusedmethods.results @@ -1,5 +1,3 @@ -basctl/source/basicide/baside2.hxx:404 - const rtl::OUString & basctl::ModulWindow::GetEditorColorScheme() basegfx/source/range/b2drangeclipper.cxx:686 type-parameter-?-? basegfx::(anonymous namespace)::eraseFromList(type-parameter-?-? &,const type-parameter-?-? &) basic/source/inc/buffer.hxx:40 @@ -40,8 +38,6 @@ canvas/source/vcl/canvasfont.hxx:76 const struct com::sun::star::geometry::Matrix2D & vclcanvas::CanvasFont::getFontMatrix() const canvas/source/vcl/impltools.hxx:83 vclcanvastools::LocalGuard::LocalGuard() -chart2/source/view/axes/VAxisBase.hxx:73 - const std::shared_ptr & chart::VAxisBase::getDataTableView() connectivity/inc/sdbcx/VGroup.hxx:61 connectivity::sdbcx::OGroup::OGroup(_Bool) connectivity/inc/sdbcx/VGroup.hxx:62 @@ -124,8 +120,6 @@ cppuhelper/inc/interfacecontainer4.hxx:277 void cppuhelper::OInterfaceContainerHelper4::NotifySingleListener::operator()(const Reference &) const cui/source/dialogs/SpellAttrib.hxx:73 _Bool svx::SpellErrorDescription::operator==(const struct svx::SpellErrorDescription &) const -cui/source/inc/CustomNotebookbarGenerator.hxx:30 - CustomNotebookbarGenerator::CustomNotebookbarGenerator() cui/source/inc/fileextcheckdlg.hxx:32 void FileExtCheckDialog::LinkStubOnOkClick(void *,weld::Button &) cui/source/inc/fileextcheckdlg.hxx:32 @@ -136,8 +130,6 @@ cui/source/inc/GraphicsTestsDialog.hxx:48 void GraphicsTestsDialog::HandleResultViewRequest(weld::Button &) cui/source/inc/GraphicsTestsDialog.hxx:48 void GraphicsTestsDialog::LinkStubHandleResultViewRequest(void *,weld::Button &) -cui/source/inc/SvxNotebookbarConfigPage.hxx:40 - void SvxNotebookbarConfigPage::SetElement() dbaccess/source/filter/hsqldb/fbalterparser.hxx:19 void dbahsql::FbAlterStmtParser::ensureProperTableLengths() const dbaccess/source/filter/hsqldb/parseschema.hxx:80 @@ -168,22 +160,6 @@ drawinglayer/inc/texture/texture.hxx:39 _Bool drawinglayer::texture::GeoTexSvx::operator!=(const drawinglayer::texture::GeoTexSvx &) const drawinglayer/source/primitive2d/GlowSoftEgdeShadowTools.hxx:37 drawinglayer::geometry::ViewInformation2D drawinglayer::primitive2d::expandB2DRangeAtViewInformation2D(const drawinglayer::geometry::ViewInformation2D &,double) -drawinglayer/source/tools/emfpstringformat.hxx:93 - _Bool emfplushelper::EMFPStringFormat::NoFitBlackBox() const -drawinglayer/source/tools/emfpstringformat.hxx:94 - _Bool emfplushelper::EMFPStringFormat::DisplayFormatControl() const -drawinglayer/source/tools/emfpstringformat.hxx:95 - _Bool emfplushelper::EMFPStringFormat::NoFontFallback() const -drawinglayer/source/tools/emfpstringformat.hxx:96 - _Bool emfplushelper::EMFPStringFormat::MeasureTrailingSpaces() const -drawinglayer/source/tools/emfpstringformat.hxx:97 - _Bool emfplushelper::EMFPStringFormat::NoWrap() const -drawinglayer/source/tools/emfpstringformat.hxx:98 - _Bool emfplushelper::EMFPStringFormat::LineLimit() const -drawinglayer/source/tools/emfpstringformat.hxx:99 - _Bool emfplushelper::EMFPStringFormat::NoClip() const -drawinglayer/source/tools/emfpstringformat.hxx:100 - _Bool emfplushelper::EMFPStringFormat::BypassGDI() const editeng/inc/EditLine.hxx:105 _Bool EditLine::IsInvalid() const editeng/inc/edtspell.hxx:99 @@ -202,10 +178,6 @@ editeng/inc/TextPortionList.hxx:66 __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator *, std::__cxx1998::vector > >, std::vector > > TextPortionList::cend() const editeng/source/editeng/impedit.hxx:231 tools::Rectangle LOKSpecialPositioning::GetWindowPos(const tools::Rectangle &,enum MapUnit) const -editeng/source/editeng/impedit.hxx:806 - double ImpEditEngine::scaleXFontValue(long) const -editeng/source/editeng/impedit.hxx:814 - double ImpEditEngine::scaleYFontValue(unsigned short) const embeddedobj/source/msole/olecomponent.hxx:72 void OleComponent::InitializeObject_Impl() embeddedobj/source/msole/olecomponent.hxx:74 @@ -216,8 +188,6 @@ embeddedobj/source/msole/olecomponent.hxx:77 void OleComponent::Dispose() embeddedobj/source/msole/olecomponent.hxx:81 OleComponent::OleComponent(const com::sun::star::uno::Reference &,OleEmbeddedObject *) -embeddedobj/source/msole/olecomponent.hxx:86 - OleComponent * OleComponent::createEmbeddedCopyOfLink() embeddedobj/source/msole/olecomponent.hxx:88 void OleComponent::disconnectEmbeddedObject() embeddedobj/source/msole/olecomponent.hxx:90 @@ -278,14 +248,10 @@ extensions/source/scanner/scanner.hxx:79 void ScannerManager::SetData(void *) extensions/source/scanner/scanner.hxx:83 com::sun::star::uno::Reference ScannerManager_CreateInstance(const com::sun::star::uno::Reference &) -filter/source/svg/svgwriter.hxx:341 - Color SVGActionWriter::ImplGetColorWithIntensity(const Color &,unsigned short) hwpfilter/source/hiodev.h:62 unsigned long HIODev::read4b(void *,unsigned long) idl/source/prj/svidl.cxx:103 int main(int,char **) -include/basegfx/color/bcolormodifier.hxx:118 - enum basegfx::BColorModifierType basegfx::BColorModifier::getBColorModifierType() const include/basegfx/color/bcolormodifier.hxx:422 basegfx::BColorModifier_randomize::BColorModifier_randomize(double) include/basegfx/curve/b2dcubicbezier.hxx:50 @@ -312,8 +278,6 @@ include/basegfx/matrix/hommatrixtemplate.hxx:43 basegfx::internal::ImplMatLine::ImplMatLine(unsigned short) include/basegfx/matrix/hommatrixtemplate.hxx:297 _Bool basegfx::internal::ImplHomMatrixTemplate::isInvertible() const -include/basegfx/numeric/ftools.hxx:114 - double basegfx::snapToRange(double,double,double) include/basegfx/numeric/ftools.hxx:118 double basegfx::copySign(double,double) include/basegfx/pixel/bpixel.hxx:53 @@ -366,8 +330,6 @@ include/basegfx/range/b3drange.hxx:97 _Bool basegfx::B3DRange::operator!=(const basegfx::B3DRange &) const include/basegfx/range/b3drange.hxx:198 basegfx::B3DTuple basegfx::B3DRange::clamp(const basegfx::B3DTuple &) const -include/basegfx/range/b3drange.hxx:218 - const basegfx::B3DRange & basegfx::B3DRange::getUnitB3DRange() include/basegfx/range/b3drange.hxx:223 basegfx::B3DRange basegfx::operator*(const basegfx::B3DHomMatrix &,const basegfx::B3DRange &) include/basegfx/range/Range2D.hxx:176 @@ -400,8 +362,6 @@ include/basegfx/utils/canvastools.hxx:129 basegfx::B3DRange basegfx::unotools::b3DRectangleFromRealRectangle3D(const struct com::sun::star::geometry::RealRectangle3D &) include/basegfx/utils/gradienttools.hxx:84 int (anonymous namespace)::ColorToBColorConverter::operator int() const -include/basegfx/utils/systemdependentdata.hxx:99 - unsigned int basegfx::SystemDependentData::getCombinedHoldCyclesInSeconds() const include/basegfx/utils/unopolypolygon.hxx:87 const basegfx::B2DPolyPolygon & basegfx::unotools::UnoPolyPolygon::getPolyPolygonUnsafe() const include/basegfx/vector/b2dsize.hxx:84 @@ -430,8 +390,6 @@ include/codemaker/global.hxx:55 FileStream & operator<<(FileStream &,const rtl::OStringBuffer *) include/codemaker/global.hxx:56 FileStream & operator<<(FileStream &,const rtl::OStringBuffer &) -include/codemaker/options.hxx:53 - const rtl::OString & Options::getProgramName() const include/codemaker/typemanager.hxx:45 const rtl::Reference & TypeManager::getManager() const include/codemaker/typemanager.hxx:49 @@ -642,8 +600,6 @@ include/editeng/svxacorr.hxx:183 const SvxAutocorrWord * SvxAutocorrWordList::Iterator::operator->() const include/filter/msfilter/mstoolbar.hxx:103 Indent::Indent(_Bool) -include/filter/msfilter/rtfutil.hxx:60 - int msfilter::rtfutil::AsHex(char) include/formula/opcode.hxx:547 std::basic_string OpCodeEnumToString(enum OpCode) include/formula/tokenarray.hxx:182 @@ -728,8 +684,6 @@ include/o3tl/enumarray.hxx:147 const type-parameter-?-?::value_type * o3tl::enumarray_const_iterator::operator->() const include/o3tl/enumarray.hxx:150 _Bool o3tl::enumarray_const_iterator::operator==(const enumarray_const_iterator &) const -include/o3tl/float_int_conversion.hxx:58 - type-parameter-?-? o3tl::roundAway(type-parameter-?-?) include/o3tl/hash_combine.hxx:20 void o3tl::hash_combine(type-parameter-?-? &,const type-parameter-?-? *,unsigned long) include/o3tl/intcmp.hxx:19 @@ -762,16 +716,12 @@ include/oox/drawingml/color.hxx:129 _Bool oox::drawingml::Color::equals(const oox::drawingml::Color &,const oox::GraphicHelper &,Color) const include/oox/drawingml/ThemeFilterBase.hxx:35 void oox::drawingml::ThemeFilterBase::setCurrentTheme(const std::shared_ptr &) -include/oox/export/DMLPresetShapeExport.hxx:100 - _Bool oox::drawingml::DMLPresetShapeExporter::HasHandleValue() const include/oox/export/DMLPresetShapeExport.hxx:129 com::sun::star::uno::Any oox::drawingml::DMLPresetShapeExporter::FindHandleValue(com::sun::star::uno::Sequence,std::basic_string_view) include/oox/export/drawingml.hxx:340 _Bool oox::drawingml::DrawingML::EqualGradients(const struct com::sun::star::awt::Gradient2 &,const struct com::sun::star::awt::Gradient2 &) include/oox/export/drawingml.hxx:377 _Bool oox::drawingml::DrawingML::WriteCharColor(const com::sun::star::uno::Reference &) -include/oox/export/drawingml.hxx:518 - Color oox::drawingml::DrawingML::ColorWithIntensity(unsigned int,unsigned int) include/oox/helper/attributelist.hxx:69 long oox::AttributeConversion::decodeHyper(std::basic_string_view) include/oox/helper/containerhelper.hxx:51 @@ -798,42 +748,26 @@ include/oox/helper/propertymap.hxx:115 void oox::PropertyMap::dumpCode(const com::sun::star::uno::Reference &) include/oox/helper/propertymap.hxx:116 void oox::PropertyMap::dumpData(const com::sun::star::uno::Reference &) -include/oox/ppt/slidepersist.hxx:93 - const std::shared_ptr & oox::ppt::SlidePersist::getBackgroundProperties() const include/opencl/openclconfig.hxx:58 _Bool OpenCLConfig::ImplMatcher::operator!=(const struct OpenCLConfig::ImplMatcher &) const include/opencl/openclconfig.hxx:95 std::basic_ostream & operator<<(std::basic_ostream &,const struct OpenCLConfig &) -include/package/InflateZstd.hxx:33 - ZipUtils::InflateZstd::InflateZstd(_Bool) -include/sfx2/childwin.hxx:120 - void SfxChildWindow::ClearController() -include/sfx2/docfilt.hxx:81 - _Bool SfxFilter::GetGpgEncryption() const include/sfx2/evntconf.hxx:61 struct SfxEventName & SfxEventNamesList::at(unsigned long) include/sfx2/infobar.hxx:104 void SfxInfoBarWindow::SetCommandHandler(weld::Button &,const rtl::OUString &) include/sfx2/lokcomponenthelpers.hxx:48 void LokChartHelper::Invalidate() -include/sfx2/viewsh.hxx:475 - enum LOKDeviceFormFactor SfxViewShell::GetLOKDeviceFormFactor() const -include/svl/itempool.hxx:202 - unsigned short SfxItemPool::GetSize_Impl() const include/svl/itempool.hxx:224 void SfxItemPool::AddRef(const SfxPoolItem &) include/svl/itempool.hxx:225 unsigned int SfxItemPool::ReleaseRef(const SfxPoolItem &,unsigned int) include/svl/itempool.hxx:247 const type-parameter-?-? * SfxItemPool::GetPoolDefaultItem(TypedWhichId) const -include/svl/itempool.hxx:262 - enum MapUnit SfxItemPool::GetDefaultMetric() const include/svl/lockfilecommon.hxx:60 void svt::LockFileCommon::SetURL(const rtl::OUString &) include/svl/ondemand.hxx:336 const CharClass & OnDemandCharClass::operator*() const -include/svl/poolitem.hxx:657 - _Bool SfxPoolItem::isPooled() const include/svl/poolitem.hxx:712 type-parameter-?-? * SfxPoolItem::DynamicWhichCast(TypedWhichId) include/svl/poolitem.hxx:868 @@ -854,8 +788,6 @@ include/svtools/DocumentToGraphicRenderer.hxx:106 _Bool DocumentToGraphicRenderer::isImpress() const include/svtools/extcolorcfg.hxx:54 const rtl::OUString & svtools::ExtendedColorConfigValue::getDisplayName() const -include/svtools/extcolorcfg.hxx:56 - Color svtools::ExtendedColorConfigValue::getDefaultColor() const include/svtools/extcolorcfg.hxx:58 void svtools::ExtendedColorConfigValue::setColor(Color) include/svtools/extcolorcfg.hxx:74 @@ -900,8 +832,6 @@ include/svtools/extcolorcfg.hxx:104 void svtools::EditableExtendedColorConfig::DisableBroadcast() include/svtools/extcolorcfg.hxx:105 void svtools::EditableExtendedColorConfig::EnableBroadcast() -include/svtools/scrolladaptor.hxx:60 - _Bool ScrollAdaptor::IsHoriScroll() const include/svx/autoformathelper.hxx:145 _Bool AutoFormatBase::operator==(const AutoFormatBase &) const include/svx/chrtitem.hxx:161 @@ -910,8 +840,6 @@ include/svx/chrtitem.hxx:180 void SvxChartColorPaletteItem::SetType(const enum ChartColorPaletteType) include/svx/chrtitem.hxx:181 void SvxChartColorPaletteItem::SetIndex(const unsigned int) -include/svx/ClassificationField.hxx:48 - const rtl::OUString & svx::ClassificationResult::getDisplayText() const include/svx/ClassificationField.hxx:53 _Bool svx::ClassificationResult::operator==(const svx::ClassificationResult &) const include/svx/ctredlin.hxx:64 @@ -924,8 +852,6 @@ include/svx/dlgctrl.hxx:263 void SvxLineEndLB::set_active_text(const rtl::OUString &) include/svx/framelink.hxx:169 _Bool svx::frame::operator>(const svx::frame::Style &,const svx::frame::Style &) -include/svx/hlnkitem.hxx:105 - void SvxHyperlinkItem::SetReplacementText(const rtl::OUString &) include/svx/langbox.hxx:95 void SvxLanguageBox::set_size_request(int,int) include/svx/Palette.hxx:45 @@ -940,10 +866,6 @@ include/svx/svdpage.hxx:230 std::reverse_iterator<__gnu_debug::_Safe_iterator, const rtl::Reference &, const rtl::Reference *>, std::deque > > > SdrObjList::rbegin() const include/svx/svdpage.hxx:231 std::reverse_iterator<__gnu_debug::_Safe_iterator, const rtl::Reference &, const rtl::Reference *>, std::deque > > > SdrObjList::rend() const -include/svx/svdpage.hxx:335 - void SdrPageProperties::sendLOKitThemeChangedCallback() -include/svx/svdpntv.hxx:518 - _Bool SdrPaintView::IsSwapAsynchron() const include/svx/svdtrans.hxx:246 _Bool IsMetric(enum MapUnit) include/svx/svxdlg.hxx:156 @@ -964,19 +886,7 @@ include/tools/bigint.hxx:210 BigInt operator-(const BigInt &,const BigInt &) include/tools/bigint.hxx:231 BigInt operator%(const BigInt &,const BigInt &) -include/tools/color.hxx:32 - unsigned int color::extractRGB(unsigned int) include/tools/cpuid.hxx:67 - _Bool cpuid::hasSSE2() -include/tools/cpuid.hxx:74 - _Bool cpuid::hasSSSE3() -include/tools/cpuid.hxx:81 - _Bool cpuid::hasAVX() -include/tools/cpuid.hxx:88 - _Bool cpuid::hasAVX2() -include/tools/cpuid.hxx:95 - _Bool cpuid::hasAVX512F() -include/tools/date.hxx:235 _Bool Date::IsValidDate(unsigned short,unsigned short,short) include/tools/datetime.hxx:52 DateTime::DateTime(const tools::Time &) @@ -1076,10 +986,6 @@ include/tools/XmlWriter.hxx:77 void tools::XmlWriter::element(const char *) include/unotest/directories.hxx:46 rtl::OUString test::Directories::getPathFromWorkdir(std::basic_string_view) const -include/unotools/charclass.hxx:101 - _Bool CharClass::isAlphaNumericType(int) -include/unotools/localedatawrapper.hxx:249 - const rtl::OUString & LocaleDataWrapper::getLongDateYearSep() const include/unotools/resmgr.hxx:58 TranslateNId::TranslateNId() include/unotools/resmgr.hxx:63 @@ -1090,10 +996,6 @@ include/unotools/securityoptions.hxx:64 _Bool SvtSecurityOptions::Certificate::operator==(const struct SvtSecurityOptions::Certificate &) const include/unotools/textsearch.hxx:122 basic_ostream & utl::operator<<(basic_ostream &,const enum utl::SearchParam::SearchType &) -include/unotools/useroptions.hxx:82 - rtl::OUString SvtUserOptions::GetSigningKeyDisplayName() const -include/unotools/useroptions.hxx:83 - rtl::OUString SvtUserOptions::GetEncryptionKeyDisplayName() const include/unotools/weakref.hxx:72 unotools::WeakReference::WeakReference(type-parameter-?-? &) include/vcl/abstdlgimpl.hxx:42 @@ -1160,12 +1062,8 @@ include/vcl/customweld.hxx:193 void weld::CustomWeld::set_tooltip_text(const rtl::OUString &) include/vcl/fieldvalues.hxx:59 double vcl::ConvertDoubleValue(long,long,unsigned short,enum FieldUnit,enum FieldUnit) -include/vcl/filter/pdfdocument.hxx:118 - const std::vector & vcl::filter::PDFObjectElement::GetDictionaryReferences() const include/vcl/filter/pdfdocument.hxx:127 unsigned long vcl::filter::PDFObjectElement::GetArrayLength() const -include/vcl/filter/pdfdocument.hxx:187 - vcl::filter::PDFNumberElement & vcl::filter::PDFReferenceElement::GetObjectElement() const include/vcl/filter/PDFiumLibrary.hxx:107 basegfx::B2DSize vcl::pdf::PDFiumAnnotation::getBorderCornerRadius() include/vcl/font/Feature.hxx:50 @@ -1186,8 +1084,6 @@ include/vcl/inputctx.hxx:62 _Bool InputContext::operator!=(const InputContext &) const include/vcl/ITiledRenderable.hxx:238 enum PointerStyle vcl::ITiledRenderable::getPointer() -include/vcl/jsdialog/executor.hxx:67 - void LOKTrigger::trigger_clicked(weld::Button &) include/vcl/lok.hxx:23 void vcl::lok::unregisterPollCallbacks() include/vcl/metric.hxx:52 @@ -1212,8 +1108,6 @@ include/vcl/salnativewidgets.hxx:387 _Bool TabitemValue::isNotAligned() const include/vcl/settings.hxx:366 void StyleSettings::SetWarningColor(const Color &) -include/vcl/settings.hxx:451 - const Color & StyleSettings::GetAlternatingRowColor() const include/vcl/settings.hxx:467 void StyleSettings::SetUseFlatBorders(_Bool) include/vcl/settings.hxx:470 @@ -1222,8 +1116,6 @@ include/vcl/settings.hxx:482 void StyleSettings::SetHideDisabledMenuItems(_Bool) include/vcl/settings.hxx:547 void StyleSettings::SetSpinSize(int) -include/vcl/settings.hxx:580 - Size StyleSettings::GetToolbarIconSizePixel() const include/vcl/settings.hxx:701 _Bool HelpSettings::operator!=(const HelpSettings &) const include/vcl/settings.hxx:762 @@ -1238,30 +1130,16 @@ include/vcl/task.hxx:86 _Bool Task::DecideTransferredExecution() include/vcl/TaskStopwatch.hxx:91 void TaskStopwatch::reset() -include/vcl/TaskStopwatch.hxx:102 - void TaskStopwatch::setInputStop(enum VclInputFlags) -include/vcl/TaskStopwatch.hxx:103 - enum VclInputFlags TaskStopwatch::inputStop() const -include/vcl/TaskStopwatch.hxx:111 - unsigned int TaskStopwatch::timeSlice() -include/vcl/TaskStopwatch.hxx:112 - void TaskStopwatch::setTimeSlice(unsigned int) include/vcl/textrectinfo.hxx:48 _Bool TextRectInfo::operator!=(const TextRectInfo &) const -include/vcl/themecolors.hxx:46 - void ThemeColors::SetThemeColors(const ThemeColors &) include/vcl/themecolors.hxx:138 const Color & ThemeColors::GetActiveTextColor() const include/vcl/themecolors.hxx:139 const Color & ThemeColors::GetActiveBorderColor() const include/vcl/themecolors.hxx:140 const Color & ThemeColors::GetFieldColor() const -include/vcl/themecolors.hxx:150 - const Color & ThemeColors::GetInactiveColor() const include/vcl/themecolors.hxx:153 const rtl::OUString & ThemeColors::GetThemeName() const -include/vcl/themecolors.hxx:156 - _Bool ThemeColors::IsAppBackBitmapStretched() include/vcl/toolkit/longcurr.hxx:46 BigInt LongCurrencyFormatter::GetValue() const include/vcl/toolkit/treelist.hxx:171 @@ -1316,8 +1194,6 @@ include/vcl/weld.hxx:1547 const rtl::OUString & weld::IconView::get_saved_value() const include/vcl/weld.hxx:1548 _Bool weld::IconView::get_value_changed_from_saved() const -include/vcl/weld.hxx:1677 - void weld::MenuButton::append_item_radio(const rtl::OUString &,const rtl::OUString &) include/vcl/weld.hxx:1685 void weld::MenuButton::append_item(const rtl::OUString &,const rtl::OUString &,VirtualDevice &) include/vcl/weld.hxx:1778 @@ -1326,16 +1202,12 @@ include/vcl/weld.hxx:2376 Size weld::MetricSpinButton::get_size_request() const include/vcl/weld.hxx:2388 void weld::MetricSpinButton::set_position(int) -include/vcl/weld.hxx:2492 - int weld::TextView::vadjustment_get_lower() const include/vcl/weld.hxx:2723 rtl::OUString weld::Toolbar::get_item_label(const rtl::OUString &) const include/vcl/weld.hxx:2773 void weld::Scrollbar::adjustment_configure(int,int,int,int,int,int) include/vcl/weld.hxx:2789 int weld::Scrollbar::get_scroll_thickness() const -include/vcl/weld.hxx:2823 - std::unique_ptr weld::Builder::weld_menu_toggle_button(const rtl::OUString &) include/vcl/weld.hxx:2936 rtl::OUString weld::MessageDialogController::get_secondary_text() const include/vcl/weldutils.hxx:198 @@ -1392,10 +1264,6 @@ oox/inc/drawingml/textliststyle.hxx:61 void oox::drawingml::TextListStyle::dump() const oox/inc/drawingml/textparagraphproperties.hxx:98 void oox::drawingml::TextParagraphProperties::setLineSpacing(const oox::drawingml::TextSpacing &) -oox/source/drawingml/diagram/diagramlayoutatoms.hxx:330 - const std::vector > & oox::drawingml::LayoutNode::getNodeShapes() const -oox/source/drawingml/diagram/diagramlayoutatoms.hxx:339 - const oox::drawingml::LayoutNode * oox::drawingml::LayoutNode::getParentLayoutNode() const oox/source/shape/WordprocessingCanvasContext.hxx:30 const _Bool & oox::shape::WordprocessingCanvasContext::isFullWPGSupport() const oox/source/shape/WordprocessingCanvasContext.hxx:31 @@ -1442,14 +1310,10 @@ sc/inc/column.hxx:293 _Bool ScColumn::HasDataAt(struct sc::ColumnBlockPosition &,int,struct ScDataAreaExtras *) sc/inc/columniterator.hxx:81 int sc::ColumnIterator::getType() const -sc/inc/datamapper.hxx:75 - void sc::ExternalDataSource::setUpdateFrequency(double) sc/inc/datamapper.hxx:78 void sc::ExternalDataSource::setURL(const rtl::OUString &) sc/inc/datamapper.hxx:79 void sc::ExternalDataSource::setProvider(const rtl::OUString &) -sc/inc/document.hxx:953 - const rtl::OUString & ScDocument::MaxRowAsString() const sc/inc/dpfilteredcache.hxx:148 void ScDPFilteredCache::dump() const sc/inc/formulacell.hxx:513 @@ -1516,8 +1380,6 @@ sc/inc/mtvelements.hxx:89 mdds::mtv::base_element_block * svl::mdds_mtv_create_new_block(const svl::SharedString &,const type-parameter-?-? &,const type-parameter-?-? &) sc/inc/mtvelements.hxx:89 void svl::mdds_mtv_insert_values(mdds::mtv::base_element_block &,unsigned long,const svl::SharedString &,const type-parameter-?-? &,const type-parameter-?-? &) -sc/inc/mtvfunctions.hxx:376 - void sc::ProcessElements2(type-parameter-?-? &,type-parameter-?-? &,type-parameter-?-? &) sc/inc/patattr.hxx:121 _Bool CellAttributeHolder::operator!() const sc/inc/rangecache.hxx:52 @@ -1592,14 +1454,8 @@ sc/source/core/tool/scmatrix.cxx:2431 wrapped_iterator (anonymous namespace)::wrapped_iterator::operator--(int) sc/source/core/tool/scmatrix.cxx:2444 type-parameter-?-? * (anonymous namespace)::wrapped_iterator::operator->() const -sc/source/filter/inc/drawingfragment.hxx:153 - const oox::vml::ShapeBase * oox::xls::VmlDrawing::getNoteShape(const ScAddress &) const sc/source/filter/inc/orcusinterface.hxx:831 const rtl::OUString * ScOrcusFactory::getString(unsigned long) const -sc/source/filter/inc/richstring.hxx:244 - _Bool oox::xls::RichString::isPreserveSpace() const -sc/source/filter/inc/tokstack.hxx:213 - _Bool TokenPool::GrowTripel(unsigned short) sc/source/filter/inc/worksheethelper.hxx:192 com::sun::star::uno::Reference oox::xls::WorksheetHelper::getCellRange(const ScRange &) const sc/source/filter/inc/xcl97rec.hxx:71 @@ -1640,26 +1496,14 @@ sc/source/ui/attrdlg/scdlgfact.cxx:83 (anonymous namespace)::ScreenshottedDialog_Impl_BASE::AbstractDialogImpl_BASE(weld::Window *&,const rtl::OUString *&) sc/source/ui/attrdlg/scdlgfact.cxx:83 (anonymous namespace)::ScreenshottedDialog_Impl_BASE::AbstractDialogImpl_BASE(weld::Window *&,enum CreateNameFlags &) -sc/source/ui/inc/dataprovider.hxx:59 - _Bool sc::CSVFetchThread::IsRequestedTerminate() sc/source/ui/inc/dataprovider.hxx:60 void sc::CSVFetchThread::Terminate() -sc/source/ui/inc/dataprovider.hxx:61 - void sc::CSVFetchThread::EndThread() sc/source/ui/inc/dataprovider.hxx:88 const rtl::OUString & sc::DataProvider::GetURL() const -sc/source/ui/inc/dataproviderdlg.hxx:57 - void ScDataProviderDlg::LinkStubStartMenuHdl(void *,const rtl::OString &) -sc/source/ui/inc/dataproviderdlg.hxx:57 - void ScDataProviderDlg::StartMenuHdl(const rtl::OString &) sc/source/ui/inc/dataproviderdlg.hxx:58 void ScDataProviderDlg::ColumnMenuHdl(const weld::ComboBox &) sc/source/ui/inc/dataproviderdlg.hxx:58 void ScDataProviderDlg::LinkStubColumnMenuHdl(void *,const weld::ComboBox &) -sc/source/ui/inc/dataproviderdlg.hxx:75 - void ScDataProviderDlg::applyAndQuit() -sc/source/ui/inc/dataproviderdlg.hxx:76 - void ScDataProviderDlg::cancelAndQuit() sc/source/ui/inc/datatableview.hxx:108 void ScDataTableView::getRowRange(int &,int &) const sc/source/ui/inc/datatransformation.hxx:197 @@ -1674,8 +1518,6 @@ sc/source/ui/inc/datatransformation.hxx:212 const rtl::OUString & sc::DeleteRowTransformation::getFindString() const sc/source/ui/inc/datatransformation.hxx:223 int sc::SwapRowsTransformation::getFirstRow() const -sc/source/ui/inc/datatransformation.hxx:224 - int sc::SwapRowsTransformation::getSecondRow() const sc/source/ui/inc/hfedtdlg.hxx:85 ScHFEditFirstHeaderDlg::ScHFEditFirstHeaderDlg(weld::Window *,const SfxItemSet &,std::basic_string_view) sc/source/ui/inc/hfedtdlg.hxx:106 @@ -1688,18 +1530,8 @@ sc/source/ui/inc/SparklineDataRangeDialog.hxx:52 _Bool sc::SparklineDataRangeDialog::checkValidInputOutput() sc/source/ui/inc/TableFillingAndNavigationTools.hxx:122 unsigned long DataRangeIterator::size() -sc/source/ui/inc/viewdata.hxx:407 - long ScViewData::GetLOKDocWidthPixel() const -sc/source/ui/inc/viewdata.hxx:408 - long ScViewData::GetLOKDocHeightPixel() const -sc/source/ui/inc/viewdata.hxx:557 - _Bool ScViewData::IsGridMode() const scaddins/source/analysis/analysishelper.hxx:781 _Bool sca::analysis::ScaDate::operator>=(const sca::analysis::ScaDate &) const -sccomp/source/solver/DifferentialEvolution.hxx:66 - int DifferentialEvolutionAlgorithm::getLastChange() -sccomp/source/solver/ParticelSwarmOptimization.hxx:84 - int ParticleSwarmOptimizationAlgorithm::getLastChange() sd/inc/sddll.hxx:47 SdDLL::SdDLL() sd/source/filter/eppt/epptooxml.hxx:96 @@ -1796,8 +1628,6 @@ sfx2/source/inc/shutdownicon.hxx:117 rtl::OUString ShutdownIcon::GetUrlDescription(std::basic_string_view) sfx2/source/inc/shutdownicon.hxx:119 void ShutdownIcon::SetVeto(_Bool) -sfx2/source/inc/templdgi.hxx:120 - void SfxCommonTemplateDialog_Impl::LinkStubUpdateStyleDependents_Hdl(void *,void *) shell/inc/xml_parser.hxx:43 xml_parser::xml_parser() shell/inc/xml_parser.hxx:66 @@ -1846,8 +1676,6 @@ slideshow/source/engine/slideoverlaybutton.hxx:66 struct com::sun::star::geometry::IntegerSize2D slideshow::internal::SlideOverlayButton::getSize() const slideshow/source/inc/box2dtools.hxx:159 void box2d::utils::box2DWorld::setShapeAngle(const com::sun::star::uno::Reference &,const double) -slideshow/source/inc/box2dtools.hxx:244 - _Bool box2d::utils::box2DWorld::shapesInitialized() slideshow/source/inc/eventmultiplexer.hxx:652 basegfx::B2DPoint slideshow::internal::EventMultiplexer::toMatrixPoint(const com::sun::star::uno::Reference &,const basegfx::B2DPoint &) slideshow/source/inc/listenercontainer.hxx:44 @@ -1868,48 +1696,12 @@ slideshow/source/inc/listenercontainer.hxx:54 _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const std::shared_ptr &) slideshow/source/inc/listenercontainer.hxx:54 _Bool slideshow::internal::FunctionApply::apply(type-parameter-?-?,const std::shared_ptr &) -slideshow/source/inc/shapeimporter.hxx:99 - void slideshow::internal::ShapeImporter::setMasterPageObjectsOnly(_Bool) -slideshow/source/inc/shapeimporter.hxx:104 - void slideshow::internal::ShapeImporter::setTextFieldsOnly(_Bool) starmath/inc/format.hxx:142 _Bool SmFormat::operator!=(const SmFormat &) const starmath/inc/mathml/attribute.hxx:80 SmMlAttribute::SmMlAttribute(const SmMlAttribute *) -starmath/inc/mathml/attribute.hxx:116 - _Bool SmMlAttribute::isMlAttributeValueType(enum SmMlAttributeValueType) const starmath/inc/mathml/attribute.hxx:132 void SmMlAttribute::setMlAttributeValue(const SmMlAttribute &) -starmath/inc/mathml/element.hxx:103 - _Bool SmMlElement::isMlElementType(enum SmMlElementType) const -starmath/inc/mathml/element.hxx:113 - const struct ESelection & SmMlElement::getESelection() const -starmath/inc/mathml/element.hxx:125 - void SmMlElement::setESelection(struct ESelection) -starmath/inc/mathml/element.hxx:132 - int SmMlElement::GetSourceCodeRow() const -starmath/inc/mathml/element.hxx:139 - int SmMlElement::GetSourceCodeColumn() const -starmath/inc/mathml/export.hxx:55 - void SmMLExportWrapper::setFlat(_Bool) -starmath/inc/mathml/export.hxx:59 - _Bool SmMLExportWrapper::getFlat() const -starmath/inc/mathml/export.hxx:63 - void SmMLExportWrapper::setUseHTMLMLEntities(_Bool) -starmath/inc/mathml/export.hxx:70 - _Bool SmMLExportWrapper::getUseHTMLMLEntities() const -starmath/inc/mathml/export.hxx:74 - _Bool SmMLExportWrapper::getUseExportTag() const -starmath/inc/mathml/export.hxx:78 - void SmMLExportWrapper::setUseExportTag(_Bool) -starmath/inc/mathml/export.hxx:81 - SmMLExportWrapper::SmMLExportWrapper(rtl::Reference) -starmath/inc/mathml/export.hxx:92 - _Bool SmMLExportWrapper::Export(SfxMedium &) -starmath/inc/mathml/export.hxx:96 - rtl::OUString SmMLExportWrapper::Export(SmMlElement *) -starmath/inc/mathml/export.hxx:139 - _Bool SmMLExport::getUseExportTag() const starmath/inc/mathml/import.hxx:39 SmMlElement * SmMLImportWrapper::getElementTree() starmath/inc/mathml/import.hxx:44 @@ -1922,12 +1714,6 @@ starmath/inc/mathml/import.hxx:141 void SmMLImport::SetSmSyntaxVersion(short) starmath/inc/mathml/import.hxx:145 short SmMLImport::GetSmSyntaxVersion() const -starmath/inc/mathml/iterator.hxx:22 - void mathml::SmMlIteratorBottomToTop(SmMlElement *,type-parameter-?-?,void *) -starmath/inc/mathml/iterator.hxx:121 - SmMlElement * mathml::SmMlIteratorCopy(SmMlElement *) -starmath/inc/mathml/mathmlexport.hxx:62 - _Bool SmXMLExportWrapper::IsUseHTMLMLEntities() const starmath/inc/mathml/mathmlimport.hxx:109 short SmXMLImport::GetSmSyntaxVersion() const starmath/inc/mathml/mathmlMo.hxx:83 @@ -1936,36 +1722,14 @@ starmath/inc/mathml/mathmlMo.hxx:88 enum moOpDF operator&(enum moOpDF,enum moOpDF) starmath/inc/mathml/mathmlMo.hxx:98 enum moOpDP operator&(enum moOpDP,enum moOpDP) -starmath/inc/mathml/starmathdatabase.hxx:288 - struct SmColorTokenTableEntry starmathdatabase::Identify_Color_DVIPSNAMES(unsigned int) -starmath/inc/node.hxx:508 - SmNode * SmStructureNode::GetSubNodeBinMo(unsigned long) const starmath/inc/node.hxx:533 void SmStructureNode::SetSubNodes(SmNode *,SmNode *,SmNode *) -starmath/inc/nodetype.hxx:59 - _Bool starmathdatabase::isStructuralNode(enum SmNodeType) -starmath/inc/nodetype.hxx:71 - _Bool starmathdatabase::isBinOperatorNode(enum SmNodeType) -starmath/inc/nodetype.hxx:77 - _Bool starmathdatabase::isUnOperatorNode(enum SmNodeType) -starmath/inc/nodetype.hxx:82 - _Bool starmathdatabase::isOperatorNode(enum SmNodeType) -starmath/inc/nodetype.hxx:89 - _Bool starmathdatabase::isStandaloneNode(enum SmNodeType) -starmath/inc/parse.hxx:31 - AbstractSmParser * starmathdatabase::GetDefaultSmParser() -starmath/inc/smmod.hxx:54 - rtl::OUString SmLocalizedSymbolData::GetExportSymbolName(std::basic_string_view) starmath/inc/token.hxx:181 SmColorTokenTableEntry::SmColorTokenTableEntry(const std::unique_ptr) starmath/inc/token.hxx:203 _Bool SmColorTokenTableEntry::equals(std::basic_string_view) const starmath/inc/token.hxx:210 _Bool SmColorTokenTableEntry::equals(Color) const -svgio/inc/svgstyleattributes.hxx:345 - const basegfx::BColor * svgio::svgreader::SvgStyleAttributes::getContextFill() const -svgio/inc/svgstyleattributes.hxx:348 - const basegfx::BColor * svgio::svgreader::SvgStyleAttributes::getContextStroke() const svgio/inc/svgstyleattributes.hxx:384 svgio::svgreader::SvgNumber svgio::svgreader::SvgStyleAttributes::getStrokeDashOffset() const svgio/inc/svgstyleattributes.hxx:408 @@ -1990,8 +1754,6 @@ svx/inc/sdr/contact/viewcontactofgraphic.hxx:51 SdrGrafObj & sdr::contact::ViewContactOfGraphic::GetGrafObject() sw/inc/AnnotationWin.hxx:208 void sw::annotation::SwAnnotationWin::queue_draw() -sw/inc/calbck.hxx:323 - sw::WriterListener * sw::ClientIteratorBase::GetLeftOfPos() sw/inc/calbck.hxx:430 SwIterator::SwIterator, TSource>(const type-parameter-?-? &) sw/inc/calbck.hxx:431 @@ -2074,8 +1836,6 @@ sw/inc/docary.hxx:143 void SwVectorModifyBase::dumpAsXml(struct _xmlTextWriter *) sw/inc/docufld.hxx:522 void SwPostItField::ToggleResolved() -sw/inc/editsh.hxx:381 - void SwEditShell::ValidateCurrentParagraphSignatures(_Bool) sw/inc/extinput.hxx:47 SwExtTextInput * SwExtTextInput::GetPrev() sw/inc/extinput.hxx:48 @@ -2098,8 +1858,6 @@ sw/inc/IDocumentLinksAdministration.hxx:53 _Bool IDocumentLinksAdministration::GetData(const rtl::OUString &,const rtl::OUString &,com::sun::star::uno::Any &) const sw/inc/IDocumentLinksAdministration.hxx:55 void IDocumentLinksAdministration::SetData(const rtl::OUString &) -sw/inc/modcfg.hxx:338 - _Bool SwModuleOptions::IsFileEncryptedFromColumn() const sw/inc/names.hxx:54 _Bool ProgName::operator==(std::basic_string_view) const sw/inc/names.hxx:55 @@ -2136,12 +1894,8 @@ sw/inc/rdfhelper.hxx:88 void SwRDFHelper::updateTextNodeStatement(const rtl::OUString &,const rtl::OUString &,SwTextNode &,const rtl::OUString &,const rtl::OUString &,const rtl::OUString &) sw/inc/ring.hxx:204 sw::RingIterator::RingIterator() -sw/inc/shellio.hxx:89 - void SwAsciiOptions::SetIncludeHidden(_Bool) sw/inc/swabstdlg.hxx:425 std::optional AbstractSwTranslateLangSelectDlg::GetSelectedLanguage() -sw/inc/swatrset.hxx:227 - const SvxNoHyphenItem & SwAttrSet::GetNoHyphenHere(_Bool) const sw/inc/swcrsr.hxx:314 SwTableCursor * SwTableCursor::GetNext() sw/inc/swcrsr.hxx:315 @@ -2154,10 +1908,6 @@ sw/inc/swrect.hxx:108 SvStream & WriteSwRect(SvStream &,const SwRect &) sw/inc/swrect.hxx:152 _Bool SwRect::OverStepTop(long) const -sw/inc/textboxhelper.hxx:260 - _Bool SwTextBoxNode::IsGroupTextBox() const -sw/inc/view.hxx:484 - void SwView::LinkStubMoveNavigationHdl(void *,void *) sw/inc/viscrs.hxx:235 SwShellTableCursor * SwShellTableCursor::GetNext() sw/inc/viscrs.hxx:236 @@ -2174,28 +1924,14 @@ sw/source/core/access/accportions.cxx:55 unsigned long FindBreak(const vector > &,type-parameter-?-?) sw/source/core/access/accportions.cxx:59 unsigned long FindLastBreak(const vector > &,type-parameter-?-?) -sw/source/core/inc/AccessibilityIssue.hxx:82 - SwTextFootnote * sw::AccessibilityIssue::getTextFootnote() -sw/source/core/inc/frame.hxx:972 - void SwFrame::dumpTopMostAsXml(struct _xmlTextWriter *) const sw/source/core/inc/frame.hxx:1428 Size SwRectFnSet::GetSize(const SwRect &) const -sw/source/core/inc/frame.hxx:1459 - long SwRectFnSet::LeftDist(const SwRect &,long) const -sw/source/core/inc/frame.hxx:1460 - long SwRectFnSet::RightDist(const SwRect &,long) const -sw/source/core/inc/mvsave.hxx:170 - _Bool ZSortFly::operator==(const ZSortFly &) const -sw/source/core/text/porlin.hxx:121 - _Bool SwLinePortion::IsTabRightPortion() const sw/source/core/text/txtpaint.hxx:73 DbgBackColor::DbgBackColor(OutputDevice *,const _Bool) sw/source/core/text/txtpaint.hxx:80 DbgRect::DbgRect(OutputDevice *,const tools::Rectangle &,const _Bool,Color) sw/source/filter/md/wrtmd.hxx:34 _Bool SwMDWriter::isInTable() const -sw/source/filter/md/wrtmd.hxx:35 - struct o3tl::strong_int SwMDWriter::StartNodeIndex() const sw/source/filter/ww8/ww8par.hxx:1043 WW8PostProcessAttrsInfo::WW8PostProcessAttrsInfo(int,int,SwPaM &) sw/source/ui/dialog/swdlgfact.cxx:108 @@ -2282,10 +2018,6 @@ vcl/inc/impfont.hxx:94 unsigned long ImplFont::GetHashValue() const vcl/inc/ImplLayoutArgs.hxx:78 std::basic_ostream & operator<<(std::basic_ostream &,const vcl::text::ImplLayoutArgs &) -vcl/inc/jsdialog/jsdialogbuilder.hxx:70 - void JSDropTarget::fire_dragEnter(const struct com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent &) -vcl/inc/jsdialog/jsdialogbuilder.hxx:592 - void JSFormattedSpinButton::set_text_without_notify(const rtl::OUString &) vcl/inc/opengl/zone.hxx:24 void OpenGLZone::relaxWatchdogTimings() vcl/inc/ppdparser.hxx:166 @@ -2336,8 +2068,6 @@ vcl/inc/skia/salbmp.hxx:107 void SkiaSalBitmap::dump(const char *) const vcl/inc/skia/utils.hxx:65 sk_sp SkiaHelper::createSkSurface(int,int,enum SkAlphaType) -vcl/inc/skia/utils.hxx:128 - void SkiaHelper::removeCachedImage(sk_sp) vcl/inc/skia/utils.hxx:138 void SkiaHelper::setPixelGeometry(enum SkPixelGeometry) vcl/inc/skia/utils.hxx:275 diff --git a/compilerplugins/clang/unusedvariableplus.cxx b/compilerplugins/clang/unusedvariableplus.cxx index 1e77efe4db0d..d26c84eaa60c 100644 --- a/compilerplugins/clang/unusedvariableplus.cxx +++ b/compilerplugins/clang/unusedvariableplus.cxx @@ -372,7 +372,6 @@ public: "SwEnhancedPDFExportHelper", "SwEnterLeave", "SwFieldSlot", - "SwFilterOptions", "SwFntAccess", "SwFontSave", "SwFootnoteSave", diff --git a/compilerplugins/clang/useuniqueptr.cxx b/compilerplugins/clang/useuniqueptr.cxx index cf4853f03b2b..14b900438bd6 100644 --- a/compilerplugins/clang/useuniqueptr.cxx +++ b/compilerplugins/clang/useuniqueptr.cxx @@ -1192,7 +1192,7 @@ void UseUniquePtr::CheckDeleteParmVar(const CXXDeleteExpr* deleteExpr, const Par if (fn == SRCDIR "/sd/source/ui/framework/tools/FrameworkHelper.cxx") return; // actually held via shared_ptr, uses protected deleter object - if (fn == SRCDIR "/sd/source/ui/presenter/CanvasUpdateRequester.cxx") + if (fn == SRCDIR "/sd/source/console/CanvasUpdateRequester.cxx") return; // actually held via shared_ptr, uses protected deleter object if (fn == SRCDIR "/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx") diff --git a/compilerplugins/clang/writeonlyvars.cxx b/compilerplugins/clang/writeonlyvars.cxx index 23c7415a0bb6..8f384614b02c 100644 --- a/compilerplugins/clang/writeonlyvars.cxx +++ b/compilerplugins/clang/writeonlyvars.cxx @@ -1125,7 +1125,7 @@ std::optional WriteOnlyVars::getCallee(CallExpr const* callExpr) if (functionDecl) return CalleeWrapper(functionDecl); - // Extract the functionprototype from a type + // Extract the function prototype from a type clang::Type const* calleeType = callExpr->getCallee()->getType().getTypePtr(); if (auto pointerType = calleeType->getUnqualifiedDesugaredType()->getAs()) { diff --git a/config_host.mk.in b/config_host.mk.in index c42d25be4358..039c77c07904 100644 --- a/config_host.mk.in +++ b/config_host.mk.in @@ -94,8 +94,6 @@ export CPDB_CFLAGS=@CPDB_CFLAGS@ export CPDB_LIBS=@CPDB_LIBS@ export CPPU_ENV=@CPPU_ENV@ export CPPU_ENV_FOR_BUILD=@CPPU_ENV_FOR_BUILD@ -export COLAMD_CFLAGS=$(gb_SPACE)@COLAMD_CFLAGS@ -export COLAMD_LIBS=$(gb_SPACE)@COLAMD_LIBS@ export CPPUNIT_CFLAGS=$(gb_SPACE)@CPPUNIT_CFLAGS@ export CPPUNIT_LIBS=$(gb_SPACE)@CPPUNIT_LIBS@ export CPUNAME=@CPUNAME@ @@ -210,7 +208,6 @@ export ENABLE_HTMLHELP=@ENABLE_HTMLHELP@ export ENABLE_JAVA=@ENABLE_JAVA@ export ENABLE_JUMBO_SHEETS=@ENABLE_JUMBO_SHEETS@ export ENABLE_LDAP=@ENABLE_LDAP@ -export ENABLE_LPSOLVE=@ENABLE_LPSOLVE@ export ENABLE_LTO=@ENABLE_LTO@ export ENABLE_LWP=@ENABLE_LWP@ export ENABLE_MACOSX_SANDBOX=@ENABLE_MACOSX_SANDBOX@ @@ -234,6 +231,7 @@ export ENABLE_POPPLER=@ENABLE_POPPLER@ export ENABLE_QT5=@ENABLE_QT5@ export ENABLE_QT6=@ENABLE_QT6@ export ENABLE_QT6_MULTIMEDIA=@ENABLE_QT6_MULTIMEDIA@ +export ENABLE_QUICKJS=@ENABLE_QUICKJS@ export ENABLE_KF5=@ENABLE_KF5@ export ENABLE_KF6=@ENABLE_KF6@ export ENABLE_GTK3_KDE5=@ENABLE_GTK3_KDE5@ @@ -285,6 +283,7 @@ export EPUBGEN_LIBS=$(gb_SPACE)@EPUBGEN_LIBS@ export ETONYEK_CFLAGS=$(gb_SPACE)@ETONYEK_CFLAGS@ export ETONYEK_LIBS=$(gb_SPACE)@ETONYEK_LIBS@ export debug=@ENABLE_DEBUG@ +FAKEROOT=@FAKEROOT@ export FIND=@FIND@ export FIREBIRD_CFLAGS=$(gb_SPACE)@FIREBIRD_CFLAGS@ export FIREBIRD_LIBS=$(gb_SPACE)@FIREBIRD_LIBS@ @@ -338,6 +337,7 @@ export HAVE_CLANG_DEBUG_INFO_KIND_CONSTRUCTOR=@HAVE_CLANG_DEBUG_INFO_KIND_CONSTR export HAVE_CXX20_ATOMIC_REF=@HAVE_CXX20_ATOMIC_REF@ export HAVE_DLLEXPORTINLINES=@HAVE_DLLEXPORTINLINES@ export HAVE_EXTERNAL_DWARF=@HAVE_EXTERNAL_DWARF@ +export HAVE_LINK_DEBUG_FASTLINK=@HAVE_LINK_DEBUG_FASTLINK@ export HAVE_LO_CLANG_DLLEXPORTINLINES=@HAVE_LO_CLANG_DLLEXPORTINLINES@ export HAVE_GCC_AVX=@HAVE_GCC_AVX@ export HAVE_GCC_BUILTIN_ATOMIC=@HAVE_GCC_BUILTIN_ATOMIC@ @@ -423,6 +423,8 @@ export LIBFONTS_JAR=@LIBFONTS_JAR@ export LIBFORMULA_JAR=@LIBFORMULA_JAR@ export LIBJPEG_CFLAGS=$(gb_SPACE)@LIBJPEG_CFLAGS@ export LIBJPEG_LIBS=$(gb_SPACE)@LIBJPEG_LIBS@ +export LIBJXL_CFLAGS=$(gb_SPACE)@LIBJXL_CFLAGS@ +export LIBJXL_LIBS=$(gb_SPACE)@LIBJXL_LIBS@ export LIBLANGTAG_CFLAGS=$(gb_SPACE)@LIBLANGTAG_CFLAGS@ export LIBLANGTAG_LIBS=$(gb_SPACE)@LIBLANGTAG_LIBS@ export LIBLAYOUT_JAR=@LIBLAYOUT_JAR@ @@ -612,9 +614,12 @@ export QT5_HAVE_GOBJECT=@QT5_HAVE_GOBJECT@ export QT5_PLATFORMS_SRCDIR=@QT5_PLATFORMS_SRCDIR@ export QT6_CFLAGS=$(gb_SPACE)@QT6_CFLAGS@ export QT6_LIBS=$(gb_SPACE)@QT6_LIBS@ +export QT6_LIBDIR=@QT6_LIBDIR@ export QT6_PLATFORMS_SRCDIR=@QT6_PLATFORMS_SRCDIR@ export QXP_CFLAGS=$(gb_SPACE)@QXP_CFLAGS@ export QXP_LIBS=$(gb_SPACE)@QXP_LIBS@ +export QUICKJS_CFLAGS=@QUICKJS_CFLAGS@ +export QUICKJS_LIBS=@QUICKJS_LIBS@ export RANLIB=@RANLIB@ export RAPTOR_MAJOR=@RAPTOR_MAJOR@ export RASQAL_MAJOR=@RASQAL_MAJOR@ @@ -640,6 +645,8 @@ export SKIA_DISABLE_VMA_USE_STL_SHARED_MUTEX=@SKIA_DISABLE_VMA_USE_STL_SHARED_MU export SKIA_GPU=@SKIA_GPU@ export SOLARINC=@SOLARINC@ export SORT=@SORT@ +# conditional assignment, to allow easy override by environment variable vs explicit argument +SOURCE_DATE_EPOCH?=@SOURCE_DATE_EPOCH@ export SPLIT_APP_MODULES=@SPLIT_APP_MODULES@ export SPLIT_OPT_FEATURES=@SPLIT_OPT_FEATURES@ export SRCDIR=@SRC_ROOT@ @@ -664,7 +671,6 @@ SYSTEM_BOX2D=@SYSTEM_BOX2D@ SYSTEM_BZIP2=@SYSTEM_BZIP2@ SYSTEM_CAIRO=@SYSTEM_CAIRO@ SYSTEM_CLUCENE=@SYSTEM_CLUCENE@ -SYSTEM_COLAMD=@SYSTEM_COLAMD@ SYSTEM_CPPUNIT=@SYSTEM_CPPUNIT@ SYSTEM_CURL=@SYSTEM_CURL@ SYSTEM_DICTS=@SYSTEM_DICTS@ @@ -699,6 +705,7 @@ SYSTEM_LIBEOT=@SYSTEM_LIBEOT@ SYSTEM_LIBEXTTEXTCAT=@SYSTEM_LIBEXTTEXTCAT@ SYSTEM_LIBEXTTEXTCAT_DATA=@SYSTEM_LIBEXTTEXTCAT_DATA@ SYSTEM_LIBFIXMATH=@SYSTEM_LIBFIXMATH@ +SYSTEM_LIBJXL=@SYSTEM_LIBJXL@ SYSTEM_LIBLANGTAG=@SYSTEM_LIBLANGTAG@ SYSTEM_LIBNUMBERTEXT=@SYSTEM_LIBNUMBERTEXT@ SYSTEM_LIBNUMBERTEXT_DATA=@SYSTEM_LIBNUMBERTEXT_DATA@ @@ -711,7 +718,6 @@ SYSTEM_LIBXML=@SYSTEM_LIBXML@ SYSTEM_LIBXML_FOR_BUILD=@SYSTEM_LIBXML_FOR_BUILD@ SYSTEM_LIBXSLT=@SYSTEM_LIBXSLT@ SYSTEM_LIBXSLT_FOR_BUILD=@SYSTEM_LIBXSLT_FOR_BUILD@ -SYSTEM_LPSOLVE=@SYSTEM_LPSOLVE@ SYSTEM_LZMA=@SYSTEM_LZMA@ SYSTEM_MD4C=@SYSTEM_MD4C@ SYSTEM_MDDS=@SYSTEM_MDDS@ @@ -731,6 +737,7 @@ SYSTEM_PAGEMAKER=@SYSTEM_PAGEMAKER@ SYSTEM_POPPLER=@SYSTEM_POPPLER@ SYSTEM_POSTGRESQL=@SYSTEM_POSTGRESQL@ SYSTEM_PYTHON=@SYSTEM_PYTHON@ +SYSTEM_QUICKJS=@SYSTEM_QUICKJS@ SYSTEM_ZXCVBN=@SYSTEM_ZXCVBN@ SYSTEM_ZXING=@SYSTEM_ZXING@ SYSTEM_QXP=@SYSTEM_QXP@ @@ -784,7 +791,6 @@ export WITH_COREDUMPCTL=@WITH_COREDUMPCTL@ export WITH_EXTENSION_INTEGRATION=@WITH_EXTENSION_INTEGRATION@ export WITH_EXTRA_EXTENSIONS=@WITH_EXTRA_EXTENSIONS@ export WITH_FONTS=@WITH_FONTS@ -export WITH_DOCREPAIR_FONTS=@WITH_DOCREPAIR_FONTS@ export WITH_GALLERY_BUILD=@WITH_GALLERY_BUILD@ export WITH_TEMPLATES=@WITH_TEMPLATES@ export WITH_GSSAPI=@WITH_GSSAPI@ @@ -792,6 +798,7 @@ export WITH_KRB5=@WITH_KRB5@ export WITH_LINKER_HASH_STYLE=@WITH_LINKER_HASH_STYLE@ export WITH_LOCALES=@WITH_LOCALES@ export WITH_MYSPELL_DICTS=@WITH_MYSPELL_DICTS@ +export WITH_PARQUET_FILTER=@WITH_PARQUET_FILTER@ export WITH_THEMES=@WITH_THEMES@ export WITH_WEBDAV=@WITH_WEBDAV@ WITH_YRS=@WITH_YRS@ @@ -822,6 +829,7 @@ MD4C_LIBS=$(gb_SPACE)@MD4C_LIBS@ export ZMF_CFLAGS=$(gb_SPACE)@ZMF_CFLAGS@ export ZMF_LIBS=$(gb_SPACE)@ZMF_LIBS@ export GET_TASK_ALLOW_ENTITLEMENT=@GET_TASK_ALLOW_ENTITLEMENT@ +export ZXCVBN_CFLAGS=$(gb_SPACE)@ZXCVBN_CFLAGS@ # lang-related stuff include $(BUILDDIR)/config_$(gb_Side)_lang.mk diff --git a/config_host/config_box2d.h.in b/config_host/config_box2d.h.in index 431987866623..54eeeb7cacf0 100644 --- a/config_host/config_box2d.h.in +++ b/config_host/config_box2d.h.in @@ -1,6 +1,9 @@ #ifndef CONFIG_BOX2D_H #define CONFIG_BOX2D_H +#undef BOX2D_MAJOR +#undef BOX2D_MINOR + /* Box2D/Box2D.h is 2.3, 2.4 has box2d/box2d.h */ #define BOX2D_HEADER diff --git a/config_host/config_features.h.in b/config_host/config_features.h.in index 042d1fec1ca3..56260c1bdf9f 100644 --- a/config_host/config_features.h.in +++ b/config_host/config_features.h.in @@ -82,11 +82,6 @@ #define HAVE_FEATURE_READONLY_INSTALLSET 0 -/* - * Whether curl is available - */ -#define HAVE_FEATURE_CURL 0 - /* * Whether we support breakpad as crash reporting lib. */ diff --git a/config_host/config_firebird.h.in b/config_host/config_firebird.h.in index edfbb2df62b4..e1d7bcce6fc3 100644 --- a/config_host/config_firebird.h.in +++ b/config_host/config_firebird.h.in @@ -7,4 +7,16 @@ Settings for Firebird #define ENABLE_FIREBIRD_SDBC 0 +/* The directory a system firebird has its plugin modules in, empty for a bundled firebird or when it + could not be determined. */ +#define SYSTEM_FIREBIRD_PLUGINS_DIRECTORY "" + +/* The directory a system firebird has its international modules in, empty for a bundled firebird or + when it could not be determined. */ +#define SYSTEM_FIREBIRD_INTL_DIRECTORY "" + +/* The directory a system firebird has its own configuration files in, empty for a bundled firebird + or when it could not be determined. */ +#define SYSTEM_FIREBIRD_CONF_DIRECTORY "" + #endif diff --git a/config_host/config_oauth2.h.in b/config_host/config_oauth2.h.in index 8b5bd3db0045..30d94c0f81ab 100644 --- a/config_host/config_oauth2.h.in +++ b/config_host/config_oauth2.h.in @@ -45,10 +45,6 @@ #define ONEDRIVE_REDIRECT_URI "http://localhost/LibreOffice" #define ONEDRIVE_SCOPE "Files.ReadWrite offline_access" -#if defined _WIN32 -#define OAUTH2REQUEST_SUPPORTED -#endif - #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configure.ac b/configure.ac index 9767560f6e8e..166e261ec39c 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl cspell:ignoreRegExp / -isystem / # several non-alphanumeric characters, those are split off and used only for the # ABOUTBOXPRODUCTVERSIONSUFFIX in openoffice.lst. Why that is necessary, no idea. -AC_INIT([LibreOffice],[26.8.0.0.alpha0+],[],[],[http://documentfoundation.org/]) +AC_INIT([LibreOffice],[27.2.0.0.alpha0+],[],[],[http://documentfoundation.org/]) dnl libnumbertext needs autoconf 2.68, but that can pick up autoconf268 just fine if it is installed dnl whereas aclocal (as run by autogen.sh) insists on using autoconf and fails hard @@ -34,7 +34,6 @@ fi save_CC=$CC save_CXX=$CXX - first_arg_basename() { for i in $1; do @@ -103,8 +102,7 @@ PathFormat() # or shell metacharacters). # # $formatted_path_unix is the argument in a form usable in Cygwin or WSL, using 8.3 components if - # necessary. On Cygwin, it is the same as $formatted_path, but on WSL it is $formatted_path as a - # Unix pathname. + # necessary. # # Errors out if 8.3 names are needed but aren't present for some of the path components. @@ -135,6 +133,7 @@ PathFormat() fi formatted_path="$1" + formatted_path_unix="$1" if test "$build_os" = "cygwin" -o "$build_os" = "wsl"; then if test "$build_os" = "wsl"; then formatted_path=$(echo "$formatted_path" | tr -d '\r') @@ -211,9 +210,6 @@ PathFormat() if test "$build_os" = "wsl"; then # WSL can't run Windows binaries from Windows pathnames so we need a separate return value in Unix format formatted_path_unix=$(wslpath "$formatted_path") - else - # But Cygwin can - formatted_path_unix="$formatted_path" fi if test -n "$WSL_ONLY_AS_HELPER"; then # if already in unix format, switch to windows format to create shortened path @@ -227,17 +223,24 @@ PathFormat() formatted_path_unix=$(wslpath -u "$(cd /mnt/c; cmd.exe /c $shortpath_cmd "$formatted_path" | tr -d '\r')") # WSL can't run Windows binaries from Windows pathnames so we need a separate return value in Unix format formatted_path=$(wslpath -m "$formatted_path_unix") - fi -} - -PathFormatUnix() -{ - # Like PathFormat, but also sets $formatted_path_unix to a Unix path in case of Cygwin, - # instead of setting it to the same as $formatted_path (which is a Windows path). - - PathFormat "$1" - if test "$build_os" = "cygwin"; then - formatted_path_unix=$(cygpath -u ${formatted_path_unix}) + # workaround for wsl < 2.4.5 not preserving the trailing slash, use case statement since + # ${VARIABLE: -1} / using offsets is not in POSIX sh + case "$formatted_path_unix" in + */) + case "$formatted_path" in + */) + ;; + *) + formatted_path="$formatted_path/" + ;; + esac + ;; + esac + elif test "$build_os" = "cygwin"; then + # while for cygwin there's no difference between the different realms during configure and + # during the build, AC_PATH_PROG still only accepts a path starting with / as valid, so also + # convert it to unix for that use case (and consistency) + formatted_path_unix=$(cygpath -u "$formatted_path") fi } @@ -310,6 +313,21 @@ dnl path location is gpg, so make sure we find it unset mac_gpg_path } +dnl format a header path taking into account Mac frameworks +format_header_path() +{ + local package_dir="${1}" + local parent_dir="${2}" + local header_file="${3}" + + local header_path="${1}/${2}/${3}" + if test "$_os" = "Darwin"; then + header_path="${1}/${2}.framework/Versions/A/Headers/${3}" + fi + PathFormat "${header_path}" +} + + dnl semantically test a three digits version dnl $1 - $3 = minimal version dnl $4 - $6 = current version @@ -603,10 +621,6 @@ AC_DEFINE_UNQUOTED(LIBO_VERSION_MINOR,$LIBO_VERSION_MINOR) AC_DEFINE_UNQUOTED(LIBO_VERSION_MICRO,$LIBO_VERSION_MICRO) AC_DEFINE_UNQUOTED(LIBO_VERSION_PATCH,$LIBO_VERSION_PATCH) -git_date=`git log -1 --pretty=format:"%cd" --date=format:'%Y' 2>/dev/null` -LIBO_THIS_YEAR=${git_date:-2026} -AC_DEFINE_UNQUOTED(LIBO_THIS_YEAR,$LIBO_THIS_YEAR) - dnl =================================================================== dnl Product version dnl =================================================================== @@ -623,6 +637,17 @@ BUILDDIR=`pwd` cd $srcdir SRC_ROOT=`pwd` cd $BUILDDIR + +# AC_DEFINE_UNQUOTED immediately appends to the intermediate confdefs.h, but +# we need that in the builddir so that the later AC_CONFIG_HEADERS calls have +# access to the value +git_date=`git -C $SRC_ROOT log -1 --pretty=format:"%cd" --date=format:'%Y' 2>/dev/null` +LIBO_THIS_YEAR=${git_date:-2026} +AC_DEFINE_UNQUOTED(LIBO_THIS_YEAR,$LIBO_THIS_YEAR) +# commit-time in unix epoch timestamp format in prep for reproducible builds +SOURCE_DATE_EPOCH=`git -C $SRC_ROOT log -1 --pretty=%ct 2>/dev/null` +AC_SUBST(SOURCE_DATE_EPOCH) + x_Cygwin=[\#] dnl ====================================== @@ -867,7 +892,7 @@ if test -n "$with_android_ndk"; then # NDK 15 or later toolchain is 64bit-only, except for Windows that we don't support. Using a 64-bit # linker is required if you compile large parts of the code with -g. A 32-bit linker just won't # manage to link the (app-specific) single huge .so that is built for the app in - # android/source/ if there is debug information in a significant part of the object files. + # android/app/ if there is debug information in a significant part of the object files. # (A 64-bit ld.gold grows too much over 10 gigabytes of virtual space when linking such a .so if # all objects have been built with debug information.) case $build_os in @@ -1107,6 +1132,7 @@ darwin*) # macOS mac_sanitize_path AC_MSG_NOTICE([sanitized the PATH to $PATH]) fi + test_qt6=yes _os=Darwin INSTROOTBASESUFFIX=/$PRODUCTNAME_WITHOUT_SPACES.app INSTROOTCONTENTSUFFIX=/Contents @@ -1146,7 +1172,6 @@ ios*) # iOS enable_lotuswordpro=no disable_database_connectivity_dependencies enable_coinmp=no - enable_lpsolve=no enable_extension_integration=no enable_xmlhelp=no with_ppds=no @@ -1239,7 +1264,6 @@ linux-android*) enable_mpl_subset=yes enable_cairo_canvas=no enable_coinmp=yes - enable_lpsolve=no enable_odk=no enable_python=no enable_xmlhelp=no @@ -1664,10 +1688,6 @@ libo_FUZZ_ARG_ENABLE(ext-wiki-publisher, [Enable the Wiki Publisher extension.]) ) -libo_FUZZ_ARG_ENABLE(lpsolve, - AS_HELP_STRING([--disable-lpsolve], - [Disable compilation of the lp solve solver ]) -) libo_FUZZ_ARG_ENABLE(coinmp, AS_HELP_STRING([--disable-coinmp], [Disable compilation of the CoinMP solver ]) @@ -1880,6 +1900,14 @@ AC_ARG_ENABLE(python, 'internal' (default) or 'fully-internal'. Otherwise the default is 'auto'. ])) +AC_ARG_ENABLE(quickjs, + AS_HELP_STRING([--enable-quickjs], [Enables experimental support for scripting with QuickJS.])) + +AC_ARG_WITH(system-quickjs, + AS_HELP_STRING([--with-system-quickjs], + [Use QuickJS already on system.]),, + [with_system_quickjs="$with_system_libs"]) + libo_FUZZ_ARG_ENABLE(gtk3, AS_HELP_STRING([--disable-gtk3], [Determines whether to use Gtk+ 3.0 vclplug on platforms where Gtk+ 3.0 is available.]), @@ -2373,9 +2401,6 @@ AC_ARG_WITH(extra-cxx-flags, [Specify extra flags (like GCC's -fdiagnostics-color=always, which is useful in combination with the GNU Make --output-sync option) to add to the end of the CXX variable.])) - - - dnl =================================================================== dnl Optional Packages (--with/without-) dnl =================================================================== @@ -2462,14 +2487,6 @@ libo_FUZZ_ARG_WITH(fonts, known to be available on the system then you should use this option.]), ,) -libo_FUZZ_ARG_WITH(docrepair-fonts, - AS_HELP_STRING([--with-docrepair-fonts], - [LibreOffice optionally includes fonts from 'The DocRepair Project' that - provide metrically equivalent fallback fonts for a variety of common fonts - seen in Office Open XML documents. See https://github.com/docrepair-fonts - for more details. This option has no effect when --without-fonts is used.]), -,) - AC_ARG_WITH(epm, AS_HELP_STRING([--with-epm], [Decides which epm to use. Default is to use the one from the system if @@ -2586,6 +2603,11 @@ AC_ARG_WITH(system-expat, [Use expat already on system.]),, [with_system_expat="$with_system_libs"]) +AC_ARG_WITH(system-libjxl, + AS_HELP_STRING([--with-system-libjxl], + [Use libjxl already on system.]),, + [with_system_libjxl="$with_system_libs"]) + AC_ARG_WITH(system-libxml, AS_HELP_STRING([--with-system-libxml], [Use libxml/libxslt already on system.]),, @@ -2667,9 +2689,6 @@ fi AC_SUBST([ENABLE_ODFSTUDIO]) - - -AC_SUBST([ENABLE_ODFSTUDIO]) AC_ARG_WITH(system-postgresql, AS_HELP_STRING([--with-system-postgresql], [Use PostgreSQL libraries already on system, for building the PostgreSQL-SDBC @@ -2877,16 +2896,6 @@ AC_ARG_WITH(system-altlinuxhyph, [Use ALTLinuxhyph already on system.]),, [with_system_altlinuxhyph="$with_system_libs"]) -AC_ARG_WITH(system-lpsolve, - AS_HELP_STRING([--with-system-lpsolve], - [Use lpsolve already on system.]),, - [with_system_lpsolve="$with_system_libs"]) - -AC_ARG_WITH(system-colamd, - AS_HELP_STRING([--with-system-colamd], - [Use COLAMD already on system.]),, - [with_system_colamd="$with_system_libs"]) - AC_ARG_WITH(system-coinmp, AS_HELP_STRING([--with-system-coinmp], [Use CoinMP already on system.]),, @@ -3487,7 +3496,6 @@ if test "$enable_wasm_strip" = "yes"; then enable_gpgmepp=no enable_ldap=no enable_lotuswordpro=no - enable_lpsolve=no enable_nss=no enable_odk=no enable_online_update=no @@ -4533,14 +4541,15 @@ find_ucrt() reg_get_value_32 "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v10.0" "InstallationFolder" if test -n "$regvalue"; then PathFormat "$regvalue" - UCRTSDKDIR=$formatted_path_unix + UCRTSDKDIR=$formatted_path + UCRTSDKDIR_unix=$formatted_path_unix reg_get_value_32 "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v10.0" "ProductVersion" if test -n "$regvalue"; then UCRTVERSION="$regvalue".0 fi # Rest if not exist - if ! test -d "${UCRTSDKDIR}Include/$UCRTVERSION/ucrt"; then + if ! test -d "${UCRTSDKDIR_unix}Include/$UCRTVERSION/ucrt"; then UCRTSDKDIR= fi fi @@ -4549,12 +4558,13 @@ find_ucrt() ide_env_file="${ide_env_dir}VsDevCmd.bat" if test -f "$ide_env_file"; then PathFormat "$(win_get_env_from_vsdevcmdbat UniversalCRTSdkDir)" - UCRTSDKDIR=$formatted_path_unix + UCRTSDKDIR=$formatted_path + UCRTSDKDIR_unix=$formatted_path_unix UCRTVERSION=$(win_get_env_from_vsdevcmdbat UCRTVersion) dnl Hack needed at least by tml: if test "$UCRTVERSION" = 10.0.15063.0 \ - -a ! -f "${UCRTSDKDIR}Include/10.0.15063.0/um/sqlext.h" \ - -a -f "${UCRTSDKDIR}Include/10.0.14393.0/um/sqlext.h" + -a ! -f "${UCRTSDKDIR_unix}Include/10.0.15063.0/um/sqlext.h" \ + -a -f "${UCRTSDKDIR_unix}Include/10.0.14393.0/um/sqlext.h" then UCRTVERSION=10.0.14393.0 fi @@ -5000,8 +5010,8 @@ if test "$GCC" = "yes" -a -z "$COM_IS_CLANG"; then AC_MSG_RESULT([gcc $_gcc_version ($gcc_full_version)]) - if test "$gcc_full_version" -lt 120000; then - AC_MSG_ERROR([GCC $_gcc_version is too old, must be at least GCC 12]) + if test "$gcc_full_version" -lt 130000; then + AC_MSG_ERROR([GCC $_gcc_version is too old, must be at least GCC 13]) fi else # Explicitly force GCC_VERSION to be empty, even for Clang, to check incorrect uses. @@ -5231,6 +5241,37 @@ fi AC_SUBST(USE_LD) AC_SUBST(LD) +dnl =================================================================== +dnl Check whether the linker supports -debug:fastlink, which links debug +dnl builds faster. link.exe offered it from VS 2017 to VS 2022 and dropped it +dnl in the VS 2026 toolset; lld-link never had it. Both then warn on every +dnl link and fall back to -debug:full, so probe the linker that will be used, +dnl and only pass the flag when it takes it silently. +dnl =================================================================== +HAVE_LINK_DEBUG_FASTLINK= +if test "$_os" = "WINNT"; then + AC_MSG_CHECKING([whether the linker supports -debug:fastlink]) + if test -n "$LLD_LINK"; then + fastlink_linker=$LLD_LINK + else + dnl PATH doesn't cover the MSVC tools yet; link.exe sits next to cl.exe + fastlink_linker=`win_short_path_for_make "$MSVC_HOST_PATH/link.exe"` + fi + dnl the link fails on the missing input file, and any mention of the flag in + dnl the output is a complaint about the flag itself: not being able to use it + if "$fastlink_linker" -debug:fastlink conftest-nonexistent.obj 2>&1 | grep -iq "debug:fastlink"; then + HAVE_LINK_DEBUG_FASTLINK= + else + HAVE_LINK_DEBUG_FASTLINK=TRUE + fi + if test -n "$HAVE_LINK_DEBUG_FASTLINK"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi +fi +AC_SUBST(HAVE_LINK_DEBUG_FASTLINK) + HAVE_LD_BSYMBOLIC_FUNCTIONS= if test "$GCC" = "yes" -a "$_os" != Emscripten ; then AC_MSG_CHECKING([for -Bsymbolic-functions linker support]) @@ -5897,7 +5938,7 @@ dnl Target-specific options dnl =================================================================== ENABLE_LASX="TRUE" -if test "$CPUNAME" == LOONGARCH64; then +if test "$CPUNAME" = LOONGARCH64; then AC_ARG_ENABLE(lasx, AS_HELP_STRING([--enable-lasx], [build with LASX vectorization]) @@ -6118,11 +6159,11 @@ msi - Windows .msi # fakeroot is needed to ensure correct file ownerships/permissions # inside deb packages and tar archives created on Linux and Solaris. if test "$OS" = "LINUX" || test "$OS" = "SOLARIS"; then - AC_PATH_PROG(FAKEROOT, fakeroot, no) - if test "$FAKEROOT" = "no"; then + # prefer fakeroot-sysv since faked-tcp can cause port collisions when packaging in parallel + AC_PATH_PROG(FAKEROOT, [fakeroot-sysv fakeroot-tcp fakeroot], AC_MSG_ERROR( [--with-package-format='$with_package_format' requires fakeroot. Install fakeroot.]) - fi + ) fi PKGFORMAT="$with_package_format" AC_MSG_RESULT([$PKGFORMAT]) @@ -6131,6 +6172,7 @@ else AC_MSG_RESULT([none]) fi AC_SUBST(PKGFORMAT) +AC_SUBST(FAKEROOT) dnl =================================================================== dnl handle help related options @@ -6328,7 +6370,7 @@ if test "$cross_compiling" = "yes"; then # similarly: at least skia headers need to be available in the cross-toolset test "${PLATFORMID}" = "windows_aarch64" && sub_conf_opts="$sub_conf_opts --enable-openssl --with-tls=openssl --enable-skia" # cross-compilations don't necessarily enable python support in the product/the sub-configure needs to know - # that the minimum supported python version is 3.7 or later... + # that the minimum supported python version is 3.11 or later... test "$with_system_harfbuzz" != "yes" && sub_conf_opts="$sub_conf_opts NEED_MESON=TRUE" # Don't bother having configure look for stuff not needed for the build platform anyway @@ -6389,6 +6431,7 @@ if test "$cross_compiling" = "yes"; then ARGON2 AVMEDIA BOOST + BROTLI BZIP2 CAIRO CLUCENE @@ -6405,9 +6448,11 @@ if test "$cross_compiling" = "yes"; then GRAPHITE HARFBUZZ HELPTOOLS + HIGHWAY ICU LCMS2 LIBJPEG_TURBO + LIBJXL LIBLANGTAG LibO LIBFFI @@ -6748,7 +6793,7 @@ if test -z "$TARFILE_LOCATION"; then else AbsolutePath "$TARFILE_LOCATION" PathFormat "${absolute_path}" - TARFILE_LOCATION="${formatted_path_unix}" + TARFILE_LOCATION="${formatted_path}" fi AC_SUBST(TARFILE_LOCATION) @@ -7088,7 +7133,12 @@ if test "$_os" = "WINNT"; then done fi fi -if test "$with_system_hsqldb" = "yes"; then + +# required for solenv/bin/rewrite_zip_timestamps.pl/for reproducible builds +# and also needed for --with-system-hsqldb +if test -n "$WSL_ONLY_AS_HELPER"; then + perl_use_string_spp="$perl_use_string_spp ; use Archive::Zip" +else perl_use_string="$perl_use_string ; use Archive::Zip" fi if test "$enable_openssl" = "yes" -a "$with_system_openssl" != "yes"; then @@ -8305,7 +8355,7 @@ if test -z "${CXXFLAGS_CXX11+x}"; then elif test "$GCC" = "yes" -o "$COM_IS_CLANG" = TRUE; then my_flags='-std=c++20 -std=c++2a' if test "$with_latest_c__" = yes; then - my_flags="-std=c++26 -std=c++2c -std=c++23 -std=c++2b $my_flags" + my_flags="-std=c++29 -std=c++2d -std=c++26 -std=c++2c -std=c++23 -std=c++2b $my_flags" fi for flag in $my_flags; do if test "$COM" = MSC; then @@ -9313,7 +9363,13 @@ if test "$ENABLE_JAVA" != "" -a "$cross_compiling" != "yes"; then if test "$_jdk_ver" -ge 180000 && test "$_jdk_ver" -lt 240000; then JDK_SECURITYMANAGER_DISALLOWED=TRUE fi - + # reproducible builds make use of jar --date and that was introduced in jdk19 + # and backported to openJDK 17.0.3/oracle JDK 17.0.6 respectively + if test "$_jdk_ver" -lt 170006 || test "$_jdk_ver" -ge 180000 && test "$_jdk_ver" -lt 190000; then + AC_MSG_WARN([JDK too old for reproducible builds, needs jar --date support (see https://bugs.openjdk.org/browse/JDK-8276766 )]) + add_warning "JDK too old for reproducible builds, needs jar --date support (see https://bugs.openjdk.org/browse/JDK-8276766 )" + SOURCE_DATE_EPOCH="" + fi JAVA_HOME=`echo $JAVAINTERPRETER | $SED -n "s,//*bin//*java,,p"` if test "$_os" = "WINNT"; then JAVA_HOME=`echo $JAVA_HOME | $SED "s,\.[[eE]][[xX]][[eE]]$,,"` @@ -9502,7 +9558,7 @@ _ACEOF fi fi PathFormat "$JAVA_HOME" - JAVA_HOME="$formatted_path_unix" + JAVA_HOME="$formatted_path" fi if test -z "$JAWTLIB" -a -n "$ENABLE_JAVA" -a "$_os" != Android -a \ @@ -10111,10 +10167,17 @@ case "$with_system_md4c" in AC_CHECK_HEADER([md4c.h], [], [AC_MSG_ERROR([md4c.h not found. Install system md4c.])]) + AC_CHECK_HEADER([md4c-html.h], [], + [AC_MSG_ERROR([md4c-html.h not found. Install system md4c.])]) + AC_CHECK_LIB([md4c], [md_parse], [ MD4C_LIBS="-lmd4c" MD4C_CFLAGS="" ], [ AC_MSG_ERROR([system md4c library not found or broken.]) ]) + + AC_CHECK_LIB([md4c-html], [md_html], + [ MD4C_LIBS="$MD4C_LIBS -lmd4c-html" ], + [ AC_MSG_ERROR([system md4c-html library not found or broken.]) ]) ;; ""|no) @@ -10600,7 +10663,7 @@ AC_SUBST(LIBXML_LIBS) AC_SUBST(XMLLINT) # ===================================================================== -# Checking for a Python interpreter with version >= 3.3 (or 3.7 if the build needs meson) +# Checking for a Python interpreter with version >= 3.11 # Optionally user can pass an option to configure, i. e. # ./configure PYTHON=/usr/bin/python # ===================================================================== @@ -10614,12 +10677,7 @@ if test "$build_os" != "cygwin" -a "$enable_python" != fully-internal; then PYTHON_FOR_BUILD=$PYTHON else # This allows a lack of system python with no error, we use internal one in that case. - if test "$with_system_harfbuzz" = "yes"; then - AM_PATH_PYTHON([3.3],, [:]) - else - # harfbuzz is built using meson, and current meson requires at least python 3.7 - AM_PATH_PYTHON([3.7],, [:]) - fi + AM_PATH_PYTHON([3.11],, [:]) # Clean PYTHON_VERSION checked below if cross-compiling PYTHON_VERSION="" if test "$PYTHON" != ":"; then @@ -10661,11 +10719,7 @@ no|disable) # we actually do check anew. AC_MSG_RESULT([]) unset PYTHON am_cv_pathless_PYTHON ac_cv_path_PYTHON am_cv_python_version am_cv_python_platform am_cv_python_pythondir am_cv_python_pyexecdir - if test -z "$NEED_MESON"; then - AM_PATH_PYTHON([3.3],, [:]) - else - AM_PATH_PYTHON([3.7],, [:]) - fi + AM_PATH_PYTHON([3.11],, [:]) AC_MSG_CHECKING([which Python to use for Pyuno]) if test "$PYTHON" = ":"; then if test -z "$PYTHON_FOR_BUILD"; then @@ -10713,12 +10767,8 @@ if test $enable_python = system; then unset PYTHON am_cv_pathless_PYTHON ac_cv_path_PYTHON am_cv_python_version am_cv_python_platform am_cv_python_pythondir am_cv_python_pyexecdir # This causes an error if no python command is found # the version found here also sets PYTHON_FOR_BUILD below, so the python picked here - # needs to be suitable for meson/the harfbuzz build - if test "$with_system_harfbuzz" = "yes" -o -n "$NEED_MESON" ; then - AM_PATH_PYTHON([3.7]) - else - AM_PATH_PYTHON([3.3]) - fi + # needs to be suitable for the build + AM_PATH_PYTHON([3.11]) python_include=`$PYTHON -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('INCLUDEPY'));"` python_version=`$PYTHON -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('VERSION'));"` python_libs=`$PYTHON -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LIBS'));"` @@ -10802,7 +10852,7 @@ if test \( "$cross_compiling" = yes -a -z "$PYTHON_FOR_BUILD" \) -o "$enable_pyt SYSTEM_PYTHON= PYTHON_VERSION_MAJOR=3 PYTHON_VERSION_MINOR=13 - PYTHON_VERSION=${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.12 + PYTHON_VERSION=${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.15 if ! grep -q -i python.*${PYTHON_VERSION} ${SRC_ROOT}/download.lst; then AC_MSG_ERROR([PYTHON_VERSION ${PYTHON_VERSION} but no matching file in download.lst]) fi @@ -10830,10 +10880,10 @@ system) #include int main(int argc, char **argv) { - if ((PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 3)) return 0; + if ((PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 11)) return 0; else return 1; } - ]])],[AC_MSG_RESULT([ok])],[AC_MSG_ERROR([Python >= 3.3 is needed when building with Python 3])],[AC_MSG_RESULT([skipped; cross-compiling])]) + ]])],[AC_MSG_RESULT([ok])],[AC_MSG_ERROR([Python >= 3.11 is needed when building with Python 3])],[AC_MSG_RESULT([skipped; cross-compiling])]) AC_LANG_POP(C) dnl FIXME Check if the Python library can be linked with, too? @@ -10863,6 +10913,31 @@ AC_SUBST(PYTHON_VERSION) AC_SUBST(PYTHON_VERSION_MAJOR) AC_SUBST(PYTHON_VERSION_MINOR) +AC_MSG_CHECKING([whether to enable QuickJS]) +if test "${enable_quickjs}" = "yes"; then + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([which QuickJS to use]) + if test "$with_system_quickjs" != "yes"; then + AC_MSG_RESULT([internal]) + BUILD_TYPE="${BUILD_TYPE} QUICKJS" + else + AC_MSG_RESULT([external]) + PKG_CHECK_MODULES([QUICKJS], [quickjs-ng], [], [ + PKG_CHECK_MODULES([QUICKJS], [qjs], []) + ]) + SYSTEM_QUICKJS=TRUE + fi + AC_DEFINE([ENABLE_QUICKJS],1) + ENABLE_QUICKJS="TRUE" +else + AC_MSG_RESULT([no]) + ENABLE_QUICKJS="" +fi +AC_SUBST(ENABLE_QUICKJS) +AC_SUBST(SYSTEM_QUICKJS) +AC_SUBST(QUICKJS_CFLAGS) +AC_SUBST(QUICKJS_LIBS) + AC_MSG_CHECKING([whether to build LibreLogo]) case "$enable_python" in no|disable) @@ -11261,6 +11336,12 @@ if test "$enable_firebird_sdbc" = "yes" ; then FIREBIRD_LIBS=`$FIREBIRDCONFIG --embedlibs` FilterLibs "${FIREBIRD_LIBS}" FIREBIRD_LIBS="${filteredlibs}" + dnl The directories chosen when firebird was built. A firebird patched to resolve them + dnl under the FIREBIRD variable instead needs to be told where its plugin modules and + dnl its international modules are. + FIREBIRD_CONFDIR=`$FIREBIRDCONFIG --confdir` + FIREBIRD_PLUGINSDIR=`$FIREBIRDCONFIG --pluginsdir` + FIREBIRD_INTLDIR=`$FIREBIRDCONFIG --intldir` fi AC_MSG_RESULT([includes `$FIREBIRD_CFLAGS', libraries `$FIREBIRD_LIBS']) AC_MSG_CHECKING([Firebird version]) @@ -11282,6 +11363,14 @@ int fb_api_is_30(void) { return 0; } #endif]])],AC_MSG_RESULT([OK]),AC_MSG_ERROR([Ensure firebird 3.0.x is installed])) CFLAGS="$save_CFLAGS" fi + if test -z "$FIREBIRD_PLUGINSDIR"; then + AC_MSG_WARN([Firebird plugins directory unknown, so a firebird that looks for its plugins + under the FIREBIRD variable cannot be told where they are, and will not open + a database. Install fb_config to get the directory.]) + fi + AC_DEFINE_UNQUOTED([SYSTEM_FIREBIRD_PLUGINS_DIRECTORY],["$FIREBIRD_PLUGINSDIR"]) + AC_DEFINE_UNQUOTED([SYSTEM_FIREBIRD_INTL_DIRECTORY],["$FIREBIRD_INTLDIR"]) + AC_DEFINE_UNQUOTED([SYSTEM_FIREBIRD_CONF_DIRECTORY],["$FIREBIRD_CONFDIR"]) ENABLE_FIREBIRD_SDBC=TRUE AC_DEFINE([ENABLE_FIREBIRD_SDBC],1) elif test "$enable_database_connectivity" = no; then @@ -11697,13 +11786,6 @@ AC_SUBST(SYSTEM_GENCMN) AC_SUBST(ICU_MAJOR) AC_SUBST(ICU_MINOR) -dnl ================================================================== -dnl CURL -dnl ================================================================== -if test "$enable_curl" = "yes"; then - AC_DEFINE([HAVE_FEATURE_CURL]) -fi - dnl ================================================================== dnl Breakpad dnl ================================================================== @@ -11761,10 +11843,34 @@ dnl FIXME by renaming SYSTEM_LIBORCUS to SYSTEM_ORCUS in the build system world SYSTEM_LIBORCUS=$SYSTEM_ORCUS AC_SUBST(SYSTEM_LIBORCUS) +AC_MSG_CHECKING([whether to enable the parquet filter]) +if test "$with_parquet_filter" = "yes"; then + AC_MSG_RESULT([yes]) + WITH_PARQUET_FILTER=TRUE + if test "$with_system_orcus" = "yes"; then + # FIXME: probably we should better check for it (orcus_parquet::detect() existing in the lib?) + # but I fail to do that with C++.. So let's do this for now... + AC_MSG_CHECKING([whether liborcus has parquet support]) + _orcus_so=`pkg-config --variable=libdir liborcus-0.21`/liborcus-0.21.so + if objdump -p $_orcus_so | grep NEEDED | grep -q parquet; then + AC_MSG_RESULT([yes]) + else + AC_MSG_ERROR([no. either build orcus with parquet support or use --disable-parquet-filter]) + fi + else + # will be checked in liborcus, too, but better fail early.. + PKG_CHECK_MODULES([PARQUET], [parquet]) + fi +else + AC_MSG_RESULT([no]) + WITH_PARQUET_FILTER= +fi +AC_SUBST(WITH_PARQUET_FILTER) + dnl =================================================================== dnl HarfBuzz dnl =================================================================== -harfbuzz_required_version=8.3.1 +harfbuzz_required_version=14.3.0 GRAPHITE_CFLAGS_internal="-I${WORKDIR}/UnpackedTarball/graphite/include -DGRAPHITE2_STATIC" HARFBUZZ_CFLAGS_internal="-I${WORKDIR}/UnpackedTarball/harfbuzz/src" @@ -12087,7 +12193,10 @@ if test "$with_system_zxcvbn" = "yes"; then AC_MSG_RESULT([external]) SYSTEM_ZXCVBN=TRUE AC_CHECK_HEADER(zxcvbn.h, [], - [ AC_MSG_ERROR(zxcvbn headers not found.)], []) + [ AC_CHECK_HEADER(zxcvbn/zxcvbn.h, + [ ZXCVBN_CFLAGS="-I/usr/include/zxcvbn" ], + [ AC_MSG_ERROR(zxcvbn headers not found.)], []) + ]) AC_CHECK_LIB(zxcvbn, ZxcvbnMatch, [], [ AC_MSG_ERROR(zxcvbn library not found.)], []) else @@ -12096,6 +12205,7 @@ else SYSTEM_ZXCVBN= fi AC_SUBST(SYSTEM_ZXCVBN) +AC_SUBST(ZXCVBN_CFLAGS) dnl =================================================================== dnl Check for system zxing @@ -12184,21 +12294,26 @@ dnl =================================================================== dnl Check for system box2d dnl =================================================================== AC_MSG_CHECKING([which box2d to use]) +BOX2D_MAJOR=3 +BOX2D_MINOR=1 if test "$with_system_box2d" = "yes"; then AC_MSG_RESULT([external]) SYSTEM_BOX2D=TRUE AC_LANG_PUSH([C++]) - AC_CHECK_HEADER(box2d/box2d.h, [BOX2D_H_FOUND='TRUE'], - [BOX2D_H_FOUND='FALSE']) - if test "$BOX2D_H_FOUND" = "TRUE"; then # 2.4.0+ - _BOX2D_LIB=box2d - AC_DEFINE(BOX2D_HEADER,) - else - # fail this. there's no other alternative to check when we are here. - AC_CHECK_HEADER([Box2D/Box2D.h], [], - [AC_MSG_ERROR(box2d headers not found.)]) - _BOX2D_LIB=Box2D - AC_DEFINE(BOX2D_HEADER,) + BOX2D_VERSION=`$PKG_CONFIG --modversion box2d 2>/dev/null` + BOX2D_MAJOR=`echo $BOX2D_VERSION | cut -d"." -f1` + BOX2D_MINOR=`echo $BOX2D_VERSION | cut -d"." -f2` + if test "$BOX2D_MAJOR" -eq "2"; then + if test "$BOX2D_MINOR" -eq "4"; then + _BOX2D_LIB=box2d + AC_DEFINE(BOX2D_HEADER,) + else + # fail this. there's no other alternative to check when we are here. + AC_CHECK_HEADER([Box2D/Box2D.h], [], + [AC_MSG_ERROR(box2d headers not found.)]) + _BOX2D_LIB=Box2D + AC_DEFINE(BOX2D_HEADER,) + fi fi AC_CHECK_LIB([$_BOX2D_LIB], [main], [:], [ AC_MSG_ERROR(box2d library not found.) ], []) @@ -12216,6 +12331,9 @@ AC_SUBST(SYSTEM_BOX2D) AC_SUBST(BOX2D_CFLAGS) AC_SUBST(BOX2D_LIBS) +AC_DEFINE_UNQUOTED(BOX2D_MAJOR,$BOX2D_MAJOR) +AC_DEFINE_UNQUOTED(BOX2D_MINOR,$BOX2D_MINOR) + dnl =================================================================== dnl Checking for altlinuxhyph dnl =================================================================== @@ -12316,64 +12434,6 @@ AC_SUBST(SYSTEM_COINMP) AC_SUBST(COINMP_CFLAGS) AC_SUBST(COINMP_LIBS) -ENABLE_LPSOLVE= -AC_MSG_CHECKING([whether to build with lpsolve]) -if test "$enable_lpsolve" != "no"; then - ENABLE_LPSOLVE=TRUE - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi -AC_SUBST(ENABLE_LPSOLVE) - -if test "$ENABLE_LPSOLVE" = TRUE; then - AC_MSG_CHECKING([which lpsolve to use]) - if test "$with_system_lpsolve" = "yes"; then - AC_MSG_RESULT([external]) - SYSTEM_LPSOLVE=TRUE - AC_CHECK_HEADER(lpsolve/lp_lib.h, [], - [ AC_MSG_ERROR(lpsolve headers not found.)], []) - save_LIBS=$LIBS - # some systems need this. Like Ubuntu... - AC_CHECK_LIB(m, floor) - AC_CHECK_LIB(dl, dlopen) - AC_CHECK_LIB([lpsolve55], [make_lp], [:], - [ AC_MSG_ERROR(lpsolve library not found or too old.)], []) - LIBS=$save_LIBS - else - AC_MSG_RESULT([internal]) - SYSTEM_LPSOLVE= - BUILD_TYPE="$BUILD_TYPE LPSOLVE" - AC_MSG_CHECKING([which colamd to use]) - if test "$with_system_colamd" = "yes"; then - AC_MSG_RESULT([external]) - SYSTEM_COLAMD=TRUE - # This assumes suitesparse, which has - # /usr/lib/x86_64-linux-gnu/pkgconfig/COLAMD.pc - PKG_CHECK_MODULES([COLAMD], [COLAMD], - [], - [ - # older versions don't. Look in /usr/include/suitesparse - COLAMD_CFLAGS=-I/usr/include/suitesparse - save_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $COLAMD_CFLAGS" - AC_CHECK_HEADER(colamd.h, [], - [ AC_MSG_ERROR(colamd.h header not found.)], []) - CFLAGS=$save_CFLAGS - AC_CHECK_LIB(colamd, colamd) - COLAMD_LIBS=-lcolamd - ]) - else - AC_MSG_RESULT([internal]) - SYSTEM_COLAMD= - fi - fi -fi -AC_SUBST(SYSTEM_COLAMD) -AC_SUBST(COLAMD_CFLAGS) -AC_SUBST(COLAMD_LIBS) -AC_SUBST(SYSTEM_LPSOLVE) - dnl =================================================================== dnl Checking for libexttextcat dnl =================================================================== @@ -13249,6 +13309,8 @@ if test \( "$ENABLE_SKIA" = TRUE -o "$ENABLE_PDFIUM" = TRUE \) -a "$COM_IS_CLANG AC_MSG_CHECKING([for clang-cl]) if test -x "$VC_PRODUCT_DIR/Tools/Llvm/bin/clang-cl.exe"; then LO_CLANG_CC=`win_short_path_for_make "$VC_PRODUCT_DIR/Tools/Llvm/bin/clang-cl.exe"` + elif test -x "$VC_PRODUCT_DIR/Tools/Llvm/$WIN_BUILD_ARCH/bin/clang-cl.exe"; then + LO_CLANG_CC=`win_short_path_for_make "$VC_PRODUCT_DIR/Tools/Llvm/$WIN_BUILD_ARCH/bin/clang-cl.exe"` elif test -n "$PROGRAMFILES" -a -x "$(cygpath -u "$PROGRAMFILES/LLVM/bin/clang-cl.exe")"; then LO_CLANG_CC=`win_short_path_for_make "$PROGRAMFILES/LLVM/bin/clang-cl.exe"` elif test -x "$(cygpath -u "c:/Program Files/LLVM/bin/clang-cl.exe")"; then @@ -13680,6 +13742,10 @@ AC_SUBST(LIBASSUAN_LIBS) AC_SUBST(GPGMEPP_CFLAGS) AC_SUBST(GPGMEPP_LIBS) +AC_ARG_WITH(parquet-filter, + AS_HELP_STRING([--with-parquet-filter], + [Enable the Parquet import filter.]),,) + AC_ARG_WITH(system-java-websocket, AS_HELP_STRING([--with-system-java-websocket], [Use Java-WebSocket already on system.]),, @@ -14157,7 +14223,7 @@ then dnl Check for qmake6 if test -n "$QT6DIR"; then - PathFormatUnix "$QT6DIR" + PathFormat "$QT6DIR" QT6DIR="${formatted_path_unix}" AC_PATH_PROG(QMAKE6, [qmake${qt6_executable_suffix}], no, [$QT6DIR/bin]) else @@ -14166,7 +14232,7 @@ then if test "$QMAKE6" = "no"; then AC_MSG_ERROR([Qmake not found. Please specify the root of your Qt6 installation by exporting QT6DIR before running "configure".]) else - qmake6_test_ver="`$QMAKE6 -v 2>&1 | $SED -n -e 's/^Using Qt version \(6\.[[0-9.]]\+\).*$/\1/p'`" + qmake6_test_ver="`$QMAKE6 -v 2>&1 | $SED -n -e 's/^Using Qt version \(6\..*\) in.*$/\1/p'`" if test -z "$qmake6_test_ver"; then AC_MSG_ERROR([Wrong qmake for Qt6 found. Please specify the root of your Qt6 installation by exporting QT6DIR before running "configure".]) fi @@ -14178,48 +14244,67 @@ then qt6_platformsdir="`$QMAKE6 -query QT_INSTALL_PLUGINS | tr -d '\r'`/platforms" QT6_PLATFORMS_SRCDIR="$qt6_platformsdir" - qt6_test_include="QtWidgets/qapplication.h" - AC_MSG_CHECKING([for Qt6 headers]) - qt6_incdir="no" - for inc_dir in $qt6_incdirs; do - PathFormatUnix "$inc_dir" - if test -r "${formatted_path_unix}/${qt6_test_include}"; then + # Look for Qt6 headers; on Mac we use the Qt framework that we find below, not + # a separate headers directory + if test "$_os" == "Darwin"; then + for inc_dir in $qt6_incdirs; do qt6_incdir="$inc_dir" break + done + else + qt6_test_include="QtWidgets/qapplication.h" + AC_MSG_CHECKING([for Qt6 headers]) + qt6_incdir="no" + for inc_dir in $qt6_incdirs; do + PathFormat "$inc_dir" + if test -r "${formatted_path_unix}/${qt6_test_include}"; then + qt6_incdir="$inc_dir" + break + fi + done + AC_MSG_RESULT([$qt6_incdir]) + if test "x$qt6_incdir" = "xno"; then + AC_MSG_ERROR([Qt6 headers not found. Please specify the root of your Qt6 installation by exporting QT6DIR before running "configure".]) fi - done - AC_MSG_RESULT([$qt6_incdir]) - if test "x$qt6_incdir" = "xno"; then - AC_MSG_ERROR([Qt6 headers not found. Please specify the root of your Qt6 installation by exporting QT6DIR before running "configure".]) - fi - # check for scenario: qt6-qtbase-devel-*.86_64 installed but host is i686 - AC_LANG_PUSH([C++]) - save_CPPFLAGS=$CPPFLAGS - CPPFLAGS="${CPPFLAGS} -I${qt6_incdir}" - AC_CHECK_HEADER(QtCore/qconfig.h, [], - [AC_MSG_ERROR(qconfig.h header not found.)], []) - CPPFLAGS=$save_CPPFLAGS - AC_LANG_POP([C++]) - if test "$_os" = "Emscripten"; then + # check for scenario: qt6-qtbase-devel-*.86_64 installed but host is i686 + AC_LANG_PUSH([C++]) + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="${CPPFLAGS} -I${qt6_incdir}" + AC_CHECK_HEADER(QtCore/qconfig.h, [], + [AC_MSG_ERROR(qconfig.h header not found.)], []) + CPPFLAGS=$save_CPPFLAGS + AC_LANG_POP([C++]) + fi + + qt6_test_library="Qt6Widgets" + case "$_os" in + Emscripten) qt6_library_prefix="lib" qt6_library_suffixes=".a" - elif test "$_os" = "WINNT"; then + ;; + WINNT) qt6_library_prefix="" # file names of libraries built in debug mode have an additional # "d" suffix in the file name, e.g. "Qt6Widgetsd.lib" qt6_library_suffixes=".lib d.lib" - else + ;; + Darwin) + qt6_library_prefix="" + qt6_library_suffixes=".framework" + qt6_test_library="QtWidgets" + ;; + *) qt6_library_prefix="lib" qt6_library_suffixes=".so" - fi + ;; + esac - qt6_test_library="Qt6Widgets" AC_MSG_CHECKING([for Qt6 libraries]) qt6_libdir="no" for lib_dir in $qt6_libdirs; do for suffix in $qt6_library_suffixes; do - PathFormatUnix "$lib_dir" + PathFormat "$lib_dir" if test -r ${formatted_path_unix}/${qt6_library_prefix}${qt6_test_library}${suffix}; then qt6_libdir="$lib_dir" qt6_library_suffix="$suffix" @@ -14231,6 +14316,7 @@ then if test "x$qt6_libdir" = "xno"; then AC_MSG_ERROR([Qt6 libraries not found. Please specify the root of your Qt6 installation by exporting QT6DIR before running "configure".]) fi + QT6_LIBDIR="${qt6_libdir}" if test "$_os" = "Emscripten"; then if test ! -f "$QT6_PLATFORMS_SRCDIR"/wasm_shell.html ; then @@ -14242,25 +14328,34 @@ then fi QT6_CFLAGS="-I$qt6_incdir -DQT_NO_VERSION_TAGGING" - QT6_CFLAGS=$(printf '%s' "$QT6_CFLAGS" | sed -e "s/-I/${ISYSTEM?}/g") if test "$_os" = "WINNT"; then QT6_LIBS="-LIBPATH:${qt6_libdir} Qt6Core${qt6_library_suffix} Qt6Gui${qt6_library_suffix} Qt6Widgets${qt6_library_suffix}" + elif test "$_os" = "Darwin"; then + QT6_LIBS="-F ${qt6_libdir} -framework QtCore -framework QtGui -framework QtWidgets -framework QtNetwork" + QT6_CFLAGS="${QT6_CFLAGS} -F ${qt6_libdir}" else QT6_LIBS="-L$qt6_libdir -lQt6Core -lQt6Gui -lQt6Widgets" fi + QT6_CFLAGS=$(printf '%s' "$QT6_CFLAGS" | sed -e "s/-I/${ISYSTEM?}/g") if test "$_os" = "Emscripten"; then QT6_LIBS="$QT6_LIBS -lQt6BundledPcre2 -lQt6BundledZLIB -L${qt6_platformsdir} -lqwasm -sGL_ENABLE_GET_PROC_ADDRESS" else if ! test "$enable_qt6_multimedia" = "no"; then - PathFormatUnix "${qt6_incdir}" - if ! test -r "${formatted_path_unix}/QtMultimediaWidgets/QVideoWidget"; then + qt6_mm_headerdir="${qt6_incdir}" + if test "$_os" = "Darwin"; then + qt6_mm_headerdir="${qt6_libdir}" + fi + format_header_path "${qt6_mm_headerdir}" "QtMultimediaWidgets" "QVideoWidget" + if ! test -r "${formatted_path_unix}"; then AC_MSG_ERROR([Qt 6 QMultimedia not found.]) break fi ENABLE_QT6_MULTIMEDIA=TRUE if test "$_os" = "WINNT"; then QT6_LIBS="$QT6_LIBS Qt6Multimedia${qt6_library_suffix} Qt6MultimediaWidgets${qt6_library_suffix}" + elif test "$_os" = "Darwin"; then + QT6_LIBS="$QT6_LIBS -framework QtMultimedia -framework QtMultimediaWidgets" else QT6_LIBS="$QT6_LIBS -lQt6Multimedia -lQt6MultimediaWidgets" fi @@ -14303,6 +14398,7 @@ the root of your Qt installation by exporting QT6DIR before running "configure". fi AC_SUBST(QT6_CFLAGS) AC_SUBST(QT6_LIBS) +AC_SUBST(QT6_LIBDIR) AC_SUBST(MOC6) AC_SUBST(QT6_PLATFORMS_SRCDIR) AC_SUBST(ENABLE_QT6_MULTIMEDIA) @@ -14554,24 +14650,17 @@ dnl =================================================================== dnl Test whether to include fonts dnl =================================================================== WITH_FONTS= -WITH_DOCREPAIR_FONTS= AC_MSG_CHECKING([whether to include third-party fonts]) if test "$with_fonts" != "no"; then AC_MSG_RESULT([yes]) WITH_FONTS=TRUE BUILD_TYPE="$BUILD_TYPE MORE_FONTS" AC_DEFINE(HAVE_MORE_FONTS) - AC_MSG_CHECKING([whether to include 'docrepair' fonts]) - if test "$with_docrepair_fonts" = "yes"; then - AC_MSG_RESULT([yes]) - WITH_DOCREPAIR_FONTS=TRUE - fi else AC_MSG_RESULT([no]) SCPDEFS="$SCPDEFS -DWITHOUT_FONTS" fi AC_SUBST(WITH_FONTS) -AC_SUBST(WITH_DOCREPAIR_FONTS) dnl =================================================================== dnl Test whether to enable online update service @@ -14977,6 +15066,16 @@ fi AC_SUBST(ENABLE_MSVC_ANALYZE) dnl =================================================================== +dnl Test whether to build libjxl or rely on the system version +dnl highway and brotli libraries are only built with internal libjxl +dnl =================================================================== + +if test "$with_system_libjxl" != "yes"; then + BUILD_TYPE="$BUILD_TYPE HIGHWAY BROTLI" +fi + +libo_CHECK_SYSTEM_MODULE([libjxl],[LIBJXL],[libjxl libjxl_threads]) + dnl Test whether to use liblangtag dnl =================================================================== SYSTEM_LIBLANGTAG= @@ -15186,7 +15285,8 @@ EOF AC_MSG_RESULT([Ant lib directory found.]) fi - ant_minver=1.6.0 + # reproducible builds need the modificationtime parameter for the jar task introduced in 1.10.2 + ant_minver=1.10.2 ant_minminor1=`echo $ant_minver | cut -d"." -f2` AC_MSG_CHECKING([whether Ant is >= $ant_minver]) @@ -15495,7 +15595,7 @@ dnl =================================================================== AC_MSG_CHECKING([for alternative branding images directory]) # initialize mapped arrays BRAND_INTRO_IMAGES="intro.png intro-highres.png" -brand_files="$BRAND_INTRO_IMAGES logo.svg logo_inverted.svg logo-sc.svg logo-sc_inverted.svg about.svg donationbackground.png donate1.png" +brand_files="$BRAND_INTRO_IMAGES logo.svg logo_inverted.svg logo-sc.svg logo-sc_inverted.svg about.svg donate1.png donate2.png" if test -z "$with_branding" -o "$with_branding" = "no"; then AC_MSG_RESULT([none]) @@ -16046,10 +16146,6 @@ if test "$enable_mpl_subset" = "yes"; then ENABLE_OPENGL_TRANSITIONS= - if test "$enable_lpsolve" != "no" -o "x$ENABLE_LPSOLVE" = "xTRUE"; then - mpl_error_string="$mpl_error_string$newline Need to --disable-lpsolve - calc linear programming solver." - fi - if test "x$mpl_error_string" != "x"; then AC_MSG_ERROR([$mpl_error_string]) fi @@ -16333,10 +16429,12 @@ else fi pathmunge "$WINDOWS_SDK_BINDIR_NO_ARCH/$WIN_BUILD_ARCH" "before" if test "$ENABLE_JAVA" != ""; then - if test -d "$JAVA_HOME/jre/bin/client"; then + PathFormat "$JAVA_HOME" + JAVA_HOME_unix="$formatted_path_unix" + if test -d "$JAVA_HOME_unix/jre/bin/client"; then pathmunge "$JAVA_HOME/jre/bin/client" "before" fi - if test -d "$JAVA_HOME/jre/bin/hotspot"; then + if test -d "$JAVA_HOME_unix/jre/bin/hotspot"; then pathmunge "$JAVA_HOME/jre/bin/hotspot" "before" fi pathmunge "$JAVA_HOME/bin" "before" @@ -16387,9 +16485,7 @@ if test -n "$WSL_ONLY_AS_HELPER"; then SRC_ROOT="$formatted_path" PathFormat "$BUILDDIR" BUILDDIR="$formatted_path" - # TARFILE_LOCATION and JAVAINTERPRETER are used in the validator scripts - PathFormat "$TARFILE_LOCATION" - TARFILE_LOCATION="$formatted_path" + # JAVAINTERPRETER is used in the validator scripts PathFormat "$JAVAINTERPRETER" JAVAINTERPRETER="$formatted_path" # git-bash has (gnu) tar, curl and sha256sum @@ -16415,6 +16511,8 @@ if test -n "$WSL_ONLY_AS_HELPER"; then mkdir -p tmp TEMP_DIRECTORY="$BUILDDIR/tmp" fi + # gnucp might be detected in the Linux container, force it to known cp.exe + GNUCP="cp.exe" fi # Keep in sync with list of files far up, at AC_MSG_CHECKING([for diff --git a/connectivity/CppunitTest_connectivity_commontools.mk b/connectivity/CppunitTest_connectivity_commontools.mk index 81dfe9e6861d..997cdf3a08ce 100644 --- a/connectivity/CppunitTest_connectivity_commontools.mk +++ b/connectivity/CppunitTest_connectivity_commontools.mk @@ -23,6 +23,8 @@ $(eval $(call gb_CppunitTest_use_sdk_api,connectivity_commontools)) $(eval $(call gb_CppunitTest_add_exception_objects,connectivity_commontools, \ connectivity/qa/connectivity/commontools/FValue_test \ + connectivity/qa/connectivity/commontools/DBTypeConversion_test \ + connectivity/qa/connectivity/commontools/SQLCommentTest \ )) $(eval $(call gb_CppunitTest_use_libraries,connectivity_commontools, \ @@ -35,6 +37,7 @@ $(eval $(call gb_CppunitTest_use_libraries,connectivity_commontools, \ $(eval $(call gb_CppunitTest_use_components,connectivity_commontools,\ configmgr/source/configmgr \ + i18npool/util/i18npool \ )) $(eval $(call gb_CppunitTest_use_configuration,connectivity_commontools)) diff --git a/connectivity/CppunitTest_connectivity_firebird_test.mk b/connectivity/CppunitTest_connectivity_firebird_test.mk new file mode 100644 index 000000000000..d056d93fee66 --- /dev/null +++ b/connectivity/CppunitTest_connectivity_firebird_test.mk @@ -0,0 +1,51 @@ +# -*- 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,connectivity_firebird_test)) + +$(eval $(call gb_CppunitTest_use_externals,connectivity_firebird_test,\ + boost_headers \ + libxml2 \ +)) + + +$(eval $(call gb_CppunitTest_add_exception_objects,connectivity_firebird_test, \ + connectivity/qa/connectivity/firebird/firebird \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,connectivity_firebird_test, \ + comphelper \ + cppu \ + cppuhelper \ + editeng \ + sal \ + sfx \ + subsequenttest \ + svl \ + test \ + tl \ + unotest \ + utl \ + vcl \ +)) + +$(eval $(call gb_CppunitTest_use_api,connectivity_firebird_test,\ + offapi \ + oovbaapi \ + udkapi \ +)) + +$(eval $(call gb_CppunitTest_use_ure,connectivity_firebird_test)) +$(eval $(call gb_CppunitTest_use_vcl,connectivity_firebird_test)) + +$(eval $(call gb_CppunitTest_use_rdb,connectivity_firebird_test,services)) + +$(eval $(call gb_CppunitTest_use_configuration,connectivity_firebird_test)) + +# vim: set noet sw=4 ts=4: diff --git a/connectivity/Module_connectivity.mk b/connectivity/Module_connectivity.mk index 3105945a6512..725a0663b1b7 100644 --- a/connectivity/Module_connectivity.mk +++ b/connectivity/Module_connectivity.mk @@ -22,7 +22,6 @@ $(eval $(call gb_Module_add_targets,connectivity,\ Configuration_flat \ Configuration_mysql_jdbc \ Configuration_odbc \ - Configuration_mysql_jdbc \ Configuration_writer \ Library_calc \ Library_dbase \ @@ -83,6 +82,12 @@ $(eval $(call gb_Module_add_targets,connectivity,\ Configuration_firebird \ Library_firebird_sdbc \ )) + +ifeq ($(SYSTEM_FIREBIRD),) +$(eval $(call gb_Module_add_check_targets,connectivity,\ + CppunitTest_connectivity_firebird_test \ +)) +endif endif ifeq ($(ENABLE_MARIADBC),TRUE) diff --git a/connectivity/qa/connectivity/commontools/DBTypeConversion_test.cxx b/connectivity/qa/connectivity/commontools/DBTypeConversion_test.cxx new file mode 100644 index 000000000000..a79369149a23 --- /dev/null +++ b/connectivity/qa/connectivity/commontools/DBTypeConversion_test.cxx @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * Unit tests for DBTypeConversion string-to-date/time/datetime conversions. + * + * These tests cover the fix for bug 153057: filtering on DATE, TIME and + * TIMESTAMP columns using a string value in the Firebird prepared statement. + * The fix added handling in OPreparedStatement::setString() for + * DataType::DATE, DataType::TIME and DataType::TIMESTAMP, relying on + * DBTypeConversion::toDate(), toTime() and toDateTime(). + */ + +#include + +#include +#include +#include +#include + +using namespace ::dbtools; +using namespace ::com::sun::star::util; + +namespace connectivity::commontools +{ +class DBTypeConversionTest : public test::BootstrapFixture +{ +public: + DBTypeConversionTest() + : test::BootstrapFixture(false, false) + { + } + + // toDate tests + void test_toDate_basic(); + void test_toDate_leading_zeros(); + void test_toDate_year_only(); + + // toTime tests + void test_toTime_basic(); + void test_toTime_with_seconds(); + void test_toTime_with_nanoseconds(); + + // toDateTime tests + void test_toDateTime_basic(); + void test_toDateTime_date_only(); + void test_toDateTime_with_nanoseconds(); + + CPPUNIT_TEST_SUITE(DBTypeConversionTest); + + CPPUNIT_TEST(test_toDate_basic); + CPPUNIT_TEST(test_toDate_leading_zeros); + CPPUNIT_TEST(test_toDate_year_only); + + CPPUNIT_TEST(test_toTime_basic); + CPPUNIT_TEST(test_toTime_with_seconds); + CPPUNIT_TEST(test_toTime_with_nanoseconds); + + CPPUNIT_TEST(test_toDateTime_basic); + CPPUNIT_TEST(test_toDateTime_date_only); + CPPUNIT_TEST(test_toDateTime_with_nanoseconds); + + CPPUNIT_TEST_SUITE_END(); +}; + +// ----- toDate --------------------------------------------------------------- + +void DBTypeConversionTest::test_toDate_basic() +{ + // SQL date format: YYYY-MM-DD + Date aDate = DBTypeConversion::toDate(u"2024-07-15"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Year", sal_Int16(2024), aDate.Year); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Month", sal_uInt16(7), aDate.Month); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Day", sal_uInt16(15), aDate.Day); +} + +void DBTypeConversionTest::test_toDate_leading_zeros() +{ + // Months and days with leading zeros must parse correctly + Date aDate = DBTypeConversion::toDate(u"2000-01-01"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Year", sal_Int16(2000), aDate.Year); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Month", sal_uInt16(1), aDate.Month); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Day", sal_uInt16(1), aDate.Day); +} + +void DBTypeConversionTest::test_toDate_year_only() +{ + // Only the year component present; month and day default to 0 + Date aDate = DBTypeConversion::toDate(u"1999"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Year", sal_Int16(1999), aDate.Year); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Month", sal_uInt16(0), aDate.Month); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Day", sal_uInt16(0), aDate.Day); +} + +// ----- toTime --------------------------------------------------------------- + +void DBTypeConversionTest::test_toTime_basic() +{ + // ISO 8601 time: HH:MM + Time aTime = DBTypeConversion::toTime(u"14:30"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Hours", sal_uInt16(14), aTime.Hours); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Minutes", sal_uInt16(30), aTime.Minutes); +} + +void DBTypeConversionTest::test_toTime_with_seconds() +{ + // ISO 8601 time: HH:MM:SS + Time aTime = DBTypeConversion::toTime(u"08:05:59"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Hours", sal_uInt16(8), aTime.Hours); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Minutes", sal_uInt16(5), aTime.Minutes); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Seconds", sal_uInt16(59), aTime.Seconds); +} + +void DBTypeConversionTest::test_toTime_with_nanoseconds() +{ + // ISO 8601 time with fractional seconds: HH:MM:SS.nnnnnnnnn + Time aTime = DBTypeConversion::toTime(u"10:20:30.123456789"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Hours", sal_uInt16(10), aTime.Hours); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Minutes", sal_uInt16(20), aTime.Minutes); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Seconds", sal_uInt16(30), aTime.Seconds); + CPPUNIT_ASSERT_EQUAL_MESSAGE("NanoSeconds", sal_uInt32(123456789), aTime.NanoSeconds); +} + +// ----- toDateTime ----------------------------------------------------------- + +void DBTypeConversionTest::test_toDateTime_basic() +{ + // SQL timestamp format: YYYY-MM-DD HH:MM:SS + DateTime aDT = DBTypeConversion::toDateTime(u"2024-03-21 11:45:00"_ustr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Year", sal_Int16(2024), aDT.Year); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Month", sal_uInt16(3), aDT.Month); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Day", sal_uInt16(21), aDT.Day); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Hours", sal_uInt16(11), aDT.Hours); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Minutes", sal_uInt16(45), aDT.Minutes); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Seconds", sal_uInt16(0), aDT.Seconds); +} + +void DBTypeConversionTest::test_toDateTime_date_only() +{ + // No time part: time fields default to 0 + DateTime aDT = DBTypeConversion::toDateTime(u"2023-12-31"_ustr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Year", sal_Int16(2023), aDT.Year); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Month", sal_uInt16(12), aDT.Month); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Day", sal_uInt16(31), aDT.Day); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Hours", sal_uInt16(0), aDT.Hours); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Minutes", sal_uInt16(0), aDT.Minutes); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Seconds", sal_uInt16(0), aDT.Seconds); +} + +void DBTypeConversionTest::test_toDateTime_with_nanoseconds() +{ + // Fractional seconds in the timestamp string + DateTime aDT = DBTypeConversion::toDateTime(u"2026-01-15 09:30:45.500000000"_ustr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Year", sal_Int16(2026), aDT.Year); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Month", sal_uInt16(1), aDT.Month); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Day", sal_uInt16(15), aDT.Day); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Hours", sal_uInt16(9), aDT.Hours); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Minutes", sal_uInt16(30), aDT.Minutes); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Seconds", sal_uInt16(45), aDT.Seconds); + CPPUNIT_ASSERT_EQUAL_MESSAGE("NanoSeconds", sal_uInt32(500000000), aDT.NanoSeconds); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(DBTypeConversionTest); + +} // namespace connectivity::commontools + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/qa/connectivity/commontools/SQLCommentTest.cxx b/connectivity/qa/connectivity/commontools/SQLCommentTest.cxx new file mode 100644 index 000000000000..b07115bcfc31 --- /dev/null +++ b/connectivity/qa/connectivity/commontools/SQLCommentTest.cxx @@ -0,0 +1,408 @@ +/* -*- 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/. + */ + +/** + * Unit tests for SQL comment handling in the connectivity SQL parser + * (OSQLParser / OSQLScanner / OSQLParseNode). + * + * These tests verify that the flex lexer correctly discards all three + * comment styles (-- line, slash-star block star-slash) so that OSQLParser::parseTree() + * succeeds and OSQLParseNode::parseNodeToStr() produces comment-free output. + * + */ + +#include + +#include +#include + +using namespace ::connectivity; + +namespace connectivity::commontools +{ +class SQLCommentTest : public test::BootstrapFixture +{ +public: + SQLCommentTest() + : test::BootstrapFixture(false, false) + { + } + + void setUp() override; + void tearDown() override; + + // -- line comment + void test_dashDash_inline_comment(); + void test_dashDash_comment_at_end_of_input_no_newline(); + void test_dashDash_comment_strips_from_output(); + + // /* block */ comment + void test_block_comment_inline(); + void test_block_comment_strips_from_output(); + void test_multiline_block_comment(); + + // -- in string literals must NOT be treated as a comment + void test_dashDash_inside_string_literal_not_comment(); + + // canonical equivalence: SQL with comment must serialise identically to SQL without + void test_canonical_dashDash_equals_plain(); + void test_canonical_block_equals_plain(); + + // comment in every syntactic position + void test_comment_between_select_and_columns(); + void test_comment_between_columns_and_from(); + void test_comment_in_where_clause(); + + // multiple and adjacent comments + void test_multiple_dashDash_comments(); + void test_mixed_comment_styles(); + + // edge cases + void test_empty_block_comment(); + void test_block_comment_containing_stars(); + void test_slashSlash_inside_string_literal_not_comment(); + + // "//" is not a valid comment; parser must reject it + void test_slashSlash_rejected(); + + // real comment + -- inside string literal in same statement + void test_real_comment_and_dashDash_in_literal_same_statement(); + + CPPUNIT_TEST_SUITE(SQLCommentTest); + + CPPUNIT_TEST(test_dashDash_inline_comment); + CPPUNIT_TEST(test_dashDash_comment_at_end_of_input_no_newline); + CPPUNIT_TEST(test_dashDash_comment_strips_from_output); + + CPPUNIT_TEST(test_block_comment_inline); + CPPUNIT_TEST(test_block_comment_strips_from_output); + CPPUNIT_TEST(test_multiline_block_comment); + + CPPUNIT_TEST(test_dashDash_inside_string_literal_not_comment); + + CPPUNIT_TEST(test_canonical_dashDash_equals_plain); + CPPUNIT_TEST(test_canonical_block_equals_plain); + + CPPUNIT_TEST(test_comment_between_select_and_columns); + CPPUNIT_TEST(test_comment_between_columns_and_from); + CPPUNIT_TEST(test_comment_in_where_clause); + + CPPUNIT_TEST(test_multiple_dashDash_comments); + CPPUNIT_TEST(test_mixed_comment_styles); + + CPPUNIT_TEST(test_empty_block_comment); + CPPUNIT_TEST(test_block_comment_containing_stars); + CPPUNIT_TEST(test_slashSlash_inside_string_literal_not_comment); + + CPPUNIT_TEST(test_slashSlash_rejected); + + CPPUNIT_TEST(test_real_comment_and_dashDash_in_literal_same_statement); + + CPPUNIT_TEST_SUITE_END(); + +private: + /** Count all nodes in the parse tree recursively. */ + static sal_uInt32 countNodes(const OSQLParseNode* pNode); + + std::unique_ptr m_pParser; +}; + +void SQLCommentTest::setUp() +{ + test::BootstrapFixture::setUp(); + // OSQLParser needs a service factory and locale; nullptr is acceptable for + // tests that only exercise comment stripping. + m_pParser = std::make_unique(getComponentContext()); +} + +void SQLCommentTest::tearDown() +{ + m_pParser.reset(); + test::BootstrapFixture::tearDown(); +} + +// Simple check, comments produce no AST nodes +// Workaround since we cannot connect a DB to the parser here + +sal_uInt32 SQLCommentTest::countNodes(const OSQLParseNode* pNode) +{ + if (!pNode) + return 0; + sal_uInt32 n = 1; + for (size_t i = 0; i < pNode->count(); ++i) + n += countNodes(pNode->getChild(i)); + return n; +} + +// --------------------------------------------------------------------------- +// -- line comment tests +// --------------------------------------------------------------------------- + +void SQLCommentTest::test_dashDash_inline_comment() +{ + // "-- comment\n" at end of a valid SQL statement must be consumed. + OUString sSQL(u"SELECT * FROM \"t\" -- inline comment\n"_ustr); + OUString sError; + std::unique_ptr pNode(m_pParser->parseTree(sError, sSQL)); + CPPUNIT_ASSERT_MESSAGE("parseTree() must succeed with a trailing -- comment", pNode != nullptr); +} + +void SQLCommentTest::test_dashDash_comment_at_end_of_input_no_newline() +{ + // just to be sure that he new flex rule for "--" works at end-of-input + // without a trailing newline + OUString sSQL(u"SELECT * FROM \"t\" --no newline at end"_ustr); + OUString sError; + std::unique_ptr pNode(m_pParser->parseTree(sError, sSQL)); + CPPUNIT_ASSERT_MESSAGE("parseTree() must succeed with -- comment at end-of-input (no newline)", + pNode != nullptr); +} + +void SQLCommentTest::test_dashDash_comment_strips_from_output() +{ + // After parsing, the parser must succeed (i.e. the comment was lexed out). + // Note: parseNodeToStr() needs a real DB connection and cannot be called + // with nullptr; parse success alone is proof the comment was consumed. + OUString sSQL(u"SELECT * FROM \"t\" -- strip me\n"_ustr); + OUString sError; + std::unique_ptr pNode(m_pParser->parseTree(sError, sSQL)); + CPPUNIT_ASSERT_MESSAGE("parseTree() must succeed (comment stripped by lexer)", + pNode != nullptr); + CPPUNIT_ASSERT_MESSAGE("No error message expected", sError.isEmpty()); +} + +// --------------------------------------------------------------------------- +// /* block */ comment tests +// --------------------------------------------------------------------------- + +void SQLCommentTest::test_block_comment_inline() +{ + OUString sSQL(u"SELECT /* block comment */ * FROM \"t\""_ustr); + OUString sError; + std::unique_ptr pNode(m_pParser->parseTree(sError, sSQL)); + CPPUNIT_ASSERT_MESSAGE("parseTree() must succeed with an inline /* comment */", + pNode != nullptr); +} + +void SQLCommentTest::test_block_comment_strips_from_output() +{ + OUString sSQL(u"SELECT /* strip me */ * FROM \"t\""_ustr); + OUString sError; + std::unique_ptr pNode(m_pParser->parseTree(sError, sSQL)); + CPPUNIT_ASSERT_MESSAGE("parseTree() must succeed (block comment consumed by lexer)", + pNode != nullptr); + CPPUNIT_ASSERT_MESSAGE("No error message expected", sError.isEmpty()); +} + +void SQLCommentTest::test_multiline_block_comment() +{ + // A block comment spanning multiple lines must be accepted. + OUString sSQL(u"SELECT /*\n multi\n line\n comment\n*/ * FROM \"t\""_ustr); + OUString sError; + std::unique_ptr pNode(m_pParser->parseTree(sError, sSQL)); + CPPUNIT_ASSERT_MESSAGE("parseTree() must succeed with a multi-line /* comment */", + pNode != nullptr); +} + +// --------------------------------------------------------------------------- +// -- inside a string literal is NOT a comment +// --------------------------------------------------------------------------- + +void SQLCommentTest::test_dashDash_inside_string_literal_not_comment() +{ + // The -- inside '...' must not be treated as a comment start. + // If it were, the parser would see a truncated WHERE clause and fail. + OUString sSQL(u"SELECT * FROM \"t\" WHERE \"c\" = 'a--b'"_ustr); + OUString sError; + std::unique_ptr pNode(m_pParser->parseTree(sError, sSQL)); + CPPUNIT_ASSERT_MESSAGE("Query with -- inside string literal must parse successfully", + pNode != nullptr); + CPPUNIT_ASSERT_MESSAGE("No error message expected", sError.isEmpty()); +} + +// --------------------------------------------------------------------------- +// SQL with comment should be the same as SQL without +// --------------------------------------------------------------------------- + +void SQLCommentTest::test_canonical_dashDash_equals_plain() +{ + // Comments produce no AST nodes. A statement with a trailing -- comment + // must parse to a tree with the same node count as the same statement + // without any comment. + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\""_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\" -- a comment\n"_ustr)); + CPPUNIT_ASSERT_MESSAGE("-- comment statement must parse", pWithComment != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("-- comment must not add AST nodes", countNodes(pPlain.get()), + countNodes(pWithComment.get())); +} + +void SQLCommentTest::test_canonical_block_equals_plain() +{ + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\""_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT /* mid-query comment */ * FROM \"t\""_ustr)); + CPPUNIT_ASSERT_MESSAGE("/* */ comment statement must parse", pWithComment != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("/* */ comment must not add AST nodes", countNodes(pPlain.get()), + countNodes(pWithComment.get())); +} + +// --------------------------------------------------------------------------- +// Comment in every syntactic position +// --------------------------------------------------------------------------- + +void SQLCommentTest::test_comment_between_select_and_columns() +{ + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\""_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT -- pick columns\n * FROM \"t\""_ustr)); + CPPUNIT_ASSERT_MESSAGE("Comment between SELECT and * must parse", pWithComment != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Comment between SELECT and * must not add AST nodes", + countNodes(pPlain.get()), countNodes(pWithComment.get())); +} + +void SQLCommentTest::test_comment_between_columns_and_from() +{ + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\""_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT * /* which table? */ FROM \"t\""_ustr)); + CPPUNIT_ASSERT_MESSAGE("Comment between * and FROM must parse", pWithComment != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Comment between * and FROM must not add AST nodes", + countNodes(pPlain.get()), countNodes(pWithComment.get())); +} + +void SQLCommentTest::test_comment_in_where_clause() +{ + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\" WHERE \"c\" = 1"_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\" WHERE /* filter */ \"c\" = 1"_ustr)); + CPPUNIT_ASSERT_MESSAGE("Comment inside WHERE clause must parse", pWithComment != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Comment inside WHERE clause must not add AST nodes", + countNodes(pPlain.get()), countNodes(pWithComment.get())); +} + +// --------------------------------------------------------------------------- +// Multiple and adjacent comments +// --------------------------------------------------------------------------- + +void SQLCommentTest::test_multiple_dashDash_comments() +{ + // Two consecutive line comments; each must be consumed independently. + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\""_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT * -- first\n-- second\nFROM \"t\""_ustr)); + CPPUNIT_ASSERT_MESSAGE("Adjacent -- comments must both parse", pWithComment != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Adjacent -- comments must not add AST nodes", + countNodes(pPlain.get()), countNodes(pWithComment.get())); +} + +void SQLCommentTest::test_mixed_comment_styles() +{ + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\""_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT /* A */ * -- B\nFROM \"t\""_ustr)); + CPPUNIT_ASSERT_MESSAGE("Mixed comment styles in one statement must parse", + pWithComment != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Mixed comment styles must not add AST nodes", + countNodes(pPlain.get()), countNodes(pWithComment.get())); +} + +// --------------------------------------------------------------------------- +// Edge cases +// --------------------------------------------------------------------------- + +void SQLCommentTest::test_empty_block_comment() +{ + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\""_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT /**/ * FROM \"t\""_ustr)); + CPPUNIT_ASSERT_MESSAGE("Empty /**/ comment must parse", pWithComment != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Empty /**/ comment must not add AST nodes", + countNodes(pPlain.get()), countNodes(pWithComment.get())); +} + +void SQLCommentTest::test_block_comment_containing_stars() +{ + // Interior stars must not prematurely close the block comment. + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\""_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT /* * not-end * */ * FROM \"t\""_ustr)); + CPPUNIT_ASSERT_MESSAGE("Block comment with interior stars must parse", pWithComment != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Block comment with interior stars must not add AST nodes", + countNodes(pPlain.get()), countNodes(pWithComment.get())); +} + +void SQLCommentTest::test_slashSlash_inside_string_literal_not_comment() +{ + // // inside a quoted string must not start a line comment. + OUString sSQL(u"SELECT * FROM \"t\" WHERE \"c\" = 'http://example.com'"_ustr); + OUString sError; + std::unique_ptr pNode(m_pParser->parseTree(sError, sSQL)); + CPPUNIT_ASSERT_MESSAGE("// inside string literal must not be treated as comment", + pNode != nullptr); + CPPUNIT_ASSERT_MESSAGE("No error message expected", sError.isEmpty()); +} + +// --------------------------------------------------------------------------- +// // is not a comment — parser must reject it +// --------------------------------------------------------------------------- + +void SQLCommentTest::test_slashSlash_rejected() +{ + // "//" is not valid SQL comment syntax; the parser must reject it. + OUString sSQL(u"SELECT * FROM \"t\" // not a comment\n"_ustr); + OUString sError; + std::unique_ptr pNode(m_pParser->parseTree(sError, sSQL)); + CPPUNIT_ASSERT_MESSAGE("parseTree() must fail when // appears outside a string", + pNode == nullptr); +} + +// --------------------------------------------------------------------------- +// real comment + -- inside string literal in same statement +// --------------------------------------------------------------------------- + +void SQLCommentTest::test_real_comment_and_dashDash_in_literal_same_statement() +{ + OUString sError; + std::unique_ptr pPlain( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\" WHERE \"c\" = 'a--b'"_ustr)); + std::unique_ptr pWithComment( + m_pParser->parseTree(sError, u"SELECT * FROM \"t\" -- comment\nWHERE \"c\" = 'a--b'"_ustr)); + CPPUNIT_ASSERT_MESSAGE( + "Real -- comment combined with -- inside string literal must parse correctly", + pWithComment != nullptr); + CPPUNIT_ASSERT_MESSAGE("No error expected", sError.isEmpty()); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Real -- comment must not add AST nodes (-- in literal is not a comment)", + countNodes(pPlain.get()), countNodes(pWithComment.get())); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(SQLCommentTest); + +} // namespace connectivity::commontools + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/qa/connectivity/firebird/firebird.cxx b/connectivity/qa/connectivity/firebird/firebird.cxx new file mode 100644 index 000000000000..5dc491d6fa6f --- /dev/null +++ b/connectivity/qa/connectivity/firebird/firebird.cxx @@ -0,0 +1,93 @@ +/* -*- 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +class FirebirdTestDriver : public UnoApiTest +{ +private: + Reference m_xFirebirdComponent; + Reference m_xDriver; + Sequence m_infos; + +public: + FirebirdTestDriver() + : UnoApiTest(u"/connectivity/qa/connectivity/firebird/data"_ustr) + { + } + virtual void setUp() override; + void testDBConnection(); + + CPPUNIT_TEST_SUITE(FirebirdTestDriver); + CPPUNIT_TEST(testDBConnection); + CPPUNIT_TEST_SUITE_END(); +}; + +void FirebirdTestDriver::setUp() +{ + UnoApiTest::setUp(); + + m_xFirebirdComponent + = getMultiServiceFactory()->createInstance(u"com.sun.star.comp.sdbc.firebird.Driver"_ustr); + CPPUNIT_ASSERT_MESSAGE("no firebird component!", m_xFirebirdComponent.is()); + + m_xDriver.set(m_xFirebirdComponent, UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE("cannot connect to firebird driver!", m_xDriver.is()); +} + +void FirebirdTestDriver::testDBConnection() +{ + // Use existing database inside the firebird tarball + const OUString sDocPath( + m_directories.getURLFromWorkdir(u"/UnpackedTarball/firebird/gen/examples/employee.fdb")); + + // and create a copy of it + auto const e = osl::File::copy(sDocPath, maTempFile.GetURL()); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); + + Reference xConnection + = m_xDriver->connect("sdbc:firebird:" + maTempFile.GetURL(), m_infos); + CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is()); + + uno::Reference xStatement = xConnection->createStatement(); + CPPUNIT_ASSERT(xStatement.is()); + + uno::Reference xRes + = xStatement->executeQuery(u"SELECT COUNTRY, CURRENCY FROM COUNTRY ORDER BY COUNTRY"_ustr); + uno::Reference xRow(xRes, UNO_QUERY_THROW); + + // assert first row + CPPUNIT_ASSERT(xRes->next()); + CPPUNIT_ASSERT_EQUAL(u"Australia"_ustr, xRow->getString(1)); + CPPUNIT_ASSERT_EQUAL(u"ADollar"_ustr, xRow->getString(2)); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(FirebirdTestDriver); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/qa/connectivity/mysql/mysql.cxx b/connectivity/qa/connectivity/mysql/mysql.cxx index 3f1c1805ba51..9fc09cc76dfb 100644 --- a/connectivity/qa/connectivity/mysql/mysql.cxx +++ b/connectivity/qa/connectivity/mysql/mysql.cxx @@ -20,6 +20,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -29,6 +34,8 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::sdb; using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; @@ -57,6 +64,7 @@ public: void testNumericConversionPrepared(); void testPreparedStmtIsAfterLast(); void testGetStringFromBlobColumn(); + void testTdf149434DottedDatabaseName(); CPPUNIT_TEST_SUITE(MysqlTestDriver); CPPUNIT_TEST(testDBConnection); @@ -69,6 +77,7 @@ public: CPPUNIT_TEST(testNumericConversionPrepared); CPPUNIT_TEST(testPreparedStmtIsAfterLast); CPPUNIT_TEST(testGetStringFromBlobColumn); + CPPUNIT_TEST(testTdf149434DottedDatabaseName); CPPUNIT_TEST_SUITE_END(); }; @@ -82,6 +91,7 @@ void MysqlTestDriver::tearDown() CPPUNIT_ASSERT(xStatement.is()); xStatement->executeUpdate(u"DROP TABLE IF EXISTS myTestTable"_ustr); xStatement->executeUpdate(u"DROP TABLE IF EXISTS otherTable"_ustr); + xStatement->executeUpdate(u"DROP DATABASE IF EXISTS `tdf149434.test.schema`"_ustr); } test::BootstrapFixture::tearDown(); } @@ -512,6 +522,55 @@ void MysqlTestDriver::testGetStringFromBlobColumn() xStatement->executeUpdate(u"DROP TABLE IF EXISTS myTestTable"_ustr); } +void MysqlTestDriver::testTdf149434DottedDatabaseName() +{ + if (m_sUrl.isEmpty()) + return; + + // Retrieve connection and create sql statement + Reference xConnection = m_xDriver->connect(m_sUrl, m_infos); + CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is()); + uno::Reference xStatement = xConnection->createStatement(); + CPPUNIT_ASSERT(xStatement.is()); + + // Drop and create database using dots in its name including a test table + static constexpr OUString sDottedSchema = u"tdf149434.test.schema"_ustr; + xStatement->executeUpdate("DROP DATABASE IF EXISTS `" + sDottedSchema + "`"); + xStatement->executeUpdate("CREATE DATABASE `" + sDottedSchema + "`"); + xStatement->executeUpdate("CREATE TABLE `" + sDottedSchema + + "`.tdf149434TestTable (id INTEGER PRIMARY KEY)"); + + // Retrieve table definition using the composed name + Reference xDDSupplier(m_xDriver, UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE("driver does not support XDataDefinitionSupplier", xDDSupplier.is()); + Reference xTablesSupplier + = xDDSupplier->getDataDefinitionByConnection(xConnection); + CPPUNIT_ASSERT_MESSAGE("cannot get tables supplier", xTablesSupplier.is()); + Reference xTables = xTablesSupplier->getTables(); + CPPUNIT_ASSERT_MESSAGE("cannot get tables container", xTables.is()); + OUString sComposedName = sDottedSchema + ".tdf149434TestTable"; + CPPUNIT_ASSERT_MESSAGE("dotted-schema table not found in tables container", + xTables->hasByName(sComposedName)); + + // Without the fix in place, this test would have failed with + // - An uncaught exception of type com.sun.star.container.NoSuchElementException + // i.e. the composed name was split at the first instead of the last dot + uno::Any aTable; + CPPUNIT_ASSERT_NO_THROW(aTable = xTables->getByName(sComposedName)); + + Reference xNamed(aTable, UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE("table object does not implement XNamed", xNamed.is()); + CPPUNIT_ASSERT_EQUAL(u"tdf149434TestTable"_ustr, xNamed->getName()); + + Reference xTableProps(aTable, UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE("table object does not implement XPropertySet", xTableProps.is()); + OUString sSchemaName; + xTableProps->getPropertyValue(u"SchemaName"_ustr) >>= sSchemaName; + CPPUNIT_ASSERT_EQUAL(sDottedSchema, sSchemaName); + + xStatement->executeUpdate("DROP DATABASE `" + sDottedSchema + "`"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(MysqlTestDriver); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/connectivity/source/commontools/DriversConfig.cxx b/connectivity/source/commontools/DriversConfig.cxx index fac2feb872ed..a823dcca0d05 100644 --- a/connectivity/source/commontools/DriversConfig.cxx +++ b/connectivity/source/commontools/DriversConfig.cxx @@ -93,7 +93,7 @@ const TInstalledDrivers& DriversConfigImpl::getInstalledDrivers(const uno::Refer if ( !m_aInstalled.isValid() ) { m_aInstalled = ::utl::OConfigurationTreeRoot::createWithComponentContext(_rxORB, - u"org.openoffice.Office.DataAccess.Drivers/Installed"_ustr, -1, ::utl::OConfigurationTreeRoot::CM_READONLY); + u"org.openoffice.Office.DataAccess.Drivers/Installed"_ustr, ::utl::OConfigurationTreeRoot::CM_READONLY); } if ( m_aInstalled.isValid() ) diff --git a/connectivity/source/commontools/FDatabaseMetaDataResultSet.cxx b/connectivity/source/commontools/FDatabaseMetaDataResultSet.cxx index 69d868c9bb40..20e959b29cbd 100644 --- a/connectivity/source/commontools/FDatabaseMetaDataResultSet.cxx +++ b/connectivity/source/commontools/FDatabaseMetaDataResultSet.cxx @@ -22,8 +22,6 @@ #include #include #include -#include -#include #include #include #include @@ -102,7 +100,7 @@ void ODatabaseMetaDataResultSet::setType(MetaDataResultSetType _eType) void ODatabaseMetaDataResultSet::disposing(std::unique_lock& rGuard) { - OPropertySetHelper::disposing(rGuard); + disposePropertySetListeners(rGuard); m_xMetaData.clear(); m_aRowsIter = m_aRows.end(); @@ -110,31 +108,6 @@ void ODatabaseMetaDataResultSet::disposing(std::unique_lock& rGuard) m_aRowsIter = m_aRows.end(); } -void SAL_CALL ODatabaseMetaDataResultSet::acquire() noexcept -{ - ODatabaseMetaDataResultSet_BASE::acquire(); -} - -void SAL_CALL ODatabaseMetaDataResultSet::release() noexcept -{ - ODatabaseMetaDataResultSet_BASE::release(); -} - -Any SAL_CALL ODatabaseMetaDataResultSet::queryInterface( const Type & rType ) -{ - Any aRet = OPropertySetHelper::queryInterface(rType); - return aRet.hasValue() ? aRet : ODatabaseMetaDataResultSet_BASE::queryInterface(rType); -} - -Sequence< Type > SAL_CALL ODatabaseMetaDataResultSet::getTypes( ) -{ - ::cppu::OTypeCollection aTypes( cppu::UnoType::get(), - cppu::UnoType::get(), - cppu::UnoType::get()); - - return ::comphelper::concatSequences(aTypes.getTypes(),ODatabaseMetaDataResultSet_BASE::getTypes()); -} - void ODatabaseMetaDataResultSet::setRows(ORows&& _rRows) { m_aRows = std::move(_rRows); @@ -466,11 +439,6 @@ Any SAL_CALL ODatabaseMetaDataResultSet::getWarnings( ) return new ::cppu::OPropertyArrayHelper(aProps); } -::cppu::IPropertyArrayHelper & ODatabaseMetaDataResultSet::getInfoHelper() -{ - return *getArrayHelper(); -} - void ODatabaseMetaDataResultSet::setProceduresMap() { m_xMetaData = new ODatabaseMetaDataResultSetMetaData(); @@ -579,11 +547,6 @@ void ODatabaseMetaDataResultSet::setImportedKeysMap() m_xMetaData->setImportedKeysMap(); } -Reference< css::beans::XPropertySetInfo > SAL_CALL ODatabaseMetaDataResultSet::getPropertySetInfo( ) -{ - return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); -} - ORowSetValueDecorator& ORowSetValueDecorator::operator=(const ORowSetValue& _aValue) { m_aValue = _aValue; diff --git a/connectivity/source/commontools/TKeyColumns.cxx b/connectivity/source/commontools/TKeyColumns.cxx index 341e130df134..b59211ac9e25 100644 --- a/connectivity/source/commontools/TKeyColumns.cxx +++ b/connectivity/source/commontools/TKeyColumns.cxx @@ -70,7 +70,7 @@ css::uno::Reference< css::beans::XPropertySet > OKeyColumnsHelper::createObject( } } - // now describe the column _rName and set his related column + // now describe the column _rName and set its related column xResult = m_pKey->getTable()->getMetaData()->getColumns(Catalog, aSchema, aTable, _rName); if ( !xResult.is() ) diff --git a/connectivity/source/commontools/TTableHelper.cxx b/connectivity/source/commontools/TTableHelper.cxx index 0eb0c1e70260..6424805147ee 100644 --- a/connectivity/source/commontools/TTableHelper.cxx +++ b/connectivity/source/commontools/TTableHelper.cxx @@ -79,7 +79,7 @@ public: OUString sName; Event.Accessor >>= sName; - if ( m_aRefNames.find(sName) != m_aRefNames.end() ) + if ( m_aRefNames.contains(sName) ) m_pComponent->refreshKeys(); } virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override @@ -87,7 +87,7 @@ public: OUString sOldComposedName,sNewComposedName; Event.ReplacedElement >>= sOldComposedName; Event.Accessor >>= sNewComposedName; - if ( sOldComposedName != sNewComposedName && m_aRefNames.find(sOldComposedName) != m_aRefNames.end() ) + if ( sOldComposedName != sNewComposedName && m_aRefNames.contains(sOldComposedName) ) m_pComponent->refreshKeys(); } // XEventListener diff --git a/connectivity/source/commontools/dbtools.cxx b/connectivity/source/commontools/dbtools.cxx index 391377601b15..17977eeabb67 100644 --- a/connectivity/source/commontools/dbtools.cxx +++ b/connectivity/source/commontools/dbtools.cxx @@ -458,7 +458,7 @@ static SharedConnection lcl_connectRowSet(const Reference< XRowSet>& _rxRowSet, } catch(Exception&) { - TOOLS_WARN_EXCEPTION( "connectivity.commontools", "EXception when we set the new active connection!"); + TOOLS_WARN_EXCEPTION( "connectivity.commontools", "Exception when we set the new active connection!"); } } } @@ -895,7 +895,8 @@ void qualifiedNameComponents(const Reference< XDatabaseMetaData >& _rxConnMetaDa if ( aNameComps.bSchemas ) { - sal_Int32 nIndex = sName.indexOf('.'); + // tdf#149434 - use the last separator as table names cannot contain dots + sal_Int32 nIndex = sName.lastIndexOf('.'); // OSL_ENSURE(-1 != nIndex, "QualifiedNameComponents: no schema separator!"); if ( nIndex != -1 ) _rSchema = sName.copy(0, nIndex); @@ -1991,7 +1992,7 @@ OSQLColumns::const_iterator find(OSQLColumns::const_iterator first, namespace dbase { - bool dbfDecodeCharset(rtl_TextEncoding &_out_encoding, sal_uInt8 nType, sal_uInt8 nCodepage) + bool dbfDecodeEncoding(rtl_TextEncoding &_out_encoding, sal_uInt8 nType, sal_uInt8 nCodepage) { switch (nType) { @@ -2054,7 +2055,7 @@ namespace dbase return false; } - bool dbfReadCharset(rtl_TextEncoding &nCharSet, SvStream* dbf_Stream) + bool dbfReadEncoding(rtl_TextEncoding &nCharSet, SvStream* dbf_Stream) { sal_uInt8 nType=0; dbf_Stream->ReadUChar( nType ); @@ -2068,7 +2069,7 @@ namespace dbase { sal_uInt8 nEncoding=0; dbf_Stream->ReadUChar( nEncoding ); - return dbfDecodeCharset(nCharSet, nType, nEncoding); + return dbfDecodeEncoding(nCharSet, nType, nEncoding); } } diff --git a/connectivity/source/commontools/dbtools2.cxx b/connectivity/source/commontools/dbtools2.cxx index 3fe9bc5b6a34..55a4833dcea3 100644 --- a/connectivity/source/commontools/dbtools2.cxx +++ b/connectivity/source/commontools/dbtools2.cxx @@ -936,7 +936,7 @@ sal_Int32 DBTypeConversion::convertUnicodeStringToLength( const OUString& _rSour OUString getDefaultReportEngineServiceName(const Reference< XComponentContext >& _rxORB) { ::utl::OConfigurationTreeRoot aReportEngines = ::utl::OConfigurationTreeRoot::createWithComponentContext( - _rxORB, u"org.openoffice.Office.DataAccess/ReportEngines"_ustr, -1, ::utl::OConfigurationTreeRoot::CM_READONLY); + _rxORB, u"org.openoffice.Office.DataAccess/ReportEngines"_ustr, ::utl::OConfigurationTreeRoot::CM_READONLY); if ( aReportEngines.isValid() ) { diff --git a/connectivity/source/drivers/ado/AKeys.cxx b/connectivity/source/drivers/ado/AKeys.cxx index caf7eda5a391..529aadd341af 100644 --- a/connectivity/source/drivers/ado/AKeys.cxx +++ b/connectivity/source/drivers/ado/AKeys.cxx @@ -79,7 +79,7 @@ css::uno::Reference< css::beans::XPropertySet > OKeys::appendObject( const OUStr vOptional)) ) { ADOS::ThrowException(m_pConnection->getConnection(),static_cast(this)); - // just make sure that an SQLExceptionis thrown here + // just make sure that an SQLException is thrown here m_pConnection->throwGenericSQLException( STR_INVALID_KEY_DESCRIPTOR_ERROR,static_cast(this) ); } diff --git a/connectivity/source/drivers/dbase/DIndex.cxx b/connectivity/source/drivers/dbase/DIndex.cxx index 35a4087c0482..8db48b3cf2ad 100644 --- a/connectivity/source/drivers/dbase/DIndex.cxx +++ b/connectivity/source/drivers/dbase/DIndex.cxx @@ -34,6 +34,8 @@ #include #include +#include + using namespace ::comphelper; using namespace connectivity; @@ -324,6 +326,11 @@ void connectivity::dbase::ReadHeader( rStream.ReadUChar(rHeader.db_unique); rStream.ReadBytes(&rHeader.db_name, 488); assert(rStream.GetError() || rStream.Tell() == nOldPos + DINDEX_PAGE_SIZE); + + // a page starts with a four byte key count and a four byte child page id, then a record id, a + // key and a child page id per key + const sal_uInt16 nKeysThatFitAPage = (DINDEX_PAGE_SIZE - 8) / (8 + rHeader.db_keylen); + rHeader.db_maxkeys = std::max(1, std::min(rHeader.db_maxkeys, nKeysThatFitAPage)); } SvStream& connectivity::dbase::operator >> (SvStream &rStream, ODbaseIndex& rIndex) @@ -518,7 +525,7 @@ void ODbaseIndex::CreateImpl() m_aHeader.db_keytype = (nType == DataType::VARCHAR || nType == DataType::CHAR) ? 0 : 1; m_aHeader.db_keylen = (m_aHeader.db_keytype) ? 8 : static_cast(getINT32(xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)))); m_aHeader.db_keylen = (( m_aHeader.db_keylen - 1) / 4 + 1) * 4; - m_aHeader.db_maxkeys = (DINDEX_PAGE_SIZE - 4) / (8 + m_aHeader.db_keylen); + m_aHeader.db_maxkeys = (DINDEX_PAGE_SIZE - 8) / (8 + m_aHeader.db_keylen); if ( m_aHeader.db_maxkeys < 3 ) { impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_KEYSIZE,sFile); @@ -547,7 +554,7 @@ void ODbaseIndex::CreateImpl() if(xSet->last()) { ODbaseResultSet* pDbaseRes = dynamic_cast(xSet.getTyped().get()); - assert(pDbaseRes); //"No dbase resultset found? What's going on here! + assert(pDbaseRes); // No dbase resultset found? What's going on here! nRowsLeft = xSet->getRow(); xSet->beforeFirst(); diff --git a/connectivity/source/drivers/dbase/DTable.cxx b/connectivity/source/drivers/dbase/DTable.cxx index 3182ba67f5fc..c41350b57816 100644 --- a/connectivity/source/drivers/dbase/DTable.cxx +++ b/connectivity/source/drivers/dbase/DTable.cxx @@ -254,7 +254,7 @@ void ODbaseTable::readHeader() case FoxProMemo: m_pFileStream->SetEndian(SvStreamEndian::LITTLE); if( getConnection()->isTextEncodingDefaulted() && - !dbfDecodeCharset(m_eEncoding, nType, m_aHeader.trailer[17])) + !dbfDecodeEncoding(m_eEncoding, nType, m_aHeader.trailer[17])) { m_eEncoding = RTL_TEXTENCODING_IBM_850; } @@ -361,7 +361,7 @@ void ODbaseTable::fillColumns() aTypeName = "NUMERIC"; eType = DataType::DECIMAL; - // for numeric fields two characters more are written, then the precision of the column description predescribes, + // for numeric fields two characters more are written, then the precision of the column description prescribes, // to keep room for the possible sign and the comma. This has to be considered... nPrecision = SvDbaseConverter::ConvertPrecisionToOdbc(nPrecision,aDBFColumn.db_dez); // This is not true for older versions... @@ -1651,7 +1651,7 @@ bool ODbaseTable::UpdateBuffer(OValueRefVector& rRow, const OValueRefRow& pOrgRo ::comphelper::UStringMixEqual aCase(isCaseSensitive()); Reference xColumns(m_xColumns.get()); - // first search a key that exist already in the table + // first search a key that exists already in the table for (sal_Int32 i = 0; i < nColumnCount; ++i) { sal_Int32 nPos = i; @@ -2519,7 +2519,7 @@ void ODbaseTable::copyData(ODbaseTable* _pNewTable,sal_Int32 _nPos) { OSL_ASSERT(false); } - } // for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.db_anz;++nRowPos) + } // for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.nbRecords;++nRowPos) } void ODbaseTable::throwInvalidDbaseFormat() diff --git a/connectivity/source/drivers/dbase/dindexnode.cxx b/connectivity/source/drivers/dbase/dindexnode.cxx index 1b070b1aace1..7d52ddf6b05e 100644 --- a/connectivity/source/drivers/dbase/dindexnode.cxx +++ b/connectivity/source/drivers/dbase/dindexnode.cxx @@ -74,8 +74,8 @@ ONDXPage::ONDXPage(ODbaseIndex& rInd, sal_uInt32 nPos, ONDXPage* pParent) , aParent(pParent) , rIndex(rInd) { - sal_uInt16 nT = rIndex.getHeader().db_maxkeys; - ppNodes.reset( new ONDXNode[nT] ); + nNodeCapacity = std::max(1, rIndex.getHeader().db_maxkeys); + ppNodes.reset( new ONDXNode[nNodeCapacity] ); } ONDXPage::~ONDXPage() @@ -103,7 +103,7 @@ void ONDXPage::QueryDelete() if (aChild.Is()) aChild->Release(false); - for (sal_uInt16 i = 0; i < rIndex.getHeader().db_maxkeys;i++) + for (sal_uInt16 i = 0; i < nNodeCapacity;i++) { if (ppNodes[i].GetChild().Is()) ppNodes[i].GetChild()->Release(false); @@ -126,11 +126,30 @@ void ONDXPage::QueryDelete() } } +// true when the page is already somewhere on the chain of parents, so that loading it would +// descend into a page the descent is already inside +static bool lcl_isOnTheParentChain(sal_uInt32 nPagePos, const ONDXPage* pPage) +{ + for (const ONDXPage* p = pPage; p; p = p->GetParent()) + { + if (p->GetPagePos() == nPagePos) + return true; + } + return false; +} + ONDXPagePtr& ONDXPage::GetChild(ODbaseIndex const * pIndex) { if (!aChild.Is() && pIndex) { - aChild = rIndex.CreatePage(aChild.GetPagePos(),this,aChild.HasPage()); + const bool bLoad = aChild.HasPage(); + if (bLoad && lcl_isOnTheParentChain(aChild.GetPagePos(), this)) + { + SAL_WARN("connectivity.dbase", "page " << aChild.GetPagePos() + << " is its own ancestor, so it is left unread"); + } + else + aChild = rIndex.CreatePage(aChild.GetPagePos(),this,bLoad); } return aChild; } @@ -150,7 +169,7 @@ sal_uInt16 ONDXPage::FindPos(const ONDXKey& rKey) const bool ONDXPage::Find(const ONDXKey& rKey) { // searches the given key - // Speciality: At the end of the method + // Specialty: At the end of the method // the actual page and the position of the node, fulfilling the '<=' condition, are saved // This is considered at insert. sal_uInt16 i = 0; @@ -307,7 +326,7 @@ bool ONDXPage::Insert(ONDXNode& rNode, sal_uInt32 nRowsLeft) bool ONDXPage::Insert(sal_uInt16 nPos, ONDXNode& rNode) { - sal_uInt16 nMaxCount = rIndex.getHeader().db_maxkeys; + sal_uInt16 nMaxCount = nNodeCapacity; if (nPos >= nMaxCount) return false; @@ -352,7 +371,7 @@ void ONDXPage::Release(bool bSave) // free pointer aChild.Clear(); - for (sal_uInt16 i = 0; i < rIndex.getHeader().db_maxkeys;i++) + for (sal_uInt16 i = 0; i < nNodeCapacity;i++) { if (ppNodes[i].GetChild()) ppNodes[i].GetChild()->Release(bSave); @@ -482,6 +501,8 @@ void ONDXPage::Merge(sal_uInt16 nParentNodePos, const ONDXPagePtr& xPage) { DBG_ASSERT(HasParent(), "no parent existing"); DBG_ASSERT(nParentNodePos != NODE_NOTFOUND, "Wrong index setup"); + if (!xPage.Is()) + return; /* Merge 2 pages */ sal_uInt16 nMaxNodes = rIndex.GetMaxNodes(), @@ -489,12 +510,12 @@ void ONDXPage::Merge(sal_uInt16 nParentNodePos, const ONDXPagePtr& xPage) // Determine if page is right or left neighbour bool bRight = ((*xPage)[0].GetKey() > (*this)[0].GetKey()); // true when xPage is at the right side - sal_uInt16 nNewCount = (*xPage).Count() + Count(); + sal_uInt32 nNewCount = (*xPage).Count() + Count(); if (IsLeaf()) { // Condition for merge - if (nNewCount < (nMaxNodes_2 * 2)) + if (nNewCount < (nMaxNodes_2 * 2u)) { sal_uInt16 nLastNode = bRight ? Count() - 1 : xPage->Count() - 1; if (bRight) @@ -575,7 +596,7 @@ void ONDXPage::Merge(sal_uInt16 nParentNodePos, const ONDXPagePtr& xPage) else // !IsLeaf() { // Condition for merge - if (nNewCount < nMaxNodes_2 * 2) + if (nNewCount < nMaxNodes_2 * 2u) { if (bRight) { @@ -731,7 +752,14 @@ ONDXPagePtr& ONDXNode::GetChild(ODbaseIndex* pIndex, ONDXPage* pParent) { if (!aChild.Is() && pIndex) { - aChild = pIndex->CreatePage(aChild.GetPagePos(),pParent,aChild.HasPage()); + const bool bLoad = aChild.HasPage(); + if (bLoad && lcl_isOnTheParentChain(aChild.GetPagePos(), pParent)) + { + SAL_WARN("connectivity.dbase", "page " << aChild.GetPagePos() + << " is its own ancestor, so it is left unread"); + } + else + aChild = pIndex->CreatePage(aChild.GetPagePos(),pParent,bLoad); } return aChild; } @@ -870,13 +898,13 @@ ONDXPagePtr& ONDXPagePtr::operator=(ONDXPagePtr && rOther) return *this; } -static sal_uInt32 nValue; - SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPage& rPage) { rStream.Seek(rPage.GetPagePos() * DINDEX_PAGE_SIZE); + sal_uInt32 nValue(0); rStream.ReadUInt32( nValue ) >> rPage.aChild; - rPage.nCount = sal_uInt16(nValue); + // a page holds at most as many keys as the node array has entries + rPage.nCount = std::min(sal_uInt16(nValue), rPage.GetIndex().getHeader().db_maxkeys); for (sal_uInt16 i = 0; i < rPage.nCount; i++) rPage[i].Read(rStream, rPage.GetIndex()); @@ -899,8 +927,7 @@ SvStream& connectivity::dbase::WriteONDXPage(SvStream &rStream, const ONDXPage& } rStream.Seek(rPage.GetPagePos() * DINDEX_PAGE_SIZE); - nValue = rPage.nCount; - rStream.WriteUInt32( nValue ); + rStream.WriteUInt32( rPage.nCount ); WriteONDXPagePtr( rStream, rPage.aChild ); sal_uInt16 i = 0; @@ -957,11 +984,15 @@ void ONDXPage::PrintPage() if (!IsLeaf()) { #if OSL_DEBUG_LEVEL > 1 - GetChild(&rIndex)->PrintPage(); + ONDXPagePtr aChildPage = GetChild(&rIndex); + if (aChildPage.Is()) + aChildPage->PrintPage(); for (sal_uInt16 i = 0; i < nCount; i++) { ONDXNode rNode = (*this)[i]; - rNode.GetChild(&rIndex,this)->PrintPage(); + ONDXPagePtr aNodePage = rNode.GetChild(&rIndex,this); + if (aNodePage.Is()) + aNodePage->PrintPage(); } #endif } @@ -1024,22 +1055,33 @@ void ONDXPage::SearchAndReplace(const ONDXKey& rSearch, } } +// a node position inside the node array +sal_uInt16 ONDXPage::ClampPos(sal_uInt16 nPos) const +{ + const sal_uInt16 nLast = nNodeCapacity - 1; + SAL_WARN_IF(nPos > nLast, "connectivity.dbase", "node " << nPos + << " asked for on a page whose last node is " << nLast); + return std::min(nPos, nLast); +} + ONDXNode& ONDXPage::operator[] (sal_uInt16 nPos) { DBG_ASSERT(nCount > nPos, "incorrect index access"); - return ppNodes[nPos]; + return ppNodes[ClampPos(nPos)]; } const ONDXNode& ONDXPage::operator[] (sal_uInt16 nPos) const { DBG_ASSERT(nCount > nPos, "incorrect index access"); - return ppNodes[nPos]; + return ppNodes[ClampPos(nPos)]; } void ONDXPage::Remove(sal_uInt16 nPos) { DBG_ASSERT(nCount > nPos, "incorrect index access"); + if (nPos >= nCount) + return; for (sal_uInt16 i = nPos; i < (nCount-1); i++) (*this)[i] = (*this)[i+1]; diff --git a/connectivity/source/drivers/evoab2/EApi.h b/connectivity/source/drivers/evoab2/EApi.h index a33bf9721de6..0a65fafda16e 100644 --- a/connectivity/source/drivers/evoab2/EApi.h +++ b/connectivity/source/drivers/evoab2/EApi.h @@ -25,7 +25,7 @@ bool EApiInit(); G_BEGIN_DECLS -// This header defined all the API methods as +// This header defines all the API methods as // function pointers instead of real functions // this will all evaporate as it is compiled generating // no symbol lookups or relocations, but giving code diff --git a/connectivity/source/drivers/file/fanalyzer.cxx b/connectivity/source/drivers/file/fanalyzer.cxx index 0a749cc3b22d..25e285b06e51 100644 --- a/connectivity/source/drivers/file/fanalyzer.cxx +++ b/connectivity/source/drivers/file/fanalyzer.cxx @@ -67,7 +67,11 @@ void OSQLAnalyzer::start(OSQLParseNode const * pSQLParseNode) || SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term) || SQL_ISRULE(pColumnRef,factor) - || SQL_ISRULE(pColumnRef,set_fct_spec) ) + || SQL_ISRULE(pColumnRef,set_fct_spec) + // tdf#65685 - treat literal constants in the SELECT list as leaf nodes rather than rules + || pColumnRef->getNodeType() == SQLNodeType::String + || pColumnRef->getNodeType() == SQLNodeType::IntNum + || pColumnRef->getNodeType() == SQLNodeType::ApproxNum ) { ::rtl::Reference pCompiler = new OPredicateCompiler(this); pCompiler->setOrigColumns(m_aCompiler->getOrigColumns()); diff --git a/connectivity/source/drivers/firebird/Clob.cxx b/connectivity/source/drivers/firebird/Clob.cxx index 95d14c11d08d..b9c14d15bc36 100644 --- a/connectivity/source/drivers/firebird/Clob.cxx +++ b/connectivity/source/drivers/firebird/Clob.cxx @@ -49,7 +49,7 @@ sal_Int64 SAL_CALL Clob::length() return m_nCharCount; m_nCharCount = 0; - // Read each segment, and calculate it's size by interpreting it as a + // Read each segment, and calculate its size by interpreting it as a // character stream. Assume that no characters are split by the segments. bool bLastSegmRead = false; std::vector aSegmentBytes; diff --git a/connectivity/source/drivers/firebird/Columns.cxx b/connectivity/source/drivers/firebird/Columns.cxx index d36e25f9195b..7d0390d9b1f5 100644 --- a/connectivity/source/drivers/firebird/Columns.cxx +++ b/connectivity/source/drivers/firebird/Columns.cxx @@ -23,7 +23,7 @@ Columns::Columns(Table& rTable, Mutex& rMutex, const ::std::vector< OUString>& rVector): OColumnsHelper(rTable, - true, // TODO: is this case sensitivity? + true, // TODO: is this case sensitive? rMutex, rVector, /*bUseHardRef*/true) diff --git a/connectivity/source/drivers/firebird/Connection.cxx b/connectivity/source/drivers/firebird/Connection.cxx index f48630fd313a..c4b9126cd0c9 100644 --- a/connectivity/source/drivers/firebird/Connection.cxx +++ b/connectivity/source/drivers/firebird/Connection.cxx @@ -22,6 +22,7 @@ #include "Clob.hxx" #include "Connection.hxx" #include "DatabaseMetaData.hxx" +#include "Driver.hxx" #include "PreparedStatement.hxx" #include "Statement.hxx" #include "Util.hxx" @@ -82,6 +83,7 @@ Connection::Connection() : Connection_BASE(m_aMutex) , m_bIsEmbedded(false) , m_bIsFile(false) + , m_bBackupDataOnDispose(false) , m_bIsAutoCommit(true) , m_bIsReadOnly(false) , m_aTransactionIsolation(TransactionIsolation::READ_COMMITTED) @@ -119,15 +121,50 @@ struct ConnectionGuard } }; +// A set nbackup state makes firebird open a difference file +// (BackupManager::actualizeState and openDelta, firebird/src/jrd/nbak.cpp). +// A database we made is never in that state, so refuse it. +bool databaseHeaderHasBackupState(const OUString& rDatabasePath) +{ + OUString sFileURL; + if (::osl::FileBase::getFileURLFromSystemPath(rDatabasePath, sFileURL) != ::osl::FileBase::E_None) + return false; + + ::osl::File aFile(sFileURL); + if (aFile.open(osl_File_OpenFlag_Read) != ::osl::FileBase::E_None) + return false; + + // Ods::header_page, firebird/src/jrd/ods.h + sal_uInt8 aHeader[44]; + sal_uInt64 nRead = 0; + ::osl::FileBase::RC eRead = aFile.read(aHeader, sizeof(aHeader), nRead); + aFile.close(); + + if (eRead != ::osl::FileBase::E_None || nRead < sizeof(aHeader)) + return false; + + // pag_type, Ods::pag_header + const sal_uInt8 nPageTypeHeader = 1; + if (aHeader[0] != nPageTypeHeader) + return false; + + // hdr_flags & hdr_backup_mask, normal state is 0 + const sal_uInt16 nFlags = aHeader[42] | (aHeader[43] << 8); + const sal_uInt16 nBackupStateMask = 0x0C00; + return (nFlags & nBackupStateMask) != 0; } -void Connection::construct(const OUString& url, const Sequence< PropertyValue >& info) +} + +void Connection::construct(const OUString& url, const Sequence< PropertyValue >& info, + FirebirdDriver& rDriver) { ConnectionGuard aGuard(m_refCount); try { m_sConnectionURL = url; + m_xDriver = &rDriver; bool bIsNewDatabase = false; // the database may be stored as an @@ -158,7 +195,8 @@ void Connection::construct(const OUString& url, const Sequence< PropertyValue >& bIsNewDatabase = !m_xEmbeddedStorage->hasElements(); - m_pDatabaseFileDir.reset(new ::utl::TempFileNamed(nullptr, true)); + const OUString sDatabaseDataDirectoryURL = rDriver.getDatabaseDataDirectoryURL(); + m_pDatabaseFileDir.reset(new ::utl::TempFileNamed(&sDatabaseDataDirectoryURL, true)); m_pDatabaseFileDir->EnableKillingFile(); m_sFirebirdURL = m_pDatabaseFileDir->GetFileName() + "/firebird.fdb"; m_sFBKPath = m_pDatabaseFileDir->GetFileName() + "/firebird.fbk"; @@ -179,6 +217,15 @@ void Connection::construct(const OUString& url, const Sequence< PropertyValue >& SAL_INFO("connectivity.firebird", "Found .fdb instead of .fbk"); bIsFdbStored = true; loadDatabaseFile(our_sFDBLocation, m_sFirebirdURL); + // Decline a database whose header asks firebird to use a + // difference file + if (databaseHeaderHasBackupState(m_sFirebirdURL)) + { + ::connectivity::SharedResources aResources; + const OUString sMessage = aResources.getResourceString(STR_COULD_NOT_LOAD_FILE).replaceFirst( + "$filename$", m_sConnectionURL); + ::dbtools::throwGenericSQLException(sMessage, *this); + } } else { @@ -203,6 +250,10 @@ void Connection::construct(const OUString& url, const Sequence< PropertyValue >& bIsNewDatabase = true; osl::FileBase::getSystemPathFromFileURL(m_sFirebirdURL, m_sFirebirdURL); + + // The user picked this file, so it is outside the directory firebird is + // restricted to. Reach it by the name the driver gives us for it. + m_sExternalDatabaseName = rDriver.addExternalDatabaseName(m_sFirebirdURL); } } @@ -228,8 +279,13 @@ void Connection::construct(const OUString& url, const Sequence< PropertyValue >& // Do any more dpbBuffer additions here + // attach without running the database's own event triggers if (m_bIsEmbedded || m_bIsFile) { + dpbBuffer.push_back(isc_dpb_no_db_triggers); + dpbBuffer.push_back(1); // 1 byte long + dpbBuffer.push_back(1); + userName = "sysdba"_ostr; userPassword = "masterkey"_ostr; } @@ -275,12 +331,13 @@ void Connection::construct(const OUString& url, const Sequence< PropertyValue >& ISC_STATUS_ARRAY status; /* status vector */ ISC_STATUS aErr; - const OString sFirebirdURL = OUStringToOString(m_sFirebirdURL, RTL_TEXTENCODING_UTF8); + const OString sDatabaseName + = OUStringToOString(getFirebirdDatabaseName(), RTL_TEXTENCODING_UTF8); if (bIsNewDatabase) { aErr = isc_create_database(status, - sFirebirdURL.getLength(), - sFirebirdURL.getStr(), + sDatabaseName.getLength(), + sDatabaseName.getStr(), &m_aDBHandle, dpbBuffer.size(), dpbBuffer.c_str(), @@ -298,8 +355,8 @@ void Connection::construct(const OUString& url, const Sequence< PropertyValue >& } aErr = isc_attach_database(status, - sFirebirdURL.getLength(), - sFirebirdURL.getStr(), + sDatabaseName.getLength(), + sDatabaseName.getStr(), &m_aDBHandle, dpbBuffer.size(), dpbBuffer.c_str()); @@ -311,6 +368,10 @@ void Connection::construct(const OUString& url, const Sequence< PropertyValue >& if (m_bIsEmbedded) // Add DocumentEventListener to save the .fdb as needed { + // The database opened without error, so its temporary .fdb is + // worth writing back into the .odb on dispose. + m_bBackupDataOnDispose = true; + // We need to attach as a document listener in order to be able to store // the temporary db back into the .odb when saving uno::Reference xBroadcaster(m_xParentDocument, UNO_QUERY); @@ -895,6 +956,12 @@ void Connection::disposing() storeDatabase(); + if (!m_sExternalDatabaseName.isEmpty()) + { + m_xDriver->removeExternalDatabaseName(m_sExternalDatabaseName); + m_sExternalDatabaseName.clear(); + } + cppu::WeakComponentImplHelperBase::disposing(); m_pDatabaseFileDir.reset(); @@ -903,7 +970,7 @@ void Connection::disposing() void Connection::storeDatabase() { MutexGuard aGuard(m_aMutex); - if (m_bIsEmbedded && m_xEmbeddedStorage.is()) + if (m_bIsEmbedded && m_bBackupDataOnDispose && m_xEmbeddedStorage.is()) { SAL_INFO("connectivity.firebird", "Writing .fbk from running db"); try diff --git a/connectivity/source/drivers/firebird/Connection.hxx b/connectivity/source/drivers/firebird/Connection.hxx index 524c0a7c476f..5d8555a394a1 100644 --- a/connectivity/source/drivers/firebird/Connection.hxx +++ b/connectivity/source/drivers/firebird/Connection.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -130,6 +131,26 @@ namespace connectivity::firebird /** We are using an external (local) file */ bool m_bIsFile; + /** The driver that made this connection, and owns the directory firebird works in. */ + rtl::Reference m_xDriver; + + /** + * The name firebird was given for a database outside its own directory, empty when the + * database is inside it and its path was handed over directly. + */ + OUString m_sExternalDatabaseName; + + /** The name or path this connection hands to firebird to reach its database. */ + const OUString& getFirebirdDatabaseName() const + { + return m_sExternalDatabaseName.isEmpty() ? m_sFirebirdURL : m_sExternalDatabaseName; + } + + /** When true the embedded database was opened in this session, so the + temporary .fdb holds live data that must be written back into the .odb + when the connection is disposed. */ + bool m_bBackupDataOnDispose; + /* CONNECTION PROPERTIES */ bool m_bIsAutoCommit; bool m_bIsReadOnly; @@ -165,7 +186,8 @@ namespace connectivity::firebird /// @throws css::sdbc::SQLException /// @throws css::uno::RuntimeException void construct( const OUString& url, - const css::uno::Sequence< css::beans::PropertyValue >& info); + const css::uno::Sequence< css::beans::PropertyValue >& info, + FirebirdDriver& rDriver); const OUString& getConnectionURL() const {return m_sConnectionURL;} bool isEmbedded() const {return m_bIsEmbedded;} diff --git a/connectivity/source/drivers/firebird/Driver.cxx b/connectivity/source/drivers/firebird/Driver.cxx index 0879a7eca310..c4fada5a07af 100644 --- a/connectivity/source/drivers/firebird/Driver.cxx +++ b/connectivity/source/drivers/firebird/Driver.cxx @@ -25,13 +25,37 @@ #include #include +#include + +// firebird's own header has functions with parameters it does not use +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4100) // unreferenced formal parameter +#endif +#include +#if defined _MSC_VER +#pragma warning(pop) +#endif +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif + #include #include #include #include +#include #include +#include +#include #include +#include + using namespace com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::lang; @@ -48,9 +72,240 @@ namespace { constexpr OUString our_sFirebirdTmpVar = u"FIREBIRD_TMP"_ustr; constexpr OUString our_sFirebirdLockVar = u"FIREBIRD_LOCK"_ustr; constexpr OUString our_sFirebirdMsgVar = u"FIREBIRD_MSG"_ustr; +constexpr OUString our_sFirebirdRootVar = u"FIREBIRD"_ustr; #ifdef MACOSX constexpr OUString our_sFirebirdLibVar = u"LIBREOFFICE_FIREBIRD_LIB"_ustr; #endif + +// The name of the file in the firebird directory that maps a name to the absolute path of a +// database. firebird looks a name up here before it treats it as a path, and re-reads the file +// whenever it has changed. +constexpr OUString our_sDatabasesConfName = u"databases.conf"_ustr; + +// The file that gives a plugin the module to load it from. +constexpr OUString our_sPluginsConfName = u"plugins.conf"_ustr; + +// Put rContent in the file at rURL, discarding whatever was there before. +bool writeFile(const OUString& rURL, std::string_view aContent) +{ + ::osl::File aFile(rURL); + if (aFile.open(osl_File_OpenFlag_Create | osl_File_OpenFlag_Write) != ::osl::FileBase::E_None) + { + if (aFile.open(osl_File_OpenFlag_Write) != ::osl::FileBase::E_None) + return false; + if (aFile.setSize(0) != ::osl::FileBase::E_None) + { + aFile.close(); + return false; + } + } + + bool bWholeContentWritten = true; + if (!aContent.empty()) + { + sal_uInt64 nWritten = 0; + bWholeContentWritten + = aFile.write(aContent.data(), aContent.size(), nWritten) == ::osl::FileBase::E_None + && nWritten == aContent.size(); + } + aFile.close(); + return bWholeContentWritten; +} + +// The whole content of the file at rURL, empty when it cannot be read. +OString readFile(const OUString& rURL) +{ + ::osl::File aFile(rURL); + if (aFile.open(osl_File_OpenFlag_Read) != ::osl::FileBase::E_None) + return OString(); + + OStringBuffer aContent; + for (;;) + { + char aBuffer[4096]; + sal_uInt64 nRead = 0; + if (aFile.read(aBuffer, sizeof(aBuffer), nRead) != ::osl::FileBase::E_None || nRead == 0) + break; + aContent.append(std::string_view(aBuffer, nRead)); + } + aFile.close(); + return aContent.makeStringAndClear(); +} + +// The directories of the firebird installation, empty for a bundled firebird, which resolves them +// where it was built. +constexpr OUString our_sSystemPluginsPath = u"" SYSTEM_FIREBIRD_PLUGINS_DIRECTORY ""_ustr; +constexpr OUString our_sSystemIntlPath = u"" SYSTEM_FIREBIRD_INTL_DIRECTORY ""_ustr; +constexpr OUString our_sSystemConfPath = u"" SYSTEM_FIREBIRD_CONF_DIRECTORY ""_ustr; + +OString toBytes(std::u16string_view rPath) +{ + return OUStringToOString(rPath, osl_getThreadTextEncoding()); +} + +// Put the directories of the installation in place of the macros that name them. rThisPath is the +// directory the file was read from, which is what the this macro means. plugins and intl under the +// root are the plugins and international module directories. +OString expandFirebirdDirectoryMacros(const OString& rContent, const OString& rThisPath) +{ + const OString sPlugins = toBytes(our_sSystemPluginsPath); + const OString sIntl = toBytes(our_sSystemIntlPath); + + OString sExpanded = rContent.replaceAll("$(this)"_ostr, rThisPath); + sExpanded = sExpanded.replaceAll("$(dir_plugins)"_ostr, sPlugins); + sExpanded = sExpanded.replaceAll("$(root)/plugins"_ostr, sPlugins); + sExpanded = sExpanded.replaceAll("$(dir_intl)"_ostr, sIntl); + sExpanded = sExpanded.replaceAll("$(root)/intl"_ostr, sIntl); + sExpanded = sExpanded.replaceAll("$(dir_conf)"_ostr, toBytes(our_sSystemConfPath)); + return sExpanded; +} + +// The file at rSourceURL with the macros expanded, empty when one is left that we have no directory +// for. A leftover macro leaves a relative path, resolved under the root we are writing for. +OString getExpandedConf(const OUString& rSourceURL, const OUString& rSourcePath) +{ + const OString sContent + = expandFirebirdDirectoryMacros(readFile(rSourceURL), toBytes(rSourcePath)); + if (sContent.indexOf("$(") == -1) + return sContent; + + SAL_WARN("connectivity.firebird", "unexpanded macro in " << rSourcePath); + return OString(); +} + +// Write a plugins.conf into the directory the FIREBIRD variable names, giving every plugin of the +// installation the absolute path of its module. A plugin no entry names is looked for by its own +// name in the plugins directory firebird resolves, which Debian patches to sit under that variable. +void writeSystemFirebirdPluginsConf(std::u16string_view rDataDirURL) +{ + if (our_sSystemPluginsPath.isEmpty()) + return; + + OUString sPluginsURL; + if (::osl::FileBase::getFileURLFromSystemPath(our_sSystemPluginsPath, sPluginsURL) + != ::osl::FileBase::E_None) + return; + + // The installation's own file names the plugins that need more than their module. + OString sSystemConf; + OUString sConfURL; + if (!our_sSystemConfPath.isEmpty() + && ::osl::FileBase::getFileURLFromSystemPath(our_sSystemConfPath, sConfURL) + == ::osl::FileBase::E_None) + { + sSystemConf = getExpandedConf(sConfURL + "/" + our_sPluginsConfName, our_sSystemConfPath); + } + + ::osl::Directory aPluginsDirectory(sPluginsURL); + if (aPluginsDirectory.open() != ::osl::FileBase::E_None) + { + SAL_WARN("connectivity.firebird", "could not read " << our_sSystemPluginsPath); + return; + } + + const OString sPluginsPath = toBytes(our_sSystemPluginsPath); + OStringBuffer aContent(sSystemConf); + ::osl::DirectoryItem aItem; + while (aPluginsDirectory.getNextItem(aItem) == ::osl::FileBase::E_None) + { + ::osl::FileStatus aStatus(osl_FileStatus_Mask_FileName); + if (aItem.getFileStatus(aStatus) != ::osl::FileBase::E_None) + continue; + + // The module libEngine13.so holds the plugin Engine13. + const OUString sName = aStatus.getFileName(); + if (!sName.startsWith("lib") || !sName.endsWith(".so") || sName.getLength() <= 6) + continue; + const OString sPlugin = toBytes(sName.subView(3, sName.getLength() - 6)); + + if (sSystemConf.indexOf(Concat2View("= " + sPlugin + " ")) != -1) + continue; + + aContent.append("\nPlugin = " + sPlugin + " {\n Module = " + sPluginsPath + "/" + sPlugin + + "\n}\n"); + } + + const OUString sURL = OUString::Concat(rDataDirURL) + "/" + our_sPluginsConfName; + const OString sContent = aContent.makeStringAndClear(); + const bool bWritten = writeFile(sURL, std::string_view(sContent)); + SAL_WARN_IF(!bWritten, "connectivity.firebird", "could not write " << sURL); +} + +// Copy the conf files of the international modules into an intl subdirectory of the directory the +// FIREBIRD variable names, with the absolute path of each module in place of the macros. Without +// them only the character sets and collations built into the engine work. +void writeSystemFirebirdIntlConfs(std::u16string_view rDataDirURL) +{ + if (our_sSystemIntlPath.isEmpty()) + return; + + OUString sIntlURL; + if (::osl::FileBase::getFileURLFromSystemPath(our_sSystemIntlPath, sIntlURL) + != ::osl::FileBase::E_None) + return; + + ::osl::Directory aIntlDirectory(sIntlURL); + if (aIntlDirectory.open() != ::osl::FileBase::E_None) + { + SAL_WARN("connectivity.firebird", "could not read " << our_sSystemIntlPath); + return; + } + + const OUString sTargetURL = OUString::Concat(rDataDirURL) + "/intl"; + if (::osl::Directory::create(sTargetURL) != ::osl::FileBase::E_None) + { + SAL_WARN("connectivity.firebird", "could not create " << sTargetURL); + return; + } + + ::osl::DirectoryItem aItem; + while (aIntlDirectory.getNextItem(aItem) == ::osl::FileBase::E_None) + { + ::osl::FileStatus aStatus(osl_FileStatus_Mask_FileName); + if (aItem.getFileStatus(aStatus) != ::osl::FileBase::E_None) + continue; + + const OUString sName = aStatus.getFileName(); + if (!sName.endsWith(".conf")) + continue; + + const OString sContent = getExpandedConf(sIntlURL + "/" + sName, our_sSystemIntlPath); + if (sContent.isEmpty()) + continue; + + const OUString sURL = sTargetURL + "/" + sName; + const bool bWritten = writeFile(sURL, std::string_view(sContent)); + SAL_WARN_IF(!bWritten, "connectivity.firebird", "could not write " << sURL); + } +} + +// firebird takes its root directory from the FIREBIRD variable on its first use, and reads the +// firebird.conf that confines it to that directory only from there. Ask firebird which directory +// it settled on and treat anything but our own as unconfined. +bool isFirebirdRootedAt(const OUString& rDataDirPath) +{ + Firebird::IMaster* pMaster = Firebird::fb_get_master_interface(); + if (!pMaster) + return false; + + Firebird::IConfigManager* pConfigManager = pMaster->getConfigManager(); + if (!pConfigManager) + return false; + + const char* pRootDirectory = pConfigManager->getRootDirectory(); + if (!pRootDirectory) + return false; + + OUString sRootPath = OStringToOUString(pRootDirectory, osl_getThreadTextEncoding()); + if (sRootPath.endsWith("/") || sRootPath.endsWith("\\")) + sRootPath = sRootPath.copy(0, sRootPath.getLength() - 1); + +#if defined(_WIN32) + return sRootPath.equalsIgnoreAsciiCase(rDataDirPath); +#else + return sRootPath == rDataDirPath; +#endif +} }; FirebirdDriver::FirebirdDriver(const css::uno::Reference< css::uno::XComponentContext >& _rxContext) @@ -58,12 +313,15 @@ FirebirdDriver::FirebirdDriver(const css::uno::Reference< css::uno::XComponentCo , m_aContext(_rxContext) , m_firebirdTMPDirectory(nullptr, true) , m_firebirdLockDirectory(nullptr, true) + , m_firebirdDataDirectory(nullptr, true) + , m_bConfined(false) { // ::utl::TempFile uses a unique temporary directory (subdirectory of // /tmp or other user specific tmp directory) per instance in which // we can create directories for firebird at will. m_firebirdTMPDirectory.EnableKillingFile(true); m_firebirdLockDirectory.EnableKillingFile(true); + m_firebirdDataDirectory.EnableKillingFile(true); // Overrides firebird's default of /tmp or c:\temp osl_setEnvironment(our_sFirebirdTmpVar.pData, m_firebirdTMPDirectory.GetFileName().pData); @@ -71,6 +329,44 @@ FirebirdDriver::FirebirdDriver(const css::uno::Reference< css::uno::XComponentCo // Overrides firebird's default of /tmp/firebird or c:\temp\firebird osl_setEnvironment(our_sFirebirdLockVar.pData, m_firebirdLockDirectory.GetFileName().pData); + // Keep the files firebird opens or creates together in one directory. + // Embedded databases are extracted here, and DatabaseAccess = Restrict + // keeps any associated files firebird makes for it under the same + // directory. firebird reads this firebird.conf from the directory the + // FIREBIRD variable names, once, on its first use, so it has to be set + // before the first connection. + OUString sDataDirPath; + ::osl::FileBase::getSystemPathFromFileURL(m_firebirdDataDirectory.GetURL(), sDataDirPath); + + writeSystemFirebirdPluginsConf(m_firebirdDataDirectory.GetURL()); + writeSystemFirebirdIntlConfs(m_firebirdDataDirectory.GetURL()); + +#if defined(_WIN32) + // firebird upper-cases the database path before the exact-match + // DatabaseAccess check, so match that here. + sDataDirPath = sDataDirPath.toAsciiUpperCase(); +#endif + + // ExternalFileAccess is already None by default. Saying so here keeps a database firebird + // opens from reading databases.conf back out of the directory it shares with it. + OString sConf = "DatabaseAccess = Restrict " + + OUStringToOString(sDataDirPath, RTL_TEXTENCODING_UTF8) + + "\nExternalFileAccess = None\n"; + + OUString sConfURL = m_firebirdDataDirectory.GetURL() + "/firebird.conf"; + if (writeFile(sConfURL, std::string_view(sConf)) + // An empty databases.conf, so that firebird has the file in hand from its first use and + // notices the names added to it later. + && writeFile(m_firebirdDataDirectory.GetURL() + "/" + our_sDatabasesConfName, + std::string_view())) + { + osl_setEnvironment(our_sFirebirdRootVar.pData, sDataDirPath.pData); + m_bConfined = isFirebirdRootedAt(sDataDirPath); + } + + SAL_WARN_IF(!m_bConfined, "connectivity.firebird", + "firebird is not confined to " << sDataDirPath << ", connections will be refused"); + #ifndef SYSTEM_FIREBIRD // Overrides firebird's hardcoded default of /usr/local/firebird on *nix, // however on Windows it seems to use the current directory as a default. @@ -93,6 +389,51 @@ FirebirdDriver::FirebirdDriver(const css::uno::Reference< css::uno::XComponentCo FirebirdDriver::~FirebirdDriver() = default; +OUString FirebirdDriver::addExternalDatabaseName(const OUString& rDatabasePath) +{ + MutexGuard aGuard(m_aMutex); + + sal_uInt8 aUuid[16]; + rtl_createUuid(aUuid, nullptr, false); + + OUStringBuffer aName(u"database"); + for (const sal_uInt8 nByte : aUuid) + { + aName.append(OUString::number(nByte >> 4, 16) + OUString::number(nByte & 0x0F, 16)); + } + const OUString sName = aName.makeStringAndClear(); + + m_aExternalDatabaseNames.emplace(sName, rDatabasePath); + writeExternalDatabaseNames(); + + return sName; +} + +void FirebirdDriver::removeExternalDatabaseName(const OUString& rName) +{ + MutexGuard aGuard(m_aMutex); + + if (m_aExternalDatabaseNames.erase(rName) != 0) + writeExternalDatabaseNames(); +} + +void FirebirdDriver::writeExternalDatabaseNames() +{ + MutexGuard aGuard(m_aMutex); + + OStringBuffer aContent; + for (const auto& [rName, rPath] : m_aExternalDatabaseNames) + { + aContent.append(OUStringToOString(rName, RTL_TEXTENCODING_UTF8) + " = " + + OUStringToOString(rPath, RTL_TEXTENCODING_UTF8) + "\n"); + } + const OString sContent = aContent.makeStringAndClear(); + + const OUString sURL = m_firebirdDataDirectory.GetURL() + "/" + our_sDatabasesConfName; + const bool bWritten = writeFile(sURL, std::string_view(sContent)); + SAL_WARN_IF(!bWritten, "connectivity.firebird", "could not write " << sURL); +} + void FirebirdDriver::disposing() { MutexGuard aGuard(m_aMutex); @@ -107,6 +448,7 @@ void FirebirdDriver::disposing() osl_clearEnvironment(our_sFirebirdTmpVar.pData); osl_clearEnvironment(our_sFirebirdLockVar.pData); + osl_clearEnvironment(our_sFirebirdRootVar.pData); #ifndef SYSTEM_FIREBIRD osl_clearEnvironment(our_sFirebirdMsgVar.pData); @@ -148,8 +490,18 @@ Reference< XConnection > SAL_CALL FirebirdDriver::connect( if ( ! acceptsURL(url) ) return nullptr; + // Without the firebird.conf that keeps firebird inside its own directory + // we do not open any database. + if (!m_bConfined) + { + ::connectivity::SharedResources aResources; + const OUString sMessage = aResources.getResourceString(STR_COULD_NOT_LOAD_FILE).replaceFirst( + "$filename$", u"firebird.conf"); + ::dbtools::throwGenericSQLException(sMessage, *this); + } + rtl::Reference pCon = new Connection(); - pCon->construct(url, info); + pCon->construct(url, info, *this); m_xConnections.push_back(pCon); diff --git a/connectivity/source/drivers/firebird/Driver.hxx b/connectivity/source/drivers/firebird/Driver.hxx index 5428568b4166..14e9d04c3697 100644 --- a/connectivity/source/drivers/firebird/Driver.hxx +++ b/connectivity/source/drivers/firebird/Driver.hxx @@ -29,6 +29,8 @@ #include #include +#include + namespace connectivity::firebird { // The SQL dialect in use @@ -48,6 +50,16 @@ namespace connectivity::firebird css::uno::Reference m_aContext; ::utl::TempFileNamed m_firebirdTMPDirectory; ::utl::TempFileNamed m_firebirdLockDirectory; + ::utl::TempFileNamed m_firebirdDataDirectory; + bool m_bConfined; + + // The names firebird may use for a database that lies outside its own directory, each + // mapped to that database's absolute path. The names are random, and only the databases + // the user picked in this session are in here. + std::map m_aExternalDatabaseNames; + + // Write m_aExternalDatabaseNames out as the databases.conf of the firebird directory. + void writeExternalDatabaseNames(); protected: ::osl::Mutex m_aMutex; // mutex is need to control member access @@ -62,6 +74,22 @@ namespace connectivity::firebird virtual ~FirebirdDriver() override; const css::uno::Reference& getContext() const { return m_aContext; } + // The directory that embedded databases are extracted into. Each + // connection makes its own subdirectory here, and firebird keeps + // associated files it creates for them under this directory as well. + OUString getDatabaseDataDirectoryURL() const { return m_firebirdDataDirectory.GetURL(); } + + // Give firebird a name for a database that lies outside its own directory, and return + // that name. firebird resolves a name it finds in databases.conf without applying the + // DatabaseAccess restriction, while every path it is handed elsewhere, a difference file + // or a shadow, is still checked against that restriction. The name is random so that a + // database firebird opens cannot ask for another database by guessing the name. + OUString addExternalDatabaseName(const OUString& rDatabasePath); + + // Take back a name from addExternalDatabaseName. Any database already attached through + // it stays open. + void removeExternalDatabaseName(const OUString& rName); + // OComponentHelper virtual void SAL_CALL disposing() override; diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx b/connectivity/source/drivers/firebird/PreparedStatement.cxx index c1ebd314ea7e..44897cc330cd 100644 --- a/connectivity/source/drivers/firebird/PreparedStatement.cxx +++ b/connectivity/source/drivers/firebird/PreparedStatement.cxx @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -267,6 +268,15 @@ void SAL_CALL OPreparedStatement::setString(sal_Int32 nParameterIndex, setBoolean(nParameterIndex, boolValue); break; } + case DataType::DATE: + setDate(nParameterIndex, ::dbtools::DBTypeConversion::toDate(sInput)); + break; + case DataType::TIME: + setTime(nParameterIndex, ::dbtools::DBTypeConversion::toTime(sInput)); + break; + case DataType::TIMESTAMP: + setTimestamp(nParameterIndex, ::dbtools::DBTypeConversion::toDateTime(sInput)); + break; case DataType::SQLNULL: { // See https://www.firebirdsql.org/file/documentation/html/en/refdocs/fblangref25/firebird-25-language-reference.html#fblangref25-datatypes-special-sqlnull diff --git a/connectivity/source/drivers/firebird/Tables.cxx b/connectivity/source/drivers/firebird/Tables.cxx index 2b68501bc785..6a230c0fbc5c 100644 --- a/connectivity/source/drivers/firebird/Tables.cxx +++ b/connectivity/source/drivers/firebird/Tables.cxx @@ -84,7 +84,7 @@ OUString Tables::createStandardColumnPart(const Reference< XPropertySet >& xColP const OUString sQuoteString = xMetaData->getIdentifierQuoteString(); OUStringBuffer aSql(::dbtools::quoteName(sQuoteString,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))))); - // check if the user enter a specific string to create autoincrement values + // check if the user enters a specific string to create autoincrement values OUString sAutoIncrementValue; Reference xPropInfo = xColProp->getPropertySetInfo(); @@ -93,7 +93,7 @@ OUString Tables::createStandardColumnPart(const Reference< XPropertySet >& xColP aSql.append(" " + dbtools::createStandardTypePart(xColProp, _xConnection)); - // Add character set for (VAR)BINARY (fix) types: + // Add character set for (VAR)BINARY (fixed) types: // (VAR) BINARY is distinguished from other CHAR types by its character set. // Octets is a special character set for binary data. if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex( diff --git a/connectivity/source/drivers/hsqldb/HConnection.cxx b/connectivity/source/drivers/hsqldb/HConnection.cxx index 0a248e31760d..863bac3ad3ec 100644 --- a/connectivity/source/drivers/hsqldb/HConnection.cxx +++ b/connectivity/source/drivers/hsqldb/HConnection.cxx @@ -245,7 +245,7 @@ namespace connectivity::hsqldb catch( const Exception& ) { // that's a serious error in impl_getTableContainer_throw, or hasByName, however, we're only - // allowed to throw an IllegalArgumentException ourself + // allowed to throw an IllegalArgumentException ourselves DBG_UNHANDLED_EXCEPTION("connectivity.hsqldb"); } diff --git a/connectivity/source/drivers/jdbc/Blob.cxx b/connectivity/source/drivers/jdbc/Blob.cxx index c62c9ba5599b..4f38c0288be0 100644 --- a/connectivity/source/drivers/jdbc/Blob.cxx +++ b/connectivity/source/drivers/jdbc/Blob.cxx @@ -135,7 +135,7 @@ sal_Int64 SAL_CALL java_sql_Blob::positionOfBlob( const css::uno::Reference< css ::dbtools::throwFeatureNotImplementedSQLException( u"XBlob::positionOfBlob"_ustr, *this ); // this was put here in CWS warnings01. The previous implementation was defective, as it did ignore // the pattern parameter. Since the effort for proper implementation is rather high - we would need - // to translated pattern into a byte[] -, we defer this functionality for the moment (hey, it was + // to translate pattern into a byte[] -, we defer this functionality for the moment (hey, it was // unusable, anyway) // #i57457# } diff --git a/connectivity/source/drivers/jdbc/JConnection.cxx b/connectivity/source/drivers/jdbc/JConnection.cxx index fcc058b7a826..4290f5afbdd6 100644 --- a/connectivity/source/drivers/jdbc/JConnection.cxx +++ b/connectivity/source/drivers/jdbc/JConnection.cxx @@ -693,7 +693,7 @@ OUString java_sql_Connection::impl_getJavaDriverClassPath_nothrow(const OUString static constexpr OUStringLiteral s_sNodeName = u"org.openoffice.Office.DataAccess/JDBC/DriverClassPaths"; ::utl::OConfigurationTreeRoot aNamesRoot = ::utl::OConfigurationTreeRoot::createWithComponentContext( - m_pDriver->getContext(), s_sNodeName, -1, ::utl::OConfigurationTreeRoot::CM_READONLY); + m_pDriver->getContext(), s_sNodeName, ::utl::OConfigurationTreeRoot::CM_READONLY); OUString sURL; if ( aNamesRoot.isValid() && aNamesRoot.hasByName( _sDriverClass ) ) { diff --git a/connectivity/source/drivers/jdbc/Timestamp.cxx b/connectivity/source/drivers/jdbc/Timestamp.cxx index eb7624719812..33235c61369c 100644 --- a/connectivity/source/drivers/jdbc/Timestamp.cxx +++ b/connectivity/source/drivers/jdbc/Timestamp.cxx @@ -39,7 +39,7 @@ java_sql_Date::java_sql_Date( const css::util::Date& _rOut ) : java_util_Date( n OUString sDateStr = ::dbtools::DBTypeConversion::toDateString(_rOut); args[0].l = convertwchar_tToJavaString(t.pEnv,sDateStr); - // Turn of Java-Call for the constructor + // Turn off Java-Call for the constructor // initialise temporary variables jobject tempObj; static jmethodID mID(nullptr); diff --git a/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx b/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx index 62d6ef224091..57a9dcad8c72 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx @@ -25,20 +25,17 @@ void connectivity::mysqlc::Tables::impl_refresh() static void lcl_unescape(OUString& rName) { // Remove ending ` if there's one - sal_Int32 nLastIndexBacktick = rName.lastIndexOf("`"); - if ((nLastIndexBacktick > 0) && (nLastIndexBacktick == (rName.getLength() - 1))) - { - rName = rName.copy(0, nLastIndexBacktick); - } + if (rName.endsWith('`')) + rName = rName.copy(0, rName.getLength() - 1); // Remove beginning ` - nLastIndexBacktick = rName.indexOf("`"); - if (nLastIndexBacktick == 0) + sal_Int32 nFirstIndexBacktick = rName.indexOf("`"); + if (nFirstIndexBacktick == 0) { rName = rName.copy(1, rName.getLength() - 1); } - // Replace double ` by simple ` + // Replace double ` with single ` rName = rName.replaceAll("``", "`"); } diff --git a/connectivity/source/drivers/odbc/ODatabaseMetaData.cxx b/connectivity/source/drivers/odbc/ODatabaseMetaData.cxx index 97cd0b1b33d9..e8337d356585 100644 --- a/connectivity/source/drivers/odbc/ODatabaseMetaData.cxx +++ b/connectivity/source/drivers/odbc/ODatabaseMetaData.cxx @@ -1496,7 +1496,7 @@ OUString SAL_CALL ODatabaseMetaData::getNumericFunctions( ) sal_Bool SAL_CALL ODatabaseMetaData::supportsExtendedSQLGrammar( ) { SQLUINTEGER nValue; - // SQL_ODBC_SQL_CONFORMANCE is deprecated in ODBC 3.x, but there does not seem te be any equivalent. + // SQL_ODBC_SQL_CONFORMANCE is deprecated in ODBC 3.x, but there does not seem to be any equivalent. OTools::GetInfo(m_pConnection,m_aConnectionHandle,SQL_ODBC_SQL_CONFORMANCE,nValue,*this); SAL_WARN_IF(! (nValue == SQL_OSC_MINIMUM || nValue == SQL_OSC_CORE || nValue == SQL_OSC_EXTENDED), "connectivity.odbc", @@ -1507,7 +1507,7 @@ sal_Bool SAL_CALL ODatabaseMetaData::supportsExtendedSQLGrammar( ) sal_Bool SAL_CALL ODatabaseMetaData::supportsCoreSQLGrammar( ) { SQLUINTEGER nValue; - // SQL_ODBC_SQL_CONFORMANCE is deprecated in ODBC 3.x, but there does not seem te be any equivalent. + // SQL_ODBC_SQL_CONFORMANCE is deprecated in ODBC 3.x, but there does not seem to be any equivalent. OTools::GetInfo(m_pConnection,m_aConnectionHandle,SQL_ODBC_SQL_CONFORMANCE,nValue,*this); SAL_WARN_IF(! (nValue == SQL_OSC_MINIMUM || nValue == SQL_OSC_CORE || nValue == SQL_OSC_EXTENDED), "connectivity.odbc", @@ -1518,7 +1518,7 @@ sal_Bool SAL_CALL ODatabaseMetaData::supportsCoreSQLGrammar( ) sal_Bool SAL_CALL ODatabaseMetaData::supportsMinimumSQLGrammar( ) { SQLUINTEGER nValue; - // SQL_ODBC_SQL_CONFORMANCE is deprecated in ODBC 3.x, but there does not seem te be any equivalent. + // SQL_ODBC_SQL_CONFORMANCE is deprecated in ODBC 3.x, but there does not seem to be any equivalent. OTools::GetInfo(m_pConnection,m_aConnectionHandle,SQL_ODBC_SQL_CONFORMANCE,nValue,*this); SAL_WARN_IF(! (nValue == SQL_OSC_MINIMUM || nValue == SQL_OSC_CORE || nValue == SQL_OSC_EXTENDED), "connectivity.odbc", diff --git a/connectivity/source/drivers/postgresql/pq_xkey.cxx b/connectivity/source/drivers/postgresql/pq_xkey.cxx index 81d1f7a86eb6..76fc109fbf30 100644 --- a/connectivity/source/drivers/postgresql/pq_xkey.cxx +++ b/connectivity/source/drivers/postgresql/pq_xkey.cxx @@ -82,7 +82,7 @@ Reference< XPropertySet > Key::createDataDescriptor( ) Reference< XNameAccess > Key::getColumns( ) { - // TODO: cash columns object ! + // TODO: cache columns object ! if( !m_keyColumns.is() ) { Sequence< OUString > columnNames, foreignColumnNames; @@ -145,7 +145,7 @@ Reference< XPropertySet > KeyDescriptor::createDataDescriptor( ) Reference< XNameAccess > KeyDescriptor::getColumns( ) { - // TODO: cash columns object ! + // TODO: cache columns object ! if( !m_keyColumns.is() ) { m_keyColumns = new KeyColumnDescriptors( m_xMutex, m_conn, m_pSettings ); diff --git a/connectivity/source/inc/FDatabaseMetaDataResultSet.hxx b/connectivity/source/inc/FDatabaseMetaDataResultSet.hxx index 6dcd7a199daf..03843436cfe4 100644 --- a/connectivity/source/inc/FDatabaseMetaDataResultSet.hxx +++ b/connectivity/source/inc/FDatabaseMetaDataResultSet.hxx @@ -32,33 +32,28 @@ #include #include #include -#include -#include + +#include #include #include -#include namespace connectivity { class ODatabaseMetaDataResultSetMetaData; - typedef ::comphelper::WeakComponentImplHelper< css::sdbc::XResultSet, - css::sdbc::XRow, - css::sdbc::XResultSetMetaDataSupplier, - css::util::XCancellable, - css::sdbc::XWarningsSupplier, - css::sdbc::XCloseable, - css::lang::XInitialization, - css::lang::XServiceInfo, - css::sdbc::XColumnLocate> ODatabaseMetaDataResultSet_BASE; - - // typedef ORefVector ORow; - // typedef ORefVector ORows; - - class SAL_DLLPUBLIC_RTTI ODatabaseMetaDataResultSet : - public ODatabaseMetaDataResultSet_BASE, - public ::comphelper::OPropertyContainer2, - public ::comphelper::OPropertyArrayUsageHelper + class SAL_DLLPUBLIC_RTTI ODatabaseMetaDataResultSet + : public comphelper::OPropertyContainerImplHelper< + comphelper::WeakComponentImplHelper< + css::sdbc::XResultSet, + css::sdbc::XRow, + css::sdbc::XResultSetMetaDataSupplier, + css::util::XCancellable, + css::sdbc::XWarningsSupplier, + css::sdbc::XCloseable, + css::lang::XInitialization, + css::lang::XServiceInfo, + css::sdbc::XColumnLocate>, + ODatabaseMetaDataResultSet> { public: @@ -131,8 +126,6 @@ namespace connectivity // OPropertyArrayUsageHelper OOO_DLLPUBLIC_DBTOOLS virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; - // OPropertySetHelper - OOO_DLLPUBLIC_DBTOOLS virtual ::cppu::IPropertyArrayHelper & getInfoHelper() override; bool next(std::unique_lock& ); bool isBeforeFirst(std::unique_lock& ); @@ -141,9 +134,6 @@ namespace connectivity virtual ~ODatabaseMetaDataResultSet() override; public: - OOO_DLLPUBLIC_DBTOOLS virtual void SAL_CALL acquire() noexcept override; - OOO_DLLPUBLIC_DBTOOLS virtual void SAL_CALL release() noexcept override; - /// default construction ODatabaseMetaDataResultSet(); /// construction of a pre-defined result set type @@ -159,12 +149,6 @@ namespace connectivity virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; // ::comphelper::WeakComponentImplHelper virtual void disposing(std::unique_lock&) override; - // XInterface - OOO_DLLPUBLIC_DBTOOLS virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override; - //XTypeProvider - virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override; - // XPropertySet - OOO_DLLPUBLIC_DBTOOLS virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; // XResultSet virtual sal_Bool SAL_CALL next( ) override; virtual sal_Bool SAL_CALL isBeforeFirst( ) override; diff --git a/connectivity/source/inc/dbase/dindexnode.hxx b/connectivity/source/inc/dbase/dindexnode.hxx index 181c6ff74322..a97c4db66770 100644 --- a/connectivity/source/inc/dbase/dindexnode.hxx +++ b/connectivity/source/inc/dbase/dindexnode.hxx @@ -75,7 +75,7 @@ namespace connectivity::dbase class ONDXPage; // Index Page Pointer - // This is ref-count pointer class + // This is a ref-counted pointer class class ONDXPagePtr { friend SvStream& WriteONDXPagePtr(SvStream &rStream, const ONDXPagePtr&); @@ -120,6 +120,7 @@ namespace connectivity::dbase sal_uInt32 nPagePos; // Position in the index file bool bModified : 1; sal_uInt16 nCount; + sal_uInt16 nNodeCapacity; // Number of entries allocated in ppNodes, one or more ONDXPagePtr aParent, // Parent page aChild; // Pointer to the right child page @@ -127,6 +128,8 @@ namespace connectivity::dbase std::unique_ptr ppNodes; // Array of nodes + sal_uInt16 ClampPos(sal_uInt16 nPos) const; + public: // Node operations sal_uInt16 Count() const {return nCount;} diff --git a/connectivity/source/inc/java/lang/Exception.hxx b/connectivity/source/inc/java/lang/Exception.hxx index 28b2d56dc90a..9981ffdacd91 100644 --- a/connectivity/source/inc/java/lang/Exception.hxx +++ b/connectivity/source/inc/java/lang/Exception.hxx @@ -28,7 +28,7 @@ namespace connectivity class java_lang_Exception : public java_lang_Throwable{ protected: - // statis Data for the class + // static Data for the class static jclass theClass; public: virtual jclass getMyClass() const override; diff --git a/connectivity/source/inc/java/lang/String.hxx b/connectivity/source/inc/java/lang/String.hxx index 2783b6eeb9bf..3e4b5bbd48af 100644 --- a/connectivity/source/inc/java/lang/String.hxx +++ b/connectivity/source/inc/java/lang/String.hxx @@ -25,7 +25,7 @@ namespace connectivity class java_lang_String : public java_lang_Object { protected: - // statis Data for the Class + // static Data for the Class static jclass theClass; public: virtual jclass getMyClass() const override; diff --git a/connectivity/source/inc/odbc/OTools.hxx b/connectivity/source/inc/odbc/OTools.hxx index c97ce4f4654a..a3c49cd79099 100644 --- a/connectivity/source/inc/odbc/OTools.hxx +++ b/connectivity/source/inc/odbc/OTools.hxx @@ -350,7 +350,7 @@ using SQLWChars = CHARS; #ifdef _WIN32 const bool bUseWChar = true; #else -const volatile inline bool bUseWChar = false; // volatile to avoid "unreachabe code" warnings +const volatile inline bool bUseWChar = false; // volatile to avoid "unreachable code" warnings #endif } diff --git a/connectivity/source/parse/sqlbison.y b/connectivity/source/parse/sqlbison.y index 9b125768d260..553df4f9f4af 100644 --- a/connectivity/source/parse/sqlbison.y +++ b/connectivity/source/parse/sqlbison.y @@ -4529,67 +4529,6 @@ void OSQLParser::setParseTree(OSQLParseNode* pNewParseTree) m_pParseTree.reset(pNewParseTree); } - -/** Delete all comments in a query. - - See also getComment()/concatComment() implementation for - OQueryController::translateStatement(). - */ -static OUString delComment( const OUString& rQuery ) -{ - // First a quick search if there is any "--" or "//" or "/*", if not then the whole - // copying loop is pointless. - if (rQuery.indexOf("--") < 0 && rQuery.indexOf("//") < 0 && - rQuery.indexOf("/*") < 0) - return rQuery; - - const sal_Unicode* pCopy = rQuery.getStr(); - sal_Int32 nQueryLen = rQuery.getLength(); - bool bIsText1 = false; // "text" - bool bIsText2 = false; // 'text' - bool bComment2 = false; // /* comment */ - bool bComment = false; // -- or // comment - OUStringBuffer aBuf(nQueryLen); - for (sal_Int32 i=0; i < nQueryLen; ++i) - { - if (bComment2) - { - if ((i+1) < nQueryLen) - { - if (pCopy[i]=='*' && pCopy[i+1]=='/') - { - bComment2 = false; - ++i; - } - } - else - { - // comment can't close anymore, actually an error, but... - } - continue; - } - if (pCopy[i] == '\n') - bComment = false; - else if (!bComment) - { - if (pCopy[i] == '\"' && !bIsText2) - bIsText1 = !bIsText1; - else if (pCopy[i] == '\'' && !bIsText1) - bIsText2 = !bIsText2; - if (!bIsText1 && !bIsText2 && (i+1) < nQueryLen) - { - if ((pCopy[i]=='-' && pCopy[i+1]=='-') || (pCopy[i]=='/' && pCopy[i+1]=='/')) - bComment = true; - else if ((pCopy[i]=='/' && pCopy[i+1]=='*')) - bComment2 = true; - } - } - if (!bComment && !bComment2) - aBuf.append( &pCopy[i], 1); - } - return aBuf.makeStringAndClear(); -} - std::unique_ptr OSQLParser::parseTree(OUString& rErrorMessage, const OUString& rStatement, bool bInternational) @@ -4601,12 +4540,9 @@ std::unique_ptr OSQLParser::parseTree(OUString& rErrorMessage, // must be reset setParser(this); - // delete comments before parsing - OUString sTemp = delComment(rStatement); - // defines how to scan s_pScanner->SetRule(OSQLScanner::GetSQLRule()); // initial - s_pScanner->prepareScan(sTemp, m_pContext, bInternational); + s_pScanner->prepareScan(rStatement, m_pContext, bInternational); SQLyylval.pParseNode = nullptr; // SQLyypvt = NULL; diff --git a/connectivity/source/parse/sqlflex.l b/connectivity/source/parse/sqlflex.l index b57b04235572..94237b3797c6 100644 --- a/connectivity/source/parse/sqlflex.l +++ b/connectivity/source/parse/sqlflex.l @@ -119,9 +119,11 @@ static void do_fatal_error(const char* msg) %s PREDICATE_GER %s DATE %s STRING +%x BLOCK_COMMENT %option noyywrap %option never-interactive +%option stack %% ABS {SQL_NEW_KEYWORD(SQL_TOKEN_ABS); } @@ -495,7 +497,12 @@ ZONE {SQL_NEW_KEYWORD(SQL_TOKEN_ZONE); } [ \t\r]+ {} -"--".*$ {} +"--"[^\n]* { /* line comment: consumed; preceding whitespace/comments are grouped with the next token */ } + +"/*" { yy_push_state(BLOCK_COMMENT); } +"*/" { yy_pop_state(); } +\n { } +. { } . {YY_FATAL_ERROR("Invalid symbol"); return SQL_TOKEN_INVALIDSYMBOL;} diff --git a/cppcanvas/qa/extras/emfplus/emfplus.cxx b/cppcanvas/qa/extras/emfplus/emfplus.cxx index fd740aa16a64..8301462277dc 100644 --- a/cppcanvas/qa/extras/emfplus/emfplus.cxx +++ b/cppcanvas/qa/extras/emfplus/emfplus.cxx @@ -35,7 +35,7 @@ public: std::shared_ptr xMetaFile = pShell->GetPreviewMetaFile(); Bitmap aResultBitmap; CPPUNIT_ASSERT(xMetaFile->CreateThumbnail(aResultBitmap)); - // If this is set, the metafile will be dumped as a PNG one for debug purposes. + // If this is set, the metafile will be dumped as a PNG for debug purposes. char* pEnv = getenv("CPPCANVAS_DEBUG_EMFPLUS_DUMP_TO"); if (pEnv) { diff --git a/cppcanvas/qa/unit/test.cxx b/cppcanvas/qa/unit/test.cxx index adab86604cfc..c23a076c6af5 100644 --- a/cppcanvas/qa/unit/test.cxx +++ b/cppcanvas/qa/unit/test.cxx @@ -152,7 +152,7 @@ CPPUNIT_TEST_FIXTURE(CanvasTest, testTdf155810) aOutputMetaFile.Stop(); } - // Then check that the text array drawn by the canvas renderer didn’t loose + // Then check that the text array drawn by the canvas renderer didn’t lose // the Kashida insertion positions. { auto pInputAction = aInputMetaFile.GetAction(aInputMetaFile.GetActionSize() - 1); diff --git a/cppcanvas/source/mtfrenderer/implrenderer.cxx b/cppcanvas/source/mtfrenderer/implrenderer.cxx index cf9e845a8193..d3214c990438 100644 --- a/cppcanvas/source/mtfrenderer/implrenderer.cxx +++ b/cppcanvas/source/mtfrenderer/implrenderer.cxx @@ -789,16 +789,16 @@ namespace cppcanvas::internal if( nFontWidthLog != 0 ) { vcl::Font aTestFont = rFont; - aTestFont.SetAverageFontWidth( 0 ); - sal_Int32 nNormalWidth = rParms.mrVDev.GetFontMetric( aTestFont ).GetAverageFontWidth(); + aTestFont.SetFontWidth( 0 ); + sal_Int32 nNormalWidth = rParms.mrVDev.GetFontMetric( aTestFont ).GetFontWidth(); if( nNormalWidth != nFontWidthLog ) if( nNormalWidth ) aFontMatrix.m00 = static_cast(nFontWidthLog) / nNormalWidth; } // #i52608# apply map mode scale also to font matrix - an - // anisotrophic mapmode must be reflected in an - // anisotrophic font matrix scale. + // anisotropic mapmode must be reflected in an + // anisotropic font matrix scale. const OutDevState& rState( rParms.mrStates.getState() ); if( !::basegfx::fTools::equal( rState.mapModeTransform.get(0,0), diff --git a/cppu/source/threadpool/threadpool.cxx b/cppu/source/threadpool/threadpool.cxx index 43d3693696c1..29fd7d0eb8c1 100644 --- a/cppu/source/threadpool/threadpool.cxx +++ b/cppu/source/threadpool/threadpool.cxx @@ -179,7 +179,7 @@ namespace cppu_threadpool std::scoped_lock guard( m_mutex ); ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId ); - OSL_ASSERT( ii != m_mapQueue.end() ); + assert( ii != m_mapQueue.end() ); if( bAsynchron ) { @@ -237,7 +237,7 @@ namespace cppu_threadpool { m_mapQueue[ aThreadId ] = std::pair < JobQueue * , JobQueue * > ( nullptr , nullptr ); ii = m_mapQueue.find( aThreadId ); - OSL_ASSERT( ii != m_mapQueue.end() ); + assert( ii != m_mapQueue.end() ); } if( bAsynchron ) diff --git a/cppu/source/uno/check.cxx b/cppu/source/uno/check.cxx index 561434aa55f3..60ab3dba4e30 100644 --- a/cppu/source/uno/check.cxx +++ b/cppu/source/uno/check.cxx @@ -260,14 +260,7 @@ static_assert(sizeof(second) == sizeof(int), "sizeof(second) != sizeof(int)"); struct Char4 { -#if defined __GNUC__ && (__GNUC__ < 12 || (__GNUC__ == 12 && __GNUC_MINOR__ < 1)) && !defined __clang__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wattributes" -#endif [[maybe_unused]] Char3 chars; -#if defined __GNUC__ && (__GNUC__ < 12 || (__GNUC__ == 12 && __GNUC_MINOR__ < 1)) && !defined __clang__ -#pragma GCC diagnostic pop -#endif char c; }; diff --git a/cppuhelper/source/defaultbootstrap.cxx b/cppuhelper/source/defaultbootstrap.cxx index ca70a91d3f57..e66052af42db 100644 --- a/cppuhelper/source/defaultbootstrap.cxx +++ b/cppuhelper/source/defaultbootstrap.cxx @@ -27,7 +27,7 @@ #include "servicemanager.hxx" #include "typemanager.hxx" -namespace com :: sun :: star :: uno { class XComponentContext; } +namespace com::sun::star::uno { class XComponentContext; } namespace { diff --git a/cppuhelper/source/interfacecontainer.cxx b/cppuhelper/source/interfacecontainer.cxx index c97a8ba9908c..c3c084d07f35 100644 --- a/cppuhelper/source/interfacecontainer.cxx +++ b/cppuhelper/source/interfacecontainer.cxx @@ -93,7 +93,7 @@ XInterface * OInterfaceIteratorHelper::next() { nRemain--; if( bIsList ) - // typecase to const,so the getArray method is faster + // typecast to const,so the getArray method is faster return (*aData.pAsVector)[nRemain].get(); if( aData.pAsInterface ) return aData.pAsInterface; diff --git a/cppuhelper/source/paths.cxx b/cppuhelper/source/paths.cxx index 0a4ccf76e6ef..171a3013591e 100644 --- a/cppuhelper/source/paths.cxx +++ b/cppuhelper/source/paths.cxx @@ -34,7 +34,7 @@ namespace { -#if !(defined ANDROID || defined EMSCRIPTEN) +#if !(defined ANDROID || defined __EMSCRIPTEN__) OUString get_this_libpath() { static OUString s_uri = []() { OUString uri; @@ -61,7 +61,7 @@ OUString cppu::getUnoIniUri() { // and since rtlBootstrapHandle is not ref-counted doing anything // clean here is hardish. OUString uri("file:///assets/program"); -#elif defined(EMSCRIPTEN) +#elif defined(__EMSCRIPTEN__) OUString uri("file:///instdir/program"); #else OUString uri(get_this_libpath()); diff --git a/cppuhelper/source/propertysetmixin.cxx b/cppuhelper/source/propertysetmixin.cxx index 78b1c2204a28..64961fd1df4c 100644 --- a/cppuhelper/source/propertysetmixin.cxx +++ b/cppuhelper/source/propertysetmixin.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -373,13 +374,13 @@ public: PropertySetMixinImpl::Implements implements; css::uno::Sequence< OUString > handleMap; - typedef std::map< OUString, BoundListenerBag > BoundListenerMap; + typedef std::unordered_map< OUString, BoundListenerBag > BoundListenerMap; typedef std::multiset< css::uno::Reference< css::beans::XVetoableChangeListener > > VetoListenerBag; - typedef std::map< OUString, VetoListenerBag > VetoListenerMap; + typedef std::unordered_map< OUString, VetoListenerBag > VetoListenerMap; mutable std::mutex mutex; BoundListenerMap boundListeners; diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx index 8ab144b115ee..2d1215761c34 100644 --- a/cppuhelper/source/servicemanager.hxx +++ b/cppuhelper/source/servicemanager.hxx @@ -38,8 +38,8 @@ namespace com::sun::star::lang { class XSingleComponentFactory; } namespace cppu { struct ContextEntry_Init; } -namespace com :: sun :: star :: lang { class XSingleServiceFactory; } -namespace com :: sun :: star :: uno { class XComponentContext; } +namespace com::sun::star::lang { class XSingleServiceFactory; } +namespace com::sun::star::uno { class XComponentContext; } class RegistryKey; diff --git a/cpputools/source/sp2bv/sp2bv.cxx b/cpputools/source/sp2bv/sp2bv.cxx index 9d502c9b4e42..651b0b2e99e7 100644 --- a/cpputools/source/sp2bv/sp2bv.cxx +++ b/cpputools/source/sp2bv/sp2bv.cxx @@ -21,6 +21,7 @@ #include #include #include +#include static bool hasOption(char const * szOption, int argc, char** argv); @@ -80,7 +81,7 @@ int main(int argc, char **argv) break; case '{': case '}': - case '\\': fprintf(stderr, "sp2vb: file URL contains invalid characters!\n"); + case '\\': fprintf(stderr, "sp2bv: file URL contains invalid characters!\n"); return -1; default: rtl_uStringbuffer_insert( &pBuffer, &nCapacity, pBuffer->length, pCur, 1); @@ -105,16 +106,7 @@ int main(int argc, char **argv) static bool hasOption(char const * szOption, int argc, char** argv) { - bool retVal = false; - for(int i= 1; i < argc; i++) - { - if( ! strcmp(argv[i], szOption)) - { - retVal = true; - break; - } - } - return retVal; + return std::any_of(argv + 1, argv + argc, [szOption](const char* s){ return !strcmp(s, szOption); }); } diff --git a/cpputools/source/unoexe/unoexe.cxx b/cpputools/source/unoexe/unoexe.cxx index 0ed543ba0335..e20bc52d325a 100644 --- a/cpputools/source/unoexe/unoexe.cxx +++ b/cpputools/source/unoexe/unoexe.cxx @@ -89,7 +89,7 @@ const char arUsingText[] = static bool readOption( OUString * pValue, const char * pOpt, sal_uInt32 * pnIndex, const OUString & aArg) { - static constexpr OUString dash(u"-"_ustr); + static constexpr std::u16string_view dash(u"-"); if(!aArg.startsWith(dash)) return false; diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk index ae03e5ce9422..4456cb86f718 100644 --- a/cui/Library_cui.mk +++ b/cui/Library_cui.mk @@ -113,8 +113,6 @@ $(eval $(call gb_Library_add_exception_objects,cui,\ cui/source/customize/SvxConfigPageHelper \ cui/source/customize/SvxMenuConfigPage \ cui/source/customize/SvxToolbarConfigPage \ - cui/source/customize/SvxNotebookbarConfigPage \ - cui/source/customize/CustomNotebookbarGenerator \ cui/source/dialogs/about \ $(call gb_Helper_optional,EXTENSIONS, \ cui/source/dialogs/AdditionsDialog) \ @@ -142,7 +140,6 @@ $(eval $(call gb_Library_add_exception_objects,cui,\ cui/source/dialogs/screenshotannotationdlg \ cui/source/dialogs/pastedlg \ cui/source/dialogs/postdlg \ - cui/source/dialogs/querydialog \ cui/source/dialogs/QrCodeGenDialog \ cui/source/dialogs/GraphicTestsDialog \ cui/source/dialogs/ImageViewerDialog \ @@ -192,7 +189,6 @@ $(eval $(call gb_Library_add_exception_objects,cui,\ cui/source/options/optgenrl \ cui/source/options/opthtml \ cui/source/options/optlanguagetool \ - cui/source/options/optdeepl \ cui/source/options/optinet2 \ cui/source/options/optjava \ cui/source/options/optjsearch \ @@ -222,6 +218,7 @@ $(eval $(call gb_Library_add_exception_objects,cui,\ cui/source/tabpages/numpages \ cui/source/tabpages/page \ cui/source/tabpages/paragrph \ + cui/source/tabpages/SvxPresetListBox \ cui/source/tabpages/swpossizetabpage \ cui/source/tabpages/tabarea \ cui/source/tabpages/tabline \ @@ -242,6 +239,7 @@ $(eval $(call gb_Library_add_exception_objects,cui,\ cui/source/tabpages/tptrans \ cui/source/tabpages/transfrm \ cui/source/util/FontFeatures \ + cui/source/util/GetDocumentModel \ cui/source/dialogs/widgettestdlg \ )) diff --git a/cui/UIConfig_cui.mk b/cui/UIConfig_cui.mk index 8b89014d42a8..9c65874891a8 100644 --- a/cui/UIConfig_cui.mk +++ b/cui/UIConfig_cui.mk @@ -137,7 +137,6 @@ $(eval $(call gb_UIConfig_add_uifiles,cui,\ cui/uiconfig/ui/optbasicidepage \ cui/uiconfig/ui/optctlpage \ cui/uiconfig/ui/optchartcolorspage \ - cui/uiconfig/ui/optdeeplpage \ cui/uiconfig/ui/optemailpage \ cui/uiconfig/ui/optfltrpage \ cui/uiconfig/ui/optfltrembedpage \ @@ -185,7 +184,6 @@ $(eval $(call gb_UIConfig_add_uifiles,cui,\ cui/uiconfig/ui/querydeletehatchdialog \ cui/uiconfig/ui/querydeletelineenddialog \ cui/uiconfig/ui/querydeletelinestyledialog \ - cui/uiconfig/ui/querydialog \ cui/uiconfig/ui/queryduplicatedialog \ cui/uiconfig/ui/querynoloadedfiledialog \ cui/uiconfig/ui/querynosavefiledialog \ diff --git a/cui/inc/bitmaps.hlst b/cui/inc/bitmaps.hlst index e118dc05d86a..d064f7aee321 100644 --- a/cui/inc/bitmaps.hlst +++ b/cui/inc/bitmaps.hlst @@ -89,6 +89,4 @@ inline constexpr OUString RID_SVXBMP_TOTD_DRAW = u"res/tipoftheday_d.png"_ustr; inline constexpr OUString RID_SVXBMP_TOTD_IMPRESS = u"res/tipoftheday_i.png"_ustr; inline constexpr OUString RID_SVXBMP_TOTD_SOFFICE = u"res/tipoftheday.png"_ustr; -inline constexpr OUString RID_CUIBMP_QUERY = u"res/query.png"_ustr; - /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/inc/pch/precompiled_cui.hxx b/cui/inc/pch/precompiled_cui.hxx index 91a156d512b4..54f365643921 100644 --- a/cui/inc/pch/precompiled_cui.hxx +++ b/cui/inc/pch/precompiled_cui.hxx @@ -161,7 +161,6 @@ #include #include #include -#include #include #include #include @@ -308,7 +307,6 @@ #include #include #include -#include #include #include #include diff --git a/cui/inc/strings.hrc b/cui/inc/strings.hrc index fb8b67f59d09..b4b0e3b82cd9 100644 --- a/cui/inc/strings.hrc +++ b/cui/inc/strings.hrc @@ -266,6 +266,7 @@ #define RID_CUISTR_OPT_GRAMMAR_BY NC_("RID_SVXSTR_OPT_GRAMMAR_BY", "~Grammar By") #define STR_MODIFY NC_("STR_MODIFY", "~Replace") #define RID_CUISTR_CONFIRM_SET_LANGUAGE NC_("RID_SVXSTR_CONFIRM_SET_LANGUAGE", "Do you want to change the '%1' dictionary language?") +#define RID_CUISTR_OPT_DICT_SEARCH_PLACEHOLDER NC_("RID_SVXSTR_OPT_DICT_SEARCH_PLACEHOLDER", "Type to search...") #define RID_CUISTR_COLOR_CONFIG_DELETE NC_("RID_SVXSTR_COLOR_CONFIG_DELETE", "Do you really want to delete the color scheme?") #define RID_CUISTR_COLOR_CONFIG_DELETE_TITLE NC_("RID_SVXSTR_COLOR_CONFIG_DELETE_TITLE", "Color Scheme Deletion") @@ -307,6 +308,8 @@ #define RID_CUISTR_DESC_COLOR NC_("RID_SVXSTR_DESC_COLOR", "Please enter a name for the new color:") #define RID_CUISTR_TABLE NC_("RID_SVXSTR_TABLE", "Table") #define RID_CUISTR_DESC_LINEEND NC_("RID_SVXSTR_DESC_LINEEND", "Please enter a name for the new arrow style:") +// To translators: The %1 will be replaced with a font style name like “No Bold”, ie, it’s the word +// “no” and not an abbreviation for “number” #define RID_CUISTR_CHARNAME_NOSTYLE NC_("RID_SVXSTR_CHARNAME_NOSTYLE", "No %1") #define RID_CUISTR_CHARNAME_FAMILY NC_("RID_SVXSTR_CHARNAME_FAMILY", "Family:") #define RID_CUISTR_CHARNAME_FONT NC_("RID_SVXSTR_CHARNAME_FONT", "Font:") @@ -325,6 +328,7 @@ #define RID_CUISTR_ORDINAL NC_("RID_SVXSTR_ORDINAL", "Format ordinal numbers suffixes (1st -> 1^st)") #define RID_CUISTR_OLD_HUNGARIAN NC_("RID_SVXSTR_OLD_HUNGARIAN", "Transliterate to Old Hungarian if the text direction is from right to left") #define RID_CUISTR_ANGLE_QUOTES NC_("RID_SVXSTR_ANGLE_QUOTES", "Replace two inequality signs (<< or >>) with angle quotes") +#define RID_CUISTR_ESPERANTO_HATS NC_("RID_CUISTR_ESPERANTO_HATS", "Replace x’s with circumflexes in Esperanto text") #define RID_CUISTR_DEL_EMPTY_PARA NC_("RID_SVXSTR_DEL_EMPTY_PARA", "Remove blank paragraphs") #define RID_CUISTR_USER_STYLE NC_("RID_SVXSTR_USER_STYLE", "Replace Custom Styles") #define RID_CUISTR_BULLET NC_("RID_SVXSTR_BULLET", "Replace bullets with: %1") @@ -385,7 +389,12 @@ #define RID_CUISTR_ADDITIONS_THEMES NC_("RID_SVXSTR_ADDITIONS_THEMES", "Extensions: Color Themes") #define RID_CUISTR_ADDITIONS_TEMPLATES NC_("RID_SVXSTR_ADDITIONS_TEMPLATES", "Extensions: Templates") -#define RID_CUISTR_UI_APPLY NC_("RID_SVXSTR_UI_APPLY", "Apply to %MODULE") +// Application names for the “Apply to X” button in the UI chooser dialog +#define RID_CUISTR_UI_APPLY_TO_WRITER NC_("RID_CUISTR_UI_APPLY_TO_WRITER", "Apply to Writer") +#define RID_CUISTR_UI_APPLY_TO_CALC NC_("RID_CUISTR_UI_APPLY_TO_CALC", "Apply to Calc") +#define RID_CUISTR_UI_APPLY_TO_IMPRESS NC_("RID_CUISTR_UI_APPLY_TO_IMPRESS", "Apply to Impress") +#define RID_CUISTR_UI_APPLY_TO_DRAW NC_("RID_CUISTR_UI_APPLY_TO_DRAW", "Apply to Draw") + #define RID_CUISTR_UI_APPLYALL NC_("RID_SVXSTR_UI_APPLYALL", "Apply to All") #define RID_CUISTR_OLE_INSERT NC_("RID_SVXSTR_OLE_INSERT", "Inserting OLE object...") @@ -528,6 +537,10 @@ #define REG_SQLCOMMENT NC_("REG_SQLCOMMENT", "SQL Comment") #define REG_WINDOWCOLOR NC_("REG_WINDOWCOLOR", "Window color") #define REG_WINDOWTEXTCOLOR NC_("REG_WINDOWTEXTCOLOR", "Window text color") +#define REG_WRITERNOTEBOOKBARCOLOR NC_("REG_WRITERNOTEBOOKBARCOLOR", "Writer Notebookbar color") +#define REG_CALCNOTEBOOKBARCOLOR NC_("REG_CALCNOTEBOOKBARCOLOR", "Calc Notebookbar color") +#define REG_IMPRESSNOTEBOOKBARCOLOR NC_("REG_IMPRESSNOTEBOOKBARCOLOR", "Impress Notebookbar color") +#define REG_DRAWNOTEBOOKBARCOLOR NC_("REG_DRAWNOTEBOOKBARCOLOR", "Draw Notebookbar color") #define REG_BASECOLOR NC_("REG_BASECOLOR", "Base color") #define REG_BUTTONCOLOR NC_("REG_BUTTONCOLOR", "Button color") #define REG_BUTTONTEXTCOLOR NC_("REG_BUTTONTEXTCOLOR", "Button text color") diff --git a/cui/inc/tipoftheday.hrc b/cui/inc/tipoftheday.hrc index 89b03727dc7a..d63351e84851 100644 --- a/cui/inc/tipoftheday.hrc +++ b/cui/inc/tipoftheday.hrc @@ -54,7 +54,7 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "%PRODUCTNAME offers a variety of user interface options to make you feel at home"), ".uno:UIPicker", "toolbarmode.png", soffice}, { NC_("RID_CUI_TIPOFTHEDAY", "Need to allow changes to parts of a read-only document in Writer? Insert frames or sections that can authorize changes."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/swriter/guide/section_edit.html", "", swriter}, //local help missing { NC_("RID_CUI_TIPOFTHEDAY", "To print the notes of your slides go to File ▸ Print ▸ %PRODUCTNAME Impress tab and select Notes under Document ▸ Type."), "", "printnote.png", soffice}, - { NC_("RID_CUI_TIPOFTHEDAY", "To start temporarily with a fresh user profile, or to restore a non-working %PRODUCTNAME, use Help ▸ Restart in Safe Mode."), "svx/ui/safemodedialog/SafeModeDialog", "", soffice}, //https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/shared/01/profile_safe_mode.html + { NC_("RID_CUI_TIPOFTHEDAY", "To start temporarily with a fresh user profile, or to restore a non-working %PRODUCTNAME, use Help ▸ Restart in Troubleshoot Mode."), "svx/ui/safemodedialog/SafeModeDialog", "", soffice}, //https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/shared/01/profile_safe_mode.html { NC_("RID_CUI_TIPOFTHEDAY", "Writing a book? %PRODUCTNAME master document lets you manage large documents as a container for individual %PRODUCTNAME Writer files."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/swriter/guide/globaldoc.html", "", swriter}, //local help missing { NC_("RID_CUI_TIPOFTHEDAY", "You can create editable Hybrid PDFs with %PRODUCTNAME."), "https://wiki.documentfoundation.org/Documentation/HowTo/CreateAHybridPDF", "hybrid_pdf.png", soffice}, { NC_("RID_CUI_TIPOFTHEDAY", "Explore the ten different functions in the status bar (at the bottom of the document window). Place the cursor over each field for an explanation. If not visible, use View ▸ Status Bar."), "", "", swriter}, @@ -84,18 +84,18 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "Want to sort a series in %PRODUCTNAME Calc such as A1, A2, A3, A11, A15, not in alphabetical order but on the number? Enable natural sort in the Options tab."), "modules/scalc/ui/sortoptionspage/SortOptionsPage", "", scalc}, //https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/scalc/01/12030200.html { NC_("RID_CUI_TIPOFTHEDAY", "You can change the default function in the status bar: right click on the area."), "", "statusbar.png", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Want to add many of the same shapes in Draw/Impress? Double-click a tool in the drawing toolbar to use it for repeated tasks."), "", "", sdraw}, - { NC_("RID_CUI_TIPOFTHEDAY", "%MOD1+Shift+F9 recalculates all formulas in all spreadsheets."), "", "", scalc}, + { NC_("RID_CUI_TIPOFTHEDAY", "%MOD1+%SHIFT+F9 recalculates all formulas in all spreadsheets."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Want to keep a part of an editable document as read-only? Insert ▸ Section. Add text to the section, then right-click “Edit Section” and check “Protect”."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Use the Backspace key instead of Delete in Calc. You can choose what to delete."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "The best way to fix bad-looking MS Word table cells is via Table ▸ Size ▸ Optimal Row Height / Column Width."), "", "", swriter}, - { NC_("RID_CUI_TIPOFTHEDAY", "To repeat a table heading when a table spans over a page, use Table ▸ Table Properties ▸ Text Flow ▸ Repeat heading."), "", "", swriter}, + { NC_("RID_CUI_TIPOFTHEDAY", "To repeat a table header when a table spans over a page, use Table ▸ Table Properties ▸ Text Flow ▸ Repeat header."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Want to quickly insert or delete rows? Select the desired number of rows (or columns) and press %MOD1+Plus sign (+) to add or %MOD1+Minus sign (-) to delete."), "modules/scalc/ui/insertcells/InsertCellsDialog", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "To repeat rows/columns on every pages use Format ▸ Print Ranges ▸ Edit."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Insert images and photos into shapes in Draw and Impress. Right-click on a shape, choose Area ▸ Image ▸ Add / Import, and use Options to adjust appearance."), "", "", sdraw}, - { NC_("RID_CUI_TIPOFTHEDAY", "Need to insert the date in a spreadsheet cell? Type %MOD1+; or Shift+%MOD1+; to insert the time."), "", "", scalc}, + { NC_("RID_CUI_TIPOFTHEDAY", "Need to insert the date in a spreadsheet cell? Type %MOD1+; or %SHIFT+%MOD1+; to insert the time."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Insert your metadata in your document with Insert ▸ Fields ▸ More Fields… ▸ Document or DocInformation."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Get help from the community via the Ask portal."), "https://ask.libreoffice.org", "", soffice}, - { NC_("RID_CUI_TIPOFTHEDAY", "Use Shift+Space to select the current row and %MOD3+Space to select the current column."), "", "", scalc}, + { NC_("RID_CUI_TIPOFTHEDAY", "Use %SHIFT+Space to select the current row and %MOD3+Space to select the current column."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "You can move an object to another layer by holding it until its edges flash, then drag it to the tab of the layer you want to move it to."), "", "", sdraw}, { NC_("RID_CUI_TIPOFTHEDAY", "Data ▸ Validity allows you to create drop-down lists where the user selects a value instead of typing."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/scalc/guide/validity.html", "", scalc}, //local help missing { NC_("RID_CUI_TIPOFTHEDAY", "Hold down %MOD1 and turn the mouse wheel to change the zoom factor."), "", "", soffice}, @@ -118,7 +118,7 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "Want to find words containing 10 or more characters? Edit ▸ Find and Replace ▸ Search ▸ \\w{10,} ▸ Other Options ▸ check Regular expressions."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Open a CSV file as a new sheet in the current spreadsheet via Sheet ▸ Sheet from file."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "You can continue writing with the default formatting attributes after manually applying bold, italic or underline by pressing %MOD1+M."), "", "", swriter}, - { NC_("RID_CUI_TIPOFTHEDAY", "Use %MOD1+%MOD2+Shift+V to paste the contents of the clipboard as unformatted text."), "", "", swriter}, + { NC_("RID_CUI_TIPOFTHEDAY", "Use %MOD1+%MOD2+%SHIFT+V to paste the contents of the clipboard as unformatted text."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Customize footnote appearance with Tools ▸ Footnote/Endnote Settings…"), ".uno:FootnoteDialog", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "With Slide Show ▸ Custom Slide Show, reorder and pick slides to fit a slideshow to the needs of your viewers."), "", "", simpress}, { NC_("RID_CUI_TIPOFTHEDAY", "Want to change spell checking for some part of the text? Click in the language zone of the status bar or better, apply a style."), "", "", swriter}, @@ -138,7 +138,7 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "Left-handed? Enable Tools ▸ Options ▸ Languages and Locales ▸ General ▸ Asian and check Tools ▸ Options ▸ %PRODUCTNAME Writer ▸ View ▸ Ruler ▸ Right-aligned, which displays the scrollbar to the left."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Want headings to always begin a page? Edit the paragraph style applied to the headings. Check “Insert” on the “Text Flow” tab, with Type “Page” and Position “Before”."), "cui/ui/textflowpage/checkInsert", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Date/time value is just a number of days since a chosen day zero; in the number, integer part represents date, and fractional part is time (elapsed part of a day), with 0.5 representing noon."), "", "", scalc}, - { NC_("RID_CUI_TIPOFTHEDAY", "Shift+%MOD1+Del deletes from cursor to the end of the current sentence."), "", "", swriter}, + { NC_("RID_CUI_TIPOFTHEDAY", "%SHIFT+%MOD1+Del deletes from cursor to the end of the current sentence."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Use column or row labels in formulas. For example, if you have two columns, “Time” and “KM”, use =Time/KM to get minutes per kilometer."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Annoyed by the “marching ants” around cells in Calc? Press escape to stop them; the copied content will remain available for pasting."), "", "marchingants.gif", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Want to become a %PRODUCTNAME Ambassador? There are certifications for developers, admins, and trainers."), "https://www.documentfoundation.org/certification/program/", "", soffice}, @@ -174,13 +174,13 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "Want to manage the presentation of hyperlinks in a spreadsheet? Insert them with the HYPERLINK function."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/scalc/01/04060109.html", "", scalc}, //local help missing { NC_("RID_CUI_TIPOFTHEDAY", "Uncheck Tools ▸ Options ▸ %PRODUCTNAME Calc ▸ View ▸ Zoom: “Synchronize sheets” so that each sheet in Calc has its own zoom factor."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "You can set a color for each tab: right-click the tab or use Sheet ▸ Sheet Tab Color."), "", "", scalc}, - { NC_("RID_CUI_TIPOFTHEDAY", "Trace cells used in a formula, precedents (Shift+F9) or dependents (Shift+F5) (or use Tools ▸ Detective). For each hit you go one more step in the chain."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/scalc/01/06030000.html", "", scalc}, //local help missing + { NC_("RID_CUI_TIPOFTHEDAY", "Trace cells used in a formula, precedents (%SHIFT+F9) or dependents (%SHIFT+F5) (or use Tools ▸ Detective). For each hit you go one more step in the chain."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/scalc/01/06030000.html", "", scalc}, //local help missing { NC_("RID_CUI_TIPOFTHEDAY", "Insert and number your formulas in one step: type fn then F3. An AutoText is inserted with formula and number aligned in a table."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "You can create an illustration index from object names, not only from captions."), "cui/ui/objectnamedialog/ObjectNameDialog", "", swriter}, //https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/shared/01/05190000.html { NC_("RID_CUI_TIPOFTHEDAY", "Use your Android or iPhone to remotely control your Impress presentation."), "https://help.libreoffice.org/%PRODUCTVERSION/he/text/simpress/guide/impress_remote.html", "", simpress}, //local help missing { NC_("RID_CUI_TIPOFTHEDAY", "Want to know how many days there are in the current month? Use the DAYSINMONTH(TODAY()) function."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Your numbers are displayed as ### in your spreadsheet? The column is too narrow to display all digits."), "", "", scalc}, - { NC_("RID_CUI_TIPOFTHEDAY", "Enable massive parallel calculations of formula cells via Tools ▸ Options ▸ %PRODUCTNAME Calc ▸ Calculate ▸ OpenCL Options."), "cui/ui/optcalculatepage/OptOpenCLPage", "", scalc}, //https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/shared/optionen/opencl.html + { NC_("RID_CUI_TIPOFTHEDAY", "Enable massive parallel calculations of formula cells via Tools ▸ Options ▸ %PRODUCTNAME Calc ▸ Calculate ▸ CPU Threading Settings."), "cui/ui/optcalculatepage/OptOpenCLPage", "", scalc}, //https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/shared/optionen/opencl.html { NC_("RID_CUI_TIPOFTHEDAY", "Use the Connector tool from the Drawing toolbar in Draw/Impress to create nice flow charts and optionally copy/paste the object into Writer."), "", "", sdraw}, { NC_("RID_CUI_TIPOFTHEDAY", "Your donations support our worldwide community."), "https://www.libreoffice.org/donate/", "", soffice}, { NC_("RID_CUI_TIPOFTHEDAY", "You want to add x months to a date? Use =EDATE(date;months)."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/scalc/01/func_edate.html", "", scalc}, //local help missing @@ -207,7 +207,7 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "You want to start working with Basic macros? Take a look at the examples under Tools ▸ Macros ▸ Edit Macros."), "", "", soffice}, { NC_("RID_CUI_TIPOFTHEDAY", "Apply Heading paragraph styles in Writer with shortcut keys: %MOD1+1 applies Heading 1, %MOD1+2 applies Heading 2, etc."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Do not get lost in large documents. Use the Navigator (F5) to find your way through the content."), "", "", swriter}, - { NC_("RID_CUI_TIPOFTHEDAY", "Edit ▸ Find and Replace lets you insert special characters directly: right click in input fields or press Shift+%MOD1+S."), "", "", soffice}, + { NC_("RID_CUI_TIPOFTHEDAY", "Edit ▸ Find and Replace lets you insert special characters directly: right click in input fields or press %SHIFT+%MOD1+S."), "", "", soffice}, { NC_("RID_CUI_TIPOFTHEDAY", "Need custom contents for metadata properties? File ▸ Properties ▸ Custom Properties tab lets you create what you want."), "", "", soffice}, { NC_("RID_CUI_TIPOFTHEDAY", "Want to see, but not print, an object in Draw? Draw it on a layer for which the “Printable” flag is not set (right-click the layer’s tab and choose “Modify Layer”)."), "", "", sdraw}, { NC_("RID_CUI_TIPOFTHEDAY", "To insert the current date in your document, use Insert ▸ Field ▸ Date."), "", "", swriter}, @@ -224,7 +224,7 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "Use font embedding for greater interoperability with other office suites at File ▸ Properties ▸ Font."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "To convert a formula into static values you do not need to copy/paste; use Data ▸ Calculate ▸ Formula to Value."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "You can reformat all comments in a document by clicking the down arrow in a comment and choose “Format all Comments”."), "", "", swriter}, - { NC_("RID_CUI_TIPOFTHEDAY", "Writer helps you to make backups: with File ▸ Save a Copy you create a new document continuing to work on the original."), "", "", swriter}, + { NC_("RID_CUI_TIPOFTHEDAY", "Create a backup of your document in Writer by selecting File ▸ Save a Copy while continuing to work on the original."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "When you have created a Style based on another, you can enter a percentage value or a point value (e.g. 110% or −2pt or +5pt)."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "To copy a comment without losing the content of the target cell you should use Paste Special and uncheck everything except “Comments” in dialog. Use Operations “Add” to not override existing content."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Batch-convert your Microsoft Office documents to the OpenDocument format by using the Document Converter wizard in menu File ▸ Wizards ▸ Document Converter."), "", "", soffice}, @@ -236,7 +236,7 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "Want to return to default after applying a list style? Click Bullets or Numbering On/Off tool on the Formatting toolbar."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Delete all of your printing areas in one step: select all sheets, then Format ▸ Print Ranges ▸ Clear."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Add background images to spreadsheets via Insert ▸ Image or drag a background from the Gallery, then Format ▸ Arrange ▸ To Background."), "", "", scalc}, - { NC_("RID_CUI_TIPOFTHEDAY", "Having trouble pasting text from PDF files or webpages into documents? Try to paste as unformatted text (%MOD1+%MOD2+Shift+V)."), "", "", swriter}, + { NC_("RID_CUI_TIPOFTHEDAY", "Having trouble pasting text from PDF files or webpages into documents? Try to paste as unformatted text (%MOD1+%MOD2+%SHIFT+V)."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "In Calc use TRIMMEAN() to return the mean of a data set excluding the highest and lowest values."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/scalc/01/04060182.html?DbPAR=CALC#bm_id3152966", "", scalc}, //local help missing { NC_("RID_CUI_TIPOFTHEDAY", "The 4th optional parameter of VLOOKUP Calc function indicates whether the first column of data is sorted. If not, enter FALSE or zero."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "Toolbars are contextual—they open depending on the context. If you do not want that, uncheck them from View ▸ Toolbars."), "", "", soffice}, @@ -262,7 +262,7 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "Apart from table of contents, %PRODUCTNAME can create Alphabetical, Illustrations, Tables, Objects, Bibliography, User-Defined indexes."), "modules/swriter/ui/tocdialog/TocDialog", "", swriter}, //https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/swriter/guide/indices_toc.html { NC_("RID_CUI_TIPOFTHEDAY", "Unable to modify or delete a custom cell style? Check all sheets, none should be protected."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "You need to fill a series? Select the cell range and Sheet ▸ Fill Cells ▸ Fill Series and choose between Linear, Growth, Date and AutoFill."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/scalc/guide/calc_series.html", "", scalc}, //local help missing - { NC_("RID_CUI_TIPOFTHEDAY", "Want to know if a cell is referred in formulas of other cells? Tools ▸ Detective ▸ Trace Dependents (Shift+F5)."), "", "", scalc}, + { NC_("RID_CUI_TIPOFTHEDAY", "Want to know if a cell is referred in formulas of other cells? Tools ▸ Detective ▸ Trace Dependents (%SHIFT+F5)."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "In the replace input field of auto correct options you can use the wildcards .*"), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "Want to duplicate the above line? Press %MOD1+D or use Sheet ▸ Fill Cells ▸ Fill Down."), "", "", scalc}, { NC_("RID_CUI_TIPOFTHEDAY", "To search in several spreadsheets, select them before you start the search."), "", "", scalc}, @@ -273,10 +273,10 @@ const std::tuple TIPOFTHEDAY_STRINGA { NC_("RID_CUI_TIPOFTHEDAY", "Drag a formatted object to the Styles and Formatting window. A dialog box opens, just enter the name of the new style."), "", "", swriter}, { NC_("RID_CUI_TIPOFTHEDAY", "New versions of %PRODUCTNAME provide new features, bug fixes, and security patches. Keep your software updated!"), "SFX2_HID_DLG_CHECKFORONLINEUPDATE", "", soffice}, { NC_("RID_CUI_TIPOFTHEDAY", "Developing new XSLT and XML filters?"), "https://fridrich.blogspot.com/2013/08/extending-swiss-army-knife-overview.html", "", soffice}, - { NC_("RID_CUI_TIPOFTHEDAY", "Press Shift+F1 to see any available extended tooltips in dialog boxes, when \"Extended tips\" is not enabled in Tools ▸ Options ▸ %PRODUCTNAME ▸ General."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/shared/05/00000120.html", "", soffice}, + { NC_("RID_CUI_TIPOFTHEDAY", "Press %SHIFT+F1 to see any available extended tooltips in dialog boxes, when \"Extended tips\" is not enabled in Tools ▸ Options ▸ %PRODUCTNAME ▸ General."), "https://help.libreoffice.org/%PRODUCTVERSION/%LANGUAGENAME/text/shared/05/00000120.html", "", soffice}, { NC_("RID_CUI_TIPOFTHEDAY", "Never use certain arrow styles? Remove them by using the Delete button on the Format ▸ Text Box and Shape ▸ Line ▸ Arrow Styles tab."), "cui/ui/lineendstabpage/BTN_MODIFY", "", sdraw}, { NC_("RID_CUI_TIPOFTHEDAY", "Don’t like the position of some icons on your toolbar? Change it with Tools ▸ Customize ▸ Toolbars tab ▸ Target."), "CUI_HID_SVX_CONFIG_TOOLBAR", "", soffice}, - { NC_("RID_CUI_TIPOFTHEDAY", "Can’t find a command in the menus? Try Shift+ESC."), ".uno:CommandPopup", "", soffice}, + { NC_("RID_CUI_TIPOFTHEDAY", "Can’t find a command in the menus? Try %SHIFT+ESC."), ".uno:CommandPopup", "", soffice}, }; #define STR_HELP_LINK NC_("STR_HELP_LINK", "%PRODUCTNAME Help") @@ -284,7 +284,9 @@ const std::tuple TIPOFTHEDAY_STRINGA #define STR_UNO_LINK NC_("STR_UNO_LINK", "Run this action now...") #define STR_TITLE NC_("STR_TITLE", "Tip of the Day: %CURRENT/%TOTAL") #define STR_CMD NC_("STR_CMD", "⌘ Cmd") //use narrow no-break space U+202F here +#define STR_CTRL_MAC NC_("STR_CTRL_MAC", "⌃ Ctrl") #define STR_CTRL NC_("STR_CTRL", "Ctrl") +#define STR_SHIFT NC_("STR_SHIFT", "⇧ Shift") //use narrow no-break space U+202F here #define STR_Alt NC_("STR_CMD", "Alt") #define STR_Option NC_("STR_CTRL", "⌥ Opt") //use narrow no-break space U+202F here diff --git a/cui/inc/treeopt.hrc b/cui/inc/treeopt.hrc index 48c7b06b89b6..4cd94099e4d8 100644 --- a/cui/inc/treeopt.hrc +++ b/cui/inc/treeopt.hrc @@ -54,8 +54,7 @@ const std::pair SID_LANGUAGE_OPTIONS_RES[] = { NC_("SID_LANGUAGE_OPTIONS_RES", "Searching in Japanese"), RID_SVXPAGE_JSEARCH_OPTIONS }, { NC_("SID_LANGUAGE_OPTIONS_RES", "Asian Layout"), RID_SVXPAGE_ASIAN_LAYOUT }, { NC_("SID_LANGUAGE_OPTIONS_RES", "Complex Text Layout"), RID_SVXPAGE_OPTIONS_CTL }, - { NC_("SID_LANGUAGE_OPTIONS_RES", "LanguageTool Server"), RID_SVXPAGE_LANGTOOL_OPTIONS }, - { NC_("SID_LANGUAGE_OPTIONS_RES", "DeepL Server"), RID_SVXPAGE_DEEPL_OPTIONS } + { NC_("SID_LANGUAGE_OPTIONS_RES", "LanguageTool Server"), RID_SVXPAGE_LANGTOOL_OPTIONS } }; const std::pair SID_INET_DLG_RES[] = diff --git a/cui/inc/widgettestdlg.hxx b/cui/inc/widgettestdlg.hxx index 340d252db608..2f4b81c7b101 100644 --- a/cui/inc/widgettestdlg.hxx +++ b/cui/inc/widgettestdlg.hxx @@ -10,9 +10,10 @@ #pragma once #include +#include #include #include -#include +#include class WidgetTestDialog final : public weld::GenericDialogController { diff --git a/cui/qa/uitest/dialogs/accelerators.py b/cui/qa/uitest/dialogs/accelerators.py index 60391edc3f9a..431aade6f8ac 100644 --- a/cui/qa/uitest/dialogs/accelerators.py +++ b/cui/qa/uitest/dialogs/accelerators.py @@ -11,6 +11,8 @@ from libreoffice.uno.propertyvalue import mkPropertyValues from uitest.uihelper.common import get_state_as_dict from com.sun.star.awt import KeyEvent from com.sun.star.awt import Key +from com.sun.star.ui import GlobalAcceleratorConfiguration +from com.sun.star.ui import ModuleAcceleratorConfiguration from com.sun.star.container import NoSuchElementException def select_key(xShortcuts, key_name): @@ -70,30 +72,29 @@ class Test(UITestCase): with self.ui_test.create_doc_in_start_center("writer") as xComponent: # Set a shortcut on the global scope with self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") as xDialog: - self.assign_key(xDialog, "office", "F7", ".uno:Credits") + self.assign_key(xDialog, "office", "F7", "Credits Online") # Check that the key made it into the global config - xGlobalAccelCfg = self.xContext.ServiceManager.createInstance( - 'com.sun.star.ui.GlobalAcceleratorConfiguration') + xGlobalAccelCfg = GlobalAcceleratorConfiguration.create(self.xContext) xKeyEvent = KeyEvent() xKeyEvent.KeyCode = Key.F7 self.assertEqual(xGlobalAccelCfg.getCommandByKeyEvent(xKeyEvent), ".uno:Credits") # Set a shortcut on the module scope with self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") as xDialog: - self.assign_key(xDialog, "module", "F8", ".uno:EditBookmark") + self.assign_key(xDialog, "module", "F8", "Bookmark") # Check that the key made it into the module config - xModuleAccelCfg = self.xContext.ServiceManager.createInstanceWithArguments( - 'com.sun.star.ui.ModuleAcceleratorConfiguration', - ('com.sun.star.text.TextDocument',)) + xModuleAccelCfg = ModuleAcceleratorConfiguration.createWithModuleIdentifier( + self.xContext, + 'com.sun.star.text.TextDocument') xKeyEvent = KeyEvent() xKeyEvent.KeyCode = Key.F8 - self.assertEqual(xModuleAccelCfg.getCommandByKeyEvent(xKeyEvent), ".uno:EditBookmark") + self.assertEqual(xModuleAccelCfg.getCommandByKeyEvent(xKeyEvent), ".uno:InsertBookmark") # Set a shortcut on the document scope with self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") as xDialog: - self.assign_key(xDialog, "Untitled 1", "F9", ".uno:OptionsSecurityDialog") + self.assign_key(xDialog, "Untitled 1", "F9", "Security Options") # Check that the key made it into the document config xDocAccelCfg = xComponent.getUIConfigurationManager().getShortCutManager() @@ -131,7 +132,7 @@ class Test(UITestCase): with self.ui_test.create_doc_in_start_center("writer") as xDoc1, \ self.ui_test.load_empty_file("writer"), \ self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") as xDialog: - self.assign_key(xDialog, "Untitled 1", "F7", ".uno:Credits") + self.assign_key(xDialog, "Untitled 1", "F7", "Credits Online") xFrame1 = xDoc1.getCurrentController().getFrame() self.xUITest.executeCommandForProvider(".uno:CloseDoc", xFrame1) @@ -143,7 +144,7 @@ class Test(UITestCase): with self.ui_test.create_doc_in_start_center("writer") as xComponent: with self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") as xDialog: # Assign a key - self.assign_key(xDialog, "Untitled 1", "F7", ".uno:Credits") + self.assign_key(xDialog, "Untitled 1", "F7", "Credits Online") # … but then press reset before pressing OK xReset = xDialog.getChild("AccelConfigPage").getChild("reset") xReset.executeAction("CLICK", tuple()) @@ -188,13 +189,13 @@ class Test(UITestCase): self.ui_test.load_empty_file("writer") as xDoc2: with self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") as xDialog: # Set a shortcut on the global scope - self.assign_key(xDialog, "office", "F7", ".uno:EditBookmark") + self.assign_key(xDialog, "office", "F7", "Bookmark") # Set a shortcut on the module scope - self.assign_key(xDialog, "module", "F7", ".uno:Credits") + self.assign_key(xDialog, "module", "F7", "Credits Online") # Set a shortcut in the first document self.assign_key(xDialog, "Untitled 1", "F7", "Spelling") # Set a shortcut in the second document - self.assign_key(xDialog, "Untitled 2", "F7", ".uno:OptionsSecurityDialog") + self.assign_key(xDialog, "Untitled 2", "F7", "Security Options") # Switch back to the first document and make sure the binding is still in the list xAcceleratorPage = xDialog.getChild("AccelConfigPage") @@ -206,15 +207,14 @@ class Test(UITestCase): "Spelling") # Check that all the accelerators made it into the configs - xGlobalAccelCfg = self.xContext.ServiceManager.createInstance( - 'com.sun.star.ui.GlobalAcceleratorConfiguration') + xGlobalAccelCfg = GlobalAcceleratorConfiguration.create(self.xContext) xKeyEvent = KeyEvent() xKeyEvent.KeyCode = Key.F7 - self.assertEqual(xGlobalAccelCfg.getCommandByKeyEvent(xKeyEvent), ".uno:EditBookmark") + self.assertEqual(xGlobalAccelCfg.getCommandByKeyEvent(xKeyEvent), ".uno:InsertBookmark") - xModuleAccelCfg = self.xContext.ServiceManager.createInstanceWithArguments( - 'com.sun.star.ui.ModuleAcceleratorConfiguration', - ('com.sun.star.text.TextDocument',)) + xModuleAccelCfg = ModuleAcceleratorConfiguration.createWithModuleIdentifier( + self.xContext, + 'com.sun.star.text.TextDocument') self.assertEqual(xModuleAccelCfg.getCommandByKeyEvent(xKeyEvent), ".uno:Credits") xDocAccelCfg = xDoc1.getUIConfigurationManager().getShortCutManager() @@ -225,4 +225,30 @@ class Test(UITestCase): self.assertEqual(xDocAccelCfg.getCommandByKeyEvent(xKeyEvent), ".uno:OptionsSecurityDialog") + def test_start_center(self): + # Try opening the customization dialog from the start center + with self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") as xDialog: + select_keyboard_tab(xDialog) + + xAcceleratorPage = xDialog.getChild("AccelConfigPage") + + # All of the radio controls apart from the global one should be hidden + xGlobal = xAcceleratorPage.getChild("office") + self.assertEqual(get_state_as_dict(xGlobal)["Visible"], "true") + xModule = xAcceleratorPage.getChild("module") + self.assertEqual(get_state_as_dict(xModule)["Visible"], "false") + xDocument = xAcceleratorPage.getChild("document") + self.assertEqual(get_state_as_dict(xDocument)["Visible"], "false") + xScope = xAcceleratorPage.getChild("savein") + self.assertEqual(get_state_as_dict(xScope)["Visible"], "false") + + # Assign a key + self.assign_key(xDialog, "office", "F7", "Edit Macros") + + # Check that the key made it into the global config + xGlobalAccelCfg = GlobalAcceleratorConfiguration.create(self.xContext) + xKeyEvent = KeyEvent() + xKeyEvent.KeyCode = Key.F7 + self.assertEqual(xGlobalAccelCfg.getCommandByKeyEvent(xKeyEvent), ".uno:BasicIDEAppear") + # vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/cui/qa/uitest/dialogs/chardlg.py b/cui/qa/uitest/dialogs/chardlg.py index ee754b3c0f3a..2456a46261dc 100644 --- a/cui/qa/uitest/dialogs/chardlg.py +++ b/cui/qa/uitest/dialogs/chardlg.py @@ -93,9 +93,10 @@ class Test(UITestCase): floatWindow = self.xUITest.getFloatWindow() paletteSelector = floatWindow.getChild("palette_listbox") select_by_text(paletteSelector, "Theme colors") - colorSet = floatWindow.getChild("colorset") - # 4 would be accent1, +12 is the first from the effect variants. - colorSet.executeAction("CHOOSE", mkPropertyValues({"POS": "16"})) + colorIconView = floatWindow.getChild("coloriconview") + # 3 would be accent1, +12 is the first from the effect variants. + colorIconView.executeAction("SELECT", mkPropertyValues({"POS": "15"})) + colorIconView.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) # Then make sure the doc model has the correct color theme index: drawPage = component.getDrawPages()[0] @@ -160,5 +161,36 @@ class Test(UITestCase): # i.e. the auto color lost its alpha component and appeared as white. self.assertEqual(get_state_as_dict(xFontColorLB)["Text"], "Automatic") + def testTdf152396CharStyleNameSubFamily(self): + # tdf#152396: an extended style (say a width such as "Condensed") + # chosen in the Character dialog must be stored as the typographic + # subfamily (CharFontStyleName), not silently dropped because only the + # family name is unchanged. + with self.ui_test.create_doc_in_start_center("writer") as component: + doc = self.xUITest.getTopFocusWindow() + editWin = doc.getChild("writer_edit") + editWin.executeAction("TYPE", mkPropertyValues({"TEXT": "t"})) + self.xUITest.executeCommand(".uno:SelectAll") + + # Choose an extended style name on the Fonts tab. + with self.ui_test.execute_dialog_through_command(".uno:FontDialog") as xDialog: + select_pos(xDialog.getChild("tabcontrol"), "0") + xStyle = xDialog.getChild("cbWestStyle") + xStyle.executeAction("TYPE", mkPropertyValues({"KEYCODE": "CTRL+A"})) + xStyle.executeAction("TYPE", mkPropertyValues({"TEXT": "Condensed"})) + + # The chosen subfamily reaches the model. Without the fix the + # style-name-only change was dropped and this was an empty string. + paragraph = component.Text.createEnumeration().nextElement() + portion = paragraph.createEnumeration().nextElement() + self.assertEqual(portion.CharFontStyleName, "Condensed") + + # Reopening the dialog shows the stored subfamily, not a + # weight/posture-derived name. + with self.ui_test.execute_dialog_through_command(".uno:FontDialog", close_button="cancel") as xDialog: + select_pos(xDialog.getChild("tabcontrol"), "0") + xStyle = xDialog.getChild("cbWestStyle") + self.assertEqual(get_state_as_dict(xStyle)["Text"], "Condensed") + # vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/cui/qa/uitest/dialogs/editdictionary.py b/cui/qa/uitest/dialogs/editdictionary.py new file mode 100644 index 000000000000..becf01a8bfb6 --- /dev/null +++ b/cui/qa/uitest/dialogs/editdictionary.py @@ -0,0 +1,69 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# +from uitest.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict, type_text +from libreoffice.uno.propertyvalue import mkPropertyValues + +class EditDictionaryFilterTest(UITestCase): + def test_dictionary_live_filter(self): + with self.ui_test.create_doc_in_start_center("writer"): + # 1. Open Tools -> Options -> Language Settings -> Writing Aids + with self.ui_test.execute_dialog_through_command(".uno:OptionsTreeDialog", close_button="cancel") as xOptionsDlg: + xPages = xOptionsDlg.getChild("pages") + xLangSettings = xPages.getChild('2') # Language Settings + xLangSettings.executeAction("EXPAND", tuple()) + xWritingAids = xLangSettings.getChild('1') # Writing Aids + xWritingAids.executeAction("SELECT", tuple()) + + dictionaries = xOptionsDlg.getChild("lingudicts") + hasEditableDictionary = False + for i in dictionaries.getChildren(): + entry = dictionaries.getChild(i) + entry_label = get_state_as_dict(entry)["Text"] + if entry_label == "List of Ignored Words [All]": + hasEditableDictionary = True + entry.executeAction("SELECT", tuple()) + break + + self.assertTrue(hasEditableDictionary, "No editable dictionary found") + + # 2. Click "Edit..." button under User-defined dictionaries + xEditDictBtn = xOptionsDlg.getChild("lingudictsedit") + + with self.ui_test.execute_blocking_action(xEditDictBtn.executeAction, args=("CLICK", ()), close_button="close") as xDictDlg: + xWordInput = xDictDlg.getChild("word") + xWordsList = xDictDlg.getChild("words") + + # 3. Add a new test word to ensure there is something to filter + xWordInput.executeAction("TYPE", mkPropertyValues({"TEXT": "uitestword"})) + xNewBtn = xDictDlg.getChild("newreplace") + xNewBtn.executeAction("CLICK", tuple()) + + # 4. Prove the filter HIDES words (type gibberish) + xWordInput.executeAction("TYPE", mkPropertyValues({"KEYCODE": "CTRL+A"})) + xWordInput.executeAction("TYPE", mkPropertyValues({"TEXT": "zzxyy"})) + + children_count = int(get_state_as_dict(xWordsList)["Children"]) + self.assertEqual(children_count, 0, "Filter should hide words and return 0 matches for gibberish") + + # 5. Prove the filter FINDS the correct word + xWordInput.executeAction("TYPE", mkPropertyValues({"KEYCODE": "CTRL+A"})) + xWordInput.executeAction("TYPE", mkPropertyValues({"TEXT": "uitest"})) + + children_count = int(get_state_as_dict(xWordsList)["Children"]) + self.assertTrue(children_count >= 1, "Filter should return at least 1 match for prefix") + + # 6. Safe Clean up: Filter for the exact word first so it's guaranteed at POS: 0 + xWordInput.executeAction("TYPE", mkPropertyValues({"KEYCODE": "CTRL+A"})) + xWordInput.executeAction("TYPE", mkPropertyValues({"TEXT": "uitestword"})) + + xDelBtn = xDictDlg.getChild("delete") + xDelBtn.executeAction("CLICK", tuple()) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/cui/qa/uitest/dialogs/macromanager.py b/cui/qa/uitest/dialogs/macromanager.py new file mode 100644 index 000000000000..3d8ba3e7f7de --- /dev/null +++ b/cui/qa/uitest/dialogs/macromanager.py @@ -0,0 +1,360 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# + +from com.sun.star.beans import PropertyValue +from com.sun.star.script.provider import ScriptURIHelper +from com.sun.star.ucb import SimpleFileAccess +from libreoffice.uno.eventlistener import EventListener +from uitest.framework import UITestCase +from uitest.test import DEFAULT_SLEEP +from uitest.uihelper.common import get_state_as_dict, type_text, mkPropertyValues +import uno + +import contextlib +import tempfile +import time +import os + + +def get_user_script_directory(context): + uriHelper = ScriptURIHelper.create(context, "Python", "user") + uri = uriHelper.getRootStorageURI() + return uno.fileUrlToSystemPath(uri) + + +def generate_test_script_for_directory(directory): + # Generate a python script that creates a file in the given directory + return f""" +import os.path + +def MyMacro(): + with open(os.path.join(r'{directory}', 'script-ran'), 'x'): + pass + """ + + +class MacroManagerTest(UITestCase): + def find_child_node(self, xNode, name): + # Find the child node with the given name + try: + return next(x for x in map(lambda name: xNode.getChild(name), + xNode.getChildren()) + if get_state_as_dict(x)["Text"] == name) + except StopIteration: + self.fail(f"Couldn’t find tree child {name}") + + def select_tree_node(self, xNode, *parts): + for i, part in enumerate(parts): + if i > 0: + xNode.executeAction("EXPAND", tuple()) + + xNode = self.find_child_node(xNode, part) + + xNode.executeAction("SELECT", tuple()) + + return xNode + + def select_macro(self, xDialog, *parts): + self.select_tree_node(xDialog.getChild("scriptcontainers"), *parts[0:-1]) + self.select_tree_node(xDialog.getChild("scripts"), parts[-1]) + + def run_macro(self, *parts): + with self.ui_test.execute_dialog_through_command(".uno:MacroManager", + close_button="run") as xDialog: + self.select_macro(xDialog, *parts) + + def run_user_script(self): + script_dir = get_user_script_directory(self.xContext) + os.makedirs(script_dir, exist_ok=True) + + # Create a temporary directory in the script directory to contain our test script + with tempfile.TemporaryDirectory(dir=script_dir) as temp_script_dir: + # Create a temporary directory to create the check file in + with tempfile.TemporaryDirectory() as check_file_dir: + # Create a script with a known name + with open(os.path.join(temp_script_dir, "MyScript.py"), "w", encoding="utf-8") as f: + print(generate_test_script_for_directory(check_file_dir), file=f) + + self.run_macro("My Macros", "Python", os.path.basename(temp_script_dir), "MyScript", + "MyMacro") + + # Return whether the test file was created + return os.path.exists(os.path.join(check_file_dir, 'script-ran')) + + def test_delete(self): + # Create a new BASIC library using the macro manager + with EventListener(self.xContext, "OnNew") as event: + with self.ui_test.execute_dialog_through_command(".uno:MacroManager", + close_button= + "librarymoduledialogedit") \ + as xDialog: + xContainers = xDialog.getChild("scriptcontainers") + xStandard = self.select_tree_node(xContainers, "My Macros", "Basic", "Standard") + + # Delete all other modules in the library. If we don’t do this then the BASIC editor + # will create an EditorWindow for every module and we won’t be able get access to + # the one we want. + xDelete = xDialog.getChild("librarymoduledialogdelete") + xStandard.executeAction("EXPAND", tuple()) + while get_state_as_dict(xStandard)["Children"] != '0': + xStandard.getChild('0').executeAction("SELECT", tuple()) + with self.ui_test.execute_blocking_action(xDelete.executeAction, + args=("CLICK", tuple()), + close_button="yes") as xConfirm: + pass + + xNewModule = xDialog.getChild("newmodule") + with self.ui_test.execute_blocking_action(xNewModule.executeAction, + args=("CLICK", tuple()), + close_button="ok") as xConfirm: + xNameEntry = xConfirm.getChild("name_entry") + type_text(xNameEntry, "TestDelete") + + self.select_tree_node(xContainers, "My Macros", "Basic", "Standard", "TestDelete") + + while not event.executed: + time.sleep(DEFAULT_SLEEP) + + self.xUITest.executeCommand(".uno:SelectAll") + + xEditorWindow = self.xUITest.getTopFocusWindow().getChild("EditorWindow") + + code = "\n\n".join(map(lambda x: f"Sub {x}\nEnd Sub", ["first", "middle", "last"])) + + for line in code.splitlines(): + type_text(xEditorWindow, line) + xEditorWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) + + text = get_state_as_dict(xEditorWindow)["Text"] + self.assertFalse(text.find("Sub middle") == -1) + + # Open the macro manager + with self.ui_test.execute_dialog_through_command(".uno:MacroManager", + close_button="close") as xDialog: + self.select_macro(xDialog, "My Macros", "Basic", "Standard", "TestDelete", "middle") + + # Delete the middle macro + xDelete = xDialog.getChild("macrodelete") + with self.ui_test.execute_blocking_action(xDelete.executeAction, ("CLICK", tuple()), + close_button="yes"): + pass + + # Make sure the macro isn’t in the list any more + xScripts = xDialog.getChild("scripts") + self.assertEqual(get_state_as_dict(xScripts)["Children"], '2') + self.assertEqual(get_state_as_dict(xScripts.getChild(0))["Text"], "first") + self.assertEqual(get_state_as_dict(xScripts.getChild(1))["Text"], "last") + + # Make sure the macro has disappeared from the macro editor source code + text = get_state_as_dict(xEditorWindow)["Text"] + self.assertEqual(text.find("Sub middle"), -1) + + def test_start_center(self): + # Try running a script directly from the start center. See tdf#171924 + self.assertTrue(self.run_user_script()) + + def test_embedded_script(self): + # Create a temporary directory to create the check file in + with tempfile.TemporaryDirectory() as check_file_dir: + # Create a new document with a temporary filename and add a test script to it + with tempfile.NamedTemporaryFile(suffix=".odt") as doc_file: + with self.ui_test.create_doc_in_start_center("writer") as xComponent: + xFileAccess = SimpleFileAccess.create(self.xContext) + xFileAccess.createFolder("vnd.sun.star.tdoc:/1/Scripts/python") + + with tempfile.NamedTemporaryFile(suffix=".py", mode="w+", + encoding="utf-8") as script_file: + print(generate_test_script_for_directory(check_file_dir), + file=script_file) + script_file.flush() + + xFileAccess.copy(uno.systemPathToFileUrl(script_file.name), + "vnd.sun.star.tdoc:/1/Scripts/python/MyScript.py") + + # Save the document to the temporary file + save_opts = ( + PropertyValue(Name="Overwrite", Value=True), + PropertyValue(Name="FilterName", Value="writer8"), + ) + xComponent.storeAsURL(uno.systemPathToFileUrl(doc_file.name), save_opts) + + # Open the document we just created + with self.ui_test.load_file(uno.systemPathToFileUrl(doc_file.name)): + # We should be able to run user macros even though we’re looking at a document + # with macros in it + self.assertTrue(self.run_user_script()) + + # We shouldn’t be able to run the embedded script because the security policy + # disallows it + with contextlib.ExitStack() as stack: + xDialog = stack.enter_context( + self.ui_test.execute_dialog_through_command(".uno:MacroManager", + close_button="run")) + self.select_macro(xDialog, os.path.basename(doc_file.name), "Python", + "MyScript", "MyMacro") + # We want to start the EventListener for the blocking action of showing the + # error dialog *after* creating the run macro dialog so that it doesn’t pick + # up the wrong event. + with self.ui_test.execute_blocking_action(stack.close): + pass + + self.assertFalse(os.path.exists(os.path.join(check_file_dir, 'script-ran'))) + + # Temporarily disable macro security + with self.ui_test.set_config("/org.openoffice.Office.Common/Security/Scripting/" + "MacroSecurityLevel", 0): + with self.ui_test.load_file(uno.systemPathToFileUrl(doc_file.name)): + # Now we should be able to run the embedded script + self.run_macro(os.path.basename(doc_file.name), "Python", "MyScript", + "MyMacro") + self.assertTrue(os.path.exists(os.path.join(check_file_dir, 'script-ran'))) + + # Tests copying and pasting Python scripts into an empty node, an + # unexpanded node and an expanded node + def test_copy_paste(self): + with contextlib.ExitStack() as stack: + script_dir = get_user_script_directory(self.xContext) + os.makedirs(script_dir, exist_ok=True) + + # Make a temporary directory with a script to copy from + src_dir = stack.enter_context(tempfile.TemporaryDirectory(dir=script_dir)) + with open(os.path.join(src_dir, "MyScript.py"), "w", encoding='utf-8') as f: + print("def MyMacro():\n pass", file=f) + + # Make an empty directory + empty_dir = stack.enter_context(tempfile.TemporaryDirectory(dir=script_dir)) + + # Make a directory and script for the unexpanded node + unexpanded_dir = stack.enter_context(tempfile.TemporaryDirectory(dir=script_dir)) + with open(os.path.join(unexpanded_dir, "MyOtherScript.py"), "w", encoding='utf-8') as f: + print("def MyMacro():\n pass", file=f) + + # Make a directory and script for the expanded node + expanded_dir = stack.enter_context(tempfile.TemporaryDirectory(dir=script_dir)) + with open(os.path.join(expanded_dir, "MyOtherScript.py"), "w", encoding='utf-8') as f: + print("def MyMacro():\n pass", file=f) + + xDialog = stack.enter_context( + self.ui_test.execute_dialog_through_command(".uno:MacroManager", + close_button="close")) + xContainers = xDialog.getChild("scriptcontainers") + + # Copy the source script + source_node = self.select_tree_node( + xContainers, "My Macros", "Python", os.path.basename(src_dir), "MyScript") + copy_button = xDialog.getChild("modulecopy") + copy_button.executeAction("CLICK", tuple()) + + python_node = self.select_tree_node(xContainers, "My Macros", "Python") + + # Paste into the empty node + empty_node = self.find_child_node(python_node, os.path.basename(empty_dir)) + empty_node.executeAction("SELECT", tuple()) + paste_button = xDialog.getChild("modulepaste") + paste_button.executeAction("CLICK", tuple()) + + # The new node should be selected + self.assertEqual(get_state_as_dict(xContainers)["SelectEntryText"], "MyScript") + # The empty node should now have exactly one child + empty_node = self.find_child_node(python_node, os.path.basename(empty_dir)) + self.assertEqual(get_state_as_dict(empty_node)["Children"], "1") + pasted_node = empty_node.getChild("0") + self.assertEqual(get_state_as_dict(pasted_node)["Text"], "MyScript") + # The file should have been created + self.assertTrue(os.path.exists(os.path.join(empty_dir, "MyScript.py"))) + + # Paste into the unexpanded node + unexpanded_node = self.find_child_node(python_node, os.path.basename(unexpanded_dir)) + unexpanded_node.executeAction("SELECT", tuple()) + paste_button.executeAction("CLICK", tuple()) + + # The new node should be selected + self.assertEqual(get_state_as_dict(xContainers)["SelectEntryText"], "MyScript") + # The newly expanded node should now have exactly two children + unexpanded_node = self.find_child_node(python_node, os.path.basename(unexpanded_dir)) + self.assertEqual(get_state_as_dict(unexpanded_node)["Children"], "2") + child_names = list(sorted(get_state_as_dict(unexpanded_node.getChild(str(i)))["Text"] + for i in range(2))) + self.assertEqual(child_names, ["MyOtherScript", "MyScript"]) + + # Make the expanded node live up to its name + expanded_node = self.find_child_node(python_node, os.path.basename(expanded_dir)) + expanded_node.executeAction("EXPAND", tuple()) + + # Paste into the expanded node + expanded_node = self.find_child_node(python_node, os.path.basename(expanded_dir)) + expanded_node.executeAction("SELECT", tuple()) + paste_button.executeAction("CLICK", tuple()) + + # The new node should be selected + self.assertEqual(get_state_as_dict(xContainers)["SelectEntryText"], "MyScript") + # The expanded node should now have exactly two children + expanded_node = self.find_child_node(python_node, os.path.basename(expanded_dir)) + self.assertEqual(get_state_as_dict(expanded_node)["Children"], "2") + child_names = list(sorted(get_state_as_dict(expanded_node.getChild(str(i)))["Text"] + for i in range(2))) + self.assertEqual(child_names, ["MyOtherScript", "MyScript"]) + + # Tests copying a Python script into a Writer document and back + def test_copy_to_document(self): + with self.ui_test.create_doc_in_start_center("writer") as xComponent: + script_dir = get_user_script_directory(self.xContext) + os.makedirs(script_dir, exist_ok=True) + + # Make a temporary directory with a script to copy from + with tempfile.TemporaryDirectory(dir=script_dir) as src_dir: + with open(os.path.join(src_dir, "MyScript.py"), "w", encoding='utf-8') as f: + print("def MyMacro():\n" + " XSCRIPTCONTEXT.getDocument().getText()." + "setString(\"test_copy_to_document\")", + file=f) + + # Copy the script into the document using the dialog + with self.ui_test.execute_dialog_through_command(".uno:MacroManager", + close_button="close") as xDialog: + xContainers = xDialog.getChild("scriptcontainers") + self.select_tree_node(xContainers, "My Macros", "Python", + os.path.basename(src_dir), "MyScript") + xDialog.getChild("modulecopy").executeAction("CLICK", tuple()) + + self.select_tree_node(xContainers, "Untitled 1", "Python") + xDialog.getChild("modulepaste").executeAction("CLICK", tuple()) + + # Make sure the script now appears in the tree + xDocumentNode = self.select_tree_node(xContainers, "Untitled 1", "Python") + self.assertEqual(get_state_as_dict(xDocumentNode)["Children"], "1") + xNewNode = xDocumentNode.getChild("0") + self.assertEqual(get_state_as_dict(xNewNode)["Text"], "MyScript") + + # The temporary script in the user directory should now be deleted, so the only + # remaining copy of it should be in the document. Let’s try running it. + with self.ui_test.execute_dialog_through_command(".uno:MacroManager", + close_button="run") as xDialog: + xContainers = xDialog.getChild("scriptcontainers") + self.select_tree_node(xContainers, "Untitled 1", "Python", "MyScript") + + # Make sure the macro successfully put text into the document + self.assertEqual(xComponent.getText().getString(), "test_copy_to_document") + + # Make a temporary directory to copy the script back into + with tempfile.TemporaryDirectory(dir=script_dir) as dest_dir: + # Copy the script into the temporary directory using the dialog + with self.ui_test.execute_dialog_through_command(".uno:MacroManager", + close_button="close") as xDialog: + xContainers = xDialog.getChild("scriptcontainers") + self.select_tree_node(xContainers, "Untitled 1", "Python", "MyScript") + xDialog.getChild("modulecopy").executeAction("CLICK", tuple()) + self.select_tree_node(xContainers, "My Macros", "Python", + os.path.basename(dest_dir)) + xDialog.getChild("modulepaste").executeAction("CLICK", tuple()) + + self.assertTrue(os.path.exists(os.path.join(dest_dir, "MyScript.py"))) + + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/cui/qa/uitest/dialogs/pythonmacroorganizer.py b/cui/qa/uitest/dialogs/pythonmacroorganizer.py index 37861b6a25c4..f45aa4540556 100644 --- a/cui/qa/uitest/dialogs/pythonmacroorganizer.py +++ b/cui/qa/uitest/dialogs/pythonmacroorganizer.py @@ -10,7 +10,9 @@ from uitest.framework import UITestCase from uitest.uihelper.common import get_state_as_dict from libreoffice.uno.propertyvalue import mkPropertyValues +from com.sun.star.beans import PropertyValue from com.sun.star.script.provider import ScriptURIHelper +from com.sun.star.ucb import SimpleFileAccess import uno import tempfile @@ -189,5 +191,75 @@ class PythonMacroOrganizerTest(UITestCase): xScript = xTestLibrary.getChild(0) self.assertEqual(get_state_as_dict(xScript)["Text"], "My Script") + def test_macros_disabled(self): + # Create a new document with a temporary filename and add a test script to it + with tempfile.NamedTemporaryFile(suffix=".odt") as doc_file: + with self.ui_test.create_doc_in_start_center("writer") as xComponent: + xFileAccess = SimpleFileAccess.create(self.xContext) + xFileAccess.createFolder("vnd.sun.star.tdoc:/1/Scripts/python") + + with tempfile.NamedTemporaryFile(suffix=".py", mode="w+", + encoding="utf-8") as script_file: + print("def addHello():\n" + " XSCRIPTCONTEXT.getDocument().getText().setString(\"hello\")", + file=script_file) + script_file.flush() + + xFileAccess.copy(uno.systemPathToFileUrl(script_file.name), + "vnd.sun.star.tdoc:/1/Scripts/python/MyScript.py") + + # Save the document to the temporary file + save_opts = ( + PropertyValue(Name="Overwrite", Value=True), + PropertyValue(Name="FilterName", Value="writer8"), + ) + xComponent.storeAsURL(uno.systemPathToFileUrl(doc_file.name), save_opts) + + # Helper function to select the macro + def select_macro(xDialog): + xScripts = xDialog.getChild("scripts") + # Find the library for the temporary document + xDocLibrary = \ + next(x for x in map(lambda i: xScripts.getChild(i), + range(int(get_state_as_dict(xScripts)["Children"]))) + if get_state_as_dict(x)["Text"] == os.path.basename(doc_file.name)) + xDocLibrary.executeAction("EXPAND", tuple()) + xScript = xDocLibrary.getChild(0) + xScript.executeAction("EXPAND", tuple()) + xMacro = xScript.getChild(0) + xMacro.executeAction("SELECT", tuple()) + + # Open the document we just created + with self.ui_test.load_file(uno.systemPathToFileUrl(doc_file.name)) as xComponent: + # We shouldn’t be able to run the embedded script because the security policy + # disallows it + with self.ui_test.execute_dialog_through_command( + ".uno:ScriptOrganizer?ScriptOrganizer.Language:string=Python", + close_button="close") as xDialog: + select_macro(xDialog) + + # Clicking run should pop up a nested modal dialog reporting the problem + xRun = xDialog.getChild("ok") + with self.ui_test.execute_blocking_action(xRun.executeAction, + args=("CLICK", tuple())): + pass + + # The macro shouldn’t have run so the document text should still be empty + self.assertEqual(xComponent.getText().getString(), "") + + # Temporarily disable macro security + with self.ui_test.set_config("/org.openoffice.Office.Common/Security/Scripting/" + "MacroSecurityLevel", 0): + with self.ui_test.load_file(uno.systemPathToFileUrl(doc_file.name)) as xComponent: + # Now we should be able to run the embedded script + with self.ui_test.execute_dialog_through_command( + ".uno:ScriptOrganizer?ScriptOrganizer.Language:string=Python", + close_button="ok") as xDialog: + select_macro(xDialog) + + # The script should have run so the document should contain the text that it + # added + self.assertEqual(xComponent.getText().getString(), "hello") + # vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/cui/qa/uitest/dialogs/runmacro.py b/cui/qa/uitest/dialogs/runmacro.py new file mode 100644 index 000000000000..7e0a58704cb6 --- /dev/null +++ b/cui/qa/uitest/dialogs/runmacro.py @@ -0,0 +1,135 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# + +from uitest.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict +from libreoffice.uno.propertyvalue import mkPropertyValues +from com.sun.star.beans import PropertyValue +from com.sun.star.script.provider import ScriptURIHelper +from com.sun.star.ucb import SimpleFileAccess +import uno + +import contextlib +import tempfile +import os + + +def get_user_script_directory(context): + uriHelper = ScriptURIHelper.create(context, "Python", "user") + uri = uriHelper.getRootStorageURI() + return uno.fileUrlToSystemPath(uri) + + +def generate_test_script_for_directory(directory): + # Generate a python script that creates a file in the given directory + return f""" +import os.path + +def MyMacro(): + with open(os.path.join(r'{directory}', 'script-ran'), 'x'): + pass + """ + + +class RunMacroTest(UITestCase): + def select_macro(self, xDialog, *parts): + xNode = xDialog.getChild("categories") + + for i, part in enumerate(parts): + if i > 0: + xNode.executeAction("EXPAND", tuple()) + + # Find the node in the tree with this part name + xNode = \ + next(x for x in map(lambda i: xNode.getChild(i), + range(int(get_state_as_dict(xNode)["Children"]))) + if get_state_as_dict(x)["Text"] == part) + + xNode.executeAction("SELECT", tuple()) + + def run_macro(self, *parts): + with self.ui_test.execute_dialog_through_command(".uno:RunMacro") as xDialog: + self.select_macro(xDialog, *parts) + + def run_user_script(self): + script_dir = get_user_script_directory(self.xContext) + os.makedirs(script_dir, exist_ok=True) + + # Create a temporary directory in the script directory to contain our test script + with tempfile.TemporaryDirectory(dir=script_dir) as temp_script_dir: + # Create a temporary directory to create the check file in + with tempfile.TemporaryDirectory() as check_file_dir: + # Create a script with a known name + with open(os.path.join(temp_script_dir, "MyScript.py"), "w", encoding="utf-8") as f: + print(generate_test_script_for_directory(check_file_dir), file=f) + + self.run_macro("My Macros", os.path.basename(temp_script_dir), "MyScript") + + # Return whether the test file was created + return os.path.exists(os.path.join(check_file_dir, 'script-ran')) + + def test_start_center(self): + # Try running a script directly from the start center. See tdf#171924 + self.assertTrue(self.run_user_script()) + + def test_embedded_script(self): + # Create a temporary directory to create the check file in + with tempfile.TemporaryDirectory() as check_file_dir: + # Create a new document with a temporary filename and add a test script to it + with tempfile.NamedTemporaryFile(suffix=".odt") as doc_file: + with self.ui_test.create_doc_in_start_center("writer") as xComponent: + xFileAccess = SimpleFileAccess.create(self.xContext) + xFileAccess.createFolder("vnd.sun.star.tdoc:/1/Scripts/python") + + with tempfile.NamedTemporaryFile(suffix=".py", mode="w+", + encoding="utf-8") as script_file: + print(generate_test_script_for_directory(check_file_dir), + file=script_file) + script_file.flush() + + xFileAccess.copy(uno.systemPathToFileUrl(script_file.name), + "vnd.sun.star.tdoc:/1/Scripts/python/MyScript.py") + + # Save the document to the temporary file + save_opts = ( + PropertyValue(Name="Overwrite", Value=True), + PropertyValue(Name="FilterName", Value="writer8"), + ) + xComponent.storeAsURL(uno.systemPathToFileUrl(doc_file.name), save_opts) + + # Open the document we just created + with self.ui_test.load_file(uno.systemPathToFileUrl(doc_file.name)): + # We should be able to run user macros even though we’re looking at a document + # with macros in it + self.assertTrue(self.run_user_script()) + + # We shouldn’t be able to run the embedded script because the security policy + # disallows it + with contextlib.ExitStack() as stack: + xDialog = stack.enter_context( + self.ui_test.execute_dialog_through_command(".uno:RunMacro")) + self.select_macro(xDialog, os.path.basename(doc_file.name), "MyScript") + # We want to start the EventListener for the blocking action of showing the + # error dialog *after* creating the run macro dialog so that it doesn’t pick + # up the wrong event. + with self.ui_test.execute_blocking_action(stack.close): + pass + + self.assertFalse(os.path.exists(os.path.join(check_file_dir, 'script-ran'))) + + # Temporarily disable macro security + with self.ui_test.set_config("/org.openoffice.Office.Common/Security/Scripting/" + "MacroSecurityLevel", 0): + with self.ui_test.load_file(uno.systemPathToFileUrl(doc_file.name)): + # Now we should be able to run the embedded script + self.run_macro(os.path.basename(doc_file.name), "MyScript") + self.assertTrue(os.path.exists(os.path.join(check_file_dir, 'script-ran'))) + + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/cui/qa/uitest/options/optchartcolorspage.py b/cui/qa/uitest/options/optchartcolorspage.py index 5b4f4809341e..bb2c3ffa38e6 100644 --- a/cui/qa/uitest/options/optchartcolorspage.py +++ b/cui/qa/uitest/options/optchartcolorspage.py @@ -23,7 +23,7 @@ class Test(UITestCase): chartsEntryDefaultColorsEntry.executeAction("SELECT", tuple()) chartsColors = xDialog.getChild("colors") - colorTable = xDialog.getChild("table") + colorTable = xDialog.getChild("tableiconview") # Chart Data Series default colors dataSeriesDefaultColors = ["004586", @@ -42,7 +42,8 @@ class Test(UITestCase): for i in range(len(dataSeriesDefaultColors)): chartsColorsDataSeriesEntry = chartsColors.getChild(i) chartsColorsDataSeriesEntry.executeAction("SELECT", tuple()) - self.assertEqual(get_state_as_dict(colorTable)["CurrColorPos"], str(i)) - self.assertEqual(get_state_as_dict(colorTable)["RGB"], self.hex_to_rgb(dataSeriesDefaultColors[i])) + self.assertEqual(get_state_as_dict(colorTable)["SelectedItemPos"], str(i)) + # ID is the RGB color value in hex + self.assertEqual(get_state_as_dict(colorTable)["SelectedItemId"].lower(), dataSeriesDefaultColors[i]) # vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/cui/qa/uitest/tabpages/page.py b/cui/qa/uitest/tabpages/page.py new file mode 100644 index 000000000000..74cf5c2a6011 --- /dev/null +++ b/cui/qa/uitest/tabpages/page.py @@ -0,0 +1,42 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# + +from uitest.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict + + +class PageTabTest(UITestCase): + # Tests that the “Resize all pages” checkbox is only visible when the dialog is opened from a + # Draw or Impress document and not from Writer or Calc. See tdf#173170 + def test_resize_all_visibility(self): + with self.ui_test.create_doc_in_start_center("impress") as xComponent: + xTemplate = self.xUITest.getTopFocusWindow() + self.ui_test.close_dialog_through_button(xTemplate.getChild("close")) + + with self.ui_test.execute_dialog_through_command(".uno:PageSetup") as xDialog: + xResizeCheckBox = xDialog.getChild("checkResizeAllPages") + self.assertEqual(get_state_as_dict(xResizeCheckBox)["ReallyVisible"], "true") + + with self.ui_test.create_doc_in_start_center("draw") as xComponent: + with self.ui_test.execute_dialog_through_command(".uno:PageSetup") as xDialog: + xResizeCheckBox = xDialog.getChild("checkResizeAllPages") + self.assertEqual(get_state_as_dict(xResizeCheckBox)["ReallyVisible"], "true") + + with self.ui_test.create_doc_in_start_center("writer") as xComponent: + with self.ui_test.execute_dialog_through_command(".uno:PageDialog") as xDialog: + xResizeCheckBox = xDialog.getChild("checkResizeAllPages") + self.assertEqual(get_state_as_dict(xResizeCheckBox)["ReallyVisible"], "false") + + with self.ui_test.create_doc_in_start_center("calc") as xComponent: + with self.ui_test.execute_dialog_through_command(".uno:PageFormatDialog") as xDialog: + xResizeCheckBox = xDialog.getChild("checkResizeAllPages") + self.assertEqual(get_state_as_dict(xResizeCheckBox)["ReallyVisible"], "false") + + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/cui/qa/uitest/tabpages/tpcolor.py b/cui/qa/uitest/tabpages/tpcolor.py index 4e7b8261ff83..906b341f7d06 100644 --- a/cui/qa/uitest/tabpages/tpcolor.py +++ b/cui/qa/uitest/tabpages/tpcolor.py @@ -55,8 +55,9 @@ class Test(UITestCase): btnColor.executeAction("CLICK", tuple()) paletteSelector = xDialog.getChild("paletteselector") select_by_text(paletteSelector, "Theme colors") - colorSelector = xDialog.getChild("colorset") - colorSelector.executeAction("CHOOSE", mkPropertyValues({"POS": "4"})) + colorSelector = xDialog.getChild("coloriconview") + colorSelector.executeAction("SELECT", mkPropertyValues({"POS": "3"})) + colorSelector.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) # Then make sure the doc model is updated accordingly: shape = drawPage[0] diff --git a/cui/source/customize/CommandCategoryListBox.cxx b/cui/source/customize/CommandCategoryListBox.cxx index 3c75cb15dc4c..b5e68a79fec1 100644 --- a/cui/source/customize/CommandCategoryListBox.cxx +++ b/cui/source/customize/CommandCategoryListBox.cxx @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -66,29 +67,6 @@ CommandCategoryListBox::~CommandCategoryListBox() { ClearAll(); } void CommandCategoryListBox::ClearAll() { - // Clear objects from m_aGroupInfo vector to avoid memory leak - for (const auto& It : m_aGroupInfo) - { - if (It->nKind == SfxCfgKind::GROUP_STYLES && It->pObject) - { - SfxStyleInfo_Impl* pStyle = static_cast(It->pObject); - delete pStyle; - } - else if (It->nKind == SfxCfgKind::FUNCTION_SCRIPT && It->pObject) - { - OUString* pScriptURI = static_cast(It->pObject); - delete pScriptURI; - } - else if (It->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER && It->pObject) - { - css::uno::XInterface* xi = static_cast(It->pObject); - if (xi != nullptr) - { - xi->release(); - } - } - } - m_aGroupInfo.clear(); m_xControl->clear(); } @@ -132,8 +110,8 @@ void CommandCategoryListBox::Init(const css::uno::Reference 0) { // Add the category of "All commands" - m_aGroupInfo.push_back( - std::make_unique(SfxCfgKind::GROUP_ALLFUNCTIONS, 0)); + m_aGroupInfo.push_back(std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), 0)); m_xControl->append(weld::toId(m_aGroupInfo.back().get()), CuiResId(RID_CUISTR_ALLFUNCTIONS)); } @@ -178,8 +156,8 @@ void CommandCategoryListBox::Init(const css::uno::Reference(SfxCfgKind::GROUP_FUNCTION, nGroupID)); + m_aGroupInfo.push_back(std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), nGroupID)); m_xControl->append(weld::toId(m_aGroupInfo.back().get()), rGroupName); } @@ -187,14 +165,14 @@ void CommandCategoryListBox::Init(const css::uno::Referenceappend_separator(u""_ustr); // Add macros category - m_aGroupInfo.push_back( - std::make_unique(SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, nullptr)); + m_aGroupInfo.push_back(std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), 0)); m_xControl->append(weld::toId(m_aGroupInfo.back().get()), CuiResId(RID_CUISTR_MACROS)); // Add styles category //TODO: last param should contain user data? - m_aGroupInfo.push_back( - std::make_unique(SfxCfgKind::GROUP_STYLES, 0, nullptr)); + m_aGroupInfo.push_back(std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), 0)); m_xControl->append(weld::toId(m_aGroupInfo.back().get()), CuiResId(RID_CUISTR_GROUP_STYLES)); } @@ -251,7 +229,8 @@ void CommandCategoryListBox::FillFunctionsList( if (pCurrentSaveInData) xImage = pCurrentSaveInData->GetImage(rInfo.Command); - m_aGroupInfo.push_back(std::make_unique(SfxCfgKind::FUNCTION_SLOT, 0)); + m_aGroupInfo.push_back(std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), 0)); SfxGroupInfo_Impl* pGrpInfo = m_aGroupInfo.back().get(); pGrpInfo->sCommand = rInfo.Command; pGrpInfo->sLabel = sUIName; @@ -300,7 +279,7 @@ void CommandCategoryListBox::categorySelected(CuiConfigFunctionListBox* pFunctio pFunctionListBox->freeze(); pFunctionListBox->ClearAll(); - switch (pInfo->nKind) + switch (pInfo->getKind()) { case SfxCfgKind::GROUP_ALLFUNCTIONS: { @@ -316,7 +295,7 @@ void CommandCategoryListBox::categorySelected(CuiConfigFunctionListBox* pFunctio if (!pCurrentInfo) //separator continue; - if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION) + if (pCurrentInfo->getKind() == SfxCfgKind::GROUP_FUNCTION) { css::uno::Sequence lCommands; try @@ -366,20 +345,16 @@ void CommandCategoryListBox::categorySelected(CuiConfigFunctionListBox* pFunctio if (rootNode.is() && rootNode->hasChildNodes()) { - //We call acquire on the XBrowseNode so that it does not - //get autodestructed and become invalid when accessed later. - rootNode->acquire(); - m_aGroupInfo.push_back(std::make_unique( - SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, static_cast(rootNode.get()))); + SfxGroupInfo_Data(SfxCfgKindAsIndex, + rootNode), + 0)); // Add main macro groups - const css::uno::Sequence> - aChildNodes = rootNode->getChildNodes(); + const std::vector> aChildNodes + = comphelper::scriptbrowse::getChildNodes(rootNode); for (auto const& childGroup : aChildNodes) { - childGroup->acquire(); - if (childGroup->hasChildNodes()) { OUString sUIName; @@ -402,7 +377,8 @@ void CommandCategoryListBox::categorySelected(CuiConfigFunctionListBox* pFunctio } m_aGroupInfo.push_back(std::make_unique( - SfxCfgKind::GROUP_SCRIPTCONTAINER, 0)); + SfxGroupInfo_Data(SfxCfgKindAsIndex), + 0)); std::unique_ptr xMacroGroup(pFunctionListBox->tree_append( weld::toId(m_aGroupInfo.back().get()), sUIName)); @@ -442,8 +418,8 @@ void CommandCategoryListBox::categorySelected(CuiConfigFunctionListBox* pFunctio continue; } - m_aGroupInfo.push_back( - std::make_unique(SfxCfgKind::GROUP_STYLES, 0)); + m_aGroupInfo.push_back(std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), 0)); // pIt.sLabel is Name of the style family std::unique_ptr xFuncEntry(pFunctionListBox->tree_append( weld::toId(m_aGroupInfo.back().get()), pIt.sLabel)); @@ -468,13 +444,15 @@ void CommandCategoryListBox::categorySelected(CuiConfigFunctionListBox* pFunctio continue; } - SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(pStyleIt); + auto pStyle = std::make_unique(pStyleIt); - m_aGroupInfo.push_back( - std::make_unique(SfxCfgKind::GROUP_STYLES, 0, pStyle)); + m_aGroupInfo.push_back(std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex, + std::move(pStyle)), + 0)); - m_aGroupInfo.back()->sCommand = pStyle->sCommand; - m_aGroupInfo.back()->sLabel = pStyle->sLabel; + m_aGroupInfo.back()->sCommand = pStyleIt.sCommand; + m_aGroupInfo.back()->sLabel = pStyleIt.sLabel; pFunctionListBox->append(weld::toId(m_aGroupInfo.back().get()), sUIName, xFuncEntry.get()); @@ -495,8 +473,7 @@ void CommandCategoryListBox::categorySelected(CuiConfigFunctionListBox* pFunctio } default: // Do nothing, the list box will stay empty - SAL_INFO("cui.customize", - "Ignoring unexpected SfxCfgKind: " << static_cast(pInfo->nKind)); + SAL_INFO("cui.customize", "Ignoring unexpected SfxCfgKind: " << pInfo->aData.index()); break; } @@ -522,19 +499,16 @@ void CommandCategoryListBox::addChildren( m_searchOptions.searchString = filterTerm; utl::TextSearch textSearch(m_searchOptions); - const css::uno::Sequence> aChildNodes - = parentNode->getChildNodes(); + const std::vector> aChildNodes + = comphelper::scriptbrowse::getSortedChildNodes(parentNode); for (auto const& child : aChildNodes) { - // Acquire to prevent auto-destruction - child->acquire(); - if (child->hasChildNodes()) { OUString sUIName = child->getName(); m_aGroupInfo.push_back(std::make_unique( - SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, static_cast(child.get()))); + SfxGroupInfo_Data(SfxCfgKindAsIndex, child), 0)); std::unique_ptr xNewEntry(pFunctionListBox->tree_append( weld::toId(m_aGroupInfo.back().get()), sUIName, parentEntry)); @@ -587,14 +561,12 @@ void CommandCategoryListBox::addChildren( description = CuiResId(RID_CUISTR_NOMACRODESC); } - OUString* pScriptURI = new OUString(uri); - css::uno::Reference xImage; if (pCurrentSaveInData) xImage = pCurrentSaveInData->GetImage(uri); - m_aGroupInfo.push_back( - std::make_unique(SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI)); + m_aGroupInfo.push_back(std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex, uri), 0)); m_aGroupInfo.back()->sCommand = uri; m_aGroupInfo.back()->sLabel = sUIName; m_aGroupInfo.back()->sHelpText = description; diff --git a/cui/source/customize/CustomNotebookbarGenerator.cxx b/cui/source/customize/CustomNotebookbarGenerator.cxx deleted file mode 100644 index 45e9ac02bd5c..000000000000 --- a/cui/source/customize/CustomNotebookbarGenerator.cxx +++ /dev/null @@ -1,283 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace css; - -CustomNotebookbarGenerator::CustomNotebookbarGenerator() {} - -static OUString lcl_activeAppName(vcl::EnumContext::Application eApp) -{ - switch (eApp) - { - case vcl::EnumContext::Application::Writer: - return u"ActiveWriter"_ustr; - case vcl::EnumContext::Application::Calc: - return u"ActiveCalc"_ustr; - case vcl::EnumContext::Application::Impress: - return u"ActiveImpress"_ustr; - case vcl::EnumContext::Application::Draw: - return u"ActiveDraw"_ustr; - default: - return OUString(); - } -} - -static OUString lcl_getAppName(vcl::EnumContext::Application eApp) -{ - switch (eApp) - { - case vcl::EnumContext::Application::Writer: - return u"Writer"_ustr; - case vcl::EnumContext::Application::Calc: - return u"Calc"_ustr; - case vcl::EnumContext::Application::Impress: - return u"Impress"_ustr; - case vcl::EnumContext::Application::Draw: - return u"Draw"_ustr; - default: - return OUString(); - } -} - -static OUString getAppNameRegistryPath() -{ - vcl::EnumContext::Application eApp = vcl::EnumContext::Application::Any; - - if (SfxViewFrame* pViewFrame = SfxViewFrame::Current()) - { - const Reference& xFrame = pViewFrame->GetFrame().GetFrameInterface(); - const Reference xModuleManager - = frame::ModuleManager::create(::comphelper::getProcessComponentContext()); - eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame)); - } - - OUString sAppName(lcl_getAppName(eApp)); - return "org.openoffice.Office.UI.ToolbarMode/Applications/" + sAppName; -} - -static OUString customizedUIPathBuffer() -{ - OUString sDirPath(u"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( - "bootstrap") ":UserInstallation}/user/config/soffice.cfg/"_ustr); - rtl::Bootstrap::expandMacros(sDirPath); - return sDirPath; -} - -OUString CustomNotebookbarGenerator::getCustomizedUIPath() -{ - OUString sAppName, sNotebookbarUIFileName; - CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName); - return customizedUIPathBuffer() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/" - + sNotebookbarUIFileName; -} - -OUString CustomNotebookbarGenerator::getOriginalUIPath() -{ - OUString sAppName, sNotebookbarUIFileName; - CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName); - return AllSettings::GetUIRootDir() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/" - + sNotebookbarUIFileName; -} - -static OUString getUIDirPath() -{ - OUString sAppName, sNotebookbarUIFileName; - CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName); - OUString sUIDirPath - = customizedUIPathBuffer() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/"; - return sUIDirPath; -} - -OString CustomNotebookbarGenerator::getSystemPath(OUString const& sURL) -{ - if (sURL.isEmpty()) - return OString(); - OUString sSystemPathSettings; - if (osl_getSystemPathFromFileURL(sURL.pData, &sSystemPathSettings.pData) != osl_File_E_None) - { - SAL_WARN("cui.customnotebookbar", "Cannot get system path for :" << sURL); - return OString(); - } - OString osSystemPathSettings - = OUStringToOString(sSystemPathSettings, osl_getThreadTextEncoding()); - return osSystemPathSettings; -} - -static void changeNodeValue(xmlNode* pNodePtr, const char* pProperty, const char* pValue) -{ - pNodePtr = pNodePtr->xmlChildrenNode; - while (pNodePtr) - { - if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast("property")))) - { - xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast("name")); - if (!(xmlStrcmp(UriValue, reinterpret_cast(pProperty)))) - xmlNodeSetContent(pNodePtr, reinterpret_cast(pValue)); - xmlFree(UriValue); - break; - } - pNodePtr = pNodePtr->next; - } -} - -static void searchNodeAndAttribute(xmlNode* pNodePtr, const char* pUIItemID, const char* pProperty, - const char* pValue) -{ - pNodePtr = pNodePtr->xmlChildrenNode; - while (pNodePtr) - { - if (pNodePtr->type == XML_ELEMENT_NODE) - { - if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast("object")))) - { - xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast("id")); - if (!(xmlStrcmp(UriValue, reinterpret_cast(pUIItemID)))) - changeNodeValue(pNodePtr, pProperty, pValue); - xmlFree(UriValue); - } - searchNodeAndAttribute(pNodePtr, pUIItemID, pProperty, pValue); - } - pNodePtr = pNodePtr->next; - } -} - -static xmlDocPtr notebookbarXMLParser(const OString& rDocName, const OString& rUIItemID, - const OString& rProperty, const OString& rValue) -{ - xmlDocPtr pDocPtr = xmlParseFile(rDocName.getStr()); - xmlNodePtr pNodePtr = xmlDocGetRootElement(pDocPtr); - searchNodeAndAttribute(pNodePtr, rUIItemID.getStr(), rProperty.getStr(), rValue.getStr()); - return pDocPtr; -} - -void CustomNotebookbarGenerator::modifyCustomizedUIFile(const Sequence& sUIItemProperties) -{ - const OUString sUIPath = getCustomizedUIPath(); - if (osl::File(sUIPath).open(osl_File_OpenFlag_Read) != osl::FileBase::E_None) - createCustomizedUIFile(); - - const OString sCustomizedUIPath = getSystemPath(sUIPath); - for (auto const& aValue : sUIItemProperties) - { - constexpr sal_Int32 aUIPropertiesCount = 3; - std::vector aProperties(aUIPropertiesCount); - for (sal_Int32 aIndex = 0; aIndex < aUIPropertiesCount; aIndex++) - { - sal_Int32 nPos = aIndex; - std::u16string_view sToken = o3tl::getToken(aValue, nPos, ',', nPos); - aProperties[aIndex] = OUStringToOString(sToken, RTL_TEXTENCODING_UTF8); - } - xmlDocPtr doc = notebookbarXMLParser(sCustomizedUIPath, aProperties[0], aProperties[1], - aProperties[2]); - - if (doc != nullptr) - { - xmlSaveFormatFile(sCustomizedUIPath.getStr(), doc, 1); - xmlFreeDoc(doc); - } - } -} - -void CustomNotebookbarGenerator::getFileNameAndAppName(OUString& sAppName, - OUString& sNotebookbarUIFileName) -{ - SfxViewFrame* pFrame = SfxViewFrame::Current(); - if (!pFrame) - return; - - const auto& xContext = comphelper::getProcessComponentContext(); - utl::OConfigurationTreeRoot aRoot(xContext, u"org.openoffice.Office.UI.ToolbarMode/"_ustr, - false); - const Reference& xFrame = pFrame->GetFrame().GetFrameInterface(); - const Reference xModuleManager = frame::ModuleManager::create(xContext); - - vcl::EnumContext::Application eApp - = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame)); - OUString sActiveAppName(lcl_activeAppName(eApp)); - sAppName = lcl_getAppName(eApp); - const Any aValue = aRoot.getNodeValue(sActiveAppName); - aValue >>= sNotebookbarUIFileName; -} - -void CustomNotebookbarGenerator::createCustomizedUIFile() -{ - OUString sUserUIDir = getUIDirPath(); - OUString sOriginalUIPath = getOriginalUIPath(); - OUString sCustomizedUIPath = getCustomizedUIPath(); - - sal_uInt32 nflag = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write; - osl::Directory aDirectory(sUserUIDir); - if (aDirectory.open() != osl::FileBase::E_None) - osl::Directory::create(sUserUIDir, nflag); - else - SAL_WARN("cui.customnotebookbar", - "Cannot create the directory or directory was present :" << sUserUIDir); - - osl::File aFile(sCustomizedUIPath); - if (aFile.open(nflag) != osl::FileBase::E_None) - osl::File::copy(sOriginalUIPath, sCustomizedUIPath); - else - SAL_WARN("cui.customnotebookbar", - "Cannot copy the file or file was present :" << sCustomizedUIPath); -} - -Sequence -CustomNotebookbarGenerator::getCustomizedUIItem(const OUString& sNotebookbarConfigType) -{ - OUString aPath = getAppNameRegistryPath(); - const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath, - false); - - const utl::OConfigurationNode aModesNode = aAppNode.openNode(u"Modes"_ustr); - const utl::OConfigurationNode aModeNode(aModesNode.openNode(sNotebookbarConfigType)); - const Any aValue = aModeNode.getNodeValue(u"UIItemProperties"_ustr); - Sequence aValues; - aValue >>= aValues; - return aValues; -} - -void CustomNotebookbarGenerator::setCustomizedUIItem(const Sequence& rUIItemProperties, - const OUString& rNotebookbarConfigType) -{ - OUString aPath = getAppNameRegistryPath(); - const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath, - true); - const utl::OConfigurationNode aModesNode = aAppNode.openNode(u"Modes"_ustr); - const utl::OConfigurationNode aModeNode(aModesNode.openNode(rNotebookbarConfigType)); - - css::uno::Any aUIItemProperties(rUIItemProperties); - aModeNode.setNodeValue(u"UIItemProperties"_ustr, aUIItemProperties); - aAppNode.commit(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/SvxConfigPageHelper.cxx b/cui/source/customize/SvxConfigPageHelper.cxx index 522dfd3eb721..3df56381e217 100644 --- a/cui/source/customize/SvxConfigPageHelper.cxx +++ b/cui/source/customize/SvxConfigPageHelper.cxx @@ -151,7 +151,7 @@ OUString SvxConfigPageHelper::generateCustomMenuURL(SvxEntries* entries, sal_Int if (!entries) return url; - // now check is there is an already existing entry with this url + // now check if there is an already existing entry with this url bool bFoundEntry = false; for (auto const& entry : *entries) { @@ -182,7 +182,7 @@ OUString SvxConfigPageHelper::generateCustomURL(SvxEntries* entries) // use a random number to minimize possible clash with existing custom toolbars OUString::number(generateRandomValue(), 16); - // now check is there is an already existing entry with this url + // now check if there is an already existing entry with this url bool bFoundEntry = false; for (auto const& entry : *entries) { diff --git a/cui/source/customize/SvxMenuConfigPage.cxx b/cui/source/customize/SvxMenuConfigPage.cxx index ed86353e382d..d0d978fc0cf5 100644 --- a/cui/source/customize/SvxMenuConfigPage.cxx +++ b/cui/source/customize/SvxMenuConfigPage.cxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/cui/source/customize/SvxNotebookbarConfigPage.cxx b/cui/source/customize/SvxNotebookbarConfigPage.cxx deleted file mode 100644 index 66156d179a9d..000000000000 --- a/cui/source/customize/SvxNotebookbarConfigPage.cxx +++ /dev/null @@ -1,569 +0,0 @@ -/* -*- 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 - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace uno = css::uno; -namespace frame = css::frame; -namespace container = css::container; -namespace beans = css::beans; - -static bool isCategoryAvailable(std::u16string_view sClassId, std::u16string_view sUIItemId, - std::u16string_view sActiveCategory, bool& isCategory) -{ - if (sUIItemId == sActiveCategory) - return true; - else if ((sClassId == u"GtkMenu" || sClassId == u"GtkGrid") && sUIItemId != sActiveCategory) - { - isCategory = false; - return false; - } - return false; -} - -static OUString charToString(const char* cString) -{ - return OUString(cString, strlen(cString), RTL_TEXTENCODING_UTF8); -} - -static OUString getFileName(std::u16string_view aFileName) -{ - if (aFileName == u"notebookbar.ui") - return CuiResId(RID_CUISTR_TABBED); - else if (aFileName == u"notebookbar_compact.ui") - return CuiResId(RID_CUISTR_TABBED_COMPACT); - else if (aFileName == u"notebookbar_groupedbar_full.ui") - return CuiResId(RID_CUISTR_GROUPEDBAR); - else if (aFileName == u"notebookbar_groupedbar_compact.ui") - return CuiResId(RID_CUISTR_GROUPEDBAR_COMPACT); - else - return u"None"_ustr; -} - -static OUString getModuleId(std::u16string_view sModuleName) -{ - if (sModuleName == u"Writer") - return u"com.sun.star.text.TextDocument"_ustr; - else if (sModuleName == u"Draw") - return u"com.sun.star.drawing.DrawingDocument"_ustr; - else if (sModuleName == u"Impress") - return u"com.sun.star.presentation.PresentationDocument"_ustr; - else if (sModuleName == u"Calc") - return u"com.sun.star.sheet.SpreadsheetDocument"_ustr; - else - return u"None"_ustr; -} - -SvxNotebookbarConfigPage::SvxNotebookbarConfigPage(weld::Container* pPage, - weld::DialogController* pController, - const SfxItemSet& rSet) - : SvxConfigPage(pPage, pController, rSet) -{ - m_xCommandCategoryListBox->set_visible(false); - m_xDescriptionFieldLb->set_visible(false); - m_xSearchEdit->set_visible(false); - m_xDescriptionField->set_visible(false); - m_xMoveUpButton->set_visible(false); - m_xMoveDownButton->set_visible(false); - m_xCommandButtons->set_visible(false); - m_xLeftFunctionLabel->set_visible(false); - m_xSearchLabel->set_visible(false); - m_xCategoryLabel->set_visible(false); - m_xCustomizeBox->set_visible(false); - m_xCustomizeLabel->set_visible(false); - - weld::TreeView& rCommandCategoryBox = m_xFunctions->get_widget(); - rCommandCategoryBox.hide(); - - m_xContentsListBox.reset( - new SvxNotebookbarEntriesListBox(m_xBuilder->weld_tree_view(u"toolcontents"_ustr), this)); - m_xDropTargetHelper.reset(new SvxConfigPageFunctionDropTarget( - *this, m_xContentsListBox->get_widget(), rCommandCategoryBox, Link())); - weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); - Size aSize(m_xFunctions->get_size_request()); - rTreeView.set_size_request(aSize.Width(), aSize.Height()); - - rTreeView.set_hexpand(true); - rTreeView.set_vexpand(true); - rTreeView.set_help_id(HID_SVX_CONFIG_NOTEBOOKBAR_CONTENTS); - rTreeView.show(); -} - -SvxNotebookbarConfigPage::~SvxNotebookbarConfigPage() {} - -void SvxNotebookbarConfigPage::DeleteSelectedTopLevel() {} - -void SvxNotebookbarConfigPage::DeleteSelectedContent() {} - -void SvxNotebookbarConfigPage::Init() -{ - m_xTopLevelListBox->clear(); - m_xContentsListBox->clear(); - m_xSaveInListBox->clear(); - OUString sNotebookbarInterface = getFileName(m_sFileName); - - OUString sScopeName - = utl::ConfigManager::getProductName() + " " + m_sAppName + " - " + sNotebookbarInterface; - OUString sSaveInListBoxID = notebookbarTabScope; - - m_xSaveInListBox->append(sSaveInListBoxID, sScopeName); - m_xSaveInListBox->set_active_id(sSaveInListBoxID); - - m_xTopLevelListBox->append(u"NotebookBar"_ustr, CuiResId(RID_CUISTR_ALL_COMMANDS)); - m_xTopLevelListBox->set_active_id(u"NotebookBar"_ustr); - SelectElement(); -} - -SaveInData* SvxNotebookbarConfigPage::CreateSaveInData( - const css::uno::Reference& xCfgMgr, - const css::uno::Reference& xParentCfgMgr, - const OUString& aModuleId, bool bDocConfig) -{ - return static_cast( - new ToolbarSaveInData(xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig)); -} - -void SvxNotebookbarConfigPage::UpdateButtonStates() {} - -short SvxNotebookbarConfigPage::QueryReset() -{ - OUString msg = CuiResId(RID_CUISTR_CONFIRM_TOOLBAR_RESET); - - OUString saveInName = m_xSaveInListBox->get_active_text(); - - OUString label = SvxConfigPageHelper::replaceSaveInName(msg, saveInName); - - std::unique_ptr xQueryBox(Application::CreateMessageDialog( - GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo, label)); - int nValue = xQueryBox->run(); - if (nValue == RET_YES) - { - osl::File::remove(CustomNotebookbarGenerator::getCustomizedUIPath()); - - OUString sNotebookbarInterface = getFileName(m_sFileName); - Sequence sSequenceEntries; - CustomNotebookbarGenerator::setCustomizedUIItem(sSequenceEntries, sNotebookbarInterface); - OUString sUIPath = "modules/s" + m_sAppName.toAsciiLowerCase() + "/ui/"; - sfx2::SfxNotebookBar::ReloadNotebookBar(sUIPath); - } - return nValue; -} - -void SvxConfigPage::InsertEntryIntoNotebookbarTabUI(std::u16string_view sClassId, - const OUString& sUIItemId, - const OUString& sUIItemCommand, - weld::TreeView& rTreeView, - const weld::TreeIter& rIter) -{ - css::uno::Reference m_xCommandToLabelMap; - const uno::Reference& xContext - = ::comphelper::getProcessComponentContext(); - uno::Reference xNameAccess( - css::frame::theUICommandDescription::get(xContext)); - - uno::Sequence aPropSeq; - - xNameAccess->getByName(getModuleId(m_sAppName)) >>= m_xCommandToLabelMap; - - try - { - uno::Any aModuleVal = m_xCommandToLabelMap->getByName(sUIItemCommand); - - aModuleVal >>= aPropSeq; - } - catch (container::NoSuchElementException&) - { - } - - OUString aLabel; - for (auto const& prop : aPropSeq) - if (prop.Name == "Name") - prop.Value >>= aLabel; - - OUString aName = SvxConfigPageHelper::stripHotKey(aLabel); - - if (sClassId == u"GtkSeparatorMenuItem" || sClassId == u"GtkSeparator") - { - rTreeView.set_text(rIter, u"--------------------------------------------"_ustr, 0); - } - else - { - if (aName.isEmpty()) - aName = sUIItemId; - auto xImage = GetSaveInData()->GetImage(sUIItemCommand); - if (xImage.is()) - rTreeView.set_image(rIter, xImage, -1); - rTreeView.set_text(rIter, aName, 0); - rTreeView.set_id(rIter, sUIItemId); - } -} - -void SvxNotebookbarConfigPage::getNodeValue(xmlNode* pNodePtr, NotebookbarEntries& aNodeEntries) -{ - pNodePtr = pNodePtr->xmlChildrenNode; - while (pNodePtr) - { - if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast("property")))) - { - xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast("name")); - if (!(xmlStrcmp(UriValue, reinterpret_cast("visible")))) - { - xmlChar* aValue = xmlNodeGetContent(pNodePtr); - const char* cVisibleValue = reinterpret_cast(aValue); - aNodeEntries.sVisibleValue = charToString(cVisibleValue); - xmlFree(aValue); - } - if (!(xmlStrcmp(UriValue, reinterpret_cast("action_name")))) - { - xmlChar* aValue = xmlNodeGetContent(pNodePtr); - const char* cActionName = reinterpret_cast(aValue); - aNodeEntries.sActionName = charToString(cActionName); - xmlFree(aValue); - } - xmlFree(UriValue); - } - pNodePtr = pNodePtr->next; - } -} - -void SvxNotebookbarConfigPage::searchNodeandAttribute(std::vector& aEntries, - std::vector& aCategoryList, - OUString& sActiveCategory, - CategoriesEntries& aCurItemEntry, - xmlNode* pNodePtr, bool isCategory) -{ - pNodePtr = pNodePtr->xmlChildrenNode; - while (pNodePtr) - { - if (pNodePtr->type == XML_ELEMENT_NODE) - { - const char* cNodeName = reinterpret_cast(pNodePtr->name); - if (strcmp(cNodeName, "object") == 0) - { - OUString sSecondVal; - - xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast("id")); - const char* cUIItemID = reinterpret_cast(UriValue); - OUString sUIItemId = charToString(cUIItemID); - xmlFree(UriValue); - - UriValue = xmlGetProp(pNodePtr, reinterpret_cast("class")); - const char* cClassId = reinterpret_cast(UriValue); - OUString sClassId = charToString(cClassId); - xmlFree(UriValue); - - CategoriesEntries aCategoryEntry; - if (sClassId == "sfxlo-PriorityHBox") - { - aCategoryEntry.sDisplayName = sUIItemId; - aCategoryEntry.sUIItemId = sUIItemId; - aCategoryEntry.sClassType = sClassId; - aCategoryList.push_back(aCategoryEntry); - - aCurItemEntry = std::move(aCategoryEntry); - } - else if (sClassId == "sfxlo-PriorityMergedHBox") - { - aCategoryEntry.sDisplayName = aCurItemEntry.sDisplayName + " | " + sUIItemId; - aCategoryEntry.sUIItemId = sUIItemId; - aCategoryEntry.sClassType = sClassId; - - if (aCurItemEntry.sClassType == sClassId) - { - sal_Int32 rPos = 0; - aCategoryEntry.sDisplayName - = OUString::Concat( - o3tl::getToken(aCurItemEntry.sDisplayName, rPos, ' ', rPos)) - + " | " + sUIItemId; - } - aCategoryList.push_back(aCategoryEntry); - aCurItemEntry = std::move(aCategoryEntry); - } - else if (sClassId == "svtlo-ManagedMenuButton") - { - sal_Int32 rPos = 1; - sSecondVal = sUIItemId.getToken(rPos, ':', rPos); - if (!sSecondVal.isEmpty()) - { - aCategoryEntry.sDisplayName - = aCurItemEntry.sDisplayName + " | " + sSecondVal; - aCategoryEntry.sUIItemId = sSecondVal; - aCategoryList.push_back(aCategoryEntry); - } - } - - NotebookbarEntries nodeEntries; - if (isCategoryAvailable(sClassId, sUIItemId, sActiveCategory, isCategory) - || isCategory) - { - isCategory = true; - if (sClassId == "GtkMenuItem" || sClassId == "GtkToolButton" - || sClassId == "GtkMenuToolButton" - || (sClassId == "svtlo-ManagedMenuButton" && sSecondVal.isEmpty())) - { - nodeEntries.sClassId = sClassId; - nodeEntries.sUIItemId = sUIItemId; - nodeEntries.sDisplayName = sUIItemId; - - getNodeValue(pNodePtr, nodeEntries); - aEntries.push_back(nodeEntries); - } - else if (sClassId == "GtkSeparatorMenuItem" || sClassId == "GtkSeparator") - { - nodeEntries.sClassId = sClassId; - nodeEntries.sUIItemId = sUIItemId; - nodeEntries.sDisplayName = "Null"; - nodeEntries.sVisibleValue = "Null"; - nodeEntries.sActionName = "Null"; - aEntries.push_back(nodeEntries); - } - else if (sClassId == "sfxlo-PriorityHBox" - || sClassId == "sfxlo-PriorityMergedHBox" - || sClassId == "svtlo-ManagedMenuButton") - { - nodeEntries.sClassId = sClassId; - nodeEntries.sUIItemId = sUIItemId; - nodeEntries.sDisplayName - = aCategoryList[aCategoryList.size() - 1].sDisplayName; - nodeEntries.sVisibleValue = "Null"; - nodeEntries.sActionName = "Null"; - aEntries.push_back(nodeEntries); - } - } - } - searchNodeandAttribute(aEntries, aCategoryList, sActiveCategory, aCurItemEntry, - pNodePtr, isCategory); - } - pNodePtr = pNodePtr->next; - } -} - -void SvxNotebookbarConfigPage::FillFunctionsList(xmlNodePtr pRootNodePtr, - std::vector& aEntries, - std::vector& aCategoryList, - OUString& sActiveCategory) -{ - CategoriesEntries aCurItemEntry; - searchNodeandAttribute(aEntries, aCategoryList, sActiveCategory, aCurItemEntry, pRootNodePtr, - false); -} - -void SvxNotebookbarConfigPage::SelectElement() -{ - OString sUIFileUIPath = CustomNotebookbarGenerator::getSystemPath( - CustomNotebookbarGenerator::getCustomizedUIPath()); - xmlDocPtr pDoc = xmlParseFile(sUIFileUIPath.getStr()); - if (!pDoc) - { - sUIFileUIPath = CustomNotebookbarGenerator::getSystemPath( - CustomNotebookbarGenerator::getOriginalUIPath()); - pDoc = xmlParseFile(sUIFileUIPath.getStr()); - } - - if (!pDoc) - return; - xmlNodePtr pNodePtr = xmlDocGetRootElement(pDoc); - - std::vector aEntries; - std::vector aCategoryList; - OUString sActiveCategory = m_xTopLevelListBox->get_active_id(); - FillFunctionsList(pNodePtr, aEntries, aCategoryList, sActiveCategory); - - if (m_xTopLevelListBox->get_count() == 1) - { - for (const auto& rCategory : aCategoryList) - m_xTopLevelListBox->append(rCategory.sUIItemId, rCategory.sDisplayName); - } - tools::ULong nStart = 0; - if (aEntries[nStart].sClassId == "sfxlo-PriorityHBox" - || aEntries[nStart].sClassId == "sfxlo-PriorityMergedHBox") - nStart = 1; - - std::vector aTempEntries; - for (std::size_t nIdx = nStart; nIdx < aEntries.size(); nIdx++) - { - if (aEntries[nIdx].sClassId == "svtlo-ManagedMenuButton") - { - aTempEntries.push_back(aEntries[nIdx]); - sal_Int32 rPos = 1; - sActiveCategory = aEntries[nIdx].sUIItemId.getToken(rPos, ':', rPos); - FillFunctionsList(pNodePtr, aTempEntries, aCategoryList, sActiveCategory); - } - else - aTempEntries.push_back(aEntries[nIdx]); - } - - aEntries = std::move(aTempEntries); - - static_cast(m_xContentsListBox.get())->GetTooltipMap().clear(); - weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); - rTreeView.bulk_insert_for_each( - aEntries.size(), [this, &rTreeView, &aEntries](weld::TreeIter& rIter, int nIdx) { - if (aEntries[nIdx].sActionName != "Null") - { - if (aEntries[nIdx].sVisibleValue == "True") - { - rTreeView.set_toggle(rIter, TRISTATE_TRUE); - } - else - { - rTreeView.set_toggle(rIter, TRISTATE_FALSE); - } - } - InsertEntryIntoNotebookbarTabUI(aEntries[nIdx].sClassId, aEntries[nIdx].sDisplayName, - aEntries[nIdx].sActionName, rTreeView, rIter); - if (aEntries[nIdx].sClassId != u"GtkSeparatorMenuItem" - && aEntries[nIdx].sClassId != u"GtkSeparator") - { - static_cast(m_xContentsListBox.get()) - ->GetTooltipMap()[aEntries[nIdx].sDisplayName] - = aEntries[nIdx].sActionName; - } - }); - - aEntries.clear(); - - xmlFreeDoc(pDoc); -} - -SvxNotebookbarEntriesListBox::SvxNotebookbarEntriesListBox(std::unique_ptr xParent, - SvxConfigPage* pPg) - : SvxMenuEntriesListBox(std::move(xParent), pPg) -{ - m_xControl->connect_toggled(LINK(this, SvxNotebookbarEntriesListBox, CheckButtonHdl)); - m_xControl->connect_key_press(Link()); - m_xControl->connect_key_press(LINK(this, SvxNotebookbarEntriesListBox, KeyInputHdl)); - // remove the inherited connect_query_tooltip then add the new one - m_xControl->connect_query_tooltip(Link()); - m_xControl->connect_query_tooltip(LINK(this, SvxNotebookbarEntriesListBox, QueryTooltip)); -} - -SvxNotebookbarEntriesListBox::~SvxNotebookbarEntriesListBox() {} - -static void EditRegistryFile(std::u16string_view sUIItemId, const OUString& sSetEntry, - const OUString& sNotebookbarInterface) -{ - int nFlag = 0; - Sequence aOldEntries - = CustomNotebookbarGenerator::getCustomizedUIItem(sNotebookbarInterface); - Sequence aNewEntries(aOldEntries.getLength() + 1); - auto pNewEntries = aNewEntries.getArray(); - for (int nIdx = 0; nIdx < aOldEntries.getLength(); nIdx++) - { - sal_Int32 rPos = 0; - std::u16string_view sFirstValue = o3tl::getToken(aOldEntries[nIdx], rPos, ',', rPos); - if (sFirstValue == sUIItemId) - { - aOldEntries.getArray()[nIdx] = sSetEntry; - nFlag = 1; - break; - } - pNewEntries[nIdx] = aOldEntries[nIdx]; - } - - if (nFlag == 0) - { - pNewEntries[aOldEntries.getLength()] = sSetEntry; - CustomNotebookbarGenerator::setCustomizedUIItem(aNewEntries, sNotebookbarInterface); - } - else - { - CustomNotebookbarGenerator::setCustomizedUIItem(aOldEntries, sNotebookbarInterface); - } -} - -void SvxNotebookbarEntriesListBox::ChangedVisibility(int nRow) -{ - OUString sUIItemId = m_xControl->get_selected_id(); - OUString sNotebookbarInterface = getFileName(m_pPage->GetFileName()); - - OUString sVisible; - if (m_xControl->get_toggle(nRow) == TRISTATE_TRUE) - sVisible = "True"; - else - sVisible = "False"; - OUString sSetEntries = sUIItemId + ",visible," + sVisible; - Sequence sSeqOfEntries{ sSetEntries }; - EditRegistryFile(sUIItemId, sSetEntries, sNotebookbarInterface); - CustomNotebookbarGenerator::modifyCustomizedUIFile(sSeqOfEntries); - OUString sUIPath = "modules/s" + m_pPage->GetAppName().toAsciiLowerCase() + "/ui/"; - sfx2::SfxNotebookBar::ReloadNotebookBar(sUIPath); -} - -IMPL_LINK(SvxNotebookbarEntriesListBox, CheckButtonHdl, const weld::TreeView::iter_col&, rRowCol, - void) -{ - ChangedVisibility(m_xControl->get_iter_index_in_parent(rRowCol.first)); -} - -IMPL_LINK(SvxNotebookbarEntriesListBox, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) -{ - if (rKeyEvent.GetKeyCode() == KEY_SPACE) - { - int nRow = m_xControl->get_selected_index(); - m_xControl->set_toggle(nRow, m_xControl->get_toggle(nRow) == TRISTATE_TRUE ? TRISTATE_FALSE - : TRISTATE_TRUE); - ChangedVisibility(nRow); - return true; - } - return SvxMenuEntriesListBox::KeyInputHdl(rKeyEvent); -} - -IMPL_LINK(SvxNotebookbarEntriesListBox, QueryTooltip, const weld::TreeIter&, rIter, OUString) -{ - const OUString& rsCommand = m_aTooltipMap[m_xControl->get_id(rIter)]; - if (rsCommand.isEmpty()) - return OUString(); - OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(m_pPage->GetFrame())); - auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(rsCommand, aModuleName); - OUString sTooltipLabel = vcl::CommandInfoProvider::GetTooltipForCommand(rsCommand, aProperties, - m_pPage->GetFrame()); - return CuiResId(RID_CUISTR_COMMANDLABEL) + ": " - + m_xControl->get_text(rIter).replaceFirst("~", "") + "\n" - + CuiResId(RID_CUISTR_COMMANDNAME) + ": " + rsCommand + "\n" - + CuiResId(RID_CUISTR_COMMANDTIP) + ": " + sTooltipLabel.replaceFirst("~", ""); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/SvxToolbarConfigPage.cxx b/cui/source/customize/SvxToolbarConfigPage.cxx index 12400ee7e191..1c70bff2b0ca 100644 --- a/cui/source/customize/SvxToolbarConfigPage.cxx +++ b/cui/source/customize/SvxToolbarConfigPage.cxx @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/cui/source/customize/acccfg.cxx b/cui/source/customize/acccfg.cxx index 6f413b570e63..0afdfca1327c 100644 --- a/cui/source/customize/acccfg.cxx +++ b/cui/source/customize/acccfg.cxx @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -1111,13 +1112,16 @@ void SfxAcceleratorConfigPage::InitAccCfg() // get global accelerator configuration m_xGlobal = css::ui::GlobalAcceleratorConfiguration::create(m_xContext); - // get module accelerator configuration - - uno::Reference xModuleCfgSupplier( - ui::theModuleUIConfigurationManagerSupplier::get(m_xContext)); - uno::Reference xUICfgManager - = xModuleCfgSupplier->getUIConfigurationManager(m_sModuleLongName); - m_xModule = xUICfgManager->getShortCutManager(); + // get module accelerator configuration, unless it’s the start module in which case we’ll + // only allow configuring the global configuration + if (m_sModuleLongName != "com.sun.star.frame.StartModule") + { + uno::Reference xModuleCfgSupplier( + ui::theModuleUIConfigurationManagerSupplier::get(m_xContext)); + uno::Reference xUICfgManager + = xModuleCfgSupplier->getUIConfigurationManager(m_sModuleLongName); + m_xModule = xUICfgManager->getShortCutManager(); + } } catch (const uno::RuntimeException&) { @@ -1250,7 +1254,7 @@ IMPL_LINK_NOARG(SfxAcceleratorConfigPage, ImplUpdateDataHdl, Timer*, void) SelectHdl(m_xGroupLBox->get_widget()); } -IMPL_LINK_NOARG(SfxAcceleratorConfigPage, SearchUpdateHdl, weld::Entry&, void) +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, SearchUpdateHdl, weld::TextWidget&, void) { m_aUpdateDataTimer.Start(); } diff --git a/cui/source/customize/cfg.cxx b/cui/source/customize/cfg.cxx index 931f064eb18e..4fe1579ec9b2 100644 --- a/cui/source/customize/cfg.cxx +++ b/cui/source/customize/cfg.cxx @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -57,10 +56,8 @@ #include #include -#include #include #include -#include #include #include "eventdlg.hxx" #include @@ -189,12 +186,6 @@ static std::unique_ptr CreateKeyboardConfigPage( weld::Container* pP return std::make_unique(pPage, pController, *rSet); } -static std::unique_ptr CreateSvxNotebookbarConfigPage(weld::Container* pPage, weld::DialogController* pController, - const SfxItemSet* rSet) -{ - return std::make_unique(pPage, pController, *rSet); -} - static std::unique_ptr CreateSvxToolbarConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) { return std::make_unique(pPage, pController, *rSet); @@ -221,8 +212,6 @@ SvxConfigDialog::SvxConfigDialog(weld::Window * pParent, const SfxItemSet* pInSe RID_L + RID_TAB_MENUS.sIconName); AddTabPage(u"toolbars"_ustr, TabResId(RID_TAB_TOOLBARS.aLabel), CreateSvxToolbarConfigPage, RID_L + RID_TAB_TOOLBARS.sIconName); - AddTabPage(u"notebookbar"_ustr, TabResId(RID_TAB_NOTEBOOKBARS.aLabel), - CreateSvxNotebookbarConfigPage, RID_L + RID_TAB_NOTEBOOKBARS.sIconName); AddTabPage(u"contextmenus"_ustr, TabResId(RID_TAB_CONTEXTMENUS.aLabel), CreateSvxContextMenuConfigPage, RID_L + RID_TAB_CONTEXTMENUS.sIconName); AddTabPage(u"keyboard"_ustr, TabResId(RID_TAB_KEYBOARD.aLabel), CreateKeyboardConfigPage, @@ -258,16 +247,6 @@ void SvxConfigDialog::ActivatePage(const OUString& rPage) void SvxConfigDialog::SetFrame(const css::uno::Reference& xFrame) { m_xFrame = xFrame; - OUString aModuleId = SvxConfigPage::GetFrameWithDefaultAndIdentify(m_xFrame); - - if (aModuleId != "com.sun.star.text.TextDocument" && - aModuleId != "com.sun.star.sheet.SpreadsheetDocument" && - aModuleId != "com.sun.star.presentation.PresentationDocument" && - aModuleId != "com.sun.star.drawing.DrawingDocument") - RemoveTabPage(u"notebookbar"_ustr); - - if (aModuleId == "com.sun.star.frame.StartModule") - RemoveTabPage(u"keyboard"_ustr); } void SvxConfigDialog::PageCreated(const OUString &rId, SfxTabPage& rPage) @@ -955,7 +934,7 @@ SvxMenuEntriesListBox::SvxMenuEntriesListBox(std::unique_ptr xCo , m_xDropDown(m_xControl->create_virtual_device()) , m_pPage(pPg) { - m_xControl->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xControl->enable_toggle_buttons(); CreateDropDown(); m_xControl->connect_key_press(LINK(this, SvxMenuEntriesListBox, KeyInputHdl)); m_xControl->connect_query_tooltip(LINK(this, SvxMenuEntriesListBox, QueryTooltip)); @@ -1038,8 +1017,6 @@ SvxConfigPage::SvxConfigPage(weld::Container* pPage, weld::DialogController* pCo , m_xAddCommandButton(m_xBuilder->weld_button(u"add"_ustr)) , m_xRemoveCommandButton(m_xBuilder->weld_button(u"remove"_ustr)) { - CustomNotebookbarGenerator::getFileNameAndAppName(m_sAppName, m_sFileName); - m_xTopLevelListBox->connect_changed(LINK(this, SvxConfigPage, SelectElementHdl)); weld::TreeView& rTreeView = m_xFunctions->get_widget(); @@ -1336,9 +1313,9 @@ OUString SvxConfigPage::GetScriptURL() const SfxGroupInfo_Impl *pData = weld::fromId(m_xFunctions->get_selected_id()); if (pData) { - if ( ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) || - ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) || - ( pData->nKind == SfxCfgKind::GROUP_STYLES ) ) + if ( ( pData->getKind() == SfxCfgKind::FUNCTION_SLOT ) || + ( pData->getKind() == SfxCfgKind::FUNCTION_SCRIPT ) || + ( pData->getKind() == SfxCfgKind::GROUP_STYLES ) ) { result = pData->sCommand; } @@ -1706,7 +1683,7 @@ IMPL_LINK_NOARG(SvxConfigPage, ImplUpdateDataHdl, Timer*, void) SelectFunctionHdl(m_xFunctions->get_widget()); } -IMPL_LINK_NOARG(SvxConfigPage, SearchUpdateHdl, weld::Entry&, void) +IMPL_LINK_NOARG(SvxConfigPage, SearchUpdateHdl, weld::TextWidget&, void) { m_aUpdateDataTimer.Start(); } @@ -1867,7 +1844,7 @@ SvxMainMenuOrganizerDialog::~SvxMainMenuOrganizerDialog() { } -IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, ModifyHdl, weld::Entry&, void) +IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, ModifyHdl, weld::TextWidget&, void) { // if the Edit control is empty do not change the name if (m_xMenuNameEdit->get_text().isEmpty()) diff --git a/cui/source/customize/cfgutil.cxx b/cui/source/customize/cfgutil.cxx index b6af7201dd3a..00400a37d9e3 100644 --- a/cui/source/customize/cfgutil.cxx +++ b/cui/source/customize/cfgutil.cxx @@ -38,13 +38,16 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -56,10 +59,10 @@ #include #include #include +#include #include #include -#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -250,11 +253,11 @@ OUString CuiConfigFunctionListBox::GetCommandHelpText() SfxGroupInfo_Impl *pData = weld::fromId(get_selected_id()); if (pData) { - if ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) + if ( pData->getKind() == SfxCfgKind::FUNCTION_SLOT ) { return Application::GetHelp()->GetHelpText(pData->sCommand); } - else if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) + else if ( pData->getKind() == SfxCfgKind::FUNCTION_SCRIPT ) { return pData->sHelpText; } @@ -311,27 +314,6 @@ void CuiConfigFunctionListBox::ClearAll() possibly existing MacroInfo. */ { - sal_uInt16 nCount = aArr.size(); - for ( sal_uInt16 i=0; inKind == SfxCfgKind::FUNCTION_SCRIPT ) - { - OUString* pScriptURI = static_cast(pData->pObject); - delete pScriptURI; - } - - if ( pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER ) - { - XInterface* xi = static_cast(pData->pObject); - if (xi != nullptr) - { - xi->release(); - } - } - } - aArr.clear(); m_xTreeView->clear(); } @@ -339,8 +321,8 @@ void CuiConfigFunctionListBox::ClearAll() OUString CuiConfigFunctionListBox::GetSelectedScriptURI() const { SfxGroupInfo_Impl *pData = weld::fromId(get_selected_id()); - if (pData && pData->nKind == SfxCfgKind::FUNCTION_SCRIPT) - return *static_cast(pData->pObject); + if (pData && pData->getKind() == SfxCfgKind::FUNCTION_SCRIPT) + return std::get(pData->aData).sUrl; return OUString(); } @@ -439,30 +421,6 @@ CuiConfigGroupListBox::~CuiConfigGroupListBox() void CuiConfigGroupListBox::ClearAll() { - sal_uInt16 nCount = aArr.size(); - for ( sal_uInt16 i=0; inKind == SfxCfgKind::GROUP_STYLES && pData->pObject) - { - SfxStyleInfo_Impl* pStyle = static_cast(pData->pObject); - delete pStyle; - } - else if (pData->nKind == SfxCfgKind::FUNCTION_SCRIPT && pData->pObject ) - { - OUString* pScriptURI = static_cast(pData->pObject); - delete pScriptURI; - } - else if (pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER) - { - XInterface* xi = static_cast(pData->pObject); - if (xi != nullptr) - { - xi->release(); - } - } - } - aArr.clear(); m_xTreeView->clear(); } @@ -493,7 +451,9 @@ sal_Int32 CuiConfigGroupListBox::InitModule() catch(const css::container::NoSuchElementException&) { continue; } - aArr.push_back( std::make_unique( SfxCfgKind::GROUP_FUNCTION, nGroupID ) ); + aArr.push_back( + std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), nGroupID ) ); m_xTreeView->append(weld::toId(aArr.back().get()), sGroupName); nAddedGroups++; } @@ -507,6 +467,7 @@ sal_Int32 CuiConfigGroupListBox::InitModule() } void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode, + const css::uno::Reference< css::frame::XModel >& xParentDocumentModel, const weld::TreeIter* pParentEntry) { try { @@ -515,8 +476,8 @@ void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::scrip // tdf#120362: Don't ask to enable disabled Java when filling script list css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext()); - const Sequence< Reference< browse::XBrowseNode > > children = - xRootNode->getChildNodes(); + std::vector< Reference< browse::XBrowseNode > > children = + comphelper::scriptbrowse::getChildNodes(xRootNode); bool bIsRootNode = false; OUString user(u"user"_ustr); @@ -525,6 +486,10 @@ void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::scrip { bIsRootNode = true; } + else + { + comphelper::scriptbrowse::sortNodes(children); + } //To mimic current starbasic behaviour we //need to make sure that only the current document @@ -546,6 +511,7 @@ void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::scrip bool bDisplay = true; OUString uiName = theChild->getName(); + Reference< XModel > xDocumentModel; if ( bIsRootNode ) { if ( ! (uiName == user || uiName == share || @@ -563,20 +529,24 @@ void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::scrip { uiName = xImp->m_sProdMacros; } + else + { + xDocumentModel = getDocumentModel(m_xContext, uiName); + } } } + else + { + xDocumentModel = xParentDocumentModel; + } if (theChild->getType() != browse::BrowseNodeTypes::SCRIPT && bDisplay ) { -// We call acquire on the XBrowseNode so that it does not -// get autodestructed and become invalid when accessed later. - theChild->acquire(); - bool bChildOnDemand = false; if ( theChild->hasChildNodes() ) { - const Sequence< Reference< browse::XBrowseNode > > grandchildren = - theChild->getChildNodes(); + const std::vector< Reference< browse::XBrowseNode > > grandchildren = + comphelper::scriptbrowse::getChildNodes(theChild); for ( const auto& rxNode : grandchildren ) { @@ -593,8 +563,12 @@ void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::scrip OUString aImage = GetImage(theChild, m_xContext, bIsRootNode); - aArr.push_back( std::make_unique(SfxCfgKind::GROUP_SCRIPTCONTAINER, - 0, static_cast( theChild.get()))); + aArr.push_back( + std::make_unique( + SfxGroupInfo_Data( + SfxCfgKindAsIndex, theChild, + xDocumentModel), + 0)); OUString sId(weld::toId(aArr.back().get())); m_xTreeView->insert(pParentEntry, -1, &uiName, &sId, nullptr, nullptr, bChildOnDemand, m_xScratchIter.get()); @@ -616,7 +590,8 @@ void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence( SfxCfgKind::FUNCTION_SLOT, 0 ) ); + aArr.push_back( std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), 0 ) ); SfxGroupInfo_Impl* pGrpInfo = aArr.back().get(); pGrpInfo->sCommand = rInfo.Command; pGrpInfo->sLabel = sUIName; @@ -669,7 +644,8 @@ void CuiConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponent // add All Commands to the top if ( bEventMode && nAddedGroups ) { - aArr.insert(aArr.begin(), std::make_unique(SfxCfgKind::GROUP_ALLFUNCTIONS, 0)); + aArr.insert(aArr.begin(), std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), 0)); OUString sId(weld::toId(aArr.front().get())); OUString s(CuiResId(RID_CUISTR_ALLFUNCTIONS)); m_xTreeView->insert(nullptr, 0, &s, &sId, nullptr, nullptr, false, nullptr); @@ -680,12 +656,11 @@ void CuiConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponent { if ( bEventMode ) { - //We call acquire on the XBrowseNode so that it does not - //get autodestructed and become invalid when accessed later. - rootNode->acquire(); - - aArr.push_back( std::make_unique( SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, - static_cast(rootNode.get()))); + aArr.push_back( + std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex, + rootNode), + 0) ); OUString aTitle(xImp->m_sDlgMacros); OUString sId(weld::toId(aArr.back().get())); m_xTreeView->insert(nullptr, -1, &aTitle, &sId, nullptr, nullptr, true, nullptr); @@ -694,19 +669,24 @@ void CuiConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponent { //We are only showing scripts not slot APIs so skip //Root node and show location nodes - FillScriptList(rootNode, nullptr); + FillScriptList(rootNode, css::uno::Reference(), nullptr); } } // add styles and sidebar decks to the end if ( bEventMode ) { - aArr.push_back( std::make_unique( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); // TODO last parameter should contain user data + aArr.push_back( std::make_unique( + // TODO last parameter should contain user data + SfxGroupInfo_Data(SfxCfgKindAsIndex), + 0 ) ); OUString sStyle(xImp->m_aStrGroupStyles); OUString sId(weld::toId(aArr.back().get())); m_xTreeView->insert(nullptr, -1, &sStyle, &sId, nullptr, nullptr, true, nullptr); - aArr.push_back( std::make_unique(SfxCfgKind::GROUP_SIDEBARDECKS, 0)); + aArr.push_back( + std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), 0) ); OUString sSidebarDecks(xImp->m_aStrGroupSidebarDecks); sId = weld::toId(aArr.back().get()); m_xTreeView->insert(nullptr, -1, &sSidebarDecks, &sId, nullptr, nullptr, false, nullptr); @@ -776,34 +756,6 @@ OUString CuiConfigGroupListBox::GetImage( return aImage; } -Reference< XInterface > -CuiConfigGroupListBox::getDocumentModel( Reference< XComponentContext > const & xCtx, std::u16string_view docName ) -{ - Reference< XInterface > xModel; - Reference< frame::XDesktop2 > desktop = frame::Desktop::create( xCtx ); - - Reference< container::XEnumerationAccess > componentsAccess = - desktop->getComponents(); - Reference< container::XEnumeration > components = - componentsAccess->createEnumeration(); - while (components->hasMoreElements()) - { - Reference< frame::XModel > model( - components->nextElement(), UNO_QUERY ); - if ( model.is() ) - { - OUString sTdocUrl = - ::comphelper::DocumentInfo::getDocumentTitle( model ); - if( sTdocUrl == docName ) - { - xModel = model; - break; - } - } - } - return xModel; -} - OUString CuiConfigGroupListBox::MapCommand2UIName(const OUString& sCommand) { OUString sUIName; @@ -845,7 +797,7 @@ void CuiConfigGroupListBox::GroupSelected() m_pFunctionListBox->freeze(); m_pFunctionListBox->ClearAll(); - switch ( pInfo->nKind ) + switch ( pInfo->getKind() ) { case SfxCfgKind::GROUP_ALLFUNCTIONS: { @@ -854,7 +806,7 @@ void CuiConfigGroupListBox::GroupSelected() while (bValidIter) { SfxGroupInfo_Impl *pCurrentInfo = weld::fromId(m_xTreeView->get_id(*xIter)); - if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION) + if (pCurrentInfo->getKind() == SfxCfgKind::GROUP_FUNCTION) { css::uno::Sequence< css::frame::DispatchInformation > lCommands; try @@ -882,14 +834,14 @@ void CuiConfigGroupListBox::GroupSelected() case SfxCfgKind::GROUP_SCRIPTCONTAINER: { - Reference< browse::XBrowseNode > rootNode( - static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; + const SfxScriptContainer_Data& rContainerData = + std::get(pInfo->aData); try { - if ( rootNode->hasChildNodes() ) + if ( rContainerData.xBrowseNode->hasChildNodes() ) { - const Sequence< Reference< browse::XBrowseNode > > children = - rootNode->getChildNodes(); + const std::vector< Reference< browse::XBrowseNode > > children = + comphelper::scriptbrowse::getSortedChildNodes(rContainerData.xBrowseNode); for ( const Reference< browse::XBrowseNode >& childNode : children ) { @@ -919,10 +871,13 @@ void CuiConfigGroupListBox::GroupSelected() // do nothing, the description will be empty } - OUString* pScriptURI = new OUString( uri ); - OUString aImage = GetImage(childNode, Reference< XComponentContext >(), false); - m_pFunctionListBox->aArr.push_back( std::make_unique( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI )); + m_pFunctionListBox->aArr.push_back( + std::make_unique( + SfxGroupInfo_Data( + SfxCfgKindAsIndex, uri, + rContainerData.xModel), + 0 )); m_pFunctionListBox->aArr.back()->sCommand = uri; m_pFunctionListBox->aArr.back()->sLabel = childNode->getName(); m_pFunctionListBox->aArr.back()->sHelpText = description; @@ -941,18 +896,24 @@ void CuiConfigGroupListBox::GroupSelected() case SfxCfgKind::GROUP_STYLES : { - SfxStyleInfo_Impl* pFamily = static_cast(pInfo->pObject); + SfxStyleInfo_Impl* pFamily + = std::get(pInfo->aData).get(); + if (pFamily) { const std::vector< SfxStyleInfo_Impl > lStyles = m_pStylesInfo->getStyles(pFamily->sFamily); for (auto const& lStyle : lStyles) { - SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(lStyle); - m_pFunctionListBox->aArr.push_back(std::make_unique(SfxCfgKind::GROUP_STYLES, 0, pStyle)); - m_pFunctionListBox->aArr.back()->sCommand = pStyle->sCommand; - m_pFunctionListBox->aArr.back()->sLabel = pStyle->sLabel; + auto pStyle = std::make_unique(lStyle); + m_pFunctionListBox->aArr.push_back( + std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex, + std::move(pStyle)), + 0)); + m_pFunctionListBox->aArr.back()->sCommand = lStyle.sCommand; + m_pFunctionListBox->aArr.back()->sLabel = lStyle.sLabel; OUString sId(weld::toId(m_pFunctionListBox->aArr.back().get())); - m_pFunctionListBox->append(sId, pStyle->sLabel); + m_pFunctionListBox->append(sId, lStyle.sLabel); } } break; @@ -968,9 +929,9 @@ void CuiConfigGroupListBox::GroupSelected() for (auto const& rDeck : aDecks) { const OUString sCommand = ".uno:SidebarDeck." + rDeck.msId; - m_pFunctionListBox->aArr.push_back(std::make_unique( - SfxCfgKind::GROUP_SIDEBARDECKS, 0, - nullptr)); + m_pFunctionListBox->aArr.push_back( + std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex), 0)); m_pFunctionListBox->aArr.back()->sCommand = sCommand; m_pFunctionListBox->aArr.back()->sLabel = rDeck.msId; m_pFunctionListBox->aArr.back()->sTooltip = @@ -984,7 +945,7 @@ void CuiConfigGroupListBox::GroupSelected() default: // Do nothing, the list box will stay empty - SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << static_cast(pInfo->nKind) ); + SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << pInfo->aData.index() ); break; } @@ -1000,15 +961,15 @@ void CuiConfigGroupListBox::GroupSelected() IMPL_LINK(CuiConfigGroupListBox, ExpandingHdl, const weld::TreeIter&, rIter, bool) { SfxGroupInfo_Impl *pInfo = weld::fromId(m_xTreeView->get_id(rIter)); - switch ( pInfo->nKind ) + switch ( pInfo->getKind() ) { case SfxCfgKind::GROUP_SCRIPTCONTAINER: { if (!m_xTreeView->iter_has_child(rIter)) { - Reference< browse::XBrowseNode > rootNode( - static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; - FillScriptList(rootNode, &rIter); + const SfxScriptContainer_Data& rContainerData = + std::get(pInfo->aData); + FillScriptList(rContainerData.xBrowseNode, rContainerData.xModel, &rIter); } break; } @@ -1020,10 +981,14 @@ IMPL_LINK(CuiConfigGroupListBox, ExpandingHdl, const weld::TreeIter&, rIter, boo const std::vector lStyleFamilies = m_pStylesInfo->getStyleFamilies(); for (auto const& lStyleFamily : lStyleFamilies) { - SfxStyleInfo_Impl* pFamily = new SfxStyleInfo_Impl(lStyleFamily); - aArr.push_back( std::make_unique( SfxCfgKind::GROUP_STYLES, 0, pFamily )); + auto pFamily = std::make_unique(lStyleFamily); + aArr.push_back( + std::make_unique( + SfxGroupInfo_Data(SfxCfgKindAsIndex, + std::move(pFamily)), + 0 )); OUString sId(weld::toId(aArr.back().get())); - m_xTreeView->insert(&rIter, -1, &pFamily->sLabel, &sId, nullptr, nullptr, false, nullptr); + m_xTreeView->insert(&rIter, -1, &lStyleFamily.sLabel, &sId, nullptr, nullptr, false, nullptr); } } break; @@ -1301,9 +1266,9 @@ SvxScriptSelectorDialog::GetScriptURL() const if (std::unique_ptr xIter = m_xCommands->get_selected()) { SfxGroupInfo_Impl *pData = weld::fromId(m_xCommands->get_id(*xIter)); - if ( ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) - || ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) - || ( pData->nKind == SfxCfgKind::GROUP_STYLES ) + if ( ( pData->getKind() == SfxCfgKind::FUNCTION_SLOT ) + || ( pData->getKind() == SfxCfgKind::FUNCTION_SCRIPT ) + || ( pData->getKind() == SfxCfgKind::GROUP_STYLES ) ) { result = pData->sCommand; @@ -1313,6 +1278,31 @@ SvxScriptSelectorDialog::GetScriptURL() const return result; } +css::uno::Reference +SvxScriptSelectorDialog::GetScriptModel() const +{ + Reference xModel; + + if (std::unique_ptr xIter = m_xCommands->get_selected()) + { + SfxGroupInfo_Impl *pData = weld::fromId(m_xCommands->get_id(*xIter)); + + switch (pData->getKind()) + { + case SfxCfgKind::FUNCTION_SCRIPT: + xModel = std::get(pData->aData).xModel; + break; + case SfxCfgKind::GROUP_SCRIPTCONTAINER: + xModel = std::get(pData->aData).xModel; + break; + default: + break; + } + } + + return xModel; +} + void SvxScriptSelectorDialog::SaveLastUsedMacro() { @@ -1380,12 +1370,16 @@ SvxScriptSelectorDialog::LoadLastUsedMacro() xCategories.expand_row(*xIter); nOpenedNodes++; } - if (xCategories.iter_has_child(*xIter)) + if (nOpenedNodes < nInfoParts - 1) + { + if (!xCategories.iter_has_child(*xIter)) + { + // If the number of levels in the tree is smaller than the number of parts in the + // macro info string, then return + return; + } (void)xCategories.iter_children(*xIter); - else if (nOpenedNodes < nInfoParts - 1) - // If the number of levels in the tree is smaller than the - // number of parts in the macro info string, then return - return; + } } xCategories.select(*xIter); xCategories.scroll_to_row(*xIter); diff --git a/cui/source/customize/eventdlg.hxx b/cui/source/customize/eventdlg.hxx index f3c93bd9eac8..75b2248c6f3d 100644 --- a/cui/source/customize/eventdlg.hxx +++ b/cui/source/customize/eventdlg.hxx @@ -19,7 +19,8 @@ #pragma once #include -#include +#include + #include #include diff --git a/cui/source/customize/macropg_impl.hxx b/cui/source/customize/macropg_impl.hxx index 3252ee7d95c2..6a0532f80d08 100644 --- a/cui/source/customize/macropg_impl.hxx +++ b/cui/source/customize/macropg_impl.hxx @@ -20,10 +20,11 @@ #pragma once #include +#include #include #include #include -#include +#include class SvxMacroTabPage_Impl { diff --git a/cui/source/dialogs/AdditionsDialog.cxx b/cui/source/dialogs/AdditionsDialog.cxx index d6ba045dd57f..78ad37b48249 100644 --- a/cui/source/dialogs/AdditionsDialog.cxx +++ b/cui/source/dialogs/AdditionsDialog.cxx @@ -719,7 +719,7 @@ bool AdditionsItem::getExtensionFile(OUString& sExtensionFile) IMPL_LINK_NOARG(AdditionsDialog, ImplUpdateDataHdl, Timer*, void) { RefreshUI(); } -IMPL_LINK_NOARG(AdditionsDialog, SearchUpdateHdl, weld::Entry&, void) +IMPL_LINK_NOARG(AdditionsDialog, SearchUpdateHdl, weld::TextWidget&, void) { m_aSearchDataTimer.Start(); } diff --git a/cui/source/dialogs/MacroManagerDialog.cxx b/cui/source/dialogs/MacroManagerDialog.cxx index bdc4ca25ff0e..2c78713c48bb 100644 --- a/cui/source/dialogs/MacroManagerDialog.cxx +++ b/cui/source/dialogs/MacroManagerDialog.cxx @@ -14,15 +14,19 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -34,8 +38,9 @@ #include #include #include +#include #include -#include +#include #include #include #include @@ -43,6 +48,8 @@ #include #include #include +#include +#include #include #include @@ -51,10 +58,10 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -220,6 +227,7 @@ void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) weld::WaitObject aWait(m_pMacroManagerDialog->getDialog()); css::uno::Reference xNode; + css::uno::Reference xParentDocumentModel; if (pEntryIter == nullptr) { ClearAll(); @@ -245,6 +253,7 @@ void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) = weld::fromId(m_xTreeView->get_id(*pEntryIter)); xNode.set(pScriptContainerInfoEntry->pBrowseNode); + xParentDocumentModel.set(pScriptContainerInfoEntry->xModel); Remove(pEntryIter, /*bRemoveEntryIter*/ false); } @@ -282,8 +291,12 @@ void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) currentDocTitle = comphelper::DocumentInfo::getDocumentTitle(xModel); } - const css::uno::Sequence> children - = xNode->getChildNodes(); + std::vector> children + = comphelper::scriptbrowse::getChildNodes(xNode); + + if (!bIsRootNode) + comphelper::scriptbrowse::sortNodes(children); + for (css::uno::Reference const& theChild : children) { if (!theChild.is()) @@ -296,6 +309,7 @@ void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) continue; OUString uiName = theChild->getName(); + css::uno::Reference xDocumentModel; if (bIsRootNode) { if (uiName == user) @@ -314,6 +328,14 @@ void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) // containers. continue; } + else + { + xDocumentModel = getDocumentModel(m_xContext, uiName); + } + } + else + { + xDocumentModel = xParentDocumentModel; } // We call acquire on the XBrowseNode so that it does not @@ -324,8 +346,8 @@ void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) if (theChild->hasChildNodes()) { - const css::uno::Sequence> - grandchildren = theChild->getChildNodes(); + const std::vector> + grandchildren = comphelper::scriptbrowse::getChildNodes(theChild); for (const auto& rxNode : grandchildren) { if (!rxNode.is()) @@ -339,7 +361,7 @@ void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) } OUString aImage = CuiConfigGroupListBox::GetImage(theChild, m_xContext, bIsRootNode); - Insert(theChild, pEntryIter, uiName, aImage, bChildOnDemand); + Insert(theChild, xDocumentModel, pEntryIter, uiName, aImage, bChildOnDemand); } } @@ -376,7 +398,8 @@ void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) for (const OUString& rDlgName : aDocument.getObjectNames(basctl::E_DIALOGS, aLibName)) { - Insert(nullptr, pEntryIter, rDlgName, RID_CUIBMP_DIALOG, false); + Insert(nullptr, xParentDocumentModel, pEntryIter, rDlgName, RID_CUIBMP_DIALOG, + false); } } } @@ -384,12 +407,13 @@ void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) void ScriptContainersListBox::Insert( const css::uno::Reference& xInsertNode, - const weld::TreeIter* pIter, const OUString& rsUiName, const OUString& rsImage, - bool bChildOnDemand, int nPos, weld::TreeIter* pRet) + const css::uno::Reference& xDocumentModel, const weld::TreeIter* pIter, + const OUString& rsUiName, const OUString& rsImage, bool bChildOnDemand, int nPos, + weld::TreeIter* pRet) { std::unique_ptr xNewEntryIter = m_xTreeView->make_iterator(); - OUString sId(weld::toId(new ScriptContainerInfo(xInsertNode.get()))); + OUString sId(weld::toId(new ScriptContainerInfo(xInsertNode.get(), xDocumentModel))); m_xTreeView->insert(pIter, nPos, &rsUiName, &sId, nullptr, nullptr, bChildOnDemand, xNewEntryIter.get()); m_xTreeView->set_image(*xNewEntryIter, rsImage); @@ -456,8 +480,8 @@ void ScriptContainersListBox::ScriptContainerSelected() { if (xBrowseNode->hasChildNodes()) { - const css::uno::Sequence> - children = xBrowseNode->getChildNodes(); + const std::vector> children + = comphelper::scriptbrowse::getSortedChildNodes(xBrowseNode); for (const css::uno::Reference& childNode : children) @@ -498,8 +522,8 @@ void ScriptContainersListBox::ScriptContainerSelected() childNode->acquire(); - m_pScriptsListBox->aArr.push_back( - std::make_unique(childNode.get(), sURI, sDescription)); + m_pScriptsListBox->aArr.push_back(std::make_unique( + childNode.get(), sURI, sDescription, pScriptContainerInfo->xModel)); OUString sId(weld::toId(m_pScriptsListBox->aArr.back().get())); m_pScriptsListBox->append(sId, childNode->getName(), RID_CUIBMP_MACRO); @@ -656,6 +680,8 @@ MacroManagerDialog::MacroManagerDialog(weld::Window* pParent, , m_xMacroDeleteButton(m_xBuilder->weld_button(u"macrodelete"_ustr)) , m_xMacroCreateButton(m_xBuilder->weld_button(u"macrocreate"_ustr)) , m_xMacroRenameButton(m_xBuilder->weld_button(u"macrorename"_ustr)) + , m_xModuleCopyButton(m_xBuilder->weld_button(u"modulecopy"_ustr)) + , m_xModulePasteButton(m_xBuilder->weld_button(u"modulepaste"_ustr)) , m_xAssignButton(m_xBuilder->weld_button(u"assign"_ustr)) { m_aScriptsListBoxLabelBaseStr = m_xScriptsListBoxLabel->get_label(); @@ -686,6 +712,8 @@ MacroManagerDialog::MacroManagerDialog(weld::Window* pParent, m_xMacroEditButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xMacroRenameButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xMacroDeleteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xModuleCopyButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xModulePasteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); StartListening(*SfxGetpApp()); } @@ -903,23 +931,6 @@ IMPL_LINK(MacroManagerDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool) return true; } -// same as OUString SvxScriptOrgDialog::getBoolProperty((Reference const& xProps, OUString const& propName) -// cui/source/dialogs/scriptdlg.cxx -bool MacroManagerDialog::getBoolProperty( - css::uno::Reference const& xProps, OUString const& propName) -{ - bool result = false; - try - { - xProps->getPropertyValue(propName) >>= result; - } - catch (css::uno::Exception&) - { - return result; - } - return result; -} - css::uno::Reference MacroManagerDialog::getBrowseNode(const weld::TreeView& rTreeView, const weld::TreeIter& rTreeIter) { @@ -989,6 +1000,8 @@ void MacroManagerDialog::CheckButtons() bool bSensitiveLibraryPasswordButton = false; bool bSensitiveLibraryImportButton = false; bool bSensitiveLibraryExportButton = false; + bool bSensitiveModuleCopyButton = false; + bool bSensitiveModulePasteButton = false; bool bSensitiveMacroRunButton = false; bool bSensitiveMacroCreateButton = false; @@ -1032,14 +1045,9 @@ void MacroManagerDialog::CheckButtons() rScriptContainersTreeView, *xScriptContainersSelectedIter); if (node.is()) { - css::uno::Reference xProps( - node, css::uno::UNO_QUERY); - if (xProps.is()) + if (comphelper::scriptbrowse::isCreatable(node)) { - if (getBoolProperty(xProps, "Creatable")) - { - bSensitiveNewLibraryButton = true; - } + bSensitiveNewLibraryButton = true; } } } @@ -1122,34 +1130,43 @@ void MacroManagerDialog::CheckButtons() } } - if (!bSharedLocationContainer && nSelectedIterDepth > 1) + if (!bSharedLocationContainer) { css::uno::Reference node = getBrowseNode(rScriptContainersTreeView, *xScriptContainersSelectedIter); if (node.is()) { - css::uno::Reference xProps(node, css::uno::UNO_QUERY); - if (xProps.is()) + if (nSelectedIterDepth > 1) { - if (getBoolProperty(xProps, "Creatable") + if (comphelper::scriptbrowse::isCreatable(node) && rScriptContainersTreeView.get_iter_depth( *xScriptContainersSelectedIter) == 2) // library entry { bSensitiveMacroCreateButton = true; } - if (getBoolProperty(xProps, "Editable")) + if (comphelper::scriptbrowse::isEditable(node)) { bSensitiveLibraryModuleDialogEditButton = true; } - if (getBoolProperty(xProps, "Deletable")) + if (comphelper::scriptbrowse::isDeletable(node)) { bSensitiveLibraryModuleDialogDeleteButton = true; } - if (getBoolProperty(xProps, "Renamable")) + if (comphelper::scriptbrowse::isRenamable(node)) { bSensitiveLibraryModuleDialogRenameButton = true; } + + css::uno::Reference xCopyableNode( + node, css::uno::UNO_QUERY); + if (xCopyableNode.is() && xCopyableNode->isCopyableNode()) + bSensitiveModuleCopyButton = true; + } + + if (m_xCopiedNode.is() && m_xCopiedNode->nodeCanBeCopiedTo(node)) + { + bSensitiveModulePasteButton = true; } } } @@ -1161,29 +1178,28 @@ void MacroManagerDialog::CheckButtons() { bSensitiveAssignButton = true; + if (bBasic) + bSensitiveMacroDeleteButton = true; + css::uno::Reference node; node = getBrowseNode(rScriptsTreeView, *xScriptsSelectedIter); if (node.is()) { bSensitiveMacroRunButton = true; - css::uno::Reference xProps(node, css::uno::UNO_QUERY); - if (xProps.is()) + if (comphelper::scriptbrowse::isEditable(node)) { - if (getBoolProperty(xProps, "Editable")) + bSensitiveMacroEditButton = true; + } + if (!bSharedLocationContainer) + { + if (comphelper::scriptbrowse::isDeletable(node)) { - bSensitiveMacroEditButton = true; + bSensitiveMacroDeleteButton = true; } - if (!bSharedLocationContainer) + if (comphelper::scriptbrowse::isRenamable(node)) { - if (getBoolProperty(xProps, "Deletable")) - { - bSensitiveMacroDeleteButton = true; - } - if (getBoolProperty(xProps, "Renamable")) - { - bSensitiveMacroRenameButton = true; - } + bSensitiveMacroRenameButton = true; } } } @@ -1205,6 +1221,8 @@ void MacroManagerDialog::CheckButtons() m_xMacroEditButton->set_sensitive(bSensitiveMacroEditButton); m_xMacroRenameButton->set_sensitive(bSensitiveMacroRenameButton); m_xMacroDeleteButton->set_sensitive(bSensitiveMacroDeleteButton); + m_xModuleCopyButton->set_sensitive(bSensitiveModuleCopyButton); + m_xModulePasteButton->set_sensitive(bSensitiveModulePasteButton); m_xAssignButton->set_sensitive(bSensitiveAssignButton); } @@ -1557,9 +1575,7 @@ IMPL_LINK(MacroManagerDialog, ClickHdl, weld::Button&, rButton, void) } else if (&rButton == m_xMacroDeleteButton.get()) { - // todo - // see: void MacroChooser::DeleteMacro() - return; + BasicScriptsMacroDelete(); } else if (&rButton == m_xAssignButton.get()) { @@ -1604,21 +1620,17 @@ IMPL_LINK(MacroManagerDialog, ClickHdl, weld::Button&, rButton, void) return; // should never happen css::uno::Reference node = getBrowseNode(rTreeView, *xSelectedIter); - css::uno::Reference xInv(node, css::uno::UNO_QUERY); - if (xInv.is()) + if (node.is()) { m_xDialog->response(RET_CANCEL); - css::uno::Sequence args(0); - css::uno::Sequence outArgs(0); - css::uno::Sequence outIndex; try { // ISSUE need code to run script here - xInv->invoke(u"Editable"_ustr, args, outIndex, outArgs); + comphelper::scriptbrowse::editNode(node); } catch (css::uno::Exception const&) { - TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to invoke"); + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to edit"); } } } @@ -1671,6 +1683,26 @@ IMPL_LINK(MacroManagerDialog, ClickHdl, weld::Button&, rButton, void) aRequest.AppendItem(aMacroInfoItem); SfxGetpApp()->ExecuteSlot(aRequest); } + else if (&rButton == m_xModuleCopyButton.get()) + { + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.get_selected(); + if (!xSelectedIter) + return; // should never happen + m_xCopiedNode.set(getBrowseNode(rTreeView, *xSelectedIter), css::uno::UNO_QUERY); + CheckButtons(); + } + else if (&rButton == m_xModulePasteButton.get()) + { + if (!m_xCopiedNode.is()) + return; + + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.get_selected(); + if (!xSelectedIter) + return; // should never happen + ScriptingFrameworkScriptsPasteEntry(rTreeView, *xSelectedIter); + } } bool MacroManagerDialog::IsLibraryReadOnlyOrFailedPasswordQuery( @@ -2031,6 +2063,27 @@ void MacroManagerDialog::BasicScriptsMacroEdit(const basctl::ScriptDocument& rDo m_xDialog->response(0); } +void MacroManagerDialog::BasicScriptsMacroDelete() +{ + SbMethod* pMethod = GetSelectedBasicMethod(); + + DBG_ASSERT(pMethod, "BasicScriptsMacroDelete: no macro found!"); + + if (!pMethod || !basctl::QueryDelMacro(pMethod->GetName(), m_xDialog.get())) + return; + + // Remove the macro from the list. We need to do this before calling DeleteMacro because that + // can trigger a notification which will cause the list of macros to be reloaded so if we do it + // after we’ll delete the wrong node. + if (std::unique_ptr xScriptsEntryIter + = m_xScriptsListBox->get_widget().get_selected()) + { + m_xScriptsListBox->Remove(*xScriptsEntryIter); + } + + basctl::DeleteMacro(*pMethod); +} + // modified version of void SvxScriptOrgDialog::renameEntry(const weld::TreeIter& rEntry) // cui/source/dialogs/scriptdlg.cxx void MacroManagerDialog::ScriptingFrameworkScriptsRenameEntry(weld::TreeView& rTreeView, @@ -2038,9 +2091,8 @@ void MacroManagerDialog::ScriptingFrameworkScriptsRenameEntry(weld::TreeView& rT { css::uno::Reference xBrowseNode = getBrowseNode(rTreeView, rEntry); - css::uno::Reference xInv(xBrowseNode, css::uno::UNO_QUERY); - if (xInv.is()) + if (xBrowseNode.is()) { OUString aNewName = xBrowseNode->getName(); sal_Int32 extnPos = aNewName.lastIndexOf('.'); @@ -2071,17 +2123,14 @@ void MacroManagerDialog::ScriptingFrameworkScriptsRenameEntry(weld::TreeView& rT aNewName = aNameDialog.GetName(); - css::uno::Sequence args{ css::uno::Any(aNewName) }; - css::uno::Sequence outArgs; - css::uno::Sequence outIndex; try { - css::uno::Any aResult = xInv->invoke(u"Renamable"_ustr, args, outIndex, outArgs); - xBrowseNode.set(aResult, css::uno::UNO_QUERY); + xBrowseNode = comphelper::scriptbrowse::renameNode(xBrowseNode, aNewName); } catch (css::uno::Exception const&) { TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Rename"); + xBrowseNode.clear(); } } if (xBrowseNode.is()) @@ -2127,6 +2176,50 @@ void MacroManagerDialog::ScriptingFrameworkScriptsRenameEntry(weld::TreeView& rT } } +void MacroManagerDialog::ScriptingFrameworkScriptsPasteEntry(weld::TreeView& rTreeView, + const weld::TreeIter& rEntry) +{ + css::uno::Reference node = getBrowseNode(rTreeView, rEntry); + if (!node.is() || !m_xCopiedNode->nodeCanBeCopiedTo(node)) + return; + + try + { + node = m_xCopiedNode->copyNode(node); + } + catch (const css::uno::Exception&) + { + return; + } + + // If we don’t expand the row before filling it then it will end up with two copies of all the + // entries + rTreeView.expand_row(rEntry); + m_xScriptContainersListBox->Fill(&rEntry); + // Filling it causes the node to close so we need to expand it again + rTreeView.expand_row(rEntry); + + // Try to select the new entry + if (rTreeView.iter_has_child(rEntry)) + { + OUString sNodeName = node->getName(); + + std::unique_ptr xIter = rTreeView.make_iterator(&rEntry); + if (rTreeView.iter_children(*xIter)) + { + do + { + if (rTreeView.get_text(*xIter) == sNodeName) + { + rTreeView.select(*xIter); + SelectHdl(rTreeView); + break; + } + } while (rTreeView.iter_next_sibling(*xIter)); + } + } +} + // for Scripting Framework entries // duplicate of OUString SvxScriptOrgDialog::getListOfChildren // cui/source/dialogs/scriptdlg.cxx @@ -2144,8 +2237,8 @@ OUString MacroManagerDialog::getListOfChildren( { if (node->hasChildNodes()) { - const css::uno::Sequence> children - = node->getChildNodes(); + const std::vector> children + = comphelper::scriptbrowse::getSortedChildNodes(node); for (const css::uno::Reference& n : children) { result.append(getListOfChildren(n, depth + 1)); @@ -2177,16 +2270,12 @@ void MacroManagerDialog::ScriptingFrameworkScriptsDeleteEntry(weld::TreeView& rT return; } - css::uno::Reference xInv(node, css::uno::UNO_QUERY); - if (xInv.is()) + if (node.is()) { - css::uno::Sequence args(0); - css::uno::Sequence outArgs(0); - css::uno::Sequence outIndex; try { - css::uno::Any aResult = xInv->invoke(u"Deletable"_ustr, args, outIndex, outArgs); - aResult >>= result; // or do we just assume true if no exception ? + result = comphelper::scriptbrowse::deleteNode(node); + // or do we just assume true if no exception ? } catch (css::uno::Exception const&) { @@ -2229,10 +2318,8 @@ void MacroManagerDialog::ScriptingFrameworkScriptsCreateEntry(InputDialogMode eI css::uno::Reference aChildNode; css::uno::Reference xBrowseNode = getBrowseNode(rTreeView, *xSelectedIter); - css::uno::Reference xInv(xBrowseNode, css::uno::UNO_QUERY); - // Currently, invocation is not implemented for python, only beanshell, javascript, and java. - if (xInv.is()) + if (xBrowseNode.is()) { OUString aNewName; OUString aNewStdName; @@ -2248,7 +2335,7 @@ void MacroManagerDialog::ScriptingFrameworkScriptsCreateEntry(InputDialogMode eI bool bValid = false; sal_Int32 i = 1; - css::uno::Sequence> childNodes; + std::vector> childNodes; // no children => ok to create Parcel1 or Script1 without checking ? try { @@ -2259,7 +2346,7 @@ void MacroManagerDialog::ScriptingFrameworkScriptsCreateEntry(InputDialogMode eI } else { - childNodes = xBrowseNode->getChildNodes(); + childNodes = comphelper::scriptbrowse::getChildNodes(xBrowseNode); } } catch (css::uno::Exception&) @@ -2272,7 +2359,7 @@ void MacroManagerDialog::ScriptingFrameworkScriptsCreateEntry(InputDialogMode eI { aNewName = aNewStdName + OUString::number(i); bool bFound = false; - if (childNodes.hasElements()) + if (!childNodes.empty()) { OUString nodeName = childNodes[0]->getName(); sal_Int32 extnPos = nodeName.lastIndexOf('.'); @@ -2353,13 +2440,9 @@ void MacroManagerDialog::ScriptingFrameworkScriptsCreateEntry(InputDialogMode eI // open up parent node (which ensures it's loaded) rTreeView.expand_row(*xSelectedIter); - css::uno::Sequence args{ css::uno::Any(aNewName) }; - css::uno::Sequence outArgs; - css::uno::Sequence outIndex; try { - css::uno::Any aResult = xInv->invoke(u"Creatable"_ustr, args, outIndex, outArgs); - aChildNode.set(aResult, css::uno::UNO_QUERY); + aChildNode = comphelper::scriptbrowse::createNode(xBrowseNode, aNewName); } catch (css::uno::Exception const&) { @@ -2405,6 +2488,20 @@ OUString MacroManagerDialog::GetScriptURL() const return result; } +css::uno::Reference MacroManagerDialog::GetScriptModel() const +{ + css::uno::Reference xModel; + + if (std::unique_ptr xIter = m_xScriptsListBox->get_selected()) + { + ScriptInfo* pScriptInfo = weld::fromId(m_xScriptsListBox->get_id(*xIter)); + if (pScriptInfo) + xModel = pScriptInfo->xModel; + } + + return xModel; +} + constexpr OUString MACRO_MANAGER_CONFIGNAME = u"MacroManagerDialog"_ustr; constexpr OUString LAST_RUN_MACRO_INFO = u"LastRunMacro"_ustr; @@ -2511,4 +2608,56 @@ void MacroManagerDialog::LoadLastUsedMacro() UpdateUI(); } +SbModule* MacroManagerDialog::GetSelectedBasicModule() const +{ + weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xIter = rScriptContainersTreeView.get_selected(); + + if (!xIter) + return nullptr; + + OUString aParts[3]; + + // The selected node needs to be at least 4 branches deep, ie, + // Document->Language->Library->Module. Here we store the names of the last three and also check + // that the language part has a parent node. + for (auto& aPart : aParts) + { + aPart = rScriptContainersTreeView.get_text(*xIter); + + if (!rScriptContainersTreeView.iter_parent(*xIter)) + return nullptr; + } + + if (aParts[2] != u"Basic"_ustr) + return nullptr; + + basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument(xIter.get()); + BasicManager* pBasicManager = aDocument.getBasicManager(); + + if (!pBasicManager) + return nullptr; + + StarBASIC* pLibrary = pBasicManager->GetLib(aParts[1]); + if (!pLibrary) + return nullptr; + + return pLibrary->FindModule(aParts[0]); +} + +SbMethod* MacroManagerDialog::GetSelectedBasicMethod() const +{ + SbModule* pModule = GetSelectedBasicModule(); + + if (!pModule) + return nullptr; + + OUString sScriptName = m_xScriptsListBox->GetSelectedScriptName(); + + if (sScriptName.getLength() <= 0) + return nullptr; + + return pModule->FindMethod(sScriptName, SbxClassType::Method); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/dialogs/SignSignatureLineDialog.cxx b/cui/source/dialogs/SignSignatureLineDialog.cxx index 36fcd169bc74..531b1e9632a8 100644 --- a/cui/source/dialogs/SignSignatureLineDialog.cxx +++ b/cui/source/dialogs/SignSignatureLineDialog.cxx @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -172,7 +171,10 @@ IMPL_LINK_NOARG(SignSignatureLineDialog, chooseCertificate, weld::Button&, void) ValidateFields(); } -IMPL_LINK_NOARG(SignSignatureLineDialog, entryChanged, weld::Entry&, void) { ValidateFields(); } +IMPL_LINK_NOARG(SignSignatureLineDialog, entryChanged, weld::TextWidget&, void) +{ + ValidateFields(); +} void SignSignatureLineDialog::ValidateFields() { diff --git a/cui/source/dialogs/SignatureLineDialog.cxx b/cui/source/dialogs/SignatureLineDialog.cxx index de97f393a9b8..eb55aedbfa91 100644 --- a/cui/source/dialogs/SignatureLineDialog.cxx +++ b/cui/source/dialogs/SignatureLineDialog.cxx @@ -12,7 +12,6 @@ #include #include #include -#include #include #include diff --git a/cui/source/dialogs/SignatureLineDialogBase.cxx b/cui/source/dialogs/SignatureLineDialogBase.cxx index 52b05d4d84d5..1d9259e84582 100644 --- a/cui/source/dialogs/SignatureLineDialogBase.cxx +++ b/cui/source/dialogs/SignatureLineDialogBase.cxx @@ -11,8 +11,6 @@ #include -#include - using namespace css; using namespace css::uno; using namespace css::frame; diff --git a/cui/source/dialogs/SpellDialog.cxx b/cui/source/dialogs/SpellDialog.cxx index 70bfd5da95f9..20baa289dfc3 100644 --- a/cui/source/dialogs/SpellDialog.cxx +++ b/cui/source/dialogs/SpellDialog.cxx @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -499,7 +498,7 @@ IMPL_LINK_NOARG(SpellDialog, CheckGrammarHdl, weld::Toggleable&, void) void SpellDialog::StartSpellOptDlg_Impl() { - auto xSet = std::make_shared>( SfxGetpApp()->GetPool() ); + auto xSet = std::make_shared(SfxItemSet::makeFixedSfxItemSet( SfxGetpApp()->GetPool() )); m_xOptionsDlg = std::make_shared( m_xDialog.get(), xSet.get(), "content", "cui/ui/spelloptionsdialog.ui", "SpellOptionsDialog"); @@ -2143,7 +2142,7 @@ svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions() const aPortion1.eLanguage = eLang; aPortion1.sText = m_xEditEngine->GetText(ESelection(0, nStart, 0, aStart->nPosition)); - bool bIsIgnoreError = m_aIgnoreErrorsAt.find( nStart ) != m_aIgnoreErrorsAt.end(); + bool bIsIgnoreError = m_aIgnoreErrorsAt.contains( nStart ); if( bIsIgnoreError ) { aPortion1.bIgnoreThisError = true; diff --git a/cui/source/dialogs/about.cxx b/cui/source/dialogs/about.cxx index 30f22aac3fcc..e6e0b7f1be12 100644 --- a/cui/source/dialogs/about.cxx +++ b/cui/source/dialogs/about.cxx @@ -32,7 +32,6 @@ #include //GetSettings #include //Application:: #include -#include #include //Translate #include //EXTRA_BUILDID @@ -166,9 +165,6 @@ OUString AboutDialog::GetVersionString() #endif return version; - - - } OUString AboutDialog::GetBuildString() diff --git a/cui/source/dialogs/cuifmsearch.cxx b/cui/source/dialogs/cuifmsearch.cxx index 56a114a5e556..eb910f4c9f99 100644 --- a/cui/source/dialogs/cuifmsearch.cxx +++ b/cui/source/dialogs/cuifmsearch.cxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/cui/source/dialogs/cuigaldlg.cxx b/cui/source/dialogs/cuigaldlg.cxx index ac0bf791a1c2..393fafad1bff 100644 --- a/cui/source/dialogs/cuigaldlg.cxx +++ b/cui/source/dialogs/cuigaldlg.cxx @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/cui/source/dialogs/hangulhanjadlg.cxx b/cui/source/dialogs/hangulhanjadlg.cxx index a1760aa67656..e5fe8eac192a 100644 --- a/cui/source/dialogs/hangulhanjadlg.cxx +++ b/cui/source/dialogs/hangulhanjadlg.cxx @@ -28,9 +28,13 @@ #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include @@ -45,1455 +49,1467 @@ #include #define HHC editeng::HangulHanjaConversion -#define LINE_CNT static_cast< sal_uInt16 >(2) #define MAXNUM_SUGGESTIONS 50 - namespace svx { +using namespace ::com::sun::star; +using namespace css::uno; +using namespace css::linguistic2; +using namespace css::lang; +using namespace css::container; - using namespace ::com::sun::star; - using namespace css::uno; - using namespace css::linguistic2; - using namespace css::lang; - using namespace css::container; +namespace +{ +class FontSwitch +{ +private: + OutputDevice& m_rDev; - - namespace +public: + FontSwitch(OutputDevice& _rDev, const vcl::Font& _rTemporaryFont) + : m_rDev(_rDev) { - class FontSwitch - { - private: - OutputDevice& m_rDev; + m_rDev.Push(vcl::PushFlags::FONT); + m_rDev.SetFont(_rTemporaryFont); + } + ~FontSwitch() { suppress_fun_call_w_exception(m_rDev.Pop()); } +}; - public: - FontSwitch( OutputDevice& _rDev, const vcl::Font& _rTemporaryFont ) - :m_rDev( _rDev ) - { - m_rDev.Push( vcl::PushFlags::FONT ); - m_rDev.SetFont( _rTemporaryFont ); - } - ~FontSwitch() - { - suppress_fun_call_w_exception(m_rDev.Pop()); - } - }; - - /** a class which allows to draw two texts in a pseudo-ruby way (which basically +/** a class which allows to draw two texts in a pseudo-ruby way (which basically means one text above or below the other, and a little bit smaller) */ - class PseudoRubyText +class PseudoRubyText +{ +public: + enum RubyPosition { - public: - enum RubyPosition - { - eAbove, eBelow - }; - - protected: - OUString m_sPrimaryText; - OUString m_sSecondaryText; - RubyPosition m_ePosition; - - public: - PseudoRubyText(); - void init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition ); - const OUString& getPrimaryText() const { return m_sPrimaryText; } - const OUString& getSecondaryText() const { return m_sSecondaryText; } - - public: - void Paint( vcl::RenderContext& _rDevice, const ::tools::Rectangle& _rRect, - ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation ); + eAbove, + eBelow }; - } - - PseudoRubyText::PseudoRubyText() - : m_ePosition(eAbove) - { - } - - void PseudoRubyText::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition ) - { - m_sPrimaryText = rPrimaryText; - m_sSecondaryText = rSecondaryText; - m_ePosition = rPosition; - } - - - void PseudoRubyText::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& _rRect, - ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation ) - { - // calculate the text flags for the painting - constexpr DrawTextFlags nTextStyle = DrawTextFlags::Mnemonic | - DrawTextFlags::Left | - DrawTextFlags::VCenter; - - Size aPlaygroundSize(_rRect.GetSize()); - - // the font for the secondary text: - vcl::Font aSmallerFont(rRenderContext.GetFont()); - // heuristic: 80% of the original size - aSmallerFont.SetFontHeight( static_cast( 0.8 * aSmallerFont.GetFontHeight() ) ); - - // let's calculate the size of our two texts - ::tools::Rectangle aPrimaryRect = rRenderContext.GetTextRect( _rRect, m_sPrimaryText, nTextStyle ); - ::tools::Rectangle aSecondaryRect; - { - FontSwitch aFontRestore(rRenderContext, aSmallerFont); - aSecondaryRect = rRenderContext.GetTextRect(_rRect, m_sSecondaryText, nTextStyle); - } - - // position these rectangles properly - // x-axis: - sal_Int32 nCombinedWidth = std::max( aSecondaryRect.GetWidth(), aPrimaryRect.GetWidth() ); - // the rectangle where both texts will reside is as high as possible, and as wide as the - // widest of both text rects - aPrimaryRect.SetLeft( _rRect.Left() ); - aSecondaryRect.SetLeft( aPrimaryRect.Left() ); - aPrimaryRect.SetRight( _rRect.Left() + nCombinedWidth ); - aSecondaryRect.SetRight( aPrimaryRect.Right() ); - - // y-axis: - sal_Int32 nCombinedHeight = aPrimaryRect.GetHeight() + aSecondaryRect.GetHeight(); - // align to the top, for the moment - aPrimaryRect.Move( 0, _rRect.Top() - aPrimaryRect.Top() ); - aSecondaryRect.Move( 0, aPrimaryRect.Top() + aPrimaryRect.GetHeight() - aSecondaryRect.Top() ); - // move the rects to the bottom - aPrimaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 ); - aSecondaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 ); - - // 'til here, everything we did assumes that the secondary text is painted _below_ the primary - // text. If this isn't the case, we need to correct the rectangles - if (eAbove == m_ePosition) - { - sal_Int32 nVertDistance = aSecondaryRect.Top() - aPrimaryRect.Top(); - aSecondaryRect.Move( 0, -nVertDistance ); - aPrimaryRect.Move( 0, nCombinedHeight - nVertDistance ); - } - - // now draw the texts - // as we already calculated the precise rectangles for the texts, we don't want to - // use the alignment flags given - within its rect, every text is centered - DrawTextFlags nDrawTextStyle( nTextStyle ); - nDrawTextStyle &= ~DrawTextFlags( DrawTextFlags::Right | DrawTextFlags::Left | DrawTextFlags::Bottom | DrawTextFlags::Top ); - nDrawTextStyle |= DrawTextFlags::Center | DrawTextFlags::VCenter; - - rRenderContext.DrawText( aPrimaryRect, m_sPrimaryText, nDrawTextStyle ); - { - FontSwitch aFontRestore(rRenderContext, aSmallerFont); - rRenderContext.DrawText( aSecondaryRect, m_sSecondaryText, nDrawTextStyle ); - } - - // outta here - if (_pPrimaryLocation) - *_pPrimaryLocation = aPrimaryRect; - if (_pSecondaryLocation) - *_pSecondaryLocation = aSecondaryRect; - } - - class RubyRadioButton - { - public: - RubyRadioButton(std::unique_ptr xControl, std::unique_ptr xImage); - void init(const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition); - - void set_sensitive(bool sensitive) - { - m_xControl->set_sensitive(sensitive); - m_xImage->set_sensitive(sensitive); - } - void set_active(bool active) { m_xControl->set_active(active); } - bool get_active() const { return m_xControl->get_active(); } - - void connect_toggled(const Link& rLink) { m_xControl->connect_toggled(rLink); } - - private: - Size GetOptimalSize() const; - void Paint(vcl::RenderContext& rRenderContext); - - ScopedVclPtr m_xVirDev; - std::unique_ptr m_xControl; - std::unique_ptr m_xImage; - PseudoRubyText m_aRubyText; - }; - - RubyRadioButton::RubyRadioButton(std::unique_ptr xControl, std::unique_ptr xImage) - : m_xVirDev(xControl->create_virtual_device()) - , m_xControl(std::move(xControl)) - , m_xImage(std::move(xImage)) - { - // expand the point size of the desired font to the equivalent pixel size - weld::SetPointFont(*m_xVirDev, m_xControl->get_font()); - } - - void RubyRadioButton::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition ) - { - m_aRubyText.init(rPrimaryText, rSecondaryText, rPosition); - - m_xVirDev->SetOutputSizePixel(GetOptimalSize()); - - Paint(*m_xVirDev); - - m_xImage->set_image(m_xVirDev.get()); - } - - void RubyRadioButton::Paint(vcl::RenderContext& rRenderContext) - { - ::tools::Rectangle aOverallRect(Point(0, 0), rRenderContext.GetOutputSizePixel()); - // inflate the rect a little bit (because the VCL radio button does the same) - ::tools::Rectangle aTextRect( aOverallRect ); - aTextRect.AdjustLeft( 1 ); aTextRect.AdjustRight( -1 ); - aTextRect.AdjustTop( 1 ); aTextRect.AdjustBottom( -1 ); - - // paint the ruby text - ::tools::Rectangle aPrimaryTextLocation; - ::tools::Rectangle aSecondaryTextLocation; - - m_aRubyText.Paint(rRenderContext, aTextRect, &aPrimaryTextLocation, &aSecondaryTextLocation); - } - - Size RubyRadioButton::GetOptimalSize() const - { - vcl::Font aSmallerFont(m_xVirDev->GetFont()); - aSmallerFont.SetFontHeight( static_cast( 0.8 * aSmallerFont.GetFontHeight() ) ); - ::tools::Rectangle rect( Point(), Size( SAL_MAX_INT32, SAL_MAX_INT32 ) ); - - Size aPrimarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getPrimaryText() ).GetSize(); - Size aSecondarySize; - { - FontSwitch aFontRestore(*m_xVirDev, aSmallerFont); - aSecondarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getSecondaryText() ).GetSize(); - } - - Size minimumSize; - minimumSize.setHeight( aPrimarySize.Height() + aSecondarySize.Height() + 5 ); - minimumSize.setWidth(std::max(aPrimarySize.Width(), aSecondarySize.Width()) + 5 ); - return minimumSize; - } - - SuggestionSet::SuggestionSet(std::unique_ptr xScrolledWindow) - : ValueSet(std::move(xScrolledWindow)) - - { - } - - void SuggestionSet::UserDraw( const UserDrawEvent& rUDEvt ) - { - vcl::RenderContext* pDev = rUDEvt.GetRenderContext(); - ::tools::Rectangle aRect = rUDEvt.GetRect(); - sal_uInt16 nItemId = rUDEvt.GetItemId(); - - OUString sText = *static_cast< OUString* >( GetItemData( nItemId ) ); - pDev->DrawText( aRect, sText, DrawTextFlags::Center | DrawTextFlags::VCenter ); - } - - SuggestionDisplay::SuggestionDisplay(weld::Builder& rBuilder) - : m_bDisplayListBox( true ) - , m_bInSelectionUpdate( false ) - , m_xValueSet(new SuggestionSet(rBuilder.weld_scrolled_window(u"scrollwin"_ustr, true))) - , m_xValueSetWin(new weld::CustomWeld(rBuilder, u"valueset"_ustr, *m_xValueSet)) - , m_xListBox(rBuilder.weld_tree_view(u"listbox"_ustr)) - { - m_xValueSet->SetSelectHdl( LINK( this, SuggestionDisplay, SelectSuggestionValueSetHdl ) ); - m_xListBox->connect_selection_changed( - LINK(this, SuggestionDisplay, SelectSuggestionListBoxHdl)); - - m_xValueSet->SetLineCount( LINE_CNT ); - m_xValueSet->SetStyle( m_xValueSet->GetStyle() | WB_ITEMBORDER | WB_VSCROLL ); - - auto nItemWidth = 2 * m_xListBox->get_pixel_size(u"AU"_ustr).Width(); - m_xValueSet->SetItemWidth( nItemWidth ); - - Size aSize(m_xListBox->get_approximate_digit_width() * 42, m_xListBox->get_text_height() * 5); - m_xValueSet->set_size_request(aSize.Width(), aSize.Height()); - m_xListBox->set_size_request(aSize.Width(), aSize.Height()); - - implUpdateDisplay(); - } - - void SuggestionDisplay::implUpdateDisplay() - { - m_xListBox->set_visible(m_bDisplayListBox); - if (!m_bDisplayListBox) - m_xValueSetWin->show(); - else - m_xValueSetWin->hide(); - } - - weld::Widget& SuggestionDisplay::implGetCurrentControl() - { - if (m_bDisplayListBox) - return *m_xListBox; - return *m_xValueSet->GetDrawingArea(); - } - - void SuggestionDisplay::DisplayListBox( bool bDisplayListBox ) - { - if( m_bDisplayListBox == bDisplayListBox ) - return; - - weld::Widget& rOldControl = implGetCurrentControl(); - bool bHasFocus = rOldControl.has_focus(); - - m_bDisplayListBox = bDisplayListBox; - - if( bHasFocus ) - { - weld::Widget& rNewControl = implGetCurrentControl(); - rNewControl.grab_focus(); - } - - implUpdateDisplay(); - } - - IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionValueSetHdl, ValueSet*, void) - { - SelectSuggestionHdl(false); - } - - IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionListBoxHdl, weld::ItemView&, void) - { - SelectSuggestionHdl(true); - } - - void SuggestionDisplay::SelectSuggestionHdl(bool bListBox) - { - if( m_bInSelectionUpdate ) - return; - - m_bInSelectionUpdate = true; - if (bListBox) - { - sal_uInt16 nPos = m_xListBox->get_selected_index(); - m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning) - } - else - { - sal_uInt16 nPos = m_xValueSet->GetSelectedItemId()-1; //itemid == pos+1 (id 0 has special meaning) - m_xListBox->select(nPos); - } - m_bInSelectionUpdate = false; - m_aSelectLink.Call( *this ); - } - - void SuggestionDisplay::SetSelectHdl( const Link& rLink ) - { - m_aSelectLink = rLink; - } - - void SuggestionDisplay::Clear() - { - m_xListBox->clear(); - m_xValueSet->Clear(); - } - - void SuggestionDisplay::InsertEntry( const OUString& rStr ) - { - m_xListBox->append_text(rStr); - sal_uInt16 nItemId = m_xListBox->n_children(); //itemid == pos+1 (id 0 has special meaning) - m_xValueSet->InsertItem( nItemId ); - OUString* pItemData = new OUString( rStr ); - m_xValueSet->SetItemData( nItemId, pItemData ); - } - - void SuggestionDisplay::SelectEntryPos( sal_uInt16 nPos ) - { - m_xListBox->select(nPos); - m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning) - } - - sal_uInt16 SuggestionDisplay::GetEntryCount() const - { - return m_xListBox->n_children(); - } - - OUString SuggestionDisplay::GetEntry( sal_uInt16 nPos ) const - { - return m_xListBox->get_text( nPos ); - } - - OUString SuggestionDisplay::GetSelectedEntry() const - { - return m_xListBox->get_selected_text(); - } - - void SuggestionDisplay::SetHelpIds() - { - m_xValueSet->SetHelpId(HID_HANGULDLG_SUGGESTIONS_GRID); - m_xListBox->set_help_id(HID_HANGULDLG_SUGGESTIONS_LIST); - } - - HangulHanjaConversionDialog::HangulHanjaConversionDialog(weld::Widget* pParent) - : GenericDialogController(pParent, u"cui/ui/hangulhanjaconversiondialog.ui"_ustr, u"HangulHanjaConversionDialog"_ustr) - , m_bDocumentMode( true ) - , m_xFind(m_xBuilder->weld_button(u"find"_ustr)) - , m_xIgnore(m_xBuilder->weld_button(u"ignore"_ustr)) - , m_xIgnoreAll(m_xBuilder->weld_button(u"ignoreall"_ustr)) - , m_xReplace(m_xBuilder->weld_button(u"replace"_ustr)) - , m_xReplaceAll(m_xBuilder->weld_button(u"replaceall"_ustr)) - , m_xOptions(m_xBuilder->weld_button(u"options"_ustr)) - , m_xSuggestions(new SuggestionDisplay(*m_xBuilder)) - , m_xSimpleConversion(m_xBuilder->weld_radio_button(u"simpleconversion"_ustr)) - , m_xHangulBracketed(m_xBuilder->weld_radio_button(u"hangulbracket"_ustr)) - , m_xHanjaBracketed(m_xBuilder->weld_radio_button(u"hanjabracket"_ustr)) - , m_xWordInput(m_xBuilder->weld_entry(u"wordinput"_ustr)) - , m_xOriginalWord(m_xBuilder->weld_label(u"originalword"_ustr)) - , m_xHanjaAbove(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hanja_above"_ustr), - m_xBuilder->weld_image(u"hanja_above_img"_ustr))) - , m_xHanjaBelow(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hanja_below"_ustr), - m_xBuilder->weld_image(u"hanja_below_img"_ustr))) - , m_xHangulAbove(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hangul_above"_ustr), - m_xBuilder->weld_image(u"hangul_above_img"_ustr))) - , m_xHangulBelow(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hangul_below"_ustr), - m_xBuilder->weld_image(u"hangul_below_img"_ustr))) - , m_xHangulOnly(m_xBuilder->weld_check_button(u"hangulonly"_ustr)) - , m_xHanjaOnly(m_xBuilder->weld_check_button(u"hanjaonly"_ustr)) - , m_xReplaceByChar(m_xBuilder->weld_check_button(u"replacebychar"_ustr)) - { - m_xSuggestions->set_size_request(m_xOriginalWord->get_approximate_digit_width() * 42, - m_xOriginalWord->get_text_height() * 5); - - const OUString sHangul(CuiResId(RID_CUISTR_HANGUL)); - const OUString sHanja(CuiResId(RID_CUISTR_HANJA)); - m_xHanjaAbove->init( sHangul, sHanja, PseudoRubyText::eAbove ); - m_xHanjaBelow->init( sHangul, sHanja, PseudoRubyText::eBelow ); - m_xHangulAbove->init( sHanja, sHangul, PseudoRubyText::eAbove ); - m_xHangulBelow->init( sHanja, sHangul, PseudoRubyText::eBelow ); - - m_xWordInput->connect_changed( LINK( this, HangulHanjaConversionDialog, OnSuggestionModified ) ); - m_xSuggestions->SetSelectHdl( LINK( this, HangulHanjaConversionDialog, OnSuggestionSelected ) ); - m_xReplaceByChar->connect_toggled( LINK( this, HangulHanjaConversionDialog, ClickByCharacterHdl ) ); - m_xHangulOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) ); - m_xHanjaOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) ); - m_xOptions->connect_clicked(LINK(this, HangulHanjaConversionDialog, OnOption)); - - // initial focus - FocusSuggestion( ); - - // initial control values - m_xSimpleConversion->set_active(true); - - m_xSuggestions->SetHelpIds(); - } - - HangulHanjaConversionDialog::~HangulHanjaConversionDialog() - { - } - - void HangulHanjaConversionDialog::FillSuggestions( const css::uno::Sequence< OUString >& _rSuggestions ) - { - m_xSuggestions->Clear(); - for ( auto const & suggestion : _rSuggestions ) - m_xSuggestions->InsertEntry( suggestion ); - - // select the first suggestion, and fill in the suggestion edit field - OUString sFirstSuggestion; - if ( m_xSuggestions->GetEntryCount() ) - { - sFirstSuggestion = m_xSuggestions->GetEntry( 0 ); - m_xSuggestions->SelectEntryPos( 0 ); - } - m_xWordInput->set_text( sFirstSuggestion ); - m_xWordInput->save_value(); - OnSuggestionModified( *m_xWordInput ); - } - - void HangulHanjaConversionDialog::SetOptionsChangedHdl(const Link& rHdl) - { - m_aOptionsChangedLink = rHdl; - } - - void HangulHanjaConversionDialog::SetIgnoreHdl(const Link& rHdl) - { - m_xIgnore->connect_clicked(rHdl); - } - - void HangulHanjaConversionDialog::SetIgnoreAllHdl(const Link& rHdl) - { - m_xIgnoreAll->connect_clicked(rHdl); - } - - void HangulHanjaConversionDialog::SetChangeHdl(const Link& rHdl ) - { - m_xReplace->connect_clicked(rHdl); - } - - void HangulHanjaConversionDialog::SetChangeAllHdl(const Link& rHdl) - { - m_xReplaceAll->connect_clicked(rHdl); - } - - void HangulHanjaConversionDialog::SetFindHdl(const Link& rHdl) - { - m_xFind->connect_clicked(rHdl); - } - - void HangulHanjaConversionDialog::SetConversionFormatChangedHdl( const Link& rHdl ) - { - m_xSimpleConversion->connect_toggled( rHdl ); - m_xHangulBracketed->connect_toggled( rHdl ); - m_xHanjaBracketed->connect_toggled( rHdl ); - m_xHanjaAbove->connect_toggled( rHdl ); - m_xHanjaBelow->connect_toggled( rHdl ); - m_xHangulAbove->connect_toggled( rHdl ); - m_xHangulBelow->connect_toggled( rHdl ); - } - - void HangulHanjaConversionDialog::SetClickByCharacterHdl( const Link& _rHdl ) - { - m_aClickByCharacterLink = _rHdl; - } - - IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionSelected, SuggestionDisplay&, void ) - { - m_xWordInput->set_text(m_xSuggestions->GetSelectedEntry()); - OnSuggestionModified( *m_xWordInput ); - } - - IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionModified, weld::Entry&, void ) - { - m_xFind->set_sensitive(m_xWordInput->get_value_changed_from_saved()); - - bool bSameLen = m_xWordInput->get_text().getLength() == m_xOriginalWord->get_label().getLength(); - m_xReplace->set_sensitive( m_bDocumentMode && bSameLen ); - m_xReplaceAll->set_sensitive( m_bDocumentMode && bSameLen ); - } - - IMPL_LINK(HangulHanjaConversionDialog, ClickByCharacterHdl, weld::Toggleable&, rBox, void) - { - m_aClickByCharacterLink.Call(rBox); - bool bByCharacter = rBox.get_active(); - m_xSuggestions->DisplayListBox( !bByCharacter ); - } - - IMPL_LINK(HangulHanjaConversionDialog, OnConversionDirectionClicked, weld::Toggleable&, rBox, void) - { - weld::CheckButton* pOtherBox = nullptr; - if (&rBox == m_xHangulOnly.get()) - pOtherBox = m_xHanjaOnly.get(); - else - pOtherBox = m_xHangulOnly.get(); - bool bBoxChecked = rBox.get_active(); - if (bBoxChecked) - pOtherBox->set_active(false); - pOtherBox->set_sensitive(!bBoxChecked); - } - - IMPL_LINK_NOARG(HangulHanjaConversionDialog, OnOption, weld::Button&, void) - { - HangulHanjaOptionsDialog aOptDlg(m_xDialog.get()); - aOptDlg.run(); - m_aOptionsChangedLink.Call( nullptr ); - } - - OUString HangulHanjaConversionDialog::GetCurrentString( ) const - { - return m_xOriginalWord->get_label(); - } - - void HangulHanjaConversionDialog::FocusSuggestion( ) - { - m_xWordInput->grab_focus(); - } - - void HangulHanjaConversionDialog::SetCurrentString( const OUString& _rNewString, - const Sequence< OUString >& _rSuggestions, bool _bOriginatesFromDocument ) - { - m_xOriginalWord->set_label(_rNewString); - - bool bOldDocumentMode = m_bDocumentMode; - m_bDocumentMode = _bOriginatesFromDocument; // before FillSuggestions! - FillSuggestions( _rSuggestions ); - - m_xIgnoreAll->set_sensitive( m_bDocumentMode ); - - // switch the def button depending if we're working for document text - if (bOldDocumentMode == m_bDocumentMode) - return; - - weld::Button* pOldDefButton = nullptr; - weld::Button* pNewDefButton = nullptr; - if (m_bDocumentMode) - { - pOldDefButton = m_xFind.get(); - pNewDefButton = m_xReplace.get(); - } - else - { - pOldDefButton = m_xReplace.get(); - pNewDefButton = m_xFind.get(); - } - - m_xDialog->change_default_button(pOldDefButton, pNewDefButton); - } - - OUString HangulHanjaConversionDialog::GetCurrentSuggestion( ) const - { - return m_xWordInput->get_text(); - } - - void HangulHanjaConversionDialog::SetByCharacter( bool _bByCharacter ) - { - m_xReplaceByChar->set_active( _bByCharacter ); - m_xSuggestions->DisplayListBox( !_bByCharacter ); - } - - void HangulHanjaConversionDialog::SetConversionDirectionState( - bool _bTryBothDirections, - HHC::ConversionDirection ePrimaryConversionDirection ) - { - // default state: try both direction - m_xHangulOnly->set_active( false ); - m_xHangulOnly->set_sensitive(true); - m_xHanjaOnly->set_active( false ); - m_xHanjaOnly->set_sensitive(true); - - if (!_bTryBothDirections) - { - weld::CheckButton* pBox = ePrimaryConversionDirection == HHC::eHangulToHanja ? - m_xHangulOnly.get() : m_xHanjaOnly.get(); - pBox->set_active(true); - OnConversionDirectionClicked(*pBox); - } - } - - bool HangulHanjaConversionDialog::GetUseBothDirections( ) const - { - return !m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active(); - } - - HHC::ConversionDirection HangulHanjaConversionDialog::GetDirection( - HHC::ConversionDirection eDefaultDirection ) const - { - HHC::ConversionDirection eDirection = eDefaultDirection; - if (m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active()) - eDirection = HHC::eHangulToHanja; - else if (!m_xHangulOnly->get_active() && m_xHanjaOnly->get_active()) - eDirection = HHC::eHanjaToHangul; - return eDirection; - } - - void HangulHanjaConversionDialog::SetConversionFormat( HHC::ConversionFormat _eType ) - { - switch ( _eType ) - { - case HHC::eSimpleConversion: m_xSimpleConversion->set_active(true); break; - case HHC::eHangulBracketed: m_xHangulBracketed->set_active(true); break; - case HHC::eHanjaBracketed: m_xHanjaBracketed->set_active(true); break; - case HHC::eRubyHanjaAbove: m_xHanjaAbove->set_active(true); break; - case HHC::eRubyHanjaBelow: m_xHanjaBelow->set_active(true); break; - case HHC::eRubyHangulAbove: m_xHangulAbove->set_active(true); break; - case HHC::eRubyHangulBelow: m_xHangulBelow->set_active(true); break; - default: - OSL_FAIL( "HangulHanjaConversionDialog::SetConversionFormat: unknown type!" ); - } - } - - HHC::ConversionFormat HangulHanjaConversionDialog::GetConversionFormat( ) const - { - if ( m_xSimpleConversion->get_active() ) - return HHC::eSimpleConversion; - if ( m_xHangulBracketed->get_active() ) - return HHC::eHangulBracketed; - if ( m_xHanjaBracketed->get_active() ) - return HHC::eHanjaBracketed; - if ( m_xHanjaAbove->get_active() ) - return HHC::eRubyHanjaAbove; - if ( m_xHanjaBelow->get_active() ) - return HHC::eRubyHanjaBelow; - if ( m_xHangulAbove->get_active() ) - return HHC::eRubyHangulAbove; - if ( m_xHangulBelow->get_active() ) - return HHC::eRubyHangulBelow; - - OSL_FAIL( "HangulHanjaConversionDialog::GetConversionFormat: no radio checked?" ); - return HHC::eSimpleConversion; - } - - void HangulHanjaConversionDialog::EnableRubySupport( bool bVal ) - { - m_xHanjaAbove->set_sensitive( bVal ); - m_xHanjaBelow->set_sensitive( bVal ); - m_xHangulAbove->set_sensitive( bVal ); - m_xHangulBelow->set_sensitive( bVal ); - } - - void HangulHanjaOptionsDialog::Init() - { - if( !m_xConversionDictionaryList.is() ) - { - m_xConversionDictionaryList = ConversionDictionaryList::create( ::comphelper::getProcessComponentContext() ); - } - - m_aDictList.clear(); - m_xDictsLB->clear(); - - Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer(); - if( xNameCont.is() ) - { - for (auto& name : xNameCont->getElementNames()) - { - Any aAny(xNameCont->getByName(name)); - Reference< XConversionDictionary > xDic; - if( ( aAny >>= xDic ) && xDic.is() ) - { - if( LANGUAGE_KOREAN == LanguageTag( xDic->getLocale() ).getLanguageType() ) - { - m_aDictList.push_back( xDic ); - AddDict( xDic->getName(), xDic->isActive() ); - } - } - } - } - if (m_xDictsLB->n_children()) - m_xDictsLB->select(0); - } - - IMPL_LINK_NOARG(HangulHanjaOptionsDialog, OkHdl, weld::Button&, void) - { - sal_uInt32 nCnt = m_aDictList.size(); - sal_uInt32 n = 0; - sal_uInt32 nActiveDics = 0; - Sequence< OUString > aActiveDics; - - aActiveDics.realloc( nCnt ); - OUString* pActActiveDic = aActiveDics.getArray(); - - while( nCnt ) - { - Reference< XConversionDictionary > xDict = m_aDictList[ n ]; - - DBG_ASSERT( xDict.is(), "-HangulHanjaOptionsDialog::OkHdl(): someone is evaporated..." ); - - bool bActive = m_xDictsLB->get_toggle(n) == TRISTATE_TRUE; - xDict->setActive( bActive ); - Reference< util::XFlushable > xFlush( xDict, uno::UNO_QUERY ); - if( xFlush.is() ) - xFlush->flush(); - - if( bActive ) - { - pActActiveDic[ nActiveDics ] = xDict->getName(); - ++nActiveDics; - } - - ++n; - --nCnt; - } - - // save configuration - aActiveDics.realloc( nActiveDics ); - Any aTmp; - SvtLinguConfig aLngCfg; - aTmp <<= aActiveDics; - aLngCfg.SetProperty( UPH_ACTIVE_CONVERSION_DICTIONARIES, aTmp ); - - aTmp <<= m_xIgnorepostCB->get_active(); - aLngCfg.SetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD, aTmp ); - - aTmp <<= m_xShowrecentlyfirstCB->get_active(); - aLngCfg.SetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, aTmp ); - - aTmp <<= m_xAutoreplaceuniqueCB->get_active(); - aLngCfg.SetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES, aTmp ); - - m_xDialog->response(RET_OK); - } - - IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DictsLB_SelectHdl, weld::ItemView&, void) - { - bool bSel = m_xDictsLB->get_selected_index() != -1; - - m_xEditPB->set_sensitive(bSel); - m_xDeletePB->set_sensitive(bSel); - } - - IMPL_LINK_NOARG(HangulHanjaOptionsDialog, NewDictHdl, weld::Button&, void) - { - OUString aName; - HangulHanjaNewDictDialog aNewDlg(m_xDialog.get()); - aNewDlg.run(); - if (!aNewDlg.GetName(aName)) - return; - - if( !m_xConversionDictionaryList.is() ) - return; - - try - { - Reference< XConversionDictionary > xDic = - m_xConversionDictionaryList->addNewDictionary( aName, LanguageTag::convertToLocale( LANGUAGE_KOREAN ), ConversionDictionaryType::HANGUL_HANJA ); - - if( xDic.is() ) - { - //adapt local caches: - m_aDictList.push_back( xDic ); - AddDict( xDic->getName(), xDic->isActive() ); - } - } - catch( const ElementExistException& ) - { - } - catch( const NoSupportException& ) - { - } - } - - IMPL_LINK_NOARG(HangulHanjaOptionsDialog, EditDictHdl, weld::Button&, void) - { - int nEntry = m_xDictsLB->get_selected_index(); - DBG_ASSERT(nEntry != -1, "+HangulHanjaEditDictDialog::EditDictHdl(): call of edit should not be possible with no selection!"); - if (nEntry != -1) - { - HangulHanjaEditDictDialog aEdDlg(m_xDialog.get(), m_aDictList, nEntry); - aEdDlg.run(); - } - } - - IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DeleteDictHdl, weld::Button&, void) - { - int nSelPos = m_xDictsLB->get_selected_index(); - if (nSelPos == -1) - return; - - Reference< XConversionDictionary > xDic( m_aDictList[ nSelPos ] ); - if( !(m_xConversionDictionaryList.is() && xDic.is()) ) - return; - - Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer(); - if( !xNameCont.is() ) - return; - - try - { - xNameCont->removeByName( xDic->getName() ); - - //adapt local caches: - m_aDictList.erase(m_aDictList.begin()+nSelPos ); - m_xDictsLB->remove(nSelPos); - } - catch( const ElementExistException& ) - { - } - catch( const NoSupportException& ) - { - } - } - - HangulHanjaOptionsDialog::HangulHanjaOptionsDialog(weld::Window* pParent) - : GenericDialogController(pParent, u"cui/ui/hangulhanjaoptdialog.ui"_ustr, u"HangulHanjaOptDialog"_ustr) - , m_xDictsLB(m_xBuilder->weld_tree_view(u"dicts"_ustr)) - , m_xIgnorepostCB(m_xBuilder->weld_check_button(u"ignorepost"_ustr)) - , m_xShowrecentlyfirstCB(m_xBuilder->weld_check_button(u"showrecentfirst"_ustr)) - , m_xAutoreplaceuniqueCB(m_xBuilder->weld_check_button(u"autoreplaceunique"_ustr)) - , m_xNewPB(m_xBuilder->weld_button(u"new"_ustr)) - , m_xEditPB(m_xBuilder->weld_button(u"edit"_ustr)) - , m_xDeletePB(m_xBuilder->weld_button(u"delete"_ustr)) - , m_xOkPB(m_xBuilder->weld_button(u"ok"_ustr)) - { - m_xDictsLB->set_size_request(m_xDictsLB->get_approximate_digit_width() * 32, - m_xDictsLB->get_height_rows(5)); - - m_xDictsLB->enable_toggle_buttons(weld::ColumnToggleType::Check); - - m_xDictsLB->connect_selection_changed( - LINK(this, HangulHanjaOptionsDialog, DictsLB_SelectHdl)); - - m_xOkPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, OkHdl ) ); - m_xNewPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, NewDictHdl ) ); - m_xEditPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, EditDictHdl ) ); - m_xDeletePB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, DeleteDictHdl ) ); - - SvtLinguConfig aLngCfg; - Any aTmp; - bool bVal = bool(); - aTmp = aLngCfg.GetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD ); - if( aTmp >>= bVal ) - m_xIgnorepostCB->set_active( bVal ); - - aTmp = aLngCfg.GetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST ); - if( aTmp >>= bVal ) - m_xShowrecentlyfirstCB->set_active( bVal ); - - aTmp = aLngCfg.GetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES ); - if( aTmp >>= bVal ) - m_xAutoreplaceuniqueCB->set_active( bVal ); - - Init(); - } - - HangulHanjaOptionsDialog::~HangulHanjaOptionsDialog() - { - } - - void HangulHanjaOptionsDialog::AddDict(const OUString& rName, bool bChecked) - { - m_xDictsLB->append(); - int nRow = m_xDictsLB->n_children() - 1; - m_xDictsLB->set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xDictsLB->set_text(nRow, rName, 0); - m_xDictsLB->set_id(nRow, rName); - } - - IMPL_LINK_NOARG(HangulHanjaNewDictDialog, OKHdl, weld::Button&, void) - { - OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ')); - - m_bEntered = !aName.isEmpty(); - if (m_bEntered) - m_xDictNameED->set_text(aName); // do this in case of trailing chars have been deleted - - m_xDialog->response(RET_OK); - } - - IMPL_LINK_NOARG(HangulHanjaNewDictDialog, ModifyHdl, weld::Entry&, void) - { - OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ')); - - m_xOkBtn->set_sensitive(!aName.isEmpty()); - } - - HangulHanjaNewDictDialog::HangulHanjaNewDictDialog(weld::Window* pParent) - : GenericDialogController(pParent, u"cui/ui/hangulhanjaadddialog.ui"_ustr, u"HangulHanjaAddDialog"_ustr) - , m_bEntered(false) - , m_xOkBtn(m_xBuilder->weld_button(u"ok"_ustr)) - , m_xDictNameED(m_xBuilder->weld_entry(u"entry"_ustr)) - { - m_xOkBtn->connect_clicked( LINK( this, HangulHanjaNewDictDialog, OKHdl ) ); - m_xDictNameED->connect_changed( LINK( this, HangulHanjaNewDictDialog, ModifyHdl ) ); - } - - HangulHanjaNewDictDialog::~HangulHanjaNewDictDialog() - { - } - - bool HangulHanjaNewDictDialog::GetName( OUString& _rRetName ) const - { - if( m_bEntered ) - _rRetName = comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '); - - return m_bEntered; - } - - class SuggestionList - { - private: - protected: - std::vector m_vElements; - sal_uInt16 m_nNumOfEntries; - // index of the internal iterator, used for First() and Next() methods - sal_uInt16 m_nAct; - - const OUString* Next_(); - public: - SuggestionList(); - ~SuggestionList(); - - void Set( const OUString& _rElement, sal_uInt16 _nNumOfElement ); - void Reset( sal_uInt16 _nNumOfElement ); - const OUString & Get( sal_uInt16 _nNumOfElement ) const; - void Clear(); - - const OUString* First(); - const OUString* Next(); - - sal_uInt16 GetCount() const { return m_nNumOfEntries; } - }; - - SuggestionList::SuggestionList() : - m_vElements(MAXNUM_SUGGESTIONS) - { - m_nAct = m_nNumOfEntries = 0; - } - - SuggestionList::~SuggestionList() - { - Clear(); - } - - void SuggestionList::Set( const OUString& _rElement, sal_uInt16 _nNumOfElement ) - { - m_vElements[_nNumOfElement] = _rElement; - ++m_nNumOfEntries; - } - - void SuggestionList::Reset( sal_uInt16 _nNumOfElement ) - { - m_vElements[_nNumOfElement].clear(); - --m_nNumOfEntries; - } - - const OUString& SuggestionList::Get( sal_uInt16 _nNumOfElement ) const - { - return m_vElements[_nNumOfElement]; - } - - void SuggestionList::Clear() - { - if( m_nNumOfEntries ) - { - for (auto & vElement : m_vElements) - vElement.clear(); - m_nNumOfEntries = m_nAct = 0; - } - } - - const OUString* SuggestionList::Next_() - { - while( m_nAct < m_vElements.size() ) - { - auto & s = m_vElements[ m_nAct ]; - if (!s.isEmpty()) - return &s; - ++m_nAct; - } - - return nullptr; - } - - const OUString* SuggestionList::First() - { - m_nAct = 0; - return Next_(); - } - - const OUString* SuggestionList::Next() - { - const OUString* pRet; - - if( m_nAct < m_nNumOfEntries ) - { - ++m_nAct; - pRet = Next_(); - } - else - pRet = nullptr; - - return pRet; - } - - - bool SuggestionEdit::ShouldScroll( bool _bUp ) const - { - bool bRet = false; - - if( _bUp ) - { - if( !m_pPrev ) - bRet = m_pScrollBar->vadjustment_get_value() > 0; - } - else - { - if( !m_pNext ) - bRet = m_pScrollBar->vadjustment_get_value() < ( m_pScrollBar->vadjustment_get_upper() - 4 ); - } - - return bRet; - } - - void SuggestionEdit::DoJump( bool _bUp ) - { - m_pScrollBar->vadjustment_set_value( m_pScrollBar->vadjustment_get_value() + ( _bUp? -1 : 1 ) ); - m_pParent->UpdateScrollbar(); - } - - SuggestionEdit::SuggestionEdit(std::unique_ptr xEntry, HangulHanjaEditDictDialog* pParent) - : m_pParent(pParent) - , m_pPrev(nullptr) - , m_pNext(nullptr) - , m_pScrollBar(nullptr) - , m_xEntry(std::move(xEntry)) - { - m_xEntry->connect_key_press(LINK(this, SuggestionEdit, KeyInputHdl)); - } - - IMPL_LINK(SuggestionEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool) - { - bool bHandled = false; - - const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); - sal_uInt16 nMod = rKeyCode.GetModifier(); - sal_uInt16 nCode = rKeyCode.GetCode(); - if( nCode == KEY_TAB && ( !nMod || KEY_SHIFT == nMod ) ) - { - bool bUp = KEY_SHIFT == nMod; - if( ShouldScroll( bUp ) ) - { - DoJump( bUp ); - m_xEntry->select_region(0, -1); - // Tab-travel doesn't really happen, so emulate it by setting a selection manually - bHandled = true; - } - } - else if( KEY_UP == nCode || KEY_DOWN == nCode ) - { - bool bUp = KEY_UP == nCode; - if( ShouldScroll( bUp ) ) - { - DoJump( bUp ); - bHandled = true; - } - else if( bUp ) - { - if( m_pPrev ) - { - m_pPrev->grab_focus(); - bHandled = true; - } - } - else if( m_pNext ) - { - m_pNext->grab_focus(); - bHandled = true; - } - } - - return bHandled; - } - - void SuggestionEdit::init(weld::ScrolledWindow* pScrollBar, SuggestionEdit* pPrev, SuggestionEdit* pNext) - { - m_pScrollBar = pScrollBar; - m_pPrev = pPrev; - m_pNext = pNext; - } - - namespace - { - bool GetConversions( const Reference< XConversionDictionary >& _xDict, - const OUString& _rOrg, - Sequence< OUString >& _rEntries ) - { - bool bRet = false; - if( _xDict.is() && !_rOrg.isEmpty() ) - { - try - { - _rEntries = _xDict->getConversions( _rOrg, - 0, - _rOrg.getLength(), - ConversionDirection_FROM_LEFT, - css::i18n::TextConversionOption::NONE ); - bRet = _rEntries.hasElements(); - } - catch( const IllegalArgumentException& ) - { - } - } - - return bRet; - } - } - - IMPL_LINK_NOARG( HangulHanjaEditDictDialog, ScrollHdl, weld::ScrolledWindow&, void ) - { - UpdateScrollbar(); - } - - IMPL_LINK_NOARG( HangulHanjaEditDictDialog, OriginalModifyHdl, weld::ComboBox&, void ) - { - m_bModifiedOriginal = true; - m_aOriginal = comphelper::string::stripEnd( m_xOriginalLB->get_active_text(), ' ' ); - - UpdateSuggestions(); - UpdateButtonStates(); - } - - IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl1, weld::Entry&, rEdit, void ) - { - EditModify( &rEdit, 0 ); - } - - IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl2, weld::Entry&, rEdit, void ) - { - EditModify( &rEdit, 1 ); - } - - IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl3, weld::Entry&, rEdit, void ) - { - EditModify( &rEdit, 2 ); - } - - IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl4, weld::Entry&, rEdit, void ) - { - EditModify( &rEdit, 3 ); - } - - IMPL_LINK_NOARG( HangulHanjaEditDictDialog, BookLBSelectHdl, weld::ComboBox&, void ) - { - InitEditDictDialog( m_xBookLB->get_active() ); - } - - IMPL_LINK_NOARG( HangulHanjaEditDictDialog, NewPBPushHdl, weld::Button&, void ) - { - DBG_ASSERT( m_xSuggestions, "-HangulHanjaEditDictDialog::NewPBPushHdl(): no suggestions... search in hell..." ); - Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ]; - if( xDict.is() && m_xSuggestions ) - { - //delete old entry - bool bRemovedSomething = DeleteEntryFromDictionary( xDict ); - - OUString aLeft( m_aOriginal ); - const OUString* pRight = m_xSuggestions->First(); - bool bAddedSomething = false; - while( pRight ) - { - try - { - //add new entry - xDict->addEntry( aLeft, *pRight ); - bAddedSomething = true; - } - catch( const IllegalArgumentException& ) - { - } - catch( const ElementExistException& ) - { - } - - pRight = m_xSuggestions->Next(); - } - - if( bAddedSomething || bRemovedSomething ) - InitEditDictDialog( m_nCurrentDict ); - } - else - { - SAL_INFO( "cui.dialogs", "dictionary faded away..." ); - } - } - - bool HangulHanjaEditDictDialog::DeleteEntryFromDictionary( const Reference< XConversionDictionary >& xDict ) - { - bool bRemovedSomething = false; - if( xDict.is() ) - { - OUString aOrg( m_aOriginal ); - Sequence< OUString > aEntries; - GetConversions( xDict, m_aOriginal, aEntries ); - - sal_uInt32 n = aEntries.getLength(); - OUString* pEntry = aEntries.getArray(); - while( n ) - { - try - { - xDict->removeEntry( aOrg, *pEntry ); - bRemovedSomething = true; - } - catch( const NoSuchElementException& ) - { // can not be... - } - - ++pEntry; - --n; - } - } - return bRemovedSomething; - } - - IMPL_LINK_NOARG( HangulHanjaEditDictDialog, DeletePBPushHdl, weld::Button&, void ) - { - if( DeleteEntryFromDictionary( m_rDictList[ m_nCurrentDict ] ) ) - { - m_aOriginal.clear(); - m_bModifiedOriginal = true; - InitEditDictDialog( m_nCurrentDict ); - } - } - - void HangulHanjaEditDictDialog::InitEditDictDialog( sal_uInt32 nSelDict ) - { - if( m_xSuggestions ) - m_xSuggestions->Clear(); - - if( m_nCurrentDict != nSelDict ) - { - m_nCurrentDict = nSelDict; - m_aOriginal.clear(); - m_bModifiedOriginal = true; - } - - UpdateOriginalLB(); - - m_xOriginalLB->set_entry_text( !m_aOriginal.isEmpty() ? m_aOriginal : m_aEditHintText); - m_xOriginalLB->select_entry_region(0, -1); - m_xOriginalLB->grab_focus(); - - UpdateSuggestions(); - UpdateButtonStates(); - } - - void HangulHanjaEditDictDialog::UpdateOriginalLB() - { - m_xOriginalLB->clear(); - Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ]; - if( xDict.is() ) - { - Sequence< OUString > aEntries = xDict->getConversionEntries( ConversionDirection_FROM_LEFT ); - sal_uInt32 n = aEntries.getLength(); - OUString* pEntry = aEntries.getArray(); - while( n ) - { - m_xOriginalLB->append_text( *pEntry ); - - ++pEntry; - --n; - } - } - else - { - SAL_INFO( "cui.dialogs", "dictionary faded away..." ); - } - } - - void HangulHanjaEditDictDialog::UpdateButtonStates() - { - bool bHaveValidOriginalString = !m_aOriginal.isEmpty() && m_aOriginal != m_aEditHintText; - bool bNew = bHaveValidOriginalString && m_xSuggestions && m_xSuggestions->GetCount() > 0; - bNew = bNew && ( m_bModifiedSuggestions || m_bModifiedOriginal ); - - m_xNewPB->set_sensitive( bNew ); - m_xDeletePB->set_sensitive(!m_bModifiedOriginal && bHaveValidOriginalString); - } - - void HangulHanjaEditDictDialog::UpdateSuggestions() - { - Sequence< OUString > aEntries; - bool bFound = GetConversions( m_rDictList[ m_nCurrentDict ], m_aOriginal, aEntries ); - if( bFound ) - { - m_bModifiedOriginal = false; - - if( m_xSuggestions ) - m_xSuggestions->Clear(); - - //fill found entries into boxes - if (aEntries.hasElements()) - { - if( !m_xSuggestions ) - m_xSuggestions.reset(new SuggestionList); - - for (sal_Int32 n = 0; n < aEntries.getLength(); ++n) - m_xSuggestions->Set(aEntries[n], n); - } - m_bModifiedSuggestions = false; - } - - m_xScrollSB->vadjustment_set_value( 0 ); - UpdateScrollbar(); // will force edits to be filled new - } - - void HangulHanjaEditDictDialog::SetEditText(SuggestionEdit& rEdit, sal_uInt16 nEntryNum) - { - OUString aStr; - if( m_xSuggestions ) - { - aStr = m_xSuggestions->Get(nEntryNum); - } - - rEdit.set_text(aStr); - } - - void HangulHanjaEditDictDialog::EditModify(const weld::Entry* pEdit, sal_uInt8 _nEntryOffset) - { - m_bModifiedSuggestions = true; - - OUString aTxt( pEdit->get_text() ); - sal_uInt16 nEntryNum = m_nTopPos + _nEntryOffset; - if( aTxt.isEmpty() ) - { - //reset suggestion - if( m_xSuggestions ) - m_xSuggestions->Reset( nEntryNum ); - } - else - { - //set suggestion - if( !m_xSuggestions ) - m_xSuggestions.reset(new SuggestionList); - m_xSuggestions->Set( aTxt, nEntryNum ); - } - - UpdateButtonStates(); - } - - HangulHanjaEditDictDialog::HangulHanjaEditDictDialog(weld::Window* pParent, HHDictList& _rDictList, sal_uInt32 nSelDict) - : GenericDialogController(pParent, u"cui/ui/hangulhanjaeditdictdialog.ui"_ustr, u"HangulHanjaEditDictDialog"_ustr) - , m_aEditHintText ( CuiResId(RID_CUISTR_EDITHINT) ) - , m_rDictList ( _rDictList ) - , m_nCurrentDict ( 0xFFFFFFFF ) - , m_nTopPos ( 0 ) - , m_bModifiedSuggestions ( false ) - , m_bModifiedOriginal ( false ) - , m_xBookLB(m_xBuilder->weld_combo_box(u"book"_ustr)) - , m_xOriginalLB(m_xBuilder->weld_combo_box(u"original"_ustr)) - , m_xEdit1(new SuggestionEdit(m_xBuilder->weld_entry(u"edit1"_ustr), this)) - , m_xEdit2(new SuggestionEdit(m_xBuilder->weld_entry(u"edit2"_ustr), this)) - , m_xEdit3(new SuggestionEdit(m_xBuilder->weld_entry(u"edit3"_ustr), this)) - , m_xEdit4(new SuggestionEdit(m_xBuilder->weld_entry(u"edit4"_ustr), this)) - , m_xContents(m_xBuilder->weld_widget(u"box"_ustr)) - , m_xScrollSB(m_xBuilder->weld_scrolled_window(u"scrollbar"_ustr, true)) - , m_xNewPB(m_xBuilder->weld_button(u"new"_ustr)) - , m_xDeletePB(m_xBuilder->weld_button(u"delete"_ustr)) - { - Size aSize(m_xContents->get_preferred_size()); - m_xScrollSB->set_size_request(-1, aSize.Height()); - - m_xEdit1->init( m_xScrollSB.get(), nullptr, m_xEdit2.get() ); - m_xEdit2->init( m_xScrollSB.get(), m_xEdit1.get(), m_xEdit3.get() ); - m_xEdit3->init( m_xScrollSB.get(), m_xEdit2.get(), m_xEdit4.get() ); - m_xEdit4->init( m_xScrollSB.get(), m_xEdit3.get(), nullptr ); - - m_xOriginalLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, OriginalModifyHdl ) ); - - m_xNewPB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, NewPBPushHdl ) ); - m_xNewPB->set_sensitive( false ); - - m_xDeletePB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, DeletePBPushHdl ) ); - m_xDeletePB->set_sensitive( false ); - - static_assert(MAXNUM_SUGGESTIONS >= 5, "number of suggestions should not under-run the value of 5"); - - // 4 here, because we have 4 edits / page - m_xScrollSB->vadjustment_configure(0, MAXNUM_SUGGESTIONS, 1, 4, 4); - m_xScrollSB->connect_vadjustment_value_changed(LINK(this, HangulHanjaEditDictDialog, ScrollHdl)); - - m_xEdit1->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl1 ) ); - m_xEdit2->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl2 ) ); - m_xEdit3->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl3 ) ); - m_xEdit4->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl4 ) ); - - m_xBookLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, BookLBSelectHdl ) ); - sal_uInt32 nDictCnt = m_rDictList.size(); - for( sal_uInt32 n = 0 ; n < nDictCnt ; ++n ) - { - Reference< XConversionDictionary > xDic( m_rDictList[n] ); - OUString aName; - if( xDic.is() ) - aName = xDic->getName(); - m_xBookLB->append_text( aName ); - } - m_xBookLB->set_active(nSelDict); - - InitEditDictDialog(nSelDict); - } - - HangulHanjaEditDictDialog::~HangulHanjaEditDictDialog() - { - } - - void HangulHanjaEditDictDialog::UpdateScrollbar() - { - sal_uInt16 nPos = m_xScrollSB->vadjustment_get_value(); - m_nTopPos = nPos; - - SetEditText( *m_xEdit1, nPos++ ); - SetEditText( *m_xEdit2, nPos++ ); - SetEditText( *m_xEdit3, nPos++ ); - SetEditText( *m_xEdit4, nPos ); +protected: + OUString m_sPrimaryText; + OUString m_sSecondaryText; + RubyPosition m_ePosition; + +public: + PseudoRubyText(); + void init(const OUString& rPrimaryText, const OUString& rSecondaryText, + const RubyPosition& rPosition); + const OUString& getPrimaryText() const { return m_sPrimaryText; } + const OUString& getSecondaryText() const { return m_sSecondaryText; } + +public: + void Paint(vcl::RenderContext& _rDevice, const ::tools::Rectangle& _rRect, + ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation); +}; +} + +PseudoRubyText::PseudoRubyText() + : m_ePosition(eAbove) +{ +} + +void PseudoRubyText::init(const OUString& rPrimaryText, const OUString& rSecondaryText, + const RubyPosition& rPosition) +{ + m_sPrimaryText = rPrimaryText; + m_sSecondaryText = rSecondaryText; + m_ePosition = rPosition; +} + +void PseudoRubyText::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& _rRect, + ::tools::Rectangle* _pPrimaryLocation, + ::tools::Rectangle* _pSecondaryLocation) +{ + // calculate the text flags for the painting + constexpr DrawTextFlags nTextStyle + = DrawTextFlags::Mnemonic | DrawTextFlags::Left | DrawTextFlags::VCenter; + + Size aPlaygroundSize(_rRect.GetSize()); + + // the font for the secondary text: + vcl::Font aSmallerFont(rRenderContext.GetFont()); + // heuristic: 80% of the original size + aSmallerFont.SetFontHeight(static_cast(0.8 * aSmallerFont.GetFontHeight())); + + // let's calculate the size of our two texts + ::tools::Rectangle aPrimaryRect + = rRenderContext.GetTextRect(_rRect, m_sPrimaryText, nTextStyle); + ::tools::Rectangle aSecondaryRect; + { + FontSwitch aFontRestore(rRenderContext, aSmallerFont); + aSecondaryRect = rRenderContext.GetTextRect(_rRect, m_sSecondaryText, nTextStyle); + } + + // position these rectangles properly + // x-axis: + sal_Int32 nCombinedWidth = std::max(aSecondaryRect.GetWidth(), aPrimaryRect.GetWidth()); + // the rectangle where both texts will reside is as high as possible, and as wide as the + // widest of both text rects + aPrimaryRect.SetLeft(_rRect.Left()); + aSecondaryRect.SetLeft(aPrimaryRect.Left()); + aPrimaryRect.SetRight(_rRect.Left() + nCombinedWidth); + aSecondaryRect.SetRight(aPrimaryRect.Right()); + + // y-axis: + sal_Int32 nCombinedHeight = aPrimaryRect.GetHeight() + aSecondaryRect.GetHeight(); + // align to the top, for the moment + aPrimaryRect.Move(0, _rRect.Top() - aPrimaryRect.Top()); + aSecondaryRect.Move(0, aPrimaryRect.Top() + aPrimaryRect.GetHeight() - aSecondaryRect.Top()); + // move the rects to the bottom + aPrimaryRect.Move(0, (aPlaygroundSize.Height() - nCombinedHeight) / 2); + aSecondaryRect.Move(0, (aPlaygroundSize.Height() - nCombinedHeight) / 2); + + // 'til here, everything we did assumes that the secondary text is painted _below_ the primary + // text. If this isn't the case, we need to correct the rectangles + if (eAbove == m_ePosition) + { + sal_Int32 nVertDistance = aSecondaryRect.Top() - aPrimaryRect.Top(); + aSecondaryRect.Move(0, -nVertDistance); + aPrimaryRect.Move(0, nCombinedHeight - nVertDistance); + } + + // now draw the texts + // as we already calculated the precise rectangles for the texts, we don't want to + // use the alignment flags given - within its rect, every text is centered + DrawTextFlags nDrawTextStyle(nTextStyle); + nDrawTextStyle &= ~DrawTextFlags(DrawTextFlags::Right | DrawTextFlags::Left + | DrawTextFlags::Bottom | DrawTextFlags::Top); + nDrawTextStyle |= DrawTextFlags::Center | DrawTextFlags::VCenter; + + rRenderContext.DrawText(aPrimaryRect, m_sPrimaryText, nDrawTextStyle); + { + FontSwitch aFontRestore(rRenderContext, aSmallerFont); + rRenderContext.DrawText(aSecondaryRect, m_sSecondaryText, nDrawTextStyle); + } + + // outta here + if (_pPrimaryLocation) + *_pPrimaryLocation = aPrimaryRect; + if (_pSecondaryLocation) + *_pSecondaryLocation = aSecondaryRect; +} + +class RubyRadioButton +{ +public: + RubyRadioButton(std::unique_ptr xControl, + std::unique_ptr xImage); + void init(const OUString& rPrimaryText, const OUString& rSecondaryText, + const PseudoRubyText::RubyPosition& rPosition); + + void set_sensitive(bool sensitive) + { + m_xControl->set_sensitive(sensitive); + m_xImage->set_sensitive(sensitive); + } + void set_active(bool active) { m_xControl->set_active(active); } + bool get_active() const { return m_xControl->get_active(); } + + void connect_toggled(const Link& rLink) + { + m_xControl->connect_toggled(rLink); + } + +private: + Size GetOptimalSize() const; + void Paint(vcl::RenderContext& rRenderContext); + + ScopedVclPtr m_xVirDev; + std::unique_ptr m_xControl; + std::unique_ptr m_xImage; + PseudoRubyText m_aRubyText; +}; + +RubyRadioButton::RubyRadioButton(std::unique_ptr xControl, + std::unique_ptr xImage) + : m_xVirDev(xControl->create_virtual_device()) + , m_xControl(std::move(xControl)) + , m_xImage(std::move(xImage)) +{ + // expand the point size of the desired font to the equivalent pixel size + weld::SetPointFont(*m_xVirDev, m_xControl->get_font()); +} + +void RubyRadioButton::init(const OUString& rPrimaryText, const OUString& rSecondaryText, + const PseudoRubyText::RubyPosition& rPosition) +{ + m_aRubyText.init(rPrimaryText, rSecondaryText, rPosition); + + m_xVirDev->SetOutputSizePixel(GetOptimalSize()); + + Paint(*m_xVirDev); + + m_xImage->set_image(m_xVirDev.get()); +} + +void RubyRadioButton::Paint(vcl::RenderContext& rRenderContext) +{ + ::tools::Rectangle aOverallRect(Point(0, 0), rRenderContext.GetOutputSizePixel()); + // inflate the rect a little bit (because the VCL radio button does the same) + ::tools::Rectangle aTextRect(aOverallRect); + aTextRect.AdjustLeft(1); + aTextRect.AdjustRight(-1); + aTextRect.AdjustTop(1); + aTextRect.AdjustBottom(-1); + + // paint the ruby text + ::tools::Rectangle aPrimaryTextLocation; + ::tools::Rectangle aSecondaryTextLocation; + + m_aRubyText.Paint(rRenderContext, aTextRect, &aPrimaryTextLocation, &aSecondaryTextLocation); +} + +Size RubyRadioButton::GetOptimalSize() const +{ + vcl::Font aSmallerFont(m_xVirDev->GetFont()); + aSmallerFont.SetFontHeight(static_cast(0.8 * aSmallerFont.GetFontHeight())); + ::tools::Rectangle rect(Point(), Size(SAL_MAX_INT32, SAL_MAX_INT32)); + + Size aPrimarySize = m_xVirDev->GetTextRect(rect, m_aRubyText.getPrimaryText()).GetSize(); + Size aSecondarySize; + { + FontSwitch aFontRestore(*m_xVirDev, aSmallerFont); + aSecondarySize = m_xVirDev->GetTextRect(rect, m_aRubyText.getSecondaryText()).GetSize(); + } + + Size minimumSize; + minimumSize.setHeight(aPrimarySize.Height() + aSecondarySize.Height() + 5); + minimumSize.setWidth(std::max(aPrimarySize.Width(), aSecondarySize.Width()) + 5); + return minimumSize; +} + +SuggestionDisplay::SuggestionDisplay(weld::Builder& rBuilder) + : m_bDisplayListBox(true) + , m_bInSelectionUpdate(false) + , m_xIconView(rBuilder.weld_icon_view(u"iconview"_ustr)) + , m_xListBox(rBuilder.weld_tree_view(u"listbox"_ustr)) +{ + m_xIconView->connect_selection_changed( + LINK(this, SuggestionDisplay, SelectSuggestionIconViewHdl)); + m_xListBox->connect_selection_changed( + LINK(this, SuggestionDisplay, SelectSuggestionListBoxHdl)); + + Size aSize(m_xListBox->get_approximate_digit_width() * 42, m_xListBox->get_text_height() * 5); + m_xListBox->set_size_request(aSize.Width(), aSize.Height()); + + implUpdateDisplay(); +} + +void SuggestionDisplay::implUpdateDisplay() +{ + m_xListBox->set_visible(m_bDisplayListBox); + m_xIconView->set_visible(!m_bDisplayListBox); +} + +weld::Widget& SuggestionDisplay::implGetCurrentControl() +{ + if (m_bDisplayListBox) + return *m_xListBox; + return *m_xIconView; +} + +void SuggestionDisplay::DisplayListBox(bool bDisplayListBox) +{ + if (m_bDisplayListBox == bDisplayListBox) + return; + + weld::Widget& rOldControl = implGetCurrentControl(); + bool bHasFocus = rOldControl.has_focus(); + + m_bDisplayListBox = bDisplayListBox; + + if (bHasFocus) + { + weld::Widget& rNewControl = implGetCurrentControl(); + rNewControl.grab_focus(); + } + + implUpdateDisplay(); +} + +IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionIconViewHdl, weld::ItemView&, void) +{ + SelectSuggestionHdl(false); +} + +IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionListBoxHdl, weld::ItemView&, void) +{ + SelectSuggestionHdl(true); +} + +void SuggestionDisplay::SelectSuggestionHdl(bool bListBox) +{ + if (m_bInSelectionUpdate) + return; + + m_bInSelectionUpdate = true; + if (bListBox) + m_xIconView->select(m_xListBox->get_selected_index()); + else + m_xListBox->select(m_xIconView->get_selected_index()); + m_bInSelectionUpdate = false; + m_aSelectLink.Call(*this); +} + +void SuggestionDisplay::SetSelectHdl(const Link& rLink) +{ + m_aSelectLink = rLink; +} + +void SuggestionDisplay::Clear() +{ + m_xListBox->clear(); + m_xIconView->clear(); +} + +ScopedVclPtr SuggestionDisplay::CreateIcon(const OUString& rText) +{ + Size aItemSize = m_xListBox->get_pixel_size(u"AU"_ustr); + aItemSize.scale(2, 2); + + ScopedVclPtr pDev = m_xIconView->create_virtual_device(); + pDev->SetOutputSize(aItemSize); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + pDev->SetBackground(rStyleSettings.GetFieldColor()); + pDev->Erase(); + pDev->SetTextColor(rStyleSettings.GetFieldTextColor()); + pDev->DrawText(tools::Rectangle(0, 0, aItemSize.Width(), aItemSize.Height()), rText, + DrawTextFlags::Center | DrawTextFlags::VCenter); + + return pDev; +} + +void SuggestionDisplay::InsertEntry(const OUString& rStr) +{ + m_xListBox->append_text(rStr); + const int nIndex = m_xIconView->n_children(); + const OUString* pNullIconName = nullptr; + m_xIconView->insert(nIndex, nullptr, nullptr, pNullIconName, nullptr); + ScopedVclPtr pDev = CreateIcon(rStr); + m_xIconView->set_image(nIndex, *pDev); + m_xIconView->set_item_accessible_name(nIndex, rStr); +} + +void SuggestionDisplay::SelectEntryPos(sal_uInt16 nPos) +{ + m_xListBox->select(nPos); + m_xIconView->select(nPos); +} + +sal_uInt16 SuggestionDisplay::GetEntryCount() const { return m_xListBox->n_children(); } + +OUString SuggestionDisplay::GetEntry(sal_uInt16 nPos) const { return m_xListBox->get_text(nPos); } + +OUString SuggestionDisplay::GetSelectedEntry() const { return m_xListBox->get_selected_text(); } + +void SuggestionDisplay::SetHelpIds() +{ + m_xIconView->set_help_id(HID_HANGULDLG_SUGGESTIONS_GRID); + m_xListBox->set_help_id(HID_HANGULDLG_SUGGESTIONS_LIST); +} + +HangulHanjaConversionDialog::HangulHanjaConversionDialog(weld::Widget* pParent) + : GenericDialogController(pParent, u"cui/ui/hangulhanjaconversiondialog.ui"_ustr, + u"HangulHanjaConversionDialog"_ustr) + , m_bDocumentMode(true) + , m_xFind(m_xBuilder->weld_button(u"find"_ustr)) + , m_xIgnore(m_xBuilder->weld_button(u"ignore"_ustr)) + , m_xIgnoreAll(m_xBuilder->weld_button(u"ignoreall"_ustr)) + , m_xReplace(m_xBuilder->weld_button(u"replace"_ustr)) + , m_xReplaceAll(m_xBuilder->weld_button(u"replaceall"_ustr)) + , m_xOptions(m_xBuilder->weld_button(u"options"_ustr)) + , m_xSuggestions(new SuggestionDisplay(*m_xBuilder)) + , m_xSimpleConversion(m_xBuilder->weld_radio_button(u"simpleconversion"_ustr)) + , m_xHangulBracketed(m_xBuilder->weld_radio_button(u"hangulbracket"_ustr)) + , m_xHanjaBracketed(m_xBuilder->weld_radio_button(u"hanjabracket"_ustr)) + , m_xWordInput(m_xBuilder->weld_entry(u"wordinput"_ustr)) + , m_xOriginalWord(m_xBuilder->weld_label(u"originalword"_ustr)) + , m_xHanjaAbove(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hanja_above"_ustr), + m_xBuilder->weld_image(u"hanja_above_img"_ustr))) + , m_xHanjaBelow(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hanja_below"_ustr), + m_xBuilder->weld_image(u"hanja_below_img"_ustr))) + , m_xHangulAbove(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hangul_above"_ustr), + m_xBuilder->weld_image(u"hangul_above_img"_ustr))) + , m_xHangulBelow(new RubyRadioButton(m_xBuilder->weld_radio_button(u"hangul_below"_ustr), + m_xBuilder->weld_image(u"hangul_below_img"_ustr))) + , m_xHangulOnly(m_xBuilder->weld_check_button(u"hangulonly"_ustr)) + , m_xHanjaOnly(m_xBuilder->weld_check_button(u"hanjaonly"_ustr)) + , m_xReplaceByChar(m_xBuilder->weld_check_button(u"replacebychar"_ustr)) +{ + m_xSuggestions->set_size_request(m_xOriginalWord->get_approximate_digit_width() * 42, + m_xOriginalWord->get_text_height() * 5); + + const OUString sHangul(CuiResId(RID_CUISTR_HANGUL)); + const OUString sHanja(CuiResId(RID_CUISTR_HANJA)); + m_xHanjaAbove->init(sHangul, sHanja, PseudoRubyText::eAbove); + m_xHanjaBelow->init(sHangul, sHanja, PseudoRubyText::eBelow); + m_xHangulAbove->init(sHanja, sHangul, PseudoRubyText::eAbove); + m_xHangulBelow->init(sHanja, sHangul, PseudoRubyText::eBelow); + + m_xWordInput->connect_changed(LINK(this, HangulHanjaConversionDialog, OnSuggestionModified)); + m_xSuggestions->SetSelectHdl(LINK(this, HangulHanjaConversionDialog, OnSuggestionSelected)); + m_xReplaceByChar->connect_toggled(LINK(this, HangulHanjaConversionDialog, ClickByCharacterHdl)); + m_xHangulOnly->connect_toggled( + LINK(this, HangulHanjaConversionDialog, OnConversionDirectionClicked)); + m_xHanjaOnly->connect_toggled( + LINK(this, HangulHanjaConversionDialog, OnConversionDirectionClicked)); + m_xOptions->connect_clicked(LINK(this, HangulHanjaConversionDialog, OnOption)); + + // initial focus + FocusSuggestion(); + + // initial control values + m_xSimpleConversion->set_active(true); + + m_xSuggestions->SetHelpIds(); +} + +HangulHanjaConversionDialog::~HangulHanjaConversionDialog() {} + +void HangulHanjaConversionDialog::FillSuggestions(const css::uno::Sequence& _rSuggestions) +{ + m_xSuggestions->Clear(); + for (auto const& suggestion : _rSuggestions) + m_xSuggestions->InsertEntry(suggestion); + + // select the first suggestion, and fill in the suggestion edit field + OUString sFirstSuggestion; + if (m_xSuggestions->GetEntryCount()) + { + sFirstSuggestion = m_xSuggestions->GetEntry(0); + m_xSuggestions->SelectEntryPos(0); + } + m_xWordInput->set_text(sFirstSuggestion); + m_xWordInput->save_value(); + OnSuggestionModified(*m_xWordInput); +} + +void HangulHanjaConversionDialog::SetOptionsChangedHdl(const Link& rHdl) +{ + m_aOptionsChangedLink = rHdl; +} + +void HangulHanjaConversionDialog::SetIgnoreHdl(const Link& rHdl) +{ + m_xIgnore->connect_clicked(rHdl); +} + +void HangulHanjaConversionDialog::SetIgnoreAllHdl(const Link& rHdl) +{ + m_xIgnoreAll->connect_clicked(rHdl); +} + +void HangulHanjaConversionDialog::SetChangeHdl(const Link& rHdl) +{ + m_xReplace->connect_clicked(rHdl); +} + +void HangulHanjaConversionDialog::SetChangeAllHdl(const Link& rHdl) +{ + m_xReplaceAll->connect_clicked(rHdl); +} + +void HangulHanjaConversionDialog::SetFindHdl(const Link& rHdl) +{ + m_xFind->connect_clicked(rHdl); +} + +void HangulHanjaConversionDialog::SetConversionFormatChangedHdl( + const Link& rHdl) +{ + m_xSimpleConversion->connect_toggled(rHdl); + m_xHangulBracketed->connect_toggled(rHdl); + m_xHanjaBracketed->connect_toggled(rHdl); + m_xHanjaAbove->connect_toggled(rHdl); + m_xHanjaBelow->connect_toggled(rHdl); + m_xHangulAbove->connect_toggled(rHdl); + m_xHangulBelow->connect_toggled(rHdl); +} + +void HangulHanjaConversionDialog::SetClickByCharacterHdl(const Link& _rHdl) +{ + m_aClickByCharacterLink = _rHdl; +} + +IMPL_LINK_NOARG(HangulHanjaConversionDialog, OnSuggestionSelected, SuggestionDisplay&, void) +{ + m_xWordInput->set_text(m_xSuggestions->GetSelectedEntry()); + OnSuggestionModified(*m_xWordInput); +} + +static int GetCodePointCount(std::u16string_view sText) +{ + sal_Int32 nCount = 0; + sal_Int32 nIndex = 0; + while (o3tl::make_unsigned(nIndex) < sText.size()) + { + o3tl::iterateCodePoints(sText, &nIndex); + nCount++; + } + + return nCount; +} + +IMPL_LINK_NOARG(HangulHanjaConversionDialog, OnSuggestionModified, weld::TextWidget&, void) +{ + m_xFind->set_sensitive(m_xWordInput->get_value_changed_from_saved()); + + bool bSameLen = GetCodePointCount(m_xWordInput->get_text()) + == GetCodePointCount(m_xOriginalWord->get_label()); + m_xReplace->set_sensitive(m_bDocumentMode && bSameLen); + m_xReplaceAll->set_sensitive(m_bDocumentMode && bSameLen); +} + +IMPL_LINK(HangulHanjaConversionDialog, ClickByCharacterHdl, weld::Toggleable&, rBox, void) +{ + m_aClickByCharacterLink.Call(rBox); + bool bByCharacter = rBox.get_active(); + m_xSuggestions->DisplayListBox(!bByCharacter); +} + +IMPL_LINK(HangulHanjaConversionDialog, OnConversionDirectionClicked, weld::Toggleable&, rBox, void) +{ + weld::CheckButton* pOtherBox = nullptr; + if (&rBox == m_xHangulOnly.get()) + pOtherBox = m_xHanjaOnly.get(); + else + pOtherBox = m_xHangulOnly.get(); + bool bBoxChecked = rBox.get_active(); + if (bBoxChecked) + pOtherBox->set_active(false); + pOtherBox->set_sensitive(!bBoxChecked); +} + +IMPL_LINK_NOARG(HangulHanjaConversionDialog, OnOption, weld::Button&, void) +{ + HangulHanjaOptionsDialog aOptDlg(m_xDialog.get()); + aOptDlg.run(); + m_aOptionsChangedLink.Call(nullptr); +} + +OUString HangulHanjaConversionDialog::GetCurrentString() const +{ + return m_xOriginalWord->get_label(); +} + +void HangulHanjaConversionDialog::FocusSuggestion() { m_xWordInput->grab_focus(); } + +void HangulHanjaConversionDialog::SetCurrentString(const OUString& _rNewString, + const Sequence& _rSuggestions, + bool _bOriginatesFromDocument) +{ + m_xOriginalWord->set_label(_rNewString); + + bool bOldDocumentMode = m_bDocumentMode; + m_bDocumentMode = _bOriginatesFromDocument; // before FillSuggestions! + FillSuggestions(_rSuggestions); + + m_xIgnoreAll->set_sensitive(m_bDocumentMode); + + // switch the def button depending if we're working for document text + if (bOldDocumentMode == m_bDocumentMode) + return; + + weld::Button* pOldDefButton = nullptr; + weld::Button* pNewDefButton = nullptr; + if (m_bDocumentMode) + { + pOldDefButton = m_xFind.get(); + pNewDefButton = m_xReplace.get(); + } + else + { + pOldDefButton = m_xReplace.get(); + pNewDefButton = m_xFind.get(); + } + + m_xDialog->change_default_button(pOldDefButton, pNewDefButton); +} + +OUString HangulHanjaConversionDialog::GetCurrentSuggestion() const +{ + return m_xWordInput->get_text(); +} + +void HangulHanjaConversionDialog::SetByCharacter(bool _bByCharacter) +{ + m_xReplaceByChar->set_active(_bByCharacter); + m_xSuggestions->DisplayListBox(!_bByCharacter); +} + +void HangulHanjaConversionDialog::SetConversionDirectionState( + bool _bTryBothDirections, HHC::ConversionDirection ePrimaryConversionDirection) +{ + // default state: try both direction + m_xHangulOnly->set_active(false); + m_xHangulOnly->set_sensitive(true); + m_xHanjaOnly->set_active(false); + m_xHanjaOnly->set_sensitive(true); + + if (!_bTryBothDirections) + { + weld::CheckButton* pBox = ePrimaryConversionDirection == HHC::eHangulToHanja + ? m_xHangulOnly.get() + : m_xHanjaOnly.get(); + pBox->set_active(true); + OnConversionDirectionClicked(*pBox); } } +bool HangulHanjaConversionDialog::GetUseBothDirections() const +{ + return !m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active(); +} + +HHC::ConversionDirection +HangulHanjaConversionDialog::GetDirection(HHC::ConversionDirection eDefaultDirection) const +{ + HHC::ConversionDirection eDirection = eDefaultDirection; + if (m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active()) + eDirection = HHC::eHangulToHanja; + else if (!m_xHangulOnly->get_active() && m_xHanjaOnly->get_active()) + eDirection = HHC::eHanjaToHangul; + return eDirection; +} + +void HangulHanjaConversionDialog::SetConversionFormat(HHC::ConversionFormat _eType) +{ + switch (_eType) + { + case HHC::eSimpleConversion: + m_xSimpleConversion->set_active(true); + break; + case HHC::eHangulBracketed: + m_xHangulBracketed->set_active(true); + break; + case HHC::eHanjaBracketed: + m_xHanjaBracketed->set_active(true); + break; + case HHC::eRubyHanjaAbove: + m_xHanjaAbove->set_active(true); + break; + case HHC::eRubyHanjaBelow: + m_xHanjaBelow->set_active(true); + break; + case HHC::eRubyHangulAbove: + m_xHangulAbove->set_active(true); + break; + case HHC::eRubyHangulBelow: + m_xHangulBelow->set_active(true); + break; + default: + OSL_FAIL("HangulHanjaConversionDialog::SetConversionFormat: unknown type!"); + } +} + +HHC::ConversionFormat HangulHanjaConversionDialog::GetConversionFormat() const +{ + if (m_xSimpleConversion->get_active()) + return HHC::eSimpleConversion; + if (m_xHangulBracketed->get_active()) + return HHC::eHangulBracketed; + if (m_xHanjaBracketed->get_active()) + return HHC::eHanjaBracketed; + if (m_xHanjaAbove->get_active()) + return HHC::eRubyHanjaAbove; + if (m_xHanjaBelow->get_active()) + return HHC::eRubyHanjaBelow; + if (m_xHangulAbove->get_active()) + return HHC::eRubyHangulAbove; + if (m_xHangulBelow->get_active()) + return HHC::eRubyHangulBelow; + + OSL_FAIL("HangulHanjaConversionDialog::GetConversionFormat: no radio checked?"); + return HHC::eSimpleConversion; +} + +void HangulHanjaConversionDialog::EnableRubySupport(bool bVal) +{ + m_xHanjaAbove->set_sensitive(bVal); + m_xHanjaBelow->set_sensitive(bVal); + m_xHangulAbove->set_sensitive(bVal); + m_xHangulBelow->set_sensitive(bVal); +} + +void HangulHanjaOptionsDialog::Init() +{ + if (!m_xConversionDictionaryList.is()) + { + m_xConversionDictionaryList + = ConversionDictionaryList::create(::comphelper::getProcessComponentContext()); + } + + m_aDictList.clear(); + m_xDictsLB->clear(); + + Reference xNameCont = m_xConversionDictionaryList->getDictionaryContainer(); + if (xNameCont.is()) + { + for (auto& name : xNameCont->getElementNames()) + { + Any aAny(xNameCont->getByName(name)); + Reference xDic; + if ((aAny >>= xDic) && xDic.is()) + { + if (LANGUAGE_KOREAN == LanguageTag(xDic->getLocale()).getLanguageType()) + { + m_aDictList.push_back(xDic); + AddDict(xDic->getName(), xDic->isActive()); + } + } + } + } + if (m_xDictsLB->n_children()) + m_xDictsLB->select(0); +} + +IMPL_LINK_NOARG(HangulHanjaOptionsDialog, OkHdl, weld::Button&, void) +{ + sal_uInt32 nCnt = m_aDictList.size(); + sal_uInt32 n = 0; + sal_uInt32 nActiveDics = 0; + Sequence aActiveDics; + + aActiveDics.realloc(nCnt); + OUString* pActActiveDic = aActiveDics.getArray(); + + while (nCnt) + { + Reference xDict = m_aDictList[n]; + + DBG_ASSERT(xDict.is(), "-HangulHanjaOptionsDialog::OkHdl(): someone is evaporated..."); + + bool bActive = m_xDictsLB->get_toggle(n) == TRISTATE_TRUE; + xDict->setActive(bActive); + Reference xFlush(xDict, uno::UNO_QUERY); + if (xFlush.is()) + xFlush->flush(); + + if (bActive) + { + pActActiveDic[nActiveDics] = xDict->getName(); + ++nActiveDics; + } + + ++n; + --nCnt; + } + + // save configuration + aActiveDics.realloc(nActiveDics); + Any aTmp; + SvtLinguConfig aLngCfg; + aTmp <<= aActiveDics; + aLngCfg.SetProperty(UPH_ACTIVE_CONVERSION_DICTIONARIES, aTmp); + + aTmp <<= m_xIgnorepostCB->get_active(); + aLngCfg.SetProperty(UPH_IS_IGNORE_POST_POSITIONAL_WORD, aTmp); + + aTmp <<= m_xShowrecentlyfirstCB->get_active(); + aLngCfg.SetProperty(UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, aTmp); + + aTmp <<= m_xAutoreplaceuniqueCB->get_active(); + aLngCfg.SetProperty(UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES, aTmp); + + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DictsLB_SelectHdl, weld::ItemView&, void) +{ + bool bSel = m_xDictsLB->get_selected_index() != -1; + + m_xEditPB->set_sensitive(bSel); + m_xDeletePB->set_sensitive(bSel); +} + +IMPL_LINK_NOARG(HangulHanjaOptionsDialog, NewDictHdl, weld::Button&, void) +{ + OUString aName; + HangulHanjaNewDictDialog aNewDlg(m_xDialog.get()); + aNewDlg.run(); + if (!aNewDlg.GetName(aName)) + return; + + if (!m_xConversionDictionaryList.is()) + return; + + try + { + Reference xDic = m_xConversionDictionaryList->addNewDictionary( + aName, LanguageTag::convertToLocale(LANGUAGE_KOREAN), + ConversionDictionaryType::HANGUL_HANJA); + + if (xDic.is()) + { + //adapt local caches: + m_aDictList.push_back(xDic); + AddDict(xDic->getName(), xDic->isActive()); + } + } + catch (const ElementExistException&) + { + } + catch (const NoSupportException&) + { + } +} + +IMPL_LINK_NOARG(HangulHanjaOptionsDialog, EditDictHdl, weld::Button&, void) +{ + int nEntry = m_xDictsLB->get_selected_index(); + DBG_ASSERT(nEntry != -1, "+HangulHanjaEditDictDialog::EditDictHdl(): call of edit should not " + "be possible with no selection!"); + if (nEntry != -1) + { + HangulHanjaEditDictDialog aEdDlg(m_xDialog.get(), m_aDictList, nEntry); + aEdDlg.run(); + } +} + +IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DeleteDictHdl, weld::Button&, void) +{ + int nSelPos = m_xDictsLB->get_selected_index(); + if (nSelPos == -1) + return; + + Reference xDic(m_aDictList[nSelPos]); + if (!(m_xConversionDictionaryList.is() && xDic.is())) + return; + + Reference xNameCont = m_xConversionDictionaryList->getDictionaryContainer(); + if (!xNameCont.is()) + return; + + try + { + xNameCont->removeByName(xDic->getName()); + + //adapt local caches: + m_aDictList.erase(m_aDictList.begin() + nSelPos); + m_xDictsLB->remove(nSelPos); + } + catch (const ElementExistException&) + { + } + catch (const NoSupportException&) + { + } +} + +HangulHanjaOptionsDialog::HangulHanjaOptionsDialog(weld::Window* pParent) + : GenericDialogController(pParent, u"cui/ui/hangulhanjaoptdialog.ui"_ustr, + u"HangulHanjaOptDialog"_ustr) + , m_xDictsLB(m_xBuilder->weld_tree_view(u"dicts"_ustr)) + , m_xIgnorepostCB(m_xBuilder->weld_check_button(u"ignorepost"_ustr)) + , m_xShowrecentlyfirstCB(m_xBuilder->weld_check_button(u"showrecentfirst"_ustr)) + , m_xAutoreplaceuniqueCB(m_xBuilder->weld_check_button(u"autoreplaceunique"_ustr)) + , m_xNewPB(m_xBuilder->weld_button(u"new"_ustr)) + , m_xEditPB(m_xBuilder->weld_button(u"edit"_ustr)) + , m_xDeletePB(m_xBuilder->weld_button(u"delete"_ustr)) + , m_xOkPB(m_xBuilder->weld_button(u"ok"_ustr)) +{ + m_xDictsLB->set_size_request(m_xDictsLB->get_approximate_digit_width() * 32, + m_xDictsLB->get_height_rows(5)); + + m_xDictsLB->enable_toggle_buttons(); + + m_xDictsLB->connect_selection_changed(LINK(this, HangulHanjaOptionsDialog, DictsLB_SelectHdl)); + + m_xOkPB->connect_clicked(LINK(this, HangulHanjaOptionsDialog, OkHdl)); + m_xNewPB->connect_clicked(LINK(this, HangulHanjaOptionsDialog, NewDictHdl)); + m_xEditPB->connect_clicked(LINK(this, HangulHanjaOptionsDialog, EditDictHdl)); + m_xDeletePB->connect_clicked(LINK(this, HangulHanjaOptionsDialog, DeleteDictHdl)); + + SvtLinguConfig aLngCfg; + Any aTmp; + bool bVal = bool(); + aTmp = aLngCfg.GetProperty(UPH_IS_IGNORE_POST_POSITIONAL_WORD); + if (aTmp >>= bVal) + m_xIgnorepostCB->set_active(bVal); + + aTmp = aLngCfg.GetProperty(UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST); + if (aTmp >>= bVal) + m_xShowrecentlyfirstCB->set_active(bVal); + + aTmp = aLngCfg.GetProperty(UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES); + if (aTmp >>= bVal) + m_xAutoreplaceuniqueCB->set_active(bVal); + + Init(); +} + +HangulHanjaOptionsDialog::~HangulHanjaOptionsDialog() {} + +void HangulHanjaOptionsDialog::AddDict(const OUString& rName, bool bChecked) +{ + m_xDictsLB->append(); + int nRow = m_xDictsLB->n_children() - 1; + m_xDictsLB->set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xDictsLB->set_text(nRow, rName, 0); + m_xDictsLB->set_id(nRow, rName); +} + +IMPL_LINK_NOARG(HangulHanjaNewDictDialog, OKHdl, weld::Button&, void) +{ + OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ')); + + m_bEntered = !aName.isEmpty(); + if (m_bEntered) + m_xDictNameED->set_text(aName); // do this in case of trailing chars have been deleted + + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(HangulHanjaNewDictDialog, ModifyHdl, weld::TextWidget&, void) +{ + OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ')); + + m_xOkBtn->set_sensitive(!aName.isEmpty()); +} + +HangulHanjaNewDictDialog::HangulHanjaNewDictDialog(weld::Window* pParent) + : GenericDialogController(pParent, u"cui/ui/hangulhanjaadddialog.ui"_ustr, + u"HangulHanjaAddDialog"_ustr) + , m_bEntered(false) + , m_xOkBtn(m_xBuilder->weld_button(u"ok"_ustr)) + , m_xDictNameED(m_xBuilder->weld_entry(u"entry"_ustr)) +{ + m_xOkBtn->connect_clicked(LINK(this, HangulHanjaNewDictDialog, OKHdl)); + m_xDictNameED->connect_changed(LINK(this, HangulHanjaNewDictDialog, ModifyHdl)); +} + +HangulHanjaNewDictDialog::~HangulHanjaNewDictDialog() {} + +bool HangulHanjaNewDictDialog::GetName(OUString& _rRetName) const +{ + if (m_bEntered) + _rRetName = comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '); + + return m_bEntered; +} + +class SuggestionList +{ +private: +protected: + std::vector m_vElements; + sal_uInt16 m_nNumOfEntries; + // index of the internal iterator, used for First() and Next() methods + sal_uInt16 m_nAct; + + const OUString* Next_(); + +public: + SuggestionList(); + ~SuggestionList(); + + void Set(const OUString& _rElement, sal_uInt16 _nNumOfElement); + void Reset(sal_uInt16 _nNumOfElement); + const OUString& Get(sal_uInt16 _nNumOfElement) const; + void Clear(); + + const OUString* First(); + const OUString* Next(); + + sal_uInt16 GetCount() const { return m_nNumOfEntries; } +}; + +SuggestionList::SuggestionList() + : m_vElements(MAXNUM_SUGGESTIONS) +{ + m_nAct = m_nNumOfEntries = 0; +} + +SuggestionList::~SuggestionList() { Clear(); } + +void SuggestionList::Set(const OUString& _rElement, sal_uInt16 _nNumOfElement) +{ + m_vElements[_nNumOfElement] = _rElement; + ++m_nNumOfEntries; +} + +void SuggestionList::Reset(sal_uInt16 _nNumOfElement) +{ + m_vElements[_nNumOfElement].clear(); + --m_nNumOfEntries; +} + +const OUString& SuggestionList::Get(sal_uInt16 _nNumOfElement) const +{ + return m_vElements[_nNumOfElement]; +} + +void SuggestionList::Clear() +{ + if (m_nNumOfEntries) + { + for (auto& vElement : m_vElements) + vElement.clear(); + m_nNumOfEntries = m_nAct = 0; + } +} + +const OUString* SuggestionList::Next_() +{ + while (m_nAct < m_vElements.size()) + { + auto& s = m_vElements[m_nAct]; + if (!s.isEmpty()) + return &s; + ++m_nAct; + } + + return nullptr; +} + +const OUString* SuggestionList::First() +{ + m_nAct = 0; + return Next_(); +} + +const OUString* SuggestionList::Next() +{ + const OUString* pRet; + + if (m_nAct < m_nNumOfEntries) + { + ++m_nAct; + pRet = Next_(); + } + else + pRet = nullptr; + + return pRet; +} + +bool SuggestionEdit::ShouldScroll(bool _bUp) const +{ + bool bRet = false; + + if (_bUp) + { + if (!m_pPrev) + bRet = m_pScrollBar->vadjustment_get_value() > 0; + } + else + { + if (!m_pNext) + bRet = m_pScrollBar->vadjustment_get_value() + < (m_pScrollBar->vadjustment_get_upper() - 4); + } + + return bRet; +} + +void SuggestionEdit::DoJump(bool _bUp) +{ + m_pScrollBar->vadjustment_set_value(m_pScrollBar->vadjustment_get_value() + (_bUp ? -1 : 1)); + m_pParent->UpdateScrollbar(); +} + +SuggestionEdit::SuggestionEdit(std::unique_ptr xEntry, + HangulHanjaEditDictDialog* pParent) + : m_pParent(pParent) + , m_pPrev(nullptr) + , m_pNext(nullptr) + , m_pScrollBar(nullptr) + , m_xEntry(std::move(xEntry)) +{ + m_xEntry->connect_key_press(LINK(this, SuggestionEdit, KeyInputHdl)); +} + +IMPL_LINK(SuggestionEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + bool bHandled = false; + + const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); + sal_uInt16 nMod = rKeyCode.GetModifier(); + sal_uInt16 nCode = rKeyCode.GetCode(); + if (nCode == KEY_TAB && (!nMod || KEY_SHIFT == nMod)) + { + bool bUp = KEY_SHIFT == nMod; + if (ShouldScroll(bUp)) + { + DoJump(bUp); + m_xEntry->select_region(0, -1); + // Tab-travel doesn't really happen, so emulate it by setting a selection manually + bHandled = true; + } + } + else if (KEY_UP == nCode || KEY_DOWN == nCode) + { + bool bUp = KEY_UP == nCode; + if (ShouldScroll(bUp)) + { + DoJump(bUp); + bHandled = true; + } + else if (bUp) + { + if (m_pPrev) + { + m_pPrev->grab_focus(); + bHandled = true; + } + } + else if (m_pNext) + { + m_pNext->grab_focus(); + bHandled = true; + } + } + + return bHandled; +} + +void SuggestionEdit::init(weld::ScrolledWindow* pScrollBar, SuggestionEdit* pPrev, + SuggestionEdit* pNext) +{ + m_pScrollBar = pScrollBar; + m_pPrev = pPrev; + m_pNext = pNext; +} + +namespace +{ +bool GetConversions(const Reference& _xDict, const OUString& _rOrg, + Sequence& _rEntries) +{ + bool bRet = false; + if (_xDict.is() && !_rOrg.isEmpty()) + { + try + { + _rEntries + = _xDict->getConversions(_rOrg, 0, _rOrg.getLength(), ConversionDirection_FROM_LEFT, + css::i18n::TextConversionOption::NONE); + bRet = _rEntries.hasElements(); + } + catch (const IllegalArgumentException&) + { + } + } + + return bRet; +} +} + +IMPL_LINK_NOARG(HangulHanjaEditDictDialog, ScrollHdl, weld::ScrolledWindow&, void) +{ + UpdateScrollbar(); +} + +IMPL_LINK_NOARG(HangulHanjaEditDictDialog, OriginalModifyHdl, weld::ComboBox&, void) +{ + m_bModifiedOriginal = true; + m_aOriginal = comphelper::string::stripEnd(m_xOriginalLB->get_active_text(), ' '); + + UpdateSuggestions(); + UpdateButtonStates(); +} + +IMPL_LINK(HangulHanjaEditDictDialog, EditModifyHdl1, weld::TextWidget&, rEdit, void) +{ + EditModify(&rEdit, 0); +} + +IMPL_LINK(HangulHanjaEditDictDialog, EditModifyHdl2, weld::TextWidget&, rEdit, void) +{ + EditModify(&rEdit, 1); +} + +IMPL_LINK(HangulHanjaEditDictDialog, EditModifyHdl3, weld::TextWidget&, rEdit, void) +{ + EditModify(&rEdit, 2); +} + +IMPL_LINK(HangulHanjaEditDictDialog, EditModifyHdl4, weld::TextWidget&, rEdit, void) +{ + EditModify(&rEdit, 3); +} + +IMPL_LINK_NOARG(HangulHanjaEditDictDialog, BookLBSelectHdl, weld::ComboBox&, void) +{ + InitEditDictDialog(m_xBookLB->get_active()); +} + +IMPL_LINK_NOARG(HangulHanjaEditDictDialog, NewPBPushHdl, weld::Button&, void) +{ + DBG_ASSERT(m_xSuggestions, + "-HangulHanjaEditDictDialog::NewPBPushHdl(): no suggestions... search in hell..."); + Reference xDict = m_rDictList[m_nCurrentDict]; + if (xDict.is() && m_xSuggestions) + { + //delete old entry + bool bRemovedSomething = DeleteEntryFromDictionary(xDict); + + OUString aLeft(m_aOriginal); + const OUString* pRight = m_xSuggestions->First(); + bool bAddedSomething = false; + while (pRight) + { + try + { + //add new entry + xDict->addEntry(aLeft, *pRight); + bAddedSomething = true; + } + catch (const IllegalArgumentException&) + { + } + catch (const ElementExistException&) + { + } + + pRight = m_xSuggestions->Next(); + } + + if (bAddedSomething || bRemovedSomething) + InitEditDictDialog(m_nCurrentDict); + } + else + { + SAL_INFO("cui.dialogs", "dictionary faded away..."); + } +} + +bool HangulHanjaEditDictDialog::DeleteEntryFromDictionary( + const Reference& xDict) +{ + bool bRemovedSomething = false; + if (xDict.is()) + { + OUString aOrg(m_aOriginal); + Sequence aEntries; + GetConversions(xDict, m_aOriginal, aEntries); + + sal_uInt32 n = aEntries.getLength(); + OUString* pEntry = aEntries.getArray(); + while (n) + { + try + { + xDict->removeEntry(aOrg, *pEntry); + bRemovedSomething = true; + } + catch (const NoSuchElementException&) + { // can not be... + } + + ++pEntry; + --n; + } + } + return bRemovedSomething; +} + +IMPL_LINK_NOARG(HangulHanjaEditDictDialog, DeletePBPushHdl, weld::Button&, void) +{ + if (DeleteEntryFromDictionary(m_rDictList[m_nCurrentDict])) + { + m_aOriginal.clear(); + m_bModifiedOriginal = true; + InitEditDictDialog(m_nCurrentDict); + } +} + +void HangulHanjaEditDictDialog::InitEditDictDialog(sal_uInt32 nSelDict) +{ + if (m_xSuggestions) + m_xSuggestions->Clear(); + + if (m_nCurrentDict != nSelDict) + { + m_nCurrentDict = nSelDict; + m_aOriginal.clear(); + m_bModifiedOriginal = true; + } + + UpdateOriginalLB(); + + m_xOriginalLB->set_entry_text(!m_aOriginal.isEmpty() ? m_aOriginal : m_aEditHintText); + m_xOriginalLB->select_entry_region(0, -1); + m_xOriginalLB->grab_focus(); + + UpdateSuggestions(); + UpdateButtonStates(); +} + +void HangulHanjaEditDictDialog::UpdateOriginalLB() +{ + m_xOriginalLB->clear(); + Reference xDict = m_rDictList[m_nCurrentDict]; + if (xDict.is()) + { + Sequence aEntries = xDict->getConversionEntries(ConversionDirection_FROM_LEFT); + sal_uInt32 n = aEntries.getLength(); + OUString* pEntry = aEntries.getArray(); + while (n) + { + m_xOriginalLB->append_text(*pEntry); + + ++pEntry; + --n; + } + } + else + { + SAL_INFO("cui.dialogs", "dictionary faded away..."); + } +} + +void HangulHanjaEditDictDialog::UpdateButtonStates() +{ + bool bHaveValidOriginalString = !m_aOriginal.isEmpty() && m_aOriginal != m_aEditHintText; + bool bNew = bHaveValidOriginalString && m_xSuggestions && m_xSuggestions->GetCount() > 0; + bNew = bNew && (m_bModifiedSuggestions || m_bModifiedOriginal); + + m_xNewPB->set_sensitive(bNew); + m_xDeletePB->set_sensitive(!m_bModifiedOriginal && bHaveValidOriginalString); +} + +void HangulHanjaEditDictDialog::UpdateSuggestions() +{ + Sequence aEntries; + bool bFound = GetConversions(m_rDictList[m_nCurrentDict], m_aOriginal, aEntries); + if (bFound) + { + m_bModifiedOriginal = false; + + if (m_xSuggestions) + m_xSuggestions->Clear(); + + //fill found entries into boxes + if (aEntries.hasElements()) + { + if (!m_xSuggestions) + m_xSuggestions.reset(new SuggestionList); + + for (sal_Int32 n = 0; n < aEntries.getLength(); ++n) + m_xSuggestions->Set(aEntries[n], n); + } + m_bModifiedSuggestions = false; + } + + m_xScrollSB->vadjustment_set_value(0); + UpdateScrollbar(); // will force edits to be filled new +} + +void HangulHanjaEditDictDialog::SetEditText(SuggestionEdit& rEdit, sal_uInt16 nEntryNum) +{ + OUString aStr; + if (m_xSuggestions) + { + aStr = m_xSuggestions->Get(nEntryNum); + } + + rEdit.set_text(aStr); +} + +void HangulHanjaEditDictDialog::EditModify(const weld::TextWidget* pEdit, sal_uInt8 _nEntryOffset) +{ + m_bModifiedSuggestions = true; + + OUString aTxt(pEdit->get_text()); + sal_uInt16 nEntryNum = m_nTopPos + _nEntryOffset; + if (aTxt.isEmpty()) + { + //reset suggestion + if (m_xSuggestions) + m_xSuggestions->Reset(nEntryNum); + } + else + { + //set suggestion + if (!m_xSuggestions) + m_xSuggestions.reset(new SuggestionList); + m_xSuggestions->Set(aTxt, nEntryNum); + } + + UpdateButtonStates(); +} + +HangulHanjaEditDictDialog::HangulHanjaEditDictDialog(weld::Window* pParent, HHDictList& _rDictList, + sal_uInt32 nSelDict) + : GenericDialogController(pParent, u"cui/ui/hangulhanjaeditdictdialog.ui"_ustr, + u"HangulHanjaEditDictDialog"_ustr) + , m_aEditHintText(CuiResId(RID_CUISTR_EDITHINT)) + , m_rDictList(_rDictList) + , m_nCurrentDict(0xFFFFFFFF) + , m_nTopPos(0) + , m_bModifiedSuggestions(false) + , m_bModifiedOriginal(false) + , m_xBookLB(m_xBuilder->weld_combo_box(u"book"_ustr)) + , m_xOriginalLB(m_xBuilder->weld_combo_box(u"original"_ustr)) + , m_xEdit1(new SuggestionEdit(m_xBuilder->weld_entry(u"edit1"_ustr), this)) + , m_xEdit2(new SuggestionEdit(m_xBuilder->weld_entry(u"edit2"_ustr), this)) + , m_xEdit3(new SuggestionEdit(m_xBuilder->weld_entry(u"edit3"_ustr), this)) + , m_xEdit4(new SuggestionEdit(m_xBuilder->weld_entry(u"edit4"_ustr), this)) + , m_xContents(m_xBuilder->weld_widget(u"box"_ustr)) + , m_xScrollSB(m_xBuilder->weld_scrolled_window(u"scrollbar"_ustr, true)) + , m_xNewPB(m_xBuilder->weld_button(u"new"_ustr)) + , m_xDeletePB(m_xBuilder->weld_button(u"delete"_ustr)) +{ + Size aSize(m_xContents->get_preferred_size()); + m_xScrollSB->set_size_request(-1, aSize.Height()); + + m_xEdit1->init(m_xScrollSB.get(), nullptr, m_xEdit2.get()); + m_xEdit2->init(m_xScrollSB.get(), m_xEdit1.get(), m_xEdit3.get()); + m_xEdit3->init(m_xScrollSB.get(), m_xEdit2.get(), m_xEdit4.get()); + m_xEdit4->init(m_xScrollSB.get(), m_xEdit3.get(), nullptr); + + m_xOriginalLB->connect_changed(LINK(this, HangulHanjaEditDictDialog, OriginalModifyHdl)); + + m_xNewPB->connect_clicked(LINK(this, HangulHanjaEditDictDialog, NewPBPushHdl)); + m_xNewPB->set_sensitive(false); + + m_xDeletePB->connect_clicked(LINK(this, HangulHanjaEditDictDialog, DeletePBPushHdl)); + m_xDeletePB->set_sensitive(false); + + static_assert(MAXNUM_SUGGESTIONS >= 5, + "number of suggestions should not under-run the value of 5"); + + // 4 here, because we have 4 edits / page + m_xScrollSB->vadjustment_configure(0, MAXNUM_SUGGESTIONS, 1, 4, 4); + m_xScrollSB->connect_vadjustment_value_changed( + LINK(this, HangulHanjaEditDictDialog, ScrollHdl)); + + m_xEdit1->connect_changed(LINK(this, HangulHanjaEditDictDialog, EditModifyHdl1)); + m_xEdit2->connect_changed(LINK(this, HangulHanjaEditDictDialog, EditModifyHdl2)); + m_xEdit3->connect_changed(LINK(this, HangulHanjaEditDictDialog, EditModifyHdl3)); + m_xEdit4->connect_changed(LINK(this, HangulHanjaEditDictDialog, EditModifyHdl4)); + + m_xBookLB->connect_changed(LINK(this, HangulHanjaEditDictDialog, BookLBSelectHdl)); + sal_uInt32 nDictCnt = m_rDictList.size(); + for (sal_uInt32 n = 0; n < nDictCnt; ++n) + { + Reference xDic(m_rDictList[n]); + OUString aName; + if (xDic.is()) + aName = xDic->getName(); + m_xBookLB->append_text(aName); + } + m_xBookLB->set_active(nSelDict); + + InitEditDictDialog(nSelDict); +} + +HangulHanjaEditDictDialog::~HangulHanjaEditDictDialog() {} + +void HangulHanjaEditDictDialog::UpdateScrollbar() +{ + sal_uInt16 nPos = m_xScrollSB->vadjustment_get_value(); + m_nTopPos = nPos; + + SetEditText(*m_xEdit1, nPos++); + SetEditText(*m_xEdit2, nPos++); + SetEditText(*m_xEdit3, nPos++); + SetEditText(*m_xEdit4, nPos); +} +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/hlmarkwn.cxx b/cui/source/dialogs/hlmarkwn.cxx index 97fa7f760cb3..78ad020efd3a 100644 --- a/cui/source/dialogs/hlmarkwn.cxx +++ b/cui/source/dialogs/hlmarkwn.cxx @@ -20,13 +20,15 @@ #include #include #include -#include +#include #include #include #include #include #include #include +#include +#include // UNO-Stuff #include @@ -364,8 +366,9 @@ int SvxHlinkDlgMarkWnd::FillTree( const uno::Reference< container::XNameAccess > sal_Int32 nOutlineLevel = *o3tl::doAccess(aAny); // pop until the top of stack entry has an outline level less than - // the to be inserted heading outline level - while (nOutlineLevel <= aHeadingsParentEntryStack.top().second) + // the to be inserted heading outline level, but keep the sentinel + while (aHeadingsParentEntryStack.size() > 1 + && nOutlineLevel <= aHeadingsParentEntryStack.top().second) aHeadingsParentEntryStack.pop(); mxLbTree->insert(aHeadingsParentEntryStack.top().first.get(), -1, diff --git a/cui/source/dialogs/hyperlinkdlg.cxx b/cui/source/dialogs/hyperlinkdlg.cxx index 69d6ecee775c..a8e13676f88a 100644 --- a/cui/source/dialogs/hyperlinkdlg.cxx +++ b/cui/source/dialogs/hyperlinkdlg.cxx @@ -43,8 +43,9 @@ HyperlinkDialog::HyperlinkDialog(weld::Window* pParent, SfxChildWindow* /*pChild SfxItemSet* HyperlinkDialog::CreateInputItemSet(const OUString&) { - m_pInputSet = std::make_unique>( - SfxGetpApp()->GetPool()); + m_pInputSet = std::make_unique( + SfxItemSet::makeFixedSfxItemSet( + SfxGetpApp()->GetPool())); return m_pInputSet.get(); } diff --git a/cui/source/dialogs/hyperlinkdoctabpage.cxx b/cui/source/dialogs/hyperlinkdoctabpage.cxx index a61bf932177f..43a714f64ac3 100644 --- a/cui/source/dialogs/hyperlinkdoctabpage.cxx +++ b/cui/source/dialogs/hyperlinkdoctabpage.cxx @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -230,7 +231,7 @@ IMPL_LINK_NOARG(HyperlinkDocTabPage, ModifiedPathHdl_Impl, weld::ComboBox&, void m_xFtFullURL->set_label(maStrURL); } -IMPL_LINK_NOARG(HyperlinkDocTabPage, ModifiedTargetHdl_Impl, weld::Entry&, void) +IMPL_LINK_NOARG(HyperlinkDocTabPage, ModifiedTargetHdl_Impl, weld::TextWidget&, void) { maStrURL = GetCurrentURL(); diff --git a/cui/source/dialogs/hyperlinkinternettabpage.cxx b/cui/source/dialogs/hyperlinkinternettabpage.cxx index d9dbc1a8bd51..346cdee075dd 100644 --- a/cui/source/dialogs/hyperlinkinternettabpage.cxx +++ b/cui/source/dialogs/hyperlinkinternettabpage.cxx @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/cui/source/dialogs/hyperlinknewdoctabpage.cxx b/cui/source/dialogs/hyperlinknewdoctabpage.cxx index 25783af7dc1d..46a32d287eec 100644 --- a/cui/source/dialogs/hyperlinknewdoctabpage.cxx +++ b/cui/source/dialogs/hyperlinknewdoctabpage.cxx @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/cui/source/dialogs/hyperlinktabpagebase.cxx b/cui/source/dialogs/hyperlinktabpagebase.cxx index 0e7f0cfbd908..5c2fad92f063 100644 --- a/cui/source/dialogs/hyperlinktabpagebase.cxx +++ b/cui/source/dialogs/hyperlinktabpagebase.cxx @@ -265,8 +265,9 @@ IMPL_LINK_NOARG(HyperlinkTabPageBase, ClickScriptHdl, weld::Button&, void) if (!m_aMacroTable.empty()) aItem.SetMacroTable(m_aMacroTable); - auto xItemSet = std::make_unique>( - SfxGetpApp()->GetPool()); + auto xItemSet = std::make_unique( + SfxItemSet::makeFixedSfxItemSet( + SfxGetpApp()->GetPool())); xItemSet->Put(aItem); weld::Window* pWin = GetFrameWeld(); diff --git a/cui/source/dialogs/insdlg.cxx b/cui/source/dialogs/insdlg.cxx index 5598bad2378c..ac4c7bfa7cd3 100644 --- a/cui/source/dialogs/insdlg.cxx +++ b/cui/source/dialogs/insdlg.cxx @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include diff --git a/cui/source/dialogs/linkdlg.cxx b/cui/source/dialogs/linkdlg.cxx index 0f34fe753ce8..8bbec8a6eccf 100644 --- a/cui/source/dialogs/linkdlg.cxx +++ b/cui/source/dialogs/linkdlg.cxx @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/cui/source/dialogs/multipat.cxx b/cui/source/dialogs/multipat.cxx index f071fb426284..6ef806d0cb44 100644 --- a/cui/source/dialogs/multipat.cxx +++ b/cui/source/dialogs/multipat.cxx @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -198,7 +197,8 @@ SvxMultiPathDialog::SvxMultiPathDialog(weld::Window* pParent) { m_xRadioLB->set_size_request(m_xRadioLB->get_approximate_digit_width() * 60, m_xRadioLB->get_text_height() * 10); - m_xRadioLB->enable_toggle_buttons(weld::ColumnToggleType::Radio); + m_xRadioLB->enable_toggle_buttons(); + m_xRadioLB->set_toggle_button_type(weld::ColumnToggleType::Radio); m_xRadioLB->connect_toggled(LINK(this, SvxMultiPathDialog, CheckHdl_Impl)); m_xRadioLB->connect_selection_changed(LINK(this, SvxMultiPathDialog, SelectHdl_Impl)); diff --git a/cui/source/dialogs/passwdomdlg.cxx b/cui/source/dialogs/passwdomdlg.cxx index a3720b6d7a0c..6d13c881ef06 100644 --- a/cui/source/dialogs/passwdomdlg.cxx +++ b/cui/source/dialogs/passwdomdlg.cxx @@ -36,9 +36,9 @@ IMPL_LINK_NOARG(PasswordToOpenModifyDialog, OkBtnClickHdl, weld::Button&, void) m_xPasswdToModifyED->get_text().isEmpty(); if (bInvalidState) { - m_xErrorBox.reset(Application::CreateMessageDialog(m_xDialog.get(), - VclMessageType::Warning, VclButtonsType::Ok, - m_bIsPasswordToModify? m_aInvalidStateForOkButton : m_aInvalidStateForOkButton_v2)); + m_xErrorBox = Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, + m_bIsPasswordToModify ? m_aInvalidStateForOkButton : m_aInvalidStateForOkButton_v2); m_xErrorBox->runAsync(m_xErrorBox, [](sal_Int32 /*nResult*/) {}); } else // check for mismatched passwords and password policy @@ -66,9 +66,9 @@ IMPL_LINK_NOARG(PasswordToOpenModifyDialog, OkBtnClickHdl, weld::Button&, void) const int nMismatch = (bToOpenMatch? 0 : 1) + (bToModifyMatch? 0 : 1); if (nMismatch > 0) { - m_xErrorBox.reset(Application::CreateMessageDialog(m_xDialog.get(), - VclMessageType::Warning, VclButtonsType::Ok, - nMismatch == 1 ? m_aOneMismatch : m_aTwoMismatch)); + m_xErrorBox = Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, + nMismatch == 1 ? m_aOneMismatch : m_aTwoMismatch); m_xErrorBox->runAsync(m_xErrorBox, [this, bToOpenMatch, nMismatch](sal_Int32 /*nResult*/) { weld::Entry* pEdit = !bToOpenMatch ? m_xPasswdToOpenED.get() : m_xPasswdToModifyED.get(); @@ -95,8 +95,9 @@ IMPL_LINK_NOARG(PasswordToOpenModifyDialog, OkBtnClickHdl, weld::Button&, void) } } -IMPL_LINK(PasswordToOpenModifyDialog, ChangeHdl, weld::Entry&, rEntry, void) +IMPL_LINK(PasswordToOpenModifyDialog, ChangeHdl, weld::TextWidget&, rTextWidget, void) { + weld::Entry& rEntry = dynamic_cast(rTextWidget); auto aPasswordText = rEntry.get_text(); weld::Label* pIndicator = nullptr; diff --git a/cui/source/dialogs/screenshotannotationdlg.cxx b/cui/source/dialogs/screenshotannotationdlg.cxx index 2c33d76a2294..eeef6c664e5f 100644 --- a/cui/source/dialogs/screenshotannotationdlg.cxx +++ b/cui/source/dialogs/screenshotannotationdlg.cxx @@ -47,11 +47,11 @@ #include #include #include +#include #include +#include #include #include -#include - #include #include #include diff --git a/cui/source/dialogs/scriptdlg.cxx b/cui/source/dialogs/scriptdlg.cxx index 7c7f980f221a..f41ad68b54d2 100644 --- a/cui/source/dialogs/scriptdlg.cxx +++ b/cui/source/dialogs/scriptdlg.cxx @@ -22,17 +22,22 @@ #include #include +#include +#include #include #include #include -#include +#include +#include #include #include #include #include +#include #include +#include #include #include #include @@ -46,12 +51,12 @@ #include #include #include -#include #include #include #include #include +#include #include #include @@ -129,7 +134,7 @@ void SvxScriptOrgDialog::Init( std::u16string_view language ) const Reference< XComponentContext >& xCtx( comphelper::getProcessComponentContext() ); - Sequence< Reference< browse::XBrowseNode > > children; + std::vector< Reference< browse::XBrowseNode > > children; try { @@ -140,7 +145,7 @@ void SvxScriptOrgDialog::Init( std::u16string_view language ) if ( rootNode.is() && rootNode->hasChildNodes() ) { - children = rootNode->getChildNodes(); + children = comphelper::scriptbrowse::getChildNodes(rootNode); } } catch( const Exception& ) @@ -167,7 +172,7 @@ void SvxScriptOrgDialog::Init( std::u16string_view language ) } else { - xDocumentModel.set(getDocumentModel(xCtx, uiName ), UNO_QUERY); + xDocumentModel = getDocumentModel(xCtx, uiName); if ( xDocumentModel.is() ) { @@ -202,33 +207,6 @@ void SvxScriptOrgDialog::Init( std::u16string_view language ) m_xScriptsBox->thaw(); } -Reference< XInterface > -SvxScriptOrgDialog::getDocumentModel( Reference< XComponentContext > const & xCtx, std::u16string_view docName ) -{ - Reference< XInterface > xModel; - Reference< frame::XDesktop2 > desktop = frame::Desktop::create(xCtx); - - Reference< container::XEnumerationAccess > componentsAccess = - desktop->getComponents(); - Reference< container::XEnumeration > components = - componentsAccess->createEnumeration(); - while (components->hasMoreElements()) - { - Reference< frame::XModel > model( - components->nextElement(), UNO_QUERY ); - if ( model.is() ) - { - OUString sTdocUrl = ::comphelper::DocumentInfo::getDocumentTitle( model ); - if( sTdocUrl == docName ) - { - xModel = model; - break; - } - } - } - return xModel; -} - Reference< browse::XBrowseNode > SvxScriptOrgDialog::getLangNodeFromRootNode( Reference< browse::XBrowseNode > const & rootNode, std::u16string_view language ) { @@ -237,7 +215,8 @@ SvxScriptOrgDialog::getLangNodeFromRootNode( Reference< browse::XBrowseNode > co try { auto tryFind = [&] { - const Sequence> children = rootNode->getChildNodes(); + const std::vector> children + = comphelper::scriptbrowse::getChildNodes(rootNode); const auto it = std::find_if(children.begin(), children.end(), [&](const Reference& child) { return child->getName() == language; @@ -271,10 +250,10 @@ void SvxScriptOrgDialog::RequestSubEntries(const weld::TreeIter& rRootEntry, Ref return; } - Sequence< Reference< browse::XBrowseNode > > children; + std::vector< Reference< browse::XBrowseNode > > children; try { - children = node->getChildNodes(); + children = comphelper::scriptbrowse::getSortedChildNodes(node); } catch ( Exception& ) { @@ -452,68 +431,13 @@ void SvxScriptOrgDialog::CheckButtons( Reference< browse::XBrowseNode > const & { if ( node.is() ) { - if ( node->getType() == browse::BrowseNodeTypes::SCRIPT) - { - m_xRunButton->set_sensitive(true); - } - else - { - m_xRunButton->set_sensitive(false); - } - Reference< beans::XPropertySet > xProps( node, UNO_QUERY ); + m_xRunButton->set_sensitive(node->getType() == browse::BrowseNodeTypes::SCRIPT && + Reference::query(node).is()); - if ( !xProps.is() ) - { - m_xEditButton->set_sensitive(false); - m_xDelButton->set_sensitive(false); - m_xCreateButton->set_sensitive(false); - m_xRunButton->set_sensitive(false); - return; - } - - OUString sName(u"Editable"_ustr); - - if ( getBoolProperty( xProps, sName ) ) - { - m_xEditButton->set_sensitive(true); - } - else - { - m_xEditButton->set_sensitive(false); - } - - sName = "Deletable"; - - if ( getBoolProperty( xProps, sName ) ) - { - m_xDelButton->set_sensitive(true); - } - else - { - m_xDelButton->set_sensitive(false); - } - - sName = "Creatable"; - - if ( getBoolProperty( xProps, sName ) ) - { - m_xCreateButton->set_sensitive(true); - } - else - { - m_xCreateButton->set_sensitive(false); - } - - sName = "Renamable"; - - if ( getBoolProperty( xProps, sName ) ) - { - m_xRenameButton->set_sensitive(true); - } - else - { - m_xRenameButton->set_sensitive(false); - } + m_xEditButton->set_sensitive(comphelper::scriptbrowse::isEditable(node)); + m_xDelButton->set_sensitive(comphelper::scriptbrowse::isDeletable(node)); + m_xCreateButton->set_sensitive(comphelper::scriptbrowse::isCreatable(node)); + m_xRenameButton->set_sensitive(comphelper::scriptbrowse::isRenamable(node)); } else { @@ -595,7 +519,11 @@ IMPL_LINK(SvxScriptOrgDialog, ButtonHdl, weld::Button&, rButton, void) if (!xEmbeddedScripts->getAllowMacroExecution()) { - // Please FIXME: Show a message box if AllowMacroExecution is false + std::unique_ptr xBox( + Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, + VclButtonsType::Ok, + SfxResId(STR_CANNOTRUNMACRO))); + xBox->run(); return; } } @@ -645,23 +573,16 @@ IMPL_LINK(SvxScriptOrgDialog, ButtonHdl, weld::Button&, rButton, void) } else if ( &rButton == m_xEditButton.get() ) { - Reference< script::XInvocation > xInv( node, UNO_QUERY ); - if ( xInv.is() ) + StoreCurrentSelection(); + m_xDialog->response(RET_CANCEL); + try { - StoreCurrentSelection(); - m_xDialog->response(RET_CANCEL); - Sequence< Any > args(0); - Sequence< Any > outArgs( 0 ); - Sequence< sal_Int16 > outIndex; - try - { - // ISSUE need code to run script here - xInv->invoke( u"Editable"_ustr, args, outIndex, outArgs ); - } - catch( Exception const & ) - { - TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to invoke" ); - } + // ISSUE need code to run script here + comphelper::scriptbrowse::editNode(node); + } + catch( Exception const & ) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to edit" ); } } else if ( &rButton == m_xCreateButton.get() ) @@ -705,9 +626,8 @@ void SvxScriptOrgDialog::createEntry(const weld::TreeIter& rEntry) Reference< browse::XBrowseNode > aChildNode; Reference< browse::XBrowseNode > node = getBrowseNode( rEntry ); - Reference< script::XInvocation > xInv( node, UNO_QUERY ); - if ( xInv.is() ) + if ( node.is() ) { OUString aNewName; OUString aNewStdName; @@ -726,7 +646,7 @@ void SvxScriptOrgDialog::createEntry(const weld::TreeIter& rEntry) bool bValid = false; sal_Int32 i = 1; - Sequence< Reference< browse::XBrowseNode > > childNodes; + std::vector< Reference< browse::XBrowseNode > > childNodes; // no children => ok to create Parcel1 or Script1 without checking try { @@ -737,7 +657,7 @@ void SvxScriptOrgDialog::createEntry(const weld::TreeIter& rEntry) } else { - childNodes = node->getChildNodes(); + childNodes = comphelper::scriptbrowse::getChildNodes(node); } } catch ( Exception& ) @@ -750,7 +670,7 @@ void SvxScriptOrgDialog::createEntry(const weld::TreeIter& rEntry) { aNewName = aNewStdName + OUString::number(i); bool bFound = false; - if(childNodes.hasElements() ) + if(!childNodes.empty() ) { OUString nodeName = childNodes[0]->getName(); sal_Int32 extnPos = nodeName.lastIndexOf( '.' ); @@ -814,14 +734,9 @@ void SvxScriptOrgDialog::createEntry(const weld::TreeIter& rEntry) // open up parent node (which ensures it's loaded) m_xScriptsBox->expand_row(rEntry); - Sequence< Any > args{ Any(aNewName) }; - Sequence< Any > outArgs; - Sequence< sal_Int16 > outIndex; try { - Any aResult = xInv->invoke( u"Creatable"_ustr, args, outIndex, outArgs ); - aChildNode.set(aResult, UNO_QUERY); - + aChildNode = comphelper::scriptbrowse::createNode(node, aNewName); } catch( Exception const & ) { @@ -878,9 +793,8 @@ void SvxScriptOrgDialog::renameEntry(const weld::TreeIter& rEntry) Reference< browse::XBrowseNode > aChildNode; Reference< browse::XBrowseNode > node = getBrowseNode(rEntry); - Reference< script::XInvocation > xInv( node, UNO_QUERY ); - if ( xInv.is() ) + if ( node.is() ) { OUString aNewName = node->getName(); sal_Int32 extnPos = aNewName.lastIndexOf( '.' ); @@ -896,14 +810,9 @@ void SvxScriptOrgDialog::renameEntry(const weld::TreeIter& rEntry) aNewName = aNewDlg.GetObjectName(); - Sequence< Any > args{ Any(aNewName) }; - Sequence< Any > outArgs; - Sequence< sal_Int16 > outIndex; try { - Any aResult = xInv->invoke( u"Renamable"_ustr, args, outIndex, outArgs ); - aChildNode.set(aResult, UNO_QUERY); - + aChildNode = comphelper::scriptbrowse::renameNode(node, aNewName); } catch( Exception const & ) { @@ -942,16 +851,12 @@ void SvxScriptOrgDialog::deleteEntry(const weld::TreeIter& rEntry) return; } - Reference< script::XInvocation > xInv( node, UNO_QUERY ); - if ( xInv.is() ) + if ( node.is() ) { - Sequence< Any > args( 0 ); - Sequence< Any > outArgs( 0 ); - Sequence< sal_Int16 > outIndex; try { - Any aResult = xInv->invoke( u"Deletable"_ustr, args, outIndex, outArgs ); - aResult >>= result; // or do we just assume true if no exception ? + result = comphelper::scriptbrowse::deleteNode(node); + // or do we just assume true if no exception ? } catch( Exception const & ) { @@ -975,21 +880,6 @@ void SvxScriptOrgDialog::deleteEntry(const weld::TreeIter& rEntry) } -bool SvxScriptOrgDialog::getBoolProperty( Reference< beans::XPropertySet > const & xProps, - OUString const & propName ) -{ - bool result = false; - try - { - xProps->getPropertyValue( propName ) >>= result; - } - catch ( Exception& ) - { - return result; - } - return result; -} - OUString SvxScriptOrgDialog::getListOfChildren( const Reference< browse::XBrowseNode >& node, int depth ) { OUStringBuffer result = "\n"; @@ -1003,8 +893,8 @@ OUString SvxScriptOrgDialog::getListOfChildren( const Reference< browse::XBrowse { if ( node->hasChildNodes() ) { - const Sequence< Reference< browse::XBrowseNode > > children - = node->getChildNodes(); + const std::vector< Reference< browse::XBrowseNode > > children + = comphelper::scriptbrowse::getSortedChildNodes(node); for( const Reference< browse::XBrowseNode >& n : children ) { result.append( getListOfChildren( n , depth+1 ) ); @@ -1322,11 +1212,8 @@ IMPL_STATIC_LINK( SvxScriptErrorDialog, ShowDialog, void*, p, void ) message = CuiResId( RID_CUISTR_ERROR_TITLE ); std::shared_ptr xBox; - xBox.reset(Application::CreateMessageDialog( - xData->pParent, - VclMessageType::Warning, - VclButtonsType::Ok, - message)); + xBox = Application::CreateMessageDialog(xData->pParent, VclMessageType::Warning, + VclButtonsType::Ok, message); xBox->set_title(CuiResId(RID_CUISTR_ERROR_TITLE)); diff --git a/cui/source/dialogs/srchxtra.cxx b/cui/source/dialogs/srchxtra.cxx index 22ad7534518f..590a3b9545b4 100644 --- a/cui/source/dialogs/srchxtra.cxx +++ b/cui/source/dialogs/srchxtra.cxx @@ -119,7 +119,7 @@ SvxSearchAttributeDialog::SvxSearchAttributeDialog(weld::Window* pParent, m_xAttrLB->set_size_request(m_xAttrLB->get_approximate_digit_width() * 50, m_xAttrLB->get_height_rows(12)); - m_xAttrLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xAttrLB->enable_toggle_buttons(); m_xOKBtn->connect_clicked(LINK( this, SvxSearchAttributeDialog, OKHdl)); diff --git a/cui/source/dialogs/thesdlg.cxx b/cui/source/dialogs/thesdlg.cxx index 7d7ad82d7a21..43e9d5e163a0 100644 --- a/cui/source/dialogs/thesdlg.cxx +++ b/cui/source/dialogs/thesdlg.cxx @@ -43,7 +43,7 @@ IMPL_LINK_NOARG( SvxThesaurusDialog, ModifyTimer_Hdl, Timer *, void ) m_aModifyIdle.Stop(); } -IMPL_LINK_NOARG(SvxThesaurusDialog, ReplaceEditHdl_Impl, weld::Entry&, void) +IMPL_LINK_NOARG(SvxThesaurusDialog, ReplaceEditHdl_Impl, weld::TextWidget&, void) { m_xReplaceBtn->set_sensitive(!m_xReplaceEdit->get_text().isEmpty()); } diff --git a/cui/source/dialogs/tipofthedaydlg.cxx b/cui/source/dialogs/tipofthedaydlg.cxx index d740f8ff2f79..239245b4fbd0 100644 --- a/cui/source/dialogs/tipofthedaydlg.cxx +++ b/cui/source/dialogs/tipofthedaydlg.cxx @@ -163,16 +163,19 @@ void TipOfTheDayDialog::UpdateTip() #ifdef MACOSX const OUString aMOD1 = CuiResId(STR_CMD); const OUString aMOD2 = CuiResId(STR_Option); - const OUString aMOD3 = CuiResId(STR_CTRL); + const OUString aMOD3 = CuiResId(STR_CTRL_MAC); + const OUString aSHIFT = CuiResId(STR_SHIFT); #else const OUString aMOD1 = CuiResId(STR_CTRL); const OUString aMOD2 = CuiResId(STR_Alt); const OUString& aMOD3 = aMOD1; + const OUString aSHIFT = CuiResId(STR_SHIFT); #endif m_pText->set_label(CuiResId(sTip) .replaceAll("%MOD1", aMOD1) .replaceAll("%MOD2", aMOD2) - .replaceAll("%MOD3", aMOD3)); + .replaceAll("%MOD3", aMOD3) + .replaceAll("%SHIFT", aSHIFT)); // hyperlink if (sLink.isEmpty()) diff --git a/cui/source/dialogs/uipickerdlg.cxx b/cui/source/dialogs/uipickerdlg.cxx index 69a3df6a3b67..c8837ae0ab3a 100644 --- a/cui/source/dialogs/uipickerdlg.cxx +++ b/cui/source/dialogs/uipickerdlg.cxx @@ -22,6 +22,33 @@ #include #include +namespace +{ +OUString lcl_GetApplyToText() +{ + if (std::optional sApp = UITabPage::GetCurrentAppEnum()) + { + switch (*sApp) + { + case vcl::EnumContext::Application::Writer: + return CuiResId(RID_CUISTR_UI_APPLY_TO_WRITER); + case vcl::EnumContext::Application::Calc: + return CuiResId(RID_CUISTR_UI_APPLY_TO_CALC); + case vcl::EnumContext::Application::Impress: + return CuiResId(RID_CUISTR_UI_APPLY_TO_IMPRESS); + case vcl::EnumContext::Application::Draw: + return CuiResId(RID_CUISTR_UI_APPLY_TO_DRAW); + default: + break; + } + } + + assert(!"UI picker dialog used for unsupported application"); + + return OUString(); +} +} + UIPickerDialog::UIPickerDialog(weld::Window* pParent) : SfxTabDialogController(pParent, u"cui/ui/uipickerdialog.ui"_ustr, u"UIPickerDialog"_ustr) , m_xOKBtn(m_xBuilder->weld_button(u"ok"_ustr)) @@ -39,8 +66,7 @@ UIPickerDialog::UIPickerDialog(weld::Window* pParent) // it's mandatory for gtk3 to set the icon before changing the label m_xApplyBtn->set_from_icon_name("sw/res/sc20558.png"); - m_xApplyBtn->set_label( - CuiResId(RID_CUISTR_UI_APPLY).replaceFirst("%MODULE", UITabPage::GetCurrentApp())); + m_xApplyBtn->set_label(lcl_GetApplyToText()); m_xResetBtn->set_label(CuiResId(RID_CUISTR_UI_APPLYALL)); m_xApplyBtn->connect_clicked(LINK(this, UIPickerDialog, OnApplyClick)); m_xResetBtn->connect_clicked(LINK(this, UIPickerDialog, OnApplyClick)); diff --git a/cui/source/dialogs/uitabpage.cxx b/cui/source/dialogs/uitabpage.cxx index 6d5b6e263cb5..a6d6b25e6bf9 100644 --- a/cui/source/dialogs/uitabpage.cxx +++ b/cui/source/dialogs/uitabpage.cxx @@ -82,15 +82,27 @@ OUString UITabPage::GetCurrentMode() return sResult; } -OUString UITabPage::GetCurrentApp() +std::optional UITabPage::GetCurrentAppEnum() { - OUString sResult; if (SfxViewFrame* pViewFrame = SfxViewFrame::Current()) { const auto xCurrentFrame = pViewFrame->GetFrame().GetFrameInterface(); const auto& xContext = comphelper::getProcessComponentContext(); const auto xModuleManager = css::frame::ModuleManager::create(xContext); - switch (vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xCurrentFrame))) + return vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xCurrentFrame)); + } + else + { + return std::nullopt; + } +} + +OUString UITabPage::GetCurrentApp() +{ + OUString sResult; + if (std::optional aAppEnum = GetCurrentAppEnum()) + { + switch (*aAppEnum) { case vcl::EnumContext::Application::Writer: sResult = "Writer"; diff --git a/cui/source/dialogs/welcomedlg.cxx b/cui/source/dialogs/welcomedlg.cxx index 742733c547d2..d51147f8c7f3 100644 --- a/cui/source/dialogs/welcomedlg.cxx +++ b/cui/source/dialogs/welcomedlg.cxx @@ -67,7 +67,7 @@ WelcomeDialog::WelcomeDialog(weld::Window* pParent, const bool bIsFirstStart) void WelcomeDialog::ImplDestroy() { m_xTabCtrl->set_current_page(sNewsTab); // ensure next start with the first page - if (!m_xShowAgain->get_active()) + if (m_xShowAgain->get_active()) { std::shared_ptr xChanges( comphelper::ConfigurationChanges::create()); diff --git a/cui/source/dialogs/widgettestdlg.cxx b/cui/source/dialogs/widgettestdlg.cxx index c0c3aaaafed0..e6042ddfc819 100644 --- a/cui/source/dialogs/widgettestdlg.cxx +++ b/cui/source/dialogs/widgettestdlg.cxx @@ -23,7 +23,7 @@ WidgetTestDialog::WidgetTestDialog(weld::Window* pParent) m_xOKButton->connect_clicked(LINK(this, WidgetTestDialog, OkHdl)); m_xCancelButton->connect_clicked(LINK(this, WidgetTestDialog, CancelHdl)); - m_xTreeView2->connect_column_clicked(LINK(this, WidgetTestDialog, HeaderBarClick)); + m_xTreeView2->connect_column_header_clicked(LINK(this, WidgetTestDialog, HeaderBarClick)); FillTreeView(); } diff --git a/cui/source/factory/dlgfact.cxx b/cui/source/factory/dlgfact.cxx index 92583fb3b6a0..41ace2aa59cc 100644 --- a/cui/source/factory/dlgfact.cxx +++ b/cui/source/factory/dlgfact.cxx @@ -97,11 +97,12 @@ #include #include #include -#include #include #include +#include + using namespace ::com::sun::star::frame; using namespace ::com::sun::star::container; @@ -241,7 +242,7 @@ VclPtr AbstractDialogFactory_Impl::CreateCustomizeTabDialo return VclPtr>::Create(std::move(xDlg1)); } -// TabDialog that use functionality of the drawing layer +// TabDialog that uses functionality of the drawing layer VclPtr AbstractDialogFactory_Impl::CreateTextTabDialog(weld::Window* pParent, const SfxItemSet* pAttrSet, SdrView* pView) @@ -251,7 +252,7 @@ VclPtr AbstractDialogFactory_Impl::CreateTextTabDialog(wel namespace { -// AbstractSvxCaptionDialog implementations just forwards everything to the dialog +// AbstractSvxCaptionDialog implementation just forwards everything to the dialog class AbstractSvxCaptionDialog_Impl final : public vcl::AbstractDialogImpl_Async { @@ -272,7 +273,7 @@ public: }; } -// TabDialog that use functionality of the drawing layer and add AnchorTypes -- for SvxCaptionTabDialog +// TabDialog that uses functionality of the drawing layer and adds AnchorTypes -- for SvxCaptionTabDialog VclPtr AbstractDialogFactory_Impl::CreateCaptionDialog(weld::Window* pParent, const SdrView* pView, SvxAnchorIds nAnchorTypes) @@ -482,6 +483,7 @@ class AbstractScriptSelectorDialog_Impl final public: using AbstractDialogImpl_BASE::AbstractDialogImpl_BASE; OUString GetScriptURL() const override { return m_pDlg->GetScriptURL(); } + Reference GetScriptModel() const override { return m_pDlg->GetScriptModel(); } void SetRunLabel() override { m_pDlg->SetRunLabel(); } }; } @@ -501,6 +503,7 @@ class AbstractMacroManagerDialog_Impl final public: using AbstractDialogImpl_BASE::AbstractDialogImpl_BASE; OUString GetScriptURL() const override { return m_pDlg->GetScriptURL(); } + Reference GetScriptModel() const override { return m_pDlg->GetScriptModel(); } void LoadLastUsedMacro() const override { m_pDlg->LoadLastUsedMacro(); } }; } @@ -1548,27 +1551,4 @@ AbstractDialogFactory_Impl::CreateFileExtCheckDialog(weld::Window* pParent, cons } #endif -namespace -{ -class AbstractQueryDialog_Impl final - : public vcl::AbstractDialogImpl_Async -{ -public: - using AbstractDialogImpl_BASE::AbstractDialogImpl_BASE; - bool ShowAgain() const override { return m_pDlg->ShowAgain(); } - void SetYesLabel(const OUString& sLabel) override { m_pDlg->SetYesLabel(sLabel); } - void SetNoLabel(const OUString& sLabel) override { m_pDlg->SetNoLabel(sLabel); } -}; -} - -VclPtr -AbstractDialogFactory_Impl::CreateQueryDialog( - weld::Window* pParent, - const OUString& sTitle, const OUString& sText, const OUString& sQuestion, - bool bShowAgain) -{ - return VclPtr::Create(pParent, sTitle, sText, sQuestion, bShowAgain); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/factory/dlgfact.hxx b/cui/source/factory/dlgfact.hxx index 4a2c0f26916c..23291cbbe638 100644 --- a/cui/source/factory/dlgfact.hxx +++ b/cui/source/factory/dlgfact.hxx @@ -20,7 +20,7 @@ #include -//AbstractDialogFactory_Impl implementations +// AbstractDialogFactory_Impl implementation class AbstractDialogFactory_Impl : public SvxAbstractDialogFactory { public: @@ -224,11 +224,6 @@ public: weld::Window* pParent, SdrObjGroup& rDiagram) override; - virtual VclPtr CreateQueryDialog( - weld::Window* pParent, - const OUString& sTitle, const OUString& sText, const OUString& sQuestion, - bool bShowAgain) override; - #ifdef _WIN32 virtual VclPtr CreateFileExtCheckDialog(weld::Window* pParent, const OUString& sTitle, diff --git a/cui/source/inc/AdditionsDialog.hxx b/cui/source/inc/AdditionsDialog.hxx index 5ea7cfc4b450..ab139d31dca7 100644 --- a/cui/source/inc/AdditionsDialog.hxx +++ b/cui/source/inc/AdditionsDialog.hxx @@ -12,12 +12,16 @@ #include #include +#include +#include #include #include #include +#include +#include +#include #include #include -#include // Detect changes on the UI #include @@ -63,7 +67,7 @@ private: Timer m_aSearchDataTimer; DECL_LINK(GearHdl, const OUString&, void); - DECL_LINK(SearchUpdateHdl, weld::Entry&, void); + DECL_LINK(SearchUpdateHdl, weld::TextWidget&, void); DECL_LINK(ImplUpdateDataHdl, Timer*, void); DECL_LINK(FocusOut_Impl, weld::Widget&, void); DECL_LINK(CloseButtonHdl, weld::Button&, void); diff --git a/cui/source/inc/CommandCategoryListBox.hxx b/cui/source/inc/CommandCategoryListBox.hxx index d90e6a095e3a..882d56469bab 100644 --- a/cui/source/inc/CommandCategoryListBox.hxx +++ b/cui/source/inc/CommandCategoryListBox.hxx @@ -63,8 +63,8 @@ public: } /** - Signals that a command category has been selected. - And updates the functions list box to include + Signals that a command category has been selected, + and updates the functions list box to include the commands in the selected category. */ void categorySelected(CuiConfigFunctionListBox* pFunctionListBox, const OUString& filterTerm, @@ -78,8 +78,6 @@ public: CuiConfigFunctionListBox* pFunctionListBox, const OUString& filterTerm, SaveInData* pCurrentSaveInData, std::vector>& rNodesToExpand); - - void set_visible(bool bVisible) { m_xControl->set_visible(bVisible); } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/CustomNotebookbarGenerator.hxx b/cui/source/inc/CustomNotebookbarGenerator.hxx deleted file mode 100644 index 53c1c4b3e85e..000000000000 --- a/cui/source/inc/CustomNotebookbarGenerator.hxx +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * 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 . - */ - -#pragma once - -#include -#include - -using namespace css::uno; - -class CustomNotebookbarGenerator -{ -public: - CustomNotebookbarGenerator(); - static OUString getCustomizedUIPath(); - static OUString getOriginalUIPath(); - static OString getSystemPath(OUString const& sURL); - static Sequence getCustomizedUIItem(const OUString& sNotebookbarConfigType); - static void getFileNameAndAppName(OUString& sAppName, OUString& sNotebookbarUIFileName); - static void modifyCustomizedUIFile(const Sequence& sUIItemProperties); - static void createCustomizedUIFile(); - static void setCustomizedUIItem(const Sequence& rUIItemProperties, - const OUString& rNotebookbarConfigType); -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/DiagramDialog.hxx b/cui/source/inc/DiagramDialog.hxx index 95ed28825bd0..34e98f9239ce 100644 --- a/cui/source/inc/DiagramDialog.hxx +++ b/cui/source/inc/DiagramDialog.hxx @@ -10,10 +10,11 @@ #pragma once #include +#include #include #include #include -#include +#include class SdrObjGroup; diff --git a/cui/source/inc/FontFeaturesDialog.hxx b/cui/source/inc/FontFeaturesDialog.hxx index e54dc73e24e4..eb3d264db8c7 100644 --- a/cui/source/inc/FontFeaturesDialog.hxx +++ b/cui/source/inc/FontFeaturesDialog.hxx @@ -12,10 +12,14 @@ #include #include +#include #include #include +#include +#include #include -#include +#include +#include #include #include #include diff --git a/cui/source/inc/GetDocumentModel.hxx b/cui/source/inc/GetDocumentModel.hxx new file mode 100644 index 000000000000..708e176c9cac --- /dev/null +++ b/cui/source/inc/GetDocumentModel.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +namespace com::sun::star::frame +{ +class XModel; +} + +css::uno::Reference +getDocumentModel(const css::uno::Reference& xContext, + std::u16string_view sDocName); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/GraphicsTestsDialog.hxx b/cui/source/inc/GraphicsTestsDialog.hxx index e1f426035462..f804b5695264 100644 --- a/cui/source/inc/GraphicsTestsDialog.hxx +++ b/cui/source/inc/GraphicsTestsDialog.hxx @@ -9,11 +9,14 @@ #pragma once #include +#include #include +#include +#include #include #include +#include #include -#include #include #include diff --git a/cui/source/inc/ImageViewerDialog.hxx b/cui/source/inc/ImageViewerDialog.hxx index 1ff26307a5f2..d60d06fe8ef1 100644 --- a/cui/source/inc/ImageViewerDialog.hxx +++ b/cui/source/inc/ImageViewerDialog.hxx @@ -10,7 +10,7 @@ #include #include -#include +#include class ImageViewerDialog : public weld::GenericDialogController { diff --git a/cui/source/inc/MacroManagerDialog.hxx b/cui/source/inc/MacroManagerDialog.hxx index 43eda0fa0cb8..1c2cc7917b20 100644 --- a/cui/source/inc/MacroManagerDialog.hxx +++ b/cui/source/inc/MacroManagerDialog.hxx @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include #include #include @@ -24,12 +26,23 @@ #include #include +class SbModule; +class SbMethod; + +namespace com::sun::star::script::browse +{ +class XCopyableBrowseNode; +} + struct ScriptContainerInfo { css::script::browse::XBrowseNode* pBrowseNode; + css::uno::Reference xModel; - ScriptContainerInfo(css::script::browse::XBrowseNode* pObj) + ScriptContainerInfo(css::script::browse::XBrowseNode* pObj, + const css::uno::Reference& xModel_) : pBrowseNode(pObj) + , xModel(xModel_) { } }; @@ -39,12 +52,14 @@ struct ScriptInfo css::script::browse::XBrowseNode* pBrowseNode; OUString sURL; OUString sDescription; + css::uno::Reference xModel; ScriptInfo(css::script::browse::XBrowseNode* pObj, const OUString& rsUrl, - const OUString& rsDesc) + const OUString& rsDesc, const css::uno::Reference& xModel_) : pBrowseNode(pObj) , sURL(rsUrl) , sDescription(rsDesc) + , xModel(xModel_) { } }; @@ -160,6 +175,7 @@ public: void ScriptContainerSelected(); void Insert(const css::uno::Reference& xInsertNode, + const css::uno::Reference& xDocumentModel, const weld::TreeIter* pParentEntry, const OUString& rsUiName, const OUString& rsImage, bool bChildOnDemand = false, int nPos = -1, weld::TreeIter* pRet = nullptr); @@ -198,8 +214,13 @@ class MacroManagerDialog : public weld::GenericDialogController, public SfxListe std::unique_ptr m_xMacroDeleteButton; std::unique_ptr m_xMacroCreateButton; std::unique_ptr m_xMacroRenameButton; + std::unique_ptr m_xModuleCopyButton; + std::unique_ptr m_xModulePasteButton; std::unique_ptr m_xAssignButton; + // Node that is selected via the “copy” button to be later pasted with the “paste” button. + css::uno::Reference m_xCopiedNode; + DECL_LINK(ClickHdl, weld::Button&, void); DECL_LINK(SelectHdl, weld::ItemView&, void); DECL_LINK(FunctionDoubleClickHdl, const weld::TreeIter&, bool); @@ -214,6 +235,7 @@ class MacroManagerDialog : public weld::GenericDialogController, public SfxListe void BasicScriptsLibraryModuleDialogDelete(const basctl::ScriptDocument& rDocument); void BasicScriptsLibraryPassword(const basctl::ScriptDocument& rDocument); void BasicScriptsMacroEdit(const basctl::ScriptDocument& rDocument); + void BasicScriptsMacroDelete(); bool IsLibraryReadOnlyOrFailedPasswordQuery(const basctl::ScriptDocument& rDocument, const weld::TreeIter* pIter); @@ -222,8 +244,8 @@ class MacroManagerDialog : public weld::GenericDialogController, public SfxListe const weld::TreeIter& rEntry); void ScriptingFrameworkScriptsDeleteEntry(weld::TreeView& rTreeView, const weld::TreeIter& rEntry); - static bool getBoolProperty(css::uno::Reference const& xProps, - OUString const& propName); + void ScriptingFrameworkScriptsPasteEntry(weld::TreeView& rTreeView, + const weld::TreeIter& rEntry); OUString getListOfChildren(const css::uno::Reference& node, int depth); @@ -233,6 +255,9 @@ class MacroManagerDialog : public weld::GenericDialogController, public SfxListe void UpdateUI(); void CheckButtons(); + SbModule* GetSelectedBasicModule() const; + SbMethod* GetSelectedBasicMethod() const; + virtual void Notify(SfxBroadcaster&, const SfxHint& rHint) override; public: @@ -241,6 +266,7 @@ public: virtual ~MacroManagerDialog() override; OUString GetScriptURL() const; + css::uno::Reference GetScriptModel() const; void SaveLastUsedMacro(); void LoadLastUsedMacro(); diff --git a/cui/source/inc/QrCodeGenDialog.hxx b/cui/source/inc/QrCodeGenDialog.hxx index bd210317227b..037f028b3385 100644 --- a/cui/source/inc/QrCodeGenDialog.hxx +++ b/cui/source/inc/QrCodeGenDialog.hxx @@ -12,9 +12,10 @@ #include #include +#include +#include #include #include -#include #include #include diff --git a/cui/source/inc/SignSignatureLineDialog.hxx b/cui/source/inc/SignSignatureLineDialog.hxx index 2a497601c071..85cf43d73d25 100644 --- a/cui/source/inc/SignSignatureLineDialog.hxx +++ b/cui/source/inc/SignSignatureLineDialog.hxx @@ -14,7 +14,9 @@ #include #include #include +#include #include +#include #include class SignSignatureLineDialog : public SignatureLineDialogBase @@ -50,7 +52,7 @@ private: DECL_LINK(clearImage, weld::Button&, void); DECL_LINK(loadImage, weld::Button&, void); DECL_LINK(chooseCertificate, weld::Button&, void); - DECL_LINK(entryChanged, weld::Entry&, void); + DECL_LINK(entryChanged, weld::TextWidget&, void); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/SignatureLineDialog.hxx b/cui/source/inc/SignatureLineDialog.hxx index 62d2dae9985d..9f909a111927 100644 --- a/cui/source/inc/SignatureLineDialog.hxx +++ b/cui/source/inc/SignatureLineDialog.hxx @@ -12,6 +12,7 @@ #include #include +#include #include #include diff --git a/cui/source/inc/SignatureLineDialogBase.hxx b/cui/source/inc/SignatureLineDialogBase.hxx index 243f8c4b60a6..5cbccdf78acf 100644 --- a/cui/source/inc/SignatureLineDialogBase.hxx +++ b/cui/source/inc/SignatureLineDialogBase.hxx @@ -13,7 +13,6 @@ #include #include -#include #include #include diff --git a/cui/source/inc/SpellDialog.hxx b/cui/source/inc/SpellDialog.hxx index 3a6a578b7a4c..6480b61d3e83 100644 --- a/cui/source/inc/SpellDialog.hxx +++ b/cui/source/inc/SpellDialog.hxx @@ -28,8 +28,12 @@ #include #include #include +#include +#include #include #include +#include +#include #include #include #include diff --git a/cui/source/inc/SvxMenuConfigPage.hxx b/cui/source/inc/SvxMenuConfigPage.hxx index a92122da14a3..0a3bd5c1ccf8 100644 --- a/cui/source/inc/SvxMenuConfigPage.hxx +++ b/cui/source/inc/SvxMenuConfigPage.hxx @@ -22,7 +22,6 @@ #include #include #include -#include #include "cfg.hxx" //for SvxConfigPage and SaveInData diff --git a/cui/source/inc/SvxNotebookbarConfigPage.hxx b/cui/source/inc/SvxNotebookbarConfigPage.hxx deleted file mode 100644 index 8b45916a6bb5..000000000000 --- a/cui/source/inc/SvxNotebookbarConfigPage.hxx +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- 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 . - */ - -#pragma once - -#include -#include -#include - -#include -#include - -#include "cfg.hxx" //for SvxConfigPage and SaveInData - -class SvxNotebookbarConfigPage : public SvxConfigPage -{ -private: - void UpdateButtonStates() override; - short QueryReset() override; - void Init() override; - void DeleteSelectedContent() override; - void DeleteSelectedTopLevel() override; - virtual void SelectElement() override; - void SetElement(); - -public: - struct NotebookbarEntries - { - OUString sUIItemId; - OUString sClassId; - OUString sActionName; - OUString sDisplayName; - OUString sVisibleValue; - }; - struct CategoriesEntries - { - OUString sDisplayName; - OUString sUIItemId; - OUString sClassType; - }; - SvxNotebookbarConfigPage(weld::Container* pPage, weld::DialogController* pController, - const SfxItemSet& rItemSet); - virtual ~SvxNotebookbarConfigPage() override; - SaveInData* CreateSaveInData(const css::uno::Reference&, - const css::uno::Reference&, - const OUString& aModuleId, bool docConfig) override; - static void FillFunctionsList(xmlNodePtr pRootNodePtr, - std::vector& aEntries, - std::vector& aCategoryList, - OUString& sActiveCategory); - static void searchNodeandAttribute(std::vector& aEntries, - std::vector& aCategoryList, - OUString& sActiveCategory, - CategoriesEntries& aCurCategoryEntry, xmlNode* pNodePtr, - bool isCategory); - static void getNodeValue(xmlNode* pNodePtr, NotebookbarEntries& aNodeEntries); -}; - -class SvxNotebookbarEntriesListBox final : public SvxMenuEntriesListBox -{ - typedef std::unordered_map TooltipMap; - TooltipMap m_aTooltipMap; - - void ChangedVisibility(int nRow); - DECL_LINK(CheckButtonHdl, const weld::TreeView::iter_col&, void); - DECL_LINK(KeyInputHdl, const KeyEvent&, bool); - DECL_LINK(QueryTooltip, const weld::TreeIter& rIter, OUString); - -public: - SvxNotebookbarEntriesListBox(std::unique_ptr xControl, SvxConfigPage* pPg); - virtual ~SvxNotebookbarEntriesListBox() override; - - TooltipMap& GetTooltipMap() { return m_aTooltipMap; } -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/donationbanner.hrc b/cui/source/inc/SvxPresetListBox.hxx similarity index 50% rename from include/sfx2/donationbanner.hrc rename to cui/source/inc/SvxPresetListBox.hxx index ee236072a42b..3d67171b71c7 100644 --- a/include/sfx2/donationbanner.hrc +++ b/cui/source/inc/SvxPresetListBox.hxx @@ -19,18 +19,41 @@ #pragma once -#include +#include +#include +#include +#include -#define NC_(Context, String) TranslateId(Context, u8##String) - -// place images at ./icon-themes/colibre/brand/shell/ and add it to "brand_files=..." in configure.ac -const std::tuple STR_DONATIONBANNER[] = +namespace weld { - { NC_("STR_DONATION", "LibreOffice is free software. Click here to donate, and support the community that makes it!"), "donate1.png" }, +class IconView; +} + +class SvxPresetListBox final +{ + weld::IconView& m_rIconView; + + Size m_aIconSize; + Link maRenameHdl; + Link maDeleteHdl; + + DECL_LINK(CommandHdl, const CommandEvent&, bool); + DECL_LINK(KeyPressHdl, const KeyEvent&, bool); + + template void FillPresetListBoxImpl(ListType& rList); + +public: + SvxPresetListBox(weld::IconView& rIconView); + + Size const& GetIconSize() const { return m_aIconSize; } + + void SetRenameHdl(const Link& rLink) { maRenameHdl = rLink; } + void SetDeleteHdl(const Link& rLink) { maDeleteHdl = rLink; } + + void FillPresetListBox(XGradientList& rList); + void FillPresetListBox(XHatchList& rList); + void FillPresetListBox(XBitmapList& rList); + void FillPresetListBox(XPatternList& rList); }; -#define DONATIONBANNER_HEIGHT 0.25 // banner height as percentage of the app height -#define DONATIONBANNER_FREQ 30 // frequency of days to show the banner; 1 = every start -#define DONATIONBANNER_BACKGROUND "donationbackground.png" // place image at ./icon-themes/colibre/brand/shell/ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/SvxToolbarConfigPage.hxx b/cui/source/inc/SvxToolbarConfigPage.hxx index f44ac22b6842..af00264eef13 100644 --- a/cui/source/inc/SvxToolbarConfigPage.hxx +++ b/cui/source/inc/SvxToolbarConfigPage.hxx @@ -21,7 +21,6 @@ #include #include -#include #include diff --git a/cui/source/inc/about.hxx b/cui/source/inc/about.hxx index 06b303802e64..6b1bdbf85caf 100644 --- a/cui/source/inc/about.hxx +++ b/cui/source/inc/about.hxx @@ -18,8 +18,12 @@ */ #pragma once +#include #include -#include +#include +#include +#include +#include class AboutDialog : public weld::GenericDialogController { diff --git a/cui/source/inc/acccfg.hxx b/cui/source/inc/acccfg.hxx index f6faa27a7e12..0387742431d2 100644 --- a/cui/source/inc/acccfg.hxx +++ b/cui/source/inc/acccfg.hxx @@ -27,8 +27,10 @@ #include #include #include +#include #include #include +#include #include #include #include "cfgutil.hxx" @@ -109,7 +111,7 @@ private: DECL_LINK(ChangeHdl, weld::Button&, void); DECL_LINK(RemoveHdl, weld::Button&, void); DECL_LINK(SelectHdl, weld::ItemView&, void); - DECL_LINK(SearchUpdateHdl, weld::Entry&, void); + DECL_LINK(SearchUpdateHdl, weld::TextWidget&, void); DECL_LINK(Save, weld::Button&, void); DECL_LINK(Load, weld::Button&, void); DECL_LINK(Default, weld::Button&, void); diff --git a/cui/source/inc/align.hxx b/cui/source/inc/align.hxx index 5d1ad35c569f..4df73d6dfce0 100644 --- a/cui/source/inc/align.hxx +++ b/cui/source/inc/align.hxx @@ -42,9 +42,11 @@ enum VerticalAlign { #include #include #include +#include #include +#include #include -#include +#include class SvxJustifyMethodItem; diff --git a/cui/source/inc/autocdlg.hxx b/cui/source/inc/autocdlg.hxx index 3f8b5f06ba1b..02afd50d64ae 100644 --- a/cui/source/inc/autocdlg.hxx +++ b/cui/source/inc/autocdlg.hxx @@ -21,7 +21,10 @@ #include #include #include +#include +#include #include +#include #include #include @@ -195,7 +198,7 @@ private: DECL_LINK(NewDelButtonHdl, weld::Button&, void); DECL_LINK(NewDelActionHdl, weld::Entry&, bool); DECL_LINK(EntrySizeAllocHdl, const Size&, void); - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); bool NewDelHdl(const weld::Widget*); void RefillReplaceBox( bool bFromReset, @@ -251,7 +254,7 @@ private: DECL_LINK(NewDelButtonHdl, weld::Button&, void); DECL_LINK(NewDelActionHdl, weld::Entry&, bool); DECL_LINK(SelectHdl, weld::ItemView&, void); - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); bool NewDelHdl(const weld::Widget*); /// Box filled with new language void RefillReplaceBoxes(bool bFromReset, @@ -281,6 +284,7 @@ private: OUString sOrdinal; OUString sTransliterateRTL; OUString sAngleQuotes; + OUString sEsperantoHats; sal_UCS4 cSglStartQuote; sal_UCS4 cSglEndQuote; diff --git a/cui/source/inc/bbdlg.hxx b/cui/source/inc/bbdlg.hxx index c18b5b3da4e6..ec7a26021b9e 100644 --- a/cui/source/inc/bbdlg.hxx +++ b/cui/source/inc/bbdlg.hxx @@ -19,6 +19,7 @@ #pragma once #include +#include /*-------------------------------------------------------------------- Description: bunch the border background pages diff --git a/cui/source/inc/border.hxx b/cui/source/inc/border.hxx index 1731e95cee95..7e6bc0b7dfd5 100644 --- a/cui/source/inc/border.hxx +++ b/cui/source/inc/border.hxx @@ -20,10 +20,11 @@ #include #include +#include #include #include +#include #include -#include #include #include #include diff --git a/cui/source/inc/cfg.hxx b/cui/source/inc/cfg.hxx index a68c78088979..b6500ae6ba29 100644 --- a/cui/source/inc/cfg.hxx +++ b/cui/source/inc/cfg.hxx @@ -20,13 +20,14 @@ #pragma once #include +#include #include #include #include +#include #include #include #include -#include #include #include @@ -386,7 +387,7 @@ private: bool bInitialised; SaveInData* pCurrentSaveInData; - DECL_LINK(SearchUpdateHdl, weld::Entry&, void); + DECL_LINK(SearchUpdateHdl, weld::TextWidget&, void); protected: @@ -434,9 +435,6 @@ protected: std::unique_ptr m_xAddCommandButton; std::unique_ptr m_xRemoveCommandButton; - OUString m_sAppName; - OUString m_sFileName; - SvxConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet&); DECL_LINK(MoveHdl, weld::Button&, void); @@ -472,10 +470,6 @@ protected: weld::TreeView& rTreeView, weld::TreeIter& rIter, bool bMenu = false); - void InsertEntryIntoNotebookbarTabUI(std::u16string_view sClassId, const OUString& sUIItemId, - const OUString& sUIItemCommand, - weld::TreeView& rTreeView, const weld::TreeIter& rIter); - SvxEntries* FindParentForChild( SvxEntries* pParentEntries, SvxConfigEntry* pChildData ); @@ -493,8 +487,6 @@ public: static bool CanConfig( std::u16string_view rModuleId ); SaveInData* GetSaveInData() { return pCurrentSaveInData; } - const OUString& GetAppName() const { return m_sAppName; } - const OUString& GetFileName() const { return m_sFileName; } int AddFunction(int nTarget, bool bAllowDuplicates, @@ -548,7 +540,7 @@ class SvxMainMenuOrganizerDialog : public weld::GenericDialogController void UpdateButtonStates(); DECL_LINK(MoveHdl, weld::Button&, void); - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); DECL_LINK(SelectHdl, weld::ItemView&, void); public: diff --git a/cui/source/inc/cfgutil.hxx b/cui/source/inc/cfgutil.hxx index a4adbda39551..940b60758231 100644 --- a/cui/source/inc/cfgutil.hxx +++ b/cui/source/inc/cfgutil.hxx @@ -18,6 +18,7 @@ */ #pragma once +#include #include #include #include @@ -30,10 +31,14 @@ #include #include #include +#include #include +#include +#include #include #include -#include +#include + #include #if HAVE_FEATURE_SCRIPTING @@ -79,29 +84,76 @@ public: static OUString generateCommand(std::u16string_view sFamily, std::u16string_view sStyle); }; +struct SfxScriptContainer_Data +{ + SfxScriptContainer_Data( + const css::uno::Reference& xBrowseNode_ = nullptr, + const css::uno::Reference& xModel_ = nullptr) + : xBrowseNode(xBrowseNode_) + , xModel(xModel_) + { + } + + css::uno::Reference xBrowseNode; + css::uno::Reference xModel; +}; + +struct SfxScriptFunction_Data +{ + SfxScriptFunction_Data( + const OUString& sUrl_ = OUString(), + const css::uno::Reference &xModel_ = nullptr) + : sUrl(sUrl_) + , xModel(xModel_) + { + } + + OUString sUrl; + css::uno::Reference xModel; +}; + enum class SfxCfgKind { - GROUP_FUNCTION = 1, - FUNCTION_SLOT = 2, - GROUP_SCRIPTCONTAINER = 3, - FUNCTION_SCRIPT = 4, - GROUP_STYLES = 5, - GROUP_ALLFUNCTIONS = 6, - GROUP_SIDEBARDECKS = 7 + GROUP_FUNCTION, + FUNCTION_SLOT, + GROUP_SCRIPTCONTAINER, + FUNCTION_SCRIPT, + GROUP_STYLES, + GROUP_ALLFUNCTIONS, + GROUP_SIDEBARDECKS, }; +// Used to construct SfxGroupInfo_Data by selecting the variant as an index tag +template +constexpr std::in_place_index_t SfxCfgKindAsIndex {}; + +// The types must match the order of the values of SfxCfgKind +typedef std::variant< + std::monostate, // GROUP_FUNCTION + std::monostate, // FUNCTION_SLOT + SfxScriptContainer_Data, // GROUP_SCRIPTCONTAINER + SfxScriptFunction_Data, // FUNCTION_SCRIPT + std::unique_ptr, // GROUP_STYLES + std::monostate, // GROUP_ALLFUNCTIONS + std::monostate // GROUP_SIDEBARDECKS + > SfxGroupInfo_Data; + struct SfxGroupInfo_Impl { - SfxCfgKind nKind; + SfxGroupInfo_Data aData; sal_uInt16 nUniqueID; - void* pObject; OUString sCommand; OUString sLabel; OUString sHelpText; OUString sTooltip; - SfxGroupInfo_Impl( SfxCfgKind n, sal_uInt16 nr, void* pObj = nullptr ) : - nKind( n ), nUniqueID( nr ), pObject( pObj ) {} + SfxGroupInfo_Impl( SfxGroupInfo_Data ad, sal_uInt16 nr ) + : aData( std::move(ad) ) + , nUniqueID( nr ) + { + } + + SfxCfgKind getKind() const { return static_cast(aData.index()); } }; typedef std::vector > SfxGroupInfoArr_Impl; @@ -202,12 +254,9 @@ class CuiConfigGroupListBox std::unique_ptr m_xTreeView; std::unique_ptr m_xScratchIter; - static css::uno::Reference< css::uno::XInterface > getDocumentModel( - css::uno::Reference< css::uno::XComponentContext > const & xCtx, - std::u16string_view docName); - sal_Int32 InitModule(); void FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode, + const css::uno::Reference< css::frame::XModel >& xParentDocumentModel, const weld::TreeIter* pParentEntry); void FillFunctionsList(const css::uno::Sequence< css::frame::DispatchInformation >& xCommands); OUString MapCommand2UIName(const OUString& sCommand); @@ -272,6 +321,7 @@ public: virtual ~SvxScriptSelectorDialog() override; OUString GetScriptURL() const; + css::uno::Reference GetScriptModel() const; void SetRunLabel(); void SaveLastUsedMacro(); void LoadLastUsedMacro(); diff --git a/cui/source/inc/chardlg.hxx b/cui/source/inc/chardlg.hxx index 4baab0edc89e..e50055cce6fb 100644 --- a/cui/source/inc/chardlg.hxx +++ b/cui/source/inc/chardlg.hxx @@ -23,12 +23,19 @@ #include #include #include +#include +#include #include #include +#include +#include +#include #include #include +#include #include -#include +#include + #include // forward --------------------------------------------------------------- diff --git a/cui/source/inc/connect.hxx b/cui/source/inc/connect.hxx index a750994613db..bdc1205c8a2f 100644 --- a/cui/source/inc/connect.hxx +++ b/cui/source/inc/connect.hxx @@ -21,9 +21,9 @@ #include #include #include +#include #include #include -#include #include class SdrView; diff --git a/cui/source/inc/cuifmsearch.hxx b/cui/source/inc/cuifmsearch.hxx index 6e7dd5db1474..1e41ca7b7b4f 100644 --- a/cui/source/inc/cuifmsearch.hxx +++ b/cui/source/inc/cuifmsearch.hxx @@ -22,9 +22,13 @@ #include #include +#include +#include #include #include -#include +#include +#include +#include #include #include diff --git a/cui/source/inc/cuigaldlg.hxx b/cui/source/inc/cuigaldlg.hxx index 992536c29418..937a2cb12847 100644 --- a/cui/source/inc/cuigaldlg.hxx +++ b/cui/source/inc/cuigaldlg.hxx @@ -30,9 +30,13 @@ #include #include #include +#include +#include #include #include #include +#include +#include #include #include diff --git a/cui/source/inc/cuigrfflt.hxx b/cui/source/inc/cuigrfflt.hxx index 22eb8b3fdba0..0f1e9641bf35 100644 --- a/cui/source/inc/cuigrfflt.hxx +++ b/cui/source/inc/cuigrfflt.hxx @@ -22,10 +22,12 @@ #include #include #include +#include #include #include #include #include +#include class CuiGraphicPreviewWindow : public weld::CustomWidgetController { diff --git a/cui/source/inc/cuiimapwnd.hxx b/cui/source/inc/cuiimapwnd.hxx index 7242b23c1dbb..fb938604934c 100644 --- a/cui/source/inc/cuiimapwnd.hxx +++ b/cui/source/inc/cuiimapwnd.hxx @@ -22,7 +22,6 @@ #include #include #include -#include #include class URLDlg : public weld::GenericDialogController diff --git a/cui/source/inc/cuioptgenrl.hxx b/cui/source/inc/cuioptgenrl.hxx index c244361cb810..b55b696cab0e 100644 --- a/cui/source/inc/cuioptgenrl.hxx +++ b/cui/source/inc/cuioptgenrl.hxx @@ -21,8 +21,10 @@ // include --------------------------------------------------------------- #include +#include +#include #include -#include +#include #include @@ -60,7 +62,7 @@ private: OUString msCurrentSigningKey; OUString msCurrentEncryptionKey; - DECL_LINK( ModifyHdl_Impl, weld::Entry&, void ); + DECL_LINK(ModifyHdl_Impl, weld::TextWidget&, void); DECL_LINK( ChooseKeyButtonHdl, weld::Button&, void ); DECL_LINK( RemoveKeyButtonHdl, weld::Button&, void ); diff --git a/cui/source/inc/cuisrchdlg.hxx b/cui/source/inc/cuisrchdlg.hxx index b22b3410296b..021e815e9658 100644 --- a/cui/source/inc/cuisrchdlg.hxx +++ b/cui/source/inc/cuisrchdlg.hxx @@ -20,6 +20,7 @@ #include #include +#include class SvxJSearchOptionsPage; diff --git a/cui/source/inc/cuitabarea.hxx b/cui/source/inc/cuitabarea.hxx index c9ac3cbad4ce..8c974f98cef2 100644 --- a/cui/source/inc/cuitabarea.hxx +++ b/cui/source/inc/cuitabarea.hxx @@ -18,20 +18,27 @@ */ #pragma once -#include +#include "SvxPresetListBox.hxx" + +#include #include #include #include -#include -#include #include #include #include +#include +#include #include #include #include +#include +#include #include +#include +#include #include +#include class ColorListBox; class SdrModel; @@ -393,20 +400,20 @@ private: std::unique_ptr m_xMtrColorFrom; std::unique_ptr m_xLbColorTo; std::unique_ptr m_xMtrColorTo; + std::unique_ptr m_xGradientPresets; std::unique_ptr m_xGradientLB; std::unique_ptr m_xMtrIncrement; std::unique_ptr m_xCbIncrement; std::unique_ptr m_xBtnAdd; std::unique_ptr m_xBtnModify; std::unique_ptr m_xCtlPreview; - std::unique_ptr m_xGradientLBWin; DECL_LINK( ClickAddHdl_Impl, weld::Button&, void ); DECL_LINK( ClickModifyHdl_Impl, weld::Button&, void ); - DECL_LINK( ChangeGradientHdl, ValueSet*, void ); + DECL_LINK(ChangeGradientHdl, const weld::TreeIter&, bool); void ChangeGradientHdl_Impl(); - DECL_LINK( ClickRenameHdl_Impl, SvxPresetListBox*, void ); - DECL_LINK( ClickDeleteHdl_Impl, SvxPresetListBox*, void ); + DECL_LINK(ClickRenameHdl_Impl, int, void); + DECL_LINK(ClickDeleteHdl_Impl, int, void); DECL_LINK( ModifiedEditHdl_Impl, weld::SpinButton&, void ); DECL_LINK( ModifiedMetricHdl_Impl, weld::MetricSpinButton&, void ); DECL_LINK( ModifiedColorListBoxHdl_Impl, ColorListBox&, void ); @@ -467,13 +474,13 @@ private: std::unique_ptr m_xLbLineColor; std::unique_ptr m_xCbBackgroundColor; std::unique_ptr m_xLbBackgroundColor; + std::unique_ptr m_xHatchPresets; std::unique_ptr m_xHatchLB; std::unique_ptr m_xBtnAdd; std::unique_ptr m_xBtnModify; - std::unique_ptr m_xHatchLBWin; std::unique_ptr m_xCtlPreview; - DECL_LINK(ChangeHatchHdl, ValueSet*, void); + DECL_LINK(ChangeHatchHdl, const weld::TreeIter&, bool); void ChangeHatchHdl_Impl(); DECL_LINK( ModifiedEditHdl_Impl, weld::MetricSpinButton&, void ); DECL_LINK( ModifiedListBoxHdl_Impl, weld::ComboBox&, void ); @@ -484,8 +491,8 @@ private: void ModifiedHdl_Impl(void const *); DECL_LINK( ClickAddHdl_Impl, weld::Button&, void ); DECL_LINK( ClickModifyHdl_Impl, weld::Button&, void ); - DECL_LINK( ClickRenameHdl_Impl, SvxPresetListBox*, void ); - DECL_LINK( ClickDeleteHdl_Impl, SvxPresetListBox*, void ); + DECL_LINK(ClickRenameHdl_Impl, int, void); + DECL_LINK(ClickDeleteHdl_Impl, int, void); sal_Int32 SearchHatchList(std::u16string_view rHatchName); @@ -516,26 +523,6 @@ public: class SvxBitmapTabPage : public SfxTabPage { - -public: - - class SvxPresetListBoxValueSet : public SvxPresetListBox - { - public: - SvxPresetListBoxValueSet(std::unique_ptr pWindow); - virtual bool KeyInput(const KeyEvent& rKEvt) override; - - void SetDialog(SvxBitmapTabPage* pSvxBitmapTabPage) - { - m_pSvxBitmapTabPage = pSvxBitmapTabPage; - } - - private: - SvxBitmapTabPage* m_pSvxBitmapTabPage; - }; - -private: - const SfxItemSet& m_rOutAttrs; XBitmapListRef m_pBitmapList; @@ -550,12 +537,13 @@ private: const SdrView* mpView; MapUnit mePoolUnit; FieldUnit meFieldUnit; - Size rBitmapSize; - Size rFilledSize; - Size rZoomedSize; + Size m_aBitmapSize; + Size m_aFilledSize; + Size m_aZoomedSize; SvxXRectPreview m_aCtlBitmapPreview; - std::unique_ptr m_xBitmapLB; + std::unique_ptr m_xBitmapsPresets; + std::unique_ptr m_xBitmapLB; std::unique_ptr m_xBitmapStyleLB; std::unique_ptr m_xSizeBox; std::unique_ptr m_xTsbScale; @@ -571,23 +559,21 @@ private: std::unique_ptr m_xTileOffset; std::unique_ptr m_xBtnImport; std::unique_ptr m_xCtlBitmapPreview; - std::unique_ptr m_xBitmapLBWin; - DECL_LINK( ModifyBitmapHdl, ValueSet*, void ); + DECL_LINK(ModifyBitmapHdl, const weld::TreeIter&, bool); DECL_LINK( ClickScaleHdl, weld::Toggleable&, void ); DECL_LINK( ModifyBitmapStyleHdl, weld::ComboBox&, void ); DECL_LINK( ModifyBitmapSizeHdl, weld::MetricSpinButton&, void ); DECL_LINK( ModifyBitmapPositionHdl, weld::ComboBox&, void ); DECL_LINK( ModifyPositionOffsetHdl, weld::MetricSpinButton&, void ); DECL_LINK( ModifyTileOffsetHdl, weld::MetricSpinButton&, void ); - DECL_LINK( ClickRenameHdl, SvxPresetListBox*, void ); - DECL_LINK( ClickDeleteHdl, SvxPresetListBox*, void ); + DECL_LINK(ClickRenameHdl, int, void); + DECL_LINK(ClickDeleteHdl, int, void); DECL_LINK( ClickImportHdl, weld::Button&, void ); - void ClickBitmapHdl_Impl(); void CalculateBitmapPresetSize(); - void DeleteBitmapHdl_Impl(const sal_uInt16 nId); sal_Int32 SearchBitmapList(std::u16string_view rBitmapName); sal_Int32 SearchBitmapList(const GraphicObject& rGraphicObject); + void UpdateBitmap(); tools::Long AddBitmap(const GraphicObject& rGraphicObject, const OUString& rName, bool bOnlyForThisDocument = false); @@ -628,21 +614,22 @@ private: std::unique_ptr m_xCtlPixel; std::unique_ptr m_xLbColor; std::unique_ptr m_xLbBackgroundColor; + std::unique_ptr m_xPatternPresets; std::unique_ptr m_xPatternLB; std::unique_ptr m_xBtnAdd; std::unique_ptr m_xBtnModify; std::unique_ptr m_xCtlPixelWin; std::unique_ptr m_xCtlPreview; - std::unique_ptr m_xPatternLBWin; std::unique_ptr m_xBitmapCtl; DECL_LINK( ClickAddHdl_Impl, weld::Button&, void ); DECL_LINK( ClickModifyHdl_Impl, weld::Button&, void ); - DECL_LINK( ChangePatternHdl_Impl, ValueSet*, void ); + DECL_LINK(ChangePatternHdl_Impl, const weld::TreeIter&, bool); DECL_LINK( ChangeColorHdl_Impl, ColorListBox&, void ); - DECL_LINK( ClickRenameHdl_Impl, SvxPresetListBox*, void ); - DECL_LINK( ClickDeleteHdl_Impl, SvxPresetListBox*, void ); + DECL_LINK(ClickRenameHdl_Impl, int, void); + DECL_LINK(ClickDeleteHdl_Impl, int, void); + void UpdatePattern(); sal_Int32 SearchPatternList(std::u16string_view rPatternName); public: @@ -695,8 +682,8 @@ private: PaletteManager maPaletteManager; SvxXRectPreview m_aCtlPreviewOld; SvxXRectPreview m_aCtlPreviewNew; - std::unique_ptr m_xValSetColorList; - std::unique_ptr m_xValSetRecentList; + ColorIconView m_aColorIconView; + ColorIconView m_aRecentIconView; std::unique_ptr m_xSelectPalette; std::unique_ptr m_xRbRGB; std::unique_ptr m_xRbCMYK; @@ -726,16 +713,13 @@ private: std::unique_ptr m_xMoreColors; std::unique_ptr m_xCtlPreviewOld; std::unique_ptr m_xCtlPreviewNew; - std::unique_ptr m_xValSetColorListWin; - std::unique_ptr m_xValSetRecentListWin; - static void ConvertColorValues (Color& rColor, ColorModel eModell); + static void ConvertColorValues (Color& rColor, ColorModel eModel); static void RgbToCmyk_Impl( Color& rColor, sal_uInt16& rK ); static void CmykToRgb_Impl( Color& rColor, const sal_uInt16 nKey ); sal_uInt16 ColorToPercent_Impl( sal_uInt16 nColor ); sal_uInt16 PercentToColor_Impl( sal_uInt16 nPercent ); - void ImpColorCountChanged(); void FillPaletteLB(); DECL_LINK(ClickAddHdl_Impl, weld::Button&, void); @@ -744,8 +728,10 @@ private: DECL_LINK(OnMoreColorsClick, weld::Button&, void); DECL_LINK(SelectPaletteLBHdl, weld::ComboBox&, void); - DECL_LINK( SelectValSetHdl_Impl, ValueSet*, void ); + DECL_LINK(ActivatePaletteColorHdl, const Color&, void); + DECL_LINK(ActivateRecentColorHdl, const Color&, void); DECL_LINK( SelectColorModeHdl_Impl, weld::Toggleable&, void ); + void UpdateToSelectedColor(const NamedColor& rNamedColor); void ChangeColor(const NamedColor &rNewColor, bool bUpdatePreset = true); void SetColorModel(ColorModel eModel); void ChangeColorModel(); @@ -754,8 +740,6 @@ private: DECL_LINK(MetricSpinValueHdl_Impl, weld::MetricSpinButton&, void); DECL_LINK(ModifiedHdl_Impl, weld::Entry&, void); - void UpdateModified(); - static sal_Int32 FindInCustomColors( std::u16string_view aColorName ); sal_Int32 FindInPalette( const Color& rColor ); diff --git a/cui/source/inc/cuitabline.hxx b/cui/source/inc/cuitabline.hxx index 310f2bfab26a..63d555d08be1 100644 --- a/cui/source/inc/cuitabline.hxx +++ b/cui/source/inc/cuitabline.hxx @@ -29,9 +29,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include diff --git a/cui/source/inc/cuitbxform.hxx b/cui/source/inc/cuitbxform.hxx index 11ec5d78a3b1..02468f2a8777 100644 --- a/cui/source/inc/cuitbxform.hxx +++ b/cui/source/inc/cuitbxform.hxx @@ -20,7 +20,7 @@ #include #include -#include +#include class FmInputRecordNoDialog : public weld::GenericDialogController { diff --git a/cui/source/inc/dbregister.hxx b/cui/source/inc/dbregister.hxx index ebc6bc6ec9f2..62c4cc422c29 100644 --- a/cui/source/inc/dbregister.hxx +++ b/cui/source/inc/dbregister.hxx @@ -22,7 +22,9 @@ #include #include #include +#include #include +#include namespace svx { diff --git a/cui/source/inc/fileextcheckdlg.hxx b/cui/source/inc/fileextcheckdlg.hxx index 99e4bc9592da..12a7ef2f1e9f 100644 --- a/cui/source/inc/fileextcheckdlg.hxx +++ b/cui/source/inc/fileextcheckdlg.hxx @@ -20,8 +20,11 @@ #include +#include +#include #include -#include +#include +#include class FileExtCheckDialog : public weld::GenericDialogController { diff --git a/cui/source/inc/grfpage.hxx b/cui/source/inc/grfpage.hxx index d4fada67e8e2..43e2213691a3 100644 --- a/cui/source/inc/grfpage.hxx +++ b/cui/source/inc/grfpage.hxx @@ -21,8 +21,11 @@ #include #include +#include #include +#include #include +#include #include #include diff --git a/cui/source/inc/hangulhanjadlg.hxx b/cui/source/inc/hangulhanjadlg.hxx index 9586b582a680..8012d7ecb79a 100644 --- a/cui/source/inc/hangulhanjadlg.hxx +++ b/cui/source/inc/hangulhanjadlg.hxx @@ -20,287 +20,288 @@ #include #include +#include +#include #include #include #include +#include +#include +#include #include #include -#include #include #include #include -#include #include #include namespace svx { +class SuggestionDisplay +{ +public: + SuggestionDisplay(weld::Builder& rBuilder); - class SuggestionSet : public ValueSet + void DisplayListBox(bool bDisplayListBox); + + void SetSelectHdl(const Link& rLink); + + void Clear(); + void InsertEntry(const OUString& rStr); + void SelectEntryPos(sal_uInt16 nPos); + + sal_uInt16 GetEntryCount() const; + + OUString GetEntry(sal_uInt16 nPos) const; + OUString GetSelectedEntry() const; + + DECL_LINK(SelectSuggestionListBoxHdl, weld::ItemView&, void); + DECL_LINK(SelectSuggestionIconViewHdl, weld::ItemView&, void); + void SelectSuggestionHdl(bool bListBox); + + void SetHelpIds(); + + void set_size_request(int nWidth, int nHeight) { - public: - SuggestionSet(std::unique_ptr xScrolledWindow); + m_xIconView->set_size_request(nWidth, nHeight); + m_xListBox->set_size_request(nWidth, nHeight); + } - virtual void UserDraw( const UserDrawEvent& rUDEvt ) override; - }; +private: + ScopedVclPtr CreateIcon(const OUString& rText); + void implUpdateDisplay(); + weld::Widget& implGetCurrentControl(); - class SuggestionDisplay - { - public: - SuggestionDisplay(weld::Builder& rBuilder); +private: + bool m_bDisplayListBox; // otherwise IconView + bool m_bInSelectionUpdate; + Link m_aSelectLink; - void DisplayListBox( bool bDisplayListBox ); + std::unique_ptr m_xIconView; + std::unique_ptr m_xListBox; +}; - void SetSelectHdl( const Link& rLink ); +class RubyRadioButton; - void Clear(); - void InsertEntry( const OUString& rStr ); - void SelectEntryPos( sal_uInt16 nPos ); +class HangulHanjaConversionDialog : public weld::GenericDialogController +{ +private: + /** are we working for a document? This is normally true, but in case + the user uses the "find" functionality, we switch to working + with what the user entered, which then does not have any relation to + the document anymore. Some functionality must be disabled then */ + bool m_bDocumentMode; - sal_uInt16 GetEntryCount() const; + Link m_aOptionsChangedLink; + Link m_aClickByCharacterLink; - OUString GetEntry( sal_uInt16 nPos ) const; - OUString GetSelectedEntry() const; + std::unique_ptr m_xFind; + std::unique_ptr m_xIgnore; + std::unique_ptr m_xIgnoreAll; + std::unique_ptr m_xReplace; + std::unique_ptr m_xReplaceAll; + std::unique_ptr m_xOptions; + std::unique_ptr m_xSuggestions; + std::unique_ptr m_xSimpleConversion; + std::unique_ptr m_xHangulBracketed; + std::unique_ptr m_xHanjaBracketed; + std::unique_ptr m_xWordInput; + std::unique_ptr m_xOriginalWord; + std::unique_ptr m_xHanjaAbove; + std::unique_ptr m_xHanjaBelow; + std::unique_ptr m_xHangulAbove; + std::unique_ptr m_xHangulBelow; + std::unique_ptr m_xHangulOnly; + std::unique_ptr m_xHanjaOnly; + std::unique_ptr m_xReplaceByChar; - DECL_LINK(SelectSuggestionListBoxHdl, weld::ItemView&, void); - DECL_LINK( SelectSuggestionValueSetHdl, ValueSet*, void ); - void SelectSuggestionHdl(bool bListBox); +public: + HangulHanjaConversionDialog(weld::Widget* pParent); + virtual ~HangulHanjaConversionDialog() override; - void SetHelpIds(); +public: + void SetOptionsChangedHdl(const Link& _rHdl); + void SetIgnoreHdl(const Link& _rHdl); + void SetIgnoreAllHdl(const Link& _rHdl); + void SetChangeHdl(const Link& _rHdl); + void SetChangeAllHdl(const Link& _rHdl); - void set_size_request(int nWidth, int nHeight) - { - m_xValueSetWin->set_size_request(nWidth, nHeight); - m_xListBox->set_size_request(nWidth, nHeight); - } + void SetClickByCharacterHdl(const Link& _rHdl); + void SetConversionFormatChangedHdl(const Link& _rHdl); + void SetFindHdl(const Link& _rHdl); - private: - void implUpdateDisplay(); - weld::Widget& implGetCurrentControl(); + OUString GetCurrentString() const; + void SetCurrentString(const OUString& _rNewString, + const css::uno::Sequence& _rSuggestions, + bool _bOriginatesFromDocument); - private: - bool m_bDisplayListBox; //otherwise ValueSet - bool m_bInSelectionUpdate; - Link m_aSelectLink; + void FocusSuggestion(); - std::unique_ptr m_xValueSet; - std::unique_ptr m_xValueSetWin; - std::unique_ptr m_xListBox; - }; + /// retrieves the current suggestion + OUString GetCurrentSuggestion() const; - class RubyRadioButton; + void SetConversionFormat(editeng::HangulHanjaConversion::ConversionFormat _eType); + editeng::HangulHanjaConversion::ConversionFormat GetConversionFormat() const; - class HangulHanjaConversionDialog : public weld::GenericDialogController - { - private: - /** are we working for a document? This is normally true, but in case - the user uses the "find" functionality, we switch to working - with what the user entered, which then does not have any relation to - the document anymore. Some functionality must be disabled then */ - bool m_bDocumentMode; + void SetByCharacter(bool _bByCharacter); + void SetConversionDirectionState( + bool _bTryBothDirections, + editeng::HangulHanjaConversion::ConversionDirection _ePrimaryConversionDirection); - Link m_aOptionsChangedLink; - Link m_aClickByCharacterLink; + /// should text which does not match the primary conversion direction be ignored? + bool GetUseBothDirections() const; - std::unique_ptr m_xFind; - std::unique_ptr m_xIgnore; - std::unique_ptr m_xIgnoreAll; - std::unique_ptr m_xReplace; - std::unique_ptr m_xReplaceAll; - std::unique_ptr m_xOptions; - std::unique_ptr m_xSuggestions; - std::unique_ptr m_xSimpleConversion; - std::unique_ptr m_xHangulBracketed; - std::unique_ptr m_xHanjaBracketed; - std::unique_ptr m_xWordInput; - std::unique_ptr m_xOriginalWord; - std::unique_ptr m_xHanjaAbove; - std::unique_ptr m_xHanjaBelow; - std::unique_ptr m_xHangulAbove; - std::unique_ptr m_xHangulBelow; - std::unique_ptr m_xHangulOnly; - std::unique_ptr m_xHanjaOnly; - std::unique_ptr m_xReplaceByChar; - public: - HangulHanjaConversionDialog(weld::Widget* pParent); - virtual ~HangulHanjaConversionDialog() override; - - public: - void SetOptionsChangedHdl( const Link& _rHdl ); - void SetIgnoreHdl( const Link& _rHdl ); - void SetIgnoreAllHdl( const Link& _rHdl ); - void SetChangeHdl( const Link& _rHdl ); - void SetChangeAllHdl( const Link& _rHdl ); - - void SetClickByCharacterHdl( const Link& _rHdl ); - void SetConversionFormatChangedHdl( const Link& _rHdl ); - void SetFindHdl( const Link& _rHdl ); - - OUString GetCurrentString( ) const; - void SetCurrentString( - const OUString& _rNewString, - const css::uno::Sequence< OUString >& _rSuggestions, - bool _bOriginatesFromDocument - ); - - void FocusSuggestion( ); - - /// retrieves the current suggestion - OUString GetCurrentSuggestion( ) const; - - void SetConversionFormat( editeng::HangulHanjaConversion::ConversionFormat _eType ); - editeng::HangulHanjaConversion::ConversionFormat GetConversionFormat( ) const; - - void SetByCharacter( bool _bByCharacter ); - void SetConversionDirectionState( bool _bTryBothDirections, editeng::HangulHanjaConversion::ConversionDirection _ePrimaryConversionDirection ); - - /// should text which does not match the primary conversion direction be ignored? - bool GetUseBothDirections( ) const; - - /** get current conversion direction to use + /** get current conversion direction to use (return argument if GetUseBothDirections is true) */ - editeng::HangulHanjaConversion::ConversionDirection GetDirection( editeng::HangulHanjaConversion::ConversionDirection eDefaultDirection ) const; + editeng::HangulHanjaConversion::ConversionDirection + GetDirection(editeng::HangulHanjaConversion::ConversionDirection eDefaultDirection) const; - /// enables or disables the checkboxes for ruby formatted replacements - void EnableRubySupport( bool bVal ); + /// enables or disables the checkboxes for ruby formatted replacements + void EnableRubySupport(bool bVal); - private: - DECL_LINK( OnOption, weld::Button&, void ); - DECL_LINK( OnSuggestionModified, weld::Entry&, void ); - DECL_LINK( OnSuggestionSelected, SuggestionDisplay&, void ); - DECL_LINK( OnConversionDirectionClicked, weld::Toggleable&, void ); - DECL_LINK( ClickByCharacterHdl, weld::Toggleable&, void ); +private: + DECL_LINK(OnOption, weld::Button&, void); + DECL_LINK(OnSuggestionModified, weld::TextWidget&, void); + DECL_LINK(OnSuggestionSelected, SuggestionDisplay&, void); + DECL_LINK(OnConversionDirectionClicked, weld::Toggleable&, void); + DECL_LINK(ClickByCharacterHdl, weld::Toggleable&, void); - /// fill the suggestion list box with suggestions for the actual input - void FillSuggestions( const css::uno::Sequence< OUString >& _rSuggestions ); - }; + /// fill the suggestion list box with suggestions for the actual input + void FillSuggestions(const css::uno::Sequence& _rSuggestions); +}; +typedef std::vector> HHDictList; - typedef std::vector< css::uno::Reference< css::linguistic2::XConversionDictionary > > HHDictList; +class HangulHanjaOptionsDialog : public weld::GenericDialogController +{ +private: + HHDictList m_aDictList; + css::uno::Reference m_xConversionDictionaryList; - class HangulHanjaOptionsDialog : public weld::GenericDialogController + std::unique_ptr m_xDictsLB; + std::unique_ptr m_xIgnorepostCB; + std::unique_ptr m_xShowrecentlyfirstCB; + std::unique_ptr m_xAutoreplaceuniqueCB; + std::unique_ptr m_xNewPB; + std::unique_ptr m_xEditPB; + std::unique_ptr m_xDeletePB; + std::unique_ptr m_xOkPB; + + DECL_LINK(OkHdl, weld::Button&, void); + DECL_LINK(DictsLB_SelectHdl, weld::ItemView&, void); + DECL_LINK(NewDictHdl, weld::Button&, void); + DECL_LINK(EditDictHdl, weld::Button&, void); + DECL_LINK(DeleteDictHdl, weld::Button&, void); + + void Init(); ///< reads settings from core and init controls +public: + HangulHanjaOptionsDialog(weld::Window* pParent); + virtual ~HangulHanjaOptionsDialog() override; + + void AddDict(const OUString& _rName, bool _bChecked); +}; + +class HangulHanjaNewDictDialog : public weld::GenericDialogController +{ +private: + bool m_bEntered; + + std::unique_ptr m_xOkBtn; + std::unique_ptr m_xDictNameED; + + DECL_LINK(OKHdl, weld::Button&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); + +public: + HangulHanjaNewDictDialog(weld::Window* pParent); + virtual ~HangulHanjaNewDictDialog() override; + + bool GetName(OUString& _rRetName) const; +}; + +class SuggestionList; +class HangulHanjaEditDictDialog; + +class SuggestionEdit +{ +private: + HangulHanjaEditDictDialog* m_pParent; + SuggestionEdit* m_pPrev; + SuggestionEdit* m_pNext; + weld::ScrolledWindow* m_pScrollBar; + std::unique_ptr m_xEntry; + + bool ShouldScroll(bool _bUp) const; + void DoJump(bool _bUp); + +public: + SuggestionEdit(std::unique_ptr xEntry, HangulHanjaEditDictDialog* pParent); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + void init(weld::ScrolledWindow* pScrollBar, SuggestionEdit* pPrev, SuggestionEdit* pNext); + + void grab_focus() { m_xEntry->grab_focus(); } + void set_text(const OUString& rText) { m_xEntry->set_text(rText); } + void connect_changed(const Link& rLink) { - private: - HHDictList m_aDictList; - css::uno::Reference< css::linguistic2::XConversionDictionaryList > m_xConversionDictionaryList; + m_xEntry->connect_changed(rLink); + } +}; - std::unique_ptr m_xDictsLB; - std::unique_ptr m_xIgnorepostCB; - std::unique_ptr m_xShowrecentlyfirstCB; - std::unique_ptr m_xAutoreplaceuniqueCB; - std::unique_ptr m_xNewPB; - std::unique_ptr m_xEditPB; - std::unique_ptr m_xDeletePB; - std::unique_ptr m_xOkPB; +class HangulHanjaEditDictDialog : public weld::GenericDialogController +{ +private: + const OUString m_aEditHintText; + HHDictList& m_rDictList; + sal_uInt32 m_nCurrentDict; - DECL_LINK( OkHdl, weld::Button&, void ); - DECL_LINK(DictsLB_SelectHdl, weld::ItemView&, void); - DECL_LINK( NewDictHdl, weld::Button&, void ); - DECL_LINK( EditDictHdl, weld::Button&, void ); - DECL_LINK( DeleteDictHdl, weld::Button&, void ); + OUString m_aOriginal; + std::unique_ptr m_xSuggestions; - void Init(); ///< reads settings from core and init controls - public: - HangulHanjaOptionsDialog(weld::Window* pParent); - virtual ~HangulHanjaOptionsDialog() override; + sal_uInt16 m_nTopPos; + bool m_bModifiedSuggestions; + bool m_bModifiedOriginal; - void AddDict( const OUString& _rName, bool _bChecked ); - }; + std::unique_ptr m_xBookLB; + std::unique_ptr m_xOriginalLB; + std::unique_ptr m_xEdit1; + std::unique_ptr m_xEdit2; + std::unique_ptr m_xEdit3; + std::unique_ptr m_xEdit4; + std::unique_ptr m_xContents; + std::unique_ptr m_xScrollSB; + std::unique_ptr m_xNewPB; + std::unique_ptr m_xDeletePB; - class HangulHanjaNewDictDialog : public weld::GenericDialogController - { - private: - bool m_bEntered; + DECL_LINK(OriginalModifyHdl, weld::ComboBox&, void); + DECL_LINK(ScrollHdl, weld::ScrolledWindow&, void); + DECL_LINK(EditModifyHdl1, weld::TextWidget&, void); + DECL_LINK(EditModifyHdl2, weld::TextWidget&, void); + DECL_LINK(EditModifyHdl3, weld::TextWidget&, void); + DECL_LINK(EditModifyHdl4, weld::TextWidget&, void); - std::unique_ptr m_xOkBtn; - std::unique_ptr m_xDictNameED; + DECL_LINK(BookLBSelectHdl, weld::ComboBox&, void); + DECL_LINK(NewPBPushHdl, weld::Button&, void); + DECL_LINK(DeletePBPushHdl, weld::Button&, void); - DECL_LINK(OKHdl, weld::Button&, void); - DECL_LINK(ModifyHdl, weld::Entry&, void); - public: - HangulHanjaNewDictDialog(weld::Window* pParent); - virtual ~HangulHanjaNewDictDialog() override; + void InitEditDictDialog(sal_uInt32 nSelDict); + void UpdateOriginalLB(); + void UpdateSuggestions(); + void UpdateButtonStates(); - bool GetName( OUString& _rRetName ) const; - }; + void SetEditText(SuggestionEdit& rEdit, sal_uInt16 nEntryNum); + void EditModify(const weld::TextWidget* pEdit, sal_uInt8 nEntryOffset); - class SuggestionList; - class HangulHanjaEditDictDialog; + bool DeleteEntryFromDictionary( + const css::uno::Reference& xDict); - class SuggestionEdit - { - private: - HangulHanjaEditDictDialog* m_pParent; - SuggestionEdit* m_pPrev; - SuggestionEdit* m_pNext; - weld::ScrolledWindow* m_pScrollBar; - std::unique_ptr m_xEntry; +public: + HangulHanjaEditDictDialog(weld::Window* pParent, HHDictList& rDictList, sal_uInt32 nSelDict); + virtual ~HangulHanjaEditDictDialog() override; - bool ShouldScroll( bool _bUp ) const; - void DoJump( bool _bUp ); - public: - SuggestionEdit(std::unique_ptr xEntry, HangulHanjaEditDictDialog* pParent); - DECL_LINK(KeyInputHdl, const KeyEvent&, bool); - void init(weld::ScrolledWindow* pScrollBar, SuggestionEdit* pPrev, SuggestionEdit* pNext); - - void grab_focus() { m_xEntry->grab_focus(); } - void set_text(const OUString& rText) { m_xEntry->set_text(rText); } - void connect_changed(const Link& rLink) { m_xEntry->connect_changed(rLink); } - }; - - class HangulHanjaEditDictDialog : public weld::GenericDialogController - { - private: - const OUString m_aEditHintText; - HHDictList& m_rDictList; - sal_uInt32 m_nCurrentDict; - - OUString m_aOriginal; - std::unique_ptr m_xSuggestions; - - sal_uInt16 m_nTopPos; - bool m_bModifiedSuggestions; - bool m_bModifiedOriginal; - - std::unique_ptr m_xBookLB; - std::unique_ptr m_xOriginalLB; - std::unique_ptr m_xEdit1; - std::unique_ptr m_xEdit2; - std::unique_ptr m_xEdit3; - std::unique_ptr m_xEdit4; - std::unique_ptr m_xContents; - std::unique_ptr m_xScrollSB; - std::unique_ptr m_xNewPB; - std::unique_ptr m_xDeletePB; - - DECL_LINK( OriginalModifyHdl, weld::ComboBox&, void ); - DECL_LINK( ScrollHdl, weld::ScrolledWindow&, void ); - DECL_LINK( EditModifyHdl1, weld::Entry&, void ); - DECL_LINK( EditModifyHdl2, weld::Entry&, void ); - DECL_LINK( EditModifyHdl3, weld::Entry&, void ); - DECL_LINK( EditModifyHdl4, weld::Entry&, void ); - - DECL_LINK( BookLBSelectHdl, weld::ComboBox&, void ); - DECL_LINK( NewPBPushHdl, weld::Button&, void ); - DECL_LINK( DeletePBPushHdl, weld::Button&, void ); - - void InitEditDictDialog(sal_uInt32 nSelDict); - void UpdateOriginalLB(); - void UpdateSuggestions(); - void UpdateButtonStates(); - - void SetEditText( SuggestionEdit& rEdit, sal_uInt16 nEntryNum ); - void EditModify( const weld::Entry* pEdit, sal_uInt8 nEntryOffset ); - - bool DeleteEntryFromDictionary( const css::uno::Reference< css::linguistic2::XConversionDictionary >& xDict ); - - public: - HangulHanjaEditDictDialog(weld::Window* pParent, HHDictList& rDictList, sal_uInt32 nSelDict); - virtual ~HangulHanjaEditDictDialog() override; - - void UpdateScrollbar(); - }; + void UpdateScrollbar(); +}; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/headertablistbox.hxx b/cui/source/inc/headertablistbox.hxx index 969813691c9f..15a8d6a2313a 100644 --- a/cui/source/inc/headertablistbox.hxx +++ b/cui/source/inc/headertablistbox.hxx @@ -20,7 +20,6 @@ #pragma once #include -#include class MacroEventListBox final { diff --git a/cui/source/inc/hlmarkwn.hxx b/cui/source/inc/hlmarkwn.hxx index ebd6384bdb42..7a1d36b6e0d9 100644 --- a/cui/source/inc/hlmarkwn.hxx +++ b/cui/source/inc/hlmarkwn.hxx @@ -19,10 +19,13 @@ #pragma once -#include +#include #include +#include #include -#include +#include + +#include class HyperlinkTabPageBase; diff --git a/cui/source/inc/hyperlinkdlg.hxx b/cui/source/inc/hyperlinkdlg.hxx index cbb1d66f1345..9e17e60c9fb1 100644 --- a/cui/source/inc/hyperlinkdlg.hxx +++ b/cui/source/inc/hyperlinkdlg.hxx @@ -16,7 +16,7 @@ #include #include #include -#include +#include class HyperlinkDialog : public SfxTabDialogController { diff --git a/cui/source/inc/hyperlinkdoctabpage.hxx b/cui/source/inc/hyperlinkdoctabpage.hxx index 039860537544..62d47fa9e3f5 100644 --- a/cui/source/inc/hyperlinkdoctabpage.hxx +++ b/cui/source/inc/hyperlinkdoctabpage.hxx @@ -9,7 +9,8 @@ #pragma once -#include +#include +#include #include #include "hyperlinktabpagebase.hxx" @@ -28,7 +29,7 @@ private: DECL_LINK(ClickFileopenHdl_Impl, weld::Button&, void); DECL_LINK(ClickTargetHdl_Impl, weld::Button&, void); DECL_LINK(ModifiedPathHdl_Impl, weld::ComboBox&, void); - DECL_LINK(ModifiedTargetHdl_Impl, weld::Entry&, void); + DECL_LINK(ModifiedTargetHdl_Impl, weld::TextWidget&, void); DECL_LINK(LostFocusPathHdl_Impl, weld::Widget&, void); DECL_LINK(TimeoutHdl_Impl, Timer*, void); diff --git a/cui/source/inc/hyperlinkinternettabpage.hxx b/cui/source/inc/hyperlinkinternettabpage.hxx index f2f0338468a8..acada3c8d090 100644 --- a/cui/source/inc/hyperlinkinternettabpage.hxx +++ b/cui/source/inc/hyperlinkinternettabpage.hxx @@ -9,10 +9,11 @@ #pragma once -#include -#include #include "hyperlinktabpagebase.hxx" +#include +#include + class HyperlinkInternetTP final : public HyperlinkTabPageBase { private: diff --git a/cui/source/inc/hyperlinkmailtabpage.hxx b/cui/source/inc/hyperlinkmailtabpage.hxx index 13d81a9d4511..6e588b30fc2a 100644 --- a/cui/source/inc/hyperlinkmailtabpage.hxx +++ b/cui/source/inc/hyperlinkmailtabpage.hxx @@ -9,9 +9,10 @@ #pragma once -#include #include #include +#include + #include "hyperlinktabpagebase.hxx" class HyperlinkMailTabPage final : public HyperlinkTabPageBase diff --git a/cui/source/inc/hyperlinknewdoctabpage.hxx b/cui/source/inc/hyperlinknewdoctabpage.hxx index 30994314ae58..e31f2f81d1b2 100644 --- a/cui/source/inc/hyperlinknewdoctabpage.hxx +++ b/cui/source/inc/hyperlinknewdoctabpage.hxx @@ -10,7 +10,8 @@ #pragma once #include -#include +#include +#include #include #include #include diff --git a/cui/source/inc/hyperlinktabpagebase.hxx b/cui/source/inc/hyperlinktabpagebase.hxx index 53b5465ebf46..5c5621703581 100644 --- a/cui/source/inc/hyperlinktabpagebase.hxx +++ b/cui/source/inc/hyperlinktabpagebase.hxx @@ -10,7 +10,8 @@ #pragma once #include -#include + +#include #include #include #include diff --git a/cui/source/inc/hyphen.hxx b/cui/source/inc/hyphen.hxx index 75f8bb7264b6..137507ad068d 100644 --- a/cui/source/inc/hyphen.hxx +++ b/cui/source/inc/hyphen.hxx @@ -21,8 +21,8 @@ #include #include +#include #include -#include #include #include #include diff --git a/cui/source/inc/insdlg.hxx b/cui/source/inc/insdlg.hxx index 38ca16b72fb9..1b4ce8c170e3 100644 --- a/cui/source/inc/insdlg.hxx +++ b/cui/source/inc/insdlg.hxx @@ -23,12 +23,16 @@ #include #include +#include +#include #include #include #include +#include +#include +#include #include #include -#include #include class InsertObjectDialog_Impl : public weld::GenericDialogController diff --git a/cui/source/inc/insrc.hxx b/cui/source/inc/insrc.hxx index f42458a493e7..ac0709e2bbb3 100644 --- a/cui/source/inc/insrc.hxx +++ b/cui/source/inc/insrc.hxx @@ -21,8 +21,9 @@ #include #include +#include #include -#include +#include class SvxInsRowColDlg : public weld::GenericDialogController { diff --git a/cui/source/inc/labdlg.hxx b/cui/source/inc/labdlg.hxx index 0ce3f7ff2c1c..ca70d48dc082 100644 --- a/cui/source/inc/labdlg.hxx +++ b/cui/source/inc/labdlg.hxx @@ -24,7 +24,10 @@ #include #include #include +#include +#include #include +#include class SdrView; diff --git a/cui/source/inc/linkdlg.hxx b/cui/source/inc/linkdlg.hxx index 5a01f265ff36..76a1587c3d82 100644 --- a/cui/source/inc/linkdlg.hxx +++ b/cui/source/inc/linkdlg.hxx @@ -21,9 +21,13 @@ #include #include -#include +#include #include -#include +#include +#include +#include +#include +#include /********************** SvUpdateLinksDialog ****************************** *************************************************************************/ diff --git a/cui/source/inc/macroass.hxx b/cui/source/inc/macroass.hxx index b93a1dde9756..584b88f9ae45 100644 --- a/cui/source/inc/macroass.hxx +++ b/cui/source/inc/macroass.hxx @@ -27,8 +27,10 @@ #include #include #include +#include +#include #include -#include + #include #include diff --git a/cui/source/inc/macropg.hxx b/cui/source/inc/macropg.hxx index 2e9f24e1e21d..cd19082836ec 100644 --- a/cui/source/inc/macropg.hxx +++ b/cui/source/inc/macropg.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff --git a/cui/source/inc/measure.hxx b/cui/source/inc/measure.hxx index a42da854a289..4cb872847fda 100644 --- a/cui/source/inc/measure.hxx +++ b/cui/source/inc/measure.hxx @@ -21,7 +21,9 @@ #include #include #include +#include #include +#include #include #include @@ -49,6 +51,7 @@ private: std::unique_ptr m_xMtrFldHelpline2Len; std::unique_ptr m_xTsbBelowRefEdge; std::unique_ptr m_xMtrFldDecimalPlaces; + std::unique_ptr m_xTsbAutoDecimalPlaces; std::unique_ptr m_xTsbAutoPosV; std::unique_ptr m_xTsbAutoPosH; std::unique_ptr m_xTsbShowUnit; diff --git a/cui/source/inc/multipat.hxx b/cui/source/inc/multipat.hxx index 7b428bf50de0..445aeb00fa9a 100644 --- a/cui/source/inc/multipat.hxx +++ b/cui/source/inc/multipat.hxx @@ -18,10 +18,10 @@ */ #pragma once +#include #include #include #include -#include class SvxMultiPathDialog : public weld::GenericDialogController { diff --git a/cui/source/inc/newtabledlg.hxx b/cui/source/inc/newtabledlg.hxx index 1aceebd6d670..40b73f7bf3de 100644 --- a/cui/source/inc/newtabledlg.hxx +++ b/cui/source/inc/newtabledlg.hxx @@ -21,7 +21,7 @@ #include #include #include -#include +#include class SvxNewTableDialog : public weld::GenericDialogController { diff --git a/cui/source/inc/numfmt.hxx b/cui/source/inc/numfmt.hxx index a51ddd1e70e7..6d5296455934 100644 --- a/cui/source/inc/numfmt.hxx +++ b/cui/source/inc/numfmt.hxx @@ -23,12 +23,15 @@ #include #include #include +#include +#include #include #include +#include +#include #include #include #include -#include class SvxNumberFormatShell; class SvxNumberInfoItem; @@ -142,10 +145,10 @@ private: DECL_LINK(SelFormatClickHdl_Impl, weld::Toggleable&, void); void SelFormatHdl_Impl(weld::Widget*); DECL_LINK(ClickHdl_Impl, weld::Button&, void); - DECL_LINK(EditModifyHdl_Impl, weld::Entry&, void); + DECL_LINK(EditModifyHdl_Impl, weld::TextWidget&, void); DECL_LINK(OptEditHdl_Impl, weld::SpinButton&, void); DECL_LINK(OptClickHdl_Impl, weld::Toggleable&, void); - void EditHdl_Impl(const weld::Entry*); + void EditHdl_Impl(const weld::TextWidget*); void OptHdl_Impl(const weld::Widget*); // set and get currency, taking into account if the legacy diff --git a/cui/source/inc/numpages.hxx b/cui/source/inc/numpages.hxx index 85ab4de4c779..65fc9364d9f1 100644 --- a/cui/source/inc/numpages.hxx +++ b/cui/source/inc/numpages.hxx @@ -26,7 +26,11 @@ #include #include #include +#include +#include #include +#include +#include #include #include #include @@ -291,7 +295,7 @@ class SvxNumOptionsTabPage : public SfxTabPage DECL_LINK(SizeHdl_Impl, weld::MetricSpinButton&, void); DECL_LINK(RatioHdl_Impl, weld::Toggleable&, void); DECL_LINK(CharFmtHdl_Impl, weld::ComboBox&, void); - DECL_LINK(EditModifyHdl_Impl, weld::Entry&, void); + DECL_LINK(EditModifyHdl_Impl, weld::TextWidget&, void); DECL_LINK(SpinModifyHdl_Impl, weld::SpinButton&, void); DECL_LINK(AllLevelHdl_Impl, weld::SpinButton&, void); DECL_LINK(IsLegalHdl_Impl, weld::Toggleable&, void); @@ -300,7 +304,7 @@ class SvxNumOptionsTabPage : public SfxTabPage DECL_LINK(BulColorHdl_Impl, ColorListBox&, void); DECL_LINK(BulRelSizeHdl_Impl, weld::MetricSpinButton&, void); DECL_LINK(PreviewInvalidateHdl_Impl, Timer*, void); - void EditModifyHdl_Impl(const weld::Entry*); + void EditModifyHdl_Impl(const weld::TextWidget*); public: SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); diff --git a/cui/source/inc/optasian.hxx b/cui/source/inc/optasian.hxx index 5303e4799f55..0a242e0d147b 100644 --- a/cui/source/inc/optasian.hxx +++ b/cui/source/inc/optasian.hxx @@ -21,7 +21,10 @@ #include #include #include +#include #include +#include +#include struct SvxAsianLayoutPage_Impl; class SvxAsianLayoutPage : public SfxTabPage @@ -44,7 +47,7 @@ class SvxAsianLayoutPage : public SfxTabPage DECL_LINK(LanguageHdl, weld::ComboBox&, void); DECL_LINK(ChangeStandardHdl, weld::Toggleable&, void); - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); public: SvxAsianLayoutPage(weld::Container* pPage, weld::DialogController* pController, diff --git a/cui/source/inc/optdict.hxx b/cui/source/inc/optdict.hxx index 56de74189d8c..3f61d6cb7434 100644 --- a/cui/source/inc/optdict.hxx +++ b/cui/source/inc/optdict.hxx @@ -18,10 +18,14 @@ */ #pragma once +#include +#include +#include #include #include +#include #include -#include +#include #include #include #include @@ -47,7 +51,7 @@ private: css::uno::Reference m_xNewDic; DECL_LINK(OKHdl_Impl, weld::Button&, void); - DECL_LINK(ModifyHdl_Impl, weld::Entry&, void); + DECL_LINK(ModifyHdl_Impl, weld::TextWidget&, void); public: SvxNewDictionaryDialog(weld::Window* pParent); @@ -72,6 +76,8 @@ private: bool bDoNothing; bool bDicIsReadonly; + std::vector m_aSortedDicEntries; + weld::TreeView* m_pWordsLB; std::unique_ptr m_xAllDictsLB; std::unique_ptr m_xLangFT; @@ -89,7 +95,7 @@ private: DECL_LINK(SelectHdl, weld::ItemView&, void); DECL_LINK(NewDelButtonHdl, weld::Button&, void); DECL_LINK(NewDelActionHdl, weld::Entry&, bool); - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); DECL_LINK(EntrySizeAllocHdl, const Size&, void); bool NewDelHdl(const weld::Widget*); @@ -101,6 +107,7 @@ private: void RemoveDictEntry(int nEntry); int GetLBInsertPos(std::u16string_view rDicWord); + void RebuildSortedDicEntries(); public: SvxEditDictionaryDialog(weld::Window* pParent, std::u16string_view rName); diff --git a/cui/source/inc/optlingu.hxx b/cui/source/inc/optlingu.hxx index e149a0fefe0b..12310e0e0bb8 100644 --- a/cui/source/inc/optlingu.hxx +++ b/cui/source/inc/optlingu.hxx @@ -23,9 +23,16 @@ #include #include #include +#include +#include +#include #include +#include +#include #include +#include + namespace com::sun::star{ namespace linguistic2{ class XDictionary; @@ -72,39 +79,37 @@ public: struct ImplSVEvent; +typedef std::map> LangImplNameTable; + // class SvxLinguTabPage ------------------------------------------------- class SvxLinguTabPage : public SfxTabPage { private: - OUString sCapitalWords; - OUString sWordsWithDigits; - OUString sSpellSpecial; - OUString sSpellAuto; - OUString sSpellClosedCompound; - OUString sSpellHyphenatedCompound; - OUString sGrammarAuto; - OUString sNumMinWordlen; - OUString sNumPreBreak; - OUString sNumPostBreak; - OUString sHyphAuto; - OUString sHyphSpecial; + OUString m_sCapitalWords; + OUString m_sWordsWithDigits; + OUString m_sSpellSpecial; + OUString m_sSpellAuto; + OUString m_sSpellClosedCompound; + OUString m_sSpellHyphenatedCompound; + OUString m_sGrammarAuto; + OUString m_sNumMinWordlen; + OUString m_sNumPreBreak; + OUString m_sNumPostBreak; + OUString m_sHyphAuto; + OUString m_sHyphSpecial; - int nUPN_HYPH_MIN_WORD_LENGTH; - int nUPN_HYPH_MIN_LEADING; - int nUPN_HYPH_MIN_TRAILING; + int m_nUPN_HYPH_MIN_WORD_LENGTH; + int m_nUPN_HYPH_MIN_LEADING; + int m_nUPN_HYPH_MIN_TRAILING; ImplSVEvent* m_nDlbClickEventId; - css::uno::Reference< - css::linguistic2::XLinguProperties > xProp; + css::uno::Reference m_xProp; - css::uno::Reference< - css::linguistic2::XDictionaryList > xDicList; - css::uno::Sequence< - css::uno::Reference< - css::linguistic2::XDictionary > > aDics; + css::uno::Reference m_xDicList; + css::uno::Sequence> m_aDics; - std::unique_ptr pLinguData; + std::unique_ptr m_pLinguData; std::unique_ptr m_xLinguModulesFrame; std::unique_ptr m_xLinguModulesCLB; @@ -133,6 +138,8 @@ private: void UpdateModulesBox_Impl(); void UpdateDicBox_Impl(); + void SetConfiguredServices(const OUString& rServiceName, const LangImplNameTable& rTable); + public: SvxLinguTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet); static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); diff --git a/cui/source/inc/optpath.hxx b/cui/source/inc/optpath.hxx index 141b2de0cf2e..2ff48a42bb29 100644 --- a/cui/source/inc/optpath.hxx +++ b/cui/source/inc/optpath.hxx @@ -24,6 +24,7 @@ #include #include #include +#include #include // forward --------------------------------------------------------------- diff --git a/cui/source/inc/page.hxx b/cui/source/inc/page.hxx index 827625e3f54a..c17a58650235 100644 --- a/cui/source/inc/page.hxx +++ b/cui/source/inc/page.hxx @@ -26,7 +26,10 @@ #include #include #include +#include +#include #include +#include // class SvxPageDescPage ------------------------------------------------- /* @@ -124,9 +127,11 @@ private: std::unique_ptr m_xRegisterFT; std::unique_ptr m_xRegisterLB; std::unique_ptr m_xGutterPositionFT; - std::unique_ptr m_xGutterPositionLB; - std::unique_ptr m_xRtlGutterCB; + std::unique_ptr m_xGutterPositionLeftInner; + std::unique_ptr m_xGutterPositionRightOuter; + std::unique_ptr m_xGutterPositionTop; std::unique_ptr m_xBackgroundFullSizeCB; + std::unique_ptr m_xLabelOptions; std::unique_ptr m_xInsideLbl; std::unique_ptr m_xOutsideLbl; std::unique_ptr m_xPrintRangeQueryText; @@ -134,7 +139,7 @@ private: void Init_Impl(); DECL_LINK(LayoutHdl_Impl, weld::ComboBox&, void); - DECL_LINK(GutterPositionHdl_Impl, weld::ComboBox&, void); + DECL_LINK(GutterPositionHdl_Impl, weld::Toggleable&, void ); DECL_LINK(PaperBinHdl_Impl, weld::Widget&, void); DECL_LINK(SwapOrientation_Impl, weld::Toggleable&, void); void SwapFirstValues_Impl( bool bSet ); diff --git a/cui/source/inc/paragrph.hxx b/cui/source/inc/paragrph.hxx index fdfa4f4a18e8..af1369fd56dd 100644 --- a/cui/source/inc/paragrph.hxx +++ b/cui/source/inc/paragrph.hxx @@ -22,8 +22,13 @@ #include #include #include +#include +#include #include +#include +#include #include +#include class SvxLineSpacingItem; @@ -259,6 +264,7 @@ private: bool bPageBreak; bool bHtmlMode; sal_uInt16 nStdPos; + sal_Int16 nHyphenLevel; // hyphenation std::unique_ptr m_xHyphenBox; @@ -276,6 +282,9 @@ private: std::unique_ptr m_xMaxHyphenEdit; std::unique_ptr m_xMinWordLabel; std::unique_ptr m_xMinWordLength; + std::unique_ptr m_xBetterSpacingLabel; + std::unique_ptr m_xLessHyphenLabel; + std::unique_ptr m_xSliderHyphen; std::unique_ptr m_xHyphenZoneLabel; SvxRelativeField m_aHyphenZone; std::unique_ptr m_xParagraphEndZoneLabel; diff --git a/cui/source/inc/passwdomdlg.hxx b/cui/source/inc/passwdomdlg.hxx index aebe32895586..cfaa6357252c 100644 --- a/cui/source/inc/passwdomdlg.hxx +++ b/cui/source/inc/passwdomdlg.hxx @@ -19,8 +19,14 @@ #pragma once #include +#include +#include #include +#include +#include +#include #include +#include #include @@ -61,7 +67,7 @@ class PasswordToOpenModifyDialog : public SfxDialogController DECL_LINK(OkBtnClickHdl, weld::Button&, void); DECL_LINK(ReadonlyOnOffHdl, weld::Toggleable&, void); - DECL_LINK(ChangeHdl, weld::Entry&, void); + DECL_LINK(ChangeHdl, weld::TextWidget&, void); DECL_LINK(ShowHdl, weld::Toggleable&, void); PasswordToOpenModifyDialog( const PasswordToOpenModifyDialog & ) = delete; diff --git a/cui/source/inc/pastedlg.hxx b/cui/source/inc/pastedlg.hxx index 2f54497b626c..5ee3981c54dc 100644 --- a/cui/source/inc/pastedlg.hxx +++ b/cui/source/inc/pastedlg.hxx @@ -23,9 +23,11 @@ #include #include #include +#include #include +#include #include -#include +#include class TransferableDataHelper; diff --git a/cui/source/inc/postdlg.hxx b/cui/source/inc/postdlg.hxx index c69a9adb548b..bd69b8298d1d 100644 --- a/cui/source/inc/postdlg.hxx +++ b/cui/source/inc/postdlg.hxx @@ -23,7 +23,9 @@ #include #include +#include #include +#include #include // class SvxPostItDialog ------------------------------------------------- diff --git a/cui/source/inc/screenshotannotationdlg.hxx b/cui/source/inc/screenshotannotationdlg.hxx index c30b4bfd8fd4..9360640141f0 100644 --- a/cui/source/inc/screenshotannotationdlg.hxx +++ b/cui/source/inc/screenshotannotationdlg.hxx @@ -19,7 +19,7 @@ #pragma once #include -#include + #include class ScreenshotAnnotationDlg_Impl; diff --git a/cui/source/inc/scriptdlg.hxx b/cui/source/inc/scriptdlg.hxx index 8bfca54446ab..8bdc9ab3c084 100644 --- a/cui/source/inc/scriptdlg.hxx +++ b/cui/source/inc/scriptdlg.hxx @@ -21,10 +21,10 @@ #include #include +#include #include #include #include -#include #include #include @@ -100,7 +100,6 @@ class SvxScriptOrgDialog : public SfxDialogController DECL_LINK(ScriptSelectHdl, weld::ItemView&, void); DECL_LINK( ExpandingHdl, const weld::TreeIter&, bool ); DECL_LINK( ButtonHdl, weld::Button&, void ); - static bool getBoolProperty( css::uno::Reference< css::beans::XPropertySet > const & xProps, OUString const & propName ); void CheckButtons( css::uno::Reference< css::script::browse::XBrowseNode > const & node ); void createEntry(const weld::TreeIter& rEntry); @@ -134,8 +133,6 @@ class SvxScriptOrgDialog : public SfxDialogController static css::uno::Reference< css::script::browse::XBrowseNode > getLangNodeFromRootNode( css::uno::Reference< css::script::browse::XBrowseNode > const & root, std::u16string_view language ); - static css::uno::Reference< css::uno::XInterface > getDocumentModel( css::uno::Reference< css::uno::XComponentContext > const & xCtx, std::u16string_view docName ); - public: // prob need another arg in the ctor // to specify the language or provider diff --git a/cui/source/inc/sdrcelldlg.hxx b/cui/source/inc/sdrcelldlg.hxx index 46f34c0dae28..406f1c13bffc 100644 --- a/cui/source/inc/sdrcelldlg.hxx +++ b/cui/source/inc/sdrcelldlg.hxx @@ -23,6 +23,7 @@ #include #include #include +#include class SdrModel; class SvxFormatCellsDialog : public SfxTabDialogController diff --git a/cui/source/inc/securityoptions.hxx b/cui/source/inc/securityoptions.hxx index 6ce11d6117a1..6bf657a93d64 100644 --- a/cui/source/inc/securityoptions.hxx +++ b/cui/source/inc/securityoptions.hxx @@ -18,8 +18,9 @@ */ #pragma once +#include #include -#include +#include namespace svx { diff --git a/cui/source/inc/showcols.hxx b/cui/source/inc/showcols.hxx index 493a675d8af6..852c7e16678f 100644 --- a/cui/source/inc/showcols.hxx +++ b/cui/source/inc/showcols.hxx @@ -21,9 +21,11 @@ #include #include + +#include #include #include -#include +#include // FmShowColsDialog diff --git a/cui/source/inc/splitcelldlg.hxx b/cui/source/inc/splitcelldlg.hxx index fff6be718f46..87f92411cabc 100644 --- a/cui/source/inc/splitcelldlg.hxx +++ b/cui/source/inc/splitcelldlg.hxx @@ -20,9 +20,12 @@ #include +#include #include +#include +#include #include -#include +#include class SvxSplitTableDlg : public weld::GenericDialogController { diff --git a/cui/source/inc/srchxtra.hxx b/cui/source/inc/srchxtra.hxx index 7dd82743de44..e36bae782b87 100644 --- a/cui/source/inc/srchxtra.hxx +++ b/cui/source/inc/srchxtra.hxx @@ -21,10 +21,11 @@ #include #include #include +#include +#include #include #include #include -#include class SvxSearchFormatDialog : public SfxTabDialogController { diff --git a/cui/source/inc/swpossizetabpage.hxx b/cui/source/inc/swpossizetabpage.hxx index f7386b8dab3a..60ca576c649f 100644 --- a/cui/source/inc/swpossizetabpage.hxx +++ b/cui/source/inc/swpossizetabpage.hxx @@ -20,9 +20,12 @@ #include #include +#include #include +#include +#include #include -#include +#include #include // SvxSwPosSizeTabPage - position and size page for Writer drawing objects diff --git a/cui/source/inc/tabstpge.hxx b/cui/source/inc/tabstpge.hxx index 03ba25d47749..8c93e9ee5d8d 100644 --- a/cui/source/inc/tabstpge.hxx +++ b/cui/source/inc/tabstpge.hxx @@ -18,12 +18,15 @@ */ #pragma once +#include +#include #include #include +#include #include +#include #include #include -#include #include #include @@ -124,6 +127,9 @@ private: void SetFillAndTabType_Impl(); void NewHdl_Impl(const weld::Button*); + OUString FormatValue(sal_Int64 nValue); + sal_Int64 GetCurrentValue(); + OUString FormatTab(); // Handler diff --git a/cui/source/inc/textanim.hxx b/cui/source/inc/textanim.hxx index 5deac4bf3455..81be4ab561f7 100644 --- a/cui/source/inc/textanim.hxx +++ b/cui/source/inc/textanim.hxx @@ -21,9 +21,12 @@ #include #include #include +#include #include +#include #include -#include +#include +#include class SdrView; diff --git a/cui/source/inc/textattr.hxx b/cui/source/inc/textattr.hxx index d1986a550c52..5ba9b86079b7 100644 --- a/cui/source/inc/textattr.hxx +++ b/cui/source/inc/textattr.hxx @@ -20,7 +20,9 @@ #include #include +#include #include +#include #include /************************************************************************* diff --git a/cui/source/inc/thesdlg.hxx b/cui/source/inc/thesdlg.hxx index a815f4f27b8c..a11644619f97 100644 --- a/cui/source/inc/thesdlg.hxx +++ b/cui/source/inc/thesdlg.hxx @@ -22,8 +22,10 @@ #include #include +#include #include #include +#include #include #include @@ -62,7 +64,7 @@ public: DECL_LINK(AlternativesSelectHdl_Impl, weld::ItemView&, void); DECL_LINK(AlternativesDoubleClickHdl_Impl, const weld::TreeIter&, bool); DECL_LINK( SelectFirstHdl_Impl, void*, void ); - DECL_LINK( ReplaceEditHdl_Impl, weld::Entry&, void ); + DECL_LINK(ReplaceEditHdl_Impl, weld::TextWidget&, void); DECL_LINK( ModifyTimer_Hdl, Timer *, void ); DECL_LINK( KeyInputHdl, const KeyEvent&, bool ); diff --git a/cui/source/inc/tipofthedaydlg.hxx b/cui/source/inc/tipofthedaydlg.hxx index 20d6c1364de3..f3733ea84dfc 100644 --- a/cui/source/inc/tipofthedaydlg.hxx +++ b/cui/source/inc/tipofthedaydlg.hxx @@ -18,8 +18,12 @@ */ #pragma once +#include +#include #include -#include +#include +#include + #include "cuigrfflt.hxx" class VclWindowEvent; diff --git a/cui/source/inc/toolbartabpage.hxx b/cui/source/inc/toolbartabpage.hxx index 29d4f5683975..319393992f54 100644 --- a/cui/source/inc/toolbartabpage.hxx +++ b/cui/source/inc/toolbartabpage.hxx @@ -13,7 +13,8 @@ #include #include -#include +#include +#include #include class ToolbarTabPage : public SfxTabPage diff --git a/cui/source/inc/transfrm.hxx b/cui/source/inc/transfrm.hxx index 0edd62deaf18..bd9f9cde1b9b 100644 --- a/cui/source/inc/transfrm.hxx +++ b/cui/source/inc/transfrm.hxx @@ -22,7 +22,12 @@ #include #include #include +#include +#include +#include +#include #include +#include #include // predefines diff --git a/cui/source/inc/treeopt.hxx b/cui/source/inc/treeopt.hxx index 488cbcc0594a..a32c84de7b55 100644 --- a/cui/source/inc/treeopt.hxx +++ b/cui/source/inc/treeopt.hxx @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -157,7 +159,7 @@ private: void clearOptionsDialog(); void selectFirstEntry(); void storeOptionsTree(); - void showDialog(VectorOfMatchedIds& pSearchIds); + void showDialog(const VectorOfMatchedIds& rPageIds); OUString sTitle; @@ -193,7 +195,7 @@ private: DECL_LINK(BackHdl_Impl, weld::Button&, void); DECL_LINK(ApplyHdl_Impl, weld::Button&, void); DECL_LINK(HelpHdl_Impl, weld::Widget&, bool); - DECL_LINK(SearchUpdateHdl, weld::Entry&, void); + DECL_LINK(SearchUpdateHdl, weld::TextWidget&, void); DECL_LINK(ImplUpdateDataHdl, Timer*, void); DECL_LINK(FocusOut_Impl, weld::Widget&, void); void ResetCurrentPageFromConfig(); diff --git a/cui/source/inc/uipickerdlg.hxx b/cui/source/inc/uipickerdlg.hxx index 3b60e3de63f8..5a3e25446874 100644 --- a/cui/source/inc/uipickerdlg.hxx +++ b/cui/source/inc/uipickerdlg.hxx @@ -10,6 +10,8 @@ #pragma once #include +#include +#include class UIPickerDialog : public SfxTabDialogController { diff --git a/cui/source/inc/uitabpage.hxx b/cui/source/inc/uitabpage.hxx index 5f4b7d2969d0..99cd39847605 100644 --- a/cui/source/inc/uitabpage.hxx +++ b/cui/source/inc/uitabpage.hxx @@ -10,9 +10,15 @@ #pragma once #include +#include +#include +#include +#include #include +#include + class UITabPage : public SfxTabPage { private: @@ -31,6 +37,7 @@ public: Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet); OUString GetSelectedMode(); + static std::optional GetCurrentAppEnum(); static OUString GetCurrentApp(); }; diff --git a/cui/source/inc/welcomedlg.hxx b/cui/source/inc/welcomedlg.hxx index 20e678c9d94a..b0d78cb0bbcb 100644 --- a/cui/source/inc/welcomedlg.hxx +++ b/cui/source/inc/welcomedlg.hxx @@ -10,6 +10,8 @@ #pragma once #include +#include +#include class WelcomeDialog : public SfxTabDialogController { diff --git a/cui/source/inc/zoom.hxx b/cui/source/inc/zoom.hxx index 89f38eebbae7..aa42eaf35a52 100644 --- a/cui/source/inc/zoom.hxx +++ b/cui/source/inc/zoom.hxx @@ -22,9 +22,11 @@ #include #include #include +#include +#include #include +#include #include -#include class SvxZoomDialog : public SfxDialogController { diff --git a/cui/source/options/appearance.cxx b/cui/source/options/appearance.cxx index 969f84019610..fda8694bea13 100644 --- a/cui/source/options/appearance.cxx +++ b/cui/source/options/appearance.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,7 @@ SvxAppearanceTabPage::SvxAppearanceTabPage(weld::Container* pPage, , m_xNotebookbarIconSize(m_xBuilder->weld_combo_box(u"notebookbariconsdropdown"_ustr)) , m_xSizeGrid(m_xBuilder->weld_widget(u"grdIconSize"_ustr)) , m_xCustomizationFrame(m_xBuilder->weld_widget(u"items"_ustr)) + , m_xDialogFrame(m_xBuilder->weld_widget(u"dialogs"_ustr)) , m_xVerticalToolbars(m_xBuilder->weld_radio_button(u"rbVertical"_ustr)) , m_xHorizontalToolbars(m_xBuilder->weld_radio_button(u"rbHorizontal"_ustr)) { @@ -213,6 +215,7 @@ void SvxAppearanceTabPage::Reset(const SfxItemSet* /* rSet */) { m_xSizeGrid->set_visible(false); m_xCustomizationFrame->set_visible(false); + m_xDialogFrame->set_visible(false); } // reset scheme list diff --git a/cui/source/options/appearance.hxx b/cui/source/options/appearance.hxx index 7cbcd7f93ccf..0474244f7ea0 100644 --- a/cui/source/options/appearance.hxx +++ b/cui/source/options/appearance.hxx @@ -9,8 +9,10 @@ #pragma once +#include +#include #include -#include +#include #include #include #include @@ -45,6 +47,7 @@ private: std::unique_ptr m_xNotebookbarIconSize; std::unique_ptr m_xSizeGrid; std::unique_ptr m_xCustomizationFrame; + std::unique_ptr m_xDialogFrame; std::unique_ptr m_xVerticalToolbars; std::unique_ptr m_xHorizontalToolbars; diff --git a/cui/source/options/certpath.cxx b/cui/source/options/certpath.cxx index 82b3184cc76c..b68934f5d37c 100644 --- a/cui/source/options/certpath.cxx +++ b/cui/source/options/certpath.cxx @@ -39,7 +39,8 @@ CertPathDialog::CertPathDialog(weld::Window* pParent) int nControlWidth = m_xCertPathList->get_approximate_digit_width() * 40; m_xCertPathList->set_column_fixed_widths({nControlWidth}); - m_xCertPathList->enable_toggle_buttons(weld::ColumnToggleType::Radio); + m_xCertPathList->enable_toggle_buttons(); + m_xCertPathList->set_toggle_button_type(weld::ColumnToggleType::Radio); m_xCertPathList->connect_toggled(LINK(this, CertPathDialog, CheckHdl_Impl)); m_xManualButton->connect_clicked( LINK( this, CertPathDialog, ManualHdl_Impl ) ); diff --git a/cui/source/options/certpath.hxx b/cui/source/options/certpath.hxx index ebdbe920dbca..cc39d565fef0 100644 --- a/cui/source/options/certpath.hxx +++ b/cui/source/options/certpath.hxx @@ -9,9 +9,11 @@ #pragma once +#include #include +#include #include -#include +#include class CertPathDialog : public weld::GenericDialogController { diff --git a/cui/source/options/connpoolconfig.cxx b/cui/source/options/connpoolconfig.cxx index c637e7d35367..ce163f7dbee3 100644 --- a/cui/source/options/connpoolconfig.cxx +++ b/cui/source/options/connpoolconfig.cxx @@ -47,7 +47,7 @@ namespace offapp { // the config node where all pooling relevant info are stored under OConfigurationTreeRoot aConnectionPoolRoot = OConfigurationTreeRoot::createWithComponentContext( - ::comphelper::getProcessComponentContext(), CONNECTIONPOOL_NODENAME, -1, OConfigurationTreeRoot::CM_READONLY); + ::comphelper::getProcessComponentContext(), CONNECTIONPOOL_NODENAME, OConfigurationTreeRoot::CM_READONLY); // the global "enabled" flag Any aEnabled = aConnectionPoolRoot.getNodeValue(ENABLE_POOLING); diff --git a/cui/source/options/connpooloptions.hxx b/cui/source/options/connpooloptions.hxx index 27e21a26aaca..6a1372ad305b 100644 --- a/cui/source/options/connpooloptions.hxx +++ b/cui/source/options/connpooloptions.hxx @@ -20,6 +20,8 @@ #pragma once #include +#include +#include #include #include #include diff --git a/cui/source/options/dbregister.cxx b/cui/source/options/dbregister.cxx index 8a48dd341fe4..2bde2d143d00 100644 --- a/cui/source/options/dbregister.cxx +++ b/cui/source/options/dbregister.cxx @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include "doclinkdialog.hxx" #include @@ -113,7 +113,8 @@ DbRegistrationOptionsPage::DbRegistrationOptionsPage(weld::Container* pPage, wel m_xEdit->connect_clicked( LINK( this, DbRegistrationOptionsPage, EditHdl ) ); m_xDelete->connect_clicked( LINK( this, DbRegistrationOptionsPage, DeleteHdl ) ); - m_xPathBox->connect_column_clicked(LINK(this, DbRegistrationOptionsPage, HeaderSelect_Impl)); + m_xPathBox->connect_column_header_clicked( + LINK(this, DbRegistrationOptionsPage, HeaderSelect_Impl)); m_xPathBox->make_sorted(); m_xPathBox->connect_item_activated( diff --git a/cui/source/options/doclinkdialog.cxx b/cui/source/options/doclinkdialog.cxx index 477d4fd61558..b76a0e41f4fe 100644 --- a/cui/source/options/doclinkdialog.cxx +++ b/cui/source/options/doclinkdialog.cxx @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -235,7 +234,7 @@ namespace svx validate(); } - IMPL_LINK_NOARG(ODocumentLinkDialog, OnEntryModified, weld::Entry&, void) + IMPL_LINK_NOARG(ODocumentLinkDialog, OnEntryModified, weld::TextWidget&, void) { validate(); } diff --git a/cui/source/options/doclinkdialog.hxx b/cui/source/options/doclinkdialog.hxx index 80add3dfdba1..2f952253c990 100644 --- a/cui/source/options/doclinkdialog.hxx +++ b/cui/source/options/doclinkdialog.hxx @@ -19,10 +19,12 @@ #pragma once +#include #include #include #include -#include +#include +#include #include #include @@ -55,7 +57,7 @@ namespace svx void getLink( OUString& _rName, OUString& _rURL ) const; private: - DECL_LINK( OnEntryModified, weld::Entry&, void ); + DECL_LINK(OnEntryModified, weld::TextWidget&, void); DECL_LINK( OnComboBoxModified, weld::ComboBox&, void ); DECL_LINK( OnBrowseFile, weld::Button&, void ); DECL_LINK( OnOk, weld::Button&, void ); diff --git a/cui/source/options/fontsubs.cxx b/cui/source/options/fontsubs.cxx index 2888dfce5265..96dbd1df8696 100644 --- a/cui/source/options/fontsubs.cxx +++ b/cui/source/options/fontsubs.cxx @@ -63,7 +63,6 @@ SvxFontSubstTabPage::SvxFontSubstTabPage(weld::Container* pPage, weld::DialogCon m_xCheckLB->set_size_request(m_xCheckLB->get_approximate_digit_width() * 60, m_xCheckLB->get_height_rows(8)); - m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check); m_xCheckLB->set_help_id(HID_OFA_FONT_SUBST_CLB); m_xCheckLB->set_selection_mode(SelectionMode::Multiple); @@ -77,7 +76,7 @@ SvxFontSubstTabPage::SvxFontSubstTabPage(weld::Container* pPage, weld::DialogCon Link aClickLink(LINK(this, SvxFontSubstTabPage, ClickHdl)); m_xCheckLB->connect_selection_changed(LINK(this, SvxFontSubstTabPage, TreeListBoxSelectHdl)); - m_xCheckLB->connect_column_clicked(LINK(this, SvxFontSubstTabPage, HeaderBarClick)); + m_xCheckLB->connect_column_header_clicked(LINK(this, SvxFontSubstTabPage, HeaderBarClick)); m_xUseTableCB->connect_toggled(LINK(this, SvxFontSubstTabPage, ToggleHdl)); m_xFont1CB->connect_changed(aLink2); m_xFont2CB->connect_changed(aLink2); diff --git a/cui/source/options/fontsubs.hxx b/cui/source/options/fontsubs.hxx index aa4c3aba7014..0302db6f8178 100644 --- a/cui/source/options/fontsubs.hxx +++ b/cui/source/options/fontsubs.hxx @@ -20,7 +20,10 @@ #pragma once #include +#include +#include #include +#include #include // class SvxFontSubstTabPage ---------------------------------------------------- diff --git a/cui/source/options/optaboutconfig.cxx b/cui/source/options/optaboutconfig.cxx index cf8e8cc8e831..7a6a20062964 100644 --- a/cui/source/options/optaboutconfig.cxx +++ b/cui/source/options/optaboutconfig.cxx @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -110,7 +112,7 @@ CuiAboutConfigTabPage::CuiAboutConfigTabPage(weld::Window* pParent) { m_xPrefBox->set_size_request(m_xPrefBox->get_approximate_digit_width() * 100, m_xPrefBox->get_height_rows(23)); - m_xPrefBox->connect_column_clicked(LINK(this, CuiAboutConfigTabPage, HeaderBarClick)); + m_xPrefBox->connect_column_header_clicked(LINK(this, CuiAboutConfigTabPage, HeaderBarClick)); m_xEditBtn->connect_clicked(LINK(this, CuiAboutConfigTabPage, StandardHdl_Impl)); m_xResetBtn->connect_clicked(LINK(this, CuiAboutConfigTabPage, ResetBtnHdl_Impl)); diff --git a/cui/source/options/optaboutconfig.hxx b/cui/source/options/optaboutconfig.hxx index 0311856983d7..861752fc33de 100644 --- a/cui/source/options/optaboutconfig.hxx +++ b/cui/source/options/optaboutconfig.hxx @@ -13,10 +13,11 @@ #include #include +#include +#include #include #include #include -#include #include diff --git a/cui/source/options/optaccessibility.cxx b/cui/source/options/optaccessibility.cxx index 185a4a09d225..6e2b14e04ad8 100644 --- a/cui/source/options/optaccessibility.cxx +++ b/cui/source/options/optaccessibility.cxx @@ -23,7 +23,11 @@ #include #include #include +#include +#include #include +#include +#include namespace { @@ -90,8 +94,7 @@ SvxAccessibilityOptionsTabPage::SvxAccessibilityOptionsTabPage(weld::Container* , m_xOptionsLB(m_xBuilder->weld_tree_view(u"options"_ustr)) , m_xDefaultPB(m_xBuilder->weld_button(u"default"_ustr)) { - - m_xOptionsLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xOptionsLB->enable_toggle_buttons(); auto pos = m_xOptionsLB->make_iterator(); for (const auto& [compatId, a11yId] : options_list) @@ -313,6 +316,15 @@ bool SvxAccessibilityOptionsTabPage::FillItemSet( SfxItemSet* ) } batch->commit(); + if (m_xHighContrast->get_value_changed_from_saved()) + { + SolarMutexGuard aGuard; + if (svtools::executeRestartDialog( + comphelper::getProcessComponentContext(), nullptr, + svtools::RESTART_REASON_HIGH_CONTRAST)) + GetDialogController()->response(RET_OK); + } + return false; } @@ -364,6 +376,7 @@ void SvxAccessibilityOptionsTabPage::Reset( const SfxItemSet* ) } m_xHighContrast->set_active( officecfg::Office::Common::Accessibility::HighContrast::get() ); + m_xHighContrast->save_value(); if (officecfg::Office::Common::Accessibility::HighContrast::isReadOnly()) { m_xHighContrast->set_sensitive(false); diff --git a/cui/source/options/optaccessibility.hxx b/cui/source/options/optaccessibility.hxx index 679543b2979f..fc34476d71e6 100644 --- a/cui/source/options/optaccessibility.hxx +++ b/cui/source/options/optaccessibility.hxx @@ -20,7 +20,10 @@ #include #include +#include +#include #include +#include #include #include diff --git a/cui/source/options/optasian.cxx b/cui/source/options/optasian.cxx index b8d8de5356d3..f014fcbb38f8 100644 --- a/cui/source/options/optasian.cxx +++ b/cui/source/options/optasian.cxx @@ -128,7 +128,7 @@ SvxAsianLayoutPage::SvxAsianLayoutPage(weld::Container* pPage, weld::DialogContr LanguageHdl(*m_xLanguageLB->get_widget()); m_xLanguageLB->connect_changed(LINK(this, SvxAsianLayoutPage, LanguageHdl)); m_xStandardCB->connect_toggled(LINK(this, SvxAsianLayoutPage, ChangeStandardHdl)); - Link aLk(LINK(this, SvxAsianLayoutPage, ModifyHdl)); + Link aLk(LINK(this, SvxAsianLayoutPage, ModifyHdl)); m_xStartED->connect_changed(aLk); m_xEndED->connect_changed(aLk); @@ -374,7 +374,7 @@ IMPL_LINK(SvxAsianLayoutPage, ChangeStandardHdl, weld::Toggleable&, rBox, void) ModifyHdl(*m_xStartED); } -IMPL_LINK(SvxAsianLayoutPage, ModifyHdl, weld::Entry&, rEdit, void) +IMPL_LINK(SvxAsianLayoutPage, ModifyHdl, weld::TextWidget&, rEdit, void) { LanguageType eSelectLanguage = m_xLanguageLB->get_active_id(); Locale aLocale( LanguageTag::convertToLocale( eSelectLanguage )); diff --git a/cui/source/options/optbasic.cxx b/cui/source/options/optbasic.cxx index aed5b6e85ae0..f7e799e6ca0b 100644 --- a/cui/source/options/optbasic.cxx +++ b/cui/source/options/optbasic.cxx @@ -21,6 +21,7 @@ #include #include #include +#include #include SvxBasicIDEOptionsPage::SvxBasicIDEOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) diff --git a/cui/source/options/optbasic.hxx b/cui/source/options/optbasic.hxx index bc4274eaca1e..70fc4c3d64b2 100644 --- a/cui/source/options/optbasic.hxx +++ b/cui/source/options/optbasic.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include class SvxBasicIDEOptionsPage: public SfxTabPage { diff --git a/cui/source/options/optchart.cxx b/cui/source/options/optchart.cxx index dc0efb062bd9..d2065f94efc0 100644 --- a/cui/source/options/optchart.cxx +++ b/cui/source/options/optchart.cxx @@ -18,13 +18,13 @@ */ #include "optchart.hxx" -#include #include #include #include +#include +#include #include #include -#include #include #include #include @@ -112,18 +112,17 @@ IMPL_LINK_NOARG(SvxDefaultColorOptPage, LbChartColorsSelectionChangedHdl, weld:: /*theme colors palette*/ aPaletteManager.IsThemePaletteSelected() || /*document colors palette*/ nPalettePos == aPaletteManager.GetPaletteCount() - 1) { - aPaletteManager.ReloadColorSet(*m_xValSetColorBox); + aPaletteManager.ReloadColorSet(m_aColorIconView); - for (size_t nItemPos = 0, nItemCount = m_xValSetColorBox->GetItemCount(); + for (size_t nItemPos = 0, nItemCount = m_aColorIconView.getItemCount(); nItemPos < nItemCount; nItemPos++) { - auto nItemId = m_xValSetColorBox->GetItemId(nItemPos); - if (m_xValSetColorBox->GetItemColor(nItemId) == rColor) + if (m_aColorIconView.getColor(nItemPos) == rColor) { m_xLbPaletteSelector->set_active_text(aPaletteManager.GetPaletteName()); SelectPaletteLbHdl(*m_xLbPaletteSelector); - m_xValSetColorBox->SelectItem(nItemId); + m_aColorIconView.select(nItemPos); return; } @@ -143,7 +142,7 @@ IMPL_LINK_NOARG(SvxDefaultColorOptPage, LbChartColorsSelectionChangedHdl, weld:: m_xLbPaletteSelector->set_active_text(aPaletteManager.GetPaletteName()); SelectPaletteLbHdl(*m_xLbPaletteSelector); - m_xValSetColorBox->SelectItem(m_xValSetColorBox->GetItemId(nPos)); + m_aColorIconView.select(nPos); return; } @@ -151,7 +150,7 @@ IMPL_LINK_NOARG(SvxDefaultColorOptPage, LbChartColorsSelectionChangedHdl, weld:: // color not found in any palette m_xLbPaletteSelector->set_active_text(OUString()); - m_xValSetColorBox->Clear(); + m_aColorIconView.clear(); } SvxDefaultColorOptPage::SvxDefaultColorOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) @@ -161,8 +160,7 @@ SvxDefaultColorOptPage::SvxDefaultColorOptPage(weld::Container* pPage, weld::Dia , m_xPBDefault(m_xBuilder->weld_button(u"default"_ustr)) , m_xPBAdd(m_xBuilder->weld_button(u"add"_ustr)) , m_xPBRemove(m_xBuilder->weld_button(u"delete"_ustr)) - , m_xValSetColorBox(new SvxColorValueSet(m_xBuilder->weld_scrolled_window(u"tablewin"_ustr, true))) - , m_xValSetColorBoxWin(new weld::CustomWeld(*m_xBuilder, u"table"_ustr, *m_xValSetColorBox)) + , m_aColorIconView(m_xBuilder->weld_icon_view(u"tableiconview"_ustr)) { m_xLbChartColors->set_size_request(-1, m_xLbChartColors->get_height_rows(16)); @@ -174,18 +172,15 @@ SvxDefaultColorOptPage::SvxDefaultColorOptPage(weld::Container* pPage, weld::Dia m_xPBDefault->set_sensitive(false); m_xPBAdd->set_sensitive(false); m_xPBRemove->set_sensitive(false); - m_xValSetColorBoxWin->set_sensitive(false); + m_aColorIconView.set_sensitive(false); } m_xPBDefault->connect_clicked( LINK( this, SvxDefaultColorOptPage, ResetToDefaults ) ); m_xPBAdd->connect_clicked( LINK( this, SvxDefaultColorOptPage, AddChartColor ) ); m_xPBRemove->connect_clicked( LINK( this, SvxDefaultColorOptPage, RemoveChartColor ) ); - m_xValSetColorBox->SetSelectHdl( LINK( this, SvxDefaultColorOptPage, BoxClickedHdl ) ); + m_aColorIconView.setColorActivatedHdl(LINK(this, SvxDefaultColorOptPage, ColorActivatedHdl)); m_xLbPaletteSelector->connect_changed( LINK( this, SvxDefaultColorOptPage, SelectPaletteLbHdl ) ); - m_xValSetColorBox->SetStyle( m_xValSetColorBox->GetStyle() - | WB_ITEMBORDER | WB_NAMEFIELD | WB_VSCROLL ); - if ( const SvxChartColorTableItem* pEditOptionsItem = rInAttrs.GetItemIfSet( SID_SCH_EDITOPTIONS, false ) ) { m_SvxChartColorTableUniquePtr = std::make_unique( @@ -203,8 +198,6 @@ SvxDefaultColorOptPage::SvxDefaultColorOptPage(weld::Container* pPage, weld::Dia SvxDefaultColorOptPage::~SvxDefaultColorOptPage() { - m_xValSetColorBoxWin.reset(); - m_xValSetColorBox.reset(); } void SvxDefaultColorOptPage::Construct() @@ -348,16 +341,15 @@ IMPL_LINK_NOARG( SvxDefaultColorOptPage, SelectPaletteLbHdl, weld::ComboBox&, vo { sal_Int32 nPos = m_xLbPaletteSelector->get_active(); aPaletteManager.SetPalette( nPos ); - aPaletteManager.ReloadColorSet( *m_xValSetColorBox ); - m_xValSetColorBox->Resize(); + aPaletteManager.ReloadColorSet(m_aColorIconView); } -IMPL_LINK_NOARG(SvxDefaultColorOptPage, BoxClickedHdl, ValueSet*, void) +IMPL_LINK(SvxDefaultColorOptPage, ColorActivatedHdl, const Color&, rColor, void) { sal_Int32 nIdx = m_xLbChartColors->get_selected_index(); if (nIdx != -1) { - const XColorEntry aEntry(m_xValSetColorBox->GetItemColor(m_xValSetColorBox->GetSelectedItemId()), m_xLbChartColors->get_selected_text()); + const XColorEntry aEntry(rColor, m_xLbChartColors->get_selected_text()); ModifyColorEntry(aEntry, nIdx); m_SvxChartColorTableUniquePtr->replace(nIdx, aEntry); diff --git a/cui/source/options/optchart.hxx b/cui/source/options/optchart.hxx index 04adef516574..d38ea4c161fb 100644 --- a/cui/source/options/optchart.hxx +++ b/cui/source/options/optchart.hxx @@ -21,8 +21,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -46,13 +48,12 @@ private: std::unique_ptr m_xPBDefault; std::unique_ptr m_xPBAdd; std::unique_ptr m_xPBRemove; - std::unique_ptr m_xValSetColorBox; - std::unique_ptr m_xValSetColorBoxWin; + ColorIconView m_aColorIconView; DECL_LINK(ResetToDefaults, weld::Button&, void); DECL_LINK(AddChartColor, weld::Button&, void); DECL_LINK(RemoveChartColor, weld::Button&, void); - DECL_LINK(BoxClickedHdl, ValueSet*, void); + DECL_LINK(ColorActivatedHdl, const Color&, void); DECL_LINK(SelectPaletteLbHdl, weld::ComboBox&, void); DECL_LINK(LbChartColorsSelectionChangedHdl, weld::ItemView&, void); diff --git a/cui/source/options/optctl.cxx b/cui/source/options/optctl.cxx index 4e9aeba9adbb..6d4201be71c5 100644 --- a/cui/source/options/optctl.cxx +++ b/cui/source/options/optctl.cxx @@ -23,6 +23,7 @@ #include #include #include +#include // class SvxCTLOptionsPage ----------------------------------------------------- diff --git a/cui/source/options/optctl.hxx b/cui/source/options/optctl.hxx index 3933ad99877a..24dd1ad0fce8 100644 --- a/cui/source/options/optctl.hxx +++ b/cui/source/options/optctl.hxx @@ -19,7 +19,9 @@ #pragma once #include +#include #include +#include // class SvxCTLOptionsPage ----------------------------------------------------- diff --git a/cui/source/options/optdeepl.cxx b/cui/source/options/optdeepl.cxx deleted file mode 100644 index 274a7e51ce87..000000000000 --- a/cui/source/options/optdeepl.cxx +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- 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 "optdeepl.hxx" -#include -#include -#include - -OptDeeplTabPage::OptDeeplTabPage(weld::Container* pPage, weld::DialogController* pController, - const SfxItemSet& rSet) - : SfxTabPage(pPage, pController, u"cui/ui/optdeeplpage.ui"_ustr, u"OptDeeplPage"_ustr, &rSet) - , m_xAPIUrl(m_xBuilder->weld_entry(u"apiurl"_ustr)) - , m_xAuthKey(m_xBuilder->weld_entry(u"authkey"_ustr)) -{ -} - -OptDeeplTabPage::~OptDeeplTabPage() {} - -void OptDeeplTabPage::Reset(const SfxItemSet*) -{ - std::optional oDeeplAPIUrl - = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get(); - if (oDeeplAPIUrl && !oDeeplAPIUrl->isEmpty()) - m_xAPIUrl->set_text(*officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get()); - - std::optional oDeeplAuthKey - = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get(); - if (oDeeplAuthKey && !oDeeplAuthKey->isEmpty()) - m_xAuthKey->set_text(*officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get()); -} - -OUString OptDeeplTabPage::GetAllStrings() -{ - OUStringBuffer sAllStrings; - OUString labels[] = { u"label1"_ustr, u"label2"_ustr, u"label3"_ustr }; - - for (const auto& label : labels) - { - if (const auto pString = m_xBuilder->weld_label(label)) - sAllStrings.append(pString->get_label() + " "); - } - - if (const auto pString = m_xBuilder->weld_link_button(u"privacy"_ustr)) - sAllStrings.append(pString->get_label() + " "); - - return sAllStrings.toString().replaceAll("_", ""); -} - -bool OptDeeplTabPage::FillItemSet(SfxItemSet*) -{ - std::shared_ptr batch( - comphelper::ConfigurationChanges::create()); - officecfg::Office::Linguistic::Translation::Deepl::ApiURL::set(m_xAPIUrl->get_text(), batch); - officecfg::Office::Linguistic::Translation::Deepl::AuthKey::set(m_xAuthKey->get_text(), batch); - batch->commit(); - return false; -} - -std::unique_ptr OptDeeplTabPage::Create(weld::Container* pPage, - weld::DialogController* pController, - const SfxItemSet* rAttrSet) -{ - return std::make_unique(pPage, pController, *rAttrSet); -} diff --git a/cui/source/options/optdeepl.hxx b/cui/source/options/optdeepl.hxx deleted file mode 100644 index 00f570e1dcd7..000000000000 --- a/cui/source/options/optdeepl.hxx +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- 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 . - */ -#pragma once - -#include -#include - -class OptDeeplTabPage : public SfxTabPage -{ -public: - OptDeeplTabPage(weld::Container* pPage, weld::DialogController* pController, - const SfxItemSet& rSet); - virtual ~OptDeeplTabPage() override; - static std::unique_ptr - Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); - - virtual OUString GetAllStrings() override; - - virtual bool FillItemSet(SfxItemSet* rSet) override; - virtual void Reset(const SfxItemSet* rSet) override; - -private: - std::unique_ptr m_xAPIUrl; - std::unique_ptr m_xAuthKey; -}; diff --git a/cui/source/options/optdict.cxx b/cui/source/options/optdict.cxx index a7e00a00c9f7..1094267582c0 100644 --- a/cui/source/options/optdict.cxx +++ b/cui/source/options/optdict.cxx @@ -33,8 +33,7 @@ #include #include #include -#include - +#include #include #include #include @@ -205,7 +204,7 @@ IMPL_LINK_NOARG(SvxNewDictionaryDialog, OKHdl_Impl, weld::Button&, void) m_xDialog->response(RET_OK); } -IMPL_LINK_NOARG(SvxNewDictionaryDialog, ModifyHdl_Impl, weld::Entry&, void) +IMPL_LINK_NOARG(SvxNewDictionaryDialog, ModifyHdl_Impl, weld::TextWidget&, void) { m_xOKBtn->set_sensitive(!m_xNameEdit->get_text().isEmpty()); } @@ -270,6 +269,7 @@ SvxEditDictionaryDialog::SvxEditDictionaryDialog(weld::Window* pParent, std::u16 m_xReplaceED->connect_changed(LINK(this, SvxEditDictionaryDialog, ModifyHdl)); m_xWordED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl)); m_xReplaceED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl)); + m_xWordED->set_placeholder_text(CuiResId(RID_CUISTR_OPT_DICT_SEARCH_PLACEHOLDER)); // fill listbox with all available WB's OUString aLookUpEntry; @@ -452,6 +452,38 @@ IMPL_LINK_NOARG(SvxEditDictionaryDialog, SelectLangHdl_Impl, weld::ComboBox&, vo SetLanguage_Impl( nOldLang ); } +void SvxEditDictionaryDialog::RebuildSortedDicEntries() +{ + int nPos = m_xAllDictsLB->get_active(); + if (nPos == -1) + return; + + Reference xDic = aDics[nPos]; + Sequence< Reference< XDictionaryEntry > > aEntries( xDic->getEntries() ); + + m_aSortedDicEntries.clear(); + m_aSortedDicEntries.reserve(aEntries.getLength()); + for (auto& xDictionaryEntry : aEntries) + { + OUString aStr = xDictionaryEntry->getDictionaryWord(); + if (!xDictionaryEntry->getReplacementText().isEmpty()) + { + aStr += "\t" + xDictionaryEntry->getReplacementText(); + } + m_aSortedDicEntries.push_back(aStr); + } + + IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag()); + const CollatorWrapper* pCollator = aIntlWrapper.getCollator(); + std::sort(m_aSortedDicEntries.begin(), m_aSortedDicEntries.end(), + [&] (OUString const & lhs, OUString const & rhs) + { + sal_Int32 nCmpRes = pCollator-> + compareString( getNormDicEntry_Impl(lhs), getNormDicEntry_Impl( rhs ) ); + return nCmpRes < 0; + }); +} + void SvxEditDictionaryDialog::ShowWords_Impl( sal_uInt16 nId ) { Reference xDic = aDics[nId]; @@ -503,31 +535,10 @@ void SvxEditDictionaryDialog::ShowWords_Impl( sal_uInt16 nId ) m_pWordsLB->clear(); - Sequence< Reference< XDictionaryEntry > > aEntries( xDic->getEntries() ); - std::vector aSortedDicEntries; - aSortedDicEntries.reserve(aEntries.getLength()); - for (auto& xDictionaryEntry : aEntries) - { - OUString aStr = xDictionaryEntry->getDictionaryWord(); - if (!xDictionaryEntry->getReplacementText().isEmpty()) - { - aStr += "\t" + xDictionaryEntry->getReplacementText(); - } - aSortedDicEntries.push_back(aStr); - } - - IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag()); - const CollatorWrapper* pCollator = aIntlWrapper.getCollator(); - std::sort(aSortedDicEntries.begin(), aSortedDicEntries.end(), - [&] (OUString const & lhs, OUString const & rhs) - { - sal_Int32 nCmpRes = pCollator-> - compareString( getNormDicEntry_Impl(lhs), getNormDicEntry_Impl( rhs ) ); - return nCmpRes < 0; - }); + RebuildSortedDicEntries(); m_pWordsLB->freeze(); // speed up insert - for (OUString const & rStr : aSortedDicEntries) + for (OUString const & rStr : m_aSortedDicEntries) { sal_Int32 index = 0; m_pWordsLB->append_text(rStr.getToken(0, '\t', index)); @@ -597,6 +608,7 @@ bool SvxEditDictionaryDialog::NewDelHdl(const weld::Widget* pBtn) int nEntry = m_pWordsLB->get_selected_index(); RemoveDictEntry(nEntry); // remove entry from dic and list-box + RebuildSortedDicEntries(); } if (pBtn == m_xNewReplacePB.get() || m_xNewReplacePB->get_sensitive()) { @@ -655,6 +667,8 @@ bool SvxEditDictionaryDialog::NewDelHdl(const weld::Widget* pBtn) m_pWordsLB->thaw(); m_pWordsLB->scroll_to_row(nEntry); + RebuildSortedDicEntries(); + // if the request came from the ReplaceEdit, give focus to the ShortEdit if (m_xReplaceED->has_focus()) m_xWordED->grab_focus(); @@ -670,7 +684,7 @@ bool SvxEditDictionaryDialog::NewDelHdl(const weld::Widget* pBtn) return true; } -IMPL_LINK(SvxEditDictionaryDialog, ModifyHdl, weld::Entry&, rEdt, void) +IMPL_LINK(SvxEditDictionaryDialog, ModifyHdl, weld::TextWidget&, rEdt, void) { OUString rEntry = rEdt.get_text(); @@ -683,6 +697,29 @@ IMPL_LINK(SvxEditDictionaryDialog, ModifyHdl, weld::Entry&, rEdt, void) if (&rEdt == m_xWordED.get()) { + bDoNothing = true; + m_pWordsLB->freeze(); + m_pWordsLB->clear(); + OUString aSearchStr = getNormDicEntry_Impl(rEntry); + + // Filter the cached dictionary entries by prefix match + for (const OUString& rStr : m_aSortedDicEntries) + { + sal_Int32 index = 0; + OUString aWord = rStr.getToken(0, '\t', index); + if (aSearchStr.isEmpty() || getNormDicEntry_Impl(aWord).startsWith(aSearchStr)) + { + m_pWordsLB->append_text(aWord); + if (index != -1 && m_pWordsLB == m_xDoubleColumnLB.get()) + { + OUString sReplace = rStr.getToken(0, '\t', index); + m_pWordsLB->set_text(m_pWordsLB->n_children() - 1, sReplace, 1); + } + } + } + m_pWordsLB->thaw(); + bDoNothing = false; + if(nWordLen>0) { bool bFound = false; diff --git a/cui/source/options/optfltr.hxx b/cui/source/options/optfltr.hxx index 47f5a701048e..1950e9423243 100644 --- a/cui/source/options/optfltr.hxx +++ b/cui/source/options/optfltr.hxx @@ -19,6 +19,9 @@ #pragma once #include +#include +#include +#include #include class OfaMSFilterTabPage : public SfxTabPage diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx index 475cfbf99d04..a9e596f5f027 100644 --- a/cui/source/options/optgdlg.cxx +++ b/cui/source/options/optgdlg.cxx @@ -86,6 +86,7 @@ #include #include #include +#include #if defined(_WIN32) #include @@ -544,8 +545,8 @@ OfaViewTabPage::OfaViewTabPage(weld::Container* pPage, weld::DialogController* p , m_xUseAntiAliaseImg(m_xBuilder->weld_widget(u"lockuseaa"_ustr)) , m_xUseSkia(m_xBuilder->weld_check_button(u"useskia"_ustr)) , m_xUseSkiaImg(m_xBuilder->weld_widget(u"lockuseskia"_ustr)) - , m_xForceSkiaRaster(m_xBuilder->weld_check_button(u"forceskiaraster"_ustr)) - , m_xForceSkiaRasterImg(m_xBuilder->weld_widget(u"lockforceskiaraster"_ustr)) + , m_xForceSkiaGPU(m_xBuilder->weld_check_button(u"forceskiagpu"_ustr)) + , m_xForceSkiaGPUImg(m_xBuilder->weld_widget(u"lockforceskiagpu"_ustr)) , m_xSkiaStatusEnabled(m_xBuilder->weld_label(u"skiaenabled"_ustr)) , m_xSkiaStatusDisabled(m_xBuilder->weld_label(u"skiadisabled"_ustr)) , m_xSkiaLog(m_xBuilder->weld_button(u"btnSkialog"_ustr)) @@ -603,7 +604,7 @@ IMPL_LINK_NOARG(OfaViewTabPage, OnCopySkiaLog, weld::Button&, void) void OfaViewTabPage::HideSkiaWidgets() { m_xUseSkia->hide(); - m_xForceSkiaRaster->hide(); + m_xForceSkiaGPU->hide(); m_xSkiaStatusEnabled->hide(); m_xSkiaStatusDisabled->hide(); m_xSkiaLog->hide(); @@ -641,8 +642,8 @@ void OfaViewTabPage::UpdateSkiaStatus() m_xUseSkia->set_sensitive(!officecfg::Office::Common::VCL::UseSkia::isReadOnly()); #endif m_xUseSkiaImg->set_visible(officecfg::Office::Common::VCL::UseSkia::isReadOnly()); - m_xForceSkiaRaster->set_sensitive(m_xUseSkia->get_active() && !officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly()); - m_xForceSkiaRasterImg->set_visible(officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly()); + m_xForceSkiaGPU->set_sensitive(m_xUseSkia->get_active() && !officecfg::Office::Common::VCL::ForceSkiaGPU::isReadOnly()); + m_xForceSkiaGPUImg->set_visible(officecfg::Office::Common::VCL::ForceSkiaGPU::isReadOnly()); m_xSkiaLog->set_sensitive(bEnabled); // Technically the 'use hardware acceleration' option could be used to mean !forceSkiaRaster, but the implementation @@ -672,7 +673,7 @@ OUString OfaViewTabPage::GetAllStrings() } OUString checkButton[] - = { u"useaccel"_ustr, u"useaa"_ustr, u"useskia"_ustr, u"forceskiaraster"_ustr, u"showfontpreview"_ustr, u"aafont"_ustr }; + = { u"useaccel"_ustr, u"useaa"_ustr, u"useskia"_ustr, u"forceskiagpu"_ustr, u"showfontpreview"_ustr, u"aafont"_ustr }; for (const auto& check : checkButton) { @@ -749,10 +750,10 @@ bool OfaViewTabPage::FillItemSet( SfxItemSet* ) } if (m_xUseSkia->get_state_changed_from_saved() || - m_xForceSkiaRaster->get_state_changed_from_saved()) + m_xForceSkiaGPU->get_state_changed_from_saved()) { officecfg::Office::Common::VCL::UseSkia::set(m_xUseSkia->get_active(), xChanges); - officecfg::Office::Common::VCL::ForceSkiaRaster::set(m_xForceSkiaRaster->get_active(), xChanges); + officecfg::Office::Common::VCL::ForceSkiaGPU::set(m_xForceSkiaGPU->get_active(), xChanges); bModified = true; } @@ -776,7 +777,7 @@ bool OfaViewTabPage::FillItemSet( SfxItemSet* ) } if (m_xUseSkia->get_state_changed_from_saved() || - m_xForceSkiaRaster->get_state_changed_from_saved()) + m_xForceSkiaGPU->get_state_changed_from_saved()) { SolarMutexGuard aGuard; if( svtools::executeRestartDialog( @@ -835,9 +836,9 @@ void OfaViewTabPage::Reset( const SfxItemSet* ) #else m_xUseSkia->set_active(officecfg::Office::Common::VCL::UseSkia::get()); #endif - m_xForceSkiaRaster->set_active(officecfg::Office::Common::VCL::ForceSkiaRaster::get()); + m_xForceSkiaGPU->set_active(officecfg::Office::Common::VCL::ForceSkiaGPU::get()); m_xUseSkia->save_state(); - m_xForceSkiaRaster->save_state(); + m_xForceSkiaGPU->save_state(); m_xFontAntiAliasing->save_state(); m_xAAPointLimit->save_value(); @@ -1516,23 +1517,23 @@ IMPL_LINK_NOARG(OfaLanguagesTabPage, LocaleSettingHdl, weld::ComboBox&, void) m_xDatePatternsED->set_message_type(weld::EntryMessageType::Normal); } -IMPL_LINK( OfaLanguagesTabPage, DatePatternsHdl, weld::Entry&, rEd, void ) +IMPL_LINK_NOARG(OfaLanguagesTabPage, DatePatternsHdl, weld::TextWidget&, void) { - OUString aPatterns(rEd.get_text()); + OUString aPatterns(m_xDatePatternsED->get_text()); bool bModified = false; const bool bValid = validateDatePatterns( bModified, aPatterns); if (bModified) { // gtk3 keeps the cursor position on equal length set_text() but at // least the 'gen' backend does not and resets to 0. - const int nCursorPos = rEd.get_position(); - rEd.set_text(aPatterns); - rEd.set_position(nCursorPos); + const int nCursorPos = m_xDatePatternsED->get_position(); + m_xDatePatternsED->set_text(aPatterns); + m_xDatePatternsED->set_position(nCursorPos); } if (bValid) - rEd.set_message_type(weld::EntryMessageType::Normal); + m_xDatePatternsED->set_message_type(weld::EntryMessageType::Normal); else - rEd.set_message_type(weld::EntryMessageType::Error); + m_xDatePatternsED->set_message_type(weld::EntryMessageType::Error); m_bDatePatternsValid = bValid; } diff --git a/cui/source/options/optgdlg.hxx b/cui/source/options/optgdlg.hxx index 81cb43da21e4..082d14a5ddbe 100644 --- a/cui/source/options/optgdlg.hxx +++ b/cui/source/options/optgdlg.hxx @@ -21,7 +21,10 @@ #include #include #include +#include +#include #include +#include #include #include @@ -103,8 +106,8 @@ private: std::unique_ptr m_xUseAntiAliaseImg; std::unique_ptr m_xUseSkia; std::unique_ptr m_xUseSkiaImg; - std::unique_ptr m_xForceSkiaRaster; - std::unique_ptr m_xForceSkiaRasterImg; + std::unique_ptr m_xForceSkiaGPU; + std::unique_ptr m_xForceSkiaGPUImg; std::unique_ptr m_xSkiaStatusEnabled; std::unique_ptr m_xSkiaStatusDisabled; @@ -175,7 +178,7 @@ class OfaLanguagesTabPage : public SfxTabPage std::unique_ptr m_xUseInputLanguageImg; DECL_LINK(LocaleSettingHdl, weld::ComboBox&, void); - DECL_LINK(DatePatternsHdl, weld::Entry&, void); + DECL_LINK(DatePatternsHdl, weld::TextWidget&, void); bool validateDatePatterns( bool& rbModified, OUString& rPatterns ); diff --git a/cui/source/options/optgenrl.cxx b/cui/source/options/optgenrl.cxx index 3091cb596d45..c21e1d4279b8 100644 --- a/cui/source/options/optgenrl.cxx +++ b/cui/source/options/optgenrl.cxx @@ -392,7 +392,7 @@ IMPL_LINK(SvxGeneralTabPage, RemoveKeyButtonHdl, weld::Button&, rButton, void) void SvxGeneralTabPage::SetLinks () { // link for updating the initials - Link aLink = LINK( this, SvxGeneralTabPage, ModifyHdl_Impl ); + Link aLink = LINK(this, SvxGeneralTabPage, ModifyHdl_Impl); Row& rNameRow = *vRows[nNameRow]; for (unsigned i = rNameRow.nFirstField; i != rNameRow.nLastField - 1; ++i) vFields[i]->xEdit->connect_changed(aLink); @@ -466,7 +466,7 @@ void SvxGeneralTabPage::Reset( const SfxItemSet* rSet ) // ModifyHdl_Impl() // This handler updates the initials (short name) // when one of the name fields was updated. -IMPL_LINK( SvxGeneralTabPage, ModifyHdl_Impl, weld::Entry&, rEdit, void ) +IMPL_LINK(SvxGeneralTabPage, ModifyHdl_Impl, weld::TextWidget&, rEdit, void) { // short name field and row Field& rShortName = *vFields[nShortNameField]; diff --git a/cui/source/options/opthtml.cxx b/cui/source/options/opthtml.cxx index 090beef4aae3..ed8761267dbf 100644 --- a/cui/source/options/opthtml.cxx +++ b/cui/source/options/opthtml.cxx @@ -23,6 +23,7 @@ #include "opthtml.hxx" #include #include +#include OfaHtmlTabPage::OfaHtmlTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) diff --git a/cui/source/options/opthtml.hxx b/cui/source/options/opthtml.hxx index 8470f4da1ec9..f6efb7ecbd56 100644 --- a/cui/source/options/opthtml.hxx +++ b/cui/source/options/opthtml.hxx @@ -19,6 +19,7 @@ #pragma once #include +#include #include class OfaHtmlTabPage : public SfxTabPage diff --git a/cui/source/options/optinet2.cxx b/cui/source/options/optinet2.cxx index e8a0df181529..f92f918ef014 100644 --- a/cui/source/options/optinet2.cxx +++ b/cui/source/options/optinet2.cxx @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -84,7 +83,7 @@ bool isValidPort(OUString const & value) { } -IMPL_LINK(SvxProxyTabPage, PortChangedHdl, weld::Entry&, rEdit, void) +IMPL_LINK(SvxProxyTabPage, PortChangedHdl, weld::TextWidget&, rEdit, void) { if (!isValidPort(rEdit.get_text())) { @@ -518,7 +517,7 @@ IMPL_LINK_NOARG(SvxSecurityTabPage, CertMgrPBHdl, weld::Button&, void) try { FileDialogHelper aHelper(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, - FileDialogFlags::NONE, nullptr); + FileDialogFlags::NONE, GetDialogController()->getDialog()); OUString sPath = m_xParameterEdit->get_text(); if (sPath.isEmpty()) sPath = "/usr/bin"; diff --git a/cui/source/options/optinet2.hxx b/cui/source/options/optinet2.hxx index ea234b337282..2f1ea04ae102 100644 --- a/cui/source/options/optinet2.hxx +++ b/cui/source/options/optinet2.hxx @@ -20,8 +20,13 @@ #include #include +#include +#include #include +#include #include +#include +#include namespace svx { class SecurityOptionsDialog; @@ -62,7 +67,7 @@ private: void ReadConfigDefaults_Impl(); void RestoreConfigDefaults_Impl(); - DECL_LINK(PortChangedHdl, weld::Entry&, void); + DECL_LINK(PortChangedHdl, weld::TextWidget&, void); DECL_STATIC_LINK(SvxProxyTabPage, NumberOnlyTextFilterHdl, OUString&, bool); DECL_STATIC_LINK(SvxProxyTabPage, NoSpaceTextFilterHdl, OUString&, bool); DECL_LINK(ProxyHdl_Impl, weld::ComboBox&, void); diff --git a/cui/source/options/optjava.cxx b/cui/source/options/optjava.cxx index d93f7468f2ef..aefd3b64061c 100644 --- a/cui/source/options/optjava.cxx +++ b/cui/source/options/optjava.cxx @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include @@ -87,7 +87,7 @@ SvxJavaOptionsPage::SvxJavaOptionsPage(weld::Container* pPage, weld::DialogContr m_xJavaList->set_size_request(m_xJavaList->get_approximate_digit_width() * 30, m_xJavaList->get_height_rows(8)); - m_xJavaList->enable_toggle_buttons(weld::ColumnToggleType::Radio); + m_xJavaList->set_toggle_button_type(weld::ColumnToggleType::Radio); m_xJavaList->connect_toggled( LINK( this, SvxJavaOptionsPage, CheckHdl_Impl ) ); m_xJavaList->connect_selection_changed(LINK(this, SvxJavaOptionsPage, SelectHdl_Impl)); @@ -357,7 +357,7 @@ void SvxJavaOptionsPage::AddJRE( JavaInfo const * _pInfo ) #if HAVE_FEATURE_JAVA int nPos = m_xJavaList->n_children(); m_xJavaList->append(); - m_xJavaList->set_toggle(nPos, TRISTATE_FALSE); + m_xJavaList->set_toggle(nPos, TRISTATE_FALSE, 0); m_xJavaList->set_text(nPos, _pInfo->sVendor, 1); // tdf#80662 Add LRM and PDF Unicode characters around version info // to display it correctly, even when UI is RTL (SAL_RTL_ENABLED=1) @@ -380,7 +380,7 @@ void SvxJavaOptionsPage::HandleCheckEntry(int nCheckedRow) for (int i = 0, nCount = m_xJavaList->n_children(); i < nCount; ++i) { // we have radio button behavior -> so uncheck the other entries - m_xJavaList->set_toggle(i, i == nCheckedRow ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xJavaList->set_toggle(i, i == nCheckedRow ? TRISTATE_TRUE : TRISTATE_FALSE, 0); } } @@ -553,7 +553,7 @@ bool SvxJavaOptionsPage::FillItemSet( SfxItemSet* /*rCoreSet*/ ) sal_uInt32 nCount = m_xJavaList->n_children(); for (sal_uInt32 i = 0; i < nCount; ++i) { - if (m_xJavaList->get_toggle(i) == TRISTATE_TRUE) + if (m_xJavaList->get_toggle(i, 0) == TRISTATE_TRUE) { JavaInfo const * pInfo; if ( i < m_parJavaInfo.size() ) @@ -669,7 +669,7 @@ SvxJavaParameterDlg::~SvxJavaParameterDlg() { } -IMPL_LINK_NOARG(SvxJavaParameterDlg, ModifyHdl_Impl, weld::Entry&, void) +IMPL_LINK_NOARG(SvxJavaParameterDlg, ModifyHdl_Impl, weld::TextWidget&, void) { OUString sParam = comphelper::string::strip(m_xParameterEdit->get_text(), ' '); m_xAssignBtn->set_sensitive(!sParam.isEmpty()); diff --git a/cui/source/options/optjava.hxx b/cui/source/options/optjava.hxx index b333c6f3d04e..483d598e1de7 100644 --- a/cui/source/options/optjava.hxx +++ b/cui/source/options/optjava.hxx @@ -25,8 +25,10 @@ #include #include #include +#include +#include #include -#include +#include #include #include #include @@ -127,7 +129,7 @@ private: std::unique_ptr m_xRemoveBtn; std::unique_ptr m_xEditBtn; - DECL_LINK(ModifyHdl_Impl, weld::Entry&, void); + DECL_LINK(ModifyHdl_Impl, weld::TextWidget&, void); DECL_LINK(ActivateHdl_Impl, weld::Entry&, bool); DECL_LINK(AssignHdl_Impl, weld::Button&, void); DECL_LINK(SelectHdl_Impl, weld::ItemView&, void); diff --git a/cui/source/options/optjsearch.cxx b/cui/source/options/optjsearch.cxx index d8fcb61d0ba6..7b94fa06a12d 100644 --- a/cui/source/options/optjsearch.cxx +++ b/cui/source/options/optjsearch.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include "optjsearch.hxx" diff --git a/cui/source/options/optjsearch.hxx b/cui/source/options/optjsearch.hxx index 0fce1a70e5f4..f13212d0f872 100644 --- a/cui/source/options/optjsearch.hxx +++ b/cui/source/options/optjsearch.hxx @@ -21,7 +21,7 @@ #include #include -#include +#include class SfxItemSet; diff --git a/cui/source/options/optlanguagetool.cxx b/cui/source/options/optlanguagetool.cxx index 025bdead6cee..2e86f3bf81da 100644 --- a/cui/source/options/optlanguagetool.cxx +++ b/cui/source/options/optlanguagetool.cxx @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include diff --git a/cui/source/options/optlanguagetool.hxx b/cui/source/options/optlanguagetool.hxx index 2958fe752212..451990caaef4 100644 --- a/cui/source/options/optlanguagetool.hxx +++ b/cui/source/options/optlanguagetool.hxx @@ -20,7 +20,9 @@ #include #include +#include #include +#include class OptLanguageToolTabPage : public SfxTabPage { diff --git a/cui/source/options/optlingu.cxx b/cui/source/options/optlingu.cxx index 892d5bcd8e02..3595b233fa6a 100644 --- a/cui/source/options/optlingu.cxx +++ b/cui/source/options/optlingu.cxx @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -57,7 +56,9 @@ #include #include #include +#include #include +#include #include #include @@ -70,7 +71,6 @@ #include #include -#include using namespace ::ucbhelper; using namespace ::com::sun::star; @@ -343,7 +343,6 @@ struct Locale_less } typedef std::vector< ServiceInfo_Impl > ServiceInfoArr; -typedef std::map< LanguageType, Sequence< OUString > > LangImplNameTable; // SvxLinguData_Impl ---------------------------------------------------- @@ -351,39 +350,39 @@ typedef std::map< LanguageType, Sequence< OUString > > LangImplNameTable; class SvxLinguData_Impl { //contains services and implementation names sorted by implementation names - ServiceInfoArr aDisplayServiceArr; - sal_uInt32 nDisplayServices; - - std::set aAllServiceLocales; - LangImplNameTable aCfgSpellTable; - LangImplNameTable aCfgHyphTable; - LangImplNameTable aCfgThesTable; - LangImplNameTable aCfgGrammarTable; - uno::Reference< XLinguServiceManager2 > xLinguSrvcMgr; + ServiceInfoArr m_aDisplayServiceArr; + sal_uInt32 m_nDisplayServices; + std::set m_aAllServiceLocales; + LangImplNameTable m_aCfgSpellTable; + LangImplNameTable m_aCfgHyphTable; + LangImplNameTable m_aCfgThesTable; + LangImplNameTable m_aCfgGrammarTable; + uno::Reference m_xLinguSrvcMgr; static bool AddRemove( Sequence< OUString > &rConfigured, const OUString &rImplName, bool bAdd ); + void MergeDisplayArray(const ServiceInfo_Impl& rToAdd); + public: SvxLinguData_Impl(); - uno::Reference & GetManager() { return xLinguSrvcMgr; } + uno::Reference& GetManager() { return m_xLinguSrvcMgr; } void SetChecked( const Sequence< OUString > &rConfiguredServices ); void Reconfigure( std::u16string_view rDisplayName, bool bEnable ); - const auto& GetAllSupportedLocales() const { return aAllServiceLocales; } + const auto& GetAllSupportedLocales() const { return m_aAllServiceLocales; } - LangImplNameTable & GetSpellTable() { return aCfgSpellTable; } - LangImplNameTable & GetHyphTable() { return aCfgHyphTable; } - LangImplNameTable & GetThesTable() { return aCfgThesTable; } - LangImplNameTable & GetGrammarTable() { return aCfgGrammarTable; } + LangImplNameTable& GetSpellTable() { return m_aCfgSpellTable; } + LangImplNameTable& GetHyphTable() { return m_aCfgHyphTable; } + LangImplNameTable& GetThesTable() { return m_aCfgThesTable; } + LangImplNameTable& GetGrammarTable() { return m_aCfgGrammarTable; } - ServiceInfoArr & GetDisplayServiceArray() { return aDisplayServiceArr; } + ServiceInfoArr& GetDisplayServiceArray() { return m_aDisplayServiceArr; } - const sal_uInt32 & GetDisplayServiceCount() const { return nDisplayServices; } - void SetDisplayServiceCount( sal_uInt32 nVal ) { nDisplayServices = nVal; } + const sal_uInt32& GetDisplayServiceCount() const { return m_nDisplayServices; } // returns the list of service implementation names for the specified // language and service (TYPE_SPELL, TYPE_HYPH, TYPE_THES) sorted in @@ -403,10 +402,18 @@ Sequence< OUString > SvxLinguData_Impl::GetSortedImplNames( LanguageType nLang, LangImplNameTable *pTable = nullptr; switch (nType) { - case TYPE_SPELL : pTable = &aCfgSpellTable; break; - case TYPE_HYPH : pTable = &aCfgHyphTable; break; - case TYPE_THES : pTable = &aCfgThesTable; break; - case TYPE_GRAMMAR : pTable = &aCfgGrammarTable; break; + case TYPE_SPELL: + pTable = &m_aCfgSpellTable; + break; + case TYPE_HYPH: + pTable = &m_aCfgHyphTable; + break; + case TYPE_THES: + pTable = &m_aCfgThesTable; + break; + case TYPE_GRAMMAR: + pTable = &m_aCfgGrammarTable; + break; } Sequence< OUString > aRes; if (!pTable) @@ -417,14 +424,14 @@ Sequence< OUString > SvxLinguData_Impl::GetSortedImplNames( LanguageType nLang, if (pTable->count( nLang )) aRes = (*pTable)[ nLang ]; // add configured services sal_Int32 nIdx = aRes.getLength(); - DBG_ASSERT( nDisplayServices >= o3tl::make_unsigned(nIdx), "size mismatch" ); - aRes.realloc( nDisplayServices ); + DBG_ASSERT(m_nDisplayServices >= o3tl::make_unsigned(nIdx), "size mismatch"); + aRes.realloc(m_nDisplayServices); OUString *pRes = aRes.getArray(); // add not configured services - for (sal_uInt32 i = 0; i < nDisplayServices; ++i) + for (sal_uInt32 i = 0; i < m_nDisplayServices; ++i) { - const ServiceInfo_Impl &rInfo = aDisplayServiceArr[ i ]; + const ServiceInfo_Impl& rInfo = m_aDisplayServiceArr[i]; OUString aImplName; switch (nType) { @@ -451,9 +458,9 @@ Sequence< OUString > SvxLinguData_Impl::GetSortedImplNames( LanguageType nLang, ServiceInfo_Impl * SvxLinguData_Impl::GetInfoByImplName( std::u16string_view rSvcImplName ) { - for (sal_uInt32 i = 0; i < nDisplayServices; ++i) + for (sal_uInt32 i = 0; i < m_nDisplayServices; ++i) { - ServiceInfo_Impl &rTmp = aDisplayServiceArr[ i ]; + ServiceInfo_Impl& rTmp = m_aDisplayServiceArr[i]; if (rTmp.sSpellImplName == rSvcImplName || rTmp.sHyphImplName == rSvcImplName || rTmp.sThesImplName == rSvcImplName || @@ -465,14 +472,10 @@ ServiceInfo_Impl * SvxLinguData_Impl::GetInfoByImplName( std::u16string_view rSv return nullptr; } -static void lcl_MergeDisplayArray( - SvxLinguData_Impl &rData, - const ServiceInfo_Impl &rToAdd ) +void SvxLinguData_Impl::MergeDisplayArray(const ServiceInfo_Impl& rToAdd) { - sal_uInt32 nCnt = 0; - - ServiceInfoArr &rSvcInfoArr = rData.GetDisplayServiceArray(); - sal_uInt32 nEntries = rData.GetDisplayServiceCount(); + ServiceInfoArr& rSvcInfoArr = GetDisplayServiceArray(); + const sal_uInt32 nEntries = m_nDisplayServices; for (sal_uInt32 i = 0; i < nEntries; ++i) { @@ -513,17 +516,16 @@ static void lcl_MergeDisplayArray( } return ; } - ++nCnt; } - rData.GetDisplayServiceArray().push_back( rToAdd ); - rData.SetDisplayServiceCount( nCnt + 1 ); + GetDisplayServiceArray().push_back(rToAdd); + m_nDisplayServices = nEntries + 1; } -SvxLinguData_Impl::SvxLinguData_Impl() : - nDisplayServices (0) +SvxLinguData_Impl::SvxLinguData_Impl() + : m_nDisplayServices(0) { const uno::Reference< XComponentContext >& xContext = ::comphelper::getProcessComponentContext(); - xLinguSrvcMgr = LinguServiceManager::create(xContext); + m_xLinguSrvcMgr = LinguServiceManager::create(xContext); const Locale& rCurrentLocale = Application::GetSettings().GetUILanguageTag().getLocale(); Sequence aArgs @@ -533,8 +535,7 @@ SvxLinguData_Impl::SvxLinguData_Impl() : }; //read spell checker - const Sequence< OUString > aSpellNames = xLinguSrvcMgr->getAvailableServices( - cSpell, Locale() ); + const Sequence aSpellNames = m_xLinguSrvcMgr->getAvailableServices(cSpell, Locale()); for(const OUString& spellName : aSpellNames) { @@ -551,14 +552,14 @@ SvxLinguData_Impl::SvxLinguData_Impl() : //! suppress display of entries with no supported languages (see feature 110994) if (aLocales.hasElements()) { - aAllServiceLocales.insert(aLocales.begin(), aLocales.end()); - lcl_MergeDisplayArray( *this, aInfo ); + m_aAllServiceLocales.insert(aLocales.begin(), aLocales.end()); + MergeDisplayArray(aInfo); } } //read grammar checker - const Sequence< OUString > aGrammarNames = xLinguSrvcMgr->getAvailableServices( - cGrammar, Locale() ); + const Sequence aGrammarNames + = m_xLinguSrvcMgr->getAvailableServices(cGrammar, Locale()); for(const OUString& grammarName : aGrammarNames) { ServiceInfo_Impl aInfo; @@ -574,14 +575,13 @@ SvxLinguData_Impl::SvxLinguData_Impl() : //! suppress display of entries with no supported languages (see feature 110994) if (aLocales.hasElements()) { - aAllServiceLocales.insert(aLocales.begin(), aLocales.end()); - lcl_MergeDisplayArray( *this, aInfo ); + m_aAllServiceLocales.insert(aLocales.begin(), aLocales.end()); + MergeDisplayArray(aInfo); } } //read hyphenator - const Sequence< OUString > aHyphNames = xLinguSrvcMgr->getAvailableServices( - cHyph, Locale() ); + const Sequence aHyphNames = m_xLinguSrvcMgr->getAvailableServices(cHyph, Locale()); for(const OUString& hyphName : aHyphNames) { ServiceInfo_Impl aInfo; @@ -596,14 +596,13 @@ SvxLinguData_Impl::SvxLinguData_Impl() : //! suppress display of entries with no supported languages (see feature 110994) if (aLocales.hasElements()) { - aAllServiceLocales.insert(aLocales.begin(), aLocales.end()); - lcl_MergeDisplayArray( *this, aInfo ); + m_aAllServiceLocales.insert(aLocales.begin(), aLocales.end()); + MergeDisplayArray(aInfo); } } //read thesauri - const Sequence< OUString > aThesNames = xLinguSrvcMgr->getAvailableServices( - cThes, Locale() ); + const Sequence aThesNames = m_xLinguSrvcMgr->getAvailableServices(cThes, Locale()); for(const OUString& thesName : aThesNames) { ServiceInfo_Impl aInfo; @@ -618,35 +617,35 @@ SvxLinguData_Impl::SvxLinguData_Impl() : //! suppress display of entries with no supported languages (see feature 110994) if (aLocales.hasElements()) { - aAllServiceLocales.insert(aLocales.begin(), aLocales.end()); - lcl_MergeDisplayArray( *this, aInfo ); + m_aAllServiceLocales.insert(aLocales.begin(), aLocales.end()); + MergeDisplayArray(aInfo); } } Sequence< OUString > aCfgSvcs; - for (auto const& locale : aAllServiceLocales) + for (auto const& locale : m_aAllServiceLocales) { LanguageType nLang = LanguageTag::convertToLanguageType( locale ); - aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cSpell, locale); + aCfgSvcs = m_xLinguSrvcMgr->getConfiguredServices(cSpell, locale); SetChecked( aCfgSvcs ); if (aCfgSvcs.hasElements()) - aCfgSpellTable[ nLang ] = aCfgSvcs; + m_aCfgSpellTable[nLang] = aCfgSvcs; - aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cGrammar, locale); + aCfgSvcs = m_xLinguSrvcMgr->getConfiguredServices(cGrammar, locale); SetChecked( aCfgSvcs ); if (aCfgSvcs.hasElements()) - aCfgGrammarTable[ nLang ] = aCfgSvcs; + m_aCfgGrammarTable[nLang] = aCfgSvcs; - aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cHyph, locale); + aCfgSvcs = m_xLinguSrvcMgr->getConfiguredServices(cHyph, locale); SetChecked( aCfgSvcs ); if (aCfgSvcs.hasElements()) - aCfgHyphTable[ nLang ] = aCfgSvcs; + m_aCfgHyphTable[nLang] = aCfgSvcs; - aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cThes, locale); + aCfgSvcs = m_xLinguSrvcMgr->getConfiguredServices(cThes, locale); SetChecked( aCfgSvcs ); if (aCfgSvcs.hasElements()) - aCfgThesTable[ nLang ] = aCfgSvcs; + m_aCfgThesTable[nLang] = aCfgSvcs; } } @@ -654,9 +653,9 @@ void SvxLinguData_Impl::SetChecked(const Sequence& rConfiguredServices { for(OUString const & configService : rConfiguredServices) { - for (sal_uInt32 i = 0; i < nDisplayServices; ++i) + for (sal_uInt32 i = 0; i < m_nDisplayServices; ++i) { - ServiceInfo_Impl& rEntry = aDisplayServiceArr[i]; + ServiceInfo_Impl& rEntry = m_aDisplayServiceArr[i]; if (!rEntry.bConfigured) { const OUString &rSrvcImplName = configService; @@ -704,9 +703,9 @@ void SvxLinguData_Impl::Reconfigure( std::u16string_view rDisplayName, bool bEna DBG_ASSERT( !rDisplayName.empty(), "empty DisplayName" ); ServiceInfo_Impl *pInfo = nullptr; - for (sal_uInt32 i = 0; i < nDisplayServices; ++i) + for (sal_uInt32 i = 0; i < m_nDisplayServices; ++i) { - ServiceInfo_Impl& rTmp = aDisplayServiceArr[i]; + ServiceInfo_Impl& rTmp = m_aDisplayServiceArr[i]; if (rTmp.sDisplayName == rDisplayName) { pInfo = &rTmp; @@ -725,10 +724,10 @@ void SvxLinguData_Impl::Reconfigure( std::u16string_view rDisplayName, bool bEna for (auto& locale : pInfo->xSpell->getLocales()) { LanguageType nLang = LanguageTag::convertToLanguageType(locale); - if (!aCfgSpellTable.count( nLang ) && bEnable) - aCfgSpellTable[ nLang ] = Sequence< OUString >(); - if (aCfgSpellTable.count( nLang )) - AddRemove( aCfgSpellTable[ nLang ], pInfo->sSpellImplName, bEnable ); + if (!m_aCfgSpellTable.count(nLang) && bEnable) + m_aCfgSpellTable[nLang] = Sequence(); + if (m_aCfgSpellTable.count(nLang)) + AddRemove(m_aCfgSpellTable[nLang], pInfo->sSpellImplName, bEnable); } } @@ -738,10 +737,10 @@ void SvxLinguData_Impl::Reconfigure( std::u16string_view rDisplayName, bool bEna for (auto& locale : pInfo->xGrammar->getLocales()) { LanguageType nLang = LanguageTag::convertToLanguageType(locale); - if (!aCfgGrammarTable.count( nLang ) && bEnable) - aCfgGrammarTable[ nLang ] = Sequence< OUString >(); - if (aCfgGrammarTable.count( nLang )) - AddRemove( aCfgGrammarTable[ nLang ], pInfo->sGrammarImplName, bEnable ); + if (!m_aCfgGrammarTable.count(nLang) && bEnable) + m_aCfgGrammarTable[nLang] = Sequence(); + if (m_aCfgGrammarTable.count(nLang)) + AddRemove(m_aCfgGrammarTable[nLang], pInfo->sGrammarImplName, bEnable); } } @@ -751,10 +750,10 @@ void SvxLinguData_Impl::Reconfigure( std::u16string_view rDisplayName, bool bEna for (auto& locale : pInfo->xHyph->getLocales()) { LanguageType nLang = LanguageTag::convertToLanguageType(locale); - if (!aCfgHyphTable.count( nLang ) && bEnable) - aCfgHyphTable[ nLang ] = Sequence< OUString >(); - if (aCfgHyphTable.count( nLang )) - AddRemove( aCfgHyphTable[ nLang ], pInfo->sHyphImplName, bEnable ); + if (!m_aCfgHyphTable.count(nLang) && bEnable) + m_aCfgHyphTable[nLang] = Sequence(); + if (m_aCfgHyphTable.count(nLang)) + AddRemove(m_aCfgHyphTable[nLang], pInfo->sHyphImplName, bEnable); } } @@ -765,33 +764,34 @@ void SvxLinguData_Impl::Reconfigure( std::u16string_view rDisplayName, bool bEna for (auto& locale : pInfo->xThes->getLocales()) { LanguageType nLang = LanguageTag::convertToLanguageType(locale); - if (!aCfgThesTable.count( nLang ) && bEnable) - aCfgThesTable[ nLang ] = Sequence< OUString >(); - if (aCfgThesTable.count( nLang )) - AddRemove( aCfgThesTable[ nLang ], pInfo->sThesImplName, bEnable ); + if (!m_aCfgThesTable.count(nLang) && bEnable) + m_aCfgThesTable[nLang] = Sequence(); + if (m_aCfgThesTable.count(nLang)) + AddRemove(m_aCfgThesTable[nLang], pInfo->sThesImplName, bEnable); } } // class SvxLinguTabPage ------------------------------------------------- -SvxLinguTabPage::SvxLinguTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) +SvxLinguTabPage::SvxLinguTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) : SfxTabPage(pPage, pController, u"cui/ui/optlingupage.ui"_ustr, u"OptLinguPage"_ustr, &rSet) - , sCapitalWords (CuiResId(RID_CUISTR_CAPITAL_WORDS)) - , sWordsWithDigits(CuiResId(RID_CUISTR_WORDS_WITH_DIGITS)) - , sSpellSpecial (CuiResId(RID_CUISTR_SPELL_SPECIAL)) - , sSpellAuto (CuiResId(RID_CUISTR_SPELL_AUTO)) - , sSpellClosedCompound (CuiResId(RID_CUISTR_SPELL_CLOSED_COMPOUND)) - , sSpellHyphenatedCompound (CuiResId(RID_CUISTR_SPELL_HYPHENATED_COMPOUND)) - , sGrammarAuto (CuiResId(RID_CUISTR_GRAMMAR_AUTO)) - , sNumMinWordlen (CuiResId(RID_CUISTR_NUM_MIN_WORDLEN)) - , sNumPreBreak (CuiResId(RID_CUISTR_NUM_PRE_BREAK)) - , sNumPostBreak (CuiResId(RID_CUISTR_NUM_POST_BREAK)) - , sHyphAuto (CuiResId(RID_CUISTR_HYPH_AUTO)) - , sHyphSpecial (CuiResId(RID_CUISTR_HYPH_SPECIAL)) - , nUPN_HYPH_MIN_WORD_LENGTH(-1) - , nUPN_HYPH_MIN_LEADING(-1) - , nUPN_HYPH_MIN_TRAILING(-1) + , m_sCapitalWords(CuiResId(RID_CUISTR_CAPITAL_WORDS)) + , m_sWordsWithDigits(CuiResId(RID_CUISTR_WORDS_WITH_DIGITS)) + , m_sSpellSpecial(CuiResId(RID_CUISTR_SPELL_SPECIAL)) + , m_sSpellAuto(CuiResId(RID_CUISTR_SPELL_AUTO)) + , m_sSpellClosedCompound(CuiResId(RID_CUISTR_SPELL_CLOSED_COMPOUND)) + , m_sSpellHyphenatedCompound(CuiResId(RID_CUISTR_SPELL_HYPHENATED_COMPOUND)) + , m_sGrammarAuto(CuiResId(RID_CUISTR_GRAMMAR_AUTO)) + , m_sNumMinWordlen(CuiResId(RID_CUISTR_NUM_MIN_WORDLEN)) + , m_sNumPreBreak(CuiResId(RID_CUISTR_NUM_PRE_BREAK)) + , m_sNumPostBreak(CuiResId(RID_CUISTR_NUM_POST_BREAK)) + , m_sHyphAuto(CuiResId(RID_CUISTR_HYPH_AUTO)) + , m_sHyphSpecial(CuiResId(RID_CUISTR_HYPH_SPECIAL)) + , m_nUPN_HYPH_MIN_WORD_LENGTH(-1) + , m_nUPN_HYPH_MIN_LEADING(-1) + , m_nUPN_HYPH_MIN_TRAILING(-1) , m_nDlbClickEventId(nullptr) , m_xLinguModulesFrame(m_xBuilder->weld_container(u"lingumodulesframe"_ustr)) , m_xLinguModulesCLB(m_xBuilder->weld_tree_view(u"lingumodules"_ustr)) @@ -806,9 +806,9 @@ SvxLinguTabPage::SvxLinguTabPage(weld::Container* pPage, weld::DialogController* , m_xMoreDictsBox(m_xBuilder->weld_box(u"moredictsbox"_ustr)) , m_xMoreDictsLink(m_xBuilder->weld_link_button(u"moredictslink"_ustr)) { - m_xLinguModulesCLB->enable_toggle_buttons(weld::ColumnToggleType::Check); - m_xLinguDicsCLB->enable_toggle_buttons(weld::ColumnToggleType::Check); - m_xLinguOptionsCLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xLinguModulesCLB->enable_toggle_buttons(); + m_xLinguDicsCLB->enable_toggle_buttons(); + m_xLinguOptionsCLB->enable_toggle_buttons(); m_xLinguModulesCLB->connect_selection_changed(LINK(this, SvxLinguTabPage, SelectHdl_Impl)); m_xLinguModulesCLB->connect_item_activated(LINK(this, SvxLinguTabPage, BoxDoubleClickHdl_Impl)); @@ -839,9 +839,9 @@ SvxLinguTabPage::SvxLinguTabPage(weld::Container* pPage, weld::DialogController* m_xMoreDictsBox->hide(); } - xProp = LinguMgr::GetLinguPropertySet(); - xDicList.set( LinguMgr::GetDictionaryList() ); - if (xDicList.is()) + m_xProp = LinguMgr::GetLinguPropertySet(); + m_xDicList.set(LinguMgr::GetDictionaryList()); + if (m_xDicList.is()) { // keep references to all **currently** available dictionaries, // since the diclist may get changed meanwhile (e.g. through the API). @@ -851,7 +851,7 @@ SvxLinguTabPage::SvxLinguTabPage(weld::Container* pPage, weld::DialogController* // someone else removes a dictionary from the list. // removed dics will be replaced by NULL new entries be added to the end // Thus we may use indices as consistent references. - aDics = xDicList->getDictionaries(); + m_aDics = m_xDicList->getDictionaries(); UpdateDicBox_Impl(); } @@ -872,7 +872,7 @@ SvxLinguTabPage::~SvxLinguTabPage() Application::RemoveUserEvent(m_nDlbClickEventId); m_nDlbClickEventId = nullptr; } - pLinguData.reset(); + m_pLinguData.reset(); } std::unique_ptr SvxLinguTabPage::Create( weld::Container* pPage, weld::DialogController* pController, @@ -897,64 +897,40 @@ OUString SvxLinguTabPage::GetAllStrings() return sAllStrings.toString().replaceAll("_", ""); } +void SvxLinguTabPage::SetConfiguredServices(const OUString& rServiceName, + const LangImplNameTable& rTable) +{ + for (auto const& elem : rTable) + { + LanguageType nLang = elem.first; + const Sequence aImplNames(elem.second); + uno::Reference xMgr(m_pLinguData->GetManager()); + Locale aLocale(LanguageTag::convertToLocale(nLang)); + if (xMgr.is()) + xMgr->setConfiguredServices(rServiceName, aLocale, aImplNames); + } +} + bool SvxLinguTabPage::FillItemSet( SfxItemSet* rCoreSet ) { - bool bModified = true; // !!!! - - // if not HideGroups was called with GROUP_MODULES... + // if not HideModulesGroup was called... if (m_xLinguModulesCLB->get_visible()) { - DBG_ASSERT( pLinguData, "pLinguData not yet initialized" ); - if (!pLinguData) - pLinguData.reset( new SvxLinguData_Impl ); + DBG_ASSERT(m_pLinguData, "pLinguData not yet initialized"); + if (!m_pLinguData) + m_pLinguData.reset(new SvxLinguData_Impl); // update spellchecker configuration entries - const LangImplNameTable *pTable = &pLinguData->GetSpellTable(); - for (auto const& elem : *pTable) - { - LanguageType nLang = elem.first; - const Sequence< OUString > aImplNames(elem.second); - uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() ); - Locale aLocale( LanguageTag::convertToLocale(nLang) ); - if (xMgr.is()) - xMgr->setConfiguredServices( cSpell, aLocale, aImplNames ); - } + SetConfiguredServices(cSpell, m_pLinguData->GetSpellTable()); // update grammar checker configuration entries - pTable = &pLinguData->GetGrammarTable(); - for (auto const& elem : *pTable) - { - LanguageType nLang = elem.first; - const Sequence< OUString > aImplNames(elem.second); - uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() ); - Locale aLocale( LanguageTag::convertToLocale(nLang) ); - if (xMgr.is()) - xMgr->setConfiguredServices( cGrammar, aLocale, aImplNames ); - } + SetConfiguredServices(cGrammar, m_pLinguData->GetGrammarTable()); // update hyphenator configuration entries - pTable = &pLinguData->GetHyphTable(); - for (auto const& elem : *pTable) - { - LanguageType nLang = elem.first; - const Sequence< OUString > aImplNames(elem.second); - uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() ); - Locale aLocale( LanguageTag::convertToLocale(nLang) ); - if (xMgr.is()) - xMgr->setConfiguredServices( cHyph, aLocale, aImplNames ); - } + SetConfiguredServices(cHyph, m_pLinguData->GetHyphTable()); // update thesaurus configuration entries - pTable = &pLinguData->GetThesTable(); - for (auto const& elem : *pTable) - { - LanguageType nLang = elem.first; - const Sequence< OUString > aImplNames(elem.second); - uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() ); - Locale aLocale( LanguageTag::convertToLocale(nLang) ); - if (xMgr.is()) - xMgr->setConfiguredServices( cThes, aLocale, aImplNames ); - } + SetConfiguredServices(cThes, m_pLinguData->GetThesTable()); } @@ -965,7 +941,7 @@ bool SvxLinguTabPage::FillItemSet( SfxItemSet* rCoreSet ) int nEntries = m_xLinguDicsCLB->n_children(); for (int i = 0; i < nEntries; ++i) { - sal_Int32 nDics = aDics.getLength(); + sal_Int32 nDics = m_aDics.getLength(); aActiveDics.realloc( nDics ); OUString *pActiveDic = aActiveDics.getArray(); @@ -974,7 +950,7 @@ bool SvxLinguTabPage::FillItemSet( SfxItemSet* rCoreSet ) if (aData.GetEntryId() < nDics) { bool bChecked = m_xLinguDicsCLB->get_toggle(i) == TRISTATE_TRUE; - uno::Reference xDic(aDics[i]); + uno::Reference xDic(m_aDics[i]); if (xDic.is()) { if (LinguMgr::GetIgnoreAllList() == xDic) @@ -1011,8 +987,8 @@ bool SvxLinguTabPage::FillItemSet( SfxItemSet* rCoreSet ) aAny <<= nVal; } - if (xProp.is()) - xProp->setPropertyValue( aPropName, aAny ); + if (m_xProp.is()) + m_xProp->setPropertyValue(aPropName, aAny); aLngCfg.SetProperty( aPropName, aAny ); } @@ -1032,10 +1008,9 @@ bool SvxLinguTabPage::FillItemSet( SfxItemSet* rCoreSet ) if ( !pOld || static_cast(pOld)->GetValue() != bNewAutoCheck ) { rCoreSet->Put( SfxBoolItem( SID_AUTOSPELL_CHECK, bNewAutoCheck ) ); - bModified = true; } - return bModified; + return true; } sal_uInt32 SvxLinguTabPage::GetDicUserData( const uno::Reference< XDictionary > &rxDic, sal_uInt16 nIdx ) @@ -1081,9 +1056,9 @@ void SvxLinguTabPage::UpdateDicBox_Impl() m_xLinguDicsCLB->freeze(); m_xLinguDicsCLB->clear(); - for (sal_Int32 i = 0; i < aDics.getLength(); ++i) + for (sal_Int32 i = 0; i < m_aDics.getLength(); ++i) { - const uno::Reference& rDic = aDics[i]; + const uno::Reference& rDic = m_aDics[i]; if (rDic.is()) AddDicBoxEntry( rDic, static_cast(i) ); } @@ -1098,11 +1073,11 @@ void SvxLinguTabPage::UpdateDicBox_Impl() void SvxLinguTabPage::UpdateModulesBox_Impl() { - if (!pLinguData) + if (!m_pLinguData) return; - const ServiceInfoArr &rAllDispSrvcArr = pLinguData->GetDisplayServiceArray(); - const sal_uInt32 nDispSrvcCount = pLinguData->GetDisplayServiceCount(); + const ServiceInfoArr& rAllDispSrvcArr = m_pLinguData->GetDisplayServiceArray(); + const sal_uInt32 nDispSrvcCount = m_pLinguData->GetDisplayServiceCount(); m_xLinguModulesCLB->clear(); @@ -1124,11 +1099,11 @@ void SvxLinguTabPage::UpdateModulesBox_Impl() void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) { - // if not HideGroups was called with GROUP_MODULES... + // if not HideModulesGroup was called... if (m_xLinguModulesCLB->get_visible()) { - if (!pLinguData) - pLinguData.reset( new SvxLinguData_Impl ); + if (!m_pLinguData) + m_pLinguData.reset(new SvxLinguData_Impl); UpdateModulesBox_Impl(); } @@ -1151,7 +1126,7 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) bVal = pItem->GetValue(); nUserData = OptionsUserData( EID_SPELL_AUTO, false, 0, true, bVal).GetUserData(); m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xLinguOptionsCLB->set_text(nEntry, sSpellAuto, 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sSpellAuto, 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_IS_SPELL_AUTO)); @@ -1161,7 +1136,7 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) aLngCfg.GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bVal; nUserData = OptionsUserData( EID_GRAMMAR_AUTO, false, 0, true, bVal).GetUserData(); m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xLinguOptionsCLB->set_text(nEntry, sGrammarAuto, 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sGrammarAuto, 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_IS_GRAMMAR_AUTO)); @@ -1171,7 +1146,7 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) aLngCfg.GetProperty( UPN_IS_SPELL_UPPER_CASE ) >>= bVal; nUserData = OptionsUserData( EID_CAPITAL_WORDS, false, 0, true, bVal).GetUserData(); m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xLinguOptionsCLB->set_text(nEntry, sCapitalWords, 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sCapitalWords, 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_IS_SPELL_UPPER_CASE)); @@ -1181,7 +1156,7 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) aLngCfg.GetProperty( UPN_IS_SPELL_WITH_DIGITS ) >>= bVal; nUserData = OptionsUserData( EID_WORDS_WITH_DIGITS, false, 0, true, bVal).GetUserData(); m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xLinguOptionsCLB->set_text(nEntry, sWordsWithDigits, 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sWordsWithDigits, 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_IS_SPELL_WITH_DIGITS)); @@ -1191,7 +1166,7 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) aLngCfg.GetProperty( UPN_IS_SPELL_CLOSED_COMPOUND ) >>= bVal; nUserData = OptionsUserData( EID_SPELL_CLOSED_COMPOUND, false, 0, true, bVal).GetUserData(); m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xLinguOptionsCLB->set_text(nEntry, sSpellClosedCompound, 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sSpellClosedCompound, 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_IS_SPELL_CLOSED_COMPOUND)); @@ -1201,7 +1176,7 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) aLngCfg.GetProperty( UPN_IS_SPELL_HYPHENATED_COMPOUND ) >>= bVal; nUserData = OptionsUserData( EID_SPELL_HYPHENATED_COMPOUND, false, 0, true, bVal).GetUserData(); m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xLinguOptionsCLB->set_text(nEntry, sSpellHyphenatedCompound, 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sSpellHyphenatedCompound, 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_IS_SPELL_HYPHENATED_COMPOUND)); @@ -1211,7 +1186,7 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) aLngCfg.GetProperty( UPN_IS_SPELL_SPECIAL ) >>= bVal; nUserData = OptionsUserData( EID_SPELL_SPECIAL, false, 0, true, bVal).GetUserData(); m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xLinguOptionsCLB->set_text(nEntry, sSpellSpecial, 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sSpellSpecial, 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_IS_SPELL_SPECIAL)); @@ -1220,10 +1195,10 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) aLngCfg.GetProperty( UPN_HYPH_MIN_WORD_LENGTH ) >>= nVal; nUserData = OptionsUserData( EID_NUM_MIN_WORDLEN, true, static_cast(nVal), false, false).GetUserData(); - m_xLinguOptionsCLB->set_text(nEntry, sNumMinWordlen + " " + OUString::number(nVal), 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sNumMinWordlen + " " + OUString::number(nVal), 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_HYPH_MIN_WORD_LENGTH)); - nUPN_HYPH_MIN_WORD_LENGTH = nEntry; + m_nUPN_HYPH_MIN_WORD_LENGTH = nEntry; const SfxHyphenRegionItem *pHyp = nullptr; if ( rSet->GetItemState( SID_ATTR_HYPHENREGION, false ) == SfxItemState::SET ) @@ -1236,10 +1211,10 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) if (pHyp) nVal = static_cast(pHyp->GetMinLead()); nUserData = OptionsUserData( EID_NUM_PRE_BREAK, true, static_cast(nVal), false, false).GetUserData(); - m_xLinguOptionsCLB->set_text(nEntry, sNumPreBreak + " " + OUString::number(nVal), 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sNumPreBreak + " " + OUString::number(nVal), 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_HYPH_MIN_LEADING)); - nUPN_HYPH_MIN_LEADING = nEntry; + m_nUPN_HYPH_MIN_LEADING = nEntry; m_xLinguOptionsCLB->append(); ++nEntry; @@ -1248,10 +1223,10 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) if (pHyp) nVal = static_cast(pHyp->GetMinTrail()); nUserData = OptionsUserData( EID_NUM_POST_BREAK, true, static_cast(nVal), false, false).GetUserData(); - m_xLinguOptionsCLB->set_text(nEntry, sNumPostBreak + " " + OUString::number(nVal), 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sNumPostBreak + " " + OUString::number(nVal), 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_HYPH_MIN_TRAILING)); - nUPN_HYPH_MIN_TRAILING = nEntry; + m_nUPN_HYPH_MIN_TRAILING = nEntry; m_xLinguOptionsCLB->append(); ++nEntry; @@ -1259,7 +1234,7 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) aLngCfg.GetProperty( UPN_IS_HYPH_AUTO ) >>= bVal; nUserData = OptionsUserData( EID_HYPH_AUTO, false, 0, true, bVal).GetUserData(); m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xLinguOptionsCLB->set_text(nEntry, sHyphAuto, 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sHyphAuto, 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_IS_HYPH_AUTO)); @@ -1269,7 +1244,7 @@ void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) aLngCfg.GetProperty( UPN_IS_HYPH_SPECIAL ) >>= bVal; nUserData = OptionsUserData( EID_HYPH_SPECIAL, false, 0, true, bVal).GetUserData(); m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xLinguOptionsCLB->set_text(nEntry, sHyphSpecial, 0); + m_xLinguOptionsCLB->set_text(nEntry, m_sHyphSpecial, 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); m_xLinguOptionsCLB->set_sensitive(nEntry, !aLngCfg.IsReadOnly(UPN_IS_HYPH_SPECIAL)); @@ -1319,15 +1294,16 @@ IMPL_LINK_NOARG(SvxLinguTabPage, PostDblClickHdl_Impl, void*, void) IMPL_LINK(SvxLinguTabPage, ModulesBoxCheckButtonHdl_Impl, const weld::TreeView::iter_col&, rRowCol, void) { - if (!pLinguData) + if (!m_pLinguData) return; - pLinguData->Reconfigure(m_xLinguModulesCLB->get_text(rRowCol.first), - m_xLinguModulesCLB->get_toggle(rRowCol.first) == TRISTATE_TRUE); + m_pLinguData->Reconfigure(m_xLinguModulesCLB->get_text(rRowCol.first), + m_xLinguModulesCLB->get_toggle(rRowCol.first) == TRISTATE_TRUE); } IMPL_LINK(SvxLinguTabPage, DicsBoxCheckButtonHdl_Impl, const weld::TreeView::iter_col&, rRowCol, void) { - const uno::Reference &rDic = aDics[m_xLinguDicsCLB->get_iter_index_in_parent(rRowCol.first)]; + const uno::Reference& rDic + = m_aDics[m_xLinguDicsCLB->get_iter_index_in_parent(rRowCol.first)]; if (LinguMgr::GetIgnoreAllList() == rDic) m_xLinguDicsCLB->set_toggle(rRowCol.first, TRISTATE_TRUE); } @@ -1336,29 +1312,29 @@ IMPL_LINK(SvxLinguTabPage, ClickHdl_Impl, weld::Button&, rBtn, void) { if (m_xLinguModulesEditPB.get() == &rBtn) { - if (!pLinguData) - pLinguData.reset( new SvxLinguData_Impl ); + if (!m_pLinguData) + m_pLinguData.reset(new SvxLinguData_Impl); - SvxLinguData_Impl aOldLinguData(*pLinguData); - SvxEditModulesDlg aDlg(GetFrameWeld(), *pLinguData); + SvxLinguData_Impl aOldLinguData(*m_pLinguData); + SvxEditModulesDlg aDlg(GetFrameWeld(), *m_pLinguData); if (aDlg.run() != RET_OK) - *pLinguData = std::move(aOldLinguData); + *m_pLinguData = std::move(aOldLinguData); // evaluate new status of 'bConfigured' flag - sal_uInt32 nLen = pLinguData->GetDisplayServiceCount(); + sal_uInt32 nLen = m_pLinguData->GetDisplayServiceCount(); for (sal_uInt32 i = 0; i < nLen; ++i) - pLinguData->GetDisplayServiceArray()[i].bConfigured = false; - for (const auto& locale : pLinguData->GetAllSupportedLocales()) + m_pLinguData->GetDisplayServiceArray()[i].bConfigured = false; + for (const auto& locale : m_pLinguData->GetAllSupportedLocales()) { LanguageType nLang = LanguageTag::convertToLanguageType(locale); - if (pLinguData->GetSpellTable().count( nLang )) - pLinguData->SetChecked( pLinguData->GetSpellTable()[ nLang ] ); - if (pLinguData->GetGrammarTable().count( nLang )) - pLinguData->SetChecked( pLinguData->GetGrammarTable()[ nLang ] ); - if (pLinguData->GetHyphTable().count( nLang )) - pLinguData->SetChecked( pLinguData->GetHyphTable()[ nLang ] ); - if (pLinguData->GetThesTable().count( nLang )) - pLinguData->SetChecked( pLinguData->GetThesTable()[ nLang ] ); + if (m_pLinguData->GetSpellTable().count(nLang)) + m_pLinguData->SetChecked(m_pLinguData->GetSpellTable()[nLang]); + if (m_pLinguData->GetGrammarTable().count(nLang)) + m_pLinguData->SetChecked(m_pLinguData->GetGrammarTable()[nLang]); + if (m_pLinguData->GetHyphTable().count(nLang)) + m_pLinguData->SetChecked(m_pLinguData->GetHyphTable()[nLang]); + if (m_pLinguData->GetThesTable().count(nLang)) + m_pLinguData->SetChecked(m_pLinguData->GetThesTable()[nLang]); } // show new status of modules @@ -1374,10 +1350,10 @@ IMPL_LINK(SvxLinguTabPage, ClickHdl_Impl, weld::Button&, rBtn, void) if ( xNewDic.is() ) { // add new dics to the end - sal_Int32 nLen = aDics.getLength(); - aDics.realloc( nLen + 1 ); + sal_Int32 nLen = m_aDics.getLength(); + m_aDics.realloc(nLen + 1); - aDics.getArray()[ nLen ] = xNewDic; + m_aDics.getArray()[nLen] = xNewDic; AddDicBoxEntry( xNewDic, static_cast(nLen) ); } @@ -1389,10 +1365,10 @@ IMPL_LINK(SvxLinguTabPage, ClickHdl_Impl, weld::Button&, rBtn, void) { DicUserData aData(m_xLinguDicsCLB->get_id(nEntry).toUInt32()); sal_uInt16 nDicPos = aData.GetEntryId(); - sal_Int32 nDics = aDics.getLength(); + sal_Int32 nDics = m_aDics.getLength(); if (nDicPos < nDics) { - uno::Reference xDic = aDics[nDicPos]; + uno::Reference xDic = m_aDics[nDicPos]; if (xDic.is()) { SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); @@ -1414,18 +1390,18 @@ IMPL_LINK(SvxLinguTabPage, ClickHdl_Impl, weld::Button&, rBtn, void) { DicUserData aData(m_xLinguDicsCLB->get_id(nEntry).toUInt32()); sal_uInt16 nDicPos = aData.GetEntryId(); - sal_Int32 nDics = aDics.getLength(); + sal_Int32 nDics = m_aDics.getLength(); if (nDicPos < nDics) { - uno::Reference xDic = aDics[nDicPos]; + uno::Reference xDic = m_aDics[nDicPos]; if (xDic.is()) { if (LinguMgr::GetIgnoreAllList() == xDic) xDic->clear(); else { - if (xDicList.is()) - xDicList->removeDictionary( xDic ); + if (m_xDicList.is()) + m_xDicList->removeDictionary(xDic); uno::Reference< frame::XStorable > xStor( xDic, UNO_QUERY ); if ( xStor->hasLocation() && !xStor->isReadonly() ) @@ -1440,7 +1416,7 @@ IMPL_LINK(SvxLinguTabPage, ClickHdl_Impl, weld::Button&, rBtn, void) } } - aDics.getArray()[ nDicPos ] = nullptr; + m_aDics.getArray()[nDicPos] = nullptr; // remove entry from checklistbox int nCnt = m_xLinguDicsCLB->n_children(); @@ -1479,12 +1455,15 @@ IMPL_LINK(SvxLinguTabPage, ClickHdl_Impl, weld::Button&, rBtn, void) { aData.SetNumericValue( static_cast(nVal) ); //! sets IsModified ! m_xLinguOptionsCLB->set_id(nEntry, OUString::number(aData.GetUserData())); - if (nEntry == nUPN_HYPH_MIN_WORD_LENGTH) - m_xLinguOptionsCLB->set_text(nEntry, sNumMinWordlen + " " + OUString::number(nVal), 0); - else if (nEntry == nUPN_HYPH_MIN_LEADING) - m_xLinguOptionsCLB->set_text(nEntry, sNumPreBreak + " " + OUString::number(nVal), 0); - else if (nEntry == nUPN_HYPH_MIN_TRAILING) - m_xLinguOptionsCLB->set_text(nEntry, sNumPostBreak + " " + OUString::number(nVal), 0); + if (nEntry == m_nUPN_HYPH_MIN_WORD_LENGTH) + m_xLinguOptionsCLB->set_text( + nEntry, m_sNumMinWordlen + " " + OUString::number(nVal), 0); + else if (nEntry == m_nUPN_HYPH_MIN_LEADING) + m_xLinguOptionsCLB->set_text( + nEntry, m_sNumPreBreak + " " + OUString::number(nVal), 0); + else if (nEntry == m_nUPN_HYPH_MIN_TRAILING) + m_xLinguOptionsCLB->set_text( + nEntry, m_sNumPostBreak + " " + OUString::number(nVal), 0); m_xLinguOptionsCLB->set_id(nEntry, OUString::number(aData.GetUserData())); } } @@ -1565,7 +1544,7 @@ SvxEditModulesDlg::SvxEditModulesDlg(weld::Window* pParent, SvxLinguData_Impl& r m_xModulesCLB->set_size_request(m_xModulesCLB->get_approximate_digit_width() * 40, m_xModulesCLB->get_height_rows(12)); - m_xModulesCLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xModulesCLB->enable_toggle_buttons(); pDefaultLinguData.reset( new SvxLinguData_Impl( rLinguData ) ); diff --git a/cui/source/options/optpath.cxx b/cui/source/options/optpath.cxx index f26b59b4b3ec..2ea4c64764b8 100644 --- a/cui/source/options/optpath.cxx +++ b/cui/source/options/optpath.cxx @@ -19,13 +19,15 @@ #include #include +#include #include #include #include #include -#include #include #include +#include +#include #include #include @@ -193,7 +195,7 @@ SvxPathTabPage::SvxPathTabPage(weld::Container* pPage, weld::DialogController* p m_xPathBox->get_height_rows(20)); m_xPathBox->connect_item_activated(LINK(this, SvxPathTabPage, DoubleClickPathHdl_Impl)); - m_xPathBox->connect_column_clicked(LINK(this, SvxPathTabPage, HeaderBarClick)); + m_xPathBox->connect_column_header_clicked(LINK(this, SvxPathTabPage, HeaderBarClick)); m_xPathBox->connect_selection_changed(LINK(this, SvxPathTabPage, PathSelect_Impl)); m_xPathBox->set_selection_mode(SelectionMode::Multiple); diff --git a/cui/source/options/optsave.cxx b/cui/source/options/optsave.cxx index 8ae50501f013..50fc194b59c8 100644 --- a/cui/source/options/optsave.cxx +++ b/cui/source/options/optsave.cxx @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -127,7 +128,6 @@ SvxSaveTabPage::SvxSaveTabPage(weld::Container* pPage, weld::DialogController* p auto aFilterClassesNode = utl::OConfigurationTreeRoot::createWithComponentContext( comphelper::getProcessComponentContext(), u"org.openoffice.Office.UI/FilterClassification/GlobalFilters/Classes"_ustr, - -1, utl::OConfigurationTreeRoot::CM_READONLY ); diff --git a/cui/source/options/optsave.hxx b/cui/source/options/optsave.hxx index b94b2315dd11..7b1b9cc5ee3e 100644 --- a/cui/source/options/optsave.hxx +++ b/cui/source/options/optsave.hxx @@ -20,7 +20,9 @@ #include #include +#include #include +#include #include enum AppType diff --git a/cui/source/options/optupdt.hxx b/cui/source/options/optupdt.hxx index 48113c8079d6..bf9395e67820 100644 --- a/cui/source/options/optupdt.hxx +++ b/cui/source/options/optupdt.hxx @@ -20,6 +20,14 @@ #pragma once #include +#include +#include +#include +#include +#include +#include +#include + #include #include diff --git a/cui/source/options/treeopt.cxx b/cui/source/options/treeopt.cxx index d0c8119c1e2b..9e249c133f92 100644 --- a/cui/source/options/treeopt.cxx +++ b/cui/source/options/treeopt.cxx @@ -60,7 +60,6 @@ #include #include "optbasic.hxx" #include "optlanguagetool.hxx" -#include "optdeepl.hxx" // include search util #include @@ -95,6 +94,7 @@ #include #include #include +#include #include #include #include @@ -102,13 +102,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include using namespace ::com::sun::star; @@ -269,7 +269,6 @@ static std::unique_ptr CreateGeneralTabPage(sal_uInt16 nId, weld::Co case RID_SVXPAGE_ACCESSIBILITYCONFIG: fnCreate = &SvxAccessibilityOptionsTabPage::Create; break; case RID_SVXPAGE_OPTIONS_CTL: fnCreate = &SvxCTLOptionsPage::Create ; break; case RID_SVXPAGE_LANGTOOL_OPTIONS: fnCreate = &OptLanguageToolTabPage::Create ; break; - case RID_SVXPAGE_DEEPL_OPTIONS: fnCreate = &OptDeeplTabPage::Create ; break; case RID_SVXPAGE_OPTIONS_JAVA: fnCreate = &SvxJavaOptionsPage::Create ; break; case RID_SVXPAGE_ONLINEUPDATE: fnCreate = &SvxOnlineUpdateTabPage::Create; break; case RID_OPTPAGE_CHART_DEFCOLORS: fnCreate = &SvxDefaultColorOptPage::Create; break; @@ -451,7 +450,7 @@ OfaTreeOptionsDialog::OfaTreeOptionsDialog(weld::Window* pParent, bool fromExten : SfxOkDialogController(pParent, u"cui/ui/optionsdialog.ui"_ustr, u"OptionsDialog"_ustr) , xOkPB(m_xBuilder->weld_button(u"ok"_ustr)) , xApplyPB(m_xBuilder->weld_button(u"apply"_ustr)) - , xBackPB(m_xBuilder->weld_button(u"revert"_ustr)) + , xBackPB(m_xBuilder->weld_button(u"reset"_ustr)) , xTreeLB(m_xBuilder->weld_tree_view(u"pages"_ustr)) , xTabBox(m_xBuilder->weld_container(u"box"_ustr)) , m_xSearchEdit(m_xBuilder->weld_entry(u"searchEntry"_ustr)) @@ -775,7 +774,7 @@ IMPL_LINK_NOARG(OfaTreeOptionsDialog, FocusOut_Impl, weld::Widget&, void) } } -IMPL_LINK_NOARG(OfaTreeOptionsDialog, SearchUpdateHdl, weld::Entry&, void) +IMPL_LINK_NOARG(OfaTreeOptionsDialog, SearchUpdateHdl, weld::TextWidget&, void) { m_aUpdateDataTimer.Start(); } @@ -988,73 +987,58 @@ int OfaTreeOptionsDialog::applySearchFilter(const OUString& rSearchTerm) return xTreeLB->n_children() ? 0 : -1; } -void OfaTreeOptionsDialog::showDialog(VectorOfMatchedIds& pSearchIds) +void OfaTreeOptionsDialog::showDialog(const VectorOfMatchedIds& rPageIds) { - // - // void generalOptions(); // SID_GENERAL_OPTIONS - // void loadAndSaveOptions(); // SID_FILTER_DLG - // void languageOptions(); // SID_LANGUAGE_OPTIONS - // void writerOptions(); // SID_SW_EDITOPTIONS - // void writerWebOptions(); // SID_SW_ONLINEOPTIONS - // void calcOptions(); // SID_SC_EDITOPTIONS - // void impressOptions(); // SID_SD_EDITOPTIONS - // void drawOptions(); // SID_SD_GRAPHIC_OPTIONS - // void mathOptions(); // SID_SM_EDITOPTIONS - // void databaseOptions(); // SID_SB_STARBASEOPTIONS - // void chartOptions(); // SID_SCH_EDITOPTIONS - // void internetOptions(); // SID_INET_DLG - // - - for (auto& aEntryId : pSearchIds) + for (const auto& rEntryId : rPageIds) { - switch (aEntryId.first) + switch (rEntryId.first) { case SID_GENERAL_OPTIONS: - generalOptions(aEntryId.second); + generalOptions(rEntryId.second); break; case SID_FILTER_DLG: - loadAndSaveOptions(aEntryId.second); + loadAndSaveOptions(rEntryId.second); break; case SID_LANGUAGE_OPTIONS: - languageOptions(aEntryId.second); + languageOptions(rEntryId.second); break; case SID_SW_EDITOPTIONS: - writerOptions(aEntryId.second); + writerOptions(rEntryId.second); break; case SID_SW_ONLINEOPTIONS: - writerWebOptions(aEntryId.second); + writerWebOptions(rEntryId.second); break; case SID_SC_EDITOPTIONS: - calcOptions(aEntryId.second); + calcOptions(rEntryId.second); break; case SID_SD_EDITOPTIONS: - impressOptions(aEntryId.second); + impressOptions(rEntryId.second); break; case SID_SD_GRAPHIC_OPTIONS: - drawOptions(aEntryId.second); + drawOptions(rEntryId.second); break; case SID_SM_EDITOPTIONS: - mathOptions(aEntryId.second); + mathOptions(rEntryId.second); break; case SID_SB_STARBASEOPTIONS: - databaseOptions(aEntryId.second); + databaseOptions(rEntryId.second); break; case SID_SCH_EDITOPTIONS: - chartOptions(aEntryId.second); + chartOptions(rEntryId.second); break; case SID_INET_DLG: - internetOptions(aEntryId.second); + internetOptions(rEntryId.second); break; default: @@ -1774,13 +1758,6 @@ void OfaTreeOptionsDialog::languageOptions(const std::vector& vPageI if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) continue; - // Disable DeepL translation settings, if experimental mode is not enabled - if( RID_SVXPAGE_DEEPL_OPTIONS == nPageId ) - { - if( ! officecfg::Office::Common::Misc::ExperimentalMode::get() ) - continue; - } - if ( ( RID_SVXPAGE_JSEARCH_OPTIONS != nPageId || SvtCJKOptions::IsJapaneseFindEnabled() ) && ( RID_SVXPAGE_ASIAN_LAYOUT != nPageId || SvtCJKOptions::IsAsianTypographyEnabled() ) && ( RID_SVXPAGE_OPTIONS_CTL != nPageId || SvtCTLOptions::IsCTLFontEnabled() ) ) diff --git a/cui/source/options/treeopthelper.cxx b/cui/source/options/treeopthelper.cxx index e7f9a173ae6d..04254b702647 100644 --- a/cui/source/options/treeopthelper.cxx +++ b/cui/source/options/treeopthelper.cxx @@ -64,7 +64,6 @@ static PageIdToFileNameMap_Impl FileMap_Impl[] = { { RID_SVXPAGE_ASIAN_LAYOUT, u""_ustr }, // AsianLayout { RID_SVXPAGE_OPTIONS_CTL, u""_ustr }, // ComplexTextLayout { RID_SVXPAGE_LANGTOOL_OPTIONS, u""_ustr }, // LanguageTool Server - { RID_SVXPAGE_DEEPL_OPTIONS, u""_ustr }, // DeepL Server // Internet, SID_INET_DLG { RID_SVXPAGE_INET_PROXY, u""_ustr }, // Proxy diff --git a/cui/source/options/tsaurls.hxx b/cui/source/options/tsaurls.hxx index 437d991d87d2..91c4a19fe312 100644 --- a/cui/source/options/tsaurls.hxx +++ b/cui/source/options/tsaurls.hxx @@ -9,9 +9,10 @@ #pragma once +#include #include +#include #include -#include #include diff --git a/cui/source/options/webconninfo.cxx b/cui/source/options/webconninfo.cxx index c7d6253f9beb..a7d104d27acf 100644 --- a/cui/source/options/webconninfo.cxx +++ b/cui/source/options/webconninfo.cxx @@ -52,7 +52,8 @@ WebConnectionInfoDialog::WebConnectionInfoDialog(weld::Window* pParent) m_xPasswordsLB->set_size_request(m_xPasswordsLB->get_approximate_digit_width() * 70, m_xPasswordsLB->get_height_rows(8)); - m_xPasswordsLB->connect_column_clicked(LINK(this, WebConnectionInfoDialog, HeaderBarClickedHdl)); + m_xPasswordsLB->connect_column_header_clicked( + LINK(this, WebConnectionInfoDialog, HeaderBarClickedHdl)); FillPasswordList(); diff --git a/cui/source/options/webconninfo.hxx b/cui/source/options/webconninfo.hxx index b1c8712e08cc..dfc53f39c574 100644 --- a/cui/source/options/webconninfo.hxx +++ b/cui/source/options/webconninfo.hxx @@ -17,9 +17,10 @@ */ #pragma once +#include #include #include -#include +#include namespace svx { diff --git a/cui/source/tabpages/SvxPresetListBox.cxx b/cui/source/tabpages/SvxPresetListBox.cxx new file mode 100644 index 000000000000..d3868968c432 --- /dev/null +++ b/cui/source/tabpages/SvxPresetListBox.cxx @@ -0,0 +1,122 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +SvxPresetListBox::SvxPresetListBox(weld::IconView& rIconView) + : m_rIconView(rIconView) + , m_aIconSize(60, 64) +{ + m_rIconView.connect_command(LINK(this, SvxPresetListBox, CommandHdl)); + m_rIconView.connect_key_press(LINK(this, SvxPresetListBox, KeyPressHdl)); +} + +IMPL_LINK(SvxPresetListBox, CommandHdl, const CommandEvent&, rEvent, bool) +{ + if (rEvent.GetCommand() != CommandEventId::ContextMenu) + return false; + + Point aPos; + std::unique_ptr pItem; + if (rEvent.IsMouseEvent()) + { + aPos = rEvent.GetMousePosPixel(); + pItem = m_rIconView.get_item_at_pos(aPos); + if (!pItem) + return false; + } + else + { + pItem = m_rIconView.get_selected(); + if (!pItem) + return false; + aPos = m_rIconView.get_rect(*pItem).Center(); + } + + const int nContextMenuItemIndex = m_rIconView.get_iter_index_in_parent(*pItem); + std::unique_ptr xBuilder( + Application::CreateBuilder(&m_rIconView, u"svx/ui/presetmenu.ui"_ustr)); + std::unique_ptr xMenu(xBuilder->weld_menu(u"menu"_ustr)); + const OUString sIdent = xMenu->popup_at_rect(&m_rIconView, tools::Rectangle(aPos, Size(1, 1))); + if (sIdent == u"rename") + maRenameHdl.Call(nContextMenuItemIndex); + else if (sIdent == u"delete") + maDeleteHdl.Call(nContextMenuItemIndex); + + return true; +} + +IMPL_LINK(SvxPresetListBox, KeyPressHdl, const KeyEvent&, rKEvt, bool) +{ + switch (rKEvt.GetKeyCode().GetCode()) + { + case KEY_DELETE: + { + maDeleteHdl.Call(m_rIconView.get_selected_index()); + return true; + } + default: + return false; + } +} + +template void SvxPresetListBox::FillPresetListBoxImpl(ListType& rList) +{ + const Size aSize(GetIconSize()); + for (tools::Long nIndex = 0; nIndex < rList.Count(); nIndex++) + { + Bitmap aBitmap = rList.CreateBitmap(nIndex, aSize); + XPropertyEntry* pItem = rList.Get(nIndex); + const OUString sName = pItem->GetName(); + m_rIconView.insert(nIndex, nullptr, nullptr, &aBitmap, nullptr); + m_rIconView.set_item_accessible_name(nIndex, sName); + m_rIconView.set_item_tooltip_text(nIndex, sName); + } +} + +void SvxPresetListBox::FillPresetListBox(XGradientList& rList) +{ + FillPresetListBoxImpl(rList); +} + +void SvxPresetListBox::FillPresetListBox(XHatchList& rList) +{ + FillPresetListBoxImpl(rList); +} + +void SvxPresetListBox::FillPresetListBox(XBitmapList& rList) +{ + FillPresetListBoxImpl(rList); +} + +void SvxPresetListBox::FillPresetListBox(XPatternList& rList) +{ + FillPresetListBoxImpl(rList); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/align.cxx b/cui/source/tabpages/align.cxx index 4124eaa0213b..1806a8f55620 100644 --- a/cui/source/tabpages/align.cxx +++ b/cui/source/tabpages/align.cxx @@ -700,13 +700,14 @@ void AlignmentTabPage::UpdateEnableControls() { const sal_Int32 nHorAlign = m_xLbHorAlign->get_active_id().toInt32(); bool bHorLeft = (nHorAlign == ALIGNDLG_HORALIGN_LEFT); + bool bHorRight = (nHorAlign == ALIGNDLG_HORALIGN_RIGHT); bool bHorBlock = (nHorAlign == ALIGNDLG_HORALIGN_BLOCK); bool bHorFill = (nHorAlign == ALIGNDLG_HORALIGN_FILL); bool bHorDist = (nHorAlign == ALIGNDLG_HORALIGN_DISTRIBUTED); - // indent edit field only for left alignment - m_xFtIndent->set_sensitive( bHorLeft ); - m_xEdIndent->set_sensitive( bHorLeft ); + // indent edit field only for left or right alignment + m_xFtIndent->set_sensitive( bHorLeft || bHorRight ); + m_xEdIndent->set_sensitive( bHorLeft || bHorRight ); // stacked disabled for fill alignment m_xCbStacked->set_sensitive(!bHorFill); diff --git a/cui/source/tabpages/autocdlg.cxx b/cui/source/tabpages/autocdlg.cxx index 32f0b189e4b5..40ef948a8a94 100644 --- a/cui/source/tabpages/autocdlg.cxx +++ b/cui/source/tabpages/autocdlg.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -216,7 +217,7 @@ OfaAutocorrOptionsPage::OfaAutocorrOptionsPage(weld::Container* pPage, weld::Dia , m_sAccidentalCaps(CuiResId(RID_CUISTR_CORRECT_ACCIDENTAL_CAPS_LOCK)) , m_xCheckLB(m_xBuilder->weld_tree_view(u"checklist"_ustr)) { - m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xCheckLB->enable_toggle_buttons(); m_xCheckLB->set_size_request(-1, m_xCheckLB->get_height_rows(10)); } @@ -921,7 +922,7 @@ void OfaAutocorrReplacePage::RefillReplaceBox(bool bFromReset, } SfxViewShell* pViewShell = SfxViewShell::Current(); - if (pViewShell && pViewShell->HasSelection()) + if (pViewShell && pViewShell->HasSelection(/*MustHaveText=*/true)) { bHasSelectionText = true; const OUString sSelection( pViewShell->GetSelectionText() ); @@ -994,24 +995,16 @@ IMPL_LINK_NOARG(OfaAutocorrReplacePage, SelectHdl, weld::ItemView&, void) void OfaAutocorrReplacePage::NewEntry(const OUString& sShort, const OUString& sLong, bool bKeepSourceFormatting) { DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries; - for (size_t i = 0; i < rNewArray.size(); i++) - { - if (rNewArray[i].sShort == sShort) - { - rNewArray.erase(rNewArray.begin() + i); - break; - } - } + auto it = std::find_if(rNewArray.begin(), rNewArray.end(), + [&sShort](const DoubleString& rEntry) { return rEntry.sShort == sShort; }); + if (it != rNewArray.end()) + rNewArray.erase(it); DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries; - for (size_t i = 0; i < rDeletedArray.size(); i++) - { - if (rDeletedArray[i].sShort == sShort) - { - rDeletedArray.erase(rDeletedArray.begin() + i); - break; - } - } + auto itDeleted = std::find_if(rDeletedArray.begin(), rDeletedArray.end(), + [&sShort](const DoubleString& rEntry) { return rEntry.sShort == sShort; }); + if (itDeleted != rDeletedArray.end()) + rDeletedArray.erase(itDeleted); DoubleString aNewString(sShort, sLong); rNewArray.push_back(aNewString); @@ -1022,24 +1015,16 @@ void OfaAutocorrReplacePage::NewEntry(const OUString& sShort, const OUString& sL void OfaAutocorrReplacePage::DeleteEntry(const OUString& sShort, const OUString& sLong) { DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries; - for (size_t i = 0; i < rNewArray.size(); i++) - { - if (rNewArray[i].sShort == sShort) - { - rNewArray.erase(rNewArray.begin() + i); - break; - } - } + auto itNew = std::find_if(rNewArray.begin(), rNewArray.end(), + [&sShort](const DoubleString& rEntry) { return rEntry.sShort == sShort; }); + if (itNew != rNewArray.end()) + rNewArray.erase(itNew); DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries; - for (size_t i = 0; i < rDeletedArray.size(); i++) - { - if (rDeletedArray[i].sShort == sShort) - { - rDeletedArray.erase(rDeletedArray.begin() + i); - break; - } - } + auto itDeleted = std::find_if(rDeletedArray.begin(), rDeletedArray.end(), + [&sShort](const DoubleString& rEntry) { return rEntry.sShort == sShort; }); + if (itDeleted != rDeletedArray.end()) + rDeletedArray.erase(itDeleted); DoubleString aDeletedString(sShort, sLong); rDeletedArray.push_back(aDeletedString); @@ -1137,7 +1122,7 @@ bool OfaAutocorrReplacePage::NewDelHdl(const weld::Widget* pBtn) return true; } -IMPL_LINK(OfaAutocorrReplacePage, ModifyHdl, weld::Entry&, rEdt, void) +IMPL_LINK(OfaAutocorrReplacePage, ModifyHdl, weld::TextWidget&, rEdt, void) { std::unique_ptr xFirstSel = m_xReplaceTLB->get_selected(); bool bFirstSelIterSet = bool(xFirstSel); @@ -1555,7 +1540,7 @@ IMPL_LINK(OfaAutocorrExceptPage, SelectHdl, weld::ItemView&, rBox, void) } } -IMPL_LINK(OfaAutocorrExceptPage, ModifyHdl, weld::Entry&, rEdt, void) +IMPL_LINK(OfaAutocorrExceptPage, ModifyHdl, weld::TextWidget&, rEdt, void) { const OUString sEntry = rEdt.get_text(); bool bEntryLen = !sEntry.isEmpty(); @@ -1584,7 +1569,8 @@ enum OfaQuoteOptions ADD_NONBRK_SPACE, REPLACE_1ST, TRANSLITERATE_RTL, - REPLACE_ANGLE_QUOTES + REPLACE_ANGLE_QUOTES, + ESPERANTO_HATS, }; } @@ -1606,6 +1592,7 @@ OfaQuoteTabPage::OfaQuoteTabPage(weld::Container* pPage, weld::DialogController* , sOrdinal(CuiResId(RID_CUISTR_ORDINAL)) , sTransliterateRTL(CuiResId(RID_CUISTR_OLD_HUNGARIAN)) , sAngleQuotes(CuiResId(RID_CUISTR_ANGLE_QUOTES)) + , sEsperantoHats(CuiResId(RID_CUISTR_ESPERANTO_HATS)) , cSglStartQuote(0) , cSglEndQuote(0) , cStartQuote(0) @@ -1647,7 +1634,7 @@ OfaQuoteTabPage::OfaQuoteTabPage(weld::Container* pPage, weld::DialogController* } else { - m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xCheckLB->enable_toggle_buttons(); m_xSwCheckLB->hide(); } @@ -1682,6 +1669,7 @@ bool OfaQuoteTabPage::FillItemSet( SfxItemSet* ) pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgOrdinalNumber, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); pAutoCorrect->SetAutoCorrFlag(ACFlags::TransliterateRTL, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::EsperantoHats, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); } bool bModified = false; @@ -1712,6 +1700,12 @@ bool OfaQuoteTabPage::FillItemSet( SfxItemSet* ) pOpt->bChgAngleQuotes = bCheck; pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes, m_xSwCheckLB->get_toggle(REPLACE_ANGLE_QUOTES, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(ESPERANTO_HATS, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bEsperantoHats != bCheck; + pOpt->bEsperantoHats = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::EsperantoHats, + m_xSwCheckLB->get_toggle(ESPERANTO_HATS, CBCOL_SECOND) == TRISTATE_TRUE); } pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgQuotes, m_xDoubleTypoCB->get_active()); @@ -1773,6 +1767,7 @@ void OfaQuoteTabPage::Reset( const SfxItemSet* ) CreateEntry(*m_xSwCheckLB, sOrdinal, CBCOL_BOTH, 2); CreateEntry(*m_xSwCheckLB, sTransliterateRTL, CBCOL_BOTH, 2); CreateEntry(*m_xSwCheckLB, sAngleQuotes, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sEsperantoHats, CBCOL_BOTH, 2); m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, pOpt->bAddNonBrkSpace ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, bool(nFlags & ACFlags::AddNonBrkSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); @@ -1782,6 +1777,8 @@ void OfaQuoteTabPage::Reset( const SfxItemSet* ) m_xSwCheckLB->set_toggle(TRANSLITERATE_RTL, bool(nFlags & ACFlags::TransliterateRTL) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, pOpt->bChgAngleQuotes ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(ESPERANTO_HATS, pOpt->bEsperantoHats ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(ESPERANTO_HATS, bool(nFlags & ACFlags::EsperantoHats) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); m_xSwCheckLB->thaw(); } @@ -1805,6 +1802,9 @@ void OfaQuoteTabPage::Reset( const SfxItemSet* ) m_xCheckLB->append(); m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE); m_xCheckLB->set_text(nPos++, sAngleQuotes, 0); + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::EsperantoHats) ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xCheckLB->set_text(nPos++, sEsperantoHats, 0); m_xCheckLB->thaw(); } @@ -2203,7 +2203,7 @@ OfaSmartTagOptionsTabPage::OfaSmartTagOptionsTabPage(weld::Container* pPage, wel m_xSmartTagTypesLB->set_size_request(m_xSmartTagTypesLB->get_approximate_digit_width() * 50, m_xSmartTagTypesLB->get_height_rows(6)); - m_xSmartTagTypesLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xSmartTagTypesLB->enable_toggle_buttons(); // set the handlers: m_xMainCB->connect_toggled(LINK(this, OfaSmartTagOptionsTabPage, CheckHdl)); diff --git a/cui/source/tabpages/backgrnd.cxx b/cui/source/tabpages/backgrnd.cxx index e68da4d79c2e..0ceb7a4e66ff 100644 --- a/cui/source/tabpages/backgrnd.cxx +++ b/cui/source/tabpages/backgrnd.cxx @@ -114,13 +114,15 @@ void SvxBkgTabPage::Reset(const SfxItemSet* pItemSet) sal_uInt16 nWhich(pItemSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_CHAR_BACK_COLOR)); Color aBackColor(static_cast(pItemSet->Get(nWhich)).GetValue()); SvxBrushItem aBrushItem(SvxBrushItem(aBackColor, SID_ATTR_BRUSH_CHAR)); - setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, m_aAttrSet); + setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, m_aAttrSet, + getActiveDocumentLinkReferer()); } else { sal_uInt16 nWhich(pItemSet->GetPool()->GetWhichIDFromSlotID(m_bHighlighting ? SID_ATTR_BRUSH_CHAR : SID_ATTR_BRUSH)); SvxBrushItem aBrushItem(static_cast(pItemSet->Get(nWhich))); - setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, m_aAttrSet); + setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, m_aAttrSet, + getActiveDocumentLinkReferer()); } SvxAreaTabPage::Reset(&m_aAttrSet); } @@ -304,7 +306,8 @@ void SvxBkgTabPage::SetActiveTableDestinationBrushItem() if (SfxItemState::SET == GetItemSet().GetItemState(nWhich)) { SvxBrushItem aBrushItem(static_cast(GetItemSet().Get(nWhich))); - setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, m_aAttrSet); + setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, m_aAttrSet, + getActiveDocumentLinkReferer()); } else { diff --git a/cui/source/tabpages/bbdlg.cxx b/cui/source/tabpages/bbdlg.cxx index 141effe9c4ac..f643213ac636 100644 --- a/cui/source/tabpages/bbdlg.cxx +++ b/cui/source/tabpages/bbdlg.cxx @@ -75,9 +75,9 @@ void SvxBorderBackgroundDlg::PageCreated(const OUString& rPageId, SfxTabPage& rT // demand, but could also be directly added from the DrawModel. else if (rPageId == "area") { - SfxItemSetFixed - aNew(*GetInputSetImpl()->GetPool()); + (*GetInputSetImpl()->GetPool())); aNew.Put(*GetInputSetImpl()); diff --git a/cui/source/tabpages/border.cxx b/cui/source/tabpages/border.cxx index 6ec63376f718..70a00a28eba2 100644 --- a/cui/source/tabpages/border.cxx +++ b/cui/source/tabpages/border.cxx @@ -314,7 +314,7 @@ SvxBorderTabPage::SvxBorderTabPage(weld::Container* pPage, weld::DialogControlle [this]{ return GetDialogController()->getDialog(); })) , m_xLineWidthLB(m_xBuilder->weld_combo_box(u"linewidthlb"_ustr)) , m_xLineWidthMF(m_xBuilder->weld_metric_spin_button(u"linewidthmf"_ustr, FieldUnit::POINT)) - , m_xSpacingFrame(m_xBuilder->weld_container(u"spacing"_ustr)) + , m_xSpacingFrame(m_xBuilder->weld_container(u"padding"_ustr)) , m_xLeftFT(m_xBuilder->weld_label(u"leftft"_ustr)) , m_xLeftMF(m_xBuilder->weld_metric_spin_button(u"leftmf"_ustr, FieldUnit::MM)) , m_xRightFT(m_xBuilder->weld_label(u"rightft"_ustr)) @@ -439,40 +439,6 @@ SvxBorderTabPage::SvxBorderTabPage(weld::Container* pPage, weld::DialogControlle // set metric FieldUnit eFUnit = GetModuleFieldUnit( rCoreAttrs ); - if( mbUseMarginItem ) - { - // copied from SvxAlignmentTabPage - switch ( eFUnit ) - { - // #103396# the default value (1pt) can't be accurately represented in - // inches or pica with two decimals, so point is used instead. - case FieldUnit::PICA: - case FieldUnit::INCH: - case FieldUnit::FOOT: - case FieldUnit::MILE: - eFUnit = FieldUnit::POINT; - break; - - case FieldUnit::CM: - case FieldUnit::M: - case FieldUnit::KM: - eFUnit = FieldUnit::MM; - break; - default: ;//prevent warning - } - } - else - { - switch ( eFUnit ) - { - case FieldUnit::M: - case FieldUnit::KM: - eFUnit = FieldUnit::MM; - break; - default: ; //prevent warning - } - } - SetFieldUnit(*m_xEdShadowSize, eFUnit); sal_uInt16 nWhich = GetWhich( SID_ATTR_BORDER_INNER, false ); diff --git a/cui/source/tabpages/chardlg.cxx b/cui/source/tabpages/chardlg.cxx index fbbb21ea9514..d4b011338ab1 100644 --- a/cui/source/tabpages/chardlg.cxx +++ b/cui/source/tabpages/chardlg.cxx @@ -68,6 +68,7 @@ #include #include #include +#include using namespace ::com::sun::star; @@ -706,8 +707,24 @@ void SvxCharNamePage::Reset_Impl( const SfxItemSet& rSet, LanguageGroup eLangGrp // currently chosen font if ( bStyle && pFontItem ) { - FontMetric aFontMetric = rFontList.Get(pFontItem->GetFamilyName(), eWeight, eItalic); - pStyleBox->set_active_text(rFontList.GetStyleName(aFontMetric)); + // Show the stored subfamily, not the one re-constructed from + // weight/italic, so an extended style stays selected when the dialog + // is reopened. + if (!pFontItem->GetStyleName().isEmpty()) + { + FontMetric aFontMetric; + aFontMetric.SetStyleName(pFontItem->GetStyleName()); + aFontMetric.SetWeight(eWeight); + aFontMetric.SetItalic(eItalic); + // The face may not be enumerated (e.g. the font is not installed); + // set_active_or_entry_text still shows it in the editable entry. + pStyleBox->set_active_or_entry_text(rFontList.GetStyleName(aFontMetric)); + } + else + { + FontMetric aFontMetric = rFontList.Get(pFontItem->GetFamilyName(), eWeight, eItalic); + pStyleBox->set_active_text(rFontList.GetStyleName(aFontMetric)); + } } else if ( !m_pImpl->m_bInSearchMode || !bStyle ) { @@ -879,7 +896,17 @@ bool SvxCharNamePage::FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp if (nEntryPos >= m_pImpl->m_nExtraEntryPos) aStyleBoxText.clear(); FontMetric aInfo(rFontList.Get( aFontName, aStyleBoxText)); - SvxFontItem aFontItem( aInfo.GetFamilyTypeMaybeAskConfig(), aInfo.GetFamilyName(), aInfo.GetStyleName(), + // R/I/B/BI styles are covered by the weight/italic items; store only + // an extended style as the subfamily, using the font’s own (not our + // localized) style name. + OUString aStyleName; + if ( !aStyleBoxText.isEmpty() + && aStyleBoxText != rFontList.GetNormalStr() + && aStyleBoxText != rFontList.GetItalicStr() + && aStyleBoxText != rFontList.GetBoldStr() + && aStyleBoxText != rFontList.GetBoldItalicStr() ) + aStyleName = rFontList.GetFaceStyleName( aFontName, aStyleBoxText ); + SvxFontItem aFontItem( aInfo.GetFamilyTypeMaybeAskConfig(), aInfo.GetFamilyName(), aStyleName, aInfo.GetPitchMaybeAskConfig(), aInfo.GetCharSet(), nWhich ); pOld = GetOldItem( rSet, nSlot ); @@ -887,7 +914,8 @@ bool SvxCharNamePage::FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp { const SvxFontItem& rItem = *static_cast(pOld); - if ( rItem.GetFamilyName() == aFontItem.GetFamilyName() ) + if ( rItem.GetFamilyName() == aFontItem.GetFamilyName() + && rItem.GetStyleName() == aFontItem.GetStyleName() ) bChanged = false; } @@ -2308,7 +2336,7 @@ bool SvxCharEffectsPage::FillItemSet( SfxItemSet* rSet ) //! item-state in the 'rOldSet' will be invalid. In this case //! changing the effect style will be allowed if a style is //! selected in the listbox. - bool bAllowChg = nPos != -1 && + bool bAllowChg = nCapsPos != -1 && SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich ); const SvxCaseMapItem& rItem = *static_cast(pOld); diff --git a/cui/source/tabpages/macroass.cxx b/cui/source/tabpages/macroass.cxx index f426407f629b..1eae1c53e4ae 100644 --- a/cui/source/tabpages/macroass.cxx +++ b/cui/source/tabpages/macroass.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include using ::com::sun::star::uno::Reference; diff --git a/cui/source/tabpages/measure.cxx b/cui/source/tabpages/measure.cxx index 7ac2ef7f0433..30b9274236de 100644 --- a/cui/source/tabpages/measure.cxx +++ b/cui/source/tabpages/measure.cxx @@ -81,6 +81,7 @@ SvxMeasurePage::SvxMeasurePage(weld::Container* pPage, weld::DialogController* p , m_xMtrFldHelpline2Len(m_xBuilder->weld_metric_spin_button(u"MTR_FLD_HELPLINE2_LEN"_ustr, FieldUnit::MM)) , m_xTsbBelowRefEdge(m_xBuilder->weld_check_button(u"TSB_BELOW_REF_EDGE"_ustr)) , m_xMtrFldDecimalPlaces(m_xBuilder->weld_spin_button(u"MTR_FLD_DECIMALPLACES"_ustr)) + , m_xTsbAutoDecimalPlaces(m_xBuilder->weld_check_button(u"TSB_AUTO_DECIMAL_PLACES"_ustr)) , m_xTsbAutoPosV(m_xBuilder->weld_check_button(u"TSB_AUTOPOSV"_ustr)) , m_xTsbAutoPosH(m_xBuilder->weld_check_button(u"TSB_AUTOPOSH"_ustr)) , m_xTsbShowUnit(m_xBuilder->weld_check_button(u"TSB_SHOW_UNIT"_ustr)) @@ -124,6 +125,9 @@ SvxMeasurePage::SvxMeasurePage(weld::Container* pPage, weld::DialogController* p m_xMtrFldHelpline2Len->connect_value_changed(aLink); m_xMtrFldHelpline2Len->set_range(-10000, 10000, FieldUnit::MM); m_xMtrFldDecimalPlaces->connect_value_changed(LINK(this, SvxMeasurePage, ChangeAttrSpinHdl_Impl)); + // tdf#171746 - limit number of decimal places to prevent numeric overflow + m_xMtrFldDecimalPlaces->set_range(0, 5); + m_xTsbAutoDecimalPlaces->connect_toggled(LINK(this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); m_xTsbBelowRefEdge->connect_toggled(LINK(this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); m_xTsbParallel->connect_toggled( LINK( this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); m_xTsbShowUnit->connect_toggled(LINK(this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); @@ -208,6 +212,15 @@ void SvxMeasurePage::Reset( const SfxItemSet* rAttrs ) static_cast(pItem)->GetValue()); m_xMtrFldDecimalPlaces->save_value(); + // SdrMeasureAutoDecimalPlacesItem + if (rAttrs->GetItemState(SDRATTR_MEASUREAUTODECIMALPLACES) != SfxItemState::INVALID) + m_xTsbAutoDecimalPlaces->set_state(rAttrs->Get(SDRATTR_MEASUREAUTODECIMALPLACES).GetValue() + ? TRISTATE_TRUE + : TRISTATE_FALSE); + else + m_xTsbAutoDecimalPlaces->set_state(TRISTATE_INDET); + m_xTsbAutoDecimalPlaces->save_state(); + // SdrMeasureTextRota90Item // Attention: negate ! if( rAttrs->GetItemState( SDRATTR_MEASURETEXTROTA90 ) != SfxItemState::INVALID ) @@ -397,6 +410,13 @@ bool SvxMeasurePage::FillItemSet( SfxItemSet* rAttrs) bModified = true; } + eState = m_xTsbAutoDecimalPlaces->get_state(); + if (m_xTsbAutoDecimalPlaces->get_state_changed_from_saved()) + { + rAttrs->Put(SdrYesNoItem(SDRATTR_MEASUREAUTODECIMALPLACES, TRISTATE_TRUE == eState)); + bModified = true; + } + eState = m_xTsbParallel->get_state(); if( m_xTsbParallel->get_state_changed_from_saved() ) { @@ -568,12 +588,14 @@ IMPL_LINK( SvxMeasurePage, ClickAutoPosHdl_Impl, weld::Toggleable&, rBox, void ) default: ;//prevent warning } } - ChangeAttrHdl_Impl(&rBox); + // tdf#171747 - fix checkbox handling to ensure preview updates correctly + ChangeAttrHdl_Impl(dynamic_cast(&rBox)); } -IMPL_LINK(SvxMeasurePage, ChangeAttrClickHdl_Impl, weld::Toggleable&, r, void) +IMPL_LINK(SvxMeasurePage, ChangeAttrClickHdl_Impl, weld::Toggleable&, rBox, void) { - ChangeAttrHdl_Impl(&r); + // tdf#171747 - fix checkbox handling to ensure preview updates correctly + ChangeAttrHdl_Impl(dynamic_cast(&rBox)); } IMPL_LINK(SvxMeasurePage, ChangeAttrListBoxHdl_Impl, weld::ComboBox&, rBox, void) @@ -637,6 +659,13 @@ void SvxMeasurePage::ChangeAttrHdl_Impl( void const * p ) aAttrSet.Put( SdrMeasureDecimalPlacesItem( nValue ) ); } + if (p == m_xTsbAutoDecimalPlaces.get()) + { + TriState eState = m_xTsbAutoDecimalPlaces->get_state(); + if (eState != TRISTATE_INDET) + aAttrSet.Put(SdrYesNoItem(SDRATTR_MEASUREAUTODECIMALPLACES, TRISTATE_TRUE == eState)); + } + if (p == m_xTsbParallel.get()) { TriState eState = m_xTsbParallel->get_state(); diff --git a/cui/source/tabpages/numfmt.cxx b/cui/source/tabpages/numfmt.cxx index 9682dc66a6c9..8783d0aeffdb 100644 --- a/cui/source/tabpages/numfmt.cxx +++ b/cui/source/tabpages/numfmt.cxx @@ -1432,12 +1432,12 @@ bool SvxNumberFormatTabPage::Click_Impl(const weld::Button& rIB) #* #************************************************************************/ -IMPL_LINK(SvxNumberFormatTabPage, EditModifyHdl_Impl, weld::Entry&, rEdit, void) +IMPL_LINK(SvxNumberFormatTabPage, EditModifyHdl_Impl, weld::TextWidget&, rEdit, void) { EditHdl_Impl(&rEdit); } -void SvxNumberFormatTabPage::EditHdl_Impl(const weld::Entry* pEdFormat) +void SvxNumberFormatTabPage::EditHdl_Impl(const weld::TextWidget* pEdFormat) { sal_uInt32 nCurKey = NUMKEY_UNDEFINED; diff --git a/cui/source/tabpages/numpages.cxx b/cui/source/tabpages/numpages.cxx index 3f8becb9e2b5..7ddd3158be15 100644 --- a/cui/source/tabpages/numpages.cxx +++ b/cui/source/tabpages/numpages.cxx @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -97,9 +98,10 @@ using namespace css::container; static bool bLastRelative = false; -static SvxNumSettings_Impl* lcl_CreateNumSettingsPtr(const Sequence& rLevelProps) +static std::unique_ptr +lcl_CreateNumSettingsPtr(const Sequence& rLevelProps) { - SvxNumSettings_Impl* pNew = new SvxNumSettings_Impl; + std::unique_ptr pNew = std::make_unique(); for (auto& prop : rLevelProps) { if (prop.Name == "NumberingType") @@ -178,10 +180,7 @@ SvxSingleNumPickTabPage::SvxSingleNumPickTabPage(weld::Container* pPage, weld::D sal_Int32 nLength = std::min(aNumberings.getLength(), NUM_VALUSET_COUNT); for(sal_Int32 i = 0; i < nLength; i++) - { - SvxNumSettings_Impl* pNew = lcl_CreateNumSettingsPtr(aNumberings[i]); - aNumSettingsArr.push_back(std::unique_ptr(pNew)); - } + aNumSettingsArr.push_back(lcl_CreateNumSettingsPtr(aNumberings[i])); } catch(const Exception&) { @@ -627,8 +626,7 @@ SvxNumPickTabPage::SvxNumPickTabPage(weld::Container* pPage, weld::DialogControl if (nLocaleLevel >= 0) xLevel->getByIndex(nLocaleLevel) >>= aLevelProps; - SvxNumSettings_Impl* pNew = lcl_CreateNumSettingsPtr(aLevelProps); - rItemArr.push_back( std::unique_ptr(pNew) ); + rItemArr.push_back(lcl_CreateNumSettingsPtr(aLevelProps)); } } } @@ -1262,8 +1260,8 @@ void SvxNumOptionsTabPage::SetMetric(FieldUnit eMetric) m_xWidthMF->set_digits(1); m_xHeightMF->set_digits(1); } - m_xWidthMF->set_unit(eMetric); - m_xHeightMF->set_unit(eMetric); + SetFieldUnit(*m_xWidthMF, eMetric); + SetFieldUnit(*m_xHeightMF, eMetric); } std::unique_ptr SvxNumOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, @@ -2090,7 +2088,7 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, PopupActivateHdl_Impl, weld::Toggleable&, double(MAX_BMP_HEIGHT) / static_cast(aSize.Height()); aBitmap.Scale(nScale, nScale); } - pVD->SetOutputSizePixel(aBitmap.GetSizePixel(), false); + pVD->SetOutputSizePixel(aBitmap.GetSizePixel()); pVD->DrawBitmap(Point(), aBitmap); m_xGalleryMenu->append(sItemId, sGrfName, *pVD); } @@ -2266,7 +2264,7 @@ IMPL_LINK_NOARG(SvxNumOptionsTabPage, CharFmtHdl_Impl, weld::ComboBox&, void) SetModified(false); }; -IMPL_LINK(SvxNumOptionsTabPage, EditModifyHdl_Impl, weld::Entry&, rEdit, void) +IMPL_LINK(SvxNumOptionsTabPage, EditModifyHdl_Impl, weld::TextWidget&, rEdit, void) { EditModifyHdl_Impl(&rEdit); } @@ -2276,7 +2274,7 @@ IMPL_LINK(SvxNumOptionsTabPage, SpinModifyHdl_Impl, weld::SpinButton&, rSpinButt EditModifyHdl_Impl(&rSpinButton); } -void SvxNumOptionsTabPage::EditModifyHdl_Impl(const weld::Entry* pEdit) +void SvxNumOptionsTabPage::EditModifyHdl_Impl(const weld::TextWidget* pEdit) { bool bPrefixSuffix = (pEdit == m_xPrefixED.get())|| (pEdit == m_xSuffixED.get()); bool bStart = pEdit == m_xStartED.get(); @@ -2785,12 +2783,12 @@ void SvxNumPositionTabPage::SetMetric(FieldUnit eMetric) m_xAlignedAtMF->set_digits(1); m_xIndentAtMF->set_digits(1); } - m_xDistBorderMF->set_unit(eMetric); - m_xDistNumMF->set_unit(eMetric); - m_xIndentMF->set_unit(eMetric); - m_xListtabMF->set_unit(eMetric); - m_xAlignedAtMF->set_unit(eMetric); - m_xIndentAtMF->set_unit(eMetric); + SetFieldUnit(*m_xDistBorderMF, eMetric); + SetFieldUnit(*m_xDistNumMF, eMetric); + SetFieldUnit(*m_xIndentMF, eMetric); + SetFieldUnit(*m_xListtabMF, eMetric); + SetFieldUnit(*m_xAlignedAtMF, eMetric); + SetFieldUnit(*m_xIndentAtMF, eMetric); } IMPL_LINK_NOARG(SvxNumPositionTabPage, EditModifyHdl_Impl, weld::ComboBox&, void) diff --git a/cui/source/tabpages/page.cxx b/cui/source/tabpages/page.cxx index 6255e79c92ed..97e4d60208c4 100644 --- a/cui/source/tabpages/page.cxx +++ b/cui/source/tabpages/page.cxx @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -182,9 +181,11 @@ SvxPageDescPage::SvxPageDescPage(weld::Container* pPage, weld::DialogController* , m_xRegisterFT(m_xBuilder->weld_label(u"labelRegisterStyle"_ustr)) , m_xRegisterLB(m_xBuilder->weld_combo_box(u"comboRegisterStyle"_ustr)) , m_xGutterPositionFT(m_xBuilder->weld_label(u"labelGutterPosition"_ustr)) - , m_xGutterPositionLB(m_xBuilder->weld_combo_box(u"comboGutterPosition"_ustr)) - , m_xRtlGutterCB(m_xBuilder->weld_check_button(u"checkRtlGutter"_ustr)) + , m_xGutterPositionLeftInner(m_xBuilder->weld_radio_button(u"rbGutterLeft"_ustr)) + , m_xGutterPositionRightOuter(m_xBuilder->weld_radio_button(u"rbGutterRight"_ustr)) + , m_xGutterPositionTop(m_xBuilder->weld_radio_button(u"rbGutterTop"_ustr)) , m_xBackgroundFullSizeCB(m_xBuilder->weld_check_button(u"checkBackgroundFullSize"_ustr)) + , m_xLabelOptions(m_xBuilder->weld_label(u"lbOptions"_ustr)) // Strings stored in UI , m_xInsideLbl(m_xBuilder->weld_label(u"labelInner"_ustr)) , m_xOutsideLbl(m_xBuilder->weld_label(u"labelOuter"_ustr)) @@ -299,6 +300,10 @@ SvxPageDescPage::SvxPageDescPage(weld::Container* pPage, weld::DialogController* // Get the i18n framework numberings and add them to the listbox. SvxNumOptionsTabPageHelper::GetI18nNumbering(m_xNumberFormatBox->get_widget(), std::numeric_limits::max()); + + // Hide the “resize all pages” checkbox if the attribute isn’t used. tdf#173170 + if (!rAttr.HasItem(SID_ATTR_RESIZE_ALL_PAGES)) + m_xResizeAllPages->set_visible(false); } SvxPageDescPage::~SvxPageDescPage() @@ -314,7 +319,9 @@ void SvxPageDescPage::Init_Impl() { // adjust the handler m_xLayoutBox->connect_changed(LINK(this, SvxPageDescPage, LayoutHdl_Impl)); - m_xGutterPositionLB->connect_changed(LINK(this, SvxPageDescPage, GutterPositionHdl_Impl)); + m_xGutterPositionLeftInner->connect_toggled(LINK(this, SvxPageDescPage, GutterPositionHdl_Impl)); + m_xGutterPositionRightOuter->connect_toggled(LINK(this, SvxPageDescPage, GutterPositionHdl_Impl)); + m_xGutterPositionTop->connect_toggled(LINK(this, SvxPageDescPage, GutterPositionHdl_Impl)); m_xPaperSizeBox->connect_changed(LINK(this, SvxPageDescPage, PaperSizeSelect_Impl)); m_xPaperWidthEdit->connect_value_changed( LINK(this, SvxPageDescPage, PaperSizeModify_Impl)); @@ -342,10 +349,10 @@ void SvxPageDescPage::Reset( const SfxItemSet* rSet ) // adjust margins (right/left) if (const SvxLRSpaceItem* pLRSpace = GetItem( *rSet, SID_ATTR_LRSPACE )) { - SetMetricValue(*m_xLeftMarginEdit, pLRSpace->ResolveLeft({}), eUnit); + SetMetricValue(*m_xLeftMarginEdit, pLRSpace->ResolveLeft(), eUnit); SetMetricValue(*m_xGutterMarginEdit, pLRSpace->GetGutterMargin(), eUnit); m_aBspWin.SetLeft( - static_cast(ConvertLong_Impl(pLRSpace->ResolveLeft({}), eUnit))); + static_cast(ConvertLong_Impl(pLRSpace->ResolveLeft(), eUnit))); SetMetricValue(*m_xRightMarginEdit, pLRSpace->ResolveRight({}), eUnit); m_aBspWin.SetRight( static_cast(ConvertLong_Impl(pLRSpace->ResolveRight({}), eUnit))); @@ -373,20 +380,20 @@ void SvxPageDescPage::Reset( const SfxItemSet* rSet ) if (bGutterAtTop) { - m_xGutterPositionLB->set_active(1); + m_xGutterPositionTop->set_active(true); } else { // Left. - m_xGutterPositionLB->set_active(0); + m_xGutterPositionLeftInner->set_active(true); } it = pGragbagItem->GetGrabBag().find(u"RtlGutter"_ustr); bool bRtlGutter{}; if (it != pGragbagItem->GetGrabBag().end()) { it->second >>= bRtlGutter; - m_xRtlGutterCB->set_active(bRtlGutter); - m_xRtlGutterCB->show(); + if (bRtlGutter) + m_xGutterPositionRightOuter->set_active(true); } it = pGragbagItem->GetGrabBag().find(u"BackgroundFullSize"_ustr); bool isBackgroundFullSize{}; @@ -395,6 +402,7 @@ void SvxPageDescPage::Reset( const SfxItemSet* rSet ) it->second >>= isBackgroundFullSize; m_xBackgroundFullSizeCB->set_active(isBackgroundFullSize); m_xBackgroundFullSizeCB->show(); + m_xLabelOptions->show(); } } @@ -520,7 +528,9 @@ void SvxPageDescPage::Reset( const SfxItemSet* rSet ) m_xGutterMarginLbl->hide(); m_xGutterMarginEdit->hide(); m_xGutterPositionFT->hide(); - m_xGutterPositionLB->hide(); + m_xGutterPositionLeftInner->hide(); + m_xGutterPositionRightOuter->hide(); + m_xGutterPositionTop->hide(); break; } @@ -540,7 +550,9 @@ void SvxPageDescPage::Reset( const SfxItemSet* rSet ) m_xGutterMarginLbl->hide(); m_xGutterMarginEdit->hide(); m_xGutterPositionFT->hide(); - m_xGutterPositionLB->hide(); + m_xGutterPositionLeftInner->hide(); + m_xGutterPositionRightOuter->hide(); + m_xGutterPositionTop->hide(); break; } @@ -576,8 +588,9 @@ void SvxPageDescPage::Reset( const SfxItemSet* rSet ) m_xVertBox->save_state(); m_xHorzBox->save_state(); m_xAdaptBox->save_state(); - m_xGutterPositionLB->save_value(); - m_xRtlGutterCB->save_state(); + m_xGutterPositionLeftInner->save_state(); + m_xGutterPositionRightOuter->save_state(); + m_xGutterPositionTop->save_state(); m_xBackgroundFullSizeCB->save_state(); CheckMarginEdits( true ); @@ -671,15 +684,15 @@ bool SvxPageDescPage::FillItemSet( SfxItemSet* rSet ) // Set gutter position. const SfxGrabBagItem& rOldGrabBagItem = rOldSet.Get(SID_ATTR_CHAR_GRABBAG); std::map aGrabBagMap = rOldGrabBagItem.GetGrabBag(); - if (m_xGutterPositionLB->get_value_changed_from_saved()) + if (m_xGutterPositionTop->get_state_changed_from_saved()) { - bool bGutterAtTop = m_xGutterPositionLB->get_active() == 1; + bool bGutterAtTop = m_xGutterPositionTop->get_active(); aGrabBagMap[u"GutterAtTop"_ustr] <<= bGutterAtTop; bModified = true; } - if (m_xRtlGutterCB->get_state_changed_from_saved()) + if (m_xGutterPositionRightOuter->get_state_changed_from_saved()) { - bool const bRtlGutter(m_xRtlGutterCB->get_active()); + bool const bRtlGutter(m_xGutterPositionRightOuter->get_active()); aGrabBagMap[u"RtlGutter"_ustr] <<= bRtlGutter; bModified = true; } @@ -898,6 +911,11 @@ IMPL_LINK_NOARG(SvxPageDescPage, LayoutHdl_Impl, weld::ComboBox&, void) m_xRightMarginLbl->hide(); m_xInsideLbl->show(); m_xOutsideLbl->show(); + m_xGutterPositionLeftInner->set_label(SvxResId(RID_SVXSTR_PAGEGUTTER_INNER)); + m_xGutterPositionRightOuter->set_label(SvxResId(RID_SVXSTR_PAGEGUTTER_OUTER)); + if (m_xGutterPositionTop->get_active()) + m_xGutterPositionLeftInner->set_active(true); + m_xGutterPositionTop->set_sensitive(false); } else { @@ -905,11 +923,14 @@ IMPL_LINK_NOARG(SvxPageDescPage, LayoutHdl_Impl, weld::ComboBox&, void) m_xRightMarginLbl->show(); m_xInsideLbl->hide(); m_xOutsideLbl->hide(); + m_xGutterPositionLeftInner->set_label(SvxResId(RID_SVXSTR_PAGEGUTTER_LEFT)); + m_xGutterPositionRightOuter->set_label(SvxResId(RID_SVXSTR_PAGEGUTTER_RIGHT)); + m_xGutterPositionTop->set_sensitive(true); } UpdateExample_Impl( true ); } -IMPL_LINK_NOARG(SvxPageDescPage, GutterPositionHdl_Impl, weld::ComboBox&, void) +IMPL_LINK_NOARG(SvxPageDescPage, GutterPositionHdl_Impl, weld::Toggleable&, void) { UpdateExample_Impl(true); } @@ -1116,7 +1137,7 @@ void SvxPageDescPage::UpdateExample_Impl( bool bResetbackground ) m_aBspWin.SetSize( aSize ); // Margins - bool bGutterAtTop = m_xGutterPositionLB->get_active() == 1; + bool bGutterAtTop = m_xGutterPositionTop->get_active(); tools::Long nTop = GetCoreValue(*m_xTopMarginEdit, MapUnit::MapTwip); if (bGutterAtTop) { @@ -1169,7 +1190,8 @@ void SvxPageDescPage::ResetBackground_Impl(const SfxItemSet& rSet) const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(rTmpSet.Get(nWhich)); SfxItemSet aTempSet(SfxItemSet::makeFixedSfxItemSet(*rTmpSet.GetPool())); - setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet, + getActiveDocumentLinkReferer()); aHeaderFillAttributes = std::make_shared(aTempSet); } } @@ -1205,7 +1227,8 @@ void SvxPageDescPage::ResetBackground_Impl(const SfxItemSet& rSet) const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(rTmpSet.Get(nWhich)); SfxItemSet aTempSet(SfxItemSet::makeFixedSfxItemSet(*rTmpSet.GetPool())); - setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet, + getActiveDocumentLinkReferer()); aFooterFillAttributes = std::make_shared(aTempSet); } } @@ -1231,7 +1254,8 @@ void SvxPageDescPage::ResetBackground_Impl(const SfxItemSet& rSet) const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(*pItem); SfxItemSet aTempSet(SfxItemSet::makeFixedSfxItemSet(*rSet.GetPool())); - setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet, + getActiveDocumentLinkReferer()); aPageFillAttributes = std::make_shared(aTempSet); } } @@ -1269,7 +1293,7 @@ void SvxPageDescPage::InitHeadFoot_Impl( const SfxItemSet& rSet ) m_aBspWin.SetHdDist( nDist ); const SvxLRSpaceItem& rLR = rHeaderSet.Get( GetWhich( SID_ATTR_LRSPACE ) ); - m_aBspWin.SetHdLeft(rLR.ResolveLeft({})); + m_aBspWin.SetHdLeft(rLR.ResolveLeft()); m_aBspWin.SetHdRight(rLR.ResolveRight({})); m_aBspWin.SetHeader( true ); } @@ -1294,7 +1318,8 @@ void SvxPageDescPage::InitHeadFoot_Impl( const SfxItemSet& rSet ) const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(rHeaderSet.Get(nWhich)); SfxItemSet aTempSet(SfxItemSet::makeFixedSfxItemSet(*rHeaderSet.GetPool())); - setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet, + getActiveDocumentLinkReferer()); aHeaderFillAttributes = std::make_shared(aTempSet); } } @@ -1324,7 +1349,7 @@ void SvxPageDescPage::InitHeadFoot_Impl( const SfxItemSet& rSet ) m_aBspWin.SetFtDist( nDist ); const SvxLRSpaceItem& rLR = rFooterSet.Get( GetWhich( SID_ATTR_LRSPACE ) ); - m_aBspWin.SetFtLeft(rLR.ResolveLeft({})); + m_aBspWin.SetFtLeft(rLR.ResolveLeft()); m_aBspWin.SetFtRight(rLR.ResolveRight({})); m_aBspWin.SetFooter( true ); } @@ -1349,7 +1374,8 @@ void SvxPageDescPage::InitHeadFoot_Impl( const SfxItemSet& rSet ) const SvxBrushItem& rItem = static_cast(rFooterSet.Get(nWhich)); SfxItemSet aTempSet(SfxItemSet::makeFixedSfxItemSet(*rFooterSet.GetPool())); - setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet, + getActiveDocumentLinkReferer()); aFooterFillAttributes = std::make_shared(aTempSet); } } @@ -1673,7 +1699,10 @@ void SvxPageDescPage::PageCreated(const SfxAllItemSet& aSet) } if (pIsImpressDoc) + { m_xNumberFormatText->set_label(SvxResId(STR_SLIDE_NUMBERS)); + m_xResizeAllPages->set_label(SvxResId(STR_RESIZE_ALL_SLIDES)); + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/paragrph.cxx b/cui/source/tabpages/paragrph.cxx index 1f3d058f254e..8c4917c1a9c6 100644 --- a/cui/source/tabpages/paragrph.cxx +++ b/cui/source/tabpages/paragrph.cxx @@ -1883,6 +1883,7 @@ bool SvxExtParagraphTabPage::FillItemSet( SfxItemSet* rOutSet ) m_xExtCompoundHyphenAfterBox->get_value_changed_from_saved() || m_xMaxHyphenEdit->get_value_changed_from_saved() || m_xMinWordLength->get_value_changed_from_saved() || + m_xSliderHyphen->get_value() != nHyphenLevel || m_aHyphenZone.get_value_changed_from_saved() || m_aParagraphEndZone.get_value_changed_from_saved() || m_aColumnEndZone.get_value_changed_from_saved() || @@ -1909,6 +1910,7 @@ bool SvxExtParagraphTabPage::FillItemSet( SfxItemSet* rOutSet ) aHyphen.GetMinWordLength() = static_cast(m_xMinWordLength->get_value()); } aHyphen.GetMaxHyphens() = static_cast(m_xMaxHyphenEdit->get_value()); + aHyphen.GetLevel() = 100 - static_cast(m_xSliderHyphen->get_value()); SfxItemPool* pPool = GetItemSet().GetPool(); DBG_ASSERT( pPool, "Where is the pool?" ); @@ -2169,6 +2171,8 @@ void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet ) m_xExtCompoundHyphenAfterBox->set_value(rHyphen.GetCompoundMinTrail()); m_xMaxHyphenEdit->set_value(rHyphen.GetMaxHyphens()); m_xMinWordLength->set_value(rHyphen.GetMinWordLength()); + m_xSliderHyphen->set_value(100 - rHyphen.GetLevel()); + nHyphenLevel = 100 - rHyphen.GetLevel(); m_aHyphenZone.SetFieldUnit(eFUnit); m_aHyphenZone.SetMetricValue(rHyphen.GetTextHyphenZone(), MapUnit::MapTwip); m_aParagraphEndZone.SetFieldUnit(eFUnit); @@ -2224,6 +2228,9 @@ void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet ) m_xMaxHyphenEdit->set_sensitive(bEnable); m_xMinWordLabel->set_sensitive(bEnable); m_xMinWordLength->set_sensitive(bEnable); + m_xBetterSpacingLabel->set_sensitive(bEnable); + m_xLessHyphenLabel->set_sensitive(bEnable); + m_xSliderHyphen->set_sensitive(bEnable); m_xHyphenZoneLabel->set_sensitive(bEnable); m_aHyphenZone.set_sensitive(bEnable); m_xParagraphEndZoneLabel->set_sensitive(bEnable); @@ -2568,6 +2575,7 @@ SvxExtParagraphTabPage::SvxExtParagraphTabPage(weld::Container* pPage, weld::Dia , bPageBreak(true) , bHtmlMode(false) , nStdPos(0) + , nHyphenLevel(0) // Hyphenation , m_xHyphenBox(m_xBuilder->weld_check_button(u"checkAuto"_ustr)) , m_xHyphenNoCapsBox(m_xBuilder->weld_check_button(u"checkNoCaps"_ustr)) @@ -2584,6 +2592,9 @@ SvxExtParagraphTabPage::SvxExtParagraphTabPage(weld::Container* pPage, weld::Dia , m_xMaxHyphenEdit(m_xBuilder->weld_spin_button(u"spinMaxNum"_ustr)) , m_xMinWordLabel(m_xBuilder->weld_label(u"labelMinLen"_ustr)) , m_xMinWordLength(m_xBuilder->weld_spin_button(u"spinMinLen"_ustr)) + , m_xBetterSpacingLabel(m_xBuilder->weld_label(u"labelBetterSpacing"_ustr)) + , m_xLessHyphenLabel(m_xBuilder->weld_label(u"labelLessHyphen"_ustr)) + , m_xSliderHyphen(m_xBuilder->weld_scale(u"hyphenslider"_ustr)) , m_xHyphenZoneLabel(m_xBuilder->weld_label(u"labelHyphenZone"_ustr)) , m_aHyphenZone(m_xBuilder->weld_metric_spin_button(u"spinHyphenZone"_ustr, FieldUnit::CM)) , m_xParagraphEndZoneLabel(m_xBuilder->weld_label(u"labelParagraphEndZone"_ustr)) @@ -2679,6 +2690,9 @@ SvxExtParagraphTabPage::SvxExtParagraphTabPage(weld::Container* pPage, weld::Dia m_xMaxHyphenEdit->set_sensitive(false); m_xMinWordLabel->set_sensitive(false); m_xMinWordLength->set_sensitive(false); + m_xBetterSpacingLabel->set_sensitive(false); + m_xLessHyphenLabel->set_sensitive(false); + m_xSliderHyphen->set_sensitive(false); m_xHyphenZoneLabel->set_sensitive(false); m_aHyphenZone.set_sensitive(false); m_xParagraphEndZoneLabel->set_sensitive(false); @@ -2833,6 +2847,9 @@ void SvxExtParagraphTabPage::HyphenClickHdl() m_xMaxHyphenEdit->set_sensitive(bEnable); m_xMinWordLabel->set_sensitive(bEnable); m_xMinWordLength->set_sensitive(bEnable); + m_xBetterSpacingLabel->set_sensitive(bEnable); + m_xLessHyphenLabel->set_sensitive(bEnable); + m_xSliderHyphen->set_sensitive(bEnable); m_xHyphenZoneLabel->set_sensitive(bEnable); m_aHyphenZone.set_sensitive(bEnable); m_xAcrossText->set_sensitive(bEnable); diff --git a/cui/source/tabpages/swpossizetabpage.cxx b/cui/source/tabpages/swpossizetabpage.cxx index 33588dec67a8..accec72631ae 100644 --- a/cui/source/tabpages/swpossizetabpage.cxx +++ b/cui/source/tabpages/swpossizetabpage.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #include diff --git a/cui/source/tabpages/tabstpge.cxx b/cui/source/tabpages/tabstpge.cxx index 6037614e0885..9b44579a9217 100644 --- a/cui/source/tabpages/tabstpge.cxx +++ b/cui/source/tabpages/tabstpge.cxx @@ -333,8 +333,7 @@ void SvxTabulatorTabPage::InitTabPos_Impl( sal_uInt16 nTabPos ) { if ( (*aNewTabs)[i].GetAdjustment() != SvxTabAdjust::Default ) { - m_xTabSpin->set_value(m_xTabSpin->normalize((*aNewTabs)[i].GetTabPos() + nOffset ), eDefUnit); - m_xTabBox->append_text(m_xTabSpin->get_text()); + m_xTabBox->append_text(FormatValue((*aNewTabs)[i].GetTabPos() + nOffset)); } else { @@ -365,8 +364,7 @@ void SvxTabulatorTabPage::InitTabPos_Impl( sal_uInt16 nTabPos ) } else { // If no entry, 0 is the default value - m_xTabSpin->set_value(0, eDefUnit); - m_xTabBox->set_entry_text(m_xTabSpin->get_text()); + m_xTabBox->set_entry_text(FormatValue(0)); m_xNewBtn->set_sensitive(true); m_xDelBtn->set_sensitive(false); @@ -428,8 +426,7 @@ void SvxTabulatorTabPage::NewHdl_Impl(const weld::Button* pBtn) // Add a new one and select it // Get the value from the display ReformatHdl_Impl(*m_xTabBox); - m_xTabSpin->set_text(m_xTabBox->get_active_text()); - auto nVal = m_xTabSpin->denormalize(m_xTabSpin->get_value(eDefUnit)); + auto nVal = GetCurrentValue(); // If the pBtn == 0 && the value == 0 then do not create a tab, because we create via OK if (nVal == 0 && pBtn == nullptr) @@ -454,8 +451,7 @@ void SvxTabulatorTabPage::NewHdl_Impl(const weld::Button* pBtn) } // Make ListBox entry - m_xTabSpin->set_value(m_xTabSpin->normalize(nVal), eDefUnit); - m_xTabBox->insert_text(i, m_xTabSpin->get_text()); + m_xTabBox->insert_text(i, FormatValue(nVal)); aCurrentTab.GetTabPos() = nReal; SvxTabAdjust eAdj = SvxTabAdjust::Left; @@ -630,11 +626,21 @@ IMPL_LINK_NOARG(SvxTabulatorTabPage, SelectHdl_Impl, const weld::TreeIter&, bool return true; } -OUString SvxTabulatorTabPage::FormatTab() +OUString SvxTabulatorTabPage::FormatValue(sal_Int64 nValue) +{ + m_xTabSpin->set_value(m_xTabSpin->normalize(nValue), eDefUnit); + return m_xTabSpin->get_text(); +} + +sal_Int64 SvxTabulatorTabPage::GetCurrentValue() { m_xTabSpin->set_text(m_xTabBox->get_active_text()); - m_xTabSpin->reformat(); - return m_xTabSpin->get_text(); + return m_xTabSpin->denormalize(m_xTabSpin->get_value(eDefUnit)); +} + +OUString SvxTabulatorTabPage::FormatTab() +{ + return FormatValue(GetCurrentValue()); } IMPL_LINK_NOARG(SvxTabulatorTabPage, ReformatHdl_Impl, weld::Widget&, void) @@ -650,8 +656,7 @@ IMPL_LINK_NOARG(SvxTabulatorTabPage, ModifyHdl_Impl, weld::ComboBox&, void) aCurrentTab = (*aNewTabs)[nPos]; SetFillAndTabType_Impl(); - m_xTabSpin->set_text(m_xTabBox->get_active_text()); - aCurrentTab.GetTabPos() = m_xTabSpin->denormalize(m_xTabSpin->get_value(eDefUnit)); + aCurrentTab.GetTabPos() = GetCurrentValue(); m_xNewBtn->set_sensitive(false); m_xDelBtn->set_sensitive(true); return; diff --git a/cui/source/tabpages/tpbitmap.cxx b/cui/source/tabpages/tpbitmap.cxx index e129a453b269..85757aac849f 100644 --- a/cui/source/tabpages/tpbitmap.cxx +++ b/cui/source/tabpages/tpbitmap.cxx @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -55,6 +54,7 @@ #include #include #include +#include using namespace com::sun::star; @@ -85,7 +85,8 @@ SvxBitmapTabPage::SvxBitmapTabPage(weld::Container* pPage, weld::DialogControlle , m_aXFillAttr(rInAttrs.GetPool()) , m_rXFSet(m_aXFillAttr.GetItemSet()) , mpView(nullptr) - , m_xBitmapLB(new SvxPresetListBoxValueSet(m_xBuilder->weld_scrolled_window(u"imagewin"_ustr, true))) + , m_xBitmapsPresets(m_xBuilder->weld_icon_view(u"images"_ustr)) + , m_xBitmapLB(new SvxPresetListBox(*m_xBitmapsPresets)) , m_xBitmapStyleLB(m_xBuilder->weld_combo_box(u"imagestyle"_ustr)) , m_xSizeBox(m_xBuilder->weld_container(u"sizebox"_ustr)) , m_xTsbScale(m_xBuilder->weld_check_button(u"scaletsb"_ustr)) @@ -101,17 +102,15 @@ SvxBitmapTabPage::SvxBitmapTabPage(weld::Container* pPage, weld::DialogControlle , m_xTileOffset(m_xBuilder->weld_metric_spin_button(u"tileoffmtr"_ustr, FieldUnit::PERCENT)) , m_xBtnImport(m_xBuilder->weld_button(u"BTN_IMPORT"_ustr)) , m_xCtlBitmapPreview(new weld::CustomWeld(*m_xBuilder, u"CTL_IMAGE_PREVIEW"_ustr, m_aCtlBitmapPreview)) - , m_xBitmapLBWin(new weld::CustomWeld(*m_xBuilder, u"IMAGE"_ustr, *m_xBitmapLB)) { // setting the output device m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_BITMAP) ); m_rXFSet.Put( XFillBitmapItem(OUString(), Graphic()) ); m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); - m_xBitmapLB->SetSelectHdl( LINK(this, SvxBitmapTabPage, ModifyBitmapHdl) ); + m_xBitmapsPresets->connect_item_activated(LINK(this, SvxBitmapTabPage, ModifyBitmapHdl)); m_xBitmapLB->SetRenameHdl( LINK(this, SvxBitmapTabPage, ClickRenameHdl) ); m_xBitmapLB->SetDeleteHdl( LINK(this, SvxBitmapTabPage, ClickDeleteHdl) ); - m_xBitmapLB->SetDialog(this); m_xBitmapStyleLB->connect_changed( LINK(this, SvxBitmapTabPage, ModifyBitmapStyleHdl) ); Link aLink1( LINK(this, SvxBitmapTabPage, ModifyBitmapSizeHdl) ); m_xBitmapWidth->connect_value_changed( aLink1 ); @@ -128,7 +127,6 @@ SvxBitmapTabPage::SvxBitmapTabPage(weld::Container* pPage, weld::DialogControlle // Calculate size of display boxes Size aSize = getDrawPreviewOptimalSize(m_aCtlBitmapPreview.GetDrawingArea()->get_ref_device()); - m_xBitmapLB->set_size_request(aSize.Width(), aSize.Height()); m_xCtlBitmapPreview->set_size_request(aSize.Width(), aSize.Height()); SfxItemPool* pPool = m_rXFSet.GetPool(); @@ -137,8 +135,6 @@ SvxBitmapTabPage::SvxBitmapTabPage(weld::Container* pPage, weld::DialogControlle SetFieldUnit( *m_xBitmapWidth, meFieldUnit, true ); SetFieldUnit( *m_xBitmapHeight, meFieldUnit, true ); - m_xBitmapLB->SetStyle(WB_FLATVALUESET | WB_NO_DIRECTSELECT | WB_TABSTOP); - SfxViewShell* pViewShell = SfxViewShell::Current(); if( pViewShell ) mpView = pViewShell->GetDrawView(); @@ -147,7 +143,6 @@ SvxBitmapTabPage::SvxBitmapTabPage(weld::Container* pPage, weld::DialogControlle SvxBitmapTabPage::~SvxBitmapTabPage() { - m_xBitmapLBWin.reset(); m_xBitmapLB.reset(); m_xCtlBitmapPreview.reset(); @@ -191,8 +186,7 @@ void SvxBitmapTabPage::ActivatePage( const SfxItemSet& rSet ) const_cast(rSet).Put( XFillBmpSizeYItem( GetCoreValue( *m_xBitmapHeight, mePoolUnit ) ) ); } - sal_uInt16 nId = m_xBitmapLB->GetItemId( static_cast( nPos ) ); - m_xBitmapLB->SelectItem( nId ); + m_xBitmapsPresets->select(nPos); } DeactivateRC SvxBitmapTabPage::DeactivatePage( SfxItemSet* _pSet ) @@ -207,11 +201,11 @@ DeactivateRC SvxBitmapTabPage::DeactivatePage( SfxItemSet* _pSet ) bool SvxBitmapTabPage::FillItemSet( SfxItemSet* rAttrs ) { rAttrs->Put(XFillStyleItem(drawing::FillStyle_BITMAP)); - size_t nPos = m_xBitmapLB->GetSelectItemPos(); - if(VALUESET_ITEM_NOTFOUND != nPos) + const int nPos = m_xBitmapsPresets->get_selected_index(); + if (nPos >= 0) { const XBitmapEntry* pXBitmapEntry = m_pBitmapList->GetBitmap(nPos); - const OUString aString(m_xBitmapLB->GetItemText( m_xBitmapLB->GetSelectedItemId() )); + const OUString aString(m_xBitmapsPresets->get_item_tooltip_text(nPos)); rAttrs->Put(XFillBitmapItem(aString, pXBitmapEntry->GetGraphicObject())); } @@ -322,7 +316,8 @@ void SvxBitmapTabPage::Reset( const SfxItemSet* rAttrs ) Bitmap aBmp(pGraphicObject->GetGraphic().GetBitmap()); Size aTempBitmapSize = aBmp.GetSizePixel(); - rBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aTempBitmapSize, MapMode(MapUnit::Map100thMM)); + m_aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aTempBitmapSize, + MapMode(MapUnit::Map100thMM)); CalculateBitmapPresetSize(); bool bTiled = false; bool bStretched = false; @@ -356,7 +351,7 @@ void SvxBitmapTabPage::Reset( const SfxItemSet* rAttrs ) { nWidth = static_cast( rAttrs->Get( XATTR_FILLBMP_SIZEX ) ).GetValue(); if(nWidth == 0) - nWidth = rBitmapSize.Width(); + nWidth = m_aBitmapSize.Width(); else if(nWidth < 0) { m_bLogicalSize = true; @@ -369,7 +364,7 @@ void SvxBitmapTabPage::Reset( const SfxItemSet* rAttrs ) { nHeight = rAttrs->Get( XATTR_FILLBMP_SIZEY ).GetValue(); if(nHeight == 0) - nHeight = rBitmapSize.Height(); + nHeight = m_aBitmapSize.Height(); else if(nHeight < 0) { m_bLogicalSize = true; @@ -380,8 +375,7 @@ void SvxBitmapTabPage::Reset( const SfxItemSet* rAttrs ) m_xTsbScale->set_state(eRelative); ClickScaleHdl(*m_xTsbScale); - - if(!rBitmapSize.IsEmpty()) + if (!m_aBitmapSize.IsEmpty()) { if (eRelative == TRISTATE_TRUE) { @@ -437,7 +431,10 @@ void SvxBitmapTabPage::Reset( const SfxItemSet* rAttrs ) } } - ClickBitmapHdl_Impl(); + m_xBitmapsPresets->set_sensitive(true); + m_xCtlBitmapPreview->set_sensitive(true); + + UpdateBitmap(); } std::unique_ptr SvxBitmapTabPage::Create(weld::Container* pPage, @@ -447,79 +444,45 @@ std::unique_ptr SvxBitmapTabPage::Create(weld::Container* pPag return std::make_unique(pPage, pController, rAttrs); } -void SvxBitmapTabPage::ClickBitmapHdl_Impl() -{ - m_xBitmapLBWin->set_sensitive(true); - m_xCtlBitmapPreview->set_sensitive(true); - - ModifyBitmapHdl(m_xBitmapLB.get()); -} - -void SvxBitmapTabPage::DeleteBitmapHdl_Impl(const sal_uInt16 nId) -{ - const size_t nPos = m_xBitmapLB->GetItemPos(nId); - if( nPos == VALUESET_ITEM_NOTFOUND ) - return; - - std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), u"cui/ui/querydeletebitmapdialog.ui"_ustr)); - std::unique_ptr xQueryBox(xBuilder->weld_message_dialog(u"AskDelBitmapDialog"_ustr)); - - if (xQueryBox->run() != RET_YES) - return; - - sal_uInt16 nNextId = m_xBitmapLB->GetSelectedItemId(); - const bool bDeletingSelectedItem(nId == nNextId); - if (bDeletingSelectedItem) - { - nNextId = m_xBitmapLB->GetItemId(nPos + 1); - if (!nNextId) - nNextId = m_xBitmapLB->GetItemId(nPos - 1); - } - - m_pBitmapList->Remove( static_cast(nPos) ); - m_xBitmapLB->RemoveItem( nId ); - - if (bDeletingSelectedItem) - { - m_xBitmapLB->SelectItem(nNextId); - m_aCtlBitmapPreview.Invalidate(); - } - ModifyBitmapHdl(m_xBitmapLB.get()); - m_nBitmapListState |= ChangeType::MODIFIED; -} - void SvxBitmapTabPage::CalculateBitmapPresetSize() { - if(rBitmapSize.IsEmpty()) + if (m_aBitmapSize.IsEmpty()) return; tools::Long nObjectWidth = static_cast(m_fObjectWidth); tools::Long nObjectHeight = static_cast(m_fObjectHeight); - if(std::abs(rBitmapSize.Width() - nObjectWidth) < std::abs(rBitmapSize.Height() - nObjectHeight)) + if (std::abs(m_aBitmapSize.Width() - nObjectWidth) + < std::abs(m_aBitmapSize.Height() - nObjectHeight)) { - rFilledSize.setWidth( nObjectWidth ); - rFilledSize.setHeight( rBitmapSize.Height()*nObjectWidth/rBitmapSize.Width() ); - rZoomedSize.setWidth( rBitmapSize.Width()*nObjectHeight/rBitmapSize.Height() ); - rZoomedSize.setHeight( nObjectHeight ); + m_aFilledSize.setWidth(nObjectWidth); + m_aFilledSize.setHeight(m_aBitmapSize.Height() * nObjectWidth / m_aBitmapSize.Width()); + m_aZoomedSize.setWidth(m_aBitmapSize.Width() * nObjectHeight / m_aBitmapSize.Height()); + m_aZoomedSize.setHeight(nObjectHeight); } else { - rFilledSize.setWidth( rBitmapSize.Width()*nObjectHeight/rBitmapSize.Height() ); - rFilledSize.setHeight( nObjectHeight ); - rZoomedSize.setWidth( nObjectWidth ); - rZoomedSize.setHeight( rBitmapSize.Height()*nObjectWidth/rBitmapSize.Width() ); + m_aFilledSize.setWidth(m_aBitmapSize.Width() * nObjectHeight / m_aBitmapSize.Height()); + m_aFilledSize.setHeight(nObjectHeight); + m_aZoomedSize.setWidth(nObjectWidth); + m_aZoomedSize.setHeight(m_aBitmapSize.Height() * nObjectWidth / m_aBitmapSize.Width()); } } -IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapHdl, ValueSet*, void) +IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapHdl, const weld::TreeIter&, bool) +{ + UpdateBitmap(); + return true; +} + +void SvxBitmapTabPage::UpdateBitmap() { std::unique_ptr pGraphicObject; - size_t nPos = m_xBitmapLB->GetSelectItemPos(); + const int nPos = m_xBitmapsPresets->get_selected_index(); - if( nPos != VALUESET_ITEM_NOTFOUND ) + if (nPos >= 0) { - pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap( static_cast(nPos) )->GetGraphicObject())); + pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap(nPos)->GetGraphicObject())); } else { @@ -534,15 +497,10 @@ IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapHdl, ValueSet*, void) } } - if(!pGraphicObject) + if (!pGraphicObject && m_xBitmapsPresets->n_children() > 0) { - sal_uInt16 nId = m_xBitmapLB->GetItemId(0); - m_xBitmapLB->SelectItem(nId); - - if(0 != nId) - { - pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap(0)->GetGraphicObject())); - } + m_xBitmapsPresets->select(0); + pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap(0)->GetGraphicObject())); } } @@ -553,8 +511,8 @@ IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapHdl, ValueSet*, void) const double fUIScale = mpView ? mpView->GetModel().GetUIScale() : 1.0; Size aBitmapSize100mm = o3tl::convert(aTempBitmapSize, o3tl::Length::pt, o3tl::Length::mm100); - rBitmapSize.setWidth(aBitmapSize100mm.Width() / fUIScale); - rBitmapSize.setHeight(aBitmapSize100mm.Height() / fUIScale); + m_aBitmapSize.setWidth(aBitmapSize100mm.Width() / fUIScale); + m_aBitmapSize.setHeight(aBitmapSize100mm.Height() / fUIScale); CalculateBitmapPresetSize(); ModifyBitmapStyleHdl( *m_xBitmapStyleLB ); ModifyBitmapPositionHdl( *m_xPositionLB ); @@ -568,17 +526,13 @@ IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapHdl, ValueSet*, void) } else { - SAL_WARN("cui.tabpages", "SvxBitmapTabPage::ModifyBitmapHdl(): null pGraphicObject"); + SAL_WARN("cui.tabpages", "SvxBitmapTabPage::UpdateBitmap(): null pGraphicObject"); } - } -IMPL_LINK_NOARG(SvxBitmapTabPage, ClickRenameHdl, SvxPresetListBox*, void) +IMPL_LINK(SvxBitmapTabPage, ClickRenameHdl, int, nPos, void) { - const sal_uInt16 nId = m_xBitmapLB->GetContextMenuItemId(); - const size_t nPos = m_xBitmapLB->GetItemPos(nId); - - if( nPos == VALUESET_ITEM_NOTFOUND ) + if (nPos < 0) return; OUString aDesc( CuiResId( RID_CUISTR_DESC_NEW_BITMAP ) ); @@ -598,7 +552,8 @@ IMPL_LINK_NOARG(SvxBitmapTabPage, ClickRenameHdl, SvxPresetListBox*, void) bLoop = false; m_pBitmapList->GetBitmap(nPos)->SetName(aName); - m_xBitmapLB->SetItemText(nId, aName); + m_xBitmapsPresets->set_item_accessible_name(nPos, aName); + m_xBitmapsPresets->set_item_tooltip_text(nPos, aName); m_nBitmapListState |= ChangeType::MODIFIED; } @@ -611,31 +566,38 @@ IMPL_LINK_NOARG(SvxBitmapTabPage, ClickRenameHdl, SvxPresetListBox*, void) } } -IMPL_LINK_NOARG(SvxBitmapTabPage, ClickDeleteHdl, SvxPresetListBox*, void) +IMPL_LINK(SvxBitmapTabPage, ClickDeleteHdl, int, nPos, void) { - DeleteBitmapHdl_Impl(m_xBitmapLB->GetContextMenuItemId()); -} + if (nPos < 0) + return; + std::unique_ptr xBuilder( + Application::CreateBuilder(GetFrameWeld(), u"cui/ui/querydeletebitmapdialog.ui"_ustr)); + std::unique_ptr xQueryBox( + xBuilder->weld_message_dialog(u"AskDelBitmapDialog"_ustr)); -SvxBitmapTabPage::SvxPresetListBoxValueSet::SvxPresetListBoxValueSet(std::unique_ptr pWindow) - : SvxPresetListBox(std::move(pWindow)) - , m_pSvxBitmapTabPage(nullptr) -{ -} + if (xQueryBox->run() != RET_YES) + return; -bool SvxBitmapTabPage::SvxPresetListBoxValueSet::KeyInput(const KeyEvent& rKEvt) -{ - switch (rKEvt.GetKeyCode().GetCode()) + int nNextPos = m_xBitmapsPresets->get_selected_index(); + const bool bDeletingSelectedItem(nPos == nNextPos); + if (bDeletingSelectedItem) { - case KEY_DELETE: - { - m_pSvxBitmapTabPage->DeleteBitmapHdl_Impl(GetSelectedItemId()); - return true; - } - break; - default: - return SvxPresetListBox::KeyInput(rKEvt); + nNextPos += 1; + if (nNextPos >= m_xBitmapsPresets->n_children()) + nNextPos = nPos - 1; } + + m_pBitmapList->Remove(static_cast(nPos)); + m_xBitmapsPresets->remove(nPos); + + if (bDeletingSelectedItem) + { + m_xBitmapsPresets->select(nNextPos); + m_aCtlBitmapPreview.Invalidate(); + } + UpdateBitmap(); + m_nBitmapListState |= ChangeType::MODIFIED; } IMPL_LINK_NOARG( SvxBitmapTabPage, ModifyBitmapSizeHdl, weld::MetricSpinButton&, void ) @@ -872,14 +834,15 @@ tools::Long SvxBitmapTabPage::AddBitmap(const GraphicObject& rGraphicObject, con xBitmapEntry->SetSavingAllowed(false); m_pBitmapList->Insert(std::move(xBitmapEntry), nLastPos); - Bitmap aBitmap = m_pBitmapList->GetBitmapForPreview(nLastPos, m_xBitmapLB->GetIconSize()); + Bitmap aBitmap = m_pBitmapList->CreateBitmap(nLastPos, m_xBitmapLB->GetIconSize()); - const sal_uInt16 nHighestId = m_xBitmapLB->GetItemId(nLastPos - 1); - m_xBitmapLB->InsertItem(nHighestId + 1, Image(aBitmap), rName); - m_xBitmapLB->SelectItem(nHighestId + 1); + m_xBitmapsPresets->insert(nLastPos, nullptr, nullptr, &aBitmap, nullptr); + m_xBitmapsPresets->set_item_accessible_name(nLastPos, rName); + m_xBitmapsPresets->set_item_tooltip_text(nLastPos, rName); + m_xBitmapsPresets->select(nLastPos); m_nBitmapListState |= ChangeType::MODIFIED; - ModifyBitmapHdl(m_xBitmapLB.get()); + UpdateBitmap(); // inform sidebar, etc. that the list of images has changed. SfxViewFrame* pViewFrame = SfxViewFrame::Current(); diff --git a/cui/source/tabpages/tpcolor.cxx b/cui/source/tabpages/tpcolor.cxx index 9d66b66986de..bfe1892354d1 100644 --- a/cui/source/tabpages/tpcolor.cxx +++ b/cui/source/tabpages/tpcolor.cxx @@ -22,9 +22,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -54,8 +54,8 @@ SvxColorTabPage::SvxColorTabPage(weld::Container* pPage, weld::DialogController* , m_aXFillAttr( rInAttrs.GetPool() ) , m_rXFSet( m_aXFillAttr.GetItemSet() ) , m_eCM( ColorModel::RGB ) - , m_xValSetColorList(new SvxColorValueSet(m_xBuilder->weld_scrolled_window(u"colorsetwin"_ustr, true))) - , m_xValSetRecentList(new SvxColorValueSet(nullptr)) + , m_aColorIconView(m_xBuilder->weld_icon_view(u"coloriconview"_ustr)) + , m_aRecentIconView(m_xBuilder->weld_icon_view(u"recentcoloriconview"_ustr)) , m_xSelectPalette(m_xBuilder->weld_combo_box(u"paletteselector"_ustr)) , m_xRbRGB(m_xBuilder->weld_radio_button(u"RGB"_ustr)) , m_xRbCMYK(m_xBuilder->weld_radio_button(u"CMYK"_ustr)) @@ -85,12 +85,9 @@ SvxColorTabPage::SvxColorTabPage(weld::Container* pPage, weld::DialogController* , m_xMoreColors(m_xBuilder->weld_button(u"btnMoreColors"_ustr)) , m_xCtlPreviewOld(new weld::CustomWeld(*m_xBuilder, u"oldpreview"_ustr, m_aCtlPreviewOld)) , m_xCtlPreviewNew(new weld::CustomWeld(*m_xBuilder, u"newpreview"_ustr, m_aCtlPreviewNew)) - , m_xValSetColorListWin(new weld::CustomWeld(*m_xBuilder, u"colorset"_ustr, *m_xValSetColorList)) - , m_xValSetRecentListWin(new weld::CustomWeld(*m_xBuilder, u"recentcolorset"_ustr, *m_xValSetRecentList)) { Size aSize(m_xBtnWorkOn->get_approximate_digit_width() * 25, m_xBtnWorkOn->get_text_height() * 10); - m_xValSetColorList->set_size_request(aSize.Width(), aSize.Height()); aSize = Size(m_xBtnWorkOn->get_approximate_digit_width() * 8, m_xBtnWorkOn->get_text_height() * 3); m_aCtlPreviewOld.set_size_request(aSize.Width(), aSize.Height()); @@ -106,9 +103,8 @@ SvxColorTabPage::SvxColorTabPage(weld::Container* pPage, weld::DialogController* // set handler m_xSelectPalette->connect_changed(LINK(this, SvxColorTabPage, SelectPaletteLBHdl)); - Link aValSelectLink = LINK(this, SvxColorTabPage, SelectValSetHdl_Impl); - m_xValSetColorList->SetSelectHdl(aValSelectLink); - m_xValSetRecentList->SetSelectHdl(aValSelectLink); + m_aColorIconView.setColorActivatedHdl(LINK(this, SvxColorTabPage, ActivatePaletteColorHdl)); + m_aRecentIconView.setColorActivatedHdl(LINK(this, SvxColorTabPage, ActivateRecentColorHdl)); Link aSpinLink = LINK(this, SvxColorTabPage, SpinValueHdl_Impl); m_xRcustom->connect_value_changed(aSpinLink); @@ -142,18 +138,7 @@ SvxColorTabPage::SvxColorTabPage(weld::Container* pPage, weld::DialogController* m_xRGBpreset->set_sensitive(false); m_xCMYKpreset->set_sensitive(false); - // ValueSet - m_xValSetColorList->SetStyle(m_xValSetColorList->GetStyle() | - WB_FLATVALUESET | WB_ITEMBORDER | WB_NO_DIRECTSELECT | WB_TABSTOP); - m_xValSetColorList->Show(); - - m_xValSetRecentList->SetStyle(m_xValSetRecentList->GetStyle() | - WB_FLATVALUESET | WB_ITEMBORDER | WB_NO_DIRECTSELECT | WB_TABSTOP); - m_xValSetRecentList->Show(); - - maPaletteManager.ReloadRecentColorSet(*m_xValSetRecentList); - aSize = m_xValSetRecentList->layoutAllVisible(maPaletteManager.GetRecentColorCount()); - m_xValSetRecentList->set_size_request(aSize.Width(), aSize.Height()); + maPaletteManager.ReloadRecentColorSet(m_aRecentIconView); // it is not possible to install color palette extensions in Online or mobile apps if(comphelper::LibreOfficeKit::isActive()) @@ -162,21 +147,7 @@ SvxColorTabPage::SvxColorTabPage(weld::Container* pPage, weld::DialogController* } } -SvxColorTabPage::~SvxColorTabPage() -{ - m_xValSetRecentListWin.reset(); - m_xValSetRecentList.reset(); - m_xValSetColorListWin.reset(); - m_xValSetColorList.reset(); -} - -void SvxColorTabPage::ImpColorCountChanged() -{ - if (!m_pColorList.is()) - return; - m_xValSetColorList->SetColCount(SvxColorValueSet::getColumnCount()); - m_xValSetRecentList->SetColCount(SvxColorValueSet::getColumnCount()); -} +SvxColorTabPage::~SvxColorTabPage() {} void SvxColorTabPage::FillPaletteLB() { @@ -197,10 +168,7 @@ void SvxColorTabPage::FillPaletteLB() void SvxColorTabPage::Construct() { if (m_pColorList.is()) - { FillPaletteLB(); - ImpColorCountChanged(); - } } void SvxColorTabPage::ActivatePage( const SfxItemSet& ) @@ -213,7 +181,11 @@ void SvxColorTabPage::ActivatePage( const SfxItemSet& ) m_aCtlPreviewOld.SetAttributes(m_aXFillAttr.GetItemSet()); m_aCtlPreviewOld.Invalidate(); - SelectValSetHdl_Impl(m_xValSetColorList.get()); + const int nSelectedIndex = m_aColorIconView.get_selected_index(); + if (nSelectedIndex < 0) + return; + + ActivatePaletteColorHdl(m_aColorIconView.getColor(nSelectedIndex)); } DeactivateRC SvxColorTabPage::DeactivatePage( SfxItemSet* _pSet ) @@ -226,12 +198,12 @@ DeactivateRC SvxColorTabPage::DeactivatePage( SfxItemSet* _pSet ) bool SvxColorTabPage::FillItemSet( SfxItemSet* rSet ) { - Color aColor = m_xValSetColorList->GetItemColor( m_xValSetColorList->GetSelectedItemId() ); + Color aColor = m_aColorIconView.getColor(m_aColorIconView.get_selected_index()); OUString sColorName; if (m_aCurrentColor.m_aColor == aColor) - sColorName = m_xValSetColorList->GetItemText( m_xValSetColorList->GetSelectedItemId() ); + sColorName = m_aColorIconView.getColorName(m_aColorIconView.get_selected_index()); else - sColorName = "#" + m_aCurrentColor.m_aColor.AsRGBHexString().toAsciiUpperCase(); + sColorName = "#" + m_aCurrentColor.m_aColor.AsRGBHexString().toAsciiUpperCase(); maPaletteManager.AddRecentColor(m_aCurrentColor.m_aColor, sColorName); XFillColorItem aColorItem(sColorName, m_aCurrentColor.m_aColor); @@ -241,12 +213,6 @@ bool SvxColorTabPage::FillItemSet( SfxItemSet* rSet ) return true; } -void SvxColorTabPage::UpdateModified() -{ - bool bEnable = m_pColorList.is() && m_pColorList->Count(); - m_xBtnWorkOn->set_sensitive(bEnable); -} - void SvxColorTabPage::Reset( const SfxItemSet* rSet ) { SfxItemState nState = rSet->GetItemState( XATTR_FILLCOLOR ); @@ -269,8 +235,6 @@ void SvxColorTabPage::Reset( const SfxItemSet* rSet ) NamedColor aColor; aColor.m_aColor = aNewColor; ChangeColor(aColor); - - UpdateModified(); } std::unique_ptr SvxColorTabPage::Create(weld::Container* pPage, @@ -371,15 +335,12 @@ IMPL_LINK_NOARG(SvxColorTabPage, ClickAddHdl_Impl, weld::Button&, void) officecfg::Office::Common::UserColors::CustomColor::set(aCustomColorList, batch); officecfg::Office::Common::UserColors::CustomColorName::set(aCustomColorNameList, batch); batch->commit(); - sal_uInt16 nId = m_xValSetColorList->GetItemId(nSize - 1); - m_xValSetColorList->InsertItem( nId + 1 , m_aCurrentColor.m_aColor, aName ); - m_xValSetColorList->SelectItem( nId + 1 ); + const int nCount = m_aColorIconView.getItemCount(); + m_aColorIconView.insert(nCount, m_aCurrentColor.m_aColor, aName); + m_aColorIconView.select(nCount); m_xBtnDelete->set_sensitive(false); m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR2) ); - ImpColorCountChanged(); } - - UpdateModified(); } IMPL_LINK_NOARG(SvxColorTabPage, ClickWorkOnHdl_Impl, weld::Button&, void) @@ -403,9 +364,8 @@ IMPL_LINK_NOARG(SvxColorTabPage, ClickWorkOnHdl_Impl, weld::Button&, void) IMPL_LINK_NOARG(SvxColorTabPage, ClickDeleteHdl_Impl, weld::Button&, void) { - sal_uInt16 nId = m_xValSetColorList->GetSelectedItemId(); - size_t nPos = m_xValSetColorList->GetSelectItemPos(); - if (m_xSelectPalette->get_active() != 0 || nPos == VALUESET_ITEM_NOTFOUND) + const int nPos = m_aColorIconView.get_selected_index(); + if (m_xSelectPalette->get_active() != 0 || nPos < 0) return; std::shared_ptr batch(comphelper::ConfigurationChanges::create()); @@ -414,7 +374,7 @@ IMPL_LINK_NOARG(SvxColorTabPage, ClickDeleteHdl_Impl, weld::Button&, void) css::uno::Sequence< OUString > aCustomColorNameList(officecfg::Office::Common::UserColors::CustomColorName::get()); auto aCustomColorNameListRange = asNonConstRange(aCustomColorNameList); sal_Int32 nSize = aCustomColorList.getLength() - 1; - for(sal_Int32 nIndex = static_cast(nPos);nIndex < nSize;nIndex++) + for (sal_Int32 nIndex = nPos; nIndex < nSize; nIndex++) { aCustomColorListRange[nIndex] = aCustomColorList[nIndex+1]; aCustomColorNameListRange[nIndex] = aCustomColorNameList[nIndex+1]; @@ -424,12 +384,11 @@ IMPL_LINK_NOARG(SvxColorTabPage, ClickDeleteHdl_Impl, weld::Button&, void) officecfg::Office::Common::UserColors::CustomColor::set(aCustomColorList, batch); officecfg::Office::Common::UserColors::CustomColorName::set(aCustomColorNameList, batch); batch->commit(); - m_xValSetColorList->RemoveItem(nId); - if (m_xValSetColorList->GetItemCount() != 0) + m_aColorIconView.remove(nPos); + if (m_aColorIconView.getItemCount() > 0) { - nId = m_xValSetColorList->GetItemId(0); - m_xValSetColorList->SelectItem(nId); - SelectValSetHdl_Impl(m_xValSetColorList.get()); + m_aColorIconView.select(0); + ActivatePaletteColorHdl(m_aColorIconView.getColor(0)); } else { @@ -440,10 +399,10 @@ IMPL_LINK_NOARG(SvxColorTabPage, ClickDeleteHdl_Impl, weld::Button&, void) IMPL_LINK_NOARG(SvxColorTabPage, SelectPaletteLBHdl, weld::ComboBox&, void) { - m_xValSetColorList->Clear(); + m_aColorIconView.clear(); sal_Int32 nPos = m_xSelectPalette->get_active(); maPaletteManager.SetPalette( nPos ); - maPaletteManager.ReloadColorSet(*m_xValSetColorList); + maPaletteManager.ReloadColorSet(m_aColorIconView); if(nPos != maPaletteManager.GetPaletteCount() - 1 && nPos != 0) { @@ -473,8 +432,6 @@ IMPL_LINK_NOARG(SvxColorTabPage, SelectPaletteLBHdl, weld::ComboBox&, void) m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR1) ); } - m_xValSetColorList->Resize(); - // select the 'Active' color in the m_xValSetColorList if it has it if (const XFillColorItem* pFillColorItem = m_rOutAttrs.GetItemIfSet(GetWhich(XATTR_FILLCOLOR))) { @@ -491,13 +448,12 @@ IMPL_LINK_NOARG(SvxColorTabPage, SelectPaletteLBHdl, weld::ComboBox&, void) /* document colors palette */ nPalettePos == maPaletteManager.GetPaletteCount() - 1 || /* custom palette */ nPalettePos == 0) { - for (size_t nItemPos = 0, nItemCount = m_xValSetColorList->GetItemCount(); + for (size_t nItemPos = 0, nItemCount = m_aColorIconView.getItemCount(); nItemPos < nItemCount; nItemPos++) { - auto nItemId = m_xValSetColorList->GetItemId(nItemPos); - if (m_xValSetColorList->GetItemColor(nItemId) == aColor) + if (m_aColorIconView.getColor(nItemPos) == aColor) { - m_xValSetColorList->SelectItem(nItemId); + m_aColorIconView.select(nItemPos); break; } } @@ -510,28 +466,31 @@ IMPL_LINK_NOARG(SvxColorTabPage, SelectPaletteLBHdl, weld::ComboBox&, void) { auto nItemPos = FindInPalette(aColor); if (nItemPos != -1) - m_xValSetColorList->SelectItem(m_xValSetColorList->GetItemId(nItemPos)); + m_aColorIconView.select(nItemPos); } } } } -IMPL_LINK(SvxColorTabPage, SelectValSetHdl_Impl, ValueSet*, pValSet, void) +void SvxColorTabPage::UpdateToSelectedColor(const NamedColor& rNamedColor) { - sal_Int32 nPos = pValSet->GetSelectedItemId(); - if( nPos == 0 ) - return; - - Color aColor = pValSet->GetItemColor( nPos ); - - m_rXFSet.Put(XFillColorItem(OUString(), aColor)); + m_rXFSet.Put(XFillColorItem(OUString(), rNamedColor.m_aColor)); m_aCtlPreviewNew.SetAttributes(m_aXFillAttr.GetItemSet()); m_aCtlPreviewNew.Invalidate(); - NamedColor aNamedColor; - aNamedColor.m_aColor = aColor; + ChangeColor(rNamedColor, false); +} - if (pValSet == m_xValSetColorList.get() && maPaletteManager.IsThemePaletteSelected()) +IMPL_LINK(SvxColorTabPage, ActivatePaletteColorHdl, const Color&, rColor, void) +{ + const int nPos = m_aColorIconView.get_selected_index(); + if (nPos < 0 || m_aColorIconView.getColor(nPos) != rColor) + return; + + NamedColor aNamedColor; + aNamedColor.m_aColor = rColor; + + if (maPaletteManager.IsThemePaletteSelected()) { sal_uInt16 nThemeIndex; sal_uInt16 nEffectIndex; @@ -542,30 +501,33 @@ IMPL_LINK(SvxColorTabPage, SelectValSetHdl_Impl, ValueSet*, pValSet, void) } } - ChangeColor(aNamedColor, false); + UpdateToSelectedColor(aNamedColor); - if (pValSet == m_xValSetColorList.get()) + m_aRecentIconView.unselect_all(); + if (m_xSelectPalette->get_active() == 0 && m_aColorIconView.get_selected_index() >= 0) { - m_xValSetRecentList->SetNoSelection(); - if (m_xSelectPalette->get_active() == 0 && m_xValSetColorList->GetSelectedItemId() != 0) - { - m_xBtnDelete->set_sensitive(true); - m_xBtnDelete->set_tooltip_text(u""_ustr); - } - else - { - m_xBtnDelete->set_sensitive(false); - m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR1) ); - } + m_xBtnDelete->set_sensitive(true); + m_xBtnDelete->set_tooltip_text(u""_ustr); } - if (pValSet == m_xValSetRecentList.get()) + else { - m_xValSetColorList->SetNoSelection(); m_xBtnDelete->set_sensitive(false); - m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR2) ); + m_xBtnDelete->set_tooltip_text(CuiResId(RID_CUISTR_DELETEUSERCOLOR1)); } } +IMPL_LINK(SvxColorTabPage, ActivateRecentColorHdl, const Color&, rColor, void) +{ + NamedColor aNamedColor; + aNamedColor.m_aColor = rColor; + + UpdateToSelectedColor(aNamedColor); + + m_aColorIconView.unselect_all(); + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text(CuiResId(RID_CUISTR_DELETEUSERCOLOR2)); +} + void SvxColorTabPage::ConvertColorValues (Color& rColor, ColorModel eModell) { switch (eModell) diff --git a/cui/source/tabpages/tpgradnt.cxx b/cui/source/tabpages/tpgradnt.cxx index 813fc8792e36..2cb05cad2860 100644 --- a/cui/source/tabpages/tpgradnt.cxx +++ b/cui/source/tabpages/tpgradnt.cxx @@ -22,9 +22,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -67,16 +67,15 @@ SvxGradientTabPage::SvxGradientTabPage(weld::Container* pPage, weld::DialogContr , m_xLbColorTo(new ColorListBox(m_xBuilder->weld_menu_button(u"colortolb"_ustr), [this]{ return GetDialogController()->getDialog(); })) , m_xMtrColorTo(m_xBuilder->weld_metric_spin_button(u"colortomtr"_ustr, FieldUnit::PERCENT)) - , m_xGradientLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window(u"gradientpresetlistwin"_ustr, true))) + , m_xGradientPresets(m_xBuilder->weld_icon_view(u"gradientpresets"_ustr)) + , m_xGradientLB(new SvxPresetListBox(*m_xGradientPresets)) , m_xMtrIncrement(m_xBuilder->weld_spin_button(u"incrementmtr"_ustr)) , m_xCbIncrement(m_xBuilder->weld_check_button(u"autoincrement"_ustr)) , m_xBtnAdd(m_xBuilder->weld_button(u"add"_ustr)) , m_xBtnModify(m_xBuilder->weld_button(u"modify"_ustr)) , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, u"previewctl"_ustr, m_aCtlPreview)) - , m_xGradientLBWin(new weld::CustomWeld(*m_xBuilder, u"gradientpresetlist"_ustr, *m_xGradientLB)) { Size aSize = getDrawPreviewOptimalSize(m_aCtlPreview.GetDrawingArea()->get_ref_device()); - m_xGradientLB->set_size_request(aSize.Width(), aSize.Height()); m_xCtlPreview->set_size_request(aSize.Width(), aSize.Height()); // this page needs ExchangeSupport SetExchangeSupport(); @@ -92,7 +91,7 @@ SvxGradientTabPage::SvxGradientTabPage(weld::Container* pPage, weld::DialogContr m_aCtlPreview.SetAttributes(m_aXFillAttr.GetItemSet()); // set handler - m_xGradientLB->SetSelectHdl( LINK( this, SvxGradientTabPage, ChangeGradientHdl ) ); + m_xGradientPresets->connect_item_activated(LINK(this, SvxGradientTabPage, ChangeGradientHdl)); m_xGradientLB->SetRenameHdl( LINK( this, SvxGradientTabPage, ClickRenameHdl_Impl ) ); m_xGradientLB->SetDeleteHdl( LINK( this, SvxGradientTabPage, ClickDeleteHdl_Impl ) ); m_xBtnAdd->connect_clicked(LINK(this, SvxGradientTabPage, ClickAddHdl_Impl)); @@ -115,8 +114,6 @@ SvxGradientTabPage::SvxGradientTabPage(weld::Container* pPage, weld::DialogContr m_xMtrColorTo->connect_value_changed( aLink ); m_xLbColorTo->SetSelectHdl( aLink3 ); - m_xGradientLB->SetStyle(WB_FLATVALUESET | WB_NO_DIRECTSELECT | WB_TABSTOP); - // #i76307# always paint the preview in LTR, because this is what the document does m_aCtlPreview.EnableRTL(false); } @@ -124,7 +121,6 @@ SvxGradientTabPage::SvxGradientTabPage(weld::Container* pPage, weld::DialogContr SvxGradientTabPage::~SvxGradientTabPage() { m_xCtlPreview.reset(); - m_xGradientLBWin.reset(); m_xGradientLB.reset(); m_xLbColorTo.reset(); m_xLbColorFrom.reset(); @@ -180,10 +176,8 @@ void SvxGradientTabPage::ActivatePage( const SfxItemSet& rSet ) sal_Int32 nPos = SearchGradientList( rSet.Get(XATTR_FILLGRADIENT).GetName() ); if ( nPos != -1) - { - sal_uInt16 nId = m_xGradientLB->GetItemId( static_cast( nPos ) ); - m_xGradientLB->SelectItem( nId ); - } + m_xGradientPresets->select(nPos); + // colors could have been deleted ChangeGradientHdl_Impl(); } @@ -200,16 +194,16 @@ DeactivateRC SvxGradientTabPage::DeactivatePage( SfxItemSet* _pSet ) bool SvxGradientTabPage::FillItemSet( SfxItemSet* rSet ) { std::unique_ptr pBGradient; - size_t nPos = m_xGradientLB->IsNoSelection() ? VALUESET_ITEM_NOTFOUND : m_xGradientLB->GetSelectItemPos(); + int nPos = m_xGradientPresets->get_selected_index(); sal_uInt16 nValue = 0; // automatic step count if (!m_xCbIncrement->get_active()) nValue = m_xMtrIncrement->get_value(); - if( nPos != VALUESET_ITEM_NOTFOUND ) + if (nPos >= 0) { pBGradient.reset(new basegfx::BGradient( m_pGradientList->GetGradient( static_cast(nPos) )->GetGradient() )); - OUString aString = m_xGradientLB->GetItemText( m_xGradientLB->GetSelectedItemId() ); + const OUString aString = m_xGradientPresets->get_item_tooltip_text(nPos); // update StepCount to current value to be in sync with FillGradientStepCount pBGradient->SetSteps(nValue); rSet->Put( XFillGradientItem( aString, *pBGradient ) ); @@ -258,31 +252,31 @@ IMPL_LINK( SvxGradientTabPage, ModifiedListBoxHdl_Impl, weld::ComboBox&, rListBo { ModifiedHdl_Impl(&rListBox); // gradient params changed, it is no longer one of the presets - m_xGradientLB->SetNoSelection(); + m_xGradientPresets->unselect_all(); } IMPL_LINK( SvxGradientTabPage, ModifiedColorListBoxHdl_Impl, ColorListBox&, rListBox, void ) { ModifiedHdl_Impl(&rListBox); - m_xGradientLB->SetNoSelection(); + m_xGradientPresets->unselect_all(); } IMPL_LINK( SvxGradientTabPage, ModifiedEditHdl_Impl, weld::SpinButton&, rBox, void ) { ModifiedHdl_Impl(&rBox); - m_xGradientLB->SetNoSelection(); + m_xGradientPresets->unselect_all(); } IMPL_LINK( SvxGradientTabPage, ModifiedMetricHdl_Impl, weld::MetricSpinButton&, rBox, void ) { ModifiedHdl_Impl(&rBox); - m_xGradientLB->SetNoSelection(); + m_xGradientPresets->unselect_all(); } IMPL_LINK( SvxGradientTabPage, ModifiedSliderHdl_Impl, weld::Scale&, rSlider, void ) { ModifiedHdl_Impl(&rSlider); - m_xGradientLB->SetNoSelection(); + m_xGradientPresets->unselect_all(); } IMPL_LINK_NOARG( SvxGradientTabPage, ChangeAutoStepHdl_Impl, weld::Toggleable&, void ) @@ -393,11 +387,11 @@ IMPL_LINK_NOARG(SvxGradientTabPage, ClickAddHdl_Impl, weld::Button&, void) m_pGradientList->Insert(std::make_unique(aBGradient, aName), nCount); - sal_Int32 nId = m_xGradientLB->GetItemId(nCount - 1); //calculate the last ID - Bitmap aBitmap = m_pGradientList->GetBitmapForPreview( nCount, m_xGradientLB->GetIconSize() ); - m_xGradientLB->InsertItem( nId + 1, Image(aBitmap), aName ); - m_xGradientLB->SelectItem( nId + 1 ); - m_xGradientLB->Resize(); + Bitmap aBitmap = m_pGradientList->CreateBitmap(nCount, m_xGradientLB->GetIconSize()); + m_xGradientPresets->insert(nCount, nullptr, nullptr, &aBitmap, nullptr); + m_xGradientPresets->set_item_accessible_name(nCount, aName); + m_xGradientPresets->set_item_tooltip_text(nCount, aName); + m_xGradientPresets->select(nCount); m_nGradientListState |= ChangeType::MODIFIED; @@ -412,13 +406,12 @@ IMPL_LINK_NOARG(SvxGradientTabPage, ClickAddHdl_Impl, weld::Button&, void) IMPL_LINK_NOARG(SvxGradientTabPage, ClickModifyHdl_Impl, weld::Button&, void) { - sal_uInt16 nId = m_xGradientLB->GetSelectedItemId(); - size_t nPos = m_xGradientLB->GetSelectItemPos(); + const int nPos = m_xGradientPresets->get_selected_index(); - if ( nPos == VALUESET_ITEM_NOTFOUND ) + if (nPos < 0) return; - OUString aName( m_pGradientList->GetGradient( static_cast(nPos) )->GetName() ); + OUString aName(m_pGradientList->GetGradient(nPos)->GetName()); sal_uInt16 nValue = 0; // automatic step count if (!m_xCbIncrement->get_active()) @@ -437,34 +430,32 @@ IMPL_LINK_NOARG(SvxGradientTabPage, ClickModifyHdl_Impl, weld::Button&, void) m_pGradientList->Replace(std::make_unique(aBGradient, aName), nPos); - Bitmap aBitmap = m_pGradientList->GetBitmapForPreview( static_cast(nPos), m_xGradientLB->GetIconSize() ); - m_xGradientLB->RemoveItem( nId ); - m_xGradientLB->InsertItem( nId, Image(aBitmap), aName, static_cast(nPos) ); - m_xGradientLB->SelectItem( nId ); + Bitmap aBitmap = m_pGradientList->CreateBitmap(nPos, m_xGradientLB->GetIconSize()); + m_xGradientPresets->remove(nPos); + m_xGradientPresets->insert(nPos, nullptr, nullptr, &aBitmap, nullptr); + m_xGradientPresets->set_item_accessible_name(nPos, aName); + m_xGradientPresets->set_item_tooltip_text(nPos, aName); + m_xGradientPresets->select(nPos); m_nGradientListState |= ChangeType::MODIFIED; } -IMPL_LINK_NOARG(SvxGradientTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) +IMPL_LINK(SvxGradientTabPage, ClickDeleteHdl_Impl, int, nPos, void) { - const sal_uInt16 nId = m_xGradientLB->GetContextMenuItemId(); - const size_t nPos = m_xGradientLB->GetItemPos(nId); - - if( nPos != VALUESET_ITEM_NOTFOUND ) + if (nPos >= 0) { std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), u"cui/ui/querydeletegradientdialog.ui"_ustr)); std::unique_ptr xQueryBox(xBuilder->weld_message_dialog(u"AskDelGradientDialog"_ustr)); if (xQueryBox->run() == RET_YES) { - const bool bDeletingSelectedItem(nId == m_xGradientLB->GetSelectedItemId()); + const bool bDeletingSelectedItem(nPos == m_xGradientPresets->get_selected_index()); m_pGradientList->Remove(nPos); - m_xGradientLB->RemoveItem( nId ); + m_xGradientPresets->remove(nPos); if (bDeletingSelectedItem) { - m_xGradientLB->SelectItem(m_xGradientLB->GetItemId(/*Position=*/0)); + m_xGradientPresets->select(0); m_aCtlPreview.Invalidate(); } - m_xGradientLB->Resize(); ChangeGradientHdl_Impl(); @@ -476,16 +467,13 @@ IMPL_LINK_NOARG(SvxGradientTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void m_xBtnModify->set_sensitive(false); } -IMPL_LINK_NOARG(SvxGradientTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void) +IMPL_LINK(SvxGradientTabPage, ClickRenameHdl_Impl, int, nPos, void) { - const sal_uInt16 nId = m_xGradientLB->GetContextMenuItemId(); - const size_t nPos = m_xGradientLB->GetItemPos(nId); - - if ( nPos == VALUESET_ITEM_NOTFOUND ) + if (nPos < 0) return; OUString aDesc( CuiResId( RID_CUISTR_DESC_GRADIENT ) ); - OUString aName( m_pGradientList->GetGradient( nPos )->GetName() ); + OUString aName(m_pGradientList->GetGradient(nPos)->GetName()); SvxNameDialog aDlg(GetFrameWeld(), aName, aDesc); @@ -494,14 +482,15 @@ IMPL_LINK_NOARG(SvxGradientTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void { aName = aDlg.GetName(); sal_Int32 nGradientPos = SearchGradientList(aName); - bool bValidGradientName = (nGradientPos == static_cast(nPos) ) || (nGradientPos == -1); + bool bValidGradientName = (nGradientPos == nPos) || (nGradientPos == -1); if( bValidGradientName ) { bLoop = false; m_pGradientList->GetGradient(nPos)->SetName(aName); - m_xGradientLB->SetItemText( nId, aName ); + m_xGradientPresets->set_item_accessible_name(nPos, aName); + m_xGradientPresets->set_item_tooltip_text(nPos, aName); m_nGradientListState |= ChangeType::MODIFIED; } @@ -514,18 +503,19 @@ IMPL_LINK_NOARG(SvxGradientTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void } } -IMPL_LINK_NOARG(SvxGradientTabPage, ChangeGradientHdl, ValueSet*, void) +IMPL_LINK_NOARG(SvxGradientTabPage, ChangeGradientHdl, const weld::TreeIter&, bool) { ChangeGradientHdl_Impl(); + return true; } void SvxGradientTabPage::ChangeGradientHdl_Impl() { std::unique_ptr pGradient; - size_t nPos = m_xGradientLB->GetSelectItemPos(); + const int nPos = m_xGradientPresets->get_selected_index(); - if( nPos != VALUESET_ITEM_NOTFOUND ) - pGradient.reset(new basegfx::BGradient( m_pGradientList->GetGradient( static_cast( nPos ) )->GetGradient() )); + if (nPos >= 0) + pGradient.reset(new basegfx::BGradient(m_pGradientList->GetGradient(nPos)->GetGradient())); else { if( const XFillStyleItem* pFillStyleItem = m_rOutAttrs.GetItemIfSet( GetWhich( XATTR_FILLSTYLE ) ) ) @@ -537,12 +527,10 @@ void SvxGradientTabPage::ChangeGradientHdl_Impl() pGradient.reset(new basegfx::BGradient( pGradientItem->GetGradientValue() )); } } - if( !pGradient ) + if (!pGradient && m_xGradientPresets->n_children() > 0) { - sal_uInt16 nPosition = m_xGradientLB->GetItemId(0); - m_xGradientLB->SelectItem( nPosition ); - if( nPosition != 0 ) - pGradient.reset(new basegfx::BGradient( m_pGradientList->GetGradient( 0 )->GetGradient() )); + m_xGradientPresets->select(0); + pGradient.reset(new basegfx::BGradient(m_pGradientList->GetGradient(0)->GetGradient())); } } diff --git a/cui/source/tabpages/tphatch.cxx b/cui/source/tabpages/tphatch.cxx index f8d8014cbc9f..3a3a35a782d6 100644 --- a/cui/source/tabpages/tphatch.cxx +++ b/cui/source/tabpages/tphatch.cxx @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -65,14 +64,13 @@ SvxHatchTabPage::SvxHatchTabPage(weld::Container* pPage, weld::DialogController* , m_xCbBackgroundColor(m_xBuilder->weld_check_button(u"backgroundcolor"_ustr)) , m_xLbBackgroundColor(new ColorListBox(m_xBuilder->weld_menu_button(u"backgroundcolorlb"_ustr), [this]{ return GetDialogController()->getDialog(); })) - , m_xHatchLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window(u"hatchpresetlistwin"_ustr, true))) + , m_xHatchPresets(m_xBuilder->weld_icon_view(u"hatchpresets"_ustr)) + , m_xHatchLB(new SvxPresetListBox(*m_xHatchPresets)) , m_xBtnAdd(m_xBuilder->weld_button(u"add"_ustr)) , m_xBtnModify(m_xBuilder->weld_button(u"modify"_ustr)) - , m_xHatchLBWin(new weld::CustomWeld(*m_xBuilder, u"hatchpresetlist"_ustr, *m_xHatchLB)) , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, u"previewctl"_ustr, m_aCtlPreview)) { Size aSize = getDrawPreviewOptimalSize(m_aCtlPreview.GetDrawingArea()->get_ref_device()); - m_xHatchLBWin->set_size_request(aSize.Width(), aSize.Height()); m_xCtlPreview->set_size_request(aSize.Width(), aSize.Height()); // this page needs ExchangeSupport @@ -100,7 +98,7 @@ SvxHatchTabPage::SvxHatchTabPage(weld::Container* pPage, weld::DialogController* m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_HATCH) ); m_rXFSet.Put( XFillHatchItem(OUString(), XHatch()) ); m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); - m_xHatchLB->SetSelectHdl( LINK( this, SvxHatchTabPage, ChangeHatchHdl ) ); + m_xHatchPresets->connect_item_activated(LINK(this, SvxHatchTabPage, ChangeHatchHdl)); m_xHatchLB->SetRenameHdl( LINK( this, SvxHatchTabPage, ClickRenameHdl_Impl ) ); m_xHatchLB->SetDeleteHdl( LINK( this, SvxHatchTabPage, ClickDeleteHdl_Impl ) ); @@ -118,15 +116,12 @@ SvxHatchTabPage::SvxHatchTabPage(weld::Container* pPage, weld::DialogController* m_xBtnAdd->connect_clicked( LINK( this, SvxHatchTabPage, ClickAddHdl_Impl ) ); m_xBtnModify->connect_clicked( LINK( this, SvxHatchTabPage, ClickModifyHdl_Impl ) ); - m_xHatchLB->SetStyle(WB_FLATVALUESET | WB_NO_DIRECTSELECT | WB_TABSTOP); - m_aCtlPreview.SetDrawMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode() ? OUTPUT_DRAWMODE_CONTRAST : OUTPUT_DRAWMODE_COLOR); } SvxHatchTabPage::~SvxHatchTabPage() { m_xCtlPreview.reset(); - m_xHatchLBWin.reset(); m_xHatchLB.reset(); m_xLbBackgroundColor.reset(); m_xLbLineColor.reset(); @@ -181,10 +176,8 @@ void SvxHatchTabPage::ActivatePage( const SfxItemSet& rSet ) sal_Int32 nPos = SearchHatchList( rSet.Get(XATTR_FILLHATCH).GetName() ); if( nPos != -1) - { - sal_uInt16 nId = m_xHatchLB->GetItemId( static_cast( nPos ) ); - m_xHatchLB->SelectItem( nId ); - } + m_xHatchPresets->select(nPos); + // colors could have been deleted ChangeHatchHdl_Impl(); } @@ -241,11 +234,11 @@ bool SvxHatchTabPage::FillItemSet( SfxItemSet* rSet ) { std::unique_ptr pXHatch; OUString aString; - size_t nPos = m_xHatchLB->IsNoSelection() ? VALUESET_ITEM_NOTFOUND : m_xHatchLB->GetSelectItemPos(); - if( nPos != VALUESET_ITEM_NOTFOUND ) + const int nPos = m_xHatchPresets->get_selected_index(); + if (nPos >= 0) { pXHatch.reset(new XHatch( m_pHatchingList->GetHatch( static_cast(nPos) )->GetHatch() )); - aString = m_xHatchLB->GetItemText( m_xHatchLB->GetSelectedItemId() ); + aString = m_xHatchPresets->get_item_tooltip_text(nPos); } // unidentified hatch has been passed else @@ -297,13 +290,13 @@ IMPL_LINK( SvxHatchTabPage, ModifiedListBoxHdl_Impl, weld::ComboBox&, rListBox, { ModifiedHdl_Impl(&rListBox); // hatch params have changed, it is no longer one of the presets - m_xHatchLB->SetNoSelection(); + m_xHatchPresets->unselect_all(); } IMPL_LINK( SvxHatchTabPage, ModifiedColorListBoxHdl_Impl, ColorListBox&, rListBox, void ) { ModifiedHdl_Impl(&rListBox); - m_xHatchLB->SetNoSelection(); + m_xHatchPresets->unselect_all(); } IMPL_LINK_NOARG( SvxHatchTabPage, ToggleHatchBackgroundColor_Impl, weld::Toggleable&, void ) @@ -334,13 +327,13 @@ IMPL_LINK_NOARG( SvxHatchTabPage, ModifiedBackgroundHdl_Impl, ColorListBox&, voi IMPL_LINK( SvxHatchTabPage, ModifiedEditHdl_Impl, weld::MetricSpinButton&, rEdit, void ) { ModifiedHdl_Impl(&rEdit); - m_xHatchLB->SetNoSelection(); + m_xHatchPresets->unselect_all(); } IMPL_LINK( SvxHatchTabPage, ModifiedSliderHdl_Impl, weld::Scale&, rSlider, void ) { ModifiedHdl_Impl(&rSlider); - m_xHatchLB->SetNoSelection(); + m_xHatchPresets->unselect_all(); } void SvxHatchTabPage::ModifiedHdl_Impl( void const * p ) @@ -362,18 +355,19 @@ void SvxHatchTabPage::ModifiedHdl_Impl( void const * p ) m_aCtlPreview.Invalidate(); } -IMPL_LINK_NOARG(SvxHatchTabPage, ChangeHatchHdl, ValueSet*, void) +IMPL_LINK_NOARG(SvxHatchTabPage, ChangeHatchHdl, const weld::TreeIter&, bool) { ChangeHatchHdl_Impl(); + return true; } void SvxHatchTabPage::ChangeHatchHdl_Impl() { std::unique_ptr pHatch; - size_t nPos = m_xHatchLB->GetSelectItemPos(); + const int nPos = m_xHatchPresets->get_selected_index(); - if( nPos != VALUESET_ITEM_NOTFOUND ) - pHatch.reset(new XHatch( m_pHatchingList->GetHatch( static_cast(nPos) )->GetHatch() )); + if (nPos >= 0) + pHatch.reset(new XHatch(m_pHatchingList->GetHatch(nPos)->GetHatch())); else { if( const XFillStyleItem* pFillStyleItem = m_rOutAttrs.GetItemIfSet( GetWhich( XATTR_FILLSTYLE ) ) ) @@ -385,12 +379,10 @@ void SvxHatchTabPage::ChangeHatchHdl_Impl() pHatch.reset(new XHatch( pFillHatchItem->GetHatchValue() )); } } - if( !pHatch ) + if (!pHatch && m_xHatchPresets->n_children() > 0) { - sal_uInt16 nPosition = m_xHatchLB->GetItemId( 0 ); - m_xHatchLB->SelectItem( nPosition ); - if( nPosition != 0 ) - pHatch.reset( new XHatch( m_pHatchingList->GetHatch( 0 )->GetHatch() ) ); + m_xHatchPresets->select(0); + pHatch.reset(new XHatch(m_pHatchingList->GetHatch(0)->GetHatch())); } } if( pHatch ) @@ -427,12 +419,12 @@ void SvxHatchTabPage::AddHatch(const OUString& aName, tools::Long nCount) m_pHatchingList->Insert(std::make_unique(aXHatch, aName), nCount); - sal_Int32 nId = m_xHatchLB->GetItemId(nCount - 1); // calculate the last ID - Bitmap aBitmap = m_pHatchingList->GetBitmapForPreview( nCount, m_xHatchLB->GetIconSize() ); + Bitmap aBitmap = m_pHatchingList->CreateBitmap(nCount, m_xHatchLB->GetIconSize()); // Insert the new entry at the next ID - m_xHatchLB->InsertItem( nId + 1, Image(aBitmap), aName ); - m_xHatchLB->SelectItem( nId + 1 ); - m_xHatchLB->Resize(); + m_xHatchPresets->insert(nCount, nullptr, nullptr, &aBitmap, nullptr); + m_xHatchPresets->set_item_accessible_name(nCount, aName); + m_xHatchPresets->set_item_tooltip_text(nCount, aName); + m_xHatchPresets->select(nCount); m_nHatchingListState |= ChangeType::MODIFIED; @@ -483,13 +475,12 @@ IMPL_LINK_NOARG(SvxHatchTabPage, ClickAddHdl_Impl, weld::Button&, void) IMPL_LINK_NOARG(SvxHatchTabPage, ClickModifyHdl_Impl, weld::Button&, void) { - sal_uInt16 nId = m_xHatchLB->GetSelectedItemId(); - size_t nPos = m_xHatchLB->GetSelectItemPos(); + const int nPos = m_xHatchPresets->get_selected_index(); - if( nPos == VALUESET_ITEM_NOTFOUND ) + if (nPos < 0) return; - OUString aName( m_pHatchingList->GetHatch( static_cast(nPos) )->GetName() ); + OUString aName(m_pHatchingList->GetHatch(nPos)->GetName()); XHatch aXHatch( m_xLbLineColor->GetSelectEntryColor(), static_cast(m_xLbLineType->get_active()), @@ -498,10 +489,12 @@ IMPL_LINK_NOARG(SvxHatchTabPage, ClickModifyHdl_Impl, weld::Button&, void) m_pHatchingList->Replace(std::make_unique(aXHatch, aName), nPos); - Bitmap aBitmap = m_pHatchingList->GetBitmapForPreview( static_cast(nPos), m_xHatchLB->GetIconSize() ); - m_xHatchLB->RemoveItem( nId ); - m_xHatchLB->InsertItem( nId, Image(aBitmap), aName, static_cast(nPos) ); - m_xHatchLB->SelectItem( nId ); + Bitmap aBitmap = m_pHatchingList->CreateBitmap(nPos, m_xHatchLB->GetIconSize()); + m_xHatchPresets->remove(nPos); + m_xHatchPresets->insert(nPos, nullptr, nullptr, &aBitmap, nullptr); + m_xHatchPresets->set_item_accessible_name(nPos, aName); + m_xHatchPresets->set_item_tooltip_text(nPos, aName); + m_xHatchPresets->select(nPos); // save values for changes recognition (-> method) m_xMtrDistance->save_value(); @@ -513,12 +506,9 @@ IMPL_LINK_NOARG(SvxHatchTabPage, ClickModifyHdl_Impl, weld::Button&, void) m_nHatchingListState |= ChangeType::MODIFIED; } -IMPL_LINK_NOARG(SvxHatchTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) +IMPL_LINK(SvxHatchTabPage, ClickDeleteHdl_Impl, int, nPos, void) { - const sal_uInt16 nId = m_xHatchLB->GetContextMenuItemId(); - const size_t nPos = m_xHatchLB->GetItemPos(nId); - - if( nPos == VALUESET_ITEM_NOTFOUND ) + if (nPos < 0) return; std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), u"cui/ui/querydeletehatchdialog.ui"_ustr)); @@ -526,27 +516,23 @@ IMPL_LINK_NOARG(SvxHatchTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) if (xQueryBox->run() != RET_YES) return; - const bool bDeletingSelectedItem(nId == m_xHatchLB->GetSelectedItemId()); + const bool bDeletingSelectedItem(nPos == m_xHatchPresets->get_selected_index()); m_pHatchingList->Remove(nPos); - m_xHatchLB->RemoveItem( nId ); + m_xHatchPresets->remove(nPos); if (bDeletingSelectedItem) { - m_xHatchLB->SelectItem(m_xHatchLB->GetItemId(/*Position=*/0)); + m_xHatchPresets->select(0); m_aCtlPreview.Invalidate(); } - m_xHatchLB->Resize(); ChangeHatchHdl_Impl(); m_nHatchingListState |= ChangeType::MODIFIED; } -IMPL_LINK_NOARG(SvxHatchTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void ) +IMPL_LINK(SvxHatchTabPage, ClickRenameHdl_Impl, int, nPos, void) { - const sal_uInt16 nId = m_xHatchLB->GetContextMenuItemId(); - const size_t nPos = m_xHatchLB->GetItemPos(nId); - - if( nPos == VALUESET_ITEM_NOTFOUND ) + if (nPos < 0) return; OUString aDesc( CuiResId( RID_CUISTR_DESC_HATCH ) ); @@ -566,7 +552,8 @@ IMPL_LINK_NOARG(SvxHatchTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void ) bLoop = false; m_pHatchingList->GetHatch(nPos)->SetName(aName); - m_xHatchLB->SetItemText(nId, aName); + m_xHatchPresets->set_item_accessible_name(nPos, aName); + m_xHatchPresets->set_item_tooltip_text(nPos, aName); m_nHatchingListState |= ChangeType::MODIFIED; } @@ -577,7 +564,6 @@ IMPL_LINK_NOARG(SvxHatchTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void ) xBox->run(); } } - } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpline.cxx b/cui/source/tabpages/tpline.cxx index bef017dfc72b..51a0e8721e2c 100644 --- a/cui/source/tabpages/tpline.cxx +++ b/cui/source/tabpages/tpline.cxx @@ -68,6 +68,7 @@ #include #include #include +#include #define MAX_BMP_WIDTH 16 #define MAX_BMP_HEIGHT 16 diff --git a/cui/source/tabpages/tplnedef.cxx b/cui/source/tabpages/tplnedef.cxx index d7208478afcc..19b5e41cccc0 100644 --- a/cui/source/tabpages/tplnedef.cxx +++ b/cui/source/tabpages/tplnedef.cxx @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -38,7 +37,6 @@ #include #include -#include #include #include #include @@ -50,6 +48,8 @@ using namespace com::sun::star; +constexpr int RET_BTN_1 = 100; +constexpr int RET_BTN_2 = 101; SvxLineDefTabPage::SvxLineDefTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) : SfxTabPage(pPage, pController, u"cui/ui/linestyletabpage.ui"_ustr, u"LineStylePage"_ustr, &rInAttrs) @@ -458,32 +458,11 @@ IMPL_LINK( SvxLineDefTabPage, SelectTypeListBoxHdl_Impl, weld::ComboBox&, rListB void SvxLineDefTabPage::SelectTypeHdl_Impl(const weld::ComboBox* p) { if (p == m_xLbType1.get() || !p) - { - if (m_xLbType1->get_active() == 0) - { - m_xMtrLength1->set_sensitive(false); - m_xMtrLength1->set_text(u""_ustr); - } - else if (!m_xMtrLength1->get_sensitive()) - { - m_xMtrLength1->set_sensitive(true); - m_xMtrLength1->reformat(); - } - } + m_xMtrLength1->set_sensitive(m_xLbType1->get_active() != 0); if (p == m_xLbType2.get() || !p) - { - if (m_xLbType2->get_active() == 0) - { - m_xMtrLength2->set_sensitive(false); - m_xMtrLength2->set_text(u""_ustr); - } - else if (!m_xMtrLength2->get_sensitive()) - { - m_xMtrLength2->set_sensitive(true); - m_xMtrLength2->reformat(); - } - } + m_xMtrLength2->set_sensitive(m_xLbType2->get_active() != 0); + ChangePreviewHdl_Impl(*m_xMtrLength1); } diff --git a/cui/source/tabpages/tplneend.cxx b/cui/source/tabpages/tplneend.cxx index 428908e504a5..0cb457c0a531 100644 --- a/cui/source/tabpages/tplneend.cxx +++ b/cui/source/tabpages/tplneend.cxx @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/cui/source/tabpages/tppattern.cxx b/cui/source/tabpages/tppattern.cxx index 90649948cfdb..5ed3751e7047 100644 --- a/cui/source/tabpages/tppattern.cxx +++ b/cui/source/tabpages/tppattern.cxx @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -88,16 +87,15 @@ SvxPatternTabPage::SvxPatternTabPage(weld::Container* pPage, weld::DialogControl [this]{ return GetDialogController()->getDialog(); })) , m_xLbBackgroundColor(new ColorListBox(m_xBuilder->weld_menu_button(u"LB_BACKGROUND_COLOR"_ustr), [this]{ return GetDialogController()->getDialog(); })) - , m_xPatternLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window(u"patternpresetlistwin"_ustr, true))) + , m_xPatternPresets(m_xBuilder->weld_icon_view(u"patternpresets"_ustr)) + , m_xPatternLB(new SvxPresetListBox(*m_xPatternPresets)) , m_xBtnAdd(m_xBuilder->weld_button(u"BTN_ADD"_ustr)) , m_xBtnModify(m_xBuilder->weld_button(u"BTN_MODIFY"_ustr)) , m_xCtlPixelWin(new weld::CustomWeld(*m_xBuilder, u"CTL_PIXEL"_ustr, *m_xCtlPixel)) , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, u"CTL_PREVIEW"_ustr, m_aCtlPreview)) - , m_xPatternLBWin(new weld::CustomWeld(*m_xBuilder, u"patternpresetlist"_ustr, *m_xPatternLB)) { // size of the bitmap display Size aSize = getDrawPreviewOptimalSize(m_aCtlPreview.GetDrawingArea()->get_ref_device()); - m_xPatternLB->set_size_request(aSize.Width(), aSize.Height()); m_xCtlPreview->set_size_request(aSize.Width(), aSize.Height()); m_xBitmapCtl.reset(new SvxBitmapCtl); @@ -112,18 +110,15 @@ SvxPatternTabPage::SvxPatternTabPage(weld::Container* pPage, weld::DialogControl m_xBtnAdd->connect_clicked( LINK( this, SvxPatternTabPage, ClickAddHdl_Impl ) ); m_xBtnModify->connect_clicked( LINK( this, SvxPatternTabPage, ClickModifyHdl_Impl ) ); - m_xPatternLB->SetSelectHdl( LINK( this, SvxPatternTabPage, ChangePatternHdl_Impl ) ); + m_xPatternPresets->connect_item_activated(LINK(this, SvxPatternTabPage, ChangePatternHdl_Impl)); m_xPatternLB->SetRenameHdl( LINK( this, SvxPatternTabPage, ClickRenameHdl_Impl ) ); m_xPatternLB->SetDeleteHdl( LINK( this, SvxPatternTabPage, ClickDeleteHdl_Impl ) ); m_xLbColor->SetSelectHdl( LINK( this, SvxPatternTabPage, ChangeColorHdl_Impl ) ); - m_xLbBackgroundColor->SetSelectHdl( LINK( this, SvxPatternTabPage, ChangeColorHdl_Impl ) ); - - m_xPatternLB->SetStyle(WB_FLATVALUESET | WB_NO_DIRECTSELECT | WB_TABSTOP); + m_xLbBackgroundColor->SetSelectHdl(LINK(this, SvxPatternTabPage, ChangeColorHdl_Impl)); } SvxPatternTabPage::~SvxPatternTabPage() { - m_xPatternLBWin.reset(); m_xCtlPreview.reset(); m_xCtlPixelWin.reset(); m_xPatternLB.reset(); @@ -184,13 +179,10 @@ void SvxPatternTabPage::ActivatePage( const SfxItemSet& rSet ) { sal_Int32 nPos = SearchPatternList( aItem.GetName() ); if ( nPos != -1) - { - sal_uInt16 nId = m_xPatternLB->GetItemId( static_cast( nPos ) ); - m_xPatternLB->SelectItem( nId ); - } + m_xPatternPresets->select(nPos); } else - m_xPatternLB->SelectItem( m_xPatternLB->GetItemId( static_cast( 0 ) ) ); + m_xPatternPresets->select(0); } @@ -206,11 +198,11 @@ DeactivateRC SvxPatternTabPage::DeactivatePage( SfxItemSet* _pSet) bool SvxPatternTabPage::FillItemSet( SfxItemSet* _rOutAttrs ) { _rOutAttrs->Put(XFillStyleItem(drawing::FillStyle_BITMAP)); - size_t nPos = m_xPatternLB->IsNoSelection() ? VALUESET_ITEM_NOTFOUND : m_xPatternLB->GetSelectItemPos(); - if(VALUESET_ITEM_NOTFOUND != nPos) + const int nPos = m_xPatternPresets->get_selected_index(); + if (nPos >= 0) { - const XBitmapEntry* pXBitmapEntry = m_pPatternList->GetBitmap( static_cast(nPos) ); - const OUString aString( m_xPatternLB->GetItemText( m_xPatternLB->GetSelectedItemId() ) ); + const XBitmapEntry* pXBitmapEntry = m_pPatternList->GetBitmap(nPos); + const OUString aString(m_xPatternPresets->get_item_tooltip_text(nPos)); _rOutAttrs->Put(XFillBitmapItem(aString, pXBitmapEntry->GetGraphicObject())); } @@ -240,7 +232,7 @@ void SvxPatternTabPage::Reset( const SfxItemSet* ) m_aCtlPreview.Invalidate(); } - ChangePatternHdl_Impl(m_xPatternLB.get()); + UpdatePattern(); // determine button state if( m_pPatternList.is() && m_pPatternList->Count() ) @@ -261,14 +253,20 @@ std::unique_ptr SvxPatternTabPage::Create(weld::Container* pP return std::make_unique(pPage, pController, rSet); } -IMPL_LINK_NOARG(SvxPatternTabPage, ChangePatternHdl_Impl, ValueSet*, void) +IMPL_LINK_NOARG(SvxPatternTabPage, ChangePatternHdl_Impl, const weld::TreeIter&, bool) +{ + UpdatePattern(); + return true; +} + +void SvxPatternTabPage::UpdatePattern() { std::unique_ptr pGraphicObject; - size_t nPos = m_xPatternLB->GetSelectItemPos(); + const int nPos = m_xPatternPresets->get_selected_index(); - if(VALUESET_ITEM_NOTFOUND != nPos) + if (nPos >= 0) { - pGraphicObject.reset(new GraphicObject(m_pPatternList->GetBitmap( static_cast(nPos) )->GetGraphicObject())); + pGraphicObject.reset(new GraphicObject(m_pPatternList->GetBitmap(nPos)->GetGraphicObject())); } else { @@ -283,14 +281,11 @@ IMPL_LINK_NOARG(SvxPatternTabPage, ChangePatternHdl_Impl, ValueSet*, void) } } - if(!pGraphicObject) + if (!pGraphicObject && m_xPatternPresets->n_children() > 0) { - sal_uInt16 nPosition = m_xPatternLB->GetItemId( 0 ); - m_xPatternLB->SelectItem( nPosition ); - if( nPosition != 0 ) - { - pGraphicObject.reset(new GraphicObject(m_pPatternList->GetBitmap(0)->GetGraphicObject())); - } + m_xPatternPresets->select(0); + pGraphicObject.reset( + new GraphicObject(m_pPatternList->GetBitmap(0)->GetGraphicObject())); } } @@ -396,15 +391,15 @@ IMPL_LINK_NOARG(SvxPatternTabPage, ClickAddHdl_Impl, weld::Button&, void) if( pEntry ) { m_pPatternList->Insert(std::move(pEntry), nCount); - sal_Int32 nId = m_xPatternLB->GetItemId( nCount - 1 ); - Bitmap aBitmap = m_pPatternList->GetBitmapForPreview( nCount, m_xPatternLB->GetIconSize() ); - m_xPatternLB->InsertItem( nId + 1, Image(aBitmap), aName ); - m_xPatternLB->SelectItem( nId + 1 ); - m_xPatternLB->Resize(); + Bitmap aBitmap = m_pPatternList->CreateBitmap(nCount, m_xPatternLB->GetIconSize()); + m_xPatternPresets->insert(nCount, nullptr, nullptr, &aBitmap, nullptr); + m_xPatternPresets->set_item_accessible_name(nCount, aName); + m_xPatternPresets->set_item_tooltip_text(nCount, aName); + m_xPatternPresets->select(nCount); m_nPatternListState |= ChangeType::MODIFIED; - ChangePatternHdl_Impl(m_xPatternLB.get()); + UpdatePattern(); } } @@ -417,32 +412,29 @@ IMPL_LINK_NOARG(SvxPatternTabPage, ClickAddHdl_Impl, weld::Button&, void) IMPL_LINK_NOARG(SvxPatternTabPage, ClickModifyHdl_Impl, weld::Button&, void) { - sal_uInt16 nId = m_xPatternLB->GetSelectedItemId(); - size_t nPos = m_xPatternLB->GetSelectItemPos(); + const int nPos = m_xPatternPresets->get_selected_index(); - if ( nPos == VALUESET_ITEM_NOTFOUND ) + if (nPos < 0) return; - OUString aName( m_pPatternList->GetBitmap( static_cast(nPos) )->GetName() ); + OUString aName(m_pPatternList->GetBitmap(nPos)->GetName()); // #i123497# Need to replace the existing entry with a new one (old returned needs to be deleted) m_pPatternList->Replace(std::make_unique(Graphic(m_xBitmapCtl->GetBitmap()), aName), nPos); - Bitmap aBitmap = m_pPatternList->GetBitmapForPreview( static_cast( nPos ), m_xPatternLB->GetIconSize() ); - m_xPatternLB->RemoveItem(nId); - m_xPatternLB->InsertItem( nId, Image(aBitmap), aName, static_cast(nPos) ); - m_xPatternLB->SelectItem( nId ); + Bitmap aBitmap = m_pPatternList->CreateBitmap(nPos, m_xPatternLB->GetIconSize()); + m_xPatternPresets->remove(nPos); + m_xPatternPresets->insert(nPos, nullptr, nullptr, &aBitmap, nullptr); + m_xPatternPresets->set_item_accessible_name(nPos, aName); + m_xPatternPresets->set_item_tooltip_text(nPos, aName); + m_xPatternPresets->select(nPos); m_nPatternListState |= ChangeType::MODIFIED; } - -IMPL_LINK_NOARG(SvxPatternTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void) +IMPL_LINK(SvxPatternTabPage, ClickRenameHdl_Impl, int, nPos, void) { - const sal_uInt16 nId = m_xPatternLB->GetContextMenuItemId(); - const size_t nPos = m_xPatternLB->GetItemPos(nId); - - if ( nPos == VALUESET_ITEM_NOTFOUND ) + if (nPos < 0) return; OUString aDesc(CuiResId(RID_CUISTR_DESC_NEW_PATTERN)); @@ -464,7 +456,8 @@ IMPL_LINK_NOARG(SvxPatternTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void) m_pPatternList->GetBitmap(nPos)->SetName(aName); - m_xPatternLB->SetItemText( nId, aName ); + m_xPatternPresets->set_item_accessible_name(nPos, aName); + m_xPatternPresets->set_item_tooltip_text(nPos, aName); m_nPatternListState |= ChangeType::MODIFIED; } @@ -477,29 +470,25 @@ IMPL_LINK_NOARG(SvxPatternTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void) } } -IMPL_LINK_NOARG(SvxPatternTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) +IMPL_LINK(SvxPatternTabPage, ClickDeleteHdl_Impl, int, nPos, void) { - const sal_uInt16 nId = m_xPatternLB->GetContextMenuItemId(); - const size_t nPos = m_xPatternLB->GetItemPos(nId); - - if( nPos != VALUESET_ITEM_NOTFOUND ) + if (nPos >= 0) { std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), u"cui/ui/querydeletebitmapdialog.ui"_ustr)); std::unique_ptr xQueryBox(xBuilder->weld_message_dialog(u"AskDelBitmapDialog"_ustr)); if (xQueryBox->run() == RET_YES) { - const bool bDeletingSelectedItem(nId == m_xPatternLB->GetSelectedItemId()); + const bool bDeletingSelectedItem(nPos == m_xPatternPresets->get_selected_index()); m_pPatternList->Remove(nPos); - m_xPatternLB->RemoveItem( nId ); + m_xPatternPresets->remove(nPos); if (bDeletingSelectedItem) { - m_xPatternLB->SelectItem(m_xPatternLB->GetItemId(/*Position=*/0)); + m_xPatternPresets->select(0); m_aCtlPreview.Invalidate(); m_xCtlPixel->Invalidate(); } - m_xPatternLB->Resize(); - ChangePatternHdl_Impl(m_xPatternLB.get()); + UpdatePattern(); m_nPatternListState |= ChangeType::MODIFIED; } @@ -514,7 +503,7 @@ IMPL_LINK_NOARG(SvxPatternTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) IMPL_LINK_NOARG(SvxPatternTabPage, ChangeColorHdl_Impl, ColorListBox&, void) { ChangeColor_Impl(); - m_xPatternLB->SetNoSelection(); + m_xPatternPresets->unselect_all(); } void SvxPatternTabPage::ChangeColor_Impl() @@ -544,7 +533,7 @@ void SvxPatternTabPage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint) m_aCtlPreview.Invalidate(); } - m_xPatternLB->SetNoSelection(); + m_xPatternPresets->unselect_all(); } sal_Int32 SvxPatternTabPage::SearchPatternList(std::u16string_view rPatternName) diff --git a/cui/source/util/GetDocumentModel.cxx b/cui/source/util/GetDocumentModel.cxx new file mode 100644 index 000000000000..f4d451776708 --- /dev/null +++ b/cui/source/util/GetDocumentModel.cxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include + +#include +#include +#include + +css::uno::Reference +getDocumentModel(const css::uno::Reference& xContext, + std::u16string_view sDocName) +{ + css::uno::Reference xDesktop = css::frame::theDesktop::get(xContext); + + css::uno::Reference xComponentsAccess + = xDesktop->getComponents(); + css::uno::Reference xComponents + = xComponentsAccess->createEnumeration(); + + while (xComponents->hasMoreElements()) + { + css::uno::Reference xModel(xComponents->nextElement(), + css::uno::UNO_QUERY); + if (xModel.is()) + { + OUString sModelName = ::comphelper::DocumentInfo::getDocumentTitle(xModel); + + if (sModelName == sDocName) + return xModel; + } + } + + return css::uno::Reference(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/uiconfig/ui/aboutconfigdialog.ui b/cui/uiconfig/ui/aboutconfigdialog.ui index 6ea660ee38d8..bd8d959e4478 100644 --- a/cui/uiconfig/ui/aboutconfigdialog.ui +++ b/cui/uiconfig/ui/aboutconfigdialog.ui @@ -328,7 +328,7 @@ edit - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/acorexceptpage.ui b/cui/uiconfig/ui/acorexceptpage.ui index 5fb6c3e2c975..c2c8ff9c53ef 100644 --- a/cui/uiconfig/ui/acorexceptpage.ui +++ b/cui/uiconfig/ui/acorexceptpage.ui @@ -1,5 +1,5 @@ - + @@ -20,34 +20,34 @@ True - False + False True True - 6 + 6 vertical 12 True - False + False True True - 0 - none + 0 + none - + True - False + False + 6 True True - 6 - 12 - 6 + 6 + 12 True - True + True True True True @@ -58,19 +58,19 @@ - 0 - 0 + 0 + 0 Auto_Include True - True - False - True - True - Automatically add to the exception list if autocorrection is immediately undone. + True + False + Automatically add to the exception list if autocorrection is immediately undone. + True + True Adds autocorrected abbreviations to the list of exceptions, if the autocorrection is immediately undone. This feature is only effective when Capitalize first letter of every sentence option is selected in the [T] column on the Options tab of this dialog. @@ -78,25 +78,25 @@ - 1 - 0 + 1 + 0 True - False + False start vertical 6 - start + start _New True False - True - True + True + True True @@ -113,10 +113,10 @@ _Replace - True - True - True - True + True + True + True + True False @@ -129,8 +129,8 @@ _Delete True False - True - True + True + True start True @@ -147,28 +147,28 @@ - 1 - 1 + 1 + 1 True - True + True True True - in + in True - True - True + True + True True True liststore2 - False - 0 - False + False + 0 + False @@ -193,8 +193,8 @@ - 0 - 1 + 0 + 1 @@ -202,7 +202,7 @@ True - False + False Abbreviations (no Subsequent Capital) @@ -219,25 +219,25 @@ True - False + False True True - 0 - none + 0 + none - + True - False + False + 6 True True - 6 - 12 - 6 + 6 + 12 True - True + True start True True @@ -249,19 +249,19 @@ - 0 - 0 + 0 + 0 A_utoInclude True - True - False - True - True - Automatically add to the exception list if autocorrection is immediately undone. + True + False + Automatically add to the exception list if autocorrection is immediately undone. + True + True Adds autocorrected words that start with two capital letters to the list of exceptions, if the autocorrection is immediately undone. This feature is only effective if the Correct TWo INitial CApitals option is selected in the [T] column on the Options tab of this dialog. @@ -269,25 +269,25 @@ - 1 - 0 + 1 + 0 True - False + False start vertical 6 - start + start _New True False - True - True + True + True True @@ -304,10 +304,10 @@ _Replace - True - True - True - True + True + True + True + True False @@ -320,8 +320,8 @@ _Delete True False - True - True + True + True start True @@ -338,28 +338,28 @@ - 1 - 1 + 1 + 1 True - True + True True True - in + in True - True - True + True + True True True liststore1 - False - 0 - False + False + 0 + False @@ -384,8 +384,8 @@ - 0 - 1 + 0 + 1 @@ -393,7 +393,7 @@ True - False + False Words With TWo INitial CApitals or sMALL iNITIAL diff --git a/cui/uiconfig/ui/acoroptionspage.ui b/cui/uiconfig/ui/acoroptionspage.ui index 4bbfadfd75fb..2a859df57a53 100644 --- a/cui/uiconfig/ui/acoroptionspage.ui +++ b/cui/uiconfig/ui/acoroptionspage.ui @@ -1,5 +1,5 @@ - + @@ -18,29 +18,29 @@ True - False + False True True - 6 + 6 vertical True - True + True True True - in + in True - True - True + True + True True True liststore2 - False - 1 - False + False + 1 + False @@ -56,12 +56,6 @@ 0 - - - - - True - 6 diff --git a/cui/uiconfig/ui/acorreplacepage.ui b/cui/uiconfig/ui/acorreplacepage.ui index 48cd8bcbec19..ec84534549c2 100644 --- a/cui/uiconfig/ui/acorreplacepage.ui +++ b/cui/uiconfig/ui/acorreplacepage.ui @@ -21,6 +21,160 @@ 6 6 12 + + + True + False + Repla_ce + True + origtext + 0 + + + + + + 0 + 0 + + + + + True + False + _With + True + newtext + 0 + + + + + + 1 + 0 + + + + + True + True + True + True + 25 + True + + + Enter the word, abbreviation or word part that you want to replace while you type. Wildcard character sequence .* in the end of word results the replacement of the word before arbitrary suffixes, too. Wildcard character sequence .* before the word results the replacement after arbitrary prefixes, too. For example, the pattern "i18n.*" with the replacement text "internationalization" finds and replaces "i18ns" with "internationalizations", or the pattern ".*..." with the replacement text "…" finds and replaces three dots in "word..." with the typographically correct precomposed Unicode horizontal ellipsis ("word…"). + + + + + 0 + 1 + + + + + True + True + True + True + 25 + True + + + Enter the replacement text, graphic, frame, or OLE object that you want to replace the text in the Replace box. If you have selected text, a graphic, a frame, or an OLE object in your document, the relevant information is already entered here. + + + + + 1 + 1 + + + + + _Text only + True + True + False + True + True + + + Saves the entry in the With box without formatting. When the replacement is made, the text uses the same format as the document text. + + + + + 2 + 1 + + + + + True + True + True + True + external + in + + + True + True + True + True + True + liststore1 + False + 0 + True + False + + + + + + True + 6 + fixed + + + + 0 + + + + + + + True + 6 + fixed + + + + 1 + + + + + + + Lists the entries for automatically replacing words, abbreviations or word parts while you type. To add an entry, enter text in the Replace and With boxes, and then click New. To edit an entry, select it, change the text in the With box, and then click Replace. To delete an entry, select it, and then click Delete. + + + + + + + 0 + 2 + 2 + + True @@ -92,160 +246,6 @@ 2 - - - True - True - True - True - external - in - - - True - True - True - True - True - liststore1 - False - 0 - True - False - - - - - - True - 6 - fixed - - - - 0 - - - - - - - True - 6 - fixed - - - - 1 - - - - - - - Lists the entries for automatically replacing words, abbreviations or word parts while you type. To add an entry, enter text in the Replace and With boxes, and then click New. To edit an entry, select it, change the text in the With box, and then click Replace. To delete an entry, select it, and then click Delete. - - - - - - - 0 - 2 - 2 - - - - - True - True - True - True - 25 - True - - - Enter the replacement text, graphic, frame, or OLE object that you want to replace the text in the Replace box. If you have selected text, a graphic, a frame, or an OLE object in your document, the relevant information is already entered here. - - - - - 1 - 1 - - - - - True - True - True - True - 25 - True - - - Enter the word, abbreviation or word part that you want to replace while you type. Wildcard character sequence .* in the end of word results the replacement of the word before arbitrary suffixes, too. Wildcard character sequence .* before the word results the replacement after arbitrary prefixes, too. For example, the pattern "i18n.*" with the replacement text "internationalization" finds and replaces "i18ns" with "internationalizations", or the pattern ".*..." with the replacement text "…" finds and replaces three dots in "word..." with the typographically correct precomposed Unicode horizontal ellipsis ("word…"). - - - - - 0 - 1 - - - - - True - False - Repla_ce - True - origtext - 0 - - - - - - 0 - 0 - - - - - True - False - _With - True - newtext - 0 - - - - - - 1 - 0 - - - - - _Text only - True - True - False - True - True - - - Saves the entry in the With box without formatting. When the replacement is made, the text uses the same format as the document text. - - - - - 2 - 1 - - diff --git a/cui/uiconfig/ui/appearance.ui b/cui/uiconfig/ui/appearance.ui index 2c1d1a653092..3c89601df55d 100644 --- a/cui/uiconfig/ui/appearance.ui +++ b/cui/uiconfig/ui/appearance.ui @@ -23,230 +23,6 @@ 6 12 24 - - - True - False - 0 - none - - - True - False - 12 - 6 - vertical - 3 - - - True - False - start - 3 - - - 200 - True - False - - Automatic - Sifr - Breeze - - - - Select an icon theme for the application. - - - - - False - True - 0 - - - - - True - True - True - Add more icons. - start - moreicons_image - True - - - Click to select and download more icons from the extensions website. - - - - - False - True - 1 - - - - - False - True - 0 - - - - - - True - False - start - start - 3 - 3 - - - True - False - start - Toolbar - - - - - - 0 - 0 - - - - - True - False - start - Sidebar - - - - - - 0 - 1 - - - - - True - False - start - Notebookbar - - - - - - 0 - 2 - - - - - True - False - - Automatic - Small - Large - Extra Large - - - - - - - Select the icon theme for the toolbar. - - - - - 1 - 0 - - - - - True - False - - Automatic - Small - Large - - - - - - - Select the icon theme for the sidebar. - - - - - 1 - 1 - - - - - True - False - - Automatic - Small - Large - - - - - - - Select the icon theme for the notebookbar. - - - - - 1 - 2 - - - - - False - True - 1 - - - - - - - True - False - Icons - - - - - - Controls to change icon theme and sizes for various user interfaces. - - - - - - - 0 - 2 - - True @@ -546,6 +322,230 @@ 1 + + + True + False + 0 + none + + + True + False + 12 + 6 + vertical + 3 + + + True + False + start + 3 + + + 200 + True + False + + Automatic + Sifr + Breeze + + + + Select an icon theme for the application. + + + + + False + True + 0 + + + + + True + True + True + Add more icons. + start + moreicons_image + True + + + Click to select and download more icons from the extensions website. + + + + + False + True + 1 + + + + + False + True + 0 + + + + + + True + False + start + start + 3 + 3 + + + True + False + start + Toolbar + + + + + + 0 + 0 + + + + + True + False + + Automatic + Small + Large + Extra Large + + + + + + + Select the icon theme for the toolbar. + + + + + 1 + 0 + + + + + True + False + start + Sidebar + + + + + + 0 + 1 + + + + + True + False + + Automatic + Small + Large + + + + + + + Select the icon theme for the sidebar. + + + + + 1 + 1 + + + + + True + False + start + Notebookbar + + + + + + 0 + 2 + + + + + True + False + + Automatic + Small + Large + + + + + + + Select the icon theme for the notebookbar. + + + + + 1 + 2 + + + + + False + True + 1 + + + + + + + True + False + Icons + + + + + + Controls to change icon theme and sizes for various user interfaces. + + + + + + + 0 + 2 + + True @@ -560,6 +560,21 @@ start 12 6 + + + True + False + Tab position: + 0 + + + + + + 0 + 0 + + Vertical at the side @@ -578,21 +593,6 @@ 0 - - - True - False - Tab position: - 0 - - - - - - 0 - 0 - - Horizontal on top diff --git a/cui/uiconfig/ui/applyautofmtpage.ui b/cui/uiconfig/ui/applyautofmtpage.ui index 211ddb69a572..5474b7d49e38 100644 --- a/cui/uiconfig/ui/applyautofmtpage.ui +++ b/cui/uiconfig/ui/applyautofmtpage.ui @@ -1,5 +1,5 @@ - + @@ -8,8 +8,6 @@ - - @@ -18,47 +16,43 @@ - - - - True - False + False True True - 6 + 6 vertical - + True - False + False True True - 12 + 12 - + True - False - 6 - 12 + False + 6 + 12 _Edit... True False - True - True + True + True center - True + True Modifies the selected AutoCorrect option. @@ -66,72 +60,72 @@ - 0 - 0 + 0 + 0 2 True - False + False [M]: Replace while modifying existing text 0 - + - 1 - 0 + 1 + 0 True - False + False [T]: AutoCorrect while typing 0 - + - 1 - 1 + 1 + 1 - 0 - 1 + 0 + 1 - + True - False + False True True - True + True True - True + True True True - in + in True - True - True + True + True True True liststore1 - 0 - False + 0 + False @@ -144,17 +138,10 @@ - 5 + 4 0 - - - - 6 - 1 - - @@ -166,8 +153,8 @@ - 7 - 2 + 5 + 1 @@ -179,7 +166,7 @@ - 3 + 2 @@ -188,15 +175,15 @@ - 0 - 0 + 0 + 0 2 - 0 - 0 + 0 + 0 diff --git a/cui/uiconfig/ui/applylocalizedpage.ui b/cui/uiconfig/ui/applylocalizedpage.ui index 1d2bca87c99e..03dd70c47e79 100644 --- a/cui/uiconfig/ui/applylocalizedpage.ui +++ b/cui/uiconfig/ui/applylocalizedpage.ui @@ -1,5 +1,5 @@ - + @@ -8,8 +8,6 @@ - - @@ -18,14 +16,10 @@ - - - - @@ -44,44 +38,44 @@ True - False + False True True - 6 + 6 vertical - + True - False + False True True - 12 + 12 - + True - False + False True True - True + True True - True + True True True - in + in True - True - True + True + True True True liststore1 - 0 - False + 0 + False @@ -94,17 +88,10 @@ - 5 + 4 0 - - - - 6 - 1 - - @@ -116,8 +103,8 @@ - 7 - 2 + 5 + 1 @@ -129,7 +116,7 @@ - 3 + 2 @@ -143,29 +130,29 @@ - 0 - 0 + 0 + 0 2 True - True + True True True - in + in True - True - True + True + True True True liststore2 - False - 0 - False + False + 0 + False @@ -181,12 +168,6 @@ 0 - - - - - True - 6 @@ -204,46 +185,46 @@ - 0 - 1 + 0 + 1 2 - 0 - 0 + 0 + 0 - + True - False - 12 - True + False + 12 + True True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 6 + 12 Repla_ce True - True - False - True - True + True + False + True + True Automatically replaces the default system symbol for the given type of quotation marks with the special character that you specify. @@ -251,38 +232,38 @@ - 0 - 0 + 0 + 0 2 True - False + False 12 _Start quote: - True - startsingle + True + startsingle 0 - 0 - 1 + 0 + 1 - + True - False - 12 + False + 12 ' True - True - True + True + True Start quote of single quotes @@ -291,75 +272,55 @@ - 0 - 0 + 0 + 0 True - False + False Default 0 - 1 - 0 + 1 + 0 - 1 - 1 - - - - - _Default - True - True - True - start - True - - - Single quotes default - Resets the quotation marks to the default symbols. - - - - - 1 - 3 + 1 + 1 True - False + False 12 _End quote: - True - endsingle + True + endsingle 0 - 0 - 2 + 0 + 2 - + True - False - 12 + False + 12 ' True - True - True + True + True End quote of single quotes @@ -368,26 +329,46 @@ - 0 - 0 + 0 + 0 True - False + False Default 0 - 1 - 0 + 1 + 0 - 1 - 2 + 1 + 2 + + + + + _Default + True + True + True + start + True + + + Single quotes default + Resets the quotation marks to the default symbols. + + + + + 1 + 3 @@ -398,7 +379,7 @@ True - False + False Single Quotes @@ -407,32 +388,32 @@ - 0 - 0 + 0 + 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 6 + 12 Repla_ce True - True - False - True - True + True + False + True + True Automatically replaces the default system symbol for the given type of quotation marks with the special character that you specify. @@ -440,38 +421,38 @@ - 0 - 0 + 0 + 0 2 True - False + False 12 _Start quote: - True - startdouble + True + startdouble 0 - 0 - 1 + 0 + 1 - + True - False - 12 + False + 12 " True - True - True + True + True Start quote of double quotes @@ -480,75 +461,55 @@ - 0 - 0 + 0 + 0 True - False + False Default 0 - 1 - 0 + 1 + 0 - 1 - 1 - - - - - _Default - True - True - True - start - True - - - Double quotes default - Resets the quotation marks to the default symbols. - - - - - 1 - 3 + 1 + 1 True - False + False 12 _End quote: - True - enddouble + True + enddouble 0 - 0 - 2 + 0 + 2 - + True - False - 12 + False + 12 " True - True - True + True + True End quote of double quotes @@ -557,26 +518,46 @@ - 0 - 0 + 0 + 0 True - False + False Default 0 - 1 - 0 + 1 + 0 - 1 - 2 + 1 + 2 + + + + + _Default + True + True + True + start + True + + + Double quotes default + Resets the quotation marks to the default symbols. + + + + + 1 + 3 @@ -587,7 +568,7 @@ True - False + False Double Quotes @@ -596,14 +577,14 @@ - 1 - 0 + 1 + 0 - 0 - 1 + 0 + 1 diff --git a/cui/uiconfig/ui/areadialog.ui b/cui/uiconfig/ui/areadialog.ui index a57d1499173a..ca14a617b344 100644 --- a/cui/uiconfig/ui/areadialog.ui +++ b/cui/uiconfig/ui/areadialog.ui @@ -106,7 +106,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/autocorrectdialog.ui b/cui/uiconfig/ui/autocorrectdialog.ui index 509c4840d39c..ec9b1a8866e2 100644 --- a/cui/uiconfig/ui/autocorrectdialog.ui +++ b/cui/uiconfig/ui/autocorrectdialog.ui @@ -177,7 +177,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/borderareatransparencydialog.ui b/cui/uiconfig/ui/borderareatransparencydialog.ui index cf51a6028875..8be35bc4f338 100644 --- a/cui/uiconfig/ui/borderareatransparencydialog.ui +++ b/cui/uiconfig/ui/borderareatransparencydialog.ui @@ -108,7 +108,7 @@ ok cancel help - reset + reset diff --git a/cui/uiconfig/ui/borderbackgrounddialog.ui b/cui/uiconfig/ui/borderbackgrounddialog.ui index 2052ea140162..8492ddbcdafe 100644 --- a/cui/uiconfig/ui/borderbackgrounddialog.ui +++ b/cui/uiconfig/ui/borderbackgrounddialog.ui @@ -108,7 +108,7 @@ ok cancel help - reset + reset diff --git a/cui/uiconfig/ui/bulletandposition.ui b/cui/uiconfig/ui/bulletandposition.ui index 1912455577b0..ede359b05965 100644 --- a/cui/uiconfig/ui/bulletandposition.ui +++ b/cui/uiconfig/ui/bulletandposition.ui @@ -1153,7 +1153,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/calloutdialog.ui b/cui/uiconfig/ui/calloutdialog.ui index d64853035807..803d5790c75e 100644 --- a/cui/uiconfig/ui/calloutdialog.ui +++ b/cui/uiconfig/ui/calloutdialog.ui @@ -104,7 +104,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/charnamepage.ui b/cui/uiconfig/ui/charnamepage.ui index 2f2e11942b62..20a767c2f732 100644 --- a/cui/uiconfig/ui/charnamepage.ui +++ b/cui/uiconfig/ui/charnamepage.ui @@ -112,49 +112,62 @@ - + True - False - Language: - True - cbWestLanguage - 0 + True + True + True + True - 0 - 4 + 1 + 0 + 2 - + True False True - liststore5 - True - 0 - 1 + True + in - - - 2 - - - - - True - False - - - - - Sets the language that the spellchecker uses for the selected text or the text that you type. Available language modules have a check mark in front of them. + + True + True + True + True + liststore1 + False + False + 0 + False + + + + + + + + + 0 + + + + + + + Select the font that you want to apply. + + 1 - 4 + 1 + 2 @@ -231,6 +244,52 @@ 2 + + + True + False + Language: + True + cbWestLanguage + 0 + + + 0 + 4 + + + + + True + False + True + liststore5 + True + 0 + 1 + + + + 2 + + + + + True + False + + + + + Sets the language that the spellchecker uses for the selected text or the text that you type. Available language modules have a check mark in front of them. + + + + + 1 + 4 + + Features... @@ -244,65 +303,6 @@ 4 - - - True - False - True - True - in - - - True - True - True - True - liststore1 - False - False - 0 - False - - - - - - - - - 0 - - - - - - - Select the font that you want to apply. - - - - - - - 1 - 1 - 2 - - - - - True - True - True - True - True - - - 1 - 0 - 2 - - True @@ -364,107 +364,6 @@ True 6 6 - - - True - False - Size: - True - cbCJKSize - 0 - - - 0 - 3 - - - - - True - False - Language: - True - cbCJKLanguage - 0 - - - 0 - 4 - - - - - True - False - True - - - True - False - - - - - Select the formatting that you want to apply. - - - - - 1 - 2 - 2 - - - - - True - False - True - - - True - False - - - - - Enter or select the font size that you want to apply. For scalable fonts, you can also enter decimal values. - - - - - 1 - 3 - 2 - - - - - True - False - Style: - True - cbCJKStyle - 0 - - - 0 - 2 - - - - - Features... - True - True - True - end - - - 2 - 4 - - True @@ -479,6 +378,20 @@ 0 + + + True + True + True + True + True + + + 1 + 0 + 2 + + True @@ -525,19 +438,93 @@ - + True - True - True - True - True + False + Style: + True + cbCJKStyle + 0 + + + 0 + 2 + + + + + True + False + True + + + True + False + + + + + Select the formatting that you want to apply. + + 1 - 0 + 2 2 + + + True + False + Size: + True + cbCJKSize + 0 + + + 0 + 3 + + + + + True + False + True + + + True + False + + + + + Enter or select the font size that you want to apply. For scalable fonts, you can also enter decimal values. + + + + + 1 + 3 + 2 + + + + + True + False + Language: + True + cbCJKLanguage + 0 + + + 0 + 4 + + True @@ -570,6 +557,19 @@ 4 + + + Features... + True + True + True + end + + + 2 + 4 + + True @@ -634,136 +634,17 @@ - - True - False - Style: - True - cbCTLStyle - 0 - - - 0 - 2 - - - - - True - False - Size: - True - cbCTLSize - 0 - - - 0 - 3 - - - - - True - False - True - - - True - False - - - - - Select the formatting that you want to apply. - - - - - 1 - 2 - 2 - - - - - True - False - True - - - True - False - - - - - Enter or select the font size that you want to apply. For scalable fonts, you can also enter decimal values. - - - - - 1 - 3 - 2 - - - - - True - False - Language: - True - cbCTLLanguage - 0 - - - 0 - 4 - - - - - Features... + True True - True - end - - - 2 - 4 - - - - - True - False True - liststore7 - True - 0 - 1 - - - - 2 - - - - - True - False - - - - - Sets the language that the spellchecker uses for the selected text or the text that you type. Available language modules have a check mark in front of them. - - + True + True 1 - 4 + 0 + 2 @@ -812,19 +693,138 @@ - + True - True - True - True - True + False + Style: + True + cbCTLStyle + 0 + + + 0 + 2 + + + + + True + False + True + + + True + False + + + + + Select the formatting that you want to apply. + + 1 - 0 + 2 2 + + + True + False + Size: + True + cbCTLSize + 0 + + + 0 + 3 + + + + + True + False + True + + + True + False + + + + + Enter or select the font size that you want to apply. For scalable fonts, you can also enter decimal values. + + + + + 1 + 3 + 2 + + + + + True + False + Language: + True + cbCTLLanguage + 0 + + + 0 + 4 + + + + + True + False + True + liststore7 + True + 0 + 1 + + + + 2 + + + + + True + False + + + + + Sets the language that the spellchecker uses for the selected text or the text that you type. Available language modules have a check mark in front of them. + + + + + 1 + 4 + + + + + Features... + True + True + True + end + + + 2 + 4 + + True diff --git a/cui/uiconfig/ui/colorpage.ui b/cui/uiconfig/ui/colorpage.ui index 672b60ea76e3..bd350cca6700 100644 --- a/cui/uiconfig/ui/colorpage.ui +++ b/cui/uiconfig/ui/colorpage.ui @@ -37,6 +37,16 @@ 1 10 + + + + + + + + + + True False @@ -47,6 +57,16 @@ False res/sc10350.png + + + + + + + + + + True False @@ -59,6 +79,7 @@ True False True + True 0 none @@ -67,9 +88,9 @@ True False start - start 12 6 + True 6 @@ -126,6 +147,43 @@ 0 + + + True + False + True + vertical + + + True + True + never + in + + + True + True + 6 + coloriconviewmodel + 12 + 0 + 2 + True + + + + + True + True + 1 + + + + + 0 + 1 + + True @@ -139,7 +197,7 @@ False Recent Colors True - recentcolorset + recentcoloriconview 0 @@ -149,17 +207,20 @@ - + True True - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK - True - True + 6 + recentcoloriconviewmodel + 12 + 0 + 2 + True - False + True True - 1 + 2 @@ -176,6 +237,22 @@ 6 3 True + + + True + False + 3 + Custom Palette + True + coloriconview + 0 + + + 0 + 0 + 2 + + _Add @@ -189,6 +266,23 @@ 1 + + + Delete + True + True + True + + + Deletes the selected element or elements without requiring confirmation. + + + + + 1 + 1 + + RGB @@ -217,86 +311,12 @@ 2 - - - Delete - True - True - True - - - Deletes the selected element or elements without requiring confirmation. - - - - - 1 - 1 - - - - - True - False - 3 - Custom Palette - True - colorset - 0 - - - 0 - 0 - 2 - - 0 3 - - - True - False - start - vertical - - - True - True - never - never - in - - - True - False - - - True - True - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK - True - True - - - - - - - False - False - 0 - - - - - 0 - 1 - - @@ -311,7 +331,7 @@ - False + True True 0 @@ -390,16 +410,29 @@ 6 6 - + True False - B + R True - B_preset + R_preset 0 - 2 + 0 + + + + + True + True + False + 3 + True + + + 1 + 0 @@ -416,16 +449,42 @@ - + + True + True + False + 3 + True + + + 1 + 1 + + + + True False - R + B True - R_preset + B_preset 0 - 0 + 2 + + + + + True + True + False + 3 + True + + + 1 + 2 @@ -454,45 +513,6 @@ 3 - - - True - True - False - 3 - True - - - 1 - 0 - - - - - True - True - False - 3 - True - - - 1 - 1 - - - - - True - True - False - 3 - True - - - 1 - 2 - - False @@ -522,32 +542,6 @@ 0 - - - True - False - _K - True - K_preset - - - 0 - 3 - - - - - True - False - _Y - True - Y_preset - - - 0 - 2 - - True @@ -561,6 +555,19 @@ 0 + + + True + False + _M + True + M_preset + + + 0 + 1 + + True @@ -574,6 +581,19 @@ 1 + + + True + False + _Y + True + Y_preset + + + 0 + 2 + + True @@ -587,6 +607,19 @@ 2 + + + True + False + _K + True + K_preset + + + 0 + 3 + + True @@ -600,19 +633,6 @@ 3 - - - True - False - _M - True - M_preset - - - 0 - 1 - - False @@ -713,17 +733,16 @@ 6 6 - + True - True - Blue - True - True - adjustment7 + False + _R + True + R_custom - 1 - 2 + 0 + 0 @@ -740,19 +759,6 @@ 0 - - - True - False - _B - True - B_custom - - - 0 - 2 - - True @@ -766,19 +772,6 @@ 1 - - - True - False - _R - True - R_custom - - - 0 - 0 - - True @@ -793,6 +786,33 @@ 1 + + + True + False + _B + True + B_custom + + + 0 + 2 + + + + + True + True + Blue + True + True + adjustment7 + + + 1 + 2 + + True @@ -850,32 +870,6 @@ 0 - - - True - False - _M - True - M_custom - - - 0 - 1 - - - - - True - False - _K - True - K_custom - - - 0 - 3 - - True @@ -890,16 +884,29 @@ - + + True + False + _M + True + M_custom + + + 0 + 1 + + + + True True True True - adjustment5 + adjustment3 1 - 3 + 1 @@ -929,16 +936,29 @@ - + + True + False + _K + True + K_custom + + + 0 + 3 + + + + True True True True - adjustment3 + adjustment5 1 - 1 + 3 diff --git a/cui/uiconfig/ui/connpooloptions.ui b/cui/uiconfig/ui/connpooloptions.ui index 4c1966da81a8..4ff8fc587843 100644 --- a/cui/uiconfig/ui/connpooloptions.ui +++ b/cui/uiconfig/ui/connpooloptions.ui @@ -9,7 +9,7 @@ 1 10 - + diff --git a/cui/uiconfig/ui/customizedialog.ui b/cui/uiconfig/ui/customizedialog.ui index 1d17004f4a91..da427adf25f8 100644 --- a/cui/uiconfig/ui/customizedialog.ui +++ b/cui/uiconfig/ui/customizedialog.ui @@ -108,7 +108,7 @@ ok cancel help - reset + reset diff --git a/cui/uiconfig/ui/databaselinkdialog.ui b/cui/uiconfig/ui/databaselinkdialog.ui index ec14bdcc3662..d3521baeb455 100644 --- a/cui/uiconfig/ui/databaselinkdialog.ui +++ b/cui/uiconfig/ui/databaselinkdialog.ui @@ -1,32 +1,32 @@ - + - False - 6 + False + 6 Create Database Link True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -39,8 +39,8 @@ _Cancel True - True - True + True + True True @@ -53,8 +53,8 @@ _Help True - True - True + True + True True @@ -68,32 +68,32 @@ False True - end + end 0 - + True - False + False True - 12 + 12 - + True - False + False True - 6 - 12 + 6 + 12 Browse... True - True - True - True + True + True + True Opens a file dialog where you can select the database file. @@ -101,79 +101,79 @@ - 1 - 1 + 1 + 1 True - False + False _Database file: - True - url + True + url 0 - 0 - 0 + 0 + 0 2 True - False + False True - True + True True - True + True + True True - True - 0 - 1 + 0 + 1 - 0 - 0 + 0 + 0 - + True - False + False True - 6 + 6 True - False + False Registered _name: - True - name + True + name 0 - 0 - 0 + 0 + 0 True - True + True True - True - 52 + True + 52 True @@ -182,25 +182,25 @@ - 0 - 1 + 0 + 1 - 0 - 1 + 0 + 1 - False - True + False + True Edit Database Link - 0 - 2 + 0 + 2 @@ -217,9 +217,6 @@ cancel help - - - Creates or edits an entry in the Databases tab page. diff --git a/cui/uiconfig/ui/dbregisterpage.ui b/cui/uiconfig/ui/dbregisterpage.ui index d6f07a66f6a9..f0f6050cedcd 100644 --- a/cui/uiconfig/ui/dbregisterpage.ui +++ b/cui/uiconfig/ui/dbregisterpage.ui @@ -1,8 +1,8 @@ - + - + @@ -17,46 +17,46 @@ True - False + False True True - 6 - 12 + 6 + 12 True - False + False True True - 0 - none + 0 + none True - False + False + 12 + 6 True True vertical 12 - 12 - 6 True - True + True True True - in + in True - True - True + True + True True True liststore3 - 0 - False + 0 + False @@ -67,7 +67,7 @@ Registered name True True - True + True @@ -108,17 +108,17 @@ True - False + False end 3 - end + end _New... True - True - True - True + True + True + True Opens the Database Link dialog to create a new entry. @@ -135,9 +135,9 @@ _Delete True - True - True - True + True + True + True Removes the selected entry from the list. @@ -154,9 +154,9 @@ _Edit... True - True - True - True + True + True + True Opens the Database Link dialog to edit the selected entry. @@ -181,7 +181,7 @@ True - False + False Registered Databases @@ -190,8 +190,8 @@ - 0 - 0 + 0 + 0 diff --git a/cui/uiconfig/ui/dimensionlinestabpage.ui b/cui/uiconfig/ui/dimensionlinestabpage.ui index 266f05a31d91..d3196ebc7386 100644 --- a/cui/uiconfig/ui/dimensionlinestabpage.ui +++ b/cui/uiconfig/ui/dimensionlinestabpage.ui @@ -58,7 +58,7 @@ 0 none - + True False @@ -81,6 +81,25 @@ 0 + + + True + True + True + True + adjustment1 + 2 + + + Specifies the distance between the dimension line and the baseline (line distance = 0). + + + + + 1 + 0 + + True @@ -95,6 +114,25 @@ 1 + + + True + True + True + True + adjustment3 + 2 + + + Specifies the length of the right and left guides starting at the dimension line. Positive values extend the guides above the dimension line and negative values extend the guides below the dimension line. + + + + + 1 + 1 + + True @@ -109,6 +147,25 @@ 2 + + + True + True + True + True + adjustment4 + 2 + + + Specifies the length of the left and right guides starting at the baseline (line distance = 0). Positive values extend the guides above the baseline and negative values extend the guides below the baseline. + + + + + 1 + 2 + + True @@ -123,6 +180,25 @@ 3 + + + True + True + True + True + adjustment5 + 2 + + + Specifies the length of the left guide starting at the dimension line. Positive values extend the guide below the dimension line and negative values extend the guide above the dimension line. + + + + + 1 + 3 + + True @@ -138,17 +214,22 @@ - + True - False - Decimal _places: - True - MTR_FLD_DECIMALPLACES - 0 + True + True + True + adjustment6 + 2 + + + Specifies the length of the right guide starting at the dimension line. Positive values extend the guide below the dimension line and negative values extend the guide above the dimension line. + + - 0 - 6 + 1 + 4 @@ -174,98 +255,17 @@ - + True - True - True - True - adjustment1 - 2 - - - Specifies the distance between the dimension line and the baseline (line distance = 0). - - + False + Decimal _places: + True + MTR_FLD_DECIMALPLACES + 0 - 1 - 0 - - - - - True - True - True - True - adjustment3 - 2 - - - Specifies the length of the right and left guides starting at the dimension line. Positive values extend the guides above the dimension line and negative values extend the guides below the dimension line. - - - - - 1 - 1 - - - - - True - True - True - True - adjustment4 - 2 - - - Specifies the length of the left and right guides starting at the baseline (line distance = 0). Positive values extend the guides above the baseline and negative values extend the guides below the baseline. - - - - - 1 - 2 - - - - - True - True - True - True - adjustment5 - 2 - - - Specifies the length of the left guide starting at the dimension line. Positive values extend the guide below the dimension line and negative values extend the guide above the dimension line. - - - - - 1 - 3 - - - - - True - True - True - True - adjustment6 - 2 - - - Specifies the length of the right guide starting at the dimension line. Positive values extend the guide below the dimension line and negative values extend the guide above the dimension line. - - - - - 1 - 4 + 0 + 6 @@ -286,6 +286,28 @@ 6 + + + _Automatic + True + True + False + 12 + True + True + True + + + Automatically adapts the number of displayed decimal places based on the precision of the measured value. + + + + + 0 + 7 + 2 + + diff --git a/cui/uiconfig/ui/editmodulesdialog.ui b/cui/uiconfig/ui/editmodulesdialog.ui index 8e14b3fd9337..c350e697649b 100644 --- a/cui/uiconfig/ui/editmodulesdialog.ui +++ b/cui/uiconfig/ui/editmodulesdialog.ui @@ -291,13 +291,6 @@ 0 - - - - - True - 6 - 0.5 diff --git a/cui/uiconfig/ui/effectspage.ui b/cui/uiconfig/ui/effectspage.ui index 3b61fae6dfe1..cbeeaee73730 100644 --- a/cui/uiconfig/ui/effectspage.ui +++ b/cui/uiconfig/ui/effectspage.ui @@ -16,553 +16,6 @@ 6 6 12 - - - True - False - end - 12 - 12 - 6 - True - True - never - never - in - - - True - False - - - True - False - - - Preview - - - - - - - - - 0 - 3 - - - - - True - False - 0 - none - - - - True - False - start - 12 - 6 - 6 - 12 - - - True - False - _Case: - True - effectslb - 0 - - - 0 - 0 - - - - - True - False - R_elief: - True - relieflb - 0 - - - 0 - 1 - - - - - True - False - - (Without) - UPPERCASE - lowercase - Capitalize Every Word - Small capitals - - - - Select the font effects that you want to apply. - - - - - 1 - 0 - - - - - True - False - - (Without) - Embossed - Engraved - - - - Select a relief effect to apply to the selected text. The embossed relief makes the characters appear as if they are raised above the page. The engraved relief makes the characters appear as if they are pressed into the page. - - - - - 1 - 1 - - - - - True - False - - (Without) - Dot - Circle - Disc - Accent - - - - Select a character to display over or below the entire length of the selected text. - - - - - 1 - 2 - - - - - True - False - - Above text - Below text - - - - Specify where to display the emphasis marks. - - - - - 1 - 3 - - - - - True - False - _Position: - True - positionlb - 0 - - - 0 - 3 - - - - - True - False - Emphasis _mark: - True - emphasislb - 0 - - - 0 - 2 - - - - - Outli_ne - True - True - False - True - True - True - - - Displays the outline of the selected characters. This effect does not work with every font. - - - - - 2 - 1 - - - - - Shado_w - True - True - False - True - True - True - - - Adds a shadow that casts below and to the right of the selected characters. - - - - - 3 - 1 - - - - - Hi_dden - True - True - False - True - True - True - - - Hides the selected characters. - - - - - 3 - 0 - - - - - - - - - - - - - - - - - - - - - - True - False - Effects - 0 - - - - - - - - 0 - 2 - - - - - True - False - 0 - none - - - - True - False - start - 12 - 6 - 6 - 12 - - - True - False - O_verlining: - True - overlinelb - 0 - - - 0 - 0 - - - - - True - False - Stri_kethrough: - True - strikeoutlb - 0 - - - 0 - 1 - - - - - True - False - _Underlining: - True - underlinelb - 0 - - - 0 - 2 - - - - - True - False - - (Without) - Single - Double - Bold - Dotted - Dotted (Bold) - Dash - Dash (Bold) - Long Dash - Long Dash (Bold) - Dot Dash - Dot Dash (Bold) - Dot Dot Dash - Dot Dot Dash (Bold) - Wave - Wave (Bold) - Double Wave - - - - Select the overlining style that you want to apply. To apply the overlining to words only, select the Individual Words box. - - - - - 1 - 0 - - - - - True - False - - (Without) - Single - Double - Bold - Dotted - Dotted (Bold) - Dash - Dash (Bold) - Long Dash - Long Dash (Bold) - Dot Dash - Dot Dash (Bold) - Dot Dot Dash - Dot Dot Dash (Bold) - Wave - Wave (Bold) - Double Wave - - - - Select the underlining style that you want to apply. To apply the underlining to words only, select the Individual Words box. - - - - - 1 - 2 - - - - - True - False - - (Without) - Single - Double - Bold - With / - With X - - - - Select a strikethrough style for the selected text. - - - - - 1 - 1 - - - - - True - True - False - start - 0 - True - - - - - - - Select the color for the underlining. - - - - - 2 - 2 - - - - - True - True - False - start - 0 - True - - - - - - - Select the color for the overlining. - - - - - 2 - 0 - - - - - _Individual words - True - True - False - True - True - - - Applies the selected effect only to words and ignores spaces. - - - - - 1 - 3 - - - - - True - False - True - overlinecolorlb - 0 - - - 2 - 3 - - - - - True - False - True - underlinecolorlb - 0 - - - 2 - 1 - - - - - - - - - - True - False - Text Decoration - 0 - - - - - - - - 0 - 1 - - True @@ -614,19 +67,6 @@ 0 - - - False - Accessibility option "Use automatic font color for screen display" is active. Font color attributes are not currently used to display text. - True - 50 - 0 - - - 1 - 1 - - True @@ -654,6 +94,19 @@ 0 + + + False + Accessibility option "Use automatic font color for screen display" is active. Font color attributes are not currently used to display text. + True + 50 + 0 + + + 1 + 1 + + @@ -682,6 +135,554 @@ 0 + + + True + False + 0 + none + + + + True + False + start + 12 + 6 + 6 + 12 + + + True + False + O_verlining: + True + overlinelb + 0 + + + 0 + 0 + + + + + True + False + + (Without) + Single + Double + Bold + Dotted + Dotted (Bold) + Dash + Dash (Bold) + Long Dash + Long Dash (Bold) + Dot Dash + Dot Dash (Bold) + Dot Dot Dash + Dot Dot Dash (Bold) + Wave + Wave (Bold) + Double Wave + + + + Select the overlining style that you want to apply. To apply the overlining to words only, select the Individual Words box. + + + + + 1 + 0 + + + + + True + True + False + start + 0 + True + + + + + + + Select the color for the overlining. + + + + + 2 + 0 + + + + + True + False + Stri_kethrough: + True + strikeoutlb + 0 + + + 0 + 1 + + + + + True + False + + (Without) + Single + Double + Bold + With / + With X + + + + Select a strikethrough style for the selected text. + + + + + 1 + 1 + + + + + True + False + True + underlinecolorlb + 0 + + + 2 + 1 + + + + + True + False + _Underlining: + True + underlinelb + 0 + + + 0 + 2 + + + + + True + False + + (Without) + Single + Double + Bold + Dotted + Dotted (Bold) + Dash + Dash (Bold) + Long Dash + Long Dash (Bold) + Dot Dash + Dot Dash (Bold) + Dot Dot Dash + Dot Dot Dash (Bold) + Wave + Wave (Bold) + Double Wave + + + + Select the underlining style that you want to apply. To apply the underlining to words only, select the Individual Words box. + + + + + 1 + 2 + + + + + True + True + False + start + 0 + True + + + + + + + Select the color for the underlining. + + + + + 2 + 2 + + + + + _Individual words + True + True + False + True + True + + + Applies the selected effect only to words and ignores spaces. + + + + + 1 + 3 + + + + + True + False + True + overlinecolorlb + 0 + + + 2 + 3 + + + + + + + + + + True + False + Text Decoration + 0 + + + + + + + + 0 + 1 + + + + + True + False + 0 + none + + + + True + False + start + 12 + 6 + 6 + 12 + + + True + False + _Case: + True + effectslb + 0 + + + 0 + 0 + + + + + True + False + + (Without) + UPPERCASE + lowercase + Capitalize Every Word + Small capitals + + + + Select the font effects that you want to apply. + + + + + 1 + 0 + + + + + Hi_dden + True + True + False + True + True + True + + + Hides the selected characters. + + + + + 3 + 0 + + + + + True + False + R_elief: + True + relieflb + 0 + + + 0 + 1 + + + + + True + False + + (Without) + Embossed + Engraved + + + + Select a relief effect to apply to the selected text. The embossed relief makes the characters appear as if they are raised above the page. The engraved relief makes the characters appear as if they are pressed into the page. + + + + + 1 + 1 + + + + + + Outli_ne + True + True + False + True + True + True + + + Displays the outline of the selected characters. This effect does not work with every font. + + + + + 2 + 1 + + + + + Shado_w + True + True + False + True + True + True + + + Adds a shadow that casts below and to the right of the selected characters. + + + + + 3 + 1 + + + + + True + False + Emphasis _mark: + True + emphasislb + 0 + + + 0 + 2 + + + + + True + False + + (Without) + Dot + Circle + Disc + Accent + + + + Select a character to display over or below the entire length of the selected text. + + + + + 1 + 2 + + + + + True + False + _Position: + True + positionlb + 0 + + + 0 + 3 + + + + + True + False + + Above text + Below text + + + + Specify where to display the emphasis marks. + + + + + 1 + 3 + + + + + + + + + + + + + + + + + + + + + + True + False + Effects + 0 + + + + + + + + 0 + 2 + + + + + True + False + end + 12 + 12 + 6 + True + True + never + never + in + + + True + False + + + True + False + + + Preview + + + + + + + + + 0 + 3 + + Specify the font effects that you want to use. diff --git a/cui/uiconfig/ui/formatcellsdialog.ui b/cui/uiconfig/ui/formatcellsdialog.ui index a6092cfc6a5c..6bfafa5d4b3c 100644 --- a/cui/uiconfig/ui/formatcellsdialog.ui +++ b/cui/uiconfig/ui/formatcellsdialog.ui @@ -118,7 +118,7 @@ - reset + reset standard ok cancel diff --git a/cui/uiconfig/ui/gallerythemedialog.ui b/cui/uiconfig/ui/gallerythemedialog.ui index 34131bd88614..dc3a040ca853 100644 --- a/cui/uiconfig/ui/gallerythemedialog.ui +++ b/cui/uiconfig/ui/gallerythemedialog.ui @@ -105,7 +105,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/galleryupdateprogress.ui b/cui/uiconfig/ui/galleryupdateprogress.ui index 13e92199ff08..f0310037e5bc 100644 --- a/cui/uiconfig/ui/galleryupdateprogress.ui +++ b/cui/uiconfig/ui/galleryupdateprogress.ui @@ -1,30 +1,30 @@ - + - False - 6 + False + 6 Update False - normal + normal - False + False vertical 12 - False - end + False + end _Cancel True - True - True - True - True + True + True + True + True True @@ -37,7 +37,7 @@ False True - end + end 0 @@ -45,27 +45,27 @@ True - False - 12 + False + 12 True - False - 0 - none + False + 0 + none True - False - 40 + False 12 6 + 40 True - False + False File @@ -74,8 +74,8 @@ - 0 - 0 + 0 + 0 @@ -90,9 +90,6 @@ cancel - - - Updates the view in the window or in the selected object. diff --git a/cui/uiconfig/ui/gradientpage.ui b/cui/uiconfig/ui/gradientpage.ui index 395d256418d3..dc68e55ac1c6 100644 --- a/cui/uiconfig/ui/gradientpage.ui +++ b/cui/uiconfig/ui/gradientpage.ui @@ -29,6 +29,16 @@ 15 15 + + + + + + + + + + 100 5 @@ -71,30 +81,26 @@ vertical 6 - + True True - True never - never in - + True - False - - - True - True - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK - True - - + True + 6 + gradientpresets_model + 3 + 0 + 2 + True - False + True True 0 @@ -265,19 +271,6 @@ 2 - - - True - True - end - True - adjustment1 - - - 1 - 1 - - A_utomatic @@ -293,6 +286,19 @@ 1 + + + True + True + end + True + adjustment1 + + + 1 + 1 + + False @@ -386,6 +392,52 @@ start 3 6 + + + True + False + True + A_ngle: + True + anglemtr + 0 + + + 0 + 0 + 2 + + + + + True + True + True + angleadjustmentslider + False + + + 0 + 1 + + + + + True + True + True + angleadjustment + + + Enter a rotation angle for the selected gradient. + + + + + 1 + 1 + + True @@ -434,89 +486,17 @@ - - True - True - True - angleadjustment - - - Enter a rotation angle for the selected gradient. - - - - - 1 - 1 - - - - + True False - True - A_ngle: + _From Color: True - anglemtr + colorfromlb 0 0 - 0 - 2 - - - - - True - True - True - percentadjustment2 - - - Enter the intensity for the color in the To Color box, where 0% corresponds to black, and 100 % to the selected color. - - - - - 1 - 7 - - - - - True - True - False - 0 - True - - - - - - - Select a color for the endpoint of the gradient. - - - - - 0 - 7 - - - - - True - False - _To Color: - True - colortolb - 0 - - - 0 - 6 + 4 2 @@ -560,31 +540,57 @@ - + True False - _From Color: + _To Color: True - colorfromlb + colortolb 0 0 - 4 + 6 2 - + True True - True - angleadjustmentslider - False + False + 0 + True + + + + + + + Select a color for the endpoint of the gradient. + + 0 - 1 + 7 + + + + + True + True + True + percentadjustment2 + + + Enter the intensity for the color in the To Color box, where 0% corresponds to black, and 100 % to the selected color. + + + + + 1 + 7 diff --git a/cui/uiconfig/ui/hangulhanjaadddialog.ui b/cui/uiconfig/ui/hangulhanjaadddialog.ui index 9f416b7130e8..78b9424acdf9 100644 --- a/cui/uiconfig/ui/hangulhanjaadddialog.ui +++ b/cui/uiconfig/ui/hangulhanjaadddialog.ui @@ -1,32 +1,32 @@ - + - False - 6 + False + 6 New Dictionary True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -39,8 +39,8 @@ _Cancel True - True - True + True + True True @@ -53,9 +53,9 @@ _Help True - True - True - True + True + True + True True @@ -69,32 +69,32 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none True - False + False start - True - 12 12 6 + True + 12 True - False + False _Name: - True - entry + True + entry False @@ -105,10 +105,10 @@ True - True + True True - 32 - True + 32 + True True @@ -127,7 +127,7 @@ True - False + False Dictionary @@ -148,8 +148,5 @@ cancel help - - - diff --git a/cui/uiconfig/ui/hangulhanjaconversiondialog.ui b/cui/uiconfig/ui/hangulhanjaconversiondialog.ui index 4d97d50d3413..1f555ed78ce2 100644 --- a/cui/uiconfig/ui/hangulhanjaconversiondialog.ui +++ b/cui/uiconfig/ui/hangulhanjaconversiondialog.ui @@ -1,7 +1,17 @@ - + + + + + + + + + + + @@ -215,20 +225,13 @@ never in - + True - False - True - True - - - True - False - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK - True - True - - + True + 6 + iconview_model + 0 + 2 diff --git a/cui/uiconfig/ui/hangulhanjaeditdictdialog.ui b/cui/uiconfig/ui/hangulhanjaeditdictdialog.ui index 30e6108bced3..a4f6609fc9cf 100644 --- a/cui/uiconfig/ui/hangulhanjaeditdictdialog.ui +++ b/cui/uiconfig/ui/hangulhanjaeditdictdialog.ui @@ -1,33 +1,33 @@ - + - False - 6 + False + 6 Edit Custom Dictionary True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 True - False - end + False + end _Close True - True - True - True - True + True + True + True + True True @@ -40,8 +40,8 @@ _Help True - True - True + True + True True @@ -55,37 +55,37 @@ False True - end + end 0 True - False + False 6 6 - 6 - 6 + 6 + 6 vertical 12 True - False - 0 - none + False + 0 + none True - False - 12 + False 12 6 + 12 True - False + False Select the user-defined dictionary that you want to edit. @@ -103,10 +103,10 @@ True - False + False Book - True - book + True + book 0 @@ -123,29 +123,29 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 6 + 6 + 12 True - False + False start True - True + True - True - True + True + True True @@ -156,24 +156,24 @@ - 0 - 0 + 0 + 0 True - False + False vertical 6 - start + start _New True - True - True - True + True + True + True Adds the current replacement definition to the dictionary. @@ -190,9 +190,9 @@ _Delete True - True - True - True + True + True + True Deletes the selected entry. @@ -207,8 +207,8 @@ - 1 - 0 + 1 + 0 @@ -216,9 +216,9 @@ True - False + False Original - True + True 0 @@ -235,39 +235,39 @@ True - False + False True - 0 - none + 0 + none True - True + True start - never - always - in 12 6 + never + always + in True - False + False True - False + False True - 3 + 3 vertical 6 True - True + True True - True - 40 + True + 40 True @@ -284,9 +284,9 @@ True - True + True True - True + True True @@ -303,9 +303,9 @@ True - True + True True - True + True True @@ -322,9 +322,9 @@ True - True + True True - True + True True @@ -347,9 +347,9 @@ True - False + False Suggestions - True + True end 0 @@ -377,8 +377,5 @@ close help - - - diff --git a/cui/uiconfig/ui/hangulhanjaoptdialog.ui b/cui/uiconfig/ui/hangulhanjaoptdialog.ui index d9043943c9d0..268c63472c6e 100644 --- a/cui/uiconfig/ui/hangulhanjaoptdialog.ui +++ b/cui/uiconfig/ui/hangulhanjaoptdialog.ui @@ -1,5 +1,5 @@ - + @@ -212,12 +212,6 @@ 0 - - - - - True - 6 diff --git a/cui/uiconfig/ui/hatchpage.ui b/cui/uiconfig/ui/hatchpage.ui index fafc49c764b6..03f3175f360e 100644 --- a/cui/uiconfig/ui/hatchpage.ui +++ b/cui/uiconfig/ui/hatchpage.ui @@ -1,62 +1,68 @@ - + 359 - 15 - 15 + 15 + 15 359 - 1 + 1 0.3 99 - 100 + 100 + + + + + + + + + + True - False + False True True - 6 + 6 6 True - False - 0 - none + False + 0 + none True - False - vertical - 6 + False 12 6 + vertical + 6 - + True - True - True - never - never - in + True + never + in - + True - False - - - True - True - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK - True - - + True + 6 + hatchpresets_model + 3 + 0 + 2 + True @@ -69,16 +75,16 @@ True - False + False center 6 - start + start _Add True - True - True + True + True True @@ -96,9 +102,9 @@ _Modify True - True - True - True + True + True + True Applies the current hatching properties to the selected hatching pattern. If you want, you can save the pattern under a different name. @@ -123,7 +129,7 @@ True - False + False Hatch @@ -140,29 +146,29 @@ True - False + False True True - 0 - none + 0 + none True - False + False start + 12 + 6 True True vertical 6 - 12 - 6 True - False + False _Spacing: - True - distancemtr + True + distancemtr 0 @@ -174,9 +180,9 @@ True - True - distanceadjustment + True True + distanceadjustment 2 @@ -193,9 +199,9 @@ True - False + False A_ngle: - True + True 0 @@ -207,16 +213,16 @@ True - False + False 6 True - True + True True adjustment1 - 1 - False + 1 + False True @@ -227,9 +233,9 @@ True - True - angleadjustment + True True + angleadjustment Enter the rotation angle for the hatch lines, or click a position in the angle grid. @@ -252,10 +258,10 @@ True - False + False _Line type: - True - linetypelb + True + linetypelb 0 @@ -267,7 +273,7 @@ True - False + False Single Crossed @@ -288,10 +294,10 @@ True - False + False Line _color: - True - linecolorlb + True + linecolorlb 0 @@ -303,11 +309,11 @@ True - True - False + True + False center 0 - True + True @@ -328,10 +334,10 @@ Background Color: True - True - False - True - True + True + False + True + True @@ -345,11 +351,11 @@ True - True - False + True + False center 0 - True + True @@ -369,7 +375,7 @@ True - False + False Options @@ -386,34 +392,34 @@ True - False + False end start - 0 - none + 0 + none True - False + False end - vertical 12 6 + vertical True - False - never - never - in + False + never + never + in True - False + False True - False + False Example @@ -435,7 +441,7 @@ True - False + False Preview @@ -446,7 +452,7 @@ False False - end + end 2 diff --git a/cui/uiconfig/ui/hyperlinkdlg.ui b/cui/uiconfig/ui/hyperlinkdlg.ui index 03c4f7224607..6d120b273d2a 100644 --- a/cui/uiconfig/ui/hyperlinkdlg.ui +++ b/cui/uiconfig/ui/hyperlinkdlg.ui @@ -99,11 +99,11 @@ - reset + reset ok cancel help apply - \ No newline at end of file + diff --git a/cui/uiconfig/ui/hyperlinkmailpage.ui b/cui/uiconfig/ui/hyperlinkmailpage.ui index ab3316e5aea2..87216c8985dd 100644 --- a/cui/uiconfig/ui/hyperlinkmailpage.ui +++ b/cui/uiconfig/ui/hyperlinkmailpage.ui @@ -1,63 +1,63 @@ - + True - False - res/adrbook.png + False + res/adrbook.png True - False + False True True - 6 + 6 vertical 12 True - False - 0 - none + False + 0 + none - + True - False - True - True - 6 - 12 + False 12 6 + True + True + 6 + 12 True - False + False start Re_cipient: - True - receiver + True + receiver 0 - 0 - 1 + 0 + 1 True - False + False True - True + True - True + True + True True - True @@ -67,16 +67,16 @@ - 1 - 1 + 1 + 1 True - True - True - Data Sources... + True + True + Data Sources... image1 True @@ -86,31 +86,31 @@ - 2 - 1 + 2 + 1 True - False + False start _Subject: - True - subject + True + subject 0 - 0 - 2 + 0 + 2 True - True + True True - True + True True @@ -119,8 +119,8 @@ - 1 - 2 + 1 + 2 @@ -140,7 +140,7 @@ True - False + False Mail @@ -157,48 +157,48 @@ True - False + False end True True - 0 - none + 0 + none - + True - False - 6 - 12 + False 12 6 + 6 + 12 True - False + False start F_rame: - True - frame + True + frame 0 - 0 - 0 + 0 + 0 - + True - False + False True - 6 - 12 + 6 + 12 True - False + False True @@ -207,28 +207,28 @@ - 0 - 0 + 0 + 0 True - False + False F_orm: - True - form + True + form 0 - 1 - 0 + 1 + 0 True - False + False True @@ -237,16 +237,16 @@ - 2 - 0 + 2 + 0 True - True - True - Events + True + True + Events Opens the Assign Macro dialog, in which you can give events such as "mouse over object" or "trigger hyperlink" their own program codes. @@ -254,51 +254,51 @@ - 3 - 0 + 3 + 0 - 1 - 0 + 1 + 0 True - False + False start Te_xt: - True - indication + True + indication 0 - 0 - 1 + 0 + 1 True - False + False start N_ame: - True - name + True + name 0 - 0 - 2 + 0 + 2 True - True - True + True + True True @@ -307,15 +307,15 @@ - 1 - 1 + 1 + 1 True - True - True + True + True True @@ -324,8 +324,8 @@ - 1 - 2 + 1 + 2 @@ -333,7 +333,7 @@ True - False + False Further Settings diff --git a/cui/uiconfig/ui/hyperlinknewdocpage.ui b/cui/uiconfig/ui/hyperlinknewdocpage.ui index df81372d1db7..4760fbf44bff 100644 --- a/cui/uiconfig/ui/hyperlinknewdocpage.ui +++ b/cui/uiconfig/ui/hyperlinknewdocpage.ui @@ -1,11 +1,11 @@ - + True - False - cmd/sc_adddirect.png + False + cmd/sc_adddirect.png @@ -17,47 +17,47 @@ True - False + False True True - 6 + 6 vertical 12 True - False + False True - 0 - none + 0 + none - + True - False - True - True - 6 - 12 + False 12 6 + True + True + 6 + 12 - + True - False + False True - 6 - 12 + 6 + 12 Edit _now True - True - False - True + True + False + True True - True + True Specifies that the new document is created and immediately opened for editing. @@ -65,18 +65,18 @@ - 0 - 0 + 0 + 0 Edit _later True - True - False - True - True + True + False + True + True editnow @@ -85,42 +85,42 @@ - 1 - 0 + 1 + 0 - 1 - 0 + 1 + 0 True - False + False start _File: - True - path + True + path 0 - 0 - 1 + 0 + 1 True - False + False True - True + True - True + True + True True - True @@ -130,16 +130,16 @@ - 1 - 1 + 1 + 1 True - True - True - Select Path + True + True + Select Path image1 True @@ -149,42 +149,42 @@ - 2 - 1 + 2 + 1 True - False + False start File _type: - True - types + True + types 0 0 - 0 - 2 + 0 + 2 True - True + True False - in + in True - True + True True liststore1 - False - False - 0 - False + False + False + 0 + False @@ -207,8 +207,8 @@ - 1 - 2 + 1 + 2 @@ -225,7 +225,7 @@ True - False + False New Document @@ -242,78 +242,78 @@ True - False + False end True True - 0 - none + 0 + none - + True - False - 6 - 12 + False 12 6 + 6 + 12 True - False + False start F_rame: - True - frame + True + frame 0 - 0 - 0 + 0 + 0 True - False + False start Te_xt: - True - indication + True + indication 0 - 0 - 1 + 0 + 1 True - False + False start N_ame: - True - name + True + name 0 - 0 - 2 + 0 + 2 - + True - False + False True - 6 - 12 + 6 + 12 True - False + False True @@ -322,27 +322,27 @@ - 0 - 0 + 0 + 0 True - False + False F_orm: - True - form + True + form - 1 - 0 + 1 + 0 True - False + False True @@ -351,16 +351,16 @@ - 2 - 0 + 2 + 0 True - True - True - Events + True + True + Events Opens the Assign Macro dialog, in which you can give events such as "mouse over object" or "trigger hyperlink" their own program codes. @@ -368,21 +368,21 @@ - 3 - 0 + 3 + 0 - 1 - 0 + 1 + 0 True - True - True + True + True True @@ -391,15 +391,15 @@ - 1 - 1 + 1 + 1 True - True - True + True + True True @@ -408,8 +408,8 @@ - 1 - 2 + 1 + 2 @@ -417,7 +417,7 @@ True - False + False Further Settings diff --git a/cui/uiconfig/ui/imagetabpage.ui b/cui/uiconfig/ui/imagetabpage.ui index 2c853fe925c3..886bdfa0af02 100644 --- a/cui/uiconfig/ui/imagetabpage.ui +++ b/cui/uiconfig/ui/imagetabpage.ui @@ -7,6 +7,16 @@ 1 10 + + + + + + + + + + True False @@ -29,30 +39,26 @@ vertical 6 - + True True - True never - never in - + True - False - - - True - True - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK - True - - + True + 6 + images_model + 3 + 0 + 2 + True - False + True True 0 @@ -170,22 +176,14 @@ False 0 none - - - True - False - Size: - 0 - - True False - vertical - 3 12 6 + vertical + 3 True @@ -281,6 +279,14 @@ + + + True + False + Size: + 0 + + False @@ -357,22 +363,14 @@ False 0 none - - - True - False - Tiling Position: - 0 - - True False - vertical - 3 12 6 + vertical + 3 True @@ -453,6 +451,14 @@ + + + True + False + Tiling Position: + 0 + + False diff --git a/cui/uiconfig/ui/linedialog.ui b/cui/uiconfig/ui/linedialog.ui index ea6de502b070..d927435206b3 100644 --- a/cui/uiconfig/ui/linedialog.ui +++ b/cui/uiconfig/ui/linedialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/linestyletabpage.ui b/cui/uiconfig/ui/linestyletabpage.ui index d9ffc2a11da2..9a42e795db31 100644 --- a/cui/uiconfig/ui/linestyletabpage.ui +++ b/cui/uiconfig/ui/linestyletabpage.ui @@ -1,41 +1,41 @@ - + 5 - 0.1 - 1 + 0.10 + 1 5 - 0.1 - 1 + 0.10 + 1 5 - 0.1 - 1 + 0.10 + 1 99 - 1 - 10 + 1 + 10 99 - 1 - 10 + 1 + 10 True - False - res/sc05501.png + False + res/sc05501.png True - False - res/sc05502.png + False + res/sc05502.png @@ -51,107 +51,107 @@ True - False + False True True - 6 - 0 - none + 6 + 0 + none True - False + False + 12 + 12 + 6 True True vertical 6 - 12 - 6 - 12 True - False + False True True 12 True - False + False start True vertical 6 - + True - False + False True True - 6 - 12 + 6 + 12 True - False + False _Type: - True - LB_TYPE_1 + True + LB_TYPE_1 0 - 0 - 1 + 0 + 1 True - False + False _Number: - True - NUM_FLD_1 + True + NUM_FLD_1 0 - 0 - 2 + 0 + 2 True - False + False _Length: - True - MTR_FLD_LENGTH_1 + True + MTR_FLD_LENGTH_1 0 - 0 - 3 + 0 + 3 True - False + False _Spacing: - True - MTR_FLD_DISTANCE + True + MTR_FLD_DISTANCE 0 - 0 - 4 + 0 + 4 True - False + False 1 Dots @@ -159,14 +159,14 @@ - 1 - 1 + 1 + 1 True - False + False 1 Dots @@ -174,116 +174,116 @@ - 2 - 1 + 2 + 1 True - True - True + True + True True adjustmentNUM - 1 - 2 + 1 + 2 True - True - True + True + True True adjustmentNUM1 - 2 - 2 + 2 + 2 True - True - True - adjustmentDIST + True + True True + adjustmentDIST 2 - 1 - 3 + 1 + 3 True - True - True - adjustmentDIST1 + True + True True + adjustmentDIST1 2 - 2 - 3 + 2 + 3 True - True - True - adjustmentDIST2 + True + True True + adjustmentDIST2 2 - 1 - 4 + 1 + 4 _Fit to line thickness True - True - False - True - True + True + False + True + True - 0 - 5 + 0 + 5 3 True - False + False Line _style: - True - LB_LINESTYLES + True + LB_LINESTYLES 0 - 0 - 0 + 0 + 0 True - False + False True liststore4 0 - 0 - 1 + 0 + 1 @@ -295,8 +295,8 @@ - 1 - 0 + 1 + 0 2 @@ -320,19 +320,19 @@ True - False + False end True vertical 6 - start + start _Add True - True - True - True + True + True + True False @@ -344,9 +344,9 @@ _Modify True - True - True - True + True + True + True False @@ -358,8 +358,8 @@ _Delete True - True - True + True + True True @@ -374,41 +374,41 @@ - + True - False - 6 - 6 - True + False + 6 + 6 + True True - True - True - Load Line Styles + True + True + Load Line Styles center image1 True - 0 - 0 + 0 + 0 True - True - True - Save Line Styles + True + True + Save Line Styles center image2 True - 1 - 0 + 1 + 0 @@ -436,18 +436,18 @@ True - False - never - never - in + False + never + never + in True - False + False True - False + False Example @@ -469,7 +469,7 @@ True - False + False Properties 0 diff --git a/cui/uiconfig/ui/macromanagerdialog.ui b/cui/uiconfig/ui/macromanagerdialog.ui index 77fdb5a6272d..12fcb65b93a7 100644 --- a/cui/uiconfig/ui/macromanagerdialog.ui +++ b/cui/uiconfig/ui/macromanagerdialog.ui @@ -246,6 +246,32 @@ 5 + + + Copy + True + True + True + + + True + True + 6 + + + + + Paste + True + True + True + + + True + True + 7 + + Password... @@ -262,7 +288,7 @@ False True - 6 + 8 @@ -281,7 +307,7 @@ False True - 7 + 9 @@ -295,7 +321,7 @@ False True - 8 + 10 diff --git a/cui/uiconfig/ui/multipathdialog.ui b/cui/uiconfig/ui/multipathdialog.ui index 919a9c101b18..96faabf78321 100644 --- a/cui/uiconfig/ui/multipathdialog.ui +++ b/cui/uiconfig/ui/multipathdialog.ui @@ -1,5 +1,5 @@ - + @@ -17,28 +17,28 @@ - False - 6 + False + 6 Select Paths False - normal + normal - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -56,8 +56,8 @@ _Cancel True - True - True + True + True True @@ -75,8 +75,8 @@ _Help True - True - True + True + True True @@ -90,43 +90,43 @@ False True - end + end 0 True - False + False True True - 0 - none + 0 + none - + True - False - True - True - 6 - 12 + False 12 6 + True + True + 6 + 12 True - False + False vertical 6 - start + start _Add... True - True - True - True + True + True + True Opens the Select Path dialog to select another folder or the Open dialog to select another file. @@ -143,8 +143,8 @@ _Delete True - True - True + True + True True @@ -160,33 +160,33 @@ - 1 - 0 + 1 + 0 True - False + False True True True - True + True True True - in + in True - True - True + True + True True liststore1 - 0 - False + 0 + False @@ -221,14 +221,14 @@ - 0 - 0 + 0 + 0 - 0 - 0 + 0 + 0 @@ -236,7 +236,7 @@ True - False + False Mark the Default Path for New Files @@ -257,8 +257,5 @@ cancel help - - - diff --git a/cui/uiconfig/ui/numberingoptionspage.ui b/cui/uiconfig/ui/numberingoptionspage.ui index a2b0b2e960bc..bbd57556425d 100644 --- a/cui/uiconfig/ui/numberingoptionspage.ui +++ b/cui/uiconfig/ui/numberingoptionspage.ui @@ -167,13 +167,78 @@ Number: True numfmtlb - 1 + 0 0 0 + + + True + False + + + Select a numbering scheme for the selected levels. + + + + + + 1 + 0 + + + + + True + False + Start at: + True + startat + 0 + + + 0 + 1 + + + + + True + True + True + True + adjustment2 + + + Enter a new starting number for the current level. + + + + + 1 + 1 + + + + + True + False + Character style: + True + charstyle + 0 + + + 0 + 3 + + True @@ -189,6 +254,120 @@ 3 + + + True + False + Color: + True + color + 0 + + + 0 + 4 + + + + + True + True + False + 0 + True + + + + + + + Select a color for the current numbering scheme. + + + + + 1 + 4 + + + + + True + False + _Relative size: + True + relsize + 0 + + + 0 + 5 + + + + + True + True + True + True + adjustment4 + + + Enter the amount by which you want to resize the bullet character with respect to the font height of the current paragraph. + + + + + 1 + 5 + + + + + True + False + Character: + True + bullet + 0 + + + 0 + 6 + + + + + Select... + True + True + True + + + Select the graphic, or locate the graphic file that you want to use as a bullet. + + + + + 1 + 6 + + + + + True + False + Show sublevels: + True + sublevels + end + 0 + + + 0 + 7 + + True @@ -228,54 +407,79 @@ - + + True + False + Separator + 0 + + + 0 + 9 + + + + + True + False + 12 + Before: + True + prefix + 0 + + + 0 + 10 + + + + True True True True - adjustment2 - - Enter a new starting number for the current level. + + Enter a character or the text to display in front of the number in the list. 1 - 1 + 10 - + True False - Start at: + 12 + After: True - startat - 1 + suffix + 0 0 - 1 + 11 - + True - False + True + True + True - - Select a numbering scheme for the selected levels. + + Enter a character or the text to display behind the number in the list. To create the numbering scheme "1.)", enter ".)" in this box. - 1 - 0 + 11 @@ -285,54 +489,13 @@ Graphics: True bitmap - 1 + 0 0 12 - - - True - False - Alignment: - True - orientlb - 1 - - - 0 - 14 - - - - - True - False - 0 - - Top of baseline - Center of baseline - Bottom of baseline - Top of character - Center of character - Bottom of character - Top of line - Center of line - Bottom of line - - - - Select the alignment option for the graphic. - - - - - 1 - 14 - - Select... @@ -356,210 +519,6 @@ 12 - - - True - True - False - 0 - True - - - - - - - Select a color for the current numbering scheme. - - - - - 1 - 4 - - - - - True - True - True - True - adjustment4 - - - Enter the amount by which you want to resize the bullet character with respect to the font height of the current paragraph. - - - - - 1 - 5 - - - - - Select... - True - True - True - - - Select the graphic, or locate the graphic file that you want to use as a bullet. - - - - - 1 - 6 - - - - - True - False - 20 - Before: - True - prefix - 1 - - - 0 - 10 - - - - - True - False - 20 - Separator - 1 - - - 0 - 9 - - - - - True - True - True - True - - - Enter a character or the text to display behind the number in the list. To create the numbering scheme "1.)", enter ".)" in this box. - - - - - 1 - 11 - - - - - True - True - True - True - - - Enter a character or the text to display in front of the number in the list. - - - - - 1 - 10 - - - - - True - False - After: - True - suffix - 1 - - - 0 - 11 - - - - - True - False - Show sublevels: - True - sublevels - end - 1 - - - 0 - 7 - - - - - True - False - Character: - True - bullet - 1 - - - 0 - 6 - - - - - True - False - _Relative size: - True - relsize - 1 - - - 0 - 5 - - - - - True - False - Color: - True - color - 1 - - - 0 - 4 - - - - - True - False - Character style: - True - charstyle - 1 - - - 0 - 3 - - True @@ -573,7 +532,7 @@ Width: True widthmf - 1 + 0 False @@ -589,7 +548,7 @@ True heightmf end - 1 + 0 False @@ -628,25 +587,6 @@ 0 - - - True - True - True - True - adjustment5 - 2 - - - Enter a height for the graphic. - - - - - 0 - 1 - - @@ -654,6 +594,17 @@ False center 3 + + + True + False + False + + + 0 + 0 + + True @@ -699,17 +650,6 @@ 2 - - - True - False - False - - - 0 - 0 - - @@ -723,12 +663,72 @@ 2 + + + True + True + True + True + adjustment5 + 2 + + + Enter a height for the graphic. + + + + + 0 + 1 + + 1 13 + + + True + False + Alignment: + True + orientlb + 0 + + + 0 + 14 + + + + + True + False + 0 + + Top of baseline + Center of baseline + Bottom of baseline + Top of character + Center of character + Bottom of character + Top of line + Center of line + Bottom of line + + + + Select the alignment option for the graphic. + + + + + 1 + 14 + + diff --git a/cui/uiconfig/ui/numberingpositionpage.ui b/cui/uiconfig/ui/numberingpositionpage.ui index 26d73d2af5fe..e4e9ee195c21 100644 --- a/cui/uiconfig/ui/numberingpositionpage.ui +++ b/cui/uiconfig/ui/numberingpositionpage.ui @@ -140,11 +140,10 @@ True False - True Followed by: True numfollowedbylb - 1 + 0 0 @@ -158,7 +157,7 @@ Alignment: True num2alignlb - 1 + 0 0 @@ -172,7 +171,7 @@ Aligned at: True alignedatmf - 1 + 0 0 @@ -186,7 +185,7 @@ Indent at: True indentatmf - 1 + 0 0 @@ -219,7 +218,7 @@ Tab stop at: True atmf - 1 + 0 0 @@ -291,7 +290,7 @@ Indent: True indentmf - 1 + 0 0 @@ -345,7 +344,7 @@ Width of numbering: True numberingwidthmf - 1 + 0 0 @@ -399,7 +398,7 @@ numbering and text: True right numdistmf - 1 + 0 0 @@ -413,7 +412,7 @@ numbering and text: Alignment: True numalignlb - 1 + 0 0 diff --git a/cui/uiconfig/ui/optaccessibilitypage.ui b/cui/uiconfig/ui/optaccessibilitypage.ui index dd57deef7298..12c351a21735 100644 --- a/cui/uiconfig/ui/optaccessibilitypage.ui +++ b/cui/uiconfig/ui/optaccessibilitypage.ui @@ -565,12 +565,6 @@ 4 - - - - - True - 6 diff --git a/cui/uiconfig/ui/optadvancedpage.ui b/cui/uiconfig/ui/optadvancedpage.ui index 6dbe234ca532..1035aa4d0704 100644 --- a/cui/uiconfig/ui/optadvancedpage.ui +++ b/cui/uiconfig/ui/optadvancedpage.ui @@ -1,13 +1,11 @@ - + - + - - @@ -16,12 +14,8 @@ - - - - @@ -211,19 +205,10 @@ True - 5 + 4 0 - - - True - - - 6 - 1 - - @@ -234,7 +219,7 @@ - 2 + 1 @@ -247,7 +232,7 @@ - 3 + 2 diff --git a/cui/uiconfig/ui/optbasicidepage.ui b/cui/uiconfig/ui/optbasicidepage.ui index f5305c41f698..2454518c268e 100644 --- a/cui/uiconfig/ui/optbasicidepage.ui +++ b/cui/uiconfig/ui/optbasicidepage.ui @@ -1,34 +1,34 @@ - + True - False - 6 + False + 6 vertical 12 True - False - 0 - none + False + 0 + none True - False + False 12 6 Enable code completion True - True - False - True - True + True + False + True + True Display methods of a Basic object. @@ -36,8 +36,8 @@ - 0 - 0 + 0 + 0 @@ -45,7 +45,7 @@ True - False + False Code Completion @@ -62,82 +62,25 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 + False 12 6 - - - Autoclose procedures - True - True - False - True - True - - - Automatically insert closing statements for procedures. - - - - - 0 - 3 - - - - - Autoclose parenthesis - True - True - False - True - True - - - Automatically close open parenthesis. - - - - - 0 - 2 - - - - - Autoclose quotes - True - True - False - True - True - - - Automatically close open quotes. - - - - - 0 - 1 - - + 6 Autocorrection True - True - False - True - True + True + False + True + True Correct cases of Basic variables and keywords while typing. @@ -145,8 +88,65 @@ - 0 - 0 + 0 + 0 + + + + + Autoclose quotes + True + True + False + True + True + + + Automatically close open quotes. + + + + + 0 + 1 + + + + + Autoclose parenthesis + True + True + False + True + True + + + Automatically close open parenthesis. + + + + + 0 + 2 + + + + + Autoclose procedures + True + True + False + True + True + + + Automatically insert closing statements for procedures. + + + + + 0 + 3 @@ -154,7 +154,7 @@ True - False + False Code Suggestion @@ -171,25 +171,25 @@ True - False - 0 - none + False + 0 + none True - False - 6 + False 12 6 + 6 Use extended types True - True - False - True - True + True + False + True + True Allow UNO object types as valid Basic types. @@ -197,8 +197,8 @@ - 0 - 0 + 0 + 0 @@ -206,7 +206,7 @@ True - False + False Language Features diff --git a/cui/uiconfig/ui/optchartcolorspage.ui b/cui/uiconfig/ui/optchartcolorspage.ui index 45d4992ee1b4..b2cf6d810e41 100644 --- a/cui/uiconfig/ui/optchartcolorspage.ui +++ b/cui/uiconfig/ui/optchartcolorspage.ui @@ -1,8 +1,8 @@ - + - + @@ -12,6 +12,17 @@ + + + + + + + + + + + True False @@ -53,17 +64,11 @@ - + 0 - - - - - True - 6 @@ -195,21 +200,18 @@ True True never - never in - + True - False - - - True - True - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK - True - True - - + True + 6 + True + tableiconview_model + 12 + 0 + 2 + True @@ -246,5 +248,4 @@ - diff --git a/cui/uiconfig/ui/optctlpage.ui b/cui/uiconfig/ui/optctlpage.ui index 81de73a34e73..4fb0877f8f29 100644 --- a/cui/uiconfig/ui/optctlpage.ui +++ b/cui/uiconfig/ui/optctlpage.ui @@ -1,36 +1,36 @@ - + True - False + False True - 6 + 6 vertical 12 True - False - 0 - none + False + 0 + none - + True - False - 6 + False 12 6 + 6 Use se_quence checking True - True - False - True - True + True + False + True + True Enables sequence input checking for languages such as Thai. @@ -38,25 +38,25 @@ - 0 - 0 + 0 + 0 - + True - False - 6 + False 12 + 6 Restricted True - True - False - True - True + True + False + True + True Prevents the use as well as the printing of illegal character combinations. @@ -64,28 +64,28 @@ - 0 - 0 + 0 + 0 _Type and replace True - True - False - True - True + True + False + True + True - 0 - 1 + 0 + 1 - 0 - 1 + 0 + 1 @@ -93,7 +93,7 @@ True - False + False Sequence Checking @@ -110,39 +110,39 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 6 + 6 + 12 True - False + False Movement: 1 - 0 - 0 + 0 + 0 Lo_gical True - True - False - True + True + False + True True - True + True Pressing the Right Arrow key moves the text cursor toward the end of the current text. Pressing the Left Arrow key moves the text cursor toward the beginning of the current text. @@ -150,18 +150,18 @@ - 1 - 0 + 1 + 0 _Visual True - True - False - True - True + True + False + True + True movementlogical @@ -170,8 +170,8 @@ - 1 - 1 + 1 + 1 @@ -182,7 +182,7 @@ True - False + False Cursor Control @@ -199,35 +199,35 @@ True - False - 0 - none + False + 0 + none - + True - False - 12 + False 12 6 + 12 True - False + False _Numerals: - True - numerals + True + numerals 1 - 0 - 0 + 0 + 0 True - False + False Arabic (1, 2, 3…) Eastern Arabic (٣ ,٢ ,١…) @@ -241,8 +241,8 @@ - 1 - 0 + 1 + 0 @@ -250,7 +250,7 @@ True - False + False General Options diff --git a/cui/uiconfig/ui/optdeeplpage.ui b/cui/uiconfig/ui/optdeeplpage.ui deleted file mode 100644 index b7c8e9aba82b..000000000000 --- a/cui/uiconfig/ui/optdeeplpage.ui +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - True - False - True - True - 6 - vertical - - - True - False - 0 - none - - - - True - False - 12 - 6 - 6 - 12 - - - Please read the privacy policy - True - True - True - start - none - https://www.deepl.com/privacy/ - - - 0 - 0 - - - - - - True - False - 6 - 12 - - - True - False - start - API URL: - True - apiurl - - - 0 - 0 - - - - - True - False - start - Authentication key: - True - authkey - - - 0 - 1 - - - - - True - True - True - True - - - 1 - 0 - - - - - True - True - True - True - - - 1 - 1 - - - - - 0 - 1 - - - - - - - True - False - DeepL API Options - True - grid1 - - - - - - - - False - True - 1 - - - - diff --git a/cui/uiconfig/ui/optemailpage.ui b/cui/uiconfig/ui/optemailpage.ui index 144220c4d598..14e3988e8469 100644 --- a/cui/uiconfig/ui/optemailpage.ui +++ b/cui/uiconfig/ui/optemailpage.ui @@ -1,50 +1,50 @@ - + True - False + False True - 6 - 0 - none + 6 + 0 + none True - False - vertical - 6 + False 12 6 + vertical + 6 - + True - False - 6 - 12 + False + 6 + 12 True - False + False _Email program: - True - url + True + url - 1 - 0 + 1 + 0 True - True + True center True - True - 32 + True + 32 True @@ -53,17 +53,17 @@ - 2 - 0 + 2 + 0 Browse... True - True - True - True + True + True + True Opens a file dialog to select the email program. @@ -71,32 +71,32 @@ - 3 - 0 + 3 + 0 - False - True + False + True center center - res/lock.png + res/lock.png - 0 - 0 + 0 + 0 - False - True + False + True All files - 0 - 1 + 0 + 1 4 @@ -108,49 +108,49 @@ - + True - False - 6 - 12 + False + 6 + 12 True - False + False Suppress hidden elements of documents - True + True 0 - 2 - 2 + 2 + 2 True - True - False - True - True + True + False + True + True - 1 - 2 + 1 + 2 - False - True + False + True center center - res/lock.png + res/lock.png - 0 - 2 + 0 + 2 @@ -183,7 +183,7 @@ True - False + False Sending Documents as Email Attachments diff --git a/cui/uiconfig/ui/optfltrembedpage.ui b/cui/uiconfig/ui/optfltrembedpage.ui index edb8ed48bb60..28216a1ba5d4 100644 --- a/cui/uiconfig/ui/optfltrembedpage.ui +++ b/cui/uiconfig/ui/optfltrembedpage.ui @@ -2,14 +2,12 @@ - + - - @@ -18,22 +16,16 @@ - - - - - - @@ -92,19 +84,11 @@ - 12 - 5 + 9 + 4 0 - - - - 13 - 6 - 1 - - @@ -116,9 +100,9 @@ - 14 - 7 - 2 + 10 + 5 + 1 @@ -130,7 +114,7 @@ - 3 + 2 diff --git a/cui/uiconfig/ui/optfontspage.ui b/cui/uiconfig/ui/optfontspage.ui index 56de95122d69..2da7c28bafac 100644 --- a/cui/uiconfig/ui/optfontspage.ui +++ b/cui/uiconfig/ui/optfontspage.ui @@ -1,5 +1,5 @@ - + @@ -12,14 +12,12 @@ False svx/res/nu02.png - + - - @@ -30,14 +28,10 @@ - - - - @@ -148,112 +142,53 @@ - + True + False False - True - - - True + True + True + + True - True - True - in - - - True - True - True - True - True - liststore1 - 0 - False - - - - - - True - 6 - Always - - - - 6 - 0 - - - - - - 7 - 1 - - - - - - - True - 6 - Screen only - - - - 8 - 2 - - - - - - - True - 6 - Font - True - - - - 3 - - - - - - - True - 6 - Replace with - True - - - - 4 - - - - - - - Lists the original font and the font that will replace it. Select Always to replace the font, even if the original font is installed on your system. Select Screen only to replace the screen font only and never replace the font for printing. - - - - + True + True + + + + + Enter or select the name of the font that you want to replace. - - True - True - 0 - 0 - 2 - 4 + 1 + + + + + True + False + False + True + True + + + True + True + True + + + + + Enter or select the name of the replacement font. + + + + + 1 + 1 @@ -297,53 +232,105 @@ - + True - False False - True - True - - + True + + + True True - True - True - - - - - Enter or select the name of the replacement font. - - - - - 1 - 1 - - - - - True - False - False - True - True - - - True - True - True - - - - - Enter or select the name of the font that you want to replace. + True + True + in + + + True + True + True + True + True + liststore1 + 0 + False + + + + + + True + 6 + Always + + + + 5 + 0 + + + + + + + True + 6 + Screen only + + + + 6 + 1 + + + + + + + True + 6 + Font + True + + + + 2 + + + + + + + True + 6 + Replace with + True + + + + 3 + + + + + + + Lists the original font and the font that will replace it. Select Always to replace the font, even if the original font is installed on your system. Select Screen only to replace the screen font only and never replace the font for printing. + + + + + + True + True + 0 + 0 - 1 + 2 + 4 diff --git a/cui/uiconfig/ui/opthtmlpage.ui b/cui/uiconfig/ui/opthtmlpage.ui index e6238703d5d6..e12481268d35 100644 --- a/cui/uiconfig/ui/opthtmlpage.ui +++ b/cui/uiconfig/ui/opthtmlpage.ui @@ -1,5 +1,5 @@ - + @@ -80,183 +80,16 @@ 6 12 - - True + False - Size _7: - True - size7 + True + center + center + res/lock.png - 1 - 6 - - - - - True - True - True - adjustsize7 - - - Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. - - - - - 2 - 6 - - - - - True - False - Size _6: - True - size6 - - - 1 - 5 - - - - - True - True - True - adjustsize6 - - - Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. - - - - - 2 - 5 - - - - - True - False - Size _5: - True - size5 - - - 1 - 4 - - - - - True - True - True - adjustsize5 - - - Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. - - - - - 2 - 4 - - - - - True - False - Size _4: - True - size4 - - - 1 - 3 - - - - - True - True - True - adjustsize4 - - - Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. - - - - - 2 - 3 - - - - - True - False - Size _3: - True - size3 - - - 1 - 2 - - - - - True - True - True - adjustsize3 - - - Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. - - - - - 2 - 2 - - - - - True - False - Size _2: - True - size2 - - - 1 - 1 - - - - - True - True - True - adjustsize2 - - - Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. - - - - - 2 - 1 + 0 + 0 @@ -289,19 +122,6 @@ 0 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - False @@ -315,6 +135,36 @@ 1 + + + True + False + Size _2: + True + size2 + + + 1 + 1 + + + + + True + True + True + adjustsize2 + + + Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. + + + + + 2 + 1 + + False @@ -328,6 +178,36 @@ 2 + + + True + False + Size _3: + True + size3 + + + 1 + 2 + + + + + True + True + True + adjustsize3 + + + Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. + + + + + 2 + 2 + + False @@ -341,6 +221,36 @@ 3 + + + True + False + Size _4: + True + size4 + + + 1 + 3 + + + + + True + True + True + adjustsize4 + + + Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. + + + + + 2 + 3 + + False @@ -354,6 +264,36 @@ 4 + + + True + False + Size _5: + True + size5 + + + 1 + 4 + + + + + True + True + True + adjustsize5 + + + Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. + + + + + 2 + 4 + + False @@ -367,6 +307,36 @@ 5 + + + True + False + Size _6: + True + size6 + + + 1 + 5 + + + + + True + True + True + adjustsize6 + + + Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. + + + + + 2 + 5 + + False @@ -380,6 +350,36 @@ 6 + + + True + False + Size _7: + True + size7 + + + 1 + 6 + + + + + True + True + True + adjustsize7 + + + Use the spin buttons Size 1 to Size 7 to define the respective font sizes for the HTML <font size=1> to <font size=7> tags. + + + + + 2 + 6 + + @@ -430,43 +430,16 @@ True 6 - - Ignore _font settings - True - True - False - True - True - True - - - Mark this check box to ignore all font settings when importing. The fonts that were defined in the HTML Page Style will be the fonts that will be used. - - + + False + True + center + center + res/lock.png - 1 - 2 - - - - - _Import unknown HTML tags as fields - True - True - False - True - True - True - - - Mark this check box if you want tags that are not recognized by Writer/Web to be imported as fields. - - - - - 1 - 1 + 0 + 0 @@ -489,19 +462,6 @@ 0 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - False @@ -515,6 +475,26 @@ 1 + + + _Import unknown HTML tags as fields + True + True + False + True + True + True + + + Mark this check box if you want tags that are not recognized by Writer/Web to be imported as fields. + + + + + 1 + 1 + + False @@ -528,6 +508,26 @@ 2 + + + Ignore _font settings + True + True + False + True + True + True + + + Mark this check box to ignore all font settings when importing. The fonts that were defined in the HTML Page Style will be the fonts that will be used. + + + + + 1 + 2 + + @@ -564,28 +564,21 @@ True 6 - - _Copy local images to Internet - True - True - False - True - True - True - - - Mark this check box to automatically upload the embedded pictures to the Internet server when uploading using a network protocol. Use the Save As dialog to save the document and enter a complete URL as the file name in the Internet. - - + + False + True + center + center + res/lock.png - 1 - 3 + 0 + 0 - - _Print layout + + LibreOffice _Basic True True False @@ -593,14 +586,27 @@ True True - - If you mark this field, the print layout of the current document (for example, table of contents with justified page numbers and dot leaders) is exported as well. + + Check this box to include the BASIC instructions when exporting to HTML format. 1 - 2 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 1 @@ -624,52 +630,6 @@ 1 - - - LibreOffice _Basic - True - True - False - True - True - True - - - Check this box to include the BASIC instructions when exporting to HTML format. - - - - - 1 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - False @@ -683,6 +643,26 @@ 2 + + + _Print layout + True + True + False + True + True + True + + + If you mark this field, the print layout of the current document (for example, table of contents with justified page numbers and dot leaders) is exported as well. + + + + + 1 + 2 + + False @@ -696,6 +676,26 @@ 3 + + + _Copy local images to Internet + True + True + False + True + True + True + + + Mark this check box to automatically upload the embedded pictures to the Internet server when uploading using a network protocol. Use the Save As dialog to save the document and enter a complete URL as the file name in the Internet. + + + + + 1 + 3 + + diff --git a/cui/uiconfig/ui/optionsdialog.ui b/cui/uiconfig/ui/optionsdialog.ui index 87bd4c8b5ed5..1fe7d95ddb42 100644 --- a/cui/uiconfig/ui/optionsdialog.ui +++ b/cui/uiconfig/ui/optionsdialog.ui @@ -45,7 +45,7 @@ - + _Reset True True @@ -239,7 +239,7 @@ help - revert + reset ok cancel diff --git a/cui/uiconfig/ui/optlanguagespage.ui b/cui/uiconfig/ui/optlanguagespage.ui index 6a8a4081a136..8e203002403c 100644 --- a/cui/uiconfig/ui/optlanguagespage.ui +++ b/cui/uiconfig/ui/optlanguagespage.ui @@ -104,6 +104,221 @@ 0 + + + True + False + True + 0 + none + + + + True + False + 12 + 6 + True + 6 + 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + True + False + Locale setting: + True + localesetting + 0 + + + 1 + 0 + + + + + True + False + start + True + + + Specifies the locale setting of the country setting. This influences settings for numbering, currency and units of measure. + + + + + 2 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + True + False + _Default currency: + True + currencylb + 0 + + + 1 + 1 + + + + + True + False + start + True + + + Specifies the default currency that is used for the currency format and the currency fields. + + + + + 2 + 1 + + + + + False + True + center + center + res/lock.png + + + 0 + 2 + + + + + True + False + Decimal key on the numpad: + True + decimalseparator + 0 + + + 1 + 2 + + + + + _Same as locale setting ( %1 ) + True + True + False + True + True + + + Specifies to use the numeric keypad decimal key that is set in your system when you press the respective key on the number pad. + + + + + 2 + 2 + + + + + False + True + center + center + res/lock.png + + + 0 + 3 + + + + + True + False + Date acceptance _patterns: + True + datepatterns + 0 + + + 1 + 3 + + + + + True + True + start + center + True + True + + + Specifies the date acceptance patterns for the current locale. Calc spreadsheet and Writer table cell input needs to match locale dependent date acceptance patterns before it is recognized as a valid date. + + + + + 2 + 3 + + + + + + + True + False + Formats + + + + + + + + 0 + 1 + + True @@ -121,6 +336,20 @@ True 6 12 + + + True + False + Western: + True + westernlanguage + 0 + + + 1 + 0 + + True @@ -153,6 +382,20 @@ 0 + + + True + False + Asian: + True + asianlanguage + 0 + + + 1 + 1 + + True @@ -185,6 +428,20 @@ 1 + + + True + False + Complex text layout: + True + complexlanguage + 0 + + + 1 + 2 + + True @@ -237,48 +494,6 @@ 3 - - - True - False - Complex text layout: - True - complexlanguage - 0 - - - 1 - 2 - - - - - True - False - Asian: - True - asianlanguage - 0 - - - 1 - 1 - - - - - True - False - Western: - True - westernlanguage - 0 - - - 1 - 0 - - False @@ -366,9 +581,7 @@ True - - Indicates whether the system input language is applied to newly typed text; when disabled, the document or paragraph language is used instead. - + Indicates whether the system input language is applied to newly typed text; when disabled, the document or paragraph language is used instead. @@ -408,221 +621,6 @@ 3 - - - True - False - True - 0 - none - - - - True - False - 12 - 6 - True - 6 - 12 - - - True - False - Locale setting: - True - localesetting - 0 - - - 1 - 0 - - - - - True - False - Decimal key on the numpad: - True - decimalseparator - 0 - - - 1 - 2 - - - - - True - False - _Default currency: - True - currencylb - 0 - - - 1 - 1 - - - - - True - False - Date acceptance _patterns: - True - datepatterns - 0 - - - 1 - 3 - - - - - True - False - start - True - - - Specifies the locale setting of the country setting. This influences settings for numbering, currency and units of measure. - - - - - 2 - 0 - - - - - True - False - start - True - - - Specifies the default currency that is used for the currency format and the currency fields. - - - - - 2 - 1 - - - - - True - True - start - center - True - True - - - Specifies the date acceptance patterns for the current locale. Calc spreadsheet and Writer table cell input needs to match locale dependent date acceptance patterns before it is recognized as a valid date. - - - - - 2 - 3 - - - - - _Same as locale setting ( %1 ) - True - True - False - True - True - - - Specifies to use the numeric keypad decimal key that is set in your system when you press the respective key on the number pad. - - - - - 2 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 3 - - - - - - - True - False - Formats - - - - - - - - 0 - 1 - - Defines the default languages and some other locale settings for documents. diff --git a/cui/uiconfig/ui/optlingupage.ui b/cui/uiconfig/ui/optlingupage.ui index ffbfb9cb9333..7bcce594ce21 100644 --- a/cui/uiconfig/ui/optlingupage.ui +++ b/cui/uiconfig/ui/optlingupage.ui @@ -2,7 +2,7 @@ - + @@ -16,7 +16,7 @@ - + @@ -30,7 +30,7 @@ - + @@ -117,12 +117,6 @@ 0 - - - - - True - 6 @@ -239,12 +233,6 @@ 0 - - - - - True - 6 @@ -409,12 +397,6 @@ 0 - - - - - True - 6 diff --git a/cui/uiconfig/ui/optpathspage.ui b/cui/uiconfig/ui/optpathspage.ui index 69cd082a8925..865a7330a7f3 100644 --- a/cui/uiconfig/ui/optpathspage.ui +++ b/cui/uiconfig/ui/optpathspage.ui @@ -1,8 +1,8 @@ - + - + @@ -30,44 +30,44 @@ True - False + False True True - 6 + 6 vertical 12 True - False + False True True - 0 - none + 0 + none True - False - vertical + False 12 6 + vertical True - True + True True True - in + in True - True - True + True + True True True liststore1 - 0 - False + 0 + False @@ -140,7 +140,7 @@ True - False + False Paths used by %PRODUCTNAME @@ -157,16 +157,16 @@ True - False + False 12 - end + end _Default True - True - True - True + True + True + True The Default button resets the predefined paths for all selected entries. @@ -183,9 +183,9 @@ _Edit... True - True - True - True + True + True + True Click to display the Select Path or Edit Paths dialog. diff --git a/cui/uiconfig/ui/optproxypage.ui b/cui/uiconfig/ui/optproxypage.ui index 442be6946b4f..ff612a9cd79b 100644 --- a/cui/uiconfig/ui/optproxypage.ui +++ b/cui/uiconfig/ui/optproxypage.ui @@ -1,5 +1,5 @@ - + @@ -10,7 +10,7 @@ 0 none - + True False @@ -19,6 +19,19 @@ True 6 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + True @@ -33,6 +46,53 @@ 0 + + + True + False + + None + System + Manual + + + + Specifies the type of proxy definition. + + + + + 2 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + True + False + HT_TP proxy: + True + http + 0 + + + 1 + 1 + + True @@ -53,41 +113,29 @@ - - True - True + + False + True + center center - True - True - True - - - Type the name of the proxy server for HTTPS. Type the port in the right-hand field. - - + res/lock.png - 2 - 2 + 3 + 1 - + True - True - center - True - True - True - - - Specifies the names of the servers that do not require any proxy servers, separated by semicolons. - - + False + _Port: + True + httpport - 2 - 4 + 4 + 1 @@ -111,6 +159,78 @@ 1 + + + False + True + center + center + res/lock.png + + + 0 + 2 + + + + + True + False + HTTP_S proxy: + True + https + 0 + + + 1 + 2 + + + + + True + True + center + True + True + True + + + Type the name of the proxy server for HTTPS. Type the port in the right-hand field. + + + + + 2 + 2 + + + + + False + True + center + center + res/lock.png + + + 3 + 2 + + + + + True + False + P_ort: + True + httpsport + + + 4 + 2 + + True @@ -133,64 +253,16 @@ - - True + False - - None - System - Manual - - - - Specifies the type of proxy definition. - - + True + center + center + res/lock.png - 2 - 0 - - - - - True - False - HT_TP proxy: - True - http - 0 - - - 1 - 1 - - - - - True - False - _Port: - True - httpport - - - 4 - 1 - - - - - True - False - HTTP_S proxy: - True - https - 0 - - - 1 - 2 + 0 + 3 @@ -204,20 +276,26 @@ 1 - 4 + 3 - + True - False - P_ort: - True - httpsport + True + center + True + True + True + + + Specifies the names of the servers that do not require any proxy servers, separated by semicolons. + + - 4 - 2 + 2 + 3 @@ -229,88 +307,10 @@ 4 - 4 + 3 2 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 4 - - - - - False - True - center - center - res/lock.png - - - 3 - 1 - - - - - False - True - center - center - res/lock.png - - - 3 - 2 - - diff --git a/cui/uiconfig/ui/optsavepage.ui b/cui/uiconfig/ui/optsavepage.ui index 556bc78b178b..83fa21af2cd8 100644 --- a/cui/uiconfig/ui/optsavepage.ui +++ b/cui/uiconfig/ui/optsavepage.ui @@ -1,5 +1,5 @@ - + @@ -31,22 +31,16 @@ True 6 - - Load printer settings with the document - True - True - False - True - True - - - If enabled, the printer settings will be loaded with the document. This can cause a document to be printed on a distant printer, if you do not change the printer manually in the Print dialog. If disabled, your standard printer will be used to print this document. The current printer settings will be stored with the document whether or not this option is checked. - - + + False + True + center + center + res/lock.png - 1 - 1 + 0 + 0 @@ -68,6 +62,51 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + Load printer settings with the document + True + True + False + True + True + + + If enabled, the printer settings will be loaded with the document. This can cause a document to be printed on a distant printer, if you do not change the printer manually in the Print dialog. If disabled, your standard printer will be used to print this document. The current printer settings will be stored with the document whether or not this option is checked. + + + + + 1 + 1 + + + + + False + True + center + center + res/lock.png + + + 0 + 2 + + Load view position with the document even if it was saved by a different user @@ -87,45 +126,6 @@ 2 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - @@ -239,25 +239,6 @@ 1 - - - Save URLs relative to file system - True - True - False - True - True - - - Select this box for relative saving of URLs in the file system. - - - - - 1 - 5 - - _Edit document properties before saving @@ -277,25 +258,6 @@ 2 - - - Save URLs relative to internet - True - True - False - True - True - - - Select this box for relative saving of URLs to the Internet. - - - - - 1 - 6 - - Al_ways create backup copy @@ -330,6 +292,44 @@ 4 + + + Save URLs relative to file system + True + True + False + True + True + + + Select this box for relative saving of URLs in the file system. + + + + + 1 + 5 + + + + + Save URLs relative to internet + True + True + False + True + True + + + Select this box for relative saving of URLs to the Internet. + + + + + 1 + 6 + + False @@ -455,6 +455,103 @@ True 6 12 + + + True + False + ODF format version: + True + odfversion + 0 + + + 1 + 0 + + + + + True + False + + 1.0/1.1 + 1.2 + 1.2 Extended (compatibility mode) + 1.2 Extended + 1.3 + 1.3 Extended + 1.4 + 1.4 Extended (recommended) + + + + Some companies or organizations may require ODF documents in the ODF 1.0/1.1/1.2 or ODF 1.3 format. You can select these format to save in the listbox. These older formats cannot store all new features, so the new format ODF 1.4 (Extended) is recommended where possible. + + + + + 2 + 0 + + + + + True + False + D_ocument type: + True + doctype + 0 + + + 1 + 1 + + + + + True + False + + + Specifies the document type for which you want to define the default file format. + + + + + 2 + 1 + + + + + True + False + Always sa_ve as: + True + saveas + 0 + + + 1 + 2 + + + + + True + False + + + Specifies how documents of the type selected on the left will always be saved as this file type. You may select another file type for the current document in the Save as dialog. + + + + + 2 + 2 + + Warn when not saving in ODF or default format @@ -511,103 +608,6 @@ 2 - - - True - False - - 1.0/1.1 - 1.2 - 1.2 Extended (compatibility mode) - 1.2 Extended - 1.3 - 1.3 Extended - 1.4 - 1.4 Extended (recommended) - - - - Some companies or organizations may require ODF documents in the ODF 1.0/1.1/1.2 or ODF 1.3 format. You can select these format to save in the listbox. These older formats cannot store all new features, so the new format ODF 1.4 (Extended) is recommended where possible. - - - - - 2 - 0 - - - - - True - False - ODF format version: - True - odfversion - 0 - - - 1 - 0 - - - - - True - False - Always sa_ve as: - True - saveas - 0 - - - 1 - 2 - - - - - True - False - - - Specifies the document type for which you want to define the default file format. - - - - - 2 - 1 - - - - - True - False - - - Specifies how documents of the type selected on the left will always be saved as this file type. You may select another file type for the current document in the Save as dialog. - - - - - 2 - 2 - - - - - True - False - D_ocument type: - True - doctype - 0 - - - 1 - 1 - - False diff --git a/cui/uiconfig/ui/optsecuritypage.ui b/cui/uiconfig/ui/optsecuritypage.ui index 9852869d9fbd..09e79251424d 100644 --- a/cui/uiconfig/ui/optsecuritypage.ui +++ b/cui/uiconfig/ui/optsecuritypage.ui @@ -1,5 +1,5 @@ - + @@ -9,7 +9,7 @@ 6 12 - + True False True @@ -17,7 +17,7 @@ none - + True False 12 @@ -25,201 +25,11 @@ True 24 - - _TSAs... - True - True - True - center - True - - - Opens the Time Stamping Authority URLs dialog. - - - - - 1 - 0 - - - - - + True False True - 6 - - - True - False - True - Maintain a list of Time Stamping Authority (TSA) URLs to be used for digital signatures in PDF export. - True - 56 - 56 - 0 - - - 1 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - 0 - 0 - - - - - - - True - False - TSAs - - - - - - - - 0 - 4 - - - - - True - False - True - 0 - none - - - - True - False - 12 - 6 - True - 24 - - - _Certificate... - True - True - True - center - True - - - Opens the Certificate Path dialog. - - - - - 1 - 0 - - - - - - True - False - True - 6 - - - True - False - True - Select the Network Security Services certificate directory to use for digital signatures. - True - 56 - 56 - 0 - - - 1 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - 0 - 0 - - - - - - - True - False - Certificate Path - - - - - - - - 0 - 3 - - - - - True - False - True - 0 - none - - - - True - False - 12 - 6 - True - 24 - - - True - False - True - Adjust the security level for executing macros and specify trusted macro developers. + Adjust security related options and define warnings for hidden information in documents. True 56 56 @@ -231,16 +41,16 @@ - - Macro Securit_y... + + O_ptions... True True True center True - - Opens the Macro Security dialog. + + Opens the "Security Options and Warnings" dialog. @@ -252,10 +62,10 @@ - + True False - Macro Security + Security Options and Warnings @@ -264,7 +74,7 @@ 0 - 2 + 0 @@ -290,6 +100,51 @@ False True 12 + + + + True + False + True + 6 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + Persistently _save passwords for web connections + True + True + False + True + True + + + If enabled, all passwords that you use to access files from web servers will be securely stored. You can retrieve the passwords from the list after you enter the master password. + + + + + 1 + 0 + + + + + 0 + 0 + + @@ -298,43 +153,6 @@ 12 True 6 - - - True - False - True - Passwords are protected by a master password. You will be asked to enter it once per session, if %PRODUCTNAME retrieves a password from the protected password list. - True - 56 - 56 - 0 - - - - - - 0 - 1 - - - - - False - True - True - Disabling the function to persistently store passwords deletes the list of passwords stored and resets the master password. - -Do you want to delete password list and reset master password? - True - 56 - 56 - 0 - - - 0 - 2 - - @@ -375,57 +193,49 @@ Do you want to delete password list and reset master password? 0 + + + True + False + True + Passwords are protected by a master password. You will be asked to enter it once per session, if %PRODUCTNAME retrieves a password from the protected password list. + True + 56 + 56 + 0 + + + + + + 0 + 1 + + + + + False + True + True + Disabling the function to persistently store passwords deletes the list of passwords stored and resets the master password. + +Do you want to delete password list and reset master password? + True + 56 + 56 + 0 + + + 0 + 2 + + 0 1 - - - - True - False - True - 6 - - - Persistently _save passwords for web connections - True - True - False - True - True - - - If enabled, all passwords that you use to access files from web servers will be securely stored. You can retrieve the passwords from the list after you enter the master password. - - - - - 1 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - 0 - 0 - - 0 @@ -523,7 +333,7 @@ Do you want to delete password list and reset master password? - + True False True @@ -531,7 +341,7 @@ Do you want to delete password list and reset master password? none - + True False 12 @@ -539,11 +349,11 @@ Do you want to delete password list and reset master password? True 24 - + True False True - Adjust security related options and define warnings for hidden information in documents. + Adjust the security level for executing macros and specify trusted macro developers. True 56 56 @@ -555,16 +365,16 @@ Do you want to delete password list and reset master password? - - O_ptions... + + Macro Securit_y... True True True center True - - Opens the "Security Options and Warnings" dialog. + + Opens the Macro Security dialog. @@ -576,10 +386,10 @@ Do you want to delete password list and reset master password? - + True False - Security Options and Warnings + Macro Security @@ -588,7 +398,197 @@ Do you want to delete password list and reset master password? 0 - 0 + 2 + + + + + True + False + True + 0 + none + + + + True + False + 12 + 6 + True + 24 + + + + True + False + True + 6 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + True + False + True + Select the Network Security Services certificate directory to use for digital signatures. + True + 56 + 56 + 0 + + + 1 + 0 + + + + + 0 + 0 + + + + + _Certificate... + True + True + True + center + True + + + Opens the Certificate Path dialog. + + + + + 1 + 0 + + + + + + + True + False + Certificate Path + + + + + + + + 0 + 3 + + + + + True + False + True + 0 + none + + + + True + False + 12 + 6 + True + 24 + + + + True + False + True + 6 + + + True + False + True + Maintain a list of Time Stamping Authority (TSA) URLs to be used for digital signatures in PDF export. + True + 56 + 56 + 0 + + + 1 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + 0 + 0 + + + + + _TSAs... + True + True + True + center + True + + + Opens the Time Stamping Authority URLs dialog. + + + + + 1 + 0 + + + + + + + True + False + TSAs + + + + + + + + 0 + 4 @@ -607,38 +607,6 @@ Do you want to delete password list and reset master password? 6 8 24 - - - _Browse... - True - True - True - True - True - - - 1 - 1 - - - - - True - True - True - True - True - - - Enter the executable of the certificate manager path. - - - - - 0 - 1 - - @@ -686,6 +654,38 @@ Do you want to delete password list and reset master password? 0 + + + True + True + True + True + True + + + Enter the executable of the certificate manager path. + + + + + 0 + 1 + + + + + _Browse... + True + True + True + True + True + + + 1 + 1 + + diff --git a/cui/uiconfig/ui/optuserpage.ui b/cui/uiconfig/ui/optuserpage.ui index c893f47631ed..af74dc4b9ff3 100644 --- a/cui/uiconfig/ui/optuserpage.ui +++ b/cui/uiconfig/ui/optuserpage.ui @@ -419,7 +419,7 @@ Position - Type your position in the company in this field. + Type your position in the organization in this field. @@ -452,7 +452,7 @@ False True start - Co_mpany: + Or_ganization: True company 0 @@ -478,7 +478,7 @@ True - Type the name of your company in this field. + Type the name of your organization in this field. diff --git a/cui/uiconfig/ui/optviewpage.ui b/cui/uiconfig/ui/optviewpage.ui index 716b80b102f8..036eabc920c6 100644 --- a/cui/uiconfig/ui/optviewpage.ui +++ b/cui/uiconfig/ui/optviewpage.ui @@ -195,18 +195,18 @@ - - Force Skia software rendering + + Force Skia hardware acceleration True True False - Requires restart. Enabling this will prevent the use of graphics drivers. + Requires restart. Enabling this will enable the use of Skia hardware acceleration. 18 True True - - Disables Skia's use of the computer graphics device. This still uses Skia software but with calls for raster framing, reduced and simplified graphics processing unit load. + + Enables Skia's use of the computer graphics device. This still uses Skia software but with hardware acceleration enabled. @@ -297,7 +297,7 @@ - + False True center diff --git a/cui/uiconfig/ui/pageformatpage.ui b/cui/uiconfig/ui/pageformatpage.ui index a680f0c3b25d..c90eba4ec878 100644 --- a/cui/uiconfig/ui/pageformatpage.ui +++ b/cui/uiconfig/ui/pageformatpage.ui @@ -52,6 +52,11 @@ True False + + + Select a predefined paper size, or create a custom format by entering the dimensions for the paper in the Height and Width boxes. + + 1 @@ -80,6 +85,11 @@ True True 2 + + + To define a custom format, enter a width here. + + 1 @@ -108,6 +118,11 @@ True True 2 + + + To define a custom format, enter a height here. + + 1 @@ -145,6 +160,11 @@ + + + Displays and prints the current document with the paper oriented vertically. + + 1 @@ -165,6 +185,11 @@ + + + Displays and prints the current document with the paper oriented horizontally. + + 1 @@ -204,6 +229,26 @@ 0 + + + Resize all pages + True + True + False + True + True + True + + + Resize all pages in the document. If unchecked, creates a master slide or page specific to the slide or page. + + + + + 1 + 0 + + @@ -250,6 +295,11 @@ True False + + + Select the paper source for your printer. If you want, you can assign different paper trays to different page styles. For example, assign a different tray to the First Page style and load the tray with your company's letterhead paper. + + 1 @@ -262,21 +312,6 @@ 0 - - - Resize all pages - True - True - False - True - True - True - - - 1 - 0 - - @@ -366,6 +401,11 @@ True True 2 + + + Enter the amount of space to leave between the left edge of the page and the document text. If you are using the Mirrored page layout, enter the amount of space to leave between the inner text margin and the inner edge of the page. + + 1 @@ -419,6 +459,11 @@ True True 2 + + + Enter the amount of space to leave between the right edge of the page and the document text. If you are using the Mirrored page layout, enter the amount of space to leave between the outer text margin and the outer edge of the page + + 1 @@ -446,6 +491,11 @@ True True 2 + + + Enter the amount of space to leave between the upper edge of the page and the document text. + + 1 @@ -473,6 +523,11 @@ True True 2 + + + Enter the amount of space to leave between the lower edge of the page and the document text. + + 1 @@ -500,6 +555,11 @@ True True 2 + + + Enter the amount of space to leave between the left edge of the page and the left margin. If you are using the Mirrored page layout, enter the amount of space to leave between the inner page margin and the inner edge of the page. + + 1 @@ -532,7 +592,7 @@ 0 none - + True False @@ -555,6 +615,27 @@ 0 + + + True + False + + Right and left + Mirrored + Only right + Only left + + + + Specify whether the current style should show odd pages, even pages, or both odd and even pages. + + + + + 1 + 0 + + True @@ -569,43 +650,6 @@ 1 - - - Use page li_ne-spacing - True - False - True - Enables page line-spacing (register-true) using the selected Reference Style - True - True - - - If enabled, then all paragraph styles with the option page line-spacing activated will be affected, assuming the line spacing of the Reference Style. This will align them to an invisible vertical page grid, regardless of their font size, so that each line is the same height. - - - - - 0 - 2 - 2 - - - - - True - False - - Right and left - Mirrored - Only right - Only left - - - - 1 - 0 - - True @@ -619,6 +663,57 @@ 1 + + + Use page li_ne-spacing + True + False + True + Enables page line-spacing (register-true) using the selected Reference Style + True + True + + + If enabled, then all paragraph styles with the option page line-spacing activated will be affected, assuming the line spacing of the Reference Style. This will align them to an invisible vertical page grid, regardless of their font size, so that each line is the same height. + + + + + 0 + 2 + 2 + + + + + False + True + 12 + Reference _Style: + True + comboRegisterStyle + 0 + + + 0 + 3 + + + + + False + True + + + Select the Paragraph Style that you want to use as a reference for lining up the text on the selected Page style. + + + + + 1 + 3 + + False @@ -641,6 +736,11 @@ True True True + + + Centers the cells horizontally on the printed page. + + 1 @@ -655,6 +755,11 @@ True True True + + + Centers the cells vertically on the printed page. + + 1 @@ -669,79 +774,35 @@ True True True + + + Resizes the drawing objects so that they fit on the paper format that you select. + + 1 6 - - - False - True - 12 - Reference _Style: - True - comboRegisterStyle - 0 - - - 0 - 3 - - - - - False - True - - - 1 - 3 - - True False Gutter position: True - comboGutterPosition 0 + + + + + 0 7 - - - True - False - - Left - Top - - - - 1 - 7 - - - - - Gutter on right side of page - True - False - True - True - True - - - 1 - 8 - - Background covers margins @@ -751,17 +812,101 @@ Any background will cover margins of the page as well True True + + + If enabled, then any background will cover the entire page, including margins. If disabled, any background will cover the page only inside the margins. + + 1 + 10 + + + + + Left + True + True + False + True + True + + + + + + Places the gutter on the left of the page. + + + + + 1 + 7 + + + + + Right + True + True + False + True + rbGutterLeft + + + + + + Places the gutter on the right of the page. + + + + + 1 + 8 + + + + + Top + True + True + False + True + rbGutterLeft + + + + + + Places the gutter on the top of the page. + + + 1 9 + + + False + Options: + True + 0 + + + + + + 0 + 10 + + diff --git a/cui/uiconfig/ui/paraindentspacing.ui b/cui/uiconfig/ui/paraindentspacing.ui index 0372cdf12720..daaa92e32397 100644 --- a/cui/uiconfig/ui/paraindentspacing.ui +++ b/cui/uiconfig/ui/paraindentspacing.ui @@ -125,6 +125,20 @@ 0 + + + True + True + True + True + adjustmentspinED_INDENT + 2 + + + 1 + 0 + + True @@ -139,6 +153,20 @@ 1 + + + True + True + True + True + adjustmentspinED_INDENT1 + 2 + + + 1 + 1 + + True @@ -153,49 +181,6 @@ 2 - - - _Automatic - True - True - False - Indent paragraph automatically according to font size and line spacing. - True - True - - - 0 - 3 - - - - - True - True - True - True - adjustmentspinED_INDENT - 2 - - - 1 - 0 - - - - - True - True - True - True - adjustmentspinED_INDENT1 - 2 - - - 1 - 1 - - True @@ -210,13 +195,27 @@ 2 + + + _Automatic + True + False + Indent paragraph automatically according to font size and line spacing. + True + True + + + 0 + 3 + + False Fixed - static + static @@ -330,7 +329,6 @@ Do not add space between paragraphs of the same style - True True False True @@ -418,7 +416,7 @@ of - static + static diff --git a/cui/uiconfig/ui/paratabspage.ui b/cui/uiconfig/ui/paratabspage.ui index 16074373de6c..24ced2ea9ea4 100644 --- a/cui/uiconfig/ui/paratabspage.ui +++ b/cui/uiconfig/ui/paratabspage.ui @@ -1,12 +1,12 @@ - + -56 56 - 1 - 10 + 1 + 10 @@ -18,48 +18,48 @@ True - False + False True True - 6 + 6 12 True - False + False True True - 0 - none + 0 + none - + True - False - True - True - 3 + False 12 6 + True + True + 3 - 42 + 42 True - False + False True True - in + in True - True + True True True liststore1 - False - False - 0 - False + False + False + 0 + False @@ -77,33 +77,33 @@ - 0 - 2 + 0 + 2 True - True + True True + True True - True - 0 - 1 + 0 + 1 - False + False True adjustment1 2 - 0 - 0 + 0 + 0 @@ -111,7 +111,7 @@ True - False + False Position 0 @@ -129,50 +129,50 @@ True - False + False True - 0 - none + 0 + none - + True - False - 6 - 12 + False 12 6 + 6 + 12 Deci_mal True - True - False - True - True + True + False + True + True radiobuttonBTN_TABTYPE_LEFT - 0 - 3 + 0 + 3 True - True + True + 3 True - 3 - 1 - 4 + 1 + 4 True - False + False Left tab preview @@ -180,14 +180,14 @@ - 1 - 0 + 1 + 0 True - False + False Right tab preview @@ -195,14 +195,14 @@ - 1 - 1 + 1 + 1 True - False + False Center tab preview @@ -210,14 +210,14 @@ - 1 - 2 + 1 + 2 True - False + False Decimal tab preview @@ -225,23 +225,23 @@ - 1 - 3 + 1 + 3 True - False + False vertical _Start - True - False - True + True + False + True True - True + True False @@ -252,10 +252,10 @@ _Left/Top - True - False - True - True + True + False + True + True radiobuttonBTN_TABTYPE_LEFT @@ -266,22 +266,22 @@ - 0 - 0 + 0 + 0 True - False + False vertical _End - True - False - True - True + True + False + True + True radiobuttonBTN_TABTYPE_LEFT @@ -293,10 +293,10 @@ Righ_t/Bottom - True - False - True - True + True + False + True + True radiobuttonBTN_TABTYPE_LEFT @@ -307,39 +307,39 @@ - 0 - 1 + 0 + 1 C_entered True - True - False - True - True + True + False + True + True radiobuttonBTN_TABTYPE_LEFT - 0 - 2 + 0 + 2 True - False + False center - _Character - True - entryED_TABTYPE_DECCHAR - 0 12 + _Character + True + entryED_TABTYPE_DECCHAR + 0 - 0 - 4 + 0 + 4 @@ -347,7 +347,7 @@ True - False + False Type @@ -364,32 +364,32 @@ True - False + False True - 0 - none + 0 + none - + True - False - 6 - 12 + False 12 6 + 6 + 12 N_one True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 2 @@ -397,15 +397,15 @@ _........ True - True - False - True - True + True + False + True + True radiobuttonBTN_FILLCHAR_NO - 0 - 1 + 0 + 1 2 @@ -413,15 +413,15 @@ _-------- True - True - False - True - True + True + False + True + True radiobuttonBTN_FILLCHAR_NO - 0 - 2 + 0 + 2 2 @@ -429,15 +429,15 @@ ______ True - True - False - True - True + True + False + True + True radiobuttonBTN_FILLCHAR_NO - 0 - 3 + 0 + 3 2 @@ -445,33 +445,33 @@ C_haracter True - True - False - True - True + True + False + True + True radiobuttonBTN_FILLCHAR_NO - 0 - 4 + 0 + 4 True - True - 3 + True + 3 True - 1 - 4 + 1 + 4 @@ -479,7 +479,7 @@ True - False + False Fill Character 0 @@ -497,17 +497,17 @@ True - False - 6 + False + 6 vertical 12 - start + start _New True - True - True + True + True True @@ -520,9 +520,9 @@ Delete _all True - True - True - True + True + True + True False @@ -534,8 +534,8 @@ _Delete True - True - True + True + True True @@ -551,10 +551,10 @@ - False + False points - True - radiobuttonBTN_FILLCHAR_POINTS + True + radiobuttonBTN_FILLCHAR_POINTS True @@ -564,10 +564,10 @@ - False + False dashes - True - radiobuttonBTN_FILLCHAR_DASHLINE + True + radiobuttonBTN_FILLCHAR_DASHLINE True @@ -577,10 +577,10 @@ - False + False underscores - True - radiobuttonBTN_FILLCHAR_UNDERSCORE + True + radiobuttonBTN_FILLCHAR_UNDERSCORE True diff --git a/cui/uiconfig/ui/patterntabpage.ui b/cui/uiconfig/ui/patterntabpage.ui index f3e25e5a0f23..3ab67dca2f8b 100644 --- a/cui/uiconfig/ui/patterntabpage.ui +++ b/cui/uiconfig/ui/patterntabpage.ui @@ -1,70 +1,76 @@ - + + + + + + + + + + + True - False + False True True - 6 + 6 6 True - False - 0 - none + False + 0 + none True - False - vertical - 6 + False 12 6 + vertical + 6 - + True - True - True - never - never - in + True + never + in - + True - True - - - True - True - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK - True - - + True + 6 + patternpresets_model + 3 + 0 + 2 + True True True - 1 + 0 True - False + False center 6 - start + start _Add True - True - True + True + True True @@ -82,9 +88,9 @@ _Modify True - True - True - True + True + True + True Applies the current pattern properties to the selected pattern. If you want, you can save the pattern under a different name. @@ -109,7 +115,7 @@ True - False + False Pattern @@ -126,32 +132,32 @@ True - False + False True True - 0 - none + 0 + none True - False + False start + 12 + 6 True True vertical 6 - 12 - 6 True - False + False vertical 3 True - False + False Pattern Editor: 0 @@ -164,20 +170,20 @@ True - True + True start start - never - never - in + never + never + in True - False + False True - True + True GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK start start @@ -208,16 +214,16 @@ True - False + False vertical 3 True - False + False Foreground Color: - True - LB_COLOR + True + LB_COLOR 0 @@ -229,10 +235,10 @@ True - True - False + True + False 0 - True + True @@ -259,16 +265,16 @@ True - False + False vertical 3 True - False + False Background Color: - True - LB_BACKGROUND_COLOR + True + LB_BACKGROUND_COLOR 0 @@ -280,10 +286,10 @@ True - True - False + True + False 0 - True + True @@ -312,7 +318,7 @@ True - False + False Options @@ -329,33 +335,33 @@ True - False + False end start - 0 - none + 0 + none True - False - vertical + False 12 6 + vertical True - False - never - never - in + False + never + never + in True - False + False True - False + False Example @@ -377,7 +383,7 @@ True - False + False Preview @@ -388,7 +394,7 @@ False False - end + end 2 diff --git a/cui/uiconfig/ui/percentdialog.ui b/cui/uiconfig/ui/percentdialog.ui index 7bf70ffa7a6a..56b321fab685 100644 --- a/cui/uiconfig/ui/percentdialog.ui +++ b/cui/uiconfig/ui/percentdialog.ui @@ -1,38 +1,38 @@ - + 100 77 - 1 - 10 + 1 + 10 - False - 6 + False + 6 Combine True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - start + False + start _OK True - True - True - True - True + True + True + True + True True @@ -46,8 +46,8 @@ _Cancel True - True - True + True + True True @@ -61,35 +61,35 @@ False True - end + end 0 True - False + False True True - 0 - none + 0 + none True - True + True start start - True - adjustment1 12 - True 6 + True + True + adjustment1 True - False + False Minimum Size @@ -109,9 +109,6 @@ ok cancel - - - Enter the minimum length for combining single-lined paragraphs as a percentage of the page width. diff --git a/cui/uiconfig/ui/pickoutlinepage.ui b/cui/uiconfig/ui/pickoutlinepage.ui index 7c6fcb7ef950..db22771b07e4 100644 --- a/cui/uiconfig/ui/pickoutlinepage.ui +++ b/cui/uiconfig/ui/pickoutlinepage.ui @@ -27,6 +27,7 @@ True + Click the outline style that you want to use. diff --git a/cui/uiconfig/ui/positionsizedialog.ui b/cui/uiconfig/ui/positionsizedialog.ui index 224456a5479d..994d97c9853d 100644 --- a/cui/uiconfig/ui/positionsizedialog.ui +++ b/cui/uiconfig/ui/positionsizedialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/querydeletebitmapdialog.ui b/cui/uiconfig/ui/querydeletebitmapdialog.ui index 954e91c839f9..fa15cace8ec5 100644 --- a/cui/uiconfig/ui/querydeletebitmapdialog.ui +++ b/cui/uiconfig/ui/querydeletebitmapdialog.ui @@ -1,30 +1,30 @@ - + - False + False Delete Bitmap? False True - dialog - True - question + dialog + True + question yes-no Are you sure you want to delete the bitmap? - False + False vertical 12 - False + False False True - end + end 0 diff --git a/cui/uiconfig/ui/querydeletegradientdialog.ui b/cui/uiconfig/ui/querydeletegradientdialog.ui index ef9d7bc70a1d..80cd1db55aa9 100644 --- a/cui/uiconfig/ui/querydeletegradientdialog.ui +++ b/cui/uiconfig/ui/querydeletegradientdialog.ui @@ -1,30 +1,30 @@ - + - False + False Delete gradient? False True - dialog - True - question + dialog + True + question yes-no Do you want to delete the gradient? - False + False vertical 12 - False + False False True - end + end 0 diff --git a/cui/uiconfig/ui/querydeletehatchdialog.ui b/cui/uiconfig/ui/querydeletehatchdialog.ui index 27cdfd527453..ab3c6f1ae15a 100644 --- a/cui/uiconfig/ui/querydeletehatchdialog.ui +++ b/cui/uiconfig/ui/querydeletehatchdialog.ui @@ -1,30 +1,30 @@ - + - False + False Delete Hatching? False True - dialog - True - question + dialog + True + question yes-no Do you want to delete the hatching? - False + False vertical 12 - False + False False True - end + end 0 diff --git a/cui/uiconfig/ui/rotationtabpage.ui b/cui/uiconfig/ui/rotationtabpage.ui index 1e27b7efddc5..2cf01048f6e1 100644 --- a/cui/uiconfig/ui/rotationtabpage.ui +++ b/cui/uiconfig/ui/rotationtabpage.ui @@ -170,7 +170,7 @@ True - False + True GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK Rotation point diff --git a/cui/uiconfig/ui/searchattrdialog.ui b/cui/uiconfig/ui/searchattrdialog.ui index b2c9fd8f40cd..f22b32546a25 100644 --- a/cui/uiconfig/ui/searchattrdialog.ui +++ b/cui/uiconfig/ui/searchattrdialog.ui @@ -117,12 +117,6 @@ 0 - - - - - True - 6 diff --git a/cui/uiconfig/ui/searchformatdialog.ui b/cui/uiconfig/ui/searchformatdialog.ui index 71f95685548f..f5f300bf4136 100644 --- a/cui/uiconfig/ui/searchformatdialog.ui +++ b/cui/uiconfig/ui/searchformatdialog.ui @@ -102,7 +102,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/shadowtabpage.ui b/cui/uiconfig/ui/shadowtabpage.ui index 32d3f5bc6ab3..5ee010cf63be 100644 --- a/cui/uiconfig/ui/shadowtabpage.ui +++ b/cui/uiconfig/ui/shadowtabpage.ui @@ -1,50 +1,50 @@ - + 999 - 1 - 10 + 1 + 10 100 - 5 - 10 + 5 + 10 150 - 1 - 10 + 1 + 10 True - False - 6 + False + 6 24 True - False - 0 - none + False + 0 + none True - False - vertical - 3 + False 12 6 + vertical + 3 _Use shadow True - True - False - True + True + False + True True - True + True Adds a shadow to the selected drawing object. @@ -58,82 +58,28 @@ - + True - False - 4 - 6 + False 18 - - - True - True - start - True - adjustmentPercent - True - - - Enter a percentage from 0% (opaque) to 100% (transparent) to specify the transparency of the shadow. - - - - - 1 - 4 - - - - - True - True - start - True - True - adjustmentPoint - 1 - - - 1 - 3 - - - - - True - True - start - True - adjustmentDistance - True - 2 - - - Enter the distance that you want the shadow to be offset from the selected object. - - - - - 1 - 2 - - + 4 + 6 True - True - never - never - in + True + never + never + in True - False + False True - True + True GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK @@ -146,17 +92,31 @@ - 1 - 0 + 1 + 0 + + + + + True + False + _Color: + True + LB_SHADOW_COLOR + 0 + + + 0 + 1 True - True - False + True + False 0 - True + True @@ -168,64 +128,104 @@ - 1 - 1 + 1 + 1 True - False + False _Distance: - True - MTR_FLD_DISTANCE + True + MTR_FLD_DISTANCE 0 - 0 - 2 + 0 + 2 - + True - False - _Color: - True - LB_SHADOW_COLOR - 0 + True + start + True + True + adjustmentDistance + 2 + + + Enter the distance that you want the shadow to be offset from the selected object. + + - 0 - 1 + 1 + 2 + + + + + True + True + start + True + True + adjustmentPoint + 1 + + + 1 + 3 True - False + False _Blur: - True - LB_SHADOW_BLUR + True + LB_SHADOW_BLUR 0 - 0 - 3 + 0 + 3 True - False + False _Transparency: - True - MTR_SHADOW_TRANSPARENT + True + MTR_SHADOW_TRANSPARENT 0 - 0 - 4 + 0 + 4 + + + + + True + True + start + True + True + adjustmentPercent + + + Enter a percentage from 0% (opaque) to 100% (transparent) to specify the transparency of the shadow. + + + + + 1 + 4 @@ -243,7 +243,7 @@ True - False + False Properties @@ -260,33 +260,33 @@ True - False - 0 - none + False + 0 + none True - False + False + 12 + 6 True vertical True - 12 - 6 True - True - never - never - in + True + never + never + in True - False + False True - False + False Example @@ -308,7 +308,7 @@ True - False + False Preview diff --git a/cui/uiconfig/ui/smarttagoptionspage.ui b/cui/uiconfig/ui/smarttagoptionspage.ui index 3f5d960c0a5f..113c67dac17a 100644 --- a/cui/uiconfig/ui/smarttagoptionspage.ui +++ b/cui/uiconfig/ui/smarttagoptionspage.ui @@ -1,5 +1,5 @@ - + @@ -19,26 +19,26 @@ True - False - 6 - 12 - 6 + False + 6 + 12 + 6 - + True - False + False True True - 6 + 6 Label text with smart tags True - True - False - True - True + True + False + True + True Enables Smart Tags to be evaluated and shown in your text document. @@ -46,38 +46,36 @@ - 0 - 0 + 0 + 0 True - False + False True True - 0 - none + 0 + none - + True - False - True - True - 12 + False 12 6 True True + 12 Properties... True - True - True + True + True start - True + True To configure a Smart Tag, select the name of the Smart Tag, then click Properties. Not all Smart Tags can be configured. @@ -85,28 +83,28 @@ - 1 - 0 + 1 + 0 True - True + True True True - in + in True - True - True + True + True True True liststore2 - False - 0 - False + False + 0 + False @@ -122,12 +120,6 @@ 0 - - - - - True - 6 @@ -140,8 +132,8 @@ - 0 - 0 + 0 + 0 @@ -149,7 +141,7 @@ True - False + False Currently Installed Smart Tags @@ -158,14 +150,14 @@ - 0 - 1 + 0 + 1 - 0 - 0 + 0 + 0 diff --git a/cui/uiconfig/ui/spellingdialog.ui b/cui/uiconfig/ui/spellingdialog.ui index e4b2d822c253..ac84cae9cfaa 100644 --- a/cui/uiconfig/ui/spellingdialog.ui +++ b/cui/uiconfig/ui/spellingdialog.ui @@ -6,7 +6,7 @@ True False - + diff --git a/cui/uiconfig/ui/swpossizepage.ui b/cui/uiconfig/ui/swpossizepage.ui index 743317282c92..f78febb0724e 100644 --- a/cui/uiconfig/ui/swpossizepage.ui +++ b/cui/uiconfig/ui/swpossizepage.ui @@ -58,6 +58,39 @@ True 3 6 + + + True + False + _Width: + True + width + 0 + + + 0 + 0 + + + + + True + True + True + True + adjustment1 + 2 + + + Enter the width that you want for the selected object. + + + + + 1 + 0 + + @@ -135,36 +168,17 @@ - - True - True - True - True - adjustment1 - 2 - - - Enter the width that you want for the selected object. - - - - - 1 - 0 - - - - + True False - _Width: + H_eight: True - width + height 0 0 - 0 + 1 @@ -186,20 +200,6 @@ 1 - - - True - False - H_eight: - True - height - 0 - - - 0 - 1 - - @@ -218,6 +218,68 @@ 0 + + + True + False + 0 + none + + + + True + False + 12 + 6 + 18 + + + Positio_n + True + True + False + True + True + True + + + 0 + 0 + + + + + _Size + True + True + False + True + True + True + + + 1 + 0 + + + + + + + True + False + Protect + + + + + + + + 0 + 1 + + True @@ -348,68 +410,6 @@ 2 - - - True - False - 0 - none - - - - True - False - 12 - 6 - 18 - - - Positio_n - True - True - False - True - True - True - - - 0 - 0 - - - - - _Size - True - True - False - True - True - True - - - 1 - 0 - - - - - - - True - False - Protect - - - - - - - - 0 - 1 - - True @@ -494,6 +494,21 @@ 0 + + + True + False + + + Select the horizontal alignment option for the object. + + + + + 1 + 0 + + True @@ -508,34 +523,6 @@ 0 - - - True - False - _by: - True - byvert - 0 - - - 2 - 2 - - - - - True - False - _to: - True - horianchor - 0 - - - 4 - 0 - - True @@ -555,6 +542,20 @@ 0 + + + True + False + _to: + True + horianchor + 0 + + + 4 + 0 + + True @@ -571,18 +572,24 @@ - + + _Mirror on even pages True - False + True + False + 12 + True + True - - Select the horizontal alignment option for the object. + + Reverses the current horizontal alignment settings on even pages. - 1 - 0 + 0 + 1 + 6 @@ -614,6 +621,20 @@ 2 + + + True + False + _by: + True + byvert + 0 + + + 2 + 2 + + True @@ -662,27 +683,6 @@ 2 - - - _Mirror on even pages - True - True - False - 12 - True - True - - - Reverses the current horizontal alignment settings on even pages. - - - - - 0 - 1 - 6 - - Keep inside te_xt boundaries diff --git a/cui/uiconfig/ui/textdialog.ui b/cui/uiconfig/ui/textdialog.ui index 01856a7fc4df..e2de28b2b2a6 100644 --- a/cui/uiconfig/ui/textdialog.ui +++ b/cui/uiconfig/ui/textdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/textflowpage.ui b/cui/uiconfig/ui/textflowpage.ui index c61e3b96871d..a251e784cc86 100644 --- a/cui/uiconfig/ui/textflowpage.ui +++ b/cui/uiconfig/ui/textflowpage.ui @@ -9,6 +9,32 @@ 1 10 + + 55.88 + 1 + 10 + + + 55.88 + 1 + 10 + + + 55.88 + 1 + 10 + + + 55.88 + 1 + 10 + + + 99 + 2 + 1 + 10 + 99 1 @@ -54,40 +80,17 @@ 10 - 0 99 2 1 10 - - 55.88 - 1 + + 100 + 10 10 - - 55.88 - 1 - 10 - - - 55.88 - 1 - 10 - - - 55.88 - 1 - 10 - - - 0 - 99 - 2 - 1 - 10 - - + True False @@ -102,7 +105,7 @@ 0 none - + True False @@ -131,106 +134,6 @@ 2 - - - True - True - start - 25 - True - True - adjustment7 - - - Enter the minimum word length in characters that can be hyphenated. - - - - - 0 - 6 - - - - - True - True - start - 25 - True - True - adjustment2 - - - Enter the maximum number of consecutive lines that can be hyphenated. - - - - - 0 - 5 - - - - - True - True - start - 25 - True - adjustment9 - True - - - Enter the minimum number of characters of a compound word constituent to leave at the end of the line before a hyphen is inserted. - - - - - 0 - 3 - - - - - True - True - start - 25 - True - adjustment14 - True - - - Enter the minimum number of characters of a compound word constituent that must appear at the beginning of the line after the hyphen. - - - - - 0 - 4 - - - - - True - True - start - 25 - True - True - adjustment4 - - - Enter the minimum number of characters that must appear at the beginning of the line after the hyphen. - - - - - 0 - 2 - - True @@ -265,6 +168,26 @@ 1 + + + True + True + start + 25 + True + True + adjustment4 + + + Enter the minimum number of characters that must appear at the beginning of the line after the hyphen. + + + + + 0 + 2 + + True @@ -280,31 +203,91 @@ - + True - False + True start - C_ompound characters at line end - True - spinCompoundLineEnd + 25 + True + True + adjustment9 + + + Enter the minimum number of characters of a compound word constituent to leave at the end of the line before a hyphen is inserted. + + - 1 - 3 + 0 + 3 + + + + + True + False + start + C_ompound characters at line end + True + spinCompoundLineEnd + + + 1 + 3 + + + + + True + True + start + 25 + True + True + adjustment14 + + + Enter the minimum number of characters of a compound word constituent that must appear at the beginning of the line after the hyphen. + + + + + 0 + 4 True - False + False start C_ompound characters at line begin - True - spinCompoundLineBegin + True + spinCompoundLineBegin - 1 - 4 + 1 + 4 + + + + + True + True + start + 25 + True + True + adjustment2 + + + Enter the maximum number of consecutive lines that can be hyphenated. + + + + + 0 + 5 @@ -321,6 +304,26 @@ 5 + + + True + True + start + 25 + True + True + adjustment7 + + + Enter the minimum word length in characters that can be hyphenated. + + + + + 0 + 6 + + True @@ -344,19 +347,6 @@ 6 6 12 - - - True - True - True - True - adjustment8 - - - 1 - 0 - - True @@ -371,6 +361,19 @@ 0 + + + True + True + True + True + adjustment8 + + + 1 + 0 + + 0 @@ -408,6 +411,68 @@ 2 + + + + True + False + 0 + 0 + 0 + 3 + + + True + False + Better Spacing + True + hyphenslider + 0 + + + 0 + 0 + + + + + True + True + True + hyphenadjustmentslider + False + + + Set paragraph layout with better spacing or worse spacing, but less hyphenation. + + + + + 1 + 0 + + + + + True + False + Fewer Hyphens + True + hyphenslider + 0 + + + 2 + 0 + + + + + 0 + 10 + 2 + + @@ -434,9 +499,8 @@ GDK_EXPOSURE_MASK 0 none - - + True False @@ -464,6 +528,33 @@ 0 + + + True + False + Paragraph end _zone: + True + spinParagraphEndZone + 0 + + + 1 + 0 + + + + + True + True + True + True + adjustment10 + + + 2 + 0 + + Column @@ -484,6 +575,33 @@ 1 + + + True + False + Column end _zone: + True + spinColumnEndZone + 0 + + + 1 + 1 + + + + + True + True + True + True + adjustment11 + + + 2 + 1 + + Page @@ -504,6 +622,33 @@ 2 + + + True + False + Page end _zone: + True + spinPageEndZone + 0 + + + 1 + 2 + + + + + True + True + True + True + adjustment12 + + + 2 + 2 + + Spread @@ -525,84 +670,17 @@ - - True - True - True - True - adjustment10 - - - 2 - 0 - - - - + True False - Paragraph end _zone: + Spread end _zone: True - spinParagraphEndZone + spinSpreadEndZone 0 1 - 0 - - - - - True - True - True - True - adjustment11 - - - 2 - 1 - - - - - True - False - Column end _zone: - True - spinColumnEndZone - 0 - - - 1 - 1 - - - - - True - True - True - True - adjustment12 - - - 2 - 2 - - - - - True - False - Page end _zone: - True - spinPageEndZone - 0 - - - 1 - 2 + 3 @@ -618,20 +696,6 @@ 3 - - - True - False - Spread end _zone: - True - spinSpreadEndZone - 0 - - - 1 - 3 - - Move Line @@ -652,6 +716,15 @@ 3 + + + + + + + + + @@ -667,7 +740,7 @@ 0 - 2 + 3 2 @@ -706,6 +779,73 @@ 0 + + + True + False + _Type: + True + comboBreakType + 1 + + + 0 + 1 + + + + + True + False + + Page + Column + + + + Select the break type that you want to insert. + + + + + 1 + 1 + + + + + True + False + Position: + True + right + comboBreakPosition + 1 + + + 0 + 2 + + + + + True + False + + Before + After + + + + Select where you want to insert the break. + + + + + 1 + 2 + + With page st_yle: @@ -730,17 +870,45 @@ - + True False - _Type: + + + + + + Page Style + Select the formatting style to use for the first page after the break. + + + + + 1 + 3 + + + + + Page _number: + True + True + False True - comboBreakType - 1 + True + True + + + + + + Assigns the page number that you specify to the page that follows the manual page break. This option is only available if you assign an arbitrary page style to the page that follows manual page break. + + 0 - 1 + 4 @@ -764,101 +932,6 @@ 4 - - - Page _number: - True - True - False - True - True - True - - - - - - Assigns the page number that you specify to the page that follows the manual page break. This option is only available if you assign an arbitrary page style to the page that follows manual page break. - - - - - 0 - 4 - - - - - True - False - Position: - True - right - comboBreakPosition - 1 - - - 0 - 2 - - - - - True - False - - - - - - Page Style - Select the formatting style to use for the first page after the break. - - - - - 1 - 3 - - - - - True - False - - Page - Column - - - - Select the break type that you want to insert. - - - - - 1 - 1 - - - - - True - False - - Before - After - - - - Select where you want to insert the break. - - - - - 1 - 2 - - @@ -895,27 +968,6 @@ 6 6 12 - - - _Allow to split paragraph - True - True - False - True - True - True - - - Shifts the entire paragraph to the next page or column after a break is inserted. - - - - - 0 - 1 - 3 - - _Keep with next paragraph @@ -937,6 +989,27 @@ 3 + + + _Allow splitting paragraph + True + True + False + True + True + True + + + Shifts the entire paragraph to the next page or column after a break is inserted. + + + + + 0 + 1 + 3 + + Don’t split at _beginning of paragraph @@ -962,6 +1035,39 @@ 2 + + + True + True + True + True + adjustment5 + + + + + + Specifies the minimum number of lines in a paragraph before a page break. Select this check box, and then enter a number in the Lines box. + + + + + 1 + 2 + + + + + True + False + lines + 0 + + + 2 + 2 + + Don’t split at _end of paragraph @@ -987,27 +1093,6 @@ 3 - - - True - True - True - True - adjustment5 - - - - - - Specifies the minimum number of lines in a paragraph before a page break. Select this check box, and then enter a number in the Lines box. - - - - - 1 - 2 - - True @@ -1030,18 +1115,6 @@ 3 - - - True - False - lines - 0 - - - 2 - 2 - - True diff --git a/cui/uiconfig/ui/transparencytabpage.ui b/cui/uiconfig/ui/transparencytabpage.ui index 7f18c631c76d..2b595638b8be 100644 --- a/cui/uiconfig/ui/transparencytabpage.ui +++ b/cui/uiconfig/ui/transparencytabpage.ui @@ -111,26 +111,6 @@ 1 - - - _Gradient - True - True - False - True - True - RBT_TRANS_OFF - - - Applies a transparency gradient to the current fill color. Select this option, and then set the gradient properties. - - - - - 0 - 2 - - True @@ -152,6 +132,26 @@ 1 + + + _Gradient + True + True + False + True + True + RBT_TRANS_OFF + + + Applies a transparency gradient to the current fill color. Select this option, and then set the gradient properties. + + + + + 0 + 2 + + @@ -173,111 +173,18 @@ 6 12 - + True - True - True - True - adjustmentPercent5 - - - Enter a transparency value for the endpoint of the gradient, where 0% is fully opaque and 100% is fully transparent. - - + False + 12 + Ty_pe: + True + LB_TRGR_GRADIENT_TYPES + 1 - 1 - 6 - - - - - True - True - True - True - adjustmentPercent4 - - - Enter a transparency value for the beginning point of the gradient, where 0% is fully opaque and 100% is fully transparent. - - - - - 1 - 5 - - - - - True - True - True - True - adjustmentPercent3 - - - Enter the amount by which you want to adjust the transparent area of the gradient. The default value is 0%. - - - - - 1 - 4 - - - - - True - True - True - True - adjustmentDegrees - - - Enter a rotation angle for the gradient. - - - - - 1 - 3 - - - - - True - True - True - True - adjustmentPercent2 - - - Enter the vertical offset for the gradient. - - - - - 1 - 2 - - - - - True - True - True - True - adjustmentPercent1 - - - Enter the horizontal offset for the gradient. - - - - - 1 - 1 + 0 + 0 @@ -303,21 +210,6 @@ 0 - - - True - False - 12 - Ty_pe: - True - LB_TRGR_GRADIENT_TYPES - 1 - - - 0 - 0 - - True @@ -333,6 +225,24 @@ 1 + + + True + True + True + True + adjustmentPercent1 + + + Enter the horizontal offset for the gradient. + + + + + 1 + 1 + + True @@ -348,6 +258,24 @@ 2 + + + True + True + True + True + adjustmentPercent2 + + + Enter the vertical offset for the gradient. + + + + + 1 + 2 + + True @@ -363,6 +291,24 @@ 3 + + + True + True + True + True + adjustmentDegrees + + + Enter a rotation angle for the gradient. + + + + + 1 + 3 + + True @@ -378,6 +324,24 @@ 4 + + + True + True + True + True + adjustmentPercent3 + + + Enter the amount by which you want to adjust the transparent area of the gradient. The default value is 0%. + + + + + 1 + 4 + + True @@ -393,6 +357,24 @@ 5 + + + True + True + True + True + adjustmentPercent4 + + + Enter a transparency value for the beginning point of the gradient, where 0% is fully opaque and 100% is fully transparent. + + + + + 1 + 5 + + True @@ -408,6 +390,24 @@ 6 + + + True + True + True + True + adjustmentPercent5 + + + Enter a transparency value for the endpoint of the gradient, where 0% is fully opaque and 100% is fully transparent. + + + + + 1 + 6 + + False diff --git a/cui/uiconfig/ui/twolinespage.ui b/cui/uiconfig/ui/twolinespage.ui index 083a5649c4c9..865b498fa3d8 100644 --- a/cui/uiconfig/ui/twolinespage.ui +++ b/cui/uiconfig/ui/twolinespage.ui @@ -1,5 +1,5 @@ - + @@ -20,34 +20,34 @@ True - False + False True True - 6 + 6 vertical 12 True - False - 0 - none + False + 0 + none Write in double lines True - True - False - True - True + True + False 12 6 + True + True True - False + False Double-lined @@ -64,62 +64,62 @@ True - False + False True True - 0 - none + 0 + none - + True - False - True - True - 6 - True + False 12 6 + True + True + 6 + True True - False + False Initial character - 0 - 0 + 0 + 0 True - False + False Final character - 1 - 0 + 1 + 0 True - True + True True True - in + in True - True + True True True liststore1 - False - False - 0 - False + False + False + 0 + False @@ -137,28 +137,28 @@ - 0 - 1 + 0 + 1 True - True + True True True - in + in True - True + True True True liststore2 - False - False - 0 - False + False + False + 0 + False @@ -176,8 +176,8 @@ - 1 - 1 + 1 + 1 @@ -185,7 +185,7 @@ True - False + False Enclosing Characters @@ -202,22 +202,22 @@ True - True - never - never - in - 12 - 6 - 12 + True end + 12 + 12 + 6 + never + never + in True - False + False True - False + False Preview @@ -231,7 +231,7 @@ False True - end + end 2 diff --git a/cui/uiconfig/ui/uipickerdialog.ui b/cui/uiconfig/ui/uipickerdialog.ui index 22b1b2d61018..84e4135d77f0 100644 --- a/cui/uiconfig/ui/uipickerdialog.ui +++ b/cui/uiconfig/ui/uipickerdialog.ui @@ -120,7 +120,7 @@ - reset + reset ok cancel help diff --git a/cui/uiconfig/ui/welcomedialog.ui b/cui/uiconfig/ui/welcomedialog.ui index 6391699daa1a..c8803eae3cc1 100644 --- a/cui/uiconfig/ui/welcomedialog.ui +++ b/cui/uiconfig/ui/welcomedialog.ui @@ -23,12 +23,11 @@ end - Do Show Again + Do not show again True True False True - True True @@ -200,7 +199,7 @@ - reset + reset ok cancel diff --git a/cui/uiconfig/ui/wordcompletionpage.ui b/cui/uiconfig/ui/wordcompletionpage.ui index aaa6c4e04e3b..e3e7ba3a2c5f 100644 --- a/cui/uiconfig/ui/wordcompletionpage.ui +++ b/cui/uiconfig/ui/wordcompletionpage.ui @@ -1,20 +1,20 @@ - + 50 4294967295 500 - 25 - 100 + 25 + 100 5 100 10 - 1 - 10 + 1 + 10 @@ -26,37 +26,37 @@ True - False + False True True - 6 + 6 vertical - + True - False + False True True - 6 - 12 + 6 + 12 - + True - False + False True - 6 + 6 - + True - False - 6 + False + 6 True - False + False Word Completion 0 @@ -64,18 +64,18 @@ - 0 - 0 + 0 + 0 Enable word _completion True - True - False - True - True + True + False + True + True Stores frequently used words, and automatically completes a word after you type three letters that match the first three letters of a stored word. @@ -83,25 +83,25 @@ - 0 - 1 + 0 + 1 - + True - False - 6 + False 18 + 6 _Append space True - True - False - True - True + True + False + True + True If you do not add punctuation after the word then a space is added automatically. @@ -109,18 +109,18 @@ - 0 - 0 + 0 + 0 _Show as tip True - True - False - True - True + True + False + True + True Displays the completed word as a Help Tip. @@ -128,53 +128,53 @@ - 0 - 1 + 0 + 1 - 0 - 2 + 0 + 2 - 0 - 0 + 0 + 0 - + True - False - True - 6 - 6 + False 18 + True + 6 + 6 True - False + False Mi_n. word length: - True - maxentries + True + maxentries 0 - 0 - 1 + 0 + 1 True - True + True 100 + True adjustment2 100 - True Enter the minimum word length for a word to become eligible for the word completion feature. @@ -182,32 +182,32 @@ - 1 - 1 + 1 + 1 True - False + False _Max. entries: - True - maxentries + True + maxentries 0 - 0 - 2 + 0 + 2 True - True + True 500 + True adjustment1 500 - True Enter the maximum number of words that you want to store in the Word Completion list. @@ -215,28 +215,28 @@ - 1 - 2 + 1 + 2 True - False + False Acc_ept with: - True - acceptwith + True + acceptwith 0 - 0 - 0 + 0 + 0 True - False + False Select the key that you want to use to accept the automatic word completion. @@ -244,35 +244,35 @@ - 1 - 0 + 1 + 0 - 0 - 1 + 0 + 1 - 0 - 0 + 0 + 0 - + True - False + False True True - 6 - 12 + 6 + 12 True - False + False Collected Words 0 @@ -280,28 +280,28 @@ - 0 - 0 + 0 + 0 True - True + True True True - in + in True - True - True + True + True True True liststore2 - False - 0 - False + False + 0 + False @@ -326,18 +326,18 @@ - 0 - 2 + 0 + 2 _When closing a document, remove the words collected from it from the list True - True - False - True - True + True + False + True + True When enabled, the list gets cleared when closing the current document. When disabled, makes the current Word Completion list available to other documents after you close the current document. The list remains available until you exit office suite. @@ -345,22 +345,22 @@ - 0 - 3 + 0 + 3 True - False + False C_ollect words True - True - False - True - True + True + False + True + True Adds the frequently used words to a list. To remove a word from the Word Completion list, select the word, and then click Delete Entry. @@ -377,11 +377,11 @@ _Delete True - True - True + True + True end True - True + True Removes the selected word or words from the Word Completion list. @@ -396,14 +396,14 @@ - 0 - 1 + 0 + 1 - 1 - 0 + 1 + 0 diff --git a/dbaccess/inc/pch/precompiled_dbahsql.hxx b/dbaccess/inc/pch/precompiled_dbahsql.hxx index 443b7f2e194b..b0841f0aa582 100644 --- a/dbaccess/inc/pch/precompiled_dbahsql.hxx +++ b/dbaccess/inc/pch/precompiled_dbahsql.hxx @@ -27,7 +27,6 @@ #if PCH_LEVEL >= 2 #include #include -#include #endif // PCH_LEVEL >= 2 #if PCH_LEVEL >= 3 #include diff --git a/dbaccess/inc/pch/precompiled_dbu.hxx b/dbaccess/inc/pch/precompiled_dbu.hxx index 6e9a4c41bcd1..1514b37dd2f4 100644 --- a/dbaccess/inc/pch/precompiled_dbu.hxx +++ b/dbaccess/inc/pch/precompiled_dbu.hxx @@ -113,7 +113,6 @@ #include #include #include -#include #include #include #endif // PCH_LEVEL >= 2 diff --git a/dbaccess/inc/strings.hrc b/dbaccess/inc/strings.hrc index c35b2066eed3..b3d94ee84443 100644 --- a/dbaccess/inc/strings.hrc +++ b/dbaccess/inc/strings.hrc @@ -139,6 +139,12 @@ #define STR_ERROR_PARSING_STATEMENT NC_("STR_ERROR_PARSING_STATEMENT", "$object$ is based on an SQL command which could not be parsed.") // To translators: for $object$, one of the values of the RSC_QUERY_OBJECT_TYPE resource (except \"SQL command\", which doesn't make sense here) will be inserted. #define STR_INFO_OPENING_IN_SQL_VIEW NC_("STR_INFO_OPENING_IN_SQL_VIEW", "$object$ will be opened in SQL view.") +// tdf#42713: warn before switching to Design View when SQL contains comments +// To translators: for $object$, one of the values of the RSC_QUERY_OBJECT_TYPE resource will be inserted. +#define STR_QRY_COMMENTS_WARNING_3CHOICES NC_("STR_QRY_COMMENTS_WARNING_3CHOICES", "$object$ contains SQL comments.\n\nIf you edit it in Design View, the comments will be lost.\n\nContinue anyway or start editing in SQL View?") +// To translators: for $object$, one of the values of the RSC_QUERY_OBJECT_TYPE resource will be inserted. +#define STR_QRY_FORMAT_WARNING_3CHOICES NC_("STR_QRY_FORMAT_WARNING_3CHOICES", "$object$ was last edited in SQL View.\n\nIf you edit it in Design View, it is possible that the SQL formatting (including any comments) will be rewritten and lost.\n\nContinue anyway or start editing in SQL View?") +#define STR_QRY_FORMAT_WARNING_2CHOICES NC_("STR_QRY_FORMAT_WARNING_2CHOICES", "Switching to Design View might rewrite this query's SQL, and its current formatting (including any comments) will be lost.\n\nContinue anyway?") #define STR_STATEMENT_WITHOUT_RESULT_SET NC_("STR_STATEMENT_WITHOUT_RESULT_SET", "The query does not create a result set, and thus cannot be part of another query.") #define RID_STR_COLUMN_FORMAT NC_("RID_STR_COLUMN_FORMAT", "Column ~Format...") diff --git a/dbaccess/inc/strings.hxx b/dbaccess/inc/strings.hxx index d1668dd24517..e838ab8a2552 100644 --- a/dbaccess/inc/strings.hxx +++ b/dbaccess/inc/strings.hxx @@ -249,6 +249,7 @@ inline constexpr OUString SERVICE_SDB_DIRECTSQLDIALOG inline constexpr OUString PROPERTY_QUERYDESIGNVIEW(u"QueryDesignView"_ustr); inline constexpr OUString PROPERTY_GRAPHICAL_DESIGN(u"GraphicalDesign"_ustr); +inline constexpr OUString PROPERTY_FORMAT_WARNING_SHOWN(u"FormatWarningShown"_ustr); inline constexpr OUString PROPERTY_HELP_URL(u"HelpURL"_ustr); inline constexpr OUString FRAME_NAME_QUERY_PREVIEW = u"QueryPreview"_ustr; inline constexpr OUString SERVICE_CONTROLDEFAULT = u"com.sun.star.comp.dbu.OColumnControl"_ustr; diff --git a/dbaccess/qa/uitest/data/tdf42713.odb b/dbaccess/qa/uitest/data/tdf42713.odb new file mode 100644 index 000000000000..05e177407c01 Binary files /dev/null and b/dbaccess/qa/uitest/data/tdf42713.odb differ diff --git a/dbaccess/qa/uitest/data/tdf46841.odb b/dbaccess/qa/uitest/data/tdf46841.odb new file mode 100644 index 000000000000..b3bc01aaba81 Binary files /dev/null and b/dbaccess/qa/uitest/data/tdf46841.odb differ diff --git a/dbaccess/qa/uitest/query/query_format_preservation.py b/dbaccess/qa/uitest/query/query_format_preservation.py new file mode 100644 index 000000000000..649827a701fe --- /dev/null +++ b/dbaccess/qa/uitest/query/query_format_preservation.py @@ -0,0 +1,77 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# + +# Regression test for tdf#42713 - SQL comments are preserved when working +# with queries containing comments in the Base query editor. +# Also covers tdf#46841 - a query's SQL formatting more generally (not just +# comments) is preserved when it was last saved from SQL View. + +from uitest.framework import UITestCase +from uitest.uihelper.common import get_url_for_data_file, get_state_as_dict + +from com.sun.star.awt import Toolkit + + +class QueryCommentPreservation(UITestCase): + """Test that SQL comments in a query are preserved when opening.""" + + def test_comment_preserved_when_opening(self): + """A saved query with comments opens in SQL view with comments intact (tdf#42713).""" + with self.ui_test.load_file( + get_url_for_data_file("tdf42713.odb") + ) as document: + xToolkit = Toolkit.create(self.xContext) + + self.xUITest.executeCommand(".uno:DBViewQueries") + xToolkit.waitUntilAllIdlesDispatched() + + # The file contains a single query ("q_with_comment"), so SelectAll + # selects exactly that one entry and DBQueryEdit opens it. + self.xUITest.executeCommand(".uno:SelectAll") + + with self.ui_test.open_subcomponent_through_command( + ".uno:DBQueryEdit" + ) as xQueryFrame: + # Query opens in SQL view (forced due to comments, tdf#42713) + xSql = self.xUITest.getTopFocusWindow().getChild("sql") + sql_text = get_state_as_dict(xSql)["Text"] + self.assertIn( + "-- my comment", + sql_text, + "SQL comment must be visible when opening query; got: " + + sql_text, + ) + + def test_format_preserved_when_last_edited_in_sql_view(self): + """A query with no comments, but last saved from SQL View, opens in + SQL View with its formatting intact instead of being + canonicalized by Design View (tdf#46841).""" + with self.ui_test.load_file( + get_url_for_data_file("tdf46841.odb") + ) as document: + xToolkit = Toolkit.create(self.xContext) + + self.xUITest.executeCommand(".uno:DBViewQueries") + xToolkit.waitUntilAllIdlesDispatched() + + self.xUITest.executeCommand(".uno:SelectAll") + + with self.ui_test.open_subcomponent_through_command( + ".uno:DBQueryEdit" + ) as xQueryFrame: + xSql = self.xUITest.getTopFocusWindow().getChild("sql") + sql_text = get_state_as_dict(xSql)["Text"] + self.assertEqual( + 'SELECT "object"."description" \nFROM "object"', + sql_text, + "Query last saved from SQL View must open in SQL View " + "with its formatting intact; got: " + sql_text, + ) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/dbaccess/qa/unit/firebird.cxx b/dbaccess/qa/unit/firebird.cxx index 5f2f4077125e..3e8b05131ce7 100644 --- a/dbaccess/qa/unit/firebird.cxx +++ b/dbaccess/qa/unit/firebird.cxx @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,11 +30,13 @@ public: void testEmptyDBConnection(); void testIntegerDatabase(); void testTdf132924(); + void testTdf153057(); CPPUNIT_TEST_SUITE(FirebirdTest); CPPUNIT_TEST(testEmptyDBConnection); CPPUNIT_TEST(testIntegerDatabase); CPPUNIT_TEST(testTdf132924); + CPPUNIT_TEST(testTdf153057); CPPUNIT_TEST_SUITE_END(); }; @@ -113,6 +117,83 @@ void FirebirdTest::testTdf132924() CPPUNIT_ASSERT_EQUAL(u"TestName"_ustr, xRow->getString(xColumnLocate->findColumn(u"TestName"_ustr))); } +/** + * Test for tdf#153057: filtering on DATE, TIME and TIMESTAMP columns via + * a string value. Before the fix, OPreparedStatement::setString() had no + * cases for DataType::DATE / TIME / TIMESTAMP and would throw + * "Incorrect type for setString" when a filter string was applied to such + * a column in Base. + */ +void FirebirdTest::testTdf153057() +{ + // Create a fresh embedded Firebird database in a temp file. + createTempCopy(u"firebird_empty.odb"); + uno::Reference xDocument = getDocumentForUrl(maTempFile.GetURL()); + + uno::Reference xConnection = getConnectionForDocument(xDocument); + CPPUNIT_ASSERT(xConnection.is()); + + // Create a table with DATE, TIME and TIMESTAMP columns and two rows. + uno::Reference xStmt = xConnection->createStatement(); + xStmt->execute(u"CREATE TABLE \"TEMPORAL\" (" + " \"ID\" INTEGER NOT NULL PRIMARY KEY," + " \"D\" DATE," + " \"T\" TIME," + " \"TS\" TIMESTAMP)"_ustr); + + xStmt->execute( + u"INSERT INTO \"TEMPORAL\" VALUES(1, '2024-07-15', '14:30:00', '2024-07-15 14:30:00')"_ustr); + xStmt->execute( + u"INSERT INTO \"TEMPORAL\" VALUES(2, '2025-01-01', '09:00:00', '2025-01-01 09:00:00')"_ustr); + xConnection->commit(); + + // --- Test DATE filtering via setString --- + // Before the fix this would throw "Incorrect type for setString". + { + uno::Reference xPS = xConnection->prepareStatement( + u"SELECT \"ID\" FROM \"TEMPORAL\" WHERE \"D\" = ?"_ustr); + uno::Reference xParams(xPS, UNO_QUERY_THROW); + xParams->setString(1, u"2024-07-15"_ustr); + + uno::Reference xRS = xPS->executeQuery(); + CPPUNIT_ASSERT_MESSAGE("DATE filter: expected at least one row", xRS->next()); + uno::Reference xRow(xRS, UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL_MESSAGE("DATE filter: wrong row returned", sal_Int32(1), + xRow->getInt(1)); + CPPUNIT_ASSERT_MESSAGE("DATE filter: expected exactly one row", !xRS->next()); + } + + // --- Test TIME filtering via setString --- + { + uno::Reference xPS = xConnection->prepareStatement( + u"SELECT \"ID\" FROM \"TEMPORAL\" WHERE \"T\" = ?"_ustr); + uno::Reference xParams(xPS, UNO_QUERY_THROW); + xParams->setString(1, u"09:00:00"_ustr); + + uno::Reference xRS = xPS->executeQuery(); + CPPUNIT_ASSERT_MESSAGE("TIME filter: expected at least one row", xRS->next()); + uno::Reference xRow(xRS, UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL_MESSAGE("TIME filter: wrong row returned", sal_Int32(2), + xRow->getInt(1)); + CPPUNIT_ASSERT_MESSAGE("TIME filter: expected exactly one row", !xRS->next()); + } + + // --- Test TIMESTAMP filtering via setString --- + { + uno::Reference xPS = xConnection->prepareStatement( + u"SELECT \"ID\" FROM \"TEMPORAL\" WHERE \"TS\" = ?"_ustr); + uno::Reference xParams(xPS, UNO_QUERY_THROW); + xParams->setString(1, u"2025-01-01 09:00:00"_ustr); + + uno::Reference xRS = xPS->executeQuery(); + CPPUNIT_ASSERT_MESSAGE("TIMESTAMP filter: expected at least one row", xRS->next()); + uno::Reference xRow(xRS, UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL_MESSAGE("TIMESTAMP filter: wrong row returned", sal_Int32(2), + xRow->getInt(1)); + CPPUNIT_ASSERT_MESSAGE("TIMESTAMP filter: expected exactly one row", !xRS->next()); + } +} + CPPUNIT_TEST_SUITE_REGISTRATION(FirebirdTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/dbaccess/qa/unoapi/dbaccess.sce b/dbaccess/qa/unoapi/dbaccess.sce index 13fa966abe1a..367655c50a14 100644 --- a/dbaccess/qa/unoapi/dbaccess.sce +++ b/dbaccess/qa/unoapi/dbaccess.sce @@ -29,4 +29,3 @@ -o dbaccess.OSQLMessageDialog -o dbaccess.OSingleSelectQueryComposer #i95611 -o dbaccess.SbaXGridControl -#i84128 -o dbaccess.TableWindowAccessibility diff --git a/dbaccess/qa/unoapi/knownissues.xcl b/dbaccess/qa/unoapi/knownissues.xcl index 8c635d097e53..e53d3041e52a 100644 --- a/dbaccess/qa/unoapi/knownissues.xcl +++ b/dbaccess/qa/unoapi/knownissues.xcl @@ -47,10 +47,6 @@ dbaccess.SbaXGridControl::com::sun::star::awt::XWindow dbaccess.ODatabaseSource::com::sun::star::beans::XPropertySet dbaccess.OCommandDefinition::com::sun::star::beans::XPropertySet -### i84128 ### -dbaccess.TableWindowAccessibility -# -> disabled in dbaccess.sce - ### i87247 ### dbaccess.DBContentLoader::com::sun::star::frame::XFrameLoader @@ -77,4 +73,4 @@ dbaccess.ORowSet::com::sun::star::sdbc::XResultSetUpdate ### i98007 ### dbaccess.ODatasourceBrowser -# -> disabled in dbaccess.sce \ No newline at end of file +# -> disabled in dbaccess.sce diff --git a/dbaccess/source/core/api/BookmarkSet.cxx b/dbaccess/source/core/api/BookmarkSet.cxx index 23e5f3abebd7..16af1a8a6b10 100644 --- a/dbaccess/source/core/api/BookmarkSet.cxx +++ b/dbaccess/source/core/api/BookmarkSet.cxx @@ -85,7 +85,7 @@ void OBookmarkSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity:: updateColumn(i,xUpdRow,*aIter); } xUpd->insertRow(); - // We must go away from the insert row when the insert is finish + // We must go away from the insert row when the insert is finished xUpd->moveToCurrentRow(); (*_rInsertRow->begin()) = m_xRowLocate->getBookmark(); } diff --git a/dbaccess/source/core/api/CacheSet.cxx b/dbaccess/source/core/api/CacheSet.cxx index 3be4a43b61d2..e08c4f71dfd3 100644 --- a/dbaccess/source/core/api/CacheSet.cxx +++ b/dbaccess/source/core/api/CacheSet.cxx @@ -168,7 +168,7 @@ void OCacheSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQ aValues[aValues.getLength() - 1] = ')'; aSql.append(aValues); - // now create end execute the prepared statement + // now create and execute the prepared statement { Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); Reference< XParameters > xParameter(xPrep,UNO_QUERY); @@ -288,7 +288,7 @@ void OCacheSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOri ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_UPDATE_MISSING_CONDITION ), StandardSQLState::GENERAL_ERROR, *this ); - // now create end execute the prepared statement + // now create and execute the prepared statement Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); Reference< XParameters > xParameter(xPrep,UNO_QUERY); sal_Int32 i = 1; diff --git a/dbaccess/source/core/api/RowSetCache.cxx b/dbaccess/source/core/api/RowSetCache.cxx index 324398a60c19..49d2ea2d39c8 100644 --- a/dbaccess/source/core/api/RowSetCache.cxx +++ b/dbaccess/source/core/api/RowSetCache.cxx @@ -1089,7 +1089,7 @@ bool ORowSetCache::last( ) } m_nPosition = m_xCacheSet->getRow(); moveWindow(); - // we have to repositioning because moveWindow can modify the cache + // we have to reposition because moveWindow can modify the cache m_xCacheSet->last(); OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < static_cast(m_pMatrix->size()),"Position is behind end()!"); m_aMatrixIter = calcPosition(); @@ -1390,7 +1390,7 @@ void ORowSetCache::moveToInsertRow( ) if(!m_aInsertRow->is()) *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount()); - // we don't unbound the bookmark column + // we don't unbind the bookmark column ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->begin()+1; ORowSetValueVector::Vector::const_iterator aEnd = (*m_aInsertRow)->end(); for(sal_Int32 i = 1;aIter != aEnd;++aIter,++i) @@ -1476,7 +1476,7 @@ void ORowSetCache::setUpdateIterator(const ORowSetMatrix::iterator& _rOriginalRo *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount()); (*(*m_aInsertRow)) = *(*_rOriginalRow); - // we don't unbound the bookmark column + // we don't unbind the bookmark column for(auto& rItem : **m_aInsertRow) rItem.setModified(false); } @@ -1554,7 +1554,7 @@ bool ORowSetCache::checkJoin(const Reference< XConnection>& _xConnection, OSL_ENSURE(pTableRefCommalist,"NO tables why!?"); if(pTableRefCommalist && pTableRefCommalist->count() == 1) { - // we found only one element so it must some kind of join here + // we found only one element so it must be some kind of join here OSQLParseNode* pJoin = pTableRefCommalist->getByRule(::connectivity::OSQLParseNode::qualified_join); if(pJoin) { // we are only interested in qualified joins like RIGHT or LEFT @@ -1601,7 +1601,7 @@ bool ORowSetCache::checkJoin(const Reference< XConnection>& _xConnection, void ORowSetCache::clearInsertRow() { - // we don't unbound the bookmark column + // we don't unbind the bookmark column if ( m_aInsertRow != m_pInsertMatrix->end() && m_aInsertRow->is() ) { ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->begin()+1; diff --git a/dbaccess/source/core/api/WrappedResultSet.cxx b/dbaccess/source/core/api/WrappedResultSet.cxx index 275a0061cff7..340173a23045 100644 --- a/dbaccess/source/core/api/WrappedResultSet.cxx +++ b/dbaccess/source/core/api/WrappedResultSet.cxx @@ -79,7 +79,7 @@ void WrappedResultSet::insertRow( const ORowSetRow& _rInsertRow,const connectivi updateColumn(i,m_xUpdRow,*aIter); } m_xUpd->insertRow(); - // We must go away from the insert row when the insert is finish + // We must go away from the insert row when the insert is finished m_xUpd->moveToCurrentRow(); (*_rInsertRow->begin()) = getBookmark(); } diff --git a/dbaccess/source/core/api/query.cxx b/dbaccess/source/core/api/query.cxx index 86e50042ece7..83e818c430bb 100644 --- a/dbaccess/source/core/api/query.cxx +++ b/dbaccess/source/core/api/query.cxx @@ -169,7 +169,7 @@ void OQuery::rebuildColumns() xColumns = OPrivateColumns::createWithIntrinsicNames( aParseColumns, xDBMeta->supportsMixedCaseQuotedIdentifiers(), *this, m_aMutex ).release(); if ( !xColumns.is() ) - throw RuntimeException(); + throw RuntimeException(u"dbaccess: OQuery::impl_initColumns_nothrow: failed to create columns"_ustr); } const Sequence aColNames = xColumns->getElementNames(); diff --git a/dbaccess/source/core/dataaccess/databasedocument.cxx b/dbaccess/source/core/dataaccess/databasedocument.cxx index b1e561c0d789..fffda2898111 100644 --- a/dbaccess/source/core/dataaccess/databasedocument.cxx +++ b/dbaccess/source/core/dataaccess/databasedocument.cxx @@ -78,6 +78,9 @@ #include #include +#include +#include + using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::frame; @@ -546,22 +549,10 @@ namespace const Sequence< Reference< XComponent > > aComponents( xDatabaseUI->getSubComponents() ); - bool isAnyModified = false; - for ( auto const & xComponent : aComponents ) - { - Reference< XModifiable > xModify( xComponent, UNO_QUERY ); - if ( xModify.is() ) - { - isAnyModified = xModify->isModified(); - continue; - } - - // TODO: clarify: anything else to care for? Both the sub components with and without model - // should support the XModifiable interface, so I think nothing more is needed here. - OSL_FAIL( "lcl_hasAnyModifiedSubComponent_throw: anything left to do here?" ); - } - - return isAnyModified; + return std::ranges::any_of(aComponents, [](const Reference& xComp) { + Reference< XModifiable > xModify( xComp, UNO_QUERY ); + return xModify.is() && xModify->isModified(); + }); } } @@ -586,11 +577,8 @@ sal_Bool SAL_CALL ODatabaseDocument::wasModifiedSinceLastSave() try { - for (auto const& controller : m_aControllers) - { - if ( lcl_hasAnyModifiedSubComponent_throw(controller) ) - return true; - } + if (std::ranges::any_of(m_aControllers, lcl_hasAnyModifiedSubComponent_throw)) + return true; } catch( const Exception& ) { @@ -1596,8 +1584,7 @@ void ODatabaseDocument::WriteThroughComponent( const Reference< XOutputStream >& Sequence aArgs( 1 + _rArguments.getLength() ); auto pArgs = aArgs.getArray(); pArgs[0] <<= xSaxWriter; - for ( sal_Int32 i = 0; i < _rArguments.getLength(); ++i ) - pArgs[ i+1 ] = _rArguments[i]; + std::ranges::copy(_rArguments, pArgs + 1); // get filter component Reference< XExporter > xExporter( m_pImpl->m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext(rServiceName, aArgs, m_pImpl->m_aContext), UNO_QUERY_THROW ); diff --git a/dbaccess/source/core/inc/migrwarndlg.hxx b/dbaccess/source/core/inc/migrwarndlg.hxx index 00eb07a85ccb..02ddc9ce2a00 100644 --- a/dbaccess/source/core/inc/migrwarndlg.hxx +++ b/dbaccess/source/core/inc/migrwarndlg.hxx @@ -8,8 +8,9 @@ */ #pragma once +#include #include -#include +#include namespace dbaccess { diff --git a/dbaccess/source/filter/hsqldb/hsqlimport.cxx b/dbaccess/source/filter/hsqldb/hsqlimport.cxx index c68f6112f0eb..49d95e235753 100644 --- a/dbaccess/source/filter/hsqldb/hsqlimport.cxx +++ b/dbaccess/source/filter/hsqldb/hsqlimport.cxx @@ -34,8 +34,7 @@ #include #include -#include - +#include #include "hsqlimport.hxx" #include "parseschema.hxx" #include "rowinputbinary.hxx" diff --git a/dbaccess/source/ui/app/AppController.cxx b/dbaccess/source/ui/app/AppController.cxx index d8adf5ba7e3b..e4311fdb34c1 100644 --- a/dbaccess/source/ui/app/AppController.cxx +++ b/dbaccess/source/ui/app/AppController.cxx @@ -71,7 +71,6 @@ #include #include -#include #include #include @@ -2393,7 +2392,7 @@ sal_Int8 OApplicationController::executeDrop( const ExecuteDropEvent& _rEvt ) { m_aAsyncDrop.aDroppedData = ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData); - // asynchron because we some dialogs and we aren't allowed to show them while in D&D + // asynchronously because we have some dialogs and we aren't allowed to show them while in D&D m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop)); return DND_ACTION_COPY; } @@ -2440,7 +2439,7 @@ sal_Int8 OApplicationController::executeDrop( const ExecuteDropEvent& _rEvt ) if ( nAction != DND_ACTION_NONE ) { m_aAsyncDrop.nAction = nAction; - // asynchron because we some dialogs and we aren't allowed to show them while in D&D + // asynchronously because we have some dialogs and we aren't allowed to show them while in D&D m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop)); } else @@ -2452,7 +2451,7 @@ sal_Int8 OApplicationController::executeDrop( const ExecuteDropEvent& _rEvt ) SharedConnection xConnection( ensureConnection() ); if ( xConnection.is() && m_aTableCopyHelper.copyTagTable( aDroppedData, m_aAsyncDrop, xConnection ) ) { - // asynchron because we some dialogs and we aren't allowed to show them while in D&D + // asynchronously because we have some dialogs and we aren't allowed to show them while in D&D m_nAsyncDrop = Application::PostUserEvent(LINK(this, OApplicationController, OnAsyncDrop)); return DND_ACTION_COPY; } @@ -2500,7 +2499,7 @@ void OApplicationController::OnFirstControllerConnected() } // if we have forms or reports which contain macros/scripts, then show a warning - // which suggests the user to migrate them to the database document + // which suggests that the user migrate them to the database document Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY ); if ( xDocumentScripts.is() ) { diff --git a/dbaccess/source/ui/app/AppControllerDnD.cxx b/dbaccess/source/ui/app/AppControllerDnD.cxx index 9ddad9c3dea2..6710d6f778df 100644 --- a/dbaccess/source/ui/app/AppControllerDnD.cxx +++ b/dbaccess/source/ui/app/AppControllerDnD.cxx @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -46,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/dbaccess/source/ui/app/AppControllerGen.cxx b/dbaccess/source/ui/app/AppControllerGen.cxx index 3a2512d35cb0..b0797a2a3294 100644 --- a/dbaccess/source/ui/app/AppControllerGen.cxx +++ b/dbaccess/source/ui/app/AppControllerGen.cxx @@ -58,7 +58,7 @@ #include #include #include -#include +#include #include namespace dbaui diff --git a/dbaccess/source/ui/app/AppDetailPageHelper.cxx b/dbaccess/source/ui/app/AppDetailPageHelper.cxx index f8e97eda7192..1b8c4f6b5db9 100644 --- a/dbaccess/source/ui/app/AppDetailPageHelper.cxx +++ b/dbaccess/source/ui/app/AppDetailPageHelper.cxx @@ -51,6 +51,8 @@ #include #include #include +#include +#include #include #include #include "AppController.hxx" diff --git a/dbaccess/source/ui/app/AppDetailPageHelper.hxx b/dbaccess/source/ui/app/AppDetailPageHelper.hxx index 001ff36f3396..b7a9cb665052 100644 --- a/dbaccess/source/ui/app/AppDetailPageHelper.hxx +++ b/dbaccess/source/ui/app/AppDetailPageHelper.hxx @@ -27,10 +27,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include "DocumentInfoPreview.hxx" diff --git a/dbaccess/source/ui/app/AppDetailView.cxx b/dbaccess/source/ui/app/AppDetailView.cxx index ff48b3d1704c..095ed7f77fa5 100644 --- a/dbaccess/source/ui/app/AppDetailView.cxx +++ b/dbaccess/source/ui/app/AppDetailView.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include "AppDetailPageHelper.hxx" #include #include diff --git a/dbaccess/source/ui/app/AppDetailView.hxx b/dbaccess/source/ui/app/AppDetailView.hxx index 90bfe4720f5f..cc5346ee8787 100644 --- a/dbaccess/source/ui/app/AppDetailView.hxx +++ b/dbaccess/source/ui/app/AppDetailView.hxx @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/dbaccess/source/ui/app/AppIconControl.hxx b/dbaccess/source/ui/app/AppIconControl.hxx index 119643df8f05..4105ffc6d845 100644 --- a/dbaccess/source/ui/app/AppIconControl.hxx +++ b/dbaccess/source/ui/app/AppIconControl.hxx @@ -21,7 +21,6 @@ #include #include #include -#include #include class MnemonicGenerator; diff --git a/dbaccess/source/ui/app/AppTitleWindow.cxx b/dbaccess/source/ui/app/AppTitleWindow.cxx index a458a96e8dfa..64bfc99fe702 100644 --- a/dbaccess/source/ui/app/AppTitleWindow.cxx +++ b/dbaccess/source/ui/app/AppTitleWindow.cxx @@ -17,10 +17,13 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include -#include #include "AppTitleWindow.hxx" +#include + +#include +#include + namespace dbaui { OTitleWindow::OTitleWindow(weld::Container* pParent, TranslateId pTitleId) diff --git a/dbaccess/source/ui/app/AppView.cxx b/dbaccess/source/ui/app/AppView.cxx index aa8124934334..f4c3f2e83681 100644 --- a/dbaccess/source/ui/app/AppView.cxx +++ b/dbaccess/source/ui/app/AppView.cxx @@ -22,7 +22,8 @@ #include #include #include -#include +#include +#include #include #include #include "AppDetailView.hxx" diff --git a/dbaccess/source/ui/app/AppView.hxx b/dbaccess/source/ui/app/AppView.hxx index 1ce62188ea7c..415be5da1872 100644 --- a/dbaccess/source/ui/app/AppView.hxx +++ b/dbaccess/source/ui/app/AppView.hxx @@ -24,8 +24,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/dbaccess/source/ui/app/DocumentInfoPreview.hxx b/dbaccess/source/ui/app/DocumentInfoPreview.hxx index 0c9548d0a759..f4cbe21ecbf5 100644 --- a/dbaccess/source/ui/app/DocumentInfoPreview.hxx +++ b/dbaccess/source/ui/app/DocumentInfoPreview.hxx @@ -25,7 +25,7 @@ #include -namespace com :: sun :: star :: uno { template class Reference; } +namespace com::sun::star::uno { template class Reference; } namespace com::sun::star { namespace document { class XDocumentProperties; } diff --git a/dbaccess/source/ui/browser/brwctrlr.cxx b/dbaccess/source/ui/browser/brwctrlr.cxx index b3e3a6df87ac..fcc775f5f008 100644 --- a/dbaccess/source/ui/browser/brwctrlr.cxx +++ b/dbaccess/source/ui/browser/brwctrlr.cxx @@ -73,7 +73,7 @@ #include #include #include -#include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; diff --git a/dbaccess/source/ui/browser/dsbrowserDnD.cxx b/dbaccess/source/ui/browser/dsbrowserDnD.cxx index 7690f339e226..dc67c0b64050 100644 --- a/dbaccess/source/ui/browser/dsbrowserDnD.cxx +++ b/dbaccess/source/ui/browser/dsbrowserDnD.cxx @@ -143,7 +143,7 @@ namespace dbaui m_aAsyncDrop.aDroppedData = ODataAccessObjectTransferable::extractObjectDescriptor(aDroppedData); m_aAsyncDrop.xDroppedAt = std::move(xHitEntry); - // asynchron because we some dialogs and we aren't allowed to show them while in D&D + // asynchronously because we have some dialogs and we aren't allowed to show them while in D&D m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop)); return DND_ACTION_COPY; } @@ -157,7 +157,7 @@ namespace dbaui { m_aAsyncDrop.xDroppedAt = std::move(xHitEntry); - // asynchron because we some dialogs and we aren't allowed to show them while in D&D + // asynchronously because we have some dialogs and we aren't allowed to show them while in D&D m_nAsyncDrop = Application::PostUserEvent(LINK(this, SbaTableQueryBrowser, OnAsyncDrop)); return DND_ACTION_COPY; } diff --git a/dbaccess/source/ui/browser/genericcontroller.cxx b/dbaccess/source/ui/browser/genericcontroller.cxx index db913fc2e2bd..ebab12356cd8 100644 --- a/dbaccess/source/ui/browser/genericcontroller.cxx +++ b/dbaccess/source/ui/browser/genericcontroller.cxx @@ -20,7 +20,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/dbaccess/source/ui/browser/sbagrid.cxx b/dbaccess/source/ui/browser/sbagrid.cxx index 035ba9cdd34c..2af952b819fd 100644 --- a/dbaccess/source/ui/browser/sbagrid.cxx +++ b/dbaccess/source/ui/browser/sbagrid.cxx @@ -626,7 +626,7 @@ void SbaGridControl::dispose() FmGridControl::dispose(); } -VclPtr SbaGridControl::imp_CreateHeaderBar(BrowseBox* pParent) +VclPtr SbaGridControl::imp_CreateHeaderBar(BrowseBox* pParent) { return VclPtr::Create(pParent); } diff --git a/dbaccess/source/ui/browser/unodatbr.cxx b/dbaccess/source/ui/browser/unodatbr.cxx index 2ab0b34bc02b..bba56d79b324 100644 --- a/dbaccess/source/ui/browser/unodatbr.cxx +++ b/dbaccess/source/ui/browser/unodatbr.cxx @@ -93,7 +93,8 @@ #include #include #include -#include +#include +#include #include diff --git a/dbaccess/source/ui/control/RelationControl.cxx b/dbaccess/source/ui/control/RelationControl.cxx index daf471e93b9c..f4bfa6ab77be 100644 --- a/dbaccess/source/ui/control/RelationControl.cxx +++ b/dbaccess/source/ui/control/RelationControl.cxx @@ -51,8 +51,7 @@ namespace dbaui using namespace ::com::sun::star::container; using namespace svt; - typedef ::svt::EditBrowseBox ORelationControl_Base; - class ORelationControl : public ORelationControl_Base + class ORelationControl : public svt::EditBrowseBox { friend class OTableListBoxControl; @@ -99,7 +98,11 @@ namespace dbaui protected: virtual ~ORelationControl() override { disposeOnce(); } - virtual void dispose() override { m_pListCell.disposeAndClear(); ORelationControl_Base::dispose(); } + virtual void dispose() override + { + m_pListCell.disposeAndClear(); + svt::EditBrowseBox::dispose(); + } virtual void Resize() override; virtual Size GetOptimalSize() const override; virtual bool PreNotify(NotifyEvent& rNEvt ) override; @@ -107,7 +110,7 @@ namespace dbaui virtual bool IsTabAllowed(bool bForward) const override; void Init(const TTableConnectionData::value_type& _pConnData); - using ORelationControl_Base::Init; + using svt::EditBrowseBox::Init; virtual void InitController( ::svt::CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol ) override; virtual ::svt::CellController* GetController( sal_Int32 nRow, sal_uInt16 nCol ) override; virtual void PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColId ) const override; diff --git a/dbaccess/source/ui/control/SqlNameEdit.cxx b/dbaccess/source/ui/control/SqlNameEdit.cxx index bdd2df56540b..ca5ea6c8932a 100644 --- a/dbaccess/source/ui/control/SqlNameEdit.cxx +++ b/dbaccess/source/ui/control/SqlNameEdit.cxx @@ -63,7 +63,7 @@ namespace dbaui namespace { - void checkName(OSQLNameChecker& rChecker, weld::Entry& rEntry) + void checkName(OSQLNameChecker& rChecker, weld::TextWidget& rEntry) { OUString sCorrected; if (rChecker.checkString(rEntry.get_text(), sCorrected)) @@ -79,13 +79,13 @@ namespace dbaui } } - IMPL_LINK(OSQLNameEditControl, ModifyHdl, weld::Entry&, rEntry, void) + IMPL_LINK(OSQLNameEditControl, ModifyHdl, weld::TextWidget&, rEntry, void) { checkName(*this, rEntry); m_ChainChangedHdl.Call(rEntry); } - IMPL_LINK(OSQLNameEntry, ModifyHdl, weld::Entry&, rEntry, void) + IMPL_LINK(OSQLNameEntry, ModifyHdl, weld::TextWidget&, rEntry, void) { checkName(*this, rEntry); } diff --git a/dbaccess/source/ui/control/TableGrantCtrl.cxx b/dbaccess/source/ui/control/TableGrantCtrl.cxx index 083bb0b3e261..7db96550d6c2 100644 --- a/dbaccess/source/ui/control/TableGrantCtrl.cxx +++ b/dbaccess/source/ui/control/TableGrantCtrl.cxx @@ -25,10 +25,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/dbaccess/source/ui/control/dbtreelistbox.cxx b/dbaccess/source/ui/control/dbtreelistbox.cxx index 88ee9635edcb..061f67819d85 100644 --- a/dbaccess/source/ui/control/dbtreelistbox.cxx +++ b/dbaccess/source/ui/control/dbtreelistbox.cxx @@ -41,6 +41,7 @@ #include #include #include +#include #include diff --git a/dbaccess/source/ui/control/tabletree.cxx b/dbaccess/source/ui/control/tabletree.cxx index db2d087412d5..d6103f165cba 100644 --- a/dbaccess/source/ui/control/tabletree.cxx +++ b/dbaccess/source/ui/control/tabletree.cxx @@ -60,7 +60,7 @@ OTableTreeListBox::OTableTreeListBox(std::unique_ptr xTreeView, , m_bShowToggles(bShowToggles) { if (m_bShowToggles) - m_xTreeView->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xTreeView->enable_toggle_buttons(); } bool OTableTreeListBox::isFolderEntry(const weld::TreeIter& rEntry) const diff --git a/dbaccess/source/ui/dlg/CollectionView.cxx b/dbaccess/source/ui/dlg/CollectionView.cxx index d34cd27b3f07..5962b92e4669 100644 --- a/dbaccess/source/ui/dlg/CollectionView.cxx +++ b/dbaccess/source/ui/dlg/CollectionView.cxx @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/dbaccess/source/ui/dlg/ConnectionHelper.cxx b/dbaccess/source/ui/dlg/ConnectionHelper.cxx index 853a17776023..cb53a3893389 100644 --- a/dbaccess/source/ui/dlg/ConnectionHelper.cxx +++ b/dbaccess/source/ui/dlg/ConnectionHelper.cxx @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/dbaccess/source/ui/dlg/ConnectionHelper.hxx b/dbaccess/source/ui/dlg/ConnectionHelper.hxx index bbcf24783355..a1faab1ea3d5 100644 --- a/dbaccess/source/ui/dlg/ConnectionHelper.hxx +++ b/dbaccess/source/ui/dlg/ConnectionHelper.hxx @@ -22,6 +22,7 @@ #include "adminpages.hxx" #include #include +#include namespace dbaui { diff --git a/dbaccess/source/ui/dlg/ConnectionPage.cxx b/dbaccess/source/ui/dlg/ConnectionPage.cxx index d9e604922678..f3acf11a8359 100644 --- a/dbaccess/source/ui/dlg/ConnectionPage.cxx +++ b/dbaccess/source/ui/dlg/ConnectionPage.cxx @@ -259,7 +259,7 @@ namespace dbaui m_xTestConnection->set_sensitive(bEnableTestConnection); return true; } - IMPL_LINK(OConnectionTabPage, OnEditModified, weld::Entry&, rEdit, void) + IMPL_LINK(OConnectionTabPage, OnEditModified, weld::TextWidget&, rEdit, void) { if (&rEdit == m_xJavaDriver.get()) m_xTestJavaDriver->set_sensitive( !o3tl::trim(m_xJavaDriver->get_text()).empty() ); diff --git a/dbaccess/source/ui/dlg/ConnectionPage.hxx b/dbaccess/source/ui/dlg/ConnectionPage.hxx index 19e76946254a..344ef67bfa1c 100644 --- a/dbaccess/source/ui/dlg/ConnectionPage.hxx +++ b/dbaccess/source/ui/dlg/ConnectionPage.hxx @@ -48,7 +48,7 @@ namespace dbaui // called when the test connection button was clicked DECL_LINK(OnTestJavaClickHdl, weld::Button&, void); - DECL_LINK(OnEditModified, weld::Entry&, void); + DECL_LINK(OnEditModified, weld::TextWidget&, void); public: OConnectionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rCoreAttrs); diff --git a/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx b/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx index 77ea1c39bd29..9ecc523ba6e2 100644 --- a/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx +++ b/dbaccess/source/ui/dlg/ConnectionPageSetup.cxx @@ -133,7 +133,7 @@ namespace dbaui return !m_xConnectionURL->get_visible() || !m_xConnectionURL->GetTextNoPrefix().isEmpty(); } - IMPL_LINK_NOARG(OConnectionTabPageSetup, OnEditModified, weld::Entry&, void) + IMPL_LINK_NOARG(OConnectionTabPageSetup, OnEditModified, weld::TextWidget&, void) { SetRoadmapStateValue(checkTestConnection()); callModifiedHdl(); diff --git a/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx b/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx index 7b79d3116baf..0f92905869f4 100644 --- a/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx +++ b/dbaccess/source/ui/dlg/ConnectionPageSetup.hxx @@ -37,7 +37,7 @@ namespace dbaui std::unique_ptr m_xHeaderText; // called when the test connection button was clicked - DECL_LINK(OnEditModified, weld::Entry&, void); + DECL_LINK(OnEditModified, weld::TextWidget&, void); public: OConnectionTabPageSetup(weld::Container* pPage, weld::DialogController* pController, const OUString& _rUIXMLDescription, const OUString& _rId, const SfxItemSet& _rCoreAttrs, TranslateId pHelpTextResId, TranslateId pHeaderResId, TranslateId pUrlResId); diff --git a/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx b/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx index 213bee12efac..1acc9843c695 100644 --- a/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx +++ b/dbaccess/source/ui/dlg/DBSetupConnectionPages.cxx @@ -727,7 +727,7 @@ using namespace ::com::sun::star; aMsg.run(); } - IMPL_LINK(OJDBCConnectionPageSetup, OnEditModified, weld::Entry&, rEdit, void) + IMPL_LINK(OJDBCConnectionPageSetup, OnEditModified, weld::TextWidget&, rEdit, void) { if (&rEdit == m_xETDriverClass.get()) m_xPBTestJavaDriver->set_sensitive(!m_xETDriverClass->get_text().isEmpty()); diff --git a/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx b/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx index 4657af017629..23620fa95e5b 100644 --- a/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx +++ b/dbaccess/source/ui/dlg/DBSetupConnectionPages.hxx @@ -27,7 +27,11 @@ #include +#include +#include #include +#include +#include namespace dbaui { @@ -195,7 +199,7 @@ namespace dbaui virtual void fillWindows(std::vector< std::unique_ptr >& _rControlList) override; DECL_LINK(OnTestJavaClickHdl, weld::Button&, void); - DECL_LINK(OnEditModified, weld::Entry&, void); + DECL_LINK(OnEditModified, weld::TextWidget&, void); std::unique_ptr m_xFTDriverClass; std::unique_ptr m_xETDriverClass; std::unique_ptr m_xPBTestJavaDriver; diff --git a/dbaccess/source/ui/dlg/DbAdminImpl.cxx b/dbaccess/source/ui/dlg/DbAdminImpl.cxx index 71685dd855a2..fe7cbe0c665b 100644 --- a/dbaccess/source/ui/dlg/DbAdminImpl.cxx +++ b/dbaccess/source/ui/dlg/DbAdminImpl.cxx @@ -56,7 +56,7 @@ #include #include #include -#include +#include #include #include diff --git a/dbaccess/source/ui/dlg/DbAdminImpl.hxx b/dbaccess/source/ui/dlg/DbAdminImpl.hxx index 827c28885541..06a02e310520 100644 --- a/dbaccess/source/ui/dlg/DbAdminImpl.hxx +++ b/dbaccess/source/ui/dlg/DbAdminImpl.hxx @@ -32,7 +32,7 @@ #include #include #include -#include +#include namespace dbaui { diff --git a/dbaccess/source/ui/dlg/TextConnectionHelper.cxx b/dbaccess/source/ui/dlg/TextConnectionHelper.cxx index 0f85de5669f0..a122ef47890b 100644 --- a/dbaccess/source/ui/dlg/TextConnectionHelper.cxx +++ b/dbaccess/source/ui/dlg/TextConnectionHelper.cxx @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -124,7 +123,7 @@ namespace dbaui m_xContainer->show(); } - IMPL_LINK_NOARG(OTextConnectionHelper, OnEditModified, weld::Entry&, void) + IMPL_LINK_NOARG(OTextConnectionHelper, OnEditModified, weld::TextWidget&, void) { m_aGetExtensionHandler.Call(this); } diff --git a/dbaccess/source/ui/dlg/TextConnectionHelper.hxx b/dbaccess/source/ui/dlg/TextConnectionHelper.hxx index 6755a422378e..4cc8fd54ef75 100644 --- a/dbaccess/source/ui/dlg/TextConnectionHelper.hxx +++ b/dbaccess/source/ui/dlg/TextConnectionHelper.hxx @@ -22,6 +22,8 @@ #include "adminpages.hxx" #include #include +#include +#include namespace dbaui @@ -69,7 +71,7 @@ namespace dbaui std::unique_ptr m_xCharSet; DECL_LINK(OnSetExtensionHdl, weld::Toggleable&, void); - DECL_LINK(OnEditModified, weld::Entry&, void); + DECL_LINK(OnEditModified, weld::TextWidget&, void); OUString GetSeparator(const weld::ComboBox& rBox, std::u16string_view rList); void SetSeparator(weld::ComboBox& rBox, std::u16string_view rList, const OUString& rVal); diff --git a/dbaccess/source/ui/dlg/UserAdmin.cxx b/dbaccess/source/ui/dlg/UserAdmin.cxx index bb2afba84271..4eab70ecf4ce 100644 --- a/dbaccess/source/ui/dlg/UserAdmin.cxx +++ b/dbaccess/source/ui/dlg/UserAdmin.cxx @@ -36,9 +36,10 @@ #include #include #include +#include #include +#include #include -#include #include using namespace ::com::sun::star::container; @@ -64,7 +65,7 @@ class OPasswordDialog : public weld::GenericDialogController std::unique_ptr m_xOKBtn; DECL_LINK(OKHdl_Impl, weld::Button&, void); - DECL_LINK(ModifiedHdl, weld::Entry&, void); + DECL_LINK(ModifiedHdl, weld::TextWidget&, void); public: OPasswordDialog(weld::Window* pParent, std::u16string_view rUserName); @@ -109,7 +110,7 @@ IMPL_LINK_NOARG(OPasswordDialog, OKHdl_Impl, weld::Button&, void) } } -IMPL_LINK(OPasswordDialog, ModifiedHdl, weld::Entry&, rEdit, void) +IMPL_LINK(OPasswordDialog, ModifiedHdl, weld::TextWidget&, rEdit, void) { m_xOKBtn->set_sensitive(!rEdit.get_text().isEmpty()); } diff --git a/dbaccess/source/ui/dlg/UserAdminDlg.cxx b/dbaccess/source/ui/dlg/UserAdminDlg.cxx index a70db89f7c49..85fc281013b1 100644 --- a/dbaccess/source/ui/dlg/UserAdminDlg.cxx +++ b/dbaccess/source/ui/dlg/UserAdminDlg.cxx @@ -60,9 +60,6 @@ namespace dbaui m_xExampleSet.reset(new SfxItemSet(*GetInputSetImpl())); AddTabPage(u"settings"_ustr, OUserAdmin::Create, nullptr); - - // remove the reset button - it's meaning is much too ambiguous in this dialog - RemoveResetButton(); } OUserAdminDlg::~OUserAdminDlg() diff --git a/dbaccess/source/ui/dlg/admincontrols.cxx b/dbaccess/source/ui/dlg/admincontrols.cxx index cc98d6cf96ae..1efcbae0b2db 100644 --- a/dbaccess/source/ui/dlg/admincontrols.cxx +++ b/dbaccess/source/ui/dlg/admincontrols.cxx @@ -81,7 +81,7 @@ namespace dbaui m_xNamedPipe->set_sensitive(m_xNamedPipeRadio->get_active()); } - IMPL_LINK(MySQLNativeSettings, EditModifyHdl, weld::Entry&, rEdit, void) + IMPL_LINK(MySQLNativeSettings, EditModifyHdl, weld::TextWidget&, rEdit, void) { m_aControlModificationLink.Call(&rEdit); } diff --git a/dbaccess/source/ui/dlg/admincontrols.hxx b/dbaccess/source/ui/dlg/admincontrols.hxx index bde9a3f5882e..a881452dcbf6 100644 --- a/dbaccess/source/ui/dlg/admincontrols.hxx +++ b/dbaccess/source/ui/dlg/admincontrols.hxx @@ -23,8 +23,9 @@ #include #include +#include +#include #include -#include namespace dbaui { @@ -50,7 +51,7 @@ namespace dbaui Link m_aControlModificationLink; DECL_LINK(RadioToggleHdl, weld::Toggleable&, void); DECL_LINK(SpinModifyHdl, weld::SpinButton&, void); - DECL_LINK(EditModifyHdl, weld::Entry&, void); + DECL_LINK(EditModifyHdl, weld::TextWidget&, void); public: MySQLNativeSettings(weld::Widget* pParent, const Link& rControlModificationLink); diff --git a/dbaccess/source/ui/dlg/adminpages.cxx b/dbaccess/source/ui/dlg/adminpages.cxx index 6e72249275f0..f517cac8241a 100644 --- a/dbaccess/source/ui/dlg/adminpages.cxx +++ b/dbaccess/source/ui/dlg/adminpages.cxx @@ -34,7 +34,6 @@ #include #include #include -#include namespace dbaui { @@ -106,7 +105,7 @@ namespace dbaui callModifiedHdl(&rCtrl); } - IMPL_LINK(OGenericAdministrationPage, OnControlEntryModifyHdl, weld::Entry&, rCtrl, void) + IMPL_LINK(OGenericAdministrationPage, OnControlEntryModifyHdl, weld::TextWidget&, rCtrl, void) { callModifiedHdl(&rCtrl); } diff --git a/dbaccess/source/ui/dlg/adminpages.hxx b/dbaccess/source/ui/dlg/adminpages.hxx index 2ce7623928a0..9c8f0d6126ee 100644 --- a/dbaccess/source/ui/dlg/adminpages.hxx +++ b/dbaccess/source/ui/dlg/adminpages.hxx @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -229,7 +230,7 @@ namespace dbaui is modified. The implementation just calls callModifiedHdl. */ DECL_LINK(OnControlModified, weld::Widget*, void); - DECL_LINK(OnControlEntryModifyHdl, weld::Entry&, void); + DECL_LINK(OnControlEntryModifyHdl, weld::TextWidget&, void); DECL_LINK(OnControlSpinButtonModifyHdl, weld::SpinButton&, void); DECL_LINK(OnControlModifiedButtonClick, weld::Toggleable&, void); DECL_LINK(OnTestConnectionButtonClickHdl, weld::Button&, void); diff --git a/dbaccess/source/ui/dlg/advancedsettings.cxx b/dbaccess/source/ui/dlg/advancedsettings.cxx index c96a3213c98b..f2965c7f8c4e 100644 --- a/dbaccess/source/ui/dlg/advancedsettings.cxx +++ b/dbaccess/source/ui/dlg/advancedsettings.cxx @@ -383,9 +383,6 @@ namespace dbaui // any "special settings"? if (rFeatures.supportsAnySpecialSetting()) AddTabPage(u"special"_ustr, DBA_RES(STR_SPECIAL_SETTINGS), ODriversSettings::CreateSpecialSettingsPage, nullptr); - - // remove the reset button - it's meaning is much too ambiguous in this dialog - RemoveResetButton(); } AdvancedSettingsDialog::~AdvancedSettingsDialog() diff --git a/dbaccess/source/ui/dlg/advancedsettings.hxx b/dbaccess/source/ui/dlg/advancedsettings.hxx index 52236990faef..d477dde75234 100644 --- a/dbaccess/source/ui/dlg/advancedsettings.hxx +++ b/dbaccess/source/ui/dlg/advancedsettings.hxx @@ -22,8 +22,10 @@ #include "adminpages.hxx" #include +#include #include #include +#include #include #include diff --git a/dbaccess/source/ui/dlg/dbadmin.cxx b/dbaccess/source/ui/dlg/dbadmin.cxx index 37b0301f4d82..240abc6d0b19 100644 --- a/dbaccess/source/ui/dlg/dbadmin.cxx +++ b/dbaccess/source/ui/dlg/dbadmin.cxx @@ -49,9 +49,6 @@ ODbAdminDialog::ODbAdminDialog(weld::Window* pParent, // add the initial tab page AddTabPage(m_sMainPageID, OConnectionTabPage::Create, nullptr); - - // remove the reset button - it's meaning is much too ambiguous in this dialog - RemoveResetButton(); } ODbAdminDialog::~ODbAdminDialog() diff --git a/dbaccess/source/ui/dlg/dbfindex.cxx b/dbaccess/source/ui/dlg/dbfindex.cxx index 6a5df9ba47cc..c9ff28ec0b53 100644 --- a/dbaccess/source/ui/dlg/dbfindex.cxx +++ b/dbaccess/source/ui/dlg/dbfindex.cxx @@ -1,3 +1,4 @@ + /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. @@ -34,6 +35,9 @@ #include #include +#include +#include + namespace dbaui { using namespace ::com::sun::star::uno; diff --git a/dbaccess/source/ui/dlg/dbfindex.hxx b/dbaccess/source/ui/dlg/dbfindex.hxx index 1d64ff560d38..5b92161216db 100644 --- a/dbaccess/source/ui/dlg/dbfindex.hxx +++ b/dbaccess/source/ui/dlg/dbfindex.hxx @@ -20,10 +20,12 @@ #pragma once #include +#include #include #include #include -#include +#include + #include namespace dbaui diff --git a/dbaccess/source/ui/dlg/directsql.cxx b/dbaccess/source/ui/dlg/directsql.cxx index 922729bc2aec..9d482d831059 100644 --- a/dbaccess/source/ui/dlg/directsql.cxx +++ b/dbaccess/source/ui/dlg/directsql.cxx @@ -31,7 +31,7 @@ #include #include #include -#include + #include #include #include diff --git a/dbaccess/source/ui/dlg/dlgsave.cxx b/dbaccess/source/ui/dlg/dlgsave.cxx index 064d19eeb8da..8390956d5769 100644 --- a/dbaccess/source/ui/dlg/dlgsave.cxx +++ b/dbaccess/source/ui/dlg/dlgsave.cxx @@ -273,7 +273,7 @@ IMPL_LINK_NOARG(OSaveAsDlg, ButtonClickHdl, weld::Button&, void) m_xTitle->grab_focus(); } -IMPL_LINK_NOARG(OSaveAsDlg, EditModifyHdl, weld::Entry&, void) +IMPL_LINK_NOARG(OSaveAsDlg, EditModifyHdl, weld::TextWidget&, void) { m_xPB_OK->set_sensitive(!m_xTitle->get_text().isEmpty()); } diff --git a/dbaccess/source/ui/dlg/dsselect.hxx b/dbaccess/source/ui/dlg/dsselect.hxx index b412626753bb..bd2a0ec74d56 100644 --- a/dbaccess/source/ui/dlg/dsselect.hxx +++ b/dbaccess/source/ui/dlg/dsselect.hxx @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/dbaccess/source/ui/dlg/generalpage.cxx b/dbaccess/source/ui/dlg/generalpage.cxx index 88fab17b8ad4..40bcfc215203 100644 --- a/dbaccess/source/ui/dlg/generalpage.cxx +++ b/dbaccess/source/ui/dlg/generalpage.cxx @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/dbaccess/source/ui/dlg/generalpage.hxx b/dbaccess/source/ui/dlg/generalpage.hxx index 57ea5f5a4937..365ebc1ed7f4 100644 --- a/dbaccess/source/ui/dlg/generalpage.hxx +++ b/dbaccess/source/ui/dlg/generalpage.hxx @@ -22,6 +22,8 @@ #include "adminpages.hxx" #include +#include + namespace dbaui { class ODbTypeWizDialogSetup; diff --git a/dbaccess/source/ui/dlg/indexdialog.cxx b/dbaccess/source/ui/dlg/indexdialog.cxx index 3609ea297b5f..105ece05ec2a 100644 --- a/dbaccess/source/ui/dlg/indexdialog.cxx +++ b/dbaccess/source/ui/dlg/indexdialog.cxx @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -127,15 +126,10 @@ DbaIndexDialog::DbaIndexDialog(weld::Window* pParent, const Sequence& m_xClose->connect_clicked(LINK(this, DbaIndexDialog, OnCloseDialog)); // if all of the indexes have an empty description, we're not interested in displaying it - bool bFound = false; - for (auto const& check : *m_xIndexes) - { - if (!check.sDescription.isEmpty()) - { - bFound = true; - break; - } - } + bool bFound + = std::ranges::any_of(m_xIndexes->begin(), m_xIndexes->end(), + [](const auto& check) { return !check.sDescription.isEmpty(); }); + if (!bFound) { // hide the controls which are necessary for the description @@ -523,12 +517,12 @@ IMPL_LINK_NOARG(DbaIndexDialog, OnEntryEditing, const weld::TreeIter&, bool) return true; } -IMPL_LINK(DbaIndexDialog, OnEntryEdited, const IterString&, rIterString, bool) +IMPL_LINK(DbaIndexDialog, OnEntryEdited, const weld::TreeView::IterColText&, rIterColText, bool) { m_bEditingActive = false; - const weld::TreeIter& rEntry = rIterString.first; - OUString sNewName = rIterString.second; + const weld::TreeIter& rEntry = rIterColText.m_rIter; + OUString sNewName = rIterColText.m_sText; Indexes::iterator aPosition = m_xIndexes->begin() + m_xIndexList->get_id(rEntry).toUInt32(); diff --git a/dbaccess/source/ui/dlg/paramdialog.cxx b/dbaccess/source/ui/dlg/paramdialog.cxx index a32ea7b5055a..410bb391dda5 100644 --- a/dbaccess/source/ui/dlg/paramdialog.cxx +++ b/dbaccess/source/ui/dlg/paramdialog.cxx @@ -27,310 +27,308 @@ #include #include #include -#include #include #include #include namespace dbaui { +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::util; - using namespace ::com::sun::star::uno; - using namespace ::com::sun::star::beans; - using namespace ::com::sun::star::container; - using namespace ::com::sun::star::sdbc; - using namespace ::com::sun::star::util; +// OParameterDialog - // OParameterDialog +OParameterDialog::OParameterDialog(weld::Window* pParent, + const Reference& rParamContainer, + const Reference& _rxConnection, + const Reference& rxContext) + : GenericDialogController(pParent, u"dbaccess/ui/parametersdialog.ui"_ustr, u"Parameters"_ustr) + , m_nCurrentlySelected(-1) + , m_xConnection(_rxConnection) + , m_aPredicateInput(rxContext, _rxConnection, getParseContext()) + , m_aResetVisitFlag("dbaccess OParameterDialog m_aResetVisitFlag") + , m_xAllParams(m_xBuilder->weld_tree_view(u"allParamTreeview"_ustr)) + , m_xParam(m_xBuilder->weld_entry(u"paramEntry"_ustr)) + , m_xTravelNext(m_xBuilder->weld_button(u"next"_ustr)) + , m_xOKBtn(m_xBuilder->weld_button(u"ok"_ustr)) + , m_xCancelBtn(m_xBuilder->weld_button(u"cancel"_ustr)) +{ + m_xAllParams->set_size_request(-1, m_xAllParams->get_height_rows(10)); - - OParameterDialog::OParameterDialog( - weld::Window* pParent, const Reference< XIndexAccess > & rParamContainer, - const Reference< XConnection > & _rxConnection, const Reference< XComponentContext >& rxContext) - : GenericDialogController(pParent, u"dbaccess/ui/parametersdialog.ui"_ustr, u"Parameters"_ustr) - , m_nCurrentlySelected(-1) - , m_xConnection(_rxConnection) - , m_aPredicateInput( rxContext, _rxConnection, getParseContext() ) - , m_aResetVisitFlag("dbaccess OParameterDialog m_aResetVisitFlag") - , m_xAllParams(m_xBuilder->weld_tree_view(u"allParamTreeview"_ustr)) - , m_xParam(m_xBuilder->weld_entry(u"paramEntry"_ustr)) - , m_xTravelNext(m_xBuilder->weld_button(u"next"_ustr)) - , m_xOKBtn(m_xBuilder->weld_button(u"ok"_ustr)) - , m_xCancelBtn(m_xBuilder->weld_button(u"cancel"_ustr)) + if (rxContext.is()) + m_xFormatter.set(NumberFormatter::create(rxContext), UNO_QUERY_THROW); + else { - m_xAllParams->set_size_request(-1, m_xAllParams->get_height_rows(10)); + OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!"); + } - if (rxContext.is()) - m_xFormatter.set( NumberFormatter::create( rxContext ), UNO_QUERY_THROW); - else { - OSL_FAIL("OParameterDialog::OParameterDialog: need a service factory!"); + Reference xNumberFormats + = ::dbtools::getNumberFormats(m_xConnection, true); + if (!xNumberFormats.is()) + ::comphelper::disposeComponent(m_xFormatter); + else + m_xFormatter->attachNumberFormatsSupplier(xNumberFormats); + try + { + OSL_ENSURE(rParamContainer->getCount(), + "OParameterDialog::OParameterDialog : can't handle empty containers !"); + + m_aFinalValues.realloc(rParamContainer->getCount()); + PropertyValue* pValues = m_aFinalValues.getArray(); + + for (sal_Int32 i = 0, nCount = rParamContainer->getCount(); i < nCount; ++i, ++pValues) + { + Reference xParamAsSet; + rParamContainer->getByIndex(i) >>= xParamAsSet; + OSL_ENSURE(xParamAsSet.is(), "Parameter is null!"); + if (!xParamAsSet.is()) + continue; + pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); + m_xAllParams->append_text(pValues->Name); + + m_aVisitedParams.push_back(VisitFlags::NONE); + // not visited, not dirty } - Reference< XNumberFormatsSupplier > xNumberFormats = ::dbtools::getNumberFormats(m_xConnection, true); - if (!xNumberFormats.is()) - ::comphelper::disposeComponent(m_xFormatter); - else - m_xFormatter->attachNumberFormatsSupplier(xNumberFormats); - try + m_xParams = rParamContainer; + } + catch (Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + Construct(); + + m_aResetVisitFlag.SetInvokeHandler(LINK(this, OParameterDialog, OnVisitedTimeout)); +} + +OParameterDialog::~OParameterDialog() +{ + if (m_aResetVisitFlag.IsActive()) + m_aResetVisitFlag.Stop(); +} + +void OParameterDialog::Construct() +{ + m_xAllParams->connect_selection_changed(LINK(this, OParameterDialog, OnEntryListBoxSelected)); + m_xParam->connect_focus_out(LINK(this, OParameterDialog, OnValueLoseFocusHdl)); + m_xParam->connect_changed(LINK(this, OParameterDialog, OnValueModified)); + m_xTravelNext->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); + m_xOKBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); + m_xCancelBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); + + if (m_xAllParams->n_children()) + { + m_xAllParams->select(0); + OnEntrySelected(); + + if (m_xAllParams->n_children() == 1) + m_xTravelNext->set_sensitive(false); + + if (m_xAllParams->n_children() > 1) + m_xDialog->change_default_button(m_xOKBtn.get(), m_xTravelNext.get()); + } + + m_xParam->grab_focus(); +} + +IMPL_LINK_NOARG(OParameterDialog, OnValueLoseFocusHdl, weld::Widget&, void) +{ + CheckValueForError(); +} + +bool OParameterDialog::CheckValueForError() +{ + if (m_nCurrentlySelected != -1) + { + if (!(m_aVisitedParams[m_nCurrentlySelected] & VisitFlags::Dirty)) + // nothing to do, the value isn't dirty + return false; + } + + bool bRet = false; + + Reference xParamAsSet; + m_xParams->getByIndex(m_nCurrentlySelected) >>= xParamAsSet; + if (xParamAsSet.is()) + { + if (m_xConnection.is() && m_xFormatter.is()) { - OSL_ENSURE(rParamContainer->getCount(), "OParameterDialog::OParameterDialog : can't handle empty containers !"); - - m_aFinalValues.realloc(rParamContainer->getCount()); - PropertyValue* pValues = m_aFinalValues.getArray(); - - for (sal_Int32 i = 0, nCount = rParamContainer->getCount(); iget_text()); + bool bValid = m_aPredicateInput.normalizePredicateString(sParamValue, xParamAsSet); + m_xParam->set_text(sParamValue); + m_xParam->set_message_type(bValid ? weld::EntryMessageType::Normal + : weld::EntryMessageType::Error); + OUString sToolTip; + if (bValid) { - Reference< XPropertySet > xParamAsSet; - rParamContainer->getByIndex(i) >>= xParamAsSet; - OSL_ENSURE(xParamAsSet.is(),"Parameter is null!"); - if(!xParamAsSet.is()) - continue; - pValues->Name = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); - m_xAllParams->append_text(pValues->Name); - - m_aVisitedParams.push_back(VisitFlags::NONE); - // not visited, not dirty + // with this the value isn't dirty anymore + if (m_nCurrentlySelected != -1) + m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty; } - - m_xParams = rParamContainer; - } - catch(Exception&) - { - DBG_UNHANDLED_EXCEPTION("dbaccess"); - } - - Construct(); - - m_aResetVisitFlag.SetInvokeHandler(LINK(this, OParameterDialog, OnVisitedTimeout)); - } - - OParameterDialog::~OParameterDialog() - { - if (m_aResetVisitFlag.IsActive()) - m_aResetVisitFlag.Stop(); - } - - void OParameterDialog::Construct() - { - m_xAllParams->connect_selection_changed( - LINK(this, OParameterDialog, OnEntryListBoxSelected)); - m_xParam->connect_focus_out(LINK(this, OParameterDialog, OnValueLoseFocusHdl)); - m_xParam->connect_changed(LINK(this, OParameterDialog, OnValueModified)); - m_xTravelNext->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); - m_xOKBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); - m_xCancelBtn->connect_clicked(LINK(this, OParameterDialog, OnButtonClicked)); - - if (m_xAllParams->n_children()) - { - m_xAllParams->select(0); - OnEntrySelected(); - - if (m_xAllParams->n_children() == 1) - m_xTravelNext->set_sensitive(false); - - if (m_xAllParams->n_children() > 1) - m_xDialog->change_default_button(m_xOKBtn.get(), m_xTravelNext.get()); - } - - m_xParam->grab_focus(); - } - - IMPL_LINK_NOARG(OParameterDialog, OnValueLoseFocusHdl, weld::Widget&, void) - { - CheckValueForError(); - } - - bool OParameterDialog::CheckValueForError() - { - if (m_nCurrentlySelected != -1) - { - if ( !( m_aVisitedParams[ m_nCurrentlySelected ] & VisitFlags::Dirty ) ) - // nothing to do, the value isn't dirty - return false; - } - - bool bRet = false; - - Reference< XPropertySet > xParamAsSet; - m_xParams->getByIndex(m_nCurrentlySelected) >>= xParamAsSet; - if (xParamAsSet.is()) - { - if (m_xConnection.is() && m_xFormatter.is()) + else { - OUString sParamValue(m_xParam->get_text()); - bool bValid = m_aPredicateInput.normalizePredicateString( sParamValue, xParamAsSet ); - m_xParam->set_text(sParamValue); - m_xParam->set_message_type(bValid ? weld::EntryMessageType::Normal : weld::EntryMessageType::Error); - OUString sToolTip; - if ( bValid ) - { - // with this the value isn't dirty anymore - if (m_nCurrentlySelected != -1) - m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty; - } - else - { - OUString sName; - try - { - sName = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); - } - catch(Exception&) - { - DBG_UNHANDLED_EXCEPTION("dbaccess"); - } - - OUString sMessage(DBA_RES(STR_COULD_NOT_CONVERT_PARAM)); - sToolTip = sMessage.replaceAll( "$name$", sName ); - m_xParam->grab_focus(); - bRet = true; - } - m_xParam->set_tooltip_text(sToolTip); - m_xOKBtn->set_sensitive(bValid); - } - } - - return bRet; - } - - IMPL_LINK(OParameterDialog, OnButtonClicked, weld::Button&, rButton, void) - { - if (m_xCancelBtn.get() == &rButton) - { - // no interpreting of the given values anymore... - m_xParam->connect_focus_out(Link()); // no direct call from the control anymore ... - m_xDialog->response(RET_CANCEL); - } - else if (m_xOKBtn.get() == &rButton) - { - // transfer the current values into the Any - if (OnEntrySelected()) - { // there was an error interpreting the current text - return; - } - - if (m_xParams.is()) - { - // write the parameters + OUString sName; try { - PropertyValue* pValues = m_aFinalValues.getArray(); - for (sal_Int32 i = 0, nCount = m_xParams->getCount(); i xParamAsSet; - m_xParams->getByIndex(i) >>= xParamAsSet; - - OUString sValue; - pValues->Value >>= sValue; - pValues->Value = m_aPredicateInput.getPredicateValue( sValue, xParamAsSet ); - } + sName = ::comphelper::getString(xParamAsSet->getPropertyValue(PROPERTY_NAME)); } - catch(Exception&) + catch (Exception&) { DBG_UNHANDLED_EXCEPTION("dbaccess"); } + OUString sMessage(DBA_RES(STR_COULD_NOT_CONVERT_PARAM)); + sToolTip = sMessage.replaceAll("$name$", sName); + m_xParam->grab_focus(); + bRet = true; } - m_xDialog->response(RET_OK); + m_xParam->set_tooltip_text(sToolTip); + m_xOKBtn->set_sensitive(bValid); } - else if (m_xTravelNext.get() == &rButton) + } + + return bRet; +} + +IMPL_LINK(OParameterDialog, OnButtonClicked, weld::Button&, rButton, void) +{ + if (m_xCancelBtn.get() == &rButton) + { + // no interpreting of the given values anymore... + m_xParam->connect_focus_out( + Link()); // no direct call from the control anymore ... + m_xDialog->response(RET_CANCEL); + } + else if (m_xOKBtn.get() == &rButton) + { + // transfer the current values into the Any + if (OnEntrySelected()) + { // there was an error interpreting the current text + return; + } + + if (m_xParams.is()) { - if (sal_Int32 nCount = m_xAllParams->n_children()) + // write the parameters + try { - sal_Int32 nCurrent = m_xAllParams->get_selected_index(); - OSL_ENSURE(static_cast(nCount) == m_aVisitedParams.size(), "OParameterDialog::OnButtonClicked : inconsistent lists !"); + PropertyValue* pValues = m_aFinalValues.getArray(); + for (sal_Int32 i = 0, nCount = m_xParams->getCount(); i < nCount; ++i, ++pValues) + { + Reference xParamAsSet; + m_xParams->getByIndex(i) >>= xParamAsSet; - // search the next entry in list we haven't visited yet - sal_Int32 nNext = (nCurrent + 1) % nCount; - while ((nNext != nCurrent) && ( m_aVisitedParams[nNext] & VisitFlags::Visited )) - nNext = (nNext + 1) % nCount; - - if ( m_aVisitedParams[nNext] & VisitFlags::Visited ) - // there is no such "not visited yet" entry -> simply take the next one - nNext = (nCurrent + 1) % nCount; - - m_xAllParams->select(nNext); - OnEntrySelected(); + OUString sValue; + pValues->Value >>= sValue; + pValues->Value = m_aPredicateInput.getPredicateValue(sValue, xParamAsSet); + } } - } - } - - IMPL_LINK_NOARG(OParameterDialog, OnEntryListBoxSelected, weld::ItemView&, void) - { - OnEntrySelected(); - } - - bool OParameterDialog::OnEntrySelected() - { - if (m_aResetVisitFlag.IsActive()) - { - LINK(this, OParameterDialog, OnVisitedTimeout).Call(&m_aResetVisitFlag); - m_aResetVisitFlag.Stop(); - } - // save the old values - if (m_nCurrentlySelected != -1) - { - // do the transformation of the current text - if (CheckValueForError()) - { // there was an error interpreting the text - m_xAllParams->select(m_nCurrentlySelected); - return true; - } - - m_aFinalValues.getArray()[m_nCurrentlySelected].Value <<= m_xParam->get_text(); - } - - // initialize the controls with the new values - sal_Int32 nSelected = m_xAllParams->get_selected_index(); - OSL_ENSURE(nSelected != -1, "OParameterDialog::OnEntrySelected : no current entry !"); - - m_xParam->set_text(::comphelper::getString(m_aFinalValues[nSelected].Value)); - m_nCurrentlySelected = nSelected; - - // with this the value isn't dirty - OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnEntrySelected : invalid current entry !"); - m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty; - - m_aResetVisitFlag.SetTimeout(1000); - m_aResetVisitFlag.Start(); - - return false; - } - - IMPL_LINK_NOARG(OParameterDialog, OnVisitedTimeout, Timer*, void) - { - OSL_ENSURE(m_nCurrentlySelected != -1, "OParameterDialog::OnVisitedTimeout : invalid call !"); - - // mark the currently selected entry as visited - OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnVisitedTimeout : invalid entry !"); - m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Visited; - - // was it the last "not visited yet" entry ? - bool bVisited = false; - for (auto const& visitedParam : m_aVisitedParams) - { - if (!(visitedParam & VisitFlags::Visited)) + catch (Exception&) { - bVisited = true; - break; + DBG_UNHANDLED_EXCEPTION("dbaccess"); } } - - if (!bVisited) + m_xDialog->response(RET_OK); + } + else if (m_xTravelNext.get() == &rButton) + { + if (sal_Int32 nCount = m_xAllParams->n_children()) { - // yes, there isn't another one -> change the "default button" - m_xDialog->change_default_button(m_xTravelNext.get(), m_xOKBtn.get()); + sal_Int32 nCurrent = m_xAllParams->get_selected_index(); + OSL_ENSURE(static_cast(nCount) == m_aVisitedParams.size(), + "OParameterDialog::OnButtonClicked : inconsistent lists !"); + + // search the next entry in list we haven't visited yet + sal_Int32 nNext = (nCurrent + 1) % nCount; + while ((nNext != nCurrent) && (m_aVisitedParams[nNext] & VisitFlags::Visited)) + nNext = (nNext + 1) % nCount; + + if (m_aVisitedParams[nNext] & VisitFlags::Visited) + // there is no such "not visited yet" entry -> simply take the next one + nNext = (nCurrent + 1) % nCount; + + m_xAllParams->select(nNext); + OnEntrySelected(); } } +} - IMPL_LINK(OParameterDialog, OnValueModified, weld::Entry&, rEdit, void) +IMPL_LINK_NOARG(OParameterDialog, OnEntryListBoxSelected, weld::ItemView&, void) +{ + OnEntrySelected(); +} + +bool OParameterDialog::OnEntrySelected() +{ + if (m_aResetVisitFlag.IsActive()) { - // mark the currently selected entry as dirty - OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), "OParameterDialog::OnValueModified : invalid entry !"); - m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Dirty; - rEdit.set_message_type(weld::EntryMessageType::Normal); + LINK(this, OParameterDialog, OnVisitedTimeout).Call(&m_aResetVisitFlag); + m_aResetVisitFlag.Stop(); + } + // save the old values + if (m_nCurrentlySelected != -1) + { + // do the transformation of the current text + if (CheckValueForError()) + { // there was an error interpreting the text + m_xAllParams->select(m_nCurrentlySelected); + return true; + } + + m_aFinalValues.getArray()[m_nCurrentlySelected].Value <<= m_xParam->get_text(); } -} // namespace dbaui + // initialize the controls with the new values + sal_Int32 nSelected = m_xAllParams->get_selected_index(); + OSL_ENSURE(nSelected != -1, "OParameterDialog::OnEntrySelected : no current entry !"); + + m_xParam->set_text(::comphelper::getString(m_aFinalValues[nSelected].Value)); + m_nCurrentlySelected = nSelected; + + // with this the value isn't dirty + OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), + "OParameterDialog::OnEntrySelected : invalid current entry !"); + m_aVisitedParams[m_nCurrentlySelected] &= ~VisitFlags::Dirty; + + m_aResetVisitFlag.SetTimeout(1000); + m_aResetVisitFlag.Start(); + + return false; +} + +IMPL_LINK_NOARG(OParameterDialog, OnVisitedTimeout, Timer*, void) +{ + OSL_ENSURE(m_nCurrentlySelected != -1, "OParameterDialog::OnVisitedTimeout : invalid call !"); + + // mark the currently selected entry as visited + OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), + "OParameterDialog::OnVisitedTimeout : invalid entry !"); + m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Visited; + + // was it the last "not visited yet" entry ? + bool bVisited = std::ranges::any_of(m_aVisitedParams, + [](const auto& p) { return !(p & VisitFlags::Visited); }); + + if (!bVisited) + { + // yes, there isn't another one -> change the "default button" + m_xDialog->change_default_button(m_xTravelNext.get(), m_xOKBtn.get()); + } +} + +IMPL_LINK_NOARG(OParameterDialog, OnValueModified, weld::TextWidget&, void) +{ + // mark the currently selected entry as dirty + OSL_ENSURE(o3tl::make_unsigned(m_nCurrentlySelected) < m_aVisitedParams.size(), + "OParameterDialog::OnValueModified : invalid entry !"); + m_aVisitedParams[m_nCurrentlySelected] |= VisitFlags::Dirty; + m_xParam->set_message_type(weld::EntryMessageType::Normal); +} + +} // namespace dbaui /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/dlg/sqlmessage.cxx b/dbaccess/source/ui/dlg/sqlmessage.cxx index 74225fcd9a5e..4de72b97aceb 100644 --- a/dbaccess/source/ui/dlg/sqlmessage.cxx +++ b/dbaccess/source/ui/dlg/sqlmessage.cxx @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -526,7 +525,8 @@ void OSQLMessageBox::Construct(weld::Window* pParent, MessBoxStyle _nStyle, Mess break; } - m_xDialog.reset(Application::CreateMessageDialog(pParent, eMessageType, VclButtonsType::NONE, u""_ustr)); + m_xDialog + = Application::CreateMessageDialog(pParent, eMessageType, VclButtonsType::NONE, u""_ustr); m_xDialog->set_title(utl::ConfigManager::getProductName() + " Base"); impl_fillMessages(); diff --git a/dbaccess/source/ui/dlg/tablespage.cxx b/dbaccess/source/ui/dlg/tablespage.cxx index c9d7210199cc..c480281c81b2 100644 --- a/dbaccess/source/ui/dlg/tablespage.cxx +++ b/dbaccess/source/ui/dlg/tablespage.cxx @@ -35,6 +35,7 @@ #include #include #include +#include namespace dbaui { diff --git a/dbaccess/source/ui/inc/ChildWindow.hxx b/dbaccess/source/ui/inc/ChildWindow.hxx index 9f9cda99fd62..87bd983a80b7 100644 --- a/dbaccess/source/ui/inc/ChildWindow.hxx +++ b/dbaccess/source/ui/inc/ChildWindow.hxx @@ -10,7 +10,7 @@ #pragma once #include -#include +#include namespace dbaui { diff --git a/dbaccess/source/ui/inc/CollectionView.hxx b/dbaccess/source/ui/inc/CollectionView.hxx index 76636e90789f..5cb2fc426ded 100644 --- a/dbaccess/source/ui/inc/CollectionView.hxx +++ b/dbaccess/source/ui/inc/CollectionView.hxx @@ -20,10 +20,13 @@ #pragma once #include +#include #include #include +#include #include -#include +#include + #include #include diff --git a/dbaccess/source/ui/inc/ConnectionLineAccess.hxx b/dbaccess/source/ui/inc/ConnectionLineAccess.hxx index bc9dbbb6fef0..86dcaf388348 100644 --- a/dbaccess/source/ui/inc/ConnectionLineAccess.hxx +++ b/dbaccess/source/ui/inc/ConnectionLineAccess.hxx @@ -43,9 +43,6 @@ namespace dbaui public: OConnectionLineAccess(OTableConnection* _pLine); - // XServiceInfo - virtual OUString SAL_CALL getImplementationName() override; - // XAccessibleContext virtual sal_Int64 SAL_CALL getAccessibleChildCount( ) override; virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int64 i ) override; diff --git a/dbaccess/source/ui/inc/ConnectionLineData.hxx b/dbaccess/source/ui/inc/ConnectionLineData.hxx index 2a41c93d9aab..e54c51443e4a 100644 --- a/dbaccess/source/ui/inc/ConnectionLineData.hxx +++ b/dbaccess/source/ui/inc/ConnectionLineData.hxx @@ -43,7 +43,6 @@ namespace dbaui OUString m_aDestFieldName; friend bool operator==(const OConnectionLineData& lhs, const OConnectionLineData& rhs); - friend bool operator!=(const OConnectionLineData& lhs, const OConnectionLineData& rhs) { return !(lhs == rhs); } protected: virtual ~OConnectionLineData() override; public: diff --git a/dbaccess/source/ui/inc/FieldDescControl.hxx b/dbaccess/source/ui/inc/FieldDescControl.hxx index ab3e1e765b91..2bd3bf7389c8 100644 --- a/dbaccess/source/ui/inc/FieldDescControl.hxx +++ b/dbaccess/source/ui/inc/FieldDescControl.hxx @@ -19,8 +19,10 @@ #pragma once #include +#include #include -#include +#include +#include #include "IClipBoardTest.hxx" #include "QEnumTypes.hxx" #include diff --git a/dbaccess/source/ui/inc/JAccess.hxx b/dbaccess/source/ui/inc/JAccess.hxx index 33c539dfb14c..e6c7bd4fc1a0 100644 --- a/dbaccess/source/ui/inc/JAccess.hxx +++ b/dbaccess/source/ui/inc/JAccess.hxx @@ -36,8 +36,6 @@ namespace dbaui */ OJoinDesignViewAccess( OJoinTableView* _pTableView); - virtual OUString SAL_CALL getImplementationName() override; - // XAccessibleContext virtual sal_Int64 SAL_CALL getAccessibleChildCount( ) override; virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int64 i ) override; diff --git a/dbaccess/source/ui/inc/JoinTableView.hxx b/dbaccess/source/ui/inc/JoinTableView.hxx index 9da25a4c1d30..8a974938ea1b 100644 --- a/dbaccess/source/ui/inc/JoinTableView.hxx +++ b/dbaccess/source/ui/inc/JoinTableView.hxx @@ -24,6 +24,7 @@ #include #include #include +#include #include "callbacks.hxx" #include "TableConnectionData.hxx" diff --git a/dbaccess/source/ui/inc/QueryPropertiesDialog.hxx b/dbaccess/source/ui/inc/QueryPropertiesDialog.hxx index 214eb7a2c632..98ad0d1a9ea7 100644 --- a/dbaccess/source/ui/inc/QueryPropertiesDialog.hxx +++ b/dbaccess/source/ui/inc/QueryPropertiesDialog.hxx @@ -11,7 +11,8 @@ #include #include -#include +#include +#include namespace dbaui { diff --git a/dbaccess/source/ui/inc/RelationControl.hxx b/dbaccess/source/ui/inc/RelationControl.hxx index e596480acb1e..6d21685ed0e4 100644 --- a/dbaccess/source/ui/inc/RelationControl.hxx +++ b/dbaccess/source/ui/inc/RelationControl.hxx @@ -19,7 +19,8 @@ #pragma once #include -#include +#include + #include "JoinTableView.hxx" namespace dbaui diff --git a/dbaccess/source/ui/inc/RelationDlg.hxx b/dbaccess/source/ui/inc/RelationDlg.hxx index dadac4096b51..18c0f2bc3fca 100644 --- a/dbaccess/source/ui/inc/RelationDlg.hxx +++ b/dbaccess/source/ui/inc/RelationDlg.hxx @@ -19,8 +19,10 @@ #pragma once #include +#include #include -#include +#include + #include "JoinTableView.hxx" #include "RelControliFace.hxx" #include "RelationControl.hxx" diff --git a/dbaccess/source/ui/inc/SqlNameEdit.hxx b/dbaccess/source/ui/inc/SqlNameEdit.hxx index a27bad896fda..7bb4d5fcf423 100644 --- a/dbaccess/source/ui/inc/SqlNameEdit.hxx +++ b/dbaccess/source/ui/inc/SqlNameEdit.hxx @@ -22,7 +22,6 @@ #include #include #include -#include namespace dbaui { @@ -59,15 +58,15 @@ namespace dbaui m_xWidget->connect_changed(LINK(this, OSQLNameEditControl, ModifyHdl)); } - virtual void connect_changed(const Link& rLink) override + virtual void connect_changed(const Link& rLink) override { m_ChainChangedHdl = rLink; } private: - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); - Link m_ChainChangedHdl; + Link m_ChainChangedHdl; }; class OWidgetBase @@ -101,7 +100,7 @@ namespace dbaui private: std::unique_ptr m_xEntry; - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); public: OSQLNameEntry(std::unique_ptr xEntry, const OUString& _rAllowedChars, diff --git a/dbaccess/source/ui/inc/TableCopyHelper.hxx b/dbaccess/source/ui/inc/TableCopyHelper.hxx index f8a4fcd7e077..782b624253f8 100644 --- a/dbaccess/source/ui/inc/TableCopyHelper.hxx +++ b/dbaccess/source/ui/inc/TableCopyHelper.hxx @@ -24,7 +24,7 @@ #include #include #include -#include + #include #include diff --git a/dbaccess/source/ui/inc/TableDesignHelpBar.hxx b/dbaccess/source/ui/inc/TableDesignHelpBar.hxx index b430a2b4a03e..ebe0d94afa43 100644 --- a/dbaccess/source/ui/inc/TableDesignHelpBar.hxx +++ b/dbaccess/source/ui/inc/TableDesignHelpBar.hxx @@ -19,7 +19,7 @@ #pragma once #include -#include + #include "IClipBoardTest.hxx" namespace dbaui diff --git a/dbaccess/source/ui/inc/TableDesignView.hxx b/dbaccess/source/ui/inc/TableDesignView.hxx index d00f20221b0a..904da97dda4e 100644 --- a/dbaccess/source/ui/inc/TableDesignView.hxx +++ b/dbaccess/source/ui/inc/TableDesignView.hxx @@ -21,8 +21,9 @@ #include #include #include +#include #include -#include + #include "IClipBoardTest.hxx" namespace dbaui diff --git a/dbaccess/source/ui/inc/TableFieldDescription.hxx b/dbaccess/source/ui/inc/TableFieldDescription.hxx index 8c3c9b1cd82a..6b0fb69f40c9 100644 --- a/dbaccess/source/ui/inc/TableFieldDescription.hxx +++ b/dbaccess/source/ui/inc/TableFieldDescription.hxx @@ -19,6 +19,7 @@ #pragma once #include +#include #include "QEnumTypes.hxx" #include @@ -116,12 +117,10 @@ namespace dbaui bool HasCriteria() const { - for (auto const& criteria : m_aCriteria) + return std::ranges::any_of(m_aCriteria, [](auto const& criteria) { - if(!criteria.isEmpty()) - return true; - } - return false; + return !criteria.isEmpty(); + }); } const std::vector< OUString>& GetCriteria() const { return m_aCriteria; } diff --git a/dbaccess/source/ui/inc/TableWindowAccess.hxx b/dbaccess/source/ui/inc/TableWindowAccess.hxx index 327f929c6d79..f25fc8a5b26c 100644 --- a/dbaccess/source/ui/inc/TableWindowAccess.hxx +++ b/dbaccess/source/ui/inc/TableWindowAccess.hxx @@ -47,10 +47,6 @@ namespace dbaui public: OTableWindowAccess( OTableWindow* _pTable); - // XServiceInfo - virtual OUString SAL_CALL getImplementationName() override; - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; - // XAccessibleContext virtual sal_Int64 SAL_CALL getAccessibleChildCount( ) override; virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int64 i ) override; diff --git a/dbaccess/source/ui/inc/TableWindowData.hxx b/dbaccess/source/ui/inc/TableWindowData.hxx index 0160ea723316..22a3fdb589e6 100644 --- a/dbaccess/source/ui/inc/TableWindowData.hxx +++ b/dbaccess/source/ui/inc/TableWindowData.hxx @@ -60,7 +60,7 @@ namespace dbaui * * \param _xConnection * \param _bAllowQueries when true, queries are allowed - * \return false if the table was unaccessible otherwise true + * \return false if the table was inaccessible otherwise true */ bool init(const css::uno::Reference< css::sdbc::XConnection >& _xConnection ,bool _bAllowQueries); diff --git a/dbaccess/source/ui/inc/TableWindowTitle.hxx b/dbaccess/source/ui/inc/TableWindowTitle.hxx index d06d621f1763..51a04efc6d70 100644 --- a/dbaccess/source/ui/inc/TableWindowTitle.hxx +++ b/dbaccess/source/ui/inc/TableWindowTitle.hxx @@ -19,7 +19,8 @@ #pragma once #include -#include +#include +#include namespace dbaui { diff --git a/dbaccess/source/ui/inc/TokenWriter.hxx b/dbaccess/source/ui/inc/TokenWriter.hxx index d857e2553503..fcf669e07b75 100644 --- a/dbaccess/source/ui/inc/TokenWriter.hxx +++ b/dbaccess/source/ui/inc/TokenWriter.hxx @@ -33,7 +33,7 @@ #include #include -#include +#include namespace com::sun::star { namespace sdbc{ diff --git a/dbaccess/source/ui/inc/UITools.hxx b/dbaccess/source/ui/inc/UITools.hxx index f45213a28b49..e1ff711ab317 100644 --- a/dbaccess/source/ui/inc/UITools.hxx +++ b/dbaccess/source/ui/inc/UITools.hxx @@ -79,7 +79,7 @@ namespace dbaui @param _rxContext the UNO component context @param _rEvtLst the eventlistener which will be added to the new created connection @param _rOUTConnection this parameter will be filled with the new created connection - @return SQLExceptionInfo contains a SQLException, SQLContext or a SQLWarning when they araised else .isValid() will return false + @return SQLExceptionInfo contains a SQLException, SQLContext or a SQLWarning when they arise else .isValid() will return false */ ::dbtools::SQLExceptionInfo createConnection( const OUString& _rsDataSourceName, @@ -92,7 +92,7 @@ namespace dbaui @param _rxContext the UNO component context @param _rEvtLst the eventlistener which will be added to the new created connection @param _rOUTConnection this parameter will be filled with the new created connection - @return SQLExceptionInfo contains a SQLException, SQLContext or a SQLWarning when they araised else .isValid() will return false + @return SQLExceptionInfo contains a SQLException, SQLContext or a SQLWarning when they arise else .isValid() will return false */ ::dbtools::SQLExceptionInfo createConnection( const css::uno::Reference< css::beans::XPropertySet >& _xDataSource, @@ -137,8 +137,8 @@ namespace dbaui /** retrieves a data source given by name or URL, and displays an error if this fails Any SQLExceptions which occur will be displayed. - Additionally, and Exceptions which indicate a data source name pointing to a non-existent database - URL will also be denoted. Yet more additionally, and other exceptions will be forwarded to + Additionally, any Exceptions which indicate a data source name pointing to a non-existent database + URL will also be denoted. Yet more additionally, any other exceptions will be forwarded to a InteractionHandler. @param _rDataSourceName @@ -192,14 +192,14 @@ namespace dbaui @param rName the name which should be appended @param rxContext needed to check if datasource is available @param pParent needed when an error must be shown - @return false when datsource is not available otherwise true + @return false when the datasource is not available otherwise true */ bool appendToFilter(const css::uno::Reference< css::sdbc::XConnection>& xConnection, const OUString& rName, const css::uno::Reference< css::uno::XComponentContext >& rxContext, weld::Window* pParent); - /** notifySystemWindow adds or remove the given window _pToRegister at the Systemwindow found when search _pWindow. + /** notifySystemWindow adds or removes the given window _pToRegister at the Systemwindow found when search _pWindow. @param _pWindow The window which is used to search for the SystemWindow. @param _pToRegister diff --git a/dbaccess/source/ui/inc/WCPage.hxx b/dbaccess/source/ui/inc/WCPage.hxx index e02663b57890..d0d7259f9c15 100644 --- a/dbaccess/source/ui/inc/WCPage.hxx +++ b/dbaccess/source/ui/inc/WCPage.hxx @@ -20,7 +20,10 @@ #include "WTabPage.hxx" +#include #include +#include +#include namespace dbaui { diff --git a/dbaccess/source/ui/inc/adtabdlg.hxx b/dbaccess/source/ui/inc/adtabdlg.hxx index 8b2472d32def..68fbc3bba61d 100644 --- a/dbaccess/source/ui/inc/adtabdlg.hxx +++ b/dbaccess/source/ui/inc/adtabdlg.hxx @@ -20,9 +20,11 @@ #include #include +#include #include +#include #include -#include + #include "tabletree.hxx" namespace dbaui diff --git a/dbaccess/source/ui/inc/brwctrlr.hxx b/dbaccess/source/ui/inc/brwctrlr.hxx index 38c8ecc40f35..31b1f4d3db4a 100644 --- a/dbaccess/source/ui/inc/brwctrlr.hxx +++ b/dbaccess/source/ui/inc/brwctrlr.hxx @@ -243,7 +243,7 @@ namespace dbaui virtual void addModelListeners(const css::uno::Reference< css::awt::XControlModel > & _xGridControlModel); virtual void removeModelListeners(const css::uno::Reference< css::awt::XControlModel > & _xGridControlModel); - // want to be a listener grid columns ? use this ! + // want to be a listener to the grid columns ? use this ! virtual void AddColumnListener(const css::uno::Reference< css::beans::XPropertySet > & xCol); virtual void RemoveColumnListener(const css::uno::Reference< css::beans::XPropertySet > & xCol); @@ -258,7 +258,7 @@ namespace dbaui // this method and don't call the base class' method virtual void LoadFinished(bool bWasSynch); - // called if the loading (the _complete_ loading process) is done (no matter if synchron or asynchron). + // called if the loading (the _complete_ loading process) is done (no matter if synchronously or asynchronously). virtual void criticalFail(); // called whenever a reload operation on the rowset failed diff --git a/dbaccess/source/ui/inc/charsetlistbox.hxx b/dbaccess/source/ui/inc/charsetlistbox.hxx index d3dc829c7193..42e537aeb5ba 100644 --- a/dbaccess/source/ui/inc/charsetlistbox.hxx +++ b/dbaccess/source/ui/inc/charsetlistbox.hxx @@ -21,7 +21,7 @@ #include #include -#include + #include "charsets.hxx" class SfxItemSet; diff --git a/dbaccess/source/ui/inc/charsets.hxx b/dbaccess/source/ui/inc/charsets.hxx index 49977bd56262..5a3c995ec71e 100644 --- a/dbaccess/source/ui/inc/charsets.hxx +++ b/dbaccess/source/ui/inc/charsets.hxx @@ -81,7 +81,6 @@ namespace dbaui friend class OCharsetDisplay; friend bool operator==(const ExtendedCharsetIterator& lhs, const ExtendedCharsetIterator& rhs); - friend bool operator!=(const ExtendedCharsetIterator& lhs, const ExtendedCharsetIterator& rhs) { return !(lhs == rhs); } typedef ::dbtools::OCharsetMap container; typedef container::CharsetIterator base_iterator; diff --git a/dbaccess/source/ui/inc/curledit.hxx b/dbaccess/source/ui/inc/curledit.hxx index b0b1753284f3..cf6e076b57fa 100644 --- a/dbaccess/source/ui/inc/curledit.hxx +++ b/dbaccess/source/ui/inc/curledit.hxx @@ -20,7 +20,8 @@ #pragma once #include -#include +#include + #include namespace dbaui @@ -43,7 +44,10 @@ public: public: bool get_visible() const { return m_xEntry->get_visible(); } - void connect_changed(const Link& rLink) { m_xEntry->connect_changed(rLink); } + void connect_changed(const Link& rLink) + { + m_xEntry->connect_changed(rLink); + } void set_help_id(const OUString& rName) { m_xEntry->set_help_id(rName); } void hide() { diff --git a/dbaccess/source/ui/inc/databaseobjectview.hxx b/dbaccess/source/ui/inc/databaseobjectview.hxx index 46df99181627..c1bcbc7aa697 100644 --- a/dbaccess/source/ui/inc/databaseobjectview.hxx +++ b/dbaccess/source/ui/inc/databaseobjectview.hxx @@ -85,6 +85,8 @@ namespace dbaui getApplicationUI() const { return m_xApplication; } css::uno::Reference< css::sdbc::XConnection > getConnection() const; + const css::uno::Reference< css::frame::XFrame >& + getParentFrame() const { return m_xParentFrame; } public: DatabaseObjectView( @@ -148,6 +150,12 @@ namespace dbaui const OUString& _rObjectName ) override; + virtual css::uno::Reference< css::lang::XComponent > doCreateView( + const css::uno::Any& _rDataSource, + const OUString& _rObjectName, + const ::comphelper::NamedValueCollection& i_rCreationArgs + ) override; + public: QueryDesigner( const css::uno::Reference< css::uno::XComponentContext >& _rxORB, diff --git a/dbaccess/source/ui/inc/dbtreelistbox.hxx b/dbaccess/source/ui/inc/dbtreelistbox.hxx index 03e193ed22df..3726231c8610 100644 --- a/dbaccess/source/ui/inc/dbtreelistbox.hxx +++ b/dbaccess/source/ui/inc/dbtreelistbox.hxx @@ -21,8 +21,9 @@ #include #include #include +#include +#include #include -#include #include diff --git a/dbaccess/source/ui/inc/directsql.hxx b/dbaccess/source/ui/inc/directsql.hxx index 58efdcbb97f9..e227387c6b20 100644 --- a/dbaccess/source/ui/inc/directsql.hxx +++ b/dbaccess/source/ui/inc/directsql.hxx @@ -21,10 +21,13 @@ #include +#include +#include #include #include #include -#include +#include + #include #include diff --git a/dbaccess/source/ui/inc/dlgsave.hxx b/dbaccess/source/ui/inc/dlgsave.hxx index 9972dc8d93ab..f44164949d2e 100644 --- a/dbaccess/source/ui/inc/dlgsave.hxx +++ b/dbaccess/source/ui/inc/dlgsave.hxx @@ -23,10 +23,12 @@ #include #include #include +#include #include #include #include -#include +#include + #include namespace com::sun::star { @@ -92,7 +94,7 @@ namespace dbaui OUString getSchema() const; private: DECL_LINK(ButtonClickHdl, weld::Button&, void); - DECL_LINK(EditModifyHdl, weld::Entry&, void); + DECL_LINK(EditModifyHdl, weld::TextWidget&, void); void implInitOnlyTitle(const OUString& _rLabel); void implInit(); diff --git a/dbaccess/source/ui/inc/dlgsize.hxx b/dbaccess/source/ui/inc/dlgsize.hxx index a477cba7c5f6..89872fcb53d1 100644 --- a/dbaccess/source/ui/inc/dlgsize.hxx +++ b/dbaccess/source/ui/inc/dlgsize.hxx @@ -18,9 +18,10 @@ */ #pragma once +#include #include #include -#include +#include namespace dbaui { diff --git a/dbaccess/source/ui/inc/indexdialog.hxx b/dbaccess/source/ui/inc/indexdialog.hxx index 01fc1c67c67f..697fc83ddee8 100644 --- a/dbaccess/source/ui/inc/indexdialog.hxx +++ b/dbaccess/source/ui/inc/indexdialog.hxx @@ -24,10 +24,15 @@ #include #include #include +#include +#include +#include #include +#include #include #include -#include +#include + #include "indexes.hxx" namespace dbaui @@ -66,8 +71,6 @@ public: const css::uno::Reference& _rxContext); virtual ~DbaIndexDialog() override; - typedef std::pair IterString; - private: void fillIndexList(); void updateToolbox(); @@ -78,7 +81,7 @@ private: DECL_LINK(OnIndexSelected, weld::ItemView&, void); DECL_LINK(OnIndexAction, const OUString&, void); DECL_LINK(OnEntryEditing, const weld::TreeIter&, bool); - DECL_LINK(OnEntryEdited, const IterString&, bool); + DECL_LINK(OnEntryEdited, const weld::TreeView::IterColText&, bool); DECL_LINK(OnModifiedClick, weld::Toggleable&, void); DECL_LINK(OnModified, IndexFieldsControl&, void); DECL_LINK(OnCloseDialog, weld::Button&, void); diff --git a/dbaccess/source/ui/inc/opendoccontrols.hxx b/dbaccess/source/ui/inc/opendoccontrols.hxx index c710b48eef7b..09331797718c 100644 --- a/dbaccess/source/ui/inc/opendoccontrols.hxx +++ b/dbaccess/source/ui/inc/opendoccontrols.hxx @@ -19,8 +19,8 @@ #pragma once +#include #include -#include #include namespace dbaui diff --git a/dbaccess/source/ui/inc/paramdialog.hxx b/dbaccess/source/ui/inc/paramdialog.hxx index b39b213cf493..0e3aeac5a045 100644 --- a/dbaccess/source/ui/inc/paramdialog.hxx +++ b/dbaccess/source/ui/inc/paramdialog.hxx @@ -19,10 +19,11 @@ #pragma once +#include #include #include #include -#include +#include #include #include @@ -33,69 +34,70 @@ #include #include -enum class VisitFlags { - NONE = 0x00, - Visited = 0x01, - Dirty = 0x02, +enum class VisitFlags +{ + NONE = 0x00, + Visited = 0x01, + Dirty = 0x02, +}; +namespace o3tl +{ +template <> struct typed_flags : is_typed_flags +{ }; -namespace o3tl { - template<> struct typed_flags : is_typed_flags {}; } namespace dbaui { - // OParameterDialog - class OParameterDialog final - : public weld::GenericDialogController - , public ::svxform::OParseContextClient +// OParameterDialog +class OParameterDialog final : public weld::GenericDialogController, + public ::svxform::OParseContextClient +{ + sal_Int32 m_nCurrentlySelected; + + css::uno::Reference m_xParams; + css::uno::Reference m_xConnection; + css::uno::Reference m_xFormatter; + ::dbtools::OPredicateInputController m_aPredicateInput; + + std::vector m_aVisitedParams; + Timer m_aResetVisitFlag; + // we reset the "visited flag" 1 second after and entry has been selected + + css::uno::Sequence + m_aFinalValues; /// the final values as entered by the user + + // the controls + std::unique_ptr m_xAllParams; + std::unique_ptr m_xParam; + std::unique_ptr m_xTravelNext; + std::unique_ptr m_xOKBtn; + std::unique_ptr m_xCancelBtn; + +public: + OParameterDialog(weld::Window* _pParent, + const css::uno::Reference& _rParamContainer, + const css::uno::Reference& _rxConnection, + const css::uno::Reference& rxContext); + virtual ~OParameterDialog() override; + + const css::uno::Sequence& getValues() const { - sal_Int32 m_nCurrentlySelected; + return m_aFinalValues; + } - css::uno::Reference< css::container::XIndexAccess > - m_xParams; - css::uno::Reference< css::sdbc::XConnection > - m_xConnection; - css::uno::Reference< css::util::XNumberFormatter > - m_xFormatter; - ::dbtools::OPredicateInputController - m_aPredicateInput; +private: + void Construct(); - std::vector m_aVisitedParams; - Timer m_aResetVisitFlag; - // we reset the "visited flag" 1 second after and entry has been selected + DECL_LINK(OnVisitedTimeout, Timer*, void); + DECL_LINK(OnValueModified, weld::TextWidget&, void); + DECL_LINK(OnEntryListBoxSelected, weld::ItemView&, void); + DECL_LINK(OnButtonClicked, weld::Button&, void); + DECL_LINK(OnValueLoseFocusHdl, weld::Widget&, void); + bool CheckValueForError(); + bool OnEntrySelected(); +}; - css::uno::Sequence< css::beans::PropertyValue > - m_aFinalValues; /// the final values as entered by the user - - // the controls - std::unique_ptr m_xAllParams; - std::unique_ptr m_xParam; - std::unique_ptr m_xTravelNext; - std::unique_ptr m_xOKBtn; - std::unique_ptr m_xCancelBtn; - - public: - OParameterDialog(weld::Window* _pParent, - const css::uno::Reference< css::container::XIndexAccess > & _rParamContainer, - const css::uno::Reference< css::sdbc::XConnection > & _rxConnection, - const css::uno::Reference< css::uno::XComponentContext >& rxContext); - virtual ~OParameterDialog() override; - - const css::uno::Sequence< css::beans::PropertyValue >& - getValues() const { return m_aFinalValues; } - - private: - void Construct(); - - DECL_LINK(OnVisitedTimeout, Timer*, void); - DECL_LINK(OnValueModified, weld::Entry&, void); - DECL_LINK(OnEntryListBoxSelected, weld::ItemView&, void); - DECL_LINK(OnButtonClicked, weld::Button&, void); - DECL_LINK(OnValueLoseFocusHdl, weld::Widget&, void); - bool CheckValueForError(); - bool OnEntrySelected(); - }; - -} // namespace dbaui +} // namespace dbaui /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/inc/querycontroller.hxx b/dbaccess/source/ui/inc/querycontroller.hxx index d4347e47d58d..09ba7282373a 100644 --- a/dbaccess/source/ui/inc/querycontroller.hxx +++ b/dbaccess/source/ui/inc/querycontroller.hxx @@ -61,6 +61,10 @@ namespace dbaui css::uno::Reference< css::sdbcx::XAlterView > m_xAlterView; OUString m_sStatement; // contains the current sql statement + OUString + m_sStatementWithComments; // original SQL with comments, saved when entering Design view + OUString + m_sStatementCanonical; // parseNodeToStr of the parse tree when entering Design view OUString m_sUpdateCatalogName; // catalog for update data OUString m_sUpdateSchemaName; // schema for update data mutable OUString @@ -74,6 +78,8 @@ namespace dbaui bool m_bGraphicalDesign; // are we in the graphical design mode (sal_True) or in the text design (sal_False)? bool m_bDistinct; // true when you want "select distinct" otherwise false bool m_bEscapeProcessing;// is true when we shouldn't parse the statement + bool m_bLastEditedInSqlView = false; //true if the query was last saved in SQL view + bool m_bFormatWarningAlreadyShown = false; // true if the destructive-format warning was already shown /** returns the container of queries, views, or command definitions, depending on what object type @@ -187,7 +193,7 @@ namespace dbaui virtual void reset() override; virtual void impl_initialize(const ::comphelper::NamedValueCollection& rArguments) override; - void impl_reset( const bool i_bIgnoreQuerySettings = false ); + void impl_reset( const bool i_bIgnoreQuerySettings = false, const bool i_bIsInitialLoad = false ); /// tells the user that we needed to switch to SQL view automatically void impl_showAutoSQLViewError( const css::uno::Any& _rErrorDetails ); @@ -195,6 +201,12 @@ namespace dbaui */ void impl_setViewMode( ::dbtools::SQLExceptionInfo* _pErrorInfo ); + /** Re-syncs m_sStatementCanonical with what the Design view actually generates + after its columns are fully populated. Must be called after forceInitialView() + or impl_setViewMode() when entering graphical design mode. + */ + void impl_resyncStatementCanonical(); + /// sets m_sStatement, and notifies our respective property change listeners void setStatement_fireEvent( const OUString& _rNewStatement, bool _bFireStatementChange = true ); /// sets the m_bEscapeProcessing member, and notifies our respective property change listeners @@ -206,6 +218,7 @@ namespace dbaui private: DECL_LINK( OnExecuteAddTable, void*, void ); + DECL_LINK( OnDecideCommentsHandling, void*, void ); private: using OQueryController_PBase::getFastPropertyValue; diff --git a/dbaccess/source/ui/inc/queryfilter.hxx b/dbaccess/source/ui/inc/queryfilter.hxx index dab889645ddd..9c0123f4faaa 100644 --- a/dbaccess/source/ui/inc/queryfilter.hxx +++ b/dbaccess/source/ui/inc/queryfilter.hxx @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/dbaccess/source/ui/inc/queryorder.hxx b/dbaccess/source/ui/inc/queryorder.hxx index 808a39a2eb70..33badda822d2 100644 --- a/dbaccess/source/ui/inc/queryorder.hxx +++ b/dbaccess/source/ui/inc/queryorder.hxx @@ -20,7 +20,7 @@ #include #include -#include +#include #define DOG_ROWS 3 diff --git a/dbaccess/source/ui/inc/sbagrid.hxx b/dbaccess/source/ui/inc/sbagrid.hxx index 9cf8c560dc79..a9c819cad3fc 100644 --- a/dbaccess/source/ui/inc/sbagrid.hxx +++ b/dbaccess/source/ui/inc/sbagrid.hxx @@ -243,7 +243,7 @@ namespace dbaui virtual void MouseButtonDown( const BrowserMouseEvent& rMEvt) override; // EditBrowseBox overridables - virtual VclPtr imp_CreateHeaderBar(BrowseBox* pParent) override; + virtual VclPtr imp_CreateHeaderBar(BrowseBox* pParent) override; virtual ::svt::CellController* GetController(sal_Int32 nRow, sal_uInt16 nCol) override; // DbGridControl overridables diff --git a/dbaccess/source/ui/inc/sqlmessage.hxx b/dbaccess/source/ui/inc/sqlmessage.hxx index 9372190c4be3..5dea2a3090a0 100644 --- a/dbaccess/source/ui/inc/sqlmessage.hxx +++ b/dbaccess/source/ui/inc/sqlmessage.hxx @@ -21,9 +21,10 @@ #include #include +#include #include #include -#include + #include namespace dbaui diff --git a/dbaccess/source/ui/inc/textconnectionsettings.hxx b/dbaccess/source/ui/inc/textconnectionsettings.hxx index af0e2fa07561..8bb72c8c3f41 100644 --- a/dbaccess/source/ui/inc/textconnectionsettings.hxx +++ b/dbaccess/source/ui/inc/textconnectionsettings.hxx @@ -20,8 +20,10 @@ #pragma once #include "propertystorage.hxx" +#include #include -#include +#include + #include class SfxItemSet; diff --git a/dbaccess/source/ui/misc/DExport.cxx b/dbaccess/source/ui/misc/DExport.cxx index ad1ff39f3b80..74734eed7818 100644 --- a/dbaccess/source/ui/misc/DExport.cxx +++ b/dbaccess/source/ui/misc/DExport.cxx @@ -242,7 +242,7 @@ ODatabaseExport::ODatabaseExport(const SharedConnection& _rxConnection, aValue.fill(nPos,aTypes[nPos],xRow); m_pTypeInfo->nNumPrecRadix = aValue.getInt32(); - // check if values are less than zero like it happens in a oracle jdbc driver + // check if values are less than zero like it happens in an Oracle JDBC driver if( m_pTypeInfo->nPrecision < 0) m_pTypeInfo->nPrecision = 0; if( m_pTypeInfo->nMinimumScale < 0) @@ -820,7 +820,7 @@ Reference< XPreparedStatement > ODatabaseExport::createPreparedStatement( const aValues[aValues.getLength()-1] = ')'; aSql.append(aValues); - // now create,fill and execute the prepared statement + // now create, fill and execute the prepared statement return _xMetaData->getConnection()->prepareStatement(aSql.makeStringAndClear()); } diff --git a/dbaccess/source/ui/misc/HtmlReader.cxx b/dbaccess/source/ui/misc/HtmlReader.cxx index 0da9f975f0b8..c8d37a0c109a 100644 --- a/dbaccess/source/ui/misc/HtmlReader.cxx +++ b/dbaccess/source/ui/misc/HtmlReader.cxx @@ -89,9 +89,6 @@ SvParserState OHTMLReader::CallParser() return m_bFoundTable ? eParseState : SvParserState::Error; } -#if defined _MSC_VER -#pragma warning(disable: 4702) // unreachable code, bug in MSVC2015 -#endif void OHTMLReader::NextToken( HtmlTokenId nToken ) { if(m_bError || !m_nRows) // if there is an error or no more rows to check, return immediately diff --git a/dbaccess/source/ui/misc/RtfReader.cxx b/dbaccess/source/ui/misc/RtfReader.cxx index 3cb47cda8388..16572699ccdd 100644 --- a/dbaccess/source/ui/misc/RtfReader.cxx +++ b/dbaccess/source/ui/misc/RtfReader.cxx @@ -78,10 +78,6 @@ SvParserState ORTFReader::CallParser() return m_bFoundTable ? eParseState : SvParserState::Error; } -#if defined _MSC_VER -#pragma warning(disable: 4702) // unreachable code, bug in MSVC2015 -#endif - void ORTFReader::NextToken( int nToken ) { if(m_bError || !m_nRows) // if there is an error or no more rows to check, return immediately diff --git a/dbaccess/source/ui/misc/TokenWriter.cxx b/dbaccess/source/ui/misc/TokenWriter.cxx index bd7c9eaafdb1..57f6c6c56e5d 100644 --- a/dbaccess/source/ui/misc/TokenWriter.cxx +++ b/dbaccess/source/ui/misc/TokenWriter.cxx @@ -215,7 +215,7 @@ void ODatabaseImportExport::initialize() if ( !m_xConnection.is() ) { // we need a connection - OSL_ENSURE(!m_sDataSourceName.isEmpty(),"There must be a datsource name!"); + OSL_ENSURE(!m_sDataSourceName.isEmpty(),"There must be a data source name!"); Reference xDatabaseContext( DatabaseContext::create(m_xContext), UNO_QUERY_THROW); Reference< XEventListener> xEvt(this); diff --git a/dbaccess/source/ui/misc/WColumnSelect.cxx b/dbaccess/source/ui/misc/WColumnSelect.cxx index bb47519ffd45..017c0660e9cf 100644 --- a/dbaccess/source/ui/misc/WColumnSelect.cxx +++ b/dbaccess/source/ui/misc/WColumnSelect.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/dbaccess/source/ui/misc/WCopyTable.cxx b/dbaccess/source/ui/misc/WCopyTable.cxx index 0226cc9b4bfb..8f1ba7412c81 100644 --- a/dbaccess/source/ui/misc/WCopyTable.cxx +++ b/dbaccess/source/ui/misc/WCopyTable.cxx @@ -52,6 +52,7 @@ #include #include #include +#include #include #include diff --git a/dbaccess/source/ui/misc/WNameMatch.cxx b/dbaccess/source/ui/misc/WNameMatch.cxx index bbd327ea45b1..2f3033dcb0f0 100644 --- a/dbaccess/source/ui/misc/WNameMatch.cxx +++ b/dbaccess/source/ui/misc/WNameMatch.cxx @@ -18,12 +18,15 @@ */ #include -#include #include #include #include #include #include + +#include +#include + #include using namespace ::dbaui; @@ -58,7 +61,7 @@ OWizNameMatching::OWizNameMatching(weld::Container* pPage, OCopyTableWizard* pWi m_xAll->connect_clicked(LINK(this,OWizNameMatching,AllNoneClickHdl)); m_xNone->connect_clicked(LINK(this,OWizNameMatching,AllNoneClickHdl)); - m_xCTRL_LEFT->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xCTRL_LEFT->enable_toggle_buttons(); m_xCTRL_LEFT->connect_selection_changed(LINK(this, OWizNameMatching, TableListClickHdl)); m_xCTRL_RIGHT->connect_selection_changed(LINK(this, OWizNameMatching, TableListRightSelectHdl)); diff --git a/dbaccess/source/ui/misc/databaseobjectview.cxx b/dbaccess/source/ui/misc/databaseobjectview.cxx index 112c79947393..e9c55451eb65 100644 --- a/dbaccess/source/ui/misc/databaseobjectview.cxx +++ b/dbaccess/source/ui/misc/databaseobjectview.cxx @@ -19,20 +19,33 @@ #include #include +#include +#include +#include #include #include #include #include #include +#include #include #include +#include +#include +#include #include +#include #include #include #include #include +#include +#include +#include +#include +#include #include namespace dbaui @@ -98,10 +111,11 @@ namespace dbaui Reference< XComponent > xReturn; if ( m_xORB.is() ) { + const bool bWeCreateTheFrame = !m_xFrameLoader.is(); try { // if we have no externally provided frame, create one - if ( !m_xFrameLoader.is() ) + if ( bWeCreateTheFrame ) { Reference< XSingleServiceFactory > xFact = TaskCreator::create(m_xORB); Sequence< Any > lArgs{ Any(NamedValue(u"ParentFrame"_ustr, Any(m_xParentFrame))), @@ -128,6 +142,23 @@ namespace dbaui 0, i_rDispatchArgs.getPropertyValues() ); + + // close the frame if the user hit "Cancel" on the SQL-comments warning, see + // OQueryController::impl_reset + if ( !xReturn.is() && bWeCreateTheFrame && m_xFrameLoader.is() ) + { + try + { + Reference< css::util::XCloseable > xCloseable( m_xFrameLoader, UNO_QUERY ); + if ( xCloseable.is() ) + xCloseable->close( true ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + m_xFrameLoader.clear(); + } } catch( const Exception& ) { @@ -187,6 +218,71 @@ namespace dbaui } } + Reference< XComponent > QueryDesigner::doCreateView( const Any& _rDataSource, const OUString& _rObjectName, + const ::comphelper::NamedValueCollection& i_rCreationArgs ) + { + const bool bHeadingIntoDesignView = i_rCreationArgs.getOrDefault( PROPERTY_GRAPHICAL_DESIGN, true ); + if ( m_nCommandType == CommandType::QUERY && !_rObjectName.isEmpty() && bHeadingIntoDesignView + && !Application::IsHeadlessModeEnabled() && !o3tl::IsRunningUITest() ) + { + try + { + Reference< XQueriesSupplier > xSupplier( getConnection(), UNO_QUERY ); + Reference< css::container::XNameAccess > xQueries( xSupplier.is() ? xSupplier->getQueries() : Reference< css::container::XNameAccess >() ); + Reference< XPropertySet > xQuery; + if ( xQueries.is() && xQueries->hasByName( _rObjectName ) ) + xQueries->getByName( _rObjectName ) >>= xQuery; + + Sequence< PropertyValue > aLayoutInformation; + if ( xQuery.is() ) + xQuery->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) >>= aLayoutInformation; + + const ::comphelper::NamedValueCollection aSettings( aLayoutInformation ); + const bool bLastEditedInSqlView = aSettings.getOrDefault( u"LastEditedInSqlView"_ustr, false ); + + if ( bLastEditedInSqlView ) + { + OUString sMessage = DBA_RES( STR_QRY_FORMAT_WARNING_3CHOICES ); + sMessage = sMessage.replaceFirst( "$object$", DBA_RES( RSC_QUERY_OBJECT_TYPE[ m_nCommandType ] ) ); + + const Reference< XFrame >& xParentFrame( getParentFrame() ); + VclPtr pParentWindow = xParentFrame.is() + ? VCLUnoHelper::GetWindow( xParentFrame->getContainerWindow() ) : nullptr; + weld::Window* pParent = pParentWindow ? pParentWindow->GetFrameWeld() : nullptr; + std::unique_ptr xDlg( + Application::CreateMessageDialog( + pParent, VclMessageType::Warning, + VclButtonsType::NONE, sMessage ) ); + xDlg->add_button( u"SQL View"_ustr, RET_NO ); + xDlg->add_button( u"Continue"_ustr, RET_YES ); + xDlg->add_button( GetStandardText( StandardButtonType::Cancel ), RET_CANCEL ); + xDlg->set_default_response( RET_NO ); + sal_uInt16 nResult = xDlg->run(); + + if ( nResult == RET_CANCEL ) + return Reference< XComponent >(); + + // tell the controller we already show the warning, so it doesn't show it again in impl_reset() + // this should be removed in the future together with the comment specific warning + ::comphelper::NamedValueCollection aForcedArgs( i_rCreationArgs ); + aForcedArgs.put( PROPERTY_FORMAT_WARNING_SHOWN, true ); + + if ( nResult == RET_NO ) + { + aForcedArgs.put( PROPERTY_GRAPHICAL_DESIGN, false ); + } + return DatabaseObjectView::doCreateView( _rDataSource, _rObjectName, aForcedArgs ); + } + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION( "dbaccess" ); + } + } + + return DatabaseObjectView::doCreateView( _rDataSource, _rObjectName, i_rCreationArgs ); + } + // TableDesigner TableDesigner::TableDesigner( const Reference< XComponentContext >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame ) :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, URL_COMPONENT_TABLEDESIGN ) diff --git a/dbaccess/source/ui/misc/datasourceconnector.cxx b/dbaccess/source/ui/misc/datasourceconnector.cxx index 33186c31a95a..e177cb9291ba 100644 --- a/dbaccess/source/ui/misc/datasourceconnector.cxx +++ b/dbaccess/source/ui/misc/datasourceconnector.cxx @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx b/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx index 091b6f71db58..95a583acb6c5 100644 --- a/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx +++ b/dbaccess/source/ui/misc/dbsubcomponentcontroller.cxx @@ -44,7 +44,6 @@ #include #include #include -#include namespace dbaui { diff --git a/dbaccess/source/ui/misc/linkeddocuments.cxx b/dbaccess/source/ui/misc/linkeddocuments.cxx index aab5814404e5..686c9ac092c0 100644 --- a/dbaccess/source/ui/misc/linkeddocuments.cxx +++ b/dbaccess/source/ui/misc/linkeddocuments.cxx @@ -37,8 +37,8 @@ #include #include #include -#include - +#include +#include #include #include #include diff --git a/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx b/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx index 881cf498f5ea..8c09be4edefc 100644 --- a/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx +++ b/dbaccess/source/ui/querydesign/ConnectionLineAccess.cxx @@ -43,10 +43,7 @@ namespace dbaui m_pLine = nullptr; VCLXAccessibleComponent::disposing(); } - OUString SAL_CALL OConnectionLineAccess::getImplementationName() - { - return u"org.openoffice.comp.dbu.ConnectionLineAccessibility"_ustr; - } + // XAccessibleContext sal_Int64 SAL_CALL OConnectionLineAccess::getAccessibleChildCount( ) { diff --git a/dbaccess/source/ui/querydesign/JAccess.cxx b/dbaccess/source/ui/querydesign/JAccess.cxx index c538fcf16c8c..f1799b22e50a 100644 --- a/dbaccess/source/ui/querydesign/JAccess.cxx +++ b/dbaccess/source/ui/querydesign/JAccess.cxx @@ -36,10 +36,7 @@ namespace dbaui , m_pTableView(_pTableView) { } - OUString SAL_CALL OJoinDesignViewAccess::getImplementationName() - { - return u"org.openoffice.comp.dbu.JoinViewAccessibility"_ustr; - } + void OJoinDesignViewAccess::clearTableView() { ::osl::MutexGuard aGuard( m_aMutex ); diff --git a/dbaccess/source/ui/querydesign/JoinController.cxx b/dbaccess/source/ui/querydesign/JoinController.cxx index df9f7e03aae7..b08add560dd2 100644 --- a/dbaccess/source/ui/querydesign/JoinController.cxx +++ b/dbaccess/source/ui/querydesign/JoinController.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff --git a/dbaccess/source/ui/querydesign/QTableWindow.cxx b/dbaccess/source/ui/querydesign/QTableWindow.cxx index ed490860c3ea..dbab2b47a434 100644 --- a/dbaccess/source/ui/querydesign/QTableWindow.cxx +++ b/dbaccess/source/ui/querydesign/QTableWindow.cxx @@ -31,6 +31,7 @@ #include "TableFieldInfo.hxx" #include #include +#include using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::uno; diff --git a/dbaccess/source/ui/querydesign/QueryDesignView.cxx b/dbaccess/source/ui/querydesign/QueryDesignView.cxx index 8a823a315471..207a44c15b2f 100644 --- a/dbaccess/source/ui/querydesign/QueryDesignView.cxx +++ b/dbaccess/source/ui/querydesign/QueryDesignView.cxx @@ -28,7 +28,6 @@ #include #include #include -#include #include #include "SelectionBrowseBox.hxx" #include diff --git a/dbaccess/source/ui/querydesign/QueryTableView.cxx b/dbaccess/source/ui/querydesign/QueryTableView.cxx index 5a3f83894303..c60d272272ea 100644 --- a/dbaccess/source/ui/querydesign/QueryTableView.cxx +++ b/dbaccess/source/ui/querydesign/QueryTableView.cxx @@ -112,6 +112,10 @@ namespace _pView->Invalidate(InvalidateFlags::NoChildren); } +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 16 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif void addConnections(OQueryTableView* _pView, const OQueryTableWindow& _rSource, const OQueryTableWindow& _rDest, @@ -172,6 +176,9 @@ namespace // the connection data if we would insert the conn-Undo-Action) } } +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 16 +#pragma GCC diagnostic pop +#endif } OQueryTableView::OQueryTableView( vcl::Window* pParent,OQueryDesignView* pView) @@ -521,6 +528,10 @@ void OQueryTableView::AddTabWin(const OUString& _rComposedName, const OUString& m_pView->getController().addUndoActionAndInvalidate( std::move(pUndoAction) ); } +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 16 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif void OQueryTableView::AddConnection(const OJoinExchangeData& jxdSource, const OJoinExchangeData& jxdDest) { OQueryTableWindow* pSourceWin = static_cast< OQueryTableWindow*>(jxdSource.pListBox->GetTabWin()); @@ -567,6 +578,9 @@ void OQueryTableView::AddConnection(const OJoinExchangeData& jxdSource, const OJ connectionModified(this,pConn,false); } } +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 16 +#pragma GCC diagnostic pop +#endif void OQueryTableView::ConnDoubleClicked(VclPtr& rConnection) { diff --git a/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx b/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx index fda18f7e2ced..b392c32f1f28 100644 --- a/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx +++ b/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include "TableFieldInfo.hxx" @@ -38,7 +39,6 @@ #include #include #include "QTableWindow.hxx" -#include #include #include "QueryDesignFieldUndoAct.hxx" #include @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -292,7 +291,7 @@ namespace } } -VclPtr OSelectionBrowseBox::imp_CreateHeaderBar(BrowseBox* /*pParent*/) +VclPtr OSelectionBrowseBox::imp_CreateHeaderBar(BrowseBox* /*pParent*/) { return VclPtr::Create(this); } diff --git a/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx b/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx index a799ca65e171..6a6a99c9a7d6 100644 --- a/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx +++ b/dbaccess/source/ui/querydesign/SelectionBrowseBox.hxx @@ -206,7 +206,7 @@ namespace dbaui virtual sal_uInt32 GetTotalCellWidth(sal_Int32 nRow, sal_uInt16 nColId) override; // if you want to have an own header ... - virtual VclPtr imp_CreateHeaderBar(BrowseBox* pParent) override; + virtual VclPtr imp_CreateHeaderBar(BrowseBox* pParent) override; void stopTimer(); void startTimer(); diff --git a/dbaccess/source/ui/querydesign/TableConnection.cxx b/dbaccess/source/ui/querydesign/TableConnection.cxx index 1e9d31f419c0..20108b534ffb 100644 --- a/dbaccess/source/ui/querydesign/TableConnection.cxx +++ b/dbaccess/source/ui/querydesign/TableConnection.cxx @@ -24,7 +24,6 @@ #include using namespace dbaui; -using namespace ::com::sun::star::accessibility; namespace dbaui { diff --git a/dbaccess/source/ui/querydesign/TableWindowAccess.cxx b/dbaccess/source/ui/querydesign/TableWindowAccess.cxx index c1932469d72c..81d4037363e5 100644 --- a/dbaccess/source/ui/querydesign/TableWindowAccess.cxx +++ b/dbaccess/source/ui/querydesign/TableWindowAccess.cxx @@ -53,14 +53,7 @@ namespace dbaui VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent ); } - OUString SAL_CALL OTableWindowAccess::getImplementationName() - { - return u"org.openoffice.comp.dbu.TableWindowAccessibility"_ustr; - } - Sequence< OUString > SAL_CALL OTableWindowAccess::getSupportedServiceNames() - { - return { u"com.sun.star.accessibility.AccessibleContext"_ustr }; - } + // XAccessibleContext sal_Int64 SAL_CALL OTableWindowAccess::getAccessibleChildCount( ) { diff --git a/dbaccess/source/ui/querydesign/limitboxcontroller.cxx b/dbaccess/source/ui/querydesign/limitboxcontroller.cxx index 30c6bbb7f967..00a493bcbd8f 100644 --- a/dbaccess/source/ui/querydesign/limitboxcontroller.cxx +++ b/dbaccess/source/ui/querydesign/limitboxcontroller.cxx @@ -15,13 +15,14 @@ #include #include +#include #include #include #include #include #include +#include #include -#include #include #include @@ -208,11 +209,11 @@ css::uno::Sequence< OUString > SAL_CALL LimitBoxController::getSupportedServiceN return { u"com.sun.star.frame.ToolbarController"_ustr }; } -/// XComponent -void SAL_CALL LimitBoxController::dispose() +/// WeakComponentImplHelperBase +void LimitBoxController::disposing(std::unique_lock& rGuard) { - svt::ToolboxController::dispose(); - + svt::ToolboxController::disposing(rGuard); + comphelper::unique_unlock aUnlock(rGuard); SolarMutexGuard aSolarMutexGuard; m_xLimitBox.disposeAndClear(); } diff --git a/dbaccess/source/ui/querydesign/limitboxcontroller.hxx b/dbaccess/source/ui/querydesign/limitboxcontroller.hxx index 142280937235..b80b9c6fa427 100644 --- a/dbaccess/source/ui/querydesign/limitboxcontroller.hxx +++ b/dbaccess/source/ui/querydesign/limitboxcontroller.hxx @@ -35,8 +35,9 @@ class LimitBoxController: public LimitBoxController_Base /// XServiceInfo DECLARE_SERVICE_INFO(); - /// XComponent - virtual void SAL_CALL dispose() override; + /// WeakComponentImplHelperBase + using LimitBoxController_Base::disposing; + virtual void disposing(std::unique_lock& rGuard) override; /// XStatusListener virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override; diff --git a/dbaccess/source/ui/querydesign/querycontroller.cxx b/dbaccess/source/ui/querydesign/querycontroller.cxx index f05cb96f6f11..f14070d21d39 100644 --- a/dbaccess/source/ui/querydesign/querycontroller.cxx +++ b/dbaccess/source/ui/querydesign/querycontroller.cxx @@ -66,9 +66,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -421,6 +421,90 @@ FeatureState OQueryController::GetState(sal_uInt16 _nId) const return aReturn; } +namespace { +struct CommentStrip +{ + OUString maComment; + bool mbLastOnLine; + CommentStrip( OUString sComment, bool bLastOnLine ) + : maComment(std::move( sComment)), mbLastOnLine( bLastOnLine) {} +}; + +} + +/** Obtain all comments in a query. + + See also delComment() implementation for OSQLParser::parseTree(). + */ +static std::vector< CommentStrip > getComment( const OUString& rQuery ) +{ + std::vector< CommentStrip > aRet; + // First a quick search if there is any "--" or "//" or "/*", if not then + // the whole copying loop is pointless. + if (rQuery.indexOf( "--" ) < 0 && rQuery.indexOf( "//" ) < 0 && + rQuery.indexOf( "/*" ) < 0) + return aRet; + + const sal_Unicode* pCopy = rQuery.getStr(); + const sal_Int32 nQueryLen = rQuery.getLength(); + bool bIsText1 = false; // "text" + bool bIsText2 = false; // 'text' + bool bComment2 = false; // /* comment */ + bool bComment = false; // -- or // comment + OUStringBuffer aBuf; + for (sal_Int32 i=0; i < nQueryLen; ++i) + { + if (bComment2) + { + aBuf.append( &pCopy[i], 1); + if ((i+1) < nQueryLen) + { + if (pCopy[i]=='*' && pCopy[i+1]=='/') + { + bComment2 = false; + aBuf.append( &pCopy[++i], 1); + aRet.emplace_back( aBuf.makeStringAndClear(), false); + } + } + else + { + // comment can't close anymore, actually an error, but... + aRet.emplace_back( aBuf.makeStringAndClear(), false); + } + continue; + } + if (pCopy[i] == '\n' || i == nQueryLen-1) + { + if (bComment) + { + if (i == nQueryLen-1 && pCopy[i] != '\n') + aBuf.append( &pCopy[i], 1); + aRet.emplace_back( aBuf.makeStringAndClear(), true); + bComment = false; + } + else if (!aRet.empty()) + aRet.back().mbLastOnLine = true; + } + else if (!bComment) + { + if (pCopy[i] == '\"' && !bIsText2) + bIsText1 = !bIsText1; + else if (pCopy[i] == '\'' && !bIsText1) + bIsText2 = !bIsText2; + if (!bIsText1 && !bIsText2 && (i+1) < nQueryLen) + { + if ((pCopy[i]=='-' && pCopy[i+1]=='-') || (pCopy[i]=='/' && pCopy[i+1]=='/')) + bComment = true; + else if (pCopy[i]=='/' && pCopy[i+1]=='*') + bComment2 = true; + } + } + if (bComment || bComment2) + aBuf.append( &pCopy[i], 1); + } + return aRet; +} + void OQueryController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs) { switch(_nId) @@ -462,7 +546,29 @@ void OQueryController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& SQLExceptionInfo aError; try { - setStatement_fireEvent( getContainer()->getStatement() ); + OUString sContainerStatement = getContainer()->getStatement(); + + // When switching Design->SQL, preserve the original SQL with + // comments if the query body was not modified in Design view. + OUString sSavedStatementWithComments; + if (m_bGraphicalDesign && !m_sStatementWithComments.isEmpty() && m_pSqlIterator + && m_pSqlIterator->getParseTree()) + { + // Parse the statement and check if it is the same with the + // cached statement m_sStatementCanonical + OUString sContainerCanonical; + { + OUString sErr; + std::unique_ptr<::connectivity::OSQLParseNode> pTmp( + m_aSqlParser.parseTree(sErr, sContainerStatement, m_bGraphicalDesign)); + if (pTmp) + pTmp->parseNodeToStr(sContainerCanonical, getConnection()); + } + if (sContainerCanonical == m_sStatementCanonical) + sSavedStatementWithComments = m_sStatementWithComments; + } + + setStatement_fireEvent(sContainerStatement); if(m_sStatement.isEmpty() && m_pSqlIterator) { // change the view of the data @@ -501,14 +607,63 @@ void OQueryController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& } else { + if (!m_bGraphicalDesign) + { + OUString sCurrentCanonical; + if (m_pSqlIterator->getParseTree()) + m_pSqlIterator->getParseTree()->parseNodeToStr( + sCurrentCanonical, getConnection()); + if (sCurrentCanonical != m_sStatement) + { + bool bUserSaysNo = true; + if (!Application::IsHeadlessModeEnabled() && !o3tl::IsRunningUITest()) + { + OUString aMessage = lcl_getObjectResourceString( + STR_QRY_FORMAT_WARNING_2CHOICES, + m_nCommandType); + std::unique_ptr xDlg( + Application::CreateMessageDialog( + getFrameWeld(), VclMessageType::Warning, + VclButtonsType::YesNo, aMessage)); + xDlg->set_default_response(RET_NO); + bUserSaysNo = (xDlg->run() == RET_NO); + } + if (bUserSaysNo) + break; // stay in SQL view + } + } + // change the view of the data m_bGraphicalDesign = !m_bGraphicalDesign; + + if (m_bGraphicalDesign) + { + // save the original SQL (with comments) + // so it can be restored when switching back. + m_sStatementWithComments = m_sStatement; + m_sStatementCanonical.clear(); + m_pSqlIterator->getParseTree()->parseNodeToStr( + m_sStatementCanonical, getConnection()); + } + else + { + m_sStatementWithComments.clear(); + m_sStatementCanonical.clear(); + } + OUString sNewStatement; - m_pSqlIterator->getParseTree()->parseNodeToStr( sNewStatement, getConnection() ); + if (!sSavedStatementWithComments.isEmpty()) + sNewStatement = sSavedStatementWithComments; + else if (m_bGraphicalDesign) + sNewStatement = m_sStatementCanonical; + else + m_pSqlIterator->getParseTree()->parseNodeToStr(sNewStatement, + getConnection()); setStatement_fireEvent( sNewStatement ); getContainer()->SaveUIConfig(); m_vTableConnectionData.clear(); impl_setViewMode( &aError ); + impl_resyncStatementCanonical(); } } } @@ -617,6 +772,23 @@ void OQueryController::impl_showAutoSQLViewError( const css::uno::Any& _rErrorDe showError( aErrorContext ); } +void OQueryController::impl_resyncStatementCanonical() +{ + if (!m_bGraphicalDesign || m_sStatementWithComments.isEmpty()) + return; + OUString sDesignSQL = getContainer()->getStatement(); + if (sDesignSQL.isEmpty()) + return; + OUString sErr; + std::unique_ptr<::connectivity::OSQLParseNode> pTmp( + m_aSqlParser.parseTree(sErr, sDesignSQL, m_bGraphicalDesign)); + if (pTmp) + { + m_sStatementCanonical.clear(); + pTmp->parseNodeToStr(m_sStatementCanonical, getConnection()); + } +} + void OQueryController::impl_setViewMode( ::dbtools::SQLExceptionInfo* _pErrorInfo ) { OSL_PRECOND( getContainer(), "OQueryController::impl_setViewMode: illegal call!" ); @@ -710,6 +882,7 @@ void OQueryController::impl_initialize(const ::comphelper::NamedValueCollection& // more non-legacy rArguments.get_ensureType( PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign ); + rArguments.get_ensureType( PROPERTY_FORMAT_WARNING_SHOWN, m_bFormatWarningAlreadyShown ); bool bEscapeProcessing( true ); if ( rArguments.get_ensureType( PROPERTY_ESCAPE_PROCESSING, bEscapeProcessing ) ) @@ -803,7 +976,7 @@ void OQueryController::impl_initialize(const ::comphelper::NamedValueCollection& try { getContainer()->initialize(); - impl_reset( bForceInitialDesign ); + impl_reset( bForceInitialDesign, /*i_bIsInitialLoad*/ true ); SQLExceptionInfo aError; const bool bAttemptedGraphicalDesign = m_bGraphicalDesign; @@ -817,6 +990,8 @@ void OQueryController::impl_initialize(const ::comphelper::NamedValueCollection& impl_setViewMode( &aError ); } + impl_resyncStatementCanonical(); + if ( aError.isValid() && bAttemptedGraphicalDesign && !m_bGraphicalDesign ) { // we tried initializing the graphical view, this failed, and we were automatically switched to SQL @@ -1010,6 +1185,7 @@ void OQueryController::saveViewSettings( ::comphelper::NamedValueCollection& o_r o_rViewSettings.put( u"Fields"_ustr, aAllFieldsData.getPropertyValues() ); o_rViewSettings.put( u"SplitterPosition"_ustr, m_nSplitPos ); o_rViewSettings.put( u"VisibleRows"_ustr, m_nVisibleRows ); + o_rViewSettings.put( u"LastEditedInSqlView"_ustr, !m_bGraphicalDesign ); } void OQueryController::loadViewSettings( const ::comphelper::NamedValueCollection& o_rViewSettings ) @@ -1019,6 +1195,7 @@ void OQueryController::loadViewSettings( const ::comphelper::NamedValueCollectio m_nSplitPos = o_rViewSettings.getOrDefault( u"SplitterPosition"_ustr, m_nSplitPos ); m_nVisibleRows = o_rViewSettings.getOrDefault( u"VisibleRows"_ustr, m_nVisibleRows ); m_aFieldInformation = o_rViewSettings.getOrDefault( u"Fields"_ustr, m_aFieldInformation ); + m_bLastEditedInSqlView = o_rViewSettings.getOrDefault( u"LastEditedInSqlView"_ustr, false ); } void OQueryController::execute_QueryPropDlg() @@ -1369,90 +1546,6 @@ bool OQueryController::doSaveAsDoc(bool _bSaveAs) return bSuccess; } -namespace { -struct CommentStrip -{ - OUString maComment; - bool mbLastOnLine; - CommentStrip( OUString sComment, bool bLastOnLine ) - : maComment(std::move( sComment)), mbLastOnLine( bLastOnLine) {} -}; - -} - -/** Obtain all comments in a query. - - See also delComment() implementation for OSQLParser::parseTree(). - */ -static std::vector< CommentStrip > getComment( const OUString& rQuery ) -{ - std::vector< CommentStrip > aRet; - // First a quick search if there is any "--" or "//" or "/*", if not then - // the whole copying loop is pointless. - if (rQuery.indexOf( "--" ) < 0 && rQuery.indexOf( "//" ) < 0 && - rQuery.indexOf( "/*" ) < 0) - return aRet; - - const sal_Unicode* pCopy = rQuery.getStr(); - const sal_Int32 nQueryLen = rQuery.getLength(); - bool bIsText1 = false; // "text" - bool bIsText2 = false; // 'text' - bool bComment2 = false; // /* comment */ - bool bComment = false; // -- or // comment - OUStringBuffer aBuf; - for (sal_Int32 i=0; i < nQueryLen; ++i) - { - if (bComment2) - { - aBuf.append( &pCopy[i], 1); - if ((i+1) < nQueryLen) - { - if (pCopy[i]=='*' && pCopy[i+1]=='/') - { - bComment2 = false; - aBuf.append( &pCopy[++i], 1); - aRet.emplace_back( aBuf.makeStringAndClear(), false); - } - } - else - { - // comment can't close anymore, actually an error, but... - aRet.emplace_back( aBuf.makeStringAndClear(), false); - } - continue; - } - if (pCopy[i] == '\n' || i == nQueryLen-1) - { - if (bComment) - { - if (i == nQueryLen-1 && pCopy[i] != '\n') - aBuf.append( &pCopy[i], 1); - aRet.emplace_back( aBuf.makeStringAndClear(), true); - bComment = false; - } - else if (!aRet.empty()) - aRet.back().mbLastOnLine = true; - } - else if (!bComment) - { - if (pCopy[i] == '\"' && !bIsText2) - bIsText1 = !bIsText1; - else if (pCopy[i] == '\'' && !bIsText1) - bIsText2 = !bIsText2; - if (!bIsText1 && !bIsText2 && (i+1) < nQueryLen) - { - if ((pCopy[i]=='-' && pCopy[i+1]=='-') || (pCopy[i]=='/' && pCopy[i+1]=='/')) - bComment = true; - else if (pCopy[i]=='/' && pCopy[i+1]=='*') - bComment2 = true; - } - } - if (bComment || bComment2) - aBuf.append( &pCopy[i], 1); - } - return aRet; -} - /** Concat/insert comments that were previously obtained with getComment(). NOTE: The current parser implementation does not preserve newlines, so all @@ -1521,18 +1614,30 @@ OUString OQueryController::translateStatement( bool _bFireStatementChange ) try { OUString aErrorMsg; + std::unique_ptr<::connectivity::OSQLParseNode> pNode + = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ); - std::vector< CommentStrip > aComments = getComment( m_sStatement); - - std::unique_ptr<::connectivity::OSQLParseNode> pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ); - if(pNode) + if (pNode) { - pNode->parseNodeToStr( sTranslatedStmt, getConnection() ); + if (m_bGraphicalDesign) + { + // Design view: need composer to assemble query from parts. + // Extract comments first, then re-attach after composition. + std::vector aComments = getComment(m_sStatement); + pNode->parseNodeToStr(sTranslatedStmt, getConnection()); + m_xComposer->setQuery(sTranslatedStmt); + sTranslatedStmt = m_xComposer->getComposedQuery(); + sTranslatedStmt = concatComment(sTranslatedStmt, aComments); + } + else + { + // SQL view (tdf#42713): preserve the raw SQL text as written + // by the user, including original formatting and comment + // positions. Parse above validated syntax; no need for + // compose/recompose round-trip. + sTranslatedStmt = m_sStatement; + } } - - m_xComposer->setQuery(sTranslatedStmt); - sTranslatedStmt = m_xComposer->getComposedQuery(); - sTranslatedStmt = concatComment( sTranslatedStmt, aComments); } catch(const SQLException& e) { @@ -1585,7 +1690,7 @@ short OQueryController::saveModified() return nRet; } -void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings ) +void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings, const bool i_bIsInitialLoad ) { bool bValid = false; @@ -1705,6 +1810,76 @@ void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings setQueryComposer(); OSL_ENSURE(m_pSqlIterator,"No SQLIterator set!"); + // When loading (or re-loading) in Design view, check whether entering it would + // be destructive: either the SQL has comments (tdf#42713), or (more generally) + // it was last saved in SQL View (tdf#46841), meaning it may carry custom + // formatting (or comments) that Design View's canonicalization would destroy. + // TODO: in the future only check if last saved in SQL View + // (keep for now the comments check for backward compatibility). + if (m_bGraphicalDesign && !m_sStatement.isEmpty() && m_sStatementWithComments.isEmpty()) + { + auto cacheStatementWithComments = [this] + { + m_sStatementWithComments = m_sStatement; + if (m_pSqlIterator && m_pSqlIterator->getParseTree()) + { + m_sStatementCanonical.clear(); + m_pSqlIterator->getParseTree()->parseNodeToStr( + m_sStatementCanonical, getConnection()); + } + }; + + std::vector aComments = getComment(m_sStatement); + if ((!aComments.empty() || m_bLastEditedInSqlView) && !m_bFormatWarningAlreadyShown) + { + if (Application::IsHeadlessModeEnabled() || o3tl::IsRunningUITest()) + { + // No UI available/desired; keep the existing safe default. + m_bGraphicalDesign = false; + } + else if (i_bIsInitialLoad) + { + OUString aMessage = lcl_getObjectResourceString( + !aComments.empty() ? STR_QRY_COMMENTS_WARNING_3CHOICES + : STR_QRY_FORMAT_WARNING_3CHOICES, + m_nCommandType); + std::unique_ptr xDlg( + Application::CreateMessageDialog( + getFrameWeld(), VclMessageType::Warning, + VclButtonsType::NONE, aMessage)); + xDlg->add_button(u"SQL View"_ustr, RET_NO); + xDlg->add_button(u"Continue"_ustr, RET_YES); + xDlg->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); + xDlg->set_default_response(RET_NO); + sal_uInt16 nResult = xDlg->run(); + + if (nResult == RET_CANCEL) + { + throw VetoException(); + } + if (nResult == RET_NO) + { + m_bGraphicalDesign = false; + m_sStatementWithComments.clear(); + m_sStatementCanonical.clear(); + } + else // RET_YES + { + cacheStatementWithComments(); + } + } + else + { + cacheStatementWithComments(); + Application::PostUserEvent(LINK(this, OQueryController, OnDecideCommentsHandling)); + } + } + else + { + cacheStatementWithComments(); + } + } + getContainer()->setNoneVisibleRow(m_nVisibleRows); } @@ -1744,6 +1919,38 @@ IMPL_LINK_NOARG( OQueryController, OnExecuteAddTable, void*, void ) Execute( ID_BROWSER_ADDTABLE,Sequence() ); } +IMPL_LINK_NOARG( OQueryController, OnDecideCommentsHandling, void*, void ) +{ + // keep for backward compatibility + const bool bHasComments = !getComment(m_sStatementWithComments).empty(); + OUString aMessage = lcl_getObjectResourceString( + bHasComments ? STR_QRY_COMMENTS_WARNING_3CHOICES : STR_QRY_FORMAT_WARNING_3CHOICES, + m_nCommandType); + std::unique_ptr xDlg( + Application::CreateMessageDialog( + getFrameWeld(), VclMessageType::Warning, + VclButtonsType::NONE, aMessage)); + xDlg->add_button(u"SQL View"_ustr, RET_NO); + xDlg->add_button(u"Continue"_ustr, RET_YES); + xDlg->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); + xDlg->set_default_response(RET_NO); + sal_uInt16 nResult = xDlg->run(); + + if (nResult == RET_CANCEL) + { + closeTask(); + return; + } + if (nResult == RET_NO) + { + m_bGraphicalDesign = false; + m_sStatementWithComments.clear(); + m_sStatementCanonical.clear(); + impl_setViewMode(nullptr); + } + // RET_YES: already tentatively in Design View; nothing more to do. +} + bool OQueryController::allowViews() const { return true; diff --git a/dbaccess/source/ui/querydesign/querydlg.hxx b/dbaccess/source/ui/querydesign/querydlg.hxx index 232a6ff07be8..7c55c6c80055 100644 --- a/dbaccess/source/ui/querydesign/querydlg.hxx +++ b/dbaccess/source/ui/querydesign/querydlg.hxx @@ -18,9 +18,11 @@ */ #pragma once +#include +#include #include #include -#include +#include #include diff --git a/dbaccess/source/ui/relationdesign/RelationController.cxx b/dbaccess/source/ui/relationdesign/RelationController.cxx index a5d7e6661166..14b3db74d401 100644 --- a/dbaccess/source/ui/relationdesign/RelationController.cxx +++ b/dbaccess/source/ui/relationdesign/RelationController.cxx @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/dbaccess/source/ui/tabledesign/TEditControl.cxx b/dbaccess/source/ui/tabledesign/TEditControl.cxx index bdf03446e32e..49ce7a749143 100644 --- a/dbaccess/source/ui/tabledesign/TEditControl.cxx +++ b/dbaccess/source/ui/tabledesign/TEditControl.cxx @@ -44,6 +44,7 @@ #include #include #include +#include using namespace ::dbaui; using namespace ::comphelper; @@ -404,18 +405,18 @@ EditBrowseBox::RowStatus OTableEditorCtrl::GetRowStatus(sal_Int32 nRow) const { const_cast(this)->SetDataPtr( nRow ); if( !pActRow ) - return EditBrowseBox::CLEAN; + return RowStatus::CLEAN; if (nRow >= 0 && nRow == m_nDataPos) { if( pActRow->IsPrimaryKey() ) - return EditBrowseBox::CURRENT_PRIMARYKEY; - return EditBrowseBox::CURRENT; + return RowStatus::CURRENT_PRIMARYKEY; + return RowStatus::CURRENT; } else { if( pActRow->IsPrimaryKey() ) - return EditBrowseBox::PRIMARYKEY; - return EditBrowseBox::CLEAN; + return RowStatus::PRIMARYKEY; + return RowStatus::CLEAN; } } diff --git a/dbaccess/source/ui/tabledesign/TableController.cxx b/dbaccess/source/ui/tabledesign/TableController.cxx index 4711e49a943f..85a2c93da4f6 100644 --- a/dbaccess/source/ui/tabledesign/TableController.cxx +++ b/dbaccess/source/ui/tabledesign/TableController.cxx @@ -53,7 +53,6 @@ #include #include #include -#include #include #include diff --git a/dbaccess/source/ui/tabledesign/TableDesignControl.cxx b/dbaccess/source/ui/tabledesign/TableDesignControl.cxx index f06bea1c45b2..a04582dd1f1e 100644 --- a/dbaccess/source/ui/tabledesign/TableDesignControl.cxx +++ b/dbaccess/source/ui/tabledesign/TableDesignControl.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -167,9 +168,9 @@ void OTableRowView::Paste( sal_Int32 nRow ) EditBrowseBox::RowStatus OTableRowView::GetRowStatus(sal_Int32 nRow) const { if (nRow >= 0 && m_nDataPos == nRow) - return CURRENT; + return RowStatus::CURRENT; else - return CLEAN; + return RowStatus::CLEAN; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/ui/uno/composerdialogs.hxx b/dbaccess/source/ui/uno/composerdialogs.hxx index b42a8b10e25a..23747b7112e4 100644 --- a/dbaccess/source/ui/uno/composerdialogs.hxx +++ b/dbaccess/source/ui/uno/composerdialogs.hxx @@ -28,7 +28,7 @@ #include #include #include -#include +#include namespace dbaui { diff --git a/dbaccess/source/ui/uno/copytablewizard.cxx b/dbaccess/source/ui/uno/copytablewizard.cxx index 13a4f050731b..29d1d8b70927 100644 --- a/dbaccess/source/ui/uno/copytablewizard.cxx +++ b/dbaccess/source/ui/uno/copytablewizard.cxx @@ -68,6 +68,7 @@ #include #include #include +#include namespace dbaui { diff --git a/dbaccess/uiconfig/dbapp/menubar/menubar.xml b/dbaccess/uiconfig/dbapp/menubar/menubar.xml index 7ef526f54527..f5f21f1a196e 100644 --- a/dbaccess/uiconfig/dbapp/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbapp/menubar/menubar.xml @@ -21,20 +21,20 @@ - - + + - + - + @@ -44,7 +44,7 @@ - + @@ -54,84 +54,84 @@ - + - - - - + + + + - - + + - - - + + + - + - - - + + + - - - - + + + + - - - + + + - + - - - - - + + + + + - - - + + + - + - - - - + + + + - + - + - - - - + + + + - + - + @@ -146,20 +146,19 @@ - + - - + - + - + diff --git a/dbaccess/uiconfig/dbquery/menubar/menubar.xml b/dbaccess/uiconfig/dbquery/menubar/menubar.xml index 52f055cd28a5..bc90bb533bd2 100644 --- a/dbaccess/uiconfig/dbquery/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbquery/menubar/menubar.xml @@ -21,20 +21,20 @@ - - + + - + - + @@ -46,48 +46,48 @@ - - - + + + - + - - + + - - + + - - - + + + - - + + - + - + - - - - + + + + - + - + @@ -95,27 +95,26 @@ - + - + - - + - + - + diff --git a/dbaccess/uiconfig/dbrelation/menubar/menubar.xml b/dbaccess/uiconfig/dbrelation/menubar/menubar.xml index 1de2991b3e48..a25bbc0f580f 100644 --- a/dbaccess/uiconfig/dbrelation/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbrelation/menubar/menubar.xml @@ -21,8 +21,8 @@ - - + + @@ -33,7 +33,7 @@ - + @@ -50,27 +50,27 @@ - - + + - + - + - - - - + + + + - + - + @@ -78,27 +78,26 @@ - + - + - - + - + - + diff --git a/dbaccess/uiconfig/dbtable/menubar/menubar.xml b/dbaccess/uiconfig/dbtable/menubar/menubar.xml index 0ee0275ff3f7..98d6985abb1e 100644 --- a/dbaccess/uiconfig/dbtable/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbtable/menubar/menubar.xml @@ -21,20 +21,20 @@ - - + + - + - + @@ -55,22 +55,22 @@ - + - + - + - - - - + + + + - + - + @@ -78,27 +78,26 @@ - + - + - - + - + - + diff --git a/dbaccess/uiconfig/dbtdata/menubar/menubar.xml b/dbaccess/uiconfig/dbtdata/menubar/menubar.xml index a00d50fbd511..bccbea561c7c 100644 --- a/dbaccess/uiconfig/dbtdata/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbtdata/menubar/menubar.xml @@ -21,20 +21,20 @@ - - + + - + - + @@ -46,12 +46,12 @@ - + - - + + - + @@ -69,33 +69,33 @@ - - - + + + - - - + + + - + - + - + - - - - + + + + - + - + @@ -103,27 +103,26 @@ - + - + - - + - + - + diff --git a/dbaccess/uiconfig/ui/admindialog.ui b/dbaccess/uiconfig/ui/admindialog.ui index 6c54c7ba0588..da2184a434a5 100644 --- a/dbaccess/uiconfig/ui/admindialog.ui +++ b/dbaccess/uiconfig/ui/admindialog.ui @@ -20,20 +20,6 @@ False end - - - _Reset - True - True - True - True - - - False - True - 0 - - _OK @@ -47,7 +33,7 @@ False True - 1 + 0 @@ -61,7 +47,7 @@ False True - 2 + 1 @@ -126,7 +112,6 @@ - reset ok cancel help diff --git a/dbaccess/uiconfig/ui/advancedsettingsdialog.ui b/dbaccess/uiconfig/ui/advancedsettingsdialog.ui index 16bb7f19aa44..044e91ceff21 100644 --- a/dbaccess/uiconfig/ui/advancedsettingsdialog.ui +++ b/dbaccess/uiconfig/ui/advancedsettingsdialog.ui @@ -20,20 +20,6 @@ False end - - - _Reset - True - True - True - True - - - False - True - 0 - - _OK @@ -47,7 +33,7 @@ False True - 1 + 0 @@ -61,7 +47,7 @@ False True - 2 + 1 @@ -75,7 +61,7 @@ False True - 3 + 2 True @@ -105,7 +91,6 @@ - reset ok cancel help diff --git a/dbaccess/uiconfig/ui/dbtreelist.ui b/dbaccess/uiconfig/ui/dbtreelist.ui index e4d628c98c83..4682dc4d5233 100644 --- a/dbaccess/uiconfig/ui/dbtreelist.ui +++ b/dbaccess/uiconfig/ui/dbtreelist.ui @@ -1,13 +1,13 @@ - + - - + + @@ -51,20 +51,20 @@ 6 - - - - 0 - - 4 - 1 + 0 5 + + + + 1 + + @@ -90,7 +90,7 @@ 0 - static + static diff --git a/dbaccess/uiconfig/ui/fielddialog.ui b/dbaccess/uiconfig/ui/fielddialog.ui index 75f5a73b0414..cbcdbc044ff1 100644 --- a/dbaccess/uiconfig/ui/fielddialog.ui +++ b/dbaccess/uiconfig/ui/fielddialog.ui @@ -175,7 +175,7 @@ - reset + reset ok cancel help diff --git a/dbaccess/uiconfig/ui/generalpagewizard.ui b/dbaccess/uiconfig/ui/generalpagewizard.ui index 9e7ecd044cf4..da8071996b03 100644 --- a/dbaccess/uiconfig/ui/generalpagewizard.ui +++ b/dbaccess/uiconfig/ui/generalpagewizard.ui @@ -250,16 +250,22 @@ 0 - - - True - False - True - 24 - - - Select the database type for the existing database connection. + + + True + False + True + 24 + + + Select the database type for the existing database connection. + + + + 0 + 10 + @@ -267,12 +273,6 @@ 10 - - - 0 - 10 - - False diff --git a/dbaccess/uiconfig/ui/namematchingpage.ui b/dbaccess/uiconfig/ui/namematchingpage.ui index 3d7d35a7241c..9b4cb2c2c31b 100644 --- a/dbaccess/uiconfig/ui/namematchingpage.ui +++ b/dbaccess/uiconfig/ui/namematchingpage.ui @@ -1,5 +1,5 @@ - + @@ -26,23 +26,23 @@ True - False + False True True - 6 + 6 12 True - False + False vertical 6 - center + center True - True - True + True + True False @@ -53,8 +53,8 @@ True - True - True + True + True False @@ -66,9 +66,9 @@ _All True - True - True - True + True + True + True False @@ -80,9 +80,9 @@ Non_e True - True - True - True + True + True + True False @@ -100,7 +100,7 @@ True - False + False True True vertical @@ -108,11 +108,11 @@ True - False + False start Source table: - True - left + True + left 0 @@ -124,21 +124,21 @@ True - True + True True True - in + in True - True - True + True + True True True liststore1 - False - 1 - False + False + 1 + False @@ -154,12 +154,6 @@ 4 - - - - - True - 6 @@ -187,7 +181,7 @@ True - False + False True True vertical @@ -195,11 +189,11 @@ True - False + False start Destination table: - True - right + True + right 0 @@ -211,21 +205,21 @@ True - True + True True True - in + in True - True - True + True + True True True liststore2 - False - 0 - False + False + 0 + False @@ -260,15 +254,15 @@ True - False + False vertical 6 - center + center True - True - True + True + True False @@ -279,8 +273,8 @@ True - True - True + True + True False diff --git a/dbaccess/uiconfig/ui/postgrespage.ui b/dbaccess/uiconfig/ui/postgrespage.ui index 207029785a21..03bd7de91777 100644 --- a/dbaccess/uiconfig/ui/postgrespage.ui +++ b/dbaccess/uiconfig/ui/postgrespage.ui @@ -151,7 +151,7 @@ True - Enter the server url of the database. + Enter the server URL of the database. diff --git a/dbaccess/uiconfig/ui/savedialog.ui b/dbaccess/uiconfig/ui/savedialog.ui index 947b4378a8ae..2e183894cfd7 100644 --- a/dbaccess/uiconfig/ui/savedialog.ui +++ b/dbaccess/uiconfig/ui/savedialog.ui @@ -1,36 +1,33 @@ - + - False - 6 + False + 6 Save As False True - 0 - 0 - dialog - - - + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -43,8 +40,8 @@ _Cancel True - True - True + True + True True @@ -57,8 +54,8 @@ _Help True - True - True + True + True True @@ -72,122 +69,137 @@ False True - end + end 0 - + True - False - 6 - 12 + False + 6 + 12 True - False + False Please enter a name for the object to be created: True - 52 + 52 0 - 0 - 0 + 0 + 0 2 True - False + False _Catalog: - True - catalog + True + catalog 1 - 0 - 1 + 0 + 1 True - False + False _Schema: - True - schema + True + schema 1 - 0 - 2 + 0 + 2 True - False - True - title + False + True + title 1 - 0 - 3 + 0 + 3 True - True + True True + True True - True + + + Enter the name of the database object to save or rename. + + - 1 - 3 + 1 + 3 True - False + False True - True + True - True + True + True True - True + + + Enter the name of the catalog that is assigned to the query or table view. + + - 1 - 1 + 1 + 1 True - False + False True - True + True - True + True + True True - True + + + Enter the name of the schema that is assigned to the query or table view. + + - 1 - 2 + 1 + 2 diff --git a/dbaccess/uiconfig/ui/tablelistbox.ui b/dbaccess/uiconfig/ui/tablelistbox.ui index bb0c932b9553..2af9c9bb55d6 100644 --- a/dbaccess/uiconfig/ui/tablelistbox.ui +++ b/dbaccess/uiconfig/ui/tablelistbox.ui @@ -2,7 +2,7 @@ - + diff --git a/dbaccess/uiconfig/ui/tablesfilterpage.ui b/dbaccess/uiconfig/ui/tablesfilterpage.ui index 6e9bf0e5ab3a..9f59e39a51dd 100644 --- a/dbaccess/uiconfig/ui/tablesfilterpage.ui +++ b/dbaccess/uiconfig/ui/tablesfilterpage.ui @@ -4,10 +4,10 @@ - - + + @@ -77,20 +77,20 @@ 6 - - - - 0 - - 4 - 1 + 0 5 + + + + 1 + + diff --git a/dbaccess/uiconfig/ui/tablesjoindialog.ui b/dbaccess/uiconfig/ui/tablesjoindialog.ui index 49fb8b719c44..5ea59744ea8a 100644 --- a/dbaccess/uiconfig/ui/tablesjoindialog.ui +++ b/dbaccess/uiconfig/ui/tablesjoindialog.ui @@ -2,7 +2,7 @@ - + diff --git a/dbaccess/uiconfig/ui/useradmindialog.ui b/dbaccess/uiconfig/ui/useradmindialog.ui index 0da35f89f259..09aae26ddae1 100644 --- a/dbaccess/uiconfig/ui/useradmindialog.ui +++ b/dbaccess/uiconfig/ui/useradmindialog.ui @@ -23,19 +23,6 @@ False end - - - _Reset - True - True - True - - - False - True - 0 - - _OK @@ -49,7 +36,7 @@ False True - 1 + 0 @@ -63,7 +50,7 @@ False True - 2 + 1 @@ -77,7 +64,7 @@ False True - 3 + 2 True @@ -152,7 +139,6 @@ - reset ok cancel help diff --git a/desktop/Executable_oosplash.mk b/desktop/Executable_oosplash.mk index 2808e0113510..d1a5013a44cc 100644 --- a/desktop/Executable_oosplash.mk +++ b/desktop/Executable_oosplash.mk @@ -12,6 +12,7 @@ $(eval $(call gb_Executable_Executable,oosplash)) $(eval $(call gb_Executable_set_targettype_gui,oosplash,YES)) $(eval $(call gb_Executable_use_libraries,oosplash,\ + comphelper \ sal \ )) @@ -20,6 +21,9 @@ $(eval $(call gb_Executable_add_cobjects,oosplash,\ desktop/unx/source/file_image_unx \ $(if $(ENABLE_PAGEIN),desktop/unx/source/pagein) \ desktop/unx/source/splashx \ +)) + +$(eval $(call gb_Executable_add_cxxobjects,oosplash,\ desktop/unx/source/start \ )) diff --git a/desktop/inc/dp_misc.h b/desktop/inc/dp_misc.h index d0004d8f5864..c6a730930aea 100644 --- a/desktop/inc/dp_misc.h +++ b/desktop/inc/dp_misc.h @@ -69,8 +69,8 @@ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString makeURL( /** appends a relative path to a url. - This is the same as makeURL, but the relative Path must me a segment - of an system path. + This is the same as makeURL, but the relative Path must be a segment + of a system path. */ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString makeURLAppendSysPathSegment( std::u16string_view baseURL, OUString const & relPath ); diff --git a/desktop/inc/initjsunoscripting.hxx b/desktop/inc/initjsunoscripting.hxx index ccfe9fd1d5fa..21039eea4024 100644 --- a/desktop/inc/initjsunoscripting.hxx +++ b/desktop/inc/initjsunoscripting.hxx @@ -11,7 +11,7 @@ #include -#if defined EMSCRIPTEN +#if defined __EMSCRIPTEN__ void initJsUnoScripting(); diff --git a/desktop/inc/pch/precompiled_deploymentgui.hxx b/desktop/inc/pch/precompiled_deploymentgui.hxx index d3a283bca842..6c37d1febca2 100644 --- a/desktop/inc/pch/precompiled_deploymentgui.hxx +++ b/desktop/inc/pch/precompiled_deploymentgui.hxx @@ -60,7 +60,6 @@ #include #include #include -#include #endif // PCH_LEVEL >= 2 #if PCH_LEVEL >= 3 #include diff --git a/desktop/qa/data/empty.ods b/desktop/qa/data/empty.ods deleted file mode 100644 index 8d9e14cf449c..000000000000 Binary files a/desktop/qa/data/empty.ods and /dev/null differ diff --git a/desktop/qa/data/formulabar.ods b/desktop/qa/data/formulabar.ods deleted file mode 100644 index ea099e24077c..000000000000 Binary files a/desktop/qa/data/formulabar.ods and /dev/null differ diff --git a/desktop/qa/data/three-changes.fodt b/desktop/qa/data/three-changes.fodt deleted file mode 100644 index 0c7072b244a0..000000000000 --- a/desktop/qa/data/three-changes.fodt +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - Mike - 2025-06-16T14:08:27 - - - - - - - Mike - 2025-06-17T12:41:00 - - - - - - - Mike - 2025-06-17T12:41:19 - - - - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum consequat mi quis pretium semper. Proin luctus orci ac neque venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis cursus egestas. Donec blandit auctor arcu, nec pellentesque eros molestie eget. In consectetur aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est orci. Sapienti sat. - - - \ No newline at end of file diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 142427b58ebe..ac6cacec276f 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -149,9 +149,6 @@ public: void testGetFilterTypes(); void testGetPartPageRectangles(); void testSearchCalc(); - void testPropertySettingOnFormulaBar(); - void testSearchTermReset(); - void testFormulaBarAcceptButton(); void testSearchAllNotificationsCalc(); void testPaintTile(); void testSaveAs(); @@ -192,9 +189,6 @@ public: void testCommentsImpress(); void testCommentsCallbacksWriter(); void testCommentsAddEditDeleteDraw(); - void testCommentsInReadOnlyMode(); - void testRedlinesInReadOnlyMode(); - void testCalcValidityDropdown(); void testCalcValidityDropdownInReadonlyMode(); void testRunMacro(); void testExtractParameter(); @@ -219,7 +213,6 @@ public: void testRenderSearchResult_CommonNode(); void testNoDuplicateTableSelection(); void testMultiViewTableSelection(); - void testColorPaletteCallback(); void testABI(); CPPUNIT_TEST_SUITE(DesktopLOKTest); @@ -229,9 +222,6 @@ public: CPPUNIT_TEST(testGetFilterTypes); CPPUNIT_TEST(testGetPartPageRectangles); CPPUNIT_TEST(testSearchCalc); - CPPUNIT_TEST(testPropertySettingOnFormulaBar); - CPPUNIT_TEST(testSearchTermReset); - CPPUNIT_TEST(testFormulaBarAcceptButton); CPPUNIT_TEST(testSearchAllNotificationsCalc); CPPUNIT_TEST(testPaintTile); CPPUNIT_TEST(testSaveAs); @@ -272,9 +262,6 @@ public: CPPUNIT_TEST(testCommentsImpress); CPPUNIT_TEST(testCommentsCallbacksWriter); CPPUNIT_TEST(testCommentsAddEditDeleteDraw); - CPPUNIT_TEST(testCommentsInReadOnlyMode); - CPPUNIT_TEST(testRedlinesInReadOnlyMode); - CPPUNIT_TEST(testCalcValidityDropdown); CPPUNIT_TEST(testCalcValidityDropdownInReadonlyMode); CPPUNIT_TEST(testRunMacro); CPPUNIT_TEST(testExtractParameter); @@ -301,7 +288,6 @@ public: CPPUNIT_TEST(testRenderSearchResult_CommonNode); CPPUNIT_TEST(testNoDuplicateTableSelection); CPPUNIT_TEST(testMultiViewTableSelection); - CPPUNIT_TEST(testColorPaletteCallback); CPPUNIT_TEST(testABI); CPPUNIT_TEST_SUITE_END(); @@ -706,7 +692,7 @@ void DesktopLOKTest::testSaveAsJsonOptions() // Then make sure the resulting PDF has 2 pages: std::unique_ptr pPdfDocument - = parsePDFExport(); + = parsePDFExport(pPDFium); // Without the accompanying fix in place, this test would have failed with: // - Expected: 2 // - Actual : 3 @@ -2230,49 +2216,6 @@ void DesktopLOKTest::testRedlineCalc() namespace { -struct RedlineInfo -{ - std::string action; - std::string index; - std::string author; - std::string type; - std::string comment; - std::string description; - std::string dateTime; -}; - -std::vector getRedlineInfo(const boost::property_tree::ptree& redlineNode) -{ - std::vector result; - result.reserve(redlineNode.size()); - for (const auto& redline : redlineNode) - { - result.emplace_back(); - result.back().index = redline.second.get("index"); - result.back().author = redline.second.get("author"); - result.back().type = redline.second.get("type"); - result.back().comment = redline.second.get("comment"); - result.back().description = redline.second.get("description"); - result.back().dateTime = redline.second.get("dateTime"); - if (auto oAction = redline.second.get_optional("action")) - result.back().action = *oAction; - } - - return result; -} - -std::vector getRedlineInfo(LibLODocument_Impl* pDocument) -{ - char* json - = pDocument->m_pDocumentClass->getCommandValues(pDocument, ".uno:AcceptTrackedChanges"); - std::stringstream stream(json); - free(json); - CPPUNIT_ASSERT(!stream.str().empty()); - boost::property_tree::ptree tree; - boost::property_tree::read_json(stream, tree); - return getRedlineInfo(tree.get_child("redlines")); -} - class ViewCallback { LibLODocument_Impl* mpDocument; @@ -2281,17 +2224,12 @@ public: OString m_aCellFormula; boost::property_tree::ptree m_JSONDialog; int m_nTableSelectionCount; - int m_nColorPaletteCallbackCount = 0; bool m_bEmptyTableSelection; bool m_bTilesInvalidated; bool m_bZeroCursor; bool m_stateBold; tools::Rectangle m_aOwnCursor; boost::property_tree::ptree m_aCommentCallbackResult; - boost::property_tree::ptree m_aColorPaletteCallbackResult; - RedlineInfo m_aLastRedlineInfo; - std::string m_searchTerm; - int m_findReplaceDialogId; ViewCallback(LibLODocument_Impl* pDocument) : mpDocument(pDocument), @@ -2361,63 +2299,6 @@ public: ++m_nTableSelectionCount; } break; - case LOK_CALLBACK_COLOR_PALETTES: - { - m_aColorPaletteCallbackResult.clear(); - std::stringstream aStream(pPayload); - boost::property_tree::read_json(aStream, m_aColorPaletteCallbackResult); - ++m_nColorPaletteCallbackCount; - } - break; - case LOK_CALLBACK_WINDOW: - { - m_JSONDialog.clear(); - std::stringstream aStream(pPayload); - boost::property_tree::read_json(aStream, m_JSONDialog); - - if (m_JSONDialog.find("title") != m_JSONDialog.not_found() && m_JSONDialog.get_child("title").get_value() == "Find and Replace") - { - m_findReplaceDialogId = std::atoi(m_JSONDialog.get_child("id").get_value().c_str()); - // Set search term to something random and make sure it is read from incoming JSON (LOK_CALLBACK_JSDIALOG). - m_searchTerm = "something random"; - } - } - break; - case LOK_CALLBACK_JSDIALOG: - { - m_JSONDialog.clear(); - std::stringstream aStream(pPayload); - boost::property_tree::read_json(aStream, m_JSONDialog); - - if (m_JSONDialog.find("jsontype") != m_JSONDialog.not_found() && m_JSONDialog.get_child("jsontype").get_value() == "dialog") - { - if (m_JSONDialog.find("data") != m_JSONDialog.not_found()) - { - if (m_JSONDialog.get_child("data").find("control_id") != m_JSONDialog.get_child("data").not_found()) - { - if (m_JSONDialog.get_child("data").get_child("control_id").get_value() == "searchterm") - { - if (m_JSONDialog.get_child("data").find("text") != m_JSONDialog.get_child("data").not_found()) - { - m_searchTerm = m_JSONDialog.get_child("data").get_child("text").get_value(); - } - } - } - } - } - } - break; - case LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED: - case LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED: - { - std::stringstream aStream(pPayload); - boost::property_tree::ptree tree; - boost::property_tree::read_json(aStream, tree); - auto redlines = getRedlineInfo(tree); - CPPUNIT_ASSERT_EQUAL(size_t(1), redlines.size()); - m_aLastRedlineInfo = redlines[0]; - } - break; case LOK_CALLBACK_STATE_CHANGED: { if (aPayload.startsWith(".uno:Bold=")) @@ -2650,7 +2531,7 @@ void DesktopLOKTest::testCommentsWriter() tools::Long nWidth, nHeight; pDocument->m_pDocumentClass->getDocumentSize(pDocument, &nWidth, &nHeight); - // Document width alongwith without sidebar comes to be < 13000 + // Document width without sidebar comes to be < 13000 CPPUNIT_ASSERT( nWidth < 13000 ); // Can we get all the comments using .uno:ViewAnnotations command ? @@ -2799,7 +2680,7 @@ void DesktopLOKTest::testCommentsImpress() void DesktopLOKTest::testCommentsCallbacksWriter() { - // Comments callback are emitted only if tiled annotations are off + // Comment callbacks are emitted only if tiled annotations are off comphelper::LibreOfficeKit::setTiledAnnotations(false); LibLODocument_Impl* pDocument = loadDoc("comments.odt"); pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); @@ -2903,7 +2784,7 @@ void addParameter(tools::JsonWriter& rJson, const char* sName, std::string_view void DesktopLOKTest::testCommentsAddEditDeleteDraw() { - // Comments callback are emitted only if tiled annotations are off + // Comment callbacks are emitted only if tiled annotations are off comphelper::LibreOfficeKit::setTiledAnnotations(false); LibLODocument_Impl* pDocument = loadDoc("BlankDrawDocument.odg"); pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); @@ -2954,210 +2835,6 @@ void DesktopLOKTest::testCommentsAddEditDeleteDraw() CPPUNIT_ASSERT_EQUAL(nCommentId1, aView1.m_aCommentCallbackResult.get("id")); } -void DesktopLOKTest::testCommentsInReadOnlyMode() -{ - // Comments callback are emitted only if tiled annotations are off - comphelper::LibreOfficeKit::setTiledAnnotations(false); - LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - - int viewId = pDocument->m_pDocumentClass->createView(pDocument); - pDocument->m_pDocumentClass->setView(pDocument, viewId); - - pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{\".uno:Author\":{\"type\":\"string\",\"value\":\"LOK User1\"}}"); - - SfxLokHelper::setViewReadOnly(viewId, true); - SfxLokHelper::setAllowChangeComments(viewId, true); - - Scheduler::ProcessEventsToIdle(); - - ViewCallback aView(pDocument); - - // Add a new comment - OString aCommandArgs; - { - tools::JsonWriter aJson; - addParameter(aJson, "Text", "string", "Comment"); - addParameter(aJson, "Author", "string", "LOK User1"); - aCommandArgs = aJson.finishAndGetAsOString(); - } - - pDocument->pClass->postUnoCommand(pDocument, ".uno:InsertAnnotation", aCommandArgs.getStr(), false); - Scheduler::ProcessEventsToIdle(); - - // We received a LOK_CALLBACK_COMMENT callback with comment 'Add' action - CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView.m_aCommentCallbackResult.get("action")); - int nCommentId = aView.m_aCommentCallbackResult.get("id"); - - // Edit the previously added comment - { - tools::JsonWriter aJson; - addParameter(aJson, "Id", "string", OString::number(nCommentId)); - addParameter(aJson, "Text", "string", "Edited comment"); - aCommandArgs = aJson.finishAndGetAsOString(); - } - - pDocument->pClass->postUnoCommand(pDocument, ".uno:EditAnnotation", aCommandArgs.getStr(), false); - Scheduler::ProcessEventsToIdle(); - - // We received a LOK_CALLBACK_COMMENT callback with comment 'Modify' action - CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView.m_aCommentCallbackResult.get("action")); - CPPUNIT_ASSERT_EQUAL(nCommentId, aView.m_aCommentCallbackResult.get("id")); - - // Delete Comment - { - tools::JsonWriter aJson; - addParameter(aJson, "Id", "string", OString::number(nCommentId)); - aCommandArgs = aJson.finishAndGetAsOString(); - } - pDocument->pClass->postUnoCommand(pDocument, ".uno:DeleteAnnotation", aCommandArgs.getStr(), false); - Scheduler::ProcessEventsToIdle(); - - // Result is not sent for delete operation for some reason. But it is sent when debugging with online. - // TODO: Enable below 2 checks. - - // We received a LOK_CALLBACK_COMMENT callback with comment 'Remove' action - //CPPUNIT_ASSERT_EQUAL(std::string("Remove"), aView.m_aCommentCallbackResult.get("action")); - //CPPUNIT_ASSERT_EQUAL(nCommentId, aView.m_aCommentCallbackResult.get("id")); -} - -void DesktopLOKTest::testRedlinesInReadOnlyMode() -{ - // In AllowManageRedlines mode, it must be possible to perform redline editing commands, - // even in read-only mode. - - using namespace std::string_literals; - - LibLODocument_Impl* pDocument = loadDoc("three-changes.fodt"); - - int viewId = pDocument->m_pDocumentClass->createView(pDocument); - pDocument->m_pDocumentClass->setView(pDocument, viewId); - pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); - ViewCallback aCallback(pDocument); - Scheduler::ProcessEventsToIdle(); - - CPPUNIT_ASSERT_EQUAL(size_t(3), getRedlineInfo(pDocument).size()); - - // Activate read-only mode - SfxLokHelper::setViewReadOnly(viewId, true); - - // Go to the 1st tracked change: "Delete “Donec”" - pDocument->pClass->postUnoCommand(pDocument, ".uno:NextTrackedChange", {}, false); - Scheduler::ProcessEventsToIdle(); - - // Check that redline management commands don't work in pure read-only - // Try to reject current redline - pDocument->pClass->postUnoCommand(pDocument, ".uno:RejectTrackedChange", {}, false); - Scheduler::ProcessEventsToIdle(); - // Nothing happened - CPPUNIT_ASSERT_EQUAL(size_t(3), getRedlineInfo(pDocument).size()); - CPPUNIT_ASSERT_EQUAL(""s, aCallback.m_aLastRedlineInfo.action); - CPPUNIT_ASSERT_EQUAL(""s, aCallback.m_aLastRedlineInfo.author); - CPPUNIT_ASSERT_EQUAL(""s, aCallback.m_aLastRedlineInfo.type); - CPPUNIT_ASSERT_EQUAL(""s, aCallback.m_aLastRedlineInfo.comment); - CPPUNIT_ASSERT_EQUAL(""s, aCallback.m_aLastRedlineInfo.description); - CPPUNIT_ASSERT_EQUAL(""s, aCallback.m_aLastRedlineInfo.dateTime); - - // Activate the AllowManageRedlines mode - SfxLokHelper::setAllowManageRedlines(viewId, true); - - // Try to reject current redline - pDocument->pClass->postUnoCommand(pDocument, ".uno:RejectTrackedChange", {}, false); - Scheduler::ProcessEventsToIdle(); - // One change gone; it is recorded "Remove"d in aCallback.m_aLastRedlineInfo - CPPUNIT_ASSERT_EQUAL(size_t(2), getRedlineInfo(pDocument).size()); - CPPUNIT_ASSERT_EQUAL("Remove"s, aCallback.m_aLastRedlineInfo.action); - CPPUNIT_ASSERT_EQUAL("Mike"s, aCallback.m_aLastRedlineInfo.author); - CPPUNIT_ASSERT_EQUAL("Delete"s, aCallback.m_aLastRedlineInfo.type); - CPPUNIT_ASSERT_EQUAL(""s, aCallback.m_aLastRedlineInfo.comment); - CPPUNIT_ASSERT_EQUAL("Delete “Donec”"s, aCallback.m_aLastRedlineInfo.description); - CPPUNIT_ASSERT_EQUAL("2025-06-16T14:08:27"s, aCallback.m_aLastRedlineInfo.dateTime); - - // Go to the 2nd tracked change: "Attributes changed" - pDocument->pClass->postUnoCommand(pDocument, ".uno:NextTrackedChange", {}, false); - Scheduler::ProcessEventsToIdle(); - - // Comment on it - pDocument->pClass->postUnoCommand(pDocument, ".uno:CommentChangeTracking", - R"({"Text":{"type":"string","value":"Some comment"}})", - false); - Scheduler::ProcessEventsToIdle(); - // One change got a comment; it is recorded "Modify"ed in aCallback.m_aLastRedlineInfo - CPPUNIT_ASSERT_EQUAL(size_t(2), getRedlineInfo(pDocument).size()); - CPPUNIT_ASSERT_EQUAL("Modify"s, aCallback.m_aLastRedlineInfo.action); - CPPUNIT_ASSERT_EQUAL("Mike"s, aCallback.m_aLastRedlineInfo.author); - CPPUNIT_ASSERT_EQUAL("Format"s, aCallback.m_aLastRedlineInfo.type); - CPPUNIT_ASSERT_EQUAL("Some comment"s, aCallback.m_aLastRedlineInfo.comment); - CPPUNIT_ASSERT_EQUAL("Attributes changed"s, aCallback.m_aLastRedlineInfo.description); - CPPUNIT_ASSERT_EQUAL("2025-06-17T12:41:00"s, aCallback.m_aLastRedlineInfo.dateTime); - - // Go to the 3rd tracked change: "Insert “ Sapienti sat.”" - pDocument->pClass->postUnoCommand(pDocument, ".uno:NextTrackedChange", {}, false); - Scheduler::ProcessEventsToIdle(); - - // Accept it - pDocument->pClass->postUnoCommand(pDocument, ".uno:AcceptTrackedChange", {}, false); - Scheduler::ProcessEventsToIdle(); - // One change gone; it is recorded "Remove"d in aCallback.m_aLastRedlineInfo - CPPUNIT_ASSERT_EQUAL(size_t(1), getRedlineInfo(pDocument).size()); - CPPUNIT_ASSERT_EQUAL("Remove"s, aCallback.m_aLastRedlineInfo.action); - CPPUNIT_ASSERT_EQUAL("Mike"s, aCallback.m_aLastRedlineInfo.author); - CPPUNIT_ASSERT_EQUAL("Insert"s, aCallback.m_aLastRedlineInfo.type); - CPPUNIT_ASSERT_EQUAL(""s, aCallback.m_aLastRedlineInfo.comment); - CPPUNIT_ASSERT_EQUAL("Insert “ Sapienti sat.”"s, aCallback.m_aLastRedlineInfo.description); - CPPUNIT_ASSERT_EQUAL("2025-06-17T12:41:19"s, aCallback.m_aLastRedlineInfo.dateTime); - - // Make sure that another (unrelated to redline management) editing command is not working - pDocument->pClass->postUnoCommand(pDocument, ".uno:InsertAnnotation", - R"({"Text":{"type":"string","value":"Comment"}})", - false); - Scheduler::ProcessEventsToIdle(); - CPPUNIT_ASSERT(aCallback.m_aCommentCallbackResult.empty()); - - // Check that the same command would succeed in AllowChangeComments mode - SfxLokHelper::setAllowChangeComments(viewId, true); - pDocument->pClass->postUnoCommand(pDocument, ".uno:InsertAnnotation", - R"({"Text":{"type":"string","value":"Comment"}})", - false); - Scheduler::ProcessEventsToIdle(); - CPPUNIT_ASSERT(!aCallback.m_aCommentCallbackResult.empty()); -} - -void DesktopLOKTest::testCalcValidityDropdown() -{ - LibLODocument_Impl* pDocument = loadDoc("validity.ods"); - Scheduler::ProcessEventsToIdle(); - pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); - Scheduler::ProcessEventsToIdle(); - - ViewCallback aView(pDocument); - Scheduler::ProcessEventsToIdle(); - - // Select row 1 from column 1. - pDocument->pClass->postMouseEvent(pDocument, LOK_MOUSEEVENT_MOUSEBUTTONDOWN, 1000, 150, 1, 1, 0); - Scheduler::ProcessEventsToIdle(); - pDocument->pClass->postMouseEvent(pDocument, LOK_MOUSEEVENT_MOUSEBUTTONUP, 1000, 150, 1, 1, 0); - Scheduler::ProcessEventsToIdle(); - - // Open dropdown. - pDocument->pClass->postMouseEvent(pDocument, LOK_MOUSEEVENT_MOUSEBUTTONDOWN, 1380, 150, 1, 1, 0); - Scheduler::ProcessEventsToIdle(); - pDocument->pClass->postMouseEvent(pDocument, LOK_MOUSEEVENT_MOUSEBUTTONUP, 1380, 150, 1, 1, 0); - Scheduler::ProcessEventsToIdle(); - - // Select some value from dropdown. - pDocument->pClass->sendDialogEvent(pDocument, aView.m_JSONDialog.get_child("id").get_value(), "{\"id\":\"list\", \"cmd\": \"select\", \"data\": \"3\", \"type\": \"treeview\"}"); - Scheduler::ProcessEventsToIdle(); - - // Activate the selected value. - pDocument->pClass->sendDialogEvent(pDocument, aView.m_JSONDialog.get_child("id").get_value(), "{\"id\":\"list\", \"cmd\": \"activate\", \"data\": \"3\", \"type\": \"treeview\"}"); - Scheduler::ProcessEventsToIdle(); - - // Check the content of the current cell. The selected value of the dropdown was 1. It should be 4 now. - char* pCellContent = pDocument->pClass->getTextSelection(pDocument, "text/plain;charset=utf-8", nullptr); - CPPUNIT_ASSERT_EQUAL("4"_ostr, OString(pCellContent)); - free(pCellContent); -} - void DesktopLOKTest::testCalcValidityDropdownInReadonlyMode() { LibLODocument_Impl* pDocument = loadDoc("validity.ods"); @@ -3188,128 +2865,6 @@ void DesktopLOKTest::testCalcValidityDropdownInReadonlyMode() CPPUNIT_ASSERT_EQUAL(true, aView.m_JSONDialog.empty()); } -void DesktopLOKTest::testPropertySettingOnFormulaBar() -{ - LibLibreOffice_Impl aOffice; - LibLODocument_Impl* pDocument = loadDoc("formulabar.ods"); - Scheduler::ProcessEventsToIdle(); - - pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); - Scheduler::ProcessEventsToIdle(); - - ViewCallback aView(pDocument); - Scheduler::ProcessEventsToIdle(); - - // Go to A1. There are 2 words in the cell. - pDocument->pClass->postMouseEvent(pDocument, LOK_MOUSEEVENT_MOUSEBUTTONDOWN, 1000, 150, 1, 1, 0); - pDocument->pClass->postMouseEvent(pDocument, LOK_MOUSEEVENT_MOUSEBUTTONUP, 1000, 150, 1, 1, 0); - Scheduler::ProcessEventsToIdle(); - - // Set the focus to formulabar. - pDocument->pClass->sendDialogEvent(pDocument, 0, "{\"id\":\"sc_input_window\", \"cmd\": \"grab_focus\", \"data\": \"null\", \"type\": \"drawingarea\"}"); - Scheduler::ProcessEventsToIdle(); - - // Select the first word. - pDocument->pClass->sendDialogEvent(pDocument, 0, "{\"id\":\"sc_input_window\", \"cmd\": \"textselection\", \"data\": \"0;3;0;0\", \"type\": \"drawingarea\"}"); - Scheduler::ProcessEventsToIdle(); - - // Set bold property for the selected word. - pDocument->pClass->postUnoCommand(pDocument, ".uno:Bold", nullptr, false); - Scheduler::ProcessEventsToIdle(); - - CPPUNIT_ASSERT_EQUAL(true, aView.m_stateBold); - - // Select the second word. Without the fix, this selection removes the "bold" attribute. - pDocument->pClass->sendDialogEvent(pDocument, 0, "{\"id\":\"sc_input_window\", \"cmd\": \"textselection\", \"data\": \"4;9;0;0\", \"type\": \"drawingarea\"}"); - Scheduler::ProcessEventsToIdle(); - - // Select the first word again. - pDocument->pClass->sendDialogEvent(pDocument, 0, "{\"id\":\"sc_input_window\", \"cmd\": \"textselection\", \"data\": \"0;3;0;0\", \"type\": \"drawingarea\"}"); - Scheduler::ProcessEventsToIdle(); - - // Unset bold property for the selected word. - pDocument->pClass->postUnoCommand(pDocument, ".uno:Bold", nullptr, false); - Scheduler::ProcessEventsToIdle(); - - CPPUNIT_ASSERT_EQUAL(false, aView.m_stateBold); // This line doesn't pass without the fix in this commit. -} - -void DesktopLOKTest::testSearchTermReset() -{ - LibLibreOffice_Impl aOffice; - LibLODocument_Impl* pDocument = loadDoc("empty.ods"); - Scheduler::ProcessEventsToIdle(); - - pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); - Scheduler::ProcessEventsToIdle(); - - ViewCallback aView(pDocument); - Scheduler::ProcessEventsToIdle(); - - pDocument->pClass->postUnoCommand(pDocument, ".uno:SearchDialog", nullptr, false); - Scheduler::ProcessEventsToIdle(); - - // Send "something" as current search string (searchterm). - pDocument->pClass->sendDialogEvent(pDocument, aView.m_findReplaceDialogId, "{\"id\":\"searchterm\", \"cmd\": \"change\", \"data\": \"something\", \"type\": \"combobox\"}"); - Scheduler::ProcessEventsToIdle(); - - // Press search button. - pDocument->pClass->sendDialogEvent(pDocument, aView.m_findReplaceDialogId, "{\"id\":\"search\", \"cmd\": \"click\", \"data\": \"undefined\", \"type\": \"pushbutton\"}"); - Scheduler::ProcessEventsToIdle(); - - // Close the dialog. - pDocument->pClass->sendDialogEvent(pDocument, aView.m_findReplaceDialogId, "{\"id\":\"__DIALOG__\", \"cmd\": \"close\", \"data\": \"null\", \"type\": \"dialog\"}"); - Scheduler::ProcessEventsToIdle(); - - // Reopen search dialog. - pDocument->pClass->postUnoCommand(pDocument, ".uno:SearchDialog", nullptr, false); - Scheduler::ProcessEventsToIdle(); - - // We should have got the "searchterm" again. It should be empty. Below line doesn't pass without the changes in this commit. - CPPUNIT_ASSERT_EQUAL(std::string(""), aView.m_searchTerm); -} - -void DesktopLOKTest::testFormulaBarAcceptButton() -{ - LibLibreOffice_Impl aOffice; - LibLODocument_Impl* pDocument = loadDoc("empty.ods"); - Scheduler::ProcessEventsToIdle(); - - pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); - Scheduler::ProcessEventsToIdle(); - - ViewCallback aView(pDocument); - Scheduler::ProcessEventsToIdle(); - - // Go to A1. - pDocument->pClass->postMouseEvent(pDocument, LOK_MOUSEEVENT_MOUSEBUTTONDOWN, 1000, 150, 1, 1, 0); - pDocument->pClass->postMouseEvent(pDocument, LOK_MOUSEEVENT_MOUSEBUTTONUP, 1000, 150, 1, 1, 0); - Scheduler::ProcessEventsToIdle(); - - // Set the focus to formulabar. - pDocument->pClass->sendDialogEvent(pDocument, 0, "{\"id\":\"sc_input_window\", \"cmd\": \"grab_focus\", \"data\": \"null\", \"type\": \"drawingarea\"}"); - Scheduler::ProcessEventsToIdle(); - - // Set selection (nothing selected). - pDocument->pClass->sendDialogEvent(pDocument, 0, "{\"id\":\"sc_input_window\", \"cmd\": \"textselection\", \"data\": \"0;0;0;0\", \"type\": \"drawingarea\"}"); - Scheduler::ProcessEventsToIdle(); - - // Set text. - pDocument->pClass->postWindowExtTextInputEvent(pDocument, 0, LOK_EXT_TEXTINPUT, "H"); - pDocument->pClass->postWindowExtTextInputEvent(pDocument, 0, LOK_EXT_TEXTINPUT_END, "H"); - Scheduler::ProcessEventsToIdle(); - - aView.m_JSONDialog.clear(); - pDocument->pClass->postUnoCommand(pDocument, ".uno:AcceptFormula", nullptr, false); - Scheduler::ProcessEventsToIdle(); - // Client should have receive a JSDialog event for formulabar by now. - - // These lines don't pass without the fix in this commit. - CPPUNIT_ASSERT_EQUAL(std::string("formulabar"), aView.m_JSONDialog.get_child("jsontype").get_value()); - CPPUNIT_ASSERT_EQUAL(std::string("setText"), aView.m_JSONDialog.get_child("data").get_child("action_type").get_value()); - CPPUNIT_ASSERT_EQUAL(std::string("sc_input_window"), aView.m_JSONDialog.get_child("data").get_child("control_id").get_value()); -} - void DesktopLOKTest::testRunMacro() { LibLibreOffice_Impl aOffice; @@ -4167,34 +3722,6 @@ void DesktopLOKTest::testMultiViewTableSelection() CPPUNIT_ASSERT(!aView1.m_bEmptyTableSelection); } -void DesktopLOKTest::testColorPaletteCallback() -{ - LibLODocument_Impl* pDocument = loadDoc("ThemeDocument.docx"); - - // Create view 1. - pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); - ViewCallback aView1(pDocument); - Scheduler::ProcessEventsToIdle(); - { - CPPUNIT_ASSERT_EQUAL(1, aView1.m_nColorPaletteCallbackCount); - boost::property_tree::ptree aValues = aView1.m_aColorPaletteCallbackResult.get_child("ThemeColors"); - CPPUNIT_ASSERT(!aValues.empty()); - CPPUNIT_ASSERT_EQUAL(size_t(6), aValues.size()); - } - - // Create view 2. - pDocument->m_pDocumentClass->createView(pDocument); - pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); - ViewCallback aView2(pDocument); - Scheduler::ProcessEventsToIdle(); - { - CPPUNIT_ASSERT_EQUAL(1, aView2.m_nColorPaletteCallbackCount); - boost::property_tree::ptree aValues = aView1.m_aColorPaletteCallbackResult.get_child("ThemeColors"); - CPPUNIT_ASSERT(!aValues.empty()); - CPPUNIT_ASSERT_EQUAL(size_t(6), aValues.size()); - } -} - namespace { constexpr size_t classOffset(int i) @@ -4225,24 +3752,23 @@ void DesktopLOKTest::testABI() CPPUNIT_ASSERT_EQUAL(classOffset(10), offsetof(LibreOfficeKitClass, runMacro)); CPPUNIT_ASSERT_EQUAL(classOffset(11), offsetof(LibreOfficeKitClass, signDocument)); CPPUNIT_ASSERT_EQUAL(classOffset(12), offsetof(LibreOfficeKitClass, runLoop)); - CPPUNIT_ASSERT_EQUAL(classOffset(13), offsetof(LibreOfficeKitClass, sendDialogEvent)); - CPPUNIT_ASSERT_EQUAL(classOffset(14), offsetof(LibreOfficeKitClass, setOption)); - CPPUNIT_ASSERT_EQUAL(classOffset(15), offsetof(LibreOfficeKitClass, dumpState)); - CPPUNIT_ASSERT_EQUAL(classOffset(16), offsetof(LibreOfficeKitClass, extractRequest)); - CPPUNIT_ASSERT_EQUAL(classOffset(17), offsetof(LibreOfficeKitClass, trimMemory)); - CPPUNIT_ASSERT_EQUAL(classOffset(18), offsetof(LibreOfficeKitClass, startURP)); - CPPUNIT_ASSERT_EQUAL(classOffset(19), offsetof(LibreOfficeKitClass, stopURP)); - CPPUNIT_ASSERT_EQUAL(classOffset(20), offsetof(LibreOfficeKitClass, joinThreads)); - CPPUNIT_ASSERT_EQUAL(classOffset(21), offsetof(LibreOfficeKitClass, startThreads)); - CPPUNIT_ASSERT_EQUAL(classOffset(22), offsetof(LibreOfficeKitClass, setForkedChild)); - CPPUNIT_ASSERT_EQUAL(classOffset(23), offsetof(LibreOfficeKitClass, extractDocumentStructureRequest)); - CPPUNIT_ASSERT_EQUAL(classOffset(24), offsetof(LibreOfficeKitClass, registerAnyInputCallback)); - CPPUNIT_ASSERT_EQUAL(classOffset(25), offsetof(LibreOfficeKitClass, getDocsCount)); - CPPUNIT_ASSERT_EQUAL(classOffset(26), offsetof(LibreOfficeKitClass, registerFileSaveDialogCallback)); + CPPUNIT_ASSERT_EQUAL(classOffset(13), offsetof(LibreOfficeKitClass, setOption)); + CPPUNIT_ASSERT_EQUAL(classOffset(14), offsetof(LibreOfficeKitClass, dumpState)); + CPPUNIT_ASSERT_EQUAL(classOffset(15), offsetof(LibreOfficeKitClass, extractRequest)); + CPPUNIT_ASSERT_EQUAL(classOffset(16), offsetof(LibreOfficeKitClass, trimMemory)); + CPPUNIT_ASSERT_EQUAL(classOffset(17), offsetof(LibreOfficeKitClass, startURP)); + CPPUNIT_ASSERT_EQUAL(classOffset(18), offsetof(LibreOfficeKitClass, stopURP)); + CPPUNIT_ASSERT_EQUAL(classOffset(19), offsetof(LibreOfficeKitClass, joinThreads)); + CPPUNIT_ASSERT_EQUAL(classOffset(20), offsetof(LibreOfficeKitClass, startThreads)); + CPPUNIT_ASSERT_EQUAL(classOffset(21), offsetof(LibreOfficeKitClass, setForkedChild)); + CPPUNIT_ASSERT_EQUAL(classOffset(22), offsetof(LibreOfficeKitClass, extractDocumentStructureRequest)); + CPPUNIT_ASSERT_EQUAL(classOffset(23), offsetof(LibreOfficeKitClass, registerAnyInputCallback)); + CPPUNIT_ASSERT_EQUAL(classOffset(24), offsetof(LibreOfficeKitClass, getDocsCount)); + CPPUNIT_ASSERT_EQUAL(classOffset(25), offsetof(LibreOfficeKitClass, registerFileSaveDialogCallback)); - // When extending LibreOfficeKit with a new function pointer, add new assert for the offsetof the + // When extending LibreOfficeKit with a new function pointer, add new assert for the offsetof the // new function pointer and bump this assert for the size of the class. - CPPUNIT_ASSERT_EQUAL(classOffset(27), sizeof(LibreOfficeKitClass)); + CPPUNIT_ASSERT_EQUAL(classOffset(26), sizeof(LibreOfficeKitClass)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(0), offsetof(LibreOfficeKitDocumentClass, destroy)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(1), offsetof(LibreOfficeKitDocumentClass, saveAs)); @@ -4305,34 +3831,31 @@ void DesktopLOKTest::testABI() CPPUNIT_ASSERT_EQUAL(documentClassOffset(53), offsetof(LibreOfficeKitDocumentClass, setClipboard)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(54), offsetof(LibreOfficeKitDocumentClass, getSelectionType)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(55), offsetof(LibreOfficeKitDocumentClass, removeTextContext)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(56), offsetof(LibreOfficeKitDocumentClass, sendDialogEvent)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(57), offsetof(LibreOfficeKitDocumentClass, renderFontOrientation)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(58), offsetof(LibreOfficeKitDocumentClass, paintWindowForView)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(59), offsetof(LibreOfficeKitDocumentClass, completeFunction)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(60), offsetof(LibreOfficeKitDocumentClass, setWindowTextSelection)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(61), offsetof(LibreOfficeKitDocumentClass, sendFormFieldEvent)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(62), offsetof(LibreOfficeKitDocumentClass, setBlockedCommandList)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(63), offsetof(LibreOfficeKitDocumentClass, renderSearchResult)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(64), offsetof(LibreOfficeKitDocumentClass, sendContentControlEvent)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(65), offsetof(LibreOfficeKitDocumentClass, getSelectionTypeAndText)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(66), offsetof(LibreOfficeKitDocumentClass, getDataArea)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(67), offsetof(LibreOfficeKitDocumentClass, getEditMode)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(68), offsetof(LibreOfficeKitDocumentClass, setViewTimezone)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(69), offsetof(LibreOfficeKitDocumentClass, setAccessibilityState)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(70), offsetof(LibreOfficeKitDocumentClass, getA11yFocusedParagraph)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(71), offsetof(LibreOfficeKitDocumentClass, getA11yCaretPosition)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(72), offsetof(LibreOfficeKitDocumentClass, setViewReadOnly)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(73), offsetof(LibreOfficeKitDocumentClass, setAllowChangeComments)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(74), offsetof(LibreOfficeKitDocumentClass, getPresentationInfo)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(75), offsetof(LibreOfficeKitDocumentClass, createSlideRenderer)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(76), offsetof(LibreOfficeKitDocumentClass, postSlideshowCleanup)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(77), offsetof(LibreOfficeKitDocumentClass, renderNextSlideLayer)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(78), offsetof(LibreOfficeKitDocumentClass, setViewOption)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(79), offsetof(LibreOfficeKitDocumentClass, setColorPreviewState)); - CPPUNIT_ASSERT_EQUAL(documentClassOffset(80), offsetof(LibreOfficeKitDocumentClass, setAllowManageRedlines)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(56), offsetof(LibreOfficeKitDocumentClass, renderFontOrientation)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(57), offsetof(LibreOfficeKitDocumentClass, paintWindowForView)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(58), offsetof(LibreOfficeKitDocumentClass, completeFunction)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(59), offsetof(LibreOfficeKitDocumentClass, setWindowTextSelection)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(60), offsetof(LibreOfficeKitDocumentClass, sendFormFieldEvent)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(61), offsetof(LibreOfficeKitDocumentClass, setBlockedCommandList)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(62), offsetof(LibreOfficeKitDocumentClass, renderSearchResult)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(63), offsetof(LibreOfficeKitDocumentClass, sendContentControlEvent)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(64), offsetof(LibreOfficeKitDocumentClass, getSelectionTypeAndText)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(65), offsetof(LibreOfficeKitDocumentClass, getDataArea)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(66), offsetof(LibreOfficeKitDocumentClass, getEditMode)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(67), offsetof(LibreOfficeKitDocumentClass, setViewTimezone)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(68), offsetof(LibreOfficeKitDocumentClass, setAccessibilityState)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(69), offsetof(LibreOfficeKitDocumentClass, getA11yFocusedParagraph)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(70), offsetof(LibreOfficeKitDocumentClass, getA11yCaretPosition)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(71), offsetof(LibreOfficeKitDocumentClass, setViewReadOnly)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(72), offsetof(LibreOfficeKitDocumentClass, getPresentationInfo)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(73), offsetof(LibreOfficeKitDocumentClass, createSlideRenderer)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(74), offsetof(LibreOfficeKitDocumentClass, postSlideshowCleanup)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(75), offsetof(LibreOfficeKitDocumentClass, renderNextSlideLayer)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(76), offsetof(LibreOfficeKitDocumentClass, setViewOption)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(77), offsetof(LibreOfficeKitDocumentClass, setColorPreviewState)); // As above - CPPUNIT_ASSERT_EQUAL(documentClassOffset(81), sizeof(LibreOfficeKitDocumentClass)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(78), sizeof(LibreOfficeKitDocumentClass)); } CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest); diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index f02498623eb1..0c1b919f3beb 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -111,7 +111,6 @@ #include #include #include -#include #include #include #include @@ -358,7 +357,7 @@ void RemoveIconCacheDirectory() namespace { -#if defined(DBG_UTIL) && !defined(EMSCRIPTEN) +#if defined(DBG_UTIL) && !defined(__EMSCRIPTEN__) void runGraphicsRenderTests() { if (comphelper::LibreOfficeKit::isActive()) @@ -484,9 +483,9 @@ void Desktop::Init() std::abort(); } - // Check whether safe mode is enabled + // Check whether troubleshoot mode is enabled const CommandLineArgs& rCmdLineArgs = GetCommandLineArgs(); - // Check if we are restarting from safe mode - in that case we don't want to enter it again + // Check if we are restarting from troubleshoot mode - in that case we don't want to enter it again if (sfx2::SafeMode::hasRestartFlag()) sfx2::SafeMode::removeRestartFlag(); else if (rCmdLineArgs.IsSafeMode() || sfx2::SafeMode::hasFlag()) @@ -532,7 +531,7 @@ void Desktop::Init() RequestHandler::Status aStatus = RequestHandler::Enable(true); if ( aStatus == RequestHandler::IPC_STATUS_PIPE_ERROR ) { -#if defined(ANDROID) || defined(EMSCRIPTEN) +#if defined(ANDROID) || defined(__EMSCRIPTEN__) // Ignore crack pipe errors on Android #else // Keep using this oddly named BE_PATHINFO_MISSING value @@ -900,7 +899,7 @@ void Desktop::HandleBootstrapErrors( // but end up in a _exit() call comphelper::BackupFileHelper::setExitWasCalled(); - // enter safe mode, too + // enter troubleshoot mode, too sfx2::SafeMode::putFlag(); OUString msg(DpResId(STR_CONFIG_ERR_ACCESS_GENERAL)); @@ -1392,7 +1391,7 @@ int Desktop::Main() recordTime(startT, "SetSplashScreenProgress(25): time = "); -#if HAVE_FEATURE_DESKTOP && !defined(EMSCRIPTEN) +#if HAVE_FEATURE_DESKTOP && !defined(__EMSCRIPTEN__) // check user installation directory for lockfile so we can be sure // there is no other instance using our data files from a remote host @@ -1644,7 +1643,7 @@ int Desktop::Main() CheckOpenCLCompute(xDesktop); #endif -#if defined(DBG_UTIL) && !defined(EMSCRIPTEN) +#if defined(DBG_UTIL) && !defined(__EMSCRIPTEN__) //Running the VCL graphics rendering tests const char * pDisplay = std::getenv("DISPLAY"); if (!pDisplay || pDisplay[0] == ':') @@ -2052,7 +2051,7 @@ void Desktop::OpenClients() bool bAllowRecoveryAndSessionManagement = ( !rArgs.IsNoRestore() ) && ( !rArgs.IsHeadless() ); #if !defined ANDROID - // Enter safe mode if requested + // Enter troubleshoot mode if requested if (Application::IsSafeModeEnabled()) { handleSafeMode(); } @@ -2340,11 +2339,11 @@ OUString GetURL_Impl( return rName; } - // Add path separator to these directory and make given URL (rName) absolute by using of current working directory + // Add path separator to this directory and make given URL (rName) absolute by using current working directory // Attention: "setFinalSlash()" is necessary for calling "smartRel2Abs()"!!! // Otherwise last part will be ignored and wrong result will be returned!!! - // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ... - // But if we add a separator - he doesn't do it anymore. + // "smartRel2Abs()" interpret given URL as file not as path. So it truncates last element to get the base path ... + // But if we add a separator - it doesn't do it anymore. INetURLObject aObj; if (cwdUrl) { aObj.SetURL(*cwdUrl); @@ -2652,7 +2651,7 @@ void Desktop::ShowBackingComponent(Desktop * progress) Reference< XController > xStartModule = StartModule::createWithParentWindow( xContext, xContainerWindow); // Attention: You MUST(!) call setComponent() before you call attachFrame(). // Because the backing component set the property "IsBackingMode" of the frame - // to true inside attachFrame(). But setComponent() reset this state everytimes ... + // to true inside attachFrame(). But setComponent() resets this state every time ... xBackingFrame->setComponent(Reference< XWindow >(xStartModule, UNO_QUERY), xStartModule); if (progress != nullptr) { diff --git a/desktop/source/app/appinit.cxx b/desktop/source/app/appinit.cxx index 8f92acecbb40..c1abcca75cef 100644 --- a/desktop/source/app/appinit.cxx +++ b/desktop/source/app/appinit.cxx @@ -45,7 +45,7 @@ #include #include -#if defined EMSCRIPTEN +#if defined __EMSCRIPTEN__ #include #endif @@ -85,7 +85,7 @@ void Desktop::InitApplicationServiceManager() UNO_QUERY_THROW); #endif comphelper::setProcessServiceFactory(sm); -#if defined EMSCRIPTEN +#if defined __EMSCRIPTEN__ initJsUnoScripting(); #endif } diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx index e5f457fb7539..3b0fb4b853c6 100644 --- a/desktop/source/app/cmdlineargs.cxx +++ b/desktop/source/app/cmdlineargs.cxx @@ -18,6 +18,7 @@ */ #include +#include #if HAVE_FEATURE_MACOSX_SANDBOX #include @@ -625,6 +626,11 @@ void CommandLineArgs::ParseCommandLine_Impl( Supplier& supplier ) #endif //ignore additional legacy options that don't do anything anymore oArg != "nocrashreport" && +#if ENABLE_QT5 || ENABLE_QT6 + // allow style-related command line options natively supported by Qt applications + !oArg.startsWith(u"style=") && + !oArg.startsWith(u"stylesheet=") && +#endif m_unknown.isEmpty()) { m_unknown = aArg; diff --git a/desktop/source/app/cmdlinehelp.cxx b/desktop/source/app/cmdlinehelp.cxx index 02b8e37a2fb1..86ba25793828 100644 --- a/desktop/source/app/cmdlinehelp.cxx +++ b/desktop/source/app/cmdlinehelp.cxx @@ -94,9 +94,9 @@ namespace desktop " when the application is controlled by external clients \n" " via the API. \n" " --norestore Disables restart and file recovery after a system crash.\n" - " --safe-mode Starts in a safe mode, i.e. starts temporarily with a \n" - " fresh user profile and helps to restore a broken \n" - " configuration. \n" + " --safe-mode Runs troubleshoot mode, which temporarily replaces the \n" + " user profile with a fresh one to help diagnose and fix \n" + " a faulty configuration. \n" " --accept={connect-string} Specifies a UNO connect-string to create a UNO \n" " acceptor through which other programs can connect to \n" " access the API. Note that API access allows execution \n" @@ -107,9 +107,8 @@ namespace desktop " or socket,host=localhost,port=54321;urp \n" " --unaccept={connect-string} Closes an acceptor that was created with \n" " --accept. Use --unaccept=all to close all acceptors. \n" - " --language={lang} Uses specified language, if language is not selected \n" - " yet for UI. The lang is a tag of the language in IETF \n" - " language tag. \n\n" + " --language={lang} Overrides the choice of language for the UI. The lang is\n" + " a tag of the language in IETF language tag. \n\n" "Developer arguments: \n" " --terminate_after_init \n" " Exit after initialization complete (no documents loaded)\n" diff --git a/desktop/source/app/initjsunoscripting.cxx b/desktop/source/app/initjsunoscripting.cxx index a6939f838e8c..ec11e725e1f9 100644 --- a/desktop/source/app/initjsunoscripting.cxx +++ b/desktop/source/app/initjsunoscripting.cxx @@ -9,7 +9,7 @@ #include -#if defined EMSCRIPTEN +#if defined __EMSCRIPTEN__ #include #include diff --git a/desktop/source/app/langselect.cxx b/desktop/source/app/langselect.cxx index 702f0a66f224..4babad8075a3 100644 --- a/desktop/source/app/langselect.cxx +++ b/desktop/source/app/langselect.cxx @@ -77,26 +77,26 @@ bool prepareLocale() { setMsLangIdFallback(officecfg::System::L10N::Locale::get()); css::uno::Sequence inst( officecfg::Setup::Office::InstalledLocales::get()->getElementNames()); - OUString locale(officecfg::Office::Linguistic::General::UILocale::get()); - if (!locale.isEmpty()) { - locale = getInstalledLocaleForLanguage(inst, locale); - if (locale.isEmpty()) { - // Selected language is not/no longer installed: - try { - std::shared_ptr batch( - comphelper::ConfigurationChanges::create()); - officecfg::Office::Linguistic::General::UILocale::set( - u""_ustr, batch); - batch->commit(); - } catch (const css::uno::Exception &) { - TOOLS_WARN_EXCEPTION("desktop.app", "ignoring"); + OUString locale = getInstalledLocaleForLanguage( + inst, Desktop::GetCommandLineArgs().GetLanguage()); + if (locale.isEmpty()) { + locale = officecfg::Office::Linguistic::General::UILocale::get(); + if (!locale.isEmpty()) { + locale = getInstalledLocaleForLanguage(inst, locale); + if (locale.isEmpty()) { + // Selected language is not/no longer installed: + try { + std::shared_ptr batch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Linguistic::General::UILocale::set( + u""_ustr, batch); + batch->commit(); + } catch (const css::uno::Exception &) { + TOOLS_WARN_EXCEPTION("desktop.app", "ignoring"); + } } } } - if (locale.isEmpty()) { - locale = getInstalledLocaleForLanguage( - inst, Desktop::GetCommandLineArgs().GetLanguage()); - } if (locale.isEmpty()) { locale = getInstalledLocaleForSystemUILanguage(inst, true); } diff --git a/desktop/source/app/lockfile2.cxx b/desktop/source/app/lockfile2.cxx index 8a5be1bd36bd..caac3a4c839f 100644 --- a/desktop/source/app/lockfile2.cxx +++ b/desktop/source/app/lockfile2.cxx @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/desktop/source/app/officeipcthread.cxx b/desktop/source/app/officeipcthread.cxx index 9c1a040768b2..f216bb5de074 100644 --- a/desktop/source/app/officeipcthread.cxx +++ b/desktop/source/app/officeipcthread.cxx @@ -668,7 +668,7 @@ RequestHandler::Status RequestHandler::Enable(bool ipc) if( pGlobal.is() ) return IPC_STATUS_OK; -#if !HAVE_FEATURE_DESKTOP || HAVE_FEATURE_MACOSX_SANDBOX || defined(EMSCRIPTEN) +#if !HAVE_FEATURE_DESKTOP || HAVE_FEATURE_MACOSX_SANDBOX || defined(__EMSCRIPTEN__) ipc = false; #endif diff --git a/desktop/source/app/sofficemain.cxx b/desktop/source/app/sofficemain.cxx index ac0f72ec5521..6ef54185b380 100644 --- a/desktop/source/app/sofficemain.cxx +++ b/desktop/source/app/sofficemain.cxx @@ -75,7 +75,7 @@ extern "C" int DESKTOP_DLLPUBLIC soffice_main() #endif tools::extendApplicationEnvironment(); -#if defined EMSCRIPTEN && !HAVE_EMSCRIPTEN_JSPI +#if defined __EMSCRIPTEN__ && !HAVE_EMSCRIPTEN_JSPI //HACK: Qt5 QWasmEventDispatcher::processEvents // (qtbase/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp) calls // emscripten_set_main_loop_arg with simulateInfiniteLoop == true, and as we use diff --git a/desktop/source/app/userinstall.cxx b/desktop/source/app/userinstall.cxx index 7243db43e691..9deea8b7da43 100644 --- a/desktop/source/app/userinstall.cxx +++ b/desktop/source/app/userinstall.cxx @@ -27,7 +27,7 @@ #include #include #include -#if defined ANDROID || defined IOS || defined EMSCRIPTEN +#if defined ANDROID || defined IOS || defined __EMSCRIPTEN__ #include #endif #include @@ -40,7 +40,7 @@ namespace desktop::userinstall { namespace { -#if !(defined ANDROID || defined IOS || defined EMSCRIPTEN) +#if !(defined ANDROID || defined IOS || defined __EMSCRIPTEN__) osl::FileBase::RC copyRecursive( OUString const & srcUri, OUString const & dstUri) { @@ -104,7 +104,7 @@ Status create(OUString const & uri) { if (e != osl::FileBase::E_None && e != osl::FileBase::E_EXIST) { return ERROR_OTHER; } -#if !(defined ANDROID || defined IOS || defined EMSCRIPTEN) +#if !(defined ANDROID || defined IOS || defined __EMSCRIPTEN__) #if defined UNIX // Set safer permissions for the user directory by default: osl::File::setAttributes( diff --git a/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx b/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx index 7aeafc870b48..6d02fd0c0c8a 100644 --- a/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx +++ b/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx @@ -21,7 +21,6 @@ #include #include -#include #include "dp_gui_dependencydialog.hxx" diff --git a/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx b/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx index f9880c5bd88f..4e363148305e 100644 --- a/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx +++ b/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx @@ -23,7 +23,7 @@ #include #include -#include +#include #include diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.cxx b/desktop/source/deployment/gui/dp_gui_dialog2.cxx index 161f95e76d82..22d75ad715ad 100644 --- a/desktop/source/deployment/gui/dp_gui_dialog2.cxx +++ b/desktop/source/deployment/gui/dp_gui_dialog2.cxx @@ -728,10 +728,7 @@ IMPL_LINK_NOARG(ExtMgrDialog, HandleExtTypeCbx, weld::Toggleable&, void) updateList(); } -IMPL_LINK_NOARG(ExtMgrDialog, HandleSearch, weld::Entry&, void) -{ - updateList(); -} +IMPL_LINK_NOARG(ExtMgrDialog, HandleSearch, weld::TextWidget&, void) { updateList(); } IMPL_LINK_NOARG(ExtMgrDialog, HandleUpdateBtn, weld::Button&, void) { diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.hxx b/desktop/source/deployment/gui/dp_gui_dialog2.hxx index 1d3496ac6ffb..98bc9e0f6f00 100644 --- a/desktop/source/deployment/gui/dp_gui_dialog2.hxx +++ b/desktop/source/deployment/gui/dp_gui_dialog2.hxx @@ -22,12 +22,16 @@ #include #include #include +#include +#include #include #include #include +#include +#include +#include #include #include -#include #include @@ -125,7 +129,7 @@ class ExtMgrDialog : public DialogHelper DECL_LINK( HandleCancelBtn, weld::Button&, void ); DECL_LINK( HandleCloseBtn, weld::Button&, void ); DECL_LINK( HandleExtTypeCbx, weld::Toggleable&, void ); - DECL_LINK( HandleSearch, weld::Entry&, void ); + DECL_LINK(HandleSearch, weld::TextWidget&, void); DECL_LINK( TimeOutHdl, Timer *, void ); DECL_LINK( startProgress, void *, void ); diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx index fcaa162b688a..e7657183fed6 100644 --- a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx +++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx @@ -60,7 +60,6 @@ #include #include #include -#include #include "dp_gui_extensioncmdqueue.hxx" #include "dp_gui_dependencydialog.hxx" diff --git a/desktop/source/deployment/gui/dp_gui_extlistbox.hxx b/desktop/source/deployment/gui/dp_gui_extlistbox.hxx index 4bda6bf2184d..043b40275698 100644 --- a/desktop/source/deployment/gui/dp_gui_extlistbox.hxx +++ b/desktop/source/deployment/gui/dp_gui_extlistbox.hxx @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/desktop/source/deployment/gui/dp_gui_service.cxx b/desktop/source/deployment/gui/dp_gui_service.cxx index bc5e09de57ab..54321dbd2469 100644 --- a/desktop/source/deployment/gui/dp_gui_service.cxx +++ b/desktop/source/deployment/gui/dp_gui_service.cxx @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.cxx b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx index b9837335254a..30e79d81a1ab 100644 --- a/desktop/source/deployment/gui/dp_gui_updatedialog.cxx +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx @@ -61,6 +61,7 @@ #include #include #include +#include #include #include @@ -456,7 +457,7 @@ UpdateDialog::UpdateDialog(uno::Reference const& context m_xDescriptions->set_size_request(nWidth, nHeight); m_xUpdates->set_size_request(nWidth, nHeight); - m_xUpdates->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xUpdates->enable_toggle_buttons(); m_xExtensionManager = deployment::ExtensionManager::get( context ); @@ -486,7 +487,7 @@ short UpdateDialog::run() { IMPL_LINK(UpdateDialog, entryToggled, const weld::TreeView::iter_col&, rRowCol, void) { - // error's can't be enabled + // errors can't be enabled const UpdateDialog::Index* p = weld::fromId(m_xUpdates->get_id(rRowCol.first)); if (p->m_eKind == SPECIFIC_ERROR) m_xUpdates->set_toggle(rRowCol.first, TRISTATE_FALSE); @@ -959,7 +960,7 @@ IMPL_LINK_NOARG(UpdateDialog, okHandler, weld::Button&, void) { OSL_ASSERT(enableUpdate.aInstalledPackage.is()); //If the user has no write access to the shared folder then the update - //for a shared extension is disable, that is it cannot be in m_enabledUpdates + //for a shared extension is disabled, that is it cannot be in m_enabledUpdates } diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.hxx b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx index f024e671e319..ac084b201141 100644 --- a/desktop/source/deployment/gui/dp_gui_updatedialog.hxx +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx @@ -27,10 +27,15 @@ #include #include #include +#include +#include #include +#include +#include +#include #include #include -#include +#include #include "dp_gui_updatedata.hxx" diff --git a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx index effa2e83bbd6..302ea27be75b 100644 --- a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx +++ b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx @@ -20,9 +20,12 @@ #pragma once #include +#include #include +#include +#include #include -#include +#include #include #include diff --git a/desktop/source/deployment/gui/license_dialog.cxx b/desktop/source/deployment/gui/license_dialog.cxx index bdb056583d9f..5c00456aa6b4 100644 --- a/desktop/source/deployment/gui/license_dialog.cxx +++ b/desktop/source/deployment/gui/license_dialog.cxx @@ -24,10 +24,11 @@ #include #include #include +#include #include #include +#include #include -#include #include #include "license_dialog.hxx" diff --git a/desktop/source/deployment/inc/dp_interact.h b/desktop/source/deployment/inc/dp_interact.h index 6a041d99f179..a5a193830ed0 100644 --- a/desktop/source/deployment/inc/dp_interact.h +++ b/desktop/source/deployment/inc/dp_interact.h @@ -92,7 +92,7 @@ inline void ProgressLevel::update( css::uno::Any const & status ) const -/** @return true if ia handler is present and any selection has been chosen +/** @return true if an interaction handler is present and any selection has been chosen */ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool interactContinuation( css::uno::Any const & request, diff --git a/desktop/source/deployment/misc/dp_misc.cxx b/desktop/source/deployment/misc/dp_misc.cxx index be180c163fbc..3ed39a649bfa 100644 --- a/desktop/source/deployment/misc/dp_misc.cxx +++ b/desktop/source/deployment/misc/dp_misc.cxx @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -70,7 +70,7 @@ std::shared_ptr & UnoRc() return theRc; }; -#if !defined EMSCRIPTEN +#if !defined __EMSCRIPTEN__ bool existsOfficePipe() { @@ -299,34 +299,25 @@ OUString generateOfficePipeId() throw Exception(u"Extension Manager: Could not obtain path for UserInstallation."_ustr, nullptr); } - rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 ); - if (!digest) { - throw RuntimeException(u"cannot get digest rtl_Digest_AlgorithmMD5!"_ustr, nullptr ); - } - sal_uInt8 const * data = reinterpret_cast(userPath.getStr()); std::size_t size = userPath.getLength() * sizeof (sal_Unicode); - sal_uInt32 md5_key_len = rtl_digest_queryLength( digest ); - std::unique_ptr md5_buf( new sal_uInt8 [ md5_key_len ] ); - rtl_digest_init( digest, data, static_cast(size) ); - rtl_digest_update( digest, data, static_cast(size) ); - rtl_digest_get( digest, md5_buf.get(), md5_key_len ); - rtl_digest_destroy( digest ); + std::vector hash{ + ::comphelper::Hash::calculateHash(data, size, ::comphelper::HashType::MD5)}; // create hex-value string from the MD5 value to keep // the string size minimal OUStringBuffer buf( "SingleOfficeIPC_" ); - for ( sal_uInt32 i = 0; i < md5_key_len; ++i ) { - buf.append( static_cast(md5_buf[ i ]), 0x10 ); + for (unsigned char b : hash) { + buf.append( static_cast(b), 0x10 ); } return buf.makeStringAndClear(); } bool office_is_running() { -#if defined EMSCRIPTEN +#if defined __EMSCRIPTEN__ return true; #else // i#82778: We need to check if we run within the office process. Then we must not use the pipe, diff --git a/desktop/source/deployment/registry/configuration/dp_configuration.cxx b/desktop/source/deployment/registry/configuration/dp_configuration.cxx index e3789008306f..fd7f03c6115c 100644 --- a/desktop/source/deployment/registry/configuration/dp_configuration.cxx +++ b/desktop/source/deployment/registry/configuration/dp_configuration.cxx @@ -205,9 +205,9 @@ BackendImpl::BackendImpl( new ConfigurationBackendDb(getComponentContext(), dbFile)); //clean up data folders which are no longer used. //This must not be done in the same process where the help files - //are still registers. Only after revoking and restarting OOo the folders + //are still registered. Only after revoking and restarting OOo the folders //can be removed. This works now, because the extension manager is a singleton - //and the backends are only create once per process. + //and the backends are only created once per process. std::vector folders = m_backendDb->getAllDataUrls(); deleteUnusedFolders(folders); @@ -503,7 +503,7 @@ bool BackendImpl::removeFromConfigmgrIni( auto i(std::find(rSet.begin(), rSet.end(), rcterm)); if (i == rSet.end() && !isSchema) { - //in case the xcu contained %origin% then the configmr.ini contains the + //in case the xcu contained %origin% then the configmgr.ini contains the //url to the file in the user installation (e.g. $BUNDLED_EXTENSIONS_USER) //However, m_url (getURL()) contains the URL for the file in the actual //extension installation. @@ -723,7 +723,7 @@ void BackendImpl::PackageImpl::processPackage_( for (auto const& entry : entries) { //If the xcu file was installed before the configmgr was changed - //to use the configmgr.ini, one needed to rebuild to whole directory + //to use the configmgr.ini, one needed to rebuild the whole directory //structure containing the xcu, xcs files from all extensions. Now, //we just add all other xcu/xcs files to the configmgr.ini instead of //rebuilding the directory structure. @@ -765,8 +765,8 @@ void BackendImpl::PackageImpl::processPackage_( } #endif ::std::optional data = that->readDataFromDb(url); - //If an xcu file was life deployed then always a data entry is written. - //If the xcu file was already in the configmr.ini then there is also + //If an xcu file was live deployed then always a data entry is written. + //If the xcu file was already in the configmgr.ini then there is also //a data entry if (!m_isSchema && data) { diff --git a/desktop/source/deployment/registry/dp_backenddb.cxx b/desktop/source/deployment/registry/dp_backenddb.cxx index 5b9d35d28dce..6949b78db563 100644 --- a/desktop/source/deployment/registry/dp_backenddb.cxx +++ b/desktop/source/deployment/registry/dp_backenddb.cxx @@ -420,7 +420,7 @@ void BackendDb::writeSimpleList( } } -//Writes only the element if is has a value. +//Writes only the element if it has a value. //The prefix is automatically added to the element name void BackendDb::writeSimpleElement( std::u16string_view sElementName, OUString const & value, @@ -464,7 +464,7 @@ Reference BackendDb::writeKeyElement( const Reference doc = getDocument(); const Reference root = doc->getFirstChild(); - //Check if there are an entry with the same url. This can be the case if the + //Check if there is an entry with the same url. This can be the case if the //status of an XPackage is ambiguous. In this case a call to activateExtension //(dp_extensionmanager.cxx), will register the package again. See also //Package::processPackage_impl in dp_backend.cxx. @@ -623,7 +623,7 @@ void RegisteredDb::addEntry(OUString const & url) Reference root = doc->getFirstChild(); #if OSL_DEBUG_LEVEL > 0 - //There must not be yet an entry with the same url + //There must not yet be an entry with the same url OUString sExpression( sPrefix + ":" + sEntry + "[@url = \"" + url + "\"]"); Reference _extensionNode = @@ -651,6 +651,6 @@ void RegisteredDb::addEntry(OUString const & url) } } -} // namespace dp_registry +} // namespace dp_registry::backend /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/inc/dp_backend.h b/desktop/source/deployment/registry/inc/dp_backend.h index a68420d6b019..f741a0d7f29b 100644 --- a/desktop/source/deployment/registry/inc/dp_backend.h +++ b/desktop/source/deployment/registry/inc/dp_backend.h @@ -195,7 +195,7 @@ typedef ::cppu::WeakComponentImplHelper< class PackageRegistryBackend : protected cppu::BaseMutex, public t_BackendBase { - //The map held originally WeakReferences. The map entries are removed in the disposing + //The map originally held WeakReferences. The map entries are removed in the disposing //function, which is called when the XPackages are destructed or they are //explicitly disposed. The latter happens, for example, when an extension is //removed (see dp_manager.cxx). However, because of how the help systems work, now @@ -242,7 +242,7 @@ protected: css::uno::Reference const & xCmdEnv); /* deletes folders and files. - All folder all files which end with ".tmp" or ".tmp_" and which are + All folders and files which end with ".tmp" or ".tmp_" and which are not used are deleted. */ void deleteUnusedFolders( diff --git a/desktop/source/deployment/registry/package/dp_extbackenddb.cxx b/desktop/source/deployment/registry/package/dp_extbackenddb.cxx index 8e656c5d7dc8..fbde76522d3f 100644 --- a/desktop/source/deployment/registry/package/dp_extbackenddb.cxx +++ b/desktop/source/deployment/registry/package/dp_extbackenddb.cxx @@ -64,7 +64,7 @@ OUString ExtensionBackendDb::getKeyElementName() void ExtensionBackendDb::addEntry(OUString const & url, Data const & data) { try{ - //reactive revoked entry if possible. + //reactivate revoked entry if possible. if (!activateEntry(url)) { Reference extensionNodeNode = writeKeyElement(url); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 7fcff604d4e0..be2f93d95ece 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -47,7 +47,7 @@ #include #endif -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ #include #include #endif @@ -209,7 +209,6 @@ #include #include #include -#include #include // Needed for getUndoManager() @@ -296,43 +295,6 @@ struct ExtensionMap OUString filterName; }; -class TraceEventDumper : public AutoTimer -{ - static const int dumpTimeoutMS = 5000; - -public: - TraceEventDumper() : AutoTimer( "Trace Event dumper" ) - { - SetTimeout(dumpTimeoutMS); - Start(); - } - - virtual void Invoke() override - { - flushRecordings(); - } - - static void flushRecordings() - { - const css::uno::Sequence aEvents = - comphelper::TraceEvent::getRecordingAndClear(); - OStringBuffer aOutput; - for (const auto &s : aEvents) - { - aOutput.append(OUStringToOString(s, RTL_TEXTENCODING_UTF8) - + "\n"); - } - if (aOutput.getLength() > 0) - { - OString aChunk = aOutput.makeStringAndClear(); - if (gImpl && gImpl->mpCallback) - gImpl->mpCallback(LOK_CALLBACK_PROFILE_FRAME, aChunk.getStr(), gImpl->mpCallbackData); - } - } -}; - -TraceEventDumper *traceEventDumper = nullptr; - constexpr ExtensionMap aWriterExtensionMap[] = { { "doc", u"MS Word 97"_ustr }, @@ -1186,9 +1148,6 @@ static void doc_removeTextContext(LibreOfficeKitDocument* pThis, unsigned nLOKWindowId, int nCharBefore, int nCharAfter); -static void doc_sendDialogEvent(LibreOfficeKitDocument* pThis, - unsigned long long int nLOKWindowId, - const char* pArguments); static void doc_postWindowKeyEvent(LibreOfficeKitDocument* pThis, unsigned nLOKWindowId, int nType, @@ -1337,10 +1296,6 @@ static void doc_setViewTimezone(LibreOfficeKitDocument* pThis, int nId, const ch static void doc_setViewReadOnly(LibreOfficeKitDocument* pThis, int nId, const bool readonly); -static void doc_setAllowChangeComments(LibreOfficeKitDocument* pThis, int nId, const bool allow); - -static void doc_setAllowManageRedlines(LibreOfficeKitDocument* pThis, int nId, bool allow); - static void doc_setAccessibilityState(LibreOfficeKitDocument* pThis, int nId, bool bEnabled); static char* doc_getA11yFocusedParagraph(LibreOfficeKitDocument* pThis); @@ -1511,7 +1466,6 @@ LibLODocument_Impl::LibLODocument_Impl(uno::Reference xC m_pDocumentClass->postWindowKeyEvent = doc_postWindowKeyEvent; m_pDocumentClass->postMouseEvent = doc_postMouseEvent; m_pDocumentClass->postWindowMouseEvent = doc_postWindowMouseEvent; - m_pDocumentClass->sendDialogEvent = doc_sendDialogEvent; m_pDocumentClass->postUnoCommand = doc_postUnoCommand; m_pDocumentClass->setTextSelection = doc_setTextSelection; m_pDocumentClass->setWindowTextSelection = doc_setWindowTextSelection; @@ -1575,9 +1529,6 @@ LibLODocument_Impl::LibLODocument_Impl(uno::Reference xC m_pDocumentClass->setViewReadOnly = doc_setViewReadOnly; - m_pDocumentClass->setAllowChangeComments = doc_setAllowChangeComments; - m_pDocumentClass->setAllowManageRedlines = doc_setAllowManageRedlines; - m_pDocumentClass->getPresentationInfo = doc_getPresentationInfo; m_pDocumentClass->createSlideRenderer = doc_createSlideRenderer; m_pDocumentClass->postSlideshowCleanup = doc_postSlideshowCleanup; @@ -1958,7 +1909,6 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) case LOK_CALLBACK_A11Y_CARET_CHANGED: case LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED: case LOK_CALLBACK_A11Y_FOCUSED_CELL_CHANGED: - case LOK_CALLBACK_COLOR_PALETTES: case LOK_CALLBACK_A11Y_EDITING_IN_SELECTION_STATE: case LOK_CALLBACK_A11Y_SELECTION_CHANGED: { @@ -2025,7 +1975,6 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) case LOK_CALLBACK_A11Y_CARET_CHANGED: case LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED: case LOK_CALLBACK_A11Y_FOCUSED_CELL_CHANGED: - case LOK_CALLBACK_COLOR_PALETTES: case LOK_CALLBACK_TOOLTIP: case LOK_CALLBACK_SHAPE_INNER_TEXT: { @@ -2768,10 +2717,6 @@ static void lo_registerAnyInputCallback(LibreOfficeKit* pThis, static void lo_registerFileSaveDialogCallback(LibreOfficeKit* pThis, LibreOfficeKitFileSaveDialogCallback pFileSaveDialogCallback); -static void lo_sendDialogEvent(LibreOfficeKit* pThis, - unsigned long long int nLOKWindowId, - const char* pArguments); - static void lo_setOption(LibreOfficeKit* pThis, const char* pOption, const char* pValue); static void lo_dumpState(LibreOfficeKit* pThis, const char* pOptions, char** pState); @@ -2805,7 +2750,6 @@ LibLibreOffice_Impl::LibLibreOffice_Impl() m_pOfficeClass->runMacro = lo_runMacro; m_pOfficeClass->signDocument = lo_signDocument; m_pOfficeClass->runLoop = lo_runLoop; - m_pOfficeClass->sendDialogEvent = lo_sendDialogEvent; m_pOfficeClass->setOption = lo_setOption; m_pOfficeClass->dumpState = lo_dumpState; m_pOfficeClass->extractRequest = lo_extractRequest; @@ -2945,9 +2889,6 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis, } } - const OUString aDeviceFormFactor = extractParameter(aOptions, u"DeviceFormFactor"); - SfxLokHelper::setDeviceFormFactor(aDeviceFormFactor); - const OUString aBatch = extractParameter(aOptions, u"Batch"); if (!aBatch.isEmpty()) { @@ -5170,95 +5111,6 @@ public: } // anonymous namespace - -static void lcl_sendDialogEvent(unsigned long long int nWindowId, const char* pArguments) -{ - SolarMutexGuard aGuard; - - const StringMap aMap(jsdialog::jsonToStringMap(pArguments)); - auto aIdIter = aMap.find(u"id"_ustr); - - if (aIdIter == aMap.end() || aIdIter->second.isEmpty()) - { - SAL_WARN("lok", "sendDialogEvent: no widget id set"); - assert(false); - return; - } - - const sal_uInt64 nCurrentShellId = reinterpret_cast(SfxViewShell::Current()); - - try - { - const OUString sControlId = aIdIter->second; - OUString sWindowId = OUString::number(nWindowId); - const OUString sCurrentShellId = OUString::number(nCurrentShellId); - - // special values for window id - if (nWindowId == static_cast(-1)) - { - sWindowId = sCurrentShellId + "sidebar"; - - // force sidebar resend - for legacy mobile-wizard: {"id":"-1"} - if (aMap.size() == 1) - { - // force resend - used in mobile-wizard - jsdialog::SendFullUpdate(sCurrentShellId + "sidebar", u"Panel"_ustr); - return; - } - } - if (nWindowId == static_cast(-2)) - sWindowId = sCurrentShellId + "notebookbar"; - if (nWindowId == static_cast(-3)) - sWindowId = sCurrentShellId + "formulabar"; - if (nWindowId == static_cast(-4)) - sWindowId = sCurrentShellId + "addressinputfield"; - if (nWindowId == static_cast(-5)) - sWindowId = sCurrentShellId + "quickfind"; - - // dialogs send own id but notebookbar and sidebar controls are remembered by SfxViewShell id - if (jsdialog::ExecuteAction(sWindowId, sControlId, aMap)) - return; - - if (jsdialog::ExecuteAction(sCurrentShellId + "sidebar", sControlId, aMap)) - return; - if (jsdialog::ExecuteAction(sCurrentShellId + "navigator", sControlId, aMap)) - return; - if (jsdialog::ExecuteAction(sCurrentShellId + "quickfind", sControlId, aMap)) - return; - if (jsdialog::ExecuteAction(sCurrentShellId + "notebookbar", sControlId, aMap)) - return; - if (jsdialog::ExecuteAction(sCurrentShellId + "formulabar", sControlId, aMap)) - return; - if (jsdialog::ExecuteAction(sCurrentShellId + "addressinputfield", sControlId, aMap)) - return; - // this is needed for dialogs shown before document is loaded: MacroWarning dialog, etc... - // these dialogs are created with WindowId "0" - if (!SfxViewShell::Current() && jsdialog::ExecuteAction(u"0"_ustr, sControlId, aMap)) - return; - - // force resend - used in mobile-wizard - jsdialog::SendSidebarForView(nCurrentShellId); - } - catch (std::out_of_range& e) - { - SAL_WARN("lok", "jsdialog::ExecuteAction syntax error - field not found in '" << e.what() << "'"); - assert(false); - } - catch (...) {} - -} - - -static void doc_sendDialogEvent(LibreOfficeKitDocument* /*pThis*/, unsigned long long int nWindowId, const char* pArguments) -{ - lcl_sendDialogEvent(nWindowId, pArguments); -} - -static void lo_sendDialogEvent(LibreOfficeKit* /*pThis*/, unsigned long long int nWindowId, const char* pArguments) -{ - lcl_sendDialogEvent(nWindowId, pArguments); -} - static void reInitDictionaryList() { uno::Reference xDicList @@ -5343,19 +5195,7 @@ static void lo_setOption(LibreOfficeKit* /*pThis*/, const char *pOption, const c { static char* pCurrentSalLogOverride = nullptr; - if (strcmp(pOption, "traceeventrecording") == 0) - { - if (strcmp(pValue, "start") == 0) - { - comphelper::TraceEvent::setBufferSizeAndCallback(100, TraceEventDumper::flushRecordings); - comphelper::TraceEvent::startRecording(); - if (traceEventDumper == nullptr) - traceEventDumper = new TraceEventDumper(); - } - else if (strcmp(pValue, "stop") == 0) - comphelper::TraceEvent::stopRecording(); - } - else if (strcmp(pOption, "sallogoverride") == 0) + if (strcmp(pOption, "sallogoverride") == 0) { if (pCurrentSalLogOverride != nullptr) free(pCurrentSalLogOverride); @@ -5376,22 +5216,10 @@ static void lo_setOption(LibreOfficeKit* /*pThis*/, const char *pOption, const c #ifdef LINUX else if (strcmp(pOption, "addfont") == 0) { - if (memcmp(pValue, "file://", 7) == 0) - pValue += 7; - - int fd = open(pValue, O_RDONLY); - if (fd == -1) - { - std::cerr << "Could not open font file '" << pValue << "': " << strerror(errno) << std::endl; - return; - } - - OUString sMagicFileName = "file:///:FD:/" + OUString::number(fd); - SolarMutexGuard aGuard; OutputDevice *pDevice = Application::GetDefaultDevice(); OutputDevice::ImplClearAllFontData(true); - pDevice->AddTempDevFont(sMagicFileName, u""_ustr); + pDevice->AddTempDevFont(OUString::fromUtf8(pValue), u""_ustr); OutputDevice::ImplRefreshAllFontData(true); } #endif @@ -5445,11 +5273,6 @@ static bool isCommandAllowed(std::u16string_view command) if (!pViewShell || !pViewShell->IsLokReadOnlyView()) return true; - if (command == u".uno:Save") - { - return pViewShell->IsAllowChangeComments() || pViewShell->IsAllowManageRedlines(); - } - if (command == u".uno:TransformDialog") { // If the just added signature line shape is selected, allow moving it. @@ -5643,39 +5466,6 @@ static void doc_postUnoCommand(LibreOfficeKitDocument* pThis, const char* pComma hideSidebar(); return; } - else if (gImpl && aCommand == ".uno:UICoverage") - { - bool report(true), linguisticDataAvailable(true); - std::optional applyTracking; - - for (const beans::PropertyValue& rPropValue : aPropertyValuesVector) - { - if (rPropValue.Name == "Report") - rPropValue.Value >>= report; - else if (rPropValue.Name == "LinguisticDataAvailable") - rPropValue.Value >>= linguisticDataAvailable; - else if (rPropValue.Name == "Track") - { - bool track(false); - rPropValue.Value >>= track; - applyTracking = track; - } - } - - if (report) - { - tools::JsonWriter aJson; - aJson.put("commandName", aCommand); - aJson.put("success", true); - Application::UICoverageReport(aJson, getDocumentType(pThis), linguisticDataAvailable); - pDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); - } - - if (applyTracking) - Application::EnableUICoverage(*applyTracking); - - return; - } else if (gImpl && aCommand == ".uno:ReportWhenIdle") { assert(pDocument->maIdleHelper.msIdleId.isEmpty() && "idle id should be unset"); @@ -5852,7 +5642,7 @@ static void doc_setWindowTextSelection(LibreOfficeKitDocument* /*pThis*/, unsign } - Size aOffset(pWindow->GetOutOffXPixel(), pWindow->GetOutOffYPixel()); + Size aOffset(pWindow->GetDeviceOriginX(), pWindow->GetDeviceOriginY()); Point aCursorPos(nX, nY); aCursorPos.Move(aOffset); sal_uInt16 nModifier = swap ? KEY_MOD1 + KEY_MOD2 : KEY_SHIFT; @@ -7168,9 +6958,6 @@ static int doc_createViewWithOptions(LibreOfficeKitDocument* pThis, comphelper::LibreOfficeKit::setLocale(LanguageTag(aLanguage)); } - const OUString aDeviceFormFactor = extractParameter(aOptions, u"DeviceFormFactor"); - SfxLokHelper::setDeviceFormFactor(aDeviceFormFactor); - LibLODocument_Impl* pDocument = static_cast(pThis); const int nId = SfxLokHelper::createView(pDocument->mnDocumentId); @@ -7436,7 +7223,7 @@ static void doc_paintWindowForView(LibreOfficeKitDocument* pThis, unsigned nLOKW aMapMode.SetOrigin(Point(-(nX / fDPIScale), -(nY / fDPIScale))); pDevice->SetMapMode(aMapMode); - pWindow->PaintToDevice(pDevice.get(), Point(0, 0)); + pWindow->PaintToDevice(*pDevice, Point(0, 0)); #endif comphelper::LibreOfficeKit::setDialogPainting(false); @@ -7641,31 +7428,9 @@ static void doc_completeFunction(LibreOfficeKitDocument* pThis, const char* pFun pDoc->completeFunction(OUString::fromUtf8(pFunctionName)); } - -static void doc_sendFormFieldEvent(LibreOfficeKitDocument* pThis, const char* pArguments) +static void doc_sendFormFieldEvent(LibreOfficeKitDocument* /*pThis*/, const char* /*pArguments*/) { - SolarMutexGuard aGuard; - - // Supported in Writer only - if (doc_getDocumentType(pThis) != LOK_DOCTYPE_TEXT) - return; - - StringMap aMap(jsdialog::jsonToStringMap(pArguments)); - ITiledRenderable* pDoc = getTiledRenderable(pThis); - if (!pDoc) - { - SetLastExceptionMsg(u"Document doesn't support tiled rendering!"_ustr); - return; - } - - // Sanity check - if (!aMap.contains(u"type"_ustr) || !aMap.contains(u"cmd"_ustr)) - { - SetLastExceptionMsg(u"Wrong arguments for sendFormFieldEvent!"_ustr); - return; - } - - pDoc->executeFromFieldEvent(aMap); + return; } static bool doc_renderSearchResult(LibreOfficeKitDocument* pThis, @@ -7718,35 +7483,9 @@ static bool doc_renderSearchResult(LibreOfficeKitDocument* pThis, return true; } -static void doc_sendContentControlEvent(LibreOfficeKitDocument* pThis, const char* pArguments) +static void doc_sendContentControlEvent(LibreOfficeKitDocument* /*pThis*/, const char* /*pArguments*/) { - SolarMutexGuard aGuard; - - // Supported in Writer only - if (doc_getDocumentType(pThis) != LOK_DOCTYPE_TEXT) - { - return; - } - - if (SfxViewShell::IsCurrentLokViewReadOnly()) - return; - - StringMap aMap(jsdialog::jsonToStringMap(pArguments)); - ITiledRenderable* pDoc = getTiledRenderable(pThis); - if (!pDoc) - { - SetLastExceptionMsg(u"Document doesn't support tiled rendering"_ustr); - return; - } - - // Sanity check - if (!aMap.contains(u"type"_ustr)) - { - SetLastExceptionMsg(u"Missing 'type' argument for sendContentControlEvent"_ustr); - return; - } - - pDoc->executeContentControlEvent(aMap); + return; } static void doc_setViewTimezone(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/, int nId, @@ -7775,26 +7514,6 @@ static void doc_setViewReadOnly(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*p SfxLokHelper::setViewReadOnly(nId, readOnly); } -static void doc_setAllowChangeComments(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/, int nId, const bool allow) -{ - comphelper::ProfileZone aZone("doc_setAllowChangeComments"); - - SolarMutexGuard aGuard; - SetLastExceptionMsg(); - - SfxLokHelper::setAllowChangeComments(nId, allow); -} - -static void doc_setAllowManageRedlines(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/, int nId, bool allow) -{ - comphelper::ProfileZone aZone("doc_setAllowManageRedlines"); - - SolarMutexGuard aGuard; - SetLastExceptionMsg(); - - SfxLokHelper::setAllowManageRedlines(nId, allow); -} - static void doc_setAccessibilityState(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* pThis, int nId, bool nEnabled) { SolarMutexGuard aGuard; @@ -7958,7 +7677,7 @@ static bool initialize_uno(const OUString& aAppProgramURL) xSFactory.set(xFactory, uno::UNO_QUERY_THROW); comphelper::setProcessServiceFactory(xSFactory); -#if defined EMSCRIPTEN +#if defined __EMSCRIPTEN__ initJsUnoScripting(); #endif @@ -8333,100 +8052,6 @@ static void preloadData() // see Bootstrap::reloadData for when it gets resynced } -namespace { - -static void activateNotebookbar(std::u16string_view rApp) -{ - OUString aPath = OUString::Concat("org.openoffice.Office.UI.ToolbarMode/Applications/") + rApp; - - const utl::OConfigurationTreeRoot aAppNode(xContext, aPath, true); - - if (aAppNode.isValid()) - { - static constexpr OUString sNoteBookbarName(u"notebookbar_online.ui"_ustr); - aAppNode.setNodeValue(u"Active"_ustr, Any(sNoteBookbarName)); - - const utl::OConfigurationNode aImplsNode = aAppNode.openNode(u"Modes"_ustr); - const Sequence aModeNodeNames( aImplsNode.getNodeNames() ); - - for (const auto& rModeNodeName : aModeNodeNames) - { - const utl::OConfigurationNode aImplNode(aImplsNode.openNode(rModeNodeName)); - if (!aImplNode.isValid()) - continue; - - OUString aCommandArg = comphelper::getString(aImplNode.getNodeValue(u"CommandArg"_ustr)); - if (aCommandArg == "notebookbar.ui") - aImplNode.setNodeValue(u"CommandArg"_ustr, Any(sNoteBookbarName)); - } - - aAppNode.commit(); - } -} - -void setHelpRootURL() -{ - const char* pHelpRootURL = ::getenv("LOK_HELP_URL"); - if (pHelpRootURL) - { - OUString aHelpRootURL = OStringToOUString(pHelpRootURL, RTL_TEXTENCODING_UTF8); - try - { - std::shared_ptr batch(comphelper::ConfigurationChanges::create()); - officecfg::Office::Common::Help::HelpRootURL::set(aHelpRootURL, batch); - batch->commit(); - } - catch (uno::Exception const& rException) - { - SAL_WARN("lok", "Failed to set the help root URL: " << rException.Message); - } - } -} - -void setCertificateDir() -{ - const char* pEnvVarString = ::getenv("LO_CERTIFICATE_DATABASE_PATH"); - if (pEnvVarString) - { - OUString aCertificateDatabasePath = OStringToOUString(pEnvVarString, RTL_TEXTENCODING_UTF8); - try - { - std::shared_ptr pBatch(comphelper::ConfigurationChanges::create()); - officecfg::Office::Common::Security::Scripting::CertDir::set(aCertificateDatabasePath, pBatch); - officecfg::Office::Common::Security::Scripting::ManualCertDir::set(aCertificateDatabasePath, pBatch); - pBatch->commit(); - } - catch (uno::Exception const& rException) - { - SAL_WARN("lok", "Failed to set the NSS certificate database directory: " << rException.Message); - } - } -} - -void setDeeplConfig() -{ - const char* pAPIUrlString = ::getenv("DEEPL_API_URL"); - const char* pAuthKeyString = ::getenv("DEEPL_AUTH_KEY"); - if (pAPIUrlString && pAuthKeyString) - { - OUString aAPIUrl = OStringToOUString(pAPIUrlString, RTL_TEXTENCODING_UTF8); - OUString aAuthKey = OStringToOUString(pAuthKeyString, RTL_TEXTENCODING_UTF8); - try - { - std::shared_ptr batch(comphelper::ConfigurationChanges::create()); - officecfg::Office::Linguistic::Translation::Deepl::ApiURL::set(aAPIUrl, batch); - officecfg::Office::Linguistic::Translation::Deepl::AuthKey::set(aAuthKey, batch); - batch->commit(); - } - catch(uno::Exception const& rException) - { - SAL_WARN("lok", "Failed to set Deepl API settings: " << rException.Message); - } - } -} - -} - static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char* pUserProfileUrl) { enum { @@ -8438,8 +8063,6 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char // Did we do a pre-initialize static bool bPreInited = false; static bool bUnipoll = false; - static bool bProfileZones = false; - static bool bNotebookbar = false; { // cf. string lifetime for preinit std::vector aOpts; @@ -8454,16 +8077,12 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char bUnipoll = true; if (it == "compact_fonts") gUseCompactFonts = true; - else if (it == "profile_events") - bProfileZones = true; else if (it == "sc_no_grid_bg") comphelper::LibreOfficeKit::setCompatFlag( comphelper::LibreOfficeKit::Compat::scNoGridBackground); else if (it == "sc_print_twips_msgs") comphelper::LibreOfficeKit::setCompatFlag( comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs); - else if (it == "notebookbar") - bNotebookbar = true; } } @@ -8498,13 +8117,6 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char if (bInitialized) return 1; - // Turn profile zones on early - if (bProfileZones && eStage == SECOND_INIT) - { - comphelper::TraceEvent::startRecording(); - traceEventDumper = new TraceEventDumper(); - } - comphelper::ProfileZone aZone("lok-init"); if (eStage == PRE_INIT) @@ -8534,7 +8146,7 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char } else { -#if defined ANDROID || defined EMSCRIPTEN +#if defined ANDROID || defined __EMSCRIPTEN__ aAppPath = OUString::fromUtf8(lo_get_app_data_dir()) + "/program"; #else // Fun conversion dance back and forth between URLs and system paths... @@ -8793,27 +8405,8 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char } #endif - - setHelpRootURL(); - setCertificateDir(); - setDeeplConfig(); setLanguageToolConfig(); - if (bNotebookbar) - { - std::shared_ptr batch(comphelper::ConfigurationChanges::create()); - officecfg::Office::UI::ToolbarMode::ActiveWriter::set(u"notebookbar_online.ui"_ustr, batch); - officecfg::Office::UI::ToolbarMode::ActiveCalc::set(u"notebookbar_online.ui"_ustr, batch); - officecfg::Office::UI::ToolbarMode::ActiveImpress::set(u"notebookbar_online.ui"_ustr, batch); - officecfg::Office::UI::ToolbarMode::ActiveDraw::set(u"notebookbar_online.ui"_ustr, batch); - batch->commit(); - - activateNotebookbar(u"Writer"); - activateNotebookbar(u"Calc"); - activateNotebookbar(u"Impress"); - activateNotebookbar(u"Draw"); - } - // staticize all strings. if (eStage == PRE_INIT) rtl_alloc_preInit(0); diff --git a/desktop/source/lib/lokclipboard.hxx b/desktop/source/lib/lokclipboard.hxx index 0ff955a8c154..02894603cf1a 100644 --- a/desktop/source/lib/lokclipboard.hxx +++ b/desktop/source/lib/lokclipboard.hxx @@ -18,8 +18,6 @@ #include #include -using namespace css::uno; - /// A clipboard implementation for LibreOfficeKit. class LOKClipboard final : public cppu::WeakComponentImplHelper SAL_CALL getSupportedServiceNames() override; - static Sequence getSupportedServiceNames_static(); + css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + static css::uno::Sequence getSupportedServiceNames_static(); // XClipboard css::uno::Reference SAL_CALL getContents() override; diff --git a/desktop/source/migration/services/wordbookmigration.cxx b/desktop/source/migration/services/wordbookmigration.cxx index 6d3f7a3a2a69..819662c2671e 100644 --- a/desktop/source/migration/services/wordbookmigration.cxx +++ b/desktop/source/migration/services/wordbookmigration.cxx @@ -66,7 +66,7 @@ namespace migration } } - // iterate recursive over subfolders + // iterate recursively over subfolders for (auto const& subDir : aSubDirs) { TStringVectorPtr aSubResult = getFiles(subDir); diff --git a/desktop/source/pkgchk/unopkg/unopkg_misc.cxx b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx index d9a34d44fabf..ea0713ebbd60 100644 --- a/desktop/source/pkgchk/unopkg/unopkg_misc.cxx +++ b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/desktop/test/deployment/locationtest/LocationTest.java b/desktop/test/deployment/locationtest/LocationTest.java index ca70b5a1e9f4..d618b1c4b730 100644 --- a/desktop/test/deployment/locationtest/LocationTest.java +++ b/desktop/test/deployment/locationtest/LocationTest.java @@ -45,7 +45,7 @@ public class LocationTest { private static final String __serviceName = "com.sun.star.comp.smoketest.LocationTest"; - /** The initial component contextr, that gives access to + /** The initial component context, that gives access to * the service manager, supported singletons, ... * It's often later used */ @@ -77,7 +77,7 @@ public class LocationTest { return getServiceNames(); } - /** This method is a simple helper function to used in the + /** This method is a simple helper function to be used in the * static component initialisation functions as well as in * getSupportedServiceNames. */ diff --git a/desktop/test/deployment/update/changing_display_name/readme.txt b/desktop/test/deployment/update/changing_display_name/readme.txt index 905f0be9a962..cf7b52fcb363 100644 --- a/desktop/test/deployment/update/changing_display_name/readme.txt +++ b/desktop/test/deployment/update/changing_display_name/readme.txt @@ -7,7 +7,7 @@ v1: no display name v2: change1 de v3: change1 de - changed display name - -change1_mod.oxt is the same as change1.oxt version 1 except that is has a display name. -This situation should actually never arise, because the version should always be +change1_mod.oxt is the same as change1.oxt version 1 except that it has a display name. +This situation should actually never arise, because the version should always be changed when the extension is changed - and be it only the display name. diff --git a/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java index 8d48a30c8178..fd4c50b744b3 100644 --- a/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java +++ b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java @@ -29,7 +29,7 @@ import com.sun.star.lang.XTypeProvider; import com.sun.star.lang.XServiceInfo; import com.sun.star.uno.Type; -/** This class capsulates the class, that implements the minimal component, a +/** This class encapsulates the class, that implements the minimal component, a * factory for creating the service (__getComponentFactory) and a * method, that writes the information into the given registry key * (__writeRegistryServiceInfo). @@ -45,7 +45,7 @@ public class TestExtension { private static final String __serviceName = "com.sun.star.comp.smoketest.TestExtension"; - /** The initial component contextr, that gives access to + /** The initial component context, that gives access to * the service manager, supported singletons, ... * It's often later used */ diff --git a/desktop/uiconfig/ui/updatedialog.ui b/desktop/uiconfig/ui/updatedialog.ui index e0fc1a96f76d..9a17c8408f99 100644 --- a/desktop/uiconfig/ui/updatedialog.ui +++ b/desktop/uiconfig/ui/updatedialog.ui @@ -191,12 +191,6 @@ 0 - - - - - True - 6 diff --git a/desktop/unx/source/args.h b/desktop/unx/source/args.h index f0fe7ce39b11..e60e61c26f83 100644 --- a/desktop/unx/source/args.h +++ b/desktop/unx/source/args.h @@ -9,6 +9,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { rtl_uString *pAppPath; const char *pPageinType; // @pagein-writer for - writer etc. else NULL @@ -25,4 +29,8 @@ typedef struct { Args *args_parse (void); void args_free (Args *args); +#ifdef __cplusplus +} +#endif + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/pagein.h b/desktop/unx/source/pagein.h index 7fb8b6a918a6..eaf11cad20fa 100644 --- a/desktop/unx/source/pagein.h +++ b/desktop/unx/source/pagein.h @@ -21,6 +21,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #if HAVE_FEATURE_PAGEIN void pagein_execute(char const* path, char const* file); #else @@ -31,4 +35,8 @@ inline void pagein_execute(char const* path, char const* file) } #endif +#ifdef __cplusplus +} +#endif + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/start.c b/desktop/unx/source/start.cxx similarity index 85% rename from desktop/unx/source/start.c rename to desktop/unx/source/start.cxx index 2529e214ff8c..6db3ae68ea9e 100644 --- a/desktop/unx/source/start.c +++ b/desktop/unx/source/start.cxx @@ -23,11 +23,11 @@ #include #include +#include #include #include #include #include -#include #include #include #include @@ -42,7 +42,7 @@ /* Easier conversions: rtl_uString to rtl_String */ static rtl_String *ustr_to_str(rtl_uString *pStr) { - rtl_String *pOut = NULL; + rtl_String *pOut = nullptr; rtl_uString2String(&pOut, rtl_uString_getStr(pStr), rtl_uString_getLength(pStr), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS); @@ -53,18 +53,22 @@ static rtl_String *ustr_to_str(rtl_uString *pStr) /* Easier conversions: char * to rtl_uString */ static rtl_uString *charp_to_ustr(const char *pStr) { - rtl_uString *pOut = NULL; + rtl_uString *pOut = nullptr; rtl_string2UString(&pOut, pStr, strlen(pStr), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS); return pOut; } +namespace { + typedef struct { int status_fd; oslProcess child; } ChildInfo; +} // namespace + static int child_info_get_status_fd(ChildInfo const *info) { @@ -79,16 +83,16 @@ child_info_destroy(ChildInfo *info) free (info); } -static ChildInfo * child_spawn(Args *args, sal_Bool bAllArgs, sal_Bool bWithStatus) +static ChildInfo * child_spawn(Args *args, bool bAllArgs, bool bWithStatus) { - rtl_uString *pApp = NULL, *pTmp = NULL; + rtl_uString *pApp = nullptr, *pTmp = nullptr; rtl_uString **ppArgs; sal_uInt32 nArgs, i; ChildInfo *info; int status_pipe[2]; oslProcessError nError; - info = calloc (1, sizeof (ChildInfo)); + info = static_cast(calloc (1, sizeof (ChildInfo))); /* create pipe */ if (pipe(status_pipe) < 0) @@ -104,11 +108,11 @@ static ChildInfo * child_spawn(Args *args, sal_Bool bAllArgs, sal_Bool bWithStat rtl_uString_newFromAscii(&pTmp, "soffice.bin"); rtl_uString_newConcat(&pApp, pApp, pTmp); rtl_uString_release(pTmp); - pTmp = NULL; + pTmp = nullptr; /* copy args */ nArgs = bAllArgs ? args->nArgsTotal : args->nArgsEnv; - ppArgs = (rtl_uString **)calloc(nArgs + 1, sizeof(rtl_uString*)); + ppArgs = static_cast(calloc(nArgs + 1, sizeof(rtl_uString*))); for (i = 0; i < nArgs; ++i) ppArgs[i] = args->ppArgs[i]; @@ -126,9 +130,9 @@ static ChildInfo * child_spawn(Args *args, sal_Bool bAllArgs, sal_Bool bWithStat /* start the main process */ nError = osl_executeProcess(pApp, ppArgs, nArgs, osl_Process_NORMAL, - NULL, - NULL, - NULL, 0, + nullptr, + nullptr, + nullptr, 0, &info->child ); if (pTmp) @@ -148,7 +152,7 @@ static ChildInfo * child_spawn(Args *args, sal_Bool bAllArgs, sal_Bool bWithStat return info; } -static sal_Bool child_exited_wait(ChildInfo *info, sal_Bool bShortWait) +static bool child_exited_wait(ChildInfo *info, bool bShortWait) { TimeValue t = { 0, 250 /* ms */ * 1000 * 1000 }; if (!bShortWait) @@ -173,8 +177,12 @@ static int child_get_exit_code(ChildInfo *info) return inf.Code; } +namespace { + typedef enum { ProgressContinue, ProgressRestart, ProgressExit } ProgressStatus; +} // namespace + /* Path of the application, with trailing slash. */ static rtl_uString *get_app_path(const char *pAppExec) { @@ -194,7 +202,7 @@ static rtl_uString *get_app_path(const char *pAppExec) len = rtl_uString_getLength(pResult); if (len > 0 && rtl_uString_getStr(pResult)[len - 1] != '/') { - rtl_uString *pSlash = NULL; + rtl_uString *pSlash = nullptr; rtl_uString_newFromAscii(&pSlash, "/"); rtl_uString_newConcat(&pResult, pResult, pSlash); rtl_uString_release(pSlash); @@ -206,60 +214,44 @@ static rtl_uString *get_app_path(const char *pAppExec) /* Compute the OOo md5 hash from 'pText' */ static rtl_uString *get_md5hash(rtl_uString *pText) { - rtl_uString *pResult = NULL; + rtl_uString *pResult = nullptr; sal_Int32 nCapacity = 100; - unsigned char *pData = NULL; + unsigned char *pData = nullptr; sal_uInt32 nSize = 0; - rtlDigest digest; - sal_uInt32 md5_key_len = 0; - sal_uInt8* md5_buf = NULL; - sal_uInt32 i = 0; if ( !pText ) - return NULL; + return nullptr; - pData = (unsigned char *)rtl_uString_getStr(pText); + pData = reinterpret_cast(rtl_uString_getStr(pText)); nSize = rtl_uString_getLength(pText) * sizeof(sal_Unicode); if (!pData) - return NULL; + return nullptr; - digest = rtl_digest_create(rtl_Digest_AlgorithmMD5); - if (!digest) - return NULL; - - md5_key_len = rtl_digest_queryLength(digest); - md5_buf = (sal_uInt8 *)calloc(md5_key_len, sizeof(sal_uInt8)); - - rtl_digest_init(digest, pData , nSize); - rtl_digest_update(digest, pData, nSize); - rtl_digest_get(digest, md5_buf, md5_key_len); - rtl_digest_destroy(digest); + const std::vector md5_buf = + comphelper::Hash::calculateHash(pData, nSize, comphelper::HashType::MD5); /* create hex-value string from the MD5 value to keep the string size minimal */ rtl_uString_new_WithLength(&pResult, nCapacity); - for (; i < md5_key_len; ++i) + for (unsigned char b : md5_buf) { char val[3]; - snprintf(val, 3, "%x", md5_buf[i]); /* sic! we ignore some of the 0's */ + snprintf(val, 3, "%x", b); /* sic! we ignore some of the 0's */ rtl_uStringbuffer_insert_ascii(&pResult, &nCapacity, rtl_uString_getLength(pResult), val, strlen(val)); } - /* cleanup */ - free(md5_buf); - return pResult; } /* Construct the pipe name */ static rtl_uString *get_pipe_path(rtl_uString *pAppPath) { - rtl_uString *pPath = NULL, *pTmp = NULL, *pUserInstallation = NULL; - rtl_uString *pResult = NULL, *pBasePath = NULL, *pAbsUserInstallation = NULL; + rtl_uString *pPath = nullptr, *pTmp = nullptr, *pUserInstallation = nullptr; + rtl_uString *pResult = nullptr, *pBasePath = nullptr, *pAbsUserInstallation = nullptr; rtlBootstrapHandle handle; - rtl_uString *pMd5hash = NULL; + rtl_uString *pMd5hash = nullptr; sal_Unicode pUnicode[RTL_USTR_MAX_VALUEOFINT32]; /* setup bootstrap filename */ @@ -273,7 +265,7 @@ static rtl_uString *get_pipe_path(rtl_uString *pAppPath) handle = rtl_bootstrap_args_open(pPath); rtl_uString_newFromAscii(&pTmp, "UserInstallation"); - rtl_bootstrap_get_from_handle(handle, pTmp, &pUserInstallation, NULL); + rtl_bootstrap_get_from_handle(handle, pTmp, &pUserInstallation, nullptr); rtl_bootstrap_args_close(handle); @@ -304,7 +296,7 @@ static rtl_uString *get_pipe_path(rtl_uString *pAppPath) rtl_uString_newFromAscii(&pTmp, "/OSL_PIPE_"); rtl_uString_newConcat(&pResult, pResult, pTmp); - rtl_ustr_valueOfInt32(pUnicode, (int)getuid(), 10); + rtl_ustr_valueOfInt32(pUnicode, static_cast(getuid()), 10); rtl_uString_newFromStr(&pTmp, pUnicode); rtl_uString_newConcat(&pResult, pResult, pTmp); @@ -354,7 +346,7 @@ static int connect_pipe(rtl_uString *pPipePath) len = sizeof(addr); #endif - if (connect(fd, (struct sockaddr *)&addr, len) < 0) + if (connect(fd, reinterpret_cast(&addr), len) < 0) { close(fd); fd = -1; @@ -365,7 +357,7 @@ static int connect_pipe(rtl_uString *pPipePath) /* Escape: "," -> "\\,", "\0" -> "\\0", "\\" -> "\\\\" */ static rtl_uString *escape_path(rtl_uString const *pToEscape) { - rtl_uString *pBuffer = NULL; + rtl_uString *pBuffer = nullptr; sal_Int32 nCapacity = 1000; sal_Int32 i = 0; sal_Int32 nEscapeLength = rtl_uString_getLength(pToEscape); @@ -403,12 +395,12 @@ static rtl_uString *escape_path(rtl_uString const *pToEscape) } /* Send args to the LO instance (using the 'fd' file descriptor) */ -static sal_Bool send_args(int fd, rtl_uString const *pCwdPath) +static bool send_args(int fd, rtl_uString const *pCwdPath) { - rtl_uString *pBuffer = NULL, *pTmp = NULL; + rtl_uString *pBuffer = nullptr, *pTmp = nullptr; sal_Int32 nCapacity = 1000; - rtl_String *pOut = NULL; - sal_Bool bResult; + rtl_String *pOut = nullptr; + bool bResult; size_t nLen; rtl_uString *pEscapedCwdPath = escape_path(pCwdPath); sal_uInt32 nArg = 0; @@ -441,7 +433,7 @@ static sal_Bool send_args(int fd, rtl_uString const *pCwdPath) for (nArg = 0; nArg < nArgCount; ++nArg) { - rtl_uString *pEscapedTmp = NULL; + rtl_uString *pEscapedTmp = nullptr; rtl_uStringbuffer_insert_ascii(&pBuffer, &nCapacity, rtl_uString_getLength(pBuffer), ",", 1); @@ -470,7 +462,7 @@ static sal_Bool send_args(int fd, rtl_uString const *pCwdPath) nLen = rtl_string_getLength(pOut) + 1; ssize_t n = write(fd, rtl_string_getStr(pOut), nLen); - bResult = (n >= 0 && (size_t) n == nLen); + bResult = (n >= 0 && static_cast(n) == nLen); if ( bResult ) { @@ -581,7 +573,7 @@ static void exec_pagein (Args *args) static void extend_library_path(const char *new_element) { - rtl_uString *pEnvName=NULL, *pOrigEnvVar=NULL, *pNewEnvVar=NULL; + rtl_uString *pEnvName=nullptr, *pOrigEnvVar=nullptr, *pNewEnvVar=nullptr; rtl_uString_newFromAscii(&pEnvName, "LD_LIBRARY_PATH"); rtl_string2UString(&pNewEnvVar, new_element, strlen(new_element), RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS); @@ -589,7 +581,7 @@ static void extend_library_path(const char *new_element) osl_getEnvironment(pEnvName, &pOrigEnvVar); if (pOrigEnvVar && pOrigEnvVar->length) { - rtl_uString *pDelim = NULL; + rtl_uString *pDelim = nullptr; rtl_uString_newFromAscii(&pDelim, ":"); rtl_uString_newConcat(&pNewEnvVar, pNewEnvVar, pDelim); rtl_uString_newConcat(&pNewEnvVar, pNewEnvVar, pOrigEnvVar); @@ -613,20 +605,20 @@ static void exec_javaldx(Args *args) rtl_uString **ppArgs; rtl_uString *pTmp, *pTmp2; - oslProcess javaldx = NULL; - oslFileHandle fileOut = NULL; + oslProcess javaldx = nullptr; + oslFileHandle fileOut = nullptr; oslProcessError err; - ppArgs = (rtl_uString **)calloc(args->nArgsEnv + 2, sizeof(rtl_uString*)); + ppArgs = static_cast(calloc(args->nArgsEnv + 2, sizeof(rtl_uString*))); for (nArgs = 0; nArgs < args->nArgsEnv; ++nArgs) ppArgs[nArgs] = args->ppArgs[nArgs]; /* Use absolute path to redirectrc */ - pTmp = NULL; + pTmp = nullptr; rtl_uString_newFromAscii(&pTmp, "-env:INIFILENAME=vnd.sun.star.pathname:"); rtl_uString_newConcat(&pTmp, pTmp, args->pAppPath); - pTmp2 = NULL; + pTmp2 = nullptr; rtl_uString_newFromAscii(&pTmp2, "redirectrc"); rtl_uString_newConcat(&pTmp, pTmp, pTmp2); ppArgs[nArgs] = pTmp; @@ -634,23 +626,23 @@ static void exec_javaldx(Args *args) nArgs++; /* And also to javaldx */ - pApp = NULL; + pApp = nullptr; rtl_uString_newFromAscii(&pApp, "file://"); rtl_uString_newConcat(&pApp, pApp, args->pAppPath); - pTmp = NULL; + pTmp = nullptr; rtl_uString_newFromAscii(&pTmp, "javaldx"); rtl_uString_newConcat(&pApp, pApp, pTmp); rtl_uString_release(pTmp); err = osl_executeProcess_WithRedirectedIO(pApp, ppArgs, nArgs, osl_Process_NORMAL, - NULL, // security - NULL, // work dir - NULL, 0, + nullptr, // security + nullptr, // work dir + nullptr, 0, &javaldx, // process handle - NULL, + nullptr, &fileOut, - NULL); + nullptr); rtl_uString_release(ppArgs[nArgs-1]); rtl_uString_release(pApp); @@ -658,7 +650,7 @@ static void exec_javaldx(Args *args) if(err != osl_Process_E_None) { - putenv("javaldx_warn=failed to launch javaldx - java may not function correctly"); + putenv(const_cast("javaldx_warn=failed to launch javaldx - java may not function correctly")); if (javaldx) osl_freeProcessHandle(javaldx); @@ -676,7 +668,7 @@ static void exec_javaldx(Args *args) if (bytes_read <= 0) { - putenv("javaldx_warn=failed to read path from javaldx"); + putenv(const_cast("javaldx_warn=failed to read path from javaldx")); if (javaldx) osl_freeProcessHandle(javaldx); @@ -707,14 +699,12 @@ static void exec_javaldx(Args *args) #endif // has to be a global :( -static oslProcess * volatile g_pProcess = NULL; +static oslProcess volatile g_pProcess = nullptr; -static void sigterm_handler(int ignored) +static void sigterm_handler(int /*ignored*/) { - (void) ignored; - if (g_pProcess) { - int SigTermSucceded = 0; + bool SigTermSucceded = false; oslProcessInfo info; info.Size = sizeof(oslProcessInfo); @@ -739,12 +729,12 @@ static void sigterm_handler(int ignored) SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) { - sal_Bool bSentArgs = sal_False; + bool bSentArgs = false; const char* pUsePlugin; - rtl_uString *pPipePath = NULL; + rtl_uString *pPipePath = nullptr; Args *args; int status = 0; - struct splash* splash = NULL; + struct splash* splash = nullptr; struct sigaction sigpipe_action; struct sigaction sigterm_action; @@ -752,11 +742,11 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) memset(&sigpipe_action, 0, sizeof(struct sigaction)); sigpipe_action.sa_handler = SIG_IGN; sigemptyset(&sigpipe_action.sa_mask); - sigaction(SIGPIPE, &sigpipe_action, NULL); + sigaction(SIGPIPE, &sigpipe_action, nullptr); memset(&sigterm_action, 0, sizeof(struct sigaction)); sigterm_action.sa_handler = &sigterm_handler; sigemptyset(&sigterm_action.sa_mask); - sigaction(SIGTERM, &sigterm_action, NULL); + sigaction(SIGTERM, &sigterm_action, nullptr); args = args_parse(); args->pAppPath = get_app_path(argv[0]); @@ -768,12 +758,12 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) #ifndef ENABLE_QUICKSTART_LIBPNG /* we can't load and render it anyway */ - args->bInhibitSplash = sal_True; + args->bInhibitSplash = true; #endif pUsePlugin = getenv("SAL_USE_VCLPLUGIN"); if (pUsePlugin && !strcmp(pUsePlugin, "svp")) - args->bInhibitSplash = sal_True; + args->bInhibitSplash = true; if (!args->bInhibitPipe && !getenv("LIBO_FLATPAK")) { @@ -785,11 +775,11 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) // Wait for answer char resp[27]; // strlen("InternalIPC::SendArguments") + 1 ssize_t n = read(fd, resp, SAL_N_ELEMENTS(resp)); - if (n == (ssize_t) SAL_N_ELEMENTS(resp) && + if (n == static_cast(SAL_N_ELEMENTS(resp)) && (memcmp(resp, "InternalIPC::SendArguments", SAL_N_ELEMENTS(resp) - 1) == 0)) { - rtl_uString *pCwdPath = NULL; + rtl_uString *pCwdPath = nullptr; osl_getProcessWorkingDir(&pCwdPath); // Then send args @@ -805,8 +795,8 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) /* we have to prepare for, and exec the binary */ int nPercent = 0; ChildInfo *info; - sal_Bool bAllArgs = sal_True; - sal_Bool bShortWait, bRestart; + bool bAllArgs = true; + bool bShortWait, bRestart; /* sanity check pieces */ system_checks(); @@ -827,10 +817,10 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) do { - bRestart = sal_False; + bRestart = false; /* fast updates if we have somewhere to update it to */ - bShortWait = splash ? sal_True : sal_False; + bShortWait = splash != nullptr; /* Periodically update the splash & the percent according to what status_fd says, poll quickly only while starting */ @@ -847,23 +837,23 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) if (eResult != ProgressContinue) { splash_destroy(splash); - splash = NULL; - bShortWait = sal_False; + splash = nullptr; + bShortWait = false; } } status = child_get_exit_code(info); - g_pProcess = NULL; // reset + g_pProcess = nullptr; // reset switch (status) { case EXITHELPER_CRASH_WITH_RESTART: // re-start with just -env: parameters - bRestart = sal_True; - bAllArgs = sal_False; + bRestart = true; + bAllArgs = false; break; case EXITHELPER_NORMAL_RESTART: // re-start with all arguments - bRestart = sal_True; - bAllArgs = sal_True; + bRestart = true; + bAllArgs = true; break; default: break; diff --git a/dictionaries b/dictionaries index 589a31b2c7e8..32b006a2c22a 160000 --- a/dictionaries +++ b/dictionaries @@ -1 +1 @@ -Subproject commit 589a31b2c7e8a592270012e111a51a80d0176f6e +Subproject commit 32b006a2c22a4ac7e8ed3f03346f7b3d85a970a4 diff --git a/distro-configs/CODAWindows.conf b/distro-configs/CODAWindows.conf deleted file mode 100644 index 01e997fd46b1..000000000000 --- a/distro-configs/CODAWindows.conf +++ /dev/null @@ -1,45 +0,0 @@ -# Collabora Online Desktop app for Windows - -# Build environment ---with-visual-studio=2022 ---enable-python=fully-internal ---without-lxml ---without-export-validation ---disable-ccache ---disable-pch ---without-doxygen ---without-java ---enable-symbols - -# Branding (unused, but...) -#--with-branding=icon-themes/galaxy/brand_cp - -# Features ---disable-breakpad ---disable-firebird-sdbc ---disable-online-update ---without-helppack-integration ---disable-avmedia ---disable-odk ---disable-skia ---disable-cli ---with-myspell-dicts ---enable-headless ---disable-win ---enable-mergelibs ---disable-opencl ---disable-opengl ---without-galleries - -# Sensible font bundling settings for desktop ---with-fonts ---with-docrepair-fonts - -# MPLv2 subset ---with-theme=colibre ---disable-mariadb-sdbc ---disable-postgresql-sdbc ---disable-lotuswordpro ---disable-lpsolve ---disable-poppler ---disable-gpgmepp diff --git a/distro-configs/CPAndroid.conf b/distro-configs/CPAndroid.conf deleted file mode 100644 index 5aaeabedc03c..000000000000 --- a/distro-configs/CPAndroid.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Use LibreOfficeAndroid.conf as the base -INCLUDE:LibreOfficeAndroid -# Add the CP stuff -INCLUDE:CPAndroidBranding diff --git a/distro-configs/CPAndroidAarch64.conf b/distro-configs/CPAndroidAarch64.conf deleted file mode 100644 index 5cef2d518cd1..000000000000 --- a/distro-configs/CPAndroidAarch64.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Use LibreOfficeAndroidAarch64.conf as the base -INCLUDE:LibreOfficeAndroidAarch64 -# Add the CP stuff -INCLUDE:CPAndroidBranding diff --git a/distro-configs/CPAndroidBranding.conf b/distro-configs/CPAndroidBranding.conf deleted file mode 100644 index 30c902df24d3..000000000000 --- a/distro-configs/CPAndroidBranding.conf +++ /dev/null @@ -1,14 +0,0 @@ -# CP specific stuff ---build=x86_64-unknown-linux-gnu ---disable-odk ---enable-android-lok ---with-android-api-level=21 ---with-android-package-name=com.collabora.libreoffice ---with-vendor=Collabora ---disable-scripting-beanshell ---disable-scripting-javascript ---with-lang=de en-US es pt-BR ---with-myspell-dicts ---with-docrepair-fonts ---enable-pdfimport ---enable-release-build diff --git a/distro-configs/CPAndroidX86.conf b/distro-configs/CPAndroidX86.conf deleted file mode 100644 index 6fba0d609cfb..000000000000 --- a/distro-configs/CPAndroidX86.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Use LibreOfficeAndroidX86.conf as the base -INCLUDE:LibreOfficeAndroidX86 -# Add the CP stuff -INCLUDE:CPAndroidBranding diff --git a/distro-configs/CPAndroidX86_64.conf b/distro-configs/CPAndroidX86_64.conf deleted file mode 100644 index 9c56e3afe3a0..000000000000 --- a/distro-configs/CPAndroidX86_64.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Use LibreOfficeAndroidX86_64.conf as the base -INCLUDE:LibreOfficeAndroidX86_64 -# Add the CP stuff -INCLUDE:CPAndroidBranding diff --git a/distro-configs/CPLinux-LOKit.conf b/distro-configs/CPLinux-LOKit.conf deleted file mode 100644 index 69d89871336f..000000000000 --- a/distro-configs/CPLinux-LOKit.conf +++ /dev/null @@ -1,68 +0,0 @@ ---enable-hardening-flags ---enable-mpl-subset ---with-vendor=Collabora -#--with-branding=icon-themes/galaxy/brand_cp ---with-system-dicts ---with-myspell-dicts ---with-system-zlib ---disable-poppler ---enable-cairo-rgba ---without-system-cairo ---without-system-fontconfig ---without-system-freetype ---without-system-graphite ---without-system-harfbuzz ---without-system-openssl ---without-system-libpng ---without-system-libxml ---without-system-jpeg ---without-system-expat ---without-system-curl ---without-system-icu ---without-system-nss ---without-system-jars ---without-system-postgresql ---without-java ---without-junit ---without-help ---with-linker-hash-style=both ---with-fonts ---with-docrepair-fonts ---with-galleries=no ---with-theme=colibre colibre_svg ---with-external-thes-dir=/usr/share/mythes ---with-external-hyph-dir=/usr/share/hyphen ---with-external-dict-dir=/usr/share/hunspell ---disable-dbus ---enable-extension-integration ---disable-odk ---disable-kf5 ---disable-gtk3 ---disable-qt5 ---disable-gstreamer-1-0 ---disable-evolution2 ---disable-gio ---disable-gui ---disable-scripting-beanshell ---disable-scripting-javascript ---disable-ext-wiki-publisher ---disable-report-builder ---disable-ext-nlpsolver ---disable-sdremote ---disable-sdremote-bluetooth ---disable-postgresql-sdbc ---disable-firebird-sdbc ---disable-randr ---enable-epm ---enable-python=internal ---disable-online-update ---disable-dconf ---enable-mergelibs ---enable-lto ---with-package-format=deb rpm ---enable-release-build ---with-lang=ar as ast bg bn-IN br ca ca-valencia cy cs da de el en-US en-GB es et eu fi fr ga gd gl gu he hi hr hu id is it ja km kn ko lt lv ml mr nb nl nn oc or pa-IN pl pt pt-BR ro ru sk sl sr sr-Latn sv ta te tr uk vi zh-CN zh-TW ---disable-lotuswordpro ---disable-lpsolve ---enable-symbols ---enable-sal-log diff --git a/distro-configs/CPMacOS-LOKit.conf b/distro-configs/CPMacOS-LOKit.conf deleted file mode 100644 index 62d4f579ee8f..000000000000 --- a/distro-configs/CPMacOS-LOKit.conf +++ /dev/null @@ -1,42 +0,0 @@ -INCLUDE:CPLinux-LOKit - -# LOKit needs to be able to run in the sandbox ---enable-macosx-sandbox - -# disable Linux stuff that we don't need ---disable-epm ---disable-python ---without-package-format ---enable-gui - -# Sensible font bundling settings for desktop ---with-fonts ---with-docrepair-fonts - -# from LibreOfficeiOS (copied only, to avoid the --host setting) ---disable-breakpad ---disable-firebird-sdbc ---disable-online-update - ---without-export-validation ---without-helppack-integration ---without-java ---without-junit - ---with-theme=colibre - ---with-build-platform-configure-options=--with-system-jpeg=no - ---disable-avahi ---disable-avmedia ---disable-compiler-plugins ---disable-cups ---disable-dconf ---disable-kf5 ---disable-odk ---disable-openssl ---disable-poppler ---disable-python ---disable-skia - ---enable-headless diff --git a/distro-configs/Jenkins/Linux_ubsan_master.conf b/distro-configs/Jenkins/Linux_ubsan_master.conf index d2b414eecfbc..f9d2455fe212 100644 --- a/distro-configs/Jenkins/Linux_ubsan_master.conf +++ b/distro-configs/Jenkins/Linux_ubsan_master.conf @@ -24,3 +24,4 @@ --disable-gtk3 --with-jdk-home=/etc/alternatives/java_sdk_17 --enable-odk +--enable-quickjs diff --git a/distro-configs/Jenkins/linux_clang_dbgutil_64 b/distro-configs/Jenkins/linux_clang_dbgutil_64 index c516bfd0c008..5f0c41dce4e1 100644 --- a/distro-configs/Jenkins/linux_clang_dbgutil_64 +++ b/distro-configs/Jenkins/linux_clang_dbgutil_64 @@ -14,3 +14,4 @@ --disable-dconf --enable-python=internal --enable-atspi-tests +--enable-quickjs diff --git a/distro-configs/LibreOfficeFlatpak.conf b/distro-configs/LibreOfficeFlatpak.conf index 2b01a6d299ce..70033f615a93 100644 --- a/distro-configs/LibreOfficeFlatpak.conf +++ b/distro-configs/LibreOfficeFlatpak.conf @@ -57,7 +57,6 @@ --without-system-libwpg --without-system-libwps --without-system-libzmf ---without-system-lpsolve --without-system-mariadb --without-system-md4c --without-system-mdds diff --git a/distro-configs/LibreOfficeMacOSX.conf b/distro-configs/LibreOfficeMacOSX.conf index 68df63a63922..7bd6d0e17bd7 100644 --- a/distro-configs/LibreOfficeMacOSX.conf +++ b/distro-configs/LibreOfficeMacOSX.conf @@ -10,3 +10,6 @@ --with-package-format=dmg --enable-odk --enable-mergelibs=more +--enable-headless +--without-system-fontconfig +--without-system-freetype diff --git a/distro-configs/LibreOfficeOssFuzz.conf b/distro-configs/LibreOfficeOssFuzz.conf index ecf1b1ba9019..4d7dfe3e2f7c 100644 --- a/distro-configs/LibreOfficeOssFuzz.conf +++ b/distro-configs/LibreOfficeOssFuzz.conf @@ -16,7 +16,6 @@ --disable-ldap --disable-libcmis --disable-librelogo ---disable-lpsolve --disable-mariadb-sdbc --disable-odk --disable-poppler diff --git a/distro-configs/LibreOfficeVanillaMacAppStore.conf b/distro-configs/LibreOfficeVanillaMacAppStore.conf index 6c96b7896005..f70dc6241571 100644 --- a/distro-configs/LibreOfficeVanillaMacAppStore.conf +++ b/distro-configs/LibreOfficeVanillaMacAppStore.conf @@ -1,6 +1,5 @@ --disable-firebird-sdbc --disable-lotuswordpro ---disable-lpsolve --disable-odk --disable-online-update --disable-pdfimport diff --git a/docmodel/Library_docmodel.mk b/docmodel/Library_docmodel.mk index 01e63c4b7e48..11ffbe302639 100644 --- a/docmodel/Library_docmodel.mk +++ b/docmodel/Library_docmodel.mk @@ -17,7 +17,6 @@ $(eval $(call gb_Library_add_exception_objects,docmodel,\ docmodel/source/uno/UnoTheme \ docmodel/source/theme/ColorSet \ docmodel/source/theme/Theme \ - docmodel/source/color/ComplexColorJSON \ docmodel/source/color/ComplexColor \ docmodel/source/styles/ChartStyle \ docmodel/source/styles/ChartColorStyle \ diff --git a/docmodel/source/color/ComplexColor.cxx b/docmodel/source/color/ComplexColor.cxx index 4b957abad991..6f64e41a15b8 100644 --- a/docmodel/source/color/ComplexColor.cxx +++ b/docmodel/source/color/ComplexColor.cxx @@ -36,15 +36,6 @@ void ComplexColor::setCRGB(sal_Int32 nR, sal_Int32 nG, sal_Int32 nB) meType = ColorType::CRGB; } -void ComplexColor::setRGB(double r, double g, double b) -{ - mnComponent1 = r; - mnComponent2 = g; - mnComponent3 = b; - maFinalColor = ::Color(sal_Int8(r), sal_Int8(g), sal_Int8(b)); - meType = ColorType::RGB; -} - void ComplexColor::getRGB(double& r, double& g, double& b) { if (meType != ColorType::RGB) @@ -86,18 +77,6 @@ void ComplexColor::setSystemColor(SystemColorType eSystemColorType, sal_Int32 nR meType = ColorType::System; } -bool ComplexColor::isOpaque() const -{ - for (const Transformation& t : maTransformations) - { - if (t.meType == model::TransformationType::Alpha && t.mnValue != 10000) - { - return false; - } - } - return true; -} - bool ComplexColor::isTransparent() const { for (const Transformation& t : maTransformations) diff --git a/docmodel/source/color/ComplexColorJSON.cxx b/docmodel/source/color/ComplexColorJSON.cxx deleted file mode 100644 index 4ff997ff2505..000000000000 --- a/docmodel/source/color/ComplexColorJSON.cxx +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- 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 -#include -#include -#include -#include - -namespace model::color -{ -bool convertFromJSON(OString const& rJsonString, model::ComplexColor& rComplexColor) -{ - model::ComplexColor aComplexColor; - - try - { - std::stringstream aStream((std::string(rJsonString))); - boost::property_tree::ptree aRootTree; - boost::property_tree::read_json(aStream, aRootTree); - - sal_Int32 nThemeType = aRootTree.get("ThemeIndex", -1); - aComplexColor.setThemeColor(model::convertToThemeColorType(nThemeType)); - boost::property_tree::ptree aTransformTree = aRootTree.get_child("Transformations"); - for (const auto& rEachTransformationNode : - boost::make_iterator_range(aTransformTree.equal_range(""))) - { - auto const& rTransformationTree = rEachTransformationNode.second; - std::string sType = rTransformationTree.get("Type", ""); - sal_Int16 nValue = rTransformationTree.get("Value", 0); - - auto eType = model::TransformationType::Undefined; - if (sType == "LumOff") - eType = model::TransformationType::LumOff; - else if (sType == "LumMod") - eType = model::TransformationType::LumMod; - else if (sType == "Tint") - eType = model::TransformationType::Tint; - else if (sType == "Shade") - eType = model::TransformationType::Shade; - - if (eType != model::TransformationType::Undefined) - aComplexColor.addTransformation({ eType, nValue }); - } - } - catch (const boost::property_tree::json_parser_error& /*exception*/) - { - return false; - } - - rComplexColor = std::move(aComplexColor); - return true; -} - -void convertToJSONTree(tools::JsonWriter& rTree, model::ComplexColor const& rComplexColor) -{ - rTree.put("ThemeIndex", sal_Int16(rComplexColor.getThemeColorType())); - auto aTransformationsList = rTree.startArray("Transformations"); - - for (auto const& rTransformation : rComplexColor.getTransformations()) - { - std::string aType; - switch (rTransformation.meType) - { - case model::TransformationType::LumMod: - aType = "LumMod"; - break; - case model::TransformationType::LumOff: - aType = "LumOff"; - break; - case model::TransformationType::Tint: - aType = "Tint"; - break; - case model::TransformationType::Shade: - aType = "Shade"; - break; - default: - break; - } - if (!aType.empty()) - { - auto aChild = rTree.startStruct(); - rTree.put("Type", aType); - rTree.put("Value", rTransformation.mnValue); - } - } -} - -OString convertToJSON(model::ComplexColor const& rComplexColor) -{ - tools::JsonWriter aTree; - convertToJSONTree(aTree, rComplexColor); - return aTree.finishAndGetAsOString(); -} - -} // end model::theme - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/docmodel/source/theme/ColorSet.cxx b/docmodel/source/theme/ColorSet.cxx index a33750666a80..4dbf965257b5 100644 --- a/docmodel/source/theme/ColorSet.cxx +++ b/docmodel/source/theme/ColorSet.cxx @@ -49,6 +49,37 @@ Color ColorSet::resolveColor(model::ComplexColor const& rComplexColor) const return rComplexColor.applyTransformations(aColor); } +Color ColorSet::resolveOOXMLColor(model::ComplexColor const& rComplexColor) const +{ + auto eThemeType = rComplexColor.getThemeColorType(); + if (eThemeType == model::ThemeColorType::Unknown) + { + SAL_WARN("svx", "ColorSet::resolveOOXMLColor with ThemeColorType::Unknown"); + return COL_AUTO; + } + + Color aColor = getColor(eThemeType); + + // ComplexColor::applyTransformations() applies LumMod and LumOff as two + // separate RGB-HSL-RGB round-trips, but they must be combined into one + // call to get correct results (the intermediate round-trip can zero out + // saturation at boundary luminance values). + sal_Int16 nLumMod = 10'000; + sal_Int16 nLumOff = 0; + for (auto const& rTransform : rComplexColor.getTransformations()) + { + if (rTransform.meType == model::TransformationType::LumMod) + nLumMod = static_cast(rTransform.mnValue); + else if (rTransform.meType == model::TransformationType::LumOff) + nLumOff = static_cast(rTransform.mnValue); + } + + if (nLumMod != 10'000 || nLumOff != 0) + aColor.ApplyLumModOff(nLumMod, nLumOff); + + return aColor; +} + void ColorSet::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ColorSet")); diff --git a/docmodel/source/uno/UnoChartColorStyle.cxx b/docmodel/source/uno/UnoChartColorStyle.cxx index 2bf4d02cd743..503b0fafa7dd 100644 --- a/docmodel/source/uno/UnoChartColorStyle.cxx +++ b/docmodel/source/uno/UnoChartColorStyle.cxx @@ -14,12 +14,6 @@ using namespace css; namespace model::style { -uno::Reference -createXChartColorStyle(model::ColorStyleSet const& rColorStyle) -{ - return new UnoChartColorStyle(rColorStyle); -} - model::ColorStyleSet* getFromXChartColorStyle(uno::Reference const& rxColorStyle) { diff --git a/docmodel/source/uno/UnoChartStyle.cxx b/docmodel/source/uno/UnoChartStyle.cxx index d7e9b5019b63..d228cac32328 100644 --- a/docmodel/source/uno/UnoChartStyle.cxx +++ b/docmodel/source/uno/UnoChartStyle.cxx @@ -15,11 +15,6 @@ using namespace css; namespace model::style { -uno::Reference createXChartStyle(model::StyleSet const& rStyle) -{ - return new UnoChartStyle(rStyle); -} - model::StyleSet* getFromXChartStyle(uno::Reference const& rxStyle) { UnoChartStyle* pUnoChartStyle = static_cast(rxStyle.get()); diff --git a/docmodel/source/uno/UnoComplexColor.cxx b/docmodel/source/uno/UnoComplexColor.cxx index c5533009a7e0..65e30eed78c0 100644 --- a/docmodel/source/uno/UnoComplexColor.cxx +++ b/docmodel/source/uno/UnoComplexColor.cxx @@ -9,7 +9,6 @@ */ #include -#include using namespace css; @@ -17,11 +16,6 @@ sal_Int32 UnoComplexColor::getType() { return sal_Int32(maColor.getType()); } sal_Int32 UnoComplexColor::getThemeColorType() { return sal_Int32(maColor.getThemeColorType()); } -OUString UnoComplexColor::getRepresentation() -{ - return OStringToOUString(model::color::convertToJSON(maColor), RTL_TEXTENCODING_UTF8); -} - util::Color UnoComplexColor::resolveColor(uno::Reference const& /*xTheme*/) { return util::Color(maColor.getFinalColor()); diff --git a/docmodel/source/uno/UnoGradientTools.cxx b/docmodel/source/uno/UnoGradientTools.cxx index 172d4cf2efe8..f0b7bfb506be 100644 --- a/docmodel/source/uno/UnoGradientTools.cxx +++ b/docmodel/source/uno/UnoGradientTools.cxx @@ -55,8 +55,8 @@ css::awt::Gradient2 createUnoGradient2(basegfx::BGradient const& rGradient) // NOTE: All code after adapting to multi color gradients works // using the ColorSteps, so in principle Start/EndColor might // be either - // (a) ignored consequently everywhere or - // (b) be set/added consequently everywhere + // (a) ignored consistently everywhere or + // (b) be set/added consistently everywhere // since this is - in principle - redundant data. // Be aware that e.g. cases like DrawingML::EqualGradients // and others would have to be identified and adapted (!) @@ -68,7 +68,7 @@ css::awt::Gradient2 createUnoGradient2(basegfx::BGradient const& rGradient) // ColorSteps if these are not empty, assuming that these // already contain Start/EndColor. // In principle that redundancy and that it is conflict-free - // could even be checked and asserted, but consequently using + // could even be checked and asserted, but consistently using // (b) methodically should be safe. const basegfx::BColorStops& rColorStops = rGradient.GetColorStops(); aGradient2.StartColor = static_cast(::Color(rColorStops.front().getStopColor())); diff --git a/download.lst b/download.lst index 1fb8a91043c9..19a3655f643e 100644 --- a/download.lst +++ b/download.lst @@ -3,8 +3,8 @@ # There is a script solenv/bin/generate-flatpak-manifest.sh to substitute the variables, # so upgrading to a new version only requires changes in download.lst. -ABW_SHA256SUM := e763a9dc21c3d2667402d66e202e3f8ef4db51b34b79ef41f56cacb86dcd6eed -ABW_TARBALL := libabw-0.1.3.tar.xz +ABW_SHA256SUM := fa2685a3440da6e03a66a778480d93cb95f6064e4541e58e37397680760fd6a0 +ABW_TARBALL := libabw-0.1.4.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts @@ -14,13 +14,13 @@ ARGON2_TARBALL := phc-winner-argon2-20190702.tar.gz # so that git cherry-pick # will not run into conflicts # please repack the tarball using external/boost/repack_tarball.sh -BOOST_SHA256SUM := b1f3cd4a82b59dd66e02c2ebae6334df18043a050d2d8eb83d12ad88b95b5e86 -BOOST_TARBALL := boost_1_90_0.tar.xz +BOOST_SHA256SUM := 6010caf17a5742227b54f0c3f5a045d09e8abb981faf7770d445cd705dc26214 +BOOST_TARBALL := boost_1_92_0.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -BOX2D_SHA256SUM := d6b4650ff897ee1ead27cf77a5933ea197cbeef6705638dd181adc2e816b23c2 -BOX2D_TARBALL := box2d-2.4.1.tar.gz +BOX2D_SHA256SUM := fb6ef914b50f4312d7d921a600eabc12318bb3c55a0b8c0b90608fa4488ef2e4 +BOX2D_TARBALL := box2d-3.1.1.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -29,6 +29,11 @@ BREAKPAD_TARBALL := breakpad-b324760c7f53667af128a6b77b790323da04fcb9.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts +BROTLI_SHA256SUM := 816c96e8e8f193b40151dad7e8ff37b1221d019dbcb9c35cd3fadbfe6477dfec +BROTLI_TARBALL := brotli-1.2.0.tar.gz +# three static lines +# so that git cherry-pick +# will not run into conflicts BSH_SHA256SUM := 2248387ceaa319840434a3547a8b2fec12f95a8418ee039ce5ff5726053a139c BSH_TARBALL := bsh-2.1.1-src.zip # three static lines @@ -45,8 +50,8 @@ CAIRO_TARBALL := cairo-1.18.$(CAIRO_VERSION_MICRO).tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -CDR_SHA256SUM := ced677c8300b29c91d3004bb1dddf0b99761bf5544991c26c2ee8f427e87193c -CDR_TARBALL := libcdr-0.1.8.tar.xz +CDR_SHA256SUM := f7bb6abdd7f226820f288a93dd8d07759833c0250d9e202af90f9b312c4665a3 +CDR_TARBALL := libcdr-0.1.9.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts @@ -60,13 +65,13 @@ DRAGONBOX_TARBALL := dragonbox-1.1.3.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -FAST_FLOAT_SHA256SUM := b90b3a415e4410822f50c70bd4485cf2c5e6962c2b05cf0dc88045d8af959ccc -FAST_FLOAT_TARBALL := fast_float-8.2.4.tar.gz +FAST_FLOAT_SHA256SUM := 90485994d0fed61d0693e8dba32c464b0e8adf7f2e7c2efbf5bff0df5ef5b13f +FAST_FLOAT_TARBALL := fast_float-8.3.0.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -LIBCMIS_SHA256SUM := 1b5c2d7258ff93eb5f9958ff0e4dfd7332dc75a071bb717dde2217a26602a644 -LIBCMIS_TARBALL := libcmis-0.6.2.tar.xz +LIBCMIS_SHA256SUM := 5adb3781f374adf491103b2cb2dc290085150c9b7d097baf56d8ac35df84e792 +LIBCMIS_TARBALL := libcmis-0.6.3.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts @@ -80,13 +85,13 @@ CPPUNIT_TARBALL := cppunit-1.15.1.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -CURL_SHA256SUM := 4eb41489790d19e190d7ac7e18e82857cdd68af8f4e66b292ced562d333f11df -CURL_TARBALL := curl-8.19.0.tar.xz +CURL_SHA256SUM := f7ef3ae8a22e521f289803fe93543eb64c329b58aa73a9e224dfd915a2a5f4f7 +CURL_TARBALL := curl-8.22.0.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -EBOOK_SHA256SUM := 7e8d8ff34f27831aca3bc6f9cc532c2f90d2057c778963b884ff3d1e34dfe1f9 -EBOOK_TARBALL := libe-book-0.1.3.tar.xz +EBOOK_SHA256SUM := 104b7e791b6632745898e9b6a0037b7540235771a4d8c3bde2c764466ad912f1 +EBOOK_TARBALL := libe-book-0.1.4.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts @@ -111,8 +116,8 @@ ETONYEK_TARBALL := libetonyek-0.1.$(ETONYEK_VERSION_MICRO).tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -EXPAT_SHA256SUM := 1032dfef4ff17f70464827daa28369b20f6584d108bc36f17ab1676e1edd2f91 -EXPAT_TARBALL := expat-2.7.5.tar.xz +EXPAT_SHA256SUM := 656ae1cc8da3b4ea513bb4e254f33e6243938084c0ec6239da873376b09985a7 +EXPAT_TARBALL := expat-2.8.4.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts @@ -121,8 +126,8 @@ FIREBIRD_TARBALL := Firebird-3.0.13.33818-0.tar.bz2 # three static lines # so that git cherry-pick # will not run into conflicts -FONTCONFIG_SHA256SUM := 9f5cae93f4fffc1fbc05ae99cdfc708cd60dfd6612ffc0512827025c026fa541 -FONTCONFIG_TARBALL := fontconfig-2.17.1.tar.xz +FONTCONFIG_SHA256SUM := 4f7b554a38cdf78c033f666c8871f3749e14a094f65a07f630c91ed0b43d35e3 +FONTCONFIG_TARBALL := fontconfig-2.18.3.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts @@ -257,43 +262,8 @@ FONT_SCHEHERAZADE_TARBALL := Scheherazade-2.100.zip # three static lines # so that git cherry-pick # will not run into conflicts -FONT_AGDASIMA_TARBALL := Agdasima-2.002.zip -FONT_AGDASIMA_SHA256SUM := b4c17499f8bc183320ffdcf1f8491c778dd68a237adc056dc08e1fcb2da488f3 -# three static lines -# so that git cherry-pick -# will not run into conflicts -FONT_BACASIME_ANTIQUE_TARBALL := Bacasime_Antique-2.000.zip -FONT_BACASIME_ANTIQUE_SHA256SUM := 81127cebc97d4ee0b950c2bc2d6be0ed29abfe0d5988435eb9a39e382557250a -# three static lines -# so that git cherry-pick -# will not run into conflicts -FONT_BELANOSIMA_TARBALL := Belanosima-2.000.zip -FONT_BELANOSIMA_SHA256SUM := 9c30e9e7cdb0797b651113a77f6b789659b8d8598a466b2ba92754e9dec30449 -# three static lines -# so that git cherry-pick -# will not run into conflicts -FONT_CAPRASIMO_TARBALL := Caprasimo-1.001.zip -FONT_CAPRASIMO_SHA256SUM := f066d27cfc99b6601083be102d08b4039da8d2834e2795aabd890f16c6fd1b9b -# three static lines -# so that git cherry-pick -# will not run into conflicts -FONT_LUGRASIMO_TARBALL := Lugrasimo-1.001.zip -FONT_LUGRASIMO_SHA256SUM := db24dff31e8ddf6a113556c947a219f9534b072852e9ce2079a08c94854a7503 -# three static lines -# so that git cherry-pick -# will not run into conflicts -FONT_LUMANOSIMO_TARBALL := Lumanosimo-1.010.zip -FONT_LUMANOSIMO_SHA256SUM := d4545ad6afded9a55d9a7728cfc7453cf5637861db87aafe0a730676a0cb960f -# three static lines -# so that git cherry-pick -# will not run into conflicts -FONT_LUNASIMA_TARBALL := Lunasima-2.009.zip -FONT_LUNASIMA_SHA256SUM := 4302809cf4b95b481bec53de87484d919b391c90a518d065f6c775fd435a5393 -# three static lines -# so that git cherry-pick -# will not run into conflicts -FREEHAND_SHA256SUM := 0e422d1564a6dbf22a9af598535425271e583514c0f7ba7d9091676420de34ac -FREEHAND_TARBALL := libfreehand-0.1.2.tar.xz +FREEHAND_SHA256SUM := 350b10d24a76d7e8c8ae98b74c2d432a2c8ddec08935d09856d20b695a35e600 +FREEHAND_TARBALL := libfreehand-0.1.4.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts @@ -317,13 +287,18 @@ GPGME_TARBALL := gpgme-1.24.3.tar.bz2 # three static lines # so that git cherry-pick # will not run into conflicts -GRAPHITE_SHA256SUM := b8e892d8627c41888ff121e921455b9e2d26836978f2359173d19825da62b8fc -GRAPHITE_TARBALL := graphite2-minimal-1.3.14.tgz +GRAPHITE_SHA256SUM := 10cfc69a6f859ce875b9708d170b8222eba76cdb89b6dbb4ee1e375bc7242409 +GRAPHITE_TARBALL := graphite2-minimal-1.3.15.tgz # three static lines # so that git cherry-pick # will not run into conflicts -HARFBUZZ_SHA256SUM := d4aa312728136e3dc7c3cda47b871614ce0d12bbb19f9dcac2ea70de836dc307 -HARFBUZZ_TARBALL := harfbuzz-14.0.0.tar.xz +HARFBUZZ_SHA256SUM := 2357ed966c6ced7bfa720b0640c0231065af01158fbea215093ffa15aed44371 +HARFBUZZ_TARBALL := harfbuzz-14.4.0.tar.xz +# three static lines +# so that git cherry-pick +# will not run into conflicts +HIGHWAY_SHA256SUM := 36f672ab48ddb3c8555e9e89e16fe400cd7d16c6eb455a1a3d0c146a63ababdc +HIGHWAY_TARBALL := highway-1.4.0.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -332,13 +307,13 @@ HSQLDB_TARBALL := 17410483b5b5f267aa18b7e00b65e6e0-hsqldb_1_8_0.zip # three static lines # so that git cherry-pick # will not run into conflicts -HUNSPELL_SHA256SUM := 11ddfa39afe28c28539fe65fc4f1592d410c1e9b6dd7d8a91ca25d85e9ec65b8 -HUNSPELL_TARBALL := hunspell-1.7.2.tar.gz +HUNSPELL_SHA256SUM := 433274dac0619cb00c2e18b43a3dd3a9d50da5b5613fa9b5c21781e35dd76bc1 +HUNSPELL_TARBALL := hunspell-1.7.3.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -HYPHEN_SHA256SUM := 304636d4eccd81a14b6914d07b84c79ebb815288c76fe027b9ebff6ff24d5705 -HYPHEN_TARBALL := 5ade6ae2a99bc1e9e57031ca88d36dad-hyphen-2.8.8.tar.gz +HYPHEN_SHA256SUM := 783743daf477de8c4d16e3c74b4d2827377017718d8e17e2d9440210246f6abe +HYPHEN_TARBALL := 442b985e604f8143a5a0e7bacd6b2e40-hyphen-2.8.9.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -390,13 +365,13 @@ LIBJPEG_TURBO_TARBALL := libjpeg-turbo-3.1.4.1.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -LANGTAGREG_SHA256SUM := 9b008d21f97bbf37c5aefd07805ff5500524bccbe8c39d623e184b1ed425ff39 -LANGTAGREG_TARBALL := language-subtag-registry-2025-08-25.tar.bz2 +LANGTAGREG_SHA256SUM := 48293d95a13372f3e5bae04890d7d54ef4168b2469060e8e49cf60461cfc616f +LANGTAGREG_TARBALL := language-subtag-registry-2026-08-08.tar.bz2 # three static lines # so that git cherry-pick # will not run into conflicts -LCMS2_SHA256SUM := ee67be3566f459362c1ee094fde2c159d33fa0390aa4ed5f5af676f9e5004347 -LCMS2_TARBALL := lcms2-2.18.tar.gz +LCMS2_SHA256SUM := bfc54f7bab59fbc921012014a8032e4cba4abd46db47d46b76416a8c0b2815c8 +LCMS2_TARBALL := lcms2-2.19.1.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -415,18 +390,23 @@ LIBEOT_TARBALL := libeot-0.01.tar.bz2 # three static lines # so that git cherry-pick # will not run into conflicts -LIBEXTTEXTCAT_SHA256SUM := df0a59d413a5b202573d8d4f5159e33a8538da4f8e8e60979facc64d6290cebd -LIBEXTTEXTCAT_TARBALL := libexttextcat-3.4.7.tar.xz +LIBEXTTEXTCAT_SHA256SUM := 93eb89fd4fc8f565806354e100e778b3ac9a24e5fc04c24e6a83fb1e9b6c9d59 +LIBEXTTEXTCAT_TARBALL := libexttextcat-3.4.8.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -LIBFFI_SHA256SUM := f3a3082a23b37c293a4fcd1053147b371f2ff91fa7ea1b2a52e335676bac82dc -LIBFFI_TARBALL := libffi-3.5.2.tar.gz +LIBFFI_SHA256SUM := 7da3e2d9a171eb0a038f592ecad3ff2bb2550f3496d87b3b29ad0cf4430c0db4 +LIBFFI_TARBALL := libffi-3.8.0.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -LIBGPGERROR_SHA256SUM := a19bc5087fd97026d93cb4b45d51638d1a25202a5e1fbc3905799f424cfa6134 -LIBGPGERROR_TARBALL := libgpg-error-1.59.tar.bz2 +LIBGPGERROR_SHA256SUM := 7a85413f2bc354f4f8aa832b718af122e48965e9e0eb9012ee659c13c6385c93 +LIBGPGERROR_TARBALL := libgpg-error-1.61.tar.bz2 +# three static lines +# so that git cherry-pick +# will not run into conflicts +LIBJXL_SHA256SUM := ab38928f7f6248e2a98cc184956021acb927b16a0dee71b4d260dc040a4320ea +LIBJXL_TARBALL := libjxl-0.11.2.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -450,13 +430,13 @@ LIBWEBP_TARBALL := libwebp-1.6.0.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -XMLSEC_SHA256SUM := a631c8cd7a6b86e6adb9f5b935d45a9cf9768b3cb090d461e8eb9d043cf9b62f -XMLSEC_TARBALL := xmlsec1-1.3.9.tar.gz +XMLSEC_SHA256SUM := 24045199af12d93fe5fdbbbf7e386e823e4842071e9432e2b90ac108b889a923 +XMLSEC_TARBALL := xmlsec1-1.3.12.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -LIBXML_SHA256SUM := c8b9bc81f8b590c33af8cc6c336dbff2f53409973588a351c95f1c621b13d09d -LIBXML_VERSION_MICRO := 2 +LIBXML_SHA256SUM := 98087fd181d9070724f3fbc65c7377db03038eb92bd882374daff44940138821 +LIBXML_VERSION_MICRO := 4 LIBXML_TARBALL := libxml2-2.15.$(LIBXML_VERSION_MICRO).tar.xz # three static lines # so that git cherry-pick @@ -467,23 +447,18 @@ LIBXSLT_TARBALL := libxslt-1.1.$(LIBXSLT_VERSION_MICRO).tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -LPSOLVE_SHA256SUM := 171816288f14215c69e730f7a4f1c325739873e21f946ff83884b350574e6695 -LPSOLVE_TARBALL := 26b3e95ddf3d9c077c480ea45874b3b8-lp_solve_5.5.tar.gz +LXML_SHA256SUM := ba96ae44888e0185281e937633a743ea90d5a196c6000f82565ebb0580012d40 +LXML_TARBALL := lxml-6.1.1.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -LXML_SHA256SUM := cd79f3367bd74b317dda655dc8fcfa304d9eb6e4fb06b7168c5cf27f96e0cd62 -LXML_TARBALL := lxml-6.0.2.tar.gz +LZMA_SHA256SUM := 0014c7886930454fe8bd4228665b51af55eeae560ea135c9c4cd33f55b2591d9 +LZMA_TARBALL := xz-5.8.4.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -LZMA_SHA256SUM := 3d3a1b973af218114f4f889bbaa2f4c037deaae0c8e815eec381c3d546b974a0 -LZMA_TARBALL := xz-5.8.3.tar.gz -# three static lines -# so that git cherry-pick -# will not run into conflicts -MARIADB_CONNECTOR_C_SHA256SUM := 156aed3b49f857d0ac74fb76f1982968bcbfd8382da3f5b6ae71f616729920d7 -MARIADB_CONNECTOR_C_TARBALL := mariadb-connector-c-3.4.8-src.tar.gz +MARIADB_CONNECTOR_C_SHA256SUM := a84bba97e59b6a322637a189964d4fd72bd8d92f2d22a9f8d6a5f0657c821e97 +MARIADB_CONNECTOR_C_TARBALL := mariadb-connector-c-3.4.9-src.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -502,24 +477,24 @@ MESON_TARBALL := meson-1.8.3.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -MSPUB_SHA256SUM := ef36c1a1aabb2ba3b0bedaaafe717bf4480be2ba8de6f3894be5fd3702b013ba -MSPUB_TARBALL := libmspub-0.1.4.tar.xz +MSPUB_SHA256SUM := 3671095f5a10bee8a755052a30576952c5b16d8b0f2ba9f2fb998338c18cb119 +MSPUB_TARBALL := libmspub-0.1.5.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -MWAW_SHA256SUM := a1a39ffcea3ff2a7a7aae0c23877ddf4918b554bf82b0de5d7ce8e7f61ea8e32 -MWAW_VERSION_MICRO := 22 +MWAW_SHA256SUM := ac3590f691a2904eb8c7dc8b757b8a29f125f592449e421459ae8fa928b399eb +MWAW_VERSION_MICRO := 23 MWAW_TARBALL := libmwaw-0.3.$(MWAW_VERSION_MICRO).tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -MYTHES_SHA256SUM := 19279f70707bbe5ffa619f2dc319f888cec0c4a8d339dc0a21330517bd6f521d -MYTHES_TARBALL := mythes-1.2.5.tar.xz +MYTHES_SHA256SUM := 97bd2ba5738aebdba1bc31f30f1be42f1404386c94105ad5990d839a1311c8a5 +MYTHES_TARBALL := mythes-1.2.6.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -NSS_SHA256SUM := d7c18446797a8b1f20524cb20ef32feba043c12077ee1a772c63f344b9435c36 -NSS_TARBALL := nss-3.122-with-nspr-4.38.2.tar.gz +NSS_SHA256SUM := d389064d5e5ef09d597f8ae8dadc066f71e97b982bd7418b835686425fc3a189 +NSS_TARBALL := nss-3.129-with-nspr-4.39.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -549,13 +524,13 @@ ONLINEUPDATE_TARBALL := onlineupdate-c003be8b9727672e7d30972983b375f4c200233f-2. # three static lines # so that git cherry-pick # will not run into conflicts -OPENLDAP_SHA256SUM := d693b49517a42efb85a1a364a310aed16a53d428d1b46c0d31ef3fba78fcb656 -OPENLDAP_TARBALL := openldap-2.6.13.tgz +OPENLDAP_SHA256SUM := 253db80f301258ea69cda1184766d57395b836aaabf41157eb0316eb0fac1341 +OPENLDAP_TARBALL := openldap-2.7.1.tgz # three static lines # so that git cherry-pick # will not run into conflicts -OPENSSL_SHA256SUM := b28c91532a8b65a1f983b4c28b7488174e4a01008e29ce8e69bd789f28bc2a89 -OPENSSL_TARBALL := openssl-3.5.5.tar.gz +OPENSSL_SHA256SUM := a8f84a39918ec6415ce765d9b429d313ba97b8143169c172e734b9514464f5b2 +OPENSSL_TARBALL := openssl-3.5.8.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -569,13 +544,13 @@ PAGEMAKER_TARBALL := libpagemaker-0.0.4.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -PDFIUM_SHA256SUM := 8de122fff74461770c9ca93ca3e6ca946b077f9110d562f40815e187e1255774 -PDFIUM_TARBALL := pdfium-7681.tar.bz2 +PDFIUM_SHA256SUM := 0340b2fca57cecdf6e2e0366129a3340f6764c132cb090f57db96d9f0f349855 +PDFIUM_TARBALL := pdfium-7988.tar.bz2 # three static lines # so that git cherry-pick # will not run into conflicts -AFDKO_SHA256SUM := 5feed7c2468e25b25fce0479c04af07f4ed2680bc9251bb4c4aef9ec2fba5720 -AFDKO_TARBALL := afdko-4.0.3.tar.gz +AFDKO_SHA256SUM := 083b504a1cd865e8bfbb42134a34318ce42ef5130daebfc5b0e2f2fb444326c5 +AFDKO_TARBALL := afdko-5.0.1.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -589,35 +564,45 @@ PIXMAN_TARBALL := pixman-0.46.4.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -LIBPNG_SHA256SUM := f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 -LIBPNG_TARBALL := libpng-1.6.56.tar.xz +LIBPNG_SHA256SUM := 28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 +LIBPNG_TARBALL := libpng-1.6.58.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -LIBTIFF_SHA256SUM := b92017489bdc1db3a4c97191aa4b75366673cb746de0dce5d7a749d5954681ba -LIBTIFF_TARBALL := tiff-4.7.1.tar.xz +LIBTIFF_SHA256SUM := 4996f0c4f93094719b1ca5c6279b20e588773ba8a247533e486416fb662ddb88 +LIBTIFF_TARBALL := tiff-4.7.2.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -POPPLER_SHA256SUM := b0955163114af96bc0106f68cb24daf973a629462453d8b82775f81b0d4e0693 -POPPLER_TARBALL := poppler-26.04.0.tar.xz +POPPLER_SHA256SUM := dc906e68cea698109706ac6aa3d2c9d4512fcfcac42d90b8afcda486d1b9abd0 +POPPLER_TARBALL := poppler-26.08.0.tar.xz POPPLER_DATA_SHA256SUM := c835b640a40ce357e1b83666aabd95edffa24ddddd49b8daff63adb851cdab74 POPPLER_DATA_TARBALL := poppler-data-0.4.12.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -POSTGRESQL_SHA256SUM := ae14f24c14727e0b2ded1c5553031666099bd1054db3ef44bfa6e2bd6d554a56 -POSTGRESQL_TARBALL := postgresql-15.17.tar.bz2 +POSTGRESQL_SHA256SUM := e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89 +POSTGRESQL_TARBALL := postgresql-15.19.tar.bz2 # three static lines # so that git cherry-pick # will not run into conflicts -PYTHON_SHA256SUM := 2a84cd31dd8d8ea8aaff75de66fc1b4b0127dd5799aa50a64ae9a313885b4593 -PYTHON_TARBALL := Python-3.13.12.tar.xz +PYTHON_SHA256SUM := 1e66a7945a48390ee4c2a4268a0e4185884059a13c4aab6d148aa208deea4a76 +PYTHON_TARBALL := Python-3.13.15.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -QXP_SHA256SUM := e137b6b110120a52c98edd02ebdc4095ee08d0d5295a94316a981750095a945c -QXP_TARBALL := libqxp-0.0.2.tar.xz +QUICKJS_SHA256SUM := 866bad1e2f148b6f8144a4a3d4c3f8a0754495a6920fe56a7dd698cf0ad27f65 +QUICKJS_TARBALL := quickjs-0.16.2-amalgam.zip +# three static lines +# so that git cherry-pick +# will not run into conflicts +PYTHON_BOOTSTRAP_SHA256SUM := 406856be971d957e0bee7a5cefe20a5ec78d70a495e9e33cd0e53d31faec049d +PYTHON_BOOTSTRAP_TARBALL := python.3.12.8.nupkg +# three static lines +# so that git cherry-pick +# will not run into conflicts +QXP_SHA256SUM := 4687a9cc96c32d7406e5072c4da150fca696c563e5cde62b024f82fa53d32332 +QXP_TARBALL := libqxp-0.0.3.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts @@ -636,14 +621,14 @@ REDLAND_TARBALL := e5be03eda13ef68aabab6e42aa67715e-redland-1.0.17.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -REVENGE_SHA256SUM := 5892ca6796f7a2a93d580832e907e849b19d980b40d326a283b18877ab6de0c5 -REVENGE_VERSION_MICRO := 5 +REVENGE_SHA256SUM := 52a65e904d255dbdd97a8b7bb28d6574e14f999eb01416aff004502406d0904d +REVENGE_VERSION_MICRO := 6 REVENGE_TARBALL := librevenge-0.0.$(REVENGE_VERSION_MICRO).tar.bz2 # three static lines # so that git cherry-pick # will not run into conflicts -MD4C_SHA256SUM := 55d0111d48fb11883aaee91465e642b8b640775a4d6993c2d0e7a8092758ef21 -MD4C_TARBALL := md4c-release-0.5.2.tar.gz +MD4C_SHA256SUM := 353c346f376b87c954a13f3415ede2d51264cc61dc5abcd38ff1d2aa0d059b9e +MD4C_TARBALL := md4c-release-0.5.3.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts @@ -652,18 +637,18 @@ RHINO_TARBALL := rhino-1.7.15.1.zip # three static lines # so that git cherry-pick # will not run into conflicts -SKIA_SHA256SUM := 1c64e5ea66040e38689e163d9a64b7aa2d3de7225c2bf21db422329f6825489a -SKIA_TARBALL := skia-m147-fd139e79fd4553ba16556c1bca6c0f4dd9bc6fa5.tar.xz +SKIA_SHA256SUM := 08458913d3076a7c1c0a1550f472b3aa5df811b2f08c7d24e65fb4d2ca3f14f4 +SKIA_TARBALL := skia-m149-9bb16a741cdbcbde46a0d4caf8ac73f4d07a89e2.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -SQLITE3_SHA256SUM := 45d0fea15971dd1300e5b509f48ca134621e10d9297713b64618fbca21b325fa -SQLITE3_TARBALL := sqlite-amalgamation-3520000.zip +SQLITE3_SHA256SUM := 1e71ddf93849c6a6ecf58b827c0692073d2dd7ee40196158068f7b29f422e87d +SQLITE3_TARBALL := sqlite-amalgamation-3530400.zip # three static lines # so that git cherry-pick # will not run into conflicts -STAROFFICE_SHA256SUM := f94fb0ad8216f97127bedef163a45886b43c62deac5e5b0f5e628e234220c8db -STAROFFICE_VERSION_MICRO := 7 +STAROFFICE_SHA256SUM := bbca92882e96c55bd1527670866d6bc7529ccb12786da55a2398b60a063378da +STAROFFICE_VERSION_MICRO := 8 STAROFFICE_TARBALL := libstaroffice-0.0.$(STAROFFICE_VERSION_MICRO).tar.xz # three static lines # so that git cherry-pick @@ -673,8 +658,8 @@ TWAIN_DSM_TARBALL := twaindsm_2.4.1.orig.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -VISIO_SHA256SUM := 9e9eff75112d4d92d92262ad7fc2599c21e26f8fc5ba54900efdc83c0501e472 -VISIO_TARBALL := libvisio-0.1.10.tar.xz +VISIO_SHA256SUM := 2a6efd40b6d9dbcb70fba3be53112366882ba97b57151df3698dfa478c8d8dd3 +VISIO_TARBALL := libvisio-0.1.11.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts @@ -726,8 +711,8 @@ ZXCVBN_C_TARBALL := zxcvbn-c-2.6.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -ZXING_SHA256SUM := e957f13e2ad4e31badb3d9af3f6ba8999a3ca3c9cc4d6bafc98032f9cce1a090 -ZXING_TARBALL := zxing-cpp-3.0.2.tar.gz +ZXING_SHA256SUM := c3c02c29c0b519de7bd4e25b376e606e87f0761befd1282815642a2246613d14 +ZXING_TARBALL := zxing-cpp-3.1.1.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts diff --git a/drawinglayer/CppunitTest_drawinglayer_processors.mk b/drawinglayer/CppunitTest_drawinglayer_processors.mk index 627809b814a8..789f878f5bb9 100644 --- a/drawinglayer/CppunitTest_drawinglayer_processors.mk +++ b/drawinglayer/CppunitTest_drawinglayer_processors.mk @@ -16,6 +16,7 @@ $(eval $(call gb_CppunitTest_use_api,drawinglayer_processors,\ $(eval $(call gb_CppunitTest_use_libraries,drawinglayer_processors, \ basegfx \ + comphelper \ $(if $(ENABLE_WASM_STRIP_CANVAS),,cppcanvas) \ cppu \ cppuhelper \ @@ -28,6 +29,7 @@ $(eval $(call gb_CppunitTest_use_libraries,drawinglayer_processors, \ tl \ unotest \ svt \ + utl \ )) $(eval $(call gb_CppunitTest_use_externals,drawinglayer_processors,\ @@ -50,6 +52,7 @@ $(eval $(call gb_CppunitTest_use_components,drawinglayer_processors,\ i18npool/util/i18npool \ ucb/source/core/ucb1 \ ucb/source/ucp/file/ucpfile1 \ + framework/util/fwk \ )) $(eval $(call gb_CppunitTest_use_configuration,drawinglayer_processors)) diff --git a/drawinglayer/README.md b/drawinglayer/README.md index 9eb7057d2a37..b53a9470d02d 100644 --- a/drawinglayer/README.md +++ b/drawinglayer/README.md @@ -34,7 +34,7 @@ A stripped down version with extended comments: pProcessor2D->process(aSequence); pProcessor2D.reset(); - // Obtain the bitmap that was rendered from the virtual device, to re-use + // Obtain the bitmap that was rendered from the virtual device, to reuse // it in the widget. aRetval = aVirtualDevice.GetBitmap(Point(0, 0), aVirtualDevice.GetOutputSizePixel()); @@ -94,8 +94,8 @@ For example, in `emfio/qa/cppunit/emf/EmfImportTest.cxx`, one can write: Primitive2DSequence aSequence = parseEmf(u"emfio/qa/cppunit/wmf/data/stockobject.emf"); drawinglayer::Primitive2dXmlDump dumper; Primitive2DContainer aContainer(aSequence); - dumper.dump(aContainer, "/tmp/drawyinglayer.xml"); + dumper.dump(aContainer, "/tmp/drawinglayer.xml"); -Then, after invoking `make CppunitTest_emfio_emf`, `/tmp/drawyinglayer.xml` will +Then, after invoking `make CppunitTest_emfio_emf`, `/tmp/drawinglayer.xml` will be the dump of the drawinglayer primitives used to draw the emf file in LibreOffice. The top level tag will be . diff --git a/drawinglayer/inc/primitive2d/texteffectprimitive2d.hxx b/drawinglayer/inc/primitive2d/texteffectprimitive2d.hxx index 8512f64114af..567063f850a6 100644 --- a/drawinglayer/inc/primitive2d/texteffectprimitive2d.hxx +++ b/drawinglayer/inc/primitive2d/texteffectprimitive2d.hxx @@ -50,8 +50,8 @@ private: double mfDirection; TextEffectStyle2D meTextEffectStyle2D; - /** the last used object to view transformtion used from getDecomposition - for decide buffering + /** the last used object to view transformation used from getDecomposition + to decide buffering */ basegfx::B2DHomMatrix maLastObjectToViewTransformation; @@ -90,6 +90,6 @@ public: const geometry::ViewInformation2D& rViewInformation) const override; }; -} // end of namespace primitive2d::drawinglayer +} // end of namespace drawinglayer::primitive2d /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/qa/unit/vclmetafileprocessor2d.cxx b/drawinglayer/qa/unit/vclmetafileprocessor2d.cxx index a6ba7a1172a2..7ce519ae1671 100644 --- a/drawinglayer/qa/unit/vclmetafileprocessor2d.cxx +++ b/drawinglayer/qa/unit/vclmetafileprocessor2d.cxx @@ -16,14 +16,23 @@ #include #include #include +#include +#include #include #include +#include #include #include +#include #include #include #include +#include +#include +#include + +#include #include using namespace drawinglayer; @@ -146,8 +155,208 @@ public: CPPUNIT_ASSERT_GREATER(100, nonWhiteCount); } + /// Export a hyperlink field to a PDF in rTempFile + void exportLinkFieldToPDF(std::vector>& rValues, + utl::TempFileNamed& rTempFile) + { + // Impress presentation mode first draws the slide to a metafile. + GDIMetaFile metafile; + // I got these values by adding debug output to cppcanvas::internal::ImplRenderer::ImplRenderer(). + metafile.SetPrefMapMode(MapMode(MapUnit::Map100thMM)); + metafile.SetPrefSize(Size(14548, 3350)); + ScopedVclPtrInstance metadevice; + + // Clickable links are only created during PDF export + vcl::PDFExtOutDevData aPDFExtOutDevData(*metadevice); + aPDFExtOutDevData.SetIsExportBookmarks(true); + aPDFExtOutDevData.SetIsExportTaggedPDF(true); + metadevice->SetExtOutDevData(&aPDFExtOutDevData); + + vcl::pdf::PDFWriter::PDFWriterContext aContext; + aContext.Version = vcl::pdf::PDFWriter::PDFVersion::PDF_1_7; + aContext.Tagged = true; + aContext.PDFDocumentMode = vcl::pdf::PDFWriter::ModeDefault; + aContext.PDFDocumentAction = vcl::pdf::PDFWriter::ActionDefault; + aContext.PageLayout = vcl::pdf::PDFWriter::DefaultLayout; + + aContext.URL = rTempFile.GetURL(); + + rtl::Reference xEnc; + vcl::pdf::PDFWriter aPDFWriter(aContext, xEnc); + aPDFWriter.NewPage(14548, 3350); + + metafile.Record(metadevice); + drawinglayer::geometry::ViewInformation2D view; + + // Set a transform to ensure processed link honors transforms + const basegfx::B2DHomMatrix aMappingTransform( + basegfx::utils::createTranslateB2DHomMatrix(500, 500)); + view.setObjectTransformation(aMappingTransform); + + std::unique_ptr processor( + processor2d::createProcessor2DFromOutputDevice(*metadevice, view)); + CPPUNIT_ASSERT(processor); + + // Create a child primitive2d that holds the bounding box for the link + drawinglayer::primitive2d::Primitive2DContainer aSeq(1); + attribute::LineAttribute lineAttributes( + basegfx::BColor(0.047058823529411764, 0.19607843137254902, 0.17254901960784313), 35, + basegfx::B2DLineJoin::Miter, css::drawing::LineCap_ROUND); + basegfx::B2DPolygon aPolygon = { { -10, 65 }, { 539, 368 } }; + aSeq[0] = new drawinglayer::primitive2d::PolygonStrokePrimitive2D(aPolygon, lineAttributes); + + // The primitive2d for the link itself + rtl::Reference fieldPrimitive( + new primitive2d::TextHierarchyFieldPrimitive2D( + std::move(aSeq), drawinglayer::primitive2d::FIELD_TYPE_URL, &rValues)); + + primitive2d::Primitive2DContainer primitives; + primitives.push_back(fieldPrimitive); + + processor->process(primitives); + + metafile.Stop(); + metafile.WindStart(); + + // Match bookmarks with their link URL; usually done by each module's + // rendering code, eg ScModelObj::render() and such + std::vector& rBookmarks = aPDFExtOutDevData.GetBookmarks(); + CPPUNIT_ASSERT(!rBookmarks.empty()); + for (const auto& rBookmark : rBookmarks) + aPDFExtOutDevData.SetLinkURL(rBookmark.nLinkId, rBookmark.aBookmark); + + aPDFExtOutDevData.PlayGlobalActions(aPDFWriter); + CPPUNIT_ASSERT(aPDFWriter.Emit()); + CPPUNIT_ASSERT(aPDFWriter.GetErrors().empty()); + } + + std::optional exportLinkContents(std::vector>& rValues) + { + utl::TempFileNamed aTempFile; + aTempFile.EnableKillingFile(); + exportLinkFieldToPDF(rValues, aTempFile); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(aTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size()); + + auto pAnnots + = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + CPPUNIT_ASSERT_EQUAL(size_t(1), pAnnots->GetElements().size()); + + auto pAnnotRef = dynamic_cast(pAnnots->GetElements()[0]); + CPPUNIT_ASSERT(pAnnotRef); + vcl::filter::PDFObjectElement* pAnnot = pAnnotRef->LookupObject(); + CPPUNIT_ASSERT(pAnnot); + + auto pContents + = dynamic_cast(pAnnot->Lookup("Contents"_ostr)); + if (!pContents) + return std::nullopt; + + return vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pContents); + } + + // Test that a link's clickable bounding box is correctly transformed + void tdf169919_link_bounding_box_transform() + { + OString aLinkUrl("http://libreoffice.org"_ostr); + std::vector> aValues{ + { u"URL"_ustr, OUString::fromUtf8(aLinkUrl) }, { u"AltText"_ustr, u"link"_ustr } + }; + + utl::TempFileNamed aTempFile; + aTempFile.EnableKillingFile(); + exportLinkFieldToPDF(aValues, aTempFile); + + SvStream* pStream = aTempFile.GetStream(StreamMode::READ); + CPPUNIT_ASSERT(pStream->TellEnd() > 5000); + + bool found = false; + OString sLine; + OString aRectStart("/Rect["_ostr); + while (pStream->ReadLine(sLine)) + { + if (sLine.isEmpty()) + continue; + + // Look for a line like + // <> + // and parse out the Rect[] bits + sal_Int32 nLinkIdx = sLine.indexOf(aLinkUrl); + if (nLinkIdx > 0 && sLine.startsWith("<> aNamed{ { u"URL"_ustr, aURL }, + { u"Representation"_ustr, + u"the link text"_ustr }, + { u"AltText"_ustr, u"the name"_ustr } }; + std::optional oContents = exportLinkContents(aNamed); + CPPUNIT_ASSERT(oContents.has_value()); + CPPUNIT_ASSERT_EQUAL(u"the name"_ustr, *oContents); + + // Without a Name, the text shown in the document is used + std::vector> aUnnamed{ + { u"URL"_ustr, aURL }, { u"Representation"_ustr, u"the link text"_ustr } + }; + oContents = exportLinkContents(aUnnamed); + + // Without the fix, no Contents entry was written at all + CPPUNIT_ASSERT(oContents.has_value()); + CPPUNIT_ASSERT_EQUAL(u"the link text"_ustr, *oContents); + + // Without a Name and without text, the URL is used + std::vector> aBare{ { u"URL"_ustr, aURL } }; + oContents = exportLinkContents(aBare); + CPPUNIT_ASSERT(oContents.has_value()); + CPPUNIT_ASSERT_EQUAL(aURL, *oContents); + } + CPPUNIT_TEST_SUITE(VclMetaFileProcessor2DTest); CPPUNIT_TEST(tdf136957_draw_impress_dotted_line); + CPPUNIT_TEST(tdf169919_link_bounding_box_transform); + CPPUNIT_TEST(testLinkContentsFallback); CPPUNIT_TEST_SUITE_END(); }; diff --git a/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx b/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx index 7d73cdbee4d1..b5183c2f77e3 100644 --- a/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx @@ -41,7 +41,7 @@ namespace drawinglayer::primitive2d if(rViewInformation.getViewport().isEmpty()) return nullptr; - // create decompose geometry + // create decomposition geometry const basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(rViewInformation.getViewport())); if (getTransparency() <= 0.0) diff --git a/drawinglayer/source/primitive2d/baseprimitive2d.cxx b/drawinglayer/source/primitive2d/baseprimitive2d.cxx index a2e0eaf6b6ba..074c9b57766e 100644 --- a/drawinglayer/source/primitive2d/baseprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/baseprimitive2d.cxx @@ -40,7 +40,7 @@ bool BasePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const namespace { -// Visitor class to get the B2D range from a tree of Primitive2DReference's +// Visitor class to get the B2D range from a tree of Primitive2DReferences // class B2DRangeVisitor : public Primitive2DDecompositionVisitor { diff --git a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx index 58b1a55ed84d..8356ea6aabac 100644 --- a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx +++ b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx @@ -349,7 +349,8 @@ namespace drawinglayer::primitive2d case Disposal::Previous: { maVirtualDevice->DrawBitmap(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmap); - Bitmap aExpandVisibilityMask(rAnimationFrame.maBitmap.CreateAlphaMask().GetBitmap(), rAnimationFrame.maBitmap.CreateAlphaMask()); + AlphaMask aAlphaMask(rAnimationFrame.maBitmap.CreateAlphaMask()); + Bitmap aExpandVisibilityMask(aAlphaMask.GetBitmap(), aAlphaMask); maVirtualDeviceMask->DrawBitmap(rAnimationFrame.maPositionPixel, aExpandVisibilityMask); break; } diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx index a0a1550d1b66..b82360bb97a1 100644 --- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx @@ -25,7 +25,11 @@ #include #include #include +#include +#include #include +#include +#include using namespace com::sun::star; @@ -133,4 +137,17 @@ namespace drawinglayer::primitive2d } // end of namespace +extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportWMF(SvStream& rStream) +{ + GDIMetaFile aGDIMetaFile; + (void)ReadWindowMetafile(rStream, aGDIMetaFile); + + rtl::Reference xMetafile( + new drawinglayer::primitive2d::MetafilePrimitive2D(basegfx::B2DHomMatrix(), aGDIMetaFile)); + drawinglayer::geometry::ViewInformation2D aViewInformation; + drawinglayer::primitive2d::Primitive2DContainer aContainer; + xMetafile->get2DDecomposition(aContainer, aViewInformation); + return true; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx index 329911541d4e..05d3c84a381c 100644 --- a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx @@ -407,7 +407,7 @@ PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(basegfx::B2DPolygon aPolygon, , maStrokeAttribute(std::move(aStrokeAttribute)) , maBufferedRange() { - // MM01: keep these - these are no curve-decompposers but just checks + // MM01: keep these - these are no curve-decomposers but just checks // simplify curve segments: moved here to not need to use it // at VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect maPolygon = basegfx::utils::simplifyCurveSegments(maPolygon); @@ -419,7 +419,7 @@ PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(basegfx::B2DPolygon aPolygon, , maLineAttribute(rLineAttribute) , maBufferedRange() { - // MM01: keep these - these are no curve-decompposers but just checks + // MM01: keep these - these are no curve-decomposers but just checks // simplify curve segments: moved here to not need to use it // at VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect maPolygon = basegfx::utils::simplifyCurveSegments(maPolygon); @@ -468,7 +468,7 @@ PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewIn // all directions and the rounded cap needs the same grow in all directions independent // from its orientation. Unfortunately this is not the case for drawing::LineCap_SQUARE - // NOTE: I thought about using [sqrt(2) * 0.5] a a factor for LineCap_SQUARE and not + // NOTE: I thought about using [sqrt(2) * 0.5] as a factor for LineCap_SQUARE and not // set bUseDecomposition. I even tried that it works. Then an auto-test failing showed // not only that view-dependent stuff needs to be considered (what is done for the // hairline case below), *BUT* also e.g. conversions to PNG/exports use the B2DRange @@ -500,7 +500,7 @@ PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewIn // and is correct when it already exists since the values the decomposition is // based on cannot change. // (3) If this *is* done (like it was here) and the Primitive is derived from - // BufferedDecompositionPrimitive2D and thus buffers it's decomposition, + // BufferedDecompositionPrimitive2D and thus buffers its decomposition, // the risk is that in this case the *wrong* decomposition will be used by // other PrimitiveProcessors. Maybe not by the VclPixelProcessor2D/VclProcessor2D // since it handles this primitive directly - not even sure for all cases. @@ -508,7 +508,7 @@ PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewIn // decomposition, and as an error, a non-stroked line will be painted/used. // (4) The B2DRange is not strictly defined as minimal bound for the geometry, // but it should be as small/tight as possible. Making it larger risks more - // area to be invalidated (repaint) and processed (all geometric stuff,l may + // area to be invalidated (repaint) and processed (all geometric stuff, may // include future and existing exports to other formats which are or will be // implemented as PrimitiveProcessor). It is easy to imagine cases with much // too large B2DRange - a line with a pattern that would solve to a single @@ -537,7 +537,7 @@ PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewIn // Thus here I would use (c): It accepts the disadvantages of (4) over speed, but // avoids the errors/problems from (1-4). // Additional argument for this: The hairline case below *also* uses the full - // B2DRange of the polygon, ignoring an evtl. stroke, so (4) applies + // B2DRange of the polygon, ignoring an eventual stroke, so (4) applies if (!getStrokeAttribute().isDefault()) { // only do this if StrokeAttribute is used, else recursion may happen (!) diff --git a/drawinglayer/source/primitive2d/softedgeprimitive2d.cxx b/drawinglayer/source/primitive2d/softedgeprimitive2d.cxx index 8529a967b44b..54842f7a6454 100644 --- a/drawinglayer/source/primitive2d/softedgeprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/softedgeprimitive2d.cxx @@ -203,16 +203,15 @@ void SoftEdgePrimitive2D::create2DDecomposition( fScale = (fScaleX + fScaleY) * 0.5; } + assert(aBitmap.HasAlpha()); + auto [aColor, aMask] = aBitmap.SplitIntoColorAndAlpha(); // Get the Alpha and use as base to blur and apply the effect - AlphaMask aMask(aBitmap.CreateAlphaMask()); - if (aMask.IsEmpty()) // There is no mask, fully opaque - break; AlphaMask blurMask(drawinglayer::primitive2d::ProcessAndBlurAlphaMask( aMask, -fDiscreteSoftRadius * fScale, fDiscreteSoftRadius * fScale, 0)); aMask.BlendWith(blurMask); // The end result is the original bitmap with blurred 8-bit alpha mask - Bitmap result(aBitmap.CreateColorBitmap(), aMask); + Bitmap result(aColor, aMask); #ifdef DBG_UTIL static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore diff --git a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx index 5784e8ec9e1b..f44ff3e9cdef 100644 --- a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx @@ -32,6 +32,7 @@ #include #include #include +#include using namespace com::sun::star; @@ -379,14 +380,12 @@ namespace drawinglayer::primitive2d if(!maMirroredGradientEntries.empty() || getGradientEntries().empty()) return; - const sal_uInt32 nCount(getGradientEntries().size()); maMirroredGradientEntries.clear(); - maMirroredGradientEntries.reserve(nCount); + maMirroredGradientEntries.reserve(getGradientEntries().size()); - for(sal_uInt32 a(0); a < nCount; a++) + const SvgGradientEntryVector& rEntries(getGradientEntries()); + for(const SvgGradientEntry& rCandidate : std::views::reverse(rEntries)) { - const SvgGradientEntry& rCandidate = getGradientEntries()[nCount - 1 - a]; - maMirroredGradientEntries.emplace_back( 1.0 - rCandidate.getOffset(), rCandidate.getColor(), diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 36f5a7bdacd2..0d9d6fed2cb0 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -46,14 +46,14 @@ namespace { class ImpTimedRefDev; -// VDev RevDevice provider +// VDev RefDevice provider -//the scoped_timed_RefDev owns an ImpTimeRefDev and releases it on dtor +//the scoped_timed_RefDev owns an ImpTimedRefDev and releases it on dtor //or disposing of the default XComponentContext which causes the underlying //OutputDevice to get released -//The ImpTimerRefDev itself, if the timeout ever gets hit, will call -//reset on the scoped_timed_RefDev to release the ImpTimerRefDev early +//The ImpTimedRefDev itself, if the timeout ever gets hit, will call +//reset on the scoped_timed_RefDev to release the ImpTimedRefDev early //if it's unused for a few minutes class scoped_timed_RefDev : public comphelper::unique_disposing_ptr { @@ -161,7 +161,7 @@ void releaseGlobalVirtualDevice() TextLayouterDevice::TextLayouterDevice() : mrDevice(acquireGlobalVirtualDevice()) { - // tdf#168002 activate SubpixelPositioning for al TextLayouterDevice-calls + // tdf#168002 activate SubpixelPositioning for all TextLayouterDevice-calls mrDevice.setSubpixelPositioning(true); } @@ -188,7 +188,7 @@ void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& rFontA if (aFontSize.Height()) { mnFontScalingFixY = fFontScaleY / aFontSize.Height(); - // aFontSize.Width() is 0 for uninformly scaled fonts: see getVclFontFromFontAttribute + // aFontSize.Width() is 0 for uniformly scaled fonts: see getVclFontFromFontAttribute mnFontScalingFixX = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : aFontSize.Height()); } @@ -423,21 +423,11 @@ vcl::Font getVclFontFromFontAttribute(const attribute::FontAttribute& rFontAttri const sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX))); const bool bFontIsScaled(nHeight != nWidth); -#ifdef _WIN32 - // for WIN32 systems, start with creating an unscaled font. If FontScaling - // is wanted, that width needs to be adapted using FontMetric again to get a - // width of the unscaled font - vcl::Font aRetval(rFontAttribute.getFamilyName(), rFontAttribute.getStyleName(), - Size(0, nHeight)); -#else - // for non-WIN32 systems things are easier since these accept a Font creation - // with initially nWidth != nHeight for FontScaling. Despite that, use zero for - // FontWidth when no scaling is used to explicitly have that zero when e.g. the - // Font would be recorded in a MetaFile (The MetaFile FontAction WILL record a - // set FontWidth; import that in a WIN32 system, and trouble is there) + // Use zero for FontWidth when no scaling is used, to explicitly have that zero + // when e.g. the Font would be recorded in a MetaFile (The MetaFile FontAction + // WILL record a set FontWidth) vcl::Font aRetval(rFontAttribute.getFamilyName(), rFontAttribute.getStyleName(), Size(bFontIsScaled ? std::max(nWidth, 1) : 0, nHeight)); -#endif // define various other FontAttribute aRetval.SetAlignment(ALIGN_BASELINE); aRetval.SetCharSet(rFontAttribute.getSymbol() ? RTL_TEXTENCODING_SYMBOL @@ -449,22 +439,6 @@ vcl::Font getVclFontFromFontAttribute(const attribute::FontAttribute& rFontAttri aRetval.SetPitch(rFontAttribute.getMonospaced() ? PITCH_FIXED : PITCH_VARIABLE); aRetval.SetLanguage(LanguageTag::convertToLanguageType(rLocale, false)); -#ifdef _WIN32 - // for WIN32 systems, correct the FontWidth if FontScaling is used - if (bFontIsScaled && nHeight > 0) - { - const FontMetric aUnscaledFontMetric( - Application::GetDefaultDevice()->GetFontMetric(aRetval)); - - if (aUnscaledFontMetric.GetAverageFontWidth() > 0) - { - const double fScaleFactor(static_cast(nWidth) / static_cast(nHeight)); - const sal_uInt32 nScaledWidth(basegfx::fround( - static_cast(aUnscaledFontMetric.GetAverageFontWidth()) * fScaleFactor)); - aRetval.SetAverageFontWidth(nScaledWidth); - } - } -#endif // handle FontRotation (if defined) if (!basegfx::fTools::equalZero(fFontRotation)) { @@ -490,37 +464,13 @@ attribute::FontAttribute getFontAttributeFromVclFont(basegfx::B2DVector& o_rSize o_rSize.setY(std::max(rFont.GetFontSize().getHeight(), 0)); o_rSize.setX(o_rSize.getY()); -#ifdef _WIN32 - // for WIN32 systems, the FontScaling at the Font is detected by - // checking that FontWidth != 0. When FontScaling is used, WIN32 - // needs to do extra stuff to detect the correct width (since it's - // zero and not equal the font height) and its relationship to - // the height - if (rFont.GetFontSize().getWidth() > 0) - { - vcl::Font aUnscaledFont(rFont); - aUnscaledFont.SetAverageFontWidth(0); - const FontMetric aUnscaledFontMetric( - Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont)); - - if (aUnscaledFontMetric.GetAverageFontWidth() > 0) - { - const double fScaleFactor( - static_cast(rFont.GetFontSize().getWidth()) - / static_cast(aUnscaledFontMetric.GetAverageFontWidth())); - o_rSize.setX(fScaleFactor * o_rSize.getY()); - } - } -#else - // For non-WIN32 systems the detection is the same, but the value - // is easier achieved since width == height is interpreted as no - // scaling. Ergo, Width == 0 means width == height, and width != 0 - // means the scaling is in the direct relation of width to height + // The FontScaling at the Font is detected by checking that FontWidth != 0. + // Width == 0 means width == height, and width != 0 means the scaling is in + // the direct relation of width to height if (rFont.GetFontSize().getWidth() > 0) { o_rSize.setX(static_cast(rFont.GetFontSize().getWidth())); } -#endif return aRetval; } diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx index 8054695ebd34..5a34757ceb7e 100644 --- a/drawinglayer/source/primitive2d/textprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -277,6 +277,7 @@ bool TextSimplePortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) && LocalesAreEqual(getLocale(), rCompare.getLocale()) && getFontColor() == rCompare.getFontColor() && maTextFillColor == rCompare.maTextFillColor + && getFontVariations() == rCompare.getFontVariations() && getProportionalFontSize() == rCompare.getProportionalFontSize() && getEscapement() == rCompare.getEscapement()); } diff --git a/drawinglayer/source/primitive3d/Tools.cxx b/drawinglayer/source/primitive3d/Tools.cxx index 23ecc0851f40..b53ec852e435 100644 --- a/drawinglayer/source/primitive3d/Tools.cxx +++ b/drawinglayer/source/primitive3d/Tools.cxx @@ -62,6 +62,6 @@ OUString idToString(sal_uInt32 nId) } } -} // end of namespace drawinglayer::primitive2d +} // end of namespace drawinglayer::primitive3d /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx index ccdab4f8ca3a..72f8811d6ac5 100644 --- a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx @@ -203,7 +203,7 @@ namespace drawinglayer::primitive3d // // Unfortunately there is no bezier polygon provided by the chart module; one reason is // that the API for extrude wants a 3D polygon geometry (for historical reasons, i guess) - // and those have no beziers. Another reason is that he chart module uses self-created + // and those have no beziers. Another reason is that the chart module uses self-created // stuff to create the 2D geometry (in ShapeFactory::createPieSegment), but this geometry // does not contain bezier infos, either. The only way which is possible for now is to 'detect' // candidates for vertical edges of pie segments by looking for the angles in the polygon. @@ -487,7 +487,7 @@ namespace drawinglayer::primitive3d std::unique_lock aGuard( m_aMutex ); // conditions of last local decomposition with reduced lines have changed. Remember - // new one and clear current decompositiopn + // new one and clear current decomposition SdrExtrudePrimitive3D* pThat = const_cast< SdrExtrudePrimitive3D* >(this); pThat->setBuffered3DDecomposition(Primitive3DContainer()); pThat->mpLastRLGViewInformation = rViewInformation; diff --git a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx index 6eaf35d9694e..6658cc2e18fb 100644 --- a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx @@ -344,7 +344,7 @@ namespace drawinglayer::primitive3d std::unique_lock aGuard( m_aMutex ); // conditions of last local decomposition with reduced lines have changed. Remember - // new one and clear current decompositiopn + // new one and clear current decomposition SdrLathePrimitive3D* pThat = const_cast< SdrLathePrimitive3D* >(this); pThat->setBuffered3DDecomposition(Primitive3DContainer()); pThat->mpLastRLGViewInformation = rViewInformation; diff --git a/drawinglayer/source/primitive3d/sdrprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrprimitive3d.cxx index d11627e95513..86b29bf8af36 100644 --- a/drawinglayer/source/primitive3d/sdrprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrprimitive3d.cxx @@ -37,7 +37,7 @@ namespace drawinglayer::primitive3d if(!rLine.isDefault() && !basegfx::fTools::equalZero(rLine.getWidth())) { - // expand by held LineWidth as tube radius + // expand by half LineWidth as tube radius aUnitRange.grow(rLine.getWidth() / 2.0); } } diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index 2352e28251ac..ab338f383d34 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -431,10 +431,10 @@ nMinimalDiscreteSquareSizeToBuffer(nMinimalDiscreteSize* nMinimalDiscreteSize); class CairoSurfaceHelper { // the buffered CairoSurface (bitmap data) - cairo_surface_t* mpCairoSurface; + cairo::CairoSurfaceSharedPtr mpCairoSurface; // evtl. MipMapped data (pre-scale to reduce data processing load) - mutable std::unordered_map maDownscaled; + mutable std::unordered_map maDownscaled; // create 32bit RGBA data for given Bitmap void createRGBA(const Bitmap& rBitmap) @@ -442,15 +442,17 @@ class CairoSurfaceHelper BitmapScopedReadAccess pReadAccess(rBitmap); const tools::Long nHeight(pReadAccess->Height()); const tools::Long nWidth(pReadAccess->Width()); - mpCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight); - if (cairo_surface_status(mpCairoSurface) != CAIRO_STATUS_SUCCESS) + mpCairoSurface = cairo::CairoSurfaceSharedPtr( + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight), + &cairo_surface_destroy); + if (cairo_surface_status(mpCairoSurface.get()) != CAIRO_STATUS_SUCCESS) { SAL_WARN("drawinglayer", "cairo_image_surface_create failed for: " << nWidth << " x " << nHeight); return; } const sal_uInt32 nStride(cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, nWidth)); - unsigned char* surfaceData(cairo_image_surface_get_data(mpCairoSurface)); + unsigned char* surfaceData(cairo_image_surface_get_data(mpCairoSurface.get())); for (tools::Long y(0); y < nHeight; ++y) { @@ -469,7 +471,7 @@ class CairoSurfaceHelper } } - cairo_surface_mark_dirty(mpCairoSurface); + cairo_surface_mark_dirty(mpCairoSurface.get()); } // create 32bit RGB data for given Bitmap @@ -478,15 +480,17 @@ class CairoSurfaceHelper BitmapScopedReadAccess pReadAccess(rBitmap); const tools::Long nHeight(pReadAccess->Height()); const tools::Long nWidth(pReadAccess->Width()); - mpCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, nWidth, nHeight); - if (cairo_surface_status(mpCairoSurface) != CAIRO_STATUS_SUCCESS) + mpCairoSurface = cairo::CairoSurfaceSharedPtr( + cairo_image_surface_create(CAIRO_FORMAT_RGB24, nWidth, nHeight), + &cairo_surface_destroy); + if (cairo_surface_status(mpCairoSurface.get()) != CAIRO_STATUS_SUCCESS) { SAL_WARN("drawinglayer", "cairo_image_surface_create failed for: " << nWidth << " x " << nHeight); return; } sal_uInt32 nStride(cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, nWidth)); - unsigned char* surfaceData(cairo_image_surface_get_data(mpCairoSurface)); + unsigned char* surfaceData(cairo_image_surface_get_data(mpCairoSurface.get())); for (tools::Long y(0); y < nHeight; ++y) { @@ -504,7 +508,7 @@ class CairoSurfaceHelper } } - cairo_surface_mark_dirty(mpCairoSurface); + cairo_surface_mark_dirty(mpCairoSurface.get()); } // #define TEST_RGB16 @@ -551,10 +555,15 @@ class CairoSurfaceHelper public: CairoSurfaceHelper(const Bitmap& rBitmap) - : mpCairoSurface(nullptr) + // When using a cairo-backed Bitmap (i.e. SvpSalBitmap), we can avoid a lot of copying, + // which is beneficial for documents with lots of large images. Try to access directly. + : mpCairoSurface(rBitmap.tryToGetCairoSurface()) , maDownscaled() { - if (rBitmap.HasAlpha()) + if (nullptr != mpCairoSurface) + { + } // all done, we got it directly + else if (rBitmap.HasAlpha()) createRGBA(rBitmap); else #ifdef TEST_RGB16 @@ -564,25 +573,8 @@ public: #endif } - /* constructor for when we are using the cairo data directly from the underlying SvpSalBitmap */ - CairoSurfaceHelper(cairo_surface_t* pCairoSurface) - : mpCairoSurface(pCairoSurface) - , maDownscaled() - { - } - - ~CairoSurfaceHelper() - { - // cleanup surface - cairo_surface_destroy(mpCairoSurface); - - // cleanup MipMap surfaces - for (auto& candidate : maDownscaled) - cairo_surface_destroy(candidate.second); - } - - cairo_surface_t* getCairoSurface(sal_uInt32 nTargetWidth = 0, - sal_uInt32 nTargetHeight = 0) const + cairo::CairoSurfaceSharedPtr getCairoSurface(sal_uInt32 nTargetWidth = 0, + sal_uInt32 nTargetHeight = 0) const { // in simple cases just return the single created surface if (bDisableDownScale || nullptr == mpCairoSurface || 0 == nTargetWidth @@ -590,35 +582,43 @@ public: return mpCairoSurface; // get width/height of original surface - const sal_uInt32 nSourceWidth(cairo_image_surface_get_width(mpCairoSurface)); - const sal_uInt32 nSourceHeight(cairo_image_surface_get_height(mpCairoSurface)); + const sal_uInt32 nSourceWidth(cairo_image_surface_get_width(mpCairoSurface.get())); + const sal_uInt32 nSourceHeight(cairo_image_surface_get_height(mpCairoSurface.get())); - // zoomed in, need to stretch at paint, no pre-scale useful - if (nTargetWidth >= nSourceWidth || nTargetHeight >= nSourceHeight) + // zoomed in on both axes, need to stretch at paint, no pre-scale useful + if (nTargetWidth >= nSourceWidth && nTargetHeight >= nSourceHeight) return mpCairoSurface; - // calculate downscale factor. Only use ONE factor to get the diagonal - // MipMap, NOT the full MipMap field in X/Y for uneven factors in both dimensions - sal_uInt32 nFactor(1); + // calculate independent downscale factors per axis, matching the + // strategy in vcl's SurfaceHelper::implCreateOrReuseDownscale + sal_uInt32 nWFactor(1); sal_uInt32 nW((nSourceWidth + 1) / 2); - sal_uInt32 nH((nSourceHeight + 1) / 2); - while (nW > nTargetWidth && nW > nHalfMDSize && nH > nTargetHeight && nH > nHalfMDSize) + while (nW > nTargetWidth && nW > nHalfMDSize) { nW = (nW + 1) / 2; - nH = (nH + 1) / 2; - nFactor *= 2; + nWFactor *= 2; } - if (1 == nFactor) + sal_uInt32 nHFactor(1); + sal_uInt32 nH((nSourceHeight + 1) / 2); + + while (nH > nTargetHeight && nH > nHalfMDSize) + { + nH = (nH + 1) / 2; + nHFactor *= 2; + } + + if (1 == nWFactor && 1 == nHFactor) { // original size *is* best binary size, use it return mpCairoSurface; } - // go up one scale again - nW *= 2; - nH *= 2; + // go up one scale again per axis, but if no downscale was needed + // on an axis use the target size directly + nW = (1 == nWFactor) ? nTargetWidth : nW * 2; + nH = (1 == nHFactor) ? nTargetHeight : nH * 2; // bail out if the multiplication for the key would overflow if (nW >= SAL_MAX_UINT32 || nH >= SAL_MAX_UINT32) @@ -633,29 +633,24 @@ public: return isHit->second; // create new surface in the targeted size - cairo_surface_t* pSurfaceTarget(cairo_surface_create_similar( - mpCairoSurface, cairo_surface_get_content(mpCairoSurface), nW, nH)); + cairo::CairoSurfaceSharedPtr pSurfaceTarget( + cairo_surface_create_similar(mpCairoSurface.get(), + cairo_surface_get_content(mpCairoSurface.get()), nW, nH), + &cairo_surface_destroy); - // made a version to scale self first with direct memory access. - // That worked well, but would've been hard to support - // CAIRO_FORMAT_A1 and similar (including bit shifting), so - // I decided to go with cairo itself - use CAIRO_FILTER_FAST or - // CAIRO_FILTER_GOOD though. Please modify as needed for - // performance/quality - cairo_t* cr = cairo_create(pSurfaceTarget); + cairo_t* cr = cairo_create(pSurfaceTarget.get()); const double fScaleX(static_cast(nW) / static_cast(nSourceWidth)); const double fScaleY(static_cast(nH) / static_cast(nSourceHeight)); cairo_scale(cr, fScaleX, fScaleY); - cairo_set_source_surface(cr, mpCairoSurface, 0.0, 0.0); + cairo_set_source_surface(cr, mpCairoSurface.get(), 0.0, 0.0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_GOOD); cairo_paint(cr); cairo_destroy(cr); - // NOTE: Took out, until now not really needed - // need to set device_scale for downscale surfaces to get - // them handled correctly - // cairo_surface_set_device_scale(pSurfaceTarget, fScaleX, fScaleY); + // NOTE: do NOT set device_scale on the mipmap surface - the callers + // build pattern matrices using cairo_image_surface_get_width/height + // (raw pixels), and device_scale would double-apply the scaling // add entry to cached entries maDownscaled[key] = pSurfaceTarget; @@ -668,8 +663,8 @@ public: if (nullptr == mpCairoSurface) return true; - const sal_uInt32 nSourceWidth(cairo_image_surface_get_width(mpCairoSurface)); - const sal_uInt32 nSourceHeight(cairo_image_surface_get_height(mpCairoSurface)); + const sal_uInt32 nSourceWidth(cairo_image_surface_get_width(mpCairoSurface.get())); + const sal_uInt32 nSourceHeight(cairo_image_surface_get_height(mpCairoSurface.get())); return nSourceWidth * nSourceHeight < nMinimalDiscreteSquareSizeToBuffer; } @@ -703,11 +698,12 @@ sal_Int64 SystemDependentData_CairoSurface::estimateUsageInBytes() const if (mpCairoSurfaceHelper) { - cairo_surface_t* pSurface(mpCairoSurfaceHelper->getCairoSurface()); - const tools::Long nStride(cairo_image_surface_get_stride(pSurface)); - const tools::Long nHeight(cairo_image_surface_get_height(pSurface)); + cairo::CairoSurfaceSharedPtr pSurface(mpCairoSurfaceHelper->getCairoSurface()); + const tools::Long nStride(cairo_image_surface_get_stride(pSurface.get())); + const tools::Long nHeight(cairo_image_surface_get_height(pSurface.get())); - nRetval = nStride * nHeight; + // w * h * 4 bytesPerPixel + nRetval = nStride * nHeight * 4; // if we do downscale, size will grow by 1/4 + 1/16 + 1/32 + ..., // rough estimation just multiplies by 1.25 .. 1.33, should be good enough @@ -723,12 +719,36 @@ sal_Int64 SystemDependentData_CairoSurface::estimateUsageInBytes() const std::shared_ptr getOrCreateCairoSurfaceHelper(const Bitmap& rBitmap) { - // When using a cairo-backed Bitmap (i.e. SvpSalBitmap), we can avoid a lot of copying, - // which is beneficial for documents with lots of large images. - cairo_surface_t* pSurface(static_cast(rBitmap.tryToGetCairoSurface())); + cairo::CairoSurfaceSharedPtr pSurface(rBitmap.tryToGetCairoSurface()); if (nullptr != pSurface) { - return std::make_shared(pSurface); + // in this case we get a cairo_surface_t directly from the underlying + // Bitmap (this is the future and the case if built using --without-system-cairo + // and --enable-cairo-rgba). The created CairoSurfaceHelper will just wrap it + // and will not have to create a cairo-compatible local clone, BUT it also + // supports the Mip-Mapping. Thus, for smaller Bitmaps, it is OK to just + // use this without the need to add data to the SystemDependentDataHolder + // mechanism since there is no real need to hold MipMapped data. + // The key here is to balance the effort for that against evtl. needed (!) + // Mip-Mapping, and that depends on the Bitmap's size (in square pixels). + // Thus, add a shortcut here - but ONLY for small enough Bitmaps that + // do not cost too much to be painted in cairo with good quality. Remember + // that cairo *is* a software-renderer after all (!). This value may be adapted as + // needed. Note that below there is also 'isTrivial' used which already uses + // nMinimalDiscreteSquareSizeToBuffer which is 15x15 (e.g. handles), but also + // for !isCairoCompatible cases. + const tools::Long aSmallBitmapSquareSize(160 * 100); + + if (cairo_image_surface_get_stride(pSurface.get()) + * cairo_image_surface_get_height(pSurface.get()) + <= aSmallBitmapSquareSize) + { + // take the shortcut: For this small directly accessible size + // we do not urgently need Mip-Mapping and spare the + // SystemDependentData buffering mechanism + SAL_INFO("drawinglayer", "BailOut SMALL Bitmap"); + return std::make_shared(rBitmap); + } } const basegfx::SystemDependentDataHolder* pHolder(rBitmap.accessSystemDependentDataHolder()); @@ -1067,8 +1087,8 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(OutputDevice& rOutputDevice, // get evtl. offsets if OutputDevice is e.g. a OUTDEV_WINDOW // to evaluate if initial clip is needed - const tools::Long nOffsetPixelX(mpTargetOutputDevice->GetOutOffXPixel()); - const tools::Long nOffsetPixelY(mpTargetOutputDevice->GetOutOffYPixel()); + const tools::Long nOffsetPixelX(mpTargetOutputDevice->GetDeviceOriginX()); + const tools::Long nOffsetPixelY(mpTargetOutputDevice->GetDeviceOriginY()); const tools::Long nWidthPixel(mpTargetOutputDevice->GetOutputWidthPixel()); const tools::Long nHeightPixel(mpTargetOutputDevice->GetOutputHeightPixel()); bool bClipNeeded(false); @@ -1180,7 +1200,7 @@ Bitmap CairoPixelProcessor2D::extractBitmap() const // we for now only support ARGB32 and RGB24, format not supported, not valid return aRetval; - // ensure surface read access, wer need CAIRO_SURFACE_TYPE_IMAGE + // ensure surface read access, we need CAIRO_SURFACE_TYPE_IMAGE cairo_surface_t* pReadSource(pSource); if (CAIRO_SURFACE_TYPE_IMAGE != cairo_surface_get_type(pReadSource)) @@ -1375,8 +1395,9 @@ void CairoPixelProcessor2D::paintBitmapAlpha(const Bitmap& rBitmap, return; } - cairo_surface_t* pTarget(aCairoSurfaceHelper->getCairoSurface(nDestWidth, nDestHeight)); - if (nullptr == pTarget) + cairo::CairoSurfaceSharedPtr pTarget( + aCairoSurfaceHelper->getCairoSurface(nDestWidth, nDestHeight)); + if (!pTarget) { SAL_WARN("drawinglayer", "SDPRCairo: No CairoSurface from Bitmap SurfaceHelper (!)"); return; @@ -1400,7 +1421,7 @@ void CairoPixelProcessor2D::paintBitmapAlpha(const Bitmap& rBitmap, cairo_stroke(mpRT); } - cairo_set_source_surface(mpRT, pTarget, 0, 0); + cairo_set_source_surface(mpRT, pTarget.get(), 0, 0); // get the pattern created by cairo_set_source_surface and // it's transformation @@ -1425,10 +1446,10 @@ void CairoPixelProcessor2D::paintBitmapAlpha(const Bitmap& rBitmap, // simple (we are in unit coordinates) cairo_rectangle(mpRT, 0, 0, 1, 1); cairo_clip(mpRT); - cairo_matrix_scale(&aMatrix, cairo_image_surface_get_width(pTarget), - cairo_image_surface_get_height(pTarget)); + cairo_matrix_scale(&aMatrix, cairo_image_surface_get_width(pTarget.get()), + cairo_image_surface_get_height(pTarget.get())); - // The alternative wpuld be: resize/scale it SLIGHTLY to force + // The alternative would be: resize/scale it SLIGHTLY to force // that half pixel overlap to be inside the unit range. // That makes the error disappear, so no clip needed, but // SLIGHTLY smaller. Keeping this code if someone might have @@ -2164,15 +2185,15 @@ void CairoPixelProcessor2D::processMarkerArrayPrimitive2D( } // do not use dimensions, these are usually small instances - cairo_surface_t* pTarget(aCairoSurfaceHelper->getCairoSurface()); - if (nullptr == pTarget) + cairo::CairoSurfaceSharedPtr pTarget(aCairoSurfaceHelper->getCairoSurface()); + if (!pTarget) { SAL_WARN("drawinglayer", "SDPRCairo: No CairoSurface from Bitmap SurfaceHelper (!)"); return; } - const sal_uInt32 nWidth(cairo_image_surface_get_width(pTarget)); - const sal_uInt32 nHeight(cairo_image_surface_get_height(pTarget)); + const sal_uInt32 nWidth(cairo_image_surface_get_width(pTarget.get())); + const sal_uInt32 nHeight(cairo_image_surface_get_height(pTarget.get())); const tools::Long nMiX((nWidth / 2) + 1); const tools::Long nMiY((nHeight / 2) + 1); @@ -2188,7 +2209,7 @@ void CairoPixelProcessor2D::processMarkerArrayPrimitive2D( const double fX(ceil(aDiscretePos.getX())); const double fY(ceil(aDiscretePos.getY())); - cairo_set_source_surface(mpRT, pTarget, fX - nMiX, fY - nMiY); + cairo_set_source_surface(mpRT, pTarget.get(), fX - nMiX, fY - nMiY); cairo_paint(mpRT); } @@ -2656,8 +2677,9 @@ void CairoPixelProcessor2D::processFillGraphicPrimitive2D( return; } - cairo_surface_t* pTarget(aCairoSurfaceHelper->getCairoSurface(nDestWidth, nDestHeight)); - if (nullptr == pTarget) + cairo::CairoSurfaceSharedPtr pTarget( + aCairoSurfaceHelper->getCairoSurface(nDestWidth, nDestHeight)); + if (!pTarget) { SAL_WARN("drawinglayer", "SDPRCairo: No CairoSurface from Bitmap SurfaceHelper (!)"); return; @@ -2671,10 +2693,10 @@ void CairoPixelProcessor2D::processFillGraphicPrimitive2D( aLocalTransform.d(), aLocalTransform.e(), aLocalTransform.f()); cairo_set_matrix(mpRT, &aMatrix); - const sal_uInt32 nWidth(cairo_image_surface_get_width(pTarget)); - const sal_uInt32 nHeight(cairo_image_surface_get_height(pTarget)); + const sal_uInt32 nWidth(cairo_image_surface_get_width(pTarget.get())); + const sal_uInt32 nHeight(cairo_image_surface_get_height(pTarget.get())); - cairo_set_source_surface(mpRT, pTarget, 0, 0); + cairo_set_source_surface(mpRT, pTarget.get(), 0, 0); // get the pattern created by cairo_set_source_surface and // it's transformation @@ -2682,7 +2704,7 @@ void CairoPixelProcessor2D::processFillGraphicPrimitive2D( cairo_pattern_get_matrix(sourcepattern, &aMatrix); // clip for RGBA (see other places) - if (CAIRO_FORMAT_ARGB32 == cairo_image_surface_get_format(pTarget)) + if (CAIRO_FORMAT_ARGB32 == cairo_image_surface_get_format(pTarget.get())) { cairo_rectangle(mpRT, 0, 0, 1, 1); cairo_clip(mpRT); @@ -2843,7 +2865,7 @@ void CairoPixelProcessor2D::processFillGradientPrimitive2D_linear_axial( aBColorStopsAlpha = rFillGradientPrimitive2D.getAlphaGradient().getColorStops(); const bool bAxial(css::awt::GradientStyle_AXIAL == rFillGradient.getStyle()); - // get and apply border - create soace at start in gradient + // get and apply border - create space at start in gradient const double fBorder(std::max(std::min(rFillGradient.getBorder(), 1.0), 0.0)); if (!basegfx::fTools::equalZero(fBorder)) { @@ -3033,7 +3055,7 @@ void CairoPixelProcessor2D::processFillGradientPrimitive2D_square_rect( aBColorStops.tryToApplyBColorModifierStack(maBColorModifierStack); } - // get and apply border - create soace at start in gradient + // get and apply border - create space at start in gradient const double fBorder(std::max(std::min(rFillGradient.getBorder(), 1.0), 0.0)); if (!basegfx::fTools::equalZero(fBorder)) { @@ -3267,7 +3289,7 @@ void CairoPixelProcessor2D::processFillGradientPrimitive2D_radial_elliptical( if (bHasAlpha) aBColorStopsAlpha = rFillGradientPrimitive2D.getAlphaGradient().getColorStops(); - // get and apply border - create soace at start in gradient + // get and apply border - create space at start in gradient const double fBorder(std::max(std::min(rFillGradient.getBorder(), 1.0), 0.0)); if (!basegfx::fTools::equalZero(fBorder)) { @@ -3379,7 +3401,7 @@ void CairoPixelProcessor2D::processFillGradientPrimitive2D_fallback_decompose( // draw all-covering initial BG polygon 1st using getOuterColor and getOutputRange processFillGradientPrimitive2D_drawOutputRange(rFillGradientPrimitive2D); - // bet basic form in unit coordinates + // get basic form in unit coordinates CairoPathHelper aForm(rFillGradientPrimitive2D.getUnitPolygon()); // paint solid fill steps by providing callback as lambda @@ -3533,27 +3555,37 @@ void CairoPixelProcessor2D::processPatternFillPrimitive2D( { if (!mpTargetOutputDevice) return; + const basegfx::B2DRange& rReferenceRange = rPrimitive.getReferenceRange(); if (rReferenceRange.isEmpty() || rReferenceRange.getWidth() <= 0.0 || rReferenceRange.getHeight() <= 0.0) return; + basegfx::B2DPolyPolygon aMask = rPrimitive.getMask(); aMask.transform(getViewInformation2D().getObjectToViewTransformation()); const basegfx::B2DRange aMaskRange(aMask.getB2DRange()); + if (aMaskRange.isEmpty() || aMaskRange.getWidth() <= 0.0 || aMaskRange.getHeight() <= 0.0) return; + sal_uInt32 nTileWidth, nTileHeight; rPrimitive.getTileSize(nTileWidth, nTileHeight, getViewInformation2D()); if (nTileWidth == 0 || nTileHeight == 0) return; Bitmap aTileImage = rPrimitive.createTileImage(nTileWidth, nTileHeight); tools::Rectangle aMaskRect = vcl::unotools::rectangleFromB2DRectangle(aMaskRange); + // Unless smooth edges are needed, simply use clipping. if (basegfx::utils::isRectangle(aMask) || !getViewInformation2D().getUseAntiAliasing()) { mpTargetOutputDevice->Push(vcl::PushFlags::CLIPREGION); mpTargetOutputDevice->IntersectClipRegion(vcl::Region(aMask)); - mpTargetOutputDevice->DrawWallpaper(aMaskRect, Wallpaper(aTileImage)); + Wallpaper aWallpaper(aTileImage); + aWallpaper.SetColor(COL_TRANSPARENT); + Point aPaperPt(aMaskRect.getX() % nTileWidth, aMaskRect.getY() % nTileHeight); + tools::Rectangle aPaperRect(aPaperPt, aTileImage.GetSizePixel()); + aWallpaper.SetRect(aPaperRect); + mpTargetOutputDevice->DrawWallpaper(aMaskRect, aWallpaper); mpTargetOutputDevice->Pop(); return; } @@ -3569,19 +3601,30 @@ void CairoPixelProcessor2D::processPatternFillPrimitive2D( } impBufferDevice aBufferDevice(*mpTargetOutputDevice, aMaskRect); + if (!aBufferDevice.isVisible()) return; + // remember last OutDev and set to content OutputDevice* pLastOutputDevice = mpTargetOutputDevice; mpTargetOutputDevice = &aBufferDevice.getContent(); - mpTargetOutputDevice->DrawWallpaper(aMaskRect, Wallpaper(aTileImage)); + + Wallpaper aWallpaper(aTileImage); + aWallpaper.SetColor(COL_TRANSPARENT); + Point aPaperPt(aMaskRect.getX() % nTileWidth, aMaskRect.getY() % nTileHeight); + tools::Rectangle aPaperRect(aPaperPt, aTileImage.GetSizePixel()); + aWallpaper.SetRect(aPaperRect); + mpTargetOutputDevice->DrawWallpaper(aMaskRect, aWallpaper); + // back to old OutDev mpTargetOutputDevice = pLastOutputDevice; + // draw mask VirtualDevice& rMask = aBufferDevice.getTransparence(); rMask.SetLineColor(); rMask.SetFillColor(COL_BLACK); rMask.DrawPolyPolygon(aMask); + // dump buffer to outdev aBufferDevice.paint(); } @@ -4202,7 +4245,7 @@ void CairoPixelProcessor2D::processSvgLinearGradientPrimitive2D( break; } - // get PathGeometry & paint it filed with gradient + // get PathGeometry & paint it filled with gradient cairo_new_path(mpRT); getOrCreateFillGeometry(mpRT, rCandidate.getPolyPolygon()); cairo_set_source(mpRT, pPattern); @@ -4310,7 +4353,7 @@ void CairoPixelProcessor2D::processSvgRadialGradientPrimitive2D( break; } - // get PathGeometry & paint it filed with gradient + // get PathGeometry & paint it filled with gradient cairo_new_path(mpRT); getOrCreateFillGeometry(mpRT, rCandidate.getPolyPolygon()); cairo_set_source(mpRT, pPattern); @@ -4340,7 +4383,7 @@ void CairoPixelProcessor2D::processControlPrimitive2D( if (bControlIsVisibleAsChildWindow) { - // f the control is already visualized as a VCL-ChildWindow it + // if the control is already visualized as a VCL-ChildWindow it // does not need to be painted at all return; } diff --git a/drawinglayer/source/processor2d/contourextractor2d.cxx b/drawinglayer/source/processor2d/contourextractor2d.cxx index 94d6b109ecfb..b62169e8dbb4 100644 --- a/drawinglayer/source/processor2d/contourextractor2d.cxx +++ b/drawinglayer/source/processor2d/contourextractor2d.cxx @@ -163,7 +163,7 @@ namespace drawinglayer::processor2d case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D : case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D : { - // primitives who's BoundRect will be added in world coordinates + // primitives whose BoundRect will be added in world coordinates basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D())); if (!aRange.isEmpty()) { diff --git a/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx b/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx index 303e0a65ac49..90cf2d887d91 100644 --- a/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx @@ -535,7 +535,7 @@ public: if (hasRenderTarget()) { - // set Viewort if none was given. We have a fixed pixel target, s we know the + // set Viewport if none was given. We have a fixed pixel target, so we know the // exact Viewport to work on if (getViewInformation2D().getViewport().isEmpty()) { @@ -1558,11 +1558,11 @@ void D2DPixelProcessor2D::processPolygonStrokePrimitive2D( // "miterLimit is relative to 1/2 LineWidth", so a length. After some experimenting // it shows that the (better understandable) angle has to be converted to the length // that a miter prolongation would have at that angle, so use some trigonometry. - // Unfortunately there is also some'precision' problem (probably), so I had to + // Unfortunately there is also some 'precision' problem (probably), so I had to // experimentally come to a correction value around 0.9925. Since that seems to // be no obvious numerical value involved somehow (and as long as I find no other // explanation) I will have to use that. - // NOTE: To find that correction value I usd that handy bRenderDecomposeForCompareInRed + // NOTE: To find that correction value I used that handy bRenderDecomposeForCompareInRed // and changes in debugger - as work tipp // With both done I can use Direct2D for Miter completely - what is good for speed. aLineJoin = D2D1_LINE_JOIN_MITER_OR_BEVEL; @@ -2063,12 +2063,12 @@ void D2DPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitiv // NOTE: In these implementations you could always call what the default // case below does - call process(rCandidate) to use the decomposition. // So these impls should only do something if they can do it better/ - // faster that the decomposition. So some of them check if they could + // faster than the decomposition. So some of them check if they could // - and if not - use exactly that. case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D: { // transparence with a fixed alpha for all content, can be done - // significally faster + // significantly faster processUnifiedTransparencePrimitive2D( static_cast(rCandidate)); break; diff --git a/drawinglayer/source/processor2d/processor2dtools.cxx b/drawinglayer/source/processor2d/processor2dtools.cxx index cfb9c3897909..d0d7822807f5 100644 --- a/drawinglayer/source/processor2d/processor2dtools.cxx +++ b/drawinglayer/source/processor2d/processor2dtools.cxx @@ -117,10 +117,10 @@ std::unique_ptr createPixelProcessor2DFromOutputDevice( // NOTE: This will also need to take extended size of target device into // consideration, using D2DPixelProcessor2D *will* have to clip // against that. Thus for now this is *not* sufficient (see tdf#163125) - if(0 != rTargetOutDev.GetOutOffXPixel() || 0 != rTargetOutDev.GetOutOffYPixel()) + if(0 != rTargetOutDev.GetDeviceOriginX() || 0 != rTargetOutDev.GetDeviceOriginY()) { basegfx::B2DHomMatrix aTransform(aViewInformation2D.getViewTransformation()); - aTransform.translate(rTargetOutDev.GetOutOffXPixel(), rTargetOutDev.GetOutOffYPixel()); + aTransform.translate(rTargetOutDev.GetDeviceOriginX(), rTargetOutDev.GetDeviceOriginY()); aViewInformation2D.setViewTransformation(aTransform); } diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx index 3546bb2a9308..9cb5522c020b 100644 --- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx +++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -395,6 +396,9 @@ impBufferDevice::impBufferDevice(OutputDevice& rOutDev, const tools::Rectangle& , mpAlpha(nullptr) , maDestPixel(rDestPixel) { + auto aRangePixel = vcl::unotools::b2DRectangleFromRectangle(maDestPixel); + aRangePixel.transform(mrOutDev.GetViewTransformation()); + maDestPixel = vcl::unotools::rectangleFromB2DRectangle(aRangePixel); maDestPixel.Intersection(tools::Rectangle{ Point{}, mrOutDev.GetOutputSizePixel() }); if (!isVisible()) diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 44b4e754cf40..f2ee40e08081 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -647,7 +647,7 @@ VclMetafileProcessor2D::~VclMetafileProcessor2D() XTEXT_EOW(i) end of word XTEXT_EOS(i) end of sentence - this three are with index and are created with the help of an i18n::XBreakIterator in + these three are with index and are created with the help of an i18n::XBreakIterator in ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some data structure for holding those TEXT infos. Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text @@ -1456,13 +1456,18 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D( return; // emulate data handling from ImpEditEngine::Paint - const basegfx::B2DRange aViewRange(rContent.getB2DRange(getViewInformation2D())); + basegfx::B2DRange aViewRange(rContent.getB2DRange(getViewInformation2D())); + aViewRange.transform(maCurrentTransformation); const tools::Rectangle aRectLogic(static_cast(floor(aViewRange.getMinX())), static_cast(floor(aViewRange.getMinY())), static_cast(ceil(aViewRange.getMaxX())), static_cast(ceil(aViewRange.getMaxY()))); vcl::PDFExtOutDevBookmarkEntry aBookmark; - OUString const altText(rFieldPrimitive.getValue(u"AltText"_ustr)); + OUString altText(rFieldPrimitive.getValue(u"AltText"_ustr)); + if (altText.isEmpty()) + altText = rFieldPrimitive.getValue(u"Representation"_ustr); + if (altText.isEmpty()) + altText = aURL; aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic, altText); aBookmark.aBookmark = aURL; std::vector& rBookmarks = mpPDFExtOutDevData->GetBookmarks(); @@ -2217,7 +2222,7 @@ void VclMetafileProcessor2D::processPolyPolygonGradientPrimitive2D( // These will need more space and time, but the result will be as if the Gradient // was rotated with the object. // This mechanism is used by all exporters still not using Primitives (e.g. Print, - // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile + // Slideshow, Export to PDF, export to Picture, ...) but relying on Metafile // transfers. One more reason to *change* these to primitives. // BTW: One more example how useful the principles of primitives are; the decomposition // is by definition a simpler, maybe more expensive representation of the same content. diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 762c61b6e85f..ca34d13e9dbd 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -579,7 +579,7 @@ void VclPixelProcessor2D::processUnifiedTransparencePrimitive2D( SAL_WARN_IF(!pPoHair, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)"); - // do no tallow by default - problem is that self-overlapping parts of this geometry will + // do not allow by default - problem is that self-overlapping parts of this geometry will // not be in an all-same transparency but will already alpha-cover themselves with blending. // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its // content to be uniformly transparent. @@ -595,7 +595,7 @@ void VclPixelProcessor2D::processUnifiedTransparencePrimitive2D( SAL_WARN_IF(!pPoStroke, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)"); - // do no tallow by default - problem is that self-overlapping parts of this geometry will + // do not allow by default - problem is that self-overlapping parts of this geometry will // not be in an all-same transparency but will already alpha-cover themselves with blending. // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its // content to be uniformly transparent. @@ -646,7 +646,7 @@ void VclPixelProcessor2D::processControlPrimitive2D( if (bControlIsVisibleAsChildWindow) { - // f the control is already visualized as a VCL-ChildWindow it + // if the control is already visualized as a VCL-ChildWindow it // does not need to be painted at all return; } @@ -979,7 +979,7 @@ void VclPixelProcessor2D::processFillGradientPrimitive2D( // To handle a primitive that needs paint, either use decompose, or - when you // do not want that for any reason, e.g. extra primitives created - implement // a direct handling in your primitive renderer. This is always possible - // since primitives by definition are self-contained what means they have all + // since primitives by definition are self-contained which means they have all // needed data locally available to do so. // The question is the complexity to invest - the implemented decompose // is always a good hint of what is needed to do this. In this case I decided diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index 9965e9bc206d..ceee771babd7 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -397,25 +397,6 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D( / (aResultFontSize.Width() ? aResultFontSize.Width() : aResultFontSize.Height()); -#ifdef _WIN32 - if (aResultFontSize.Width() - && aResultFontSize.Width() != aResultFontSize.Height()) - { - // See getVclFontFromFontAttribute in drawinglayer/source/primitive2d/textlayoutdevice.cxx - vcl::Font aUnscaledTest(aFont); - aUnscaledTest.SetFontSize({ 0, aResultFontSize.Height() }); - const FontMetric aUnscaledFontMetric( - Application::GetDefaultDevice()->GetFontMetric(aUnscaledTest)); - if (aUnscaledFontMetric.GetAverageFontWidth() > 0) - { - double nExistingXScale = static_cast(aResultFontSize.Width()) - / aUnscaledFontMetric.GetAverageFontWidth(); - nFontScalingFixX - = aFontScaling.getX() / aFontScaling.getY() / nExistingXScale; - } - } -#endif - if (!rtl_math_approxEqual(nFontScalingFixY, 1.0) || !rtl_math_approxEqual(nFontScalingFixX, 1.0)) { diff --git a/drawinglayer/source/texture/texture3d.cxx b/drawinglayer/source/texture/texture3d.cxx index 7e965770ab9f..e3c1239b4144 100644 --- a/drawinglayer/source/texture/texture3d.cxx +++ b/drawinglayer/source/texture/texture3d.cxx @@ -156,7 +156,7 @@ namespace drawinglayer::texture } else { - // this texture is a color bitmap used as transparence map + // this texture is a color bitmap used as transparency map const Color aColor(aBMCol.GetRed(), aBMCol.GetGreen(), aBMCol.GetBlue()); rfOpacity = (static_cast(0xff - aColor.GetLuminance()) * (1.0 / 255.0)); diff --git a/drawinglayer/source/tools/converters.cxx b/drawinglayer/source/tools/converters.cxx index 5673a2f08d05..a3bedbb53c52 100644 --- a/drawinglayer/source/tools/converters.cxx +++ b/drawinglayer/source/tools/converters.cxx @@ -200,7 +200,7 @@ Bitmap convertToBitmap(drawinglayer::primitive2d::Primitive2DContainer&& rSeq, // COL_WHITE in the 1st layer of targets (not in buffers below) // but is kind of a 'hack' doing so // - Other renderers (system-dependent PrimitiveRenderers, other - // than the VCL-based ones) will probably not support splitted + // than the VCL-based ones) will probably not support split // VDevs for content/alpha, so require a method that works with // RGB targeting (for now) // - Less resource usage, better speed (no 2 VDevs, no merge of diff --git a/drawinglayer/source/tools/emfpbrush.cxx b/drawinglayer/source/tools/emfpbrush.cxx index 51fce424b70a..9c69a31fae19 100644 --- a/drawinglayer/source/tools/emfpbrush.cxx +++ b/drawinglayer/source/tools/emfpbrush.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "emfpbrush.hxx" #include "emfppath.hxx" @@ -62,7 +63,7 @@ namespace emfplushelper void EMFPBrush::Read(SvMemoryStream& s, EmfPlusHelperData const & rR, sal_uInt32 dataSize, bool bUseWholeStream) { - sal_uInt32 header; + sal_uInt32 header(0); s.ReadUInt32(header).ReadUInt32(type); @@ -73,7 +74,7 @@ namespace emfplushelper { case BrushTypeSolidColor: { - sal_uInt32 color; + sal_uInt32 color(0); s.ReadUInt32(color); solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); @@ -82,14 +83,14 @@ namespace emfplushelper } case BrushTypeHatchFill: { - sal_uInt32 style; - sal_uInt32 foregroundColor; - sal_uInt32 backgroundColor; + sal_uInt32 style(0); + sal_uInt32 foregroundColor(0); + sal_uInt32 backgroundColor(0); s.ReadUInt32(style); s.ReadUInt32(foregroundColor); s.ReadUInt32(backgroundColor); - hatchStyle = static_cast(style); + hatchStyle = style; solidColor = ::Color(ColorAlpha, (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff); secondColor = ::Color(ColorAlpha, (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tHatch style: 0x" << std::hex << style); @@ -120,7 +121,7 @@ namespace emfplushelper { s.ReadUInt32(additionalFlags).ReadInt32(wrapMode); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tAdditional flags: 0x" << std::hex << additionalFlags << std::dec); - sal_uInt32 color; + sal_uInt32 color(0); s.ReadUInt32(color); solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tCenter color: 0x" << std::hex << color << std::dec); @@ -129,6 +130,12 @@ namespace emfplushelper s.ReadUInt32(surroundColorsNumber); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t number of surround colors: " << surroundColorsNumber); + if (surroundColorsNumber > s.remainingSize() / sizeof(sal_uInt32)) + { + SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated surround colors"); + return; + } + surroundColors.reset( new ::Color[surroundColorsNumber] ); for (sal_uInt32 i = 0; i < surroundColorsNumber; i++) @@ -142,15 +149,15 @@ namespace emfplushelper if (additionalFlags & 0x01) // BrushDataPath { - sal_Int32 pathLength; + sal_Int32 pathLength(0); s.ReadInt32(pathLength); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPath length: " << pathLength); sal_uInt64 const pos = s.Tell(); - sal_uInt32 pathHeader; - sal_Int32 pathPoints, pathFlags; + sal_uInt32 pathHeader(0); + sal_Int32 pathPoints(0), pathFlags(0); s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPath (brush path gradient)"); @@ -171,15 +178,25 @@ namespace emfplushelper } else { - sal_Int32 boundaryPointCount; + sal_Int32 boundaryPointCount(0); s.ReadInt32(boundaryPointCount); sal_uInt64 const pos = s.Tell(); SAL_INFO("drawinglayer.emf", "EMF+\t use boundary, points: " << boundaryPointCount); - path.reset( new EMFPPath(boundaryPointCount) ); + + sal_uInt64 const nBytesPerPoint = 2 * sizeof(float); + sal_uInt64 const nMaxPoints = s.remainingSize() / nBytesPerPoint; + if (boundaryPointCount < 0 + || o3tl::make_unsigned(boundaryPointCount) > nMaxPoints) + { + SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated boundary points"); + return; + } + + path.reset( new EMFPPath(boundaryPointCount, false/*bHasPointTypes*/) ); path->Read(s, 0x0); - s.Seek(pos + 8 * boundaryPointCount); + s.Seek(pos + nBytesPerPoint * boundaryPointCount); const ::basegfx::B2DRectangle aBounds(path->GetPolygon(rR, false).getB2DRange()); aWidth = aBounds.getWidth(); @@ -205,6 +222,13 @@ namespace emfplushelper { s.ReadUInt32(blendPoints); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tuse blend, points: " << blendPoints); + + if (blendPoints > s.remainingSize() / (2 * sizeof(float))) + { + SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated blend points"); + return; + } + blendPositions.reset( new float[2 * blendPoints] ); blendFactors = blendPositions.get() + blendPoints; @@ -225,6 +249,13 @@ namespace emfplushelper { s.ReadUInt32(colorblendPoints); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints); + + if (colorblendPoints > s.remainingSize() / (sizeof(float) + sizeof(sal_uInt32))) + { + SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated color blend points"); + return; + } + colorblendPositions.reset( new float[colorblendPoints] ); colorblendColors.reset( new ::Color[colorblendPoints] ); @@ -251,7 +282,7 @@ namespace emfplushelper s.ReadFloat(firstPointX).ReadFloat(firstPointY).ReadFloat(aWidth).ReadFloat(aHeight); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tFirst gradient point: " << firstPointX << ":" << firstPointY << ", size " << aWidth << "x" << aHeight); - sal_uInt32 color; + sal_uInt32 color(0); s.ReadUInt32(color); solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tfirst color: 0x" << std::hex << color << std::dec); @@ -280,6 +311,13 @@ namespace emfplushelper { s.ReadUInt32(blendPoints); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse blend, points: " << blendPoints); + + if (blendPoints > s.remainingSize() / (2 * sizeof(float))) + { + SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated blend points"); + return; + } + blendPositions.reset( new float[2 * blendPoints] ); blendFactors = blendPositions.get() + blendPoints; @@ -300,6 +338,13 @@ namespace emfplushelper { s.ReadUInt32(colorblendPoints); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints); + + if (colorblendPoints > s.remainingSize() / (sizeof(float) + sizeof(sal_uInt32))) + { + SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated color blend points"); + return; + } + colorblendPositions.reset( new float[colorblendPoints] ); colorblendColors.reset( new ::Color[colorblendPoints] ); diff --git a/drawinglayer/source/tools/emfpbrush.hxx b/drawinglayer/source/tools/emfpbrush.hxx index d50df7176133..d61a6d300fc1 100644 --- a/drawinglayer/source/tools/emfpbrush.hxx +++ b/drawinglayer/source/tools/emfpbrush.hxx @@ -114,7 +114,7 @@ namespace emfplushelper sal_uInt32 surroundColorsNumber; std::unique_ptr<::Color[]> surroundColors; std::unique_ptr path; - EmfPlusHatchStyle hatchStyle; + sal_uInt32 hatchStyle; std::unique_ptr textureImage; EMFPBrush(); diff --git a/drawinglayer/source/tools/emfpcustomlinecap.cxx b/drawinglayer/source/tools/emfpcustomlinecap.cxx index 351b2e82dd6d..792e12e4d68e 100644 --- a/drawinglayer/source/tools/emfpcustomlinecap.cxx +++ b/drawinglayer/source/tools/emfpcustomlinecap.cxx @@ -46,11 +46,11 @@ namespace emfplushelper void EMFPCustomLineCap::ReadPath(SvStream& s, EmfPlusHelperData const & rR, bool bFill) { - sal_Int32 pathLength; + sal_Int32 pathLength(0); s.ReadInt32(pathLength); SAL_INFO("drawinglayer.emf", "EMF+\t\tpath length: " << pathLength); - sal_uInt32 pathHeader; - sal_Int32 pathPoints, pathFlags; + sal_uInt32 pathHeader(0); + sal_Int32 pathPoints(0), pathFlags(0); s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags); SAL_INFO("drawinglayer.emf", "EMF+\t\tpath (custom cap line path)"); SAL_INFO("drawinglayer.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec); @@ -65,16 +65,16 @@ namespace emfplushelper void EMFPCustomLineCap::Read(SvStream& s, EmfPlusHelperData const & rR) { - sal_uInt32 header; + sal_uInt32 header(0); s.ReadUInt32(header).ReadUInt32(type); SAL_INFO("drawinglayer.emf", "EMF+\t\tcustom cap"); SAL_INFO("drawinglayer.emf", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec); if (type == EmfPlusCustomLineCapDataTypeDefault) { - sal_uInt32 customLineCapDataFlags, baseCap; - float baseInset; - float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY; + sal_uInt32 customLineCapDataFlags(0), baseCap(0); + float baseInset(0); + float fillHotSpotX(0), fillHotSpotY(0), strokeHotSpotX(0), strokeHotSpotY(0); s.ReadUInt32(customLineCapDataFlags).ReadUInt32(baseCap).ReadFloat(baseInset) .ReadUInt32(strokeStartCap).ReadUInt32(strokeEndCap).ReadUInt32(strokeJoin) @@ -100,8 +100,8 @@ namespace emfplushelper // TODO only reads the data, does not use them [I've had // no test document to be able to implement it] - sal_Int32 fillState; - float width, height, middleInset, unusedHotSpot; + sal_Int32 fillState(0); + float width(0), height(0), middleInset(0), unusedHotSpot(0); s.ReadFloat(width).ReadFloat(height).ReadFloat(middleInset).ReadInt32(fillState).ReadUInt32(strokeStartCap) .ReadUInt32(strokeEndCap).ReadUInt32(strokeJoin).ReadFloat(miterLimit).ReadFloat(widthScale) diff --git a/drawinglayer/source/tools/emfpfont.cxx b/drawinglayer/source/tools/emfpfont.cxx index 3fd6537e75a0..bd10cb439b7e 100644 --- a/drawinglayer/source/tools/emfpfont.cxx +++ b/drawinglayer/source/tools/emfpfont.cxx @@ -44,9 +44,9 @@ namespace emfplushelper void EMFPFont::Read(SvMemoryStream &s) { - sal_uInt32 header; - sal_uInt32 reserved; - sal_uInt32 length; + sal_uInt32 header(0); + sal_uInt32 reserved(0); + sal_uInt32 length(0); s.ReadUInt32(header).ReadFloat(emSize).ReadUInt32(sizeUnit).ReadInt32(fontFlags).ReadUInt32(reserved).ReadUInt32(length); SAL_WARN_IF((header >> 12) != 0xdbc01, "drawinglayer.emf", "Invalid header - not 0xdbc01"); SAL_INFO("drawinglayer.emf", "EMF+\tHeader: 0x" << std::hex << (header >> 12)); diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx index a7fb1d14eaaa..c38fd226ca00 100644 --- a/drawinglayer/source/tools/emfphelperdata.cxx +++ b/drawinglayer/source/tools/emfphelperdata.cxx @@ -52,8 +52,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -289,7 +291,7 @@ namespace emfplushelper } case EmfPlusObjectTypePath: { - sal_uInt32 aVersion, aPathPointCount, aPathPointFlags; + sal_uInt32 aVersion(0), aPathPointCount(0), aPathPointFlags(0); rObjectStream.ReadUInt32(aVersion).ReadUInt32(aPathPointCount).ReadUInt32(aPathPointFlags); SAL_INFO("drawinglayer.emf", "EMF+\t\tVersion: 0x" << std::hex << aVersion); @@ -370,7 +372,7 @@ namespace emfplushelper if (flags & 0x4000) { - sal_Int16 ix, iy; + sal_Int16 ix(0), iy(0); s.ReadInt16(ix).ReadInt16(iy); @@ -387,7 +389,7 @@ namespace emfplushelper { if (bCompressed) { - sal_Int16 ix, iy, iw, ih; + sal_Int16 ix(0), iy(0), iw(0), ih(0); s.ReadInt16(ix).ReadInt16(iy).ReadInt16(iw).ReadInt16(ih); @@ -448,7 +450,7 @@ namespace emfplushelper maMapTransform = maWorldTransform; maMapTransform.scale(mfPageScaleX, mfPageScaleY); maMapTransform *= basegfx::utils::createScaleTranslateB2DHomMatrix(100.0 * mnMmX / mnPixX, 100.0 * mnMmY / mnPixY, - double(-mnFrameLeft), double(-mnFrameTop)); + -double(mnFrameLeft), -double(mnFrameTop)); maMapTransform *= maBaseTransform; // Used only for performance optimization, to do not calculate it every line draw @@ -609,7 +611,8 @@ namespace emfplushelper drawinglayer::attribute::LineStartEndAttribute aStart; if (pen->penDataFlags & EmfPlusPenDataStartCap) { - if ((pen->penDataFlags & EmfPlusPenDataCustomStartCap) + if ((pen->penDataFlags & EmfPlusPenDataCustomStartCap) && pen->customStartCap + && pen->customStartCap->polygon.count() && (pen->customStartCap->polygon.begin()->count() > 1)) aStart = drawinglayer::attribute::LineStartEndAttribute( pen->customStartCap->polygon.getB2DRange().getRange().getX() * mdExtractedXScale @@ -622,7 +625,8 @@ namespace emfplushelper drawinglayer::attribute::LineStartEndAttribute aEnd; if (pen->penDataFlags & EmfPlusPenDataEndCap) { - if ((pen->penDataFlags & EmfPlusPenDataCustomEndCap) + if ((pen->penDataFlags & EmfPlusPenDataCustomEndCap) && pen->customEndCap + && pen->customEndCap->polygon.count() && (pen->customEndCap->polygon.begin()->count() > 1)) aEnd = drawinglayer::attribute::LineStartEndAttribute( pen->customEndCap->polygon.getB2DRange().getRange().getX() * mdExtractedXScale @@ -672,6 +676,33 @@ namespace emfplushelper mrPropertyHolders.Current().setFillColorActive(false); } + // Convert a polypolygon so that nonzero/winding fill semantics produce + // the same visual result when rendered with the even-odd fill rule used + // by the primitive2d fill primitives. A self-intersecting single + // polygon is resolved by solveCrossovers + stripNeutralPolygons and the + // resulting sub-loops are merged. Multi-polygon inputs use + // createNonzeroConform which removes inner duplicates of nested + // same-orientation polygons. + static ::basegfx::B2DPolyPolygon convertWindingToEvenOdd( + const ::basegfx::B2DPolyPolygon& rIn) + { + if (rIn.count() == 1) + { + ::basegfx::B2DPolyPolygon aResolved + = ::basegfx::utils::solveCrossovers(rIn.getB2DPolygon(0)); + aResolved = ::basegfx::utils::stripNeutralPolygons(aResolved); + if (aResolved.count() > 1) + { + ::basegfx::B2DPolyPolygonVector aInput; + for (sal_uInt32 i = 0; i < aResolved.count(); ++i) + aInput.push_back(::basegfx::B2DPolyPolygon(aResolved.getB2DPolygon(i))); + return ::basegfx::utils::mergeToSinglePolyPolygon(aInput); + } + return aResolved; + } + return ::basegfx::utils::createNonzeroConform(rIn); + } + void EmfPlusHelperData::EMFPPlusFillPolygonSolidColor(const ::basegfx::B2DPolyPolygon& polygon, Color const& color) { if (color.GetAlpha() == 0) @@ -937,21 +968,498 @@ namespace emfplushelper aSpreadMethod)); } else // BrushTypePathGradient - { // TODO The PathGradient is not implemented, and Radial Gradient is used instead - basegfx::B2DPoint aCenterPoint = Map(brush->firstPointX, brush->firstPointY); - aCenterPoint = aPolygonTransformation * aCenterPoint; + { + // Render the gradient pattern into a small bitmap and use + // it as a (potentially tiled) texture fill. SvgRadialGradient + // alone cannot reproduce path-gradient tiling because the + // brush coordinate space and the fill-polygon space need + // not overlap. + if (!brush->path) + return; + + basegfx::B2DRange aBrushBounds( + brush->path->GetPolygon(*this, false).getB2DRange()); + if (aBrushBounds.getWidth() <= 0 || aBrushBounds.getHeight() <= 0) + return; + + constexpr sal_Int32 nMaxDim = 256; + sal_Int32 nBmpW, nBmpH; + if (aBrushBounds.getWidth() >= aBrushBounds.getHeight()) + { + nBmpW = nMaxDim; + nBmpH = std::max( + 1, std::lround(nMaxDim * aBrushBounds.getHeight() + / aBrushBounds.getWidth())); + } + else + { + nBmpH = nMaxDim; + nBmpW = std::max( + 1, std::lround(nMaxDim * aBrushBounds.getWidth() + / aBrushBounds.getHeight())); + } + + // Path-gradient sweep: GDI+ partitions the brush + // boundary into triangles formed by (centre, V_i, + // V_{i+1}) and Gouraud-shades each one with vertex + // colours (centerColor, surround[i], + // surround[(i+1) % nSurround]). Inside a triangle the + // pixel colour is the barycentric blend of the three + // vertex colours; this reproduces the colourful per- + // segment rendering that GDI+ produces (red/green/blue + // points on a star with multiple surround colours, and + // smooth radial gradient on a uniform-surround brush). + basegfx::B2DPolygon aSweepPolygon + = brush->path->GetPolygon(*this, false).getB2DPolygon(0); + // Flatten Bezier control points into straight-line + // segments so the triangulation has a fine-enough + // boundary. Without this, a 4-cardinal-vertex Bezier + // ellipse becomes 4 triangles meeting at the centre + // (a diamond), which is visibly wrong. + if (aSweepPolygon.areControlPointsUsed()) + aSweepPolygon = basegfx::utils::adaptiveSubdivideByDistance( + aSweepPolygon, + std::max(aBrushBounds.getWidth(), + aBrushBounds.getHeight()) / 512.0); + while (aSweepPolygon.count() >= 2 + && aSweepPolygon.getB2DPoint(0) + == aSweepPolygon.getB2DPoint(aSweepPolygon.count() - 1)) + aSweepPolygon.remove(aSweepPolygon.count() - 1); + + const sal_uInt32 nVerts = aSweepPolygon.count(); + const basegfx::B2DPoint aCentre( + brush->firstPointX, brush->firstPointY); + + // Per-vertex surround colour (one per boundary vertex). + // surroundColors[i] is a sal_uInt8-channel Color; convert + // to BColor (0..1 doubles) once. + std::vector aVertColor(nVerts); + std::vector aVertAlpha(nVerts); + { + const sal_uInt32 nSurr + = brush->surroundColorsNumber > 0 + ? brush->surroundColorsNumber + : 1; + for (sal_uInt32 i = 0; i < nVerts; ++i) + { + const Color& c + = brush->surroundColorsNumber > 0 + ? brush->surroundColors[i % nSurr] + : brush->secondColor; + aVertColor[i] = c.getBColor(); + aVertAlpha[i] = c.GetAlpha() / 255.0; + } + } + const basegfx::BColor aCentreColor + = brush->solidColor.getBColor(); + const double fCentreAlpha + = brush->solidColor.GetAlpha() / 255.0; + + // Optional centre->edge transition curves carried by the + // brush. BlendFactors remap the gradient parameter t + // (0 at centre, 1 at edge) before the centre/edge mix. + // PresetColors (colorblend) replace the centre/edge mix + // entirely with a sampled multi-stop colour curve. The + // two are mutually exclusive in well-formed EMF+ data. + struct FactorStop { double pos; double factor; }; + std::vector aFactorCurve; + if (brush->blendPositions && brush->blendPoints > 0) + { + aFactorCurve.reserve(brush->blendPoints); + for (sal_uInt32 i = 0; i < brush->blendPoints; ++i) + aFactorCurve.push_back({brush->blendPositions[i], + brush->blendFactors[i]}); + std::sort(aFactorCurve.begin(), aFactorCurve.end(), + [](const FactorStop& a, const FactorStop& b) + { return a.pos < b.pos; }); + } + + struct ColorStop { double pos; basegfx::BColor color; double alpha; }; + std::vector aColorCurve; + if (brush->colorblendPositions && brush->colorblendPoints > 0) + { + aColorCurve.reserve(brush->colorblendPoints); + for (sal_uInt32 i = 0; i < brush->colorblendPoints; ++i) + aColorCurve.push_back( + {brush->colorblendPositions[i], + brush->colorblendColors[i].getBColor(), + brush->colorblendColors[i].GetAlpha() / 255.0}); + std::sort(aColorCurve.begin(), aColorCurve.end(), + [](const ColorStop& a, const ColorStop& b) + { return a.pos < b.pos; }); + } + + auto sampleFactor = [&aFactorCurve](double t) -> double + { + if (aFactorCurve.empty()) return t; + if (t <= aFactorCurve.front().pos) + return aFactorCurve.front().factor; + if (t >= aFactorCurve.back().pos) + return aFactorCurve.back().factor; + for (size_t i = 0; i + 1 < aFactorCurve.size(); ++i) + { + if (t <= aFactorCurve[i + 1].pos) + { + const double span + = aFactorCurve[i + 1].pos - aFactorCurve[i].pos; + const double f + = span > 0.0 ? (t - aFactorCurve[i].pos) / span : 0.0; + return aFactorCurve[i].factor + + f * (aFactorCurve[i + 1].factor + - aFactorCurve[i].factor); + } + } + return aFactorCurve.back().factor; + }; + + auto sampleColor = [&aColorCurve](double t) + -> std::pair + { + if (aColorCurve.empty()) return {basegfx::BColor(), 1.0}; + if (t <= aColorCurve.front().pos) + return {aColorCurve.front().color, + aColorCurve.front().alpha}; + if (t >= aColorCurve.back().pos) + return {aColorCurve.back().color, + aColorCurve.back().alpha}; + for (size_t i = 0; i + 1 < aColorCurve.size(); ++i) + { + if (t <= aColorCurve[i + 1].pos) + { + const double span + = aColorCurve[i + 1].pos - aColorCurve[i].pos; + const double f + = span > 0.0 ? (t - aColorCurve[i].pos) / span : 0.0; + basegfx::BColor c; + c.setRed(aColorCurve[i].color.getRed() + + f * (aColorCurve[i + 1].color.getRed() + - aColorCurve[i].color.getRed())); + c.setGreen(aColorCurve[i].color.getGreen() + + f * (aColorCurve[i + 1].color.getGreen() + - aColorCurve[i].color.getGreen())); + c.setBlue(aColorCurve[i].color.getBlue() + + f * (aColorCurve[i + 1].color.getBlue() + - aColorCurve[i].color.getBlue())); + return {c, aColorCurve[i].alpha + + f * (aColorCurve[i + 1].alpha + - aColorCurve[i].alpha)}; + } + } + return {aColorCurve.back().color, + aColorCurve.back().alpha}; + }; + + auto signedCross = [](const basegfx::B2DPoint& a, + const basegfx::B2DPoint& b, + const basegfx::B2DPoint& c) -> double + { + return (b.getX() - a.getX()) * (c.getY() - a.getY()) + - (b.getY() - a.getY()) * (c.getX() - a.getX()); + }; + + // Compose the final pixel colour given the active + // boundary segment index i, the segment-edge weights + // w0/w1 and the centre-edge parameter tRaw. Mixes the + // per-segment surround colours (Gouraud) and applies + // the brush's blend curve when present. + auto composeColor + = [&aVertColor, &aVertAlpha, &aCentreColor, &fCentreAlpha, + &aColorCurve, &sampleColor, &sampleFactor, nVerts]( + sal_uInt32 i, double w0, double w1, double tRaw, + basegfx::BColor& outColor, double& outAlpha) + { + basegfx::BColor aEdgeColor; + double fEdgeAlpha = 0.0; + const double fEdgeSum = w0 + w1; + if (fEdgeSum > 1e-12) + { + const double f0 = w0 / fEdgeSum; + const double f1 = w1 / fEdgeSum; + aEdgeColor.setRed( + f0 * aVertColor[i].getRed() + + f1 * aVertColor[(i + 1) % nVerts].getRed()); + aEdgeColor.setGreen( + f0 * aVertColor[i].getGreen() + + f1 * aVertColor[(i + 1) % nVerts].getGreen()); + aEdgeColor.setBlue( + f0 * aVertColor[i].getBlue() + + f1 * aVertColor[(i + 1) % nVerts].getBlue()); + fEdgeAlpha + = f0 * aVertAlpha[i] + + f1 * aVertAlpha[(i + 1) % nVerts]; + } + else + { + aEdgeColor = aVertColor[i]; + fEdgeAlpha = aVertAlpha[i]; + } + if (!aColorCurve.empty()) + { + // PresetColors override the centre/edge mix. + auto [presetColor, presetAlpha] = sampleColor(tRaw); + outColor = presetColor; + outAlpha = presetAlpha; + } + else + { + // BlendFactors remap tRaw before mixing centre + // and (per-segment Gouraud) edge colour. With + // an empty factor curve sampleFactor returns t + // unchanged so the mix is linear. + const double tCurve = sampleFactor(tRaw); + outColor.setRed( + (1.0 - tCurve) * aCentreColor.getRed() + + tCurve * aEdgeColor.getRed()); + outColor.setGreen( + (1.0 - tCurve) * aCentreColor.getGreen() + + tCurve * aEdgeColor.getGreen()); + outColor.setBlue( + (1.0 - tCurve) * aCentreColor.getBlue() + + tCurve * aEdgeColor.getBlue()); + outAlpha = (1.0 - tCurve) * fCentreAlpha + + tCurve * fEdgeAlpha; + } + }; + + Bitmap aBmp(Size(nBmpW, nBmpH), vcl::PixelFormat::N32_BPP); + AlphaMask aAlpha(Size(nBmpW, nBmpH)); + aBmp.Erase(COL_BLACK); + aAlpha.Erase(255); + { + BitmapScopedWriteAccess pBmpWrite(aBmp); + BitmapScopedWriteAccess pAlphaWrite(aAlpha); + if (!pBmpWrite || !pAlphaWrite) + return; + + // Track which pixels Pass 1 has painted so the + // Clamp-mode Pass 2 can find the rest. Alpha == 0 + // alone is not a reliable "uncovered" marker + // because a translucent surround colour can + // legitimately produce alpha == 0 inside a fan + // triangle. + std::vector aCovered( + static_cast(nBmpW) * nBmpH, false); + + auto writePixel + = [&pBmpWrite, &pAlphaWrite, &aCovered, nBmpW]( + sal_Int32 x, sal_Int32 y, + const basegfx::BColor& c, double a) + { + pBmpWrite->SetPixel(y, x, BitmapColor( + static_cast(std::lround(std::clamp(c.getRed(), 0.0, 1.0) * 255)), + static_cast(std::lround(std::clamp(c.getGreen(), 0.0, 1.0) * 255)), + static_cast(std::lround(std::clamp(c.getBlue(), 0.0, 1.0) * 255)))); + pAlphaWrite->SetPixelIndex(y, x, static_cast( + std::lround(std::clamp(a, 0.0, 1.0) * 255))); + aCovered[static_cast(y) * nBmpW + x] = true; + }; + + // Pixel <-> brush-coord helpers. A pixel at integer + // (x,y) has its centre at world coord + // bb.minX + (x + 0.5) / nBmpW * bb.width + // (and similarly for y). + auto pixelToWorld + = [&aBrushBounds, nBmpW, nBmpH]( + sal_Int32 x, sal_Int32 y) -> basegfx::B2DPoint + { + return basegfx::B2DPoint( + aBrushBounds.getMinX() + + (x + 0.5) / nBmpW * aBrushBounds.getWidth(), + aBrushBounds.getMinY() + + (y + 0.5) / nBmpH * aBrushBounds.getHeight()); + }; + auto worldToPixelX + = [&aBrushBounds, nBmpW](double wx) -> double + { + return (wx - aBrushBounds.getMinX()) * nBmpW + / aBrushBounds.getWidth() - 0.5; + }; + auto worldToPixelY + = [&aBrushBounds, nBmpH](double wy) -> double + { + return (wy - aBrushBounds.getMinY()) * nBmpH + / aBrushBounds.getHeight() - 0.5; + }; + + // Pass 1: rasterize each fan triangle (centre, + // V_i, V_{i+1}) by iterating only the triangle's + // pixel-space AABB. Cost is O(sum of triangle + // areas), not O(bitmap area * triangle count). + // Structurally this is what cairo's mesh-pattern + // rasterizer does for PDF type-7 shadings: each + // patch paints into its own pixel range, rather + // than every pixel testing every patch. + for (sal_uInt32 i = 0; i < nVerts; ++i) + { + const basegfx::B2DPoint aV0 + = aSweepPolygon.getB2DPoint(i); + const basegfx::B2DPoint aV1 + = aSweepPolygon.getB2DPoint((i + 1) % nVerts); + // Total triangle area (signed). Sign of + // fTotal carries the polygon winding; a + // point is inside the triangle when all + // three sub-areas have that same sign. + const double fTotal + = signedCross(aCentre, aV0, aV1); + if (std::abs(fTotal) < 1e-12) + continue; + const double s = fTotal > 0.0 ? 1.0 : -1.0; + const double fInvAbsTotal = 1.0 / std::abs(fTotal); + + const double fMinX = std::min({aCentre.getX(), aV0.getX(), aV1.getX()}); + const double fMaxX = std::max({aCentre.getX(), aV0.getX(), aV1.getX()}); + const double fMinY = std::min({aCentre.getY(), aV0.getY(), aV1.getY()}); + const double fMaxY = std::max({aCentre.getY(), aV0.getY(), aV1.getY()}); + const sal_Int32 nXMin = std::clamp( + static_cast(std::floor(worldToPixelX(fMinX))), + 0, nBmpW - 1); + const sal_Int32 nXMax = std::clamp( + static_cast(std::ceil(worldToPixelX(fMaxX))), + 0, nBmpW - 1); + const sal_Int32 nYMin = std::clamp( + static_cast(std::floor(worldToPixelY(fMinY))), + 0, nBmpH - 1); + const sal_Int32 nYMax = std::clamp( + static_cast(std::ceil(worldToPixelY(fMaxY))), + 0, nBmpH - 1); + + for (sal_Int32 y = nYMin; y <= nYMax; ++y) + { + for (sal_Int32 x = nXMin; x <= nXMax; ++x) + { + const basegfx::B2DPoint aP = pixelToWorld(x, y); + // Barycentric weights via signed + // sub-triangle areas. wC = area(P, + // V0, V1) / area(C, V0, V1) etc. + const double wC + = s * signedCross(aP, aV0, aV1) * fInvAbsTotal; + const double w0 + = s * signedCross(aCentre, aP, aV1) * fInvAbsTotal; + const double w1 + = s * signedCross(aCentre, aV0, aP) * fInvAbsTotal; + constexpr double EPS = -1e-9; + if (wC < EPS || w0 < EPS || w1 < EPS) + continue; + // Centre/edge parameter (0 at centre, + // 1 at boundary segment). + const double tRaw + = std::clamp(1.0 - wC, 0.0, 1.0); + basegfx::BColor aColor; + double fAlpha = 0.0; + composeColor(i, w0, w1, tRaw, aColor, fAlpha); + writePixel(x, y, aColor, fAlpha); + } + } + } + + // Pass 2 (Clamp wrap mode): for pixels that fell + // outside every fan triangle, fill with the + // closest triangle's edge colour. This + // eliminates sub-pixel transparent jaggies along + // smooth Bezier fill polygons that extend + // slightly past the flattened boundary. + // + // For other wrap modes we leave uncovered pixels + // transparent so that adjacent tiles in the fill + // polygon stay visually separate. + if (brush->wrapMode == WrapModeClamp) + { + for (sal_Int32 y = 0; y < nBmpH; ++y) + { + for (sal_Int32 x = 0; x < nBmpW; ++x) + { + if (aCovered[static_cast(y) * nBmpW + x]) + continue; + const basegfx::B2DPoint aP = pixelToWorld(x, y); + sal_uInt32 nClosestI = 0; + double fClosestW0 = 0.0; + double fClosestW1 = 0.0; + double fMaxNegMargin + = std::numeric_limits::lowest(); + for (sal_uInt32 i = 0; i < nVerts; ++i) + { + const basegfx::B2DPoint aV0 + = aSweepPolygon.getB2DPoint(i); + const basegfx::B2DPoint aV1 + = aSweepPolygon.getB2DPoint((i + 1) % nVerts); + const double fTotal + = signedCross(aCentre, aV0, aV1); + if (std::abs(fTotal) < 1e-12) + continue; + const double s + = fTotal > 0.0 ? 1.0 : -1.0; + const double fInvAbsTotal + = 1.0 / std::abs(fTotal); + const double wC + = s * signedCross(aP, aV0, aV1) * fInvAbsTotal; + const double w0 + = s * signedCross(aCentre, aP, aV1) * fInvAbsTotal; + const double w1 + = s * signedCross(aCentre, aV0, aP) * fInvAbsTotal; + const double fMin + = std::min({wC, w0, w1}); + if (fMin > fMaxNegMargin) + { + fMaxNegMargin = fMin; + nClosestI = i; + fClosestW0 = w0; + fClosestW1 = w1; + } + } + // The pixel is outside its closest + // triangle (wC < 0), so the centre/ + // edge parameter clamps to 1 and the + // colour is the pure edge mix. + basegfx::BColor aColor; + double fAlpha = 0.0; + composeColor(nClosestI, fClosestW0, + fClosestW1, 1.0, + aColor, fAlpha); + writePixel(x, y, aColor, fAlpha); + } + } + } + } + Graphic aGraphic(Bitmap(aBmp, aAlpha)); + + // Map bitmap [0,1] to the brush's bounds in raw EMF + // coords (with translation so the bitmap is anchored + // where the brush actually lives, not at world origin). + // maMapTransform then converts to world space, where + // the fill polygon also lives - so the bitmap content + // aligns with the fill polygon. + const basegfx::B2DHomMatrix aBitmapToBrushSpace( + aBrushBounds.getWidth(), 0.0, aBrushBounds.getMinX(), + 0.0, aBrushBounds.getHeight(), aBrushBounds.getMinY()); + + basegfx::B2DHomMatrix aBrushMatrix; + if (brush->hasTransformation) + aBrushMatrix = brush->brush_transformation; + + const basegfx::B2DHomMatrix aTotalMatrix + = maMapTransform * aBrushMatrix * aBitmapToBrushSpace; + + basegfx::B2DHomMatrix aInvTotalMatrix = aTotalMatrix; + if (!aInvTotalMatrix.invert()) + return; + basegfx::B2DPolyPolygon aLocalPolygon = polygon; + aLocalPolygon.transform(aInvTotalMatrix); + + const bool bIsTiled = (brush->wrapMode != WrapModeClamp); + + const drawinglayer::attribute::FillGraphicAttribute aFillAttribute( + aGraphic, basegfx::B2DRange(0.0, 0.0, 1.0, 1.0), bIsTiled); + + drawinglayer::primitive2d::Primitive2DReference xFillPrimitive + = new drawinglayer::primitive2d::PolyPolygonGraphicPrimitive2D( + aLocalPolygon, + basegfx::B2DRange(0.0, 0.0, 1.0, 1.0), + aFillAttribute); - // create the same one used for SVG mrTargetHolders.Current().append( - new drawinglayer::primitive2d::SvgRadialGradientPrimitive2D( - aTextureTransformation, - polygon, - std::move(aVector), - aCenterPoint, - 0.7, // relative radius little bigger to cover all elements - true, // use UnitCoordinates to stretch the gradient - drawinglayer::primitive2d::SpreadMethod::Pad, - nullptr)); + new drawinglayer::primitive2d::TransformPrimitive2D( + aTotalMatrix, + drawinglayer::primitive2d::Primitive2DContainer({ xFillPrimitive }))); } } } @@ -1055,14 +1563,11 @@ namespace emfplushelper // 12 is minimal valid EMF+ record size; remaining bytes are padding while (length >= 12) { - sal_uInt16 type, flags; - sal_uInt32 size, dataSize; - sal_uInt64 next; + sal_uInt16 type(0), flags(0); + sal_uInt32 size(0), dataSize(0); rMS.ReadUInt16(type).ReadUInt16(flags).ReadUInt32(size).ReadUInt32(dataSize); - next = rMS.Tell() + (size - 12); - if (size < 12) { SAL_WARN("drawinglayer.emf", "Size field is less than 12 bytes"); @@ -1074,6 +1579,8 @@ namespace emfplushelper break; } + sal_uInt64 next = rMS.Tell() + (size - 12); + if (dataSize > (size - 12)) { SAL_WARN("drawinglayer.emf", "DataSize field is greater than Size-12"); @@ -1103,6 +1610,12 @@ namespace emfplushelper } if (type == EmfPlusRecordTypeObject && ((mbMultipart && (flags & 0x7fff) == (mMFlags & 0x7fff)) || (flags & 0x8000))) { + if (dataSize < 4) + { + SAL_WARN("drawinglayer.emf", "DataSize field has no room for TotalObjectSize"); + break; + } + if (!mbMultipart) { mbMultipart = true; @@ -1110,8 +1623,6 @@ namespace emfplushelper mMStream.Seek(0); } - OSL_ENSURE(dataSize >= 4, "No room for TotalObjectSize in EmfPlusContinuedObjectRecord"); - // 1st 4 bytes are TotalObjectSize mMStream.WriteBytes(static_cast(rMS.GetData()) + rMS.Tell() + 4, dataSize - 4); SAL_INFO("drawinglayer.emf", "EMF+ read next object part size: " << size << " type: " << type << " flags: " << flags << " data size: " << dataSize); @@ -1134,7 +1645,7 @@ namespace emfplushelper { case EmfPlusRecordTypeHeader: { - sal_uInt32 version, emfPlusFlags; + sal_uInt32 version(0), emfPlusFlags(0); SAL_INFO("drawinglayer.emf", "EMF+\tDual: " << ((flags & 1) ? "true" : "false")); rMS.ReadUInt32(version).ReadUInt32(emfPlusFlags).ReadUInt32(mnHDPI).ReadUInt32(mnVDPI); @@ -1191,7 +1702,7 @@ namespace emfplushelper case EmfPlusRecordTypeDrawPie: case EmfPlusRecordTypeDrawArc: { - float startAngle, sweepAngle; + float startAngle(0), sweepAngle(0); // Silent MSVC warning C4701: potentially uninitialized local variable 'brushIndexOrColor' used sal_uInt32 brushIndexOrColor = 999; @@ -1211,7 +1722,7 @@ namespace emfplushelper } rMS.ReadFloat(startAngle).ReadFloat(sweepAngle); - float dx, dy, dw, dh; + float dx(0), dy(0), dw(0), dh(0); ReadRectangle(rMS, dx, dy, dw, dh, bool(flags & 0x4000)); SAL_INFO("drawinglayer.emf", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh); startAngle = basegfx::deg2rad(startAngle); @@ -1258,7 +1769,7 @@ namespace emfplushelper case EmfPlusRecordTypeFillPath: { sal_uInt32 index = flags & 0xff; - sal_uInt32 brushIndexOrColor; + sal_uInt32 brushIndexOrColor(0); rMS.ReadUInt32(brushIndexOrColor); SAL_INFO("drawinglayer.emf", "EMF+ FillPath slot: " << index); @@ -1272,7 +1783,7 @@ namespace emfplushelper case EmfPlusRecordTypeFillRegion: { sal_uInt32 index = flags & 0xff; - sal_uInt32 brushIndexOrColor; + sal_uInt32 brushIndexOrColor(0); rMS.ReadUInt32(brushIndexOrColor); SAL_INFO("drawinglayer.emf", "EMF+\t FillRegion slot: " << index); @@ -1297,7 +1808,7 @@ namespace emfplushelper } SAL_INFO("drawinglayer.emf", "EMF+\t " << (type == EmfPlusRecordTypeFillEllipse ? "Fill" : "Draw") << "Ellipse slot: " << (flags & 0xff)); - float dx, dy, dw, dh; + float dx(0), dy(0), dw(0), dh(0); ReadRectangle(rMS, dx, dy, dw, dh, bool(flags & 0x4000)); SAL_INFO("drawinglayer.emf", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh); ::basegfx::B2DPolyPolygon polyPolygon( @@ -1316,8 +1827,8 @@ namespace emfplushelper // Silent MSVC warning C4701: potentially uninitialized local variable 'brushIndexOrColor' used sal_uInt32 brushIndexOrColor = 999; ::basegfx::B2DPolyPolygon polyPolygon; - sal_uInt32 rectangles; - float x, y, width, height; + sal_uInt32 rectangles(0); + float x(0), y(0), width(0), height(0); const bool isColor = (flags & 0x8000); ::basegfx::B2DPolygon polygon; @@ -1344,24 +1855,37 @@ namespace emfplushelper polygon.setClosed(true); SAL_INFO("drawinglayer.emf", "EMF+\t\t rectangle: " << x << ", "<< y << " " << width << "x" << height); - polyPolygon.append(polygon); + + if (type == EmfPlusRecordTypeFillRects) + { + // Per MS-EMFPLUS each rect fills its + // interior independently. Emitting them + // as one polypolygon would cancel + // pairwise overlaps under drawinglayer's + // even-odd fill rule, leaving hollow + // stripes where overlapping squares meet. + EMFPPlusFillPolygon(::basegfx::B2DPolyPolygon(polygon), + isColor, brushIndexOrColor); + } + else + { + polyPolygon.append(polygon); + } } - if (type == EmfPlusRecordTypeFillRects) - EMFPPlusFillPolygon(polyPolygon, isColor, brushIndexOrColor); - else + if (type == EmfPlusRecordTypeDrawRects) EMFPPlusDrawPolygon(polyPolygon, flags & 0xff); break; } case EmfPlusRecordTypeFillPolygon: { - sal_uInt32 brushIndexOrColor, points; + sal_uInt32 brushIndexOrColor(0), points(0); rMS.ReadUInt32(brushIndexOrColor); rMS.ReadUInt32(points); SAL_INFO("drawinglayer.emf", "EMF+\t Points: " << points); SAL_INFO("drawinglayer.emf", "EMF+\t " << ((flags & 0x8000) ? "Color" : "Brush index") << " : 0x" << std::hex << brushIndexOrColor << std::dec); - EMFPPath path(points, true); + EMFPPath path(points, false/*bHasPointTypes*/); path.Read(rMS, flags); EMFPPlusFillPolygon(path.GetPolygon(*this), flags & 0x8000, brushIndexOrColor); @@ -1369,10 +1893,10 @@ namespace emfplushelper } case EmfPlusRecordTypeDrawLines: { - sal_uInt32 points; + sal_uInt32 points(0); rMS.ReadUInt32(points); SAL_INFO("drawinglayer.emf", "EMF+\t Points: " << points); - EMFPPath path(points, true); + EMFPPath path(points, false/*bHasPointTypes*/); path.Read(rMS, flags); // 0x2000 bit indicates whether to draw an extra line between the last point @@ -1383,7 +1907,7 @@ namespace emfplushelper } case EmfPlusRecordTypeDrawPath: { - sal_uInt32 penIndex; + sal_uInt32 penIndex(0); rMS.ReadUInt32(penIndex); SAL_INFO("drawinglayer.emf", "EMF+\t Pen: " << penIndex); @@ -1397,8 +1921,8 @@ namespace emfplushelper } case EmfPlusRecordTypeDrawBeziers: { - sal_uInt32 aCount; - float x1, y1, x2, y2, x3, y3, x4, y4; + sal_uInt32 aCount(0); + float x1(0), y1(0), x2(0), y2(0), x3(0), y3(0), x4(0), y4(0); ::basegfx::B2DPolygon aPolygon; rMS.ReadUInt32(aCount); SAL_INFO("drawinglayer.emf", "EMF+\t DrawBeziers slot: " << (flags & 0xff)); @@ -1436,8 +1960,8 @@ namespace emfplushelper } case EmfPlusRecordTypeDrawCurve: { - sal_uInt32 aOffset, aNumSegments, points; - float aTension; + sal_uInt32 aOffset(0), aNumSegments(0), points(0); + float aTension(0); rMS.ReadFloat(aTension); rMS.ReadUInt32(aOffset); rMS.ReadUInt32(aNumSegments); @@ -1447,7 +1971,7 @@ namespace emfplushelper << " NumSegments: " << aNumSegments << " Points: " << points); - EMFPPath path(points, true); + EMFPPath path(points, false/*bHasPointTypes*/); path.Read(rMS, flags); if (points >= 2) @@ -1463,7 +1987,7 @@ namespace emfplushelper { // Silent MSVC warning C4701: potentially uninitialized local variable 'brushIndexOrColor' used sal_uInt32 brushIndexOrColor = 999, points; - float aTension; + float aTension(0); if (type == EmfPlusRecordTypeFillClosedCurve) { rMS.ReadUInt32(brushIndexOrColor); @@ -1483,11 +2007,16 @@ namespace emfplushelper SAL_WARN("drawinglayer.emf", "Not enough number of points"); break; } - EMFPPath path(points, true); + EMFPPath path(points, false/*bHasPointTypes*/); path.Read(rMS, flags); if (type == EmfPlusRecordTypeFillClosedCurve) - EMFPPlusFillPolygon(path.GetClosedCardinalSpline(*this, aTension), - flags & 0x8000, brushIndexOrColor); + { + ::basegfx::B2DPolyPolygon aPoly + = path.GetClosedCardinalSpline(*this, aTension); + if (flags & 0x2000) + aPoly = convertWindingToEvenOdd(aPoly); + EMFPPlusFillPolygon(aPoly, flags & 0x8000, brushIndexOrColor); + } else EMFPPlusDrawPolygon(path.GetClosedCardinalSpline(*this, aTension), flags & 0xff); @@ -1496,8 +2025,8 @@ namespace emfplushelper case EmfPlusRecordTypeDrawImage: case EmfPlusRecordTypeDrawImagePoints: { - sal_uInt32 imageAttributesId; - sal_Int32 sourceUnit; + sal_uInt32 imageAttributesId(0); + sal_Int32 sourceUnit(0); rMS.ReadUInt32(imageAttributesId).ReadInt32(sourceUnit); SAL_INFO("drawinglayer.emf", "EMF+\t " << (type == EmfPlusRecordTypeDrawImage ? "DrawImage" @@ -1511,7 +2040,7 @@ namespace emfplushelper dynamic_cast(maEMFPObjects[flags & 0xff].get()) : nullptr) { - float sx, sy, sw, sh; + float sx(0), sy(0), sw(0), sh(0); ReadRectangle(rMS, sx, sy, sw, sh); ::tools::Rectangle aSource(Point(sx, sy), Size(sw + 1, sh + 1)); @@ -1527,7 +2056,7 @@ namespace emfplushelper double fShearY = 0.0; if (type == EmfPlusRecordTypeDrawImagePoints) { - sal_uInt32 aCount; + sal_uInt32 aCount(0); rMS.ReadUInt32(aCount); // Number of points used by DrawImagePoints. Exactly 3 points must be specified. @@ -1538,7 +2067,7 @@ namespace emfplushelper << aCount); break; } - float x1, y1, x2, y2, x3, y3; + float x1(0), y1(0), x2(0), y2(0), x3(0), y3(0); ReadPoint(rMS, x1, y1, flags); // upper-left point ReadPoint(rMS, x2, y2, flags); // upper-right @@ -1658,7 +2187,7 @@ namespace emfplushelper } case EmfPlusRecordTypeDrawString: { - sal_uInt32 brushId, formatId, stringLength; + sal_uInt32 brushId(0), formatId(0), stringLength(0); rMS.ReadUInt32(brushId).ReadUInt32(formatId).ReadUInt32(stringLength); SAL_INFO("drawinglayer.emf", "EMF+\t FontId: " << OUString::number(flags & 0xFF)); SAL_INFO("drawinglayer.emf", "EMF+\t BrushId: " << BrushIDToString(flags, brushId)); @@ -1666,7 +2195,7 @@ namespace emfplushelper SAL_INFO("drawinglayer.emf", "EMF+\t Length: " << stringLength); // read the layout rectangle - float lx, ly, lw, lh; + float lx(0), ly(0), lw(0), lh(0); rMS.ReadFloat(lx).ReadFloat(ly).ReadFloat(lw).ReadFloat(lh); SAL_INFO("drawinglayer.emf", "EMF+\t DrawString layoutRect: " << lx << "," << ly << " - " << lw << "x" << lh); @@ -1698,6 +2227,7 @@ namespace emfplushelper css::lang::Locale locale; double stringAlignmentHorizontalOffset = 0.0; double stringAlignmentVerticalOffset = font->emSize; + std::vector aDXArray; if (stringFormat) { LanguageTag aLanguageTag(static_cast(stringFormat->language)); @@ -1708,6 +2238,18 @@ namespace emfplushelper font->emSize, locale); double fTextWidth = aTextLayouter.getTextWidth(text, 0, stringLength); + + // Apply character spacing (tracking). Tracking is a multiplier on + // each character's natural advance; default 1.0 means no change. + if (stringFormat->tracking != 1.0f && stringLength > 0) + { + aDXArray = aTextLayouter.getTextArray(text, 0, stringLength); + for (double& rPos : aDXArray) + rPos *= stringFormat->tracking; + if (!aDXArray.empty()) + fTextWidth = aDXArray.back(); + } + SAL_WARN_IF(stringFormat->DirectionRightToLeft(), "drawinglayer.emf", "EMF+\t DrawString Alignment TODO For a right-to-left layout rectangle, the origin should be at the upper right."); if (stringFormat->stringAlignment == StringAlignmentNear) @@ -1774,7 +2316,6 @@ namespace emfplushelper if (color.GetAlpha() > 0) { - std::vector emptyVector; rtl::Reference pBaseText; if (font->Underline() || font->Strikeout()) { @@ -1783,7 +2324,7 @@ namespace emfplushelper text, 0, // text always starts at 0 stringLength, - std::move(emptyVector), // EMF-PLUS has no DX-array + std::move(aDXArray), {}, std::move(fontAttribute), locale, @@ -1807,7 +2348,7 @@ namespace emfplushelper text, 0, // text always starts at 0 stringLength, - std::move(emptyVector), // EMF-PLUS has no DX-array + std::move(aDXArray), {}, std::move(fontAttribute), std::move(locale), @@ -1830,7 +2371,7 @@ namespace emfplushelper } case EmfPlusRecordTypeSetPageTransform: { - float pageScale; + float pageScale(0); rMS.ReadFloat(pageScale); SAL_INFO("drawinglayer.emf", "EMF+\t Scale: " << pageScale << " unit: " << UnitTypeToString(flags)); @@ -1890,7 +2431,7 @@ namespace emfplushelper } case EmfPlusRecordTypeSave: { - sal_uInt32 stackIndex; + sal_uInt32 stackIndex(0); rMS.ReadUInt32(stackIndex); SAL_INFO("drawinglayer.emf", "EMF+\t Save stack index: " << stackIndex); @@ -1900,7 +2441,7 @@ namespace emfplushelper } case EmfPlusRecordTypeRestore: { - sal_uInt32 stackIndex; + sal_uInt32 stackIndex(0); rMS.ReadUInt32(stackIndex); SAL_INFO("drawinglayer.emf", "EMF+\t Restore stack index: " << stackIndex); @@ -1909,15 +2450,15 @@ namespace emfplushelper } case EmfPlusRecordTypeBeginContainer: { - float dx, dy, dw, dh; + float dx(0), dy(0), dw(0), dh(0); ReadRectangle(rMS, dx, dy, dw, dh); SAL_INFO("drawinglayer.emf", "EMF+\t Dest RectData: " << dx << "," << dy << " " << dw << "x" << dh); - float sx, sy, sw, sh; + float sx(0), sy(0), sw(0), sh(0); ReadRectangle(rMS, sx, sy, sw, sh); SAL_INFO("drawinglayer.emf", "EMF+\t Source RectData: " << sx << "," << sy << " " << sw << "x" << sh); - sal_uInt32 stackIndex; + sal_uInt32 stackIndex(0); rMS.ReadUInt32(stackIndex); SAL_INFO("drawinglayer.emf", "EMF+\t Begin Container stack index: " << stackIndex << ", PageUnit: " << flags); @@ -1933,7 +2474,7 @@ namespace emfplushelper } case EmfPlusRecordTypeBeginContainerNoParams: { - sal_uInt32 stackIndex; + sal_uInt32 stackIndex(0); rMS.ReadUInt32(stackIndex); SAL_INFO("drawinglayer.emf", "EMF+\t Begin Container No Params stack index: " << stackIndex); @@ -1942,7 +2483,7 @@ namespace emfplushelper } case EmfPlusRecordTypeEndContainer: { - sal_uInt32 stackIndex; + sal_uInt32 stackIndex(0); rMS.ReadUInt32(stackIndex); SAL_INFO("drawinglayer.emf", "EMF+\t End Container stack index: " << stackIndex); @@ -1996,7 +2537,7 @@ namespace emfplushelper SAL_INFO("drawinglayer.emf", "EMF+\t TranslateWorldTransform, Post multiply: " << bool(flags & 0x2000)); basegfx::B2DHomMatrix transform; - float eDx, eDy; + float eDx(0), eDy(0); rMS.ReadFloat(eDx).ReadFloat(eDy); transform.set(0, 2, eDx); transform.set(1, 2, eDy); @@ -2025,7 +2566,7 @@ namespace emfplushelper case EmfPlusRecordTypeScaleWorldTransform: { basegfx::B2DHomMatrix transform; - float eSx, eSy; + float eSx(0), eSy(0); rMS.ReadFloat(eSx).ReadFloat(eSy); transform.set(0, 0, eSx); transform.set(1, 1, eSy); @@ -2056,7 +2597,7 @@ namespace emfplushelper case EmfPlusRecordTypeRotateWorldTransform: { // Angle of rotation in degrees - float eAngle; + float eAngle(0); rMS.ReadFloat(eAngle); SAL_INFO("drawinglayer.emf", "EMF+\t RotateWorldTransform Angle: " << eAngle << @@ -2090,7 +2631,7 @@ namespace emfplushelper { SAL_INFO("drawinglayer.emf", "EMF+\t SetClipRect"); - float dx, dy, dw, dh; + float dx(0), dy(0), dw(0), dh(0); ReadRectangle(rMS, dx, dy, dw, dh); SAL_INFO("drawinglayer.emf", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh); @@ -2174,7 +2715,7 @@ namespace emfplushelper } case EmfPlusRecordTypeOffsetClip: { - float dx, dy; + float dx(0), dy(0); rMS.ReadFloat(dx).ReadFloat(dy); SAL_INFO("drawinglayer.emf", "EMF+\tOffset x:" << dx << ", y:" << dy); @@ -2198,17 +2739,19 @@ namespace emfplushelper } case EmfPlusRecordTypeDrawDriverString: { - sal_uInt32 brushIndexOrColor; - sal_uInt32 optionFlags; - sal_uInt32 hasMatrix; - sal_uInt32 glyphsCount; + sal_uInt32 brushIndexOrColor(0); + sal_uInt32 optionFlags(0); + sal_uInt32 hasMatrix(0); + sal_uInt32 glyphsCount(0); rMS.ReadUInt32(brushIndexOrColor).ReadUInt32(optionFlags).ReadUInt32(hasMatrix).ReadUInt32(glyphsCount); SAL_INFO("drawinglayer.emf", "EMF+\t " << ((flags & 0x8000) ? "Color" : "Brush index") << ": 0x" << std::hex << brushIndexOrColor << std::dec); SAL_INFO("drawinglayer.emf", "EMF+\t Option flags: 0x" << std::hex << optionFlags << std::dec); SAL_INFO("drawinglayer.emf", "EMF+\t Has matrix: " << hasMatrix); SAL_INFO("drawinglayer.emf", "EMF+\t Glyphs: " << glyphsCount); - if ((optionFlags & 1) && glyphsCount > 0) + // each glyph needs 2 bytes (UTF-16) + 2*4 bytes (X,Y floats) = 10 bytes + if ((optionFlags & 1) && glyphsCount > 0 + && glyphsCount <= rMS.remainingSize() / 10) { std::unique_ptr charsPosX(new float[glyphsCount]); std::unique_ptr charsPosY(new float[glyphsCount]); diff --git a/drawinglayer/source/tools/emfpimage.cxx b/drawinglayer/source/tools/emfpimage.cxx index bb33eaf46622..9a7f711b4836 100644 --- a/drawinglayer/source/tools/emfpimage.cxx +++ b/drawinglayer/source/tools/emfpimage.cxx @@ -24,7 +24,7 @@ namespace emfplushelper { void EMFPImage::Read(SvMemoryStream &s, sal_uInt32 dataSize, bool bUseWholeStream) { - sal_uInt32 header, bitmapType; + sal_uInt32 header(0), bitmapType(0); s.ReadUInt32(header).ReadUInt32(type); SAL_INFO("drawinglayer.emf", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec); @@ -45,13 +45,20 @@ namespace emfplushelper else if (ImageDataTypeMetafile == type) { // metafile - sal_uInt32 mfType, mfSize; + sal_uInt32 mfType(0), mfSize(0); s.ReadUInt32(mfType).ReadUInt32(mfSize); if (bUseWholeStream) dataSize = s.remainingSize(); else + { + if (dataSize < 16) + return; dataSize -= 16; + } + + if (dataSize > s.remainingSize()) + dataSize = s.remainingSize(); SAL_INFO("drawinglayer.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize); diff --git a/drawinglayer/source/tools/emfpimageattributes.cxx b/drawinglayer/source/tools/emfpimageattributes.cxx index 11c1f47173e4..5efaef928e8f 100644 --- a/drawinglayer/source/tools/emfpimageattributes.cxx +++ b/drawinglayer/source/tools/emfpimageattributes.cxx @@ -36,8 +36,8 @@ EMFPImageAttributes::~EMFPImageAttributes() {} void EMFPImageAttributes::Read(SvStream& s) { - sal_uInt32 graphicsVersion, reserved1, reserved2, tempClampColor; - sal_uInt8 clampColorBlue, clampColorGreen, clampColorRed, clampColorAlpha; + sal_uInt32 graphicsVersion(0), reserved1(0), reserved2(0), tempClampColor(0); + sal_uInt8 clampColorBlue(0), clampColorGreen(0), clampColorRed(0), clampColorAlpha(0); s.ReadUInt32(graphicsVersion) .ReadUInt32(reserved1) diff --git a/drawinglayer/source/tools/emfppath.cxx b/drawinglayer/source/tools/emfppath.cxx index cf841fd999e0..40298937d7e6 100644 --- a/drawinglayer/source/tools/emfppath.cxx +++ b/drawinglayer/source/tools/emfppath.cxx @@ -64,17 +64,10 @@ namespace emfplushelper return static_cast(nRet); } - EMFPPath::EMFPPath (sal_uInt32 _nPoints, bool bLines) + EMFPPath::EMFPPath (sal_uInt32 _nPoints, bool _bHasPointTypes) + : nPoints(_nPoints) + , bHasPointTypes(_bHasPointTypes) { - if (_nPoints > SAL_MAX_UINT32 / (2 * sizeof(float))) - { - _nPoints = SAL_MAX_UINT32 / (2 * sizeof(float)); - } - - nPoints = _nPoints; - - if (!bLines) - pPointTypes.reset( new sal_uInt8 [_nPoints] ); } EMFPPath::~EMFPPath () @@ -83,7 +76,31 @@ namespace emfplushelper void EMFPPath::Read (SvStream& s, sal_uInt32 pathFlags) { - float fx, fy; + // A point requires at least this many bytes in the stream, so the + // stream that is left says how many points there can really be, + // whatever count the file gave. + sal_uInt32 nBytesPerPoint; + if (pathFlags & 0x800) + nBytesPerPoint = 2; // EmfPlusPointR, one byte for each of the two coordinates + else if (pathFlags & 0x4000) + nBytesPerPoint = 4; // EmfPlusPoint + else + nBytesPerPoint = 8; // EmfPlusPointF + if (bHasPointTypes) + nBytesPerPoint += 1; + + const sal_uInt64 nMaxPoints = s.remainingSize() / nBytesPerPoint; + if (nPoints > nMaxPoints) + { + SAL_WARN("drawinglayer.emf", "EMF+\tpath wants " << nPoints + << " points, the stream holds " << nMaxPoints); + nPoints = nMaxPoints; + } + + if (bHasPointTypes) + pPointTypes.reset( new sal_uInt8 [nPoints] ); + + float fx(0), fy(0); for (sal_uInt32 i = 0; i < nPoints; i++) { if (pathFlags & 0x800) @@ -100,7 +117,7 @@ namespace emfplushelper else if (pathFlags & 0x4000) { // EMFPlusPoint: stored in signed short 16bit integer format - sal_Int16 x, y; + sal_Int16 x(0), y(0); s.ReadInt16(x).ReadInt16(y); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t" << i << ". EmfPlusPoint [x,y]: " << x << ", " << y); @@ -139,7 +156,7 @@ namespace emfplushelper for (sal_uInt32 i = 0; i < nPoints; i++) { - if (p && pPointTypes && (pPointTypes [i] == 0)) + if (p && pPointTypes && (pPointTypes[i] == 0)) { aPolygon.append (polygon); last_normal = i; @@ -148,15 +165,15 @@ namespace emfplushelper } if (bMapIt) - mapped = rR.Map(xPoints[i], yPoints [i]); + mapped = rR.Map(xPoints[i], yPoints[i]); else mapped = ::basegfx::B2DPoint(xPoints[i], yPoints[i]); if (pPointTypes) { - if ((pPointTypes [i] & 0x07) == 3) + if ((pPointTypes[i] & 0x07) == 3) { - if (((i - last_normal )% 3) == 1) + if (((i - last_normal) % 3) == 1) { assert(p != 0); polygon.setNextControlPoint (p - 1, mapped); @@ -188,7 +205,7 @@ namespace emfplushelper p++; - if (pPointTypes && (pPointTypes [i] & 0x80)) // closed polygon + if (pPointTypes && (pPointTypes[i] & 0x80)) // closed polygon { polygon.setClosed (true); aPolygon.append (polygon); @@ -260,8 +277,12 @@ namespace emfplushelper ::basegfx::B2DPolygon polygon; matrix mat; double x, y; + if (nPoints < 1) + return aPolygon; if (aNumSegments >= nPoints) aNumSegments = nPoints - 1; + if (aOffset >= aNumSegments) + return aPolygon; GetCardinalMatrix(fTension, mat); // duplicate first point xPoints.push_front(xPoints.front()); @@ -291,6 +312,8 @@ namespace emfplushelper ::basegfx::B2DPolygon polygon; matrix mat; double x, y; + if (nPoints < 3) + return aPolygon; GetCardinalMatrix(fTension, mat); // add three first points at the end xPoints.push_back(xPoints[0]); @@ -316,6 +339,6 @@ namespace emfplushelper aPolygon.append(polygon); return aPolygon; } -} +} // namespace emfplushelper /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/tools/emfppath.hxx b/drawinglayer/source/tools/emfppath.hxx index e6104fcb1fc7..782957440241 100644 --- a/drawinglayer/source/tools/emfppath.hxx +++ b/drawinglayer/source/tools/emfppath.hxx @@ -29,19 +29,21 @@ namespace emfplushelper sal_uInt32 nPoints; std::deque xPoints, yPoints; std::unique_ptr pPointTypes; + /// true when a point type byte follows each point in the stream + bool bHasPointTypes; public: - EMFPPath(sal_uInt32 _nPoints, bool bLines = false); + EMFPPath(sal_uInt32 _nPoints, bool _bHasPointTypes = true); virtual ~EMFPPath() override; void Read(SvStream& s, sal_uInt32 pathFlags); - ::basegfx::B2DPolyPolygon& GetPolygon(EmfPlusHelperData const & rR, bool bMapIt = true, bool bAddLineToCloseShape = false); + ::basegfx::B2DPolyPolygon& GetPolygon(EmfPlusHelperData const& rR, bool bMapIt = true, bool bAddLineToCloseShape = false); ::basegfx::B2DPolyPolygon& GetCardinalSpline(EmfPlusHelperData const& rR, float fTension, sal_uInt32 aOffset, sal_uInt32 aNumSegments); ::basegfx::B2DPolyPolygon& GetClosedCardinalSpline(EmfPlusHelperData const& rR, float fTension); }; -} +} // namespace emfplushelper /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/tools/emfppen.cxx b/drawinglayer/source/tools/emfppen.cxx index 789239d62e8b..9ec5a58e0c5f 100644 --- a/drawinglayer/source/tools/emfppen.cxx +++ b/drawinglayer/source/tools/emfppen.cxx @@ -181,7 +181,7 @@ namespace emfplushelper void EMFPPen::Read(SvMemoryStream& s, EmfPlusHelperData const & rR, sal_uInt32 dataSize, bool bUseWholeStream) { sal_Int32 lineJoin = EmfPlusLineJoinTypeMiter; - sal_uInt32 graphicsVersion, penType; + sal_uInt32 graphicsVersion(0), penType(0); s.ReadUInt32(graphicsVersion).ReadUInt32(penType).ReadUInt32(penDataFlags).ReadUInt32(penUnit).ReadFloat(penWidth); SAL_INFO("drawinglayer.emf", "EMF+\t\tGraphics version: 0x" << std::hex << graphicsVersion); SAL_INFO("drawinglayer.emf", "EMF+\t\tType: " << penType); @@ -246,7 +246,7 @@ namespace emfplushelper if (penDataFlags & EmfPlusPenDataMiterLimit) { - float miterLimit; + float miterLimit(0); s.ReadFloat(miterLimit); // EMF+ JoinTypeMiterClipped is working as our B2DLineJoin::Miter @@ -300,11 +300,17 @@ namespace emfplushelper if (penDataFlags & EmfPlusPenDataDashedLine) { dashStyle = EmfPlusLineStyleCustom; - sal_uInt32 dashPatternLen; + sal_uInt32 dashPatternLen(0); s.ReadUInt32(dashPatternLen); SAL_INFO("drawinglayer.emf", "EMF+\t\t\tdashPatternLen: " << dashPatternLen); + if (dashPatternLen > s.remainingSize() / sizeof(float)) + { + SAL_WARN("drawinglayer.emf", "EMF+\t\t\tTruncated dash pattern"); + return; + } + dashPattern.resize( dashPatternLen ); for (sal_uInt32 i = 0; i < dashPatternLen; i++) @@ -327,9 +333,15 @@ namespace emfplushelper if (penDataFlags & EmfPlusPenDataCompoundLine) { SAL_WARN("drawinglayer.emf", "EMF+\t\t\tTODO PenDataCompoundLine"); - sal_uInt32 compoundArrayLen; + sal_uInt32 compoundArrayLen(0); s.ReadUInt32(compoundArrayLen); + if (compoundArrayLen > s.remainingSize() / sizeof(float)) + { + SAL_WARN("drawinglayer.emf", "EMF+\t\t\tTruncated compound array"); + return; + } + compoundArray.resize(compoundArrayLen); for (sal_uInt32 i = 0; i < compoundArrayLen; i++) diff --git a/drawinglayer/source/tools/emfpregion.cxx b/drawinglayer/source/tools/emfpregion.cxx index 9fcced337733..1dae9f3c974d 100644 --- a/drawinglayer/source/tools/emfpregion.cxx +++ b/drawinglayer/source/tools/emfpregion.cxx @@ -36,14 +36,21 @@ namespace emfplushelper { } - ::basegfx::B2DPolyPolygon EMFPRegion::ReadRegionNode(SvStream& s, EmfPlusHelperData& rR) + ::basegfx::B2DPolyPolygon EMFPRegion::ReadRegionNode(SvStream& s, EmfPlusHelperData& rR, int nDepth) { // Regions are specified as a binary tree of region nodes, and each node must either be a terminal node // (RegionNodeDataTypeRect, RegionNodeDataTypePath, RegionNodeDataTypeEmpty, RegionNodeDataTypeInfinite) // or specify one or two child nodes // (RegionNodeDataTypeAnd, RegionNodeDataTypeOr, RegionNodeDataTypeXor, // RegionNodeDataTypeExclude, RegionNodeDataTypeComplement). - sal_uInt32 dataType; + constexpr int nMaxDepth = 2048; + if (nDepth >= nMaxDepth) + { + SAL_WARN("drawinglayer.emf", "EMF+\t Region node too deeply nested (>" << nMaxDepth << ")"); + return {}; + } + + sal_uInt32 dataType(0); ::basegfx::B2DPolyPolygon polygon; s.ReadUInt32(dataType); SAL_INFO("drawinglayer.emf", "EMF+\t Region node data type 0x" << std::hex << dataType << std::dec); @@ -56,14 +63,14 @@ namespace emfplushelper case RegionNodeDataTypeExclude: // CombineModeExclude case RegionNodeDataTypeComplement: // CombineModeComplement { - ::basegfx::B2DPolyPolygon leftPolygon = ReadRegionNode(s, rR); - ::basegfx::B2DPolyPolygon rightPolygon = ReadRegionNode(s, rR); + ::basegfx::B2DPolyPolygon leftPolygon = ReadRegionNode(s, rR, nDepth + 1); + ::basegfx::B2DPolyPolygon rightPolygon = ReadRegionNode(s, rR, nDepth + 1); polygon = EmfPlusHelperData::combineClip(leftPolygon, dataType, rightPolygon); break; } case RegionNodeDataTypeRect: { - float dx, dy, dw, dh; + float dx(0), dy(0), dw(0), dh(0); s.ReadFloat(dx).ReadFloat(dy).ReadFloat(dw).ReadFloat(dh); SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypeRect x:" << dx << ", y:" << dy << ", width:" << dw << ", height:" << dh); @@ -81,12 +88,12 @@ namespace emfplushelper } case RegionNodeDataTypePath: { - sal_Int32 pathLength; + sal_Int32 pathLength(0); s.ReadInt32(pathLength); SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypePath, Path Length: " << pathLength << " bytes"); - sal_uInt32 header, pathFlags; - sal_Int32 points; + sal_uInt32 header(0), pathFlags(0); + sal_Int32 points(0); s.ReadUInt32(header).ReadInt32(points).ReadUInt32(pathFlags); SAL_INFO("drawinglayer.emf", "EMF+\t\t header: 0x" << std::hex << header << @@ -122,12 +129,12 @@ namespace emfplushelper void EMFPRegion::ReadRegion(SvStream& s, EmfPlusHelperData& rR) { - sal_uInt32 header, count; + sal_uInt32 header(0), count(0); s.ReadUInt32(header).ReadUInt32(count); // An array should be RegionNodeCount+1 of EmfPlusRegionNode objects. SAL_INFO("drawinglayer.emf", "EMF+\t version: 0x" << std::hex << header << std::dec << ", region node count: " << count); - regionPolyPolygon = ReadRegionNode(s, rR); + regionPolyPolygon = ReadRegionNode(s, rR, 0); } } diff --git a/drawinglayer/source/tools/emfpregion.hxx b/drawinglayer/source/tools/emfpregion.hxx index a234abbb5539..a59e8b305de4 100644 --- a/drawinglayer/source/tools/emfpregion.hxx +++ b/drawinglayer/source/tools/emfpregion.hxx @@ -43,7 +43,7 @@ namespace emfplushelper EMFPRegion(); virtual ~EMFPRegion() override; void ReadRegion(SvStream& s, EmfPlusHelperData& rR); - ::basegfx::B2DPolyPolygon ReadRegionNode(SvStream& s, EmfPlusHelperData& rR); + ::basegfx::B2DPolyPolygon ReadRegionNode(SvStream& s, EmfPlusHelperData& rR, int nDepth); }; } diff --git a/drawinglayer/source/tools/emfpstringformat.cxx b/drawinglayer/source/tools/emfpstringformat.cxx index c66aa090f438..10ebbd078f1d 100644 --- a/drawinglayer/source/tools/emfpstringformat.cxx +++ b/drawinglayer/source/tools/emfpstringformat.cxx @@ -185,7 +185,6 @@ namespace emfplushelper "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:digitSubstitution"); SAL_WARN_IF(firstTabOffset != 0.0, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:firstTabOffset"); SAL_WARN_IF(hotkeyPrefix != HotkeyPrefix::HotkeyPrefixNone, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:hotkeyPrefix"); - SAL_WARN_IF(tracking != 1.0, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:tracking"); SAL_WARN_IF(trimming != StringTrimming::StringTrimmingNone, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:trimming"); SAL_WARN_IF(tabStopCount, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:tabStopCount"); SAL_WARN_IF(rangeCount != 0, "drawinglayer.emf", "EMF+\t TODO EMFPStringFormat:StringFormatData"); diff --git a/drawinglayer/source/tools/emfpstringformat.hxx b/drawinglayer/source/tools/emfpstringformat.hxx index b4d8cb380e36..1b8b2b1fce0b 100644 --- a/drawinglayer/source/tools/emfpstringformat.hxx +++ b/drawinglayer/source/tools/emfpstringformat.hxx @@ -90,14 +90,6 @@ namespace emfplushelper // flags table from MS-EMFPLUS doc bool DirectionRightToLeft() const { return stringFormatFlags & 0x00000001;} bool DirectionVertical() const { return stringFormatFlags & 0x00000002;} - bool NoFitBlackBox() const { return stringFormatFlags & 0x00000004;} - bool DisplayFormatControl() const { return stringFormatFlags & 0x00000020;} - bool NoFontFallback() const { return stringFormatFlags & 0x00000400;} - bool MeasureTrailingSpaces() const { return stringFormatFlags & 0x00000800;} - bool NoWrap() const { return stringFormatFlags & 0x00001000;} - bool LineLimit() const { return stringFormatFlags & 0x00002000;} - bool NoClip() const { return stringFormatFlags & 0x00004000;} - bool BypassGDI() const { return stringFormatFlags & 0x80000000;} }; } diff --git a/drawinglayer/source/tools/wmfemfhelper.cxx b/drawinglayer/source/tools/wmfemfhelper.cxx index a49f793bdb99..20e80981e9f3 100644 --- a/drawinglayer/source/tools/wmfemfhelper.cxx +++ b/drawinglayer/source/tools/wmfemfhelper.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include #include @@ -155,25 +157,31 @@ namespace wmfemfhelper void PropertyHolders::Push(vcl::PushFlags nPushFlags) { - if (bool(nPushFlags)) - { - OSL_ENSURE(maPropertyHolders.size(), "PropertyHolders: PUSH with no property holders (!)"); - if (!maPropertyHolders.empty()) - { - PropertyHolder* pNew = new PropertyHolder(*maPropertyHolders.back()); - pNew->setPushFlags(nPushFlags); - maPropertyHolders.push_back(pNew); - } - } + // The holder the stack is constructed with is never popped, so there is always one to copy. + assert(!maPropertyHolders.empty()); + + // Every push adds a holder, including one with no flags at all, so each pop has exactly one + // push to pair with. A holder with no flags copies nothing back when it is popped. + PropertyHolder* pNew = new PropertyHolder(*maPropertyHolders.back()); + pNew->setPushFlags(nPushFlags); + maPropertyHolders.push_back(pNew); } void PropertyHolders::Pop() { - OSL_ENSURE(maPropertyHolders.size(), "PropertyHolders: POP with no property holders (!)"); - const sal_uInt32 nSize(maPropertyHolders.size()); + assert(!maPropertyHolders.empty()); - if (!nSize) + // Only a holder that a push added can be popped, so a metafile with more pops than pushes + // keeps the holder the stack was constructed with. + const size_t nPushCount(maPropertyHolders.size() - 1); + + if (!nPushCount) + { + SAL_WARN("drawinglayer", "PropertyHolders: POP without a matching PUSH (!)"); return; + } + + const sal_uInt32 nSize(maPropertyHolders.size()); const PropertyHolder* pTip = maPropertyHolders.back(); const vcl::PushFlags nPushFlags(pTip->getPushFlags()); diff --git a/editeng/CppunitTest_editeng_editeng.mk b/editeng/CppunitTest_editeng_editeng.mk index 7ebea4c4ef81..4f364cd01fda 100644 --- a/editeng/CppunitTest_editeng_editeng.mk +++ b/editeng/CppunitTest_editeng_editeng.mk @@ -12,6 +12,7 @@ $(eval $(call gb_CppunitTest_CppunitTest,editeng_editeng)) $(eval $(call gb_CppunitTest_add_exception_objects,editeng_editeng, \ + editeng/qa/editeng/CharacterConversionTest \ editeng/qa/editeng/editeng \ )) diff --git a/editeng/inc/edtspell.hxx b/editeng/inc/edtspell.hxx index d8eefcd1c14a..c538f072c223 100644 --- a/editeng/inc/edtspell.hxx +++ b/editeng/inc/edtspell.hxx @@ -122,6 +122,8 @@ public: virtual void SetAttr( sal_Int32 nStt, sal_Int32 nEnd, sal_uInt16 nSlotId, SfxPoolItem& ) override; virtual bool SetINetAttr( sal_Int32 nStt, sal_Int32 nEnd, const OUString& rURL ) override; + virtual const OUString& GetText() const override; + virtual OUString const* GetPrevPara(bool bAtNormalPos) override; virtual bool ChgAutoCorrWord( sal_Int32& rSttPos, sal_Int32 nEndPos, diff --git a/editeng/inc/pch/precompiled_editeng.hxx b/editeng/inc/pch/precompiled_editeng.hxx index 3af424d7907d..25efee398b9f 100644 --- a/editeng/inc/pch/precompiled_editeng.hxx +++ b/editeng/inc/pch/precompiled_editeng.hxx @@ -120,7 +120,6 @@ #include #include #include -#include #include #endif // PCH_LEVEL >= 2 #if PCH_LEVEL >= 3 diff --git a/editeng/qa/editeng/CharacterConversionTest.cxx b/editeng/qa/editeng/CharacterConversionTest.cxx new file mode 100644 index 000000000000..ef6a7bc56cc1 --- /dev/null +++ b/editeng/qa/editeng/CharacterConversionTest.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include + +namespace +{ +class CharacterConversionTest : public test::BootstrapFixture +{ +}; + +bool isValidOUString(const OUString& rString) +{ + OString sDummy; + return rString.convertToString(&sDummy, RTL_TEXTENCODING_UTF8, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR); +} + +// Test that Korean Hangul/Hanja character conversion only gives conversion +// candidate strings consisting of valid UTF-16 strings. +// Underlying logic is implemented in i18npool and gets used in class HangulHanjaConversion in editeng. +// Test is done in editeng (and not i18npool) tests to have access to a component context +// that supplies the required service com.sun.star.linguistic2.ConversionDictionaryList. +CPPUNIT_TEST_FIXTURE(CharacterConversionTest, testKoreanHangulHanjaCharacterConversion) +{ + css::lang::Locale aKoreanLocale; + aKoreanLocale.Language = u"ko"_ustr; + aKoreanLocale.Country = u"KR"_ustr; + + css::uno::Reference xConverter + = css::i18n::TextConversion::create(m_xContext); + CPPUNIT_ASSERT_MESSAGE("Creating text converter for Korean must succeed", xConverter); + css::i18n::TextConversionResult aResult = xConverter->getConversions( + u"한글맞춤법"_ustr, 0, 5, aKoreanLocale, css::i18n::TextConversionType::TO_HANJA, + css::i18n::TextConversionOption::CHARACTER_BY_CHARACTER + | css::i18n::TextConversionOption::IGNORE_POST_POSITIONAL_WORD); + + CPPUNIT_ASSERT_MESSAGE("Converter must return character conversion candidates", + aResult.Candidates.size() > 0); + + for (const OUString& rCandidate : aResult.Candidates) + CPPUNIT_ASSERT_MESSAGE("Conversion candidate must be a valid UTF-16 string", + isValidOUString(rCandidate)); +} + +} // end anonymous namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/editeng/qa/editeng/editeng.cxx b/editeng/qa/editeng/editeng.cxx index f15ffd96fa42..d2348d986c16 100644 --- a/editeng/qa/editeng/editeng.cxx +++ b/editeng/qa/editeng/editeng.cxx @@ -192,7 +192,7 @@ CPPUNIT_TEST_FIXTURE(Test, testRTFStyleExportFollowRecursive) CPPUNIT_ASSERT_GREATER(static_cast(0), rStream.remainingSize()); } -CPPUNIT_TEST_FIXTURE(Test, testTdf119192) +CPPUNIT_TEST_FIXTURE(Test, testTdf119192RTFFontAttributesInParagraphScope) { // Tests that font changes due to a script type change are placed in paragraph scope EditEngine aEditEngine(mpItemPool.get()); diff --git a/editeng/qa/unit/core-test.cxx b/editeng/qa/unit/core-test.cxx index 6bca50a7af94..cf979e68f190 100644 --- a/editeng/qa/unit/core-test.cxx +++ b/editeng/qa/unit/core-test.cxx @@ -14,12 +14,14 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -30,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -127,9 +130,9 @@ public: void testTransliterate(); - void testTdf147196(); + void testTdf147196TitleCaseMultilineTransliteration(); - void testTdf148148(); + void testTdf148148CaseWhitespaceOnlyTransliteration(); void testSingleLine(); void testMoveParagraph(); @@ -139,6 +142,10 @@ public: void testTdf162803StaleKashidaArray(); void testTdf157037PasteTextAutoDirection(); void testFontVariationsItem(); + void testFontVariationsScript(); + void testEscapementNotPreservedOnParaBreak(); + void testAutoDirNotPreservedOnParaBreak(); + void testFontTypographicConversion(); DECL_STATIC_LINK(Test, CalcFieldValueHdl, EditFieldInfo*, void); @@ -165,8 +172,8 @@ public: CPPUNIT_TEST(testSectionAttributes); CPPUNIT_TEST(testLargeParaCopyPaste); CPPUNIT_TEST(testTransliterate); - CPPUNIT_TEST(testTdf147196); - CPPUNIT_TEST(testTdf148148); + CPPUNIT_TEST(testTdf147196TitleCaseMultilineTransliteration); + CPPUNIT_TEST(testTdf148148CaseWhitespaceOnlyTransliteration); CPPUNIT_TEST(testSingleLine); CPPUNIT_TEST(testMoveParagraph); CPPUNIT_TEST(testCreateLines); @@ -175,6 +182,10 @@ public: CPPUNIT_TEST(testTdf162803StaleKashidaArray); CPPUNIT_TEST(testTdf157037PasteTextAutoDirection); CPPUNIT_TEST(testFontVariationsItem); + CPPUNIT_TEST(testFontVariationsScript); + CPPUNIT_TEST(testEscapementNotPreservedOnParaBreak); + CPPUNIT_TEST(testAutoDirNotPreservedOnParaBreak); + CPPUNIT_TEST(testFontTypographicConversion); CPPUNIT_TEST_SUITE_END(); private: @@ -985,9 +996,9 @@ void Test::testBoldItalicCopyPaste() aEditEngine.QuickSetAttribs(*pSet, ESelection(0, 2, 0, 14)); // Assert changes - std::unique_ptr pEditText1(aEditEngine.CreateTextObject()); + EditTextObject aEditText1(aEditEngine.CreateTextObject()); std::vector aAttrs1; - pEditText1->GetAllSections(aAttrs1); + aEditText1.GetAllSections(aAttrs1); // There should be 3 sections - woBold - wBold - woBold (w - with, wo - without) CPPUNIT_ASSERT_EQUAL(size_t(3), aAttrs1.size()); @@ -1014,9 +1025,9 @@ void Test::testBoldItalicCopyPaste() aEditEngine.QuickSetAttribs(*pSet, ESelection(0, 8, 0, 18)); // Assert changes - std::unique_ptr pEditText2(aEditEngine.CreateTextObject()); + EditTextObject aEditText2(aEditEngine.CreateTextObject()); std::vector aAttrs2; - pEditText2->GetAllSections(aAttrs2); + aEditText2.GetAllSections(aAttrs2); // There should be 5 sections - woBold&woItalic - wBold&woItalic - wBold&wItalic - woBold&wItalic - woBold&woItalic (w - with, wo - without) CPPUNIT_ASSERT_EQUAL(size_t(5), aAttrs2.size()); @@ -1062,9 +1073,9 @@ void Test::testBoldItalicCopyPaste() rDoc.GetParaAsString(sal_Int32(0))); // Check updated text for appropriate Bold/Italics - std::unique_ptr pEditText3(aEditEngine.CreateTextObject()); + EditTextObject aEditText3(aEditEngine.CreateTextObject()); std::vector aAttrs3; - pEditText3->GetAllSections(aAttrs3); + aEditText3.GetAllSections(aAttrs3); // There should be 9 sections - woBold&woItalic - wBold&woItalic - wBold&wItalic - woBold&wItalic - woBold&woItalic - wBold&woItalic // - wBold&wItalic - woBold&wItalic - woBold&woItalic(w - with, wo - without) CPPUNIT_ASSERT_EQUAL(size_t(9), aAttrs3.size()); @@ -1162,9 +1173,9 @@ void Test::testUnderlineCopyPaste() aEditEngine.QuickSetAttribs(*pSet, ESelection(0, 6, 0, 18)); // Assert changes - std::unique_ptr pEditText1(aEditEngine.CreateTextObject()); + EditTextObject aEditText1(aEditEngine.CreateTextObject()); std::vector aAttrs1; - pEditText1->GetAllSections(aAttrs1); + aEditText1.GetAllSections(aAttrs1); // There should be 3 sections - woUnderline - wUnderline - woUnderline (w - with, wo - without) CPPUNIT_ASSERT_EQUAL(size_t(3), aAttrs1.size()); @@ -1198,9 +1209,9 @@ void Test::testUnderlineCopyPaste() CPPUNIT_ASSERT_EQUAL(OUString(aParaText + "textforunder"), rDoc.GetParaAsString(sal_Int32(0))); // Check updated text for appropriate Underline - std::unique_ptr pEditText2(aEditEngine.CreateTextObject()); + EditTextObject aEditText2(aEditEngine.CreateTextObject()); std::vector aAttrs2; - pEditText2->GetAllSections(aAttrs2); + aEditText2.GetAllSections(aAttrs2); // There should be 4 sections - woUnderline - wUnderline - woUnderline - wUnderline (w - with, wo - without) CPPUNIT_ASSERT_EQUAL(size_t(4), aAttrs2.size()); @@ -1319,9 +1330,9 @@ void Test::testParaBoldItalicCopyPaste() aEditEngine.QuickSetAttribs(*pSet, ESelection(1, 5, 1, 19)); // Assert changes - std::unique_ptr pEditText1(aEditEngine.CreateTextObject()); + EditTextObject aEditText1(aEditEngine.CreateTextObject()); std::vector aAttrs1; - pEditText1->GetAllSections(aAttrs1); + aEditText1.GetAllSections(aAttrs1); // There should be 7 sections - woB - wB - woB -woB -wB -woB -woB (w - with, wo - without, B - Bold, I - Italic) CPPUNIT_ASSERT_EQUAL(size_t(7), aAttrs1.size()); @@ -1369,9 +1380,9 @@ void Test::testParaBoldItalicCopyPaste() aEditEngine.QuickSetAttribs(*pSet, ESelection(0, 14, 1, 9)); // Assert changes - std::unique_ptr pEditText2(aEditEngine.CreateTextObject()); + EditTextObject aEditText2(aEditEngine.CreateTextObject()); std::vector aAttrs2; - pEditText2->GetAllSections(aAttrs2); + aEditText2.GetAllSections(aAttrs2); // There should be 9 sections - woB&woI - wB&woI - wB&wI -woB&wI - woB&wI - wB&wI - wB&woI - woB&woI - woB&woI (w - with, wo - without, B - Bold, I - Italic) CPPUNIT_ASSERT_EQUAL(size_t(9), aAttrs2.size()); @@ -1444,9 +1455,9 @@ void Test::testParaBoldItalicCopyPaste() CPPUNIT_ASSERT_EQUAL( u"This is second"_ustr, rDoc.GetParaAsString(sal_Int32(3)) ); // Check updated text for appropriate Bold/Italics - std::unique_ptr pEditText3(aEditEngine.CreateTextObject()); + EditTextObject aEditText3(aEditEngine.CreateTextObject()); std::vector aAttrs3; - pEditText3->GetAllSections(aAttrs3); + aEditText3.GetAllSections(aAttrs3); // There should be 15 sections - woB&woI - wB&woI - wB&wI -woB&wI - woB&wI - wB&wI - wB&woI - woB&woI - woB&woI // - wB&woI - wB&wI - woB&wI - -woB&wI - wB&wI - wB&woI (w - with, wo - without, B - Bold, I - Italic) CPPUNIT_ASSERT_EQUAL(size_t(15), aAttrs3.size()); @@ -1610,10 +1621,9 @@ void Test::testSectionAttributes() static_cast(1), pSet->Count()); aEngine.QuickSetAttribs(*pSet, ESelection(0, 3, 0, 9)); // 'bbbccc' - std::unique_ptr pEditText(aEngine.CreateTextObject()); - CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText); + EditTextObject aEditText(aEngine.CreateTextObject()); std::vector aAttrs; - pEditText->GetAllSections(aAttrs); + aEditText.GetAllSections(aAttrs); // Now, we should have a total of 3 sections. CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be 3 sections.", static_cast(3), @@ -1659,10 +1669,9 @@ void Test::testSectionAttributes() aEngine.QuickSetAttribs(*pSet, ESelection(2, 0, 2, 3)); aEngine.QuickSetAttribs(*pSet, ESelection(4, 0, 4, 5)); - std::unique_ptr pEditText(aEngine.CreateTextObject()); - CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText); + EditTextObject aEditText(aEngine.CreateTextObject()); std::vector aAttrs; - pEditText->GetAllSections(aAttrs); + aEditText.GetAllSections(aAttrs); CPPUNIT_ASSERT_EQUAL(size_t(5), aAttrs.size()); // 1st, 3rd and 5th sections should correspond with 1st, 3rd and 5th paragraphs. @@ -1714,10 +1723,9 @@ void Test::testSectionAttributes() aEngine.QuickDelete(ESelection(0, 0, 1, 3)); CPPUNIT_ASSERT_EQUAL(static_cast(1), aEngine.GetParagraphCount()); - std::unique_ptr pEditText(aEngine.CreateTextObject()); - CPPUNIT_ASSERT_MESSAGE("Failed to create text object.", pEditText); + EditTextObject aEditText(aEngine.CreateTextObject()); std::vector aAttrs; - pEditText->GetAllSections(aAttrs); + aEditText.GetAllSections(aAttrs); CPPUNIT_ASSERT_EQUAL(static_cast(1), aAttrs.size()); @@ -1934,7 +1942,7 @@ void Test::testTransliterate() } -void Test::testTdf147196() +void Test::testTdf147196TitleCaseMultilineTransliteration() { EditEngine editEng( mpItemPool.get() ); editEng.SetText(u"2.2 Publication of information - CAA\nSection 4.2 of a CA\'s Certificate Policy and/or Certification Practice Statement SHALL state the CA\'s policy or practice on processing CAA Records for Fully Qualified Domain Names; that policy shall be consistent with these Requirements. \n\nIt shall clearly specify the set of Issuer Domain Names that the CA recognises in CAA \"issue\" or \"issuewild\" records as permitting it to issue. The CA SHALL log all actions taken, if any, consistent with its processing practice."_ustr); @@ -1942,7 +1950,7 @@ void Test::testTdf147196() CPPUNIT_ASSERT_EQUAL(u"2.2 Publication Of Information - Caa\nSection 4.2 Of A Ca\'s Certificate Policy And/Or Certification Practice Statement Shall State The Ca\'s Policy Or Practice On Processing Caa Records For Fully Qualified Domain Names; That Policy Shall Be Consistent With These Requirements. \n\nIt Shall Clearly Specify The Set Of Issuer Domain Names That The Ca Recognises In Caa \"Issue\" Or \"Issuewild\" Records As Permitting It To Issue. The Ca Shall Log All Actions Taken, If Any, Consistent With Its Processing Practice."_ustr, editEng.GetText()); } -void Test::testTdf148148() +void Test::testTdf148148CaseWhitespaceOnlyTransliteration() { using TF = TransliterationFlags; EditEngine editEng(mpItemPool.get()); @@ -2462,6 +2470,26 @@ void Test::testTdf157037PasteTextAutoDirection() CPPUNIT_ASSERT(!aEditEngine.IsRightToLeft(4)); } +void Test::testFontVariationsScript() +{ + CPPUNIT_ASSERT(IsScriptItemValid(EE_CHAR_FONTVARIATIONS, i18n::ScriptType::LATIN)); + CPPUNIT_ASSERT(!IsScriptItemValid(EE_CHAR_FONTVARIATIONS, i18n::ScriptType::ASIAN)); + CPPUNIT_ASSERT(!IsScriptItemValid(EE_CHAR_FONTVARIATIONS, i18n::ScriptType::COMPLEX)); + + CPPUNIT_ASSERT(!IsScriptItemValid(EE_CHAR_FONTVARIATIONS_CJK, i18n::ScriptType::LATIN)); + CPPUNIT_ASSERT(IsScriptItemValid(EE_CHAR_FONTVARIATIONS_CJK, i18n::ScriptType::ASIAN)); + CPPUNIT_ASSERT(!IsScriptItemValid(EE_CHAR_FONTVARIATIONS_CJK, i18n::ScriptType::COMPLEX)); + + CPPUNIT_ASSERT(!IsScriptItemValid(EE_CHAR_FONTVARIATIONS_CTL, i18n::ScriptType::LATIN)); + CPPUNIT_ASSERT(!IsScriptItemValid(EE_CHAR_FONTVARIATIONS_CTL, i18n::ScriptType::ASIAN)); + CPPUNIT_ASSERT(IsScriptItemValid(EE_CHAR_FONTVARIATIONS_CTL, i18n::ScriptType::COMPLEX)); + + CPPUNIT_ASSERT_EQUAL(sal_uInt16(EE_CHAR_FONTVARIATIONS_CJK), + GetScriptItemId(EE_CHAR_FONTVARIATIONS, SvtScriptType::ASIAN)); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(EE_CHAR_FONTVARIATIONS_CTL), + GetScriptItemId(EE_CHAR_FONTVARIATIONS, SvtScriptType::COMPLEX)); +} + void Test::testFontVariationsItem() { // Test default construction (empty variations) @@ -2498,7 +2526,101 @@ void Test::testFontVariationsItem() SvxFontVariationsItem aItem4(EE_CHAR_FONTVARIATIONS); CPPUNIT_ASSERT(aItem4.PutValue(aAny, 0)); CPPUNIT_ASSERT(aItem4.operator==(aItem2)); +} +void Test::testEscapementNotPreservedOnParaBreak() +{ + EditEngine aEditEngine(mpItemPool.get()); + EditDoc& rDoc = aEditEngine.GetEditDoc(); + + OUString aParaText = u"item 1st"_ustr; + aEditEngine.SetText(aParaText); + CPPUNIT_ASSERT_EQUAL(aParaText, rDoc.GetParaAsString(sal_Int32(0))); + + { + std::unique_ptr pSet(new SfxItemSet(aEditEngine.GetEmptyItemSet())); + SvxEscapementItem aSuperscript(SvxEscapement::Superscript, EE_CHAR_ESCAPEMENT); + pSet->Put(aSuperscript); + aEditEngine.QuickSetAttribs(*pSet, ESelection(0, 6, 0, 8)); + } + + { + std::unique_ptr pSet(new SfxItemSet(aEditEngine.GetEmptyItemSet())); + SvxWeightItem aBold(WEIGHT_BOLD, EE_CHAR_WEIGHT); + pSet->Put(aBold); + aEditEngine.QuickSetAttribs(*pSet, ESelection(0, 6, 0, 8)); + } + + // new para break at the end of the text (cf. pressing enter) + ContentNode* pNode = rDoc.GetObject(0); + CPPUNIT_ASSERT(pNode); + EditPaM aEndPaM(pNode, pNode->Len()); + rDoc.InsertParaBreak(aEndPaM, true /* bKeepEndingAttribs */); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rDoc.Count()); + CPPUNIT_ASSERT_EQUAL(aParaText, rDoc.GetParaAsString(sal_Int32(0))); + CPPUNIT_ASSERT_EQUAL(OUString(), rDoc.GetParaAsString(sal_Int32(1))); + + // Check new para's character attributes + pNode = rDoc.GetObject(1); + CPPUNIT_ASSERT(pNode); + + const EditCharAttrib* pBoldAttr = pNode->GetCharAttribs().FindEmptyAttrib(EE_CHAR_WEIGHT, 0); + CPPUNIT_ASSERT_MESSAGE("Bold attribute should be carried over.", pBoldAttr != nullptr); + + const EditCharAttrib* pEscAttr = pNode->GetCharAttribs().FindEmptyAttrib(EE_CHAR_ESCAPEMENT, 0); + CPPUNIT_ASSERT_MESSAGE("Escapement attribute should NOT be included.", !pEscAttr); +} + +void Test::testAutoDirNotPreservedOnParaBreak() +{ + EditEngine aEditEngine(mpItemPool.get()); + EditDoc& rDoc = aEditEngine.GetEditDoc(); + + aEditEngine.SetText(u"Some content"_ustr); + + // Set autowritingdir DF on the first paragraph + auto pSet = std::make_unique(aEditEngine.GetEmptyItemSet()); + pSet->Put(SvxAutoFrameDirectionItem{ false, EE_PARA_AUTOWRITINGDIR }); + aEditEngine.QuickSetAttribs(*pSet, ESelection{ 0, 0, 0, 12 }); + + // Insert paragraph break in the middle of the paragraph + rDoc.InsertParaBreak(EditPaM{ rDoc.GetObject(0), 6 }, /*bKeepEndingAttribs*/ true); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rDoc.Count()); + CPPUNIT_ASSERT_EQUAL(u"Some c"_ustr, rDoc.GetParaAsString(sal_Int32(0))); + CPPUNIT_ASSERT_EQUAL(u"ontent"_ustr, rDoc.GetParaAsString(sal_Int32(1))); + + // The first paragraph should still have the DF + auto* pNode = rDoc.GetObject(0); + CPPUNIT_ASSERT(pNode); + + CPPUNIT_ASSERT(pNode->GetContentAttribs().HasItem(EE_PARA_AUTOWRITINGDIR)); + const SvxAutoFrameDirectionItem& rAttr + = pNode->GetContentAttribs().GetItem(EE_PARA_AUTOWRITINGDIR); + CPPUNIT_ASSERT(!rAttr.GetValue()); + + const auto* pNode2 = rDoc.GetObject(1); + CPPUNIT_ASSERT(pNode2); + CPPUNIT_ASSERT(!pNode2->GetContentAttribs().HasItem(EE_PARA_AUTOWRITINGDIR)); +} + +void Test::testFontTypographicConversion() +{ +#if HAVE_MORE_FONTS + EditEngine aEditEngine(mpItemPool.get()); + + SfxItemSet aSet(aEditEngine.GetEmptyItemSet()); + SvxFontItem aFont(EE_CHAR_FONTINFO); + aFont.SetFamilyName(u"DejaVu Sans Condensed"_ustr); + aSet.Put(aFont); + aEditEngine.QuickSetAttribs(aSet, ESelection(0, 0, 0, 1)); + + const SfxItemSet aStored = aEditEngine.GetAttribs(ESelection(0, 0, 0, 1)); + const SvxFontItem& rStored = aStored.Get(EE_CHAR_FONTINFO); + CPPUNIT_ASSERT_EQUAL(u"DejaVu Sans"_ustr, rStored.GetFamilyName()); + CPPUNIT_ASSERT_EQUAL(u"Condensed"_ustr, rStored.GetStyleName()); +#endif } CPPUNIT_TEST_SUITE_REGISTRATION(Test); diff --git a/editeng/source/accessibility/AccessibleContextBase.cxx b/editeng/source/accessibility/AccessibleContextBase.cxx index d61bbd2c808c..17269ffcc33d 100644 --- a/editeng/source/accessibility/AccessibleContextBase.cxx +++ b/editeng/source/accessibility/AccessibleContextBase.cxx @@ -42,9 +42,9 @@ namespace accessibility { // internal AccessibleContextBase::AccessibleContextBase ( - uno::Reference xParent, + const rtl::Reference& rpParent, const sal_Int16 aRole) - : mxParent(std::move(xParent)), + : mpParent(rpParent), meDescriptionOrigin(NotSet), meNameOrigin(NotSet), maRole(aRole) @@ -170,12 +170,16 @@ uno::Reference SAL_CALL nullptr); } +rtl::Reference AccessibleContextBase::implGetAccessibleParent() +{ + ensureAlive(); + return mpParent; +} uno::Reference SAL_CALL AccessibleContextBase::getAccessibleParent() { - ensureAlive(); - return mxParent; + return implGetAccessibleParent(); } sal_Int16 SAL_CALL @@ -250,19 +254,12 @@ sal_Int64 SAL_CALL } } - -lang::Locale SAL_CALL - AccessibleContextBase::getLocale() +lang::Locale SAL_CALL AccessibleContextBase::getLocale() { ensureAlive(); // Delegate request to parent. - if (mxParent.is()) - { - uno::Reference xParentContext ( - mxParent->getAccessibleContext()); - if (xParentContext.is()) - return xParentContext->getLocale (); - } + if (mpParent.is()) + return mpParent->getLocale(); // No locale and no parent. Therefore throw exception to indicate this // cluelessness. @@ -301,24 +298,6 @@ sal_Int32 SAL_CALL AccessibleContextBase::getBackground() return sal_Int32(COL_WHITE); } -// XServiceInfo -OUString SAL_CALL AccessibleContextBase::getImplementationName() -{ - return u"AccessibleContextBase"_ustr; -} - -sal_Bool SAL_CALL AccessibleContextBase::supportsService (const OUString& sServiceName) -{ - return cppu::supportsService(this, sServiceName); -} - -uno::Sequence< OUString > SAL_CALL - AccessibleContextBase::getSupportedServiceNames() -{ - return { - u"com.sun.star.accessibility.AccessibleContext"_ustr}; -} - void SAL_CALL AccessibleContextBase::disposing() { SetState (AccessibleStateType::DEFUNC); @@ -327,7 +306,7 @@ void SAL_CALL AccessibleContextBase::disposing() comphelper::OAccessible::disposing(); - mxParent.clear(); + mpParent.clear(); mxRelationSet.clear(); } diff --git a/editeng/source/accessibility/AccessibleEditableTextPara.cxx b/editeng/source/accessibility/AccessibleEditableTextPara.cxx index 27dc053b80f1..149cadb22f17 100644 --- a/editeng/source/accessibility/AccessibleEditableTextPara.cxx +++ b/editeng/source/accessibility/AccessibleEditableTextPara.cxx @@ -98,13 +98,13 @@ static const SvxItemPropertySet* ImplGetSvxCharAndParaPropertiesSet() // #i27138# - add parameter <_pParaManager> AccessibleEditableTextPara::AccessibleEditableTextPara( - uno::Reference< XAccessible > xParent, - const AccessibleParaManager* _pParaManager ) + const rtl::Reference& rpParent, + const AccessibleParaManager* _pParaManager) : mnParagraphIndex( 0 ), mnIndexInParent( 0 ), mpEditSource( nullptr ), maEEOffset( 0, 0 ), - mxParent(std::move( xParent )), + mpParent(rpParent), mpParaManager( _pParaManager ) { @@ -255,7 +255,7 @@ void SAL_CALL AccessibleEditableTextPara::dispose() xBullet->dispose(); maImageBullet.clear(); - mxParent = nullptr; + mpParent = nullptr; mpEditSource = nullptr; comphelper::OAccessible::dispose(); @@ -567,9 +567,9 @@ uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessible uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleParent() { - SAL_WARN_IF(!mxParent.is(), "editeng", "AccessibleEditableTextPara::getAccessibleParent: no frontend set, did somebody forgot to call AccessibleTextHelper::SetEventSource()?"); + SAL_WARN_IF(!mpParent.is(), "editeng", "AccessibleEditableTextPara::getAccessibleParent: no frontend set, did somebody forgot to call AccessibleTextHelper::SetEventSource()?"); - return mxParent; + return mpParent; } sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleIndexInParent() @@ -1196,21 +1196,16 @@ void AccessibleEditableTextPara::_correctValues( uno::Sequence< PropertyValue >& anyChar >>= crChar; if (COL_AUTO == crChar ) { - uno::Reference< css::accessibility::XAccessibleComponent > xComponent(mxParent,uno::UNO_QUERY); - if (xComponent.is()) + if (mpParent->getAccessibleRole() == AccessibleRole::SHAPE + || mpParent->getAccessibleRole() == AccessibleRole::TABLE_CELL) { - uno::Reference< css::accessibility::XAccessibleContext > xContext(xComponent,uno::UNO_QUERY); - if (xContext->getAccessibleRole() == AccessibleRole::SHAPE - || xContext->getAccessibleRole() == AccessibleRole::TABLE_CELL) - { - anyChar <<= COL_BLACK; - } - else - { - Color cr(ColorTransparency, xComponent->getBackground()); - crChar = cr.IsDark() ? COL_WHITE : COL_BLACK; - anyChar <<= crChar; - } + anyChar <<= COL_BLACK; + } + else + { + Color cr(ColorTransparency, mpParent->getBackground()); + crChar = cr.IsDark() ? COL_WHITE : COL_BLACK; + anyChar <<= crChar; } } continue; @@ -1228,21 +1223,16 @@ void AccessibleEditableTextPara::_correctValues( uno::Sequence< PropertyValue >& anyCharUnderLine >>= crCharUnderLine; if (COL_AUTO == crCharUnderLine ) { - uno::Reference< css::accessibility::XAccessibleComponent > xComponent(mxParent,uno::UNO_QUERY); - if (xComponent.is()) + if (mpParent->getAccessibleRole() == AccessibleRole::SHAPE + || mpParent->getAccessibleRole() == AccessibleRole::TABLE_CELL) { - uno::Reference< css::accessibility::XAccessibleContext > xContext(xComponent,uno::UNO_QUERY); - if (xContext->getAccessibleRole() == AccessibleRole::SHAPE - || xContext->getAccessibleRole() == AccessibleRole::TABLE_CELL) - { - anyCharUnderLine <<= COL_BLACK; - } - else - { - Color cr(ColorTransparency, xComponent->getBackground()); - crCharUnderLine = cr.IsDark() ? COL_WHITE : COL_BLACK; - anyCharUnderLine <<= crCharUnderLine; - } + anyCharUnderLine <<= COL_BLACK; + } + else + { + Color cr(ColorTransparency, mpParent->getBackground()); + crCharUnderLine = cr.IsDark() ? COL_WHITE : COL_BLACK; + anyCharUnderLine <<= crCharUnderLine; } } continue; diff --git a/editeng/source/accessibility/AccessibleImageBullet.cxx b/editeng/source/accessibility/AccessibleImageBullet.cxx index 87e1ab03b6b1..4b5cd3c275bb 100644 --- a/editeng/source/accessibility/AccessibleImageBullet.cxx +++ b/editeng/source/accessibility/AccessibleImageBullet.cxx @@ -192,22 +192,6 @@ sal_Int32 SAL_CALL AccessibleImageBullet::getBackground( ) return static_cast( aColor ); } -OUString SAL_CALL AccessibleImageBullet::getImplementationName() -{ - return u"AccessibleImageBullet"_ustr; -} - -sal_Bool SAL_CALL AccessibleImageBullet::supportsService (const OUString& sServiceName) -{ - - return cppu::supportsService(this, sServiceName); -} - -uno::Sequence< OUString > SAL_CALL AccessibleImageBullet::getSupportedServiceNames() -{ - return { u"com.sun.star.accessibility.AccessibleContext"_ustr }; -} - void AccessibleImageBullet::SetEEOffset( const Point& rOffset ) { maEEOffset = rOffset; @@ -227,7 +211,7 @@ void AccessibleImageBullet::SetEditSource( SvxEditSource* pEditSource ) if( !mpEditSource ) { - // going defunc + // going defunct UnSetState( AccessibleStateType::SHOWING ); UnSetState( AccessibleStateType::VISIBLE ); SetState( AccessibleStateType::INVALID ); diff --git a/editeng/source/accessibility/AccessibleImageBullet.hxx b/editeng/source/accessibility/AccessibleImageBullet.hxx index 354579773fa9..e426fc4b4be4 100644 --- a/editeng/source/accessibility/AccessibleImageBullet.hxx +++ b/editeng/source/accessibility/AccessibleImageBullet.hxx @@ -24,7 +24,6 @@ #include #include -#include #include class SvxEditSource; @@ -36,8 +35,7 @@ namespace accessibility /** This class implements the image bullets for the EditEngine/Outliner UAA */ -class AccessibleImageBullet final - : public cppu::ImplInheritanceHelper +class AccessibleImageBullet final : public comphelper::OAccessible { public: @@ -63,11 +61,6 @@ public: virtual sal_Int32 SAL_CALL getForeground( ) override; virtual sal_Int32 SAL_CALL getBackground( ) override; - // XServiceInfo - virtual OUString SAL_CALL getImplementationName() override; - virtual sal_Bool SAL_CALL supportsService (const OUString& sServiceName) override; - virtual css::uno::Sequence< OUString> SAL_CALL getSupportedServiceNames() override; - /** Set the edit engine offset @attention This method does not lock the SolarMutex, diff --git a/editeng/source/accessibility/AccessibleStringWrap.cxx b/editeng/source/accessibility/AccessibleStringWrap.cxx index 323761dafac8..14fd95fe1399 100644 --- a/editeng/source/accessibility/AccessibleStringWrap.cxx +++ b/editeng/source/accessibility/AccessibleStringWrap.cxx @@ -43,7 +43,7 @@ void AccessibleStringWrap::GetCharacterBounds( sal_Int32 nIndex, tools::Rectangl mrFont.SetPhysFont(mrDev); - // #108900# Handle virtual position one-past-the end of the string + // #108900# Handle virtual position one-past-the-end of the string if( nIndex >= maText.getLength() ) { // create a caret bounding rect that has the height of the diff --git a/editeng/source/editeng/ContentNode.cxx b/editeng/source/editeng/ContentNode.cxx index 56c2659c7025..1904e55cb1aa 100644 --- a/editeng/source/editeng/ContentNode.cxx +++ b/editeng/source/editeng/ContentNode.cxx @@ -302,7 +302,8 @@ void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, else if ( pAttrib->GetEnd() == nCut ) { // must be copied as an empty attributes. - if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !maCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) ) + if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !maCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) + && pAttrib->GetItem()->Which() != EE_CHAR_ESCAPEMENT ) { EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 ); assert(pNewAttrib); diff --git a/editeng/source/editeng/editattr.cxx b/editeng/source/editeng/editattr.cxx index 63ab6f4973db..a4aad600cd6d 100644 --- a/editeng/source/editeng/editattr.cxx +++ b/editeng/source/editeng/editattr.cxx @@ -89,6 +89,7 @@ void EditCharAttribFont::SetFont( SvxFont& rFont, OutputDevice* ) const SvxFontItem& rAttr = static_cast(*GetItem()); rFont.SetFamilyName( rAttr.GetFamilyName() ); + rFont.SetStyleName( rAttr.GetStyleName() ); rFont.SetFamily( rAttr.GetFamily() ); rFont.SetPitch( rAttr.GetPitch() ); rFont.SetCharSet( rAttr.GetCharSet() ); @@ -483,7 +484,8 @@ void EditCharAttribOpticalSizing::SetFont( SvxFont& rFont, OutputDevice* ) EditCharAttribFontVariations::EditCharAttribFontVariations(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) : EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rItem.Which() == EE_CHAR_FONTVARIATIONS); + assert(rItem.Which() == EE_CHAR_FONTVARIATIONS || rItem.Which() == EE_CHAR_FONTVARIATIONS_CJK + || rItem.Which() == EE_CHAR_FONTVARIATIONS_CTL); } void EditCharAttribFontVariations::SetFont( SvxFont& rFont, OutputDevice* ) diff --git a/editeng/source/editeng/editdbg.cxx b/editeng/source/editeng/editdbg.cxx index aaef04702ff2..576a146818cc 100644 --- a/editeng/source/editeng/editdbg.cxx +++ b/editeng/source/editeng/editdbg.cxx @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx index 229592edff13..16a76a302004 100644 --- a/editeng/source/editeng/editdoc.cxx +++ b/editeng/source/editeng/editdoc.cxx @@ -111,6 +111,9 @@ sal_uInt16 GetScriptItemId( sal_uInt16 nItemId, SvtScriptType nScriptType ) case EE_CHAR_ITALIC: nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL; break; + case EE_CHAR_FONTVARIATIONS: + nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_FONTVARIATIONS_CJK : EE_CHAR_FONTVARIATIONS_CTL; + break; } } @@ -168,6 +171,15 @@ bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType ) case EE_CHAR_ITALIC_CTL: bValid = nScriptType == i18n::ScriptType::COMPLEX; break; + case EE_CHAR_FONTVARIATIONS: + bValid = nScriptType == i18n::ScriptType::LATIN; + break; + case EE_CHAR_FONTVARIATIONS_CJK: + bValid = nScriptType == i18n::ScriptType::ASIAN; + break; + case EE_CHAR_FONTVARIATIONS_CTL: + bValid = nScriptType == i18n::ScriptType::COMPLEX; + break; } return bValid; @@ -329,6 +341,8 @@ EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sa } break; case EE_CHAR_FONTVARIATIONS: + case EE_CHAR_FONTVARIATIONS_CJK: + case EE_CHAR_FONTVARIATIONS_CTL: { return new EditCharAttribFontVariations(rPool, rAttr, nS, nE ); } @@ -609,7 +623,7 @@ void ConvertItem( std::unique_ptr& rPoolItem, MapUnit eSourceUnit, case EE_PARA_LRSPACE: { assert(dynamic_cast(rPoolItem.get()) != nullptr); - SvxLRSpaceItem& rItem = static_cast(*rPoolItem); + SvxLRSpaceItem& rItem = rPoolItem->StaticWhichCast(EE_PARA_LRSPACE); if (rItem.GetTextFirstLineOffset().m_nUnit == css::util::MeasureUnit::TWIP) { rItem.SetTextFirstLineOffset( @@ -628,7 +642,7 @@ void ConvertItem( std::unique_ptr& rPoolItem, MapUnit eSourceUnit, case EE_PARA_ULSPACE: { assert(dynamic_cast(rPoolItem.get()) != nullptr); - SvxULSpaceItem& rItem = static_cast(*rPoolItem); + SvxULSpaceItem& rItem = rPoolItem->StaticWhichCast(EE_PARA_ULSPACE); rItem.SetUpper( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetUpper(), eSourceUnit, eDestUnit ) ) ); rItem.SetLower( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLower(), eSourceUnit, eDestUnit ) ) ); } @@ -636,7 +650,7 @@ void ConvertItem( std::unique_ptr& rPoolItem, MapUnit eSourceUnit, case EE_PARA_SBL: { assert(dynamic_cast(rPoolItem.get()) != nullptr); - SvxLineSpacingItem& rItem = static_cast(*rPoolItem); + SvxLineSpacingItem& rItem = rPoolItem->StaticWhichCast(EE_PARA_SBL); // SetLineHeight changes also eLineSpace! if ( rItem.GetLineSpaceRule() == SvxLineSpaceRule::Min ) rItem.SetLineHeight( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLineHeight(), eSourceUnit, eDestUnit ) ) ); @@ -645,7 +659,7 @@ void ConvertItem( std::unique_ptr& rPoolItem, MapUnit eSourceUnit, case EE_PARA_TABS: { assert(dynamic_cast(rPoolItem.get()) != nullptr); - SvxTabStopItem& rItem = static_cast(*rPoolItem); + SvxTabStopItem& rItem = rPoolItem->StaticWhichCast(EE_PARA_TABS); SvxTabStopItem* pNewItem(new SvxTabStopItem(EE_PARA_TABS)); if (sal_Int32 nDefTabDistance = rItem.GetDefaultDistance()) @@ -1244,11 +1258,16 @@ void YrsInsertAttribImplImpl(YrsWrite const& yw, SfxPoolItem const& rItm, break; } case EE_CHAR_FONTVARIATIONS: + case EE_CHAR_FONTVARIATIONS_CJK: + case EE_CHAR_FONTVARIATIONS_CTL: { SvxFontVariationsItem const& rItem{static_cast(rItm)}; OUString aStr = vcl::font::VariationsToString(rItem.GetVariations()); attr = yinput_str(OUStringToOString(aStr, RTL_TEXTENCODING_UTF8)); - attrName = "EE_CHAR_FONTVARIATIONS"; + attrName = rItm.Which() == EE_CHAR_FONTVARIATIONS + ? "EE_CHAR_FONTVARIATIONS" + : rItm.Which() == EE_CHAR_FONTVARIATIONS_CJK ? "EE_CHAR_FONTVARIATIONS_CJK" + : "EE_CHAR_FONTVARIATIONS_CTL"; break; } default: @@ -1611,6 +1630,10 @@ char const* YrsWhichToAttrName(sal_Int16 const nWhich) return "EE_CHAR_OPTICALSIZING"; case EE_CHAR_FONTVARIATIONS: return "EE_CHAR_FONTVARIATIONS"; + case EE_CHAR_FONTVARIATIONS_CJK: + return "EE_CHAR_FONTVARIATIONS_CJK"; + case EE_CHAR_FONTVARIATIONS_CTL: + return "EE_CHAR_FONTVARIATIONS_CTL"; default: assert(false); abort(); @@ -1861,6 +1884,14 @@ void YrsImplInsertAttr(SfxItemSet & rSet, ::std::vector *const pRemo { nWhich = EE_CHAR_FONTVARIATIONS; } + else if (strcmp(pKey, "EE_CHAR_FONTVARIATIONS_CJK") == 0) + { + nWhich = EE_CHAR_FONTVARIATIONS_CJK; + } + else if (strcmp(pKey, "EE_CHAR_FONTVARIATIONS_CTL") == 0) + { + nWhich = EE_CHAR_FONTVARIATIONS_CTL; + } else if (pKey[0] == 'E' && pKey[1] == 'E' && pKey[2] == '_') { abort(); @@ -2500,6 +2531,8 @@ void YrsImplInsertAttr(SfxItemSet & rSet, ::std::vector *const pRemo break; } case EE_CHAR_FONTVARIATIONS: + case EE_CHAR_FONTVARIATIONS_CJK: + case EE_CHAR_FONTVARIATIONS_CTL: { yvalidate(rValue.tag == Y_JSON_STRING); OUString aStr = OStringToOUString( @@ -3278,11 +3311,13 @@ void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, S sal_uInt16 nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType ); sal_uInt16 nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType ); sal_uInt16 nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType ); + sal_uInt16 nWhich_FontVariations = GetScriptItemId( EE_CHAR_FONTVARIATIONS, nScriptType ); if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SfxItemState::SET ) ) { const SvxFontItem& rFontItem = static_cast(rSet.Get( nWhich_FontInfo )); rFont.SetFamilyName( rFontItem.GetFamilyName() ); + rFont.SetStyleName( rFontItem.GetStyleName() ); rFont.SetFamily( rFontItem.GetFamily() ); rFont.SetPitch( rFontItem.GetPitch() ); rFont.SetCharSet( rFontItem.GetCharSet() ); @@ -3337,8 +3372,8 @@ void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, S rFont.SetRelief( rSet.Get( EE_CHAR_RELIEF ).GetValue() ); if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OPTICALSIZING ) == SfxItemState::SET ) ) rFont.SetOpticalSizing( rSet.Get( EE_CHAR_OPTICALSIZING ).GetValue() ); - if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_FONTVARIATIONS ) == SfxItemState::SET ) ) - rFont.SetVariations( rSet.Get( EE_CHAR_FONTVARIATIONS ).GetVariations() ); + if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontVariations ) == SfxItemState::SET ) ) + rFont.SetVariations( static_cast(rSet.Get( nWhich_FontVariations )).GetVariations() ); // Operator == compares the individual members of the font if the impl pointer is // not equal. If all members are the same, this assignment makes @@ -3622,6 +3657,10 @@ EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, bool bKeepEndingAttribs ) // for a new paragraph we like to have the bullet/numbering visible by default aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, true) ); + // tdf#172081: The auto writing dir attrib is used to flag paragraphs that + // have writing dir manually set. This shouldn't be copied to new paragraphs. + aContentAttribs.GetItems().ClearItem(EE_PARA_AUTOWRITINGDIR); + // ContentNode constructor copies also the paragraph attributes ContentNode* pNode = new ContentNode(aStr, std::move(aContentAttribs)); diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx index 4c0694f8f424..0abffe21478a 100644 --- a/editeng/source/editeng/editeng.cxx +++ b/editeng/source/editeng/editeng.cxx @@ -833,17 +833,17 @@ void EditEngine::Write( SvStream& rOutput, EETextFormat eFormat ) getImpl().Write(rOutput, eFormat); } -std::unique_ptr EditEngine::CreateTextObject() +EditTextObject EditEngine::CreateTextObject() { return getImpl().CreateTextObject(); } -std::unique_ptr EditEngine::CreateTextObject( const ESelection& rESelection ) +EditTextObject EditEngine::CreateTextObject( const ESelection& rESelection ) { return getImpl().CreateTextObject(CreateSelection(rESelection)); } -std::unique_ptr EditEngine::GetEmptyTextObject() +EditTextObject EditEngine::GetEmptyTextObject() { return getImpl().GetEmptyTextObject(); } @@ -920,7 +920,7 @@ void EditEngine::SetEndPasteOrDropHdl( const Link& rLink getImpl().maEndPasteOrDropHdl = rLink; } -std::unique_ptr EditEngine::CreateTextObject( sal_Int32 nPara, sal_Int32 nParas ) +EditTextObject EditEngine::CreateTextObject( sal_Int32 nPara, sal_Int32 nParas ) { return getImpl().CreateTextObject(nPara, nParas); } diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx index 371cb90d325b..2ecc95e4df83 100644 --- a/editeng/source/editeng/editobj.cxx +++ b/editeng/source/editeng/editobj.cxx @@ -98,7 +98,10 @@ ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse maText(rCopyFrom.maText), aStyle(rCopyFrom.aStyle), eFamily(rCopyFrom.eFamily), - aParaAttribs(SfxItemSet::makeFixedSfxItemSet(rPoolToUse)) + aParaAttribs(SfxItemSet::makeFixedSfxItemSet(rPoolToUse)), + mnNumberingDepth(rCopyFrom.mnNumberingDepth), + mnNumberingStartValue(rCopyFrom.mnNumberingStartValue), + mbNumberingRestart(rCopyFrom.mbNumberingRestart) { // this should ensure that the Items end up in the correct Pool! aParaAttribs.Set( rCopyFrom.GetParaAttribs() ); @@ -144,6 +147,9 @@ void ContentInfo::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentInfo")); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("style"), BAD_CAST(aStyle.toUtf8().getStr())); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("nNumberingDepth"), "%" SAL_PRIdINT32, static_cast(mnNumberingDepth)); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("mnNumberingStartValue"), "%" SAL_PRIdINT32, static_cast(mnNumberingStartValue)); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("mbNumberingRestart"), "%" SAL_PRIdINT32, static_cast(mbNumberingRestart)); (void)xmlTextWriterStartElement(pWriter, BAD_CAST("text")); OUString aText = GetText(); // TODO share code with sax_fastparser::FastSaxSerializer::write(). @@ -203,22 +209,18 @@ bool ContentInfo::Equals(const ContentInfo& rCompare, bool bComparePool) const { return maText == rCompare.maText && aStyle == rCompare.aStyle && eFamily == rCompare.eFamily && aParaAttribs.Equals(rCompare.aParaAttribs, bComparePool) - && maCharAttribs == rCompare.maCharAttribs; -} - -EditTextObject::~EditTextObject() = default; - -std::unique_ptr EditTextObjectImpl::Clone() const -{ - return std::make_unique(*this); + && maCharAttribs == rCompare.maCharAttribs + && mnNumberingDepth == rCompare.mnNumberingDepth + && mnNumberingStartValue == rCompare.mnNumberingStartValue + && mbNumberingRestart == rCompare.mbNumberingRestart; } bool EditTextObject::Equals( const EditTextObject& rCompare ) const { - return toImpl(*this).Equals(toImpl(rCompare), false /*bComparePool*/); + return Equals(rCompare, false /*bComparePool*/); } -void EditTextObjectImpl::dumpAsXml(xmlTextWriterPtr pWriter) const +void EditTextObject::dumpAsXml(xmlTextWriterPtr pWriter) const { bool bOwns = false; if (!pWriter) @@ -246,7 +248,7 @@ void EditTextObjectImpl::dumpAsXml(xmlTextWriterPtr pWriter) const } #if DEBUG_EDIT_ENGINE -void EditTextObjectImpl::Dump() const +void EditTextObject::Dump() const { for (auto const& content : maContents) content.Dump(); @@ -269,7 +271,7 @@ static rtl::Reference getEditEngineItemPool(SfxItemPool* pPool, Map return pRetval; } -EditTextObjectImpl::EditTextObjectImpl(SfxItemPool* pP, MapUnit eDefaultMetric, bool bVertical, +EditTextObject::EditTextObject(SfxItemPool* pP, MapUnit eDefaultMetric, bool bVertical, TextRotation eRotation, SvtScriptType eScriptType) : mpPool(getEditEngineItemPool(pP, eDefaultMetric)) , meUserType(OutlinerMode::DontKnow) @@ -280,7 +282,7 @@ EditTextObjectImpl::EditTextObjectImpl(SfxItemPool* pP, MapUnit eDefaultMetric, { } -EditTextObjectImpl::EditTextObjectImpl( const EditTextObjectImpl& r ) +EditTextObject::EditTextObject( const EditTextObject& r ) : mpPool(r.mpPool) , meUserType(r.meUserType) , meScriptType(r.meScriptType) @@ -295,7 +297,9 @@ EditTextObjectImpl::EditTextObjectImpl( const EditTextObjectImpl& r ) maContents.push_back(std::unique_ptr(new ContentInfo(*content, *mpPool))); } -EditTextObjectImpl::~EditTextObjectImpl() +EditTextObject::EditTextObject( EditTextObject&& ) noexcept = default; + +EditTextObject::~EditTextObject() { ClearPortionInfo(); @@ -304,13 +308,14 @@ EditTextObjectImpl::~EditTextObjectImpl() maContents.clear(); } +EditTextObject& EditTextObject::operator=(EditTextObject&&) = default; -void EditTextObjectImpl::SetUserType( OutlinerMode n ) +void EditTextObject::SetUserType( OutlinerMode n ) { meUserType = n; } -void EditTextObjectImpl::NormalizeString( svl::SharedStringPool& rPool ) +void EditTextObject::NormalizeString( svl::SharedStringPool& rPool ) { for (auto const& content : maContents) { @@ -319,7 +324,7 @@ void EditTextObjectImpl::NormalizeString( svl::SharedStringPool& rPool ) } } -std::vector EditTextObjectImpl::GetSharedStrings() const +std::vector EditTextObject::GetSharedStrings() const { std::vector aSSs; aSSs.reserve(maContents.size()); @@ -331,19 +336,19 @@ std::vector EditTextObjectImpl::GetSharedStrings() const return aSSs; } -bool EditTextObjectImpl::IsEffectivelyVertical() const +bool EditTextObject::IsEffectivelyVertical() const { return (mbVertical && meRotation == TextRotation::NONE) || (!mbVertical && meRotation != TextRotation::NONE); } -bool EditTextObjectImpl::IsTopToBottom() const +bool EditTextObject::IsTopToBottom() const { return (mbVertical && meRotation == TextRotation::NONE) || (!mbVertical && meRotation == TextRotation::TOPTOBOTTOM); } -void EditTextObjectImpl::SetVertical( bool bVert) +void EditTextObject::SetVertical( bool bVert) { if (bVert != mbVertical) { @@ -352,12 +357,12 @@ void EditTextObjectImpl::SetVertical( bool bVert) } } -bool EditTextObjectImpl::GetVertical() const +bool EditTextObject::GetVertical() const { return mbVertical; } -void EditTextObjectImpl::SetRotation(TextRotation nRotation) +void EditTextObject::SetRotation(TextRotation nRotation) { if (meRotation != nRotation) { @@ -366,42 +371,34 @@ void EditTextObjectImpl::SetRotation(TextRotation nRotation) } } -TextRotation EditTextObjectImpl::GetRotation() const +TextRotation EditTextObject::GetRotation() const { return meRotation; } -XEditAttribute EditTextObjectImpl::CreateAttrib( const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd ) -{ - return XEditAttribute(*mpPool, rItem, nStart, nEnd); -} - -ContentInfo* EditTextObjectImpl::CreateAndInsertContent() +ContentInfo* EditTextObject::CreateAndInsertContent() { maContents.push_back(std::unique_ptr(new ContentInfo(*mpPool))); return maContents.back().get(); } -sal_Int32 EditTextObjectImpl::GetParagraphCount() const +sal_Int32 EditTextObject::GetParagraphCount() const { size_t nSize = maContents.size(); if (nSize > EE_PARA_MAX) { - SAL_WARN( "editeng", "EditTextObjectImpl::GetParagraphCount - overflow " << nSize); + SAL_WARN( "editeng", "EditTextObject::GetParagraphCount - overflow " << nSize); return EE_PARA_MAX; } return static_cast(nSize); } -OUString EditTextObjectImpl::GetText(sal_Int32 nPara) const +OUString EditTextObject::GetText(sal_Int32 nPara) const { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) - return OUString(); - return maContents[nPara]->GetText(); } -OUString EditTextObjectImpl::GetText(LineEnd eEnd) const +OUString EditTextObject::GetText(LineEnd eEnd) const { const size_t nParas = maContents.size(); if (nParas == 0) @@ -421,20 +418,47 @@ OUString EditTextObjectImpl::GetText(LineEnd eEnd) const return aBuffer.makeStringAndClear(); } -sal_Int32 EditTextObjectImpl::GetTextLen(sal_Int32 nPara ) const +sal_Int32 EditTextObject::GetTextLen(sal_Int32 nPara ) const { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) - return 0; - return maContents[nPara]->GetTextLen(); } -void EditTextObjectImpl::ClearPortionInfo() +sal_Int16 EditTextObject::GetNumberingDepth(sal_Int32 nPara) const +{ + return maContents[nPara]->GetNumberingDepth(); +} + +void EditTextObject::SetNumberingDepth(sal_Int32 nPara, sal_Int16 nDepth) +{ + maContents[nPara]->SetNumberingDepth(nDepth); +} + +sal_Int16 EditTextObject::GetNumberingStartValue(sal_Int32 nPara) const +{ + return maContents[nPara]->GetNumberingStartValue(); +} + +void EditTextObject::SetNumberingStartValue(sal_Int32 nPara, sal_Int16 nStartValue) +{ + maContents[nPara]->SetNumberingStartValue(nStartValue); +} + +bool EditTextObject::IsNumberingRestart(sal_Int32 nPara) const +{ + return maContents[nPara]->IsNumberingRestart(); +} + +void EditTextObject::SetNumberingRestart(sal_Int32 nPara, bool bRestart) +{ + maContents[nPara]->SetNumberingRestart(bRestart); +} + +void EditTextObject::ClearPortionInfo() { mpPortionInfo.reset(); } -bool EditTextObjectImpl::HasOnlineSpellErrors() const +bool EditTextObject::HasOnlineSpellErrors() const { for (auto const& content : maContents) { @@ -444,11 +468,8 @@ bool EditTextObjectImpl::HasOnlineSpellErrors() const return false; } -void EditTextObjectImpl::GetCharAttribs( sal_Int32 nPara, std::vector& rLst ) const +void EditTextObject::GetCharAttribs( sal_Int32 nPara, std::vector& rLst ) const { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) - return; - rLst.clear(); const ContentInfo& rC = *maContents[nPara]; for (const XEditAttribute & rAttr : rC.maCharAttribs) @@ -458,12 +479,12 @@ void EditTextObjectImpl::GetCharAttribs( sal_Int32 nPara, std::vector= maContents.size()) - return nullptr; - const ContentInfo& rC = *maContents[nPara]; if (nPos >= rC.maCharAttribs.size()) // URL position is out-of-bound. @@ -515,7 +533,7 @@ const SvxFieldData* EditTextObjectImpl::GetFieldData(sal_Int32 nPara, size_t nPo return nullptr; // field not found. } -bool EditTextObjectImpl::HasField( sal_Int32 nType ) const +bool EditTextObject::HasField( sal_Int32 nType ) const { size_t nParagraphs = maContents.size(); for (size_t nPara = 0; nPara < nParagraphs; ++nPara) @@ -540,13 +558,13 @@ bool EditTextObjectImpl::HasField( sal_Int32 nType ) const return false; } -const SfxItemSet& EditTextObjectImpl::GetParaAttribs(sal_Int32 nPara) const +const SfxItemSet& EditTextObject::GetParaAttribs(sal_Int32 nPara) const { const ContentInfo& rC = *maContents[nPara]; return rC.GetParaAttribs(); } -bool EditTextObjectImpl::RemoveCharAttribs( sal_uInt16 _nWhich ) +bool EditTextObject::RemoveCharAttribs( sal_uInt16 _nWhich ) { bool bChanged = false; @@ -598,7 +616,7 @@ public: } -void EditTextObjectImpl::GetAllSections( std::vector& rAttrs ) const +void EditTextObject::GetAllSections( std::vector& rAttrs ) const { std::vector aAttrs; aAttrs.reserve(maContents.size()); @@ -701,27 +719,21 @@ void EditTextObjectImpl::GetAllSections( std::vector& rAttrs ) rAttrs.swap(aAttrs); } -void EditTextObjectImpl::GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& rFamily) const +void EditTextObject::GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& rFamily) const { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) - return; - const ContentInfo& rC = *maContents[nPara]; rName = rC.GetStyle(); rFamily = rC.GetFamily(); } -void EditTextObjectImpl::SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& rFamily) +void EditTextObject::SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& rFamily) { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) - return; - ContentInfo& rC = *maContents[nPara]; rC.SetStyle(rName); rC.SetFamily(rFamily); } -bool EditTextObjectImpl::ImpChangeStyleSheets( +bool EditTextObject::ImpChangeStyleSheets( std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily ) { @@ -744,7 +756,7 @@ bool EditTextObjectImpl::ImpChangeStyleSheets( return bChanges; } -bool EditTextObjectImpl::ChangeStyleSheets( +bool EditTextObject::ChangeStyleSheets( std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily) { @@ -755,18 +767,18 @@ bool EditTextObjectImpl::ChangeStyleSheets( return bChanges; } -void EditTextObjectImpl::ChangeStyleSheetName( SfxStyleFamily eFamily, +void EditTextObject::ChangeStyleSheetName( SfxStyleFamily eFamily, std::u16string_view rOldName, const OUString& rNewName ) { ImpChangeStyleSheets( rOldName, eFamily, rNewName, eFamily ); } -bool EditTextObjectImpl::operator==( const EditTextObject& rCompare ) const +bool EditTextObject::operator==( const EditTextObject& rCompare ) const { - return Equals(toImpl(rCompare), true); + return Equals(rCompare, true); } -bool EditTextObjectImpl::Equals( const EditTextObjectImpl& rCompare, bool bComparePool ) const +bool EditTextObject::Equals( const EditTextObject& rCompare, bool bComparePool ) const { if( this == &rCompare ) return true; @@ -785,12 +797,17 @@ bool EditTextObjectImpl::Equals( const EditTextObjectImpl& rCompare, bool bCompa } // #i102062# -bool EditTextObjectImpl::isWrongListEqual(const EditTextObject& rComp) const +bool EditTextObject::isWrongListEqual(const EditTextObject& rCompare) const { - const EditTextObjectImpl& rCompare = toImpl(rComp); return std::equal( maContents.begin(), maContents.end(), rCompare.maContents.begin(), rCompare.maContents.end(), [](const auto& c1, const auto& c2) { return c1->isWrongListEqual(*c2); }); } +editeng::FieldUpdater EditTextObject::GetFieldUpdater() +{ return editeng::FieldUpdater(*this); } + +void EditTextObject::SetPortionInfo( std::unique_ptr pP ) +{ mpPortionInfo = std::move(pP); } + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editobj2.hxx b/editeng/source/editeng/editobj2.hxx index c34c2efa2743..c9c9a951097e 100644 --- a/editeng/source/editeng/editobj2.hxx +++ b/editeng/source/editeng/editobj2.hxx @@ -114,7 +114,7 @@ public: class ContentInfo { - friend class EditTextObjectImpl; + friend class EditTextObject; private: svl::SharedString maText; @@ -125,6 +125,9 @@ private: SfxItemSet aParaAttribs; std::unique_ptr mpWrongs; + sal_Int16 mnNumberingDepth { -1 }; + sal_Int16 mnNumberingStartValue { -1 }; + bool mbNumberingRestart { false }; ContentInfo( SfxItemPool& rPool ); ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse ); @@ -161,123 +164,16 @@ public: // #i102062# bool isWrongListEqual(const ContentInfo& rCompare) const; + sal_Int16 GetNumberingDepth() const { return mnNumberingDepth; } + void SetNumberingDepth(sal_Int16 nDepth) { mnNumberingDepth = nDepth; } + sal_Int16 GetNumberingStartValue() const { return mnNumberingStartValue; } + void SetNumberingStartValue(sal_Int16 nStartValue) { mnNumberingStartValue = nStartValue; } + bool IsNumberingRestart() const { return mbNumberingRestart; } + void SetNumberingRestart(bool bRestart) { mbNumberingRestart = bRestart; } + #if DEBUG_EDIT_ENGINE void Dump() const; #endif }; -class EditTextObjectImpl final : public EditTextObject -{ -public: - typedef std::vector > ContentInfosType; - -private: - ContentInfosType maContents; - rtl::Reference mpPool; - std::unique_ptr mpPortionInfo; - - OutlinerMode meUserType; - SvtScriptType meScriptType; - TextRotation meRotation; - MapUnit meMetric; - - bool mbVertical; - - bool ImpChangeStyleSheets( std::u16string_view rOldName, SfxStyleFamily eOldFamily, - const OUString& rNewName, SfxStyleFamily eNewFamily ); - -public: - EditTextObjectImpl(SfxItemPool* pPool, MapUnit eDefaultMetric, bool bVertical, - TextRotation eRotation, SvtScriptType eScriptType); - EditTextObjectImpl( const EditTextObjectImpl& r ); - virtual ~EditTextObjectImpl() override; - - EditTextObjectImpl& operator=(const EditTextObjectImpl&) = delete; - - virtual OutlinerMode GetUserType() const override { return meUserType;} - virtual void SetUserType( OutlinerMode n ) override; - - virtual void NormalizeString( svl::SharedStringPool& rPool ) override; - virtual std::vector GetSharedStrings() const override; - - virtual bool IsEffectivelyVertical() const override; - virtual bool GetVertical() const override; - virtual bool IsTopToBottom() const override; - virtual void SetVertical( bool bVert) override; - virtual void SetRotation(TextRotation nRotation) override; - virtual TextRotation GetRotation() const override; - - virtual SvtScriptType GetScriptType() const override { return meScriptType;} - - virtual std::unique_ptr Clone() const override; - - ContentInfo* CreateAndInsertContent(); - XEditAttribute CreateAttrib( const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd ); - - ContentInfosType& GetContents() { return maContents;} - const ContentInfosType& GetContents() const { return maContents;} - SfxItemPool* GetPool() { return mpPool.get(); } - virtual const SfxItemPool* GetPool() const override { return mpPool.get(); } - XParaPortionList* GetPortionInfo() const { return mpPortionInfo.get(); } - void SetPortionInfo( std::unique_ptr pP ) - { mpPortionInfo = std::move(pP); } - - virtual sal_Int32 GetParagraphCount() const override; - virtual OUString GetText(sal_Int32 nParagraph) const override; - virtual OUString GetText(LineEnd eEnd = LINEEND_LF) const override; - virtual sal_Int32 GetTextLen(sal_Int32 nParagraph) const override; - - virtual void ClearPortionInfo() override; - - virtual bool HasOnlineSpellErrors() const override; - - virtual void GetCharAttribs( sal_Int32 nPara, std::vector& rLst ) const override; - - virtual bool RemoveCharAttribs( sal_uInt16 nWhich ) override; - - virtual void GetAllSections( std::vector& rAttrs ) const override; - - virtual bool IsFieldObject() const override; - virtual const SvxFieldItem* GetField() const override; - virtual const SvxFieldData* GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const override; - - virtual bool HasField( sal_Int32 nType = css::text::textfield::Type::UNSPECIFIED ) const override; - - virtual const SfxItemSet& GetParaAttribs(sal_Int32 nPara) const override; - - virtual void GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& eFamily) const override; - virtual void SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& eFamily) override; - virtual bool ChangeStyleSheets( - std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily) override; - virtual void ChangeStyleSheetName(SfxStyleFamily eFamily, std::u16string_view rOldName, const OUString& rNewName) override; - - virtual editeng::FieldUpdater GetFieldUpdater() override { return editeng::FieldUpdater(*this); } - - bool HasMetric() const { return meMetric != MapUnit::LASTENUMDUMMY; } - MapUnit GetMetric() const { return meMetric; } - - virtual bool operator==( const EditTextObject& rCompare ) const override; - bool Equals( const EditTextObjectImpl& rCompare, bool bComparePool ) const; - - // #i102062# - virtual bool isWrongListEqual(const EditTextObject& rCompare) const override; - -#if DEBUG_EDIT_ENGINE - virtual void Dump() const override; -#endif - virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override; -}; - -inline EditTextObjectImpl& toImpl(EditTextObject& rObj) -{ - assert(dynamic_cast(&rObj)); - return static_cast(rObj); -} - -inline const EditTextObjectImpl& toImpl(const EditTextObject& rObj) -{ - assert(dynamic_cast(&rObj)); - return static_cast(rObj); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editundo.cxx b/editeng/source/editeng/editundo.cxx index 47f5ac5b246f..e728f4855e86 100644 --- a/editeng/source/editeng/editundo.cxx +++ b/editeng/source/editeng/editundo.cxx @@ -605,9 +605,9 @@ void EditUndoTransliteration::Undo() aDelSel.Max() = aSel.Min(); aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs(); EditSelection aNewSel; - if ( pTxtObj ) + if ( moTxtObj ) { - aNewSel = pEE->InsertText( *pTxtObj, aSel ); + aNewSel = pEE->InsertText( *moTxtObj, aSel ); } else { diff --git a/editeng/source/editeng/editundo.hxx b/editeng/source/editeng/editundo.hxx index 72abafdec9d5..745672c835ab 100644 --- a/editeng/source/editeng/editundo.hxx +++ b/editeng/source/editeng/editundo.hxx @@ -253,8 +253,8 @@ private: TransliterationFlags nMode; - std::unique_ptr - pTxtObj; + std::optional + moTxtObj; OUString aText; public: @@ -262,7 +262,7 @@ public: virtual ~EditUndoTransliteration() override; void SetText( const OUString& rText ) { aText = rText; } - void SetText( std::unique_ptr pObj ) { pTxtObj = std::move( pObj ); } + void SetText( EditTextObject&& aObj ) { moTxtObj.emplace( std::move( aObj ) ); } void SetNewSelection( const ESelection& rSel ) { aNewESel = rSel; } virtual void Undo() override; diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx index 9d35e2636eee..8a17d02bee45 100644 --- a/editeng/source/editeng/editview.cxx +++ b/editeng/source/editeng/editview.cxx @@ -225,7 +225,9 @@ void EditView::InvalidateWindow(const tools::Rectangle& rClipRect) { // classic mode: invalidate and trigger full repaint // of the changed area - GetWindow()->Invalidate(bNegativeX ? lcl_negateRectX(rClipRect) : rClipRect); + vcl::Window* pWin = GetWindow(); + if (pWin && !pWin->isDisposed()) + pWin->Invalidate(bNegativeX ? lcl_negateRectX(rClipRect) : rClipRect); } } @@ -596,7 +598,7 @@ void EditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor, bool bActivat if (getImpl().mpViewShell && !bActivate) { - if (!getImpl().mpOutputWindow) + if (!getImpl().mpOutputWindow || getImpl().mpOutputWindow->isDisposed()) return; VclPtr pParent = getImpl().mpOutputWindow->GetParentWithLOKNotifier(); if (pParent && pParent->GetLOKWindowId() != 0) @@ -614,7 +616,7 @@ void EditView::HideCursor(bool bDeactivate) if (getImpl().mpViewShell && !bDeactivate) { - if (!getImpl().mpOutputWindow) + if (!getImpl().mpOutputWindow || getImpl().mpOutputWindow->isDisposed()) return; VclPtr pParent = getImpl().mpOutputWindow->GetParentWithLOKNotifier(); if (pParent && pParent->GetLOKWindowId() != 0) @@ -832,7 +834,7 @@ EVControlBits EditView::GetControlWord() const return getImpl().mnControl; } -std::unique_ptr EditView::CreateTextObject() +EditTextObject EditView::CreateTextObject() { return getImpEditEngine().CreateTextObject( getImpl().GetEditSelection() ); } diff --git a/editeng/source/editeng/edtspell.cxx b/editeng/source/editeng/edtspell.cxx index 8eef9af2bbe7..3aa32382f39f 100644 --- a/editeng/source/editeng/edtspell.cxx +++ b/editeng/source/editeng/edtspell.cxx @@ -602,6 +602,11 @@ bool EdtAutoCorrDoc::SetINetAttr(sal_Int32 nStt, sal_Int32 nEnd, return true; } +const OUString& EdtAutoCorrDoc::GetText() const +{ + return pCurNode->GetString(); +} + OUString const* EdtAutoCorrDoc::GetPrevPara(bool const) { // Return previous paragraph, so that it can be determined, diff --git a/editeng/source/editeng/eerdll.cxx b/editeng/source/editeng/eerdll.cxx index 5f660588835a..3b0c2cff13c4 100644 --- a/editeng/source/editeng/eerdll.cxx +++ b/editeng/source/editeng/eerdll.cxx @@ -164,6 +164,8 @@ ItemInfoPackage& getItemInfoPackageEditEngine() { EE_CHAR_SCRIPT_HINT, new SvxScriptHintItem( EE_CHAR_SCRIPT_HINT ), SID_ATTR_CHAR_SCRIPT_HINT, SFX_ITEMINFOFLAG_NONE }, { EE_CHAR_OPTICALSIZING, new SvxOpticalSizingItem( false, EE_CHAR_OPTICALSIZING ), SID_ATTR_CHAR_OPTICAL_SIZING, SFX_ITEMINFOFLAG_NONE }, { EE_CHAR_FONTVARIATIONS, new SvxFontVariationsItem( EE_CHAR_FONTVARIATIONS ), SID_ATTR_CHAR_FONT_VARIATIONS, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_FONTVARIATIONS_CJK, new SvxFontVariationsItem( EE_CHAR_FONTVARIATIONS_CJK ), SID_ATTR_CHAR_CJK_FONT_VARIATIONS, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_FONTVARIATIONS_CTL, new SvxFontVariationsItem( EE_CHAR_FONTVARIATIONS_CTL ), SID_ATTR_CHAR_CTL_FONT_VARIATIONS, SFX_ITEMINFOFLAG_NONE }, { EE_FEATURE_TAB, new SfxVoidItem( EE_FEATURE_TAB ), 0, SFX_ITEMINFOFLAG_NONE }, { EE_FEATURE_LINEBR, new SfxVoidItem( EE_FEATURE_LINEBR ), 0, SFX_ITEMINFOFLAG_NONE }, { EE_FEATURE_NOTCONV, new SvxColorItem( COL_RED, EE_FEATURE_NOTCONV ), SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEMINFOFLAG_NONE }, diff --git a/editeng/source/editeng/fieldupdater.cxx b/editeng/source/editeng/fieldupdater.cxx index 41a431a81651..c7bdff24f4db 100644 --- a/editeng/source/editeng/fieldupdater.cxx +++ b/editeng/source/editeng/fieldupdater.cxx @@ -37,14 +37,14 @@ public: class FieldUpdaterImpl { - EditTextObjectImpl& mrObj; + EditTextObject& mrObj; public: - explicit FieldUpdaterImpl(EditTextObject& rObj) : mrObj(toImpl(rObj)) {} + explicit FieldUpdaterImpl(EditTextObject& rObj) : mrObj(rObj) {} void updateTableFields(int nTab) { SfxItemPool* pPool = mrObj.GetPool(); - EditTextObjectImpl::ContentInfosType& rContents = mrObj.GetContents(); + EditTextObject::ContentInfosType& rContents = mrObj.GetContents(); for (std::unique_ptr & i : rContents) { ContentInfo& rContent = *i; @@ -71,7 +71,7 @@ public: void UpdatePageRelativeURLs(const std::function& rItemCallback) { - EditTextObjectImpl::ContentInfosType& rContents = mrObj.GetContents(); + EditTextObject::ContentInfosType& rContents = mrObj.GetContents(); for (std::unique_ptr & i : rContents) { ContentInfo& rContent = *i; diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx index 251bdaf6b198..1606eb166d34 100644 --- a/editeng/source/editeng/impedit.cxx +++ b/editeng/source/editeng/impedit.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -290,7 +291,7 @@ static void lcl_translateTwips(const OutputDevice& rParent, OutputDevice& rChild return; // Set map mode, so that callback payloads will contain absolute coordinates instead of relative ones. - Point aOffset(rChild.GetOutOffXPixel() - rParent.GetOutOffXPixel(), rChild.GetOutOffYPixel() - rParent.GetOutOffYPixel()); + Point aOffset(rChild.GetDeviceOriginX() - rParent.GetDeviceOriginX(), rChild.GetDeviceOriginY() - rParent.GetDeviceOriginY()); if (!rChild.IsMapModeEnabled()) { MapMode aMapMode(rChild.GetMapMode()); @@ -329,8 +330,8 @@ void ImpEditView::lokSelectionCallback(const std::optional & if (pParent && pParent->GetLOKWindowId() != 0) { - const tools::Long nX = mpOutputWindow->GetOutOffXPixel() - pParent->GetOutOffXPixel(); - const tools::Long nY = mpOutputWindow->GetOutOffYPixel() - pParent->GetOutOffYPixel(); + const tools::Long nX = mpOutputWindow->GetDeviceOriginX() - pParent->GetDeviceOriginX(); + const tools::Long nY = mpOutputWindow->GetDeviceOriginY() - pParent->GetDeviceOriginY(); std::vector aRectangles; aRegion.GetRegionRectangles(aRectangles); @@ -360,8 +361,8 @@ void ImpEditView::lokSelectionCallback(const std::optional & // on top of us to use its offset. vcl::Window* parent = mpOutputWindow->GetParent(); while (parent && - parent->GetOutOffXPixel() == mpOutputWindow->GetOutOffXPixel() && - parent->GetOutOffYPixel() == mpOutputWindow->GetOutOffYPixel()) + parent->GetDeviceOriginX() == mpOutputWindow->GetDeviceOriginX() && + parent->GetDeviceOriginY() == mpOutputWindow->GetDeviceOriginY()) { parent = parent->GetParent(); } @@ -894,11 +895,11 @@ void ImpEditView::InvalidateAtWindow(const tools::Rectangle& rRect) // be used to visualize the active edit text in an OverlayObject pCallbacks->EditViewInvalidate(mbNegativeX ? lcl_negateRectX(rRect) : rRect); } - else + else if (mpOutputWindow && !mpOutputWindow->isDisposed()) { // classic mode: invalidate and trigger full repaint // of the changed area - GetWindow()->Invalidate(mbNegativeX ? lcl_negateRectX(rRect) : rRect); + mpOutputWindow->Invalidate(mbNegativeX ? lcl_negateRectX(rRect) : rRect); } } @@ -1332,7 +1333,15 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) if (getImpEditEngine().IsInUndo()) return; - if (mpOutputWindow && mpOutputWindow->GetCursor() != GetCursor()) + // In multi-view LOK sessions a secondary view's window can be disposed + // while the EditView is still registered in the EditEngine. Without + // EditViewCallbacks the rest of this function relies on GetOutputDevice() + // which dereferences the window's mpWindowImpl — null after dispose. + if (!getEditViewCallbacks() && (!mpOutputWindow || mpOutputWindow->isDisposed())) + return; + + if (mpOutputWindow && !mpOutputWindow->isDisposed() + && mpOutputWindow->GetCursor() != GetCursor()) mpOutputWindow->SetCursor(GetCursor()); EditPaM aPaM(maEditSelection.Max()); @@ -1600,7 +1609,7 @@ Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRa if ( aNewVisArea.Left() < 0 ) aNewVisArea.Move( -aNewVisArea.Left(), 0 ); - // The difference must be alignt on pixel (due to scroll!) + // The difference must be aligned on pixel (due to scroll!) tools::Long nDiffX = !IsVertical() ? ( GetVisDocLeft() - aNewVisArea.Left() ) : (IsTopToBottom() ? -( GetVisDocTop() - aNewVisArea.Top() ) : (GetVisDocTop() - aNewVisArea.Top())); tools::Long nDiffY = !IsVertical() ? ( GetVisDocTop() - aNewVisArea.Top() ) : (IsTopToBottom() ? (GetVisDocLeft() - aNewVisArea.Left()) : -(GetVisDocTop() - aNewVisArea.Top())); diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index df2ac3ef133a..5880c10579bc 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -672,7 +672,7 @@ private: std::unique_ptr CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet ); - std::unique_ptr GetEmptyTextObject(); + EditTextObject GetEmptyTextObject(); std::tuple GetPortionAndLine(Point aDocPos); EditPaM GetPaM( Point aDocPos, bool bSmart = true ); @@ -685,8 +685,7 @@ private: void ParaAttribsToCharAttribs( ContentNode* pNode ); void GetCharAttribs( sal_Int32 nPara, std::vector& rLst ) const; - std::unique_ptr - CreateTextObject(EditSelection aSelection, SfxItemPool*, bool bAllowBigObjects = false, sal_Int32 nBigObjStart = 0); + EditTextObject CreateTextObject(EditSelection aSelection, SfxItemPool*, bool bAllowBigObjects = false, sal_Int32 nBigObjStart = 0); EditSelection InsertTextObject( const EditTextObject&, EditPaM aPaM ); EditSelection PasteText( css::uno::Reference< css::datatransfer::XTransferable > const & rxDataObj, const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial, SotClipboardFormatId format = SotClipboardFormatId::NONE); @@ -802,22 +801,6 @@ private: return double(nYValue) * maScalingParameters.fSpacingY; } - double scaleXFontValue(tools::Long nXValue) const - { - if (!maStatus.DoStretch() || (maScalingParameters.fFontX == 1.0)) - return nXValue; - - return double(nXValue) * maScalingParameters.fFontX; - } - - double scaleYFontValue(sal_uInt16 nYValue) const - { - if (!maStatus.DoStretch() || (maScalingParameters.fFontY == 1.0)) - return nYValue; - - return double(nYValue) * maScalingParameters.fFontY; - } - void setRoundToNearestPt(bool bRound) { mbRoundToNearestPt = bRound; } double roundToNearestPt(double fInput) const; @@ -1053,9 +1036,9 @@ public: void Write(SvStream& rOutput, EETextFormat eFormat, const EditSelection& rSel); OString GetSimpleHtml() const; - std::unique_ptr CreateTextObject(sal_Int32 nPara, sal_Int32 nParas); - std::unique_ptr CreateTextObject(); - std::unique_ptr CreateTextObject(const EditSelection& rSel); + EditTextObject CreateTextObject(sal_Int32 nPara, sal_Int32 nParas); + EditTextObject CreateTextObject(); + EditTextObject CreateTextObject(const EditSelection& rSel); void SetText( const EditTextObject& rTextObject ); EditSelection InsertText( const EditTextObject& rTextObject, EditSelection aSel ); diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx index e52553e4a7b5..9a68fa50df87 100644 --- a/editeng/source/editeng/impedit2.cxx +++ b/editeng/source/editeng/impedit2.cxx @@ -2892,7 +2892,7 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin // in the to be appended data, otherwise already existing // characters would have to be moved and PaM to be updated. // Restrict to 2*42, if not found by then assume other data or - // language-script uses only letters or idiographs. + // language-script uses only letters or ideographs. sal_Int32 nPos = nMaxNewChars; while (nPos-- > 0 && (nMaxNewChars - nPos) <= 84) { @@ -4423,8 +4423,8 @@ sal_Int32 ImpEditEngine::GetChar(ParaPortion const& rParaPortion, EditLine const if (bSmart && nDiffRight < nDiffLeft) { - // I18N: If there are character position with the length of 0, - // they belong to the same character, we can not use this position as an index. + // I18N: If there are character positions with the length of 0, + // they belong to the same character, we cannot use this position as an index. // Skip all 0-positions, cheaper than using XBreakIterator: tools::Long nX = rLine.GetCharPosArray()[nTmpCurIndex + x]; while(x < nMax && static_cast(rLine.GetCharPosArray()[nTmpCurIndex + x]) == nX) @@ -4616,7 +4616,7 @@ tools::Long ImpEditEngine::GetXPos(ParaPortion const& rParaPortion, EditLine con tools::Long nX = GetPortionXOffset(rParaPortion, rLine, nTextPortion); // calc text width, portion size may include CJK/CTL spacing... - // But the array might not be init yet, if using text ranger this method is called within CreateLines()... + // But the array might not be initialized yet, if using text ranger this method is called within CreateLines()... tools::Long nPortionTextWidth = rPortion.GetSize().Width(); if ( ( rPortion.GetKind() == PortionKind::TEXT ) && rPortion.GetLen() && !GetTextRanger() ) { diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index 17a7d5c44427..c3806fe306eb 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -78,6 +78,7 @@ #include #include #include +#include #include #include @@ -2888,6 +2889,7 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo { const SvxFontItem& rFontItem = static_cast(pNode->GetContentAttribs().GetItem( GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ) )); rFont.SetFamilyName( rFontItem.GetFamilyName() ); + rFont.SetStyleName( rFontItem.GetStyleName() ); rFont.SetFamily( rFontItem.GetFamily() ); rFont.SetPitch( rFontItem.GetPitch() ); rFont.SetCharSet( rFontItem.GetCharSet() ); @@ -4791,7 +4793,7 @@ Color ImpEditEngine::GetAutoColor(const SvxFont* pFont) const Color aBackgroundColor(COL_AUTO); if (pFont) //check for char background color aBackgroundColor = pFont->GetFillColor(); - if (aBackgroundColor == COL_AUTO) // check for aother background (i.e: cell color) + if (aBackgroundColor == COL_AUTO) // check for another background (i.e: cell color) aBackgroundColor = GetBackgroundColor(); const SfxViewShell* pKitSh = comphelper::LibreOfficeKit::isActive() ? SfxViewShell::Current() : nullptr; @@ -4990,7 +4992,7 @@ void ImpEditEngine::ImplExpandCompressedPortions(EditLine& rLine, ParaPortion& r DBG_ASSERT( nTxtPortionStart >= rLine.GetStart(), "Portion doesn't belong to the line!!!" ); double* pDXArray = rLine.GetCharPosArray().data() + (nTxtPortionStart - rLine.GetStart()); if ( pTP->GetExtraInfos()->pOrgDXArray ) - memcpy( pDXArray, pTP->GetExtraInfos()->pOrgDXArray.get(), (pTP->GetLen()-1)*sizeof(double) ); + std::copy_n( pTP->GetExtraInfos()->pOrgDXArray.get(), pTP->GetLen()-1, pDXArray ); ImplCalcAsianCompression( rParaPortion.GetNode(), pTP, nTxtPortionStart, pDXArray, static_cast(nCompressPercent), true ); } } diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx index 0e4b6934308d..e5da28b7d2a4 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -1146,7 +1146,7 @@ OString ImpEditEngine::GetSimpleHtml() const return aOutput.makeStringAndClear(); } -std::unique_ptr ImpEditEngine::GetEmptyTextObject() +EditTextObject ImpEditEngine::GetEmptyTextObject() { EditSelection aEmptySel; aEmptySel.Min() = maEditDoc.GetStartPaM(); @@ -1155,27 +1155,23 @@ std::unique_ptr ImpEditEngine::GetEmptyTextObject() return CreateTextObject( aEmptySel ); } -std::unique_ptr ImpEditEngine::CreateTextObject( sal_Int32 nPara, sal_Int32 nParas ) +EditTextObject ImpEditEngine::CreateTextObject( sal_Int32 nPara, sal_Int32 nParas ) { - DBG_ASSERT(0 <= nPara && nPara < maEditDoc.Count(), "CreateTextObject: Startpara out of Range"); - DBG_ASSERT(nParas <= maEditDoc.Count() - nPara, "CreateTextObject: Endpara out of Range"); + assert(0 <= nPara && nPara < maEditDoc.Count() && "CreateTextObject: Startpara out of Range"); + assert(nParas <= maEditDoc.Count() - nPara && "CreateTextObject: Endpara out of Range"); ContentNode* pStartNode = maEditDoc.GetObject(nPara); ContentNode* pEndNode = maEditDoc.GetObject(nPara + nParas - 1); - DBG_ASSERT( pStartNode, "Start-Paragraph does not exist: CreateTextObject" ); - DBG_ASSERT( pEndNode, "End-Paragraph does not exist: CreateTextObject" ); + assert( pStartNode && "Start-Paragraph does not exist: CreateTextObject" ); + assert( pEndNode && "End-Paragraph does not exist: CreateTextObject" ); - if ( pStartNode && pEndNode ) - { - EditSelection aTmpSel; - aTmpSel.Min() = EditPaM( pStartNode, 0 ); - aTmpSel.Max() = EditPaM( pEndNode, pEndNode->Len() ); - return CreateTextObject(aTmpSel); - } - return nullptr; + EditSelection aTmpSel; + aTmpSel.Min() = EditPaM( pStartNode, 0 ); + aTmpSel.Max() = EditPaM( pEndNode, pEndNode->Len() ); + return CreateTextObject(aTmpSel); } -std::unique_ptr ImpEditEngine::CreateTextObject() +EditTextObject ImpEditEngine::CreateTextObject() { EditSelection aCompleteSelection; aCompleteSelection.Min() = maEditDoc.GetStartPaM(); @@ -1184,12 +1180,12 @@ std::unique_ptr ImpEditEngine::CreateTextObject() return CreateTextObject( aCompleteSelection ); } -std::unique_ptr ImpEditEngine::CreateTextObject(const EditSelection& rSel) +EditTextObject ImpEditEngine::CreateTextObject(const EditSelection& rSel) { return CreateTextObject(rSel, &maEditDoc.GetItemPool(), maStatus.AllowBigObjects(), mnBigTextObjectStart); } -std::unique_ptr ImpEditEngine::CreateTextObject( EditSelection aSel, SfxItemPool* pPool, bool bAllowBigObjects, sal_Int32 nBigObjectStart ) +EditTextObject ImpEditEngine::CreateTextObject( EditSelection aSel, SfxItemPool* pPool, bool bAllowBigObjects, sal_Int32 nBigObjectStart ) { sal_Int32 nStartNode, nEndNode; sal_Int32 nTextPortions = 0; @@ -1205,8 +1201,8 @@ std::unique_ptr ImpEditEngine::CreateTextObject( EditSelection a // (Only the name and family, template itself must be in App!) const MapUnit eMapUnit = maEditDoc.GetItemPool().GetMetric(DEF_METRIC); - auto pTxtObj(std::make_unique(pPool, eMapUnit, GetVertical(), GetRotation(), - GetItemScriptType(aSel))); + EditTextObject aTxtObj(pPool, eMapUnit, GetVertical(), GetRotation(), + GetItemScriptType(aSel)); // iterate over the paragraphs ... sal_Int32 nNode; @@ -1231,7 +1227,7 @@ std::unique_ptr ImpEditEngine::CreateTextObject( EditSelection a nEndPos = aSel.Max().GetIndex(); - ContentInfo *pC = pTxtObj->CreateAndInsertContent(); + ContentInfo *pC = aTxtObj.CreateAndInsertContent(); // The paragraph attributes ... pC->GetParaAttribs().Set( pNode->GetContentAttribs().GetItems() ); @@ -1257,7 +1253,7 @@ std::unique_ptr ImpEditEngine::CreateTextObject( EditSelection a if ( bEmptyPara || ( ( pAttr->GetEnd() > nStartPos ) && ( pAttr->GetStart() < nEndPos ) ) ) { - XEditAttribute aX = pTxtObj->CreateAttrib(*pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd()); + XEditAttribute aX(*aTxtObj.GetPool(), *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd()); // Possibly Correct ... if ( ( nNode == nStartNode ) && ( nStartPos != 0 ) ) { @@ -1291,7 +1287,7 @@ std::unique_ptr ImpEditEngine::CreateTextObject( EditSelection a XParaPortionList* pXList = new XParaPortionList(GetRefDevice(), GetColumnWidth(maPaperSize), maScalingParameters.fFontX, maScalingParameters.fFontY, maScalingParameters.fSpacingX, maScalingParameters.fSpacingY); - pTxtObj->SetPortionInfo(std::unique_ptr(pXList)); + aTxtObj.SetPortionInfo(std::unique_ptr(pXList)); for ( nNode = nStartNode; nNode <= nEndNode; nNode++ ) { ParaPortion const& rParaPortion = GetParaPortions().getRef(nNode); @@ -1329,7 +1325,7 @@ std::unique_ptr ImpEditEngine::CreateTextObject( EditSelection a #endif } } - return pTxtObj; + return aTxtObj; } void ImpEditEngine::SetText( const EditTextObject& rTextObject ) @@ -1370,8 +1366,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject DBG_ASSERT( !aSel.DbgIsBuggy( maEditDoc ), "InsertBibTextObject: Selection broken!(1)" ); bool bUsePortionInfo = false; - const EditTextObjectImpl& rTextObjectImpl = toImpl(rTextObject); - XParaPortionList* pPortionInfo = rTextObjectImpl.GetPortionInfo(); + XParaPortionList* pPortionInfo = rTextObject.GetPortionInfo(); if (pPortionInfo && ( static_cast(pPortionInfo->GetPaperWidth()) == GetColumnWidth(maPaperSize)) && pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() @@ -1387,9 +1382,9 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject bool bConvertMetricOfItems = false; MapUnit eSourceUnit = MapUnit(), eDestUnit = MapUnit(); - if (rTextObjectImpl.HasMetric()) + if (rTextObject.HasMetric()) { - eSourceUnit = rTextObjectImpl.GetMetric(); + eSourceUnit = rTextObject.GetMetric(); eDestUnit = maEditDoc.GetItemPool().GetMetric( DEF_METRIC ); if ( eSourceUnit != eDestUnit ) bConvertMetricOfItems = true; @@ -1398,13 +1393,13 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject // Before, paragraph count was of type sal_uInt16 so if nContents exceeded // 0xFFFF this wouldn't have worked anyway, given that nPara is used to // number paragraphs and is fearlessly incremented. - sal_Int32 nContents = static_cast(rTextObjectImpl.GetContents().size()); + sal_Int32 nContents = static_cast(rTextObject.GetContents().size()); SAL_WARN_IF( nContents < 0, "editeng", "ImpEditEngine::InsertTextObject - contents overflow " << nContents); sal_Int32 nPara = maEditDoc.GetPos( aPaM.GetNode() ); for (sal_Int32 n = 0; n < nContents; ++n, ++nPara) { - const ContentInfo* pC = rTextObjectImpl.GetContents()[n].get(); + const ContentInfo* pC = rTextObject.GetContents()[n].get(); bool bNewContent = aPaM.GetNode()->Len() == 0; const sal_Int32 nStartPos = aPaM.GetIndex(); @@ -1427,6 +1422,19 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject //TODO! Still true, still needed? if ( rX.GetEnd() <= aPaM.GetNode()->Len() ) { + // tdf#172647: this load path bypasses SetAttribs, so + // convert to typographic names here too. + const SfxPoolItem* pSrcItem = rX.GetItem(); + std::unique_ptr pConvFont; + const sal_uInt16 nFontWhich = pSrcItem->Which(); + if ((nFontWhich == EE_CHAR_FONTINFO || nFontWhich == EE_CHAR_FONTINFO_CJK + || nFontWhich == EE_CHAR_FONTINFO_CTL) + && GetRefDevice()) + { + pConvFont.reset(static_cast(pSrcItem->Clone())); + pConvFont->makeTypographic(*GetRefDevice()); + pSrcItem = pConvFont.get(); + } if ( !bAllreadyHasAttribs || rX.IsFeature() ) { // Normal attributes then go faster ... @@ -1436,10 +1444,10 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject DBG_ASSERT( rX.GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute too large!" ); EditCharAttrib* pAttr; if ( !bConvertMetricOfItems ) - pAttr = MakeCharAttrib( maEditDoc.GetItemPool(), *(rX.GetItem()), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); + pAttr = MakeCharAttrib( maEditDoc.GetItemPool(), *pSrcItem, rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); else { - std::unique_ptr pNew(rX.GetItem()->Clone()); + std::unique_ptr pNew(pSrcItem->Clone()); ConvertItem( pNew, eSourceUnit, eDestUnit ); pAttr = MakeCharAttrib( maEditDoc.GetItemPool(), *pNew, rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); } @@ -1452,7 +1460,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject { DBG_ASSERT( rX.GetEnd()+nStartPos <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute does not fit! (2)" ); // Tabs and other Features can not be inserted through InsertAttrib: - maEditDoc.InsertAttrib( aPaM.GetNode(), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos, *rX.GetItem() ); + maEditDoc.InsertAttrib( aPaM.GetNode(), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos, *pSrcItem ); } } } @@ -3241,16 +3249,11 @@ short ImpEditEngine::ReplaceTextOnly( DBG_ASSERT( (nCurrentPos+1) < pNode->Len(), "TransliterateText - String smaller than expected!" ); GetEditDoc().RemoveChars( EditPaM( pNode, nCurrentPos+1 ), -nDiff); - ESelection const deleted{maEditDoc.GetPos(pNode), nCurrentPos+1, maEditDoc.GetPos(pNode), nCurrentPos-nDiff}; - UpdateSelectionsDelete(deleted); } else { DBG_ASSERT( nDiff == 1, "TransliterateText - Diff other than expected! But should work..." ); GetEditDoc().InsertText( EditPaM( pNode, nCurrentPos ), OUStringChar(rNewText[n]) ); - ESelection const inserted{maEditDoc.GetPos(pNode), nCurrentPos, maEditDoc.GetPos(pNode), nCurrentPos+nDiff}; - UpdateSelectionsInsert(inserted); - } nDiffs = sal::static_int_cast< short >(nDiffs + nDiff); } diff --git a/editeng/source/editeng/impedit5.cxx b/editeng/source/editeng/impedit5.cxx index c3a5c0c49d9f..6b6b758797c8 100644 --- a/editeng/source/editeng/impedit5.cxx +++ b/editeng/source/editeng/impedit5.cxx @@ -21,6 +21,9 @@ #include "impedit.hxx" #include #include +#include +#include +#include #include #include #include @@ -564,7 +567,37 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetA } else { - maEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem ); + // tdf#172647: convert the font to its typographic names + // here at the model write boundary. + if ((nWhich == EE_CHAR_FONTINFO || nWhich == EE_CHAR_FONTINFO_CJK + || nWhich == EE_CHAR_FONTINFO_CTL) + && GetRefDevice()) + { + TypedWhichId nWeightId = EE_CHAR_WEIGHT; + TypedWhichId nPostureId = EE_CHAR_ITALIC; + if (nWhich == EE_CHAR_FONTINFO_CJK) + { + nWeightId = EE_CHAR_WEIGHT_CJK; + nPostureId = EE_CHAR_ITALIC_CJK; + } + else if (nWhich == EE_CHAR_FONTINFO_CTL) + { + nWeightId = EE_CHAR_WEIGHT_CTL; + nPostureId = EE_CHAR_ITALIC_CTL; + } + FontWeight eWeight = WEIGHT_DONTKNOW; + if (const SvxWeightItem* pWeight = rSet.GetItemIfSet(nWeightId, false)) + eWeight = pWeight->GetWeight(); + FontItalic eItalic = ITALIC_DONTKNOW; + if (const SvxPostureItem* pPosture = rSet.GetItemIfSet(nPostureId, false)) + eItalic = pPosture->GetPosture(); + + SvxFontItem aFont(static_cast(rItem)); + aFont.makeTypographic(*GetRefDevice(), eWeight, WIDTH_DONTKNOW, eItalic); + maEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, aFont ); + } + else + maEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem ); bCharAttribFound = true; if ( nSpecial == SetAttribsMode::Edge ) { @@ -1154,38 +1187,42 @@ bool ImpEditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView break; case KEY_RETURN: { - if ( !bReadOnly ) + if (bReadOnly) + break; + + pEditView->getImpl().DrawSelectionXOR(); + if (rKeyEvent.GetKeyCode().IsMod1() || rKeyEvent.GetKeyCode().IsMod2()) + break; + + if (aAutoText.isEmpty() || rKeyEvent.GetKeyCode().IsShift()) { - pEditView->getImpl().DrawSelectionXOR(); - if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() ) + EditSelection aAutoCorrectSel(aCurSel); + + // for undo stack - start the next line first, so it is undone last + if (rKeyEvent.GetKeyCode().IsShift()) + aCurSel = InsertLineBreak(aCurSel); + else + aCurSel = InsertParaBreak(aCurSel); + + // for the undo stack - do the autocorrect last, so it is undone 1st + if (GetStatus().DoAutoCorrect()) { - UndoActionStart( EDITUNDO_INSERT ); - if ( rKeyEvent.GetKeyCode().IsShift() ) - { - aCurSel = AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); - aCurSel = InsertLineBreak( aCurSel ); - } - else - { - if (aAutoText.isEmpty()) - { - if (GetStatus().DoAutoCorrect()) - aCurSel = AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); - aCurSel = InsertParaBreak( aCurSel ); - } - else - { - DBG_ASSERT( !aCurSel.HasRange(), "Selection on complete?!" ); - EditPaM aStart = WordLeft(aCurSel.Max()); - EditSelection aSelection(aStart, aCurSel.Max()); - aCurSel = InsertText(aSelection, aAutoText); - SetAutoCompleteText( OUString(), true ); - } - } + UndoActionStart(EDITUNDO_INSERT, CreateESel(aCurSel)); + AutoCorrect(aAutoCorrectSel, 0, !pEditView->IsInsertMode(), pFrameWin); UndoActionEnd(); - bModified = true; } } + else + { + UndoActionStart(EDITUNDO_INSERT); + DBG_ASSERT(!aCurSel.HasRange(), "Selection on complete?!"); + EditPaM aStart = WordLeft(aCurSel.Max()); + EditSelection aSelection(aStart, aCurSel.Max()); + aCurSel = InsertText(aSelection, aAutoText); + SetAutoCompleteText(OUString(), true); + UndoActionEnd(); + } + bModified = true; } break; case KEY_INSERT: diff --git a/editeng/source/editeng/textconv.cxx b/editeng/source/editeng/textconv.cxx index 7fe919d5bb36..556a4f6c8156 100644 --- a/editeng/source/editeng/textconv.cxx +++ b/editeng/source/editeng/textconv.cxx @@ -25,7 +25,7 @@ #include #include "textconv.hxx" #include -#include +#include using namespace com::sun::star; using namespace com::sun::star::uno; @@ -81,18 +81,6 @@ bool TextConvWrapper::ConvNext_impl() return true; } return false; - - } - - if ( m_bStartDone && m_bEndDone ) - { - if ( ConvMore_impl() ) // examine another document? - { - m_bStartDone = true; - m_bEndDone = false; - ConvStart_impl( SvxSpellArea::Body ); - return true; - } } else if (!m_aConvSel.HasRange()) { @@ -403,7 +391,7 @@ void TextConvWrapper::ChangeText( const OUString &rNewText, if (rNewText.isEmpty()) return; - if (pOffsets && pESelection) // try to keep as much attributation as possible ? + if (pOffsets && pESelection) // try to keep as much attribution as possible ? { pESelection->Adjust(); @@ -502,8 +490,8 @@ void TextConvWrapper::ChangeText_impl( const OUString &rNewText, bool bKeepAttri // replace old text and select new text m_pEditView->InsertText( rNewText, true ); - // since 'SetAttribs' below function like merging with the attributes - // from the itemset with any existing ones we have to get rid of all + // since 'SetAttribs' below functions like merging with the attributes + // from the itemset with any existing ones we have to get rid of // all attributes now. (Those attributes that may take effect left // to the position where the new text gets inserted after the old text // was deleted) diff --git a/editeng/source/items/flditem.cxx b/editeng/source/items/flditem.cxx index 70a54653b090..f9189173e427 100644 --- a/editeng/source/items/flditem.cxx +++ b/editeng/source/items/flditem.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #include #include +#include #include #include @@ -264,6 +266,11 @@ bool SvxFieldData::operator==( const SvxFieldData& rFld ) const return true; // Basic class is always the same. } +size_t SvxFieldData::hashCode() const +{ + // Extremely basic hash-code, just splits things up by SvxFieldData sub-type. + return std::type_index(typeid(*this)).hash_code(); +} void SvxFieldData::dumpAsXml(xmlTextWriterPtr pWriter) const { @@ -314,6 +321,13 @@ bool SvxFieldItem::operator==( const SfxPoolItem& rItem ) const && ( *mpField == *pOtherFld ); } +size_t SvxFieldItem::hashCode() const +{ + if (mpField) + return mpField->hashCode(); + return 0; +} + void SvxFieldItem::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxFieldItem")); @@ -463,6 +477,15 @@ bool SvxURLField::operator==( const SvxFieldData& rOther ) const ( aTargetFrame == rOtherFld.aTargetFrame ) ); } +size_t SvxURLField::hashCode() const +{ + std::size_t seed(0); + o3tl::hash_combine(seed, eFormat); + o3tl::hash_combine(seed, aURL); + o3tl::hash_combine(seed, aRepresentation); + o3tl::hash_combine(seed, aTargetFrame); + return seed; +} void SvxURLField::dumpAsXml(xmlTextWriterPtr pWriter) const { diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx index 7da518b7fc65..bfe52859a5a5 100644 --- a/editeng/source/items/frmitems.cxx +++ b/editeng/source/items/frmitems.cxx @@ -449,7 +449,7 @@ bool SvxLRSpaceItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const { css::frame::status::LeftRightMarginScale aLRSpace; - auto nLeftTwips = ResolveLeft({}); + auto nLeftTwips = ResolveLeft(); aLRSpace.Left = static_cast(bConvert ? convertTwipToMm100(nLeftTwips) : nLeftTwips); @@ -675,9 +675,9 @@ void SvxLRSpaceItem::SetLeft(SvxIndentValue stL, const sal_uInt16 nProp) const SvxIndentValue & SvxLRSpaceItem::GetLeft() const { return m_stLeftMargin; } -sal_Int32 SvxLRSpaceItem::ResolveLeft(const SvxFontUnitMetrics& rMetrics) const +sal_Int32 SvxLRSpaceItem::ResolveLeft() const { - return m_stLeftMargin.Resolve(rMetrics); + return m_stLeftMargin.Resolve({}); } void SvxRightMarginItem::SetRight(SvxIndentValue stR, const sal_uInt16 nProp) @@ -2163,7 +2163,7 @@ boost::property_tree::ptree SvxLRSpaceItem::dumpAsJSON() const MapUnit eTargetUnit = MapUnit::MapInch; - OUString sLeft = GetMetricText(ResolveLeft({}), MapUnit::MapTwip, eTargetUnit, nullptr); + OUString sLeft = GetMetricText(ResolveLeft(), MapUnit::MapTwip, eTargetUnit, nullptr); OUString sRight = GetMetricText(ResolveRight({}), MapUnit::MapTwip, eTargetUnit, nullptr); diff --git a/editeng/source/items/paraitem.cxx b/editeng/source/items/paraitem.cxx index 527e590d441e..aa46545a8a1c 100644 --- a/editeng/source/items/paraitem.cxx +++ b/editeng/source/items/paraitem.cxx @@ -631,7 +631,8 @@ SvxHyphenZoneItem::SvxHyphenZoneItem( const bool bHyph, const sal_uInt16 nId ) : nKeepType(css::text::ParagraphHyphenationKeepType::COLUMN), bKeepLine(false), nCompoundMinLead(2), - nCompoundMinTrail(2) + nCompoundMinTrail(2), + nLevel(50) { } @@ -692,6 +693,9 @@ bool SvxHyphenZoneItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) con case MID_HYPHEN_COMPOUND_MIN_TRAIL: rVal <<= static_cast(nCompoundMinTrail); break; + case MID_HYPHEN_LEVEL: + rVal <<= static_cast(nLevel); + break; } return true; } @@ -762,6 +766,9 @@ bool SvxHyphenZoneItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) case MID_HYPHEN_COMPOUND_MIN_TRAIL: nCompoundMinTrail = static_cast(nNewVal); break; + case MID_HYPHEN_LEVEL: + nLevel = static_cast(nNewVal); + break; } return true; } @@ -788,7 +795,8 @@ bool SvxHyphenZoneItem::operator==( const SfxPoolItem& rAttr ) const && rItem.nTextHyphenZonePage == nTextHyphenZonePage && rItem.nTextHyphenZoneSpread == nTextHyphenZoneSpread && rItem.bKeepLine == bKeepLine - && rItem.nKeepType == nKeepType ); + && rItem.nKeepType == nKeepType + && rItem.nLevel == nLevel ); } SvxHyphenZoneItem* SvxHyphenZoneItem::Clone( SfxItemPool * ) const @@ -819,6 +827,7 @@ bool SvxHyphenZoneItem::GetPresentation OUString::number( nCompoundMinTrail ) + cpDelimTmp + OUString::number( nMaxHyphens ) + cpDelimTmp + OUString::number( nMinWordLength ) + cpDelimTmp + + OUString::number( 100 - nLevel ) + cpDelimTmp + GetMetricText( nTextHyphenZone, eCoreUnit, ePresUnit, &rIntl ) + " " + EditResId(GetMetricId(ePresUnit)) + GetMetricText( nTextHyphenZoneAlways, eCoreUnit, ePresUnit, &rIntl ) + @@ -838,8 +847,8 @@ bool SvxHyphenZoneItem::GetPresentation if ( bKeep ) { - rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_TRUE) + - cpDelimTmp + OUString::number( nKeepType ); + rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_KEEP_TRUE) + + cpDelimTmp + OUString::number( nKeepType ) + " "; if ( bKeepLine ) rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_LINE_TRUE); else @@ -862,14 +871,24 @@ bool SvxHyphenZoneItem::GetPresentation EditResId(RID_SVXITEMS_HYPHEN_MINLEAD).replaceAll("%1", OUString::number(nMinLead)) + cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_MINTRAIL).replaceAll("%1", OUString::number(nMinTrail)) + - cpDelimTmp + - EditResId(RID_SVXITEMS_HYPHEN_COMPOUND_MINLEAD).replaceAll("%1", OUString::number(nCompoundMinLead)) + - cpDelimTmp + - EditResId(RID_SVXITEMS_HYPHEN_COMPOUND_MINTRAIL).replaceAll("%1", OUString::number(nCompoundMinTrail)) + + ( nCompoundMinLead == 2 + ? EMPTY_OUSTRING + : cpDelimTmp + + EditResId(RID_SVXITEMS_HYPHEN_COMPOUND_MINLEAD).replaceAll("%1", OUString::number(nCompoundMinLead)) ) + + ( nCompoundMinTrail == 2 + ? EMPTY_OUSTRING + : cpDelimTmp + + EditResId(RID_SVXITEMS_HYPHEN_COMPOUND_MINTRAIL).replaceAll("%1", OUString::number(nCompoundMinTrail)) ) + cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_MAX).replaceAll("%1", OUString::number(nMaxHyphens)) + - cpDelimTmp + - EditResId(RID_SVXITEMS_HYPHEN_MINWORDLEN).replaceAll("%1", OUString::number(nMinWordLength)); + ( ( nMinWordLength == 0 || nMinWordLength == 4 ) + ? EMPTY_OUSTRING + : cpDelimTmp + + EditResId(RID_SVXITEMS_HYPHEN_MINWORDLEN).replaceAll("%1", OUString::number(nMinWordLength)) ) + + ( nLevel == 50 + ? EMPTY_OUSTRING + : cpDelimTmp + + EditResId(RID_SVXITEMS_HYPHEN_LEVEL).replaceAll("$(ARG1)", OUString::number(100 - nLevel)) ); if ( nTextHyphenZone > 0 || nTextHyphenZoneAlways > 0 || nTextHyphenZoneColumn > 0 || nTextHyphenZonePage > 0 || @@ -900,7 +919,7 @@ bool SvxHyphenZoneItem::GetPresentation if ( bKeep ) { - rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_TRUE) + cpDelimTmp; + rText += cpDelimTmp; switch ( nKeepType ) { @@ -922,12 +941,12 @@ bool SvxHyphenZoneItem::GetPresentation } if ( bKeepLine ) - rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_LINE_TRUE); + rText += " " + EditResId(RID_SVXITEMS_HYPHEN_KEEP_LINE_TRUE); else - rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_LINE_FALSE); + rText += " " + EditResId(RID_SVXITEMS_HYPHEN_KEEP_LINE_FALSE); } else - rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_FALSE); + rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_KEEP_FALSE); return true; } diff --git a/editeng/source/items/textitem.cxx b/editeng/source/items/textitem.cxx index b59b95867091..cded332ecc4a 100644 --- a/editeng/source/items/textitem.cxx +++ b/editeng/source/items/textitem.cxx @@ -84,7 +84,6 @@ #include #include #include -#include #include #include #include @@ -112,8 +111,6 @@ SfxPoolItem* SvxEmphasisMarkItem::CreateDefault() {return new SvxEmphasisMarkIte SfxPoolItem* SvxCharRotateItem::CreateDefault() {return new SvxCharRotateItem(0_deg10, false, TypedWhichId(0));} SfxPoolItem* SvxCharScaleWidthItem::CreateDefault() {return new SvxCharScaleWidthItem(100, TypedWhichId(0));} SfxPoolItem* SvxCharReliefItem::CreateDefault() {return new SvxCharReliefItem(FontRelief::NONE, 0);} -SfxPoolItem* SvxOpticalSizingItem::CreateDefault() {return new SvxOpticalSizingItem(false, 0);} -SfxPoolItem* SvxFontVariationsItem::CreateDefault() {return new SvxFontVariationsItem(0);} // class SvxFontListItem ------------------------------------------------- @@ -326,6 +323,21 @@ void SvxFontItem::SetStyleName(const OUString &rStyleName) aStyleName = rStyleName; } +void SvxFontItem::makeTypographic(const OutputDevice& rDevice, FontWeight eWeight, FontWidth eWidth, + FontItalic eItalic) +{ + OUString aTypoFamily, aTypoStyle; + // Only rewrite when the name resolves to a *different* typographic family, i.e. it was a + // legacy name. + if (rDevice.GetTypographicFontName(aFamilyName, eWeight, eWidth, eItalic, aTypoFamily, + aTypoStyle) + && !aTypoFamily.equalsIgnoreAsciiCase(aFamilyName)) + { + SetFamilyName(aTypoFamily); + SetStyleName(aTypoStyle); + } +} + void SvxFontItem::SetFamily(FontFamily _eFamily) { if (eFamily == _eFamily) @@ -1642,11 +1654,6 @@ bool SvxColorItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const rVal <<= nValue; break; } - case MID_COMPLEX_COLOR_JSON: - { - rVal <<= OStringToOUString(model::color::convertToJSON(maComplexColor), RTL_TEXTENCODING_UTF8); - break; - } case MID_COMPLEX_COLOR: { auto xComplexColor = model::color::createXComplexColor(maComplexColor); @@ -1729,20 +1736,6 @@ bool SvxColorItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) maComplexColor.addTransformation({model::TransformationType::LumOff, nLumOff}); } break; - case MID_COMPLEX_COLOR_JSON: - { - OUString sComplexColorJson; - if (!(rVal >>= sComplexColorJson)) - return false; - - if (sComplexColorJson.isEmpty()) - return false; - - OString aJSON = OUStringToOString(sComplexColorJson, RTL_TEXTENCODING_ASCII_US); - if (!model::color::convertFromJSON(aJSON, maComplexColor)) - return false; - } - break; case MID_COMPLEX_COLOR: { css::uno::Reference xComplexColor; diff --git a/editeng/source/misc/acorrcfg.cxx b/editeng/source/misc/acorrcfg.cxx index c4db9dfc3bae..4bc1f0fc7aa1 100644 --- a/editeng/source/misc/acorrcfg.cxx +++ b/editeng/source/misc/acorrcfg.cxx @@ -186,8 +186,9 @@ Sequence SvxBaseAutoCorrCfg::GetPropertyNames() u"TransliterateRTL"_ustr, // 18 u"ChangeAngleQuotes"_ustr, // 19 u"SetDOIAttribute"_ustr, // 20 + u"EsperantoHats"_ustr, // 21 }; - const int nCount = 21; + const int nCount = 22; Sequence aNames(nCount); OUString* pNames = aNames.getArray(); for(int i = 0; i < nCount; i++) @@ -299,11 +300,15 @@ void SvxBaseAutoCorrCfg::Load(bool bInit) if (aValues[nProp] == true) nFlags |= ACFlags::SetDOIAttr; break;//"SetDOIAttr", + case 21: + if (aValues[nProp] == true) + nFlags |= ACFlags::EsperantoHats; + break;//"EsperantoHats" } } if( nFlags != ACFlags::NONE ) rParent.pAutoCorrect->SetAutoCorrFlag( nFlags ); - rParent.pAutoCorrect->SetAutoCorrFlag( ( static_cast(0xffff) & ~nFlags ), false ); + rParent.pAutoCorrect->SetAutoCorrFlag( static_cast(AC_OPTION_MASK) & ~nFlags, false ); } SvxBaseAutoCorrCfg::SvxBaseAutoCorrCfg(SvxAutoCorrCfg& rPar) : @@ -356,6 +361,7 @@ void SvxBaseAutoCorrCfg::ImplCommit() css::uno::Any(bool(nFlags & ACFlags::ChgAngleQuotes)), // "ChangeAngleQuotes" css::uno::Any(bool(nFlags & ACFlags::SetDOIAttr)), // "SetDOIAttribute" + css::uno::Any(bool(nFlags & ACFlags::EsperantoHats)), // "EsperantoHats" }); } @@ -418,8 +424,9 @@ Sequence SvxSwAutoCorrCfg::GetPropertyNames() u"Format/Option/SetDOIAttribute"_ustr, //47 u"Format/ByInput/ApplyBulletsAfterSpace"_ustr, //48 u"Format/Option/ReplaceStyle"_ustr, //49 + u"Format/Option/EsperantoHats"_ustr, //50 }; - const int nCount = 50; + const int nCount = 51; Sequence aNames(nCount); OUString* pNames = aNames.getArray(); for(int i = 0; i < nCount; i++) @@ -569,6 +576,7 @@ void SvxSwAutoCorrCfg::Load(bool bInit) case 47: rSwFlags.bSetDOIAttr = (aValues[nProp] == true); break; // "Format/Option/SetDOIAttribute", case 48: rSwFlags.bSetNumRuleAfterSpace = (aValues[nProp] == true); break; // "Format/ByInput/ApplyNumberingAfterSpace", case 49: rSwFlags.bReplaceStyles = (aValues[nProp] == true); break; // "Format/Option/ReplaceStyle", + case 50: rSwFlags.bEsperantoHats = (aValues[nProp] == true); break; // "Format/Option/EsperantoHats", } } } @@ -674,6 +682,7 @@ void SvxSwAutoCorrCfg::ImplCommit() css::uno::Any(rSwFlags.bSetDOIAttr), css::uno::Any(rSwFlags.bSetNumRuleAfterSpace), // "Format/ByInput/ApplyNumberingAfterSpace" css::uno::Any(rSwFlags.bReplaceStyles), // "Format/Option/ReplaceStyle" + css::uno::Any(rSwFlags.bEsperantoHats), // "Format/Option/EsperantoHats" }); // "Format/Option/SetDOIAttribute" } diff --git a/editeng/source/misc/hangulhanja.cxx b/editeng/source/misc/hangulhanja.cxx index a7945dc990df..29ebf54cd2f0 100644 --- a/editeng/source/misc/hangulhanja.cxx +++ b/editeng/source/misc/hangulhanja.cxx @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -593,8 +593,8 @@ namespace editeng { // found asian text // determine if it's Hangul - CharClass aCharClassificaton( m_xContext, LanguageTag( m_aSourceLocale) ); - css::i18n::UnicodeScript nScript = aCharClassificaton.getScript( m_sCurrentPortion, sal::static_int_cast< sal_uInt16 >(nNextAsianScript) ); + CharClass aCharClassification( m_xContext, LanguageTag( m_aSourceLocale) ); + css::i18n::UnicodeScript nScript = aCharClassification.getScript( m_sCurrentPortion, sal::static_int_cast< sal_uInt16 >(nNextAsianScript) ); if ( ( UnicodeScript_kHangulJamo == nScript ) || ( UnicodeScript_kHangulCompatibilityJamo == nScript ) || ( UnicodeScript_kHangulSyllable == nScript ) @@ -743,7 +743,7 @@ namespace editeng // // aOffsets is needed in ReplaceUnit below in order to find out // exactly which characters are really changed in order to keep as much - // from attributation for the text as possible. + // from attribution for the text as possible. Sequence< sal_Int32 > aOffsets; if (m_eConvType == HHC::eConvSimplifiedTraditional && m_xConverter.is()) { diff --git a/editeng/source/misc/splwrap.cxx b/editeng/source/misc/splwrap.cxx index c950041054ff..b12ee6fd5f22 100644 --- a/editeng/source/misc/splwrap.cxx +++ b/editeng/source/misc/splwrap.cxx @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include diff --git a/editeng/source/misc/svxacorr.cxx b/editeng/source/misc/svxacorr.cxx index e17921630ed9..264ba23c0bb4 100644 --- a/editeng/source/misc/svxacorr.cxx +++ b/editeng/source/misc/svxacorr.cxx @@ -281,6 +281,7 @@ ACFlags SvxAutoCorrect::GetDefaultFlags() | ACFlags::AddNonBrkSpace | ACFlags::TransliterateRTL | ACFlags::ChgAngleQuotes + | ACFlags::EsperantoHats | ACFlags::ChgWeightUnderl | ACFlags::SetINetAttr | ACFlags::SetDOIAttr @@ -378,10 +379,11 @@ void SvxAutoCorrect::SetAutoCorrFlag( ACFlags nFlag, bool bOn ) // Correct TWo INitial CApitals -void SvxAutoCorrect::FnCapitalStartWord( SvxAutoCorrDoc& rDoc, const OUString& rTxt, +void SvxAutoCorrect::FnCapitalStartWord( SvxAutoCorrDoc& rDoc, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang ) { + const OUString& rTxt = rDoc.GetText(); CharClass& rCC = GetCharClass( eLang ); // Delete all non alphanumeric. Test the characters at the beginning/end of @@ -576,10 +578,11 @@ bool SvxAutoCorrect::FnChgOrdinalNumber( // Replace dashes bool SvxAutoCorrect::FnChgToEnEmDash( - SvxAutoCorrDoc& rDoc, const OUString& rTxt, + SvxAutoCorrDoc& rDoc, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang ) { + const OUString& rTxt = rDoc.GetText(); bool bRet = false; CharClass& rCC = GetCharClass( eLang ); if (eLang == LANGUAGE_SYSTEM) @@ -909,10 +912,11 @@ bool SvxAutoCorrect::FnChgWeightUnderl( SvxAutoCorrDoc& rDoc, const OUString& rT // Capitalize first letter of every sentence void SvxAutoCorrect::FnCapitalStartSentence( SvxAutoCorrDoc& rDoc, - const OUString& rTxt, bool bNormalPos, + bool bNormalPos, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang ) { + const OUString& rTxt = rDoc.GetText(); if( rTxt.isEmpty() || nEndPos <= nSttPos ) return; @@ -1195,10 +1199,12 @@ void SvxAutoCorrect::FnCapitalStartSentence( SvxAutoCorrDoc& rDoc, } // Correct accidental use of cAPS LOCK key -bool SvxAutoCorrect::FnCorrectCapsLock( SvxAutoCorrDoc& rDoc, const OUString& rTxt, +bool SvxAutoCorrect::FnCorrectCapsLock( SvxAutoCorrDoc& rDoc, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang ) { + const OUString& rTxt = rDoc.GetText(); + if (nEndPos - nSttPos < 2) // string must be at least 2-character long. return false; @@ -1240,6 +1246,57 @@ bool SvxAutoCorrect::FnCorrectCapsLock( SvxAutoCorrDoc& rDoc, const OUString& rT return true; } +void SvxAutoCorrect::FnAddEsperantoHats( SvxAutoCorrDoc& rDoc, sal_Int32 nStart, sal_Int32& nEnd ) +{ + static const std::pair aCharMap[] = { + { 'C', u'Ĉ' }, { 'G', u'Ĝ' }, { 'H', u'Ĥ' }, { 'J', u'Ĵ' }, { 'S', u'Ŝ' }, { 'U', u'Ŭ' }, + { 'c', u'ĉ' }, { 'g', u'ĝ' }, { 'h', u'ĥ' }, { 'j', u'ĵ' }, { 's', u'ŝ' }, { 'u', u'ŭ' }, + }; + // Use an initial capacity of 0 so that it won’t do an allocation + // in the likely event that there is nothing to change. + OUStringBuffer sReplacement(0); + sal_Int32 nPendingPos = nStart; + const OUString& rText = rDoc.GetText(); + + for (int i = nStart + 1; i < nEnd; ++i) + { + if (!lcl_IsInArr(u"xX", rText[i])) + continue; + + const std::pair* pPos + = std::lower_bound(std::begin(aCharMap), std::end(aCharMap), rText[i - 1], + [](const auto& a, const auto& b) { return a.first < b; }); + + if (pPos == std::end(aCharMap) || pPos->first != rText[i - 1]) + continue; + + // Only fix ux if it follows e or a because the letter is found almost exclusively in the + // combinations eŭ and aŭ. That way we avoid changing the letter in common proper nouns such + // as Linux. + if (lcl_IsInArr(u"ŭŬ", pPos->second)) + { + if (i - 1 <= nStart || !lcl_IsInArr(u"aeAE", rText[i - 2])) + continue; + } + + if (sReplacement.isEmpty()) + { + nStart = i - 1; + nPendingPos = i - 1; + } + + sReplacement.append(rText.subView(nPendingPos, i - 1 - nPendingPos) + + OUStringChar(pPos->second)); + nPendingPos = i + 1; + } + + if (sReplacement.isEmpty()) + return; + + nEnd = nStart + sReplacement.getLength() + nEnd - nPendingPos; + rDoc.Delete(nStart, nPendingPos); + rDoc.Insert(nStart, sReplacement.makeStringAndClear()); +} sal_Unicode SvxAutoCorrect::GetQuote( sal_Unicode cInsChar, bool bSttQuote, LanguageType eLang ) const @@ -1294,29 +1351,22 @@ void SvxAutoCorrect::InsertQuote( SvxAutoCorrDoc& rDoc, sal_Int32 nInsPos, else cRet = GetQuote( cInsChar, bSttQuote, eLang ); - OUString sChg( cInsChar ); + // Put the final typographic quote in place with a single edit instead of + // inserting the typed character and then replacing it with the typographic + // one. With the two-edit form, undoing the autocorrect first turned the + // quote back into a straight quote and only a second undo removed it, so a + // stray straight quote was left behind. A single edit means one undo + // removes the whole quote. + OUString sChg( cRet ); if( bIns ) rDoc.Insert( nInsPos, sChg ); else rDoc.Replace( nInsPos, sChg ); - sChg = OUString(cRet); - if( eType == ACQuotes::NonBreakingSpace ) - { - if( rDoc.Insert( bSttQuote ? nInsPos+1 : nInsPos, OUStringChar(cNonBreakingSpace) )) - { - if( !bSttQuote ) - ++nInsPos; - } - } + rDoc.Insert(bSttQuote ? nInsPos + 1 : nInsPos, OUStringChar(cNonBreakingSpace)); else if( eType == ACQuotes::DoubleAngleQuote && cInsChar != '\"' ) - { - rDoc.Delete( nInsPos-1, nInsPos); - --nInsPos; - } - - rDoc.Replace( nInsPos, sChg ); + rDoc.Delete(nInsPos - 1, nInsPos); // i' -> I' in English (last step for the Undo) if( eType == ACQuotes::CapitalizeIAm ) @@ -1652,13 +1702,12 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, // Capital letter at beginning of paragraph? if( IsAutoCorrFlag( ACFlags::CapitalStartSentence ) ) { - FnCapitalStartSentence( rDoc, aPara, false, - nCapLttrPos, nEnd, eLang ); + FnCapitalStartSentence( rDoc, false, nCapLttrPos, nEnd, eLang ); } if( IsAutoCorrFlag( ACFlags::ChgToEnEmDash ) ) { - FnChgToEnEmDash( rDoc, aPara, nCapLttrPos, nEnd, eLang ); + FnChgToEnEmDash( rDoc, nCapLttrPos, nEnd, eLang ); } } break; @@ -1689,8 +1738,12 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, bool bLockKeyOn = pFrameWin && (pFrameWin->GetIndicatorState() & KeyIndicatorState::CAPSLOCK); bool bUnsupported = lcl_IsUnsupportedUnicodeChar( rCC, rTxt, nCapLttrPos, nInsPos ); + if ( IsAutoCorrFlag( ACFlags::EsperantoHats ) && + eLang == LANGUAGE_USER_ESPERANTO ) + FnAddEsperantoHats( rDoc, nCapLttrPos, nInsPos ); + if ( bLockKeyOn && IsAutoCorrFlag( ACFlags::CorrectCapsLock ) && - FnCorrectCapsLock( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) + FnCorrectCapsLock( rDoc, nCapLttrPos, nInsPos, eLang ) ) { // Correct accidental use of cAPS LOCK key (do this only when // the caps or shift lock key is pressed). Turn off the caps @@ -1702,19 +1755,19 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, if( !bUnsupported && IsAutoCorrFlag( ACFlags::CapitalStartSentence ) ) { - FnCapitalStartSentence( rDoc, rTxt, true, nCapLttrPos, nInsPos, eLang ); + FnCapitalStartSentence( rDoc, true, nCapLttrPos, nInsPos, eLang ); } // Two capital letters at beginning of word ?? if( !bUnsupported && IsAutoCorrFlag( ACFlags::CapitalStartWord ) ) { - FnCapitalStartWord( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ); + FnCapitalStartWord( rDoc, nCapLttrPos, nInsPos, eLang ); } if( IsAutoCorrFlag( ACFlags::ChgToEnEmDash ) ) { - FnChgToEnEmDash( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ); + FnChgToEnEmDash( rDoc, nCapLttrPos, nInsPos, eLang ); } } diff --git a/editeng/source/misc/swafopt.cxx b/editeng/source/misc/swafopt.cxx index 7b1df87aa700..a799c3a52e8b 100644 --- a/editeng/source/misc/swafopt.cxx +++ b/editeng/source/misc/swafopt.cxx @@ -32,6 +32,7 @@ SvxSwAutoFormatFlags::SvxSwAutoFormatFlags() bChgOrdinalNumber = bTransliterateRTL = bChgAngleQuotes = + bEsperantoHats = bChgToEnEmDash = bChgWeightUnderl = bSetINetAttr = @@ -79,4 +80,10 @@ SvxSwAutoFormatFlags::SvxSwAutoFormatFlags() pSmartTagMgr = nullptr; } +void SvxSwAutoFormatFlags::resetAllFlags() +{ + // Set all of the flags to false + SVX_SW_FLAG_ENTRIES(, = false) +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/misc/unolingu.cxx b/editeng/source/misc/unolingu.cxx index 14d0620b9c73..472d885ec186 100644 --- a/editeng/source/misc/unolingu.cxx +++ b/editeng/source/misc/unolingu.cxx @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx index 016669a23f40..9d216af0ff3f 100644 --- a/editeng/source/outliner/outliner.cxx +++ b/editeng/source/outliner/outliner.cxx @@ -82,11 +82,11 @@ Paragraph* Outliner::Insert(const OUString& rText, sal_Int32 nAbsPos, sal_Int16 if( bFirstParaIsEmpty ) { pPara = pParaList->GetParagraph( 0 ); - if( pPara->GetDepth() != nDepth ) + if( pPara->GetNumberingDepth() != nDepth ) { - nDepthChangedHdlPrevDepth = pPara->GetDepth(); + nDepthChangedHdlPrevDepth = pPara->GetNumberingDepth(); ParaFlag nPrevFlags = pPara->nFlags; - pPara->SetDepth( nDepth ); + pPara->SetNumberingDepth( nDepth ); DepthChangedHdl(pPara, nPrevFlags); } pPara->nFlags |= ParaFlag::HOLDDEPTH; @@ -127,7 +127,7 @@ void Outliner::ParagraphInserted( sal_Int32 nPara ) { pPara->bVisible = true; const SfxInt16Item& rLevel = pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); - pPara->SetDepth( rLevel.GetValue() ); + pPara->SetNumberingDepth( rLevel.GetValue() ); } } else @@ -135,7 +135,7 @@ void Outliner::ParagraphInserted( sal_Int32 nPara ) sal_Int16 nDepth = -1; Paragraph* pParaBefore = pParaList->GetParagraph( nPara-1 ); if ( pParaBefore ) - nDepth = pParaBefore->GetDepth(); + nDepth = pParaBefore->GetNumberingDepth(); Paragraph* pPara = new Paragraph( nDepth ); pParaList->Insert( std::unique_ptr(pPara), nPara ); @@ -158,7 +158,7 @@ void Outliner::ParagraphDeleted( sal_Int32 nPara ) if (!pPara) return; - sal_Int16 nDepth = pPara->GetDepth(); + sal_Int16 nDepth = pPara->GetNumberingDepth(); if( !pEditEngine->IsInUndo() ) { @@ -171,15 +171,15 @@ void Outliner::ParagraphDeleted( sal_Int32 nPara ) return; pPara = pParaList->GetParagraph( nPara ); - if ( pPara && ( pPara->GetDepth() > nDepth ) ) + if ( pPara && ( pPara->GetNumberingDepth() > nDepth ) ) { ImplCalcBulletText( nPara, true, false ); // Search for next on the this level ... - while ( pPara && pPara->GetDepth() > nDepth ) + while ( pPara && pPara->GetNumberingDepth() > nDepth ) pPara = pParaList->GetParagraph( ++nPara ); } - if ( pPara && ( pPara->GetDepth() == nDepth ) ) + if ( pPara && ( pPara->GetNumberingDepth() == nDepth ) ) ImplCalcBulletText( nPara, true, false ); } @@ -231,7 +231,7 @@ sal_Int16 Outliner::GetDepth( sal_Int32 nPara ) const { Paragraph* pPara = pParaList->GetParagraph( nPara ); DBG_ASSERT( pPara, "Outliner::GetDepth - Paragraph not found!" ); - return pPara ? pPara->GetDepth() : -1; + return pPara ? pPara->GetNumberingDepth() : -1; } void Outliner::SetDepth( Paragraph* pPara, sal_Int16 nNewDepth ) @@ -239,10 +239,10 @@ void Outliner::SetDepth( Paragraph* pPara, sal_Int16 nNewDepth ) ImplCheckDepth( nNewDepth ); - if ( nNewDepth == pPara->GetDepth() ) + if ( nNewDepth == pPara->GetNumberingDepth() ) return; - nDepthChangedHdlPrevDepth = pPara->GetDepth(); + nDepthChangedHdlPrevDepth = pPara->GetNumberingDepth(); ParaFlag nPrevFlags = pPara->nFlags; sal_Int32 nPara = GetAbsPos( pPara ); @@ -271,7 +271,7 @@ void Outliner::SetNumberingStartValue( sal_Int32 nPara, sal_Int16 nNumberingStar if( IsUndoEnabled() && !IsInUndo() ) InsertUndo( std::make_unique( this, nPara, pPara->GetNumberingStartValue(), nNumberingStartValue, - pPara->IsParaIsNumberingRestart(), pPara->IsParaIsNumberingRestart() ) ); + pPara->IsNumberingRestart(), pPara->IsNumberingRestart() ) ); pPara->SetNumberingStartValue( nNumberingStartValue ); ImplCheckParagraphs( nPara, pParaList->GetParagraphCount() ); @@ -283,21 +283,21 @@ bool Outliner::IsParaIsNumberingRestart( sal_Int32 nPara ) const { Paragraph* pPara = pParaList->GetParagraph( nPara ); DBG_ASSERT( pPara, "Outliner::IsParaIsNumberingRestart - Paragraph not found!" ); - return pPara && pPara->IsParaIsNumberingRestart(); + return pPara && pPara->IsNumberingRestart(); } void Outliner::SetParaIsNumberingRestart( sal_Int32 nPara, bool bParaIsNumberingRestart ) { Paragraph* pPara = pParaList->GetParagraph( nPara ); DBG_ASSERT( pPara, "Outliner::SetParaIsNumberingRestart - Paragraph not found!" ); - if( pPara && (pPara->IsParaIsNumberingRestart() != bParaIsNumberingRestart) ) + if( pPara && (pPara->IsNumberingRestart() != bParaIsNumberingRestart) ) { if( IsUndoEnabled() && !IsInUndo() ) InsertUndo( std::make_unique( this, nPara, pPara->GetNumberingStartValue(), pPara->GetNumberingStartValue(), - pPara->IsParaIsNumberingRestart(), bParaIsNumberingRestart ) ); + pPara->IsNumberingRestart(), bParaIsNumberingRestart ) ); - pPara->SetParaIsNumberingRestart( bParaIsNumberingRestart ); + pPara->SetNumberingRestart( bParaIsNumberingRestart ); ImplCheckParagraphs( nPara, pParaList->GetParagraphCount() ); pEditEngine->SetModified(); } @@ -373,18 +373,18 @@ std::optional Outliner::CreateParaObject( sal_Int32 nStartPa if (nCount <= 0) return std::nullopt; - std::unique_ptr xText = pEditEngine->CreateTextObject( nStartPara, nCount ); - const bool bIsEditDoc(OutlinerMode::TextObject == GetOutlinerMode()); - ParagraphDataVector aParagraphDataVector(nCount); + EditTextObject aText = pEditEngine->CreateTextObject( nStartPara, nCount ); const sal_Int32 nLastPara(nStartPara + nCount - 1); for(sal_Int32 nPara(nStartPara); nPara <= nLastPara; nPara++) { - aParagraphDataVector[nPara-nStartPara] = *GetParagraph(nPara); + aText.SetNumberingDepth(nPara - nStartPara, GetParagraph(nPara)->GetNumberingDepth()); + aText.SetNumberingStartValue(nPara - nStartPara, GetParagraph(nPara)->GetNumberingStartValue()); + aText.SetNumberingRestart(nPara - nStartPara, GetParagraph(nPara)->IsNumberingRestart()); } - xText->ClearPortionInfo(); // tdf#147166 the PortionInfo is unwanted here - OutlinerParaObject aPObj(std::move(xText), std::move(aParagraphDataVector), bIsEditDoc); + aText.ClearPortionInfo(); // tdf#147166 the PortionInfo is unwanted here + OutlinerParaObject aPObj(std::move(aText)); aPObj.SetOutlinerMode(GetOutlinerMode()); return aPObj; @@ -414,7 +414,7 @@ void Outliner::SetText( const OUString& rText, Paragraph* pPara ) if (rText.isEmpty()) { pEditEngine->SetText( nPara, rText ); - ImplInitDepth( nPara, pPara->GetDepth(), false ); + ImplInitDepth( nPara, pPara->GetNumberingDepth(), false ); } else { @@ -438,7 +438,7 @@ void Outliner::SetText( const OUString& rText, Paragraph* pPara ) nCurDepth = -1; } else - nCurDepth = pPara->GetDepth(); + nCurDepth = pPara->GetNumberingDepth(); // In the outliner mode, filter the tabs and set the indentation // about a LRSpaceItem. In EditEngine mode intend over old tabs @@ -457,7 +457,7 @@ void Outliner::SetText( const OUString& rText, Paragraph* pPara ) { nCurDepth = nTabs-1; //TODO: sal_Int32 -> sal_Int16! ImplCheckDepth( nCurDepth ); - pPara->SetDepth( nCurDepth ); + pPara->SetNumberingDepth( nCurDepth ); } } if( nPos ) // not with the first paragraph @@ -574,8 +574,8 @@ void Outliner::SetText( const OutlinerParaObject& rPObj ) pParaList->Clear(); for( sal_Int32 nCurPara = 0; nCurPara < rPObj.Count(); nCurPara++ ) { - std::unique_ptr pPara(new Paragraph( rPObj.GetParagraphData(nCurPara))); - ImplCheckDepth( pPara->nDepth ); + std::unique_ptr pPara(new Paragraph( rPObj.GetNumberingDepth(nCurPara), rPObj.GetNumberingStartValue(nCurPara), rPObj.IsNumberingRestart(nCurPara) )); + ImplCheckDepth( pPara->mnNumberingDepth ); pParaList->Append(std::move(pPara)); ImplCheckNumBulletItem( nCurPara ); @@ -621,11 +621,11 @@ void Outliner::AddText( const OutlinerParaObject& rPObj, bool bAppend ) continue; } - Paragraph* pPara = new Paragraph( rPObj.GetParagraphData(n) ); + Paragraph* pPara = new Paragraph( rPObj.GetNumberingDepth(n), rPObj.GetNumberingStartValue(n), rPObj.IsNumberingRestart(n) ); pParaList->Append(std::unique_ptr(pPara)); sal_Int32 nP = nPara+n; DBG_ASSERT(pParaList->GetAbsPos(pPara)==nP,"AddText:Out of sync"); - ImplInitDepth( nP, pPara->GetDepth(), false ); + ImplInitDepth( nP, pPara->GetNumberingDepth(), false ); } DBG_ASSERT( pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(), "SetText: OutOfSync" ); @@ -721,8 +721,8 @@ void Outliner::ImplInitDepth( sal_Int32 nPara, sal_Int16 nDepth, bool bCreateUnd Paragraph* pPara = pParaList->GetParagraph( nPara ); if (!pPara) return; - sal_Int16 nOldDepth = pPara->GetDepth(); - pPara->SetDepth( nDepth ); + sal_Int16 nOldDepth = pPara->GetNumberingDepth(); + pPara->SetNumberingDepth( nDepth ); // For IsInUndo attributes and style do not have to be set, there // the old values are restored by the EditEngine. @@ -1069,10 +1069,10 @@ void Outliner::ImpFilterIndents( sal_Int32 nFirstPara, sal_Int32 nLastPara ) else if ( pLastConverted ) { // Arrange normal paragraphs below the heading ... - pPara->SetDepth( pLastConverted->GetDepth() ); + pPara->SetNumberingDepth( pLastConverted->GetNumberingDepth() ); } - ImplInitDepth( nPara, pPara->GetDepth(), false ); + ImplInitDepth( nPara, pPara->GetNumberingDepth(), false ); } } @@ -1101,7 +1101,7 @@ void Outliner::ImpTextPasted( sal_Int32 nStartPara, sal_Int32 nCount ) { if( GetOutlinerMode() != OutlinerMode::TextObject ) { - nDepthChangedHdlPrevDepth = pPara->GetDepth(); + nDepthChangedHdlPrevDepth = pPara->GetNumberingDepth(); ParaFlag nPrevFlags = pPara->nFlags; ImpConvertEdtToOut( nStartPara ); @@ -1109,7 +1109,7 @@ void Outliner::ImpTextPasted( sal_Int32 nStartPara, sal_Int32 nCount ) if( nStartPara == nStart ) { // the existing paragraph has changed depth or flags - if( (pPara->GetDepth() != nDepthChangedHdlPrevDepth) || (pPara->nFlags != nPrevFlags) ) + if( (pPara->GetNumberingDepth() != nDepthChangedHdlPrevDepth) || (pPara->nFlags != nPrevFlags) ) DepthChangedHdl(pPara, nPrevFlags); } } @@ -1300,7 +1300,7 @@ const SvxNumberFormat* Outliner::GetNumberFormat( sal_Int32 nPara ) const if (!pPara) return nullptr; - sal_Int16 nDepth = pPara->GetDepth(); + sal_Int16 nDepth = pPara->GetNumberingDepth(); if( nDepth >= 0 ) { @@ -1394,9 +1394,9 @@ void Outliner::ParaAttribsChanged( sal_Int32 nPara ) // tdf#100734: force update of bullet pPara->Invalidate(); const SfxInt16Item& rLevel = pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); - if (pPara->GetDepth() == rLevel.GetValue()) + if (pPara->GetNumberingDepth() == rLevel.GetValue()) return; - pPara->SetDepth(rLevel.GetValue()); + pPara->SetNumberingDepth(rLevel.GetValue()); ImplCalcBulletText(nPara, true, true); } @@ -1663,12 +1663,12 @@ sal_uInt16 Outliner::ImplGetNumbering( sal_Int32 nPara, const SvxNumberFormat* p sal_uInt16 nNumber = pParaFmt->GetStart() - 1; Paragraph* pPara = pParaList->GetParagraph( nPara ); - const sal_Int16 nParaDepth = pPara->GetDepth(); + const sal_Int16 nParaDepth = pPara->GetNumberingDepth(); do { pPara = pParaList->GetParagraph( nPara ); - const sal_Int16 nDepth = pPara->GetDepth(); + const sal_Int16 nDepth = pPara->GetNumberingDepth(); // ignore paragraphs that are below our paragraph or have no numbering if( (nDepth > nParaDepth) || (nDepth == -1) ) @@ -1700,7 +1700,7 @@ sal_uInt16 Outliner::ImplGetNumbering( sal_Int32 nPara, const SvxNumberFormat* p // same depth, same number format, check for restart const sal_Int16 nNumberingStartValue = pPara->GetNumberingStartValue(); - if( (nNumberingStartValue != -1) || pPara->IsParaIsNumberingRestart() ) + if( (nNumberingStartValue != -1) || pPara->IsNumberingRestart() ) { if( nNumberingStartValue != -1 ) nNumber += nNumberingStartValue - 1; @@ -1741,15 +1741,15 @@ void Outliner::ImplCalcBulletText( sal_Int32 nPara, bool bRecalcLevel, bool bRec if ( bRecalcLevel ) { - sal_Int16 nDepth = pPara->GetDepth(); + sal_Int16 nDepth = pPara->GetNumberingDepth(); pPara = pParaList->GetParagraph( ++nPara ); if ( !bRecalcChildren ) { - while ( pPara && ( pPara->GetDepth() > nDepth ) ) + while ( pPara && ( pPara->GetNumberingDepth() > nDepth ) ) pPara = pParaList->GetParagraph( ++nPara ); } - if ( pPara && ( pPara->GetDepth() < nDepth ) ) + if ( pPara && ( pPara->GetNumberingDepth() < nDepth ) ) pPara = nullptr; } else @@ -1775,7 +1775,7 @@ void Outliner::Clear() { Paragraph* pPara = pParaList->GetParagraph( 0 ); if(pPara) - pPara->SetDepth( gnMinDepth ); + pPara->SetNumberingDepth( gnMinDepth ); } } @@ -1914,7 +1914,7 @@ std::optional Outliner::GetNonOverflowingText() const if (nCount < 0) { SAL_INFO("editeng.chaining", - "[Overflowing] No Overflowing text but GetNonOverflowinText called?!"); + "[Overflowing] No Overflowing text but GetNonOverflowingText called?!"); return {}; } @@ -1996,8 +1996,8 @@ std::optional Outliner::GetNonOverflowingText() const OutlinerParaObject Outliner::GetEmptyParaObject() const { - std::unique_ptr pEmptyText = pEditEngine->GetEmptyTextObject(); - OutlinerParaObject aPObj( std::move(pEmptyText) ); + EditTextObject aEmptyText = pEditEngine->GetEmptyTextObject(); + OutlinerParaObject aPObj( std::move(aEmptyText) ); aPObj.SetOutlinerMode(GetOutlinerMode()); return aPObj; } diff --git a/editeng/source/outliner/outlobj.cxx b/editeng/source/outliner/outlobj.cxx index d2da7beae858..e7abd91063ef 100644 --- a/editeng/source/outliner/outlobj.cxx +++ b/editeng/source/outliner/outlobj.cxx @@ -27,46 +27,10 @@ #include #include -OutlinerParaObjData::OutlinerParaObjData( std::unique_ptr pEditTextObject, ParagraphDataVector&& rParagraphDataVector, bool bIsEditDoc ) : - mpEditTextObject(std::move(pEditTextObject)), - maParagraphDataVector(std::move(rParagraphDataVector)), - mbIsEditDoc(bIsEditDoc) -{ - if( maParagraphDataVector.empty() && (mpEditTextObject->GetParagraphCount() != 0) ) - maParagraphDataVector.resize(mpEditTextObject->GetParagraphCount()); -} -OutlinerParaObjData::OutlinerParaObjData( const OutlinerParaObjData& r ): - mpEditTextObject(r.mpEditTextObject->Clone()), - maParagraphDataVector(r.maParagraphDataVector), - mbIsEditDoc(r.mbIsEditDoc) -{ -} -OutlinerParaObjData::~OutlinerParaObjData() -{ -} - -bool OutlinerParaObjData::operator==(const OutlinerParaObjData& rCandidate) const -{ - return (*mpEditTextObject == *rCandidate.mpEditTextObject - && maParagraphDataVector == rCandidate.maParagraphDataVector - && mbIsEditDoc == rCandidate.mbIsEditDoc); -} - -bool OutlinerParaObjData::isWrongListEqual(const OutlinerParaObjData& rCompare) const -{ - return mpEditTextObject->isWrongListEqual(*rCompare.mpEditTextObject); -} - -OutlinerParaObject::OutlinerParaObject( - std::unique_ptr xTextObj, ParagraphDataVector&& rParagraphDataVector, bool bIsEditDoc ) : - mpImpl(OutlinerParaObjData(std::move(xTextObj), std::move(rParagraphDataVector), bIsEditDoc)) -{ -} - -OutlinerParaObject::OutlinerParaObject( std::unique_ptr pTextObj ) : - mpImpl(OutlinerParaObjData(std::move(pTextObj), ParagraphDataVector(), true)) +OutlinerParaObject::OutlinerParaObject( EditTextObject&& aTextObj ) : + mpImpl(std::move(aTextObj)) { } @@ -114,56 +78,56 @@ bool OutlinerParaObject::isWrongListEqual( const OutlinerParaObject& r ) const OutlinerMode OutlinerParaObject::GetOutlinerMode() const { - return mpImpl->mpEditTextObject->GetUserType(); + return mpImpl->GetUserType(); } void OutlinerParaObject::SetOutlinerMode(OutlinerMode nNew) { // create a const pointer to avoid an early call to // make_unique() in the dereference of mpImpl - const ::o3tl::cow_wrapper< OutlinerParaObjData >* pImpl = &mpImpl; - if ( ( *pImpl )->mpEditTextObject->GetUserType() != nNew ) + const ::o3tl::cow_wrapper< EditTextObject >* pImpl = &mpImpl; + if ( ( *pImpl )->GetUserType() != nNew ) { - mpImpl->mpEditTextObject->SetUserType(nNew); + mpImpl->SetUserType(nNew); } } bool OutlinerParaObject::IsEffectivelyVertical() const { - return mpImpl->mpEditTextObject->IsEffectivelyVertical(); + return mpImpl->IsEffectivelyVertical(); } bool OutlinerParaObject::GetVertical() const { - return mpImpl->mpEditTextObject->GetVertical(); + return mpImpl->GetVertical(); } bool OutlinerParaObject::IsTopToBottom() const { - return mpImpl->mpEditTextObject->IsTopToBottom(); + return mpImpl->IsTopToBottom(); } void OutlinerParaObject::SetVertical(bool bNew) { - const ::o3tl::cow_wrapper< OutlinerParaObjData >* pImpl = &mpImpl; - if ( ( *pImpl )->mpEditTextObject->IsEffectivelyVertical() != bNew) + const ::o3tl::cow_wrapper< EditTextObject >* pImpl = &mpImpl; + if ( ( *pImpl )->IsEffectivelyVertical() != bNew) { - mpImpl->mpEditTextObject->SetVertical(bNew); + mpImpl->SetVertical(bNew); } } void OutlinerParaObject::SetRotation(TextRotation nRotation) { - mpImpl->mpEditTextObject->SetRotation(nRotation); + mpImpl->SetRotation(nRotation); } TextRotation OutlinerParaObject::GetRotation() const { - return mpImpl->mpEditTextObject->GetRotation(); + return mpImpl->GetRotation(); } sal_Int32 OutlinerParaObject::Count() const { - size_t nSize = mpImpl->maParagraphDataVector.size(); + size_t nSize = mpImpl->GetParagraphCount(); if (nSize > o3tl::make_unsigned(EE_PARA_MAX)) { SAL_WARN( "editeng", "OutlinerParaObject::Count - overflow " << nSize); @@ -172,52 +136,41 @@ sal_Int32 OutlinerParaObject::Count() const return static_cast(nSize); } -sal_Int16 OutlinerParaObject::GetDepth(sal_Int32 nPara) const +sal_Int16 OutlinerParaObject::GetNumberingDepth(sal_Int32 nPara) const { - if(0 <= nPara && o3tl::make_unsigned(nPara) < mpImpl->maParagraphDataVector.size()) - { - return mpImpl->maParagraphDataVector[nPara].getDepth(); - } - else - { - return -1; - } + return mpImpl->GetNumberingDepth(nPara); +} + +sal_Int16 OutlinerParaObject::GetNumberingStartValue(sal_Int32 nPara) const +{ + return mpImpl->GetNumberingStartValue(nPara); +} + +bool OutlinerParaObject::IsNumberingRestart(sal_Int32 nPara) const +{ + return mpImpl->IsNumberingRestart(nPara); } const EditTextObject& OutlinerParaObject::GetTextObject() const { - return *mpImpl->mpEditTextObject; -} - -const ParagraphData& OutlinerParaObject::GetParagraphData(sal_Int32 nIndex) const -{ - if(0 <= nIndex && o3tl::make_unsigned(nIndex) < mpImpl->maParagraphDataVector.size()) - { - return mpImpl->maParagraphDataVector[nIndex]; - } - else - { - OSL_FAIL("OutlinerParaObject::GetParagraphData: Access out of range (!)"); - static ParagraphData aEmptyParagraphData; - return aEmptyParagraphData; - } + return *mpImpl; } void OutlinerParaObject::ClearPortionInfo() { - mpImpl->mpEditTextObject->ClearPortionInfo(); + mpImpl->ClearPortionInfo(); } bool OutlinerParaObject::ChangeStyleSheets(std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily) { - return mpImpl->mpEditTextObject->ChangeStyleSheets(rOldName, eOldFamily, rNewName, eNewFamily); + return mpImpl->ChangeStyleSheets(rOldName, eOldFamily, rNewName, eNewFamily); } void OutlinerParaObject::ChangeStyleSheetName(SfxStyleFamily eFamily, std::u16string_view rOldName, const OUString& rNewName) { - mpImpl->mpEditTextObject->ChangeStyleSheetName(eFamily, rOldName, rNewName); + mpImpl->ChangeStyleSheetName(eFamily, rOldName, rNewName); } void OutlinerParaObject::SetStyleSheets(sal_uInt16 nLevel, const OUString& rNewName, @@ -231,9 +184,9 @@ void OutlinerParaObject::SetStyleSheets(sal_uInt16 nLevel, const OUString& rNewN while(nDecrementer > 0) { - if(GetDepth(--nDecrementer) == nLevel) + if(GetNumberingDepth(--nDecrementer) == nLevel) { - mpImpl->mpEditTextObject->SetStyleSheet(nDecrementer, rNewName, rNewFamily); + mpImpl->SetStyleSheet(nDecrementer, rNewName, rNewFamily); } } } @@ -243,9 +196,7 @@ void OutlinerParaObject::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("OutlinerParaObject")); (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); - mpImpl->mpEditTextObject->dumpAsXml(pWriter); - for (ParagraphData const & p : mpImpl->maParagraphDataVector) - Paragraph(p).dumpAsXml(pWriter); + mpImpl->dumpAsXml(pWriter); (void)xmlTextWriterEndElement(pWriter); } diff --git a/editeng/source/outliner/outlundo.cxx b/editeng/source/outliner/outlundo.cxx index 799d33e29018..86e63ac1e8b9 100644 --- a/editeng/source/outliner/outlundo.cxx +++ b/editeng/source/outliner/outlundo.cxx @@ -51,7 +51,7 @@ void OutlinerUndoChangeParaFlags::ImplChangeFlags( ParaFlag nFlags ) Paragraph* pPara = pOutliner->GetParagraph( mnPara ); if( pPara ) { - pOutliner->nDepthChangedHdlPrevDepth = pPara->GetDepth(); + pOutliner->nDepthChangedHdlPrevDepth = pPara->GetNumberingDepth(); ParaFlag nPrevFlags = pPara->nFlags; pPara->nFlags = nFlags; @@ -124,7 +124,7 @@ void OutlinerUndoCheckPara::Redo() OLUndoExpand::OLUndoExpand(Outliner* pOut, sal_uInt16 _nId ) : EditUndo( _nId, nullptr ), pOutliner(pOut), nCount(0) { - DBG_ASSERT(pOut,"Undo:No Outliner"); + DBG_ASSERT(pOut,"Undo: No Outliner"); } OLUndoExpand::~OLUndoExpand() @@ -133,7 +133,7 @@ OLUndoExpand::~OLUndoExpand() void OLUndoExpand::Restore( bool bUndo ) { - assert(pOutliner && "Undo:No Outliner"); + assert(pOutliner && "Undo: No Outliner"); DBG_ASSERT(pOutliner->pEditEngine,"Outliner already deleted"); Paragraph* pPara; diff --git a/editeng/source/outliner/outlvw.cxx b/editeng/source/outliner/outlvw.cxx index c5d90d0713fd..56a4528e9d5b 100644 --- a/editeng/source/outliner/outlvw.cxx +++ b/editeng/source/outliner/outlvw.cxx @@ -178,7 +178,7 @@ bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFra Paragraph* pPrev = rOwner.pParaList->GetParagraph(aSel.end.nPara - 1); if( !pPrev->IsVisible() ) return true; - if( !pPara->GetDepth() ) + if( !pPara->GetNumberingDepth() ) { if (!rOwner.ImpCanDeleteSelectedPages(this, aSel.end.nPara, 1)) return true; @@ -197,7 +197,7 @@ bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFra if( !aKeyCode.IsShift() ) { // Don't let insert empty paragraph with numbering. Instead end numbering. - if (pPara->GetDepth() > -1 && + if (pPara->GetNumberingDepth() > -1 && rOwner.pEditEngine->GetTextLen( aSel.end.nPara ) == 0) { ToggleBullets(); @@ -217,7 +217,7 @@ bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFra SAL_WARN_IF( nTemp < 0, "editeng", "OutlinerView::PostKeyEvent - overflow"); if (nTemp >= 0) { - rOwner.Insert( OUString(),nTemp,pPara->GetDepth()); + rOwner.Insert( OUString(),nTemp,pPara->GetNumberingDepth()); // Position the cursor ESelection aTmpSel(nTemp, 0); pEditView->SetSelection( aTmpSel ); @@ -235,7 +235,7 @@ bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFra rOwner.UndoActionStart( OLUNDO_INSERT ); sal_Int32 nTemp = aSel.end.nPara; nTemp++; - rOwner.Insert( OUString(), nTemp, pPara->GetDepth()+1 ); + rOwner.Insert( OUString(), nTemp, pPara->GetNumberingDepth()+1 ); // Position the cursor ESelection aTmpSel(nTemp, 0); @@ -486,7 +486,7 @@ void OutlinerView::Indent( short nDiff ) { Paragraph* pPara = rOwner.pParaList->GetParagraph( nPara ); - sal_Int16 nOldDepth = pPara->GetDepth(); + sal_Int16 nOldDepth = pPara->GetNumberingDepth(); sal_Int16 nNewDepth = nOldDepth + nDiff; if( bOutlinerView && nPara ) @@ -545,7 +545,7 @@ void OutlinerView::Indent( short nDiff ) #endif Paragraph* pPrev= rOwner.pParaList->GetParagraph( aSel.nStartPara-1 ); - if( !pPrev->IsVisible() && ( pPrev->GetDepth() == nNewDepth ) ) + if( !pPrev->IsVisible() && ( pPrev->GetNumberingDepth() == nNewDepth ) ) { // Predecessor is collapsed and is on the same level // => find next visible paragraph and expand it @@ -581,7 +581,7 @@ void OutlinerView::Indent( short nDiff ) for ( sal_Int32 n = aSel.nEndPara+1; n < nParas; n++ ) { Paragraph* pPara = rOwner.pParaList->GetParagraph( n ); - if ( pPara->GetDepth() < nMinDepth ) + if ( pPara->GetNumberingDepth() < nMinDepth ) break; rOwner.ImplCalcBulletText( n, false, false ); } @@ -1244,7 +1244,7 @@ void OutlinerView::RemoveAttribs( bool bRemoveParaAttribs, bool bKeepLanguages ) for (sal_Int32 nPara = aSel.start.nPara; nPara <= aSel.end.nPara; nPara++) { Paragraph* pPara = rOwner.pParaList->GetParagraph( nPara ); - rOwner.ImplInitDepth( nPara, pPara->GetDepth(), false ); + rOwner.ImplInitDepth( nPara, pPara->GetNumberingDepth(), false ); } } rOwner.UndoActionEnd(); diff --git a/editeng/source/outliner/paralist.cxx b/editeng/source/outliner/paralist.cxx index d46fc8cf7d48..9ced9f808386 100644 --- a/editeng/source/outliner/paralist.cxx +++ b/editeng/source/outliner/paralist.cxx @@ -28,53 +28,41 @@ #include #include -ParagraphData::ParagraphData() -: nDepth( -1 ) -, mnNumberingStartValue( -1 ) -, mbParaIsNumberingRestart( false ) -{ -} - -bool ParagraphData::operator==(const ParagraphData& rCandidate) const -{ - return (nDepth == rCandidate.nDepth - && mnNumberingStartValue == rCandidate.mnNumberingStartValue - && mbParaIsNumberingRestart == rCandidate.mbParaIsNumberingRestart); -} - Paragraph::Paragraph( sal_Int16 nDDepth ) { DBG_ASSERT( ( nDDepth >= -1 ) && ( nDDepth < SVX_MAX_NUM ), "Paragraph-CTOR: nDepth invalid!" ); - nDepth = nDDepth; + mnNumberingDepth = nDDepth; + mnNumberingStartValue = -1; + mbNumberingRestart = false; } -Paragraph::Paragraph( const ParagraphData& rData ) +Paragraph::Paragraph( sal_Int16 nDepth, sal_Int16 nNumberingStartValue, bool bNumberingRestart ) { - nDepth = rData.nDepth; - mnNumberingStartValue = rData.mnNumberingStartValue; - mbParaIsNumberingRestart = rData.mbParaIsNumberingRestart; + mnNumberingDepth = nDepth; + mnNumberingStartValue = nNumberingStartValue; + mbNumberingRestart = bNumberingRestart; } void Paragraph::SetNumberingStartValue( sal_Int16 nNumberingStartValue ) { mnNumberingStartValue = nNumberingStartValue; if( mnNumberingStartValue != -1 ) - mbParaIsNumberingRestart = true; + mbNumberingRestart = true; } -void Paragraph::SetParaIsNumberingRestart( bool bParaIsNumberingRestart ) +void Paragraph::SetNumberingRestart( bool bParaIsNumberingRestart ) { - mbParaIsNumberingRestart = bParaIsNumberingRestart; - if( !mbParaIsNumberingRestart ) + mbNumberingRestart = bParaIsNumberingRestart; + if( !mbNumberingRestart ) mnNumberingStartValue = -1; } void Paragraph::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("Paragraph")); - (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("nDepth"), "%" SAL_PRIdINT32, static_cast(nDepth)); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("nNumberingDepth"), "%" SAL_PRIdINT32, static_cast(mnNumberingDepth)); (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("mnNumberingStartValue"), "%" SAL_PRIdINT32, static_cast(mnNumberingStartValue)); - (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("mbParaIsNumberingRestart"), "%" SAL_PRIdINT32, static_cast(mbParaIsNumberingRestart)); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("mbNumberingRestart"), "%" SAL_PRIdINT32, static_cast(mbNumberingRestart)); (void)xmlTextWriterEndElement(pWriter); } @@ -146,21 +134,21 @@ bool ParagraphList::HasChildren( Paragraph const * pParagraph ) const { sal_Int32 n = GetAbsPos( pParagraph ); Paragraph* pNext = GetParagraph( ++n ); - return pNext && ( pNext->GetDepth() > pParagraph->GetDepth() ); + return pNext && ( pNext->GetNumberingDepth() > pParagraph->GetNumberingDepth() ); } bool ParagraphList::HasHiddenChildren( Paragraph const * pParagraph ) const { sal_Int32 n = GetAbsPos( pParagraph ); Paragraph* pNext = GetParagraph( ++n ); - return pNext && ( pNext->GetDepth() > pParagraph->GetDepth() ) && !pNext->IsVisible(); + return pNext && ( pNext->GetNumberingDepth() > pParagraph->GetNumberingDepth() ) && !pNext->IsVisible(); } bool ParagraphList::HasVisibleChildren( Paragraph const * pParagraph ) const { sal_Int32 n = GetAbsPos( pParagraph ); Paragraph* pNext = GetParagraph( ++n ); - return pNext && ( pNext->GetDepth() > pParagraph->GetDepth() ) && pNext->IsVisible(); + return pNext && ( pNext->GetNumberingDepth() > pParagraph->GetNumberingDepth() ) && pNext->IsVisible(); } sal_Int32 ParagraphList::GetChildCount( Paragraph const * pParent ) const @@ -168,7 +156,7 @@ sal_Int32 ParagraphList::GetChildCount( Paragraph const * pParent ) const sal_Int32 nChildCount = 0; sal_Int32 n = GetAbsPos( pParent ); Paragraph* pPara = GetParagraph( ++n ); - while ( pPara && ( pPara->GetDepth() > pParent->GetDepth() ) ) + while ( pPara && ( pPara->GetNumberingDepth() > pParent->GetNumberingDepth() ) ) { nChildCount++; pPara = GetParagraph( ++n ); @@ -180,7 +168,7 @@ Paragraph* ParagraphList::GetParent( Paragraph const * pParagraph ) const { sal_Int32 n = GetAbsPos( pParagraph ); Paragraph* pPrev = GetParagraph( --n ); - while ( pPrev && ( pPrev->GetDepth() >= pParagraph->GetDepth() ) ) + while ( pPrev && ( pPrev->GetNumberingDepth() >= pParagraph->GetNumberingDepth() ) ) { pPrev = GetParagraph( --n ); } diff --git a/editeng/source/uno/unofdesc.cxx b/editeng/source/uno/unofdesc.cxx index a9b619ee21fa..e4184e275911 100644 --- a/editeng/source/uno/unofdesc.cxx +++ b/editeng/source/uno/unofdesc.cxx @@ -193,10 +193,10 @@ void SvxUnoFontDescriptor::setPropertyToDefault( SfxItemSet& rSet ) uno::Any SvxUnoFontDescriptor::getPropertyDefault( SfxItemPool* pPool ) { - SfxItemSetFixed< + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet< EE_CHAR_FONTINFO, EE_CHAR_FONTHEIGHT, EE_CHAR_WEIGHT, EE_CHAR_ITALIC, - EE_CHAR_WLM, EE_CHAR_WLM> aSet(*pPool); + EE_CHAR_WLM, EE_CHAR_WLM> (*pPool)); uno::Any aAny; diff --git a/editeng/source/uno/unofored.cxx b/editeng/source/uno/unofored.cxx index c8728c6255a5..11bc4f42d2f2 100644 --- a/editeng/source/uno/unofored.cxx +++ b/editeng/source/uno/unofored.cxx @@ -513,8 +513,8 @@ void SvxEditEngineForwarder::CopyText(const SvxTextForwarder& rSource) const SvxEditEngineForwarder* pSourceForwarder = dynamic_cast< const SvxEditEngineForwarder* >( &rSource ); if( !pSourceForwarder ) return; - std::unique_ptr pNewTextObject = pSourceForwarder->rEditEngine.CreateTextObject(); - rEditEngine.SetText( *pNewTextObject ); + EditTextObject aNewTextObject = pSourceForwarder->rEditEngine.CreateTextObject(); + rEditEngine.SetText( aNewTextObject ); } diff --git a/editeng/source/uno/unonrule.cxx b/editeng/source/uno/unonrule.cxx index a508d6a7544c..3a9bc44df0d6 100644 --- a/editeng/source/uno/unonrule.cxx +++ b/editeng/source/uno/unonrule.cxx @@ -431,8 +431,8 @@ void SvxUnoNumberingRules::setNumberingRuleByIndex(const Sequence>= nSize ) { - // [AOO Bug 120650] the slide content corrupt when open in Aoo - // [TDF# 126234] when MS Office document being imported, the value of the relative size + // [AOO Bug 120650] the slide content is corrupted when opened in AOO + // [TDF# 126234] when an MS Office document is being imported, the value of the relative size // of the bullet could be as high as 400% if ((nSize>400)||(nSize<=0)) { diff --git a/editeng/source/uno/unotext.cxx b/editeng/source/uno/unotext.cxx index fb2c22d772dc..a831dbe2cde7 100644 --- a/editeng/source/uno/unotext.cxx +++ b/editeng/source/uno/unotext.cxx @@ -1784,9 +1784,8 @@ void SAL_CALL SvxUnoTextBase::insertString( const uno::Reference< text::XTextRan if (GetEditSource()) { - ESelection aSelection; - ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() ); - SetSelection( aSelection ); + // Make the selection dynamic (whole text) instead of current text range + maSelection = ESelection(EE_PARA_MAX, 0, 0, 0); } } diff --git a/embeddedobj/Library_embobj.mk b/embeddedobj/Library_embobj.mk index 18cf55518d44..03c96f79b341 100644 --- a/embeddedobj/Library_embobj.mk +++ b/embeddedobj/Library_embobj.mk @@ -34,6 +34,7 @@ $(eval $(call gb_Library_use_libraries,embobj,\ cppu \ cppuhelper \ sal \ + svl \ svt \ utl \ vcl \ diff --git a/embeddedobj/source/commonembedding/embedobj.cxx b/embeddedobj/source/commonembedding/embedobj.cxx index a5ce1443515e..ad4cbf52ac9b 100644 --- a/embeddedobj/source/commonembedding/embedobj.cxx +++ b/embeddedobj/source/commonembedding/embedobj.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include #include @@ -39,10 +41,25 @@ #include #include #include +#include #include #include +#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include #include @@ -51,6 +68,183 @@ #include #include +namespace { + +// tdf#157943 / tdf#126742: locate the visible top-level frame loaded from +// sLinkURL, or null. Hidden frames are skipped (caller routes them to the +// warn path). Comparison mirrors LoadEnv::impl_searchAlreadyLoaded. +css::uno::Reference< css::frame::XFrame > findLinkSourceFrame( + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const OUString& sLinkURL ) +{ + if ( sLinkURL.isEmpty() || INetURLObject( sLinkURL ).IsExoticProtocol() ) + return nullptr; + + try + { + css::uno::Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create( xContext ); + css::uno::Reference< css::container::XIndexAccess > xFrames = xDesktop->getFrames(); + if ( !xFrames.is() ) + return nullptr; + + const sal_Int32 nCount = xFrames->getCount(); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + try + { + css::uno::Reference< css::frame::XFrame > xFrame; + xFrames->getByIndex( i ) >>= xFrame; + if ( !xFrame.is() ) + continue; + + OUString sFrameURL; + css::uno::Reference< css::frame::XController > xController = xFrame->getController(); + if ( xController.is() ) + { + css::uno::Reference< css::frame::XModel > xModel = xController->getModel(); + if ( xModel.is() ) + { + // Skip hidden frames. Calling activate() / toFront() + // on one would either silently no-op or unexpectedly + // reveal a frame meant to stay invisible. + bool bHidden = false; + for ( const auto& rProp : xModel->getArgs() ) + { + if ( rProp.Name == "Hidden" ) + { + rProp.Value >>= bHidden; + break; + } + } + if ( bHidden ) + continue; + + sFrameURL = xModel->getURL(); + } + } + else + { + // load may be in progress - URL lives on the frame itself + css::uno::Reference< css::beans::XPropertySet > xFrameProps( xFrame, css::uno::UNO_QUERY ); + if ( xFrameProps.is() ) + xFrameProps->getPropertyValue( u"URL"_ustr ) >>= sFrameURL; + } + + if ( sFrameURL.isEmpty() ) + continue; + + if ( ::utl::UCBContentHelper::EqualURLs( sLinkURL, sFrameURL ) ) + return xFrame; + } + catch ( const css::uno::Exception& ) + { + // ignore individual frame errors and keep iterating + } + } + } + catch ( const css::uno::Exception& ) + { + } + return nullptr; +} + +// Bring an already-loaded source document's frame to the front. Best-effort: +// failure here is harmless because the caller refuses the OLE activation +// regardless, which is the safe outcome. +void switchToExistingFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + if ( !xFrame.is() ) + return; + + try + { + xFrame->activate(); + css::uno::Reference< css::awt::XTopWindow > xTopWindow( xFrame->getContainerWindow(), css::uno::UNO_QUERY ); + if ( xTopWindow.is() ) + xTopWindow->toFront(); + } + catch ( const css::uno::Exception& ) + { + } +} + +// tdf#157943: any lock - foreign, hidden own frame, or stale own lock - +// would fail the OLE writeback at save time, so the caller refuses on +// any non-empty result. Visible-own-frame is filtered out earlier. +// On non-multiuser builds (Android/iOS) the svt::*DocumentLockFile +// symbols aren't linked, so the body short-circuits to "" - the caller +// just skips case 2 naturally without needing a separate gate. +OUString getSourceLockOwner( std::u16string_view sLinkURL ) +{ + if ( sLinkURL.empty() || INetURLObject( sLinkURL ).IsExoticProtocol() ) + return u""_ustr; + +#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT + auto formatOwner = []( const LockFileEntry& aData, bool bMSO ) + { + OUString sOwner = aData[LockFileComponent::OOOUSERNAME]; + if ( sOwner.isEmpty() ) + sOwner = aData[LockFileComponent::SYSUSERNAME]; + if ( sOwner.isEmpty() ) + return u""_ustr; // empty/corrupt lock data - treat as no lock + if ( bMSO ) + sOwner += " (MS Office)"; + return sOwner; + }; + + // LO format (.~lock.*#) + try + { + svt::DocumentLockFile aLockFile( sLinkURL ); + if ( OUString sOwner = formatOwner( aLockFile.GetLockData(), false ); + !sOwner.isEmpty() ) + return sOwner; + } + catch ( const css::uno::Exception& ) + { + } + + // MSO format (~$*) - LO understands these via tdf#34171 + if ( svt::MSODocumentLockFile::IsMSOSupportedFileFormat( sLinkURL ) ) + { + try + { + svt::MSODocumentLockFile aMSOLockFile( sLinkURL ); + if ( OUString sOwner = formatOwner( aMSOLockFile.GetLockData(), true ); + !sOwner.isEmpty() ) + return sOwner; + } + catch ( const css::uno::Exception& ) + { + } + } +#endif + + return u""_ustr; +} + +void showLinkSourceLockedDialog( const css::uno::Reference< css::awt::XWindow >& xClientWindow, + std::u16string_view sLinkURL, + std::u16string_view sOwner ) +{ + std::locale aResLocale = Translate::Create( "emo" ); + OUString aMsg = Translate::get( STR_LINK_SOURCE_LOCKED, aResLocale ); + + OUString aLinkURL( sLinkURL ); + OUString aSysPath = aLinkURL; + osl::FileBase::getSystemPathFromFileURL( aLinkURL, aSysPath ); + aMsg = aMsg.replaceFirst( "%{filename}", aSysPath ); + aMsg = aMsg.replaceFirst( "%{owner}", sOwner ); + + weld::Window* pParent = Application::GetFrameWeld( xClientWindow ); + std::shared_ptr< weld::MessageDialog > xQueryBox( + Application::CreateMessageDialog( pParent, + VclMessageType::Warning, VclButtonsType::Ok, aMsg ) ); + xQueryBox->runAsync( xQueryBox, []( sal_Int32 ) {} ); +} + +} // anonymous namespace + using namespace ::com::sun::star; awt::Rectangle GetRectangleInterception( const awt::Rectangle& aRect1, const awt::Rectangle& aRect2 ) @@ -603,7 +797,49 @@ void SAL_CALL OCommonEmbeddedObject::doVerb( sal_Int32 nVerbID ) } else { - aGuard.clear(); + // tdf#157943 / tdf#126742: refuse user-initiated activation of an + // OLE link whose source is in use - either navigate to the visible + // frame (matches MSO) or warn on any lock (foreign, hidden own + // frame, or stale). Gated to visible-state verbs so internal + // RUNNING transitions aren't redirected. Skipped in headless. + if ( m_bIsLinkURL + && ( nNewState == embed::EmbedStates::INPLACE_ACTIVE + || nNewState == embed::EmbedStates::UI_ACTIVE + || nNewState == embed::EmbedStates::ACTIVE ) + && !Application::IsHeadlessModeEnabled() ) + { + // snapshot under m_aMutex so the framework calls below run on + // stable values even if breakLink/reload races on another thread + const OUString aLinkURL = m_aLinkURL; + const auto xClientWindow = m_xClientWindow; + const auto xContext = m_xContext; + aGuard.clear(); + + // 1. Source loaded as a visible frame here: bring it to front. + // Matches MSO's "navigate to existing editor" behaviour. + if ( auto xExistingFrame = findLinkSourceFrame( xContext, aLinkURL ); + xExistingFrame.is() ) + { + switchToExistingFrame( xExistingFrame ); + return; + } + + // 2. Lock file present (foreign, hidden own frame, or stale + // own lock from a crash) - all fail writeback at save time. + // On non-multiuser builds getSourceLockOwner returns "" and + // this branch is naturally skipped - no #if needed here. + if ( OUString sLockOwner = getSourceLockOwner( aLinkURL ); + !sLockOwner.isEmpty() ) + { + showLinkSourceLockedDialog( xClientWindow, aLinkURL, sLockOwner ); + return; + } + } + else + { + aGuard.clear(); + } + changeState( nNewState ); } } diff --git a/embeddedobj/source/commonembedding/miscobj.cxx b/embeddedobj/source/commonembedding/miscobj.cxx index 0834f5143c7c..083ab26122b2 100644 --- a/embeddedobj/source/commonembedding/miscobj.cxx +++ b/embeddedobj/source/commonembedding/miscobj.cxx @@ -36,7 +36,6 @@ #include #include -#include #include #include #include diff --git a/embeddedobj/source/commonembedding/persistence.cxx b/embeddedobj/source/commonembedding/persistence.cxx index af72eb466a8f..de9f12991c35 100644 --- a/embeddedobj/source/commonembedding/persistence.cxx +++ b/embeddedobj/source/commonembedding/persistence.cxx @@ -1020,7 +1020,7 @@ void SAL_CALL OCommonEmbeddedObject::setPersistentEntry( } // for now support of this interface is required to allow breaking of links and converting them to normal embedded - // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) + // objects, so the persist name must be handled correctly ( although no real persist entry is used ) // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); if ( m_bIsLinkURL ) { @@ -1194,7 +1194,7 @@ void SAL_CALL OCommonEmbeddedObject::storeToEntry( const uno::Reference< embed:: static_cast< ::cppu::OWeakObject* >(this) ); // for now support of this interface is required to allow breaking of links and converting them to normal embedded - // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) + // objects, so the persist name must be handled correctly ( although no real persist entry is used ) // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); if ( m_bIsLinkURL ) return; @@ -1324,7 +1324,7 @@ void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed:: static_cast< ::cppu::OWeakObject* >(this) ); // for now support of this interface is required to allow breaking of links and converting them to normal embedded - // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) + // objects, so the persist name must be handled correctly ( although no real persist entry is used ) // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); if ( m_bIsLinkURL ) { @@ -1460,7 +1460,7 @@ void SAL_CALL OCommonEmbeddedObject::saveCompleted( sal_Bool bUseNew ) } // for now support of this interface is required to allow breaking of links and converting them to normal embedded - // objects, so the persist name must be handled correctly ( althowgh no real persist entry is used ) + // objects, so the persist name must be handled correctly ( although no real persist entry is used ) // OSL_ENSURE( !m_bIsLinkURL, "This method implementation must not be used for links!" ); if ( m_bIsLinkURL ) { diff --git a/embeddedobj/source/inc/strings.hrc b/embeddedobj/source/inc/strings.hrc index 420d2d05d091..2936b88d577d 100644 --- a/embeddedobj/source/inc/strings.hrc +++ b/embeddedobj/source/inc/strings.hrc @@ -14,6 +14,7 @@ #define BTN_OVERWRITE_TEXT NC_("BTN_OVERWRITE_TEXT", "Overwrite") #define STR_OVERWRITE_LINK NC_("STR_OVERWRITE_LINK", "You have made changes to the %{filename}, saving will overwrite the data from the inserted object.\n\nDo you still want to overwrite this data?") #define STR_OVERWRITE_TEMP NC_("STR_OVERWRITE_TEMP", "You have changed the data in the inserted object which will be overwritten by updating the %{filename}.\n\nDo you still want to overwrite this data?") +#define STR_LINK_SOURCE_LOCKED NC_("STR_LINK_SOURCE_LOCKED", "The source of this OLE link, %{filename}, is currently locked by %{owner}.\n\nSaving changes through this link will fail. Please close the file before editing.") /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/embeddedobj/source/msole/advisesink.cxx b/embeddedobj/source/msole/advisesink.cxx index 5601c8d9eb34..cd3ed4c73ea3 100644 --- a/embeddedobj/source/msole/advisesink.cxx +++ b/embeddedobj/source/msole/advisesink.cxx @@ -69,7 +69,7 @@ STDMETHODIMP_(ULONG) OleWrapperAdviseSink::Release() void OleWrapperAdviseSink::disconnectOleComponent() { - // must not be called from the descructor of OleComponent!!! + // must not be called from the destructor of OleComponent!!! osl::MutexGuard aGuard( m_aMutex ); m_pOleComp = nullptr; } diff --git a/embeddedobj/source/msole/olecomponent.hxx b/embeddedobj/source/msole/olecomponent.hxx index 7df0cebdd75c..788c1778beeb 100644 --- a/embeddedobj/source/msole/olecomponent.hxx +++ b/embeddedobj/source/msole/olecomponent.hxx @@ -81,8 +81,6 @@ public: virtual ~OleComponent() override; - OleComponent* createEmbeddedCopyOfLink(); - void disconnectEmbeddedObject(); static css::awt::Size CalculateWithFactor( const css::awt::Size& aSize, diff --git a/embeddedobj/source/msole/oleembed.cxx b/embeddedobj/source/msole/oleembed.cxx index 063646d39590..5c7da623260e 100644 --- a/embeddedobj/source/msole/oleembed.cxx +++ b/embeddedobj/source/msole/oleembed.cxx @@ -536,7 +536,7 @@ void SAL_CALL OleEmbeddedObject::changeState( sal_Int32 nNewState ) return; } - // so now the object is either switched from Active to Running state or viceversa + // so now the object is either switched from Active to Running state or vice versa // the notification about object state change will be done asynchronously if ( m_nObjectState == embed::EmbedStates::RUNNING && nNewState == embed::EmbedStates::ACTIVE ) { diff --git a/embeddedobj/source/msole/olewrapclient.cxx b/embeddedobj/source/msole/olewrapclient.cxx index 15d5f16632fa..9ec3bd16af13 100644 --- a/embeddedobj/source/msole/olewrapclient.cxx +++ b/embeddedobj/source/msole/olewrapclient.cxx @@ -22,7 +22,7 @@ #include "olewrapclient.hxx" #include "olecomponent.hxx" -// TODO: May be a mutex must be introduced +// TODO: Maybe a mutex must be introduced OleWrapperClientSite::OleWrapperClientSite( OleComponent* pOleComp ) : m_nRefCount( 0 ) @@ -70,7 +70,7 @@ STDMETHODIMP_(ULONG) OleWrapperClientSite::Release() void OleWrapperClientSite::disconnectOleComponent() { - // must not be called from the descructor of OleComponent!!! + // must not be called from the destructor of OleComponent!!! osl::MutexGuard aGuard( m_aMutex ); m_pOleComp = nullptr; } diff --git a/emfio/README.md b/emfio/README.md index b1a0de61c888..b24f3e8a4c3e 100644 --- a/emfio/README.md +++ b/emfio/README.md @@ -63,7 +63,7 @@ Currently, these records are not implemented for WMF (specified in `wmfreader.cxx`): ``` -W_META_SETRELABS W_META_SETPOLYFILLMODE W_META_SETSTRETCHBLTMODE +W_META_SETRELABS W_META_SETSTRETCHBLTMODE W_META_SETTEXTCHAREXTRA W_META_SETTEXTJUSTIFICATION W_META_FLOODFILL W_META_FILLREGION W_META_FRAMEREGION W_META_INVERTREGION W_META_PAINTREGION W_META_DRAWTEXT W_META_SETMAPPERFLAGS @@ -77,18 +77,18 @@ And these records are not implemented for EMF/EMF+ (specified in `emfreader.cxx` ``` EMR_MASKBLT EMR_PLGBLT EMR_SETDIBITSTODEVICE EMR_FRAMERGN -EMR_INVERTRGN EMR_FLATTENPATH EMR_WIDENPATH EMR_POLYDRAW +EMR_INVERTRGN EMR_FLATTENPATH EMR_WIDENPATH EMR_SETPALETTEENTRIES EMR_RESIZEPALETTE -EMR_EXTFLOODFILL EMR_ANGLEARC EMR_SETCOLORADJUSTMENT EMR_POLYDRAW16 -EMR_CREATECOLORSPACE EMR_SETCOLORSPACE EMR_DELETECOLORSPACE +EMR_EXTFLOODFILL EMR_SETCOLORADJUSTMENT EMR_POLYDRAW16 +EMR_SETCOLORSPACE EMR_DELETECOLORSPACE EMR_GLSRECORD EMR_GLSBOUNDEDRECORD EMR_PIXELFORMAT EMR_DRAWESCAPE EMR_EXTESCAPE EMR_STARTDOC EMR_FORCEUFIMAPPING EMR_NAMEDESCAPE EMR_COLORCORRECTPALETTE EMR_SETICMPROFILEA EMR_SETICMPROFILEW EMR_TRANSPARENTBLT EMR_TRANSPARENTDIB -EMR_GRADIENTFILL EMR_SETLINKEDUFIS EMR_SETMAPPERFLAGS EMR_SETICMMODE -EMR_CREATEMONOBRUSH EMR_SETBRUSHORGEX EMR_SETMETARGN EMR_SETMITERLIMIT -EMR_EXCLUDECLIPRECT EMR_REALIZEPALETTE EMR_SELECTPALETTE -EMR_CREATEPALETTE EMR_ALPHADIBBLEND EMR_SETTEXTJUSTIFICATION +EMR_SETLINKEDUFIS EMR_SETMAPPERFLAGS EMR_SETICMMODE +EMR_SETBRUSHORGEX EMR_SETMETARGN EMR_SETMITERLIMIT +EMR_REALIZEPALETTE EMR_SELECTPALETTE +EMR_CREATEPALETTE EMR_SETTEXTJUSTIFICATION ``` Due to the difference on the fonts available on various platforms, the outcome diff --git a/emfio/inc/emfreader.hxx b/emfio/inc/emfreader.hxx index 4893a45733af..65d2e888f7d3 100644 --- a/emfio/inc/emfreader.hxx +++ b/emfio/inc/emfreader.hxx @@ -44,9 +44,9 @@ namespace emfio ~EmfReader(); bool ReadEnhWMF(); - void ReadGDIComment(sal_uInt32 nCommentId); + void ReadGDIComment(sal_uInt32 nCommentId, sal_uInt64 nNextPos); /// Parses EMR_COMMENT_MULTIFORMATS. - void ReadMultiformatsComment(); + void ReadMultiformatsComment(sal_uInt64 nNextPos); void SetSizeHint(const basegfx::B2DTuple& rSizeHint) { maSizeHint = rSizeHint; } void SetEnableEMFPlus(bool bEnableEMFPlus) { mbEnableEMFPlus = bEnableEMFPlus; } diff --git a/emfio/inc/mtftools.hxx b/emfio/inc/mtftools.hxx index 8f605ebc7db4..5f0fd268953d 100644 --- a/emfio/inc/mtftools.hxx +++ b/emfio/inc/mtftools.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -329,6 +330,10 @@ namespace emfio //Scalar constants constexpr sal_Int32 UNDOCUMENTED_WIN_RCL_RELATION = 32; constexpr sal_Int32 MS_FIXPOINT_BITCOUNT_28_4 = 4; + + /** Map a Windows hatch index (HS_*) to a VCL Hatch. + * [MS-WMF] 2.1.1.12 HatchStyle Enumeration */ + Hatch mapWindowsHatch(sal_uInt32 nHatchIndex, const Color& rColor); } //============================ WmfReader ================================== @@ -401,7 +406,7 @@ namespace emfio enum class WinMtfFillStyleType { - Solid, Pattern + Solid, Pattern, Hatch }; struct WinMtfFillStyle final : GDIObj @@ -410,6 +415,7 @@ namespace emfio bool bTransparent; WinMtfFillStyleType aType; Bitmap aBmp; + Hatch aHatch; WinMtfFillStyle() : aFillColor(COL_BLACK) @@ -429,11 +435,20 @@ namespace emfio , aBmp(rBmp) {} + WinMtfFillStyle(const Color& rColor, const Hatch& rHatch) + : aFillColor(rColor) + , bTransparent(false) + , aType(WinMtfFillStyleType::Hatch) + , aHatch(rHatch) + {} + bool operator==(const WinMtfFillStyle& rStyle) const { return aFillColor == rStyle.aFillColor && bTransparent == rStyle.bTransparent - && aType == rStyle.aType; + && aType == rStyle.aType + && aHatch == rStyle.aHatch + && aBmp == rStyle.aBmp; } }; @@ -458,19 +473,24 @@ namespace emfio Color aLineColor; LineInfo aLineInfo; bool bTransparent; + bool bHasHatch; + Hatch aHatch; WinMtfLineStyle() : aLineColor(COL_BLACK) , bTransparent(false) + , bHasHatch(false) {} WinMtfLineStyle(const Color& rColor, bool bTrans = false) : aLineColor(rColor) , bTransparent(bTrans) + , bHasHatch(false) {} WinMtfLineStyle(const Color& rColor, const sal_uInt32 nStyle, const sal_uInt32 nPenWidth) : aLineColor(rColor) + , bHasHatch(false) { // According to documentation: nStyle = PS_COSMETIC = 0x0 - line with a width of one logical unit and a style that is a solid color // tdf#140271 Based on observed behaviour the line width is not constant with PS_COSMETIC @@ -543,7 +563,9 @@ namespace emfio { return aLineColor == rStyle.aLineColor && bTransparent == rStyle.bTransparent - && aLineInfo == rStyle.aLineInfo; + && aLineInfo == rStyle.aLineInfo + && bHasHatch == rStyle.bHasHatch + && aHatch == rStyle.aHatch; } }; @@ -593,6 +615,7 @@ namespace emfio bool bClockWiseArcDirection; bool bFillStyleSelected; + sal_uInt32 nPolyFillMode; }; struct BSaveStruct @@ -662,6 +685,9 @@ namespace emfio RasterOp meRasterOp; std::vector< std::unique_ptr > mvGDIObj; + /// Every slot in mvGDIObj below this index holds an object, so the first free one is here + /// or above. + std::size_t mnLowestFreeGDIObj; Point maActPos; WMFRasterOp mnRop; std::vector< std::shared_ptr > mvSaveStack; @@ -699,6 +725,7 @@ namespace emfio bool mbNopMode : 1; bool mbClockWiseArcDirection : 1; bool mbFillStyleSelected : 1; + sal_uInt32 mnPolyFillMode; // ALTERNATE(1) or WINDING(2) bool mbClipNeedsUpdate : 1; bool mbComplexClip : 1; bool mbIsMapWinSet : 1; @@ -721,6 +748,8 @@ namespace emfio void ImplSetNonPersistentLineColorTransparenz(); void ImplDrawClippedPolyPolygon(const tools::PolyPolygon& rPolyPoly); void ImplDrawBitmap(const Point& rPos, const Size& rSize, const Bitmap& rBitmap); + bool ImplEmitLineHatch(const tools::Polygon& rPoly); + void ImplEmitPatternFill(const tools::PolyPolygon& rPolyPoly); public: @@ -756,6 +785,7 @@ namespace emfio void SetGfxMode(GraphicsMode nGfxMode) { meGfxMode = nGfxMode; }; GraphicsMode GetGfxMode() const { return meGfxMode; }; void SetBkMode(BackgroundMode nMode); + void SetPolyFillMode(sal_uInt32 nPolyFillMode); void SetBkColor(const Color& rColor); void SetTextColor(const Color& rColor); void SetTextAlign(sal_uInt32 nAlign); @@ -816,6 +846,18 @@ namespace emfio bool bRecordPath = false, GraphicsMode nGraphicsMode = GraphicsMode::GM_COMPATIBLE); + /// Render pre-shaped glyph indices as polypolygon outlines. + /// Returns false if the required font is not available (caller + /// should fall back to DrawText). + bool DrawGlyphs(Point& rPosition, + const std::vector& rGlyphIds, + KernArray* pDXArry = nullptr, + tools::Long* pDYArry = nullptr, + const float fXScale = 1.0, + const float fYScale = 1.0, + bool bRecordPath = false, + GraphicsMode nGraphicsMode = GraphicsMode::GM_COMPATIBLE); + void ResolveBitmapActions(std::vector& rSaveList); void IntersectClipRect(const tools::Rectangle& rRect); diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx index 35ca71f10786..4050036d9562 100644 --- a/emfio/qa/cppunit/emf/EmfImportTest.cxx +++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx @@ -83,36 +83,35 @@ CPPUNIT_TEST_FIXTURE(Test, testPolyPolygon) // Chart axis assertXPath(pDocument, aXPathPrefix + "mask/polypolygon", "path", u"m0 0h19746v14817h-19746z"); - assertXPath(pDocument, aXPathPrefix + "mask/polypolygoncolor", 2); - assertXPath(pDocument, aXPathPrefix + "mask/polypolygoncolor[1]", "color", u"#ffffff"); - assertXPath(pDocument, aXPathPrefix + "mask/polypolygoncolor[1]/polypolygon", "path", + const OString aClipped = aXPathPrefix + "mask/group[1]/mask/"; + assertXPath(pDocument, aClipped + "polypolygoncolor", 2); + assertXPath(pDocument, aClipped + "polypolygoncolor[1]", "color", u"#ffffff"); + assertXPath(pDocument, aClipped + "polypolygoncolor[1]/polypolygon", "path", u"m0 0h19781v14852h-19781z"); - assertXPath(pDocument, aXPathPrefix + "mask/polypolygoncolor[2]/polypolygon", "path", + assertXPath(pDocument, aClipped + "polypolygoncolor[2]/polypolygon", "path", u"m2574 13194v-12065h15303v12065z"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke", 116); - assertXPathContent(pDocument, aXPathPrefix + "mask/polygonstroke[1]/polygon", + assertXPath(pDocument, aXPathPrefix + "mask//polygonstroke", 116); + assertXPathContent(pDocument, aClipped + "polygonstroke[1]/polygon", u"2574,13194 2574,1129 17877,1129 17877,13194"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke[1]/line", "color", u"#ffffff"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke[1]/line", "width", u"35"); - assertXPathContent(pDocument, aXPathPrefix + "mask/polygonstroke[2]/polygon", - u"2574,13194 2574,1129"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke[2]/line", "color", u"#000000"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke[2]/line", "width", u"35"); - assertXPathContent(pDocument, aXPathPrefix + "mask/polygonstroke[10]/polygon", - u"8674,13194 8674,1129"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke[10]/line", "color", u"#000000"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke[10]/line", "width", u"35"); + assertXPath(pDocument, aClipped + "polygonstroke[1]/line", "color", u"#ffffff"); + assertXPath(pDocument, aClipped + "polygonstroke[1]/line", "width", u"35"); + assertXPathContent(pDocument, aClipped + "polygonstroke[2]/polygon", u"2574,13194 2574,1129"); + assertXPath(pDocument, aClipped + "polygonstroke[2]/line", "color", u"#000000"); + assertXPath(pDocument, aClipped + "polygonstroke[2]/line", "width", u"35"); + assertXPathContent(pDocument, aClipped + "polygonstroke[10]/polygon", u"8674,13194 8674,1129"); + assertXPath(pDocument, aClipped + "polygonstroke[10]/line", "color", u"#000000"); + assertXPath(pDocument, aClipped + "polygonstroke[10]/line", "width", u"35"); - assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion", 28); - assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[6]", "width", u"459"); - assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[6]", "x", u"9908"); - assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[6]", "text", u"0.5"); - assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[6]", "fontcolor", u"#000000"); - assertXPath(pDocument, aXPathPrefix + "mask/pointarray", 98); - assertXPath(pDocument, aXPathPrefix + "mask/pointarray[1]", "color", u"#000000"); - assertXPath(pDocument, aXPathPrefix + "mask/pointarray[1]/point", "x", u"2574"); - assertXPath(pDocument, aXPathPrefix + "mask/pointarray[1]/point", "y", u"1129"); + assertXPath(pDocument, aXPathPrefix + "mask//textsimpleportion", 28); + assertXPath(pDocument, aClipped + "textsimpleportion[6]", "width", u"459"); + assertXPath(pDocument, aClipped + "textsimpleportion[6]", "x", u"9908"); + assertXPath(pDocument, aClipped + "textsimpleportion[6]", "text", u"0.5"); + assertXPath(pDocument, aClipped + "textsimpleportion[6]", "fontcolor", u"#000000"); + assertXPath(pDocument, aXPathPrefix + "mask//pointarray", 98); + assertXPath(pDocument, aClipped + "pointarray[1]", "color", u"#000000"); + assertXPath(pDocument, aClipped + "pointarray[1]/point", "x", u"2574"); + assertXPath(pDocument, aClipped + "pointarray[1]/point", "y", u"1129"); } CPPUNIT_TEST_FIXTURE(Test, testDrawImagePointsTypeBitmap) @@ -182,7 +181,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDrawImagePointsWithMetafile) assertXPath( pDocument, - aXPathPrefix + "mask/mask/metafile/transform/mask/mask/metafile/transform/mask/group", 17); + aXPathPrefix + "mask/mask/metafile/transform/mask/mask/metafile/transform/mask/group", 22); assertXPathDoubleValue( pDocument, aXPathPrefix + "mask/mask/metafile/transform/mask/mask/metafile/transform", @@ -249,6 +248,28 @@ CPPUNIT_TEST_FIXTURE(Test, testFillRectsWithTextureBrush) assertXPath(pDocument, aXPathPrefix + "polypolygonstroke/polypolygon", "miny", u"397"); } +CPPUNIT_TEST_FIXTURE(Test, testEmfPlusFillRectsOverlap) +{ + // Three south-east-shifted overlapping squares in a single + // EmfPlusFillRects record must each fill independently. Combining + // them into one polypolygon would cancel pairwise overlaps under + // drawinglayer's even-odd fill rule, producing hollow stripes + // where two of the three squares meet. + Primitive2DSequence aSequence + = parseEmf(u"/emfio/qa/cppunit/emf/data/TestEmfPlusFillRectsOverlap.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // Three independent gray fills, one per rect (not one + // polypolygoncolor wrapping all three, which is the buggy form). + assertXPath(pDocument, "//polypolygoncolor", 3); + assertXPath(pDocument, "(//polypolygoncolor)[1]", "color", u"#808080"); + assertXPath(pDocument, "(//polypolygoncolor)[2]", "color", u"#808080"); + assertXPath(pDocument, "(//polypolygoncolor)[3]", "color", u"#808080"); +} + CPPUNIT_TEST_FIXTURE(Test, testDrawString) { #if HAVE_MORE_FONTS @@ -297,17 +318,18 @@ CPPUNIT_TEST_FIXTURE(Test, testDrawStringAlign) assertXPath(pDocument, aXPathPrefix + "mask/transform[2]/textsimpleportion", "width", u"12"); assertXPath(pDocument, aXPathPrefix + "mask/transform[2]/textsimpleportion", "height", u"12"); + // The file uses tracking == 1.03, so the centered text width includes the + // 3% character-spacing stretch and the centered position shifts left. assertXPathDoubleValue(pDocument, aXPathPrefix + "mask/transform[2]/textsimpleportion", "x", - 143.666, 0.001); + 143.177, 0.001); assertXPath(pDocument, aXPathPrefix + "mask/transform[2]/textsimpleportion", "y", u"22"); assertXPath(pDocument, aXPathPrefix + "mask/transform[2]/textsimpleportion", "text", u"HCVT"); // TODO Make the position of the text the same across the platforms (Arial vs Liberation Sans). - // This is usually 276, but can be 275 as well; depends on what fonts are installed? sal_Int32 nX = getXPath(pDocument, aXPathPrefix + "mask/transform[3]/textsimpleportion", "x").toInt32(); - CPPUNIT_ASSERT(nX >= 275); - CPPUNIT_ASSERT(nX <= 276); + CPPUNIT_ASSERT(nX >= 274); + CPPUNIT_ASSERT(nX <= 275); assertXPath(pDocument, aXPathPrefix + "mask/transform[3]/textsimpleportion", "y", u"22"); assertXPath(pDocument, aXPathPrefix + "mask/transform[3]/textsimpleportion", "text", u"HRVT"); @@ -316,13 +338,12 @@ CPPUNIT_TEST_FIXTURE(Test, testDrawStringAlign) assertXPath(pDocument, aXPathPrefix + "mask/transform[4]/textsimpleportion", "text", u"HLVC"); assertXPathDoubleValue(pDocument, aXPathPrefix + "mask/transform[5]/textsimpleportion", "x", - 143.0, 0.001); + 142.489, 0.001); assertXPath(pDocument, aXPathPrefix + "mask/transform[5]/textsimpleportion", "y", u"66"); assertXPath(pDocument, aXPathPrefix + "mask/transform[5]/textsimpleportion", "text", u"HCVC"); - // This is usually 274, but can be 273 as well; depends on what fonts are installed? nX = getXPath(pDocument, aXPathPrefix + "mask/transform[6]/textsimpleportion", "x").toInt32(); - CPPUNIT_ASSERT(nX >= 273); + CPPUNIT_ASSERT(nX >= 272); CPPUNIT_ASSERT(nX <= 274); assertXPath(pDocument, aXPathPrefix + "mask/transform[6]/textsimpleportion", "y", u"66"); assertXPath(pDocument, aXPathPrefix + "mask/transform[6]/textsimpleportion", "text", u"HRVC"); @@ -332,14 +353,13 @@ CPPUNIT_TEST_FIXTURE(Test, testDrawStringAlign) assertXPath(pDocument, aXPathPrefix + "mask/transform[7]/textsimpleportion", "text", u"HLVB"); assertXPathDoubleValue(pDocument, aXPathPrefix + "mask/transform[8]/textsimpleportion", "x", - 143.330, 0.001); + 142.830, 0.001); assertXPath(pDocument, aXPathPrefix + "mask/transform[8]/textsimpleportion", "y", u"110"); assertXPath(pDocument, aXPathPrefix + "mask/transform[8]/textsimpleportion", "text", u"HCVB"); - // This is usually 275, but can be 274 as well; depends on what fonts are installed? nX = getXPath(pDocument, aXPathPrefix + "mask/transform[9]/textsimpleportion", "x").toInt32(); - CPPUNIT_ASSERT(nX >= 274); - CPPUNIT_ASSERT(nX <= 275); + CPPUNIT_ASSERT(nX >= 273); + CPPUNIT_ASSERT(nX <= 274); assertXPath(pDocument, aXPathPrefix + "mask/transform[9]/textsimpleportion", "y", u"110"); assertXPath(pDocument, aXPathPrefix + "mask/transform[9]/textsimpleportion", "text", u"HRVB"); #endif @@ -395,6 +415,37 @@ CPPUNIT_TEST_FIXTURE(Test, testDrawStringWithBrush) u"TIMES NEW ROMAN"); } +CPPUNIT_TEST_FIXTURE(Test, testDrawStringTracking) +{ +#if HAVE_MORE_FONTS + // tdf#143056 EMF+ DrawString with StringFormat tracking != 1.0 + // (here tracking == 1.5 applied to "HLVT" rendered at em size 24 in + // Courier New). The fix populates the text primitive's DX-array with + // tracking-stretched cumulative advances so the characters spread out. + Primitive2DSequence aSequence + = parseEmf(u"/emfio/qa/cppunit/emf/data/TestDrawStringTracking.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // Three text portions ("HLVT", "HCVT", "HRVT"), each must carry a + // populated DX-array with strictly-increasing positions. + for (int i = 1; i <= 3; ++i) + { + const OString aTextPath + = aXPathPrefix + "mask/transform[" + OString::number(i) + "]/textsimpleportion"; + // dx0..dx3 must exist (4-char string, tracking != 1.0 -> non-empty DX-array) + assertXPath(pDocument, aTextPath + "[@dx0 and @dx1 and @dx2 and @dx3]"); + // For Courier New at em 24, natural advance is ~14.4; tracking 1.5 + // stretches each cumulative position by the same factor. Allow a + // generous tolerance to absorb font-substitution variance. + assertXPathDoubleValue(pDocument, aTextPath, "dx0", 21.6, 1.5); + assertXPathDoubleValue(pDocument, aTextPath, "dx3", 86.4, 6.0); + } +#endif +} + CPPUNIT_TEST_FIXTURE(Test, testEmfPlusDrawBeziers) { // tdf#107019 tdf#154789 EMF+ records: DrawBeziers @@ -623,16 +674,18 @@ CPPUNIT_TEST_FIXTURE(Test, testTextMapMode) xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); CPPUNIT_ASSERT(pDocument); - assertXPath(pDocument, aXPathPrefix + "polypolygoncolor", 2); - assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[1]", "color", u"#ffffff"); - assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[1]/polypolygon", "path", + assertXPath(pDocument, aXPathPrefix + "polypolygoncolor", 1); + assertXPath(pDocument, aXPathPrefix + "polypolygoncolor", "color", u"#ffffff"); + assertXPath(pDocument, aXPathPrefix + "polypolygoncolor/polypolygon", "path", u"m0 0h3542v4647h-3542z"); + assertXPath(pDocument, aXPathPrefix + "group[1]/mask/polypolygoncolor", 1); - assertXPath(pDocument, aXPathPrefix + "textsimpleportion", 20); - assertXPath(pDocument, aXPathPrefix + "textsimpleportion[1]", "text", u"N"); - assertXPath(pDocument, aXPathPrefix + "textsimpleportion[1]", "fontcolor", u"#4a70e3"); - assertXPath(pDocument, aXPathPrefix + "textsimpleportion[1]", "x", u"2099"); - assertXPath(pDocument, aXPathPrefix + "textsimpleportion[1]", "y", u"1859"); + assertXPath(pDocument, aXPathPrefix + "group/mask/textsimpleportion", 20); + assertXPath(pDocument, aXPathPrefix + "group[2]/mask/textsimpleportion", "text", u"N"); + assertXPath(pDocument, aXPathPrefix + "group[2]/mask/textsimpleportion", "fontcolor", + u"#4a70e3"); + assertXPath(pDocument, aXPathPrefix + "group[2]/mask/textsimpleportion", "x", u"2099"); + assertXPath(pDocument, aXPathPrefix + "group[2]/mask/textsimpleportion", "y", u"1859"); assertXPath(pDocument, aXPathPrefix + "polygonstroke", 138); assertXPathContent(pDocument, aXPathPrefix + "polygonstroke[1]/polygon", @@ -683,13 +736,16 @@ CPPUNIT_TEST_FIXTURE(Test, testEnglishMapMode) assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[1]", "width", u"424"); assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[1]", "height", u"424"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonhairline", 5); + // WINDING fill mode: fill and stroke are separated; strokes come from + // MetaPolyLineAction instead of MetaPolygonAction, one per shape. + assertXPath(pDocument, aXPathPrefix + "mask/polygonhairline", 3); assertXPathContent(pDocument, aXPathPrefix + "mask/polygonhairline[1]/polygon", u"-1,-1 29699,-1 29699,21000 -1,21000"); assertXPathContent(pDocument, aXPathPrefix + "mask/polygonhairline[2]/polygon", u"1058,7937 1058,13230 4233,13230 4233,12171 2115,12171 2115,7937"); - assertXPathContent(pDocument, aXPathPrefix + "mask/polygonhairline[3]/polygon", - u"1058,7937 1058,13230 4233,13230 4233,12171 2115,12171 2115,7937"); + assertXPathContent( + pDocument, aXPathPrefix + "mask/polygonhairline[3]/polygon", + u"12699,1058 16933,1058 16933,2118 15346,2118 15346,6349 14287,6349 14287,2118 12699,2118"); } CPPUNIT_TEST_FIXTURE(Test, testRectangleWithModifyWorldTransform) @@ -1049,12 +1105,67 @@ CPPUNIT_TEST_FIXTURE(Test, testEmfPlusBrushPathGradientWithBlendColors) xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); CPPUNIT_ASSERT(pDocument); - assertXPath(pDocument, aXPathPrefix + "svgradialgradient", "radius", u"0.7"); - assertXPath(pDocument, aXPathPrefix + "svgradialgradient/focalx", 0); - assertXPath(pDocument, aXPathPrefix + "svgradialgradient/focaly", 0); - assertXPathDoubleValue(pDocument, aXPathPrefix + "svgradialgradient", "startx", 0.5, 0.001); - assertXPathDoubleValue(pDocument, aXPathPrefix + "svgradialgradient", "starty", 0.5, 0.001); - assertXPath(pDocument, aXPathPrefix + "svgradialgradient", "spreadmethod", u"pad"); + // Path gradient brushes are rendered as a bitmap fill + // (polypolygongraphic with embedded bitmap), not an svgradialgradient. + // The bitmap is anchored to the brush bounds so for a brush whose path + // covers the fill polygon a single bitmap copy appears. + assertXPath(pDocument, aXPathPrefix + "transform/polypolygongraphic", 1); + assertXPath(pDocument, aXPathPrefix + "transform/polypolygongraphic//bitmap", 1); +} + +CPPUNIT_TEST_FIXTURE(Test, testEmfPlusBrushPathGradientMultiSurroundColor) +{ + // EMF+ PathGradient brushes can carry one surround colour per boundary + // vertex; per-triangle Gouraud shading then produces distinct colour + // at each vertex with smooth blends along the segments and toward the + // centre. The test EMF (extracted from the libUEMF v0.2.1 test file) + // contains four 5-point-star path-gradient fills: + // - two with BrushDataPath (path-based brush, 10 boundary vertices) + // - two boundary-only (no BrushDataPath, 10 raw boundary points) + // surround colours are blue/green/red/green/blue/green/red/green/ + // magenta/green and the centre is black. + // + // Validates two things from the path-gradient rewrite: + // - boundary-only brushes parse correctly via GetRawPointsPolygon() + // instead of producing a degenerate single-vertex polygon (which + // would yield no fill at all) + // - all four fills emit a polypolygongraphic with a bitmap that + // actually paints the shape (the bitmap is 256 px wide). + Primitive2DSequence aSequence + = parseEmf(u"emfio/qa/cppunit/emf/data/TestEmfPlusBrushPathGradientMultiSurroundColor.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // Each star fill produces a polypolygongraphic with a bitmap. + assertXPath(pDocument, "//polypolygongraphic", 4); + assertXPath(pDocument, "//polypolygongraphic//bitmap", 4); + // Bitmap is 256 px on its longest side (path-gradient renderer's + // nMaxDim), so the rewrite did emit non-empty pixel content for the + // boundary-only brushes too (which previously collapsed to a + // degenerate single-vertex polygon and produced no fill at all). + assertXPath(pDocument, "(//polypolygongraphic//bitmap)[1]", "width", u"256"); +} + +CPPUNIT_TEST_FIXTURE(Test, testEmfPlusBrushPathGradientTiled) +{ + // tdf#143031 EMF+ PathGradient brush with WrapMode = Tile must produce + // a tiled bitmap fill. The test file uses a single FillPath where the + // brush's gradient path is far away in coordinate space from the fill + // polygon; without tiling, only a flat boundary colour shows up. + Primitive2DSequence aSequence + = parseEmf(u"emfio/qa/cppunit/emf/data/tdf143031_BrushPathGrad.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // The brush should produce a polypolygongraphic with a tiled bitmap. + // Without the fix, an empty/flat-coloured fill primitive was emitted. + assertXPath(pDocument, aXPathPrefix + "transform/polypolygongraphic", 1); + assertXPath(pDocument, "(" + aXPathPrefix + "transform/polypolygongraphic//bitmap)[1]", "width", + u"256"); } CPPUNIT_TEST_FIXTURE(Test, testEmfPlusDrawCurve) @@ -1224,28 +1335,29 @@ CPPUNIT_TEST_FIXTURE(Test, testEmfPlusSetPageTransform) xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); CPPUNIT_ASSERT(pDocument); - assertXPath(pDocument, aXPathPrefix + "textsimpleportion", 2); - assertXPath(pDocument, aXPathPrefix + "textsimpleportion[1]", "text", + assertXPath(pDocument, aXPathPrefix + "/textsimpleportion", 2); + assertXPath(pDocument, aXPathPrefix + "group[1]/mask/textsimpleportion", "text", u"Flow Chart LM_SOP_01.04.04_02_Sonderfreigabe Lieferant_DE.igx"); - assertXPath(pDocument, aXPathPrefix + "textsimpleportion[1]", "fontcolor", u"#000000"); + assertXPath(pDocument, aXPathPrefix + "group[1]/mask/textsimpleportion", "fontcolor", + u"#000000"); - assertXPath(pDocument, aXPathPrefix + "group", 2); - - assertXPath(pDocument, aXPathPrefix + "group[1]/mask/polypolygon", 1); - assertXPath(pDocument, aXPathPrefix + "group[1]/mask/polypolygoncolor", 1); - assertXPath(pDocument, aXPathPrefix + "group[1]/mask/polypolygoncolor", "color", u"#4080c0"); - assertXPath(pDocument, aXPathPrefix + "group[1]/mask/polypolygoncolor/polypolygon", "height", - u"1620"); - assertXPath(pDocument, aXPathPrefix + "group[1]/mask/polypolygoncolor/polypolygon", "maxy", - u"1994"); + assertXPath(pDocument, aXPathPrefix + "group", 4); assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygon", 1); - assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor", 2); - assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor[1]", "color", u"#00eeee"); - assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor[1]/polypolygon", "height", + assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor", 1); + assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor", "color", u"#4080c0"); + assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor/polypolygon", "height", + u"1620"); + assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor/polypolygon", "maxy", + u"1994"); + + assertXPath(pDocument, aXPathPrefix + "group[4]/mask/polypolygon", 1); + assertXPath(pDocument, aXPathPrefix + "group[4]/mask/polypolygoncolor", 2); + assertXPath(pDocument, aXPathPrefix + "group[4]/mask/polypolygoncolor[1]", "color", u"#00eeee"); + assertXPath(pDocument, aXPathPrefix + "group[4]/mask/polypolygoncolor[1]/polypolygon", "height", u"2457"); - assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor[2]", "color", u"#ee00ee"); - assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor[2]/polypolygon", "height", + assertXPath(pDocument, aXPathPrefix + "group[4]/mask/polypolygoncolor[2]", "color", u"#ee00ee"); + assertXPath(pDocument, aXPathPrefix + "group[4]/mask/polypolygoncolor[2]/polypolygon", "height", u"2457"); } @@ -1506,20 +1618,12 @@ CPPUNIT_TEST_FIXTURE(Test, testExtTextOutScaleGM_COMPATIBLE) assertXPath(pDocument, aXPathPrefix + "textsimpleportion[3]", "text", u"24"); assertXPath(pDocument, aXPathPrefix + "textsimpleportion[3]", "fontcolor", u"#000000"); -#ifndef _WIN32 //FIXME assertXPath(pDocument, aXPathPrefix + "textsimpleportion[3]", "width", u"201"); -#else - assertXPathDoubleValue(pDocument, aXPathPrefix + "textsimpleportion[3]", "width", 199.0, 1.0); -#endif assertXPath(pDocument, aXPathPrefix + "textsimpleportion[3]", "height", u"317"); assertXPath(pDocument, aXPathPrefix + "textsimpleportion[4]", "text", u"25"); assertXPath(pDocument, aXPathPrefix + "textsimpleportion[4]", "fontcolor", u"#000000"); -#ifndef _WIN32 //FIXME assertXPath(pDocument, aXPathPrefix + "textsimpleportion[4]", "width", u"268"); -#else - assertXPathDoubleValue(pDocument, aXPathPrefix + "textsimpleportion[4]", "width", 267.0, 1.0); -#endif assertXPath(pDocument, aXPathPrefix + "textsimpleportion[4]", "height", u"317"); assertXPath(pDocument, aXPathPrefix + "polygonstroke", 9); @@ -1842,6 +1946,27 @@ CPPUNIT_TEST_FIXTURE(Test, testRoundRect) assertXPath(pDocument, aXPathPrefix + "polygonstroke[2]/line", "color", u"#ff0000"); } +CPPUNIT_TEST_FIXTURE(Test, testExtSelectClipRgnCopy) +{ + // EMR_EXTSELECTCLIPRGN with iMode = RGN_COPY (5) and a non-empty + // RegionData must replace the clip with the given region. The test + // file draws a (0,0)-(200,200) rectangle but first sets the clip to + // (50,50)-(150,150); the imported metafile must therefore wrap the + // rectangle in a clip-region mask matching the requested rectangle. + Primitive2DSequence aSequence + = parseEmf(u"/emfio/qa/cppunit/emf/data/TestExtSelectClipRgnCopy.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygon", 1); + assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygon", "minx", u"1600"); + assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygon", "miny", u"1600"); + assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygon", "maxx", u"4800"); + assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygon", "maxy", u"4800"); +} + CPPUNIT_TEST_FIXTURE(Test, testCreatePen) { // Check import of EMF image with records: RESTOREDC, SAVEDC, MOVETOEX, LINETO, POLYLINE16, EXTTEXTOUTW with DxBuffer @@ -1854,7 +1979,7 @@ CPPUNIT_TEST_FIXTURE(Test, testCreatePen) assertXPath(pDocument, aXPathPrefix + "mask/polypolygon", "path", u"m0 0h31250v18192h-31250z"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke", 748); + assertXPath(pDocument, aXPathPrefix + "mask//polygonstroke", 748); assertXPathContent(pDocument, aXPathPrefix + "mask/polygonstroke[1]/polygon", u"27875,16523 27875,1453"); assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke[1]/line", "color", u"#ff0000"); @@ -1870,9 +1995,9 @@ CPPUNIT_TEST_FIXTURE(Test, testCreatePen) assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke[3]/line", "color", u"#ff0000"); assertXPath(pDocument, aXPathPrefix + "mask/polygonstroke[3]/line", "width", u"6"); - assertXPath(pDocument, aXPathPrefix + "mask/polygonhairline", 10); + assertXPath(pDocument, aXPathPrefix + "mask//polygonhairline", 10); - assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion", 69); + assertXPath(pDocument, aXPathPrefix + "mask//textsimpleportion", 69); assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[1]", "height", u"374"); #ifndef _WIN32 // FIXME assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[1]", "width", u"310"); @@ -1893,12 +2018,38 @@ CPPUNIT_TEST_FIXTURE(Test, testCreatePen) assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[10]", "text", u"-6"); assertXPath(pDocument, aXPathPrefix + "mask/textsimpleportion[10]", "fontcolor", u"#000000"); - assertXPath(pDocument, aXPathPrefix + "mask/pointarray", 8); - assertXPath(pDocument, aXPathPrefix + "mask/pointarray[1]", "color", u"#008000"); - assertXPath(pDocument, aXPathPrefix + "mask/pointarray[1]/point", "x", u"25844"); - assertXPath(pDocument, aXPathPrefix + "mask/pointarray[1]/point", "y", u"8918"); + assertXPath(pDocument, aXPathPrefix + "mask//pointarray", 8); + assertXPath(pDocument, aXPathPrefix + "mask//pointarray[1]", "color", u"#008000"); + assertXPath(pDocument, aXPathPrefix + "mask//pointarray[1]/point", "x", u"25844"); + assertXPath(pDocument, aXPathPrefix + "mask//pointarray[1]/point", "y", u"8918"); } +#if !defined(MACOSX) +CPPUNIT_TEST_FIXTURE(Test, testPdfInEmfVersion0) +{ + // tdf#167641 EMF with EMR_COMMENT_MULTIFORMATS carrying a PDF, where the + // EmrFormat.Version field is 0 (as written by current MS Office) and the + // OutputRect is empty (0,0,0,0). [MS-EMF] 2.3.3.4.2 says Version must be + // ignored unless Signature == EPS_SIGNATURE; an empty OutputRect must fall + // back to the EMF's logical bounds. Without the fix, the embedded PDF was + // not rendered at all. + if (!vcl::pdf::PDFiumLibrary::get()) + { + return; + } + + Primitive2DSequence aSequence + = parseEmf(u"/emfio/qa/cppunit/emf/data/TestPdfInEmfVersion0.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // Without the fix the metafile was empty (no bitmap was drawn). + assertXPath(pDocument, "//bitmap"_ostr, 1); +} +#endif + CPPUNIT_TEST_FIXTURE(Test, testPdfInEmf) { if (!vcl::pdf::PDFiumLibrary::get()) @@ -1984,6 +2135,104 @@ CPPUNIT_TEST_FIXTURE(Test, testSmallTextOutAnsi) assertXPathContent(pDoc, "/metafile/push[2]/textarray/text", u"AnsiSmall"); } +CPPUNIT_TEST_FIXTURE(Test, testExcludeClipRect) +{ + // EMR_EXCLUDECLIPRECT punches a hole in the clip region. + // The EMF sets clip to (0,0)-(1000,1000), then excludes (200,200)-(800,800), + // then fills the whole area with red — only the frame outside the hole is visible. + Primitive2DSequence aSequence = parseEmf(u"/emfio/qa/cppunit/emf/data/TestExcludeClipRect.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // The clip mask polypolygon has two sub-polygons: the excluded inner rect + // and the outer clip rect, forming a frame-shaped clip region. + assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygon", "path", + u"m1323 1319v2613h2619v-2613zm-1323-1319h5265v5251h-5265z"); + + // The red fill covers the whole area, but is clipped by the mask above. + assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygoncolor", "color", u"#ff0000"); +} + +CPPUNIT_TEST_FIXTURE(Test, testEmfPlusFillClosedCurveWinding) +{ + // EMF+ EmfPlusFillClosedCurve record with the Winding flag (0x2000) set, + // tracing a self-intersecting pentagram (5 vertices in every-other-corner + // order, tension 0). With WINDING the inner pentagon is part of the fill; + // with ALTERNATE it would be a hole. The geometry is converted at parse + // time so even-odd rendering of the resulting polypolygon fills the + // entire star including the centre. + Primitive2DSequence aSequence + = parseEmf(u"/emfio/qa/cppunit/emf/data/TestEmfPlusFillClosedCurveWinding.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // Single fill primitive in red, with the self-intersecting input + // collapsed to one polygon (the outer boundary of the filled star). + assertXPath(pDocument, aXPathPrefix + "polypolygoncolor", "color", u"#ff0000"); + assertXPath(pDocument, aXPathPrefix + "polypolygoncolor/polypolygon/polygon", 1); +} + +CPPUNIT_TEST_FIXTURE(Test, testPolyFillModeWinding) +{ + // EMR_SETPOLYFILLMODE sets WINDING mode, then draws a self-intersecting + // pentagram (5-pointed star) filled with red. With WINDING the entire + // star including the center is filled; with ALTERNATE the center pentagon + // would be a hole. The geometry is converted by CreateWindingFillPolyPolygon() + // so that even-odd rendering fills the star completely. + Primitive2DSequence aSequence + = parseEmf(u"/emfio/qa/cppunit/emf/data/TestPolyFillModeWinding.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // The pentagram is filled with red. The self-intersecting polygon is + // resolved into a non-self-intersecting outer boundary via union of + // sub-regions, so even-odd fill covers the entire star including the center. + assertXPath(pDocument, aXPathPrefix + "polypolygoncolor", "color", u"#ff0000"); + assertXPath(pDocument, aXPathPrefix + "polypolygoncolor/polypolygon/polygon", 1); + + // The stroke preserves the original 5-vertex star shape. + assertXPath(pDocument, aXPathPrefix + "polygonhairline", 1); + assertXPathContent(pDocument, aXPathPrefix + "polygonhairline/polygon", + u"2646,264 4048,4565 370,1900 4921,1900 1244,4565"); +} + +CPPUNIT_TEST_FIXTURE(Test, testHatchedBrush) +{ + // EMR_CREATEBRUSHINDIRECT with BS_HATCHED (HS_DIAGCROSS, red hatch color) + // draws a hatched rectangle. The MetaHatchAction should produce a + // mask primitive wrapping a FillHatchPrimitive2D in the drawinglayer output. + Primitive2DSequence aSequence = parseEmf(u"/emfio/qa/cppunit/emf/data/TestHatchedBrush.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // The polygon is filled (polypolygoncolor from the background fill) + // and a mask primitive should be present for the hatch pattern. + assertXPath(pDocument, aXPathPrefix + "mask", 1); +} + +CPPUNIT_TEST_FIXTURE(Test, testHatchedPen) +{ + // EMR_EXTCREATEPEN with BS_HATCHED (HS_DIAGCROSS, red, width 300) + // draws a polyline with a wide hatched pen. The ImplEmitLineHatch + // path should produce a mask primitive for the stroke area hatch. + Primitive2DSequence aSequence = parseEmf(u"/emfio/qa/cppunit/emf/data/TestHatchedPen.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + // The hatched pen stroke area should produce a mask primitive. + assertXPath(pDocument, aXPathPrefix + "mask", 1); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/emfio/qa/cppunit/emf/data/TestDrawStringTracking.emf b/emfio/qa/cppunit/emf/data/TestDrawStringTracking.emf new file mode 100644 index 000000000000..636c4da02a07 Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestDrawStringTracking.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestEmfPlusBrushPathGradientMultiSurroundColor.emf b/emfio/qa/cppunit/emf/data/TestEmfPlusBrushPathGradientMultiSurroundColor.emf new file mode 100644 index 000000000000..ba174817043c Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestEmfPlusBrushPathGradientMultiSurroundColor.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestEmfPlusFillClosedCurveWinding.emf b/emfio/qa/cppunit/emf/data/TestEmfPlusFillClosedCurveWinding.emf new file mode 100644 index 000000000000..d2255e89f114 Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestEmfPlusFillClosedCurveWinding.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestEmfPlusFillRectsOverlap.emf b/emfio/qa/cppunit/emf/data/TestEmfPlusFillRectsOverlap.emf new file mode 100644 index 000000000000..2f3e6eacd6fe Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestEmfPlusFillRectsOverlap.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestExcludeClipRect.emf b/emfio/qa/cppunit/emf/data/TestExcludeClipRect.emf new file mode 100644 index 000000000000..d8c3c491f55f Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestExcludeClipRect.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestExtSelectClipRgnCopy.emf b/emfio/qa/cppunit/emf/data/TestExtSelectClipRgnCopy.emf new file mode 100644 index 000000000000..793c9b6f0b95 Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestExtSelectClipRgnCopy.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestHatchedBrush.emf b/emfio/qa/cppunit/emf/data/TestHatchedBrush.emf new file mode 100644 index 000000000000..4c4a5abee012 Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestHatchedBrush.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestHatchedPen.emf b/emfio/qa/cppunit/emf/data/TestHatchedPen.emf new file mode 100644 index 000000000000..3358cf2cb0a9 Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestHatchedPen.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestPdfInEmfVersion0.emf b/emfio/qa/cppunit/emf/data/TestPdfInEmfVersion0.emf new file mode 100644 index 000000000000..b025f9f6b690 Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestPdfInEmfVersion0.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestPolyFillModeWinding.emf b/emfio/qa/cppunit/emf/data/TestPolyFillModeWinding.emf new file mode 100644 index 000000000000..aeb45b6a917f Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestPolyFillModeWinding.emf differ diff --git a/emfio/qa/cppunit/emf/data/tdf143031_BrushPathGrad.emf b/emfio/qa/cppunit/emf/data/tdf143031_BrushPathGrad.emf new file mode 100644 index 000000000000..d7ffebd9b48a Binary files /dev/null and b/emfio/qa/cppunit/emf/data/tdf143031_BrushPathGrad.emf differ diff --git a/emfio/qa/cppunit/wmf/data/TestHatchBkMode.wmf b/emfio/qa/cppunit/wmf/data/TestHatchBkMode.wmf new file mode 100644 index 000000000000..8ff2c9f8a80f Binary files /dev/null and b/emfio/qa/cppunit/wmf/data/TestHatchBkMode.wmf differ diff --git a/emfio/qa/cppunit/wmf/data/TestPatternBrush.wmf b/emfio/qa/cppunit/wmf/data/TestPatternBrush.wmf new file mode 100644 index 000000000000..9a4d29889c14 Binary files /dev/null and b/emfio/qa/cppunit/wmf/data/TestPatternBrush.wmf differ diff --git a/emfio/qa/cppunit/wmf/data/TestPatternBrushEllipse.wmf b/emfio/qa/cppunit/wmf/data/TestPatternBrushEllipse.wmf new file mode 100644 index 000000000000..f7456a501ed1 Binary files /dev/null and b/emfio/qa/cppunit/wmf/data/TestPatternBrushEllipse.wmf differ diff --git a/emfio/qa/cppunit/wmf/wmfimporttest.cxx b/emfio/qa/cppunit/wmf/wmfimporttest.cxx index c44fc7d363ff..bdf192a07b93 100644 --- a/emfio/qa/cppunit/wmf/wmfimporttest.cxx +++ b/emfio/qa/cppunit/wmf/wmfimporttest.cxx @@ -63,6 +63,9 @@ public: void testETO_PDYWmf(); void testETO_PDYEmf(); void testStockObject(); + void testPatternBrushWmf(); + void testPatternBrushEllipseWmf(); + void testHatchBkModeWmf(); CPPUNIT_TEST_SUITE(WmfTest); CPPUNIT_TEST(testEOFWmf); @@ -82,6 +85,9 @@ public: CPPUNIT_TEST(testETO_PDYWmf); CPPUNIT_TEST(testETO_PDYEmf); CPPUNIT_TEST(testStockObject); + CPPUNIT_TEST(testPatternBrushWmf); + CPPUNIT_TEST(testPatternBrushEllipseWmf); + CPPUNIT_TEST(testHatchBkModeWmf); CPPUNIT_TEST_SUITE_END(); }; @@ -310,7 +316,7 @@ void WmfTest::testSine() CPPUNIT_ASSERT(pDoc); - assertXPath(pDoc, "/metafile/sectrectclipregion", 0); + assertXPath(pDoc, "/metafile/sectrectclipregion", 2); } void WmfTest::testEmfProblem() @@ -572,6 +578,62 @@ void WmfTest::testStockObject() assertXPath(pDoc, "/metafile/push[2]/fillcolor[2]", "color", u"#000000"); } +void WmfTest::testPatternBrushWmf() +{ + // META_DIBCREATEPATTERNBRUSH must produce a tiled bitmap fill, + // not an averaged solid color (and not no fill at all). + SvFileStream aFileStream(getFullUrl(u"TestPatternBrush.wmf"), StreamMode::READ); + GDIMetaFile aGDIMetaFile; + ReadWindowMetafile(aFileStream, aGDIMetaFile); + + xmlDocUniquePtr pDoc = dumpAndParse(aGDIMetaFile); + CPPUNIT_ASSERT(pDoc); + + // The fill emits a clip-region wrapped tiled wallpaper of the 8x8 DIB. + assertXPath(pDoc, "//wallpaper/wallpaper", "style", u"Tile"); + assertXPath(pDoc, "//wallpaper/wallpaper/bitmap", "width", u"00000008"); + assertXPath(pDoc, "//wallpaper/wallpaper/bitmap", "height", u"00000008"); +} + +void WmfTest::testPatternBrushEllipseWmf() +{ + // META_ELLIPSE drawn with a DIB pattern brush must produce a tiled + // bitmap fill, not a hollow ellipse. Same wallpaper sequence as + // testPatternBrushWmf, but exercising a non-rectangular shape. + SvFileStream aFileStream(getFullUrl(u"TestPatternBrushEllipse.wmf"), StreamMode::READ); + GDIMetaFile aGDIMetaFile; + ReadWindowMetafile(aFileStream, aGDIMetaFile); + + xmlDocUniquePtr pDoc = dumpAndParse(aGDIMetaFile); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//wallpaper/wallpaper", "style", u"Tile"); + assertXPath(pDoc, "//wallpaper/wallpaper/bitmap", "width", u"00000008"); + assertXPath(pDoc, "//wallpaper/wallpaper/bitmap", "height", u"00000008"); +} + +void WmfTest::testHatchBkModeWmf() +{ + // META_SETBKMODE between two rectangles drawn with the same hatched + // brush must trigger a fresh MetaFillColorAction. Otherwise the gap + // fill color from the previous OPAQUE rectangle leaks into the + // subsequent TRANSPARENT one. + SvFileStream aFileStream(getFullUrl(u"TestHatchBkMode.wmf"), StreamMode::READ); + GDIMetaFile aGDIMetaFile; + ReadWindowMetafile(aFileStream, aGDIMetaFile); + + xmlDocUniquePtr pDoc = dumpAndParse(aGDIMetaFile); + CPPUNIT_ASSERT(pDoc); + + // BkColor is red. Under OPAQUE the hatch background is filled with + // it; under TRANSPARENT it must be replaced with #000000 (unset). + // Without the fix UpdateFillStyle short-circuits and the second + // rectangle inherits the previous OPAQUE fillcolor, leaving the + // metafile with only one red fillcolor and no later transparent one. + assertXPath(pDoc, "//fillcolor[@color='#ff0000']", 1); + assertXPath(pDoc, "//fillcolor[@color='#000000']", 1); +} + CPPUNIT_TEST_SUITE_REGISTRATION(WmfTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx index 4f4f7ff93c9d..6289dac4fd9d 100644 --- a/emfio/source/reader/emfreader.cxx +++ b/emfio/source/reader/emfreader.cxx @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -164,7 +166,7 @@ #define EMR_SETICMPROFILEA 112 #define EMR_SETICMPROFILEW 113 #define EMR_ALPHABLEND 114 -#define EMR_ALPHADIBBLEND 115 +#define EMR_SETLAYOUT 115 #define EMR_TRANSPARENTBLT 116 #define EMR_TRANSPARENTDIB 117 #define EMR_GRADIENTFILL 118 @@ -311,7 +313,7 @@ record_type_name(sal_uInt32 nRecType) case EMR_SETICMPROFILEA: return "SETICMPROFILEA"; case EMR_SETICMPROFILEW: return "SETICMPROFILEW"; case EMR_ALPHABLEND: return "ALPHABLEND"; - case EMR_ALPHADIBBLEND: return "ALPHADIBBLEND"; + case EMR_SETLAYOUT: return "SETLAYOUT"; case EMR_TRANSPARENTBLT: return "TRANSPARENTBLT"; case EMR_TRANSPARENTDIB: return "TRANSPARENTDIB"; case EMR_GRADIENTFILL: return "GRADIENTFILL"; @@ -421,7 +423,7 @@ namespace emfio const sal_uInt32 EMR_COMMENT_MULTIFORMATS = 0x40000004; const sal_uInt32 EMR_COMMENT_WINDOWS_METAFILE = 0x80000001; - void EmfReader::ReadGDIComment(sal_uInt32 nCommentId) + void EmfReader::ReadGDIComment(sal_uInt32 nCommentId, sal_uInt64 nNextPos) { sal_uInt32 nPublicCommentIdentifier(0); mpInputStream->ReadUInt32(nPublicCommentIdentifier); @@ -458,7 +460,7 @@ namespace emfio break; case EMR_COMMENT_MULTIFORMATS: - ReadMultiformatsComment(); + ReadMultiformatsComment(nNextPos); break; case EMR_COMMENT_WINDOWS_METAFILE: @@ -471,10 +473,18 @@ namespace emfio } } - void EmfReader::ReadMultiformatsComment() + void EmfReader::ReadMultiformatsComment(sal_uInt64 nNextPos) { tools::Rectangle aOutputRect = EmfReader::ReadRectangle(); + // [MS-EMF] 2.3.3.4.3 EMR_COMMENT_MULTIFORMATS: OutputRect is in logical + // coordinates. MS Office sometimes writes (0,0,0,0); fall back to the + // EMF's logical bounds so the embedded PDF actually gets drawn. + if (aOutputRect.GetWidth() <= 1 && aOutputRect.GetHeight() <= 1) + { + aOutputRect = mrclBounds; + } + sal_uInt32 nCountFormats(0); mpInputStream->ReadUInt32(nCountFormats); if (nCountFormats < 1) @@ -490,16 +500,23 @@ namespace emfio return; } - sal_uInt32 nVersion(0); - mpInputStream->ReadUInt32(nVersion); - if (nVersion != 1) - { - return; - } + // [MS-EMF] 2.3.3.4.2 EmrFormat: Version MUST be 0x00000001 only when + // Signature == EPS_SIGNATURE; for any other signature it MUST be ignored. + // MS Office writes Version=0 with Signature="PDF "; older code rejected that. + // Skip the Version field without reading it, since its value is irrelevant here. + mpInputStream->SeekRel(sizeof(sal_uInt32)); + + // The embedded data lives inside this comment record, so the record says how much of it + // there can be. + const sal_uInt64 nRecordEnd = std::min(nNextPos, mnEndPos); + const sal_uInt64 nDataLeft = mpInputStream->Tell() < nRecordEnd + ? std::min(nRecordEnd - mpInputStream->Tell(), + mpInputStream->remainingSize()) + : 0; sal_uInt32 nSizeData(0); mpInputStream->ReadUInt32(nSizeData); - if (!nSizeData || nSizeData > mpInputStream->remainingSize()) + if (!nSizeData || nSizeData > nDataLeft) { return; } @@ -527,12 +544,6 @@ namespace emfio return; } - // aGraphic will be the only output of the EMF parser, so its size hint can be the same as - // ours. - aGraphic.getVectorGraphicData()->setSizeHint(maSizeHint); - - maBmpSaveList.emplace_back( - aGraphic.GetBitmap(), aOutputRect, SRCCOPY, /*bForceAlpha=*/true); const std::shared_ptr pVectorGraphicData = aGraphic.getVectorGraphicData(); if (!pVectorGraphicData) @@ -540,6 +551,13 @@ namespace emfio return; } + // aGraphic will be the only output of the EMF parser, so its size hint can be the same as + // ours. + pVectorGraphicData->setSizeHint(maSizeHint); + + maBmpSaveList.emplace_back( + aGraphic.GetBitmap(), aOutputRect, SRCCOPY, /*bForceAlpha=*/true); + if (pVectorGraphicData->getType() != VectorGraphicDataType::Pdf) { return; @@ -671,7 +689,17 @@ namespace emfio if (!bRecordOk || !nPoints) return tools::Polygon(); - auto nRemainingSize = std::min(nNextPos - mpInputStream->Tell(), mpInputStream->remainingSize()); + // The header fields are read before this point, so a record that is shorter than those + // fields leaves the stream past the end of its own data and holds no points at all. + const sal_uInt64 nEndPos = std::min(nNextPos, mnEndPos); + if (mpInputStream->Tell() >= nEndPos) + { + SAL_WARN("emfio", "polygon record ends before its points begin"); + return tools::Polygon(); + } + + const sal_uInt64 nRemainingSize + = std::min(nEndPos - mpInputStream->Tell(), mpInputStream->remainingSize()); auto nMaxPossiblePoints = nRemainingSize / (sizeof(T) * 2); auto nPointCount = nPoints - nStartIndex; if (nPointCount > nMaxPossiblePoints) @@ -796,6 +824,14 @@ namespace emfio for (sal_uInt32 i = 0; i < nPoly && mpInputStream->good(); ++i) { const sal_uInt32 nPointCount(aPoints[i]); + auto nRemainingSize = nEndPos - mpInputStream->Tell(); + if (nPointCount > nRemainingSize / (sizeof(T) * 2)) + { + SAL_WARN("emfio", "polygon " << i << " claims " << nPointCount + << " points but only " << nRemainingSize / (sizeof(T) * 2) + << " fit in remaining stream"); + return; + } std::vector aPtAry(nPointCount); for (sal_uInt32 j = 0; j < nPointCount && mpInputStream->good(); ++j) { @@ -884,7 +920,10 @@ namespace emfio SAL_INFO("emfio", "\tGDI comment, length: " << length); - if( mpInputStream->good() && length >= 4 && length <= mpInputStream->remainingSize() ) { + // DataSize counts the bytes that follow it inside this record, so the record size + // minus its own 8 byte header and the 4 byte DataSize field is the most it can be. + if( mpInputStream->good() && length >= 4 && nRecSize >= 12 + && length <= nRecSize - 12 && length <= mpInputStream->remainingSize() ) { sal_uInt32 nCommentId; mpInputStream->ReadUInt32( nCommentId ); @@ -899,7 +938,7 @@ namespace emfio } else if( nCommentId == EMR_COMMENT_PUBLIC && nRecSize >= 12 ) { - ReadGDIComment(nCommentId); + ReadGDIComment(nCommentId, nNextPos); } else if( nCommentId == EMR_COMMENT_EMFSPOOL && nRecSize >= 12 ) { @@ -1130,7 +1169,25 @@ namespace emfio } break; + case EMR_SETLAYOUT : + { + // [MS-EMF] 2.3.11.23 — LayoutMode flags: + // LAYOUT_LTR 0x00000000 + // LAYOUT_RTL 0x00000001 + // LAYOUT_BITMAPORIENTATIONPRESERVED 0x00000008 + sal_uInt32 nLayoutMode(0); + mpInputStream->ReadUInt32( nLayoutMode ); + if ( nLayoutMode != 0 ) + SAL_WARN("emfio", "\t\tEMR_SETLAYOUT: unhandled LayoutMode 0x" << std::hex << nLayoutMode << std::dec); + } + break; + case EMR_SETPOLYFILLMODE : + { + mpInputStream->ReadUInt32( nDat32 ); + SAL_INFO("emfio", "\t\tPolyFillMode: 0x" << std::hex << nDat32 << std::dec); + SetPolyFillMode( nDat32 ); + } break; case EMR_SETROP2 : @@ -1191,6 +1248,15 @@ namespace emfio } break; + case EMR_EXCLUDECLIPRECT : + { + mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ); + ExcludeClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) ); + SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")"); + SAL_INFO("emfio", "\t\tPoint: (" << nx32 << ", " << ny32 << ")"); + } + break; + case EMR_INTERSECTCLIPRECT : { mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ); @@ -1281,7 +1347,25 @@ namespace emfio if ((nPenStyle & PS_STYLE_MASK) > PS_INSIDEFRAME) nPenStyle = PS_COSMETIC; SAL_INFO("emfio", "\t\tWidth: " << nWidth); - CreateObjectIndexed(nIndex, std::make_unique(aColorRef, nPenStyle, nWidth)); + + // [MS-EMF] 2.2.20: when elpBrushStyle is BS_HATCHED, + // elpHatch specifies the hatch pattern or color alias. + BrushStyle ePenBrush = static_cast(nBrushStyle); + if (ePenBrush == BrushStyle::BS_HATCHED) + { + if (elpHatch == 8 || elpHatch == 9) // HS_SOLIDTEXTCLR / HS_DITHEREDTEXTCLR + aColorRef = maTextColor; + else if (elpHatch == 10 || elpHatch == 11) // HS_SOLIDBKCLR / HS_DITHEREDBKCLR + aColorRef = maBkColor; + // 0-7: keep aColorRef (brush/hatch color) + } + auto pLineStyle = std::make_unique(aColorRef, nPenStyle, nWidth); + if (ePenBrush == BrushStyle::BS_HATCHED && elpHatch >= 0 && elpHatch <= 5) + { + pLineStyle->bHasHatch = true; + pLineStyle->aHatch = mapWindowsHatch(elpHatch, aColorRef); + } + CreateObjectIndexed(nIndex, std::move(pLineStyle)); } } } @@ -1292,10 +1376,31 @@ namespace emfio mpInputStream->ReadUInt32( nIndex ); if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 ) { - sal_uInt32 nStyle; + sal_uInt32 nStyle(0); mpInputStream->ReadUInt32( nStyle ); BrushStyle eStyle = static_cast(nStyle); - CreateObjectIndexed(nIndex, std::make_unique( ReadColor(), ( eStyle == BrushStyle::BS_HOLLOW ) )); + Color aColor = ReadColor(); + sal_Int32 nHatch(0); + mpInputStream->ReadInt32( nHatch ); + if (eStyle == BrushStyle::BS_HATCHED && nHatch >= 0 && nHatch <= 5) + CreateObjectIndexed(nIndex, std::make_unique( aColor, mapWindowsHatch(nHatch, aColor) )); + else if (eStyle == BrushStyle::BS_HATCHED && (nHatch == 6 || nHatch == 7)) + { + // [MS-EMF] 2.1.17 HS_SOLIDCLR / HS_DITHEREDCLR: brush color + CreateObjectIndexed(nIndex, std::make_unique( aColor )); + } + else if (eStyle == BrushStyle::BS_HATCHED && (nHatch == 8 || nHatch == 9)) + { + // [MS-EMF] 2.1.17 HS_SOLIDTEXTCLR / HS_DITHEREDTEXTCLR: text color + CreateObjectIndexed(nIndex, std::make_unique( maTextColor )); + } + else if (eStyle == BrushStyle::BS_HATCHED && (nHatch == 10 || nHatch == 11)) + { + // [MS-EMF] 2.1.17 HS_SOLIDBKCLR / HS_DITHEREDBKCLR: background color + CreateObjectIndexed(nIndex, std::make_unique( maBkColor )); + } + else + CreateObjectIndexed(nIndex, std::make_unique( aColor, eStyle == BrushStyle::BS_HOLLOW )); } } break; @@ -1478,17 +1583,23 @@ namespace emfio mpInputStream->ReadUInt32(nClippingMode); nRemainingRecSize -= 8; - // This record's region data should be ignored if mode - // is RGN_COPY - see EMF spec section 2.3.2.2 - if (static_cast(nClippingMode) == RegionMode::RGN_COPY) + // [MS-EMF] 2.3.2.2 says RegionData "MUST be ignored" + // when iMode is RGN_COPY, but real EMFs (and MS Word) + // treat it like the Win32 ExtSelectClipRgn API: a + // non-NULL region with RGN_COPY replaces the clip, + // and a NULL region (cbRgnData == 0) with RGN_COPY + // resets the clip to the default null region. + basegfx::B2DPolyPolygon aPolyPoly; + if (cbRgnDataSize) + ImplReadRegion(aPolyPoly, *mpInputStream, nRemainingRecSize, GetWinOrg()); + + if (!cbRgnDataSize) { - SetDefaultClipPath(); + if (static_cast(nClippingMode) == RegionMode::RGN_COPY) + SetDefaultClipPath(); } else { - basegfx::B2DPolyPolygon aPolyPoly; - if (cbRgnDataSize) - ImplReadRegion(aPolyPoly, *mpInputStream, nRemainingRecSize, GetWinOrg()); const tools::PolyPolygon aPolyPolygon(aPolyPoly); SetClipPath(aPolyPolygon, static_cast(nClippingMode), false); } @@ -2000,104 +2111,169 @@ namespace emfio if ( nOptions & ETO_RTLREADING ) nTextLayoutMode = vcl::text::ComplexTextLayoutFlags::BiDiRtl | vcl::text::ComplexTextLayoutFlags::TextOriginLeft; SetTextLayoutMode( nTextLayoutMode ); - SAL_WARN_IF( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) != 0, "emfio", "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" ); Point aPos( ptlReferenceX, ptlReferenceY ); bool bOffStringSane = nOffString <= nNextPos - nCurPos; if ( bOffStringSane ) { - mpInputStream->Seek( nCurPos + nOffString ); - OUString aText; - if ( bFlag ) + // ETO_GLYPH_INDEX: string data contains pre-shaped glyph indices, + // not Unicode codepoints. Render as polypolygon outlines to bypass + // text shaping (tdf#168107). Falls back to text path if the + // required font is not available. + bool bGlyphsDone = false; + if ( (nOptions & ETO_GLYPH_INDEX) && !bFlag ) { - if ( nLen <= ( nNextPos - mpInputStream->Tell() ) ) + mpInputStream->Seek( nCurPos + nOffString ); + std::vector aGlyphIds; + if ( ( nLen * sizeof(sal_uInt16) ) <= ( nNextPos - mpInputStream->Tell() ) ) { - std::vector pBuf( nLen ); - mpInputStream->ReadBytes(pBuf.data(), nLen); - aText = OUString(pBuf.data(), nLen, GetCharSet()); - } - } - else - { - if ( ( nLen * sizeof(sal_Unicode) ) <= ( nNextPos - mpInputStream->Tell() ) ) - { - aText = read_uInt16s_ToOUString(*mpInputStream, nLen); - } - } - - SAL_INFO("emfio", "\t\tText: " << aText); - SAL_INFO("emfio", "\t\tDxBuffer:"); - - KernArray aDXAry; - std::unique_ptr pDYAry; - - sal_Int32 nDxSize; - sal_Int32 nBytesEach; - - // Reading OutputDx - // ETO_PDY flag indicates that we should read twice values - // compared to the number of characters in the output string. - // Values are stored in an array of 32-bit unsigned integers - // named OutputDx, so there will be either 8 bytes or 4 bytes - // each depending on ETO_PDY is set or not. - if (nOptions & ETO_PDY) - nBytesEach = 8; - else - nBytesEach = 4; - - bool bOverflow = o3tl::checked_multiply(nLen, nBytesEach, nDxSize); - if (!bOverflow && offDx && ((nCurPos + offDx + nDxSize) <= nNextPos ) && nNextPos <= mnEndPos) - { - mpInputStream->Seek( nCurPos + offDx ); - aDXAry.resize(aText.getLength()); - if (nOptions & ETO_PDY) - { - pDYAry.reset( new tools::Long[aText.getLength()] ); - } - - for (sal_Int32 i = 0; i < aText.getLength(); ++i) - { - sal_Int32 nDxCount = 1; - if ( static_cast( aText.getLength() ) != nLen ) + aGlyphIds.resize(nLen); + for (sal_uInt32 i = 0; i < nLen; ++i) { - sal_Unicode cUniChar = aText[i]; - OString aTmp(&cUniChar, 1, GetCharSet()); - if (aTmp.getLength() > 1) - { - nDxCount = aTmp.getLength(); - } + sal_uInt16 nGlyphId = 0; + mpInputStream->ReadUInt16(nGlyphId); + aGlyphIds[i] = nGlyphId; } + } - aDXAry[i] = 0; + SAL_INFO("emfio", "\t\tGlyph indices: " << nLen << " glyphs"); + SAL_INFO("emfio", "\t\tDxBuffer:"); + + KernArray aDXAry; + std::unique_ptr pDYAry; + + sal_Int32 nDxSize; + sal_Int32 nBytesEach = (nOptions & ETO_PDY) ? 8 : 4; + + bool bOverflow = o3tl::checked_multiply(nLen, nBytesEach, nDxSize); + if (!bOverflow && offDx && ((nCurPos + offDx + nDxSize) <= nNextPos ) && nNextPos <= mnEndPos) + { + mpInputStream->Seek( nCurPos + offDx ); + sal_Int32 nGlyphs = static_cast(aGlyphIds.size()); + aDXAry.resize(nGlyphs); if (nOptions & ETO_PDY) - { - pDYAry[i] = 0; - } + pDYAry.reset( new tools::Long[nGlyphs] ); - while (nDxCount--) + for (sal_Int32 i = 0; i < nGlyphs; ++i) { sal_Int32 nDxTmp = 0; mpInputStream->ReadInt32(nDxTmp); - aDXAry[i] += nDxTmp; + aDXAry[i] = nDxTmp; if (nOptions & ETO_PDY) { sal_Int32 nDyTmp = 0; mpInputStream->ReadInt32(nDyTmp); - pDYAry[i] += nDyTmp; + pDYAry[i] = nDyTmp; } + SAL_INFO("emfio", "\t\t\tSpacing " << i << ": " << aDXAry[i]); + } + } + if ( nOptions & ETO_CLIPPED ) + { + Push(); + IntersectClipRect( aRect ); + } + // DrawGlyphs returns false if the font is not available + bGlyphsDone = DrawGlyphs(aPos, aGlyphIds, aDXAry.empty() ? nullptr : &aDXAry, pDYAry.get(), fXScale, fYScale, mbRecordPath, static_cast(nGfxMode)); + if ( nOptions & ETO_CLIPPED ) + Pop(); + } + if ( !bGlyphsDone ) + { + // Standard text path: read Unicode or ANSI text + mpInputStream->Seek( nCurPos + nOffString ); + OUString aText; + if ( bFlag ) + { + if ( nLen <= ( nNextPos - mpInputStream->Tell() ) ) + { + std::vector pBuf( nLen ); + mpInputStream->ReadBytes(pBuf.data(), nLen); + aText = OUString(pBuf.data(), nLen, GetCharSet()); + } + } + else + { + if ( ( nLen * sizeof(sal_Unicode) ) <= ( nNextPos - mpInputStream->Tell() ) ) + { + aText = read_uInt16s_ToOUString(*mpInputStream, nLen); + } + } + + SAL_INFO("emfio", "\t\tText: " << aText); + SAL_INFO("emfio", "\t\tDxBuffer:"); + + KernArray aDXAry; + std::unique_ptr pDYAry; + + sal_Int32 nDxSize; + sal_Int32 nBytesEach; + + // Reading OutputDx + // ETO_PDY flag indicates that we should read twice values + // compared to the number of characters in the output string. + // Values are stored in an array of 32-bit unsigned integers + // named OutputDx, so there will be either 8 bytes or 4 bytes + // each depending on ETO_PDY is set or not. + if (nOptions & ETO_PDY) + nBytesEach = 8; + else + nBytesEach = 4; + + bool bOverflow = o3tl::checked_multiply(nLen, nBytesEach, nDxSize); + if (!bOverflow && offDx && ((nCurPos + offDx + nDxSize) <= nNextPos ) && nNextPos <= mnEndPos) + { + mpInputStream->Seek( nCurPos + offDx ); + aDXAry.resize(aText.getLength()); + if (nOptions & ETO_PDY) + { + pDYAry.reset( new tools::Long[aText.getLength()] ); } - SAL_INFO("emfio", "\t\t\tSpacing " << i << ": " << aDXAry[i]); + for (sal_Int32 i = 0; i < aText.getLength(); ++i) + { + sal_Int32 nDxCount = 1; + if ( static_cast( aText.getLength() ) != nLen ) + { + sal_Unicode cUniChar = aText[i]; + OString aTmp(&cUniChar, 1, GetCharSet()); + if (aTmp.getLength() > 1) + { + nDxCount = aTmp.getLength(); + } + } + + aDXAry[i] = 0; + if (nOptions & ETO_PDY) + { + pDYAry[i] = 0; + } + + while (nDxCount--) + { + sal_Int32 nDxTmp = 0; + mpInputStream->ReadInt32(nDxTmp); + aDXAry[i] += nDxTmp; + if (nOptions & ETO_PDY) + { + sal_Int32 nDyTmp = 0; + mpInputStream->ReadInt32(nDyTmp); + pDYAry[i] += nDyTmp; + } + } + + SAL_INFO("emfio", "\t\t\tSpacing " << i << ": " << aDXAry[i]); + } } + if ( nOptions & ETO_CLIPPED ) + { + Push(); // Save the current clip. It will be restored after text drawing + IntersectClipRect( aRect ); + } + DrawText(aPos, aText, aDXAry.empty() ? nullptr : &aDXAry, pDYAry.get(), fXScale, fYScale, mbRecordPath, static_cast(nGfxMode)); + if ( nOptions & ETO_CLIPPED ) + Pop(); } - if ( nOptions & ETO_CLIPPED ) - { - Push(); // Save the current clip. It will be restored after text drawing - IntersectClipRect( aRect ); - } - DrawText(aPos, aText, aDXAry.empty() ? nullptr : &aDXAry, pDYAry.get(), fXScale, fYScale, mbRecordPath, static_cast(nGfxMode)); - if ( nOptions & ETO_CLIPPED ) - Pop(); } mnBkMode = mnBkModeBackup; } @@ -2242,6 +2418,140 @@ namespace emfio } break; + case EMR_CREATEMONOBRUSH : + { + sal_uInt64 nStart = mpInputStream->Tell() - 8; + Bitmap aBitmap; + + mpInputStream->ReadUInt32( nIndex ); + + if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 ) + { + sal_uInt32 usage, offBmi, cbBmi, offBits, cbBits; + + mpInputStream->ReadUInt32( usage ); + mpInputStream->ReadUInt32( offBmi ); + mpInputStream->ReadUInt32( cbBmi ); + mpInputStream->ReadUInt32( offBits ); + mpInputStream->ReadUInt32( cbBits ); + + if ( !mpInputStream->good() || (cbBits > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBits < cbBmi) ) + bStatus = false; + else if ( offBmi ) + { + sal_uInt32 nSize = cbBmi + cbBits + 14; + if ( nSize <= ( mnEndPos - mnStartPos ) ) + { + char* pBuf = new char[ nSize ]; + + SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE ); + aTmp.ObjectOwnsMemory( true ); + aTmp.WriteUChar( 'B' ) + .WriteUChar( 'M' ) + .WriteUInt32( cbBits ) + .WriteUInt16( 0 ) + .WriteUInt16( 0 ) + .WriteUInt32( cbBmi + 14 ); + + mpInputStream->Seek( nStart + offBmi ); + char* pWritePos = pBuf + 14; + auto nRead = mpInputStream->ReadBytes(pWritePos, cbBmi); + if (nRead != cbBmi) + { + // zero remainder if short read + memset(pWritePos + nRead, 0, cbBmi - nRead); + } + + mpInputStream->Seek( nStart + offBits ); + pWritePos = pBuf + 14 + cbBmi; + nRead = mpInputStream->ReadBytes(pWritePos, cbBits); + if (nRead != cbBits) + { + // zero remainder if short read + memset(pWritePos + nRead, 0, cbBits - nRead); + } + + aTmp.Seek( 0 ); + ReadDIB(aBitmap, aTmp, true); + } + } + } + + CreateObjectIndexed(nIndex, std::make_unique( aBitmap )); + } + break; + + case EMR_GRADIENTFILL : + { + // [MS-EMF] 2.3.5.12 EMR_GRADIENTFILL + sal_Int32 BoundsLeft, BoundsTop, BoundsRight, BoundsBottom; + sal_uInt32 nVer, nTri, ulMode; + mpInputStream->ReadInt32( BoundsLeft ).ReadInt32( BoundsTop ) + .ReadInt32( BoundsRight ).ReadInt32( BoundsBottom ); + mpInputStream->ReadUInt32( nVer ).ReadUInt32( nTri ).ReadUInt32( ulMode ); + + SAL_INFO("emfio", "\t\tGradientFill nVer: " << nVer << " nTri: " << nTri << " mode: " << ulMode); + + // A vertex costs 16 bytes and a triangle or rectangle index pair 8, so what is + // left of this record says how many of each there can really be. + const sal_uInt64 nRecordEnd = std::min(nNextPos, mnEndPos); + const sal_uInt64 nRecordLeft = mpInputStream->Tell() < nRecordEnd + ? nRecordEnd - mpInputStream->Tell() + : 0; + if ( !mpInputStream->good() || nVer > 256 * 1024 || nTri > 256 * 1024 + || nVer * sal_uInt64( 16 ) + nTri * sal_uInt64( 8 ) > nRecordLeft ) + { + bStatus = false; + break; + } + + // Read TriVertex array (each 16 bytes: x, y, Red, Green, Blue, Alpha as int32+int32+4*uint16) + struct TriVertex { sal_Int32 x, y; sal_uInt16 Red, Green, Blue, Alpha; }; + std::vector vertices(nVer); + for (sal_uInt32 i = 0; i < nVer && mpInputStream->good(); ++i) + { + mpInputStream->ReadInt32( vertices[i].x ).ReadInt32( vertices[i].y ); + mpInputStream->ReadUInt16( vertices[i].Red ).ReadUInt16( vertices[i].Green ) + .ReadUInt16( vertices[i].Blue ).ReadUInt16( vertices[i].Alpha ); + } + + if (ulMode == 0x00 || ulMode == 0x01) // GRADIENT_FILL_RECT_H or GRADIENT_FILL_RECT_V + { + for (sal_uInt32 i = 0; i < nTri && mpInputStream->good(); ++i) + { + sal_uInt32 nUpperLeft(0), nLowerRight(0); + mpInputStream->ReadUInt32( nUpperLeft ).ReadUInt32( nLowerRight ); + + if (nUpperLeft >= nVer || nLowerRight >= nVer) + continue; + + const TriVertex& ul = vertices[nUpperLeft]; + const TriVertex& lr = vertices[nLowerRight]; + + Color aStartColor( static_cast(ul.Red >> 8), + static_cast(ul.Green >> 8), + static_cast(ul.Blue >> 8) ); + Color aEndColor( static_cast(lr.Red >> 8), + static_cast(lr.Green >> 8), + static_cast(lr.Blue >> 8) ); + + Gradient aGradient( css::awt::GradientStyle_LINEAR, aStartColor, aEndColor ); + // GRADIENT_FILL_RECT_H: left-to-right -> angle 900 + // GRADIENT_FILL_RECT_V: top-to-bottom -> angle 0 + aGradient.SetAngle( Degree10(ulMode == 0x00 ? 900 : 0) ); + + tools::Rectangle aRect( Point( ul.x, ul.y ), Point( lr.x, lr.y ) ); + DrawRect( aRect, false ); + mpGDIMetaFile->AddAction( new MetaGradientAction( ImplMap( aRect ), aGradient ) ); + } + } + else if (ulMode == 0x02) // GRADIENT_FILL_TRIANGLE + { + SAL_WARN("emfio", "TODO: EMR_GRADIENTFILL triangle mode not implemented"); + } + } + break; + case EMR_CREATECOLORSPACE : { sal_uInt32 nRemainingRecSize = nRecSize - 8; @@ -2296,19 +2606,15 @@ namespace emfio case EMR_SETICMPROFILEW : case EMR_TRANSPARENTBLT : case EMR_TRANSPARENTDIB : - case EMR_GRADIENTFILL : case EMR_SETLINKEDUFIS : case EMR_SETMAPPERFLAGS : case EMR_SETICMMODE : - case EMR_CREATEMONOBRUSH : case EMR_SETBRUSHORGEX : case EMR_SETMETARGN : case EMR_SETMITERLIMIT : - case EMR_EXCLUDECLIPRECT : case EMR_REALIZEPALETTE : case EMR_SELECTPALETTE : case EMR_CREATEPALETTE : - case EMR_ALPHADIBBLEND : case EMR_SETTEXTJUSTIFICATION : { SAL_WARN("emfio", "TODO: EMF record not implemented: " << record_type_name(nRecType)); diff --git a/emfio/source/reader/mtftools.cxx b/emfio/source/reader/mtftools.cxx index eb771f711c56..11c6268d1574 100644 --- a/emfio/source/reader/mtftools.cxx +++ b/emfio/source/reader/mtftools.cxx @@ -22,12 +22,16 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -77,6 +81,31 @@ namespace emfio return rInStream; } + Hatch mapWindowsHatch(sal_uInt32 nHatchIndex, const Color& rColor) + { + HatchStyle eStyle; + Degree10 nAngle; + switch (nHatchIndex) + { + case 0: // HS_HORIZONTAL + eStyle = HatchStyle::Single; nAngle = 0_deg10; break; + case 1: // HS_VERTICAL + eStyle = HatchStyle::Single; nAngle = Degree10(900); break; + case 2: // HS_FDIAGONAL + eStyle = HatchStyle::Single; nAngle = Degree10(1350); break; + case 3: // HS_BDIAGONAL + eStyle = HatchStyle::Single; nAngle = Degree10(450); break; + case 4: // HS_CROSS + eStyle = HatchStyle::Double; nAngle = 0_deg10; break; + case 5: // HS_DIAGCROSS + eStyle = HatchStyle::Double; nAngle = Degree10(450); break; + default: + SAL_WARN("emfio", "Unknown hatch index: " << nHatchIndex); + eStyle = HatchStyle::Single; nAngle = 0_deg10; break; + } + return Hatch(eStyle, rColor, 50, nAngle); + } + void WinMtfClipPath::intersectClip( const basegfx::B2DPolyPolygon& rPolyPolygon ) { maClip.intersectPolyPolygon(rPolyPolygon); @@ -291,22 +320,20 @@ namespace emfio // tdf#127471 adapt nFontWidth from Windows-like notation to // NormedFontScaling if used for text scaling -#ifndef _WIN32 const bool bFontScaledHorizontally(aFontSize.Width() != 0 && aFontSize.Width() != aFontSize.Height()); if(bFontScaledHorizontally) { - // tdf#127471 nFontWidth is the Windows FontScaling, need to convert to - // Non-Windowslike notation relative to FontHeight. + // tdf#127471 nFontWidth is the Windows FontScaling, need to convert + // to notation relative to FontHeight. const tools::Long nAverageFontWidth(aFont.GetOrCalculateAverageFontWidth()); if(nAverageFontWidth > 0) { const double fScaleFactor(static_cast(aFontSize.Height()) / static_cast(nAverageFontWidth)); - aFont.SetAverageFontWidth(static_cast(static_cast(aFontSize.Width()) * fScaleFactor)); + aFont.SetFontWidth(static_cast(static_cast(aFontSize.Width()) * fScaleFactor)); } } -#endif }; WinMtfFontStyle::~WinMtfFontStyle() = default; @@ -371,7 +398,7 @@ namespace emfio // so this will already sort out most situations const vcl::Font& rCandidate(rNewMetaFontAction->GetFont()); - if(0 != rCandidate.GetAverageFontWidth()) + if(0 != rCandidate.GetFontWidth()) { const tools::Long nUnscaledAverageFontWidth(rCandidate.GetOrCalculateAverageFontWidth()); @@ -408,27 +435,18 @@ namespace emfio const double fFactorTextPercent(fabs(1.0 - fFactorText) * 100.0); // if we assume that loaded file was written on old linux, we have to - // back-convert the scale value depending on which system we run -#ifdef _WIN32 - // When running on Windows the value was not adapted at font import (see WinMtfFontStyle - // constructor), so it is still NormedFontScaling and we need to convert to Windows-style - // scaling -#else - // When running on unx (non-Windows) the value was already adapted at font import (see WinMtfFontStyle - // constructor). It was wrongly assumed to be Windows-style FontScaling, so we need to revert that - // to get back to the needed unx-style FontScale -#endif - // Interestingly this leads to the *same* correction, so no need to make this - // system-dependent (!) + // back-convert the scale value: it was already adapted at font import (see + // WinMtfFontStyle constructor). It was wrongly assumed to be Windows-style + // FontScaling, so we need to revert that to get back to the needed FontScale const tools::Long nUnscaledAverageFontWidth(rFontCandidate.GetOrCalculateAverageFontWidth()); - const tools::Long nScaledAverageFontWidth(rFontCandidate.GetAverageFontWidth()); + const tools::Long nScaledAverageFontWidth(rFontCandidate.GetFontWidth()); const double fScaleFactor(static_cast(nUnscaledAverageFontWidth) / static_cast(rFontCandidate.GetFontHeight())); const double fCorrectedAverageFontWidth(static_cast(nScaledAverageFontWidth) * fScaleFactor); tools::Long nCorrectedTextLength(0); { // do in own scope, only need nUnscaledAverageFontWidth vcl::Font rFontCandidate2(rFontCandidate); - rFontCandidate2.SetAverageFontWidth(static_cast(fCorrectedAverageFontWidth)); + rFontCandidate2.SetFontWidth(static_cast(fCorrectedAverageFontWidth)); pTempVirtualDevice->SetFont(rFontCandidate2); nCorrectedTextLength = pTempVirtualDevice->GetTextWidth(rText); // on failure, use original length @@ -880,7 +898,21 @@ namespace emfio void MtfTools::SetBkMode( BackgroundMode nMode ) { - mnBkMode = nMode; + if (mnBkMode != nMode) + { + mnBkMode = nMode; + // The hatch fill background color emitted by UpdateFillStyle + // depends on bk mode: opaque -> bk color, transparent -> none. + // Invalidate maLatestFillStyle so UpdateFillStyle re-emits a + // fresh MetaFillColorAction even when the brush is otherwise + // unchanged. + maLatestFillStyle.aFillColor = Color(0x12, 0x34, 0x56); + } + } + + void MtfTools::SetPolyFillMode( sal_uInt32 nPolyFillMode ) + { + mnPolyFillMode = nPolyFillMode; } void MtfTools::SetBkColor( const Color& rColor ) @@ -903,12 +935,60 @@ namespace emfio mvGDIObj.resize(nNewEntrys); } + // Convert a PolyPolygon so that nonzero/winding fill rule gives the same visual + // result when rendered with even-odd fill rule (which is all VCL supports). + static tools::PolyPolygon CreateWindingFillPolyPolygon(const tools::PolyPolygon& rPolyPoly) + { + basegfx::B2DPolyPolygon aB2D = rPolyPoly.getB2DPolyPolygon(); + + if (aB2D.count() == 1) + { + // Single self-intersecting polygon (e.g. pentagram star): resolve + // self-intersections, then union (OR) all resulting sub-regions. + // This gives the outer boundary of the filled area, which even-odd + // fill renders correctly. createNonzeroConform() fails here because + // solveCrossovers() produces overlapping loops for odd-crossing + // polygons, and the center ends up inside an even number of loops. + basegfx::B2DPolyPolygon aResolved + = basegfx::utils::solveCrossovers(aB2D.getB2DPolygon(0)); + aResolved = basegfx::utils::stripNeutralPolygons(aResolved); + + if (aResolved.count() > 1) + { + basegfx::B2DPolyPolygonVector aInput; + for (sal_uInt32 i = 0; i < aResolved.count(); ++i) + aInput.push_back(basegfx::B2DPolyPolygon(aResolved.getB2DPolygon(i))); + aB2D = basegfx::utils::mergeToSinglePolyPolygon(aInput); + } + else + { + aB2D = aResolved; + } + } + else + { + // Multiple polygons: use createNonzeroConform (handles nested + // same-orientation polygons by removing inner duplicates). + aB2D = basegfx::utils::createNonzeroConform(aB2D); + } + + return tools::PolyPolygon(aB2D); + } + void MtfTools::ImplDrawClippedPolyPolygon( const tools::PolyPolygon& rPolyPoly ) { if ( !rPolyPoly.Count() ) return; ImplSetNonPersistentLineColorTransparenz(); + + if (mnPolyFillMode == 2) // WINDING + { + tools::PolyPolygon aFill = CreateWindingFillPolyPolygon(rPolyPoly); + mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aFill ) ); + return; + } + if ( rPolyPoly.Count() == 1 ) { if ( rPolyPoly.IsRect() ) @@ -930,6 +1010,9 @@ namespace emfio } else mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) ); + + if (maLatestFillStyle.aType == WinMtfFillStyleType::Hatch) + mpGDIMetaFile->AddAction( new MetaHatchAction( rPolyPoly, maLatestFillStyle.aHatch ) ); } void MtfTools::CreateObject( std::unique_ptr pObject ) @@ -953,15 +1036,21 @@ namespace emfio } } std::vector>::size_type nIndex; - for ( nIndex = 0; nIndex < mvGDIObj.size(); nIndex++ ) + for ( nIndex = mnLowestFreeGDIObj; nIndex < mvGDIObj.size(); nIndex++ ) { if ( !mvGDIObj[ nIndex ] ) break; } + if ( nIndex > 0xffff ) // the same ceiling an indexed object has + { + SAL_WARN( "emfio", "too many objects" ); + return; + } if ( nIndex == mvGDIObj.size() ) ImplResizeObjectArry( mvGDIObj.size() + 16 ); mvGDIObj[ nIndex ] = std::move(pObject); + mnLowestFreeGDIObj = nIndex + 1; } void MtfTools::CreateObjectIndexed( sal_uInt32 nIndex, std::unique_ptr pObject ) @@ -1006,6 +1095,9 @@ namespace emfio if ( nIndex >= mvGDIObj.size() ) ImplResizeObjectArry( nIndex + 16 ); + if ( !pObject && nIndex < mnLowestFreeGDIObj ) + mnLowestFreeGDIObj = nIndex; + mvGDIObj[ nIndex ] = std::move(pObject); } @@ -1021,6 +1113,8 @@ namespace emfio if ( nIndex < mvGDIObj.size() ) { mvGDIObj[ nIndex ].reset(); + if ( nIndex < mnLowestFreeGDIObj ) + mnLowestFreeGDIObj = nIndex; } } } @@ -1091,6 +1185,7 @@ namespace emfio mnBkMode(BackgroundMode::OPAQUE), meLatestRasterOp(RasterOp::Invert), meRasterOp(RasterOp::OverPaint), + mnLowestFreeGDIObj(0), mnRop(), meGfxMode(GraphicsMode::GM_COMPATIBLE), meMapMode(MappingMode::MM_TEXT), @@ -1113,6 +1208,7 @@ namespace emfio mbNopMode(false), mbClockWiseArcDirection(false), mbFillStyleSelected(false), + mnPolyFillMode(1), // ALTERNATE mbClipNeedsUpdate(true), mbComplexClip(false), mbIsMapWinSet(false), @@ -1192,6 +1288,50 @@ namespace emfio } } + bool MtfTools::ImplEmitLineHatch(const tools::Polygon& rPoly) + { + if (!maLineStyle.bHasHatch || maLineStyle.aLineInfo.GetWidth() <= 0) + return false; + + basegfx::B2DPolyPolygon aArea = basegfx::utils::createAreaGeometry( + rPoly.getB2DPolygon(), + maLineStyle.aLineInfo.GetWidth() / 2.0, + maLineStyle.aLineInfo.GetLineJoin(), + maLineStyle.aLineInfo.GetLineCap()); + tools::PolyPolygon aPP(aArea); + + // Fill the stroke area with background color (opaque) or transparent + mpGDIMetaFile->AddAction(new MetaPushAction(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR)); + mpGDIMetaFile->AddAction(new MetaLineColorAction(Color(), false)); + if (mnBkMode == BackgroundMode::OPAQUE) + mpGDIMetaFile->AddAction(new MetaFillColorAction(maBkColor, true)); + else + mpGDIMetaFile->AddAction(new MetaFillColorAction(Color(), false)); + mpGDIMetaFile->AddAction(new MetaPolyPolygonAction(aPP)); + mpGDIMetaFile->AddAction(new MetaPopAction()); + + // Draw the hatch pattern on top + mpGDIMetaFile->AddAction(new MetaHatchAction(aPP, maLineStyle.aHatch)); + return true; + } + + void MtfTools::ImplEmitPatternFill(const tools::PolyPolygon& rPolyPoly) + { + const tools::Rectangle aBound = rPolyPoly.GetBoundRect(); + if (aBound.IsEmpty() || maLatestFillStyle.aBmp.IsEmpty()) + return; + + Wallpaper aWallpaper(maLatestFillStyle.aBmp); + aWallpaper.SetStyle(WallpaperStyle::Tile); + + // Clip the tiled wallpaper to the polypoly so non-rectangular fills + // (and edge-tile bleed at the bounds) stay inside the shape. + mpGDIMetaFile->AddAction(new MetaPushAction(vcl::PushFlags::CLIPREGION)); + mpGDIMetaFile->AddAction(new MetaISectRegionClipRegionAction(vcl::Region(rPolyPoly))); + mpGDIMetaFile->AddAction(new MetaWallpaperAction(aBound, aWallpaper)); + mpGDIMetaFile->AddAction(new MetaPopAction()); + } + void MtfTools::ImplSetNonPersistentLineColorTransparenz() { WinMtfLineStyle aTransparentLine( COL_TRANSPARENT, true ); @@ -1234,6 +1374,13 @@ namespace emfio maLatestFillStyle = maFillStyle; if (maFillStyle.aType == WinMtfFillStyleType::Solid) mpGDIMetaFile->AddAction( new MetaFillColorAction( maFillStyle.aFillColor, !maFillStyle.bTransparent ) ); + else if (maFillStyle.aType == WinMtfFillStyleType::Hatch) + { + if (mnBkMode == BackgroundMode::OPAQUE) + mpGDIMetaFile->AddAction( new MetaFillColorAction( maBkColor, true ) ); + else + mpGDIMetaFile->AddAction( new MetaFillColorAction( Color(), false ) ); + } } } @@ -1292,30 +1439,49 @@ namespace emfio UpdateClipRegion(); UpdateLineStyle(); UpdateFillStyle(); + bool bWindingFill = (mnPolyFillMode == 2); if ( bFill ) { - if ( !bStroke ) + // When using WINDING fill mode, we convert the geometry so it renders + // correctly with even-odd fill. We must also disable line color to avoid + // stroking internal edges of the converted fill geometry. + if ( !bStroke || bWindingFill ) { mpGDIMetaFile->AddAction( new MetaPushAction( vcl::PushFlags::LINECOLOR ) ); mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), false ) ); } - if ( maPathObj.Count() == 1 ) - mpGDIMetaFile->AddAction( new MetaPolygonAction( maPathObj.GetObject( 0 ) ) ); + if (bWindingFill) + { + tools::PolyPolygon aFill = CreateWindingFillPolyPolygon(maPathObj); + mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aFill ) ); + } else - mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( maPathObj ) ); + { + if ( maPathObj.Count() == 1 ) + mpGDIMetaFile->AddAction( new MetaPolygonAction( maPathObj.GetObject( 0 ) ) ); + else + mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( maPathObj ) ); + } - if ( !bStroke ) + if (maLatestFillStyle.aType == WinMtfFillStyleType::Hatch) + mpGDIMetaFile->AddAction( new MetaHatchAction( maPathObj, maLatestFillStyle.aHatch ) ); + + if ( !bStroke || bWindingFill ) mpGDIMetaFile->AddAction( new MetaPopAction() ); } // tdf#142014 By default the stroke is made with hairline. If width is bigger, we need to use PolyLineAction if ( bStroke ) { // bFill is drawing hairstyle line. So we need to draw it only when the width is different than 0 - if ( !bFill || maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) ) + // When using WINDING fill mode, line was disabled for the fill, so always draw stroke + if ( !bFill || bWindingFill || maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) ) { sal_uInt16 i, nCount = maPathObj.Count(); for ( i = 0; i < nCount; i++ ) - mpGDIMetaFile->AddAction( new MetaPolyLineAction( maPathObj[ i ], maLineStyle.aLineInfo ) ); + { + if (!ImplEmitLineHatch( maPathObj[ i ] )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( maPathObj[ i ], maLineStyle.aLineInfo ) ); + } } } ClearPath(); @@ -1349,7 +1515,11 @@ namespace emfio else { UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaLineAction( maActPos, aDest, maLineStyle.aLineInfo ) ); + tools::Polygon aLinePoly(2); + aLinePoly.SetPoint(maActPos, 0); + aLinePoly.SetPoint(aDest, 1); + if (!ImplEmitLineHatch(aLinePoly)) + mpGDIMetaFile->AddAction( new MetaLineAction( maActPos, aDest, maLineStyle.aLineInfo ) ); } maActPos = aDest; } @@ -1386,25 +1556,43 @@ namespace emfio } else { + const bool bPattern = (maLatestFillStyle.aType == WinMtfFillStyleType::Pattern); if ( bEdge ) { if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) ) { ImplSetNonPersistentLineColorTransparenz(); - mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) ); + if ( bPattern ) + ImplEmitPatternFill( tools::PolyPolygon( tools::Polygon( ImplMap( rRect ) ) ) ); + else + mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) ); UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( ImplMap( rRect ) ),maLineStyle.aLineInfo ) ); + tools::Polygon aEdgePoly( ImplMap( rRect ) ); + if (!ImplEmitLineHatch( aEdgePoly )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( aEdgePoly, maLineStyle.aLineInfo ) ); } else { UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) ); + if ( bPattern ) + ImplEmitPatternFill( tools::PolyPolygon( tools::Polygon( ImplMap( rRect ) ) ) ); + else + mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) ); } } else { ImplSetNonPersistentLineColorTransparenz(); - mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) ); + if ( bPattern ) + ImplEmitPatternFill( tools::PolyPolygon( tools::Polygon( ImplMap( rRect ) ) ) ); + else + mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) ); + } + + if (maLatestFillStyle.aType == WinMtfFillStyleType::Hatch) + { + tools::PolyPolygon aPolyPoly( tools::Polygon( ImplMap( rRect ) ) ); + mpGDIMetaFile->AddAction( new MetaHatchAction( aPolyPoly, maLatestFillStyle.aHatch ) ); } } } @@ -1414,12 +1602,21 @@ namespace emfio UpdateClipRegion(); UpdateLineStyle(); UpdateFillStyle(); - mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), std::abs( ImplMap( rSize ).Width() ), std::abs( ImplMap( rSize ).Height() ) ) ); + if (maLatestFillStyle.aType == WinMtfFillStyleType::Pattern) + { + tools::Polygon aRoundRectPoly( rRect, rSize.Width(), rSize.Height() ); + ImplMap( aRoundRectPoly ); + ImplEmitPatternFill( tools::PolyPolygon( aRoundRectPoly ) ); + } + else + mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), std::abs( ImplMap( rSize ).Width() ), std::abs( ImplMap( rSize ).Height() ) ) ); // tdf#142139 Wrong line width during WMF import if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) ) { tools::Polygon aRoundRectPoly( rRect, rSize.Width(), rSize.Height() ); - mpGDIMetaFile->AddAction( new MetaPolyLineAction( ImplMap( aRoundRectPoly ), maLineStyle.aLineInfo ) ); + ImplMap( aRoundRectPoly ); + if (!ImplEmitLineHatch( aRoundRectPoly )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( aRoundRectPoly, maLineStyle.aLineInfo ) ); } } @@ -1428,20 +1625,29 @@ namespace emfio UpdateClipRegion(); UpdateFillStyle(); + const bool bPattern = (maLatestFillStyle.aType == WinMtfFillStyleType::Pattern); + const Point aCenter( ImplMap( rRect.Center() ) ); + const Size aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) ); + if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) ) { - Point aCenter( ImplMap( rRect.Center() ) ); - Size aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) ); - ImplSetNonPersistentLineColorTransparenz(); - mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) ); + if ( bPattern ) + ImplEmitPatternFill( tools::PolyPolygon( tools::Polygon( aCenter, aRad.Width(), aRad.Height() ) ) ); + else + mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) ); UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( std::move(aCenter), aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) ); + tools::Polygon aEllipsePoly( aCenter, aRad.Width(), aRad.Height() ); + if (!ImplEmitLineHatch( aEllipsePoly )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( aEllipsePoly, maLineStyle.aLineInfo ) ); } else { UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) ); + if ( bPattern ) + ImplEmitPatternFill( tools::PolyPolygon( tools::Polygon( aCenter, aRad.Width(), aRad.Height() ) ) ); + else + mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) ); } } @@ -1461,11 +1667,16 @@ namespace emfio { // SJ: #i53768# if start & end is identical, then we have to draw a full ellipse Point aCenter( aRect.Center() ); Size aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 ); - - mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( std::move(aCenter), aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) ); + tools::Polygon aArcPoly( aCenter, aRad.Width(), aRad.Height() ); + if (!ImplEmitLineHatch( aArcPoly )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( aArcPoly, maLineStyle.aLineInfo ) ); } else - mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Arc ), maLineStyle.aLineInfo ) ); + { + tools::Polygon aArcPoly( aRect, aStart, aEnd, PolyStyle::Arc ); + if (!ImplEmitLineHatch( aArcPoly )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( aArcPoly, maLineStyle.aLineInfo ) ); + } } else mpGDIMetaFile->AddAction( new MetaArcAction( aRect, aStart, aEnd ) ); @@ -1482,18 +1693,29 @@ namespace emfio tools::Rectangle aRect( ImplMap( rRect ) ); Point aStart( ImplMap( rStart ) ); Point aEnd( ImplMap( rEnd ) ); + const bool bPattern = (maLatestFillStyle.aType == WinMtfFillStyleType::Pattern); if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) ) { ImplSetNonPersistentLineColorTransparenz(); - mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) ); + if ( bPattern ) + ImplEmitPatternFill( tools::PolyPolygon( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Pie ) ) ); + else + mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) ); UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Pie ), maLineStyle.aLineInfo ) ); + { + tools::Polygon aPiePoly( aRect, aStart, aEnd, PolyStyle::Pie ); + if (!ImplEmitLineHatch( aPiePoly )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( aPiePoly, maLineStyle.aLineInfo ) ); + } } else { UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) ); + if ( bPattern ) + ImplEmitPatternFill( tools::PolyPolygon( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Pie ) ) ); + else + mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) ); } } @@ -1505,18 +1727,29 @@ namespace emfio tools::Rectangle aRect( ImplMap( rRect ) ); Point aStart( ImplMap( rStart ) ); Point aEnd( ImplMap( rEnd ) ); + const bool bPattern = (maLatestFillStyle.aType == WinMtfFillStyleType::Pattern); if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) ) { ImplSetNonPersistentLineColorTransparenz(); - mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) ); + if ( bPattern ) + ImplEmitPatternFill( tools::PolyPolygon( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Chord ) ) ); + else + mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) ); UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Chord ), maLineStyle.aLineInfo ) ); + { + tools::Polygon aChordPoly( aRect, aStart, aEnd, PolyStyle::Chord ); + if (!ImplEmitLineHatch( aChordPoly )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( aChordPoly, maLineStyle.aLineInfo ) ); + } } else { UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) ); + if ( bPattern ) + ImplEmitPatternFill( tools::PolyPolygon( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Chord ) ) ); + else + mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) ); } } @@ -1552,40 +1785,54 @@ namespace emfio } } ImplSetNonPersistentLineColorTransparenz(); - mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) ); + if (mnPolyFillMode == 2) // WINDING + { + tools::PolyPolygon aFill = CreateWindingFillPolyPolygon(tools::PolyPolygon(rPolygon)); + mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aFill ) ); + } + else + { + mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) ); + } + if (maLatestFillStyle.aType == WinMtfFillStyleType::Hatch) + mpGDIMetaFile->AddAction( new MetaHatchAction( tools::PolyPolygon( rPolygon ), maLatestFillStyle.aHatch ) ); UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaPolyLineAction( std::move(rPolygon), maLineStyle.aLineInfo ) ); + if (!ImplEmitLineHatch( rPolygon )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) ); } else { UpdateLineStyle(); - if (maLatestFillStyle.aType != WinMtfFillStyleType::Pattern) - mpGDIMetaFile->AddAction( new MetaPolygonAction( std::move(rPolygon) ) ); - else { - SvtGraphicFill aFill( tools::PolyPolygon( rPolygon ), - Color(), - 0.0, - SvtGraphicFill::fillNonZero, - SvtGraphicFill::fillTexture, - SvtGraphicFill::Transform(), - true, - SvtGraphicFill::hatchSingle, - Color(), - SvtGraphicFill::GradientType::Linear, - Color(), - Color(), - 0, - Graphic(maLatestFillStyle.aBmp)); - - SvMemoryStream aMemStm; - - WriteSvtGraphicFill( aMemStm, aFill ); - - mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN"_ostr, 0, - static_cast(aMemStm.GetData()), - aMemStm.TellEnd() ) ); - mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_END"_ostr ) ); + if (maLatestFillStyle.aType == WinMtfFillStyleType::Hatch) + { + mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) ); + mpGDIMetaFile->AddAction( new MetaHatchAction( tools::PolyPolygon( std::move(rPolygon) ), maLatestFillStyle.aHatch ) ); + } + else if (maLatestFillStyle.aType != WinMtfFillStyleType::Pattern) + { + if (mnPolyFillMode == 2) // WINDING + { + tools::PolyPolygon aFill = CreateWindingFillPolyPolygon(tools::PolyPolygon(rPolygon)); + ImplSetNonPersistentLineColorTransparenz(); + mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aFill ) ); + UpdateLineStyle(); + // Stroke with original polygon, closing it for the polyline + sal_uInt16 nCount = rPolygon.GetSize(); + if (nCount && rPolygon[nCount - 1] != rPolygon[0]) + { + Point aPoint(rPolygon[0]); + rPolygon.Insert(nCount, aPoint); + } + if (!ImplEmitLineHatch( rPolygon )) + mpGDIMetaFile->AddAction(new MetaPolyLineAction(rPolygon, maLineStyle.aLineInfo)); + } + else + mpGDIMetaFile->AddAction( new MetaPolygonAction( std::move(rPolygon) ) ); + } + else + { + ImplEmitPatternFill( tools::PolyPolygon( std::move(rPolygon) ) ); } } @@ -1614,12 +1861,39 @@ namespace emfio else { UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) ); - if (maLineStyle.aLineInfo.GetWidth() > 0 || maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash) + if (mnPolyFillMode == 2) // WINDING { + // Convert geometry so even-odd rendering matches winding fill. + // Disable line to avoid stroking internal resolved edges. + tools::PolyPolygon aFill = CreateWindingFillPolyPolygon(rPolyPolygon); + mpGDIMetaFile->AddAction( new MetaPushAction( vcl::PushFlags::LINECOLOR ) ); + mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), false ) ); + mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aFill ) ); + mpGDIMetaFile->AddAction( new MetaPopAction() ); + if (maLatestFillStyle.aType == WinMtfFillStyleType::Hatch) + mpGDIMetaFile->AddAction( new MetaHatchAction( rPolyPolygon, maLatestFillStyle.aHatch ) ); + // Stroke with original geometry for (sal_uInt16 nPoly = 0; nPoly < rPolyPolygon.Count(); ++nPoly) { - mpGDIMetaFile->AddAction(new MetaPolyLineAction(rPolyPolygon[nPoly], maLineStyle.aLineInfo)); + if (!ImplEmitLineHatch( rPolyPolygon[nPoly] )) + mpGDIMetaFile->AddAction(new MetaPolyLineAction(rPolyPolygon[nPoly], maLineStyle.aLineInfo)); + } + } + else + { + if (maLatestFillStyle.aType == WinMtfFillStyleType::Pattern) + ImplEmitPatternFill( rPolyPolygon ); + else + mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) ); + if (maLatestFillStyle.aType == WinMtfFillStyleType::Hatch) + mpGDIMetaFile->AddAction( new MetaHatchAction( rPolyPolygon, maLatestFillStyle.aHatch ) ); + if (maLineStyle.aLineInfo.GetWidth() > 0 || maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash) + { + for (sal_uInt16 nPoly = 0; nPoly < rPolyPolygon.Count(); ++nPoly) + { + if (!ImplEmitLineHatch( rPolyPolygon[nPoly] )) + mpGDIMetaFile->AddAction(new MetaPolyLineAction(rPolyPolygon[nPoly], maLineStyle.aLineInfo)); + } } } } @@ -1645,7 +1919,8 @@ namespace emfio else { UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaPolyLineAction( std::move(rPolygon), maLineStyle.aLineInfo ) ); + if (!ImplEmitLineHatch( rPolygon )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( std::move(rPolygon), maLineStyle.aLineInfo ) ); } } @@ -1696,7 +1971,8 @@ namespace emfio else { UpdateLineStyle(); - mpGDIMetaFile->AddAction( new MetaPolyLineAction( std::move(rPolygon), maLineStyle.aLineInfo ) ); + if (!ImplEmitLineHatch( rPolygon )) + mpGDIMetaFile->AddAction( new MetaPolyLineAction( std::move(rPolygon), maLineStyle.aLineInfo ) ); } } @@ -1980,6 +2256,290 @@ namespace emfio SetGfxMode( nOldGfxMode ); } + bool MtfTools::DrawGlyphs( Point& rPosition, const std::vector& rGlyphIds, + KernArray* pDXArry, tools::Long* pDYArry, + const float fXScale, const float fYScale, + bool bRecordPath, GraphicsMode nGfxMode ) + { + if (rGlyphIds.empty()) + return true; + + // Check that the required font is actually available — glyph indices + // are font-specific and meaningless if a different font is substituted. + { + SolarMutexGuard aGuard; + ScopedVclPtrInstance< VirtualDevice > pVDev; + if ( !pVDev->IsFontAvailable( maFont.GetFamilyName() ) ) + { + SAL_WARN("emfio", "ETO_GLYPH_INDEX: font '" + << maFont.GetFamilyName() + << "' not available, falling back to text path, which will be a " + "garbled nonsense"); + return false; + } + } + + UpdateClipRegion(); + rPosition = ImplMap( rPosition ); + GraphicsMode nOldGfxMode = GetGfxMode(); + SetGfxMode( GraphicsMode::GM_COMPATIBLE ); + + // Map DX/DY arrays (same as DrawText) + sal_Int32 nLen = static_cast(rGlyphIds.size()); + if (pDXArry) + { + sal_Int64 nSumX = 0, nSumY = 0; + for (sal_Int32 i = 0; i < nLen; i++) + { + nSumX += (*pDXArry)[i]; + const Size aSizeX(ImplMap(Size(nSumX, 0))); + const basegfx::B2DVector aVectorX(aSizeX.Width(), aSizeX.Height()); + (*pDXArry)[i] = aVectorX.getLength() * (nSumX >= 0 ? 1 : -1); + + if (pDYArry) + { + nSumY += pDYArry[i]; + const Size aSizeY(ImplMap(Size(0, nSumY))); + const basegfx::B2DVector aVectorY(aSizeY.Width(), aSizeY.Height()); + pDYArry[i] = basegfx::fround(aVectorY.getLength()); + pDYArry[i] *= (nSumY >= 0 ? -1 : 1); + } + } + } + + // Text layout mode (same as DrawText) + if ( mnLatestTextLayoutMode != mnTextLayoutMode ) + { + mnLatestTextLayoutMode = mnTextLayoutMode; + mpGDIMetaFile->AddAction( new MetaLayoutModeAction( mnTextLayoutMode ) ); + } + SetGfxMode(nGfxMode); + + // Text alignment (same as DrawText) + TextAlign eTextAlign; + if (mnTextAlign & TA_BASELINE) + eTextAlign = ALIGN_BASELINE; + else if (mnTextAlign & TA_BOTTOM) + eTextAlign = ALIGN_BOTTOM; + else + eTextAlign = ALIGN_TOP; + + bool bChangeFont = false; + if ( mnLatestTextAlign != mnTextAlign ) + { + bChangeFont = true; + mnLatestTextAlign = mnTextAlign; + mpGDIMetaFile->AddAction( new MetaTextAlignAction( eTextAlign ) ); + } + if ( maLatestTextColor != maTextColor ) + { + bChangeFont = true; + maLatestTextColor = maTextColor; + mpGDIMetaFile->AddAction( new MetaTextColorAction( maTextColor ) ); + } + bool bChangeFillColor = false; + if ( maLatestBkColor != maBkColor ) + { + bChangeFillColor = true; + maLatestBkColor = maBkColor; + } + if ( mnLatestBkMode != mnBkMode ) + { + bChangeFillColor = true; + mnLatestBkMode = mnBkMode; + } + if ( bChangeFillColor ) + { + bChangeFont = true; + mpGDIMetaFile->AddAction( new MetaTextFillColorAction( maFont.GetFillColor(), !maFont.IsTransparent() ) ); + } + vcl::Font aTmp( maFont ); + aTmp.SetColor( maTextColor ); + + if( mnBkMode == BackgroundMode::Transparent ) + { + aTmp.SetFillColor( COL_TRANSPARENT ); + aTmp.SetTransparent( true ); + } + else + { + aTmp.SetFillColor( maBkColor ); + aTmp.SetTransparent( false ); + } + + aTmp.SetAlignment( eTextAlign ); + + if ( nGfxMode == GraphicsMode::GM_ADVANCED ) + { + Point aP1( ImplMap( Point() ) ); + Point aP2( ImplMap( Point( 0, 100 ) ) ); + aP2.setX(o3tl::saturating_sub(aP2.X(), aP1.X())); + aP2.setY(o3tl::saturating_sub(aP2.Y(), aP1.Y())); + double fX = aP2.X(); + double fY = aP2.Y(); + if ( fX ) + { + double fOrientation = basegfx::rad2deg(acos(fX / std::hypot(fX, fY))); + if ( fY > 0 ) + fOrientation = 360 - fOrientation; + fOrientation += 90; + fOrientation *= 10; + aTmp.SetOrientation( aTmp.GetOrientation() + Degree10( static_cast(fOrientation) ) ); + } + } + else if (nGfxMode == GraphicsMode::GM_COMPATIBLE) + { + if (fXScale != 0.0) + { + const bool bNeedsWidthScale = (std::fabs(fYScale) != std::fabs(fXScale)); + if (bNeedsWidthScale) + { + Size aFontSize = aTmp.GetFontSize(); + const float fTestWidthScale = std::fabs(fYScale / fXScale); + + if (aFontSize.Width() == 0) + aFontSize.setWidth(basegfx::fround(aFontSize.Height() * fTestWidthScale)); + else + aFontSize.setWidth(basegfx::fround(aFontSize.Width() * fTestWidthScale)); + aTmp.SetFontSize(aFontSize); + bChangeFont = true; + } + } + + if ((fYScale < 0.0) && (fXScale < 0.0)) + { + aTmp.SetOrientation(aTmp.GetOrientation() + Degree10(1800)); + } + else if ((fYScale < 0.0) || (fXScale < 0.0)) + { + aTmp.SetOrientation(Degree10(3600) - aTmp.GetOrientation()); + } + } + + if( mnTextAlign & ( TA_UPDATECP | TA_RIGHT_CENTER ) ) + { + SolarMutexGuard aGuard; + ScopedVclPtrInstance< VirtualDevice > pVDev; + sal_Int32 nTextWidth; + Point aActPosDelta; + pVDev->SetMapMode( MapMode( MapUnit::Map100thMM ) ); + pVDev->SetFont( maFont ); + if (nLen && pDXArry) + { + // Approximate width of last glyph + nTextWidth = pVDev->GetTextWidth( u"M"_ustr ); + if( nLen > 1 ) + nTextWidth += (*pDXArry)[ nLen - 2 ]; + aActPosDelta.setX( (*pDXArry)[ nLen - 1 ] ); + if ( pDYArry ) + aActPosDelta.setY( pDYArry[ nLen - 1 ] ); + } + else + { + nTextWidth = 0; + aActPosDelta.setX( nTextWidth ); + } + + if( mnTextAlign & TA_UPDATECP ) + rPosition = maActPos; + + if (mnTextAlign & TA_RIGHT_CENTER) + { + Point aDisplacement(((mnTextAlign & TA_RIGHT_CENTER) == TA_CENTER) ? nTextWidth >> 1: nTextWidth, 0); + Point().RotateAround(aDisplacement, maFont.GetOrientation()); + rPosition -= aDisplacement; + } + + if( mnTextAlign & TA_UPDATECP ) + { + Point().RotateAround(aActPosDelta, maFont.GetOrientation()); + maActPos = rPosition + aActPosDelta; + } + } + + if(bChangeFont || (maLatestFont != aTmp)) + { + maLatestFont = aTmp; + rtl::Reference aNewMetaFontAction(new MetaFontAction(aTmp)); + maScaledFontHelper.endCurrentMetaFontAction(); + mpGDIMetaFile->AddAction( aNewMetaFontAction ); + mpGDIMetaFile->AddAction( new MetaTextAlignAction( aTmp.GetAlignment() ) ); + mpGDIMetaFile->AddAction( new MetaTextColorAction( aTmp.GetColor() ) ); + mpGDIMetaFile->AddAction( new MetaTextFillColorAction( aTmp.GetFillColor(), !aTmp.IsTransparent() ) ); + } + + // Convert glyph indices to polypolygon outlines + if ( !bRecordPath ) + { + SolarMutexGuard aGuard; + ScopedVclPtrInstance< VirtualDevice > pVDev; + pVDev->SetMapMode( MapMode( MapUnit::Map100thMM ) ); + pVDev->SetFont( maLatestFont ); + + // GetGlyphOutlines() returns outlines in the OutputDevice's + // logical coordinates; since the VirtualDevice is set to + // Map100thMM above, outlines come back in 100th-mm — no + // additional scaling is needed. + std::vector aGlyphIds32(rGlyphIds.begin(), rGlyphIds.end()); + basegfx::B2DPolyPolygonVector aOutlines; + pVDev->GetGlyphOutlines(aGlyphIds32.data(), nLen, aOutlines); + + // Emit each glyph as a separate filled PolyPolygon. We must NOT + // combine all glyphs into a single PolyPolygon because the even-odd + // fill rule would cancel out overlapping regions where Arabic + // connected glyphs overlap, leaving visible white gaps. + bool bHasGlyphs = false; + for (sal_Int32 i = 0; i < nLen && i < static_cast(aOutlines.size()); ++i) + { + basegfx::B2DPolyPolygon aGlyph = aOutlines[i]; + if (aGlyph.count() == 0) + continue; + + // Position glyph: glyph 0 at origin, glyph i at DX[i-1] + double fDX = 0, fDY = 0; + if (pDXArry && i > 0) + fDX = (*pDXArry)[i - 1]; + if (pDYArry && i > 0) + fDY = pDYArry[i - 1]; + + basegfx::B2DHomMatrix aMat; + if (fDX != 0 || fDY != 0) + aMat.translate(fDX, fDY); + + // Translate to text position + aMat.translate(rPosition.X(), rPosition.Y()); + aGlyph.transform(aMat); + + tools::PolyPolygon aGlyphPoly(aGlyph); + // Use aTmp's orientation so scale-induced rotation (GM_COMPATIBLE + // with negative fXScale/fYScale, or GM_ADVANCED world transform) + // is applied to the emitted polygons. + if (aTmp.GetOrientation() != 0_deg10) + { + for (sal_uInt16 p = 0; p < aGlyphPoly.Count(); ++p) + aGlyphPoly[p].Rotate(rPosition, aTmp.GetOrientation()); + } + + if (!bHasGlyphs) + { + // Emit Push/FillColor/LineColor once before the first glyph + mpGDIMetaFile->AddAction( new MetaPushAction( vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR ) ); + mpGDIMetaFile->AddAction( new MetaFillColorAction( maTextColor, true ) ); + mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), false ) ); + bHasGlyphs = true; + } + + mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aGlyphPoly ) ); + } + + if (bHasGlyphs) + mpGDIMetaFile->AddAction( new MetaPopAction() ); + } + + SetGfxMode( nOldGfxMode ); + return true; + } + void MtfTools::ImplDrawBitmap( const Point& rPos, const Size& rSize, const Bitmap& rBitmap ) { Bitmap aBmp( rBitmap ); @@ -2498,6 +3058,7 @@ namespace emfio pSave->aBkColor = maBkColor; pSave->bClockWiseArcDirection = mbClockWiseArcDirection; pSave->bFillStyleSelected = mbFillStyleSelected; + pSave->nPolyFillMode = mnPolyFillMode; pSave->aActPos = maActPos; pSave->aXForm = maXForm; @@ -2560,6 +3121,7 @@ namespace emfio maBkColor = pSave->aBkColor; mbClockWiseArcDirection = pSave->bClockWiseArcDirection; mbFillStyleSelected = pSave->bFillStyleSelected; + mnPolyFillMode = pSave->nPolyFillMode; maActPos = pSave->aActPos; maXForm = pSave->aXForm; diff --git a/emfio/source/reader/wmfreader.cxx b/emfio/source/reader/wmfreader.cxx index cb3e130cd551..b118d531e47e 100644 --- a/emfio/source/reader/wmfreader.cxx +++ b/emfio/source/reader/wmfreader.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #include #include @@ -246,6 +248,66 @@ namespace #endif } + // Reads a Bitmap16 from rStream and returns it as a Bitmap. nHeaderSize + // is the on-wire size of the header before the Bits field: per + // [MS-WMF] 2.2.2.1 the structure is 10 bytes; META_CREATEPATTERNBRUSH + // [MS-WMF] 2.3.4.4 instead wraps it in a 14-byte legacy BITMAP struct + // (with a 4-byte bmBits placeholder) plus 18 bytes of padding, for a + // total of 32. Only the 1bpp form actually seen in BS_PATTERN / + // META_CREATEPATTERNBRUSH is supported; anything else returns an empty + // Bitmap. + Bitmap CreateBitmap16(SvStream& rStream, sal_uInt32 nHeaderSize) + { + const sal_uInt64 nHdrStart = rStream.Tell(); + sal_Int16 nType(0), nWidth(0), nHeight(0), nWidthBytes(0); + sal_uInt8 nPlanes(0), nBitsPixel(0); + rStream.ReadInt16(nType).ReadInt16(nWidth).ReadInt16(nHeight) + .ReadInt16(nWidthBytes).ReadUChar(nPlanes).ReadUChar(nBitsPixel); + rStream.Seek(nHdrStart + nHeaderSize); + + if (!rStream.good() || nType != 0 || nPlanes != 1 || nBitsPixel != 1 + || nWidth <= 0 || nHeight <= 0 || nWidthBytes <= 0) + { + SAL_WARN("emfio", "\tUnsupported Bitmap16 (Type=" << nType + << ", Planes=" << int(nPlanes) + << ", BitsPixel=" << int(nBitsPixel) + << ", " << nWidth << "x" << nHeight << ")"); + return Bitmap(); + } + + const sal_uInt32 nMinStride = (o3tl::make_unsigned(nWidth) + 7) / 8; + if (o3tl::make_unsigned(nWidthBytes) < nMinStride) + return Bitmap(); + + const sal_uInt64 nBitsSize = o3tl::make_unsigned(nWidthBytes) * o3tl::make_unsigned(nHeight); + if (nBitsSize > rStream.remainingSize()) + return Bitmap(); + + std::vector aBits(nBitsSize, 0); + if (rStream.ReadBytes(aBits.data(), aBits.size()) != aBits.size()) + return Bitmap(); + + BitmapPalette aPalette(2); + aPalette[0] = BitmapColor(COL_WHITE); + aPalette[1] = BitmapColor(COL_BLACK); + Bitmap aBmp(Size(nWidth, nHeight), vcl::PixelFormat::N8_BPP, &aPalette); + BitmapScopedWriteAccess pAccess(aBmp); + if (!pAccess) + return Bitmap(); + + for (sal_Int16 y = 0; y < nHeight; ++y) + { + const sal_uInt8* pRow = aBits.data() + o3tl::make_unsigned(y) * o3tl::make_unsigned(nWidthBytes); + Scanline pScan = pAccess->GetScanline(y); + for (sal_Int16 x = 0; x < nWidth; ++x) + { + // Bit 7 of byte 0 is the leftmost pixel. + const sal_uInt8 nMask = sal_uInt8(0x80) >> (x & 7); + pAccess->SetPixelOnData(pScan, x, BitmapColor((pRow[x >> 3] & nMask) ? 1 : 0)); + } + } + return aBmp; + } } namespace emfio @@ -986,7 +1048,6 @@ namespace emfio case W_META_DIBCREATEPATTERNBRUSH: { Bitmap aBmp; - sal_uInt32 nRed(0), nGreen(0), nBlue(0), nCount(1); sal_uInt16 nStyle(0), nColorUsage(0); if (nRecordSize < 5) @@ -994,34 +1055,41 @@ namespace emfio mpInputStream->ReadUInt16( nStyle ).ReadUInt16( nColorUsage ); BrushStyle eStyle = static_cast(nStyle); SAL_INFO( "emfio", "\t\t Style:" << nStyle << ", ColorUsage: " << nColorUsage ); - if ( eStyle == BrushStyle::BS_PATTERN ) // TODO tdf#142625 Add support for pattern + // Per [MS-WMF] 2.3.4.8, BS_PATTERN means the Target is a + // Bitmap16 and other styles mean a DIB. In practice many + // generators write a DIB even with Style == BS_PATTERN, so + // peek at the leading DWORD: a known DIB header size means + // a DIB; otherwise fall back to Bitmap16. + bool bIsDib = true; + if ( eStyle == BrushStyle::BS_PATTERN ) { - SAL_WARN( "emfio", "\tTODO: Pattern brush style is not supported." ); - CreateObject(); - break; + // The leading DWORD of a DIB header is its own size, + // and only a small set of values is valid: + // 12 BITMAPCOREHEADER + // 40 BITMAPINFOHEADER + // 52 BITMAPV2INFOHEADER (Adobe extension) + // 56 BITMAPV3INFOHEADER (Adobe extension) + // 64 OS22XBITMAPHEADER (OS/2 2.x) + // 108 BITMAPV4HEADER + // 124 BITMAPV5HEADER + // A leading DWORD outside this set means the Target is + // a Bitmap16, not a DIB. + sal_uInt32 nProbe(0); + const sal_uInt64 nProbePos = mpInputStream->Tell(); + mpInputStream->ReadUInt32( nProbe ); + mpInputStream->Seek( nProbePos ); + bIsDib = (nProbe == 12 || nProbe == 40 || nProbe == 52 + || nProbe == 56 || nProbe == 64 || nProbe == 108 + || nProbe == 124); } - if ( !ReadDIB( aBmp, *mpInputStream, false ) ) + if ( !bIsDib ) + aBmp = CreateBitmap16( *mpInputStream, 10 ); + else if ( !ReadDIB( aBmp, *mpInputStream, false ) ) SAL_WARN( "emfio", "\tTODO Read DIB failed. Interrupting processing whole image. Please report bug report." ); - if ( !aBmp.IsEmpty() ) - { - BitmapScopedReadAccess pBmp(aBmp); - for ( tools::Long y = 0, nHeight = pBmp->Height(); y < nHeight; y++ ) - { - for ( tools::Long x = 0, nWidth = pBmp->Width(); x < nWidth; x++ ) - { - const BitmapColor aColor( pBmp->GetColor( y, x ) ); - - nRed += aColor.GetRed(); - nGreen += aColor.GetGreen(); - nBlue += aColor.GetBlue(); - } - } - nCount = pBmp->Height() * pBmp->Width(); - if ( !nCount ) - nCount++; - } - Color aColor( static_cast( nRed / nCount ), static_cast( nGreen / nCount ), static_cast( nBlue / nCount ) ); - CreateObject(std::make_unique( aColor, false )); + if ( aBmp.IsEmpty() ) + CreateObject(); + else + CreateObject(std::make_unique( aBmp )); } break; @@ -1045,11 +1113,11 @@ namespace emfio if (nRecordSize != 2u * nNumberOfEntries + 5u) bRecordOk = false; SAL_INFO("emfio", "\t\t Start 0x" << std::hex << nStart << std::dec << ", Number of entries: " << nNumberOfEntries); - sal_uInt32 nPalleteEntry; std::vector< Color > aPaletteColors; - for (sal_uInt16 i = 0; i < nNumberOfEntries; ++i) + for (sal_uInt16 i = 0; i < nNumberOfEntries && mpInputStream->good(); ++i) { //PALETTEENTRY: Values, Blue, Green, Red + sal_uInt32 nPalleteEntry(0); mpInputStream->ReadUInt32( nPalleteEntry ); SAL_INFO("emfio", "\t\t " << i << ". Palette entry: " << std::setw(10) << std::showbase <(nPalleteEntry), static_cast(nPalleteEntry >> 8), static_cast(nPalleteEntry >> 16)); @@ -1067,8 +1135,14 @@ namespace emfio case W_META_CREATEPATTERNBRUSH: { - SAL_WARN( "emfio", "TODO: Not implemented. Please fill the bug report" ); - CreateObject(std::make_unique( COL_WHITE, false )); + // [MS-WMF] 2.3.4.4: Pattern is a 32-byte legacy BITMAP + // struct (with bmBits placeholder + reserved padding) + // followed by the actual bits. + Bitmap aBmp = CreateBitmap16( *mpInputStream, 32 ); + if ( aBmp.IsEmpty() ) + CreateObject(std::make_unique( COL_WHITE, false )); + else + CreateObject(std::make_unique( aBmp )); } break; @@ -1093,11 +1167,16 @@ namespace emfio { if (nRecordSize != 7) bRecordOk = false; - sal_uInt16 nBrushStyle = 0; + sal_uInt16 nBrushStyle = 0; mpInputStream->ReadUInt16( nBrushStyle ); BrushStyle eBrushStyle = static_cast(nBrushStyle); - CreateObject(std::make_unique( ReadColor(), ( eBrushStyle == BrushStyle::BS_NULL ) )); - SAL_WARN_IF( (eBrushStyle != BrushStyle::BS_SOLID) && (eBrushStyle != BrushStyle::BS_NULL), "emfio", "TODO: Brush style not implemented. Please fill the bug report" ); + Color aColor = ReadColor(); + sal_uInt16 nHatch(0); + mpInputStream->ReadUInt16( nHatch ); + if (eBrushStyle == BrushStyle::BS_HATCHED) + CreateObject(std::make_unique( aColor, mapWindowsHatch(nHatch, aColor) )); + else + CreateObject(std::make_unique( aColor, eBrushStyle == BrushStyle::BS_NULL )); } break; @@ -1264,18 +1343,19 @@ namespace emfio mpInputStream->ReadBytes(pData.get(), nEscLen); nCheckSum = rtl_crc32(nCheckSum, pData.get(), nEscLen); } - if (nCheck == nCheckSum) + if (comphelper::IsFuzzing() || nCheck == nCheckSum) { switch (nEsc) { case PRIVATE_ESCAPE_UNICODE: { // we will use text instead of polygons only if we have the correct font - if (Application::GetDefaultDevice()->IsFontAvailable( - GetFont().GetFamilyName())) + if (comphelper::IsFuzzing() + || Application::GetDefaultDevice()->IsFontAvailable( + GetFont().GetFamilyName())) { Point aPt; - sal_uInt32 nStringLen, nDXCount; + sal_uInt32 nStringLen(0), nDXCount(0); KernArray aDXAry; SvMemoryStream aMemoryStream(nEscLen); aMemoryStream.WriteBytes(pData.get(), nEscLen); @@ -1294,6 +1374,8 @@ namespace emfio OUString aString = read_uInt16s_ToOUString( aMemoryStream, nStringLen); aMemoryStream.ReadUInt32(nDXCount); + if (nDXCount < o3tl::make_unsigned(aString.getLength())) + nDXCount = 0; if ((static_cast(nDXCount) * sizeof(sal_Int32)) >= (nEscLen - aMemoryStream.Tell())) @@ -1302,7 +1384,7 @@ namespace emfio aDXAry.resize(nDXCount); for (sal_uInt32 i = 0; i < nDXCount; i++) { - sal_Int32 val; + sal_Int32 val(0); aMemoryStream.ReadInt32(val); aDXAry[i] = val; } @@ -1390,8 +1472,17 @@ namespace emfio } break; - case W_META_SETRELABS: case W_META_SETPOLYFILLMODE: + { + if ((nRecordSize != 4) && (nRecordSize != 5)) + bRecordOk = false; + sal_uInt16 nDat = 0; + mpInputStream->ReadUInt16( nDat ); + SetPolyFillMode( nDat ); + } + break; + + case W_META_SETRELABS: case W_META_SETSTRETCHBLTMODE: case W_META_SETTEXTCHAREXTRA: case W_META_SETTEXTJUSTIFICATION: @@ -1476,6 +1567,8 @@ namespace emfio // inch mpInputStream->ReadUInt16( mnUnitsPerInch ); + SAL_WARN_IF(!mnUnitsPerInch, "emfio", "Invalid WMF: mnUnitsPerInch is 0"); + // reserved mpInputStream->SeekRel( 4 ); @@ -1542,7 +1635,7 @@ namespace emfio SAL_INFO("emfio", "WMF size w: " << aWMFSize.Width() << " h: " << aWMFSize.Height()); Size aDevExt( 10000, 10000 ); - if( ( std::abs( aWMFSize.Width() ) > 1 ) && ( std::abs( aWMFSize.Height() ) > 1 ) ) + if( ( std::abs( aWMFSize.Width() ) > 1 ) && ( std::abs( aWMFSize.Height() ) > 1 ) && mnUnitsPerInch ) { const double fFrac = 1.0 / mnUnitsPerInch; MapMode aWMFMap( MapUnit::MapInch, Point(), fFrac, fFrac ); diff --git a/eventattacher/source/eventattacher.cxx b/eventattacher/source/eventattacher.cxx index 76cae1103862..a7f2e640769b 100644 --- a/eventattacher/source/eventattacher.cxx +++ b/eventattacher/source/eventattacher.cxx @@ -123,7 +123,7 @@ Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, { Any aRet; - // Check if to firing or approveFiring has to be called + // Check if firing or approveFiring has to be called Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName ); bool bApproveFiring = false; if( !xMethod.is() ) @@ -385,7 +385,7 @@ Reference< XTypeConverter > EventAttacherImpl::getConverter() namespace { -// Implementation of an EventAttacher-related AllListeners, which brings +// Implementation of an EventAttacher-related AllListener, which brings // a few Events to a general AllListener class FilterAllListenerImpl : public WeakImplHelper< XAllListener > { @@ -737,7 +737,7 @@ void EventAttacherImpl::removeListener if( !xIntrospection.is() ) throw IntrospectionException(); - //Inspect Introspection + // Inspect Introspection Any aObjAny( &xObject, cppu::UnoType::get()); Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny ); if( !xAccess.is() ) diff --git a/extensions/CustomTarget_automationtest.mk b/extensions/CustomTarget_automationtest.mk deleted file mode 100644 index b6de71b74211..000000000000 --- a/extensions/CustomTarget_automationtest.mk +++ /dev/null @@ -1,29 +0,0 @@ -# -*- 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_CustomTarget_CustomTarget,extensions/automationtest)) - -extensions_AUTOMATIONTESTDIR := $(gb_CustomTarget_workdir)/extensions/automationtest - -extensions_AUTOMATIONTESTLOG1 := $(extensions_AUTOMATIONTESTDIR)/automationtest.1.log -extensions_AUTOMATIONTESTLOG2 := $(extensions_AUTOMATIONTESTDIR)/automationtest.2.log - -$(call gb_CustomTarget_get_target,extensions/automationtest) : \ - $(SRCDIR)/extensions/qa/ole/automationtest.vbs \ - | $(extensions_AUTOMATIONTESTDIR)/.dir - $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),VBS,1) - $(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),VBS) - SAL_LOG=+INFO.extensions.olebridge+WARN $(INSTDIR)/program/soffice 2>$(extensions_AUTOMATIONTESTLOG1) & - sleep 10 - $(call gb_Helper_abbreviate_dirs, \ - cscript -nologo $(SRCDIR)/extensions/qa/ole/automationtest.vbs $(SRCDIR)) >$(extensions_AUTOMATIONTESTLOG2) || \ - (cat $(extensions_AUTOMATIONTESTLOG1) $(extensions_AUTOMATIONTESTLOG2) && exit 1) - $(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),VBS) - -# vim:set shiftwidth=4 tabstop=4 noexpandtab: diff --git a/extensions/Module_extensions.mk b/extensions/Module_extensions.mk index cfd7cda7d2c2..b1cc40d8dd79 100644 --- a/extensions/Module_extensions.mk +++ b/extensions/Module_extensions.mk @@ -90,10 +90,6 @@ $(eval $(call gb_Module_add_targets,extensions,\ Library_oleautobridge \ )) -# $(eval $(call gb_Module_add_subsequentcheck_targets,extensions,\ -# CustomTarget_automationtest \ -# )) - endif # WNT ifeq ($(OS),MACOSX) diff --git a/extensions/qa/ole/automationtest.vbs b/extensions/qa/ole/automationtest.vbs deleted file mode 100644 index 9b5dff05e957..000000000000 --- a/extensions/qa/ole/automationtest.vbs +++ /dev/null @@ -1,132 +0,0 @@ -' -*- tab-width: 4; indent-tabs-mode: nil -*- - -If WScript.Arguments.Count <> 1 Then - WScript.Echo "Pass $(SRCDIR) as parameter" - WScript.Quit(1) -End If - -srcdir = WScript.Arguments.Item(0) - -exitStatus = 0 - -testCounter = 0 -okCounter = 0 - -Sub ExitWithReport - If okCounter <> testCounter Then - exitStatus = 1 - End If - WScript.Echo "OK (" + CStr(okCounter) + ")" - WScript.Quit(exitstatus) -End Sub - -Sub CheckFatal(expr) - testCounter = testCounter + 1 - If Not Eval(expr) Then - WScript.Echo "FAIL: " & expr - ExitWithReport - Else - WScript.Echo "PASS: " & expr - okCounter = okCounter + 1 - End If -End Sub - -Sub Check(expr) - testCounter = testCounter + 1 - If Not Eval(expr) Then - WScript.Echo "FAIL: " & expr - Else - WScript.Echo "PASS: " & expr - okCounter = okCounter + 1 - End If -End Sub - -Sub CheckIfExpected(expr, expected) - testCounter = testCounter + 1 - actual = Eval(expr) - If actual <> expected Then - WScript.Echo "FAIL: Value of '" & expr & "' was expected to be '" & CStr(expected) & "', but was " & CStr(actual) - Else - WScript.Echo "PASS: " & expr & " == " & CStr(expected) - okCounter = okCounter + 1 - End If -End Sub - -Sub CheckErrorFatal(test) - testCounter = testCounter + 1 - Execute(test) - If Err.Number <> 0 Then - WScript.Echo "FAIL: " & test - WScript.Echo "ERROR: " & Err.Description - ExitWithReport - Else - WScript.Echo "PASS: " & test - okCounter = okCounter + 1 - End If -End Sub - -Sub CheckError(test) - testCounter = testCounter + 1 - Execute(test) - If Err.Number <> 0 Then - WScript.Echo "FAIL: " & test - WScript.Echo "ERROR: " & Err.Description - Else - WScript.Echo "PASS: " & test - okCounter = okCounter + 1 - End If -End Sub - -WScript.Echo "Running Automation client tests" - -On Error Resume Next - -' FIXME: How can we ever make this work specifically with the -' LibreOffice in instdir, when WScript.CreateObject() wants the -' symbolic name that it then looks up from the Registry to find the -' CLSID of the class? - -CheckErrorFatal "Set writer = WScript.CreateObject(""Writer.Application"")" -CheckErrorFatal "writer.Visible = True" -CheckErrorFatal "writer.Caption = ""=== This is Writer ===""" -CheckErrorFatal "writer.ShowMe" - -CheckErrorFatal "Set documents = writer.Documents" - -' Open two randomly chosen documents -CheckErrorFatal "Set d1 = documents.Open(""" & srcdir & "/sw/qa/extras/ww8export/data/n325936.doc"")" -CheckErrorFatal "Set d2 = documents.Open(""" & srcdir & "/sw/qa/extras/ww8export/data/bnc636128.doc"")" - -CheckErrorFatal "n1 = d1.FullName" -CheckErrorFatal "n2 = d2.FullName" - -CheckIfExpected "n1", "n325936.doc" -CheckIfExpected "n2", "bnc636128.doc" - -CheckErrorFatal "Set c1 = d1.Content" -CheckErrorFatal "Set c2 = d2.Content" - -' The range of characters in these documents -CheckIfExpected "c1.Start", 0 -CheckIfExpected "c1.End", 4 -CheckIfExpected "c2.Start", 0 -CheckIfExpected "c2.End", 42 - -' Check number of paragraphs in each document -CheckErrorFatal "Set p1 = d1.Paragraphs" -nparas = 0 -For Each i in p1 - nparas = nparas + 1 -Next -CheckIfExpected "nparas", 1 - -CheckErrorFatal "Set p2 = d2.Paragraphs" -nparas = 0 -For Each i in p2 - nparas = nparas + 1 -Next -CheckIfExpected "nparas", 1 - -CheckErrorFatal "writer.Quit" - -ExitWithReport diff --git a/extensions/source/abpilot/abpfinalpage.cxx b/extensions/source/abpilot/abpfinalpage.cxx index 2821222e31d5..3568bef27c5f 100644 --- a/extensions/source/abpilot/abpfinalpage.cxx +++ b/extensions/source/abpilot/abpfinalpage.cxx @@ -192,10 +192,7 @@ namespace abp m_xDuplicateNameError->set_visible(!bValidName && !bEmptyName); } - IMPL_LINK_NOARG( FinalPage, OnEntryNameModified, weld::Entry&, void ) - { - implCheckName(); - } + IMPL_LINK_NOARG(FinalPage, OnEntryNameModified, weld::TextWidget&, void) { implCheckName(); } IMPL_LINK_NOARG( FinalPage, OnComboNameModified, weld::ComboBox&, void ) { diff --git a/extensions/source/abpilot/abpfinalpage.hxx b/extensions/source/abpilot/abpfinalpage.hxx index aa45b7cb55ca..922e63456c3e 100644 --- a/extensions/source/abpilot/abpfinalpage.hxx +++ b/extensions/source/abpilot/abpfinalpage.hxx @@ -24,8 +24,11 @@ #include #include +#include +#include #include #include +#include namespace abp { @@ -62,7 +65,7 @@ namespace abp // OImportPage overridables virtual bool canAdvance() const override; - DECL_LINK(OnEntryNameModified, weld::Entry&, void); + DECL_LINK(OnEntryNameModified, weld::TextWidget&, void); DECL_LINK(OnComboNameModified, weld::ComboBox&, void); DECL_LINK(OnRegister, weld::Toggleable&, void); DECL_LINK(OnEmbed, weld::Toggleable&, void); diff --git a/extensions/source/abpilot/abspilot.cxx b/extensions/source/abpilot/abspilot.cxx index 5f80f3014535..0bafcc5ceacb 100644 --- a/extensions/source/abpilot/abspilot.cxx +++ b/extensions/source/abpilot/abspilot.cxx @@ -27,7 +27,7 @@ #include "tableselectionpage.hxx" #include #include -#include +#include #include #include "abpfinalpage.hxx" #include "fieldmappingpage.hxx" diff --git a/extensions/source/abpilot/admininvokationimpl.cxx b/extensions/source/abpilot/admininvokationimpl.cxx index 20f290f9d5ce..5352db37afb0 100644 --- a/extensions/source/abpilot/admininvokationimpl.cxx +++ b/extensions/source/abpilot/admininvokationimpl.cxx @@ -28,7 +28,8 @@ #include #include #include -#include +#include +#include namespace abp { diff --git a/extensions/source/abpilot/admininvokationpage.hxx b/extensions/source/abpilot/admininvokationpage.hxx index 3d4f676e2d9a..84fedc6aa353 100644 --- a/extensions/source/abpilot/admininvokationpage.hxx +++ b/extensions/source/abpilot/admininvokationpage.hxx @@ -21,6 +21,8 @@ #include "abspage.hxx" +#include +#include namespace abp { diff --git a/extensions/source/abpilot/datasourcehandling.cxx b/extensions/source/abpilot/datasourcehandling.cxx index 46c0f3410bff..2ec1be447797 100644 --- a/extensions/source/abpilot/datasourcehandling.cxx +++ b/extensions/source/abpilot/datasourcehandling.cxx @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/extensions/source/abpilot/fieldmappingimpl.cxx b/extensions/source/abpilot/fieldmappingimpl.cxx index 32d97af51fa8..f3ba7f946860 100644 --- a/extensions/source/abpilot/fieldmappingimpl.cxx +++ b/extensions/source/abpilot/fieldmappingimpl.cxx @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -156,7 +156,7 @@ namespace abp // create a config node for this OConfigurationTreeRoot aDriverFieldAliasing = OConfigurationTreeRoot::createWithComponentContext( - _rxContext, sDriverAliasesNodeName, -1, OConfigurationTreeRoot::CM_READONLY); + _rxContext, sDriverAliasesNodeName, OConfigurationTreeRoot::CM_READONLY); // loop through all programmatic pairs DBG_ASSERT( 0 == std::size( pMappingProgrammatics ) % 2, diff --git a/extensions/source/abpilot/fieldmappingpage.hxx b/extensions/source/abpilot/fieldmappingpage.hxx index 2147c68d346c..2949ac3b8bf1 100644 --- a/extensions/source/abpilot/fieldmappingpage.hxx +++ b/extensions/source/abpilot/fieldmappingpage.hxx @@ -20,7 +20,9 @@ #pragma once #include "abspage.hxx" -#include + +#include +#include namespace abp { diff --git a/extensions/source/abpilot/tableselectionpage.hxx b/extensions/source/abpilot/tableselectionpage.hxx index a7513a4301ef..04ce55f2d20c 100644 --- a/extensions/source/abpilot/tableselectionpage.hxx +++ b/extensions/source/abpilot/tableselectionpage.hxx @@ -21,7 +21,6 @@ #include "abspage.hxx" #include -#include namespace abp { diff --git a/extensions/source/abpilot/typeselectionpage.cxx b/extensions/source/abpilot/typeselectionpage.cxx index cfd206e0bd34..6e9a0201f207 100644 --- a/extensions/source/abpilot/typeselectionpage.cxx +++ b/extensions/source/abpilot/typeselectionpage.cxx @@ -23,7 +23,7 @@ #include #include #include -#include + #include #include diff --git a/extensions/source/abpilot/typeselectionpage.hxx b/extensions/source/abpilot/typeselectionpage.hxx index 204c96341f1d..fa1bd069dcdf 100644 --- a/extensions/source/abpilot/typeselectionpage.hxx +++ b/extensions/source/abpilot/typeselectionpage.hxx @@ -21,7 +21,8 @@ #include "abspage.hxx" #include "addresssettings.hxx" -#include + +#include namespace abp { diff --git a/extensions/source/abpilot/unodialogabp.cxx b/extensions/source/abpilot/unodialogabp.cxx index b8d78e81e888..b9b30f5da428 100644 --- a/extensions/source/abpilot/unodialogabp.cxx +++ b/extensions/source/abpilot/unodialogabp.cxx @@ -94,8 +94,8 @@ namespace abp // -> call the execute method of the XExecutableDialog static_cast< XExecutableDialog* >( this )->execute(); - // result interest not really ... - // We show this dialog one times only! + // result is not really interesting ... + // We show this dialog once only! // User has one chance to accept it or not. // (or he can start it again by using wizard-menu!) // So we should deregister it on our general job execution service by using right protocol parameters. diff --git a/extensions/source/activex/StdAfx2.cxx b/extensions/source/activex/StdAfx2.cxx index c2df5c5c0ef6..08b26532f3be 100644 --- a/extensions/source/activex/StdAfx2.cxx +++ b/extensions/source/activex/StdAfx2.cxx @@ -17,9 +17,9 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -// stdafx1.cpp : source file that includes just the standard includes -// stdafx1.pch will be the pre-compiled header -// stdafx1.obj will contain the pre-compiled type information +// StdAfx2.cxx : source file that includes just the standard includes +// StdAfx2.pch will be the pre-compiled header +// StdAfx2.obj will contain the pre-compiled type information #include "StdAfx2.h" diff --git a/extensions/source/activex/StdAfx2.h b/extensions/source/activex/StdAfx2.h index b2ab095e91f3..8423f53576d2 100644 --- a/extensions/source/activex/StdAfx2.h +++ b/extensions/source/activex/StdAfx2.h @@ -17,7 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -// stdafx1.h : include file for standard system include files, +// StdAfx2.h : include file for standard system include files, // or project specific include files that are used frequently, // but are changed infrequently diff --git a/extensions/source/bibliography/bibview.cxx b/extensions/source/bibliography/bibview.cxx index 529935d916fb..c6183261516a 100644 --- a/extensions/source/bibliography/bibview.cxx +++ b/extensions/source/bibliography/bibview.cxx @@ -29,8 +29,9 @@ #include #include +#include #include -#include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::form; diff --git a/extensions/source/bibliography/datman.cxx b/extensions/source/bibliography/datman.cxx index dc33cf830b33..c783c12f4925 100644 --- a/extensions/source/bibliography/datman.cxx +++ b/extensions/source/bibliography/datman.cxx @@ -47,10 +47,10 @@ #include #include #include +#include #include #include #include -#include #include "datman.hxx" #include "bibresid.hxx" #include "bibmod.hxx" diff --git a/extensions/source/bibliography/framectr.cxx b/extensions/source/bibliography/framectr.cxx index ccfcc6ae9fd5..204bc9542b22 100644 --- a/extensions/source/bibliography/framectr.cxx +++ b/extensions/source/bibliography/framectr.cxx @@ -46,7 +46,8 @@ #include #include #include -#include +#include +#include #include #include diff --git a/extensions/source/bibliography/general.hxx b/extensions/source/bibliography/general.hxx index 891d1cbf3477..f832e396f775 100644 --- a/extensions/source/bibliography/general.hxx +++ b/extensions/source/bibliography/general.hxx @@ -22,9 +22,11 @@ #include #include -#include +#include +#include #include #include +#include #include #include #include "bibshortcuthandler.hxx" diff --git a/extensions/source/bibliography/toolbar.cxx b/extensions/source/bibliography/toolbar.cxx index 1533975f03d6..80724db26723 100644 --- a/extensions/source/bibliography/toolbar.cxx +++ b/extensions/source/bibliography/toolbar.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #include #include diff --git a/extensions/source/bibliography/toolbar.hxx b/extensions/source/bibliography/toolbar.hxx index 7b3404587d21..e98062daa31f 100644 --- a/extensions/source/bibliography/toolbar.hxx +++ b/extensions/source/bibliography/toolbar.hxx @@ -25,9 +25,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/extensions/source/dbpilots/commonpagesdbp.cxx b/extensions/source/dbpilots/commonpagesdbp.cxx index f3b0a18fa856..c4c276f57176 100644 --- a/extensions/source/dbpilots/commonpagesdbp.cxx +++ b/extensions/source/dbpilots/commonpagesdbp.cxx @@ -40,6 +40,7 @@ #include #include #include +#include namespace dbp { diff --git a/extensions/source/dbpilots/commonpagesdbp.hxx b/extensions/source/dbpilots/commonpagesdbp.hxx index 1bf98755b251..2fe898782a00 100644 --- a/extensions/source/dbpilots/commonpagesdbp.hxx +++ b/extensions/source/dbpilots/commonpagesdbp.hxx @@ -20,9 +20,12 @@ #pragma once #include "controlwizard.hxx" +#include #include +#include +#include #include -#include + #include namespace dbp diff --git a/extensions/source/dbpilots/controlwizard.hxx b/extensions/source/dbpilots/controlwizard.hxx index 18da64a382a1..2c2c574b7522 100644 --- a/extensions/source/dbpilots/controlwizard.hxx +++ b/extensions/source/dbpilots/controlwizard.hxx @@ -25,8 +25,9 @@ #include #include #include +#include +#include #include -#include #include #include "dbptypes.hxx" #include diff --git a/extensions/source/dbpilots/groupboxwiz.cxx b/extensions/source/dbpilots/groupboxwiz.cxx index bd28e08c50c9..eb40607ac331 100644 --- a/extensions/source/dbpilots/groupboxwiz.cxx +++ b/extensions/source/dbpilots/groupboxwiz.cxx @@ -263,7 +263,7 @@ namespace dbp implCheckMoveButtons(); } - IMPL_LINK_NOARG( ORadioSelectionPage, OnNameModified, weld::Entry&, void ) + IMPL_LINK_NOARG(ORadioSelectionPage, OnNameModified, weld::TextWidget&, void) { implCheckMoveButtons(); } @@ -391,7 +391,7 @@ namespace dbp m_xOptions->append_text(label); // remember the values ... can't set them directly in the settings without the explicit commit call - // so we need have a copy of the values + // so we need to have a copy of the values m_aUncommittedValues = rSettings.aValues; // select the first entry diff --git a/extensions/source/dbpilots/groupboxwiz.hxx b/extensions/source/dbpilots/groupboxwiz.hxx index a68ec578bc29..49f2410f14ff 100644 --- a/extensions/source/dbpilots/groupboxwiz.hxx +++ b/extensions/source/dbpilots/groupboxwiz.hxx @@ -22,7 +22,9 @@ #include "controlwizard.hxx" #include "commonpagesdbp.hxx" +#include #include +#include using vcl::WizardTypes::WizardState; using vcl::WizardTypes::CommitPageReason; @@ -98,7 +100,7 @@ namespace dbp DECL_LINK( OnMoveEntry, weld::Button&, void ); DECL_LINK(OnEntrySelected, weld::ItemView&, void); - DECL_LINK( OnNameModified, weld::Entry&, void ); + DECL_LINK(OnNameModified, weld::TextWidget&, void); void implCheckMoveButtons(); }; diff --git a/extensions/source/dbpilots/listcombowizard.hxx b/extensions/source/dbpilots/listcombowizard.hxx index 6ae3d320ec25..bf2d9df04f6c 100644 --- a/extensions/source/dbpilots/listcombowizard.hxx +++ b/extensions/source/dbpilots/listcombowizard.hxx @@ -23,6 +23,7 @@ #include "commonpagesdbp.hxx" #include +#include using vcl::WizardTypes::WizardState; using vcl::WizardTypes::CommitPageReason; diff --git a/extensions/source/ole/unoconversionutilities.hxx b/extensions/source/ole/unoconversionutilities.hxx index 746957525478..7274e6329cfc 100644 --- a/extensions/source/ole/unoconversionutilities.hxx +++ b/extensions/source/ole/unoconversionutilities.hxx @@ -81,7 +81,7 @@ extern std::unordered_map > ComPtrToWrapp // must be returned. extern std::unordered_map > UnoObjToWrapperMap; -// This function tries to the change the type of a value (contained in the Any) +// This function tries to change the type of a value (contained in the Any) // to the smallest possible that can hold the value. This is actually done only // for types of VT_I4 (see o2u_variantToAny). The reason is the following: // JavaScript passes integer values always as VT_I4. If there is a parameter or @@ -188,7 +188,7 @@ public: /* Return true means var contained a ValueObject, and it was successfully converted. - The result is in any. It an error occurred a BridgeRuntimeError will be thrown. + The result is in any. If an error occurred a BridgeRuntimeError will be thrown. */ bool convertValueObject( const VARIANTARG *var, Any& any); void dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type); @@ -600,7 +600,7 @@ void UnoConversionUtilities::variantToAny( const VARIANTARG* pArg, Any& rAny, throw IllegalArgumentException( "[automation bridge]UnoConversionUtilities:variantToAny\n" "The provided VARIANT of type\" " + OUString::number(static_cast(var.vt)) + - "\" is unappropriate for conversion!", Reference(), -1); + "\" is inappropriate for conversion!", Reference(), -1); } catch (const CannotConvertException &) { @@ -1008,7 +1008,7 @@ void UnoConversionUtilities::anyToVariant(VARIANT* pVariant, const Any& rAny) throw IllegalArgumentException( "[automation bridge]UnoConversionUtilities::anyToVariant\n" "The provided any of type\" " + rAny.getValueTypeName() + - "\" is unappropriate for conversion!", Reference(), -1); + "\" is inappropriate for conversion!", Reference(), -1); } } @@ -1672,7 +1672,7 @@ void UnoConversionUtilities::variantToAny( const VARIANT* pVariant, Any& rAny // implements all these interfaces. // This is only done if "pUnknown" is not already a UNO wrapper, // that is it is actually NOT a UNO object that was converted to a COM object. If it is an -// UNO wrapper than the original UNO object is being extracted, queried for "aType" (if +// UNO wrapper then the original UNO object is being extracted, queried for "aType" (if // it is no struct) and returned. template Any UnoConversionUtilities::createOleObjectWrapper(VARIANT* pVar, const Type& aType) @@ -1889,7 +1889,7 @@ Reference UnoConversionUtilities::createAdapter(const Sequence bool UnoConversionUtilities::convertValueObject( const VARIANTARG *var, Any& any) diff --git a/extensions/source/ole/unotypewrapper.cxx b/extensions/source/ole/unotypewrapper.cxx index 6ec58096e919..90e0a4f6f5b9 100644 --- a/extensions/source/ole/unotypewrapper.cxx +++ b/extensions/source/ole/unotypewrapper.cxx @@ -33,7 +33,7 @@ bool createUnoTypeWrapper(BSTR sTypeName, VARIANT * pVar) pObj->AddRef(); pVar->vt= VT_DISPATCH; pVar->pdispVal= CComQIPtr(pObj->GetUnknown()); - //now set the value, e.i. the name of the type + //now set the value, i.e. the name of the type CComQIPtr spType(pVar->pdispVal); OSL_ASSERT(spType); if (SUCCEEDED(spType->put_Name(sTypeName))) @@ -145,7 +145,7 @@ COM_DECLSPEC_NOTHROW STDMETHODIMP UnoTypeWrapper::put_Name(BSTR val) return S_OK; } -// (UnoTypeWrapper----------------------- +// IUnoTypeWrapper----------------------- COM_DECLSPEC_NOTHROW STDMETHODIMP UnoTypeWrapper::get_Name(BSTR *pVal) { Lock(); diff --git a/extensions/source/propctrlr/browserline.cxx b/extensions/source/propctrlr/browserline.cxx index 2471337b095a..3e5c3d9951b2 100644 --- a/extensions/source/propctrlr/browserline.cxx +++ b/extensions/source/propctrlr/browserline.cxx @@ -33,8 +33,7 @@ #include #include #include -#include -#include +#include namespace pcr { diff --git a/extensions/source/propctrlr/browserline.hxx b/extensions/source/propctrlr/browserline.hxx index d591262b69f6..f20471c93741 100644 --- a/extensions/source/propctrlr/browserline.hxx +++ b/extensions/source/propctrlr/browserline.hxx @@ -21,7 +21,10 @@ #include #include -#include +#include +#include +#include +#include namespace com::sun::star::inspection::PropertyLineElement { diff --git a/extensions/source/propctrlr/browserlistbox.hxx b/extensions/source/propctrlr/browserlistbox.hxx index 9f65c8136d78..f8292541d2e8 100644 --- a/extensions/source/propctrlr/browserlistbox.hxx +++ b/extensions/source/propctrlr/browserlistbox.hxx @@ -25,8 +25,9 @@ #include #include #include +#include +#include #include -#include #include #include diff --git a/extensions/source/propctrlr/browserview.hxx b/extensions/source/propctrlr/browserview.hxx index c14e41f0abb3..ff5181bc07f9 100644 --- a/extensions/source/propctrlr/browserview.hxx +++ b/extensions/source/propctrlr/browserview.hxx @@ -22,8 +22,8 @@ #include #include #include +#include #include -#include namespace pcr { diff --git a/extensions/source/propctrlr/cellbindinghandler.hxx b/extensions/source/propctrlr/cellbindinghandler.hxx index c627cc4fdfe0..8bb7da3603d7 100644 --- a/extensions/source/propctrlr/cellbindinghandler.hxx +++ b/extensions/source/propctrlr/cellbindinghandler.hxx @@ -48,7 +48,7 @@ protected: virtual OUString SAL_CALL getImplementationName() override; virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; - // XPropertyHandler overriables + // XPropertyHandler overridables virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& _rPropertyName) override; virtual void SAL_CALL setPropertyValue(const OUString& _rPropertyName, const css::uno::Any& _rValue) override; @@ -72,7 +72,7 @@ private: /** updates a property (UI) whose state depends on more than one other property ->actuatingPropertyChanged is called for certain properties in whose changes - we expressed interes (->getActuatingProperty). Now such a property change can + we expressed interest (->getActuatingProperty). Now such a property change can result in simple UI updates, for instance another property being enabled or disabled. However, it can also result in a more complex change: The current (UI) state might diff --git a/extensions/source/propctrlr/commoncontrol.cxx b/extensions/source/propctrlr/commoncontrol.cxx index 5fcca3a9aed6..1b0afd9e6e66 100644 --- a/extensions/source/propctrlr/commoncontrol.cxx +++ b/extensions/source/propctrlr/commoncontrol.cxx @@ -61,7 +61,7 @@ void CommonBehaviourControlHelper::notifyModifiedValue() void CommonBehaviourControlHelper::editChanged() { setModified(); } -IMPL_LINK_NOARG(CommonBehaviourControlHelper, EditModifiedHdl, weld::Entry&, void) +IMPL_LINK_NOARG(CommonBehaviourControlHelper, EditModifiedHdl, weld::TextWidget&, void) { editChanged(); } diff --git a/extensions/source/propctrlr/commoncontrol.hxx b/extensions/source/propctrlr/commoncontrol.hxx index d9191b66efcd..92d8888c73a1 100644 --- a/extensions/source/propctrlr/commoncontrol.hxx +++ b/extensions/source/propctrlr/commoncontrol.hxx @@ -25,10 +25,10 @@ #include #include #include +#include #include #include -#include -#include +#include class ColorListBox; class SvtCalendarBox; @@ -89,7 +89,7 @@ public: /// may be used by derived classes, they forward the event to the PropCtrListener DECL_LINK(ModifiedHdl, weld::ComboBox&, void); DECL_LINK(ColorModifiedHdl, ColorListBox&, void); - DECL_LINK(EditModifiedHdl, weld::Entry&, void); + DECL_LINK(EditModifiedHdl, weld::TextWidget&, void); DECL_LINK(MetricModifiedHdl, weld::MetricSpinButton&, void); DECL_LINK(FormattedModifiedHdl, weld::FormattedSpinButton&, void); DECL_LINK(TimeModifiedHdl, weld::FormattedSpinButton&, void); diff --git a/extensions/source/propctrlr/fontdialog.hxx b/extensions/source/propctrlr/fontdialog.hxx index 07d72a600f4d..a0bc3be5f346 100644 --- a/extensions/source/propctrlr/fontdialog.hxx +++ b/extensions/source/propctrlr/fontdialog.hxx @@ -23,7 +23,7 @@ #include #include #include - +#include namespace pcr { diff --git a/extensions/source/propctrlr/formcomponenthandler.cxx b/extensions/source/propctrlr/formcomponenthandler.cxx index b5d1c6a04ab8..b96bfb09060e 100644 --- a/extensions/source/propctrlr/formcomponenthandler.cxx +++ b/extensions/source/propctrlr/formcomponenthandler.cxx @@ -106,6 +106,7 @@ #include #include #include +#include #include #include diff --git a/extensions/source/propctrlr/formcomponenthandler.hxx b/extensions/source/propctrlr/formcomponenthandler.hxx index d28c893f3b74..b70becd92b1d 100644 --- a/extensions/source/propctrlr/formcomponenthandler.hxx +++ b/extensions/source/propctrlr/formcomponenthandler.hxx @@ -73,7 +73,7 @@ namespace pcr /// the string indicating a "default" (VOID) value in list-like controls OUString m_sDefaultValueString; - /// all properties to whose control's we added ->m_sDefaultValueString + /// all properties to whose controls we added ->m_sDefaultValueString std::set< OUString > m_aPropertiesWithDefListEntry; /// type of our component ComponentClassification m_eComponentClass; @@ -234,7 +234,7 @@ namespace pcr */ void impl_displaySQLError_nothrow( const ::dbtools::SQLExceptionInfo& _rErrorDescriptor ) const; - /** let's the user chose a selection of entries from a string list, and stores this + /** lets the user choose a selection of entries from a string list, and stores this selection in the given property @return if and only if the user successfully changed the property @@ -260,7 +260,7 @@ namespace pcr @precond we're inspecting (sub) database form @return - if and only if the user successfully enter master and slave fields + if and only if the user successfully entered master and slave fields */ bool impl_dialogLinkedFormFields_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; @@ -276,7 +276,7 @@ namespace pcr */ bool impl_dialogFormatting_nothrow( css::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; - /** executes a dialog which allows to the user to change the ImageURL property + /** executes a dialog which allows the user to change the ImageURL property of our component by browsing for an image file. @precond our component actually has an ImageURL property @@ -379,7 +379,7 @@ namespace pcr /** updates a property (UI) whose state depends on more than one other property ->actuatingPropertyChanged is called for certain properties in whose changes - we expressed interes (->getActuatingProperty). Now such a property change can + we expressed interest (->getActuatingProperty). Now such a property change can result in simple UI updates, for instance another property being enabled or disabled. However, it can also result in a more complex change: The current (UI) state might diff --git a/extensions/source/propctrlr/formlinkdialog.cxx b/extensions/source/propctrlr/formlinkdialog.cxx index d9ddbdb23076..6f0a164ffd2b 100644 --- a/extensions/source/propctrlr/formlinkdialog.cxx +++ b/extensions/source/propctrlr/formlinkdialog.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/extensions/source/propctrlr/formlinkdialog.hxx b/extensions/source/propctrlr/formlinkdialog.hxx index 855d5670a640..ff759617d5e7 100644 --- a/extensions/source/propctrlr/formlinkdialog.hxx +++ b/extensions/source/propctrlr/formlinkdialog.hxx @@ -19,8 +19,10 @@ #pragma once +#include #include -#include +#include +#include #include #include diff --git a/extensions/source/propctrlr/formmetadata.hxx b/extensions/source/propctrlr/formmetadata.hxx index 14b9a05a846a..cbf493672905 100644 --- a/extensions/source/propctrlr/formmetadata.hxx +++ b/extensions/source/propctrlr/formmetadata.hxx @@ -69,7 +69,7 @@ protected: virtual ~DefaultEnumRepresentation() override; protected: - // IPropertyEnumRepresentation implementqation + // IPropertyEnumRepresentation implementation virtual std::vector getDescriptions() const override; virtual void getValueFromDescription(const OUString& _rDescription, css::uno::Any& _out_rValue) const override; @@ -94,7 +94,7 @@ private: #define PROP_FLAG_ENUM 0x00000020 // the property is an enum property starting with 1 (note that this includes PROP_FLAG_ENUM) #define PROP_FLAG_ENUM_ONE 0x00000060 -// the property is "composeable", i.e. an intersection of property sets should expose it, if all elements do +// the property is "composable", i.e. an intersection of property sets should expose it, if all elements do #define PROP_FLAG_COMPOSEABLE 0x00000080 // the property is experimental, i.e. should not appear in the UI, // unless experimental properties are enabled by a configuration option diff --git a/extensions/source/propctrlr/genericpropertyhandler.cxx b/extensions/source/propctrlr/genericpropertyhandler.cxx index 1abc97c962f5..afb4d239c0a9 100644 --- a/extensions/source/propctrlr/genericpropertyhandler.cxx +++ b/extensions/source/propctrlr/genericpropertyhandler.cxx @@ -73,7 +73,7 @@ namespace pcr EnumRepresentation(const EnumRepresentation&) = delete; EnumRepresentation& operator=(const EnumRepresentation&) = delete; - // IPropertyEnumRepresentation implementqation + // IPropertyEnumRepresentation implementation virtual std::vector< OUString > getDescriptions() const override; virtual void getValueFromDescription( const OUString& _rDescription, css::uno::Any& _out_rValue ) const override; diff --git a/extensions/source/propctrlr/handlerhelper.cxx b/extensions/source/propctrlr/handlerhelper.cxx index bf56b1a666b2..5dc4f650badb 100644 --- a/extensions/source/propctrlr/handlerhelper.cxx +++ b/extensions/source/propctrlr/handlerhelper.cxx @@ -32,8 +32,7 @@ #include #include #include -#include -#include +#include #include diff --git a/extensions/source/propctrlr/inspectorhelpwindow.hxx b/extensions/source/propctrlr/inspectorhelpwindow.hxx index 4440949fad58..cc78c5844e78 100644 --- a/extensions/source/propctrlr/inspectorhelpwindow.hxx +++ b/extensions/source/propctrlr/inspectorhelpwindow.hxx @@ -20,7 +20,6 @@ #include #include -#include namespace pcr { diff --git a/extensions/source/propctrlr/listselectiondlg.hxx b/extensions/source/propctrlr/listselectiondlg.hxx index 6e4d611b02c2..ab5371b03044 100644 --- a/extensions/source/propctrlr/listselectiondlg.hxx +++ b/extensions/source/propctrlr/listselectiondlg.hxx @@ -20,8 +20,9 @@ #pragma once #include +#include #include -#include +#include #include diff --git a/extensions/source/propctrlr/newdatatype.cxx b/extensions/source/propctrlr/newdatatype.cxx index 66428ceb5f30..5ff402e405e2 100644 --- a/extensions/source/propctrlr/newdatatype.cxx +++ b/extensions/source/propctrlr/newdatatype.cxx @@ -66,7 +66,7 @@ namespace pcr { } - IMPL_LINK_NOARG(NewDataTypeDialog, OnNameModified, weld::Entry&, void) + IMPL_LINK_NOARG(NewDataTypeDialog, OnNameModified, weld::TextWidget&, void) { OUString sCurrentName = GetName(); bool bNameIsOK = ( !sCurrentName.isEmpty() ) diff --git a/extensions/source/propctrlr/newdatatype.hxx b/extensions/source/propctrlr/newdatatype.hxx index c9b0f84055e1..e145bfa65f25 100644 --- a/extensions/source/propctrlr/newdatatype.hxx +++ b/extensions/source/propctrlr/newdatatype.hxx @@ -19,9 +19,10 @@ #pragma once +#include #include #include -#include +#include #include #include @@ -45,7 +46,7 @@ namespace pcr OUString GetName() const { return m_xName->get_text(); } private: - DECL_LINK(OnNameModified, weld::Entry&, void); + DECL_LINK(OnNameModified, weld::TextWidget&, void); }; diff --git a/extensions/source/propctrlr/propcontroller.cxx b/extensions/source/propctrlr/propcontroller.cxx index 32a46510b38f..3d5523829084 100644 --- a/extensions/source/propctrlr/propcontroller.cxx +++ b/extensions/source/propctrlr/propcontroller.cxx @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/extensions/source/propctrlr/propcontroller.hxx b/extensions/source/propctrlr/propcontroller.hxx index 8def42fd1251..292decb28b86 100644 --- a/extensions/source/propctrlr/propcontroller.hxx +++ b/extensions/source/propctrlr/propcontroller.hxx @@ -37,8 +37,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/extensions/source/propctrlr/propertyeditor.hxx b/extensions/source/propctrlr/propertyeditor.hxx index 2562665cfe31..36bee84ae4b8 100644 --- a/extensions/source/propctrlr/propertyeditor.hxx +++ b/extensions/source/propctrlr/propertyeditor.hxx @@ -25,7 +25,7 @@ #include #include #include -#include + #include namespace pcr diff --git a/extensions/source/propctrlr/propertyhandler.cxx b/extensions/source/propctrlr/propertyhandler.cxx index 723f217dd337..dea795cb65f1 100644 --- a/extensions/source/propctrlr/propertyhandler.cxx +++ b/extensions/source/propctrlr/propertyhandler.cxx @@ -406,7 +406,7 @@ sal_Int16 PropertyHandler::impl_getDocumentMeasurementUnit_throw() const { ::utl::OConfigurationTreeRoot aConfigTree( ::utl::OConfigurationTreeRoot::createWithComponentContext( - m_xContext, sConfigurationLocation, -1, + m_xContext, sConfigurationLocation, ::utl::OConfigurationTreeRoot::CM_READONLY)); sal_Int32 nUnitAsInt = sal_Int32(FieldUnit::NONE); aConfigTree.getNodeValue(sConfigurationProperty) >>= nUnitAsInt; diff --git a/extensions/source/propctrlr/selectlabeldialog.cxx b/extensions/source/propctrlr/selectlabeldialog.cxx index 13a697ad737e..a22667c3ca53 100644 --- a/extensions/source/propctrlr/selectlabeldialog.cxx +++ b/extensions/source/propctrlr/selectlabeldialog.cxx @@ -36,6 +36,7 @@ #include #include #include +#include namespace pcr { diff --git a/extensions/source/propctrlr/selectlabeldialog.hxx b/extensions/source/propctrlr/selectlabeldialog.hxx index 36a30753c556..df7330160c72 100644 --- a/extensions/source/propctrlr/selectlabeldialog.hxx +++ b/extensions/source/propctrlr/selectlabeldialog.hxx @@ -19,9 +19,12 @@ #pragma once +#include #include +#include #include -#include +#include + #include namespace pcr diff --git a/extensions/source/propctrlr/standardcontrol.cxx b/extensions/source/propctrlr/standardcontrol.cxx index 379b484cb9ca..375cd24ded4f 100644 --- a/extensions/source/propctrlr/standardcontrol.cxx +++ b/extensions/source/propctrlr/standardcontrol.cxx @@ -781,7 +781,7 @@ namespace pcr m_xOk->connect_clicked(LINK(this, OMultilineEditControl, ButtonHandler)); } - IMPL_LINK_NOARG(OMultilineEditControl, TextViewModifiedHdl, weld::TextView&, void) + IMPL_LINK_NOARG(OMultilineEditControl, TextViewModifiedHdl, weld::TextWidget&, void) { // tdf#139070 during editing update the entry to look like how it will // look once editing is finished so that the default behaviour of vcl diff --git a/extensions/source/propctrlr/standardcontrol.hxx b/extensions/source/propctrlr/standardcontrol.hxx index fcf996bcbb54..702c974b14ff 100644 --- a/extensions/source/propctrlr/standardcontrol.hxx +++ b/extensions/source/propctrlr/standardcontrol.hxx @@ -28,11 +28,15 @@ #include #include #include +#include +#include +#include #include #include #include #include #include +#include namespace pcr { @@ -374,7 +378,7 @@ namespace pcr GetStringListValue() const; DECL_LINK(ButtonHandler, weld::Button&, void); - DECL_LINK(TextViewModifiedHdl, weld::TextView&, void); + DECL_LINK(TextViewModifiedHdl, weld::TextWidget&, void); void CheckEntryTextViewMisMatch(); diff --git a/extensions/source/propctrlr/taborder.cxx b/extensions/source/propctrlr/taborder.cxx index 1b292bccb175..ede2708485cf 100644 --- a/extensions/source/propctrlr/taborder.cxx +++ b/extensions/source/propctrlr/taborder.cxx @@ -33,6 +33,7 @@ #include #include #include +#include namespace pcr { diff --git a/extensions/source/propctrlr/taborder.hxx b/extensions/source/propctrlr/taborder.hxx index 934bfd39f52d..a92c0d7d0ff6 100644 --- a/extensions/source/propctrlr/taborder.hxx +++ b/extensions/source/propctrlr/taborder.hxx @@ -24,9 +24,10 @@ #include #include +#include #include #include -#include +#include namespace pcr { diff --git a/extensions/source/propctrlr/usercontrol.hxx b/extensions/source/propctrlr/usercontrol.hxx index 267bc263b9fc..174ab90027e9 100644 --- a/extensions/source/propctrlr/usercontrol.hxx +++ b/extensions/source/propctrlr/usercontrol.hxx @@ -22,6 +22,8 @@ #include "commoncontrol.hxx" #include #include +#include +#include #include #include diff --git a/extensions/source/propctrlr/xsdvalidationpropertyhandler.cxx b/extensions/source/propctrlr/xsdvalidationpropertyhandler.cxx index 2296958293be..4e3d173cb12f 100644 --- a/extensions/source/propctrlr/xsdvalidationpropertyhandler.cxx +++ b/extensions/source/propctrlr/xsdvalidationpropertyhandler.cxx @@ -42,7 +42,6 @@ #include #include #include -#include #include #include diff --git a/extensions/source/scanner/grid.hxx b/extensions/source/scanner/grid.hxx index a4e826de2084..2690dbcea4ba 100644 --- a/extensions/source/scanner/grid.hxx +++ b/extensions/source/scanner/grid.hxx @@ -18,9 +18,10 @@ */ #pragma once +#include #include #include -#include +#include #include class GridWindow; diff --git a/extensions/source/scanner/sanedlg.cxx b/extensions/source/scanner/sanedlg.cxx index a8065b891424..758a008b2f38 100644 --- a/extensions/source/scanner/sanedlg.cxx +++ b/extensions/source/scanner/sanedlg.cxx @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include "sanedlg.hxx" @@ -752,7 +751,7 @@ IMPL_LINK_NOARG(SaneDlg, OptionsBoxSelectHdl, weld::ItemView&, void) } } -IMPL_LINK(SaneDlg, ModifyHdl, weld::Entry&, rEdit, void) +IMPL_LINK(SaneDlg, ModifyHdl, weld::TextWidget&, rEdit, void) { if( !mrSane.IsOpen() ) return; diff --git a/extensions/source/scanner/sanedlg.hxx b/extensions/source/scanner/sanedlg.hxx index d81da0d90cc9..450eccbde7d2 100644 --- a/extensions/source/scanner/sanedlg.hxx +++ b/extensions/source/scanner/sanedlg.hxx @@ -18,14 +18,17 @@ */ #pragma once +#include +#include #include #include #include +#include #include #include #include +#include #include -#include #include "sane.hxx" @@ -83,7 +86,7 @@ private: DECL_LINK( ClickBtnHdl, weld::Button&, void ); DECL_LINK( ToggleBtnHdl, weld::Toggleable&, void ); DECL_LINK( SelectHdl, weld::ComboBox&, void ); - DECL_LINK( ModifyHdl, weld::Entry&, void ); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); DECL_LINK( MetricValueModifyHdl, weld::MetricSpinButton&, void ); DECL_LINK( ValueModifyHdl, weld::ComboBox&, void ); DECL_LINK( ReloadSaneOptionsHdl, Sane&, void ); diff --git a/extensions/source/update/check/onlinecheck.cxx b/extensions/source/update/check/onlinecheck.cxx index af6ade879f40..ccfacc1b5932 100644 --- a/extensions/source/update/check/onlinecheck.cxx +++ b/extensions/source/update/check/onlinecheck.cxx @@ -18,7 +18,7 @@ */ #include -#include +#include #include "onlinecheck.hxx" @@ -36,7 +36,7 @@ extern "C" bool WNT_hasInternetConnection() bool fIsConnected = InternetGetConnectedStateExW( &dwFlags, szConnectionName, - SAL_N_ELEMENTS(szConnectionName), + std::size(szConnectionName), 0 ); return fIsConnected; diff --git a/extensions/source/update/check/updatecheckconfig.cxx b/extensions/source/update/check/updatecheckconfig.cxx index 718a33539523..52410d4b8242 100644 --- a/extensions/source/update/check/updatecheckconfig.cxx +++ b/extensions/source/update/check/updatecheckconfig.cxx @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -74,7 +75,7 @@ const char * const aUpdateEntryProperties[] = { OLD_VERSION }; -const sal_uInt32 nUpdateEntryProperties = SAL_N_ELEMENTS(aUpdateEntryProperties); +const sal_uInt32 nUpdateEntryProperties = static_cast(std::size(aUpdateEntryProperties)); css::uno::Any NamedValueByNameAccess::getValue(const char * pName) { diff --git a/extensions/source/update/ui/updatecheckui.cxx b/extensions/source/update/ui/updatecheckui.cxx index 87ede6e14d1a..e6b7e2de0252 100644 --- a/extensions/source/update/ui/updatecheckui.cxx +++ b/extensions/source/update/ui/updatecheckui.cxx @@ -36,7 +36,6 @@ #include #include #include -#include #include #include diff --git a/extensions/test/ole/DCOM/dcom_test/readme.txt b/extensions/test/ole/DCOM/dcom_test/readme.txt index 215d6f409f2c..cf5d51aced54 100644 --- a/extensions/test/ole/DCOM/dcom_test/readme.txt +++ b/extensions/test/ole/DCOM/dcom_test/readme.txt @@ -1,5 +1,5 @@ -The program creates the com.sun.star.Servicemanager on a remote machine: +The program creates the com.sun.star.ServiceManager on a remote machine: Set objServiceManager = CreateObject("com.sun.star.ServiceManager", "\\jl-1036") -creates a document and writes in it. \ No newline at end of file +creates a document and writes in it. diff --git a/extensions/uiconfig/sbibliography/menubar/menubar.xml b/extensions/uiconfig/sbibliography/menubar/menubar.xml index ed8bb50951cd..7a96bb7e6ad6 100644 --- a/extensions/uiconfig/sbibliography/menubar/menubar.xml +++ b/extensions/uiconfig/sbibliography/menubar/menubar.xml @@ -4,9 +4,9 @@ - + - + @@ -19,31 +19,31 @@ - + - - + + - - + + - + - + - - - - + + + + - - + + - + @@ -51,7 +51,7 @@ - + @@ -59,20 +59,19 @@ - + - - + - + - + diff --git a/extensions/uiconfig/spropctrlr/ui/controlfontdialog.ui b/extensions/uiconfig/spropctrlr/ui/controlfontdialog.ui index a56d7ad4cd4c..b2bec7ff360f 100644 --- a/extensions/uiconfig/spropctrlr/ui/controlfontdialog.ui +++ b/extensions/uiconfig/spropctrlr/ui/controlfontdialog.ui @@ -196,7 +196,7 @@ - reset + reset ok cancel help diff --git a/extensions/uiconfig/spropctrlr/ui/multiline.ui b/extensions/uiconfig/spropctrlr/ui/multiline.ui index dbe860a0bcd1..14e65a1878d2 100644 --- a/extensions/uiconfig/spropctrlr/ui/multiline.ui +++ b/extensions/uiconfig/spropctrlr/ui/multiline.ui @@ -26,6 +26,7 @@ True Multiline Editing True + diff --git a/external/Module_external.mk b/external/Module_external.mk index 830850e8b279..c94454a96707 100644 --- a/external/Module_external.mk +++ b/external/Module_external.mk @@ -17,6 +17,7 @@ $(eval $(call gb_Module_add_moduledirs,external,\ $(call gb_Helper_optional,BOOST,boost) \ $(call gb_Helper_optional,BOX2D,box2d) \ $(call gb_Helper_optional,BREAKPAD,breakpad) \ + $(call gb_Helper_optional,BROTLI,brotli) \ $(call gb_Helper_optional,BSH,beanshell) \ $(call gb_Helper_optional,BZIP2,bzip2) \ $(call gb_Helper_optional,CAIRO,cairo) \ @@ -44,6 +45,7 @@ $(eval $(call gb_Module_add_moduledirs,external,\ $(call gb_Helper_optional,GPGMEPP,gpgmepp) \ $(call gb_Helper_optional,GRAPHITE,graphite) \ $(call gb_Helper_optional,HARFBUZZ,harfbuzz) \ + $(call gb_Helper_optional,HIGHWAY,highway) \ $(call gb_Helper_optional,HSQLDB,hsqldb) \ $(call gb_Helper_optional,HUNSPELL,hunspell) \ $(call gb_Helper_optional,HYPHEN,hyphen) \ @@ -59,6 +61,7 @@ $(eval $(call gb_Module_add_moduledirs,external,\ $(call gb_Helper_optional,LIBEXTTEXTCAT,libexttextcat) \ $(call gb_Helper_optional,LIBFFI,libffi) \ $(call gb_Helper_optional,LIBGPGERROR,libgpg-error) \ + $(call gb_Helper_optional,LIBJXL,libjxl) \ $(call gb_Helper_optional,LIBLANGTAG,liblangtag) \ $(call gb_Helper_optional,LIBNUMBERTEXT,libnumbertext) \ $(call gb_Helper_optional,LIBPNG,libpng) \ @@ -66,7 +69,6 @@ $(eval $(call gb_Module_add_moduledirs,external,\ $(call gb_Helper_optional,LIBWEBP,libwebp) \ $(call gb_Helper_optional,LIBXML2,libxml2) \ $(call gb_Helper_optional,LIBXSLT,libxslt) \ - $(call gb_Helper_optional,LPSOLVE,lpsolve) \ $(call gb_Helper_optional,LIBTOMMATH,libtommath) \ $(call gb_Helper_optional,LXML,lxml) \ $(call gb_Helper_optional,LZMA,lzma) \ @@ -90,6 +92,7 @@ $(eval $(call gb_Module_add_moduledirs,external,\ $(call gb_Helper_optional,POPPLER,poppler) \ $(call gb_Helper_optional,POSTGRESQL,postgresql) \ $(call gb_Helper_optional,PYTHON,python3) \ + $(call gb_Helper_optional,QUICKJS,quickjs) \ $(call gb_Helper_optional,QXP,libqxp) \ $(call gb_Helper_optional,ZXCVBN,zxcvbn-c) \ $(call gb_Helper_optional,ZXING,zxing) \ diff --git a/external/afdko/StaticLibrary_afdko.mk b/external/afdko/StaticLibrary_afdko.mk index 607e84632989..dec589b45635 100644 --- a/external/afdko/StaticLibrary_afdko.mk +++ b/external/afdko/StaticLibrary_afdko.mk @@ -15,11 +15,14 @@ $(eval $(call gb_StaticLibrary_set_warnings_disabled,afdko)) $(eval $(call gb_StaticLibrary_set_generated_cxx_suffix,afdko,cpp)) +# c/shared/include must come before c/addfeatures/include so that the +# shared sources find their own pstoken.h. The addfeatures consumers of +# the other pstoken.h are patched to include it by relative path, see +# extern_addfeatures.patch. $(eval $(call gb_StaticLibrary_set_include,afdko,\ -I$(gb_UnpackedTarball_workdir)/afdko/c/shared/include \ -I$(gb_UnpackedTarball_workdir)/afdko/c/shared/resource \ - -I$(gb_UnpackedTarball_workdir)/afdko/c/shared/source/tx_shared \ - -I$(gb_UnpackedTarball_workdir)/afdko/c/makeotf \ + -I$(gb_UnpackedTarball_workdir)/afdko/c/addfeatures/include \ -I$(gb_UnpackedTarball_workdir)/afdko/a4/runtime/src \ $$(INCLUDE) \ )) @@ -29,113 +32,101 @@ $(eval $(call gb_StaticLibrary_use_externals,afdko,\ )) $(eval $(call gb_StaticLibrary_add_defs,afdko, \ - -DTC_EURO_SUPPORT=1 \ - -DTC_SUBR_SUPPORT=1 \ - -DTC_HINT_CHECK=1 \ -DANTLR4CPP_STATIC \ )) $(eval $(call gb_StaticLibrary_add_generated_cobjects,afdko,\ - UnpackedTarball/afdko/c/shared/source/absfont/absfont \ - UnpackedTarball/afdko/c/shared/source/absfont/absfont_afm \ - UnpackedTarball/afdko/c/shared/source/absfont/absfont_compare \ - UnpackedTarball/afdko/c/shared/source/absfont/absfont_desc \ - UnpackedTarball/afdko/c/shared/source/absfont/absfont_draw \ - UnpackedTarball/afdko/c/shared/source/absfont/absfont_dump \ - UnpackedTarball/afdko/c/shared/source/absfont/absfont_metrics \ - UnpackedTarball/afdko/c/shared/source/absfont/absfont_path \ - UnpackedTarball/afdko/c/shared/source/cfembed/cfembed \ - UnpackedTarball/afdko/c/shared/source/cffread/cffread \ - UnpackedTarball/afdko/c/shared/source/cffwrite/cffwrite \ - UnpackedTarball/afdko/c/shared/source/cffwrite/cffwrite_charset \ - UnpackedTarball/afdko/c/shared/source/cffwrite/cffwrite_dict \ - UnpackedTarball/afdko/c/shared/source/cffwrite/cffwrite_encoding \ - UnpackedTarball/afdko/c/shared/source/cffwrite/cffwrite_fdselect \ - UnpackedTarball/afdko/c/shared/source/cffwrite/cffwrite_sindex \ - UnpackedTarball/afdko/c/shared/source/cffwrite/cffwrite_subr \ - UnpackedTarball/afdko/c/shared/source/cffwrite/cffwrite_t2cstr \ - UnpackedTarball/afdko/c/shared/source/cffwrite/cffwrite_varstore \ - UnpackedTarball/afdko/c/shared/source/ctutil/ctutil \ - UnpackedTarball/afdko/c/shared/source/dynarr/dynarr \ - UnpackedTarball/afdko/c/shared/source/nameread/nameread \ - UnpackedTarball/afdko/c/shared/source/pdfwrite/pdfwrite \ - UnpackedTarball/afdko/c/shared/source/pstoken/pstoken \ - UnpackedTarball/afdko/c/shared/source/sfntread/sfntread \ - UnpackedTarball/afdko/c/shared/source/sfntwrite/sfntwrite \ - UnpackedTarball/afdko/c/shared/source/sha1/sha1 \ - UnpackedTarball/afdko/c/shared/source/support/canthappen \ - UnpackedTarball/afdko/c/shared/source/support/except \ - UnpackedTarball/afdko/c/shared/source/support/fixed \ - UnpackedTarball/afdko/c/shared/source/svgwrite/svgwrite \ - UnpackedTarball/afdko/c/shared/source/svread/svread \ - UnpackedTarball/afdko/c/shared/source/t1cstr/t1cstr \ - UnpackedTarball/afdko/c/shared/source/t1read/t1read \ - UnpackedTarball/afdko/c/shared/source/t1write/t1write \ - UnpackedTarball/afdko/c/shared/source/t2cstr/t2cstr \ - UnpackedTarball/afdko/c/shared/source/ttread/ttread \ - UnpackedTarball/afdko/c/shared/source/varread/varread \ - UnpackedTarball/afdko/c/shared/source/uforead/uforead \ - UnpackedTarball/afdko/c/shared/source/ufowrite/ufowrite \ - UnpackedTarball/afdko/c/shared/source/tx_shared/tx_shared \ -)) - -$(eval $(call gb_StaticLibrary_add_generated_cobjects,afdko,\ - UnpackedTarball/afdko/c/tx/source/tx \ -)) - -$(eval $(call gb_StaticLibrary_add_generated_cobjects,afdko,\ - UnpackedTarball/afdko/c/mergefonts/source/mergeFonts \ -)) - -$(eval $(call gb_StaticLibrary_add_generated_cobjects,afdko,\ - UnpackedTarball/afdko/c/makeotf/source/c_main \ - UnpackedTarball/afdko/c/makeotf/source/cb \ - UnpackedTarball/afdko/c/makeotf/source/cbpriv \ - UnpackedTarball/afdko/c/makeotf/source/fcdb \ - UnpackedTarball/afdko/c/makeotf/source/file \ - UnpackedTarball/afdko/c/makeotf/source/mac \ - UnpackedTarball/afdko/c/makeotf/lib/cffread/cffread \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/BASE \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/CFF_ \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/GDEF \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/GPOS \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/GSUB \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/OS_2 \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/STAT \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/VORG \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/anon \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/cmap \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/head \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/hhea \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/hmtx \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/hot \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/map \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/maxp \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/name \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/otl \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/post \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/sfnt \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/vhea \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/vmtx \ - UnpackedTarball/afdko/c/makeotf/lib/pstoken/pstoken \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/charset \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/cs \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/dict \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/encoding \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/fdselect \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/parse \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/recode \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/sindex \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/subr \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/t13 \ - UnpackedTarball/afdko/c/makeotf/lib/typecomp/tc \ + UnpackedTarball/afdko/c/shared/cffread \ + UnpackedTarball/afdko/c/shared/ctutil \ + UnpackedTarball/afdko/c/shared/da \ + UnpackedTarball/afdko/c/shared/dynarr \ + UnpackedTarball/afdko/c/shared/sha1 \ + UnpackedTarball/afdko/c/shared/smem \ + UnpackedTarball/afdko/c/shared/support/except \ + UnpackedTarball/afdko/c/shared/support/fixed \ )) $(eval $(call gb_StaticLibrary_add_generated_exception_objects,afdko,\ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/FeatCtx \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/FeatLexer \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/FeatParser \ - UnpackedTarball/afdko/c/makeotf/lib/hotconv/FeatVisitor \ + UnpackedTarball/afdko/c/shared/absfont/absfont \ + UnpackedTarball/afdko/c/shared/absfont/absfont_afm \ + UnpackedTarball/afdko/c/shared/absfont/absfont_compare \ + UnpackedTarball/afdko/c/shared/absfont/absfont_desc \ + UnpackedTarball/afdko/c/shared/absfont/absfont_draw \ + UnpackedTarball/afdko/c/shared/absfont/absfont_dump \ + UnpackedTarball/afdko/c/shared/absfont/absfont_metrics \ + UnpackedTarball/afdko/c/shared/absfont/absfont_path \ + UnpackedTarball/afdko/c/shared/afdko_version \ + UnpackedTarball/afdko/c/shared/cfembed \ + UnpackedTarball/afdko/c/shared/cffread_abs \ + UnpackedTarball/afdko/c/shared/cffwrite/cffwrite \ + UnpackedTarball/afdko/c/shared/cffwrite/cffwrite_charset \ + UnpackedTarball/afdko/c/shared/cffwrite/cffwrite_dict \ + UnpackedTarball/afdko/c/shared/cffwrite/cffwrite_encoding \ + UnpackedTarball/afdko/c/shared/cffwrite/cffwrite_fdselect \ + UnpackedTarball/afdko/c/shared/cffwrite/cffwrite_sindex \ + UnpackedTarball/afdko/c/shared/cffwrite/cffwrite_subr \ + UnpackedTarball/afdko/c/shared/cffwrite/cffwrite_t2cstr \ + UnpackedTarball/afdko/c/shared/cffwrite/cffwrite_varstore \ + UnpackedTarball/afdko/c/shared/designspace \ + UnpackedTarball/afdko/c/shared/goadb \ + UnpackedTarball/afdko/c/shared/namesupport \ + UnpackedTarball/afdko/c/shared/pdfwrite \ + UnpackedTarball/afdko/c/shared/pstoken \ + UnpackedTarball/afdko/c/shared/sfile \ + UnpackedTarball/afdko/c/shared/sfntread \ + UnpackedTarball/afdko/c/shared/sfntwrite \ + UnpackedTarball/afdko/c/shared/slogger \ + UnpackedTarball/afdko/c/shared/svgwrite \ + UnpackedTarball/afdko/c/shared/svread/svread \ + UnpackedTarball/afdko/c/shared/t1cstr \ + UnpackedTarball/afdko/c/shared/t1read \ + UnpackedTarball/afdko/c/shared/t1write/t1write \ + UnpackedTarball/afdko/c/shared/t2cstr \ + UnpackedTarball/afdko/c/shared/ttread \ + UnpackedTarball/afdko/c/shared/tx_shared \ + UnpackedTarball/afdko/c/shared/uforead \ + UnpackedTarball/afdko/c/shared/ufowrite \ + UnpackedTarball/afdko/c/shared/varsupport \ +)) + +$(eval $(call gb_StaticLibrary_add_generated_exception_objects,afdko,\ + UnpackedTarball/afdko/c/mergefonts/mergeFonts \ +)) + +$(eval $(call gb_StaticLibrary_add_generated_cobjects,afdko,\ + UnpackedTarball/afdko/c/addfeatures/pstoken/pstoken \ +)) + +$(eval $(call gb_StaticLibrary_add_generated_exception_objects,afdko,\ + UnpackedTarball/afdko/c/addfeatures/cb \ + UnpackedTarball/afdko/c/addfeatures/fcdb \ + UnpackedTarball/afdko/c/addfeatures/hotconv/BASE \ + UnpackedTarball/afdko/c/addfeatures/hotconv/FeatCtx \ + UnpackedTarball/afdko/c/addfeatures/hotconv/FeatLexer \ + UnpackedTarball/afdko/c/addfeatures/hotconv/FeatParser \ + UnpackedTarball/afdko/c/addfeatures/hotconv/FeatParserBaseVisitor \ + UnpackedTarball/afdko/c/addfeatures/hotconv/FeatParserVisitor \ + UnpackedTarball/afdko/c/addfeatures/hotconv/FeatVisitor \ + UnpackedTarball/afdko/c/addfeatures/hotconv/GDEF \ + UnpackedTarball/afdko/c/addfeatures/hotconv/GPOS \ + UnpackedTarball/afdko/c/addfeatures/hotconv/GSUB \ + UnpackedTarball/afdko/c/addfeatures/hotconv/MVAR \ + UnpackedTarball/afdko/c/addfeatures/hotconv/OS_2 \ + UnpackedTarball/afdko/c/addfeatures/hotconv/STAT \ + UnpackedTarball/afdko/c/addfeatures/hotconv/anon \ + UnpackedTarball/afdko/c/addfeatures/hotconv/cmap \ + UnpackedTarball/afdko/c/addfeatures/hotconv/glyphmetrics \ + UnpackedTarball/afdko/c/addfeatures/hotconv/head \ + UnpackedTarball/afdko/c/addfeatures/hotconv/hmtx \ + UnpackedTarball/afdko/c/addfeatures/hotconv/hot \ + UnpackedTarball/afdko/c/addfeatures/hotconv/hotlogger \ + UnpackedTarball/afdko/c/addfeatures/hotconv/map \ + UnpackedTarball/afdko/c/addfeatures/hotconv/maxp \ + UnpackedTarball/afdko/c/addfeatures/hotconv/name \ + UnpackedTarball/afdko/c/addfeatures/hotconv/otl \ + UnpackedTarball/afdko/c/addfeatures/hotconv/post \ + UnpackedTarball/afdko/c/addfeatures/hotconv/sfnt \ + UnpackedTarball/afdko/c/addfeatures/hotconv/vmtx \ )) $(eval $(call gb_StaticLibrary_add_generated_exception_objects,afdko,\ diff --git a/external/afdko/UnpackedTarball_afdko.mk b/external/afdko/UnpackedTarball_afdko.mk index 8989baf2eccd..5ec094424e67 100644 --- a/external/afdko/UnpackedTarball_afdko.mk +++ b/external/afdko/UnpackedTarball_afdko.mk @@ -17,19 +17,29 @@ $(eval $(call gb_UnpackedTarball_set_pre_action,afdko,\ $(eval $(call gb_UnpackedTarball_set_patchlevel,afdko,1)) -# mergeFonts_crash.patch upstream attempt as: -# https://github.com/adobe-type-tools/afdko/pull/1806 +# lookuplist-deref.patch upstream attempt as: +# https://github.com/adobe-type-tools/afdko/pull/1840 +# glyphmetrics-instance.patch upstream attempt as: +# https://github.com/adobe-type-tools/afdko/pull/1841 $(eval $(call gb_UnpackedTarball_add_patches,afdko, \ - external/afdko/extern_tx.patch \ - external/afdko/extern_tx_shared.patch \ external/afdko/extern_mergefonts.patch \ - external/afdko/extern_makeotf.patch \ - external/afdko/warnings.patch \ - external/afdko/mergeFonts_crash.patch \ - external/afdko/noverbose.patch \ + external/afdko/extern_addfeatures.patch \ + external/afdko/fatal-callback.patch \ + external/afdko/glyphmetrics-instance.patch \ + external/afdko/lookuplist-deref.patch \ + external/afdko/pastend-iterators.patch \ + external/afdko/itemvariationstore-tag.patch \ + external/afdko/sfnt-named-structs.patch \ external/afdko/antlr4-chrono.patch \ external/afdko/ubsan.patch.0 \ + external/afdko/cstdint.patch \ + external/afdko/classrec-fallback-ref.patch.0 \ + external/afdko/clang.patch.0 \ )) +# static replacement for the cmake-generated version files +$(eval $(call gb_UnpackedTarball_add_file,afdko,c/shared/include/afdko_version.h,external/afdko/afdko_version.h)) +$(eval $(call gb_UnpackedTarball_add_file,afdko,c/shared/afdko_version.cpp,external/afdko/afdko_version.cpp)) + # vim: set noet sw=4 ts=4: diff --git a/external/afdko/afdko_version.cpp b/external/afdko/afdko_version.cpp new file mode 100644 index 000000000000..b53c488ec2a9 --- /dev/null +++ b/external/afdko/afdko_version.cpp @@ -0,0 +1,25 @@ +/* + * AFDKO Version Implementation + * + * Static replacement for the cmake-generated afdko_version.cpp. Keep the + * version here in sync with AFDKO_TARBALL in download.lst. + */ + +#include "afdko_version.h" +#include +#include + +static const char build_version[] = "5.0.1"; + +/* Mutable version pointer - initialized by init_fdk_version() */ +char *FDK_VERSION = NULL; + +/* Initialize FDK_VERSION with a malloc'd copy */ +void init_fdk_version(void) { + if (FDK_VERSION == NULL) { + FDK_VERSION = (char *)malloc(strlen(build_version) + 1); + if (FDK_VERSION != NULL) { + strcpy(FDK_VERSION, build_version); + } + } +} diff --git a/external/afdko/afdko_version.h b/external/afdko/afdko_version.h new file mode 100644 index 000000000000..486d7c8e1ab4 --- /dev/null +++ b/external/afdko/afdko_version.h @@ -0,0 +1,25 @@ +/* + * AFDKO Version Header + * + * Static replacement for the cmake-generated afdko_version.h. Keep the + * version in afdko_version.cpp in sync with AFDKO_TARBALL in download.lst. + */ + +#ifndef AFDKO_VERSION_H +#define AFDKO_VERSION_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Mutable version pointer - must be initialized by init_fdk_version() */ +extern char *FDK_VERSION; + +/* Initialize FDK_VERSION with the build-time version */ +void init_fdk_version(void); + +#ifdef __cplusplus +} +#endif + +#endif /* AFDKO_VERSION_H */ diff --git a/external/afdko/clang.patch.0 b/external/afdko/clang.patch.0 new file mode 100644 index 000000000000..231138ba2a48 --- /dev/null +++ b/external/afdko/clang.patch.0 @@ -0,0 +1,87 @@ +--- c/shared/absfont/absfont_dump.cpp ++++ c/shared/absfont/absfont_dump.cpp +@@ -552,11 +552,11 @@ + // dumpInstr(cb, " %.3f %.3f %s", edge0, edge1, (flags & ABF_VERT_STEM)? "vstem3": "hstem3"); + } else { + float width = RND(edge1 - edge0); +- if (width == ABF_EDGE_HINT_LO) { ++ if (width == float(ABF_EDGE_HINT_LO)) { + writeReal(buf, bufLen, edge1); + STRCAT_S(buf, bufLen, (flags & ABF_VERT_STEM) ? " leftedge" : " bottomedge"); + // dumpInstr(cb, " %.3f %s", edge1, (flags & ABF_VERT_STEM)? "leftedge": "bottomedge"); +- } else if (width == ABF_EDGE_HINT_HI) { ++ } else if (width == float(ABF_EDGE_HINT_HI)) { + writeReal(buf, bufLen, edge0); + STRCAT_S(buf, bufLen, (flags & ABF_VERT_STEM) ? " rightedge" : " topedge"); + // dumpInstr(cb, " %.3f %s", edge0, (flags & ABF_VERT_STEM)? "rightedge": "topedge"); +--- c/shared/cffwrite/cffwrite_t2cstr.cpp ++++ c/shared/cffwrite/cffwrite_t2cstr.cpp +@@ -1643,7 +1643,7 @@ + #endif + + delta = edge1 - edge0; +- if (delta < 0 && delta != ABF_EDGE_HINT_LO && delta != ABF_EDGE_HINT_HI) { ++ if (delta < 0 && delta != float(ABF_EDGE_HINT_LO) && delta != float(ABF_EDGE_HINT_HI)) { + if (!(h->g->flags & CFW_NO_HINT_WARNINGS)) + addWarn(h, warn_hint0); + _new.edge0v.value = edge1; +@@ -1716,7 +1716,7 @@ + #endif + + delta = edge1 - edge0; +- if (delta < 0 && delta != ABF_EDGE_HINT_LO && delta != ABF_EDGE_HINT_HI) { ++ if (delta < 0 && delta != float(ABF_EDGE_HINT_LO) && delta != float(ABF_EDGE_HINT_HI)) { + if (!(h->g->flags & CFW_NO_HINT_WARNINGS)) + addWarn(h, warn_hint0); + _new.edge0v = *edge1v; +--- c/shared/include/varsupport.h ++++ c/shared/include/varsupport.h +@@ -463,7 +463,7 @@ + ivsOffset - offset to the IVS data from the beginning of the + container table. + */ +- itemVariationStore() {} ++ itemVariationStore(); + itemVariationStore(ctlSharedStmCallbacks *sscb, uint32_t tableOffset, + uint32_t tableLength, uint32_t ivsOffset); + +@@ -594,16 +594,7 @@ + + void write(VarWriter &vw); + +- void reset(bool clearAxisCount = false) { +- if (clearAxisCount) +- axisCount = 0; +- regions.clear(); +- regionMap.clear(); +- subtables.clear(); +- values.clear(); +- models.clear(); +- locationSetMap.clear(); +- } ++ void reset(bool clearAxisCount = false); + + private: + uint32_t getRegionListSize() { +--- c/shared/varsupport.cpp ++++ c/shared/varsupport.cpp +@@ -673,6 +673,19 @@ + } + } + ++itemVariationStore::itemVariationStore() {} ++ ++void itemVariationStore::reset(bool clearAxisCount) { ++ if (clearAxisCount) ++ axisCount = 0; ++ regions.clear(); ++ regionMap.clear(); ++ subtables.clear(); ++ values.clear(); ++ models.clear(); ++ locationSetMap.clear(); ++} ++ + /* item variation store sub-table */ + + itemVariationStore::itemVariationStore(ctlSharedStmCallbacks *sscb, diff --git a/external/afdko/classrec-fallback-ref.patch.0 b/external/afdko/classrec-fallback-ref.patch.0 new file mode 100644 index 000000000000..77b011622366 --- /dev/null +++ b/external/afdko/classrec-fallback-ref.patch.0 @@ -0,0 +1,22 @@ +--- c/addfeatures/hotconv/FeatCtx.cpp ++++ c/addfeatures/hotconv/FeatCtx.cpp +@@ -490,7 +490,8 @@ const GPat::ClassRec &FeatCtx::lookupGlyphClass(const std::string &gcname) { + auto search = namedGlyphClasses.find(gcname); + if ( search == namedGlyphClasses.end() ) { + featMsg(sFATAL, "glyph class not defined"); +- return GPat::ClassRec {}; ++ static const GPat::ClassRec empty; ++ return empty; + } + return search->second; + } +--- c/addfeatures/hotconv/GPOS.cpp ++++ c/addfeatures/hotconv/GPOS.cpp +@@ -997,7 +997,7 @@ GPat::ClassRec &GPOS::getCR(uint32_t cls, int classDefInx) { + g->logger->log(sFATAL, "class <%u> not valid in classDef", cls); + */ + assert(false); +- GPat::ClassRec cr; ++ static GPat::ClassRec cr; + return cr; + } diff --git a/external/afdko/cstdint.patch b/external/afdko/cstdint.patch new file mode 100644 index 000000000000..79e8099f5dd9 --- /dev/null +++ b/external/afdko/cstdint.patch @@ -0,0 +1,18 @@ +--- afdko/c/shared/sha1.c 2026-06-26 00:09:12.530617735 +0200 ++++ afdko/c/shared/sha1.c 2026-06-26 00:09:22.842585047 +0200 +@@ -5,14 +5,7 @@ + + #include + #include /* to get info about range unsigned int */ +- +-#if ULONG_MAX == 4294967295U +-typedef unsigned long int uint32_t; +-#elif UINT_MAX == 4294967295U +-typedef unsigned int uint32_t; +-#else +-#error "There must be a way to get an unsigned 32 bit integer" +-#endif ++#include + + typedef struct sha1_ctx { + uint32_t H[5]; diff --git a/external/afdko/extern_addfeatures.patch b/external/afdko/extern_addfeatures.patch new file mode 100644 index 000000000000..186556d87f0f --- /dev/null +++ b/external/afdko/extern_addfeatures.patch @@ -0,0 +1,80 @@ +--- afdko/c/addfeatures/cb.h ++++ afdko/c/addfeatures/cb.h +@@ -19,7 +19,8 @@ + + /* --- Basic functions --- */ + cbCtx cbNew(const char *progname, const char *indir, const char *outdir, +- const char *cmapdir, const char *featdir, dnaCtx mainDnaCtx); ++ const char *cmapdir, const char *featdir, dnaCtx mainDnaCtx, ++ void (*fatal)(void *ctx)); + void cbConvert(cbCtx h, int flags, const char *clientVers, + const char *infile, const char *outfile, + const char *featurefile, const char *hcmapfile, +--- afdko/c/addfeatures/cb.cpp ++++ afdko/c/addfeatures/cb.cpp +@@ -91,6 +91,7 @@ + std::shared_ptr goadb; + std::shared_ptr ds; + std::shared_ptr logger; ++ void (*clientFatal)(void *ctx) = NULL; /* Called by myfatal() in place of process exit. Must not return. */ + }; + + /* ----------------------------- Error Handling ---------------------------- */ +@@ -98,6 +99,8 @@ + /* Fatal exception handler */ + static void myfatal(void *ctx) { + cbCtx h = (cbCtx) ctx; ++ if (h->clientFatal != NULL) ++ h->clientFatal(ctx); + /*This seems to cause all kinds of crashes on Windows and OSX*/ + /* hotFree(h->hot.ctx);*/ /* Free library context */ + +@@ -468,9 +471,12 @@ + + /* Create new callback context */ + cbCtx cbNew(const char *progname, const char *indir, const char *outdir, +- const char *cmapdir, const char *featdir, dnaCtx mainDnaCtx) { ++ const char *cmapdir, const char *featdir, dnaCtx mainDnaCtx, ++ void (*fatal)(void *ctx)) { + cbCtx h = new cbCtx_; + ++ h->clientFatal = fatal; ++ + hotcbInit(h); + + stmClear(&h->in); +@@ -808,3 +814,12 @@ + + delete h; + } ++ ++/* Defined in main.cpp upstream, which is not compiled here. */ ++extern "C" const char *curdir() { ++ return "."; ++} ++ ++extern "C" const char *sep() { ++ return "/"; ++} +--- afdko/c/addfeatures/pstoken/pstoken.c ++++ afdko/c/addfeatures/pstoken/pstoken.c +@@ -7,7 +7,7 @@ + */ + + #include +-#include "pstoken.h" ++#include "../include/pstoken.h" + + #include + #include +--- afdko/c/addfeatures/hotconv/map.cpp ++++ afdko/c/addfeatures/hotconv/map.cpp +@@ -23,7 +23,7 @@ + #include "otl.h" + #include "FeatCtx.h" + +-#include "pstoken.h" ++#include "../include/pstoken.h" + + #define SET_BIT_ARR(a, b) (a[(b) / 32] |= 1UL << (b) % 32) + #define TEST_BIT_ARR(a, b) (a[(b) / 32] & 1UL << (b) % 32) diff --git a/external/afdko/extern_makeotf.patch b/external/afdko/extern_makeotf.patch deleted file mode 100644 index 4021d52dec45..000000000000 --- a/external/afdko/extern_makeotf.patch +++ /dev/null @@ -1,354 +0,0 @@ ---- afdko/c/makeotf/source/c_main.c -+++ afdko/c/makeotf/source/c_main.c -@@ -269,6 +269,7 @@ - exit(0); - } - -+#if 0 - extern char *sep(); - - /* Copy directory path with overflow checking */ -@@ -744,6 +745,7 @@ - - convert.fontDone = 1; - } -+#endif - - /*Used to parse the parameter string passed in by python - * start is the start index and is updated to the beginning of the next substring -@@ -822,6 +824,7 @@ - } - } - -+#if 0 - /* Main program */ - int c_main(int argc, char *argv[]) { - dnaCtx mainDnaCtx = NULL; -@@ -874,3 +877,4 @@ - - return 0; - } -+#endif ---- afdko/c/makeotf/source/cb.c 2025-09-23 13:18:57.919265608 +0100 -+++ afdko/c/makeotf/source/cb.c 2025-09-23 13:20:13.039352315 +0100 -@@ -267,14 +267,14 @@ - /* Full block */ - *count = fileReadN(&h->ps.file, BUFSIZ, h->ps.buf); - if (*count != BUFSIZ) { -- fileError(&h->ps.file); -+ fileHandleError(&h->ps.file); - } - h->ps.left -= BUFSIZ; - } else if (h->ps.left > 0) { - /* Partial block */ - *count = fileReadN(&h->ps.file, h->ps.left, h->ps.buf); - if (*count != h->ps.left) { -- fileError(&h->ps.file); -+ fileHandleError(&h->ps.file); - } - h->ps.left = 0; - } else { -@@ -531,7 +531,7 @@ - cbCtx h = ctx; - h->tmp.file.name = "tmpfile"; - if ((h->tmp.file.fp = tmpfile()) == NULL) { -- fileError(&h->tmp.file); -+ fileHandleError(&h->tmp.file); - } - } - -@@ -636,7 +636,7 @@ - File *file = &h->fcdb.files.array[fileid]; - fileSeek(file, offset, SEEK_SET); - if (fileReadN(file, length, buf) != length) -- fileError(file); -+ fileHandleError(file); - } - - // [fcdb callback] Report database parsing warning. -@@ -1185,7 +1185,8 @@ - - /* Create new callback context */ - cbCtx cbNew(char *progname, char *pfbdir, char *otfdir, -- char *cmapdir, char *featdir, dnaCtx mainDnaCtx) { -+ char *cmapdir, char *featdir, dnaCtx mainDnaCtx, -+ void (*fatal)(void*)) { - static hotCallbacks template = { - NULL, /* Callback context; set after creation */ - myfatal, -@@ -1233,6 +1234,8 @@ - h->dir.cmap = cmapdir; - - h->hot.cb = template; /* Copy template */ -+ if (fatal) -+ h->hot.cb.fatal = fatal; - h->hot.cb.ctx = h; - - h->dnaCtx = mainDnaCtx; ---- afdko/c/makeotf/source/file.c 2025-09-23 13:18:57.919265608 +0100 -+++ afdko/c/makeotf/source/file.c 2025-09-23 13:20:04.148358137 +0100 -@@ -23,7 +23,7 @@ - #endif /* SUNOS */ - - /* Print file error message and quit */ --void fileError(File *f) { -+void fileHandleError(File *f) { - cbFatal(f->h, "file error <%s> [%s]", strerror(errno), f->name); - } - -@@ -33,7 +33,7 @@ - f->name = filename; - f->fp = fopen(filename, mode); - if (f->fp == NULL) { -- fileError(f); -+ fileHandleError(f); - } - } - -@@ -52,7 +52,7 @@ - int fileReadN(File *f, size_t count, void *ptr) { - size_t n = fread(ptr, 1, count, f->fp); - if (n == 0 && ferror(f->fp)) { -- fileError(f); -+ fileHandleError(f); - } - return n; - } -@@ -61,7 +61,7 @@ - int fileWriteN(File *f, size_t count, void *ptr) { - size_t n = fwrite(ptr, 1, count, f->fp); - if (n != count) { -- fileError(f); -+ fileHandleError(f); - } - return n; - } -@@ -88,7 +88,7 @@ - /* Seek on file */ - void fileSeek(File *f, long offset, int wherefrom) { - if (fseek(f->fp, offset, wherefrom) != 0) { -- fileError(f); -+ fileHandleError(f); - } - } - -@@ -96,7 +96,7 @@ - long fileTell(File *f) { - long posn = ftell(f->fp); - if (posn == -1) { -- fileError(f); -+ fileHandleError(f); - } - return posn; - } -@@ -104,7 +104,7 @@ - /* Check for errors and close file */ - void fileClose(File *f) { - if (ferror(f->fp)) { -- fileError(f); -+ fileHandleError(f); - } - fclose(f->fp); - } ---- afdko/c/makeotf/source/file.h 2025-09-23 13:18:57.919265608 +0100 -+++ afdko/c/makeotf/source/file.h 2025-09-23 13:20:01.042950337 +0100 -@@ -29,6 +29,6 @@ - void fileSeek(File *file, long offset, int wherefrom); - long fileTell(File *file); - void fileClose(File *file); --void fileError(File *file); -+void fileHandleError(File *file); - - #endif /* MAKEOTF_FILE_H */ ---- afdko/c/makeotf/lib/hotconv/common.h -+++ afdko/c/makeotf/lib/hotconv/common.h -@@ -14,7 +14,7 @@ --#include "hotconv.h" -+#include "../../include/hotconv.h" - #include "dynarr.h" - #include "txops.h" --#include "cffread.h" -+#include "../../include/cffread.h" --#include "typecomp.h" -+#include "../../include/typecomp.h" - #include "ctutil.h" - ---- afdko/c/makeotf/source/package.h -+++ afdko/c/makeotf/source/package.h -@@ -7,7 +7,7 @@ - #define MAKEOTF_PACKAGE_SPECS_H - - #define TYPECOMP "typecomp.h" --#define HOTCONV "hotconv.h" -+#define HOTCONV "../include/hotconv.h" - #define DYNARR "dynarr.h" - - #endif /* MAKEOTF_PACKAGE_SPECS_H */ ---- afdko/c/makeotf/include/cffread.h -+++ afdko/c/makeotf/include/cffread.h -@@ -144,7 +144,7 @@ - to cffFontInfo data structure the function returns. This data structure is - described below. */ - --#include "txops.h" -+#include "../resource/txops.h" - - typedef unsigned short cffSID; /* String identifier */ - typedef short cffFWord; /* Font metric in em-relative units */ ---- afdko/c/makeotf/lib/typecomp/common.h -+++ afdko/c/makeotf/lib/typecomp/common.h -@@ -7,7 +7,7 @@ - #define COMMON_H - - #include "dynarr.h" --#include "typecomp.h" -+#include "../../include/typecomp.h" - #include "stdint.h" - - /* Types */ ---- afdko/c/makeotf/lib/typecomp/t13.h -+++ afdko/c/makeotf/lib/typecomp/t13.h -@@ -13,7 +13,7 @@ - #include "common.h" - #include "cs.h" - --#include "pstoken.h" -+#include "../../include/pstoken.h" - - void t13New(tcCtx g); - void t13Free(tcCtx g); ---- afdko/c/makeotf/lib/hotconv/map.c -+++ afdko/c/makeotf/lib/hotconv/map.c -@@ -21,7 +21,7 @@ - #include - #include - --#include "pstoken.h" -+#include "../../include/pstoken.h" - - #define SET_BIT_ARR(a, b) (a[(b) / 32] |= 1UL << (b) % 32) - #define TEST_BIT_ARR(a, b) (a[(b) / 32] & 1UL << (b) % 32) ---- afdko/c/makeotf/lib/pstoken/pstoken.c -+++ afdko/c/makeotf/lib/pstoken/pstoken.c -@@ -7,7 +7,7 @@ - */ - - #include --#include "pstoken.h" -+#include "../../include/pstoken.h" - - #include - #include ---- afdko/c/makeotf/lib/hotconv/cmap.c -+++ afdko/c/makeotf/lib/hotconv/cmap.c -@@ -8,7 +8,7 @@ - #include - #include - --#include "hotconv.h" -+#include "../../include/hotconv.h" - #include "cmap.h" - #include "hotmap.h" - #include "feat.h" ---- afdko/c/makeotf/lib/cffread/cffread.c -+++ afdko/c/makeotf/lib/cffread/cffread.c -@@ -11,8 +11,8 @@ - #include - #include - #include --#include "cffread.h" --#include "dictops.h" -+#include "../../include/cffread.h" -+#include "../../resource/dictops.h" - - /* Define to supply Microsoft-specific function calling info, e.g. __cdecl */ - #ifndef CDECL ---- afdko/c/makeotf/lib/typecomp/recode.c -+++ afdko/c/makeotf/lib/typecomp/recode.c -@@ -8,7 +8,7 @@ - #include "parse.h" - #include "subr.h" - --#include "txops.h" -+#include "../../resource/txops.h" - - #include - #include -@@ -248,7 +248,7 @@ - - #include - --#include "cffread.h" -+#include "../../include/cffread.h" - - /* Degrees to radians multiplying constant */ - #define DEG_2_RAD (3.141592653589793 / 180) - ---- afdko/c/makeotf/lib/typecomp/parse.c -+++ afdko/c/makeotf/lib/typecomp/parse.c -@@ -15,8 +15,8 @@ - #include "t13.h" - #include "recode.h" - --#include "txops.h" --#include "pstoken.h" -+#include "../../resource/txops.h" -+#include "../../include/pstoken.h" - - #include - #include ---- afdko/c/makeotf/lib/typecomp/dict.h -+++ afdko/c/makeotf/lib/typecomp/dict.h -@@ -11,7 +11,7 @@ - #define DICT_H - - #include "common.h" --#include "dictops.h" -+#include "../../resource/dictops.h" - - /* Tokenized dictionary data */ - typedef dnaDCL(char, DICT); ---- afdko/c/makeotf/source/cbpriv.c -+++ afdko/c/makeotf/source/cbpriv.c -@@ -5,7 +5,7 @@ - #include - #include - --#include "hotconv.h" -+#include "../include/hotconv.h" - #include "cb.h" - - extern void myfatal(void *ctx); ---- afdko/c/makeotf/source/cb.h -+++ afdko/c/makeotf/source/cb.h -@@ -8,6 +8,11 @@ - - #include - #include "dynarr.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - typedef struct cbCtx_ *cbCtx; - - /* Define to supply Microsoft-specific function calling info, e.g. __cdecl */ -@@ -22,7 +22,8 @@ - - /* --- Basic functions --- */ - extern cbCtx cbNew(char *progname, char *pfbdir, char *otfdir, -- char *cmapdir, char *featdir, dnaCtx mainDnaCtx); -+ char *cmapdir, char *featdir, dnaCtx mainDnaCtx, -+ void (*fatal)(void*)); - extern void cbConvert(cbCtx h, int flags, char *clientVers, - char *pfbfile, char *otffile, - char *featurefile, char *hcmapfile, char *vcmapfile, -@@ -80,4 +85,8 @@ - #define OTHERFLAGS_VERBOSE (1 << 15) - #define OTHERFLAGS_FINAL_NAMES (1 << 16) - -+#ifdef __cplusplus -+} -+#endif -+ - #endif /* CB_H */ diff --git a/external/afdko/extern_mergefonts.patch b/external/afdko/extern_mergefonts.patch index bca249fd94a1..845e88f872d5 100644 --- a/external/afdko/extern_mergefonts.patch +++ b/external/afdko/extern_mergefonts.patch @@ -1,116 +1,53 @@ ---- afdko/c/mergefonts/source/mergeFonts.c 2025-09-23 10:51:19.857082828 +0100 -+++ afdko/c/mergefonts/source/mergeFonts.c 2025-09-23 10:51:40.645895437 +0100 -@@ -1200,7 +1200,7 @@ - } - } - --static void readCIDFontInfo(txCtx h, char *filePath) { -+void readCIDFontInfo(txCtx h, char *filePath) { - int lineno; - FILE *fp; - MergeInfo *mergeInfo = (MergeInfo *)h->appSpecificInfo; -@@ -1677,7 +1677,7 @@ - - /* Process merging multi-file set. Return index of last used arg. */ - /* Currently implemented only for mode_cff */ --static int doMergeFileSet(txCtx h, int argc, char *argv[], int i) { -+int doMergeFileSet(txCtx h, int argc, char *argv[], int i) { - sourceCtx srcCtx; - int fileIndex = 0; - int fileCount = 0; -@@ -2609,10 +2609,34 @@ - } - } - -+void mergeFontsFree(txCtx h); -+ - /* Initialize context. */ --static void txNew(txCtx h, char *progname) { -+txCtx mergeFontsNew(char *progname) { - ctlMemoryCallbacks cb; -- MergeInfo *mergeInfo = (MergeInfo *)h->appSpecificInfo; -+ txCtx h; -+ MergeInfo *mergeInfo; -+ -+ /* Allocate program context */ -+ h = malloc(sizeof(struct txCtx_)); -+ if (h == NULL) { -+ fprintf(stderr, "%s: out of memory\n", progname); -+ return NULL; -+ } -+ memset(h, 0, sizeof(struct txCtx_)); -+ -+ h->app = APP_MERGEFONTS; -+ h->appSpecificInfo = malloc(sizeof(MergeInfo)); -+ if (h == NULL) { -+ fprintf(stderr, "%s: out of memory\n", progname); -+ free(h); -+ return NULL; -+ } -+ memset(h->appSpecificInfo, 0, sizeof(MergeInfo)); -+ -+ h->appSpecificFree = mergeFontsFree; -+ -+ mergeInfo = (MergeInfo *)h->appSpecificInfo; - - h->progname = progname; - h->flags = 0; -@@ -2690,10 +2714,12 @@ - - /* Clear the SEEN_MODE bit after setting the default mode */ - h->flags = 0; -+ -+ return h; - } - - /* Free context. */ --static void txFree(txCtx h) { -+void mergeFontsFree(txCtx h) { - long i; - - memFree(h, h->script.buf); -@@ -2749,6 +2775,7 @@ - free(h); - } - -+#if 0 - /* Main program. */ - int CTL_CDECL main(int argc, char *argv[]) { - txCtx h; -@@ -2770,25 +2797,11 @@ - --argc; - ++argv; - -- /* Allocate program context */ -- h = malloc(sizeof(struct txCtx_)); -- if (h == NULL) { -- fprintf(stderr, "%s: out of memory\n", progname); -- return EXIT_FAILURE; -- } -- memset(h, 0, sizeof(struct txCtx_)); -- -- h->app = APP_MERGEFONTS; -- h->appSpecificInfo = malloc(sizeof(MergeInfo)); -+ h = mergeFontsNew(progname); - if (h == NULL) { - fprintf(stderr, "%s: out of memory\n", progname); - exit(1); - } -- memset(h->appSpecificInfo, 0, sizeof(MergeInfo)); -- -- h->appSpecificFree = txFree; -- -- txNew(h, progname); - - if (argc > 1 && getOptionIndex(argv[argc - 2]) == opt_s) { - /* Option list ends with script option */ -@@ -2810,7 +2823,8 @@ - fprintf(stderr, "mem_manage() called %ld times in this run.\n", - h->failmem.iCall); - } -- txFree(h); -+ mergeFontsFree(h); +--- afdko/c/mergefonts/mergeFonts.cpp ++++ afdko/c/mergefonts/mergeFonts.cpp +@@ -1384,3 +1384,50 @@ return 0; } -+#endif ++ ++/* Embedding interface: the same wiring as main__mergefonts above, but with ++ heap allocation and caller-driven steps in place of argv parsing. */ ++extern "C" txCtx mergeFontsNew(void) { ++ MergeInfo *mi = (MergeInfo *)calloc(1, sizeof(MergeInfo)); ++ txExtCtx e = (txExtCtx)calloc(1, sizeof(struct txExtCtx_)); ++ txCtx h = (txCtx)calloc(1, sizeof(struct txCtx_)); ++ ++ if (mi == NULL || e == NULL || h == NULL) { ++ free(mi); ++ free(e); ++ free(h); ++ return NULL; ++ } ++ ++ e->extData = mi; ++ e->progname = "mergefonts"; ++ e->version = MERGEFONTS_VERSION; ++ e->processOption = &mf_processOption; ++ e->usage = &mf_usage; ++ e->help = &mf_help; ++ e->cfr_ReadFontCB = &mf_cfr_ReadFontCB; ++ ++ mi->tx = h; ++ ++ txNew(h, e); ++ ++ return h; ++} ++ ++extern "C" void mergeFontsFree(txCtx h) { ++ txExtCtx e = h->ext; ++ void *mi = e->extData; ++ ++ txFree(h); ++ free(mi); ++ free(e); ++ free(h); ++} ++ ++extern "C" void mergeFontsReadCIDFontInfo(txCtx h, const char *filePath) { ++ readCIDFontInfo((MergeInfo *)h->ext->extData, filePath); ++} ++ ++extern "C" int mergeFontsDoMergeFileSet(txCtx h, int argc, char *argv[], int i) { ++ return doMergeFileSet(h, argc, argv, i); ++} diff --git a/external/afdko/extern_tx.patch b/external/afdko/extern_tx.patch deleted file mode 100644 index 44a645fafdc6..000000000000 --- a/external/afdko/extern_tx.patch +++ /dev/null @@ -1,64 +0,0 @@ ---- afdko/c/tx/source/tx.c -+++ afdko/c/tx/source/tx.c -@@ -127,7 +127,7 @@ - /* ---------------------------- cffread Library ---------------------------- */ - - /* Read font with cffread library. */ --static void cfrReadFont(txCtx h, long origin, int ttcIndex) { -+void cfrReadFont(txCtx h, long origin, int ttcIndex) { - float *uv; - if (h->cfr.ctx == NULL) { - h->cfr.ctx = cfrNew(&h->cb.mem, &h->cb.stm, CFR_CHECK_ARGS); -@@ -1403,9 +1403,24 @@ - } - } - -+void txFree(txCtx h); -+ - /* Initialize context. */ --static void txNew(txCtx h, char *progname) { -+txCtx txNew(char *progname) { - ctlMemoryCallbacks cb; -+ txCtx h; -+ -+ /* Allocate program context */ -+ h = malloc(sizeof(struct txCtx_)); -+ if (h == NULL) { -+ fprintf(stderr, "%s: out of memory\n", progname); -+ return NULL; -+ } -+ memset(h, 0, sizeof(struct txCtx_)); -+ -+ h->app = APP_TX; -+ h->appSpecificInfo = NULL; /* unused in tx.c, used in rotateFont.c & mergeFonts.c */ -+ h->appSpecificFree = txFree; - - h->progname = progname; - h->flags = 0; -@@ -1480,10 +1495,12 @@ - - /* Clear the SEEN_MODE bit after setting the default mode */ - h->flags = 0; -+ -+ return h; - } - - /* Free context. */ --static void txFree(txCtx h) { -+void txFree(txCtx h) { - long i; - - memFree(h, h->script.buf); -@@ -1539,6 +1556,7 @@ - free(h); - } - -+#if 0 - /* Main program. */ - int CTL_CDECL main(int argc, char *argv[]) { - txCtx h; -@@ -1602,3 +1620,4 @@ - - return 0; - } -+#endif diff --git a/external/afdko/extern_tx_shared.patch b/external/afdko/extern_tx_shared.patch deleted file mode 100644 index b06cec02774f..000000000000 --- a/external/afdko/extern_tx_shared.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- afdko/c/shared/include/tx_shared.h -+++ afdko/c/shared/include/tx_shared.h -@@ -86,6 +86,11 @@ - #define sig_UFO CTL_TAG('<', '?', 'x', 'm') - /* Generate n-bit mask */ - #define N_BIT_MASK(n) (~(~0UL << (n))) -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - enum { MAX_VERSION_SIZE = 100 }; - - typedef struct txCtx_ *txCtx; /* tx program context */ -@@ -587,4 +592,8 @@ - void ttrReadFont(txCtx h, long origin, int iTTC); - void ufoReadFont(txCtx h, long origin); - -+#ifdef __cplusplus -+} -+#endif -+ - #endif /* TX_SHARED_H */ diff --git a/external/afdko/fatal-callback.patch b/external/afdko/fatal-callback.patch new file mode 100644 index 000000000000..e75f322a6511 --- /dev/null +++ b/external/afdko/fatal-callback.patch @@ -0,0 +1,21 @@ +--- afdko/c/shared/include/tx_shared.h ++++ afdko/c/shared/include/tx_shared.h +@@ -288,6 +288,7 @@ + int mode; /* Current mode */ + const char *modename; /* Name of current mode */ + txExtCtx ext; /* Extension context (if any) */ ++ void (*fatalCallback)(struct txCtx_ *h); /* Called by fatal() in place of process exit. Must not return. */ + abfTopDict *top; /* Top dictionary */ + struct { /* Source data */ + int type; /* Font technology type */ +--- afdko/c/shared/tx_shared.cpp ++++ afdko/c/shared/tx_shared.cpp +@@ -33,6 +33,8 @@ + } else { + h->logger->msg(sFATAL, "fatal error"); + } ++ if (h->fatalCallback != NULL) ++ h->fatalCallback(h); + txFree(h); + exit(EXIT_FAILURE); + } diff --git a/external/afdko/glyphmetrics-instance.patch b/external/afdko/glyphmetrics-instance.patch new file mode 100644 index 000000000000..7769acb90584 --- /dev/null +++ b/external/afdko/glyphmetrics-instance.patch @@ -0,0 +1,11 @@ +--- afdko/c/addfeatures/hotconv/glyphmetrics.cpp ++++ afdko/c/addfeatures/hotconv/glyphmetrics.cpp +@@ -294,7 +294,7 @@ + } + + void GlyphMetrics::processGlyphs(const std::vector &gids) { +- static abfGlyphCallbacks glyphcb = { ++ abfGlyphCallbacks glyphcb = { + (void *)this, + NULL, + NULL, diff --git a/external/afdko/itemvariationstore-tag.patch b/external/afdko/itemvariationstore-tag.patch new file mode 100644 index 000000000000..a83d0b047420 --- /dev/null +++ b/external/afdko/itemvariationstore-tag.patch @@ -0,0 +1,17 @@ +The type is defined as a class in varsupport.h and forward declared as a +class in cffread_abs.h. absfont.h forward declared it as a struct, which +trips -Wmismatched-tags on clang and C4099 on MSVC when both headers are +pulled into the same translation unit. absfont.h is only ever included by +C++ sources, so the class keyword is safe here. + +--- afdko/c/shared/include/absfont.h ++++ afdko/c/shared/include/absfont.h +@@ -102,7 +102,7 @@ + }; + + /* item variation store */ +-struct itemVariationStore; ++class itemVariationStore; + + /* Top dictionary data. Comments indicate default/initial values. */ + typedef struct { diff --git a/external/afdko/lookuplist-deref.patch b/external/afdko/lookuplist-deref.patch new file mode 100644 index 000000000000..56a45fc5eb62 --- /dev/null +++ b/external/afdko/lookuplist-deref.patch @@ -0,0 +1,21 @@ +--- afdko/c/addfeatures/hotconv/otl.cpp ++++ afdko/c/addfeatures/hotconv/otl.cpp +@@ -674,15 +674,15 @@ void OTL::prepLookupList() { + + auto prevl = subtables.begin(); + for (auto sl = prevl + 1; sl <= subtables.end(); sl++) { +- auto &slr = *sl; ++ Subtable *slr = sl == subtables.end() ? nullptr : sl->get(); + auto &prevlr = *prevl; +- if (sl == subtables.end() || slr->isRef() || slr->isParam() || ++ if (slr == nullptr || slr->isRef() || slr->isParam() || + slr->index.lookup != prevlr->index.lookup) { + /* Lookup index change */ + prevlr->span.lookup = sl; + prevl = sl; + } +- if (sl != subtables.end() && (slr->isRef() || slr->isParam())) ++ if (slr != nullptr && (slr->isRef() || slr->isParam())) + break; + } + } diff --git a/external/afdko/mergeFonts_crash.patch b/external/afdko/mergeFonts_crash.patch deleted file mode 100644 index b14ea4e1ee91..000000000000 --- a/external/afdko/mergeFonts_crash.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- afdko/c/mergefonts/source/mergeFonts.c -+++ afdko/c/mergefonts/source/mergeFonts.c -@@ -1177,21 +1177,21 @@ - if (end == 0) - return; - -- while (start < MAX_DICT_ENTRY_LEN) { -- if ((str[start] == ' ') || (str[start] == '\t') || (str[start] == '(') || (str[start] == '\r') || (str[start] == '\n')) -- start++; -+ while (end >= 0) { -+ if ((str[end] == ' ') || (str[end] == '\t') || (str[end] == ')') || (str[end] == '\r') || (str[end] == '\n')) -+ end--; - else - break; - } -+ str[end + 1] = 0; - -- while (end >= 0) { -- if ((str[end] == ' ') || (str[end] == '\t') || (str[end] == ')') || (str[end] == '\r') || (str[end] == '\n')) -- end--; -+ while (start < MAX_DICT_ENTRY_LEN) { -+ if ((str[start] == ' ') || (str[start] == '\t') || (str[start] == '(') || (str[start] == '\r') || (str[start] == '\n')) -+ start++; - else - break; - } - -- str[end + 1] = 0; - if (start > 0) - memmove(str, &str[start], (end - start) + 2); - if (strlen(str) == 0) { diff --git a/external/afdko/noverbose.patch b/external/afdko/noverbose.patch deleted file mode 100644 index 4173d973dc67..000000000000 --- a/external/afdko/noverbose.patch +++ /dev/null @@ -1,56 +0,0 @@ ---- afdko/c/mergefonts/source/mergeFonts.c 2025-10-22 13:47:13.840056699 +0100 -+++ afdko/c/mergefonts/source/mergeFonts.c 2025-10-22 13:48:02.496428544 +0100 -@@ -1727,7 +1727,9 @@ - for (j = 0; j < mergeInfo->newiFDArray.cnt; j++) { - if (curMaxFD < mergeInfo->newiFDArray.array[j]) { - curMaxFD = mergeInfo->newiFDArray.array[j]; -- fprintf(stderr, "Adding font dict %d from %s.\n", curMaxFD, h->src.stm.filename); -+ if (h->flags & SHOW_NAMES) { -+ fprintf(stderr, "Adding font dict %d from %s.\n", curMaxFD, h->src.stm.filename); -+ } - } - } - ---- afdko/c/makeotf/include/hotconv.h 2025-10-22 14:51:54.161381982 +0100 -+++ afdko/c/makeotf/include/hotconv.h 2025-10-22 14:57:50.948032645 +0100 -@@ -383,6 +383,7 @@ - #define HOT_SUBSET (1<<13) - #define HOT_SUPRESS__WIDTH_OPT (1<<14) /* suppress width optimization in CFF: makes it easier to poke at charstrings with other tools */ - #define HOT_VERBOSE (1<<15) /* Print all warnings and notes: else suppress the most annoying ones. */ -+#define HOT_SUPRESS_WARNINGS (1<<16) /* Print standard warnings and notes: else suppress the standard warnings. */ - - struct hotReadFontOverrides_ /* Record for instructions to modify font as it is read in. */ - { ---- afdko/c/makeotf/lib/hotconv/hot.c 2025-10-22 14:51:49.995353104 +0100 -+++ afdko/c/makeotf/lib/hotconv/hot.c 2025-10-22 14:56:10.084139451 +0100 -@@ -324,7 +324,9 @@ - - /* Convert to CFF */ - tcflags = 0; -- tcflags |= TC_DO_WARNINGS; -+ if (!(flags & HOT_SUPRESS_WARNINGS)) { -+ tcflags |= TC_DO_WARNINGS; -+ } - if (flags & HOT_ADD_AUTH_AREA) { - tcflags |= TC_ADDAUTHAREA; - } -@@ -385,7 +385,9 @@ - fi->FontName.length); - g->font.FontName.array[fi->FontName.length] = '\0'; - g->font.FontName.cnt = fi->FontName.length + 1; -- hotMsg(g, hotHEADING, "processing font <%s>", g->font.FontName.array); -+ if (!(flags & HOT_SUPRESS_WARNINGS)) { -+ hotMsg(g, hotHEADING, "processing font <%s>", g->font.FontName.array); -+ } - - /* Copy basic font information */ - g->font.Notice = fi->Notice; -@@ -1444,7 +1444,7 @@ - /* Print note, error, warning, or fatal message (from note buffer is fmt is - NULL). If note used, handle reuse of g->note. */ - void CDECL hotMsg(hotCtx g, int level, const char *fmt, ...) { -- if (g->cb.message != NULL) { -+ if (g->cb.message != NULL && g->convertFlags & HOT_CONVERT_VERBOSE) { - // int lenName = g->font.FontName.cnt + 2; - - if (fmt == NULL) { diff --git a/external/afdko/pastend-iterators.patch b/external/afdko/pastend-iterators.patch new file mode 100644 index 000000000000..ad4e942dd20c --- /dev/null +++ b/external/afdko/pastend-iterators.patch @@ -0,0 +1,122 @@ +--- afdko/c/addfeatures/hotconv/GPOS.cpp ++++ afdko/c/addfeatures/hotconv/GPOS.cpp +@@ -1025,12 +1025,14 @@ GPOS::PairPos::Format1::Format1(GPOS &h, GPOS::SubtableInfo &si) : PairPos(h, si + auto previ = si.pairs.begin(); + std::vector pairSetEnds; + cac->coverageBegin(); +- for (auto i = previ + 1; i <= si.pairs.end(); i++) { ++ for (auto i = previ + 1;; i++) { + if (i == si.pairs.end() || i->first != previ->first) { + cac->coverageAddGlyph(previ->first); + pairSetEnds.emplace_back(i); + previ = i; + } ++ if (i == si.pairs.end()) ++ break; + } + + auto nvals = MetricsInfo::numValues(ValueFormat1) + MetricsInfo::numValues(ValueFormat2); +--- afdko/c/addfeatures/hotconv/otl.cpp ++++ afdko/c/addfeatures/hotconv/otl.cpp +@@ -463,34 +463,41 @@ void OTL::calcFeatureListIndices() { + void OTL::prepScriptList() { + std::stable_sort(subtables.begin(), subtables.end(), Subtable::ltScriptList); + ++ if (subtables.size() == 0) ++ return; ++ + auto prevs = subtables.begin(); +- for (auto ss = prevs + 1; ss <= subtables.end(); ss++) { ++ for (auto ss = prevs + 1;; ss++) { + if (ss == subtables.end() || (*ss)->isAnon() || (*ss)->isStandAlone() || + (*ss)->script != (*prevs)->script) { + // script change + (*prevs)->span.script = ss; + + auto prevl = prevs; +- for (auto sl = prevl + 1; sl <= ss ; sl++) { ++ for (auto sl = prevl + 1;; sl++) { + if (sl == ss || (*sl)->language != (*prevl)->language) { + // language change + (*prevl)->span.language = sl; + + auto prevf = prevl; +- for (auto sf = prevf + 1; sf <= sl ; sf++) { ++ for (auto sf = prevf + 1;; sf++) { + if (sf == sl || + (*sf)->index.feature != (*prevf)->index.feature) { + // feature index change + (*prevf)->span.feature = sf; + prevf = sf; + } ++ if (sf == sl) ++ break; + } + prevl = sl; + } ++ if (sl == ss) ++ break; + } + prevs = ss; + } +- if (ss != subtables.end() && ((*ss)->isAnon() || (*ss)->isStandAlone())) ++ if (ss == subtables.end() || (*ss)->isAnon() || (*ss)->isStandAlone()) + break; + } + } +@@ -560,8 +567,11 @@ Offset OTL::fillScriptList() { + void OTL::prepFeatureList() { + std::stable_sort(subtables.begin(), subtables.end(), Subtable::ltFeatureList); + ++ if (subtables.size() == 0) ++ return; ++ + auto prevf = subtables.begin(); +- for (auto sf = prevf + 1; sf <= subtables.end(); sf++) { ++ for (auto sf = prevf + 1;; sf++) { + // Whenever we encounter new feature index, store the current subtable + // index in the first subtable of the sequence of subtables that + // had the previous subtable index. The array is this divided into +@@ -576,16 +586,18 @@ void OTL::prepFeatureList() { + (*prevf)->span.feature = sf; + + auto prevl = prevf; +- for (auto sl = prevl + 1; sl <= sf; sl++) { ++ for (auto sl = prevl + 1;; sl++) { + if (sl == sf || (*sl)->index.lookup != (*prevl)->index.lookup) { + // lookup index change + (*prevl)->span.lookup = sl; + prevl = sl; + } ++ if (sl == sf) ++ break; + } + prevf = sf; + } +- if (sf != subtables.end() && ((*sf)->isStandAlone() || (*sf)->isAnon())) ++ if (sf == subtables.end() || (*sf)->isStandAlone() || (*sf)->isAnon()) + break; + } + } +@@ -672,8 +684,11 @@ void OTL::fixFeatureParamOffsets(Offset shortfeatureParamBaseOffset) { + void OTL::prepLookupList() { + std::stable_sort(subtables.begin(), subtables.end(), Subtable::ltLookupList); + ++ if (subtables.size() == 0) ++ return; ++ + auto prevl = subtables.begin(); +- for (auto sl = prevl + 1; sl <= subtables.end(); sl++) { ++ for (auto sl = prevl + 1;; sl++) { + Subtable *slr = sl == subtables.end() ? nullptr : sl->get(); + auto &prevlr = *prevl; + if (slr == nullptr || slr->isRef() || slr->isParam() || +@@ -682,7 +697,7 @@ void OTL::prepLookupList() { + prevlr->span.lookup = sl; + prevl = sl; + } +- if (slr != nullptr && (slr->isRef() || slr->isParam())) ++ if (slr == nullptr || slr->isRef() || slr->isParam()) + break; + } + } diff --git a/external/afdko/sfnt-named-structs.patch b/external/afdko/sfnt-named-structs.patch new file mode 100644 index 000000000000..f3fafa14d6f1 --- /dev/null +++ b/external/afdko/sfnt-named-structs.patch @@ -0,0 +1,25 @@ +Give these two structs a tag name. C++20 forbids default member +initializers in an unnamed class that is given a typedef name for linkage +purposes, which MSVC reports as the hard error C7626. Naming the class +takes it out of that rule. clang and gcc accept it either way. + +--- afdko/c/addfeatures/hotconv/sfnt.cpp ++++ afdko/c/addfeatures/hotconv/sfnt.cpp +@@ -77,7 +77,7 @@ + + /* ---------------------------- Table Definition --------------------------- */ + +-typedef struct { ++typedef struct Entry { + int32_t tag = 0; + uint32_t checksum = 0; + uint32_t offset = 0; +@@ -85,7 +85,7 @@ + } Entry; + #define ENTRY_SIZE (uint32 * 4) + +-typedef struct { ++typedef struct sfntTbl { + Fixed version = 0; + uint16_t numTables = 0; + uint16_t searchRange = 0; diff --git a/external/afdko/ubsan.patch.0 b/external/afdko/ubsan.patch.0 index f79429697f28..cdffdb2c6f90 100644 --- a/external/afdko/ubsan.patch.0 +++ b/external/afdko/ubsan.patch.0 @@ -1,53 +1,6 @@ ---- c/makeotf/lib/cffread/cffread.c -+++ c/makeotf/lib/cffread/cffread.c -@@ -49,7 +49,7 @@ - /* Type conversions */ - #define INT(f) ((int16_t)(((f)&0xffff0000) >> 16)) - #define FRAC(f) ((f)&0x0000ffff) --#define INT2FIX(i) ((Fixed)(i) << 16) -+#define INT2FIX(i) ((Fixed)((uint32_t)(i) << 16)) - #define FIX2INT(f) ((short)(((f) + FixedHalf) >> 16)) - #define FIX2DBL(f) ((double)((f) / fixedScale)) - #define DBL2FIX(d) ((Fixed)((d)*fixedScale + ((d) < 0 ? -0.5 : 0.5))) ---- c/makeotf/lib/typecomp/common.h -+++ c/makeotf/lib/typecomp/common.h -@@ -36,7 +36,7 @@ - #define INDEX_SIZE(items, size) \ - ((items) == 0 ? sizeCard16 : (sizeCard16 + sizeCard8 + ((items) + 1) * INDEX_OFF_SIZE(size) + (size))) - #define FixedHalf ((Fixed)0x00008000) --#define INT2FIX(i) ((Fixed)((uint32_t)i) << 16) -+#define INT2FIX(i) ((Fixed)((uint32_t)i << 16)) - #define DBL2FIX(d) ((Fixed)((double)(d)*65536.0 + ((d) < 0 ? -0.5 : 0.5))) - #define FIX2DBL(f) ((double)(f) / 65536.0) - #define RNDFIX(f) (((f) + FixedHalf) & 0xffff0000) ---- c/makeotf/lib/typecomp/recode.c -+++ c/makeotf/lib/typecomp/recode.c -@@ -1727,10 +1727,10 @@ - - case 255: { - /* 5 byte number */ -- int32_t value = (int32_t)cstr[i + 1] << 24 | (int32_t)cstr[i + 2] << 16 | -- (int32_t)cstr[i + 3] << 8 | (int32_t)cstr[i + 4]; -+ int32_t value = (uint32_t)cstr[i + 1] << 24 | (uint32_t)cstr[i + 2] << 16 | -+ (uint32_t)cstr[i + 3] << 8 | (uint32_t)cstr[i + 4]; - if (-32000 <= value && value <= 32000) { -- value <<= 16; -+ value = (uint32_t)value << 16; - } else { - h->intDiv = 1; - } -@@ -3690,7 +3690,7 @@ - /* Remove encryption */ - for (i = 0; i < length; i++) { - unsigned char plain = cstr[i] ^ (r1 >> 8); -- r1 = (cstr[i] + r1) * 52845 + 22719; -+ r1 = (unsigned)(cstr[i] + r1) * 52845 + 22719; - cstr[i] = plain; - } - } --- c/shared/include/cffwrite.h +++ c/shared/include/cffwrite.h -@@ -156,7 +156,7 @@ +@@ -168,7 +168,7 @@ compatible with a destination font dict of the same FontName, the function returns 1 else it returns 0. */ @@ -56,20 +9,20 @@ /* cfwMergeFDArray() merges all the fdArray font dicts of the passed-in source font top dict into the destination font. It also fills in the array pointed ---- c/shared/source/cffwrite/cffwrite.c -+++ c/shared/source/cffwrite/cffwrite.c -@@ -488,7 +488,8 @@ +--- c/shared/cffwrite/cffwrite.cpp ++++ c/shared/cffwrite/cffwrite.cpp +@@ -469,7 +469,8 @@ return newFDIndex; } -int cfwMergeFDArray(cfwCtx g, abfTopDict *top, int *newFDIndex) { +long cfwMergeFDArray(void *g_, abfTopDict *top, int *newFDIndex) { -+ cfwCtx g = g_; ++ cfwCtx g = (cfwCtx)g_; abfFontDict *srcDict = &top->FDArray.array[0]; int i = 0; ---- c/shared/source/dynarr/dynarr.c -+++ c/shared/source/dynarr/dynarr.c +--- c/shared/dynarr.c ++++ c/shared/dynarr.c @@ -68,6 +68,9 @@ 0. If the client has arranged to trap allocation failures in the memory callback functions by using setjmp/longjmp, for example, the -1 return will @@ -80,9 +33,9 @@ long dnaGrow(void *object, size_t elemsize, long index) { void *new_ptr; size_t new_size; ---- c/shared/source/pstoken/pstoken.c -+++ c/shared/source/pstoken/pstoken.c -@@ -201,7 +201,7 @@ +--- c/shared/pstoken.cpp ++++ c/shared/pstoken.cpp +@@ -199,7 +199,7 @@ else { unsigned char cipher = hi_nib << 4 | nib; *dst++ = cipher ^ (h->cipher.r >> 8); @@ -91,7 +44,7 @@ hi_nib = -1; } } while (src < end); -@@ -232,7 +232,7 @@ +@@ -230,7 +230,7 @@ for (i = 0; i < length; i++) { unsigned char cipher = *src++; *dst++ = cipher ^ (h->cipher.r >> 8); @@ -100,9 +53,9 @@ } return 0; ---- c/shared/source/t1cstr/t1cstr.c -+++ c/shared/source/t1cstr/t1cstr.c -@@ -1504,13 +1504,13 @@ +--- c/shared/t1cstr.cpp ++++ c/shared/t1cstr.cpp +@@ -1494,13 +1494,13 @@ /* Prime state from random initial bytes */ while (lenIV--) @@ -118,29 +71,56 @@ } } return t1cSuccess; ---- c/shared/source/t1write/t1write.c -+++ c/shared/source/t1write/t1write.c -@@ -187,7 +187,7 @@ +@@ -1524,7 +1524,7 @@ + while (lenIV--) { + single = *c ^ (r2 >> 8); + r2 = (*c++ + r2) * 16477 + 21483; +- r1 = (single + r1) * 52845 + 22719; ++ r1 = (unsigned)(single + r1) * 52845 + 22719; + } + + /* Double decrypt and copy bytes */ +@@ -1533,7 +1533,7 @@ + single = c1 ^ (r2 >> 8); + r2 = (c1 + r2) * 16477 + 21483; + *p++ = single ^ (r1 >> 8); +- r1 = (single + r1) * 52845 + 22719; ++ r1 = (unsigned)(single + r1) * 52845 + 22719; + } + } + return t1cSuccess; +--- c/shared/t1write/t1write.cpp ++++ c/shared/t1write/t1write.cpp +@@ -166,7 +166,7 @@ char *q = buf; while (cnt--) { - unsigned char c = *p++ ^ h->eexec.r >> 8; + uint8_t c = *p++ ^ h->eexec.r >> 8; - h->eexec.r = (c + h->eexec.r) * 52845 + 22719; + h->eexec.r = (unsigned)(c + h->eexec.r) * 52845 + 22719; *q++ = hexmap[c >> 4 & 0xf]; *q++ = hexmap[c & 0xf]; } -@@ -376,7 +376,7 @@ +@@ -192,7 +192,7 @@ + /* Binary eexec; encrypt in-place */ + while (cnt--) { + uint8_t c = *p ^ h->eexec.r >> 8; +- h->eexec.r = (c + h->eexec.r) * 52845 + 22719; ++ h->eexec.r = (unsigned)(c + h->eexec.r) * 52845 + 22719; + *p++ = c; + } + writeDst(h, h->dst.cnt, h->dst.buf); +@@ -355,7 +355,7 @@ p = data; for (i = 0; i < length; i++) { - unsigned char c = *p ^ (r >> 8); + uint8_t c = *p ^ (r >> 8); - r = (c + r) * 52845 + 22719; + r = (unsigned)(c + r) * 52845 + 22719; *p++ = c; } ---- c/shared/source/t2cstr/t2cstr.c -+++ c/shared/source/t2cstr/t2cstr.c -@@ -673,7 +673,7 @@ +--- c/shared/t2cstr.cpp ++++ c/shared/t2cstr.cpp +@@ -661,7 +661,7 @@ /* Compute mask length and unused bit mask */ h->mask.length = (short)((h->stems.cnt + 7) / 8); @@ -149,9 +129,9 @@ return 0; } ---- c/shared/source/ttread/ttread.c -+++ c/shared/source/ttread/ttread.c -@@ -721,7 +721,7 @@ +--- c/shared/ttread.cpp ++++ c/shared/ttread.cpp +@@ -673,7 +673,7 @@ /* Read 4-byte signed number. */ static int32_t sread4(ttrCtx h) { diff --git a/external/afdko/warnings.patch b/external/afdko/warnings.patch deleted file mode 100644 index 9f5579dd709c..000000000000 --- a/external/afdko/warnings.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- afdko/c/shared/include/tx_shared.h -+++ afdko/c/shared/include/tx_shared.h -@@ -35,7 +35,7 @@ - #include - #include - --#if PLAT_MAC -+#ifdef PLAT_MAC - #include - #include - #endif /* PLAT_MAC */ -@@ -48,7 +48,7 @@ - #include - #include - --#if _WIN32 -+#ifdef _WIN32 - #include - #include - #define stat _stat diff --git a/external/beanshell/ExternalProject_beanshell.mk b/external/beanshell/ExternalProject_beanshell.mk index 604b3571fe44..cce25bd1d28b 100644 --- a/external/beanshell/ExternalProject_beanshell.mk +++ b/external/beanshell/ExternalProject_beanshell.mk @@ -13,13 +13,18 @@ $(eval $(call gb_ExternalProject_register_targets,beanshell,\ build \ )) +# older versions of ant expect SOURCE_DATE_EPOCH to be in milliseconds, so if set in environment +# that also would take precedence over the -Dant.tstam.now property and fail. That can be a problem +# if the variable is overridden/provided by exporting it in the env instead of passing it to make +# as a parameter. To counteract that problem, explicitly unset it here. $(call gb_ExternalProject_get_state_target,beanshell,build) : $(call gb_Trace_StartRange,beanshell,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/beanshell/UnpackedTarball_beanshell.mk b/external/beanshell/UnpackedTarball_beanshell.mk index ba472ebda6f1..91ee76f499b2 100644 --- a/external/beanshell/UnpackedTarball_beanshell.mk +++ b/external/beanshell/UnpackedTarball_beanshell.mk @@ -22,6 +22,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,beanshell,\ external/beanshell/beanshell-invoke.patch \ external/beanshell/java9.patch.0 \ external/beanshell/applet.patch.0 \ + external/beanshell/beanshell-jar-timestamps.patch.1 \ )) # vim: set noet sw=4 ts=4: diff --git a/external/beanshell/beanshell-jar-timestamps.patch.1 b/external/beanshell/beanshell-jar-timestamps.patch.1 new file mode 100644 index 000000000000..19671abe8b08 --- /dev/null +++ b/external/beanshell/beanshell-jar-timestamps.patch.1 @@ -0,0 +1,23 @@ +diff -ur beanshell.org/build.xml beanshell/build.xml +--- beanshell.org/build.xml 2026-06-24 14:37:04.303021292 +0000 ++++ beanshell/build.xml 2026-06-24 14:42:15.878048543 +0000 +@@ -11,7 +11,9 @@ + useful... + --> + +- ++ ++ ++ + + + +@@ -433,7 +435,7 @@ + + + +- ++ + + + diff --git a/external/boost/UnpackedTarball_boost.mk b/external/boost/UnpackedTarball_boost.mk index 23b9a3c23dc8..7520e82629d1 100644 --- a/external/boost/UnpackedTarball_boost.mk +++ b/external/boost/UnpackedTarball_boost.mk @@ -26,8 +26,6 @@ boost_patches += clang-cl.patch.0 boost_patches += boost_1_63_0.undef.warning.patch.1 boost_patches += windows-no-utf8-locales.patch.0 -boost_patches += msvc2017.patch.0 - boost_patches += boost-ios.patch.0 boost_patches += boost.file_iterator.sharing_win.patch @@ -36,6 +34,8 @@ boost_patches += Wundef.patch.0 boost_patches += boost.spirit.noreturn.patch +boost_patches += unreachable_code.patch.1 + $(eval $(call gb_UnpackedTarball_UnpackedTarball,boost)) $(eval $(call gb_UnpackedTarball_set_tarball,boost,$(BOOST_TARBALL))) diff --git a/external/boost/Wundef.patch.0 b/external/boost/Wundef.patch.0 index 8cb546464373..f3dd5c07ca01 100644 --- a/external/boost/Wundef.patch.0 +++ b/external/boost/Wundef.patch.0 @@ -1,16 +1,3 @@ ---- boost/config/workaround.hpp -+++ boost/config/workaround.hpp -@@ -264,6 +264,10 @@ - #else - #define BOOST_CLANG_VERSION_WORKAROUND_GUARD 0 - #endif -+ -+#if !defined BOOST_LIBSTDCXX_VERSION_WORKAROUND_GUARD -+#define BOOST_LIBSTDCXX_VERSION_WORKAROUND_GUARD 0 -+#endif - - // Always define to zero, if it's used it'll be defined my MPL: - #define BOOST_MPL_CFG_GCC_WORKAROUND_GUARD 0 --- boost/locale/detail/facet_id.hpp +++ boost/locale/detail/facet_id.hpp @@ -12,7 +12,7 @@ diff --git a/external/boost/include/boost/algorithm/string.hpp b/external/boost/include/boost/algorithm/string.hpp index 472a574f6a77..1ca5a3697e33 100644 --- a/external/boost/include/boost/algorithm/string.hpp +++ b/external/boost/include/boost/algorithm/string.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/algorithm/string/classification.hpp b/external/boost/include/boost/algorithm/string/classification.hpp index eb1aa76adbc2..561153008b84 100644 --- a/external/boost/include/boost/algorithm/string/classification.hpp +++ b/external/boost/include/boost/algorithm/string/classification.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/algorithm/string/join.hpp b/external/boost/include/boost/algorithm/string/join.hpp index 40609df2c811..e0bdae46b4d0 100644 --- a/external/boost/include/boost/algorithm/string/join.hpp +++ b/external/boost/include/boost/algorithm/string/join.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/algorithm/string/predicate.hpp b/external/boost/include/boost/algorithm/string/predicate.hpp index 915cc978d541..4a7f0bd0b762 100644 --- a/external/boost/include/boost/algorithm/string/predicate.hpp +++ b/external/boost/include/boost/algorithm/string/predicate.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/algorithm/string/replace.hpp b/external/boost/include/boost/algorithm/string/replace.hpp index a2589ad92c8b..bb74f42c1789 100644 --- a/external/boost/include/boost/algorithm/string/replace.hpp +++ b/external/boost/include/boost/algorithm/string/replace.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/algorithm/string/split.hpp b/external/boost/include/boost/algorithm/string/split.hpp index 315c3d2571d4..3c6670fd0288 100644 --- a/external/boost/include/boost/algorithm/string/split.hpp +++ b/external/boost/include/boost/algorithm/string/split.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/algorithm/string/trim.hpp b/external/boost/include/boost/algorithm/string/trim.hpp index 2c7215d533a9..ce7feb7ba0ca 100644 --- a/external/boost/include/boost/algorithm/string/trim.hpp +++ b/external/boost/include/boost/algorithm/string/trim.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/any.hpp b/external/boost/include/boost/any.hpp index a6dbf86b7fa4..11b330fc9542 100644 --- a/external/boost/include/boost/any.hpp +++ b/external/boost/include/boost/any.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/archive/iterators/base64_from_binary.hpp b/external/boost/include/boost/archive/iterators/base64_from_binary.hpp index 21215264a11c..8d3bb2c7c1fc 100644 --- a/external/boost/include/boost/archive/iterators/base64_from_binary.hpp +++ b/external/boost/include/boost/archive/iterators/base64_from_binary.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/archive/iterators/binary_from_base64.hpp b/external/boost/include/boost/archive/iterators/binary_from_base64.hpp index 1b77e76eab9c..d5cb3e726f74 100644 --- a/external/boost/include/boost/archive/iterators/binary_from_base64.hpp +++ b/external/boost/include/boost/archive/iterators/binary_from_base64.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/archive/iterators/remove_whitespace.hpp b/external/boost/include/boost/archive/iterators/remove_whitespace.hpp index 61a0314adb91..03acd4442f45 100644 --- a/external/boost/include/boost/archive/iterators/remove_whitespace.hpp +++ b/external/boost/include/boost/archive/iterators/remove_whitespace.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/archive/iterators/transform_width.hpp b/external/boost/include/boost/archive/iterators/transform_width.hpp index c2e23f004f0e..25e0ad55e32a 100644 --- a/external/boost/include/boost/archive/iterators/transform_width.hpp +++ b/external/boost/include/boost/archive/iterators/transform_width.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/asio/ip/tcp.hpp b/external/boost/include/boost/asio/ip/tcp.hpp new file mode 100644 index 000000000000..1bdc3531677a --- /dev/null +++ b/external/boost/include/boost/asio/ip/tcp.hpp @@ -0,0 +1,34 @@ +/* generated by bin/gen-boost-headers, do not edit! */ +#pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" /* first! for GCC */ +#pragma GCC diagnostic ignored "-Wunknown-warning-option" // second! for Clang 5 +#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" +#pragma GCC diagnostic ignored "-Wdeprecated-builtins" +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor" +#pragma GCC diagnostic ignored "-Wextra" +#pragma GCC diagnostic ignored "-Wignored-qualifiers" +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Winvalid-constexpr" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic ignored "-Wmicrosoft-unqualified-friend" +#pragma GCC diagnostic ignored "-Wnonnull" +#pragma GCC diagnostic ignored "-Wparentheses" +#pragma GCC diagnostic ignored "-Wplacement-new" +#pragma GCC diagnostic ignored "-Wreturn-type" +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#pragma GCC diagnostic ignored "-Wtype-limits" +#pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#pragma GCC diagnostic ignored "-Wunused-macros" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#include_next +#pragma GCC diagnostic pop diff --git a/external/boost/include/boost/beast/core.hpp b/external/boost/include/boost/beast/core.hpp new file mode 100644 index 000000000000..c31ae6505128 --- /dev/null +++ b/external/boost/include/boost/beast/core.hpp @@ -0,0 +1,34 @@ +/* generated by bin/gen-boost-headers, do not edit! */ +#pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" /* first! for GCC */ +#pragma GCC diagnostic ignored "-Wunknown-warning-option" // second! for Clang 5 +#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" +#pragma GCC diagnostic ignored "-Wdeprecated-builtins" +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor" +#pragma GCC diagnostic ignored "-Wextra" +#pragma GCC diagnostic ignored "-Wignored-qualifiers" +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Winvalid-constexpr" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic ignored "-Wmicrosoft-unqualified-friend" +#pragma GCC diagnostic ignored "-Wnonnull" +#pragma GCC diagnostic ignored "-Wparentheses" +#pragma GCC diagnostic ignored "-Wplacement-new" +#pragma GCC diagnostic ignored "-Wreturn-type" +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#pragma GCC diagnostic ignored "-Wtype-limits" +#pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#pragma GCC diagnostic ignored "-Wunused-macros" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#include_next +#pragma GCC diagnostic pop diff --git a/external/boost/include/boost/beast/http.hpp b/external/boost/include/boost/beast/http.hpp new file mode 100644 index 000000000000..fbb361894a0f --- /dev/null +++ b/external/boost/include/boost/beast/http.hpp @@ -0,0 +1,34 @@ +/* generated by bin/gen-boost-headers, do not edit! */ +#pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" /* first! for GCC */ +#pragma GCC diagnostic ignored "-Wunknown-warning-option" // second! for Clang 5 +#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" +#pragma GCC diagnostic ignored "-Wdeprecated-builtins" +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor" +#pragma GCC diagnostic ignored "-Wextra" +#pragma GCC diagnostic ignored "-Wignored-qualifiers" +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Winvalid-constexpr" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic ignored "-Wmicrosoft-unqualified-friend" +#pragma GCC diagnostic ignored "-Wnonnull" +#pragma GCC diagnostic ignored "-Wparentheses" +#pragma GCC diagnostic ignored "-Wplacement-new" +#pragma GCC diagnostic ignored "-Wreturn-type" +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#pragma GCC diagnostic ignored "-Wtype-limits" +#pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#pragma GCC diagnostic ignored "-Wunused-macros" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#include_next +#pragma GCC diagnostic pop diff --git a/external/boost/include/boost/bind/bind.hpp b/external/boost/include/boost/bind/bind.hpp index babdac2fd43e..0d97f583d8b8 100644 --- a/external/boost/include/boost/bind/bind.hpp +++ b/external/boost/include/boost/bind/bind.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/cast.hpp b/external/boost/include/boost/cast.hpp index ef9dca82f344..b37a9cf995a6 100644 --- a/external/boost/include/boost/cast.hpp +++ b/external/boost/include/boost/cast.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/circular_buffer.hpp b/external/boost/include/boost/circular_buffer.hpp index 6e963e818ef1..9210359a2540 100644 --- a/external/boost/include/boost/circular_buffer.hpp +++ b/external/boost/include/boost/circular_buffer.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/container/deque.hpp b/external/boost/include/boost/container/deque.hpp index cd8781e4b0b8..ad4631cb7362 100644 --- a/external/boost/include/boost/container/deque.hpp +++ b/external/boost/include/boost/container/deque.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/container/flat_map.hpp b/external/boost/include/boost/container/flat_map.hpp index 43a633c2fb44..2d08389abc4f 100644 --- a/external/boost/include/boost/container/flat_map.hpp +++ b/external/boost/include/boost/container/flat_map.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/container/small_vector.hpp b/external/boost/include/boost/container/small_vector.hpp index 2382383e1bab..167f7f3cfb00 100644 --- a/external/boost/include/boost/container/small_vector.hpp +++ b/external/boost/include/boost/container/small_vector.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/container/vector.hpp b/external/boost/include/boost/container/vector.hpp new file mode 100644 index 000000000000..2a0abf8d16cb --- /dev/null +++ b/external/boost/include/boost/container/vector.hpp @@ -0,0 +1,33 @@ +/* generated by bin/gen-boost-headers, do not edit! */ +#pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" /* first! for GCC */ +#pragma GCC diagnostic ignored "-Wunknown-warning-option" // second! for Clang 5 +#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" +#pragma GCC diagnostic ignored "-Wdeprecated-builtins" +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor" +#pragma GCC diagnostic ignored "-Wextra" +#pragma GCC diagnostic ignored "-Wignored-qualifiers" +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Winvalid-constexpr" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic ignored "-Wmicrosoft-unqualified-friend" +#pragma GCC diagnostic ignored "-Wnonnull" +#pragma GCC diagnostic ignored "-Wparentheses" +#pragma GCC diagnostic ignored "-Wplacement-new" +#pragma GCC diagnostic ignored "-Wreturn-type" +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#pragma GCC diagnostic ignored "-Wtype-limits" +#pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#pragma GCC diagnostic ignored "-Wunused-macros" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" +#pragma GCC diagnostic ignored "-Wunused-variable" +#include_next +#pragma GCC diagnostic pop diff --git a/external/boost/include/boost/core/noinit_adaptor.hpp b/external/boost/include/boost/core/noinit_adaptor.hpp index 4fb9b72da2e6..0241509994e9 100644 --- a/external/boost/include/boost/core/noinit_adaptor.hpp +++ b/external/boost/include/boost/core/noinit_adaptor.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/cstdint.hpp b/external/boost/include/boost/cstdint.hpp index 66e8c4321e00..8b9a54399700 100644 --- a/external/boost/include/boost/cstdint.hpp +++ b/external/boost/include/boost/cstdint.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/current_function.hpp b/external/boost/include/boost/current_function.hpp index 47002b61eaec..4a688acc3638 100644 --- a/external/boost/include/boost/current_function.hpp +++ b/external/boost/include/boost/current_function.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/date_time.hpp b/external/boost/include/boost/date_time.hpp index b9629a46d95e..6215c1fbc926 100644 --- a/external/boost/include/boost/date_time.hpp +++ b/external/boost/include/boost/date_time.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/date_time/gregorian/greg_date.hpp b/external/boost/include/boost/date_time/gregorian/greg_date.hpp index ffe15b05763e..9c36259d596b 100644 --- a/external/boost/include/boost/date_time/gregorian/greg_date.hpp +++ b/external/boost/include/boost/date_time/gregorian/greg_date.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/date_time/posix_time/posix_time.hpp b/external/boost/include/boost/date_time/posix_time/posix_time.hpp index f0ec8364e9fc..f637ed5cde6e 100644 --- a/external/boost/include/boost/date_time/posix_time/posix_time.hpp +++ b/external/boost/include/boost/date_time/posix_time/posix_time.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/enable_shared_from_this.hpp b/external/boost/include/boost/enable_shared_from_this.hpp index 261a77b97d51..877d1a33c838 100644 --- a/external/boost/include/boost/enable_shared_from_this.hpp +++ b/external/boost/include/boost/enable_shared_from_this.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/filesystem.hpp b/external/boost/include/boost/filesystem.hpp index 6efb78f6c811..c1f9c148f490 100644 --- a/external/boost/include/boost/filesystem.hpp +++ b/external/boost/include/boost/filesystem.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/filesystem/path.hpp b/external/boost/include/boost/filesystem/path.hpp index 7b3b4e265756..ed4133e0f352 100644 --- a/external/boost/include/boost/filesystem/path.hpp +++ b/external/boost/include/boost/filesystem/path.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/format.hpp b/external/boost/include/boost/format.hpp index b483226a628f..5a79532d02b8 100644 --- a/external/boost/include/boost/format.hpp +++ b/external/boost/include/boost/format.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/function.hpp b/external/boost/include/boost/function.hpp index 1d2e2a705da8..e7daca1aa76f 100644 --- a/external/boost/include/boost/function.hpp +++ b/external/boost/include/boost/function.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/functional/hash.hpp b/external/boost/include/boost/functional/hash.hpp index fe2cbf3d6687..ecbb2a718f34 100644 --- a/external/boost/include/boost/functional/hash.hpp +++ b/external/boost/include/boost/functional/hash.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/fusion/adapted/std_pair.hpp b/external/boost/include/boost/fusion/adapted/std_pair.hpp index bfc667ef9cd3..417ea25d25a6 100644 --- a/external/boost/include/boost/fusion/adapted/std_pair.hpp +++ b/external/boost/include/boost/fusion/adapted/std_pair.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/fusion/include/adapt_struct.hpp b/external/boost/include/boost/fusion/include/adapt_struct.hpp index f19c4694e432..38ec681ea916 100644 --- a/external/boost/include/boost/fusion/include/adapt_struct.hpp +++ b/external/boost/include/boost/fusion/include/adapt_struct.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/fusion/include/std_pair.hpp b/external/boost/include/boost/fusion/include/std_pair.hpp index bc115040eaac..a261762405f3 100644 --- a/external/boost/include/boost/fusion/include/std_pair.hpp +++ b/external/boost/include/boost/fusion/include/std_pair.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/interprocess/file_mapping.hpp b/external/boost/include/boost/interprocess/file_mapping.hpp index 8f3bb340be9d..75549b4620b8 100644 --- a/external/boost/include/boost/interprocess/file_mapping.hpp +++ b/external/boost/include/boost/interprocess/file_mapping.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/interprocess/mapped_region.hpp b/external/boost/include/boost/interprocess/mapped_region.hpp index bba283c8d527..29c9d1d92121 100644 --- a/external/boost/include/boost/interprocess/mapped_region.hpp +++ b/external/boost/include/boost/interprocess/mapped_region.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/intrusive/circular_list_algorithms.hpp b/external/boost/include/boost/intrusive/circular_list_algorithms.hpp index 456d4dbf47f3..c9db9773d862 100644 --- a/external/boost/include/boost/intrusive/circular_list_algorithms.hpp +++ b/external/boost/include/boost/intrusive/circular_list_algorithms.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/intrusive_ptr.hpp b/external/boost/include/boost/intrusive_ptr.hpp index 2b21a26f834e..819e051e54cc 100644 --- a/external/boost/include/boost/intrusive_ptr.hpp +++ b/external/boost/include/boost/intrusive_ptr.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/iostreams/device/file_descriptor.hpp b/external/boost/include/boost/iostreams/device/file_descriptor.hpp index 16517f28f17c..fa3f60456acc 100644 --- a/external/boost/include/boost/iostreams/device/file_descriptor.hpp +++ b/external/boost/include/boost/iostreams/device/file_descriptor.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/iostreams/filter/gzip.hpp b/external/boost/include/boost/iostreams/filter/gzip.hpp index 7f700501a290..7d32ee276a6c 100644 --- a/external/boost/include/boost/iostreams/filter/gzip.hpp +++ b/external/boost/include/boost/iostreams/filter/gzip.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/iostreams/filtering_stream.hpp b/external/boost/include/boost/iostreams/filtering_stream.hpp index a5f566c3a651..02ae15e0dcd4 100644 --- a/external/boost/include/boost/iostreams/filtering_stream.hpp +++ b/external/boost/include/boost/iostreams/filtering_stream.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/iterator/iterator_facade.hpp b/external/boost/include/boost/iterator/iterator_facade.hpp index b6610c19f03f..6933b20bb56d 100644 --- a/external/boost/include/boost/iterator/iterator_facade.hpp +++ b/external/boost/include/boost/iterator/iterator_facade.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/lexical_cast.hpp b/external/boost/include/boost/lexical_cast.hpp index 4f2d00e28d91..e46360e299a2 100644 --- a/external/boost/include/boost/lexical_cast.hpp +++ b/external/boost/include/boost/lexical_cast.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/locale.hpp b/external/boost/include/boost/locale.hpp index 6b9529635635..827a30bc4355 100644 --- a/external/boost/include/boost/locale.hpp +++ b/external/boost/include/boost/locale.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/locale/gnu_gettext.hpp b/external/boost/include/boost/locale/gnu_gettext.hpp index 5487b5d41b89..daafca51c84b 100644 --- a/external/boost/include/boost/locale/gnu_gettext.hpp +++ b/external/boost/include/boost/locale/gnu_gettext.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/make_shared.hpp b/external/boost/include/boost/make_shared.hpp index 7c8511076790..8dacaab6d88c 100644 --- a/external/boost/include/boost/make_shared.hpp +++ b/external/boost/include/boost/make_shared.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/math/constants/constants.hpp b/external/boost/include/boost/math/constants/constants.hpp index af2acf585aff..d1e818569bde 100644 --- a/external/boost/include/boost/math/constants/constants.hpp +++ b/external/boost/include/boost/math/constants/constants.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/math/special_functions/sinc.hpp b/external/boost/include/boost/math/special_functions/sinc.hpp index 38875f4f66cc..74b61d9934a3 100644 --- a/external/boost/include/boost/math/special_functions/sinc.hpp +++ b/external/boost/include/boost/math/special_functions/sinc.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/multi_array.hpp b/external/boost/include/boost/multi_array.hpp index 64a7b8002786..677a5fcf7004 100644 --- a/external/boost/include/boost/multi_array.hpp +++ b/external/boost/include/boost/multi_array.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/multi_index/composite_key.hpp b/external/boost/include/boost/multi_index/composite_key.hpp index dccd54eac08f..67c9377d8310 100644 --- a/external/boost/include/boost/multi_index/composite_key.hpp +++ b/external/boost/include/boost/multi_index/composite_key.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/multi_index/identity.hpp b/external/boost/include/boost/multi_index/identity.hpp index a3a8d3f0bf04..60aca2427454 100644 --- a/external/boost/include/boost/multi_index/identity.hpp +++ b/external/boost/include/boost/multi_index/identity.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/multi_index/mem_fun.hpp b/external/boost/include/boost/multi_index/mem_fun.hpp index be5343e1174d..904827160ef7 100644 --- a/external/boost/include/boost/multi_index/mem_fun.hpp +++ b/external/boost/include/boost/multi_index/mem_fun.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/multi_index/ordered_index.hpp b/external/boost/include/boost/multi_index/ordered_index.hpp index 3667290cef4e..daaa831eb0e8 100644 --- a/external/boost/include/boost/multi_index/ordered_index.hpp +++ b/external/boost/include/boost/multi_index/ordered_index.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/multi_index/random_access_index.hpp b/external/boost/include/boost/multi_index/random_access_index.hpp index 7e7f8a7ba16b..d5b3308c690a 100644 --- a/external/boost/include/boost/multi_index/random_access_index.hpp +++ b/external/boost/include/boost/multi_index/random_access_index.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/multi_index/tag.hpp b/external/boost/include/boost/multi_index/tag.hpp index 65b57f4de6af..24a38befb9b4 100644 --- a/external/boost/include/boost/multi_index/tag.hpp +++ b/external/boost/include/boost/multi_index/tag.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/multi_index_container.hpp b/external/boost/include/boost/multi_index_container.hpp index d7b7435f5947..9e5f36a3f834 100644 --- a/external/boost/include/boost/multi_index_container.hpp +++ b/external/boost/include/boost/multi_index_container.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/none.hpp b/external/boost/include/boost/none.hpp index e02a162ff400..04f18088e43d 100644 --- a/external/boost/include/boost/none.hpp +++ b/external/boost/include/boost/none.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/numeric/conversion/cast.hpp b/external/boost/include/boost/numeric/conversion/cast.hpp index 452ac4609c31..edfe11533be1 100644 --- a/external/boost/include/boost/numeric/conversion/cast.hpp +++ b/external/boost/include/boost/numeric/conversion/cast.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/operators.hpp b/external/boost/include/boost/operators.hpp index 266e511ff553..23aa780754e8 100644 --- a/external/boost/include/boost/operators.hpp +++ b/external/boost/include/boost/operators.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/optional.hpp b/external/boost/include/boost/optional.hpp index 4369bf77eec9..855ca09af10e 100644 --- a/external/boost/include/boost/optional.hpp +++ b/external/boost/include/boost/optional.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/phoenix.hpp b/external/boost/include/boost/phoenix.hpp index 674054aca90e..127b734cbb73 100644 --- a/external/boost/include/boost/phoenix.hpp +++ b/external/boost/include/boost/phoenix.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/pool/object_pool.hpp b/external/boost/include/boost/pool/object_pool.hpp index 9f109ff18157..4d46e525146f 100644 --- a/external/boost/include/boost/pool/object_pool.hpp +++ b/external/boost/include/boost/pool/object_pool.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/program_options.hpp b/external/boost/include/boost/program_options.hpp index b763a905e452..abd022273f1e 100644 --- a/external/boost/include/boost/program_options.hpp +++ b/external/boost/include/boost/program_options.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/property_tree/info_parser.hpp b/external/boost/include/boost/property_tree/info_parser.hpp index fe4c44aa4a88..aaf3660e5796 100644 --- a/external/boost/include/boost/property_tree/info_parser.hpp +++ b/external/boost/include/boost/property_tree/info_parser.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/property_tree/ini_parser.hpp b/external/boost/include/boost/property_tree/ini_parser.hpp index d510817939e3..4c7558996387 100644 --- a/external/boost/include/boost/property_tree/ini_parser.hpp +++ b/external/boost/include/boost/property_tree/ini_parser.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/property_tree/json_parser.hpp b/external/boost/include/boost/property_tree/json_parser.hpp index e6c24c19c60f..8c7c6dd876df 100644 --- a/external/boost/include/boost/property_tree/json_parser.hpp +++ b/external/boost/include/boost/property_tree/json_parser.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/property_tree/json_parser/error.hpp b/external/boost/include/boost/property_tree/json_parser/error.hpp index b4e084fc4406..5d59a0aa4c1f 100644 --- a/external/boost/include/boost/property_tree/json_parser/error.hpp +++ b/external/boost/include/boost/property_tree/json_parser/error.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/property_tree/ptree.hpp b/external/boost/include/boost/property_tree/ptree.hpp index f44ddac47b8b..1d7b199d8e9d 100644 --- a/external/boost/include/boost/property_tree/ptree.hpp +++ b/external/boost/include/boost/property_tree/ptree.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/property_tree/ptree_fwd.hpp b/external/boost/include/boost/property_tree/ptree_fwd.hpp index 2d85e28d7093..2e8b89844f06 100644 --- a/external/boost/include/boost/property_tree/ptree_fwd.hpp +++ b/external/boost/include/boost/property_tree/ptree_fwd.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/range/adaptor/reversed.hpp b/external/boost/include/boost/range/adaptor/reversed.hpp index 95b7c2dfcc46..d44ebc4862d5 100644 --- a/external/boost/include/boost/range/adaptor/reversed.hpp +++ b/external/boost/include/boost/range/adaptor/reversed.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/range/iterator_range.hpp b/external/boost/include/boost/range/iterator_range.hpp index 9252012d3edd..6c38433edf45 100644 --- a/external/boost/include/boost/range/iterator_range.hpp +++ b/external/boost/include/boost/range/iterator_range.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/rational.hpp b/external/boost/include/boost/rational.hpp index 9e879bb79f84..207dce7cd6da 100644 --- a/external/boost/include/boost/rational.hpp +++ b/external/boost/include/boost/rational.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/regex.hpp b/external/boost/include/boost/regex.hpp index 3c7465b41510..219846d48b7e 100644 --- a/external/boost/include/boost/regex.hpp +++ b/external/boost/include/boost/regex.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/scoped_ptr.hpp b/external/boost/include/boost/scoped_ptr.hpp index 4d2ac5f8bede..e26fed180a0f 100644 --- a/external/boost/include/boost/scoped_ptr.hpp +++ b/external/boost/include/boost/scoped_ptr.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/shared_ptr.hpp b/external/boost/include/boost/shared_ptr.hpp index a531a6760099..bd8765eb0c21 100644 --- a/external/boost/include/boost/shared_ptr.hpp +++ b/external/boost/include/boost/shared_ptr.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/smart_ptr/make_shared.hpp b/external/boost/include/boost/smart_ptr/make_shared.hpp index 3d9027174a4d..d047cdcc2b23 100644 --- a/external/boost/include/boost/smart_ptr/make_shared.hpp +++ b/external/boost/include/boost/smart_ptr/make_shared.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/classic.hpp b/external/boost/include/boost/spirit/include/classic.hpp index 08f9541b52fb..094b12ad43f2 100644 --- a/external/boost/include/boost/spirit/include/classic.hpp +++ b/external/boost/include/boost/spirit/include/classic.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/classic_core.hpp b/external/boost/include/boost/spirit/include/classic_core.hpp index 872bc6df4d09..9d0ffb339b4d 100644 --- a/external/boost/include/boost/spirit/include/classic_core.hpp +++ b/external/boost/include/boost/spirit/include/classic_core.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/classic_error_handling.hpp b/external/boost/include/boost/spirit/include/classic_error_handling.hpp index 8c15ad91e6e8..aac5e16de720 100644 --- a/external/boost/include/boost/spirit/include/classic_error_handling.hpp +++ b/external/boost/include/boost/spirit/include/classic_error_handling.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/classic_file_iterator.hpp b/external/boost/include/boost/spirit/include/classic_file_iterator.hpp index 3fd75cd603bc..c471761d9ba4 100644 --- a/external/boost/include/boost/spirit/include/classic_file_iterator.hpp +++ b/external/boost/include/boost/spirit/include/classic_file_iterator.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/classic_utility.hpp b/external/boost/include/boost/spirit/include/classic_utility.hpp index 30648200bf08..4ecd7ab65faa 100644 --- a/external/boost/include/boost/spirit/include/classic_utility.hpp +++ b/external/boost/include/boost/spirit/include/classic_utility.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/phoenix.hpp b/external/boost/include/boost/spirit/include/phoenix.hpp index 8051c7caff92..8d9d831f1d9f 100644 --- a/external/boost/include/boost/spirit/include/phoenix.hpp +++ b/external/boost/include/boost/spirit/include/phoenix.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/qi.hpp b/external/boost/include/boost/spirit/include/qi.hpp index 69389b5c84d2..3d9459577f56 100644 --- a/external/boost/include/boost/spirit/include/qi.hpp +++ b/external/boost/include/boost/spirit/include/qi.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/qi_attr.hpp b/external/boost/include/boost/spirit/include/qi_attr.hpp index 314f7e8cd5a7..9545a3ccb2a5 100644 --- a/external/boost/include/boost/spirit/include/qi_attr.hpp +++ b/external/boost/include/boost/spirit/include/qi_attr.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/qi_lit.hpp b/external/boost/include/boost/spirit/include/qi_lit.hpp index 66d7ad804ea9..60b6ad69c5bd 100644 --- a/external/boost/include/boost/spirit/include/qi_lit.hpp +++ b/external/boost/include/boost/spirit/include/qi_lit.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/qi_optional.hpp b/external/boost/include/boost/spirit/include/qi_optional.hpp index c6b4b90fbaca..d5372a495f0b 100644 --- a/external/boost/include/boost/spirit/include/qi_optional.hpp +++ b/external/boost/include/boost/spirit/include/qi_optional.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/qi_parse_attr.hpp b/external/boost/include/boost/spirit/include/qi_parse_attr.hpp index 399df002e93a..2e9a50d1e4e9 100644 --- a/external/boost/include/boost/spirit/include/qi_parse_attr.hpp +++ b/external/boost/include/boost/spirit/include/qi_parse_attr.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/qi_sequence.hpp b/external/boost/include/boost/spirit/include/qi_sequence.hpp index ed6dbf821d98..81f74e87fb20 100644 --- a/external/boost/include/boost/spirit/include/qi_sequence.hpp +++ b/external/boost/include/boost/spirit/include/qi_sequence.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/spirit/include/qi_symbols.hpp b/external/boost/include/boost/spirit/include/qi_symbols.hpp index f8e479ddf039..ee5c03cad016 100644 --- a/external/boost/include/boost/spirit/include/qi_symbols.hpp +++ b/external/boost/include/boost/spirit/include/qi_symbols.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/static_assert.hpp b/external/boost/include/boost/static_assert.hpp index 52a3cb459414..4b52f78bd464 100644 --- a/external/boost/include/boost/static_assert.hpp +++ b/external/boost/include/boost/static_assert.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/system/error_code.hpp b/external/boost/include/boost/system/error_code.hpp index a78acae4d303..2790e8037b80 100644 --- a/external/boost/include/boost/system/error_code.hpp +++ b/external/boost/include/boost/system/error_code.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/type_index.hpp b/external/boost/include/boost/type_index.hpp index 2b45b772f9df..9019b3ab632c 100644 --- a/external/boost/include/boost/type_index.hpp +++ b/external/boost/include/boost/type_index.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/type_traits/function_traits.hpp b/external/boost/include/boost/type_traits/function_traits.hpp index 34d4da4556b9..cd20b8050bad 100644 --- a/external/boost/include/boost/type_traits/function_traits.hpp +++ b/external/boost/include/boost/type_traits/function_traits.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/unordered_map.hpp b/external/boost/include/boost/unordered_map.hpp index a5b6251cde89..b76271a04e74 100644 --- a/external/boost/include/boost/unordered_map.hpp +++ b/external/boost/include/boost/unordered_map.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/uuid/detail/sha1.hpp b/external/boost/include/boost/uuid/detail/sha1.hpp index fc48b0a98787..7c07a37612f8 100644 --- a/external/boost/include/boost/uuid/detail/sha1.hpp +++ b/external/boost/include/boost/uuid/detail/sha1.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/uuid/sha1.hpp b/external/boost/include/boost/uuid/sha1.hpp index 36356294490c..22a083169bb6 100644 --- a/external/boost/include/boost/uuid/sha1.hpp +++ b/external/boost/include/boost/uuid/sha1.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/uuid/uuid.hpp b/external/boost/include/boost/uuid/uuid.hpp index 0a629f2c325d..2303305ed33b 100644 --- a/external/boost/include/boost/uuid/uuid.hpp +++ b/external/boost/include/boost/uuid/uuid.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/uuid/uuid_generators.hpp b/external/boost/include/boost/uuid/uuid_generators.hpp index 9cf428738b5e..c3d827b3221f 100644 --- a/external/boost/include/boost/uuid/uuid_generators.hpp +++ b/external/boost/include/boost/uuid/uuid_generators.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/uuid/uuid_io.hpp b/external/boost/include/boost/uuid/uuid_io.hpp index a605a8c0ede5..313c3d2952e5 100644 --- a/external/boost/include/boost/uuid/uuid_io.hpp +++ b/external/boost/include/boost/uuid/uuid_io.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/variant.hpp b/external/boost/include/boost/variant.hpp index adda214637cb..3fb7e0346a1c 100644 --- a/external/boost/include/boost/variant.hpp +++ b/external/boost/include/boost/variant.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/variant/recursive_variant.hpp b/external/boost/include/boost/variant/recursive_variant.hpp index 23491f236c88..8ecb18ecdd6f 100644 --- a/external/boost/include/boost/variant/recursive_variant.hpp +++ b/external/boost/include/boost/variant/recursive_variant.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/include/boost/version.hpp b/external/boost/include/boost/version.hpp index f0d78c0acac1..fb7da5bdb809 100644 --- a/external/boost/include/boost/version.hpp +++ b/external/boost/include/boost/version.hpp @@ -27,6 +27,7 @@ #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-template" #pragma GCC diagnostic ignored "-Wunused-variable" #include_next #pragma GCC diagnostic pop diff --git a/external/boost/msvc2017.patch.0 b/external/boost/msvc2017.patch.0 deleted file mode 100644 index 4b1002a17e96..000000000000 --- a/external/boost/msvc2017.patch.0 +++ /dev/null @@ -1,17 +0,0 @@ ---- boost/iterator.hpp -+++ boost/iterator.hpp -@@ -13,7 +13,14 @@ - namespace boost - { - -+#if defined _MSC_VER && !defined __clang__ -+#pragma warning(push) -+#pragma warning(disable: 4996) -+#endif - using std::iterator; -+#if defined _MSC_VER && !defined __clang__ -+#pragma warning(pop) -+#endif - - } // namespace boost - diff --git a/external/boost/unreachable_code.patch.1 b/external/boost/unreachable_code.patch.1 new file mode 100644 index 000000000000..848a1c26d459 --- /dev/null +++ b/external/boost/unreachable_code.patch.1 @@ -0,0 +1,13 @@ +--- a/boost/optional/detail/union_optional.hpp ++++ b/boost/optional/detail/union_optional.hpp +@@ -597,7 +597,9 @@ namespace boost { + + constexpr reference_const_type value() const& + { +- return this->is_initialized() ? this->get() : (boost::throw_exception(boost::bad_optional_access()), this->get()); ++ if (!this->is_initialized()) ++ boost::throw_exception(boost::bad_optional_access()); ++ return this->get(); + } + + BOOST_CXX14_CONSTEXPR reference_type value() & diff --git a/external/box2d/StaticLibrary_box2d.mk b/external/box2d/StaticLibrary_box2d.mk index ac16db04e176..50875b838476 100644 --- a/external/box2d/StaticLibrary_box2d.mk +++ b/external/box2d/StaticLibrary_box2d.mk @@ -17,56 +17,51 @@ $(eval $(call gb_StaticLibrary_set_generated_cxx_suffix,box2d,cpp)) $(eval $(call gb_StaticLibrary_set_include,box2d,\ -I$(gb_UnpackedTarball_workdir)/box2d/include/\ - -I$(gb_UnpackedTarball_workdir)/box2d/src/\ + -I$(gb_UnpackedTarball_workdir)/box2d/extern/simde/\ $$(INCLUDE)\ )) -$(eval $(call gb_StaticLibrary_add_generated_exception_objects,box2d,\ - UnpackedTarball/box2d/src/common/b2_timer \ - UnpackedTarball/box2d/src/common/b2_stack_allocator \ - UnpackedTarball/box2d/src/common/b2_draw \ - UnpackedTarball/box2d/src/common/b2_math \ - UnpackedTarball/box2d/src/common/b2_block_allocator \ - UnpackedTarball/box2d/src/common/b2_settings \ - UnpackedTarball/box2d/src/dynamics/b2_body \ - UnpackedTarball/box2d/src/dynamics/b2_polygon_circle_contact \ - UnpackedTarball/box2d/src/dynamics/b2_circle_contact \ - UnpackedTarball/box2d/src/dynamics/b2_contact_solver \ - UnpackedTarball/box2d/src/dynamics/b2_polygon_contact \ - UnpackedTarball/box2d/src/dynamics/b2_chain_polygon_contact \ - UnpackedTarball/box2d/src/dynamics/b2_chain_circle_contact \ - UnpackedTarball/box2d/src/dynamics/b2_contact \ - UnpackedTarball/box2d/src/dynamics/b2_edge_polygon_contact \ - UnpackedTarball/box2d/src/dynamics/b2_edge_circle_contact \ - UnpackedTarball/box2d/src/dynamics/b2_wheel_joint \ - UnpackedTarball/box2d/src/dynamics/b2_friction_joint \ - UnpackedTarball/box2d/src/dynamics/b2_prismatic_joint \ - UnpackedTarball/box2d/src/dynamics/b2_weld_joint \ - UnpackedTarball/box2d/src/dynamics/b2_pulley_joint \ - UnpackedTarball/box2d/src/dynamics/b2_mouse_joint \ - UnpackedTarball/box2d/src/dynamics/b2_motor_joint \ - UnpackedTarball/box2d/src/dynamics/b2_distance_joint \ - UnpackedTarball/box2d/src/dynamics/b2_gear_joint \ - UnpackedTarball/box2d/src/dynamics/b2_joint \ - UnpackedTarball/box2d/src/dynamics/b2_revolute_joint \ - UnpackedTarball/box2d/src/dynamics/b2_world_callbacks \ - UnpackedTarball/box2d/src/dynamics/b2_fixture \ - UnpackedTarball/box2d/src/dynamics/b2_contact_manager \ - UnpackedTarball/box2d/src/dynamics/b2_island \ - UnpackedTarball/box2d/src/dynamics/b2_world \ - UnpackedTarball/box2d/src/rope/b2_rope \ - UnpackedTarball/box2d/src/collision/b2_time_of_impact \ - UnpackedTarball/box2d/src/collision/b2_collide_polygon \ - UnpackedTarball/box2d/src/collision/b2_distance \ - UnpackedTarball/box2d/src/collision/b2_collision \ - UnpackedTarball/box2d/src/collision/b2_collide_edge \ - UnpackedTarball/box2d/src/collision/b2_collide_circle \ - UnpackedTarball/box2d/src/collision/b2_broad_phase \ - UnpackedTarball/box2d/src/collision/b2_edge_shape \ - UnpackedTarball/box2d/src/collision/b2_circle_shape \ - UnpackedTarball/box2d/src/collision/b2_chain_shape \ - UnpackedTarball/box2d/src/collision/b2_polygon_shape \ - UnpackedTarball/box2d/src/collision/b2_dynamic_tree \ +ifeq ($(OS),WNT) +$(eval $(call gb_StaticLibrary_add_cflags,box2d,\ + /std:c17 /experimental:c11atomics \ +)) +endif + +$(eval $(call gb_StaticLibrary_add_generated_cobjects,box2d,\ + UnpackedTarball/box2d/src/aabb \ + UnpackedTarball/box2d/src/arena_allocator \ + UnpackedTarball/box2d/src/body \ + UnpackedTarball/box2d/src/dynamic_tree \ + UnpackedTarball/box2d/src/island \ + UnpackedTarball/box2d/src/motor_joint \ + UnpackedTarball/box2d/src/table \ + UnpackedTarball/box2d/src/wheel_joint \ + UnpackedTarball/box2d/src/broad_phase \ + UnpackedTarball/box2d/src/core \ + UnpackedTarball/box2d/src/geometry \ + UnpackedTarball/box2d/src/joint \ + UnpackedTarball/box2d/src/mouse_joint \ + UnpackedTarball/box2d/src/shape \ + UnpackedTarball/box2d/src/timer \ + UnpackedTarball/box2d/src/world \ + UnpackedTarball/box2d/src/array \ + UnpackedTarball/box2d/src/constraint_graph \ + UnpackedTarball/box2d/src/distance \ + UnpackedTarball/box2d/src/hull \ + UnpackedTarball/box2d/src/manifold \ + UnpackedTarball/box2d/src/prismatic_joint \ + UnpackedTarball/box2d/src/types \ + UnpackedTarball/box2d/src/bitset \ + UnpackedTarball/box2d/src/contact \ + UnpackedTarball/box2d/src/contact_solver \ + UnpackedTarball/box2d/src/distance_joint \ + UnpackedTarball/box2d/src/id_pool \ + UnpackedTarball/box2d/src/math_functions \ + UnpackedTarball/box2d/src/revolute_joint \ + UnpackedTarball/box2d/src/sensor \ + UnpackedTarball/box2d/src/solver \ + UnpackedTarball/box2d/src/solver_set \ + UnpackedTarball/box2d/src/weld_joint \ )) # vim: set noet sw=4 ts=4: diff --git a/external/box2d/UnpackedTarball_box2d.mk b/external/box2d/UnpackedTarball_box2d.mk index 340a17511711..fa23b5b9782a 100644 --- a/external/box2d/UnpackedTarball_box2d.mk +++ b/external/box2d/UnpackedTarball_box2d.mk @@ -11,4 +11,8 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,box2d)) $(eval $(call gb_UnpackedTarball_set_tarball,box2d,$(BOX2D_TARBALL))) +$(eval $(call gb_UnpackedTarball_add_patches,box2d, \ + external/box2d/wasm.patch \ +)) + # vim: set noet sw=4 ts=4: diff --git a/external/box2d/wasm.patch b/external/box2d/wasm.patch new file mode 100644 index 000000000000..92eb14a97e94 --- /dev/null +++ b/external/box2d/wasm.patch @@ -0,0 +1,13 @@ +--- box2d/src/core.h 2026-05-08 15:52:10.437558753 +0200 ++++ box2d/src/core.h 2026-05-08 15:53:32.176900568 +0200 +@@ -72,10 +72,6 @@ + #elif defined( B2_CPU_ARM ) + #define B2_SIMD_NEON + #define B2_SIMD_WIDTH 4 +- #elif defined( B2_CPU_WASM ) +- #define B2_CPU_WASM +- #define B2_SIMD_SSE2 +- #define B2_SIMD_WIDTH 4 + #else + #define B2_SIMD_NONE + #define B2_SIMD_WIDTH 4 diff --git a/external/breakpad/UnpackedTarball_breakpad.mk b/external/breakpad/UnpackedTarball_breakpad.mk index ce553e334251..a2113c0c456b 100644 --- a/external/breakpad/UnpackedTarball_breakpad.mk +++ b/external/breakpad/UnpackedTarball_breakpad.mk @@ -36,6 +36,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,breakpad,\ external/breakpad/SIGSTKSZ.patch \ external/breakpad/sanitizer.patch \ external/breakpad/include.patch \ + external/breakpad/no-checked_array_iterator.patch \ )) $(eval $(call gb_UnpackedTarball_add_files,breakpad,src/tools/windows/dump_syms,\ diff --git a/external/breakpad/no-checked_array_iterator.patch b/external/breakpad/no-checked_array_iterator.patch new file mode 100644 index 000000000000..110415a70421 --- /dev/null +++ b/external/breakpad/no-checked_array_iterator.patch @@ -0,0 +1,16 @@ +--- src/client/windows/crash_generation/minidump_generator.cc ++++ src/client/windows/crash_generation/minidump_generator.cc +@@ -176,13 +176,7 @@ + stream_data->Reserved = 0; + std::copy(operations_.begin(), + operations_.end(), +-#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) +- stdext::checked_array_iterator( +- reinterpret_cast(stream_data + 1), +- operations_.size()) +-#else + reinterpret_cast(stream_data + 1) +-#endif + ); + + return true; diff --git a/external/lpsolve/Makefile b/external/brotli/Makefile similarity index 100% rename from external/lpsolve/Makefile rename to external/brotli/Makefile diff --git a/external/more_fonts/UnpackedTarball_agdasima.mk b/external/brotli/Module_brotli.mk similarity index 69% rename from external/more_fonts/UnpackedTarball_agdasima.mk rename to external/brotli/Module_brotli.mk index 5c003c18cbfd..657998a67dec 100644 --- a/external/more_fonts/UnpackedTarball_agdasima.mk +++ b/external/brotli/Module_brotli.mk @@ -7,8 +7,11 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # -$(eval $(call gb_UnpackedTarball_UnpackedTarball,font_agdasima)) +$(eval $(call gb_Module_Module,brotli)) -$(eval $(call gb_UnpackedTarball_set_tarball,font_agdasima,$(FONT_AGDASIMA_TARBALL),0)) +$(eval $(call gb_Module_add_targets,brotli,\ + StaticLibrary_brotli \ + UnpackedTarball_brotli \ +)) # vim: set noet sw=4 ts=4: diff --git a/external/brotli/README b/external/brotli/README new file mode 100644 index 000000000000..ab203ab248b6 --- /dev/null +++ b/external/brotli/README @@ -0,0 +1,3 @@ +brotli is a lossless compression algorithm using the "stream" format. + +From [https://github.com/google/brotli]. diff --git a/external/brotli/StaticLibrary_brotli.mk b/external/brotli/StaticLibrary_brotli.mk new file mode 100644 index 000000000000..6bd8ea7c5bbe --- /dev/null +++ b/external/brotli/StaticLibrary_brotli.mk @@ -0,0 +1,72 @@ +# -*- 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_StaticLibrary_StaticLibrary,brotli)) + +$(eval $(call gb_StaticLibrary_use_unpacked,brotli,brotli)) + +$(eval $(call gb_StaticLibrary_set_warnings_disabled,brotli)) + +$(eval $(call gb_StaticLibrary_set_include,brotli,\ + -I$(WORKDIR)/UnpackedTarball/brotli \ + -I$(WORKDIR)/UnpackedTarball/brotli/c/include \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_StaticLibrary_add_generated_cobjects,brotli,\ + $(addprefix UnpackedTarball/brotli/c/common/, \ + constants \ + context \ + dictionary \ + platform \ + shared_dictionary \ + transform \ + ) \ +)) + +$(eval $(call gb_StaticLibrary_add_generated_cobjects,brotli,\ + $(addprefix UnpackedTarball/brotli/c/enc/, \ + backward_references \ + backward_references_hq \ + bit_cost \ + block_splitter \ + brotli_bit_stream \ + cluster \ + command \ + compound_dictionary \ + compress_fragment \ + compress_fragment_two_pass \ + dictionary_hash \ + encode \ + encoder_dict \ + entropy_encode \ + fast_log \ + histogram \ + literal_cost \ + memory \ + metablock \ + static_dict \ + static_dict_lut \ + static_init \ + utf8_util \ + ) \ +)) + +$(eval $(call gb_StaticLibrary_add_generated_cobjects,brotli,\ + $(addprefix UnpackedTarball/brotli/c/dec/, \ + bit_reader \ + decode \ + huffman \ + prefix \ + state \ + static_init \ + ) \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/UnpackedTarball_lunasima.mk b/external/brotli/UnpackedTarball_brotli.mk similarity index 69% rename from external/more_fonts/UnpackedTarball_lunasima.mk rename to external/brotli/UnpackedTarball_brotli.mk index 0b75460a740e..3d02dbfe09b0 100644 --- a/external/more_fonts/UnpackedTarball_lunasima.mk +++ b/external/brotli/UnpackedTarball_brotli.mk @@ -7,8 +7,8 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # -$(eval $(call gb_UnpackedTarball_UnpackedTarball,font_lunasima)) +$(eval $(call gb_UnpackedTarball_UnpackedTarball,brotli)) -$(eval $(call gb_UnpackedTarball_set_tarball,font_lunasima,$(FONT_LUNASIMA_TARBALL),0)) +$(eval $(call gb_UnpackedTarball_set_tarball,brotli,$(BROTLI_TARBALL))) # vim: set noet sw=4 ts=4: diff --git a/external/cairo/UnpackedTarball_cairo.mk b/external/cairo/UnpackedTarball_cairo.mk index aa80de736d50..b5d2442add55 100644 --- a/external/cairo/UnpackedTarball_cairo.mk +++ b/external/cairo/UnpackedTarball_cairo.mk @@ -25,7 +25,6 @@ endif $(eval $(call gb_UnpackedTarball_add_patches,cairo,\ external/cairo/cairo/cairo.RGB24_888.patch \ external/cairo/cairo/san.patch.0 \ - external/cairo/cairo/cairo-fd-hack.patch.0 \ external/cairo/cairo/cairo.ofz57493-Timeout.patch.1 \ external/cairo/cairo/shm-null-deref.patch.1 \ external/cairo/cairo/avoid-negative-left-shift.patch.1 \ diff --git a/external/cairo/cairo/cairo-fd-hack.patch.0 b/external/cairo/cairo/cairo-fd-hack.patch.0 deleted file mode 100644 index e5d980e94dfb..000000000000 --- a/external/cairo/cairo/cairo-fd-hack.patch.0 +++ /dev/null @@ -1,15 +0,0 @@ -# -*- Mode: Diff -*- ---- src/cairo-ft-font.c -+++ src/cairo-ft-font.c -@@ -737,7 +737,10 @@ - if (ret == FcResultOutOfMemory) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - if (ret == FcResultMatch) { -- if (access (filename, R_OK) == 0) { -+ int nFD = -1; -+ int n; -+ if ((sscanf (filename, "/:FD:/%d%n", &nFD, &n) == 1 && filename[n] == '\0') || -+ access (filename, R_OK) == 0) { - /* If FC_INDEX is not set, we just use 0 */ - ret = FcPatternGetInteger (pattern, FC_INDEX, 0, &id); - if (ret == FcResultOutOfMemory) diff --git a/external/coinmp/ubsan.patch.0 b/external/coinmp/ubsan.patch.0 index 157332986098..116dbca61a18 100644 --- a/external/coinmp/ubsan.patch.0 +++ b/external/coinmp/ubsan.patch.0 @@ -1,3 +1,153 @@ +--- Cbc/src/CbcModel.cpp ++++ Cbc/src/CbcModel.cpp +@@ -7107,7 +7107,7 @@ + { + CbcCutGenerator ** temp = generator_; + generator_ = new CbcCutGenerator * [numberCutGenerators_+1]; +- memcpy(generator_, temp, numberCutGenerators_*sizeof(CbcCutGenerator *)); ++ if (numberCutGenerators_ != 0) memcpy(generator_, temp, numberCutGenerators_*sizeof(CbcCutGenerator *)); + delete[] temp ; + generator_[numberCutGenerators_] = + new CbcCutGenerator(this, generator, howOften, name, +@@ -7116,7 +7116,7 @@ + // and before any changes + temp = virginGenerator_; + virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_+1]; +- memcpy(virginGenerator_, temp, numberCutGenerators_*sizeof(CbcCutGenerator *)); ++ if (numberCutGenerators_ != 0) memcpy(virginGenerator_, temp, numberCutGenerators_*sizeof(CbcCutGenerator *)); + delete[] temp ; + virginGenerator_[numberCutGenerators_++] = + new CbcCutGenerator(this, generator, howOften, name, +@@ -7131,7 +7131,7 @@ + { + CbcHeuristic ** temp = heuristic_; + heuristic_ = new CbcHeuristic * [numberHeuristics_+1]; +- memcpy(heuristic_, temp, numberHeuristics_*sizeof(CbcHeuristic *)); ++ if (numberHeuristics_ != 0) memcpy(heuristic_, temp, numberHeuristics_*sizeof(CbcHeuristic *)); + delete [] temp; + int where; + if (before < 0 || before >= numberHeuristics_) { +@@ -9329,8 +9329,8 @@ + adjustment should be made for calling frequency. + */ + int iProbing = -1; +- double smallProblem = (0.2 * totalCuts) / +- static_cast (numberActiveGenerators) ; ++ double smallProblem = numberActiveGenerators == 0 ? 0.0 : (0.2 * totalCuts) / ++ static_cast (numberActiveGenerators); + for (i = 0; i < numberCutGenerators_; i++) { + int howOften = generator_[i]->howOften() ; + /* Probing can be set to just do column cuts in treee. +@@ -9350,7 +9350,7 @@ + bool probingWasOnBut = false; + CglProbing * probing = dynamic_cast(generator_[i]->generator()); + if (probing && !numberNodes_) { +- if (generator_[i]->numberCutsInTotal()) { ++ if (generator_[i]->numberCutsInTotal() && numberActiveGenerators != 1) { + // If large number of probing - can be biased + smallProblem = (0.2 * (totalCuts - generator_[i]->numberCutsInTotal())) / + static_cast (numberActiveGenerators - 1) ; +@@ -11501,7 +11501,7 @@ + } + delete [] mark; + // Now append other objects +- memcpy(object_ + numberIntegers_, oldObject, nObjects*sizeof(OsiObject *)); ++ if (nObjects != 0) memcpy(object_ + numberIntegers_, oldObject, nObjects*sizeof(OsiObject *)); + // Delete old array (just array) + delete [] oldObject; + +--- Cgl/src/CglClique/CglCliqueHelper.cpp ++++ Cgl/src/CglClique/CglCliqueHelper.cpp +@@ -293,7 +293,7 @@ + nodes[i].nbrs = all_nbr + old_total; + } + +- fgraph.density = static_cast (total_deg) / (sp_numcols * (sp_numcols-1)); ++ fgraph.density = sp_numcols == 1 ? 0.0 : static_cast (total_deg) / (sp_numcols * (sp_numcols-1)); + + /*========================================================================* + Compute the min and max degree. +--- Cgl/src/CglGomory/CglGomory.cpp ++++ Cgl/src/CglGomory/CglGomory.cpp +@@ -2,6 +2,8 @@ + // Corporation and others. All Rights Reserved. + // This code is licensed under the terms of the Eclipse Public License (EPL). + ++#include ++#include + #include + #include + #include +@@ -1314,7 +1316,7 @@ + for (j=0; j (dxInt+0.5); ++ xInt[j]= static_cast (std::min(std::max(dxInt, std::numeric_limits::min()), std::numeric_limits::max())+0.5); + #if CGL_DEBUG>1 + printf("%g => %g \n",value,dxInt); + #endif +--- Cgl/src/CglKnapsackCover/CglKnapsackCover.cpp ++++ Cgl/src/CglKnapsackCover/CglKnapsackCover.cpp +@@ -3,6 +3,8 @@ + // Corporation and others. All Rights Reserved. + // This code is licensed under the terms of the Eclipse Public License (EPL). + ++#include ++#include + #include + #include + #include +@@ -3905,7 +3907,7 @@ + } + } + int iUpper = static_cast (floor(upperValue+1.0e-5)); +- int iLower = static_cast (ceil(lowerValue-1.0e-5)); ++ int iLower = static_cast (ceil(std::min(std::max(lowerValue, std::numeric_limits::min()), std::numeric_limits::max())-1.0e-5)); + int state=0; + if (upperValue<1.0e6) { + if (iUpper==1-numberM1) +--- Cgl/src/CglPreProcess/CglPreProcess.cpp ++++ Cgl/src/CglPreProcess/CglPreProcess.cpp +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + + #include "CoinPragma.hpp" +@@ -1718,8 +1719,8 @@ + } + if (allPlus) + nPossible++; +- int iUpper = static_cast (floor(upperValue+1.0e-5)); +- int iLower = static_cast (ceil(lowerValue-1.0e-5)); ++ int iUpper = static_cast (floor(std::min(std::max(upperValue, std::numeric_limits::min()), std::numeric_limits::max())+1.0e-5)); ++ int iLower = static_cast (ceil(std::min(std::max(lowerValue, std::numeric_limits::min()), std::numeric_limits::max())-1.0e-5)); + int state=0; + if (upperValue<1.0e6) { + if (iUpper==1-numberM1) +@@ -6429,7 +6430,7 @@ + { + CglCutGenerator ** temp = generator_; + generator_ = new CglCutGenerator * [numberCutGenerators_+1]; +- memcpy(generator_,temp,numberCutGenerators_*sizeof(CglCutGenerator *)); ++ if (numberCutGenerators_ != 0) memcpy(generator_,temp,numberCutGenerators_*sizeof(CglCutGenerator *)); + delete[] temp ; + generator_[numberCutGenerators_++]=generator->clone(); + } +--- Cgl/src/CglTwomir/CglTwomir.cpp ++++ Cgl/src/CglTwomir/CglTwomir.cpp +@@ -1779,7 +1779,7 @@ + norm_val += (cut->coeff[i]*cut->coeff[i]); + } + +- norm_val /= cut->rhs * cut->rhs; ++ norm_val = cut->rhs == 0 ? COIN_DBL_MAX : norm_val / (cut->rhs * cut->rhs); + + if (rc_val < best_rc_val ) { + best_rc_val = rc_val; best_rc_alpha = alpha; } --- Clp/src/ClpParameters.hpp +++ Clp/src/ClpParameters.hpp @@ -81,7 +81,7 @@ @@ -9,3 +159,23 @@ } /// And set template inline void +--- Clp/src/ClpSimplex.cpp ++++ Clp/src/ClpSimplex.cpp +@@ -2557,14 +2557,14 @@ + numberTotal = 2 * (maximumInternalColumns_ + maximumInternalRows_); + } + lower_ = ClpCopyOfArray(rhs.lower_, numberTotal); +- rowLowerWork_ = lower_ + numberColumns_; ++ rowLowerWork_ = lower_ == nullptr ? nullptr : lower_ + numberColumns_; + columnLowerWork_ = lower_; + upper_ = ClpCopyOfArray(rhs.upper_, numberTotal); +- rowUpperWork_ = upper_ + numberColumns_; ++ rowUpperWork_ = upper_ == nullptr ? nullptr : upper_ + numberColumns_; + columnUpperWork_ = upper_; + cost_ = ClpCopyOfArray(rhs.cost_, numberTotal); + objectiveWork_ = cost_; +- rowObjectiveWork_ = cost_ + numberColumns_; ++ rowObjectiveWork_ = cost_ == nullptr ? nullptr : cost_ + numberColumns_; + dj_ = ClpCopyOfArray(rhs.dj_, numberTotal); + if (dj_) { + reducedCostWork_ = dj_; diff --git a/external/cppunit/ExternalProject_cppunit.mk b/external/cppunit/ExternalProject_cppunit.mk index f0b4ff06acce..e20ceab8a940 100644 --- a/external/cppunit/ExternalProject_cppunit.mk +++ b/external/cppunit/ExternalProject_cppunit.mk @@ -52,6 +52,7 @@ $(call gb_ExternalProject_get_state_target,cppunit,build) : $(if $(filter SOLARIS,$(OS)),LIBS="-lm") \ $(if $(filter ANDROID,$(OS)),LIBS="$(gb_STDLIBS)") \ $(if $(verbose),--disable-silent-rules,--enable-silent-rules) \ + $(if $(ENABLE_DEBUG),--enable-debug,--disable-debug) \ CXXFLAGS="$(cppunit_CXXFLAGS)" \ && cd src \ && $(MAKE) \ diff --git a/external/curl/zlib.patch.0 b/external/curl/zlib.patch.0 index c334d6de452b..400f01d54f40 100644 --- a/external/curl/zlib.patch.0 +++ b/external/curl/zlib.patch.0 @@ -37,8 +37,8 @@ if test -z "$OPT_ZLIB"; then -@@ -24232,6 +24248,7 @@ - LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE zlib" +@@ -24777,6 +24777,7 @@ + fi curl_zlib_msg="enabled" fi + fi @@ -79,8 +79,8 @@ if test -z "$OPT_ZLIB"; then CURL_CHECK_PKGCONFIG(zlib) -@@ -1395,6 +1395,7 @@ - LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE zlib" +@@ -1571,6 +1571,7 @@ + fi curl_zlib_msg="enabled" fi + fi diff --git a/external/expat/ExternalProject_expat.mk b/external/expat/ExternalProject_expat.mk index 1e9609a4aff8..5a6f8ebee84d 100644 --- a/external/expat/ExternalProject_expat.mk +++ b/external/expat/ExternalProject_expat.mk @@ -17,6 +17,11 @@ $(call gb_ExternalProject_get_state_target,expat,configure) : $(call gb_Trace_StartRange,expat,EXTERNAL) $(call gb_ExternalProject_run,configure,\ $(gb_RUN_CONFIGURE) ./configure --without-docbook \ + --without-arc4random --without-arc4random-buf \ + --without-dev-urandom --without-getentropy \ + --without-sys-getrandom --without-getrandom\ + $(if $(filter LINUX ANDROID,$(OS)),--with-sys-getrandom) \ + $(if $(filter EMSCRIPTEN MACOSX,$(OS)),--with-getentropy) \ $(gb_CONFIGURE_PLATFORMS) \ $(if $(CROSS_COMPILING),$(if $(filter INTEL ARM,$(CPUNAME)),ac_cv_c_bigendian=no)) \ ,,expat_configure.log) diff --git a/external/expat/StaticLibrary_expat.mk b/external/expat/StaticLibrary_expat.mk index f088b4b5d49e..6ca4fc84bf7f 100644 --- a/external/expat/StaticLibrary_expat.mk +++ b/external/expat/StaticLibrary_expat.mk @@ -42,6 +42,20 @@ $(eval $(call gb_StaticLibrary_add_defs,expat,\ )) endif +ifeq ($(OS),WNT) +$(eval $(call gb_StaticLibrary_add_generated_cobjects,expat,\ + UnpackedTarball/expat/lib/random_rand_s \ +)) +else ifneq ($(filter EMSCRIPTEN MACOSX,$(OS)),) +$(eval $(call gb_StaticLibrary_add_generated_cobjects,expat,\ + UnpackedTarball/expat/lib/random_getentropy \ +)) +else +$(eval $(call gb_StaticLibrary_add_generated_cobjects,expat,\ + UnpackedTarball/expat/lib/random_getrandom \ +)) +endif + $(eval $(call gb_StaticLibrary_add_generated_cobjects,expat,\ UnpackedTarball/expat/lib/xmlparse \ UnpackedTarball/expat/lib/xmlrole \ diff --git a/external/expat/expat-winapi.patch b/external/expat/expat-winapi.patch index 8abe65ae7cf1..ea664c3db76c 100644 --- a/external/expat/expat-winapi.patch +++ b/external/expat/expat-winapi.patch @@ -13,13 +13,15 @@ --- misc/expat-2.5.0/lib/xmlparse.c 2022-10-26 00:09:08.000000000 +0900 +++ misc/build/expat-2.5.0/lib/xmlparse.c 2022-10-30 23:09:01.843006341 +0900 -@@ -67,6 +67,9 @@ - #endif +@@ -98,6 +98,10 @@ + #include #ifdef _WIN32 ++# undef HAVE_ARC4RANDOM +# undef HAVE_ARC4RANDOM_BUF +# undef HAVE_GETRANDOM +# undef HAVE_SYSCALL_GETRANDOM - /* force stdlib to define rand_s() */ - # if ! defined(_CRT_RAND_S) - # define _CRT_RAND_S + # define getpid GetCurrentProcessId + #else + # include /* gettimeofday() */ + diff --git a/external/firebird/UnpackedTarball_firebird.mk b/external/firebird/UnpackedTarball_firebird.mk index 060da2e08aea..42bec1e356c1 100644 --- a/external/firebird/UnpackedTarball_firebird.mk +++ b/external/firebird/UnpackedTarball_firebird.mk @@ -31,6 +31,7 @@ $(eval $(call gb_UnpackedTarball_update_autoconf_configs,firebird,\ # of # "Fix for most cases of #7522 (#7828)": $(eval $(call gb_UnpackedTarball_add_patches,firebird,\ + external/firebird/firebird-nbak-difference-file-access.patch.1 \ external/firebird/firebird.disable-ib-util-not-found.patch.1 \ external/firebird/firebird-Engine12.patch \ external/firebird/firebird-rpath.patch.0 \ diff --git a/external/firebird/firebird-nbak-difference-file-access.patch.1 b/external/firebird/firebird-nbak-difference-file-access.patch.1 new file mode 100644 index 000000000000..256d805e8f1d --- /dev/null +++ b/external/firebird/firebird-nbak-difference-file-access.patch.1 @@ -0,0 +1,47 @@ +Verify difference file path against DatabaseAccess + +The difference file opened in openDelta and beginBackup was not verified +against DatabaseAccess like the other database file paths. + +Submitted upstream as https://github.com/FirebirdSQL/firebird/pull/9089 + +--- firebird/src/jrd/nbak.cpp ++++ firebird/src/jrd/nbak.cpp +@@ -35,6 +35,7 @@ + #include "lck.h" + #include "cch.h" + #include "lck_proto.h" ++#include "jrd_proto.h" + #include "pag_proto.h" + #include "err_proto.h" + #include "cch_proto.h" +@@ -224,6 +225,14 @@ + void BackupManager::openDelta(thread_db* tdbb) + { + fb_assert(!diff_file); ++ ++ // Verify difference file path against DatabaseAccess entry of firebird.conf ++ if (!JRD_verify_database_access(diff_name)) ++ { ++ ERR_post(Arg::Gds(isc_conf_access_denied) << Arg::Str("difference file") << ++ Arg::Str(diff_name)); ++ } ++ + diff_file = PIO_open(tdbb, diff_name, diff_name); + + if (database->dbb_flags & (DBB_force_write | DBB_no_fs_cache)) +@@ -283,6 +292,14 @@ + { + // Create file + NBAK_TRACE(("Creating difference file %s", diff_name.c_str())); ++ ++ // Verify difference file path against DatabaseAccess entry of firebird.conf ++ if (!JRD_verify_database_access(diff_name)) ++ { ++ ERR_post(Arg::Gds(isc_conf_access_denied) << Arg::Str("difference file") << ++ Arg::Str(diff_name)); ++ } ++ + diff_file = PIO_create(tdbb, diff_name, true, false); + } + catch (const Firebird::Exception&) diff --git a/external/fontconfig/ExternalProject_fontconfig.mk b/external/fontconfig/ExternalProject_fontconfig.mk index 547f69881e6b..6ac0b46913d2 100644 --- a/external/fontconfig/ExternalProject_fontconfig.mk +++ b/external/fontconfig/ExternalProject_fontconfig.mk @@ -32,8 +32,8 @@ $(call gb_ExternalProject_get_state_target,fontconfig,build) : $(if $(filter ANDROID,$(OS)),LIBS="-lm") \ $(if $(filter EMSCRIPTEN,$(OS)),LIBXML2_CFLAGS="$(LIBXML_CFLAGS)" LIBXML2_LIBS="$(LIBXML_LIBS)") \ $(gb_RUN_CONFIGURE) ./configure \ - --includedir=${WORKDIR}/UnpackedTarball/fontconfig \ - --libdir=${WORKDIR}/UnpackedTarball/fontconfig/src/.libs \ + --includedir=$(gb_UnpackedTarball_workdir)/fontconfig \ + --libdir=$(gb_UnpackedTarball_workdir)/fontconfig/src/.libs \ --disable-silent-rules \ --with-pic \ $(if $(filter ANDROID,$(OS)),--with-arch=arm) \ @@ -42,6 +42,7 @@ $(call gb_ExternalProject_get_state_target,fontconfig,build) : $(gb_CONFIGURE_PLATFORMS) \ $(if $(filter ANDROID,$(OS)), \ --disable-shared \ + ac_cv_va_copy=no \ ) \ $(if $(filter EMSCRIPTEN,$(OS)), \ --disable-shared \ @@ -49,7 +50,7 @@ $(call gb_ExternalProject_get_state_target,fontconfig,build) : --with-cache-dir=/instdir/share/fontconfig/cache \ --with-add-fonts=/instdir/share/fonts \ --enable-libxml2 \ - ac_cv_func_fstatfs=no ac_cv_func_fstatvfs=no \ + ac_cv_func_fstatfs=no ac_cv_func_fstatvfs=no ac_cv_va_copy=no \ ) \ $(if $(filter FUZZERS,$(BUILD_TYPE)), \ --disable-shared, \ @@ -60,8 +61,13 @@ $(call gb_ExternalProject_get_state_target,fontconfig,build) : --with-cache-dir=/usr/lib/fontconfig/cache \ ) \ ) \ - $(if $(filter MACOSX,$(OS)),--prefix=/@.__________________________________________________OOO) \ - && $(MAKE) -C src && $(MAKE) fonts.conf \ + && $(MAKE) -C fc-const && $(MAKE) -C fc-genericfamily && $(MAKE) -C src && $(MAKE) fonts.conf \ + $(if $(filter MACOSX,$(OS)), \ + && $(INSTALL_NAME_TOOL) -id @__________________________________________________OOO/libfontconfig.1.dylib \ + $(gb_UnpackedTarball_workdir)/fontconfig/src/.libs/libfontconfig.1.dylib \ + && $(PERL) $(SRCDIR)/solenv/bin/macosx-change-install-names.pl shl OOO \ + $(gb_UnpackedTarball_workdir)/fontconfig/src/.libs/libfontconfig.1.dylib \ + ) \ ) $(call gb_Trace_EndRange,fontconfig,EXTERNAL) diff --git a/external/fontconfig/UnpackedTarball_fontconfig.mk b/external/fontconfig/UnpackedTarball_fontconfig.mk index 86f39ae25abe..a43a3db7f840 100644 --- a/external/fontconfig/UnpackedTarball_fontconfig.mk +++ b/external/fontconfig/UnpackedTarball_fontconfig.mk @@ -24,7 +24,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,fontconfig,\ )) endif -ifeq ($(COM),MSC) +ifeq ($(OS)-$(ENABLE_HEADLESS),WNT-TRUE) $(eval $(call gb_UnpackedTarball_add_patches,fontconfig,\ external/fontconfig/windowsfonts.patch \ diff --git a/external/fontconfig/fontconfig-2.12.1.patch.1 b/external/fontconfig/fontconfig-2.12.1.patch.1 index b2dce3f1526b..1fa35d4d904a 100644 --- a/external/fontconfig/fontconfig-2.12.1.patch.1 +++ b/external/fontconfig/fontconfig-2.12.1.patch.1 @@ -106,9 +106,9 @@ diff -up fontconfig/configure.dt fontconfig/configure # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. -@@ -12386,7 +12386,7 @@ fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 - printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; } +@@ -13035,7 +13035,7 @@ + { printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 + printf '%s\n' "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' diff --git a/external/freetype/UnpackedTarball_freetype.mk b/external/freetype/UnpackedTarball_freetype.mk index f7fb7dabb450..2fe682cbb793 100644 --- a/external/freetype/UnpackedTarball_freetype.mk +++ b/external/freetype/UnpackedTarball_freetype.mk @@ -14,7 +14,6 @@ $(eval $(call gb_UnpackedTarball_set_tarball,freetype,$(FREETYPE_TARBALL),,freet $(eval $(call gb_UnpackedTarball_add_patches,freetype,\ external/freetype/freetype-2.6.5.patch.1 \ external/freetype/ubsan.patch \ - external/freetype/freetype-fd-hack.patch.0 \ external/freetype/windows.patch \ )) diff --git a/external/freetype/freetype-fd-hack.patch.0 b/external/freetype/freetype-fd-hack.patch.0 deleted file mode 100644 index 96f666c15daf..000000000000 --- a/external/freetype/freetype-fd-hack.patch.0 +++ /dev/null @@ -1,60 +0,0 @@ -# -*- Mode: Diff -*- ---- src/base/ftsystem.c -+++ src/base/ftsystem.c -@@ -24,6 +24,7 @@ - * - */ - -+#include - - #include - #include FT_CONFIG_CONFIG_H -@@ -238,6 +239,8 @@ - const char* filepathname ) - { - FT_FILE* file; -+ int nFD; -+ int n; - - - if ( !stream ) -@@ -250,7 +253,13 @@ - stream->read = NULL; - stream->close = NULL; - -- file = ft_fopen( filepathname, "rb" ); -+ if ( sscanf( filepathname, "/:FD:/%d%n", &nFD, &n ) == 1 && filepathname[n] == '\0') -+ { -+ lseek( nFD, 0, SEEK_SET ); -+ file = fdopen( dup( nFD ), "rb" ); -+ } -+ else -+ file = ft_fopen( filepathname, "rb" ); - if ( !file ) - { - FT_ERROR(( "FT_Stream_Open:" ---- builds/unix/ftsystem.c -+++ builds/unix/ftsystem.c -@@ -249,13 +249,21 @@ - { - int file; - struct stat stat_buf; -+ int nFD; -+ int n; - - - if ( !stream ) - return FT_THROW( Invalid_Stream_Handle ); - - /* open the file */ -- file = open( filepathname, O_RDONLY ); -+ if ( sscanf( filepathname, "/:FD:/%d%n", &nFD, &n ) == 1 && filepathname[n] == '\0') -+ { -+ lseek( nFD, 0, SEEK_SET ); -+ file = dup( nFD ); -+ } -+ else -+ file = open( filepathname, O_RDONLY ); - if ( file < 0 ) - { - FT_ERROR(( "FT_Stream_Open:" )); diff --git a/external/freetype/windows.patch b/external/freetype/windows.patch index b1b79232223b..2239db2f5a4c 100644 --- a/external/freetype/windows.patch +++ b/external/freetype/windows.patch @@ -3,7 +3,7 @@ we don't define DLL_EXPORT as there in general is no need to export freetype symbols from the (dynamkic) library that freetype gets linked into, cairo.dll and vcllo.dll (or mergedlo.dll). But there is one exception: FT_Done_MM_Var *must* be exported as the code in -dlFT_Done_MM_Var() in vcl/unx/generic/glyphs/freetype_glyphcache.cxx +dlFT_Done_MM_Var() in vcl/unx/generic/font/freetype_glyphcache.cxx wants to look it up and call it. --- include/freetype/ftmm.h diff --git a/external/graphite/UnpackedTarball_graphite.mk b/external/graphite/UnpackedTarball_graphite.mk index 640368833144..29ce937d6322 100644 --- a/external/graphite/UnpackedTarball_graphite.mk +++ b/external/graphite/UnpackedTarball_graphite.mk @@ -15,12 +15,11 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,graphite,0)) $(eval $(call gb_UnpackedTarball_add_patches,graphite, \ external/graphite/ubsan.patch \ - external/graphite/enumarith.patch \ )) # cannot use post_action since $(file ..) would be run when the recipe is parsed, i.e. would always # happen before the tarball is unpacked $(gb_UnpackedTarball_workdir)/graphite/graphite2-uninstalled.pc: $(call gb_UnpackedTarball_get_target,graphite) - $(file >$@,$(call gb_pkgconfig_file,graphite2,1.3.14,$(GRAPHITE_CFLAGS),$(GRAPHITE_LIBS))) + $(file >$@,$(call gb_pkgconfig_file,graphite2,1.3.15,$(GRAPHITE_CFLAGS),$(GRAPHITE_LIBS))) # vim: set noet sw=4 ts=4: diff --git a/external/graphite/enumarith.patch b/external/graphite/enumarith.patch deleted file mode 100644 index f5b83097f2b6..000000000000 --- a/external/graphite/enumarith.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- src/Pass.cpp -+++ src/Pass.cpp -@@ -194,7 +194,7 @@ - m_cPConstraint = vm::Machine::Code(true, pcCode, pcCode + pass_constraint_len, - precontext[0], be::peek(sort_keys), *m_silf, face, PASS_TYPE_UNKNOWN); - if (e.test(!m_cPConstraint, E_OUTOFMEM) -- || e.test(m_cPConstraint.status() != Code::loaded, m_cPConstraint.status() + E_CODEFAILURE)) -+ || e.test(m_cPConstraint.status() != Code::loaded, +m_cPConstraint.status() + E_CODEFAILURE)) - return face.error(e); - face.error_context(face.error_context() - 1); - } -@@ -266,8 +266,8 @@ - r->constraint = new (m_codes+n*2-1) vm::Machine::Code(true, rc_begin, rc_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free); - - if (e.test(!r->action || !r->constraint, E_OUTOFMEM) -- || e.test(r->action->status() != Code::loaded, r->action->status() + E_CODEFAILURE) -- || e.test(r->constraint->status() != Code::loaded, r->constraint->status() + E_CODEFAILURE) -+ || e.test(r->action->status() != Code::loaded, +r->action->status() + E_CODEFAILURE) -+ || e.test(r->constraint->status() != Code::loaded, +r->constraint->status() + E_CODEFAILURE) - || e.test(!r->constraint->immutable(), E_MUTABLECCODE)) - return face.error(e); - } diff --git a/external/harfbuzz/ExternalProject_harfbuzz.mk b/external/harfbuzz/ExternalProject_harfbuzz.mk index 204ff93457a8..85406c75e6f1 100644 --- a/external/harfbuzz/ExternalProject_harfbuzz.mk +++ b/external/harfbuzz/ExternalProject_harfbuzz.mk @@ -19,6 +19,10 @@ $(eval $(call gb_ExternalProject_use_externals,harfbuzz,\ meson \ )) +# Hide HarfBuzz symbols. +harfbuzz_cpp_args = $(CXXFLAGS) $(if $(filter-out MSC,$(COM)),-fvisibility=hidden) \ + $(if $(ENABLE_DBGUTIL)$(ENABLE_DEBUG),,$(if $(call gb_Module__symbols_enabled,harfbuzz),$(gb_DEBUGINFO_FLAGS))) + # We cannot use environment vars inside the meson cross-build file, # so we're going to have to generate one on-the-fly. # mungle variables into python list format @@ -45,6 +49,8 @@ endef # cannot use CROSS_COMPILING as condition since we have cross-compilation "light" for cases where # the builder can run the host binaries, like for example when compiling for win 32bit on win 64bit +# +#TODO: Drop filtering out of -std=c++29 and -std=c++2d once Meson supports C++29: $(call gb_ExternalProject_get_state_target,harfbuzz,build) : | $(call gb_ExternalExecutable_get_dependencies,python) $(call gb_Trace_StartRange,harfbuzz,EXTERNAL) $(file >$(gb_UnpackedTarball_workdir)/harfbuzz/cross-file.txt,$(gb_harfbuzz_cross_compile)) @@ -52,10 +58,10 @@ $(call gb_ExternalProject_get_state_target,harfbuzz,build) : | $(call gb_Externa PKG_CONFIG_PATH="${PKG_CONFIG_PATH}$(LIBO_PATH_SEPARATOR)$(gb_UnpackedTarball_workdir)/graphite$(if $(SYSTEM_ICU),,$(LIBO_PATH_SEPARATOR)$(gb_UnpackedTarball_workdir)/icu)" \ PYTHONWARNINGS= \ $(MESON) setup --wrap-mode nofallback builddir \ - -Ddefault_library=static -Dbuildtype=$(if $(ENABLE_DBGUTIL),debug,$(if $(ENABLE_DEBUG),debugoptimized,release \ - $(if $(call gb_Module__symbols_enabled,harfbuzz),$(addsuffix "$(strip $(gb_DEBUGINFO_FLAGS))",-Dc_args= -Dcpp_args=)))) \ + -Ddefault_library=static -Dbuildtype=$(if $(ENABLE_DBGUTIL),debug,$(if $(ENABLE_DEBUG),debugoptimized,release)) \ + $(addsuffix "$(strip $(harfbuzz_cpp_args))",-Dc_args= -Dcpp_args=) \ -Dauto_features=disabled \ - -Dcpp_std=$(subst -std:,,$(subst -std=,,$(filter -std%,$(CXXFLAGS_CXX11)))) \ + -Dcpp_std=$(subst c++29,c++26,$(subst c++2d,c++26,$(subst -std:,,$(subst -std=,,$(filter -std%,$(CXXFLAGS_CXX11)))))) \ -Dtests=disabled \ -Dutilities=disabled \ -Dsubset=enabled \ diff --git a/external/harfbuzz/UnpackedTarball_harfbuzz.mk b/external/harfbuzz/UnpackedTarball_harfbuzz.mk index b3b63944d0dc..a732153dba74 100644 --- a/external/harfbuzz/UnpackedTarball_harfbuzz.mk +++ b/external/harfbuzz/UnpackedTarball_harfbuzz.mk @@ -16,7 +16,6 @@ $(eval $(call gb_UnpackedTarball_update_autoconf_configs,harfbuzz)) $(eval $(call gb_UnpackedTarball_set_patchlevel,harfbuzz,0)) $(eval $(call gb_UnpackedTarball_add_patches,harfbuzz, \ - external/harfbuzz/harfbuzz_visibility.patch.1 \ )) # meson will replace python3 from shebang in build commands with the diff --git a/external/harfbuzz/harfbuzz_visibility.patch.1 b/external/harfbuzz/harfbuzz_visibility.patch.1 deleted file mode 100644 index 2b72a35da460..000000000000 --- a/external/harfbuzz/harfbuzz_visibility.patch.1 +++ /dev/null @@ -1,11 +0,0 @@ -diff -ur harfbuzz.org/src/meson.build harfbuzz/src/meson.build ---- harfbuzz.org/src/meson.build 2025-04-30 11:53:08 -+++ harfbuzz/src/meson.build 2025-04-30 12:02:08 -@@ -624,6 +624,7 @@ - include_directories: incconfig, - dependencies: harfbuzz_deps, - cpp_args: cpp_args + extra_hb_cpp_args, -+ gnu_symbol_visibility: 'hidden', - soversion: hb_so_version, - version: version, - install: true, diff --git a/sccomp/Makefile b/external/highway/Makefile similarity index 71% rename from sccomp/Makefile rename to external/highway/Makefile index ccb1c85a04da..e4968cf85fb6 100644 --- a/sccomp/Makefile +++ b/external/highway/Makefile @@ -2,6 +2,6 @@ module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) -include $(module_directory)/../solenv/gbuild/partial_build.mk +include $(module_directory)/../../solenv/gbuild/partial_build.mk # vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/UnpackedTarball_belanosima.mk b/external/highway/Module_highway.mk similarity index 69% rename from external/more_fonts/UnpackedTarball_belanosima.mk rename to external/highway/Module_highway.mk index e752c46f31c0..3ba9f73be9c9 100644 --- a/external/more_fonts/UnpackedTarball_belanosima.mk +++ b/external/highway/Module_highway.mk @@ -7,8 +7,11 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # -$(eval $(call gb_UnpackedTarball_UnpackedTarball,font_belanosima)) +$(eval $(call gb_Module_Module,highway)) -$(eval $(call gb_UnpackedTarball_set_tarball,font_belanosima,$(FONT_BELANOSIMA_TARBALL),0)) +$(eval $(call gb_Module_add_targets,highway,\ + StaticLibrary_highway \ + UnpackedTarball_highway \ +)) # vim: set noet sw=4 ts=4: diff --git a/external/highway/README b/external/highway/README new file mode 100644 index 000000000000..ab1fe14dfd20 --- /dev/null +++ b/external/highway/README @@ -0,0 +1,4 @@ +According to the library's own README: "Highway is a C++ library that provides +portable SIMD/vector intrinsics." + +From [https://github.com/google/highway]. diff --git a/external/highway/StaticLibrary_highway.mk b/external/highway/StaticLibrary_highway.mk new file mode 100644 index 000000000000..5adbde67684d --- /dev/null +++ b/external/highway/StaticLibrary_highway.mk @@ -0,0 +1,29 @@ +# -*- 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_StaticLibrary_StaticLibrary,highway)) + +$(eval $(call gb_StaticLibrary_use_unpacked,highway,highway)) + +$(eval $(call gb_StaticLibrary_set_warnings_disabled,highway)) + +$(eval $(call gb_StaticLibrary_set_include,highway,\ + -I$(WORKDIR)/UnpackedTarball/highway \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_StaticLibrary_set_generated_cxx_suffix,highway,cc)) + +$(eval $(call gb_StaticLibrary_add_generated_exception_objects,highway,\ + UnpackedTarball/highway/hwy/timer \ + UnpackedTarball/highway/hwy/targets \ + UnpackedTarball/highway/hwy/abort \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/UnpackedTarball_lugrasimo.mk b/external/highway/UnpackedTarball_highway.mk similarity index 69% rename from external/more_fonts/UnpackedTarball_lugrasimo.mk rename to external/highway/UnpackedTarball_highway.mk index f3632a0f6ec7..99e4cd88030e 100644 --- a/external/more_fonts/UnpackedTarball_lugrasimo.mk +++ b/external/highway/UnpackedTarball_highway.mk @@ -7,8 +7,8 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # -$(eval $(call gb_UnpackedTarball_UnpackedTarball,font_lugrasimo)) +$(eval $(call gb_UnpackedTarball_UnpackedTarball,highway)) -$(eval $(call gb_UnpackedTarball_set_tarball,font_lugrasimo,$(FONT_LUGRASIMO_TARBALL),0)) +$(eval $(call gb_UnpackedTarball_set_tarball,highway,$(HIGHWAY_TARBALL))) # vim: set noet sw=4 ts=4: diff --git a/external/hsqldb/ExternalProject_hsqldb.mk b/external/hsqldb/ExternalProject_hsqldb.mk index fb6dc4d49d71..ac24850e84b4 100644 --- a/external/hsqldb/ExternalProject_hsqldb.mk +++ b/external/hsqldb/ExternalProject_hsqldb.mk @@ -18,15 +18,20 @@ $(eval $(call gb_ExternalProject_register_targets,hsqldb,\ # org.apache.tools.ant.types.Permissions.setSecurityManager) would otherwise throw an # UnsupportedOperationException (see "Deprecate the Security # Manager for Removal"): +# older versions of ant expect SOURCE_DATE_EPOCH to be in milliseconds, so if set in environment +# that also would take precedence over the -Dant.tstam.now property and fail. That can be a problem +# if the variable is overridden/provided by exporting it in the env instead of passing it to make +# as a parameter. To counteract that problem, explicitly unset it here. $(call gb_ExternalProject_get_state_target,hsqldb,build) : $(call gb_Trace_StartRange,hsqldb,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(if $(JDK_SECURITYMANAGER_DISALLOWED_FOR_BUILD), \ ANT_OPTS="$$ANT_OPTS -Djava.security.manager=allow") \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build/build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/hsqldb/UnpackedTarball_hsqldb.mk b/external/hsqldb/UnpackedTarball_hsqldb.mk index 29bd33cb7860..c532b9cc2266 100644 --- a/external/hsqldb/UnpackedTarball_hsqldb.mk +++ b/external/hsqldb/UnpackedTarball_hsqldb.mk @@ -32,6 +32,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,hsqldb,\ external/hsqldb/patches/disable-dump-script.patch \ external/hsqldb/patches/abstract.patch \ external/hsqldb/patches/applet.patch.0 \ + external/hsqldb/patches/hsqldb-jar-timestamps.patch.1 \ )) # vim: set noet sw=4 ts=4: diff --git a/external/hsqldb/patches/hsqldb-jar-timestamps.patch.1 b/external/hsqldb/patches/hsqldb-jar-timestamps.patch.1 new file mode 100644 index 000000000000..209897c46599 --- /dev/null +++ b/external/hsqldb/patches/hsqldb-jar-timestamps.patch.1 @@ -0,0 +1,19 @@ +diff -ur hsqldb.org/build/build.xml hsqldb/build/build.xml +--- hsqldb.org/build/build.xml 2026-06-24 11:33:53.281747718 +0000 ++++ hsqldb/build/build.xml 2026-06-24 14:14:08.447370174 +0000 +@@ -19,6 +19,7 @@ + + ++ + + + +@@ -626,6 +627,7 @@ + + + diff --git a/external/hunspell/0001-Keep-only-REP-ph-or-2-word-dictionary-phrase-suggest.patch b/external/hunspell/0001-Keep-only-REP-ph-or-2-word-dictionary-phrase-suggest.patch deleted file mode 100644 index 2e903a34e42a..000000000000 --- a/external/hunspell/0001-Keep-only-REP-ph-or-2-word-dictionary-phrase-suggest.patch +++ /dev/null @@ -1,149 +0,0 @@ -From b88f9ea57bdb9b219f3c1d2c67f4f882f1f23194 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?L=C3=A1szl=C3=B3=20N=C3=A9meth?= -Date: Sun, 14 May 2023 22:15:15 +0200 -Subject: [PATCH] Keep only REP, ph: or 2-word dictionary phrase suggestions - -These are the best suggestions, no need to search other -ones to avoid annoying redundant and long list. - -For example to suggest only "a lot" to the bad form "alot", -add the 2-word phrase "a lot" to the dic file. - -Or for a very typical spelling mistake, enough to specify the -bad form with a ph: in the dictionary file to remove the other -suggestions. - -Note: partial revert of commit de9fe28008eb0761c33bd83847f282602c599fda -"fix up some warnings seen with -Wall -Wextra". ---- - src/hunspell/atypes.hxx | 1 + - src/hunspell/suggestmgr.cxx | 31 ++++++++++++++++++++++++++----- - src/hunspell/suggestmgr.hxx | 2 +- - tests/ph.sug | 4 ++-- - tests/rep.sug | 2 +- - 5 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/src/hunspell/atypes.hxx b/src/hunspell/atypes.hxx -index 7e5a5c0..6e3ed1b 100644 ---- a/src/hunspell/atypes.hxx -+++ b/src/hunspell/atypes.hxx -@@ -82,6 +82,7 @@ static inline void HUNSPELL_WARNING(FILE*, const char*, ...) {} - #define SPELL_ORIGCAP (1 << 5) - #define SPELL_WARN (1 << 6) - #define SPELL_COMPOUND_2 (1 << 7) // permit only 2 dictionary words in the compound -+#define SPELL_BEST_SUG (1 << 8) // limit suggestions for the best ones, i.e. ph: - - #define MINCPDLEN 3 - #define MAXCOMPOUND 10 -diff --git a/src/hunspell/suggestmgr.cxx b/src/hunspell/suggestmgr.cxx -index 19a24f8..ba688aa 100644 ---- a/src/hunspell/suggestmgr.cxx -+++ b/src/hunspell/suggestmgr.cxx -@@ -242,8 +242,11 @@ bool SuggestMgr::suggest(std::vector& slst, - if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) { - size_t i = slst.size(); - replchars(slst, word, cpdsuggest, info); -- if (slst.size() > i) -+ if (slst.size() > i) { - good_suggestion = true; -+ if (info & SPELL_BEST_SUG) -+ return true; -+ } - } - if (clock() > timelimit + TIMELIMIT_SUGGESTION) - return good_suggestion; -@@ -365,7 +368,10 @@ bool SuggestMgr::suggest(std::vector& slst, - // we always suggest them, in despite of nosplitsugs, and - // drop compound word and other suggestions) - if (!cpdsuggest || (!nosplitsugs && slst.size() < oldSug + maxcpdsugs)) { -- good_suggestion = twowords(slst, word, cpdsuggest, good_suggestion, info); -+ good_suggestion = twowords(slst, word, cpdsuggest, good_suggestion, info); -+ -+ if (info & SPELL_BEST_SUG) -+ return true; - } - if (clock() > timelimit + TIMELIMIT_SUGGESTION) - return good_suggestion; -@@ -506,15 +512,23 @@ int SuggestMgr::replchars(std::vector& wlst, - candidate.assign(word, 0, r); - candidate.append(entry.outstrings[type]); - candidate.append(word, r + entry.pattern.size(), std::string::npos); -+ size_t sp = candidate.find(' '); -+ size_t oldns = wlst.size(); - testsug(wlst, candidate, cpdsuggest, NULL, NULL, info); -+ if (oldns < wlst.size()) { -+ int patlen = entry.pattern.size(); -+ int replen = entry.outstrings[type].size(); -+ // REP suggestions are the best, don't search other type of suggestions -+ info |= SPELL_BEST_SUG; -+ } -+ - // check REP suggestions with space -- size_t sp = candidate.find(' '); - if (sp != std::string::npos) { - size_t prev = 0; - while (sp != std::string::npos) { - std::string prev_chunk = candidate.substr(prev, sp - prev); - if (checkword(prev_chunk, 0, NULL, NULL)) { -- size_t oldns = wlst.size(); -+ oldns = wlst.size(); - std::string post_chunk = candidate.substr(sp + 1); - testsug(wlst, post_chunk, cpdsuggest, NULL, NULL, info); - if (oldns < wlst.size()) { -@@ -854,11 +868,15 @@ bool SuggestMgr::twowords(std::vector& wlst, - // alot -> a lot, alto, slot... - *p = ' '; - if (!cpdsuggest && checkword(candidate, cpdsuggest, NULL, NULL)) { -+ // best solution -+ info |= SPELL_BEST_SUG; -+ - // remove not word pair suggestions - if (!good) { - good = true; - wlst.clear(); - } -+ - wlst.insert(wlst.begin(), candidate); - } - -@@ -867,6 +885,9 @@ bool SuggestMgr::twowords(std::vector& wlst, - *p = '-'; - - if (!cpdsuggest && checkword(candidate, cpdsuggest, NULL, NULL)) { -+ // best solution -+ info |= SPELL_BEST_SUG; -+ - // remove not word pair suggestions - if (!good) { - good = true; -diff --git a/tests/ph.sug b/tests/ph.sug -index 8daee56..ccd936e 100644 ---- a/tests/ph.sug -+++ b/tests/ph.sug -@@ -1,11 +1,11 @@ - a lot --in spite, inspire -+in spite - what - what - Wednesday - Wednesday - Wednesday - Wednesday --which, witch, winch, wish -+which, witch - Oh, my gosh! - OH, MY GOSH! -diff --git a/tests/rep.sug b/tests/rep.sug -index b48a5b8..424731c 100644 ---- a/tests/rep.sug -+++ b/tests/rep.sug -@@ -5,4 +5,4 @@ a lot, lot - un alunno - bar - vinte e un --auto's, auto -+auto's --- -2.25.1 - diff --git a/external/hunspell/0001-Resolves-rhbz-2158548-allow-longer-words-for-hunspel.patch b/external/hunspell/0001-Resolves-rhbz-2158548-allow-longer-words-for-hunspel.patch deleted file mode 100644 index c0225fbd70a4..000000000000 --- a/external/hunspell/0001-Resolves-rhbz-2158548-allow-longer-words-for-hunspel.patch +++ /dev/null @@ -1,77 +0,0 @@ -From e2fe9f86e1769b440972971240e9b8fb1cd53b97 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Fri, 6 Jan 2023 16:20:45 +0000 -Subject: [PATCH] Resolves: rhbz#2158548 allow longer words for hunspell-ko -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://github.com/hunspell/hunspell/issues/903 - -A problem since the sanity check added in: - -commit 05e44e069e4cfaa9ce1264bf13f23fc9abd7ed05 -Author: Caolán McNamara -Date: Thu Sep 1 13:46:40 2022 +0100 - - Check word limit (#813) - - * check against hentry blen max ---- - src/hunspell/hashmgr.cxx | 6 +++--- - src/hunspell/htypes.hxx | 4 ++-- - tests/korean.dic | 3 ++- - 3 files changed, 7 insertions(+), 6 deletions(-) - -diff --git a/src/hunspell/hashmgr.cxx b/src/hunspell/hashmgr.cxx -index 100916d..14201e9 100644 ---- a/src/hunspell/hashmgr.cxx -+++ b/src/hunspell/hashmgr.cxx -@@ -209,7 +209,7 @@ int HashMgr::add_word(const std::string& in_word, - } - - // limit of hp->blen -- if (word->size() > std::numeric_limits::max()) { -+ if (word->size() > std::numeric_limits::max()) { - HUNSPELL_WARNING(stderr, "error: word len %ld is over max limit\n", word->size()); - delete desc_copy; - delete word_copy; -@@ -235,8 +235,8 @@ int HashMgr::add_word(const std::string& in_word, - - int i = hash(hpw, word->size()); - -- hp->blen = (unsigned char)word->size(); -- hp->clen = (unsigned char)wcl; -+ hp->blen = (unsigned short)word->size(); -+ hp->clen = (unsigned short)wcl; - hp->alen = (short)al; - hp->astr = aff; - hp->next = NULL; -diff --git a/src/hunspell/htypes.hxx b/src/hunspell/htypes.hxx -index 44366b1..2b896fb 100644 ---- a/src/hunspell/htypes.hxx -+++ b/src/hunspell/htypes.hxx -@@ -62,8 +62,8 @@ - #endif - - struct hentry { -- unsigned char blen; // word length in bytes -- unsigned char clen; // word length in characters (different for UTF-8 enc.) -+ unsigned short blen; // word length in bytes -+ unsigned short clen; // word length in characters (different for UTF-8 enc.) - short alen; // length of affix flag vector - unsigned short* astr; // affix flag vector - struct hentry* next; // next word with same hash code -diff --git a/tests/korean.dic b/tests/korean.dic -index 95cb450..d76ea05 100644 ---- a/tests/korean.dic -+++ b/tests/korean.dic -@@ -1,3 +1,4 @@ --2 -+3 - 들어오세요 - 안녕하세요 -+김수한무거북이와두루미삼천갑자동방삭치치카포사리사리세ᅡ워리워리세브리캉무드셀ᅡ구름위허ᅵ케ᅵᆫᅦ담벼락서생원에ᄀ양 --- -2.38.1 - diff --git a/external/hunspell/0001-fix-LibreOffice-build-problem-with-basic_string-appe.patch b/external/hunspell/0001-fix-LibreOffice-build-problem-with-basic_string-appe.patch deleted file mode 100644 index 3c6f9831b2b4..000000000000 --- a/external/hunspell/0001-fix-LibreOffice-build-problem-with-basic_string-appe.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 1587ea4ab5e8d94c9c0d552f7ab61c217ebdcbeb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?L=C3=A1szl=C3=B3=20N=C3=A9meth?= -Date: Fri, 30 Dec 2022 12:20:02 +0100 -Subject: [PATCH] fix LibreOffice build problem with basic_string::append() - ---- - src/hunspell/affentry.cxx | 6 +++--- - src/hunspell/affixmgr.cxx | 8 ++++---- - 2 files changed, 7 insertions(+), 7 deletions(-) - -diff --git a/src/hunspell/affentry.cxx b/src/hunspell/affentry.cxx -index 46e8b58..6ee23be 100644 ---- a/src/hunspell/affentry.cxx -+++ b/src/hunspell/affentry.cxx -@@ -290,7 +290,7 @@ struct hentry* PfxEntry::check_twosfx(const std::string& word, - // back any characters that would have been stripped - - std::string tmpword(strip); -- tmpword.append(word, start + appnd.size()); -+ tmpword.append(word, start + appnd.size(), tmpl); - - // now make sure all of the conditions on characters - // are met. Please see the appendix at the end of -@@ -338,7 +338,7 @@ std::string PfxEntry::check_twosfx_morph(const std::string& word, - // back any characters that would have been stripped - - std::string tmpword(strip); -- tmpword.append(word, start + appnd.size()); -+ tmpword.append(word, start + appnd.size(), tmpl); - - // now make sure all of the conditions on characters - // are met. Please see the appendix at the end of -@@ -386,7 +386,7 @@ std::string PfxEntry::check_morph(const std::string& word, - // back any characters that would have been stripped - - std::string tmpword(strip); -- tmpword.append(word, start + appnd.size()); -+ tmpword.append(word, start + appnd.size(), tmpl); - - // now make sure all of the conditions on characters - // are met. Please see the appendix at the end of -diff --git a/src/hunspell/affixmgr.cxx b/src/hunspell/affixmgr.cxx -index 4d1ad2f..a8931c1 100644 ---- a/src/hunspell/affixmgr.cxx -+++ b/src/hunspell/affixmgr.cxx -@@ -2465,7 +2465,7 @@ int AffixMgr::compound_check_morph(const std::string& word, - result.append(presult); - result.push_back(MSEP_FLD); - result.append(MORPH_PART); -- result.append(word, i); -+ result.append(word, i, word.size()); - if (complexprefixes && HENTRY_DATA(rv)) - result.append(HENTRY_DATA2(rv)); - if (!HENTRY_FIND(rv, MORPH_STEM)) { -@@ -2522,7 +2522,7 @@ int AffixMgr::compound_check_morph(const std::string& word, - result.append(presult); - result.push_back(MSEP_FLD); - result.append(MORPH_PART); -- result.append(word, i); -+ result.append(word, i, word.size()); - - if (HENTRY_DATA(rv)) { - if (complexprefixes) -@@ -2573,7 +2573,7 @@ int AffixMgr::compound_check_morph(const std::string& word, - if (!m.empty()) { - result.push_back(MSEP_FLD); - result.append(MORPH_PART); -- result.append(word, i); -+ result.append(word, i, word.size()); - line_uniq_app(m, MSEP_REC); - result.append(m); - } -@@ -2665,7 +2665,7 @@ int AffixMgr::compound_check_morph(const std::string& word, - if (!m.empty()) { - result.push_back(MSEP_FLD); - result.append(MORPH_PART); -- result.append(word, i); -+ result.append(word, i, word.size()); - line_uniq_app(m, MSEP_REC); - result.push_back(MSEP_FLD); - result.append(m); --- -2.17.1 - diff --git a/external/hunspell/0001-move-iscii_devanagari_tbl-etc-out-of-.data-section.patch b/external/hunspell/0001-move-iscii_devanagari_tbl-etc-out-of-.data-section.patch deleted file mode 100644 index 412eb4d51ff3..000000000000 --- a/external/hunspell/0001-move-iscii_devanagari_tbl-etc-out-of-.data-section.patch +++ /dev/null @@ -1,375 +0,0 @@ -From f9b326c5fd84ad976eaaa88582bb57d47d22ffb8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Sun, 13 Jul 2025 19:17:55 +0100 -Subject: [PATCH] move iscii_devanagari_tbl, etc out of .data section - ---- - src/hunspell/affixmgr.hxx | 2 +- - src/hunspell/csutil.cxx | 52 ++++++++++++++++++------------------- - src/hunspell/csutil.hxx | 4 +-- - src/hunspell/hashmgr.hxx | 2 +- - src/hunspell/hunspell.cxx | 8 +++--- - src/hunspell/hunspell.hxx | 2 +- - src/hunspell/suggestmgr.cxx | 8 +++--- - src/hunspell/suggestmgr.hxx | 2 +- - 8 files changed, 40 insertions(+), 40 deletions(-) - -diff --git a/src/hunspell/affixmgr.hxx b/src/hunspell/affixmgr.hxx -index 0fc22a3..84caed1 100644 ---- a/src/hunspell/affixmgr.hxx -+++ b/src/hunspell/affixmgr.hxx -@@ -99,7 +99,7 @@ class AffixMgr { - std::string keystring; - std::string trystring; - std::string encoding; -- struct cs_info* csconv; -+ const struct cs_info* csconv; - int utf8; - int complexprefixes; - FLAG compoundflag; -diff --git a/src/hunspell/csutil.cxx b/src/hunspell/csutil.cxx -index 4589e77..92eb014 100644 ---- a/src/hunspell/csutil.cxx -+++ b/src/hunspell/csutil.cxx -@@ -685,7 +685,7 @@ char* get_stored_pointer(const char* s) { - // encodings supported - // supplying isupper, tolower, and toupper - --static struct cs_info iso1_tbl[] = { -+const struct cs_info iso1_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -773,7 +773,7 @@ static struct cs_info iso1_tbl[] = { - {0x00, 0xfc, 0xdc}, {0x00, 0xfd, 0xdd}, {0x00, 0xfe, 0xde}, - {0x00, 0xff, 0xff}}; - --static struct cs_info iso2_tbl[] = { -+const struct cs_info iso2_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -861,7 +861,7 @@ static struct cs_info iso2_tbl[] = { - {0x00, 0xfc, 0xdc}, {0x00, 0xfd, 0xdd}, {0x00, 0xfe, 0xde}, - {0x00, 0xff, 0xff}}; - --static struct cs_info iso3_tbl[] = { -+const struct cs_info iso3_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -949,7 +949,7 @@ static struct cs_info iso3_tbl[] = { - {0x00, 0xfc, 0xdc}, {0x00, 0xfd, 0xdd}, {0x00, 0xfe, 0xde}, - {0x00, 0xff, 0xff}}; - --static struct cs_info iso4_tbl[] = { -+const struct cs_info iso4_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1037,7 +1037,7 @@ static struct cs_info iso4_tbl[] = { - {0x00, 0xfc, 0xdc}, {0x00, 0xfd, 0xdd}, {0x00, 0xfe, 0xde}, - {0x00, 0xff, 0xff}}; - --static struct cs_info iso5_tbl[] = { -+const struct cs_info iso5_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1125,7 +1125,7 @@ static struct cs_info iso5_tbl[] = { - {0x00, 0xfc, 0xac}, {0x00, 0xfd, 0xfd}, {0x00, 0xfe, 0xae}, - {0x00, 0xff, 0xaf}}; - --static struct cs_info iso6_tbl[] = { -+const struct cs_info iso6_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1213,7 +1213,7 @@ static struct cs_info iso6_tbl[] = { - {0x00, 0xfc, 0xfc}, {0x00, 0xfd, 0xfd}, {0x00, 0xfe, 0xfe}, - {0x00, 0xff, 0xff}}; - --static struct cs_info iso7_tbl[] = { -+const struct cs_info iso7_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1301,7 +1301,7 @@ static struct cs_info iso7_tbl[] = { - {0x00, 0xfc, 0xbc}, {0x00, 0xfd, 0xbe}, {0x00, 0xfe, 0xbf}, - {0x00, 0xff, 0xff}}; - --static struct cs_info iso8_tbl[] = { -+const struct cs_info iso8_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1389,7 +1389,7 @@ static struct cs_info iso8_tbl[] = { - {0x00, 0xfc, 0xfc}, {0x00, 0xfd, 0xfd}, {0x00, 0xfe, 0xfe}, - {0x00, 0xff, 0xff}}; - --static struct cs_info iso9_tbl[] = { -+const struct cs_info iso9_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1477,7 +1477,7 @@ static struct cs_info iso9_tbl[] = { - {0x00, 0xfc, 0xdc}, {0x00, 0xfd, 0x49}, {0x00, 0xfe, 0xde}, - {0x00, 0xff, 0xff}}; - --static struct cs_info iso10_tbl[] = { -+const struct cs_info iso10_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1565,7 +1565,7 @@ static struct cs_info iso10_tbl[] = { - {0x00, 0xfc, 0xfc}, {0x00, 0xfd, 0xfd}, {0x00, 0xfe, 0xfe}, - {0x00, 0xff, 0xff}}; - --static struct cs_info koi8r_tbl[] = { -+const struct cs_info koi8r_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1653,7 +1653,7 @@ static struct cs_info koi8r_tbl[] = { - {0x01, 0xdc, 0xfc}, {0x01, 0xdd, 0xfd}, {0x01, 0xde, 0xfe}, - {0x01, 0xdf, 0xff}}; - --static struct cs_info koi8u_tbl[] = { -+const struct cs_info koi8u_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1743,7 +1743,7 @@ static struct cs_info koi8u_tbl[] = { - {0x01, 0xda, 0xfa}, {0x01, 0xdb, 0xfb}, {0x01, 0xdc, 0xfc}, - {0x01, 0xdd, 0xfd}, {0x01, 0xde, 0xfe}, {0x01, 0xdf, 0xff}}; - --static struct cs_info cp1251_tbl[] = { -+const struct cs_info cp1251_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1831,7 +1831,7 @@ static struct cs_info cp1251_tbl[] = { - {0x00, 0xfc, 0xdc}, {0x00, 0xfd, 0xdd}, {0x00, 0xfe, 0xde}, - {0x00, 0xff, 0xdf}}; - --static struct cs_info iso13_tbl[] = { -+const struct cs_info iso13_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -1919,7 +1919,7 @@ static struct cs_info iso13_tbl[] = { - {0x00, 0xFC, 0xDC}, {0x00, 0xFD, 0xDD}, {0x00, 0xFE, 0xDE}, - {0x00, 0xFF, 0xFF}}; - --static struct cs_info iso14_tbl[] = { -+const struct cs_info iso14_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -2007,7 +2007,7 @@ static struct cs_info iso14_tbl[] = { - {0x00, 0xfc, 0xdc}, {0x00, 0xfd, 0xdd}, {0x00, 0xfe, 0xde}, - {0x00, 0xff, 0xff}}; - --static struct cs_info iso15_tbl[] = { -+const struct cs_info iso15_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -2095,7 +2095,7 @@ static struct cs_info iso15_tbl[] = { - {0x00, 0xfc, 0xdc}, {0x00, 0xfd, 0xdd}, {0x00, 0xfe, 0xde}, - {0x00, 0xff, 0xbe}}; - --static struct cs_info iscii_devanagari_tbl[] = { -+const struct cs_info iscii_devanagari_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -2183,7 +2183,7 @@ static struct cs_info iscii_devanagari_tbl[] = { - {0x00, 0xfc, 0xfc}, {0x00, 0xfd, 0xfd}, {0x00, 0xfe, 0xfe}, - {0x00, 0xff, 0xff}}; - --static struct cs_info tis620_tbl[] = { -+const struct cs_info tis620_tbl[] = { - {0x00, 0x00, 0x00}, {0x00, 0x01, 0x01}, {0x00, 0x02, 0x02}, - {0x00, 0x03, 0x03}, {0x00, 0x04, 0x04}, {0x00, 0x05, 0x05}, - {0x00, 0x06, 0x06}, {0x00, 0x07, 0x07}, {0x00, 0x08, 0x08}, -@@ -2273,10 +2273,10 @@ static struct cs_info tis620_tbl[] = { - - struct enc_entry { - const char* enc_name; -- struct cs_info* cs_table; -+ const struct cs_info* cs_table; - }; - --static struct enc_entry encds[] = { -+const struct enc_entry encds[] = { - {"iso88591", iso1_tbl}, // ISO-8859-1 - {"iso88592", iso2_tbl}, // ISO-8859-2 - {"iso88593", iso3_tbl}, // ISO-8859-3 -@@ -2323,11 +2323,11 @@ static void toAsciiLowerAndRemoveNonAlphanumeric(const char* pName, - *pBuf = '\0'; - } - --struct cs_info* get_current_cs(const std::string& es) { -+const struct cs_info* get_current_cs(const std::string& es) { - char* normalized_encoding = new char[es.size() + 1]; - toAsciiLowerAndRemoveNonAlphanumeric(es.c_str(), normalized_encoding); - -- struct cs_info* ccs = NULL; -+ const struct cs_info* ccs = NULL; - for (const auto& encd : encds) { - if (strcmp(normalized_encoding, encd.enc_name) == 0) { - ccs = encd.cs_table; -@@ -2350,7 +2350,7 @@ struct cs_info* get_current_cs(const std::string& es) { - // XXX This function was rewritten for mozilla. Instead of storing the - // conversion tables static in this file, create them when needed - // with help the mozilla backend. --struct cs_info* get_current_cs(const std::string& es) { -+const struct cs_info* get_current_cs(const std::string& es) { - struct cs_info* ccs = new cs_info[256]; - // Initialze the array with dummy data so that we wouldn't need - // to return null in case of failures. -@@ -2437,7 +2437,7 @@ struct cs_info* get_current_cs(const std::string& es) { - - // primitive isalpha() replacement for tokenization - std::string get_casechars(const char* enc) { -- struct cs_info* csconv = get_current_cs(enc); -+ const struct cs_info* csconv = get_current_cs(enc); - std::string expw; - for (int i = 0; i <= 255; ++i) { - if (cupper(csconv, i) != clower(csconv, i)) { -@@ -2457,7 +2457,7 @@ struct lang_map { - int num; - }; - --static struct lang_map lang2enc[] = -+const struct lang_map lang2enc[] = - {{"ar", LANG_ar}, {"az", LANG_az}, - {"az_AZ", LANG_az}, // for back-compatibility - {"bg", LANG_bg}, {"ca", LANG_ca}, -@@ -2527,7 +2527,7 @@ int unicodeisalpha(unsigned short c) { - } - - /* get type of capitalization */ --int get_captype(const std::string& word, cs_info* csconv) { -+int get_captype(const std::string& word, const cs_info* csconv) { - // now determine the capitalization type of the first nl letters - size_t ncap = 0; - size_t nneutral = 0; -diff --git a/src/hunspell/csutil.hxx b/src/hunspell/csutil.hxx -index 808087d..fd11266 100644 ---- a/src/hunspell/csutil.hxx -+++ b/src/hunspell/csutil.hxx -@@ -189,7 +189,7 @@ LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetolower(unsigned short c, - int langnum); - LIBHUNSPELL_DLL_EXPORTED int unicodeisalpha(unsigned short c); - --LIBHUNSPELL_DLL_EXPORTED struct cs_info* get_current_cs(const std::string& es); -+LIBHUNSPELL_DLL_EXPORTED const struct cs_info* get_current_cs(const std::string& es); - - // get language identifiers of language codes - LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const std::string& lang); -@@ -230,7 +230,7 @@ LIBHUNSPELL_DLL_EXPORTED std::vector& - mkallcap_utf(std::vector& u, int langnum); - - // get type of capitalization --LIBHUNSPELL_DLL_EXPORTED int get_captype(const std::string& q, cs_info*); -+LIBHUNSPELL_DLL_EXPORTED int get_captype(const std::string& q, const cs_info*); - - // get type of capitalization (UTF-8) - LIBHUNSPELL_DLL_EXPORTED int get_captype_utf8(const std::vector& q, int langnum); -diff --git a/src/hunspell/hashmgr.hxx b/src/hunspell/hashmgr.hxx -index 792b2f1..9e0975a 100644 ---- a/src/hunspell/hashmgr.hxx -+++ b/src/hunspell/hashmgr.hxx -@@ -96,7 +96,7 @@ class HashMgr { - int langnum; - std::string enc; - std::string lang; -- struct cs_info* csconv; -+ const struct cs_info* csconv; - std::string ignorechars; - std::vector ignorechars_utf16; - std::vector aliasf; // flag vector `compression' with aliases -diff --git a/src/hunspell/hunspell.cxx b/src/hunspell/hunspell.cxx -index 51e0937..2bb1b94 100644 ---- a/src/hunspell/hunspell.cxx -+++ b/src/hunspell/hunspell.cxx -@@ -112,7 +112,7 @@ public: - int add_with_affix(const std::string& word, const std::string& example); - int remove(const std::string& word); - const std::string& get_version_cpp() const; -- struct cs_info* get_csconv(); -+ const struct cs_info* get_csconv() const; - - int spell(const char* word, int* info = NULL, char** root = NULL); - int suggest(char*** slst, const char* word); -@@ -134,7 +134,7 @@ private: - SuggestMgr* pSMgr; - std::string affixpath; - std::string encoding; -- struct cs_info* csconv; -+ const struct cs_info* csconv; - int langnum; - int utf8; - int complexprefixes; -@@ -1505,7 +1505,7 @@ const std::string& HunspellImpl::get_version_cpp() const { - return pAMgr->get_version(); - } - --struct cs_info* HunspellImpl::get_csconv() { -+const struct cs_info* HunspellImpl::get_csconv() const { - return csconv; - } - -@@ -2186,7 +2186,7 @@ const std::string& Hunspell::get_version_cpp() const { - return m_Impl->get_version_cpp(); - } - --struct cs_info* Hunspell::get_csconv() { -+const struct cs_info* Hunspell::get_csconv() const { - return m_Impl->get_csconv(); - } - -diff --git a/src/hunspell/hunspell.hxx b/src/hunspell/hunspell.hxx -index 142017f..267a745 100644 ---- a/src/hunspell/hunspell.hxx -+++ b/src/hunspell/hunspell.hxx -@@ -217,7 +217,7 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell { - const std::string& get_wordchars_cpp() const; - const std::vector& get_wordchars_utf16() const; - -- struct cs_info* get_csconv(); -+ const struct cs_info* get_csconv() const; - - const char* get_version() const; - const std::string& get_version_cpp() const; -diff --git a/src/hunspell/suggestmgr.cxx b/src/hunspell/suggestmgr.cxx -index 5f480f9..82b53d2 100644 ---- a/src/hunspell/suggestmgr.cxx -+++ b/src/hunspell/suggestmgr.cxx -@@ -1207,7 +1207,7 @@ void SuggestMgr::ngsuggest(std::vector& wlst, - - // set character based ngram suggestion for words with non-BMP Unicode - // characters -- struct cs_info* origconv = csconv; -+ const struct cs_info* origconv = csconv; - if (n == -1) { - utf8 = 0; // XXX not state-free - if (!csconv) -diff --git a/src/hunspell/suggestmgr.hxx b/src/hunspell/suggestmgr.hxx -index 7fa1a6b..0f8bcc5 100644 ---- a/src/hunspell/suggestmgr.hxx -+++ b/src/hunspell/suggestmgr.hxx -@@ -103,7 +103,7 @@ class SuggestMgr { - - AffixMgr* pAMgr; - unsigned int maxSug; -- struct cs_info* csconv; -+ const struct cs_info* csconv; - int utf8; - int langnum; - int nosplitsugs; --- -2.49.0 - diff --git a/external/hunspell/UnpackedTarball_hunspell.mk b/external/hunspell/UnpackedTarball_hunspell.mk index ce4da507e295..6c664f830d25 100644 --- a/external/hunspell/UnpackedTarball_hunspell.mk +++ b/external/hunspell/UnpackedTarball_hunspell.mk @@ -19,14 +19,4 @@ $(eval $(call gb_UnpackedTarball_set_post_action,hunspell,\ )) endif -$(eval $(call gb_UnpackedTarball_add_patches,hunspell, \ - external/hunspell/0001-fix-LibreOffice-build-problem-with-basic_string-appe.patch \ - external/hunspell/0001-Resolves-rhbz-2158548-allow-longer-words-for-hunspel.patch \ - external/hunspell/0001-Keep-only-REP-ph-or-2-word-dictionary-phrase-suggest.patch \ - external/hunspell/0001-move-iscii_devanagari_tbl-etc-out-of-.data-section.patch \ - external/hunspell/bit_cast.patch.0 \ - external/hunspell/clock-monotonic.patch.1 \ - external/hunspell/dont-suggest-matching-capitalized-replacement.patch \ -)) - # vim: set noet sw=4 ts=4: diff --git a/external/hunspell/bit_cast.patch.0 b/external/hunspell/bit_cast.patch.0 deleted file mode 100644 index 777b9bbfdd8e..000000000000 --- a/external/hunspell/bit_cast.patch.0 +++ /dev/null @@ -1,22 +0,0 @@ ---- src/hunspell/w_char.hxx -+++ src/hunspell/w_char.hxx -@@ -42,9 +42,8 @@ - - #if __cplusplus >= 202002L - #include --#else -+#endif - #include --#endif - - #ifndef GCC - struct w_char { -@@ -58,7 +57,7 @@ - { - #if defined(__i386__) || defined(_M_IX86) || defined(_M_X64) - //use little-endian optimized version --#if __cplusplus >= 202002L -+#if __cplusplus >= 202002L && defined __cpp_lib_bit_cast && __cpp_lib_bit_cast >= 201806L - return std::bit_cast(*this); - #else - unsigned short u; diff --git a/external/hunspell/clock-monotonic.patch.1 b/external/hunspell/clock-monotonic.patch.1 deleted file mode 100644 index dd873f6c3908..000000000000 --- a/external/hunspell/clock-monotonic.patch.1 +++ /dev/null @@ -1,105 +0,0 @@ -From 5737bdb3d7e5819528e33c360a73372e0e93a6be Mon Sep 17 00:00:00 2001 -From: Noel Grandin -Date: Fri, 3 Nov 2023 12:04:30 +0000 -Subject: [PATCH] speed up hunspell inner loop - -which calls into the kernel to get elapsed time, instead of using the -VDSO-based CLOCK_MONOTONIC (or at least, the C++ equivalent of that), -which is much faster - -https://gerrit.libreoffice.org/c/core/+/158809 ---- - src/hunspell/affixmgr.cxx | 43 +++++++++++++++++++++++---------------- - 1 file changed, 25 insertions(+), 18 deletions(-) - -diff --git a/src/hunspell/affixmgr.cxx b/src/hunspell/affixmgr.cxx -index 2cad09f..a3c93cd 100644 ---- a/src/hunspell/affixmgr.cxx -+++ b/src/hunspell/affixmgr.cxx -@@ -75,6 +75,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -1590,17 +1591,20 @@ struct hentry* AffixMgr::compound_check(const std::string& word, - // add a time limit to handle possible - // combinatorical explosion of the overlapping words - -- HUNSPELL_THREAD_LOCAL clock_t timelimit; -+ HUNSPELL_THREAD_LOCAL std::chrono::steady_clock::time_point clock_time_start; -+ HUNSPELL_THREAD_LOCAL bool timelimit_exceeded; -+ -+ // get the current time -+ std::chrono::steady_clock::time_point clock_now = std::chrono::steady_clock::now(); - - if (wordnum == 0) { -- // get the start time, seeing as we're reusing this set to 0 -- // to flag timeout, use clock() + 1 to avoid start clock() -- // of 0 as being a timeout -- timelimit = clock() + 1; -- } -- else if (timelimit != 0 && (clock() > timelimit + TIMELIMIT)) { -- timelimit = 0; -+ // set the start time -+ clock_time_start = clock_now; -+ timelimit_exceeded = false; - } -+ else if (std::chrono::duration_cast(clock_now - clock_time_start).count() -+ > TIMELIMIT * CLOCKS_PER_SEC * 1000) -+ timelimit_exceeded = true; - - setcminmax(&cmin, &cmax, word.c_str(), len); - -@@ -1626,7 +1630,7 @@ struct hentry* AffixMgr::compound_check(const std::string& word, - - do { // simplified checkcompoundpattern loop - -- if (timelimit == 0) -+ if (timelimit_exceeded) - return 0; - - if (scpd > 0) { -@@ -2216,17 +2220,20 @@ int AffixMgr::compound_check_morph(const std::string& word, - // add a time limit to handle possible - // combinatorical explosion of the overlapping words - -- HUNSPELL_THREAD_LOCAL clock_t timelimit; -+ HUNSPELL_THREAD_LOCAL std::chrono::steady_clock::time_point clock_time_start; -+ HUNSPELL_THREAD_LOCAL bool timelimit_exceeded; -+ -+ // get the current time -+ std::chrono::steady_clock::time_point clock_now = std::chrono::steady_clock::now(); - - if (wordnum == 0) { -- // get the start time, seeing as we're reusing this set to 0 -- // to flag timeout, use clock() + 1 to avoid start clock() -- // of 0 as being a timeout -- timelimit = clock() + 1; -- } -- else if (timelimit != 0 && (clock() > timelimit + TIMELIMIT)) { -- timelimit = 0; -+ // set the start time -+ clock_time_start = clock_now; -+ timelimit_exceeded = false; - } -+ else if (std::chrono::duration_cast(clock_now - clock_time_start).count() -+ > TIMELIMIT * CLOCKS_PER_SEC * 1000) -+ timelimit_exceeded = true; - - setcminmax(&cmin, &cmax, word.c_str(), len); - -@@ -2246,7 +2253,7 @@ int AffixMgr::compound_check_morph(const std::string& word, - - do { // onlycpdrule loop - -- if (timelimit == 0) -+ if (timelimit_exceeded) - return 0; - - oldnumsyllable = numsyllable; --- -2.41.0 - diff --git a/external/hunspell/dont-suggest-matching-capitalized-replacement.patch b/external/hunspell/dont-suggest-matching-capitalized-replacement.patch deleted file mode 100644 index 8e295b7572e4..000000000000 --- a/external/hunspell/dont-suggest-matching-capitalized-replacement.patch +++ /dev/null @@ -1,61 +0,0 @@ -*** a/src/hunspell/hunspell.cxx 2025-10-01 17:20:17.599434991 -0400 ---- b/src/hunspell/hunspell.cxx 2025-10-01 17:21:01.839629317 -0400 -*************** -*** 155,160 **** ---- 155,161 ---- - size_t* pabbrev); - void clean_ignore(std::string& dest, const std::string& src); - void mkinitcap(std::string& u8); -+ void mkinitsmall(std::string& u8); - int mkinitcap2(std::string& u8, std::vector& u16); - int mkinitsmall2(std::string& u8, std::vector& u16); - void mkallcap(std::string& u8); -*************** -*** 964,973 **** - } - - // capitalize -! if (capwords) - for (auto& j : slst) { - mkinitcap(j); - } - - // expand suggestions with dot(s) - if (abbv && pAMgr && pAMgr->get_sugswithdots() && word.size() >= abbv) { ---- 965,980 ---- - } - - // capitalize -! if (capwords) { -! std::string initsmallword(word); -! mkinitsmall(initsmallword); -! - for (auto& j : slst) { -+ if (initsmallword == j) -+ continue; // if capitalized, it would match misspelled word! - mkinitcap(j); - } -+ } - - // expand suggestions with dot(s) - if (abbv && pAMgr && pAMgr->get_sugswithdots() && word.size() >= abbv) { -*************** -*** 1442,1447 **** ---- 1449,1465 ---- - u16_u8(u8, u16); - } else { - ::mkinitcap(u8, csconv); -+ } -+ } -+ -+ void HunspellImpl::mkinitsmall(std::string& u8) { -+ if (utf8) { -+ std::vector u16; -+ u8_u16(u16, u8); -+ ::mkinitsmall_utf(u16, langnum); -+ u16_u8(u8, u16); -+ } else { -+ ::mkinitcap(u8, csconv); - } - } - diff --git a/external/hyphen/UnpackedTarball_hyphen.mk b/external/hyphen/UnpackedTarball_hyphen.mk index 21b1f8f7629c..924e07343e3e 100644 --- a/external/hyphen/UnpackedTarball_hyphen.mk +++ b/external/hyphen/UnpackedTarball_hyphen.mk @@ -17,7 +17,6 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,hyphen,2)) $(eval $(call gb_UnpackedTarball_add_patches,hyphen,\ external/hyphen/hyphen-build.patch \ - external/hyphen/hyphen-fdo48017-wfopen.patch \ )) # vim: set noet sw=4 ts=4: diff --git a/external/hyphen/hyphen-fdo48017-wfopen.patch b/external/hyphen/hyphen-fdo48017-wfopen.patch deleted file mode 100644 index 815eeda79a37..000000000000 --- a/external/hyphen/hyphen-fdo48017-wfopen.patch +++ /dev/null @@ -1,49 +0,0 @@ -diff -u hyphen/hyphen.c build/hyphen/hyphen.c ---- hyphen/hyphen.c 2014-05-22 00:28:13.164587974 +0200 -+++ build/hyphen/hyphen.c 2015-05-22 11:08:55.000000000 +0200 -@@ -44,6 +44,11 @@ - #include /* for exit */ - #endif - -+#ifdef _WIN32 -+#include -+#include -+#endif -+ - #define noVERBOSE - - /* calculate hyphenmin values with long ligature length (2 or 3 characters -@@ -371,12 +376,32 @@ - } - } - -+FILE * hnj_fopen(const char * path, const char * mode) { -+#ifdef _WIN32 -+#define WIN32_LONG_PATH_PREFIX "\\\\?\\" -+ if (strncmp(path, WIN32_LONG_PATH_PREFIX, 4) == 0) { -+ int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); -+ wchar_t *buff = (wchar_t *) malloc(len * sizeof(wchar_t)); -+ wchar_t *buff2 = (wchar_t *) malloc(len * sizeof(wchar_t)); -+ FILE * f = NULL; -+ MultiByteToWideChar(CP_UTF8, 0, path, -1, buff, len); -+ if (_wfullpath( buff2, buff, len ) != NULL) { -+ f = _wfopen(buff2, (strcmp(mode, "r") == 0) ? L"r" : L"rb"); -+ } -+ free(buff); -+ free(buff2); -+ return f; -+ } -+#endif -+ return fopen(path, mode); -+} -+ - HyphenDict * - hnj_hyphen_load (const char *fn) - { - HyphenDict *result; - FILE *f; -- f = fopen (fn, "r"); -+ f = hnj_fopen (fn, "r"); - if (f == NULL) - return NULL; - diff --git a/external/java_websocket/ExternalProject_java_websocket.mk b/external/java_websocket/ExternalProject_java_websocket.mk index 9d4a62d81183..513840683d00 100644 --- a/external/java_websocket/ExternalProject_java_websocket.mk +++ b/external/java_websocket/ExternalProject_java_websocket.mk @@ -16,10 +16,11 @@ $(eval $(call gb_ExternalProject_register_targets,java_websocket,\ $(call gb_ExternalProject_get_state_target,java_websocket,build) : $(call gb_Trace_StartRange,java_websocket,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/java_websocket/UnpackedTarball_java_websocket.mk b/external/java_websocket/UnpackedTarball_java_websocket.mk index 1d05361a25f9..7f865eec72cf 100644 --- a/external/java_websocket/UnpackedTarball_java_websocket.mk +++ b/external/java_websocket/UnpackedTarball_java_websocket.mk @@ -24,6 +24,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,java_websocket,\ external/java_websocket/patches/0001-cid-1546341-Resource-leak-on-an-exceptional-path.patch \ external/java_websocket/patches/0001-cid-1545249-Bad-bit-shift-operation.patch \ external/java_websocket/patches/0001-cid-1546344-Dm-Dubious-method-used.patch \ + external/java_websocket/patches/java-websocket-jar-timestamps.patch.1 \ )) # vim: set noet sw=4 ts=4: diff --git a/external/java_websocket/patches/java-websocket-jar-timestamps.patch.1 b/external/java_websocket/patches/java-websocket-jar-timestamps.patch.1 new file mode 100644 index 000000000000..3f7d0097c3a2 --- /dev/null +++ b/external/java_websocket/patches/java-websocket-jar-timestamps.patch.1 @@ -0,0 +1,20 @@ +diff -ur java_websocket.org/build.xml java_websocket/build.xml +--- java_websocket.org/build.xml 2026-06-24 15:32:09.431913892 +0000 ++++ java_websocket/build.xml 2026-06-24 15:33:15.528712683 +0000 +@@ -1,4 +1,7 @@ + ++ ++ ++ + + + +@@ -11,7 +14,7 @@ + + + +- ++ + + + diff --git a/external/jfreereport/ExternalProject_jfreereport_flow_engine.mk b/external/jfreereport/ExternalProject_jfreereport_flow_engine.mk index fa90262e0d05..abd33f931f7d 100644 --- a/external/jfreereport/ExternalProject_jfreereport_flow_engine.mk +++ b/external/jfreereport/ExternalProject_jfreereport_flow_engine.mk @@ -20,10 +20,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_flow_engine,\ $(call gb_ExternalProject_get_state_target,jfreereport_flow_engine,build) : $(call gb_Trace_StartRange,jfreereport_flow_engine,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dlibbase.jar=$(gb_UnpackedTarball_workdir)/jfreereport_libbase/dist/libbase-$(LIBBASE_VERSION).jar \ -Dlibformula.jar=$(gb_UnpackedTarball_workdir)/jfreereport_libformula/dist/libformula-$(LIBFORMULA_VERSION).jar \ diff --git a/external/jfreereport/ExternalProject_jfreereport_flute.mk b/external/jfreereport/ExternalProject_jfreereport_flute.mk index 1a57167246c0..f4194345f8cc 100644 --- a/external/jfreereport/ExternalProject_jfreereport_flute.mk +++ b/external/jfreereport/ExternalProject_jfreereport_flute.mk @@ -19,10 +19,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_flute,\ $(call gb_ExternalProject_get_state_target,jfreereport_flute,build) : $(call gb_Trace_StartRange,jfreereport_flute,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/jfreereport/ExternalProject_jfreereport_libbase.mk b/external/jfreereport/ExternalProject_jfreereport_libbase.mk index 864b13ed1519..2ed6c80c2c55 100644 --- a/external/jfreereport/ExternalProject_jfreereport_libbase.mk +++ b/external/jfreereport/ExternalProject_jfreereport_libbase.mk @@ -19,10 +19,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_libbase,\ $(call gb_ExternalProject_get_state_target,jfreereport_libbase,build) : $(call gb_Trace_StartRange,jfreereport_libbase,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/jfreereport/ExternalProject_jfreereport_libfonts.mk b/external/jfreereport/ExternalProject_jfreereport_libfonts.mk index 6b7da7b5c52b..ff3bd2edb72a 100644 --- a/external/jfreereport/ExternalProject_jfreereport_libfonts.mk +++ b/external/jfreereport/ExternalProject_jfreereport_libfonts.mk @@ -19,10 +19,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_libfonts,\ $(call gb_ExternalProject_get_state_target,jfreereport_libfonts,build) : $(call gb_Trace_StartRange,jfreereport_libfonts,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/jfreereport/ExternalProject_jfreereport_libformula.mk b/external/jfreereport/ExternalProject_jfreereport_libformula.mk index 5211d54fbca9..7bf2e930ff3d 100644 --- a/external/jfreereport/ExternalProject_jfreereport_libformula.mk +++ b/external/jfreereport/ExternalProject_jfreereport_libformula.mk @@ -19,10 +19,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_libformula,\ $(call gb_ExternalProject_get_state_target,jfreereport_libformula,build) : $(call gb_Trace_StartRange,jfreereport_libformula,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/jfreereport/ExternalProject_jfreereport_liblayout.mk b/external/jfreereport/ExternalProject_jfreereport_liblayout.mk index 8fc997806c4f..6ddb16b9c2f2 100644 --- a/external/jfreereport/ExternalProject_jfreereport_liblayout.mk +++ b/external/jfreereport/ExternalProject_jfreereport_liblayout.mk @@ -28,10 +28,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_liblayout,\ $(call gb_ExternalProject_get_state_target,jfreereport_liblayout,build) : $(call gb_Trace_StartRange,jfreereport_liblayout,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dflute.jar=$(gb_UnpackedTarball_workdir)/jfreereport_flute/dist/flute-$(FLUTE_VERSION).jar \ -Dlibbase.jar=$(gb_UnpackedTarball_workdir)/jfreereport_libbase/dist/libbase-$(LIBBASE_VERSION).jar \ diff --git a/external/jfreereport/ExternalProject_jfreereport_libloader.mk b/external/jfreereport/ExternalProject_jfreereport_libloader.mk index 5c5964b9e17a..0f9d874cd9e3 100644 --- a/external/jfreereport/ExternalProject_jfreereport_libloader.mk +++ b/external/jfreereport/ExternalProject_jfreereport_libloader.mk @@ -19,10 +19,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_libloader,\ $(call gb_ExternalProject_get_state_target,jfreereport_libloader,build) : $(call gb_Trace_StartRange,jfreereport_libloader,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/jfreereport/ExternalProject_jfreereport_librepository.mk b/external/jfreereport/ExternalProject_jfreereport_librepository.mk index 49d7e9497fb9..e66e548a28a8 100644 --- a/external/jfreereport/ExternalProject_jfreereport_librepository.mk +++ b/external/jfreereport/ExternalProject_jfreereport_librepository.mk @@ -19,10 +19,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_librepository,\ $(call gb_ExternalProject_get_state_target,jfreereport_librepository,build) : $(call gb_Trace_StartRange,jfreereport_librepository,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/jfreereport/ExternalProject_jfreereport_libserializer.mk b/external/jfreereport/ExternalProject_jfreereport_libserializer.mk index d0d37a59bded..e3e79cb2083c 100644 --- a/external/jfreereport/ExternalProject_jfreereport_libserializer.mk +++ b/external/jfreereport/ExternalProject_jfreereport_libserializer.mk @@ -19,10 +19,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_libserializer,\ $(call gb_ExternalProject_get_state_target,jfreereport_libserializer,build) : $(call gb_Trace_StartRange,jfreereport_libserializer,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)." \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/jfreereport/ExternalProject_jfreereport_libxml.mk b/external/jfreereport/ExternalProject_jfreereport_libxml.mk index f79bf3731eac..015dfb684e98 100644 --- a/external/jfreereport/ExternalProject_jfreereport_libxml.mk +++ b/external/jfreereport/ExternalProject_jfreereport_libxml.mk @@ -19,10 +19,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_libxml,\ $(call gb_ExternalProject_get_state_target,jfreereport_libxml,build) : $(call gb_Trace_StartRange,jfreereport_libxml,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/jfreereport/ExternalProject_jfreereport_sac.mk b/external/jfreereport/ExternalProject_jfreereport_sac.mk index 807f30e37ab5..01454bd9a396 100644 --- a/external/jfreereport/ExternalProject_jfreereport_sac.mk +++ b/external/jfreereport/ExternalProject_jfreereport_sac.mk @@ -16,10 +16,11 @@ $(eval $(call gb_ExternalProject_register_targets,jfreereport_sac,\ $(call gb_ExternalProject_get_state_target,jfreereport_sac,build) : $(call gb_Trace_StartRange,jfreereport_sac,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MSYS_NO_PATHCONV && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ + unset MSYS_NO_PATHCONV SOURCE_DATE_EPOCH && JAVA_HOME=$(JAVA_HOME_FOR_BUILD) \ $(ICECREAM_RUN) "$(ANT)" \ $(if $(verbose),-v,-q) \ -f build.xml \ + $(if $(SOURCE_DATE_EPOCH),-Dant.tstamp.now=$(SOURCE_DATE_EPOCH)) \ -Dbuild.label="build-$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)" \ -Dant.build.javac.source=$(JAVA_SOURCE_VER) \ -Dant.build.javac.target=$(JAVA_TARGET_VER) \ diff --git a/external/jfreereport/UnpackedTarball_jfreereport_flow_engine.mk b/external/jfreereport/UnpackedTarball_jfreereport_flow_engine.mk index 92b827255ca0..f15d35db9407 100644 --- a/external/jfreereport/UnpackedTarball_jfreereport_flow_engine.mk +++ b/external/jfreereport/UnpackedTarball_jfreereport_flow_engine.mk @@ -21,6 +21,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,jfreereport_flow_engine,\ external/jfreereport/patches/flow-engine.patch \ external/jfreereport/patches/flow-engine_date_is_datetime.patch.1 \ external/jfreereport/patches/pentaho-reporting-flow-engine-0.9.4-remove-commons-logging.patch.1 \ + external/jfreereport/patches/flow-engine-jar-timestamps.patch.1 \ )) # vim: set noet sw=4 ts=4: diff --git a/external/jfreereport/UnpackedTarball_jfreereport_liblayout.mk b/external/jfreereport/UnpackedTarball_jfreereport_liblayout.mk index 9e01fcd7699b..db40a9f63750 100644 --- a/external/jfreereport/UnpackedTarball_jfreereport_liblayout.mk +++ b/external/jfreereport/UnpackedTarball_jfreereport_liblayout.mk @@ -20,6 +20,7 @@ $(eval $(call gb_UnpackedTarball_fix_end_of_line,jfreereport_liblayout,\ $(eval $(call gb_UnpackedTarball_add_patches,jfreereport_liblayout,\ external/jfreereport/patches/liblayout.patch \ external/jfreereport/patches/liblayout-0.2.10-remove-commons-logging.patch.1 \ + external/jfreereport/patches/liblayout-jar-timestamps.patch.1 \ )) # vim: set noet sw=4 ts=4: diff --git a/external/jfreereport/java/sac/build.xml b/external/jfreereport/java/sac/build.xml index 0e85dff04f3a..7eea51ac9fa1 100644 --- a/external/jfreereport/java/sac/build.xml +++ b/external/jfreereport/java/sac/build.xml @@ -1,5 +1,7 @@ - + + + @@ -42,7 +44,7 @@ - + @@ -61,4 +63,4 @@ - \ No newline at end of file + diff --git a/external/jfreereport/patches/common_build.patch b/external/jfreereport/patches/common_build.patch index b197f494e128..905b1cbda0f7 100644 --- a/external/jfreereport/patches/common_build.patch +++ b/external/jfreereport/patches/common_build.patch @@ -117,3 +117,25 @@ +diff -ur jfreereport_flute.org/common_build.xml jfreereport_flute/common_build.xml +--- a/jfreereport_flute.org/common_build.xml 2026-06-24 14:47:35.842081102 +0000 ++++ b/jfreereport_flute/common_build.xml 2026-06-24 15:07:49.965391582 +0000 +@@ -47,6 +47,9 @@ + + + ++ ++ ++ + + ------------------------------------------------------------------------------- + Common Build file provides tasks needed to perform a project build. +@@ -1160,7 +1163,7 @@ + Creates a jar file from the bin directory + ====================================================================--> + +- ++ + + + diff --git a/external/jfreereport/patches/flow-engine-jar-timestamps.patch.1 b/external/jfreereport/patches/flow-engine-jar-timestamps.patch.1 new file mode 100644 index 000000000000..ccd867a751a6 --- /dev/null +++ b/external/jfreereport/patches/flow-engine-jar-timestamps.patch.1 @@ -0,0 +1,20 @@ +diff -ur jfreereport_flow_engine.org/build.xml jfreereport_flow_engine/build.xml +--- jfreereport_flow_engine.org/build.xml 2026-06-24 14:47:45.196052819 +0000 ++++ jfreereport_flow_engine/build.xml 2026-06-24 14:50:20.231584057 +0000 +@@ -1,4 +1,7 @@ + ++ ++ ++ + + + +@@ -55,7 +58,7 @@ + + + +- ++ + + + diff --git a/external/jfreereport/patches/liblayout-jar-timestamps.patch.1 b/external/jfreereport/patches/liblayout-jar-timestamps.patch.1 new file mode 100644 index 000000000000..161fe531ad56 --- /dev/null +++ b/external/jfreereport/patches/liblayout-jar-timestamps.patch.1 @@ -0,0 +1,20 @@ +diff -ur jfreereport_liblayout.org/build.xml jfreereport_liblayout/build.xml +--- jfreereport_liblayout.org/build.xml 2026-06-24 15:14:55.392091886 +0000 ++++ jfreereport_liblayout/build.xml 2026-06-24 15:23:10.047571909 +0000 +@@ -1,4 +1,7 @@ + ++ ++ ++ + + + +@@ -60,7 +63,7 @@ + + + +- ++ + + + diff --git a/external/lcms2/ExternalPackage_lcms2.mk b/external/lcms2/ExternalPackage_lcms2.mk index 896af12ad31f..2d3ad61a76c8 100644 --- a/external/lcms2/ExternalPackage_lcms2.mk +++ b/external/lcms2/ExternalPackage_lcms2.mk @@ -17,7 +17,7 @@ $(eval $(call gb_ExternalPackage_add_file,lcms2,$(LIBO_LIB_FOLDER)/liblcms2.2.dy else ifeq ($(COM),MSC) $(eval $(call gb_ExternalPackage_add_file,lcms2,$(LIBO_LIB_FOLDER)/lcms2.dll,bin/lcms2.dll)) else -$(eval $(call gb_ExternalPackage_add_file,lcms2,$(LIBO_LIB_FOLDER)/liblcms2.so.2,src/.libs/liblcms2.so.2.0.18)) +$(eval $(call gb_ExternalPackage_add_file,lcms2,$(LIBO_LIB_FOLDER)/liblcms2.so.2,src/.libs/liblcms2.so.2.0.19)) endif endif # $(DISABLE_DYNLOADING) diff --git a/external/libcdr/libcdr-visibility-win.patch b/external/libcdr/libcdr-visibility-win.patch index 5333b5e44b1f..27c2d251c006 100644 --- a/external/libcdr/libcdr-visibility-win.patch +++ b/external/libcdr/libcdr-visibility-win.patch @@ -1,11 +1,12 @@ --- configure.dt 2018-12-29 16:23:02.355271146 +0100 +++ configure 2018-12-29 16:23:21.644060142 +0100 -@@ -23329,6 +23329,8 @@ +@@ -24915,7 +24915,8 @@ if test $platform_win32 = yes then : +- + HAVE_VISIBILITY_TRUE='#' + HAVE_VISIBILITY_FALSE= - - else $as_nop - + else case e in #( + e) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -fvisibility=hidden compiler flag" >&5 diff --git a/external/libcmis/0001-Fix-boost-1.86-breakage.patch b/external/libcmis/0001-Fix-boost-1.86-breakage.patch deleted file mode 100644 index ef398dfcc98b..000000000000 --- a/external/libcmis/0001-Fix-boost-1.86-breakage.patch +++ /dev/null @@ -1,47 +0,0 @@ -From dfcb642a491f7ec2ae52e3e83d31bb6cdf3670c2 Mon Sep 17 00:00:00 2001 -From: David Seifert -Date: Sat, 31 Aug 2024 12:39:39 +0200 -Subject: [PATCH] Fix boost 1.86 breakage - -The fix does not break building against <1.86 since we're now accessing the -object representation of the return value. - -Fixes #67 ---- - src/libcmis/xml-utils.cxx | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/src/libcmis/xml-utils.cxx b/src/libcmis/xml-utils.cxx -index e487d17..cdf088f 100644 ---- a/src/libcmis/xml-utils.cxx -+++ b/src/libcmis/xml-utils.cxx -@@ -531,16 +531,22 @@ namespace libcmis - boost::uuids::detail::sha1 sha1; - sha1.process_bytes( str.c_str(), str.size() ); - -- unsigned int digest[5]; -+ // on boost < 1.86.0, digest_type is typedef'd as unsigned int[5] -+ // on boost >= 1.86.0, digest_type is typedef'd as unsigned char[20] -+ boost::uuids::detail::sha1::digest_type digest; - sha1.get_digest( digest ); - -+ // by using a pointer to unsigned char, we can read the -+ // object representation of either typedef. -+ const unsigned char* ptr = reinterpret_cast( digest ); -+ - stringstream out; -- // Setup writing mode. Every number must produce eight -+ // Setup writing mode. Every number must produce two - // hexadecimal digits, including possible leading 0s, or we get - // less than 40 digits as result. - out << hex << setfill('0') << right; -- for ( int i = 0; i < 5; ++i ) -- out << setw(8) << digest[i]; -+ for ( int i = 0; i < sizeof( digest ); ++ptr, ++i ) -+ out << setw(2) << static_cast( *ptr ); - return out.str(); - } - --- -2.45.1 - diff --git a/external/libcmis/0001-Fix-warning-C4589-when-building-with-MSVC.patch b/external/libcmis/0001-Fix-warning-C4589-when-building-with-MSVC.patch deleted file mode 100644 index 0883d708f3af..000000000000 --- a/external/libcmis/0001-Fix-warning-C4589-when-building-with-MSVC.patch +++ /dev/null @@ -1,222 +0,0 @@ -From c86638560b3cb39b847d4e84ae9b8492f0c5fa22 Mon Sep 17 00:00:00 2001 -From: Mike Kaganski -Date: Thu, 22 Feb 2024 20:47:48 +0600 -Subject: [PATCH] Fix warning C4589 when building with MSVC - -C:\libcmis\inc\libcmis/document.hxx(51): warning C4589: Constructor of abstract class 'libcmis::Document' ignores initializer for virtual base class 'libcmis::Object' -C:\libcmis\inc\libcmis/document.hxx(51): note: virtual base classes are only initialized by the most-derived type -C:\libcmis\inc\libcmis/folder.hxx(58): warning C4589: Constructor of abstract class 'libcmis::Folder' ignores initializer for virtual base class 'libcmis::Object' -C:\libcmis\inc\libcmis/folder.hxx(58): note: virtual base classes are only initialized by the most-derived type ---- - inc/libcmis/document.hxx | 1 - - inc/libcmis/folder.hxx | 1 - - src/libcmis/atom-document.cxx | 2 -- - src/libcmis/atom-folder.cxx | 1 - - src/libcmis/gdrive-document.cxx | 2 -- - src/libcmis/gdrive-folder.cxx | 2 -- - src/libcmis/onedrive-document.cxx | 2 -- - src/libcmis/onedrive-folder.cxx | 2 -- - src/libcmis/sharepoint-document.cxx | 2 -- - src/libcmis/sharepoint-folder.cxx | 2 -- - src/libcmis/ws-document.cxx | 1 - - src/libcmis/ws-folder.cxx | 1 - - 12 files changed, 19 deletions(-) - -diff --git a/inc/libcmis/document.hxx b/inc/libcmis/document.hxx -index 8f44313..ca18a84 100644 ---- a/inc/libcmis/document.hxx -+++ b/inc/libcmis/document.hxx -@@ -48,7 +48,6 @@ namespace libcmis - class LIBCMIS_API Document : public virtual Object - { - public: -- Document( Session* session ) : Object( session ) { } - virtual ~Document( ) { } - - /** Get the folder parents for the document. -diff --git a/inc/libcmis/folder.hxx b/inc/libcmis/folder.hxx -index 0010dbd..24f4ac4 100644 ---- a/inc/libcmis/folder.hxx -+++ b/inc/libcmis/folder.hxx -@@ -55,7 +55,6 @@ namespace libcmis - class LIBCMIS_API Folder : public virtual Object - { - public: -- Folder( Session* session ) : Object( session ) { } - virtual ~Folder() { } - - virtual std::vector< std::string > getPaths( ); -diff --git a/src/libcmis/atom-document.cxx b/src/libcmis/atom-document.cxx -index e0400b1..8871dbc 100644 ---- a/src/libcmis/atom-document.cxx -+++ b/src/libcmis/atom-document.cxx -@@ -43,7 +43,6 @@ using namespace libcmis; - - AtomDocument::AtomDocument( AtomPubSession* session ) : - libcmis::Object( session ), -- libcmis::Document( session ), - AtomObject( session ), - m_contentUrl( ) - { -@@ -52,7 +51,6 @@ AtomDocument::AtomDocument( AtomPubSession* session ) : - - AtomDocument::AtomDocument( AtomPubSession* session, xmlNodePtr entryNd ) : - libcmis::Object( session ), -- libcmis::Document( session ), - AtomObject( session ), - m_contentUrl( ) - { -diff --git a/src/libcmis/atom-folder.cxx b/src/libcmis/atom-folder.cxx -index 5e41194..25276a1 100644 ---- a/src/libcmis/atom-folder.cxx -+++ b/src/libcmis/atom-folder.cxx -@@ -46,7 +46,6 @@ namespace - - AtomFolder::AtomFolder( AtomPubSession* session, xmlNodePtr entryNd ) : - libcmis::Object( session ), -- libcmis::Folder( session ), - AtomObject( session ) - { - xmlDocPtr doc = libcmis::wrapInDoc( entryNd ); -diff --git a/src/libcmis/gdrive-document.cxx b/src/libcmis/gdrive-document.cxx -index ecb13d6..a826cf7 100644 ---- a/src/libcmis/gdrive-document.cxx -+++ b/src/libcmis/gdrive-document.cxx -@@ -40,7 +40,6 @@ using namespace libcmis; - - GDriveDocument::GDriveDocument( GDriveSession* session ) : - libcmis::Object( session), -- libcmis::Document( session ), - GDriveObject( session ), - m_isGoogleDoc( false ) - { -@@ -48,7 +47,6 @@ GDriveDocument::GDriveDocument( GDriveSession* session ) : - - GDriveDocument::GDriveDocument( GDriveSession* session, Json json, string id, string name ) : - libcmis::Object( session), -- libcmis::Document( session ), - GDriveObject( session, json, id, name ), - m_isGoogleDoc( false ) - { -diff --git a/src/libcmis/gdrive-folder.cxx b/src/libcmis/gdrive-folder.cxx -index 26de89b..3aa5faf 100644 ---- a/src/libcmis/gdrive-folder.cxx -+++ b/src/libcmis/gdrive-folder.cxx -@@ -38,14 +38,12 @@ using namespace libcmis; - - GDriveFolder::GDriveFolder( GDriveSession* session ): - libcmis::Object( session ), -- libcmis::Folder( session ), - GDriveObject( session ) - { - } - - GDriveFolder::GDriveFolder( GDriveSession* session, Json json ): - libcmis::Object( session ), -- libcmis::Folder( session ), - GDriveObject( session, json ) - { - } -diff --git a/src/libcmis/onedrive-document.cxx b/src/libcmis/onedrive-document.cxx -index 863a92f..ced64e0 100644 ---- a/src/libcmis/onedrive-document.cxx -+++ b/src/libcmis/onedrive-document.cxx -@@ -40,14 +40,12 @@ using namespace libcmis; - - OneDriveDocument::OneDriveDocument( OneDriveSession* session ) : - libcmis::Object( session), -- libcmis::Document( session ), - OneDriveObject( session ) - { - } - - OneDriveDocument::OneDriveDocument( OneDriveSession* session, Json json, string id, string name ) : - libcmis::Object( session), -- libcmis::Document( session ), - OneDriveObject( session, json, id, name ) - { - } -diff --git a/src/libcmis/onedrive-folder.cxx b/src/libcmis/onedrive-folder.cxx -index c1980c8..3fa455a 100644 ---- a/src/libcmis/onedrive-folder.cxx -+++ b/src/libcmis/onedrive-folder.cxx -@@ -38,14 +38,12 @@ using namespace libcmis; - - OneDriveFolder::OneDriveFolder( OneDriveSession* session ): - libcmis::Object( session ), -- libcmis::Folder( session ), - OneDriveObject( session ) - { - } - - OneDriveFolder::OneDriveFolder( OneDriveSession* session, Json json ): - libcmis::Object( session ), -- libcmis::Folder( session ), - OneDriveObject( session, json ) - { - } -diff --git a/src/libcmis/sharepoint-document.cxx b/src/libcmis/sharepoint-document.cxx -index dec5527..61b4431 100644 ---- a/src/libcmis/sharepoint-document.cxx -+++ b/src/libcmis/sharepoint-document.cxx -@@ -37,14 +37,12 @@ using namespace libcmis; - - SharePointDocument::SharePointDocument( SharePointSession* session ) : - libcmis::Object( session), -- libcmis::Document( session ), - SharePointObject( session ) - { - } - - SharePointDocument::SharePointDocument( SharePointSession* session, Json json, string parentId, string name ) : - libcmis::Object( session), -- libcmis::Document( session ), - SharePointObject( session, json, parentId, name ) - { - } -diff --git a/src/libcmis/sharepoint-folder.cxx b/src/libcmis/sharepoint-folder.cxx -index e4da4a3..8bcb2db 100644 ---- a/src/libcmis/sharepoint-folder.cxx -+++ b/src/libcmis/sharepoint-folder.cxx -@@ -38,14 +38,12 @@ using namespace libcmis; - - SharePointFolder::SharePointFolder( SharePointSession* session ): - libcmis::Object( session ), -- libcmis::Folder( session ), - SharePointObject( session ) - { - } - - SharePointFolder::SharePointFolder( SharePointSession* session, Json json, string parentId ): - libcmis::Object( session ), -- libcmis::Folder( session ), - SharePointObject( session, json, parentId ) - { - } -diff --git a/src/libcmis/ws-document.cxx b/src/libcmis/ws-document.cxx -index ba2f2bc..c085d5b 100644 ---- a/src/libcmis/ws-document.cxx -+++ b/src/libcmis/ws-document.cxx -@@ -33,7 +33,6 @@ using libcmis::PropertyPtrMap; - - WSDocument::WSDocument( const WSObject& object ) : - libcmis::Object( object ), -- libcmis::Document( const_cast< WSObject& >( object ).getSession( ) ), - WSObject( object ) - { - } -diff --git a/src/libcmis/ws-folder.cxx b/src/libcmis/ws-folder.cxx -index 4e82ac2..aca0543 100644 ---- a/src/libcmis/ws-folder.cxx -+++ b/src/libcmis/ws-folder.cxx -@@ -33,7 +33,6 @@ using libcmis::PropertyPtrMap; - - WSFolder::WSFolder( const WSObject& object ) : - libcmis::Object( object ), -- libcmis::Folder( const_cast< WSObject& >( object ).getSession( ) ), - WSObject( object ) - { - } --- -2.43.0.windows.1 - diff --git a/external/libcmis/0001-Take-into-account-m_CurlInitProtocolsFunction-in-cop.patch b/external/libcmis/0001-Take-into-account-m_CurlInitProtocolsFunction-in-cop.patch deleted file mode 100644 index 235adbe38252..000000000000 --- a/external/libcmis/0001-Take-into-account-m_CurlInitProtocolsFunction-in-cop.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 98e7e9f15449e0c8eaa12776c6c126ea0411002e Mon Sep 17 00:00:00 2001 -From: Julien Nabet -Date: Fri, 23 Feb 2024 21:59:12 +0100 -Subject: [PATCH] Take into account m_CurlInitProtocolsFunction in copy - constructor HttpSession - ---- - src/libcmis/http-session.cxx | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/libcmis/http-session.cxx b/src/libcmis/http-session.cxx -index 8d427a4..79bcc08 100644 ---- a/src/libcmis/http-session.cxx -+++ b/src/libcmis/http-session.cxx -@@ -183,6 +183,7 @@ HttpSession::HttpSession( string username, string password, bool noSslCheck, - - HttpSession::HttpSession( const HttpSession& copy ) : - m_curlHandle( NULL ), -+ m_CurlInitProtocolsFunction( copy.m_CurlInitProtocolsFunction ), - m_no100Continue( copy.m_no100Continue ), - m_oauth2Handler( copy.m_oauth2Handler ), - m_username( copy.m_username ), --- -2.45.1 - diff --git a/external/libcmis/0001-cid-1545775-COPY_INSTEAD_OF_MOVE.patch b/external/libcmis/0001-cid-1545775-COPY_INSTEAD_OF_MOVE.patch deleted file mode 100644 index ff022a82867e..000000000000 --- a/external/libcmis/0001-cid-1545775-COPY_INSTEAD_OF_MOVE.patch +++ /dev/null @@ -1,69 +0,0 @@ -From ca078137dfa94664275f021c5fbf08a34f3fbc10 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Sun, 14 Jan 2024 20:41:06 +0000 -Subject: [PATCH] cid#1545775 COPY_INSTEAD_OF_MOVE - -and - -cid#1546321 COPY_INSTEAD_OF_MOVE -cid#1546272 COPY_INSTEAD_OF_MOVE -cid#1546287 COPY_INSTEAD_OF_MOVE -cid#1545443 COPY_INSTEAD_OF_MOVE ---- - inc/libcmis/exception.hxx | 4 ++-- - inc/libcmis/property-type.hxx | 10 +++++----- - inc/libcmis/session-factory.hxx | 2 +- - 3 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/inc/libcmis/exception.hxx b/inc/libcmis/exception.hxx -index aa42ae7..565bff0 100644 ---- a/inc/libcmis/exception.hxx -+++ b/inc/libcmis/exception.hxx -@@ -44,8 +44,8 @@ namespace libcmis - public: - Exception( std::string message, std::string type = "runtime" ) : - exception( ), -- m_message( message ), -- m_type( type ) -+ m_message( std::move(message) ), -+ m_type( std::move(type) ) - { - } - -diff --git a/inc/libcmis/property-type.hxx b/inc/libcmis/property-type.hxx -index 350a7b2..e6b3779 100644 ---- a/inc/libcmis/property-type.hxx -+++ b/inc/libcmis/property-type.hxx -@@ -102,11 +102,11 @@ namespace libcmis - bool isOrderable( ) { return m_orderable; } - bool isOpenChoice( ) { return m_openChoice; } - -- void setId( std::string id ) { m_id = id; } -- void setLocalName( std::string localName ) { m_localName = localName; } -- void setLocalNamespace( std::string localNamespace ) { m_localNamespace = localNamespace; } -- void setDisplayName( std::string displayName ) { m_displayName = displayName; } -- void setQueryName( std::string queryName ) { m_queryName = queryName; } -+ void setId( const std::string& id ) { m_id = id; } -+ void setLocalName( const std::string& localName ) { m_localName = localName; } -+ void setLocalNamespace( const std::string& localNamespace ) { m_localNamespace = localNamespace; } -+ void setDisplayName( const std::string& displayName ) { m_displayName = displayName; } -+ void setQueryName( const std::string& queryName ) { m_queryName = queryName; } - void setType( Type type ) { m_type = type; } - void setMultiValued( bool multivalued ) { m_multiValued = multivalued; } - void setUpdatable( bool updatable ) { m_updatable = updatable; } -diff --git a/inc/libcmis/session-factory.hxx b/inc/libcmis/session-factory.hxx -index 227ac4d..1887254 100644 ---- a/inc/libcmis/session-factory.hxx -+++ b/inc/libcmis/session-factory.hxx -@@ -111,7 +111,7 @@ namespace libcmis - /** Set the handler to ask the user what to do with invalid SSL certificates. If not set, - every invalid certificate will raise an exception. - */ -- static void setCertificateValidationHandler( CertValidationHandlerPtr handler ) { s_certValidationHandler = handler; } -+ static void setCertificateValidationHandler(const CertValidationHandlerPtr& handler ) { s_certValidationHandler = handler; } - static CertValidationHandlerPtr getCertificateValidationHandler( ) { return s_certValidationHandler; } - - static void setCurlInitProtocolsFunction(CurlInitProtocolsFunction); --- -2.43.0 - diff --git a/external/libcmis/0001-cppcheck-operatorEqVarError-in-src-libcmis-http-sess.patch b/external/libcmis/0001-cppcheck-operatorEqVarError-in-src-libcmis-http-sess.patch deleted file mode 100644 index fc1acef60fab..000000000000 --- a/external/libcmis/0001-cppcheck-operatorEqVarError-in-src-libcmis-http-sess.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 308a5352bab44157ba13962b9aa4becefb6e3817 Mon Sep 17 00:00:00 2001 -From: Julien Nabet -Date: Fri, 23 Feb 2024 17:56:17 +0100 -Subject: [PATCH] cppcheck: operatorEqVarError in src/libcmis/http-session.cxx - ---- - src/libcmis/http-session.cxx | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/libcmis/http-session.cxx b/src/libcmis/http-session.cxx -index f690914..8d427a4 100644 ---- a/src/libcmis/http-session.cxx -+++ b/src/libcmis/http-session.cxx -@@ -224,6 +224,7 @@ HttpSession& HttpSession::operator=( const HttpSession& copy ) - { - curl_easy_cleanup( m_curlHandle ); - m_curlHandle = NULL; -+ m_CurlInitProtocolsFunction = copy.m_CurlInitProtocolsFunction; - m_no100Continue = copy.m_no100Continue; - m_oauth2Handler = copy.m_oauth2Handler; - m_username = copy.m_username; --- -2.45.1 - diff --git a/external/libcmis/UnpackedTarball_libcmis.mk b/external/libcmis/UnpackedTarball_libcmis.mk index 33f128a41036..67bd43c0a829 100644 --- a/external/libcmis/UnpackedTarball_libcmis.mk +++ b/external/libcmis/UnpackedTarball_libcmis.mk @@ -11,19 +11,4 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,libcmis)) $(eval $(call gb_UnpackedTarball_set_tarball,libcmis,$(LIBCMIS_TARBALL))) -# 0001-cid-1545775-COPY_INSTEAD_OF_MOVE.patch is upstreamed - -$(eval $(call gb_UnpackedTarball_add_patches,libcmis,\ - external/libcmis/0001-cid-1545775-COPY_INSTEAD_OF_MOVE.patch \ - external/libcmis/0001-Fix-warning-C4589-when-building-with-MSVC.patch \ - external/libcmis/http-session-cleanup.patch.1 \ - external/libcmis/factory-no-retry-ssl.patch.1 \ - external/libcmis/sharepoint-auth.patch.1 \ - external/libcmis/exceptions.patch.1 \ - external/libcmis/0001-cppcheck-operatorEqVarError-in-src-libcmis-http-sess.patch \ - external/libcmis/0001-Take-into-account-m_CurlInitProtocolsFunction-in-cop.patch \ - external/libcmis/initprotocols.patch.1 \ - external/libcmis/0001-Fix-boost-1.86-breakage.patch \ -)) - # vim: set noet sw=4 ts=4: diff --git a/external/libcmis/exceptions.patch.1 b/external/libcmis/exceptions.patch.1 deleted file mode 100644 index 3b4090aa54f7..000000000000 --- a/external/libcmis/exceptions.patch.1 +++ /dev/null @@ -1,172 +0,0 @@ ---- libcmis/src/libcmis/http-session.cxx.orig 2024-06-21 12:22:36.083125022 +0200 -+++ libcmis/src/libcmis/http-session.cxx 2024-06-21 13:08:37.403016695 +0200 -@@ -653,7 +653,7 @@ - m_authProvided = authProvider->authenticationQuery( m_username, m_password ); - if ( !m_authProvided ) - { -- throw CurlException( "User cancelled authentication request" ); -+ throw CurlException("User cancelled authentication request", CURLE_OK); - } - } - } -@@ -762,6 +762,7 @@ - if ( CURLE_SSL_CACERT == errCode ) - { - vector< string > certificates; -+ string err(errBuff); - - // We somehow need to rerun the request to get the certificate - curl_easy_setopt(m_curlHandle, CURLOPT_SSL_VERIFYHOST, 0); -@@ -814,7 +815,7 @@ - } - else - { -- throw CurlException( "Invalid SSL certificate" ); -+ throw CurlException(err, CURLE_SSL_CACERT); - } - } - } -@@ -827,7 +828,6 @@ - - - void HttpSession::checkOAuth2( string url ) --try - { - if ( m_oauth2Handler ) - { -@@ -836,10 +836,6 @@ - oauth2Authenticate( ); - } - } --catch ( const libcmis::Exception& e ) --{ -- throw CurlException( e.what( ) ); --} - - long HttpSession::getHttpStatus( ) - { -@@ -906,15 +902,10 @@ - } - - void HttpSession::oauth2Refresh( ) --try - { - const ScopeGuard inOauth2Guard(m_inOAuth2Authentication, true); - m_oauth2Handler->refresh( ); - } --catch ( const libcmis::Exception& e ) --{ -- throw CurlException( e.what() ); --} - - void HttpSession::initProtocols( ) - { -@@ -981,11 +972,45 @@ - break; - default: - msg = what(); -- if ( !isCancelled( ) ) -- msg += ": " + m_url; -- else -- type = "permissionDenied"; -- break; -+ switch (m_code) -+ { -+ case CURLE_COULDNT_RESOLVE_PROXY: -+ case CURLE_COULDNT_RESOLVE_HOST: -+ type = "dnsFailed"; -+ break; -+ case CURLE_COULDNT_CONNECT: -+ case CURLE_SSL_CONNECT_ERROR: -+ case CURLE_SSL_CERTPROBLEM: -+ case CURLE_SSL_CIPHER: -+ case CURLE_PEER_FAILED_VERIFICATION: -+#if CURL_AT_LEAST_VERSION(7, 19, 0) -+ case CURLE_SSL_ISSUER_ERROR: -+#endif -+ case CURLE_SSL_PINNEDPUBKEYNOTMATCH: -+ case CURLE_SSL_INVALIDCERTSTATUS: -+ case CURLE_FAILED_INIT: -+#if CURL_AT_LEAST_VERSION(7, 69, 0) -+ case CURLE_QUIC_CONNECT_ERROR: -+#endif -+ type = "connectFailed"; -+ break; -+ case CURLE_OPERATION_TIMEDOUT: -+ type = "connectTimeout"; -+ break; -+ case CURLE_WRITE_ERROR: -+ case CURLE_READ_ERROR: // error returned from our callbacks -+ case CURLE_ABORTED_BY_CALLBACK: -+ case CURLE_SEND_ERROR: -+ case CURLE_RECV_ERROR: -+ type = "transferFailed"; -+ break; -+ default: -+ if ( !isCancelled( ) ) -+ msg += ": " + m_url; -+ else if (msg == "User cancelled authentication request") -+ type = "permissionDenied"; -+ break; -+ } - } - - return libcmis::Exception( msg, type ); ---- libcmis/src/libcmis/http-session.hxx.orig 2024-06-21 12:36:22.785868998 +0200 -+++ libcmis/src/libcmis/http-session.hxx 2024-06-21 12:36:44.272966309 +0200 -@@ -71,10 +71,10 @@ - { - } - -- CurlException( std::string message ) : -+ CurlException(std::string message, CURLcode const code) : - exception( ), - m_message( message ), -- m_code( CURLE_OK ), -+ m_code(code), - m_url( ), - m_httpStatus( 0 ), - m_cancelled( true ), ---- libcmis/src/libcmis/sharepoint-session.cxx.orig 2024-06-21 12:23:07.164265783 +0200 -+++ libcmis/src/libcmis/sharepoint-session.cxx 2024-06-21 12:37:45.528243723 +0200 -@@ -289,6 +291,7 @@ - if ( CURLE_SSL_CACERT == errCode ) - { - vector< string > certificates; -+ string err(errBuff); - - // We somehow need to rerun the request to get the certificate - curl_easy_setopt(m_curlHandle, CURLOPT_SSL_VERIFYHOST, 0); -@@ -344,7 +344,7 @@ - } - else - { -- throw CurlException( "Invalid SSL certificate" ); -+ throw CurlException(err, CURLE_SSL_CACERT); - } - } - } ---- libcmis/src/libcmis/session-factory.cxx.orig 2024-06-21 15:37:55.132824666 +0200 -+++ libcmis/src/libcmis/session-factory.cxx 2024-06-21 15:36:17.558408868 +0200 -@@ -96,7 +96,7 @@ - } - catch (const CurlException& e) - { -- if (strcmp(e.what(), "Invalid SSL certificate") == 0) -+ if (e.getErrorCode() == CURLE_SSL_CACERT) - { - // no point in trying other protocols - throw e.getCmisException(); ---- libcmis/qa/libcmis/test-atom.cxx.orig 2024-06-21 15:39:49.130310447 +0200 -+++ libcmis/qa/libcmis/test-atom.cxx 2024-06-21 15:39:51.541320721 +0200 -@@ -323,8 +323,8 @@ - } - catch ( const libcmis::Exception& e ) - { -- CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong exception message", -- string( "Invalid SSL certificate" ), string( e.what() ) ); -+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong exception type", -+ string("connectFailed"), string(e.getType()) ); - } - } - } diff --git a/external/libcmis/factory-no-retry-ssl.patch.1 b/external/libcmis/factory-no-retry-ssl.patch.1 deleted file mode 100644 index e549ca5e08c8..000000000000 --- a/external/libcmis/factory-no-retry-ssl.patch.1 +++ /dev/null @@ -1,17 +0,0 @@ ---- libcmis/src/libcmis/session-factory.cxx.orig 2024-06-19 18:43:56.244832053 +0200 -+++ libcmis/src/libcmis/session-factory.cxx 2024-06-20 11:46:26.518263605 +0200 -@@ -94,8 +94,13 @@ - { - response = httpSession->httpGetRequest( bindingUrl ); - } -- catch ( const CurlException& ) -+ catch (const CurlException& e) - { -+ if (strcmp(e.what(), "Invalid SSL certificate") == 0) -+ { -+ // no point in trying other protocols -+ throw e.getCmisException(); -+ } - // Could be SharePoint - needs NTLM authentication - session = new SharePointSession( bindingUrl, username, - password, verbose ); diff --git a/external/libcmis/http-session-cleanup.patch.1 b/external/libcmis/http-session-cleanup.patch.1 deleted file mode 100644 index 0c7b352d4407..000000000000 --- a/external/libcmis/http-session-cleanup.patch.1 +++ /dev/null @@ -1,82 +0,0 @@ ---- libcmis/src/libcmis/http-session.cxx.orig 2024-06-19 18:04:14.198691623 +0200 -+++ libcmis/src/libcmis/http-session.cxx 2024-06-19 18:09:08.853234764 +0200 -@@ -670,16 +670,17 @@ - curl_easy_setopt( m_curlHandle, CURLOPT_URL, url.c_str() ); - - // Set the headers -- struct curl_slist *headers_slist = NULL; -+ struct deleter { void operator()(curl_slist* p) const { curl_slist_free_all(p); } }; -+ unique_ptr headers_slist; - for ( vector< string >::iterator it = headers.begin( ); it != headers.end( ); ++it ) -- headers_slist = curl_slist_append( headers_slist, it->c_str( ) ); -+ headers_slist.reset(curl_slist_append(headers_slist.release(), it->c_str())); - - // If we are using OAuth2, then add the proper header with token to authenticate - // Otherwise, just set the credentials normally using in libcurl options - if ( m_oauth2Handler != NULL && !m_oauth2Handler->getHttpHeader( ).empty() ) - { -- headers_slist = curl_slist_append( headers_slist, -- m_oauth2Handler->getHttpHeader( ).c_str( ) ); -+ headers_slist.reset(curl_slist_append(headers_slist.release(), -+ m_oauth2Handler->getHttpHeader().c_str())); - } - else if ( !getUsername().empty() ) - { -@@ -693,7 +693,7 @@ - #endif - } - -- curl_easy_setopt( m_curlHandle, CURLOPT_HTTPHEADER, headers_slist ); -+ curl_easy_setopt(m_curlHandle, CURLOPT_HTTPHEADER, headers_slist.get()); - - // Set the proxy configuration if any - if ( !libcmis::SessionFactory::getProxy( ).empty() ) -@@ -747,9 +747,6 @@ - // Perform the query - CURLcode errCode = curl_easy_perform( m_curlHandle ); - -- // Free the headers list -- curl_slist_free_all( headers_slist ); -- - // Process the response - bool isHttpError = errCode == CURLE_HTTP_RETURNED_ERROR; - if ( CURLE_OK != errCode && !( m_noHttpErrors && isHttpError ) ) ---- libcmis/src/libcmis/sharepoint-session.cxx.orig 2024-06-19 18:04:35.761804551 +0200 -+++ libcmis/src/libcmis/sharepoint-session.cxx 2024-06-19 18:08:44.563107553 +0200 -@@ -200,12 +200,13 @@ - curl_easy_setopt( m_curlHandle, CURLOPT_URL, url.c_str() ); - - // Set the headers -- struct curl_slist *headers_slist = NULL; -+ struct deleter { void operator()(curl_slist* p) const { curl_slist_free_all(p); } }; -+ unique_ptr headers_slist; - for ( vector< string >::iterator it = headers.begin( ); it != headers.end( ); ++it ) -- headers_slist = curl_slist_append( headers_slist, it->c_str( ) ); -+ headers_slist.reset(curl_slist_append(headers_slist.release(), it->c_str())); - -- headers_slist = curl_slist_append( headers_slist, "accept:application/json; odata=verbose" ); -- headers_slist = curl_slist_append( headers_slist, ( "x-requestdigest:" + m_digestCode ).c_str( ) ); -+ headers_slist.reset(curl_slist_append(headers_slist.release(), "accept:application/json; odata=verbose")); -+ headers_slist.reset(curl_slist_append(headers_slist.release(), ("x-requestdigest:" + m_digestCode).c_str())); - - if ( !getUsername().empty() && !getPassword().empty() ) - { -@@ -220,7 +219,7 @@ - #endif - } - -- curl_easy_setopt( m_curlHandle, CURLOPT_HTTPHEADER, headers_slist ); -+ curl_easy_setopt(m_curlHandle, CURLOPT_HTTPHEADER, headers_slist.get()); - - // Set the proxy configuration if any - if ( !libcmis::SessionFactory::getProxy( ).empty() ) -@@ -274,9 +273,6 @@ - // Perform the query - CURLcode errCode = curl_easy_perform( m_curlHandle ); - -- // Free the headers list -- curl_slist_free_all( headers_slist ); -- - // Process the response - bool isHttpError = errCode == CURLE_HTTP_RETURNED_ERROR; - if ( CURLE_OK != errCode && !( m_noHttpErrors && isHttpError ) ) diff --git a/external/libcmis/initprotocols.patch.1 b/external/libcmis/initprotocols.patch.1 deleted file mode 100644 index 5e1d8943c699..000000000000 --- a/external/libcmis/initprotocols.patch.1 +++ /dev/null @@ -1,147 +0,0 @@ ---- libcmis/src/libcmis/session-factory.cxx.orig 2024-06-21 17:40:02.696092806 +0200 -+++ libcmis/src/libcmis/session-factory.cxx 2024-06-21 17:32:21.759833389 +0200 -@@ -75,12 +75,15 @@ - if ( bindingUrl == "https://www.googleapis.com/drive/v3" ) - { - session = new GDriveSession( bindingUrl, username, password, -- oauth2, verbose ); -+ oauth2, verbose, -+ g_CurlInitProtocolsFunction); -+ - } - else if ( bindingUrl == "https://graph.microsoft.com/v1.0" ) - { - session = new OneDriveSession( bindingUrl, username, password, -- oauth2, verbose); -+ oauth2, verbose, -+ g_CurlInitProtocolsFunction); - } - else - { -@@ -103,7 +106,7 @@ - } - // Could be SharePoint - needs NTLM authentication - session = new SharePointSession( bindingUrl, username, -- password, verbose ); -+ password, verbose, g_CurlInitProtocolsFunction); - } - - // Try the CMIS cases: we need to autodetect the binding type ---- libcmis/src/libcmis/base-session.hxx.orig 2024-06-21 17:41:56.737651815 +0200 -+++ libcmis/src/libcmis/base-session.hxx 2024-06-21 17:42:08.466709308 +0200 -@@ -59,7 +59,8 @@ - BaseSession( std::string sBindingUrl, std::string repository, - std::string username, std::string password, - bool noSslCheck = false, -- libcmis::OAuth2DataPtr oauth2 = libcmis::OAuth2DataPtr(), bool verbose = false ); -+ libcmis::OAuth2DataPtr oauth2 = libcmis::OAuth2DataPtr(), bool verbose = false, -+ libcmis::CurlInitProtocolsFunction = nullptr); - - /** This constructor copies an existing http session. - This has been mostly designed for SessionFactory to save ---- libcmis/src/libcmis/base-session.cxx.orig 2024-06-21 17:42:28.593807967 +0200 -+++ libcmis/src/libcmis/base-session.cxx 2024-06-21 17:43:37.051143529 +0200 -@@ -43,9 +43,10 @@ - using namespace std; - - BaseSession::BaseSession( string bindingUrl, string repositoryId, string username, -- string password, bool noSslCheck, libcmis::OAuth2DataPtr oauth2, bool verbose ) : -+ string password, bool noSslCheck, libcmis::OAuth2DataPtr oauth2, bool verbose, -+ libcmis::CurlInitProtocolsFunction initProtocolsFunction) : - Session( ), -- HttpSession( username, password, noSslCheck, oauth2, verbose ), -+ HttpSession( username, password, noSslCheck, oauth2, verbose, initProtocolsFunction ), - m_bindingUrl( bindingUrl ), - m_repositoryId( repositoryId ), - m_repositories( ) ---- libcmis/src/libcmis/gdrive-session.hxx.orig 2024-06-21 17:44:32.721416413 +0200 -+++ libcmis/src/libcmis/gdrive-session.hxx 2024-06-21 17:39:01.143791090 +0200 -@@ -39,7 +39,8 @@ - std::string username, - std::string password, - libcmis::OAuth2DataPtr oauth2, -- bool verbose = false ); -+ bool verbose = false, -+ libcmis::CurlInitProtocolsFunction = nullptr); - - ~GDriveSession ( ); - ---- libcmis/src/libcmis/gdrive-session.cxx.orig 2024-06-21 17:44:59.947549870 +0200 -+++ libcmis/src/libcmis/gdrive-session.cxx 2024-06-21 17:45:26.666680841 +0200 -@@ -43,9 +43,10 @@ - string username, - string password, - libcmis::OAuth2DataPtr oauth2, -- bool verbose ) : -+ bool verbose, -+ libcmis::CurlInitProtocolsFunction initProtocolsFunction) : - BaseSession( baseUrl, string(), username, password, false, -- libcmis::OAuth2DataPtr(), verbose ) -+ libcmis::OAuth2DataPtr(), verbose, initProtocolsFunction ) - - { - // Add the dummy repository, even if we don't have OAuth2 ---- libcmis/src/libcmis/onedrive-session.hxx.orig 2024-06-21 17:46:39.857039605 +0200 -+++ libcmis/src/libcmis/onedrive-session.hxx 2024-06-21 17:46:59.045133662 +0200 -@@ -40,7 +40,8 @@ - std::string username, - std::string password, - libcmis::OAuth2DataPtr oauth2, -- bool verbose = false ); -+ bool verbose = false, -+ libcmis::CurlInitProtocolsFunction = nullptr); - - ~OneDriveSession ( ); - ---- libcmis/src/libcmis/onedrive-session.cxx.orig 2024-06-21 17:47:35.187310824 +0200 -+++ libcmis/src/libcmis/onedrive-session.cxx 2024-06-21 17:48:02.068442589 +0200 -@@ -41,9 +41,10 @@ - string username, - string password, - libcmis::OAuth2DataPtr oauth2, -- bool verbose ) : -+ bool verbose, -+ libcmis::CurlInitProtocolsFunction initProtocolsFunction) : - BaseSession( baseUrl, string(), username, password, false, -- libcmis::OAuth2DataPtr(), verbose ) -+ libcmis::OAuth2DataPtr(), verbose, initProtocolsFunction) - - { - // Add the dummy repository ---- libcmis/src/libcmis/sharepoint-session.hxx.orig 2024-06-21 18:02:35.120719197 +0200 -+++ libcmis/src/libcmis/sharepoint-session.hxx 2024-06-21 18:02:54.288813088 +0200 -@@ -39,7 +39,8 @@ - SharePointSession( std::string baseUrl, - std::string username, - std::string password, -- bool verbose = false ); -+ bool verbose = false, -+ libcmis::CurlInitProtocolsFunction = nullptr); - - SharePointSession( std::string baseUrl, - const HttpSession& httpSession, ---- libcmis/src/libcmis/sharepoint-session.cxx.orig 2024-06-21 16:02:24.597237776 +0200 -+++ libcmis/src/libcmis/sharepoint-session.cxx 2024-06-21 18:03:48.109076715 +0200 -@@ -42,9 +42,10 @@ - SharePointSession::SharePointSession ( string baseUrl, - string username, - string password, -- bool verbose ) : -+ bool verbose, -+ libcmis::CurlInitProtocolsFunction initProtocolsFunction) : - BaseSession( baseUrl, string(), username, password, false, -- libcmis::OAuth2DataPtr(), verbose ), -+ libcmis::OAuth2DataPtr(), verbose, initProtocolsFunction ), - m_digestCode( string( ) ) - - { ---- libcmis/src/libcmis/http-session.cxx.orig 2024-06-21 18:24:44.192002619 +0200 -+++ libcmis/src/libcmis/http-session.cxx 2024-06-21 18:24:46.329012530 +0200 -@@ -981,6 +981,7 @@ - case CURLE_COULDNT_RESOLVE_HOST: - type = "dnsFailed"; - break; -+ case CURLE_UNSUPPORTED_PROTOCOL: - case CURLE_COULDNT_CONNECT: - case CURLE_SSL_CONNECT_ERROR: - case CURLE_SSL_CERTPROBLEM: diff --git a/external/libcmis/sharepoint-auth.patch.1 b/external/libcmis/sharepoint-auth.patch.1 deleted file mode 100644 index ff01c1291787..000000000000 --- a/external/libcmis/sharepoint-auth.patch.1 +++ /dev/null @@ -1,13 +0,0 @@ ---- libcmis/src/libcmis/sharepoint-session.cxx.orig 2024-06-20 18:02:12.751118095 +0200 -+++ libcmis/src/libcmis/sharepoint-session.cxx 2024-06-20 18:04:36.467083223 +0200 -@@ -207,6 +207,10 @@ - - headers_slist.reset(curl_slist_append(headers_slist.release(), "accept:application/json; odata=verbose")); - headers_slist.reset(curl_slist_append(headers_slist.release(), ("x-requestdigest:" + m_digestCode).c_str())); -+ // newer Sharepoint requires this; this can be detected based on header -+ // "x-msdavext_error" starting with "917656;" typically with a 403 status -+ // but since this class is specifically for SharePoint just add it always -+ headers_slist.reset(curl_slist_append(headers_slist.release(), "X-FORMS_BASED_AUTH_ACCEPTED: f")); - - if ( !getUsername().empty() && !getPassword().empty() ) - { diff --git a/external/libebook/ExternalProject_libebook.mk b/external/libebook/ExternalProject_libebook.mk index e1b04df38087..61ad9037ff4e 100644 --- a/external/libebook/ExternalProject_libebook.mk +++ b/external/libebook/ExternalProject_libebook.mk @@ -27,7 +27,7 @@ $(eval $(call gb_ExternalProject_use_externals,libebook,\ $(call gb_ExternalProject_get_state_target,libebook,build) : $(call gb_Trace_StartRange,libebook,EXTERNAL) $(call gb_ExternalProject_run,build,\ - export PKG_CONFIG="" \ + export PKG_CONFIG=true \ && unset MSYS_NO_PATHCONV && MAKE=$(MAKE) $(gb_RUN_CONFIGURE) ./configure \ --with-pic \ --enable-static \ diff --git a/external/libebook/UnpackedTarball_libebook.mk b/external/libebook/UnpackedTarball_libebook.mk index b294b69b19aa..f2e252fc5729 100644 --- a/external/libebook/UnpackedTarball_libebook.mk +++ b/external/libebook/UnpackedTarball_libebook.mk @@ -15,10 +15,4 @@ $(eval $(call gb_UnpackedTarball_update_autoconf_configs,libebook)) $(eval $(call gb_UnpackedTarball_set_patchlevel,libebook,0)) -$(eval $(call gb_UnpackedTarball_add_patches,libebook, \ - external/libebook/libebook-no-icu-boolean.patch.1 \ - external/libebook/include.patch \ - external/libebook/enumarith.patch \ -)) - # vim: set noet sw=4 ts=4: diff --git a/external/libebook/enumarith.patch b/external/libebook/enumarith.patch deleted file mode 100644 index f82c29d61747..000000000000 --- a/external/libebook/enumarith.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- src/lib/EBOOKDocument.cpp -+++ src/lib/EBOOKDocument.cpp -@@ -147,11 +147,11 @@ - { - const char *const name = char_cast(xmlTextReaderConstLocalName(reader.get())); - const char *const uri = char_cast(xmlTextReaderConstNamespaceUri(reader.get())); -- if ((EBOOKHTMLToken::html | EBOOKHTMLToken::NS_html) == getHTMLTokenId(name, uri)) -+ if ((+EBOOKHTMLToken::html | EBOOKHTMLToken::NS_html) == getHTMLTokenId(name, uri)) - type = EBOOKDocument::TYPE_XHTML; -- else if ((EPubToken::container | EPubToken::NS_container) == getEPubTokenId(name, uri)) -+ else if ((+EPubToken::container | EPubToken::NS_container) == getEPubTokenId(name, uri)) - type = EBOOKDocument::TYPE_EPUB; -- else if ((EBOOKOPFToken::package | EBOOKOPFToken::NS_opf) == getOPFTokenId(name, uri)) -+ else if ((+EBOOKOPFToken::package | EBOOKOPFToken::NS_opf) == getOPFTokenId(name, uri)) - type = EBOOKDocument::TYPE_EPUB; - else if (EBOOKOPFToken::package == getOPFTokenId(name, uri)) - type = EBOOKDocument::TYPE_OPENEBOOK; diff --git a/external/libebook/include.patch b/external/libebook/include.patch deleted file mode 100644 index fe6d8bdbe33c..000000000000 --- a/external/libebook/include.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- src/lib/BBeBCollector.cpp -+++ src/lib/BBeBCollector.cpp -@@ -7,6 +7,7 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -+#include - #include - - #include diff --git a/external/libebook/libebook-no-icu-boolean.patch.1 b/external/libebook/libebook-no-icu-boolean.patch.1 deleted file mode 100644 index 0e53546b7cc9..000000000000 --- a/external/libebook/libebook-no-icu-boolean.patch.1 +++ /dev/null @@ -1,12 +0,0 @@ -diff -ur libebook.org/src/lib/EBOOKCharsetConverter.cpp libebook/src/lib/EBOOKCharsetConverter.cpp ---- libebook.org/src/lib/EBOOKCharsetConverter.cpp 2018-01-01 12:16:28.000000000 +0100 -+++ libebook/src/lib/EBOOKCharsetConverter.cpp 2020-11-16 21:19:46.699315299 +0100 -@@ -124,7 +124,7 @@ - m_converterToUTF8.get(), m_converterToUnicode.get(), - &outText, outText + out.size(), &inText, inText + length, - nullptr, nullptr, nullptr, nullptr, -- TRUE, TRUE, &status) -+ true, true, &status) - ; - if (status==U_BUFFER_OVERFLOW_ERROR) - { diff --git a/external/libepubgen/UnpackedTarball_libepubgen.mk b/external/libepubgen/UnpackedTarball_libepubgen.mk index 3c505ea1b2b4..5c9dcf26d3a2 100644 --- a/external/libepubgen/UnpackedTarball_libepubgen.mk +++ b/external/libepubgen/UnpackedTarball_libepubgen.mk @@ -8,7 +8,7 @@ # epubgen_patches := -epubgen_patches += tdf-120491.patch +epubgen_patches += tdf-120491.patch tdf-119539.patch.1 $(eval $(call gb_UnpackedTarball_UnpackedTarball,libepubgen)) diff --git a/external/libepubgen/tdf-119539.patch.1 b/external/libepubgen/tdf-119539.patch.1 new file mode 100644 index 000000000000..1d8326deb107 --- /dev/null +++ b/external/libepubgen/tdf-119539.patch.1 @@ -0,0 +1,50 @@ +diff -ur libepubgen.org/src/lib/EPUBGenerator.cpp libepubgen/src/lib/EPUBGenerator.cpp +--- libepubgen.org/src/lib/EPUBGenerator.cpp 2026-07-02 18:46:39.616796632 +0200 ++++ libepubgen/src/lib/EPUBGenerator.cpp 2026-07-02 18:50:55.733580395 +0200 +@@ -336,6 +336,29 @@ + sink.insertCharacters(language); + sink.closeElement("dc:language"); + ++ const librevenge::RVNGPropertyListVector *coverImages = m_metadata.child("librevenge:cover-images"); ++ if (coverImages) ++ { ++ int nCurrentCover = 0; ++ for (size_t i = 0; i < coverImages->count(); ++i) ++ { ++ librevenge::RVNGPropertyList const &propertyList = (*coverImages)[i]; ++ if (propertyList["office:binary-data"] && propertyList["librevenge:mime-type"]) ++ { ++ ++nCurrentCover; ++ ++ std::string strCurrentCover = std::to_string(nCurrentCover); ++ strCurrentCover.insert(0, 4 - strCurrentCover.length(), '0'); ++ std::string content = "cover" + strCurrentCover; ++ RVNGPropertyList metaAttrs; ++ metaAttrs.insert("content", content.c_str()); ++ metaAttrs.insert("name", "cover"); ++ sink.openElement("meta", metaAttrs); ++ sink.closeElement("meta"); ++ } ++ } ++ } ++ + if (m_version >= 30) + { + RVNGString date; +diff -ur libepubgen.org/src/lib/EPUBImageManager.cpp libepubgen/src/lib/EPUBImageManager.cpp +--- libepubgen.org/src/lib/EPUBImageManager.cpp 2026-07-02 18:46:39.615945896 +0200 ++++ libepubgen/src/lib/EPUBImageManager.cpp 2026-07-02 18:50:02.905292875 +0200 +@@ -84,7 +84,12 @@ + const string mime(mimetype.cstr()); + + std::ostringstream nameBuf; +- nameBuf << "image" << std::setw(4) << std::setfill('0') << m_number.next(); ++ std::string prefix = "image"; ++ if (properties == "cover-image") ++ { ++ prefix = "cover"; ++ } ++ nameBuf << prefix << std::setw(4) << std::setfill('0') << m_number.next(); + const string id = nameBuf.str(); + + nameBuf << "." << getExtension(mime); diff --git a/external/libexttextcat/ExternalPackage_fingerprint.mk b/external/libexttextcat/ExternalPackage_fingerprint.mk index fc53611e17c9..4c5fd0880793 100644 --- a/external/libexttextcat/ExternalPackage_fingerprint.mk +++ b/external/libexttextcat/ExternalPackage_fingerprint.mk @@ -61,6 +61,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,libexttextcat_fingerprint,$( langclass/LM/fo.lm \ langclass/LM/fon.lm \ langclass/LM/fr.lm \ + langclass/LM/frp.lm \ langclass/LM/fur.lm \ langclass/LM/fy.lm \ langclass/LM/ga.lm \ @@ -70,7 +71,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,libexttextcat_fingerprint,$( langclass/LM/gu.lm \ langclass/LM/gug.lm \ langclass/LM/gv.lm \ - langclass/LM/ha-NG.lm \ + langclass/LM/ha-Latn-NG.lm \ langclass/LM/haw.lm \ langclass/LM/he.lm \ langclass/LM/hi.lm \ @@ -87,6 +88,8 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,libexttextcat_fingerprint,$( langclass/LM/it.lm \ langclass/LM/ja.lm \ langclass/LM/ka.lm \ + langclass/LM/kaa.lm \ + langclass/LM/kab.lm \ langclass/LM/kbd.lm \ langclass/LM/kk.lm \ langclass/LM/kl.lm \ @@ -107,6 +110,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,libexttextcat_fingerprint,$( langclass/LM/lt.lm \ langclass/LM/lv.lm \ langclass/LM/mai.lm \ + langclass/LM/mfe.lm \ langclass/LM/mi.lm \ langclass/LM/min.lm \ langclass/LM/mk.lm \ @@ -134,6 +138,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,libexttextcat_fingerprint,$( langclass/LM/plt.lm \ langclass/LM/pt.lm \ langclass/LM/quh.lm \ + langclass/LM/qul.lm \ langclass/LM/quz.lm \ langclass/LM/rm.lm \ langclass/LM/ro.lm \ @@ -148,9 +153,12 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,libexttextcat_fingerprint,$( langclass/LM/sg.lm \ langclass/LM/shs.lm \ langclass/LM/si.lm \ + langclass/LM/sid.lm \ langclass/LM/sk.lm \ langclass/LM/skr.lm \ langclass/LM/sl.lm \ + langclass/LM/smn.lm \ + langclass/LM/sms.lm \ langclass/LM/so.lm \ langclass/LM/sq.lm \ langclass/LM/sr-Cyrl.lm \ @@ -162,6 +170,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,libexttextcat_fingerprint,$( langclass/LM/swb.lm \ langclass/LM/sw.lm \ langclass/LM/ta.lm \ + langclass/LM/te.lm \ langclass/LM/tet.lm \ langclass/LM/tg.lm \ langclass/LM/th.lm \ @@ -188,6 +197,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,libexttextcat_fingerprint,$( langclass/LM/xh.lm \ langclass/LM/yi.lm \ langclass/LM/yo.lm \ + langclass/LM/yrk.lm \ langclass/LM/zh-Hans.lm \ langclass/LM/zh-Hant.lm \ langclass/LM/zu.lm \ diff --git a/external/libfreehand/UnpackedTarball_libfreehand.mk b/external/libfreehand/UnpackedTarball_libfreehand.mk index 641b470e3b25..e089e6a1dcec 100644 --- a/external/libfreehand/UnpackedTarball_libfreehand.mk +++ b/external/libfreehand/UnpackedTarball_libfreehand.mk @@ -15,10 +15,4 @@ $(eval $(call gb_UnpackedTarball_update_autoconf_configs,libfreehand)) $(eval $(call gb_UnpackedTarball_set_patchlevel,libfreehand,0)) -# icu-65-api-macros-with-semicolon.patch.1 -# See http://site.icu-project.org/download/65 Migration Issues -$(eval $(call gb_UnpackedTarball_add_patches,libfreehand,\ - external/libfreehand/icu-65-api-macros-with-semicolon.patch.1 \ -)) - # vim: set noet sw=4 ts=4: diff --git a/external/libfreehand/icu-65-api-macros-with-semicolon.patch.1 b/external/libfreehand/icu-65-api-macros-with-semicolon.patch.1 deleted file mode 100644 index 20b0af801a3a..000000000000 --- a/external/libfreehand/icu-65-api-macros-with-semicolon.patch.1 +++ /dev/null @@ -1,12 +0,0 @@ -diff -ur libfreehand.org/src/lib/libfreehand_utils.cpp libfreehand/src/lib/libfreehand_utils.cpp ---- libfreehand.org/src/lib/libfreehand_utils.cpp 2017-09-16 12:28:50.000000000 +0200 -+++ libfreehand/src/lib/libfreehand_utils.cpp 2019-10-28 23:02:38.581354923 +0100 -@@ -162,7 +162,7 @@ - while (j < length) - { - UChar32 c; -- U16_NEXT(s, j, length, c) -+ U16_NEXT(s, j, length, c); - unsigned char outbuf[U8_MAX_LENGTH+1]; - int i = 0; - U8_APPEND_UNSAFE(&outbuf[0], i, c); diff --git a/external/libgpg-error/ExternalPackage_libgpg-error.mk b/external/libgpg-error/ExternalPackage_libgpg-error.mk index 9ac9b2e61ae0..b8ae19fce5ce 100644 --- a/external/libgpg-error/ExternalPackage_libgpg-error.mk +++ b/external/libgpg-error/ExternalPackage_libgpg-error.mk @@ -15,7 +15,7 @@ ifneq ($(DISABLE_DYNLOADING),TRUE) ifeq ($(OS),LINUX) -$(eval $(call gb_ExternalPackage_add_file,libgpg-error,$(LIBO_LIB_FOLDER)/libgpg-error-lo.so.0,src/.libs/libgpg-error-lo.so.0.41.2)) +$(eval $(call gb_ExternalPackage_add_file,libgpg-error,$(LIBO_LIB_FOLDER)/libgpg-error-lo.so.0,src/.libs/libgpg-error-lo.so.0.42.1)) else ifeq ($(OS),MACOSX) diff --git a/external/libjxl/Makefile b/external/libjxl/Makefile new file mode 100644 index 000000000000..e4968cf85fb6 --- /dev/null +++ b/external/libjxl/Makefile @@ -0,0 +1,7 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- + +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/external/libjxl/Module_libjxl.mk b/external/libjxl/Module_libjxl.mk new file mode 100644 index 000000000000..a20f2199ee02 --- /dev/null +++ b/external/libjxl/Module_libjxl.mk @@ -0,0 +1,17 @@ +# -*- 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,libjxl)) + +$(eval $(call gb_Module_add_targets,libjxl,\ + StaticLibrary_libjxl \ + UnpackedTarball_libjxl \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/external/libjxl/README b/external/libjxl/README new file mode 100644 index 000000000000..be8a7d7acfcf --- /dev/null +++ b/external/libjxl/README @@ -0,0 +1,19 @@ +libjxl is a library for encoding and decoding JPEG XL images, from +[https://github.com/libjxl/libjxl]. + +How to update the extra headers: +================================ + +The extra header files (jxl_cms_export.h, jxl_export.h, jxl_threads_export.h, +version.h) can be generated with: + +(cd workdir/UnpackedTarball/libjxl/ && cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF) + +If new header files are generated in this way, they will be placed in +workdir/UnpackedTarball/libjxl/lib/include/jxl/. + +There are more detailed build instructions in +workdir/UnpackedTarball/libjxl/BUILDING.md (for Linux) and +workdir/UnpackedTarball/libjxl/developing_in_windows_vcpkg.md (for Windows). (A +full build isn't necessary to generate the headers, only the first cmake +command without --build.) diff --git a/external/libjxl/StaticLibrary_libjxl.mk b/external/libjxl/StaticLibrary_libjxl.mk new file mode 100644 index 000000000000..e6112db0eb69 --- /dev/null +++ b/external/libjxl/StaticLibrary_libjxl.mk @@ -0,0 +1,109 @@ +# -*- 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_StaticLibrary_StaticLibrary,libjxl)) + +$(eval $(call gb_StaticLibrary_use_unpacked,libjxl,libjxl)) + +$(eval $(call gb_StaticLibrary_use_externals,libjxl,\ + brotli \ + highway \ + lcms2 \ +)) + +$(eval $(call gb_StaticLibrary_set_warnings_disabled,libjxl)) + +$(eval $(call gb_StaticLibrary_set_include,libjxl,\ + -I$(WORKDIR)/UnpackedTarball/libjxl \ + -I$(WORKDIR)/UnpackedTarball/libjxl/lib/include \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_StaticLibrary_add_defs,libjxl,\ + -DJPEGXL_ENABLE_TRANSCODE_JPEG=OFF \ + -DJXL_INTERNAL_LIBRARY_BUILD \ + -DJXL_THREADS_INTERNAL_LIBRARY_BUILD \ + -Djxl_cms_EXPORTS \ +)) + +$(eval $(call gb_StaticLibrary_set_generated_cxx_suffix,libjxl,cc)) + +$(eval $(call gb_StaticLibrary_add_generated_exception_objects,libjxl,\ + UnpackedTarball/libjxl/lib/jxl/ac_strategy \ + UnpackedTarball/libjxl/lib/jxl/alpha \ + UnpackedTarball/libjxl/lib/jxl/ans_common \ + UnpackedTarball/libjxl/lib/jxl/blending \ + UnpackedTarball/libjxl/lib/jxl/box_content_decoder \ + UnpackedTarball/libjxl/lib/jxl/chroma_from_luma \ + UnpackedTarball/libjxl/lib/jxl/coeff_order \ + UnpackedTarball/libjxl/lib/jxl/color_encoding_internal \ + UnpackedTarball/libjxl/lib/jxl/compressed_dc \ + UnpackedTarball/libjxl/lib/jxl/dec_ans \ + UnpackedTarball/libjxl/lib/jxl/dec_cache \ + UnpackedTarball/libjxl/lib/jxl/dec_context_map \ + UnpackedTarball/libjxl/lib/jxl/dec_frame \ + UnpackedTarball/libjxl/lib/jxl/dec_group \ + UnpackedTarball/libjxl/lib/jxl/dec_group_border \ + UnpackedTarball/libjxl/lib/jxl/dec_huffman \ + UnpackedTarball/libjxl/lib/jxl/dec_modular \ + UnpackedTarball/libjxl/lib/jxl/dec_noise \ + UnpackedTarball/libjxl/lib/jxl/dec_patch_dictionary \ + UnpackedTarball/libjxl/lib/jxl/dec_xyb \ + UnpackedTarball/libjxl/lib/jxl/decode \ + UnpackedTarball/libjxl/lib/jxl/encode \ + UnpackedTarball/libjxl/lib/jxl/entropy_coder \ + UnpackedTarball/libjxl/lib/jxl/epf \ + UnpackedTarball/libjxl/lib/jxl/fields \ + UnpackedTarball/libjxl/lib/jxl/frame_header \ + UnpackedTarball/libjxl/lib/jxl/headers \ + UnpackedTarball/libjxl/lib/jxl/huffman_table \ + UnpackedTarball/libjxl/lib/jxl/icc_codec \ + UnpackedTarball/libjxl/lib/jxl/icc_codec_common \ + UnpackedTarball/libjxl/lib/jxl/image \ + UnpackedTarball/libjxl/lib/jxl/image_bundle \ + UnpackedTarball/libjxl/lib/jxl/image_metadata \ + UnpackedTarball/libjxl/lib/jxl/loop_filter \ + UnpackedTarball/libjxl/lib/jxl/memory_manager_internal \ + UnpackedTarball/libjxl/lib/jxl/modular/encoding/dec_ma \ + UnpackedTarball/libjxl/lib/jxl/modular/encoding/encoding \ + UnpackedTarball/libjxl/lib/jxl/modular/modular_image \ + UnpackedTarball/libjxl/lib/jxl/modular/transform/palette \ + UnpackedTarball/libjxl/lib/jxl/modular/transform/rct \ + UnpackedTarball/libjxl/lib/jxl/modular/transform/squeeze \ + UnpackedTarball/libjxl/lib/jxl/modular/transform/transform \ + UnpackedTarball/libjxl/lib/jxl/opsin_params \ + UnpackedTarball/libjxl/lib/jxl/passes_state \ + UnpackedTarball/libjxl/lib/jxl/quant_weights \ + UnpackedTarball/libjxl/lib/jxl/quantizer \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/low_memory_render_pipeline \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/render_pipeline \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/simple_render_pipeline \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_blending \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_chroma_upsampling \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_cms \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_epf \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_from_linear \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_gaborish \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_noise \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_patches \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_splines \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_spot \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_to_linear \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_tone_mapping \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_upsampling \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_write \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_xyb \ + UnpackedTarball/libjxl/lib/jxl/render_pipeline/stage_ycbcr \ + UnpackedTarball/libjxl/lib/jxl/simd_util \ + UnpackedTarball/libjxl/lib/jxl/splines \ + UnpackedTarball/libjxl/lib/jxl/toc \ + UnpackedTarball/libjxl/lib/threads/resizable_parallel_runner \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/external/libjxl/UnpackedTarball_libjxl.mk b/external/libjxl/UnpackedTarball_libjxl.mk new file mode 100644 index 000000000000..88b69da0b4b3 --- /dev/null +++ b/external/libjxl/UnpackedTarball_libjxl.mk @@ -0,0 +1,33 @@ +# -*- 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_UnpackedTarball_UnpackedTarball,libjxl)) + +$(eval $(call gb_UnpackedTarball_set_tarball,libjxl,$(LIBJXL_TARBALL))) + +# Exclude tools/benchmark/metrics subdirectory containing symlinks that tar +# in the Windows build cannot handle +$(eval $(call gb_UnpackedTarball_set_exclude_pattern,libjxl,\ + */tools/benchmark/metrics \ +)) + +$(eval $(call gb_UnpackedTarball_add_files,libjxl,lib/include/jxl,\ + external/libjxl/jxl_cms_export.h \ + external/libjxl/jxl_export.h \ + external/libjxl/jxl_threads_export.h \ + external/libjxl/version.h \ +)) + +ifeq ($(OS),WNT) +$(eval $(call gb_UnpackedTarball_add_patches,libjxl,\ + external/libjxl/windows-compile-directives.patch.0 \ +)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/external/libjxl/jxl_cms_export.h b/external/libjxl/jxl_cms_export.h new file mode 100644 index 000000000000..3e28f0522679 --- /dev/null +++ b/external/libjxl/jxl_cms_export.h @@ -0,0 +1,43 @@ + +#ifndef JXL_CMS_EXPORT_H +#define JXL_CMS_EXPORT_H + +#ifdef JXL_CMS_STATIC_DEFINE +# define JXL_CMS_EXPORT +# define JXL_CMS_NO_EXPORT +#else +# ifndef JXL_CMS_EXPORT +# ifdef jxl_cms_EXPORTS + /* We are building this library */ +# define JXL_CMS_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define JXL_CMS_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef JXL_CMS_NO_EXPORT +# define JXL_CMS_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef JXL_CMS_DEPRECATED +# define JXL_CMS_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef JXL_CMS_DEPRECATED_EXPORT +# define JXL_CMS_DEPRECATED_EXPORT JXL_CMS_EXPORT JXL_CMS_DEPRECATED +#endif + +#ifndef JXL_CMS_DEPRECATED_NO_EXPORT +# define JXL_CMS_DEPRECATED_NO_EXPORT JXL_CMS_NO_EXPORT JXL_CMS_DEPRECATED +#endif + +/* NOLINTNEXTLINE(readability-avoid-unconditional-preprocessor-if) */ +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef JXL_CMS_NO_DEPRECATED +# define JXL_CMS_NO_DEPRECATED +# endif +#endif + +#endif /* JXL_CMS_EXPORT_H */ diff --git a/external/libjxl/jxl_export.h b/external/libjxl/jxl_export.h new file mode 100644 index 000000000000..3489ab6816c4 --- /dev/null +++ b/external/libjxl/jxl_export.h @@ -0,0 +1,43 @@ + +#ifndef JXL_EXPORT_H +#define JXL_EXPORT_H + +#ifdef JXL_STATIC_DEFINE +# define JXL_EXPORT +# define JXL_NO_EXPORT +#else +# ifndef JXL_EXPORT +# ifdef JXL_INTERNAL_LIBRARY_BUILD + /* We are building this library */ +# define JXL_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define JXL_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef JXL_NO_EXPORT +# define JXL_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef JXL_DEPRECATED +# define JXL_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef JXL_DEPRECATED_EXPORT +# define JXL_DEPRECATED_EXPORT JXL_EXPORT JXL_DEPRECATED +#endif + +#ifndef JXL_DEPRECATED_NO_EXPORT +# define JXL_DEPRECATED_NO_EXPORT JXL_NO_EXPORT JXL_DEPRECATED +#endif + +/* NOLINTNEXTLINE(readability-avoid-unconditional-preprocessor-if) */ +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef JXL_NO_DEPRECATED +# define JXL_NO_DEPRECATED +# endif +#endif + +#endif /* JXL_EXPORT_H */ diff --git a/external/libjxl/jxl_threads_export.h b/external/libjxl/jxl_threads_export.h new file mode 100644 index 000000000000..62a56e2846d0 --- /dev/null +++ b/external/libjxl/jxl_threads_export.h @@ -0,0 +1,43 @@ + +#ifndef JXL_THREADS_EXPORT_H +#define JXL_THREADS_EXPORT_H + +#ifdef JXL_THREADS_STATIC_DEFINE +# define JXL_THREADS_EXPORT +# define JXL_THREADS_NO_EXPORT +#else +# ifndef JXL_THREADS_EXPORT +# ifdef JXL_THREADS_INTERNAL_LIBRARY_BUILD + /* We are building this library */ +# define JXL_THREADS_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define JXL_THREADS_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef JXL_THREADS_NO_EXPORT +# define JXL_THREADS_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef JXL_THREADS_DEPRECATED +# define JXL_THREADS_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef JXL_THREADS_DEPRECATED_EXPORT +# define JXL_THREADS_DEPRECATED_EXPORT JXL_THREADS_EXPORT JXL_THREADS_DEPRECATED +#endif + +#ifndef JXL_THREADS_DEPRECATED_NO_EXPORT +# define JXL_THREADS_DEPRECATED_NO_EXPORT JXL_THREADS_NO_EXPORT JXL_THREADS_DEPRECATED +#endif + +/* NOLINTNEXTLINE(readability-avoid-unconditional-preprocessor-if) */ +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef JXL_THREADS_NO_DEPRECATED +# define JXL_THREADS_NO_DEPRECATED +# endif +#endif + +#endif /* JXL_THREADS_EXPORT_H */ diff --git a/external/libjxl/version.h b/external/libjxl/version.h new file mode 100644 index 000000000000..6689bd1f60f3 --- /dev/null +++ b/external/libjxl/version.h @@ -0,0 +1,44 @@ +/* Copyright (c) the JPEG XL Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +/** @addtogroup libjxl_common + * @{ + * @file version.h + * @brief libjxl version information + */ + +#ifndef JXL_VERSION_H_ +#define JXL_VERSION_H_ + +#if defined(JPEGXL_MAJOR_VERSION) || defined(JPEGXL_MINOR_VERSION) || \ + defined(JPEGXL_PATCH_VERSION) +#error JPEGXL_VERSION is already defined +#endif + +#define JPEGXL_MAJOR_VERSION 0 ///< JPEG XL Major version +#define JPEGXL_MINOR_VERSION 11 ///< JPEG XL Minor version +#define JPEGXL_PATCH_VERSION 2 ///< JPEG XL Patch version + +/** Can be used to conditionally compile code for a specific JXL version + * @param[maj] major version + * @param[min] minor version + * + * @code + * #if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0,8,0) + * // use old/deprecated api + * #else + * // use current api + * #endif + * @endcode + */ +#define JPEGXL_COMPUTE_NUMERIC_VERSION(major,minor,patch) (((major)<<24) | ((minor)<<16) | ((patch)<<8) | 0) + +/* Numeric representation of the version */ +#define JPEGXL_NUMERIC_VERSION JPEGXL_COMPUTE_NUMERIC_VERSION(JPEGXL_MAJOR_VERSION, JPEGXL_MINOR_VERSION, JPEGXL_PATCH_VERSION) + +#endif /* JXL_VERSION_H_ */ + +/** @}*/ diff --git a/external/libjxl/windows-compile-directives.patch.0 b/external/libjxl/windows-compile-directives.patch.0 new file mode 100644 index 000000000000..9f7d640cc145 --- /dev/null +++ b/external/libjxl/windows-compile-directives.patch.0 @@ -0,0 +1,81 @@ +--- lib/include/jxl/jxl_cms_export.h 2026-08-21 18:50:38.834365872 +0200 ++++ lib/include/jxl/jxl_cms_export.h 2026-08-21 18:50:38.834365872 +0200 +@@ -9,20 +9,20 @@ + # ifndef JXL_CMS_EXPORT + # ifdef jxl_cms_EXPORTS + /* We are building this library */ +-# define JXL_CMS_EXPORT __attribute__((visibility("default"))) ++# define JXL_CMS_EXPORT __declspec(dllexport) + # else + /* We are using this library */ +-# define JXL_CMS_EXPORT __attribute__((visibility("default"))) ++# define JXL_CMS_EXPORT __declspec(dllimport) + # endif + # endif + + # ifndef JXL_CMS_NO_EXPORT +-# define JXL_CMS_NO_EXPORT __attribute__((visibility("hidden"))) ++# define JXL_CMS_NO_EXPORT + # endif + #endif + + #ifndef JXL_CMS_DEPRECATED +-# define JXL_CMS_DEPRECATED __attribute__ ((__deprecated__)) ++# define JXL_CMS_DEPRECATED __declspec(deprecated) + #endif + + #ifndef JXL_CMS_DEPRECATED_EXPORT +--- lib/include/jxl/jxl_export.h 2026-08-21 18:50:38.834365872 +0200 ++++ lib/include/jxl/jxl_export.h 2026-08-21 18:50:38.834365872 +0200 +@@ -9,20 +9,20 @@ + # ifndef JXL_EXPORT + # ifdef JXL_INTERNAL_LIBRARY_BUILD + /* We are building this library */ +-# define JXL_EXPORT __attribute__((visibility("default"))) ++# define JXL_EXPORT __declspec(dllexport) + # else + /* We are using this library */ +-# define JXL_EXPORT __attribute__((visibility("default"))) ++# define JXL_EXPORT __declspec(dllimport) + # endif + # endif + + # ifndef JXL_NO_EXPORT +-# define JXL_NO_EXPORT __attribute__((visibility("hidden"))) ++# define JXL_NO_EXPORT + # endif + #endif + + #ifndef JXL_DEPRECATED +-# define JXL_DEPRECATED __attribute__ ((__deprecated__)) ++# define JXL_DEPRECATED __declspec(deprecated) + #endif + + #ifndef JXL_DEPRECATED_EXPORT +--- lib/include/jxl/jxl_threads_export.h 2026-08-21 18:50:38.834365872 +0200 ++++ lib/include/jxl/jxl_threads_export.h 2026-08-21 18:50:38.834365872 +0200 +@@ -9,20 +9,20 @@ + # ifndef JXL_THREADS_EXPORT + # ifdef JXL_THREADS_INTERNAL_LIBRARY_BUILD + /* We are building this library */ +-# define JXL_THREADS_EXPORT __attribute__((visibility("default"))) ++# define JXL_THREADS_EXPORT __declspec(dllexport) + # else + /* We are using this library */ +-# define JXL_THREADS_EXPORT __attribute__((visibility("default"))) ++# define JXL_THREADS_EXPORT __declspec(dllimport) + # endif + # endif + + # ifndef JXL_THREADS_NO_EXPORT +-# define JXL_THREADS_NO_EXPORT __attribute__((visibility("hidden"))) ++# define JXL_THREADS_NO_EXPORT + # endif + #endif + + #ifndef JXL_THREADS_DEPRECATED +-# define JXL_THREADS_DEPRECATED __attribute__ ((__deprecated__)) ++# define JXL_THREADS_DEPRECATED __declspec(deprecated) + #endif + + #ifndef JXL_THREADS_DEPRECATED_EXPORT diff --git a/external/libmspub/UnpackedTarball_libmspub.mk b/external/libmspub/UnpackedTarball_libmspub.mk index 287be540dee6..1fa4c4135d50 100644 --- a/external/libmspub/UnpackedTarball_libmspub.mk +++ b/external/libmspub/UnpackedTarball_libmspub.mk @@ -16,16 +16,9 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,libmspub,0)) # * external/libmspub/stdint.patch is upstream at # "missing include": $(eval $(call gb_UnpackedTarball_add_patches,libmspub,\ - external/libmspub/ubsan.patch \ external/libmspub/stdint.patch \ )) $(eval $(call gb_UnpackedTarball_update_autoconf_configs,libmspub)) -ifeq ($(ANDROID_APP_ABI),armeabi-v7a) -$(eval $(call gb_UnpackedTarball_add_patches,libmspub, \ - external/libmspub/libmspub_android_arm.patch.1 \ -)) -endif - # vim: set noet sw=4 ts=4: diff --git a/external/libmspub/libmspub_android_arm.patch.1 b/external/libmspub/libmspub_android_arm.patch.1 deleted file mode 100644 index 2d7d0e12c02a..000000000000 --- a/external/libmspub/libmspub_android_arm.patch.1 +++ /dev/null @@ -1,12 +0,0 @@ -diff -ur libmspub.org/src/lib/libmspub_utils.cpp libmspub/src/lib/libmspub_utils.cpp ---- libmspub.org/src/lib/libmspub_utils.cpp 2018-04-07 15:13:32.041792236 +0200 -+++ libmspub/src/lib/libmspub_utils.cpp 2018-04-07 15:14:08.547790739 +0200 -@@ -29,7 +29,7 @@ - { - va_list args; - va_start(args, format); -- std::vfprintf(stderr, format, args); -+ vfprintf(stderr, format, args); - va_end(args); - } - diff --git a/external/libmspub/ubsan.patch b/external/libmspub/ubsan.patch deleted file mode 100644 index b58249e18e0f..000000000000 --- a/external/libmspub/ubsan.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- src/lib/MSPUBContentChunkType.h -+++ src/lib/MSPUBContentChunkType.h -@@ -27,7 +27,8 @@ - CELLS = 0x63, - FONT = 0x6C, - IMAGE_2K, //these don't exist in Pub 2k3 so their value in the enum is not used. -- IMAGE_2K_DATA -+ IMAGE_2K_DATA, -+ MSPUBContentChunkType_dummy=0xFF // MSPUBParser.cpp:2359:9: runtime error: load of value 138, which is not a valid value for type 'libmspub::MSPUBContentChunkType' - }; - } // namespace libmspub - diff --git a/external/libmwaw/0001-const-up-some-arrays.patch.1 b/external/libmwaw/0001-const-up-some-arrays.patch.1 deleted file mode 100644 index 446f3748d4a0..000000000000 --- a/external/libmwaw/0001-const-up-some-arrays.patch.1 +++ /dev/null @@ -1,1065 +0,0 @@ -From eb67ddd122b2222db975ede465bb0983029f9219 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Tue, 22 Jul 2025 14:39:58 +0100 -Subject: [PATCH] const up some arrays - ---- - src/lib/BeagleWksText.cxx | 2 +- - src/lib/Canvas5Parser.cxx | 2 +- - src/lib/CanvasParser.cxx | 2 +- - src/lib/ClarisDrawParser.cxx | 2 +- - src/lib/ClarisDrawText.cxx | 4 ++-- - src/lib/ClarisWksDbaseContent.cxx | 10 +++++----- - src/lib/ClarisWksDocument.cxx | 2 +- - src/lib/ClarisWksStyleManager.cxx | 2 +- - src/lib/ClarisWksText.cxx | 4 ++-- - src/lib/DocMkrParser.cxx | 4 ++-- - src/lib/DocMkrText.cxx | 4 ++-- - src/lib/EDocParser.cxx | 2 +- - src/lib/FullWrtGraph.cxx | 2 +- - src/lib/GreatWksDBParser.cxx | 6 +++--- - src/lib/GreatWksDocument.cxx | 2 +- - src/lib/GreatWksGraph.cxx | 2 +- - src/lib/GreatWksParser.cxx | 6 +++--- - src/lib/GreatWksSSParser.cxx | 8 ++++---- - src/lib/HanMacWrdJGraph.cxx | 2 +- - src/lib/HanMacWrdJParser.cxx | 2 +- - src/lib/HanMacWrdKGraph.cxx | 2 +- - src/lib/MWAWCell.cxx | 2 +- - src/lib/MWAWGraphicStyle.cxx | 2 +- - src/lib/MWAWInputStream.cxx | 2 +- - src/lib/MWAWOLEParser.cxx | 2 +- - src/lib/MWAWParagraph.cxx | 2 +- - src/lib/MWAWPictMac.cxx | 4 ++-- - src/lib/MWAWSection.cxx | 2 +- - src/lib/MacDocParser.cxx | 2 +- - src/lib/MacDrawProParser.cxx | 2 +- - src/lib/MacWrtProStructures.cxx | 2 +- - src/lib/MarinerWrtText.cxx | 2 +- - src/lib/MoreParser.cxx | 4 ++-- - src/lib/MsWksDBParser.cxx | 6 +++--- - src/lib/MsWksDocument.cxx | 6 +++--- - src/lib/MsWksSSParser.cxx | 4 ++-- - src/lib/MultiplanParser.cxx | 2 +- - src/lib/NisusWrtParser.cxx | 12 ++++++------ - src/lib/PixelPaintParser.cxx | 2 +- - src/lib/RagTime5ClusterManager.cxx | 4 ++-- - src/lib/RagTime5Formula.cxx | 2 +- - src/lib/RagTime5Spreadsheet.cxx | 2 +- - src/lib/RagTime5StyleManager.cxx | 6 +++--- - src/lib/RagTimeParser.cxx | 6 +++--- - src/lib/RagTimeSpreadsheet.cxx | 8 ++++---- - src/lib/RagTimeStruct.hxx | 2 +- - src/lib/ReadySetGoGraph.cxx | 8 ++++---- - src/lib/WingzGraph.cxx | 2 +- - src/lib/WingzParser.cxx | 4 ++-- - src/lib/WriteNowText.cxx | 2 +- - src/lib/libmwaw_internal.cxx | 4 ++-- - src/tools/zip/xattr.cpp | 2 +- - 52 files changed, 92 insertions(+), 92 deletions(-) - -diff --git a/src/lib/BeagleWksText.cxx b/src/lib/BeagleWksText.cxx -index 3736e263..d6fc56f3 100644 ---- a/src/lib/BeagleWksText.cxx -+++ b/src/lib/BeagleWksText.cxx -@@ -228,7 +228,7 @@ struct Section final : public MWAWSection { - for (int i=0; i<4; ++i) { - if (sec.m_limitPos[i+1]<=sec.m_limitPos[i]+2) - continue; -- static char const *wh[] = {"header[fP]", "footer[fP]", "header", "footer"}; -+ static char const* const wh[] = {"header[fP]", "footer[fP]", "header", "footer"}; - o << wh[i] << "=" << std::hex << sec.m_limitPos[i] - << "->" << sec.m_limitPos[i+1] << std::hex << ","; - } -diff --git a/src/lib/Canvas5Parser.cxx b/src/lib/Canvas5Parser.cxx -index 7dee085e..b1b7004d 100644 ---- a/src/lib/Canvas5Parser.cxx -+++ b/src/lib/Canvas5Parser.cxx -@@ -387,7 +387,7 @@ bool Canvas5Parser::createZones() - - for (int w=0; w<2; ++w) { - // also some icons: ICN#, icl8, ics#, ics8 -- static char const *wh[]= {"pnot" /*0*/, "PICT" /* value in pnot */}; -+ static char const* const wh[]= {"pnot" /*0*/, "PICT" /* value in pnot */}; - auto it = entryMap.lower_bound(wh[w]); - while (it != entryMap.end() && it->first==wh[w]) { - auto const &entry=it++->second; -diff --git a/src/lib/CanvasParser.cxx b/src/lib/CanvasParser.cxx -index fba45e94..0ca7ae39 100644 ---- a/src/lib/CanvasParser.cxx -+++ b/src/lib/CanvasParser.cxx -@@ -664,7 +664,7 @@ bool CanvasParser::createZones() - auto const &entryMap = rsrcParser->getEntriesMap(); - - for (int w=0; w<5; ++w) { -- static char const *wh[]= {"HeAd" /*11164*/, "Jinf" /* 10568 */, "WIND" /* 10568 */, "LPol" /* 2,4,... */, "USER" /*0*/}; -+ static char const* const wh[]= {"HeAd" /*11164*/, "Jinf" /* 10568 */, "WIND" /* 10568 */, "LPol" /* 2,4,... */, "USER" /*0*/}; - auto it = entryMap.lower_bound(wh[w]); - while (it != entryMap.end() && it->first==wh[w]) { - auto const &entry=it++->second; -diff --git a/src/lib/ClarisDrawParser.cxx b/src/lib/ClarisDrawParser.cxx -index b5cbc4d1..87c4ff19 100644 ---- a/src/lib/ClarisDrawParser.cxx -+++ b/src/lib/ClarisDrawParser.cxx -@@ -546,7 +546,7 @@ bool ClarisDrawParser::readDocHeader() - num[i]=static_cast(input->readULong(2)); - if (!num[i]) - continue; -- static char const *wh[]= {"color", "unkn1", "gradient"}; -+ static char const* const wh[]= {"color", "unkn1", "gradient"}; - f << "num[" << wh[i] << "]=" << num[i] << ","; - } - m_styleManager->setDefaultNumbers(num[0], num[2]); -diff --git a/src/lib/ClarisDrawText.cxx b/src/lib/ClarisDrawText.cxx -index 6bc532c3..7b6184c9 100644 ---- a/src/lib/ClarisDrawText.cxx -+++ b/src/lib/ClarisDrawText.cxx -@@ -126,7 +126,7 @@ struct Paragraph final : public MWAWParagraph { - { - o << static_cast(ind) << ","; - if (ind.m_labelType > 0 && ind.m_labelType < 12) { -- static char const *labelNames[] = { -+ static char const* const labelNames[] = { - "none", "diamond", "bullet", "checkbox", "hardvard", "leader", "legal", - "upperalpha", "alpha", "numeric", "upperroman", "roman" - }; -@@ -261,7 +261,7 @@ struct ParagraphPLC { - - auto listType=int((info.m_flags>>3)&0xF); - if (listType>0 && listType < 12) { -- static char const *labelNames[] = { -+ static char const* const labelNames[] = { - "none", "diamond", "bullet", "checkbox", "hardvard", "leader", "legal", - "upperalpha", "alpha", "numeric", "upperroman", "roman" - }; -diff --git a/src/lib/ClarisWksDbaseContent.cxx b/src/lib/ClarisWksDbaseContent.cxx -index cf86f351..84f58178 100644 ---- a/src/lib/ClarisWksDbaseContent.cxx -+++ b/src/lib/ClarisWksDbaseContent.cxx -@@ -461,7 +461,7 @@ bool ClarisWksDbaseContent::readRecordSSV1(MWAWVec2i const &id, long pos, Claris - case 7: - case 8: - case 9: { -- static char const *wh[]= {"%m/%d/%y", "%B %d, %y", "%B %d, %Y", "%a, %b %d %y", "%A, %B %d %Y" }; -+ static char const* const wh[]= {"%m/%d/%y", "%B %d, %y", "%B %d, %Y", "%a, %b %d %y", "%A, %B %d %Y" }; - format.m_format=MWAWCell::F_DATE; - format.m_DTFormat=wh[fileFormat-5]; - break; -@@ -470,7 +470,7 @@ bool ClarisWksDbaseContent::readRecordSSV1(MWAWVec2i const &id, long pos, Claris - case 11: - case 12: - case 13: { -- static char const *wh[]= {"%I:%M %p", "%I:%M:%S %p", "%H:%M", "%H:%M:%S" }; -+ static char const* const wh[]= {"%I:%M %p", "%I:%M:%S %p", "%H:%M", "%H:%M:%S" }; - format.m_format=MWAWCell::F_TIME; - format.m_DTFormat=wh[fileFormat-10]; - break; -@@ -781,7 +781,7 @@ bool ClarisWksDbaseContent::readRecordSS(MWAWVec2i const &id, long pos, ClarisWk - case 7: - case 8: - case 9: { -- static char const *wh[]= {"%m/%d/%y", "%B %d, %y", "%B %d, %Y", "%a, %b %d %y", "%A, %B %d %Y" }; -+ static char const* const wh[]= {"%m/%d/%y", "%B %d, %y", "%B %d, %Y", "%a, %b %d %y", "%A, %B %d %Y" }; - format.m_format=MWAWCell::F_DATE; - format.m_DTFormat=wh[fileFormat-5]; - break; -@@ -793,7 +793,7 @@ bool ClarisWksDbaseContent::readRecordSS(MWAWVec2i const &id, long pos, ClarisWk - case 13: - case 14: - case 15: { -- static char const *wh[]= {"%H:%M", "%H:%M:%S", "%I:%M %p", "%I:%M:%S %p" }; -+ static char const* const wh[]= {"%H:%M", "%H:%M:%S", "%I:%M %p", "%I:%M:%S %p" }; - format.m_format=MWAWCell::F_TIME; - format.m_DTFormat=wh[fileFormat-12]; - break; -@@ -1389,7 +1389,7 @@ bool ClarisWksDbaseContent::readFormula(MWAWVec2i const &cPos, long endPos, std: - arity=static_cast(input->readULong(1)); - std::string name(""); - if (val<0x70) { -- static char const *wh[] = { -+ static char const* const wh[] = { - "Abs", "Acos", "Alert", "And", "Code", "Asin", "Atan", "Atan2", - "Average", "Choose", "Char", "Concatenate", "Cos", "Count", "Date", "DateToText", - -diff --git a/src/lib/ClarisWksDocument.cxx b/src/lib/ClarisWksDocument.cxx -index 42a99ca3..f9d5de3c 100644 ---- a/src/lib/ClarisWksDocument.cxx -+++ b/src/lib/ClarisWksDocument.cxx -@@ -1225,7 +1225,7 @@ bool ClarisWksDocument::readDocHeader() - val = static_cast(input->readULong(1)); - if (type != val) { - if (val >= 0 && val < 7) { -- static char const *wh[]= { "draw", "text", "spreadsheet", "database", "paint", "presentation", "table" }; -+ static char const* const wh[]= { "draw", "text", "spreadsheet", "database", "paint", "presentation", "table" }; - f << "type[display]=" << wh[val] << ","; - } - else { -diff --git a/src/lib/ClarisWksStyleManager.cxx b/src/lib/ClarisWksStyleManager.cxx -index 25e860ae..71cd8a78 100644 ---- a/src/lib/ClarisWksStyleManager.cxx -+++ b/src/lib/ClarisWksStyleManager.cxx -@@ -2806,7 +2806,7 @@ std::ostream &operator<<(std::ostream &o, ClarisWksStyleManager::CellFormat cons - { - o << static_cast(form) << ","; - if (form.m_fileFormat >= 0 && form.m_fileFormat < 16) { -- static char const *wh[16] = { -+ static char const* const wh[16] = { - "general", "currency", "percent", "scientific", "fixed", - "date[m/d/y]", "date[d B y]", "date[B d Y]", "date[a, b d Y]", "date[A, B d Y]", - "form10", "form11", -diff --git a/src/lib/ClarisWksText.cxx b/src/lib/ClarisWksText.cxx -index f8ea8865..539b2a63 100644 ---- a/src/lib/ClarisWksText.cxx -+++ b/src/lib/ClarisWksText.cxx -@@ -130,7 +130,7 @@ struct Paragraph final : public MWAWParagraph { - { - o << static_cast(ind) << ","; - if (ind.m_labelType > 0 && ind.m_labelType < 12) { -- static char const *labelNames[] = { -+ static char const* const labelNames[] = { - "none", "diamond", "bullet", "checkbox", "hardvard", "leader", "legal", - "upperalpha", "alpha", "numeric", "upperroman", "roman" - }; -@@ -260,7 +260,7 @@ struct ParagraphPLC { - - auto listType=int((info.m_flags>>3)&0xF); - if (listType>0 && listType < 12) { -- static char const *labelNames[] = { -+ static char const* const labelNames[] = { - "none", "diamond", "bullet", "checkbox", "hardvard", "leader", "legal", - "upperalpha", "alpha", "numeric", "upperroman", "roman" - }; -diff --git a/src/lib/DocMkrParser.cxx b/src/lib/DocMkrParser.cxx -index bf676852..7ea33e17 100644 ---- a/src/lib/DocMkrParser.cxx -+++ b/src/lib/DocMkrParser.cxx -@@ -113,7 +113,7 @@ std::ostream &operator<<(std::ostream &o, PictInfo const &info) - break; - } - if (info.m_action >= 0 && info.m_action <= 16) { -- static char const *wh[]= { -+ static char const* const wh[]= { - "", "goTo", "aboutDialog", "print", "quit", "launch", "sound", "QMOV", - "note", "export[asText]", "last[chapter]", "TOC[show]", "find", "appleEvent", - "next[chapter]", "prev[chapter]", "script" -@@ -389,7 +389,7 @@ bool DocMkrParser::createZones() - #ifdef DEBUG_WITH_FILES - // get rid of the default application resource - libmwaw::DebugFile &ascFile = rsrcAscii(); -- static char const *appliRsrc[]= { -+ static char const* const appliRsrc[]= { - // default, Dialog (3000: DLOG,DITL,DLGX,dctb","ictb","STR ") - "ALRT","BNDL","CNTL","CURS","CDEF", "DLOG","DLGX","DITL","FREF","ICON", "ICN#","MENU","SIZE", - "crsr","dctb","icl4","icl8","ics4", "ics8","ics#","ictb","snd ", -diff --git a/src/lib/DocMkrText.cxx b/src/lib/DocMkrText.cxx -index 0b6e7dc0..abe5af2e 100644 ---- a/src/lib/DocMkrText.cxx -+++ b/src/lib/DocMkrText.cxx -@@ -99,8 +99,8 @@ struct Footer { - //! operator<< - friend std::ostream &operator<<(std::ostream &o, Footer const &f) - { -- static char const *where[]= {"TL", "TC", "TR", "BL", "BC", "BR" }; -- static char const *what[]= { "nothing", "unkn1", "unkn2", "time", "date", -+ static char const* const where[]= {"TL", "TC", "TR", "BL", "BC", "BR" }; -+ static char const* const what[]= { "nothing", "unkn1", "unkn2", "time", "date", - "page", "fileName", "chapName", "userText" - }; - if (f.m_chapterResetPage) -diff --git a/src/lib/EDocParser.cxx b/src/lib/EDocParser.cxx -index 318a48cd..147de249 100644 ---- a/src/lib/EDocParser.cxx -+++ b/src/lib/EDocParser.cxx -@@ -267,7 +267,7 @@ bool EDocParser::createZones() - #ifdef DEBUG_WITH_FILES - // get rid of the default application resource - libmwaw::DebugFile &ascFile = rsrcAscii(); -- static char const *appliRsrc[]= { -+ static char const* const appliRsrc[]= { - // default, Dialog (3000: DLOG,DITL,DLGX,dctb","ictb","STR ") - "ALRT","BNDL","CNTL","CURS","CDEF", "DLOG","DLGX","DITL","FREF","ICON", - "ICN#","MENU","SIZE","WIND", -diff --git a/src/lib/FullWrtGraph.cxx b/src/lib/FullWrtGraph.cxx -index 845554af..bf4c28cc 100644 ---- a/src/lib/FullWrtGraph.cxx -+++ b/src/lib/FullWrtGraph.cxx -@@ -320,7 +320,7 @@ std::shared_ptr FullWrtGraph::readSideBar(FullWrtStru - if (ok) continue; - MWAW_DEBUG_MSG(("FullWrtGraph::readSideBar: pb reading the zone %d\n", i)); - f.str(""); -- static char const *wh[]= {"position","format","unknown"}; -+ static char const* const wh[]= {"position","format","unknown"}; - f << "SideBar[" << wh[i] << ":###"; - asciiFile.addPos(pos); - asciiFile.addNote(f.str().c_str()); -diff --git a/src/lib/GreatWksDBParser.cxx b/src/lib/GreatWksDBParser.cxx -index 72c28078..19b653ad 100644 ---- a/src/lib/GreatWksDBParser.cxx -+++ b/src/lib/GreatWksDBParser.cxx -@@ -791,7 +791,7 @@ bool GreatWksDBParser::readHeader() - ascii().addNote(f.str().c_str()); - return false; - } -- static char const *wh[]= {"Free", "RecLink", "Block2"}; -+ static char const* const wh[]= {"Free", "RecLink", "Block2"}; - block.m_name=wh[i]; - m_state->m_blocks.push_back(block); - f << block << ","; -@@ -1194,7 +1194,7 @@ bool GreatWksDBParser::checkSmallZone(MWAWEntry &entry) - its length will be underestimate */ - entry.setLength(6+long(input->readULong(4))); - if (id>=0 && id<15) { -- static char const *names[]= { -+ static char const* const names[]= { - "Zone0A", "Field", "FrmLink", "Zone3A", "Zone4A", "ListFrmula", "ListSummary", "Zone7A", - "Zone8A", "Form", "FldLink", "Zone11A", "Zone12A", "FldAuxi", "Zone14A" - }; -@@ -1610,7 +1610,7 @@ bool GreatWksDBParser::readFields(MWAWEntry const &entry) - if (val!=0x10a) f << "fl=" << std::hex << val << std::dec << ","; - field.m_summaryType=static_cast(input->readULong(2)); - if (field.m_summaryType > 0 && field.m_summaryType < 6) { -- static char const *wh[] = { "", "average", "count", "total", "minimum", "maximum" }; -+ static char const* const wh[] = { "", "average", "count", "total", "minimum", "maximum" }; - f << wh[field.m_summaryType] << ","; - } - else -diff --git a/src/lib/GreatWksDocument.cxx b/src/lib/GreatWksDocument.cxx -index 06a0fdb8..e3b5c7fc 100644 ---- a/src/lib/GreatWksDocument.cxx -+++ b/src/lib/GreatWksDocument.cxx -@@ -703,7 +703,7 @@ bool GreatWksDocument::readFormula(MWAWVec2i const &cPos, long endPos, std::vect - arity= static_cast(input->readULong(1)); - instr.m_type=MWAWCellContent::FormulaInstruction::F_Function; - -- static char const *s_functions[] = { -+ static char const* const s_functions[] = { - "", "Abs", "Exp", "Fact", "Int", "Ln", "Log", "Log10", - "Mod", "Pi", "Product", "Rand", "Round", "Sign", "Sqrt", "Trunc", - -diff --git a/src/lib/GreatWksGraph.cxx b/src/lib/GreatWksGraph.cxx -index b670c5ae..8dc2e50b 100644 ---- a/src/lib/GreatWksGraph.cxx -+++ b/src/lib/GreatWksGraph.cxx -@@ -1212,7 +1212,7 @@ bool GreatWksGraph::readPageFrames() - f << "page=" << pageZone.m_page << ","; - endPos=pos+6+long(input->readULong(4)); - } -- static char const *wh[]= {"head", "gstyle", "root", "unknown"}; -+ static char const* const wh[]= {"head", "gstyle", "root", "unknown"}; - long zoneSz[4]= {0,0,0,0}; - for (int i=0; i < nZones; ++i) { - zoneSz[i] = long(input->readULong(4)); -diff --git a/src/lib/GreatWksParser.cxx b/src/lib/GreatWksParser.cxx -index 8ed0fec4..57fd42ad 100644 ---- a/src/lib/GreatWksParser.cxx -+++ b/src/lib/GreatWksParser.cxx -@@ -384,7 +384,7 @@ bool GreatWksParser::readDocInfo() - f << "Entries(DocInfo):"; - int val; - for (int i=0; i < 4; ++i) { -- static char const *wh[]= {"fl0", "fl1", "smartquote","hidepict"}; -+ static char const* const wh[]= {"fl0", "fl1", "smartquote","hidepict"}; - val =static_cast(input->readLong(1)); - if (!val) continue; - if (val==1) f << wh[i] << ","; -@@ -408,7 +408,7 @@ bool GreatWksParser::readDocInfo() - for (int i=0; i < 4; ++i) { - val=static_cast(input->readLong(1)); - if (!val) continue; -- static char const *wh[]= {"titlePage", "left/rightPage", "header","footer"}; -+ static char const* const wh[]= {"titlePage", "left/rightPage", "header","footer"}; - if (val!=1) { - f << "#" << wh[i] << "=" << val << ","; - continue; -@@ -437,7 +437,7 @@ bool GreatWksParser::readDocInfo() - pos = input->tell(); - f.str(""); - if (i<4) { -- static char const *wh[]= {"margins", "header/footer", "1", "pageDim" }; -+ static char const* const wh[]= {"margins", "header/footer", "1", "pageDim" }; - f << "DocInfo[" << wh[i] << "]:"; - } - else -diff --git a/src/lib/GreatWksSSParser.cxx b/src/lib/GreatWksSSParser.cxx -index 158a8a45..972252f4 100644 ---- a/src/lib/GreatWksSSParser.cxx -+++ b/src/lib/GreatWksSSParser.cxx -@@ -429,7 +429,7 @@ bool GreatWksSSParser::readSpreadsheet() - f << "Entries(Zone10):"; - } - else if (type>=0 && type < 0x1a) { -- static char const *wh[0x1a] = { -+ static char const* const wh[0x1a] = { - "_", "FontNames", "Style", "Column", "Column", "Row", "Zone6", "Row", - "Column", "Zone9", "Zonea", "Zoneb", "Row", "Screen", "DocOptions", "Selection", - "DocInfo", "CalcMode", "Zone12", "Zone13", "Zone14", "GridOptions", "DocInfo", "Header", -@@ -579,7 +579,7 @@ bool GreatWksSSParser::readSpreadsheet() - val=static_cast(input->readULong(1)); - if (!val) continue; - // checkme: same value in v2 ? -- static char const *what[]= {"grid[display]", "headerRC[display]", "zero[doc]", "formula[doc]", "grid[print]", "headerRC[print]", "header[print]", "footer[print]", "protected" }; -+ static char const* const what[]= {"grid[display]", "headerRC[display]", "zero[doc]", "formula[doc]", "grid[print]", "headerRC[print]", "header[print]", "footer[print]", "protected" }; - if (val==1) { - if (i==6) - m_state->m_headerPrint=true; -@@ -936,7 +936,7 @@ bool GreatWksSSParser::readCell(GreatWksSSParserInternal::Cell &cell) - case 16: - case 17: - case 18: { -- static char const *wh[] = { -+ static char const* const wh[] = { - "%m/%d/%y", "%b %d, %Y", "%b %Y", "%b %d", "%B %d, %Y", "%B %Y", "%B %d", "%a, %b %d, %Y", "%A, %B %d, %Y" - }; - format.m_format=MWAWCell::F_DATE; -@@ -948,7 +948,7 @@ bool GreatWksSSParser::readCell(GreatWksSSParserInternal::Cell &cell) - case 21: - case 22: - case 23: { -- static char const *wh[] = { -+ static char const* const wh[] = { - "%H:%M", "%H:%M:%S", "%I:%M %p", "%I:%M:%S %p" - }; - format.m_format=MWAWCell::F_TIME; -diff --git a/src/lib/HanMacWrdJGraph.cxx b/src/lib/HanMacWrdJGraph.cxx -index 8905ff66..78014e4b 100644 ---- a/src/lib/HanMacWrdJGraph.cxx -+++ b/src/lib/HanMacWrdJGraph.cxx -@@ -1951,7 +1951,7 @@ bool HanMacWrdJGraph::readTableFormatsList(HanMacWrdJGraphInternal::Table &table - - int color, pattern; - format.m_borders.resize(4); -- static char const *what[] = {"T", "L", "B", "R"}; -+ static char const* const what[] = {"T", "L", "B", "R"}; - static size_t const which[] = { libmwaw::Top, libmwaw::Left, libmwaw::Bottom, libmwaw::Right }; - for (int b=0; b < 4; b++) { - f2.str(""); -diff --git a/src/lib/HanMacWrdJParser.cxx b/src/lib/HanMacWrdJParser.cxx -index 157c6c93..e2c70acd 100644 ---- a/src/lib/HanMacWrdJParser.cxx -+++ b/src/lib/HanMacWrdJParser.cxx -@@ -438,7 +438,7 @@ bool HanMacWrdJParser::checkEntry(MWAWEntry &entry) - entry.setLength(length); - - if (type>=0 && type <= 15) { -- static char const *what[] = { -+ static char const* const what[] = { - "FontDef", "Ruler", "Style", "FrameDef", "TZoneList", - "TextZone", "Picture", "Table", "GraphData", "GroupData", - "ZoneA", "ZoneB", "Section", "FtnDef", "ZoneE", "FontsName" -diff --git a/src/lib/HanMacWrdKGraph.cxx b/src/lib/HanMacWrdKGraph.cxx -index ae92a52f..4948ded9 100644 ---- a/src/lib/HanMacWrdKGraph.cxx -+++ b/src/lib/HanMacWrdKGraph.cxx -@@ -1919,7 +1919,7 @@ std::shared_ptr HanMacWrdKGraph::readTable(std:: - val = input->readLong(2); - if (val) f << "f2=" << val << ","; - -- static char const *what[] = {"T", "L", "B", "R"}; -+ static char const* const what[] = {"T", "L", "B", "R"}; - static int const which[] = { libmwaw::TopBit, libmwaw::LeftBit, libmwaw::BottomBit, libmwaw::RightBit }; - for (int b = 0; b < 4; ++b) { // find _,4000,_,_,1,_, and 1,_,_,_,1,_, - f2.str(""); -diff --git a/src/lib/MWAWCell.cxx b/src/lib/MWAWCell.cxx -index 2fe054b2..1c490ab8 100644 ---- a/src/lib/MWAWCell.cxx -+++ b/src/lib/MWAWCell.cxx -@@ -458,7 +458,7 @@ std::ostream &operator<<(std::ostream &o, MWAWCell const &cell) - continue; - o << "bord"; - if (i < 6) { -- static char const *wh[] = { "L", "R", "T", "B", "MiddleH", "MiddleV" }; -+ static char const* const wh[] = { "L", "R", "T", "B", "MiddleH", "MiddleV" }; - o << wh[i]; - } - else o << "[#wh=" << i << "]"; -diff --git a/src/lib/MWAWGraphicStyle.cxx b/src/lib/MWAWGraphicStyle.cxx -index 5ba36268..1c2f83eb 100644 ---- a/src/lib/MWAWGraphicStyle.cxx -+++ b/src/lib/MWAWGraphicStyle.cxx -@@ -648,7 +648,7 @@ std::ostream &operator<<(std::ostream &o, MWAWGraphicStyle const &st) - continue; - o << "bord"; - if (i < 4) { -- static char const *wh[] = { "L", "R", "T", "B"}; -+ static char const* const wh[] = { "L", "R", "T", "B"}; - o << wh[i]; - } - else o << "[#wh=" << i << "]"; -diff --git a/src/lib/MWAWInputStream.cxx b/src/lib/MWAWInputStream.cxx -index dda89e19..eec2c8cd 100644 ---- a/src/lib/MWAWInputStream.cxx -+++ b/src/lib/MWAWInputStream.cxx -@@ -744,7 +744,7 @@ bool MWAWInputStream::unMacMIME(MWAWInputStream *inp, - return false; - } - #ifdef DEBUG -- static const char *what[] = { -+ static const char* const what[] = { - "", "Data", "Rsrc", "FileName", "Comment", "IconBW", "IconColor", "", - "FileDates", "FinderInfo", "MacInfo", "ProDosInfo", - "MSDosInfo", "AFPName", "AFPInfo", "AFPDirId" -diff --git a/src/lib/MWAWOLEParser.cxx b/src/lib/MWAWOLEParser.cxx -index 4894d74f..1c2460a0 100644 ---- a/src/lib/MWAWOLEParser.cxx -+++ b/src/lib/MWAWOLEParser.cxx -@@ -897,7 +897,7 @@ bool MWAWOLEParser::readSummaryInformation(MWAWInputStreamPtr input, std::string - else if (sect==0 && type==0x1e && !isDoc && ((it->second>=2 && it->second<=6) || it->second==8)) { - librevenge::RVNGString text; - if (readSummaryPropertyString(input, sEndPos, type, text, f) && !text.empty()) { -- static char const *attribNames[] = { -+ static char const* const attribNames[] = { - "", "", "dc:title", "dc:subject", "meta:initial-creator", - "meta:keywords", "dc:description"/*comment*/, "", "dc:creator" - }; -diff --git a/src/lib/MWAWParagraph.cxx b/src/lib/MWAWParagraph.cxx -index 243f1e2b..6676830c 100644 ---- a/src/lib/MWAWParagraph.cxx -+++ b/src/lib/MWAWParagraph.cxx -@@ -521,7 +521,7 @@ std::ostream &operator<<(std::ostream &o, MWAWParagraph const &pp) - continue; - o << "bord"; - if (i < 6) { -- static char const *wh[] = { "L", "R", "T", "B", "MiddleH", "MiddleV" }; -+ static char const* const wh[] = { "L", "R", "T", "B", "MiddleH", "MiddleV" }; - o << wh[i]; - } - else o << "[#wh=" << i << "]"; -diff --git a/src/lib/MWAWPictMac.cxx b/src/lib/MWAWPictMac.cxx -index 56130ae5..31f119f0 100644 ---- a/src/lib/MWAWPictMac.cxx -+++ b/src/lib/MWAWPictMac.cxx -@@ -293,7 +293,7 @@ struct Bitmap { - if (f.m_region.get()) o << ", " << *f.m_region; - - if (f.m_mode >= 0 && f.m_mode < 16) { -- static char const *mode0[] = { // 0-15 -+ static char const* const mode0[] = { // 0-15 - "srcCopy", "srcOr", "srcXOr", "srcBic", - "notSrcCopy", "notSrcOr", "notSrcXOr", "notSrcBic", - "patCopy", "patOr", "patXOr", "patBic", -@@ -302,7 +302,7 @@ struct Bitmap { - o << ", " << mode0[f.m_mode] << ", [...]"; - } - else if (f.m_mode >= 32 && f.m_mode < 40) { -- static char const *mode1[] = { // 32-39 -+ static char const* const mode1[] = { // 32-39 - "blend", "addPin", "addOver", "subPin", - "transparent", "addMax", "subOver", "addMin" - }; -diff --git a/src/lib/MWAWSection.cxx b/src/lib/MWAWSection.cxx -index c6003d83..24ebf6fd 100644 ---- a/src/lib/MWAWSection.cxx -+++ b/src/lib/MWAWSection.cxx -@@ -44,7 +44,7 @@ - std::ostream &operator<<(std::ostream &o, MWAWSection::Column const &col) - { - if (col.m_width > 0) o << "w=" << col.m_width << ","; -- static char const *wh[4]= {"L", "R", "T", "B"}; -+ static char const* const wh[4]= {"L", "R", "T", "B"}; - for (int i = 0; i < 4; i++) { - if (col.m_margins[i]>0) - o << "col" << wh[i] << "=" << col.m_margins[i] << ","; -diff --git a/src/lib/MacDocParser.cxx b/src/lib/MacDocParser.cxx -index 56554160..08be7101 100644 ---- a/src/lib/MacDocParser.cxx -+++ b/src/lib/MacDocParser.cxx -@@ -303,7 +303,7 @@ bool MacDocParser::createZones() - - // get rid of the default application resource - libmwaw::DebugFile &ascFile = rsrcAscii(); -- static char const *appliRsrc[]= { -+ static char const* const appliRsrc[]= { - "ALRT","BNDL","CNTL","CURS","CDEF", "CODE","DLOG","DLGX","DITL","FREF", - "ICON","ICN#","MENU","MBAR","MDEF", "SIZE","TMPL","WIND", - "acur","cicn","crsr","dctb","icl4", "icl8","ics4","ics8","ics#","ictb", -diff --git a/src/lib/MacDrawProParser.cxx b/src/lib/MacDrawProParser.cxx -index 37d55b1f..64c626c8 100644 ---- a/src/lib/MacDrawProParser.cxx -+++ b/src/lib/MacDrawProParser.cxx -@@ -1388,7 +1388,7 @@ int MacDrawProParser::readObject() - } - // reads the pattern - int patId[2]= {0,0}; -- static char const *wh[]= {"line", "surf"}; -+ static char const* const wh[]= {"line", "surf"}; - for (int i=0; i<2; ++i) { - val=static_cast(input->readULong(2)); - if (vers>0) { -diff --git a/src/lib/MacWrtProStructures.cxx b/src/lib/MacWrtProStructures.cxx -index 2bbed648..9da5b53b 100644 ---- a/src/lib/MacWrtProStructures.cxx -+++ b/src/lib/MacWrtProStructures.cxx -@@ -195,7 +195,7 @@ struct Graphic { - } - if (bl.m_id >= 0) o << "id=" << bl.m_id << ","; - o << "box=" << bl.m_box << ","; -- static char const *wh[] = { "L", "R", "T", "B" }; -+ static char const* const wh[] = { "L", "R", "T", "B" }; - if (bl.hasSameBorders()) { - if (bl.m_borderWList[0] > 0) - o << "bord[width]=" << bl.m_borderWList[0] << ","; -diff --git a/src/lib/MarinerWrtText.cxx b/src/lib/MarinerWrtText.cxx -index 12b64195..d47024f8 100644 ---- a/src/lib/MarinerWrtText.cxx -+++ b/src/lib/MarinerWrtText.cxx -@@ -300,7 +300,7 @@ std::ostream &operator<<(std::ostream &o, Paragraph::BorderFill const &fill) - if (fill.m_patternId) o << "patId=" << fill.m_patternId << ","; - o << "],"; - } -- static char const *wh[] = {"bordL", "bordT", "bordR", "bordB" }; -+ static char const* const wh[] = {"bordL", "bordT", "bordR", "bordB" }; - if (!fill.m_borderColor.isBlack() && fill.hasBorders()) - o << "borderColor=" << fill.m_borderColor << ","; - for (int i = 0; i < 4; i++) { -diff --git a/src/lib/MoreParser.cxx b/src/lib/MoreParser.cxx -index 64e25d38..76cfdf57 100644 ---- a/src/lib/MoreParser.cxx -+++ b/src/lib/MoreParser.cxx -@@ -405,7 +405,7 @@ bool MoreParser::readZonesList() - MWAWEntry entry; - entry.setBegin(long(input->readULong(4))); - entry.setLength(long(input->readULong(4))); -- static char const *names[]= { -+ static char const* const names[]= { - "PrintInfo", "DocInfo", "Unknown2", "Topic", - "Comment", "Slide", "Outline", "FreePos", "SpeakerNote" - }; -@@ -423,7 +423,7 @@ bool MoreParser::readZonesList() - if (unkn) f << "unkn=" << unkn << ","; - /* checkme: another list begins here, but I am not sure of its length :-~ */ - for (int i=0; i < 5; i++) { -- static char const *names[]= -+ static char const* const names[]= - { "Unknown9", "Fonts", "UnknownB","UnknownC", "UnknownD" }; - MWAWEntry entry; - entry.setBegin(long(input->readULong(4))); -diff --git a/src/lib/MsWksDBParser.cxx b/src/lib/MsWksDBParser.cxx -index 4d07b085..5a635272 100644 ---- a/src/lib/MsWksDBParser.cxx -+++ b/src/lib/MsWksDBParser.cxx -@@ -1617,7 +1617,7 @@ bool MsWksDBParser::readFieldTypes() - format.m_format=MWAWCell::F_DATE; - content.m_contentType=MWAWCellContent::C_NUMBER; - if (subformat>=0 && subformat < 5) { // checkme -- static char const *wh[]= {"%m/%d/%y", "%b %d, %Y", "%b, %d", "%b, %Y", "%a, %d %b, %Y" }; -+ static char const* const wh[]= {"%m/%d/%y", "%b %d, %Y", "%b, %d", "%b, %Y", "%a, %d %b, %Y" }; - format.m_DTFormat=wh[subformat]; - subformat=0; - } -@@ -1626,7 +1626,7 @@ bool MsWksDBParser::readFieldTypes() - format.m_format=MWAWCell::F_TIME; - content.m_contentType=MWAWCellContent::C_NUMBER; - if (subformat >= 0 && subformat < 4) { // checkme -- static char const *wh[]= {"%I:%M:%S %p", "%I:%M %p", "%H:%M:%S", "%H:%M"}; -+ static char const* const wh[]= {"%I:%M:%S %p", "%I:%M %p", "%H:%M:%S", "%H:%M"}; - format.m_DTFormat=wh[subformat]; - subformat=0; - } -@@ -1813,7 +1813,7 @@ bool MsWksDBParser::readFieldTypesV2() - break; - case 6: { - format.m_format=MWAWCell::F_DATE; -- static char const *wh[]= {"%B %d, %Y", "%b %d, %Y", "%A, %d %B, %Y", "%a, %d %b, %Y" }; -+ static char const* const wh[]= {"%B %d, %Y", "%b %d, %Y", "%A, %d %B, %Y", "%a, %d %b, %Y" }; - format.m_DTFormat=wh[((what>>5)&3)]; - what &= 0x9F; - break; -diff --git a/src/lib/MsWksDocument.cxx b/src/lib/MsWksDocument.cxx -index 99b76f93..4c0ac464 100644 ---- a/src/lib/MsWksDocument.cxx -+++ b/src/lib/MsWksDocument.cxx -@@ -1273,7 +1273,7 @@ bool MsWksDocument::readFormula(long endPos, MWAWCellContent &content, std::stri - case 0x2: - case 0x4: - case 0x6: { -- static char const *wh[]= {"+","-","*","/"}; -+ static char const* const wh[]= {"+","-","*","/"}; - instr.m_type=MWAWCellContent::FormulaInstruction::F_Operator; - instr.m_content=wh[code/2]; - break; -@@ -1299,7 +1299,7 @@ bool MsWksDocument::readFormula(long endPos, MWAWCellContent &content, std::stri - } - case 0x0c: { // function - auto v = static_cast(input->readULong(1)); -- static char const *(listFunc) [0x41] = { -+ static char const* const listFunc [0x41] = { - "Abs", "Sum", "Na", "Error", "ACos", "And", "ASin", "ATan", - "ATan2", "Average", "Choose", "Cos", "Count", "Exp", "False", "FV", - "HLookup", "If", "Index", "Int", "IRR", "IsBlank", "IsError", "IsNa", -@@ -1343,7 +1343,7 @@ bool MsWksDocument::readFormula(long endPos, MWAWCellContent &content, std::stri - break; - default: - if ((code%2)==0 && code>=0x10 && code<=0x22) { -- static char const *wh[]= {"(", ")", ";", "end", "<", ">", "=", "<=", ">=", "<>" }; -+ static char const* const wh[]= {"(", ")", ";", "end", "<", ">", "=", "<=", ">=", "<>" }; - instr.m_type=MWAWCellContent::FormulaInstruction::F_Operator; - instr.m_content=wh[(code-0x10)/2]; - break; -diff --git a/src/lib/MsWksSSParser.cxx b/src/lib/MsWksSSParser.cxx -index 79bed425..faa4cef5 100644 ---- a/src/lib/MsWksSSParser.cxx -+++ b/src/lib/MsWksSSParser.cxx -@@ -1025,7 +1025,7 @@ bool MsWksSSParser::readCell(int sz, MWAWVec2i const &cellPos, MsWksSSParserInte - break; - case MWAWCell::F_TIME: - if (subformat >= 0 && subformat < 4) { -- static char const *wh[]= {"%I:%M:%S %p", "%I:%M %p", "%H:%M:%S", "%H:%M"}; -+ static char const* const wh[]= {"%I:%M:%S %p", "%I:%M %p", "%H:%M:%S", "%H:%M"}; - format.m_DTFormat=wh[subformat]; - } - else -@@ -1038,7 +1038,7 @@ bool MsWksSSParser::readCell(int sz, MWAWVec2i const &cellPos, MsWksSSParserInte - case 6: - case 7: - case 8: { -- static char const *wh[]= {"%m/%d/%y", "%b %d, %Y", "%b, %d", "%b, %Y", "%a, %d %b, %Y" }; -+ static char const* const wh[]= {"%m/%d/%y", "%b %d, %Y", "%b, %d", "%b, %Y", "%a, %d %b, %Y" }; - format.m_DTFormat=wh[subformat-4]; - break; - } -diff --git a/src/lib/MultiplanParser.cxx b/src/lib/MultiplanParser.cxx -index a445722d..a11dc6f8 100644 ---- a/src/lib/MultiplanParser.cxx -+++ b/src/lib/MultiplanParser.cxx -@@ -1042,7 +1042,7 @@ static Functions const s_listOperators[] = { - { "", -2}, { "", -2}, { "", -2}, { "", -2}, - }; - --static char const *s_listFunctions[]= { -+static char const* const s_listFunctions[]= { - // 0 - "Count", "If", "IsNA", "IsError", - "Sum", "Average", "Min", "Max", -diff --git a/src/lib/NisusWrtParser.cxx b/src/lib/NisusWrtParser.cxx -index e7ec48bb..078b3500 100644 ---- a/src/lib/NisusWrtParser.cxx -+++ b/src/lib/NisusWrtParser.cxx -@@ -227,15 +227,15 @@ std::ostream &operator<<(std::ostream &o, Variable const &num) - if (num.m_startNumber != 1) o << "start=" << num.m_startNumber << ","; - if (num.m_increment != 1) o << "increment=" << num.m_increment << ","; - if (num.m_prefix.length()) { -- static char const *wh0[] = { "unkn0", "prefix", "name", "comments" }; -+ static char const* const wh0[] = { "unkn0", "prefix", "name", "comments" }; - o << wh0[num.m_containerType] << "=\"" << num.m_prefix << "\","; - } - if (num.m_suffix.length()) { -- static char const *wh2[] = { "unkn2", "suffix", "suffix", "unkn2" }; -+ static char const* const wh2[] = { "unkn2", "suffix", "suffix", "unkn2" }; - o << wh2[num.m_containerType] << "=\"" << num.m_suffix << "\","; - } - if (num.m_sample.length()) { -- static char const *wh1[] = { "unkn1", "sample", "sample", "author?" }; -+ static char const* const wh1[] = { "unkn1", "sample", "sample", "author?" }; - o << wh1[num.m_containerType] << "=\"" << num.m_sample << "\","; - } - if (num.m_dateFormat) { -@@ -1052,9 +1052,9 @@ bool NisusWrtParser::readVariable(NisusWrtStruct::RecursifData const &data) - std::string text(""); - for (int i = 0; i < mSz; i++) - text+= char(input->readULong(1)); -- static char const *wh0[] = { "unkn0", "prefix", "name", "comments" }; -- static char const *wh1[] = { "unkn1", "sample", "sample", "author?" }; -- static char const *wh2[] = { "unkn2", "suffix", "suffix", "unkn2" }; -+ static char const* const wh0[] = { "unkn0", "prefix", "name", "comments" }; -+ static char const* const wh1[] = { "unkn1", "sample", "sample", "author?" }; -+ static char const* const wh2[] = { "unkn2", "suffix", "suffix", "unkn2" }; - switch (id) { - case 2: - num.m_prefix = text; -diff --git a/src/lib/PixelPaintParser.cxx b/src/lib/PixelPaintParser.cxx -index 1bb976d2..5a9837fe 100644 ---- a/src/lib/PixelPaintParser.cxx -+++ b/src/lib/PixelPaintParser.cxx -@@ -325,7 +325,7 @@ bool PixelPaintParser::readFileHeaderV1(bool onlyCheck) - for (int i=0; i<6; ++i) { - val=static_cast(input->readULong(1)); - if (!val) continue; -- static char const *wh[]= {"setForAllTools", "noFullScreen[zoom]","fl2","autoscroll[fatbits]","center[createObject]","remap[color]"}; -+ static char const* const wh[]= {"setForAllTools", "noFullScreen[zoom]","fl2","autoscroll[fatbits]","center[createObject]","remap[color]"}; - f << wh[i]; - if (val!=1) - f << "=" << val; -diff --git a/src/lib/RagTime5ClusterManager.cxx b/src/lib/RagTime5ClusterManager.cxx -index ca22ef57..f53f47f3 100644 ---- a/src/lib/RagTime5ClusterManager.cxx -+++ b/src/lib/RagTime5ClusterManager.cxx -@@ -1427,7 +1427,7 @@ protected: - for (size_t i=0; i<4; ++i) { - if (listIds[i]==0) continue; - m_cluster->m_styleClusterIds[i]=listIds[i]; -- static char const *wh[]= { "graph", "units", "units2", "text" }; -+ static char const* const wh[]= { "graph", "units", "units2", "text" }; - f << wh[i] << "Style=data" << listIds[i] << "A,"; - } - } -@@ -1447,7 +1447,7 @@ protected: - for (size_t i=0; i<3; ++i) { - if (listIds[i]==0) continue; - m_cluster->m_styleClusterIds[i+4]=listIds[i]; -- static char const *wh[]= { "format", "#unk", "graphColor" }; -+ static char const* const wh[]= { "format", "#unk", "graphColor" }; - f << wh[i] << "Style=data" << listIds[i] << "A,"; - } - } -diff --git a/src/lib/RagTime5Formula.cxx b/src/lib/RagTime5Formula.cxx -index 04a59c82..86ff7111 100644 ---- a/src/lib/RagTime5Formula.cxx -+++ b/src/lib/RagTime5Formula.cxx -@@ -527,7 +527,7 @@ static Functions const s_listFunctions[] = { - - static size_t const s_numFunctions=MWAW_N_ELEMENTS(s_listFunctions); - --static char const *s_listFunctions2[] = { -+static char const* const s_listFunctions2[] = { - "^", "*", "/", nullptr, "+", "-", "&", "&", /*concat+space*/ // 80-9c - "=", "!=", ">", "<", ">=", "<=", "AND", "OR", // a0-bc - "NOT" // c0 -diff --git a/src/lib/RagTime5Spreadsheet.cxx b/src/lib/RagTime5Spreadsheet.cxx -index 7895ce14..65be8b84 100644 ---- a/src/lib/RagTime5Spreadsheet.cxx -+++ b/src/lib/RagTime5Spreadsheet.cxx -@@ -216,7 +216,7 @@ struct CellContent { - o << "["; - for (int i=0; i<8; ++i) { - if (cell.m_id[i]<0) continue; -- static char const *wh[]= {"V", "U", "G", "T", "bv", "BV", "bh", "BH"}; -+ static char const* const wh[]= {"V", "U", "G", "T", "bv", "BV", "bh", "BH"}; - o << wh[i] << cell.m_id[i] << ","; - } - o << "]"; -diff --git a/src/lib/RagTime5StyleManager.cxx b/src/lib/RagTime5StyleManager.cxx -index cc671d80..2cfe6c27 100644 ---- a/src/lib/RagTime5StyleManager.cxx -+++ b/src/lib/RagTime5StyleManager.cxx -@@ -2031,7 +2031,7 @@ bool RagTime5StyleManager::TextStyle::read(RagTime5StructManager::Field const &f - if (wh==2) - m_fontName=child.m_string; - else { -- static char const *what[]= {"[full]" /* unsure */, "[##UNDEF]", "", "[style]" /* regular, ...*/, "[from]", "[full2]"}; -+ static char const* const what[]= {"[full]" /* unsure */, "[##UNDEF]", "", "[style]" /* regular, ...*/, "[from]", "[full2]"}; - s << "font" << what[wh] << "=\"" << child.m_string.cstr() << "\","; - } - continue; -@@ -2372,7 +2372,7 @@ std::ostream &operator<<(std::ostream &o, RagTime5StyleManager::TextStyle const - } - for (int i=0; i<3; ++i) { - if (style.m_margins[i]<0) continue; -- static char const *wh[]= {"left", "right", "first"}; -+ static char const* const wh[]= {"left", "right", "first"}; - o << "margins[" << wh[i] << "]=" << style.m_margins[i] << ","; - } - for (int i=0; i<3; ++i) { -@@ -2457,7 +2457,7 @@ std::ostream &operator<<(std::ostream &o, RagTime5StyleManager::TextStyle const - - for (int i=0; i<4; ++i) { - if (style.m_letterSpacings[i]<=0&&style.m_letterSpacings[i]>=0) continue; -- static char const *wh[]= {"", "[optimal]", "[min]", "[max]"}; -+ static char const* const wh[]= {"", "[optimal]", "[min]", "[max]"}; - o << "letterSpacing" << wh[i] << "=" << style.m_letterSpacings[i] << ","; - } - if (style.m_widthStreching>=0) -diff --git a/src/lib/RagTimeParser.cxx b/src/lib/RagTimeParser.cxx -index 7c5b7c5d..35aa64f9 100644 ---- a/src/lib/RagTimeParser.cxx -+++ b/src/lib/RagTimeParser.cxx -@@ -260,7 +260,7 @@ std::ostream &operator<<(std::ostream &o, Zone const &z) - o << "ids=["; - for (int i=0; i<5; ++i) { - if (!z.m_linkZones[i]) continue; -- static char const *wh[]= {"parent", "prev", "next", "child", "linked"}; -+ static char const* const wh[]= {"parent", "prev", "next", "child", "linked"}; - o << wh[i] << "=Z" << z.m_linkZones[i] << ","; - } - o << "],"; -@@ -668,7 +668,7 @@ bool RagTimeParser::createZones() - BuGr : structure with many data of size 0x1a - Unamed: sometimes structured - */ -- static char const *what[]= { -+ static char const* const what[]= { - "rsrcgray", "rsrccolr", "rsrcres_", - "rsrcBuSl", "rsrcBuGr", "rsrcUnamed" - }; -@@ -970,7 +970,7 @@ bool RagTimeParser::readDataZoneHeader(int id, long endPos) - bool const isLine=zone.m_type==RagTimeParserInternal::Zone::Line; - int const numColorsInFile=isLine ? 1 : 2; - for (int i=0; i(input->readLong(1)); -diff --git a/src/lib/RagTimeSpreadsheet.cxx b/src/lib/RagTimeSpreadsheet.cxx -index 1fee0e66..e7810fb3 100644 ---- a/src/lib/RagTimeSpreadsheet.cxx -+++ b/src/lib/RagTimeSpreadsheet.cxx -@@ -2413,7 +2413,7 @@ bool RagTimeSpreadsheet::readSpreadsheetExtraV2(MWAWEntry &entry, RagTimeSpreads - for (int i=0; i<2; ++i) { - pos=input->tell(); - f.str(""); -- static char const *what[]= {"SpreadsheetRow", "SpreadsheetCol"}; -+ static char const* const what[]= {"SpreadsheetRow", "SpreadsheetCol"}; - f << "Entries(" << what[i] << "):"; - auto n=static_cast(input->readULong(2)); - f << "N=" << n << ","; -@@ -3026,7 +3026,7 @@ bool RagTimeSpreadsheet::readFormula(MWAWVec2i const &cellPos, std::vector(input->readULong(1)); - std::string funct(""); - if (val>=0 && val<0x60) { -- static char const *s_functions[] = { -+ static char const* const s_functions[] = { - // 0 - "Abs(", "Sign(", "Rand()", "Sqrt(", "Sum(", "SumSq(", "Max(", "Min(", - "Average(", "StDev(", "Pi()", "Sin(", "ASin(", "Cos(", "ACos(", "Tan(", -@@ -3089,7 +3089,7 @@ bool RagTimeSpreadsheet::readFormula(MWAWVec2i const &cellPos, std::vectorreadULong(2)); - -- static char const *wh[]= {"EndZone", "Text", nullptr, "Frame", "Solid", "Picture"}; -+ static char const* const wh[]= {"EndZone", "Text", nullptr, "Frame", "Solid", "Picture"}; - if (type<0 || type==2 || type>5) { - MWAW_DEBUG_MSG(("ReadySetGoGraph::readShapeV1: unknown type\n")); - return false; -@@ -1086,7 +1086,7 @@ bool ReadySetGoGraph::readShapeV3(ReadySetGoGraphInternal::Layout &layout, bool - ReadySetGoGraphInternal::Shape::T_Line, - ReadySetGoGraphInternal::Shape::T_Line - }; -- static char const *what[]= { "Rectangle", "RectOval", "Oval", "Picture", "Text", "Line" /* hv*/, "Line" /* not axis aligned*/}; -+ static char const* const what[]= { "Rectangle", "RectOval", "Oval", "Picture", "Text", "Line" /* hv*/, "Line" /* not axis aligned*/}; - f << "Entries(" << what[type] << "):"; - ReadySetGoGraphInternal::Shape shape(shapeTypes[type]); - f << "IDS=["; // next, prev -@@ -1515,7 +1515,7 @@ bool ReadySetGoGraph::readShapeV6(ReadySetGoGraphInternal::Layout &layout, bool - ReadySetGoGraphInternal::Shape::T_Line, - ReadySetGoGraphInternal::Shape::T_Polygon, - }; -- static char const *what[]= { "Rectangle", "RectOval", "Oval", "Picture", "Text", "Line" /* hv*/, "Line" /* not axis aligned*/, "Polygon" }; -+ static char const* const what[]= { "Rectangle", "RectOval", "Oval", "Picture", "Text", "Line" /* hv*/, "Line" /* not axis aligned*/, "Polygon" }; - f << "Entries(" << what[type] << "):"; - ReadySetGoGraphInternal::Shape shape(shapeTypes[type]); - f << "IDS=["; // next, prev -@@ -2109,7 +2109,7 @@ bool ReadySetGoGraph::readShapeDSV2(ReadySetGoGraphInternal::Layout &layout, boo - ReadySetGoGraphInternal::Shape::T_Polygon, - }; - // checkme can type=1 and type=6 exists -- static char const *what[]= { "Rectangle", "RectOval", "Oval", "Picture", "Text", "Line" /* hv*/, "Line" /* not axis aligned*/, "Polygon" }; -+ static char const* const what[]= { "Rectangle", "RectOval", "Oval", "Picture", "Text", "Line" /* hv*/, "Line" /* not axis aligned*/, "Polygon" }; - f << "Entries(" << what[type] << "):"; - ReadySetGoGraphInternal::Shape shape(shapeTypes[type]); - f << "IDS=["; // next, prev -diff --git a/src/lib/WingzGraph.cxx b/src/lib/WingzGraph.cxx -index 44b0acfd..c7835f48 100644 ---- a/src/lib/WingzGraph.cxx -+++ b/src/lib/WingzGraph.cxx -@@ -449,7 +449,7 @@ bool WingzGraph::readGraphic() - MWAW_DEBUG_MSG(("WingzGraph::readGraphic: find bad size for shape\n")); - return false; - } -- static char const *what[]= {"line", "arc", "circle", "rectangle", "poly" }; -+ static char const* const what[]= {"line", "arc", "circle", "rectangle", "poly" }; - f << what[type-5] << ","; - switch (type) { - case 5: { -diff --git a/src/lib/WingzParser.cxx b/src/lib/WingzParser.cxx -index 18d215ff..681307cc 100644 ---- a/src/lib/WingzParser.cxx -+++ b/src/lib/WingzParser.cxx -@@ -602,7 +602,7 @@ bool WingzParser::readSpreadsheet() - } - std::string name(""); - if (type<=0x10) { -- static char const *wh[]= { -+ static char const* const wh[]= { - "", "SheetSize", "SheetSize", "", "", "", "", "CellName", - "Formula", "Style", "SheetErr", "Sheet2Err", "", "SheetMcro", "Graphic", "", - "PrintInfo" -@@ -1514,7 +1514,7 @@ bool WingzParser::readFormula() - instr.m_doubleValue=value; - if (wh>=0x2a&&wh<=0x2d) { // mixed operator + number - stack.push_back(std::vector(1,instr)); -- static char const *what[]= {"+","-","*","/"}; -+ static char const* const what[]= {"+","-","*","/"}; - - instr=MWAWCellContent::FormulaInstruction(); - instr.m_type=MWAWCellContent::FormulaInstruction::F_Function; -diff --git a/src/lib/WriteNowText.cxx b/src/lib/WriteNowText.cxx -index dae61448..d2c701a6 100644 ---- a/src/lib/WriteNowText.cxx -+++ b/src/lib/WriteNowText.cxx -@@ -285,7 +285,7 @@ struct TableData { - if (!table.m_color.isWhite()) - o << "color=" << table.m_color << ","; - for (int i = 0; i < 4; i++) { -- static char const *wh[4]= {"T", "R", "B", "L"}; -+ static char const* const wh[4]= {"T", "R", "B", "L"}; - if (table.m_flags[i]&0xFF00) - o << "#bFlags" << wh[i] << "[high]=" << (table.m_flags[i]>>8) << ","; - // flags&0x80 : duplicated? -diff --git a/src/lib/libmwaw_internal.cxx b/src/lib/libmwaw_internal.cxx -index a9d89ed2..939f25d9 100644 ---- a/src/lib/libmwaw_internal.cxx -+++ b/src/lib/libmwaw_internal.cxx -@@ -148,10 +148,10 @@ std::string numberingValueToString(NumberingType type, int value) - return s; - case LOWERCASE_ROMAN: - case UPPERCASE_ROMAN: { -- static char const *romanS[] = {"M", "CM", "D", "CD", "C", "XC", "L", -+ static char const* const romanS[] = {"M", "CM", "D", "CD", "C", "XC", "L", - "XL", "X", "IX", "V", "IV", "I" - }; -- static char const *romans[] = {"m", "cm", "d", "cd", "c", "xc", "l", -+ static char const* const romans[] = {"m", "cm", "d", "cd", "c", "xc", "l", - "xl", "x", "ix", "v", "iv", "i" - }; - static int const romanV[] = {1000, 900, 500, 400, 100, 90, 50, -diff --git a/src/tools/zip/xattr.cpp b/src/tools/zip/xattr.cpp -index 4cf85bca..05eb2c55 100644 ---- a/src/tools/zip/xattr.cpp -+++ b/src/tools/zip/xattr.cpp -@@ -87,7 +87,7 @@ std::shared_ptr XAttr::getStream() const - # define MWAW_EXTENDED_FS - # endif - ssize_t sz[2]; -- static char const *attr[2] = { "com.apple.FinderInfo", "com.apple.ResourceFork" }; -+ static char const* const attr[2] = { "com.apple.FinderInfo", "com.apple.ResourceFork" }; - int find=0; - for (int i = 0; i < 2; i++) { - sz[i]=getxattr(m_fName.c_str(), attr[i], 0, 0 MWAW_EXTENDED_FS); --- -2.49.0 - diff --git a/external/libmwaw/ExternalProject_libmwaw.mk b/external/libmwaw/ExternalProject_libmwaw.mk index 7a67a067fa77..59075c7b9278 100644 --- a/external/libmwaw/ExternalProject_libmwaw.mk +++ b/external/libmwaw/ExternalProject_libmwaw.mk @@ -22,7 +22,7 @@ $(eval $(call gb_ExternalProject_use_externals,libmwaw,\ $(call gb_ExternalProject_get_state_target,libmwaw,build) : $(call gb_Trace_StartRange,libmwaw,EXTERNAL) $(call gb_ExternalProject_run,build,\ - export PKG_CONFIG="" \ + export PKG_CONFIG="true" \ && $(gb_RUN_CONFIGURE) ./configure \ --with-pic \ $(if $(DISABLE_DYNLOADING), \ diff --git a/external/libmwaw/UnpackedTarball_libmwaw.mk b/external/libmwaw/UnpackedTarball_libmwaw.mk index 7f13a5d80ff2..935cbc1eb1c3 100644 --- a/external/libmwaw/UnpackedTarball_libmwaw.mk +++ b/external/libmwaw/UnpackedTarball_libmwaw.mk @@ -23,14 +23,6 @@ $(eval $(call gb_UnpackedTarball_add_patches,libmwaw, \ endif endif -# external/libmwaw/0001-const-up-some-arrays.patch.1 -# upstreaming effort as: -# https://sourceforge.net/p/libmwaw/libmwaw/merge-requests/4/ - -$(eval $(call gb_UnpackedTarball_add_patches,libmwaw, \ - external/libmwaw/0001-const-up-some-arrays.patch.1 \ -)) - ifeq ($(SYSTEM_REVENGE),) $(eval $(call gb_UnpackedTarball_add_patches,libmwaw, \ external/libmwaw/rpath.patch \ diff --git a/external/libnumbertext/ExternalProject_libnumbertext.mk b/external/libnumbertext/ExternalProject_libnumbertext.mk index 71376be45dbd..e307a14387cd 100644 --- a/external/libnumbertext/ExternalProject_libnumbertext.mk +++ b/external/libnumbertext/ExternalProject_libnumbertext.mk @@ -24,7 +24,7 @@ $(call gb_ExternalProject_get_state_target,libnumbertext,build): $(call gb_Trace_StartRange,libnumbertext,EXTERNAL) $(call gb_ExternalProject_run,build,\ LIBS="$(gb_STDLIBS) $(LIBS)" \ - $(SHELL) $(gb_RUN_CONFIGURE) ./configure --disable-shared --with-pic \ + $(gb_RUN_CONFIGURE) ./configure --disable-shared --with-pic \ $(if $(verbose),--disable-silent-rules,--enable-silent-rules) \ $(if $(ENABLE_WERROR),--enable-werror,--disable-werror) \ $(gb_CONFIGURE_PLATFORMS) \ diff --git a/external/libodfgen/0001-Missing-include.patch.1 b/external/libodfgen/0001-Missing-include.patch.1 new file mode 100644 index 000000000000..7476d7095c1e --- /dev/null +++ b/external/libodfgen/0001-Missing-include.patch.1 @@ -0,0 +1,24 @@ +From 4da0b148def5b40ee60d4cd79762c0f158d64cc7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fridrich=20=C5=A0trba?= +Date: Fri, 16 Aug 2024 09:38:03 +0200 +Subject: [PATCH] Missing include + +--- + src/OdfGenerator.cxx | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/OdfGenerator.cxx b/src/OdfGenerator.cxx +index f29c480..07fd0bc 100644 +--- a/src/OdfGenerator.cxx ++++ b/src/OdfGenerator.cxx +@@ -33,6 +33,7 @@ + #include + + #include ++#include + #include + #include + #include +-- +2.47.3 + diff --git a/external/libodfgen/UnpackedTarball_libodfgen.mk b/external/libodfgen/UnpackedTarball_libodfgen.mk index 9be46b4cd823..cdc2effca69b 100644 --- a/external/libodfgen/UnpackedTarball_libodfgen.mk +++ b/external/libodfgen/UnpackedTarball_libodfgen.mk @@ -23,6 +23,7 @@ $(eval $(call gb_UnpackedTarball_update_autoconf_configs,libodfgen)) $(eval $(call gb_UnpackedTarball_add_patches,libodfgen, \ external/libodfgen/ellipticalarc.patch \ external/libodfgen/0001-const-up-libodfgen.patch.1 \ + external/libodfgen/0001-Missing-include.patch.1 \ )) ifeq ($(SYSTEM_REVENGE),) diff --git a/external/liborcus/ExternalProject_liborcus.mk b/external/liborcus/ExternalProject_liborcus.mk index 3fc01cbb448d..d6a955cc4fbf 100644 --- a/external/liborcus/ExternalProject_liborcus.mk +++ b/external/liborcus/ExternalProject_liborcus.mk @@ -101,6 +101,7 @@ $(call gb_ExternalProject_get_state_target,liborcus,build) : --without-doc-example \ --disable-python \ --disable-werror \ + $(if $(WITH_PARQUET_FILTER),--with-parquet-filter) \ $(if $(filter MACOSX,$(OS)),--prefix=/@.__________________________________________________OOO) \ $(if $(SYSTEM_BOOST),,\ --with-boost=$(WORKDIR)/UnpackedTarball/boost \ diff --git a/external/liborcus/UnpackedTarball_liborcus.mk b/external/liborcus/UnpackedTarball_liborcus.mk index 39e01c8d43cc..8183c8bb01a0 100644 --- a/external/liborcus/UnpackedTarball_liborcus.mk +++ b/external/liborcus/UnpackedTarball_liborcus.mk @@ -19,6 +19,12 @@ $(eval $(call gb_UnpackedTarball_add_patches,liborcus,\ external/liborcus/add-lt-operator.patch.1 \ )) +ifeq ($(WITH_PARQUET_FILTER),TRUE) +$(eval $(call gb_UnpackedTarball_add_patches,liborcus,\ + external/liborcus/arrow-23.diff \ +)) +endif + ifeq ($(OS),WNT) $(eval $(call gb_UnpackedTarball_add_patches,liborcus,\ external/liborcus/windows-constants-hack.patch \ diff --git a/external/liborcus/arrow-23.diff b/external/liborcus/arrow-23.diff new file mode 100644 index 000000000000..accb4099ae2b --- /dev/null +++ b/external/liborcus/arrow-23.diff @@ -0,0 +1,25 @@ +diff --git a/src/liborcus/orcus_parquet.cpp b/src/liborcus/orcus_parquet.cpp +index eb90ef970ed3d4f8a4a01596e9ace161f33c82f4..dcc10c14db21ded8915baf759684e3c3b4692c7d 100644 +--- a/src/liborcus/orcus_parquet.cpp ++++ b/src/liborcus/orcus_parquet.cpp +@@ -13,6 +13,7 @@ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wshadow" + #pragma GCC diagnostic ignored "-Wunused-parameter" ++#include + #include + #include + #include +@@ -346,9 +347,10 @@ class orcus_parquet::impl + + void read_stream_with_sheet_name(std::string_view sheet_name, std::string_view stream) + { +- auto buf = std::make_shared(stream); ++ auto buf = std::make_shared(stream); ++ auto buf_reader = std::make_shared(buf); + +- auto file_reader = parquet::ParquetFileReader::Open(buf); ++ auto file_reader = parquet::ParquetFileReader::Open(buf_reader); + if (!file_reader) + { + warn("failed to open a parquet file reader from an in-memory buffer."); diff --git a/external/libqxp/UnpackedTarball_libqxp.mk b/external/libqxp/UnpackedTarball_libqxp.mk index 54d3e36addd4..0d9a067282e1 100644 --- a/external/libqxp/UnpackedTarball_libqxp.mk +++ b/external/libqxp/UnpackedTarball_libqxp.mk @@ -17,7 +17,6 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,libqxp,0)) $(eval $(call gb_UnpackedTarball_add_patches,libqxp, \ external/libqxp/android-workaround.patch.1 \ - external/libqxp/ax_gcc_func_attribute.m4.patch \ )) # vim: set noet sw=4 ts=4: diff --git a/external/libqxp/ax_gcc_func_attribute.m4.patch b/external/libqxp/ax_gcc_func_attribute.m4.patch deleted file mode 100644 index 8f7457816efd..000000000000 --- a/external/libqxp/ax_gcc_func_attribute.m4.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- configure -+++ configure -@@ -18136,7 +18136,7 @@ - - _ACEOF - if ac_fn_cxx_try_link "$LINENO"; then : -- if test -s conftest.err; then : -+ if grep -- -Wattributes conftest.err; then : - ax_cv_have_func_attribute_visibility=no - else - ax_cv_have_func_attribute_visibility=yes diff --git a/external/librevenge/C2039-unique-shared_ptr.patch.0 b/external/librevenge/C2039-unique-shared_ptr.patch.0 deleted file mode 100644 index 0dcec5058e89..000000000000 --- a/external/librevenge/C2039-unique-shared_ptr.patch.0 +++ /dev/null @@ -1,11 +0,0 @@ ---- src/lib/RVNGBinaryData.cpp 2024-05-10 13:20:09.278288686 +0200 -+++ src/lib/RVNGBinaryData.cpp 2024-05-10 13:23:14.365139906 +0200 -@@ -93,7 +93,7 @@ - - void RVNGBinaryDataImpl::makeUnique() - { -- if (!m_ptr.unique()) -+ if (!(m_ptr.use_count() == 1)) - { - std::shared_ptr ptr(new DataImpl()); - ptr->m_buf = m_ptr->m_buf; diff --git a/external/librevenge/ExternalProject_librevenge.mk b/external/librevenge/ExternalProject_librevenge.mk index 4e64d5534b6b..98a2236bb376 100644 --- a/external/librevenge/ExternalProject_librevenge.mk +++ b/external/librevenge/ExternalProject_librevenge.mk @@ -22,8 +22,7 @@ $(eval $(call gb_ExternalProject_use_externals,librevenge,\ $(call gb_ExternalProject_get_state_target,librevenge,build) : $(call gb_Trace_StartRange,librevenge,EXTERNAL) $(call gb_ExternalProject_run,build,\ - export PKG_CONFIG="" \ - && $(gb_RUN_CONFIGURE) ./configure \ + $(gb_RUN_CONFIGURE) ./configure \ --with-pic \ $(if $(DISABLE_DYNLOADING), \ --disable-shared --enable-static, \ diff --git a/external/librevenge/UnpackedTarball_librevenge.mk b/external/librevenge/UnpackedTarball_librevenge.mk index 316e961bd1ba..74f28751c609 100644 --- a/external/librevenge/UnpackedTarball_librevenge.mk +++ b/external/librevenge/UnpackedTarball_librevenge.mk @@ -17,8 +17,6 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,librevenge,0)) $(eval $(call gb_UnpackedTarball_add_patches,librevenge, \ external/librevenge/rpath.patch \ - external/librevenge/tdf63130-improve-perf.patch.0 \ - external/librevenge/C2039-unique-shared_ptr.patch.0 \ )) ifneq ($(OS),MACOSX) diff --git a/external/librevenge/tdf63130-improve-perf.patch.0 b/external/librevenge/tdf63130-improve-perf.patch.0 deleted file mode 100644 index f8b972217c76..000000000000 --- a/external/librevenge/tdf63130-improve-perf.patch.0 +++ /dev/null @@ -1,80 +0,0 @@ ---- inc/librevenge/RVNGString.h 2023-05-17 15:48:15.373159469 +0200 -+++ inc/librevenge/RVNGString.h 2023-05-17 15:49:00.781411917 +0200 -@@ -22,6 +22,7 @@ - #define RVNGSTRING_H - - #include "librevenge-api.h" -+#include - - namespace librevenge - { -@@ -36,6 +37,7 @@ - RVNGString(); - RVNGString(const RVNGString &other); - RVNGString(const char *str); -+ RVNGString(std::string&&); - ~RVNGString(); - - /** Create a new string from \a s as escaped XML. ---- src/lib/RVNGBinaryData.cpp 2023-05-17 15:48:15.373159469 +0200 -+++ src/lib/RVNGBinaryData.cpp 2023-05-17 15:49:00.773411873 +0200 -@@ -68,9 +68,9 @@ - boost::archive::iterators::transform_width::const_iterator, 6, 8 > > base64_encoder; - - // Encode the buffer and create a string -- std::copy( -+ result.insert(result.begin(), - base64_encoder(source.begin()), -- base64_encoder(source.end()), std::back_inserter(result)); -+ base64_encoder(source.end())); - - result.append(numPadding, '='); // add '=' for each padded character - } -@@ -153,10 +153,10 @@ - { - m_binaryDataImpl->makeUnique(); - -- unsigned long previousSize = m_binaryDataImpl->m_ptr->m_buf.size(); -- m_binaryDataImpl->m_ptr->m_buf.reserve(previousSize + data.m_binaryDataImpl->m_ptr->m_buf.size()); -- const auto &src = data.m_binaryDataImpl->m_ptr->m_buf; -- std::copy(src.begin(), src.end(), std::back_inserter(m_binaryDataImpl->m_ptr->m_buf)); -+ m_binaryDataImpl->m_ptr->m_buf.insert( -+ m_binaryDataImpl->m_ptr->m_buf.end(), -+ data.m_binaryDataImpl->m_ptr->m_buf.begin(), -+ data.m_binaryDataImpl->m_ptr->m_buf.end()); - } - - void RVNGBinaryData::appendBase64Data(const RVNGString &base64) -@@ -234,8 +234,9 @@ - const RVNGString RVNGBinaryData::getBase64Data() const - { - std::string base64; -+ base64.reserve(m_binaryDataImpl->m_ptr->m_buf.size() / 4 * 3); - convertToBase64(base64, m_binaryDataImpl->m_ptr->m_buf); -- return RVNGString(base64.c_str()); -+ return RVNGString(std::move(base64)); - } - - RVNGInputStream *RVNGBinaryData::getDataStream() const ---- src/lib/RVNGString.cpp 2023-05-17 15:48:15.373159469 +0200 -+++ src/lib/RVNGString.cpp 2023-05-17 15:49:00.773411873 +0200 -@@ -76,6 +76,7 @@ - { - public: - RVNGStringImpl() : m_buf() {} -+ RVNGStringImpl(std::string&& str) : m_buf(std::move(str)) {} - bool empty() const - { - return m_buf.empty(); -@@ -200,6 +201,11 @@ - m_stringImpl->append(str); - } - -+RVNGString::RVNGString(std::string&& str) : -+ m_stringImpl(new RVNGStringImpl(std::move(str))) -+{ -+} -+ - RVNGString RVNGString::escapeXML(const RVNGString &s) - { - RVNGString escaped; diff --git a/external/libstaroffice/0001-const-up-these-arrays.patch.1 b/external/libstaroffice/0001-const-up-these-arrays.patch.1 deleted file mode 100644 index 5da9ce35c78e..000000000000 --- a/external/libstaroffice/0001-const-up-these-arrays.patch.1 +++ /dev/null @@ -1,264 +0,0 @@ -From 6fc47d83edee9e13e09a96b1e719c2bf8cadcb43 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Tue, 22 Jul 2025 19:54:24 +0100 -Subject: [PATCH] const up these arrays - -and move them out of the .data section ---- - src/lib/StarCellFormula.cxx | 8 ++++---- - src/lib/StarFileManager.cxx | 2 +- - src/lib/StarFormatManager.cxx | 2 +- - src/lib/StarItem.cxx | 2 +- - src/lib/StarObject.cxx | 6 +++--- - src/lib/StarObjectChart.cxx | 10 +++++----- - src/lib/StarObjectModel.cxx | 2 +- - src/lib/StarObjectNumericRuler.cxx | 2 +- - src/lib/StarObjectSpreadsheet.cxx | 8 ++++---- - src/lib/libstaroffice_internal.cxx | 4 ++-- - 10 files changed, 23 insertions(+), 23 deletions(-) - -diff --git a/src/lib/StarCellFormula.cxx b/src/lib/StarCellFormula.cxx -index b994e13..a8e3bfc 100644 ---- a/src/lib/StarCellFormula.cxx -+++ b/src/lib/StarCellFormula.cxx -@@ -216,7 +216,7 @@ bool Token::updateFunction() - instr.m_content=nOp==33 ? "and" : "or"; - } - else if (nOp>=21 && nOp<=37) { -- static char const *wh[]= -+ static char const* const wh[]= - {"+", "-", "*", "/", "&", "^", "=", "<>", "<", ">", "<=", ">=", "OR", "AND", "!", "~", ":"}; - m_content=StarCellFormulaInternal::Token::C_FunctionOperator; - m_longValue=2; -@@ -238,7 +238,7 @@ bool Token::updateFunction() - } - // function no parameter - else if (nOp>=46 && nOp<=53) { // 60 endNoPar -- static char const *wh[]= { -+ static char const* const wh[]= { - "Pi", "Random", "True", "False", "Today"/*getActDate*/, "Now"/*getActTime*/, - "NA", "Current" - }; -@@ -255,7 +255,7 @@ bool Token::updateFunction() - else if (nOp>=61 && nOp<=131) { // 200 endOnePar - m_content=StarCellFormulaInternal::Token::C_FunctionOperator; - m_longValue=1; -- static char const *wh[]= { -+ static char const* const wh[]= { - "Degrees", "Radians", "Sin", "Cos", "Tan", "Cot", "Asin", "Acos", "Atan", "ACot", // 70 - "SinH", "CosH", "TanH", "CotH", "AsinH", "ACosH", "ATanH", "ACosH", // 78 - "Exp", "Ln", "Sqrt", "Fact", // 82 -@@ -273,7 +273,7 @@ bool Token::updateFunction() - // multiple - else if (nOp>=201 && nOp<=386) { - m_content=StarCellFormulaInternal::Token::C_FunctionOperator; -- static char const *wh[]= { -+ static char const* const wh[]= { - "Atan2", "Ceil", "Floor", "Round", "RoundUp", "RoundDown", "Trunc", "Log", // 208 - "Power", "GCD", "LCM", "Mod", "SumProduct", "SumSQ", "SumX2MY2", "SumX2PY2", "SumXMY2", // 217 - "Date", "Time", "Days", "Days360", "Min", "Max", "Sum", "Product", "Average", "Count", // 227 -diff --git a/src/lib/StarFileManager.cxx b/src/lib/StarFileManager.cxx -index f0587a9..e9d9471 100644 ---- a/src/lib/StarFileManager.cxx -+++ b/src/lib/StarFileManager.cxx -@@ -886,7 +886,7 @@ bool StarFileManager::readJobSetUp(StarZone &zone, bool useJobLen) - name+=ch; - } - if (!name.empty()) { -- static char const *wh[]= { "printerName", "deviceName", "portName", "driverName" }; -+ static char const* const wh[]= { "printerName", "deviceName", "portName", "driverName" }; - f << wh[i] << "=" << name << ","; - } - input->seek(actPos+length, librevenge::RVNG_SEEK_SET); -diff --git a/src/lib/StarFormatManager.cxx b/src/lib/StarFormatManager.cxx -index b92bc41..6211406 100644 ---- a/src/lib/StarFormatManager.cxx -+++ b/src/lib/StarFormatManager.cxx -@@ -311,7 +311,7 @@ bool NumberFormatter::FormatItem::updateNumberingProperties(librevenge::RVNGProp - if (m_text.empty()) break; - auto fChar=int(m_text.cstr()[0]); - if (fChar>=32) { -- static int cCharWidths[ 128-32 ] = { -+ static const int cCharWidths[ 128-32 ] = { - 1,1,1,2,2,3,2,1,1,1,1,2,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,2, - 3,2,2,2,2,2,2,3,2,1,2,2,2,3,3,3, -diff --git a/src/lib/StarItem.cxx b/src/lib/StarItem.cxx -index 1dda45e..a48f5a1 100644 ---- a/src/lib/StarItem.cxx -+++ b/src/lib/StarItem.cxx -@@ -70,7 +70,7 @@ std::ostream &operator<<(std::ostream &o, StarItemStyle const &style) - { - for (int i=0; i<4; ++i) { - if (style.m_names[i].empty()) continue; -- static char const *wh[]= {"name","parent","follow","help"}; -+ static char const* const wh[]= {"name","parent","follow","help"}; - o << wh[i] << "=" << style.m_names[i].cstr() << ","; - } - switch (style.m_family&0xff) { -diff --git a/src/lib/StarObject.cxx b/src/lib/StarObject.cxx -index a915b79..3820686 100644 ---- a/src/lib/StarObject.cxx -+++ b/src/lib/StarObject.cxx -@@ -533,7 +533,7 @@ bool StarObject::readSfxDocumentInformation(STOFFInputStreamPtr input, std::stri - f << "SfxDocInfo-A" << i << ":"; - auto dSz=int(input->readULong(2)); - int expectedSz= i < 3 ? 33 : i < 5 ? 65 : i==5 ? 257 : i==6 ? 129 : i<15 ? 21 : 2; -- static char const *wh[]= { -+ static char const* const wh[]= { - "time[creation]","time[mod]","time[print]","title","subject","comment","keyword", - "user0[name]", "user0[data]","user1[name]", "user1[data]","user2[name]", "user2[data]","user3[name]", "user3[data]", - "template[name]", "template[filename]" -@@ -559,7 +559,7 @@ bool StarObject::readSfxDocumentInformation(STOFFInputStreamPtr input, std::stri - if (StarEncoding::convert(string, encoding, finalString, srcPositions)) { - auto attrib=libstoff::getString(finalString); - f << attrib.cstr() << ","; -- static char const *attribNames[] = { -+ static char const* const attribNames[] = { - "meta:initial-creator", "dc:creator", "", "dc:title", "dc:subject", "dc:description"/*comment*/, "meta:keywords", - "", "user", "", "user", "", "user", "", "user", - "librevenge:template-name", "librevenge:template-filename" -@@ -590,7 +590,7 @@ bool StarObject::readSfxDocumentInformation(STOFFInputStreamPtr input, std::stri - f << "date=" << date << ", time=" << time << ","; - std::string dateTime; - if (date && libstoff::convertToDateTime(date,time, dateTime)) { -- static char const *attribNames[]= { "meta:creation-date", "dc:date", "meta:print-date" }; -+ static char const* const attribNames[]= { "meta:creation-date", "dc:date", "meta:print-date" }; - m_metaData.insert(attribNames[i], dateTime.c_str()); - } - } -diff --git a/src/lib/StarObjectChart.cxx b/src/lib/StarObjectChart.cxx -index 9af3f8f..e26f35b 100644 ---- a/src/lib/StarObjectChart.cxx -+++ b/src/lib/StarObjectChart.cxx -@@ -496,7 +496,7 @@ bool StarObjectChart::readSCHAttributes(StarZone &zone) - zone.closeSCHHeader("SCHAttributes"); - return true; - } -- static char const *wh[]= {"mainTitle", "subTitle", "xAxisTitle", "yAxisTitle", "zAxisTitle" }; -+ static char const* const wh[]= {"mainTitle", "subTitle", "xAxisTitle", "yAxisTitle", "zAxisTitle" }; - f << wh[i] << "=" << libstoff::getString(string).cstr(); - if (bShow) f << ":show"; - f << ","; -@@ -506,7 +506,7 @@ bool StarObjectChart::readSCHAttributes(StarZone &zone) - bool bShow; - *input>>bShow; - if (!bShow) continue; -- static char const *wh[]= {"Axis", "GridMain", "GridHelp", "Descr"}; -+ static char const* const wh[]= {"Axis", "GridMain", "GridHelp", "Descr"}; - f << "show" << char('X'+i) << wh[j] << ","; - } - } -@@ -772,7 +772,7 @@ bool StarObjectChart::readSCHAttributes(StarZone &zone) - for (int i=0; i<7; ++i) { - *input >> nInt16; - if (!nInt16) continue; -- static char const *wh[]= {"useRelPosForChartGroup","adjMargForLegend","adjMargForTitle","adjMargForSubTitle", -+ static char const* const wh[]= {"useRelPosForChartGroup","adjMargForLegend","adjMargForTitle","adjMargForSubTitle", - "adjMargForXAxisTitle","adjMargForYAxisTitle","adjMargForZAxisTitle" - }; - f << wh[i] << ","; -@@ -797,7 +797,7 @@ bool StarObjectChart::readSCHAttributes(StarZone &zone) - bool hasMoved; - *input>>hasMoved; - if (!hasMoved) continue; -- static char const *wh[]= {"diagram", "title", "subTitle", "legend", "XAxis", "YAxis", "ZAxis"}; -+ static char const* const wh[]= {"diagram", "title", "subTitle", "legend", "XAxis", "YAxis", "ZAxis"}; - f << wh[i] << "HasMoved,"; - } - } -@@ -978,7 +978,7 @@ bool StarObjectChart::readSCHMemChart(StarZone &zone) - } - if (string.empty()) continue; - if (i<5) { -- static char const *wh[]= {"mainTitle","subTitle","xAxisTitle","yAxisTitle","zAxisTitle"}; -+ static char const* const wh[]= {"mainTitle","subTitle","xAxisTitle","yAxisTitle","zAxisTitle"}; - f << wh[i] << "=" << libstoff::getString(string).cstr() << ","; - } - else if (i<5+int(nCol)) -diff --git a/src/lib/StarObjectModel.cxx b/src/lib/StarObjectModel.cxx -index 9d9c4f8..761b167 100644 ---- a/src/lib/StarObjectModel.cxx -+++ b/src/lib/StarObjectModel.cxx -@@ -669,7 +669,7 @@ bool StarObjectModel::read(StarZone &zone) - break; - } - if (string.empty()) continue; -- static char const *wh[]= {"cTableName", "dashName", "lineEndName", "hashName", "gradientName", "bitmapName"}; -+ static char const* const wh[]= {"cTableName", "dashName", "lineEndName", "hashName", "gradientName", "bitmapName"}; - f << wh[i] << "=" << libstoff::getString(string).cstr() << ","; - } - } -diff --git a/src/lib/StarObjectNumericRuler.cxx b/src/lib/StarObjectNumericRuler.cxx -index 75a620b..48c91b0 100644 ---- a/src/lib/StarObjectNumericRuler.cxx -+++ b/src/lib/StarObjectNumericRuler.cxx -@@ -233,7 +233,7 @@ bool StarObjectNumericRuler::readLevel(StarZone &zone, STOFFListLevel &level) - return true; - } - if (string.empty()) continue; -- static char const *wh[]= {"prefix", "postfix", "fontname", "fontstyle"}; -+ static char const* const wh[]= {"prefix", "postfix", "fontname", "fontstyle"}; - f << wh[i] << "=" << libstoff::getString(string).cstr() << ","; - if (i==0) level.m_propertyList.insert("style:num-prefix",libstoff::getString(string)); - else if (i==1) level.m_propertyList.insert("style:num-suffix",libstoff::getString(string)); -diff --git a/src/lib/StarObjectSpreadsheet.cxx b/src/lib/StarObjectSpreadsheet.cxx -index 4723f33..a8419a4 100644 ---- a/src/lib/StarObjectSpreadsheet.cxx -+++ b/src/lib/StarObjectSpreadsheet.cxx -@@ -1172,7 +1172,7 @@ try - break; - } - if (string.empty()) continue; -- static char const *wh[]= {"serviceName","source","name","user","pass"}; -+ static char const* const wh[]= {"serviceName","source","name","user","pass"}; - f << wh[j] << "=" << libstoff::getString(string).cstr() << ","; - } - break; -@@ -1946,7 +1946,7 @@ bool StarObjectSpreadsheet::readSCTable(StarZone &zone, StarObjectSpreadsheetInt - break; - } - if (!string.empty()) { -- static char const *wh[]= {"name", "comment", "pass"}; -+ static char const* const wh[]= {"name", "comment", "pass"}; - f << wh[i] << "=" << libstoff::getString(string).cstr() << ","; - if (i==0 && !m_spreadsheetState->m_tableList.empty() && m_spreadsheetState->m_tableList.back()) - m_spreadsheetState->m_tableList.back()->m_name=libstoff::getString(string); -@@ -2036,7 +2036,7 @@ bool StarObjectSpreadsheet::readSCTable(StarZone &zone, StarObjectSpreadsheetInt - break; - } - if (string.empty()) continue; -- static char const *wh[]= {"doc", "flt", "tab"}; -+ static char const* const wh[]= {"doc", "flt", "tab"}; - f << "link[" << wh[i] << "]=" << libstoff::getString(string).cstr() << ","; - } - if (!ok) break; -@@ -2121,7 +2121,7 @@ bool StarObjectSpreadsheet::readSCColumn(StarZone &zone, StarObjectSpreadsheetIn - break; - } - if (string.empty()) continue; -- static char const *wh[]= {"note","date","author"}; -+ static char const* const wh[]= {"note","date","author"}; - cell.m_notes[j]=libstoff::getString(string); - f << wh[j] << "=" << cell.m_notes[j].cstr() << ","; - } -diff --git a/src/lib/libstaroffice_internal.cxx b/src/lib/libstaroffice_internal.cxx -index c23880a..0894c7a 100644 ---- a/src/lib/libstaroffice_internal.cxx -+++ b/src/lib/libstaroffice_internal.cxx -@@ -164,10 +164,10 @@ std::string numberingValueToString(NumberingType type, int value) - return s; - case LOWERCASE_ROMAN: - case UPPERCASE_ROMAN: { -- static char const *romanS[] = {"M", "CM", "D", "CD", "C", "XC", "L", -+ static char const* const romanS[] = {"M", "CM", "D", "CD", "C", "XC", "L", - "XL", "X", "IX", "V", "IV", "I" - }; -- static char const *romans[] = {"m", "cm", "d", "cd", "c", "xc", "l", -+ static char const* const romans[] = {"m", "cm", "d", "cd", "c", "xc", "l", - "xl", "x", "ix", "v", "iv", "i" - }; - static int const romanV[] = {1000, 900, 500, 400, 100, 90, 50, --- -2.49.0 - diff --git a/external/libstaroffice/ExternalProject_libstaroffice.mk b/external/libstaroffice/ExternalProject_libstaroffice.mk index a81428e713e4..4279b832304c 100644 --- a/external/libstaroffice/ExternalProject_libstaroffice.mk +++ b/external/libstaroffice/ExternalProject_libstaroffice.mk @@ -22,8 +22,7 @@ $(eval $(call gb_ExternalProject_use_externals,libstaroffice,\ $(call gb_ExternalProject_get_state_target,libstaroffice,build) : $(call gb_Trace_StartRange,libstaroffice,EXTERNAL) $(call gb_ExternalProject_run,build,\ - export PKG_CONFIG="" \ - && $(gb_RUN_CONFIGURE) ./configure \ + $(gb_RUN_CONFIGURE) ./configure \ --with-pic \ $(if $(DISABLE_DYNLOADING), \ --enable-static --disable-shared \ diff --git a/external/libstaroffice/UnpackedTarball_libstaroffice.mk b/external/libstaroffice/UnpackedTarball_libstaroffice.mk index d926c9901086..b7d8f4ee744d 100644 --- a/external/libstaroffice/UnpackedTarball_libstaroffice.mk +++ b/external/libstaroffice/UnpackedTarball_libstaroffice.mk @@ -15,14 +15,6 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,libstaroffice,0)) $(eval $(call gb_UnpackedTarball_update_autoconf_configs,libstaroffice)) -# 0001-const-up-these-arrays.patch.1 -# upstream attempt as: -# https://github.com/fosnola/libstaroffice/pull/12 - -$(eval $(call gb_UnpackedTarball_add_patches,libstaroffice, \ - external/libstaroffice/0001-const-up-these-arrays.patch.1 \ -)) - ifneq ($(OS),MACOSX) ifneq ($(OS),WNT) $(eval $(call gb_UnpackedTarball_add_patches,libstaroffice, \ diff --git a/external/libtiff/UnpackedTarball_libtiff.mk b/external/libtiff/UnpackedTarball_libtiff.mk index 52b56a498b0a..d799953bebb1 100644 --- a/external/libtiff/UnpackedTarball_libtiff.mk +++ b/external/libtiff/UnpackedTarball_libtiff.mk @@ -14,7 +14,6 @@ $(eval $(call gb_UnpackedTarball_set_tarball,libtiff,$(LIBTIFF_TARBALL))) $(eval $(call gb_UnpackedTarball_add_patches,libtiff,\ external/libtiff/libtiff.linknolibs.patch \ external/libtiff/0001-ofz-54685-Timeout.patch \ - external/libtiff/ofz68840.patch \ )) # vim: set noet sw=4 ts=4: diff --git a/external/libtiff/ofz68840.patch b/external/libtiff/ofz68840.patch deleted file mode 100644 index 0a8721ebe012..000000000000 --- a/external/libtiff/ofz68840.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- a/libtiff/tif_tile.c -+++ b/libtiff/tif_tile.c -@@ -233,7 +233,13 @@ - _TIFFMultiply64(tif, samplingrow_size, samplingblocks_ver, module)); - } - else -- return (_TIFFMultiply64(tif, nrows, TIFFTileRowSize64(tif), module)); -+ { -+ uint64_t row_size = TIFFTileRowSize64(tif); -+ /* I think the way this works the expectation is there are always even num of samples */ -+ if (td->td_photometric == PHOTOMETRIC_YCBCR) -+ row_size = TIFFroundup_64(row_size, 2); -+ return (_TIFFMultiply64(tif, nrows, row_size, module)); -+ } - } - tmsize_t TIFFVTileSize(TIFF *tif, uint32_t nrows) - { diff --git a/external/libwps/UnpackedTarball_libwps.mk b/external/libwps/UnpackedTarball_libwps.mk index 44a0ab6c80ec..522e4b11a1f5 100644 --- a/external/libwps/UnpackedTarball_libwps.mk +++ b/external/libwps/UnpackedTarball_libwps.mk @@ -23,6 +23,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,libwps,\ external/libwps/libtool.patch.0 \ external/libwps/enumarith.patch \ external/libwps/0001-const-up-some-things.patch.1 \ + external/libwps/tdf148749.patch.1 \ )) ifneq ($(OS),MACOSX) diff --git a/external/libwps/tdf148749.patch.1 b/external/libwps/tdf148749.patch.1 new file mode 100644 index 000000000000..823605c7eaae --- /dev/null +++ b/external/libwps/tdf148749.patch.1 @@ -0,0 +1,62 @@ +From 2e1d8e8b8ee0ff54d5c8448b6ead95aaf12f1e52 +Author: Julien Nabet +Date: Thu Aug 13 20:59:25 2026 +0200 + + Deal with some LMBCS group control + + LMBCS is Lotus Multi-Byte Character Set + Group control in LMBCS begin with 0x0F and the control character is the second byte + See https://github.com/unicode-org/icu/blob/main/icu4c/source/common/ucnv_lmb.cpp + + It'll allow to fix Libreoffice bug tdf#148749: FILEOPEN Lotus 123 entity encoding + +diff -ur libwps.org/src/lib/LotusSpreadsheet.cpp libwps/src/lib/LotusSpreadsheet.cpp +--- libwps.org/src/lib/LotusSpreadsheet.cpp 2026-08-13 20:01:53.946906461 +0200 ++++ libwps/src/lib/LotusSpreadsheet.cpp 2026-08-13 20:02:27.643098528 +0200 +@@ -3348,6 +3348,7 @@ + WPSFont font=style.getFont(); + m_listener->setFont(font); + bool prevEOL=false; ++ bool prevLMBCS_EOL=false; + std::string text; + while (!input->isEnd()) + { +@@ -3431,6 +3432,38 @@ + } + prevEOL=false; + break; ++ case 0xf: ++ if (pos+1>=endPos) ++ { ++ WPS_DEBUG_MSG(("LotusSpreadsheet::sendText: can not read the control character value\n")); ++ break; ++ } ++ c=char(libwps::readU8(input)); ++ if (c >= 0x20 && c <= 0x2F) ++ { ++ c -= 0x20; ++ switch(c) ++ { ++ case 0xd: ++ m_listener->insertUnicodeString(libwps_tools_win::Font::unicodeString(text, fontType)); ++ text.clear(); ++ m_listener->insertEOL(); ++ prevLMBCS_EOL=true; ++ break; ++ case 0xa: ++ if (!prevLMBCS_EOL) ++ { ++ WPS_DEBUG_MSG(("LotusSpreadsheet::sendText: find 0xa without 0xd\n")); ++ } ++ prevLMBCS_EOL=false; ++ break; ++ } ++ } ++ else ++ { ++ WPS_DEBUG_MSG(("LotusSpreadsheet::sendText: find a control character followed by a character not included between 0x20 and 0x2F\n")); ++ } ++ break; + default: + if (c) + text.push_back(c); diff --git a/external/lpsolve/0001-const-up-some-statics.patch.1 b/external/lpsolve/0001-const-up-some-statics.patch.1 deleted file mode 100644 index 7d1a8173ba66..000000000000 --- a/external/lpsolve/0001-const-up-some-statics.patch.1 +++ /dev/null @@ -1,129 +0,0 @@ -From 75ba3f247d6f0baa6dc83b7eca09ec67dabe0924 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Tue, 22 Jul 2025 13:12:12 +0100 -Subject: [PATCH] const up some statics - ---- - lp_params.c | 26 +++++++++++++------------- - 1 file changed, 13 insertions(+), 13 deletions(-) - -diff --git a/lp_params.c b/lp_params.c -index e8fcd2e..c5de106 100644 ---- a/lp_params.c -+++ b/lp_params.c -@@ -53,13 +53,13 @@ - REAL_set_function *REAL_set_function; /* set via setREALfunction */ - } set_function; - int type; /* set via set*function */ -- struct _values *values; /* set via setvalues to a structure of _values */ -+ const struct _values *values; /* set via setvalues to a structure of _values */ - int elements; /* or via setNULLvalues if the value is shown as is */ - unsigned int basemask; - int mask; /* WRITE_ACTIVE or WRITE_COMMENTED */ - }; - --static struct _values anti_degen[] = -+static const struct _values anti_degen[] = - { - { setvalue(ANTIDEGEN_NONE) }, - { setvalue(ANTIDEGEN_FIXEDVARS) }, -@@ -74,7 +74,7 @@ - { setvalue(ANTIDEGEN_BOUNDFLIP) }, - }; - --static struct _values basiscrash[] = -+static const struct _values basiscrash[] = - { - { setvalue(CRASH_NONE) }, - /* { setvalue(CRASH_NONBASICBOUNDS) }, */ /* not yet implemented */ -@@ -82,14 +82,14 @@ - { setvalue(CRASH_LEASTDEGENERATE) }, - }; - --static struct _values bb_floorfirst[] = -+static const struct _values bb_floorfirst[] = - { - { setvalue(BRANCH_CEILING) }, - { setvalue(BRANCH_FLOOR) }, - { setvalue(BRANCH_AUTOMATIC) }, - }; - --static struct _values bb_rule[] = -+static const struct _values bb_rule[] = - { - { setvalue(NODE_FIRSTSELECT) }, - { setvalue(NODE_GAPSELECT) }, -@@ -114,7 +114,7 @@ - { setvalue(NODE_STRONGINIT) }, - }; - --static struct _values improve[] = -+static const struct _values improve[] = - { - { setvalue(IMPROVE_NONE) }, - { setvalue(IMPROVE_SOLUTION) }, -@@ -143,7 +143,7 @@ - set_mip_gap(lp, FALSE, mip_gap); - } - --static struct _values pivoting[] = -+static const struct _values pivoting[] = - { - { setvalue(PRICER_FIRSTINDEX) }, - { setvalue(PRICER_DANTZIG) }, -@@ -161,7 +161,7 @@ - { setvalue(PRICE_TRUENORMINIT) }, - }; - --static struct _values presolving[] = -+static const struct _values presolving[] = - { - { setvalue(PRESOLVE_NONE) }, - { setvalue(PRESOLVE_ROWS) }, -@@ -217,14 +217,14 @@ - set_presolve(lp, get_presolve(lp), maxloops); - } - --static struct _values print_sol[] = -+static const struct _values print_sol[] = - { - { FALSE, "0" }, - { TRUE, "1" }, - { setvalue(AUTOMATIC) }, - }; - --static struct _values scaling[] = -+static const struct _values scaling[] = - { - { setvalue(SCALE_NONE) }, - { setvalue(SCALE_EXTREME) }, -@@ -243,7 +243,7 @@ - { setvalue(SCALE_COLSONLY) }, - }; - --static struct _values simplextype[] = -+static const struct _values simplextype[] = - { - { setvalue(SIMPLEX_PRIMAL_PRIMAL) }, - { setvalue(SIMPLEX_DUAL_PRIMAL) }, -@@ -251,7 +251,7 @@ - { setvalue(SIMPLEX_DUAL_DUAL) }, - }; - --static struct _values verbose[] = -+static const struct _values verbose[] = - { - { setvalue(NEUTRAL) }, - { setvalue(CRITICAL) }, -@@ -262,7 +262,7 @@ - { setvalue(FULL) }, - }; - --static struct _functions functions[] = -+static const struct _functions functions[] = - { - /* solve options */ - { "ANTI_DEGEN", setintfunction(get_anti_degen, set_anti_degen), setvalues(anti_degen, ~0), WRITE_ACTIVE }, --- -2.49.0 - diff --git a/external/lpsolve/ExternalPackage_lpsolve.mk b/external/lpsolve/ExternalPackage_lpsolve.mk deleted file mode 100644 index 23c2c5abfa03..000000000000 --- a/external/lpsolve/ExternalPackage_lpsolve.mk +++ /dev/null @@ -1,24 +0,0 @@ -# -*- 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_ExternalPackage_ExternalPackage,lpsolve,lpsolve)) - -$(eval $(call gb_ExternalPackage_use_external_project,lpsolve,lpsolve)) - -ifneq ($(DISABLE_DYNLOADING),TRUE) -ifeq ($(OS),WNT) -$(eval $(call gb_ExternalPackage_add_file,lpsolve,$(LIBO_LIB_FOLDER)/lpsolve55.dll,lpsolve55/lpsolve55.dll)) -else ifeq ($(OS),MACOSX) -$(eval $(call gb_ExternalPackage_add_file,lpsolve,$(LIBO_LIB_FOLDER)/liblpsolve55.dylib,lpsolve55/liblpsolve55.dylib)) -else # $(OS) != WNT/MACOSX -$(eval $(call gb_ExternalPackage_add_file,lpsolve,$(LIBO_LIB_FOLDER)/liblpsolve55.so,lpsolve55/liblpsolve55.so)) -endif # $(OS) -endif # $(DISABLE_DYNLOADING) - -# vim: set noet sw=4 ts=4: diff --git a/external/lpsolve/ExternalProject_lpsolve.mk b/external/lpsolve/ExternalProject_lpsolve.mk deleted file mode 100644 index 2bd5cdacbe2a..000000000000 --- a/external/lpsolve/ExternalProject_lpsolve.mk +++ /dev/null @@ -1,37 +0,0 @@ -# -*- 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_ExternalProject_ExternalProject,lpsolve)) - -$(eval $(call gb_ExternalProject_register_targets,lpsolve,\ - build \ -)) - -ifeq ($(OS),WNT) -$(call gb_ExternalProject_get_state_target,lpsolve,build): - $(call gb_Trace_StartRange,lpsolve,EXTERNAL) - $(call gb_ExternalProject_run,build,\ - LIB="$(ILIB)" RUNTIME_FLAG="$(if $(MSVC_USE_DEBUG_RUNTIME),/MDd,/MD)" \ - cmd /c cvc6.bat \ - ,lpsolve55) - $(call gb_Trace_EndRange,lpsolve,EXTERNAL) -else # $(OS)!=WNT -$(call gb_ExternalProject_get_state_target,lpsolve,build): - $(call gb_Trace_StartRange,lpsolve,EXTERNAL) - $(call gb_ExternalProject_run,build,\ - CC="$(CC) $(call gb_ExternalProject_get_build_flags,lpsolve)" \ - SYSTEM_COLAMD=$(SYSTEM_COLAMD) \ - $(if $(filter MACOSX,$(OS)),EXTRA_LINKFLAGS='-install_name @__________________________________________________OOO/liblpsolve55.dylib') \ - sh -e $(if $(filter MACOSX,$(OS)),ccc.osx, \ - $(if $(filter TRUE,$(DISABLE_DYNLOADING)),ccc.static, \ - ccc)) \ - ,lpsolve55) - $(call gb_Trace_EndRange,lpsolve,EXTERNAL) -endif # $(OS) -# vim: set noet sw=4 ts=4: diff --git a/external/lpsolve/README b/external/lpsolve/README deleted file mode 100644 index 95059b25cd4e..000000000000 --- a/external/lpsolve/README +++ /dev/null @@ -1 +0,0 @@ -A mixed Integer Linear Programming (MILP) solver from [https://github.com/lp-solve/lp_solve]. diff --git a/external/lpsolve/UnpackedTarball_lpsolve.mk b/external/lpsolve/UnpackedTarball_lpsolve.mk deleted file mode 100644 index 167c14862587..000000000000 --- a/external/lpsolve/UnpackedTarball_lpsolve.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- 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_UnpackedTarball_UnpackedTarball,lpsolve)) - -$(eval $(call gb_UnpackedTarball_set_tarball,lpsolve,$(LPSOLVE_TARBALL))) - -$(eval $(call gb_UnpackedTarball_set_patchlevel,lpsolve,3)) - -# external/lpsolve/0001-const-up-some-statics.patch.1 -# upstreaming attempt as: -# https://github.com/lp-solve/lp_solve/pull/1 - -$(eval $(call gb_UnpackedTarball_add_patches,lpsolve,\ - external/lpsolve/0001-const-up-some-statics.patch.1 \ -)) - -ifeq ($(OS_FOR_BUILD),WNT) - -$(eval $(call gb_UnpackedTarball_set_patchflags,lpsolve,--binary)) -$(eval $(call gb_UnpackedTarball_add_patches,lpsolve,\ - external/lpsolve/lp_solve_5.5-windows.patch \ -)) - -else - -$(eval $(call gb_UnpackedTarball_add_patches,lpsolve,\ - external/lpsolve/lp_solve_5.5.patch \ - external/lpsolve/lpsolve-ubsan.patch.0 \ - external/lpsolve/system-colamd.diff \ -)) - -$(eval $(call gb_UnpackedTarball_add_file,lpsolve,lpsolve55/ccc.static,external/lpsolve/ccc.static)) - -endif -# vim: set noet sw=4 ts=4: - - diff --git a/external/lpsolve/ccc.static b/external/lpsolve/ccc.static deleted file mode 100644 index c8f070921202..000000000000 --- a/external/lpsolve/ccc.static +++ /dev/null @@ -1,20 +0,0 @@ -if [ "$SYSTEM_COLAMD" != "TRUE" ]; then - colamd_c=../colamd/colamd.c -fi -src='../lp_MDO.c ../shared/commonlib.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../fortify.c $colamd_c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c' -obj=`echo $src|sed -e 's/\.c/.o/g' -e 's!\([^ ]*/\)*!!g'` - -opts='-O3' - -def= - -# FIMXE: Link statically with colamd? -if test "$SYSTEM_COLAMD" = "TRUE"; then - colamd_i=$COLAMD_CFLAGS -else - colamd_i=-I../colamd -fi -$CC -I.. -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL $colamd_i -I../shared $opts $def -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine -c $src - -$AR -r liblpsolve55.a $obj -rm $obj diff --git a/external/lpsolve/lp_solve_5.5-windows.patch b/external/lpsolve/lp_solve_5.5-windows.patch deleted file mode 100644 index 16d5261c7c7f..000000000000 --- a/external/lpsolve/lp_solve_5.5-windows.patch +++ /dev/null @@ -1,60 +0,0 @@ -*** misc/lp_solve_5.5/lpsolve55/cgcc.bat Sun Jun 12 04:27:28 2005 ---- misc/build/lp_solve_5.5/lpsolve55/cgcc.bat Sun Dec 14 07:55:19 2008 -*************** -*** 7,14 **** - - set c=gcc - -! rem rc lpsolve.rc -! %c% -DINLINE=static -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -s -O3 -shared -mno-cygwin -enable-stdcall-fixup -D_USRDLL -DWIN32 -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine %src% ..\lp_solve.def -o lpsolve55.dll - - %c% -DINLINE=static -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -s -O3 -shared -D_USRDLL -DWIN32 -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine %src% -o liblpsolve55.so - ---- 7,14 ---- - - set c=gcc - -! windres lpsolve.rc lpsolve_res.obj -! %c% -DINLINE=static -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -s -O3 -shared -mno-cygwin -enable-stdcall-fixup -mthreads %lpsolve_LDFLAGS% -D_USRDLL -DWIN32 -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine %src% lpsolve_res.obj ..\lp_solve.def %lpsolve_LIBS% -o lpsolve55.dll - - %c% -DINLINE=static -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -s -O3 -shared -D_USRDLL -DWIN32 -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine %src% -o liblpsolve55.so - -*** misc/lp_solve_5.5/lpsolve55/lpsolve.rc Sun Jun 4 00:15:24 2006 ---- misc/build/lp_solve_5.5/lpsolve55/lpsolve.rc Fri Nov 23 16:34:22 2007 -*************** -*** 7,13 **** - // - // Generated from the TEXTINCLUDE 2 resource. - // -! #include "afxres.h" - - ///////////////////////////////////////////////////////////////////////////// - #undef APSTUDIO_READONLY_SYMBOLS ---- 7,13 ---- - // - // Generated from the TEXTINCLUDE 2 resource. - // -! #include "winresrc.h" - - ///////////////////////////////////////////////////////////////////////////// - #undef APSTUDIO_READONLY_SYMBOLS ---- misc/lp_solve_5.5/lpsolve55/cvc6.bat -+++ misc/build/lp_solve_5.5/lpsolve55/cvc6.bat -@@ -14,15 +14,4 @@ - set c=cl - --rc lpsolve.rc -+rc %SOLARINC% lpsolve.rc --%c% -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd /LD /MD /O1 /Zp8 /Gz -D_WINDLL -D_USRDLL -DWIN32 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine %src% lpsolve.res ..\lp_solve.def -o lpsolve55.dll -+%c% -Zi -FS -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd %SOLARINC% /LD %RUNTIME_FLAG% /O1 /Zp8 /Gz -D_WINDLL -D_USRDLL -DWIN32 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine %src% lpsolve.res ..\lp_solve.def -Felpsolve55.dll --rem /link /LINK50COMPAT -- --if exist a.obj del a.obj --%c% -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd /MT /O1 /Zp8 /Gd /c -DWIN32 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine %src% --lib *.obj /OUT:liblpsolve55.lib -- --if exist a.obj del a.obj --%c% -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd /MTd /O1 /Zp8 /Gd /c -DWIN32 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine %src% --lib *.obj /OUT:liblpsolve55d.lib -- --if exist *.obj del *.obj diff --git a/external/lpsolve/lp_solve_5.5.patch b/external/lpsolve/lp_solve_5.5.patch deleted file mode 100644 index 2b2588a9f15a..000000000000 --- a/external/lpsolve/lp_solve_5.5.patch +++ /dev/null @@ -1,95 +0,0 @@ ---- misc/build/lp_solve_5.5/lpsolve55/ccc.orig Sat Jun 11 21:27:18 2005 -+++ misc/build/lp_solve_5.5/lpsolve55/ccc Sun May 22 11:20:19 2011 -@@ -1,25 +1,42 @@ - src='../lp_MDO.c ../shared/commonlib.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../fortify.c ../colamd/colamd.c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c' --c=cc -+ar=$AR -+c=$CC -+ranlib=$RANLIB - - def= - so= --if [ "$PLATFORM" = "SCO_UNIX" ] --then def='-dy -K PIC -DNOLONGLONG' -- dl=-lc --else dl=-ldl -- so=y -+soprefix= -+libs= -+pic= -+ldflags= -+inline= -+if [ "$OS" = "WNT" -a "$COM" = "GCC" ]; then -+ so=dll -+ a=dll.a -+ inline=-DINLINE=static -+else -+ so=so -+ a=a -+ soprefix=lib -+ libs="-lm" -+ pic=-fpic -+ ldflags="-Wl,-Bsymbolic -Wl,-soname,liblpsolve55.$so" - fi - -+if [ "$OS" = "LINUX" ]; then -+ libs="$libs -ldl" -+fi -+ - opts='-O3' - --$c -s -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd $opts $def -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src -+$c -s $inline -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd $opts $def -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src --ar rv liblpsolve55.a `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` --ranlib liblpsolve55.a -+$ar rv liblpsolve55.$a `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` -+$ranlib liblpsolve55.$a - - if [ "$so" != "" ] - then -- $c -fpic -s -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I. $opts -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src -- $c -shared -Wl,-Bsymbolic -Wl,-soname,liblpsolve55.so -o liblpsolve55.so `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` -lc -lm -ldl -+ $c $pic -s $inline -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I. $opts -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src -+ $c -shared $ldflags -o ${soprefix}lpsolve55.$so `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` $libs - fi - - rm *.o 2>/dev/null ---- misc/build/lp_solve_5.5/lpsolve55/ccc.osx.orig Thu Jun 23 22:53:08 2005 -+++ misc/build/lp_solve_5.5/lpsolve55/ccc.osx -@@ -1,23 +1,30 @@ - src='../lp_MDO.c ../shared/commonlib.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../fortify.c ../colamd/colamd.c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c' --c=cc -+c=$CC - -+if test -n "$verbose"; then -+ set -x -+fi -+ - def= - so= -+# EXTRA_LINKFLAGS is set in the ExternalProject_lpsolve.mk -+extra_linkflags=$EXTRA_LINKFLAGS -+ - if [ "$PLATFORM" = "SCO_UNIX" ] - then def='-DLoadInverseLib=0 -DLoadLanguageLib=0 -D__HYPER=long' - else dl=-ldl - so=y - fi - --opts='-idirafter /usr/include/sys -O3 -DINTEGERTIME -Wno-long-double' -+opts='-idirafter /usr/include/sys -O3 -DINTEGERTIME' - --$c -s -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd $opts $def -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src -+$c -s -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd $opts $def -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src --libtool -static -o liblpsolve55.a `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` -+$LIBTOOL -static -o liblpsolve55.a `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` - - if [ "$so" != "" ] - then -- $c -fPIC -fno-common -s -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I. $opts -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src -- $c -dynamiclib liblpsolve55.a -compatibility_version 5.5.0 -current_version 5.5.0 -o liblpsolve55.dylib `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` -lc -+ $c -fPIC -fno-common -s -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I. $opts -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src -+ $c $extra_linkflags -dynamiclib liblpsolve55.a -compatibility_version 5.5.0 -current_version 5.5.0 -o liblpsolve55.dylib `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` -lc - fi - - rm *.o 2>/dev/null diff --git a/external/lpsolve/lpsolve-ubsan.patch.0 b/external/lpsolve/lpsolve-ubsan.patch.0 deleted file mode 100644 index 7a5e308c6efd..000000000000 --- a/external/lpsolve/lpsolve-ubsan.patch.0 +++ /dev/null @@ -1,22 +0,0 @@ ---- lp_presolve.c -+++ lp_presolve.c -@@ -168,7 +168,7 @@ - if(isprimal) { - if(psdata->primalundo != NULL) - mat = psdata->primalundo->tracker; -- solution = lp->full_solution + lp->presolve_undo->orig_rows; -+ solution = lp->full_solution == NULL ? NULL : lp->full_solution + lp->presolve_undo->orig_rows; - slacks = lp->full_solution; - } - else { ---- lp_pricePSE.c -+++ lp_pricePSE.c -@@ -145,7 +147,7 @@ - - /* Store the active/current pricing type */ - if(isdual == AUTOMATIC) -- isdual = (MYBOOL) lp->edgeVector[0]; -+ isdual = lp->edgeVector[0] != 0.0; - else - lp->edgeVector[0] = isdual; - diff --git a/external/lpsolve/system-colamd.diff b/external/lpsolve/system-colamd.diff deleted file mode 100644 index 80eba695f379..000000000000 --- a/external/lpsolve/system-colamd.diff +++ /dev/null @@ -1,39 +0,0 @@ -diff -urN lp_solve_5.5-old/lpsolve55/ccc lp_solve_5.5/lpsolve55/ccc ---- misc/build/lp_solve_5.5/lpsolve55/ccc 2005-06-11 21:27:18.000000000 +0200 -+++ misc/build/lp_solve_5.5/lpsolve55/ccc 2025-03-02 17:58:19.904235635 +0100 -@@ -1,4 +1,7 @@ --src='../lp_MDO.c ../shared/commonlib.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../fortify.c ../colamd/colamd.c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c' -+if test "$SYSTEM_COLAMD" != "TRUE"; then -+ colamd_c=../colamd/colamd.c -+fi -+src="../lp_MDO.c ../shared/commonlib.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../fortify.c $colamd_c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c" - ar=$AR - c=$CC - ranlib=$RANLIB -@@ -25,17 +28,24 @@ - - if [ "$OS" = "LINUX" ]; then - libs="$libs -ldl" -+ libs="$libs $COLAMD_LIBS" - fi - - opts='-O3' - --$c -s $inline -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd $opts $def -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src -+if test "$SYSTEM_COLAMD" = "TRUE"; then -+ colamd_i=$COLAMD_CFLAGS -+else -+ colamd_i=-I../colamd -+fi -+ -+$c -s $inline -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL $colamd_i $opts $def -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src - $ar rv liblpsolve55.$a `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` - $ranlib liblpsolve55.$a - - if [ "$so" != "" ] - then -- $c $pic -s $inline -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I. $opts -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src -+ $c $pic -s $inline -c -I.. -I../shared -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL $colamd_i -I. $opts -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine $src - $c -shared $ldflags -o ${soprefix}lpsolve55.$so `echo $src|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` $libs - fi - diff --git a/external/md4c/0001-const-up-scheme_map.patch.1 b/external/md4c/0001-const-up-scheme_map.patch.1 deleted file mode 100644 index ca2f1d4aaf51..000000000000 --- a/external/md4c/0001-const-up-scheme_map.patch.1 +++ /dev/null @@ -1,25 +0,0 @@ -From 66526366b67e3b42eb4c30cefa6f5efdff690c8e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Sat, 26 Jul 2025 21:38:34 +0100 -Subject: [PATCH] const up scheme_map - ---- - src/md4c.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/md4c.c b/src/md4c.c -index e3f5cf9..947f5c9 100644 ---- a/src/md4c.c -+++ b/src/md4c.c -@@ -3238,7 +3238,7 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines, int table_m - - /* A potential permissive URL autolink. */ - if(ch == _T(':')) { -- static struct { -+ static const struct { - const CHAR* scheme; - SZ scheme_size; - const CHAR* suffix; --- -2.49.0 - diff --git a/external/md4c/UnpackedTarball_md4c.mk b/external/md4c/UnpackedTarball_md4c.mk index d4ea369638f3..ed368456c249 100644 --- a/external/md4c/UnpackedTarball_md4c.mk +++ b/external/md4c/UnpackedTarball_md4c.mk @@ -10,12 +10,5 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,md4c)) $(eval $(call gb_UnpackedTarball_set_tarball,md4c,$(MD4C_TARBALL))) -# 0001-const-up-scheme_map.patch.1 effort to upstream at: -# https://github.com/mity/md4c/pull/291 - -$(eval $(call gb_UnpackedTarball_add_patches,md4c,\ - external/md4c/0001-const-up-scheme_map.patch.1 \ -)) - # vim: set noet sw=4 ts=4: diff --git a/external/mdds/UnpackedTarball_mdds.mk b/external/mdds/UnpackedTarball_mdds.mk index fe10a60bde59..3bb404724f2f 100644 --- a/external/mdds/UnpackedTarball_mdds.mk +++ b/external/mdds/UnpackedTarball_mdds.mk @@ -13,8 +13,4 @@ $(eval $(call gb_UnpackedTarball_set_tarball,mdds,$(MDDS_TARBALL))) $(eval $(call gb_UnpackedTarball_set_patchlevel,mdds,0)) -$(eval $(call gb_UnpackedTarball_add_patches,mdds,\ - external/mdds/gcc-12-silence-use-after-free.patch.1 \ -)) - # vim: set noet sw=4 ts=4: diff --git a/external/mdds/gcc-12-silence-use-after-free.patch.1 b/external/mdds/gcc-12-silence-use-after-free.patch.1 deleted file mode 100644 index 4fd742182d32..000000000000 --- a/external/mdds/gcc-12-silence-use-after-free.patch.1 +++ /dev/null @@ -1,42 +0,0 @@ -Workaround for gcc-toolset-12 on almalinux8 on a release/optimized build: -[build CXX] sc/source/core/data/column2.cxx -In file included from /home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/workdir/UnpackedTarball/mdds/include/mdds/flat_segment_tree.hpp:37, - from /home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/sc/inc/columnspanset.hxx:16, - from /home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/sc/inc/column.hxx:25, - from /home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/sc/source/core/data/column2.cxx:20: -In function ‘void mdds::__st::intrusive_ptr_release(node*) [with T = mdds::flat_segment_tree]’, - inlined from ‘boost::intrusive_ptr::~intrusive_ptr() [with T = mdds::__st::node >]’ at /home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/workdir/UnpackedTarball/boost/boost/smart_ptr/intrusive_ptr.hpp:100:44, - inlined from ‘std::pair::const_iterator, bool> mdds::flat_segment_tree::insert_segment_impl(key_type, key_type, value_type, bool) [with Key = int; Value = bool]’ at /home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/workdir/UnpackedTarball/mdds/include/mdds/flat_segment_tree_def.inl:225:1: -/home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/workdir/UnpackedTarball/mdds/include/mdds/node.hpp:247:10: error: pointer used after ‘void operator delete(void*, std::size_t)’ [-Werror=use-after-free] - 247 | --p->refcount; - | ~~~^~~~~~~~ -In function ‘void mdds::__st::intrusive_ptr_release(node*) [with T = mdds::flat_segment_tree]’, - inlined from ‘void mdds::__st::intrusive_ptr_release(node*) [with T = mdds::flat_segment_tree]’ at /home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/workdir/UnpackedTarball/mdds/include/mdds/node.hpp:245:13, - inlined from ‘boost::intrusive_ptr::~intrusive_ptr() [with T = mdds::__st::node >]’ at /home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/workdir/UnpackedTarball/boost/boost/smart_ptr/intrusive_ptr.hpp:100:44, - inlined from ‘std::pair::const_iterator, bool> mdds::flat_segment_tree::insert_segment_impl(key_type, key_type, value_type, bool) [with Key = int; Value = bool]’ at /home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/workdir/UnpackedTarball/mdds/include/mdds/flat_segment_tree_def.inl:224:93: -/home/tdf/lode/jenkins/workspace/lo_gerrit/Config/linux_gcc_release_64/workdir/UnpackedTarball/mdds/include/mdds/node.hpp:249:9: note: call to ‘void operator delete(void*, std::size_t)’ here - 249 | delete p; - | ^~~~~~~~ -cc1plus: all warnings being treated as errors - -diff -ur mdds.org/include/mdds/node.hpp mdds/include/mdds/node.hpp ---- mdds.org/include/mdds/node.hpp 2023-07-24 18:27:14.427139325 +0000 -+++ mdds/include/mdds/node.hpp 2023-07-24 18:26:54.554461294 +0000 -@@ -210,9 +210,15 @@ - template - inline void intrusive_ptr_release(node* p) - { -- --p->refcount; -- if (!p->refcount) -+#if defined __GNUC__ && __GNUC__ == 12 && __GNUC_MINOR__ <= 3 && !defined __clang__ -+#pragma GCC diagnostic push -+#pragma GCC diagnostic ignored "-Wuse-after-free" -+#endif -+ if(--p->refcount == 0) - delete p; -+#if defined __GNUC__ && __GNUC__ == 12 && __GNUC_MINOR__ <= 3 && !defined __clang__ -+#pragma GCC diagnostic pop -+#endif - } - - template diff --git a/external/more_fonts/ExternalPackage_agdasima.mk b/external/more_fonts/ExternalPackage_agdasima.mk deleted file mode 100644 index 25867d9ec3e5..000000000000 --- a/external/more_fonts/ExternalPackage_agdasima.mk +++ /dev/null @@ -1,17 +0,0 @@ -# -*- 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_ExternalPackage_ExternalPackage,fonts_agdasima,font_agdasima)) - -$(eval $(call gb_ExternalPackage_add_unpacked_files,fonts_agdasima,$(LIBO_SHARE_FOLDER)/fonts/truetype,\ - Agdasima-Regular.ttf \ - Agdasima-Bold.ttf \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/ExternalPackage_bacasime_antique.mk b/external/more_fonts/ExternalPackage_bacasime_antique.mk deleted file mode 100644 index 892260df7a98..000000000000 --- a/external/more_fonts/ExternalPackage_bacasime_antique.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- 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_ExternalPackage_ExternalPackage,fonts_bacasime_antique,font_bacasime_antique)) - -$(eval $(call gb_ExternalPackage_add_unpacked_files,fonts_bacasime_antique,$(LIBO_SHARE_FOLDER)/fonts/truetype,\ - BacasimeAntique-Regular.ttf \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/ExternalPackage_caprasimo.mk b/external/more_fonts/ExternalPackage_caprasimo.mk deleted file mode 100644 index 9e347449cb34..000000000000 --- a/external/more_fonts/ExternalPackage_caprasimo.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- 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_ExternalPackage_ExternalPackage,fonts_caprasimo,font_caprasimo)) - -$(eval $(call gb_ExternalPackage_add_unpacked_files,fonts_caprasimo,$(LIBO_SHARE_FOLDER)/fonts/truetype,\ - Caprasimo-Regular.ttf \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/ExternalPackage_lugrasimo.mk b/external/more_fonts/ExternalPackage_lugrasimo.mk deleted file mode 100644 index 69084ca701ea..000000000000 --- a/external/more_fonts/ExternalPackage_lugrasimo.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- 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_ExternalPackage_ExternalPackage,fonts_lugrasimo,font_lugrasimo)) - -$(eval $(call gb_ExternalPackage_add_unpacked_files,fonts_lugrasimo,$(LIBO_SHARE_FOLDER)/fonts/truetype,\ - Lugrasimo-Regular.ttf \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/ExternalPackage_lumanosimo.mk b/external/more_fonts/ExternalPackage_lumanosimo.mk deleted file mode 100644 index b60ecc8a471c..000000000000 --- a/external/more_fonts/ExternalPackage_lumanosimo.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- 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_ExternalPackage_ExternalPackage,fonts_lumanosimo,font_lumanosimo)) - -$(eval $(call gb_ExternalPackage_add_unpacked_files,fonts_lumanosimo,$(LIBO_SHARE_FOLDER)/fonts/truetype,\ - Lumanosimo-Regular.ttf \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/ExternalPackage_lunasima.mk b/external/more_fonts/ExternalPackage_lunasima.mk deleted file mode 100644 index 475568f8406b..000000000000 --- a/external/more_fonts/ExternalPackage_lunasima.mk +++ /dev/null @@ -1,17 +0,0 @@ -# -*- 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_ExternalPackage_ExternalPackage,fonts_lunasima,font_lunasima)) - -$(eval $(call gb_ExternalPackage_add_unpacked_files,fonts_lunasima,$(LIBO_SHARE_FOLDER)/fonts/truetype,\ - Lunasima-Regular.ttf \ - Lunasima-Bold.ttf \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/Module_more_fonts.mk b/external/more_fonts/Module_more_fonts.mk index bcb97d11ca33..01d56fb12cb3 100644 --- a/external/more_fonts/Module_more_fonts.mk +++ b/external/more_fonts/Module_more_fonts.mk @@ -36,13 +36,6 @@ $(eval $(call gb_Module_add_targets,more_fonts,\ ExternalPackage_noto_serif_lao \ ExternalPackage_reem \ ExternalPackage_scheherazade \ - $(if $(WITH_DOCREPAIR_FONTS),ExternalPackage_agdasima,) \ - $(if $(WITH_DOCREPAIR_FONTS),ExternalPackage_bacasime_antique,) \ - $(if $(WITH_DOCREPAIR_FONTS),ExternalPackage_belanosima,) \ - $(if $(WITH_DOCREPAIR_FONTS),ExternalPackage_caprasimo,) \ - $(if $(WITH_DOCREPAIR_FONTS),ExternalPackage_lugrasimo,) \ - $(if $(WITH_DOCREPAIR_FONTS),ExternalPackage_lumanosimo,) \ - $(if $(WITH_DOCREPAIR_FONTS),ExternalPackage_lunasima,) \ UnpackedTarball_alef \ UnpackedTarball_amiri \ UnpackedTarball_caladea \ @@ -69,13 +62,6 @@ $(eval $(call gb_Module_add_targets,more_fonts,\ UnpackedTarball_noto_serif_lao \ UnpackedTarball_reem \ UnpackedTarball_scheherazade \ - $(if $(WITH_DOCREPAIR_FONTS),UnpackedTarball_agdasima,) \ - $(if $(WITH_DOCREPAIR_FONTS),UnpackedTarball_bacasime_antique,) \ - $(if $(WITH_DOCREPAIR_FONTS),UnpackedTarball_belanosima,) \ - $(if $(WITH_DOCREPAIR_FONTS),UnpackedTarball_caprasimo,) \ - $(if $(WITH_DOCREPAIR_FONTS),UnpackedTarball_lugrasimo,) \ - $(if $(WITH_DOCREPAIR_FONTS),UnpackedTarball_lumanosimo,) \ - $(if $(WITH_DOCREPAIR_FONTS),UnpackedTarball_lunasima,) \ )) # vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/UnpackedTarball_bacasime_antique.mk b/external/more_fonts/UnpackedTarball_bacasime_antique.mk deleted file mode 100644 index 7533fb16e9a9..000000000000 --- a/external/more_fonts/UnpackedTarball_bacasime_antique.mk +++ /dev/null @@ -1,14 +0,0 @@ -# -*- 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_UnpackedTarball_UnpackedTarball,font_bacasime_antique)) - -$(eval $(call gb_UnpackedTarball_set_tarball,font_bacasime_antique,$(FONT_BACASIME_ANTIQUE_TARBALL),0)) - -# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/fc_local.snippet b/external/more_fonts/fc_local.snippet index fdc0a627a042..cb49929b0a4a 100644 --- a/external/more_fonts/fc_local.snippet +++ b/external/more_fonts/fc_local.snippet @@ -27,52 +27,3 @@ Caladea - - - Agency FB - - Agdasima - - - - - Baskerville Old Face - - Bacasime Antique - - - - - Berlin Sans FB - - Belanosima - - - - - Cooper Black - - Caprasimo - - - - - Lucida Grande - - Lunasima - - - - - Lucida Handwriting - - Lumanosimo - - - - - Lucida Calligraphy - - Lugrasimo - - diff --git a/external/mythes/UnpackedTarball_mythes.mk b/external/mythes/UnpackedTarball_mythes.mk index 8bd75f971795..1abee0019cf4 100644 --- a/external/mythes/UnpackedTarball_mythes.mk +++ b/external/mythes/UnpackedTarball_mythes.mk @@ -13,11 +13,4 @@ $(eval $(call gb_UnpackedTarball_set_tarball,mythes,$(MYTHES_TARBALL))) $(eval $(call gb_UnpackedTarball_update_autoconf_configs,mythes)) -$(eval $(call gb_UnpackedTarball_set_patchlevel,mythes,2)) - -$(eval $(call gb_UnpackedTarball_add_patches,mythes,\ - external/mythes/mythes-1.2.0-vanilla-th-gen-idx.patch \ - external/mythes/mythes-fdo48017-wfopen.patch \ -)) - # vim: set noet sw=4 ts=4: diff --git a/external/mythes/mythes-1.2.0-vanilla-th-gen-idx.patch b/external/mythes/mythes-1.2.0-vanilla-th-gen-idx.patch deleted file mode 100644 index 3752e291200e..000000000000 --- a/external/mythes/mythes-1.2.0-vanilla-th-gen-idx.patch +++ /dev/null @@ -1,90 +0,0 @@ ---- misc/mythes-1.2.3.orig/th_gen_idx.pl -+++ misc/build/mythes-1.2.3/th_gen_idx.pl -@@ -1,11 +1,25 @@ --#!/usr/bin/perl -- --# perl program to take a thesaurus structured text data file --# and create the proper sorted index file (.idx) -+: -+eval 'exec perl -wS $0 ${1+"$@"}' -+ if 0; -+# -+# 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 . -+# - # --# typically invoked as follows: --# cat th_en_US_new.dat | ./th_gen_idx.pl > th_en_US_new.idx - # - - sub by_entry { - my ($aent, $aoff) = split('\|',$a); -@@ -13,6 +34,27 @@ sub by_entry { - $aent cmp $bent; - } - -+#FIXME: someone may want "infile" or even parameter parsing -+sub get_outfile { -+ my $next_is_file = 0; -+ foreach ( @ARGV ) { -+ if ( $next_is_file ) { -+ return $_ -+ } -+ if ( $_ eq "-o" ) { -+ $next_is_file = 1; -+ } -+ } -+ return ""; -+} -+ -+sub usage { -+ print "usage:\n"; -+ print "$0 -o outfile < input\n"; -+ -+ exit 99; -+} -+ - # main routine - my $ne = 0; # number of entries in index - my @tindex=(); # the index itself -@@ -24,6 +66,10 @@ my $nm=0; # number of meaning fo - my $meaning=""; # current meaning and synonyms - my $p; # misc uses - my $encoding; # encoding used by text file -+my $outfile = ""; -+ -+$outfile = get_outfile(); -+usage() if ( $outfile eq "" ); - - # top line of thesaurus provides encoding - $encoding=; -@@ -51,9 +97,13 @@ while ($rec=){ - # now we have all of the information - # so sort it and then output the encoding, count and index data - @tindex = sort by_entry @tindex; --print STDOUT "$encoding\n"; --print STDOUT "$ne\n"; -+ -+print "$outfile\n"; -+open OUTFILE, ">$outfile" or die "ERROR: Can't open $outfile for writing!"; -+print OUTFILE "$encoding\n"; -+print OUTFILE "$ne\n"; - foreach $one (@tindex) { -- print STDOUT "$one\n"; -+ print OUTFILE "$one\n"; - } -+close OUTFILE; - diff --git a/external/mythes/mythes-fdo48017-wfopen.patch b/external/mythes/mythes-fdo48017-wfopen.patch deleted file mode 100644 index 82d69ad6626e..000000000000 --- a/external/mythes/mythes-fdo48017-wfopen.patch +++ /dev/null @@ -1,77 +0,0 @@ -diff -u mythes/mythes.cxx build/mythes/mythes.cxx ---- mythes/mythes.cxx 2014-05-22 00:27:38.508588487 +0200 -+++ build/mythes/mythes.cxx 2014-05-22 10:07:06.107547417 +0200 -@@ -8,6 +8,11 @@ - - #include "mythes.hxx" - -+#ifdef _WIN32 -+#include -+#include -+#endif -+ - MyThes::MyThes(const char* idxpath, const char * datpath) - { - nw = 0; -@@ -35,7 +40,7 @@ - { - - // open the index file -- FILE * pifile = fopen(idxpath,"r"); -+ FILE * pifile = myfopen(idxpath,"r"); - if (!pifile) { - return 0; - } -@@ -90,7 +95,7 @@ - fclose(pifile); - - /* next open the data file */ -- pdfile = fopen(datpath,"r"); -+ pdfile = myfopen(datpath,"r"); - if (!pdfile) { - return 0; - } -@@ -373,3 +378,22 @@ - return -1; - } - -+FILE * MyThes::myfopen(const char * path, const char * mode) { -+#ifdef _WIN32 -+#define WIN32_LONG_PATH_PREFIX "\\\\?\\" -+ if (strncmp(path, WIN32_LONG_PATH_PREFIX, 4) == 0) { -+ int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); -+ wchar_t *buff = (wchar_t *) malloc(len * sizeof(wchar_t)); -+ wchar_t *buff2 = (wchar_t *) malloc(len * sizeof(wchar_t)); -+ FILE * f = NULL; -+ MultiByteToWideChar(CP_UTF8, 0, path, -1, buff, len); -+ if (_wfullpath( buff2, buff, len ) != NULL) { -+ f = _wfopen(buff2, (strcmp(mode, "r") == 0) ? L"r" : L"rb"); -+ } -+ free(buff); -+ free(buff2); -+ return f; -+ } -+#endif -+ return fopen(path, mode); -+} -diff -u mythes/mythes.hxx build/mythes/mythes.hxx ---- mythes/mythes.hxx 2010-03-04 12:56:23.000000000 +0100 -+++ build/mythes/mythes.hxx 2014-05-22 10:11:14.363543731 +0200 -@@ -30,6 +30,7 @@ - MyThes & operator = (const MyThes &); - - public: -+ // use UTF-8 encoded paths in WIN32 environment - MyThes(const char* idxpath, const char* datpath); - ~MyThes(); - -@@ -66,6 +67,9 @@ - // return index of char in string - int mystr_indexOfChar(const char * d, int c); - -+ // fopen or _wfopen -+ FILE * myfopen(const char * path, const char * mode); -+ - }; - - #endif diff --git a/external/nss/ExternalProject_nss.mk b/external/nss/ExternalProject_nss.mk index cd198051c017..f658c45a0f50 100644 --- a/external/nss/ExternalProject_nss.mk +++ b/external/nss/ExternalProject_nss.mk @@ -43,6 +43,7 @@ $(call gb_ExternalProject_get_state_target,nss,build): \ $(MAKE) nss_build_all RC="rc.exe $(SOLARINC)" \ NSINSTALL='$(call gb_ExternalExecutable_get_command,python) $(SRCDIR)/external/nss/nsinstall.py' \ NSS_DISABLE_GTESTS=1 \ + NSS_DISABLE_CMD_TOOLS=1 \ CCC="$(CXX)" \ ,nss) $(call gb_Trace_EndRange,nss,EXTERNAL) @@ -80,6 +81,7 @@ $(call gb_ExternalProject_get_state_target,nss,build): \ $(if $(CROSS_COMPILING),NSINSTALL="$(if $(filter MACOSX,$(OS_FOR_BUILD)),xcrun python3,$(call gb_ExternalExecutable_get_command,python)) $(SRCDIR)/external/nss/nsinstall.py") \ $(if $(filter ANDROID,$(OS)),OS_TARGET=Android OS_TARGET_RELEASE=$(ANDROID_API_LEVEL) ARCHFLAG="" DEFAULT_COMPILER=clang ANDROID_NDK=$(ANDROID_NDK_DIR) ANDROID_TOOLCHAIN_VERSION=obsolete ANDROID_PREFIX=$(HOST_PLATFORM) ANDROID_SYSROOT=$(ANDROID_NDK_DIR)/sysroot) \ NSS_DISABLE_GTESTS=1 \ + NSS_DISABLE_CMD_TOOLS=1 \ nss_build_all \ && rm -f $(gb_UnpackedTarball_workdir)/nss/dist/out/lib/*.a \ $(if $(filter MACOSX,$(OS)),\ diff --git a/external/nss/UnpackedTarball_nss.mk b/external/nss/UnpackedTarball_nss.mk index 74e7d5da0779..0be1273b4e28 100644 --- a/external/nss/UnpackedTarball_nss.mk +++ b/external/nss/UnpackedTarball_nss.mk @@ -41,6 +41,8 @@ $(eval $(call gb_UnpackedTarball_add_patches,nss,\ external/nss/nss.windows.patch \ external/nss/nss.nowerror.patch \ external/nss/nss.utf8bom.patch.1) \ + external/nss/outofbounds.patch.0 \ + external/nss/nss-skip-command-line-tools.patch.1 \ )) ifeq ($(COM_IS_CLANG),TRUE) diff --git a/external/nss/nss-skip-command-line-tools.patch.1 b/external/nss/nss-skip-command-line-tools.patch.1 new file mode 100644 index 000000000000..721bf5c0ec64 --- /dev/null +++ b/external/nss/nss-skip-command-line-tools.patch.1 @@ -0,0 +1,22 @@ +Add a switch that leaves out the nss command-line tools. + +The build only needs the nss shared libraries. The tools under nss/cmd, such as +certutil and pk12util, are never installed or run. Building them costs about a +tenth of the whole nss build. The library headers that the tools directory +exports, and shlibsign, are still built. + +diff --git a/nss/cmd/manifest.mn b/nss/cmd/manifest.mn +--- a/nss/cmd/manifest.mn ++++ b/nss/cmd/manifest.mn +@@ -92,6 +92,11 @@ + endif + endif + ++ifdef NSS_DISABLE_CMD_TOOLS ++SOFTOKEN_SRCDIRS = $(SHLIBSIGN_SRCDIR) ++NSS_SRCDIRS = ++endif ++ + DIRS = \ + $(LIB_SRCDIRS) \ + $(SOFTOKEN_SRCDIRS) \ diff --git a/external/nss/nss.disablefsync.patch b/external/nss/nss.disablefsync.patch index 8c5d84b553ce..192721d1c58a 100644 --- a/external/nss/nss.disablefsync.patch +++ b/external/nss/nss.disablefsync.patch @@ -1,9 +1,10 @@ --- a/nss/nss/lib/sqlite/sqlite3.c +++ b/nss/nss/lib/sqlite/sqlite3.c -@@ -36136,6 +36136,15 @@ +@@ -43915,6 +43915,15 @@ + */ static int full_fsync(int fd, int fullSync, int dataOnly){ int rc; - ++ + static int disabledKnown = 0, disabled = 0; + if (!disabledKnown) + { @@ -12,7 +13,6 @@ + } + if (disabled) + return 0; -+ + /* The following "ifdef/elif/else/" block has the same structure as - ** the one below. It is replicated here solely to avoid cluttering - ** up the real code with the UNUSED_PARAMETER() macros. + ** the one below. It is replicated here solely to avoid cluttering diff --git a/external/nss/outofbounds.patch.0 b/external/nss/outofbounds.patch.0 new file mode 100644 index 000000000000..f99bbb62119e --- /dev/null +++ b/external/nss/outofbounds.patch.0 @@ -0,0 +1,11 @@ +--- nss/lib/nss/nssinit.c ++++ nss/lib/nss/nssinit.c +@@ -289,7 +289,7 @@ + + /* back up to the top of the directory */ + PORT_Memcpy(path, dbpath, path_len); +- if (path[path_len - 1] != FILE_SEP) { ++ if (path_len == 0 || path[path_len - 1] != FILE_SEP) { + path[path_len++] = FILE_SEP; + } + PORT_Strcpy(&path[path_len], dllname); diff --git a/external/openssl/ExternalProject_openssl.mk b/external/openssl/ExternalProject_openssl.mk index a31945fab0db..397dccd25145 100644 --- a/external/openssl/ExternalProject_openssl.mk +++ b/external/openssl/ExternalProject_openssl.mk @@ -78,7 +78,7 @@ else $(call gb_ExternalProject_get_state_target,openssl,build): $(call gb_Trace_StartRange,openssl,EXTERNAL) $(call gb_ExternalProject_run,build,\ - unset MAKEFLAGS && \ + unset MAKEFLAGS && $(if $(SOURCE_DATE_EPOCH),export SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) &&) \ $(if $(filter LINUX MACOSX FREEBSD ANDROID SOLARIS iOS,$(OS)), \ ./Configure, \ $(if $(filter WNT,$(OS)), \ diff --git a/external/pdfium/Library_pdfium.mk b/external/pdfium/Library_pdfium.mk index 3a69170bdaef..0906bbe7c944 100644 --- a/external/pdfium/Library_pdfium.mk +++ b/external/pdfium/Library_pdfium.mk @@ -24,6 +24,10 @@ $(eval $(call gb_Library_add_cxxflags,pdfium, \ )) endif endif +#TODO: Drop this once Clang supports -std=c++29: +ifneq ($(filter -std=c++29,$(CXXFLAGS_CXX11)),) +$(eval $(call gb_Library_add_cxxflags,pdfium,-std=c++2d)) +endif $(eval $(call gb_Library_set_include,pdfium,\ -I$(gb_UnpackedTarball_workdir)/pdfium \ @@ -45,6 +49,7 @@ $(eval $(call gb_Library_add_defs,pdfium,\ -DUNICODE \ -DWIN32_LEAN_AND_MEAN \ -DCOMPONENT_BUILD \ + -DPDF_USE_AGG \ )) ifeq ($(SYSTEM_OPENJPEG2),TRUE) $(eval $(call gb_Library_add_defs,pdfium,\ @@ -251,7 +256,6 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fpdfapi/parser/fpdf_parser_utility \ UnpackedTarball/pdfium/core/fpdfapi/parser/cpdf_object_walker \ UnpackedTarball/pdfium/core/fpdfapi/parser/cpdf_read_validator \ - UnpackedTarball/pdfium/core/fpdfapi/render/charposlist \ UnpackedTarball/pdfium/core/fpdfapi/render/cpdf_devicebuffer \ UnpackedTarball/pdfium/core/fpdfapi/render/cpdf_docrenderdata \ UnpackedTarball/pdfium/core/fpdfapi/page/cpdf_imageloader \ @@ -270,8 +274,7 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fpdfapi/edit/cpdf_creator \ UnpackedTarball/pdfium/core/fpdfapi/parser/cpdf_encryptor \ UnpackedTarball/pdfium/core/fpdfapi/parser/cpdf_flateencoder \ - UnpackedTarball/pdfium/core/fpdfapi/font/cfx_cttgsubtable \ - UnpackedTarball/pdfium/core/fpdfapi/font/cfx_stockfontarray \ + UnpackedTarball/pdfium/core/fpdfapi/font/cpdf_stockfontarray \ UnpackedTarball/pdfium/core/fpdfapi/font/cpdf_cid2unicodemap \ UnpackedTarball/pdfium/core/fpdfapi/font/cpdf_cmap \ UnpackedTarball/pdfium/core/fpdfapi/font/cpdf_cmapparser \ @@ -297,6 +300,8 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fpdfapi/edit/cpdf_stringarchivestream \ UnpackedTarball/pdfium/core/fpdfapi/page/cpdf_occontext \ UnpackedTarball/pdfium/core/fpdfapi/edit/cpdf_contentstream_write_utils \ + UnpackedTarball/pdfium/core/fpdfapi/edit/cpdf_font_util \ + UnpackedTarball/pdfium/core/fpdfapi/edit/cpdf_fontsubsetter \ UnpackedTarball/pdfium/core/fpdfapi/page/cpdf_annotcontext \ UnpackedTarball/pdfium/core/fpdfapi/render/cpdf_pagerendercontext \ UnpackedTarball/pdfium/core/fpdfapi/page/cpdf_transferfuncdib \ @@ -304,6 +309,7 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fpdfapi/page/cpdf_basedcs \ UnpackedTarball/pdfium/core/fpdfapi/page/cpdf_indexedcs \ UnpackedTarball/pdfium/core/fpdfapi/parser/object_tree_traversal_util \ + UnpackedTarball/pdfium/core/fpdfapi/font/cpdf_facebasedsimplefont \ )) # fpdfdoc @@ -339,6 +345,7 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fpdfdoc/cpdf_generateap \ UnpackedTarball/pdfium/core/fpdfdoc/cpvt_section \ UnpackedTarball/pdfium/core/fpdfdoc/cpvt_variabletext \ + UnpackedTarball/pdfium/core/fpdfdoc/cpvt_word \ )) # fpdftext @@ -352,22 +359,6 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ # fxcodec $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fxcodec/fx_codec \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_ArithDecoder \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_ArithIntDecoder \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_BitStream \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_Context \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_GrdProc \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_GrrdProc \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_HtrdProc \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_HuffmanDecoder \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_HuffmanTable \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_Image \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_PatternDict \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_PddProc \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_SddProc \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_Segment \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_SymbolDict \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_TrdProc \ UnpackedTarball/pdfium/core/fxcodec/gif/cfx_gif \ UnpackedTarball/pdfium/core/fxcodec/gif/lzw_decompressor \ UnpackedTarball/pdfium/core/fxcodec/cfx_codec_memory \ @@ -376,12 +367,28 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fxcodec/jpeg/jpegmodule \ UnpackedTarball/pdfium/core/fxcodec/jpx/cjpx_decoder \ UnpackedTarball/pdfium/core/fxcodec/jpx/jpx_decode_utils \ - UnpackedTarball/pdfium/core/fxcodec/jbig2/JBig2_DocumentContext \ UnpackedTarball/pdfium/core/fxcodec/basic/basicmodule \ UnpackedTarball/pdfium/core/fxcodec/flate/flatemodule \ UnpackedTarball/pdfium/core/fxcodec/icc/icc_transform \ UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_decoder \ UnpackedTarball/pdfium/core/fxcodec/data_and_bytes_consumed \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_arith_decoder \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_arith_int_decoder \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_bit_stream \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_context \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_document_context \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_grd_proc \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_grrd_proc \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_htrd_proc \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_huffman_decoder \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_huffman_table \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_image \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_pattern_dict \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_pdd_proc \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_sdd_proc \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_segment \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_symbol_dict \ + UnpackedTarball/pdfium/core/fxcodec/jbig2/jbig2_trd_proc \ )) $(eval $(call gb_Library_add_generated_cobjects,pdfium,\ @@ -438,14 +445,22 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fxcrt/string_data_template \ UnpackedTarball/pdfium/core/fxcrt/binary_buffer \ UnpackedTarball/pdfium/core/fxcrt/cfx_read_only_span_stream \ - UnpackedTarball/pdfium/core/fxcrt/cfx_read_only_string_stream \ - UnpackedTarball/pdfium/core/fxcrt/cfx_read_only_vector_stream \ UnpackedTarball/pdfium/core/fxcrt/fx_memory_malloc \ UnpackedTarball/pdfium/core/fxcrt/widetext_buffer \ UnpackedTarball/pdfium/core/fxcrt/debug/alias \ UnpackedTarball/pdfium/core/fxcrt/string_template \ + UnpackedTarball/pdfium/core/fxcrt/cfx_fileaccess_stream \ + UnpackedTarball/pdfium/core/fxcrt/cfx_read_only_container_stream \ + UnpackedTarball/pdfium/core/fxcrt/bytestring_pool \ + UnpackedTarball/pdfium/core/fxcrt/cfx_bidi_resolver \ )) +ifneq ($(OS),WNT) +$(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ + UnpackedTarball/pdfium/core/fxcrt/mapped_data_bytes \ +)) +endif + # fxge $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fxge/dib/cfx_bitmapstorer \ @@ -491,7 +506,6 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fxge/cfx_path \ UnpackedTarball/pdfium/core/fxge/cfx_renderdevice \ UnpackedTarball/pdfium/core/fxge/cfx_substfont \ - UnpackedTarball/pdfium/core/fxge/cfx_unicodeencoding \ UnpackedTarball/pdfium/core/fxge/cfx_glyphbitmap \ UnpackedTarball/pdfium/core/fxge/text_glyph_pos \ UnpackedTarball/pdfium/core/fxge/fx_font \ @@ -499,8 +513,11 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fxge/dib/cfx_cmyk_to_srgb \ UnpackedTarball/pdfium/core/fxge/text_char_pos \ UnpackedTarball/pdfium/core/fxge/cfx_face \ - UnpackedTarball/pdfium/core/fxge/cfx_defaultrenderdevice \ UnpackedTarball/pdfium/core/fxge/calculate_pitch \ + UnpackedTarball/pdfium/core/fxge/cfx_charmap_resolver \ + UnpackedTarball/pdfium/core/fxge/cfx_cttgsubtable \ + UnpackedTarball/pdfium/core/fxge/cfx_cttnametable \ + UnpackedTarball/pdfium/core/fxge/cfx_standardfont \ )) # javascript, build with pdf_enable_v8 disabled. @@ -575,6 +592,7 @@ $(eval $(call gb_Library_use_externals,pdfium,\ zlib \ icu_headers \ icuuc \ + harfbuzz \ )) ifneq (,$(filter LINUX ANDROID,$(OS))) @@ -596,6 +614,7 @@ $(eval $(call gb_Library_add_libs,pdfium,\ endif $(eval $(call gb_Library_use_external,pdfium,freetype)) +$(eval $(call gb_Library_use_external,pdfium,libpng)) $(eval $(call gb_Library_add_defs,pdfium,\ -DDEFINE_PS_TABLES_DATA \ )) @@ -656,12 +675,10 @@ $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ UnpackedTarball/pdfium/core/fxge/win32/ctext_only_printer_driver \ UnpackedTarball/pdfium/core/fxge/win32/cwin32_platform \ UnpackedTarball/pdfium/core/fxge/win32/cfx_psfonttracker \ - UnpackedTarball/pdfium/core/fxge/cfx_windowsrenderdevice \ UnpackedTarball/pdfium/core/fxcrt/cfx_fileaccess_windows \ UnpackedTarball/pdfium/core/fxcrt/fx_folder_windows \ UnpackedTarball/pdfium/core/fxcrt/win/win_util \ UnpackedTarball/pdfium/core/fxcrt/code_point_view \ - UnpackedTarball/pdfium/core/fpdfapi/render/cpdf_windowsrenderdevice \ )) $(eval $(call gb_Library_use_system_win32_libs,pdfium,\ @@ -676,9 +693,9 @@ endif ifeq ($(OS),MACOSX) # fxge $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ - UnpackedTarball/pdfium/core/fxge/apple/fx_apple_platform \ + UnpackedTarball/pdfium/core/fxge/apple/capple_platform \ UnpackedTarball/pdfium/core/fxge/apple/fx_apple_impl \ - UnpackedTarball/pdfium/core/fxge/apple/fx_quartz_device \ + UnpackedTarball/pdfium/core/fxge/apple/cquartz_2d \ )) $(eval $(call gb_Library_use_system_darwin_frameworks,pdfium,\ @@ -690,9 +707,9 @@ endif ifeq ($(OS),iOS) # fxge $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ - UnpackedTarball/pdfium/core/fxge/apple/fx_apple_platform \ + UnpackedTarball/pdfium/core/fxge/apple/capple_platform \ UnpackedTarball/pdfium/core/fxge/apple/fx_apple_impl \ - UnpackedTarball/pdfium/core/fxge/apple/fx_quartz_device \ + UnpackedTarball/pdfium/core/fxge/apple/cquartz_2d \ )) $(eval $(call gb_Library_use_system_darwin_frameworks,pdfium,\ @@ -704,12 +721,8 @@ endif ifeq ($(OS),ANDROID) # fxge $(eval $(call gb_Library_add_generated_exception_objects,pdfium,\ - UnpackedTarball/pdfium/core/fxge/android/cfpf_skiadevicemodule \ - UnpackedTarball/pdfium/core/fxge/android/cfpf_skiafont \ - UnpackedTarball/pdfium/core/fxge/android/cfpf_skiafontmgr \ UnpackedTarball/pdfium/core/fxge/android/cfx_androidfontinfo \ UnpackedTarball/pdfium/core/fxge/android/fx_android_impl \ - UnpackedTarball/pdfium/core/fxge/android/cfpf_skiapathfont \ )) endif diff --git a/external/pdfium/UnpackedTarball_pdfium.mk b/external/pdfium/UnpackedTarball_pdfium.mk index 2f857315ac6e..c72d719ddea4 100644 --- a/external/pdfium/UnpackedTarball_pdfium.mk +++ b/external/pdfium/UnpackedTarball_pdfium.mk @@ -21,6 +21,10 @@ pdfium_patches += charcodetoglyphindex.patch.1 pdfium_patches += getfontdictobjnum.patch.1 pdfium_patches += system-fast_float.diff +# https://pdfium-review.googlesource.com/c/pdfium/+/154490 +pdfium_patches += system-icu.patch.1 +# https://pdfium-review.googlesource.com/c/pdfium/+/154690 +pdfium_patches += fix-windows-build.patch.1 ifeq ($(OS),WNT) pdfium_patches += pdfium-vs2019-arm64_no-__umulh.patch.1 @@ -29,6 +33,9 @@ endif # TODO, attempt upstream pdfium_patches += ofz451333752.patch pdfium_patches += extractpatterns.patch +pdfium_patches += charbboxinflation.patch.1 +# Hide bundled FreeType symbols +pdfium_patches += freetype-hidden-visibility.patch $(eval $(call gb_UnpackedTarball_UnpackedTarball,pdfium)) diff --git a/external/pdfium/charbboxinflation.patch.1 b/external/pdfium/charbboxinflation.patch.1 new file mode 100644 index 000000000000..e70b44b58bbf --- /dev/null +++ b/external/pdfium/charbboxinflation.patch.1 @@ -0,0 +1,32 @@ +Don't grow the top of the glyph bounding box by a 64th. + +CPDF_CIDFont::GetCharBBox() is the only caller of CFX_Face::GetCharBBox(), +so this made composite fonts measure glyphs taller than simple fonts, which +get their bounding box from CFX_Face::GetGlyphBBox() directly. + +diff -ru pdfium.orig/core/fxge/cfx_face.cpp pdfium/core/fxge/cfx_face.cpp +--- pdfium.orig/core/fxge/cfx_face.cpp ++++ pdfium/core/fxge/cfx_face.cpp +@@ -68,10 +68,6 @@ + + constexpr int kMaxGlyphDimension = 2048; + +-// Boundary value to avoid integer overflow when adding 1/64th of the value. +-constexpr int kMaxRectTop = 2114445437; +- +- + int FTPosToCBoxInt(FT_Pos pos) { + // Boundary values to avoid integer overflow when multiplied by 1000. + static constexpr FT_Pos kMinCBox = -2147483; +@@ -1289,11 +1289,6 @@ + int err = LoadGlyph(glyph_index, /*scale=*/false); + if (err == 0) { + rect = GetGlyphBBox(glyph_index); +- if (rect.top <= kMaxRectTop) { +- rect.top += rect.top / 64; +- } else { +- rect.top = std::numeric_limits::max(); +- } + #if defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS) + #if defined(PDF_ENABLE_FONTATIONS) + if (skrifa_font_ && skrifa_font_->font->is_ok()) { diff --git a/external/pdfium/extractpatterns.patch b/external/pdfium/extractpatterns.patch index 475f15a91d5c..56a3b04c3928 100644 --- a/external/pdfium/extractpatterns.patch +++ b/external/pdfium/extractpatterns.patch @@ -28,7 +28,7 @@ #include "core/fpdfapi/page/cpdf_textobject.h" #include "core/fpdfapi/page/cpdf_textstate.h" #include "core/fpdfapi/parser/cpdf_array.h" -@@ -834,6 +835,108 @@ +@@ -834,6 +835,110 @@ return FPDFBitmapFromCFXDIBitmap(result_bitmap.Leak()); } @@ -48,7 +48,7 @@ + + // `rect` has to use integer values. Round up as needed. + const FX_RECT rect = pattern_bbox.GetOuterRect(); -+ if (rect.IsEmpty()) ++ if (rect.IsEmpty() || !rect.Valid()) + return nullptr; + + auto result_bitmap = pdfium::MakeRetain(); @@ -61,9 +61,11 @@ + CFX_Matrix mtPattern2Bitmap; + mtPattern2Bitmap.MatchRect(bitmap_rect, cell_bbox); + -+ CFX_DefaultRenderDevice bitmap_device; -+ bitmap_device.AttachWithBackdropAndGroupKnockout( -+ result_bitmap, /*pBackdropBitmap=*/nullptr, /*bGroupKnockout=*/true); ++ auto bitmap_device = ++ CFX_RenderDevice::CreateForBitmapWithBackdropAndGroupKnockout( ++ result_bitmap, /*backdrop_bitmap=*/nullptr, /*group_knockout=*/true); ++ if (!bitmap_device) ++ return nullptr; + + CPDF_RenderOptions options; + if (!pTilingPattern->colored()) @@ -72,7 +74,7 @@ + + CPDF_RenderContext context(&doc, nullptr, nullptr); + context.AppendLayer(pPatternForm.get(), mtPattern2Bitmap); -+ context.Render(&bitmap_device, nullptr, &options, nullptr); ++ context.Render(bitmap_device.get(), nullptr, &options, nullptr); + + CHECK(!result_bitmap->IsPremultiplied()); + diff --git a/external/pdfium/fix-windows-build.patch.1 b/external/pdfium/fix-windows-build.patch.1 new file mode 100644 index 000000000000..abc5a72ee453 --- /dev/null +++ b/external/pdfium/fix-windows-build.patch.1 @@ -0,0 +1,44 @@ +From 3abda657c073f89dc6b39bbad8f7dfe2fbf17fd4 Mon Sep 17 00:00:00 2001 +Date: Mon, 10 Aug 2026 11:59:46 -0700 +Subject: [PATCH] fxge: fix missing windows include in cfx_renderdevice.h + +This resulted in a build failure here: +In file included from .../pdfium/core/fxge/cfx_drawutils.cpp:13: +.../core/fxge/cfx_renderdevice.h(74,7): error: unknown type name 'HDC' + 74 | HDC hdc, + | ^ + +It seems this started after commit +fc790866bf26d977b2ea3a0c3938bb52895309ea (Consolidate CFX_RenderDevice +and remove CPDF_WindowsRenderDevice, 2026-06-29): the Windows-DC code +was moved from cpdf_windowsrenderdevice.h to cfx_renderdevice.h but the +windows.h include wasn't moved. + +Given that it looks like every other pdfium header that uses HDC +includes directly (core/fxge/win32/cpsoutput.h etc.), just +add the missing include here as well, conditionally. + +Change-Id: Ie9920b2031148f7781862502905d999ce045b014 +Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/154690 +Reviewed-by: Tom Sepez +Reviewed-by: Lei Zhang +Commit-Queue: Lei Zhang +--- + core/fxge/cfx_renderdevice.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/core/fxge/cfx_renderdevice.h b/core/fxge/cfx_renderdevice.h +index 8f427ce01..4114b9884 100644 +--- a/core/fxge/cfx_renderdevice.h ++++ b/core/fxge/cfx_renderdevice.h +@@ -19,6 +19,10 @@ + #include "core/fxge/dib/fx_dib.h" + #include "core/fxge/renderdevicedriver_iface.h" + ++#if BUILDFLAG(IS_WIN) ++#include ++#endif ++ + class CFX_DIBBase; + class CFX_DIBitmap; + class CFX_Font; diff --git a/external/pdfium/freetype-hidden-visibility.patch b/external/pdfium/freetype-hidden-visibility.patch new file mode 100644 index 000000000000..2b8604f2f286 --- /dev/null +++ b/external/pdfium/freetype-hidden-visibility.patch @@ -0,0 +1,12 @@ +--- third_party/freetype/src/include/freetype/config/public-macros.h ++++ third_party/freetype/src/include/freetype/config/public-macros.h +@@ -73,8 +73,7 @@ + + /* gcc, clang */ + #elif ( defined( __GNUC__ ) && __GNUC__ >= 4 ) || defined( __clang__ ) +-#define FT_PUBLIC_FUNCTION_ATTRIBUTE \ +- __attribute__(( visibility( "default" ) )) ++#define FT_PUBLIC_FUNCTION_ATTRIBUTE /* hidden, pdfium internal */ + + /* Sun */ + #elif defined( __SUNPRO_C ) && __SUNPRO_C >= 0x550 diff --git a/external/pdfium/inc/pch/precompiled_pdfium.hxx b/external/pdfium/inc/pch/precompiled_pdfium.hxx index 9f896ec61178..9b4a2399f282 100644 --- a/external/pdfium/inc/pch/precompiled_pdfium.hxx +++ b/external/pdfium/inc/pch/precompiled_pdfium.hxx @@ -13,7 +13,7 @@ manual changes will be rewritten by the next run of update_pch.sh (which presumably also fixes all possible problems, so it's usually better to use it). - Generated on 2026-02-19 12:36:16 using: + Generated on 2026-08-03 16:22:37 using: ./bin/update_pch external/pdfium pdfium --cutoff=1 --exclude:system --include:module --include:local If after updating build fails, use the following command to locate conflicting headers: @@ -36,8 +36,11 @@ #include #include #include +#include #include #include +#include +#include #include #include #include @@ -76,6 +79,7 @@ #include #include #include +#include #include #include #include @@ -92,22 +96,24 @@ #include #include #include +#include +#include #include #include #include #include #include #include -#include -#include #include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -197,7 +203,6 @@ #include #include #include -#include #include #include #include @@ -258,25 +263,25 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -287,12 +292,14 @@ #include #include #include +#include +#include #include #include +#include #include +#include #include -#include -#include #include #include #include @@ -325,7 +332,6 @@ #include #include #include -#include #include #include #include @@ -344,6 +350,7 @@ #include #include #include +#include #include #include #include @@ -356,11 +363,12 @@ #include #include #include +#include #include #include #include -#include #include +#include #include #include #include @@ -379,8 +387,10 @@ #include #include #include +#include #include -#include +#include +#include #include #include #include @@ -395,9 +405,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -480,6 +490,7 @@ #include #include #include +#include #include #include #include diff --git a/external/pdfium/system-icu.patch.1 b/external/pdfium/system-icu.patch.1 new file mode 100644 index 000000000000..13d3ea858632 --- /dev/null +++ b/external/pdfium/system-icu.patch.1 @@ -0,0 +1,33 @@ +From 9b6f23989c5da39bff4ce36df96d62f9cabeebbf Mon Sep 17 00:00:00 2001 +Date: Fri, 7 Aug 2026 14:36:14 -0700 +Subject: [PATCH] fxcrt: fix building against system ICU in cfx_bidi_resolver + +This was the only location which forgot to check for this define, +core/fxcrt/fx_extension.h:18 already did the same. + +Change-Id: I6efdd8c5a3322b146f9ccabcabd2ac2506912d85 +Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/154490 +Commit-Queue: Andy Phan +Reviewed-by: Lei Zhang +Reviewed-by: Andy Phan +--- + core/fxcrt/cfx_bidi_resolver.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/core/fxcrt/cfx_bidi_resolver.cpp b/core/fxcrt/cfx_bidi_resolver.cpp +index 50e302e35..efa585f38 100644 +--- a/core/fxcrt/cfx_bidi_resolver.cpp ++++ b/core/fxcrt/cfx_bidi_resolver.cpp +@@ -10,7 +10,12 @@ + #include "core/fxcrt/check_op.h" + #include "core/fxcrt/fx_safe_types.h" + #include "core/fxcrt/ptr_util.h" ++ ++#if defined(USE_SYSTEM_ICUUC) ++#include ++#else + #include "third_party/icu/source/common/unicode/ubidi.h" ++#endif + + void CFX_BidiResolver::UBiDiDeleter::operator()(UBiDi* bidi) const { + ubidi_close(bidi); diff --git a/external/poppler/disable-freetype.patch.1 b/external/poppler/disable-freetype.patch.1 index 49a76ec41426..26c9ca84c355 100644 --- a/external/poppler/disable-freetype.patch.1 +++ b/external/poppler/disable-freetype.patch.1 @@ -23,14 +23,14 @@ disable freetype dependent code #include // helper for using std::visit to get a dependent false for static_asserts -@@ -2723,6 +2723,8 @@ +@@ -2738,6 +2738,8 @@ Form::AddFontResult Form::addFontToDefaultResources(const std::string &filepath, int faceIndex, const std::string &fontFamily, const std::string &fontStyle, bool fontSubstitutedIn, bool forceName) { + return {}; +#if 0 if (!filepath.ends_with(".ttf") && !filepath.ends_with(".ttc") && !filepath.ends_with(".otf")) { - error(errIO, -1, "We only support embedding ttf/ttc/otf fonts for now. The font file for {0:s} {1:s} was {2:s}", fontFamily.c_str(), fontStyle.c_str(), filepath.c_str()); + error(errIO, -1, "We only support embedding ttf/ttc/otf fonts for now. The font file for {0:r} {1:r} was {2:r}", &fontFamily, &fontStyle, &filepath); return {}; @@ -2974,6 +2974,7 @@ } @@ -75,15 +75,15 @@ disable freetype dependent code SplashFTFontEngine &operator=(const SplashFTFontEngine &) = delete; // Load fonts. -- std::shared_ptr loadType1Font(std::unique_ptr idA, std::unique_ptr src, const char **enc, int faceIndex); -- std::shared_ptr loadType1CFont(std::unique_ptr idA, std::unique_ptr src, const char **enc, int faceIndex); -- std::shared_ptr loadOpenTypeT1CFont(std::unique_ptr idA, std::unique_ptr src, const char **enc, int faceIndex); +- std::shared_ptr loadType1Font(std::unique_ptr idA, std::unique_ptr src, const std::array &enc, int faceIndex); +- std::shared_ptr loadType1CFont(std::unique_ptr idA, std::unique_ptr src, const std::array &enc, int faceIndex); +- std::shared_ptr loadOpenTypeT1CFont(std::unique_ptr idA, std::unique_ptr src, const std::array &enc, int faceIndex); - std::shared_ptr loadCIDFont(std::unique_ptr idA, std::unique_ptr src, int faceIndex); - std::shared_ptr loadOpenTypeCFFFont(std::unique_ptr idA, std::unique_ptr src, std::vector &&codeToGID, int faceIndex); - std::shared_ptr loadTrueTypeFont(std::unique_ptr idA, std::unique_ptr src, std::vector &&codeToGID, int faceIndex); -+ std::shared_ptr loadType1Font(std::unique_ptr idA, std::unique_ptr src, const char **enc, int faceIndex) { return nullptr; }; -+ std::shared_ptr loadType1CFont(std::unique_ptr idA, std::unique_ptr src, const char **enc, int faceIndex) { return nullptr; }; -+ std::shared_ptr loadOpenTypeT1CFont(std::unique_ptr idA, std::unique_ptr src, const char **enc, int faceIndex) { return nullptr; }; ++ std::shared_ptr loadType1Font(std::unique_ptr idA, std::unique_ptr src, const std::array &enc, int faceIndex) { return nullptr; }; ++ std::shared_ptr loadType1CFont(std::unique_ptr idA, std::unique_ptr src, const std::array &enc, int faceIndex) { return nullptr; }; ++ std::shared_ptr loadOpenTypeT1CFont(std::unique_ptr idA, std::unique_ptr src, const std::array &enc, int faceIndex) { return nullptr; }; + std::shared_ptr loadCIDFont(std::unique_ptr idA, std::unique_ptr src, int faceIndex) { return nullptr; }; + std::shared_ptr loadOpenTypeCFFFont(std::unique_ptr idA, std::unique_ptr src, std::vector &&codeToGID, int faceIndex) { return nullptr; }; + std::shared_ptr loadTrueTypeFont(std::unique_ptr idA, std::unique_ptr src, std::vector &&codeToGID, int faceIndex) { return nullptr; }; diff --git a/external/poppler/poppler-config.patch.1 b/external/poppler/poppler-config.patch.1 index 3a1f2c1eb6ba..b6ace1d64f08 100644 --- a/external/poppler/poppler-config.patch.1 +++ b/external/poppler/poppler-config.patch.1 @@ -120,7 +120,7 @@ index 0fbd336a..451213f8 100644 +#define PACKAGE_NAME "poppler" + +/* Define to the full name and version of this package. */ -+#define PACKAGE_STRING "poppler 26.04.0" ++#define PACKAGE_STRING "poppler 26.06.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "poppler" @@ -129,7 +129,7 @@ index 0fbd336a..451213f8 100644 +#define PACKAGE_URL "" + +/* Define to the version of this package. */ -+#define PACKAGE_VERSION "26.04.0" ++#define PACKAGE_VERSION "26.06.0" + +/* Poppler data dir */ +#define POPPLER_DATADIR "/usr/local/share/poppler" @@ -144,7 +144,7 @@ index 0fbd336a..451213f8 100644 +#define USE_FLOAT 0 + +/* Version number of package */ -+#define VERSION "26.04.0" ++#define VERSION "26.06.0" + +#if defined(__APPLE__) +#elif defined (_WIN32) @@ -222,7 +222,7 @@ index 0fbd336a..451213f8 100644 +#define POPPLER_CONFIG_H + +/* Defines the poppler version. */ -+#define POPPLER_VERSION "26.04.0" ++#define POPPLER_VERSION "26.06.0" + +/* Use single precision arithmetic in the Splash backend */ +#define USE_FLOAT 0 @@ -310,9 +310,9 @@ index 0fbd336a..451213f8 100644 + +#include "poppler-global.h" + -+#define POPPLER_VERSION "26.04.0" ++#define POPPLER_VERSION "26.06.0" +#define POPPLER_VERSION_MAJOR 26 -+#define POPPLER_VERSION_MINOR 04 ++#define POPPLER_VERSION_MINOR 06 +#define POPPLER_VERSION_MICRO 0 + +namespace poppler diff --git a/external/python3/ExternalPackage_python3.mk b/external/python3/ExternalPackage_python3.mk index e145207040a1..3e0b8a02bc9f 100644 --- a/external/python3/ExternalPackage_python3.mk +++ b/external/python3/ExternalPackage_python3.mk @@ -725,7 +725,6 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_internal,\ Lib/pip/_internal/__init__.py \ - Lib/pip/_internal/build_env.py \ Lib/pip/_internal/cache.py \ Lib/pip/_internal/configuration.py \ Lib/pip/_internal/exceptions.py \ @@ -735,6 +734,15 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p Lib/pip/_internal/wheel_builder.py \ )) +$(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_internal/build_env,\ + Lib/pip/_internal/build_env/__init__.py \ + Lib/pip/_internal/build_env/base.py \ + Lib/pip/_internal/build_env/installer.py \ + Lib/pip/_internal/build_env/noop.py \ + Lib/pip/_internal/build_env/venv.py \ + Lib/pip/_internal/build_env/virtual.py \ +)) + $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_internal/cli,\ Lib/pip/_internal/cli/__init__.py \ Lib/pip/_internal/cli/autocompletion.py \ @@ -817,7 +825,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p Lib/pip/_internal/models/index.py \ Lib/pip/_internal/models/installation_report.py \ Lib/pip/_internal/models/link.py \ - Lib/pip/_internal/models/pylock.py \ + Lib/pip/_internal/models/release_control.py \ Lib/pip/_internal/models/scheme.py \ Lib/pip/_internal/models/search_scope.py \ Lib/pip/_internal/models/selection_prefs.py \ @@ -860,6 +868,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_internal/req,\ Lib/pip/_internal/req/__init__.py \ Lib/pip/_internal/req/constructors.py \ + Lib/pip/_internal/req/pep723.py \ Lib/pip/_internal/req/req_dependency_group.py \ Lib/pip/_internal/req/req_file.py \ Lib/pip/_internal/req/req_install.py \ @@ -908,6 +917,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p Lib/pip/_internal/utils/logging.py \ Lib/pip/_internal/utils/misc.py \ Lib/pip/_internal/utils/packaging.py \ + Lib/pip/_internal/utils/pylock.py \ Lib/pip/_internal/utils/retry.py \ Lib/pip/_internal/utils/subprocess.py \ Lib/pip/_internal/utils/temp_dir.py \ @@ -957,16 +967,6 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p Lib/pip/_vendor/certifi/core.py \ )) -$(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/dependency_groups,\ - Lib/pip/_vendor/dependency_groups/LICENSE.txt \ - Lib/pip/_vendor/dependency_groups/__init__.py \ - Lib/pip/_vendor/dependency_groups/__main__.py \ - Lib/pip/_vendor/dependency_groups/_implementation.py \ - Lib/pip/_vendor/dependency_groups/_lint_dependency_groups.py \ - Lib/pip/_vendor/dependency_groups/_pip_wrapper.py \ - Lib/pip/_vendor/dependency_groups/_toml_compat.py \ -)) - $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/distlib,\ Lib/pip/_vendor/distlib/LICENSE.txt \ Lib/pip/_vendor/distlib/__init__.py \ @@ -990,6 +990,8 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/idna,\ Lib/pip/_vendor/idna/__init__.py \ + Lib/pip/_vendor/idna/__main__.py \ + Lib/pip/_vendor/idna/cli.py \ Lib/pip/_vendor/idna/codec.py \ Lib/pip/_vendor/idna/compat.py \ Lib/pip/_vendor/idna/core.py \ @@ -1014,8 +1016,12 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p Lib/pip/_vendor/packaging/_parser.py \ Lib/pip/_vendor/packaging/_structures.py \ Lib/pip/_vendor/packaging/_tokenizer.py \ + Lib/pip/_vendor/packaging/dependency_groups.py \ + Lib/pip/_vendor/packaging/direct_url.py \ + Lib/pip/_vendor/packaging/errors.py \ Lib/pip/_vendor/packaging/markers.py \ Lib/pip/_vendor/packaging/metadata.py \ + Lib/pip/_vendor/packaging/pylock.py \ Lib/pip/_vendor/packaging/requirements.py \ Lib/pip/_vendor/packaging/specifiers.py \ Lib/pip/_vendor/packaging/tags.py \ @@ -1035,6 +1041,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/platformdirs,\ Lib/pip/_vendor/platformdirs/__init__.py \ Lib/pip/_vendor/platformdirs/__main__.py \ + Lib/pip/_vendor/platformdirs/_xdg.py \ Lib/pip/_vendor/platformdirs/android.py \ Lib/pip/_vendor/platformdirs/api.py \ Lib/pip/_vendor/platformdirs/macos.py \ @@ -1095,6 +1102,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p Lib/pip/_vendor/requests/__init__.py \ Lib/pip/_vendor/requests/__version__.py \ Lib/pip/_vendor/requests/_internal_utils.py \ + Lib/pip/_vendor/requests/_types.py \ Lib/pip/_vendor/requests/adapters.py \ Lib/pip/_vendor/requests/api.py \ Lib/pip/_vendor/requests/auth.py \ @@ -1231,7 +1239,9 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/urllib3,\ Lib/pip/_vendor/urllib3/LICENSE.txt \ Lib/pip/_vendor/urllib3/__init__.py \ + Lib/pip/_vendor/urllib3/_base_connection.py \ Lib/pip/_vendor/urllib3/_collections.py \ + Lib/pip/_vendor/urllib3/_request_methods.py \ Lib/pip/_vendor/urllib3/_version.py \ Lib/pip/_vendor/urllib3/connection.py \ Lib/pip/_vendor/urllib3/connectionpool.py \ @@ -1239,42 +1249,33 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p Lib/pip/_vendor/urllib3/fields.py \ Lib/pip/_vendor/urllib3/filepost.py \ Lib/pip/_vendor/urllib3/poolmanager.py \ - Lib/pip/_vendor/urllib3/request.py \ Lib/pip/_vendor/urllib3/response.py \ )) $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/urllib3/contrib,\ Lib/pip/_vendor/urllib3/contrib/__init__.py \ - Lib/pip/_vendor/urllib3/contrib/_appengine_environ.py \ - Lib/pip/_vendor/urllib3/contrib/appengine.py \ - Lib/pip/_vendor/urllib3/contrib/ntlmpool.py \ Lib/pip/_vendor/urllib3/contrib/pyopenssl.py \ - Lib/pip/_vendor/urllib3/contrib/securetransport.py \ Lib/pip/_vendor/urllib3/contrib/socks.py \ )) -$(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/urllib3/contrib/_securetransport,\ - Lib/pip/_vendor/urllib3/contrib/_securetransport/__init__.py \ - Lib/pip/_vendor/urllib3/contrib/_securetransport/bindings.py \ - Lib/pip/_vendor/urllib3/contrib/_securetransport/low_level.py \ +$(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/urllib3/contrib/emscripten,\ + Lib/pip/_vendor/urllib3/contrib/emscripten/__init__.py \ + Lib/pip/_vendor/urllib3/contrib/emscripten/connection.py \ + Lib/pip/_vendor/urllib3/contrib/emscripten/fetch.py \ + Lib/pip/_vendor/urllib3/contrib/emscripten/request.py \ + Lib/pip/_vendor/urllib3/contrib/emscripten/response.py \ )) -$(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/urllib3/packages,\ - Lib/pip/_vendor/urllib3/packages/__init__.py \ - Lib/pip/_vendor/urllib3/packages/six.py \ -)) - -$(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/urllib3/packages/backports,\ - Lib/pip/_vendor/urllib3/packages/backports/__init__.py \ - Lib/pip/_vendor/urllib3/packages/backports/makefile.py \ - Lib/pip/_vendor/urllib3/packages/backports/weakref_finalize.py \ +$(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/urllib3/http2,\ + Lib/pip/_vendor/urllib3/http2/__init__.py \ + Lib/pip/_vendor/urllib3/http2/connection.py \ + Lib/pip/_vendor/urllib3/http2/probe.py \ )) $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pip/_vendor/urllib3/util,\ Lib/pip/_vendor/urllib3/util/__init__.py \ Lib/pip/_vendor/urllib3/util/connection.py \ Lib/pip/_vendor/urllib3/util/proxy.py \ - Lib/pip/_vendor/urllib3/util/queue.py \ Lib/pip/_vendor/urllib3/util/request.py \ Lib/pip/_vendor/urllib3/util/response.py \ Lib/pip/_vendor/urllib3/util/retry.py \ @@ -1283,6 +1284,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p Lib/pip/_vendor/urllib3/util/ssltransport.py \ Lib/pip/_vendor/urllib3/util/timeout.py \ Lib/pip/_vendor/urllib3/util/url.py \ + Lib/pip/_vendor/urllib3/util/util.py \ Lib/pip/_vendor/urllib3/util/wait.py \ )) @@ -1293,6 +1295,7 @@ $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/p $(eval $(call gb_ExternalPackage_add_unpacked_files,python3,$(LIBO_BIN_FOLDER)/python-core-$(PYTHON_VERSION)/lib/pydoc_data,\ Lib/pydoc_data/__init__.py \ + Lib/pydoc_data/module_docs.py \ Lib/pydoc_data/topics.py \ )) diff --git a/external/python3/ExternalProject_python3.mk b/external/python3/ExternalProject_python3.mk index 462004d1d1e3..844fa5813801 100644 --- a/external/python3/ExternalProject_python3.mk +++ b/external/python3/ExternalProject_python3.mk @@ -39,11 +39,13 @@ ifeq ($(OS),WNT) $(call gb_ExternalProject_get_state_target,python3,build) : $(call gb_Trace_StartRange,python3,EXTERNAL) $(call gb_ExternalProject_run,build,\ - MAKEFLAGS= MSBuild.exe pcbuild.sln /t:Build $(gb_MSBUILD_CONFIG_AND_PLATFORM) \ + MAKEFLAGS= CL=-D_SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS \ + MSBuild.exe pcbuild.sln /t:Build $(gb_MSBUILD_CONFIG_AND_PLATFORM) \ /p:bz2Dir=$(gb_UnpackedTarball_workdir)/bzip2 \ /p:opensslIncludeDir=$(gb_UnpackedTarball_workdir)/openssl/include \ /p:opensslOutDir=$(gb_UnpackedTarball_workdir)/openssl \ /p:zlibDir=$(gb_UnpackedTarball_workdir)/zlib \ + /p:KillPython=false \ /p:sqlite3Dir=$(gb_UnpackedTarball_workdir)/sqlite3 \ /p:lzmaDir=$(gb_UnpackedTarball_workdir)/lzma/ \ /p:mpdecimalDir=$(gb_UnpackedTarball_workdir)/python3/Modules/_decimal/ \ @@ -88,6 +90,7 @@ endif $(call gb_ExternalProject_get_state_target,python3,build) : $(call gb_Trace_StartRange,python3,EXTERNAL) $(call gb_ExternalProject_run,build,\ + $(if $(SOURCE_DATE_EPOCH),export SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) &&) \ $(if $(filter MACOSX,$(OS)), \ $(if $(filter 10.8 10.9 10.10 10.11,$(MACOSX_DEPLOYMENT_TARGET)), \ ac_cv_func_getentropy=no \ @@ -101,9 +104,6 @@ $(call gb_ExternalProject_get_state_target,python3,build) : --prefix=/python-inst \ --with-system-expat \ $(if $(filter MACOSX,$(OS)), \ - $(if $(filter INTEL,$(CPUNAME)),--enable-universalsdk=$(MACOSX_SDK_PATH) \ - --with-universal-archs=intel \ - ) \ --enable-framework=/@__________________________________________________OOO --with-framework-name=LibreOfficePython, \ --enable-shared \ ) \ diff --git a/external/python3/UnpackedTarball_python3.mk b/external/python3/UnpackedTarball_python3.mk index 8543137f9a0b..2d57c81c956f 100644 --- a/external/python3/UnpackedTarball_python3.mk +++ b/external/python3/UnpackedTarball_python3.mk @@ -11,11 +11,17 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,python3)) $(eval $(call gb_UnpackedTarball_set_tarball,python3,$(PYTHON_TARBALL),,python3)) +# Since Python 3.11, _freeze_module.vcxproj needs python.exe to build deepfreeze.c on Windows # Since a wheel file is just a zip file, unzil them to the Lib directory with the other libraries $(eval $(call gb_UnpackedTarball_set_pre_action,python3,\ - cp PC/pyconfig.h.in PC/pyconfig.h && \ + $(if $(filter WNT,$(OS)), \ + mkdir -p externals/pythonx86 && \ + unzip -q -d externals/pythonx86 -o $(gb_UnpackedTarget_TARFILE_LOCATION)/$(PYTHON_BOOTSTRAP_TARBALL) && \ + chmod +x externals/pythonx86/tools/* && \ + cp PC/pyconfig.h.in PC/pyconfig.h && \ + ) \ unzip -q -d Lib/ -o Lib/test/wheeldata/setuptools-79.0.1-py3-none-any.whl && \ - unzip -q -d Lib/ -o Lib/ensurepip/_bundled/pip-25.3-py3-none-any.whl && \ + unzip -q -d Lib/ -o Lib/ensurepip/_bundled/pip-26.2.1-py3-none-any.whl && \ mv Lib/setuptools/_vendor/jaraco/text/Lorem\ ipsum.txt Lib/setuptools/_vendor/jaraco/text/Lorem_ipsum.txt \ )) @@ -39,6 +45,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,python3,\ external/python3/sqlite3.patch.1 \ external/python3/lzma.patch.1 \ external/python3/decimal.patch.1 \ + external/python3/destdir-darwin.patch.1 \ )) ifneq ($(filter DRAGONFLY FREEBSD LINUX NETBSD OPENBSD SOLARIS,$(OS)),) diff --git a/external/python3/destdir-darwin.patch.1 b/external/python3/destdir-darwin.patch.1 new file mode 100644 index 000000000000..43301aba991c --- /dev/null +++ b/external/python3/destdir-darwin.patch.1 @@ -0,0 +1,11 @@ +--- python3/Makefile.pre.in 2026-06-12 15:31:46.305166136 +0200 ++++ python3/Makefile.pre.in 2026-06-12 15:33:10.216862520 +0200 +@@ -955,7 +955,7 @@ + $(INSTALL) -d -m $(DIRMODE) $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION) + $(CC) -o $(LDLIBRARY) $(PY_CORE_LDFLAGS) -dynamiclib \ + -all_load $(LIBRARY) \ +- -install_name $(PYTHONFRAMEWORKINSTALLNAMEPREFIX)/$(PYTHONFRAMEWORK) \ ++ -install_name $(DESTDIR)$(PYTHONFRAMEWORKINSTALLNAMEPREFIX)/$(PYTHONFRAMEWORK) \ + -compatibility_version $(VERSION) \ + -current_version $(VERSION) \ + -framework CoreFoundation $(LIBS); diff --git a/external/python3/python-3.3.0-darwin.patch.1 b/external/python3/python-3.3.0-darwin.patch.1 index 67f27c78d776..5cc2671d6078 100644 --- a/external/python3/python-3.3.0-darwin.patch.1 +++ b/external/python3/python-3.3.0-darwin.patch.1 @@ -2,31 +2,6 @@ LO needs to build both against MacOSX SDK and not produce universal binaries. -diff -ru python3.orig/configure python3/configure ---- python3.orig/configure 2015-07-26 17:36:11.808497783 +0200 -+++ python3/configure 2015-07-26 17:38:49.016508337 +0200 -@@ -7385,7 +7385,20 @@ - then - case "$UNIVERSAL_ARCHS" in - 32-bit) -- UNIVERSAL_ARCH_FLAGS="-arch ppc -arch i386" -+ # LO does not use Universal Binaries (but the only way to set a SDK -+ # here implies that, so de-universalize here...) -+ case `/usr/bin/arch` in -+ i386) -+ UNIVERSAL_ARCH_FLAGS="-arch i386" -+ ;; -+ ppc) -+ UNIVERSAL_ARCH_FLAGS="" -+ ;; -+ *) -+ as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5 -+ ;; -+ esac -+ - LIPO_32BIT_FLAGS="" - ARCH_RUN_32BIT="" - ;; diff -ru python3.orig/Mac/Makefile.in python3/Mac/Makefile.in --- python3.orig/Mac/Makefile.in 2015-07-05 18:50:07.000000000 +0200 +++ python3/Mac/Makefile.in 2015-07-26 17:40:14.860514100 +0200 diff --git a/external/python3/ubsan.patch.0 b/external/python3/ubsan.patch.0 index 5947d3905797..0ae1e4abf281 100644 --- a/external/python3/ubsan.patch.0 +++ b/external/python3/ubsan.patch.0 @@ -65,10 +65,10 @@ for (index = tok->tok_mode_stack_index; index >= 0; --index) { mode = &(tok->tok_mode_stack[index]); -- mode->f_string_start = tok->buf + mode->f_string_start_offset; -- mode->f_string_multi_line_start = tok->buf + mode->f_string_multi_line_start_offset; -+ mode->f_string_start = (char *) (((intptr_t) tok->buf) + mode->f_string_start_offset); -+ mode->f_string_multi_line_start = (char *) (((intptr_t) tok->buf) + mode->f_string_multi_line_start_offset); +- mode->f_string_start = mode->f_string_start_offset < 0 ? NULL : tok->buf + mode->f_string_start_offset; +- mode->f_string_multi_line_start = mode->f_string_multi_line_start_offset < 0 ? NULL : tok->buf + mode->f_string_multi_line_start_offset; ++ mode->f_string_start = mode->f_string_start_offset < 0 ? NULL : (char *) (((intptr_t) tok->buf) + mode->f_string_start_offset); ++ mode->f_string_multi_line_start = mode->f_string_multi_line_start_offset < 0 ? NULL : (char *) (((intptr_t) tok->buf) + mode->f_string_multi_line_start_offset); } } diff --git a/sccomp/source/solver/solver.component.lpsolve b/external/quickjs/ExternalProject_quickjs.mk similarity index 58% rename from sccomp/source/solver/solver.component.lpsolve rename to external/quickjs/ExternalProject_quickjs.mk index 3b571fbc324d..a332be287dd7 100644 --- a/sccomp/source/solver/solver.component.lpsolve +++ b/external/quickjs/ExternalProject_quickjs.mk @@ -1,7 +1,12 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# # This file is part of the LibreOffice project. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +# -com.sun.star.comp.Calc.LpsolveSolver +$(eval $(call gb_ExternalProject_ExternalProject,quickjs)) + +# vim: set noet sw=4 ts=4: diff --git a/external/quickjs/Module_quickjs.mk b/external/quickjs/Module_quickjs.mk new file mode 100644 index 000000000000..ddc0f37465ba --- /dev/null +++ b/external/quickjs/Module_quickjs.mk @@ -0,0 +1,18 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Module_Module,quickjs)) + +$(eval $(call gb_Module_add_targets,quickjs,\ + StaticLibrary_quickjs \ + ExternalProject_quickjs \ + UnpackedTarball_quickjs \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/external/quickjs/StaticLibrary_quickjs.mk b/external/quickjs/StaticLibrary_quickjs.mk new file mode 100644 index 000000000000..25934e6bab16 --- /dev/null +++ b/external/quickjs/StaticLibrary_quickjs.mk @@ -0,0 +1,26 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_StaticLibrary_StaticLibrary,quickjs)) + +$(eval $(call gb_StaticLibrary_use_unpacked,quickjs,quickjs)) + +$(eval $(call gb_StaticLibrary_set_warnings_disabled,quickjs)) + +$(eval $(call gb_StaticLibrary_add_generated_cobjects,quickjs, \ + UnpackedTarball/quickjs/quickjs-amalgam \ +)) + +ifeq ($(OS),WNT) +$(eval $(call gb_StaticLibrary_add_cflags,quickjs,\ + /std:c17 /experimental:c11atomics \ +)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/UnpackedTarball_caprasimo.mk b/external/quickjs/UnpackedTarball_quickjs.mk similarity index 55% rename from external/more_fonts/UnpackedTarball_caprasimo.mk rename to external/quickjs/UnpackedTarball_quickjs.mk index 41d6d796ced9..248440955a5d 100644 --- a/external/more_fonts/UnpackedTarball_caprasimo.mk +++ b/external/quickjs/UnpackedTarball_quickjs.mk @@ -1,4 +1,4 @@ -# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- # # This file is part of the LibreOffice project. # @@ -7,8 +7,8 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # -$(eval $(call gb_UnpackedTarball_UnpackedTarball,font_caprasimo)) +$(eval $(call gb_UnpackedTarball_UnpackedTarball,quickjs)) -$(eval $(call gb_UnpackedTarball_set_tarball,font_caprasimo,$(FONT_CAPRASIMO_TARBALL),0)) +$(eval $(call gb_UnpackedTarball_set_tarball,quickjs,$(QUICKJS_TARBALL),0,quickjs)) # vim: set noet sw=4 ts=4: diff --git a/external/redland/UnpackedTarball_raptor.mk b/external/redland/UnpackedTarball_raptor.mk index 26c681b344a3..8491e104cc41 100644 --- a/external/redland/UnpackedTarball_raptor.mk +++ b/external/redland/UnpackedTarball_raptor.mk @@ -32,6 +32,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,raptor,\ $(if $(SYSTEM_ICU),,external/redland/raptor/raptor-icu.patch) \ external/redland/raptor/disable-libxml-cleanup.patch.1 \ external/redland/raptor/CVE-2024-57823.patch.1 \ + external/redland/raptor/raptor-backport-unreleased-fixes.patch.1 \ )) # vim: set noet sw=4 ts=4: diff --git a/external/redland/UnpackedTarball_redland.mk b/external/redland/UnpackedTarball_redland.mk index 31ebcb8f2f0a..ed589b2d6b9a 100644 --- a/external/redland/UnpackedTarball_redland.mk +++ b/external/redland/UnpackedTarball_redland.mk @@ -34,6 +34,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,redland,\ external/redland/redland/clang-cl.patch \ external/redland/redland/libtool.patch \ external/redland/redland/ubsan.patch \ + external/redland/redland/hash-memory-key-deref.patch \ )) # vim: set noet sw=4 ts=4: diff --git a/external/redland/raptor/raptor-backport-unreleased-fixes.patch.1 b/external/redland/raptor/raptor-backport-unreleased-fixes.patch.1 new file mode 100644 index 000000000000..7683ca73a44f --- /dev/null +++ b/external/redland/raptor/raptor-backport-unreleased-fixes.patch.1 @@ -0,0 +1,58 @@ +--- a/src/raptor_ntriples.c ++++ b/src/raptor_ntriples.c +@@ -212,7 +212,7 @@ raptor_ntriples_parse_term_internal(raptor_world* world, + locator->column--; + locator->byte--; + } +- if(term_class == RAPTOR_TERM_CLASS_BNODEID && dest[-1] == '.') { ++ if(term_class == RAPTOR_TERM_CLASS_BNODEID && position > 0 && dest[-1] == '.') { + /* If bnode id ended on '.' move back one */ + dest--; + +--- a/src/raptor_rfc2396.c ++++ b/src/raptor_rfc2396.c +@@ -351,6 +351,10 @@ raptor_uri_normalize_path(unsigned char* path_buffer, size_t path_len) + *dest++ = *s++; + *dest = '\0'; + path_len -= len; ++ if(path_len <= 0) { ++ *path_buffer = '\0'; ++ return 0; ++ } + + if(p && p < prev) { + /* We know the previous prev path component and we didn't do +@@ -390,6 +394,10 @@ raptor_uri_normalize_path(unsigned char* path_buffer, size_t path_len) + /* Remove /.. at the end of the path */ + *prev = '\0'; + path_len -= (s-prev); ++ if(path_len <= 0) { ++ *path_buffer = '\0'; ++ return 0; ++ } + } + + +--- a/src/raptor_term.c ++++ b/src/raptor_term.c +@@ -209,10 +209,16 @@ raptor_new_term_from_counted_literal(raptor_world* world, + } + + l = new_language; +- while((c = *language++)) { +- if(c == '_') +- c = '-'; +- *l++ = c; ++ { ++ size_t i; ++ for(i = 0; i < language_len; i++) { ++ c = *language++; ++ if(!c) ++ break; ++ if(c == '_') ++ c = '-'; ++ *l++ = c; ++ } + } + *l = '\0'; + } else diff --git a/external/redland/redland/hash-memory-key-deref.patch b/external/redland/redland/hash-memory-key-deref.patch new file mode 100644 index 000000000000..b78209373068 --- /dev/null +++ b/external/redland/redland/hash-memory-key-deref.patch @@ -0,0 +1,11 @@ +--- src/rdf_hash_memory.c ++++ src/rdf_hash_memory.c +@@ -910,7 +910,7 @@ + + node=next; + while(node) { +- if(key->size == node->key_len && !memcmp(key, node->key, key->size)){ ++ if(key->size == node->key_len && !memcmp(key->data, node->key, key->size)){ + found=1; + break; + } diff --git a/external/rhino/ExternalProject_rhino.mk b/external/rhino/ExternalProject_rhino.mk index 8d29bf284de0..83966016ceba 100644 --- a/external/rhino/ExternalProject_rhino.mk +++ b/external/rhino/ExternalProject_rhino.mk @@ -27,7 +27,7 @@ $(call gb_ExternalProject_get_state_target,rhino,build) : $(gb_UnpackedTarball_workdir)/rhino/NOTICE-tools.txt \ $(gb_UnpackedTarball_workdir)/rhino/NOTICE.txt \ $(gb_UnpackedTarball_workdir)/rhino/build/content/META-INF/ \ - && $(gb_Jar_JARCOMMAND) -cf $(gb_UnpackedTarball_workdir)/rhino/build/js.jar \ + && $(gb_Jar_JARCOMMAND) -c -f $(gb_UnpackedTarball_workdir)/rhino/build/js.jar \ -C $(gb_UnpackedTarball_workdir)/rhino/build/content . \ -C $(gb_UnpackedTarball_workdir)/rhino/src \ org/mozilla/javascript/commonjs/module/package.html \ diff --git a/external/skia/0002-loong64-Honor-existing-LASX-LSX-settings.patch b/external/skia/0002-loong64-Honor-existing-LASX-LSX-settings.patch index 2f5b2a3d87c4..fe257d5d079b 100644 --- a/external/skia/0002-loong64-Honor-existing-LASX-LSX-settings.patch +++ b/external/skia/0002-loong64-Honor-existing-LASX-LSX-settings.patch @@ -34,10 +34,10 @@ diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h index d12968d876b5..27a00474e07b 100644 --- a/src/opts/SkRasterPipeline_opts.h +++ b/src/opts/SkRasterPipeline_opts.h -@@ -69,7 +69,7 @@ using NoCtx = const void*; +@@ -75,7 +75,7 @@ - #if defined(SKRP_CPU_SCALAR) || defined(SKRP_CPU_NEON) || defined(SKRP_CPU_HSW) || \ - defined(SKRP_CPU_SKX) || defined(SKRP_CPU_AVX) || defined(SKRP_CPU_SSE41) || \ + #if defined(SKRP_CPU_SCALAR) || defined(SKRP_CPU_NEON) || defined(SKRP_CPU_AVX2) || \ + defined(SKRP_CPU_ML4) || defined(SKRP_CPU_AVX) || defined(SKRP_CPU_SSE41) || \ - defined(SKRP_CPU_SSE2) + defined(SKRP_CPU_SSE2) || defined(SKRP_CPU_LASX) || defined(SKRP_CPU_LSX) // Honor the existing setting diff --git a/external/skia/0004-loong64-Fix-the-remaining-implicit-vector-casts.patch b/external/skia/0004-loong64-Fix-the-remaining-implicit-vector-casts.patch index 722b9f3e3bff..8bf435d54305 100644 --- a/external/skia/0004-loong64-Fix-the-remaining-implicit-vector-casts.patch +++ b/external/skia/0004-loong64-Fix-the-remaining-implicit-vector-casts.patch @@ -362,16 +362,7 @@ index 42e9cd8aa229..97dfe7213d42 100644 fr = gather((int *)c->factors[0], i0, i1, i2, i3); br = gather((int *)c->biases[0], i0, i1, i2, i3); fg = gather((int *)c->factors[1], i0, i1, i2, i3); -@@ -5942,7 +5940,7 @@ SI void from_8888(U32 rgba, U16* r, U16* g, U16* b, U16* a) { - split(v, &_02,&_13); - __m256i tmp0 = __lasx_xvsat_wu(_02, 15); - __m256i tmp1 = __lasx_xvsat_wu(_13, 15); -- return __lasx_xvpickev_h(tmp1, tmp0); -+ return (U16)__lasx_xvpickev_h(tmp1, tmp0); - }; - #elif defined(SKRP_CPU_LSX) - __m128i _01, _23, rg, ba; -@@ -5952,10 +5950,10 @@ SI void from_8888(U32 rgba, U16* r, U16* g, U16* b, U16* a) { +@@ -6133,10 +6133,10 @@ __m128i mask_00ff = __lsx_vreplgr2vr_h(0xff); @@ -384,8 +375,17 @@ index 42e9cd8aa229..97dfe7213d42 100644 + *b = (U16)__lsx_vand_v(ba, mask_00ff); + *a = (U16)__lsx_vsrli_h(ba, 8); #else - auto cast_U16 = [](U32 v) -> U16 { - return cast(v); + #if defined(SKRP_CPU_AVX2) + // Swap the middle 128-bit lanes to make _mm256_packus_epi32() in cast_U16() work out nicely. +@@ -6163,7 +6163,7 @@ + split(v, &_02, &_13); + __m256i tmp0 = __lasx_xvsat_wu(_02, 15); + __m256i tmp1 = __lasx_xvsat_wu(_13, 15); +- return __lasx_xvpickev_h(tmp1, tmp0); ++ return (U16)__lasx_xvpickev_h(tmp1, tmp0); + }; + #else + auto cast_U16 = [](U32 v) -> U16 { @@ -5983,26 +5981,26 @@ SI void load_8888_(const uint32_t* ptr, U16* r, U16* g, U16* b, U16* a) { SI void store_8888_(uint32_t* ptr, U16 r, U16 g, U16 b, U16 a) { #if defined(SKRP_CPU_LSX) diff --git a/external/skia/Library_skia.mk b/external/skia/Library_skia.mk index 4eb075cfc155..889dc0e202ed 100644 --- a/external/skia/Library_skia.mk +++ b/external/skia/Library_skia.mk @@ -20,9 +20,9 @@ $(eval $(call gb_Library_use_clang,skia)) $(eval $(call gb_Library_add_defs,skia,\ -DSKIA_IMPLEMENTATION=1 \ -DSKIA_DLL \ - -DSK_USER_CONFIG_HEADER="<$(BUILDDIR)/config_host/config_skia.h>" \ - $(if $(filter INTEL,$(CPUNAME)),$(if $(filter WNT,$(OS)),-DSK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSE2,-DSK_CPU_SSE_LEVEL=0)) \ - $(if $(filter X86_64,$(CPUNAME)),-DSK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSE2) \ + -DSK_USER_CONFIG_HEADER="" \ + $(if $(filter INTEL,$(CPUNAME)),$(if $(filter WNT,$(OS)),-DSK_CPU_X64_LEVEL=SK_CPU_X64_LEVEL_SSE2,-DSK_CPU_X64_LEVEL=0)) \ + $(if $(filter X86_64,$(CPUNAME)),-DSK_CPU_X64_LEVEL=SK_CPU_X64_LEVEL_SSE2) \ -DSK_ENABLE_SKSL_IN_RASTER_PIPELINE \ )) @@ -500,6 +500,7 @@ $(eval $(call gb_Library_add_generated_exception_objects,skia,\ UnpackedTarball/skia/src/core/SkPathUtils \ UnpackedTarball/skia/src/core/SkPath_serial \ UnpackedTarball/skia/src/core/SkPixelRef \ + UnpackedTarball/skia/src/core/SkPixelStorage \ UnpackedTarball/skia/src/core/SkPixmap \ UnpackedTarball/skia/src/core/SkPixmapDraw \ UnpackedTarball/skia/src/core/SkPoint \ @@ -1069,6 +1070,7 @@ $(eval $(call gb_Library_add_generated_exception_objects,skia,\ UnpackedTarball/skia/src/gpu/ganesh/gradients/GrGradientBitmapCache \ UnpackedTarball/skia/src/gpu/ganesh/gradients/GrGradientShader \ UnpackedTarball/skia/src/gpu/ganesh/image/GrImageUtils \ + UnpackedTarball/skia/src/gpu/ganesh/image/GrMippedBitmap \ UnpackedTarball/skia/src/gpu/ganesh/image/GrTextureGenerator \ UnpackedTarball/skia/src/gpu/ganesh/image/SkImage_Ganesh \ UnpackedTarball/skia/src/gpu/ganesh/image/SkImage_GaneshBase \ @@ -1077,6 +1079,7 @@ $(eval $(call gb_Library_add_generated_exception_objects,skia,\ UnpackedTarball/skia/src/gpu/ganesh/image/SkImage_LazyTexture \ UnpackedTarball/skia/src/gpu/ganesh/image/SkImage_RasterPinnable \ UnpackedTarball/skia/src/gpu/ganesh/image/SkSpecialImage_Ganesh \ + UnpackedTarball/skia/src/gpu/ganesh/mock/GrMockBackendSurface \ UnpackedTarball/skia/src/gpu/ganesh/mock/GrMockCaps \ UnpackedTarball/skia/src/gpu/ganesh/mock/GrMockGpu \ UnpackedTarball/skia/src/gpu/ganesh/mock/GrMockTypes \ @@ -1319,9 +1322,9 @@ $(eval $(call gb_Library_add_generated_exception_objects,skia,\ $(LO_SKIA_AVOID_INLINE_COPIES) \ )) $(eval $(call gb_Library_add_generated_exception_objects,skia,\ - UnpackedTarball/skia/src/opts/SkOpts_hsw \ - UnpackedTarball/skia/src/core/SkSwizzler_opts_hsw \ - UnpackedTarball/skia/src/core/SkBlitRow_opts_hsw \ + UnpackedTarball/skia/src/opts/SkOpts_ml3 \ + UnpackedTarball/skia/src/core/SkSwizzler_opts_ml3 \ + UnpackedTarball/skia/src/core/SkBlitRow_opts_ml3 \ UnpackedTarball/skia/modules/skcms/src/skcms_TransformHsw, \ $(CXXFLAGS_INTRINSICS_AVX2) $(CXXFLAGS_INTRINSICS_F16C) $(CXXFLAGS_INTRINSICS_FMA) \ $(LO_CLANG_CXXFLAGS_INTRINSICS_AVX2) $(LO_CLANG_CXXFLAGS_INTRINSICS_F16C) $(LO_CLANG_CXXFLAGS_INTRINSICS_FMA) \ @@ -1358,6 +1361,11 @@ $(eval $(call gb_Library_add_cxxflags,skia, \ endif endif +#TODO: Drop this once Clang supports -std=c++29: +ifneq ($(filter -std=c++29,$(CXXFLAGS_CXX11)),) +$(eval $(call gb_Library_add_cxxflags,skia,-std=c++2d)) +endif + # Skcms code is used by png writer, which is used by SkiaHelper::dump(). Building # this without optimizations would mean having each pixel of saved images be # processed by unoptimized code. diff --git a/external/skia/source/skia_opts.cxx b/external/skia/source/skia_opts.cxx index 4dbc2c214e01..1986555b36c8 100644 --- a/external/skia/source/skia_opts.cxx +++ b/external/skia/source/skia_opts.cxx @@ -40,7 +40,7 @@ void SkConvertRGBAToR(uint8_t* dest, const uint32_t* src, int count) // The rest is mostly based on Skia's SkOpts.cpp, reduced to only SSSE3 so far. -#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3 +#if SK_CPU_X64_LEVEL >= SK_CPU_X64_LEVEL_SSSE3 #define SK_OPTS_NS ssse3 #else #define SK_OPTS_NS portable @@ -64,8 +64,8 @@ namespace SkLoOpts { static void init() { #if !defined(SK_BUILD_NO_OPTS) #if defined(SK_CPU_X86) - #if SK_CPU_SSE_LEVEL < SK_CPU_SSE_LEVEL_SSSE3 - if (SkCpu::Supports(SkCpu::SSSE3)) { Init_ssse3(); } + #if SK_CPU_X64_LEVEL < SK_CPU_X64_LEVEL_SSSE3 + if (SkCpu::Supports(SkX64::SSSE3)) { Init_ssse3(); } #endif #endif #endif diff --git a/external/skia/source/skia_opts_internal.hxx b/external/skia/source/skia_opts_internal.hxx index c8c86ca4da5d..29590a39be21 100644 --- a/external/skia/source/skia_opts_internal.hxx +++ b/external/skia/source/skia_opts_internal.hxx @@ -5,7 +5,7 @@ #pragma once -#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3 +#if SK_CPU_X64_LEVEL >= SK_CPU_X64_LEVEL_SSSE3 #include #endif @@ -25,7 +25,7 @@ static void RGB1_to_R_portable(uint8_t dst[], const uint32_t* src, int count) { } } -#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3 +#if SK_CPU_X64_LEVEL >= SK_CPU_X64_LEVEL_SSSE3 inline void RGB1_to_RGB(uint8_t dst[], const uint32_t* src, int count) { const uint8_t X = 0xFF; // Used a placeholder. The value of X is irrelevant. __m128i pack = _mm_setr_epi8(0,1,2, 4,5,6, 8,9,10, 12,13,14, X,X,X,X); diff --git a/external/xmlsec/UnpackedTarball_xmlsec.mk b/external/xmlsec/UnpackedTarball_xmlsec.mk index 6a8bdad73d6e..c96527e29cb7 100644 --- a/external/xmlsec/UnpackedTarball_xmlsec.mk +++ b/external/xmlsec/UnpackedTarball_xmlsec.mk @@ -13,8 +13,4 @@ $(eval $(call gb_UnpackedTarball_set_tarball,xmlsec,$(XMLSEC_TARBALL),,xmlsec)) $(eval $(call gb_UnpackedTarball_update_autoconf_configs,xmlsec)) -$(eval $(call gb_UnpackedTarball_add_patches,xmlsec,\ - external/xmlsec/xmlsec-msvc.patch \ -)) - # vim: set noet sw=4 ts=4: diff --git a/external/xmlsec/xmlsec-msvc.patch b/external/xmlsec/xmlsec-msvc.patch deleted file mode 100644 index b4a0006250eb..000000000000 --- a/external/xmlsec/xmlsec-msvc.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- xmlsec/win32/Makefile.msvc 2026-03-30 14:53:44.477606963 +0200 -+++ xmlsec/win32/Makefile.msvc 2026-03-30 14:54:59.101302260 +0200 -@@ -502,7 +502,11 @@ - LDFLAGS = $(LDFLAGS) /WX - !endif - -+!if "$(MSVC_USE_DEBUG_RUNTIME)" == "TRUE" -+SOLIBS = $(LIBS) libxml2d.lib bcrypt.lib ws2_32.lib -+!else - SOLIBS = $(LIBS) libxml2.lib bcrypt.lib ws2_32.lib -+!endif - ALIBS = $(LIBS) libxml2s.lib bcrypt.lib ws2_32.lib - - !if "$(WITH_ICONV)" == "1" - diff --git a/external/zxing/0001-Silence-deprecated-declarations-warnings-on-Windows-.patch b/external/zxing/0001-Silence-deprecated-declarations-warnings-on-Windows-.patch deleted file mode 100644 index ca1b73e76d4a..000000000000 --- a/external/zxing/0001-Silence-deprecated-declarations-warnings-on-Windows-.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 9fb2ecdd5209ca22823b143b66e7123da8e66a76 Mon Sep 17 00:00:00 2001 -From: Xisco Fauli -Date: Mon, 2 Mar 2026 20:48:22 +0100 -Subject: [PATCH] Silence deprecated-declarations warnings on Windows too - -Seen when building zxing-cpp as an external library in LibreOffice -E:\jenkins\workspace\gerrit_windows_wsl\workdir\UnpackedTarball\zxing\core\src\ReaderOptions.h(173): error C2220: the following warning is treated as an error -E:\jenkins\workspace\gerrit_windows_wsl\workdir\UnpackedTarball\zxing\core\src\ReaderOptions.h(173): warning C4996: 'ZXing::ReaderOptions::tryCode39ExtendedMode': was declared deprecated -E:\jenkins\workspace\gerrit_windows_wsl\workdir\UnpackedTarball\zxing\core\src\ReaderOptions.h(176): warning C4996: 'ZXing::ReaderOptions::validateCode39CheckSum': was declared deprecated -E:\jenkins\workspace\gerrit_windows_wsl\workdir\UnpackedTarball\zxing\core\src\ReaderOptions.h(180): warning C4996: 'ZXing::ReaderOptions::validateITFCheckSum': was declared deprecated ---- - core/src/ReaderOptions.h | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/core/src/ReaderOptions.h b/core/src/ReaderOptions.h -index 9804faf1..509637e0 100644 ---- a/core/src/ReaderOptions.h -+++ b/core/src/ReaderOptions.h -@@ -156,10 +156,13 @@ public: - - #undef ZX_PROPERTY - -- // Silence deprecated-declarations warnings, only happening here for deprecated inline functions and only with GCC -+ // Silence deprecated-declarations warnings, only happening here for deprecated inline functions - #ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -+#elif defined(_MSC_VER) -+#pragma warning(push) -+#pragma warning(disable : 4996) - #endif - - #define ZX_DEPRECATED_PROPERTY(TYPE, NAME, SETTER, GET_IMPL, SET_IMPL) \ -@@ -183,6 +186,8 @@ public: - - #ifdef __GNUC__ - #pragma GCC diagnostic pop -+#elif defined(_MSC_VER) -+#pragma warning(pop) - #endif - - #ifdef ZXING_INTERNAL --- -2.39.5 - diff --git a/external/zxing/0001-TextEncoder-add-missing-include-Version.h.patch b/external/zxing/0001-TextEncoder-add-missing-include-Version.h.patch deleted file mode 100644 index 4af4a326e4b0..000000000000 --- a/external/zxing/0001-TextEncoder-add-missing-include-Version.h.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 475a022e0c85edfc58b525bb7debe40df455b380 Mon Sep 17 00:00:00 2001 -From: axxel -Date: Tue, 3 Mar 2026 13:23:16 +0100 -Subject: [PATCH] TextEncoder: add missing #include "Version.h" - -Fails to compile with -DZXING_READERS=OFF -DZXING_WRITERS=NEW and without -precompiled headers. - -Thanks to @x1sc0 for reporting this (showed up in LibreOffice's own build -system). ---- - core/src/TextEncoder.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/core/src/TextEncoder.cpp b/core/src/TextEncoder.cpp -index 06dc524d..afcaef85 100644 ---- a/core/src/TextEncoder.cpp -+++ b/core/src/TextEncoder.cpp -@@ -9,6 +9,8 @@ - #include "ECI.h" - #include "Utf.h" - #include "ZXAlgorithms.h" -+#include "Version.h" -+ - #ifdef ZXING_USE_ZINT - #include - #else --- -2.39.5 - diff --git a/external/zxing/0001-add-ZXVersion-h.patch b/external/zxing/0001-add-ZXVersion-h.patch index 84c9b2e2fdb5..77e818aaba77 100644 --- a/external/zxing/0001-add-ZXVersion-h.patch +++ b/external/zxing/0001-add-ZXVersion-h.patch @@ -27,8 +27,8 @@ + +// Version numbering +#define ZXING_VERSION_MAJOR 3 -+#define ZXING_VERSION_MINOR 0 -+#define ZXING_VERSION_PATCH 2 ++#define ZXING_VERSION_MINOR 1 ++#define ZXING_VERSION_PATCH 0 +#define ZXING_VERSION_SUFFIX "" + -+#define ZXING_VERSION_STR "3.0.2" ++#define ZXING_VERSION_STR "3.1.0" diff --git a/external/zxing/StaticLibrary_zxing.mk b/external/zxing/StaticLibrary_zxing.mk index 6f7ffa51a1ad..6656b89585e6 100644 --- a/external/zxing/StaticLibrary_zxing.mk +++ b/external/zxing/StaticLibrary_zxing.mk @@ -44,8 +44,6 @@ $(eval $(call gb_StaticLibrary_add_generated_exception_objects,zxing,\ UnpackedTarball/zxing/core/src/ECI \ UnpackedTarball/zxing/core/src/Error \ UnpackedTarball/zxing/core/src/GTIN \ - UnpackedTarball/zxing/core/src/GenericGF \ - UnpackedTarball/zxing/core/src/GenericGFPoly \ UnpackedTarball/zxing/core/src/GlobalHistogramBinarizer \ UnpackedTarball/zxing/core/src/GridSampler \ UnpackedTarball/zxing/core/src/HRI \ @@ -55,8 +53,6 @@ $(eval $(call gb_StaticLibrary_add_generated_exception_objects,zxing,\ UnpackedTarball/zxing/core/src/MultiFormatWriter \ UnpackedTarball/zxing/core/src/PerspectiveTransform \ UnpackedTarball/zxing/core/src/ReadBarcode \ - UnpackedTarball/zxing/core/src/ReedSolomonDecoder \ - UnpackedTarball/zxing/core/src/ReedSolomonEncoder \ UnpackedTarball/zxing/core/src/ResultPoint \ UnpackedTarball/zxing/core/src/TextDecoder \ UnpackedTarball/zxing/core/src/TextEncoder \ @@ -70,7 +66,6 @@ $(eval $(call gb_StaticLibrary_add_generated_exception_objects,zxing,\ UnpackedTarball/zxing/core/src/maxicode/MCReader \ UnpackedTarball/zxing/core/src/oned/ODCodabarReader \ UnpackedTarball/zxing/core/src/oned/ODCodabarWriter \ - UnpackedTarball/zxing/core/src/oned/ODCode128Patterns \ UnpackedTarball/zxing/core/src/oned/ODCode128Reader \ UnpackedTarball/zxing/core/src/oned/ODCode128Writer \ UnpackedTarball/zxing/core/src/oned/ODCode39Reader \ @@ -130,6 +125,7 @@ $(eval $(call gb_StaticLibrary_add_generated_cobjects,zxing,\ UnpackedTarball/zxing/core/src/libzint/rss \ UnpackedTarball/zxing/core/src/libzint/stubs \ UnpackedTarball/zxing/core/src/libzint/svg \ + UnpackedTarball/zxing/core/src/libzint/telepen \ UnpackedTarball/zxing/core/src/libzint/upcean \ UnpackedTarball/zxing/core/src/libzint/vector \ )) diff --git a/external/zxing/UnpackedTarball_zxing.mk b/external/zxing/UnpackedTarball_zxing.mk index 0917df80f142..c1f754bcfede 100644 --- a/external/zxing/UnpackedTarball_zxing.mk +++ b/external/zxing/UnpackedTarball_zxing.mk @@ -13,10 +13,6 @@ $(eval $(call gb_UnpackedTarball_set_tarball,zxing,$(ZXING_TARBALL))) $(eval $(call gb_UnpackedTarball_add_patches,zxing, \ external/zxing/0001-add-ZXVersion-h.patch \ - external/zxing/cassert.patch \ - external/zxing/0001-Silence-deprecated-declarations-warnings-on-Windows-.patch \ - external/zxing/macOS14.patch \ - external/zxing/0001-TextEncoder-add-missing-include-Version.h.patch \ )) # vim: set noet sw=4 ts=4: diff --git a/external/zxing/cassert.patch b/external/zxing/cassert.patch deleted file mode 100644 index d244807dadac..000000000000 --- a/external/zxing/cassert.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/core/src/Content.cpp 2026-02-27 12:01:25.753592314 +0100 -+++ b/core/src/Content.cpp 2026-02-27 12:01:38.773532220 +0100 -@@ -18,6 +18,7 @@ - #endif - - #include -+#include - - namespace ZXing { - diff --git a/external/zxing/macOS14.patch b/external/zxing/macOS14.patch deleted file mode 100644 index e4278d0c4a81..000000000000 --- a/external/zxing/macOS14.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/core/src/CreateBarcode.cpp 2026-03-03 14:41:48.255770172 +0100 -+++ b/core/src/CreateBarcode.cpp 2026-03-03 14:42:12.911576522 +0100 -@@ -45,6 +45,10 @@ - // structured_append (idx, cnt, ID) - - mutable unique_zint_symbol zint; -+ -+#ifndef __cpp_aggregate_paren_init // make XCode 14.x happy -+ Data(BarcodeFormat format, std::string options) : format(format), options(std::move(options)) {} -+#endif - }; - - // TODO: check return type diff --git a/extras/CustomTarget_autocorr.mk b/extras/CustomTarget_autocorr.mk index 6fcbc2c66481..2942ada0796e 100644 --- a/extras/CustomTarget_autocorr.mk +++ b/extras/CustomTarget_autocorr.mk @@ -282,6 +282,7 @@ $(gb_CustomTarget_workdir)/extras/source/autocorr/acor_%.dat : \ $(autocorr_PYTHONCOMMAND) $(SRCDIR)/bin/check-autocorr.py DocumentList.xml && \ $(call gb_Helper_wsl_path,$(WSL) zip -q0X --filesync --must-match $@ mimetype) && \ $(call gb_Helper_wsl_path,$(WSL) zip -qrX --must-match $@ $(call extras_AUTOCORR_XMLFILES_LANG,$(call extras_AUTOCORR_SHORTLANG,$*))) \ + $(call gb_Helper_make_zip_deterministic,$@) \ ) $(call gb_Trace_EndRange,autocorr/acor_$*.dat,ZIP) diff --git a/extras/CustomTarget_autotextshare.mk b/extras/CustomTarget_autotextshare.mk index 0c79da5da6ed..158cc30bc52c 100644 --- a/extras/CustomTarget_autotextshare.mk +++ b/extras/CustomTarget_autotextshare.mk @@ -3670,6 +3670,7 @@ $(gb_CustomTarget_workdir)/extras/source/autotext/share/%.bau : \ $(call gb_Helper_wsl_path,\ $(WSL) zip -q0X --filesync --must-match $@ mimetype && \ $(WSL) zip -qrX --must-match $@ $(call extras_AUTOTEXTSHARE_XMLFILES_RELATIVE,$*)) \ + $(call gb_Helper_make_zip_deterministic,$@) \ ) $(call gb_Trace_EndRange,autotext/$*.bau,ZIP) diff --git a/extras/CustomTarget_autotextuser.mk b/extras/CustomTarget_autotextuser.mk index f81fb07250ad..bfe4d10e023d 100644 --- a/extras/CustomTarget_autotextuser.mk +++ b/extras/CustomTarget_autotextuser.mk @@ -44,6 +44,7 @@ $(gb_CustomTarget_workdir)/extras/source/autotext/user/%.bau : \ $(call gb_Helper_wsl_path,\ $(WSL) zip -q0X --filesync --must-match $@ mimetype && \ $(WSL) zip -qrX --must-match $@ $(call extras_AUTOTEXTUSER_XMLFILES_RELATIVE,$*)) \ + $(call gb_Helper_make_zip_deterministic,$@) \ ) $(call gb_Trace_EndRange,autotext/user/$*.bau,ZIP) diff --git a/extras/CustomTarget_templates.mk b/extras/CustomTarget_templates.mk index a0661e96b356..9ba3284d4151 100644 --- a/extras/CustomTarget_templates.mk +++ b/extras/CustomTarget_templates.mk @@ -17,7 +17,8 @@ $(call gb_Trace_StartRange,$(subst $(gb_CustomTarget_workdir)/extras/source/,,$@ cd $(dir $<) && \ $(call gb_Helper_wsl_path,\ $(WSL) zip -q0X --filesync --must-match $@ mimetype && \ -$(WSL) zip -qrX --must-match $@ $(subst $(dir $<),,$^)) -x mimetype +$(WSL) zip -qrX --must-match $@ $(subst $(dir $<),,$^) -x mimetype) \ +$(call gb_Helper_make_zip_deterministic,$@) $(call gb_Trace_EndRange,$(subst $(gb_CustomTarget_workdir)/extras/source/,,$@),ZIP) endef diff --git a/extras/source/autocorr/emoji/emoji.ulf b/extras/source/autocorr/emoji/emoji.ulf index d2b8b4e6696d..73db415ba0d7 100644 --- a/extras/source/autocorr/emoji/emoji.ulf +++ b/extras/source/autocorr/emoji/emoji.ulf @@ -529,7 +529,7 @@ en-US = "divides" [DOES_NOT_DIVIDE] x-comment = "∤ (U+02224), see http://wiki.documentfoundation.org/Emoji" -en-US = "not divides" +en-US = "does not divide" [PARALLEL_TO] x-comment = "∥ (U+02225), see http://wiki.documentfoundation.org/Emoji" diff --git a/extras/source/gallery/gallery_system/bullets.thm b/extras/source/gallery/gallery_system/bullets.thm index ed74a8da1208..26057f3cc6d8 100644 Binary files a/extras/source/gallery/gallery_system/bullets.thm and b/extras/source/gallery/gallery_system/bullets.thm differ diff --git a/extras/source/wordbook/technical.dic b/extras/source/wordbook/technical.dic index 6cad6e3be246..98004cf1beaf 100644 --- a/extras/source/wordbook/technical.dic +++ b/extras/source/wordbook/technical.dic @@ -19,6 +19,7 @@ AMD Amiga= Analogue Android +Ansible ANSI API AppArmor @@ -81,6 +82,7 @@ DHCP= Diners Club Discover Card DNS +Docker DocLink Docuflex= Documaker= @@ -163,12 +165,14 @@ iSCSI ISP JavaScript JCB +Jenkins Jessie JPEG Kakao KDE Kerberos kHz +Kubernetes Kubuntu Kyocera LAN @@ -222,6 +226,7 @@ NetMail NetStorage NetWare Nextcloud +EGroupware Nixie NNTP Nokia @@ -313,6 +318,7 @@ TCL TCP= TeliaSonera Tencent +Terraform Tesla The Thunderbird diff --git a/filter/Configuration_filter.mk b/filter/Configuration_filter.mk index d157a4c664d7..78405f6f6c1c 100644 --- a/filter/Configuration_filter.mk +++ b/filter/Configuration_filter.mk @@ -475,7 +475,6 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_calc_types.xcu,f generic_XML \ calc_Gnumeric \ calc_Lotus \ - calc_Parquet \ calc_QPro \ calc_MS_Excel_40 \ calc_MS_Excel_40_VorlageTemplate \ @@ -538,7 +537,6 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_calc_filters.x calc_HTML_WebQuery \ calc_StarOffice_XML_Calc_Template \ calc_pdf_Export \ - calc_Parquet \ dBase \ calc8 \ calc8_template \ @@ -563,6 +561,15 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_calc_filters.x MS_Multiplan \ )) +ifeq "$(WITH_PARQUET_FILTER)" "TRUE" +$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_calc_types.xcu,filter/source/config/fragments/types,\ + calc_Parquet \ +)) +$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_calc_filters.xcu,filter/source/config/fragments/filters,\ + calc_Parquet \ +)) +endif + ifneq ($(ENABLE_WASM_STRIP_BASIC_DRAW_MATH_IMPRESS),TRUE) # fcfg_draw $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_draw_types.xcu,filter/source/config/fragments/types,\ @@ -578,7 +585,6 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_draw_types.xcu,f draw_CorelDraw_Document \ draw_Corel_Presentation_Exchange \ draw_Freehand_Document \ - draw_Visio_Document \ draw_ClarisWorks \ draw_PageMaker_Document \ draw_QXP_Document \ @@ -708,8 +714,9 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_drawgraphics_typ gif_Graphics_Interchange \ graphic_HTML \ jpg_JPEG \ + jxl_JPEG_XL \ met_OS2_Metafile \ - mov_MOV \ + mov_MOV \ pbm_Portable_Bitmap \ pcd_Photo_CD_Base \ pcd_Photo_CD_Base16 \ @@ -743,6 +750,7 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_drawgraphics_f EPS___Encapsulated_PostScript \ GIF___Graphics_Interchange \ JPG___JPEG \ + JXL___JPEG_XL \ MET___OS_2_Metafile \ mov__MOV \ PBM___Portable_Bitmap \ @@ -794,6 +802,7 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_impressgraphics_ graphic_HTML \ impress_CGM_Computer_Graphics_Metafile \ jpg_JPEG \ + jxl_JPEG_XL \ met_OS2_Metafile \ pbm_Portable_Bitmap \ pct_Mac_Pict \ @@ -864,8 +873,9 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_internalgraphics eps_Encapsulated_PostScript \ gif_Graphics_Interchange \ jpg_JPEG \ + jxl_JPEG_XL \ met_OS2_Metafile \ - mov_MOV \ + mov_MOV \ pbm_Portable_Bitmap \ pcd_Photo_CD_Base \ pcd_Photo_CD_Base16 \ @@ -904,6 +914,7 @@ $(eval $(call filter_Configuration_add_internal_filters,fcfg_langpack,fcfg_inter gif_Import \ jpg_Export \ jpg_Import \ + jxl_Import \ met_Import \ pbm_Import \ pcd_Import_Base \ diff --git a/filter/CustomTarget_docbook.mk b/filter/CustomTarget_docbook.mk index 4221a5fefcc1..94a58a449213 100644 --- a/filter/CustomTarget_docbook.mk +++ b/filter/CustomTarget_docbook.mk @@ -22,7 +22,8 @@ $(call gb_Trace_StartRange,$(subst $(gb_CustomTarget_workdir)/filter/source/docb cd $(dir $<) && \ $(call gb_Helper_wsl_path,\ $(WSL) zip -q0X --filesync --must-match $@ mimetype && \ -$(WSL) zip -qrX --must-match $@ $(subst $(dir $<),,$^)) -x mimetype +$(WSL) zip -qrX --must-match $@ $(subst $(dir $<),,$^) -x mimetype) \ +$(call gb_Helper_make_zip_deterministic,$@) $(call gb_Trace_EndRange,$(subst $(gb_CustomTarget_workdir)/filter/source/docbook/,,$@),ZIP) endef diff --git a/filter/qa/cppunit/data/xslt/document.xslt b/filter/qa/cppunit/data/xslt/document.xslt new file mode 100644 index 000000000000..712df80e850d --- /dev/null +++ b/filter/qa/cppunit/data/xslt/document.xslt @@ -0,0 +1,16 @@ + + + + + + + + written + + + + + diff --git a/filter/qa/cppunit/xslt-test.cxx b/filter/qa/cppunit/xslt-test.cxx index 3ef87ad118ee..82c10aa4465f 100644 --- a/filter/qa/cppunit/xslt-test.cxx +++ b/filter/qa/cppunit/xslt-test.cxx @@ -44,27 +44,38 @@ class XsltFilterTest public: void testXsltCopyOld(); void testXsltCopyNew(); + void testXsltOutputStreamOnly(); CPPUNIT_TEST_SUITE(XsltFilterTest); CPPUNIT_TEST(testXsltCopyOld); CPPUNIT_TEST(testXsltCopyNew); + CPPUNIT_TEST(testXsltOutputStreamOnly); CPPUNIT_TEST_SUITE_END(); }; class Listener : public ::cppu::WeakImplHelper { public: - Listener() : m_bDone(false) {} + /// Pass false for bFailOnError when the transformation is meant to fail. + Listener(bool bFailOnError = true) + : m_bDone(false), m_bFailOnError(bFailOnError), m_bError(false) {} void wait() { std::unique_lock g(m_mutex); m_cond.wait(g, [this]() { return m_bDone; }); } + bool hadError() { + std::scoped_lock g(m_mutex); + return m_bError; + } + private: std::mutex m_mutex; std::condition_variable m_cond; bool m_bDone; + bool m_bFailOnError; + bool m_bError; virtual void SAL_CALL disposing(const lang::EventObject&) noexcept override {} virtual void SAL_CALL started() noexcept override {} @@ -72,9 +83,16 @@ private: virtual void SAL_CALL terminated() noexcept override { notifyDone(); } virtual void SAL_CALL error(const uno::Any& e) override { + { + std::scoped_lock g(m_mutex); + m_bError = true; + } notifyDone(); // set on error too, otherwise main thread waits forever SAL_WARN("filter.xslt", e); - CPPUNIT_FAIL("exception while in XSLT"); + // A failure thrown here would land on the transformation thread, so record it and let + // the test body check hadError. + if (m_bFailOnError) + CPPUNIT_FAIL("exception while in XSLT"); } void notifyDone() { @@ -198,6 +216,63 @@ void XsltFilterTest::testXsltCopyOld() osl_removeFile(tempURL.pData); } +// The transformation writes to the output stream it is given, and nowhere else. +void XsltFilterTest::testXsltOutputStreamOnly() +{ + OUString tempDirURL; + osl_getTempDirURL(&tempDirURL.pData); + oslFileHandle tempFile; + OUString tempURL; + osl::File::RC rc = osl::File::createTempFile(nullptr, &tempFile, &tempURL); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, rc); + osl_closeFile(tempFile); // close it so xSFA can open it on WNT + + OUString writtenURL(tempDirURL + "/xslt-write-test.txt"); + osl_removeFile(writtenURL.pData); + + OUString source( + m_directories.getURLFromSrc(u"/filter/source/xsltfilter/xsltfilter.component")); + uno::Sequence args{ + uno::Any(beans::NamedValue(u"StylesheetURL"_ustr, + uno::Any(m_directories.getURLFromSrc(u"/filter/qa/cppunit/data/xslt/document.xslt")))), + uno::Any(beans::NamedValue(u"SourceURL"_ustr, uno::Any(source))), + uno::Any(beans::NamedValue(u"TargetURL"_ustr, uno::Any(tempURL))), + uno::Any(beans::NamedValue(u"TargetBaseURL"_ustr, uno::Any(tempDirURL + "/"))), + uno::Any(beans::NamedValue(u"SystemType"_ustr, uno::Any(OUString()))), + uno::Any(beans::NamedValue(u"PublicType"_ustr, uno::Any(OUString()))) + }; + + uno::Reference xSFA = + ucb::SimpleFileAccess::create(getComponentContext()); + + uno::Reference xIn = xSFA->openFileRead(source); + uno::Reference xOut = xSFA->openFileWrite(tempURL); + + rtl::Reference xListener = new Listener(false); + + uno::Reference xXslt( + xml::xslt::XSLTTransformer::create(getComponentContext(), args)); + + xXslt->addListener(xListener); + xXslt->setInputStream(xIn); + xXslt->setOutputStream(xOut); + + xXslt->start(); + + xListener->wait(); + + xIn->closeInput(); + xOut->closeOutput(); + xXslt->terminate(); + + CPPUNIT_ASSERT_MESSAGE("the transformation wrote outside its output stream", + !xSFA->exists(writtenURL)); + CPPUNIT_ASSERT_MESSAGE("the transformation was not reported as failed", + xListener->hadError()); + + osl_removeFile(tempURL.pData); +} + CPPUNIT_TEST_SUITE_REGISTRATION(XsltFilterTest); } diff --git a/filter/qa/pdf.cxx b/filter/qa/pdf.cxx index 791a7494a28d..36a7db8a7345 100644 --- a/filter/qa/pdf.cxx +++ b/filter/qa/pdf.cxx @@ -149,11 +149,6 @@ void Test::doTestCommentsInMargin(bool commentsInMarginEnabled) return; loadFromFile(u"commentsInMargin.odt"); - if (comphelper::LibreOfficeKit::isActive()) - { - vcl::ITiledRenderable* pTiledDoc = dynamic_cast(mxComponent.get()); - pTiledDoc->initializeForTiledRendering(uno::Sequence()); - } uno::Reference xFactory = getMultiServiceFactory(); uno::Reference xFilter( xFactory->createInstance(u"com.sun.star.document.PDFFilter"_ustr), uno::UNO_QUERY); @@ -468,7 +463,7 @@ CPPUNIT_TEST_FIXTURE(Test, testSignCertificatePEM) std::unique_ptr pPdfDocument = pPDFium->openDocument(aStream.GetData(), aStream.GetSize(), OString()); // Without the accompanying fix in place, this test would have failed, as signing was enabled - // without configured certificate, so the whole export failed. + // without configuring a certificate, so the whole export failed. CPPUNIT_ASSERT(pPdfDocument); CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getSignatureCount()); } diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx index 3b53605fc8a9..45c6bf60405a 100644 --- a/filter/qa/unit/svg.cxx +++ b/filter/qa/unit/svg.cxx @@ -533,6 +533,34 @@ CPPUNIT_TEST_FIXTURE(SvgFilterTest, testFontVariationSettings) "font-variation-settings", u"\"wght\" 700, \"wdth\" 75"); } +CPPUNIT_TEST_FIXTURE(SvgFilterTest, testExportControllerFromModel) +{ + // Given a Writer, then a Draw document loaded, the Writer document is the current one: + uno::Sequence aEmptyProps; + mxComponent2 = mxDesktop->loadComponentFromURL(u"private:factory/swriter"_ustr, u"_blank"_ustr, + 0, aEmptyProps); + CPPUNIT_ASSERT(mxComponent2); + uno::Sequence aHiddenProps{ comphelper::makePropertyValue(u"Hidden"_ustr, + true) }; + mxComponent = mxDesktop->loadComponentFromURL(u"private:factory/sdraw"_ustr, u"_default"_ustr, + 0, aHiddenProps); + CPPUNIT_ASSERT(mxComponent); + uno::Reference xWriterModel(mxComponent2, uno::UNO_QUERY_THROW); + uno::Reference xWriterFrame(xWriterModel->getCurrentController()->getFrame(), + uno::UNO_SET_THROW); + mxDesktop->setActiveFrame(xWriterFrame); + CPPUNIT_ASSERT_EQUAL(xWriterFrame, mxDesktop->getCurrentFrame()); + + // When exporting the Draw document to SVG: + // Then make sure storeToURL() doesn't fail: + uno::Reference xStorable(mxComponent, uno::UNO_QUERY_THROW); + comphelper::SequenceAsHashMap aMediaDescriptor; + aMediaDescriptor[u"FilterName"_ustr] <<= u"draw_svg_Export"_ustr; + // Without the accompanying fix in place, this test would have failed with an IOException, as it + // tried to export the current Writer document, not the Draw one. + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/config/cache/filtercache.cxx b/filter/source/config/cache/filtercache.cxx index 5cb2dd63eb91..cdb76667e49a 100644 --- a/filter/source/config/cache/filtercache.cxx +++ b/filter/source/config/cache/filtercache.cxx @@ -82,7 +82,7 @@ FilterCache::FilterCache() css::uno::Sequence< OUString >(sStandardProps, 3); m_aStandardProps[E_READ_ALL] = css::uno::Sequence< OUString >(sStandardProps, - SAL_N_ELEMENTS(sStandardProps)); + std::size(sStandardProps)); i = 0; OUString sTypeProps[7]; @@ -103,7 +103,7 @@ FilterCache::FilterCache() css::uno::Sequence< OUString >(sTypeProps, 1); m_aTypeProps[E_READ_ALL] = css::uno::Sequence< OUString >(sTypeProps, - SAL_N_ELEMENTS(sTypeProps)); + std::size(sTypeProps)); } @@ -223,13 +223,13 @@ void FilterCache::load(EFillState eRequired) m_sActLocale = DEFAULT_OFFICELOCALE; } - // Support the old configuration support. Read it only one times during office runtime! + // Support the old configuration support. Read it only once during office runtime! impl_readOldFormat(); } // b) If the required fill state was not reached - // but std values was already loaded ... + // but std values were already loaded ... // we must load some further missing items. impl_load(eRequired); // <- SAFE @@ -253,7 +253,7 @@ std::vector FilterCache::getMatchingItemsByProps( EItemType eTyp // search for right list // An exception is thrown - "eType" is unknown. - // => rList will be valid everytimes next line is reached. + // => rList will be valid every time next line is reached. const CacheItemList& rList = impl_getItemList(eType); std::vector lKeys; @@ -284,7 +284,7 @@ bool FilterCache::hasItems(EItemType eType) const // search for right list // An exception is thrown - "eType" is unknown. - // => rList will be valid everytimes next line is reached. + // => rList will be valid every time next line is reached. const CacheItemList& rList = impl_getItemList(eType); return !rList.empty(); @@ -299,7 +299,7 @@ std::vector FilterCache::getItemNames(EItemType eType) const // search for right list // An exception is thrown - "eType" is unknown. - // => rList will be valid everytimes next line is reached. + // => rList will be valid every time next line is reached. const CacheItemList& rList = impl_getItemList(eType); std::vector lKeys; @@ -320,7 +320,7 @@ bool FilterCache::hasItem( EItemType eType, // search for right list // An exception is thrown - "eType" is unknown. - // => rList will be valid everytimes next line is reached. + // => rList will be valid every time next line is reached. const CacheItemList& rList = impl_getItemList(eType); // if item could not be found - check if it can be loaded @@ -361,7 +361,7 @@ CacheItem& FilterCache::impl_getItem( EItemType eType, { // search for right list // An exception is thrown if "eType" is unknown. - // => rList will be valid everytimes next line is reached. + // => rList will be valid every time next line is reached. CacheItemList& rList = impl_getItemList(eType); // check if item exists ... @@ -410,7 +410,7 @@ void FilterCache::removeItem( EItemType eType, // search for right list // An exception is thrown - "eType" is unknown. - // => rList will be valid everytimes next line is reached. + // => rList will be valid every time next line is reached. CacheItemList& rList = impl_getItemList(eType); CacheItemList::iterator pItem = rList.find(sItem); @@ -431,7 +431,7 @@ void FilterCache::setItem( EItemType eType , // search for right list // An exception is thrown - "eType" is unknown. - // => rList will be valid everytimes next line is reached. + // => rList will be valid every time next line is reached. CacheItemList& rList = impl_getItemList(eType); // name must be part of the property set too ... otherwise our @@ -494,7 +494,7 @@ css::uno::Any FilterCache::getItemWithStateProps( EItemType eType, The default frame loader can't be located inside the normal set of frame loaders. It's an atomic property inside the misc cfg package. So we can't retrieve the information about FINALIZED and MANDATORY very easy ... :-( - => set it to readonly/required everytimes :-) + => set it to readonly/required every time :-) */ css::uno::Any aDirectValue = impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER); OUString sDefaultFrameLoader; @@ -807,7 +807,7 @@ css::uno::Reference< css::uno::XInterface > FilterCache::impl_openConfig(EConfig } break; - default : throw css::uno::RuntimeException(u"These configuration node is not supported here for open!"_ustr, nullptr); + default : throw css::uno::RuntimeException(u"This configuration node is not supported here for open!"_ustr, nullptr); } { @@ -1704,10 +1704,10 @@ CacheItemList::iterator FilterCache::impl_loadItemOnDemand( EItemType { if (pItemInCache != pList->end()) pList->erase(pItemInCache); - // OK - this item does not exists inside configuration. + // OK - this item does not exist inside configuration. // And we already updated our internal cache. // But the outside code needs this NoSuchElementException - // to know, that this item does notexists. + // to know, that this item does not exist. // Nobody checks the iterator! throw css::container::NoSuchElementException(); } diff --git a/filter/source/config/cache/filtercache.hxx b/filter/source/config/cache/filtercache.hxx index 8445efea8227..19c1af066408 100644 --- a/filter/source/config/cache/filtercache.hxx +++ b/filter/source/config/cache/filtercache.hxx @@ -131,7 +131,7 @@ class FilterCache : public cppu::BaseMutex
  • if the item exists inside config layer but not inside our cache => REMOVED
  • if the item exists inside config layer and inside our cache => CHANGED
  • -
  • if the item does not exists inside config layer but inside our cache => ADDED.
  • +
  • if the item does not exist inside config layer but inside our cache => ADDED.
*/ enum EItemFlushState @@ -142,7 +142,7 @@ class FilterCache : public cppu::BaseMutex E_ITEM_REMOVED = 1, /// indicates an item, which exists inside config layer and inside our own cache E_ITEM_CHANGED = 2, - /// indicates an item, which does not exists inside config layer but inside our own cache + /// indicates an item, which does not exist inside config layer but inside our own cache E_ITEM_ADDED = 3 }; @@ -212,7 +212,7 @@ class FilterCache : public cppu::BaseMutex /** @short contains status, which cache items/properties - was already loaded from the underlying configuration. + were already loaded from the underlying configuration. @descr This information can be used to detect missing information and load it on demand. @@ -663,14 +663,14 @@ class FilterCache : public cppu::BaseMutex @return [css::uno::Any] the value of the requested key. Can be empty if an internal error occurred or if the requested - key does not exists! + key does not exist! */ css::uno::Any impl_getDirectCFGValue(std::u16string_view sDirectKey); /** @short load the underlying configuration into this cache. - @descr Which items should be read can be regulate by the + @descr Which items should be read can be regulated by the parameter eRequiredState. That provides the possibility to load standard values on startup only and update this cache later on demand with all available information. @@ -766,7 +766,7 @@ class FilterCache : public cppu::BaseMutex /** @short try to load the requested item on demand from the underlying configuration layer. - @descr The outside code has to be sure, that the item does not already exists + @descr The outside code has to be sure, that the item does not already exist inside this cache. Otherwise it will be loaded twice. This method doesn't check such constellations! @@ -783,7 +783,7 @@ class FilterCache : public cppu::BaseMutex But to improve robustness - it should be checked :-) @throw [css::container::NoSuchElementException] - if the item does not exists inside the configuration layer too! + if the item does not exist inside the configuration layer too! @throw [css::uno::Exception] if an unrecoverable error occurs inside this operation. @@ -821,7 +821,7 @@ class FilterCache : public cppu::BaseMutex /** @short specify, which save operation is necessary for the specified item. - @desrc If an item of this cache will be added/removed or modified it will + @descr If an item of this cache will be added/removed or modified it will be changed inside memory only first. But we save its name inside a special list of changed items. If at least the method flush() is called, we use this list to check if the item was changed/added or removed. This method diff --git a/filter/source/config/cache/typedetection.cxx b/filter/source/config/cache/typedetection.cxx index c50c8522a1d2..37342f08c6a1 100644 --- a/filter/source/config/cache/typedetection.cxx +++ b/filter/source/config/cache/typedetection.cxx @@ -234,6 +234,7 @@ int getFlatTypeRank(std::u16string_view rType) "psd_Adobe_Photoshop", "png_Portable_Network_Graphic", "jpg_JPEG", + "jxl_JPEG_XL", "mov_MOV", "gif_Graphics_Interchange", "bmp_MS_Windows", @@ -917,7 +918,7 @@ OUString TypeDetection::impl_detectTypeFlatAndDeep(comphelper::SequenceAsHashMap bool bAllowDeep , OUString& rLastChance ) { - // reset it everytimes, so the outside code can distinguish between + // reset it every time, so the outside code can distinguish between // a set and a not set value. rLastChance.clear(); @@ -962,7 +963,7 @@ OUString TypeDetection::impl_detectTypeFlatAndDeep(comphelper::SequenceAsHashMap = aURL.getName(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset); - // Ask the user whether they wants to try to repair + // Ask the user whether they want to try to repair RequestPackageReparation aRequest(aDocumentTitle); xInteraction->handle(aRequest.GetRequest()); @@ -991,7 +992,7 @@ OUString TypeDetection::impl_detectTypeFlatAndDeep(comphelper::SequenceAsHashMap // a) no types => no detection // b) deep detection not allowed => return first valid type of list (because it's the preferred or the first valid one) // or(!) match by URLPattern => in such case a deep detection will be suppressed! - // c) type has no detect service => safe the first occurred type without a detect service + // c) type has no detect service => save the first occurred type without a detect service // as "last chance"(!). It will be used outside of this method // if no further type could be detected. // It must be the first one, because it can be a preferred type. diff --git a/filter/source/config/fragments/filters/JXL___JPEG_XL.xcu b/filter/source/config/fragments/filters/JXL___JPEG_XL.xcu new file mode 100644 index 000000000000..cc49099002c6 --- /dev/null +++ b/filter/source/config/fragments/filters/JXL___JPEG_XL.xcu @@ -0,0 +1,30 @@ + + + IMPORT ALIEN + + + + + JXL - JPEG XL Image + + 0 + jxl_JPEG_XL + + com.sun.star.drawing.DrawingDocument + diff --git a/canvas/source/simplecanvas/simplecanvas.component b/filter/source/config/fragments/internalgraphicfilters/jxl_Import.xcu similarity index 62% rename from canvas/source/simplecanvas/simplecanvas.component rename to filter/source/config/fragments/internalgraphicfilters/jxl_Import.xcu index 9be11ad47952..862f2b599f68 100644 --- a/canvas/source/simplecanvas/simplecanvas.component +++ b/filter/source/config/fragments/internalgraphicfilters/jxl_Import.xcu @@ -1,4 +1,3 @@ - - - - - - - +--> + + jxl_JPEG_XL + SVIJXL + JXL - JPEG XL + + + JXL - JPEG XL Image + + IMPORT + diff --git a/filter/source/config/fragments/types/jxl_JPEG_XL.xcu b/filter/source/config/fragments/types/jxl_JPEG_XL.xcu new file mode 100644 index 000000000000..ef884eb9f428 --- /dev/null +++ b/filter/source/config/fragments/types/jxl_JPEG_XL.xcu @@ -0,0 +1,29 @@ + + + com.sun.star.comp.draw.FormatDetector + + jxl + image/jxl + false + JXL - JPEG XL + + JXL - JPEG XL Image + + + diff --git a/filter/source/graphicfilter/icgm/class4.cxx b/filter/source/graphicfilter/icgm/class4.cxx index 4c0f204f08fd..c1aa27746219 100644 --- a/filter/source/graphicfilter/icgm/class4.cxx +++ b/filter/source/graphicfilter/icgm/class4.cxx @@ -26,6 +26,7 @@ #include #include +#include #include @@ -127,6 +128,11 @@ void CGM::ImplDoClass4() case 0x01 : /*PolyLine*/ { sal_uInt32 nPoints = mnElementSize / ImplGetPointSize(); + if (nPoints > SAL_MAX_UINT16) + { + SAL_WARN("filter.icgm", "CGM PolyLine too many points: " << nPoints); + break; + } tools::Polygon aPolygon( static_cast(nPoints) ); for ( sal_uInt32 i = 0; i < nPoints; i++) { diff --git a/filter/source/graphicfilter/icgm/class5.cxx b/filter/source/graphicfilter/icgm/class5.cxx index 7cfd9911c7d4..bc91e1d500b4 100644 --- a/filter/source/graphicfilter/icgm/class5.cxx +++ b/filter/source/graphicfilter/icgm/class5.cxx @@ -439,7 +439,7 @@ void CGM::ImplDoClass5() case 0x64 : /*Block Text Paragraph Bullet Level*/ break; case 0x65 : /*Block Text Paragraph Line Horizontal Alignment*/ break; case 0x66 : /*Block Text Paragraph Line Vertical Alignment*/ break; - case 0x67 : /*Block Text Paragragh Line Spacing*/ break; + case 0x67 : /*Block Text Paragraph Line Spacing*/ break; case 0x68 : /*Block Text Paragraph Word Wrap*/ break; case 0x70 : /*Block Text Forward Advance Distance*/ break; case 0x71 : /*Word Spacing*/ break; @@ -526,7 +526,7 @@ void CGM::ImplDoClass5() case 0xf4 : /*set color name - for Pantone support*/ break; default: break; } -}; +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx index 58858a880154..8d633f84bfe2 100644 --- a/filter/source/msfilter/escherex.cxx +++ b/filter/source/msfilter/escherex.cxx @@ -2044,12 +2044,12 @@ bool EscherPropertyContainer::CreatePolygonProperties( /* -in MS,the connector including 9 types : +in MS, the connector includes 9 types : "straightConnector1", "bentConnector2","bentConnector3","bentConnector4","bentConnector5" "curvedConnector2","curvedConnector3","curvedConnector4","curvedConnector5" -in AOO,including 4 types:"standard","lines","line","curve" -when save as MS file, the connector must be convert to corresponding type. +in AOO, including 4 types: "standard","lines","line","curve" +when saved as MS file, the connector must be converted to corresponding type. "line" and "lines" <-> "straightConnector1" "standard" <-> "bentConnector2-5" "curve" <-> "curvedConnector2-5" @@ -2140,7 +2140,7 @@ static void lcl_Rotate(Degree100 nAngle, Point center, Point& pt) /* FlipV defines that the shape will be flipped vertically about the center of its bounding box. Generally, draw the connector from top to bottom, from left to right when meet the adjust value, -but when (X1>X2 or Y1>Y2),the draw director must be reverse, FlipV or FlipH should be set to true. +but when (X1>X2 or Y1>Y2), the draw direction must be reversed, FlipV or FlipH should be set to true. */ static bool lcl_GetAngle(tools::Polygon &rPoly, ShapeFlag& rShapeFlags,sal_Int32& nAngle ) { @@ -2871,7 +2871,7 @@ void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeT double fExtrusionShininess = 0; if ( rrProp.Value >>= fExtrusionShininess ) { - // ODF to MS Office conversion invers to msdffimp.cxx + // ODF to MS Office conversion inverse to msdffimp.cxx fExtrusionShininess = std::round(fExtrusionShininess / 10.0); AddOpt( DFF_Prop_c3DShininess, static_cast(fExtrusionShininess) ); } diff --git a/filter/source/msfilter/mscodec.cxx b/filter/source/msfilter/mscodec.cxx index afd5b50dc4e2..551eff80f78e 100644 --- a/filter/source/msfilter/mscodec.cxx +++ b/filter/source/msfilter/mscodec.cxx @@ -468,7 +468,14 @@ bool MSCodec_Std97::InitCipher(sal_uInt32 nCounter) bool MSCodec_CryptoAPI::InitCipher(sal_uInt32 nCounter) { // data = hash + iterator (4bytes) +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 17 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wrestrict" +#endif std::vector aKeyData(m_aDigestValue); +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 17 +#pragma GCC diagnostic pop +#endif aKeyData.push_back(sal_uInt8((nCounter >> 0) & 0xff)); aKeyData.push_back(sal_uInt8((nCounter >> 8) & 0xff)); aKeyData.push_back(sal_uInt8((nCounter >> 16) & 0xff)); diff --git a/filter/source/msfilter/msdffimp.cxx b/filter/source/msfilter/msdffimp.cxx index b3184b2467c6..22f66c694fd1 100644 --- a/filter/source/msfilter/msdffimp.cxx +++ b/filter/source/msfilter/msdffimp.cxx @@ -4379,7 +4379,7 @@ rtl::Reference SvxMSDffManager::ImportShape( const DffRecordHeader& r /* After CWS aw033 has been integrated, an empty group object cannot store its resulting bounding rectangle anymore. We have to return this rectangle via rClientRect now, but only, if - caller has not passed an own bounding ractangle. */ + caller has not passed an own bounding rectangle. */ if ( rClientRect.IsEmpty() ) rClientRect = aObjData.aBoundRect; nGroupShapeFlags = aObjData.nSpFlags; @@ -6462,7 +6462,7 @@ bool SvxMSDffManager::GetBLIP( sal_uLong nIdx_, Graphic& rGraphic, tools::Rectan bOk = GetBLIPDirect( *pStData, rGraphic, pVisArea ); if( pStData2 && !bOk ) { - // Error, but the is a second chance: There is a second + // Error, but there is a second chance: There is a second // data stream in which the graphic could be stored! if( pStData2->GetError() ) pStData2->ResetError(); @@ -7241,11 +7241,10 @@ css::uno::Reference < css::embed::XEmbeddedObject > SvxMSDffManager::CheckForCo } // JP 26.10.2001: Bug 93374 / 91928 the writer - // objects need the correct visarea needs the - // correct visarea, but this is not true for + // objects need the correct visarea, but this is not true for // PowerPoint (see bugdoc 94908b) // SJ: 19.11.2001 bug 94908, also chart objects - // needs the correct visarea + // need the correct visarea // If pName is set this is an own embedded object, it should have the correct size internally // TODO/LATER: it might make sense in future to set the size stored in internal object diff --git a/filter/source/msfilter/msocximex.cxx b/filter/source/msfilter/msocximex.cxx index 1aaeb334890d..bf96e7406d86 100644 --- a/filter/source/msfilter/msocximex.cxx +++ b/filter/source/msfilter/msocximex.cxx @@ -99,7 +99,7 @@ const uno::Reference< container::XIndexContainer >& xFormsSupplier->getForms(); // The form gets a new name like "WW-Standard[n]" and will - // created new in any case. + // be created anew in any case. OUString sName( sWW8_form ); sal_uInt16 n = 0; diff --git a/filter/source/msfilter/msvbahelper.cxx b/filter/source/msfilter/msvbahelper.cxx index 28556b2ca116..047feafc619c 100644 --- a/filter/source/msfilter/msvbahelper.cxx +++ b/filter/source/msfilter/msvbahelper.cxx @@ -73,7 +73,7 @@ OUString extractMacroName( std::u16string_view rMacroUrl ) static std::u16string_view trimMacroName( std::u16string_view rMacroName ) { - // the name may contain whitespaces and may be enclosed in apostrophs + // the name may contain whitespaces and may be enclosed in apostrophes std::u16string_view aMacroName = o3tl::trim(rMacroName); size_t nMacroLen = aMacroName.size(); if( (nMacroLen >= 2) && (aMacroName[ 0 ] == '\'') && (aMacroName[ nMacroLen - 1 ] == '\'') ) @@ -204,7 +204,7 @@ static bool hasMacro(SfxObjectShell const* pShell, const OUString& sLibrary, OUS if (!pBasic) return false; - if (!sMod.isEmpty()) // we wish to find the macro is a specific module + if (!sMod.isEmpty()) // we wish to find the macro in a specific module { SbModule* pModule = pBasic->FindModule(sMod); if (!pModule) @@ -316,7 +316,7 @@ MacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const OUString& Macro if( !pShell ) return MacroResolvedInfo(); - // the name may be enclosed in apostrophs + // the name may be enclosed in apostrophes std::u16string_view aMacroName = trimMacroName( MacroName ); // parse the macro name @@ -579,7 +579,7 @@ OUString SAL_CALL VBAMacroResolver::resolveVBAMacroToScriptURL( const OUString& if( !mpObjShell ) throw uno::RuntimeException(); - // the name may be enclosed in apostrophs + // the name may be enclosed in apostrophes OUString aMacroName( trimMacroName( rVBAMacroName ) ); if( aMacroName.isEmpty() ) throw lang::IllegalArgumentException(); diff --git a/filter/source/msfilter/svdfppt.cxx b/filter/source/msfilter/svdfppt.cxx index 84b16851b799..42eb16d24373 100644 --- a/filter/source/msfilter/svdfppt.cxx +++ b/filter/source/msfilter/svdfppt.cxx @@ -625,65 +625,54 @@ void SdrEscherImport::RecolorGraphic( SvStream& rSt, sal_uInt32 nRecLen, Graphic sal_uInt32 OriginalGlobalColors[ 64 ]; sal_uInt32 NewGlobalColors[ 64 ]; - sal_uInt32 i, j, nGlobalColorsChanged, nFillColorsChanged; - nGlobalColorsChanged = nFillColorsChanged = 0; + sal_uInt32 nGlobalColorsChanged = 0; - sal_uInt32* pCurrentOriginal = OriginalGlobalColors; - sal_uInt32* pCurrentNew = NewGlobalColors; - sal_uInt32* pCount = &nGlobalColorsChanged; - i = nGlobalColorsCount; - - for ( j = 0; j < 2; j++ ) + for ( sal_uInt32 i = 0; i < nGlobalColorsCount; i++ ) { - for ( ; i > 0; i-- ) + sal_uInt64 nPos = rSt.Tell(); + sal_uInt16 nChanged(0); + rSt.ReadUInt16( nChanged ); + if ( nChanged & 1 ) { - sal_uInt64 nPos = rSt.Tell(); - sal_uInt16 nChanged; - rSt.ReadUInt16( nChanged ); - if ( nChanged & 1 ) - { - sal_uInt8 nDummy, nRed, nGreen, nBlue; - sal_uInt32 nColor = 0; - sal_uInt32 nIndex; - rSt.ReadUChar( nDummy ) - .ReadUChar( nRed ) - .ReadUChar( nDummy ) - .ReadUChar( nGreen ) - .ReadUChar( nDummy ) - .ReadUChar( nBlue ) - .ReadUInt32( nIndex ); + sal_uInt8 nDummy, nRed, nGreen, nBlue; + sal_uInt32 nColor(0); + sal_uInt32 nIndex(0); + rSt.ReadUChar( nDummy ) + .ReadUChar( nRed ) + .ReadUChar( nDummy ) + .ReadUChar( nGreen ) + .ReadUChar( nDummy ) + .ReadUChar( nBlue ) + .ReadUInt32( nIndex ); - if ( nIndex < 8 ) - { - Color aColor = MSO_CLR_ToColor( nIndex << 24 ); - nRed = aColor.GetRed(); - nGreen = aColor.GetGreen(); - nBlue = aColor.GetBlue(); - } - nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 ); - *pCurrentNew++ = nColor; - rSt.ReadUChar( nDummy ) - .ReadUChar( nRed ) - .ReadUChar( nDummy ) - .ReadUChar( nGreen ) - .ReadUChar( nDummy ) - .ReadUChar( nBlue ); - nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 ); - *pCurrentOriginal++ = nColor; - (*pCount)++; + if ( nIndex < 8 ) + { + Color aColor = MSO_CLR_ToColor( nIndex << 24 ); + nRed = aColor.GetRed(); + nGreen = aColor.GetGreen(); + nBlue = aColor.GetBlue(); } - rSt.Seek( nPos + 44 ); + nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 ); + NewGlobalColors[ nGlobalColorsChanged ] = nColor; + rSt.ReadUChar( nDummy ) + .ReadUChar( nRed ) + .ReadUChar( nDummy ) + .ReadUChar( nGreen ) + .ReadUChar( nDummy ) + .ReadUChar( nBlue ); + nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 ); + OriginalGlobalColors[ nGlobalColorsChanged ] = nColor; + nGlobalColorsChanged++; } - pCount = &nFillColorsChanged; - i = nFillColorsCount; + rSt.Seek( nPos + 44 ); } - if ( !(nGlobalColorsChanged || nFillColorsChanged) ) + if ( !nGlobalColorsChanged ) return; std::unique_ptr pSearchColors(new Color[ nGlobalColorsChanged ]); std::unique_ptr pReplaceColors(new Color[ nGlobalColorsChanged ]); - for ( j = 0; j < nGlobalColorsChanged; j++ ) + for ( sal_uInt32 j = 0; j < nGlobalColorsChanged; j++ ) { sal_uInt32 nSearch = OriginalGlobalColors[ j ]; sal_uInt32 nReplace = NewGlobalColors[ j ]; @@ -2638,7 +2627,7 @@ bool SdrPowerPointImport::SeekToShape( SvStream& rSt, SvxMSDffClientData* pClien if ( pPageList && ( nMasterNum < pPageList->size() ) ) { assert( !pPageList->is_null( nMasterNum ) ); - const PptSlidePersistEntry& rPersist = (*pPageList)[ nMasterNum ]; // get the masterpage's persistentry + const PptSlidePersistEntry& rPersist = (*pPageList)[ nMasterNum ]; // get the masterpage's persist entry if ( rPersist.pPresentationObjects ) { sal_uInt32 nCurrent(0); diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx index 400aa505dc6c..ad5ac53ba11b 100644 --- a/filter/source/pdf/impdialog.cxx +++ b/filter/source/pdf/impdialog.cxx @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -60,6 +59,7 @@ using namespace ::com::sun::star::uno; Please note: the default used here are the same as per specification, They should be the same in PDFFilter::implExport and in PDFExport::PDFExport */ +static bool bDialogUsedThisSession = false; ImpPDFTabDialog::ImpPDFTabDialog(weld::Window* pParent, const Sequence< PropertyValue >& rFilterData, const Reference< XComponent >& rxDoc) : SfxTabDialogController(pParent, u"filter/ui/pdfoptionsdialog.ui"_ustr, u"PdfOptionsDialog"_ustr) @@ -228,9 +228,6 @@ ImpPDFTabDialog::ImpPDFTabDialog(weld::Window* pParent, const Sequence< Property GetCancelButton().connect_clicked(LINK(this, ImpPDFTabDialog, CancelHdl)); GetOKButton().connect_clicked(LINK(this, ImpPDFTabDialog, OkHdl)); - - // remove the reset button, not needed in this tabbed dialog - RemoveResetButton(); } ImpPDFTabSecurityPage* ImpPDFTabDialog::getSecurityPage() const @@ -722,8 +719,10 @@ void ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent) mxEdSheets->show(); mxCbSinglePageSheets->show(); - mxCbSinglePageSheets->set_active(pParent->mbSinglePageSheets); + mxCbSinglePageSheets->set_active(bDialogUsedThisSession ? pParent->mbSinglePageSheets : false); mxCbSinglePageSheets->set_sensitive(!pParent->maConfigItem.IsReadOnly(u"SinglePageSheets"_ustr)); + mxCbSinglePageSheets->connect_toggled(LINK(this, ImpPDFTabGeneralPage, ToggleSinglePageSheetsHdl)); + ToggleSinglePageSheetsHdl(*mxCbSinglePageSheets); } else { @@ -766,7 +765,10 @@ void ImpPDFTabGeneralPage::GetFilterConfigItem( ImpPDFTabDialog* pParent ) pParent->mbExportHiddenSlides = mxCbExportHiddenSlides->get_active(); if (mbIsSpreadsheet) + { pParent->mbSinglePageSheets = mxCbSinglePageSheets->get_active(); + bDialogUsedThisSession = true; + } pParent->mbIsSkipEmptyPages = !mxCbExportEmptyPages->get_active(); pParent->mbIsExportPlaceholders = mxCbExportPlaceholders->get_active(); @@ -947,6 +949,17 @@ IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleAddStreamHdl, weld::Toggleable&, voi } } +IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleSinglePageSheetsHdl, weld::Toggleable&, void) +{ + const bool bSinglePageSheets = mxCbSinglePageSheets->get_active(); + mxRbAll->set_sensitive(!bSinglePageSheets); + mxRbPageRange->set_sensitive(!bSinglePageSheets); + mxRbSheetRange->set_sensitive(!bSinglePageSheets); + mxRbSelection->set_sensitive(!bSinglePageSheets); + mxEdPages->set_sensitive(!bSinglePageSheets && mxRbPageRange->get_active()); + mxEdSheets->set_sensitive(!bSinglePageSheets && mxRbSheetRange->get_active()); +} + void ImpPDFTabGeneralPage::thePDFVersionChanged() { const bool bIsPDFA = IsPdfaSelected(); diff --git a/filter/source/pdf/impdialog.hxx b/filter/source/pdf/impdialog.hxx index f29a8fa63ffa..51347366fa99 100644 --- a/filter/source/pdf/impdialog.hxx +++ b/filter/source/pdf/impdialog.hxx @@ -24,13 +24,16 @@ #include #include +#include +#include #include #include #include +#include #include +#include #include #include -#include #include #include @@ -234,6 +237,7 @@ class ImpPDFTabGeneralPage : public SfxTabPage DECL_LINK(ToggleReduceImageResolutionHdl, weld::Toggleable&, void); DECL_LINK(ToggleWatermarkHdl, weld::Toggleable&, void); DECL_LINK(ToggleAddStreamHdl, weld::Toggleable&, void); + DECL_LINK(ToggleSinglePageSheetsHdl, weld::Toggleable&, void); DECL_LINK(ToggleExportFormFieldsHdl, weld::Toggleable&, void); DECL_LINK(ToggleExportNotesPagesHdl, weld::Toggleable&, void); diff --git a/filter/source/pdf/pdfdialog.cxx b/filter/source/pdf/pdfdialog.cxx index a1737a04d6f4..ef94917e1ed9 100644 --- a/filter/source/pdf/pdfdialog.cxx +++ b/filter/source/pdf/pdfdialog.cxx @@ -78,13 +78,13 @@ void PDFDialog::executedDialog( sal_Int16 nExecutionResult ) void PDFDialog::runAsync(const css::uno::Reference< css::ui::dialogs::XDialogClosedListener >& xListener) { - SfxTabDialogController::runAsync(m_xAsyncDialog, [this, xListener](sal_Int32 nResponse) { - rtl::Reference xThis(this); // keep alive for scope, dialogClosed can cause owner to drop this - executedAsyncDialog( m_xAsyncDialog, nResponse ); + rtl::Reference xThis(this); // keep alive, 'this' may be dropped otherwise + SfxTabDialogController::runAsync(m_xAsyncDialog, [xThis, xListener](sal_Int32 nResponse) { + xThis->executedAsyncDialog( xThis->m_xAsyncDialog, nResponse ); css::ui::dialogs::DialogClosedEvent aEvent; aEvent.DialogResult = nResponse; xListener->dialogClosed( aEvent ); - destroyAsyncDialog(); + xThis->destroyAsyncDialog(); }); } diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx index a7e0e9b98adb..f61792bbccfc 100644 --- a/filter/source/svg/svgexport.cxx +++ b/filter/source/svg/svgexport.cxx @@ -78,6 +78,13 @@ using namespace css::presentation; using namespace ::com::sun::star::graphic; using namespace ::com::sun::star::style; using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; using namespace ::xmloff::token; // - ooo elements and attributes - @@ -2005,7 +2012,9 @@ bool SVGFilter::implExportPage( std::u16string_view sPageId, // Slide custom background, if any, is referenced at a different position // in order to not overlap background objects. std::unique_ptr xDefsExp; - if (!bMaster) // insert the open tag related to the slide background + // tdf#151746 + // Do not use def tags for Draw as it hides the background + if ( !bMaster && mbPresentation ) // insert the open tag related to the slide background { mpSVGExport->AddAttribute(u"class"_ustr, u"SlideBackground"_ustr); xDefsExp.reset(new SvXMLElementExport(*mpSVGExport, u"defs"_ustr, true, true)); @@ -2047,27 +2056,49 @@ bool SVGFilter::implExportPage( std::u16string_view sPageId, // into a group element, this group will make up the so named "background objects" if( bMaster ) { - // background objects id = "bo-" + page id - OUString sBackgroundObjectsId = OUString::Concat("bo-") + sPageId; - mpSVGExport->AddAttribute(u"id"_ustr, sBackgroundObjectsId); - if( !mbPresentation ) + // tdf#151746 + // For Draw, we want to wrap the Master Background Objects in defs tags so + // they can be drawn on top of the normal page background later + std::unique_ptr xDefsExp; + if (!mbPresentation) { - if( !mVisiblePagePropSet.bAreBackgroundObjectsVisible ) - { - mpSVGExport->AddAttribute(u"visibility"_ustr, u"hidden"_ustr); - } + xDefsExp.reset(new SvXMLElementExport(*mpSVGExport, u"defs"_ustr, true, true)); } - mpSVGExport->AddAttribute(u"class"_ustr, u"BackgroundObjects"_ustr); - // insert the open tag related to the Background Objects - SvXMLElementExport aExp2(*mpSVGExport, u"g"_ustr, true, true); + { + // background objects id = "bo-" + page id + OUString sBackgroundObjectsId = OUString::Concat("bo-") + sPageId; + mpSVGExport->AddAttribute(u"id"_ustr, sBackgroundObjectsId); + if (!mbPresentation) + { + if (!mVisiblePagePropSet.bAreBackgroundObjectsVisible) + { + mpSVGExport->AddAttribute(u"visibility"_ustr, u"hidden"_ustr); + } + } + mpSVGExport->AddAttribute(u"class"_ustr, u"BackgroundObjects"_ustr); - // append all shapes that make up the Master Slide - bRet = implExportShapes( xShapes, true ) || bRet; - } // append the closing tag related to the Background Objects + // insert the open tag related to the Background Objects + SvXMLElementExport aExp2(*mpSVGExport, u"g"_ustr, true, true); + + // append all shapes that make up the Master Slide + bRet = implExportShapes(xShapes, true) || bRet; + } // append the closing tag related to the Background Objects + } // append the closing tag related to the Background Objects else { + // tdf#151746 + // For Draw, we want to reference the Master Background Objects after the normal page + // background but before the shapes that make up the slides + if ( !mMasterPageTargets.empty() && !mbPresentation ) + { + std::u16string_view sMasterPageId = implGetValidIDFromInterface(mMasterPageTargets[0]); + OUString sMasterObjectsRef = OUString::Concat("#bo-") + sMasterPageId; + mpSVGExport->AddAttribute(u"href"_ustr, sMasterObjectsRef); + SvXMLElementExport aUseElem(*mpSVGExport, u"use"_ustr, true, true); + } // append all shapes that make up the Slide + bRet = implExportShapes( xShapes, false ) || bRet; } } // append the closing tag related to the Slide/Master_Slide @@ -2162,7 +2193,7 @@ bool SVGFilter::implExportShape( const Reference< css::drawing::XShape >& rxShap bool bTextField = bIsPageNumber || bIsFooter || bIsDateTime; if( bTextField ) { - // to notify to the SVGActionWriter::ImplWriteActions method + // to notify the SVGActionWriter::ImplWriteActions method // that we are dealing with a placeholder shape aElementId = sPlaceholderTag; @@ -2592,7 +2623,7 @@ void SVGFilter::implCreateObjectsFromBackground( const Reference< css::drawing:: maPatterProps[ sPageId ] = { nChecksum, aPos, aSize, { nSlideWidth, nSlideHeight } }; - // create meta comment action that is used to exporting + // create meta comment action that is used for exporting // a element which points to the group element representing the background const OUString sBgId = getIdForTiledBackground( sPageId, nChecksum ); OString sComment = sTiledBackgroundTag + " " + sBgId.toUtf8(); @@ -2674,7 +2705,7 @@ IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo, void ) bFieldProcessed = true; if( mpSVGExport->IsEmbedFonts() && mpSVGExport->IsUsePositionedCharacters() ) { - // to notify to the SVGActionWriter::ImplWriteText method + // to notify the SVGActionWriter::ImplWriteText method // that we are dealing with a placeholder shape OUStringBuffer aRepresentation(sPlaceholderTag); diff --git a/filter/source/svg/svgfilter.cxx b/filter/source/svg/svgfilter.cxx index 8521c58b5593..6517f0aac048 100644 --- a/filter/source/svg/svgfilter.cxx +++ b/filter/source/svg/svgfilter.cxx @@ -59,6 +59,9 @@ #include using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; namespace { @@ -521,8 +524,8 @@ bool SVGFilter::filterImpressOrDraw( const Sequence< PropertyValue >& rDescripto else { /* - * We get all master page that are targeted by at least one draw page. - * The master page are put in an unordered set. + * We get all master pages that are targeted by at least one draw page. + * The master pages are put in an unordered set. */ std::unordered_set> aMasterPageTargetSet; for(const uno::Reference & mSelectedPage : mSelectedPages) diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx index 7d1ea55ceb7d..8d784da082ad 100644 --- a/filter/source/svg/svgfilter.hxx +++ b/filter/source/svg/svgfilter.hxx @@ -44,17 +44,9 @@ #include #include -using namespace ::com::sun::star::beans; -using namespace ::com::sun::star::document; -using namespace ::com::sun::star::io; -using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star; -using namespace ::com::sun::star::xml::sax; - namespace com::sun::star::frame { class XController; } -// Placeholder tag used into the ImplWriteActions method to filter text placeholder fields +// Placeholder tag used in the ImplWriteActions method to filter text placeholder fields inline constexpr OUString sPlaceholderTag = u"<[:isPlaceholder:]>"_ustr; // This tag is used for exporting a slide background made of tiled bitmaps inline constexpr OString sTiledBackgroundTag = "SLIDE_BACKGROUND"_ostr; @@ -72,8 +64,8 @@ class SVGExport : public SvXMLExport public: SVGExport( const css::uno::Reference< css::uno::XComponentContext >& rContext, - const Reference< XDocumentHandler >& rxHandler, - const Sequence< PropertyValue >& rFilterData ); + const css::uno::Reference< css::xml::sax::XDocumentHandler >& rxHandler, + const css::uno::Sequence< css::beans::PropertyValue >& rFilterData ); virtual ~SVGExport() override; @@ -102,18 +94,18 @@ class ObjectRepresentation { private: - Reference< XInterface > mxObject; + css::uno::Reference< css::uno::XInterface > mxObject; std::unique_ptr mxMtf; public: ObjectRepresentation(); - ObjectRepresentation(const Reference< XInterface >& rxIf, + ObjectRepresentation(const css::uno::Reference< css::uno::XInterface >& rxIf, const GDIMetaFile& rMtf); ObjectRepresentation(const ObjectRepresentation& rPresentation); ObjectRepresentation& operator=(const ObjectRepresentation& rPresentation); - const Reference< XInterface >& GetObject() const { return mxObject; } + const css::uno::Reference< css::uno::XInterface >& GetObject() const { return mxObject; } bool HasRepresentation() const { return static_cast(mxMtf); } const GDIMetaFile& GetRepresentation() const { return *mxMtf; } }; @@ -165,26 +157,26 @@ class SVGFontExport; class SVGActionWriter; class EditFieldInfo; -class SVGFilter : public cppu::WeakImplHelper < XFilter, - XImporter, - XExporter, - XExtendedFilterDetection, XServiceInfo > +class SVGFilter : public cppu::WeakImplHelper < css::document::XFilter, + css::document::XImporter, + css::document::XExporter, + css::document::XExtendedFilterDetection, css::lang::XServiceInfo > { public: - typedef std::unordered_map< Reference< XInterface >, ObjectRepresentation > ObjectMap; - typedef std::unordered_set< Reference< XInterface > > ObjectSet; + typedef std::unordered_map< css::uno::Reference< css::uno::XInterface >, ObjectRepresentation > ObjectMap; + typedef std::unordered_set< css::uno::Reference< css::uno::XInterface > > ObjectSet; typedef std::unordered_set< sal_Unicode, HashUChar > UCharSet; typedef std::unordered_map< OUString, UCharSet > UCharSetMap; - typedef std::unordered_map< Reference< css::drawing::XDrawPage >, UCharSetMap > UCharSetMapMap; + typedef std::unordered_map< css::uno::Reference< css::drawing::XDrawPage >, UCharSetMap > UCharSetMapMap; typedef std::unordered_set< ObjectRepresentation, HashBitmap, EqualityBitmap > MetaBitmapActionSet; private: - /// Generally use members + /// Generally used members - Reference< XComponentContext > mxContext; + css::uno::Reference< css::uno::XComponentContext > mxContext; SvXMLElementExport* mpSVGDoc; rtl::Reference mpSVGExport; SVGFontExport* mpSVGFontExport; @@ -192,15 +184,15 @@ private: bool mbSinglePage; sal_Int32 mnVisiblePage; ObjectMap* mpObjects; - Reference< XComponent > mxSrcDoc; - Reference< XComponent > mxDstDoc; + css::uno::Reference< css::lang::XComponent > mxSrcDoc; + css::uno::Reference< css::lang::XComponent > mxDstDoc; // #i124608# explicit ShapeSelection for export when export of the selection is wanted - Reference< css::drawing::XShapes > maShapeSelection; + css::uno::Reference< css::drawing::XShapes > maShapeSelection; bool mbExportShapeSelection; - Sequence< PropertyValue > maFilterData; - Reference< css::drawing::XDrawPage > mxDefaultPage; - Reference mxStatusIndicator; - std::vector< Reference< css::drawing::XDrawPage > > mSelectedPages; + css::uno::Sequence< css::beans::PropertyValue > maFilterData; + css::uno::Reference< css::drawing::XDrawPage > mxDefaultPage; + css::uno::Reference mxStatusIndicator; + std::vector< css::uno::Reference< css::drawing::XDrawPage > > mSelectedPages; bool mbIsPreview; bool mbShouldCompress; @@ -216,27 +208,27 @@ private: PagePropertySet mVisiblePagePropSet; OUString msClipPathId; UCharSetMapMap mTextFieldCharSets; - Reference< css::drawing::XDrawPage > mCreateOjectsCurrentMasterPage; - std::unordered_map< Reference< css::drawing::XDrawPage >, OUString > + css::uno::Reference< css::drawing::XDrawPage > mCreateOjectsCurrentMasterPage; + std::unordered_map< css::uno::Reference< css::drawing::XDrawPage >, OUString > mTextShapeIdListMap; MetaBitmapActionSet mEmbeddedBitmapActionSet; ObjectMap mEmbeddedBitmapActionMap; MetaBitmapActionMap maBitmapActionMap; PatternPropertySet maPatterProps; - std::vector< Reference< css::drawing::XDrawPage > > mMasterPageTargets; + std::vector< css::uno::Reference< css::drawing::XDrawPage > > mMasterPageTargets; Link maOldFieldHdl; Link maNewFieldHdl; /// @throws css::uno::RuntimeException - bool implExport( const Sequence< PropertyValue >& rDescriptor ); - bool implExportImpressOrDraw( const Reference< XOutputStream >& rxOStm ); - bool implExportWriterOrCalc( const Reference< XOutputStream >& rxOStm ); - bool implExportWriterTextGraphic( const Reference< view::XSelectionSupplier >& xSelectionSupplier ); + bool implExport( const css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ); + bool implExportImpressOrDraw( const css::uno::Reference< css::io::XOutputStream >& rxOStm ); + bool implExportWriterOrCalc( const css::uno::Reference< css::io::XOutputStream >& rxOStm ); + bool implExportWriterTextGraphic( const css::uno::Reference< css::view::XSelectionSupplier >& xSelectionSupplier ); - static Reference< XWriter > implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm ); + static css::uno::Reference< css::xml::sax::XWriter > implCreateExportDocumentHandler( const css::uno::Reference< css::io::XOutputStream >& rxOStm ); - void implGetPagePropSet( const Reference< css::drawing::XDrawPage > & rxPage ); + void implGetPagePropSet( const css::uno::Reference< css::drawing::XDrawPage > & rxPage ); void implGenerateMetaData(); void implExportTextShapeIndex(); void implEmbedBulletGlyphs(); @@ -253,37 +245,37 @@ private: sal_Int32 nDocWidth, sal_Int32 nDocHeight); void implExportAnimations(); - bool implExportMasterPages( const std::vector< Reference< css::drawing::XDrawPage > >& rxPages, + bool implExportMasterPages( const std::vector< css::uno::Reference< css::drawing::XDrawPage > >& rxPages, sal_Int32 nFirstPage, sal_Int32 nLastPage ); - void implExportDrawPages( const std::vector< Reference< css::drawing::XDrawPage > >& rxPages, + void implExportDrawPages( const std::vector< css::uno::Reference< css::drawing::XDrawPage > >& rxPages, sal_Int32 nFirstPage, sal_Int32 nLastPage ); bool implExportPage( std::u16string_view sPageId, - const Reference< css::drawing::XDrawPage > & rxPage, - const Reference< css::drawing::XShapes > & xShapes, + const css::uno::Reference< css::drawing::XDrawPage > & rxPage, + const css::uno::Reference< css::drawing::XShapes > & xShapes, bool bMaster ); - bool implExportShapes( const Reference< css::drawing::XShapes >& rxShapes, + bool implExportShapes( const css::uno::Reference< css::drawing::XShapes >& rxShapes, bool bMaster ); - bool implExportShape( const Reference< css::drawing::XShape >& rxShape, + bool implExportShape( const css::uno::Reference< css::drawing::XShape >& rxShape, bool bMaster ); bool implCreateObjects(); - bool implCreateObjectsFromShapes( const Reference< css::drawing::XDrawPage > & rxPage, const Reference< css::drawing::XShapes >& rxShapes ); - bool implCreateObjectsFromShape( const Reference< css::drawing::XDrawPage > & rxPage, const Reference< css::drawing::XShape >& rxShape ); - void implCreateObjectsFromBackground( const Reference< css::drawing::XDrawPage >& rxMasterPage ); + bool implCreateObjectsFromShapes( const css::uno::Reference< css::drawing::XDrawPage > & rxPage, const css::uno::Reference< css::drawing::XShapes >& rxShapes ); + bool implCreateObjectsFromShape( const css::uno::Reference< css::drawing::XDrawPage > & rxPage, const css::uno::Reference< css::drawing::XShape >& rxShape ); + void implCreateObjectsFromBackground( const css::uno::Reference< css::drawing::XDrawPage >& rxMasterPage ); - static OUString implGetClassFromShape( const Reference< css::drawing::XShape >& rxShape ); - void implRegisterInterface( const Reference< XInterface >& rxIf ); - const OUString & implGetValidIDFromInterface( const Reference< XInterface >& rxIf ); - static OUString implGetInterfaceName( const Reference< XInterface >& rxIf ); + static OUString implGetClassFromShape( const css::uno::Reference< css::drawing::XShape >& rxShape ); + void implRegisterInterface( const css::uno::Reference< css::uno::XInterface >& rxIf ); + const OUString & implGetValidIDFromInterface( const css::uno::Reference< css::uno::XInterface >& rxIf ); + static OUString implGetInterfaceName( const css::uno::Reference< css::uno::XInterface >& rxIf ); bool implLookForFirstVisiblePage(); - static Any implSafeGetPagePropSet( const OUString & sPropertyName, - const Reference< XPropertySet > & rxPropSet, - const Reference< XPropertySetInfo > & rxPropSetInfo ); + static css::uno::Any implSafeGetPagePropSet( const OUString & sPropertyName, + const css::uno::Reference< css::beans::XPropertySet > & rxPropSet, + const css::uno::Reference< css::beans::XPropertySetInfo > & rxPropSetInfo ); DECL_LINK( CalcFieldHdl, EditFieldInfo*, void ); - bool filterImpressOrDraw( const Sequence< PropertyValue >& rDescriptor ); - bool filterWriterOrCalc( const Sequence< PropertyValue >& rDescriptor ); + bool filterImpressOrDraw( const css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ); + bool filterWriterOrCalc( const css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ); css::uno::Reference getSourceController() const; css::uno::Reference fillDrawImpressSelectedPages(); @@ -291,21 +283,21 @@ private: protected: // XFilter - virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& rDescriptor ) override; + virtual sal_Bool SAL_CALL filter( const css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ) override; virtual void SAL_CALL cancel( ) override; // XImporter - virtual void SAL_CALL setTargetDocument( const Reference< XComponent >& xDoc ) override; + virtual void SAL_CALL setTargetDocument( const css::uno::Reference< css::lang::XComponent >& xDoc ) override; // XExporter - virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) override; + virtual void SAL_CALL setSourceDocument( const css::uno::Reference< css::lang::XComponent >& xDoc ) override; // XExtendedFilterDetection - virtual OUString SAL_CALL detect( Sequence< PropertyValue >& io_rDescriptor ) override; + virtual OUString SAL_CALL detect( css::uno::Sequence< css::beans::PropertyValue >& io_rDescriptor ) override; public: - explicit SVGFilter( const Reference< XComponentContext >& rxCtx ); + explicit SVGFilter( const css::uno::Reference< css::uno::XComponentContext >& rxCtx ); virtual ~SVGFilter() override; // XServiceInfo diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx index 47c5faf47bca..0c7a631127ad 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -55,7 +55,14 @@ #include +using namespace ::com::sun::star; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; using namespace ::com::sun::star::style; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; constexpr OUString aPrefixClipPathId = u"clip_path_"_ustr; @@ -2170,7 +2177,9 @@ void SVGActionWriter::ImplAddLineAttr( const LineInfo &rAttrs ) { if (!aDashArrayStr.isEmpty()) aDashArrayStr.append(","); - aDashArrayStr.append(x); + // tdf#86206 - map dash lengths to ensure correct dash pattern in scaled documents + const sal_Int32 nDash = ImplMap(basegfx::fround(x)); + aDashArrayStr.append(nDash); } if (!aDashArrayStr.isEmpty()) mrExport.AddAttribute(u"stroke-dasharray"_ustr, aDashArrayStr.makeStringAndClear()); @@ -2529,17 +2538,6 @@ void SVGActionWriter::ImplWriteGradientStop( const Color& rColor, double fOffset } } - -Color SVGActionWriter::ImplGetColorWithIntensity( const Color& rColor, - sal_uInt16 nIntensity ) -{ - sal_uInt8 nNewRed = static_cast( static_cast(rColor.GetRed()) * nIntensity / 100 ); - sal_uInt8 nNewGreen = static_cast( static_cast(rColor.GetGreen()) * nIntensity / 100 ); - sal_uInt8 nNewBlue = static_cast( static_cast(rColor.GetBlue()) * nIntensity / 100 ); - return Color( nNewRed, nNewGreen, nNewBlue); -} - - void SVGActionWriter::StartMask(const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, sal_uInt32 nWriteFlags, const basegfx::BColorStops* pColorStops, OUString* pTextFillOpacity) @@ -3004,8 +3002,13 @@ void SVGActionWriter::ImplWriteBmp( const Bitmap& rBmp, Size aSize; ImplMap( rSz, aSize ); - double fFractionX = double(aSize.Width()) / rSourceRect.GetWidth(); - double fFractionY = double(aSize.Height()) / rSourceRect.GetHeight(); + double fFractionX(0.0); + if (rSourceRect.GetWidth()) + fFractionX = double(aSize.Width()) / rSourceRect.GetWidth(); + + double fFractionY(0.0); + if (rSourceRect.GetHeight()) + fFractionY = double(aSize.Height()) / rSourceRect.GetHeight(); double scaleX = rtl_math_round( fFractionX, 3, rtl_math_RoundingMode::rtl_math_RoundingMode_Corrected ); double scaleY = rtl_math_round( fFractionY, 3, rtl_math_RoundingMode::rtl_math_RoundingMode_Corrected ); if( !rtl_math_approxEqual( scaleX, 1.0 ) || !rtl_math_approxEqual( scaleY, 1.0 ) ) @@ -3523,7 +3526,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, double fOff, fR, fG, fB; aMemStm.ReadUInt16( nTmp ); - const size_t nMaxPossibleEntries = aMemStm.remainingSize() / 4 * sizeof(double); + const size_t nMaxPossibleEntries = aMemStm.remainingSize() / (4 * sizeof(double)); if (nTmp > nMaxPossibleEntries) { SAL_WARN("filter.svg", "gradient record claims to have: " << nTmp << " entries, but only " << nMaxPossibleEntries << " possible, clamping"); @@ -3674,7 +3677,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, if(1 != mapCurShape->maShapePolyPoly.Count() || !mapCurShape->maShapePolyPoly[0].IsEqual(aPoly)) { - // this path action is not covering the same path than the already existing + // this path action is not covering the same path as the already existing // fill polypolygon, so write out the fill polygon ImplWriteShape( *mapCurShape ); mapCurShape.reset(); diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx index 8b9b531caa38..0d1f392f8eaa 100644 --- a/filter/source/svg/svgwriter.hxx +++ b/filter/source/svg/svgwriter.hxx @@ -43,13 +43,6 @@ namespace basegfx { class BColorStops; } -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::container; -using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::text; -using namespace ::com::sun::star::svg; -using namespace ::com::sun::star::xml::sax; - inline constexpr OUString SVG_DTD_STRING = u""_ustr; #define SVGWRITER_WRITE_FILL 0x00000001 @@ -198,12 +191,12 @@ class SVGTextWriter final SVGActionWriter& mrActionWriter; VclPtr mpVDev; bool mbIsTextShapeStarted; - Reference mrTextShape; + css::uno::Reference mrTextShape; OUString msShapeId; - Reference mrParagraphEnumeration; - Reference mrCurrentTextParagraph; - Reference mrTextPortionEnumeration; - Reference mrCurrentTextPortion; + css::uno::Reference mrParagraphEnumeration; + css::uno::Reference mrCurrentTextParagraph; + css::uno::Reference mrTextPortionEnumeration; + css::uno::Reference mrCurrentTextPortion; const GDIMetaFile* mpTextEmbeddedBitmapMtf; MapMode* mpTargetMapMode; std::unique_ptr mpTextShapeElem; @@ -271,7 +264,7 @@ class SVGTextWriter final mpTargetMapMode = &rTargetMapMode; } - void setTextShape( const Reference& rxText, + void setTextShape( const css::uno::Reference& rxText, const GDIMetaFile* pTextEmbeddedBitmapMtf ) { mrTextShape.set( rxText ); @@ -289,8 +282,8 @@ class SVGTextWriter final template< typename SubType > bool implGetTextPositionFromBitmap( const MetaAction* pAction, Point& raPos, bool& rbEmpty ); - void implRegisterInterface( const Reference< XInterface >& rxIf ); - const OUString & implGetValidIDFromInterface( const Reference< XInterface >& rxIf ); + void implRegisterInterface( const css::uno::Reference& rxIf ); + const OUString & implGetValidIDFromInterface( const css::uno::Reference& rxIf ); }; @@ -341,7 +334,6 @@ private: void ImplWriteGradientEx( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient, sal_uInt32 nWriteFlags, const basegfx::BColorStops* pColorStops); void ImplWriteGradientLinear( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient, const basegfx::BColorStops* pColorStops ); void ImplWriteGradientStop( const Color& rColor, double fOffset ); - static Color ImplGetColorWithIntensity( const Color& rColor, sal_uInt16 nIntensity ); void ImplWriteMask( GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, sal_uInt32 nWriteFlags, const basegfx::BColorStops* pColorStops); void ImplWriteText( const Point& rPos, const OUString& rText, KernArraySpan pDXArray, tools::Long nWidth ); void ImplWriteText( const Point& rPos, const OUString& rText, KernArraySpan pDXArray, tools::Long nWidth, Color aTextColor ); @@ -350,7 +342,7 @@ private: void ImplWriteActions( const GDIMetaFile& rMtf, sal_uInt32 nWriteFlags, const OUString& aElementId, - const Reference< css::drawing::XShape >* pXShape = nullptr, + const css::uno::Reference< css::drawing::XShape >* pXShape = nullptr, const GDIMetaFile* pTextEmbeddedBitmapMtf = nullptr ); vcl::Font ImplSetCorrectFontHeight() const; @@ -369,7 +361,7 @@ public: const GDIMetaFile& rMtf, sal_uInt32 nWriteFlags, const OUString& aElementId = u""_ustr, - const Reference< css::drawing::XShape >* pXShape = nullptr, + const css::uno::Reference< css::drawing::XShape >* pXShape = nullptr, const GDIMetaFile* pTextEmbeddedBitmapMtf = nullptr ); void SetEmbeddedBitmapRefs( const MetaBitmapActionMap* pEmbeddedBitmapsMap ); @@ -379,20 +371,20 @@ public: }; -class SVGWriter : public cppu::WeakImplHelper< XSVGWriter, XServiceInfo > +class SVGWriter : public cppu::WeakImplHelper { private: - Reference< XComponentContext > mxContext; - Sequence< css::beans::PropertyValue > maFilterData; + css::uno::Reference mxContext; + css::uno::Sequence< css::beans::PropertyValue > maFilterData; public: - explicit SVGWriter( const Sequence& args, - const Reference< XComponentContext >& rxCtx ); + explicit SVGWriter( const css::uno::Sequence& args, + const css::uno::Reference& rxCtx ); virtual ~SVGWriter() override; // XSVGWriter - virtual void SAL_CALL write( const Reference& rxDocHandler, - const Sequence& rMtfSeq ) override; + virtual void SAL_CALL write( const css::uno::Reference& rxDocHandler, + const css::uno::Sequence& rMtfSeq ) override; // XServiceInfo virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override; diff --git a/filter/source/xslt/import/wordml/wordml2ooo_text.xsl b/filter/source/xslt/import/wordml/wordml2ooo_text.xsl index e2b94b3ec51f..d147629cb63a 100644 --- a/filter/source/xslt/import/wordml/wordml2ooo_text.xsl +++ b/filter/source/xslt/import/wordml/wordml2ooo_text.xsl @@ -1001,21 +1001,37 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/filter/source/xslt/odf2xhtml/export/common/body.xsl b/filter/source/xslt/odf2xhtml/export/common/body.xsl index 8dfb78222186..28bbf0c241a0 100644 --- a/filter/source/xslt/odf2xhtml/export/common/body.xsl +++ b/filter/source/xslt/odf2xhtml/export/common/body.xsl @@ -24,6 +24,17 @@ + + ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_ + + + + + + + @@ -87,10 +98,14 @@ - + + + - + + + @@ -141,10 +156,14 @@ - + + + - + + + @@ -163,10 +182,14 @@ - + + + - + + + @@ -182,10 +205,14 @@ - + + + - + + + @@ -206,10 +233,14 @@ - + + + - + + + @@ -330,7 +361,9 @@ - + + + diff --git a/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl b/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl index 0f36b36486de..22706aeb9769 100644 --- a/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl +++ b/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl @@ -527,7 +527,9 @@ Scenarios unmatched: - + + + diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl index d28ed42dcbd9..45c4f7cba468 100644 --- a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl +++ b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl @@ -1292,7 +1292,9 @@ - + + + @@ -2671,7 +2673,9 @@ - + + + diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx index eb89c94b4925..8ad80402b5b7 100644 --- a/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx +++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx b/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx index 06ecb5b789eb..f9380d8ef3b2 100644 --- a/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx +++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx @@ -20,10 +20,10 @@ #include #include +#include #include #include #include -#include #include #include diff --git a/filter/source/xsltdialog/xmlfiltertabdialog.cxx b/filter/source/xsltdialog/xmlfiltertabdialog.cxx index 401b50d1a011..db7796298651 100644 --- a/filter/source/xsltdialog/xmlfiltertabdialog.cxx +++ b/filter/source/xsltdialog/xmlfiltertabdialog.cxx @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/filter/source/xsltdialog/xmlfiltertabdialog.hxx b/filter/source/xsltdialog/xmlfiltertabdialog.hxx index 0a404340a5e7..839a940d13de 100644 --- a/filter/source/xsltdialog/xmlfiltertabdialog.hxx +++ b/filter/source/xsltdialog/xmlfiltertabdialog.hxx @@ -19,9 +19,10 @@ #pragma once #include +#include #include #include -#include +#include class filter_info_impl; class XMLFilterTabPageBasic; diff --git a/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx b/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx index 95fe7bef3f2a..fbdab2f151fc 100644 --- a/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx +++ b/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx @@ -22,7 +22,6 @@ #include #include #include -#include class filter_info_impl; diff --git a/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx b/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx index 68bf7a937cfc..8426d94a2584 100644 --- a/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx +++ b/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx @@ -19,8 +19,9 @@ #pragma once #include +#include +#include #include -#include #include class filter_info_impl; diff --git a/filter/source/xsltdialog/xmlfiltertestdialog.hxx b/filter/source/xsltdialog/xmlfiltertestdialog.hxx index dd71bc94e195..c9a571da60a0 100644 --- a/filter/source/xsltdialog/xmlfiltertestdialog.hxx +++ b/filter/source/xsltdialog/xmlfiltertestdialog.hxx @@ -23,8 +23,11 @@ #include #include +#include +#include #include -#include +#include +#include class filter_info_impl; class GlobalEventListenerImpl; diff --git a/filter/source/xsltfilter/LibXSLTTransformer.cxx b/filter/source/xsltfilter/LibXSLTTransformer.cxx index 4defe3ff160d..2282ff0e9b3e 100644 --- a/filter/source/xsltfilter/LibXSLTTransformer.cxx +++ b/filter/source/xsltfilter/LibXSLTTransformer.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -307,6 +308,7 @@ namespace XSLT xsltDebugDumpExtensions(NULL); #endif std::optional oh(std::in_place, m_transformer->getComponentContext()); + xsltSecurityPrefsPtr securityPrefs = nullptr; if (styleSheet) { xsltTransformContextPtr tcontext = xsltNewTransformContext( @@ -317,8 +319,23 @@ namespace XSLT } oh->registercontext(tcontext); xsltQuoteUserParams(tcontext, params.data()); - result = xsltApplyStylesheetUser(styleSheet, doc, nullptr, nullptr, nullptr, - tcontext); + // A stylesheet builds the result tree and nothing else. Refuse every option libxslt + // has, then allow back the local reads, which is how a stylesheet picks up a second + // file that sits beside the one it converts. + securityPrefs = xsltNewSecurityPrefs(); + if (securityPrefs) + { + for (auto eOption : { XSLT_SECPREF_READ_FILE, XSLT_SECPREF_WRITE_FILE, + XSLT_SECPREF_CREATE_DIRECTORY, XSLT_SECPREF_READ_NETWORK, + XSLT_SECPREF_WRITE_NETWORK }) + xsltSetSecurityPrefs(securityPrefs, eOption, xsltSecurityForbid); + xsltSetSecurityPrefs(securityPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityAllow); + } + if (securityPrefs && xsltSetCtxtSecurityPrefs(securityPrefs, tcontext) == 0) + result = xsltApplyStylesheetUser(styleSheet, doc, nullptr, nullptr, nullptr, + tcontext); + else + m_transformer->error(u"No security preferences were applied"_ustr); } if (result) @@ -351,6 +368,7 @@ namespace XSLT std::swap(m_tcontext, tcontext); } xsltFreeTransformContext(tcontext); + xsltFreeSecurityPrefs(securityPrefs); xmlFreeDoc(doc); xmlFreeDoc(result); } diff --git a/filter/uiconfig/ui/pdfoptionsdialog.ui b/filter/uiconfig/ui/pdfoptionsdialog.ui index bf2e4930304c..c7fc68e55fd6 100644 --- a/filter/uiconfig/ui/pdfoptionsdialog.ui +++ b/filter/uiconfig/ui/pdfoptionsdialog.ui @@ -20,19 +20,6 @@ False end - - - _Reset - True - True - True - - - False - True - 0 - - E_xport @@ -46,7 +33,7 @@ False True - 1 + 0 @@ -60,7 +47,7 @@ False True - 2 + 1 @@ -74,7 +61,7 @@ False True - 3 + 2 True diff --git a/forms/CppunitTest_forms_unit.mk b/forms/CppunitTest_forms_unit.mk new file mode 100644 index 000000000000..4a740fe34417 --- /dev/null +++ b/forms/CppunitTest_forms_unit.mk @@ -0,0 +1,39 @@ +# -*- 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,forms_unit)) + +$(eval $(call gb_CppunitTest_use_sdk_api,forms_unit)) + +$(eval $(call gb_CppunitTest_use_externals,forms_unit, \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,forms_unit, \ + forms/qa/unit/forms_test \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,forms_unit, \ + comphelper \ + cppu \ + cppuhelper \ + sal \ + subsequenttest \ + test \ + tl \ + unotest \ + utl \ +)) + +$(eval $(call gb_CppunitTest_use_ure,forms_unit)) +$(eval $(call gb_CppunitTest_use_vcl,forms_unit)) +$(eval $(call gb_CppunitTest_use_rdb,forms_unit,services)) +$(eval $(call gb_CppunitTest_use_configuration,forms_unit)) + +# vim: set noet sw=4 ts=4: diff --git a/forms/Module_forms.mk b/forms/Module_forms.mk index 7ba484b81d3a..d708317c3b31 100644 --- a/forms/Module_forms.mk +++ b/forms/Module_forms.mk @@ -13,6 +13,10 @@ $(eval $(call gb_Module_add_targets,forms,\ Library_frm \ )) +$(eval $(call gb_Module_add_check_targets,forms,\ + CppunitTest_forms_unit \ +)) + $(eval $(call gb_Module_add_l10n_targets,forms,\ AllLangMoTarget_frm \ )) diff --git a/forms/qa/integration/forms/DocumentHelper.java b/forms/qa/integration/forms/DocumentHelper.java index 64caf0a152e6..984c3c8ea4a2 100644 --- a/forms/qa/integration/forms/DocumentHelper.java +++ b/forms/qa/integration/forms/DocumentHelper.java @@ -240,7 +240,7 @@ public class DocumentHelper /* ------------------------------------------------------------------ */ /** creates a form which is a sibling of the given form @param aForm - A sinbling of the to be created form. + A sibling of the to be created form. @param sInitialName The initial name of the form. May be null, in this case the default (which @@ -329,7 +329,7 @@ public class DocumentHelper xReturn = UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( 0 ) ); - // Note that this is no really error-proof code: If the document model does not support the + // Note that this is not really error-proof code: If the document model does not support the // XDrawPagesSupplier interface, or if the pages collection returned is empty, this will break. } diff --git a/forms/qa/unit/forms_test.cxx b/forms/qa/unit/forms_test.cxx new file mode 100644 index 000000000000..6a45d3d565c7 --- /dev/null +++ b/forms/qa/unit/forms_test.cxx @@ -0,0 +1,53 @@ +/* -*- 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 +#include +#include + +using namespace com::sun::star; + +namespace +{ +class FormsTest : public UnoApiTest +{ +public: + FormsTest() + : UnoApiTest(u""_ustr) + { + } + + uno::Reference createFormComponent(const OUString& rServiceName) + { + return uno::Reference( + comphelper::getProcessServiceFactory()->createInstance(rServiceName), + uno::UNO_QUERY_THROW); + } +}; + +CPPUNIT_TEST_FIXTURE(FormsTest, testTdf51727_GridControlTabStopDefault) +{ + auto xModel = createFormComponent(u"com.sun.star.form.component.GridControl"_ustr); + + // Without the fix in place, this test would have failed with + // - Expected: false + // - Actual : void + // i.e. the tab stop property of the grid control was not initialized correctly + uno::Any aTabStop = xModel->getPropertyValue(u"Tabstop"_ustr); + CPPUNIT_ASSERT(aTabStop.hasValue()); + bool bTabStop = true; + CPPUNIT_ASSERT(aTabStop >>= bTabStop); + CPPUNIT_ASSERT_EQUAL(false, bTabStop); +} + +} // namespace + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/forms/source/component/Grid.cxx b/forms/source/component/Grid.cxx index 67957dbfff88..ba2e0b107063 100644 --- a/forms/source/component/Grid.cxx +++ b/forms/source/component/Grid.cxx @@ -82,6 +82,8 @@ OGridControlModel::OGridControlModel(const Reference& _rxFact ,m_bDisplaySynchron(true) { m_nClassId = FormComponentType::GRIDCONTROL; + // tdf#51727 - explicitly set to false so tab navigation skips this control by default + m_aTabStop <<= false; } OGridControlModel::OGridControlModel( const OGridControlModel* _pOriginal, const Reference< XComponentContext >& _rxFactory ) @@ -104,6 +106,7 @@ OGridControlModel::OGridControlModel( const OGridControlModel* _pOriginal, const m_bPrintable = _pOriginal->m_bPrintable; m_bAlwaysShowCursor = _pOriginal->m_bAlwaysShowCursor; m_bDisplaySynchron = _pOriginal->m_bDisplaySynchron; + m_aTabStop = _pOriginal->m_aTabStop; // clone the columns cloneColumns( _pOriginal ); // TODO: clone the events? @@ -662,6 +665,7 @@ Any OGridControlModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const aReturn <<= true; break; case PROPERTY_ID_ALWAYSSHOWCURSOR: + case PROPERTY_ID_TABSTOP: aReturn <<= false; break; case PROPERTY_ID_HELPURL: @@ -672,7 +676,6 @@ Any OGridControlModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const aReturn <<= sal_Int16(1); break; case PROPERTY_ID_BORDERCOLOR: - case PROPERTY_ID_TABSTOP: case PROPERTY_ID_BACKGROUNDCOLOR: case PROPERTY_ID_ROWHEIGHT: case PROPERTY_ID_CURSORCOLOR: diff --git a/forms/source/component/clickableimage.cxx b/forms/source/component/clickableimage.cxx index 634b57c27094..2698e5710f28 100644 --- a/forms/source/component/clickableimage.cxx +++ b/forms/source/component/clickableimage.cxx @@ -745,10 +745,10 @@ namespace frm if (!rURL.isEmpty() && !::svt::GraphicAccess::isSupportedURL( rURL ) ) { - m_pMedium.reset(new SfxMedium(rURL, StreamMode::STD_READ)); - SfxObjectShell *pObjSh = GetObjectShell(); + m_pMedium.reset(new SfxMedium(rURL, StreamMode::STD_READ)); + if( pObjSh ) { // Transfer target frame, so that javascript: URLs diff --git a/forms/source/component/formcontrolfont.cxx b/forms/source/component/formcontrolfont.cxx index 9f6663d09c71..9f8b9ed62e56 100644 --- a/forms/source/component/formcontrolfont.cxx +++ b/forms/source/component/formcontrolfont.cxx @@ -491,7 +491,7 @@ namespace frm Any FontControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const { Any aReturn; - // some defaults which are the same, not matter if we have toolkit-compatible + // some defaults which are the same, no matter if we have toolkit-compatible // defaults or not bool bHandled = false; switch( _nHandle ) diff --git a/forms/source/component/propertybaghelper.cxx b/forms/source/component/propertybaghelper.cxx index 34c4b7926cae..74a2522c1194 100644 --- a/forms/source/component/propertybaghelper.cxx +++ b/forms/source/component/propertybaghelper.cxx @@ -142,35 +142,24 @@ namespace frm ::comphelper::OPropertyArrayAggregationHelper& PropertyBagHelper::impl_ts_getArrayHelper() const { - OPropertyArrayAggregationHelper* p = m_pPropertyArrayHelper.get(); - if ( !p ) + ::osl::MutexGuard aGuard( m_rContext.getMutex() ); + if (!m_pPropertyArrayHelper) { - ::osl::MutexGuard aGuard( m_rContext.getMutex() ); - p = m_pPropertyArrayHelper.get(); - if ( !p ) - { - // our own fixed and our aggregate's properties - Sequence< Property > aFixedProps; - Sequence< Property > aAggregateProps; - m_rContext.describeFixedAndAggregateProperties( aFixedProps, aAggregateProps ); + // our own fixed and our aggregate's properties + Sequence< Property > aFixedProps; + Sequence< Property > aAggregateProps; + m_rContext.describeFixedAndAggregateProperties( aFixedProps, aAggregateProps ); - // our dynamic properties - Sequence< Property > aDynamicProps; - m_aDynamicProperties.describeProperties( aDynamicProps ); + // our dynamic properties + Sequence< Property > aDynamicProps; + m_aDynamicProperties.describeProperties( aDynamicProps ); - Sequence< Property > aOwnProps( - ::comphelper::concatSequences( aFixedProps, aDynamicProps ) ); + Sequence< Property > aOwnProps( + ::comphelper::concatSequences( aFixedProps, aDynamicProps ) ); - p = new OPropertyArrayAggregationHelper( aOwnProps, aAggregateProps, &lcl_getPropertyInfos(), NEW_HANDLE_BASE ); - OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); - const_cast< PropertyBagHelper* >( this )->m_pPropertyArrayHelper.reset( p ); - } - } // if ( !p ) - else - { - OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + const_cast(this)->m_pPropertyArrayHelper = std::make_unique( aOwnProps, aAggregateProps, &lcl_getPropertyInfos(), NEW_HANDLE_BASE ); } - return *p; + return *m_pPropertyArrayHelper; } diff --git a/forms/source/helper/controlfeatureinterception.cxx b/forms/source/helper/controlfeatureinterception.cxx index 924a1a0041fc..2fe6915df393 100644 --- a/forms/source/helper/controlfeatureinterception.cxx +++ b/forms/source/helper/controlfeatureinterception.cxx @@ -72,7 +72,7 @@ namespace frm { // our chain will have a new first element m_xFirstDispatchInterceptor.set(m_xFirstDispatchInterceptor->getSlaveDispatchProvider(), UNO_QUERY); } - // do this before removing the interceptor from the chain as we won't know it's slave afterwards) + // do this before removing the interceptor from the chain as we won't know its slave afterwards while ( xChainWalk.is() ) { @@ -116,7 +116,7 @@ namespace frm // ask for its successor Reference< XDispatchProvider > xSlave = xInterceptor->getSlaveDispatchProvider(); - // and give it the new (means no) successoert + // and give it the new (means no) successor xInterceptor->setSlaveDispatchProvider( nullptr ); // start over with the next chain element diff --git a/forms/source/inc/FormComponent.hxx b/forms/source/inc/FormComponent.hxx index ee28dcc8a42a..2bf542da4eb7 100644 --- a/forms/source/inc/FormComponent.hxx +++ b/forms/source/inc/FormComponent.hxx @@ -616,7 +616,7 @@ protected: /** initializes the part of the class which is related to the control value.

Kind of late ctor, to be called for derivees which have a dedicated value property.
- The value property is the property which's value is synced with either the database + The value property is the property whose value is synced with either the database column the object is bound to, or with the external value binding, if present.
E.g. for a text control model, this property will most probably be "Text".

@@ -629,7 +629,7 @@ protected: aggregate then.

@precond - The method has not be called before during the life time of the object. + The method has not been called before during the life time of the object. @param _rValuePropertyName the name of the value property diff --git a/forms/source/inc/formnavigation.hxx b/forms/source/inc/formnavigation.hxx index 50f313325b24..aec8c118301b 100644 --- a/forms/source/inc/formnavigation.hxx +++ b/forms/source/inc/formnavigation.hxx @@ -97,8 +97,8 @@ namespace frm virtual sal_Int32 getIntegerState( sal_Int16 _nFeatureId ) const override; // own overridables - /** is called when the interceptors have. -

The default implementations simply calls updateDispatches, + /** is called when the interceptors have changed. +

The default implementation simply calls updateDispatches, derived classes can prevent this in certain cases, or do additional handling.

*/ virtual void interceptorsChanged( ); @@ -107,21 +107,21 @@ namespace frm

The default implementation does nothing.

-

If the feature in question does support more state information that just the +

If the feature in question does support more state information than just the enabled/disabled state, then this additional information is to be retrieved in a separate call.

@param _nFeatureId the id of the feature @param _bEnabled - determines if the features is enabled or disabled + determines if the feature is enabled or disabled @see getBooleanState */ virtual void featureStateChanged( sal_Int16 _nFeatureId, bool _bEnabled ); /** notification for (potential) changes in the state of all features

The base class implementation does nothing. Derived classes could force - their peer to update it's state, depending on the result of calls to + their peer to update its state, depending on the result of calls to IFeatureDispatcher::isEnabled.

*/ virtual void allFeatureStatesChanged( ); @@ -200,7 +200,7 @@ namespace frm @complexity O(n), with n being the number of all potentially known URLs @return - the id of the feature URL, or -1 if the URl is not known + the id of the feature URL, or -1 if the URL is not known (which is a valid usage) */ static sal_Int16 getFeatureId( std::u16string_view _rCompleteURL ); diff --git a/forms/source/misc/InterfaceContainer.cxx b/forms/source/misc/InterfaceContainer.cxx index 50935403e6fe..68c4f34285c9 100644 --- a/forms/source/misc/InterfaceContainer.cxx +++ b/forms/source/misc/InterfaceContainer.cxx @@ -105,45 +105,41 @@ void OInterfaceContainer::impl_addVbEvents_nolck_nothrow( const sal_Int32 i_nIn // we are dealing with form controls try { - do - { - Reference< XModel > xDoc( getXModel( static_cast< XContainer *> ( this ) ) ); - if ( !xDoc.is() ) - break; + Reference< XModel > xDoc( getXModel( static_cast< XContainer *> ( this ) ) ); + if ( !xDoc.is() ) + return; - Reference< XMultiServiceFactory > xDocFac( xDoc, UNO_QUERY_THROW ); - Reference< XCodeNameQuery > xNameQuery( xDocFac->createInstance(u"ooo.vba.VBACodeNameProvider"_ustr), UNO_QUERY ); - if ( !xNameQuery.is() ) - break; + Reference< XMultiServiceFactory > xDocFac( xDoc, UNO_QUERY_THROW ); + Reference< XCodeNameQuery > xNameQuery( xDocFac->createInstance(u"ooo.vba.VBACodeNameProvider"_ustr), UNO_QUERY ); + if ( !xNameQuery.is() ) + return; - ::osl::MutexGuard aGuard( m_rMutex ); - bool hasVBABindings = lcl_hasVbaEvents( m_xEventAttacher->getScriptEvents( i_nIndex ) ); - if ( hasVBABindings ) - break; + ::osl::MutexGuard aGuard( m_rMutex ); + bool hasVBABindings = lcl_hasVbaEvents( m_xEventAttacher->getScriptEvents( i_nIndex ) ); + if ( hasVBABindings ) + return; - Reference< XInterface > xElement( getByIndex( i_nIndex ) , UNO_QUERY_THROW ); - Reference< XForm > xElementAsForm( xElement, UNO_QUERY ); - if ( xElementAsForm.is() ) - break; + Reference< XInterface > xElement( getByIndex( i_nIndex ) , UNO_QUERY_THROW ); + Reference< XForm > xElementAsForm( xElement, UNO_QUERY ); + if ( xElementAsForm.is() ) + return; - // Try getting the code name from the container first (faster), - // then from the element if that fails (slower). - Reference xThis = static_cast(this); - OUString sCodeName = xNameQuery->getCodeNameForContainer(xThis); - if (sCodeName.isEmpty()) - sCodeName = xNameQuery->getCodeNameForObject(xElement); + // Try getting the code name from the container first (faster), + // then from the element if that fails (slower). + Reference xThis = static_cast(this); + OUString sCodeName = xNameQuery->getCodeNameForContainer(xThis); + if (sCodeName.isEmpty()) + sCodeName = xNameQuery->getCodeNameForObject(xElement); - Reference< XPropertySet > xProps( xElement, UNO_QUERY_THROW ); - OUString sServiceName; - xProps->getPropertyValue(u"DefaultControl"_ustr) >>= sServiceName; + Reference< XPropertySet > xProps( xElement, UNO_QUERY_THROW ); + OUString sServiceName; + xProps->getPropertyValue(u"DefaultControl"_ustr) >>= sServiceName; - Reference< ooo::vba::XVBAToOOEventDescGen > xDescSupplier( m_xContext->getServiceManager()->createInstanceWithContext(u"ooo.vba.VBAToOOEventDesc"_ustr, m_xContext), UNO_QUERY_THROW ); - Sequence< ScriptEventDescriptor > vbaEvents = xDescSupplier->getEventDescriptions( sServiceName , sCodeName ); + Reference< ooo::vba::XVBAToOOEventDescGen > xDescSupplier( m_xContext->getServiceManager()->createInstanceWithContext(u"ooo.vba.VBAToOOEventDesc"_ustr, m_xContext), UNO_QUERY_THROW ); + Sequence< ScriptEventDescriptor > vbaEvents = xDescSupplier->getEventDescriptions( sServiceName , sCodeName ); - // register the vba script events - m_xEventAttacher->registerScriptEvents( i_nIndex, vbaEvents ); - } - while ( false ); + // register the vba script events + m_xEventAttacher->registerScriptEvents( i_nIndex, vbaEvents ); } catch ( const ServiceNotRegisteredException& ) { @@ -778,7 +774,7 @@ void OInterfaceContainer::implInsert(sal_Int32 _nIndex, const Reference< XProper } - // approveNewElement (no matter if called here or outside) has ensure that all relevant interfaces + // approveNewElement (no matter if called here or outside) has ensured that all relevant interfaces // exist // set the name, and add as change listener for the name diff --git a/forms/source/richtext/featuredispatcher.hxx b/forms/source/richtext/featuredispatcher.hxx index 5c863f10f8eb..d1945cb035a2 100644 --- a/forms/source/richtext/featuredispatcher.hxx +++ b/forms/source/richtext/featuredispatcher.hxx @@ -60,7 +60,7 @@ namespace frm /// clean up resources associated with this instance void dispose(); - // invalidate the feature, re-retrieve it's state, and broadcast changes, if necessary + // invalidate the feature, re-retrieve its state, and broadcast changes, if necessary void invalidate(); protected: @@ -68,7 +68,7 @@ namespace frm virtual void disposing( ::osl::ClearableMutexGuard& _rClearBeforeNotify ); virtual void invalidateFeatureState_Broadcast(); - // to be overridden, and filled with the info special do your derived class + // to be overridden, and filled with the info special to your derived class virtual css::frame::FeatureStateEvent buildStatusEvent() const; diff --git a/forms/source/richtext/richtextcontrol.cxx b/forms/source/richtext/richtextcontrol.cxx index fe1218d7092b..516020facbae 100644 --- a/forms/source/richtext/richtextcontrol.cxx +++ b/forms/source/richtext/richtextcontrol.cxx @@ -327,7 +327,7 @@ namespace frm if ( eTargetUnit != MapUnit::MapPixel ) aPos = pTargetDevice->PixelToLogic( aPos ); - pControl->Draw( pTargetDevice, aPos, SystemTextColorFlags::NoControls ); + pControl->Draw(*pTargetDevice, aPos, SystemTextColorFlags::NoControls); } diff --git a/forms/source/richtext/richtextengine.cxx b/forms/source/richtext/richtextengine.cxx index 325d27c9bd29..8c56a6207d8d 100644 --- a/forms/source/richtext/richtextengine.cxx +++ b/forms/source/richtext/richtextengine.cxx @@ -78,13 +78,11 @@ namespace frm RichTextEngine* pClone( nullptr ); { SolarMutexGuard aGuard; - std::unique_ptr pMyText(CreateTextObject()); - OSL_ENSURE( pMyText, "RichTextEngine::Clone: CreateTextObject returned nonsense!" ); + EditTextObject aMyText(CreateTextObject()); pClone = Create(); - if ( pMyText ) - pClone->SetText( *pMyText ); + pClone->SetText( aMyText ); } return pClone; diff --git a/forms/source/richtext/richtextimplcontrol.hxx b/forms/source/richtext/richtextimplcontrol.hxx index c227fc62ac9f..563c24031659 100644 --- a/forms/source/richtext/richtextimplcontrol.hxx +++ b/forms/source/richtext/richtextimplcontrol.hxx @@ -97,13 +97,13 @@ namespace frm There are some attributes which are script dependent, e.g. the CharPosture. This means that in real, there are 3 attributes for this, one for every possible script type (latin, - asian, complex). However, to the out world, we behave as if there is only one attribute: + asian, complex). However, to the outer world, we behave as if there is only one attribute: E.g., if the outer world asks for the state of the "CharPosture" attribute, we return the state of either CharPostureLatin, CharPostureAsian, or CharPostureComplex, depending on the script type of the current selection. (In real, it may be more complex since the current selection may contain more than one script type.) - This method normalizes a script dependent attribute, so that it's state takes into account + This method normalizes a script dependent attribute, so that its state takes into account the currently selected script type. */ void normalizeScriptDependentAttribute( SvxScriptSetItem& _rScriptSetItem ); diff --git a/forms/source/richtext/richtextvclcontrol.cxx b/forms/source/richtext/richtextvclcontrol.cxx index 8f8a9cd28010..1a1cbe33eaa7 100644 --- a/forms/source/richtext/richtextvclcontrol.cxx +++ b/forms/source/richtext/richtextvclcontrol.cxx @@ -289,9 +289,10 @@ namespace frm return bDone || Control::EventNotify(_rNEvt); } - void RichTextControl::Draw( OutputDevice* _pDev, const Point& _rPos, SystemTextColorFlags /*_nFlags*/ ) + void RichTextControl::Draw(OutputDevice& rDev, const Point& _rPos, + SystemTextColorFlags /*_nFlags*/) { - m_pImpl->Draw( _pDev, _rPos, _pDev->PixelToLogic(GetSizePixel()) ); + m_pImpl->Draw(&rDev, _rPos, rDev.PixelToLogic(GetSizePixel())); } EditView& RichTextControl::getView() diff --git a/forms/source/richtext/richtextvclcontrol.hxx b/forms/source/richtext/richtextvclcontrol.hxx index 92d0c047d7ea..1b58bc4acde7 100644 --- a/forms/source/richtext/richtextvclcontrol.hxx +++ b/forms/source/richtext/richtextvclcontrol.hxx @@ -96,7 +96,7 @@ namespace frm EditView& getView(); // Window overridables - virtual void Draw( OutputDevice* _pDev, const Point& _rPos, SystemTextColorFlags _nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& _rPos, SystemTextColorFlags _nFlags) override; protected: // Window overridables diff --git a/forms/source/runtime/formoperations.cxx b/forms/source/runtime/formoperations.cxx index 1e432fc076e2..6c7fc89ed20f 100644 --- a/forms/source/runtime/formoperations.cxx +++ b/forms/source/runtime/formoperations.cxx @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/forms/source/solar/control/navtoolbar.cxx b/forms/source/solar/control/navtoolbar.cxx index f637ca3154d5..bb04c5aa36b7 100644 --- a/forms/source/solar/control/navtoolbar.cxx +++ b/forms/source/solar/control/navtoolbar.cxx @@ -29,11 +29,10 @@ #include +#include #include #include #include - -#include #include #include @@ -271,7 +270,7 @@ namespace frm }; FeatureDescription const * pSupportedFeatures = aSupportedFeatures; - FeatureDescription const * pSupportedFeaturesEnd = aSupportedFeatures + SAL_N_ELEMENTS( aSupportedFeatures ); + FeatureDescription const * pSupportedFeaturesEnd = aSupportedFeatures + std::size( aSupportedFeatures ); for ( ; pSupportedFeatures < pSupportedFeaturesEnd; ++pSupportedFeatures ) { if ( pSupportedFeatures->nId ) diff --git a/forms/source/xforms/datatypes.cxx b/forms/source/xforms/datatypes.cxx index 4739c1ead758..c5126fbb6bdf 100644 --- a/forms/source/xforms/datatypes.cxx +++ b/forms/source/xforms/datatypes.cxx @@ -98,11 +98,6 @@ namespace xforms } - IMPLEMENT_FORWARD_XINTERFACE2( OXSDDataType, OXSDDataType_Base, ::comphelper::OPropertyContainer2 ) - - - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OXSDDataType, OXSDDataType_Base, ::comphelper::OPropertyContainer2 ) - OUString SAL_CALL OXSDDataType::getName( ) { return m_sName; @@ -232,10 +227,10 @@ namespace xforms } - bool OXSDDataType::convertFastPropertyValue( std::unique_lock& rGuard, Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) + bool OXSDDataType::convertFastPropertyValue( std::unique_lock& /*rGuard*/, Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) { // let the base class do the conversion - if ( !::comphelper::OPropertyContainer2::convertFastPropertyValue( rGuard, _rConvertedValue, _rOldValue, _nHandle, _rValue ) ) + if ( !OPropertyContainerHelper::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ) ) return false; // sanity checks @@ -249,9 +244,9 @@ namespace xforms } - void OXSDDataType::setFastPropertyValue_NoBroadcast( std::unique_lock& rGuard, sal_Int32 _nHandle, const Any& _rValue ) + void OXSDDataType::setFastPropertyValue_NoBroadcast( std::unique_lock& /*rGuard*/, sal_Int32 _nHandle, const Any& _rValue ) { - ::comphelper::OPropertyContainer2::setFastPropertyValue_NoBroadcast( rGuard, _nHandle, _rValue ); + OPropertyContainerHelper::setFastPropertyValue( _nHandle, _rValue ); if ( _nHandle == PROPERTY_ID_XSD_PATTERN ) m_bPatternMatcherDirty = true; } @@ -277,41 +272,6 @@ namespace xforms } - void SAL_CALL OXSDDataType::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) - { - ::comphelper::OPropertyContainer2::setPropertyValue( aPropertyName, aValue ); - } - - - Any SAL_CALL OXSDDataType::getPropertyValue( const OUString& PropertyName ) - { - return ::comphelper::OPropertyContainer2::getPropertyValue( PropertyName ); - } - - - void SAL_CALL OXSDDataType::addPropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) - { - ::comphelper::OPropertyContainer2::addPropertyChangeListener( aPropertyName, xListener ); - } - - - void SAL_CALL OXSDDataType::removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) - { - ::comphelper::OPropertyContainer2::removePropertyChangeListener( aPropertyName, aListener ); - } - - - void SAL_CALL OXSDDataType::addVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) - { - ::comphelper::OPropertyContainer2::addVetoableChangeListener( PropertyName, aListener ); - } - - - void SAL_CALL OXSDDataType::removeVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) - { - ::comphelper::OPropertyContainer2::removeVetoableChangeListener( PropertyName, aListener ); - } - OValueLimitedType_Base::OValueLimitedType_Base( const OUString& _rName, sal_Int16 _nTypeClass ) :OXSDDataType( _rName, _nTypeClass ) ,m_fCachedMaxInclusive( 0 ) @@ -1165,13 +1125,6 @@ template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS > } -template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS > -css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::getPropertySetInfo() -{ - return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); -} - - template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS > ::cppu::IPropertyArrayHelper& ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::getInfoHelper() { diff --git a/forms/source/xforms/datatypes.hxx b/forms/source/xforms/datatypes.hxx index bc1428ab7bab..a6bbb9846755 100644 --- a/forms/source/xforms/datatypes.hxx +++ b/forms/source/xforms/datatypes.hxx @@ -24,10 +24,10 @@ #include #include #include -#include -#include -#include + #include +#include +#include #include #include @@ -44,11 +44,9 @@ namespace xforms //= OXSDDataType - typedef ::comphelper::WeakImplHelper < css::xsd::XDataType - > OXSDDataType_Base; - - class OXSDDataType :public OXSDDataType_Base - ,public ::comphelper::OPropertyContainer2 + class OXSDDataType + : public comphelper::OPropertyImplHelper>, + public comphelper::OPropertyContainerHelper { private: // @@ -76,9 +74,6 @@ namespace xforms virtual ~OXSDDataType() override; public: - DECLARE_XINTERFACE() - DECLARE_XTYPEPROVIDER() - virtual OUString SAL_CALL getName( ) override; virtual void SAL_CALL setName( const OUString& aName ) override; virtual OUString SAL_CALL getPattern() override; @@ -91,14 +86,6 @@ namespace xforms virtual sal_Bool SAL_CALL validate( const OUString& value ) override; virtual OUString SAL_CALL explainInvalid( const OUString& value ) override; - // XPropertySet - is a base of XDataType and needs to be disambiguated - virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; - virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override; - virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override; - virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override; - virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; - virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; - public: rtl::Reference clone( const OUString& _rNewName ) const; @@ -110,6 +97,12 @@ namespace xforms sal_Int32 nHandle, const css::uno::Any& rValue ) override; + using OPropertyImplHelper::setFastPropertyValue; + using OPropertyImplHelper::getFastPropertyValue; + virtual void getFastPropertyValue( std::unique_lock&, css::uno::Any& rValue, sal_Int32 nHandle ) const override + { + OPropertyContainerHelper::getFastPropertyValue( rValue, nHandle ); + } // --- own overridables --- // helper for implementing cloning of data types @@ -213,9 +206,6 @@ namespace xforms protected: // OPropertyArrayUsageHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override; - - // XPropertySet - virtual css::uno::Reference SAL_CALL getPropertySetInfo() override; virtual ::cppu::IPropertyArrayHelper& getInfoHelper() override; }; diff --git a/forms/source/xforms/model.cxx b/forms/source/xforms/model.cxx index 105f7f449963..27844c6398d5 100644 --- a/forms/source/xforms/model.cxx +++ b/forms/source/xforms/model.cxx @@ -32,7 +32,9 @@ #include #include +#include #include +#include #include #include @@ -318,6 +320,12 @@ void Model::loadInstance( sal_Int32 nInstance ) if( sURL.isEmpty() ) return; + if( INetURLObject( sURL ).IsExoticProtocol() ) + { + SAL_WARN("forms.xforms", "Model::loadInstance: blocked exotic protocol: \"" << sURL << "\""); + return; + } + try { Reference xInput = diff --git a/forms/source/xforms/submission.cxx b/forms/source/xforms/submission.cxx index 2f59f58a5999..5b9f34ecc6ea 100644 --- a/forms/source/xforms/submission.cxx +++ b/forms/source/xforms/submission.cxx @@ -51,7 +51,7 @@ #include #include #include -#include + #include #include #include diff --git a/forms/source/xforms/submission/serialization_app_xml.cxx b/forms/source/xforms/submission/serialization_app_xml.cxx index 0e34f3d418c8..044e290d91f9 100644 --- a/forms/source/xforms/submission/serialization_app_xml.cxx +++ b/forms/source/xforms/submission/serialization_app_xml.cxx @@ -58,7 +58,7 @@ CSerializationAppXML::CSerializationAppXML() Reference< css::io::XInputStream > CSerializationAppXML::getInputStream() { - // The pipes output is provided through it's + // The pipe's output is provided through its // XOutputStream interface aspect return m_xBuffer; } diff --git a/forms/source/xforms/submission/submission_get.cxx b/forms/source/xforms/submission/submission_get.cxx index 34f34040d39e..7759b9cbdc83 100644 --- a/forms/source/xforms/submission/submission_get.cxx +++ b/forms/source/xforms/submission/submission_get.cxx @@ -41,7 +41,7 @@ CSubmissionGet::CSubmissionGet(std::u16string_view aURL, const css::uno::Referen CSubmission::SubmissionResult CSubmissionGet::submit(const css::uno::Reference< css::task::XInteractionHandler >& aInteractionHandler) { - // GET always uses application/x-www-formurlencoded + // GET always uses application/x-www-form-urlencoded CSerializationURLEncoded aSerialization; aSerialization.setSource(m_aFragment); aSerialization.serialize(); diff --git a/formula/CppunitTest_formula_ooxml.mk b/formula/CppunitTest_formula_ooxml.mk new file mode 100644 index 000000000000..5c082b9a47e5 --- /dev/null +++ b/formula/CppunitTest_formula_ooxml.mk @@ -0,0 +1,43 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# Copyright the LibreOffice contributors. +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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,formula_ooxml)) + +$(eval $(call gb_CppunitTest_use_sdk_api,formula_ooxml)) + +$(eval $(call gb_CppunitTest_use_ure,formula_ooxml)) + +$(eval $(call gb_CppunitTest_set_include,formula_ooxml,\ + -I$(SRCDIR)/formula/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,formula_ooxml,\ + formula/qa/unit/OOXMLRewriterTest \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,formula_ooxml,\ + comphelper \ + cppu \ + cppuhelper \ + for \ + i18nlangtag \ + sal \ + svl \ + svt \ + tl \ + utl \ + vcl \ +)) + +$(eval $(call gb_CppunitTest_use_external,formula_ooxml,boost_headers)) + +# vim: set noet sw=4 ts=4: diff --git a/formula/Library_for.mk b/formula/Library_for.mk index 5ff739b2acd8..5de3597f23a2 100644 --- a/formula/Library_for.mk +++ b/formula/Library_for.mk @@ -38,9 +38,11 @@ $(eval $(call gb_Library_use_libraries,for,\ $(eval $(call gb_Library_set_componentfile,for,formula/util/for,services)) $(eval $(call gb_Library_add_exception_objects,for,\ + formula/source/core/api/callable \ formula/source/core/api/FormulaCompiler \ formula/source/core/api/FormulaOpCodeMapperObj \ formula/source/core/api/grammar \ + formula/source/core/api/OOXMLRewriter \ formula/source/core/api/token \ formula/source/core/api/vectortoken \ formula/source/core/resource/core_resource \ diff --git a/formula/Module_formula.mk b/formula/Module_formula.mk index eac8702bf5ff..ad27bd677bc3 100644 --- a/formula/Module_formula.mk +++ b/formula/Module_formula.mk @@ -15,6 +15,10 @@ $(eval $(call gb_Module_add_targets,formula,\ UIConfig_formula \ )) +$(eval $(call gb_Module_add_check_targets,formula,\ + CppunitTest_formula_ooxml \ +)) + $(eval $(call gb_Module_add_l10n_targets,formula,\ AllLangMoTarget_for \ )) diff --git a/formula/README.Callable.md b/formula/README.Callable.md new file mode 100644 index 000000000000..1988e0a5a24f --- /dev/null +++ b/formula/README.Callable.md @@ -0,0 +1,127 @@ +# Callable + +A callable is a formula data type that represents code that can be called on a +(possibly empty) set of arguments to produce a result. + +## Using Callables + +The following elements are involved in using callables: + +* The `StackVar` enum provides `svCallable` to identify callable objects. + +* The `FormulaCallableToken` class allows you to create callable tokens. +Pass a `FormulaCallableRef` to the constructor. Use `GetCallable` to +retrieve the reference. + +* The `FormulaCallable` class contains the data for a callable object. It is an +abstract base class; you should not instantiate it directly. Use +`FormulaCallableRef` to refer to these objects. + +* Three subclasses of `FormulaCallable` have been implemented: + + 1. The `FormulaBuiltInFunction` represents a function that is provided by +Calc. + + * The `FormulaBuiltInFunction` class stores a table of references to +functions that have been accessed. The class should not be instantiated +directly. + + * If you have an `OpCode`, you can retrieve the corresponding +`FormulaBuiltInFunction` reference by calling `FormulaBuiltInFunction::Get()`. + + 2. The `FormulaExternalFunction` class represents a function that is +external to Calc. These are provided by means of add-ins. + + * Pass the name of the external function to the constructor to +instantiate an object. + + 3. The `ScFormulaFunction` class represents a function that has been built +using a `LAMBDA` formula. + + * To instantiate a `ScFormulaFunction`, pass a reference to the +interpreter containing the `LAMBDA`, along with an `OUString` vector naming the +parameters, and a reference to the `TokenArray` that the `LAMBDA` body comes +from, along with the positions of the beginning and end of the `LAMBDA` body +within that array. + + 4. The `ScMacroFunction` class represents a function that is defined as a +macro. + * Pass the `ScInterpreter` and the name of the macro to the constructor +to instantiate an object. + +* The `OpCode` enum provides `ocCall` as a left-associative binary operator. +This operator is automatically inserted by `ScCompiler` between the callable +name (or expression) and the opening parenthesis of the argument list. The next +phase of the compiler (in `FormulaCompiler`) acts on that `OpCode` to properly +build the call in RPN form. + +* To execute a `FormulaCallable`, use `ScInterpreter`'s `ScCall` method. Provide +a reference to the `FormulaCallable`, along with either a vector of arguments +(`FormulaConstTokenRef`) or the number of arguments to extract from the top of +the interpreter's stack. The result is placed on the top of the stack. + +## How it Works + +### Constructing + +* `ScCompiler::CompileString` identifies the use of a built-in operator without +a following parenthesis, and inserts a `FormulaBuiltInFunction` there instead. +If a (left) parenthesis does follow the reference to a built-in operator, its +`OpCode` is used instead. This makes things more efficient during +interpretation. + +* `ScCompiler::CompileString` also identifies the use of an external function +without a following parenthesis, and inserts a `FormulaExternalFunction` there +instead. As with a built-in function, if an external function is called +immediately, no callable is created. + +* The `LAMBDA` operator (`ocLambda`) is dealt with (mostly) like other jump +operators. See [../sc/README.Lambda.md](../sc/README.Lambda.md) for details. +When an `ocLambda` is interpreted, a `ScFormulaFunction` is built, which can be +called by the interpreter via `ScInterpreter::ScCall`. + +* Macro references produce `ocMacro` tokens (in `ScCompiler::CompileString`), +which generate `ScMacroFunction` objects when interpreted. +`ScInterpreter::ScCall` can call these. + +### Compiling + +1. `ScCompiler::CompileString` identifies when an open parenthesis appears after +either a closing parenthesis, a reference, or a name that doesn't match a +built-in operator, and injects `ocCall` into the output token stream before +continuing. + +2. `FormulaCompiler::CompileTokenArray` includes `CallLine` in its binary +operator precedence rules. `CallLine` detects `ocCall` and builds the necessary +RPN syntax for a call. + +### Interpreting + +1. `ScInterpreter::ScCall` collects the arguments provided and the +`FormulaCallable` reference, and passes them on to the other +`ScInterpreter::ScCall` methods. + +2. There are two versions of `ScInterpreter::ScCall` which, combined, are +capable of calling the different types of functions. The first accepts a +`FormulaCallable` and an integer, which indicates how many arguments are being +passed to it on the stack. The other accepts a vector of `FormulaConstTokenRef` +objects, which supplies the argument list directly. The idea is to be able to +call whichever method corresponds to the most convenient means of passing the +arguments, and let the two versions of `ScInterpreter::ScCall` figure out how +to actually make the call. + +3. If a `FormulaCallable` needs to be called by any other means, one of the +versions of the `ScInterpereter::ScCall` method that accepts arguments may be +used. The result appears on the top of the stack. + +### Subclassing + +A subclass must implement a `GetOpCode` method, whose result uniquely determines +which subclass it is. `FormulaBuiltInFunction` returns an `OpCode` corresponding +to one of the built-in operators. `FormulaExternalFunction` returns ocExternal, +`ScFormulaFunction` returns `ocLambda`, and `ScMacroFunction` returns `ocMacro`. +The versions of `ScInterpreter::ScCall` use this information to determine which +subclass is being called, and perform the actions necessary to implement the +call. Note that each subclass has a preferred means of receiving arguments; the +other version of `ScInterpreter::ScCall` just sets up the arguments and calls +the preferred version. diff --git a/formula/inc/OOXMLRewriter.hxx b/formula/inc/OOXMLRewriter.hxx new file mode 100644 index 000000000000..bd82e97f7d8b --- /dev/null +++ b/formula/inc/OOXMLRewriter.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +namespace formula +{ +class FormulaTokenArray; + +/** Rewrites the token array to make it compatible with OOXML. + + OOXML writes @ and # as calls and a reference union as a parenthesised list. Those call + names and parentheses become tokens here, so writing the result is a plain walk. The # + also moves in front of its operand and becomes ocAnchorArray. + + Operator extents come from the token order, so this restates the precedence the parser + applied. Change one and the other needs it too. + */ +class FORMULA_DLLPUBLIC OOXMLRewriter +{ +public: + explicit OOXMLRewriter(FormulaTokenArray const& rTokens); + + /** The OOXML compatible token array, or nullptr. The caller takes ownership. */ + std::unique_ptr releaseTokens() { return std::move(mpRewritten); } + +private: + std::unique_ptr mpRewritten; +}; + +} // namespace formula + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/formula/inc/core_resource.hrc b/formula/inc/core_resource.hrc index cb2359afc069..12f90af5fe6c 100644 --- a/formula/inc/core_resource.hrc +++ b/formula/inc/core_resource.hrc @@ -19,7 +19,7 @@ #pragma once -#include +#include #include #include @@ -34,936 +34,962 @@ // ScCompiler::IsOpCode() in the if (mxSymbols->isODFF()) block. const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF[] = { - { "IF" , SC_OPCODE_IF }, - { "IFERROR" , SC_OPCODE_IF_ERROR }, - { "IFNA" , SC_OPCODE_IF_NA }, - { "CHOOSE" , SC_OPCODE_CHOOSE }, - { "(" , SC_OPCODE_OPEN }, - { ")" , SC_OPCODE_CLOSE }, - // SC_OPCODE_TABLE_REF_... not supported in ODFF - { "{" , SC_OPCODE_ARRAY_OPEN }, - { "}" , SC_OPCODE_ARRAY_CLOSE }, - { "|" , SC_OPCODE_ARRAY_ROW_SEP }, - { ";" , SC_OPCODE_ARRAY_COL_SEP }, - { ";" , SC_OPCODE_SEP }, - { "%" , SC_OPCODE_PERCENT_SIGN }, - { "+" , SC_OPCODE_ADD }, - { "-" , SC_OPCODE_SUB }, - { "*" , SC_OPCODE_MUL }, - { "/" , SC_OPCODE_DIV }, - { "&" , SC_OPCODE_AMPERSAND }, - { "^" , SC_OPCODE_POW }, - { "=" , SC_OPCODE_EQUAL }, - { "<>" , SC_OPCODE_NOT_EQUAL }, - { "<" , SC_OPCODE_LESS }, - { ">" , SC_OPCODE_GREATER }, - { "<=" , SC_OPCODE_LESS_EQUAL }, - { ">=" , SC_OPCODE_GREATER_EQUAL }, - { "AND" , SC_OPCODE_AND }, - { "OR" , SC_OPCODE_OR }, - { "XOR" , SC_OPCODE_XOR }, - { "!" , SC_OPCODE_INTERSECT }, - { "~" , SC_OPCODE_UNION }, - { ":" , SC_OPCODE_RANGE }, - { "NOT" , SC_OPCODE_NOT }, - { "NEG" , SC_OPCODE_NEG }, - { "-" , SC_OPCODE_NEG_SUB }, - { "PI" , SC_OPCODE_PI }, - { "RAND" , SC_OPCODE_RANDOM }, - { "TRUE" , SC_OPCODE_TRUE }, - { "FALSE" , SC_OPCODE_FALSE }, - { "TODAY" , SC_OPCODE_GET_ACT_DATE }, - { "NOW" , SC_OPCODE_GET_ACT_TIME }, - { "NA" , SC_OPCODE_NO_VALUE }, - { "ORG.OPENOFFICE.CURRENT" , SC_OPCODE_CURRENT }, - { "DEGREES" , SC_OPCODE_DEG }, - { "RADIANS" , SC_OPCODE_RAD }, - { "SIN" , SC_OPCODE_SIN }, - { "COS" , SC_OPCODE_COS }, - { "TAN" , SC_OPCODE_TAN }, - { "COT" , SC_OPCODE_COT }, - { "ASIN" , SC_OPCODE_ARC_SIN }, - { "ACOS" , SC_OPCODE_ARC_COS }, - { "ATAN" , SC_OPCODE_ARC_TAN }, - { "ACOT" , SC_OPCODE_ARC_COT }, - { "SINH" , SC_OPCODE_SIN_HYP }, - { "COSH" , SC_OPCODE_COS_HYP }, - { "TANH" , SC_OPCODE_TAN_HYP }, - { "COTH" , SC_OPCODE_COT_HYP }, - { "ASINH" , SC_OPCODE_ARC_SIN_HYP }, - { "ACOSH" , SC_OPCODE_ARC_COS_HYP }, - { "ATANH" , SC_OPCODE_ARC_TAN_HYP }, - { "ACOTH" , SC_OPCODE_ARC_COT_HYP }, - { "CSC" , SC_OPCODE_COSECANT }, - { "SEC" , SC_OPCODE_SECANT }, - { "CSCH" , SC_OPCODE_COSECANT_HYP }, - { "SECH" , SC_OPCODE_SECANT_HYP }, - { "EXP" , SC_OPCODE_EXP }, - { "LN" , SC_OPCODE_LN }, - { "SQRT" , SC_OPCODE_SQRT }, - { "FACT" , SC_OPCODE_FACT }, - { "YEAR" , SC_OPCODE_GET_YEAR }, - { "MONTH" , SC_OPCODE_GET_MONTH }, - { "DAY" , SC_OPCODE_GET_DAY }, - { "HOUR" , SC_OPCODE_GET_HOUR }, - { "MINUTE" , SC_OPCODE_GET_MIN }, - { "SECOND" , SC_OPCODE_GET_SEC }, - { "SIGN" , SC_OPCODE_PLUS_MINUS }, - { "ABS" , SC_OPCODE_ABS }, - { "INT" , SC_OPCODE_INT }, - { "PHI" , SC_OPCODE_PHI }, - { "GAUSS" , SC_OPCODE_GAUSS }, - { "ISBLANK" , SC_OPCODE_IS_EMPTY }, - { "ISTEXT" , SC_OPCODE_IS_STRING }, - { "ISNONTEXT" , SC_OPCODE_IS_NON_STRING }, - { "ISLOGICAL" , SC_OPCODE_IS_LOGICAL }, - { "TYPE" , SC_OPCODE_TYPE }, - { "CELL" , SC_OPCODE_CELL }, - { "ISREF" , SC_OPCODE_IS_REF }, - { "ISNUMBER" , SC_OPCODE_IS_VALUE }, - { "ISFORMULA" , SC_OPCODE_IS_FORMULA }, - { "ISNA" , SC_OPCODE_IS_NV }, - { "ISERR" , SC_OPCODE_IS_ERR }, - { "ISERROR" , SC_OPCODE_IS_ERROR }, - { "ISEVEN" , SC_OPCODE_IS_EVEN }, - { "ISODD" , SC_OPCODE_IS_ODD }, - { "N" , SC_OPCODE_N }, - { "DATEVALUE" , SC_OPCODE_GET_DATE_VALUE }, - { "TIMEVALUE" , SC_OPCODE_GET_TIME_VALUE }, - { "CODE" , SC_OPCODE_CODE }, - { "TRIM" , SC_OPCODE_TRIM }, - { "UPPER" , SC_OPCODE_UPPER }, - { "PROPER" , SC_OPCODE_PROPER }, - { "LOWER" , SC_OPCODE_LOWER }, - { "LEN" , SC_OPCODE_LEN }, - { "T" , SC_OPCODE_T }, - { "VALUE" , SC_OPCODE_VALUE }, - { "CLEAN" , SC_OPCODE_CLEAN }, - { "CHAR" , SC_OPCODE_CHAR }, - { "JIS" , SC_OPCODE_JIS }, - { "ASC" , SC_OPCODE_ASC }, - { "UNICODE" , SC_OPCODE_UNICODE }, - { "UNICHAR" , SC_OPCODE_UNICHAR }, - { "LOG10" , SC_OPCODE_LOG10 }, - { "EVEN" , SC_OPCODE_EVEN }, - { "ODD" , SC_OPCODE_ODD }, - { "LEGACY.NORMSDIST" , SC_OPCODE_STD_NORM_DIST }, - { "COM.MICROSOFT.NORM.S.DIST" , SC_OPCODE_STD_NORM_DIST_MS }, - { "FISHER" , SC_OPCODE_FISHER }, - { "FISHERINV" , SC_OPCODE_FISHER_INV }, - { "LEGACY.NORMSINV" , SC_OPCODE_S_NORM_INV }, - { "COM.MICROSOFT.NORM.S.INV" , SC_OPCODE_S_NORM_INV_MS }, - { "GAMMALN" , SC_OPCODE_GAMMA_LN }, - { "COM.MICROSOFT.GAMMALN.PRECISE" , SC_OPCODE_GAMMA_LN_MS }, - { "ORG.OPENOFFICE.ERRORTYPE" , SC_OPCODE_ERROR_TYPE }, - { "ERROR.TYPE" , SC_OPCODE_ERROR_TYPE_ODF }, - { "FORMULA" , SC_OPCODE_FORMULA }, - { "ATAN2" , SC_OPCODE_ARC_TAN_2 }, - { "COM.MICROSOFT.CEILING.MATH" , SC_OPCODE_CEIL_MATH }, - { "CEILING" , SC_OPCODE_CEIL }, - { "COM.MICROSOFT.CEILING" , SC_OPCODE_CEIL_MS }, - { "COM.MICROSOFT.CEILING.PRECISE" , SC_OPCODE_CEIL_PRECISE }, - { "COM.MICROSOFT.ISO.CEILING" , SC_OPCODE_CEIL_ISO }, - { "FLOOR" , SC_OPCODE_FLOOR }, - { "COM.MICROSOFT.FLOOR" , SC_OPCODE_FLOOR_MS }, - { "COM.MICROSOFT.FLOOR.MATH" , SC_OPCODE_FLOOR_MATH }, - { "COM.MICROSOFT.FLOOR.PRECISE" , SC_OPCODE_FLOOR_PRECISE }, - { "ROUND" , SC_OPCODE_ROUND }, - { "ROUNDUP" , SC_OPCODE_ROUND_UP }, - { "ROUNDDOWN" , SC_OPCODE_ROUND_DOWN }, - { "TRUNC" , SC_OPCODE_TRUNC }, - { "LOG" , SC_OPCODE_LOG }, - { "POWER" , SC_OPCODE_POWER }, - { "GCD" , SC_OPCODE_GCD }, - { "LCM" , SC_OPCODE_LCM }, - { "MOD" , SC_OPCODE_MOD }, - { "SUMPRODUCT" , SC_OPCODE_SUM_PRODUCT }, - { "SUMSQ" , SC_OPCODE_SUM_SQ }, - { "SUMX2MY2" , SC_OPCODE_SUM_X2MY2 }, - { "SUMX2PY2" , SC_OPCODE_SUM_X2DY2 }, - { "SUMXMY2" , SC_OPCODE_SUM_XMY2 }, - { "DATE" , SC_OPCODE_GET_DATE }, - { "TIME" , SC_OPCODE_GET_TIME }, - { "DAYS" , SC_OPCODE_GET_DIFF_DATE }, - { "DAYS360" , SC_OPCODE_GET_DIFF_DATE_360 }, - { "DATEDIF" , SC_OPCODE_GET_DATEDIF }, - { "MIN" , SC_OPCODE_MIN }, - { "MINA" , SC_OPCODE_MIN_A }, - { "MAX" , SC_OPCODE_MAX }, - { "MAXA" , SC_OPCODE_MAX_A }, - { "SUM" , SC_OPCODE_SUM }, - { "PRODUCT" , SC_OPCODE_PRODUCT }, - { "AVERAGE" , SC_OPCODE_AVERAGE }, - { "AVERAGEA" , SC_OPCODE_AVERAGE_A }, - { "COUNT" , SC_OPCODE_COUNT }, - { "COUNTA" , SC_OPCODE_COUNT_2 }, - { "NPV" , SC_OPCODE_NPV }, - { "IRR" , SC_OPCODE_IRR }, - { "MIRR" , SC_OPCODE_MIRR }, - { "ISPMT" , SC_OPCODE_ISPMT }, - { "VAR" , SC_OPCODE_VAR }, - { "VARA" , SC_OPCODE_VAR_A }, - { "VARP" , SC_OPCODE_VAR_P }, - { "VARPA" , SC_OPCODE_VAR_P_A }, - { "COM.MICROSOFT.VAR.P" , SC_OPCODE_VAR_P_MS }, - { "COM.MICROSOFT.VAR.S" , SC_OPCODE_VAR_S }, - { "STDEV" , SC_OPCODE_ST_DEV }, - { "STDEVA" , SC_OPCODE_ST_DEV_A }, - { "STDEVP" , SC_OPCODE_ST_DEV_P }, - { "STDEVPA" , SC_OPCODE_ST_DEV_P_A }, - { "COM.MICROSOFT.STDEV.P" , SC_OPCODE_ST_DEV_P_MS }, - { "COM.MICROSOFT.STDEV.S" , SC_OPCODE_ST_DEV_S }, - { "BINOM.DIST.RANGE" , SC_OPCODE_B }, - { "NORMDIST" , SC_OPCODE_NORM_DIST }, - { "COM.MICROSOFT.NORM.DIST" , SC_OPCODE_NORM_DIST_MS }, - { "EXPONDIST" , SC_OPCODE_EXP_DIST }, - { "COM.MICROSOFT.EXPON.DIST" , SC_OPCODE_EXP_DIST_MS }, - { "BINOMDIST" , SC_OPCODE_BINOM_DIST }, - { "COM.MICROSOFT.BINOM.DIST" , SC_OPCODE_BINOM_DIST_MS }, - { "POISSON" , SC_OPCODE_POISSON_DIST }, - { "COM.MICROSOFT.POISSON.DIST" , SC_OPCODE_POISSON_DIST_MS }, - { "COMBIN" , SC_OPCODE_COMBIN }, - { "COMBINA" , SC_OPCODE_COMBIN_A }, - { "PERMUT" , SC_OPCODE_PERMUT }, - { "PERMUTATIONA" , SC_OPCODE_PERMUTATION_A }, - { "PV" , SC_OPCODE_PV }, - { "SYD" , SC_OPCODE_SYD }, - { "DDB" , SC_OPCODE_DDB }, - { "DB" , SC_OPCODE_DB }, - { "VDB" , SC_OPCODE_VBD }, - { "PDURATION" , SC_OPCODE_PDURATION }, - { "SLN" , SC_OPCODE_SLN }, - { "PMT" , SC_OPCODE_PMT }, - { "COLUMNS" , SC_OPCODE_COLUMNS }, - { "ROWS" , SC_OPCODE_ROWS }, - { "SHEETS" , SC_OPCODE_SHEETS }, - { "COLUMN" , SC_OPCODE_COLUMN }, - { "ROW" , SC_OPCODE_ROW }, - { "SHEET" , SC_OPCODE_SHEET }, - { "RRI" , SC_OPCODE_RRI }, - { "FV" , SC_OPCODE_FV }, - { "NPER" , SC_OPCODE_NPER }, - { "RATE" , SC_OPCODE_RATE }, - { "IPMT" , SC_OPCODE_IPMT }, - { "PPMT" , SC_OPCODE_PPMT }, - { "CUMIPMT" , SC_OPCODE_CUM_IPMT }, - { "CUMPRINC" , SC_OPCODE_CUM_PRINC }, - { "EFFECT" , SC_OPCODE_EFFECT }, - { "NOMINAL" , SC_OPCODE_NOMINAL }, - { "SUBTOTAL" , SC_OPCODE_SUB_TOTAL }, - { "DSUM" , SC_OPCODE_DB_SUM }, - { "DCOUNT" , SC_OPCODE_DB_COUNT }, - { "DCOUNTA" , SC_OPCODE_DB_COUNT_2 }, - { "DAVERAGE" , SC_OPCODE_DB_AVERAGE }, - { "DGET" , SC_OPCODE_DB_GET }, - { "DMAX" , SC_OPCODE_DB_MAX }, - { "DMIN" , SC_OPCODE_DB_MIN }, - { "DPRODUCT" , SC_OPCODE_DB_PRODUCT }, - { "DSTDEV" , SC_OPCODE_DB_STD_DEV }, - { "DSTDEVP" , SC_OPCODE_DB_STD_DEV_P }, - { "DVAR" , SC_OPCODE_DB_VAR }, - { "DVARP" , SC_OPCODE_DB_VAR_P }, - { "INDIRECT" , SC_OPCODE_INDIRECT }, - { "ADDRESS" , SC_OPCODE_ADDRESS }, - { "MATCH" , SC_OPCODE_MATCH }, - { "COM.MICROSOFT.XMATCH" , SC_OPCODE_X_MATCH }, - { "COUNTBLANK" , SC_OPCODE_COUNT_EMPTY_CELLS }, - { "COUNTIF" , SC_OPCODE_COUNT_IF }, - { "SUMIF" , SC_OPCODE_SUM_IF }, - { "AVERAGEIF" , SC_OPCODE_AVERAGE_IF }, - { "SUMIFS" , SC_OPCODE_SUM_IFS }, - { "AVERAGEIFS" , SC_OPCODE_AVERAGE_IFS }, - { "COUNTIFS" , SC_OPCODE_COUNT_IFS }, - { "LOOKUP" , SC_OPCODE_LOOKUP }, - { "VLOOKUP" , SC_OPCODE_V_LOOKUP }, - { "COM.MICROSOFT.XLOOKUP" , SC_OPCODE_X_LOOKUP }, - { "HLOOKUP" , SC_OPCODE_H_LOOKUP }, - { "COM.MICROSOFT.FILTER" , SC_OPCODE_FILTER }, - { "COM.MICROSOFT.SORT" , SC_OPCODE_SORT }, - { "COM.MICROSOFT.SORTBY" , SC_OPCODE_SORTBY }, - { "COM.MICROSOFT.CHOOSECOLS" , SC_OPCODE_CHOOSECOLS }, - { "COM.MICROSOFT.CHOOSEROWS" , SC_OPCODE_CHOOSEROWS }, - { "COM.MICROSOFT.DROP" , SC_OPCODE_DROP }, - { "COM.MICROSOFT.EXPAND" , SC_OPCODE_EXPAND }, - { "COM.MICROSOFT.HSTACK" , SC_OPCODE_HSTACK }, - { "COM.MICROSOFT.VSTACK" , SC_OPCODE_VSTACK }, - { "COM.MICROSOFT.TAKE" , SC_OPCODE_TAKE }, - { "COM.MICROSOFT.TEXTAFTER" , SC_OPCODE_TEXTAFTER }, - { "COM.MICROSOFT.TEXTBEFORE" , SC_OPCODE_TEXTBEFORE }, - { "COM.MICROSOFT.TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, - { "COM.MICROSOFT.TOCOL" , SC_OPCODE_TOCOL }, - { "COM.MICROSOFT.TOROW" , SC_OPCODE_TOROW }, - { "COM.MICROSOFT.UNIQUE" , SC_OPCODE_UNIQUE }, - { "COM.MICROSOFT.LET" , SC_OPCODE_LET }, - { "COM.MICROSOFT.WRAPCOLS" , SC_OPCODE_WRAPCOLS }, - { "COM.MICROSOFT.WRAPROWS" , SC_OPCODE_WRAPROWS }, - { "_xlpm." , SC_OPCODE_STRINGNAME }, - { "ORG.OPENOFFICE.MULTIRANGE" , SC_OPCODE_MULTI_AREA }, // legacy for range list (union) - { "OFFSET" , SC_OPCODE_OFFSET }, - { "INDEX" , SC_OPCODE_INDEX }, - { "AREAS" , SC_OPCODE_AREAS }, - { "DOLLAR" , SC_OPCODE_CURRENCY }, - { "REPLACE" , SC_OPCODE_REPLACE }, - { "FIXED" , SC_OPCODE_FIXED }, - { "FIND" , SC_OPCODE_FIND }, - { "EXACT" , SC_OPCODE_EXACT }, - { "LEFT" , SC_OPCODE_LEFT }, - { "RIGHT" , SC_OPCODE_RIGHT }, - { "SEARCH" , SC_OPCODE_SEARCH }, - { "MID" , SC_OPCODE_MID }, - { "LENB" , SC_OPCODE_LENB }, - { "RIGHTB" , SC_OPCODE_RIGHTB }, - { "LEFTB" , SC_OPCODE_LEFTB }, - { "REPLACEB" , SC_OPCODE_REPLACEB }, - { "FINDB" , SC_OPCODE_FINDB }, - { "SEARCHB" , SC_OPCODE_SEARCHB }, - { "MIDB" , SC_OPCODE_MIDB }, - { "TEXT" , SC_OPCODE_TEXT }, - { "SUBSTITUTE" , SC_OPCODE_SUBSTITUTE }, - { "REPT" , SC_OPCODE_REPT }, - { "CONCATENATE" , SC_OPCODE_CONCAT }, - { "COM.MICROSOFT.CONCAT" , SC_OPCODE_CONCAT_MS }, - { "COM.MICROSOFT.TEXTJOIN" , SC_OPCODE_TEXTJOIN_MS }, - { "COM.MICROSOFT.IFS" , SC_OPCODE_IFS_MS }, - { "COM.MICROSOFT.SWITCH" , SC_OPCODE_SWITCH_MS }, - { "COM.MICROSOFT.MINIFS" , SC_OPCODE_MINIFS_MS }, - { "COM.MICROSOFT.MAXIFS" , SC_OPCODE_MAXIFS_MS }, - { "MVALUE" , SC_OPCODE_MAT_VALUE }, - { "MDETERM" , SC_OPCODE_MAT_DET }, - { "MINVERSE" , SC_OPCODE_MAT_INV }, - { "MMULT" , SC_OPCODE_MAT_MULT }, - { "COM.MICROSOFT.SEQUENCE" , SC_OPCODE_MAT_SEQUENCE }, - { "TRANSPOSE" , SC_OPCODE_MAT_TRANS }, - { "MUNIT" , SC_OPCODE_MATRIX_UNIT }, - { "ORG.OPENOFFICE.GOALSEEK" , SC_OPCODE_BACK_SOLVER }, - { "HYPGEOMDIST" , SC_OPCODE_HYP_GEOM_DIST }, - { "COM.MICROSOFT.HYPGEOM.DIST" , SC_OPCODE_HYP_GEOM_DIST_MS }, - { "LOGNORMDIST" , SC_OPCODE_LOG_NORM_DIST }, - { "COM.MICROSOFT.LOGNORM.DIST" , SC_OPCODE_LOG_NORM_DIST_MS }, - { "LEGACY.TDIST" , SC_OPCODE_T_DIST }, - { "COM.MICROSOFT.T.DIST.2T" , SC_OPCODE_T_DIST_2T }, - { "COM.MICROSOFT.T.DIST" , SC_OPCODE_T_DIST_MS }, - { "COM.MICROSOFT.T.DIST.RT" , SC_OPCODE_T_DIST_RT }, - { "LEGACY.FDIST" , SC_OPCODE_F_DIST }, - { "FDIST" , SC_OPCODE_F_DIST_LT }, - { "COM.MICROSOFT.F.DIST.RT" , SC_OPCODE_F_DIST_RT }, - { "LEGACY.CHIDIST" , SC_OPCODE_CHI_DIST }, - { "COM.MICROSOFT.CHISQ.DIST.RT" , SC_OPCODE_CHI_DIST_MS }, - { "WEIBULL" , SC_OPCODE_WEIBULL }, - { "COM.MICROSOFT.WEIBULL.DIST" , SC_OPCODE_WEIBULL_MS }, - { "NEGBINOMDIST" , SC_OPCODE_NEG_BINOM_VERT }, - { "COM.MICROSOFT.NEGBINOM.DIST" , SC_OPCODE_NEG_BINOM_DIST_MS }, - { "CRITBINOM" , SC_OPCODE_CRIT_BINOM }, - { "COM.MICROSOFT.BINOM.INV" , SC_OPCODE_BINOM_INV }, - { "KURT" , SC_OPCODE_KURT }, - { "HARMEAN" , SC_OPCODE_HAR_MEAN }, - { "GEOMEAN" , SC_OPCODE_GEO_MEAN }, - { "STANDARDIZE" , SC_OPCODE_STANDARD }, - { "AVEDEV" , SC_OPCODE_AVE_DEV }, - { "SKEW" , SC_OPCODE_SKEW }, - { "SKEWP" , SC_OPCODE_SKEWP }, - { "DEVSQ" , SC_OPCODE_DEV_SQ }, - { "MEDIAN" , SC_OPCODE_MEDIAN }, - { "MODE" , SC_OPCODE_MODAL_VALUE }, - { "COM.MICROSOFT.MODE.SNGL" , SC_OPCODE_MODAL_VALUE_MS }, - { "COM.MICROSOFT.MODE.MULT" , SC_OPCODE_MODAL_VALUE_MULTI }, - { "ZTEST" , SC_OPCODE_Z_TEST }, - { "COM.MICROSOFT.Z.TEST" , SC_OPCODE_Z_TEST_MS }, - { "COM.MICROSOFT.AGGREGATE" , SC_OPCODE_AGGREGATE }, - { "TTEST" , SC_OPCODE_T_TEST }, - { "COM.MICROSOFT.T.TEST" , SC_OPCODE_T_TEST_MS }, - { "RANK" , SC_OPCODE_RANK }, - { "PERCENTILE" , SC_OPCODE_PERCENTILE }, - { "PERCENTRANK" , SC_OPCODE_PERCENT_RANK }, - { "COM.MICROSOFT.PERCENTILE.INC" , SC_OPCODE_PERCENTILE_INC }, - { "COM.MICROSOFT.PERCENTRANK.INC" , SC_OPCODE_PERCENT_RANK_INC }, - { "COM.MICROSOFT.QUARTILE.INC" , SC_OPCODE_QUARTILE_INC }, - { "COM.MICROSOFT.RANK.EQ" , SC_OPCODE_RANK_EQ }, - { "COM.MICROSOFT.PERCENTILE.EXC" , SC_OPCODE_PERCENTILE_EXC }, - { "COM.MICROSOFT.PERCENTRANK.EXC" , SC_OPCODE_PERCENT_RANK_EXC }, - { "COM.MICROSOFT.QUARTILE.EXC" , SC_OPCODE_QUARTILE_EXC }, - { "COM.MICROSOFT.RANK.AVG" , SC_OPCODE_RANK_AVG }, - { "LARGE" , SC_OPCODE_LARGE }, - { "SMALL" , SC_OPCODE_SMALL }, - { "FREQUENCY" , SC_OPCODE_FREQUENCY }, - { "QUARTILE" , SC_OPCODE_QUARTILE }, - { "NORMINV" , SC_OPCODE_NORM_INV }, - { "COM.MICROSOFT.NORM.INV" , SC_OPCODE_NORM_INV_MS }, - { "CONFIDENCE" , SC_OPCODE_CONFIDENCE }, - { "COM.MICROSOFT.CONFIDENCE.NORM" , SC_OPCODE_CONFIDENCE_N }, - { "COM.MICROSOFT.CONFIDENCE.T" , SC_OPCODE_CONFIDENCE_T }, - { "FTEST" , SC_OPCODE_F_TEST }, - { "COM.MICROSOFT.F.TEST" , SC_OPCODE_F_TEST_MS }, - { "TRIMMEAN" , SC_OPCODE_TRIM_MEAN }, - { "PROB" , SC_OPCODE_PROB }, - { "CORREL" , SC_OPCODE_CORREL }, - { "COVAR" , SC_OPCODE_COVAR }, - { "COM.MICROSOFT.COVARIANCE.P" , SC_OPCODE_COVARIANCE_P }, - { "COM.MICROSOFT.COVARIANCE.S" , SC_OPCODE_COVARIANCE_S }, - { "PEARSON" , SC_OPCODE_PEARSON }, - { "RSQ" , SC_OPCODE_RSQ }, - { "STEYX" , SC_OPCODE_STEYX }, - { "SLOPE" , SC_OPCODE_SLOPE }, - { "INTERCEPT" , SC_OPCODE_INTERCEPT }, - { "TREND" , SC_OPCODE_TREND }, - { "GROWTH" , SC_OPCODE_GROWTH }, - { "LINEST" , SC_OPCODE_LINEST }, - { "LOGEST" , SC_OPCODE_LOGEST }, - { "FORECAST" , SC_OPCODE_FORECAST }, - { "COM.MICROSOFT.FORECAST.ETS" , SC_OPCODE_FORECAST_ETS_ADD }, - { "COM.MICROSOFT.FORECAST.ETS.SEASONALITY" , SC_OPCODE_FORECAST_ETS_SEA }, - { "ORG.LIBREOFFICE.FORECAST.ETS.MULT" , SC_OPCODE_FORECAST_ETS_MUL }, - { "COM.MICROSOFT.FORECAST.ETS.CONFINT" , SC_OPCODE_FORECAST_ETS_PIA }, - { "ORG.LIBREOFFICE.FORECAST.ETS.PI.MULT" , SC_OPCODE_FORECAST_ETS_PIM }, - { "COM.MICROSOFT.FORECAST.ETS.STAT" , SC_OPCODE_FORECAST_ETS_STA }, - { "ORG.LIBREOFFICE.FORECAST.ETS.STAT.MULT" , SC_OPCODE_FORECAST_ETS_STM }, - { "COM.MICROSOFT.FORECAST.LINEAR" , SC_OPCODE_FORECAST_LIN }, - { "LEGACY.CHIINV" , SC_OPCODE_CHI_INV }, - { "COM.MICROSOFT.CHISQ.INV.RT" , SC_OPCODE_CHI_INV_MS }, - { "GAMMADIST" , SC_OPCODE_GAMMA_DIST }, - { "COM.MICROSOFT.GAMMA.DIST" , SC_OPCODE_GAMMA_DIST_MS }, - { "GAMMAINV" , SC_OPCODE_GAMMA_INV }, - { "COM.MICROSOFT.GAMMA.INV" , SC_OPCODE_GAMMA_INV_MS }, - { "TINV" , SC_OPCODE_T_INV }, - { "COM.MICROSOFT.T.INV.2T" , SC_OPCODE_T_INV_2T }, - { "COM.MICROSOFT.T.INV" , SC_OPCODE_T_INV_MS }, - { "LEGACY.FINV" , SC_OPCODE_F_INV }, - { "FINV" , SC_OPCODE_F_INV_LT }, - { "COM.MICROSOFT.F.INV.RT" , SC_OPCODE_F_INV_RT }, - { "LEGACY.CHITEST" , SC_OPCODE_CHI_TEST }, - { "COM.MICROSOFT.CHISQ.TEST" , SC_OPCODE_CHI_TEST_MS }, - { "LOGINV" , SC_OPCODE_LOG_INV }, - { "COM.MICROSOFT.LOGNORM.INV" , SC_OPCODE_LOG_INV_MS }, - { "MULTIPLE.OPERATIONS" , SC_OPCODE_TABLE_OP }, - { "BETADIST" , SC_OPCODE_BETA_DIST }, - { "BETAINV" , SC_OPCODE_BETA_INV }, - { "COM.MICROSOFT.BETA.DIST" , SC_OPCODE_BETA_DIST_MS }, - { "COM.MICROSOFT.BETA.INV" , SC_OPCODE_BETA_INV_MS }, - { "WEEKNUM" , SC_OPCODE_WEEK }, - { "ISOWEEKNUM" , SC_OPCODE_ISOWEEKNUM }, - { "ORG.LIBREOFFICE.WEEKNUM_OOO" , SC_OPCODE_WEEKNUM_OOO }, - { "EASTERSUNDAY" , SC_OPCODE_EASTERSUNDAY }, - { "WEEKDAY" , SC_OPCODE_GET_DAY_OF_WEEK }, - { "NETWORKDAYS" , SC_OPCODE_NETWORKDAYS }, - { "COM.MICROSOFT.NETWORKDAYS.INTL" , SC_OPCODE_NETWORKDAYS_MS }, - { "COM.MICROSOFT.WORKDAY.INTL" , SC_OPCODE_WORKDAY_MS }, - { "#NAME!" , SC_OPCODE_NO_NAME }, - { "ORG.OPENOFFICE.STYLE" , SC_OPCODE_STYLE }, - { "DDE" , SC_OPCODE_DDE }, - { "BASE" , SC_OPCODE_BASE }, - { "DECIMAL" , SC_OPCODE_DECIMAL }, - { "ORG.OPENOFFICE.CONVERT" , SC_OPCODE_CONVERT_OOO }, - { "ROMAN" , SC_OPCODE_ROMAN }, - { "ARABIC" , SC_OPCODE_ARABIC }, - { "HYPERLINK" , SC_OPCODE_HYPERLINK }, - { "INFO" , SC_OPCODE_INFO }, - { "COM.MICROSOFT.BAHTTEXT" , SC_OPCODE_BAHTTEXT }, - { "GETPIVOTDATA" , SC_OPCODE_GET_PIVOT_DATA }, - { "EUROCONVERT" , SC_OPCODE_EUROCONVERT }, - { "NUMBERVALUE" , SC_OPCODE_NUMBERVALUE }, - { "GAMMA" , SC_OPCODE_GAMMA }, - { "CHISQDIST" , SC_OPCODE_CHISQ_DIST }, - { "COM.MICROSOFT.CHISQ.DIST" , SC_OPCODE_CHISQ_DIST_MS }, - { "CHISQINV" , SC_OPCODE_CHISQ_INV }, - { "COM.MICROSOFT.CHISQ.INV" , SC_OPCODE_CHISQ_INV_MS }, - { "BITAND" , SC_OPCODE_BITAND }, - { "BITOR" , SC_OPCODE_BITOR }, - { "BITXOR" , SC_OPCODE_BITXOR }, - { "BITRSHIFT" , SC_OPCODE_BITRSHIFT }, - { "BITLSHIFT" , SC_OPCODE_BITLSHIFT }, + { "IF" , ocIf }, + { "IFERROR" , ocIfError }, + { "IFNA" , ocIfNA }, + { "CHOOSE" , ocChoose }, + { "(" , ocOpen }, + { ")" , ocClose }, + // ocTableRef... not supported in ODFF + { "{" , ocArrayOpen }, + { "}" , ocArrayClose }, + { "|" , ocArrayRowSep }, + { ";" , ocArrayColSep }, + { ";" , ocSep }, + { "%" , ocPercentSign }, + { "+" , ocAdd }, + { "-" , ocSub }, + { "*" , ocMul }, + { "/" , ocDiv }, + { "&" , ocAmpersand }, + { "^" , ocPow }, + { "=" , ocEqual }, + { "<>" , ocNotEqual }, + { "<" , ocLess }, + { ">" , ocGreater }, + { "<=" , ocLessEqual }, + { ">=" , ocGreaterEqual }, + { "AND" , ocAnd }, + { "OR" , ocOr }, + { "XOR" , ocXor }, + { "!" , ocIntersect }, + { "~" , ocUnion }, + { ":" , ocRange }, + { "NOT" , ocNot }, + { "NEG" , ocNeg }, + { "-" , ocNegSub }, + { "@" , ocSingleValue }, + { "#" , ocSpill }, + { "PI" , ocPi }, + { "RAND" , ocRandom }, + { "TRUE" , ocTrue }, + { "FALSE" , ocFalse }, + { "TODAY" , ocGetActDate }, + { "NOW" , ocGetActTime }, + { "NA" , ocNotAvail }, + { "ORG.OPENOFFICE.CURRENT" , ocCurrent }, + { "DEGREES" , ocDeg }, + { "RADIANS" , ocRad }, + { "SIN" , ocSin }, + { "COS" , ocCos }, + { "TAN" , ocTan }, + { "COT" , ocCot }, + { "ASIN" , ocArcSin }, + { "ACOS" , ocArcCos }, + { "ATAN" , ocArcTan }, + { "ACOT" , ocArcCot }, + { "SINH" , ocSinHyp }, + { "COSH" , ocCosHyp }, + { "TANH" , ocTanHyp }, + { "COTH" , ocCotHyp }, + { "ASINH" , ocArcSinHyp }, + { "ACOSH" , ocArcCosHyp }, + { "ATANH" , ocArcTanHyp }, + { "ACOTH" , ocArcCotHyp }, + { "CSC" , ocCosecant }, + { "SEC" , ocSecant }, + { "CSCH" , ocCosecantHyp }, + { "SECH" , ocSecantHyp }, + { "EXP" , ocExp }, + { "LN" , ocLn }, + { "SQRT" , ocSqrt }, + { "FACT" , ocFact }, + { "YEAR" , ocGetYear }, + { "MONTH" , ocGetMonth }, + { "DAY" , ocGetDay }, + { "HOUR" , ocGetHour }, + { "MINUTE" , ocGetMin }, + { "SECOND" , ocGetSec }, + { "SIGN" , ocPlusMinus }, + { "ABS" , ocAbs }, + { "INT" , ocInt }, + { "PHI" , ocPhi }, + { "GAUSS" , ocGauss }, + { "ISBLANK" , ocIsEmpty }, + { "ISTEXT" , ocIsString }, + { "ISNONTEXT" , ocIsNonString }, + { "ISLOGICAL" , ocIsLogical }, + { "TYPE" , ocType }, + { "CELL" , ocCell }, + { "ISREF" , ocIsRef }, + { "ISNUMBER" , ocIsValue }, + { "ISFORMULA" , ocIsFormula }, + { "ISNA" , ocIsNA }, + { "ISERR" , ocIsErr }, + { "ISERROR" , ocIsError }, + { "ISEVEN" , ocIsEven }, + { "ISODD" , ocIsOdd }, + { "N" , ocN }, + { "DATEVALUE" , ocGetDateValue }, + { "TIMEVALUE" , ocGetTimeValue }, + { "CODE" , ocCode }, + { "TRIM" , ocTrim }, + { "UPPER" , ocUpper }, + { "PROPER" , ocProper }, + { "LOWER" , ocLower }, + { "LEN" , ocLen }, + { "T" , ocT }, + { "VALUE" , ocValue }, + { "CLEAN" , ocClean }, + { "CHAR" , ocChar}, + { "JIS" , ocJis }, + { "ASC" , ocAsc }, + { "UNICODE" , ocUnicode }, + { "UNICHAR" , ocUnichar }, + { "LOG10" , ocLog10 }, + { "EVEN" , ocEven }, + { "ODD" , ocOdd }, + { "LEGACY.NORMSDIST" , ocStdNormDist }, + { "COM.MICROSOFT.NORM.S.DIST" , ocStdNormDist_MS }, + { "FISHER" , ocFisher }, + { "FISHERINV" , ocFisherInv }, + { "LEGACY.NORMSINV" , ocSNormInv }, + { "COM.MICROSOFT.NORM.S.INV" , ocSNormInv_MS }, + { "GAMMALN" , ocGammaLn }, + { "COM.MICROSOFT.GAMMALN.PRECISE" , ocGammaLn_MS }, + { "ORG.OPENOFFICE.ERRORTYPE" , ocErrorType }, + { "ERROR.TYPE" , ocErrorType_ODF }, + { "FORMULA" , ocFormula }, + { "ATAN2" , ocArcTan2 }, + { "COM.MICROSOFT.CEILING.MATH" , ocCeil_Math }, + { "CEILING" , ocCeil }, + { "COM.MICROSOFT.CEILING" , ocCeil_MS }, + { "COM.MICROSOFT.CEILING.PRECISE" , ocCeil_Precise }, + { "COM.MICROSOFT.ISO.CEILING" , ocCeil_ISO }, + { "FLOOR" , ocFloor }, + { "COM.MICROSOFT.FLOOR" , ocFloor_MS }, + { "COM.MICROSOFT.FLOOR.MATH" , ocFloor_Math }, + { "COM.MICROSOFT.FLOOR.PRECISE" , ocFloor_Precise }, + { "ROUND" , ocRound }, + { "ROUNDUP" , ocRoundUp }, + { "ROUNDDOWN" , ocRoundDown }, + { "TRUNC" , ocTrunc }, + { "LOG" , ocLog }, + { "POWER" , ocPower }, + { "GCD" , ocGCD }, + { "LCM" , ocLCM }, + { "MOD" , ocMod }, + { "SUMPRODUCT" , ocSumProduct }, + { "SUMSQ" , ocSumSQ }, + { "SUMX2MY2" , ocSumX2MY2 }, + { "SUMX2PY2" , ocSumX2DY2 }, + { "SUMXMY2" , ocSumXMY2 }, + { "DATE" , ocGetDate }, + { "TIME" , ocGetTime }, + { "DAYS" , ocGetDiffDate }, + { "DAYS360" , ocGetDiffDate360 }, + { "DATEDIF" , ocGetDateDif }, + { "MIN" , ocMin }, + { "MINA" , ocMinA }, + { "MAX" , ocMax }, + { "MAXA" , ocMaxA }, + { "SUM" , ocSum }, + { "PRODUCT" , ocProduct }, + { "AVERAGE" , ocAverage }, + { "AVERAGEA" , ocAverageA }, + { "COUNT" , ocCount }, + { "COUNTA" , ocCount2 }, + { "NPV" , ocNPV }, + { "IRR" , ocIRR }, + { "MIRR" , ocMIRR }, + { "ISPMT" , ocISPMT }, + { "VAR" , ocVar }, + { "VARA" , ocVarA }, + { "VARP" , ocVarP }, + { "VARPA" , ocVarPA }, + { "COM.MICROSOFT.VAR.P" , ocVarP_MS }, + { "COM.MICROSOFT.VAR.S" , ocVarS }, + { "STDEV" , ocStDev }, + { "STDEVA" , ocStDevA }, + { "STDEVP" , ocStDevP }, + { "STDEVPA" , ocStDevPA }, + { "COM.MICROSOFT.STDEV.P" , ocStDevP_MS }, + { "COM.MICROSOFT.STDEV.S" , ocStDevS }, + { "BINOM.DIST.RANGE" , ocB }, + { "NORMDIST" , ocNormDist }, + { "COM.MICROSOFT.NORM.DIST" , ocNormDist_MS }, + { "EXPONDIST" , ocExpDist }, + { "COM.MICROSOFT.EXPON.DIST" , ocExpDist_MS }, + { "BINOMDIST" , ocBinomDist }, + { "COM.MICROSOFT.BINOM.DIST" , ocBinomDist_MS }, + { "POISSON" , ocPoissonDist }, + { "COM.MICROSOFT.POISSON.DIST" , ocPoissonDist_MS }, + { "COMBIN" , ocCombin }, + { "COMBINA" , ocCombinA }, + { "PERMUT" , ocPermut }, + { "PERMUTATIONA" , ocPermutationA }, + { "PV" , ocPV }, + { "SYD" , ocSYD }, + { "DDB" , ocDDB }, + { "DB" , ocDB }, + { "VDB" , ocVBD }, + { "PDURATION" , ocPDuration }, + { "SLN" , ocSLN }, + { "PMT" , ocPMT }, + { "COLUMNS" , ocColumns }, + { "ROWS" , ocRows }, + { "SHEETS" , ocSheets }, + { "COLUMN" , ocColumn }, + { "ROW" , ocRow }, + { "SHEET" , ocSheet }, + { "RRI" , ocRRI }, + { "FV" , ocFV }, + { "NPER" , ocNper }, + { "RATE" , ocRate }, + { "IPMT" , ocIpmt }, + { "PPMT" , ocPpmt }, + { "CUMIPMT" , ocCumIpmt }, + { "CUMPRINC" , ocCumPrinc }, + { "EFFECT" , ocEffect }, + { "NOMINAL" , ocNominal }, + { "SUBTOTAL" , ocSubTotal }, + { "DSUM" , ocDBSum }, + { "DCOUNT" , ocDBCount }, + { "DCOUNTA" , ocDBCount2 }, + { "DAVERAGE" , ocDBAverage }, + { "DGET" , ocDBGet }, + { "DMAX" , ocDBMax }, + { "DMIN" , ocDBMin }, + { "DPRODUCT" , ocDBProduct }, + { "DSTDEV" , ocDBStdDev }, + { "DSTDEVP" , ocDBStdDevP }, + { "DVAR" , ocDBVar }, + { "DVARP" , ocDBVarP }, + { "INDIRECT" , ocIndirect }, + { "ADDRESS" , ocAddress }, + { "MATCH" , ocMatch }, + { "COM.MICROSOFT.XMATCH" , ocXMatch }, + { "COUNTBLANK" , ocCountEmptyCells }, + { "COUNTIF" , ocCountIf }, + { "SUMIF" , ocSumIf }, + { "AVERAGEIF" , ocAverageIf }, + { "SUMIFS" , ocSumIfs }, + { "AVERAGEIFS" , ocAverageIfs }, + { "COUNTIFS" , ocCountIfs }, + { "LOOKUP" , ocLookup }, + { "VLOOKUP" , ocVLookup }, + { "COM.MICROSOFT.XLOOKUP" , ocXLookup }, + { "HLOOKUP" , ocHLookup }, + { "COM.MICROSOFT.FILTER" , ocFilter }, + { "COM.MICROSOFT.SORT" , ocSort }, + { "COM.MICROSOFT.SORTBY" , ocSortBy }, + { "COM.MICROSOFT.CHOOSECOLS" , ocChooseCols }, + { "COM.MICROSOFT.CHOOSEROWS" , ocChooseRows }, + { "COM.MICROSOFT.DROP" , ocDrop }, + { "COM.MICROSOFT.EXPAND" , ocExpand }, + { "COM.MICROSOFT.HSTACK" , ocHStack }, + { "COM.MICROSOFT.VSTACK" , ocVStack }, + { "COM.MICROSOFT.TAKE" , ocTake }, + { "COM.MICROSOFT.TEXTAFTER" , ocTextAfter }, + { "COM.MICROSOFT.TEXTBEFORE" , ocTextBefore }, + { "COM.MICROSOFT.TEXTSPLIT" , ocTextSplit }, + { "COM.MICROSOFT.TOCOL" , ocToCol }, + { "COM.MICROSOFT.TOROW" , ocToRow }, + { "COM.MICROSOFT.UNIQUE" , ocUnique }, + { "COM.MICROSOFT.LET" , ocLet }, + { "COM.MICROSOFT.WRAPCOLS" , ocWrapCols }, + { "COM.MICROSOFT.WRAPROWS" , ocWrapRows }, + { "COM.MICROSOFT.LAMBDA" , ocLambda }, + { "COM.MICROSOFT.ISOMITTED" , ocIsOmitted }, + { "COM.MICROSOFT.BYCOL" , ocByCol }, + { "COM.MICROSOFT.BYROW" , ocByRow }, + { "COM.MICROSOFT.MAKEARRAY" , ocMakeArray }, + { "COM.MICROSOFT.MAP" , ocMap }, + { "COM.MICROSOFT.REDUCE" , ocReduce }, + { "COM.MICROSOFT.SCAN" , ocScan }, + { "COM.MICROSOFT.ARRAYTOTEXT" , ocArrayToText }, + { "_xlpm." , ocStringName }, + { "_xlop." , ocStringName }, + { "ORG.OPENOFFICE.MULTIRANGE" , ocMultiArea }, // legacy for range list (union) + { "OFFSET" , ocOffset }, + { "INDEX" , ocIndex }, + { "AREAS" , ocAreas }, + { "DOLLAR" , ocCurrency }, + { "REPLACE" , ocReplace }, + { "FIXED" , ocFixed }, + { "FIND" , ocFind }, + { "EXACT" , ocExact }, + { "LEFT" , ocLeft }, + { "RIGHT" , ocRight }, + { "SEARCH" , ocSearch }, + { "MID" , ocMid }, + { "LENB" , ocLenB }, + { "RIGHTB" , ocRightB }, + { "LEFTB" , ocLeftB }, + { "REPLACEB" , ocReplaceB }, + { "FINDB" , ocFindB }, + { "SEARCHB" , ocSearchB }, + { "MIDB" , ocMidB }, + { "TEXT" , ocText }, + { "SUBSTITUTE" , ocSubstitute }, + { "REPT" , ocRept }, + { "CONCATENATE" , ocConcat }, + { "COM.MICROSOFT.CONCAT" , ocConcat_MS }, + { "COM.MICROSOFT.TEXTJOIN" , ocTextJoin_MS }, + { "COM.MICROSOFT.IFS" , ocIfs_MS }, + { "COM.MICROSOFT.SWITCH" , ocSwitch_MS }, + { "COM.MICROSOFT.MINIFS" , ocMinIfs_MS }, + { "COM.MICROSOFT.MAXIFS" , ocMaxIfs_MS }, + { "MVALUE" , ocMatValue }, + { "MDETERM" , ocMatDet }, + { "MINVERSE" , ocMatInv }, + { "MMULT" , ocMatMult }, + { "COM.MICROSOFT.SEQUENCE" , ocMatSequence }, + { "TRANSPOSE" , ocMatTrans }, + { "MUNIT" , ocMatrixUnit }, + { "ORG.OPENOFFICE.GOALSEEK" , ocBackSolver }, + { "HYPGEOMDIST" , ocHypGeomDist }, + { "COM.MICROSOFT.HYPGEOM.DIST" , ocHypGeomDist_MS }, + { "LOGNORMDIST" , ocLogNormDist }, + { "COM.MICROSOFT.LOGNORM.DIST" , ocLogNormDist_MS }, + { "LEGACY.TDIST" , ocTDist }, + { "COM.MICROSOFT.T.DIST.2T" , ocTDist_2T }, + { "COM.MICROSOFT.T.DIST" , ocTDist_MS }, + { "COM.MICROSOFT.T.DIST.RT" , ocTDist_RT }, + { "LEGACY.FDIST" , ocFDist }, + { "FDIST" , ocFDist_LT }, + { "COM.MICROSOFT.F.DIST.RT" , ocFDist_RT }, + { "LEGACY.CHIDIST" , ocChiDist }, + { "COM.MICROSOFT.CHISQ.DIST.RT" , ocChiDist_MS }, + { "WEIBULL" , ocWeibull }, + { "COM.MICROSOFT.WEIBULL.DIST" , ocWeibull_MS }, + { "NEGBINOMDIST" , ocNegBinomVert }, + { "COM.MICROSOFT.NEGBINOM.DIST" , ocNegBinomDist_MS }, + { "CRITBINOM" , ocCritBinom }, + { "COM.MICROSOFT.BINOM.INV" , ocBinomInv }, + { "KURT" , ocKurt }, + { "HARMEAN" , ocHarMean }, + { "GEOMEAN" , ocGeoMean }, + { "STANDARDIZE" , ocStandard }, + { "AVEDEV" , ocAveDev }, + { "SKEW" , ocSkew }, + { "SKEWP" , ocSkewp }, + { "DEVSQ" , ocDevSq }, + { "MEDIAN" , ocMedian }, + { "MODE" , ocModalValue }, + { "COM.MICROSOFT.MODE.SNGL" , ocModalValue_MS }, + { "COM.MICROSOFT.MODE.MULT" , ocModalValue_Multi }, + { "ZTEST" , ocZTest }, + { "COM.MICROSOFT.Z.TEST" , ocZTest_MS }, + { "COM.MICROSOFT.AGGREGATE" , ocAggregate }, + { "TTEST" , ocTTest }, + { "COM.MICROSOFT.T.TEST" , ocTTest_MS }, + { "RANK" , ocRank }, + { "PERCENTILE" , ocPercentile }, + { "PERCENTRANK" , ocPercentrank }, + { "COM.MICROSOFT.PERCENTILE.INC" , ocPercentile_Inc }, + { "COM.MICROSOFT.PERCENTRANK.INC" , ocPercentrank_Inc }, + { "COM.MICROSOFT.QUARTILE.INC" , ocQuartile_Inc }, + { "COM.MICROSOFT.RANK.EQ" , ocRank_Eq }, + { "COM.MICROSOFT.PERCENTILE.EXC" , ocPercentile_Exc }, + { "COM.MICROSOFT.PERCENTRANK.EXC" , ocPercentrank_Exc }, + { "COM.MICROSOFT.QUARTILE.EXC" , ocQuartile_Exc }, + { "COM.MICROSOFT.RANK.AVG" , ocRank_Avg }, + { "LARGE" , ocLarge }, + { "SMALL" , ocSmall }, + { "FREQUENCY" , ocFrequency }, + { "QUARTILE" , ocQuartile }, + { "NORMINV" , ocNormInv }, + { "COM.MICROSOFT.NORM.INV" , ocNormInv_MS }, + { "CONFIDENCE" , ocConfidence }, + { "COM.MICROSOFT.CONFIDENCE.NORM" , ocConfidence_N }, + { "COM.MICROSOFT.CONFIDENCE.T" , ocConfidence_T }, + { "FTEST" , ocFTest }, + { "COM.MICROSOFT.F.TEST" , ocFTest_MS }, + { "TRIMMEAN" , ocTrimMean }, + { "PROB" , ocProb }, + { "CORREL" , ocCorrel }, + { "COVAR" , ocCovar }, + { "COM.MICROSOFT.COVARIANCE.P" , ocCovarianceP }, + { "COM.MICROSOFT.COVARIANCE.S" , ocCovarianceS }, + { "PEARSON" , ocPearson }, + { "RSQ" , ocRSQ }, + { "STEYX" , ocSTEYX }, + { "SLOPE" , ocSlope }, + { "INTERCEPT" , ocIntercept }, + { "TREND" , ocTrend }, + { "GROWTH" , ocGrowth }, + { "LINEST" , ocLinest }, + { "LOGEST" , ocLogest }, + { "FORECAST" , ocForecast }, + { "COM.MICROSOFT.FORECAST.ETS" , ocForecast_ETS_ADD }, + { "COM.MICROSOFT.FORECAST.ETS.SEASONALITY" , ocForecast_ETS_SEA }, + { "ORG.LIBREOFFICE.FORECAST.ETS.MULT" , ocForecast_ETS_MUL }, + { "COM.MICROSOFT.FORECAST.ETS.CONFINT" , ocForecast_ETS_PIA }, + { "ORG.LIBREOFFICE.FORECAST.ETS.PI.MULT" , ocForecast_ETS_PIM }, + { "COM.MICROSOFT.FORECAST.ETS.STAT" , ocForecast_ETS_STA }, + { "ORG.LIBREOFFICE.FORECAST.ETS.STAT.MULT" , ocForecast_ETS_STM }, + { "COM.MICROSOFT.FORECAST.LINEAR" , ocForecast_LIN }, + { "LEGACY.CHIINV" , ocChiInv }, + { "COM.MICROSOFT.CHISQ.INV.RT" , ocChiInv_MS }, + { "GAMMADIST" , ocGammaDist }, + { "COM.MICROSOFT.GAMMA.DIST" , ocGammaDist_MS }, + { "GAMMAINV" , ocGammaInv }, + { "COM.MICROSOFT.GAMMA.INV" , ocGammaInv_MS }, + { "TINV" , ocTInv }, + { "COM.MICROSOFT.T.INV.2T" , ocTInv_2T }, + { "COM.MICROSOFT.T.INV" , ocTInv_MS }, + { "LEGACY.FINV" , ocFInv }, + { "FINV" , ocFInv_LT }, + { "COM.MICROSOFT.F.INV.RT" , ocFInv_RT }, + { "LEGACY.CHITEST" , ocChiTest }, + { "COM.MICROSOFT.CHISQ.TEST" , ocChiTest_MS }, + { "LOGINV" , ocLogInv }, + { "COM.MICROSOFT.LOGNORM.INV" , ocLogInv_MS }, + { "MULTIPLE.OPERATIONS" , ocTableOp }, + { "BETADIST" , ocBetaDist }, + { "BETAINV" , ocBetaInv }, + { "COM.MICROSOFT.BETA.DIST" , ocBetaDist_MS }, + { "COM.MICROSOFT.BETA.INV" , ocBetaInv_MS }, + { "WEEKNUM" , ocWeek }, + { "ISOWEEKNUM" , ocIsoWeeknum }, + { "ORG.LIBREOFFICE.WEEKNUM_OOO" , ocWeeknumOOo }, + { "EASTERSUNDAY" , ocEasterSunday }, + { "WEEKDAY" , ocGetDayOfWeek }, + { "NETWORKDAYS" , ocNetWorkdays }, + { "COM.MICROSOFT.NETWORKDAYS.INTL" , ocNetWorkdays_MS }, + { "COM.MICROSOFT.WORKDAY.INTL" , ocWorkday_MS }, + { "#NAME!" , ocNoName }, + { "ORG.OPENOFFICE.STYLE" , ocStyle }, + { "DDE" , ocDde }, + { "BASE" , ocBase }, + { "DECIMAL" , ocDecimal }, + { "ORG.OPENOFFICE.CONVERT" , ocConvertOOo }, + { "ROMAN" , ocRoman }, + { "ARABIC" , ocArabic }, + { "HYPERLINK" , ocHyperLink }, + { "INFO" , ocInfo }, + { "COM.MICROSOFT.BAHTTEXT" , ocBahtText }, + { "GETPIVOTDATA" , ocGetPivotData }, + { "EUROCONVERT" , ocEuroConvert }, + { "NUMBERVALUE" , ocNumberValue }, + { "GAMMA" , ocGamma }, + { "CHISQDIST" , ocChiSqDist }, + { "COM.MICROSOFT.CHISQ.DIST" , ocChiSqDist_MS }, + { "CHISQINV" , ocChiSqInv }, + { "COM.MICROSOFT.CHISQ.INV" , ocChiSqInv_MS }, + { "BITAND" , ocBitAnd }, + { "BITOR" , ocBitOr }, + { "BITXOR" , ocBitXor }, + { "BITRSHIFT" , ocBitRshift }, + { "BITLSHIFT" , ocBitLshift }, /* BEGIN defined ERROR.TYPE() values. */ - { "#NULL!" , SC_OPCODE_ERROR_NULL }, - { "#DIV/0!" , SC_OPCODE_ERROR_DIVZERO }, - { "#VALUE!" , SC_OPCODE_ERROR_VALUE }, - { "#REF!" , SC_OPCODE_ERROR_REF }, - { "#NAME?" , SC_OPCODE_ERROR_NAME }, - { "#NUM!" , SC_OPCODE_ERROR_NUM }, - { "#N/A" , SC_OPCODE_ERROR_NA }, + { "#NULL!" , ocErrNull }, + { "#DIV/0!" , ocErrDivZero }, + { "#VALUE!" , ocErrValue }, + { "#REF!" , ocErrRef }, + { "#NAME?" , ocErrName }, + { "#NUM!" , ocErrNum }, + { "#N/A" , ocErrNA }, + { "#SPILL!" , ocErrSpill }, /* END defined ERROR.TYPE() values. */ - { "COM.MICROSOFT.FILTERXML" , SC_OPCODE_FILTERXML }, - { "COM.MICROSOFT.WEBSERVICE" , SC_OPCODE_WEBSERVICE }, - { "ORG.LIBREOFFICE.COLOR" , SC_OPCODE_COLOR }, - { "COM.MICROSOFT.ERF.PRECISE" , SC_OPCODE_ERF_MS }, - { "COM.MICROSOFT.ERFC.PRECISE" , SC_OPCODE_ERFC_MS }, - { "COM.MICROSOFT.ENCODEURL" , SC_OPCODE_ENCODEURL }, - { "ORG.LIBREOFFICE.RAWSUBTRACT" , SC_OPCODE_RAWSUBTRACT }, - { "ORG.LIBREOFFICE.ROUNDSIG" , SC_OPCODE_ROUNDSIG }, - { "ORG.LIBREOFFICE.REGEX" , SC_OPCODE_REGEX }, - { "ORG.LIBREOFFICE.FOURIER", SC_OPCODE_FOURIER }, - { "ORG.LIBREOFFICE.RAND.NV" , SC_OPCODE_RANDOM_NV }, - { "ORG.LIBREOFFICE.RANDBETWEEN.NV" , SC_OPCODE_RANDBETWEEN_NV }, - { "COM.MICROSOFT.RANDARRAY" , SC_OPCODE_RANDARRAY }, + { "COM.MICROSOFT.FILTERXML" , ocFilterXML }, + { "COM.MICROSOFT.WEBSERVICE" , ocWebservice }, + { "ORG.LIBREOFFICE.COLOR" , ocColor }, + { "COM.MICROSOFT.ERF.PRECISE" , ocErf_MS }, + { "COM.MICROSOFT.ERFC.PRECISE" , ocErfc_MS }, + { "COM.MICROSOFT.ENCODEURL" , ocEncodeURL }, + { "ORG.LIBREOFFICE.RAWSUBTRACT" , ocRawSubtract }, + { "ORG.LIBREOFFICE.ROUNDSIG" , ocRoundSig }, + { "ORG.LIBREOFFICE.REGEX" , ocRegex }, + { "ORG.LIBREOFFICE.FOURIER", ocFourier }, + { "ORG.LIBREOFFICE.RAND.NV" , ocRandomNV }, + { "ORG.LIBREOFFICE.RANDBETWEEN.NV" , ocRandbetweenNV }, + { "COM.MICROSOFT.RANDARRAY" , ocRandArray }, { nullptr, -1 } }; /** These function names are used in the OOXML XLSX import/export. */ const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML[] = { - { "IF" , SC_OPCODE_IF }, - { "IFERROR" , SC_OPCODE_IF_ERROR }, - { "_xlfn.IFNA" , SC_OPCODE_IF_NA }, - { "CHOOSE" , SC_OPCODE_CHOOSE }, - { "(" , SC_OPCODE_OPEN }, - { ")" , SC_OPCODE_CLOSE }, - { "[" , SC_OPCODE_TABLE_REF_OPEN }, - { "]" , SC_OPCODE_TABLE_REF_CLOSE }, - { "#All" , SC_OPCODE_TABLE_REF_ITEM_ALL }, - { "#Headers" , SC_OPCODE_TABLE_REF_ITEM_HEADERS }, - { "#Data" , SC_OPCODE_TABLE_REF_ITEM_DATA }, - { "#Totals" , SC_OPCODE_TABLE_REF_ITEM_TOTALS }, - { "#This Row" , SC_OPCODE_TABLE_REF_ITEM_THIS_ROW }, - { "{" , SC_OPCODE_ARRAY_OPEN }, - { "}" , SC_OPCODE_ARRAY_CLOSE }, - { ";" , SC_OPCODE_ARRAY_ROW_SEP }, - { "," , SC_OPCODE_ARRAY_COL_SEP }, - { "," , SC_OPCODE_SEP }, - { "%" , SC_OPCODE_PERCENT_SIGN }, - { "+" , SC_OPCODE_ADD }, - { "-" , SC_OPCODE_SUB }, - { "*" , SC_OPCODE_MUL }, - { "/" , SC_OPCODE_DIV }, - { "&" , SC_OPCODE_AMPERSAND }, - { "^" , SC_OPCODE_POW }, - { "=" , SC_OPCODE_EQUAL }, - { "<>" , SC_OPCODE_NOT_EQUAL }, - { "<" , SC_OPCODE_LESS }, - { ">" , SC_OPCODE_GREATER }, - { "<=" , SC_OPCODE_LESS_EQUAL }, - { ">=" , SC_OPCODE_GREATER_EQUAL }, - { "AND" , SC_OPCODE_AND }, - { "OR" , SC_OPCODE_OR }, - { "_xlfn.XOR" , SC_OPCODE_XOR }, - { " " , SC_OPCODE_INTERSECT }, - { "," , SC_OPCODE_UNION }, // Excel uses ',' as Union operator - { ":" , SC_OPCODE_RANGE }, - { "NOT" , SC_OPCODE_NOT }, - { "NEG" , SC_OPCODE_NEG }, - { "-" , SC_OPCODE_NEG_SUB }, - { "PI" , SC_OPCODE_PI }, - { "RAND" , SC_OPCODE_RANDOM }, - { "TRUE" , SC_OPCODE_TRUE }, - { "FALSE" , SC_OPCODE_FALSE }, - { "TODAY" , SC_OPCODE_GET_ACT_DATE }, - { "NOW" , SC_OPCODE_GET_ACT_TIME }, - { "NA" , SC_OPCODE_NO_VALUE }, - { "_xlfn.ORG.OPENOFFICE.CURRENT" , SC_OPCODE_CURRENT }, - { "DEGREES" , SC_OPCODE_DEG }, - { "RADIANS" , SC_OPCODE_RAD }, - { "SIN" , SC_OPCODE_SIN }, - { "COS" , SC_OPCODE_COS }, - { "TAN" , SC_OPCODE_TAN }, - { "_xlfn.COT" , SC_OPCODE_COT }, - { "ASIN" , SC_OPCODE_ARC_SIN }, - { "ACOS" , SC_OPCODE_ARC_COS }, - { "ATAN" , SC_OPCODE_ARC_TAN }, - { "_xlfn.ACOT" , SC_OPCODE_ARC_COT }, - { "SINH" , SC_OPCODE_SIN_HYP }, - { "COSH" , SC_OPCODE_COS_HYP }, - { "TANH" , SC_OPCODE_TAN_HYP }, - { "_xlfn.COTH" , SC_OPCODE_COT_HYP }, - { "ASINH" , SC_OPCODE_ARC_SIN_HYP }, - { "ACOSH" , SC_OPCODE_ARC_COS_HYP }, - { "ATANH" , SC_OPCODE_ARC_TAN_HYP }, - { "_xlfn.ACOTH" , SC_OPCODE_ARC_COT_HYP }, - { "_xlfn.CSC" , SC_OPCODE_COSECANT }, - { "_xlfn.SEC" , SC_OPCODE_SECANT }, - { "_xlfn.CSCH" , SC_OPCODE_COSECANT_HYP }, - { "_xlfn.SECH" , SC_OPCODE_SECANT_HYP }, - { "EXP" , SC_OPCODE_EXP }, - { "LN" , SC_OPCODE_LN }, - { "SQRT" , SC_OPCODE_SQRT }, - { "FACT" , SC_OPCODE_FACT }, - { "YEAR" , SC_OPCODE_GET_YEAR }, - { "MONTH" , SC_OPCODE_GET_MONTH }, - { "DAY" , SC_OPCODE_GET_DAY }, - { "HOUR" , SC_OPCODE_GET_HOUR }, - { "MINUTE" , SC_OPCODE_GET_MIN }, - { "SECOND" , SC_OPCODE_GET_SEC }, - { "SIGN" , SC_OPCODE_PLUS_MINUS }, - { "ABS" , SC_OPCODE_ABS }, - { "INT" , SC_OPCODE_INT }, - { "_xlfn.PHI" , SC_OPCODE_PHI }, - { "_xlfn.GAUSS" , SC_OPCODE_GAUSS }, - { "ISBLANK" , SC_OPCODE_IS_EMPTY }, - { "ISTEXT" , SC_OPCODE_IS_STRING }, - { "ISNONTEXT" , SC_OPCODE_IS_NON_STRING }, - { "ISLOGICAL" , SC_OPCODE_IS_LOGICAL }, - { "TYPE" , SC_OPCODE_TYPE }, - { "CELL" , SC_OPCODE_CELL }, - { "ISREF" , SC_OPCODE_IS_REF }, - { "ISNUMBER" , SC_OPCODE_IS_VALUE }, - { "_xlfn.ISFORMULA" , SC_OPCODE_IS_FORMULA }, - { "ISNA" , SC_OPCODE_IS_NV }, - { "ISERR" , SC_OPCODE_IS_ERR }, - { "ISERROR" , SC_OPCODE_IS_ERROR }, - { "ISEVEN" , SC_OPCODE_IS_EVEN }, - { "ISODD" , SC_OPCODE_IS_ODD }, - { "N" , SC_OPCODE_N }, - { "DATEVALUE" , SC_OPCODE_GET_DATE_VALUE }, - { "TIMEVALUE" , SC_OPCODE_GET_TIME_VALUE }, - { "CODE" , SC_OPCODE_CODE }, - { "TRIM" , SC_OPCODE_TRIM }, - { "UPPER" , SC_OPCODE_UPPER }, - { "PROPER" , SC_OPCODE_PROPER }, - { "LOWER" , SC_OPCODE_LOWER }, - { "LEN" , SC_OPCODE_LEN }, - { "T" , SC_OPCODE_T }, - { "VALUE" , SC_OPCODE_VALUE }, - { "CLEAN" , SC_OPCODE_CLEAN }, - { "CHAR" , SC_OPCODE_CHAR }, - { "JIS" , SC_OPCODE_JIS }, - { "ASC" , SC_OPCODE_ASC }, - { "_xlfn.UNICODE" , SC_OPCODE_UNICODE }, - { "_xlfn.UNICHAR" , SC_OPCODE_UNICHAR }, - { "LOG10" , SC_OPCODE_LOG10 }, - { "EVEN" , SC_OPCODE_EVEN }, - { "ODD" , SC_OPCODE_ODD }, - { "NORMSDIST" , SC_OPCODE_STD_NORM_DIST }, - { "_xlfn.NORM.S.DIST" , SC_OPCODE_STD_NORM_DIST_MS }, - { "FISHER" , SC_OPCODE_FISHER }, - { "FISHERINV" , SC_OPCODE_FISHER_INV }, - { "NORMSINV" , SC_OPCODE_S_NORM_INV }, - { "_xlfn.NORM.S.INV" , SC_OPCODE_S_NORM_INV_MS }, - { "GAMMALN" , SC_OPCODE_GAMMA_LN }, - { "_xlfn.GAMMALN.PRECISE" , SC_OPCODE_GAMMA_LN_MS }, - { "_xlfn.ORG.OPENOFFICE.ERRORTYPE" , SC_OPCODE_ERROR_TYPE }, - { "ERROR.TYPE" , SC_OPCODE_ERROR_TYPE_ODF }, - { "_xlfn.FORMULATEXT" , SC_OPCODE_FORMULA }, - { "ATAN2" , SC_OPCODE_ARC_TAN_2 }, - { "_xlfn.CEILING.MATH" , SC_OPCODE_CEIL_MATH }, - { "_xlfn.CEILING.MATH" , SC_OPCODE_CEIL }, - { "CEILING" , SC_OPCODE_CEIL_MS }, - { "_xlfn.CEILING.PRECISE" , SC_OPCODE_CEIL_PRECISE }, - { "ISO.CEILING" , SC_OPCODE_CEIL_ISO }, - { "FLOOR" , SC_OPCODE_FLOOR_MS }, - { "_xlfn.FLOOR.MATH" , SC_OPCODE_FLOOR_MATH }, - { "_xlfn.FLOOR.MATH" , SC_OPCODE_FLOOR }, - { "_xlfn.FLOOR.PRECISE" , SC_OPCODE_FLOOR_PRECISE }, - { "ROUND" , SC_OPCODE_ROUND }, - { "ROUNDUP" , SC_OPCODE_ROUND_UP }, - { "ROUNDDOWN" , SC_OPCODE_ROUND_DOWN }, - { "TRUNC" , SC_OPCODE_TRUNC }, - { "LOG" , SC_OPCODE_LOG }, - { "POWER" , SC_OPCODE_POWER }, - { "GCD" , SC_OPCODE_GCD }, - { "LCM" , SC_OPCODE_LCM }, - { "MOD" , SC_OPCODE_MOD }, - { "SUMPRODUCT" , SC_OPCODE_SUM_PRODUCT }, - { "SUMSQ" , SC_OPCODE_SUM_SQ }, - { "SUMX2MY2" , SC_OPCODE_SUM_X2MY2 }, - { "SUMX2PY2" , SC_OPCODE_SUM_X2DY2 }, - { "SUMXMY2" , SC_OPCODE_SUM_XMY2 }, - { "DATE" , SC_OPCODE_GET_DATE }, - { "TIME" , SC_OPCODE_GET_TIME }, - { "_xlfn.DAYS" , SC_OPCODE_GET_DIFF_DATE }, - { "DAYS360" , SC_OPCODE_GET_DIFF_DATE_360 }, - { "DATEDIF" , SC_OPCODE_GET_DATEDIF }, - { "MIN" , SC_OPCODE_MIN }, - { "MINA" , SC_OPCODE_MIN_A }, - { "MAX" , SC_OPCODE_MAX }, - { "MAXA" , SC_OPCODE_MAX_A }, - { "SUM" , SC_OPCODE_SUM }, - { "PRODUCT" , SC_OPCODE_PRODUCT }, - { "AVERAGE" , SC_OPCODE_AVERAGE }, - { "AVERAGEA" , SC_OPCODE_AVERAGE_A }, - { "COUNT" , SC_OPCODE_COUNT }, - { "COUNTA" , SC_OPCODE_COUNT_2 }, - { "NPV" , SC_OPCODE_NPV }, - { "IRR" , SC_OPCODE_IRR }, - { "MIRR" , SC_OPCODE_MIRR }, - { "ISPMT" , SC_OPCODE_ISPMT }, - { "VAR" , SC_OPCODE_VAR }, - { "VARA" , SC_OPCODE_VAR_A }, - { "VARP" , SC_OPCODE_VAR_P }, - { "VARPA" , SC_OPCODE_VAR_P_A }, - { "_xlfn.VAR.P" , SC_OPCODE_VAR_P_MS }, - { "_xlfn.VAR.S" , SC_OPCODE_VAR_S }, - { "STDEV" , SC_OPCODE_ST_DEV }, - { "STDEVA" , SC_OPCODE_ST_DEV_A }, - { "STDEVP" , SC_OPCODE_ST_DEV_P }, - { "STDEVPA" , SC_OPCODE_ST_DEV_P_A }, - { "_xlfn.STDEV.P" , SC_OPCODE_ST_DEV_P_MS }, - { "_xlfn.STDEV.S" , SC_OPCODE_ST_DEV_S }, - { "B" , SC_OPCODE_B }, - { "NORMDIST" , SC_OPCODE_NORM_DIST }, - { "_xlfn.NORM.DIST" , SC_OPCODE_NORM_DIST_MS }, - { "EXPONDIST" , SC_OPCODE_EXP_DIST }, - { "_xlfn.EXPON.DIST" , SC_OPCODE_EXP_DIST_MS }, - { "BINOMDIST" , SC_OPCODE_BINOM_DIST }, - { "_xlfn.BINOM.DIST" , SC_OPCODE_BINOM_DIST_MS }, - { "POISSON" , SC_OPCODE_POISSON_DIST }, - { "_xlfn.POISSON.DIST" , SC_OPCODE_POISSON_DIST_MS }, - { "COMBIN" , SC_OPCODE_COMBIN }, - { "_xlfn.COMBINA" , SC_OPCODE_COMBIN_A }, - { "PERMUT" , SC_OPCODE_PERMUT }, - { "_xlfn.PERMUTATIONA" , SC_OPCODE_PERMUTATION_A }, - { "PV" , SC_OPCODE_PV }, - { "SYD" , SC_OPCODE_SYD }, - { "DDB" , SC_OPCODE_DDB }, - { "DB" , SC_OPCODE_DB }, - { "VDB" , SC_OPCODE_VBD }, - { "_xlfn.PDURATION" , SC_OPCODE_PDURATION }, - { "SLN" , SC_OPCODE_SLN }, - { "PMT" , SC_OPCODE_PMT }, - { "COLUMNS" , SC_OPCODE_COLUMNS }, - { "ROWS" , SC_OPCODE_ROWS }, - { "_xlfn.SHEETS" , SC_OPCODE_SHEETS }, - { "COLUMN" , SC_OPCODE_COLUMN }, - { "ROW" , SC_OPCODE_ROW }, - { "_xlfn.SHEET" , SC_OPCODE_SHEET }, - { "_xlfn.RRI" , SC_OPCODE_RRI }, - { "FV" , SC_OPCODE_FV }, - { "NPER" , SC_OPCODE_NPER }, - { "RATE" , SC_OPCODE_RATE }, - { "IPMT" , SC_OPCODE_IPMT }, - { "PPMT" , SC_OPCODE_PPMT }, - { "CUMIPMT" , SC_OPCODE_CUM_IPMT }, - { "CUMPRINC" , SC_OPCODE_CUM_PRINC }, - { "EFFECT" , SC_OPCODE_EFFECT }, - { "NOMINAL" , SC_OPCODE_NOMINAL }, - { "SUBTOTAL" , SC_OPCODE_SUB_TOTAL }, - { "DSUM" , SC_OPCODE_DB_SUM }, - { "DCOUNT" , SC_OPCODE_DB_COUNT }, - { "DCOUNTA" , SC_OPCODE_DB_COUNT_2 }, - { "DAVERAGE" , SC_OPCODE_DB_AVERAGE }, - { "DGET" , SC_OPCODE_DB_GET }, - { "DMAX" , SC_OPCODE_DB_MAX }, - { "DMIN" , SC_OPCODE_DB_MIN }, - { "DPRODUCT" , SC_OPCODE_DB_PRODUCT }, - { "DSTDEV" , SC_OPCODE_DB_STD_DEV }, - { "DSTDEVP" , SC_OPCODE_DB_STD_DEV_P }, - { "DVAR" , SC_OPCODE_DB_VAR }, - { "DVARP" , SC_OPCODE_DB_VAR_P }, - { "INDIRECT" , SC_OPCODE_INDIRECT }, - { "ADDRESS" , SC_OPCODE_ADDRESS }, - { "MATCH" , SC_OPCODE_MATCH }, - { "_xlfn.XMATCH" , SC_OPCODE_X_MATCH }, - { "COUNTBLANK" , SC_OPCODE_COUNT_EMPTY_CELLS }, - { "COUNTIF" , SC_OPCODE_COUNT_IF }, - { "SUMIF" , SC_OPCODE_SUM_IF }, - { "AVERAGEIF" , SC_OPCODE_AVERAGE_IF }, - { "SUMIFS" , SC_OPCODE_SUM_IFS }, - { "AVERAGEIFS" , SC_OPCODE_AVERAGE_IFS }, - { "COUNTIFS" , SC_OPCODE_COUNT_IFS }, - { "LOOKUP" , SC_OPCODE_LOOKUP }, - { "VLOOKUP" , SC_OPCODE_V_LOOKUP }, - { "_xlfn.XLOOKUP" , SC_OPCODE_X_LOOKUP }, - { "HLOOKUP" , SC_OPCODE_H_LOOKUP }, - { "_xlfn._xlws.FILTER" , SC_OPCODE_FILTER }, - { "_xlfn._xlws.SORT" , SC_OPCODE_SORT }, - { "_xlfn.SORTBY" , SC_OPCODE_SORTBY }, - { "_xlfn.CHOOSECOLS" , SC_OPCODE_CHOOSECOLS }, - { "_xlfn.CHOOSEROWS" , SC_OPCODE_CHOOSEROWS }, - { "_xlfn.DROP" , SC_OPCODE_DROP }, - { "_xlfn.EXPAND" , SC_OPCODE_EXPAND }, - { "_xlfn.HSTACK" , SC_OPCODE_HSTACK }, - { "_xlfn.VSTACK" , SC_OPCODE_VSTACK }, - { "_xlfn.TAKE" , SC_OPCODE_TAKE }, - { "_xlfn.TEXTAFTER" , SC_OPCODE_TEXTAFTER }, - { "_xlfn.TEXTBEFORE" , SC_OPCODE_TEXTBEFORE }, - { "_xlfn.TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, - { "_xlfn.TOCOL" , SC_OPCODE_TOCOL }, - { "_xlfn.TOROW" , SC_OPCODE_TOROW }, - { "_xlfn.UNIQUE" , SC_OPCODE_UNIQUE }, - { "_xlfn.LET" , SC_OPCODE_LET }, - { "_xlfn.WRAPCOLS" , SC_OPCODE_WRAPCOLS }, - { "_xlfn.WRAPROWS" , SC_OPCODE_WRAPROWS }, - { "_xlpm." , SC_OPCODE_STRINGNAME }, - { "_xlfn.ORG.OPENOFFICE.MULTIRANGE" , SC_OPCODE_MULTI_AREA }, // legacy for range list (union) - { "OFFSET" , SC_OPCODE_OFFSET }, - { "INDEX" , SC_OPCODE_INDEX }, - { "AREAS" , SC_OPCODE_AREAS }, - { "DOLLAR" , SC_OPCODE_CURRENCY }, - { "REPLACE" , SC_OPCODE_REPLACE }, - { "FIXED" , SC_OPCODE_FIXED }, - { "FIND" , SC_OPCODE_FIND }, - { "EXACT" , SC_OPCODE_EXACT }, - { "LEFT" , SC_OPCODE_LEFT }, - { "RIGHT" , SC_OPCODE_RIGHT }, - { "SEARCH" , SC_OPCODE_SEARCH }, - { "MID" , SC_OPCODE_MID }, - { "LENB" , SC_OPCODE_LENB }, - { "RIGHTB" , SC_OPCODE_RIGHTB }, - { "LEFTB" , SC_OPCODE_LEFTB }, - { "REPLACEB" , SC_OPCODE_REPLACEB }, - { "FINDB" , SC_OPCODE_FINDB }, - { "SEARCHB" , SC_OPCODE_SEARCHB }, - { "MIDB" , SC_OPCODE_MIDB }, - { "TEXT" , SC_OPCODE_TEXT }, - { "SUBSTITUTE" , SC_OPCODE_SUBSTITUTE }, - { "REPT" , SC_OPCODE_REPT }, - { "CONCATENATE" , SC_OPCODE_CONCAT }, - { "_xlfn.CONCAT" , SC_OPCODE_CONCAT_MS }, - { "_xlfn.TEXTJOIN" , SC_OPCODE_TEXTJOIN_MS }, - { "_xlfn.IFS" , SC_OPCODE_IFS_MS }, - { "_xlfn.SWITCH" , SC_OPCODE_SWITCH_MS }, - { "_xlfn.MINIFS" , SC_OPCODE_MINIFS_MS }, - { "_xlfn.MAXIFS" , SC_OPCODE_MAXIFS_MS }, - { "MVALUE" , SC_OPCODE_MAT_VALUE }, - { "MDETERM" , SC_OPCODE_MAT_DET }, - { "MINVERSE" , SC_OPCODE_MAT_INV }, - { "MMULT" , SC_OPCODE_MAT_MULT }, - { "_xlfn.SEQUENCE" , SC_OPCODE_MAT_SEQUENCE }, - { "TRANSPOSE" , SC_OPCODE_MAT_TRANS }, - { "_xlfn.MUNIT" , SC_OPCODE_MATRIX_UNIT }, - { "_xlfn.ORG.OPENOFFICE.GOALSEEK" , SC_OPCODE_BACK_SOLVER }, - { "HYPGEOMDIST" , SC_OPCODE_HYP_GEOM_DIST }, - { "_xlfn.HYPGEOM.DIST" , SC_OPCODE_HYP_GEOM_DIST_MS }, - { "LOGNORMDIST" , SC_OPCODE_LOG_NORM_DIST }, - { "_xlfn.LOGNORM.DIST" , SC_OPCODE_LOG_NORM_DIST_MS }, - { "TDIST" , SC_OPCODE_T_DIST }, - { "_xlfn.T.DIST.2T" , SC_OPCODE_T_DIST_2T }, - { "_xlfn.T.DIST" , SC_OPCODE_T_DIST_MS }, - { "_xlfn.T.DIST.RT" , SC_OPCODE_T_DIST_RT }, - { "FDIST" , SC_OPCODE_F_DIST }, - { "_xlfn.F.DIST" , SC_OPCODE_F_DIST_LT }, - { "_xlfn.F.DIST.RT" , SC_OPCODE_F_DIST_RT }, - { "CHIDIST" , SC_OPCODE_CHI_DIST }, - { "_xlfn.CHISQ.DIST.RT" , SC_OPCODE_CHI_DIST_MS }, - { "WEIBULL" , SC_OPCODE_WEIBULL }, - { "_xlfn.WEIBULL.DIST" , SC_OPCODE_WEIBULL_MS }, - { "NEGBINOMDIST" , SC_OPCODE_NEG_BINOM_VERT }, - { "_xlfn.NEGBINOM.DIST" , SC_OPCODE_NEG_BINOM_DIST_MS }, - { "CRITBINOM" , SC_OPCODE_CRIT_BINOM }, - { "_xlfn.BINOM.INV" , SC_OPCODE_BINOM_INV }, - { "KURT" , SC_OPCODE_KURT }, - { "HARMEAN" , SC_OPCODE_HAR_MEAN }, - { "GEOMEAN" , SC_OPCODE_GEO_MEAN }, - { "STANDARDIZE" , SC_OPCODE_STANDARD }, - { "AVEDEV" , SC_OPCODE_AVE_DEV }, - { "SKEW" , SC_OPCODE_SKEW }, - { "_xlfn.SKEW.P" , SC_OPCODE_SKEWP }, - { "DEVSQ" , SC_OPCODE_DEV_SQ }, - { "MEDIAN" , SC_OPCODE_MEDIAN }, - { "MODE" , SC_OPCODE_MODAL_VALUE }, - { "_xlfn.MODE.SNGL" , SC_OPCODE_MODAL_VALUE_MS }, - { "_xlfn.MODE.MULT" , SC_OPCODE_MODAL_VALUE_MULTI }, - { "ZTEST" , SC_OPCODE_Z_TEST }, - { "_xlfn.Z.TEST" , SC_OPCODE_Z_TEST_MS }, - { "_xlfn.AGGREGATE" , SC_OPCODE_AGGREGATE }, - { "TTEST" , SC_OPCODE_T_TEST }, - { "_xlfn.T.TEST" , SC_OPCODE_T_TEST_MS }, - { "RANK" , SC_OPCODE_RANK }, - { "PERCENTILE" , SC_OPCODE_PERCENTILE }, - { "PERCENTRANK" , SC_OPCODE_PERCENT_RANK }, - { "_xlfn.PERCENTILE.INC" , SC_OPCODE_PERCENTILE_INC }, - { "_xlfn.PERCENTRANK.INC" , SC_OPCODE_PERCENT_RANK_INC }, - { "_xlfn.QUARTILE.INC" , SC_OPCODE_QUARTILE_INC }, - { "_xlfn.RANK.EQ" , SC_OPCODE_RANK_EQ }, - { "_xlfn.PERCENTILE.EXC" , SC_OPCODE_PERCENTILE_EXC }, - { "_xlfn.PERCENTRANK.EXC" , SC_OPCODE_PERCENT_RANK_EXC }, - { "_xlfn.QUARTILE.EXC" , SC_OPCODE_QUARTILE_EXC }, - { "_xlfn.RANK.AVG" , SC_OPCODE_RANK_AVG }, - { "LARGE" , SC_OPCODE_LARGE }, - { "SMALL" , SC_OPCODE_SMALL }, - { "FREQUENCY" , SC_OPCODE_FREQUENCY }, - { "QUARTILE" , SC_OPCODE_QUARTILE }, - { "NORMINV" , SC_OPCODE_NORM_INV }, - { "_xlfn.NORM.INV" , SC_OPCODE_NORM_INV_MS }, - { "CONFIDENCE" , SC_OPCODE_CONFIDENCE }, - { "_xlfn.CONFIDENCE.NORM" , SC_OPCODE_CONFIDENCE_N }, - { "_xlfn.CONFIDENCE.T" , SC_OPCODE_CONFIDENCE_T }, - { "FTEST" , SC_OPCODE_F_TEST }, - { "_xlfn.F.TEST" , SC_OPCODE_F_TEST_MS }, - { "TRIMMEAN" , SC_OPCODE_TRIM_MEAN }, - { "PROB" , SC_OPCODE_PROB }, - { "CORREL" , SC_OPCODE_CORREL }, - { "COVAR" , SC_OPCODE_COVAR }, - { "_xlfn.COVARIANCE.P" , SC_OPCODE_COVARIANCE_P }, - { "_xlfn.COVARIANCE.S" , SC_OPCODE_COVARIANCE_S }, - { "PEARSON" , SC_OPCODE_PEARSON }, - { "RSQ" , SC_OPCODE_RSQ }, - { "STEYX" , SC_OPCODE_STEYX }, - { "SLOPE" , SC_OPCODE_SLOPE }, - { "INTERCEPT" , SC_OPCODE_INTERCEPT }, - { "TREND" , SC_OPCODE_TREND }, - { "GROWTH" , SC_OPCODE_GROWTH }, - { "LINEST" , SC_OPCODE_LINEST }, - { "LOGEST" , SC_OPCODE_LOGEST }, - { "FORECAST" , SC_OPCODE_FORECAST }, - { "_xlfn.FORECAST.ETS" , SC_OPCODE_FORECAST_ETS_ADD }, - { "_xlfn.FORECAST.ETS.SEASONALITY" , SC_OPCODE_FORECAST_ETS_SEA }, - { "_xlfn.ORG.LIBREOFFICE.FORECAST.ETS.MULT" , SC_OPCODE_FORECAST_ETS_MUL }, - { "_xlfn.FORECAST.ETS.CONFINT" , SC_OPCODE_FORECAST_ETS_PIA }, - { "_xlfn.ORG.LIBREOFFICE.FORECAST.ETS.PI.MULT" , SC_OPCODE_FORECAST_ETS_PIM }, - { "_xlfn.FORECAST.ETS.STAT" , SC_OPCODE_FORECAST_ETS_STA }, - { "_xlfn.ORG.LIBREOFFICE.FORECAST.ETS.STAT.MULT" , SC_OPCODE_FORECAST_ETS_STM }, - { "_xlfn.FORECAST.LINEAR" , SC_OPCODE_FORECAST_LIN }, - { "CHIINV" , SC_OPCODE_CHI_INV }, - { "_xlfn.CHISQ.INV.RT" , SC_OPCODE_CHI_INV_MS }, - { "GAMMADIST" , SC_OPCODE_GAMMA_DIST }, - { "_xlfn.GAMMA.DIST" , SC_OPCODE_GAMMA_DIST_MS }, - { "GAMMAINV" , SC_OPCODE_GAMMA_INV }, - { "_xlfn.GAMMA.INV" , SC_OPCODE_GAMMA_INV_MS }, - { "TINV" , SC_OPCODE_T_INV }, - { "_xlfn.T.INV.2T" , SC_OPCODE_T_INV_2T }, - { "_xlfn.T.INV" , SC_OPCODE_T_INV_MS }, - { "FINV" , SC_OPCODE_F_INV }, - { "_xlfn.F.INV" , SC_OPCODE_F_INV_LT }, - { "_xlfn.F.INV.RT" , SC_OPCODE_F_INV_RT }, - { "CHITEST" , SC_OPCODE_CHI_TEST }, - { "_xlfn.CHISQ.TEST" , SC_OPCODE_CHI_TEST_MS }, - { "LOGINV" , SC_OPCODE_LOG_INV }, - { "_xlfn.LOGNORM.INV" , SC_OPCODE_LOG_INV_MS }, - { "TABLE" , SC_OPCODE_TABLE_OP }, - { "BETADIST" , SC_OPCODE_BETA_DIST }, - { "BETAINV" , SC_OPCODE_BETA_INV }, - { "_xlfn.BETA.DIST" , SC_OPCODE_BETA_DIST_MS }, - { "_xlfn.BETA.INV" , SC_OPCODE_BETA_INV_MS }, - { "WEEKNUM" , SC_OPCODE_WEEK }, - { "_xlfn.ISOWEEKNUM" , SC_OPCODE_ISOWEEKNUM }, - { "_xlfn.ORG.LIBREOFFICE.WEEKNUM_OOO" , SC_OPCODE_WEEKNUM_OOO }, - { "_xlfn.ORG.OPENOFFICE.EASTERSUNDAY" , SC_OPCODE_EASTERSUNDAY }, - { "WEEKDAY" , SC_OPCODE_GET_DAY_OF_WEEK }, - { "NETWORKDAYS" , SC_OPCODE_NETWORKDAYS }, - { "NETWORKDAYS.INTL" , SC_OPCODE_NETWORKDAYS_MS }, - { "WORKDAY.INTL" , SC_OPCODE_WORKDAY_MS }, - { "#NAME!" , SC_OPCODE_NO_NAME }, - { "_xlfn.ORG.OPENOFFICE.STYLE" , SC_OPCODE_STYLE }, - { "DDE" , SC_OPCODE_DDE }, - { "_xlfn.BASE" , SC_OPCODE_BASE }, - { "_xlfn.DECIMAL" , SC_OPCODE_DECIMAL }, - { "_xlfn.ORG.OPENOFFICE.CONVERT" , SC_OPCODE_CONVERT_OOO }, - { "ROMAN" , SC_OPCODE_ROMAN }, - { "_xlfn.ARABIC" , SC_OPCODE_ARABIC }, - { "HYPERLINK" , SC_OPCODE_HYPERLINK }, - { "INFO" , SC_OPCODE_INFO }, - { "_xlfn.BAHTTEXT" , SC_OPCODE_BAHTTEXT }, - { "GETPIVOTDATA" , SC_OPCODE_GET_PIVOT_DATA }, - { "EUROCONVERT" , SC_OPCODE_EUROCONVERT }, - { "_xlfn.NUMBERVALUE" , SC_OPCODE_NUMBERVALUE }, - { "_xlfn.GAMMA" , SC_OPCODE_GAMMA }, - { "CHISQDIST" , SC_OPCODE_CHISQ_DIST }, - { "_xlfn.CHISQ.DIST" , SC_OPCODE_CHISQ_DIST_MS }, - { "CHISQINV" , SC_OPCODE_CHISQ_INV }, - { "_xlfn.CHISQ.INV" , SC_OPCODE_CHISQ_INV_MS }, - { "_xlfn.BITAND" , SC_OPCODE_BITAND }, - { "_xlfn.BITOR" , SC_OPCODE_BITOR }, - { "_xlfn.BITXOR" , SC_OPCODE_BITXOR }, - { "_xlfn.BITRSHIFT" , SC_OPCODE_BITRSHIFT }, - { "_xlfn.BITLSHIFT" , SC_OPCODE_BITLSHIFT }, - { "#NULL!" , SC_OPCODE_ERROR_NULL }, - { "#DIV/0!" , SC_OPCODE_ERROR_DIVZERO }, - { "#VALUE!" , SC_OPCODE_ERROR_VALUE }, - { "#REF!" , SC_OPCODE_ERROR_REF }, - { "#NAME?" , SC_OPCODE_ERROR_NAME }, - { "#NUM!" , SC_OPCODE_ERROR_NUM }, - { "#N/A" , SC_OPCODE_ERROR_NA }, + { "IF" , ocIf }, + { "IFERROR" , ocIfError }, + { "_xlfn.IFNA" , ocIfNA }, + { "_xlfn.SINGLE" , ocSingleValue }, + { "_xlfn.ANCHORARRAY" , ocAnchorArray }, + { "CHOOSE" , ocChoose }, + { "(" , ocOpen }, + { ")" , ocClose }, + { "[" , ocTableRefOpen }, + { "]" , ocTableRefClose }, + { "#All" , ocTableRefItemAll }, + { "#Headers" , ocTableRefItemHeaders }, + { "#Data" , ocTableRefItemData }, + { "#Totals" , ocTableRefItemTotals }, + { "#This Row" , ocTableRefItemThisRow }, + { "{" , ocArrayOpen }, + { "}" , ocArrayClose }, + { ";" , ocArrayRowSep }, + { "," , ocArrayColSep }, + { "," , ocSep }, + { "%" , ocPercentSign }, + { "+" , ocAdd }, + { "-" , ocSub }, + { "*" , ocMul }, + { "/" , ocDiv }, + { "&" , ocAmpersand }, + { "^" , ocPow }, + { "=" , ocEqual }, + { "<>" , ocNotEqual }, + { "<" , ocLess }, + { ">" , ocGreater }, + { "<=" , ocLessEqual }, + { ">=" , ocGreaterEqual }, + { "AND" , ocAnd }, + { "OR" , ocOr }, + { "_xlfn.XOR" , ocXor }, + { " " , ocIntersect }, + { "," , ocUnion }, // Excel uses ',' as Union operator + { ":" , ocRange }, + { "NOT" , ocNot }, + { "NEG" , ocNeg }, + { "-" , ocNegSub }, + { "PI" , ocPi }, + { "RAND" , ocRandom }, + { "TRUE" , ocTrue }, + { "FALSE" , ocFalse }, + { "TODAY" , ocGetActDate }, + { "NOW" , ocGetActTime }, + { "NA" , ocNotAvail }, + { "_xlfn.ORG.OPENOFFICE.CURRENT" , ocCurrent }, + { "DEGREES" , ocDeg }, + { "RADIANS" , ocRad }, + { "SIN" , ocSin }, + { "COS" , ocCos }, + { "TAN" , ocTan }, + { "_xlfn.COT" , ocCot }, + { "ASIN" , ocArcSin }, + { "ACOS" , ocArcCos }, + { "ATAN" , ocArcTan }, + { "_xlfn.ACOT" , ocArcCot }, + { "SINH" , ocSinHyp }, + { "COSH" , ocCosHyp }, + { "TANH" , ocTanHyp }, + { "_xlfn.COTH" , ocCotHyp }, + { "ASINH" , ocArcSinHyp }, + { "ACOSH" , ocArcCosHyp }, + { "ATANH" , ocArcTanHyp }, + { "_xlfn.ACOTH" , ocArcCotHyp }, + { "_xlfn.CSC" , ocCosecant }, + { "_xlfn.SEC" , ocSecant }, + { "_xlfn.CSCH" , ocCosecantHyp }, + { "_xlfn.SECH" , ocSecantHyp }, + { "EXP" , ocExp }, + { "LN" , ocLn }, + { "SQRT" , ocSqrt }, + { "FACT" , ocFact }, + { "YEAR" , ocGetYear }, + { "MONTH" , ocGetMonth }, + { "DAY" , ocGetDay }, + { "HOUR" , ocGetHour }, + { "MINUTE" , ocGetMin }, + { "SECOND" , ocGetSec }, + { "SIGN" , ocPlusMinus }, + { "ABS" , ocAbs }, + { "INT" , ocInt }, + { "_xlfn.PHI" , ocPhi }, + { "_xlfn.GAUSS" , ocGauss }, + { "ISBLANK" , ocIsEmpty }, + { "ISTEXT" , ocIsString }, + { "ISNONTEXT" , ocIsNonString }, + { "ISLOGICAL" , ocIsLogical }, + { "TYPE" , ocType }, + { "CELL" , ocCell }, + { "ISREF" , ocIsRef }, + { "ISNUMBER" , ocIsValue }, + { "_xlfn.ISFORMULA" , ocIsFormula }, + { "ISNA" , ocIsNA }, + { "ISERR" , ocIsErr }, + { "ISERROR" , ocIsError }, + { "ISEVEN" , ocIsEven }, + { "ISODD" , ocIsOdd }, + { "N" , ocN }, + { "DATEVALUE" , ocGetDateValue }, + { "TIMEVALUE" , ocGetTimeValue }, + { "CODE" , ocCode }, + { "TRIM" , ocTrim }, + { "UPPER" , ocUpper }, + { "PROPER" , ocProper }, + { "LOWER" , ocLower }, + { "LEN" , ocLen }, + { "T" , ocT }, + { "VALUE" , ocValue }, + { "CLEAN" , ocClean }, + { "CHAR" , ocChar }, + { "JIS" , ocJis }, + { "ASC" , ocAsc }, + { "_xlfn.UNICODE" , ocUnicode }, + { "_xlfn.UNICHAR" , ocUnichar }, + { "LOG10" , ocLog10 }, + { "EVEN" , ocEven }, + { "ODD" , ocOdd }, + { "NORMSDIST" , ocStdNormDist }, + { "_xlfn.NORM.S.DIST" , ocStdNormDist_MS }, + { "FISHER" , ocFisher }, + { "FISHERINV" , ocFisherInv }, + { "NORMSINV" , ocSNormInv }, + { "_xlfn.NORM.S.INV" , ocSNormInv_MS }, + { "GAMMALN" , ocGammaLn }, + { "_xlfn.GAMMALN.PRECISE" , ocGammaLn_MS }, + { "_xlfn.ORG.OPENOFFICE.ERRORTYPE" , ocErrorType }, + { "ERROR.TYPE" , ocErrorType_ODF }, + { "_xlfn.FORMULATEXT" , ocFormula }, + { "ATAN2" , ocArcTan2 }, + { "_xlfn.CEILING.MATH" , ocCeil_Math }, + { "_xlfn.CEILING.MATH" , ocCeil }, + { "CEILING" , ocCeil_MS }, + { "_xlfn.CEILING.PRECISE" , ocCeil_Precise }, + { "ISO.CEILING" , ocCeil_ISO }, + { "FLOOR" , ocFloor_MS }, + { "_xlfn.FLOOR.MATH" , ocFloor_Math }, + { "_xlfn.FLOOR.MATH" , ocFloor }, + { "_xlfn.FLOOR.PRECISE" , ocFloor_Precise }, + { "ROUND" , ocRound }, + { "ROUNDUP" , ocRoundUp }, + { "ROUNDDOWN" , ocRoundDown }, + { "TRUNC" , ocTrunc }, + { "LOG" , ocLog }, + { "POWER" , ocPower }, + { "GCD" , ocGCD }, + { "LCM" , ocLCM }, + { "MOD" , ocMod }, + { "SUMPRODUCT" , ocSumProduct }, + { "SUMSQ" , ocSumSQ }, + { "SUMX2MY2" , ocSumX2MY2 }, + { "SUMX2PY2" , ocSumX2DY2 }, + { "SUMXMY2" , ocSumXMY2 }, + { "DATE" , ocGetDate }, + { "TIME" , ocGetTime }, + { "_xlfn.DAYS" , ocGetDiffDate }, + { "DAYS360" , ocGetDiffDate360 }, + { "DATEDIF" , ocGetDateDif }, + { "MIN" , ocMin }, + { "MINA" , ocMinA }, + { "MAX" , ocMax }, + { "MAXA" , ocMaxA }, + { "SUM" , ocSum }, + { "PRODUCT" , ocProduct }, + { "AVERAGE" , ocAverage }, + { "AVERAGEA" , ocAverageA }, + { "COUNT" , ocCount }, + { "COUNTA" , ocCount2 }, + { "NPV" , ocNPV }, + { "IRR" , ocIRR }, + { "MIRR" , ocMIRR }, + { "ISPMT" , ocISPMT }, + { "VAR" , ocVar }, + { "VARA" , ocVarA }, + { "VARP" , ocVarP }, + { "VARPA" , ocVarPA }, + { "_xlfn.VAR.P" , ocVarP_MS }, + { "_xlfn.VAR.S" , ocVarS }, + { "STDEV" , ocStDev }, + { "STDEVA" , ocStDevA }, + { "STDEVP" , ocStDevP }, + { "STDEVPA" , ocStDevPA }, + { "_xlfn.STDEV.P" , ocStDevP_MS }, + { "_xlfn.STDEV.S" , ocStDevS }, + { "B" , ocB }, + { "NORMDIST" , ocNormDist }, + { "_xlfn.NORM.DIST" , ocNormDist_MS }, + { "EXPONDIST" , ocExpDist }, + { "_xlfn.EXPON.DIST" , ocExpDist_MS }, + { "BINOMDIST" , ocBinomDist }, + { "_xlfn.BINOM.DIST" , ocBinomDist_MS }, + { "POISSON" , ocPoissonDist }, + { "_xlfn.POISSON.DIST" , ocPoissonDist_MS }, + { "COMBIN" , ocCombin }, + { "_xlfn.COMBINA" , ocCombinA }, + { "PERMUT" , ocPermut }, + { "_xlfn.PERMUTATIONA" , ocPermutationA }, + { "PV" , ocPV }, + { "SYD" , ocSYD }, + { "DDB" , ocDDB }, + { "DB" , ocDB }, + { "VDB" , ocVBD }, + { "_xlfn.PDURATION" , ocPDuration }, + { "SLN" , ocSLN }, + { "PMT" , ocPMT }, + { "COLUMNS" , ocColumns }, + { "ROWS" , ocRows }, + { "_xlfn.SHEETS" , ocSheets }, + { "COLUMN" , ocColumn }, + { "ROW" , ocRow }, + { "_xlfn.SHEET" , ocSheet }, + { "_xlfn.RRI" , ocRRI }, + { "FV" , ocFV }, + { "NPER" , ocNper }, + { "RATE" , ocRate }, + { "IPMT" , ocIpmt }, + { "PPMT" , ocPpmt }, + { "CUMIPMT" , ocCumIpmt }, + { "CUMPRINC" , ocCumPrinc }, + { "EFFECT" , ocEffect }, + { "NOMINAL" , ocNominal }, + { "SUBTOTAL" , ocSubTotal }, + { "DSUM" , ocDBSum}, + { "DCOUNT" , ocDBCount }, + { "DCOUNTA" , ocDBCount2 }, + { "DAVERAGE" , ocDBAverage }, + { "DGET" , ocDBGet }, + { "DMAX" , ocDBMax }, + { "DMIN" , ocDBMin }, + { "DPRODUCT" , ocDBProduct }, + { "DSTDEV" , ocDBStdDev }, + { "DSTDEVP" , ocDBStdDevP }, + { "DVAR" , ocDBVar }, + { "DVARP" , ocDBVarP }, + { "INDIRECT" , ocIndirect }, + { "ADDRESS" , ocAddress }, + { "MATCH" , ocMatch }, + { "_xlfn.XMATCH" , ocXMatch }, + { "COUNTBLANK" , ocCountEmptyCells }, + { "COUNTIF" , ocCountIf }, + { "SUMIF" , ocSumIf }, + { "AVERAGEIF" , ocAverageIf }, + { "SUMIFS" , ocSumIfs }, + { "AVERAGEIFS" , ocAverageIfs }, + { "COUNTIFS" , ocCountIfs }, + { "LOOKUP" , ocLookup }, + { "VLOOKUP" , ocVLookup }, + { "_xlfn.XLOOKUP" , ocXLookup }, + { "HLOOKUP" , ocHLookup }, + { "_xlfn._xlws.FILTER" , ocFilter }, + { "_xlfn._xlws.SORT" , ocSort }, + { "_xlfn.SORTBY" , ocSortBy }, + { "_xlfn.CHOOSECOLS" , ocChooseCols }, + { "_xlfn.CHOOSEROWS" , ocChooseRows }, + { "_xlfn.DROP" , ocDrop }, + { "_xlfn.EXPAND" , ocExpand }, + { "_xlfn.HSTACK" , ocHStack }, + { "_xlfn.VSTACK" , ocVStack }, + { "_xlfn.TAKE" , ocTake }, + { "_xlfn.TEXTAFTER" , ocTextAfter }, + { "_xlfn.TEXTBEFORE" , ocTextBefore }, + { "_xlfn.TEXTSPLIT" , ocTextSplit }, + { "_xlfn.TOCOL" , ocToCol }, + { "_xlfn.TOROW" , ocToRow }, + { "_xlfn.UNIQUE" , ocUnique }, + { "_xlfn.LET" , ocLet }, + { "_xlfn.WRAPCOLS" , ocWrapCols }, + { "_xlfn.WRAPROWS" , ocWrapRows }, + { "_xlfn.LAMBDA" , ocLambda }, + { "_xlfn.ISOMITTED" , ocIsOmitted }, + { "_xlfn.BYCOL" , ocByCol }, + { "_xlfn.BYROW" , ocByRow }, + { "_xlfn.MAKEARRAY" , ocMakeArray }, + { "_xlfn.MAP" , ocMap }, + { "_xlfn.REDUCE" , ocReduce }, + { "_xlfn.SCAN" , ocScan }, + { "_xlfn.ARRAYTOTEXT" , ocArrayToText }, + { "_xlpm." , ocStringName }, + { "_xlop." , ocStringName }, + { "_xlfn.ORG.OPENOFFICE.MULTIRANGE" , ocMultiArea }, // legacy for range list (union) + { "OFFSET" , ocOffset }, + { "INDEX" , ocIndex }, + { "AREAS" , ocAreas }, + { "DOLLAR" , ocCurrency }, + { "REPLACE" , ocReplace }, + { "FIXED" , ocFixed }, + { "FIND" , ocFind }, + { "EXACT" , ocExact }, + { "LEFT" , ocLeft }, + { "RIGHT" , ocRight }, + { "SEARCH" , ocSearch }, + { "MID" , ocMid }, + { "LENB" , ocLenB }, + { "RIGHTB" , ocRightB }, + { "LEFTB" , ocLeftB }, + { "REPLACEB" , ocReplaceB }, + { "FINDB" , ocFindB }, + { "SEARCHB" , ocSearchB }, + { "MIDB" , ocMidB }, + { "TEXT" , ocText }, + { "SUBSTITUTE" , ocSubstitute }, + { "REPT" , ocRept }, + { "CONCATENATE" , ocConcat }, + { "_xlfn.CONCAT" , ocConcat_MS }, + { "_xlfn.TEXTJOIN" , ocTextJoin_MS }, + { "_xlfn.IFS" , ocIfs_MS }, + { "_xlfn.SWITCH" , ocSwitch_MS }, + { "_xlfn.MINIFS" , ocMinIfs_MS }, + { "_xlfn.MAXIFS" , ocMaxIfs_MS }, + { "MVALUE" , ocMatValue }, + { "MDETERM" , ocMatDet }, + { "MINVERSE" , ocMatInv }, + { "MMULT" , ocMatMult }, + { "_xlfn.SEQUENCE" , ocMatSequence }, + { "TRANSPOSE" , ocMatTrans }, + { "_xlfn.MUNIT" , ocMatrixUnit }, + { "_xlfn.ORG.OPENOFFICE.GOALSEEK" , ocBackSolver }, + { "HYPGEOMDIST" , ocHypGeomDist }, + { "_xlfn.HYPGEOM.DIST" , ocHypGeomDist_MS }, + { "LOGNORMDIST" , ocLogNormDist }, + { "_xlfn.LOGNORM.DIST" , ocLogNormDist_MS }, + { "TDIST" , ocTDist }, + { "_xlfn.T.DIST.2T" , ocTDist_2T }, + { "_xlfn.T.DIST" , ocTDist_MS }, + { "_xlfn.T.DIST.RT" , ocTDist_RT }, + { "FDIST" , ocFDist }, + { "_xlfn.F.DIST" , ocFDist_LT }, + { "_xlfn.F.DIST.RT" , ocFDist_RT }, + { "CHIDIST" , ocChiDist }, + { "_xlfn.CHISQ.DIST.RT" , ocChiDist_MS }, + { "WEIBULL" , ocWeibull }, + { "_xlfn.WEIBULL.DIST" , ocWeibull_MS }, + { "NEGBINOMDIST" , ocNegBinomVert }, + { "_xlfn.NEGBINOM.DIST" , ocNegBinomDist_MS }, + { "CRITBINOM" , ocCritBinom }, + { "_xlfn.BINOM.INV" , ocBinomInv }, + { "KURT" , ocKurt }, + { "HARMEAN" , ocHarMean }, + { "GEOMEAN" , ocGeoMean }, + { "STANDARDIZE" , ocStandard }, + { "AVEDEV" , ocAveDev }, + { "SKEW" , ocSkew }, + { "_xlfn.SKEW.P" , ocSkewp }, + { "DEVSQ" , ocDevSq }, + { "MEDIAN" , ocMedian }, + { "MODE" , ocModalValue }, + { "_xlfn.MODE.SNGL" , ocModalValue_MS }, + { "_xlfn.MODE.MULT" , ocModalValue_Multi }, + { "ZTEST" , ocZTest }, + { "_xlfn.Z.TEST" , ocZTest_MS }, + { "_xlfn.AGGREGATE" , ocAggregate }, + { "TTEST" , ocTTest }, + { "_xlfn.T.TEST" , ocTTest_MS }, + { "RANK" , ocRank }, + { "PERCENTILE" , ocPercentile }, + { "PERCENTRANK" , ocPercentrank }, + { "_xlfn.PERCENTILE.INC" , ocPercentile_Inc }, + { "_xlfn.PERCENTRANK.INC" , ocPercentrank_Inc }, + { "_xlfn.QUARTILE.INC" , ocQuartile_Inc }, + { "_xlfn.RANK.EQ" , ocRank_Eq }, + { "_xlfn.PERCENTILE.EXC" , ocPercentile_Exc }, + { "_xlfn.PERCENTRANK.EXC" , ocPercentrank_Exc }, + { "_xlfn.QUARTILE.EXC" , ocQuartile_Exc }, + { "_xlfn.RANK.AVG" , ocRank_Avg }, + { "LARGE" , ocLarge }, + { "SMALL" , ocSmall }, + { "FREQUENCY" , ocFrequency }, + { "QUARTILE" , ocQuartile }, + { "NORMINV" , ocNormInv }, + { "_xlfn.NORM.INV" , ocNormInv_MS }, + { "CONFIDENCE" , ocConfidence }, + { "_xlfn.CONFIDENCE.NORM" , ocConfidence_N }, + { "_xlfn.CONFIDENCE.T" , ocConfidence_T }, + { "FTEST" , ocFTest }, + { "_xlfn.F.TEST" , ocFTest_MS }, + { "TRIMMEAN" , ocTrimMean }, + { "PROB" , ocProb }, + { "CORREL" , ocCorrel }, + { "COVAR" , ocCovar }, + { "_xlfn.COVARIANCE.P" , ocCovarianceP }, + { "_xlfn.COVARIANCE.S" , ocCovarianceS }, + { "PEARSON" , ocPearson }, + { "RSQ" , ocRSQ }, + { "STEYX" , ocSTEYX }, + { "SLOPE" , ocSlope }, + { "INTERCEPT" , ocIntercept }, + { "TREND" , ocTrend }, + { "GROWTH" , ocGrowth }, + { "LINEST" , ocLinest }, + { "LOGEST" , ocLogest }, + { "FORECAST" , ocForecast }, + { "_xlfn.FORECAST.ETS" , ocForecast_ETS_ADD }, + { "_xlfn.FORECAST.ETS.SEASONALITY" , ocForecast_ETS_SEA }, + { "_xlfn.ORG.LIBREOFFICE.FORECAST.ETS.MULT" , ocForecast_ETS_MUL }, + { "_xlfn.FORECAST.ETS.CONFINT" , ocForecast_ETS_PIA }, + { "_xlfn.ORG.LIBREOFFICE.FORECAST.ETS.PI.MULT" , ocForecast_ETS_PIM }, + { "_xlfn.FORECAST.ETS.STAT" , ocForecast_ETS_STA }, + { "_xlfn.ORG.LIBREOFFICE.FORECAST.ETS.STAT.MULT" , ocForecast_ETS_STM }, + { "_xlfn.FORECAST.LINEAR" , ocForecast_LIN }, + { "CHIINV" , ocChiInv }, + { "_xlfn.CHISQ.INV.RT" , ocChiInv_MS }, + { "GAMMADIST" , ocGammaDist }, + { "_xlfn.GAMMA.DIST" , ocGammaDist_MS }, + { "GAMMAINV" , ocGammaInv }, + { "_xlfn.GAMMA.INV" , ocGammaInv_MS }, + { "TINV" , ocTInv }, + { "_xlfn.T.INV.2T" , ocTInv_2T }, + { "_xlfn.T.INV" , ocTInv_MS }, + { "FINV" , ocFInv }, + { "_xlfn.F.INV" , ocFInv_LT }, + { "_xlfn.F.INV.RT" , ocFInv_RT }, + { "CHITEST" , ocChiTest }, + { "_xlfn.CHISQ.TEST" , ocChiTest_MS }, + { "LOGINV" , ocLogInv }, + { "_xlfn.LOGNORM.INV" , ocLogInv_MS }, + { "TABLE" , ocTableOp }, + { "BETADIST" , ocBetaDist }, + { "BETAINV" , ocBetaInv }, + { "_xlfn.BETA.DIST" , ocBetaDist_MS }, + { "_xlfn.BETA.INV" , ocBetaInv_MS }, + { "WEEKNUM" , ocWeek }, + { "_xlfn.ISOWEEKNUM" , ocIsoWeeknum }, + { "_xlfn.ORG.LIBREOFFICE.WEEKNUM_OOO" , ocWeeknumOOo }, + { "_xlfn.ORG.OPENOFFICE.EASTERSUNDAY" , ocEasterSunday }, + { "WEEKDAY" , ocGetDayOfWeek }, + { "NETWORKDAYS" , ocNetWorkdays }, + { "NETWORKDAYS.INTL" , ocNetWorkdays_MS }, + { "WORKDAY.INTL" , ocWorkday_MS }, + { "#NAME!" , ocNoName }, + { "_xlfn.ORG.OPENOFFICE.STYLE" , ocStyle }, + { "DDE" , ocDde }, + { "_xlfn.BASE" , ocBase }, + { "_xlfn.DECIMAL" , ocDecimal }, + { "_xlfn.ORG.OPENOFFICE.CONVERT" , ocConvertOOo }, + { "ROMAN" , ocRoman }, + { "_xlfn.ARABIC" , ocArabic }, + { "HYPERLINK" , ocHyperLink }, + { "INFO" , ocInfo }, + { "_xlfn.BAHTTEXT" , ocBahtText }, + { "GETPIVOTDATA" , ocGetPivotData }, + { "EUROCONVERT" , ocEuroConvert }, + { "_xlfn.NUMBERVALUE" , ocNumberValue }, + { "_xlfn.GAMMA" , ocGamma }, + { "CHISQDIST" , ocChiSqDist }, + { "_xlfn.CHISQ.DIST" , ocChiSqDist_MS }, + { "CHISQINV" , ocChiSqInv }, + { "_xlfn.CHISQ.INV" , ocChiSqInv_MS }, + { "_xlfn.BITAND" , ocBitAnd }, + { "_xlfn.BITOR" , ocBitOr }, + { "_xlfn.BITXOR" , ocBitXor }, + { "_xlfn.BITRSHIFT" , ocBitRshift }, + { "_xlfn.BITLSHIFT" , ocBitLshift }, + { "#NULL!" , ocErrNull }, + { "#DIV/0!" , ocErrDivZero }, + { "#VALUE!" , ocErrValue }, + { "#REF!" , ocErrRef }, + { "#NAME?" , ocErrName }, + { "#NUM!" , ocErrNum }, + { "#N/A" , ocErrNA }, + { "#SPILL!" , ocErrSpill }, /* END defined ERROR.TYPE() values. */ - { "_xlfn.FILTERXML" , SC_OPCODE_FILTERXML }, - { "_xlfn.WEBSERVICE" , SC_OPCODE_WEBSERVICE }, - { "_xlfn.ORG.LIBREOFFICE.COLOR" , SC_OPCODE_COLOR }, - { "_xlfn.ERF.PRECISE" , SC_OPCODE_ERF_MS }, - { "_xlfn.ERFC.PRECISE" , SC_OPCODE_ERFC_MS }, - { "_xlfn.ENCODEURL" , SC_OPCODE_ENCODEURL }, - { "_xlfn.ORG.LIBREOFFICE.RAWSUBTRACT" , SC_OPCODE_RAWSUBTRACT }, - { "_xlfn.ORG.LIBREOFFICE.ROUNDSIG" , SC_OPCODE_ROUNDSIG }, - { "_xlfn.ORG.LIBREOFFICE.REGEX" , SC_OPCODE_REGEX }, - { "_xlfn.ORG.LIBREOFFICE.FOURIER", SC_OPCODE_FOURIER }, - { "_xlfn.ORG.LIBREOFFICE.RAND.NV" , SC_OPCODE_RANDOM_NV }, - { "_xlfn.ORG.LIBREOFFICE.RANDBETWEEN.NV" , SC_OPCODE_RANDBETWEEN_NV }, - { "_xlfn.RANDARRAY" , SC_OPCODE_RANDARRAY }, - { "#REF!", SC_OPCODE_STOP }, + { "_xlfn.FILTERXML" , ocFilterXML }, + { "_xlfn.WEBSERVICE" , ocWebservice }, + { "_xlfn.ORG.LIBREOFFICE.COLOR" , ocColor }, + { "_xlfn.ERF.PRECISE" , ocErf_MS }, + { "_xlfn.ERFC.PRECISE" , ocErfc_MS }, + { "_xlfn.ENCODEURL" , ocEncodeURL }, + { "_xlfn.ORG.LIBREOFFICE.RAWSUBTRACT" , ocRawSubtract }, + { "_xlfn.ORG.LIBREOFFICE.ROUNDSIG" , ocRoundSig }, + { "_xlfn.ORG.LIBREOFFICE.REGEX" , ocRegex }, + { "_xlfn.ORG.LIBREOFFICE.FOURIER", ocFourier }, + { "_xlfn.ORG.LIBREOFFICE.RAND.NV" , ocRandomNV }, + { "_xlfn.ORG.LIBREOFFICE.RANDBETWEEN.NV" , ocRandbetweenNV }, + { "_xlfn.RANDARRAY" , ocRandArray }, + { "_xludf.", ocUDExternal }, { nullptr, -1 } }; @@ -974,470 +1000,482 @@ const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML[] = // ScCompiler::IsOpCode() in the else if (mxSymbols->isPODF()) block. const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_PODF[] = { - { "IF" , SC_OPCODE_IF }, - { "IFERROR" , SC_OPCODE_IF_ERROR }, - { "IFNA" , SC_OPCODE_IF_NA }, - { "CHOOSE" , SC_OPCODE_CHOOSE }, - { "(" , SC_OPCODE_OPEN }, - { ")" , SC_OPCODE_CLOSE }, - { "[" , SC_OPCODE_TABLE_REF_OPEN }, - { "]" , SC_OPCODE_TABLE_REF_CLOSE }, - { "#All" , SC_OPCODE_TABLE_REF_ITEM_ALL }, - { "#Headers" , SC_OPCODE_TABLE_REF_ITEM_HEADERS }, - { "#Data" , SC_OPCODE_TABLE_REF_ITEM_DATA }, - { "#Totals" , SC_OPCODE_TABLE_REF_ITEM_TOTALS }, - { "#This Row" , SC_OPCODE_TABLE_REF_ITEM_THIS_ROW }, - { "{" , SC_OPCODE_ARRAY_OPEN }, - { "}" , SC_OPCODE_ARRAY_CLOSE }, - { "|" , SC_OPCODE_ARRAY_ROW_SEP }, - { ";" , SC_OPCODE_ARRAY_COL_SEP }, - { ";" , SC_OPCODE_SEP }, - { "%" , SC_OPCODE_PERCENT_SIGN }, - { "+" , SC_OPCODE_ADD }, - { "-" , SC_OPCODE_SUB }, - { "*" , SC_OPCODE_MUL }, - { "/" , SC_OPCODE_DIV }, - { "&" , SC_OPCODE_AMPERSAND }, - { "^" , SC_OPCODE_POW }, - { "=" , SC_OPCODE_EQUAL }, - { "<>" , SC_OPCODE_NOT_EQUAL }, - { "<" , SC_OPCODE_LESS }, - { ">" , SC_OPCODE_GREATER }, - { "<=" , SC_OPCODE_LESS_EQUAL }, - { ">=" , SC_OPCODE_GREATER_EQUAL }, - { "AND" , SC_OPCODE_AND }, - { "OR" , SC_OPCODE_OR }, - { "XOR" , SC_OPCODE_XOR }, - { "!" , SC_OPCODE_INTERSECT }, - { "~" , SC_OPCODE_UNION }, - { ":" , SC_OPCODE_RANGE }, - { "NOT" , SC_OPCODE_NOT }, - { "NEG" , SC_OPCODE_NEG }, - { "-" , SC_OPCODE_NEG_SUB }, - { "PI" , SC_OPCODE_PI }, - { "RAND" , SC_OPCODE_RANDOM }, - { "TRUE" , SC_OPCODE_TRUE }, - { "FALSE" , SC_OPCODE_FALSE }, - { "TODAY" , SC_OPCODE_GET_ACT_DATE }, - { "NOW" , SC_OPCODE_GET_ACT_TIME }, - { "NA" , SC_OPCODE_NO_VALUE }, - { "CURRENT" , SC_OPCODE_CURRENT }, - { "DEGREES" , SC_OPCODE_DEG }, - { "RADIANS" , SC_OPCODE_RAD }, - { "SIN" , SC_OPCODE_SIN }, - { "COS" , SC_OPCODE_COS }, - { "TAN" , SC_OPCODE_TAN }, - { "COT" , SC_OPCODE_COT }, - { "ASIN" , SC_OPCODE_ARC_SIN }, - { "ACOS" , SC_OPCODE_ARC_COS }, - { "ATAN" , SC_OPCODE_ARC_TAN }, - { "ACOT" , SC_OPCODE_ARC_COT }, - { "SINH" , SC_OPCODE_SIN_HYP }, - { "COSH" , SC_OPCODE_COS_HYP }, - { "TANH" , SC_OPCODE_TAN_HYP }, - { "COTH" , SC_OPCODE_COT_HYP }, - { "ASINH" , SC_OPCODE_ARC_SIN_HYP }, - { "ACOSH" , SC_OPCODE_ARC_COS_HYP }, - { "ATANH" , SC_OPCODE_ARC_TAN_HYP }, - { "ACOTH" , SC_OPCODE_ARC_COT_HYP }, - { "CSC" , SC_OPCODE_COSECANT }, - { "SEC" , SC_OPCODE_SECANT }, - { "CSCH" , SC_OPCODE_COSECANT_HYP }, - { "SECH" , SC_OPCODE_SECANT_HYP }, - { "EXP" , SC_OPCODE_EXP }, - { "LN" , SC_OPCODE_LN }, - { "SQRT" , SC_OPCODE_SQRT }, - { "FACT" , SC_OPCODE_FACT }, - { "YEAR" , SC_OPCODE_GET_YEAR }, - { "MONTH" , SC_OPCODE_GET_MONTH }, - { "DAY" , SC_OPCODE_GET_DAY }, - { "HOUR" , SC_OPCODE_GET_HOUR }, - { "MINUTE" , SC_OPCODE_GET_MIN }, - { "SECOND" , SC_OPCODE_GET_SEC }, - { "SIGN" , SC_OPCODE_PLUS_MINUS }, - { "ABS" , SC_OPCODE_ABS }, - { "INT" , SC_OPCODE_INT }, - { "PHI" , SC_OPCODE_PHI }, - { "GAUSS" , SC_OPCODE_GAUSS }, - { "ISBLANK" , SC_OPCODE_IS_EMPTY }, - { "ISTEXT" , SC_OPCODE_IS_STRING }, - { "ISNONTEXT" , SC_OPCODE_IS_NON_STRING }, - { "ISLOGICAL" , SC_OPCODE_IS_LOGICAL }, - { "TYPE" , SC_OPCODE_TYPE }, - { "CELL" , SC_OPCODE_CELL }, - { "ISREF" , SC_OPCODE_IS_REF }, - { "ISNUMBER" , SC_OPCODE_IS_VALUE }, - { "ISFORMULA" , SC_OPCODE_IS_FORMULA }, - { "ISNA" , SC_OPCODE_IS_NV }, - { "ISERR" , SC_OPCODE_IS_ERR }, - { "ISERROR" , SC_OPCODE_IS_ERROR }, - { "ISEVEN" , SC_OPCODE_IS_EVEN }, - { "ISODD" , SC_OPCODE_IS_ODD }, - { "N" , SC_OPCODE_N }, - { "DATEVALUE" , SC_OPCODE_GET_DATE_VALUE }, - { "TIMEVALUE" , SC_OPCODE_GET_TIME_VALUE }, - { "CODE" , SC_OPCODE_CODE }, - { "TRIM" , SC_OPCODE_TRIM }, - { "UPPER" , SC_OPCODE_UPPER }, - { "PROPER" , SC_OPCODE_PROPER }, - { "LOWER" , SC_OPCODE_LOWER }, - { "LEN" , SC_OPCODE_LEN }, - { "T" , SC_OPCODE_T }, - { "VALUE" , SC_OPCODE_VALUE }, - { "CLEAN" , SC_OPCODE_CLEAN }, - { "CHAR" , SC_OPCODE_CHAR }, - { "JIS" , SC_OPCODE_JIS }, - { "ASC" , SC_OPCODE_ASC }, - { "UNICODE" , SC_OPCODE_UNICODE }, - { "UNICHAR" , SC_OPCODE_UNICHAR }, - { "LOG10" , SC_OPCODE_LOG10 }, - { "EVEN" , SC_OPCODE_EVEN }, - { "ODD" , SC_OPCODE_ODD }, - { "NORMSDIST" , SC_OPCODE_STD_NORM_DIST }, - { "NORM.S.DIST" , SC_OPCODE_STD_NORM_DIST_MS }, - { "FISHER" , SC_OPCODE_FISHER }, - { "FISHERINV" , SC_OPCODE_FISHER_INV }, - { "NORMSINV" , SC_OPCODE_S_NORM_INV }, - { "NORM.S.INV" , SC_OPCODE_S_NORM_INV_MS }, - { "GAMMALN" , SC_OPCODE_GAMMA_LN }, - { "GAMMALN.PRECISE" , SC_OPCODE_GAMMA_LN_MS }, - { "ERRORTYPE" , SC_OPCODE_ERROR_TYPE }, - { "ERROR.TYPE" , SC_OPCODE_ERROR_TYPE_ODF }, - { "FORMULA" , SC_OPCODE_FORMULA }, - { "ATAN2" , SC_OPCODE_ARC_TAN_2 }, - { "CEILING.MATH" , SC_OPCODE_CEIL_MATH }, - { "CEILING" , SC_OPCODE_CEIL }, - { "CEILING.XCL" , SC_OPCODE_CEIL_MS }, - { "CEILING.PRECISE" , SC_OPCODE_CEIL_PRECISE }, - { "ISO.CEILING" , SC_OPCODE_CEIL_ISO }, - { "FLOOR" , SC_OPCODE_FLOOR }, - { "FLOOR.XCL" , SC_OPCODE_FLOOR_MS }, - { "FLOOR.MATH" , SC_OPCODE_FLOOR_MATH }, - { "FLOOR.PRECISE" , SC_OPCODE_FLOOR_PRECISE }, - { "ROUND" , SC_OPCODE_ROUND }, - { "ROUNDUP" , SC_OPCODE_ROUND_UP }, - { "ROUNDDOWN" , SC_OPCODE_ROUND_DOWN }, - { "TRUNC" , SC_OPCODE_TRUNC }, - { "LOG" , SC_OPCODE_LOG }, - { "POWER" , SC_OPCODE_POWER }, - { "GCD" , SC_OPCODE_GCD }, - { "LCM" , SC_OPCODE_LCM }, - { "MOD" , SC_OPCODE_MOD }, - { "SUMPRODUCT" , SC_OPCODE_SUM_PRODUCT }, - { "SUMSQ" , SC_OPCODE_SUM_SQ }, - { "SUMX2MY2" , SC_OPCODE_SUM_X2MY2 }, - { "SUMX2PY2" , SC_OPCODE_SUM_X2DY2 }, - { "SUMXMY2" , SC_OPCODE_SUM_XMY2 }, - { "DATE" , SC_OPCODE_GET_DATE }, - { "TIME" , SC_OPCODE_GET_TIME }, - { "DAYS" , SC_OPCODE_GET_DIFF_DATE }, - { "DAYS360" , SC_OPCODE_GET_DIFF_DATE_360 }, - { "DATEDIF" , SC_OPCODE_GET_DATEDIF }, - { "MIN" , SC_OPCODE_MIN }, - { "MINA" , SC_OPCODE_MIN_A }, - { "MAX" , SC_OPCODE_MAX }, - { "MAXA" , SC_OPCODE_MAX_A }, - { "SUM" , SC_OPCODE_SUM }, - { "PRODUCT" , SC_OPCODE_PRODUCT }, - { "AVERAGE" , SC_OPCODE_AVERAGE }, - { "AVERAGEA" , SC_OPCODE_AVERAGE_A }, - { "COUNT" , SC_OPCODE_COUNT }, - { "COUNTA" , SC_OPCODE_COUNT_2 }, - { "NPV" , SC_OPCODE_NPV }, - { "IRR" , SC_OPCODE_IRR }, - { "MIRR" , SC_OPCODE_MIRR }, - { "ISPMT" , SC_OPCODE_ISPMT }, - { "VAR" , SC_OPCODE_VAR }, - { "VARA" , SC_OPCODE_VAR_A }, - { "VARP" , SC_OPCODE_VAR_P }, - { "VARPA" , SC_OPCODE_VAR_P_A }, - { "VAR.P" , SC_OPCODE_VAR_P_MS }, - { "VAR.S" , SC_OPCODE_VAR_S }, - { "STDEV" , SC_OPCODE_ST_DEV }, - { "STDEVA" , SC_OPCODE_ST_DEV_A }, - { "STDEVP" , SC_OPCODE_ST_DEV_P }, - { "STDEVPA" , SC_OPCODE_ST_DEV_P_A }, - { "STDEV.P" , SC_OPCODE_ST_DEV_P_MS }, - { "STDEV.S" , SC_OPCODE_ST_DEV_S }, - { "B" , SC_OPCODE_B }, - { "NORMDIST" , SC_OPCODE_NORM_DIST }, - { "NORM.DIST" , SC_OPCODE_NORM_DIST_MS }, - { "EXPONDIST" , SC_OPCODE_EXP_DIST }, - { "EXPON.DIST" , SC_OPCODE_EXP_DIST_MS }, - { "BINOMDIST" , SC_OPCODE_BINOM_DIST }, - { "BINOM.DIST" , SC_OPCODE_BINOM_DIST_MS }, - { "POISSON" , SC_OPCODE_POISSON_DIST }, - { "POISSON.DIST" , SC_OPCODE_POISSON_DIST_MS }, - { "COMBIN" , SC_OPCODE_COMBIN }, - { "COMBINA" , SC_OPCODE_COMBIN_A }, - { "PERMUT" , SC_OPCODE_PERMUT }, - { "PERMUTATIONA" , SC_OPCODE_PERMUTATION_A }, - { "PV" , SC_OPCODE_PV }, - { "SYD" , SC_OPCODE_SYD }, - { "DDB" , SC_OPCODE_DDB }, - { "DB" , SC_OPCODE_DB }, - { "VDB" , SC_OPCODE_VBD }, - { "DURATION" , SC_OPCODE_PDURATION }, // wrong but ODF1.1, keep it. - { "SLN" , SC_OPCODE_SLN }, - { "PMT" , SC_OPCODE_PMT }, - { "COLUMNS" , SC_OPCODE_COLUMNS }, - { "ROWS" , SC_OPCODE_ROWS }, - { "SHEETS" , SC_OPCODE_SHEETS }, - { "COLUMN" , SC_OPCODE_COLUMN }, - { "ROW" , SC_OPCODE_ROW }, - { "SHEET" , SC_OPCODE_SHEET }, - { "ZGZ" , SC_OPCODE_RRI }, - { "FV" , SC_OPCODE_FV }, - { "NPER" , SC_OPCODE_NPER }, - { "RATE" , SC_OPCODE_RATE }, - { "IPMT" , SC_OPCODE_IPMT }, - { "PPMT" , SC_OPCODE_PPMT }, - { "CUMIPMT" , SC_OPCODE_CUM_IPMT }, - { "CUMPRINC" , SC_OPCODE_CUM_PRINC }, - { "EFFECTIVE" , SC_OPCODE_EFFECT }, - { "NOMINAL" , SC_OPCODE_NOMINAL }, - { "SUBTOTAL" , SC_OPCODE_SUB_TOTAL }, - { "DSUM" , SC_OPCODE_DB_SUM }, - { "DCOUNT" , SC_OPCODE_DB_COUNT }, - { "DCOUNTA" , SC_OPCODE_DB_COUNT_2 }, - { "DAVERAGE" , SC_OPCODE_DB_AVERAGE }, - { "DGET" , SC_OPCODE_DB_GET }, - { "DMAX" , SC_OPCODE_DB_MAX }, - { "DMIN" , SC_OPCODE_DB_MIN }, - { "DPRODUCT" , SC_OPCODE_DB_PRODUCT }, - { "DSTDEV" , SC_OPCODE_DB_STD_DEV }, - { "DSTDEVP" , SC_OPCODE_DB_STD_DEV_P }, - { "DVAR" , SC_OPCODE_DB_VAR }, - { "DVARP" , SC_OPCODE_DB_VAR_P }, - { "INDIRECT" , SC_OPCODE_INDIRECT }, - { "ADDRESS" , SC_OPCODE_ADDRESS }, - { "MATCH" , SC_OPCODE_MATCH }, - { "XMATCH" , SC_OPCODE_X_MATCH }, - { "COUNTBLANK" , SC_OPCODE_COUNT_EMPTY_CELLS }, - { "COUNTIF" , SC_OPCODE_COUNT_IF }, - { "SUMIF" , SC_OPCODE_SUM_IF }, - { "AVERAGEIF" , SC_OPCODE_AVERAGE_IF }, - { "SUMIFS" , SC_OPCODE_SUM_IFS }, - { "AVERAGEIFS" , SC_OPCODE_AVERAGE_IFS }, - { "COUNTIFS" , SC_OPCODE_COUNT_IFS }, - { "LOOKUP" , SC_OPCODE_LOOKUP }, - { "VLOOKUP" , SC_OPCODE_V_LOOKUP }, - { "XLOOKUP" , SC_OPCODE_X_LOOKUP }, - { "HLOOKUP" , SC_OPCODE_H_LOOKUP }, - { "FILTER" , SC_OPCODE_FILTER }, - { "SORT" , SC_OPCODE_SORT }, - { "SORTBY" , SC_OPCODE_SORTBY }, - { "CHOOSECOLS" , SC_OPCODE_CHOOSECOLS }, - { "CHOOSEROWS" , SC_OPCODE_CHOOSEROWS }, - { "DROP" , SC_OPCODE_DROP }, - { "EXPAND" , SC_OPCODE_EXPAND }, - { "HSTACK" , SC_OPCODE_HSTACK }, - { "VSTACK" , SC_OPCODE_VSTACK }, - { "TAKE" , SC_OPCODE_TAKE }, - { "TEXTAFTER" , SC_OPCODE_TEXTAFTER }, - { "TEXTBEFORE" , SC_OPCODE_TEXTBEFORE }, - { "TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, - { "TOCOL" , SC_OPCODE_TOCOL }, - { "TOROW" , SC_OPCODE_TOROW }, - { "UNIQUE" , SC_OPCODE_UNIQUE }, - { "LET" , SC_OPCODE_LET }, - { "WRAPCOLS" , SC_OPCODE_WRAPCOLS }, - { "WRAPROWS" , SC_OPCODE_WRAPROWS }, - { "MULTIRANGE" , SC_OPCODE_MULTI_AREA }, // legacy for range list (union) - { "OFFSET" , SC_OPCODE_OFFSET }, - { "INDEX" , SC_OPCODE_INDEX }, - { "AREAS" , SC_OPCODE_AREAS }, - { "DOLLAR" , SC_OPCODE_CURRENCY }, - { "REPLACE" , SC_OPCODE_REPLACE }, - { "FIXED" , SC_OPCODE_FIXED }, - { "FIND" , SC_OPCODE_FIND }, - { "EXACT" , SC_OPCODE_EXACT }, - { "LEFT" , SC_OPCODE_LEFT }, - { "RIGHT" , SC_OPCODE_RIGHT }, - { "SEARCH" , SC_OPCODE_SEARCH }, - { "MID" , SC_OPCODE_MID }, - { "LENB" , SC_OPCODE_LENB }, - { "RIGHTB" , SC_OPCODE_RIGHTB }, - { "LEFTB" , SC_OPCODE_LEFTB }, - { "REPLACEB" , SC_OPCODE_REPLACEB }, - { "FINDB" , SC_OPCODE_FINDB }, - { "SEARCHB" , SC_OPCODE_SEARCHB }, - { "MIDB" , SC_OPCODE_MIDB }, - { "TEXT" , SC_OPCODE_TEXT }, - { "SUBSTITUTE" , SC_OPCODE_SUBSTITUTE }, - { "REPT" , SC_OPCODE_REPT }, - { "CONCATENATE" , SC_OPCODE_CONCAT }, - { "CONCAT" , SC_OPCODE_CONCAT_MS }, - { "TEXTJOIN" , SC_OPCODE_TEXTJOIN_MS }, - { "IFS" , SC_OPCODE_IFS_MS }, - { "SWITCH" , SC_OPCODE_SWITCH_MS }, - { "MINIFS" , SC_OPCODE_MINIFS_MS }, - { "MAXIFS" , SC_OPCODE_MAXIFS_MS }, - { "MVALUE" , SC_OPCODE_MAT_VALUE }, - { "MDETERM" , SC_OPCODE_MAT_DET }, - { "MINVERSE" , SC_OPCODE_MAT_INV }, - { "MMULT" , SC_OPCODE_MAT_MULT }, - { "SEQUENCE" , SC_OPCODE_MAT_SEQUENCE }, - { "TRANSPOSE" , SC_OPCODE_MAT_TRANS }, - { "MUNIT" , SC_OPCODE_MATRIX_UNIT }, - { "GOALSEEK" , SC_OPCODE_BACK_SOLVER }, - { "HYPGEOMDIST" , SC_OPCODE_HYP_GEOM_DIST }, - { "HYPGEOM.DIST" , SC_OPCODE_HYP_GEOM_DIST_MS }, - { "LOGNORMDIST" , SC_OPCODE_LOG_NORM_DIST }, - { "LOGNORM.DIST" , SC_OPCODE_LOG_NORM_DIST_MS }, - { "TDIST" , SC_OPCODE_T_DIST }, - { "T.DIST.2T" , SC_OPCODE_T_DIST_2T }, - { "T.DIST" , SC_OPCODE_T_DIST_MS }, - { "T.DIST.RT" , SC_OPCODE_T_DIST_RT }, - { "FDIST" , SC_OPCODE_F_DIST }, - { "F.DIST" , SC_OPCODE_F_DIST_LT }, - { "F.DIST.RT" , SC_OPCODE_F_DIST_RT }, - { "CHIDIST" , SC_OPCODE_CHI_DIST }, - { "CHISQ.DIST.RT" , SC_OPCODE_CHI_DIST_MS }, - { "WEIBULL" , SC_OPCODE_WEIBULL }, - { "WEIBULL.DIST" , SC_OPCODE_WEIBULL_MS }, - { "NEGBINOMDIST" , SC_OPCODE_NEG_BINOM_VERT }, - { "NEGBINOM.DIST" , SC_OPCODE_NEG_BINOM_DIST_MS }, - { "CRITBINOM" , SC_OPCODE_CRIT_BINOM }, - { "BINOM.INV" , SC_OPCODE_BINOM_INV }, - { "KURT" , SC_OPCODE_KURT }, - { "HARMEAN" , SC_OPCODE_HAR_MEAN }, - { "GEOMEAN" , SC_OPCODE_GEO_MEAN }, - { "STANDARDIZE" , SC_OPCODE_STANDARD }, - { "AVEDEV" , SC_OPCODE_AVE_DEV }, - { "SKEW" , SC_OPCODE_SKEW }, - { "SKEWP" , SC_OPCODE_SKEWP }, - { "DEVSQ" , SC_OPCODE_DEV_SQ }, - { "MEDIAN" , SC_OPCODE_MEDIAN }, - { "MODE" , SC_OPCODE_MODAL_VALUE }, - { "MODE.SNGL" , SC_OPCODE_MODAL_VALUE_MS }, - { "MODE.MULT" , SC_OPCODE_MODAL_VALUE_MULTI }, - { "ZTEST" , SC_OPCODE_Z_TEST }, - { "Z.TEST" , SC_OPCODE_Z_TEST_MS }, - { "AGGREGATE" , SC_OPCODE_AGGREGATE }, - { "TTEST" , SC_OPCODE_T_TEST }, - { "T.TEST" , SC_OPCODE_T_TEST_MS }, - { "RANK" , SC_OPCODE_RANK }, - { "PERCENTILE" , SC_OPCODE_PERCENTILE }, - { "PERCENTRANK" , SC_OPCODE_PERCENT_RANK }, - { "PERCENTILE.INC" , SC_OPCODE_PERCENTILE_INC }, - { "PERCENTRANK.INC" , SC_OPCODE_PERCENT_RANK_INC }, - { "QUARTILE.INC" , SC_OPCODE_QUARTILE_INC }, - { "RANK.EQ" , SC_OPCODE_RANK_EQ }, - { "PERCENTILE.EXC" , SC_OPCODE_PERCENTILE_EXC }, - { "PERCENTRANK.EXC" , SC_OPCODE_PERCENT_RANK_EXC }, - { "QUARTILE.EXC" , SC_OPCODE_QUARTILE_EXC }, - { "RANK.AVG" , SC_OPCODE_RANK_AVG }, - { "LARGE" , SC_OPCODE_LARGE }, - { "SMALL" , SC_OPCODE_SMALL }, - { "FREQUENCY" , SC_OPCODE_FREQUENCY }, - { "QUARTILE" , SC_OPCODE_QUARTILE }, - { "NORMINV" , SC_OPCODE_NORM_INV }, - { "NORM.INV" , SC_OPCODE_NORM_INV_MS }, - { "CONFIDENCE" , SC_OPCODE_CONFIDENCE }, - { "CONFIDENCE.NORM" , SC_OPCODE_CONFIDENCE_N }, - { "CONFIDENCE.T" , SC_OPCODE_CONFIDENCE_T }, - { "FTEST" , SC_OPCODE_F_TEST }, - { "F.TEST" , SC_OPCODE_F_TEST_MS }, - { "TRIMMEAN" , SC_OPCODE_TRIM_MEAN }, - { "PROB" , SC_OPCODE_PROB }, - { "CORREL" , SC_OPCODE_CORREL }, - { "COVAR" , SC_OPCODE_COVAR }, - { "COVARIANCE.P" , SC_OPCODE_COVARIANCE_P }, - { "COVARIANCE.S" , SC_OPCODE_COVARIANCE_S }, - { "PEARSON" , SC_OPCODE_PEARSON }, - { "RSQ" , SC_OPCODE_RSQ }, - { "STEYX" , SC_OPCODE_STEYX }, - { "SLOPE" , SC_OPCODE_SLOPE }, - { "INTERCEPT" , SC_OPCODE_INTERCEPT }, - { "TREND" , SC_OPCODE_TREND }, - { "GROWTH" , SC_OPCODE_GROWTH }, - { "LINEST" , SC_OPCODE_LINEST }, - { "LOGEST" , SC_OPCODE_LOGEST }, - { "FORECAST" , SC_OPCODE_FORECAST }, - { "FORECAST.ETS.ADD" , SC_OPCODE_FORECAST_ETS_ADD }, - { "FORECAST.ETS.SEASONALITY" , SC_OPCODE_FORECAST_ETS_SEA }, - { "FORECAST.ETS.MULT" , SC_OPCODE_FORECAST_ETS_MUL }, - { "FORECAST.ETS.PI.ADD" , SC_OPCODE_FORECAST_ETS_PIA }, - { "FORECAST.ETS.PI.MULT" , SC_OPCODE_FORECAST_ETS_PIM }, - { "FORECAST.ETS.STAT.ADD" , SC_OPCODE_FORECAST_ETS_STA }, - { "FORECAST.ETS.STAT.MULT" , SC_OPCODE_FORECAST_ETS_STM }, - { "FORECAST.LINEAR" , SC_OPCODE_FORECAST_LIN }, - { "CHIINV" , SC_OPCODE_CHI_INV }, - { "CHISQ.INV.RT" , SC_OPCODE_CHI_INV_MS }, - { "GAMMADIST" , SC_OPCODE_GAMMA_DIST }, - { "GAMMA.DIST" , SC_OPCODE_GAMMA_DIST_MS }, - { "GAMMAINV" , SC_OPCODE_GAMMA_INV }, - { "GAMMA.INV" , SC_OPCODE_GAMMA_INV_MS }, - { "TINV" , SC_OPCODE_T_INV }, - { "T.INV.2T" , SC_OPCODE_T_INV_2T }, - { "T.INV" , SC_OPCODE_T_INV_MS }, - { "FINV" , SC_OPCODE_F_INV }, - { "F.INV" , SC_OPCODE_F_INV_LT }, - { "F.INV.RT" , SC_OPCODE_F_INV_RT }, - { "CHITEST" , SC_OPCODE_CHI_TEST }, - { "CHISQ.TEST" , SC_OPCODE_CHI_TEST_MS }, - { "LOGINV" , SC_OPCODE_LOG_INV }, - { "LOGNORM.INV" , SC_OPCODE_LOG_INV_MS }, - { "TABLE" , SC_OPCODE_TABLE_OP }, - { "BETADIST" , SC_OPCODE_BETA_DIST }, - { "BETAINV" , SC_OPCODE_BETA_INV }, - { "BETA.DIST" , SC_OPCODE_BETA_DIST_MS }, - { "BETA.INV" , SC_OPCODE_BETA_INV_MS }, - { "WEEKNUM" , SC_OPCODE_WEEK }, - { "ISOWEEKNUM" , SC_OPCODE_ISOWEEKNUM }, - { "WEEKNUM_OOO" , SC_OPCODE_WEEKNUM_OOO }, - { "EASTERSUNDAY" , SC_OPCODE_EASTERSUNDAY }, - { "WEEKDAY" , SC_OPCODE_GET_DAY_OF_WEEK }, - { "NETWORKDAYS" , SC_OPCODE_NETWORKDAYS }, - { "NETWORKDAYS.INTL" , SC_OPCODE_NETWORKDAYS_MS }, - { "WORKDAY.INTL" , SC_OPCODE_WORKDAY_MS }, - { "#NAME!" , SC_OPCODE_NO_NAME }, - { "STYLE" , SC_OPCODE_STYLE }, - { "DDE" , SC_OPCODE_DDE }, - { "BASE" , SC_OPCODE_BASE }, - { "DECIMAL" , SC_OPCODE_DECIMAL }, - { "CONVERT" , SC_OPCODE_CONVERT_OOO }, // wrong but ODF1.1, keep it - { "ROMAN" , SC_OPCODE_ROMAN }, - { "ARABIC" , SC_OPCODE_ARABIC }, - { "HYPERLINK" , SC_OPCODE_HYPERLINK }, - { "INFO" , SC_OPCODE_INFO }, - { "BAHTTEXT" , SC_OPCODE_BAHTTEXT }, - { "GETPIVOTDATA" , SC_OPCODE_GET_PIVOT_DATA }, - { "EUROCONVERT" , SC_OPCODE_EUROCONVERT }, - { "NUMBERVALUE" , SC_OPCODE_NUMBERVALUE }, - { "GAMMA" , SC_OPCODE_GAMMA }, - { "CHISQDIST" , SC_OPCODE_CHISQ_DIST }, - { "CHISQ.DIST" , SC_OPCODE_CHISQ_DIST_MS }, - { "CHISQ.INV" , SC_OPCODE_CHISQ_INV_MS }, - { "CHISQINV" , SC_OPCODE_CHISQ_INV }, - { "BITAND" , SC_OPCODE_BITAND }, - { "BITOR" , SC_OPCODE_BITOR }, - { "BITXOR" , SC_OPCODE_BITXOR }, - { "BITRSHIFT" , SC_OPCODE_BITRSHIFT }, - { "BITLSHIFT" , SC_OPCODE_BITLSHIFT }, + { "IF" , ocIf }, + { "IFERROR" , ocIfError }, + { "IFNA" , ocIfNA }, + { "CHOOSE" , ocChoose }, + { "(" , ocOpen }, + { ")" , ocClose }, + { "[" , ocTableRefOpen }, + { "]" , ocTableRefClose }, + { "#All" , ocTableRefItemAll }, + { "#Headers" , ocTableRefItemHeaders }, + { "#Data" , ocTableRefItemData }, + { "#Totals" , ocTableRefItemTotals }, + { "#This Row" , ocTableRefItemThisRow }, + { "{" , ocArrayOpen }, + { "}" , ocArrayClose }, + { "|" , ocArrayRowSep }, + { ";" , ocArrayColSep }, + { ";" , ocSep }, + { "%" , ocPercentSign }, + { "+" , ocAdd }, + { "-" , ocSub }, + { "*" , ocMul }, + { "/" , ocDiv }, + { "&" , ocAmpersand }, + { "^" , ocPow }, + { "=" , ocEqual }, + { "<>" , ocNotEqual }, + { "<" , ocLess }, + { ">" , ocGreater }, + { "<=" , ocLessEqual }, + { ">=" , ocGreaterEqual }, + { "AND" , ocAnd }, + { "OR" , ocOr }, + { "XOR" , ocXor }, + { "!" , ocIntersect }, + { "~" , ocUnion }, + { ":" , ocRange }, + { "NOT" , ocNot }, + { "NEG" , ocNeg }, + { "-" , ocNegSub }, + { "@" , ocSingleValue }, + { "#" , ocSpill }, + { "PI" , ocPi }, + { "RAND" , ocRandom }, + { "TRUE" , ocTrue }, + { "FALSE" , ocFalse }, + { "TODAY" , ocGetActDate }, + { "NOW" , ocGetActTime }, + { "NA" , ocNotAvail }, + { "CURRENT" , ocCurrent }, + { "DEGREES" , ocDeg }, + { "RADIANS" , ocRad }, + { "SIN" , ocSin }, + { "COS" , ocCos }, + { "TAN" , ocTan }, + { "COT" , ocCot }, + { "ASIN" , ocArcSin }, + { "ACOS" , ocArcCos }, + { "ATAN" , ocArcTan }, + { "ACOT" , ocArcCot }, + { "SINH" , ocSinHyp }, + { "COSH" , ocCosHyp }, + { "TANH" , ocTanHyp }, + { "COTH" , ocCotHyp }, + { "ASINH" , ocArcSinHyp }, + { "ACOSH" , ocArcCosHyp }, + { "ATANH" , ocArcTanHyp }, + { "ACOTH" , ocArcCotHyp }, + { "CSC" , ocCosecant }, + { "SEC" , ocSecant }, + { "CSCH" , ocCosecantHyp }, + { "SECH" , ocSecantHyp }, + { "EXP" , ocExp }, + { "LN" , ocLn }, + { "SQRT" , ocSqrt }, + { "FACT" , ocFact }, + { "YEAR" , ocGetYear }, + { "MONTH" , ocGetMonth }, + { "DAY" , ocGetDay }, + { "HOUR" , ocGetHour }, + { "MINUTE" , ocGetMin }, + { "SECOND" , ocGetSec }, + { "SIGN" , ocPlusMinus }, + { "ABS" , ocAbs }, + { "INT" , ocInt }, + { "PHI" , ocPhi }, + { "GAUSS" , ocGauss }, + { "ISBLANK" , ocIsEmpty }, + { "ISTEXT" , ocIsString }, + { "ISNONTEXT" , ocIsNonString }, + { "ISLOGICAL" , ocIsLogical }, + { "TYPE" , ocType }, + { "CELL" , ocCell }, + { "ISREF" , ocIsRef }, + { "ISNUMBER" , ocIsValue }, + { "ISFORMULA" , ocIsFormula }, + { "ISNA" , ocIsNA }, + { "ISERR" , ocIsErr }, + { "ISERROR" , ocIsError }, + { "ISEVEN" , ocIsEven }, + { "ISODD" , ocIsOdd }, + { "N" , ocN }, + { "DATEVALUE" , ocGetDateValue }, + { "TIMEVALUE" , ocGetTimeValue }, + { "CODE" , ocCode }, + { "TRIM" , ocTrim }, + { "UPPER" , ocUpper }, + { "PROPER" , ocProper }, + { "LOWER" , ocLower }, + { "LEN" , ocLen }, + { "T" , ocT }, + { "VALUE" , ocValue }, + { "CLEAN" , ocClean }, + { "CHAR" , ocChar }, + { "JIS" , ocJis }, + { "ASC" , ocAsc }, + { "UNICODE" , ocUnicode }, + { "UNICHAR" , ocUnichar }, + { "LOG10" , ocLog10 }, + { "EVEN" , ocEven }, + { "ODD" , ocOdd }, + { "NORMSDIST" , ocStdNormDist }, + { "NORM.S.DIST" , ocStdNormDist_MS }, + { "FISHER" , ocFisher }, + { "FISHERINV" , ocFisherInv }, + { "NORMSINV" , ocSNormInv }, + { "NORM.S.INV" , ocSNormInv_MS }, + { "GAMMALN" , ocGammaLn }, + { "GAMMALN.PRECISE" , ocGammaLn_MS }, + { "ERRORTYPE" , ocErrorType }, + { "ERROR.TYPE" , ocErrorType_ODF }, + { "FORMULA" , ocFormula }, + { "ATAN2" , ocArcTan2 }, + { "CEILING.MATH" , ocCeil_Math }, + { "CEILING" , ocCeil }, + { "CEILING.XCL" , ocCeil_MS }, + { "CEILING.PRECISE" , ocCeil_Precise }, + { "ISO.CEILING" , ocCeil_ISO }, + { "FLOOR" , ocFloor }, + { "FLOOR.XCL" , ocFloor_MS }, + { "FLOOR.MATH" , ocFloor_Math }, + { "FLOOR.PRECISE" , ocFloor_Precise }, + { "ROUND" , ocRound }, + { "ROUNDUP" , ocRoundUp }, + { "ROUNDDOWN" , ocRoundDown }, + { "TRUNC" , ocTrunc }, + { "LOG" , ocLog }, + { "POWER" , ocPower }, + { "GCD" , ocGCD }, + { "LCM" , ocLCM }, + { "MOD" , ocMod }, + { "SUMPRODUCT" , ocSumProduct }, + { "SUMSQ" , ocSumSQ }, + { "SUMX2MY2" , ocSumX2MY2 }, + { "SUMX2PY2" , ocSumX2DY2 }, + { "SUMXMY2" , ocSumXMY2 }, + { "DATE" , ocGetDate }, + { "TIME" , ocGetTime }, + { "DAYS" , ocGetDiffDate }, + { "DAYS360" , ocGetDiffDate360 }, + { "DATEDIF" , ocGetDateDif }, + { "MIN" , ocMin }, + { "MINA" , ocMinA }, + { "MAX" , ocMax }, + { "MAXA" , ocMaxA }, + { "SUM" , ocSum }, + { "PRODUCT" , ocProduct }, + { "AVERAGE" , ocAverage }, + { "AVERAGEA" , ocAverageA }, + { "COUNT" , ocCount }, + { "COUNTA" , ocCount2 }, + { "NPV" , ocNPV }, + { "IRR" , ocIRR }, + { "MIRR" , ocMIRR }, + { "ISPMT" , ocISPMT }, + { "VAR" , ocVar }, + { "VARA" , ocVarA }, + { "VARP" , ocVarP }, + { "VARPA" , ocVarPA }, + { "VAR.P" , ocVarP_MS }, + { "VAR.S" , ocVarS }, + { "STDEV" , ocStDev }, + { "STDEVA" , ocStDevA }, + { "STDEVP" , ocStDevP }, + { "STDEVPA" , ocStDevPA }, + { "STDEV.P" , ocStDevP_MS }, + { "STDEV.S" , ocStDevS }, + { "B" , ocB }, + { "NORMDIST" , ocNormDist }, + { "NORM.DIST" , ocNormDist_MS }, + { "EXPONDIST" , ocExpDist }, + { "EXPON.DIST" , ocExpDist_MS }, + { "BINOMDIST" , ocBinomDist }, + { "BINOM.DIST" , ocBinomDist_MS }, + { "POISSON" , ocPoissonDist }, + { "POISSON.DIST" , ocPoissonDist_MS }, + { "COMBIN" , ocCombin }, + { "COMBINA" , ocCombinA }, + { "PERMUT" , ocPermut }, + { "PERMUTATIONA" , ocPermutationA }, + { "PV" , ocPV }, + { "SYD" , ocSYD }, + { "DDB" , ocDDB }, + { "DB" , ocDB }, + { "VDB" , ocVBD }, + { "DURATION" , ocPDuration }, // wrong but ODF1.1, keep it. + { "SLN" , ocSLN }, + { "PMT" , ocPMT }, + { "COLUMNS" , ocColumns }, + { "ROWS" , ocRows }, + { "SHEETS" , ocSheets }, + { "COLUMN" , ocColumn }, + { "ROW" , ocRow }, + { "SHEET" , ocSheet }, + { "ZGZ" , ocRRI }, + { "FV" , ocFV }, + { "NPER" , ocNper }, + { "RATE" , ocRate }, + { "IPMT" , ocIpmt }, + { "PPMT" , ocPpmt }, + { "CUMIPMT" , ocCumIpmt }, + { "CUMPRINC" , ocCumPrinc }, + { "EFFECTIVE" , ocEffect }, + { "NOMINAL" , ocNominal }, + { "SUBTOTAL" , ocSubTotal }, + { "DSUM" , ocDBSum }, + { "DCOUNT" , ocDBCount }, + { "DCOUNTA" , ocDBCount2 }, + { "DAVERAGE" , ocDBAverage }, + { "DGET" , ocDBGet }, + { "DMAX" , ocDBMax }, + { "DMIN" , ocDBMin }, + { "DPRODUCT" , ocDBProduct }, + { "DSTDEV" , ocDBStdDev }, + { "DSTDEVP" , ocDBStdDevP }, + { "DVAR" , ocDBVar }, + { "DVARP" , ocDBVarP }, + { "INDIRECT" , ocIndirect }, + { "ADDRESS" , ocAddress }, + { "MATCH" , ocMatch }, + { "XMATCH" , ocXMatch }, + { "COUNTBLANK" , ocCountEmptyCells }, + { "COUNTIF" , ocCountIf }, + { "SUMIF" , ocSumIf }, + { "AVERAGEIF" , ocAverageIf }, + { "SUMIFS" , ocSumIfs }, + { "AVERAGEIFS" , ocAverageIfs }, + { "COUNTIFS" , ocCountIfs }, + { "LOOKUP" , ocLookup }, + { "VLOOKUP" , ocVLookup }, + { "XLOOKUP" , ocXLookup }, + { "HLOOKUP" , ocHLookup }, + { "FILTER" , ocFilter }, + { "SORT" , ocSort }, + { "SORTBY" , ocSortBy }, + { "CHOOSECOLS" , ocChooseCols }, + { "CHOOSEROWS" , ocChooseRows }, + { "DROP" , ocDrop }, + { "EXPAND" , ocExpand }, + { "HSTACK" , ocHStack }, + { "VSTACK" , ocVStack }, + { "TAKE" , ocTake }, + { "TEXTAFTER" , ocTextAfter }, + { "TEXTBEFORE" , ocTextBefore }, + { "TEXTSPLIT" , ocTextSplit }, + { "TOCOL" , ocToCol }, + { "TOROW" , ocToRow }, + { "UNIQUE" , ocUnique }, + { "LET" , ocLet }, + { "WRAPCOLS" , ocWrapCols }, + { "WRAPROWS" , ocWrapRows }, + { "LAMBDA" , ocLambda }, + { "ISOMITTED" , ocIsOmitted }, + { "BYCOL" , ocByCol }, + { "BYROW" , ocByRow }, + { "MAKEARRAY" , ocMakeArray }, + { "MAP" , ocMap }, + { "REDUCE" , ocReduce }, + { "SCAN" , ocScan }, + { "ARRAYTOTEXT" , ocArrayToText }, + { "MULTIRANGE" , ocMultiArea }, // legacy for range list (union) + { "OFFSET" , ocOffset }, + { "INDEX" , ocIndex }, + { "AREAS" , ocAreas }, + { "DOLLAR" , ocCurrency }, + { "REPLACE" , ocReplace }, + { "FIXED" , ocFixed }, + { "FIND" , ocFind }, + { "EXACT" , ocExact }, + { "LEFT" , ocLeft }, + { "RIGHT" , ocRight }, + { "SEARCH" , ocSearch }, + { "MID" , ocMid }, + { "LENB" , ocLenB }, + { "RIGHTB" , ocRightB }, + { "LEFTB" , ocLeftB }, + { "REPLACEB" , ocReplaceB }, + { "FINDB" , ocFindB }, + { "SEARCHB" , ocSearchB }, + { "MIDB" , ocMidB }, + { "TEXT" , ocText }, + { "SUBSTITUTE" , ocSubstitute }, + { "REPT" , ocRept }, + { "CONCATENATE" , ocConcat }, + { "CONCAT" , ocConcat_MS }, + { "TEXTJOIN" , ocTextJoin_MS }, + { "IFS" , ocIfs_MS }, + { "SWITCH" , ocSwitch_MS }, + { "MINIFS" , ocMinIfs_MS }, + { "MAXIFS" , ocMaxIfs_MS }, + { "MVALUE" , ocMatValue }, + { "MDETERM" , ocMatDet }, + { "MINVERSE" , ocMatInv }, + { "MMULT" , ocMatMult }, + { "SEQUENCE" , ocMatSequence }, + { "TRANSPOSE" , ocMatTrans }, + { "MUNIT" , ocMatrixUnit }, + { "GOALSEEK" , ocBackSolver }, + { "HYPGEOMDIST" , ocHypGeomDist }, + { "HYPGEOM.DIST" , ocHypGeomDist_MS }, + { "LOGNORMDIST" , ocLogNormDist }, + { "LOGNORM.DIST" , ocLogNormDist_MS }, + { "TDIST" , ocTDist }, + { "T.DIST.2T" , ocTDist_2T }, + { "T.DIST" , ocTDist_MS }, + { "T.DIST.RT" , ocTDist_RT }, + { "FDIST" , ocFDist }, + { "F.DIST" , ocFDist_LT }, + { "F.DIST.RT" , ocFDist_RT }, + { "CHIDIST" , ocChiDist }, + { "CHISQ.DIST.RT" , ocChiDist_MS }, + { "WEIBULL" , ocWeibull }, + { "WEIBULL.DIST" , ocWeibull_MS }, + { "NEGBINOMDIST" , ocNegBinomVert }, + { "NEGBINOM.DIST" , ocNegBinomDist_MS }, + { "CRITBINOM" , ocCritBinom }, + { "BINOM.INV" , ocBinomInv }, + { "KURT" , ocKurt }, + { "HARMEAN" , ocHarMean }, + { "GEOMEAN" , ocGeoMean }, + { "STANDARDIZE" , ocStandard }, + { "AVEDEV" , ocAveDev }, + { "SKEW" , ocSkew }, + { "SKEWP" , ocSkewp }, + { "DEVSQ" , ocDevSq }, + { "MEDIAN" , ocMedian }, + { "MODE" , ocModalValue }, + { "MODE.SNGL" , ocModalValue_MS }, + { "MODE.MULT" , ocModalValue_Multi }, + { "ZTEST" , ocZTest }, + { "Z.TEST" , ocZTest_MS }, + { "AGGREGATE" , ocAggregate }, + { "TTEST" , ocTTest }, + { "T.TEST" , ocTTest_MS }, + { "RANK" , ocRank }, + { "PERCENTILE" , ocPercentile }, + { "PERCENTRANK" , ocPercentrank }, + { "PERCENTILE.INC" , ocPercentile_Inc }, + { "PERCENTRANK.INC" , ocPercentrank_Inc }, + { "QUARTILE.INC" , ocQuartile_Inc }, + { "RANK.EQ" , ocRank_Eq }, + { "PERCENTILE.EXC" , ocPercentile_Exc }, + { "PERCENTRANK.EXC" , ocPercentrank_Exc }, + { "QUARTILE.EXC" , ocQuartile_Exc }, + { "RANK.AVG" , ocRank_Avg }, + { "LARGE" , ocLarge }, + { "SMALL" , ocSmall }, + { "FREQUENCY" , ocFrequency }, + { "QUARTILE" , ocQuartile }, + { "NORMINV" , ocNormInv }, + { "NORM.INV" , ocNormInv_MS }, + { "CONFIDENCE" , ocConfidence }, + { "CONFIDENCE.NORM" , ocConfidence_N }, + { "CONFIDENCE.T" , ocConfidence_T }, + { "FTEST" , ocFTest }, + { "F.TEST" , ocFTest_MS }, + { "TRIMMEAN" , ocTrimMean }, + { "PROB" , ocProb }, + { "CORREL" , ocCorrel }, + { "COVAR" , ocCovar }, + { "COVARIANCE.P" , ocCovarianceP }, + { "COVARIANCE.S" , ocCovarianceS }, + { "PEARSON" , ocPearson }, + { "RSQ" , ocRSQ }, + { "STEYX" , ocSTEYX }, + { "SLOPE" , ocSlope }, + { "INTERCEPT" , ocIntercept }, + { "TREND" , ocTrend }, + { "GROWTH" , ocGrowth }, + { "LINEST" , ocLinest }, + { "LOGEST" , ocLogest }, + { "FORECAST" , ocForecast }, + { "FORECAST.ETS.ADD" , ocForecast_ETS_ADD }, + { "FORECAST.ETS.SEASONALITY" , ocForecast_ETS_SEA }, + { "FORECAST.ETS.MULT" , ocForecast_ETS_MUL }, + { "FORECAST.ETS.PI.ADD" , ocForecast_ETS_PIA }, + { "FORECAST.ETS.PI.MULT" , ocForecast_ETS_PIM }, + { "FORECAST.ETS.STAT.ADD" , ocForecast_ETS_STA }, + { "FORECAST.ETS.STAT.MULT" , ocForecast_ETS_STM }, + { "FORECAST.LINEAR" , ocForecast_LIN }, + { "CHIINV" , ocChiInv }, + { "CHISQ.INV.RT" , ocChiInv_MS }, + { "GAMMADIST" , ocGammaDist }, + { "GAMMA.DIST" , ocGammaDist_MS }, + { "GAMMAINV" , ocGammaInv }, + { "GAMMA.INV" , ocGammaInv_MS }, + { "TINV" , ocTInv }, + { "T.INV.2T" , ocTInv_2T }, + { "T.INV" , ocTInv_MS }, + { "FINV" , ocFInv }, + { "F.INV" , ocFInv_LT }, + { "F.INV.RT" , ocFInv_RT }, + { "CHITEST" , ocChiTest }, + { "CHISQ.TEST" , ocChiTest_MS }, + { "LOGINV" , ocLogInv }, + { "LOGNORM.INV" , ocLogInv_MS }, + { "TABLE" , ocTableOp }, + { "BETADIST" , ocBetaDist }, + { "BETAINV" , ocBetaInv }, + { "BETA.DIST" , ocBetaDist_MS }, + { "BETA.INV" , ocBetaInv_MS }, + { "WEEKNUM" , ocWeek }, + { "ISOWEEKNUM" , ocIsoWeeknum }, + { "WEEKNUM_OOO" , ocWeeknumOOo }, + { "EASTERSUNDAY" , ocEasterSunday }, + { "WEEKDAY" , ocGetDayOfWeek }, + { "NETWORKDAYS" , ocNetWorkdays }, + { "NETWORKDAYS.INTL" , ocNetWorkdays_MS }, + { "WORKDAY.INTL" , ocWorkday_MS }, + { "#NAME!" , ocNoName }, + { "STYLE" , ocStyle }, + { "DDE" , ocDde }, + { "BASE" , ocBase }, + { "DECIMAL" , ocDecimal }, + { "CONVERT" , ocConvertOOo }, // wrong but ODF1.1, keep it + { "ROMAN" , ocRoman }, + { "ARABIC" , ocArabic }, + { "HYPERLINK" , ocHyperLink }, + { "INFO" , ocInfo }, + { "BAHTTEXT" , ocBahtText }, + { "GETPIVOTDATA" , ocGetPivotData }, + { "EUROCONVERT" , ocEuroConvert }, + { "NUMBERVALUE" , ocNumberValue }, + { "GAMMA" , ocGamma }, + { "CHISQDIST" , ocChiSqDist }, + { "CHISQ.DIST" , ocChiSqDist_MS }, + { "CHISQ.INV" , ocChiSqInv_MS }, + { "CHISQINV" , ocChiSqInv }, + { "BITAND" , ocBitAnd }, + { "BITOR" , ocBitOr }, + { "BITXOR" , ocBitXor }, + { "BITRSHIFT" , ocBitRshift }, + { "BITLSHIFT" , ocBitLshift }, /* BEGIN defined ERROR.TYPE() values. */ - { "#NULL!" , SC_OPCODE_ERROR_NULL }, - { "#DIV/0!" , SC_OPCODE_ERROR_DIVZERO }, - { "#VALUE!" , SC_OPCODE_ERROR_VALUE }, - { "#REF!" , SC_OPCODE_ERROR_REF }, - { "#NAME?" , SC_OPCODE_ERROR_NAME }, - { "#NUM!" , SC_OPCODE_ERROR_NUM }, - { "#N/A" , SC_OPCODE_ERROR_NA }, + { "#NULL!" , ocErrNull }, + { "#DIV/0!" , ocErrDivZero }, + { "#VALUE!" , ocErrValue }, + { "#REF!" , ocErrRef }, + { "#NAME?" , ocErrName }, + { "#NUM!" , ocErrNum }, + { "#N/A" , ocErrNA }, + { "#SPILL!" , ocErrSpill }, /* END defined ERROR.TYPE() values. */ - { "FILTERXML" , SC_OPCODE_FILTERXML }, - { "WEBSERVICE" , SC_OPCODE_WEBSERVICE }, - { "COLOR" , SC_OPCODE_COLOR }, - { "ERF.PRECISE" , SC_OPCODE_ERF_MS }, - { "ERFC.PRECISE" , SC_OPCODE_ERFC_MS }, - { "ENCODEURL" , SC_OPCODE_ENCODEURL }, - { "RAWSUBTRACT" , SC_OPCODE_RAWSUBTRACT }, - { "ROUNDSIG" , SC_OPCODE_ROUNDSIG }, - { "REGEX" , SC_OPCODE_REGEX }, - { "FOURIER", SC_OPCODE_FOURIER }, - { "RAND.NV" , SC_OPCODE_RANDOM_NV }, - { "RANDBETWEEN.NV" , SC_OPCODE_RANDBETWEEN_NV }, - { "RANDARRAY" , SC_OPCODE_RANDARRAY }, + { "FILTERXML" , ocFilterXML }, + { "WEBSERVICE" , ocWebservice }, + { "COLOR" , ocColor }, + { "ERF.PRECISE" , ocErf_MS }, + { "ERFC.PRECISE" , ocErfc_MS }, + { "ENCODEURL" , ocEncodeURL }, + { "RAWSUBTRACT" , ocRawSubtract }, + { "ROUNDSIG" , ocRoundSig }, + { "REGEX" , ocRegex }, + { "FOURIER", ocFourier }, + { "RAND.NV" , ocRandomNV }, + { "RANDBETWEEN.NV" , ocRandbetweenNV }, + { "RANDARRAY" , ocRandArray }, { nullptr, -1 } }; @@ -1448,469 +1486,481 @@ const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_PODF[] = // ScCompiler::IsOpCode(). const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_API[] = { - { "IF" , SC_OPCODE_IF }, - { "IFERROR" , SC_OPCODE_IF_ERROR }, - { "IFNA" , SC_OPCODE_IF_NA }, - { "CHOOSE" , SC_OPCODE_CHOOSE }, - { "(" , SC_OPCODE_OPEN }, - { ")" , SC_OPCODE_CLOSE }, - { "[" , SC_OPCODE_TABLE_REF_OPEN }, - { "]" , SC_OPCODE_TABLE_REF_CLOSE }, - { "#All" , SC_OPCODE_TABLE_REF_ITEM_ALL }, - { "#Headers" , SC_OPCODE_TABLE_REF_ITEM_HEADERS }, - { "#Data" , SC_OPCODE_TABLE_REF_ITEM_DATA }, - { "#Totals" , SC_OPCODE_TABLE_REF_ITEM_TOTALS }, - { "#This Row" , SC_OPCODE_TABLE_REF_ITEM_THIS_ROW }, - { "{" , SC_OPCODE_ARRAY_OPEN }, - { "}" , SC_OPCODE_ARRAY_CLOSE }, - { "|" , SC_OPCODE_ARRAY_ROW_SEP }, - { ";" , SC_OPCODE_ARRAY_COL_SEP }, - { ";" , SC_OPCODE_SEP }, - { "%" , SC_OPCODE_PERCENT_SIGN }, - { "+" , SC_OPCODE_ADD }, - { "-" , SC_OPCODE_SUB }, - { "*" , SC_OPCODE_MUL }, - { "/" , SC_OPCODE_DIV }, - { "&" , SC_OPCODE_AMPERSAND }, - { "^" , SC_OPCODE_POW }, - { "=" , SC_OPCODE_EQUAL }, - { "<>" , SC_OPCODE_NOT_EQUAL }, - { "<" , SC_OPCODE_LESS }, - { ">" , SC_OPCODE_GREATER }, - { "<=" , SC_OPCODE_LESS_EQUAL }, - { ">=" , SC_OPCODE_GREATER_EQUAL }, - { "AND" , SC_OPCODE_AND }, - { "OR" , SC_OPCODE_OR }, - { "XOR" , SC_OPCODE_XOR }, - { "!" , SC_OPCODE_INTERSECT }, - { "~" , SC_OPCODE_UNION }, - { ":" , SC_OPCODE_RANGE }, - { "NOT" , SC_OPCODE_NOT }, - { "NEG" , SC_OPCODE_NEG }, - { "-" , SC_OPCODE_NEG_SUB }, - { "PI" , SC_OPCODE_PI }, - { "RAND" , SC_OPCODE_RANDOM }, - { "TRUE" , SC_OPCODE_TRUE }, - { "FALSE" , SC_OPCODE_FALSE }, - { "TODAY" , SC_OPCODE_GET_ACT_DATE }, - { "NOW" , SC_OPCODE_GET_ACT_TIME }, - { "NA" , SC_OPCODE_NO_VALUE }, - { "CURRENT" , SC_OPCODE_CURRENT }, - { "DEGREES" , SC_OPCODE_DEG }, - { "RADIANS" , SC_OPCODE_RAD }, - { "SIN" , SC_OPCODE_SIN }, - { "COS" , SC_OPCODE_COS }, - { "TAN" , SC_OPCODE_TAN }, - { "COT" , SC_OPCODE_COT }, - { "ASIN" , SC_OPCODE_ARC_SIN }, - { "ACOS" , SC_OPCODE_ARC_COS }, - { "ATAN" , SC_OPCODE_ARC_TAN }, - { "ACOT" , SC_OPCODE_ARC_COT }, - { "SINH" , SC_OPCODE_SIN_HYP }, - { "COSH" , SC_OPCODE_COS_HYP }, - { "TANH" , SC_OPCODE_TAN_HYP }, - { "COTH" , SC_OPCODE_COT_HYP }, - { "ASINH" , SC_OPCODE_ARC_SIN_HYP }, - { "ACOSH" , SC_OPCODE_ARC_COS_HYP }, - { "ATANH" , SC_OPCODE_ARC_TAN_HYP }, - { "ACOTH" , SC_OPCODE_ARC_COT_HYP }, - { "CSC" , SC_OPCODE_COSECANT }, - { "SEC" , SC_OPCODE_SECANT }, - { "CSCH" , SC_OPCODE_COSECANT_HYP }, - { "SECH" , SC_OPCODE_SECANT_HYP }, - { "EXP" , SC_OPCODE_EXP }, - { "LN" , SC_OPCODE_LN }, - { "SQRT" , SC_OPCODE_SQRT }, - { "FACT" , SC_OPCODE_FACT }, - { "YEAR" , SC_OPCODE_GET_YEAR }, - { "MONTH" , SC_OPCODE_GET_MONTH }, - { "DAY" , SC_OPCODE_GET_DAY }, - { "HOUR" , SC_OPCODE_GET_HOUR }, - { "MINUTE" , SC_OPCODE_GET_MIN }, - { "SECOND" , SC_OPCODE_GET_SEC }, - { "SIGN" , SC_OPCODE_PLUS_MINUS }, - { "ABS" , SC_OPCODE_ABS }, - { "INT" , SC_OPCODE_INT }, - { "PHI" , SC_OPCODE_PHI }, - { "GAUSS" , SC_OPCODE_GAUSS }, - { "ISBLANK" , SC_OPCODE_IS_EMPTY }, - { "ISTEXT" , SC_OPCODE_IS_STRING }, - { "ISNONTEXT" , SC_OPCODE_IS_NON_STRING }, - { "ISLOGICAL" , SC_OPCODE_IS_LOGICAL }, - { "TYPE" , SC_OPCODE_TYPE }, - { "CELL" , SC_OPCODE_CELL }, - { "ISREF" , SC_OPCODE_IS_REF }, - { "ISNUMBER" , SC_OPCODE_IS_VALUE }, - { "ISFORMULA" , SC_OPCODE_IS_FORMULA }, - { "ISNA" , SC_OPCODE_IS_NV }, - { "ISERR" , SC_OPCODE_IS_ERR }, - { "ISERROR" , SC_OPCODE_IS_ERROR }, - { "ISEVEN" , SC_OPCODE_IS_EVEN }, - { "ISODD" , SC_OPCODE_IS_ODD }, - { "N" , SC_OPCODE_N }, - { "DATEVALUE" , SC_OPCODE_GET_DATE_VALUE }, - { "TIMEVALUE" , SC_OPCODE_GET_TIME_VALUE }, - { "CODE" , SC_OPCODE_CODE }, - { "TRIM" , SC_OPCODE_TRIM }, - { "UPPER" , SC_OPCODE_UPPER }, - { "PROPER" , SC_OPCODE_PROPER }, - { "LOWER" , SC_OPCODE_LOWER }, - { "LEN" , SC_OPCODE_LEN }, - { "T" , SC_OPCODE_T }, - { "VALUE" , SC_OPCODE_VALUE }, - { "CLEAN" , SC_OPCODE_CLEAN }, - { "CHAR" , SC_OPCODE_CHAR }, - { "JIS" , SC_OPCODE_JIS }, - { "ASC" , SC_OPCODE_ASC }, - { "UNICODE" , SC_OPCODE_UNICODE }, - { "UNICHAR" , SC_OPCODE_UNICHAR }, - { "LOG10" , SC_OPCODE_LOG10 }, - { "EVEN" , SC_OPCODE_EVEN }, - { "ODD" , SC_OPCODE_ODD }, - { "NORMSDIST" , SC_OPCODE_STD_NORM_DIST }, - { "NORM.S.DIST" , SC_OPCODE_STD_NORM_DIST_MS }, - { "FISHER" , SC_OPCODE_FISHER }, - { "FISHERINV" , SC_OPCODE_FISHER_INV }, - { "NORMSINV" , SC_OPCODE_S_NORM_INV }, - { "NORM.S.INV" , SC_OPCODE_S_NORM_INV_MS }, - { "GAMMALN" , SC_OPCODE_GAMMA_LN }, - { "GAMMALN.PRECISE" , SC_OPCODE_GAMMA_LN_MS }, - { "ERRORTYPE" , SC_OPCODE_ERROR_TYPE }, - { "ERROR.TYPE" , SC_OPCODE_ERROR_TYPE_ODF }, - { "FORMULA" , SC_OPCODE_FORMULA }, - { "ATAN2" , SC_OPCODE_ARC_TAN_2 }, - { "CEILING.MATH" , SC_OPCODE_CEIL_MATH }, - { "CEILING" , SC_OPCODE_CEIL }, - { "CEILING.XCL" , SC_OPCODE_CEIL_MS }, - { "CEILING.PRECISE" , SC_OPCODE_CEIL_PRECISE }, - { "ISO.CEILING" , SC_OPCODE_CEIL_ISO }, - { "FLOOR" , SC_OPCODE_FLOOR }, - { "FLOOR.XCL" , SC_OPCODE_FLOOR_MS }, - { "FLOOR.MATH" , SC_OPCODE_FLOOR_MATH }, - { "FLOOR.PRECISE" , SC_OPCODE_FLOOR_PRECISE }, - { "ROUND" , SC_OPCODE_ROUND }, - { "ROUNDUP" , SC_OPCODE_ROUND_UP }, - { "ROUNDDOWN" , SC_OPCODE_ROUND_DOWN }, - { "TRUNC" , SC_OPCODE_TRUNC }, - { "LOG" , SC_OPCODE_LOG }, - { "POWER" , SC_OPCODE_POWER }, - { "GCD" , SC_OPCODE_GCD }, - { "LCM" , SC_OPCODE_LCM }, - { "MOD" , SC_OPCODE_MOD }, - { "SUMPRODUCT" , SC_OPCODE_SUM_PRODUCT }, - { "SUMSQ" , SC_OPCODE_SUM_SQ }, - { "SUMX2MY2" , SC_OPCODE_SUM_X2MY2 }, - { "SUMX2PY2" , SC_OPCODE_SUM_X2DY2 }, - { "SUMXMY2" , SC_OPCODE_SUM_XMY2 }, - { "DATE" , SC_OPCODE_GET_DATE }, - { "TIME" , SC_OPCODE_GET_TIME }, - { "DAYS" , SC_OPCODE_GET_DIFF_DATE }, - { "DAYS360" , SC_OPCODE_GET_DIFF_DATE_360 }, - { "DATEDIF" , SC_OPCODE_GET_DATEDIF }, - { "MIN" , SC_OPCODE_MIN }, - { "MINA" , SC_OPCODE_MIN_A }, - { "MAX" , SC_OPCODE_MAX }, - { "MAXA" , SC_OPCODE_MAX_A }, - { "SUM" , SC_OPCODE_SUM }, - { "PRODUCT" , SC_OPCODE_PRODUCT }, - { "AVERAGE" , SC_OPCODE_AVERAGE }, - { "AVERAGEA" , SC_OPCODE_AVERAGE_A }, - { "COUNT" , SC_OPCODE_COUNT }, - { "COUNTA" , SC_OPCODE_COUNT_2 }, - { "NPV" , SC_OPCODE_NPV }, - { "IRR" , SC_OPCODE_IRR }, - { "MIRR" , SC_OPCODE_MIRR }, - { "ISPMT" , SC_OPCODE_ISPMT }, - { "VAR" , SC_OPCODE_VAR }, - { "VARA" , SC_OPCODE_VAR_A }, - { "VARP" , SC_OPCODE_VAR_P }, - { "VARPA" , SC_OPCODE_VAR_P_A }, - { "VAR.P" , SC_OPCODE_VAR_P_MS }, - { "VAR.S" , SC_OPCODE_VAR_S }, - { "STDEV" , SC_OPCODE_ST_DEV }, - { "STDEVA" , SC_OPCODE_ST_DEV_A }, - { "STDEVP" , SC_OPCODE_ST_DEV_P }, - { "STDEVPA" , SC_OPCODE_ST_DEV_P_A }, - { "STDEV.P" , SC_OPCODE_ST_DEV_P_MS }, - { "STDEV.S" , SC_OPCODE_ST_DEV_S }, - { "B" , SC_OPCODE_B }, - { "NORMDIST" , SC_OPCODE_NORM_DIST }, - { "NORM.DIST" , SC_OPCODE_NORM_DIST_MS }, - { "EXPONDIST" , SC_OPCODE_EXP_DIST }, - { "EXPON.DIST" , SC_OPCODE_EXP_DIST_MS }, - { "BINOMDIST" , SC_OPCODE_BINOM_DIST }, - { "BINOM.DIST" , SC_OPCODE_BINOM_DIST_MS }, - { "POISSON" , SC_OPCODE_POISSON_DIST }, - { "POISSON.DIST" , SC_OPCODE_POISSON_DIST_MS }, - { "COMBIN" , SC_OPCODE_COMBIN }, - { "COMBINA" , SC_OPCODE_COMBIN_A }, - { "PERMUT" , SC_OPCODE_PERMUT }, - { "PERMUTATIONA" , SC_OPCODE_PERMUTATION_A }, - { "PV" , SC_OPCODE_PV }, - { "SYD" , SC_OPCODE_SYD }, - { "DDB" , SC_OPCODE_DDB }, - { "DB" , SC_OPCODE_DB }, - { "VDB" , SC_OPCODE_VBD }, - { "DURATION" , SC_OPCODE_PDURATION }, - { "SLN" , SC_OPCODE_SLN }, - { "PMT" , SC_OPCODE_PMT }, - { "COLUMNS" , SC_OPCODE_COLUMNS }, - { "ROWS" , SC_OPCODE_ROWS }, - { "SHEETS" , SC_OPCODE_SHEETS }, - { "COLUMN" , SC_OPCODE_COLUMN }, - { "ROW" , SC_OPCODE_ROW }, - { "SHEET" , SC_OPCODE_SHEET }, - { "ZGZ" , SC_OPCODE_RRI }, - { "FV" , SC_OPCODE_FV }, - { "NPER" , SC_OPCODE_NPER }, - { "RATE" , SC_OPCODE_RATE }, - { "IPMT" , SC_OPCODE_IPMT }, - { "PPMT" , SC_OPCODE_PPMT }, - { "CUMIPMT" , SC_OPCODE_CUM_IPMT }, - { "CUMPRINC" , SC_OPCODE_CUM_PRINC }, - { "EFFECTIVE" , SC_OPCODE_EFFECT }, - { "NOMINAL" , SC_OPCODE_NOMINAL }, - { "SUBTOTAL" , SC_OPCODE_SUB_TOTAL }, - { "DSUM" , SC_OPCODE_DB_SUM }, - { "DCOUNT" , SC_OPCODE_DB_COUNT }, - { "DCOUNTA" , SC_OPCODE_DB_COUNT_2 }, - { "DAVERAGE" , SC_OPCODE_DB_AVERAGE }, - { "DGET" , SC_OPCODE_DB_GET }, - { "DMAX" , SC_OPCODE_DB_MAX }, - { "DMIN" , SC_OPCODE_DB_MIN }, - { "DPRODUCT" , SC_OPCODE_DB_PRODUCT }, - { "DSTDEV" , SC_OPCODE_DB_STD_DEV }, - { "DSTDEVP" , SC_OPCODE_DB_STD_DEV_P }, - { "DVAR" , SC_OPCODE_DB_VAR }, - { "DVARP" , SC_OPCODE_DB_VAR_P }, - { "INDIRECT" , SC_OPCODE_INDIRECT }, - { "ADDRESS" , SC_OPCODE_ADDRESS }, - { "MATCH" , SC_OPCODE_MATCH }, - { "XMATCH" , SC_OPCODE_X_MATCH }, - { "COUNTBLANK" , SC_OPCODE_COUNT_EMPTY_CELLS }, - { "COUNTIF" , SC_OPCODE_COUNT_IF }, - { "SUMIF" , SC_OPCODE_SUM_IF }, - { "AVERAGEIF" , SC_OPCODE_AVERAGE_IF }, - { "SUMIFS" , SC_OPCODE_SUM_IFS }, - { "AVERAGEIFS" , SC_OPCODE_AVERAGE_IFS }, - { "COUNTIFS" , SC_OPCODE_COUNT_IFS }, - { "LOOKUP" , SC_OPCODE_LOOKUP }, - { "VLOOKUP" , SC_OPCODE_V_LOOKUP }, - { "XLOOKUP" , SC_OPCODE_X_LOOKUP }, - { "HLOOKUP" , SC_OPCODE_H_LOOKUP }, - { "FILTER" , SC_OPCODE_FILTER }, - { "SORT" , SC_OPCODE_SORT }, - { "SORTBY" , SC_OPCODE_SORTBY }, - { "CHOOSECOLS" , SC_OPCODE_CHOOSECOLS }, - { "CHOOSEROWS" , SC_OPCODE_CHOOSEROWS }, - { "DROP" , SC_OPCODE_DROP }, - { "EXPAND" , SC_OPCODE_EXPAND }, - { "HSTACK" , SC_OPCODE_HSTACK }, - { "VSTACK" , SC_OPCODE_VSTACK }, - { "TAKE" , SC_OPCODE_TAKE }, - { "TEXTAFTER" , SC_OPCODE_TEXTAFTER }, - { "TEXTBEFORE" , SC_OPCODE_TEXTBEFORE }, - { "TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, - { "TOCOL" , SC_OPCODE_TOCOL }, - { "TOROW" , SC_OPCODE_TOROW }, - { "UNIQUE" , SC_OPCODE_UNIQUE }, - { "LET" , SC_OPCODE_LET }, - { "WRAPCOLS" , SC_OPCODE_WRAPCOLS }, - { "WRAPROWS" , SC_OPCODE_WRAPROWS }, - { "MULTIRANGE" , SC_OPCODE_MULTI_AREA }, // legacy for range list (union) - { "OFFSET" , SC_OPCODE_OFFSET }, - { "INDEX" , SC_OPCODE_INDEX }, // ?? first character = I ?? - { "AREAS" , SC_OPCODE_AREAS }, - { "DOLLAR" , SC_OPCODE_CURRENCY }, - { "REPLACE" , SC_OPCODE_REPLACE }, - { "FIXED" , SC_OPCODE_FIXED }, - { "FIND" , SC_OPCODE_FIND }, - { "EXACT" , SC_OPCODE_EXACT }, - { "LEFT" , SC_OPCODE_LEFT }, - { "RIGHT" , SC_OPCODE_RIGHT }, - { "SEARCH" , SC_OPCODE_SEARCH }, - { "MID" , SC_OPCODE_MID }, - { "LENB" , SC_OPCODE_LENB }, - { "RIGHTB" , SC_OPCODE_RIGHTB }, - { "LEFTB" , SC_OPCODE_LEFTB }, - { "REPLACEB" , SC_OPCODE_REPLACEB }, - { "FINDB" , SC_OPCODE_FINDB }, - { "SEARCHB" , SC_OPCODE_SEARCHB }, - { "MIDB" , SC_OPCODE_MIDB }, - { "TEXT" , SC_OPCODE_TEXT }, - { "SUBSTITUTE" , SC_OPCODE_SUBSTITUTE }, - { "REPT" , SC_OPCODE_REPT }, - { "CONCATENATE" , SC_OPCODE_CONCAT }, - { "CONCAT" , SC_OPCODE_CONCAT_MS }, - { "TEXTJOIN" , SC_OPCODE_TEXTJOIN_MS }, - { "IFS" , SC_OPCODE_IFS_MS }, - { "SWITCH" , SC_OPCODE_SWITCH_MS }, - { "MINIFS" , SC_OPCODE_MINIFS_MS }, - { "MAXIFS" , SC_OPCODE_MAXIFS_MS }, - { "MVALUE" , SC_OPCODE_MAT_VALUE }, - { "MDETERM" , SC_OPCODE_MAT_DET }, - { "MINVERSE" , SC_OPCODE_MAT_INV }, - { "MMULT" , SC_OPCODE_MAT_MULT }, - { "SEQUENCE" , SC_OPCODE_MAT_SEQUENCE }, - { "TRANSPOSE" , SC_OPCODE_MAT_TRANS }, - { "MUNIT" , SC_OPCODE_MATRIX_UNIT }, - { "GOALSEEK" , SC_OPCODE_BACK_SOLVER }, - { "HYPGEOMDIST" , SC_OPCODE_HYP_GEOM_DIST }, - { "HYPGEOM.DIST" , SC_OPCODE_HYP_GEOM_DIST_MS }, - { "LOGNORMDIST" , SC_OPCODE_LOG_NORM_DIST }, - { "LOGNORM.DIST" , SC_OPCODE_LOG_NORM_DIST_MS }, - { "TDIST" , SC_OPCODE_T_DIST }, - { "T.DIST.2T" , SC_OPCODE_T_DIST_2T }, - { "T.DIST" , SC_OPCODE_T_DIST_MS }, - { "T.DIST.RT" , SC_OPCODE_T_DIST_RT }, - { "FDIST" , SC_OPCODE_F_DIST }, - { "F.DIST" , SC_OPCODE_F_DIST_LT }, - { "F.DIST.RT" , SC_OPCODE_F_DIST_RT }, - { "CHIDIST" , SC_OPCODE_CHI_DIST }, - { "CHISQ.DIST.RT" , SC_OPCODE_CHI_DIST_MS }, - { "WEIBULL" , SC_OPCODE_WEIBULL }, - { "WEIBULL.DIST" , SC_OPCODE_WEIBULL_MS }, - { "NEGBINOMDIST" , SC_OPCODE_NEG_BINOM_VERT }, - { "NEGBINOM.DIST" , SC_OPCODE_NEG_BINOM_DIST_MS }, - { "CRITBINOM" , SC_OPCODE_CRIT_BINOM }, - { "BINOM.INV" , SC_OPCODE_BINOM_INV }, - { "KURT" , SC_OPCODE_KURT }, - { "HARMEAN" , SC_OPCODE_HAR_MEAN }, - { "GEOMEAN" , SC_OPCODE_GEO_MEAN }, - { "STANDARDIZE" , SC_OPCODE_STANDARD }, - { "AVEDEV" , SC_OPCODE_AVE_DEV }, - { "SKEW" , SC_OPCODE_SKEW }, - { "SKEWP" , SC_OPCODE_SKEWP }, - { "DEVSQ" , SC_OPCODE_DEV_SQ }, - { "MEDIAN" , SC_OPCODE_MEDIAN }, - { "MODE" , SC_OPCODE_MODAL_VALUE }, - { "MODE.SNGL" , SC_OPCODE_MODAL_VALUE_MS }, - { "MODE.MULT" , SC_OPCODE_MODAL_VALUE_MULTI }, - { "ZTEST" , SC_OPCODE_Z_TEST }, - { "Z.TEST" , SC_OPCODE_Z_TEST_MS }, - { "AGGREGATE" , SC_OPCODE_AGGREGATE }, - { "TTEST" , SC_OPCODE_T_TEST }, - { "T.TEST" , SC_OPCODE_T_TEST_MS }, - { "RANK" , SC_OPCODE_RANK }, - { "PERCENTILE" , SC_OPCODE_PERCENTILE }, - { "PERCENTRANK" , SC_OPCODE_PERCENT_RANK }, - { "PERCENTILE.INC" , SC_OPCODE_PERCENTILE_INC }, - { "PERCENTRANK.INC" , SC_OPCODE_PERCENT_RANK_INC }, - { "QUARTILE.INC" , SC_OPCODE_QUARTILE_INC }, - { "RANK.EQ" , SC_OPCODE_RANK_EQ }, - { "PERCENTILE.EXC" , SC_OPCODE_PERCENTILE_EXC }, - { "PERCENTRANK.EXC" , SC_OPCODE_PERCENT_RANK_EXC }, - { "QUARTILE.EXC" , SC_OPCODE_QUARTILE_EXC }, - { "RANK.AVG" , SC_OPCODE_RANK_AVG }, - { "LARGE" , SC_OPCODE_LARGE }, - { "SMALL" , SC_OPCODE_SMALL }, - { "FREQUENCY" , SC_OPCODE_FREQUENCY }, - { "QUARTILE" , SC_OPCODE_QUARTILE }, - { "NORMINV" , SC_OPCODE_NORM_INV }, - { "NORM.INV" , SC_OPCODE_NORM_INV_MS }, - { "CONFIDENCE" , SC_OPCODE_CONFIDENCE }, - { "CONFIDENCE.NORM" , SC_OPCODE_CONFIDENCE_N }, - { "CONFIDENCE.T" , SC_OPCODE_CONFIDENCE_T }, - { "FTEST" , SC_OPCODE_F_TEST }, - { "F.TEST" , SC_OPCODE_F_TEST_MS }, - { "TRIMMEAN" , SC_OPCODE_TRIM_MEAN }, - { "PROB" , SC_OPCODE_PROB }, - { "CORREL" , SC_OPCODE_CORREL }, - { "COVAR" , SC_OPCODE_COVAR }, - { "COVARIANCE.P" , SC_OPCODE_COVARIANCE_P }, - { "COVARIANCE.S" , SC_OPCODE_COVARIANCE_S }, - { "PEARSON" , SC_OPCODE_PEARSON }, - { "RSQ" , SC_OPCODE_RSQ }, - { "STEYX" , SC_OPCODE_STEYX }, - { "SLOPE" , SC_OPCODE_SLOPE }, - { "INTERCEPT" , SC_OPCODE_INTERCEPT }, - { "TREND" , SC_OPCODE_TREND }, - { "GROWTH" , SC_OPCODE_GROWTH }, - { "LINEST" , SC_OPCODE_LINEST }, - { "LOGEST" , SC_OPCODE_LOGEST }, - { "FORECAST" , SC_OPCODE_FORECAST }, - { "FORECAST.ETS.ADD" , SC_OPCODE_FORECAST_ETS_ADD }, - { "FORECAST.ETS.SEASONALITY" , SC_OPCODE_FORECAST_ETS_SEA }, - { "FORECAST.ETS.MULT" , SC_OPCODE_FORECAST_ETS_MUL }, - { "FORECAST.ETS.PI.ADD" , SC_OPCODE_FORECAST_ETS_PIA }, - { "FORECAST.ETS.PI.MULT" , SC_OPCODE_FORECAST_ETS_PIM }, - { "FORECAST.ETS.STAT.ADD" , SC_OPCODE_FORECAST_ETS_STA }, - { "FORECAST.ETS.STAT.MULT" , SC_OPCODE_FORECAST_ETS_STM }, - { "FORECAST.LINEAR" , SC_OPCODE_FORECAST_LIN }, - { "CHIINV" , SC_OPCODE_CHI_INV }, - { "CHISQ.INV.RT" , SC_OPCODE_CHI_INV_MS }, - { "GAMMADIST" , SC_OPCODE_GAMMA_DIST }, - { "GAMMA.DIST" , SC_OPCODE_GAMMA_DIST_MS }, - { "GAMMAINV" , SC_OPCODE_GAMMA_INV }, - { "GAMMA.INV" , SC_OPCODE_GAMMA_INV_MS }, - { "TINV" , SC_OPCODE_T_INV }, - { "T.INV.2T" , SC_OPCODE_T_INV_2T }, - { "T.INV" , SC_OPCODE_T_INV_MS }, - { "FINV" , SC_OPCODE_F_INV }, - { "F.INV" , SC_OPCODE_F_INV_LT }, - { "F.INV.RT" , SC_OPCODE_F_INV_RT }, - { "CHITEST" , SC_OPCODE_CHI_TEST }, - { "CHISQ.TEST" , SC_OPCODE_CHI_TEST_MS }, - { "LOGINV" , SC_OPCODE_LOG_INV }, - { "LOGNORM.INV" , SC_OPCODE_LOG_INV_MS }, - { "TABLE" , SC_OPCODE_TABLE_OP }, - { "BETADIST" , SC_OPCODE_BETA_DIST }, - { "BETAINV" , SC_OPCODE_BETA_INV }, - { "BETA.DIST" , SC_OPCODE_BETA_DIST_MS }, - { "BETA.INV" , SC_OPCODE_BETA_INV_MS }, - { "WEEKNUM" , SC_OPCODE_WEEK }, - { "ISOWEEKNUM" , SC_OPCODE_ISOWEEKNUM }, - { "WEEKNUM_OOO" , SC_OPCODE_WEEKNUM_OOO }, - { "EASTERSUNDAY" , SC_OPCODE_EASTERSUNDAY }, - { "WEEKDAY" , SC_OPCODE_GET_DAY_OF_WEEK }, - { "NETWORKDAYS" , SC_OPCODE_NETWORKDAYS }, - { "NETWORKDAYS.INTL" , SC_OPCODE_NETWORKDAYS_MS }, - { "WORKDAY.INTL" , SC_OPCODE_WORKDAY_MS }, - { "#NAME!" , SC_OPCODE_NO_NAME }, - { "STYLE" , SC_OPCODE_STYLE }, - { "DDE" , SC_OPCODE_DDE }, - { "BASE" , SC_OPCODE_BASE }, - { "DECIMAL" , SC_OPCODE_DECIMAL }, - { "CONVERT" , SC_OPCODE_CONVERT_OOO }, - { "ROMAN" , SC_OPCODE_ROMAN }, - { "ARABIC" , SC_OPCODE_ARABIC }, - { "HYPERLINK" , SC_OPCODE_HYPERLINK }, - { "INFO" , SC_OPCODE_INFO }, - { "BAHTTEXT" , SC_OPCODE_BAHTTEXT }, - { "GETPIVOTDATA" , SC_OPCODE_GET_PIVOT_DATA }, - { "EUROCONVERT" , SC_OPCODE_EUROCONVERT }, - { "NUMBERVALUE" , SC_OPCODE_NUMBERVALUE }, - { "GAMMA" , SC_OPCODE_GAMMA }, - { "CHISQDIST" , SC_OPCODE_CHISQ_DIST }, - { "CHISQ.DIST" , SC_OPCODE_CHISQ_DIST_MS }, - { "CHISQ.INV" , SC_OPCODE_CHISQ_INV_MS }, - { "CHISQINV" , SC_OPCODE_CHISQ_INV }, - { "BITAND" , SC_OPCODE_BITAND }, - { "BITOR" , SC_OPCODE_BITOR }, - { "BITXOR" , SC_OPCODE_BITXOR }, - { "BITRSHIFT" , SC_OPCODE_BITRSHIFT }, - { "BITLSHIFT" , SC_OPCODE_BITLSHIFT }, - { "#NULL!" , SC_OPCODE_ERROR_NULL }, - { "#DIV/0!" , SC_OPCODE_ERROR_DIVZERO }, - { "#VALUE!" , SC_OPCODE_ERROR_VALUE }, - { "#REF!" , SC_OPCODE_ERROR_REF }, - { "#NAME?" , SC_OPCODE_ERROR_NAME }, - { "#NUM!" , SC_OPCODE_ERROR_NUM }, - { "#N/A" , SC_OPCODE_ERROR_NA }, + { "IF" , ocIf }, + { "IFERROR" , ocIfError }, + { "IFNA" , ocIfNA }, + { "CHOOSE" , ocChoose }, + { "(" , ocOpen }, + { ")" , ocClose }, + { "[" , ocTableRefOpen }, + { "]" , ocTableRefClose }, + { "#All" , ocTableRefItemAll }, + { "#Headers" , ocTableRefItemHeaders }, + { "#Data" , ocTableRefItemData }, + { "#Totals" , ocTableRefItemTotals }, + { "#This Row" , ocTableRefItemThisRow }, + { "{" , ocArrayOpen }, + { "}" , ocArrayClose }, + { "|" , ocArrayRowSep }, + { ";" , ocArrayColSep }, + { ";" , ocSep }, + { "%" , ocPercentSign }, + { "+" , ocAdd }, + { "-" , ocSub }, + { "*" , ocMul }, + { "/" , ocDiv }, + { "&" , ocAmpersand }, + { "^" , ocPow }, + { "=" , ocEqual }, + { "<>" , ocNotEqual }, + { "<" , ocLess }, + { ">" , ocGreater }, + { "<=" , ocLessEqual }, + { ">=" , ocGreaterEqual }, + { "AND" , ocAnd }, + { "OR" , ocOr }, + { "XOR" , ocXor }, + { "!" , ocIntersect }, + { "~" , ocUnion }, + { ":" , ocRange }, + { "NOT" , ocNot }, + { "NEG" , ocNeg }, + { "-" , ocNegSub }, + { "@" , ocSingleValue }, + { "#" , ocSpill }, + { "PI" , ocPi }, + { "RAND" , ocRandom }, + { "TRUE" , ocTrue }, + { "FALSE" , ocFalse }, + { "TODAY" , ocGetActDate }, + { "NOW" , ocGetActTime }, + { "NA" , ocNotAvail }, + { "CURRENT" , ocCurrent }, + { "DEGREES" , ocDeg }, + { "RADIANS" , ocRad }, + { "SIN" , ocSin }, + { "COS" , ocCos }, + { "TAN" , ocTan }, + { "COT" , ocCot }, + { "ASIN" , ocArcSin }, + { "ACOS" , ocArcCos }, + { "ATAN" , ocArcTan }, + { "ACOT" , ocArcCot }, + { "SINH" , ocSinHyp }, + { "COSH" , ocCosHyp }, + { "TANH" , ocTanHyp }, + { "COTH" , ocCotHyp }, + { "ASINH" , ocArcSinHyp }, + { "ACOSH" , ocArcCosHyp }, + { "ATANH" , ocArcTanHyp }, + { "ACOTH" , ocArcCotHyp }, + { "CSC" , ocCosecant }, + { "SEC" , ocSecant }, + { "CSCH" , ocCosecantHyp }, + { "SECH" , ocSecantHyp }, + { "EXP" , ocExp }, + { "LN" , ocLn }, + { "SQRT" , ocSqrt }, + { "FACT" , ocFact }, + { "YEAR" , ocGetYear }, + { "MONTH" , ocGetMonth }, + { "DAY" , ocGetDay }, + { "HOUR" , ocGetHour }, + { "MINUTE" , ocGetMin }, + { "SECOND" , ocGetSec }, + { "SIGN" , ocPlusMinus }, + { "ABS" , ocAbs }, + { "INT" , ocInt }, + { "PHI" , ocPhi }, + { "GAUSS" , ocGauss }, + { "ISBLANK" , ocIsEmpty }, + { "ISTEXT" , ocIsString }, + { "ISNONTEXT" , ocIsNonString }, + { "ISLOGICAL" , ocIsLogical }, + { "TYPE" , ocType }, + { "CELL" , ocCell }, + { "ISREF" , ocIsRef }, + { "ISNUMBER" , ocIsValue }, + { "ISFORMULA" , ocIsFormula }, + { "ISNA" , ocIsNA }, + { "ISERR" , ocIsErr }, + { "ISERROR" , ocIsError }, + { "ISEVEN" , ocIsEven }, + { "ISODD" , ocIsOdd }, + { "N" , ocN }, + { "DATEVALUE" , ocGetDateValue }, + { "TIMEVALUE" , ocGetTimeValue }, + { "CODE" , ocCode }, + { "TRIM" , ocTrim }, + { "UPPER" , ocUpper }, + { "PROPER" , ocProper }, + { "LOWER" , ocLower }, + { "LEN" , ocLen }, + { "T" , ocT }, + { "VALUE" , ocValue }, + { "CLEAN" , ocClean }, + { "CHAR" , ocChar }, + { "JIS" , ocJis }, + { "ASC" , ocAsc }, + { "UNICODE" , ocUnicode }, + { "UNICHAR" , ocUnichar }, + { "LOG10" , ocLog10 }, + { "EVEN" , ocEven }, + { "ODD" , ocOdd }, + { "NORMSDIST" , ocStdNormDist }, + { "NORM.S.DIST" , ocStdNormDist_MS }, + { "FISHER" , ocFisher }, + { "FISHERINV" , ocFisherInv }, + { "NORMSINV" , ocSNormInv }, + { "NORM.S.INV" , ocSNormInv_MS }, + { "GAMMALN" , ocGammaLn }, + { "GAMMALN.PRECISE" , ocGammaLn_MS }, + { "ERRORTYPE" , ocErrorType }, + { "ERROR.TYPE" , ocErrorType_ODF }, + { "FORMULA" , ocFormula }, + { "ATAN2" , ocArcTan2 }, + { "CEILING.MATH" , ocCeil_Math }, + { "CEILING" , ocCeil }, + { "CEILING.XCL" , ocCeil_MS }, + { "CEILING.PRECISE" , ocCeil_Precise }, + { "ISO.CEILING" , ocCeil_ISO }, + { "FLOOR" , ocFloor }, + { "FLOOR.XCL" , ocFloor_MS }, + { "FLOOR.MATH" , ocFloor_Math }, + { "FLOOR.PRECISE" , ocFloor_Precise }, + { "ROUND" , ocRound }, + { "ROUNDUP" , ocRoundUp }, + { "ROUNDDOWN" , ocRoundDown }, + { "TRUNC" , ocTrunc }, + { "LOG" , ocLog }, + { "POWER" , ocPower }, + { "GCD" , ocGCD }, + { "LCM" , ocLCM }, + { "MOD" , ocMod }, + { "SUMPRODUCT" , ocSumProduct }, + { "SUMSQ" , ocSumSQ }, + { "SUMX2MY2" , ocSumX2MY2 }, + { "SUMX2PY2" , ocSumX2DY2 }, + { "SUMXMY2" , ocSumXMY2 }, + { "DATE" , ocGetDate }, + { "TIME" , ocGetTime }, + { "DAYS" , ocGetDiffDate }, + { "DAYS360" , ocGetDiffDate360 }, + { "DATEDIF" , ocGetDateDif }, + { "MIN" , ocMin }, + { "MINA" , ocMinA }, + { "MAX" , ocMax }, + { "MAXA" , ocMaxA }, + { "SUM" , ocSum }, + { "PRODUCT" , ocProduct }, + { "AVERAGE" , ocAverage }, + { "AVERAGEA" , ocAverageA }, + { "COUNT" , ocCount }, + { "COUNTA" , ocCount2 }, + { "NPV" , ocNPV }, + { "IRR" , ocIRR }, + { "MIRR" , ocMIRR }, + { "ISPMT" , ocISPMT }, + { "VAR" , ocVar }, + { "VARA" , ocVarA }, + { "VARP" , ocVarP }, + { "VARPA" , ocVarPA }, + { "VAR.P" , ocVarP_MS }, + { "VAR.S" , ocVarS }, + { "STDEV" , ocStDev }, + { "STDEVA" , ocStDevA }, + { "STDEVP" , ocStDevP }, + { "STDEVPA" , ocStDevPA }, + { "STDEV.P" , ocStDevP_MS }, + { "STDEV.S" , ocStDevS }, + { "B" , ocB }, + { "NORMDIST" , ocNormDist }, + { "NORM.DIST" , ocNormDist_MS }, + { "EXPONDIST" , ocExpDist }, + { "EXPON.DIST" , ocExpDist_MS }, + { "BINOMDIST" , ocBinomDist }, + { "BINOM.DIST" , ocBinomDist_MS }, + { "POISSON" , ocPoissonDist }, + { "POISSON.DIST" , ocPoissonDist_MS }, + { "COMBIN" , ocCombin }, + { "COMBINA" , ocCombinA }, + { "PERMUT" , ocPermut }, + { "PERMUTATIONA" , ocPermutationA }, + { "PV" , ocPV }, + { "SYD" , ocSYD }, + { "DDB" , ocDDB }, + { "DB" , ocDB }, + { "VDB" , ocVBD }, + { "DURATION" , ocPDuration }, + { "SLN" , ocSLN }, + { "PMT" , ocPMT }, + { "COLUMNS" , ocColumns }, + { "ROWS" , ocRows }, + { "SHEETS" , ocSheets }, + { "COLUMN" , ocColumn }, + { "ROW" , ocRow }, + { "SHEET" , ocSheet }, + { "ZGZ" , ocRRI }, + { "FV" , ocFV }, + { "NPER" , ocNper }, + { "RATE" , ocRate }, + { "IPMT" , ocIpmt }, + { "PPMT" , ocPpmt }, + { "CUMIPMT" , ocCumIpmt }, + { "CUMPRINC" , ocCumPrinc }, + { "EFFECTIVE" , ocEffect }, + { "NOMINAL" , ocNominal }, + { "SUBTOTAL" , ocSubTotal }, + { "DSUM" , ocDBSum }, + { "DCOUNT" , ocDBCount }, + { "DCOUNTA" , ocDBCount2 }, + { "DAVERAGE" , ocDBAverage }, + { "DGET" , ocDBGet }, + { "DMAX" , ocDBMax }, + { "DMIN" , ocDBMin }, + { "DPRODUCT" , ocDBProduct }, + { "DSTDEV" , ocDBStdDev }, + { "DSTDEVP" , ocDBStdDevP }, + { "DVAR" , ocDBVar }, + { "DVARP" , ocDBVarP }, + { "INDIRECT" , ocIndirect }, + { "ADDRESS" , ocAddress }, + { "MATCH" , ocMatch }, + { "XMATCH" , ocXMatch }, + { "COUNTBLANK" , ocCountEmptyCells }, + { "COUNTIF" , ocCountIf }, + { "SUMIF" , ocSumIf }, + { "AVERAGEIF" , ocAverageIf }, + { "SUMIFS" , ocSumIfs }, + { "AVERAGEIFS" , ocAverageIfs }, + { "COUNTIFS" , ocCountIfs }, + { "LOOKUP" , ocLookup }, + { "VLOOKUP" , ocVLookup }, + { "XLOOKUP" , ocXLookup }, + { "HLOOKUP" , ocHLookup }, + { "FILTER" , ocFilter }, + { "SORT" , ocSort }, + { "SORTBY" , ocSortBy }, + { "CHOOSECOLS" , ocChooseCols }, + { "CHOOSEROWS" , ocChooseRows }, + { "DROP" , ocDrop }, + { "EXPAND" , ocExpand }, + { "HSTACK" , ocHStack }, + { "VSTACK" , ocVStack }, + { "TAKE" , ocTake }, + { "TEXTAFTER" , ocTextAfter }, + { "TEXTBEFORE" , ocTextBefore }, + { "TEXTSPLIT" , ocTextSplit }, + { "TOCOL" , ocToCol }, + { "TOROW" , ocToRow }, + { "UNIQUE" , ocUnique }, + { "LET" , ocLet }, + { "WRAPCOLS" , ocWrapCols }, + { "WRAPROWS" , ocWrapRows }, + { "LAMBDA" , ocLambda }, + { "ISOMITTED" , ocIsOmitted }, + { "BYCOL" , ocByCol }, + { "BYROW" , ocByRow }, + { "MAKEARRAY" , ocMakeArray }, + { "MAP" , ocMap }, + { "REDUCE" , ocReduce }, + { "SCAN" , ocScan }, + { "ARRAYTOTEXT" , ocArrayToText }, + { "MULTIRANGE" , ocMultiArea }, // legacy for range list (union) + { "OFFSET" , ocOffset }, + { "INDEX" , ocIndex }, // ?? first character = I ?? + { "AREAS" , ocAreas }, + { "DOLLAR" , ocCurrency }, + { "REPLACE" , ocReplace }, + { "FIXED" , ocFixed }, + { "FIND" , ocFind }, + { "EXACT" , ocExact }, + { "LEFT" , ocLeft }, + { "RIGHT" , ocRight }, + { "SEARCH" , ocSearch }, + { "MID" , ocMid }, + { "LENB" , ocLenB }, + { "RIGHTB" , ocRightB }, + { "LEFTB" , ocLeftB }, + { "REPLACEB" , ocReplaceB }, + { "FINDB" , ocFindB }, + { "SEARCHB" , ocSearchB }, + { "MIDB" , ocMidB }, + { "TEXT" , ocText }, + { "SUBSTITUTE" , ocSubstitute }, + { "REPT" , ocRept }, + { "CONCATENATE" , ocConcat }, + { "CONCAT" , ocConcat_MS }, + { "TEXTJOIN" , ocTextJoin_MS }, + { "IFS" , ocIfs_MS }, + { "SWITCH" , ocSwitch_MS }, + { "MINIFS" , ocMinIfs_MS }, + { "MAXIFS" , ocMaxIfs_MS }, + { "MVALUE" , ocMatValue }, + { "MDETERM" , ocMatDet }, + { "MINVERSE" , ocMatInv }, + { "MMULT" , ocMatMult }, + { "SEQUENCE" , ocMatSequence }, + { "TRANSPOSE" , ocMatTrans }, + { "MUNIT" , ocMatrixUnit }, + { "GOALSEEK" , ocBackSolver }, + { "HYPGEOMDIST" , ocHypGeomDist }, + { "HYPGEOM.DIST" , ocHypGeomDist_MS }, + { "LOGNORMDIST" , ocLogNormDist }, + { "LOGNORM.DIST" , ocLogNormDist_MS }, + { "TDIST" , ocTDist }, + { "T.DIST.2T" , ocTDist_2T }, + { "T.DIST" , ocTDist_MS }, + { "T.DIST.RT" , ocTDist_RT }, + { "FDIST" , ocFDist }, + { "F.DIST" , ocFDist_LT }, + { "F.DIST.RT" , ocFDist_RT }, + { "CHIDIST" , ocChiDist }, + { "CHISQ.DIST.RT" , ocChiDist_MS }, + { "WEIBULL" , ocWeibull }, + { "WEIBULL.DIST" , ocWeibull_MS }, + { "NEGBINOMDIST" , ocNegBinomVert }, + { "NEGBINOM.DIST" , ocNegBinomDist_MS }, + { "CRITBINOM" , ocCritBinom }, + { "BINOM.INV" , ocBinomInv }, + { "KURT" , ocKurt }, + { "HARMEAN" , ocHarMean }, + { "GEOMEAN" , ocGeoMean }, + { "STANDARDIZE" , ocStandard }, + { "AVEDEV" , ocAveDev }, + { "SKEW" , ocSkew }, + { "SKEWP" , ocSkewp }, + { "DEVSQ" , ocDevSq }, + { "MEDIAN" , ocMedian }, + { "MODE" , ocModalValue }, + { "MODE.SNGL" , ocModalValue_MS }, + { "MODE.MULT" , ocModalValue_Multi }, + { "ZTEST" , ocZTest }, + { "Z.TEST" , ocZTest_MS }, + { "AGGREGATE" , ocAggregate }, + { "TTEST" , ocTTest }, + { "T.TEST" , ocTTest_MS }, + { "RANK" , ocRank }, + { "PERCENTILE" , ocPercentile }, + { "PERCENTRANK" , ocPercentrank }, + { "PERCENTILE.INC" , ocPercentile_Inc }, + { "PERCENTRANK.INC" , ocPercentrank_Inc }, + { "QUARTILE.INC" , ocQuartile_Inc }, + { "RANK.EQ" , ocRank_Eq }, + { "PERCENTILE.EXC" , ocPercentile_Exc }, + { "PERCENTRANK.EXC" , ocPercentrank_Exc }, + { "QUARTILE.EXC" , ocQuartile_Exc }, + { "RANK.AVG" , ocRank_Avg }, + { "LARGE" , ocLarge }, + { "SMALL" , ocSmall }, + { "FREQUENCY" , ocFrequency }, + { "QUARTILE" , ocQuartile }, + { "NORMINV" , ocNormInv }, + { "NORM.INV" , ocNormInv_MS }, + { "CONFIDENCE" , ocConfidence }, + { "CONFIDENCE.NORM" , ocConfidence_N }, + { "CONFIDENCE.T" , ocConfidence_T }, + { "FTEST" , ocFTest }, + { "F.TEST" , ocFTest_MS }, + { "TRIMMEAN" , ocTrimMean }, + { "PROB" , ocProb }, + { "CORREL" , ocCorrel }, + { "COVAR" , ocCovar }, + { "COVARIANCE.P" , ocCovarianceP }, + { "COVARIANCE.S" , ocCovarianceS }, + { "PEARSON" , ocPearson }, + { "RSQ" , ocRSQ }, + { "STEYX" , ocSTEYX }, + { "SLOPE" , ocSlope }, + { "INTERCEPT" , ocIntercept }, + { "TREND" , ocTrend }, + { "GROWTH" , ocGrowth }, + { "LINEST" , ocLinest }, + { "LOGEST" , ocLogest }, + { "FORECAST" , ocForecast }, + { "FORECAST.ETS.ADD" , ocForecast_ETS_ADD }, + { "FORECAST.ETS.SEASONALITY" , ocForecast_ETS_SEA }, + { "FORECAST.ETS.MULT" , ocForecast_ETS_MUL }, + { "FORECAST.ETS.PI.ADD" , ocForecast_ETS_PIA }, + { "FORECAST.ETS.PI.MULT" , ocForecast_ETS_PIM }, + { "FORECAST.ETS.STAT.ADD" , ocForecast_ETS_STA }, + { "FORECAST.ETS.STAT.MULT" , ocForecast_ETS_STM }, + { "FORECAST.LINEAR" , ocForecast_LIN }, + { "CHIINV" , ocChiInv }, + { "CHISQ.INV.RT" , ocChiInv_MS }, + { "GAMMADIST" , ocGammaDist }, + { "GAMMA.DIST" , ocGammaDist_MS }, + { "GAMMAINV" , ocGammaInv }, + { "GAMMA.INV" , ocGammaInv_MS }, + { "TINV" , ocTInv }, + { "T.INV.2T" , ocTInv_2T }, + { "T.INV" , ocTInv_MS }, + { "FINV" , ocFInv }, + { "F.INV" , ocFInv_LT }, + { "F.INV.RT" , ocFInv_RT }, + { "CHITEST" , ocChiTest }, + { "CHISQ.TEST" , ocChiTest_MS }, + { "LOGINV" , ocLogInv }, + { "LOGNORM.INV" , ocLogInv_MS }, + { "TABLE" , ocTableOp }, + { "BETADIST" , ocBetaDist }, + { "BETAINV" , ocBetaInv }, + { "BETA.DIST" , ocBetaDist_MS }, + { "BETA.INV" , ocBetaInv_MS }, + { "WEEKNUM" , ocWeek }, + { "ISOWEEKNUM" , ocIsoWeeknum }, + { "WEEKNUM_OOO" , ocWeeknumOOo }, + { "EASTERSUNDAY" , ocEasterSunday }, + { "WEEKDAY" , ocGetDayOfWeek }, + { "NETWORKDAYS" , ocNetWorkdays }, + { "NETWORKDAYS.INTL" , ocNetWorkdays_MS }, + { "WORKDAY.INTL" , ocWorkday_MS }, + { "#NAME!" , ocNoName }, + { "STYLE" , ocStyle }, + { "DDE" , ocDde }, + { "BASE" , ocBase }, + { "DECIMAL" , ocDecimal }, + { "CONVERT" , ocConvertOOo }, + { "ROMAN" , ocRoman }, + { "ARABIC" , ocArabic }, + { "HYPERLINK" , ocHyperLink }, + { "INFO" , ocInfo }, + { "BAHTTEXT" , ocBahtText }, + { "GETPIVOTDATA" , ocGetPivotData }, + { "EUROCONVERT" , ocEuroConvert }, + { "NUMBERVALUE" , ocNumberValue }, + { "GAMMA" , ocGamma }, + { "CHISQDIST" , ocChiSqDist }, + { "CHISQ.DIST" , ocChiSqDist_MS }, + { "CHISQ.INV" , ocChiSqInv_MS }, + { "CHISQINV" , ocChiSqInv }, + { "BITAND" , ocBitAnd }, + { "BITOR" , ocBitOr }, + { "BITXOR" , ocBitXor }, + { "BITRSHIFT" , ocBitRshift }, + { "BITLSHIFT" , ocBitLshift }, + { "#NULL!" , ocErrNull }, + { "#DIV/0!" , ocErrDivZero }, + { "#VALUE!" , ocErrValue }, + { "#REF!" , ocErrRef }, + { "#NAME?" , ocErrName }, + { "#NUM!" , ocErrNum }, + { "#N/A" , ocErrNA }, + { "#SPILL!" , ocErrSpill }, /* END defined ERROR.TYPE() values. */ - { "FILTERXML" , SC_OPCODE_FILTERXML }, - { "WEBSERVICE" , SC_OPCODE_WEBSERVICE }, - { "COLOR" , SC_OPCODE_COLOR }, - { "ERF.PRECISE" , SC_OPCODE_ERF_MS }, - { "ERFC.PRECISE" , SC_OPCODE_ERFC_MS }, - { "ENCODEURL" , SC_OPCODE_ENCODEURL }, - { "RAWSUBTRACT" , SC_OPCODE_RAWSUBTRACT }, - { "ROUNDSIG" , SC_OPCODE_ROUNDSIG }, - { "REGEX" , SC_OPCODE_REGEX }, - { "FOURIER", SC_OPCODE_FOURIER }, - { "RAND.NV" , SC_OPCODE_RANDOM_NV }, - { "RANDBETWEEN.NV" , SC_OPCODE_RANDBETWEEN_NV }, - { "RANDARRAY" , SC_OPCODE_RANDARRAY }, + { "FILTERXML" , ocFilterXML }, + { "WEBSERVICE" , ocWebservice }, + { "COLOR" , ocColor }, + { "ERF.PRECISE" , ocErf_MS }, + { "ERFC.PRECISE" , ocErfc_MS }, + { "ENCODEURL" , ocEncodeURL }, + { "RAWSUBTRACT" , ocRawSubtract }, + { "ROUNDSIG" , ocRoundSig }, + { "REGEX" , ocRegex }, + { "FOURIER", ocFourier }, + { "RAND.NV" , ocRandomNV }, + { "RANDBETWEEN.NV" , ocRandbetweenNV }, + { "RANDARRAY" , ocRandArray }, { nullptr, -1 } }; @@ -1920,469 +1970,481 @@ const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_API[] = // at the same time. const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH[] = { - { "IF" , SC_OPCODE_IF }, - { "IFERROR" , SC_OPCODE_IF_ERROR }, - { "IFNA" , SC_OPCODE_IF_NA }, - { "CHOOSE" , SC_OPCODE_CHOOSE }, - { "(" , SC_OPCODE_OPEN }, - { ")" , SC_OPCODE_CLOSE }, - { "[" , SC_OPCODE_TABLE_REF_OPEN }, - { "]" , SC_OPCODE_TABLE_REF_CLOSE }, - { "#All" , SC_OPCODE_TABLE_REF_ITEM_ALL }, - { "#Headers" , SC_OPCODE_TABLE_REF_ITEM_HEADERS }, - { "#Data" , SC_OPCODE_TABLE_REF_ITEM_DATA }, - { "#Totals" , SC_OPCODE_TABLE_REF_ITEM_TOTALS }, - { "#This Row" , SC_OPCODE_TABLE_REF_ITEM_THIS_ROW }, - { "{" , SC_OPCODE_ARRAY_OPEN }, - { "}" , SC_OPCODE_ARRAY_CLOSE }, - { "|" , SC_OPCODE_ARRAY_ROW_SEP }, - { ";" , SC_OPCODE_ARRAY_COL_SEP }, - { ";" , SC_OPCODE_SEP }, - { "%" , SC_OPCODE_PERCENT_SIGN }, - { "+" , SC_OPCODE_ADD }, - { "-" , SC_OPCODE_SUB }, - { "*" , SC_OPCODE_MUL }, - { "/" , SC_OPCODE_DIV }, - { "&" , SC_OPCODE_AMPERSAND }, - { "^" , SC_OPCODE_POW }, - { "=" , SC_OPCODE_EQUAL }, - { "<>" , SC_OPCODE_NOT_EQUAL }, - { "<" , SC_OPCODE_LESS }, - { ">" , SC_OPCODE_GREATER }, - { "<=" , SC_OPCODE_LESS_EQUAL }, - { ">=" , SC_OPCODE_GREATER_EQUAL }, - { "AND" , SC_OPCODE_AND }, - { "OR" , SC_OPCODE_OR }, - { "XOR" , SC_OPCODE_XOR }, - { "!" , SC_OPCODE_INTERSECT }, - { "~" , SC_OPCODE_UNION }, - { ":" , SC_OPCODE_RANGE }, - { "NOT" , SC_OPCODE_NOT }, - { "NEG" , SC_OPCODE_NEG }, - { "-" , SC_OPCODE_NEG_SUB }, - { "PI" , SC_OPCODE_PI }, - { "RAND" , SC_OPCODE_RANDOM }, - { "TRUE" , SC_OPCODE_TRUE }, - { "FALSE" , SC_OPCODE_FALSE }, - { "TODAY" , SC_OPCODE_GET_ACT_DATE }, - { "NOW" , SC_OPCODE_GET_ACT_TIME }, - { "NA" , SC_OPCODE_NO_VALUE }, - { "CURRENT" , SC_OPCODE_CURRENT }, - { "DEGREES" , SC_OPCODE_DEG }, - { "RADIANS" , SC_OPCODE_RAD }, - { "SIN" , SC_OPCODE_SIN }, - { "COS" , SC_OPCODE_COS }, - { "TAN" , SC_OPCODE_TAN }, - { "COT" , SC_OPCODE_COT }, - { "ASIN" , SC_OPCODE_ARC_SIN }, - { "ACOS" , SC_OPCODE_ARC_COS }, - { "ATAN" , SC_OPCODE_ARC_TAN }, - { "ACOT" , SC_OPCODE_ARC_COT }, - { "SINH" , SC_OPCODE_SIN_HYP }, - { "COSH" , SC_OPCODE_COS_HYP }, - { "TANH" , SC_OPCODE_TAN_HYP }, - { "COTH" , SC_OPCODE_COT_HYP }, - { "ASINH" , SC_OPCODE_ARC_SIN_HYP }, - { "ACOSH" , SC_OPCODE_ARC_COS_HYP }, - { "ATANH" , SC_OPCODE_ARC_TAN_HYP }, - { "ACOTH" , SC_OPCODE_ARC_COT_HYP }, - { "CSC" , SC_OPCODE_COSECANT }, - { "SEC" , SC_OPCODE_SECANT }, - { "CSCH" , SC_OPCODE_COSECANT_HYP }, - { "SECH" , SC_OPCODE_SECANT_HYP }, - { "EXP" , SC_OPCODE_EXP }, - { "LN" , SC_OPCODE_LN }, - { "SQRT" , SC_OPCODE_SQRT }, - { "FACT" , SC_OPCODE_FACT }, - { "YEAR" , SC_OPCODE_GET_YEAR }, - { "MONTH" , SC_OPCODE_GET_MONTH }, - { "DAY" , SC_OPCODE_GET_DAY }, - { "HOUR" , SC_OPCODE_GET_HOUR }, - { "MINUTE" , SC_OPCODE_GET_MIN }, - { "SECOND" , SC_OPCODE_GET_SEC }, - { "SIGN" , SC_OPCODE_PLUS_MINUS }, - { "ABS" , SC_OPCODE_ABS }, - { "INT" , SC_OPCODE_INT }, - { "PHI" , SC_OPCODE_PHI }, - { "GAUSS" , SC_OPCODE_GAUSS }, - { "ISBLANK" , SC_OPCODE_IS_EMPTY }, - { "ISTEXT" , SC_OPCODE_IS_STRING }, - { "ISNONTEXT" , SC_OPCODE_IS_NON_STRING }, - { "ISLOGICAL" , SC_OPCODE_IS_LOGICAL }, - { "TYPE" , SC_OPCODE_TYPE }, - { "CELL" , SC_OPCODE_CELL }, - { "ISREF" , SC_OPCODE_IS_REF }, - { "ISNUMBER" , SC_OPCODE_IS_VALUE }, - { "ISFORMULA" , SC_OPCODE_IS_FORMULA }, - { "ISNA" , SC_OPCODE_IS_NV }, - { "ISERR" , SC_OPCODE_IS_ERR }, - { "ISERROR" , SC_OPCODE_IS_ERROR }, - { "ISEVEN" , SC_OPCODE_IS_EVEN }, - { "ISODD" , SC_OPCODE_IS_ODD }, - { "N" , SC_OPCODE_N }, - { "DATEVALUE" , SC_OPCODE_GET_DATE_VALUE }, - { "TIMEVALUE" , SC_OPCODE_GET_TIME_VALUE }, - { "CODE" , SC_OPCODE_CODE }, - { "TRIM" , SC_OPCODE_TRIM }, - { "UPPER" , SC_OPCODE_UPPER }, - { "PROPER" , SC_OPCODE_PROPER }, - { "LOWER" , SC_OPCODE_LOWER }, - { "LEN" , SC_OPCODE_LEN }, - { "T" , SC_OPCODE_T }, - { "VALUE" , SC_OPCODE_VALUE }, - { "CLEAN" , SC_OPCODE_CLEAN }, - { "CHAR" , SC_OPCODE_CHAR }, - { "JIS" , SC_OPCODE_JIS }, - { "ASC" , SC_OPCODE_ASC }, - { "UNICODE" , SC_OPCODE_UNICODE }, - { "UNICHAR" , SC_OPCODE_UNICHAR }, - { "LOG10" , SC_OPCODE_LOG10 }, - { "EVEN" , SC_OPCODE_EVEN }, - { "ODD" , SC_OPCODE_ODD }, - { "NORMSDIST" , SC_OPCODE_STD_NORM_DIST }, - { "NORM.S.DIST" , SC_OPCODE_STD_NORM_DIST_MS }, - { "FISHER" , SC_OPCODE_FISHER }, - { "FISHERINV" , SC_OPCODE_FISHER_INV }, - { "NORMSINV" , SC_OPCODE_S_NORM_INV }, - { "NORM.S.INV" , SC_OPCODE_S_NORM_INV_MS }, - { "GAMMALN" , SC_OPCODE_GAMMA_LN }, - { "GAMMALN.PRECISE" , SC_OPCODE_GAMMA_LN_MS }, - { "ERRORTYPE" , SC_OPCODE_ERROR_TYPE }, - { "ERROR.TYPE" , SC_OPCODE_ERROR_TYPE_ODF }, - { "FORMULA" , SC_OPCODE_FORMULA }, - { "ATAN2" , SC_OPCODE_ARC_TAN_2 }, - { "CEILING.MATH" , SC_OPCODE_CEIL_MATH }, - { "CEILING" , SC_OPCODE_CEIL }, - { "CEILING.XCL" , SC_OPCODE_CEIL_MS }, - { "CEILING.PRECISE" , SC_OPCODE_CEIL_PRECISE }, - { "ISO.CEILING" , SC_OPCODE_CEIL_ISO }, - { "FLOOR" , SC_OPCODE_FLOOR }, - { "FLOOR.XCL" , SC_OPCODE_FLOOR_MS }, - { "FLOOR.MATH" , SC_OPCODE_FLOOR_MATH }, - { "FLOOR.PRECISE" , SC_OPCODE_FLOOR_PRECISE }, - { "ROUND" , SC_OPCODE_ROUND }, - { "ROUNDUP" , SC_OPCODE_ROUND_UP }, - { "ROUNDDOWN" , SC_OPCODE_ROUND_DOWN }, - { "TRUNC" , SC_OPCODE_TRUNC }, - { "LOG" , SC_OPCODE_LOG }, - { "POWER" , SC_OPCODE_POWER }, - { "GCD" , SC_OPCODE_GCD }, - { "LCM" , SC_OPCODE_LCM }, - { "MOD" , SC_OPCODE_MOD }, - { "SUMPRODUCT" , SC_OPCODE_SUM_PRODUCT }, - { "SUMSQ" , SC_OPCODE_SUM_SQ }, - { "SUMX2MY2" , SC_OPCODE_SUM_X2MY2 }, - { "SUMX2PY2" , SC_OPCODE_SUM_X2DY2 }, - { "SUMXMY2" , SC_OPCODE_SUM_XMY2 }, - { "DATE" , SC_OPCODE_GET_DATE }, - { "TIME" , SC_OPCODE_GET_TIME }, - { "DAYS" , SC_OPCODE_GET_DIFF_DATE }, - { "DAYS360" , SC_OPCODE_GET_DIFF_DATE_360 }, - { "DATEDIF" , SC_OPCODE_GET_DATEDIF }, - { "MIN" , SC_OPCODE_MIN }, - { "MINA" , SC_OPCODE_MIN_A }, - { "MAX" , SC_OPCODE_MAX }, - { "MAXA" , SC_OPCODE_MAX_A }, - { "SUM" , SC_OPCODE_SUM }, - { "PRODUCT" , SC_OPCODE_PRODUCT }, - { "AVERAGE" , SC_OPCODE_AVERAGE }, - { "AVERAGEA" , SC_OPCODE_AVERAGE_A }, - { "COUNT" , SC_OPCODE_COUNT }, - { "COUNTA" , SC_OPCODE_COUNT_2 }, - { "NPV" , SC_OPCODE_NPV }, - { "IRR" , SC_OPCODE_IRR }, - { "MIRR" , SC_OPCODE_MIRR }, - { "ISPMT" , SC_OPCODE_ISPMT }, - { "VAR" , SC_OPCODE_VAR }, - { "VARA" , SC_OPCODE_VAR_A }, - { "VARP" , SC_OPCODE_VAR_P }, - { "VARPA" , SC_OPCODE_VAR_P_A }, - { "VAR.P" , SC_OPCODE_VAR_P_MS }, - { "VAR.S" , SC_OPCODE_VAR_S }, - { "STDEV" , SC_OPCODE_ST_DEV }, - { "STDEVA" , SC_OPCODE_ST_DEV_A }, - { "STDEVP" , SC_OPCODE_ST_DEV_P }, - { "STDEVPA" , SC_OPCODE_ST_DEV_P_A }, - { "STDEV.P" , SC_OPCODE_ST_DEV_P_MS }, - { "STDEV.S" , SC_OPCODE_ST_DEV_S }, - { "B" , SC_OPCODE_B }, - { "NORMDIST" , SC_OPCODE_NORM_DIST }, - { "NORM.DIST" , SC_OPCODE_NORM_DIST_MS }, - { "EXPONDIST" , SC_OPCODE_EXP_DIST }, - { "EXPON.DIST" , SC_OPCODE_EXP_DIST_MS }, - { "BINOMDIST" , SC_OPCODE_BINOM_DIST }, - { "BINOM.DIST" , SC_OPCODE_BINOM_DIST_MS }, - { "POISSON" , SC_OPCODE_POISSON_DIST }, - { "POISSON.DIST" , SC_OPCODE_POISSON_DIST_MS }, - { "COMBIN" , SC_OPCODE_COMBIN }, - { "COMBINA" , SC_OPCODE_COMBIN_A }, - { "PERMUT" , SC_OPCODE_PERMUT }, - { "PERMUTATIONA" , SC_OPCODE_PERMUTATION_A }, - { "PV" , SC_OPCODE_PV }, - { "SYD" , SC_OPCODE_SYD }, - { "DDB" , SC_OPCODE_DDB }, - { "DB" , SC_OPCODE_DB }, - { "VDB" , SC_OPCODE_VBD }, - { "PDURATION" , SC_OPCODE_PDURATION }, - { "SLN" , SC_OPCODE_SLN }, - { "PMT" , SC_OPCODE_PMT }, - { "COLUMNS" , SC_OPCODE_COLUMNS }, - { "ROWS" , SC_OPCODE_ROWS }, - { "SHEETS" , SC_OPCODE_SHEETS }, - { "COLUMN" , SC_OPCODE_COLUMN }, - { "ROW" , SC_OPCODE_ROW }, - { "SHEET" , SC_OPCODE_SHEET }, - { "ZGZ" , SC_OPCODE_RRI }, - { "FV" , SC_OPCODE_FV }, - { "NPER" , SC_OPCODE_NPER }, - { "RATE" , SC_OPCODE_RATE }, - { "IPMT" , SC_OPCODE_IPMT }, - { "PPMT" , SC_OPCODE_PPMT }, - { "CUMIPMT" , SC_OPCODE_CUM_IPMT }, - { "CUMPRINC" , SC_OPCODE_CUM_PRINC }, - { "EFFECT" , SC_OPCODE_EFFECT }, - { "NOMINAL" , SC_OPCODE_NOMINAL }, - { "SUBTOTAL" , SC_OPCODE_SUB_TOTAL }, - { "DSUM" , SC_OPCODE_DB_SUM }, - { "DCOUNT" , SC_OPCODE_DB_COUNT }, - { "DCOUNTA" , SC_OPCODE_DB_COUNT_2 }, - { "DAVERAGE" , SC_OPCODE_DB_AVERAGE }, - { "DGET" , SC_OPCODE_DB_GET }, - { "DMAX" , SC_OPCODE_DB_MAX }, - { "DMIN" , SC_OPCODE_DB_MIN }, - { "DPRODUCT" , SC_OPCODE_DB_PRODUCT }, - { "DSTDEV" , SC_OPCODE_DB_STD_DEV }, - { "DSTDEVP" , SC_OPCODE_DB_STD_DEV_P }, - { "DVAR" , SC_OPCODE_DB_VAR }, - { "DVARP" , SC_OPCODE_DB_VAR_P }, - { "INDIRECT" , SC_OPCODE_INDIRECT }, - { "ADDRESS" , SC_OPCODE_ADDRESS }, - { "MATCH" , SC_OPCODE_MATCH }, - { "XMATCH" , SC_OPCODE_X_MATCH }, - { "COUNTBLANK" , SC_OPCODE_COUNT_EMPTY_CELLS }, - { "COUNTIF" , SC_OPCODE_COUNT_IF }, - { "SUMIF" , SC_OPCODE_SUM_IF }, - { "AVERAGEIF" , SC_OPCODE_AVERAGE_IF }, - { "SUMIFS" , SC_OPCODE_SUM_IFS }, - { "AVERAGEIFS" , SC_OPCODE_AVERAGE_IFS }, - { "COUNTIFS" , SC_OPCODE_COUNT_IFS }, - { "LOOKUP" , SC_OPCODE_LOOKUP }, - { "VLOOKUP" , SC_OPCODE_V_LOOKUP }, - { "XLOOKUP" , SC_OPCODE_X_LOOKUP }, - { "HLOOKUP" , SC_OPCODE_H_LOOKUP }, - { "FILTER" , SC_OPCODE_FILTER }, - { "SORT" , SC_OPCODE_SORT }, - { "SORTBY" , SC_OPCODE_SORTBY }, - { "CHOOSECOLS" , SC_OPCODE_CHOOSECOLS }, - { "CHOOSEROWS" , SC_OPCODE_CHOOSEROWS }, - { "DROP" , SC_OPCODE_DROP }, - { "EXPAND" , SC_OPCODE_EXPAND }, - { "HSTACK" , SC_OPCODE_HSTACK }, - { "VSTACK" , SC_OPCODE_VSTACK }, - { "TAKE" , SC_OPCODE_TAKE }, - { "TEXTAFTER" , SC_OPCODE_TEXTAFTER }, - { "TEXTBEFORE" , SC_OPCODE_TEXTBEFORE }, - { "TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, - { "TOCOL" , SC_OPCODE_TOCOL }, - { "TOROW" , SC_OPCODE_TOROW }, - { "UNIQUE" , SC_OPCODE_UNIQUE }, - { "LET" , SC_OPCODE_LET }, - { "WRAPCOLS" , SC_OPCODE_WRAPCOLS }, - { "WRAPROWS" , SC_OPCODE_WRAPROWS }, - { "MULTIRANGE" , SC_OPCODE_MULTI_AREA }, - { "OFFSET" , SC_OPCODE_OFFSET }, - { "INDEX" , SC_OPCODE_INDEX }, - { "AREAS" , SC_OPCODE_AREAS }, - { "DOLLAR" , SC_OPCODE_CURRENCY }, - { "REPLACE" , SC_OPCODE_REPLACE }, - { "FIXED" , SC_OPCODE_FIXED }, - { "FIND" , SC_OPCODE_FIND }, - { "EXACT" , SC_OPCODE_EXACT }, - { "LEFT" , SC_OPCODE_LEFT }, - { "RIGHT" , SC_OPCODE_RIGHT }, - { "SEARCH" , SC_OPCODE_SEARCH }, - { "MID" , SC_OPCODE_MID }, - { "LENB" , SC_OPCODE_LENB }, - { "RIGHTB" , SC_OPCODE_RIGHTB }, - { "LEFTB" , SC_OPCODE_LEFTB }, - { "REPLACEB" , SC_OPCODE_REPLACEB }, - { "FINDB" , SC_OPCODE_FINDB }, - { "SEARCHB" , SC_OPCODE_SEARCHB }, - { "MIDB" , SC_OPCODE_MIDB }, - { "TEXT" , SC_OPCODE_TEXT }, - { "SUBSTITUTE" , SC_OPCODE_SUBSTITUTE }, - { "REPT" , SC_OPCODE_REPT }, - { "CONCATENATE" , SC_OPCODE_CONCAT }, - { "CONCAT" , SC_OPCODE_CONCAT_MS }, - { "TEXTJOIN" , SC_OPCODE_TEXTJOIN_MS }, - { "IFS" , SC_OPCODE_IFS_MS }, - { "SWITCH" , SC_OPCODE_SWITCH_MS }, - { "MINIFS" , SC_OPCODE_MINIFS_MS }, - { "MAXIFS" , SC_OPCODE_MAXIFS_MS }, - { "MVALUE" , SC_OPCODE_MAT_VALUE }, - { "MDETERM" , SC_OPCODE_MAT_DET }, - { "MINVERSE" , SC_OPCODE_MAT_INV }, - { "MMULT" , SC_OPCODE_MAT_MULT }, - { "SEQUENCE" , SC_OPCODE_MAT_SEQUENCE }, - { "TRANSPOSE" , SC_OPCODE_MAT_TRANS }, - { "MUNIT" , SC_OPCODE_MATRIX_UNIT }, - { "GOALSEEK" , SC_OPCODE_BACK_SOLVER }, - { "HYPGEOMDIST" , SC_OPCODE_HYP_GEOM_DIST }, - { "HYPGEOM.DIST" , SC_OPCODE_HYP_GEOM_DIST_MS }, - { "LOGNORMDIST" , SC_OPCODE_LOG_NORM_DIST }, - { "LOGNORM.DIST" , SC_OPCODE_LOG_NORM_DIST_MS }, - { "TDIST" , SC_OPCODE_T_DIST }, - { "T.DIST.2T" , SC_OPCODE_T_DIST_2T }, - { "T.DIST" , SC_OPCODE_T_DIST_MS }, - { "T.DIST.RT" , SC_OPCODE_T_DIST_RT }, - { "FDIST" , SC_OPCODE_F_DIST }, - { "F.DIST" , SC_OPCODE_F_DIST_LT }, - { "F.DIST.RT" , SC_OPCODE_F_DIST_RT }, - { "CHIDIST" , SC_OPCODE_CHI_DIST }, - { "CHISQ.DIST.RT" , SC_OPCODE_CHI_DIST_MS }, - { "WEIBULL" , SC_OPCODE_WEIBULL }, - { "WEIBULL.DIST" , SC_OPCODE_WEIBULL_MS }, - { "NEGBINOMDIST" , SC_OPCODE_NEG_BINOM_VERT }, - { "NEGBINOM.DIST" , SC_OPCODE_NEG_BINOM_DIST_MS }, - { "CRITBINOM" , SC_OPCODE_CRIT_BINOM }, - { "BINOM.INV" , SC_OPCODE_BINOM_INV }, - { "KURT" , SC_OPCODE_KURT }, - { "HARMEAN" , SC_OPCODE_HAR_MEAN }, - { "GEOMEAN" , SC_OPCODE_GEO_MEAN }, - { "STANDARDIZE" , SC_OPCODE_STANDARD }, - { "AVEDEV" , SC_OPCODE_AVE_DEV }, - { "SKEW" , SC_OPCODE_SKEW }, - { "SKEWP" , SC_OPCODE_SKEWP }, - { "DEVSQ" , SC_OPCODE_DEV_SQ }, - { "MEDIAN" , SC_OPCODE_MEDIAN }, - { "MODE" , SC_OPCODE_MODAL_VALUE }, - { "MODE.SNGL" , SC_OPCODE_MODAL_VALUE_MS }, - { "MODE.MULT" , SC_OPCODE_MODAL_VALUE_MULTI }, - { "ZTEST" , SC_OPCODE_Z_TEST }, - { "Z.TEST" , SC_OPCODE_Z_TEST_MS }, - { "AGGREGATE" , SC_OPCODE_AGGREGATE }, - { "TTEST" , SC_OPCODE_T_TEST }, - { "T.TEST" , SC_OPCODE_T_TEST_MS }, - { "RANK" , SC_OPCODE_RANK }, - { "PERCENTILE" , SC_OPCODE_PERCENTILE }, - { "PERCENTRANK" , SC_OPCODE_PERCENT_RANK }, - { "PERCENTILE.INC" , SC_OPCODE_PERCENTILE_INC }, - { "PERCENTRANK.INC" , SC_OPCODE_PERCENT_RANK_INC }, - { "QUARTILE.INC" , SC_OPCODE_QUARTILE_INC }, - { "RANK.EQ" , SC_OPCODE_RANK_EQ }, - { "PERCENTILE.EXC" , SC_OPCODE_PERCENTILE_EXC }, - { "PERCENTRANK.EXC" , SC_OPCODE_PERCENT_RANK_EXC }, - { "QUARTILE.EXC" , SC_OPCODE_QUARTILE_EXC }, - { "RANK.AVG" , SC_OPCODE_RANK_AVG }, - { "LARGE" , SC_OPCODE_LARGE }, - { "SMALL" , SC_OPCODE_SMALL }, - { "FREQUENCY" , SC_OPCODE_FREQUENCY }, - { "QUARTILE" , SC_OPCODE_QUARTILE }, - { "NORMINV" , SC_OPCODE_NORM_INV }, - { "NORM.INV" , SC_OPCODE_NORM_INV_MS }, - { "CONFIDENCE" , SC_OPCODE_CONFIDENCE }, - { "CONFIDENCE.NORM" , SC_OPCODE_CONFIDENCE_N }, - { "CONFIDENCE.T" , SC_OPCODE_CONFIDENCE_T }, - { "FTEST" , SC_OPCODE_F_TEST }, - { "F.TEST" , SC_OPCODE_F_TEST_MS }, - { "TRIMMEAN" , SC_OPCODE_TRIM_MEAN }, - { "PROB" , SC_OPCODE_PROB }, - { "CORREL" , SC_OPCODE_CORREL }, - { "COVAR" , SC_OPCODE_COVAR }, - { "COVARIANCE.P" , SC_OPCODE_COVARIANCE_P }, - { "COVARIANCE.S" , SC_OPCODE_COVARIANCE_S }, - { "PEARSON" , SC_OPCODE_PEARSON }, - { "RSQ" , SC_OPCODE_RSQ }, - { "STEYX" , SC_OPCODE_STEYX }, - { "SLOPE" , SC_OPCODE_SLOPE }, - { "INTERCEPT" , SC_OPCODE_INTERCEPT }, - { "TREND" , SC_OPCODE_TREND }, - { "GROWTH" , SC_OPCODE_GROWTH }, - { "LINEST" , SC_OPCODE_LINEST }, - { "LOGEST" , SC_OPCODE_LOGEST }, - { "FORECAST" , SC_OPCODE_FORECAST }, - { "FORECAST.ETS.ADD" , SC_OPCODE_FORECAST_ETS_ADD }, - { "FORECAST.ETS.SEASONALITY" , SC_OPCODE_FORECAST_ETS_SEA }, - { "FORECAST.ETS.MULT" , SC_OPCODE_FORECAST_ETS_MUL }, - { "FORECAST.ETS.PI.ADD" , SC_OPCODE_FORECAST_ETS_PIA }, - { "FORECAST.ETS.PI.MULT" , SC_OPCODE_FORECAST_ETS_PIM }, - { "FORECAST.ETS.STAT.ADD" , SC_OPCODE_FORECAST_ETS_STA }, - { "FORECAST.ETS.STAT.MULT" , SC_OPCODE_FORECAST_ETS_STM }, - { "FORECAST.LINEAR" , SC_OPCODE_FORECAST_LIN }, - { "CHIINV" , SC_OPCODE_CHI_INV }, - { "CHISQ.INV.RT" , SC_OPCODE_CHI_INV_MS }, - { "GAMMADIST" , SC_OPCODE_GAMMA_DIST }, - { "GAMMA.DIST" , SC_OPCODE_GAMMA_DIST_MS }, - { "GAMMAINV" , SC_OPCODE_GAMMA_INV }, - { "GAMMA.INV" , SC_OPCODE_GAMMA_INV_MS }, - { "TINV" , SC_OPCODE_T_INV }, - { "T.INV.2T" , SC_OPCODE_T_INV_2T }, - { "T.INV" , SC_OPCODE_T_INV_MS }, - { "FINV" , SC_OPCODE_F_INV }, - { "F.INV" , SC_OPCODE_F_INV_LT }, - { "F.INV.RT" , SC_OPCODE_F_INV_RT }, - { "CHITEST" , SC_OPCODE_CHI_TEST }, - { "CHISQ.TEST" , SC_OPCODE_CHI_TEST_MS }, - { "LOGINV" , SC_OPCODE_LOG_INV }, - { "LOGNORM.INV" , SC_OPCODE_LOG_INV_MS }, - { "TABLE" , SC_OPCODE_TABLE_OP }, - { "BETADIST" , SC_OPCODE_BETA_DIST }, - { "BETAINV" , SC_OPCODE_BETA_INV }, - { "BETA.DIST" , SC_OPCODE_BETA_DIST_MS }, - { "BETA.INV" , SC_OPCODE_BETA_INV_MS }, - { "WEEKNUM" , SC_OPCODE_WEEK }, - { "ISOWEEKNUM" , SC_OPCODE_ISOWEEKNUM }, - { "WEEKNUM_OOO" , SC_OPCODE_WEEKNUM_OOO }, - { "EASTERSUNDAY" , SC_OPCODE_EASTERSUNDAY }, - { "WEEKDAY" , SC_OPCODE_GET_DAY_OF_WEEK }, - { "NETWORKDAYS" , SC_OPCODE_NETWORKDAYS }, - { "NETWORKDAYS.INTL" , SC_OPCODE_NETWORKDAYS_MS }, - { "WORKDAY.INTL" , SC_OPCODE_WORKDAY_MS }, - { "#NAME!" , SC_OPCODE_NO_NAME }, - { "STYLE" , SC_OPCODE_STYLE }, - { "DDE" , SC_OPCODE_DDE }, - { "BASE" , SC_OPCODE_BASE }, - { "DECIMAL" , SC_OPCODE_DECIMAL }, - { "CONVERT_OOO" , SC_OPCODE_CONVERT_OOO }, - { "ROMAN" , SC_OPCODE_ROMAN }, - { "ARABIC" , SC_OPCODE_ARABIC }, - { "HYPERLINK" , SC_OPCODE_HYPERLINK }, - { "INFO" , SC_OPCODE_INFO }, - { "BAHTTEXT" , SC_OPCODE_BAHTTEXT }, - { "GETPIVOTDATA" , SC_OPCODE_GET_PIVOT_DATA }, - { "EUROCONVERT" , SC_OPCODE_EUROCONVERT }, - { "NUMBERVALUE" , SC_OPCODE_NUMBERVALUE }, - { "GAMMA" , SC_OPCODE_GAMMA }, - { "CHISQDIST" , SC_OPCODE_CHISQ_DIST }, - { "CHISQ.DIST" , SC_OPCODE_CHISQ_DIST_MS }, - { "CHISQ.INV" , SC_OPCODE_CHISQ_INV_MS }, - { "CHISQINV" , SC_OPCODE_CHISQ_INV }, - { "BITAND" , SC_OPCODE_BITAND }, - { "BITOR" , SC_OPCODE_BITOR }, - { "BITXOR" , SC_OPCODE_BITXOR }, - { "BITRSHIFT" , SC_OPCODE_BITRSHIFT }, - { "BITLSHIFT" , SC_OPCODE_BITLSHIFT }, - { "#NULL!" , SC_OPCODE_ERROR_NULL }, - { "#DIV/0!" , SC_OPCODE_ERROR_DIVZERO }, - { "#VALUE!" , SC_OPCODE_ERROR_VALUE }, - { "#REF!" , SC_OPCODE_ERROR_REF }, - { "#NAME?" , SC_OPCODE_ERROR_NAME }, - { "#NUM!" , SC_OPCODE_ERROR_NUM }, - { "#N/A" , SC_OPCODE_ERROR_NA }, + { "IF" , ocIf }, + { "IFERROR" , ocIfError }, + { "IFNA" , ocIfNA }, + { "CHOOSE" , ocChoose }, + { "(" , ocOpen }, + { ")" , ocClose }, + { "[" , ocTableRefOpen }, + { "]" , ocTableRefClose }, + { "#All" , ocTableRefItemAll }, + { "#Headers" , ocTableRefItemHeaders }, + { "#Data" , ocTableRefItemData }, + { "#Totals" , ocTableRefItemTotals }, + { "#This Row" , ocTableRefItemThisRow }, + { "{" , ocArrayOpen }, + { "}" , ocArrayClose }, + { "|" , ocArrayRowSep }, + { ";" , ocArrayColSep }, + { ";" , ocSep }, + { "%" , ocPercentSign }, + { "+" , ocAdd }, + { "-" , ocSub }, + { "*" , ocMul }, + { "/" , ocDiv }, + { "&" , ocAmpersand }, + { "^" , ocPow }, + { "=" , ocEqual }, + { "<>" , ocNotEqual }, + { "<" , ocLess }, + { ">" , ocGreater }, + { "<=" , ocLessEqual }, + { ">=" , ocGreaterEqual }, + { "AND" , ocAnd }, + { "OR" , ocOr }, + { "XOR" , ocXor }, + { "!" , ocIntersect }, + { "~" , ocUnion }, + { ":" , ocRange }, + { "NOT" , ocNot }, + { "NEG" , ocNeg }, + { "-" , ocNegSub }, + { "@" , ocSingleValue }, + { "#" , ocSpill }, + { "PI" , ocPi }, + { "RAND" , ocRandom }, + { "TRUE" , ocTrue }, + { "FALSE" , ocFalse }, + { "TODAY" , ocGetActDate }, + { "NOW" , ocGetActTime }, + { "NA" , ocNotAvail }, + { "CURRENT" , ocCurrent }, + { "DEGREES" , ocDeg }, + { "RADIANS" , ocRad }, + { "SIN" , ocSin }, + { "COS" , ocCos }, + { "TAN" , ocTan }, + { "COT" , ocCot }, + { "ASIN" , ocArcSin }, + { "ACOS" , ocArcCos }, + { "ATAN" , ocArcTan }, + { "ACOT" , ocArcCot }, + { "SINH" , ocSinHyp }, + { "COSH" , ocCosHyp }, + { "TANH" , ocTanHyp }, + { "COTH" , ocCotHyp }, + { "ASINH" , ocArcSinHyp }, + { "ACOSH" , ocArcCosHyp }, + { "ATANH" , ocArcTanHyp }, + { "ACOTH" , ocArcCotHyp }, + { "CSC" , ocCosecant }, + { "SEC" , ocSecant }, + { "CSCH" , ocCosecantHyp }, + { "SECH" , ocSecantHyp }, + { "EXP" , ocExp }, + { "LN" , ocLn }, + { "SQRT" , ocSqrt }, + { "FACT" , ocFact }, + { "YEAR" , ocGetYear }, + { "MONTH" , ocGetMonth }, + { "DAY" , ocGetDay }, + { "HOUR" , ocGetHour }, + { "MINUTE" , ocGetMin }, + { "SECOND" , ocGetSec }, + { "SIGN" , ocPlusMinus }, + { "ABS" , ocAbs }, + { "INT" , ocInt }, + { "PHI" , ocPhi }, + { "GAUSS" , ocGauss }, + { "ISBLANK" , ocIsEmpty }, + { "ISTEXT" , ocIsString }, + { "ISNONTEXT" , ocIsNonString }, + { "ISLOGICAL" , ocIsLogical }, + { "TYPE" , ocType }, + { "CELL" , ocCell }, + { "ISREF" , ocIsRef }, + { "ISNUMBER" , ocIsValue }, + { "ISFORMULA" , ocIsFormula }, + { "ISNA" , ocIsNA }, + { "ISERR" , ocIsErr }, + { "ISERROR" , ocIsError }, + { "ISEVEN" , ocIsEven }, + { "ISODD" , ocIsOdd }, + { "N" , ocN }, + { "DATEVALUE" , ocGetDateValue }, + { "TIMEVALUE" , ocGetTimeValue }, + { "CODE" , ocCode }, + { "TRIM" , ocTrim }, + { "UPPER" , ocUpper }, + { "PROPER" , ocProper }, + { "LOWER" , ocLower }, + { "LEN" , ocLen }, + { "T" , ocT }, + { "VALUE" , ocValue }, + { "CLEAN" , ocClean }, + { "CHAR" , ocChar }, + { "JIS" , ocJis }, + { "ASC" , ocAsc }, + { "UNICODE" , ocUnicode }, + { "UNICHAR" , ocUnichar }, + { "LOG10" , ocLog10 }, + { "EVEN" , ocEven }, + { "ODD" , ocOdd }, + { "NORMSDIST" , ocStdNormDist }, + { "NORM.S.DIST" , ocStdNormDist_MS }, + { "FISHER" , ocFisher }, + { "FISHERINV" , ocFisherInv }, + { "NORMSINV" , ocSNormInv }, + { "NORM.S.INV" , ocSNormInv_MS }, + { "GAMMALN" , ocGammaLn }, + { "GAMMALN.PRECISE" , ocGammaLn_MS }, + { "ERRORTYPE" , ocErrorType }, + { "ERROR.TYPE" , ocErrorType_ODF }, + { "FORMULA" , ocFormula }, + { "ATAN2" , ocArcTan2 }, + { "CEILING.MATH" , ocCeil_Math }, + { "CEILING" , ocCeil }, + { "CEILING.XCL" , ocCeil_MS }, + { "CEILING.PRECISE" , ocCeil_Precise }, + { "ISO.CEILING" , ocCeil_ISO }, + { "FLOOR" , ocFloor }, + { "FLOOR.XCL" , ocFloor_MS }, + { "FLOOR.MATH" , ocFloor_Math }, + { "FLOOR.PRECISE" , ocFloor_Precise }, + { "ROUND" , ocRound }, + { "ROUNDUP" , ocRoundUp }, + { "ROUNDDOWN" , ocRoundDown }, + { "TRUNC" , ocTrunc }, + { "LOG" , ocLog }, + { "POWER" , ocPower }, + { "GCD" , ocGCD }, + { "LCM" , ocLCM }, + { "MOD" , ocMod }, + { "SUMPRODUCT" , ocSumProduct }, + { "SUMSQ" , ocSumSQ }, + { "SUMX2MY2" , ocSumX2MY2 }, + { "SUMX2PY2" , ocSumX2DY2 }, + { "SUMXMY2" , ocSumXMY2 }, + { "DATE" , ocGetDate }, + { "TIME" , ocGetTime }, + { "DAYS" , ocGetDiffDate }, + { "DAYS360" , ocGetDiffDate360 }, + { "DATEDIF" , ocGetDateDif }, + { "MIN" , ocMin }, + { "MINA" , ocMinA }, + { "MAX" , ocMax }, + { "MAXA" , ocMaxA }, + { "SUM" , ocSum }, + { "PRODUCT" , ocProduct }, + { "AVERAGE" , ocAverage }, + { "AVERAGEA" , ocAverageA }, + { "COUNT" , ocCount }, + { "COUNTA" , ocCount2 }, + { "NPV" , ocNPV }, + { "IRR" , ocIRR }, + { "MIRR" , ocMIRR }, + { "ISPMT" , ocISPMT }, + { "VAR" , ocVar }, + { "VARA" , ocVarA }, + { "VARP" , ocVarP }, + { "VARPA" , ocVarPA }, + { "VAR.P" , ocVarP_MS }, + { "VAR.S" , ocVarS }, + { "STDEV" , ocStDev }, + { "STDEVA" , ocStDevA }, + { "STDEVP" , ocStDevP }, + { "STDEVPA" , ocStDevPA }, + { "STDEV.P" , ocStDevP_MS }, + { "STDEV.S" , ocStDevS }, + { "B" , ocB }, + { "NORMDIST" , ocNormDist }, + { "NORM.DIST" , ocNormDist_MS }, + { "EXPONDIST" , ocExpDist }, + { "EXPON.DIST" , ocExpDist_MS }, + { "BINOMDIST" , ocBinomDist }, + { "BINOM.DIST" , ocBinomDist_MS }, + { "POISSON" , ocPoissonDist }, + { "POISSON.DIST" , ocPoissonDist_MS }, + { "COMBIN" , ocCombin }, + { "COMBINA" , ocCombinA }, + { "PERMUT" , ocPermut }, + { "PERMUTATIONA" , ocPermutationA }, + { "PV" , ocPV }, + { "SYD" , ocSYD }, + { "DDB" , ocDDB }, + { "DB" , ocDB }, + { "VDB" , ocVBD }, + { "PDURATION" , ocPDuration }, + { "SLN" , ocSLN }, + { "PMT" , ocPMT }, + { "COLUMNS" , ocColumns }, + { "ROWS" , ocRows }, + { "SHEETS" , ocSheets }, + { "COLUMN" , ocColumn }, + { "ROW" , ocRow }, + { "SHEET" , ocSheet }, + { "ZGZ" , ocRRI }, + { "FV" , ocFV }, + { "NPER" , ocNper }, + { "RATE" , ocRate }, + { "IPMT" , ocIpmt }, + { "PPMT" , ocPpmt }, + { "CUMIPMT" , ocCumIpmt }, + { "CUMPRINC" , ocCumPrinc }, + { "EFFECT" , ocEffect }, + { "NOMINAL" , ocNominal }, + { "SUBTOTAL" , ocSubTotal }, + { "DSUM" , ocDBSum }, + { "DCOUNT" , ocDBCount }, + { "DCOUNTA" , ocDBCount2 }, + { "DAVERAGE" , ocDBAverage }, + { "DGET" , ocDBGet }, + { "DMAX" , ocDBMax }, + { "DMIN" , ocDBMin }, + { "DPRODUCT" , ocDBProduct }, + { "DSTDEV" , ocDBStdDev }, + { "DSTDEVP" , ocDBStdDevP }, + { "DVAR" , ocDBVar }, + { "DVARP" , ocDBVarP }, + { "INDIRECT" , ocIndirect }, + { "ADDRESS" , ocAddress }, + { "MATCH" , ocMatch }, + { "XMATCH" , ocXMatch }, + { "COUNTBLANK" , ocCountEmptyCells }, + { "COUNTIF" , ocCountIf }, + { "SUMIF" , ocSumIf }, + { "AVERAGEIF" , ocAverageIf }, + { "SUMIFS" , ocSumIfs }, + { "AVERAGEIFS" , ocAverageIfs }, + { "COUNTIFS" , ocCountIfs }, + { "LOOKUP" , ocLookup }, + { "VLOOKUP" , ocVLookup }, + { "XLOOKUP" , ocXLookup }, + { "HLOOKUP" , ocHLookup }, + { "FILTER" , ocFilter }, + { "SORT" , ocSort }, + { "SORTBY" , ocSortBy }, + { "CHOOSECOLS" , ocChooseCols }, + { "CHOOSEROWS" , ocChooseRows }, + { "DROP" , ocDrop }, + { "EXPAND" , ocExpand }, + { "HSTACK" , ocHStack }, + { "VSTACK" , ocVStack }, + { "TAKE" , ocTake }, + { "TEXTAFTER" , ocTextAfter }, + { "TEXTBEFORE" , ocTextBefore }, + { "TEXTSPLIT" , ocTextSplit }, + { "TOCOL" , ocToCol }, + { "TOROW" , ocToRow }, + { "UNIQUE" , ocUnique }, + { "LET" , ocLet }, + { "WRAPCOLS" , ocWrapCols }, + { "WRAPROWS" , ocWrapRows }, + { "LAMBDA" , ocLambda }, + { "ISOMITTED" , ocIsOmitted }, + { "BYCOL" , ocByCol }, + { "BYROW" , ocByRow }, + { "MAKEARRAY" , ocMakeArray }, + { "MAP" , ocMap }, + { "REDUCE" , ocReduce }, + { "SCAN" , ocScan }, + { "ARRAYTOTEXT" , ocArrayToText }, + { "MULTIRANGE" , ocMultiArea }, + { "OFFSET" , ocOffset }, + { "INDEX" , ocIndex }, + { "AREAS" , ocAreas }, + { "DOLLAR" , ocCurrency }, + { "REPLACE" , ocReplace }, + { "FIXED" , ocFixed }, + { "FIND" , ocFind }, + { "EXACT" , ocExact }, + { "LEFT" , ocLeft }, + { "RIGHT" , ocRight }, + { "SEARCH" , ocSearch }, + { "MID" , ocMid }, + { "LENB" , ocLenB }, + { "RIGHTB" , ocRightB }, + { "LEFTB" , ocLeftB }, + { "REPLACEB" , ocReplaceB }, + { "FINDB" , ocFindB }, + { "SEARCHB" , ocSearchB }, + { "MIDB" , ocMidB }, + { "TEXT" , ocText }, + { "SUBSTITUTE" , ocSubstitute }, + { "REPT" , ocRept }, + { "CONCATENATE" , ocConcat }, + { "CONCAT" , ocConcat_MS }, + { "TEXTJOIN" , ocTextJoin_MS }, + { "IFS" , ocIfs_MS }, + { "SWITCH" , ocSwitch_MS }, + { "MINIFS" , ocMinIfs_MS }, + { "MAXIFS" , ocMaxIfs_MS }, + { "MVALUE" , ocMatValue }, + { "MDETERM" , ocMatDet }, + { "MINVERSE" , ocMatInv }, + { "MMULT" , ocMatMult }, + { "SEQUENCE" , ocMatSequence }, + { "TRANSPOSE" , ocMatTrans }, + { "MUNIT" , ocMatrixUnit }, + { "GOALSEEK" , ocBackSolver }, + { "HYPGEOMDIST" , ocHypGeomDist }, + { "HYPGEOM.DIST" , ocHypGeomDist_MS }, + { "LOGNORMDIST" , ocLogNormDist }, + { "LOGNORM.DIST" , ocLogNormDist_MS }, + { "TDIST" , ocTDist }, + { "T.DIST.2T" , ocTDist_2T }, + { "T.DIST" , ocTDist_MS }, + { "T.DIST.RT" , ocTDist_RT }, + { "FDIST" , ocFDist }, + { "F.DIST" , ocFDist_LT }, + { "F.DIST.RT" , ocFDist_RT }, + { "CHIDIST" , ocChiDist }, + { "CHISQ.DIST.RT" , ocChiDist_MS }, + { "WEIBULL" , ocWeibull }, + { "WEIBULL.DIST" , ocWeibull_MS }, + { "NEGBINOMDIST" , ocNegBinomVert }, + { "NEGBINOM.DIST" , ocNegBinomDist_MS }, + { "CRITBINOM" , ocCritBinom }, + { "BINOM.INV" , ocBinomInv }, + { "KURT" , ocKurt }, + { "HARMEAN" , ocHarMean }, + { "GEOMEAN" , ocGeoMean }, + { "STANDARDIZE" , ocStandard }, + { "AVEDEV" , ocAveDev }, + { "SKEW" , ocSkew }, + { "SKEWP" , ocSkewp }, + { "DEVSQ" , ocDevSq }, + { "MEDIAN" , ocMedian }, + { "MODE" , ocModalValue }, + { "MODE.SNGL" , ocModalValue_MS }, + { "MODE.MULT" , ocModalValue_Multi }, + { "ZTEST" , ocZTest }, + { "Z.TEST" , ocZTest_MS }, + { "AGGREGATE" , ocAggregate }, + { "TTEST" , ocTTest }, + { "T.TEST" , ocTTest_MS }, + { "RANK" , ocRank }, + { "PERCENTILE" , ocPercentile }, + { "PERCENTRANK" , ocPercentrank }, + { "PERCENTILE.INC" , ocPercentile_Inc }, + { "PERCENTRANK.INC" , ocPercentrank_Inc }, + { "QUARTILE.INC" , ocQuartile_Inc }, + { "RANK.EQ" , ocRank_Eq }, + { "PERCENTILE.EXC" , ocPercentile_Exc }, + { "PERCENTRANK.EXC" , ocPercentrank_Exc }, + { "QUARTILE.EXC" , ocQuartile_Exc }, + { "RANK.AVG" , ocRank_Avg }, + { "LARGE" , ocLarge }, + { "SMALL" , ocSmall }, + { "FREQUENCY" , ocFrequency }, + { "QUARTILE" , ocQuartile }, + { "NORMINV" , ocNormInv }, + { "NORM.INV" , ocNormInv_MS }, + { "CONFIDENCE" , ocConfidence }, + { "CONFIDENCE.NORM" , ocConfidence_N }, + { "CONFIDENCE.T" , ocConfidence_T }, + { "FTEST" , ocFTest }, + { "F.TEST" , ocFTest_MS }, + { "TRIMMEAN" , ocTrimMean }, + { "PROB" , ocProb }, + { "CORREL" , ocCorrel }, + { "COVAR" , ocCovar }, + { "COVARIANCE.P" , ocCovarianceP }, + { "COVARIANCE.S" , ocCovarianceS }, + { "PEARSON" , ocPearson }, + { "RSQ" , ocRSQ }, + { "STEYX" , ocSTEYX }, + { "SLOPE" , ocSlope }, + { "INTERCEPT" , ocIntercept }, + { "TREND" , ocTrend }, + { "GROWTH" , ocGrowth }, + { "LINEST" , ocLinest }, + { "LOGEST" , ocLogest }, + { "FORECAST" , ocForecast }, + { "FORECAST.ETS.ADD" , ocForecast_ETS_ADD }, + { "FORECAST.ETS.SEASONALITY" , ocForecast_ETS_SEA }, + { "FORECAST.ETS.MULT" , ocForecast_ETS_MUL }, + { "FORECAST.ETS.PI.ADD" , ocForecast_ETS_PIA }, + { "FORECAST.ETS.PI.MULT" , ocForecast_ETS_PIM }, + { "FORECAST.ETS.STAT.ADD" , ocForecast_ETS_STA }, + { "FORECAST.ETS.STAT.MULT" , ocForecast_ETS_STM }, + { "FORECAST.LINEAR" , ocForecast_LIN }, + { "CHIINV" , ocChiInv }, + { "CHISQ.INV.RT" , ocChiInv_MS }, + { "GAMMADIST" , ocGammaDist }, + { "GAMMA.DIST" , ocGammaDist_MS }, + { "GAMMAINV" , ocGammaInv }, + { "GAMMA.INV" , ocGammaInv_MS }, + { "TINV" , ocTInv }, + { "T.INV.2T" , ocTInv_2T }, + { "T.INV" , ocTInv_MS }, + { "FINV" , ocFInv }, + { "F.INV" , ocFInv_LT }, + { "F.INV.RT" , ocFInv_RT }, + { "CHITEST" , ocChiTest }, + { "CHISQ.TEST" , ocChiTest_MS }, + { "LOGINV" , ocLogInv }, + { "LOGNORM.INV" , ocLogInv_MS }, + { "TABLE" , ocTableOp }, + { "BETADIST" , ocBetaDist }, + { "BETAINV" , ocBetaInv }, + { "BETA.DIST" , ocBetaDist_MS }, + { "BETA.INV" , ocBetaInv_MS }, + { "WEEKNUM" , ocWeek }, + { "ISOWEEKNUM" , ocIsoWeeknum }, + { "WEEKNUM_OOO" , ocWeeknumOOo }, + { "EASTERSUNDAY" , ocEasterSunday }, + { "WEEKDAY" , ocGetDayOfWeek }, + { "NETWORKDAYS" , ocNetWorkdays }, + { "NETWORKDAYS.INTL" , ocNetWorkdays_MS }, + { "WORKDAY.INTL" , ocWorkday_MS }, + { "#NAME!" , ocNoName }, + { "STYLE" , ocStyle }, + { "DDE" , ocDde }, + { "BASE" , ocBase }, + { "DECIMAL" , ocDecimal }, + { "CONVERT_OOO" , ocConvertOOo }, + { "ROMAN" , ocRoman }, + { "ARABIC" , ocArabic }, + { "HYPERLINK" , ocHyperLink }, + { "INFO" , ocInfo }, + { "BAHTTEXT" , ocBahtText }, + { "GETPIVOTDATA" , ocGetPivotData }, + { "EUROCONVERT" , ocEuroConvert }, + { "NUMBERVALUE" , ocNumberValue }, + { "GAMMA" , ocGamma }, + { "CHISQDIST" , ocChiSqDist }, + { "CHISQ.DIST" , ocChiSqDist_MS }, + { "CHISQ.INV" , ocChiSqInv_MS }, + { "CHISQINV" , ocChiSqInv }, + { "BITAND" , ocBitAnd }, + { "BITOR" , ocBitOr }, + { "BITXOR" , ocBitXor }, + { "BITRSHIFT" , ocBitRshift }, + { "BITLSHIFT" , ocBitLshift }, + { "#NULL!" , ocErrNull }, + { "#DIV/0!" , ocErrDivZero }, + { "#VALUE!" , ocErrValue }, + { "#REF!" , ocErrRef }, + { "#NAME?" , ocErrName }, + { "#NUM!" , ocErrNum }, + { "#N/A" , ocErrNA }, + { "#SPILL!" , ocErrSpill }, /* END defined ERROR.TYPE() values. */ - { "FILTERXML" , SC_OPCODE_FILTERXML }, - { "WEBSERVICE" , SC_OPCODE_WEBSERVICE }, - { "COLOR" , SC_OPCODE_COLOR }, - { "ERF.PRECISE" , SC_OPCODE_ERF_MS }, - { "ERFC.PRECISE" , SC_OPCODE_ERFC_MS }, - { "ENCODEURL" , SC_OPCODE_ENCODEURL }, - { "RAWSUBTRACT" , SC_OPCODE_RAWSUBTRACT }, - { "ROUNDSIG" , SC_OPCODE_ROUNDSIG }, - { "REGEX" , SC_OPCODE_REGEX }, - { "FOURIER", SC_OPCODE_FOURIER }, - { "RAND.NV" , SC_OPCODE_RANDOM_NV }, - { "RANDBETWEEN.NV" , SC_OPCODE_RANDBETWEEN_NV }, - { "RANDARRAY" , SC_OPCODE_RANDARRAY }, + { "FILTERXML" , ocFilterXML }, + { "WEBSERVICE" , ocWebservice }, + { "COLOR" , ocColor }, + { "ERF.PRECISE" , ocErf_MS }, + { "ERFC.PRECISE" , ocErfc_MS }, + { "ENCODEURL" , ocEncodeURL }, + { "RAWSUBTRACT" , ocRawSubtract }, + { "ROUNDSIG" , ocRoundSig }, + { "REGEX" , ocRegex }, + { "FOURIER", ocFourier }, + { "RAND.NV" , ocRandomNV }, + { "RANDBETWEEN.NV" , ocRandbetweenNV }, + { "RANDARRAY" , ocRandArray }, { nullptr, -1 } }; @@ -2393,497 +2455,510 @@ const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH[] = */ const std::pair RID_STRLIST_FUNCTION_NAMES[] = { - { NC_("RID_STRLIST_FUNCTION_NAMES", "IF") , SC_OPCODE_IF }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "IFERROR") , SC_OPCODE_IF_ERROR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "IFNA") , SC_OPCODE_IF_NA }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHOOSE") , SC_OPCODE_CHOOSE }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "IF") , ocIf }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "IFERROR") , ocIfError }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "IFNA") , ocIfNA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHOOSE") , ocChoose }, /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#All") , SC_OPCODE_TABLE_REF_ITEM_ALL }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#All") , ocTableRefItemAll }, /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#Headers") , SC_OPCODE_TABLE_REF_ITEM_HEADERS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#Headers") , ocTableRefItemHeaders }, /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#Data") , SC_OPCODE_TABLE_REF_ITEM_DATA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#Data") , ocTableRefItemData }, /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#Totals") , SC_OPCODE_TABLE_REF_ITEM_TOTALS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#Totals") , ocTableRefItemTotals }, /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#This Row") , SC_OPCODE_TABLE_REF_ITEM_THIS_ROW }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "AND") , SC_OPCODE_AND }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "OR") , SC_OPCODE_OR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "XOR") , SC_OPCODE_XOR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NOT") , SC_OPCODE_NOT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NEG") , SC_OPCODE_NEG }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PI") , SC_OPCODE_PI }, // ??? - { NC_("RID_STRLIST_FUNCTION_NAMES", "RAND") , SC_OPCODE_RANDOM }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TRUE") , SC_OPCODE_TRUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FALSE") , SC_OPCODE_FALSE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TODAY") , SC_OPCODE_GET_ACT_DATE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NOW") , SC_OPCODE_GET_ACT_TIME }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NA") , SC_OPCODE_NO_VALUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CURRENT") , SC_OPCODE_CURRENT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DEGREES") , SC_OPCODE_DEG }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RADIANS") , SC_OPCODE_RAD }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SIN") , SC_OPCODE_SIN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COS") , SC_OPCODE_COS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TAN") , SC_OPCODE_TAN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COT") , SC_OPCODE_COT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ASIN") , SC_OPCODE_ARC_SIN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ACOS") , SC_OPCODE_ARC_COS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ATAN") , SC_OPCODE_ARC_TAN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ACOT") , SC_OPCODE_ARC_COT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SINH") , SC_OPCODE_SIN_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COSH") , SC_OPCODE_COS_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TANH") , SC_OPCODE_TAN_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COTH") , SC_OPCODE_COT_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ASINH") , SC_OPCODE_ARC_SIN_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ACOSH") , SC_OPCODE_ARC_COS_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ATANH") , SC_OPCODE_ARC_TAN_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ACOTH") , SC_OPCODE_ARC_COT_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CSC") , SC_OPCODE_COSECANT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SEC") , SC_OPCODE_SECANT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CSCH") , SC_OPCODE_COSECANT_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SECH") , SC_OPCODE_SECANT_HYP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "EXP") , SC_OPCODE_EXP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LN") , SC_OPCODE_LN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SQRT") , SC_OPCODE_SQRT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FACT") , SC_OPCODE_FACT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "YEAR") , SC_OPCODE_GET_YEAR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MONTH") , SC_OPCODE_GET_MONTH }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DAY") , SC_OPCODE_GET_DAY }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "HOUR") , SC_OPCODE_GET_HOUR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MINUTE") , SC_OPCODE_GET_MIN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SECOND") , SC_OPCODE_GET_SEC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SIGN") , SC_OPCODE_PLUS_MINUS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ABS") , SC_OPCODE_ABS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "INT") , SC_OPCODE_INT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PHI") , SC_OPCODE_PHI }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GAUSS") , SC_OPCODE_GAUSS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISBLANK") , SC_OPCODE_IS_EMPTY }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISTEXT") , SC_OPCODE_IS_STRING }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISNONTEXT") , SC_OPCODE_IS_NON_STRING }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISLOGICAL") , SC_OPCODE_IS_LOGICAL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TYPE") , SC_OPCODE_TYPE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CELL") , SC_OPCODE_CELL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISREF") , SC_OPCODE_IS_REF }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISNUMBER") , SC_OPCODE_IS_VALUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISFORMULA") , SC_OPCODE_IS_FORMULA }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISNA") , SC_OPCODE_IS_NV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISERR") , SC_OPCODE_IS_ERR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISERROR") , SC_OPCODE_IS_ERROR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISEVEN") , SC_OPCODE_IS_EVEN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISODD") , SC_OPCODE_IS_ODD }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "N") , SC_OPCODE_N }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DATEVALUE") , SC_OPCODE_GET_DATE_VALUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TIMEVALUE") , SC_OPCODE_GET_TIME_VALUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CODE") , SC_OPCODE_CODE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TRIM") , SC_OPCODE_TRIM }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "UPPER") , SC_OPCODE_UPPER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PROPER") , SC_OPCODE_PROPER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LOWER") , SC_OPCODE_LOWER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LEN") , SC_OPCODE_LEN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "T") , SC_OPCODE_T }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VALUE") , SC_OPCODE_VALUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CLEAN") , SC_OPCODE_CLEAN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHAR") , SC_OPCODE_CHAR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "JIS") , SC_OPCODE_JIS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ASC") , SC_OPCODE_ASC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "UNICODE") , SC_OPCODE_UNICODE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "UNICHAR") , SC_OPCODE_UNICHAR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LOG10") , SC_OPCODE_LOG10 }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "EVEN") , SC_OPCODE_EVEN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ODD") , SC_OPCODE_ODD }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NORMSDIST") , SC_OPCODE_STD_NORM_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NORM.S.DIST") , SC_OPCODE_STD_NORM_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FISHER") , SC_OPCODE_FISHER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FISHERINV") , SC_OPCODE_FISHER_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NORMSINV") , SC_OPCODE_S_NORM_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NORM.S.INV") , SC_OPCODE_S_NORM_INV_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMALN") , SC_OPCODE_GAMMA_LN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMALN.PRECISE") , SC_OPCODE_GAMMA_LN_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ERRORTYPE") , SC_OPCODE_ERROR_TYPE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ERROR.TYPE") , SC_OPCODE_ERROR_TYPE_ODF }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORMULA") , SC_OPCODE_FORMULA }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ARABIC") , SC_OPCODE_ARABIC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ATAN2") , SC_OPCODE_ARC_TAN_2 }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CEILING.MATH") , SC_OPCODE_CEIL_MATH }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CEILING") , SC_OPCODE_CEIL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CEILING.XCL") , SC_OPCODE_CEIL_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CEILING.PRECISE") , SC_OPCODE_CEIL_PRECISE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISO.CEILING") , SC_OPCODE_CEIL_ISO }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FLOOR") , SC_OPCODE_FLOOR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FLOOR.XCL") , SC_OPCODE_FLOOR_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FLOOR.MATH") , SC_OPCODE_FLOOR_MATH }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FLOOR.PRECISE") , SC_OPCODE_FLOOR_PRECISE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ROUND") , SC_OPCODE_ROUND }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ROUNDUP") , SC_OPCODE_ROUND_UP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ROUNDDOWN") , SC_OPCODE_ROUND_DOWN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TRUNC") , SC_OPCODE_TRUNC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LOG") , SC_OPCODE_LOG }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "POWER") , SC_OPCODE_POWER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GCD") , SC_OPCODE_GCD }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LCM") , SC_OPCODE_LCM }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MOD") , SC_OPCODE_MOD }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMPRODUCT") , SC_OPCODE_SUM_PRODUCT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMSQ") , SC_OPCODE_SUM_SQ }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMX2MY2") , SC_OPCODE_SUM_X2MY2 }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMX2PY2") , SC_OPCODE_SUM_X2DY2 }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMXMY2") , SC_OPCODE_SUM_XMY2 }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DATE") , SC_OPCODE_GET_DATE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TIME") , SC_OPCODE_GET_TIME }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DAYS") , SC_OPCODE_GET_DIFF_DATE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DAYS360") , SC_OPCODE_GET_DIFF_DATE_360 }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DATEDIF") , SC_OPCODE_GET_DATEDIF }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MIN") , SC_OPCODE_MIN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MINA") , SC_OPCODE_MIN_A }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MAX") , SC_OPCODE_MAX }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MAXA") , SC_OPCODE_MAX_A }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUM") , SC_OPCODE_SUM }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PRODUCT") , SC_OPCODE_PRODUCT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "AVERAGE") , SC_OPCODE_AVERAGE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "AVERAGEA") , SC_OPCODE_AVERAGE_A }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNT") , SC_OPCODE_COUNT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNTA") , SC_OPCODE_COUNT_2 }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NPV") , SC_OPCODE_NPV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "IRR") , SC_OPCODE_IRR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MIRR") , SC_OPCODE_MIRR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISPMT") , SC_OPCODE_ISPMT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VAR") , SC_OPCODE_VAR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VARA") , SC_OPCODE_VAR_A }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VARP") , SC_OPCODE_VAR_P }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VARPA") , SC_OPCODE_VAR_P_A }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VAR.P") , SC_OPCODE_VAR_P_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VAR.S") , SC_OPCODE_VAR_S }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEV") , SC_OPCODE_ST_DEV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEVA") , SC_OPCODE_ST_DEV_A }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEVP") , SC_OPCODE_ST_DEV_P }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEVPA") , SC_OPCODE_ST_DEV_P_A }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEV.P") , SC_OPCODE_ST_DEV_P_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEV.S") , SC_OPCODE_ST_DEV_S }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "B") , SC_OPCODE_B }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NORMDIST") , SC_OPCODE_NORM_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NORM.DIST") , SC_OPCODE_NORM_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "EXPONDIST") , SC_OPCODE_EXP_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "EXPON.DIST") , SC_OPCODE_EXP_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BINOMDIST") , SC_OPCODE_BINOM_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BINOM.DIST") , SC_OPCODE_BINOM_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "POISSON") , SC_OPCODE_POISSON_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "POISSON.DIST") , SC_OPCODE_POISSON_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COMBIN") , SC_OPCODE_COMBIN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COMBINA") , SC_OPCODE_COMBIN_A }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PERMUT") , SC_OPCODE_PERMUT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PERMUTATIONA") , SC_OPCODE_PERMUTATION_A }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PV") , SC_OPCODE_PV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SYD") , SC_OPCODE_SYD }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DDB") , SC_OPCODE_DDB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DB") , SC_OPCODE_DB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VDB") , SC_OPCODE_VBD }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PDURATION") , SC_OPCODE_PDURATION }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SLN") , SC_OPCODE_SLN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PMT") , SC_OPCODE_PMT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COLUMNS") , SC_OPCODE_COLUMNS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ROWS") , SC_OPCODE_ROWS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SHEETS") , SC_OPCODE_SHEETS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COLUMN") , SC_OPCODE_COLUMN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ROW") , SC_OPCODE_ROW }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SHEET") , SC_OPCODE_SHEET }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RRI") , SC_OPCODE_RRI }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FV") , SC_OPCODE_FV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NPER") , SC_OPCODE_NPER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RATE") , SC_OPCODE_RATE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "IPMT") , SC_OPCODE_IPMT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PPMT") , SC_OPCODE_PPMT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CUMIPMT") , SC_OPCODE_CUM_IPMT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CUMPRINC") , SC_OPCODE_CUM_PRINC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "EFFECT") , SC_OPCODE_EFFECT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NOMINAL") , SC_OPCODE_NOMINAL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUBTOTAL") , SC_OPCODE_SUB_TOTAL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DSUM") , SC_OPCODE_DB_SUM }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DCOUNT") , SC_OPCODE_DB_COUNT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DCOUNTA") , SC_OPCODE_DB_COUNT_2 }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DAVERAGE") , SC_OPCODE_DB_AVERAGE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DGET") , SC_OPCODE_DB_GET }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DMAX") , SC_OPCODE_DB_MAX }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DMIN") , SC_OPCODE_DB_MIN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DPRODUCT") , SC_OPCODE_DB_PRODUCT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DSTDEV") , SC_OPCODE_DB_STD_DEV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DSTDEVP") , SC_OPCODE_DB_STD_DEV_P }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DVAR") , SC_OPCODE_DB_VAR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DVARP") , SC_OPCODE_DB_VAR_P }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "INDIRECT") , SC_OPCODE_INDIRECT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ADDRESS") , SC_OPCODE_ADDRESS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MATCH") , SC_OPCODE_MATCH }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "XMATCH") , SC_OPCODE_X_MATCH }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNTBLANK") , SC_OPCODE_COUNT_EMPTY_CELLS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNTIF") , SC_OPCODE_COUNT_IF }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMIF") , SC_OPCODE_SUM_IF }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "AVERAGEIF") , SC_OPCODE_AVERAGE_IF }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMIFS") , SC_OPCODE_SUM_IFS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "AVERAGEIFS") , SC_OPCODE_AVERAGE_IFS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNTIFS") , SC_OPCODE_COUNT_IFS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LOOKUP") , SC_OPCODE_LOOKUP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VLOOKUP") , SC_OPCODE_V_LOOKUP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "XLOOKUP") , SC_OPCODE_X_LOOKUP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "HLOOKUP") , SC_OPCODE_H_LOOKUP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FILTER") , SC_OPCODE_FILTER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SORT") , SC_OPCODE_SORT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SORTBY") , SC_OPCODE_SORTBY }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHOOSECOLS") , SC_OPCODE_CHOOSECOLS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHOOSEROWS") , SC_OPCODE_CHOOSEROWS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DROP") , SC_OPCODE_DROP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "EXPAND") , SC_OPCODE_EXPAND }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "HSTACK") , SC_OPCODE_HSTACK }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "VSTACK") , SC_OPCODE_VSTACK }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TAKE") , SC_OPCODE_TAKE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTAFTER") , SC_OPCODE_TEXTAFTER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTBEFORE") , SC_OPCODE_TEXTBEFORE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTSPLIT") , SC_OPCODE_TEXTSPLIT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TOCOL") , SC_OPCODE_TOCOL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TOROW") , SC_OPCODE_TOROW }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "UNIQUE") , SC_OPCODE_UNIQUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LET") , SC_OPCODE_LET }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "WRAPCOLS") , SC_OPCODE_WRAPCOLS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "WRAPROWS") , SC_OPCODE_WRAPROWS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MULTIRANGE") , SC_OPCODE_MULTI_AREA }, // legacy for range list (union) - { NC_("RID_STRLIST_FUNCTION_NAMES", "OFFSET") , SC_OPCODE_OFFSET }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "INDEX") , SC_OPCODE_INDEX }, // ?? first character = I ?? - { NC_("RID_STRLIST_FUNCTION_NAMES", "AREAS") , SC_OPCODE_AREAS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DOLLAR") , SC_OPCODE_CURRENCY }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "REPLACE") , SC_OPCODE_REPLACE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FIXED") , SC_OPCODE_FIXED }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FIND") , SC_OPCODE_FIND }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "EXACT") , SC_OPCODE_EXACT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LEFT") , SC_OPCODE_LEFT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RIGHT") , SC_OPCODE_RIGHT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SEARCH") , SC_OPCODE_SEARCH }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MID") , SC_OPCODE_MID }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LENB") , SC_OPCODE_LENB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RIGHTB") , SC_OPCODE_RIGHTB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LEFTB") , SC_OPCODE_LEFTB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "REPLACEB") , SC_OPCODE_REPLACEB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MIDB") , SC_OPCODE_MIDB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXT") , SC_OPCODE_TEXT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SUBSTITUTE") , SC_OPCODE_SUBSTITUTE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "REPT") , SC_OPCODE_REPT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CONCATENATE") , SC_OPCODE_CONCAT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CONCAT") , SC_OPCODE_CONCAT_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTJOIN") , SC_OPCODE_TEXTJOIN_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "IFS") , SC_OPCODE_IFS_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SWITCH") , SC_OPCODE_SWITCH_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MINIFS") , SC_OPCODE_MINIFS_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MAXIFS") , SC_OPCODE_MAXIFS_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MVALUE") , SC_OPCODE_MAT_VALUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MDETERM") , SC_OPCODE_MAT_DET }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MINVERSE") , SC_OPCODE_MAT_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MMULT") , SC_OPCODE_MAT_MULT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SEQUENCE") , SC_OPCODE_MAT_SEQUENCE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TRANSPOSE") , SC_OPCODE_MAT_TRANS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MUNIT") , SC_OPCODE_MATRIX_UNIT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GOALSEEK") , SC_OPCODE_BACK_SOLVER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "HYPGEOMDIST") , SC_OPCODE_HYP_GEOM_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "HYPGEOM.DIST") , SC_OPCODE_HYP_GEOM_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGNORMDIST") , SC_OPCODE_LOG_NORM_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGNORM.DIST") , SC_OPCODE_LOG_NORM_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TDIST") , SC_OPCODE_T_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "T.DIST.2T") , SC_OPCODE_T_DIST_2T }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "T.DIST") , SC_OPCODE_T_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "T.DIST.RT") , SC_OPCODE_T_DIST_RT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FDIST") , SC_OPCODE_F_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "F.DIST") , SC_OPCODE_F_DIST_LT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "F.DIST.RT") , SC_OPCODE_F_DIST_RT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHIDIST") , SC_OPCODE_CHI_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.DIST.RT") , SC_OPCODE_CHI_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "WEIBULL") , SC_OPCODE_WEIBULL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "WEIBULL.DIST") , SC_OPCODE_WEIBULL_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NEGBINOMDIST") , SC_OPCODE_NEG_BINOM_VERT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NEGBINOM.DIST") , SC_OPCODE_NEG_BINOM_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CRITBINOM") , SC_OPCODE_CRIT_BINOM }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BINOM.INV") , SC_OPCODE_BINOM_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "KURT") , SC_OPCODE_KURT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "HARMEAN") , SC_OPCODE_HAR_MEAN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GEOMEAN") , SC_OPCODE_GEO_MEAN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "STANDARDIZE") , SC_OPCODE_STANDARD }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "AVEDEV") , SC_OPCODE_AVE_DEV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SKEW") , SC_OPCODE_SKEW }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SKEWP") , SC_OPCODE_SKEWP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DEVSQ") , SC_OPCODE_DEV_SQ }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MEDIAN") , SC_OPCODE_MEDIAN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MODE") , SC_OPCODE_MODAL_VALUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MODE.SNGL") , SC_OPCODE_MODAL_VALUE_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MODE.MULT") , SC_OPCODE_MODAL_VALUE_MULTI }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ZTEST") , SC_OPCODE_Z_TEST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "Z.TEST") , SC_OPCODE_Z_TEST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "AGGREGATE") , SC_OPCODE_AGGREGATE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TTEST") , SC_OPCODE_T_TEST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "T.TEST") , SC_OPCODE_T_TEST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RANK") , SC_OPCODE_RANK }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTILE") , SC_OPCODE_PERCENTILE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTRANK") , SC_OPCODE_PERCENT_RANK }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTILE.INC") , SC_OPCODE_PERCENTILE_INC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTRANK.INC") , SC_OPCODE_PERCENT_RANK_INC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "QUARTILE.INC") , SC_OPCODE_QUARTILE_INC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RANK.EQ") , SC_OPCODE_RANK_EQ }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTILE.EXC") , SC_OPCODE_PERCENTILE_EXC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTRANK.EXC") , SC_OPCODE_PERCENT_RANK_EXC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "QUARTILE.EXC") , SC_OPCODE_QUARTILE_EXC }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RANK.AVG") , SC_OPCODE_RANK_AVG }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LARGE") , SC_OPCODE_LARGE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SMALL") , SC_OPCODE_SMALL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FREQUENCY") , SC_OPCODE_FREQUENCY }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "QUARTILE") , SC_OPCODE_QUARTILE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NORMINV") , SC_OPCODE_NORM_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NORM.INV") , SC_OPCODE_NORM_INV_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CONFIDENCE") , SC_OPCODE_CONFIDENCE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CONFIDENCE.NORM") , SC_OPCODE_CONFIDENCE_N }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CONFIDENCE.T") , SC_OPCODE_CONFIDENCE_T }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FTEST") , SC_OPCODE_F_TEST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "F.TEST") , SC_OPCODE_F_TEST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TRIMMEAN") , SC_OPCODE_TRIM_MEAN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PROB") , SC_OPCODE_PROB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CORREL") , SC_OPCODE_CORREL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COVAR") , SC_OPCODE_COVAR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COVARIANCE.P") , SC_OPCODE_COVARIANCE_P }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COVARIANCE.S") , SC_OPCODE_COVARIANCE_S }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "PEARSON") , SC_OPCODE_PEARSON }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RSQ") , SC_OPCODE_RSQ }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "STEYX") , SC_OPCODE_STEYX }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SLOPE") , SC_OPCODE_SLOPE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "INTERCEPT") , SC_OPCODE_INTERCEPT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TREND") , SC_OPCODE_TREND }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GROWTH") , SC_OPCODE_GROWTH }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LINEST") , SC_OPCODE_LINEST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGEST") , SC_OPCODE_LOGEST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST") , SC_OPCODE_FORECAST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.ADD") , SC_OPCODE_FORECAST_ETS_ADD }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.SEASONALITY") , SC_OPCODE_FORECAST_ETS_SEA }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.MULT") , SC_OPCODE_FORECAST_ETS_MUL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.PI.ADD") , SC_OPCODE_FORECAST_ETS_PIA }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.PI.MULT") , SC_OPCODE_FORECAST_ETS_PIM }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.STAT.ADD") , SC_OPCODE_FORECAST_ETS_STA }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.STAT.MULT") , SC_OPCODE_FORECAST_ETS_STM }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.LINEAR") , SC_OPCODE_FORECAST_LIN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHIINV") , SC_OPCODE_CHI_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.INV.RT") , SC_OPCODE_CHI_INV_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMADIST") , SC_OPCODE_GAMMA_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMA.DIST") , SC_OPCODE_GAMMA_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMAINV") , SC_OPCODE_GAMMA_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMA.INV") , SC_OPCODE_GAMMA_INV_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "TINV") , SC_OPCODE_T_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "T.INV.2T") , SC_OPCODE_T_INV_2T }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "T.INV") , SC_OPCODE_T_INV_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FINV") , SC_OPCODE_F_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "F.INV") , SC_OPCODE_F_INV_LT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "F.INV.RT") , SC_OPCODE_F_INV_RT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHITEST") , SC_OPCODE_CHI_TEST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.TEST") , SC_OPCODE_CHI_TEST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGINV") , SC_OPCODE_LOG_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGNORM.INV") , SC_OPCODE_LOG_INV_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "MULTIPLE.OPERATIONS") , SC_OPCODE_TABLE_OP }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BETADIST") , SC_OPCODE_BETA_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BETAINV") , SC_OPCODE_BETA_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BETA.DIST") , SC_OPCODE_BETA_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BETA.INV") , SC_OPCODE_BETA_INV_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "WEEKNUM") , SC_OPCODE_WEEK }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ISOWEEKNUM") , SC_OPCODE_ISOWEEKNUM }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "WEEKNUM_OOO") , SC_OPCODE_WEEKNUM_OOO }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "EASTERSUNDAY") , SC_OPCODE_EASTERSUNDAY }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "WEEKDAY") , SC_OPCODE_GET_DAY_OF_WEEK }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NETWORKDAYS") , SC_OPCODE_NETWORKDAYS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NETWORKDAYS.INTL") , SC_OPCODE_NETWORKDAYS_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "WORKDAY.INTL") , SC_OPCODE_WORKDAY_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#This Row") , ocTableRefItemThisRow }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "AND") , ocAnd }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "OR") , ocOr }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "XOR") , ocXor }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NOT") , ocNot }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NEG") , ocNeg }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PI") , ocPi }, // ??? + { NC_("RID_STRLIST_FUNCTION_NAMES", "RAND") , ocRandom }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TRUE") , ocTrue }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FALSE") , ocFalse }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TODAY") , ocGetActDate }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NOW") , ocGetActTime }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NA") , ocNotAvail }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CURRENT") , ocCurrent }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DEGREES") , ocDeg }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RADIANS") , ocRad }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SIN") , ocSin }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COS") , ocCos }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TAN") , ocTan }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COT") , ocCot }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ASIN") , ocArcSin }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ACOS") , ocArcCos }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ATAN") , ocArcTan }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ACOT") , ocArcCot }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SINH") , ocSinHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COSH") , ocCosHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TANH") , ocTanHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COTH") , ocCotHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ASINH") , ocArcSinHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ACOSH") , ocArcCosHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ATANH") , ocArcTanHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ACOTH") , ocArcCotHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CSC") , ocCosecant }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SEC") , ocSecant }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CSCH") , ocCosecantHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SECH") , ocSecantHyp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "EXP") , ocExp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LN") , ocLn }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SQRT") , ocSqrt }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FACT") , ocFact }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "YEAR") , ocGetYear }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MONTH") , ocGetMonth }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DAY") , ocGetDay }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "HOUR") , ocGetHour }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MINUTE") , ocGetMin }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SECOND") , ocGetSec }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SIGN") , ocPlusMinus }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ABS") , ocAbs }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "INT") , ocInt }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PHI") , ocPhi }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GAUSS") , ocGauss }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISBLANK") , ocIsEmpty }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISTEXT") , ocIsString }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISNONTEXT") , ocIsNonString }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISLOGICAL") , ocIsLogical }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TYPE") , ocType }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CELL") , ocCell }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISREF") , ocIsRef }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISNUMBER") , ocIsValue }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISFORMULA") , ocIsFormula }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISNA") , ocIsNA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISERR") , ocIsErr }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISERROR") , ocIsError }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISEVEN") , ocIsEven }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISODD") , ocIsOdd }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "N") , ocN }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DATEVALUE") , ocGetDateValue }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TIMEVALUE") , ocGetTimeValue }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CODE") , ocCode }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TRIM") , ocTrim }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "UPPER") , ocUpper }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PROPER") , ocProper }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LOWER") , ocLower }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LEN") , ocLen }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "T") , ocT }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VALUE") , ocValue }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CLEAN") , ocClean }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHAR") , ocChar }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "JIS") , ocJis }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ASC") , ocAsc }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "UNICODE") , ocUnicode }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "UNICHAR") , ocUnichar }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LOG10") , ocLog10 }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "EVEN") , ocEven }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ODD") , ocOdd }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NORMSDIST") , ocStdNormDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NORM.S.DIST") , ocStdNormDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FISHER") , ocFisher }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FISHERINV") , ocFisherInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NORMSINV") , ocSNormInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NORM.S.INV") , ocSNormInv_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMALN") , ocGammaLn }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMALN.PRECISE") , ocGammaLn_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ERRORTYPE") , ocErrorType }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ERROR.TYPE") , ocErrorType_ODF }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORMULA") , ocFormula }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ARABIC") , ocArabic }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ATAN2") , ocArcTan2 }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CEILING.MATH") , ocCeil_Math }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CEILING") , ocCeil }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CEILING.XCL") , ocCeil_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CEILING.PRECISE") , ocCeil_Precise }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISO.CEILING") , ocCeil_ISO }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FLOOR") , ocFloor }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FLOOR.XCL") , ocFloor_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FLOOR.MATH") , ocFloor_Math }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FLOOR.PRECISE") , ocFloor_Precise }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ROUND") , ocRound }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ROUNDUP") , ocRoundUp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ROUNDDOWN") , ocRoundDown }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TRUNC") , ocTrunc }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LOG") , ocLog }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "POWER") , ocPower }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GCD") , ocGCD }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LCM") , ocLCM }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MOD") , ocMod }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMPRODUCT") , ocSumProduct }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMSQ") , ocSumSQ }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMX2MY2") , ocSumX2MY2 }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMX2PY2") , ocSumX2DY2 }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMXMY2") , ocSumXMY2 }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DATE") , ocGetDate }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TIME") , ocGetTime }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DAYS") , ocGetDiffDate }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DAYS360") , ocGetDiffDate360 }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DATEDIF") , ocGetDateDif }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MIN") , ocMin }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MINA") , ocMinA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MAX") , ocMax }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MAXA") , ocMaxA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUM") , ocSum }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PRODUCT") , ocProduct }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "AVERAGE") , ocAverage }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "AVERAGEA") , ocAverageA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNT") , ocCount }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNTA") , ocCount2 }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NPV") , ocNPV }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "IRR") , ocIRR }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MIRR") , ocMIRR }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISPMT") , ocISPMT }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VAR") , ocVar }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VARA") , ocVarA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VARP") , ocVarP }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VARPA") , ocVarPA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VAR.P") , ocVarP_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VAR.S") , ocVarS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEV") , ocStDev }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEVA") , ocStDevA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEVP") , ocStDevP }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEVPA") , ocStDevPA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEV.P") , ocStDevP_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "STDEV.S") , ocStDevS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "B") , ocB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NORMDIST") , ocNormDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NORM.DIST") , ocNormDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "EXPONDIST") , ocExpDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "EXPON.DIST") , ocExpDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BINOMDIST") , ocBinomDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BINOM.DIST") , ocBinomDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "POISSON") , ocPoissonDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "POISSON.DIST") , ocPoissonDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COMBIN") , ocCombin }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COMBINA") , ocCombinA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PERMUT") , ocPermut }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PERMUTATIONA") , ocPermutationA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PV") , ocPV }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SYD") , ocSYD }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DDB") , ocDDB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DB") , ocDB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VDB") , ocVBD }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PDURATION") , ocPDuration }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SLN") , ocSLN }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PMT") , ocPMT }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COLUMNS") , ocColumns }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ROWS") , ocRows }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SHEETS") , ocSheets }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COLUMN") , ocColumn }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ROW") , ocRow }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SHEET") , ocSheet }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RRI") , ocRRI }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FV") , ocFV }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NPER") , ocNper }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RATE") , ocRate }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "IPMT") , ocIpmt }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PPMT") , ocPpmt }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CUMIPMT") , ocCumIpmt }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CUMPRINC") , ocCumPrinc }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "EFFECT") , ocEffect }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NOMINAL") , ocNominal }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUBTOTAL") , ocSubTotal }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DSUM") , ocDBSum }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DCOUNT") , ocDBCount }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DCOUNTA") , ocDBCount2 }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DAVERAGE") , ocDBAverage }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DGET") , ocDBGet }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DMAX") , ocDBMax }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DMIN") , ocDBMin }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DPRODUCT") , ocDBProduct }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DSTDEV") , ocDBStdDev }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DSTDEVP") , ocDBStdDevP }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DVAR") , ocDBVar }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DVARP") , ocDBVarP }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "INDIRECT") , ocIndirect }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ADDRESS") , ocAddress }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MATCH") , ocMatch }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "XMATCH") , ocXMatch }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNTBLANK") , ocCountEmptyCells }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNTIF") , ocCountIf }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMIF") , ocSumIf }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "AVERAGEIF") , ocAverageIf }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUMIFS") , ocSumIfs }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "AVERAGEIFS") , ocAverageIfs }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COUNTIFS") , ocCountIfs }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LOOKUP") , ocLookup }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VLOOKUP") , ocVLookup }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "XLOOKUP") , ocXLookup }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "HLOOKUP") , ocHLookup }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FILTER") , ocFilter }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SORT") , ocSort }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SORTBY") , ocSortBy }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHOOSECOLS") , ocChooseCols }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHOOSEROWS") , ocChooseRows }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DROP") , ocDrop }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "EXPAND") , ocExpand }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "HSTACK") , ocHStack }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "VSTACK") , ocVStack }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TAKE") , ocTake }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTAFTER") , ocTextAfter }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTBEFORE") , ocTextBefore }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTSPLIT") , ocTextSplit }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TOCOL") , ocToCol }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TOROW") , ocToRow }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "UNIQUE") , ocUnique }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LET") , ocLet }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "WRAPCOLS") , ocWrapCols }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "WRAPROWS") , ocWrapRows }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LAMBDA") , ocLambda }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISOMITTED") , ocIsOmitted }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BYCOL") , ocByCol }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BYROW") , ocByRow }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MAKEARRAY") , ocMakeArray }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MAP") , ocMap }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "REDUCE") , ocReduce }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SCAN") , ocScan }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ARRAYTOTEXT") , ocArrayToText }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MULTIRANGE") , ocMultiArea }, // legacy for range list (union) + { NC_("RID_STRLIST_FUNCTION_NAMES", "OFFSET") , ocOffset }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "INDEX") , ocIndex }, // ?? first character = I ?? + { NC_("RID_STRLIST_FUNCTION_NAMES", "AREAS") , ocAreas }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DOLLAR") , ocCurrency }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "REPLACE") , ocReplace }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FIXED") , ocFixed }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FIND") , ocFind }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "EXACT") , ocExact }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LEFT") , ocLeft }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RIGHT") , ocRight }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SEARCH") , ocSearch }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MID") , ocMid }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LENB") , ocLenB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RIGHTB") , ocRightB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LEFTB") , ocLeftB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "REPLACEB") , ocReplaceB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MIDB") , ocMidB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXT") , ocText }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SUBSTITUTE") , ocSubstitute }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "REPT") , ocRept }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CONCATENATE") , ocConcat }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CONCAT") , ocConcat_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTJOIN") , ocTextJoin_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "IFS") , ocIfs_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SWITCH") , ocSwitch_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MINIFS") , ocMinIfs_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MAXIFS") , ocMaxIfs_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MVALUE") , ocMatValue }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MDETERM") , ocMatDet }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MINVERSE") , ocMatInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MMULT") , ocMatMult }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SEQUENCE") , ocMatSequence }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TRANSPOSE") , ocMatTrans }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MUNIT") , ocMatrixUnit }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GOALSEEK") , ocBackSolver }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "HYPGEOMDIST") , ocHypGeomDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "HYPGEOM.DIST") , ocHypGeomDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGNORMDIST") , ocLogNormDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGNORM.DIST") , ocLogNormDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TDIST") , ocTDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "T.DIST.2T") , ocTDist_2T }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "T.DIST") , ocTDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "T.DIST.RT") , ocTDist_RT }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FDIST") , ocFDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "F.DIST") , ocFDist_LT }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "F.DIST.RT") , ocFDist_RT }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHIDIST") , ocChiDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.DIST.RT") , ocChiDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "WEIBULL") , ocWeibull }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "WEIBULL.DIST") , ocWeibull_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NEGBINOMDIST") , ocNegBinomVert }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NEGBINOM.DIST") , ocNegBinomDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CRITBINOM") , ocCritBinom }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BINOM.INV") , ocBinomInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "KURT") , ocKurt }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "HARMEAN") , ocHarMean }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GEOMEAN") , ocGeoMean }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "STANDARDIZE") , ocStandard }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "AVEDEV") , ocAveDev }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SKEW") , ocSkew }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SKEWP") , ocSkewp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DEVSQ") , ocDevSq }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MEDIAN") , ocMedian }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MODE") , ocModalValue }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MODE.SNGL") , ocModalValue_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MODE.MULT") , ocModalValue_Multi }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ZTEST") , ocZTest }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "Z.TEST") , ocZTest_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "AGGREGATE") , ocAggregate }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TTEST") , ocTTest }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "T.TEST") , ocTTest_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RANK") , ocRank }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTILE") , ocPercentile }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTRANK") , ocPercentrank }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTILE.INC") , ocPercentile_Inc }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTRANK.INC") , ocPercentrank_Inc }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "QUARTILE.INC") , ocQuartile_Inc }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RANK.EQ") , ocRank_Eq }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTILE.EXC") , ocPercentile_Exc }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PERCENTRANK.EXC") , ocPercentrank_Exc }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "QUARTILE.EXC") , ocQuartile_Exc }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RANK.AVG") , ocRank_Avg }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LARGE") , ocLarge }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SMALL") , ocSmall }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FREQUENCY") , ocFrequency }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "QUARTILE") , ocQuartile }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NORMINV") , ocNormInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NORM.INV") , ocNormInv_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CONFIDENCE") , ocConfidence }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CONFIDENCE.NORM") , ocConfidence_N }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CONFIDENCE.T") , ocConfidence_T }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FTEST") , ocFTest }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "F.TEST") , ocFTest_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TRIMMEAN") , ocTrimMean }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PROB") , ocProb }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CORREL") , ocCorrel }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COVAR") , ocCovar }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COVARIANCE.P") , ocCovarianceP }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COVARIANCE.S") , ocCovarianceS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "PEARSON") , ocPearson }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RSQ") , ocRSQ }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "STEYX") , ocSTEYX }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SLOPE") , ocSlope }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "INTERCEPT") , ocIntercept }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TREND") , ocTrend }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GROWTH") , ocGrowth }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LINEST") , ocLinest }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGEST") , ocLogest }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST") , ocForecast }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.ADD") , ocForecast_ETS_ADD }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.SEASONALITY") , ocForecast_ETS_SEA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.MULT") , ocForecast_ETS_MUL }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.PI.ADD") , ocForecast_ETS_PIA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.PI.MULT") , ocForecast_ETS_PIM }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.STAT.ADD") , ocForecast_ETS_STA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.ETS.STAT.MULT") , ocForecast_ETS_STM }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FORECAST.LINEAR") , ocForecast_LIN }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHIINV") , ocChiInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.INV.RT") , ocChiInv_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMADIST") , ocGammaDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMA.DIST") , ocGammaDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMAINV") , ocGammaInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMA.INV") , ocGammaInv_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "TINV") , ocTInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "T.INV.2T") , ocTInv_2T }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "T.INV") , ocTInv_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FINV") , ocFInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "F.INV") , ocFInv_LT }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "F.INV.RT") , ocFInv_RT }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHITEST") , ocChiTest }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.TEST") , ocChiTest_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGINV") , ocLogInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "LOGNORM.INV") , ocLogInv_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "MULTIPLE.OPERATIONS") , ocTableOp }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BETADIST") , ocBetaDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BETAINV") , ocBetaInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BETA.DIST") , ocBetaDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BETA.INV") , ocBetaInv_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "WEEKNUM") , ocWeek }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ISOWEEKNUM") , ocIsoWeeknum }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "WEEKNUM_OOO") , ocWeeknumOOo }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "EASTERSUNDAY") , ocEasterSunday }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "WEEKDAY") , ocGetDayOfWeek }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NETWORKDAYS") , ocNetWorkdays }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NETWORKDAYS.INTL") , ocNetWorkdays_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "WORKDAY.INTL") , ocWorkday_MS }, /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#NAME!") , SC_OPCODE_NO_NAME }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "STYLE") , SC_OPCODE_STYLE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DDE") , SC_OPCODE_DDE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BASE") , SC_OPCODE_BASE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "DECIMAL") , SC_OPCODE_DECIMAL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CONVERT_OOO") , SC_OPCODE_CONVERT_OOO }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ROMAN") , SC_OPCODE_ROMAN }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "HYPERLINK") , SC_OPCODE_HYPERLINK }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "INFO") , SC_OPCODE_INFO }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BAHTTEXT") , SC_OPCODE_BAHTTEXT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GETPIVOTDATA") , SC_OPCODE_GET_PIVOT_DATA }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "EUROCONVERT") , SC_OPCODE_EUROCONVERT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "NUMBERVALUE") , SC_OPCODE_NUMBERVALUE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMA") , SC_OPCODE_GAMMA }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQDIST") , SC_OPCODE_CHISQ_DIST }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.DIST") , SC_OPCODE_CHISQ_DIST_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQINV") , SC_OPCODE_CHISQ_INV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.INV") , SC_OPCODE_CHISQ_INV_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BITAND") , SC_OPCODE_BITAND }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BITOR") , SC_OPCODE_BITOR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BITXOR") , SC_OPCODE_BITXOR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BITRSHIFT") , SC_OPCODE_BITRSHIFT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "BITLSHIFT") , SC_OPCODE_BITLSHIFT }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#NAME!") , ocNoName }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "STYLE") , ocStyle }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DDE") , ocDde }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BASE") , ocBase }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "DECIMAL") , ocDecimal }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CONVERT_OOO") , ocConvertOOo }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ROMAN") , ocRoman }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "HYPERLINK") , ocHyperLink }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "INFO") , ocInfo }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BAHTTEXT") , ocBahtText }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GETPIVOTDATA") , ocGetPivotData }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "EUROCONVERT") , ocEuroConvert }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "NUMBERVALUE") , ocNumberValue }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "GAMMA") , ocGamma }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQDIST") , ocChiSqDist }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.DIST") , ocChiSqDist_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQINV") , ocChiSqInv }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "CHISQ.INV") , ocChiSqInv_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BITAND") , ocBitAnd }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BITOR") , ocBitOr }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BITXOR") , ocBitXor }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BITRSHIFT") , ocBitRshift }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "BITLSHIFT") , ocBitLshift }, /* BEGIN defined ERROR.TYPE() values. */ /* ERROR.TYPE( #NULL! ) == 1 */ /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#NULL!") , SC_OPCODE_ERROR_NULL }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#NULL!") , ocErrNull }, /* ERROR.TYPE( #DIV/0! ) == 2 */ /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#DIV/0!") , SC_OPCODE_ERROR_DIVZERO }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#DIV/0!") , ocErrDivZero }, /* ERROR.TYPE( #VALUE! ) == 3 */ /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#VALUE!") , SC_OPCODE_ERROR_VALUE }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#VALUE!") , ocErrValue }, /* ERROR.TYPE( #REF! ) == 4 */ /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#REF!") , SC_OPCODE_ERROR_REF }, - /* ERROR.TYPE( #NAME! ) == 5 */ + { NC_("RID_STRLIST_FUNCTION_NAMES", "#REF!") , ocErrRef }, + /* ERROR.TYPE( #NAME? ) == 5 */ /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#NAME?") , SC_OPCODE_ERROR_NAME }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#NAME?") , ocErrName }, /* ERROR.TYPE( #NUM! ) == 6 */ /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#NUM!") , SC_OPCODE_ERROR_NUM }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#NUM!") , ocErrNum }, /* ERROR.TYPE( #N/A ) == 7 */ /* L10n: preserve the leading '#' hash character in translations. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "#N/A") , SC_OPCODE_ERROR_NA }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "#N/A") , ocErrNA }, + /* L10n: preserve the leading '#' hash character and trailing '!' in translations. */ + { NC_("RID_STRLIST_FUNCTION_NAMES", "#SPILL!") , ocErrSpill }, /* END defined ERROR.TYPE() values. */ - { NC_("RID_STRLIST_FUNCTION_NAMES", "FILTERXML") , SC_OPCODE_FILTERXML }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "COLOR") , SC_OPCODE_COLOR }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "WEBSERVICE") , SC_OPCODE_WEBSERVICE }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ERF.PRECISE") , SC_OPCODE_ERF_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ERFC.PRECISE") , SC_OPCODE_ERFC_MS }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ENCODEURL") , SC_OPCODE_ENCODEURL }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RAWSUBTRACT") , SC_OPCODE_RAWSUBTRACT }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "ROUNDSIG") , SC_OPCODE_ROUNDSIG }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FINDB") , SC_OPCODE_FINDB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "SEARCHB") , SC_OPCODE_SEARCHB }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "REGEX") , SC_OPCODE_REGEX }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "FOURIER"), SC_OPCODE_FOURIER }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RAND.NV"), SC_OPCODE_RANDOM_NV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RANDBETWEEN.NV"), SC_OPCODE_RANDBETWEEN_NV }, - { NC_("RID_STRLIST_FUNCTION_NAMES", "RANDARRAY"), SC_OPCODE_RANDARRAY }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FILTERXML") , ocFilterXML }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "COLOR") , ocColor }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "WEBSERVICE") , ocWebservice }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ERF.PRECISE") , ocErf_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ERFC.PRECISE") , ocErfc_MS }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ENCODEURL") , ocEncodeURL }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RAWSUBTRACT") , ocRawSubtract }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "ROUNDSIG") , ocRoundSig }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FINDB") , ocFindB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "SEARCHB") , ocSearchB }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "REGEX") , ocRegex }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "FOURIER"), ocFourier }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RAND.NV"), ocRandomNV }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RANDBETWEEN.NV"), ocRandbetweenNV }, + { NC_("RID_STRLIST_FUNCTION_NAMES", "RANDARRAY"), ocRandArray }, { {}, -1 } }; const std::pair RID_STRLIST_FUNCTION_NAMES_SYMBOLS[] = { - { "(" , SC_OPCODE_OPEN }, - { ")" , SC_OPCODE_CLOSE }, - { "[" , SC_OPCODE_TABLE_REF_OPEN }, - { "]" , SC_OPCODE_TABLE_REF_CLOSE }, - { "{" , SC_OPCODE_ARRAY_OPEN }, - { "}" , SC_OPCODE_ARRAY_CLOSE }, - { "|" , SC_OPCODE_ARRAY_ROW_SEP }, - { ";" , SC_OPCODE_ARRAY_COL_SEP }, - { ";" , SC_OPCODE_SEP }, - { "%" , SC_OPCODE_PERCENT_SIGN }, - { "+" , SC_OPCODE_ADD }, - { "-" , SC_OPCODE_SUB }, - { "*" , SC_OPCODE_MUL }, - { "/" , SC_OPCODE_DIV }, - { "&" , SC_OPCODE_AMPERSAND }, - { "^" , SC_OPCODE_POW }, - { "=" , SC_OPCODE_EQUAL }, - { "<>" , SC_OPCODE_NOT_EQUAL }, - { "<" , SC_OPCODE_LESS }, - { ">" , SC_OPCODE_GREATER }, - { "<=" , SC_OPCODE_LESS_EQUAL }, - { ">=" , SC_OPCODE_GREATER_EQUAL }, - { "!" , SC_OPCODE_INTERSECT }, - { "~" , SC_OPCODE_UNION }, - { ":" , SC_OPCODE_RANGE }, - { "-" , SC_OPCODE_NEG_SUB }, + { "(" , ocOpen }, + { ")" , ocClose }, + { "[" , ocTableRefOpen }, + { "]" , ocTableRefClose }, + { "{" , ocArrayOpen }, + { "}" , ocArrayClose }, + { "|" , ocArrayRowSep }, + { ";" , ocArrayColSep }, + { ";" , ocSep }, + { "%" , ocPercentSign }, + { "+" , ocAdd }, + { "-" , ocSub }, + { "*" , ocMul }, + { "/" , ocDiv }, + { "&" , ocAmpersand }, + { "^" , ocPow }, + { "=" , ocEqual }, + { "<>" , ocNotEqual }, + { "<" , ocLess }, + { ">" , ocGreater }, + { "<=" , ocLessEqual }, + { ">=" , ocGreaterEqual }, + { "!" , ocIntersect }, + { "~" , ocUnion }, + { ":" , ocRange }, + { "-" , ocNegSub }, + { "@" , ocSingleValue }, + { "#" , ocSpill }, { nullptr, -1 } }; diff --git a/formula/qa/unit/OOXMLRewriterTest.cxx b/formula/qa/unit/OOXMLRewriterTest.cxx new file mode 100644 index 000000000000..47af68931752 --- /dev/null +++ b/formula/qa/unit/OOXMLRewriterTest.cxx @@ -0,0 +1,323 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +using namespace formula; + +namespace +{ +class OOXMLRewriterTest : public CppUnit::TestFixture +{ +protected: + /** Add an operand. The rewrite reads opcodes and stack types, never whether a token is a + reference, so any push token does. A number is the shortest to build. */ + static void addOperand(FormulaTokenArray& rTokens) { rTokens.AddDouble(1.0); } + + static std::unique_ptr rewrite(const FormulaTokenArray& rTokens) + { + return OOXMLRewriter(rTokens).releaseTokens(); + } + + /** The token sequence as a readable line, so a failure says what came out. The names are + the tokens' own, not the text: a union stays ~ here, though OOXML writes it as a + comma. */ + static OUString describe(const FormulaTokenArray& rTokens) + { + OUStringBuffer aBuffer; + for (sal_uInt16 nPosition = 0; nPosition < rTokens.GetLen(); ++nPosition) + { + if (!aBuffer.isEmpty()) + aBuffer.append(' '); + aBuffer.append(name(rTokens.TokenAt(nPosition)->GetOpCode())); + } + return aBuffer.makeStringAndClear(); + } + +private: + static OUString name(OpCode eOp) + { + switch (eOp) + { + case ocPush: + return u"operand"_ustr; + case ocOpen: + return u"("_ustr; + case ocClose: + return u")"_ustr; + case ocUnion: + return u"~"_ustr; + case ocAdd: + return u"+"_ustr; + case ocSingleValue: + return u"_xlfn.SINGLE"_ustr; + case ocSpill: + return u"#"_ustr; + case ocAnchorArray: + return u"_xlfn.ANCHORARRAY"_ustr; + case ocOffset: + return u"OFFSET"_ustr; + case ocPercentSign: + return u"%"_ustr; + case ocMissing: + return u"missing"_ustr; + case ocBad: + return u"bad"_ustr; + case ocErrRef: + return u"#REF!"_ustr; + default: + return u"?"_ustr; + } + } +}; + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testSpillBecomesACallInFrontOfItsOperand) +{ + // A1# -> _xlfn.ANCHORARRAY(A1). The operator moves and gets an opcode of its own, so + // nothing later has to tell the two spellings apart by position. + FormulaTokenArray aTokens; + addOperand(aTokens); + aTokens.AddOpCode(ocSpill); + + const std::unique_ptr pRewritten = rewrite(aTokens); + + CPPUNIT_ASSERT(pRewritten); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.ANCHORARRAY ( operand )"_ustr, describe(*pRewritten)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testSingleValueKeepsItsPlaceAndGainsParentheses) +{ + // =@A1 -> _xlfn.SINGLE(A1). The @ is already in front, so only the parentheses are new. + FormulaTokenArray aTokens; + aTokens.AddOpCode(ocSingleValue); + addOperand(aTokens); + + const std::unique_ptr pRewritten = rewrite(aTokens); + + CPPUNIT_ASSERT(pRewritten); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE ( operand )"_ustr, describe(*pRewritten)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testAnOperandInParenthesesKeepsTheOnesItHas) +{ + // =@(A1) comes out like =@A1 - the parentheses already there serve, no second pair. + FormulaTokenArray aTokens; + aTokens.AddOpCode(ocSingleValue); + aTokens.AddOpCode(ocOpen); + addOperand(aTokens); + aTokens.AddOpCode(ocClose); + + const std::unique_ptr pRewritten = rewrite(aTokens); + + CPPUNIT_ASSERT(pRewritten); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE ( operand )"_ustr, describe(*pRewritten)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testUnionGainsParenthesesButKeepsItsOpcode) +{ + // A1~B1 -> (A1,B1). ocUnion already spells as a comma, so only the parentheses are new. + FormulaTokenArray aTokens; + addOperand(aTokens); + aTokens.AddOpCode(ocUnion); + addOperand(aTokens); + + const std::unique_ptr pRewritten = rewrite(aTokens); + + CPPUNIT_ASSERT(pRewritten); + CPPUNIT_ASSERT_EQUAL(u"( operand ~ operand )"_ustr, describe(*pRewritten)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testSpillInsideSingleValueNestsTheTwoCalls) +{ + // =@A1# -> _xlfn.SINGLE(_xlfn.ANCHORARRAY(A1)), the @ taking in the whole of the #. + FormulaTokenArray aTokens; + aTokens.AddOpCode(ocSingleValue); + addOperand(aTokens); + aTokens.AddOpCode(ocSpill); + + const std::unique_ptr pRewritten = rewrite(aTokens); + + CPPUNIT_ASSERT(pRewritten); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE ( _xlfn.ANCHORARRAY ( operand ) )"_ustr, + describe(*pRewritten)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testSingleValueClosesBeforeAnArithmeticOperator) +{ + // =@A1+B1 -> _xlfn.SINGLE(A1)+B1. The plus is above the @, so only A1 is under it. + FormulaTokenArray aTokens; + aTokens.AddOpCode(ocSingleValue); + addOperand(aTokens); + aTokens.AddOpCode(ocAdd); + addOperand(aTokens); + + const std::unique_ptr pRewritten = rewrite(aTokens); + + CPPUNIT_ASSERT(pRewritten); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE ( operand ) + operand"_ustr, describe(*pRewritten)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testLiteralFirstArgumentOfOffsetBecomesAnError) +{ + // OFFSET needs a reference in its first argument, so a literal there is swapped for + // #REF!, which is all any reader accepts. + FormulaTokenArray aTokens; + aTokens.AddOpCode(ocOffset); + aTokens.AddOpCode(ocOpen); + aTokens.AddDouble(1.0); + aTokens.AddOpCode(ocClose); + + const std::unique_ptr pRewritten = rewrite(aTokens); + + CPPUNIT_ASSERT(pRewritten); + CPPUNIT_ASSERT_EQUAL(u"OFFSET ( #REF! )"_ustr, describe(*pRewritten)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testAUnionAlreadyInParenthesesNeedsNoRewrite) +{ + // =(A1~B1) already has the parentheses OOXML wants, so there is nothing to change. + FormulaTokenArray aTokens; + aTokens.AddOpCode(ocOpen); + addOperand(aTokens); + aTokens.AddOpCode(ocUnion); + addOperand(aTokens); + aTokens.AddOpCode(ocClose); + + CPPUNIT_ASSERT(!rewrite(aTokens)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testAnAtWithNothingToEncloseIsDropped) +{ + // The call name comes from the wrapper, so an @ that got none has to go rather than write + // _xlfn.SINGLE on its own. + FormulaTokenArray aAlone; + aAlone.AddOpCode(ocSingleValue); + + const std::unique_ptr pAlone = rewrite(aAlone); + + CPPUNIT_ASSERT(pAlone); + CPPUNIT_ASSERT_EQUAL(OUString(), describe(*pAlone)); + + // The operand of the first @ is the second one, which writes nothing either. + FormulaTokenArray aNested; + aNested.AddOpCode(ocSingleValue); + aNested.AddOpCode(ocSingleValue); + + const std::unique_ptr pNested = rewrite(aNested); + + CPPUNIT_ASSERT(pNested); + CPPUNIT_ASSERT_EQUAL(OUString(), describe(*pNested)); + + // A missing argument is a token, but it writes no text, so it fills no operand. + FormulaTokenArray aMissing; + aMissing.AddOpCode(ocSingleValue); + aMissing.AddOpCode(ocMissing); + + const std::unique_ptr pMissing = rewrite(aMissing); + + CPPUNIT_ASSERT(pMissing); + CPPUNIT_ASSERT_EQUAL(u"missing"_ustr, describe(*pMissing)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testASpillWithNoFactorBeforeItIsDropped) +{ + // A percent sign ends the factor, so the # that follows has nothing to enclose. The pair + // would span no tokens at all, so it goes and the # with it. + FormulaTokenArray aTokens; + addOperand(aTokens); + aTokens.AddOpCode(ocPercentSign); + aTokens.AddOpCode(ocSpill); + + const std::unique_ptr pRewritten = rewrite(aTokens); + + CPPUNIT_ASSERT(pRewritten); + CPPUNIT_ASSERT_EQUAL(u"operand %"_ustr, describe(*pRewritten)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testTextThatDidNotParseTakesNoWrapper) +{ + // Parentheses cannot go around text that never parsed, so a wrapper waiting on it is + // dropped and the operator it would have named goes with it. A prefix sign stays. + FormulaTokenArray aSigned; + aSigned.AddOpCode(ocSingleValue); + aSigned.AddOpCode(ocAdd); + aSigned.AddBad(u"PW value"_ustr); + + const std::unique_ptr pSigned = rewrite(aSigned); + + CPPUNIT_ASSERT(pSigned); + CPPUNIT_ASSERT_EQUAL(u"+ bad"_ustr, describe(*pSigned)); + + // Both @ wrappers go at once. + FormulaTokenArray aNested; + aNested.AddOpCode(ocSingleValue); + aNested.AddOpCode(ocSingleValue); + aNested.AddBad(u"PW value"_ustr); + + const std::unique_ptr pNested = rewrite(aNested); + + CPPUNIT_ASSERT(pNested); + CPPUNIT_ASSERT_EQUAL(u"bad"_ustr, describe(*pNested)); + + // A # behind such text has nothing to bind to either. + FormulaTokenArray aSpilled; + aSpilled.AddOpCode(ocSingleValue); + aSpilled.AddBad(u"PW value"_ustr); + aSpilled.AddOpCode(ocSpill); + + const std::unique_ptr pSpilled = rewrite(aSpilled); + + CPPUNIT_ASSERT(pSpilled); + CPPUNIT_ASSERT_EQUAL(u"bad"_ustr, describe(*pSpilled)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testAUnionReachingSuchTextNeedsNoRewrite) +{ + // The list loses its parentheses for the same reason. With nothing else to change and no + // token to drop, there is no rewrite at all. + FormulaTokenArray aTokens; + addOperand(aTokens); + aTokens.AddOpCode(ocUnion); + aTokens.AddBad(u"PW value"_ustr); + + CPPUNIT_ASSERT(!rewrite(aTokens)); +} + +CPPUNIT_TEST_FIXTURE(OOXMLRewriterTest, testAnExpressionThatNeedsNoRewrite) +{ + // A1+B1 reads the same in both grammars. + FormulaTokenArray aTokens; + addOperand(aTokens); + aTokens.AddOpCode(ocAdd); + addOperand(aTokens); + + CPPUNIT_ASSERT(!rewrite(aTokens)); +} +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx index f9e5107e05d2..5ab0b2304429 100644 --- a/formula/source/core/api/FormulaCompiler.cxx +++ b/formula/source/core/api/FormulaCompiler.cxx @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,9 @@ #include #include #include +#include + +#include #include #include @@ -56,6 +60,15 @@ class FormulaCompilerRecursionGuard ~FormulaCompilerRecursionGuard() { --rRecursion; } }; +// True when the opcode needs an operand after it: the prefix unary +// and binary operators. The postfix # is excluded, as its operand +// comes before it, so a binary operator may follow it. +bool isOperatorExpectingOperand(OpCode eOp) +{ + return (isBinaryOperatorOpCode(eOp) || isUnaryOperatorOpCode(eOp)) + && eOp != ocSpill; +} + SvNumFormatType lcl_GetRetFormat( OpCode eOpCode ) { switch (eOpCode) @@ -181,14 +194,14 @@ OpCodeList::OpCodeList(const std::pair* pSymbols, const Formul const CharClass* pCharClass = xCharClass.get(); if (meSepType == FormulaCompiler::SeparatorType::RESOURCE_BASE) { - for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i) + for (sal_uInt16 i = 0; i <= ocLastOpcodeId; ++i) { putDefaultOpCode( xMap, i, pCharClass); } } else { - for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i) + for (sal_uInt16 i = 0; i <= ocLastOpcodeId; ++i) { OUString aOpStr; if ( getOpCodeString( aOpStr, i) ) @@ -209,14 +222,14 @@ OpCodeList::OpCodeList(const std::pair* pSymbols, const Formul const CharClass* pCharClass = xCharClass.get(); if (meSepType == FormulaCompiler::SeparatorType::RESOURCE_BASE) { - for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i) + for (sal_uInt16 i = 0; i <= ocLastOpcodeId; ++i) { putDefaultOpCode( xMap, i, pCharClass); } } else { - for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i) + for (sal_uInt16 i = 0; i <= ocLastOpcodeId; ++i) { OUString aOpStr; if ( getOpCodeString( aOpStr, i) ) @@ -231,7 +244,7 @@ bool OpCodeList::getOpCodeString( OUString& rStr, sal_uInt16 nOp ) { switch (nOp) { - case SC_OPCODE_SEP: + case ocSep: { if (meSepType == FormulaCompiler::SeparatorType::SEMICOLON_BASE) { @@ -240,7 +253,7 @@ bool OpCodeList::getOpCodeString( OUString& rStr, sal_uInt16 nOp ) } } break; - case SC_OPCODE_ARRAY_COL_SEP: + case ocArrayColSep: { if (meSepType == FormulaCompiler::SeparatorType::SEMICOLON_BASE) { @@ -249,7 +262,7 @@ bool OpCodeList::getOpCodeString( OUString& rStr, sal_uInt16 nOp ) } } break; - case SC_OPCODE_ARRAY_ROW_SEP: + case ocArrayRowSep: { if (meSepType == FormulaCompiler::SeparatorType::SEMICOLON_BASE) { @@ -326,6 +339,9 @@ bool isPotentialRangeLeftOp( OpCode eOp ) switch (eOp) { case ocClose: + // The # comes after its operand, so it is the last opcode of a sub-expression that + // yields a reference. + case ocSpill: return true; default: return false; @@ -338,6 +354,9 @@ bool isRangeResultFunction( OpCode eOp ) { case ocIndirect: case ocOffset: + // In OOXML the # is written before its operand, so there it is the first opcode of a + // sub-expression that yields a reference. + case ocSpill: return true; default: return false; @@ -353,6 +372,10 @@ bool isRangeResultOpCode( OpCode eOp ) case ocIntersect: case ocIndirect: case ocOffset: + case ocIndex: + // The # postfix operator gives the spill range of the master cell before it, which + // is a reference just like the operators above. + case ocSpill: return true; default: return false; @@ -389,8 +412,9 @@ bool isPotentialRangeType( FormulaToken const * pToken, bool bRPN, bool bRight ) return true; case svSep: // A special case if a previous ocSep was converted to ocUnion it - // stays svSep instead of svByte. - return bRPN && !bRight && pToken->GetOpCode() == ocUnion; + // stays svSep instead of svByte. A union yields a reference, so it + // is fine on either side of an operator. + return bRPN && pToken->GetOpCode() == ocUnion; default: // Separators are not part of RPN and right opcodes need to be // other StackVar types or functions and thus svByte. @@ -398,6 +422,46 @@ bool isPotentialRangeType( FormulaToken const * pToken, bool bRPN, bool bRight ) } } +/** Whether a token can start a part of a parenthesised range list: a reference, or a + function that returns one. Only the start matters, what the rest of the part makes of + it is the calculation's business. Anything else leaves the separator a separator. + */ +bool isRangeListPartStart( const FormulaToken& rToken ) +{ + switch (rToken.GetType()) + { + case svSingleRef: + case svDoubleRef: + case svExternalSingleRef: + case svExternalDoubleRef: + case svExternalName: + case svIndex: + // An error constant is a part too, and its error becomes the union's result. + case svError: + return true; + default: + break; + } + switch (rToken.GetOpCode()) + { + // A parenthesised part, for example a nested list. + case ocOpen: + // IF and CHOOSE return the reference of the branch they take, IFS and SWITCH the + // reference of the result they pick, and a lookup a piece of the range it searched. + case ocIf: + case ocChoose: + case ocIfs_MS: + case ocSwitch_MS: + case ocIndex: + case ocXLookup: + // The @ operator comes before a reference it reads one value from. + case ocSingleValue: + return true; + default: + return isRangeResultFunction( rToken.GetOpCode()); + } +} + bool isIntersectable( FormulaToken** pCode1, FormulaToken** pCode2 ) { FormulaToken* pToken1 = *pCode1; @@ -557,27 +621,23 @@ uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::create } else { - /* FIXME: Once we support error constants in formulas we'll need a map - * group for that, e.g. FormulaMapGroup::ERROR_CONSTANTS, and fill - * SC_OPCODE_START_ERRORS to SC_OPCODE_STOP_ERRORS. */ - // Anything else but SPECIAL. if ((nGroups & FormulaMapGroup::SEPARATORS) != 0) { static const sal_uInt16 aOpCodes[] = { - SC_OPCODE_OPEN, - SC_OPCODE_CLOSE, - SC_OPCODE_SEP, + ocOpen, + ocClose, + ocSep, }; lclPushOpCodeMapEntries( aVec, mpTable.get(), aOpCodes, std::size(aOpCodes) ); } if ((nGroups & FormulaMapGroup::ARRAY_SEPARATORS) != 0) { static const sal_uInt16 aOpCodes[] = { - SC_OPCODE_ARRAY_OPEN, - SC_OPCODE_ARRAY_CLOSE, - SC_OPCODE_ARRAY_ROW_SEP, - SC_OPCODE_ARRAY_COL_SEP + ocArrayOpen, + ocArrayClose, + ocArrayRowSep, + ocArrayColSep }; lclPushOpCodeMapEntries( aVec, mpTable.get(), aOpCodes, std::size(aOpCodes) ); } @@ -590,21 +650,21 @@ uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::create if ((nGroups & FormulaMapGroup::BINARY_OPERATORS) == 0) lclPushOpCodeMapEntry( aVec, mpTable.get(), ocAdd ); // regular unary operators - for (sal_uInt16 nOp = SC_OPCODE_START_UN_OP; nOp < SC_OPCODE_STOP_UN_OP && nOp < mnSymbols; ++nOp) + for (sal_uInt16 nOp = ocStartUnaryOperators; nOp < ocStopUnaryOperators && nOp < mnSymbols; ++nOp) { lclPushOpCodeMapEntry( aVec, mpTable.get(), nOp ); } } if ((nGroups & FormulaMapGroup::BINARY_OPERATORS) != 0) { - for (sal_uInt16 nOp = SC_OPCODE_START_BIN_OP; nOp < SC_OPCODE_STOP_BIN_OP && nOp < mnSymbols; ++nOp) + for (sal_uInt16 nOp = ocStartBinaryOperators; nOp < ocStopBinaryOperators && nOp < mnSymbols; ++nOp) { switch (nOp) { // AND and OR in fact are functions but for legacy reasons // are sorted into binary operators for compiler interna. - case SC_OPCODE_AND : - case SC_OPCODE_OR : + case ocAnd : + case ocOr : break; // nothing, default: lclPushOpCodeMapEntry( aVec, mpTable.get(), nOp ); @@ -615,28 +675,29 @@ uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::create { // Function names are not consecutive, skip the gaps between // functions with no parameter, functions with 1 parameter - lclPushOpCodeMapEntries( aVec, mpTable.get(), SC_OPCODE_START_NO_PAR, - ::std::min< sal_uInt16 >( SC_OPCODE_STOP_NO_PAR, mnSymbols ) ); - lclPushOpCodeMapEntries( aVec, mpTable.get(), SC_OPCODE_START_1_PAR, - ::std::min< sal_uInt16 >( SC_OPCODE_STOP_1_PAR, mnSymbols ) ); + lclPushOpCodeMapEntries( aVec, mpTable.get(), ocStartNoParameters, + ::std::min< sal_uInt16 >( ocStopNoParameters, mnSymbols ) ); + lclPushOpCodeMapEntries( aVec, mpTable.get(), ocStartOneParameter, + ::std::min< sal_uInt16 >( ocStopOneParameter, mnSymbols ) ); // Additional functions not within range of functions. static const sal_uInt16 aOpCodes[] = { - SC_OPCODE_IF, - SC_OPCODE_IF_ERROR, - SC_OPCODE_IF_NA, - SC_OPCODE_CHOOSE, - SC_OPCODE_LET, - SC_OPCODE_AND, - SC_OPCODE_OR + ocIf, + ocIfError, + ocIfNA, + ocChoose, + ocLet, + ocLambda, + ocAnd, + ocOr }; lclPushOpCodeMapEntries( aVec, mpTable.get(), aOpCodes, std::size(aOpCodes) ); // functions with 2 or more parameters. - for (sal_uInt16 nOp = SC_OPCODE_START_2_PAR; nOp < SC_OPCODE_STOP_2_PAR && nOp < mnSymbols; ++nOp) + for (sal_uInt16 nOp = ocStartTwoParameters; nOp < ocStopTwoParameters && nOp < mnSymbols; ++nOp) { switch (nOp) { // NO_NAME is in SPECIAL. - case SC_OPCODE_NO_NAME : + case ocNoName : break; // nothing, default: lclPushOpCodeMapEntry( aVec, mpTable.get(), nOp ); @@ -659,6 +720,11 @@ uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::create rCompiler.fillAddInToken( aVec, isEnglish()); } } + if ((nGroups & FormulaMapGroup::ERROR_CONSTANTS) != 0) + { + lclPushOpCodeMapEntries( aVec, mpTable.get(), ocStartErrors, + ::std::min< sal_uInt16 >( ocStopErrors, mnSymbols ) ); + } } return uno::Sequence< FormulaOpCodeMapEntry >(aVec.data(), aVec.size()); } @@ -674,6 +740,11 @@ void FormulaCompiler::OpCodeMap::putOpCode( const OUString & rStr, const OpCode { switch (eOp) { + // The _xlpm. and _xlop. prefixes both introduce a lambda + // parameter name. Keep the first spelling for output and + // register the rest as recognized aliases for input. + case ocStringName: + break; // These OpCodes are meant to overwrite and also remove an // existing mapping. case ocCurrency: @@ -765,24 +836,25 @@ void FormulaCompiler::OpCodeMap::putOpCode( const OUString & rStr, const OpCode FormulaCompiler::FormulaCompiler( FormulaTokenArray& rArr, bool bComputeII, bool bMatrixFlag ) : - nCurrentFactorParam(0), - pArr( &rArr ), + mnCurrentFactorParam(0), + mpArr( &rArr ), maArrIterator( rArr ), - pCode( nullptr ), - pStack( nullptr ), - eLastOp( ocPush ), - nRecursion( 0 ), - nNumFmt( SvNumFormatType::UNDEFINED ), - pc( 0 ), + mpCode( nullptr ), + mpStack( nullptr ), + meLastOp( ocPush ), + mnRecursion( 0 ), + mnNumFmt( SvNumFormatType::UNDEFINED ), + mnPC( 0 ), meGrammar( formula::FormulaGrammar::GRAM_UNSPECIFIED ), - bAutoCorrect( false ), - bCorrected( false ), - glSubTotal( false ), - needsRPNTokenCheck( false ), + mbAutoCorrect( false ), + mbCorrected( false ), + mbGlSubTotal( false ), + mbNeedsRPNTokenCheck( false ), mbJumpCommandReorder(true), mbStopOnError(true), mbComputeII(bComputeII), - mbMatrixFlag(bMatrixFlag) + mbMatrixFlag(bMatrixFlag), + mbPreferLocalNames(false) { } @@ -790,24 +862,25 @@ FormulaTokenArray FormulaCompiler::smDummyTokenArray; FormulaCompiler::FormulaCompiler(bool bComputeII, bool bMatrixFlag) : - nCurrentFactorParam(0), - pArr( nullptr ), + mnCurrentFactorParam(0), + mpArr( nullptr ), maArrIterator( smDummyTokenArray ), - pCode( nullptr ), - pStack( nullptr ), - eLastOp( ocPush ), - nRecursion(0), - nNumFmt( SvNumFormatType::UNDEFINED ), - pc( 0 ), + mpCode( nullptr ), + mpStack( nullptr ), + meLastOp( ocPush ), + mnRecursion(0), + mnNumFmt( SvNumFormatType::UNDEFINED ), + mnPC( 0 ), meGrammar( formula::FormulaGrammar::GRAM_UNSPECIFIED ), - bAutoCorrect( false ), - bCorrected( false ), - glSubTotal( false ), - needsRPNTokenCheck( false ), + mbAutoCorrect( false ), + mbCorrected( false ), + mbGlSubTotal( false ), + mbNeedsRPNTokenCheck( false ), mbJumpCommandReorder(true), mbStopOnError(true), mbComputeII(bComputeII), - mbMatrixFlag(bMatrixFlag) + mbMatrixFlag(bMatrixFlag), + mbPreferLocalNames(false) { } @@ -939,7 +1012,7 @@ FormulaCompiler::OpCodeMapPtr FormulaCompiler::CreateOpCodeMap( { using sheet::FormulaOpCodeMapEntry; // Filter / API maps are never Core - NonConstOpCodeMapPtr xMap = std::make_shared( SC_OPCODE_LAST_OPCODE_ID + 1, false, + NonConstOpCodeMapPtr xMap = std::make_shared( ocLastOpcodeId + 1, false, FormulaGrammar::mergeToGrammar( FormulaGrammar::setEnglishBit( FormulaGrammar::GRAM_EXTERNAL, bEnglish), FormulaGrammar::CONV_UNSPECIFIED)); std::unique_ptr xCharClass( xMap->isEnglish() ? nullptr : createCharClassIfNonEnglishUI()); @@ -966,7 +1039,7 @@ FormulaCompiler::OpCodeMapPtr FormulaCompiler::CreateOpCodeMap( static bool lcl_fillNativeSymbols( FormulaCompiler::NonConstOpCodeMapPtr& xMap, FormulaCompiler::InitSymbols eWhat = FormulaCompiler::InitSymbols::INIT ) { static OpCodeMapData aSymbolMap; - static std::map aLocaleSymbolMap; + static std::unordered_map aLocaleSymbolMap; std::unique_lock aGuard(aSymbolMap.maMtx); if (comphelper::LibreOfficeKit::isActive()) @@ -977,23 +1050,25 @@ static bool lcl_fillNativeSymbols( FormulaCompiler::NonConstOpCodeMapPtr& xMap, return aLocaleSymbolMap.contains(language) && bool(aLocaleSymbolMap[language].mxSymbolMap); } - else if (eWhat == FormulaCompiler::InitSymbols::DESTROY) + + auto& rEntry = aLocaleSymbolMap[language]; + if (eWhat == FormulaCompiler::InitSymbols::DESTROY) { - aLocaleSymbolMap[language].mxSymbolMap.reset(); + rEntry.mxSymbolMap.reset(); } - else if (!aLocaleSymbolMap[language].mxSymbolMap) + else if (!rEntry.mxSymbolMap) { // Core - aLocaleSymbolMap[language].mxSymbolMap = std::make_shared( - SC_OPCODE_LAST_OPCODE_ID + 1, true, FormulaGrammar::GRAM_NATIVE_UI); + rEntry.mxSymbolMap = std::make_shared( + ocLastOpcodeId + 1, true, FormulaGrammar::GRAM_NATIVE_UI); OpCodeList aOpCodeListSymbols(RID_STRLIST_FUNCTION_NAMES_SYMBOLS, - aLocaleSymbolMap[language].mxSymbolMap); + rEntry.mxSymbolMap); OpCodeList aOpCodeListNative(RID_STRLIST_FUNCTION_NAMES, - aLocaleSymbolMap[language].mxSymbolMap); + rEntry.mxSymbolMap); // No AddInMap for native core mapping. } - xMap = aLocaleSymbolMap[language].mxSymbolMap; + xMap = rEntry.mxSymbolMap; } else { @@ -1009,7 +1084,7 @@ static bool lcl_fillNativeSymbols( FormulaCompiler::NonConstOpCodeMapPtr& xMap, { // Core aSymbolMap.mxSymbolMap = std::make_shared( - SC_OPCODE_LAST_OPCODE_ID + 1, true, FormulaGrammar::GRAM_NATIVE_UI); + ocLastOpcodeId + 1, true, FormulaGrammar::GRAM_NATIVE_UI); OpCodeList aOpCodeListSymbols(RID_STRLIST_FUNCTION_NAMES_SYMBOLS, aSymbolMap.mxSymbolMap); OpCodeList aOpCodeListNative(RID_STRLIST_FUNCTION_NAMES, aSymbolMap.mxSymbolMap); @@ -1141,7 +1216,7 @@ void FormulaCompiler::loadSymbols(const std::pair* pSymbols, F return; // not Core - rxMap = std::make_shared( SC_OPCODE_LAST_OPCODE_ID + 1, eGrammar != FormulaGrammar::GRAM_ODFF, eGrammar ); + rxMap = std::make_shared( ocLastOpcodeId + 1, eGrammar != FormulaGrammar::GRAM_ODFF, eGrammar ); OpCodeList aOpCodeList(pSymbols, rxMap, eSepType); fillFromAddInMap( rxMap, eGrammar); @@ -1202,7 +1277,7 @@ bool FormulaCompiler::IsOpCodeVolatile( OpCode eOp ) // one parameter: case ocFormula: case ocInfo: - // more than one parameters: + // more than one parameter: // ocIndirect otherwise would have to do // StopListening and StartListening on a reference for every // interpreted value. @@ -1213,6 +1288,15 @@ bool FormulaCompiler::IsOpCodeVolatile( OpCode eOp ) case ocDebugVar: // ocRandArray is a volatile function. case ocRandArray: + // ocCall could wind up calling any of the above + // as could any higher-order function that uses callables + case ocCall: + case ocByCol: + case ocByRow: + case ocMakeArray: + case ocMap: + case ocReduce: + case ocScan: bRet = true; break; default: @@ -1231,6 +1315,7 @@ bool FormulaCompiler::IsOpCodeJumpCommand( OpCode eOp ) case ocIfNA: case ocChoose: case ocLet: + case ocLambda: return true; default: ; @@ -1292,6 +1377,7 @@ bool FormulaCompiler::IsMatrixFunction( OpCode eOpCode ) case ocLet : case ocWrapCols : case ocWrapRows : + case ocMakeArray : return true; default: { @@ -1427,6 +1513,9 @@ FormulaError FormulaCompiler::GetErrorConstant( const OUString& rName ) const case ocErrNA: nError = FormulaError::NotAvailable; break; + case ocErrSpill: + nError = FormulaError::Spill; + break; default: ; // nothing } @@ -1482,6 +1571,9 @@ void FormulaCompiler::AppendErrorConstant( OUStringBuffer& rBuffer, FormulaError case FormulaError::NotAvailable: eOp = ocErrNA; break; + case FormulaError::Spill: + eOp = ocErrSpill; + break; default: { // Per convention create detailed "#ERRxxx!" constants, always @@ -1499,32 +1591,32 @@ constexpr short nRecursionMax = 100; bool FormulaCompiler::GetToken() { - FormulaCompilerRecursionGuard aRecursionGuard( nRecursion ); - if ( nRecursion > nRecursionMax ) + FormulaCompilerRecursionGuard aRecursionGuard( mnRecursion ); + if ( mnRecursion > nRecursionMax ) { SetError( FormulaError::StackOverflow ); mpLastToken = mpToken = new FormulaByteToken( ocStop ); return false; } - if ( bAutoCorrect && !pStack ) + if ( mbAutoCorrect && !mpStack ) { // don't merge stacked subroutine code into entered formula - aCorrectedFormula += aCorrectedSymbol; - aCorrectedSymbol.clear(); + maCorrectedFormula += maCorrectedSymbol; + maCorrectedSymbol.clear(); } bool bStop = false; - if (pArr->GetCodeError() != FormulaError::NONE && mbStopOnError) + if (mpArr->GetCodeError() != FormulaError::NONE && mbStopOnError) bStop = true; else { FormulaTokenRef pSpacesToken; short nWasColRowName; - if ( pArr->OpCodeBefore( maArrIterator.GetIndex() ) == ocColRowName ) + if ( mpArr->OpCodeBefore( maArrIterator.GetIndex() ) == ocColRowName ) nWasColRowName = 1; else nWasColRowName = 0; OpCode eTmpOp; mpToken = maArrIterator.Next(); - while (mpToken && ((eTmpOp = mpToken->GetOpCode()) == ocSpaces || eTmpOp == ocWhitespace)) + while (mpToken && isWhitespaceOpCode(eTmpOp = mpToken->GetOpCode())) { if (eTmpOp == ocSpaces) { @@ -1534,15 +1626,15 @@ bool FormulaCompiler::GetToken() if ( nWasColRowName ) nWasColRowName++; } - if ( bAutoCorrect && !pStack ) - CreateStringFromToken( aCorrectedFormula, mpToken.get() ); + if ( mbAutoCorrect && !mpStack ) + CreateStringFromToken( maCorrectedFormula, mpToken.get() ); mpToken = maArrIterator.Next(); } - if ( bAutoCorrect && !pStack && mpToken ) - CreateStringFromToken( aCorrectedSymbol, mpToken.get() ); + if ( mbAutoCorrect && !mpStack && mpToken ) + CreateStringFromToken( maCorrectedSymbol, mpToken.get() ); if( !mpToken ) { - if( pStack ) + if( mpStack ) { PopTokenArray(); // mpLastToken was popped as well and corresponds to the @@ -1562,7 +1654,8 @@ bool FormulaCompiler::GetToken() } else if (pSpacesToken && FormulaGrammar::isExcelSyntax( meGrammar) && mpLastToken && mpToken && - isPotentialRangeType( mpToken.get(), false, true) && + (mpToken->GetOpCode() == ocOpen + || isPotentialRangeType(mpToken.get(), false, true)) && (mpLastToken->GetOpCode() == ocClose || isPotentialRangeType( mpLastToken.get(), false, false))) { // Let IntersectionLine() <- Factor() decide how to treat this, @@ -1593,7 +1686,7 @@ bool FormulaCompiler::GetToken() { case ocSubTotal: case ocAggregate: - glSubTotal = true; + mbGlSubTotal = true; break; case ocStringName: if( HandleStringName()) @@ -1610,7 +1703,7 @@ bool FormulaCompiler::GetToken() { // Expanding ocName might have introduced tokens such as ocStyle that prevent formula threading, // but those wouldn't be present in the raw tokens array, so ensure RPN tokens will be checked too. - needsRPNTokenCheck = true; + mbNeedsRPNTokenCheck = true; return true; } return false; @@ -1635,7 +1728,7 @@ bool FormulaCompiler::GetToken() // RPN creation by recursion void FormulaCompiler::Factor() { - if (pArr->GetCodeError() != FormulaError::NONE && mbStopOnError) + if (mpArr->GetCodeError() != FormulaError::NONE && mbStopOnError) return; CurrentFactor pFacToken( this ); @@ -1655,10 +1748,10 @@ void FormulaCompiler::Factor() ( mpToken->GetType() == svString || mpToken->GetType() == svSingleRef ) ? FormulaError::NoName : FormulaError::OperatorExpected ); - if ( bAutoCorrect && !pStack ) + if ( mbAutoCorrect && !mpStack ) { // assume multiplication - aCorrectedFormula += mxSymbols->getSymbol( ocMul); - bCorrected = true; + maCorrectedFormula += mxSymbols->getSymbol( ocMul); + mbCorrected = true; NextToken(); eOp = Expression(); if( eOp != ocClose ) @@ -1672,28 +1765,29 @@ void FormulaCompiler::Factor() { NextToken(); eOp = Expression(); - while ((eOp == ocSep) && (pArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) + while ((eOp == ocSep) && (mpArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) { // range list (A1;A2) converted to (A1~A2) pFacToken = mpToken; NextToken(); CheckSetForceArrayParameter( mpToken, 0); + // What the part starts with decides whether it can join the list. + const FormulaTokenRef pPartFirst = mpToken; + const sal_uInt16 nPartStart = mnPC; eOp = Expression(); // Do not ignore error here, regardless of mbStopOnError, to not // change the formula expression in case of an unexpected state. - if (pArr->GetCodeError() == FormulaError::NONE && pc >= 2) + if (mpArr->GetCodeError() == FormulaError::NONE && nPartStart >= 1 && mnPC > nPartStart) { - // Left and right operands must be reference or function - // returning reference to form a range list. - const FormulaToken* p = pCode[-2]; - if (p && isPotentialRangeType( p, true, false)) + // The left operand has to be a reference or a function that returns one. + // The right part joins if it starts with one. What the part does with it + // from there is up to the calculation. + const FormulaToken* pLeft = mpCode[-static_cast(mnPC - nPartStart) - 1]; + if (pLeft && isPotentialRangeType(pLeft, true, false) + && pPartFirst && isRangeListPartStart(*pPartFirst)) { - p = pCode[-1]; - if (p && isPotentialRangeType( p, true, true)) - { - pFacToken->NewOpCode( ocUnion, FormulaToken::PrivateAccess()); - // XXX NOTE: the token's eType is still svSep here! - PutCode( pFacToken); - } + pFacToken->NewOpCode(ocUnion, FormulaToken::PrivateAccess()); + // XXX NOTE: the token's eType is still svSep here! + PutCode(pFacToken); } } } @@ -1715,63 +1809,101 @@ void FormulaCompiler::Factor() } else { - if( nNumFmt == SvNumFormatType::UNDEFINED ) - nNumFmt = lcl_GetRetFormat( eOp ); + if( mnNumFmt == SvNumFormatType::UNDEFINED ) + mnNumFmt = lcl_GetRetFormat( eOp ); - if ( IsOpCodeVolatile( eOp) ) - pArr->SetExclusiveRecalcModeAlways(); - else + if ( std::none_of( maBindings.begin(), maBindings.end(), [](BindingsLayer aLayer) { + return aLayer.eOpCode == ocLambda; + })) // anything inside a LAMBDA is never volatile, until it's called { - switch( eOp ) + if ( IsOpCodeVolatile( eOp) ) + mpArr->SetExclusiveRecalcModeAlways(); + else { - // Functions recalculated on every document load. - // ONLOAD_LENIENT here to be able to distinguish and not - // force a recalc (if not in an ALWAYS or ONLOAD_MUST - // context) but keep an imported result from for example - // OOXML a DDE call. Will be recalculated for ODFF. - case ocConvertOOo : - case ocDde: - case ocMacro: - case ocWebservice: - pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); - break; - // RANDBETWEEN() is volatile like RAND(). Other Add-In - // functions may have to be recalculated or not, we don't - // know, classify as ONLOAD_LENIENT. - case ocExternal: - if (mpToken->GetExternal() == "com.sun.star.sheet.addin.Analysis.getRandbetween") - pArr->SetExclusiveRecalcModeAlways(); - else - pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); - break; - // If the referred cell is moved the value changes. - case ocColumn : - case ocRow : - pArr->SetRecalcModeOnRefMove(); - break; - // ocCell needs recalc on move for some possible type values. - // And recalc mode on load, tdf#60645 - case ocCell : - pArr->SetRecalcModeOnRefMove(); - pArr->AddRecalcMode( ScRecalcMode::ONLOAD_MUST ); - break; - case ocHyperLink : - // Cell with hyperlink needs to be calculated on load to - // get its matrix result generated. - pArr->AddRecalcMode( ScRecalcMode::ONLOAD_MUST ); - pArr->SetHyperLink( true); - break; - default: - ; // nothing + switch( eOp ) + { + // Functions recalculated on every document load. + // ONLOAD_LENIENT here to be able to distinguish and not + // force a recalc (if not in an ALWAYS or ONLOAD_MUST + // context) but keep an imported result from for example + // OOXML a DDE call. Will be recalculated for ODFF. + case ocConvertOOo : + case ocDde: + case ocMacro: + case ocWebservice: + mpArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); + break; + // RANDBETWEEN() is volatile like RAND(). Other Add-In + // functions may have to be recalculated or not, we don't + // know, classify as ONLOAD_LENIENT. + case ocExternal: + case ocUDExternal: + if (mpToken->GetType() == svExternal + && static_cast(mpToken.get())->GetExternal() + == "com.sun.star.sheet.addin.Analysis.getRandbetween") + mpArr->SetExclusiveRecalcModeAlways(); + else + mpArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); + break; + // If the referred cell is moved the value changes. + case ocColumn : + case ocRow : + mpArr->SetRecalcModeOnRefMove(); + break; + // ocCell needs recalc on move for some possible type values. + // And recalc mode on load, tdf#60645 + case ocCell : + mpArr->SetRecalcModeOnRefMove(); + mpArr->AddRecalcMode( ScRecalcMode::ONLOAD_MUST ); + break; + case ocHyperLink : + // Cell with hyperlink needs to be calculated on load to + // get its matrix result generated. + mpArr->AddRecalcMode( ScRecalcMode::ONLOAD_MUST ); + mpArr->SetHyperLink( true); + break; + // Functions whose natural output is a dynamic array. A + // 1 by 1 declared matrix formula wrapping one of these is + // treated as a dynamic array. Other matrix formulas keep + // their declared dimensions. + case ocUnique: + case ocFilter: + case ocSort: + case ocSortBy: + case ocMatSequence: + case ocRandArray: + case ocChooseCols: + case ocChooseRows: + case ocDrop: + case ocExpand: + case ocHStack: + case ocVStack: + case ocTake: + case ocTextSplit: + case ocToCol: + case ocToRow: + case ocWrapCols: + case ocWrapRows: + case ocByCol: + case ocByRow: + case ocMakeArray: + case ocMap: + case ocScan: + mpArr->SetDynamicArrayFunction( true); + break; + default: + ; // nothing + } } } - if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR) + if (ocStartNoParameters <= eOp && eOp < ocStopNoParameters) { pFacToken = mpToken; eOp = NextToken(); if (eOp != ocOpen) { - SetError( FormulaError::PairExpected); + // if we're not calling the function right now, we need the Callable form + pFacToken = new FormulaCallableToken( FormulaBuiltInFunction::Get( pFacToken->GetOpCode() ) ); PutCode( pFacToken ); } else @@ -1783,7 +1915,7 @@ void FormulaCompiler::Factor() NextToken(); } } - else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) + else if (ocStartOneParameter <= eOp && eOp < ocStopOneParameter) { if (eOp == ocIsoWeeknum && FormulaGrammar::isODFF( meGrammar )) { @@ -1810,7 +1942,7 @@ void FormulaCompiler::Factor() if( !bNoParam ) { nSepCount++; - while ((eOp == ocSep) && (pArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) + while ((eOp == ocSep) && (mpArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) { NextToken(); CheckSetForceArrayParameter( mpToken, nSepCount); @@ -1824,7 +1956,7 @@ void FormulaCompiler::Factor() SetError( FormulaError::PairExpected); else NextToken(); - pFacToken->SetByte( nSepCount ); + static_cast(&*pFacToken)->SetByte( nSepCount ); if (nSepCount == 2) { // An old mode!=1 indicates ISO week, remove argument if @@ -1835,18 +1967,18 @@ void FormulaCompiler::Factor() // Current index is nSepPos+3 if expression stops, or // nSepPos+4 if expression continues after the call because // we just called NextToken() to move away from it. - if (pc >= 2 && (maArrIterator.GetIndex() == nSepPos + 3 || maArrIterator.GetIndex() == nSepPos + 4) && - pArr->TokenAt(nSepPos+1)->GetType() == svDouble && - pArr->TokenAt(nSepPos+1)->GetDouble() != 1.0 && - pArr->TokenAt(nSepPos+2)->GetOpCode() == ocClose && - pArr->RemoveToken( nSepPos, 2) == 2) + if (mnPC >= 2 && (maArrIterator.GetIndex() == nSepPos + 3 || maArrIterator.GetIndex() == nSepPos + 4) && + mpArr->TokenAt(nSepPos+1)->GetType() == svDouble && + static_cast(mpArr->TokenAt(nSepPos+1))->GetDouble() != 1.0 && + mpArr->TokenAt(nSepPos+2)->GetOpCode() == ocClose && + mpArr->RemoveToken( nSepPos, 2) == 2) { maArrIterator.AfterRemoveToken( nSepPos, 2); // Remove the ocPush/svDouble just removed also from // the compiler local RPN array. - --pCode; --pc; - (*pCode)->DecRef(); // may be dead now - pFacToken->SetByte( nSepCount - 1 ); + --mpCode; --mnPC; + (*mpCode)->DecRef(); // may be dead now + static_cast(&*pFacToken)->SetByte( nSepCount - 1 ); } else { @@ -1862,33 +1994,38 @@ void FormulaCompiler::Factor() // standard handling of 1-parameter opcodes pFacToken = mpToken; eOp = NextToken(); - if( nNumFmt == SvNumFormatType::UNDEFINED && eOp == ocNot ) - nNumFmt = SvNumFormatType::LOGICAL; - if (eOp == ocOpen) + if( mnNumFmt == SvNumFormatType::UNDEFINED && eOp == ocNot ) + mnNumFmt = SvNumFormatType::LOGICAL; + if (eOp != ocOpen) + { + // if we're not calling the function right now, we need the Callable form + pFacToken = new FormulaCallableToken( FormulaBuiltInFunction::Get( pFacToken->GetOpCode() ) ); + PutCode( pFacToken); + } + else { NextToken(); CheckSetForceArrayParameter( mpToken, 0); eOp = Expression(); - } - else - SetError( FormulaError::PairExpected); - if (eOp != ocClose) - SetError( FormulaError::PairExpected); - else if ( pArr->GetCodeError() == FormulaError::NONE ) - { - pFacToken->SetByte( 1 ); - if (mbComputeII) + if (eOp != ocClose) + SetError( FormulaError::PairExpected); + else if ( mpArr->GetCodeError() == FormulaError::NONE ) { - FormulaToken** pArg = pCode - 1; - HandleIIOpCode(pFacToken, &pArg, 1); + static_cast(&*pFacToken)->SetByte( 1 ); + if (mbComputeII) + { + FormulaToken** pArg = mpCode - 1; + HandleIIOpCode(pFacToken, &pArg, 1); + } } + PutCode( pFacToken ); + NextToken(); } - PutCode( pFacToken ); - NextToken(); } } - else if ((SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR) + else if ((ocStartTwoParameters <= eOp && eOp < ocStopTwoParameters) || eOp == ocExternal + || eOp == ocUDExternal || eOp == ocMacro || eOp == ocAnd || eOp == ocOr @@ -1899,120 +2036,125 @@ void FormulaCompiler::Factor() pFacToken = mpToken; OpCode eMyLastOp = eOp; eOp = NextToken(); - bool bNoParam = false; - bool bBadName = false; - if (eOp == ocOpen) + if (eOp != ocOpen) { - eOp = NextToken(); - if (eOp == ocClose) - bNoParam = true; + if (eMyLastOp == ocBad) + { + // Just a bad name, not an unknown function, no parameters, no + // closing expected. A bad name is held in a string token, so + // set its parameter count to zero through that type. The byte + // then lands in the token's own field next to its string. + if (pFacToken->GetType() == svString) + static_cast(&*pFacToken)->SetByte(0); + else + static_cast(&*pFacToken)->SetByte(0); + PutCode( pFacToken); + // keep current token for return + } else + { + // if we're not calling the function right now, we need a Callable form + if ((ocStartTwoParameters <= eMyLastOp && eMyLastOp < ocStopTwoParameters) + || eMyLastOp == ocAnd + || eMyLastOp == ocOr) + pFacToken = new FormulaCallableToken( FormulaBuiltInFunction::Get( eMyLastOp ) ); + PutCode( pFacToken); + } + } + else + { + sal_uInt32 nSepCount = 0; + eOp = NextToken(); + if (eOp != ocClose) { CheckSetForceArrayParameter( mpToken, 0); eOp = Expression(); - } - } - else if (eMyLastOp == ocBad) - { - // Just a bad name, not an unknown function, no parameters, no - // closing expected. - bBadName = true; - bNoParam = true; - } - else - SetError( FormulaError::PairExpected); - sal_uInt32 nSepCount = 0; - if( !bNoParam ) - { - bool bDoIICompute = mbComputeII; - // Array of FormulaToken double pointers to collect the parameters of II opcodes. - FormulaToken*** pArgArray = nullptr; - if (bDoIICompute) - { - pArgArray = static_cast(alloca(sizeof(FormulaToken**)*FORMULA_MAXPARAMSII)); - if (!pArgArray) - bDoIICompute = false; - } - nSepCount++; + bool bDoIICompute = mbComputeII; + // Array of FormulaToken double pointers to collect the parameters of II opcodes. + FormulaToken*** pArgArray = nullptr; + if (bDoIICompute) + { + pArgArray = static_cast(alloca(sizeof(FormulaToken**)*FORMULA_MAXPARAMSII)); + if (!pArgArray) + bDoIICompute = false; + } - if (bDoIICompute) - pArgArray[nSepCount-1] = pCode - 1; // Add first argument + nSepCount++; - while ((eOp == ocSep) && (pArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) + if (bDoIICompute) + pArgArray[nSepCount-1] = mpCode - 1; // Add first argument + + while ((eOp == ocSep) && (mpArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) + { + NextToken(); + CheckSetForceArrayParameter( mpToken, nSepCount); + nSepCount++; + if (nSepCount > FORMULA_MAXPARAMS) + SetError( FormulaError::CodeOverflow); + eOp = Expression(); + if (bDoIICompute && nSepCount <= FORMULA_MAXPARAMSII) + pArgArray[nSepCount - 1] = mpCode - 1; // Add rest of the arguments + } + if (bDoIICompute) + HandleIIOpCode(pFacToken, pArgArray, + std::min(nSepCount, static_cast(FORMULA_MAXPARAMSII))); + } // params were supplied + bool bDone = false; + if (eOp != ocClose) + SetError( FormulaError::PairExpected); + else { NextToken(); - CheckSetForceArrayParameter( mpToken, nSepCount); - nSepCount++; - if (nSepCount > FORMULA_MAXPARAMS) - SetError( FormulaError::CodeOverflow); - eOp = Expression(); - if (bDoIICompute && nSepCount <= FORMULA_MAXPARAMSII) - pArgArray[nSepCount - 1] = pCode - 1; // Add rest of the arguments + bDone = true; } - if (bDoIICompute) - HandleIIOpCode(pFacToken, pArgArray, - std::min(nSepCount, static_cast(FORMULA_MAXPARAMSII))); - } - bool bDone = false; - if (bBadName) - ; // nothing, keep current token for return - else if (eOp != ocClose) - SetError( FormulaError::PairExpected); - else - { - NextToken(); - bDone = true; - } - // Jumps are just normal functions for the FunctionAutoPilot tree view - if (!mbJumpCommandReorder && pFacToken->GetType() == svJump) - pFacToken = new FormulaFAPToken( pFacToken->GetOpCode(), nSepCount, pFacToken ); - else - pFacToken->SetByte( nSepCount ); - PutCode( pFacToken ); + // Jumps are just normal functions for the FunctionAutoPilot tree view + if (!mbJumpCommandReorder && pFacToken->GetType() == svJump) + pFacToken = new FormulaFAPToken( pFacToken->GetOpCode(), nSepCount, pFacToken ); + else if (pFacToken->GetType() == svExternal) + static_cast(&*pFacToken)->SetByte( nSepCount ); + else if (pFacToken->GetType() == svString) + static_cast(&*pFacToken)->SetByte( nSepCount ); + else + static_cast(&*pFacToken)->SetByte( nSepCount ); + PutCode( pFacToken ); - if (bDone) - AnnotateOperands(); + if (bDone) + AnnotateOperands(); + } } else if (IsOpCodeJumpCommand(eOp)) { // the PC counters are -1 pFacToken = mpToken; + auto pJumpToken = static_cast(&*pFacToken); switch (eOp) { case ocIf: - pFacToken->GetJump()[ 0 ] = 3; // if, else, behind + pJumpToken->GetJump()[ 0 ] = 3; // if, else, behind break; case ocChoose: - pFacToken->GetJump()[ 0 ] = FORMULA_MAXJUMPCOUNT + 1; + pJumpToken->GetJump()[ 0 ] = FORMULA_MAXJUMPCOUNT + 1; break; case ocLet: - pFacToken->GetJump()[ 0 ] = FORMULA_MAXPARAMS + 1; + case ocLambda: + pJumpToken->GetJump()[ 0 ] = FORMULA_MAXPARAMS + 1; break; case ocIfError: case ocIfNA: - pFacToken->GetJump()[ 0 ] = 2; // if, behind + pJumpToken->GetJump()[ 0 ] = 2; // if, behind break; default: SAL_WARN("formula.core","Jump OpCode: " << +eOp); assert(!"FormulaCompiler::Factor: someone forgot to add a jump count case"); } - eOp = NextToken(); - if (eOp == ocOpen) - { - NextToken(); - CheckSetForceArrayParameter( mpToken, 0); - eOp = Expression(); - } - else - SetError( FormulaError::PairExpected); - PutCode( pFacToken ); + OpCode eFacOpCode = pFacToken->GetOpCode(); // During AutoCorrect (since pArr->GetCodeError() is // ignored) an unlimited ocIf would crash because // ScRawToken::Clone() allocates the JumpBuffer according to // nJump[0]*2+2, which is 3*2+2 on ocIf and 2*2+2 ocIfError and ocIfNA. + // Also, ocChoose, ocLet, and ocLambda have variable parameter list lengths. short nJumpMax; - OpCode eFacOpCode = pFacToken->GetOpCode(); switch (eFacOpCode) { case ocIf: @@ -2022,6 +2164,7 @@ void FormulaCompiler::Factor() nJumpMax = FORMULA_MAXJUMPCOUNT; break; case ocLet: + case ocLambda: nJumpMax = FORMULA_MAXPARAMS; break; case ocIfError: @@ -2031,7 +2174,7 @@ void FormulaCompiler::Factor() case ocStop: // May happen only if PutCode(pFacToken) ran into overflow. nJumpMax = 0; - assert(pc == FORMULA_MAXTOKENS && pArr->GetCodeError() != FormulaError::NONE); + assert(mnPC == FORMULA_MAXTOKENS && mpArr->GetCodeError() != FormulaError::NONE); break; default: nJumpMax = 0; @@ -2039,17 +2182,114 @@ void FormulaCompiler::Factor() assert(!"FormulaCompiler::Factor: someone forgot to add a jump max case"); } short nJumpCount = 0; - while ( (nJumpCount < (FORMULA_MAXPARAMS - 1)) && (eOp == ocSep) - && (pArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) + // ocLambda requires the operator to appear before all subexpressions in RPN + // ocIf, ocIfError, ocIfNA, and ocChoose require the first subexpression + // to appear before the operator. ocLet could be arranged either way, but the + // interpreter expects the first subexpression to appear before the operator. + if (eFacOpCode == ocLambda) { - if ( ++nJumpCount <= nJumpMax ) - pFacToken->GetJump()[nJumpCount] = pc-1; - NextToken(); - CheckSetForceArrayParameter( mpToken, nJumpCount - 1); - eOp = Expression(); + PutCode(pFacToken); + if (++nJumpCount <= nJumpMax) + static_cast(&*pFacToken)->GetJump()[ nJumpCount ] = mnPC-1; + + eOp = NextToken(); + if (eOp == ocOpen) + { + NextToken(); + // Optional LAMBDA parameters are surrounded by [] + if (mpToken->GetOpCode() == ocTableRefOpen) + { + meLastOp = ocSep; // So that NextToken() doesn't produce an error + eOp = NextToken(); + if (eOp == ocPush && mpToken->GetType() == svStringName) + { + CheckSetForceArrayParameter(mpToken, 0); + static_cast(mpToken.get())->SetIsOptional(true); + PutCode(mpToken); + eOp = NextToken(); + if (eOp == ocTableRefClose) + { + meLastOp = ocPush; // So that NextToken() doesn't produce an error + eOp = NextToken(); + } + else + SetError(FormulaError::PairExpected); + } + else + SetError(FormulaError::ParameterExpected); + } + else + { + CheckSetForceArrayParameter(mpToken, 0); + eOp = Expression(); + } + } + else + SetError(FormulaError::PairExpected); // ocSep or ocClose terminate the subexpression - PutCode( mpToken ); - } + PutCode(mpToken); + while ( (nJumpCount < (FORMULA_MAXPARAMS - 1)) && (eOp == ocSep) + && (mpArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) + { + if ( ++nJumpCount <= nJumpMax ) + static_cast(&*pFacToken)->GetJump()[nJumpCount] = mnPC-1; + NextToken(); + // Optional LAMBDA parameters are surrounded by [] + if (mpToken->GetOpCode() == ocTableRefOpen) + { + meLastOp = ocSep; // So that NextToken() doesn't produce an error + eOp = NextToken(); + if (eOp == ocPush && mpToken->GetType() == svStringName) + { + CheckSetForceArrayParameter(mpToken, nJumpCount - 1); + static_cast(mpToken.get())->SetIsOptional(true); + PutCode(mpToken); + eOp = NextToken(); + if (eOp == ocTableRefClose) + { + meLastOp = ocPush; // So that NextToken() doesn't produce an error + eOp = NextToken(); + } + else + SetError(FormulaError::PairExpected); + } + else + SetError(FormulaError::ParameterExpected); + } + else + { + CheckSetForceArrayParameter(mpToken, nJumpCount - 1); + eOp = Expression(); + } + // ocSep or ocClose terminate the subexpression + PutCode(mpToken); + } + } // eFacOpCode == ocLambda + else + { + eOp = NextToken(); + if (eOp == ocOpen) + { + NextToken(); + CheckSetForceArrayParameter(mpToken, 0); + eOp = Expression(); + } + else + SetError(FormulaError::PairExpected); + PutCode(pFacToken); + + while ( (nJumpCount < (FORMULA_MAXPARAMS - 1)) && (eOp == ocSep) + && (mpArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) + { + if ( ++nJumpCount <= nJumpMax ) + static_cast(&*pFacToken)->GetJump()[nJumpCount] = mnPC-1; + NextToken(); + CheckSetForceArrayParameter(mpToken, nJumpCount - 1); + eOp = Expression(); + // ocSep or ocClose terminate the subexpression + PutCode(mpToken); + } + } // eFacOpCode != ocLambda if (eOp != ocClose) SetError( FormulaError::PairExpected); else @@ -2057,7 +2297,7 @@ void FormulaCompiler::Factor() NextToken(); // always limit to nJumpMax, no arbitrary overwrites if ( ++nJumpCount <= nJumpMax ) - pFacToken->GetJump()[ nJumpCount ] = pc-1; + static_cast(&*pFacToken)->GetJump()[ nJumpCount ] = mnPC-1; eFacOpCode = pFacToken->GetOpCode(); bool bLimitOk; switch (eFacOpCode) @@ -2069,6 +2309,7 @@ void FormulaCompiler::Factor() bLimitOk = (nJumpCount < FORMULA_MAXJUMPCOUNT); break; case ocLet: + case ocLambda: bLimitOk = (nJumpCount < FORMULA_MAXPARAMS); break; case ocIfError: @@ -2081,7 +2322,7 @@ void FormulaCompiler::Factor() // error wasn't propagated so assert only the program // counter. bLimitOk = false; - assert(pc == FORMULA_MAXTOKENS); + assert(mnPC == FORMULA_MAXTOKENS); break; default: bLimitOk = false; @@ -2089,7 +2330,7 @@ void FormulaCompiler::Factor() assert(!"FormulaCompiler::Factor: someone forgot to add a jump limit case"); } if (bLimitOk) - pFacToken->GetJump()[ 0 ] = nJumpCount; + static_cast(&*pFacToken)->GetJump()[ 0 ] = nJumpCount; else SetError( FormulaError::IllegalParameter); } @@ -2106,10 +2347,10 @@ void FormulaCompiler::Factor() else if ( eOp == ocSep ) { // Subsequent ocSep SetError( FormulaError::ParameterExpected ); - if ( bAutoCorrect && !pStack ) + if ( mbAutoCorrect && !mpStack ) { - aCorrectedSymbol.clear(); - bCorrected = true; + maCorrectedSymbol.clear(); + mbCorrected = true; } } else if ( mpToken->IsExternalRef() ) @@ -2120,31 +2361,48 @@ void FormulaCompiler::Factor() else { SetError( FormulaError::UnknownToken ); - if ( bAutoCorrect && !pStack ) + if ( mbAutoCorrect && !mpStack ) { if ( eOp == ocStop ) { // trailing operator w/o operand - sal_Int32 nLen = aCorrectedFormula.getLength(); + sal_Int32 nLen = maCorrectedFormula.getLength(); if ( nLen ) - aCorrectedFormula = aCorrectedFormula.copy( 0, nLen - 1 ); - aCorrectedSymbol.clear(); - bCorrected = true; + maCorrectedFormula = maCorrectedFormula.copy( 0, nLen - 1 ); + maCorrectedSymbol.clear(); + mbCorrected = true; } } } } } +void FormulaCompiler::SpillOperator() +{ + while (mpToken->GetOpCode() == ocSpill) + { // this operator _follows_ the reference it takes the spill range of, and binds + // to that reference alone + if (mbComputeII) + { + FormulaToken** pArg = mpCode - 1; + HandleIIOpCode(mpToken.get(), &pArg, 1); + } + PutCode(mpToken); + NextToken(); + } +} + void FormulaCompiler::RangeLine() { Factor(); + SpillOperator(); while (mpToken->GetOpCode() == ocRange) { - FormulaToken** pCode1 = pCode - 1; + FormulaToken** pCode1 = mpCode - 1; FormulaTokenRef p = mpToken; NextToken(); Factor(); - FormulaToken** pCode2 = pCode - 1; + SpillOperator(); + FormulaToken** pCode2 = mpCode - 1; if (!MergeRangeReference( pCode1, pCode2)) PutCode(p); } @@ -2156,23 +2414,23 @@ void FormulaCompiler::IntersectionLine() while (mpToken->GetOpCode() == ocIntersect || mpToken->GetOpCode() == ocSpaces) { sal_uInt16 nCodeIndex = maArrIterator.GetIndex() - 1; - FormulaToken** pCode1 = pCode - 1; + FormulaToken** pCode1 = mpCode - 1; FormulaTokenRef p = mpToken; NextToken(); RangeLine(); - FormulaToken** pCode2 = pCode - 1; + FormulaToken** pCode2 = mpCode - 1; if (p->GetOpCode() == ocSpaces) { // Convert to intersection if both left and right are references or // functions (potentially returning references, if not then a space // or no space would be a syntax error anyway), not other operators // or operands. Else discard. - if (isAdjacentOrGapRpnEnd( pc, pCode, pCode1, pCode2) && isIntersectable( pCode1, pCode2)) + if (isAdjacentOrGapRpnEnd( mnPC, mpCode, pCode1, pCode2) && isIntersectable( pCode1, pCode2)) { FormulaTokenRef pIntersect( new FormulaByteToken( ocIntersect)); // Replace ocSpaces with ocIntersect so that when switching // formula syntax the correct operator string is created. - pArr->ReplaceToken( nCodeIndex, pIntersect.get(), FormulaTokenArray::ReplaceMode::CODE_ONLY); + mpArr->ReplaceToken( nCodeIndex, pIntersect.get(), FormulaTokenArray::ReplaceMode::CODE_ONLY); PutCode( pIntersect); } } @@ -2183,14 +2441,146 @@ void FormulaCompiler::IntersectionLine() } } -void FormulaCompiler::UnionLine() +void FormulaCompiler::CallLine() { IntersectionLine(); + OpCode eOp = mpToken->GetOpCode(); + while (mpToken->GetOpCode() == ocCall) + { + FormulaToken* pPrevToken = mpCode[-1]; + FormulaTokenRef pOpToken = mpToken; + OpCode eCallableOp = ocNone; + sal_uInt32 nMaxArgs = FORMULA_MAXPARAMS; + bool isBuiltIn = false; + if (pPrevToken && pPrevToken->GetType() == svCallable && pPrevToken->GetOpCode() == ocPush) + { + eCallableOp = static_cast(pPrevToken)->GetCallable()->GetOpCode(); + if ( ocStartNoParameters <= eCallableOp && eCallableOp < ocStopNoParameters ) + { + nMaxArgs = 0; + isBuiltIn = true; + } + else if ( ocStartOneParameter <= eCallableOp && eCallableOp < ocStopOneParameter ) + { + nMaxArgs = 1; + isBuiltIn = true; + } + else if ( ocStartTwoParameters <= eCallableOp && eCallableOp < ocStopTwoParameters ) + { + nMaxArgs = FORMULA_MAXPARAMS; + isBuiltIn = true; + } + if (isBuiltIn) + { + // directly calling a builtin takes a shortcut; see below + // we're taking ownership of pPrevToken + *(--mpCode) = nullptr; + mnPC--; + } + } + OpCode eMyLastOp = eOp; + eOp = NextToken(); + if (eOp != ocOpen) + { + if (eMyLastOp == ocBad) + { + // Just a bad name, not an unknown function, no parameters, no + // closing expected. + static_cast(pOpToken.get())->SetByte( 0 ); + PutCode( pOpToken); + // keep current token for return + } + else + { + SetError( FormulaError::PairExpected); + PutCode( pOpToken); + } + } + else + { + sal_uInt32 nArgCount = 0; + eOp = NextToken(); + if (eOp != ocClose) + { + if (nMaxArgs < 1) + SetError( FormulaError::PairExpected); + CheckSetForceArrayParameter( mpToken, 0); + eOp = Expression(); + bool bDoIICompute = mbComputeII; + // Array of FormulaToken double pointers to collect the parameters of II opcodes. + FormulaToken*** pArgArray = nullptr; + if (bDoIICompute) + { + pArgArray = static_cast(alloca(sizeof(FormulaToken**)*FORMULA_MAXPARAMSII)); + if (!pArgArray) + bDoIICompute = false; + } + + nArgCount++; + + if (bDoIICompute) + pArgArray[nArgCount - 1] = mpCode - 1; // Add first argument + + while ((eOp == ocSep) && (mpArr->GetCodeError() == FormulaError::NONE || !mbStopOnError)) + { + NextToken(); + CheckSetForceArrayParameter( mpToken, nArgCount); + nArgCount++; + if (nArgCount > FORMULA_MAXPARAMS) + SetError( FormulaError::CodeOverflow); + else if (nArgCount > nMaxArgs) + SetError( FormulaError::PairExpected); + eOp = Expression(); + if (bDoIICompute && nArgCount <= FORMULA_MAXPARAMSII) + pArgArray[nArgCount - 1] = mpCode - 1; // Add rest of the arguments + } + if (bDoIICompute) + HandleIIOpCode(&*pOpToken, pArgArray, + std::min(nArgCount, static_cast(FORMULA_MAXPARAMSII))); + } + bool bDone = false; + if (eOp != ocClose) + SetError( FormulaError::PairExpected); + else + { + NextToken(); + bDone = true; + } + // The ocCall token's byte counts the arguments plus the callable + // operand on the stack. A built-in invoked directly uses its own + // opcode and has had its callable operand removed from the code, so + // its byte counts only the arguments. + if (!isBuiltIn) + nArgCount++; + // Jumps are just normal functions for the FunctionAutoPilot tree view + if (!mbJumpCommandReorder && pOpToken->GetType() == svJump) + pOpToken = new FormulaFAPToken( pOpToken->GetOpCode(), nArgCount, &*pOpToken ); + else + { + // instead of using ocCall, built-in functions use their own OpCodes, if they are called directly + if (isBuiltIn) + pOpToken->NewOpCode( eCallableOp, FormulaToken::PrivateAccess() ); + static_cast(pOpToken.get())->SetByte( nArgCount); + } + PutCode( pOpToken); + + if (bDone) + AnnotateOperands(); + } + + if (isBuiltIn) + pPrevToken->DecRef(); + } +} + +void FormulaCompiler::UnionLine() +{ + CallLine(); while (mpToken->GetOpCode() == ocUnion) { FormulaTokenRef p = mpToken; NextToken(); - IntersectionLine(); + CallLine(); PutCode(p); } } @@ -2199,15 +2589,21 @@ void FormulaCompiler::UnaryLine() { if( mpToken->GetOpCode() == ocAdd ) GetToken(); - else if (SC_OPCODE_START_UN_OP <= mpToken->GetOpCode() && - mpToken->GetOpCode() < SC_OPCODE_STOP_UN_OP) + else if (isUnaryOperatorOpCode(mpToken->GetOpCode())) { FormulaTokenRef p = mpToken; NextToken(); - UnaryLine(); + // Hold the unary operator as the current factor so its + // parameter classification reaches the nested operators. + { + CurrentFactor pInnerFac(this); + pInnerFac = p; + CheckSetForceArrayParameter(mpToken, 0); + UnaryLine(); + } if (mbComputeII) { - FormulaToken** pArg = pCode - 1; + FormulaToken** pArg = mpCode - 1; HandleIIOpCode(p.get(), &pArg, 1); } PutCode( p ); @@ -2219,11 +2615,11 @@ void FormulaCompiler::UnaryLine() void FormulaCompiler::PostOpLine() { UnaryLine(); - while ( mpToken->GetOpCode() == ocPercentSign ) + while (mpToken->GetOpCode() == ocPercentSign) { // this operator _follows_ its operand if (mbComputeII) { - FormulaToken** pArg = pCode - 1; + FormulaToken** pArg = mpCode - 1; HandleIIOpCode(mpToken.get(), &pArg, 1); } PutCode( mpToken ); @@ -2239,12 +2635,12 @@ void FormulaCompiler::PowLine() FormulaTokenRef p = mpToken; FormulaToken** pArgArray[2]; if (mbComputeII) - pArgArray[0] = pCode - 1; // Add first argument + pArgArray[0] = mpCode - 1; // Add first argument NextToken(); PostOpLine(); if (mbComputeII) { - pArgArray[1] = pCode - 1; // Add second argument + pArgArray[1] = mpCode - 1; // Add second argument HandleIIOpCode(p.get(), pArgArray, 2); } PutCode(p); @@ -2259,12 +2655,12 @@ void FormulaCompiler::MulDivLine() FormulaTokenRef p = mpToken; FormulaToken** pArgArray[2]; if (mbComputeII) - pArgArray[0] = pCode - 1; // Add first argument + pArgArray[0] = mpCode - 1; // Add first argument NextToken(); PowLine(); if (mbComputeII) { - pArgArray[1] = pCode - 1; // Add second argument + pArgArray[1] = mpCode - 1; // Add second argument HandleIIOpCode(p.get(), pArgArray, 2); } PutCode(p); @@ -2279,12 +2675,12 @@ void FormulaCompiler::AddSubLine() FormulaTokenRef p = mpToken; FormulaToken** pArgArray[2]; if (mbComputeII) - pArgArray[0] = pCode - 1; // Add first argument + pArgArray[0] = mpCode - 1; // Add first argument NextToken(); MulDivLine(); if (mbComputeII) { - pArgArray[1] = pCode - 1; // Add second argument + pArgArray[1] = mpCode - 1; // Add second argument HandleIIOpCode(p.get(), pArgArray, 2); } PutCode(p); @@ -2299,12 +2695,12 @@ void FormulaCompiler::ConcatLine() FormulaTokenRef p = mpToken; FormulaToken** pArgArray[2]; if (mbComputeII) - pArgArray[0] = pCode - 1; // Add first argument + pArgArray[0] = mpCode - 1; // Add first argument NextToken(); AddSubLine(); if (mbComputeII) { - pArgArray[1] = pCode - 1; // Add second argument + pArgArray[1] = mpCode - 1; // Add second argument HandleIIOpCode(p.get(), pArgArray, 2); } PutCode(p); @@ -2319,12 +2715,12 @@ void FormulaCompiler::CompareLine() FormulaTokenRef p = mpToken; FormulaToken** pArgArray[2]; if (mbComputeII) - pArgArray[0] = pCode - 1; // Add first argument + pArgArray[0] = mpCode - 1; // Add first argument NextToken(); ConcatLine(); if (mbComputeII) { - pArgArray[1] = pCode - 1; // Add second argument + pArgArray[1] = mpCode - 1; // Add second argument HandleIIOpCode(p.get(), pArgArray, 2); } PutCode(p); @@ -2333,8 +2729,8 @@ void FormulaCompiler::CompareLine() OpCode FormulaCompiler::Expression() { - FormulaCompilerRecursionGuard aRecursionGuard( nRecursion ); - if ( nRecursion > nRecursionMax ) + FormulaCompilerRecursionGuard aRecursionGuard( mnRecursion ); + if ( mnRecursion > nRecursionMax ) { SetError( FormulaError::StackOverflow ); return ocStop; //! generate token instead? @@ -2343,15 +2739,15 @@ OpCode FormulaCompiler::Expression() while (mpToken->GetOpCode() == ocAnd || mpToken->GetOpCode() == ocOr) { FormulaTokenRef p = mpToken; - mpToken->SetByte( 2 ); // 2 parameters! + static_cast(mpToken.get())->SetByte( 2 ); // 2 parameters! FormulaToken** pArgArray[2]; if (mbComputeII) - pArgArray[0] = pCode - 1; // Add first argument + pArgArray[0] = mpCode - 1; // Add first argument NextToken(); CompareLine(); if (mbComputeII) { - pArgArray[1] = pCode - 1; // Add second argument + pArgArray[1] = mpCode - 1; // Add second argument HandleIIOpCode(p.get(), pArgArray, 2); } PutCode(p); @@ -2371,7 +2767,7 @@ FormulaTokenRef FormulaCompiler::ExtendRangeReference( FormulaToken & /*rTok1*/, bool FormulaCompiler::MergeRangeReference( FormulaToken * * const pCode1, FormulaToken * const * const pCode2 ) { - if (!isAdjacentRpnEnd( pc, pCode, pCode1, pCode2)) + if (!isAdjacentRpnEnd( mnPC, mpCode, pCode1, pCode2)) return false; FormulaToken *p1 = *pCode1, *p2 = *pCode2; @@ -2383,41 +2779,41 @@ bool FormulaCompiler::MergeRangeReference( FormulaToken * * const pCode1, Formul p1->DecRef(); p2->DecRef(); *pCode1 = p.get(); - --pCode; - --pc; + --mpCode; + --mnPC; return true; } bool FormulaCompiler::CompileTokenArray() { - glSubTotal = false; - bCorrected = false; - needsRPNTokenCheck = false; - if (pArr->GetCodeError() == FormulaError::NONE || !mbStopOnError) + mbGlSubTotal = false; + mbCorrected = false; + mbNeedsRPNTokenCheck = false; + if (mpArr->GetCodeError() == FormulaError::NONE || !mbStopOnError) { - if ( bAutoCorrect ) + if ( mbAutoCorrect ) { - aCorrectedFormula.clear(); - aCorrectedSymbol.clear(); + maCorrectedFormula.clear(); + maCorrectedSymbol.clear(); } - pArr->DelRPN(); + mpArr->DelRPN(); maArrIterator.Reset(); - pStack = nullptr; + mpStack = nullptr; FormulaToken* pDataArray[ FORMULA_MAXTOKENS + 1 ]; // Code in some places refers to the last token as 'pCode - 1', which may // point before the first element if the expression is bad. So insert a dummy // node in that place which will make that token be nullptr. pDataArray[ 0 ] = nullptr; FormulaToken** pData = pDataArray + 1; - pCode = pData; - bool bWasForced = pArr->IsRecalcModeForced(); - if ( bWasForced && bAutoCorrect ) - aCorrectedFormula = "="; - pArr->ClearRecalcMode(); + mpCode = pData; + bool bWasForced = mpArr->IsRecalcModeForced(); + if ( bWasForced && mbAutoCorrect ) + maCorrectedFormula = "="; + mpArr->ClearRecalcMode(); maArrIterator.Reset(); - eLastOp = ocOpen; - pc = 0; + meLastOp = ocOpen; + mnPC = 0; NextToken(); OpCode eOp = Expression(); // Some trailing garbage that doesn't form an expression? @@ -2425,55 +2821,55 @@ bool FormulaCompiler::CompileTokenArray() SetError( FormulaError::OperatorExpected); PostProcessCode(); - FormulaError nErrorBeforePop = pArr->GetCodeError(); + FormulaError nErrorBeforePop = mpArr->GetCodeError(); - while( pStack ) + while( mpStack ) PopTokenArray(); - if( pc ) + if( mnPC ) { - pArr->CreateNewRPNArrayFromData( pData, pc ); - if( needsRPNTokenCheck ) - pArr->CheckAllRPNTokens(); + mpArr->CreateNewRPNArrayFromData( pData, mnPC ); + if( mbNeedsRPNTokenCheck ) + mpArr->CheckAllRPNTokens(); } // once an error, always an error - if( pArr->GetCodeError() == FormulaError::NONE && nErrorBeforePop != FormulaError::NONE ) - pArr->SetCodeError( nErrorBeforePop); + if( mpArr->GetCodeError() == FormulaError::NONE && nErrorBeforePop != FormulaError::NONE ) + mpArr->SetCodeError( nErrorBeforePop); - if (pArr->GetCodeError() != FormulaError::NONE && mbStopOnError) + if (mpArr->GetCodeError() != FormulaError::NONE && mbStopOnError) { - pArr->DelRPN(); + mpArr->DelRPN(); maArrIterator.Reset(); - pArr->SetHyperLink( false); + mpArr->SetHyperLink( false); } if ( bWasForced ) - pArr->SetRecalcModeForced(); + mpArr->SetRecalcModeForced(); } - if( nNumFmt == SvNumFormatType::UNDEFINED ) - nNumFmt = SvNumFormatType::NUMBER; - return glSubTotal; + if( mnNumFmt == SvNumFormatType::UNDEFINED ) + mnNumFmt = SvNumFormatType::NUMBER; + return mbGlSubTotal; } void FormulaCompiler::PopTokenArray() { - if( !pStack ) + if( !mpStack ) return; - FormulaArrayStack* p = pStack; - pStack = p->pNext; + FormulaArrayStack* p = mpStack; + mpStack = p->pNext; // obtain special RecalcMode from SharedFormula - if ( pArr->IsRecalcModeAlways() ) + if ( mpArr->IsRecalcModeAlways() ) p->pArr->SetExclusiveRecalcModeAlways(); - else if ( !pArr->IsRecalcModeNormal() && p->pArr->IsRecalcModeNormal() ) - p->pArr->SetMaskedRecalcMode( pArr->GetRecalcMode() ); - p->pArr->SetCombinedBitsRecalcMode( pArr->GetRecalcMode() ); - if ( pArr->IsHyperLink() ) // fdo 87534 + else if ( !mpArr->IsRecalcModeNormal() && p->pArr->IsRecalcModeNormal() ) + p->pArr->SetMaskedRecalcMode( mpArr->GetRecalcMode() ); + p->pArr->SetCombinedBitsRecalcMode( mpArr->GetRecalcMode() ); + if ( mpArr->IsHyperLink() ) // fdo 87534 p->pArr->SetHyperLink( true ); if( p->bTemp ) - delete pArr; - pArr = p->pArr; - maArrIterator = FormulaTokenArrayPlainIterator(*pArr); + delete mpArr; + mpArr = p->pArr; + maArrIterator = FormulaTokenArrayPlainIterator(*mpArr); maArrIterator.Jump(p->nIndex); mpLastToken = p->mpLastToken; delete p; @@ -2481,67 +2877,108 @@ void FormulaCompiler::PopTokenArray() void FormulaCompiler::CreateStringFromTokenArray( OUString& rFormula ) { - OUStringBuffer aBuffer( pArr->GetLen() * 5 ); + OUStringBuffer aBuffer( mpArr->GetLen() * 5 ); CreateStringFromTokenArray( aBuffer ); rFormula = aBuffer.makeStringAndClear(); } +bool FormulaCompiler::AppendTokenOrError(OUStringBuffer& rBuffer, const FormulaToken*& rpToken) +{ + const OpCode eOp = rpToken->GetOpCode(); + if (rpToken->GetType() == svByte) + { + if (eOp == ocNoName && FormulaGrammar::isOOXML(meGrammar)) + { + // A call with no name would come out as "#NAME!()", which no reader + // accepts, so the error string replaces the whole formula. + rBuffer.setLength(0); + rBuffer.append(mxSymbols->getSymbol(ocErrRef)); + return false; + } + if (eOp == ocExternal || eOp == ocPush) + { + // A function token that lost its name. The error string stands in for + // this one token only. + rBuffer.append(mxSymbols->getSymbol(ocErrRef)); + rpToken = maArrIterator.Next(); + return true; + } + } + else if (eOp == ocPush && rpToken->GetType() == svError + && static_cast(rpToken)->GetError() == FormulaError::NoName + && FormulaGrammar::isOOXML(meGrammar)) + { + const FormulaToken* pNext = maArrIterator.PeekNext(); + if (pNext && pNext->IsRef()) + { + // The error would come out as "#NAME?$C7", which no reader accepts, + // so the error string replaces the whole formula. + rBuffer.setLength(0); + rBuffer.append(mxSymbols->getSymbol(ocErrName)); + return false; + } + } + rpToken = CreateStringFromToken(rBuffer, rpToken, true); + return true; +} + void FormulaCompiler::CreateStringFromTokenArray( OUStringBuffer& rBuffer ) { rBuffer.setLength(0); - if( !pArr->GetLen() ) + if( !mpArr->GetLen() ) return; - FormulaTokenArray* pSaveArr = pArr; + FormulaTokenArray* pSaveArr = mpArr; int nSaveIndex = maArrIterator.GetIndex(); bool bODFF = FormulaGrammar::isODFF( meGrammar); if (bODFF || FormulaGrammar::isPODF( meGrammar) ) { // Scan token array for missing args and re-write if present. MissingConventionODF aConv( bODFF); - if (pArr->NeedsPodfRewrite( aConv)) + if (mpArr->NeedsPodfRewrite( aConv)) { - pArr = pArr->RewriteMissing( aConv ); - maArrIterator = FormulaTokenArrayPlainIterator( *pArr ); + mpArr = mpArr->RewriteMissing( aConv ); + maArrIterator = FormulaTokenArrayPlainIterator( *mpArr ); } } else if ( FormulaGrammar::isOOXML( meGrammar ) ) { // Scan token array for missing args and rewrite if present. - if (pArr->NeedsOoxmlRewrite()) + if (mpArr->NeedsOoxmlRewrite()) { MissingConventionOOXML aConv; - pArr = pArr->RewriteMissing( aConv ); - maArrIterator = FormulaTokenArrayPlainIterator( *pArr ); + mpArr = mpArr->RewriteMissing( aConv ); } + // Put in what OOXML spells out, so writing is a plain walk over the tokens. + OOXMLRewriter aRewriter(*mpArr); + if (std::unique_ptr pOoxml = aRewriter.releaseTokens()) + { + if (mpArr != pSaveArr) + delete mpArr; + mpArr = pOoxml.release(); + } + maArrIterator = FormulaTokenArrayPlainIterator( *mpArr ); } // At least one character per token, plus some are references, some are // function names, some are numbers, ... - rBuffer.ensureCapacity( pArr->GetLen() * 5 ); + rBuffer.ensureCapacity( mpArr->GetLen() * 5 ); - if ( pArr->IsRecalcModeForced() ) + if ( mpArr->IsRecalcModeForced() ) rBuffer.append( '='); + const FormulaToken* t = maArrIterator.First(); while( t ) { - // Discard writing unknown functions without a name in OOXML ex: #NAME!() - if (FormulaGrammar::isOOXML(meGrammar) - && (t->GetOpCode() == ocNoName || t->GetOpCode() == ocExternal) - && t->GetType() == svByte) - { - rBuffer.setLength(0); - rBuffer.append(GetNativeSymbol(ocErrRef)); + if (!AppendTokenOrError(rBuffer, t)) break; - } - t = CreateStringFromToken(rBuffer, t, true); } - if (pSaveArr != pArr) + if (pSaveArr != mpArr) { - delete pArr; - pArr = pSaveArr; - maArrIterator = FormulaTokenArrayPlainIterator( *pArr ); + delete mpArr; + mpArr = pSaveArr; + maArrIterator = FormulaTokenArrayPlainIterator( *mpArr ); maArrIterator.Jump(nSaveIndex); } } @@ -2559,6 +2996,7 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf { bool bNext = true; bool bSpaces = false; + bool bCloseOptionalParam = false; const FormulaToken* t = pTokenP; OpCode eOp = t->GetOpCode(); if( eOp >= ocAnd && eOp <= ocOr ) @@ -2574,7 +3012,7 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf if( bSpaces ) rBuffer.append( ' '); - if (eOp == ocSpaces || eOp == ocWhitespace) + if (isWhitespaceOpCode(eOp)) { bool bWriteSpaces = true; if (eOp == ocSpaces && mxSymbols->isODFF()) @@ -2605,7 +3043,7 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf // Suppress/remove it in any case also in UI, it will not be // preserved. const FormulaToken* p = maArrIterator.PeekPrevNoSpaces(); - if (p && p->IsFunction()) + if (p && (p->IsFunction() || p->GetOpCode() == ocCall) ) { p = maArrIterator.PeekNextNoSpaces(); if (p && p->GetOpCode() == ocOpen) @@ -2615,11 +3053,17 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf if (bWriteSpaces) { // most times it's just one blank - sal_uInt8 n = t->GetByte(); + sal_uInt8 n = 0; + if (t->GetOpCode() == ocWhitespace) + n = static_cast(t)->GetByte(); + else if (t->GetOpCode() == ocSpaces) + n = static_cast(t)->GetByte(); + else + assert(false); for ( sal_uInt8 j=0; jGetChar()); + rBuffer.append( static_cast(t)->GetChar()); else rBuffer.append( ' '); } @@ -2647,12 +3091,47 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf else rBuffer.append(mxSymbols->getSymbol(eOp)); } + else if (eOp == ocSingleValue) + { + // The @ implicit-intersection operator is an in-memory marker + // for plain non-array formulas. ODF saves drop it. The next + // import re-adds it for any plain non-array, non-loext:spill + // cell whose RPN intends to produce an array. OOXML keeps the + // @ as the format does carry the operator. + if (!m_oODFSavingVersion.has_value()) + rBuffer.append(mxSymbols->getSymbol(eOp)); + } else if (eOp == ocNoName && FormulaGrammar::isOOXML(meGrammar)) { // Don't export "#name!" in OOXML } + else if (eOp == ocUDExternal) + { + if (t->GetType() == svExternal && static_cast(t)->GetExternal().isEmpty()) + rBuffer.append(mxSymbols->getSymbol(ocErrRef)); + else if (maArrIterator.PeekNext() && maArrIterator.PeekNext()->GetOpCode() == ocOpen) + rBuffer.append(mxSymbols->getSymbol(eOp)); + } + else if (eOp == ocStringName) + { + // A lambda parameter. An optional parameter, whose byte is set, takes + // the _xlop. prefix in OOXML and is wrapped in square brackets in the + // other grammars. A required parameter or a body reference takes the + // grammar's plain prefix, which is _xlpm. for the formats that use one + // and empty otherwise. + const bool bOptional = static_cast(t)->GetByte() != 0; + if (bOptional && FormulaGrammar::isOOXML(meGrammar)) + rBuffer.append(u"_xlop."); + else if (bOptional) + { + rBuffer.append(mxSymbols->getSymbol(ocTableRefOpen)); + bCloseOptionalParam = true; + } + else + rBuffer.append(mxSymbols->getSymbol(ocStringName)); + } else if( static_cast(eOp) < mxSymbols->getSymbolCount()) // Keyword: - rBuffer.append( mxSymbols->getSymbol( eOp)); + rBuffer.append(mxSymbols->getSymbol(eOp)); else { SAL_WARN( "formula.core","unknown OpCode"); @@ -2669,16 +3148,22 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf switch( t->GetType() ) { case svDouble: - AppendDouble( rBuffer, t->GetDouble() ); + AppendDouble( rBuffer, static_cast(t)->GetDouble() ); break; case svString: if( eOp == ocBad || eOp == ocStringXML || eOp == ocStringName ) - rBuffer.append( t->GetString().getString()); + { + assert(dynamic_cast(t)); + rBuffer.append( static_cast(t)->GetString().getString()); + } else if (eOp == ocDPFieldName) CreateStringFromDPFieldName( rBuffer, t ); else - AppendString( rBuffer, t->GetString().getString() ); + { + assert(dynamic_cast(t)); + AppendString( rBuffer, static_cast(t)->GetString().getString() ); + } break; case svSingleRef: CreateStringFromSingleRef( rBuffer, t); @@ -2739,7 +3224,7 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf case svExternal: { // mapped or translated name of AddIns - OUString aAddIn( t->GetExternal() ); + OUString aAddIn( static_cast(t)->GetExternal() ); bool bMapped = mxSymbols->isPODF(); // ODF 1.1 directly uses programmatical name if (!bMapped && mxSymbols->hasExternals()) { @@ -2765,7 +3250,7 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf } break; case svError: - AppendErrorConstant( rBuffer, t->GetError()); + AppendErrorConstant( rBuffer, static_cast(t)->GetError()); break; case svByte: case svJump: @@ -2778,6 +3263,8 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf } // of switch } } + if (bCloseOptionalParam) + rBuffer.append(mxSymbols->getSymbol(ocTableRefClose)); if( bSpaces ) rBuffer.append( ' '); if ( bAllowArrAdvance ) @@ -2868,83 +3355,82 @@ OpCode FormulaCompiler::NextToken() OpCode eOp = mpToken->GetOpCode(); // There must be an operator before a push if ( (eOp == ocPush || eOp == ocColRowNameAuto) && - !( (eLastOp == ocOpen) || (eLastOp == ocSep) || - (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP)) ) + !( (meLastOp == ocOpen) || (meLastOp == ocSep) || + isOperatorExpectingOperand(meLastOp)) ) SetError( FormulaError::OperatorExpected); // Operator and Plus => operator - if (eOp == ocAdd && (eLastOp == ocOpen || eLastOp == ocSep || - (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP))) + if (eOp == ocAdd && (meLastOp == ocOpen || meLastOp == ocSep || + isOperatorExpectingOperand(meLastOp))) { - FormulaCompilerRecursionGuard aRecursionGuard( nRecursion ); + FormulaCompilerRecursionGuard aRecursionGuard( mnRecursion ); eOp = NextToken(); } else { // Before an operator there must not be another operator, with the // exception of AND and OR. - if ( eOp != ocAnd && eOp != ocOr && - (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP ) - && (eLastOp == ocOpen || eLastOp == ocSep || - (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP))) + if ( eOp != ocAnd && eOp != ocOr && isBinaryOperatorOpCode(eOp) + && (meLastOp == ocOpen || meLastOp == ocSep || + isOperatorExpectingOperand(meLastOp))) { SetError( FormulaError::VariableExpected); - if ( bAutoCorrect && !pStack ) + if ( mbAutoCorrect && !mpStack ) { - if ( eOp == eLastOp || eLastOp == ocOpen ) + if ( eOp == meLastOp || meLastOp == ocOpen ) { // throw away duplicated operator - aCorrectedSymbol.clear(); - bCorrected = true; + maCorrectedSymbol.clear(); + mbCorrected = true; } else { - sal_Int32 nPos = aCorrectedFormula.getLength(); + sal_Int32 nPos = maCorrectedFormula.getLength(); if ( nPos ) { nPos--; - sal_Unicode c = aCorrectedFormula[ nPos ]; + sal_Unicode c = maCorrectedFormula[ nPos ]; switch ( eOp ) { // swap operators case ocGreater: if ( c == mxSymbols->getSymbolChar( ocEqual) ) { // >= instead of => - aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1, + maCorrectedFormula = maCorrectedFormula.replaceAt( nPos, 1, rtl::OUStringChar( mxSymbols->getSymbolChar(ocGreater) ) ); - aCorrectedSymbol = OUString(c); - bCorrected = true; + maCorrectedSymbol = OUString(c); + mbCorrected = true; } break; case ocLess: if ( c == mxSymbols->getSymbolChar( ocEqual) ) { // <= instead of =< - aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1, + maCorrectedFormula = maCorrectedFormula.replaceAt( nPos, 1, rtl::OUStringChar( mxSymbols->getSymbolChar(ocLess) ) ); - aCorrectedSymbol = OUString(c); - bCorrected = true; + maCorrectedSymbol = OUString(c); + mbCorrected = true; } else if ( c == mxSymbols->getSymbolChar( ocGreater) ) { // <> instead of >< - aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1, + maCorrectedFormula = maCorrectedFormula.replaceAt( nPos, 1, rtl::OUStringChar( mxSymbols->getSymbolChar(ocLess) ) ); - aCorrectedSymbol = OUString(c); - bCorrected = true; + maCorrectedSymbol = OUString(c); + mbCorrected = true; } break; case ocMul: if ( c == mxSymbols->getSymbolChar( ocSub) ) { // *- instead of -* - aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1, + maCorrectedFormula = maCorrectedFormula.replaceAt( nPos, 1, rtl::OUStringChar( mxSymbols->getSymbolChar(ocMul) ) ); - aCorrectedSymbol = OUString(c); - bCorrected = true; + maCorrectedSymbol = OUString(c); + mbCorrected = true; } break; case ocDiv: if ( c == mxSymbols->getSymbolChar( ocSub) ) { // /- instead of -/ - aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1, + maCorrectedFormula = maCorrectedFormula.replaceAt( nPos, 1, rtl::OUStringChar( mxSymbols->getSymbolChar(ocDiv) ) ); - aCorrectedSymbol = OUString(c); - bCorrected = true; + maCorrectedSymbol = OUString(c); + mbCorrected = true; } break; default: @@ -2958,46 +3444,50 @@ OpCode FormulaCompiler::NextToken() if (eOp == ocSpaces && FormulaGrammar::isExcelSyntax( meGrammar)) { // Fake an intersection op as last op for the next round, but at - // least roughly check if it could make sense at all. + // least roughly check if it could make sense at all. The parenthesis + // tokens have the separator type, so accept them by opcode instead - + // a parenthesised expression is valid on either side of the space. FormulaToken* pPrev = maArrIterator.PeekPrevNoSpaces(); - if (pPrev && isPotentialRangeType( pPrev, false, false)) + if (pPrev + && (pPrev->GetOpCode() == ocClose || isPotentialRangeType(pPrev, false, false))) { FormulaToken* pNext = maArrIterator.PeekNextNoSpaces(); - if (pNext && isPotentialRangeType( pNext, false, true)) - eLastOp = ocIntersect; + if (pNext + && (pNext->GetOpCode() == ocOpen || isPotentialRangeType(pNext, false, true))) + meLastOp = ocIntersect; else - eLastOp = eOp; + meLastOp = eOp; } else - eLastOp = eOp; + meLastOp = eOp; } else - eLastOp = eOp; + meLastOp = eOp; } return eOp; } void FormulaCompiler::PutCode( FormulaTokenRef& p ) { - if( pc >= FORMULA_MAXTOKENS - 1 ) + if( mnPC >= FORMULA_MAXTOKENS - 1 ) { - if ( pc == FORMULA_MAXTOKENS - 1 ) + if ( mnPC == FORMULA_MAXTOKENS - 1 ) { SAL_WARN("formula.core", "FormulaCompiler::PutCode - CodeOverflow with OpCode " << +p->GetOpCode()); p = new FormulaByteToken( ocStop ); p->IncRef(); - *pCode++ = p.get(); - ++pc; + *mpCode++ = p.get(); + ++mnPC; } SetError( FormulaError::CodeOverflow); return; } - if (pArr->GetCodeError() != FormulaError::NONE && mbJumpCommandReorder) + if (mpArr->GetCodeError() != FormulaError::NONE && mbJumpCommandReorder) return; ForceArrayOperator( p); p->IncRef(); - *pCode++ = p.get(); - pc++; + *mpCode++ = p.get(); + mnPC++; } @@ -3076,7 +3566,7 @@ formula::ParamClass FormulaCompiler::GetForceArrayParameter( const FormulaToken* void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) { - if (pCurrentFactorToken.get() == rCurr.get()) + if (mpCurrentFactorToken.get() == rCurr.get()) return; const OpCode eOp = rCurr->GetOpCode(); @@ -3103,7 +3593,7 @@ void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) // returning array/matrix or inline arrays, though for the latter has one // example in 18.17.2 Syntax: // "SUM(SQRT({1,2,3,4})) returns 6.14 when entered normally". However, - // these need to be treated similar but not as ParamClass::ForceArray + // these need to be treated similarly but not as ParamClass::ForceArray // (which would contradict the example in // https://bugs.documentfoundation.org/show_bug.cgi?id=122301#c19 and A6 of // https://bugs.documentfoundation.org/show_bug.cgi?id=133260#c10 ). @@ -3116,19 +3606,19 @@ void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) { // rCurr->SetInForceArray() can not be used with ocPush, but ocPush // with svMatrix has an implicit ParamClass::ForceArrayReturn. - if (nCurrentFactorParam > 0 && pCurrentFactorToken - && pCurrentFactorToken->GetInForceArray() == ParamClass::Unknown - && GetForceArrayParameter( pCurrentFactorToken.get(), static_cast(nCurrentFactorParam - 1)) + if (mnCurrentFactorParam > 0 && mpCurrentFactorToken + && mpCurrentFactorToken->GetInForceArray() == ParamClass::Unknown + && GetForceArrayParameter( mpCurrentFactorToken.get(), static_cast(mnCurrentFactorParam - 1)) == ParamClass::Value) { // Propagate to caller as if a function returning an array/matrix // was called (see also below). - pCurrentFactorToken->SetInForceArray( eArrayReturn); + mpCurrentFactorToken->SetInForceArray( eArrayReturn); } return; } - if (!pCurrentFactorToken) + if (!mpCurrentFactorToken) { if (mbMatrixFlag) { @@ -3137,7 +3627,7 @@ void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) // below. rCurr->SetInForceArray( ParamClass::ForceArray); } - else if (pc >= 2 && SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP) + else if (mnPC >= 2 && isBinaryOperatorOpCode(eOp)) { // Binary operators are not functions followed by arguments // and need some peeking into RPN to inspect their operands. @@ -3153,21 +3643,21 @@ void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) // functions returning matrix have ForceArrayReturn (yet?), see // OOXML comment above. - const OpCode eOp1 = pCode[-1]->GetOpCode(); - const OpCode eOp2 = pCode[-2]->GetOpCode(); - const bool b1 = (pCode[-1]->GetInForceArray() != ParamClass::Unknown || IsMatrixFunction(eOp1)); - const bool b2 = (pCode[-2]->GetInForceArray() != ParamClass::Unknown || IsMatrixFunction(eOp2)); + const OpCode eOp1 = mpCode[-1]->GetOpCode(); + const OpCode eOp2 = mpCode[-2]->GetOpCode(); + const bool b1 = (mpCode[-1]->GetInForceArray() != ParamClass::Unknown || IsMatrixFunction(eOp1)); + const bool b2 = (mpCode[-2]->GetInForceArray() != ParamClass::Unknown || IsMatrixFunction(eOp2)); if ((b1 && b2) - || (b1 && eOp2 == ocPush && pCode[-2]->GetType() != svDoubleRef) - || (b2 && eOp1 == ocPush && pCode[-1]->GetType() != svDoubleRef)) + || (b1 && eOp2 == ocPush && mpCode[-2]->GetType() != svDoubleRef) + || (b2 && eOp1 == ocPush && mpCode[-1]->GetType() != svDoubleRef)) { rCurr->SetInForceArray( eArrayReturn); } } - else if (pc >= 1 && SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP) + else if (mnPC >= 1 && isUnaryOperatorOpCode(eOp)) { // Similar for unary operators. - if (pCode[-1]->GetInForceArray() != ParamClass::Unknown || IsMatrixFunction(pCode[-1]->GetOpCode())) + if (mpCode[-1]->GetInForceArray() != ParamClass::Unknown || IsMatrixFunction(mpCode[-1]->GetOpCode())) { rCurr->SetInForceArray( eArrayReturn); } @@ -3176,15 +3666,15 @@ void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) } // Inherited parameter class. - const formula::ParamClass eForceType = pCurrentFactorToken->GetInForceArray(); + const formula::ParamClass eForceType = mpCurrentFactorToken->GetInForceArray(); if (eForceType == ParamClass::ForceArray || eForceType == ParamClass::ReferenceOrRefArray) { // ReferenceOrRefArray was set only if in ForceArray context already, // it is valid for the one function only to indicate the preferred // return type. Propagate as ForceArray if not another parameter // handling ReferenceOrRefArray. - if (nCurrentFactorParam > 0 - && (GetForceArrayParameter( pCurrentFactorToken.get(), static_cast(nCurrentFactorParam - 1)) + if (mnCurrentFactorParam > 0 + && (GetForceArrayParameter( mpCurrentFactorToken.get(), static_cast(mnCurrentFactorParam - 1)) == ParamClass::ReferenceOrRefArray)) rCurr->SetInForceArray( ParamClass::ReferenceOrRefArray); else @@ -3202,12 +3692,12 @@ void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) return; } - if (nCurrentFactorParam <= 0) + if (mnCurrentFactorParam <= 0) return; // Actual current parameter's class. const formula::ParamClass eParamType = GetForceArrayParameter( - pCurrentFactorToken.get(), static_cast(nCurrentFactorParam - 1)); + mpCurrentFactorToken.get(), static_cast(mnCurrentFactorParam - 1)); if (eParamType == ParamClass::ForceArray) rCurr->SetInForceArray( eParamType); else if (eParamType == ParamClass::ReferenceOrForceArray) @@ -3221,41 +3711,41 @@ void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) // Propagate a ForceArrayReturn to caller if the called function // returns one and the caller so far does not have a stronger array // mode set and expects a scalar value for this parameter. - if (eParamType == ParamClass::Value && pCurrentFactorToken->GetInForceArray() == ParamClass::Unknown) + if (eParamType == ParamClass::Value && mpCurrentFactorToken->GetInForceArray() == ParamClass::Unknown) { if (IsMatrixFunction( eOp)) - pCurrentFactorToken->SetInForceArray( eArrayReturn); + mpCurrentFactorToken->SetInForceArray( eArrayReturn); else if (GetForceArrayParameter( rCurr.get(), SAL_MAX_UINT16) == ParamClass::ForceArrayReturn) - pCurrentFactorToken->SetInForceArray( ParamClass::ForceArrayReturn); + mpCurrentFactorToken->SetInForceArray( ParamClass::ForceArrayReturn); } } void FormulaCompiler::CheckSetForceArrayParameter( FormulaTokenRef const & rCurr, sal_uInt8 nParam ) { - if (!pCurrentFactorToken) + if (!mpCurrentFactorToken) return; - nCurrentFactorParam = nParam + 1; + mnCurrentFactorParam = nParam + 1; ForceArrayOperator( rCurr); } void FormulaCompiler::PushTokenArray( FormulaTokenArray* pa, bool bTemp ) { - if ( bAutoCorrect && !pStack ) + if ( mbAutoCorrect && !mpStack ) { // don't merge stacked subroutine code into entered formula - aCorrectedFormula += aCorrectedSymbol; - aCorrectedSymbol.clear(); + maCorrectedFormula += maCorrectedSymbol; + maCorrectedSymbol.clear(); } FormulaArrayStack* p = new FormulaArrayStack; - p->pNext = pStack; - p->pArr = pArr; + p->pNext = mpStack; + p->pArr = mpArr; p->nIndex = maArrIterator.GetIndex(); p->mpLastToken = mpLastToken; p->bTemp = bTemp; - pStack = p; - pArr = pa; - maArrIterator = FormulaTokenArrayPlainIterator( *pArr ); + mpStack = p; + mpArr = pa; + maArrIterator = FormulaTokenArrayPlainIterator( *mpArr ); } } // namespace formula diff --git a/formula/source/core/api/OOXMLRewriter.cxx b/formula/source/core/api/OOXMLRewriter.cxx new file mode 100644 index 000000000000..db448b8a8331 --- /dev/null +++ b/formula/source/core/api/OOXMLRewriter.cxx @@ -0,0 +1,551 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 + +#include +#include + +#include +#include +#include +#include + +namespace formula +{ +namespace +{ +const sal_uInt16 NO_POSITION = SAL_MAX_UINT16; + +// Tokens the OOXML shape has no place for: the call name of the wrapper around their operand +// stands for them. +bool lclIsDropped(OpCode eOp) { return eOp == ocSingleValue || eOp == ocSpill; } + +// Tokens that write no text, so an operand made of nothing else leaves its wrapper with +// nothing to enclose and the wrapper goes. +bool lclWritesNoText(OpCode eOp) { return lclIsDropped(eOp) || eOp == ocMissing; } + +// A parenthesis pair to put around a token range, with a call name before it. What the first +// pass hands the second. +struct OOXMLWrapper +{ + // Half-open range of token positions. + sal_uInt16 mnBegin; + sal_uInt16 mnEnd; + // Call name before the opening parenthesis, ocNone for a bare pair. + OpCode meOperator; + // False when the range already is a parenthesised group, so its own pair serves. + bool mbOwnParentheses; +}; + +// Operators that can come before an operand. A sign there is always the unary form, no +// matter which of the two opcodes the parser used. @ and # are left out, they get their own +// wrappers. +bool lclIsPrefixOperator(OpCode eOp) +{ + if (eOp == ocSingleValue || eOp == ocSpill) + return false; + return eOp == ocAdd || eOp == ocSub || isUnaryOperatorOpCode(eOp); +} + +bool lclIsFactorSeparator(OpCode eOp) +{ + // Tokens between two factors at the same parenthesis depth - a new operand starts after + // them. + if (isBinaryOperatorOpCode(eOp)) + return true; + return eOp == ocSep || eOp == ocArrayColSep || eOp == ocArrayRowSep; +} + +// Tokens that end the operand of a preceding @. Range, intersection, union and call bind +// tighter than the @ so they stay inside, everything above it in the grammar ends it. +bool lclEndsSingleValueOperand(OpCode eOp) +{ + if (eOp == ocRange || eOp == ocIntersect || eOp == ocUnion || eOp == ocCall) + return false; + return lclIsFactorSeparator(eOp) || eOp == ocPercentSign; +} + +// Single pass over the token array to collect what the OOXML spelling needs. +// +// Precedence comes from the order the tokens appear in, so this is a second statement of the +// precedence the parser already applied. Change how an operator binds in one place and the +// other one needs the same change. +class RewriteCollector +{ +public: + RewriteCollector(const FormulaTokenArray& rTokens, std::vector& rWrappers, + std::vector& rErrorPositions) + : mrTokens(rTokens) + , mrWrappers(rWrappers) + , mrErrorPositions(rErrorPositions) + { + } + + void collect(); + +private: + // An @ we have not recorded a wrapper for yet. + struct PendingSingleValue + { + // Parenthesis scope the operand is in, 1 is the outermost. + size_t mnScope; + // First token position of the operand. + sal_uInt16 mnBegin; + // Set once a token that actually carries an operand shows up in the range. + bool mbHasOperand; + }; + + // Positions tracked for one open parenthesis scope. + struct Scope + { + // First token position inside the scope. + sal_uInt16 mnContentStart; + // Start of the union-level expression we are reading. + sal_uInt16 mnExpressionStart; + // Start of the current factor: an operand plus its parentheses and arguments. + sal_uInt16 mnFactorStart; + // Start of an open union list, NO_POSITION if there is none. + sal_uInt16 mnListStart; + // The scope is a grouping parenthesis, not a call's argument list. + bool mbGroupParenthesis; + }; + + OpCode opCodeAt(sal_uInt16 nPosition) const; + sal_uInt16 endWithoutTrailingWhitespace(sal_uInt16 nBegin, sal_uInt16 nEnd) const; + sal_uInt16 literalOffsetArgument(sal_uInt16 nPosition) const; + bool isCallBeforeArguments(OpCode eOp, sal_uInt16 nPosition) const; + bool isOneParenthesizedGroup(sal_uInt16 nBegin, sal_uInt16 nEnd) const; + bool hasPendingAtStart(sal_uInt16 nContentStart) const; + + void markPendingOperand(); + static void movePastToken(Scope& rScope, sal_uInt16 nPosition); + void closeSingleValues(size_t nScope, sal_uInt16 nEnd); + void cancelSingleValues(size_t nScope); + void closeUnionList(sal_uInt16 nEnd, bool bMayTakeScopeParenthesis); + + const FormulaTokenArray& mrTokens; + std::vector& mrWrappers; + std::vector& mrErrorPositions; + std::vector maPendingSingles; + std::vector maScopes; +}; + +OpCode RewriteCollector::opCodeAt(sal_uInt16 nPosition) const +{ + return mrTokens.TokenAt(nPosition)->GetOpCode(); +} + +// An operand stops before the whitespace in front of the operator that ends it. +sal_uInt16 RewriteCollector::endWithoutTrailingWhitespace(sal_uInt16 nBegin, sal_uInt16 nEnd) const +{ + while (nEnd > nBegin && isWhitespaceOpCode(opCodeAt(sal_uInt16(nEnd - 1)))) + --nEnd; + return nEnd; +} + +// Position of the first argument if the token at nPosition opens an OFFSET() call with a +// literal string or number there, NO_POSITION otherwise. OFFSET() needs a reference, so a +// literal cannot be written out in a way any reader accepts. +sal_uInt16 RewriteCollector::literalOffsetArgument(sal_uInt16 nPosition) const +{ + if (nPosition + 2 >= mrTokens.GetLen()) + return NO_POSITION; + const FormulaToken* pName = mrTokens.TokenAt(nPosition); + if (pName->GetOpCode() != ocOffset || pName->GetType() != svByte) + return NO_POSITION; + const FormulaToken* pOpen = mrTokens.TokenAt(sal_uInt16(nPosition + 1)); + if (pOpen->GetOpCode() != ocOpen || pOpen->GetType() != svSep) + return NO_POSITION; + const FormulaToken* pArgument = mrTokens.TokenAt(sal_uInt16(nPosition + 2)); + if (pArgument->GetOpCode() != ocPush) + return NO_POSITION; + const StackVar eType = pArgument->GetType(); + if (eType != svString && eType != svDouble) + return NO_POSITION; + return sal_uInt16(nPosition + 2); +} + +// AND, OR and the call operator have operator opcodes but are written as calls, so the +// parenthesis after the name opens an argument list, not a group. +bool RewriteCollector::isCallBeforeArguments(OpCode eOp, sal_uInt16 nPosition) const +{ + if (eOp != ocAnd && eOp != ocOr && eOp != ocCall) + return false; + for (sal_uInt16 nNext = sal_uInt16(nPosition + 1); nNext < mrTokens.GetLen(); ++nNext) + { + const OpCode eNext = opCodeAt(nNext); + if (!isWhitespaceOpCode(eNext)) + return eNext == ocOpen; + } + return false; +} + +// The range is a single parenthesised group, so we can reuse its parentheses for the +// wrapper. +bool RewriteCollector::isOneParenthesizedGroup(sal_uInt16 nBegin, sal_uInt16 nEnd) const +{ + if (nEnd - nBegin < 2 || opCodeAt(nBegin) != ocOpen) + return false; + sal_Int32 nDepth = 0; + for (sal_uInt16 nPosition = nBegin; nPosition < nEnd; ++nPosition) + { + // Inline matrix braces and table reference brackets have separators of their own, + // so count them as scopes too. + const OpCode eOp = opCodeAt(nPosition); + if (eOp == ocOpen || eOp == ocArrayOpen || eOp == ocTableRefOpen) + { + ++nDepth; + } + else if (eOp == ocClose || eOp == ocArrayClose || eOp == ocTableRefClose) + { + --nDepth; + if (nDepth == 0) + return nPosition == nEnd - 1; + } + else if (nDepth == 1 && (eOp == ocUnion || eOp == ocSep)) + { + // A separator directly inside means the parentheses hold arguments together, + // so we cannot reuse them. + return false; + } + } + return false; +} + +// A pending operand starts at or before the scope's own tokens, so the scope's parentheses +// are already taken. +bool RewriteCollector::hasPendingAtStart(sal_uInt16 nContentStart) const +{ + for (const PendingSingleValue& rSingle : maPendingSingles | std::views::reverse) + { + if (rSingle.mnScope < maScopes.size()) + break; + if (rSingle.mnBegin <= nContentStart) + return true; + } + return false; +} + +// A token that writes no text cannot be the start of anything, so move any start that sits +// on it forward. +void RewriteCollector::movePastToken(Scope& rScope, sal_uInt16 nPosition) +{ + if (rScope.mnContentStart == nPosition) + rScope.mnContentStart = sal_uInt16(nPosition + 1); + if (rScope.mnExpressionStart == nPosition) + rScope.mnExpressionStart = sal_uInt16(nPosition + 1); + if (rScope.mnFactorStart == nPosition) + rScope.mnFactorStart = sal_uInt16(nPosition + 1); +} + +// Mark pending operands as filled. A mark is never cleared, so walking from the back can +// stop at the first marked one. +void RewriteCollector::markPendingOperand() +{ + for (PendingSingleValue& rSingle : maPendingSingles | std::views::reverse) + { + if (rSingle.mbHasOperand) + break; + rSingle.mbHasOperand = true; + } +} + +// Record the wrappers pending from nScope and deeper, innermost first. Each operand runs +// from its own start to nEnd. +void RewriteCollector::closeSingleValues(size_t nScope, sal_uInt16 nEnd) +{ + while (!maPendingSingles.empty() && maPendingSingles.back().mnScope >= nScope) + { + const PendingSingleValue& rSingle = maPendingSingles.back(); + // An empty operand gets no wrapper. + if (rSingle.mbHasOperand) + { + const sal_uInt16 nOperandEnd = endWithoutTrailingWhitespace(rSingle.mnBegin, nEnd); + mrWrappers.push_back({ rSingle.mnBegin, nOperandEnd, ocSingleValue, + !isOneParenthesizedGroup(rSingle.mnBegin, nOperandEnd) }); + // The wrapper now encloses the expression, so the expression starts at the + // wrapper. Whitespace the scope start had skipped is inside the wrapper too, + // so pull that start back as well. + if (maScopes.back().mnExpressionStart > rSingle.mnBegin) + maScopes.back().mnExpressionStart = rSingle.mnBegin; + if (maScopes.back().mnContentStart > rSingle.mnBegin) + maScopes.back().mnContentStart = rSingle.mnBegin; + } + maPendingSingles.pop_back(); + } +} + +// Throw away the wrappers pending from nScope and deeper. +void RewriteCollector::cancelSingleValues(size_t nScope) +{ + while (!maPendingSingles.empty() && maPendingSingles.back().mnScope >= nScope) + maPendingSingles.pop_back(); +} + +// Record the parentheses for the scope's open union list. If the list exactly fills a +// grouping parenthesis and bMayTakeScopeParenthesis allows it, reuse that pair. +void RewriteCollector::closeUnionList(sal_uInt16 nEnd, bool bMayTakeScopeParenthesis) +{ + Scope& rScope = maScopes.back(); + if (rScope.mnListStart == NO_POSITION) + return; + if (!(bMayTakeScopeParenthesis && rScope.mbGroupParenthesis + && rScope.mnListStart == rScope.mnContentStart)) + { + mrWrappers.push_back({ rScope.mnListStart, + endWithoutTrailingWhitespace(rScope.mnListStart, nEnd), ocNone, + true }); + } + rScope.mnListStart = NO_POSITION; +} + +void RewriteCollector::collect() +{ + const sal_uInt16 nLength = mrTokens.GetLen(); + maScopes.push_back({ 0, 0, 0, NO_POSITION, false }); + // The next token is where an operand starts, so a plus or minus there is the unary form. + bool bOperandPosition = true; + // The current factor is raw text that never parsed - we cannot put wrapper parentheses + // around that. + bool bBadFactor = false; + + for (sal_uInt16 nPosition = 0; nPosition < nLength; ++nPosition) + { + const OpCode eOp = opCodeAt(nPosition); + + const sal_uInt16 nLiteralOffsetArgument = literalOffsetArgument(nPosition); + if (nLiteralOffsetArgument != NO_POSITION) + mrErrorPositions.push_back(nLiteralOffsetArgument); + + // The @ writes no text of its own. Remember where the operand starts and which scope + // it is in, the wrapper gets recorded once we know how far the operand reaches. + if (eOp == ocSingleValue) + { + Scope& rScope = maScopes.back(); + // Any start sitting on the @ moves on to the operand after it, and so does the + // factor it begins. + movePastToken(rScope, nPosition); + rScope.mnFactorStart = sal_uInt16(nPosition + 1); + maPendingSingles.push_back({ maScopes.size(), sal_uInt16(nPosition + 1), false }); + continue; + } + + // The # is written as a call around the factor before it and binds tighter than any + // operator that can come before that factor. Raw text that never parsed takes no + // parentheses, so drop a # after one, and drop a # with no factor before it at all. + if (eOp == ocSpill) + { + if (!bBadFactor) + { + mrWrappers.push_back( + { maScopes.back().mnFactorStart, nPosition, ocAnchorArray, true }); + markPendingOperand(); + } + bOperandPosition = false; + continue; + } + + const bool bWhitespace = isWhitespaceOpCode(eOp); + // A sign where an operand starts is always the unary form, whichever opcode the + // parser used, and it belongs to the operand after it. + const bool bPrefix = bOperandPosition && lclIsPrefixOperator(eOp); + const bool bCallName = !bPrefix && isCallBeforeArguments(eOp, nPosition); + const bool bSeparator = !bPrefix && !bCallName && lclIsFactorSeparator(eOp); + // The union list and the @ operand cover the same part of the grammar, so the same + // tokens end both. + const bool bEndsOperand = !bPrefix && !bCallName && lclEndsSingleValueOperand(eOp); + + // A structured table reference comes through here token by token, so its brackets + // scope like parentheses and the separators inside stay with the reference. + if (eOp == ocOpen || eOp == ocTableRefOpen) + { + markPendingOperand(); + // A grouping parenthesis is where an operand starts, a call's parenthesis comes + // after the function name. + maScopes.push_back({ sal_uInt16(nPosition + 1), sal_uInt16(nPosition + 1), + sal_uInt16(nPosition + 1), NO_POSITION, + eOp == ocOpen && bOperandPosition }); + bOperandPosition = true; + bBadFactor = false; + continue; + } + if (eOp == ocClose || eOp == ocTableRefClose) + { + if (maScopes.size() > 1) + { + // The union list closes before the @ wrappers, so its parentheses end up + // inside theirs. + const bool bMayTakeScopeParenthesis + = !hasPendingAtStart(maScopes.back().mnContentStart); + closeUnionList(nPosition, bMayTakeScopeParenthesis); + closeSingleValues(maScopes.size(), nPosition); + maScopes.pop_back(); + } + markPendingOperand(); + bOperandPosition = false; + bBadFactor = false; + continue; + } + + // An operator higher up in the grammar ends both the union list and the @ operand, + // so their wrappers close before it. + if (bEndsOperand) + { + closeUnionList(nPosition, false); + closeSingleValues(maScopes.size(), nPosition); + } + + if (eOp == ocBad) + { + // Raw text that never parsed cannot take parentheses, so drop the wrappers + // waiting on it. + maScopes.back().mnListStart = NO_POSITION; + cancelSingleValues(maScopes.size()); + bBadFactor = true; + } + + Scope& rScope = maScopes.back(); + // Whitespace before a scope, expression or factor is not part of it. + if (bWhitespace) + movePastToken(rScope, nPosition); + if (!bPrefix && !bWhitespace && !lclWritesNoText(eOp)) + markPendingOperand(); + if (eOp == ocUnion && rScope.mnListStart == NO_POSITION) + { + // The first union operator opens the list, the ones after it just extend it. + rScope.mnListStart = rScope.mnExpressionStart; + } + if (bPrefix || (bEndsOperand && bSeparator)) + { + // A prefix sign or an infix operator starts a new expression after it. A postfix + // one does not, it belongs to the operand before it. + rScope.mnExpressionStart = sal_uInt16(nPosition + 1); + } + if (bPrefix || bSeparator || bEndsOperand) + { + // Every operator and separator ends the factor before it, so the next factor + // starts after. A function name does not. + rScope.mnFactorStart = sal_uInt16(nPosition + 1); + } + if (bSeparator) + bBadFactor = false; + if (!bWhitespace) + bOperandPosition = bPrefix || bSeparator; + } + + // Anything still pending reaches the end of the formula. Union lists close first so + // their parentheses end up inside the @ wrappers. + while (maScopes.size() > 1) + { + closeUnionList(nLength, false); + maScopes.pop_back(); + } + closeUnionList(nLength, false); + closeSingleValues(1, nLength); + + // A wrapper recorded later always reaches at least as far as an earlier one, so sorting + // by end descending puts the wider of two wrappers with the same begin first. The + // reverse before that handles the ones that also end at the same position. + std::reverse(mrWrappers.begin(), mrWrappers.end()); + std::stable_sort(mrWrappers.begin(), mrWrappers.end(), + [](const OOXMLWrapper& rLeft, const OOXMLWrapper& rRight) { + if (rLeft.mnBegin != rRight.mnBegin) + return rLeft.mnBegin < rRight.mnBegin; + return rLeft.mnEnd > rRight.mnEnd; + }); +} + +// Copy rTokens with the recorded call names and parentheses put in, and #REF! for the tokens +// that have no OOXML spelling. +std::unique_ptr lclBuild(const FormulaTokenArray& rTokens, + const std::vector& rWrappers, + const std::vector& rErrorPositions) +{ + auto pRewritten = std::make_unique(); + pRewritten->AddRecalcMode(rTokens.GetRecalcMode()); + + // The end position of every pair opened so far, innermost last. + std::vector aOpenEnds; + size_t nNextWrapper = 0; + const sal_uInt16 nLength = rTokens.GetLen(); + // One past the last token, so the pairs reaching the end get closed. + for (sal_uInt16 nPosition = 0; nPosition <= nLength; ++nPosition) + { + while (!aOpenEnds.empty() && aOpenEnds.back() <= nPosition) + { + pRewritten->AddOpCode(ocClose); + aOpenEnds.pop_back(); + } + while (nNextWrapper < rWrappers.size() && rWrappers[nNextWrapper].mnBegin <= nPosition) + { + const OOXMLWrapper& rWrapper = rWrappers[nNextWrapper++]; + // Nothing between the ends, so there is nothing to enclose and the pair goes. + // A # with no factor in front of it is the case that gets here. + if (rWrapper.mnBegin == rWrapper.mnEnd) + continue; + if (rWrapper.meOperator != ocNone) + pRewritten->AddOpCode(rWrapper.meOperator); + if (rWrapper.mbOwnParentheses) + { + pRewritten->AddOpCode(ocOpen); + aOpenEnds.push_back(rWrapper.mnEnd); + } + } + if (nPosition == nLength) + break; + + const FormulaToken* pToken = rTokens.TokenAt(nPosition); + const OpCode eOp = pToken->GetOpCode(); + if (lclIsDropped(eOp)) + { + // The wrapper's call name stands for these. A # that got no wrapper had + // nothing to bind to, so it goes. + continue; + } + if (std::binary_search(rErrorPositions.begin(), rErrorPositions.end(), nPosition)) + pRewritten->AddOpCode(ocErrRef); + else + pRewritten->AddToken(*pToken); + } + return pRewritten; +} + +// Whether the OOXML shape differs from the array as it stands. Dropping a token counts, so a +// lone @ with no operand is a change even though it takes no wrapper. +bool lclNeedsRewrite(const FormulaTokenArray& rTokens, const std::vector& rWrappers, + const std::vector& rErrorPositions) +{ + if (!rWrappers.empty() || !rErrorPositions.empty()) + return true; + for (sal_uInt16 nPosition = 0; nPosition < rTokens.GetLen(); ++nPosition) + { + if (lclIsDropped(rTokens.TokenAt(nPosition)->GetOpCode())) + return true; + } + return false; +} + +} // namespace + +OOXMLRewriter::OOXMLRewriter(const FormulaTokenArray& rTokens) +{ + std::vector aWrappers; + std::vector aErrorPositions; + RewriteCollector(rTokens, aWrappers, aErrorPositions).collect(); + if (!lclNeedsRewrite(rTokens, aWrappers, aErrorPositions)) + return; + mpRewritten = lclBuild(rTokens, aWrappers, aErrorPositions); +} + +} // namespace formula + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/editeng/paragraphdata.hxx b/formula/source/core/api/callable.cxx similarity index 54% rename from include/editeng/paragraphdata.hxx rename to formula/source/core/api/callable.cxx index f0e859d6fe1a..49b549cebc83 100644 --- a/include/editeng/paragraphdata.hxx +++ b/formula/source/core/api/callable.cxx @@ -17,32 +17,34 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_EDITENG_PARAGRAPHDATA_HXX -#define INCLUDED_EDITENG_PARAGRAPHDATA_HXX +#include +#include #include -#include -class ParagraphData +#include +#include +#include +#include + +#include + +namespace formula { - friend class Paragraph; - friend class OutlinerParaObject; +/// a static hash of all the built-ins that have been accessed +static std::map aAllBuiltIns; -protected: - sal_Int16 nDepth; - sal_Int16 mnNumberingStartValue; - bool mbParaIsNumberingRestart; - -public: - ParagraphData(); - - bool operator==(const ParagraphData& rCandidate) const; - - sal_Int16 getDepth() const { return nDepth; } -}; - -typedef ::std::vector< ParagraphData > ParagraphDataVector; - -#endif // INCLUDED_EDITENG_PARAGRAPHDATA_HXX +// We're ensuring that a FormulaBuiltInFunction corresponding to eOpCode is +// in our map, and returning a reference to it. This allows us to ensure that +// at most one FormulaBuiltInFunction exists for each OpCode. +FormulaCallableRef FormulaBuiltInFunction::Get(OpCode eOpCode) +{ + auto iter = aAllBuiltIns.find(eOpCode); + if (iter == aAllBuiltIns.end()) + return (aAllBuiltIns[eOpCode] = new FormulaBuiltInFunction(eOpCode)); + else + return iter->second; +} +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx index 8cbaa7bb05a5..b270a56acdd2 100644 --- a/formula/source/core/api/token.cxx +++ b/formula/source/core/api/token.cxx @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -70,43 +70,68 @@ FormulaToken::~FormulaToken() bool FormulaToken::IsFunction() const { - return (eOp != ocPush && eOp != ocBad && eOp != ocColRowName && + if (!(eOp != ocPush && eOp != ocBad && eOp != ocColRowName && eOp != ocColRowNameAuto && eOp != ocName && eOp != ocDBArea && eOp != ocTableRef && - (GetByte() != 0 // x parameters - || (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR) // no parameter + eOp != ocSep && eOp != ocDPFieldName && eOp != ocClose && eOp != ocOpen)) + return false; + if ((ocStartNoParameters <= eOp && eOp < ocStopNoParameters) // no parameter || FormulaCompiler::IsOpCodeJumpCommand( eOp ) // @ jump commands - || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) // one parameter - || (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR) // x parameters (cByte==0 in + || (ocStartOneParameter <= eOp && eOp < ocStopOneParameter) // one parameter + || (ocStartTwoParameters <= eOp && eOp < ocStopTwoParameters) // x parameters (cByte==0 in // FuncAutoPilot) - || eOp == ocMacro || eOp == ocExternal // macros, AddIns + || eOp == ocMacro || eOp == ocExternal || eOp == ocUDExternal // macros, AddIns || eOp == ocAnd || eOp == ocOr // former binary, now x parameters || (eOp >= ocInternalBegin && eOp <= ocInternalEnd) // internal - )); + ) + return true; + if (eOp == ocWhitespace) + return (static_cast(this)->GetByte() != 0); // x parameters + if (eType == svByte) + return (static_cast(this)->GetByte() != 0); // x parameters + return false; } sal_uInt8 FormulaToken::GetParamCount() const { - if ( eOp < SC_OPCODE_STOP_DIV && eOp != ocExternal && eOp != ocMacro && - !FormulaCompiler::IsOpCodeJumpCommand( eOp ) && - eOp != ocPercentSign ) + if (eOp < ocStopDiv && eOp != ocExternal && eOp != ocMacro && eOp != ocUDExternal + && !FormulaCompiler::IsOpCodeJumpCommand(eOp) && eOp != ocPercentSign) return 0; // parameters and specials // ocIf... jump commands not for FAP, have cByte then -//2do: bool parameter whether FAP or not? - else if (GetByte()) - return GetByte(); // all functions, also ocExternal and ocMacro - else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP && eOp != ocAnd && eOp != ocOr) - return 2; // binary operators, compiler checked; OR and AND legacy but are functions - else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP) || eOp == ocPercentSign) + else if (isBinaryOperatorOpCode(eOp) && eOp != ocAnd && eOp != ocOr && eOp != ocCall) + return 2; // binary operators, compiler checked; OR and AND legacy but are + // functions; ocCall may have more than two params + else if (isUnaryOperatorOpCode(eOp) || eOp == ocPercentSign) return 1; // unary operators, compiler checked - else if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR) + else if (ocStartNoParameters <= eOp && eOp < ocStopNoParameters) return 0; // no parameter else if (FormulaCompiler::IsOpCodeJumpCommand( eOp )) return 1; // only the condition counts as parameter - else - return 0; // all the rest, no Parameter, or - // if so then it should be in cByte + + //2do: bool parameter whether FAP or not? + if (GetType() == svByte) + { + if (auto n = static_cast(this)->GetByte()) + return n; // all functions, also ocExternal and ocMacro + } + if (GetType() == svFAP) + { + if (auto n = static_cast(this)->GetByte()) + return n; // all functions, also ocExternal and ocMacro + } + if (GetType() == svExternal) + { + if (auto n = static_cast(this)->GetByte()) + return n; + } + if (GetType() == svString && (eOp == ocBad || eOp == ocStringXML || eOp == ocStringName || eOp == ocDPFieldName)) + { + if (auto n = static_cast(this)->GetByte()) + return n; + } + return 0; // all the rest, no Parameter, or + // if so then it should be in cByte } bool FormulaToken::IsExternalRef() const @@ -159,17 +184,6 @@ bool FormulaToken::operator==( const FormulaToken& rToken ) const // --- virtual dummy methods ------------------------------------------------- -sal_uInt8 FormulaToken::GetByte() const -{ - // ok to be called for any derived class - return 0; -} - -void FormulaToken::SetByte( sal_uInt8 ) -{ - assert( !"virtual dummy called" ); -} - ParamClass FormulaToken::GetInForceArray() const { // ok to be called for any derived class @@ -181,168 +195,8 @@ void FormulaToken::SetInForceArray( ParamClass ) assert( !"virtual dummy called" ); } -double FormulaToken::GetDouble() const -{ - // This Get is worth an assert. - assert( !"virtual dummy called" ); - return 0.0; -} - -void FormulaToken::SetDouble(double) -{ - // This Get is worth an assert. - assert( !"virtual dummy called" ); -} - -sal_Int16 FormulaToken::GetDoubleType() const -{ - SAL_WARN( "formula.core", "FormulaToken::GetDoubleType: virtual dummy called" ); - return 0; -} - -void FormulaToken::SetDoubleType( sal_Int16 ) -{ - assert( !"virtual dummy called" ); -} - const svl::SharedString INVALID_STRING; -const svl::SharedString & FormulaToken::GetString() const -{ - SAL_WARN( "formula.core", "FormulaToken::GetString: virtual dummy called" ); - return INVALID_STRING; // invalid string -} - -void FormulaToken::SetString( const svl::SharedString& ) -{ - assert( !"virtual dummy called" ); -} - -sal_uInt16 FormulaToken::GetIndex() const -{ - SAL_WARN( "formula.core", "FormulaToken::GetIndex: virtual dummy called" ); - return 0; -} - -void FormulaToken::SetIndex( sal_uInt16 ) -{ - assert( !"virtual dummy called" ); -} - -sal_Int16 FormulaToken::GetSheet() const -{ - SAL_WARN( "formula.core", "FormulaToken::GetSheet: virtual dummy called" ); - return -1; -} - -void FormulaToken::SetSheet( sal_Int16 ) -{ - assert( !"virtual dummy called" ); -} - -sal_Unicode FormulaToken::GetChar() const -{ - // This Get is worth an assert. - assert( !"virtual dummy called" ); - return 0; -} - -short* FormulaToken::GetJump() const -{ - SAL_WARN( "formula.core", "FormulaToken::GetJump: virtual dummy called" ); - return nullptr; -} - - -const OUString& FormulaToken::GetExternal() const -{ - SAL_WARN( "formula.core", "FormulaToken::GetExternal: virtual dummy called" ); - static OUString aDummyString; - return aDummyString; -} - -FormulaToken* FormulaToken::GetFAPOrigToken() const -{ - SAL_WARN( "formula.core", "FormulaToken::GetFAPOrigToken: virtual dummy called" ); - return nullptr; -} - -FormulaError FormulaToken::GetError() const -{ - SAL_WARN( "formula.core", "FormulaToken::GetError: virtual dummy called" ); - return FormulaError::NONE; -} - -void FormulaToken::SetError( FormulaError ) -{ - assert( !"virtual dummy called" ); -} - -const ScSingleRefData* FormulaToken::GetSingleRef() const -{ - OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" ); - return nullptr; -} - -ScSingleRefData* FormulaToken::GetSingleRef() -{ - OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" ); - return nullptr; -} - -const ScComplexRefData* FormulaToken::GetDoubleRef() const -{ - OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" ); - return nullptr; -} - -ScComplexRefData* FormulaToken::GetDoubleRef() -{ - OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" ); - return nullptr; -} - -const ScSingleRefData* FormulaToken::GetSingleRef2() const -{ - OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" ); - return nullptr; -} - -ScSingleRefData* FormulaToken::GetSingleRef2() -{ - OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" ); - return nullptr; -} - -const ScMatrix* FormulaToken::GetMatrix() const -{ - OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" ); - return nullptr; -} - -ScMatrix* FormulaToken::GetMatrix() -{ - OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" ); - return nullptr; -} - -ScJumpMatrix* FormulaToken::GetJumpMatrix() const -{ - OSL_FAIL( "FormulaToken::GetJumpMatrix: virtual dummy called" ); - return nullptr; -} -const std::vector* FormulaToken::GetRefList() const -{ - OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" ); - return nullptr; -} - -std::vector* FormulaToken::GetRefList() -{ - OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" ); - return nullptr; -} - bool FormulaToken::TextEqual( const FormulaToken& rToken ) const { return *this == rToken; @@ -355,18 +209,18 @@ sal_uInt8 FormulaSpaceToken::GetByte() const { return nByte; } sal_Unicode FormulaSpaceToken::GetChar() const { return cChar; } bool FormulaSpaceToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && nByte == r.GetByte() && - cChar == r.GetChar(); + return FormulaToken::operator==( r ) + && nByte == static_cast(r).GetByte() + && cChar == static_cast(r).GetChar(); } -sal_uInt8 FormulaByteToken::GetByte() const { return nByte; } -void FormulaByteToken::SetByte( sal_uInt8 n ) { nByte = n; } ParamClass FormulaByteToken::GetInForceArray() const { return eInForceArray; } void FormulaByteToken::SetInForceArray( ParamClass c ) { eInForceArray = c; } bool FormulaByteToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && nByte == r.GetByte() && + return FormulaToken::operator==( r ) + && mnByte == static_cast(r).mnByte && eInForceArray == r.GetInForceArray(); } @@ -374,24 +228,36 @@ bool FormulaByteToken::operator==( const FormulaToken& r ) const FormulaToken* FormulaFAPToken::GetFAPOrigToken() const { return pOrigToken.get(); } bool FormulaFAPToken::operator==( const FormulaToken& r ) const { - return FormulaByteToken::operator==( r ) && pOrigToken == r.GetFAPOrigToken(); + return FormulaToken::operator==( r ) + && mnByte == static_cast(r).mnByte + && pOrigToken == static_cast(r).GetFAPOrigToken(); } -short* FormulaJumpToken::GetJump() const { return pJump.get(); } ParamClass FormulaJumpToken::GetInForceArray() const { return eInForceArray; } void FormulaJumpToken::SetInForceArray( ParamClass c ) { eInForceArray = c; } bool FormulaJumpToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && pJump[0] == r.GetJump()[0] && - memcmp( pJump.get()+1, r.GetJump()+1, pJump[0] * sizeof(short) ) == 0 && - eInForceArray == r.GetInForceArray(); + if (!FormulaToken::operator==( r )) + return false; + auto const & rhs = static_cast(r); + return pJump[0] == rhs.GetJump()[0] && + memcmp( pJump.get()+1, rhs.GetJump()+1, pJump[0] * sizeof(short) ) == 0 && + eInForceArray == rhs.GetInForceArray(); } FormulaJumpToken::~FormulaJumpToken() { } +FormulaCallableRef FormulaCallableToken::GetCallable() const { return mpCallable; } +bool FormulaCallableToken::operator==( const FormulaToken& r ) const +{ + return FormulaToken::operator==( r ) && + mpCallable == static_cast(r).GetCallable(); +} + + bool FormulaTokenArray::AddFormulaToken( const sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool, ExternalReferenceHelper* /*pExtRef*/) { @@ -402,8 +268,34 @@ bool FormulaTokenArray::AddFormulaToken( switch ( eClass ) { case uno::TypeClass_VOID: - // empty data -> use AddOpCode (does some special cases) - AddOpCode( eOpCode ); + switch (eOpCode) + { + case ocErrNull: + AddError(FormulaError::NoCode); + break; + case ocErrDivZero: + AddError(FormulaError::DivisionByZero); + break; + case ocErrValue: + AddError(FormulaError::NoValue); + break; + case ocErrRef: + AddError(FormulaError::NoRef); + break; + case ocErrName: + AddError(FormulaError::NoName); + break; + case ocErrNum: + AddError(FormulaError::IllegalFPOperation); + break; + case ocErrNA: + AddError(FormulaError::NotAvailable); + break; + default: + // empty data -> use AddOpCode (does some special cases) + AddOpCode(eOpCode); + break; + } break; case uno::TypeClass_DOUBLE: // double is only used for "push" @@ -437,7 +329,7 @@ bool FormulaTokenArray::AddFormulaToken( AddStringName( aStrVal ); else if ( eOpCode == ocDPFieldName ) AddDPFieldName( aStrVal ); - else if ( eOpCode == ocExternal || eOpCode == ocMacro ) + else if ( eOpCode == ocExternal || eOpCode == ocMacro || eOpCode == ocUDExternal) Add( new formula::FormulaExternalToken( eOpCode, aStrVal ) ); else if ( eOpCode == ocWhitespace ) { @@ -478,14 +370,13 @@ void FormulaTokenArray::DelRPN() { if( nRPN ) { - FormulaToken** p = pRPN; + FormulaToken** p = pRPN.get(); for( sal_uInt16 i = 0; i < nRPN; i++ ) { (*p++)->DecRef(); } - delete [] pRPN; + pRPN.reset(); } - pRPN = nullptr; nRPN = 0; } @@ -510,13 +401,6 @@ FormulaToken* FormulaTokenArray::FirstRPNToken() const return pRPN[0]; } -FormulaToken* FormulaTokenArray::LastRPNToken() const -{ - if (!pRPN || nRPN == 0) - return nullptr; - return pRPN[nRPN - 1]; -} - bool FormulaTokenArray::HasReferences() const { for (auto i: Tokens()) @@ -586,7 +470,6 @@ bool FormulaTokenArray::HasOpCodes(const unordered_opcode_set& rOpCodes) const } FormulaTokenArray::FormulaTokenArray() : - pRPN(nullptr), nLen(0), nRPN(0), nError(FormulaError::NONE), @@ -594,7 +477,8 @@ FormulaTokenArray::FormulaTokenArray() : bHyperLink(false), mbFromRangeName(false), mbShareable(true), - mbFinalized(false) + mbFinalized(false), + mbDynamicArrayFunction(false) { } @@ -635,6 +519,7 @@ void FormulaTokenArray::Assign( const FormulaTokenArray& r ) mbFromRangeName = r.mbFromRangeName; mbShareable = r.mbShareable; mbFinalized = r.mbFinalized; + mbDynamicArrayFunction = r.mbDynamicArrayFunction; pCode = nullptr; pRPN = nullptr; FormulaToken** pp; @@ -649,8 +534,9 @@ void FormulaTokenArray::Assign( const FormulaTokenArray& r ) } if( nRPN ) { - pp = pRPN = new FormulaToken*[ nRPN ]; - memcpy( pp, r.pRPN, nRPN * sizeof( FormulaToken* ) ); + pRPN = std::make_unique(nRPN); + pp = pRPN.get(); + memcpy( pp, r.pRPN.get(), nRPN * sizeof( FormulaToken* ) ); for( sal_uInt16 i = 0; i < nRPN; i++ ) (*pp++)->IncRef(); } @@ -659,8 +545,7 @@ void FormulaTokenArray::Assign( const FormulaTokenArray& r ) void FormulaTokenArray::Move( FormulaTokenArray&& r ) { pCode = std::move(r.pCode); - pRPN = r.pRPN; - r.pRPN = nullptr; + pRPN = std::move(r.pRPN); nLen = r.nLen; r.nLen = 0; nRPN = r.nRPN; @@ -671,6 +556,7 @@ void FormulaTokenArray::Move( FormulaTokenArray&& r ) mbFromRangeName = r.mbFromRangeName; mbShareable = r.mbShareable; mbFinalized = r.mbFinalized; + mbDynamicArrayFunction = r.mbDynamicArrayFunction; } /// Optimisation for efficiently creating StringXML placeholders @@ -728,6 +614,7 @@ void FormulaTokenArray::Clear() mbFromRangeName = false; mbShareable = true; mbFinalized = false; + mbDynamicArrayFunction = false; ClearRecalcMode(); } @@ -740,7 +627,7 @@ void FormulaTokenArray::CheckAllRPNTokens() { if( nRPN ) { - FormulaToken** p = pRPN; + FormulaToken** p = pRPN.get(); for( sal_uInt16 i = 0; i < nRPN; i++ ) { CheckToken( *p[ i ] ); @@ -908,9 +795,9 @@ FormulaToken* FormulaTokenArray::AddString( const svl::SharedString& rStr ) return Add( new FormulaStringToken( rStr ) ); } -FormulaToken* FormulaTokenArray::AddStringName( const svl::SharedString& rStr ) +FormulaToken* FormulaTokenArray::AddStringName(const svl::SharedString& rString, bool bOptional) { - return Add( new FormulaStringNameToken( svStringName, rStr ) ); + return Add(new FormulaStringNameToken(svStringName, rString, bOptional)); } FormulaToken* FormulaTokenArray::AddDPFieldName( const svl::SharedString& rStr ) @@ -1309,6 +1196,18 @@ void FormulaMissingContext::AddMoreArgs( FormulaTokenArray *pNewArr, const Missi } break; + case ocExternal: + if (static_cast(mpFunc)->GetExternal().equalsIgnoreAsciiCase( + "com.sun.star.sheet.addin.Analysis.getAccrintm")) + { + if (mnCurArg == 2) + { + pNewArr->AddOpCode(ocSep); + pNewArr->AddDouble(1000.0); + } + } + break; + default: break; } @@ -1332,7 +1231,7 @@ bool FormulaMissingContext::AddMissingExternal( FormulaTokenArray *pNewArr ) con { // Only called for PODF, not ODFF. No need to distinguish. - const OUString &rName = mpFunc->GetExternal(); + const OUString &rName = static_cast(mpFunc)->GetExternal(); // initial (fast) checks: sal_Int32 nLength = rName.getLength(); @@ -1474,7 +1373,7 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention & FormulaMissingContext* pCtx = (nAlloc < nTokens ? new FormulaMissingContext[nTokens] : &aCtx[0]); int* pOcas = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeAddressStack[0]); int* pOcds = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeDcountStack[0]); - // Never go below 0, never use 0, mpFunc always NULL. + // Never go below 0, never use 0, mpFunc always nullptr. pCtx[0].Clear(); int nFn = 0; int nOcas = 0; @@ -1512,7 +1411,7 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention & { // Omit only a literal 0 value, nothing else. if (pOcds[ i ] == nFn && pCur->GetOpCode() == ocPush && pCur->GetType() == svDouble && - pCur->GetDouble() == 0.0) + static_cast(pCur)->GetDouble() == 0.0) { // No other expression, between separators. FormulaToken* p = aIter.PeekPrevNoSpaces(); @@ -1576,7 +1475,7 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention & { OpCode eOp = pCur->GetOpCode(); if ( ( eOp == ocCeil || eOp == ocFloor || - ( eOp == ocLogNormDist && pCur->GetByte() == 4 ) ) && + ( eOp == ocLogNormDist && static_cast(pCur)->GetByte() == 4 ) ) && rConv.getConvention() == MissingConvention::FORMULA_MISSING_CONVENTION_OOXML ) { switch ( eOp ) @@ -1618,10 +1517,6 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention & return pNewArr; } -namespace { -inline bool isWhitespace( OpCode eOp ) { return eOp == ocSpaces || eOp == ocWhitespace; } -} - bool FormulaTokenArray::MayReferenceFollow() { if ( !pCode || nLen <= 0 ) @@ -1629,16 +1524,15 @@ bool FormulaTokenArray::MayReferenceFollow() // ignore trailing spaces sal_uInt16 i = nLen - 1; - while (i > 0 && isWhitespace( pCode[i]->GetOpCode())) + while (i > 0 && isWhitespaceOpCode( pCode[i]->GetOpCode())) { --i; } - if (i > 0 || !isWhitespace( pCode[i]->GetOpCode())) + if (i > 0 || !isWhitespaceOpCode( pCode[i]->GetOpCode())) { OpCode eOp = pCode[i]->GetOpCode(); - if ( (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP ) || - (SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP ) || - eOp == SC_OPCODE_OPEN || eOp == SC_OPCODE_SEP ) + if (isBinaryOperatorOpCode(eOp) || isUnaryOperatorOpCode(eOp) || eOp == ocOpen + || eOp == ocSep) { return true; } @@ -1664,13 +1558,14 @@ FormulaToken* FormulaTokenArray::AddOpCode( OpCode eOp ) case ocIfNA: case ocChoose: case ocLet: + case ocLambda: { short nJump[FORMULA_MAXPARAMS + 1]; if ( eOp == ocIf ) nJump[ 0 ] = 3; else if ( eOp == ocChoose ) nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1; - else if ( eOp == ocLet ) + else if ( eOp == ocLet || eOp == ocLambda ) nJump[ 0 ] = FORMULA_MAXPARAMS + 1; else nJump[ 0 ] = 2; @@ -1691,8 +1586,12 @@ void FormulaTokenArray::ReinternStrings( svl::SharedStringPool& rPool ) switch (i->GetType()) { case svString: - i->SetString( rPool.intern( i->GetString().getString())); + { + assert(dynamic_cast(i)); + auto pStrToken = static_cast(i); + pStrToken->SetString( rPool.intern( pStrToken->GetString().getString())); break; + } default: ; // nothing } @@ -1728,16 +1627,16 @@ void FormulaTokenIterator::Pop() maStack.pop_back(); } -void FormulaTokenIterator::FrontPop() -{ - maStack.erase(maStack.begin()); -} - void FormulaTokenIterator::Lambda(bool bOpt) { maStack.back().bLambda = bOpt; } +bool FormulaTokenIterator::IsLambda() const +{ + return maStack.back().bLambda; +} + void FormulaTokenIterator::Reset() { while( maStack.size() > 1 ) @@ -1761,20 +1660,6 @@ FormulaToken* FormulaTokenArrayPlainIterator::GetNextName() return nullptr; } -FormulaToken* FormulaTokenArrayPlainIterator::GetNextStringNameRPN() -{ - if (mpFTA->GetCode()) - { - while (mnIndex < mpFTA->GetCodeLen()) - { - FormulaToken* t = mpFTA->GetCode()[ mnIndex++ ]; - if (t->GetType() == svStringName) - return t; - } - } - return nullptr; -} - FormulaToken* FormulaTokenArrayPlainIterator::GetNextDPFieldNameRPN() { if (mpFTA->GetCode()) @@ -1948,8 +1833,10 @@ FormulaToken* FormulaTokenArrayPlainIterator::NextNoSpaces() { if( mpFTA->GetArray() ) { - while ((mnIndex < mpFTA->GetLen()) && isWhitespace( mpFTA->GetArray()[ mnIndex ]->GetOpCode())) + while ((mnIndex < mpFTA->GetLen()) && isWhitespaceOpCode(mpFTA->GetArray()[mnIndex]->GetOpCode())) + { ++mnIndex; + } if( mnIndex < mpFTA->GetLen() ) return mpFTA->GetArray()[ mnIndex++ ]; } @@ -1985,7 +1872,7 @@ FormulaToken* FormulaTokenArrayPlainIterator::PeekNextNoSpaces() const if( mpFTA->GetArray() && mnIndex < mpFTA->GetLen() ) { sal_uInt16 j = mnIndex; - while (j < mpFTA->GetLen() && isWhitespace( mpFTA->GetArray()[j]->GetOpCode())) + while (j < mpFTA->GetLen() && isWhitespaceOpCode( mpFTA->GetArray()[j]->GetOpCode())) j++; if ( j < mpFTA->GetLen() ) return mpFTA->GetArray()[ j ]; @@ -2001,9 +1888,9 @@ FormulaToken* FormulaTokenArrayPlainIterator::PeekPrevNoSpaces() const if( mpFTA->GetArray() && mnIndex > 1 ) { sal_uInt16 j = mnIndex - 2; - while (isWhitespace( mpFTA->GetArray()[j]->GetOpCode()) && j > 0 ) + while (isWhitespaceOpCode( mpFTA->GetArray()[j]->GetOpCode()) && j > 0 ) j--; - if (j > 0 || !isWhitespace( mpFTA->GetArray()[j]->GetOpCode())) + if (j > 0 || !isWhitespaceOpCode( mpFTA->GetArray()[j]->GetOpCode())) return mpFTA->GetArray()[ j ]; else return nullptr; @@ -2036,7 +1923,7 @@ sal_Int16 FormulaDoubleToken::GetDoubleType() const bool FormulaDoubleToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && fDouble == r.GetDouble(); + return FormulaToken::operator==( r ) && fDouble == static_cast(r).GetDouble(); } sal_Int16 FormulaTypedDoubleToken::GetDoubleType() const @@ -2051,7 +1938,8 @@ void FormulaTypedDoubleToken::SetDoubleType( sal_Int16 nType ) bool FormulaTypedDoubleToken::operator==( const FormulaToken& r ) const { - return FormulaDoubleToken::operator==( r ) && mnType == r.GetDoubleType(); + return FormulaDoubleToken::operator==( r ) + && mnType == static_cast(r).GetDoubleType(); } FormulaStringToken::FormulaStringToken( svl::SharedString r ) : @@ -2059,6 +1947,11 @@ FormulaStringToken::FormulaStringToken( svl::SharedString r ) : { } +FormulaStringToken::FormulaStringToken( OpCode e, svl::SharedString r ) : + FormulaToken( svString, e ), maString(std::move( r )) +{ +} + FormulaStringToken::FormulaStringToken( const FormulaStringToken& r ) : FormulaToken( r ), maString( r.maString ) {} @@ -2067,11 +1960,6 @@ FormulaToken* FormulaStringToken::Clone() const return new FormulaStringToken(*this); } -const svl::SharedString & FormulaStringToken::GetString() const -{ - return maString; -} - void FormulaStringToken::SetString( const svl::SharedString& rStr ) { maString = rStr; @@ -2079,42 +1967,36 @@ void FormulaStringToken::SetString( const svl::SharedString& rStr ) bool FormulaStringToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && maString == r.GetString(); + return FormulaToken::operator==( r ) + && maString == static_cast(r).GetString(); } FormulaStringOpToken::FormulaStringOpToken( OpCode e, svl::SharedString r ) : - FormulaByteToken( e, 0, svString, ParamClass::Unknown ), maString(std::move( r )) {} + FormulaStringToken(e, r), nByte(0), eInForceArray(ParamClass::Unknown) {} FormulaStringOpToken::FormulaStringOpToken( const FormulaStringOpToken& r ) : - FormulaByteToken( r ), maString( r.maString ) {} + FormulaStringToken( r ), nByte(r.nByte), eInForceArray(r.eInForceArray) {} FormulaToken* FormulaStringOpToken::Clone() const { return new FormulaStringOpToken(*this); } -const svl::SharedString & FormulaStringOpToken::GetString() const -{ - return maString; -} - -void FormulaStringOpToken::SetString( const svl::SharedString& rStr ) -{ - maString = rStr; -} - bool FormulaStringOpToken::operator==( const FormulaToken& r ) const { - return FormulaByteToken::operator==( r ) && maString == r.GetString(); + return FormulaStringToken::operator==( r ) + && nByte == static_cast(r).nByte + && eInForceArray == static_cast(r).eInForceArray; } -FormulaStringNameToken::FormulaStringNameToken( StackVar eTypeP, svl::SharedString r ) : - FormulaToken( eTypeP ), maString(std::move( r )) +FormulaStringNameToken::FormulaStringNameToken( StackVar eTypeP, svl::SharedString r, + bool isOptional ) : + FormulaToken( eTypeP ), maString(std::move( r )), mIsOptional(isOptional) { } FormulaStringNameToken::FormulaStringNameToken( const FormulaStringNameToken& r ) : - FormulaToken( r ), maString( r.maString ) { + FormulaToken( r ), maString( r.maString ), mIsOptional(r.mIsOptional) { } FormulaToken* FormulaStringNameToken::Clone() const @@ -2122,19 +2004,11 @@ FormulaToken* FormulaStringNameToken::Clone() const return new FormulaStringNameToken(*this); } -const svl::SharedString& FormulaStringNameToken::GetString() const -{ - return maString; -} - -void FormulaStringNameToken::SetString( const svl::SharedString& rStr ) -{ - maString = rStr; -} - bool FormulaStringNameToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && maString == r.GetString(); + return FormulaToken::operator==( r ) + && maString == static_cast(r).GetString() + && mIsOptional == static_cast(r).GetIsOptional(); } sal_uInt16 FormulaIndexToken::GetIndex() const { return nIndex; } @@ -2143,13 +2017,17 @@ sal_Int16 FormulaIndexToken::GetSheet() const { return mnSheet; } void FormulaIndexToken::SetSheet( sal_Int16 n ) { mnSheet = n; } bool FormulaIndexToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && nIndex == r.GetIndex() && - mnSheet == r.GetSheet(); + return FormulaToken::operator==( r ) + && nIndex == static_cast(r).GetIndex() + && mnSheet == static_cast(r).GetSheet(); } const OUString& FormulaExternalToken::GetExternal() const { return aExternal; } bool FormulaExternalToken::operator==( const FormulaToken& r ) const { - return FormulaByteToken::operator==( r ) && aExternal == r.GetExternal(); + return FormulaToken::operator==( r ) + && mnByte == static_cast(r).mnByte + && eInForceArray == static_cast(r).eInForceArray + && aExternal == static_cast(r).GetExternal(); } @@ -2160,12 +2038,6 @@ bool FormulaErrorToken::operator==( const FormulaToken& r ) const return FormulaToken::operator==( r ) && nError == static_cast< const FormulaErrorToken & >(r).GetError(); } -double FormulaMissingToken::GetDouble() const { return 0.0; } - -const svl::SharedString & FormulaMissingToken::GetString() const -{ - return svl::SharedString::getEmptyString(); -} bool FormulaMissingToken::operator==( const FormulaToken& r ) const { diff --git a/formula/source/ui/dlg/ControlHelper.hxx b/formula/source/ui/dlg/ControlHelper.hxx index c0eb9e8034ae..d225d43ae510 100644 --- a/formula/source/ui/dlg/ControlHelper.hxx +++ b/formula/source/ui/dlg/ControlHelper.hxx @@ -19,7 +19,9 @@ #pragma once #include +#include #include +#include #include namespace formula @@ -53,15 +55,15 @@ private: class ArgInput final { private: - Link aFxClickLink; - Link aFxFocusLink; - Link aEdFocusLink; - Link aEdModifyLink; + Link m_aFxClickLink; + Link m_aFxFocusLink; + Link m_aEdFocusLink; + Link m_aEdModifyLink; - weld::Label*pFtArg; - weld::Button* pBtnFx; - ArgEdit* pEdArg; - RefButton* pRefBtn; + weld::Label* m_pFtArg; + weld::Button* m_pBtnFx; + ArgEdit* m_pEdArg; + RefButton* m_pRefBtn; DECL_LINK( FxBtnClickHdl, weld::Button&, void ); DECL_LINK( FxBtnFocusHdl, weld::Widget&, void ); @@ -72,10 +74,8 @@ public: ArgInput(); - void InitArgInput(weld::Label* pftArg, - weld::Button* pbtnFx, - ArgEdit* pedArg, - RefButton* prefBtn); + void InitArgInput(weld::Label& rArgLabel, weld::Button& rFxButton, ArgEdit& rArgEdit, + RefButton& rRefButton); void SetArgName(const OUString &aArg); OUString GetArgName() const; @@ -86,16 +86,15 @@ public: void SelectAll(); - ArgEdit* GetArgEdPtr() { return pEdArg; } + ArgEdit* GetArgEdPtr() { return m_pEdArg; } + void SetFxClickHdl(const Link& rLink) { m_aFxClickLink = rLink; } - void SetFxClickHdl( const Link& rLink ) { aFxClickLink = rLink; } + void SetFxFocusHdl(const Link& rLink) { m_aFxFocusLink = rLink; } - void SetFxFocusHdl( const Link& rLink ) { aFxFocusLink = rLink; } + void SetEdFocusHdl(const Link& rLink) { m_aEdFocusLink = rLink; } - void SetEdFocusHdl( const Link& rLink ) { aEdFocusLink = rLink; } - - void SetEdModifyHdl( const Link& rLink ) { aEdModifyLink = rLink; } + void SetEdModifyHdl(const Link& rLink) { m_aEdModifyLink = rLink; } void Hide(); void Show(); diff --git a/formula/source/ui/dlg/formula.cxx b/formula/source/ui/dlg/formula.cxx index c569de51832b..cca69f8c33bd 100644 --- a/formula/source/ui/dlg/formula.cxx +++ b/formula/source/ui/dlg/formula.cxx @@ -20,10 +20,10 @@ #include #include #include +#include #include #include #include -#include #include @@ -119,7 +119,7 @@ public: DECL_LINK( FxHdl, ParaWin&, void ); DECL_LINK( MatrixHdl, weld::Toggleable&, void ); - DECL_LINK( FormulaHdl, weld::TextView&, void); + DECL_LINK(FormulaHdl, weld::TextWidget&, void); DECL_LINK( FormulaCursorHdl, weld::TextWidget&, void); DECL_LINK( BtnHdl, weld::Button&, void ); DECL_LINK( FavToggleHdl, weld::Button&, void ); @@ -205,7 +205,7 @@ public: bool _bSupportMatrix, IFormulaEditorHelper* _pHelper, const IFunctionManager* _pFunctionMgr, - IControlReferenceHandler* _pDlg); + IControlReferenceHandler& rDlg); ~FormulaDlg_Impl(); }; @@ -216,7 +216,7 @@ FormulaDlg_Impl::FormulaDlg_Impl(weld::Dialog& rDialog, bool _bSupportMatrix, IFormulaEditorHelper* _pHelper, const IFunctionManager* _pFunctionMgr, - IControlReferenceHandler* _pDlg) + IControlReferenceHandler& rDlg) : m_pHelper(_pHelper) , m_rDialog(rDialog) , m_bUserMatrixFlag(false) @@ -269,10 +269,10 @@ FormulaDlg_Impl::FormulaDlg_Impl(weld::Dialog& rDialog, m_xMEdit->set_size_request(nWidth, m_xMEdit->get_height_rows(5)); - m_xEdRef->SetReferences(_pDlg, m_xFtEditName.get()); - m_xRefBtn->SetReferences(_pDlg, m_xEdRef.get()); + m_xEdRef->SetReferences(&rDlg, m_xFtEditName.get()); + m_xRefBtn->SetReferences(&rDlg, m_xEdRef.get()); - m_xParaWin.reset(new ParaWin(m_xParaWinBox.get(), _pDlg)); + m_xParaWin.reset(new ParaWin(m_xParaWinBox.get(), rDlg)); m_xParaWin->Show(); m_xParaWinBox->hide(); m_xFtEditName->hide(); @@ -599,7 +599,7 @@ void FormulaDlg_Impl::MakeTree(StructPage* _pTree, weld::TreeIter* pParent, cons OpCode eOp = _pToken->GetOpCode(); // #i101512# for output, the original token is needed - const FormulaToken* pOrigToken = (_pToken->GetType() == svFAP) ? _pToken->GetFAPOrigToken() : _pToken; + const FormulaToken* pOrigToken = (_pToken->GetType() == svFAP) ? static_cast(_pToken)->GetFAPOrigToken() : _pToken; ::std::map::const_iterator itr = m_aTokenMap.find(pOrigToken); if (itr == m_aTokenMap.end()) return; @@ -630,8 +630,8 @@ void FormulaDlg_Impl::MakeTree(StructPage* _pTree, weld::TreeIter* pParent, cons { _pTree->InsertEntry(aResult, pParent, StructType::Error, 0, _pToken, *xEntry); } - else if (!((SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP) || - (SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP))) + else if (!((ocStartBinaryOperators <= eOp && eOp < ocStopBinaryOperators) || + (ocStartUnaryOperators <= eOp && eOp < ocStopUnaryOperators))) { // Not a binary or unary operator. bCalcSubformula = true; @@ -1325,7 +1325,7 @@ IMPL_LINK( FormulaDlg_Impl, ModifyHdl, ParaWin&, rPtr, void ) } } -IMPL_LINK_NOARG( FormulaDlg_Impl, FormulaHdl, weld::TextView&, void) +IMPL_LINK_NOARG(FormulaDlg_Impl, FormulaHdl, weld::TextWidget&, void) { FormEditData* pData = m_pHelper->getFormEditData(); @@ -1542,7 +1542,7 @@ void FormulaDlg_Impl::UpdateSelection() aOrigSelection = m_pTheRefEdit->GetSelection(); } - // because its initially hidden, give it its optimal size so clicking the + // because it is initially hidden, give it its optimal size so clicking the // refbutton has an initial size to work when retro-fitting this to .ui m_xEdRef->GetWidget()->set_size_request(m_xEdRef->GetWidget()->get_preferred_size().Width(), -1); m_xEdRef->GetWidget()->show(); @@ -1789,11 +1789,11 @@ void FormulaDlg_Impl::SetEdSelection() FormulaModalDialog::FormulaModalDialog(weld::Window* pParent, IFunctionManager const * _pFunctionMgr, - IControlReferenceHandler* _pDlg) + IControlReferenceHandler& rDlg) : GenericDialogController(pParent, u"formula/ui/formuladialog.ui"_ustr, u"FormulaDialog"_ustr) , m_pImpl(new FormulaDlg_Impl(*m_xDialog, *m_xBuilder, false/*_bSupportFunctionResult*/, false/*_bSupportResult*/, false/*_bSupportMatrix*/, - this, _pFunctionMgr, _pDlg)) + this, _pFunctionMgr, rDlg)) { m_xDialog->set_title(m_pImpl->m_aTitle1); } @@ -1843,12 +1843,12 @@ void FormulaModalDialog::StoreFormEditData(FormEditData* pData) // Initialisation / General functions for Dialog FormulaDlg::FormulaDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, - IFunctionManager const * _pFunctionMgr, IControlReferenceHandler* _pDlg) + IFunctionManager const * _pFunctionMgr, IControlReferenceHandler& rDlg) : SfxModelessDialogController( pB, pCW, pParent, u"formula/ui/formuladialog.ui"_ustr, u"FormulaDialog"_ustr) , m_pImpl(new FormulaDlg_Impl(*m_xDialog, *m_xBuilder, true/*_bSupportFunctionResult*/ , true/*_bSupportResult*/ , true/*_bSupportMatrix*/ - , this, _pFunctionMgr, _pDlg)) + , this, _pFunctionMgr, rDlg)) { m_xDialog->set_title(m_pImpl->m_aTitle1); } diff --git a/formula/source/ui/dlg/funcpage.cxx b/formula/source/ui/dlg/funcpage.cxx index 99ece328c631..f78ce77aecf9 100644 --- a/formula/source/ui/dlg/funcpage.cxx +++ b/formula/source/ui/dlg/funcpage.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "funcpage.hxx" @@ -323,7 +324,7 @@ IMPL_LINK_NOARG(FuncPage, DblClkHdl, const weld::TreeIter&, bool) return true; } -IMPL_LINK_NOARG(FuncPage, ModifyHdl, weld::Entry&, void) +IMPL_LINK_NOARG(FuncPage, ModifyHdl, weld::TextWidget&, void) { if (m_xLbCategory->get_active() == LRU_CATEGORY || m_xLbCategory->get_active() == FAVOURITES_CATEGORY) diff --git a/formula/source/ui/dlg/funcpage.hxx b/formula/source/ui/dlg/funcpage.hxx index 8991bd16a040..a2925241caac 100644 --- a/formula/source/ui/dlg/funcpage.hxx +++ b/formula/source/ui/dlg/funcpage.hxx @@ -20,10 +20,13 @@ #pragma once #include +#include +#include #include +#include #include #include -#include + #include #include #include @@ -72,7 +75,7 @@ private: DECL_LINK(SelTreeViewHdl, weld::ItemView&, void); DECL_LINK(DblClkHdl, const weld::TreeIter&, bool); DECL_LINK(KeyInputHdl, const KeyEvent&, bool); - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); DECL_LINK(SelHelpClickHdl, weld::Button&, void); DECL_LINK(SimilarityToggleHdl, weld::Toggleable&, void); diff --git a/formula/source/ui/dlg/funcutl.cxx b/formula/source/ui/dlg/funcutl.cxx index fa602258dfb4..d39ece8b9946 100644 --- a/formula/source/ui/dlg/funcutl.cxx +++ b/formula/source/ui/dlg/funcutl.cxx @@ -130,135 +130,130 @@ bool ArgEdit::KeyInput(const KeyEvent& rKEvt) ArgInput::ArgInput() { - pFtArg=nullptr; - pBtnFx=nullptr; - pEdArg=nullptr; - pRefBtn=nullptr; + m_pFtArg = nullptr; + m_pBtnFx = nullptr; + m_pEdArg = nullptr; + m_pRefBtn = nullptr; } -void ArgInput::InitArgInput(weld::Label* pftArg, weld::Button* pbtnFx, - ArgEdit* pedArg, RefButton* prefBtn) +void ArgInput::InitArgInput(weld::Label& rArgLabel, weld::Button& rFxButton, ArgEdit& rArgEdit, + RefButton& rRefButton) { - pFtArg =pftArg; - pBtnFx =pbtnFx; - pEdArg =pedArg; - pRefBtn=prefBtn; + m_pFtArg = &rArgLabel; + m_pBtnFx = &rFxButton; + m_pEdArg = &rArgEdit; + m_pRefBtn = &rRefButton; - if(pBtnFx!=nullptr) - { - pBtnFx->connect_clicked( LINK( this, ArgInput, FxBtnClickHdl ) ); - pBtnFx->connect_focus_in( LINK( this, ArgInput, FxBtnFocusHdl ) ); - } - if(pEdArg!=nullptr) - { - pEdArg->SetGetFocusHdl ( LINK( this, ArgInput, EdFocusHdl ) ); - pEdArg->SetModifyHdl ( LINK( this, ArgInput, EdModifyHdl ) ); - } + m_pBtnFx->connect_clicked(LINK(this, ArgInput, FxBtnClickHdl)); + m_pBtnFx->connect_focus_in(LINK(this, ArgInput, FxBtnFocusHdl)); + + m_pEdArg->SetGetFocusHdl(LINK(this, ArgInput, EdFocusHdl)); + m_pEdArg->SetModifyHdl(LINK(this, ArgInput, EdModifyHdl)); } // Sets the Name for the Argument void ArgInput::SetArgName(const OUString &aArg) { - if (pFtArg) - pFtArg->set_label(aArg ); + if (m_pFtArg) + m_pFtArg->set_label(aArg); } // Returns the Name for the Argument OUString ArgInput::GetArgName() const { OUString aPrivArgName; - if (pFtArg) - aPrivArgName = pFtArg->get_label(); + if (m_pFtArg) + aPrivArgName = m_pFtArg->get_label(); return aPrivArgName; } //Sets the Name for the Argument void ArgInput::SetArgNameFont(const vcl::Font &aFont) { - if (pFtArg) - pFtArg->set_font(aFont); + if (m_pFtArg) + m_pFtArg->set_font(aFont); } //Sets up the Selection for the EditBox. void ArgInput::SelectAll() { - if (pEdArg) - pEdArg->SelectAll(); + if (m_pEdArg) + m_pEdArg->SelectAll(); } //Sets the Value for the Argument void ArgInput::SetArgVal(const OUString &rVal) { - if (pEdArg) - pEdArg->SetRefString(rVal); + if (m_pEdArg) + m_pEdArg->SetRefString(rVal); } //Returns the Value for the Argument OUString ArgInput::GetArgVal() const { OUString aResult; - if (pEdArg) - aResult=pEdArg->GetText(); + if (m_pEdArg) + aResult = m_pEdArg->GetText(); return aResult; } //Hides the Controls void ArgInput::Hide() { - if (pFtArg && pBtnFx && pEdArg && pRefBtn) + if (m_pFtArg && m_pBtnFx && m_pEdArg && m_pRefBtn) { - pFtArg->hide(); - pBtnFx->hide(); - pEdArg->GetWidget()->hide(); - pRefBtn->GetWidget()->hide(); + m_pFtArg->hide(); + m_pBtnFx->hide(); + m_pEdArg->GetWidget()->hide(); + m_pRefBtn->GetWidget()->hide(); } } -//Casts the Controls again. +//Shows the Controls again. void ArgInput::Show() { - if (pFtArg && pBtnFx && pEdArg && pRefBtn) + if (m_pFtArg && m_pBtnFx && m_pEdArg && m_pRefBtn) { - pFtArg->show(); - pBtnFx->show(); - pEdArg->GetWidget()->show(); - pRefBtn->GetWidget()->show(); + m_pFtArg->show(); + m_pBtnFx->show(); + m_pEdArg->GetWidget()->show(); + m_pRefBtn->GetWidget()->show(); } } void ArgInput::UpdateAccessibleNames() { - OUString aArgName = ":" + pFtArg->get_label(); + OUString aArgName = ":" + m_pFtArg->get_label(); - OUString aName = pBtnFx->get_tooltip_text() + aArgName; - pBtnFx->set_accessible_name(aName); + OUString aName = m_pBtnFx->get_tooltip_text() + aArgName; + m_pBtnFx->set_accessible_name(aName); - aName = pRefBtn->GetWidget()->get_tooltip_text() + aArgName; - pRefBtn->GetWidget()->set_accessible_name(aName); + aName = m_pRefBtn->GetWidget()->get_tooltip_text() + aArgName; + m_pRefBtn->GetWidget()->set_accessible_name(aName); } IMPL_LINK(ArgInput, FxBtnClickHdl, weld::Button&, rBtn, void) { - if (&rBtn == pBtnFx) - aFxClickLink.Call(*this); + if (&rBtn == m_pBtnFx) + m_aFxClickLink.Call(*this); } IMPL_LINK( ArgInput, FxBtnFocusHdl, weld::Widget&, rControl, void ) { - if (&rControl == pBtnFx) - aFxFocusLink.Call(*this); + if (&rControl == m_pBtnFx) + m_aFxFocusLink.Call(*this); } IMPL_LINK( ArgInput, EdFocusHdl, RefEdit&, rControl, void ) { - if (&rControl == pEdArg) - aEdFocusLink.Call(*this); + if (&rControl == m_pEdArg) + m_aEdFocusLink.Call(*this); } IMPL_LINK( ArgInput, EdModifyHdl, RefEdit&, rEdit, void ) { - if (&rEdit == pEdArg) - aEdModifyLink.Call(*this); + if (&rEdit == m_pEdArg) + m_aEdModifyLink.Call(*this); } RefEdit::RefEdit(std::unique_ptr xControl) @@ -337,6 +332,15 @@ void RefEdit::SetReferences(IControlReferenceHandler* pDlg, weld::Frame* pFrame) maGetLabelTextForShrinkModeFunc = [pFrame] { return pFrame->get_label(); }; } +Selection RefEdit::GetSelection() const +{ + int nStartPos, nEndPos; + if (mxEntry->get_selection_bounds(nStartPos, nEndPos)) + return Selection(nStartPos, nEndPos); + + return Selection(); +} + OUString RefEdit::GetLabelTextForShrinkMode() { if (maGetLabelTextForShrinkModeFunc) @@ -345,7 +349,7 @@ OUString RefEdit::GetLabelTextForShrinkMode() return OUString(); } -IMPL_LINK_NOARG(RefEdit, Modify, weld::Entry&, void) +IMPL_LINK_NOARG(RefEdit, Modify, weld::TextWidget&, void) { maModifyHdl.Call(*this); if (mpAnyRefDlg) diff --git a/formula/source/ui/dlg/parawin.cxx b/formula/source/ui/dlg/parawin.cxx index a2094702160a..6939be710db3 100644 --- a/formula/source/ui/dlg/parawin.cxx +++ b/formula/source/ui/dlg/parawin.cxx @@ -37,9 +37,9 @@ namespace formula constexpr sal_uInt16 kMaxArgCount = 255; constexpr sal_uInt16 kMaxArgOffset = kMaxArgCount - 1; -ParaWin::ParaWin(weld::Container* pParent,IControlReferenceHandler* _pDlg) - : pFuncDesc(nullptr) - , pMyParent(_pDlg) +ParaWin::ParaWin(weld::Container* pParent, IControlReferenceHandler& rDlg) + : m_pFuncDesc(nullptr) + , m_rMyParent(rDlg) , m_sOptional(ForResId(STR_OPTIONAL)) , m_sRequired(ForResId(STR_REQUIRED)) , m_xBuilder(Application::CreateBuilder(pParent, u"formula/ui/parameter.ui"_ustr)) @@ -88,9 +88,9 @@ ParaWin::ParaWin(weld::Container* pParent,IControlReferenceHandler* _pDlg) Size aSize(m_xContainer->get_preferred_size()); m_xContainer->set_size_request(aSize.Width(), aSize.Height()); - aDefaultString = m_xFtEditDesc->get_label(); - nEdFocus = NOT_FOUND; - nActiveLine = 0; + m_aDefaultString = m_xFtEditDesc->get_label(); + m_nEdFocus = NOT_FOUND; + m_nActiveLine = 0; m_xSlider->connect_vadjustment_value_changed(LINK(this, ParaWin, ScrollHdl)); @@ -106,10 +106,10 @@ void ParaWin::UpdateArgDesc( sal_uInt16 nArg ) if (nArg == NOT_FOUND) return; - if (nMaxArgs > 4) + if (m_nMaxArgs > 4) nArg = sal::static_int_cast( nArg + GetSliderPos() ); - if ((nMaxArgs <= 0) || (nArg >= nMaxArgs)) + if ((m_nMaxArgs <= 0) || (nArg >= m_nMaxArgs)) return; OUString aArgDesc; @@ -118,45 +118,57 @@ void ParaWin::UpdateArgDesc( sal_uInt16 nArg ) SetArgumentDesc( OUString() ); SetArgumentText( OUString() ); - if ( nArgs < VAR_ARGS ) + if (m_nArgs < VAR_ARGS) { - sal_uInt16 nRealArg = (nArg < aVisibleArgMapping.size()) ? aVisibleArgMapping[nArg] : nArg; - aArgDesc = pFuncDesc->getParameterDescription(nRealArg); - aArgName = pFuncDesc->getParameterName(nRealArg) + " " + - ((pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired); + sal_uInt16 nRealArg + = (nArg < m_aVisibleArgMapping.size()) ? m_aVisibleArgMapping[nArg] : nArg; + aArgDesc = m_pFuncDesc->getParameterDescription(nRealArg); + aArgName = m_pFuncDesc->getParameterName(nRealArg) + " " + + ((m_pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired); } - else if ( nArgs < PAIRED_VAR_ARGS ) + else if (m_nArgs < PAIRED_VAR_ARGS) { - sal_uInt16 nFix = nArgs - VAR_ARGS; + sal_uInt16 nFix = m_nArgs - VAR_ARGS; sal_uInt16 nPos = std::min( nArg, nFix ); - sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ? - aVisibleArgMapping[nPos] : aVisibleArgMapping.back()); - aArgDesc = pFuncDesc->getParameterDescription(nRealArg); - aArgName = pFuncDesc->getParameterName(nRealArg); - sal_uInt16 nVarArgsStart = pFuncDesc->getVarArgsStart(); + sal_uInt16 nRealArg = (nPos < m_aVisibleArgMapping.size() ? m_aVisibleArgMapping[nPos] + : m_aVisibleArgMapping.back()); + aArgDesc = m_pFuncDesc->getParameterDescription(nRealArg); + aArgName = m_pFuncDesc->getParameterName(nRealArg); + sal_uInt16 nVarArgsStart = m_pFuncDesc->getVarArgsStart(); if ( nArg >= nVarArgsStart ) - aArgName += OUString::number( nArg-nVarArgsStart+1 ); - aArgName += " " + ((nArg > nFix || pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired) ; + { + OUString aFuncName = m_pFuncDesc->getFunctionName(); + sal_Int16 nShifted = (aFuncName.equalsIgnoreAsciiCase(u"LAMBDA") || + aFuncName.equalsIgnoreAsciiCase(u"MAP")) ? nPos : 0; + aArgName += OUString::number( nArg-nVarArgsStart + 1 + nShifted ); + } + aArgName += " " + + ((nArg > nFix || m_pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional + : m_sRequired); } else { - sal_uInt16 nFix = nArgs - PAIRED_VAR_ARGS; + sal_uInt16 nFix = m_nArgs - PAIRED_VAR_ARGS; sal_uInt16 nPos; if ( nArg < nFix ) nPos = nArg; else nPos = nFix + ( (nArg-nFix) % 2); - sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ? - aVisibleArgMapping[nPos] : aVisibleArgMapping.back()); - aArgDesc = pFuncDesc->getParameterDescription(nRealArg); - aArgName = pFuncDesc->getParameterName(nRealArg); - sal_uInt16 nVarArgsStart = pFuncDesc->getVarArgsStart(); + sal_uInt16 nRealArg = (nPos < m_aVisibleArgMapping.size() ? m_aVisibleArgMapping[nPos] + : m_aVisibleArgMapping.back()); + aArgDesc = m_pFuncDesc->getParameterDescription(nRealArg); + aArgName = m_pFuncDesc->getParameterName(nRealArg); + sal_uInt16 nVarArgsStart = m_pFuncDesc->getVarArgsStart(); if ( nArg >= nVarArgsStart ) { - sal_Int16 nShifted = pFuncDesc->getFunctionName().equalsIgnoreAsciiCase(u"LET") ? nPos / 2 : 0; + sal_Int16 nShifted + = m_pFuncDesc->getFunctionName().equalsIgnoreAsciiCase(u"LET") ? nPos / 2 : 0; aArgName += OUString::number( (nArg-nVarArgsStart)/2 + 1 + nShifted ); } - aArgName += " " + ((nArg > (nFix+1) || pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired) ; + aArgName + += " " + + ((nArg > (nFix + 1) || m_pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional + : m_sRequired); } SetArgumentDesc(aArgDesc); @@ -169,61 +181,64 @@ void ParaWin::UpdateArgInput( sal_uInt16 nOffset, sal_uInt16 i ) if (nArg > kMaxArgOffset) return; - if ( nArgs < VAR_ARGS) + if (m_nArgs < VAR_ARGS) { - if (nArg < nMaxArgs) + if (nArg < m_nMaxArgs) { - sal_uInt16 nRealArg = aVisibleArgMapping[nArg]; - SetArgNameFont (i,(pFuncDesc->isParameterOptional(nRealArg)) - ? aFntLight : aFntBold ); - SetArgName (i,pFuncDesc->getParameterName(nRealArg)); + sal_uInt16 nRealArg = m_aVisibleArgMapping[nArg]; + SetArgNameFont(i, + (m_pFuncDesc->isParameterOptional(nRealArg)) ? m_aFntLight : m_aFntBold); + SetArgName(i, m_pFuncDesc->getParameterName(nRealArg)); } } - else if ( nArgs < PAIRED_VAR_ARGS) + else if (m_nArgs < PAIRED_VAR_ARGS) { - sal_uInt16 nFix = nArgs - VAR_ARGS; + sal_uInt16 nFix = m_nArgs - VAR_ARGS; sal_uInt16 nPos = std::min( nArg, nFix ); - sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ? - aVisibleArgMapping[nPos] : aVisibleArgMapping.back()); - SetArgNameFont( i, - (nArg > nFix || pFuncDesc->isParameterOptional(nRealArg)) ? - aFntLight : aFntBold ); - sal_uInt16 nVarArgsStart = pFuncDesc->getVarArgsStart(); + sal_uInt16 nRealArg = (nPos < m_aVisibleArgMapping.size() ? m_aVisibleArgMapping[nPos] + : m_aVisibleArgMapping.back()); + SetArgNameFont(i, (nArg > nFix || m_pFuncDesc->isParameterOptional(nRealArg)) ? m_aFntLight + : m_aFntBold); + sal_uInt16 nVarArgsStart = m_pFuncDesc->getVarArgsStart(); if ( nArg >= nVarArgsStart ) { - OUString aArgName = pFuncDesc->getParameterName(nRealArg) + - OUString::number(nArg-nVarArgsStart+1); + OUString aFuncName = m_pFuncDesc->getFunctionName(); + sal_Int16 nShifted = (aFuncName.equalsIgnoreAsciiCase(u"LAMBDA") || + aFuncName.equalsIgnoreAsciiCase(u"MAP")) ? nPos : 0; + OUString aArgName = m_pFuncDesc->getParameterName(nRealArg) + + OUString::number(nArg - nVarArgsStart + 1 + nShifted); SetArgName( i, aArgName ); } else - SetArgName( i, pFuncDesc->getParameterName(nRealArg) ); + SetArgName(i, m_pFuncDesc->getParameterName(nRealArg)); } else { - sal_uInt16 nFix = nArgs - PAIRED_VAR_ARGS; + sal_uInt16 nFix = m_nArgs - PAIRED_VAR_ARGS; sal_uInt16 nPos; if ( nArg < nFix ) nPos = nArg; else nPos = nFix + ( (nArg-nFix) % 2); - sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ? - aVisibleArgMapping[nPos] : aVisibleArgMapping.back()); - SetArgNameFont( i, - (nArg > (nFix+1) || pFuncDesc->isParameterOptional(nRealArg)) ? - aFntLight : aFntBold ); - sal_uInt16 nVarArgsStart = pFuncDesc->getVarArgsStart(); + sal_uInt16 nRealArg = (nPos < m_aVisibleArgMapping.size() ? m_aVisibleArgMapping[nPos] + : m_aVisibleArgMapping.back()); + SetArgNameFont(i, (nArg > (nFix + 1) || m_pFuncDesc->isParameterOptional(nRealArg)) + ? m_aFntLight + : m_aFntBold); + sal_uInt16 nVarArgsStart = m_pFuncDesc->getVarArgsStart(); if ( nArg >= nVarArgsStart ) { - sal_Int16 nShifted = pFuncDesc->getFunctionName().equalsIgnoreAsciiCase(u"LET") ? nPos / 2 : 0; - OUString aArgName = pFuncDesc->getParameterName(nRealArg) + - OUString::number( (nArg-nVarArgsStart)/2 + 1 + nShifted); + sal_Int16 nShifted + = m_pFuncDesc->getFunctionName().equalsIgnoreAsciiCase(u"LET") ? nPos / 2 : 0; + OUString aArgName = m_pFuncDesc->getParameterName(nRealArg) + + OUString::number((nArg - nVarArgsStart) / 2 + 1 + nShifted); SetArgName( i, aArgName ); } else - SetArgName( i, pFuncDesc->getParameterName(nRealArg) ); + SetArgName(i, m_pFuncDesc->getParameterName(nRealArg)); } - if (nArg < nMaxArgs) - aArgInput[i].SetArgVal(aParaArray[nArg]); + if (nArg < m_nMaxArgs) + m_aArgInput[i].SetArgVal(m_aParaArray[nArg]); } ParaWin::~ParaWin() @@ -239,27 +254,27 @@ ParaWin::~ParaWin() void ParaWin::SetActiveLine(sal_uInt16 no) { - if (no >= nMaxArgs) + if (no >= m_nMaxArgs) return; tools::Long nOffset = GetSliderPos(); - nActiveLine=no; - tools::Long nNewEdPos=static_cast(nActiveLine)-nOffset; + m_nActiveLine = no; + tools::Long nNewEdPos = static_cast(m_nActiveLine) - nOffset; if(nNewEdPos<0 || nNewEdPos>3) { nOffset+=nNewEdPos; SetSliderPos(static_cast(nOffset)); nOffset=GetSliderPos(); } - nEdFocus=no-static_cast(nOffset); - UpdateArgDesc( nEdFocus ); + m_nEdFocus = no - static_cast(nOffset); + UpdateArgDesc(m_nEdFocus); } RefEdit* ParaWin::GetActiveEdit() { - if (nMaxArgs > 0 && nEdFocus != NOT_FOUND) + if (m_nMaxArgs > 0 && m_nEdFocus != NOT_FOUND) { - return aArgInput[nEdFocus].GetArgEdPtr(); + return m_aArgInput[m_nEdFocus].GetArgEdPtr(); } else { @@ -271,10 +286,10 @@ RefEdit* ParaWin::GetActiveEdit() OUString ParaWin::GetArgument(sal_uInt16 no) { OUString aStr; - if(no 0 && nEdFocus != NOT_FOUND) + if (m_nMaxArgs > 0 && m_nEdFocus != NOT_FOUND) { - aStr=aArgInput[nEdFocus].GetArgName(); + aStr = m_aArgInput[m_nEdFocus].GetArgName(); } return aStr; } @@ -293,42 +308,42 @@ OUString ParaWin::GetActiveArgName() const void ParaWin::SetArgument(sal_uInt16 no, std::u16string_view aString) { - if (no < aParaArray.size()) - aParaArray[no] = comphelper::string::stripStart(aString, ' '); + if (no < m_aParaArray.size()) + m_aParaArray[no] = comphelper::string::stripStart(aString, ' '); } void ParaWin::SetArgumentFonts(const vcl::Font&aBoldFont,const vcl::Font&aLightFont) { - aFntBold=aBoldFont; - aFntLight=aLightFont; + m_aFntBold = aBoldFont; + m_aFntLight = aLightFont; } void ParaWin::SetFunctionDesc(const IFunctionDescription* pFDesc) { - pFuncDesc=pFDesc; + m_pFuncDesc = pFDesc; SetArgumentDesc( OUString() ); SetArgumentText( OUString() ); SetEditDesc( OUString() ); - nMaxArgs = nArgs = 0; - if ( pFuncDesc!=nullptr) + m_nMaxArgs = m_nArgs = 0; + if (m_pFuncDesc != nullptr) { - if ( !pFuncDesc->getDescription().isEmpty() ) + if (!m_pFuncDesc->getDescription().isEmpty()) { - SetEditDesc(pFuncDesc->getDescription()); + SetEditDesc(m_pFuncDesc->getDescription()); } else { - SetEditDesc(aDefaultString); + SetEditDesc(m_aDefaultString); } - nArgs = pFuncDesc->getSuppressedArgumentCount(); - nMaxArgs = std::min( nArgs, kMaxArgCount); - if (sal_uInt16 nVarArgsLimit = pFuncDesc->getVarArgsLimit()) - nMaxArgs = std::min( nVarArgsLimit, nMaxArgs); - pFuncDesc->fillVisibleArgumentMapping(aVisibleArgMapping); + m_nArgs = m_pFuncDesc->getSuppressedArgumentCount(); + m_nMaxArgs = std::min(m_nArgs, kMaxArgCount); + if (sal_uInt16 nVarArgsLimit = m_pFuncDesc->getVarArgsLimit()) + m_nMaxArgs = std::min(nVarArgsLimit, m_nMaxArgs); + m_pFuncDesc->fillVisibleArgumentMapping(m_aVisibleArgMapping); m_xSlider->set_vpolicy(VclPolicyType::NEVER); m_xSlider->set_size_request(-1, -1); - OUString sHelpId = pFuncDesc->getHelpId(); + OUString sHelpId = m_pFuncDesc->getHelpId(); m_xContainer->set_help_id(sHelpId); m_xEdArg1->GetWidget()->set_help_id(sHelpId); m_xEdArg2->GetWidget()->set_help_id(sHelpId); @@ -339,7 +354,7 @@ void ParaWin::SetFunctionDesc(const IFunctionDescription* pFDesc) } else { - nActiveLine=0; + m_nActiveLine = 0; } } @@ -361,38 +376,37 @@ void ParaWin::SetEditDesc(const OUString& aText) void ParaWin::SetArgName(sal_uInt16 no,const OUString& aText) { - aArgInput[no].SetArgName(aText); - aArgInput[no].UpdateAccessibleNames(); + m_aArgInput[no].SetArgName(aText); + m_aArgInput[no].UpdateAccessibleNames(); } void ParaWin::SetArgNameFont(sal_uInt16 no,const vcl::Font& aFont) { - aArgInput[no].SetArgNameFont(aFont); + m_aArgInput[no].SetArgNameFont(aFont); } void ParaWin::SetEdFocus() { UpdateArgDesc(0); - if(!aParaArray.empty()) - aArgInput[0].GetArgEdPtr()->GrabFocus(); + if (!m_aParaArray.empty()) + m_aArgInput[0].GetArgEdPtr()->GrabFocus(); } void ParaWin::InitArgInput(sal_uInt16 nPos, weld::Label& rFtArg, weld::Button& rBtnFx, ArgEdit& rEdArg, RefButton& rRefBtn) { + rRefBtn.SetReferences(&m_rMyParent, &rEdArg); + rEdArg.SetReferences(&m_rMyParent, &rFtArg); - rRefBtn.SetReferences(pMyParent, &rEdArg); - rEdArg.SetReferences(pMyParent, &rFtArg); + m_aArgInput[nPos].InitArgInput(rFtArg, rBtnFx, rEdArg, rRefBtn); - aArgInput[nPos].InitArgInput (&rFtArg,&rBtnFx,&rEdArg,&rRefBtn); + m_aArgInput[nPos].Hide(); - aArgInput[nPos].Hide(); - - aArgInput[nPos].SetFxClickHdl ( LINK( this, ParaWin, GetFxHdl ) ); - aArgInput[nPos].SetFxFocusHdl ( LINK( this, ParaWin, GetFxFocusHdl ) ); - aArgInput[nPos].SetEdFocusHdl ( LINK( this, ParaWin, GetEdFocusHdl ) ); - aArgInput[nPos].SetEdModifyHdl ( LINK( this, ParaWin, ModifyHdl ) ); - aArgInput[nPos].UpdateAccessibleNames(); + m_aArgInput[nPos].SetFxClickHdl(LINK(this, ParaWin, GetFxHdl)); + m_aArgInput[nPos].SetFxFocusHdl(LINK(this, ParaWin, GetFxFocusHdl)); + m_aArgInput[nPos].SetEdFocusHdl(LINK(this, ParaWin, GetEdFocusHdl)); + m_aArgInput[nPos].SetEdModifyHdl(LINK(this, ParaWin, ModifyHdl)); + m_aArgInput[nPos].UpdateAccessibleNames(); } void ParaWin::ClearAll() @@ -403,33 +417,33 @@ void ParaWin::ClearAll() void ParaWin::SetArgumentOffset(sal_uInt16 nOffset) { - aParaArray.clear(); + m_aParaArray.clear(); m_xSlider->vadjustment_set_value(0); - aParaArray.resize(nMaxArgs); + m_aParaArray.resize(m_nMaxArgs); - if (nMaxArgs > 0) + if (m_nMaxArgs > 0) { - for ( int i=0; i<4 && iInit( - (i==0) ? nullptr : aArgInput[i-1].GetArgEdPtr(), - (i==3 || i==nMaxArgs-1) ? nullptr : aArgInput[i+1].GetArgEdPtr(), - *m_xSlider, *this, nMaxArgs ); + m_aArgInput[i].SetArgVal(OUString()); + m_aArgInput[i].GetArgEdPtr()->Init( + (i == 0) ? nullptr : m_aArgInput[i - 1].GetArgEdPtr(), + (i == 3 || i == m_nMaxArgs - 1) ? nullptr : m_aArgInput[i + 1].GetArgEdPtr(), + *m_xSlider, *this, m_nMaxArgs); } } UpdateParas(); - if (nMaxArgs < 5) + if (m_nMaxArgs < 5) { m_xSlider->set_vpolicy(VclPolicyType::NEVER); m_xSlider->set_size_request(-1, -1); } else { - m_xSlider->vadjustment_configure(nOffset, nMaxArgs, 1, 4, 4); + m_xSlider->vadjustment_configure(nOffset, m_nMaxArgs, 1, 4, 4); m_xSlider->set_vpolicy(VclPolicyType::ALWAYS); Size aPrefSize(m_xGrid->get_preferred_size()); m_xSlider->set_size_request(aPrefSize.Width(), aPrefSize.Height()); @@ -441,17 +455,17 @@ void ParaWin::UpdateParas() sal_uInt16 i; sal_uInt16 nOffset = GetSliderPos(); - if ( nMaxArgs > 0 ) + if (m_nMaxArgs > 0) { - for ( i=0; (i= aParaArray.size() " << aParaArray.size() << - " with nEdFocus " << nEdFocus << - " and aArgInput[nEdFocus].GetArgVal() '" << aArgInput[nEdFocus].GetArgVal() << "'"); + SAL_WARN("formula.ui", "ParaWin::ModifyHdl - shot in foot: nPara " + << nPara << " >= aParaArray.size() " << m_aParaArray.size() + << " with nEdFocus " << m_nEdFocus + << " and aArgInput[nEdFocus].GetArgVal() '" + << m_aArgInput[m_nEdFocus].GetArgVal() << "'"); } - UpdateArgDesc( nEdFocus); - nActiveLine = static_cast(nPara); + UpdateArgDesc(m_nEdFocus); + m_nActiveLine = static_cast(nPara); } ArgumentModified(); diff --git a/formula/source/ui/dlg/parawin.hxx b/formula/source/ui/dlg/parawin.hxx index 58076a19c60d..afba5d9ccd2b 100644 --- a/formula/source/ui/dlg/parawin.hxx +++ b/formula/source/ui/dlg/parawin.hxx @@ -22,14 +22,16 @@ #include #include #include +#include +#include +#include #include -#include + #include "ControlHelper.hxx" #include namespace formula { - #define NOT_FOUND 0xffff class IFunctionDescription; @@ -38,111 +40,111 @@ class IControlReferenceHandler; class ParaWin { private: - Link aFxLink; - Link aArgModifiedLink; + Link m_aFxLink; + Link m_aArgModifiedLink; - ::std::vector aVisibleArgMapping; - const IFunctionDescription* pFuncDesc; - IControlReferenceHandler* pMyParent; - sal_uInt16 nArgs; // unsuppressed arguments, may be >= VAR_ARGS to indicate repeating parameters - sal_uInt16 nMaxArgs; // max arguments, limited to supported number of arguments - vcl::Font aFntBold; - vcl::Font aFntLight; + ::std::vector m_aVisibleArgMapping; + const IFunctionDescription* m_pFuncDesc; + IControlReferenceHandler& m_rMyParent; + // unsuppressed arguments, may be >= VAR_ARGS to indicate repeating parameters + sal_uInt16 m_nArgs; + // max arguments, limited to supported number of arguments + sal_uInt16 m_nMaxArgs; + vcl::Font m_aFntBold; + vcl::Font m_aFntLight; - OUString m_sOptional; - OUString m_sRequired; + OUString m_sOptional; + OUString m_sRequired; - sal_uInt16 nEdFocus; - sal_uInt16 nActiveLine; + sal_uInt16 m_nEdFocus; + sal_uInt16 m_nActiveLine; - ArgInput aArgInput[4]; - OUString aDefaultString; - ::std::vector aParaArray; + ArgInput m_aArgInput[4]; + OUString m_aDefaultString; + ::std::vector m_aParaArray; - std::unique_ptr m_xBuilder; - std::unique_ptr m_xContainer; + std::unique_ptr m_xBuilder; + std::unique_ptr m_xContainer; - std::unique_ptr m_xSlider; - std::unique_ptr m_xParamGrid; - std::unique_ptr m_xGrid; + std::unique_ptr m_xSlider; + std::unique_ptr m_xParamGrid; + std::unique_ptr m_xGrid; - std::unique_ptr m_xFtEditDesc; - std::unique_ptr m_xFtArgName; - std::unique_ptr m_xFtArgDesc; + std::unique_ptr m_xFtEditDesc; + std::unique_ptr m_xFtArgName; + std::unique_ptr m_xFtArgDesc; - std::unique_ptr m_xBtnFx1; - std::unique_ptr m_xBtnFx2; - std::unique_ptr m_xBtnFx3; - std::unique_ptr m_xBtnFx4; + std::unique_ptr m_xBtnFx1; + std::unique_ptr m_xBtnFx2; + std::unique_ptr m_xBtnFx3; + std::unique_ptr m_xBtnFx4; - std::unique_ptr m_xFtArg1; - std::unique_ptr m_xFtArg2; - std::unique_ptr m_xFtArg3; - std::unique_ptr m_xFtArg4; + std::unique_ptr m_xFtArg1; + std::unique_ptr m_xFtArg2; + std::unique_ptr m_xFtArg3; + std::unique_ptr m_xFtArg4; - std::unique_ptr m_xEdArg1; - std::unique_ptr m_xEdArg2; - std::unique_ptr m_xEdArg3; - std::unique_ptr m_xEdArg4; + std::unique_ptr m_xEdArg1; + std::unique_ptr m_xEdArg2; + std::unique_ptr m_xEdArg3; + std::unique_ptr m_xEdArg4; - std::unique_ptr m_xRefBtn1; - std::unique_ptr m_xRefBtn2; - std::unique_ptr m_xRefBtn3; - std::unique_ptr m_xRefBtn4; + std::unique_ptr m_xRefBtn1; + std::unique_ptr m_xRefBtn2; + std::unique_ptr m_xRefBtn3; + std::unique_ptr m_xRefBtn4; - DECL_LINK( ScrollHdl, weld::ScrolledWindow&, void); - DECL_LINK( ModifyHdl, ArgInput&, void ); - DECL_LINK( GetEdFocusHdl, ArgInput&, void ); - DECL_LINK( GetFxFocusHdl, ArgInput&, void ); - DECL_LINK( GetFxHdl, ArgInput&, void ); + DECL_LINK(ScrollHdl, weld::ScrolledWindow&, void); + DECL_LINK(ModifyHdl, ArgInput&, void); + DECL_LINK(GetEdFocusHdl, ArgInput&, void); + DECL_LINK(GetFxFocusHdl, ArgInput&, void); + DECL_LINK(GetFxHdl, ArgInput&, void); - void ArgumentModified(); + void ArgumentModified(); - void InitArgInput(sal_uInt16 nPos, weld::Label& rFtArg, weld::Button& rBtnFx, - ArgEdit& rEdArg, RefButton& rRefBtn); + void InitArgInput(sal_uInt16 nPos, weld::Label& rFtArg, weld::Button& rBtnFx, ArgEdit& rEdArg, + RefButton& rRefBtn); - void SetArgumentDesc(const OUString& aText); - void SetArgumentText(const OUString& aText); + void SetArgumentDesc(const OUString& aText); + void SetArgumentText(const OUString& aText); + void SetArgName(sal_uInt16 no, const OUString& aArg); + void SetArgNameFont(sal_uInt16 no, const vcl::Font&); - void SetArgName (sal_uInt16 no,const OUString &aArg); - void SetArgNameFont (sal_uInt16 no,const vcl::Font&); - - void UpdateArgDesc( sal_uInt16 nArg ); - void UpdateArgInput( sal_uInt16 nOffset, sal_uInt16 i ); + void UpdateArgDesc(sal_uInt16 nArg); + void UpdateArgInput(sal_uInt16 nOffset, sal_uInt16 i); public: - ParaWin(weld::Container* pParent, IControlReferenceHandler* _pDlg); - ~ParaWin(); + ParaWin(weld::Container* pParent, IControlReferenceHandler& rDlg); + ~ParaWin(); - void SetFunctionDesc(const IFunctionDescription* pFDesc); - void SetArgumentOffset(sal_uInt16 nOffset); - void SetEditDesc(const OUString& aText); - void UpdateParas(); - void ClearAll(); + void SetFunctionDesc(const IFunctionDescription* pFDesc); + void SetArgumentOffset(sal_uInt16 nOffset); + void SetEditDesc(const OUString& aText); + void UpdateParas(); + void ClearAll(); - sal_uInt16 GetActiveLine() const { return nActiveLine;} - void SetActiveLine(sal_uInt16 no); - RefEdit* GetActiveEdit(); - OUString GetActiveArgName() const; + sal_uInt16 GetActiveLine() const { return m_nActiveLine; } + void SetActiveLine(sal_uInt16 no); + RefEdit* GetActiveEdit(); + OUString GetActiveArgName() const; - OUString GetArgument(sal_uInt16 no); - void SetArgument(sal_uInt16 no, std::u16string_view aString); - void SetArgumentFonts(const vcl::Font& aBoldFont,const vcl::Font& aLightFont); + OUString GetArgument(sal_uInt16 no); + void SetArgument(sal_uInt16 no, std::u16string_view aString); + void SetArgumentFonts(const vcl::Font& aBoldFont, const vcl::Font& aLightFont); - void SetEdFocus(); // visible edit lines - sal_uInt16 GetSliderPos() const; - void SetSliderPos(sal_uInt16 nSliderPos); + void SetEdFocus(); // visible edit lines + sal_uInt16 GetSliderPos() const; + void SetSliderPos(sal_uInt16 nSliderPos); - void SetArgModifiedHdl( const Link& rLink ) { aArgModifiedLink = rLink; } - void SetFxHdl( const Link& rLink ) { aFxLink = rLink; } + void SetArgModifiedHdl(const Link& rLink) { m_aArgModifiedLink = rLink; } + void SetFxHdl(const Link& rLink) { m_aFxLink = rLink; } - void SliderMoved(); + void SliderMoved(); - void Show() { m_xContainer->show(); } + void Show() { m_xContainer->show(); } }; - } // formula /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/formula/source/ui/dlg/structpg.cxx b/formula/source/ui/dlg/structpg.cxx index 94ee07e513cb..dd8c928b43a4 100644 --- a/formula/source/ui/dlg/structpg.cxx +++ b/formula/source/ui/dlg/structpg.cxx @@ -18,6 +18,7 @@ */ #include +#include #include "structpg.hxx" #include diff --git a/formula/source/ui/dlg/structpg.hxx b/formula/source/ui/dlg/structpg.hxx index 104dfd8594ad..3b32337bf989 100644 --- a/formula/source/ui/dlg/structpg.hxx +++ b/formula/source/ui/dlg/structpg.hxx @@ -21,8 +21,8 @@ #include #include +#include #include -#include namespace formula { diff --git a/fpicker/source/office/OfficeControlAccess.cxx b/fpicker/source/office/OfficeControlAccess.cxx index f83122e8cf5c..d3f8e5f22a89 100644 --- a/fpicker/source/office/OfficeControlAccess.cxx +++ b/fpicker/source/office/OfficeControlAccess.cxx @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #include #include diff --git a/fpicker/source/office/PlacesListBox.hxx b/fpicker/source/office/PlacesListBox.hxx index c415a5293215..7950cbfdc290 100644 --- a/fpicker/source/office/PlacesListBox.hxx +++ b/fpicker/source/office/PlacesListBox.hxx @@ -11,8 +11,8 @@ #include "iodlg.hxx" #include +#include #include -#include #include #include diff --git a/fpicker/source/office/QueryFolderName.hxx b/fpicker/source/office/QueryFolderName.hxx index 4ebcbc99af3b..3cbb5f56653e 100644 --- a/fpicker/source/office/QueryFolderName.hxx +++ b/fpicker/source/office/QueryFolderName.hxx @@ -18,9 +18,10 @@ */ #pragma once +#include #include #include -#include +#include class QueryFolderNameDialog : public weld::GenericDialogController { @@ -29,7 +30,7 @@ private: std::unique_ptr m_xOKBtn; DECL_LINK(OKHdl, weld::Button&, void); - DECL_LINK(NameHdl, weld::Entry&, void); + DECL_LINK(NameHdl, weld::TextWidget&, void); public: QueryFolderNameDialog(weld::Window* _pParent, const OUString& rTitle, diff --git a/fpicker/source/office/RemoteFilesDialog.cxx b/fpicker/source/office/RemoteFilesDialog.cxx index 00fe2ff36f01..cc9af3e47090 100644 --- a/fpicker/source/office/RemoteFilesDialog.cxx +++ b/fpicker/source/office/RemoteFilesDialog.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include using namespace ::svt; diff --git a/fpicker/source/office/RemoteFilesDialog.hxx b/fpicker/source/office/RemoteFilesDialog.hxx index 5267e0ad7d2e..2fae68804a95 100644 --- a/fpicker/source/office/RemoteFilesDialog.hxx +++ b/fpicker/source/office/RemoteFilesDialog.hxx @@ -11,10 +11,10 @@ #include "autocmpledit.hxx" #include - -#include - +#include #include +#include +#include #include #include diff --git a/fpicker/source/office/autocmpledit.cxx b/fpicker/source/office/autocmpledit.cxx index 89a2d0b0c245..cff53c751278 100644 --- a/fpicker/source/office/autocmpledit.cxx +++ b/fpicker/source/office/autocmpledit.cxx @@ -27,7 +27,7 @@ IMPL_LINK(AutocompleteEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool) return false; } -IMPL_LINK_NOARG(AutocompleteEdit, ChangedHdl, weld::Entry&, void) +IMPL_LINK_NOARG(AutocompleteEdit, ChangedHdl, weld::TextWidget&, void) { m_aChangeHdl.Call(*m_xEntry); diff --git a/fpicker/source/office/autocmpledit.hxx b/fpicker/source/office/autocmpledit.hxx index e86a685c5abe..c96582e45612 100644 --- a/fpicker/source/office/autocmpledit.hxx +++ b/fpicker/source/office/autocmpledit.hxx @@ -11,7 +11,7 @@ #include #include -#include + #include class AutocompleteEdit @@ -26,7 +26,7 @@ private: sal_uInt16 m_nLastCharCode; DECL_LINK(KeyInputHdl, const KeyEvent&, bool); - DECL_LINK(ChangedHdl, weld::Entry&, void); + DECL_LINK(ChangedHdl, weld::TextWidget&, void); DECL_LINK(TryAutoComplete, Timer*, void); bool Match(std::u16string_view rText); diff --git a/fpicker/source/office/breadcrumb.hxx b/fpicker/source/office/breadcrumb.hxx index b8b94d2bc2b0..74b779e82c01 100644 --- a/fpicker/source/office/breadcrumb.hxx +++ b/fpicker/source/office/breadcrumb.hxx @@ -10,7 +10,10 @@ #pragma once #include -#include +#include +#include +#include + #include #include diff --git a/fpicker/source/office/fileview.cxx b/fpicker/source/office/fileview.cxx index e4e82b97392b..f8daf109f15b 100644 --- a/fpicker/source/office/fileview.cxx +++ b/fpicker/source/office/fileview.cxx @@ -63,6 +63,8 @@ #include #include #include +#include +#include #include #include "fileview.hxx" @@ -208,7 +210,8 @@ public: void end_editing() { mxTreeView->end_editing(); - mxTreeView->connect_editing(Link(), Link()); + mxTreeView->connect_editing(Link(), + Link()); mbEditing = false; } @@ -232,8 +235,7 @@ public: DECL_LINK(ResetQuickSearch_Impl, Timer *, void); DECL_LINK(CommandHdl, const CommandEvent&, bool); DECL_LINK(EditingEntryHdl, const weld::TreeIter&, bool); - typedef std::pair IterString; - DECL_LINK(EditedEntryHdl, const IterString&, bool); + DECL_LINK(EditedEntryHdl, const weld::TreeView::IterColText&, bool); DECL_LINK(KeyInputHdl, const KeyEvent&, bool); void ExecuteContextMenuAction(std::u16string_view rSelectedPopentry); @@ -670,14 +672,16 @@ void ViewTabListBox_Impl::DeleteEntries() mxTreeView->remove_selection(); } -IMPL_LINK(ViewTabListBox_Impl, EditedEntryHdl, const IterString&, rIterString, bool) +IMPL_LINK(ViewTabListBox_Impl, EditedEntryHdl, const weld::TreeView::IterColText&, rIterColText, + bool) { mbEditing = false; - mxTreeView->connect_editing(Link(), Link()); + mxTreeView->connect_editing(Link(), + Link()); - const weld::TreeIter& rEntry = rIterString.first; - OUString sNewText = rIterString.second; + const weld::TreeIter& rEntry = rIterColText.m_rIter; + OUString sNewText = rIterColText.m_sText; if (sNewText.isEmpty()) return false; @@ -813,7 +817,7 @@ SvtFileView::SvtFileView(weld::Window* pTopLevel, mpImpl.reset(new SvtFileView_Impl(this, pTopLevel, std::move(xTreeView), std::move(xIconView), xCmdEnv, nFlags, bOnlyFolder)); weld::TreeView* pView = mpImpl->mxView->getWidget(); - pView->connect_column_clicked(LINK(this, SvtFileView, HeaderSelect_Impl)); + pView->connect_column_header_clicked(LINK(this, SvtFileView, HeaderSelect_Impl)); } void SvtFileView::grab_focus() diff --git a/fpicker/source/office/fileview.hxx b/fpicker/source/office/fileview.hxx index 4145f6896c8f..38559e693b49 100644 --- a/fpicker/source/office/fileview.hxx +++ b/fpicker/source/office/fileview.hxx @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include // class SvtFileView ----------------------------------------------------- diff --git a/fpicker/source/office/foldertree.cxx b/fpicker/source/office/foldertree.cxx index 821210a076d6..4674a73c4e4e 100644 --- a/fpicker/source/office/foldertree.cxx +++ b/fpicker/source/office/foldertree.cxx @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "contentenumeration.hxx" #include "foldertree.hxx" diff --git a/fpicker/source/office/foldertree.hxx b/fpicker/source/office/foldertree.hxx index 8f0833de45a7..4e0238e2a8a4 100644 --- a/fpicker/source/office/foldertree.hxx +++ b/fpicker/source/office/foldertree.hxx @@ -12,9 +12,9 @@ #include #include #include -#include +#include -namespace com :: sun :: star :: ucb { class XCommandEnvironment; } +namespace com::sun::star::ucb { class XCommandEnvironment; } using namespace ::com::sun::star::ucb; using namespace ::com::sun::star::uno; diff --git a/fpicker/source/office/fpdialogbase.hxx b/fpicker/source/office/fpdialogbase.hxx index 003b9f157ed5..3e3363228926 100644 --- a/fpicker/source/office/fpdialogbase.hxx +++ b/fpicker/source/office/fpdialogbase.hxx @@ -20,7 +20,8 @@ #include #include -#include +#include + #include #include #include diff --git a/fpicker/source/office/iodlg.cxx b/fpicker/source/office/iodlg.cxx index 77e14b4628ed..808df6bf8f3c 100644 --- a/fpicker/source/office/iodlg.cxx +++ b/fpicker/source/office/iodlg.cxx @@ -41,9 +41,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -2275,7 +2275,7 @@ IMPL_LINK_NOARG(QueryFolderNameDialog, OKHdl, weld::Button&, void) m_xDialog->response(RET_OK); } -IMPL_LINK_NOARG(QueryFolderNameDialog, NameHdl, weld::Entry&, void) +IMPL_LINK_NOARG(QueryFolderNameDialog, NameHdl, weld::TextWidget&, void) { // trim the strings OUString aName = comphelper::string::strip(m_xNameEdit->get_text(), ' '); diff --git a/fpicker/source/office/iodlg.hxx b/fpicker/source/office/iodlg.hxx index 0b7745191143..c34e33a5a85f 100644 --- a/fpicker/source/office/iodlg.hxx +++ b/fpicker/source/office/iodlg.hxx @@ -28,7 +28,11 @@ #include "asyncfilepicker.hxx" #include "fpsmartcontent.hxx" #include "fpdialogbase.hxx" +#include +#include #include +#include +#include #include #include diff --git a/fpicker/source/office/iodlgimp.hxx b/fpicker/source/office/iodlgimp.hxx index b7e5082020d9..05ef874db04f 100644 --- a/fpicker/source/office/iodlgimp.hxx +++ b/fpicker/source/office/iodlgimp.hxx @@ -21,9 +21,13 @@ #include "PlacesListBox.hxx" #include +#include +#include #include +#include #include #include +#include #include #include diff --git a/fpicker/source/win32/FilterContainer.cxx b/fpicker/source/win32/FilterContainer.cxx index 67ccd6353ba3..c675c77fb811 100644 --- a/fpicker/source/win32/FilterContainer.cxx +++ b/fpicker/source/win32/FilterContainer.cxx @@ -220,12 +220,6 @@ static sal_uInt32 getTotalFilterLength( CFilterContainer& aFilterContainer ) return ( totalLength > 0 ) ? totalLength + 1 : totalLength; } -static -void wcsmemcpy( sal_Unicode* pDest, const sal_Unicode* pSrc, sal_uInt32 nLength ) -{ - memcpy( pDest, pSrc, nLength * sizeof( sal_Unicode ) ); -} - // a helper trivial helper function to create a filter buffer in the // format the Win32 API requires, // e.g. "Text\0*.txt\0Doc\0*.doc;*xls\0\0" @@ -252,17 +246,17 @@ OUString makeWinFilterBuffer( CFilterContainer& aFilterContainer ) while( aFilterContainer.getNextFilter( nextFilter ) ) { - wcsmemcpy( - pBuff.get() + memPos, + std::copy_n( nextFilter.first.getStr( ), - nextFilter.first.getLength( ) ); + nextFilter.first.getLength( ), + pBuff.get() + memPos ); memPos += nextFilter.first.getLength( ) + 1; - wcsmemcpy( - pBuff.get() + memPos, + std::copy_n( nextFilter.second.getStr( ), - nextFilter.second.getLength( ) ); + nextFilter.second.getLength( ), + pBuff.get() + memPos ); memPos += nextFilter.second.getLength( ) + 1 ; } diff --git a/framework/inc/acceleratorconst.h b/framework/inc/acceleratorconst.h index 667dc06c07e8..f4187d048dd2 100644 --- a/framework/inc/acceleratorconst.h +++ b/framework/inc/acceleratorconst.h @@ -23,7 +23,7 @@ namespace framework{ -// same items with a name space alias +// same items with a namespace alias inline constexpr OUString AL_ELEMENT_ACCELERATORLIST = u"accel:acceleratorlist"_ustr; inline constexpr OUString AL_ELEMENT_ITEM = u"accel:item"_ustr; diff --git a/framework/inc/dispatch/closedispatcher.hxx b/framework/inc/dispatch/closedispatcher.hxx index 2217afa9c8d7..b76b58ef4dec 100644 --- a/framework/inc/dispatch/closedispatcher.hxx +++ b/framework/inc/dispatch/closedispatcher.hxx @@ -91,7 +91,7 @@ class CloseDispatcher final : public ::cppu::WeakImplHelper< /** @short for asynchronous operations we must hold us self alive! */ css::uno::Reference< css::uno::XInterface > m_xSelfHold; - /** @short holded alive for internally asynchronous operations! */ + /** @short held alive for internally asynchronous operations! */ css::uno::Reference< css::frame::XDispatchResultListener > m_xResultListener; VclPtr m_pSysWindow; @@ -149,9 +149,8 @@ class CloseDispatcher final : public ::cppu::WeakImplHelper< /** @short a callback for asynchronous started operations. - @descr As already mentioned, we make internally all operations - asynchronous. Otherwise our callis kill its own environment - during they call us... + @descr As already mentioned, we make all operations asynchronous internally. + Otherwise, our callers would kill their own environment while calling us. */ DECL_LINK( impl_asyncCallback, LinkParamNone*, void ); diff --git a/framework/inc/helper/ocomponentaccess.hxx b/framework/inc/helper/ocomponentaccess.hxx index 4ca28b843463..6506c28a435f 100644 --- a/framework/inc/helper/ocomponentaccess.hxx +++ b/framework/inc/helper/ocomponentaccess.hxx @@ -82,7 +82,7 @@ class OComponentAccess final : public ::cppu::WeakImplHelper< css::container::XE @seealso interface XEnumeration @seealso class Desktop @return If the desktop and some components exist => a valid reference to an enumeration
- An NULL-reference, other way. + A NULL-reference, otherwise. *//*-*****************************************************************************************************/ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override; diff --git a/framework/inc/helper/oframes.hxx b/framework/inc/helper/oframes.hxx index db725e1235fa..c3ddd95984a0 100644 --- a/framework/inc/helper/oframes.hxx +++ b/framework/inc/helper/oframes.hxx @@ -30,16 +30,16 @@ namespace framework{ /** - @short implement XFrames, XIndexAccess and XElementAccess interfaces as helper for services + @short implements XFrames, XIndexAccess and XElementAccess interfaces as helper for services @descr Use this class as helper for these interfaces. We share mutex and framecontainer with our owner. The framecontainer is a member of it from type "FrameContainer". That means; we have the same information as our owner. In current implementation we use mutex and lock-mechanism - to prevent against compete access. In future we plan support of semaphore! + to prevent concurrent access. In future we plan support of semaphore! @devstatus deprecated @ATTENTION Don't use this class as direct member - use it dynamically. Do not derive from this class. - We hold a weakreference to our owner not to our superclass. + We hold a weak reference to our owner, not to our superclass. */ class OFrames final : public ::cppu::WeakImplHelper< css::frame::XFrames > { @@ -47,10 +47,10 @@ class OFrames final : public ::cppu::WeakImplHelper< css::frame::XFrames > /** @short standard ctor - @descr These initialize a new instance of this class with all needed information for work. + @descr This initializes a new instance of this class with all needed information for work. We share framecontainer with owner implementation! It's a threadsafe container. - @param xOwner , reference to our owner. We hold a wekreference to prevent us against cross-references! - @param pFrameContainer , pointer to shared framecontainer of owner. It's valid only, if weakreference is valid! + @param xOwner , reference to our owner. We hold a weak reference to prevent cross-references! + @param pFrameContainer , pointer to shared framecontainer of owner. It's valid only, if weak reference is valid! */ OFrames( const css::uno::Reference< css::frame::XFrame >& xOwner , FrameContainer* pFrameContainer ); @@ -83,9 +83,9 @@ class OFrames final : public ::cppu::WeakImplHelper< css::frame::XFrames > /** @short return list of all applicable frames for given flags - @descr Call these to get a list of all frames, which are match with given search flags. + @descr Call this to get a list of all frames, which match given search flags. @param "nSearchFlag", flags to search right frames. - @return A list of founded frames. + @return A list of found frames. @onerror An empty list is returned. */ @@ -96,19 +96,19 @@ class OFrames final : public ::cppu::WeakImplHelper< css::frame::XFrames > /** @short get count of all current frames in container @descr This is the beginning of full index-access. With a count you can step over all items in container. - Next call should be getByIndex(). But these mechanism works only, if no lock in container is set! + Next call should be getByIndex(). But this mechanism works only, if no lock in container is set! @seealso class FrameContainer @seealso method getByIndex() @return Count of current items in container. - @onerror If a lock is set, we return 0 for prevent further access! + @onerror If a lock is set, we return 0 to prevent further access! */ virtual sal_Int32 SAL_CALL getCount() override; /** @short get specified container item by index - @descr If you called getCount() successful - this method return the specified element as an Any. + @descr If you called getCount() successfully - this method returns the specified element as an Any. You must observe the range from 0 to count-1! Otherwise an IndexOutOfBoundsException is thrown. @seealso class FrameContainer @@ -134,7 +134,7 @@ class OFrames final : public ::cppu::WeakImplHelper< css::frame::XFrames > /** @short get fill state of current container - @descr Call these to get information about, if items exist in container or not. + @descr Call this to get information about, if items exist in container or not. (container-lock is ignored) @return sal_True, if container contains some items. @return sal_False, otherwise. @@ -147,7 +147,7 @@ class OFrames final : public ::cppu::WeakImplHelper< css::frame::XFrames > /** @short standard destructor - @descr This method destruct an instance of this class and clear some member. + @descr This method destructs an instance of this class and clear some member. This method is protected, because it's not allowed to use this class as a member! You MUST use a dynamical instance (pointer). That's the reason for a protected dtor. */ @@ -157,8 +157,8 @@ class OFrames final : public ::cppu::WeakImplHelper< css::frame::XFrames > @short reset instance to default values @descr There are two ways to delete an instance of this class.
1) delete with destructor
- 2) dispose from parent or factory ore ...
- This method do the same for both ways! It free used memory and release references ... + 2) dispose from parent or factory or...
+ This method does the same for both ways! It frees used memory and release references ... @seealso method dispose() (if it exist!) @seealso destructor ~TaskEnumeration() diff --git a/framework/inc/properties.h b/framework/inc/properties.h index cf6a76f11906..22c0b28104d8 100644 --- a/framework/inc/properties.h +++ b/framework/inc/properties.h @@ -24,7 +24,7 @@ namespace framework{ -// Please add new entries alphabetical sorted and correct all other handles! +// Please add new entries alphabetically sorted and correct all other handles! // Start counting with 0, so it can be used as direct index into an array too. enum class FramePropHandle : sal_Int32 { @@ -111,8 +111,8 @@ class PropHelper { public: - /** checks if given property will be changed by this settings. - * We compare the content of the given any values. If they are different we return sal_True - sal_False otherwise. + /** checks if given property will be changed by these settings. + * We compare the content of the given any values. If they are different we return true - false otherwise. * * @param aCurrentValue contains the current value for this property * @param aNewValue contains the new value for this property @@ -133,7 +133,7 @@ class PropHelper aOldValue.clear(); aChangedValue.clear(); - // if value change ... + // if value changed ... bChanged = aCurrentValue != aNewValue; if (bChanged) { diff --git a/framework/inc/protocols.h b/framework/inc/protocols.h index 7ba3d41de394..9fa0cc7e58e5 100644 --- a/framework/inc/protocols.h +++ b/framework/inc/protocols.h @@ -31,7 +31,7 @@ namespace framework{ /** some protocols must be checked during loading or dispatching URLs manually - It can be necessary to decide, if a URL represent a non visible content or + It can be necessary to decide if a URL represents a non-visible content or a real visible component. */ @@ -43,7 +43,7 @@ namespace framework{ #define SPECIALPROTOCOL_PRIVATE_FACTORY u"private:factory" // internal protocol of the sfx project for generic dispatch functionality #define SPECIALPROTOCOL_SLOT u"slot:" -// external representation of the slot protocol using names instead of id's +// external representation of the slot protocol using names instead of IDs #define SPECIALPROTOCOL_UNO u".uno:" // special sfx protocol to execute macros #define SPECIALPROTOCOL_MACRO u"macro:" @@ -73,7 +73,7 @@ class ProtocolCheck public: /** - it checks if given URL match the required protocol only + it checks if a given URL matches the required protocol only It should be used instead of specifyProtocol() if only this question is interesting to perform the code. We must not check for all possible protocols here... */ diff --git a/framework/inc/services.h b/framework/inc/services.h index d758c5225c8d..0d50caa015d2 100644 --- a/framework/inc/services.h +++ b/framework/inc/services.h @@ -23,7 +23,7 @@ namespace framework{ -// used servicenames by framework +// used service names by framework inline constexpr OUString SERVICENAME_FILTERFACTORY = u"com.sun.star.document.FilterFactory"_ustr; inline constexpr OUString SERVICENAME_CFGUPDATEACCESS = u"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr; // provides read/write access to the configuration @@ -32,7 +32,7 @@ inline constexpr OUString SERVICENAME_JOB = u"com.sun.star.task.Job"_ustr; inline constexpr OUString SERVICENAME_PROTOCOLHANDLER = u"com.sun.star.frame.ProtocolHandler"_ustr; inline constexpr OUString SERVICENAME_POPUPMENUCONTROLLER = u"com.sun.star.frame.PopupMenuController"_ustr; -// used implementationnames by framework +// used implementation names by framework #define IMPLEMENTATIONNAME_QUICKLAUNCHER "com.sun.star.comp.desktop.QuickstartWrapper" diff --git a/framework/inc/stdtypes.h b/framework/inc/stdtypes.h index 265daba7786e..32b93eb48971 100644 --- a/framework/inc/stdtypes.h +++ b/framework/inc/stdtypes.h @@ -24,7 +24,7 @@ namespace framework{ /** - Own hash functions used for stl-structures ... e.g. hash tables/maps ... + Own hash functions used for STL structures ... e.g. hash tables/maps ... */ struct KeyEventHashCode diff --git a/framework/inc/strings.hrc b/framework/inc/strings.hrc index 99949fcfeabd..0c94fb1255e9 100644 --- a/framework/inc/strings.hrc +++ b/framework/inc/strings.hrc @@ -39,7 +39,7 @@ #define STR_TOGGLE_CURRENT_MODULE_HELP NC_("STR_TOGGLE_CURRENT_MODULE_HELP", "Shows only documents from the current module") #define STR_REMOTE_TITLE NC_("STR_REMOTE_TITLE", " (Remote)") #define STR_EMDASH_SEPARATOR NC_("STR_EMDASH_SEPARATOR", " — ") -#define STR_SAFEMODE_TITLE NC_("STR_SAFEMODE_TITLE", " (Safe Mode)") +#define STR_SAFEMODE_TITLE NC_("STR_SAFEMODE_TITLE", " (Troubleshoot Mode)") #define STR_TOOLBAR_TITLE_ADDON NC_("STR_TOOLBAR_TITLE_ADDON", "Add-On %num%") #define STR_FULL_DISC_RETRY_BUTTON NC_("STR_FULL_DISC_RETRY_BUTTON", "Retry" ) #define STR_FULL_DISC_MSG NC_("STR_FULL_DISC_MSG", "%PRODUCTNAME could not save important internal information due to insufficient free disk space at the following location:\n%PATH\n\nYou will not be able to continue working with %PRODUCTNAME without allocating more free disk space at that location.\n\nPress the 'Retry' button after you have allocated more free disk space to retry saving the data.\n\n" ) diff --git a/framework/inc/uielement/FixedImageToolbarController.hxx b/framework/inc/uielement/FixedImageToolbarController.hxx index ffe40713b524..198c617bfc42 100644 --- a/framework/inc/uielement/FixedImageToolbarController.hxx +++ b/framework/inc/uielement/FixedImageToolbarController.hxx @@ -37,8 +37,9 @@ public: const css::uno::Reference& rFrame, ToolBox* pToolBar, ToolBoxItemId nID, const OUString& aCommand); - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using ComplexToolbarController::disposing; + void disposing(std::unique_lock& rGuard) override; void CheckAndUpdateImages(); diff --git a/framework/inc/uielement/FixedTextToolbarController.hxx b/framework/inc/uielement/FixedTextToolbarController.hxx index bcf1d093f3f6..6a51e0d8ca9f 100644 --- a/framework/inc/uielement/FixedTextToolbarController.hxx +++ b/framework/inc/uielement/FixedTextToolbarController.hxx @@ -37,8 +37,9 @@ public: const css::uno::Reference& rFrame, ToolBox* pToolBar, ToolBoxItemId nID, const OUString& aCommand); - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using ComplexToolbarController::disposing; + void disposing(std::unique_lock& rGuard) override; private: virtual void executeControlCommand(const css::frame::ControlCommand& rControlCommand) override; diff --git a/framework/inc/uielement/comboboxtoolbarcontroller.hxx b/framework/inc/uielement/comboboxtoolbarcontroller.hxx index 126aab6500dd..998e28255b69 100644 --- a/framework/inc/uielement/comboboxtoolbarcontroller.hxx +++ b/framework/inc/uielement/comboboxtoolbarcontroller.hxx @@ -40,8 +40,9 @@ class ComboboxToolbarController final : public ComplexToolbarController const OUString& aCommand ); virtual ~ComboboxToolbarController() override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using ComplexToolbarController::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // called from ComboBoxControl void Select(); diff --git a/framework/inc/uielement/complextoolbarcontroller.hxx b/framework/inc/uielement/complextoolbarcontroller.hxx index 0aa10471be44..f2dfff34b252 100644 --- a/framework/inc/uielement/complextoolbarcontroller.hxx +++ b/framework/inc/uielement/complextoolbarcontroller.hxx @@ -45,8 +45,9 @@ class ComplexToolbarController : public svt::ToolboxController const OUString& aCommand ); virtual ~ComplexToolbarController() override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using svt::ToolboxController::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // XToolbarController virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override; diff --git a/framework/inc/uielement/dropdownboxtoolbarcontroller.hxx b/framework/inc/uielement/dropdownboxtoolbarcontroller.hxx index cb01578629cd..ab79c3c2ac5e 100644 --- a/framework/inc/uielement/dropdownboxtoolbarcontroller.hxx +++ b/framework/inc/uielement/dropdownboxtoolbarcontroller.hxx @@ -43,8 +43,9 @@ class DropdownToolbarController final : public ComplexToolbarController const OUString& aCommand ); virtual ~DropdownToolbarController() override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using ComplexToolbarController::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // called from ListBoxControl void Select(); diff --git a/framework/inc/uielement/edittoolbarcontroller.hxx b/framework/inc/uielement/edittoolbarcontroller.hxx index c45aa38937cf..04e916425e05 100644 --- a/framework/inc/uielement/edittoolbarcontroller.hxx +++ b/framework/inc/uielement/edittoolbarcontroller.hxx @@ -42,8 +42,9 @@ class EditToolbarController final : public ComplexToolbarController const OUString& aCommand ); virtual ~EditToolbarController() override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using ComplexToolbarController::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // called from EditControl void Modify(); diff --git a/framework/inc/uielement/fontsizemenucontroller.hxx b/framework/inc/uielement/fontsizemenucontroller.hxx index 6e4e23f84959..fb7dd315d3a1 100644 --- a/framework/inc/uielement/fontsizemenucontroller.hxx +++ b/framework/inc/uielement/fontsizemenucontroller.hxx @@ -55,7 +55,6 @@ namespace framework virtual void impl_setPopupMenu(std::unique_lock& rGuard) override; void setCurHeight( tools::Long nHeight, css::uno::Reference< css::awt::XPopupMenu > const & rPopupMenu ); void fillPopupMenu( css::uno::Reference< css::awt::XPopupMenu > const & rPopupMenu ); - OUString retrievePrinterName( css::uno::Reference< css::frame::XFrame > const & rFrame ); std::vector m_aHeightArray; css::frame::status::FontHeight m_aFontHeight; diff --git a/framework/inc/uielement/imagebuttontoolbarcontroller.hxx b/framework/inc/uielement/imagebuttontoolbarcontroller.hxx index f6c07c206128..f2e5a217164e 100644 --- a/framework/inc/uielement/imagebuttontoolbarcontroller.hxx +++ b/framework/inc/uielement/imagebuttontoolbarcontroller.hxx @@ -40,9 +40,6 @@ class ImageButtonToolbarController final : public ComplexToolbarController const OUString& aCommand ); virtual ~ImageButtonToolbarController() override; - // XComponent - virtual void SAL_CALL dispose() override; - private: virtual void executeControlCommand( const css::frame::ControlCommand& rControlCommand ) override; diff --git a/framework/inc/uielement/popuptoolbarcontroller.hxx b/framework/inc/uielement/popuptoolbarcontroller.hxx index ebeda5df1851..4317c3aa8220 100644 --- a/framework/inc/uielement/popuptoolbarcontroller.hxx +++ b/framework/inc/uielement/popuptoolbarcontroller.hxx @@ -34,8 +34,9 @@ typedef cppu::ImplInheritanceHelper& rGuard) override; // XInitialization virtual void SAL_CALL initialize(const css::uno::Sequence& aArguments) override; // XToolbarController diff --git a/framework/inc/uielement/spinfieldtoolbarcontroller.hxx b/framework/inc/uielement/spinfieldtoolbarcontroller.hxx index 796a5e00b277..55ab57c84fae 100644 --- a/framework/inc/uielement/spinfieldtoolbarcontroller.hxx +++ b/framework/inc/uielement/spinfieldtoolbarcontroller.hxx @@ -43,8 +43,9 @@ class SpinfieldToolbarController final : public ComplexToolbarController const OUString& aCommand ); virtual ~SpinfieldToolbarController() override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using ComplexToolbarController::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // called from SpinfieldControl void Modify(); diff --git a/framework/inc/uielement/styletoolbarcontroller.hxx b/framework/inc/uielement/styletoolbarcontroller.hxx index c155a7b2242b..ed9131c6f568 100644 --- a/framework/inc/uielement/styletoolbarcontroller.hxx +++ b/framework/inc/uielement/styletoolbarcontroller.hxx @@ -71,8 +71,9 @@ public: // XStatusListener void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; - // XComponent - void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using svt::ToolboxController::disposing; + void disposing(std::unique_lock& rGuard) override; }; } diff --git a/framework/inc/uielement/togglebuttontoolbarcontroller.hxx b/framework/inc/uielement/togglebuttontoolbarcontroller.hxx index fe11433434b7..502cb6609350 100644 --- a/framework/inc/uielement/togglebuttontoolbarcontroller.hxx +++ b/framework/inc/uielement/togglebuttontoolbarcontroller.hxx @@ -55,9 +55,6 @@ class ToggleButtonToolbarController final : public ComplexToolbarController const OUString& aCommand ); virtual ~ToggleButtonToolbarController() override; - // XComponent - virtual void SAL_CALL dispose() override; - // XToolbarController virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createPopupWindow() override; diff --git a/framework/inc/uielement/toolbarmanager.hxx b/framework/inc/uielement/toolbarmanager.hxx index 218eb3bf6350..a962378a931d 100644 --- a/framework/inc/uielement/toolbarmanager.hxx +++ b/framework/inc/uielement/toolbarmanager.hxx @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/framework/qa/complex/api_internal/api.lst b/framework/qa/complex/api_internal/api.lst index 02e660a765b3..305f18ec79fa 100644 --- a/framework/qa/complex/api_internal/api.lst +++ b/framework/qa/complex/api_internal/api.lst @@ -174,8 +174,6 @@ job254=sysdtrans.SystemClipboard job255=syssh.SystemShellExecute job256=text.DefaultNumberingProvider job257=toolkit.AccessibleComboBox -job258=toolkit.AccessibleList -job259=toolkit.AccessibleListBox job260=toolkit.AccessibleMenuSeparator job261=toolkit.AccessibleStatusBar job262=toolkit.AccessibleTabControl diff --git a/framework/qa/complex/framework/recovery/RecoveryTest.java b/framework/qa/complex/framework/recovery/RecoveryTest.java index ede07b4863e8..60a767125959 100644 --- a/framework/qa/complex/framework/recovery/RecoveryTest.java +++ b/framework/qa/complex/framework/recovery/RecoveryTest.java @@ -57,7 +57,7 @@ public class RecoveryTest extends ComplexTestCase { */ static Point windowMaxPosition; /** - * The office windows starts in the first quarter of the screen. In this variable + * The office windows start in the first quarter of the screen. In this variable * the maximum size for the windows was stored so the windows can be placed * visible on the screen. */ @@ -65,7 +65,7 @@ public class RecoveryTest extends ComplexTestCase { /** * All office windows will be placed by this test on randomized positions. - * This positions was stored in this Hashmap. The keys are the frame names + * These positions were stored in this Hashmap. The keys are the frame names * and the values are com sun.star.awt.Rectangle. * @see com.sun.star.awt.Rectangle */ @@ -77,7 +77,7 @@ public class RecoveryTest extends ComplexTestCase { * * @todo: hidden documents * @todo: running presentation - * @todo: modular dialogs like Hpyerlink-Dialog + * @todo: modular dialogs like Hyperlink-Dialog * @todo: second view of a document * @todo: remove recovery data before start test * @todo: after a second start after the crash there should no documents recovered anymore @@ -210,7 +210,7 @@ public class RecoveryTest extends ComplexTestCase { /** * This function uses accessibility to handle the dialog which appears while the - * office is crashed. It click the button "OK" to continue. + * office is crashed. It clicks the button "OK" to continue. */ private void handleRecoveryDialogAfterCrash(int expectedDocumentCount){ try{ @@ -362,7 +362,7 @@ public class RecoveryTest extends ComplexTestCase { oButton = oUITools.getButton("Next >"); } catch (NullPointerException e){ // no fault: The title "Start Recovery" switches to "Next" - // while all documents are recoverd + // while all documents are recovered } util.utils.shortWait(); counter++; @@ -395,7 +395,7 @@ public class RecoveryTest extends ComplexTestCase { /** * This function uses accessibility to handle the dialog "Are you sure". - * It click "Yes" or "No", dependent on the value of the parameter Yes + * It clicks "Yes" or "No", dependent on the value of the parameter Yes * @param yes If value is TRUE the button "Yes" was clicked, otherwise the button * "No". */ @@ -413,10 +413,10 @@ public class RecoveryTest extends ComplexTestCase { } /** - * This function uses accessibility to handle the dialog "Are you sure". - * It click "Yes" or "No", depending on the value of the parameter Yes - * @param saveDocuments If value is TRUE the button "Yes" was clicked, otherwise the button - * "No". + * This function uses accessibility to handle the dialog "Save Documents". + * It clicks "OK" or "Cancel", depending on the value of the parameter saveDocuments + * @param saveDocuments If value is TRUE the documents are saved, otherwise the button + * "Cancel" is clicked. */ private void handleSaveDocumentsDialog(boolean saveDocuments) { @@ -465,7 +465,7 @@ public class RecoveryTest extends ComplexTestCase { } /** - * This function gets the current screen size and calculate the first + * This function gets the current screen size and calculates the first * quarter of it. This quarter was used to position to Office windows. * Further this function calculates the maximum window size so the window * is visible if it placed on extreme position. @@ -530,7 +530,7 @@ public class RecoveryTest extends ComplexTestCase { int height = rand.nextInt(maxHeight + 1); int width = rand.nextInt((windowMaxSize.Width-posSize.Y) + 1); - // be sure that the new size his greater than the half of windowMaxSize + // be sure that the new size is greater than the half of windowMaxSize posSize.Height = (height < (maxHeight / 2)) ? height + (maxHeight / 2) : height; posSize.Width = (width < (maxWidth / 2)) ? width + (maxWidth / 2) : width; diff --git a/framework/qa/complex/framework/recovery/RecoveryTools.java b/framework/qa/complex/framework/recovery/RecoveryTools.java index cb0183caf455..eb662297ab82 100644 --- a/framework/qa/complex/framework/recovery/RecoveryTools.java +++ b/framework/qa/complex/framework/recovery/RecoveryTools.java @@ -39,7 +39,7 @@ import util.UITools; import util.utils; /** - * this class supports the RecoverTest. You will find here some helper + * this class supports the RecoveryTest. You will find here some helper * functions. */ public class RecoveryTools { @@ -81,16 +81,16 @@ public class RecoveryTools { } /** - * After a crash the office start with a recovery dialog. It could be that the office - * is connectable but not all services to get the dialog a loaded. This function + * After a crash the office starts with a recovery dialog. It could be that the office + * is connectable but not all services to get the dialog are loaded. This function * tries to get the dialog until the OfficeWatcher kills the office. * @return a XDialog interface of the dialog */ public XDialog getActiveDialogAfterStartup(XMultiServiceFactory xMSF){ // while the office starts it takes some time to get the dialog. - // the dialog is accessible AFTER the office has recoverd all documents. - // This could consumes more time then the TimeOut allow. + // the dialog is accessible AFTER the office has recovered all documents. + // This could consume more time than the TimeOut allows. int counter = 0; int multi = 5; int pause = utils.DEFAULT_SHORT_WAIT_MS * 10; @@ -109,7 +109,7 @@ public class RecoveryTools { } /** - * remove the content of the user backup folder and removes the Recovery.xcu. This + * remove the content of the user backup folder and remove the Recovery.xcu. This * was done from the Office via XSimpleFileAccess * @throws com.sun.star.io.IOException the exception was thrown if something goes wrong. */ @@ -176,8 +176,8 @@ public class RecoveryTools { /** - * This function waits until the office is closed. If the closing time reach - * the value of parameter THREAD_TIME_OUT the office was killed. + * This function waits until the office is closed. If the closing time reaches + * the value of parameter THREAD_TIME_OUT the office is killed. */ public void waitForClosedOffice(){ // check for the office process diff --git a/framework/qa/cppunit/accelerators.cxx b/framework/qa/cppunit/accelerators.cxx index 6f1fd27d0ab8..370875ddd4af 100644 --- a/framework/qa/cppunit/accelerators.cxx +++ b/framework/qa/cppunit/accelerators.cxx @@ -57,7 +57,7 @@ void AcceleratorsTest::configNotification() CPPUNIT_ASSERT(xSwAccelCfg.is()); } - // The two modules configs shouldn’t be the same object, otherwise + // The two module configs shouldn’t be the same object, otherwise // the test is not really testing anything CPPUNIT_ASSERT(xSwAccelCfgs[0] != xSwAccelCfgs[1]); diff --git a/framework/qa/cppunit/dispatchtest.cxx b/framework/qa/cppunit/dispatchtest.cxx index 3e9710910970..332d783cfdfc 100644 --- a/framework/qa/cppunit/dispatchtest.cxx +++ b/framework/qa/cppunit/dispatchtest.cxx @@ -21,7 +21,7 @@ using namespace ::com::sun::star; namespace { -/// Sample interception implementation that asserts getInterceptedURLs() and queryDispatch() is in sync. +/// Sample interception implementation that asserts getInterceptedURLs() and queryDispatch() are in sync. class MyInterceptor : public cppu::WeakImplHelper { diff --git a/framework/source/dispatch/closedispatcher.cxx b/framework/source/dispatch/closedispatcher.cxx index 98aa117de13a..b3c77a7f3bb6 100644 --- a/framework/source/dispatch/closedispatcher.cxx +++ b/framework/source/dispatch/closedispatcher.cxx @@ -141,7 +141,7 @@ void SAL_CALL CloseDispatcher::dispatchWithNotification(const css::util::URL& // We have to reject double calls. Otherwise we risk, // that we try to close an already closed resource... // And it is no problem to do nothing then. The UI user will try it again, if - // non of these jobs was successful. + // none of these jobs was successful. if (m_xSelfHold.is()) { aWriteLock.clear(); @@ -194,9 +194,9 @@ void SAL_CALL CloseDispatcher::dispatchWithNotification(const css::util::URL& // OK - URLs are the right ones. // But we can't execute synchronously :-) - // May we are called from a generic key-input handler, - // which isn't aware that this call kill its own environment... - // Do it asynchronous everytimes! + // Maybe we are called from a generic key-input handler, + // which isn't aware that this call kills its own environment... + // Do it asynchronous every time! // But don't forget to hold ourselves alive. // We are called back from an environment, which doesn't know a uno reference. @@ -235,9 +235,9 @@ void SAL_CALL CloseDispatcher::dispatchWithNotification(const css::util::URL& - close all views to the same document, if needed and possible - make the current frame empty ! This step is necessary to handle errors during closing the - document inside the frame. May the document shows a dialog and - the user ignore it. Then the state of the office can be changed - during we try to close frame and document. + document inside the frame. Maybe the document shows a dialog and + the user ignores it. Then the state of the office can be changed + while we try to close frame and document. - check the environment (means count open frames - excluding our current one) - decide then, if we must close this frame only, establish the backing mode @@ -248,7 +248,7 @@ IMPL_LINK_NOARG(CloseDispatcher, impl_asyncCallback, LinkParamNone*, void) try { - // Allow calling of XController->suspend() everytimes. + // Allow calling of XController->suspend() every time. // Dispatch is an UI functionality. We implement such dispatch object here. // And further XController->suspend() was designed to bring an UI ... bool bControllerSuspended = false; @@ -350,7 +350,7 @@ IMPL_LINK_NOARG(CloseDispatcher, impl_asyncCallback, LinkParamNone*, void) else // c3) there is no other (visible) frame open ... - // The help module will be ignored everytimes! + // The help module will be ignored every time! // But we have to decide if we must terminate the // application or establish the backing mode now. // And that depends from the dispatched URL ... @@ -467,7 +467,7 @@ bool CloseDispatcher::implts_prepareFrameForClosing(const css::uno::Reference< c // Inform user about modified documents or still running jobs (e.g. printing). { css::uno::Reference< css::frame::XController > xController = xFrame->getController(); - if (xController.is()) // some views don't uses a controller .-( (e.g. the help window) + if (xController.is()) // some views don't use a controller .-( (e.g. the help window) { bControllerSuspended = xController->suspend(true); if (! bControllerSuspended) @@ -587,9 +587,9 @@ css::uno::Reference< css::frame::XFrame > CloseDispatcher::static_impl_searchRig if (xTopWindowCheck.is()) { // b1) Note: Toolkit interface XTopWindow sometimes is used by real VCL-child-windows also .-) - // Be sure that these window is really a "top system window". + // Be sure that this window is really a "top system window". // Attention ! Checking Window->GetParent() isn't the right approach here. - // Because sometimes VCL create "implicit border windows" as parents even we created + // Because sometimes VCL create "implicit border windows" as parents even if we created // a simple XWindow using the toolkit only .-( SolarMutexGuard aSolarLock; VclPtr pWindow = VCLUnoHelper::GetWindow( xWindow ); diff --git a/framework/source/dispatch/interceptionhelper.cxx b/framework/source/dispatch/interceptionhelper.cxx index 2756c5e4afa3..5253eb110352 100644 --- a/framework/source/dispatch/interceptionhelper.cxx +++ b/framework/source/dispatch/interceptionhelper.cxx @@ -51,8 +51,8 @@ css::uno::Reference< css::frame::XDispatch > SAL_CALL InterceptionHelper::queryD { SolarMutexGuard aReadLock; - // a) first search an interceptor, which match to this URL by its URL pattern registration - // Note: if it return NULL - it does not mean an empty interceptor list automatically! + // a) first search an interceptor, which matches to this URL by its URL pattern registration + // Note: if it returns NULL - it does not mean an empty interceptor list automatically! InterceptorList::const_iterator pIt = m_lInterceptionRegs.findByPattern(aURL.Complete); if (pIt != m_lInterceptionRegs.end()) xInterceptor = pIt->xInterceptor; @@ -75,8 +75,8 @@ css::uno::Reference< css::frame::XDispatch > SAL_CALL InterceptionHelper::queryD // patterns above) } // c) No registered interceptor => use our direct slave. - // This helper exist by design and must be valid everytimes ... - // But to be more feature proof - we should check that .-) + // This helper exists by design and must be valid every time ... + // But to be more future proof - we should check that .-) if (!xInterceptor.is() && m_xSlave.is()) xInterceptor = m_xSlave; } @@ -106,8 +106,8 @@ void SAL_CALL InterceptionHelper::registerDispatchProviderInterceptor(const css: throw css::uno::RuntimeException(u"NULL references not allowed as in parameter"_ustr, xThis); // Fill a new info structure for new interceptor. - // Save his reference and try to get an additional URL/pattern list from him. - // If no list exist register these interceptor for all dispatch events with "*"! + // Save its reference and try to get an additional URL/pattern list from it. + // If no list exists register this interceptor for all dispatch events with "*"! InterceptorInfo aInfo; aInfo.xInterceptor = xInterceptor; @@ -131,7 +131,7 @@ void SAL_CALL InterceptionHelper::registerDispatchProviderInterceptor(const css: } // b) OK - there is at least one interceptor already registered. - // It's slave and it's master must be valid references ... + // Its slave and its master must be valid references ... // because we created it. // insert it before any other existing interceptor - means at the beginning of our list. @@ -172,7 +172,7 @@ void SAL_CALL InterceptionHelper::releaseDispatchProviderInterceptor(const css:: // If it could be located inside cache - // use its slave/master relations to update the interception list; // set empty references for it as new master and slave; - // and release it from out cache. + // and release it from our cache. InterceptorList::iterator pIt = m_lInterceptionRegs.findByReference(xInterceptor); if (pIt != m_lInterceptionRegs.end()) { @@ -227,8 +227,8 @@ void SAL_CALL InterceptionHelper::disposing(const css::lang::EventObject& aEvent if (aEvent.Source != xOwner) return; - // Because every interceptor hold at least one reference to us ... and we destruct this list - // of interception objects ... we should hold ourself alive .-) + // Because every interceptor holds at least one reference to us ... and we destruct this list + // of interception objects ... we should hold ourselves alive .-) css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY_THROW); // We need a full copy of all currently registered interceptor objects. diff --git a/framework/source/dispatch/oxt_handler.cxx b/framework/source/dispatch/oxt_handler.cxx index de47f9383b19..cf208b5f6cc6 100644 --- a/framework/source/dispatch/oxt_handler.cxx +++ b/framework/source/dispatch/oxt_handler.cxx @@ -75,7 +75,7 @@ Oxt_Handler::~Oxt_Handler() @short try to load audio file @descr This method try to load given audio file by URL and play it. We use vcl/Sound class to do that. - Playing of sound is asynchron every time. + Playing of sound is asynchronous every time. @attention We must hold us alive by ourself ... because we use async. vcl sound player ... but playing is started in async interface call "dispatch()" too. And caller forget us immediately. But then our uno ref count diff --git a/framework/source/dispatch/systemexec.cxx b/framework/source/dispatch/systemexec.cxx index ac1338e2c852..161e8025c0ab 100644 --- a/framework/source/dispatch/systemexec.cxx +++ b/framework/source/dispatch/systemexec.cxx @@ -108,7 +108,7 @@ void SAL_CALL SystemExec::dispatchWithNotification( const css::util::URL& { css::uno::Reference< css::util::XStringSubstitution > xPathSubst( css::util::PathSubstitution::create(m_xContext) ); - OUString sSystemURL = xPathSubst->substituteVariables(sSystemURLWithVariables, true); // sal_True force an exception if unknown variables exists ! + OUString sSystemURL = xPathSubst->substituteVariables(sSystemURLWithVariables, true); // sal_True forces an exception if unknown variables exist ! css::uno::Reference< css::system::XSystemShellExecute > xShell = css::system::SystemShellExecute::create( m_xContext ); diff --git a/framework/source/fwe/helper/windowstatehelper.cxx b/framework/source/fwe/helper/windowstatehelper.cxx index 2d110a69612e..32ea528058e6 100644 --- a/framework/source/fwe/helper/windowstatehelper.cxx +++ b/framework/source/fwe/helper/windowstatehelper.cxx @@ -46,7 +46,7 @@ OUString WindowStateHelper::GetFromWindow(vcl::Window* pWin) { vcl::WindowDataMask const nMask = vcl::WindowDataMask::All & ~vcl::WindowDataMask::Minimized; - return static_cast(pWin)->GetWindowState(nMask); + return static_cast(pWin)->GetWindowState(nMask).toStr(); } return {}; diff --git a/framework/source/fwe/xml/xmlnamespaces.cxx b/framework/source/fwe/xml/xmlnamespaces.cxx index d8afe175a159..32ae49863dfa 100644 --- a/framework/source/fwe/xml/xmlnamespaces.cxx +++ b/framework/source/fwe/xml/xmlnamespaces.cxx @@ -45,8 +45,8 @@ void XMLNamespaces::addNamespace( const OUString& aName, const OUString& aValue } else { - // a xml namespace without name is not allowed (e.g. "xmlns:" ) - throw SAXException( u"A xml namespace without name is not allowed!"_ustr, Reference< XInterface >(), Any() ); + // an XML namespace without name is not allowed (e.g. "xmlns:" ) + throw SAXException( u"An XML namespace without name is not allowed!"_ustr, Reference< XInterface >(), Any() ); } } diff --git a/framework/source/helper/persistentwindowstate.cxx b/framework/source/helper/persistentwindowstate.cxx index 5d7c1d6014dc..d83fa95a473d 100644 --- a/framework/source/helper/persistentwindowstate.cxx +++ b/framework/source/helper/persistentwindowstate.cxx @@ -226,7 +226,7 @@ OUString PersistentWindowState::implst_getWindowStateFromWindow(const css::uno:: if ( pWindow && pWindow->IsSystemWindow() ) { vcl::WindowDataMask const nMask = vcl::WindowDataMask::All & ~vcl::WindowDataMask::Minimized; - sWindowState = static_cast(pWindow.get())->GetWindowState(nMask); + sWindowState = static_cast(pWindow.get())->GetWindowState(nMask).toStr(); } // <- SOLAR SAFE ------------------------ } @@ -264,9 +264,9 @@ void PersistentWindowState::implst_setWindowStateOnWindow(const css::uno::Refere if (pWorkWindow->IsMinimized()) return; - OUString sOldWindowState = pSystemWindow->GetWindowState(); - if ( sOldWindowState != sWindowState ) - pSystemWindow->SetWindowState(sWindowState); + vcl::WindowData aOldWindowState = pSystemWindow->GetWindowState(); + if (aOldWindowState.toStr() != sWindowState) + pSystemWindow->SetWindowState(vcl::WindowData(sWindowState)); // <- SOLAR SAFE ------------------------ } diff --git a/framework/source/helper/statusindicatorfactory.cxx b/framework/source/helper/statusindicatorfactory.cxx index 8351f1921667..3cc800515406 100644 --- a/framework/source/helper/statusindicatorfactory.cxx +++ b/framework/source/helper/statusindicatorfactory.cxx @@ -87,7 +87,7 @@ void SAL_CALL StatusIndicatorFactory::initialize(const css::uno::Sequence< css:: } } -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ m_bDisableReschedule = true; #endif impl_createProgress(); diff --git a/framework/source/helper/titlebarupdate.cxx b/framework/source/helper/titlebarupdate.cxx index 40e8f482bc3e..b6208a6ca92d 100644 --- a/framework/source/helper/titlebarupdate.cxx +++ b/framework/source/helper/titlebarupdate.cxx @@ -70,7 +70,7 @@ void SAL_CALL TitleBarUpdate::initialize(const css::uno::Sequence< css::uno::Any { SolarMutexGuard g; - // hold the frame as weak reference(!) so it can die everytimes :-) + // hold the frame as weak reference(!) so it can die every time :-) m_xFrame = xFrame; } @@ -84,7 +84,7 @@ void SAL_CALL TitleBarUpdate::initialize(const css::uno::Sequence< css::uno::Any void SAL_CALL TitleBarUpdate::frameAction(const css::frame::FrameActionEvent& aEvent) { - // we are interested on events only, which must trigger a title bar update + // we are interested in events only, which must trigger a title bar update // because component was changed. if ( (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ) || @@ -107,7 +107,7 @@ void SAL_CALL TitleBarUpdate::disposing(const css::lang::EventObject&) if (xFrame.is()) xFrame->removeFrameActionListener(this); - // nothing todo here - because we hold the frame as weak reference only + // nothing to do here - because we hold the frame as weak reference only } //http://live.gnome.org/GnomeShell/ApplicationBased @@ -234,7 +234,7 @@ void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFra sal_Int32 nIcon = INVALID_ICON_ID; // b) try to find information on controller property set directly - // Don't forget to catch possible exceptions - because these property is an optional one! + // Don't forget to catch possible exceptions - because this property is an optional one! css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY ); if ( xSet.is() ) { @@ -251,7 +251,7 @@ void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFra } // c) if b) failed ... identify the used module and retrieve set icon from module config. - // Tirck :-) Module was already specified outside and aInfo contains all needed information. + // Trick :-) Module was already specified outside and aInfo contains all needed information. if ( nIcon == INVALID_ICON_ID ) { TModuleInfo aInfo; diff --git a/framework/source/inc/accelerators/presethandler.hxx b/framework/source/inc/accelerators/presethandler.hxx index 0800c8c8353d..2251edfff004 100644 --- a/framework/source/inc/accelerators/presethandler.hxx +++ b/framework/source/inc/accelerators/presethandler.hxx @@ -67,7 +67,7 @@ class PresetHandler private: - /** @short can be used to create on needed uno resources. */ + /** @short can be used to create needed uno resources. */ css::uno::Reference< css::uno::XComponentContext > m_xContext; /** @short knows the type of provided configuration. @@ -87,8 +87,8 @@ class PresetHandler this member is meant relative to the document root... not to the share layer root! - Further is defined, that m_xWorkingStorageUser - is equals to m_xWorkingStorageShare then! + Further it is defined, that m_xWorkingStorageUser + is equal to m_xWorkingStorageShare then! */ css::uno::Reference< css::embed::XStorage > m_xWorkingStorageShare; @@ -103,8 +103,8 @@ class PresetHandler this member is meant relative to the document root... not to the user layer root! - Further is defined, that m_xWorkingStorageUser - is equals to m_xWorkingStorageShare then! + Further it is defined, that m_xWorkingStorageUser + is equal to m_xWorkingStorageShare then! */ css::uno::Reference< css::embed::XStorage > m_xWorkingStorageUser; @@ -134,7 +134,7 @@ class PresetHandler /** @short closes all open storages ... if user forgot that .-) */ ~PresetHandler(); - /** @short free all currently cache(!) storages. */ + /** @short free all currently cached(!) storages. */ void forgetCachedStorages(); /** @short return access to the internally used and cached root storage. @@ -144,7 +144,7 @@ class PresetHandler older implementations, which base on them ... getOrCreate...() - What does it mean? - Such root storage will be created one times only and + Such root storage will be created one time only and cached then internally till the last instance of such PresetHandler dies. @@ -157,10 +157,10 @@ class PresetHandler /** @short provides access to the current working storages. @descr Working storages are the "lowest" storages, where the - preset and target files exists. + preset and target files exist. @return css::embed::XStorage - which the current working storage. + which is the current working storage. */ css::uno::Reference< css::embed::XStorage > getWorkingStorageUser() const; @@ -168,10 +168,10 @@ class PresetHandler the specified child storage and return it. @param xChild - the child storage where a paranet storage should be searched for. + the child storage where a parent storage should be searched for. @return css::embed::XStorage - A valid storage if a paranet exists. NULL otherwise. + A valid storage if a parent exists. NULL otherwise. */ css::uno::Reference< css::embed::XStorage > getParentStorageShare(); css::uno::Reference< css::embed::XStorage > getParentStorageUser (); @@ -180,20 +180,20 @@ class PresetHandler work on a new type of configuration sets. @param eConfigType - differ between global or module dependent configuration. + differs between global or module dependent configuration. @param sResourceType - differ between menubar/toolbar/accelerator/... configuration. + differs between menubar/toolbar/accelerator/... configuration. @param sModule if sResourceType is set to a module dependent configuration, - it address the current application module. + it addresses the current application module. @param xDocumentRoot if sResourceType is set to E_DOCUMENT, this value points to the root storage inside the document, where we can save our configuration files. Note: that's not the real root of the document... - its only a sub storage. But we interpret it as our root storage. + it's only a sub storage. But we interpret it as our root storage. @param rLanguageTag in case this configuration supports localized entries, @@ -231,7 +231,7 @@ class PresetHandler the ALIAS name of the target. @throw css::container::NoSuchElementException - if the specified preset does not exists. + if the specified preset does not exist. @throw css::io::IOException if copying failed. @@ -242,7 +242,7 @@ class PresetHandler /** @short open the specified preset as stream object and return it. - @descr Note: Because presets resist inside the share + @descr Note: Because presets reside inside the share layer, they will be opened readonly every time. @param sPreset @@ -250,14 +250,14 @@ class PresetHandler Accesses the global language-independent storage instead of the preset storage - @return The opened preset stream ... or NULL if the preset does not exists. + @return The opened preset stream ... or NULL if the preset does not exist. */ css::uno::Reference< css::io::XStream > openPreset(std::u16string_view sPreset); /** @short open the specified target as stream object and return it. - @descr Note: Targets resist inside the user + @descr Note: Targets reside inside the user layer. Normally they are opened in read/write mode. But it will be opened readonly automatically if that isn't possible (may be the file is write protected on the system ...). @@ -265,7 +265,7 @@ class PresetHandler @param sTarget the ALIAS name of the target. - @return The opened target stream ... or NULL if the target does not exists + @return The opened target stream ... or NULL if the target does not exist or couldn't be created as new one. */ css::uno::Reference< css::io::XStream > openTarget( @@ -276,7 +276,7 @@ class PresetHandler @descr We have to call commit on all cached sub storages on the path from the root storage upside down to the working storage - (which are not really used, but required to be holded alive!). + (which are not really used, but required to be held alive!). */ void commitUserChanges(); @@ -333,9 +333,9 @@ class PresetHandler /** @short try to find the specified locale inside list of possible ones. @descr The list of possible locale values was e.g. retrieved from the system - (configuration, directory listing etcpp). The locale normally represent - the current office locale. This method search for a suitable item by using - different algorithm. + (configuration, directory listing etcpp). The locale normally represents + the current office locale. This method searches for a suitable item by using + different algorithms: a) exact search b) search with using fallbacks @@ -344,7 +344,7 @@ class PresetHandler @param rLanguageTag [IN ] the current office locale, which should be searched inside lLocalizedValues. - [OUT] in case fallbacks was allowed, it contains afterwards the fallback locale. + [OUT] in case fallbacks were allowed, it contains afterwards the fallback locale. @param bAllowFallbacks enable/disable using of fallbacks @@ -359,9 +359,9 @@ class PresetHandler /** @short open a config path ignoring errors (catching exceptions). @descr We catch only normal exceptions here - no runtime exceptions. - Further the path itself is tries in different versions (using locale + Further the path itself is tried in different versions (using locale specific attributes). - e.g. "path/e-US" => "path/en" => "path/de" + e.g. "path/en-US" => "path/en" => "path/de" @param sPath the configuration path, which should be opened. diff --git a/framework/source/inc/loadenv/loadenv.hxx b/framework/source/inc/loadenv/loadenv.hxx index 38bfab20e393..48705d24f0da 100644 --- a/framework/source/inc/loadenv/loadenv.hxx +++ b/framework/source/inc/loadenv/loadenv.hxx @@ -32,7 +32,7 @@ /** @short enable/disable special features of a load request. - @desrc Such features must outcome without + @descr Such features must outcome without any special parameters. To make enabling/disabling of features very easy (e.g. at the ctor of @@ -75,7 +75,7 @@ public: model-controller-view paradigm can be loaded into a frame. Such contents are classified as E_CAN_BE_LOADED. - But e.g. for the dispatch framework exists special ContentHandler + But e.g. for the dispatch framework exist special ContentHandler objects, which can load a content in "non visible" mode ... and do not need a target frame for its operation. Such ContentHandler e.g. plays sounds. @@ -99,7 +99,7 @@ private: mutable osl::Mutex m_mutex; /** @short reference to a uno service manager, which must be used - to created on needed services on demand. + to create needed services on demand. */ css::uno::Reference< css::uno::XComponentContext > m_xContext; @@ -112,9 +112,9 @@ private: @descr Note: This reference will be empty if loading failed or a non visible content was loaded! - It can be the same frame as m_xBaseFrame it describe, in case + It can be the same frame as m_xBaseFrame it describes, in case the target "_self", "" or the search flag "SELF" was used. - Otherwise it's the new created or recycled frame, which was + Otherwise it's the newly created or recycled frame, which was used for loading and contains further the new component. Please use method getTarget() or getTargetComponent() @@ -128,7 +128,7 @@ private: */ OUString m_sTarget; - /** @short if m_sTarget is not a special one, this flags regulate searching + /** @short if m_sTarget is not a special one, these flags regulate searching of a suitable one. */ sal_Int32 m_nSearchFlags; @@ -152,7 +152,7 @@ private: /** @short classify the content, which should be loaded by this instance. */ EContentType m_eContentType; - /** @short it indicates, that the member m_xTargetFrame was new created for this + /** @short it indicates, that the member m_xTargetFrame was newly created for this load request and must be closed in case loading (not handling!) operation failed. The default value is sal_False! */ @@ -160,13 +160,13 @@ private: /** @short it indicates, that the old document (which was located inside m_xBaseFrame in combination with the m_sTarget value "_self") was suspended. - Normally it will be replaced by the new loaded document. But in case + Normally it will be replaced by the newly loaded document. But in case loading (not handling!) failed, it must be reactivated. The default value is sal_False! */ bool m_bReactivateControllerOnError; - /** @short it holds one (!) asynchronous used contenthandler or frameloader + /** @short it holds one (!) asynchronously used contenthandler or frameloader alive, till the asynchronous operation will be finished. */ css::uno::Reference< css::uno::XInterface > m_xAsynchronousJob; @@ -199,7 +199,7 @@ public: @param xContext reference to a uno service manager, which can be used internally - to create on needed services on demand. + to create needed services on demand. @throw Currently there is no reason to throw such exception! @@ -232,12 +232,12 @@ public: synchronisation methods or callbacks. There is no direct return value possible here. Because it depends - from the usage of this instance! E.g. for loading a "visible component" + on the usage of this instance! E.g. for loading a "visible component" a frame with a controller/model inside can be possible. For loading - of a "non visible component" only an information about a successfully start + of a "non visible component" only an information about a successful start can be provided. Further it can't be guaranteed, that the internal process runs synchronous. - that's why we prefer using of specialized methods afterwards e.g. to: + That's why we prefer using of specialized methods afterwards e.g. to: - wait till the internal job will be finished and get the results - or to let it run without any further control from outside. @@ -252,18 +252,18 @@ public: points to the frame which must be used as start point for target search. @param sTarget - regulate searching/creating of frames, which should contain the + regulates searching/creating of frames, which should contain the new loaded component afterwards. @param nSearchFlags - regulate searching of targets, if sTarget is not a special one. + regulates searching of targets, if sTarget is not a special one. @param eFeature - flag field, which enable/disable special features of this + flag field, which enables/disables special features of this new instance for following load call. - @throw A LoadEnvException e.g. if another load operation is till in progress - or initialization of a new one fail by other reasons. + @throw A LoadEnvException e.g. if another load operation is still in progress + or initialization of a new one fails for other reasons. The real reason, a suitable message and ID will be given here immediately. @throw A RuntimeException in case any internal process indicates, that @@ -286,7 +286,7 @@ public: @param nTimeout specify a timeout in [ms]. - A value 0 let it wait forever! + A value 0 lets it wait forever! @return sal_True if the started load process could be finished in time; sal_False if the specified time was over. @@ -349,14 +349,14 @@ public: /** TODO document me ... */ css::uno::Reference< css::uno::XInterface > impl_searchLoader(); - /** @short it means; show the frame, bring it to front, + /** @short it means: show the frame, bring it to front, might set the right icon etcpp. in case loading was - successfully or reactivate a might existing old document or + successful or reactivate a might existing old document or close the frame if it was created before in case loading failed. @throw A LoadEnvException only in cases, where an internal error indicates, that the complete load environment seems to be not usable in general. - In such cases a RuntimeException would be to hard for the outside code :-) + In such cases a RuntimeException would be too hard for the outside code :-) @throw A RuntimeException in case any internal process indicates, that the whole runtime can't be used any longer. @@ -368,14 +368,14 @@ private: /** @short tries to detect the type and the filter of the specified content. - @descr This method update the available media descriptor of this instance, - so it contains the right type, a corresponding filter, may a + @descr This method updates the available media descriptor of this instance, + so it contains the right type, a corresponding filter, maybe a valid frame loader etc. In case detection failed, this descriptor is corrected first, before a suitable exception will be thrown. (Excepting a RuntimeException occurrence!) @attention Not all types we know, are supported by filters. So it does not - indicates an error, if no suitable filter(loader etcpp will be found + indicate an error, if no suitable filter/loader etcpp will be found for a type. But a type must be detected for the specified content. Otherwise it's an error and loading can't be finished successfully. @@ -391,9 +391,9 @@ private: @descr It searches for a suitable content handler object, registered for the detected content type (must be done before by calling impl_detectTypeAndFilter()). Because such handler does not depend - from a real target frame, location of such frame will be + on a real target frame, location of such frame will be suppressed here. - In case handle failed all new created resources will be + In case handling failed all newly created resources will be removed before a suitable exception is thrown. (Excepting a RuntimeException occurrence!) @@ -426,13 +426,13 @@ private: /** @short checks if the specified content is already loaded. - @descr It depends from the set target information, if such + @descr It depends on the set target information, if such search is allowed or not! So this method checks first, if the target is the special one "_default". If not it returns with an empty result immediately! In case search is allowed, an existing document with the same URL is searched. If it could be found, the corresponding - view will get the focus and this method return the corresponding frame. + view will get the focus and this method returns the corresponding frame. Optional jumpmarks will be accepted here too. So the view of the document will be updated to show the position inside the document, which is related to the jumpmark. @@ -442,7 +442,7 @@ private: @throw A LoadEnvException only in cases, where an internal error indicates, that the complete load environment seems to be not usable in general. - In such cases a RuntimeException would be to hard for the outside code :-) + In such cases a RuntimeException would be too hard for the outside code :-) @throw A RuntimeException in case any internal process indicates, that the whole runtime can't be used any longer. @@ -453,9 +453,9 @@ private: for this load request. @descr Because this special feature is bound to the target specifier "_default" - its checked inside first. If it's not set => this method return an empty + it's checked inside first. If it's not set => this method returns an empty reference. Otherwise any currently existing frame will be analyzed, if - it can be used here. The following rules exists: + it can be used here. The following rules exist:
  • The frame must be empty ...
  • @@ -468,11 +468,11 @@ private: If a suitable target is located it will be locked. That's why the last rule exists! If this method returns a valid frame reference, it was locked to be usable for this load request only. (Don't forget to reset this state later!) - Concurrent LoadEnv instances can synchronize her work be using such locks :-) HOPEFULLY + Concurrent LoadEnv instances can synchronize their work by using such locks :-) HOPEFULLY @throw A LoadEnvException only in cases, where an internal error indicates, that the complete load environment seems to be not usable in general. - In such cases a RuntimeException would be to hard for the outside code :-) + In such cases a RuntimeException would be too hard for the outside code :-) @throw A RuntimeException in case any internal process indicates, that the whole runtime can't be used any longer. @@ -488,9 +488,9 @@ private: visible frames only! b) If the document was already shown (e.g. by our progress implementation) we do nothing here. The reason behind: The document was already shown... - and it was already make a top window... - If the user activated another frame inbetween (because loading needed some time) - it's not allowed to disturb the user again. Then the frame must resists in the background. + and it was already made a top window... + If the user activated another frame in between (because loading needed some time) + it's not allowed to disturb the user again. Then the frame must reside in the background. c) If the frame was not shown before... but loading of a visible document into this frame was finished... we need both actions: setVisible() and toFront(). @@ -498,10 +498,10 @@ private: points to the container window of a frame. @param bForceToFront - if it's set to sal_False... showing of the window is done more intelligent. + if it's set to sal_False... showing of the window is done more intelligently. setVisible() is called only if the window was not shown before. This mode is needed by b) and c) - If it's set to sal_True... both actions has to be done: setVisible(), toFront()! + If it's set to sal_True... both actions have to be done: setVisible(), toFront()! This mode is needed by a) */ static void impl_makeFrameWindowVisible(const css::uno::Reference< css::awt::XWindow >& xWindow , diff --git a/framework/source/jobs/job.cxx b/framework/source/jobs/job.cxx index 26f5fe6b8df8..1d6fe5d80ee0 100644 --- a/framework/source/jobs/job.cxx +++ b/framework/source/jobs/job.cxx @@ -39,8 +39,8 @@ namespace framework{ /** @short standard ctor - @descr It initialize this new instance. But it set some generic parameters here only. - Specialized information (e.g. the alias or service name ofthis job) will be set + @descr It initializes this new instance. But it sets some generic parameters here only. + Specialized information (e.g. the alias or service name of this job) will be set later using the method setJobData(). @param xContext @@ -66,8 +66,8 @@ Job::Job( /*IN*/ const css::uno::Reference< css::uno::XComponentContext >& xCont /** @short standard ctor - @descr It initialize this new instance. But it set some generic parameters here only. - Specialized information (e.g. the alias or service name ofthis job) will be set + @descr It initializes this new instance. But it sets some generic parameters here only. + Specialized information (e.g. the alias or service name of this job) will be set later using the method setJobData(). @param xContext @@ -104,7 +104,7 @@ Job::~Job() @short set (or delete) a listener for sending dispatch result events @descr Because this object is used in a wrapped mode ... the original listener for such events can't be registered here directly. Because the - listener expect to get the original object given as source of the event. + listener expects to get the original object given as source of the event. That's why we get this source here too, to fake(!) it at sending time! @param xListener @@ -186,7 +186,7 @@ void Job::execute( /*IN*/ const css::uno::Sequence< css::beans::NamedValue >& lD css::uno::Reference< css::task::XJob > xSJob; css::uno::Sequence< css::beans::NamedValue > lJobArgs = impl_generateJobArgs(lDynamicArgs); - // It's necessary to hold us self alive! + // It's necessary to hold ourselves alive! // Otherwise we might die by ref count ... css::uno::Reference< css::task::XJobListener > xThis(this); @@ -213,7 +213,7 @@ void Job::execute( /*IN*/ const css::uno::Sequence< css::beans::NamedValue >& lD /* SAFE { */ // Note: Result handling was already done inside the callback! } - // execute it synchron + // execute it synchronously else if (xSJob.is()) { css::uno::Any aResult; @@ -246,7 +246,7 @@ void Job::execute( /*IN*/ const css::uno::Sequence< css::beans::NamedValue >& lD // but we disagreed with that by throwing a veto exception... // and got the ownership... // we have to close the resource frame or model now - - // and to disable ourself! + // and to disable ourselves! if (m_bPendingCloseFrame) { m_bPendingCloseFrame = false; @@ -326,11 +326,11 @@ void Job::die() /** @short generates list of arguments for job execute @descr There exist a set of information, which can be needed by a job. - a) it's static configuration data (Equals for all jobs. ) - b) it's specific configuration data (Different for every job.) + a) its static configuration data (Equal for all jobs. ) + b) its specific configuration data (Different for every job.) c) some environment values (e.g. the frame, for which this job was started) d) any other dynamic data (e.g. parameters of a dispatch() request) - We collect all this information and generate one list which include all others. + We collect all this information and generate one list which includes all others. @param lDynamicArgs list of dynamic arguments (given by a corresponding dispatch() call) @@ -345,7 +345,7 @@ css::uno::Sequence< css::beans::NamedValue > Job::impl_generateJobArgs( /*IN*/ c /* SAFE { */ SolarMutexClearableGuard aReadLock; - // the real structure of the returned list depends from the environment of this job! + // the real structure of the returned list depends on the environment of this job! JobData::EMode eMode = m_aJobCfg.getMode(); // Create list of environment variables. This list must be part of the @@ -456,7 +456,7 @@ void Job::impl_reactForJobResult( /*IN*/ const css::uno::Any& aResult ) JobData::EEnvironment eEnvironment = m_aJobCfg.getEnvironment(); // write back the job specific configuration data ... - // If the environment allow it and if this job has a configuration! + // If the environment allows it and if this job has a configuration! if ( (m_aJobCfg.hasConfig() ) && (aAnalyzedResult.existPart(JobResult::E_ARGUMENTS)) @@ -484,8 +484,8 @@ void Job::impl_reactForJobResult( /*IN*/ const css::uno::Any& aResult ) (aAnalyzedResult.existPart(JobResult::E_DISPATCHRESULT)) ) { - // Attention: Because the listener expect that the original object send this event ... - // and we nor the job are the right ones ... + // Attention: Because the listener expects that the original object sends this event ... + // and neither we nor the job are the right ones ... // our user has set itself before. So we can fake this source address! css::frame::DispatchResultEvent aEvent = aAnalyzedResult.getDispatchResult(); aEvent.Source = m_xResultSourceFake; @@ -496,13 +496,13 @@ void Job::impl_reactForJobResult( /*IN*/ const css::uno::Any& aResult ) /** @short starts listening for office shutdown and closing of our given target frame (if it's a valid reference) - @descr We will register ourself as terminate listener + @descr We will register ourselves as terminate listener at the global desktop instance. That will hold us - alive and additional we get the information, if the - office wish to shutdown. If then an internal job + alive and additionally we get the information, if the + office wishes to shutdown. If then an internal job is running we will have the chance to suppress that - by throwing a veto exception. If our internal wrapped - job finished his work, we can release this listener + by throwing a veto exception. If our internally wrapped + job finished its work, we can release this listener connection. Further we are listener for closing of the (possible valid) @@ -661,9 +661,9 @@ void SAL_CALL Job::jobFinished( /*IN*/ const css::uno::Reference< css::task::XAs m_xJob.clear(); } - // And let the start method "execute()" finishing it's job. + // And let the start method "execute()" finish its job. // But do it every time. So any outside blocking code can finish - // his work too. + // its work too. m_aAsyncWait.set(); } @@ -673,7 +673,7 @@ void SAL_CALL Job::jobFinished( /*IN*/ const css::uno::Reference< css::task::XAs If the internal wrapped job is still in progress, we disagree with that by throwing the right veto exception. If not - we agree. But then we must be aware, that another event notifyTermination() can follow. Then we have no chance to do the same. Then we have to - accept that and stop our work instandly. + accept that and stop our work instantly. @param aEvent describes the broadcaster and must be the desktop instance @@ -720,7 +720,7 @@ void SAL_CALL Job::queryTermination( /*IN*/ const css::lang::EventObject& ) void SAL_CALL Job::notifyTermination( /*IN*/ const css::lang::EventObject& ) { die(); - // Do nothing else here. Our internal resources was released ... + // Do nothing else here. Our internal resources were released ... } /** @@ -729,7 +729,7 @@ void SAL_CALL Job::notifyTermination( /*IN*/ const css::lang::EventObject& ) If the internal wrapped job is still in progress, we disagree with that by throwing the right veto exception. If not - we agree. But then we must be aware, that another event notifyClosing() can follow. Then we have no chance to do the same. Then we have to - accept that and stop our work instandly. + accept that and stop our work instantly. @param aEvent describes the broadcaster and must be the frame instance @@ -786,7 +786,7 @@ void SAL_CALL Job::queryClosing( const css::lang::EventObject& aEvent , { // analyze event source - to find out, which resource called queryClosing() at this // job wrapper. We must bind a "pending close" request to this resource. - // Closing of the corresponding resource will be done if our internal job finish it's work. + // Closing of the corresponding resource will be done if our internal job finishes its work. m_bPendingCloseFrame = (m_xFrame.is() && aEvent.Source == m_xFrame); m_bPendingCloseModel = (m_xModel.is() && aEvent.Source == m_xModel); @@ -798,8 +798,8 @@ void SAL_CALL Job::queryClosing( const css::lang::EventObject& aEvent , // No veto ... // But don't call die() here or free our internal member. // This must be done inside notifyClosing() only. Otherwise the - // might stopped job has no chance to return its results or - // call us back. We must give him the chance to finish it's work successfully. + // maybe stopped job has no chance to return its results or + // call us back. We must give it the chance to finish its work successfully. } /** @@ -813,7 +813,7 @@ void SAL_CALL Job::queryClosing( const css::lang::EventObject& aEvent , void SAL_CALL Job::notifyClosing( const css::lang::EventObject& ) { die(); - // Do nothing else here. Our internal resources was released ... + // Do nothing else here. Our internal resources were released ... } /** @@ -822,7 +822,7 @@ void SAL_CALL Job::notifyClosing( const css::lang::EventObject& ) running processes hardly. @param aEvent - describe the broadcaster + describes the broadcaster */ void SAL_CALL Job::disposing( const css::lang::EventObject& aEvent ) { @@ -849,7 +849,7 @@ void SAL_CALL Job::disposing( const css::lang::EventObject& aEvent ) /* } SAFE */ die(); - // Do nothing else here. Our internal resources was released ... + // Do nothing else here. Our internal resources were released ... } } // namespace framework diff --git a/framework/source/jobs/jobdispatch.cxx b/framework/source/jobs/jobdispatch.cxx index a51d248c601f..36cb87f36b09 100644 --- a/framework/source/jobs/jobdispatch.cxx +++ b/framework/source/jobs/jobdispatch.cxx @@ -48,10 +48,10 @@ namespace { @descr Such dispatch object will be used by the generic dispatch mechanism if a URL "vnd.sun.star.job:alias=" occurs. Then an instance of this class will be created and used. - This new instance will be called within his method + This new instance will be called within its method dispatch() or dispatchWithNotification() for executing the real job. We do it, control the life cycle of this internal - wrapped job and inform any interested listener if it finish. + wrapped job and inform any interested listener if it finishes. */ class JobDispatch : public ::cppu::WeakImplHelper< css::lang::XServiceInfo @@ -128,7 +128,7 @@ public: /** @short standard ctor - @descr It initialize this new instance. + @descr It initializes this new instance. @param xContext reference to the uno service manager @@ -151,7 +151,7 @@ JobDispatch::~JobDispatch() /** @short implementation of XInitialization - @descr A protocol handler can provide this functionality, if it wish to get additional information + @descr A protocol handler can provide this functionality, if it wishes to get additional information about the context it runs. In this case the frame reference would be given by the outside code. @param lArguments @@ -182,7 +182,7 @@ void SAL_CALL JobDispatch::initialize( const css::uno::Sequence< css::uno::Any > /** @short implementation of XDispatchProvider::queryDispatches() - @descr Every protocol handler will be asked for his agreement, if a URL was queried + @descr Every protocol handler will be asked for its agreement, if a URL was queried for which this handler is registered. It's the chance for this handler to validate the given URL and return a dispatch object (may be itself) or not. @@ -300,7 +300,7 @@ void JobDispatch::impl_dispatchEvent( /*IN*/ const OUString& { // get list of all enabled jobs // The called static helper methods read it from the configuration and - // filter disabled jobs using it's time stamp values. + // filter disabled jobs using its timestamp values. std::vector< OUString > lJobs = JobData::getEnabledJobsForEvent(m_xContext, sEvent); css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY ); @@ -371,7 +371,7 @@ void JobDispatch::impl_dispatchService( /*IN*/ const OUString& /*Attention! Jobs implements interfaces and dies by ref count! And freeing of such uno object is done by uno itself. - So we have to use dynamic memory everytimes. + So we have to use dynamic memory every time. */ rtl::Reference pJob = new Job(m_xContext, m_xFrame); pJob->setJobData(aCfg); @@ -428,7 +428,7 @@ void JobDispatch::impl_dispatchAlias( /*IN*/ const OUString& /** @short implementation of XDispatch::dispatch() - @descr Because the methods dispatch() and dispatchWithNotification() are different in her parameters + @descr Because the methods dispatch() and dispatchWithNotification() are different in their parameters only, we can forward this request to dispatchWithNotification() by using an empty listener! @param aURL diff --git a/framework/source/jobs/jobexecutor.cxx b/framework/source/jobs/jobexecutor.cxx index 4acf2bec24da..431b390717ab 100644 --- a/framework/source/jobs/jobexecutor.cxx +++ b/framework/source/jobs/jobexecutor.cxx @@ -114,7 +114,7 @@ public: /** @short standard ctor - @descr It initialize this new instance. + @descr It initializes this new instance. @param xContext reference to the uno service manager @@ -182,7 +182,7 @@ void JobExecutor::disposing(std::unique_lock& /*rGuard*/) { @short implementation of XJobExecutor interface @descr We use the given event to locate any registered job inside our configuration and execute it. Further we control the lifetime of it and suppress - shutdown of the office till all jobs was finished. + shutdown of the office till all jobs were finished. @param sEvent is used to locate registered jobs @@ -196,7 +196,7 @@ void SAL_CALL JobExecutor::trigger( const OUString& sEvent ) std::unique_lock g(m_aMutex); // Optimization! - // Check if the given event name exist inside configuration and reject wrong requests. + // Check if the given event name exists inside configuration and reject wrong requests. // This optimization suppress using of the cfg api for getting event and job descriptions ... if (std::find(m_lEvents.begin(), m_lEvents.end(), sEvent) == m_lEvents.end()) return; @@ -205,7 +205,7 @@ void SAL_CALL JobExecutor::trigger( const OUString& sEvent ) // get list of all enabled jobs // The called static helper methods read it from the configuration and - // filter disabled jobs using it's time stamp values. + // filter disabled jobs using its timestamp values. std::vector< OUString > lJobs = JobData::getEnabledJobsForEvent(m_xContext, sEvent); // step over all enabled jobs and execute it @@ -219,7 +219,7 @@ void SAL_CALL JobExecutor::trigger( const OUString& sEvent ) /*Attention! Jobs implements interfaces and dies by ref count! And freeing of such uno object is done by uno itself. - So we have to use dynamic memory everytimes. + So we have to use dynamic memory every time. */ rtl::Reference pJob = new Job(m_xContext, css::uno::Reference< css::frame::XFrame >()); pJob->setJobData(aCfg); @@ -237,8 +237,8 @@ void SAL_CALL JobExecutor::notifyEvent( const css::document::EventObject& aEvent ::std::vector< JobData::TJob2DocEventBinding > lJobs; // Optimization! - // Check if the given event name exist inside configuration and reject wrong requests. - // This optimization suppress using of the cfg api for getting event and job descriptions. + // Check if the given event name exists inside configuration and reject wrong requests. + // This optimization suppresses using of the cfg api for getting event and job descriptions. // see using of m_lEvents.find() below ... // retrieve event context from event source @@ -253,7 +253,7 @@ void SAL_CALL JobExecutor::notifyEvent( const css::document::EventObject& aEvent { std::unique_lock g(m_aMutex); - // Special feature: If the events "OnNew" or "OnLoad" occurs - we generate our own event "onDocumentOpened". + // Special feature: If the events "OnNew" or "OnLoad" occur - we generate our own event "onDocumentOpened". if ( (aEvent.EventName == "OnNew") || (aEvent.EventName == "OnLoad") @@ -263,7 +263,7 @@ void SAL_CALL JobExecutor::notifyEvent( const css::document::EventObject& aEvent JobData::appendEnabledJobsForEvent(m_xContext, EVENT_ON_DOCUMENT_OPENED, lJobs); } - // Special feature: If the events "OnCreate" or "OnLoadFinished" occurs - we generate our own event "onDocumentAdded". + // Special feature: If the events "OnCreate" or "OnLoadFinished" occur - we generate our own event "onDocumentAdded". if ( (aEvent.EventName == "OnCreate") || (aEvent.EventName == "OnLoadFinished") @@ -295,7 +295,7 @@ void SAL_CALL JobExecutor::notifyEvent( const css::document::EventObject& aEvent /*Attention! Jobs implements interfaces and dies by ref count! And freeing of such uno object is done by uno itself. - So we have to use dynamic memory everytimes. + So we have to use dynamic memory every time. */ css::uno::Reference< css::frame::XModel > xModel(aEvent.Source, css::uno::UNO_QUERY); pJob = new Job(m_xContext, xModel); @@ -340,7 +340,7 @@ void SAL_CALL JobExecutor::elementReplaced( const css::container::ContainerEvent // I'm not interested on changed items :-) } -/** @short the used cfg changes notifier wish to be released in its reference. +/** @short the used cfg changes notifier wishes to be released in its reference. @descr We close our internal used configuration instance to free this reference. @@ -351,8 +351,8 @@ void SAL_CALL JobExecutor::elementReplaced( const css::container::ContainerEvent the global event broadcaster service. But we don't hold any reference to this service which can or must be released. Because this broadcaster itself is a one instance service too, we can ignore this request. On the other side we must release our internal CFG - reference... SOLUTION => check the given event source and react only, if it's our internal - hold configuration object! + reference... SOLUTION => check the given event source and react only, if it's our internally + held configuration object! */ void SAL_CALL JobExecutor::disposing( const css::lang::EventObject& aEvent ) { diff --git a/framework/source/loadenv/loadenv.cxx b/framework/source/loadenv/loadenv.cxx index 201ddaaf5ce5..9d45b5941053 100644 --- a/framework/source/loadenv/loadenv.cxx +++ b/framework/source/loadenv/loadenv.cxx @@ -1814,7 +1814,7 @@ void LoadEnv::impl_applyPersistentWindowState(const css::uno::Reference< css::aw return; SystemWindow* pSystemWindow = static_cast(pWindowCheck.get()); - pSystemWindow->SetWindowState(sWindowState); + pSystemWindow->SetWindowState(vcl::WindowData(sWindowState)); // <- SOLAR SAFE } } diff --git a/framework/source/loadenv/targethelper.cxx b/framework/source/loadenv/targethelper.cxx index 7c06521da6d3..5e4c1e482687 100644 --- a/framework/source/loadenv/targethelper.cxx +++ b/framework/source/loadenv/targethelper.cxx @@ -46,7 +46,7 @@ bool TargetHelper::matchSpecialTarget(std::u16string_view sCheckTarget , bool TargetHelper::isValidNameForFrame(std::u16string_view sName) { // some special targets are really special ones :-) - // E.g. the are really used to locate one frame inside the frame tree. + // E.g. they are really used to locate one frame inside the frame tree. if ( (sName.empty() ) || (TargetHelper::matchSpecialTarget(sName, ESpecialTarget::HelpTask)) || @@ -54,8 +54,8 @@ bool TargetHelper::isValidNameForFrame(std::u16string_view sName) ) return true; - // all other names must be checked more general - // special targets starts with a "_". + // all other names must be checked more generally + // special targets start with a "_". return (sName.find('_') != 0); } diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx index 1518e973befb..f0242359a7ae 100644 --- a/framework/source/services/autorecovery.cxx +++ b/framework/source/services/autorecovery.cxx @@ -94,7 +94,6 @@ #include #include -#include #include #include #include diff --git a/framework/source/services/pathsettings.cxx b/framework/source/services/pathsettings.cxx index 4cf707ce30f3..2eb67f99abe3 100644 --- a/framework/source/services/pathsettings.cxx +++ b/framework/source/services/pathsettings.cxx @@ -44,7 +44,7 @@ #include #include -#include +#include #include #include #include @@ -87,15 +87,14 @@ sal_Int32 impl_getPropGroup(sal_Int32 nID) disable it in case only the new schema must be used. */ -typedef ::comphelper::WeakComponentImplHelper< - css::lang::XServiceInfo, - css::lang::XInitialization, - css::util::XChangesListener, // => XEventListener - css::util::XPathSettings> // => XPropertySet - PathSettings_BASE; +using PathSettings_BASE = comphelper::OPropertyImplHelper< + comphelper::WeakComponentImplHelper< + css::lang::XServiceInfo, + css::lang::XInitialization, + css::util::XChangesListener, // => XEventListener + css::util::XPathSettings>>; // => XPropertySet class PathSettings : public PathSettings_BASE - , public comphelper::OPropertySetHelper { struct PathInfo { @@ -163,10 +162,6 @@ private: public: - /** initialize a new instance of this class. - Attention: It's necessary for right function of this class, that the order of base - classes is the right one. Because we transfer information from one base to another - during this ctor runs! */ explicit PathSettings(css::uno::Reference< css::uno::XComponentContext > xContext); /** free all used resources ... if it was not already done. */ @@ -187,16 +182,6 @@ public: return {u"com.sun.star.util.PathSettings"_ustr}; } - // XInterface - virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& type) override; - virtual void SAL_CALL acquire() noexcept override - { OWeakObject::acquire(); } - virtual void SAL_CALL release() noexcept override - { OWeakObject::release(); } - - // XTypeProvider - virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override; - // css::util::XChangesListener virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent& aEvent) override; @@ -311,22 +296,6 @@ public: virtual void SAL_CALL setBasePathUserLayer(const OUString& p1) override { setStringProperty(u"UserConfig"_ustr, p1); } - /** - * overrides to resolve inheritance ambiguity - */ - virtual void SAL_CALL setPropertyValue(const OUString& p1, const css::uno::Any& p2) override - { ::comphelper::OPropertySetHelper::setPropertyValue(p1, p2); } - virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& p1) override - { return ::comphelper::OPropertySetHelper::getPropertyValue(p1); } - virtual void SAL_CALL addPropertyChangeListener(const OUString& p1, const css::uno::Reference& p2) override - { ::comphelper::OPropertySetHelper::addPropertyChangeListener(p1, p2); } - virtual void SAL_CALL removePropertyChangeListener(const OUString& p1, const css::uno::Reference& p2) override - { ::comphelper::OPropertySetHelper::removePropertyChangeListener(p1, p2); } - virtual void SAL_CALL addVetoableChangeListener(const OUString& p1, const css::uno::Reference& p2) override - { ::comphelper::OPropertySetHelper::addVetoableChangeListener(p1, p2); } - virtual void SAL_CALL removeVetoableChangeListener(const OUString& p1, const css::uno::Reference& p2) override - { ::comphelper::OPropertySetHelper::removeVetoableChangeListener(p1, p2); } - // XInitialization virtual void SAL_CALL initialize(const css::uno::Sequence& rArguments) override; @@ -416,7 +385,7 @@ private: const PathSettings::PathInfo* pPathOld, const PathSettings::PathInfo* pPathNew); - // OPropertySetHelper + // OPropertyImplHelper virtual bool convertFastPropertyValue( std::unique_lock& g, css::uno::Any& aConvertedValue, css::uno::Any& aOldValue, sal_Int32 nHandle, @@ -425,12 +394,8 @@ private: const css::uno::Any& aValue ) override; virtual void getFastPropertyValue( std::unique_lock& g, css::uno::Any& aValue, sal_Int32 nHandle ) const override; - // Avoid: - // warning: 'virtual css::uno::Any cppu::OPropertySetHelper::getFastPropertyValue(sal_Int32)' was hidden [-Woverloaded-virtual] - // warning: by ‘virtual void {anonymous}::PathSettings::getFastPropertyValue(css::uno::Any&, sal_Int32) const’ [-Woverloaded-virtual] - using comphelper::OPropertySetHelper::getFastPropertyValue; + using PathSettings_BASE::getFastPropertyValue; virtual ::cppu::IPropertyArrayHelper& getInfoHelper() override; - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override; /** factory methods to guarantee right (but on demand) initialized members ... */ css::uno::Reference< css::util::XStringSubstitution > fa_getSubstitution(std::unique_lock& g); @@ -439,9 +404,7 @@ private: }; PathSettings::PathSettings( css::uno::Reference< css::uno::XComponentContext > xContext ) - : PathSettings_BASE() - , comphelper::OPropertySetHelper() - , m_xContext (std::move(xContext)) + : m_xContext(std::move(xContext)) { } @@ -451,8 +414,10 @@ PathSettings::~PathSettings() disposing(g); } -void PathSettings::disposing(std::unique_lock& /*g*/) +void PathSettings::disposing(std::unique_lock& g) { + disposePropertySetListeners(g); + css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(m_xCfgNew, css::uno::UNO_QUERY); if (xBroadcaster.is()) @@ -466,22 +431,6 @@ void PathSettings::disposing(std::unique_lock& /*g*/) m_pPropHelp.reset(); } -css::uno::Any SAL_CALL PathSettings::queryInterface( const css::uno::Type& _rType ) -{ - css::uno::Any aRet = PathSettings_BASE::queryInterface( _rType ); - if ( !aRet.hasValue() ) - aRet = ::comphelper::OPropertySetHelper::queryInterface( _rType ); - return aRet; -} - -css::uno::Sequence< css::uno::Type > SAL_CALL PathSettings::getTypes( ) -{ - return comphelper::concatSequences( - PathSettings_BASE::getTypes(), - ::comphelper::OPropertySetHelper::getTypes() - ); -} - void SAL_CALL PathSettings::changesOccurred(const css::util::ChangesEvent& aEvent) { std::unique_lock g(m_aMutex); @@ -523,7 +472,7 @@ void SAL_CALL PathSettings::disposing(const css::lang::EventObject& aSource) OUString PathSettings::getStringProperty(const OUString& p1) { - css::uno::Any a = ::comphelper::OPropertySetHelper::getPropertyValue(p1); + css::uno::Any a = getPropertyValue(p1); OUString s; a >>= s; return s; @@ -531,7 +480,7 @@ OUString PathSettings::getStringProperty(const OUString& p1) void PathSettings::setStringProperty(const OUString& p1, const OUString& p2) { - ::comphelper::OPropertySetHelper::setPropertyValue(p1, css::uno::Any(p2)); + setPropertyValue(p1, css::uno::Any(p2)); } void PathSettings::readAll() @@ -1344,11 +1293,6 @@ void PathSettings::getFastPropertyValue(std::unique_lock& g, return *m_pPropHelp; } -css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PathSettings::getPropertySetInfo() -{ - return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); -} - css::uno::Reference< css::util::XStringSubstitution > PathSettings::fa_getSubstitution(std::unique_lock& g) { css::uno::Reference< css::util::XStringSubstitution > xSubst = m_xSubstitution; diff --git a/framework/source/uielement/FixedImageToolbarController.cxx b/framework/source/uielement/FixedImageToolbarController.cxx index 1603fd111574..15965ac4b3c3 100644 --- a/framework/source/uielement/FixedImageToolbarController.cxx +++ b/framework/source/uielement/FixedImageToolbarController.cxx @@ -19,12 +19,13 @@ #include +#include #include #include #include #include -#include #include +#include #include #include #include @@ -88,14 +89,17 @@ FixedImageToolbarController::FixedImageToolbarController( SvtMiscOptions().AddListenerLink(LINK(this, FixedImageToolbarController, MiscOptionsChanged)); } -void SAL_CALL FixedImageToolbarController::dispose() +void FixedImageToolbarController::disposing(std::unique_lock& rGuard) { - SolarMutexGuard aSolarMutexGuard; - SvtMiscOptions().RemoveListenerLink( - LINK(this, FixedImageToolbarController, MiscOptionsChanged)); - m_xToolbar->SetItemWindow(m_nID, nullptr); - m_pFixedImageControl.disposeAndClear(); - ComplexToolbarController::dispose(); + { + comphelper::unique_unlock aUnlock(rGuard); + SolarMutexGuard aSolarMutexGuard; + SvtMiscOptions().RemoveListenerLink( + LINK(this, FixedImageToolbarController, MiscOptionsChanged)); + m_xToolbar->SetItemWindow(m_nID, nullptr); + m_pFixedImageControl.disposeAndClear(); + } + ComplexToolbarController::disposing(rGuard); } void FixedImageToolbarController::executeControlCommand(const css::frame::ControlCommand&) {} diff --git a/framework/source/uielement/FixedTextToolbarController.cxx b/framework/source/uielement/FixedTextToolbarController.cxx index 994a3f707840..2189168a4b09 100644 --- a/framework/source/uielement/FixedTextToolbarController.cxx +++ b/framework/source/uielement/FixedTextToolbarController.cxx @@ -20,11 +20,12 @@ #include #include +#include #include #include #include -#include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -79,12 +80,15 @@ FixedTextToolbarController::FixedTextToolbarController( m_xToolbar->SetItemBits(m_nID, ToolBoxItemBits::AUTOSIZE | m_xToolbar->GetItemBits(m_nID)); } -void SAL_CALL FixedTextToolbarController::dispose() +void FixedTextToolbarController::disposing(std::unique_lock& rGuard) { - SolarMutexGuard aSolarMutexGuard; - m_xToolbar->SetItemWindow(m_nID, nullptr); - m_pFixedTextControl.disposeAndClear(); - ComplexToolbarController::dispose(); + { + comphelper::unique_unlock aUnlock(rGuard); + SolarMutexGuard aSolarMutexGuard; + m_xToolbar->SetItemWindow(m_nID, nullptr); + m_pFixedTextControl.disposeAndClear(); + } + ComplexToolbarController::disposing(rGuard); } Sequence FixedTextToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const diff --git a/framework/source/uielement/comboboxtoolbarcontroller.cxx b/framework/source/uielement/comboboxtoolbarcontroller.cxx index 285f4b4858b2..deb5e80bf63d 100644 --- a/framework/source/uielement/comboboxtoolbarcontroller.cxx +++ b/framework/source/uielement/comboboxtoolbarcontroller.cxx @@ -22,9 +22,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -169,14 +169,15 @@ ComboboxToolbarController::~ComboboxToolbarController() { } -void SAL_CALL ComboboxToolbarController::dispose() +void ComboboxToolbarController::disposing(std::unique_lock& rGuard) { - SolarMutexGuard aSolarMutexGuard; - - m_xToolbar->SetItemWindow( m_nID, nullptr ); - m_pComboBox.disposeAndClear(); - - ComplexToolbarController::dispose(); + { + comphelper::unique_unlock aUnlock(rGuard); + SolarMutexGuard aSolarMutexGuard; + m_xToolbar->SetItemWindow( m_nID, nullptr ); + m_pComboBox.disposeAndClear(); + } + ComplexToolbarController::disposing(rGuard); } Sequence ComboboxToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const diff --git a/framework/source/uielement/complextoolbarcontroller.cxx b/framework/source/uielement/complextoolbarcontroller.cxx index 921d83410d1e..ccb9d0673b60 100644 --- a/framework/source/uielement/complextoolbarcontroller.cxx +++ b/framework/source/uielement/complextoolbarcontroller.cxx @@ -29,6 +29,8 @@ #include #include +#include +#include #include #include #include @@ -63,12 +65,18 @@ ComplexToolbarController::~ComplexToolbarController() { } -void SAL_CALL ComplexToolbarController::dispose() +void ComplexToolbarController::disposing(std::unique_lock& rGuard) { + comphelper::unique_unlock aUnlock(rGuard); SolarMutexGuard aSolarMutexGuard; m_xToolbar->SetItemWindow( m_nID, nullptr ); - svt::ToolboxController::dispose(); + { + // Locking a mess because of order of calls; I don't know if the order is important - I + // just keep it as it was before. + SolarMutexReleaser releaser; + svt::ToolboxController::disposing(o3tl::temporary(std::unique_lock(m_aMutex))); + } m_xURLTransformer.clear(); m_xToolbar.reset(); diff --git a/framework/source/uielement/dropdownboxtoolbarcontroller.cxx b/framework/source/uielement/dropdownboxtoolbarcontroller.cxx index a4de2da2e527..eae3fab0a1cb 100644 --- a/framework/source/uielement/dropdownboxtoolbarcontroller.cxx +++ b/framework/source/uielement/dropdownboxtoolbarcontroller.cxx @@ -22,11 +22,11 @@ #include #include +#include #include #include #include #include -#include #include #include @@ -39,7 +39,7 @@ namespace framework { // Wrapper class to notify controller about events from ListBox. -// Unfortunaltly the events are notified through virtual methods instead +// Unfortunately the events are notified through virtual methods instead // of Listeners. class ListBoxControl final : public InterimItemWindow @@ -144,14 +144,15 @@ DropdownToolbarController::~DropdownToolbarController() { } -void SAL_CALL DropdownToolbarController::dispose() +void DropdownToolbarController::disposing(std::unique_lock& rGuard) { - SolarMutexGuard aSolarMutexGuard; - - m_xToolbar->SetItemWindow( m_nID, nullptr ); - m_pListBoxControl.disposeAndClear(); - - ComplexToolbarController::dispose(); + { + comphelper::unique_unlock aUnlock(rGuard); + SolarMutexGuard aSolarMutexGuard; + m_xToolbar->SetItemWindow( m_nID, nullptr ); + m_pListBoxControl.disposeAndClear(); + } + ComplexToolbarController::disposing(rGuard); } Sequence DropdownToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const diff --git a/framework/source/uielement/edittoolbarcontroller.cxx b/framework/source/uielement/edittoolbarcontroller.cxx index e3cc9b06f9a2..9564c87b4c81 100644 --- a/framework/source/uielement/edittoolbarcontroller.cxx +++ b/framework/source/uielement/edittoolbarcontroller.cxx @@ -22,13 +22,14 @@ #include #include +#include #include #include #include #include #include -#include #include +#include #include using namespace ::com::sun::star; @@ -40,7 +41,7 @@ namespace framework { // Wrapper class to notify controller about events from edit. -// Unfortunaltly the events are notified through virtual methods instead +// Unfortunately the events are notified through virtual methods instead // of Listeners. class EditControl final : public InterimItemWindow @@ -59,7 +60,7 @@ private: DECL_LINK(FocusInHdl, weld::Widget&, void); DECL_LINK(FocusOutHdl, weld::Widget&, void); - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); DECL_LINK(ActivateHdl, weld::Entry&, bool); DECL_LINK(KeyInputHdl, const ::KeyEvent&, bool); }; @@ -101,7 +102,7 @@ void EditControl::dispose() InterimItemWindow::dispose(); } -IMPL_LINK_NOARG(EditControl, ModifyHdl, weld::Entry&, void) +IMPL_LINK_NOARG(EditControl, ModifyHdl, weld::TextWidget&, void) { if (m_pEditToolbarController) m_pEditToolbarController->Modify(); @@ -151,14 +152,15 @@ EditToolbarController::~EditToolbarController() { } -void SAL_CALL EditToolbarController::dispose() +void EditToolbarController::disposing(std::unique_lock& rGuard) { - SolarMutexGuard aSolarMutexGuard; - - m_xToolbar->SetItemWindow( m_nID, nullptr ); - m_pEditControl.disposeAndClear(); - - ComplexToolbarController::dispose(); + { + comphelper::unique_unlock aUnlock(rGuard); + SolarMutexGuard aSolarMutexGuard; + m_xToolbar->SetItemWindow( m_nID, nullptr ); + m_pEditControl.disposeAndClear(); + } + ComplexToolbarController::disposing(rGuard); } Sequence EditToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const diff --git a/framework/source/uielement/fontsizemenucontroller.cxx b/framework/source/uielement/fontsizemenucontroller.cxx index 953814efb475..435c3c1091ad 100644 --- a/framework/source/uielement/fontsizemenucontroller.cxx +++ b/framework/source/uielement/fontsizemenucontroller.cxx @@ -24,19 +24,15 @@ #include #include -#include #include -#include #include #include #include -#include #include #include #include #include -#include #include // Defines @@ -44,9 +40,7 @@ using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::frame; -using namespace com::sun::star::beans; using namespace com::sun::star::util; -using namespace com::sun::star::view; namespace framework { @@ -75,35 +69,6 @@ FontSizeMenuController::~FontSizeMenuController() { } -// private function -OUString FontSizeMenuController::retrievePrinterName( css::uno::Reference< css::frame::XFrame > const & rFrame ) -{ - OUString aPrinterName; - - if ( rFrame.is() ) - { - Reference< XController > xController = m_xFrame->getController(); - if ( xController.is() ) - { - Reference< XPrintable > xPrintable( xController->getModel(), UNO_QUERY ); - if ( xPrintable.is() ) - { - const Sequence< PropertyValue > aPrinterSeq = xPrintable->getPrinter(); - for ( PropertyValue const & prop : aPrinterSeq ) - { - if ( prop.Name == "Name" ) - { - prop.Value >>= aPrinterName; - break; - } - } - } - } - } - - return aPrinterName; -} - // private function void FontSizeMenuController::setCurHeight( tools::Long nHeight, Reference< css::awt::XPopupMenu > const & rPopupMenu ) { @@ -133,24 +98,8 @@ void FontSizeMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu > co { resetPopupMenu( rPopupMenu ); - std::unique_ptr pFontList; - ScopedVclPtr pInfoPrinter; - OUString aPrinterName; - SolarMutexGuard aSolarMutexGuard; - // try to retrieve printer name of document - aPrinterName = retrievePrinterName( m_xFrame ); - if ( !aPrinterName.isEmpty() ) - { - pInfoPrinter.disposeAndReset(VclPtr::Create( aPrinterName )); - if ( pInfoPrinter && pInfoPrinter->GetFontFaceCollectionCount() > 0 ) - pFontList.reset(new FontList( pInfoPrinter.get() )); - } - - if ( !pFontList ) - pFontList.reset(new FontList( Application::GetDefaultDevice() )); - // setup font size array m_aHeightArray.clear(); diff --git a/framework/source/uielement/generictoolbarcontroller.cxx b/framework/source/uielement/generictoolbarcontroller.cxx index 6ae9069fb095..f21d5af33994 100644 --- a/framework/source/uielement/generictoolbarcontroller.cxx +++ b/framework/source/uielement/generictoolbarcontroller.cxx @@ -28,13 +28,13 @@ #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -121,12 +121,12 @@ GenericToolbarController::~GenericToolbarController() { } -void SAL_CALL GenericToolbarController::dispose() +void GenericToolbarController::disposing(std::unique_lock& rGuard) { + svt::ToolboxController::disposing(rGuard); + comphelper::unique_unlock aUnlock(rGuard); SolarMutexGuard aSolarMutexGuard; - svt::ToolboxController::dispose(); - m_pToolbar = nullptr; m_xToolbar.reset(); m_nID = ToolBoxItemId(0); @@ -358,9 +358,9 @@ ImageOrientationController::ImageOrientationController(const ReferenceAddEventListener(LINK(this, ImageOrientationController, WindowEventListener)); } -void ImageOrientationController::dispose() +void ImageOrientationController::disposing(std::unique_lock& rGuard) { - ToolboxController::dispose(); + ToolboxController::disposing(rGuard); VclPtr pWindow = VCLUnoHelper::GetWindow(getParent()); if (pWindow) pWindow->RemoveEventListener(LINK(this, ImageOrientationController, WindowEventListener)); diff --git a/framework/source/uielement/imagebuttontoolbarcontroller.cxx b/framework/source/uielement/imagebuttontoolbarcontroller.cxx index 653038d35825..8af7f3e35e9b 100644 --- a/framework/source/uielement/imagebuttontoolbarcontroller.cxx +++ b/framework/source/uielement/imagebuttontoolbarcontroller.cxx @@ -71,12 +71,6 @@ ImageButtonToolbarController::~ImageButtonToolbarController() { } -void SAL_CALL ImageButtonToolbarController::dispose() -{ - SolarMutexGuard aSolarMutexGuard; - ComplexToolbarController::dispose(); -} - void ImageButtonToolbarController::executeControlCommand( const css::frame::ControlCommand& rControlCommand ) { SolarMutexGuard aSolarMutexGuard; diff --git a/framework/source/uielement/popuptoolbarcontroller.cxx b/framework/source/uielement/popuptoolbarcontroller.cxx index 33d1aacbdc00..fdd5567507ba 100644 --- a/framework/source/uielement/popuptoolbarcontroller.cxx +++ b/framework/source/uielement/popuptoolbarcontroller.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -62,30 +63,31 @@ PopupMenuToolbarController::PopupMenuToolbarController( { } -void SAL_CALL PopupMenuToolbarController::dispose() +void PopupMenuToolbarController::disposing(std::unique_lock& rGuard) { - svt::ToolboxController::dispose(); - - osl::MutexGuard aGuard( m_aMutex ); - if( m_xPopupMenuController.is() ) + svt::ToolboxController::disposing(rGuard); { - css::uno::Reference< css::lang::XComponent > xComponent( - m_xPopupMenuController, css::uno::UNO_QUERY ); - if( xComponent.is() ) + comphelper::unique_unlock aUnlock(rGuard); + if( m_xPopupMenuController.is() ) { - try + css::uno::Reference< css::lang::XComponent > xComponent( + m_xPopupMenuController, css::uno::UNO_QUERY ); + if( xComponent.is() ) { - xComponent->dispose(); + try + { + xComponent->dispose(); + } + catch (...) + {} } - catch (...) - {} + m_xPopupMenuController.clear(); } - m_xPopupMenuController.clear(); - } - m_xContext.clear(); - m_xPopupMenuFactory.clear(); - m_xPopupMenu.clear(); + m_xContext.clear(); + m_xPopupMenuFactory.clear(); + m_xPopupMenu.clear(); + } } void SAL_CALL PopupMenuToolbarController::initialize( @@ -93,7 +95,7 @@ void SAL_CALL PopupMenuToolbarController::initialize( { ToolboxController::initialize( aArguments ); - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_aPopupCommand.getLength() ) m_aPopupCommand = m_aCommandURL; @@ -152,7 +154,7 @@ PopupMenuToolbarController::createPopupWindow() { css::uno::Reference< css::awt::XWindow > xRet; - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_bHasController ) return xRet; @@ -375,8 +377,8 @@ public: // XEventListener virtual void SAL_CALL disposing( const css::lang::EventObject& rEvent ) override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + virtual void disposing(std::unique_lock& rGuard) override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; @@ -523,9 +525,10 @@ void SaveToolbarController::disposing( const css::lang::EventObject& rEvent ) PopupMenuToolbarController::disposing( rEvent ); } -void SaveToolbarController::dispose() +void SaveToolbarController::disposing(std::unique_lock& rGuard) { - PopupMenuToolbarController::dispose(); + PopupMenuToolbarController::disposing(rGuard); + comphelper::unique_unlock aUnlock(rGuard); if ( m_xModifiable.is() ) { m_xModifiable->removeModifyListener( this ); @@ -609,7 +612,7 @@ void SAL_CALL NewToolbarController::initialize( const css::uno::Sequence< css::u { PopupMenuToolbarController::initialize( aArguments ); - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); createPopupMenuController(); } @@ -638,7 +641,7 @@ void SAL_CALL NewToolbarController::statusChanged( const css::frame::FeatureStat void SAL_CALL NewToolbarController::execute( sal_Int16 /*KeyModifier*/ ) { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); OUString aURL, aTarget; if ( m_xPopupMenu.is() && m_nMenuId ) diff --git a/framework/source/uielement/recentfilesmenucontroller.cxx b/framework/source/uielement/recentfilesmenucontroller.cxx index 56fdf9963324..66c8c71016f5 100644 --- a/framework/source/uielement/recentfilesmenucontroller.cxx +++ b/framework/source/uielement/recentfilesmenucontroller.cxx @@ -25,12 +25,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -273,7 +273,8 @@ void RecentFilesMenuController::fillPopupMenu(std::unique_lock& /*rG else { // In all other URLs show the protocol name before the file name - aMenuTitle = INetURLObject::GetSchemeName(aURL.GetProtocol()) + ": " + aURL.getName(); + aMenuTitle = INetURLObject::GetSchemeName(aURL.GetProtocol()) + ": " + + aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset); } aMenuShortCut.append( aMenuTitle ); @@ -404,30 +405,10 @@ void SAL_CALL RecentFilesMenuController::itemSelected( const css::awt::MenuEvent const OUString aCommand( xPopupMenu->getCommand( rEvent.MenuId ) ); if ( aCommand == CMD_CLEAR_LIST ) { - const bool bDoAsk = officecfg::Office::Common::Misc::QueryClearRecentDocuments::get(); - short nresult = RET_YES; - if (bDoAsk) - { - VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create(); - auto pDlg = pFact->CreateQueryDialog( - Application::GetDefDialogParent(), - FwkResId(STR_QUERY_CLR_RECENTS_DOCS_TITLE), + if (ConfirmationDlg::Query( + Application::GetDefDialogParent(), FwkResId(STR_QUERY_CLR_RECENTS_DOCS_TITLE), FwkResId(STR_QUERY_CLR_RECENTS_DOCS_TEXT), - FwkResId(STR_QUERY_CLR_RECENTS_DOCS_QUESTION), - true); - nresult = pDlg->Execute(); - - if (pDlg->ShowAgain() == false) - { - std::shared_ptr xChanges( - comphelper::ConfigurationChanges::create()); - officecfg::Office::Common::Misc::QueryClearRecentDocuments::set(false, xChanges); - xChanges->commit(); - } - pDlg->disposeOnce(); - } - - if ( ! bDoAsk || nresult == RET_YES ) + FwkResId(STR_QUERY_CLR_RECENTS_DOCS_QUESTION))) { SvtHistoryOptions::Clear( EHistoryType::PickList, false ); dispatchCommand( diff --git a/framework/source/uielement/spinfieldtoolbarcontroller.cxx b/framework/source/uielement/spinfieldtoolbarcontroller.cxx index 68b401235573..1ad9787a87fe 100644 --- a/framework/source/uielement/spinfieldtoolbarcontroller.cxx +++ b/framework/source/uielement/spinfieldtoolbarcontroller.cxx @@ -26,13 +26,13 @@ #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -46,7 +46,7 @@ namespace framework { // Wrapper class to notify controller about events from combobox. -// Unfortunaltly the events are notified through virtual methods instead +// Unfortunately the events are notified through virtual methods instead // of Listeners. class SpinfieldControl final : public InterimItemWindow @@ -66,7 +66,7 @@ public: DECL_LINK(ValueChangedHdl, weld::FormattedSpinButton&, void); DECL_LINK(FormatOutputHdl, double, std::optional); DECL_STATIC_LINK(SpinfieldControl, ParseInputHdl, const OUString&, Formatter::ParseResult); - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); DECL_LINK(ActivateHdl, weld::Entry&, bool); DECL_LINK(FocusInHdl, weld::Widget&, void); DECL_LINK(FocusOutHdl, weld::Widget&, void); @@ -130,7 +130,7 @@ IMPL_LINK_NOARG(SpinfieldControl, ValueChangedHdl, weld::FormattedSpinButton&, v m_pSpinfieldToolbarController->execute(0); } -IMPL_LINK_NOARG(SpinfieldControl, ModifyHdl, weld::Entry&, void) +IMPL_LINK_NOARG(SpinfieldControl, ModifyHdl, weld::TextWidget&, void) { if (m_pSpinfieldToolbarController) m_pSpinfieldToolbarController->Modify(); @@ -194,14 +194,15 @@ SpinfieldToolbarController::~SpinfieldToolbarController() { } -void SAL_CALL SpinfieldToolbarController::dispose() +void SpinfieldToolbarController::disposing(std::unique_lock& rGuard) { - SolarMutexGuard aSolarMutexGuard; - - m_xToolbar->SetItemWindow( m_nID, nullptr ); - m_pSpinfieldControl.disposeAndClear(); - - ComplexToolbarController::dispose(); + { + comphelper::unique_unlock aUnlock(rGuard); + SolarMutexGuard aSolarMutexGuard; + m_xToolbar->SetItemWindow( m_nID, nullptr ); + m_pSpinfieldControl.disposeAndClear(); + } + ComplexToolbarController::disposing(rGuard); } Sequence SpinfieldToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const diff --git a/framework/source/uielement/styletoolbarcontroller.cxx b/framework/source/uielement/styletoolbarcontroller.cxx index acad86db5e25..cbf015e8ce0d 100644 --- a/framework/source/uielement/styletoolbarcontroller.cxx +++ b/framework/source/uielement/styletoolbarcontroller.cxx @@ -258,9 +258,9 @@ void StyleToolbarController::statusChanged( const css::frame::FeatureStateEvent& } } -void StyleToolbarController::dispose() +void StyleToolbarController::disposing(std::unique_lock& rGuard) { - ToolboxController::dispose(); + ToolboxController::disposing(rGuard); m_aListenerMap.clear(); // Break the cycle with StyleDispatcher. } diff --git a/framework/source/uielement/subtoolbarcontroller.cxx b/framework/source/uielement/subtoolbarcontroller.cxx index e6509bb6be06..0c26ffa56c21 100644 --- a/framework/source/uielement/subtoolbarcontroller.cxx +++ b/framework/source/uielement/subtoolbarcontroller.cxx @@ -30,8 +30,9 @@ #include #include #include +#include #include -#include +#include #include #include @@ -91,8 +92,8 @@ public: // XEventListener virtual void SAL_CALL disposing( const css::lang::EventObject& e ) override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + virtual void disposing(std::unique_lock& rGuard) override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; @@ -514,12 +515,9 @@ void SubToolBarController::PopoverDestroyed() m_xUIElement = nullptr; } -void SubToolBarController::dispose() +void SubToolBarController::disposing(std::unique_lock& rGuard) { - if ( m_bDisposed ) - return; - - svt::PopupWindowController::dispose(); + svt::PopupWindowController::disposing(rGuard); disposeUIElement(); m_xUIElement = nullptr; } diff --git a/framework/source/uielement/togglebuttontoolbarcontroller.cxx b/framework/source/uielement/togglebuttontoolbarcontroller.cxx index be57703f87ff..d2410487acc6 100644 --- a/framework/source/uielement/togglebuttontoolbarcontroller.cxx +++ b/framework/source/uielement/togglebuttontoolbarcontroller.cxx @@ -52,12 +52,6 @@ ToggleButtonToolbarController::~ToggleButtonToolbarController() { } -void SAL_CALL ToggleButtonToolbarController::dispose() -{ - SolarMutexGuard aSolarMutexGuard; - ComplexToolbarController::dispose(); -} - Sequence ToggleButtonToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const { Sequence aArgs{ // Add key modifier to argument list diff --git a/framework/source/uielement/toolbarmanager.cxx b/framework/source/uielement/toolbarmanager.cxx index be60ae37bebb..257dc861f16b 100644 --- a/framework/source/uielement/toolbarmanager.cxx +++ b/framework/source/uielement/toolbarmanager.cxx @@ -76,7 +76,7 @@ #include #include #include -#include +#include #include // namespaces diff --git a/framework/source/uielement/toolbarwrapper.cxx b/framework/source/uielement/toolbarwrapper.cxx index 0726a55cadff..9f1367a59b0e 100644 --- a/framework/source/uielement/toolbarwrapper.cxx +++ b/framework/source/uielement/toolbarwrapper.cxx @@ -28,7 +28,8 @@ #include #include -#include +#include +#include #include using namespace com::sun::star; diff --git a/framework/uiconfig/startmodule/menubar/menubar.xml b/framework/uiconfig/startmodule/menubar/menubar.xml index b7309cb05f0c..b8163de46382 100644 --- a/framework/uiconfig/startmodule/menubar/menubar.xml +++ b/framework/uiconfig/startmodule/menubar/menubar.xml @@ -22,10 +22,10 @@ - + - + @@ -38,20 +38,20 @@ - + - + - + - - - + + + - + @@ -62,19 +62,18 @@ - + - - + - + - + diff --git a/helpcompiler/source/BasCodeTagger.cxx b/helpcompiler/source/BasCodeTagger.cxx index 3511617f4dfb..f47f6c1d0376 100644 --- a/helpcompiler/source/BasCodeTagger.cxx +++ b/helpcompiler/source/BasCodeTagger.cxx @@ -94,7 +94,7 @@ void BasicCodeTagger::getBasicCodeContainerNodes() //! Extracts Basic Codes contained in tags. /*! - * For each this method iterates through it's tags and "inserts" tags according + * For each this method iterates through its tags and "inserts" tags according * to the Basic code syntax found in that paragraph. */ void BasicCodeTagger::tagBasCodeParagraphs() diff --git a/helpcontent2 b/helpcontent2 index 1f0e174580e7..099d2dbd383b 160000 --- a/helpcontent2 +++ b/helpcontent2 @@ -1 +1 @@ -Subproject commit 1f0e174580e7a87f2979a728f38e6be86eb741c4 +Subproject commit 099d2dbd383b6fc748d9aa9ca05ac9f2e9aaaaa2 diff --git a/hwpfilter/source/cspline.h b/hwpfilter/source/cspline.h index b6ddcceb8ab0..542f21e7f433 100644 --- a/hwpfilter/source/cspline.h +++ b/hwpfilter/source/cspline.h @@ -17,14 +17,11 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_HWPFILTER_SOURCE_CSPLINE_H -#define INCLUDED_HWPFILTER_SOURCE_CSPLINE_H +#pragma once void NaturalSpline (int N, const double* x, const double* a, std::unique_ptr& b, std::unique_ptr& c, std::unique_ptr& d); void PeriodicSpline (int N, const double* x, const double* a, std::unique_ptr& b, std::unique_ptr& c, std::unique_ptr& d); -#endif // INCLUDED_HWPFILTER_SOURCE_CSPLINE_H - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/hwpfilter/source/datecode.h b/hwpfilter/source/datecode.h index 900d1e6c9d6b..7c154480352d 100644 --- a/hwpfilter/source/datecode.h +++ b/hwpfilter/source/datecode.h @@ -17,11 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_HWPFILTER_SOURCE_DATECODE_H -#define INCLUDED_HWPFILTER_SOURCE_DATECODE_H +#pragma once const hchar defaultform[] = { '1', 0x9165, 32, '2', 0xB6A9, 32, '3', 0xB7A9, 0 }; -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/hwpfilter/source/drawing.h b/hwpfilter/source/drawing.h index ce68499e97c6..a604ba98f52a 100644 --- a/hwpfilter/source/drawing.h +++ b/hwpfilter/source/drawing.h @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_HWPFILTER_SOURCE_DRAWING_H -#define INCLUDED_HWPFILTER_SOURCE_DRAWING_H +#pragma once #include "precompile.h" @@ -374,7 +373,7 @@ static std::unique_ptr LoadDrawingObject(HWPFile& hwpf) return head; error: -// drawing object can be list. +// drawing object can be a list. // hdo = current item, head = list; if (hdo->type < 0 || hdo->type >= HWPDO_NITEMS) @@ -699,6 +698,5 @@ HWPDrawingObject::~HWPDrawingObject() HWPDOFunc(this, OBJFUNC_FREE, nullptr, 0); } -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/hwpfilter/source/hbox.cxx b/hwpfilter/source/hbox.cxx index 855b73e25c6c..a9c5ea62bee5 100644 --- a/hwpfilter/source/hbox.cxx +++ b/hwpfilter/source/hbox.cxx @@ -442,7 +442,7 @@ static hchar olHanglJaso(unsigned int num, int type) if (type == OL_HANGL_JASO) { - num = num % (14 + SAL_N_ELEMENTS(jung)); + num = num % (14 + std::size(jung)); if (num < 14) hh = (han_init[num] << 8) | 'A'; @@ -455,7 +455,7 @@ static hchar olHanglJaso(unsigned int num, int type) hh = (han_init[num] << 8) | 'a'; else { - int j = (num / 14) % SAL_N_ELEMENTS(jung2); + int j = (num / 14) % std::size(jung2); num = num % 14; hh = (han_init[num] << 8) | (jung2[j] << 5) | 1; diff --git a/hwpfilter/source/hbox.h b/hwpfilter/source/hbox.h index e27f8fc64c4f..6829c63cc134 100644 --- a/hwpfilter/source/hbox.h +++ b/hwpfilter/source/hbox.h @@ -33,9 +33,9 @@ #include "hpara.h" /** - * The HBox class is the base class for all date classes in hwp document. + * The HBox class is the base class for all data classes in hwp document. * For example, there are special character, table, image, etc. - * It has one character. The ascii code value of special characters are smaller than 32. General character is greater than 32. + * It has one character. The ASCII code values of special characters are smaller than 32. General character is greater than 32. * * @short Base class for characters */ @@ -207,7 +207,7 @@ struct CellLine * @li ypos - distance between top border of cell and top border of table * @li width - distance between left border of cell and right border of cell * @li height - distance between top border of cell and bottom border of table - * This is differ from the format of other office in fact cell has two properties + * This is different from the format of other office in fact cell has two properties * - rowindex and column index. * * @short Cell object @@ -574,7 +574,7 @@ struct Picture: public FBox hchar dummy; /** * follow_block_size is the size information of the Drawing object of hwp. - * It's value is greater than 0 if the pictype is PICTYPE_DRAW. + * Its value is greater than 0 if the pictype is PICTYPE_DRAW. */ uint follow_block_size; /* Additional information length. */ short dummy1; // to not change structure size */ @@ -867,7 +867,7 @@ struct TocMark: public HBox // index mark(26) /** * IndexMark marks the table of search. - * If you set IndexMark at current position, hwp make it as search index. + * If you set IndexMark at current position, hwp makes it as search index. * @short Table of search */ struct IndexMark: public HBox diff --git a/hwpfilter/source/hcode.cxx b/hwpfilter/source/hcode.cxx index 9616529bbb33..5caad7185bb8 100644 --- a/hwpfilter/source/hcode.cxx +++ b/hwpfilter/source/hcode.cxx @@ -556,7 +556,7 @@ static int is_jaso(hchar hh) { unsigned int i; - for (i = 0; i < SAL_N_ELEMENTS(jaso_hh_code); i++) + for (i = 0; i < std::size(jaso_hh_code); i++) if (hh == jaso_hh_code[i]) return 1; return 0; @@ -565,7 +565,7 @@ static int is_jaso(hchar hh) static hchar jaso2ks(hchar hh) { - for (size_t i = 0; i < SAL_N_ELEMENTS(jaso_hh_code); i++) + for (size_t i = 0; i < std::size(jaso_hh_code); i++) if (hh == jaso_hh_code[i]) { return sal::static_int_cast(0xa4a1 + i); @@ -1080,7 +1080,7 @@ int kssm_hangul_to_ucs2(hchar ch, hchar *dest) } else{ /* combination of consonants and vowels includes old characters: an unfinished table */ unsigned int index = choseong * 32 + jongseong - 308; - if( index < SAL_N_ELEMENTS(jamocomp1_to_unicode) ){ + if( index < std::size(jamocomp1_to_unicode) ){ dest[0] = jamocomp1_to_unicode[index].v1; dest[1] = jamocomp1_to_unicode[index].v2; dest[2] = jamocomp1_to_unicode[index].v3; @@ -1144,7 +1144,7 @@ hchar ksc5601_sym_to_ucs2 (hchar input) unsigned char ch = sal::static_int_cast(input >> 8); unsigned char ch2 = sal::static_int_cast(input & 0xff); int idx = (ch - 0xA1) * 94 + (ch2 - 0xA1); - if (idx >= 0 && o3tl::make_unsigned(idx) < SAL_N_ELEMENTS(ksc5601_2uni_page21)) { + if (idx >= 0 && o3tl::make_unsigned(idx) < std::size(ksc5601_2uni_page21)) { hchar value = ksc5601_2uni_page21[idx]; return value ? value : 0x25a1; } @@ -1156,7 +1156,7 @@ hchar ksc5601_han_to_ucs2 (hchar input) unsigned char ch = sal::static_int_cast(input >> 8); unsigned char ch2 = sal::static_int_cast(input & 0xff); int idx = (ch - 0xA1) * 94 + (ch2 - 0xA1); - if (idx >= 3854 && o3tl::make_unsigned(idx) < 3854 + SAL_N_ELEMENTS(ksc5601_2uni_page21)) { + if (idx >= 3854 && o3tl::make_unsigned(idx) < 3854 + std::size(ksc5601_2uni_page21)) { // Hanja : row 42 - row 93 : 3854 = 94 * (42-1) hchar value = ksc5601_2uni_page21[idx - 3854]; return value ? value : '?'; diff --git a/hwpfilter/source/hcode.h b/hwpfilter/source/hcode.h index 53c1513e246f..d905c5c7a024 100644 --- a/hwpfilter/source/hcode.h +++ b/hwpfilter/source/hcode.h @@ -31,7 +31,7 @@ */ enum { KSSM, KS, UNICODE }; /** - * Transfer combination-code for internal using of hwp to ascii + * Transfer combination-code for internal use of hwp to ASCII */ DLLEXPORT int hcharconv(hchar ch, hchar *dest, int codeType) ; diff --git a/hwpfilter/source/hinfo.cxx b/hwpfilter/source/hinfo.cxx index 9a4eb628b015..41ca6571dbc0 100644 --- a/hwpfilter/source/hinfo.cxx +++ b/hwpfilter/source/hinfo.cxx @@ -71,7 +71,7 @@ HWPInfo::~HWPInfo() */ void HWPInfo::Read(HWPFile & hwpf) { - hwpf.Read2b(&cur_col, 1); /* When a document is saving, the paragraph number where the coursor is */ + hwpf.Read2b(&cur_col, 1); /* When a document is saving, the paragraph number where the cursor is */ hwpf.Read2b(&cur_row, 1); /* Paragraphs rows */ hwpf.Read1b(paper.paper_kind); /* Paper Type */ diff --git a/hwpfilter/source/hpara.cxx b/hwpfilter/source/hpara.cxx index d8719d81efb3..80cb47e10f03 100644 --- a/hwpfilter/source/hpara.cxx +++ b/hwpfilter/source/hpara.cxx @@ -102,7 +102,7 @@ bool HWPPara::Read(HWPFile & hwpf, unsigned char flag) if (nch > 0) hwpf.AddCharShape(cshape); -/* Paragraph paragraphs shape */ +/* Paragraph shape */ if (nch && !reuse_shape) { pshape->Read(hwpf); diff --git a/hwpfilter/source/hpara.h b/hwpfilter/source/hpara.h index 1749985c7327..7798fc63d724 100644 --- a/hwpfilter/source/hpara.h +++ b/hwpfilter/source/hpara.h @@ -32,7 +32,7 @@ struct HBox; /** * etc flag * 0 bit : Use page columns - * 1 bit : Use page lows + * 1 bit : Use page rows * 2 bit : Use section break * 3 bit : Block start * 4 bit : In Block @@ -82,9 +82,9 @@ class DLLEXPORT HWPPara unsigned char scflag; /** - * If the value is 0, all character of paragraph have same style given cshape + * If the value is 0, all characters of paragraph have the same style as the given cshape */ - unsigned char contain_cshape; /* if it's 0, all the characters are representing with representative shape */ + unsigned char contain_cshape; /* if it's 0, all the characters are represented with representative shape */ unsigned char etcflag; /** * Checks the special characters in the paragraph diff --git a/hwpfilter/source/hstyle.h b/hwpfilter/source/hstyle.h index d55b2f19c6fc..2afde56d11ea 100644 --- a/hwpfilter/source/hstyle.h +++ b/hwpfilter/source/hstyle.h @@ -28,7 +28,7 @@ namespace hwpfilter { struct StyleData; } /** - * @short Using for global style object like "Standard" + * @short Used for global style objects like "Standard" */ class DLLEXPORT HWPStyle { diff --git a/hwpfilter/source/hutil.h b/hwpfilter/source/hutil.h index 84660e03c61e..340493fcac8f 100644 --- a/hwpfilter/source/hutil.h +++ b/hwpfilter/source/hutil.h @@ -21,11 +21,11 @@ #include "hbox.h" /** - * Transfer number to roman character + * Transfer number to Roman numeral */ void num2roman(int num, char *buf); /** - * Transfer 8bit string to 16bit string used internally in hwp + * Transfer 8-bit string to 16-bit string used internally in hwp */ void str2hstr(const char *c, hchar *i); diff --git a/hwpfilter/source/hwpfile.h b/hwpfilter/source/hwpfile.h index 126b7edf0fd8..5d1abe4410be 100644 --- a/hwpfilter/source/hwpfile.h +++ b/hwpfilter/source/hwpfile.h @@ -88,9 +88,9 @@ struct HWPColumnInfo{ * f.ReadHwpFile( stream ); * * - * There are two way to read hwp information from stream, one is to read all at a time - * to use @ref ReadhwpFile() method like above example, other is to read partial information - * to use @ref Open(), @ref InfoRead(), @ref FontRead(), @ref StyleRead(), @ref ParaListRead(), @ref TagsRead(), + * There are two ways to read hwp information from stream, one is to read all at a time + * using @ref ReadHwpFile() method like the example above; the other is to read partial information + * using @ref Open(), @ref InfoRead(), @ref FontRead(), @ref StyleRead(), @ref ParaListRead(), @ref TagsRead(), * * @short HWP file management object */ @@ -114,7 +114,7 @@ class DLLEXPORT HWPFile /** * Say current state - * @returns 0 if normal, otherwise error code. If it's bigger than USER_ERROR_BIT, it is internally using error, otherwise it's system error which is able to get the message @ref strerror() method. + * @returns 0 if normal, otherwise error code. If it's bigger than USER_ERROR_BIT, it is an internal error, otherwise it's system error which is able to get the message @ref strerror() method. */ int State( void ) const { return error_code;} /** @@ -282,7 +282,7 @@ class DLLEXPORT HWPFile std::vector> columnlist; // paragraph list std::vector> plist; - // keep paragraph's that failed to load until + // keep paragraphs that failed to load until // import is complete to avoid dangling references // elsewhere std::vector> pfailedlist; @@ -297,7 +297,7 @@ class DLLEXPORT HWPFile std::vector headerfooters; std::vector pagenumbers; std::vector> tables; - //track the stack of HParas types we're currently importing + // track the stack of HPara types we're currently importing std::vector element_import_stack; // for global document handling diff --git a/hwpfilter/source/hwplib.h b/hwpfilter/source/hwplib.h index d62266cc4e3c..dd1f4518a66e 100644 --- a/hwpfilter/source/hwplib.h +++ b/hwpfilter/source/hwplib.h @@ -31,7 +31,7 @@ /* hwp96부터 hunit가 4byte가 되었다. */ /** - * size of hunit is 4 since hwp96 version + * size of hunit is 4 bytes since hwp96 version */ typedef char16_t hchar; typedef int hunit; diff --git a/hwpfilter/source/mapping.h b/hwpfilter/source/mapping.h index 389ed6272bbd..95b84bf08299 100644 --- a/hwpfilter/source/mapping.h +++ b/hwpfilter/source/mapping.h @@ -304,7 +304,7 @@ constexpr struct FormulaEntry FormulaMapTab[] = { {"rightharpoonup", DEFAULT_VALUE}, {"rightharpoondown", DEFAULT_VALUE}, -// Delimeter +// Delimiter {"(", DEFAULT_VALUE}, {")", DEFAULT_VALUE}, {"[", DEFAULT_VALUE}, @@ -319,7 +319,7 @@ constexpr struct FormulaEntry FormulaMapTab[] = { {"rangle", DEFAULT_VALUE}, {"mid", DEFAULT_VALUE}, -// Large Delimeter +// Large Delimiter {"rmoustache", DEFAULT_VALUE}, {"lmoustache", DEFAULT_VALUE}, {"rgroup", DEFAULT_VALUE}, diff --git a/hwpfilter/source/solver.cxx b/hwpfilter/source/solver.cxx index cbb9e4e72449..72bd4fbb0e48 100644 --- a/hwpfilter/source/solver.cxx +++ b/hwpfilter/source/solver.cxx @@ -24,7 +24,7 @@ std::unique_ptr[]> mgcLinearSystemD::NewMatrix (int N) { - std::unique_ptr[]> A(new std::unique_ptr); + std::unique_ptr[]> A(new std::unique_ptr[N]); for (int row = 0; row < N; row++) { diff --git a/i18nlangtag/qa/cppunit/test_languagetag.cxx b/i18nlangtag/qa/cppunit/test_languagetag.cxx index 4d575984a7f8..657ddc1d5aa4 100644 --- a/i18nlangtag/qa/cppunit/test_languagetag.cxx +++ b/i18nlangtag/qa/cppunit/test_languagetag.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -36,12 +37,18 @@ public: void testAllIsoLangEntries(); void testDisplayNames(); void testLanguagesWithoutHyphenation(); + void testLongBcp47ToStackString(); + void testLongLanguageToStackString(); + void testLongLanguageCountryToStackString(); CPPUNIT_TEST_SUITE(TestLanguageTag); CPPUNIT_TEST(testAllTags); CPPUNIT_TEST(testAllIsoLangEntries); CPPUNIT_TEST(testDisplayNames); CPPUNIT_TEST(testLanguagesWithoutHyphenation); + CPPUNIT_TEST(testLongBcp47ToStackString); + CPPUNIT_TEST(testLongLanguageToStackString); + CPPUNIT_TEST(testLongLanguageCountryToStackString); CPPUNIT_TEST_SUITE_END(); }; @@ -1093,6 +1100,51 @@ void TestLanguageTag::testLanguagesWithoutHyphenation() CPPUNIT_ASSERT(!MsLangId::usesHyphenation(LANGUAGE_VIETNAMESE)); } +void TestLanguageTag::testLongBcp47ToStackString() +{ + // A qlt locale whose variant exceeds the StackString64 buffer must + // not overflow. convertToBcp47 rejects it, leaving the buffer empty. + lang::Locale aLocale; + aLocale.Language = I18NLANGTAG_QLT; + aLocale.Country = u"US"_ustr; + aLocale.Variant = u"en-US-x-aaaa-bbbb-cccc-dddd-eeee-ffff-gggg-hhhh-" + "iiii-jjjj-kkkk-llll-mmmm-nnnn-oooo-pppp-qqqq-rrrr"_ustr; + StackString64 aBuf; + LanguageTag::convertToBcp47(aBuf, aLocale, false); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aBuf.getLength()); +} + +OUString makeRepeated(sal_Unicode c, sal_Int32 n) +{ + OUStringBuffer aBuf(n); + for (sal_Int32 i = 0; i < n; ++i) + aBuf.append(c); + return aBuf.makeStringAndClear(); +} + +void TestLanguageTag::testLongLanguageToStackString() +{ + // A non-qlt locale with an overlong Language field and no Country + // must not overflow the StackString64 buffer. + lang::Locale aLocale; + aLocale.Language = makeRepeated(u'a', 80); + StackString64 aBuf; + LanguageTag::convertToBcp47(aBuf, aLocale, false); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aBuf.getLength()); +} + +void TestLanguageTag::testLongLanguageCountryToStackString() +{ + // A non-qlt locale whose Language + "-" + Country exceeds the + // StackString64 buffer must not overflow. + lang::Locale aLocale; + aLocale.Language = makeRepeated(u'a', 40); + aLocale.Country = makeRepeated(u'B', 40); + StackString64 aBuf; + LanguageTag::convertToBcp47(aBuf, aLocale, false); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aBuf.getLength()); +} + CPPUNIT_TEST_SUITE_REGISTRATION( TestLanguageTag ); } diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx index 2b686a0ea3ed..8894d44f81b1 100644 --- a/i18nlangtag/source/languagetag/languagetag.cxx +++ b/i18nlangtag/source/languagetag/languagetag.cxx @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -38,7 +37,7 @@ #include #endif -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ #include #endif @@ -221,7 +220,7 @@ void LiblangtagDataRef::teardown() void LiblangtagDataRef::setupDataPath() { -#if defined(ANDROID) || defined(EMSCRIPTEN) +#if defined(ANDROID) || defined(__EMSCRIPTEN__) maDataPath = OString(lo_get_app_data_dir()) + "/share/liblangtag"; #else // maDataPath is assumed to be empty here. @@ -2893,13 +2892,15 @@ static void appendAscii(StackString64& rBuf, const OUString& s) // static void LanguageTagImpl::convertToBcp47( StackString64& rBuf, const css::lang::Locale& rLocale ) { + assert(rBuf.getLength() == 0); if (rLocale.Language.isEmpty()) { // aBcp47 stays empty } else if (rLocale.Language == I18NLANGTAG_QLT) { - appendAscii(rBuf, rLocale.Variant); + if (rLocale.Variant.getLength() < 64) + appendAscii(rBuf, rLocale.Variant); } else { @@ -2907,8 +2908,11 @@ void LanguageTagImpl::convertToBcp47( StackString64& rBuf, const css::lang::Loca * now just concatenate language and country. In case we stumbled over * variant aware code we'd have to take care of that. */ if (rLocale.Country.isEmpty()) - appendAscii(rBuf, rLocale.Language); - else + { + if (rLocale.Language.getLength() < 64) + appendAscii(rBuf, rLocale.Language); + } + else if (rLocale.Language.getLength() + 1 + rLocale.Country.getLength() < 64) { appendAscii(rBuf, rLocale.Language); rBuf.append("-"); @@ -3085,363 +3089,4 @@ bool LanguageTag::isValidBcp47( const OUString& rString, OUString* o_pCanonicali return bValid; } -LanguageTag makeLanguageTagFromAppleLanguageId(AppleLanguageId nLanguage) -{ - //map the simple ones via LanguageTypes, and the hard ones explicitly - LanguageType nLang(LANGUAGE_DONTKNOW); - - switch (nLanguage) - { - case AppleLanguageId::ENGLISH: - nLang = LANGUAGE_ENGLISH_US; - break; - case AppleLanguageId::FRENCH: - nLang = LANGUAGE_FRENCH; - break; - case AppleLanguageId::GERMAN: - nLang = LANGUAGE_GERMAN; - break; - case AppleLanguageId::ITALIAN: - nLang = LANGUAGE_ITALIAN; - break; - case AppleLanguageId::DUTCH: - nLang = LANGUAGE_DUTCH; - break; - case AppleLanguageId::SWEDISH: - nLang = LANGUAGE_SWEDISH; - break; - case AppleLanguageId::SPANISH: - nLang = LANGUAGE_SPANISH; - break; - case AppleLanguageId::DANISH: - nLang = LANGUAGE_DANISH; - break; - case AppleLanguageId::PORTUGUESE: - nLang = LANGUAGE_PORTUGUESE; - break; - case AppleLanguageId::NORWEGIAN: - nLang = LANGUAGE_NORWEGIAN; - break; - case AppleLanguageId::HEBREW: - nLang = LANGUAGE_HEBREW; - break; - case AppleLanguageId::JAPANESE: - nLang = LANGUAGE_JAPANESE; - break; - case AppleLanguageId::ARABIC: - nLang = LANGUAGE_ARABIC_PRIMARY_ONLY; - break; - case AppleLanguageId::FINNISH: - nLang = LANGUAGE_FINNISH; - break; - case AppleLanguageId::GREEK: - nLang = LANGUAGE_GREEK; - break; - case AppleLanguageId::ICELANDIC: - nLang = LANGUAGE_ICELANDIC; - break; - case AppleLanguageId::MALTESE: - nLang = LANGUAGE_MALTESE; - break; - case AppleLanguageId::TURKISH: - nLang = LANGUAGE_TURKISH; - break; - case AppleLanguageId::CROATIAN: - nLang = LANGUAGE_CROATIAN; - break; - case AppleLanguageId::CHINESE_TRADITIONAL: - nLang = LANGUAGE_CHINESE_TRADITIONAL; - break; - case AppleLanguageId::URDU: - nLang = LANGUAGE_URDU_PAKISTAN; //probably, otherwise we need a LANGUAGE_URDU_PRIMARY_ONLY - break; - case AppleLanguageId::HINDI: - nLang = LANGUAGE_HINDI; - break; - case AppleLanguageId::THAI: - nLang = LANGUAGE_THAI; - break; - case AppleLanguageId::KOREAN: - nLang = LANGUAGE_KOREAN; - break; - case AppleLanguageId::LITHUANIAN: - nLang = LANGUAGE_LITHUANIAN; - break; - case AppleLanguageId::POLISH: - nLang = LANGUAGE_POLISH; - break; - case AppleLanguageId::HUNGARIAN: - nLang = LANGUAGE_HUNGARIAN; - break; - case AppleLanguageId::ESTONIAN: - nLang = LANGUAGE_ESTONIAN; - break; - case AppleLanguageId::LATVIAN: - nLang = LANGUAGE_LATVIAN; - break; - case AppleLanguageId::SAMI: - nLang = LANGUAGE_SAMI_NORTHERN_NORWAY; //maybe - break; - case AppleLanguageId::FAROESE: - nLang = LANGUAGE_FAEROESE; - break; - case AppleLanguageId::FARSI: - nLang = LANGUAGE_FARSI; - break; - case AppleLanguageId::RUSSIAN: - nLang = LANGUAGE_RUSSIAN; - break; - case AppleLanguageId::CHINESE_SIMPLIFIED: - nLang = LANGUAGE_CHINESE_SIMPLIFIED; - break; - case AppleLanguageId::FLEMISH: - nLang = LANGUAGE_DUTCH_BELGIAN; - break; - case AppleLanguageId::IRISH_GAELIC: - nLang = LANGUAGE_GAELIC_IRELAND; - break; - case AppleLanguageId::ALBANIAN: - nLang = LANGUAGE_ALBANIAN; - break; - case AppleLanguageId::ROMANIAN: - nLang = LANGUAGE_ROMANIAN; - break; - case AppleLanguageId::CZECH: - nLang = LANGUAGE_CZECH; - break; - case AppleLanguageId::SLOVAK: - nLang = LANGUAGE_SLOVAK; - break; - case AppleLanguageId::SLOVENIAN: - nLang = LANGUAGE_SLOVENIAN; - break; - case AppleLanguageId::YIDDISH: - nLang = LANGUAGE_YIDDISH; - break; - case AppleLanguageId::SERBIAN: - nLang = LANGUAGE_SERBIAN_CYRILLIC_SERBIA; //maybe - break; - case AppleLanguageId::MACEDONIAN: - nLang = LANGUAGE_MACEDONIAN; - break; - case AppleLanguageId::BULGARIAN: - nLang = LANGUAGE_BULGARIAN; - break; - case AppleLanguageId::UKRAINIAN: - nLang = LANGUAGE_UKRAINIAN; - break; - case AppleLanguageId::BYELORUSSIAN: - nLang = LANGUAGE_BELARUSIAN; - break; - case AppleLanguageId::UZBEK: - nLang = LANGUAGE_UZBEK_CYRILLIC; //maybe - break; - case AppleLanguageId::KAZAKH: - nLang = LANGUAGE_KAZAKH; - break; - case AppleLanguageId::AZERI_CYRILLIC: - nLang = LANGUAGE_AZERI_CYRILLIC; - break; - case AppleLanguageId::AZERI_ARABIC: - return LanguageTag(u"az-Arab"_ustr); - case AppleLanguageId::ARMENIAN: - nLang = LANGUAGE_ARMENIAN; - break; - case AppleLanguageId::GEORGIAN: - nLang = LANGUAGE_GEORGIAN; - break; - case AppleLanguageId::MOLDAVIAN: - nLang = LANGUAGE_ROMANIAN_MOLDOVA; - break; - case AppleLanguageId::KIRGHIZ: - nLang = LANGUAGE_KIRGHIZ; - break; - case AppleLanguageId::TAJIKI: - nLang = LANGUAGE_TAJIK; - break; - case AppleLanguageId::TURKMEN: - nLang = LANGUAGE_TURKMEN; - break; - case AppleLanguageId::MONGOLIAN_MONGOLIAN: - nLang = LANGUAGE_MONGOLIAN_MONGOLIAN_MONGOLIA; - break; - case AppleLanguageId::MONGOLIAN_CYRILLIC: - nLang = LANGUAGE_MONGOLIAN_CYRILLIC_MONGOLIA; - break; - case AppleLanguageId::PASHTO: - nLang = LANGUAGE_PASHTO; - break; - case AppleLanguageId::KURDISH: - nLang = LANGUAGE_USER_KURDISH_TURKEY; //maybe - break; - case AppleLanguageId::KASHMIRI: - nLang = LANGUAGE_KASHMIRI; - break; - case AppleLanguageId::SINDHI: - nLang = LANGUAGE_SINDHI; - break; - case AppleLanguageId::TIBETAN: - nLang = LANGUAGE_TIBETAN; - break; - case AppleLanguageId::NEPALI: - nLang = LANGUAGE_NEPALI; - break; - case AppleLanguageId::SANSKRIT: - nLang = LANGUAGE_SANSKRIT; - break; - case AppleLanguageId::MARATHI: - nLang = LANGUAGE_MARATHI; - break; - case AppleLanguageId::BENGALI: - nLang = LANGUAGE_BENGALI; - break; - case AppleLanguageId::ASSAMESE: - nLang = LANGUAGE_ASSAMESE; - break; - case AppleLanguageId::GUJARATI: - nLang = LANGUAGE_GUJARATI; - break; - case AppleLanguageId::PUNJABI: - nLang = LANGUAGE_PUNJABI; - break; - case AppleLanguageId::ORIYA: - nLang = LANGUAGE_ODIA; - break; - case AppleLanguageId::MALAYALAM: - nLang = LANGUAGE_MALAYALAM; - break; - case AppleLanguageId::KANNADA: - nLang = LANGUAGE_KANNADA; - break; - case AppleLanguageId::TAMIL: - nLang = LANGUAGE_TAMIL; - break; - case AppleLanguageId::TELUGU: - nLang = LANGUAGE_TELUGU; - break; - case AppleLanguageId::SINHALESE: - nLang = LANGUAGE_SINHALESE_SRI_LANKA; - break; - case AppleLanguageId::BURMESE: - nLang = LANGUAGE_BURMESE; - break; - case AppleLanguageId::KHMER: - nLang = LANGUAGE_KHMER; - break; - case AppleLanguageId::LAO: - nLang = LANGUAGE_LAO; - break; - case AppleLanguageId::VIETNAMESE: - nLang = LANGUAGE_VIETNAMESE; - break; - case AppleLanguageId::INDONESIAN: - nLang = LANGUAGE_INDONESIAN; - break; - case AppleLanguageId::TAGALONG: - nLang = LANGUAGE_USER_TAGALOG; - break; - case AppleLanguageId::MALAY_LATIN: - nLang = LANGUAGE_MALAY_MALAYSIA; - break; - case AppleLanguageId::MALAY_ARABIC: - nLang = LANGUAGE_USER_MALAY_ARABIC_MALAYSIA; - break; - case AppleLanguageId::AMHARIC: - nLang = LANGUAGE_AMHARIC_ETHIOPIA; - break; - case AppleLanguageId::TIGRINYA: - nLang = LANGUAGE_TIGRIGNA_ETHIOPIA; - break; - case AppleLanguageId::GALLA: - nLang = LANGUAGE_OROMO; - break; - case AppleLanguageId::SOMALI: - nLang = LANGUAGE_SOMALI; - break; - case AppleLanguageId::SWAHILI: - nLang = LANGUAGE_SWAHILI; - break; - case AppleLanguageId::KINYARWANDA: - nLang = LANGUAGE_KINYARWANDA_RWANDA; - break; - case AppleLanguageId::RUNDI: - return LanguageTag(u"rn"_ustr); - case AppleLanguageId::NYANJA: - nLang = LANGUAGE_USER_NYANJA; - break; - case AppleLanguageId::MALAGASY: - nLang = LANGUAGE_MALAGASY_PLATEAU; - break; - case AppleLanguageId::ESPERANTO: - nLang = LANGUAGE_USER_ESPERANTO; - break; - case AppleLanguageId::WELSH: - nLang = LANGUAGE_WELSH; - break; - case AppleLanguageId::BASQUE: - nLang = LANGUAGE_BASQUE; - break; - case AppleLanguageId::CATALAN: - nLang = LANGUAGE_CATALAN; - break; - case AppleLanguageId::LATIN: - nLang = LANGUAGE_LATIN; - break; - case AppleLanguageId::QUENCHUA: - nLang = LANGUAGE_QUECHUA_BOLIVIA; //maybe - break; - case AppleLanguageId::GUARANI: - nLang = LANGUAGE_GUARANI_PARAGUAY; - break; - case AppleLanguageId::AYMARA: - return LanguageTag(u"ay"_ustr); - case AppleLanguageId::TATAR: - nLang = LANGUAGE_TATAR; - break; - case AppleLanguageId::UIGHUR: - nLang = LANGUAGE_UIGHUR_CHINA; - break; - case AppleLanguageId::DZONGKHA: - nLang = LANGUAGE_DZONGKHA_BHUTAN; - break; - case AppleLanguageId::JAVANESE_LATIN: - return LanguageTag(u"jv-Latn"_ustr); - case AppleLanguageId::SUNDANESE_LATIN: - return LanguageTag(u"su-Latn"_ustr); - case AppleLanguageId::GALICIAN: - nLang = LANGUAGE_GALICIAN; - break; - case AppleLanguageId::AFRIKAANS: - nLang = LANGUAGE_AFRIKAANS; - break; - case AppleLanguageId::BRETON: - nLang = LANGUAGE_BRETON_FRANCE; - break; - case AppleLanguageId::INUKTITUT: - nLang = LANGUAGE_INUKTITUT_LATIN_CANADA; //probably - break; - case AppleLanguageId::SCOTTISH_GAELIC: - nLang = LANGUAGE_GAELIC_SCOTLAND; - break; - case AppleLanguageId::MANX_GAELIC: - nLang = LANGUAGE_USER_MANX; - break; - case AppleLanguageId::IRISH_GAELIC_WITH_DOT_ABOVE: - return LanguageTag(u"ga-Latg"_ustr); - case AppleLanguageId::TONGAN: - return LanguageTag(u"to"_ustr); - case AppleLanguageId::GREEK_POLYTONIC: - nLang = LANGUAGE_USER_ANCIENT_GREEK; - break; - case AppleLanguageId::GREENLANDIC: - nLang = LANGUAGE_KALAALLISUT_GREENLAND; - break; - case AppleLanguageId::AZERI_LATIN: - nLang = LANGUAGE_AZERI_LATIN; - break; - } - - return LanguageTag(nLang); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/i18npool/inc/wtt.h b/i18npool/inc/wtt.h index c81afe0e1f7f..e6c82802f29b 100644 --- a/i18npool/inc/wtt.h +++ b/i18npool/inc/wtt.h @@ -27,7 +27,7 @@ namespace i18npool { */ #define CT_CTRL 0 // Control character -#define CT_NON 1 // Non-composible +#define CT_NON 1 // Non-composable #define CT_CONS 2 // Consonant #define CT_LV 3 // Leading vowel #define CT_FV1 4 // Following vowel diff --git a/i18npool/qa/cppunit/test_textsearch.cxx b/i18npool/qa/cppunit/test_textsearch.cxx index 1ea1bf64d66f..7f56548f297d 100644 --- a/i18npool/qa/cppunit/test_textsearch.cxx +++ b/i18npool/qa/cppunit/test_textsearch.cxx @@ -37,6 +37,7 @@ public: void testICU(); void testSearches(); void testWildcardSearch(); + void testTdf172646_wildcardBeforeSurrogatePair(); void testApostropheSearch(); void testQuotationMarkSearch(); void testTdf91764_searchArabicDiacritics(); @@ -45,6 +46,7 @@ public: CPPUNIT_TEST(testICU); CPPUNIT_TEST(testSearches); CPPUNIT_TEST(testWildcardSearch); + CPPUNIT_TEST(testTdf172646_wildcardBeforeSurrogatePair); CPPUNIT_TEST(testApostropheSearch); CPPUNIT_TEST(testQuotationMarkSearch); CPPUNIT_TEST(testTdf91764_searchArabicDiacritics); @@ -293,6 +295,55 @@ void TestTextSearch::testWildcardSearch() CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes.endOffset[0]); } +void TestTextSearch::testTdf172646_wildcardBeforeSurrogatePair() +{ + util::SearchOptions2 aOptions; + aOptions.AlgorithmType2 = util::SearchAlgorithms2::WILDCARD; + aOptions.transliterateFlags = sal_Int32(::css::i18n::TransliterationModules::TransliterationModules_IGNORE_CASE); + util::SearchResult aRes; + + // A match ending at a supplementary character (a surrogate pair in + // UTF-16) must report the end offset behind the whole pair. + OUString aText = u"a\U0001F334"_ustr; + + aOptions.searchString = u"*\U0001F334"_ustr; + m_xSearch2->setOptions2( aOptions ); + // match the whole string, [0,3) + aRes = m_xSearch2->searchForward( aText, 0, aText.getLength()); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aRes.subRegExpressions); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes.startOffset[0]); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aRes.endOffset[0]); + // match the whole string, (3,0] + aRes = m_xSearch2->searchBackward( aText, aText.getLength(), 0); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aRes.subRegExpressions); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aRes.startOffset[0]); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes.endOffset[0]); + + // The same in whole-cell matching mode (as used e.g. by SUMIF), matching + // "abc" then the surrogate pair. + aText = u"abc\U0001F334"_ustr; + aOptions.searchFlag |= util::SearchFlags::WILD_MATCH_SELECTION; + m_xSearch2->setOptions2( aOptions ); + // match the whole string, [0,5) + aRes = m_xSearch2->searchForward( aText, 0, aText.getLength()); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aRes.subRegExpressions); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes.startOffset[0]); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes.endOffset[0]); + // match the whole string, (5,0] + aRes = m_xSearch2->searchBackward( aText, aText.getLength(), 0); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aRes.subRegExpressions); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes.startOffset[0]); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes.endOffset[0]); + + aOptions.searchString = u"*\U0001F334*"_ustr; + m_xSearch2->setOptions2( aOptions ); + // match the whole string, [0,5) + aRes = m_xSearch2->searchForward( aText, 0, aText.getLength()); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aRes.subRegExpressions); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes.startOffset[0]); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes.endOffset[0]); +} + void TestTextSearch::testApostropheSearch() { // A) find typographic apostrophes also by using ASCII apostrophe in searchString diff --git a/i18npool/source/breakiterator/data/README b/i18npool/source/breakiterator/data/README index 76e3e37c3faf..e6cd7425a632 100644 --- a/i18npool/source/breakiterator/data/README +++ b/i18npool/source/breakiterator/data/README @@ -6,7 +6,7 @@ dict_word is used for dictionary word break, edit_word is for cursor travelling, while count_word is for word count. At various stages these copies have been customized and are now horribly out of -sync. It unclear which diffs from the base versions are deliberate and which +sync. It is unclear which diffs from the base versions are deliberate and which are now accidental :-( The various issues and customizations have been reviewed, with tests written for diff --git a/i18npool/source/calendar/calendar_gregorian.cxx b/i18npool/source/calendar/calendar_gregorian.cxx index 1282d400fc79..14dc8800d08c 100644 --- a/i18npool/source/calendar/calendar_gregorian.cxx +++ b/i18npool/source/calendar/calendar_gregorian.cxx @@ -565,7 +565,7 @@ void Calendar_gregorian::submitFields() void Calendar_gregorian::setValue() { // Copy fields before calling submitFields() directly or indirectly below. - memcpy(fieldSetValue, fieldValue, sizeof(fieldSetValue)); + std::copy(std::begin(fieldValue), std::end(fieldValue), std::begin(fieldSetValue)); // Possibly setup ERA and YEAR in fieldSetValue. mapToGregorian(); @@ -662,7 +662,7 @@ Calendar_gregorian::isValid() if (fieldSet) { sal_Int32 tmp = fieldSet; setValue(); - memcpy(fieldSetValue, fieldValue, sizeof(fieldSetValue)); + std::copy(std::begin(fieldValue), std::end(fieldValue), std::begin(fieldSetValue)); getValue(); for ( sal_Int16 fieldIndex = 0; fieldIndex < FIELD_INDEX_COUNT; fieldIndex++ ) { // compare only with fields that are set and reset fieldSet[] diff --git a/i18npool/source/characterclassification/cclass_unicode_parser.cxx b/i18npool/source/characterclassification/cclass_unicode_parser.cxx index ddb895882dcd..0a6c3eae20e8 100644 --- a/i18npool/source/characterclassification/cclass_unicode_parser.cxx +++ b/i18npool/source/characterclassification/cclass_unicode_parser.cxx @@ -18,6 +18,8 @@ */ +#include + #include #include #include @@ -415,7 +417,7 @@ void cclass_Unicode::initParserTable( const Locale& rLocale, sal_Int32 startChar // Memory of pTable is reused. if ( !pTable ) pTable.reset(new ParserFlags[nDefCnt]); - memcpy( pTable.get(), pDefaultParserTable, sizeof(ParserFlags) * nDefCnt ); + std::copy_n( pDefaultParserTable, nDefCnt, pTable.get() ); // Start and cont tables only need reallocation if different length. if ( pStart && userDefinedCharactersStart.getLength() != aStartChars.getLength() ) { @@ -656,8 +658,8 @@ ParserFlags cclass_Unicode::getFlagsExtended(sal_uInt32 const c, const cclass_Un return ((nTypes & KParseTokens::IGNORE_LEADING_WS) ? ParserFlags::CHAR_DONTCARE : (bStart ? ParserFlags::CHAR_WORD : (ParserFlags::CHAR_DONTCARE | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP) )); case U_OTHER_PUNCTUATION: - // fdo#61754 Let's see (if we not at the start) if this is midletter - // punctuation and allow it in a word if it is similarly to + // fdo#61754 Let's see (if we are not at the start) if this is midletter + // punctuation and allow it in a word if it is similar to // U_NON_SPACING_MARK, for example U+00B7 MIDDLE DOT. // tdf#123575 for U+30FB KATAKANA MIDDLE DOT property is not // U_WB_MIDLETTER but U_WB_KATAKANA instead, explicitly test that @@ -800,14 +802,14 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32 eState = ssGetWordFirstChar; bQuote = true; postSymbolIndex = nextCharIndex; - nParseTokensType = 0; // will be taken of first real character + nParseTokensType = 0; // will be taken from first real character r.TokenType = KParseType::SINGLE_QUOTE_NAME; } else if ( nMask & ParserFlags::CHAR_STRING ) { eState = ssGetString; postSymbolIndex = nextCharIndex; - nParseTokensType = 0; // will be taken of first real character + nParseTokensType = 0; // will be taken from first real character r.TokenType = KParseType::DOUBLE_QUOTE_STRING; } else if ( nMask & ParserFlags::CHAR_DONTCARE ) @@ -852,7 +854,7 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32 { if (current == cGroupSep) { - // depending or requested nContTypes, accept only if + // depending on requested nContTypes, accept only if // it is followed by 3 digits sal_Int32 tempIndex(index); sal_uInt32 const nextChar2((tempIndex < rText.getLength()) ? rText.iterateCodePoints(&tempIndex) : 0); diff --git a/i18npool/source/characterclassification/unoscripttypedetector.cxx b/i18npool/source/characterclassification/unoscripttypedetector.cxx index 673b486d73aa..20dd46ded31a 100644 --- a/i18npool/source/characterclassification/unoscripttypedetector.cxx +++ b/i18npool/source/characterclassification/unoscripttypedetector.cxx @@ -29,7 +29,7 @@ UnoScriptTypeDetector::getScriptDirection( const OUString& Text, sal_Int32 nPos, return ScriptTypeDetector::getScriptDirection(Text, nPos, defaultScriptDirection); } -// return value '-1' means either the direction on nPos is not same as scriptDirection or nPos is out of range. +// return value '-1' means either the direction of nPos is not the same as scriptDirection or nPos is out of range. sal_Int32 SAL_CALL UnoScriptTypeDetector::beginOfScriptDirection( const OUString& Text, sal_Int32 nPos, sal_Int16 direction ) { diff --git a/i18npool/source/collator/collator_unicode.cxx b/i18npool/source/collator/collator_unicode.cxx index 4e19eed9de23..352a34db141a 100644 --- a/i18npool/source/collator/collator_unicode.cxx +++ b/i18npool/source/collator/collator_unicode.cxx @@ -30,6 +30,7 @@ #include #include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::i18n; @@ -156,7 +157,7 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang:: size_t (*funclen)() = nullptr; #ifndef DISABLE_DYNLOADING - static constexpr OUString sModuleName( u"" SAL_MODULENAME( "i18npool" ) ""_ustr ); + static constexpr OUString sModuleName( u"" SVLIBRARY( "i18npool" ) ""_ustr ); hModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, SAL_LOADMODULE_DEFAULT ); if (hModule) { OUStringBuffer aBuf("get_collator_data_" + rLocale.Language + "_"); diff --git a/i18npool/source/indexentry/indexentrysupplier_default.cxx b/i18npool/source/indexentry/indexentrysupplier_default.cxx index 75f5038578ff..24df60360f39 100644 --- a/i18npool/source/indexentry/indexentrysupplier_default.cxx +++ b/i18npool/source/indexentry/indexentrysupplier_default.cxx @@ -225,7 +225,7 @@ void Index::makeIndexKeys(const lang::Locale &rLocale, std::u16string_view algor sal_Int16 end = i+1; for (; end < len && keyStr[end] != close; end++) ; - if (end >= len) // no found + if (end >= len) // not found throw RuntimeException(u"Index::makeIndexKeys: Closing bracket not found"_ustr); if (close == ')') keys[key_count-1].desc = keyStr.copy(i+1, end-i-1); diff --git a/i18npool/source/inputchecker/inputsequencechecker.cxx b/i18npool/source/inputchecker/inputsequencechecker.cxx index ff1ea652f980..8273add0a65c 100644 --- a/i18npool/source/inputchecker/inputsequencechecker.cxx +++ b/i18npool/source/inputchecker/inputsequencechecker.cxx @@ -55,7 +55,7 @@ InputSequenceCheckerImpl::checkInputSequence(const OUString& Text, sal_Int32 nSt if (language) return getInputSequenceChecker(language)->checkInputSequence(Text, nStartPos, inputChar, inputCheckMode); else - return true; // not a checkable languages. + return true; // not a checkable language. } sal_Int32 SAL_CALL diff --git a/i18npool/source/localedata/data/ar_SA.xml b/i18npool/source/localedata/data/ar_SA.xml index f5189198d65a..7faebde1350b 100644 --- a/i18npool/source/localedata/data/ar_SA.xml +++ b/i18npool/source/localedata/data/ar_SA.xml @@ -52,7 +52,7 @@ م metric - + diff --git a/i18npool/source/localedata/data/eo.xml b/i18npool/source/localedata/data/eo.xml index ba718f92f4a1..86cd1f819cf6 100644 --- a/i18npool/source/localedata/data/eo.xml +++ b/i18npool/source/localedata/data/eo.xml @@ -222,7 +222,7 @@ ABCĈDEFGĜHĤIJĴKLMNOPRSŜTUŬVZ 0 - 1 + 2 p. pp. diff --git a/i18npool/source/localedata/data/sort-formats.awk b/i18npool/source/localedata/data/sort-formats.awk index 1ac040ddb75d..68340d2ce611 100755 --- a/i18npool/source/localedata/data/sort-formats.awk +++ b/i18npool/source/localedata/data/sort-formats.awk @@ -7,7 +7,7 @@ # 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/. -# Usage: gawk -f sort-formats-by-formatindex.awk [-v group=1] ll_CC.xml +# Usage: gawk -f sort-formats.awk [-v group=1] ll_CC.xml # # Sort the LC_FORMAT child elements FormatElement and their children by # formatindex="..." value for easier comparison between locales. diff --git a/i18npool/source/localedata/filewriter.cxx b/i18npool/source/localedata/filewriter.cxx index e6bafdee5e7c..629a794b6e4a 100644 --- a/i18npool/source/localedata/filewriter.cxx +++ b/i18npool/source/localedata/filewriter.cxx @@ -20,8 +20,7 @@ #include #include "LocaleNode.hxx" -// The document handler, which is needed for the saxparser -// The Documenthandler for reading sax +// The DocumentHandler for reading SAX OFileWriter::OFileWriter(const char *pcFile, const char *locale ): theLocale(locale) { diff --git a/i18npool/source/nativenumber/data/numberchar.h b/i18npool/source/nativenumber/data/numberchar.h index ec647b7b9ce0..01f522f835a5 100644 --- a/i18npool/source/nativenumber/data/numberchar.h +++ b/i18npool/source/nativenumber/data/numberchar.h @@ -95,7 +95,7 @@ const sal_Unicode NumberChar[][10] = { }; static sal_Unicode DecimalChar[] = { - 0x002E, // Half Width (Ascii) + 0x002E, // Half Width (ASCII) 0xFF0E, // Full Width 0xFF0E, // Chinese Lower 0x70B9, // S. Chinese Upper @@ -130,7 +130,7 @@ static sal_Unicode DecimalChar[] = { }; const sal_Unicode MinusChar[] = { - 0x002D, // Half Width (Ascii) + 0x002D, // Half Width (ASCII) 0xFF0D, // Full Width 0xFF0D, // Chinese Lower 0x8D1F, // S. Chinese Upper @@ -141,7 +141,7 @@ const sal_Unicode MinusChar[] = { 0xFF0D, // Korean Upper 0xFF0D, // Korean Hangul 0x0000, // Arabic Indic - 0x2212, // Est. Arabic Indic + 0x2212, // East Arabic Indic 0x0000, // Indic 0x0000, // Thai 0x0000, // Odia @@ -165,7 +165,7 @@ const sal_Unicode MinusChar[] = { }; static sal_uInt16 SeparatorChar[] = { - 0x002C, // Half Width (Ascii) + 0x002C, // Half Width (ASCII) 0xFF0C, // Full Width 0x3001, // Chinese Lower 0x3001, // S. Chinese Upper @@ -176,7 +176,7 @@ static sal_uInt16 SeparatorChar[] = { 0x002C, // Korean Upper 0x002C, // Korean Hangul 0x0000, // Arabic Indic - 0x066C, // Est. Arabic Indic + 0x066C, // East Arabic Indic 0x0000, // Indic 0x0000, // Thai 0x0000, // Odia diff --git a/i18npool/source/ordinalsuffix/ordinalsuffix.cxx b/i18npool/source/ordinalsuffix/ordinalsuffix.cxx index 482f540a1435..1f7c35faa9ec 100644 --- a/i18npool/source/ordinalsuffix/ordinalsuffix.cxx +++ b/i18npool/source/ordinalsuffix/ordinalsuffix.cxx @@ -65,7 +65,7 @@ namespace /* * For this method to properly return the ordinal suffix for other locales - * than english ones, ICU 4.2+ has to be used. + * than English ones, ICU 4.2+ has to be used. */ uno::Sequence< OUString > SAL_CALL OrdinalSuffixService::getOrdinalSuffix( sal_Int32 nNumber, const lang::Locale &rLocale ) @@ -126,7 +126,7 @@ uno::Sequence< OUString > SAL_CALL OrdinalSuffixService::getOrdinalSuffix( sal_I if (!bSimpleOrdinalSuffix) continue; - // Remove the number to get the prefix + // Remove the number to get the suffix sal_Int32 len = sValueWithNoOrdinal.getLength(); retVec.push_back(sValueWithOrdinal.copy(len)); } diff --git a/i18npool/source/search/textsearch.cxx b/i18npool/source/search/textsearch.cxx index ae0d1fab4f0d..cf24b282b44c 100644 --- a/i18npool/source/search/textsearch.cxx +++ b/i18npool/source/search/textsearch.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -117,7 +118,7 @@ OUString replacePunctuation( const OUString &rStr ) .replace(u'\u201E', '"') .replace(u'\u201F', '"'); } -}; +} TextSearch::TextSearch(const Reference < XComponentContext > & rxContext) : m_xContext( rxContext ) @@ -163,7 +164,7 @@ void TextSearch::setOptions2( const SearchOptions2& rOptions ) // match is not case-altered, leave case-(in)sensitive to regex engine. transliterateFlags &= ~TransliterationFlags::IGNORE_CASE; } - else if ( aSrchPara.searchString.indexOf('\'') > - 1 || aSrchPara.searchString.indexOf('"') > - 1 ) + else if ( aSrchPara.searchString.indexOf('\'') > -1 || aSrchPara.searchString.indexOf('"') > -1 ) { bSearchApostrophe = true; bReplaceApostrophe = isReplacePunctuation(aSrchPara.searchString); @@ -322,6 +323,12 @@ static sal_Int32 FindPosInSeq_Impl( const Sequence & rOff, sal_Int32 return static_cast(std::distance(rOff.begin(), pOff)); } +static auto nextCodePoint(std::u16string_view rStr, sal_Int32 nPos) +{ + o3tl::iterateCodePoints(rStr, &nPos); + return nPos; +} + SearchResult TextSearch::searchForward( const OUString& searchStr, sal_Int32 startPos, sal_Int32 endPos ) { std::unique_lock g(m_aMutex); @@ -391,7 +398,8 @@ SearchResult TextSearch::searchForward( const OUString& searchStr, sal_Int32 sta // Result offsets are negative (-1) if a group expression was // not matched. if (nStart >= 0) - sres_startOffsetRange[k] = (nStart < nOffsets ? offset[nStart] : (offset[nOffsets - 1] + 1)); + sres_startOffsetRange[k] = (nStart < nOffsets ? offset[nStart] + : nextCodePoint(searchStr, offset[nOffsets - 1])); // JP 20.6.2001: end is ever exclusive and then don't return // the position of the next character - return the // next position behind the last found character! @@ -400,7 +408,8 @@ SearchResult TextSearch::searchForward( const OUString& searchStr, sal_Int32 sta if (nStop >= 0) { if (nStop > 0) - sres_endOffsetRange[k] = offset[(nStop <= nOffsets ? nStop : nOffsets) - 1] + 1; + sres_endOffsetRange[k] = nextCodePoint(searchStr, + offset[(nStop <= nOffsets ? nStop : nOffsets) - 1]); else sres_endOffsetRange[k] = offset[0]; } @@ -440,9 +449,9 @@ SearchResult TextSearch::searchForward( const OUString& searchStr, sal_Int32 sta for ( int k = 0; k < sres2.startOffset.getLength(); k++ ) { if (sres2.startOffset[k]) - sres2_startOffsetRange[k] = offset[sres2.startOffset[k]-1] + 1; + sres2_startOffsetRange[k] = nextCodePoint(searchStr, offset[sres2.startOffset[k]-1]); if (sres2.endOffset[k]) - sres2_endOffsetRange[k] = offset[sres2.endOffset[k]-1] + 1; + sres2_endOffsetRange[k] = nextCodePoint(searchStr, offset[sres2.endOffset[k]-1]); } // pick first and long one @@ -515,7 +524,8 @@ SearchResult TextSearch::searchBackward( const OUString& searchStr, sal_Int32 st if (nStart >= 0) { if (nStart > 0) - sres_startOffsetRange[k] = offset[(nStart <= nOffsets ? nStart : nOffsets) - 1] + 1; + sres_startOffsetRange[k] = nextCodePoint(searchStr, + offset[(nStart <= nOffsets ? nStart : nOffsets) - 1]); else sres_startOffsetRange[k] = offset[0]; } @@ -525,7 +535,8 @@ SearchResult TextSearch::searchBackward( const OUString& searchStr, sal_Int32 st // "a b c" find "b" must return 2,3 and not 2,4!!! const sal_Int32 nStop = sres.endOffset[k]; if (nStop >= 0) - sres_endOffsetRange[k] = (nStop < nOffsets ? offset[nStop] : (offset[nOffsets - 1] + 1)); + sres_endOffsetRange[k] = (nStop < nOffsets ? offset[nStop] + : nextCodePoint(searchStr, offset[nOffsets - 1])); } } } @@ -562,9 +573,9 @@ SearchResult TextSearch::searchBackward( const OUString& searchStr, sal_Int32 st for( int k = 0; k < sres2.startOffset.getLength(); k++ ) { if (sres2.startOffset[k]) - sres2_startOffsetRange[k] = offset[sres2.startOffset[k]-1]+1; + sres2_startOffsetRange[k] = nextCodePoint(searchStr, offset[sres2.startOffset[k]-1]); if (sres2.endOffset[k]) - sres2_endOffsetRange[k] = offset[sres2.endOffset[k]-1]+1; + sres2_endOffsetRange[k] = nextCodePoint(searchStr, offset[sres2.endOffset[k]-1]); } // pick last and long one @@ -783,7 +794,7 @@ SearchResult TextSearch::NSrchFrwrd( std::unique_lock& /*rGuard*/, c return aRet; } -SearchResult TextSearch::NSrchBkwrd( std::unique_lock& /*rGuard*/,const OUString& searchStr, sal_Int32 startPos, sal_Int32 endPos ) +SearchResult TextSearch::NSrchBkwrd( std::unique_lock& /*rGuard*/, const OUString& searchStr, sal_Int32 startPos, sal_Int32 endPos ) { SearchResult aRet; aRet.subRegExpressions = 0; @@ -959,26 +970,8 @@ SearchResult TextSearch::RESrchFrwrd( std::unique_lock& /*rGuard*/, const icu::UnicodeString aSearchTargetStr(false, reinterpret_cast(searchStr.getStr()), searchStr.getLength()); pRegexMatcher->reset( aSearchTargetStr); - // search until there is a valid match - for(;;) - { - if (!lcl_findRegex( pRegexMatcher, startPos, endPos, nIcuErr)) - return aRet; - - // #i118887# ignore zero-length matches e.g. "a*" in "bc" - int nStartOfs = pRegexMatcher->start( nIcuErr); - int nEndOfs = pRegexMatcher->end( nIcuErr); - if( nStartOfs < nEndOfs) - break; - // If the zero-length match is behind the string, do not match it again - // and again until startPos reaches there. A match behind the string is - // a "$" anchor. - if (nStartOfs == endPos) - break; - // try at next position if there was a zero-length match - if( ++startPos >= endPos) - return aRet; - } + if (!lcl_findRegex( pRegexMatcher, startPos, endPos, nIcuErr)) + return aRet; // extract the result of the search const int nGroupCount = pRegexMatcher->groupCount(); diff --git a/i18npool/source/textconversion/textconversion_ko.cxx b/i18npool/source/textconversion/textconversion_ko.cxx index 2e77df454bc2..99d7f0c1fbfd 100644 --- a/i18npool/source/textconversion/textconversion_ko.cxx +++ b/i18npool/source/textconversion/textconversion_ko.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -132,8 +133,20 @@ TextConversion_ko::getCharConversions(std::u16string_view aText, sal_Int32 nStar sal_Int16 count = Hangul_ko[current].count; output.realloc(count); auto poutput = output.getArray(); - for (sal_Int16 i = 0; i < count; i++) - poutput[i] = OUString(ptr + i, 1); + + // split into single characters/code points + // (one code point can be represented by multiple UTF-16 code units) + const std::u16string_view sAllChars(ptr, count); + sal_Int32 nIndex = 0; + sal_Int32 nCodePointCount = 0; + while (o3tl::make_unsigned(nIndex) < sAllChars.size()) + { + auto nChar = o3tl::iterateCodePoints(sAllChars, &nIndex); + poutput[nCodePointCount] = OUString{&nChar, 1}; + nCodePointCount++; + } + output.realloc(nCodePointCount); + break; } } diff --git a/i18npool/source/transliteration/transliterationImpl.cxx b/i18npool/source/transliteration/transliterationImpl.cxx index c28bec179578..c7a03a5ad64c 100644 --- a/i18npool/source/transliteration/transliterationImpl.cxx +++ b/i18npool/source/transliteration/transliterationImpl.cxx @@ -155,7 +155,7 @@ TMList const TMlist[] = { // Modules ModulesNew // no enum defined for these trans. application has to use impl name to load them // TmItem2 (NumToCharArabic_Indic), // () (67) -// TmItem2 (NumToCharEstern_Arabic_Indic),// () (68) +// TmItem2 (NumToCharEastern_Arabic_Indic),// () (68) // TmItem2 (NumToCharIndic), // () (69) // TmItem2 (NumToCharThai), // () (70) {TransliterationModules(0), TransliterationModulesNew(0), nullptr} @@ -631,7 +631,7 @@ TransliterationImpl::loadModuleByName( std::u16string_view implName, if (body.is()) { body->loadModule(TransliterationModules(0), rLocale); // toUpper/toLoad need rLocale - // if the module is ignore case/kana/width, load caseignore for equals/compareString mothed + // if the module is ignore case/kana/width, load caseignore for equals/compareString method for (sal_Int16 i = 0; i < 3; i++) { if (o3tl::equalsAscii(implName, TMlist[i].implName)) { if (i == 0) // current module is caseignore diff --git a/i18npool/source/transliteration/transliteration_body.cxx b/i18npool/source/transliteration/transliteration_body.cxx index f4679571d510..a5578e92bbe6 100644 --- a/i18npool/source/transliteration/transliteration_body.cxx +++ b/i18npool/source/transliteration/transliteration_body.cxx @@ -72,7 +72,7 @@ static MappingType lcl_getMappingTypeForToggleCase( MappingType nMappingType, sa MappingType nRes = nMappingType; // take care of TOGGLE_CASE transliteration: - // nMappingType should not be a combination of flags, thuse we decide now + // nMappingType should not be a combination of flags, thus we decide now // which one to use. if (nMappingType == (MappingType::LowerToUpper | MappingType::UpperToLower)) { @@ -248,9 +248,9 @@ static OUString transliterate_titlecase_Impl( rtl::Reference< CharacterClassificationImpl > xCharClassImpl( new CharacterClassificationImpl( xContext ) ); // because xCharClassImpl.toTitle does not handle ligatures or Beta but will raise - // an exception we need to handle the first chara manually... + // an exception we need to handle the first character manually... - // we don't want to change surrogates by accident, thuse we use proper code point iteration + // we don't want to change surrogates by accident, thus we use proper code point iteration sal_uInt32 cFirstChar = aText.iterateCodePoints( &o3tl::temporary(sal_Int32(0)) ); OUString aResolvedLigature( &cFirstChar, 1 ); // toUpper can be used to properly resolve ligatures and characters like Beta diff --git a/i18nutil/qa/cppunit/test_kashida.cxx b/i18nutil/qa/cppunit/test_kashida.cxx index fa47e4cf135f..5dc4f966c970 100644 --- a/i18nutil/qa/cppunit/test_kashida.cxx +++ b/i18nutil/qa/cppunit/test_kashida.cxx @@ -27,6 +27,7 @@ public: void testNoZwnjExpansion(); void testExcludeInvalid(); void testSyriac(); + void testSyriacVowelMarks(); CPPUNIT_TEST_SUITE(KashidaTest); CPPUNIT_TEST(testCharacteristic); @@ -35,6 +36,7 @@ public: CPPUNIT_TEST(testNoZwnjExpansion); CPPUNIT_TEST(testExcludeInvalid); CPPUNIT_TEST(testSyriac); + CPPUNIT_TEST(testSyriacVowelMarks); CPPUNIT_TEST_SUITE_END(); }; @@ -125,31 +127,56 @@ void KashidaTest::testSyriac() aValid.resize(7, true); // - Start from end and work toward midpoint, then reverse direction - CPPUNIT_ASSERT_EQUAL(sal_Int32(5), - GetWordKashidaPosition(u"ܥܥܥܥܥܥܥ"_ustr, aValid).value().nIndex); + OUString aStr = u"ܥܥܥܥܥܥܥ"_ustr; + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), GetWordKashidaPosition(aStr, aValid).value().nIndex); aValid[5] = false; - CPPUNIT_ASSERT_EQUAL(sal_Int32(4), - GetWordKashidaPosition(u"ܥܥܥܥܥܥܥ"_ustr, aValid).value().nIndex); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), GetWordKashidaPosition(aStr, aValid).value().nIndex); aValid[4] = false; - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), - GetWordKashidaPosition(u"ܥܥܥܥܥܥܥ"_ustr, aValid).value().nIndex); - aValid[0] = false; - - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), - GetWordKashidaPosition(u"ܥܥܥܥܥܥܥ"_ustr, aValid).value().nIndex); - aValid[1] = false; - - CPPUNIT_ASSERT_EQUAL(sal_Int32(2), - GetWordKashidaPosition(u"ܥܥܥܥܥܥܥ"_ustr, aValid).value().nIndex); - aValid[2] = false; - - CPPUNIT_ASSERT_EQUAL(sal_Int32(3), - GetWordKashidaPosition(u"ܥܥܥܥܥܥܥ"_ustr, aValid).value().nIndex); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), GetWordKashidaPosition(aStr, aValid).value().nIndex); aValid[3] = false; - CPPUNIT_ASSERT(!GetWordKashidaPosition(u"ܥܥܥܥܥܥܥ"_ustr, aValid).has_value()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), GetWordKashidaPosition(aStr, aValid).value().nIndex); + aValid[0] = false; + + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), GetWordKashidaPosition(aStr, aValid).value().nIndex); + aValid[1] = false; + + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), GetWordKashidaPosition(aStr, aValid).value().nIndex); + aValid[2] = false; + + CPPUNIT_ASSERT(!GetWordKashidaPosition(aStr, aValid).has_value()); +} + +void KashidaTest::testSyriacVowelMarks() +{ + std::vector aValid; + aValid.resize(13, true); + + // - Start from end and work toward midpoint, then reverse direction + // - Ignoring vowel marks + OUString aStr = u"ܥܥܥܥܥ\u073F\u073Eܥ\u073F\u073Eܥ\u073F\u073E"_ustr; + CPPUNIT_ASSERT_EQUAL(sal_Int32(7), GetWordKashidaPosition(aStr, aValid).value().nIndex); + aValid[7] = false; + + // Without ignoring vowel marks, this would be 0 + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), GetWordKashidaPosition(aStr, aValid).value().nIndex); + aValid[4] = false; + + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), GetWordKashidaPosition(aStr, aValid).value().nIndex); + aValid[3] = false; + + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), GetWordKashidaPosition(aStr, aValid).value().nIndex); + aValid[0] = false; + + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), GetWordKashidaPosition(aStr, aValid).value().nIndex); + aValid[1] = false; + + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), GetWordKashidaPosition(aStr, aValid).value().nIndex); + aValid[2] = false; + + CPPUNIT_ASSERT(!GetWordKashidaPosition(aStr, aValid).has_value()); } CPPUNIT_TEST_SUITE_REGISTRATION(KashidaTest); diff --git a/i18nutil/source/utility/casefolding.cxx b/i18nutil/source/utility/casefolding.cxx index 52dbeb1ca1c5..67fc3f7e3abc 100644 --- a/i18nutil/source/utility/casefolding.cxx +++ b/i18nutil/source/utility/casefolding.cxx @@ -28,6 +28,8 @@ #include +#include + using namespace com::sun::star::lang; using namespace com::sun::star::uno; @@ -106,7 +108,7 @@ Mapping casefolding::getValue(const sal_Unicode* str, sal_Int32 pos, sal_Int32 l c = str[pos]; sal_Int16 address = -1; - if (c < SAL_N_ELEMENTS(CaseMappingIndex) * 256) + if (c < std::size(CaseMappingIndex) * 256) address = CaseMappingIndex[c >> 8]; if (address >= 0) { diff --git a/i18nutil/source/utility/casefolding_data.h b/i18nutil/source/utility/casefolding_data.h index 6c6c1bd357de..5110e5693ad5 100644 --- a/i18nutil/source/utility/casefolding_data.h +++ b/i18nutil/source/utility/casefolding_data.h @@ -849,7 +849,7 @@ Mapping const CaseMappingExtra[] = { {0x40, 2, {0x0073, 0x0073, 0x0000}}, // 0x1e9e (351 0x015F) }; -/* Following code need special handling +/* Following codes need special handling 0x0069, 0x00CC, 0x00CD, 0x0128, 0x012E, 0x0130, 0x0049, 0x004A, 0x0307, 0x03A3, */ diff --git a/i18nutil/source/utility/kashida.cxx b/i18nutil/source/utility/kashida.cxx index 5181f099d92c..3e235067d1df 100644 --- a/i18nutil/source/utility/kashida.cxx +++ b/i18nutil/source/utility/kashida.cxx @@ -330,6 +330,47 @@ GetWordKashidaPositionArabic(const OUString& rWord, const std::vector& pVa return std::nullopt; } +sal_Int32 GetSyriacWordMidpoint(const OUString& rWord) +{ + sal_Int32 nLowIndex = 0; + sal_Int32 nHighIndex = rWord.getLength() - 1; + + sal_Int32 nLowCount = 0; + sal_Int32 nHighCount = 0; + while (nLowIndex < nHighIndex) + { + if (nHighCount <= nLowCount) + { + if (!isTransparentChar(rWord[nHighIndex--])) + { + ++nHighCount; + } + } + else + { + if (!isTransparentChar(rWord[nLowIndex++])) + { + ++nLowCount; + } + } + } + + return nLowIndex; +} + +sal_Int32 GetSyriacWordEndpoint(const OUString& rWord) +{ + for (sal_Int32 nPos = rWord.getLength() - 1; nPos >= 0; --nPos) + { + if (!isTransparentChar(rWord[nPos])) + { + return nPos; + } + } + + return 0; +} + std::optional GetWordKashidaPositionSyriac(const OUString& rWord, const std::vector& pValidPositions) { @@ -348,7 +389,8 @@ GetWordKashidaPositionSyriac(const OUString& rWord, const std::vector& pVa // - First, work from the end of the word toward the midpoint // - Then, work from the beginning of the word toward the midpoint - sal_Int32 nWordMidpoint = nWordLen / 2; + sal_Int32 nWordMidpoint = GetSyriacWordMidpoint(rWord); + sal_Int32 nWordEndpoint = GetSyriacWordEndpoint(rWord); auto fnPositionValid = [&pValidPositions, &rWord](sal_Int32 nIdx) { // Exclusions: @@ -360,11 +402,11 @@ GetWordKashidaPositionSyriac(const OUString& rWord, const std::vector& pVa } sal_Unicode cCh = rWord[nIdx]; - return isSyriacChar(cCh); + return isSyriacChar(cCh) && !isTransparentChar(cCh); }; // End to midpoint - for (sal_Int32 i = nWordLen - 2; i > nWordMidpoint; --i) + for (sal_Int32 i = nWordEndpoint - 1; i >= nWordMidpoint; --i) { if (fnPositionValid(i)) { @@ -373,7 +415,7 @@ GetWordKashidaPositionSyriac(const OUString& rWord, const std::vector& pVa } // Beginning to midpoint - for (sal_Int32 i = 0; i <= nWordMidpoint; ++i) + for (sal_Int32 i = 0; i < nWordMidpoint; ++i) { if (fnPositionValid(i)) { diff --git a/i18nutil/source/utility/paper.cxx b/i18nutil/source/utility/paper.cxx index 80fd4633c93e..90fe363795f2 100644 --- a/i18nutil/source/utility/paper.cxx +++ b/i18nutil/source/utility/paper.cxx @@ -19,11 +19,12 @@ #include +#include + #include #include #include #include -#include #include #include #include @@ -159,7 +160,7 @@ constexpr PageDesc aDinTab[] = }; -const size_t nTabSize = SAL_N_ELEMENTS(aDinTab); +const size_t nTabSize = std::size(aDinTab); // tdf#151107 make this not just large enough for rounding errors on our side // but also large enough to match where the ppd side rounded up to the next @@ -240,7 +241,7 @@ PaperInfo PaperInfo::getSystemDefaultPaper() if (bInitialized) return aInstance; -#if ! defined(MACOSX) && ! defined(EMSCRIPTEN) +#if ! defined(MACOSX) && ! defined(__EMSCRIPTEN__) // try libpaper // #i78617# workaround missing paperconf command FILE* pPipe = popen( "paperconf 2>/dev/null", "r" ); @@ -277,7 +278,7 @@ PaperInfo PaperInfo::getSystemDefaultPaper() bool bHalve = false; - size_t const nExtraTabSize = SAL_N_ELEMENTS(aCustoms); + size_t const nExtraTabSize = std::size(aCustoms); for (size_t i = 0; i < nExtraTabSize; ++i) { if (o3tl::equalsIgnoreAsciiCase(aCustoms[i].aName, aPaper)) @@ -369,7 +370,7 @@ PaperInfo PaperInfo::getSystemDefaultPaper() PaperInfo::PaperInfo(Paper eType) : m_eType(eType) { - static_assert( SAL_N_ELEMENTS(aDinTab) == NUM_PAPER_ENTRIES, + static_assert( std::size(aDinTab) == NUM_PAPER_ENTRIES, "mismatch between array entries and enum values" ); m_nPaperWidth = aDinTab[m_eType].m_nWidth; diff --git a/i18nutil/source/utility/scriptclass.cxx b/i18nutil/source/utility/scriptclass.cxx index 843f654ac7d0..a0c6745de395 100644 --- a/i18nutil/source/utility/scriptclass.cxx +++ b/i18nutil/source/utility/scriptclass.cxx @@ -30,6 +30,8 @@ #include #include +#include + using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::i18n; @@ -77,8 +79,6 @@ const UBlock2Script scriptList[] = { { UBLOCK_LATIN_EXTENDED_C, UBLOCK_LATIN_EXTENDED_D, ScriptType::LATIN } }; -#define scriptListCount SAL_N_ELEMENTS(scriptList) - //always sets rScriptType //returns true for characters historically explicitly assigned to @@ -109,13 +109,13 @@ bool getCompatibilityScriptClassByBlock(sal_uInt32 currentChar, sal_Int16& rScri { UBlockCode block = ublock_getCode(currentChar); size_t i = 0; - while (i < scriptListCount) + while (i < std::size(scriptList)) { if (block <= scriptList[i].to) break; ++i; } - if (i < scriptListCount && block >= scriptList[i].from) + if (i < std::size(scriptList) && block >= scriptList[i].from) rScriptType = scriptList[i].script; else { diff --git a/i18nutil/source/utility/unicode_data.h b/i18nutil/source/utility/unicode_data.h index af23f9548892..255b6d298c5a 100644 --- a/i18nutil/source/utility/unicode_data.h +++ b/i18nutil/source/utility/unicode_data.h @@ -755,7 +755,7 @@ const sal_Unicode UnicodeScriptType[][2] = { {0xfe50, 0xfe6f}, // 83. Small Form Variants {0xfe70, 0xfefe}, // 84. Arabic Presentation Forms-B {0xfeff, 0xfeff}, // 85. kNoScript - {0xff00, 0xffef}, // 85. Halfwidth and Fullwidth Forms + {0xff00, 0xffef}, // 86. Halfwidth and Fullwidth Forms }; #endif diff --git a/icon-themes/breeze/cmd/32/insertenvelope.png b/icon-themes/breeze/cmd/32/insertenvelope.png index 2bf3e6515c09..3ce5853f59a5 100644 Binary files a/icon-themes/breeze/cmd/32/insertenvelope.png and b/icon-themes/breeze/cmd/32/insertenvelope.png differ diff --git a/icon-themes/breeze/cmd/32/sendfeedback.png b/icon-themes/breeze/cmd/32/sendfeedback.png deleted file mode 100644 index 3ce5853f59a5..000000000000 Binary files a/icon-themes/breeze/cmd/32/sendfeedback.png and /dev/null differ diff --git a/icon-themes/breeze/cmd/32/shortcutkeysdialog.png b/icon-themes/breeze/cmd/32/shortcutkeysdialog.png new file mode 100644 index 000000000000..a2fd856df80e Binary files /dev/null and b/icon-themes/breeze/cmd/32/shortcutkeysdialog.png differ diff --git a/icon-themes/breeze/cmd/32/signaturelinedialog.png b/icon-themes/breeze/cmd/32/signaturelinedialog.png index 6a966a10e5f0..2b501bb14b74 100644 Binary files a/icon-themes/breeze/cmd/32/signaturelinedialog.png and b/icon-themes/breeze/cmd/32/signaturelinedialog.png differ diff --git a/icon-themes/breeze/cmd/lc_autoformatapply.png b/icon-themes/breeze/cmd/lc_autoformatapply.png new file mode 100644 index 000000000000..cb33ef34471c Binary files /dev/null and b/icon-themes/breeze/cmd/lc_autoformatapply.png differ diff --git a/icon-themes/breeze/cmd/lc_insertenvelope.png b/icon-themes/breeze/cmd/lc_insertenvelope.png index 45d58ea03f44..f70595998872 100644 Binary files a/icon-themes/breeze/cmd/lc_insertenvelope.png and b/icon-themes/breeze/cmd/lc_insertenvelope.png differ diff --git a/icon-themes/breeze/cmd/lc_sendfeedback.png b/icon-themes/breeze/cmd/lc_sendfeedback.png deleted file mode 100644 index f70595998872..000000000000 Binary files a/icon-themes/breeze/cmd/lc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/breeze/cmd/lc_shortcutkeysdialog.png b/icon-themes/breeze/cmd/lc_shortcutkeysdialog.png new file mode 100644 index 000000000000..5e071e85d875 Binary files /dev/null and b/icon-themes/breeze/cmd/lc_shortcutkeysdialog.png differ diff --git a/icon-themes/breeze/cmd/lc_signaturelinedialog.png b/icon-themes/breeze/cmd/lc_signaturelinedialog.png index a0d64e6d91dd..1119e200bec4 100644 Binary files a/icon-themes/breeze/cmd/lc_signaturelinedialog.png and b/icon-themes/breeze/cmd/lc_signaturelinedialog.png differ diff --git a/icon-themes/breeze/cmd/sc_insertenvelope.png b/icon-themes/breeze/cmd/sc_insertenvelope.png index 157c0b36ff65..235c6b0c93d3 100644 Binary files a/icon-themes/breeze/cmd/sc_insertenvelope.png and b/icon-themes/breeze/cmd/sc_insertenvelope.png differ diff --git a/icon-themes/breeze/cmd/sc_sendfeedback.png b/icon-themes/breeze/cmd/sc_sendfeedback.png deleted file mode 100644 index 235c6b0c93d3..000000000000 Binary files a/icon-themes/breeze/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/breeze/cmd/sc_shortcutkeysdialog.png b/icon-themes/breeze/cmd/sc_shortcutkeysdialog.png new file mode 100644 index 000000000000..a6110b377a6f Binary files /dev/null and b/icon-themes/breeze/cmd/sc_shortcutkeysdialog.png differ diff --git a/icon-themes/breeze/cmd/sc_signaturelinedialog.png b/icon-themes/breeze/cmd/sc_signaturelinedialog.png index a33dad5952ef..daeb394170a1 100644 Binary files a/icon-themes/breeze/cmd/sc_signaturelinedialog.png and b/icon-themes/breeze/cmd/sc_signaturelinedialog.png differ diff --git a/icon-themes/breeze/res/recentdoc_pin.png b/icon-themes/breeze/res/recentdoc_pin.png index a022906f65c6..a22cce64c17c 100644 Binary files a/icon-themes/breeze/res/recentdoc_pin.png and b/icon-themes/breeze/res/recentdoc_pin.png differ diff --git a/icon-themes/breeze/res/recentdoc_pin_highlighted.png b/icon-themes/breeze/res/recentdoc_pin_highlighted.png index 877b80bfafe0..5dd6fd2d27e8 100644 Binary files a/icon-themes/breeze/res/recentdoc_pin_highlighted.png and b/icon-themes/breeze/res/recentdoc_pin_highlighted.png differ diff --git a/icon-themes/breeze_dark/cmd/32/insertenvelope.png b/icon-themes/breeze_dark/cmd/32/insertenvelope.png index 07cb042e516c..9a4affea06ae 100644 Binary files a/icon-themes/breeze_dark/cmd/32/insertenvelope.png and b/icon-themes/breeze_dark/cmd/32/insertenvelope.png differ diff --git a/icon-themes/breeze_dark/cmd/32/sendfeedback.png b/icon-themes/breeze_dark/cmd/32/sendfeedback.png deleted file mode 100644 index 9a4affea06ae..000000000000 Binary files a/icon-themes/breeze_dark/cmd/32/sendfeedback.png and /dev/null differ diff --git a/icon-themes/breeze_dark/cmd/32/shortcutkeysdialog.png b/icon-themes/breeze_dark/cmd/32/shortcutkeysdialog.png new file mode 100644 index 000000000000..0e88d977b3a8 Binary files /dev/null and b/icon-themes/breeze_dark/cmd/32/shortcutkeysdialog.png differ diff --git a/icon-themes/breeze_dark/cmd/32/signaturelinedialog.png b/icon-themes/breeze_dark/cmd/32/signaturelinedialog.png index 30c0269b584c..a256b098799d 100644 Binary files a/icon-themes/breeze_dark/cmd/32/signaturelinedialog.png and b/icon-themes/breeze_dark/cmd/32/signaturelinedialog.png differ diff --git a/icon-themes/breeze_dark/cmd/lc_autoformatapply.png b/icon-themes/breeze_dark/cmd/lc_autoformatapply.png new file mode 100644 index 000000000000..3d59e61c6af4 Binary files /dev/null and b/icon-themes/breeze_dark/cmd/lc_autoformatapply.png differ diff --git a/icon-themes/breeze_dark/cmd/lc_insertenvelope.png b/icon-themes/breeze_dark/cmd/lc_insertenvelope.png index b55efd01f6af..3fbed6e5dbf7 100644 Binary files a/icon-themes/breeze_dark/cmd/lc_insertenvelope.png and b/icon-themes/breeze_dark/cmd/lc_insertenvelope.png differ diff --git a/icon-themes/breeze_dark/cmd/lc_sendfeedback.png b/icon-themes/breeze_dark/cmd/lc_sendfeedback.png deleted file mode 100644 index 3fbed6e5dbf7..000000000000 Binary files a/icon-themes/breeze_dark/cmd/lc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/breeze_dark/cmd/lc_shortcutkeysdialog.png b/icon-themes/breeze_dark/cmd/lc_shortcutkeysdialog.png new file mode 100644 index 000000000000..d8b6ab24a960 Binary files /dev/null and b/icon-themes/breeze_dark/cmd/lc_shortcutkeysdialog.png differ diff --git a/icon-themes/breeze_dark/cmd/lc_signaturelinedialog.png b/icon-themes/breeze_dark/cmd/lc_signaturelinedialog.png index 7b73ded4f25c..d410a41f6ab8 100644 Binary files a/icon-themes/breeze_dark/cmd/lc_signaturelinedialog.png and b/icon-themes/breeze_dark/cmd/lc_signaturelinedialog.png differ diff --git a/icon-themes/breeze_dark/cmd/sc_insertenvelope.png b/icon-themes/breeze_dark/cmd/sc_insertenvelope.png index 5fa66325072c..81b4b2fa3c50 100644 Binary files a/icon-themes/breeze_dark/cmd/sc_insertenvelope.png and b/icon-themes/breeze_dark/cmd/sc_insertenvelope.png differ diff --git a/icon-themes/breeze_dark/cmd/sc_sendfeedback.png b/icon-themes/breeze_dark/cmd/sc_sendfeedback.png deleted file mode 100644 index 81b4b2fa3c50..000000000000 Binary files a/icon-themes/breeze_dark/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/breeze_dark/cmd/sc_shortcutkeysdialog.png b/icon-themes/breeze_dark/cmd/sc_shortcutkeysdialog.png new file mode 100644 index 000000000000..9f95464da991 Binary files /dev/null and b/icon-themes/breeze_dark/cmd/sc_shortcutkeysdialog.png differ diff --git a/icon-themes/breeze_dark/cmd/sc_signaturelinedialog.png b/icon-themes/breeze_dark/cmd/sc_signaturelinedialog.png index a33dad5952ef..32e67076effe 100644 Binary files a/icon-themes/breeze_dark/cmd/sc_signaturelinedialog.png and b/icon-themes/breeze_dark/cmd/sc_signaturelinedialog.png differ diff --git a/icon-themes/breeze_dark/res/recentdoc_pin.png b/icon-themes/breeze_dark/res/recentdoc_pin.png index a022906f65c6..bde1251a64b0 100644 Binary files a/icon-themes/breeze_dark/res/recentdoc_pin.png and b/icon-themes/breeze_dark/res/recentdoc_pin.png differ diff --git a/icon-themes/breeze_dark/res/recentdoc_pin_highlighted.png b/icon-themes/breeze_dark/res/recentdoc_pin_highlighted.png index 877b80bfafe0..e5266245f9d5 100644 Binary files a/icon-themes/breeze_dark/res/recentdoc_pin_highlighted.png and b/icon-themes/breeze_dark/res/recentdoc_pin_highlighted.png differ diff --git a/icon-themes/breeze_dark_svg/cmd/32/insertenvelope.svg b/icon-themes/breeze_dark_svg/cmd/32/insertenvelope.svg index 182b3e826a33..fad82995e6cb 100644 --- a/icon-themes/breeze_dark_svg/cmd/32/insertenvelope.svg +++ b/icon-themes/breeze_dark_svg/cmd/32/insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/32/sendfeedback.svg b/icon-themes/breeze_dark_svg/cmd/32/sendfeedback.svg deleted file mode 100644 index fad82995e6cb..000000000000 --- a/icon-themes/breeze_dark_svg/cmd/32/sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/32/shortcutkeysdialog.svg b/icon-themes/breeze_dark_svg/cmd/32/shortcutkeysdialog.svg new file mode 100644 index 000000000000..28b4f5a47a3b --- /dev/null +++ b/icon-themes/breeze_dark_svg/cmd/32/shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/32/signaturelinedialog.svg b/icon-themes/breeze_dark_svg/cmd/32/signaturelinedialog.svg index 88495fe461b2..de173556522f 100644 --- a/icon-themes/breeze_dark_svg/cmd/32/signaturelinedialog.svg +++ b/icon-themes/breeze_dark_svg/cmd/32/signaturelinedialog.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/lc_insertenvelope.svg b/icon-themes/breeze_dark_svg/cmd/lc_insertenvelope.svg index a84112ff3e69..c85603ad155d 100644 --- a/icon-themes/breeze_dark_svg/cmd/lc_insertenvelope.svg +++ b/icon-themes/breeze_dark_svg/cmd/lc_insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/lc_sendfeedback.svg b/icon-themes/breeze_dark_svg/cmd/lc_sendfeedback.svg deleted file mode 100644 index c85603ad155d..000000000000 --- a/icon-themes/breeze_dark_svg/cmd/lc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/lc_shortcutkeysdialog.svg b/icon-themes/breeze_dark_svg/cmd/lc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..577eb2d14391 --- /dev/null +++ b/icon-themes/breeze_dark_svg/cmd/lc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/lc_signaturelinedialog.svg b/icon-themes/breeze_dark_svg/cmd/lc_signaturelinedialog.svg index 0a6c158ec7bd..1399b9982c61 100644 --- a/icon-themes/breeze_dark_svg/cmd/lc_signaturelinedialog.svg +++ b/icon-themes/breeze_dark_svg/cmd/lc_signaturelinedialog.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/sc_insertenvelope.svg b/icon-themes/breeze_dark_svg/cmd/sc_insertenvelope.svg index dc52ca45c6c4..411abece2816 100644 --- a/icon-themes/breeze_dark_svg/cmd/sc_insertenvelope.svg +++ b/icon-themes/breeze_dark_svg/cmd/sc_insertenvelope.svg @@ -1 +1 @@ -/> \ No newline at end of file +/> \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/sc_sendfeedback.svg b/icon-themes/breeze_dark_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index 411abece2816..000000000000 --- a/icon-themes/breeze_dark_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ -/> \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/sc_shortcutkeysdialog.svg b/icon-themes/breeze_dark_svg/cmd/sc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..70743784854b --- /dev/null +++ b/icon-themes/breeze_dark_svg/cmd/sc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/cmd/sc_signaturelinedialog.svg b/icon-themes/breeze_dark_svg/cmd/sc_signaturelinedialog.svg index 2dbae4bf20b7..ed824d600ee8 100644 --- a/icon-themes/breeze_dark_svg/cmd/sc_signaturelinedialog.svg +++ b/icon-themes/breeze_dark_svg/cmd/sc_signaturelinedialog.svg @@ -1 +1 @@ - \ No newline at end of file +/> \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/res/recentdoc_pin.svg b/icon-themes/breeze_dark_svg/res/recentdoc_pin.svg index 32066cbe19a8..83439ed4ef10 100644 --- a/icon-themes/breeze_dark_svg/res/recentdoc_pin.svg +++ b/icon-themes/breeze_dark_svg/res/recentdoc_pin.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_dark_svg/res/recentdoc_pin_highlighted.svg b/icon-themes/breeze_dark_svg/res/recentdoc_pin_highlighted.svg index 3b58afd11a4e..265932320717 100644 --- a/icon-themes/breeze_dark_svg/res/recentdoc_pin_highlighted.svg +++ b/icon-themes/breeze_dark_svg/res/recentdoc_pin_highlighted.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/32/insertenvelope.svg b/icon-themes/breeze_svg/cmd/32/insertenvelope.svg index c2f43889dd8d..dd2fb731d823 100644 --- a/icon-themes/breeze_svg/cmd/32/insertenvelope.svg +++ b/icon-themes/breeze_svg/cmd/32/insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/32/sendfeedback.svg b/icon-themes/breeze_svg/cmd/32/sendfeedback.svg deleted file mode 100644 index dd2fb731d823..000000000000 --- a/icon-themes/breeze_svg/cmd/32/sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/32/shortcutkeysdialog.svg b/icon-themes/breeze_svg/cmd/32/shortcutkeysdialog.svg new file mode 100644 index 000000000000..e625e58c7fda --- /dev/null +++ b/icon-themes/breeze_svg/cmd/32/shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/32/signaturelinedialog.svg b/icon-themes/breeze_svg/cmd/32/signaturelinedialog.svg index e875fb23b3ee..8bc02842dd54 100644 --- a/icon-themes/breeze_svg/cmd/32/signaturelinedialog.svg +++ b/icon-themes/breeze_svg/cmd/32/signaturelinedialog.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/lc_insertenvelope.svg b/icon-themes/breeze_svg/cmd/lc_insertenvelope.svg index 90dc59bf7a7d..045154c4d464 100644 --- a/icon-themes/breeze_svg/cmd/lc_insertenvelope.svg +++ b/icon-themes/breeze_svg/cmd/lc_insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/lc_sendfeedback.svg b/icon-themes/breeze_svg/cmd/lc_sendfeedback.svg deleted file mode 100644 index 045154c4d464..000000000000 --- a/icon-themes/breeze_svg/cmd/lc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/lc_shortcutkeysdialog.svg b/icon-themes/breeze_svg/cmd/lc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..b8173f7a0fa8 --- /dev/null +++ b/icon-themes/breeze_svg/cmd/lc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/lc_signaturelinedialog.svg b/icon-themes/breeze_svg/cmd/lc_signaturelinedialog.svg index 5c45915cf732..2146f5ef374b 100644 --- a/icon-themes/breeze_svg/cmd/lc_signaturelinedialog.svg +++ b/icon-themes/breeze_svg/cmd/lc_signaturelinedialog.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/sc_insertenvelope.svg b/icon-themes/breeze_svg/cmd/sc_insertenvelope.svg index 7142f172b137..ff5176b3a95c 100644 --- a/icon-themes/breeze_svg/cmd/sc_insertenvelope.svg +++ b/icon-themes/breeze_svg/cmd/sc_insertenvelope.svg @@ -1 +1 @@ -/> \ No newline at end of file +/> \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/sc_sendfeedback.svg b/icon-themes/breeze_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index ff5176b3a95c..000000000000 --- a/icon-themes/breeze_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ -/> \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/sc_shortcutkeysdialog.svg b/icon-themes/breeze_svg/cmd/sc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..20e533f4bc49 --- /dev/null +++ b/icon-themes/breeze_svg/cmd/sc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/breeze_svg/cmd/sc_signaturelinedialog.svg b/icon-themes/breeze_svg/cmd/sc_signaturelinedialog.svg index 2dbae4bf20b7..4ca9ea1e35de 100644 --- a/icon-themes/breeze_svg/cmd/sc_signaturelinedialog.svg +++ b/icon-themes/breeze_svg/cmd/sc_signaturelinedialog.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_svg/res/recentdoc_pin.svg b/icon-themes/breeze_svg/res/recentdoc_pin.svg index 8854aa8919f1..fc081594944d 100644 --- a/icon-themes/breeze_svg/res/recentdoc_pin.svg +++ b/icon-themes/breeze_svg/res/recentdoc_pin.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/breeze_svg/res/recentdoc_pin_highlighted.svg b/icon-themes/breeze_svg/res/recentdoc_pin_highlighted.svg index b045ef068630..02ce3e041516 100644 --- a/icon-themes/breeze_svg/res/recentdoc_pin_highlighted.svg +++ b/icon-themes/breeze_svg/res/recentdoc_pin_highlighted.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/colibre/brand/shell/donate2.png b/icon-themes/colibre/brand/shell/donate2.png new file mode 100644 index 000000000000..ad44c983d52b Binary files /dev/null and b/icon-themes/colibre/brand/shell/donate2.png differ diff --git a/icon-themes/colibre/brand/shell/donate2.svg b/icon-themes/colibre/brand/shell/donate2.svg new file mode 100644 index 000000000000..f6f44284f7bc --- /dev/null +++ b/icon-themes/colibre/brand/shell/donate2.svg @@ -0,0 +1,44 @@ + + + + \ No newline at end of file diff --git a/icon-themes/colibre/brand/shell/donationbackground.png b/icon-themes/colibre/brand/shell/donationbackground.png deleted file mode 100644 index 0aba95e5ed85..000000000000 Binary files a/icon-themes/colibre/brand/shell/donationbackground.png and /dev/null differ diff --git a/icon-themes/colibre/chart2/res/correlationcircle_52x60.png b/icon-themes/colibre/chart2/res/correlationcircle_52x60.png new file mode 100644 index 000000000000..c0f0434e8c1b Binary files /dev/null and b/icon-themes/colibre/chart2/res/correlationcircle_52x60.png differ diff --git a/icon-themes/colibre/chart2/res/histogram_52x60_new.png b/icon-themes/colibre/chart2/res/histogram_52x60_new.png new file mode 100644 index 000000000000..d8c9a4340713 Binary files /dev/null and b/icon-themes/colibre/chart2/res/histogram_52x60_new.png differ diff --git a/icon-themes/colibre/chart2/res/typecorrelationcircle_16.png b/icon-themes/colibre/chart2/res/typecorrelationcircle_16.png new file mode 100644 index 000000000000..7c87ec093753 Binary files /dev/null and b/icon-themes/colibre/chart2/res/typecorrelationcircle_16.png differ diff --git a/icon-themes/colibre/chart2/res/typehistogram_16_new.png b/icon-themes/colibre/chart2/res/typehistogram_16_new.png new file mode 100644 index 000000000000..0bab3c3f7e82 Binary files /dev/null and b/icon-themes/colibre/chart2/res/typehistogram_16_new.png differ diff --git a/icon-themes/colibre/cmd/32/shortcutkeysdialog.png b/icon-themes/colibre/cmd/32/shortcutkeysdialog.png new file mode 100644 index 000000000000..83922241ffda Binary files /dev/null and b/icon-themes/colibre/cmd/32/shortcutkeysdialog.png differ diff --git a/icon-themes/colibre/cmd/lc_autoformatapply.png b/icon-themes/colibre/cmd/lc_autoformatapply.png new file mode 100644 index 000000000000..1d56a2817c33 Binary files /dev/null and b/icon-themes/colibre/cmd/lc_autoformatapply.png differ diff --git a/icon-themes/colibre/cmd/lc_shortcutkeysdialog.png b/icon-themes/colibre/cmd/lc_shortcutkeysdialog.png new file mode 100644 index 000000000000..4e7e65163e48 Binary files /dev/null and b/icon-themes/colibre/cmd/lc_shortcutkeysdialog.png differ diff --git a/icon-themes/colibre/cmd/sc_sendfeedback.png b/icon-themes/colibre/cmd/sc_sendfeedback.png deleted file mode 100644 index dae028b117fa..000000000000 Binary files a/icon-themes/colibre/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/colibre/cmd/sc_shortcutkeysdialog.png b/icon-themes/colibre/cmd/sc_shortcutkeysdialog.png new file mode 100644 index 000000000000..f9519773a0ba Binary files /dev/null and b/icon-themes/colibre/cmd/sc_shortcutkeysdialog.png differ diff --git a/icon-themes/colibre/links.txt b/icon-themes/colibre/links.txt index fad1d55d2e9a..bdce1375e745 100644 --- a/icon-themes/colibre/links.txt +++ b/icon-themes/colibre/links.txt @@ -1737,18 +1737,15 @@ cmd/sc_toolsmacroedit.png cmd/sc_basicideappear.png cmd/32/donation.png cmd/32/currencyfield.png cmd/32/helperdialog.png cmd/32/helpindex.png cmd/32/questionanswers.png cmd/32/browseview.png -cmd/32/sendfeedback.png cmd/32/insertenvelope.png cmd/lc_donation.png cmd/lc_currencyfield.png cmd/lc_helperdialog.png cmd/lc_helpindex.png cmd/lc_questionanswers.png cmd/lc_browseview.png -cmd/lc_sendfeedback.png cmd/lc_insertenvelope.png cmd/sc_about.png res/mainapp_16_8.png cmd/sc_donation.png cmd/sc_currencyfield.png cmd/sc_helperdialog.png cmd/sc_helpindex.png cmd/sc_questionanswers.png cmd/sc_browseview.png -cmd/sc_sendfeedback.png cmd/sc_insertenvelope.png # Math cmd/32/symbolcatalogue.png cmd/32/insertsymbol.png @@ -2221,6 +2218,10 @@ sd/res/page.png cmd/sc_adddirect.png sd/res/pipette.png cmd/sc_bmpmask.png sd/res/playblue_16.png cmd/sc_runbasic.png sd/res/sf02.png cmd/sc_presentationlayout.png +sd/res/sf02.png cmd/sc_drawinglayout.png +cmd/32/drawinglayout.png cmd/32/presentationlayout.png +cmd/lc_drawinglayout.png cmd/lc_presentationlayout.png +sd/res/sf02.png cmd/sc_presentationlayout.png sd/res/stopplayingblue_16.png cmd/sc_basicstop.png sd/res/time_16.png cmd/sc_timefield.png sd/res/waiticon.png cmd/sc_mediapause.png diff --git a/icon-themes/colibre/res/recentdoc_pin.png b/icon-themes/colibre/res/recentdoc_pin.png index a022906f65c6..a1df9cd9456f 100644 Binary files a/icon-themes/colibre/res/recentdoc_pin.png and b/icon-themes/colibre/res/recentdoc_pin.png differ diff --git a/icon-themes/colibre/res/recentdoc_pin_highlighted.png b/icon-themes/colibre/res/recentdoc_pin_highlighted.png index 877b80bfafe0..1f6d947af8b6 100644 Binary files a/icon-themes/colibre/res/recentdoc_pin_highlighted.png and b/icon-themes/colibre/res/recentdoc_pin_highlighted.png differ diff --git a/icon-themes/colibre/help/warning_large.png b/icon-themes/colibre/res/warn.png similarity index 100% rename from icon-themes/colibre/help/warning_large.png rename to icon-themes/colibre/res/warn.png diff --git a/icon-themes/colibre_dark/cmd/32/shortcutkeysdialog.png b/icon-themes/colibre_dark/cmd/32/shortcutkeysdialog.png new file mode 100644 index 000000000000..62ed82998d58 Binary files /dev/null and b/icon-themes/colibre_dark/cmd/32/shortcutkeysdialog.png differ diff --git a/icon-themes/colibre_dark/cmd/lc_autoformatapply.png b/icon-themes/colibre_dark/cmd/lc_autoformatapply.png new file mode 100644 index 000000000000..d47d9e6fd0d6 Binary files /dev/null and b/icon-themes/colibre_dark/cmd/lc_autoformatapply.png differ diff --git a/icon-themes/colibre_dark/cmd/lc_shortcutkeysdialog.png b/icon-themes/colibre_dark/cmd/lc_shortcutkeysdialog.png new file mode 100644 index 000000000000..a9984fc85c30 Binary files /dev/null and b/icon-themes/colibre_dark/cmd/lc_shortcutkeysdialog.png differ diff --git a/icon-themes/colibre_dark/cmd/sc_sendfeedback.png b/icon-themes/colibre_dark/cmd/sc_sendfeedback.png deleted file mode 100644 index 9a6d1286c0b0..000000000000 Binary files a/icon-themes/colibre_dark/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/colibre_dark/cmd/sc_shortcutkeysdialog.png b/icon-themes/colibre_dark/cmd/sc_shortcutkeysdialog.png new file mode 100644 index 000000000000..6f598153cd1b Binary files /dev/null and b/icon-themes/colibre_dark/cmd/sc_shortcutkeysdialog.png differ diff --git a/icon-themes/colibre_dark/links.txt b/icon-themes/colibre_dark/links.txt index 97820a1d4881..dc485dcf9c3e 100644 --- a/icon-themes/colibre_dark/links.txt +++ b/icon-themes/colibre_dark/links.txt @@ -1736,18 +1736,15 @@ cmd/sc_toolsmacroedit.png cmd/sc_basicideappear.png cmd/32/donation.png cmd/32/currencyfield.png cmd/32/helperdialog.png cmd/32/helpindex.png cmd/32/questionanswers.png cmd/32/browseview.png -cmd/32/sendfeedback.png cmd/32/insertenvelope.png cmd/lc_donation.png cmd/lc_currencyfield.png cmd/lc_helperdialog.png cmd/lc_helpindex.png cmd/lc_questionanswers.png cmd/lc_browseview.png -cmd/lc_sendfeedback.png cmd/lc_insertenvelope.png cmd/sc_about.png res/mainapp_16_8.png cmd/sc_donation.png cmd/sc_currencyfield.png cmd/sc_helperdialog.png cmd/sc_helpindex.png cmd/sc_questionanswers.png cmd/sc_browseview.png -cmd/sc_sendfeedback.png cmd/sc_insertenvelope.png # Math cmd/32/symbolcatalogue.png cmd/32/insertsymbol.png diff --git a/icon-themes/colibre_dark/res/recentdoc_pin.png b/icon-themes/colibre_dark/res/recentdoc_pin.png index a022906f65c6..b6dd80d3f76b 100644 Binary files a/icon-themes/colibre_dark/res/recentdoc_pin.png and b/icon-themes/colibre_dark/res/recentdoc_pin.png differ diff --git a/icon-themes/colibre_dark/res/recentdoc_pin_highlighted.png b/icon-themes/colibre_dark/res/recentdoc_pin_highlighted.png index 877b80bfafe0..b3ffab470072 100644 Binary files a/icon-themes/colibre_dark/res/recentdoc_pin_highlighted.png and b/icon-themes/colibre_dark/res/recentdoc_pin_highlighted.png differ diff --git a/icon-themes/colibre_dark_svg/cmd/32/shortcutkeysdialog.svg b/icon-themes/colibre_dark_svg/cmd/32/shortcutkeysdialog.svg new file mode 100644 index 000000000000..f975db996983 --- /dev/null +++ b/icon-themes/colibre_dark_svg/cmd/32/shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/colibre_dark_svg/cmd/lc_shortcutkeysdialog.svg b/icon-themes/colibre_dark_svg/cmd/lc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..c3794a66ae0a --- /dev/null +++ b/icon-themes/colibre_dark_svg/cmd/lc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/colibre_dark_svg/cmd/sc_sendfeedback.svg b/icon-themes/colibre_dark_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index 463f0c1bf09b..000000000000 --- a/icon-themes/colibre_dark_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1,2 +0,0 @@ - -/&gt; \ No newline at end of file diff --git a/icon-themes/colibre_dark_svg/cmd/sc_shortcutkeysdialog.svg b/icon-themes/colibre_dark_svg/cmd/sc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..8f1057a817a1 --- /dev/null +++ b/icon-themes/colibre_dark_svg/cmd/sc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/colibre_dark_svg/res/recentdoc_pin.svg b/icon-themes/colibre_dark_svg/res/recentdoc_pin.svg index 8854aa8919f1..872579afa5c5 100644 --- a/icon-themes/colibre_dark_svg/res/recentdoc_pin.svg +++ b/icon-themes/colibre_dark_svg/res/recentdoc_pin.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/colibre_dark_svg/res/recentdoc_pin_highlighted.svg b/icon-themes/colibre_dark_svg/res/recentdoc_pin_highlighted.svg index b045ef068630..959a6dd8047a 100644 --- a/icon-themes/colibre_dark_svg/res/recentdoc_pin_highlighted.svg +++ b/icon-themes/colibre_dark_svg/res/recentdoc_pin_highlighted.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/colibre_svg/cmd/32/shortcutkeysdialog.svg b/icon-themes/colibre_svg/cmd/32/shortcutkeysdialog.svg new file mode 100644 index 000000000000..734313f2ba7e --- /dev/null +++ b/icon-themes/colibre_svg/cmd/32/shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/colibre_svg/cmd/lc_shortcutkeysdialog.svg b/icon-themes/colibre_svg/cmd/lc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..6155430995bd --- /dev/null +++ b/icon-themes/colibre_svg/cmd/lc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/colibre_svg/cmd/sc_sendfeedback.svg b/icon-themes/colibre_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index 74704d474222..000000000000 --- a/icon-themes/colibre_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ -/> \ No newline at end of file diff --git a/icon-themes/colibre_svg/cmd/sc_shortcutkeysdialog.svg b/icon-themes/colibre_svg/cmd/sc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..b2e629b1ca2a --- /dev/null +++ b/icon-themes/colibre_svg/cmd/sc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/colibre_svg/res/recentdoc_pin.svg b/icon-themes/colibre_svg/res/recentdoc_pin.svg index 8854aa8919f1..5ab377f7be25 100644 --- a/icon-themes/colibre_svg/res/recentdoc_pin.svg +++ b/icon-themes/colibre_svg/res/recentdoc_pin.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/colibre_svg/res/recentdoc_pin_highlighted.svg b/icon-themes/colibre_svg/res/recentdoc_pin_highlighted.svg index 8854aa8919f1..60ca41e4caf9 100644 --- a/icon-themes/colibre_svg/res/recentdoc_pin_highlighted.svg +++ b/icon-themes/colibre_svg/res/recentdoc_pin_highlighted.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary/cmd/32/ar/recsave.png b/icon-themes/elementary/cmd/32/ar/recsave.png index 9df2e5e879a6..0002aa154a9f 100644 Binary files a/icon-themes/elementary/cmd/32/ar/recsave.png and b/icon-themes/elementary/cmd/32/ar/recsave.png differ diff --git a/icon-themes/elementary/cmd/32/insertenvelope.png b/icon-themes/elementary/cmd/32/insertenvelope.png index 69d11afae70b..92ab3a3b16ca 100644 Binary files a/icon-themes/elementary/cmd/32/insertenvelope.png and b/icon-themes/elementary/cmd/32/insertenvelope.png differ diff --git a/icon-themes/elementary/cmd/32/mailmergeprintdocuments.png b/icon-themes/elementary/cmd/32/mailmergeprintdocuments.png index 1d6b9a057684..28d9101923ed 100644 Binary files a/icon-themes/elementary/cmd/32/mailmergeprintdocuments.png and b/icon-themes/elementary/cmd/32/mailmergeprintdocuments.png differ diff --git a/icon-themes/elementary/cmd/32/mailmergesavedocuments.png b/icon-themes/elementary/cmd/32/mailmergesavedocuments.png index 9506752381c6..e3e29ae1ca21 100644 Binary files a/icon-themes/elementary/cmd/32/mailmergesavedocuments.png and b/icon-themes/elementary/cmd/32/mailmergesavedocuments.png differ diff --git a/icon-themes/elementary/cmd/32/open.png b/icon-themes/elementary/cmd/32/open.png index fc450817ba53..498af58996c5 100644 Binary files a/icon-themes/elementary/cmd/32/open.png and b/icon-themes/elementary/cmd/32/open.png differ diff --git a/icon-themes/elementary/cmd/32/openreadonly.png b/icon-themes/elementary/cmd/32/openreadonly.png index e2f8cceb4d8e..e7eecea8310f 100644 Binary files a/icon-themes/elementary/cmd/32/openreadonly.png and b/icon-themes/elementary/cmd/32/openreadonly.png differ diff --git a/icon-themes/elementary/cmd/32/openremote.png b/icon-themes/elementary/cmd/32/openremote.png index 1261aa7e6372..5d5d66ef2798 100644 Binary files a/icon-themes/elementary/cmd/32/openremote.png and b/icon-themes/elementary/cmd/32/openremote.png differ diff --git a/icon-themes/elementary/cmd/32/opentemplate.png b/icon-themes/elementary/cmd/32/opentemplate.png index ae5e4361f99a..15d2f525bd6a 100644 Binary files a/icon-themes/elementary/cmd/32/opentemplate.png and b/icon-themes/elementary/cmd/32/opentemplate.png differ diff --git a/icon-themes/elementary/cmd/32/printpreview.png b/icon-themes/elementary/cmd/32/printpreview.png index 9950ff4b89f6..c276369dc013 100644 Binary files a/icon-themes/elementary/cmd/32/printpreview.png and b/icon-themes/elementary/cmd/32/printpreview.png differ diff --git a/icon-themes/elementary/cmd/32/recsave.png b/icon-themes/elementary/cmd/32/recsave.png index f7d0b7d699b1..daf53e86e796 100644 Binary files a/icon-themes/elementary/cmd/32/recsave.png and b/icon-themes/elementary/cmd/32/recsave.png differ diff --git a/icon-themes/elementary/cmd/32/recsearch.png b/icon-themes/elementary/cmd/32/recsearch.png index eaca62bc31c2..55359df8a96e 100644 Binary files a/icon-themes/elementary/cmd/32/recsearch.png and b/icon-themes/elementary/cmd/32/recsearch.png differ diff --git a/icon-themes/elementary/cmd/32/save.png b/icon-themes/elementary/cmd/32/save.png index 0ca8742e62c3..c2089c797baf 100644 Binary files a/icon-themes/elementary/cmd/32/save.png and b/icon-themes/elementary/cmd/32/save.png differ diff --git a/icon-themes/elementary/cmd/32/saveacopy.png b/icon-themes/elementary/cmd/32/saveacopy.png index edaa4a48c1b2..fbc41c806ed4 100644 Binary files a/icon-themes/elementary/cmd/32/saveacopy.png and b/icon-themes/elementary/cmd/32/saveacopy.png differ diff --git a/icon-themes/elementary/cmd/32/saveall.png b/icon-themes/elementary/cmd/32/saveall.png index 4b58f2dcd972..7b35fc91c409 100644 Binary files a/icon-themes/elementary/cmd/32/saveall.png and b/icon-themes/elementary/cmd/32/saveall.png differ diff --git a/icon-themes/elementary/cmd/32/saveas.png b/icon-themes/elementary/cmd/32/saveas.png index edd8df6027b7..ffd4b5dbcea5 100644 Binary files a/icon-themes/elementary/cmd/32/saveas.png and b/icon-themes/elementary/cmd/32/saveas.png differ diff --git a/icon-themes/elementary/cmd/32/saveasremote.png b/icon-themes/elementary/cmd/32/saveasremote.png index 66fc1231a14d..6638847ac11f 100644 Binary files a/icon-themes/elementary/cmd/32/saveasremote.png and b/icon-themes/elementary/cmd/32/saveasremote.png differ diff --git a/icon-themes/elementary/cmd/32/savebackground.png b/icon-themes/elementary/cmd/32/savebackground.png index 129c09ff3c93..a1d80f516181 100644 Binary files a/icon-themes/elementary/cmd/32/savebackground.png and b/icon-themes/elementary/cmd/32/savebackground.png differ diff --git a/icon-themes/elementary/cmd/32/scriptorganizer.png b/icon-themes/elementary/cmd/32/scriptorganizer.png index 75e0c5fb1d5b..09abbcfe7599 100644 Binary files a/icon-themes/elementary/cmd/32/scriptorganizer.png and b/icon-themes/elementary/cmd/32/scriptorganizer.png differ diff --git a/icon-themes/elementary/cmd/32/searchdialog.png b/icon-themes/elementary/cmd/32/searchdialog.png index a87d3d759cf4..c28ee316ae23 100644 Binary files a/icon-themes/elementary/cmd/32/searchdialog.png and b/icon-themes/elementary/cmd/32/searchdialog.png differ diff --git a/icon-themes/elementary/cmd/32/sendfeedback.png b/icon-themes/elementary/cmd/32/sendfeedback.png deleted file mode 100644 index 92ab3a3b16ca..000000000000 Binary files a/icon-themes/elementary/cmd/32/sendfeedback.png and /dev/null differ diff --git a/icon-themes/elementary/cmd/32/shortcutkeysdialog.png b/icon-themes/elementary/cmd/32/shortcutkeysdialog.png new file mode 100644 index 000000000000..891d4d2684f7 Binary files /dev/null and b/icon-themes/elementary/cmd/32/shortcutkeysdialog.png differ diff --git a/icon-themes/elementary/cmd/ar/lc_recsave.png b/icon-themes/elementary/cmd/ar/lc_recsave.png index ef305722e8b6..455a42ef042f 100644 Binary files a/icon-themes/elementary/cmd/ar/lc_recsave.png and b/icon-themes/elementary/cmd/ar/lc_recsave.png differ diff --git a/icon-themes/elementary/cmd/ar/sc_recsave.png b/icon-themes/elementary/cmd/ar/sc_recsave.png index 9054fde97adb..4cfaf4eac910 100644 Binary files a/icon-themes/elementary/cmd/ar/sc_recsave.png and b/icon-themes/elementary/cmd/ar/sc_recsave.png differ diff --git a/icon-themes/elementary/cmd/lc_addprintarea.png b/icon-themes/elementary/cmd/lc_addprintarea.png index 8ff12b60ce4b..5b1e6fc95960 100644 Binary files a/icon-themes/elementary/cmd/lc_addprintarea.png and b/icon-themes/elementary/cmd/lc_addprintarea.png differ diff --git a/icon-themes/elementary/cmd/lc_autoformatapply.png b/icon-themes/elementary/cmd/lc_autoformatapply.png new file mode 100644 index 000000000000..e15064d27ff3 Binary files /dev/null and b/icon-themes/elementary/cmd/lc_autoformatapply.png differ diff --git a/icon-themes/elementary/cmd/lc_defineprintarea.png b/icon-themes/elementary/cmd/lc_defineprintarea.png index f64ec324f4cb..fc41157b5158 100644 Binary files a/icon-themes/elementary/cmd/lc_defineprintarea.png and b/icon-themes/elementary/cmd/lc_defineprintarea.png differ diff --git a/icon-themes/elementary/cmd/lc_deleteprintarea.png b/icon-themes/elementary/cmd/lc_deleteprintarea.png index 7108bdb5afff..473e2a84c286 100644 Binary files a/icon-themes/elementary/cmd/lc_deleteprintarea.png and b/icon-themes/elementary/cmd/lc_deleteprintarea.png differ diff --git a/icon-themes/elementary/cmd/lc_editprintarea.png b/icon-themes/elementary/cmd/lc_editprintarea.png index 847698af6533..ded9ba13874c 100644 Binary files a/icon-themes/elementary/cmd/lc_editprintarea.png and b/icon-themes/elementary/cmd/lc_editprintarea.png differ diff --git a/icon-themes/elementary/cmd/lc_insertenvelope.png b/icon-themes/elementary/cmd/lc_insertenvelope.png index 15ec36c50940..dca2096ed44c 100644 Binary files a/icon-themes/elementary/cmd/lc_insertenvelope.png and b/icon-themes/elementary/cmd/lc_insertenvelope.png differ diff --git a/icon-themes/elementary/cmd/lc_mailmergesavedocuments.png b/icon-themes/elementary/cmd/lc_mailmergesavedocuments.png index 507bc5fd7b51..0ba0c7333a0a 100644 Binary files a/icon-themes/elementary/cmd/lc_mailmergesavedocuments.png and b/icon-themes/elementary/cmd/lc_mailmergesavedocuments.png differ diff --git a/icon-themes/elementary/cmd/lc_open.png b/icon-themes/elementary/cmd/lc_open.png index 47a99b3ed32f..b24b11864265 100644 Binary files a/icon-themes/elementary/cmd/lc_open.png and b/icon-themes/elementary/cmd/lc_open.png differ diff --git a/icon-themes/elementary/cmd/lc_openreadonly.png b/icon-themes/elementary/cmd/lc_openreadonly.png index 9c5951a893be..c2d2dd1cd14f 100644 Binary files a/icon-themes/elementary/cmd/lc_openreadonly.png and b/icon-themes/elementary/cmd/lc_openreadonly.png differ diff --git a/icon-themes/elementary/cmd/lc_openremote.png b/icon-themes/elementary/cmd/lc_openremote.png index 53c670db1776..37b84b865d64 100644 Binary files a/icon-themes/elementary/cmd/lc_openremote.png and b/icon-themes/elementary/cmd/lc_openremote.png differ diff --git a/icon-themes/elementary/cmd/lc_opentemplate.png b/icon-themes/elementary/cmd/lc_opentemplate.png new file mode 100644 index 000000000000..5982d97112da Binary files /dev/null and b/icon-themes/elementary/cmd/lc_opentemplate.png differ diff --git a/icon-themes/elementary/cmd/lc_printlayout.png b/icon-themes/elementary/cmd/lc_printlayout.png index 6871b04fc95b..cb81f64c3fed 100644 Binary files a/icon-themes/elementary/cmd/lc_printlayout.png and b/icon-themes/elementary/cmd/lc_printlayout.png differ diff --git a/icon-themes/elementary/cmd/lc_printpreview.png b/icon-themes/elementary/cmd/lc_printpreview.png index 3a8e4729c8cf..7a679332aae1 100644 Binary files a/icon-themes/elementary/cmd/lc_printpreview.png and b/icon-themes/elementary/cmd/lc_printpreview.png differ diff --git a/icon-themes/elementary/cmd/lc_recsave.png b/icon-themes/elementary/cmd/lc_recsave.png index 35f6a05e27d1..de8720ee996e 100644 Binary files a/icon-themes/elementary/cmd/lc_recsave.png and b/icon-themes/elementary/cmd/lc_recsave.png differ diff --git a/icon-themes/elementary/cmd/lc_recsearch.png b/icon-themes/elementary/cmd/lc_recsearch.png index b166399be9b3..5fa6468af478 100644 Binary files a/icon-themes/elementary/cmd/lc_recsearch.png and b/icon-themes/elementary/cmd/lc_recsearch.png differ diff --git a/icon-themes/elementary/cmd/lc_save.png b/icon-themes/elementary/cmd/lc_save.png index 05d96546c72a..876693c648c2 100644 Binary files a/icon-themes/elementary/cmd/lc_save.png and b/icon-themes/elementary/cmd/lc_save.png differ diff --git a/icon-themes/elementary/cmd/lc_saveacopy.png b/icon-themes/elementary/cmd/lc_saveacopy.png index 22191a3f1c57..61fd5c1a14d5 100644 Binary files a/icon-themes/elementary/cmd/lc_saveacopy.png and b/icon-themes/elementary/cmd/lc_saveacopy.png differ diff --git a/icon-themes/elementary/cmd/lc_saveall.png b/icon-themes/elementary/cmd/lc_saveall.png index 86c7f2afb3b4..fc2ad4b04047 100644 Binary files a/icon-themes/elementary/cmd/lc_saveall.png and b/icon-themes/elementary/cmd/lc_saveall.png differ diff --git a/icon-themes/elementary/cmd/lc_saveas.png b/icon-themes/elementary/cmd/lc_saveas.png index 9bfa0c00a73c..e68e9dde024a 100644 Binary files a/icon-themes/elementary/cmd/lc_saveas.png and b/icon-themes/elementary/cmd/lc_saveas.png differ diff --git a/icon-themes/elementary/cmd/lc_saveasremote.png b/icon-themes/elementary/cmd/lc_saveasremote.png index 2eef5ae5f17f..f77082c66003 100644 Binary files a/icon-themes/elementary/cmd/lc_saveasremote.png and b/icon-themes/elementary/cmd/lc_saveasremote.png differ diff --git a/icon-themes/elementary/cmd/lc_savebackground.png b/icon-themes/elementary/cmd/lc_savebackground.png index 5d4c2ab41bbc..18af38adb4fc 100644 Binary files a/icon-themes/elementary/cmd/lc_savebackground.png and b/icon-themes/elementary/cmd/lc_savebackground.png differ diff --git a/icon-themes/elementary/cmd/lc_scriptorganizer.png b/icon-themes/elementary/cmd/lc_scriptorganizer.png index d60c17604a64..c06cc7966fca 100644 Binary files a/icon-themes/elementary/cmd/lc_scriptorganizer.png and b/icon-themes/elementary/cmd/lc_scriptorganizer.png differ diff --git a/icon-themes/elementary/cmd/lc_searchdialog.png b/icon-themes/elementary/cmd/lc_searchdialog.png index 4ad73e817971..be8cdfc64a93 100644 Binary files a/icon-themes/elementary/cmd/lc_searchdialog.png and b/icon-themes/elementary/cmd/lc_searchdialog.png differ diff --git a/icon-themes/elementary/cmd/lc_sendfeedback.png b/icon-themes/elementary/cmd/lc_sendfeedback.png deleted file mode 100644 index dca2096ed44c..000000000000 Binary files a/icon-themes/elementary/cmd/lc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/elementary/cmd/lc_shortcutkeysdialog.png b/icon-themes/elementary/cmd/lc_shortcutkeysdialog.png new file mode 100644 index 000000000000..abfbaed08e02 Binary files /dev/null and b/icon-themes/elementary/cmd/lc_shortcutkeysdialog.png differ diff --git a/icon-themes/elementary/cmd/sc_addprintarea.png b/icon-themes/elementary/cmd/sc_addprintarea.png index cd9d7d11b905..d9c04c54cd6c 100644 Binary files a/icon-themes/elementary/cmd/sc_addprintarea.png and b/icon-themes/elementary/cmd/sc_addprintarea.png differ diff --git a/icon-themes/elementary/cmd/sc_defineprintarea.png b/icon-themes/elementary/cmd/sc_defineprintarea.png index 27e848236527..303ef4c76edf 100644 Binary files a/icon-themes/elementary/cmd/sc_defineprintarea.png and b/icon-themes/elementary/cmd/sc_defineprintarea.png differ diff --git a/icon-themes/elementary/cmd/sc_deleteprintarea.png b/icon-themes/elementary/cmd/sc_deleteprintarea.png index 76200a5a0363..b8ec7244e519 100644 Binary files a/icon-themes/elementary/cmd/sc_deleteprintarea.png and b/icon-themes/elementary/cmd/sc_deleteprintarea.png differ diff --git a/icon-themes/elementary/cmd/sc_editprintarea.png b/icon-themes/elementary/cmd/sc_editprintarea.png index 2cccbe6febd1..b487998e8009 100644 Binary files a/icon-themes/elementary/cmd/sc_editprintarea.png and b/icon-themes/elementary/cmd/sc_editprintarea.png differ diff --git a/icon-themes/elementary/cmd/sc_insertenvelope.png b/icon-themes/elementary/cmd/sc_insertenvelope.png index 1cae6caa5a3d..41e9ad15b75e 100644 Binary files a/icon-themes/elementary/cmd/sc_insertenvelope.png and b/icon-themes/elementary/cmd/sc_insertenvelope.png differ diff --git a/icon-themes/elementary/cmd/sc_mailmergeprintdocuments.png b/icon-themes/elementary/cmd/sc_mailmergeprintdocuments.png index 923b32a3e260..d4f8e351dd77 100644 Binary files a/icon-themes/elementary/cmd/sc_mailmergeprintdocuments.png and b/icon-themes/elementary/cmd/sc_mailmergeprintdocuments.png differ diff --git a/icon-themes/elementary/cmd/sc_mailmergesavedocuments.png b/icon-themes/elementary/cmd/sc_mailmergesavedocuments.png index 6e5933aa9263..9ac061886882 100644 Binary files a/icon-themes/elementary/cmd/sc_mailmergesavedocuments.png and b/icon-themes/elementary/cmd/sc_mailmergesavedocuments.png differ diff --git a/icon-themes/elementary/cmd/sc_open.png b/icon-themes/elementary/cmd/sc_open.png index 5bb8c0bac3ea..112ac33d3cc7 100644 Binary files a/icon-themes/elementary/cmd/sc_open.png and b/icon-themes/elementary/cmd/sc_open.png differ diff --git a/icon-themes/elementary/cmd/sc_openreadonly.png b/icon-themes/elementary/cmd/sc_openreadonly.png index 5d1ddd4a0360..caa50d43b99e 100644 Binary files a/icon-themes/elementary/cmd/sc_openreadonly.png and b/icon-themes/elementary/cmd/sc_openreadonly.png differ diff --git a/icon-themes/elementary/cmd/sc_openremote.png b/icon-themes/elementary/cmd/sc_openremote.png index d94b61bdbd53..25155161d32c 100644 Binary files a/icon-themes/elementary/cmd/sc_openremote.png and b/icon-themes/elementary/cmd/sc_openremote.png differ diff --git a/icon-themes/elementary/cmd/sc_opentemplate.png b/icon-themes/elementary/cmd/sc_opentemplate.png index f2c9ae82f502..085be6d61bc2 100644 Binary files a/icon-themes/elementary/cmd/sc_opentemplate.png and b/icon-themes/elementary/cmd/sc_opentemplate.png differ diff --git a/icon-themes/elementary/cmd/sc_print.png b/icon-themes/elementary/cmd/sc_print.png index 6c5d9eb94a8f..dcc2ff9c5327 100644 Binary files a/icon-themes/elementary/cmd/sc_print.png and b/icon-themes/elementary/cmd/sc_print.png differ diff --git a/icon-themes/elementary/cmd/sc_printdefault.png b/icon-themes/elementary/cmd/sc_printdefault.png index 128e73a8be3e..e847ad472cde 100644 Binary files a/icon-themes/elementary/cmd/sc_printdefault.png and b/icon-themes/elementary/cmd/sc_printdefault.png differ diff --git a/icon-themes/elementary/cmd/sc_printersetup.png b/icon-themes/elementary/cmd/sc_printersetup.png index 64367a89d216..5379a2907896 100644 Binary files a/icon-themes/elementary/cmd/sc_printersetup.png and b/icon-themes/elementary/cmd/sc_printersetup.png differ diff --git a/icon-themes/elementary/cmd/sc_printlayout.png b/icon-themes/elementary/cmd/sc_printlayout.png index 81641aa80d13..bea69ff5377c 100644 Binary files a/icon-themes/elementary/cmd/sc_printlayout.png and b/icon-themes/elementary/cmd/sc_printlayout.png differ diff --git a/icon-themes/elementary/cmd/sc_printpreview.png b/icon-themes/elementary/cmd/sc_printpreview.png index 135e75922476..70df44b92e00 100644 Binary files a/icon-themes/elementary/cmd/sc_printpreview.png and b/icon-themes/elementary/cmd/sc_printpreview.png differ diff --git a/icon-themes/elementary/cmd/sc_recsave.png b/icon-themes/elementary/cmd/sc_recsave.png index 3fe4fd355001..6a11d3dfdb33 100644 Binary files a/icon-themes/elementary/cmd/sc_recsave.png and b/icon-themes/elementary/cmd/sc_recsave.png differ diff --git a/icon-themes/elementary/cmd/sc_recsearch.png b/icon-themes/elementary/cmd/sc_recsearch.png index 3c6b4d90aa62..1a2755eaaa90 100644 Binary files a/icon-themes/elementary/cmd/sc_recsearch.png and b/icon-themes/elementary/cmd/sc_recsearch.png differ diff --git a/icon-themes/elementary/cmd/sc_save.png b/icon-themes/elementary/cmd/sc_save.png index d01a21a453df..5cc4a4aa0c6c 100644 Binary files a/icon-themes/elementary/cmd/sc_save.png and b/icon-themes/elementary/cmd/sc_save.png differ diff --git a/icon-themes/elementary/cmd/sc_saveacopy.png b/icon-themes/elementary/cmd/sc_saveacopy.png index 6015a367f160..9738baf39915 100644 Binary files a/icon-themes/elementary/cmd/sc_saveacopy.png and b/icon-themes/elementary/cmd/sc_saveacopy.png differ diff --git a/icon-themes/elementary/cmd/sc_saveall.png b/icon-themes/elementary/cmd/sc_saveall.png index 093a511a7e1f..0e0eab030e45 100644 Binary files a/icon-themes/elementary/cmd/sc_saveall.png and b/icon-themes/elementary/cmd/sc_saveall.png differ diff --git a/icon-themes/elementary/cmd/sc_saveas.png b/icon-themes/elementary/cmd/sc_saveas.png index bb40402d5ae6..db5cf74cb5fb 100644 Binary files a/icon-themes/elementary/cmd/sc_saveas.png and b/icon-themes/elementary/cmd/sc_saveas.png differ diff --git a/icon-themes/elementary/cmd/sc_saveasremote.png b/icon-themes/elementary/cmd/sc_saveasremote.png index 57bdfdd2d205..1b1949df3078 100644 Binary files a/icon-themes/elementary/cmd/sc_saveasremote.png and b/icon-themes/elementary/cmd/sc_saveasremote.png differ diff --git a/icon-themes/elementary/cmd/sc_savebackground.png b/icon-themes/elementary/cmd/sc_savebackground.png index 9212802d1f7b..fae150a96b88 100644 Binary files a/icon-themes/elementary/cmd/sc_savebackground.png and b/icon-themes/elementary/cmd/sc_savebackground.png differ diff --git a/icon-themes/elementary/cmd/sc_scriptorganizer.png b/icon-themes/elementary/cmd/sc_scriptorganizer.png index eeb79e6c2f9a..67572aad6ec7 100644 Binary files a/icon-themes/elementary/cmd/sc_scriptorganizer.png and b/icon-themes/elementary/cmd/sc_scriptorganizer.png differ diff --git a/icon-themes/elementary/cmd/sc_searchdialog.png b/icon-themes/elementary/cmd/sc_searchdialog.png index 4d2edb8948e9..0bec7035c058 100644 Binary files a/icon-themes/elementary/cmd/sc_searchdialog.png and b/icon-themes/elementary/cmd/sc_searchdialog.png differ diff --git a/icon-themes/elementary/cmd/sc_sendfeedback.png b/icon-themes/elementary/cmd/sc_sendfeedback.png deleted file mode 100644 index 41e9ad15b75e..000000000000 Binary files a/icon-themes/elementary/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/elementary/cmd/sc_shortcutkeysdialog.png b/icon-themes/elementary/cmd/sc_shortcutkeysdialog.png new file mode 100644 index 000000000000..4ffb879b4a28 Binary files /dev/null and b/icon-themes/elementary/cmd/sc_shortcutkeysdialog.png differ diff --git a/icon-themes/elementary/dbaccess/res/lc039.png b/icon-themes/elementary/dbaccess/res/lc039.png index 4f7630f8d5bc..07404701586e 100644 Binary files a/icon-themes/elementary/dbaccess/res/lc039.png and b/icon-themes/elementary/dbaccess/res/lc039.png differ diff --git a/icon-themes/elementary/framework/res/folder_32.png b/icon-themes/elementary/framework/res/folder_32.png index fc450817ba53..498af58996c5 100644 Binary files a/icon-themes/elementary/framework/res/folder_32.png and b/icon-themes/elementary/framework/res/folder_32.png differ diff --git a/icon-themes/elementary/framework/res/recent-documents.png b/icon-themes/elementary/framework/res/recent-documents.png index ad6458025146..d3e1e065aa1a 100644 Binary files a/icon-themes/elementary/framework/res/recent-documents.png and b/icon-themes/elementary/framework/res/recent-documents.png differ diff --git a/icon-themes/elementary/framework/res/remote-documents.png b/icon-themes/elementary/framework/res/remote-documents.png index 518f997b9d14..4f0ced14c349 100644 Binary files a/icon-themes/elementary/framework/res/remote-documents.png and b/icon-themes/elementary/framework/res/remote-documents.png differ diff --git a/icon-themes/elementary/framework/res/templates_32.png b/icon-themes/elementary/framework/res/templates_32.png index 0763c68940d8..bae6d7f31faf 100644 Binary files a/icon-themes/elementary/framework/res/templates_32.png and b/icon-themes/elementary/framework/res/templates_32.png differ diff --git a/icon-themes/elementary/res/dialogfolder_16.png b/icon-themes/elementary/res/dialogfolder_16.png index f5a4d85e33dc..53907268c4c9 100644 Binary files a/icon-themes/elementary/res/dialogfolder_16.png and b/icon-themes/elementary/res/dialogfolder_16.png differ diff --git a/icon-themes/elementary/res/fp015.png b/icon-themes/elementary/res/fp015.png index 96ca12646ca7..7aed9c635f67 100644 Binary files a/icon-themes/elementary/res/fp015.png and b/icon-themes/elementary/res/fp015.png differ diff --git a/icon-themes/elementary/res/inserthyperlink.png b/icon-themes/elementary/res/inserthyperlink.png index 072e2817b14f..a25f7966f8e4 100644 Binary files a/icon-themes/elementary/res/inserthyperlink.png and b/icon-themes/elementary/res/inserthyperlink.png differ diff --git a/icon-themes/elementary/res/recentdoc_pin.png b/icon-themes/elementary/res/recentdoc_pin.png index a022906f65c6..01de3a0c2ef4 100644 Binary files a/icon-themes/elementary/res/recentdoc_pin.png and b/icon-themes/elementary/res/recentdoc_pin.png differ diff --git a/icon-themes/elementary/res/recentdoc_pin_highlighted.png b/icon-themes/elementary/res/recentdoc_pin_highlighted.png index 877b80bfafe0..411c863e52ea 100644 Binary files a/icon-themes/elementary/res/recentdoc_pin_highlighted.png and b/icon-themes/elementary/res/recentdoc_pin_highlighted.png differ diff --git a/icon-themes/elementary/res/savemodified_extralarge.png b/icon-themes/elementary/res/savemodified_extralarge.png index 5d3685762886..d3e1d7a1955a 100644 Binary files a/icon-themes/elementary/res/savemodified_extralarge.png and b/icon-themes/elementary/res/savemodified_extralarge.png differ diff --git a/icon-themes/elementary/res/savemodified_large.png b/icon-themes/elementary/res/savemodified_large.png index 742027dce316..53016f3d6c28 100644 Binary files a/icon-themes/elementary/res/savemodified_large.png and b/icon-themes/elementary/res/savemodified_large.png differ diff --git a/icon-themes/elementary/res/savemodified_small.png b/icon-themes/elementary/res/savemodified_small.png index 89024570c578..e392c771f03a 100644 Binary files a/icon-themes/elementary/res/savemodified_small.png and b/icon-themes/elementary/res/savemodified_small.png differ diff --git a/icon-themes/elementary/res/unpin_document.png b/icon-themes/elementary/res/unpin_document.png new file mode 100644 index 000000000000..05b4e3a0fa3e Binary files /dev/null and b/icon-themes/elementary/res/unpin_document.png differ diff --git a/icon-themes/elementary/sfx2/res/actiontemplates017.png b/icon-themes/elementary/sfx2/res/actiontemplates017.png index abf5a2a6fe6d..3eb623a75359 100644 Binary files a/icon-themes/elementary/sfx2/res/actiontemplates017.png and b/icon-themes/elementary/sfx2/res/actiontemplates017.png differ diff --git a/icon-themes/elementary/sfx2/res/actionview026.png b/icon-themes/elementary/sfx2/res/actionview026.png index 53c670db1776..37b84b865d64 100644 Binary files a/icon-themes/elementary/sfx2/res/actionview026.png and b/icon-themes/elementary/sfx2/res/actionview026.png differ diff --git a/icon-themes/elementary/sfx2/res/actionview029.png b/icon-themes/elementary/sfx2/res/actionview029.png index 6ed1c415c00a..5a6d4d28b64f 100644 Binary files a/icon-themes/elementary/sfx2/res/actionview029.png and b/icon-themes/elementary/sfx2/res/actionview029.png differ diff --git a/icon-themes/elementary/svtools/res/folder.png b/icon-themes/elementary/svtools/res/folder.png index 6732e57f390b..5cf36fbbaa62 100644 Binary files a/icon-themes/elementary/svtools/res/folder.png and b/icon-themes/elementary/svtools/res/folder.png differ diff --git a/icon-themes/elementary/svx/res/doc_modified_yes.png b/icon-themes/elementary/svx/res/doc_modified_yes.png index 32bf101b856b..97b0fff7416d 100644 Binary files a/icon-themes/elementary/svx/res/doc_modified_yes.png and b/icon-themes/elementary/svx/res/doc_modified_yes.png differ diff --git a/icon-themes/elementary/svx/res/galdefs.png b/icon-themes/elementary/svx/res/galdefs.png index 54e104e540e2..7b120bf005f0 100644 Binary files a/icon-themes/elementary/svx/res/galdefs.png and b/icon-themes/elementary/svx/res/galdefs.png differ diff --git a/icon-themes/elementary/svx/res/galnorl.png b/icon-themes/elementary/svx/res/galnorl.png index 22a01d771d11..859ad87c5a05 100644 Binary files a/icon-themes/elementary/svx/res/galnorl.png and b/icon-themes/elementary/svx/res/galnorl.png differ diff --git a/icon-themes/elementary/svx/res/galnors.png b/icon-themes/elementary/svx/res/galnors.png index 57341728962f..6a1f9f562454 100644 Binary files a/icon-themes/elementary/svx/res/galnors.png and b/icon-themes/elementary/svx/res/galnors.png differ diff --git a/icon-themes/elementary/svx/res/galrdefl.png b/icon-themes/elementary/svx/res/galrdefl.png index 0e29d57c4454..6bdcbd63d46d 100644 Binary files a/icon-themes/elementary/svx/res/galrdefl.png and b/icon-themes/elementary/svx/res/galrdefl.png differ diff --git a/icon-themes/elementary/svx/res/galrdol.png b/icon-themes/elementary/svx/res/galrdol.png index 5e296506f2ee..fbf17cfc2abd 100644 Binary files a/icon-themes/elementary/svx/res/galrdol.png and b/icon-themes/elementary/svx/res/galrdol.png differ diff --git a/icon-themes/elementary/xmlsecurity/res/certificate_16.png b/icon-themes/elementary/xmlsecurity/res/certificate_16.png index 812da3114c30..5f2f05f77c49 100644 Binary files a/icon-themes/elementary/xmlsecurity/res/certificate_16.png and b/icon-themes/elementary/xmlsecurity/res/certificate_16.png differ diff --git a/icon-themes/elementary_svg/cmd/32/ar/recsave.svg b/icon-themes/elementary_svg/cmd/32/ar/recsave.svg index 95cd1e75cc5c..c2bd37e9696e 100644 --- a/icon-themes/elementary_svg/cmd/32/ar/recsave.svg +++ b/icon-themes/elementary_svg/cmd/32/ar/recsave.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/insertenvelope.svg b/icon-themes/elementary_svg/cmd/32/insertenvelope.svg index 210fb5b9c946..702d4f35bfe4 100644 --- a/icon-themes/elementary_svg/cmd/32/insertenvelope.svg +++ b/icon-themes/elementary_svg/cmd/32/insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/mailmergeprintdocuments.svg b/icon-themes/elementary_svg/cmd/32/mailmergeprintdocuments.svg index 0ac2d5e2057c..19a196250c47 100644 --- a/icon-themes/elementary_svg/cmd/32/mailmergeprintdocuments.svg +++ b/icon-themes/elementary_svg/cmd/32/mailmergeprintdocuments.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/mailmergesavedocuments.svg b/icon-themes/elementary_svg/cmd/32/mailmergesavedocuments.svg index 0838597af112..1141db7f8d0d 100644 --- a/icon-themes/elementary_svg/cmd/32/mailmergesavedocuments.svg +++ b/icon-themes/elementary_svg/cmd/32/mailmergesavedocuments.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/open.svg b/icon-themes/elementary_svg/cmd/32/open.svg index 92b903c2498a..a440fa8cbd00 100644 --- a/icon-themes/elementary_svg/cmd/32/open.svg +++ b/icon-themes/elementary_svg/cmd/32/open.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/openreadonly.svg b/icon-themes/elementary_svg/cmd/32/openreadonly.svg index 8ab34b1bcfa1..37ba67c1e828 100644 --- a/icon-themes/elementary_svg/cmd/32/openreadonly.svg +++ b/icon-themes/elementary_svg/cmd/32/openreadonly.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/openremote.svg b/icon-themes/elementary_svg/cmd/32/openremote.svg index 298521ace5cd..0793c5a79d92 100644 --- a/icon-themes/elementary_svg/cmd/32/openremote.svg +++ b/icon-themes/elementary_svg/cmd/32/openremote.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/opentemplate.svg b/icon-themes/elementary_svg/cmd/32/opentemplate.svg index 56b06584a978..fce865c05c31 100644 --- a/icon-themes/elementary_svg/cmd/32/opentemplate.svg +++ b/icon-themes/elementary_svg/cmd/32/opentemplate.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/printpreview.svg b/icon-themes/elementary_svg/cmd/32/printpreview.svg index f53b9d817ffb..3e654a7e8180 100644 --- a/icon-themes/elementary_svg/cmd/32/printpreview.svg +++ b/icon-themes/elementary_svg/cmd/32/printpreview.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/recsave.svg b/icon-themes/elementary_svg/cmd/32/recsave.svg index 633731a5c974..a1c62d463524 100644 --- a/icon-themes/elementary_svg/cmd/32/recsave.svg +++ b/icon-themes/elementary_svg/cmd/32/recsave.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/recsearch.svg b/icon-themes/elementary_svg/cmd/32/recsearch.svg index ae61533af4a6..96e9919e339a 100644 --- a/icon-themes/elementary_svg/cmd/32/recsearch.svg +++ b/icon-themes/elementary_svg/cmd/32/recsearch.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/save.svg b/icon-themes/elementary_svg/cmd/32/save.svg index ad5cc431b346..6df1d323e94b 100644 --- a/icon-themes/elementary_svg/cmd/32/save.svg +++ b/icon-themes/elementary_svg/cmd/32/save.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/saveacopy.svg b/icon-themes/elementary_svg/cmd/32/saveacopy.svg index 68080b1f9806..ea4d9baefe95 100644 --- a/icon-themes/elementary_svg/cmd/32/saveacopy.svg +++ b/icon-themes/elementary_svg/cmd/32/saveacopy.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/saveall.svg b/icon-themes/elementary_svg/cmd/32/saveall.svg index efb7eb5ecbca..0ff41e70daf9 100644 --- a/icon-themes/elementary_svg/cmd/32/saveall.svg +++ b/icon-themes/elementary_svg/cmd/32/saveall.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/saveas.svg b/icon-themes/elementary_svg/cmd/32/saveas.svg index c43770651cd1..78d0490ae41b 100644 --- a/icon-themes/elementary_svg/cmd/32/saveas.svg +++ b/icon-themes/elementary_svg/cmd/32/saveas.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/saveasremote.svg b/icon-themes/elementary_svg/cmd/32/saveasremote.svg index 75712e177666..db53a2053eb5 100644 --- a/icon-themes/elementary_svg/cmd/32/saveasremote.svg +++ b/icon-themes/elementary_svg/cmd/32/saveasremote.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/savebackground.svg b/icon-themes/elementary_svg/cmd/32/savebackground.svg index 63383388d164..c5e303141e3e 100644 --- a/icon-themes/elementary_svg/cmd/32/savebackground.svg +++ b/icon-themes/elementary_svg/cmd/32/savebackground.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/scriptorganizer.svg b/icon-themes/elementary_svg/cmd/32/scriptorganizer.svg index 6680ee2735bb..f84d6f2d2cd5 100644 --- a/icon-themes/elementary_svg/cmd/32/scriptorganizer.svg +++ b/icon-themes/elementary_svg/cmd/32/scriptorganizer.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/searchdialog.svg b/icon-themes/elementary_svg/cmd/32/searchdialog.svg index 0f1a7170251c..777fc779a424 100644 --- a/icon-themes/elementary_svg/cmd/32/searchdialog.svg +++ b/icon-themes/elementary_svg/cmd/32/searchdialog.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/sendfeedback.svg b/icon-themes/elementary_svg/cmd/32/sendfeedback.svg deleted file mode 100644 index 702d4f35bfe4..000000000000 --- a/icon-themes/elementary_svg/cmd/32/sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/32/shortcutkeysdialog.svg b/icon-themes/elementary_svg/cmd/32/shortcutkeysdialog.svg new file mode 100644 index 000000000000..09d8ecc6c083 --- /dev/null +++ b/icon-themes/elementary_svg/cmd/32/shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/ar/lc_recsave.svg b/icon-themes/elementary_svg/cmd/ar/lc_recsave.svg index 57fa04dcaee0..760158c0342a 100644 --- a/icon-themes/elementary_svg/cmd/ar/lc_recsave.svg +++ b/icon-themes/elementary_svg/cmd/ar/lc_recsave.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/ar/sc_recsave.svg b/icon-themes/elementary_svg/cmd/ar/sc_recsave.svg index 5e8ec807d2b3..32d9b552f21a 100644 --- a/icon-themes/elementary_svg/cmd/ar/sc_recsave.svg +++ b/icon-themes/elementary_svg/cmd/ar/sc_recsave.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_addprintarea.svg b/icon-themes/elementary_svg/cmd/lc_addprintarea.svg index 6adabf5c8a69..98c6aa69c8d0 100644 --- a/icon-themes/elementary_svg/cmd/lc_addprintarea.svg +++ b/icon-themes/elementary_svg/cmd/lc_addprintarea.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_defineprintarea.svg b/icon-themes/elementary_svg/cmd/lc_defineprintarea.svg index 1760357be071..2bb3eb154933 100644 --- a/icon-themes/elementary_svg/cmd/lc_defineprintarea.svg +++ b/icon-themes/elementary_svg/cmd/lc_defineprintarea.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_deleteprintarea.svg b/icon-themes/elementary_svg/cmd/lc_deleteprintarea.svg index 7795328b3840..13ff5d841755 100644 --- a/icon-themes/elementary_svg/cmd/lc_deleteprintarea.svg +++ b/icon-themes/elementary_svg/cmd/lc_deleteprintarea.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_editprintarea.svg b/icon-themes/elementary_svg/cmd/lc_editprintarea.svg index 7ddc8d3f4844..c34dfbee1905 100644 --- a/icon-themes/elementary_svg/cmd/lc_editprintarea.svg +++ b/icon-themes/elementary_svg/cmd/lc_editprintarea.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_insertenvelope.svg b/icon-themes/elementary_svg/cmd/lc_insertenvelope.svg index ea6e13c1db4c..276797c0b483 100644 --- a/icon-themes/elementary_svg/cmd/lc_insertenvelope.svg +++ b/icon-themes/elementary_svg/cmd/lc_insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_mailmergesavedocuments.svg b/icon-themes/elementary_svg/cmd/lc_mailmergesavedocuments.svg index bb3e4b799495..77c1efd29d2a 100644 --- a/icon-themes/elementary_svg/cmd/lc_mailmergesavedocuments.svg +++ b/icon-themes/elementary_svg/cmd/lc_mailmergesavedocuments.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_open.svg b/icon-themes/elementary_svg/cmd/lc_open.svg index 6f06319b5e2b..cbe786d1b087 100644 --- a/icon-themes/elementary_svg/cmd/lc_open.svg +++ b/icon-themes/elementary_svg/cmd/lc_open.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_openreadonly.svg b/icon-themes/elementary_svg/cmd/lc_openreadonly.svg index 3b74447293ff..f826c8d496f0 100644 --- a/icon-themes/elementary_svg/cmd/lc_openreadonly.svg +++ b/icon-themes/elementary_svg/cmd/lc_openreadonly.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_openremote.svg b/icon-themes/elementary_svg/cmd/lc_openremote.svg index c2355978d79d..54cda99c6a20 100644 --- a/icon-themes/elementary_svg/cmd/lc_openremote.svg +++ b/icon-themes/elementary_svg/cmd/lc_openremote.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_opentemplate.svg b/icon-themes/elementary_svg/cmd/lc_opentemplate.svg new file mode 100644 index 000000000000..c5b6df0973b6 --- /dev/null +++ b/icon-themes/elementary_svg/cmd/lc_opentemplate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_printlayout.svg b/icon-themes/elementary_svg/cmd/lc_printlayout.svg index 8ee253a859ff..bd39babd0b0d 100644 --- a/icon-themes/elementary_svg/cmd/lc_printlayout.svg +++ b/icon-themes/elementary_svg/cmd/lc_printlayout.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_printpreview.svg b/icon-themes/elementary_svg/cmd/lc_printpreview.svg index 3de9166f1a24..d303034cb990 100644 --- a/icon-themes/elementary_svg/cmd/lc_printpreview.svg +++ b/icon-themes/elementary_svg/cmd/lc_printpreview.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_recsave.svg b/icon-themes/elementary_svg/cmd/lc_recsave.svg index 13d56acbb040..d80c40877730 100644 --- a/icon-themes/elementary_svg/cmd/lc_recsave.svg +++ b/icon-themes/elementary_svg/cmd/lc_recsave.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_recsearch.svg b/icon-themes/elementary_svg/cmd/lc_recsearch.svg index 14ddbe72ffe1..0c5316fe8300 100644 --- a/icon-themes/elementary_svg/cmd/lc_recsearch.svg +++ b/icon-themes/elementary_svg/cmd/lc_recsearch.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_save.svg b/icon-themes/elementary_svg/cmd/lc_save.svg index 1267e714f682..33ee3a48661f 100644 --- a/icon-themes/elementary_svg/cmd/lc_save.svg +++ b/icon-themes/elementary_svg/cmd/lc_save.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_saveacopy.svg b/icon-themes/elementary_svg/cmd/lc_saveacopy.svg index cb4bbe9777a1..5c0608b41bff 100644 --- a/icon-themes/elementary_svg/cmd/lc_saveacopy.svg +++ b/icon-themes/elementary_svg/cmd/lc_saveacopy.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_saveall.svg b/icon-themes/elementary_svg/cmd/lc_saveall.svg index 6d71451cc7d7..32a5bdae6aa9 100644 --- a/icon-themes/elementary_svg/cmd/lc_saveall.svg +++ b/icon-themes/elementary_svg/cmd/lc_saveall.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_saveas.svg b/icon-themes/elementary_svg/cmd/lc_saveas.svg index b247d451f0ca..ad7611d1f922 100644 --- a/icon-themes/elementary_svg/cmd/lc_saveas.svg +++ b/icon-themes/elementary_svg/cmd/lc_saveas.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_saveasremote.svg b/icon-themes/elementary_svg/cmd/lc_saveasremote.svg index 765e15137441..b402402f74a1 100644 --- a/icon-themes/elementary_svg/cmd/lc_saveasremote.svg +++ b/icon-themes/elementary_svg/cmd/lc_saveasremote.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_savebackground.svg b/icon-themes/elementary_svg/cmd/lc_savebackground.svg index fa2137bab3bc..d0a069aa3bce 100644 --- a/icon-themes/elementary_svg/cmd/lc_savebackground.svg +++ b/icon-themes/elementary_svg/cmd/lc_savebackground.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_scriptorganizer.svg b/icon-themes/elementary_svg/cmd/lc_scriptorganizer.svg index ad7512bd3766..c0f6059e2c18 100644 --- a/icon-themes/elementary_svg/cmd/lc_scriptorganizer.svg +++ b/icon-themes/elementary_svg/cmd/lc_scriptorganizer.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_searchdialog.svg b/icon-themes/elementary_svg/cmd/lc_searchdialog.svg index 814e463f16bf..7c0ec9b23f54 100644 --- a/icon-themes/elementary_svg/cmd/lc_searchdialog.svg +++ b/icon-themes/elementary_svg/cmd/lc_searchdialog.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_sendfeedback.svg b/icon-themes/elementary_svg/cmd/lc_sendfeedback.svg deleted file mode 100644 index 276797c0b483..000000000000 --- a/icon-themes/elementary_svg/cmd/lc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/lc_shortcutkeysdialog.svg b/icon-themes/elementary_svg/cmd/lc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..b56501b4b24f --- /dev/null +++ b/icon-themes/elementary_svg/cmd/lc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_addprintarea.svg b/icon-themes/elementary_svg/cmd/sc_addprintarea.svg index b981ac35978d..7221b6973aba 100644 --- a/icon-themes/elementary_svg/cmd/sc_addprintarea.svg +++ b/icon-themes/elementary_svg/cmd/sc_addprintarea.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_defineprintarea.svg b/icon-themes/elementary_svg/cmd/sc_defineprintarea.svg index 695d0d1aad3c..0ff90245c9b1 100644 --- a/icon-themes/elementary_svg/cmd/sc_defineprintarea.svg +++ b/icon-themes/elementary_svg/cmd/sc_defineprintarea.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_deleteprintarea.svg b/icon-themes/elementary_svg/cmd/sc_deleteprintarea.svg index 76e2f8f8ff10..96ce192d9ea0 100644 --- a/icon-themes/elementary_svg/cmd/sc_deleteprintarea.svg +++ b/icon-themes/elementary_svg/cmd/sc_deleteprintarea.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_editprintarea.svg b/icon-themes/elementary_svg/cmd/sc_editprintarea.svg index 41093166a4e0..d6d28046ff7b 100644 --- a/icon-themes/elementary_svg/cmd/sc_editprintarea.svg +++ b/icon-themes/elementary_svg/cmd/sc_editprintarea.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_insertenvelope.svg b/icon-themes/elementary_svg/cmd/sc_insertenvelope.svg index 04c2f587e682..6a96b15b9e2d 100644 --- a/icon-themes/elementary_svg/cmd/sc_insertenvelope.svg +++ b/icon-themes/elementary_svg/cmd/sc_insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_mailmergeprintdocuments.svg b/icon-themes/elementary_svg/cmd/sc_mailmergeprintdocuments.svg index 91a10e997333..cef503659e68 100644 --- a/icon-themes/elementary_svg/cmd/sc_mailmergeprintdocuments.svg +++ b/icon-themes/elementary_svg/cmd/sc_mailmergeprintdocuments.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_mailmergesavedocuments.svg b/icon-themes/elementary_svg/cmd/sc_mailmergesavedocuments.svg index cf12e78a7982..747933e46537 100644 --- a/icon-themes/elementary_svg/cmd/sc_mailmergesavedocuments.svg +++ b/icon-themes/elementary_svg/cmd/sc_mailmergesavedocuments.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_open.svg b/icon-themes/elementary_svg/cmd/sc_open.svg index c5ebeb625b20..007df0b6ea33 100644 --- a/icon-themes/elementary_svg/cmd/sc_open.svg +++ b/icon-themes/elementary_svg/cmd/sc_open.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_openreadonly.svg b/icon-themes/elementary_svg/cmd/sc_openreadonly.svg index 6c367b4d3437..b75f7ab12a3d 100644 --- a/icon-themes/elementary_svg/cmd/sc_openreadonly.svg +++ b/icon-themes/elementary_svg/cmd/sc_openreadonly.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_openremote.svg b/icon-themes/elementary_svg/cmd/sc_openremote.svg index 59a7883eeaf0..49240708250c 100644 --- a/icon-themes/elementary_svg/cmd/sc_openremote.svg +++ b/icon-themes/elementary_svg/cmd/sc_openremote.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_opentemplate.svg b/icon-themes/elementary_svg/cmd/sc_opentemplate.svg index cf806dddde7a..340a8597f238 100644 --- a/icon-themes/elementary_svg/cmd/sc_opentemplate.svg +++ b/icon-themes/elementary_svg/cmd/sc_opentemplate.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_print.svg b/icon-themes/elementary_svg/cmd/sc_print.svg index e0ff0d10277e..a1f19993ce77 100644 --- a/icon-themes/elementary_svg/cmd/sc_print.svg +++ b/icon-themes/elementary_svg/cmd/sc_print.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_printdefault.svg b/icon-themes/elementary_svg/cmd/sc_printdefault.svg index 0d4602395386..164612bdf67c 100644 --- a/icon-themes/elementary_svg/cmd/sc_printdefault.svg +++ b/icon-themes/elementary_svg/cmd/sc_printdefault.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_printersetup.svg b/icon-themes/elementary_svg/cmd/sc_printersetup.svg index e25016338082..89ccb6a64d84 100644 --- a/icon-themes/elementary_svg/cmd/sc_printersetup.svg +++ b/icon-themes/elementary_svg/cmd/sc_printersetup.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_printlayout.svg b/icon-themes/elementary_svg/cmd/sc_printlayout.svg index fd27e6c6acf9..18aecc844ab6 100644 --- a/icon-themes/elementary_svg/cmd/sc_printlayout.svg +++ b/icon-themes/elementary_svg/cmd/sc_printlayout.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_printpreview.svg b/icon-themes/elementary_svg/cmd/sc_printpreview.svg index fee82daa0f84..8325f37eb3ca 100644 --- a/icon-themes/elementary_svg/cmd/sc_printpreview.svg +++ b/icon-themes/elementary_svg/cmd/sc_printpreview.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_recsave.svg b/icon-themes/elementary_svg/cmd/sc_recsave.svg index f49a247843a2..b71055501a19 100644 --- a/icon-themes/elementary_svg/cmd/sc_recsave.svg +++ b/icon-themes/elementary_svg/cmd/sc_recsave.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_recsearch.svg b/icon-themes/elementary_svg/cmd/sc_recsearch.svg index a9ce4632774e..646a9bf088f8 100644 --- a/icon-themes/elementary_svg/cmd/sc_recsearch.svg +++ b/icon-themes/elementary_svg/cmd/sc_recsearch.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_save.svg b/icon-themes/elementary_svg/cmd/sc_save.svg index 5e6fd4b8a4aa..f8d831d03471 100644 --- a/icon-themes/elementary_svg/cmd/sc_save.svg +++ b/icon-themes/elementary_svg/cmd/sc_save.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_saveacopy.svg b/icon-themes/elementary_svg/cmd/sc_saveacopy.svg index fc0ec94695c7..90b71fd31d6b 100644 --- a/icon-themes/elementary_svg/cmd/sc_saveacopy.svg +++ b/icon-themes/elementary_svg/cmd/sc_saveacopy.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_saveall.svg b/icon-themes/elementary_svg/cmd/sc_saveall.svg index 9193444dd051..c4a962ed9a65 100644 --- a/icon-themes/elementary_svg/cmd/sc_saveall.svg +++ b/icon-themes/elementary_svg/cmd/sc_saveall.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_saveas.svg b/icon-themes/elementary_svg/cmd/sc_saveas.svg index aa1ffafd1c23..8fad4a1c669d 100644 --- a/icon-themes/elementary_svg/cmd/sc_saveas.svg +++ b/icon-themes/elementary_svg/cmd/sc_saveas.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_saveasremote.svg b/icon-themes/elementary_svg/cmd/sc_saveasremote.svg index df4f179c7882..45d98fc09770 100644 --- a/icon-themes/elementary_svg/cmd/sc_saveasremote.svg +++ b/icon-themes/elementary_svg/cmd/sc_saveasremote.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_savebackground.svg b/icon-themes/elementary_svg/cmd/sc_savebackground.svg index 7f6b0c509181..73fae25119a4 100644 --- a/icon-themes/elementary_svg/cmd/sc_savebackground.svg +++ b/icon-themes/elementary_svg/cmd/sc_savebackground.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_scriptorganizer.svg b/icon-themes/elementary_svg/cmd/sc_scriptorganizer.svg index bf0793656d9d..ec9ad2329705 100644 --- a/icon-themes/elementary_svg/cmd/sc_scriptorganizer.svg +++ b/icon-themes/elementary_svg/cmd/sc_scriptorganizer.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_searchdialog.svg b/icon-themes/elementary_svg/cmd/sc_searchdialog.svg index 48cdf0983e13..b95977209a31 100644 --- a/icon-themes/elementary_svg/cmd/sc_searchdialog.svg +++ b/icon-themes/elementary_svg/cmd/sc_searchdialog.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_sendfeedback.svg b/icon-themes/elementary_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index 6a96b15b9e2d..000000000000 --- a/icon-themes/elementary_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/elementary_svg/cmd/sc_shortcutkeysdialog.svg b/icon-themes/elementary_svg/cmd/sc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..17e3d584fe63 --- /dev/null +++ b/icon-themes/elementary_svg/cmd/sc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/elementary_svg/dbaccess/res/lc039.svg b/icon-themes/elementary_svg/dbaccess/res/lc039.svg index be2fd5354cbb..ae259f6f939a 100644 --- a/icon-themes/elementary_svg/dbaccess/res/lc039.svg +++ b/icon-themes/elementary_svg/dbaccess/res/lc039.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/framework/res/folder_32.svg b/icon-themes/elementary_svg/framework/res/folder_32.svg index 92b903c2498a..a440fa8cbd00 100644 --- a/icon-themes/elementary_svg/framework/res/folder_32.svg +++ b/icon-themes/elementary_svg/framework/res/folder_32.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/framework/res/recent-documents.svg b/icon-themes/elementary_svg/framework/res/recent-documents.svg index 573e8d3da12c..d61efb847532 100644 --- a/icon-themes/elementary_svg/framework/res/recent-documents.svg +++ b/icon-themes/elementary_svg/framework/res/recent-documents.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/framework/res/remote-documents.svg b/icon-themes/elementary_svg/framework/res/remote-documents.svg index 88357b9f1863..d8602e0866a8 100644 --- a/icon-themes/elementary_svg/framework/res/remote-documents.svg +++ b/icon-themes/elementary_svg/framework/res/remote-documents.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/framework/res/templates_32.svg b/icon-themes/elementary_svg/framework/res/templates_32.svg index 237954be74e3..b3b2088e0386 100644 --- a/icon-themes/elementary_svg/framework/res/templates_32.svg +++ b/icon-themes/elementary_svg/framework/res/templates_32.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/res/dialogfolder_16.svg b/icon-themes/elementary_svg/res/dialogfolder_16.svg index 90050fc26b21..75aefff73fcf 100644 --- a/icon-themes/elementary_svg/res/dialogfolder_16.svg +++ b/icon-themes/elementary_svg/res/dialogfolder_16.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/res/fp015.svg b/icon-themes/elementary_svg/res/fp015.svg index cd87b669d869..c8aae5930322 100644 --- a/icon-themes/elementary_svg/res/fp015.svg +++ b/icon-themes/elementary_svg/res/fp015.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/res/inserthyperlink.svg b/icon-themes/elementary_svg/res/inserthyperlink.svg index eb1e08e55468..ee1175474911 100644 --- a/icon-themes/elementary_svg/res/inserthyperlink.svg +++ b/icon-themes/elementary_svg/res/inserthyperlink.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/res/recentdoc_pin.svg b/icon-themes/elementary_svg/res/recentdoc_pin.svg index 8854aa8919f1..cf577f135963 100644 --- a/icon-themes/elementary_svg/res/recentdoc_pin.svg +++ b/icon-themes/elementary_svg/res/recentdoc_pin.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/res/recentdoc_pin_highlighted.svg b/icon-themes/elementary_svg/res/recentdoc_pin_highlighted.svg index b045ef068630..26dab5e0efc0 100644 --- a/icon-themes/elementary_svg/res/recentdoc_pin_highlighted.svg +++ b/icon-themes/elementary_svg/res/recentdoc_pin_highlighted.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/res/savemodified_extralarge.svg b/icon-themes/elementary_svg/res/savemodified_extralarge.svg index 3f8eaa780b48..5f865467b8de 100644 --- a/icon-themes/elementary_svg/res/savemodified_extralarge.svg +++ b/icon-themes/elementary_svg/res/savemodified_extralarge.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/res/savemodified_large.svg b/icon-themes/elementary_svg/res/savemodified_large.svg index 3f2886830371..92eda5cb2808 100644 --- a/icon-themes/elementary_svg/res/savemodified_large.svg +++ b/icon-themes/elementary_svg/res/savemodified_large.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/res/savemodified_small.svg b/icon-themes/elementary_svg/res/savemodified_small.svg index a569103282d3..fa44a85d45ff 100644 --- a/icon-themes/elementary_svg/res/savemodified_small.svg +++ b/icon-themes/elementary_svg/res/savemodified_small.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/res/unpin_document.svg b/icon-themes/elementary_svg/res/unpin_document.svg new file mode 100644 index 000000000000..638dd291f346 --- /dev/null +++ b/icon-themes/elementary_svg/res/unpin_document.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/elementary_svg/sfx2/res/actiontemplates017.svg b/icon-themes/elementary_svg/sfx2/res/actiontemplates017.svg index 18070f64502b..0e668a0b733a 100644 --- a/icon-themes/elementary_svg/sfx2/res/actiontemplates017.svg +++ b/icon-themes/elementary_svg/sfx2/res/actiontemplates017.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/sfx2/res/actionview026.svg b/icon-themes/elementary_svg/sfx2/res/actionview026.svg index c2355978d79d..54cda99c6a20 100644 --- a/icon-themes/elementary_svg/sfx2/res/actionview026.svg +++ b/icon-themes/elementary_svg/sfx2/res/actionview026.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/sfx2/res/actionview029.svg b/icon-themes/elementary_svg/sfx2/res/actionview029.svg index 085a50b0b63f..8e4c1337af9a 100644 --- a/icon-themes/elementary_svg/sfx2/res/actionview029.svg +++ b/icon-themes/elementary_svg/sfx2/res/actionview029.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/svtools/res/folder.svg b/icon-themes/elementary_svg/svtools/res/folder.svg index 8b7431ee93b9..f6a790514207 100644 --- a/icon-themes/elementary_svg/svtools/res/folder.svg +++ b/icon-themes/elementary_svg/svtools/res/folder.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/svx/res/doc_modified_yes.svg b/icon-themes/elementary_svg/svx/res/doc_modified_yes.svg index 899f2da2ae34..a35db2a27af1 100644 --- a/icon-themes/elementary_svg/svx/res/doc_modified_yes.svg +++ b/icon-themes/elementary_svg/svx/res/doc_modified_yes.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/svx/res/galdefs.svg b/icon-themes/elementary_svg/svx/res/galdefs.svg index 13bcf0369e58..1f7d6eb3446c 100644 --- a/icon-themes/elementary_svg/svx/res/galdefs.svg +++ b/icon-themes/elementary_svg/svx/res/galdefs.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/svx/res/galnorl.svg b/icon-themes/elementary_svg/svx/res/galnorl.svg index 72d5794f147d..310677233b32 100644 --- a/icon-themes/elementary_svg/svx/res/galnorl.svg +++ b/icon-themes/elementary_svg/svx/res/galnorl.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/svx/res/galnors.svg b/icon-themes/elementary_svg/svx/res/galnors.svg index 47ab541c4a83..7a3bf060049d 100644 --- a/icon-themes/elementary_svg/svx/res/galnors.svg +++ b/icon-themes/elementary_svg/svx/res/galnors.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/svx/res/galrdefl.svg b/icon-themes/elementary_svg/svx/res/galrdefl.svg index 0d52384133b9..782ae94f1cef 100644 --- a/icon-themes/elementary_svg/svx/res/galrdefl.svg +++ b/icon-themes/elementary_svg/svx/res/galrdefl.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/svx/res/galrdol.svg b/icon-themes/elementary_svg/svx/res/galrdol.svg index 3427e03022f9..f7747221299f 100644 --- a/icon-themes/elementary_svg/svx/res/galrdol.svg +++ b/icon-themes/elementary_svg/svx/res/galrdol.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/elementary_svg/xmlsecurity/res/certificate_16.svg b/icon-themes/elementary_svg/xmlsecurity/res/certificate_16.svg index 5a3c23db222b..4fed0ac41059 100644 --- a/icon-themes/elementary_svg/xmlsecurity/res/certificate_16.svg +++ b/icon-themes/elementary_svg/xmlsecurity/res/certificate_16.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/karasa_jaga/cmd/32/insertenvelope.png b/icon-themes/karasa_jaga/cmd/32/insertenvelope.png index a8a3dd919b5a..2ad6316322e0 100644 Binary files a/icon-themes/karasa_jaga/cmd/32/insertenvelope.png and b/icon-themes/karasa_jaga/cmd/32/insertenvelope.png differ diff --git a/icon-themes/karasa_jaga/cmd/32/sendfeedback.png b/icon-themes/karasa_jaga/cmd/32/sendfeedback.png deleted file mode 100644 index 2ad6316322e0..000000000000 Binary files a/icon-themes/karasa_jaga/cmd/32/sendfeedback.png and /dev/null differ diff --git a/icon-themes/karasa_jaga/cmd/32/shortcutkeysdialog.png b/icon-themes/karasa_jaga/cmd/32/shortcutkeysdialog.png new file mode 100644 index 000000000000..f1ad7dc933f3 Binary files /dev/null and b/icon-themes/karasa_jaga/cmd/32/shortcutkeysdialog.png differ diff --git a/icon-themes/karasa_jaga/cmd/lc_insertenvelope.png b/icon-themes/karasa_jaga/cmd/lc_insertenvelope.png index 3ef1c0ac288b..742885d3a7d0 100644 Binary files a/icon-themes/karasa_jaga/cmd/lc_insertenvelope.png and b/icon-themes/karasa_jaga/cmd/lc_insertenvelope.png differ diff --git a/icon-themes/karasa_jaga/cmd/lc_sendfeedback.png b/icon-themes/karasa_jaga/cmd/lc_sendfeedback.png deleted file mode 100644 index 742885d3a7d0..000000000000 Binary files a/icon-themes/karasa_jaga/cmd/lc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/karasa_jaga/cmd/lc_shortcutkeysdialog.png b/icon-themes/karasa_jaga/cmd/lc_shortcutkeysdialog.png new file mode 100644 index 000000000000..b0150d7305c9 Binary files /dev/null and b/icon-themes/karasa_jaga/cmd/lc_shortcutkeysdialog.png differ diff --git a/icon-themes/karasa_jaga/cmd/sc_insertenvelope.png b/icon-themes/karasa_jaga/cmd/sc_insertenvelope.png index 9f883833b21f..e7d953ae5b35 100644 Binary files a/icon-themes/karasa_jaga/cmd/sc_insertenvelope.png and b/icon-themes/karasa_jaga/cmd/sc_insertenvelope.png differ diff --git a/icon-themes/karasa_jaga/cmd/sc_sendfeedback.png b/icon-themes/karasa_jaga/cmd/sc_sendfeedback.png deleted file mode 100644 index e7d953ae5b35..000000000000 Binary files a/icon-themes/karasa_jaga/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/karasa_jaga/cmd/sc_shortcutkeysdialog.png b/icon-themes/karasa_jaga/cmd/sc_shortcutkeysdialog.png new file mode 100644 index 000000000000..5ba51ecdc6f6 Binary files /dev/null and b/icon-themes/karasa_jaga/cmd/sc_shortcutkeysdialog.png differ diff --git a/icon-themes/karasa_jaga/res/recentdoc_pin.png b/icon-themes/karasa_jaga/res/recentdoc_pin.png new file mode 100644 index 000000000000..184bd6bce341 Binary files /dev/null and b/icon-themes/karasa_jaga/res/recentdoc_pin.png differ diff --git a/icon-themes/karasa_jaga/res/recentdoc_pin_highlighted.png b/icon-themes/karasa_jaga/res/recentdoc_pin_highlighted.png new file mode 100644 index 000000000000..eec413a49cdb Binary files /dev/null and b/icon-themes/karasa_jaga/res/recentdoc_pin_highlighted.png differ diff --git a/icon-themes/karasa_jaga_svg/cmd/32/insertenvelope.svg b/icon-themes/karasa_jaga_svg/cmd/32/insertenvelope.svg index 1f61639a3c22..1933402ee524 100644 --- a/icon-themes/karasa_jaga_svg/cmd/32/insertenvelope.svg +++ b/icon-themes/karasa_jaga_svg/cmd/32/insertenvelope.svg @@ -1 +1 @@ -32PX \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/cmd/32/sendfeedback.svg b/icon-themes/karasa_jaga_svg/cmd/32/sendfeedback.svg deleted file mode 100644 index 1933402ee524..000000000000 --- a/icon-themes/karasa_jaga_svg/cmd/32/sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/cmd/32/shortcutkeysdialog.svg b/icon-themes/karasa_jaga_svg/cmd/32/shortcutkeysdialog.svg new file mode 100644 index 000000000000..3e4e68c7672a --- /dev/null +++ b/icon-themes/karasa_jaga_svg/cmd/32/shortcutkeysdialog.svg @@ -0,0 +1 @@ +KARASA JAGA \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/cmd/lc_insertenvelope.svg b/icon-themes/karasa_jaga_svg/cmd/lc_insertenvelope.svg index ecfaa111c5db..b8340c101bdf 100644 --- a/icon-themes/karasa_jaga_svg/cmd/lc_insertenvelope.svg +++ b/icon-themes/karasa_jaga_svg/cmd/lc_insertenvelope.svg @@ -1 +1 @@ -Lorem ipsum dolor sitMaece convallis duilamos. Pha Lorem ipsum dolor sit \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/cmd/lc_sendfeedback.svg b/icon-themes/karasa_jaga_svg/cmd/lc_sendfeedback.svg deleted file mode 100644 index b8340c101bdf..000000000000 --- a/icon-themes/karasa_jaga_svg/cmd/lc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/cmd/lc_shortcutkeysdialog.svg b/icon-themes/karasa_jaga_svg/cmd/lc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..350b33ae8c57 --- /dev/null +++ b/icon-themes/karasa_jaga_svg/cmd/lc_shortcutkeysdialog.svg @@ -0,0 +1 @@ +KARASA JAGA \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/cmd/sc_insertenvelope.svg b/icon-themes/karasa_jaga_svg/cmd/sc_insertenvelope.svg index 18f0e68262a6..65c554c855da 100644 --- a/icon-themes/karasa_jaga_svg/cmd/sc_insertenvelope.svg +++ b/icon-themes/karasa_jaga_svg/cmd/sc_insertenvelope.svg @@ -1 +1 @@ -blallallalalablallall \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/cmd/sc_sendfeedback.svg b/icon-themes/karasa_jaga_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index 65c554c855da..000000000000 --- a/icon-themes/karasa_jaga_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/cmd/sc_shortcutkeysdialog.svg b/icon-themes/karasa_jaga_svg/cmd/sc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..ce24c37fb207 --- /dev/null +++ b/icon-themes/karasa_jaga_svg/cmd/sc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/res/recentdoc_pin.svg b/icon-themes/karasa_jaga_svg/res/recentdoc_pin.svg new file mode 100644 index 000000000000..4d68d0475841 --- /dev/null +++ b/icon-themes/karasa_jaga_svg/res/recentdoc_pin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/karasa_jaga_svg/res/recentdoc_pin_highlighted.svg b/icon-themes/karasa_jaga_svg/res/recentdoc_pin_highlighted.svg new file mode 100644 index 000000000000..07bc6552610b --- /dev/null +++ b/icon-themes/karasa_jaga_svg/res/recentdoc_pin_highlighted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr/cmd/32/defaultparastyle.png b/icon-themes/sifr/cmd/32/defaultparastyle.png new file mode 100644 index 000000000000..7e3926369575 Binary files /dev/null and b/icon-themes/sifr/cmd/32/defaultparastyle.png differ diff --git a/icon-themes/sifr/cmd/32/insertenvelope.png b/icon-themes/sifr/cmd/32/insertenvelope.png index 6a767328c6ee..9b84311d27b9 100644 Binary files a/icon-themes/sifr/cmd/32/insertenvelope.png and b/icon-themes/sifr/cmd/32/insertenvelope.png differ diff --git a/icon-themes/sifr/cmd/32/sendfeedback.png b/icon-themes/sifr/cmd/32/sendfeedback.png deleted file mode 100644 index 9b84311d27b9..000000000000 Binary files a/icon-themes/sifr/cmd/32/sendfeedback.png and /dev/null differ diff --git a/icon-themes/sifr/cmd/32/shortcutkeysdialog.png b/icon-themes/sifr/cmd/32/shortcutkeysdialog.png new file mode 100644 index 000000000000..d0734a5fd315 Binary files /dev/null and b/icon-themes/sifr/cmd/32/shortcutkeysdialog.png differ diff --git a/icon-themes/sifr/cmd/32/textbodyparastyle.png b/icon-themes/sifr/cmd/32/textbodyparastyle.png index c25d5621e4c7..569c821042d5 100644 Binary files a/icon-themes/sifr/cmd/32/textbodyparastyle.png and b/icon-themes/sifr/cmd/32/textbodyparastyle.png differ diff --git a/icon-themes/sifr/cmd/lc_autoformatapply.png b/icon-themes/sifr/cmd/lc_autoformatapply.png new file mode 100644 index 000000000000..0c736e890d19 Binary files /dev/null and b/icon-themes/sifr/cmd/lc_autoformatapply.png differ diff --git a/icon-themes/sifr/cmd/lc_defaultparastyle.png b/icon-themes/sifr/cmd/lc_defaultparastyle.png new file mode 100644 index 000000000000..ffb56058aa62 Binary files /dev/null and b/icon-themes/sifr/cmd/lc_defaultparastyle.png differ diff --git a/icon-themes/sifr/cmd/lc_insertenvelope.png b/icon-themes/sifr/cmd/lc_insertenvelope.png index 51411e3e22f6..a0498802ba92 100644 Binary files a/icon-themes/sifr/cmd/lc_insertenvelope.png and b/icon-themes/sifr/cmd/lc_insertenvelope.png differ diff --git a/icon-themes/sifr/cmd/lc_sendfeedback.png b/icon-themes/sifr/cmd/lc_sendfeedback.png deleted file mode 100644 index a0498802ba92..000000000000 Binary files a/icon-themes/sifr/cmd/lc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/sifr/cmd/lc_shortcutkeysdialog.png b/icon-themes/sifr/cmd/lc_shortcutkeysdialog.png new file mode 100644 index 000000000000..07f33b086812 Binary files /dev/null and b/icon-themes/sifr/cmd/lc_shortcutkeysdialog.png differ diff --git a/icon-themes/sifr/cmd/lc_textbodyparastyle.png b/icon-themes/sifr/cmd/lc_textbodyparastyle.png index bb44f532078b..aee0bade5220 100644 Binary files a/icon-themes/sifr/cmd/lc_textbodyparastyle.png and b/icon-themes/sifr/cmd/lc_textbodyparastyle.png differ diff --git a/icon-themes/sifr/cmd/sc_defaultparastyle.png b/icon-themes/sifr/cmd/sc_defaultparastyle.png new file mode 100644 index 000000000000..fa8d80bd5870 Binary files /dev/null and b/icon-themes/sifr/cmd/sc_defaultparastyle.png differ diff --git a/icon-themes/sifr/cmd/sc_insertenvelope.png b/icon-themes/sifr/cmd/sc_insertenvelope.png index 4dad6d1773ad..ee935e3e14b1 100644 Binary files a/icon-themes/sifr/cmd/sc_insertenvelope.png and b/icon-themes/sifr/cmd/sc_insertenvelope.png differ diff --git a/icon-themes/sifr/cmd/sc_sendfeedback.png b/icon-themes/sifr/cmd/sc_sendfeedback.png deleted file mode 100644 index ee935e3e14b1..000000000000 Binary files a/icon-themes/sifr/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/sifr/cmd/sc_shortcutkeysdialog.png b/icon-themes/sifr/cmd/sc_shortcutkeysdialog.png new file mode 100644 index 000000000000..eaf6a88f232d Binary files /dev/null and b/icon-themes/sifr/cmd/sc_shortcutkeysdialog.png differ diff --git a/icon-themes/sifr/cmd/sc_textbodyparastyle.png b/icon-themes/sifr/cmd/sc_textbodyparastyle.png index d58b81061621..dbf3eaaf5426 100644 Binary files a/icon-themes/sifr/cmd/sc_textbodyparastyle.png and b/icon-themes/sifr/cmd/sc_textbodyparastyle.png differ diff --git a/icon-themes/sifr/links.txt b/icon-themes/sifr/links.txt index 8def24478e3c..ed6535dd8340 100644 --- a/icon-themes/sifr/links.txt +++ b/icon-themes/sifr/links.txt @@ -966,11 +966,8 @@ cmd/sc_removefilter.png cmd/sc_removefiltersort.png # Bullets cmd/32/bulletliststyle.png cmd/32/defaultbullet.png -cmd/32/defaultparastyle.png cmd/32/controlcodes.png cmd/lc_bulletliststyle.png cmd/lc_defaultbullet.png -cmd/lc_defaultparastyle.png cmd/lc_controlcodes.png cmd/sc_bulletliststyle.png cmd/sc_defaultbullet.png -cmd/sc_defaultparastyle.png cmd/sc_controlcodes.png # Group cmd/32/groupmenu.png cmd/32/formatgroup.png diff --git a/icon-themes/sifr/res/recentdoc_pin.png b/icon-themes/sifr/res/recentdoc_pin.png index a022906f65c6..f0ed534c8ed6 100644 Binary files a/icon-themes/sifr/res/recentdoc_pin.png and b/icon-themes/sifr/res/recentdoc_pin.png differ diff --git a/icon-themes/sifr/res/recentdoc_pin_highlighted.png b/icon-themes/sifr/res/recentdoc_pin_highlighted.png index 877b80bfafe0..cc261808c975 100644 Binary files a/icon-themes/sifr/res/recentdoc_pin_highlighted.png and b/icon-themes/sifr/res/recentdoc_pin_highlighted.png differ diff --git a/icon-themes/sifr_dark/cmd/32/defaultparastyle.png b/icon-themes/sifr_dark/cmd/32/defaultparastyle.png new file mode 100644 index 000000000000..267430e5c7b9 Binary files /dev/null and b/icon-themes/sifr_dark/cmd/32/defaultparastyle.png differ diff --git a/icon-themes/sifr_dark/cmd/32/insertenvelope.png b/icon-themes/sifr_dark/cmd/32/insertenvelope.png index 22ed07c73c98..7602f1305738 100644 Binary files a/icon-themes/sifr_dark/cmd/32/insertenvelope.png and b/icon-themes/sifr_dark/cmd/32/insertenvelope.png differ diff --git a/icon-themes/sifr_dark/cmd/32/sendfeedback.png b/icon-themes/sifr_dark/cmd/32/sendfeedback.png deleted file mode 100644 index 7602f1305738..000000000000 Binary files a/icon-themes/sifr_dark/cmd/32/sendfeedback.png and /dev/null differ diff --git a/icon-themes/sifr_dark/cmd/32/shortcutkeysdialog.png b/icon-themes/sifr_dark/cmd/32/shortcutkeysdialog.png new file mode 100644 index 000000000000..d1f10cfc0c2f Binary files /dev/null and b/icon-themes/sifr_dark/cmd/32/shortcutkeysdialog.png differ diff --git a/icon-themes/sifr_dark/cmd/32/textbodyparastyle.png b/icon-themes/sifr_dark/cmd/32/textbodyparastyle.png index c25d5621e4c7..620ae6c981c4 100644 Binary files a/icon-themes/sifr_dark/cmd/32/textbodyparastyle.png and b/icon-themes/sifr_dark/cmd/32/textbodyparastyle.png differ diff --git a/icon-themes/sifr_dark/cmd/lc_autoformatapply.png b/icon-themes/sifr_dark/cmd/lc_autoformatapply.png new file mode 100644 index 000000000000..e0458114966e Binary files /dev/null and b/icon-themes/sifr_dark/cmd/lc_autoformatapply.png differ diff --git a/icon-themes/sifr_dark/cmd/lc_defaultparastyle.png b/icon-themes/sifr_dark/cmd/lc_defaultparastyle.png new file mode 100644 index 000000000000..b1b4bcd51418 Binary files /dev/null and b/icon-themes/sifr_dark/cmd/lc_defaultparastyle.png differ diff --git a/icon-themes/sifr_dark/cmd/lc_insertenvelope.png b/icon-themes/sifr_dark/cmd/lc_insertenvelope.png index e6da01974102..f2991d8368ed 100644 Binary files a/icon-themes/sifr_dark/cmd/lc_insertenvelope.png and b/icon-themes/sifr_dark/cmd/lc_insertenvelope.png differ diff --git a/icon-themes/sifr_dark/cmd/lc_sendfeedback.png b/icon-themes/sifr_dark/cmd/lc_sendfeedback.png deleted file mode 100644 index f2991d8368ed..000000000000 Binary files a/icon-themes/sifr_dark/cmd/lc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/sifr_dark/cmd/lc_shortcutkeysdialog.png b/icon-themes/sifr_dark/cmd/lc_shortcutkeysdialog.png new file mode 100644 index 000000000000..f89407bf509e Binary files /dev/null and b/icon-themes/sifr_dark/cmd/lc_shortcutkeysdialog.png differ diff --git a/icon-themes/sifr_dark/cmd/lc_textbodyparastyle.png b/icon-themes/sifr_dark/cmd/lc_textbodyparastyle.png index ec6ff971a955..ecf2bf51de67 100644 Binary files a/icon-themes/sifr_dark/cmd/lc_textbodyparastyle.png and b/icon-themes/sifr_dark/cmd/lc_textbodyparastyle.png differ diff --git a/icon-themes/sifr_dark/cmd/sc_defaultparastyle.png b/icon-themes/sifr_dark/cmd/sc_defaultparastyle.png new file mode 100644 index 000000000000..18fd2b653c9c Binary files /dev/null and b/icon-themes/sifr_dark/cmd/sc_defaultparastyle.png differ diff --git a/icon-themes/sifr_dark/cmd/sc_insertenvelope.png b/icon-themes/sifr_dark/cmd/sc_insertenvelope.png index b10da56e4d1d..57eb3c24c3b5 100644 Binary files a/icon-themes/sifr_dark/cmd/sc_insertenvelope.png and b/icon-themes/sifr_dark/cmd/sc_insertenvelope.png differ diff --git a/icon-themes/sifr_dark/cmd/sc_sendfeedback.png b/icon-themes/sifr_dark/cmd/sc_sendfeedback.png deleted file mode 100644 index 57eb3c24c3b5..000000000000 Binary files a/icon-themes/sifr_dark/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/sifr_dark/cmd/sc_shortcutkeysdialog.png b/icon-themes/sifr_dark/cmd/sc_shortcutkeysdialog.png new file mode 100644 index 000000000000..63be5853e94b Binary files /dev/null and b/icon-themes/sifr_dark/cmd/sc_shortcutkeysdialog.png differ diff --git a/icon-themes/sifr_dark/cmd/sc_textbodyparastyle.png b/icon-themes/sifr_dark/cmd/sc_textbodyparastyle.png index 98a58cb7dbbf..56d2d884e864 100644 Binary files a/icon-themes/sifr_dark/cmd/sc_textbodyparastyle.png and b/icon-themes/sifr_dark/cmd/sc_textbodyparastyle.png differ diff --git a/icon-themes/sifr_dark/links.txt b/icon-themes/sifr_dark/links.txt index 33280de44223..ae83ceba6b9d 100644 --- a/icon-themes/sifr_dark/links.txt +++ b/icon-themes/sifr_dark/links.txt @@ -965,11 +965,8 @@ cmd/sc_removefilter.png cmd/sc_removefiltersort.png # Bullets cmd/32/bulletliststyle.png cmd/32/defaultbullet.png -cmd/32/defaultparastyle.png cmd/32/controlcodes.png cmd/lc_bulletliststyle.png cmd/lc_defaultbullet.png -cmd/lc_defaultparastyle.png cmd/lc_controlcodes.png cmd/sc_bulletliststyle.png cmd/sc_defaultbullet.png -cmd/sc_defaultparastyle.png cmd/sc_controlcodes.png # Group cmd/32/groupmenu.png cmd/32/formatgroup.png diff --git a/icon-themes/sifr_dark/res/recentdoc_pin.png b/icon-themes/sifr_dark/res/recentdoc_pin.png index a022906f65c6..f8260767b3a3 100644 Binary files a/icon-themes/sifr_dark/res/recentdoc_pin.png and b/icon-themes/sifr_dark/res/recentdoc_pin.png differ diff --git a/icon-themes/sifr_dark/res/recentdoc_pin_highlighted.png b/icon-themes/sifr_dark/res/recentdoc_pin_highlighted.png index 877b80bfafe0..146450fd9a8d 100644 Binary files a/icon-themes/sifr_dark/res/recentdoc_pin_highlighted.png and b/icon-themes/sifr_dark/res/recentdoc_pin_highlighted.png differ diff --git a/icon-themes/sifr_dark_svg/cmd/32/defaultparastyle.svg b/icon-themes/sifr_dark_svg/cmd/32/defaultparastyle.svg new file mode 100644 index 000000000000..4a585c1bf9ef --- /dev/null +++ b/icon-themes/sifr_dark_svg/cmd/32/defaultparastyle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/32/insertenvelope.svg b/icon-themes/sifr_dark_svg/cmd/32/insertenvelope.svg index 6c223abc77b0..41f62c763efd 100644 --- a/icon-themes/sifr_dark_svg/cmd/32/insertenvelope.svg +++ b/icon-themes/sifr_dark_svg/cmd/32/insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/32/sendfeedback.svg b/icon-themes/sifr_dark_svg/cmd/32/sendfeedback.svg deleted file mode 100644 index 41f62c763efd..000000000000 --- a/icon-themes/sifr_dark_svg/cmd/32/sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/32/shortcutkeysdialog.svg b/icon-themes/sifr_dark_svg/cmd/32/shortcutkeysdialog.svg new file mode 100644 index 000000000000..d3b71c122de2 --- /dev/null +++ b/icon-themes/sifr_dark_svg/cmd/32/shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/32/textbodyparastyle.svg b/icon-themes/sifr_dark_svg/cmd/32/textbodyparastyle.svg new file mode 100644 index 000000000000..7280ce939c6c --- /dev/null +++ b/icon-themes/sifr_dark_svg/cmd/32/textbodyparastyle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/lc_defaultparastyle.svg b/icon-themes/sifr_dark_svg/cmd/lc_defaultparastyle.svg new file mode 100644 index 000000000000..fc898ee7ae2b --- /dev/null +++ b/icon-themes/sifr_dark_svg/cmd/lc_defaultparastyle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/lc_insertenvelope.svg b/icon-themes/sifr_dark_svg/cmd/lc_insertenvelope.svg index 157767fb9a2a..29fca11ca17d 100644 --- a/icon-themes/sifr_dark_svg/cmd/lc_insertenvelope.svg +++ b/icon-themes/sifr_dark_svg/cmd/lc_insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/lc_sendfeedback.svg b/icon-themes/sifr_dark_svg/cmd/lc_sendfeedback.svg deleted file mode 100644 index 29fca11ca17d..000000000000 --- a/icon-themes/sifr_dark_svg/cmd/lc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/lc_shortcutkeysdialog.svg b/icon-themes/sifr_dark_svg/cmd/lc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..041e6adf8bb0 --- /dev/null +++ b/icon-themes/sifr_dark_svg/cmd/lc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/lc_textbodyparastyle.svg b/icon-themes/sifr_dark_svg/cmd/lc_textbodyparastyle.svg index 7f68c740e4b6..2482e4207dea 100644 --- a/icon-themes/sifr_dark_svg/cmd/lc_textbodyparastyle.svg +++ b/icon-themes/sifr_dark_svg/cmd/lc_textbodyparastyle.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/sc_defaultparastyle.svg b/icon-themes/sifr_dark_svg/cmd/sc_defaultparastyle.svg new file mode 100644 index 000000000000..cda610ab591f --- /dev/null +++ b/icon-themes/sifr_dark_svg/cmd/sc_defaultparastyle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/sc_insertenvelope.svg b/icon-themes/sifr_dark_svg/cmd/sc_insertenvelope.svg index 47769d34e2c3..d5e131d77a3e 100644 --- a/icon-themes/sifr_dark_svg/cmd/sc_insertenvelope.svg +++ b/icon-themes/sifr_dark_svg/cmd/sc_insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/sc_sendfeedback.svg b/icon-themes/sifr_dark_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index d5e131d77a3e..000000000000 --- a/icon-themes/sifr_dark_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/sc_shortcutkeysdialog.svg b/icon-themes/sifr_dark_svg/cmd/sc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..d8bcceeaea2e --- /dev/null +++ b/icon-themes/sifr_dark_svg/cmd/sc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/cmd/sc_textbodyparastyle.svg b/icon-themes/sifr_dark_svg/cmd/sc_textbodyparastyle.svg index 80b90d6371c9..603c85c236da 100644 --- a/icon-themes/sifr_dark_svg/cmd/sc_textbodyparastyle.svg +++ b/icon-themes/sifr_dark_svg/cmd/sc_textbodyparastyle.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/res/recentdoc_pin.svg b/icon-themes/sifr_dark_svg/res/recentdoc_pin.svg index 8854aa8919f1..7efb2d2ba4fd 100644 --- a/icon-themes/sifr_dark_svg/res/recentdoc_pin.svg +++ b/icon-themes/sifr_dark_svg/res/recentdoc_pin.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_dark_svg/res/recentdoc_pin_highlighted.svg b/icon-themes/sifr_dark_svg/res/recentdoc_pin_highlighted.svg index b045ef068630..bf33af14cac0 100644 --- a/icon-themes/sifr_dark_svg/res/recentdoc_pin_highlighted.svg +++ b/icon-themes/sifr_dark_svg/res/recentdoc_pin_highlighted.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/32/defaultparastyle.svg b/icon-themes/sifr_svg/cmd/32/defaultparastyle.svg new file mode 100644 index 000000000000..384bc845f62a --- /dev/null +++ b/icon-themes/sifr_svg/cmd/32/defaultparastyle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/32/insertenvelope.svg b/icon-themes/sifr_svg/cmd/32/insertenvelope.svg index 05f993b56f2a..f6fd617d672b 100644 --- a/icon-themes/sifr_svg/cmd/32/insertenvelope.svg +++ b/icon-themes/sifr_svg/cmd/32/insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/32/sendfeedback.svg b/icon-themes/sifr_svg/cmd/32/sendfeedback.svg deleted file mode 100644 index f6fd617d672b..000000000000 --- a/icon-themes/sifr_svg/cmd/32/sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/32/shortcutkeysdialog.svg b/icon-themes/sifr_svg/cmd/32/shortcutkeysdialog.svg new file mode 100644 index 000000000000..e1639b75e7f5 --- /dev/null +++ b/icon-themes/sifr_svg/cmd/32/shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/32/textbodyparastyle.svg b/icon-themes/sifr_svg/cmd/32/textbodyparastyle.svg new file mode 100644 index 000000000000..aa5af710be01 --- /dev/null +++ b/icon-themes/sifr_svg/cmd/32/textbodyparastyle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/lc_defaultparastyle.svg b/icon-themes/sifr_svg/cmd/lc_defaultparastyle.svg new file mode 100644 index 000000000000..d715c56dc544 --- /dev/null +++ b/icon-themes/sifr_svg/cmd/lc_defaultparastyle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/lc_insertenvelope.svg b/icon-themes/sifr_svg/cmd/lc_insertenvelope.svg index 4d06dd2b6104..1ac6e64111d6 100644 --- a/icon-themes/sifr_svg/cmd/lc_insertenvelope.svg +++ b/icon-themes/sifr_svg/cmd/lc_insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/lc_sendfeedback.svg b/icon-themes/sifr_svg/cmd/lc_sendfeedback.svg deleted file mode 100644 index 1ac6e64111d6..000000000000 --- a/icon-themes/sifr_svg/cmd/lc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/lc_shortcutkeysdialog.svg b/icon-themes/sifr_svg/cmd/lc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..ff7262b94ba6 --- /dev/null +++ b/icon-themes/sifr_svg/cmd/lc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/lc_textbodyparastyle.svg b/icon-themes/sifr_svg/cmd/lc_textbodyparastyle.svg index 7f796fa9ac37..69e676ba8a84 100644 --- a/icon-themes/sifr_svg/cmd/lc_textbodyparastyle.svg +++ b/icon-themes/sifr_svg/cmd/lc_textbodyparastyle.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/sc_defaultparastyle.svg b/icon-themes/sifr_svg/cmd/sc_defaultparastyle.svg new file mode 100644 index 000000000000..3d1efe143bfc --- /dev/null +++ b/icon-themes/sifr_svg/cmd/sc_defaultparastyle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/sc_insertenvelope.svg b/icon-themes/sifr_svg/cmd/sc_insertenvelope.svg index f714dda93617..54280393c78c 100644 --- a/icon-themes/sifr_svg/cmd/sc_insertenvelope.svg +++ b/icon-themes/sifr_svg/cmd/sc_insertenvelope.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/sc_sendfeedback.svg b/icon-themes/sifr_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index 54280393c78c..000000000000 --- a/icon-themes/sifr_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/sc_shortcutkeysdialog.svg b/icon-themes/sifr_svg/cmd/sc_shortcutkeysdialog.svg new file mode 100644 index 000000000000..9a7fe95e27db --- /dev/null +++ b/icon-themes/sifr_svg/cmd/sc_shortcutkeysdialog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon-themes/sifr_svg/cmd/sc_textbodyparastyle.svg b/icon-themes/sifr_svg/cmd/sc_textbodyparastyle.svg index 2b02aaad0669..bbbf7530137a 100644 --- a/icon-themes/sifr_svg/cmd/sc_textbodyparastyle.svg +++ b/icon-themes/sifr_svg/cmd/sc_textbodyparastyle.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_svg/res/recentdoc_pin.svg b/icon-themes/sifr_svg/res/recentdoc_pin.svg index 8854aa8919f1..87dda2495f79 100644 --- a/icon-themes/sifr_svg/res/recentdoc_pin.svg +++ b/icon-themes/sifr_svg/res/recentdoc_pin.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sifr_svg/res/recentdoc_pin_highlighted.svg b/icon-themes/sifr_svg/res/recentdoc_pin_highlighted.svg index b045ef068630..a175e490a802 100644 --- a/icon-themes/sifr_svg/res/recentdoc_pin_highlighted.svg +++ b/icon-themes/sifr_svg/res/recentdoc_pin_highlighted.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icon-themes/sukapura/cmd/lc_autoformatapply.png b/icon-themes/sukapura/cmd/lc_autoformatapply.png new file mode 100644 index 000000000000..1b8b3096258d Binary files /dev/null and b/icon-themes/sukapura/cmd/lc_autoformatapply.png differ diff --git a/icon-themes/sukapura/cmd/sc_insertenvelope.png b/icon-themes/sukapura/cmd/sc_insertenvelope.png index 38a0aa2374b6..682c7ac1bf69 100644 Binary files a/icon-themes/sukapura/cmd/sc_insertenvelope.png and b/icon-themes/sukapura/cmd/sc_insertenvelope.png differ diff --git a/icon-themes/sukapura/cmd/sc_sendfeedback.png b/icon-themes/sukapura/cmd/sc_sendfeedback.png deleted file mode 100644 index 682c7ac1bf69..000000000000 Binary files a/icon-themes/sukapura/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/sukapura/links.txt b/icon-themes/sukapura/links.txt index cc52386a874d..4b622576a6b3 100644 --- a/icon-themes/sukapura/links.txt +++ b/icon-themes/sukapura/links.txt @@ -1794,18 +1794,15 @@ cmd/sc_toolsmacroedit.png cmd/sc_basicideappear.png cmd/32/donation.png cmd/32/currencyfield.png cmd/32/helperdialog.png cmd/32/helpindex.png cmd/32/questionanswers.png cmd/32/browseview.png -cmd/32/sendfeedback.png cmd/32/insertenvelope.png cmd/lc_donation.png cmd/lc_currencyfield.png cmd/lc_helperdialog.png cmd/lc_helpindex.png cmd/lc_questionanswers.png cmd/lc_browseview.png -cmd/lc_sendfeedback.png cmd/lc_insertenvelope.png cmd/sc_about.png res/mainapp_16_8.png cmd/sc_donation.png cmd/sc_currencyfield.png cmd/sc_helperdialog.png cmd/sc_helpindex.png cmd/sc_questionanswers.png cmd/sc_browseview.png -cmd/sc_sendfeedback.png cmd/sc_insertenvelope.png # Math cmd/32/symbolcatalogue.png cmd/32/insertsymbol.png diff --git a/icon-themes/sukapura_dark/cmd/lc_autoformatapply.png b/icon-themes/sukapura_dark/cmd/lc_autoformatapply.png new file mode 100644 index 000000000000..7cdd09762a9c Binary files /dev/null and b/icon-themes/sukapura_dark/cmd/lc_autoformatapply.png differ diff --git a/icon-themes/sukapura_dark/cmd/sc_insertenvelope.png b/icon-themes/sukapura_dark/cmd/sc_insertenvelope.png index 0a7d9abe41ac..35680b41877d 100644 Binary files a/icon-themes/sukapura_dark/cmd/sc_insertenvelope.png and b/icon-themes/sukapura_dark/cmd/sc_insertenvelope.png differ diff --git a/icon-themes/sukapura_dark/cmd/sc_sendfeedback.png b/icon-themes/sukapura_dark/cmd/sc_sendfeedback.png deleted file mode 100644 index 35680b41877d..000000000000 Binary files a/icon-themes/sukapura_dark/cmd/sc_sendfeedback.png and /dev/null differ diff --git a/icon-themes/sukapura_dark/links.txt b/icon-themes/sukapura_dark/links.txt index beeb8c10686b..0f64992a7afd 100644 --- a/icon-themes/sukapura_dark/links.txt +++ b/icon-themes/sukapura_dark/links.txt @@ -1794,18 +1794,15 @@ cmd/sc_toolsmacroedit.png cmd/sc_basicideappear.png cmd/32/donation.png cmd/32/currencyfield.png cmd/32/helperdialog.png cmd/32/helpindex.png cmd/32/questionanswers.png cmd/32/browseview.png -cmd/32/sendfeedback.png cmd/32/insertenvelope.png cmd/lc_donation.png cmd/lc_currencyfield.png cmd/lc_helperdialog.png cmd/lc_helpindex.png cmd/lc_questionanswers.png cmd/lc_browseview.png -cmd/lc_sendfeedback.png cmd/lc_insertenvelope.png cmd/sc_about.png res/mainapp_16_8.png cmd/sc_donation.png cmd/sc_currencyfield.png cmd/sc_helperdialog.png cmd/sc_helpindex.png cmd/sc_questionanswers.png cmd/sc_browseview.png -cmd/sc_sendfeedback.png cmd/sc_insertenvelope.png # Math cmd/32/symbolcatalogue.png cmd/32/insertsymbol.png diff --git a/icon-themes/sukapura_dark_svg/cmd/sc_insertenvelope.svg b/icon-themes/sukapura_dark_svg/cmd/sc_insertenvelope.svg index cf5c2488b007..20636d66b4eb 100644 --- a/icon-themes/sukapura_dark_svg/cmd/sc_insertenvelope.svg +++ b/icon-themes/sukapura_dark_svg/cmd/sc_insertenvelope.svg @@ -1,9 +1,2 @@ - - - - - - - - /&amp;amp;amp;amp;gt; - \ No newline at end of file + +/&gt; \ No newline at end of file diff --git a/icon-themes/sukapura_dark_svg/cmd/sc_sendfeedback.svg b/icon-themes/sukapura_dark_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index 20636d66b4eb..000000000000 --- a/icon-themes/sukapura_dark_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1,2 +0,0 @@ - -/&gt; \ No newline at end of file diff --git a/icon-themes/sukapura_svg/cmd/sc_insertenvelope.svg b/icon-themes/sukapura_svg/cmd/sc_insertenvelope.svg index aec18d75ffd6..df0486758943 100644 --- a/icon-themes/sukapura_svg/cmd/sc_insertenvelope.svg +++ b/icon-themes/sukapura_svg/cmd/sc_insertenvelope.svg @@ -1,9 +1,2 @@ - - - - - - - - /&amp;amp;amp;amp;gt; - \ No newline at end of file + +/&gt; \ No newline at end of file diff --git a/icon-themes/sukapura_svg/cmd/sc_sendfeedback.svg b/icon-themes/sukapura_svg/cmd/sc_sendfeedback.svg deleted file mode 100644 index df0486758943..000000000000 --- a/icon-themes/sukapura_svg/cmd/sc_sendfeedback.svg +++ /dev/null @@ -1,2 +0,0 @@ - -/&gt; \ No newline at end of file diff --git a/idl/source/objects/types.cxx b/idl/source/objects/types.cxx index 8f6c949af531..56ee05400ffc 100644 --- a/idl/source/objects/types.cxx +++ b/idl/source/objects/types.cxx @@ -249,7 +249,7 @@ void SvMetaType::WriteSfxItem( // write the implementation part rOutStm.WriteOString( "#ifdef SFX_TYPEMAP" ) << endl; - rOutStm.WriteOString( "#if !defined(_WIN32) && (defined(DISABLE_DYNLOADING) && (defined(ANDROID) || defined(IOS) || defined(EMSCRIPTEN) || defined(LINUX)))" ) << endl; + rOutStm.WriteOString( "#if !defined(_WIN32) && (defined(DISABLE_DYNLOADING) && (defined(ANDROID) || defined(IOS) || defined(__EMSCRIPTEN__) || defined(LINUX)))" ) << endl; rOutStm.WriteOString( "__attribute__((__weak__))" ) << endl; rOutStm.WriteOString( "#endif" ) << endl; rOutStm.WriteOString( "constinit const " ).WriteOString( aTypeName ).WriteOString( aVarName ) diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h index 2bed98e212be..9c28a3ff348d 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.h +++ b/include/LibreOfficeKit/LibreOfficeKit.h @@ -129,11 +129,6 @@ struct LibreOfficeKitClassStruct LibreOfficeKitWakeCallback pWakeCallback, void* pData); - /// @see lok::Office::sendDialogEvent - void (*sendDialogEvent) (LibreOfficeKit* pThis, - unsigned long long int nLOKWindowId, - const char* pArguments); - /// @see lok::Office::setOption void (*setOption) (LibreOfficeKit* pThis, const char* pOption, const char* pValue); @@ -399,7 +394,7 @@ struct LibreOfficeKitDocumentClassStruct /// @see lok::Document::getPartInfo(). char* (*getPartInfo) (LibreOfficeKitDocument* pThis, int nPart); - /// Paints window with given id to the buffer with the give DPI scale + /// Paints window with given id to the buffer with the given DPI scale /// (every pixel is dpiscale-times larger). /// @see lok::Document::paintWindow(). void (*paintWindowDPI) (LibreOfficeKitDocument* pThis, unsigned nWindowId, @@ -476,11 +471,6 @@ struct LibreOfficeKitDocumentClassStruct int nBefore, int nAfter); - /// @see lok::Document::sendDialogEvent - void (*sendDialogEvent) (LibreOfficeKitDocument* pThis, - unsigned long long int nLOKWindowId, - const char* pArguments); - /// @see lok::Document::renderFontOrientation(). unsigned char* (*renderFontOrientation) (LibreOfficeKitDocument* pThis, const char* pFontName, @@ -557,9 +547,6 @@ struct LibreOfficeKitDocumentClassStruct /// @see lok::Document::setViewReadOnly(). void (*setViewReadOnly) (LibreOfficeKitDocument* pThis, int nId, const bool readOnly); - /// @see lok::Document::setAllowChangeComments(). - void (*setAllowChangeComments) (LibreOfficeKitDocument* pThis, int nId, const bool allow); - /// @see lok::Document::getPresentationInfo char* (*getPresentationInfo) (LibreOfficeKitDocument* pThis); @@ -583,9 +570,6 @@ struct LibreOfficeKitDocumentClassStruct /// @see lok::Document::setColorPreviewState(). void (*setColorPreviewState) (LibreOfficeKitDocument* pThis, int nId, bool nEnabled); - /// @see lok::Document::setAllowManageRedlines(). - void (*setAllowManageRedlines)(LibreOfficeKitDocument* pThis, int nId, bool allow); - #endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY }; diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx index d2977a4e8a24..a8f5f0eea8ab 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.hxx +++ b/include/LibreOfficeKit/LibreOfficeKit.hxx @@ -313,17 +313,6 @@ public: mpDoc->pClass->postWindowMouseEvent(mpDoc, nWindowId, nType, nX, nY, nCount, nButtons, nModifier); } - /** - * Posts a dialog event for the window with given id - * - * @param nWindowId id of the window to notify - * @param pArguments arguments of the event. - */ - void sendDialogEvent(unsigned long long int nWindowId, const char* pArguments = NULL) - { - mpDoc->pClass->sendDialogEvent(mpDoc, nWindowId, pArguments); - } - /** * Posts a UNO command to the document. * @@ -872,26 +861,6 @@ public: mpDoc->pClass->setViewReadOnly(mpDoc, nId, readOnly); } - /** Set if the view can edit comments on readonly mode or not. - * - * @param nId view ID - * @param allow - */ - void setAllowChangeComments(int nId, const bool allow) - { - mpDoc->pClass->setAllowChangeComments(mpDoc, nId, allow); - } - - /** Set if the view can manage redlines in readonly mode or not. - * - * @param nId view ID - * @param allow - */ - void setAllowManageRedlines(int nId, bool allow) - { - mpDoc->pClass->setAllowManageRedlines(mpDoc, nId, allow); - } - /** * Enable/Disable accessibility support for the window with the specified nId. * @@ -1164,17 +1133,6 @@ public: mpThis->pClass->runLoop(mpThis, pPollCallback, pWakeCallback, pData); } - /** - * Posts a dialog event for the window with given id - * - * @param nWindowId id of the window to notify - * @param pArguments arguments of the event. - */ - void sendDialogEvent(unsigned long long int nWindowId, const char* pArguments = NULL) - { - mpThis->pClass->sendDialogEvent(mpThis, nWindowId, pArguments); - } - /** * Generic function to toggle and tweak various things in the core LO * @@ -1250,12 +1208,12 @@ public: } /** - * Start a UNO acceptor using the function pointers provides to read and write data to/from the acceptor. + * Start a UNO acceptor using the function pointers provided to read and write data to/from the acceptor. * - * @param pReceiveURPFromLOContext A pointer that will be passed to your fnRecieveURPFromLO function + * @param pReceiveURPFromLOContext A pointer that will be passed to your fnReceiveURPFromLO function * @param pSendURPToLOContext A pointer that will be passed to your fnSendURPToLO function * @param fnReceiveURPFromLO A function pointer that LO should use to pass URP back to the caller - * @param fnSendURPToLO A function pointer pointer that the caller should use to pass URP to LO + * @param fnSendURPToLO A function pointer that the caller should use to pass URP to LO */ void* startURP(void* pReceiveURPFromLOContext, void* pSendURPToLOContext, int (*fnReceiveURPFromLO)(void* pContext, const signed char* pBuffer, int nLen), diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h index 516622722bb9..86b2fd23769f 100644 --- a/include/LibreOfficeKit/LibreOfficeKitEnums.h +++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h @@ -83,7 +83,7 @@ typedef enum LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY = (1ULL << 1), /** - * Request to have the part number as an 5th value in the + * Request to have the part number as a 5th value in the * LOK_CALLBACK_INVALIDATE_TILES payload. */ LOK_FEATURE_PART_IN_INVALIDATION_CALLBACK = (1ULL << 2), @@ -269,7 +269,7 @@ typedef enum * having to do an explicit lok::Document::getDocumentSize() call. * * A size change is always preceded by a series of - * LOK_CALLBACK_INVALIDATE_TILES events invalidating any areas + * LOK_CALLBACK_INVALIDATE_TILES events invalidating any areas that * need re-rendering to adapt. */ LOK_CALLBACK_DOCUMENT_SIZE_CHANGED = 13, @@ -594,7 +594,7 @@ typedef enum * "unit": "..." * } * - * Here all aproperties are same as described in svxruler. + * Here all properties are the same as described in svxruler. */ LOK_CALLBACK_RULER_UPDATE = 35, /** @@ -709,12 +709,6 @@ typedef enum */ LOK_CALLBACK_REFERENCE_MARKS = 45, - /** - * Callback related to native dialogs generated in JavaScript from - * the description. - */ - LOK_CALLBACK_JSDIALOG = 46, - /** * Send the list of functions whose name starts with the characters entered * by the user in the formula input bar. @@ -910,10 +904,10 @@ typedef enum /** * Some attribute of this view has changed, that will cause it * to completely re-render, eg. non-printing characters or - * or dark mode was toggled, and then distinct from other views. + * dark mode was toggled, and then distinct from other views. * * Payload is an opaque string that matches this set of states. - * this will be emitted after creating a new view. + * This will be emitted after creating a new view. */ LOK_CALLBACK_VIEW_RENDER_STATE = 60, @@ -961,11 +955,6 @@ typedef enum */ LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED = 64, - /** - * Informs the LibreOfficeKit client that the color palettes have changed. - */ - LOK_CALLBACK_COLOR_PALETTES = 65, - /** * Informs that the document password has been successfully changed. * The payload contains the new password and the type. @@ -1029,7 +1018,7 @@ typedef enum /** * Forwarding logs from core to client can be useful - * for keep track of the real core/client event sequence + * to keep track of the real core/client event sequence * * Payload is the log to be sent */ @@ -1065,7 +1054,7 @@ typedef enum * "unit": "..." * } * - * Here all aproperties are same as described in svxruler. + * Here all properties are the same as described in svxruler. */ LOK_CALLBACK_VERTICAL_RULER_UPDATE = 73 @@ -1193,8 +1182,6 @@ static inline const char* lokCallbackTypeToString(int nType) return "LOK_CALLBACK_TABLE_SELECTED"; case LOK_CALLBACK_REFERENCE_MARKS: return "LOK_CALLBACK_REFERENCE_MARKS"; - case LOK_CALLBACK_JSDIALOG: - return "LOK_CALLBACK_JSDIALOG"; case LOK_CALLBACK_CALC_FUNCTION_LIST: return "LOK_CALLBACK_CALC_FUNCTION_LIST"; case LOK_CALLBACK_TAB_STOP_LIST: @@ -1229,8 +1216,6 @@ static inline const char* lokCallbackTypeToString(int nType) return "LOK_CALLBACK_A11Y_CARET_CHANGED"; case LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED: return "LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED"; - case LOK_CALLBACK_COLOR_PALETTES: - return "LOK_CALLBACK_COLOR_PALETTES"; case LOK_CALLBACK_DOCUMENT_PASSWORD_RESET: return "LOK_CALLBACK_DOCUMENT_PASSWORD_RESET"; case LOK_CALLBACK_A11Y_FOCUSED_CELL_CHANGED: @@ -1291,7 +1276,7 @@ typedef enum LOK_SETGRAPHICSELECTION_START, /** * A move or resize action stops. It is assumed that this is always used - * only after a LOK_SETTEXTSELECTION_START. The supplied coordinates are + * only after a LOK_SETGRAPHICSELECTION_START. The supplied coordinates are * the ones where the user released the screen. */ LOK_SETGRAPHICSELECTION_END diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h index d3001f318875..b391f580f1cf 100644 --- a/include/LibreOfficeKit/LibreOfficeKitGtk.h +++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h @@ -131,10 +131,10 @@ LOK_DOC_VIEW_DLLPUBLIC LibreOfficeKitDocument* lok_doc_view_get_document (LOKDoc /** * lok_doc_view_set_zoom: * @pDocView: The #LOKDocView instance - * @fZoom: The new zoom level that pDocView must set it into. + * @fZoom: The new zoom level that pDocView must set it to. * * Sets the new zoom level for the widget. Does nothing if fZoom is equal to - * existing zoom level. Values outside the range [0.25, 5.0] are clamped into + * existing zoom level. Values outside the range [0.25, 5.0] are clamped to * the nearest allowed value in the interval. */ LOK_DOC_VIEW_DLLPUBLIC void lok_doc_view_set_zoom (LOKDocView* pDocView, @@ -189,7 +189,7 @@ LOK_DOC_VIEW_DLLPUBLIC void lok_doc_view_set_part (LOKDocView* * @pDocView: The #LOKDocView instance * @nPart: * - * Returns: Get current part name of loaded document. Returns null if no + * Returns: Gets current part name of loaded document. Returns null if no * document is set, or document has been destroyed using lok_doc_view_destroy_document. */ LOK_DOC_VIEW_DLLPUBLIC gchar* lok_doc_view_get_part_name (LOKDocView* pDocView, @@ -248,10 +248,10 @@ LOK_DOC_VIEW_DLLPUBLIC void lok_doc_view_post_command (LOKDocView* * @pDocView: the #LOKDocView instance * @pCommand: the command to issue to LO core * - * Get a json mapping of the possible values for the given command. + * Gets a JSON mapping of the possible values for the given command. * In the form of: {commandName: unoCmd, commandValues: {possible_values}} * - * Returns: A json mapping of the possible values for the given command + * Returns: A JSON mapping of the possible values for the given command */ LOK_DOC_VIEW_DLLPUBLIC gchar * lok_doc_view_get_command_values (LOKDocView* pDocView, const gchar* pCommand); @@ -263,7 +263,7 @@ LOK_DOC_VIEW_DLLPUBLIC gchar * lok_doc_view_get_command_values (LOKDocView* * @bHighlightAll: Whether all the matches should be highlighted or not * * Highlights the next matching text in the view. `search-not-found` signal will - * be emitted when no search is found + * be emitted when no match is found */ LOK_DOC_VIEW_DLLPUBLIC void lok_doc_view_find_next (LOKDocView* pDocView, const gchar* pText, @@ -276,7 +276,7 @@ LOK_DOC_VIEW_DLLPUBLIC void lok_doc_view_find_next (LOKDocView* * @bHighlightAll: Whether all the matches should be highlighted or not * * Highlights the previous matching text in the view. `search-not-found` signal - * will be emitted when no search is found + * will be emitted when no match is found */ LOK_DOC_VIEW_DLLPUBLIC void lok_doc_view_find_prev (LOKDocView* pDocView, const gchar* pText, @@ -288,7 +288,7 @@ LOK_DOC_VIEW_DLLPUBLIC void lok_doc_view_find_prev (LOKDocView* * @pText: text to search for * * Highlights all matching texts in the view. `search-not-found` signal - * will be emitted when no search is found + * will be emitted when no match is found */ LOK_DOC_VIEW_DLLPUBLIC void lok_doc_view_highlight_all (LOKDocView* pDocView, const gchar* pText); diff --git a/include/avmedia/MediaControlBase.hxx b/include/avmedia/MediaControlBase.hxx index 00769d78addc..422feceac127 100644 --- a/include/avmedia/MediaControlBase.hxx +++ b/include/avmedia/MediaControlBase.hxx @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include diff --git a/include/avmedia/mediaplayer.hxx b/include/avmedia/mediaplayer.hxx index f0da5b2d84d7..71d73eb9f302 100644 --- a/include/avmedia/mediaplayer.hxx +++ b/include/avmedia/mediaplayer.hxx @@ -30,7 +30,7 @@ namespace avmedia class AVMEDIA_DLLPUBLIC MediaPlayer final : public SfxChildWindow { public: - MediaPlayer( vcl::Window*, sal_uInt16, SfxBindings*, SfxChildWinInfo* ); + MediaPlayer(vcl::Window*, sal_uInt16, SfxBindings&, SfxChildWinInfo&); virtual ~MediaPlayer() override; SFX_DECL_CHILDWINDOW_WITHID( MediaPlayer ); @@ -41,9 +41,8 @@ class MediaWindow; class AVMEDIA_DLLPUBLIC MediaFloater final : public SfxDockingWindow { public: - - MediaFloater( SfxBindings* pBindings, SfxChildWindow* pCW, vcl::Window* pParent ); - virtual ~MediaFloater() override; + MediaFloater(SfxBindings& rBindings, SfxChildWindow* pCW, vcl::Window* pParent); + virtual ~MediaFloater() override; virtual void dispose() override; void setURL( const OUString& rURL, const OUString& rReferer, bool bPlayImmediately ); diff --git a/include/basctl/basctldllpublic.hxx b/include/basctl/basctldllpublic.hxx index bdb23f3101d2..84e9ae60e128 100644 --- a/include/basctl/basctldllpublic.hxx +++ b/include/basctl/basctldllpublic.hxx @@ -41,12 +41,15 @@ namespace weld class Widget; } +class SbMethod; + namespace basctl { BASCTL_DLLPUBLIC bool IsValidSbxName(std::u16string_view rName); BASCTL_DLLPUBLIC SAL_RET_MAYBENULL SfxDispatcher* GetDispatcher(); BASCTL_DLLPUBLIC void MarkDocumentModified(const ScriptDocument& rDocument); +BASCTL_DLLPUBLIC bool QueryDelMacro(std::u16string_view rName, weld::Widget* pParent); BASCTL_DLLPUBLIC bool QueryDelDialog(std::u16string_view rName, weld::Widget* pParent); BASCTL_DLLPUBLIC bool QueryDelModule(std::u16string_view rName, weld::Widget* pParent); BASCTL_DLLPUBLIC bool QueryDelLib(std::u16string_view rName, bool bRef, weld::Widget* pParent); @@ -63,6 +66,8 @@ BASCTL_DLLPUBLIC void ImportLib(const ScriptDocument& rDocument, weld::Dialog* p BASCTL_DLLPUBLIC void Export(const ScriptDocument& rDocument, const OUString& aLibName, weld::Dialog* pDialog); + +BASCTL_DLLPUBLIC void DeleteMacro(SbMethod& rMethod); } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/basctl/idecodecompletiontypes.hxx b/include/basctl/idecodecompletiontypes.hxx index ff31a273e8b5..870bfe48db9a 100644 --- a/include/basctl/idecodecompletiontypes.hxx +++ b/include/basctl/idecodecompletiontypes.hxx @@ -102,7 +102,6 @@ struct IdeParamInfo bool bIsIn = true; IdeParamInfo() = default; - IdeParamInfo(OUString sName_, OUString sTypeName_, bool bOut, bool bIn); }; /** @@ -116,7 +115,6 @@ struct IdeDimensionInfo bool bIsDynamic = true; IdeDimensionInfo() = default; - IdeDimensionInfo(sal_Int32 lower, sal_Int32 upper, bool dynamic = false); }; /** @@ -162,15 +160,11 @@ struct IdeSymbolInfo IdeSymbolInfo() = default; IdeSymbolInfo(std::u16string_view rName, IdeSymbolKind eTheKind, std::u16string_view rParentIdentifier); - - void AddMember(std::shared_ptr pMember); }; using SymbolInfoList = std::vector>; using ParamInfoList = std::vector; -OUString CreateRootIdentifier(IdeSymbolKind eKind, std::u16string_view sOptionalPayload = u""); - } // namespace basctl /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/basegfx/color/bcolormodifier.hxx b/include/basegfx/color/bcolormodifier.hxx index f6052067767f..e245b1ee25ff 100644 --- a/include/basegfx/color/bcolormodifier.hxx +++ b/include/basegfx/color/bcolormodifier.hxx @@ -113,9 +113,6 @@ namespace basegfx virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const = 0; virtual OUString getModifierName() const = 0; - - // return type - BColorModifierType getBColorModifierType() const { return maType; } }; /** convert color to gray diff --git a/include/basegfx/color/bcolortools.hxx b/include/basegfx/color/bcolortools.hxx index 8af2b7c94715..a47ee764894b 100644 --- a/include/basegfx/color/bcolortools.hxx +++ b/include/basegfx/color/bcolortools.hxx @@ -38,6 +38,27 @@ BASEGFX_DLLPUBLIC BColor rgb2hsv(const BColor& rRGBColor); /// Transform from HSV to RGB BASEGFX_DLLPUBLIC BColor hsv2rgb(const BColor& rHSVColor); +/** Determines an interpolated color using HSL color model + + @param rStartRGB color at position 0 + @param rEndRGB color at position 1 + The components are assumed to contain RGB values, such as Color.getBColor() produces. + + @param fFact position in interval [0..1] for which the interpolated color is requested. + Values <0 are treated as 0, values >1 are treated as 1. + + @param bInc. If bInc is true, the arc of the color wheel where the angles increase from the start + color to the end color is used. If bInc is false, the opposite arc is used. Example: + For start color Magenta (Hue 300°) and end color Cyan (Hue 180°) and fFact=0.5, for bInc value + true the color Yellow (Hue 60°) is used for the result, whereas for value false the color Blue + (Hue 240°) is used. + + @returns the color at the position fFact as BColor to be interpreted as RGB color, with each + component in range [0..1]. +*/ +BASEGFX_DLLPUBLIC BColor interpolateInHSL(const BColor& rStartRGB, const BColor& rEndRGB, + const double fFact, const bool bInc); + } // end of namespace basegfx /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/matrix/hommatrixtemplate.hxx b/include/basegfx/matrix/hommatrixtemplate.hxx index 9794b2a9aecf..bad4f5716fe5 100644 --- a/include/basegfx/matrix/hommatrixtemplate.hxx +++ b/include/basegfx/matrix/hommatrixtemplate.hxx @@ -370,17 +370,6 @@ namespace basegfx::internal } } - void doMulMatrix(const double& rfValue) - { - for(sal_uInt16 a(0); a < RowSize; a++) - { - for(sal_uInt16 b(0); b < RowSize; b++) - { - set(a, b, get(a, b) * rfValue); - } - } - } - void doMulMatrix(const ImplHomMatrixTemplate& rMat) { // create a copy as source for the original values diff --git a/include/basegfx/numeric/ftools.hxx b/include/basegfx/numeric/ftools.hxx index 8404dc2babcd..a3335da57db1 100644 --- a/include/basegfx/numeric/ftools.hxx +++ b/include/basegfx/numeric/ftools.hxx @@ -109,10 +109,6 @@ namespace basegfx */ BASEGFX_DLLPUBLIC double snapToZeroRange(double v, double fWidth); - /** Snap v to the range [fLow .. fHigh] using modulo - */ - double snapToRange(double v, double fLow, double fHigh); - /** return fValue with the sign of fSignCarrier, thus evtl. changed */ inline double copySign(double fValue, double fSignCarrier) diff --git a/include/basegfx/polygon/b2dpolygon.hxx b/include/basegfx/polygon/b2dpolygon.hxx index 8471a14ef06e..f5b6b82f6fac 100644 --- a/include/basegfx/polygon/b2dpolygon.hxx +++ b/include/basegfx/polygon/b2dpolygon.hxx @@ -123,7 +123,7 @@ namespace basegfx Index of the addressed edge's start point @param rTarget - The B2DCubicBezier to be filled. It's data WILL be changed. + The B2DCubicBezier to be filled. Its data WILL be changed. */ void getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const; @@ -234,7 +234,7 @@ namespace basegfx template std::shared_ptr getSystemDependentData(basegfx::SDD_Type aType) const { - return std::static_pointer_cast(getSystemDependantDataInternal(aType)); + return std::static_pointer_cast(getSystemDependentDataInternal(aType)); } template @@ -254,7 +254,7 @@ namespace basegfx private: void addOrReplaceSystemDependentDataInternal(SystemDependentData_SharedPtr& rData) const; - SystemDependentData_SharedPtr getSystemDependantDataInternal(basegfx::SDD_Type aType) const; + SystemDependentData_SharedPtr getSystemDependentDataInternal(basegfx::SDD_Type aType) const; const basegfx::B2DVector& getPrevControlVector(sal_uInt32 nIndex) const; const basegfx::B2DVector& getNextControlVector(sal_uInt32 nIndex) const; }; diff --git a/include/basegfx/polygon/b2dpolypolygon.hxx b/include/basegfx/polygon/b2dpolypolygon.hxx index eb7b4d0f7444..d6106671edd5 100644 --- a/include/basegfx/polygon/b2dpolypolygon.hxx +++ b/include/basegfx/polygon/b2dpolypolygon.hxx @@ -132,7 +132,7 @@ namespace basegfx template std::shared_ptr getSystemDependentData(basegfx::SDD_Type aType) const { - return std::static_pointer_cast(getSystemDependantDataInternal(aType)); + return std::static_pointer_cast(getSystemDependentDataInternal(aType)); } template @@ -152,7 +152,7 @@ namespace basegfx private: void addOrReplaceSystemDependentDataInternal(SystemDependentData_SharedPtr& rData) const; - SystemDependentData_SharedPtr getSystemDependantDataInternal(basegfx::SDD_Type aType) const; + SystemDependentData_SharedPtr getSystemDependentDataInternal(basegfx::SDD_Type aType) const; }; // typedef for a vector of B2DPolyPolygons diff --git a/include/basegfx/polygon/b2dtrapezoid.hxx b/include/basegfx/polygon/b2dtrapezoid.hxx index baeab9896362..b6610a44d1a3 100644 --- a/include/basegfx/polygon/b2dtrapezoid.hxx +++ b/include/basegfx/polygon/b2dtrapezoid.hxx @@ -79,7 +79,7 @@ namespace basegfx::utils { // convert SourcePolyPolygon to trapezoids. The trapezoids will be appended to // ro_Result. ro_Result will not be cleared. If SourcePolyPolygon contains curves, - // it's default AdaptiveSubdivision will be used. + // its default AdaptiveSubdivision will be used. // CAUTION: Trapezoids are orientation-dependent in the sense that the upper and lower // lines have to be parallel to the X-Axis, thus this subdivision is NOT simply usable // for primitive decompositions. To use it, the shear and rotate parts of the diff --git a/include/basegfx/range/b2dconnectedranges.hxx b/include/basegfx/range/b2dconnectedranges.hxx index fa442d62fb82..97d782d91bdb 100644 --- a/include/basegfx/range/b2dconnectedranges.hxx +++ b/include/basegfx/range/b2dconnectedranges.hxx @@ -166,7 +166,7 @@ namespace basegfx aCurrAggregate->maComponentList ); // remove and delete aCurrAggregate entry - // from list (we've gutted it's content + // from list (we've gutted its content // above). list::erase() will update our // iterator with the predecessor here. aCurrAggregate = maDisjunctAggregatesList.erase( aCurrAggregate ); diff --git a/include/basegfx/range/b3drange.hxx b/include/basegfx/range/b3drange.hxx index 338c4f54a029..102ae1e12c20 100644 --- a/include/basegfx/range/b3drange.hxx +++ b/include/basegfx/range/b3drange.hxx @@ -213,9 +213,6 @@ namespace basegfx is part of the transformation. */ B3DRange& operator*=( const ::basegfx::B3DHomMatrix& rMat ); - - /** Get a range filled with (0.0, 0.0, 0.0, 1.0, 1.0, 1.0) */ - static const B3DRange& getUnitB3DRange(); }; /** Transform B3DRange by given transformation matrix (see operator*=()) diff --git a/include/basegfx/utils/canvastools.hxx b/include/basegfx/utils/canvastools.hxx index 5fcb6fb531d8..fe531ecb4e2b 100644 --- a/include/basegfx/utils/canvastools.hxx +++ b/include/basegfx/utils/canvastools.hxx @@ -139,8 +139,8 @@ namespace basegfx::unotools // Geometry comparisons - /** Return smalltest integer range, which completely contains - given floating point range. + /** Return the smallest integer range, which completely contains + the given floating point range. @param rRange Input range. Values must be within the representable @@ -151,8 +151,8 @@ namespace basegfx::unotools */ BASEGFX_DLLPUBLIC ::basegfx::B2IRange b2ISurroundingRangeFromB2DRange( const ::basegfx::B2DRange& rRange ); - /** Return smalltest B2DRange with integer values, which - completely contains given floating point range. + /** Return the smallest B2DRange with integer values, which + completely contains the given floating point range. @param rRange Input range. diff --git a/include/basegfx/utils/systemdependentdata.hxx b/include/basegfx/utils/systemdependentdata.hxx index b594766c3766..792c16007f40 100644 --- a/include/basegfx/utils/systemdependentdata.hxx +++ b/include/basegfx/utils/systemdependentdata.hxx @@ -72,7 +72,7 @@ namespace basegfx // getHoldCyclesInSeconds and estimateUsageInBytes, executed // using getHoldCyclesInSeconds. StartValue is 0 to detect // not-yet-calculated state - sal_uInt32 mnCalculatedCycles; + mutable sal_uInt32 mnCalculatedCycles; public: SystemDependentData( @@ -93,10 +93,6 @@ namespace basegfx // mnCalculatedCycles sal_uInt32 calculateCombinedHoldCyclesInSeconds() const; - // Allow read access to the calculated cycles in seconds, this - // can be e.g. used to determine if this instance got added - sal_uInt32 getCombinedHoldCyclesInSeconds() const { return mnCalculatedCycles; } - // Size estimation of the entry in bytes - does not have to // be used, but should be. Default returns zero what // means there is no size estimation available. Override to diff --git a/include/basegfx/utils/tools.hxx b/include/basegfx/utils/tools.hxx index f8fc61999505..5d59dfecc3f1 100644 --- a/include/basegfx/utils/tools.hxx +++ b/include/basegfx/utils/tools.hxx @@ -31,13 +31,13 @@ namespace basegfx namespace basegfx::utils { - /** Expand given parallelogram, such that it extends beyond - bound rect in a given direction. + /** Expand the given parallelogram, such that it extends beyond + the bounding rect in a given direction. This method is useful when e.g. generating one-dimensional gradients, such as linear or axial gradients: those gradients vary only in one direction, the other has - constant color. Most of the time, those gradients extends + constant color. Most of the time, those gradients extend infinitely in the direction with the constant color, but practically, one always has a limiting bound rect into which the gradient is painted. The method at hand now @@ -55,34 +55,34 @@ namespace basegfx::utils infinite lines. @param io_rLeftTop - Left, top edge of the parallelogramm. Note that this need + Left, top edge of the parallelogram. Note that this need not be the left, top edge geometrically, it's just used when determining the extension direction. Thus, it's - perfectly legal to affine-transform a rectangle, and given + perfectly legal to affine-transform a rectangle, and give the transformed point here. On method return, this parameter will contain the adapted output. @param io_rLeftBottom - Left, bottom edge of the parallelogramm. Note that this need + Left, bottom edge of the parallelogram. Note that this need not be the left, bottom edge geometrically, it's just used when determining the extension direction. Thus, it's - perfectly legal to affine-transform a rectangle, and given + perfectly legal to affine-transform a rectangle, and give the transformed point here. On method return, this parameter will contain the adapted output. @param io_rRightTop - Right, top edge of the parallelogramm. Note that this need + Right, top edge of the parallelogram. Note that this need not be the right, top edge geometrically, it's just used when determining the extension direction. Thus, it's - perfectly legal to affine-transform a rectangle, and given + perfectly legal to affine-transform a rectangle, and give the transformed point here. On method return, this parameter will contain the adapted output. @param io_rRightBottom - Right, bottom edge of the parallelogramm. Note that this need + Right, bottom edge of the parallelogram. Note that this need not be the right, bottom edge geometrically, it's just used when determining the extension direction. Thus, it's - perfectly legal to affine-transform a rectangle, and given + perfectly legal to affine-transform a rectangle, and give the transformed point here. On method return, this parameter will contain the adapted output. @@ -95,7 +95,7 @@ namespace basegfx::utils ::basegfx::B2DPoint& io_rRightBottom, const ::basegfx::B2DRange& rFitTarget ); - /** Creates polypolygon with the given number as seven-segment + /** Creates a polypolygon with the given number as seven-segment digits @param fVal @@ -103,12 +103,12 @@ namespace basegfx::utils @param nTotalDigits Total number of digits to display. If less is needed for - given number, fill space with blanks. + the given number, fill space with blanks. @param nDecPlaces Decimal places to show. When 0, display as integer. When - negative, fill given number of before-the-decimal point - with zero. + negative, fill given number of places before the decimal point + with zeroes. @param bLitSegments When true, return a polygon containing the segments that diff --git a/include/basic/sbmeth.hxx b/include/basic/sbmeth.hxx index 9c884bcf9518..c483034866b1 100644 --- a/include/basic/sbmeth.hxx +++ b/include/basic/sbmeth.hxx @@ -57,7 +57,7 @@ public: SbModule* GetModule() { return pMod; } BasicDebugFlags GetDebugFlags() const { return nDebugFlags; } void SetDebugFlags( BasicDebugFlags n ) { nDebugFlags = n; } - void GetLineRange( sal_uInt16&, sal_uInt16& ); + void GetLineRange( sal_uInt16&, sal_uInt16& ) const; // Interface to execute a method from the applications ErrCode Call( SbxValue* pRet, SbxVariable* pCaller = nullptr ); diff --git a/include/basic/sbmod.hxx b/include/basic/sbmod.hxx index e9f7a1fc15fc..de3ffd9810d2 100644 --- a/include/basic/sbmod.hxx +++ b/include/basic/sbmod.hxx @@ -107,6 +107,9 @@ public: const OUString& GetSource() const { return aOUSource;} void SetSource( const OUString& r ); + // Gets a copy of the module source but within the given method removed + OUString GetSourceWithoutMethod(const SbMethod& rMethod) const; + bool Compile(); bool IsCompiled() const; SAL_DLLPRIVATE const SbxObject* FindType( const OUString& aTypeName ) const; diff --git a/include/basic/sbutil.hxx b/include/basic/sbutil.hxx new file mode 100644 index 000000000000..d0329243a29f --- /dev/null +++ b/include/basic/sbutil.hxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * 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 . + */ + +#pragma once + +#include + +#include + +#include + +#include + +namespace sb +{ +// Returns the position of the last character of any of the following EOL char combinations: +// CR, CR/LF, LF, return -1 if no EOL is found +BASIC_DLLPUBLIC sal_Int32 searchEOL(std::u16string_view rStr, sal_Int32 fromIndex = 0); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/basic/sbxvar.hxx b/include/basic/sbxvar.hxx index a98e1f957dd4..06f91282a998 100644 --- a/include/basic/sbxvar.hxx +++ b/include/basic/sbxvar.hxx @@ -320,7 +320,7 @@ public: typedef tools::SvRef SbxObjectRef; typedef tools::SvRef SbxVariableRef; -//tdf#59222 SbxEnsureParentVariable is a SbxVariable which keeps a reference to +// tdf#59222 SbxEnsureParentVariable is a SbxVariable which keeps a reference to //its parent, ensuring it always exists while this SbxVariable exists class SbxEnsureParentVariable final : public SbxVariable { @@ -330,4 +330,9 @@ public: virtual void SetParent(SbxObject* p) override; }; +// tdf#102381 - turns a variable into the representation of a missing argument including the +// error value 448 (ERRCODE_BASIC_NAMED_NOT_FOUND, as in VB). Exported so that callers outside +// can pass missing arguments to basic. +BASIC_DLLPUBLIC void SbxSetMissingParameter(SbxVariable& rVar); + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/codemaker/options.hxx b/include/codemaker/options.hxx index 6107419636fe..664a02c21fcc 100644 --- a/include/codemaker/options.hxx +++ b/include/codemaker/options.hxx @@ -50,7 +50,6 @@ public: virtual ::rtl::OString prepareHelp() = 0; - const ::rtl::OString& getProgramName() const { return m_program;} bool isValid(const ::rtl::OString& option) const; /// @throws IllegalArgument const OString& getOption(const ::rtl::OString& option) const; diff --git a/include/com/sun/star/uno/Any.h b/include/com/sun/star/uno/Any.h index 6efc711b6a3d..01b22cf0e2d8 100644 --- a/include/com/sun/star/uno/Any.h +++ b/include/com/sun/star/uno/Any.h @@ -34,7 +34,7 @@ #include "com/sun/star/uno/TypeClass.hdl" #include "rtl/alloc.h" -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY #include #endif @@ -82,7 +82,7 @@ public: @param value value of the Any */ template -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY // Disallow things like // Reference x(...); // Any a(*x); @@ -289,14 +289,14 @@ public: The values need not be of equal type, e.g. a short integer is compared to a long integer. @param rAny another any (right side) - @return true if both any contains equal values + @return true if both anys contain equal values */ inline bool SAL_CALL operator == ( const Any & rAny ) const; /** Inequality operator: compares two anys. The values need not be of equal type, e.g. a short integer is compared to a long integer. @param rAny another any (right side) - @return true if both any contains unequal values + @return true if both anys contain unequal values */ inline bool SAL_CALL operator != ( const Any & rAny ) const; diff --git a/include/com/sun/star/uno/Any.hxx b/include/com/sun/star/uno/Any.hxx index d1e83dc54cf7..e5bb5b9268f2 100644 --- a/include/com/sun/star/uno/Any.hxx +++ b/include/com/sun/star/uno/Any.hxx @@ -63,7 +63,7 @@ inline Any::Any() template -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY // Disallow things like // Reference x(...); // Any a(*x); diff --git a/include/com/sun/star/uno/Reference.h b/include/com/sun/star/uno/Reference.h index cff277630465..1135e75c395f 100644 --- a/include/com/sun/star/uno/Reference.h +++ b/include/com/sun/star/uno/Reference.h @@ -61,7 +61,7 @@ enum UnoReference_NoAcquire }; /** This base class serves as a base class for all template reference classes and - has been introduced due to compiler problems with templated operators ==, =!. + has been introduced due to compiler problems with templated operators ==, !=. */ class BaseReference { @@ -374,7 +374,7 @@ public: /** Cast operator to Reference< XInterface >: Reference objects are binary compatible and any interface must be derived from com.sun.star.uno.XInterface. - This a useful direct cast possibility. + This is a useful direct cast possibility. */ SAL_CALL operator const Reference< XInterface > & () const { return * reinterpret_cast< const Reference< XInterface > * >( this ); } @@ -564,14 +564,14 @@ public: #if defined LIBO_INTERNAL_ONLY /** Queries this for the required interface, and returns the requested reference, possibly empty. A syntactic sugar for 'Reference< other_type > xOther(xThis, UNO_QUERY)' that avoids some - verbocity. + verbosity. @return new reference */ template< class other_type > inline Reference< other_type > query() const; /** Queries this for the required interface, and returns the requested reference, or throws on failure. A syntactic sugar for 'Reference< other_type > xOther(xThis, UNO_QUERY_THROW)' - that avoids some verbocity. + that avoids some verbosity. @return new reference */ diff --git a/include/com/sun/star/uno/Type.h b/include/com/sun/star/uno/Type.h index 5dc1b41e0bc2..28c5c4eb6a95 100644 --- a/include/com/sun/star/uno/Type.h +++ b/include/com/sun/star/uno/Type.h @@ -176,21 +176,21 @@ public: /** Compares two types. @param rType another type - @return true if both types refer the same type, false otherwise + @return true if both types refer to the same type, false otherwise */ bool SAL_CALL equals( const Type & rType ) const { return ::typelib_typedescriptionreference_equals( _pType, rType._pType ); } /** Equality operator: Compares two types. @param rType another type - @return true if both types refer the same type, false otherwise + @return true if both types refer to the same type, false otherwise */ bool SAL_CALL operator == ( const Type & rType ) const { return ::typelib_typedescriptionreference_equals( _pType, rType._pType ); } /** Inequality operator: Compares two types. @param rType another type - @return false if both types refer the same type, true otherwise + @return false if both types refer to the same type, true otherwise */ bool SAL_CALL operator != ( const Type & rType ) const { return (! ::typelib_typedescriptionreference_equals( _pType, rType._pType )); } diff --git a/include/comphelper/ChainablePropertySet.hxx b/include/comphelper/ChainablePropertySet.hxx index 0a0fda0d742d..a243d34f525a 100644 --- a/include/comphelper/ChainablePropertySet.hxx +++ b/include/comphelper/ChainablePropertySet.hxx @@ -40,7 +40,7 @@ namespace comphelper * * 1. It implements both the PropertySet and MultiPropertySet interfaces. * 2. It can be 'included' in a MasterPropertySet to seamlessly appear as if - * if it's properties were in the master. + * its properties were in the master. * * To be used as a base class for PropertySets, the subclass must implement * the 6 protected pure virtual functions. If a mutex is passed to the diff --git a/include/comphelper/SelectionMultiplex.hxx b/include/comphelper/SelectionMultiplex.hxx index b33c9911add0..e53556505a30 100644 --- a/include/comphelper/SelectionMultiplex.hxx +++ b/include/comphelper/SelectionMultiplex.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_SELECTIONMULTIPLEX_HXX -#define INCLUDED_COMPHELPER_SELECTIONMULTIPLEX_HXX +#pragma once #include #include @@ -88,7 +87,4 @@ namespace comphelper } // namespace comphelper - -#endif // INCLUDED_COMPHELPER_SELECTIONMULTIPLEX_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/accessiblekeybindinghelper.hxx b/include/comphelper/accessiblekeybindinghelper.hxx index 141388aeaf8b..105bfcd1c66c 100644 --- a/include/comphelper/accessiblekeybindinghelper.hxx +++ b/include/comphelper/accessiblekeybindinghelper.hxx @@ -39,8 +39,7 @@ namespace comphelper class COMPHELPER_DLLPUBLIC OAccessibleKeyBindingHelper final : public OAccessibleKeyBindingHelper_Base { private: - typedef ::std::vector< css::uno::Sequence< css::awt::KeyStroke > > KeyBindings; - KeyBindings m_aKeyBindings; + std::vector> m_aKeyBindings; std::mutex m_aMutex; virtual ~OAccessibleKeyBindingHelper() override; diff --git a/include/comphelper/anycompare.hxx b/include/comphelper/anycompare.hxx index 3618106db34f..9352961f48bb 100644 --- a/include/comphelper/anycompare.hxx +++ b/include/comphelper/anycompare.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_ANYCOMPARE_HXX -#define INCLUDED_COMPHELPER_ANYCOMPARE_HXX +#pragma once #include @@ -213,7 +212,4 @@ namespace comphelper } // namespace comphelper - -#endif // INCLUDED_COMPHELPER_ANYCOMPARE_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/anytohash.hxx b/include/comphelper/anytohash.hxx index 0aa14f47e8de..847765ac479b 100644 --- a/include/comphelper/anytohash.hxx +++ b/include/comphelper/anytohash.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_ANYTOHASH_HXX -#define INCLUDED_COMPHELPER_ANYTOHASH_HXX +#pragma once #include @@ -43,6 +42,4 @@ namespace comphelper COMPHELPER_DLLPUBLIC std::optional anyToHash(css::uno::Any const& value); } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/anytostring.hxx b/include/comphelper/anytostring.hxx index 6d100221e7d8..db9b97e60c9a 100644 --- a/include/comphelper/anytostring.hxx +++ b/include/comphelper/anytostring.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_ANYTOSTRING_HXX -#define INCLUDED_COMPHELPER_ANYTOSTRING_HXX +#pragma once #include #include @@ -40,6 +39,4 @@ namespace comphelper COMPHELPER_DLLPUBLIC OUString anyToString(css::uno::Any const& value); } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/asyncquithandler.hxx b/include/comphelper/asyncquithandler.hxx index ce3db23a147a..742fb86c9fec 100644 --- a/include/comphelper/asyncquithandler.hxx +++ b/include/comphelper/asyncquithandler.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_ASYNCQUITHANDLER_HXX -#define INCLUDED_COMPHELPER_ASYNCQUITHANDLER_HXX +#pragma once #include #include @@ -39,6 +38,4 @@ public: DECL_STATIC_LINK(AsyncQuitHandler, OnAsyncQuit, void*, void); }; -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/attributelist.hxx b/include/comphelper/attributelist.hxx index e49beeb5fd60..5500a6bfa46d 100644 --- a/include/comphelper/attributelist.hxx +++ b/include/comphelper/attributelist.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_ATTRIBUTELIST_HXX -#define INCLUDED_COMPHELPER_ATTRIBUTELIST_HXX +#pragma once #include @@ -86,6 +85,4 @@ public: } // namespace comphelper -#endif // INCLUDED_COMPHELPER_ATTRIBUTELIST_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/backupfilehelper.hxx b/include/comphelper/backupfilehelper.hxx index d2bdf5d0e86d..a90a41bb0b06 100644 --- a/include/comphelper/backupfilehelper.hxx +++ b/include/comphelper/backupfilehelper.hxx @@ -178,7 +178,7 @@ namespace comphelper /** Return the profile url */ static const OUString& getUserProfileURL(); - /** Return the url of the backed up profile (when in safe mode) */ + /** Return the url of the backed up profile (when in troubleshoot mode) */ static const OUString& getUserProfileWorkURL(); private: diff --git a/include/comphelper/basicio.hxx b/include/comphelper/basicio.hxx index 62260e3da360..88b2994ce649 100644 --- a/include/comphelper/basicio.hxx +++ b/include/comphelper/basicio.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_BASICIO_HXX -#define INCLUDED_COMPHELPER_BASICIO_HXX +#pragma once #include #include @@ -82,7 +81,4 @@ const css::uno::Reference& operator << (const css: } // namespace comphelper - -#endif // INCLUDED_COMPHELPER_BASICIO_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/classids.hxx b/include/comphelper/classids.hxx index 4c345b84bf93..d6af27c4a162 100644 --- a/include/comphelper/classids.hxx +++ b/include/comphelper/classids.hxx @@ -16,8 +16,8 @@ * 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_COMPHELPER_CLASSIDS_HXX -#define INCLUDED_COMPHELPER_CLASSIDS_HXX + +#pragma once /* * StarWriter @@ -329,6 +329,4 @@ 0xd7896d52, 0xb7af, 0x4820, \ 0x9d, 0xfe, 0xd4, 0x04, 0xd0, 0x15, 0x96, 0x0f -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/container.hxx b/include/comphelper/container.hxx index 84acfc5b0fc5..af13279d93a4 100644 --- a/include/comphelper/container.hxx +++ b/include/comphelper/container.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_CONTAINER_HXX -#define INCLUDED_COMPHELPER_CONTAINER_HXX +#pragma once #include #include @@ -69,8 +68,4 @@ protected: } // namespace comphelper - -#endif // INCLUDED_COMPHELPER_CONTAINER_HXX - - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/diagnose_ex.hxx b/include/comphelper/diagnose_ex.hxx index 28de2330c4b3..c98b6c269480 100644 --- a/include/comphelper/diagnose_ex.hxx +++ b/include/comphelper/diagnose_ex.hxx @@ -16,8 +16,8 @@ * 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_COMPHELPER_DIAGNOSE_EX_HXX -#define INCLUDED_COMPHELPER_DIAGNOSE_EX_HXX + +#pragma once #include #include @@ -176,6 +176,4 @@ COMPHELPER_DLLPUBLIC OString exceptionToString(css::uno::Any const & caughtEx); } while (false) #endif -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/documentinfo.hxx b/include/comphelper/documentinfo.hxx index a7002120a4bf..6fb2002c4504 100644 --- a/include/comphelper/documentinfo.hxx +++ b/include/comphelper/documentinfo.hxx @@ -23,6 +23,7 @@ #include #include +namespace com::sun::star::beans { class XPropertySet; } namespace com::sun::star::frame { class XModel; } namespace com::sun::star::uno { template class Reference; } @@ -41,6 +42,16 @@ namespace comphelper { /** notify that this document contains a macro event handler */ COMPHELPER_DLLPUBLIC void notifyMacroEventRead( const css::uno::Reference< css::frame::XModel >& _rxDocument ); + + /** notify that this document contains a form control with a remote + image URL that was deferred during import. The control reference + and URL are accumulated so they can be registered as links + post-load when the user allows updates. + */ + COMPHELPER_DLLPUBLIC void notifyRemoteContentFound( + const css::uno::Reference< css::frame::XModel >& _rxDocument, + const css::uno::Reference< css::beans::XPropertySet >& _rxControl, + const OUString& _rURL ); } } // namespace comphelper diff --git a/include/comphelper/embeddedobjectcontainer.hxx b/include/comphelper/embeddedobjectcontainer.hxx index a6723af4d649..3b8116797e6a 100644 --- a/include/comphelper/embeddedobjectcontainer.hxx +++ b/include/comphelper/embeddedobjectcontainer.hxx @@ -16,8 +16,8 @@ * 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_COMPHELPER_EMBEDDEDOBJECTCONTAINER_HXX -#define INCLUDED_COMPHELPER_EMBEDDEDOBJECTCONTAINER_HXX + +#pragma once #include @@ -210,6 +210,4 @@ public: } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/emscriptenthreading.hxx b/include/comphelper/emscriptenthreading.hxx index 9d0abc273feb..5fccc4eeeb20 100644 --- a/include/comphelper/emscriptenthreading.hxx +++ b/include/comphelper/emscriptenthreading.hxx @@ -14,7 +14,8 @@ #include #include -#if defined EMSCRIPTEN && ENABLE_QT6 && HAVE_EMSCRIPTEN_JSPI && !HAVE_EMSCRIPTEN_PROXY_TO_PTHREAD +#if defined __EMSCRIPTEN__ && ENABLE_QT6 && HAVE_EMSCRIPTEN_JSPI \ + && !HAVE_EMSCRIPTEN_PROXY_TO_PTHREAD #include diff --git a/include/comphelper/errcode.hxx b/include/comphelper/errcode.hxx index 9cabdc55d9a8..49aeefe0b88f 100644 --- a/include/comphelper/errcode.hxx +++ b/include/comphelper/errcode.hxx @@ -281,86 +281,86 @@ enum class ErrCodeClass { Compiler = 23 }; -#define ERRCODE_NONE ErrCode(0) +constexpr ErrCode ERRCODE_NONE {0}; -#define ERRCODE_IO_MISPLACEDCHAR ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 1 ) -#define ERRCODE_IO_NOTEXISTS ErrCode( ErrCodeArea::Io, ErrCodeClass::NotExists, 2 ) -#define ERRCODE_IO_ALREADYEXISTS ErrCode( ErrCodeArea::Io, ErrCodeClass::AlreadyExists, 3 ) -#define ERRCODE_IO_NOTADIRECTORY ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 4 ) -#define ERRCODE_IO_NOTAFILE ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 5 ) -#define ERRCODE_IO_INVALIDDEVICE ErrCode( ErrCodeArea::Io, ErrCodeClass::Path, 6 ) -#define ERRCODE_IO_ACCESSDENIED ErrCode( ErrCodeArea::Io, ErrCodeClass::Access, 7 ) -#define ERRCODE_IO_LOCKVIOLATION ErrCode( ErrCodeArea::Io, ErrCodeClass::Locking, 8 ) -#define ERRCODE_IO_OUTOFSPACE ErrCode( ErrCodeArea::Io, ErrCodeClass::Space, 9 ) -#define ERRCODE_IO_ISWILDCARD ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 11 ) -#define ERRCODE_IO_NOTSUPPORTED ErrCode( ErrCodeArea::Io, ErrCodeClass::NotSupported, 12 ) -#define ERRCODE_IO_GENERAL ErrCode( ErrCodeArea::Io, ErrCodeClass::General, 13 ) -#define ERRCODE_IO_TOOMANYOPENFILES ErrCode( ErrCodeArea::Io, ErrCodeClass::Space, 14 ) -#define ERRCODE_IO_CANTREAD ErrCode( ErrCodeArea::Io, ErrCodeClass::Read, 15 ) -#define ERRCODE_IO_CANTWRITE ErrCode( ErrCodeArea::Io, ErrCodeClass::Write, 16 ) -#define ERRCODE_IO_OUTOFMEMORY ErrCode( ErrCodeArea::Io, ErrCodeClass::Space, 17 ) -#define ERRCODE_IO_CANTSEEK ErrCode( ErrCodeArea::Io, ErrCodeClass::General, 18 ) -#define ERRCODE_IO_CANTTELL ErrCode( ErrCodeArea::Io, ErrCodeClass::General, 19 ) -#define ERRCODE_IO_WRONGVERSION ErrCode( ErrCodeArea::Io, ErrCodeClass::Version, 20 ) -#define ERRCODE_IO_WRONGFORMAT ErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ) -#define ERRCODE_IO_INVALIDCHAR ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 22 ) -#define ERRCODE_IO_UNKNOWN ErrCode( ErrCodeArea::Io, ErrCodeClass::Unknown, 23 ) -#define ERRCODE_IO_INVALIDACCESS ErrCode( ErrCodeArea::Io, ErrCodeClass::Access, 24 ) -#define ERRCODE_IO_CANTCREATE ErrCode( ErrCodeArea::Io, ErrCodeClass::Create, 25 ) -#define ERRCODE_IO_INVALIDPARAMETER ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 26 ) -#define ERRCODE_IO_ABORT ErrCode( ErrCodeArea::Io, ErrCodeClass::Abort, 27 ) -#define ERRCODE_IO_NOTEXISTSPATH ErrCode( ErrCodeArea::Io, ErrCodeClass::NotExists, 28 ) -#define ERRCODE_IO_PENDING ErrCode( ErrCodeArea::Io, ErrCodeClass::NotExists, 29 ) -#define ERRCODE_IO_RECURSIVE ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 30 ) -#define ERRCODE_IO_NAMETOOLONG ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 31 ) -#define ERRCODE_IO_INVALIDLENGTH ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 32 ) -#define ERRCODE_IO_CURRENTDIR ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 33 ) -#define ERRCODE_IO_NOTSAMEDEVICE ErrCode( ErrCodeArea::Io, ErrCodeClass::Parameter, 34 ) -#define ERRCODE_IO_DEVICENOTREADY ErrCode( ErrCodeArea::Io, ErrCodeClass::Read, 35 ) -#define ERRCODE_IO_BADCRC ErrCode( ErrCodeArea::Io, ErrCodeClass::Read, 36 ) -#define ERRCODE_IO_WRITEPROTECTED ErrCode( ErrCodeArea::Io, ErrCodeClass::Access, 37 ) -#define ERRCODE_IO_BROKENPACKAGE ErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 38 ) -#define ERRCODE_IO_NOTSTORABLEINBINARYFORMAT ErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 39 ) -#define ERRCODE_IO_FILTERDISABLED ErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 40 ) +constexpr ErrCode ERRCODE_IO_MISPLACEDCHAR { ErrCodeArea::Io, ErrCodeClass::Parameter, 1 }; +constexpr ErrCode ERRCODE_IO_NOTEXISTS { ErrCodeArea::Io, ErrCodeClass::NotExists, 2 }; +constexpr ErrCode ERRCODE_IO_ALREADYEXISTS { ErrCodeArea::Io, ErrCodeClass::AlreadyExists, 3 }; +constexpr ErrCode ERRCODE_IO_NOTADIRECTORY { ErrCodeArea::Io, ErrCodeClass::Parameter, 4 }; +constexpr ErrCode ERRCODE_IO_NOTAFILE { ErrCodeArea::Io, ErrCodeClass::Parameter, 5 }; +constexpr ErrCode ERRCODE_IO_INVALIDDEVICE { ErrCodeArea::Io, ErrCodeClass::Path, 6 }; +constexpr ErrCode ERRCODE_IO_ACCESSDENIED { ErrCodeArea::Io, ErrCodeClass::Access, 7 }; +constexpr ErrCode ERRCODE_IO_LOCKVIOLATION { ErrCodeArea::Io, ErrCodeClass::Locking, 8 }; +constexpr ErrCode ERRCODE_IO_OUTOFSPACE { ErrCodeArea::Io, ErrCodeClass::Space, 9 }; +constexpr ErrCode ERRCODE_IO_ISWILDCARD { ErrCodeArea::Io, ErrCodeClass::Parameter, 11 }; +constexpr ErrCode ERRCODE_IO_NOTSUPPORTED { ErrCodeArea::Io, ErrCodeClass::NotSupported, 12 }; +constexpr ErrCode ERRCODE_IO_GENERAL { ErrCodeArea::Io, ErrCodeClass::General, 13 }; +constexpr ErrCode ERRCODE_IO_TOOMANYOPENFILES { ErrCodeArea::Io, ErrCodeClass::Space, 14 }; +constexpr ErrCode ERRCODE_IO_CANTREAD { ErrCodeArea::Io, ErrCodeClass::Read, 15 }; +constexpr ErrCode ERRCODE_IO_CANTWRITE { ErrCodeArea::Io, ErrCodeClass::Write, 16 }; +constexpr ErrCode ERRCODE_IO_OUTOFMEMORY { ErrCodeArea::Io, ErrCodeClass::Space, 17 }; +constexpr ErrCode ERRCODE_IO_CANTSEEK { ErrCodeArea::Io, ErrCodeClass::General, 18 }; +constexpr ErrCode ERRCODE_IO_CANTTELL { ErrCodeArea::Io, ErrCodeClass::General, 19 }; +constexpr ErrCode ERRCODE_IO_WRONGVERSION { ErrCodeArea::Io, ErrCodeClass::Version, 20 }; +constexpr ErrCode ERRCODE_IO_WRONGFORMAT { ErrCodeArea::Io, ErrCodeClass::Format, 21 }; +constexpr ErrCode ERRCODE_IO_INVALIDCHAR { ErrCodeArea::Io, ErrCodeClass::Parameter, 22 }; +constexpr ErrCode ERRCODE_IO_UNKNOWN { ErrCodeArea::Io, ErrCodeClass::Unknown, 23 }; +constexpr ErrCode ERRCODE_IO_INVALIDACCESS { ErrCodeArea::Io, ErrCodeClass::Access, 24 }; +constexpr ErrCode ERRCODE_IO_CANTCREATE { ErrCodeArea::Io, ErrCodeClass::Create, 25 }; +constexpr ErrCode ERRCODE_IO_INVALIDPARAMETER { ErrCodeArea::Io, ErrCodeClass::Parameter, 26 }; +constexpr ErrCode ERRCODE_IO_ABORT { ErrCodeArea::Io, ErrCodeClass::Abort, 27 }; +constexpr ErrCode ERRCODE_IO_NOTEXISTSPATH { ErrCodeArea::Io, ErrCodeClass::NotExists, 28 }; +constexpr ErrCode ERRCODE_IO_PENDING { ErrCodeArea::Io, ErrCodeClass::NotExists, 29 }; +constexpr ErrCode ERRCODE_IO_RECURSIVE { ErrCodeArea::Io, ErrCodeClass::Parameter, 30 }; +constexpr ErrCode ERRCODE_IO_NAMETOOLONG { ErrCodeArea::Io, ErrCodeClass::Parameter, 31 }; +constexpr ErrCode ERRCODE_IO_INVALIDLENGTH { ErrCodeArea::Io, ErrCodeClass::Parameter, 32 }; +constexpr ErrCode ERRCODE_IO_CURRENTDIR { ErrCodeArea::Io, ErrCodeClass::Parameter, 33 }; +constexpr ErrCode ERRCODE_IO_NOTSAMEDEVICE { ErrCodeArea::Io, ErrCodeClass::Parameter, 34 }; +constexpr ErrCode ERRCODE_IO_DEVICENOTREADY { ErrCodeArea::Io, ErrCodeClass::Read, 35 }; +constexpr ErrCode ERRCODE_IO_BADCRC { ErrCodeArea::Io, ErrCodeClass::Read, 36 }; +constexpr ErrCode ERRCODE_IO_WRITEPROTECTED { ErrCodeArea::Io, ErrCodeClass::Access, 37 }; +constexpr ErrCode ERRCODE_IO_BROKENPACKAGE { ErrCodeArea::Io, ErrCodeClass::Format, 38 }; +constexpr ErrCode ERRCODE_IO_NOTSTORABLEINBINARYFORMAT { ErrCodeArea::Io, ErrCodeClass::Format, 39 }; +constexpr ErrCode ERRCODE_IO_FILTERDISABLED { ErrCodeArea::Io, ErrCodeClass::Format, 40 }; // StreamErrorCodes -#define SVSTREAM_GENERALERROR ERRCODE_IO_GENERAL -#define SVSTREAM_FILE_NOT_FOUND ERRCODE_IO_NOTEXISTS -#define SVSTREAM_PATH_NOT_FOUND ERRCODE_IO_NOTEXISTSPATH -#define SVSTREAM_TOO_MANY_OPEN_FILES ERRCODE_IO_TOOMANYOPENFILES -#define SVSTREAM_ACCESS_DENIED ERRCODE_IO_ACCESSDENIED -#define SVSTREAM_SHARING_VIOLATION ERRCODE_IO_LOCKVIOLATION -#define SVSTREAM_LOCKING_VIOLATION ERRCODE_IO_LOCKVIOLATION -#define SVSTREAM_SHARE_BUFF_EXCEEDED ERRCODE_IO_LOCKVIOLATION +constexpr ErrCode SVSTREAM_GENERALERROR = ERRCODE_IO_GENERAL; +constexpr ErrCode SVSTREAM_FILE_NOT_FOUND = ERRCODE_IO_NOTEXISTS; +constexpr ErrCode SVSTREAM_PATH_NOT_FOUND = ERRCODE_IO_NOTEXISTSPATH; +constexpr ErrCode SVSTREAM_TOO_MANY_OPEN_FILES = ERRCODE_IO_TOOMANYOPENFILES; +constexpr ErrCode SVSTREAM_ACCESS_DENIED = ERRCODE_IO_ACCESSDENIED; +constexpr ErrCode SVSTREAM_SHARING_VIOLATION = ERRCODE_IO_LOCKVIOLATION; +constexpr ErrCode SVSTREAM_LOCKING_VIOLATION = ERRCODE_IO_LOCKVIOLATION; +constexpr ErrCode SVSTREAM_SHARE_BUFF_EXCEEDED = ERRCODE_IO_LOCKVIOLATION; -#define SVSTREAM_INVALID_ACCESS ERRCODE_IO_INVALIDACCESS -#define SVSTREAM_INVALID_HANDLE ERRCODE_IO_GENERAL -#define SVSTREAM_CANNOT_MAKE ERRCODE_IO_CANTCREATE -#define SVSTREAM_INVALID_PARAMETER ERRCODE_IO_INVALIDPARAMETER +constexpr ErrCode SVSTREAM_INVALID_ACCESS = ERRCODE_IO_INVALIDACCESS; +constexpr ErrCode SVSTREAM_INVALID_HANDLE = ERRCODE_IO_GENERAL; +constexpr ErrCode SVSTREAM_CANNOT_MAKE = ERRCODE_IO_CANTCREATE; +constexpr ErrCode SVSTREAM_INVALID_PARAMETER = ERRCODE_IO_INVALIDPARAMETER; -#define SVSTREAM_READ_ERROR ERRCODE_IO_CANTREAD -#define SVSTREAM_WRITE_ERROR ERRCODE_IO_CANTWRITE -#define SVSTREAM_SEEK_ERROR ERRCODE_IO_CANTSEEK +constexpr ErrCode SVSTREAM_READ_ERROR = ERRCODE_IO_CANTREAD; +constexpr ErrCode SVSTREAM_WRITE_ERROR = ERRCODE_IO_CANTWRITE; +constexpr ErrCode SVSTREAM_SEEK_ERROR = ERRCODE_IO_CANTSEEK; -#define SVSTREAM_OUTOFMEMORY ERRCODE_IO_OUTOFMEMORY +constexpr ErrCode SVSTREAM_OUTOFMEMORY = ERRCODE_IO_OUTOFMEMORY; -#define SVSTREAM_FILEFORMAT_ERROR ERRCODE_IO_WRONGFORMAT -#define SVSTREAM_WRONGVERSION ERRCODE_IO_WRONGVERSION +constexpr ErrCode SVSTREAM_FILEFORMAT_ERROR = ERRCODE_IO_WRONGFORMAT; +constexpr ErrCode SVSTREAM_WRONGVERSION = ERRCODE_IO_WRONGVERSION; -#define SVSTREAM_DISK_FULL ERRCODE_IO_OUTOFSPACE +constexpr ErrCode SVSTREAM_DISK_FULL = ERRCODE_IO_OUTOFSPACE; -#define PRINTER_ABORT ERRCODE_IO_ABORT -#define PRINTER_GENERALERROR ERRCODE_IO_GENERAL +constexpr ErrCode PRINTER_ABORT = ERRCODE_IO_ABORT; +constexpr ErrCode PRINTER_GENERALERROR = ERRCODE_IO_GENERAL; -#define ERRCODE_ABORT ERRCODE_IO_ABORT +constexpr ErrCode ERRCODE_ABORT = ERRCODE_IO_ABORT; -#define ERRCODE_INET_NAME_RESOLVE ErrCode(ErrCodeArea::Inet, ErrCodeClass::Read, 1) -#define ERRCODE_INET_CONNECT ErrCode(ErrCodeArea::Inet, ErrCodeClass::Read, 2) -#define ERRCODE_INET_READ ErrCode(ErrCodeArea::Inet, ErrCodeClass::Read, 3) -#define ERRCODE_INET_WRITE ErrCode(ErrCodeArea::Inet, ErrCodeClass::Write, 4) -#define ERRCODE_INET_GENERAL ErrCode(ErrCodeArea::Inet, ErrCodeClass::Write, 5) -#define ERRCODE_INET_OFFLINE ErrCode(ErrCodeArea::Inet, ErrCodeClass::Read, 6) -#define ERRCODE_INET_CONNECT_MSG ErrCode(ErrCodeArea::Inet, ErrCodeClass::Read, 7) +constexpr ErrCode ERRCODE_INET_NAME_RESOLVE {ErrCodeArea::Inet, ErrCodeClass::Read, 1}; +constexpr ErrCode ERRCODE_INET_CONNECT {ErrCodeArea::Inet, ErrCodeClass::Read, 2}; +constexpr ErrCode ERRCODE_INET_READ {ErrCodeArea::Inet, ErrCodeClass::Read, 3}; +constexpr ErrCode ERRCODE_INET_WRITE {ErrCodeArea::Inet, ErrCodeClass::Write, 4}; +constexpr ErrCode ERRCODE_INET_GENERAL {ErrCodeArea::Inet, ErrCodeClass::Write, 5}; +constexpr ErrCode ERRCODE_INET_OFFLINE {ErrCodeArea::Inet, ErrCodeClass::Read, 6}; +constexpr ErrCode ERRCODE_INET_CONNECT_MSG {ErrCodeArea::Inet, ErrCodeClass::Read, 7}; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/extract.hxx b/include/comphelper/extract.hxx index c8ab9c6e6e7b..3d47590d32be 100644 --- a/include/comphelper/extract.hxx +++ b/include/comphelper/extract.hxx @@ -16,8 +16,7 @@ * 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_COMPHELPER_EXTRACT_HXX -#define INCLUDED_COMPHELPER_EXTRACT_HXX +#pragma once #include @@ -108,6 +107,4 @@ inline bool any2bool(const css::uno::Any& rAny) } } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/graphicmimetype.hxx b/include/comphelper/graphicmimetype.hxx index 974a83fb7b6f..0ee2ca656431 100644 --- a/include/comphelper/graphicmimetype.hxx +++ b/include/comphelper/graphicmimetype.hxx @@ -7,8 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_COMPHELPER_GMH_HXX -#define INCLUDED_COMPHELPER_GMH_HXX +#pragma once #include @@ -47,6 +46,4 @@ public: }; } -#endif // INCLUDED_COMPHELPER_GMH_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/hash.hxx b/include/comphelper/hash.hxx index 7e49b7d2efec..8313ddf93466 100644 --- a/include/comphelper/hash.hxx +++ b/include/comphelper/hash.hxx @@ -7,8 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_COMPHELPER_HASH_HXX -#define INCLUDED_COMPHELPER_HASH_HXX +#pragma once #include #include @@ -128,6 +127,4 @@ public: } -#endif // INCLUDED_COMPHELPER_HASH_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/numberedcollection.hxx b/include/comphelper/numberedcollection.hxx index 346e36600add..9d6a6406bf1b 100644 --- a/include/comphelper/numberedcollection.hxx +++ b/include/comphelper/numberedcollection.hxx @@ -40,7 +40,7 @@ namespace comphelper{ /** @short defines a collection of UNO components, where every component will get its own unique number. @descr Such number will be unique at runtime only... but it supports fragmentation. - Note: This collection uses weak references only to know her components. + Note: This collection uses weak references only to know its components. So lifetime of these components must be controlled outside. @threadsafe @@ -82,7 +82,7 @@ class UNLESS_MERGELIBS_MORE(COMPHELPER_DLLPUBLIC) NumberedCollection final : /** set an outside component which uses this container and must be set as source of all broadcasted messages, exceptions. - It's holded weak only so we do not need any complex dispose sessions. + It's held weak only so we do not need any complex dispose sessions. Note: Passing NULL as parameter will be allowed. It will reset the internal member reference only. @@ -96,7 +96,7 @@ class UNLESS_MERGELIBS_MORE(COMPHELPER_DLLPUBLIC) NumberedCollection final : /** set the localized prefix to be used for untitled components. Localization has to be done outside. This container will return - those value then. There are no further checks. Its up to you to define + that value then. There are no further checks. Its up to you to define a suitable string here :-) @param sPrefix @@ -131,10 +131,10 @@ class UNLESS_MERGELIBS_MORE(COMPHELPER_DLLPUBLIC) NumberedCollection final : of this collection. (fragmentation!) If collection is full (means there is no free number) the special value INVALID_NUMBER will be returned. - @note Those method can't be called within a multithreaded environment. - Because such number won't be "reserved" for the call of these method - it can happen that two calls returns the same number (reasoned by the fact that first call - doesn't used the returned number already. + @note This method cannot be called within a multithreaded environment. + Because such number won't be "reserved" for the call of this method + it can happen that two calls return the same number (reasoned by the fact that the first call + has not used the returned number already). So the outside code has to make sure that retrieving and using of those numbers will be an atomic operation. diff --git a/include/comphelper/numbers.hxx b/include/comphelper/numbers.hxx index c69c1a5198a4..2827b425df5f 100644 --- a/include/comphelper/numbers.hxx +++ b/include/comphelper/numbers.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_NUMBERS_HXX -#define INCLUDED_COMPHELPER_NUMBERS_HXX +#pragma once #include #include @@ -52,6 +51,4 @@ namespace comphelper } // namespace comphelper -#endif // INCLUDED_COMPHELPER_NUMBERS_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/proparrhlp.hxx b/include/comphelper/proparrhlp.hxx index 9093ff579f0c..6482c7a50a76 100644 --- a/include/comphelper/proparrhlp.hxx +++ b/include/comphelper/proparrhlp.hxx @@ -76,7 +76,7 @@ protected: css::uno::Sequence< css::beans::Property >& /* [out] */ _rAggregateProps ) const = 0; - /** creates an OPropertyArrayAggregationHelper filled with properties for which's initialization + /** creates an OPropertyArrayAggregationHelper filled with properties for whose initialization fillProperties is called. getInfoService and getFirstAggregateId may be overwritten to determine the additional parameters of the OPropertyArrayAggregationHelper. */ @@ -100,7 +100,7 @@ template OPropertyArrayUsageHelper::~OPropertyArrayUsageHelper() { std::unique_lock aGuard(theMutex()); - OSL_ENSURE(s_nRefCount > 0, "OPropertyArrayUsageHelper::~OPropertyArrayUsageHelper : suspicious call : have a refcount of 0 !"); + assert(s_nRefCount > 0 && "OPropertyArrayUsageHelper::~OPropertyArrayUsageHelper : suspicious call : have a refcount of 0 !"); if (!--s_nRefCount) { delete s_pProps; @@ -111,12 +111,12 @@ OPropertyArrayUsageHelper::~OPropertyArrayUsageHelper() template ::cppu::IPropertyArrayHelper* OPropertyArrayUsageHelper::getArrayHelper() { - OSL_ENSURE(s_nRefCount, "OPropertyArrayUsageHelper::getArrayHelper : suspicious call : have a refcount of 0 !"); std::unique_lock aGuard(theMutex()); + assert(s_nRefCount && "OPropertyArrayUsageHelper::getArrayHelper : suspicious call : have a refcount of 0 !"); if (!s_pProps) { s_pProps = createArrayHelper(); - OSL_ENSURE(s_pProps, "OPropertyArrayUsageHelper::getArrayHelper : createArrayHelper returned nonsense !"); + assert(s_pProps && "OPropertyArrayUsageHelper::getArrayHelper : createArrayHelper returned nonsense !"); } return s_pProps; } diff --git a/include/comphelper/propcontainerimplhelper.hxx b/include/comphelper/propcontainerimplhelper.hxx new file mode 100644 index 000000000000..f654e49b4418 --- /dev/null +++ b/include/comphelper/propcontainerimplhelper.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include +#include + +namespace comphelper +{ +/** + Combines OPropertyImplHelper, OPropertyContainerHelper, and + OPropertyArrayUsageHelper into a single base class — the template + replacement for OPropertyContainer2. + + Derived classes just need to implement createArrayHelper() (typically + calling describeProperties + wrapping in OPropertyArrayHelper) and + call registerProperty() in their constructor. + + @tparam BaseClass Same as OPropertyImplHelper: must satisfy IsUnoImplBase. + @tparam Derived The final class (CRTP), needed by OPropertyArrayUsageHelper + for per-class static caching of the property array. + @tparam Ifc Optional additional UNO interfaces. +*/ +template +class SAL_DLLPUBLIC_TEMPLATE OPropertyContainerImplHelper + : public OPropertyImplHelper, + public OPropertyContainerHelper, + public OPropertyArrayUsageHelper +{ +protected: + cppu::IPropertyArrayHelper& getInfoHelper() override { return *this->getArrayHelper(); } + + bool convertFastPropertyValue(std::unique_lock&, css::uno::Any& rConvertedValue, + css::uno::Any& rOldValue, sal_Int32 nHandle, + const css::uno::Any& rValue) override + { + return OPropertyContainerHelper::convertFastPropertyValue(rConvertedValue, rOldValue, + nHandle, rValue); + } + + void setFastPropertyValue_NoBroadcast(std::unique_lock&, sal_Int32 nHandle, + const css::uno::Any& rValue) override + { + OPropertyContainerHelper::setFastPropertyValue(nHandle, rValue); + } + + using OPropertyImplHelper::getFastPropertyValue; + void getFastPropertyValue(std::unique_lock&, css::uno::Any& rValue, + sal_Int32 nHandle) const override + { + OPropertyContainerHelper::getFastPropertyValue(rValue, nHandle); + } +}; + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/comphelper/property.hxx b/include/comphelper/property.hxx index b9787f1308bc..1ea12016cb1f 100644 --- a/include/comphelper/property.hxx +++ b/include/comphelper/property.hxx @@ -45,7 +45,7 @@ COMPHELPER_DLLPUBLIC void RemoveProperty(css::uno::Sequence -#include -#include - -namespace com::sun::star::uno -{ -class Type; -} - -namespace comphelper -{ -/** - This class is a copy of comphelper::OPropertyContainer except that it extends comphelper::OPropertySetHelper - instead of cppu::OPropertySetHelper. - - An OPropertySetHelper implementation which is just a simple container for properties represented - by class members, usually in a derived class. -
    - A restriction of this class is that no value conversions are made on a setPropertyValue call. Though - the base class supports this with the convertFastPropertyValue method, the OPropertyContainer accepts only - values which already have the correct type, it's unable to convert, for instance, a long to a short. -*/ -class COMPHELPER_DLLPUBLIC OPropertyContainer2 : public comphelper::OPropertySetHelper, - public OPropertyContainerHelper -{ -public: - // this dtor is needed otherwise we can get a wrong delete operator - virtual ~OPropertyContainer2(); - -protected: - OPropertyContainer2(); - - /// for scripting : the types of the interfaces supported by this class - /// - /// @throws css::uno::RuntimeException - static css::uno::Sequence getBaseTypes(); - - // OPropertySetHelper overridables - virtual bool convertFastPropertyValue(std::unique_lock& rGuard, - css::uno::Any& rConvertedValue, css::uno::Any& rOldValue, - sal_Int32 nHandle, const css::uno::Any& rValue) override; - - virtual void setFastPropertyValue_NoBroadcast(std::unique_lock& rGuard, - sal_Int32 nHandle, - const css::uno::Any& rValue) override; - - using OPropertySetHelper::getFastPropertyValue; - virtual void getFastPropertyValue(std::unique_lock& rGuard, css::uno::Any& rValue, - sal_Int32 nHandle) const override; - - // disambiguate a base class method (XFastPropertySet) - using OPropertySetHelper::setFastPropertyValue; -}; - -} // namespace comphelper - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/propimplhelper.hxx b/include/comphelper/propimplhelper.hxx new file mode 100644 index 000000000000..c1deba69eef2 --- /dev/null +++ b/include/comphelper/propimplhelper.hxx @@ -0,0 +1,872 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace comphelper +{ +/// BaseClass must inherit from comphelper::UnoImplBase (provides m_aMutex, m_bDisposed). +template concept IsUnoImplBase = std::derived_from; + +namespace detail +{ +// Filter out interfaces that BaseClass already provides, to avoid duplicate +// base classes (e.g. when BaseClass inherits from XPathSettings which already +// extends XPropertySet). TODO: maybe move closer to ImplInheritanceHelper? +template struct TypeList +{ +}; + +template +TypeList operator+(TypeList, TypeList); + +template using MaybeType = std::conditional_t, TypeList<>>; + +template +using FilterNewInterfaces + = decltype((TypeList{} + ... + MaybeType, Ifc>{})); + +template cppu::ImplInheritanceHelper makeImplBase(TypeList); + +template +using MakeImplBase = decltype(makeImplBase(FilterNewInterfaces{})); + +template +using PropertyImplBase = MakeImplBase; + +/// XPropertySetInfo implementation shared by all OPropertyImplHelper instantiations. +class PropertyImplHelperInfo : public comphelper::WeakImplHelper +{ + css::uno::Sequence m_aProperties; + +public: + explicit PropertyImplHelperInfo(cppu::IPropertyArrayHelper& rHelper) + : m_aProperties(rHelper.getProperties()) + { + } + + css::uno::Sequence SAL_CALL getProperties() override + { + return m_aProperties; + } + + css::beans::Property SAL_CALL getPropertyByName(const OUString& rName) override + { + auto it = findByName(rName); + if (it == m_aProperties.end() || it->Name != rName) + throw css::beans::UnknownPropertyException(rName); + return *it; + } + + sal_Bool SAL_CALL hasPropertyByName(const OUString& rName) override + { + auto it = findByName(rName); + return it != m_aProperties.end() && it->Name == rName; + } + +private: + const css::beans::Property* findByName(const OUString& rName) const + { + return std::lower_bound( + m_aProperties.begin(), m_aProperties.end(), rName, + [](const css::beans::Property& p, const OUString& n) { return p.Name < n; }); + } +}; + +} // namespace detail + +/** + Template reimplementation of comphelper::OPropertySetHelper based on + cppu::ImplInheritanceHelper. + + Instead of requiring multiple inheritance from both a WeakImplHelper and + OPropertySetHelper (with the associated XInterface diamond and manual + queryInterface resolution), this template combines everything in a single + inheritance chain: + + @code + // Old pattern (multiple inheritance, diamond, manual QI resolution): + class MyService : public comphelper::WeakComponentImplHelper, + public comphelper::OPropertySetHelper + { + css::uno::Any SAL_CALL queryInterface(const css::uno::Type& rType) override + { + auto ret = WeakComponentImplHelper::queryInterface(rType); + if (!ret.hasValue()) + ret = OPropertySetHelper::queryInterface(rType); + return ret; + } + // Must also resolve getTypes(), acquire(), release()... + }; + + // New pattern (single chain, no diamond, all handled automatically): + class MyService : public comphelper::OPropertyImplHelper< + comphelper::WeakComponentImplHelper> + { + // queryInterface, acquire, release, getTypes all work automatically. + // XPropertySet, XMultiPropertySet, XFastPropertySet are included. + }; + @endcode + + The template adds css::beans::XPropertySet, css::beans::XMultiPropertySet + and css::beans::XFastPropertySet on top of whatever interfaces BaseClass + and Ifc... already provide. + + Derived classes must implement: + - getInfoHelper() + - convertFastPropertyValue() + - setFastPropertyValue_NoBroadcast() + - getFastPropertyValue() + + @tparam BaseClass Must inherit from comphelper::UnoImplBase (enforced + by the IsUnoImplBase concept), e.g. + comphelper::WeakComponentImplHelper<...> or + comphelper::WeakImplHelper<...>. + @tparam Ifc Optional additional UNO interfaces to implement beyond + the three property interfaces. +*/ +template +class SAL_NO_VTABLE SAL_DLLPUBLIC_TEMPLATE OPropertyImplHelper + : public detail::PropertyImplBase +{ +public: + template + explicit OPropertyImplHelper(Arg&&... arg) + : detail::PropertyImplBase(std::forward(arg)...) + { + } + + // XPropertySet + + void SAL_CALL setPropertyValue(const OUString& rPropertyName, + const css::uno::Any& aValue) override + { + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + std::unique_lock aGuard(this->m_aMutex); + setFastPropertyValueImpl(aGuard, nHandle, aValue); + } + + css::uno::Any SAL_CALL getPropertyValue(const OUString& aPropertyName) override + { + std::unique_lock aGuard(this->m_aMutex); + return getPropertyValueImpl(aGuard, aPropertyName); + } + + css::uno::Reference SAL_CALL getPropertySetInfo() override + { + return createPropertySetInfo(getInfoHelper()); + } + + void SAL_CALL addPropertyChangeListener( + const OUString& rPropertyName, + const css::uno::Reference& rxListener) override; + + void SAL_CALL removePropertyChangeListener( + const OUString& rPropertyName, + const css::uno::Reference& rxListener) override; + + void SAL_CALL addVetoableChangeListener( + const OUString& rPropertyName, + const css::uno::Reference& rxListener) override; + + void SAL_CALL removeVetoableChangeListener( + const OUString& rPropertyName, + const css::uno::Reference& rxListener) override; + + // XFastPropertySet + + void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, + const css::uno::Any& rValue) override final + { + std::unique_lock aGuard(this->m_aMutex); + setFastPropertyValueImpl(aGuard, nHandle, rValue); + } + + css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override final; + + // XMultiPropertySet + + void SAL_CALL setPropertyValues(const css::uno::Sequence& PropertyNames, + const css::uno::Sequence& Values) override; + + css::uno::Sequence SAL_CALL + getPropertyValues(const css::uno::Sequence& PropertyNames) override final; + + void SAL_CALL addPropertiesChangeListener( + const css::uno::Sequence&, + const css::uno::Reference& Listener) override final + { + std::unique_lock aGuard(this->m_aMutex); + m_aPropertiesChangeListeners.addInterface(aGuard, Listener); + } + + void SAL_CALL removePropertiesChangeListener( + const css::uno::Reference& Listener) override final + { + std::unique_lock aGuard(this->m_aMutex); + m_aPropertiesChangeListeners.removeInterface(aGuard, Listener); + } + + void SAL_CALL firePropertiesChangeEvent( + const css::uno::Sequence& PropertyNames, + const css::uno::Reference& Listener) override final; + + // Utilities + + static css::uno::Reference + createPropertySetInfo(cppu::IPropertyArrayHelper& rProperties) + { + return new detail::PropertyImplHelperInfo(rProperties); + } + +protected: + /// Call from your disposing() override to clear all property listeners. + void disposePropertySetListeners(std::unique_lock& rGuard) + { + // prevent double-destruction: aEvt.Source holds a ref to this; if we're called from the + // destructor, when it's released, ref count drops to 0, which would delete this again + osl_atomic_increment(&this->m_refCount); + { + css::lang::EventObject aEvt; + aEvt.Source = static_cast(this); + m_aBoundLC.disposeAndClear(rGuard, aEvt); + m_aVetoableLC.disposeAndClear(rGuard, aEvt); + } + osl_atomic_decrement(&this->m_refCount); + } + + /// Override this if you need to do something special during setFastPropertyValue. + virtual void setFastPropertyValueImpl(std::unique_lock& rGuard, sal_Int32 nHandle, + const css::uno::Any& rValue); + + css::uno::Any getPropertyValueImpl(std::unique_lock& rGuard, + const OUString& aPropertyName) + { + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + sal_Int32 nHandle = rPH.getHandleByName(aPropertyName); + if (nHandle == -1) + throw css::beans::UnknownPropertyException(aPropertyName); + css::uno::Any aAny; + getFastPropertyValue(rGuard, aAny, nHandle); + return aAny; + } + + void fire(std::unique_lock& rGuard, const sal_Int32* pnHandles, + const css::uno::Any* pNewValues, const css::uno::Any* pOldValues, sal_Int32 nCount, + bool bVetoable); + + void setFastPropertyValues(std::unique_lock& rGuard, sal_Int32 nSeqLen, + sal_Int32* pHandles, const css::uno::Any* pValues, + sal_Int32 nHitCount); + + /// Return the property name-to-handle mapping. + virtual cppu::IPropertyArrayHelper& getInfoHelper() = 0; + + /// Convert and validate a property value. + virtual bool convertFastPropertyValue(std::unique_lock& rGuard, + css::uno::Any& rConvertedValue, css::uno::Any& rOldValue, + sal_Int32 nHandle, const css::uno::Any& rValue) + = 0; + + /// Set a property without broadcasting. + virtual void setFastPropertyValue_NoBroadcast(std::unique_lock& rGuard, + sal_Int32 nHandle, const css::uno::Any& rValue) + = 0; + + /// Get a property value by handle. + virtual void getFastPropertyValue(std::unique_lock& rGuard, css::uno::Any& rValue, + sal_Int32 nHandle) const = 0; + + /** Set a dependent property from within setFastPropertyValue_NoBroadcast. + The change event is deferred and fired together with the triggering + property's event. */ + void setDependentFastPropertyValue(std::unique_lock& rGuard, sal_Int32 nHandle, + const css::uno::Any& rValue); + + /// Enable/disable ignoring RuntimeExceptions during listener notification. + void setIgnoreRuntimeExceptionsWhileFiring(bool b) + { + m_bIgnoreRuntimeExceptionsWhileFiring = b; + } + +private: + template void callNoBroadcast(Func&& fn); + + void impl_fireAll(std::unique_lock& rGuard, sal_Int32* pHandles, + const css::uno::Any* pNewValues, const css::uno::Any* pOldValues, + sal_Int32 nCount); + + template + void addListener(const OUString& rPropertyName, + const css::uno::Reference& rxListener, sal_Int16 nRequiredAttribute, + OMultiTypeInterfaceContainerHelperVar4& rByHandleLC, + comphelper::OInterfaceContainerHelper4& rAllLC); + + template + void removeListener(const OUString& rPropertyName, + const css::uno::Reference& rxListener, + OMultiTypeInterfaceContainerHelperVar4& rByHandleLC, + comphelper::OInterfaceContainerHelper4& rAllLC); + + template + void fireListeners(std::unique_lock& rGuard, + comphelper::OInterfaceContainerHelper4* pListeners, + const css::beans::PropertyChangeEvent& rChangeEvent); + + OMultiTypeInterfaceContainerHelperVar4 + m_aBoundLC; + OMultiTypeInterfaceContainerHelperVar4 + m_aVetoableLC; + comphelper::OInterfaceContainerHelper4 + m_aPropertyChangeListeners; + comphelper::OInterfaceContainerHelper4 + m_aPropertiesChangeListeners; + comphelper::OInterfaceContainerHelper4 + m_aVetoableChangeListeners; + std::vector m_aPendingHandles; + std::vector m_aPendingNewValues; + std::vector m_aPendingOldValues; + bool m_bIgnoreRuntimeExceptionsWhileFiring = false; +}; + +// XPropertySet + +template +void OPropertyImplHelper::addPropertyChangeListener( + const OUString& rPropertyName, + const css::uno::Reference& rxListener) +{ + addListener(rPropertyName, rxListener, css::beans::PropertyAttribute::BOUND, m_aBoundLC, + m_aPropertyChangeListeners); +} + +template +void OPropertyImplHelper::removePropertyChangeListener( + const OUString& rPropertyName, + const css::uno::Reference& rxListener) +{ + removeListener(rPropertyName, rxListener, m_aBoundLC, m_aPropertyChangeListeners); +} + +template +void OPropertyImplHelper::addVetoableChangeListener( + const OUString& rPropertyName, + const css::uno::Reference& rxListener) +{ + addListener(rPropertyName, rxListener, css::beans::PropertyAttribute::CONSTRAINED, + m_aVetoableLC, m_aVetoableChangeListeners); +} + +template +void OPropertyImplHelper::removeVetoableChangeListener( + const OUString& rPropertyName, + const css::uno::Reference& rxListener) +{ + removeListener(rPropertyName, rxListener, m_aVetoableLC, m_aVetoableChangeListeners); +} + +template +template +void OPropertyImplHelper::addListener( + const OUString& rPropertyName, const css::uno::Reference& rxListener, + sal_Int16 nRequiredAttribute, + OMultiTypeInterfaceContainerHelperVar4& rByHandleLC, + comphelper::OInterfaceContainerHelper4& rAllLC) +{ + std::unique_lock aGuard(this->m_aMutex); + assert(!this->m_bDisposed); + if (this->m_bDisposed) + return; + + if (!rPropertyName.isEmpty()) + { + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + throw css::beans::UnknownPropertyException(rPropertyName); + + sal_Int16 nAttributes; + rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle); + if (!(nAttributes & nRequiredAttribute)) + { + SAL_WARN("comphelper", "addListener: property lacks required attribute"); + return; + } + rByHandleLC.addInterface(aGuard, nHandle, rxListener); + } + else + rAllLC.addInterface(aGuard, rxListener); +} + +template +template +void OPropertyImplHelper::removeListener( + const OUString& rPropertyName, const css::uno::Reference& rxListener, + OMultiTypeInterfaceContainerHelperVar4& rByHandleLC, + comphelper::OInterfaceContainerHelper4& rAllLC) +{ + std::unique_lock aGuard(this->m_aMutex); + assert(!this->m_bDisposed); + if (this->m_bDisposed) + return; + + if (!rPropertyName.isEmpty()) + { + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + throw css::beans::UnknownPropertyException(rPropertyName); + rByHandleLC.removeInterface(aGuard, nHandle, rxListener); + } + else + rAllLC.removeInterface(aGuard, rxListener); +} + +template +template +void OPropertyImplHelper::callNoBroadcast(Func&& fn) +{ + try + { + fn(); + } + catch (const css::beans::UnknownPropertyException&) + { + throw; + } + catch (const css::beans::PropertyVetoException&) + { + throw; + } + catch (const css::lang::IllegalArgumentException&) + { + throw; + } + catch (const css::lang::WrappedTargetException&) + { + throw; + } + catch (const css::uno::RuntimeException&) + { + throw; + } + catch (const css::uno::Exception&) + { + css::lang::WrappedTargetException aWrap; + aWrap.TargetException = cppu::getCaughtException(); + aWrap.Context = static_cast(this); + throw aWrap; + } +} + +// XFastPropertySet + +template +css::uno::Any SAL_CALL +OPropertyImplHelper::getFastPropertyValue(sal_Int32 nHandle) +{ + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + if (!rPH.fillPropertyMembersByHandle(nullptr, nullptr, nHandle)) + throw css::beans::UnknownPropertyException(OUString::number(nHandle)); + + css::uno::Any aRet; + std::unique_lock aGuard(this->m_aMutex); + getFastPropertyValue(aGuard, aRet, nHandle); + return aRet; +} + +template +void OPropertyImplHelper::setFastPropertyValueImpl( + std::unique_lock& rGuard, sal_Int32 nHandle, const css::uno::Any& rValue) +{ + assert(!this->m_bDisposed); + + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + sal_Int16 nAttributes; + if (!rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle)) + throw css::beans::UnknownPropertyException(OUString::number(nHandle)); + if (nAttributes & css::beans::PropertyAttribute::READONLY) + throw css::beans::PropertyVetoException(); + + css::uno::Any aConvertedVal; + css::uno::Any aOldVal; + + bool bChanged = convertFastPropertyValue(rGuard, aConvertedVal, aOldVal, nHandle, rValue); + if (!bChanged) + return; + + if (nAttributes & css::beans::PropertyAttribute::CONSTRAINED) + fire(rGuard, &nHandle, &rValue, &aOldVal, 1, true); + + callNoBroadcast([&] { setFastPropertyValue_NoBroadcast(rGuard, nHandle, aConvertedVal); }); + + impl_fireAll(rGuard, &nHandle, &rValue, &aOldVal, 1); +} + +// XMultiPropertySet + +template +void OPropertyImplHelper::setPropertyValues( + const css::uno::Sequence& rPropertyNames, + const css::uno::Sequence& rValues) +{ + sal_Int32 nSeqLen = rPropertyNames.getLength(); + if (nSeqLen != rValues.getLength()) + throw css::lang::IllegalArgumentException(u"lengths do not match"_ustr, + static_cast(this), -1); + auto pHandles = std::make_unique(nSeqLen); + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + sal_Int32 nHitCount = rPH.fillHandles(pHandles.get(), rPropertyNames); + if (nHitCount == 0) + return; + std::unique_lock aGuard(this->m_aMutex); + setFastPropertyValues(aGuard, nSeqLen, pHandles.get(), rValues.getConstArray(), nHitCount); +} + +template +css::uno::Sequence OPropertyImplHelper::getPropertyValues( + const css::uno::Sequence& rPropertyNames) +{ + sal_Int32 nSeqLen = rPropertyNames.getLength(); + auto pHandles = std::make_unique(nSeqLen); + css::uno::Sequence aValues(nSeqLen); + + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + rPH.fillHandles(pHandles.get(), rPropertyNames); + + css::uno::Any* pValues = aValues.getArray(); + std::unique_lock aGuard(this->m_aMutex); + for (sal_Int32 i = 0; i < nSeqLen; i++) + getFastPropertyValue(aGuard, pValues[i], pHandles[i]); + + return aValues; +} + +template +void OPropertyImplHelper::firePropertiesChangeEvent( + const css::uno::Sequence& rPropertyNames, + const css::uno::Reference& rListener) +{ + sal_Int32 nLen = rPropertyNames.getLength(); + auto pHandles = std::make_unique(nLen); + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + rPH.fillHandles(pHandles.get(), rPropertyNames); + + sal_Int32 nFireLen + = std::count_if(pHandles.get(), pHandles.get() + nLen, [](sal_Int32 h) { return h != -1; }); + if (nFireLen) + { + css::uno::Sequence aChanges(nFireLen); + css::beans::PropertyChangeEvent* pChanges = aChanges.getArray(); + std::unique_lock aGuard(this->m_aMutex); + css::uno::Reference xSource( + static_cast(this), css::uno::UNO_QUERY); + sal_Int32 nFirePos = 0; + for (sal_Int32 i = 0; i < nLen; i++) + { + if (pHandles[i] != -1) + { + pChanges[nFirePos].Source = xSource; + pChanges[nFirePos].PropertyName = rPropertyNames[i]; + pChanges[nFirePos].PropertyHandle = pHandles[i]; + getFastPropertyValue(aGuard, pChanges[nFirePos].OldValue, pHandles[i]); + pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue; + nFirePos++; + } + } + rListener->propertiesChange(aChanges); + } +} + +template +void OPropertyImplHelper::setDependentFastPropertyValue( + std::unique_lock& rGuard, sal_Int32 nHandle, const css::uno::Any& rValue) +{ + sal_Int16 nAttributes(0); + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + if (!rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle)) + throw css::beans::UnknownPropertyException(OUString::number(nHandle)); + + css::uno::Any aConverted, aOld; + bool bChanged = convertFastPropertyValue(rGuard, aConverted, aOld, nHandle, rValue); + if (!bChanged) + return; + + assert(!(nAttributes & css::beans::PropertyAttribute::CONSTRAINED)); + + callNoBroadcast([&] { setFastPropertyValue_NoBroadcast(rGuard, nHandle, aConverted); }); + + m_aPendingHandles.push_back(nHandle); + m_aPendingNewValues.push_back(aConverted); + m_aPendingOldValues.push_back(aOld); +} + +template +void OPropertyImplHelper::setFastPropertyValues( + std::unique_lock& rGuard, sal_Int32 nSeqLen, sal_Int32* pHandles, + const css::uno::Any* pValues, sal_Int32 nHitCount) +{ + assert(!this->m_bDisposed); + + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + + auto pConvertedValues = std::make_unique(nHitCount); + auto pOldValues = std::make_unique(nHitCount); + sal_Int32 n = 0; + + for (sal_Int32 i = 0; i < nSeqLen; i++) + { + if (pHandles[i] != -1) + { + sal_Int16 nAttributes; + rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, pHandles[i]); + if (nAttributes & css::beans::PropertyAttribute::READONLY) + throw css::beans::PropertyVetoException(); + if (convertFastPropertyValue(rGuard, pConvertedValues[n], pOldValues[n], pHandles[i], + pValues[i])) + { + pHandles[n] = pHandles[i]; + n++; + } + } + } + + fire(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n, true); + + for (sal_Int32 i = 0; i < n; i++) + setFastPropertyValue_NoBroadcast(rGuard, pHandles[i], pConvertedValues[i]); + + impl_fireAll(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n); +} + +template +void OPropertyImplHelper::impl_fireAll(std::unique_lock& rGuard, + sal_Int32* pHandles, + const css::uno::Any* pNewValues, + const css::uno::Any* pOldValues, + sal_Int32 nCount) +{ + if (m_aPendingHandles.empty()) + { + fire(rGuard, pHandles, pNewValues, pOldValues, nCount, false); + return; + } + + assert(m_aPendingHandles.size() == m_aPendingNewValues.size() + && m_aPendingHandles.size() == m_aPendingOldValues.size()); + + auto allHandles = std::exchange(m_aPendingHandles, {}); + +#if defined __GNUC__ && (__GNUC__ == 13) && !defined __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + allHandles.insert(allHandles.end(), pHandles, pHandles + nCount); +#if defined __GNUC__ && (__GNUC__ == 13) && !defined __clang__ +#pragma GCC diagnostic pop +#endif + + auto allNewValues = std::exchange(m_aPendingNewValues, {}); + +#if defined __GNUC__ && (__GNUC__ == 13) && !defined __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + allNewValues.insert(allNewValues.end(), pNewValues, pNewValues + nCount); +#if defined __GNUC__ && (__GNUC__ == 13) && !defined __clang__ +#pragma GCC diagnostic pop +#endif + + auto allOldValues = std::exchange(m_aPendingOldValues, {}); + +#if defined __GNUC__ && (__GNUC__ == 13) && !defined __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + allOldValues.insert(allOldValues.end(), pOldValues, pOldValues + nCount); +#if defined __GNUC__ && (__GNUC__ == 13) && !defined __clang__ +#pragma GCC diagnostic pop +#endif + + fire(rGuard, allHandles.data(), allNewValues.data(), allOldValues.data(), allHandles.size(), + false); +} + +template +void OPropertyImplHelper::fire(std::unique_lock& rGuard, + const sal_Int32* pnHandles, + const css::uno::Any* pNewValues, + const css::uno::Any* pOldValues, + sal_Int32 nHandles, bool bVetoable) +{ + if (!nHandles) + return; + + css::uno::Sequence aEvts(nHandles); + css::beans::PropertyChangeEvent* pEvts = aEvts.getArray(); + css::uno::Reference xSource(static_cast(this), + css::uno::UNO_QUERY); + + cppu::IPropertyArrayHelper& rPH = getInfoHelper(); + sal_Int32 nChangesLen = 0; + for (sal_Int32 i = 0; i < nHandles; i++) + { + sal_Int16 nAttributes; + OUString aPropName; + rPH.fillPropertyMembersByHandle(&aPropName, &nAttributes, pnHandles[i]); + + if ((bVetoable && (nAttributes & css::beans::PropertyAttribute::CONSTRAINED)) + || (!bVetoable && (nAttributes & css::beans::PropertyAttribute::BOUND))) + { + pEvts[nChangesLen].Source = xSource; + pEvts[nChangesLen].PropertyName = aPropName; + pEvts[nChangesLen].PropertyHandle = pnHandles[i]; + pEvts[nChangesLen].OldValue = pOldValues[i]; + pEvts[nChangesLen].NewValue = pNewValues[i]; + nChangesLen++; + } + } + + bool bIgnoreRuntimeExceptionsWhileFiring = m_bIgnoreRuntimeExceptionsWhileFiring; + + for (sal_Int32 i = 0; i < nChangesLen; i++) + { + if (bVetoable) + { + fireListeners(rGuard, m_aVetoableLC.getContainer(rGuard, aEvts[i].PropertyHandle), + aEvts[i]); + fireListeners(rGuard, &m_aVetoableChangeListeners, aEvts[i]); + } + else + { + fireListeners(rGuard, m_aBoundLC.getContainer(rGuard, aEvts[i].PropertyHandle), + aEvts[i]); + fireListeners(rGuard, &m_aPropertyChangeListeners, aEvts[i]); + } + } + + aEvts.realloc(nChangesLen); + + if (bVetoable) + return; + + // TODO: here is a bug — unbound properties are also fired + if (!m_aPropertiesChangeListeners.getLength(rGuard)) + return; + + OInterfaceIteratorHelper4 aIt(rGuard, m_aPropertiesChangeListeners); + rGuard.unlock(); + while (aIt.hasMoreElements()) + { + css::beans::XPropertiesChangeListener* pL = aIt.next().get(); + try + { + try + { + pL->propertiesChange(aEvts); + } + catch (css::lang::DisposedException& exc) + { + SAL_WARN_IF(!exc.Context.is(), "comphelper", "DisposedException without Context!"); + if (exc.Context == pL) + { + rGuard.lock(); + aIt.remove(rGuard); + rGuard.unlock(); + } + else + throw; + } + } + catch (css::uno::RuntimeException& exc) + { + SAL_INFO("comphelper", "caught RuntimeException while firing listeners: " << exc); + if (!bIgnoreRuntimeExceptionsWhileFiring) + throw; + } + } + rGuard.lock(); +} + +template +template +void OPropertyImplHelper::fireListeners( + std::unique_lock& rGuard, + comphelper::OInterfaceContainerHelper4* pListeners, + const css::beans::PropertyChangeEvent& rChangeEvent) +{ + if (!pListeners || !pListeners->getLength(rGuard)) + return; + OInterfaceIteratorHelper4 aIt(rGuard, *pListeners); + rGuard.unlock(); + while (aIt.hasMoreElements()) + { + ListenerT* pL = aIt.next().get(); + try + { + try + { + if constexpr (std::is_same_v) + pL->vetoableChange(rChangeEvent); + else + pL->propertyChange(rChangeEvent); + } + catch (css::lang::DisposedException& exc) + { + SAL_WARN_IF(!exc.Context.is(), "comphelper", "DisposedException without Context!"); + if (exc.Context == pL) + { + rGuard.lock(); + aIt.remove(rGuard); + rGuard.unlock(); + } + else + throw; + } + } + catch (css::uno::RuntimeException& exc) + { + SAL_INFO("comphelper", "caught RuntimeException while firing listeners: " << exc); + if (!m_bIgnoreRuntimeExceptionsWhileFiring) + throw; + } + } + rGuard.lock(); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/comphelper/scriptbrowse.hxx b/include/comphelper/scriptbrowse.hxx new file mode 100644 index 000000000000..02c4366bb937 --- /dev/null +++ b/include/comphelper/scriptbrowse.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +#include + +#include + +namespace com::sun::star::script::browse +{ +class XBrowseNode; +} + +namespace comphelper::scriptbrowse +{ +COMPHELPER_DLLPUBLIC bool +isEditable(const css::uno::Reference& xNode); +COMPHELPER_DLLPUBLIC bool +editNode(const css::uno::Reference& xNode); + +COMPHELPER_DLLPUBLIC bool +isDeletable(const css::uno::Reference& xNode); +COMPHELPER_DLLPUBLIC bool +deleteNode(const css::uno::Reference& xNode); + +COMPHELPER_DLLPUBLIC bool +isCreatable(const css::uno::Reference& xNode); +COMPHELPER_DLLPUBLIC css::uno::Reference +createNode(const css::uno::Reference& xNode, + const OUString& sName); + +COMPHELPER_DLLPUBLIC bool +isRenamable(const css::uno::Reference& xNode); +COMPHELPER_DLLPUBLIC css::uno::Reference +renameNode(const css::uno::Reference& xNode, + const OUString& sName); + +COMPHELPER_DLLPUBLIC std::vector> +getChildNodes(const css::uno::Reference& xNode); +COMPHELPER_DLLPUBLIC void +sortNodes(std::vector>& aNodes); +COMPHELPER_DLLPUBLIC std::vector> +getSortedChildNodes(const css::uno::Reference& xNode); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/comphelper/servicehelper.hxx b/include/comphelper/servicehelper.hxx index 03e7a322c340..2c81e70eaa09 100644 --- a/include/comphelper/servicehelper.hxx +++ b/include/comphelper/servicehelper.hxx @@ -26,7 +26,7 @@ namespace comphelper { - // Class incapsulating UIDs used as e.g. tunnel IDs for css::lang::XUnoTunnel, + // Class encapsulating UIDs used as e.g. tunnel IDs for css::lang::XUnoTunnel, // or implementation IDs for css::lang::XTypeProvider class UnoIdInit { @@ -97,7 +97,7 @@ namespace comphelper { } -/** the UNO3_GETIMPLEMENTATION_* macros implement a static helper function +/** the UNO3_GETIMPLEMENTATION_* macros implement a static helper function that gives access to your implementation for a given interface reference, if possible. diff --git a/include/comphelper/threadpool.hxx b/include/comphelper/threadpool.hxx index c5cc92944da9..e5483d919b0a 100644 --- a/include/comphelper/threadpool.hxx +++ b/include/comphelper/threadpool.hxx @@ -68,7 +68,7 @@ public: @param bJoin - if set call joinThreadsIfIdle() at the end */ void waitUntilDone(const std::shared_ptr&, bool bJoin = -#if defined EMSCRIPTEN +#if defined __EMSCRIPTEN__ false #else true diff --git a/include/comphelper/traceevent.hxx b/include/comphelper/traceevent.hxx index 85d403797bc1..b98c8c1d1caf 100644 --- a/include/comphelper/traceevent.hxx +++ b/include/comphelper/traceevent.hxx @@ -101,7 +101,6 @@ public: static void startRecording(); static void stopRecording(); - static void setBufferSizeAndCallback(std::size_t bufferSize, void (*bufferFullCallback)()); static std::vector getEventVectorAndClear(); diff --git a/include/comphelper/unique_unlock.hxx b/include/comphelper/unique_unlock.hxx new file mode 100644 index 000000000000..c8cb06728997 --- /dev/null +++ b/include/comphelper/unique_unlock.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include + +namespace comphelper +{ +/// RAII guard: unlocks a unique_lock on construction, relocks on destruction. +template class unique_unlock +{ + std::unique_lock& m_rLock; + +public: + explicit unique_unlock(std::unique_lock& rLock) + : m_rLock(rLock) + { + assert(m_rLock.owns_lock()); + if (m_rLock.owns_lock()) + m_rLock.unlock(); + } + ~unique_unlock() + { + if (!m_rLock.owns_lock()) + m_rLock.lock(); + } + unique_unlock(const unique_unlock&) = delete; + unique_unlock& operator=(const unique_unlock&) = delete; +}; +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/comphelper/xmlsechelper.hxx b/include/comphelper/xmlsechelper.hxx index 7ae26c92c666..8ba04aeed472 100644 --- a/include/comphelper/xmlsechelper.hxx +++ b/include/comphelper/xmlsechelper.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_XMLSECHELPER_HXX -#define INCLUDED_COMPHELPER_XMLSECHELPER_HXX +#pragma once #include #include @@ -66,5 +65,4 @@ COMPHELPER_DLLPUBLIC css::uno::Reference FindCertIn const OUString& rSHA1Thumbprint); } -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/xmltools.hxx b/include/comphelper/xmltools.hxx index 9ef64b17db5e..40a8c1208b1a 100644 --- a/include/comphelper/xmltools.hxx +++ b/include/comphelper/xmltools.hxx @@ -7,8 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_COMPHELPER_XMLTOOLS_HXX -#define INCLUDED_COMPHELPER_XMLTOOLS_HXX +#pragma once #include #include @@ -19,6 +18,4 @@ namespace comphelper::xml COMPHELPER_DLLPUBLIC OString generateGUIDString(); } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/connectivity/dbtools.hxx b/include/connectivity/dbtools.hxx index b06ffe74a0a7..a86f43046b66 100644 --- a/include/connectivity/dbtools.hxx +++ b/include/connectivity/dbtools.hxx @@ -93,13 +93,13 @@ namespace dbtools // date conversion - // calculates the default numberformat for a given datatype and a give language + // calculates the default numberformat for a given datatype and a given language OOO_DLLPUBLIC_DBTOOLS sal_Int32 getDefaultNumberFormat(const css::uno::Reference< css::beans::XPropertySet >& _xColumn, const css::uno::Reference< css::util::XNumberFormatTypes >& _xTypes, const css::lang::Locale& _rLocale); - // calculates the default numberformat for a given datatype and a give language + // calculates the default numberformat for a given datatype and a given language // @param _nDataType @see com.sun.star.sdbc.DataType // @param _nScale can be zero OOO_DLLPUBLIC_DBTOOLS @@ -241,7 +241,7 @@ namespace dbtools Your fields live as long as this component lives.
    Additionally, you are encouraged to dispose this component as soon as you don't need the fields anymore. - It depends on the connection's implementation if this is necessary, but the is no guarantee, so to + It depends on the connection's implementation if this is necessary, but there is no guarantee, so to be on the safe side with respect to resource leaks, you should dispose the component. @param _pErrorInfo @@ -547,7 +547,7 @@ namespace dbtools const css::uno::Reference< css::uno::XComponentContext>& _rxContext); /** implements XRowUpdate::updateObject -

    The object which is to be set is analyzed, and in case it is a simlpe scalar type for which there +

    The object which is to be set is analyzed, and in case it is a simple scalar type for which there is another updateXXX method, this other method is used.

    @param _rxUpdatedObject the interface to forward all updateXXX calls to (except updateObject) @@ -610,7 +610,7 @@ namespace dbtools /** implements XParameters::setObject -

    The object which is to be set is analyzed, and in case it is a simlpe scalar type for which there +

    The object which is to be set is analyzed, and in case it is a simple scalar type for which there is another setXXX method, this other method is used.

    @param _rxParameters the interface to forward all setXXX calls to (except setObject) @@ -842,33 +842,33 @@ namespace dbase FoxProMemo = 0xF5 }; - /** decode a DBase file's codepage byte to a RTL charset - @param _out_nCharset - in case of success, the decoded RTL charset is written there. + /** decode a DBase file's codepage byte to a RTL encoding + @param _out_nEncoding + in case of success, the decoded RTL encoding is written there. else, this is not written to. @param nType the file's type byte @param nCodepage the file's codepage byte @return - true if a RTL charset was successfully decoded and written to _out_nCharset - false if nothing was written to _out_nCharset + true if a RTL charset was successfully decoded and written to _out_nEncoding + false if nothing was written to _out_nEncoding */ - OOO_DLLPUBLIC_DBTOOLS bool dbfDecodeCharset(rtl_TextEncoding &_out_nCharset, sal_uInt8 nType, sal_uInt8 nCodepage); + OOO_DLLPUBLIC_DBTOOLS bool dbfDecodeEncoding(rtl_TextEncoding &_out_nCharset, sal_uInt8 nType, sal_uInt8 nCodepage); - /** decode a DBase file's codepage byte to a RTL charset - @param _out_nCharset - in case of success, the decoded RTL charset is written there. + /** decode a DBase file's codepage byte to a RTL encoding + @param _out_nEncoding + in case of success, the decoded RTL encoding is written there. else, this is not written to. @param dbf_Stream pointer to a SvStream encapsulating the DBase file. - The stream will be rewinded and read from. + The stream will be rewound and read from. No guarantee is made on its position afterwards. Caller must reposition it itself. @return - true if a RTL charset was successfully decoded and written to _out_nCharset - false if nothing was written to _out_nCharset + true if a RTL encoding was successfully decoded and written to _out_nEncoding + false if nothing was written to _out_nEncoding */ - OOO_DLLPUBLIC_DBTOOLS bool dbfReadCharset(rtl_TextEncoding &nCharSet, SvStream* dbf_Stream); + OOO_DLLPUBLIC_DBTOOLS bool dbfReadEncoding(rtl_TextEncoding &nCharSet, SvStream* dbf_Stream); } // namespace connectivity::dbase } // namespace connectivity diff --git a/include/cppuhelper/interfacecontainer.h b/include/cppuhelper/interfacecontainer.h index d901b2db3ccc..9551094f9ce6 100644 --- a/include/cppuhelper/interfacecontainer.h +++ b/include/cppuhelper/interfacecontainer.h @@ -75,12 +75,12 @@ public: Create an iterator over the elements of the container. The iterator copies the elements of the container. A change to the container during the lifetime of an iterator is allowed and does not - affect the iterator-instance. The iterator and the container take cares - themself for concurrent access, no additional guarding is necessary. + affect the iterator-instance. The iterator and the container take care + themselves for concurrent access, no additional guarding is necessary. - Remark: The copy is on demand. The iterator copy the elements only if the container - change the contents. It is not allowed to destroy the container as long - as an iterator exist. + Remark: The copy is on demand. The iterator copies the elements only if the container + changes the contents. It is not allowed to destroy the container as long + as an iterator exists. @param rCont the container of the elements. */ @@ -124,7 +124,7 @@ private: /** A container of interfaces. To access the elements use an iterator. - This implementation is thread save. + This implementation is thread safe. @see OInterfaceIteratorHelper */ @@ -191,7 +191,7 @@ public: */ sal_Int32 SAL_CALL removeInterface( const css::uno::Reference< css::uno::XInterface > & rxIFace ); /** - Call disposing on all object in the container that + Call disposing on all objects in the container that support XEventListener. Then clear the container. */ void SAL_CALL disposeAndClear( const css::lang::EventObject & rEvt ); @@ -258,7 +258,7 @@ friend class OInterfaceIteratorHelper; /* Duplicate content of the container and release the old one without destroying. - The mutex must be locked and the memberbInUse must be true. + The mutex must be locked and the member bInUse must be true. */ void copyAndResetInUse(); @@ -587,7 +587,7 @@ public: const css::uno::Reference< css::uno::XInterface > & rxIFace ); /** - Call disposing on all object in the container that + Call disposing on all objects in the container that support XEventListener. Then clear the container. */ void SAL_CALL disposeAndClear( const css::lang::EventObject & rEvt ); diff --git a/include/cppuhelper/proptypehlp.h b/include/cppuhelper/proptypehlp.h index 348e45afbc15..35f999d7859f 100644 --- a/include/cppuhelper/proptypehlp.h +++ b/include/cppuhelper/proptypehlp.h @@ -32,7 +32,7 @@ namespace cppu { /** Converts the value stored in an any to a concrete C++ type. The function does the same as the operator >>= () at the Any class, except that it throws an IllegalArgumentException in case of - failures (the value cannot be extracted without data loss ) + failures (the value cannot be extracted without data loss) @exception css::lang::IllegalArgumentException when the type could not be converted. */ diff --git a/include/docmodel/color/ComplexColor.hxx b/include/docmodel/color/ComplexColor.hxx index 456ca99062c0..6990136d9f26 100644 --- a/include/docmodel/color/ComplexColor.hxx +++ b/include/docmodel/color/ComplexColor.hxx @@ -159,8 +159,6 @@ public: void setCRGB(sal_Int32 nR, sal_Int32 nG, sal_Int32 nB); - void setRGB(double r, double g, double b); - void getRGB(double& r, double& g, double& b); Color getRGB() const; @@ -173,8 +171,6 @@ public: void setSystemColor(SystemColorType eSystemColorType, sal_Int32 nRGB); - bool isOpaque() const; - bool isTransparent() const; void setThemePlaceholder() { meType = ColorType::Placeholder; } diff --git a/include/docmodel/color/ComplexColorJSON.hxx b/include/docmodel/color/ComplexColorJSON.hxx deleted file mode 100644 index b35d938f007c..000000000000 --- a/include/docmodel/color/ComplexColorJSON.hxx +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- 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/. - * - */ - -#pragma once - -#include -#include - -namespace tools -{ -class JsonWriter; -} - -namespace model::color -{ -DOCMODEL_DLLPUBLIC OString convertToJSON(model::ComplexColor const& rComplexColor); -DOCMODEL_DLLPUBLIC void convertToJSONTree(tools::JsonWriter& rTree, - model::ComplexColor const& rComplexColor); -DOCMODEL_DLLPUBLIC bool convertFromJSON(OString const& rJsonString, - model::ComplexColor& rComplexColor); - -} // end of namespace model - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/docmodel/theme/ColorSet.hxx b/include/docmodel/theme/ColorSet.hxx index 5bad82633c78..8581ad775daf 100644 --- a/include/docmodel/theme/ColorSet.hxx +++ b/include/docmodel/theme/ColorSet.hxx @@ -37,6 +37,12 @@ public: Color resolveColor(model::ComplexColor const& rComplexColor) const; + /// Resolve a themed ComplexColor by applying LumMod and LumOff together + /// in a single HSL round-trip. Use this instead of resolveColor() for + /// OOXML-originated colors, where the two transforms must be combined + /// to produce correct results. + Color resolveOOXMLColor(model::ComplexColor const& rComplexColor) const; + Color getColor(model::ThemeColorType eType) const; void dumpAsXml(xmlTextWriterPtr pWriter) const; diff --git a/include/docmodel/uno/UnoChartColorStyle.hxx b/include/docmodel/uno/UnoChartColorStyle.hxx index 7b2201716a57..07be2082b55a 100644 --- a/include/docmodel/uno/UnoChartColorStyle.hxx +++ b/include/docmodel/uno/UnoChartColorStyle.hxx @@ -26,18 +26,11 @@ private: public: UnoChartColorStyle() = default; - UnoChartColorStyle(model::ColorStyleSet const& rStyle) - : maColorStyle(rStyle) - { - } - model::ColorStyleSet& getChartColorStyle() { return maColorStyle; } }; namespace model::style { -DOCMODEL_DLLPUBLIC css::uno::Reference -createXChartColorStyle(model::ColorStyleSet const& rColorStyle); DOCMODEL_DLLPUBLIC model::ColorStyleSet* getFromXChartColorStyle(css::uno::Reference const& rxColorStyle); } diff --git a/include/docmodel/uno/UnoChartStyle.hxx b/include/docmodel/uno/UnoChartStyle.hxx index 5686bd5ac2f2..b3db5e4bcc7b 100644 --- a/include/docmodel/uno/UnoChartStyle.hxx +++ b/include/docmodel/uno/UnoChartStyle.hxx @@ -31,11 +31,6 @@ private: public: UnoChartStyle() = default; - UnoChartStyle(model::StyleSet const& rStyle) - : maStyle(rStyle) - { - } - model::StyleSet& getChartStyle() { return maStyle; } // XChartStyle @@ -43,8 +38,6 @@ public: namespace model::style { -DOCMODEL_DLLPUBLIC css::uno::Reference -createXChartStyle(model::StyleSet const& rStyle); DOCMODEL_DLLPUBLIC model::StyleSet* getFromXChartStyle(css::uno::Reference const& rxStyle); } diff --git a/include/docmodel/uno/UnoComplexColor.hxx b/include/docmodel/uno/UnoComplexColor.hxx index 500c1c125a3f..4c584b2ab7c4 100644 --- a/include/docmodel/uno/UnoComplexColor.hxx +++ b/include/docmodel/uno/UnoComplexColor.hxx @@ -35,7 +35,6 @@ public: // XComplexColor sal_Int32 SAL_CALL getType() override; sal_Int32 SAL_CALL getThemeColorType() override; - OUString SAL_CALL getRepresentation() override; css::util::Color SAL_CALL resolveColor(css::uno::Reference const& xTheme) override; }; diff --git a/include/drawinglayer/attribute/sdrallattribute3d.hxx b/include/drawinglayer/attribute/sdrallattribute3d.hxx index 53d7a1f75aa7..e4e9c8b3acb3 100644 --- a/include/drawinglayer/attribute/sdrallattribute3d.hxx +++ b/include/drawinglayer/attribute/sdrallattribute3d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRALLATTRIBUTE3D_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRALLATTRIBUTE3D_HXX +#pragma once #include @@ -65,7 +64,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::overlay - -#endif // INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRALLATTRIBUTE3D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrfillattribute.hxx b/include/drawinglayer/attribute/sdrfillattribute.hxx index 6ba140065d4c..3a88593a50d6 100644 --- a/include/drawinglayer/attribute/sdrfillattribute.hxx +++ b/include/drawinglayer/attribute/sdrfillattribute.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRFILLATTRIBUTE_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRFILLATTRIBUTE_HXX +#pragma once #include #include @@ -82,7 +81,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::attribute - -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRFILLATTRIBUTE_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrfillgraphicattribute.hxx b/include/drawinglayer/attribute/sdrfillgraphicattribute.hxx index 4a39313d10aa..711e5a71850c 100644 --- a/include/drawinglayer/attribute/sdrfillgraphicattribute.hxx +++ b/include/drawinglayer/attribute/sdrfillgraphicattribute.hxx @@ -16,8 +16,8 @@ * 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_DRAWINGLAYER_ATTRIBUTE_SDRFILLGRAPHICATTRIBUTE_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRFILLGRAPHICATTRIBUTE_HXX + +#pragma once #include #include @@ -88,7 +88,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::attribute - -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRFILLGRAPHICATTRIBUTE_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrglowattribute.hxx b/include/drawinglayer/attribute/sdrglowattribute.hxx index d4045bbc14f7..4212fdeb8737 100644 --- a/include/drawinglayer/attribute/sdrglowattribute.hxx +++ b/include/drawinglayer/attribute/sdrglowattribute.hxx @@ -7,8 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRGLOWATTRIBUTE_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRGLOWATTRIBUTE_HXX +#pragma once #include #include @@ -40,6 +39,4 @@ public: } // end of namespace drawinglayer::attribute -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRGLOWATTRIBUTE_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrglowtextattribute.hxx b/include/drawinglayer/attribute/sdrglowtextattribute.hxx index 6702bae72c14..94261c23b6ec 100644 --- a/include/drawinglayer/attribute/sdrglowtextattribute.hxx +++ b/include/drawinglayer/attribute/sdrglowtextattribute.hxx @@ -7,8 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRGLOWTEXTATTRIBUTE_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRGLOWTEXTATTRIBUTE_HXX +#pragma once #include #include @@ -40,6 +39,4 @@ public: } // end of namespace drawinglayer::attribute -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRGLOWTEXTATTRIBUTE_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrlightattribute3d.hxx b/include/drawinglayer/attribute/sdrlightattribute3d.hxx index b3c1fcaaabae..3a9b0f595997 100644 --- a/include/drawinglayer/attribute/sdrlightattribute3d.hxx +++ b/include/drawinglayer/attribute/sdrlightattribute3d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLIGHTATTRIBUTE3D_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLIGHTATTRIBUTE3D_HXX +#pragma once #include #include @@ -69,7 +68,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::attribute - -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLIGHTATTRIBUTE3D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrlightingattribute3d.hxx b/include/drawinglayer/attribute/sdrlightingattribute3d.hxx index ae2155a542ab..8a78ea0a7ba5 100644 --- a/include/drawinglayer/attribute/sdrlightingattribute3d.hxx +++ b/include/drawinglayer/attribute/sdrlightingattribute3d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLIGHTINGATTRIBUTE3D_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLIGHTINGATTRIBUTE3D_HXX +#pragma once #include #include @@ -80,7 +79,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::attribute - -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLIGHTINGATTRIBUTE3D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrlineattribute.hxx b/include/drawinglayer/attribute/sdrlineattribute.hxx index 9ff6ed42e614..301fd1af60bc 100644 --- a/include/drawinglayer/attribute/sdrlineattribute.hxx +++ b/include/drawinglayer/attribute/sdrlineattribute.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLINEATTRIBUTE_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLINEATTRIBUTE_HXX +#pragma once #include #include @@ -83,7 +82,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::attribute - -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLINEATTRIBUTE_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrlinestartendattribute.hxx b/include/drawinglayer/attribute/sdrlinestartendattribute.hxx index afcf1fd6d369..27cb9d85ce60 100644 --- a/include/drawinglayer/attribute/sdrlinestartendattribute.hxx +++ b/include/drawinglayer/attribute/sdrlinestartendattribute.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLINESTARTENDATTRIBUTE_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLINESTARTENDATTRIBUTE_HXX +#pragma once #include #include @@ -82,7 +81,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::attribute - -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRLINESTARTENDATTRIBUTE_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrobjectattribute3d.hxx b/include/drawinglayer/attribute/sdrobjectattribute3d.hxx index 21576a7c04d8..cd228d3d1af0 100644 --- a/include/drawinglayer/attribute/sdrobjectattribute3d.hxx +++ b/include/drawinglayer/attribute/sdrobjectattribute3d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDROBJECTATTRIBUTE3D_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDROBJECTATTRIBUTE3D_HXX +#pragma once #include @@ -86,7 +85,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::attribute - -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDROBJECTATTRIBUTE3D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrsceneattribute3d.hxx b/include/drawinglayer/attribute/sdrsceneattribute3d.hxx index 62aa7d6fc093..a3451a61046e 100644 --- a/include/drawinglayer/attribute/sdrsceneattribute3d.hxx +++ b/include/drawinglayer/attribute/sdrsceneattribute3d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRSCENEATTRIBUTE3D_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRSCENEATTRIBUTE3D_HXX +#pragma once #include @@ -74,7 +73,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::attribute - -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRSCENEATTRIBUTE3D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/attribute/sdrshadowattribute.hxx b/include/drawinglayer/attribute/sdrshadowattribute.hxx index ab2c045e49bb..1e2eeb7e3204 100644 --- a/include/drawinglayer/attribute/sdrshadowattribute.hxx +++ b/include/drawinglayer/attribute/sdrshadowattribute.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRSHADOWATTRIBUTE_HXX -#define INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRSHADOWATTRIBUTE_HXX +#pragma once #include #include @@ -83,7 +82,4 @@ namespace drawinglayer::attribute } // end of namespace drawinglayer::attribute - -#endif //INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRSHADOWATTRIBUTE_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/geometry/viewinformation3d.hxx b/include/drawinglayer/geometry/viewinformation3d.hxx index ca368a6c3d3c..1b7a167fc5c9 100644 --- a/include/drawinglayer/geometry/viewinformation3d.hxx +++ b/include/drawinglayer/geometry/viewinformation3d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_GEOMETRY_VIEWINFORMATION3D_HXX -#define INCLUDED_DRAWINGLAYER_GEOMETRY_VIEWINFORMATION3D_HXX +#pragma once #include @@ -156,7 +155,4 @@ namespace drawinglayer::geometry } // end of namespace drawinglayer::geometry - -#endif //INCLUDED_DRAWINGLAYER_GEOMETRY_VIEWINFORMATION3D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx b/include/drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx index 47c9bbb83b0b..0bb67c3d0c7a 100644 --- a/include/drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx +++ b/include/drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx @@ -68,8 +68,7 @@ public: sometimes useful for simpler tasks and decomposes to a more generalized PolyPolygonColorPrimitive2D (see above) */ -class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) FilledRectanglePrimitive2D final - : public BasePrimitive2D +class DRAWINGLAYER_DLLPUBLIC FilledRectanglePrimitive2D final : public BasePrimitive2D { private: /// the geometry diff --git a/include/drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx b/include/drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx index f20df8b35bfe..1b42a740bc4a 100644 --- a/include/drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx +++ b/include/drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx @@ -27,10 +27,10 @@ namespace drawinglayer::primitive2d { -/** PolyPolygonColorPrimitive2D class +/** PolyPolygonGradientPrimitive2D class This primitive defines a tools::PolyPolygon filled with a gradient. The - decomosition will create a MaskPrimitive2D containing a + decomposition will create a MaskPrimitive2D containing a FillGradientPrimitive2D. */ class DRAWINGLAYER_DLLPUBLIC PolyPolygonGradientPrimitive2D final diff --git a/include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx b/include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx index 998a294da97f..ebb902638348 100644 --- a/include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx +++ b/include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx @@ -30,12 +30,12 @@ namespace drawinglayer::primitive2d /** PolyPolygonGraphicPrimitive2D class This primitive defines a tools::PolyPolygon filled with bitmap data - (including transparence). The decomosition will create a MaskPrimitive2D + (including transparency). The decomposition will create a MaskPrimitive2D containing a FillGraphicPrimitive2D. SDPR: support alpha now directly: the decomposition creates FillGraphicPrimitive2D which also supports alpha directly - now. All direct usages are covered + now. All direct usages are covered. */ class DRAWINGLAYER_DLLPUBLIC PolyPolygonGraphicPrimitive2D final : public BufferedDecompositionPrimitive2D diff --git a/include/drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx b/include/drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx index 5519cacae85d..b0c7d014c8cb 100644 --- a/include/drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx +++ b/include/drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx @@ -31,7 +31,7 @@ namespace drawinglayer::primitive2d /** PolyPolygonHatchPrimitive2D class This primitive defines a tools::PolyPolygon filled with a hatch. The - decomosition will create a MaskPrimitive2D containing a + decomposition will create a MaskPrimitive2D containing a FillHatchPrimitive2D. */ class DRAWINGLAYER_DLLPUBLIC PolyPolygonHatchPrimitive2D final diff --git a/include/drawinglayer/primitive2d/gridprimitive2d.hxx b/include/drawinglayer/primitive2d/gridprimitive2d.hxx index cb5f1c1a082d..e566ca9dded1 100644 --- a/include/drawinglayer/primitive2d/gridprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/gridprimitive2d.hxx @@ -33,12 +33,12 @@ namespace drawinglayer::primitive2d { /** GridPrimitive2D class - This primitive is specialized to Grid visualisation. The graphic definition + This primitive is specialized to grid visualization. The graphic definition (Transform) contains the whole grid area, but will of course be combined with the visible area (Viewport) when decomposed. Also a resolution-dependent - point reduction is used to not create too much grid visualisation data. This + point reduction is used to not create too much grid visualization data. This makes this primitive highly view-dependent and it dynamically buffers - the last decomposition dependent from the Viewport used. + the last decomposition depending on the Viewport used. */ class DRAWINGLAYER_DLLPUBLIC GridPrimitive2D final : public BufferedDecompositionPrimitive2D { @@ -57,11 +57,11 @@ namespace drawinglayer::primitive2d /// Grid color for single-pixel grid points basegfx::BColor maBColor; - /// The Bitmap (with transparence) for grid cross points + /// The Bitmap (with transparency) for grid cross points Bitmap maCrossMarker; - /** the last used object to view transformtion and the last Viewport, - used from getDecomposition for decide buffering + /** the last used object to view transformation and the last Viewport, + used from getDecomposition to decide buffering */ basegfx::B2DHomMatrix maLastObjectToViewTransformation; basegfx::B2DRange maLastViewport; diff --git a/include/drawinglayer/primitive2d/helplineprimitive2d.hxx b/include/drawinglayer/primitive2d/helplineprimitive2d.hxx index db2fc1cf3775..4a15bee200c4 100644 --- a/include/drawinglayer/primitive2d/helplineprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/helplineprimitive2d.hxx @@ -44,11 +44,11 @@ namespace drawinglayer::primitive2d This primitive provides a view-dependent helpline definition. The Helpline is defined by a line equation (Point and vector) and a style. When the style - is a line, dependent from Viewport the visible part of that Helpline is + is a line, depending on the Viewport the visible part of that Helpline is constructed. For Point, a cross is constructed. This primitive is highly view-dependent. - The visualisation uses the two given colors to create a dashed line with + The visualization uses the two given colors to create a dashed line with the given dash length. */ class DRAWINGLAYER_DLLPUBLIC HelplinePrimitive2D final : public BufferedDecompositionPrimitive2D @@ -64,8 +64,8 @@ namespace drawinglayer::primitive2d basegfx::BColor maRGBColB; double mfDiscreteDashLength; - /** the last used object to view transformtion and the last Viewport, - used from getDecomposition for decide buffering + /** the last used object to view transformation and the last Viewport, + used from getDecomposition to decide buffering */ basegfx::B2DHomMatrix maLastObjectToViewTransformation; basegfx::B2DRange maLastViewport; diff --git a/include/drawinglayer/processor2d/baseprocessor2d.hxx b/include/drawinglayer/processor2d/baseprocessor2d.hxx index 1d01c60e08ff..11455e402608 100644 --- a/include/drawinglayer/processor2d/baseprocessor2d.hxx +++ b/include/drawinglayer/processor2d/baseprocessor2d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX -#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX +#pragma once #include @@ -193,7 +192,4 @@ namespace drawinglayer::processor2d } // end of namespace drawinglayer::processor2d - -#endif //INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/processor2d/contourextractor2d.hxx b/include/drawinglayer/processor2d/contourextractor2d.hxx index 53158cc21291..00491cf5027c 100644 --- a/include/drawinglayer/processor2d/contourextractor2d.hxx +++ b/include/drawinglayer/processor2d/contourextractor2d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_CONTOUREXTRACTOR2D_HXX -#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_CONTOUREXTRACTOR2D_HXX +#pragma once #include @@ -56,7 +55,4 @@ namespace drawinglayer::processor2d } // end of namespace drawinglayer::processor2d - -#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_CONTOUREXTRACTOR2D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/processor2d/hittestprocessor2d.hxx b/include/drawinglayer/processor2d/hittestprocessor2d.hxx index 5a72498f44e3..d9f335c12228 100644 --- a/include/drawinglayer/processor2d/hittestprocessor2d.hxx +++ b/include/drawinglayer/processor2d/hittestprocessor2d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_HITTESTPROCESSOR2D_HXX -#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_HITTESTPROCESSOR2D_HXX +#pragma once #include #include @@ -93,6 +92,4 @@ namespace drawinglayer::processor2d } // end of namespace drawinglayer::processor2d -#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_HITTESTPROCESSOR2D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/processor2d/linegeometryextractor2d.hxx b/include/drawinglayer/processor2d/linegeometryextractor2d.hxx index a2a388dd12f3..87bb33c7b921 100644 --- a/include/drawinglayer/processor2d/linegeometryextractor2d.hxx +++ b/include/drawinglayer/processor2d/linegeometryextractor2d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_LINEGEOMETRYEXTRACTOR2D_HXX -#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_LINEGEOMETRYEXTRACTOR2D_HXX +#pragma once #include @@ -55,7 +54,4 @@ namespace drawinglayer::processor2d } // end of namespace drawinglayer::processor2d - -#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_LINEGEOMETRYEXTRACTOR2D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/processor2d/objectinfoextractor2d.hxx b/include/drawinglayer/processor2d/objectinfoextractor2d.hxx index f7dc1d146885..1ab7a1f30d4b 100644 --- a/include/drawinglayer/processor2d/objectinfoextractor2d.hxx +++ b/include/drawinglayer/processor2d/objectinfoextractor2d.hxx @@ -16,8 +16,8 @@ * 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_DRAWINGLAYER_PROCESSOR2D_OBJECTINFOEXTRACTOR2D_HXX -#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_OBJECTINFOEXTRACTOR2D_HXX + +#pragma once #include #include @@ -49,6 +49,4 @@ namespace drawinglayer::processor2d } // end of namespace drawinglayer::processor2d -#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_OBJECTINFOEXTRACTOR2D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/processor2d/processor2dtools.hxx b/include/drawinglayer/processor2d/processor2dtools.hxx index 91908b303805..0266a96dbbd3 100644 --- a/include/drawinglayer/processor2d/processor2dtools.hxx +++ b/include/drawinglayer/processor2d/processor2dtools.hxx @@ -16,8 +16,8 @@ * 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_DRAWINGLAYER_PROCESSOR2D_PROCESSOR2DTOOLS_HXX -#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_PROCESSOR2DTOOLS_HXX + +#pragma once #include #include @@ -100,6 +100,4 @@ namespace drawinglayer::processor2d } // end of namespace drawinglayer::processor2d -#endif //INCLUDED_DRAWINGLAYER_PROCESSOR2D_PROCESSOR2DTOOLS_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/processor2d/textaspolygonextractor2d.hxx b/include/drawinglayer/processor2d/textaspolygonextractor2d.hxx index a7189778a7f2..460daf428c1e 100644 --- a/include/drawinglayer/processor2d/textaspolygonextractor2d.hxx +++ b/include/drawinglayer/processor2d/textaspolygonextractor2d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_TEXTASPOLYGONEXTRACTOR2D_HXX -#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_TEXTASPOLYGONEXTRACTOR2D_HXX +#pragma once #include @@ -90,7 +89,4 @@ namespace drawinglayer::processor2d } // end of namespace drawinglayer::processor2d - -#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_TEXTASPOLYGONEXTRACTOR2D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/processor3d/baseprocessor3d.hxx b/include/drawinglayer/processor3d/baseprocessor3d.hxx index 3832b9bbb300..0fda00b696a4 100644 --- a/include/drawinglayer/processor3d/baseprocessor3d.hxx +++ b/include/drawinglayer/processor3d/baseprocessor3d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR3D_BASEPROCESSOR3D_HXX -#define INCLUDED_DRAWINGLAYER_PROCESSOR3D_BASEPROCESSOR3D_HXX +#pragma once #include @@ -62,7 +61,4 @@ namespace drawinglayer::processor3d } // end of namespace drawinglayer::processor3d - -#endif //_DRAWINGLAYER_PROCESSOR3D_BASEPROCESSOR3D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/processor3d/cutfindprocessor3d.hxx b/include/drawinglayer/processor3d/cutfindprocessor3d.hxx index 0914a33e6132..12e6acd98327 100644 --- a/include/drawinglayer/processor3d/cutfindprocessor3d.hxx +++ b/include/drawinglayer/processor3d/cutfindprocessor3d.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR3D_CUTFINDPROCESSOR3D_HXX -#define INCLUDED_DRAWINGLAYER_PROCESSOR3D_CUTFINDPROCESSOR3D_HXX +#pragma once #include #include @@ -69,7 +68,4 @@ namespace drawinglayer::processor3d } // end of namespace drawinglayer::processor3d - -#endif //INCLUDED_DRAWINGLAYER_PROCESSOR3D_CUTFINDPROCESSOR3D_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/tools/primitive2dxmldump.hxx b/include/drawinglayer/tools/primitive2dxmldump.hxx index 8d01633935ef..b204edf82d9a 100644 --- a/include/drawinglayer/tools/primitive2dxmldump.hxx +++ b/include/drawinglayer/tools/primitive2dxmldump.hxx @@ -7,8 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_DRAWINGLAYER_TOOLS_PRIMITIVE2DXMLDUMP_HXX -#define INCLUDED_DRAWINGLAYER_TOOLS_PRIMITIVE2DXMLDUMP_HXX +#pragma once #include #include @@ -55,6 +54,4 @@ public: } -#endif // INCLUDED_DRAWINGLAYER_TOOLS_PRIMITIVE2DXMLDUMP_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/editeng/AccessibleContextBase.hxx b/include/editeng/AccessibleContextBase.hxx index 69d5625035fb..6a73a11fd1ce 100644 --- a/include/editeng/AccessibleContextBase.hxx +++ b/include/editeng/AccessibleContextBase.hxx @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -30,8 +29,7 @@ namespace utl { class AccessibleRelationSetHelper; } namespace accessibility { -class EDITENG_DLLPUBLIC AccessibleContextBase - : public cppu::ImplInheritanceHelper +class EDITENG_DLLPUBLIC AccessibleContextBase : public comphelper::OAccessible { public: /** The origin of the accessible name or description. @@ -43,9 +41,8 @@ public: NotSet }; - AccessibleContextBase ( - css::uno::Reference< css::accessibility::XAccessible> xParent, - const sal_Int16 aRole); + AccessibleContextBase(const rtl::Reference& rpParent, + const sal_Int16 aRole); virtual ~AccessibleContextBase() override; @@ -151,8 +148,8 @@ public: getAccessibleChild (sal_Int64 nIndex) override; /// Return a reference to the parent. - virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL - getAccessibleParent() override; + virtual css::uno::Reference + SAL_CALL getAccessibleParent() override final; /// Return this object's role. virtual sal_Int16 SAL_CALL @@ -198,21 +195,6 @@ public: */ virtual sal_Int32 SAL_CALL getBackground() override; - //===== XServiceInfo ==================================================== - - /** Returns an identifier for the implementation of this object. - */ - virtual OUString SAL_CALL - getImplementationName() override; - - /** Return whether the specified service is supported by this class. - */ - virtual sal_Bool SAL_CALL - supportsService (const OUString& sServiceName) override final; - - virtual css::uno::Sequence< OUString> SAL_CALL - getSupportedServiceNames() override; - /** Check whether or not the object has been disposed (or is in the state of being disposed). @@ -221,6 +203,8 @@ public: */ bool IsDisposed() const; + rtl::Reference implGetAccessibleParent(); + protected: /** The state set. */ @@ -253,7 +237,7 @@ protected: private: /// Reference to the parent object. - css::uno::Reference< css::accessibility::XAccessible> mxParent; + rtl::Reference mpParent; /** Description of this object. This is not a constant because it can be set from the outside. Furthermore, it changes according to the diff --git a/include/editeng/AccessibleEditableTextPara.hxx b/include/editeng/AccessibleEditableTextPara.hxx index 27b7d63f0087..0f4ea8b3909e 100644 --- a/include/editeng/AccessibleEditableTextPara.hxx +++ b/include/editeng/AccessibleEditableTextPara.hxx @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -72,8 +71,8 @@ public: // - add parameter <_pParaManager> (default value NULL) // This has to be the instance of , which // created and manages this accessible paragraph. - AccessibleEditableTextPara ( css::uno::Reference< css::accessibility::XAccessible > xParent, - const AccessibleParaManager* _pParaManager = nullptr ); + AccessibleEditableTextPara(const rtl::Reference& rpParent, + const AccessibleParaManager* _pParaManager = nullptr); // XAccessibleContext virtual sal_Int64 SAL_CALL getAccessibleChildCount() override; @@ -335,7 +334,7 @@ private: sal_Int64 mnStateSet; /// The shape we're the accessible for (unguarded) - css::uno::Reference< css::accessibility::XAccessible > mxParent; + rtl::Reference mpParent; private: // Text paragraphs should provide FLOWS_TO and FLOWS_FROM relations (#i27138#) diff --git a/include/editeng/crossedoutitem.hxx b/include/editeng/crossedoutitem.hxx index fc75cc183f08..2d368387c330 100644 --- a/include/editeng/crossedoutitem.hxx +++ b/include/editeng/crossedoutitem.hxx @@ -26,7 +26,7 @@ // class SvxCrossedOutItem ----------------------------------------------- /* [Description] - This item describes, whether and how it is striked out. + This item describes whether and how it is struck out. */ class EDITENG_DLLPUBLIC SvxCrossedOutItem final : public SfxEnumItem diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx index 891383f7ad62..5b48537e18b0 100644 --- a/include/editeng/editeng.hxx +++ b/include/editeng/editeng.hxx @@ -306,10 +306,10 @@ public: void Clear(); void SetText( const OUString& rStr ); - std::unique_ptr CreateTextObject(); - SAL_DLLPRIVATE std::unique_ptr GetEmptyTextObject(); - std::unique_ptr CreateTextObject( sal_Int32 nPara, sal_Int32 nParas = 1 ); - std::unique_ptr CreateTextObject( const ESelection& rESelection ); + EditTextObject CreateTextObject(); + SAL_DLLPRIVATE EditTextObject GetEmptyTextObject(); + EditTextObject CreateTextObject( sal_Int32 nPara, sal_Int32 nParas = 1 ); + EditTextObject CreateTextObject( const ESelection& rESelection ); void SetText( const EditTextObject& rTextObject ); SAL_DLLPRIVATE void RemoveParagraph(sal_Int32 nPara); @@ -483,7 +483,7 @@ public: SAL_DLLPRIVATE void SetBeginMovingParagraphsHdl( const Link& rLink ); SAL_DLLPRIVATE void SetEndMovingParagraphsHdl( const Link& rLink ); SAL_DLLPRIVATE void SetBeginPasteOrDropHdl( const Link& rLink ); - SAL_DLLPRIVATE void SetEndPasteOrDropHdl( const Link& rLink ); + void SetEndPasteOrDropHdl( const Link& rLink ); virtual void ProcessFirstLineOfParagraph(sal_Int32 nPara, const Point& rStartPos, OutputDevice& rOutDev, StripPortionsHelper& rStripPortionsHelper); diff --git a/include/editeng/editids.hrc b/include/editeng/editids.hrc index 6c170ff00b04..6d5279164dba 100644 --- a/include/editeng/editids.hrc +++ b/include/editeng/editids.hrc @@ -162,16 +162,17 @@ class SvxOpticalSizingItem; #define SID_PARA_VERTALIGN TypedWhichId( SID_SVX_START + 925 ) #define SID_ATTR_FRAMEDIRECTION TypedWhichId( SID_SVX_START + 944 ) #define SID_ATTR_PARA_SNAPTOGRID TypedWhichId( SID_SVX_START + 945 ) -#define SID_ATTR_PARA_AUTOFRAMEDIRECTION TypedWhichId( SID_SVX_START + 946 ) +// CAUTION! 946 used by include/svx/svxids.hrc #define SID_ATTR_PARA_LRSPACE_VERTICAL ( SID_SVX_START + 947 ) -#define SID_ATTR_PARA_LEFT_TO_RIGHT ( SID_SVX_START + 950 ) -#define SID_ATTR_PARA_RIGHT_TO_LEFT ( SID_SVX_START + 951 ) +#define SID_ATTR_PARA_LEFT_TO_RIGHT TypedWhichId( SID_SVX_START + 950 ) +#define SID_ATTR_PARA_RIGHT_TO_LEFT TypedWhichId( SID_SVX_START + 951 ) #define SID_ATTR_CHAR_HIDDEN TypedWhichId( SID_SVX_START + 989 ) #define SID_ATTR_CHAR_LATIN_FONT ( SID_SVX_START + 994 ) #define SID_ATTR_CHAR_LATIN_FONTHEIGHT TypedWhichId( SID_SVX_START + 995 ) #define SID_ATTR_CHAR_LATIN_LANGUAGE ( SID_SVX_START + 996 ) #define SID_ATTR_CHAR_LATIN_POSTURE TypedWhichId( SID_SVX_START + 997 ) #define SID_ATTR_CHAR_LATIN_WEIGHT ( SID_SVX_START + 998 ) +#define SID_ATTR_PARA_AUTOFRAMEDIRECTION TypedWhichId( SID_SVX_START + 1069 ) #define SID_ATTR_CHAR_GRABBAG TypedWhichId( SID_SVX_START + 1142 ) #define SID_ATTR_CHAR_BACK_COLOR ( SID_SVX_START + 1153 ) @@ -191,6 +192,8 @@ class SvxOpticalSizingItem; #define SID_ATTR_PARA_ADJUST_END ( SID_EDIT_START + 80 ) #define SID_ATTR_CHAR_OPTICAL_SIZING TypedWhichId( SID_EDIT_START + 81 ) #define SID_ATTR_CHAR_FONT_VARIATIONS TypedWhichId( SID_EDIT_START + 82 ) +#define SID_ATTR_CHAR_CJK_FONT_VARIATIONS TypedWhichId( SID_EDIT_START + 83 ) +#define SID_ATTR_CHAR_CTL_FONT_VARIATIONS TypedWhichId( SID_EDIT_START + 84 ) #if 95 > (SID_EDIT_END-SID_EDIT_START) diff --git a/include/editeng/editobj.hxx b/include/editeng/editobj.hxx index 840f2e291da7..2cee547b57e8 100644 --- a/include/editeng/editobj.hxx +++ b/include/editeng/editobj.hxx @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include #include @@ -38,69 +40,84 @@ class SvxFieldData; enum class OutlinerMode; struct EECharAttrib; typedef struct _xmlTextWriter* xmlTextWriterPtr; +class ContentInfo; +class XParaPortionList; namespace editeng { - class FieldUpdater; struct Section; - } namespace svl { - class SharedString; class SharedStringPool; - } enum class TextRotation { NONE, TOPTOBOTTOM, BOTTOMTOTOP }; -class EDITENG_DLLPUBLIC EditTextObject +class EDITENG_DLLPUBLIC EditTextObject final { public: - virtual ~EditTextObject(); + typedef std::vector > ContentInfosType; + + EditTextObject(SfxItemPool* pPool, MapUnit eDefaultMetric, bool bVertical, + TextRotation eRotation, SvtScriptType eScriptType); + EditTextObject( const EditTextObject& r ); + EditTextObject( EditTextObject&& r ) noexcept; + ~EditTextObject(); + + EditTextObject& operator=(EditTextObject&&); /** * Set paragraph strings to the shared string pool. * * @param rPool shared string pool. */ - virtual void NormalizeString( svl::SharedStringPool& rPool ) = 0; + void NormalizeString( svl::SharedStringPool& rPool ); - virtual std::vector GetSharedStrings() const = 0; + std::vector GetSharedStrings() const; - virtual const SfxItemPool* GetPool() const = 0; - virtual OutlinerMode GetUserType() const = 0; // For OutlinerMode, it can however not save in compatible format - virtual void SetUserType( OutlinerMode n ) = 0; + const SfxItemPool* GetPool() const { return mpPool.get(); } + SfxItemPool* GetPool() { return mpPool.get(); } - virtual bool IsEffectivelyVertical() const = 0; - virtual bool GetVertical() const = 0; - virtual bool IsTopToBottom() const = 0; - virtual void SetVertical( bool bVertical ) = 0; - virtual void SetRotation( TextRotation nRotation ) = 0; - virtual TextRotation GetRotation() const = 0; + OutlinerMode GetUserType() const { return meUserType;} // For OutlinerMode, it can however not save in compatible format + void SetUserType( OutlinerMode n ); - virtual SvtScriptType GetScriptType() const = 0; + bool IsEffectivelyVertical() const; + bool GetVertical() const; + bool IsTopToBottom() const; + void SetVertical( bool bVertical ); + void SetRotation( TextRotation nRotation ); + TextRotation GetRotation() const; - virtual std::unique_ptr Clone() const = 0; + SvtScriptType GetScriptType() const { return meScriptType;} - virtual sal_Int32 GetParagraphCount() const = 0; + sal_Int32 GetParagraphCount() const; - virtual OUString GetText(sal_Int32 nPara) const = 0; + OUString GetText(sal_Int32 nPara) const; - virtual OUString GetText(LineEnd eEnd = LINEEND_LF) const = 0; + OUString GetText(LineEnd eEnd = LINEEND_LF) const; - virtual sal_Int32 GetTextLen(sal_Int32 nPara) const = 0; + sal_Int32 GetTextLen(sal_Int32 nPara) const; bool HasText(sal_Int32 nPara) const { return GetTextLen(nPara) > 0; } - virtual void ClearPortionInfo() = 0; + XParaPortionList* GetPortionInfo() const { return mpPortionInfo.get(); } + void SetPortionInfo( std::unique_ptr pP ); + void ClearPortionInfo(); - virtual bool HasOnlineSpellErrors() const = 0; + sal_Int16 GetNumberingDepth(sal_Int32 nPara) const; + void SetNumberingDepth(sal_Int32 nPara, sal_Int16 nDepth); + sal_Int16 GetNumberingStartValue(sal_Int32 nPara) const; + void SetNumberingStartValue(sal_Int32 nPara, sal_Int16 nStartValue); + bool IsNumberingRestart(sal_Int32 nPara) const; + void SetNumberingRestart(sal_Int32 nPara, bool bRestart); - virtual void GetCharAttribs( sal_Int32 nPara, std::vector& rLst ) const = 0; + bool HasOnlineSpellErrors() const; - virtual bool RemoveCharAttribs( sal_uInt16 nWhich ) = 0; + void GetCharAttribs( sal_Int32 nPara, std::vector& rLst ) const; + + bool RemoveCharAttribs( sal_uInt16 nWhich ); /** * Get all text sections in this content. Sections are non-overlapping @@ -108,36 +125,58 @@ public: * boundaries. Each section object contains all applied formats and/or a * field item. */ - virtual void GetAllSections( std::vector& rAttrs ) const = 0; + void GetAllSections( std::vector& rAttrs ) const; - virtual bool IsFieldObject() const = 0; - virtual const SvxFieldItem* GetField() const = 0; - virtual const SvxFieldData* GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const = 0; - virtual bool HasField( sal_Int32 nType = css::text::textfield::Type::UNSPECIFIED ) const = 0; + bool IsFieldObject() const; + const SvxFieldItem* GetField() const; + const SvxFieldData* GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const; + bool HasField( sal_Int32 nType = css::text::textfield::Type::UNSPECIFIED ) const; - virtual const SfxItemSet& GetParaAttribs(sal_Int32 nPara) const = 0; + const SfxItemSet& GetParaAttribs(sal_Int32 nPara) const; - virtual void GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& eFamily) const = 0; - virtual void SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& eFamily) = 0; - virtual bool ChangeStyleSheets( - std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily) = 0; - virtual void ChangeStyleSheetName(SfxStyleFamily eFamily, std::u16string_view rOldName, const OUString& rNewName) = 0; + void GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& eFamily) const; + void SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& eFamily); + bool ChangeStyleSheets( + std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily); + void ChangeStyleSheetName(SfxStyleFamily eFamily, std::u16string_view rOldName, const OUString& rNewName); - virtual editeng::FieldUpdater GetFieldUpdater() = 0; + editeng::FieldUpdater GetFieldUpdater(); - virtual bool operator==( const EditTextObject& rCompare ) const = 0; + bool operator==( const EditTextObject& rCompare ) const; /** Compare, ignoring SfxItemPool pointer. */ bool Equals( const EditTextObject& rCompare ) const; + bool Equals( const EditTextObject& rCompare, bool bComparePool ) const; + // #i102062# - virtual bool isWrongListEqual(const EditTextObject& rCompare) const = 0; + bool isWrongListEqual(const EditTextObject& rCompare) const; + + ContentInfo* CreateAndInsertContent(); + ContentInfosType& GetContents() { return maContents;} + const ContentInfosType& GetContents() const { return maContents;} + + bool HasMetric() const { return meMetric != MapUnit::LASTENUMDUMMY; } + MapUnit GetMetric() const { return meMetric; } #if DEBUG_EDIT_ENGINE - virtual void Dump() const = 0; + void Dump() const; #endif - virtual void dumpAsXml(xmlTextWriterPtr pWriter) const = 0; + void dumpAsXml(xmlTextWriterPtr pWriter) const; + +private: + bool ImpChangeStyleSheets( std::u16string_view rOldName, SfxStyleFamily eOldFamily, + const OUString& rNewName, SfxStyleFamily eNewFamily ); + + ContentInfosType maContents; + rtl::Reference mpPool; + std::unique_ptr mpPortionInfo; + OutlinerMode meUserType; + SvtScriptType meScriptType; + TextRotation meRotation; + MapUnit meMetric; + bool mbVertical; }; #endif // INCLUDED_EDITENG_EDITOBJ_HXX diff --git a/include/editeng/editrids.hrc b/include/editeng/editrids.hrc index 9d8105e62547..255db9e9ec91 100644 --- a/include/editeng/editrids.hrc +++ b/include/editeng/editrids.hrc @@ -67,10 +67,10 @@ #define RID_SVXITEMS_WEIGHT_ULTRALIGHT NC_("RID_SVXITEMS_WEIGHT_ULTRALIGHT", "ultra thin") #define RID_SVXITEMS_WEIGHT_LIGHT NC_("RID_SVXITEMS_WEIGHT_LIGHT", "light") #define RID_SVXITEMS_WEIGHT_SEMILIGHT NC_("RID_SVXITEMS_WEIGHT_SEMILIGHT", "semi light") -#define RID_SVXITEMS_WEIGHT_NORMAL NC_("RID_SVXITEMS_WEIGHT_NORMAL", "normal") +#define RID_SVXITEMS_WEIGHT_NORMAL NC_("RID_SVXITEMS_WEIGHT_NORMAL", "Not Bold") #define RID_SVXITEMS_WEIGHT_MEDIUM NC_("RID_SVXITEMS_WEIGHT_MEDIUM", "medium") #define RID_SVXITEMS_WEIGHT_SEMIBOLD NC_("RID_SVXITEMS_WEIGHT_SEMIBOLD", "semi bold") -#define RID_SVXITEMS_WEIGHT_BOLD NC_("RID_SVXITEMS_WEIGHT_BOLD", "bold") +#define RID_SVXITEMS_WEIGHT_BOLD NC_("RID_SVXITEMS_WEIGHT_BOLD", "Bold") #define RID_SVXITEMS_WEIGHT_ULTRABOLD NC_("RID_SVXITEMS_WEIGHT_ULTRABOLD", "ultra bold") #define RID_SVXITEMS_WEIGHT_BLACK NC_("RID_SVXITEMS_WEIGHT_BLACK", "black") @@ -133,7 +133,7 @@ #define RID_SVXITEMS_SCRIPTHINTVAL_COMPLEX NC_("RID_SVXITEMS_SCRIPTHINTVAL_COMPLEX", "Complex") // enum CASEMAP ---------------------------------------------------------- -#define RID_SVXITEMS_CASEMAP_NONE NC_("RID_SVXITEMS_CASEMAP_NONE", "None") +#define RID_SVXITEMS_CASEMAP_NONE NC_("RID_SVXITEMS_CASEMAP_NONE", "No caps") #define RID_SVXITEMS_CASEMAP_UPPERCASE NC_("RID_SVXITEMS_CASEMAP_VERSALIEN", "Caps") #define RID_SVXITEMS_CASEMAP_LOWERCASE NC_("RID_SVXITEMS_CASEMAP_GEMEINE", "Lowercase") #define RID_SVXITEMS_CASEMAP_TITLE NC_("RID_SVXITEMS_CASEMAP_TITEL", "Title") @@ -190,7 +190,9 @@ #define RID_SVXITEMS_NOHYPHENATION_TRUE NC_("RID_SVXITEMS_NOHYPHENATION_TRUE", "No hyphenation") #define RID_SVXITEMS_WORDLINE_TRUE NC_("RID_SVXITEMS_WORDLINE_TRUE", "Individual words") #define RID_SVXITEMS_WORDLINE_FALSE NC_("RID_SVXITEMS_WORDLINE_FALSE", "Not Words Only") +// To translators: Outline as in the lines of the shape of a character #define RID_SVXITEMS_CONTOUR_TRUE NC_("RID_SVXITEMS_CONTOUR_TRUE", "Outline") +// To translators: Outline as in the lines of the shape of a character #define RID_SVXITEMS_CONTOUR_FALSE NC_("RID_SVXITEMS_CONTOUR_FALSE", "No Outline") #define RID_SVXITEMS_PRINT_TRUE NC_("RID_SVXITEMS_PRINT_TRUE", "Print") #define RID_SVXITEMS_PRINT_FALSE NC_("RID_SVXITEMS_PRINT_FALSE", "Don't print") @@ -259,12 +261,13 @@ #define RID_SVXITEMS_HYPHEN_KEEP_PAGE NC_("RID_SVXITEMS_HYPHEN_KEEP_PAGE", "Avoid hyphenation across page") #define RID_SVXITEMS_HYPHEN_KEEP_COLUMN NC_("RID_SVXITEMS_HYPHEN_KEEP_COLUMN", "Avoid hyphenation across column and page") #define RID_SVXITEMS_HYPHEN_KEEP_ALWAYS NC_("RID_SVXITEMS_HYPHEN_KEEP_ALWAYS", "Avoid hyphenation across last full paragraph line, column and page") +#define RID_SVXITEMS_HYPHEN_LEVEL NC_("RID_SVXITEMS_HYPHEN_LEVEL", "Hyphenation level $(ARG1)%") #define RID_SVXITEMS_PAGEMODEL_COMPLETE NC_("RID_SVXITEMS_PAGEMODEL_COMPLETE", "Page Style: ") #define RID_SVXITEMS_KERNING_COMPLETE NC_("RID_SVXITEMS_KERNING_COMPLETE", "Kerning ") #define RID_SVXITEMS_KERNING_EXPANDED NC_("RID_SVXITEMS_KERNING_EXPANDED", "locked ") #define RID_SVXITEMS_KERNING_CONDENSED NC_("RID_SVXITEMS_KERNING_CONDENSED", "Condensed ") #define RID_SVXITEMS_GRAPHIC NC_("RID_SVXITEMS_GRAPHIC", "Graphic") -#define RID_SVXITEMS_EMPHASIS_NONE_STYLE NC_("RID_SVXITEMS_EMPHASIS_NONE_STYLE", "none") +#define RID_SVXITEMS_EMPHASIS_NONE_STYLE NC_("RID_SVXITEMS_EMPHASIS_NONE_STYLE", "No emphasis") #define RID_SVXITEMS_EMPHASIS_DOT_STYLE NC_("RID_SVXITEMS_EMPHASIS_DOT_STYLE", "Dots ") #define RID_SVXITEMS_EMPHASIS_CIRCLE_STYLE NC_("RID_SVXITEMS_EMPHASIS_CIRCLE_STYLE", "Circle ") // ??? disc == filled ring diff --git a/include/editeng/editview.hxx b/include/editeng/editview.hxx index e77cea8c56b1..cb2fa7947c77 100644 --- a/include/editeng/editview.hxx +++ b/include/editeng/editview.hxx @@ -301,7 +301,7 @@ public: void SetControlWord( EVControlBits nWord ); EVControlBits GetControlWord() const; - std::unique_ptr CreateTextObject(); + EditTextObject CreateTextObject(); void InsertText( const EditTextObject& rTextObject ); void InsertText( css::uno::Reference< css::datatransfer::XTransferable > const & xDataObj, const OUString& rBaseURL, bool bUseSpecial ); diff --git a/include/editeng/eeitem.hxx b/include/editeng/eeitem.hxx index 9491438fcd95..54fff78c7c5c 100644 --- a/include/editeng/eeitem.hxx +++ b/include/editeng/eeitem.hxx @@ -137,8 +137,10 @@ inline constexpr TypedWhichId EE_CHAR_RUBY (EE inline constexpr TypedWhichId EE_CHAR_SCRIPT_HINT (EE_CHAR_START+33); inline constexpr TypedWhichId EE_CHAR_OPTICALSIZING (EE_CHAR_START+34); inline constexpr TypedWhichId EE_CHAR_FONTVARIATIONS (EE_CHAR_START+35); +inline constexpr TypedWhichId EE_CHAR_FONTVARIATIONS_CJK (EE_CHAR_START+36); +inline constexpr TypedWhichId EE_CHAR_FONTVARIATIONS_CTL (EE_CHAR_START+37); -inline constexpr sal_uInt16 EE_CHAR_END (EE_CHAR_START + 35); +inline constexpr sal_uInt16 EE_CHAR_END (EE_CHAR_START + 37); inline constexpr sal_uInt16 EE_FEATURE_START (EE_CHAR_END + 1); inline constexpr sal_uInt16 EE_FEATURE_TAB (EE_FEATURE_START + 0); @@ -151,6 +153,6 @@ inline constexpr sal_uInt16 EE_ITEMS_END (EE_FEATURE_END); inline constexpr sal_uInt16 EDITITEMCOUNT (EE_ITEMS_END - EE_ITEMS_START + 1); -#endif // _ INCLUDED_EDITENG_EEITEM_HXX +#endif // INCLUDED_EDITENG_EEITEM_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/editeng/flditem.hxx b/include/editeng/flditem.hxx index a901336b54a4..85cdc2a5da37 100644 --- a/include/editeng/flditem.hxx +++ b/include/editeng/flditem.hxx @@ -56,6 +56,7 @@ public: virtual std::unique_ptr Clone() const; virtual bool operator==( const SvxFieldData& ) const; + virtual size_t hashCode() const; virtual void dumpAsXml(xmlTextWriterPtr pWriter) const; }; @@ -77,6 +78,8 @@ public: virtual bool operator==( const SfxPoolItem& ) const override; virtual SvxFieldItem* Clone( SfxItemPool *pPool = nullptr ) const override; virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override; + virtual bool supportsHashCode() const override { return true; } + virtual size_t hashCode() const override; const SvxFieldData* GetField() const { return mpField.get(); } }; @@ -172,6 +175,7 @@ public: virtual std::unique_ptr Clone() const override; virtual bool operator==( const SvxFieldData& ) const override; + virtual size_t hashCode() const override; void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; diff --git a/include/editeng/fontitem.hxx b/include/editeng/fontitem.hxx index 1f93e88e5fde..9beb3ac7c575 100644 --- a/include/editeng/fontitem.hxx +++ b/include/editeng/fontitem.hxx @@ -24,6 +24,8 @@ #include #include +class OutputDevice; + /** This item describes a Font. */ class EDITENG_DLLPUBLIC SvxFontItem final : public SfxPoolItem @@ -72,6 +74,9 @@ public: return aStyleName; } + void makeTypographic(const OutputDevice& rDevice, FontWeight eWeight = WEIGHT_DONTKNOW, + FontWidth eWidth = WIDTH_DONTKNOW, FontItalic eItalic = ITALIC_DONTKNOW); + void SetFamily(FontFamily _eFamily); FontFamily GetFamily() const { diff --git a/include/editeng/fontvariationsitem.hxx b/include/editeng/fontvariationsitem.hxx index 784e5dd5a5fd..ec2e7e2ba962 100644 --- a/include/editeng/fontvariationsitem.hxx +++ b/include/editeng/fontvariationsitem.hxx @@ -18,7 +18,6 @@ class EDITENG_DLLPUBLIC SvxFontVariationsItem final : public SfxPoolItem std::vector maVariations; public: - static SfxPoolItem* CreateDefault(); DECLARE_ITEM_TYPE_FUNCTION(SvxFontVariationsItem) SvxFontVariationsItem(sal_uInt16 nId); diff --git a/include/editeng/hyphenzoneitem.hxx b/include/editeng/hyphenzoneitem.hxx index 5e57f73ee156..44cde4b87e58 100644 --- a/include/editeng/hyphenzoneitem.hxx +++ b/include/editeng/hyphenzoneitem.hxx @@ -49,6 +49,7 @@ class EDITENG_DLLPUBLIC SvxHyphenZoneItem final : public SfxPoolItem bool bKeepLine : 1; // if bKeep, shift the hyphenated word (true), or the full line sal_uInt8 nCompoundMinLead; // min. characters between left compound word boundary and hyphenation sal_uInt8 nCompoundMinTrail; // min. characters between hyphenation and right compound word boundary + sal_uInt8 nLevel; // level between Fewer Hyphens (0%) or Better Spacing (100%) public: static SfxPoolItem* CreateDefault(); @@ -118,6 +119,9 @@ public: void SetKeepLine( const bool bNew ) { bKeepLine = bNew; } bool IsKeepLine() const { return bKeepLine; } + + sal_uInt8 &GetLevel() { return nLevel; } + sal_uInt8 GetLevel() const { return nLevel; } }; #endif diff --git a/include/editeng/lrspitem.hxx b/include/editeng/lrspitem.hxx index 1e39f89c511e..78f3367846bc 100644 --- a/include/editeng/lrspitem.hxx +++ b/include/editeng/lrspitem.hxx @@ -387,7 +387,7 @@ public: // Query/direct setting of the absolute values const SvxIndentValue & GetLeft() const; - sal_Int32 ResolveLeft(const SvxFontUnitMetrics& rMetrics) const; + sal_Int32 ResolveLeft() const; const SvxIndentValue & GetRight() const; sal_Int32 ResolveRight(const SvxFontUnitMetrics& rMetrics) const; bool IsAutoFirst() const { return bAutoFirst; } diff --git a/include/editeng/memberids.h b/include/editeng/memberids.h index 19ea071076a7..fa9306e52440 100644 --- a/include/editeng/memberids.h +++ b/include/editeng/memberids.h @@ -60,6 +60,7 @@ #define MID_HYPHEN_COMPOUND_MIN_LEAD 14 #define MID_HYPHEN_COMPOUND_MIN_TRAIL 15 #define MID_HYPHEN_KEEP_LINE 16 +#define MID_HYPHEN_LEVEL 17 // SvxBoxInfoItem #define MID_HORIZONTAL 1 @@ -218,8 +219,7 @@ #define MID_COLOR_TINT_OR_SHADE 5 #define MID_COLOR_LUM_MOD 6 #define MID_COLOR_LUM_OFF 7 -#define MID_COMPLEX_COLOR_JSON 8 -#define MID_COMPLEX_COLOR 9 +#define MID_COMPLEX_COLOR 8 // SvxRubyItem and SwFormatRuby #define MID_RUBY_TEXT 0 diff --git a/include/editeng/opticalsizingitem.hxx b/include/editeng/opticalsizingitem.hxx index 7e1dca8f02ff..26e098fb0349 100644 --- a/include/editeng/opticalsizingitem.hxx +++ b/include/editeng/opticalsizingitem.hxx @@ -22,7 +22,6 @@ class EDITENG_DLLPUBLIC SvxOpticalSizingItem final : public SfxBoolItem { public: - static SfxPoolItem* CreateDefault(); DECLARE_ITEM_TYPE_FUNCTION(SvxOpticalSizingItem) SvxOpticalSizingItem(const bool bOpticalSizing /*= false*/, const sal_uInt16 nId); diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx index 84bf25345cd9..b9708d1ee83c 100644 --- a/include/editeng/outliner.hxx +++ b/include/editeng/outliner.hxx @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -125,7 +124,7 @@ public: ScalingParameters maScalingParameters; }; -class Paragraph : protected ParagraphData +class Paragraph { private: friend class Outliner; @@ -138,6 +137,9 @@ private: Paragraph& operator=(const Paragraph& rPara ) = delete; + sal_Int16 mnNumberingDepth; + sal_Int16 mnNumberingStartValue; + bool mbNumberingRestart; BulletInfo maBullet; ParaFlag nFlags = ParaFlag::NONE; bool bVisible = true; @@ -178,9 +180,9 @@ private: maBullet.maSize.setHeight(-1); } - void SetDepth(sal_Int16 nNewDepth) + void SetNumberingDepth(sal_Int16 nNewDepth) { - nDepth = nNewDepth; + mnNumberingDepth = nNewDepth; Invalidate(); } @@ -191,15 +193,15 @@ private: Paragraph( sal_Int16 nDepth ); Paragraph( const Paragraph& ) = delete; - Paragraph( const ParagraphData& ); + Paragraph( sal_Int16 nDepth, sal_Int16 nNumberingStartValue, bool bParaIsNumberingRestart); - sal_Int16 GetDepth() const { return nDepth; } + sal_Int16 GetNumberingDepth() const { return mnNumberingDepth; } sal_Int16 GetNumberingStartValue() const { return mnNumberingStartValue; } void SetNumberingStartValue( sal_Int16 nNumberingStartValue ); - bool IsParaIsNumberingRestart() const { return mbParaIsNumberingRestart; } - void SetParaIsNumberingRestart( bool bParaIsNumberingRestart ); + bool IsNumberingRestart() const { return mbNumberingRestart; } + void SetNumberingRestart( bool bRestart ); void SetFlag( ParaFlag nFlag ) { nFlags |= nFlag; } void RemoveFlag( ParaFlag nFlag ) { nFlags &= ~nFlag; } @@ -838,7 +840,7 @@ public: // Only for EditEngine mode void QuickInsertText( const OUString& rText, const ESelection& rSel ); void QuickDelete( const ESelection& rSel ); - /// Set attributes from rSet an all characters of nPara. + /// Set attributes from rSet on all characters of nPara. void SetCharAttribs(sal_Int32 nPara, const SfxItemSet& rSet); void RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich = 0 ); void QuickFormatDoc(); diff --git a/include/editeng/outlobj.hxx b/include/editeng/outlobj.hxx index 1703cf09cf34..bb3fbd41124a 100644 --- a/include/editeng/outlobj.hxx +++ b/include/editeng/outlobj.hxx @@ -19,8 +19,8 @@ #pragma once -#include #include +#include #include #include #include @@ -28,44 +28,10 @@ #include #include -class EditTextObject; -enum class OutlinerMode; -enum class TextRotation; - -/** - * This is the guts of OutlinerParaObject, refcounted and shared among - * multiple instances of OutlinerParaObject. - */ -struct EDITENG_DLLPUBLIC OutlinerParaObjData -{ - // data members - std::unique_ptr mpEditTextObject; - ParagraphDataVector maParagraphDataVector; - bool mbIsEditDoc; - - // constructor - OutlinerParaObjData( std::unique_ptr pEditTextObject, ParagraphDataVector&& rParagraphDataVector, bool bIsEditDoc ); - - OutlinerParaObjData( const OutlinerParaObjData& r ); - - OutlinerParaObjData( OutlinerParaObjData&& r ) = default; - - // assignment operator - OutlinerParaObjData& operator=(const OutlinerParaObjData& rCandidate) = delete; - - // destructor - ~OutlinerParaObjData(); - - bool operator==(const OutlinerParaObjData& rCandidate) const; - - // #i102062# - bool isWrongListEqual(const OutlinerParaObjData& rCompare) const; -}; - class EDITENG_DLLPUBLIC OutlinerParaObject { friend class std::optional; - ::o3tl::cow_wrapper< OutlinerParaObjData > mpImpl; + ::o3tl::cow_wrapper< EditTextObject > mpImpl; OutlinerParaObject(std::nullopt_t) noexcept : mpImpl(std::nullopt) {} @@ -74,8 +40,7 @@ friend class std::optional; public: // constructors/destructor - OutlinerParaObject(std::unique_ptr, ParagraphDataVector&&, bool bIsEditDoc); - OutlinerParaObject( std::unique_ptr ); + OutlinerParaObject(EditTextObject&&); OutlinerParaObject( const OutlinerParaObject&); OutlinerParaObject(OutlinerParaObject&&) noexcept; ~OutlinerParaObject(); @@ -105,9 +70,10 @@ public: // data read access sal_Int32 Count() const; - sal_Int16 GetDepth(sal_Int32 nPara) const; + sal_Int16 GetNumberingDepth(sal_Int32 nPara) const; + sal_Int16 GetNumberingStartValue(sal_Int32 nPara) const; + bool IsNumberingRestart(sal_Int32 nPara) const; const EditTextObject& GetTextObject() const; - const ParagraphData& GetParagraphData(sal_Int32 nIndex) const; // portion info support void ClearPortionInfo(); diff --git a/include/editeng/splwrap.hxx b/include/editeng/splwrap.hxx index 28a226add0ca..7ad1505a8251 100644 --- a/include/editeng/splwrap.hxx +++ b/include/editeng/splwrap.hxx @@ -24,7 +24,7 @@ #include #include #include -#include +#include // forward --------------------------------------------------------------- diff --git a/include/editeng/svxacorr.hxx b/include/editeng/svxacorr.hxx index 89df7eb25765..908317a6173a 100644 --- a/include/editeng/svxacorr.hxx +++ b/include/editeng/svxacorr.hxx @@ -77,13 +77,18 @@ enum class ACFlags : sal_uInt32 { TransliterateRTL = 0x00004000, // Transliterate RTL text ChgAngleQuotes = 0x00008000, // >>, << -> angle quotes in some languages SetDOIAttr = 0x00010000, // Set DOIAttribute + EsperantoHats = 0x00020000, // Cxapelo -> ĉapelo ChgWordLstLoad = 0x20000000, // Replacement list loaded CplSttLstLoad = 0x40000000, // Exception list for Capital letters Start loaded WordStartLstLoad = 0x80000000, // Exception list for Word Start loaded }; +constexpr sal_uInt32 AC_OPTION_MASK = 0x3ffff; +constexpr sal_uInt32 AC_LOAD_MASK = 0xe0000000; namespace o3tl { - template<> struct typed_flags : is_typed_flags {}; + template<> struct typed_flags : is_typed_flags + { + }; } enum class ACQuotes @@ -113,6 +118,12 @@ public: virtual bool SetINetAttr( sal_Int32 nStt, sal_Int32 nEnd, const OUString& rURL ) = 0; + // Gets the text of the paragraph being corrected. This is the same as the rTxt referenced + // passed into the AutoCorrect function, but it can sometimes change after performing + // modifications on the document if redlines are enabled. Eventually we should move towards + // always using this method to retrieve the text instead of the rTxt parameter. + virtual const OUString& GetText() const = 0; + // Return the text of a previous paragraph. // If no paragraph exits or just an empty one, then return an empty string. // The flag indicates: @@ -456,13 +467,13 @@ public: bool bAbbreviation = false); // Methods for the auto-correction - void FnCapitalStartWord( SvxAutoCorrDoc&, const OUString&, + void FnCapitalStartWord( SvxAutoCorrDoc&, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang ); bool FnChgOrdinalNumber( SvxAutoCorrDoc&, const OUString&, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang ); - bool FnChgToEnEmDash( SvxAutoCorrDoc&, const OUString&, + bool FnChgToEnEmDash( SvxAutoCorrDoc&, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang ); // Returns an updated position, at which the insertion/removal happened. It may be @@ -478,12 +489,14 @@ public: LanguageType eLang ); bool FnChgWeightUnderl( SvxAutoCorrDoc&, const OUString&, sal_Int32 nEndPos ); - void FnCapitalStartSentence( SvxAutoCorrDoc&, const OUString&, bool bNormalPos, + void FnCapitalStartSentence( SvxAutoCorrDoc&, bool bNormalPos, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang); - bool FnCorrectCapsLock( SvxAutoCorrDoc&, const OUString&, + bool FnCorrectCapsLock( SvxAutoCorrDoc&, sal_Int32 nSttPos, sal_Int32 nEndPos, LanguageType eLang ); + void FnAddEsperantoHats( SvxAutoCorrDoc&, sal_Int32 nStartPos, + sal_Int32& nEndPos ); static ACFlags GetDefaultFlags(); diff --git a/include/editeng/swafopt.hxx b/include/editeng/swafopt.hxx index a80a34fc072d..4d840e40e827 100644 --- a/include/editeng/swafopt.hxx +++ b/include/editeng/swafopt.hxx @@ -92,51 +92,56 @@ struct EDITENG_DLLPUBLIC SvxSwAutoFormatFlags sal_uInt8 nRightMargin; - bool bAutoCorrect : 1; - bool bCapitalStartSentence : 1; - bool bCapitalStartWord : 1; +#define SVX_SW_FLAG_ENTRIES(prefix, suffix) \ + prefix bAutoCorrect suffix; \ + prefix bCapitalStartSentence suffix; \ + prefix bCapitalStartWord suffix; \ + \ + prefix bChgUserColl suffix; \ + prefix bChgEnumNum suffix; \ + \ + prefix bAFormatByInput suffix; \ + prefix bDelEmptyNode suffix; \ + prefix bSetNumRule suffix; \ + prefix bSetNumRuleAfterSpace suffix; \ + \ + prefix bChgOrdinalNumber suffix; \ + prefix bChgToEnEmDash suffix; \ + prefix bAddNonBrkSpace suffix; \ + prefix bTransliterateRTL suffix; \ + prefix bChgAngleQuotes suffix; \ + prefix bEsperantoHats suffix; \ + prefix bChgWeightUnderl suffix; \ + prefix bSetINetAttr suffix; \ + prefix bSetDOIAttr suffix; \ + \ + prefix bSetBorder suffix; \ + prefix bCreateTable suffix; \ + prefix bReplaceStyles suffix; \ + prefix bReplaceStylesByInput suffix; \ + \ + prefix bWithRedlining suffix; \ + \ + prefix bRightMargin suffix; \ + \ + prefix bAutoCompleteWords suffix; \ + prefix bAutoCmpltCollectWords suffix; \ + prefix bAutoCmpltEndless suffix; \ + /* -- under NT here starts a new long */ \ + prefix bAutoCmpltAppendBlank suffix; \ + prefix bAutoCmpltShowAsTip suffix; \ + \ + prefix bAFormatDelSpacesAtSttEnd suffix; \ + prefix bAFormatDelSpacesBetweenLines suffix; \ + prefix bAFormatByInpDelSpacesAtSttEnd suffix; \ + prefix bAFormatByInpDelSpacesBetweenLines suffix; \ + \ + prefix bAutoCmpltKeepList suffix; - bool bChgUserColl : 1; - bool bChgEnumNum : 1; - - bool bAFormatByInput : 1; - bool bDelEmptyNode : 1; - bool bSetNumRule : 1; - bool bSetNumRuleAfterSpace : 1; - - bool bChgOrdinalNumber : 1; - bool bChgToEnEmDash : 1; - bool bAddNonBrkSpace : 1; - bool bTransliterateRTL : 1; - bool bChgAngleQuotes : 1; - bool bChgWeightUnderl : 1; - bool bSetINetAttr : 1; - bool bSetDOIAttr : 1; - - bool bSetBorder : 1; - bool bCreateTable : 1; - bool bReplaceStyles : 1; - bool bReplaceStylesByInput : 1; - - bool bWithRedlining : 1; - - bool bRightMargin : 1; - - bool bAutoCompleteWords : 1; - bool bAutoCmpltCollectWords : 1; - bool bAutoCmpltEndless : 1; -// -- under NT here starts a new long - bool bAutoCmpltAppendBlank : 1; - bool bAutoCmpltShowAsTip : 1; - - bool bAFormatDelSpacesAtSttEnd : 1; - bool bAFormatDelSpacesBetweenLines : 1; - bool bAFormatByInpDelSpacesAtSttEnd : 1; - bool bAFormatByInpDelSpacesBetweenLines : 1; - - bool bAutoCmpltKeepList : 1; + SVX_SW_FLAG_ENTRIES(bool, : 1) SvxSwAutoFormatFlags(); + void resetAllFlags(); }; #endif diff --git a/include/editeng/unoprnms.hxx b/include/editeng/unoprnms.hxx index 5b2e4e621ba5..5e3e8b38081f 100644 --- a/include/editeng/unoprnms.hxx +++ b/include/editeng/unoprnms.hxx @@ -320,6 +320,8 @@ inline constexpr OUString UNO_NAME_EDIT_CHAR_FONTPITCH = u"CharFontPitch"_ustr; inline constexpr OUString UNO_NAME_EDIT_CHAR_POSTURE = u"CharPosture"_ustr; inline constexpr OUString UNO_NAME_EDIT_CHAR_WEIGHT = u"CharWeight"_ustr; inline constexpr OUString UNO_NAME_EDIT_CHAR_FONTVARIATIONS = u"CharFontVariations"_ustr; +inline constexpr OUString UNO_NAME_EDIT_CHAR_FONTVARIATIONS_ASIAN = u"CharFontVariationsAsian"_ustr; +inline constexpr OUString UNO_NAME_EDIT_CHAR_FONTVARIATIONS_COMPLEX = u"CharFontVariationsComplex"_ustr; inline constexpr OUString UNO_NAME_EDIT_CHAR_OPTICALSIZING = u"CharOpticalSizing"_ustr; inline constexpr OUString UNO_NAME_EDIT_CHAR_LOCALE = u"CharLocale"_ustr; @@ -382,6 +384,7 @@ inline constexpr OUString UNO_NAME_GRAPHIC_GAMMA = u"Gamma"_ustr; inline constexpr OUString UNO_NAME_GRAPHIC_TRANSPARENCY = u"Transparency"_ustr; inline constexpr OUString UNO_NAME_GRAPHIC_COLOR_MODE = u"GraphicColorMode"_ustr; inline constexpr OUString UNO_NAME_GRAPHIC_GRAPHICCROP = u"GraphicCrop"_ustr; +inline constexpr OUString UNO_NAME_GRAPHIC_GRAPHICCLIPPOLYPOLYGON = u"GraphicClipPolyPolygon"_ustr; inline constexpr OUString UNO_NAME_OBJ_ISEMPTYPRESOBJ = u"IsEmptyPresentationObject"_ustr; diff --git a/include/editeng/unotext.hxx b/include/editeng/unotext.hxx index b1bc3d1f6667..d5a219d4e750 100644 --- a/include/editeng/unotext.hxx +++ b/include/editeng/unotext.hxx @@ -139,7 +139,9 @@ struct SfxItemPropertyMapEntry; { UNO_NAME_EDIT_CHAR_RUBY_POSITION, EE_CHAR_RUBY, ::cppu::UnoType::get(), 0, MID_RUBY_POSITION }, \ { UNO_NAME_EDIT_CHAR_SCRIPT_HINT, EE_CHAR_SCRIPT_HINT, ::cppu::UnoType::get(), 0, MID_SCRIPTHINT }, \ { UNO_NAME_EDIT_CHAR_OPTICALSIZING, EE_CHAR_OPTICALSIZING, ::cppu::UnoType::get(), 0, 0 }, \ - { UNO_NAME_EDIT_CHAR_FONTVARIATIONS, EE_CHAR_FONTVARIATIONS, ::cppu::UnoType::get(), 0, 0 } + { UNO_NAME_EDIT_CHAR_FONTVARIATIONS, EE_CHAR_FONTVARIATIONS, ::cppu::UnoType::get(), 0, 0 }, \ + { UNO_NAME_EDIT_CHAR_FONTVARIATIONS_ASIAN, EE_CHAR_FONTVARIATIONS_CJK, ::cppu::UnoType::get(), 0, 0 }, \ + { UNO_NAME_EDIT_CHAR_FONTVARIATIONS_COMPLEX, EE_CHAR_FONTVARIATIONS_CTL, ::cppu::UnoType::get(), 0, 0 } #define SVX_UNOEDIT_FONT_PROPERTIES \ diff --git a/include/filter/msfilter/rtfutil.hxx b/include/filter/msfilter/rtfutil.hxx index 94004d9778d0..530cf1ab556f 100644 --- a/include/filter/msfilter/rtfutil.hxx +++ b/include/filter/msfilter/rtfutil.hxx @@ -47,13 +47,6 @@ MSFILTER_DLLPUBLIC OString OutString(std::u16string_view rStr, rtl_TextEncoding MSFILTER_DLLPUBLIC OString OutStringUpr(std::string_view pToken, std::u16string_view rStr, rtl_TextEncoding eDestEnc); -/** - * Get the numeric value of a single character, representing a hex value. - * - * @return -1 on failure - */ -MSFILTER_DLLPUBLIC int AsHex(char ch); - /// Writes binary data as a hex dump. MSFILTER_DLLPUBLIC OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, SvStream* pStream = nullptr, sal_uInt32 nLimit = 64); diff --git a/include/filter/msfilter/svxmsbas.hxx b/include/filter/msfilter/svxmsbas.hxx index a5a62e0bd401..7f2aabcc90e8 100644 --- a/include/filter/msfilter/svxmsbas.hxx +++ b/include/filter/msfilter/svxmsbas.hxx @@ -51,13 +51,13 @@ public: { } // only for the export - copy or delete the saved VBA-macro-storage - // form the ObjectShell - // - returns a warning code if a modified basic exist, in all other + // from the ObjectShell + // - returns a warning code if a modified basic exists, in all other // cases return ERRCODE_NONE. ErrCode SaveOrDelMSVBAStorage(bool bSaveInto, const OUString& rStorageName); - // check if the MS-VBA-Storage exist in the RootStorage of the DocShell. - // If it exist, then return the WarningId for losing the information. + // check if the MS-VBA-Storage exists in the RootStorage of the DocShell. + // If it exists, then return the WarningId for losing the information. static ErrCode GetSaveWarningOfMSVBAStorage(SfxObjectShell& rDocS); static OUString GetMSBasicStorageName(); diff --git a/include/formula/FormulaCompiler.hxx b/include/formula/FormulaCompiler.hxx index 0adc678f75eb..66d4240a3ba4 100644 --- a/include/formula/FormulaCompiler.hxx +++ b/include/formula/FormulaCompiler.hxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -88,7 +89,7 @@ public: ExternalHashMap maReverseExternalHashMap; /// Hash map of ocExternal, AddIn String -> Filter String FormulaGrammar::Grammar meGrammar; /// Grammar, language and reference convention sal_uInt16 mnSymbols; /// Count of OpCode symbols - bool mbCore : 1; /// If mapping was setup by core, not filters + bool mbCore : 1; /// If mapping was set up by core, not filters bool mbEnglish : 1; /// If English symbols and external names bool mbEnglishLocale : 1; /// If English locale for numbers @@ -287,7 +288,7 @@ public: static sal_Unicode GetNativeSymbolChar( OpCode eOp ); static bool IsMatrixFunction(OpCode _eOpCode); // if a function _always_ returns a Matrix - SvNumFormatType GetNumFormatType() const { return nNumFmt; } + SvNumFormatType GetNumFormatType() const { return mnNumFmt; } bool CompileTokenArray(); void CreateStringFromTokenArray( OUString& rFormula ); @@ -296,6 +297,13 @@ public: const FormulaToken* CreateStringFromToken( OUStringBuffer& rBuffer, const FormulaToken* pToken, bool bAllowArrAdvance = false ); +private: + // Write one token, or the error string that stands in for it, and + // advance rpToken. When this returns false, the buffer holds the + // error string that replaces the whole formula. + bool AppendTokenOrError(OUStringBuffer& rBuffer, const FormulaToken*& rpToken); +public: + void AppendBoolean( OUStringBuffer& rBuffer, bool bVal ) const; void AppendDouble( OUStringBuffer& rBuffer, double fVal ) const; static void AppendString( OUStringBuffer& rBuffer, const OUString & rStr ); @@ -322,9 +330,11 @@ public: /** Sets the implicit intersection compute flag */ void SetComputeIIFlag(bool bSet) { mbComputeII = bSet; } - /** Sets the matrix flag for the formula*/ + /** Sets the matrix flag for the formula */ void SetMatrixFlag(bool bSet) { mbMatrixFlag = bSet; } + void SetPreferLocalNames(bool bSet) { mbPreferLocalNames = bSet; } + /** Separators mapped when loading opcodes from the resource, values other than RESOURCE_BASE may override the resource strings. Used by OpCodeList implementation via loadSymbols(). @@ -367,8 +377,10 @@ protected: void PutCode( FormulaTokenRef& ); void Factor(); void RangeLine(); + void SpillOperator(); void UnionLine(); void IntersectionLine(); + void CallLine(); void UnaryLine(); void PostOpLine(); void PowLine(); @@ -392,32 +404,32 @@ protected: virtual void AnnotateOperands() {} - OUString aCorrectedFormula; // autocorrected Formula - OUString aCorrectedSymbol; // autocorrected Symbol + OUString maCorrectedFormula; // autocorrected Formula + OUString maCorrectedSymbol; // autocorrected Symbol OpCodeMapPtr mxSymbols; // which symbols are used FormulaTokenRef mpToken; // current token - FormulaTokenRef pCurrentFactorToken; // current factor token (of Factor() method) - sal_uInt16 nCurrentFactorParam; // current factor token's parameter, 1-based - FormulaTokenArray* pArr; + FormulaTokenRef mpCurrentFactorToken; // current factor token (of Factor() method) + sal_uInt16 mnCurrentFactorParam; // current factor token's parameter, 1-based + FormulaTokenArray* mpArr; FormulaTokenArrayPlainIterator maArrIterator; FormulaTokenRef mpLastToken; // last token - FormulaToken** pCode; - FormulaArrayStack* pStack; + FormulaToken** mpCode; + FormulaArrayStack* mpStack; - OpCode eLastOp; - short nRecursion; // GetToken() recursions - SvNumFormatType nNumFmt; // set during CompileTokenArray() - sal_uInt16 pc; // program counter + OpCode meLastOp; + short mnRecursion; // GetToken() recursions + SvNumFormatType mnNumFmt; // set during CompileTokenArray() + sal_uInt16 mnPC; // program counter FormulaGrammar::Grammar meGrammar; // The grammar used, language plus convention. - bool bAutoCorrect; // whether to apply AutoCorrection - bool bCorrected; // AutoCorrection was applied - bool glSubTotal; // if code contains one or more subtotal functions - bool needsRPNTokenCheck; // whether to make FormulaTokenArray check all tokens at the end + bool mbAutoCorrect; // whether to apply AutoCorrection + bool mbCorrected; // AutoCorrection was applied + bool mbGlSubTotal; // if code contains one or more subtotal functions + bool mbNeedsRPNTokenCheck; // whether to make FormulaTokenArray check all tokens at the end bool mbJumpCommandReorder; /// Whether or not to reorder RPN for jump commands. bool mbStopOnError; /// Whether to stop compilation on first encountered error. @@ -425,14 +437,20 @@ protected: bool mbComputeII; // whether to attempt computing implicit intersection ranges while building the RPN array. bool mbMatrixFlag; // whether the formula is a matrix formula (needed for II computation) - struct LambdaFunc + bool mbPreferLocalNames; // Whether local names/bindings have priority over built-ins + + struct BindingsLayer { - bool bInLambdaFunction = false; - short nBracketPos = 0; - short nParaPos = 0; - short nParaCount = 3; // minimum required parameter count: 3 - std::unordered_set aNameSet; - } m_aLambda; + OpCode eOpCode; // the OpCode that applies to this layer; should be ocLet or ocLambda + short nBracketPos; // how deep the nesting is to reach this layer + short nParaPos; // the current parameter position; starts at 1 + short nParaCount; // the number of parameters in this layer + std::unordered_set aNameSet; // a set of names bound in this layer + }; + + // a stack keeping track of names bound using LET or LAMBDA + std::forward_list maBindings; + bool mIsInBinding = false; // true iff the layer we're currently working on is a binding layer // ODF version at time of saving. Set by ScXMLExport::WriteCell(). std::optional< SvtSaveOptions::ODFSaneDefaultVersion > m_oODFSavingVersion; @@ -474,21 +492,21 @@ private: CurrentFactor& operator=( const CurrentFactor& ) = delete; public: explicit CurrentFactor( FormulaCompiler* pComp ) - : pPrevFac( pComp->pCurrentFactorToken ) - , nPrevParam( pComp->nCurrentFactorParam ) + : pPrevFac( pComp->mpCurrentFactorToken ) + , nPrevParam( pComp->mnCurrentFactorParam ) , pCompiler( pComp ) {} ~CurrentFactor() { - pCompiler->pCurrentFactorToken = pPrevFac; - pCompiler->nCurrentFactorParam = nPrevParam; + pCompiler->mpCurrentFactorToken = pPrevFac; + pCompiler->mnCurrentFactorParam = nPrevParam; } // yes, this operator= may modify the RValue void operator=( FormulaTokenRef const & r ) { pCompiler->ForceArrayOperator( r ); - pCompiler->pCurrentFactorToken = r; - pCompiler->nCurrentFactorParam = 0; + pCompiler->mpCurrentFactorToken = r; + pCompiler->mnCurrentFactorParam = 0; } void operator=( FormulaToken* p ) { @@ -496,9 +514,9 @@ private: *this = xTemp; } operator FormulaTokenRef&() - { return pCompiler->pCurrentFactorToken; } + { return pCompiler->mpCurrentFactorToken; } FormulaToken* operator->() - { return pCompiler->pCurrentFactorToken.operator->(); } + { return pCompiler->mpCurrentFactorToken.operator->(); } operator FormulaToken*() { return operator->(); } }; diff --git a/include/formula/callable.hxx b/include/formula/callable.hxx new file mode 100644 index 000000000000..ae840fbd34a5 --- /dev/null +++ b/include/formula/callable.hxx @@ -0,0 +1,109 @@ +/* -*- 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 . + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace formula +{ +/// represents a function that can be called to produce a result +class FORMULA_DLLPUBLIC FormulaCallable +{ +private: + mutable oslInterlockedCount mnRefCnt; + +protected: + FormulaCallable() + : mnRefCnt(0) + { + } + + FormulaCallable(const FormulaCallable&) + : mnRefCnt(0) + { + } + +public: + void IncRef() const { osl_atomic_increment(&mnRefCnt); } + void DecRef() const + { + if (!osl_atomic_decrement(&mnRefCnt)) + const_cast(this)->Delete(); + } + void Delete() { delete this; } + + virtual ~FormulaCallable() {} + virtual OpCode GetOpCode() const { return ocNone; } +}; + +inline void intrusive_ptr_add_ref(const FormulaCallable* p) { p->IncRef(); } +inline void intrusive_ptr_release(const FormulaCallable* p) { p->DecRef(); } + +/// a callable built-in function +class FORMULA_DLLPUBLIC FormulaBuiltInFunction : public FormulaCallable +{ +private: + OpCode meOpCode; + + /// no copy constructor; copies are not allowed! + FormulaBuiltInFunction(OpCode eOpCode) + : FormulaCallable() + , meOpCode(eOpCode) + { + } + +public: + /// use Get instead of constructing new objects + static FormulaCallableRef Get(OpCode eOpCode); + + virtual OpCode GetOpCode() const override { return meOpCode; } +}; + +/// a callable external function +class FORMULA_DLLPUBLIC FormulaExternalFunction : public FormulaCallable +{ +private: + OUString maName; + +public: + FormulaExternalFunction(const OUString& aName) + : FormulaCallable() + , maName(aName) + { + } + FormulaExternalFunction(const FormulaExternalFunction& r) + : FormulaCallable(r) + , maName(r.maName) + { + } + + virtual OpCode GetOpCode() const override { return ocExternal; } + const OUString& GetName() const { return maName; } + FormulaCallable* Clone() const { return new FormulaExternalFunction(*this); } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/formula/compiler.hxx b/include/formula/compiler.hxx deleted file mode 100644 index d10c5b937793..000000000000 --- a/include/formula/compiler.hxx +++ /dev/null @@ -1,551 +0,0 @@ -/* -*- 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 . - */ - -#pragma once - -/* Central definition of OpCodes for spreadsheet functions */ - -/*** Special commands ***/ -#define SC_OPCODE_PUSH 0 /* internal commands */ -// used to be SC_OPCODE_CALL -#define SC_OPCODE_STOP 2 -#define SC_OPCODE_EXTERNAL 3 -#define SC_OPCODE_NAME 4 -#define SC_OPCODE_EXTERNAL_REF 5 -#define SC_OPCODE_IF 6 /* jump commands */ -#define SC_OPCODE_IF_ERROR 7 -#define SC_OPCODE_IF_NA 8 -#define SC_OPCODE_CHOOSE 9 -#define SC_OPCODE_OPEN 10 /* parentheses and separators */ -#define SC_OPCODE_CLOSE 11 -#define SC_OPCODE_SEP 12 -#define SC_OPCODE_MISSING 13 /* special OpCodes */ -#define SC_OPCODE_BAD 14 -#define SC_OPCODE_STRINGXML 15 -#define SC_OPCODE_SPACES 16 -#define SC_OPCODE_WHITESPACE 17 -#define SC_OPCODE_MAT_REF 18 -#define SC_OPCODE_DB_AREA 19 /* additional access operators */ -#define SC_OPCODE_TABLE_REF 20 -#define SC_OPCODE_MACRO 21 -#define SC_OPCODE_COL_ROW_NAME 22 -#define SC_OPCODE_COL_ROW_NAME_AUTO 23 -#define SC_OPCODE_PERCENT_SIGN 24 /* operator _follows_ value */ -#define SC_OPCODE_ARRAY_OPEN 25 -#define SC_OPCODE_ARRAY_CLOSE 26 -#define SC_OPCODE_ARRAY_ROW_SEP 27 -#define SC_OPCODE_ARRAY_COL_SEP 28 /* some convs use sep != col_sep */ -#define SC_OPCODE_TABLE_REF_OPEN 29 -#define SC_OPCODE_TABLE_REF_CLOSE 30 -#define SC_OPCODE_TABLE_REF_ITEM_ALL 31 -#define SC_OPCODE_TABLE_REF_ITEM_HEADERS 32 -#define SC_OPCODE_TABLE_REF_ITEM_DATA 33 -#define SC_OPCODE_TABLE_REF_ITEM_TOTALS 34 -#define SC_OPCODE_TABLE_REF_ITEM_THIS_ROW 35 -#define SC_OPCODE_STOP_DIV 36 -#define SC_OPCODE_SKIP 37 /* used to skip raw tokens during string compilation */ -#define SC_OPCODE_STRINGNAME 38 /* special OpCode for lambda function names */ -#define SC_OPCODE_LET 39 -#define SC_OPCODE_DP_FIELD 40 - -/*** error constants #... ***/ -#define SC_OPCODE_START_ERRORS 41 -#define SC_OPCODE_ERROR_NULL 41 -#define SC_OPCODE_ERROR_DIVZERO 42 -#define SC_OPCODE_ERROR_VALUE 43 -#define SC_OPCODE_ERROR_REF 44 -#define SC_OPCODE_ERROR_NAME 45 -#define SC_OPCODE_ERROR_NUM 46 -#define SC_OPCODE_ERROR_NA 47 -#define SC_OPCODE_STOP_ERRORS 48 - -/*** Binary operators ***/ -#define SC_OPCODE_START_BIN_OP 50 -#define SC_OPCODE_ADD 50 -#define SC_OPCODE_SUB 51 -#define SC_OPCODE_MUL 52 -#define SC_OPCODE_DIV 53 -#define SC_OPCODE_AMPERSAND 54 -#define SC_OPCODE_POW 55 -#define SC_OPCODE_EQUAL 56 -#define SC_OPCODE_NOT_EQUAL 57 -#define SC_OPCODE_LESS 58 -#define SC_OPCODE_GREATER 59 -#define SC_OPCODE_LESS_EQUAL 60 -#define SC_OPCODE_GREATER_EQUAL 61 -#define SC_OPCODE_AND 62 -#define SC_OPCODE_OR 63 -#define SC_OPCODE_INTERSECT 64 -#define SC_OPCODE_UNION 65 -#define SC_OPCODE_RANGE 66 -#define SC_OPCODE_STOP_BIN_OP 67 - -/* NOTE: binary and unary operators must be in sequence for compiler! */ - -/*** Unary operators ***/ -#define SC_OPCODE_START_UN_OP 70 -#define SC_OPCODE_NEG_SUB 70 -#define SC_OPCODE_STOP_UN_OP 71 - -#define SC_OPCODE_START_FUNCTION 75 - -/*** Functions without parameters ***/ -#define SC_OPCODE_START_NO_PAR 75 -#define SC_OPCODE_PI 75 -#define SC_OPCODE_RANDOM 76 -#define SC_OPCODE_TRUE 77 -#define SC_OPCODE_FALSE 78 -#define SC_OPCODE_GET_ACT_DATE 79 -#define SC_OPCODE_GET_ACT_TIME 80 -#define SC_OPCODE_NO_VALUE 81 -#define SC_OPCODE_CURRENT 82 -#define SC_OPCODE_RANDOM_NV 83 -#define SC_OPCODE_STOP_NO_PAR 84 - -/*** Functions with one parameter ***/ -#define SC_OPCODE_START_1_PAR 90 -#define SC_OPCODE_DEG 90 /* trigonometric */ -#define SC_OPCODE_RAD 91 -#define SC_OPCODE_SIN 92 -#define SC_OPCODE_COS 93 -#define SC_OPCODE_TAN 94 -#define SC_OPCODE_COT 95 -#define SC_OPCODE_ARC_SIN 96 -#define SC_OPCODE_ARC_COS 97 -#define SC_OPCODE_ARC_TAN 98 -#define SC_OPCODE_ARC_COT 99 -#define SC_OPCODE_SIN_HYP 100 -#define SC_OPCODE_COS_HYP 101 -#define SC_OPCODE_TAN_HYP 102 -#define SC_OPCODE_COT_HYP 103 -#define SC_OPCODE_ARC_SIN_HYP 104 /* transcendent */ -#define SC_OPCODE_ARC_COS_HYP 105 -#define SC_OPCODE_ARC_TAN_HYP 106 -#define SC_OPCODE_ARC_COT_HYP 107 -#define SC_OPCODE_COSECANT 108 -#define SC_OPCODE_SECANT 109 -#define SC_OPCODE_COSECANT_HYP 110 -#define SC_OPCODE_SECANT_HYP 111 -#define SC_OPCODE_EXP 112 -#define SC_OPCODE_LN 113 -#define SC_OPCODE_SQRT 114 -#define SC_OPCODE_FACT 115 -#define SC_OPCODE_GET_YEAR 116 /* date and time */ -#define SC_OPCODE_GET_MONTH 117 -#define SC_OPCODE_GET_DAY 118 -#define SC_OPCODE_GET_HOUR 119 -#define SC_OPCODE_GET_MIN 120 -#define SC_OPCODE_GET_SEC 121 -#define SC_OPCODE_PLUS_MINUS 122 /* miscellaneous */ -#define SC_OPCODE_ABS 123 -#define SC_OPCODE_INT 124 -#define SC_OPCODE_PHI 125 -#define SC_OPCODE_GAUSS 126 -#define SC_OPCODE_IS_EMPTY 127 /* obtain type */ -#define SC_OPCODE_IS_STRING 128 -#define SC_OPCODE_IS_NON_STRING 129 -#define SC_OPCODE_IS_LOGICAL 130 -#define SC_OPCODE_TYPE 131 -#define SC_OPCODE_IS_REF 132 -#define SC_OPCODE_IS_VALUE 133 -#define SC_OPCODE_IS_FORMULA 134 -#define SC_OPCODE_IS_NV 135 -#define SC_OPCODE_IS_ERR 136 -#define SC_OPCODE_IS_ERROR 137 -#define SC_OPCODE_IS_EVEN 138 -#define SC_OPCODE_IS_ODD 139 -#define SC_OPCODE_N 140 -#define SC_OPCODE_GET_DATE_VALUE 141 /* string functions */ -#define SC_OPCODE_GET_TIME_VALUE 142 -#define SC_OPCODE_CODE 143 -#define SC_OPCODE_TRIM 144 -#define SC_OPCODE_UPPER 145 -#define SC_OPCODE_PROPER 146 -#define SC_OPCODE_LOWER 147 -#define SC_OPCODE_LEN 148 -#define SC_OPCODE_T 149 /* miscellaneous, part 21 */ -#define SC_OPCODE_VALUE 150 -#define SC_OPCODE_CLEAN 151 -#define SC_OPCODE_CHAR 152 -#define SC_OPCODE_LOG10 153 -#define SC_OPCODE_EVEN 154 -#define SC_OPCODE_ODD 155 -#define SC_OPCODE_STD_NORM_DIST 156 -#define SC_OPCODE_FISHER 157 -#define SC_OPCODE_FISHER_INV 158 -#define SC_OPCODE_S_NORM_INV 159 -#define SC_OPCODE_GAMMA_LN 160 -#define SC_OPCODE_ERROR_TYPE 161 -#define SC_OPCODE_FORMULA 163 -#define SC_OPCODE_ARABIC 164 -#define SC_OPCODE_INFO 165 -#define SC_OPCODE_BAHTTEXT 166 -#define SC_OPCODE_JIS 167 -#define SC_OPCODE_ASC 168 -#define SC_OPCODE_UNICODE 169 -#define SC_OPCODE_UNICHAR 170 -#define SC_OPCODE_GAMMA 171 -#define SC_OPCODE_GAMMA_LN_MS 172 -#define SC_OPCODE_ERF_MS 173 -#define SC_OPCODE_ERFC_MS 174 -#define SC_OPCODE_ERROR_TYPE_ODF 175 -#define SC_OPCODE_ENCODEURL 176 -#define SC_OPCODE_ISOWEEKNUM 177 -#define SC_OPCODE_NOT 178 -#define SC_OPCODE_NEG 179 -#define SC_OPCODE_STOP_1_PAR 180 - -/*** Functions with more than one parameters ***/ -#define SC_OPCODE_START_2_PAR 201 -#define SC_OPCODE_ARC_TAN_2 201 -#define SC_OPCODE_CEIL 202 -#define SC_OPCODE_FLOOR 203 -#define SC_OPCODE_ROUND 204 -#define SC_OPCODE_ROUND_UP 205 -#define SC_OPCODE_ROUND_DOWN 206 -#define SC_OPCODE_TRUNC 207 -#define SC_OPCODE_LOG 208 -#define SC_OPCODE_POWER 209 -#define SC_OPCODE_GCD 210 -#define SC_OPCODE_LCM 211 -#define SC_OPCODE_MOD 212 -#define SC_OPCODE_SUM_PRODUCT 213 -#define SC_OPCODE_SUM_SQ 214 -#define SC_OPCODE_SUM_X2MY2 215 -#define SC_OPCODE_SUM_X2DY2 216 -#define SC_OPCODE_SUM_XMY2 217 -#define SC_OPCODE_GET_DATE 218 -#define SC_OPCODE_GET_TIME 219 -#define SC_OPCODE_GET_DIFF_DATE 220 -#define SC_OPCODE_GET_DIFF_DATE_360 221 -#define SC_OPCODE_MIN 222 -#define SC_OPCODE_MAX 223 -#define SC_OPCODE_SUM 224 -#define SC_OPCODE_PRODUCT 225 -#define SC_OPCODE_AVERAGE 226 -#define SC_OPCODE_COUNT 227 -#define SC_OPCODE_COUNT_2 228 -#define SC_OPCODE_NPV 229 -#define SC_OPCODE_IRR 230 -#define SC_OPCODE_VAR 231 -#define SC_OPCODE_VAR_P 232 -#define SC_OPCODE_ST_DEV 233 -#define SC_OPCODE_ST_DEV_P 234 -#define SC_OPCODE_B 235 -#define SC_OPCODE_NORM_DIST 236 -#define SC_OPCODE_EXP_DIST 237 -#define SC_OPCODE_BINOM_DIST 238 -#define SC_OPCODE_POISSON_DIST 239 -#define SC_OPCODE_COMBIN 240 -#define SC_OPCODE_COMBIN_A 241 -#define SC_OPCODE_PERMUT 242 -#define SC_OPCODE_PERMUTATION_A 243 -#define SC_OPCODE_PV 244 -#define SC_OPCODE_SYD 245 -#define SC_OPCODE_DDB 246 -#define SC_OPCODE_DB 247 -#define SC_OPCODE_VBD 248 -#define SC_OPCODE_PDURATION 249 -#define SC_OPCODE_SLN 250 -#define SC_OPCODE_PMT 251 -#define SC_OPCODE_COLUMNS 252 -#define SC_OPCODE_ROWS 253 -#define SC_OPCODE_COLUMN 254 -#define SC_OPCODE_ROW 255 -#define SC_OPCODE_RRI 256 -#define SC_OPCODE_FV 257 -#define SC_OPCODE_NPER 258 -#define SC_OPCODE_RATE 259 -#define SC_OPCODE_IPMT 260 -#define SC_OPCODE_PPMT 261 -#define SC_OPCODE_CUM_IPMT 262 -#define SC_OPCODE_CUM_PRINC 263 -#define SC_OPCODE_EFFECT 264 -#define SC_OPCODE_NOMINAL 265 -#define SC_OPCODE_SUB_TOTAL 266 -#define SC_OPCODE_DB_SUM 267 /* database functions */ -#define SC_OPCODE_DB_COUNT 268 -#define SC_OPCODE_DB_COUNT_2 269 -#define SC_OPCODE_DB_AVERAGE 270 -#define SC_OPCODE_DB_GET 271 -#define SC_OPCODE_DB_MAX 272 -#define SC_OPCODE_DB_MIN 273 -#define SC_OPCODE_DB_PRODUCT 274 -#define SC_OPCODE_DB_STD_DEV 275 -#define SC_OPCODE_DB_STD_DEV_P 276 -#define SC_OPCODE_DB_VAR 277 -#define SC_OPCODE_DB_VAR_P 278 -#define SC_OPCODE_INDIRECT 279 /* management functions */ -#define SC_OPCODE_ADDRESS 280 -#define SC_OPCODE_MATCH 281 -#define SC_OPCODE_COUNT_EMPTY_CELLS 282 -#define SC_OPCODE_COUNT_IF 283 -#define SC_OPCODE_SUM_IF 284 -#define SC_OPCODE_LOOKUP 285 -#define SC_OPCODE_V_LOOKUP 286 -#define SC_OPCODE_H_LOOKUP 287 -#define SC_OPCODE_MULTI_AREA 288 -#define SC_OPCODE_OFFSET 289 -#define SC_OPCODE_INDEX 290 -#define SC_OPCODE_AREAS 291 -#define SC_OPCODE_CURRENCY 292 /* string functions */ -#define SC_OPCODE_REPLACE 293 -#define SC_OPCODE_FIXED 294 -#define SC_OPCODE_FIND 295 -#define SC_OPCODE_EXACT 296 -#define SC_OPCODE_LEFT 297 -#define SC_OPCODE_RIGHT 298 -#define SC_OPCODE_SEARCH 299 -#define SC_OPCODE_MID 300 -#define SC_OPCODE_TEXT 301 -#define SC_OPCODE_SUBSTITUTE 302 -#define SC_OPCODE_REPT 303 -#define SC_OPCODE_CONCAT 304 -#define SC_OPCODE_MAT_VALUE 305 /* matrix functions */ -#define SC_OPCODE_MAT_DET 306 -#define SC_OPCODE_MAT_INV 307 -#define SC_OPCODE_MAT_MULT 308 -#define SC_OPCODE_MAT_TRANS 309 -#define SC_OPCODE_MATRIX_UNIT 310 -#define SC_OPCODE_BACK_SOLVER 311 /* BackSolver */ -#define SC_OPCODE_HYP_GEOM_DIST 312 /* statistical functions */ -#define SC_OPCODE_LOG_NORM_DIST 313 -#define SC_OPCODE_T_DIST 314 -#define SC_OPCODE_F_DIST 315 -#define SC_OPCODE_CHI_DIST 316 -#define SC_OPCODE_WEIBULL 317 -#define SC_OPCODE_NEG_BINOM_VERT 318 -#define SC_OPCODE_CRIT_BINOM 319 -#define SC_OPCODE_KURT 320 -#define SC_OPCODE_HAR_MEAN 321 -#define SC_OPCODE_GEO_MEAN 322 -#define SC_OPCODE_STANDARD 323 -#define SC_OPCODE_AVE_DEV 324 -#define SC_OPCODE_SKEW 325 -#define SC_OPCODE_DEV_SQ 326 -#define SC_OPCODE_MEDIAN 327 -#define SC_OPCODE_MODAL_VALUE 328 -#define SC_OPCODE_Z_TEST 329 -#define SC_OPCODE_T_TEST 330 -#define SC_OPCODE_RANK 331 -#define SC_OPCODE_PERCENTILE 332 -#define SC_OPCODE_PERCENT_RANK 333 -#define SC_OPCODE_LARGE 334 -#define SC_OPCODE_SMALL 335 -#define SC_OPCODE_FREQUENCY 336 -#define SC_OPCODE_QUARTILE 337 -#define SC_OPCODE_NORM_INV 338 -#define SC_OPCODE_CONFIDENCE 339 -#define SC_OPCODE_F_TEST 340 -#define SC_OPCODE_TRIM_MEAN 341 -#define SC_OPCODE_PROB 342 -#define SC_OPCODE_CORREL 343 -#define SC_OPCODE_COVAR 344 -#define SC_OPCODE_PEARSON 345 -#define SC_OPCODE_RSQ 346 -#define SC_OPCODE_STEYX 347 -#define SC_OPCODE_SLOPE 348 -#define SC_OPCODE_INTERCEPT 349 -#define SC_OPCODE_TREND 350 -#define SC_OPCODE_GROWTH 351 -#define SC_OPCODE_LINEST 352 -#define SC_OPCODE_LOGEST 353 -#define SC_OPCODE_FORECAST 354 -#define SC_OPCODE_CHI_INV 355 -#define SC_OPCODE_GAMMA_DIST 356 -#define SC_OPCODE_GAMMA_INV 357 -#define SC_OPCODE_T_INV 358 -#define SC_OPCODE_F_INV 359 -#define SC_OPCODE_CHI_TEST 360 -#define SC_OPCODE_LOG_INV 361 -#define SC_OPCODE_TABLE_OP 362 -#define SC_OPCODE_BETA_DIST 363 -#define SC_OPCODE_BETA_INV 364 -#define SC_OPCODE_WEEK 365 /* miscellaneous */ -#define SC_OPCODE_GET_DAY_OF_WEEK 366 -#define SC_OPCODE_NO_NAME 367 -#define SC_OPCODE_STYLE 368 -#define SC_OPCODE_DDE 369 -#define SC_OPCODE_BASE 370 -#define SC_OPCODE_SHEET 371 -#define SC_OPCODE_SHEETS 372 -#define SC_OPCODE_MIN_A 373 -#define SC_OPCODE_MAX_A 374 -#define SC_OPCODE_AVERAGE_A 375 -#define SC_OPCODE_ST_DEV_A 376 -#define SC_OPCODE_ST_DEV_P_A 377 -#define SC_OPCODE_VAR_A 378 -#define SC_OPCODE_VAR_P_A 379 -#define SC_OPCODE_EASTERSUNDAY 380 -#define SC_OPCODE_DECIMAL 381 -#define SC_OPCODE_CONVERT_OOO 382 -#define SC_OPCODE_ROMAN 383 -#define SC_OPCODE_MIRR 384 -#define SC_OPCODE_CELL 385 -#define SC_OPCODE_ISPMT 386 -#define SC_OPCODE_HYPERLINK 387 -#define SC_OPCODE_X_LOOKUP 388 -#define SC_OPCODE_X_MATCH 389 -#define SC_OPCODE_GET_PIVOT_DATA 390 -#define SC_OPCODE_EUROCONVERT 391 -#define SC_OPCODE_NUMBERVALUE 392 -#define SC_OPCODE_CHISQ_DIST 393 -#define SC_OPCODE_CHISQ_INV 394 -#define SC_OPCODE_BITAND 395 -#define SC_OPCODE_BITOR 396 -#define SC_OPCODE_BITXOR 397 -#define SC_OPCODE_BITRSHIFT 398 -#define SC_OPCODE_BITLSHIFT 399 -#define SC_OPCODE_GET_DATEDIF 400 -#define SC_OPCODE_XOR 401 -#define SC_OPCODE_AVERAGE_IF 402 -#define SC_OPCODE_SUM_IFS 403 -#define SC_OPCODE_AVERAGE_IFS 404 -#define SC_OPCODE_COUNT_IFS 405 -#define SC_OPCODE_SKEWP 406 -#define SC_OPCODE_LENB 407 -#define SC_OPCODE_RIGHTB 408 -#define SC_OPCODE_LEFTB 409 -#define SC_OPCODE_MIDB 410 -#define SC_OPCODE_FILTERXML 411 -#define SC_OPCODE_WEBSERVICE 412 -#define SC_OPCODE_COVARIANCE_S 413 -#define SC_OPCODE_COVARIANCE_P 414 -#define SC_OPCODE_ST_DEV_P_MS 415 -#define SC_OPCODE_ST_DEV_S 416 -#define SC_OPCODE_VAR_P_MS 417 -#define SC_OPCODE_VAR_S 418 -#define SC_OPCODE_BETA_DIST_MS 419 -#define SC_OPCODE_BETA_INV_MS 420 -#define SC_OPCODE_BINOM_DIST_MS 421 -#define SC_OPCODE_BINOM_INV 422 -#define SC_OPCODE_CHI_DIST_MS 423 -#define SC_OPCODE_CHI_INV_MS 424 -#define SC_OPCODE_CHI_TEST_MS 425 -#define SC_OPCODE_CHISQ_DIST_MS 426 -#define SC_OPCODE_CHISQ_INV_MS 427 -#define SC_OPCODE_CONFIDENCE_N 428 -#define SC_OPCODE_CONFIDENCE_T 429 -#define SC_OPCODE_F_DIST_LT 430 -#define SC_OPCODE_F_DIST_RT 431 -#define SC_OPCODE_F_INV_LT 432 -#define SC_OPCODE_F_INV_RT 433 -#define SC_OPCODE_F_TEST_MS 434 -#define SC_OPCODE_EXP_DIST_MS 435 -#define SC_OPCODE_HYP_GEOM_DIST_MS 436 -#define SC_OPCODE_POISSON_DIST_MS 437 -#define SC_OPCODE_WEIBULL_MS 438 -#define SC_OPCODE_GAMMA_DIST_MS 439 -#define SC_OPCODE_GAMMA_INV_MS 440 -#define SC_OPCODE_LOG_NORM_DIST_MS 441 -#define SC_OPCODE_LOG_INV_MS 442 -#define SC_OPCODE_NORM_DIST_MS 443 -#define SC_OPCODE_NORM_INV_MS 444 -#define SC_OPCODE_STD_NORM_DIST_MS 445 -#define SC_OPCODE_S_NORM_INV_MS 446 -#define SC_OPCODE_T_DIST_MS 447 -#define SC_OPCODE_T_DIST_RT 448 -#define SC_OPCODE_T_DIST_2T 449 -#define SC_OPCODE_T_INV_2T 450 -#define SC_OPCODE_T_INV_MS 451 -#define SC_OPCODE_T_TEST_MS 452 -#define SC_OPCODE_PERCENTILE_INC 453 -#define SC_OPCODE_PERCENT_RANK_INC 454 -#define SC_OPCODE_QUARTILE_INC 455 -#define SC_OPCODE_RANK_EQ 456 -#define SC_OPCODE_PERCENTILE_EXC 457 -#define SC_OPCODE_PERCENT_RANK_EXC 458 -#define SC_OPCODE_QUARTILE_EXC 459 -#define SC_OPCODE_RANK_AVG 460 -#define SC_OPCODE_MODAL_VALUE_MS 461 -#define SC_OPCODE_MODAL_VALUE_MULTI 462 -#define SC_OPCODE_NEG_BINOM_DIST_MS 463 -#define SC_OPCODE_Z_TEST_MS 464 -#define SC_OPCODE_CEIL_MS 465 -#define SC_OPCODE_CEIL_ISO 466 -#define SC_OPCODE_FLOOR_MS 467 -#define SC_OPCODE_NETWORKDAYS_MS 468 -#define SC_OPCODE_WORKDAY_MS 469 -#define SC_OPCODE_AGGREGATE 470 -#define SC_OPCODE_COLOR 471 -#define SC_OPCODE_CEIL_MATH 472 -#define SC_OPCODE_CEIL_PRECISE 473 -#define SC_OPCODE_NETWORKDAYS 474 -#define SC_OPCODE_FLOOR_MATH 475 -#define SC_OPCODE_FLOOR_PRECISE 476 -#define SC_OPCODE_RAWSUBTRACT 477 -#define SC_OPCODE_WEEKNUM_OOO 478 -#define SC_OPCODE_FORECAST_ETS_ADD 479 -#define SC_OPCODE_FORECAST_ETS_SEA 480 -#define SC_OPCODE_FORECAST_ETS_MUL 481 -#define SC_OPCODE_FORECAST_ETS_PIA 482 -#define SC_OPCODE_FORECAST_ETS_PIM 483 -#define SC_OPCODE_FORECAST_ETS_STA 484 -#define SC_OPCODE_FORECAST_ETS_STM 485 -#define SC_OPCODE_FORECAST_LIN 486 -#define SC_OPCODE_CONCAT_MS 487 -#define SC_OPCODE_TEXTJOIN_MS 488 -#define SC_OPCODE_IFS_MS 489 -#define SC_OPCODE_SWITCH_MS 490 -#define SC_OPCODE_MINIFS_MS 491 -#define SC_OPCODE_MAXIFS_MS 492 -#define SC_OPCODE_ROUNDSIG 493 -#define SC_OPCODE_REPLACEB 494 -#define SC_OPCODE_FINDB 495 -#define SC_OPCODE_SEARCHB 496 -#define SC_OPCODE_REGEX 497 -#define SC_OPCODE_FOURIER 498 -#define SC_OPCODE_RANDBETWEEN_NV 499 -#define SC_OPCODE_FILTER 500 -#define SC_OPCODE_SORT 501 -#define SC_OPCODE_SORTBY 502 -#define SC_OPCODE_MAT_SEQUENCE 503 -#define SC_OPCODE_RANDARRAY 504 -#define SC_OPCODE_CHOOSECOLS 505 -#define SC_OPCODE_CHOOSEROWS 506 -#define SC_OPCODE_DROP 507 -#define SC_OPCODE_EXPAND 508 -#define SC_OPCODE_HSTACK 509 -#define SC_OPCODE_VSTACK 510 -#define SC_OPCODE_TAKE 511 -#define SC_OPCODE_TEXTAFTER 512 -#define SC_OPCODE_TEXTBEFORE 513 -#define SC_OPCODE_TEXTSPLIT 514 -#define SC_OPCODE_TOCOL 515 -#define SC_OPCODE_TOROW 516 -#define SC_OPCODE_UNIQUE 517 -#define SC_OPCODE_WRAPCOLS 518 -#define SC_OPCODE_WRAPROWS 519 -#define SC_OPCODE_STOP_2_PAR 520 /* last function with two or more parameters' OpCode + 1 */ - -#define SC_OPCODE_STOP_FUNCTION SC_OPCODE_STOP_2_PAR /* last function's OpCode + 1 */ -#define SC_OPCODE_LAST_OPCODE_ID (SC_OPCODE_STOP_FUNCTION - 1) /* last OpCode */ - -/*** Internal ***/ -#define SC_OPCODE_INTERNAL_BEGIN 9999 -#define SC_OPCODE_TTT 9999 -#define SC_OPCODE_DEBUG_VAR 10000 -#define SC_OPCODE_INTERNAL_END 10000 - -/*** from here on ExtraData contained ***/ -#define SC_OPCODE_DATA_TOKEN_1 10001 - -#define SC_OPCODE_NONE 0xFFFF - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/formula/errorcodes.hxx b/include/formula/errorcodes.hxx index 80ba58fff488..ad6493905d07 100644 --- a/include/formula/errorcodes.hxx +++ b/include/formula/errorcodes.hxx @@ -87,6 +87,10 @@ enum class FormulaError : sal_uInt16 // Interpreter: signal result not available because updating links is not // allowed (yet) and tell to try hybrid string as result. LinkFormulaNeedingCheck = 540, +// Array/matrix formula result can't spill because target cells are not empty. + Spill = 541, +// Expected function here; signaled when attempting to call a non-function + NotAFunction = 542, // Interpreter: NA() not available condition, not a real error NotAvailable = 0x7fff @@ -176,6 +180,8 @@ inline bool isPublishedFormulaError( FormulaError nErr ) case FormulaError::MatrixSize: case FormulaError::LinkFormulaNeedingCheck: + case FormulaError::Spill: + case FormulaError::NotAFunction: return true; case FormulaError::NotAvailable: diff --git a/include/formula/formula.hxx b/include/formula/formula.hxx index 3107041b2fbf..1f4bdbc984db 100644 --- a/include/formula/formula.hxx +++ b/include/formula/formula.hxx @@ -60,7 +60,7 @@ class UNLESS_MERGELIBS_MORE(FORMULA_DLLPUBLIC) FormulaModalDialog friend class FormulaDlg_Impl; public: FormulaModalDialog(weld::Window* pParent, IFunctionManager const * _pFunctionMgr, - IControlReferenceHandler* _pDlg); + IControlReferenceHandler& rDlg); virtual ~FormulaModalDialog() override; private: @@ -88,7 +88,7 @@ public: FormulaDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, IFunctionManager const * _pFunctionMgr, - IControlReferenceHandler* _pDlg); + IControlReferenceHandler& rDlg); virtual ~FormulaDlg() override; private: std::unique_ptr> m_pImpl; diff --git a/include/formula/funcutl.hxx b/include/formula/funcutl.hxx index bb7de3975f6e..3d3d4e6c1e8c 100644 --- a/include/formula/funcutl.hxx +++ b/include/formula/funcutl.hxx @@ -23,8 +23,10 @@ #include #include #include +#include #include -#include +#include +#include class KeyEvent; struct ImplSVEvent; @@ -57,7 +59,7 @@ private: DECL_DLLPRIVATE_LINK(LoseFocusHdl, weld::Widget&, void); DECL_DLLPRIVATE_LINK(AsyncFocusInHdl, void*, void); DECL_DLLPRIVATE_LINK(AsyncFocusOutHdl, void*, void); - DECL_DLLPRIVATE_LINK(Modify, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(Modify, weld::TextWidget&, void); void GetFocus(); void LoseFocus(); @@ -115,12 +117,7 @@ public: mxEntry->set_position(-1); } - Selection GetSelection() const - { - int nStartPos, nEndPos; - mxEntry->get_selection_bounds(nStartPos, nEndPos); - return Selection(nStartPos, nEndPos); - } + Selection GetSelection() const; OUString GetLabelTextForShrinkMode(); diff --git a/include/formula/opcode.hxx b/include/formula/opcode.hxx index 33833215c3e2..499a55f0a565 100644 --- a/include/formula/opcode.hxx +++ b/include/formula/opcode.hxx @@ -19,525 +19,590 @@ #pragma once +#include #include -#include #include +/* Central definition of OpCodes for spreadsheet functions */ + enum OpCode : sal_uInt16 { // Special commands - ocPush = SC_OPCODE_PUSH, - ocStop = SC_OPCODE_STOP, - ocExternal = SC_OPCODE_EXTERNAL, - ocName = SC_OPCODE_NAME, + ocPush = 0, + // 1 used to be ocCall, which is now a binary operator + ocStop = 2, + ocExternal = 3, + ocName = 4, + // 5 used to be SC_OPCODE_EXTERNAL_REF // Jump commands - ocIf = SC_OPCODE_IF, - ocIfError = SC_OPCODE_IF_ERROR, - ocIfNA = SC_OPCODE_IF_NA, - ocChoose = SC_OPCODE_CHOOSE, - ocLet = SC_OPCODE_LET, + ocIf = 6, + ocIfError = 7, + ocIfNA = 8, + ocChoose = 9, + ocLet = 10, + ocLambda = 11, // Parentheses and separators - ocOpen = SC_OPCODE_OPEN, - ocClose = SC_OPCODE_CLOSE, - ocTableRefOpen = SC_OPCODE_TABLE_REF_OPEN, - ocTableRefClose = SC_OPCODE_TABLE_REF_CLOSE, - ocSep = SC_OPCODE_SEP, - ocArrayOpen = SC_OPCODE_ARRAY_OPEN, - ocArrayClose = SC_OPCODE_ARRAY_CLOSE, - ocArrayRowSep = SC_OPCODE_ARRAY_ROW_SEP, - ocArrayColSep = SC_OPCODE_ARRAY_COL_SEP, + ocOpen = 12, + ocClose = 13, + ocSep = 14, // Special OpCodes - ocMissing = SC_OPCODE_MISSING, - ocBad = SC_OPCODE_BAD, - ocStringXML = SC_OPCODE_STRINGXML, - ocSpaces = SC_OPCODE_SPACES, - ocWhitespace = SC_OPCODE_WHITESPACE, - ocMatRef = SC_OPCODE_MAT_REF, - ocTableRefItemAll = SC_OPCODE_TABLE_REF_ITEM_ALL, - ocTableRefItemHeaders = SC_OPCODE_TABLE_REF_ITEM_HEADERS, - ocTableRefItemData = SC_OPCODE_TABLE_REF_ITEM_DATA, - ocTableRefItemTotals = SC_OPCODE_TABLE_REF_ITEM_TOTALS, - ocTableRefItemThisRow = SC_OPCODE_TABLE_REF_ITEM_THIS_ROW, - ocSkip = SC_OPCODE_SKIP, - ocStringName = SC_OPCODE_STRINGNAME, + ocMissing = 15, + ocBad = 16, + ocStringXML = 17, + ocSpaces = 18, + ocWhitespace = 19, + ocMatRef = 20, // Access commands - ocDBArea = SC_OPCODE_DB_AREA, - ocTableRef = SC_OPCODE_TABLE_REF, - ocMacro = SC_OPCODE_MACRO, - ocColRowName = SC_OPCODE_COL_ROW_NAME, - ocColRowNameAuto = SC_OPCODE_COL_ROW_NAME_AUTO, - ocDPFieldName = SC_OPCODE_DP_FIELD, + /* additional access operators */ + ocDBArea = 21, + ocTableRef = 22, + ocMacro = 23, + ocColRowName = 24, + ocColRowNameAuto = 25, // Percent operator _follows_ value - ocPercentSign = SC_OPCODE_PERCENT_SIGN, + ocPercentSign = 26, + ocArrayOpen = 27, + ocArrayClose = 28, + ocArrayRowSep = 29, + ocArrayColSep = 30, /* some convs use sep != col_sep */ + ocTableRefOpen = 31, + ocTableRefClose = 32, + ocTableRefItemAll = 33, + ocTableRefItemHeaders = 34, + ocTableRefItemData = 35, + ocTableRefItemTotals = 36, + ocTableRefItemThisRow = 37, + ocStopDiv = 38, + ocSkip = 39, /* used to skip raw tokens during string compilation */ + ocStringName = 40, /* special OpCode for locally bound names (LET) */ + ocDPFieldName = 41, // Error constants - ocErrNull = SC_OPCODE_ERROR_NULL, - ocErrDivZero = SC_OPCODE_ERROR_DIVZERO, - ocErrValue = SC_OPCODE_ERROR_VALUE, - ocErrRef = SC_OPCODE_ERROR_REF, - ocErrName = SC_OPCODE_ERROR_NAME, - ocErrNum = SC_OPCODE_ERROR_NUM, - ocErrNA = SC_OPCODE_ERROR_NA, + ocStartErrors = 42, + ocErrNull = 42, + ocErrDivZero = 43, + ocErrValue = 44, + ocErrRef = 45, + ocErrName = 46, + ocErrNum = 47, + ocErrNA = 48, + ocErrSpill = 49, + ocStopErrors = 50, // Binary operators - ocAdd = SC_OPCODE_ADD, - ocSub = SC_OPCODE_SUB, - ocMul = SC_OPCODE_MUL, - ocDiv = SC_OPCODE_DIV, - ocAmpersand = SC_OPCODE_AMPERSAND, - ocPow = SC_OPCODE_POW, - ocEqual = SC_OPCODE_EQUAL, - ocNotEqual = SC_OPCODE_NOT_EQUAL, - ocLess = SC_OPCODE_LESS, - ocGreater = SC_OPCODE_GREATER, - ocLessEqual = SC_OPCODE_LESS_EQUAL, - ocGreaterEqual = SC_OPCODE_GREATER_EQUAL, - ocAnd = SC_OPCODE_AND, - ocOr = SC_OPCODE_OR, - ocXor = SC_OPCODE_XOR, - ocIntersect = SC_OPCODE_INTERSECT, - ocUnion = SC_OPCODE_UNION, - ocRange = SC_OPCODE_RANGE, + ocStartBinaryOperators = 51, + ocAdd = 51, + ocSub = 52, + ocMul = 53, + ocDiv = 54, + ocAmpersand = 55, + ocPow = 56, + ocEqual = 57, + ocNotEqual = 58, + ocLess = 59, + ocGreater = 60, + ocLessEqual = 61, + ocGreaterEqual = 62, + ocAnd = 63, + ocOr = 64, + ocIntersect = 65, + ocUnion = 66, + ocRange = 67, + ocCall = 68, + ocStopBinaryOperators = 69, + + /* NOTE: binary and unary operators must be in sequence for compiler! */ + // Unary operators - ocNegSub = SC_OPCODE_NEG_SUB, + ocStartUnaryOperators = 70, + ocNegSub = 70, + // The @ single-value prefix operator (implicit intersection). + ocSingleValue = 71, + // The # postfix spilled-range operator: A1# expands to the + // spill range of the dynamic-array formula at A1. + ocSpill = 72, + ocStopUnaryOperators = 73, + + ocStartFunction = 75, + // Functions with no parameters - ocPi = SC_OPCODE_PI, - ocRandom = SC_OPCODE_RANDOM, - ocTrue = SC_OPCODE_TRUE, - ocFalse = SC_OPCODE_FALSE, - ocGetActDate = SC_OPCODE_GET_ACT_DATE, - ocGetActTime = SC_OPCODE_GET_ACT_TIME, - ocNotAvail = SC_OPCODE_NO_VALUE, - ocCurrent = SC_OPCODE_CURRENT, - ocRandomNV = SC_OPCODE_RANDOM_NV, + ocStartNoParameters = 75, + ocPi = 75, + ocRandom = 76, + ocTrue = 77, + ocFalse = 78, + ocGetActDate = 79, + ocGetActTime = 80, + ocNotAvail = 81, + ocCurrent = 82, + ocRandomNV = 83, + ocStopNoParameters = 84, // Functions with one parameter - ocNot = SC_OPCODE_NOT, - ocNeg = SC_OPCODE_NEG, - ocDeg = SC_OPCODE_DEG, - ocRad = SC_OPCODE_RAD, - ocSin = SC_OPCODE_SIN, - ocCos = SC_OPCODE_COS, - ocTan = SC_OPCODE_TAN, - ocCot = SC_OPCODE_COT, - ocArcSin = SC_OPCODE_ARC_SIN, - ocArcCos = SC_OPCODE_ARC_COS, - ocArcTan = SC_OPCODE_ARC_TAN, - ocArcCot = SC_OPCODE_ARC_COT, - ocSinHyp = SC_OPCODE_SIN_HYP, - ocCosHyp = SC_OPCODE_COS_HYP, - ocTanHyp = SC_OPCODE_TAN_HYP, - ocCotHyp = SC_OPCODE_COT_HYP, - ocArcSinHyp = SC_OPCODE_ARC_SIN_HYP, - ocArcCosHyp = SC_OPCODE_ARC_COS_HYP, - ocArcTanHyp = SC_OPCODE_ARC_TAN_HYP, - ocArcCotHyp = SC_OPCODE_ARC_COT_HYP, - ocCosecant = SC_OPCODE_COSECANT, - ocSecant = SC_OPCODE_SECANT, - ocCosecantHyp = SC_OPCODE_COSECANT_HYP, - ocSecantHyp = SC_OPCODE_SECANT_HYP, - ocExp = SC_OPCODE_EXP, - ocLn = SC_OPCODE_LN, - ocSqrt = SC_OPCODE_SQRT, - ocFact = SC_OPCODE_FACT, - ocGetYear = SC_OPCODE_GET_YEAR, - ocGetMonth = SC_OPCODE_GET_MONTH, - ocGetDay = SC_OPCODE_GET_DAY, - ocGetHour = SC_OPCODE_GET_HOUR, - ocGetMin = SC_OPCODE_GET_MIN, - ocGetSec = SC_OPCODE_GET_SEC, - ocPlusMinus = SC_OPCODE_PLUS_MINUS, - ocAbs = SC_OPCODE_ABS, - ocInt = SC_OPCODE_INT, - ocPhi = SC_OPCODE_PHI, - ocGauss = SC_OPCODE_GAUSS, - ocIsEmpty = SC_OPCODE_IS_EMPTY, - ocIsString = SC_OPCODE_IS_STRING, - ocIsNonString = SC_OPCODE_IS_NON_STRING, - ocIsLogical = SC_OPCODE_IS_LOGICAL, - ocType = SC_OPCODE_TYPE, - ocCell = SC_OPCODE_CELL, - ocIsRef = SC_OPCODE_IS_REF, - ocIsValue = SC_OPCODE_IS_VALUE, - ocIsFormula = SC_OPCODE_IS_FORMULA, - ocIsNA = SC_OPCODE_IS_NV, - ocIsErr = SC_OPCODE_IS_ERR, - ocIsError = SC_OPCODE_IS_ERROR, - ocIsEven = SC_OPCODE_IS_EVEN, - ocIsOdd = SC_OPCODE_IS_ODD, - ocN = SC_OPCODE_N, + ocStartOneParameter = 90, + ocDeg = 90, /* trigonometric */ + ocRad = 91, + ocSin = 92, + ocCos = 93, + ocTan = 94, + ocCot = 95, + ocArcSin = 96, + ocArcCos = 97, + ocArcTan = 98, + ocArcCot = 99, + ocSinHyp = 100, + ocCosHyp = 101, + ocTanHyp = 102, + ocCotHyp = 103, + ocArcSinHyp = 104, /* transcendent */ + ocArcCosHyp = 105, + ocArcTanHyp = 106, + ocArcCotHyp = 107, + ocCosecant = 108, + ocSecant = 109, + ocCosecantHyp = 110, + ocSecantHyp = 111, + ocExp = 112, + ocLn = 113, + ocSqrt = 114, + ocFact = 115, + ocGetYear = 116, /* date and time */ + ocGetMonth = 117, + ocGetDay = 118, + ocGetHour = 119, + ocGetMin = 120, + ocGetSec = 121, + ocPlusMinus = 122, /* miscellaneous */ + ocAbs = 123, + ocInt = 124, + ocPhi = 125, + ocGauss = 126, + ocIsEmpty = 127, /* obtain type */ + ocIsString = 128, + ocIsNonString = 129, + ocIsLogical = 130, + ocType = 131, + ocIsRef = 132, + ocIsValue = 133, + ocIsFormula = 134, + ocIsNA = 135, + ocIsErr = 136, + ocIsError = 137, + ocIsEven = 138, + ocIsOdd = 139, + ocN = 140, + ocIsOmitted = 141, // String functions - ocGetDateValue = SC_OPCODE_GET_DATE_VALUE, - ocGetTimeValue = SC_OPCODE_GET_TIME_VALUE, - ocCode = SC_OPCODE_CODE, - ocTrim = SC_OPCODE_TRIM, - ocUpper = SC_OPCODE_UPPER, - ocProper = SC_OPCODE_PROPER, - ocLower = SC_OPCODE_LOWER, - ocLen = SC_OPCODE_LEN, - ocT = SC_OPCODE_T, - ocValue = SC_OPCODE_VALUE, - ocClean = SC_OPCODE_CLEAN, - ocChar = SC_OPCODE_CHAR, - ocLog10 = SC_OPCODE_LOG10, - ocEven = SC_OPCODE_EVEN, - ocOdd = SC_OPCODE_ODD, - ocStdNormDist = SC_OPCODE_STD_NORM_DIST, - ocStdNormDist_MS = SC_OPCODE_STD_NORM_DIST_MS, - ocFisher = SC_OPCODE_FISHER, - ocFisherInv = SC_OPCODE_FISHER_INV, - ocSNormInv = SC_OPCODE_S_NORM_INV, - ocSNormInv_MS = SC_OPCODE_S_NORM_INV_MS, - ocGammaLn = SC_OPCODE_GAMMA_LN, - ocGammaLn_MS = SC_OPCODE_GAMMA_LN_MS, - ocGamma = SC_OPCODE_GAMMA, - ocErrorType = SC_OPCODE_ERROR_TYPE, - ocErrorType_ODF = SC_OPCODE_ERROR_TYPE_ODF, - ocFormula = SC_OPCODE_FORMULA, - ocArabic = SC_OPCODE_ARABIC, - ocInfo = SC_OPCODE_INFO, - ocBahtText = SC_OPCODE_BAHTTEXT, - ocJis = SC_OPCODE_JIS, - ocAsc = SC_OPCODE_ASC, - ocUnicode = SC_OPCODE_UNICODE, - ocUnichar = SC_OPCODE_UNICHAR, - // Functions with more than one parameters - ocArcTan2 = SC_OPCODE_ARC_TAN_2, - ocCeil = SC_OPCODE_CEIL, - ocCeil_MS = SC_OPCODE_CEIL_MS, - ocCeil_Precise = SC_OPCODE_CEIL_PRECISE, - ocCeil_ISO = SC_OPCODE_CEIL_ISO, - ocCeil_Math = SC_OPCODE_CEIL_MATH, - ocFloor = SC_OPCODE_FLOOR, - ocFloor_MS = SC_OPCODE_FLOOR_MS, - ocFloor_Math = SC_OPCODE_FLOOR_MATH, - ocFloor_Precise = SC_OPCODE_FLOOR_PRECISE, - ocRound = SC_OPCODE_ROUND, - ocRoundUp = SC_OPCODE_ROUND_UP, - ocRoundDown = SC_OPCODE_ROUND_DOWN, - ocTrunc = SC_OPCODE_TRUNC, - ocLog = SC_OPCODE_LOG, - ocPower = SC_OPCODE_POWER, - ocGCD = SC_OPCODE_GCD, - ocLCM = SC_OPCODE_LCM, - ocMod = SC_OPCODE_MOD, - ocSumProduct = SC_OPCODE_SUM_PRODUCT, - ocSumSQ = SC_OPCODE_SUM_SQ, - ocSumX2MY2 = SC_OPCODE_SUM_X2MY2, - ocSumX2DY2 = SC_OPCODE_SUM_X2DY2, - ocSumXMY2 = SC_OPCODE_SUM_XMY2, - ocGetDate = SC_OPCODE_GET_DATE, - ocGetTime = SC_OPCODE_GET_TIME, - ocGetDiffDate = SC_OPCODE_GET_DIFF_DATE, - ocGetDiffDate360 = SC_OPCODE_GET_DIFF_DATE_360, - ocGetDateDif = SC_OPCODE_GET_DATEDIF, - ocMin = SC_OPCODE_MIN, - ocMax = SC_OPCODE_MAX, - ocSum = SC_OPCODE_SUM, - ocProduct = SC_OPCODE_PRODUCT, - ocAverage = SC_OPCODE_AVERAGE, - ocCount = SC_OPCODE_COUNT, - ocCount2 = SC_OPCODE_COUNT_2, - ocNPV = SC_OPCODE_NPV, - ocIRR = SC_OPCODE_IRR, - ocMIRR = SC_OPCODE_MIRR, - ocISPMT = SC_OPCODE_ISPMT, - ocVar = SC_OPCODE_VAR, - ocVarP = SC_OPCODE_VAR_P, - ocVarP_MS = SC_OPCODE_VAR_P_MS, - ocVarS = SC_OPCODE_VAR_S, - ocStDev = SC_OPCODE_ST_DEV, - ocStDevP = SC_OPCODE_ST_DEV_P, - ocStDevP_MS = SC_OPCODE_ST_DEV_P_MS, - ocStDevS = SC_OPCODE_ST_DEV_S, - ocB = SC_OPCODE_B, - ocNormDist = SC_OPCODE_NORM_DIST, - ocNormDist_MS = SC_OPCODE_NORM_DIST_MS, - ocExpDist = SC_OPCODE_EXP_DIST, - ocExpDist_MS = SC_OPCODE_EXP_DIST_MS, - ocBinomDist = SC_OPCODE_BINOM_DIST, - ocBinomDist_MS = SC_OPCODE_BINOM_DIST_MS, - ocBinomInv = SC_OPCODE_BINOM_INV, - ocPoissonDist = SC_OPCODE_POISSON_DIST, - ocPoissonDist_MS = SC_OPCODE_POISSON_DIST_MS, - ocCombin = SC_OPCODE_COMBIN, - ocCombinA = SC_OPCODE_COMBIN_A, - ocPermut = SC_OPCODE_PERMUT, - ocPermutationA = SC_OPCODE_PERMUTATION_A, - ocPV = SC_OPCODE_PV, - ocSYD = SC_OPCODE_SYD, - ocDDB = SC_OPCODE_DDB, - ocDB = SC_OPCODE_DB, - ocVBD = SC_OPCODE_VBD, - ocPDuration = SC_OPCODE_PDURATION, - ocSLN = SC_OPCODE_SLN, - ocPMT = SC_OPCODE_PMT, - ocColumns = SC_OPCODE_COLUMNS, - ocRows = SC_OPCODE_ROWS, - ocColumn = SC_OPCODE_COLUMN, - ocRow = SC_OPCODE_ROW, - ocRRI = SC_OPCODE_RRI, - ocFV = SC_OPCODE_FV, - ocNper = SC_OPCODE_NPER, - ocRate = SC_OPCODE_RATE, - ocIpmt = SC_OPCODE_IPMT, - ocPpmt = SC_OPCODE_PPMT, - ocCumIpmt = SC_OPCODE_CUM_IPMT, - ocCumPrinc = SC_OPCODE_CUM_PRINC, - ocEffect = SC_OPCODE_EFFECT, - ocNominal = SC_OPCODE_NOMINAL, - ocSubTotal = SC_OPCODE_SUB_TOTAL, - ocRawSubtract = SC_OPCODE_RAWSUBTRACT, - ocIfs_MS = SC_OPCODE_IFS_MS, - ocSwitch_MS = SC_OPCODE_SWITCH_MS, - ocMinIfs_MS = SC_OPCODE_MINIFS_MS, - ocMaxIfs_MS = SC_OPCODE_MAXIFS_MS, - ocRoundSig = SC_OPCODE_ROUNDSIG, + ocGetDateValue = 142, + ocGetTimeValue = 143, + ocCode = 144, + ocTrim = 145, + ocUpper = 146, + ocProper = 147, + ocLower = 148, + ocLen = 149, + ocT = 150, /* miscellaneous, part 21 */ + ocValue = 151, + ocClean = 152, + ocChar = 153, + ocLog10 = 154, + ocEven = 155, + ocOdd = 156, + ocStdNormDist = 157, + ocFisher = 158, + ocFisherInv = 159, + ocSNormInv = 160, + ocGammaLn = 161, + ocErrorType = 162, + // 163 was ??? + ocFormula = 164, + ocArabic = 165, + ocInfo = 166, + ocBahtText = 167, + ocJis = 168, + ocAsc = 169, + ocUnicode = 170, + ocUnichar = 171, + ocGamma = 172, + ocGammaLn_MS = 173, + ocErf_MS = 174, + ocErfc_MS = 175, + ocErrorType_ODF = 176, + ocEncodeURL = 177, + ocIsoWeeknum = 178, + ocNot = 179, + ocNeg = 180, + // OOXML spelling of the # operator, a call in front of its operand. Only a + // rewritten token array has this. + ocAnchorArray = 181, + ocStopOneParameter = 182, + + // Functions with more than one parameter + ocStartTwoParameters = 201, + ocArcTan2 = 201, + ocCeil = 202, + ocFloor = 203, + ocRound = 204, + ocRoundUp = 205, + ocRoundDown = 206, + ocTrunc = 207, + ocLog = 208, + ocPower = 209, + ocGCD = 210, + ocLCM = 211, + ocMod = 212, + ocSumProduct = 213, + ocSumSQ = 214, + ocSumX2MY2 = 215, + ocSumX2DY2 = 216, + ocSumXMY2 = 217, + ocGetDate = 218, + ocGetTime = 219, + ocGetDiffDate = 220, + ocGetDiffDate360 = 221, + ocMin = 222, + ocMax = 223, + ocSum = 224, + ocProduct = 225, + ocAverage = 226, + ocCount = 227, + ocCount2 = 228, + ocNPV = 229, + ocIRR = 230, + ocVar = 231, + ocVarP = 232, + ocStDev = 233, + ocStDevP = 234, + ocB = 235, + ocNormDist = 236, + ocExpDist = 237, + ocBinomDist = 238, + ocPoissonDist = 239, + ocCombin = 240, + ocCombinA = 241, + ocPermut = 242, + ocPermutationA = 243, + ocPV = 244, + ocSYD = 245, + ocDDB = 246, + ocDB = 247, + ocVBD = 248, + ocPDuration = 249, + ocSLN = 250, + ocPMT = 251, + ocColumns = 252, + ocRows = 253, + ocColumn = 254, + ocRow = 255, + ocRRI = 256, + ocFV = 257, + ocNper = 258, + ocRate = 259, + ocIpmt = 260, + ocPpmt = 261, + ocCumIpmt = 262, + ocCumPrinc = 263, + ocEffect = 264, + ocNominal = 265, + ocSubTotal = 266, // Database functions - ocDBSum = SC_OPCODE_DB_SUM, - ocDBCount = SC_OPCODE_DB_COUNT, - ocDBCount2 = SC_OPCODE_DB_COUNT_2, - ocDBAverage = SC_OPCODE_DB_AVERAGE, - ocDBGet = SC_OPCODE_DB_GET, - ocDBMax = SC_OPCODE_DB_MAX, - ocDBMin = SC_OPCODE_DB_MIN, - ocDBProduct = SC_OPCODE_DB_PRODUCT, - ocDBStdDev = SC_OPCODE_DB_STD_DEV, - ocDBStdDevP = SC_OPCODE_DB_STD_DEV_P, - ocDBVar = SC_OPCODE_DB_VAR, - ocDBVarP = SC_OPCODE_DB_VAR_P, + ocDBSum = 267, + ocDBCount = 268, + ocDBCount2 = 269, + ocDBAverage = 270, + ocDBGet = 271, + ocDBMax = 272, + ocDBMin = 273, + ocDBProduct = 274, + ocDBStdDev = 275, + ocDBStdDevP = 276, + ocDBVar = 277, + ocDBVarP = 278, // Management functions - ocIndirect = SC_OPCODE_INDIRECT, - ocAddress = SC_OPCODE_ADDRESS, - ocMatch = SC_OPCODE_MATCH, - ocXMatch = SC_OPCODE_X_MATCH, - ocCountEmptyCells = SC_OPCODE_COUNT_EMPTY_CELLS, - ocCountIf = SC_OPCODE_COUNT_IF, - ocSumIf = SC_OPCODE_SUM_IF, - ocAverageIf = SC_OPCODE_AVERAGE_IF, - ocSumIfs = SC_OPCODE_SUM_IFS, - ocAverageIfs = SC_OPCODE_AVERAGE_IFS, - ocCountIfs = SC_OPCODE_COUNT_IFS, - ocLookup = SC_OPCODE_LOOKUP, - ocVLookup = SC_OPCODE_V_LOOKUP, - ocXLookup = SC_OPCODE_X_LOOKUP, - ocHLookup = SC_OPCODE_H_LOOKUP, - ocMultiArea = SC_OPCODE_MULTI_AREA, - ocOffset = SC_OPCODE_OFFSET, - ocIndex = SC_OPCODE_INDEX, - ocAreas = SC_OPCODE_AREAS, + ocIndirect = 279, + ocAddress = 280, + ocMatch = 281, + ocCountEmptyCells = 282, + ocCountIf = 283, + ocSumIf = 284, + ocLookup = 285, + ocVLookup = 286, + ocHLookup = 287, + ocMultiArea = 288, + ocOffset = 289, + ocIndex = 290, + ocAreas = 291, // String functions - ocCurrency = SC_OPCODE_CURRENCY, - ocReplace = SC_OPCODE_REPLACE, - ocFixed = SC_OPCODE_FIXED, - ocFind = SC_OPCODE_FIND, - ocExact = SC_OPCODE_EXACT, - ocLeft = SC_OPCODE_LEFT, - ocRight = SC_OPCODE_RIGHT, - ocSearch = SC_OPCODE_SEARCH, - ocMid = SC_OPCODE_MID, - ocText = SC_OPCODE_TEXT, - ocSubstitute = SC_OPCODE_SUBSTITUTE, - ocRept = SC_OPCODE_REPT, - ocConcat = SC_OPCODE_CONCAT, - ocConcat_MS = SC_OPCODE_CONCAT_MS, - ocTextJoin_MS = SC_OPCODE_TEXTJOIN_MS, - ocLenB = SC_OPCODE_LENB, - ocRightB = SC_OPCODE_RIGHTB, - ocLeftB = SC_OPCODE_LEFTB, - ocMidB = SC_OPCODE_MIDB, - ocReplaceB = SC_OPCODE_REPLACEB, - ocFindB = SC_OPCODE_FINDB, - ocSearchB = SC_OPCODE_SEARCHB, - ocNumberValue = SC_OPCODE_NUMBERVALUE, - ocRegex = SC_OPCODE_REGEX, + ocCurrency = 292, + ocReplace = 293, + ocFixed = 294, + ocFind = 295, + ocExact = 296, + ocLeft = 297, + ocRight = 298, + ocSearch = 299, + ocMid = 300, + ocText = 301, + ocSubstitute = 302, + ocRept = 303, + ocConcat = 304, // Matrix functions - ocMatValue = SC_OPCODE_MAT_VALUE, - ocMatDet = SC_OPCODE_MAT_DET, - ocMatInv = SC_OPCODE_MAT_INV, - ocMatMult = SC_OPCODE_MAT_MULT, - ocMatTrans = SC_OPCODE_MAT_TRANS, - ocMatrixUnit = SC_OPCODE_MATRIX_UNIT, + ocMatValue = 305, + ocMatDet = 306, + ocMatInv = 307, + ocMatMult = 308, + ocMatTrans = 309, + ocMatrixUnit = 310, // BackSolver - ocBackSolver = SC_OPCODE_BACK_SOLVER, + ocBackSolver = 311, // Statistical functions - ocHypGeomDist = SC_OPCODE_HYP_GEOM_DIST, - ocHypGeomDist_MS = SC_OPCODE_HYP_GEOM_DIST_MS, - ocLogNormDist = SC_OPCODE_LOG_NORM_DIST, - ocLogNormDist_MS = SC_OPCODE_LOG_NORM_DIST_MS, - ocTDist = SC_OPCODE_T_DIST, - ocTDist_MS = SC_OPCODE_T_DIST_MS, - ocTDist_RT = SC_OPCODE_T_DIST_RT, - ocTDist_2T = SC_OPCODE_T_DIST_2T, - ocFDist = SC_OPCODE_F_DIST, - ocFDist_LT = SC_OPCODE_F_DIST_LT, - ocFDist_RT = SC_OPCODE_F_DIST_RT, - ocChiDist = SC_OPCODE_CHI_DIST, - ocChiDist_MS = SC_OPCODE_CHI_DIST_MS, - ocChiSqDist = SC_OPCODE_CHISQ_DIST, - ocChiSqDist_MS = SC_OPCODE_CHISQ_DIST_MS, - ocChiSqInv = SC_OPCODE_CHISQ_INV, - ocChiSqInv_MS = SC_OPCODE_CHISQ_INV_MS, - ocWeibull = SC_OPCODE_WEIBULL, - ocWeibull_MS = SC_OPCODE_WEIBULL_MS, - ocNegBinomVert = SC_OPCODE_NEG_BINOM_VERT, - ocNegBinomDist_MS = SC_OPCODE_NEG_BINOM_DIST_MS, - ocCritBinom = SC_OPCODE_CRIT_BINOM, - ocKurt = SC_OPCODE_KURT, - ocHarMean = SC_OPCODE_HAR_MEAN, - ocGeoMean = SC_OPCODE_GEO_MEAN, - ocStandard = SC_OPCODE_STANDARD, - ocAveDev = SC_OPCODE_AVE_DEV, - ocSkew = SC_OPCODE_SKEW, - ocSkewp = SC_OPCODE_SKEWP, - ocDevSq = SC_OPCODE_DEV_SQ, - ocMedian = SC_OPCODE_MEDIAN, - ocModalValue = SC_OPCODE_MODAL_VALUE, - ocModalValue_MS = SC_OPCODE_MODAL_VALUE_MS, - ocModalValue_Multi = SC_OPCODE_MODAL_VALUE_MULTI, - ocZTest = SC_OPCODE_Z_TEST, - ocZTest_MS = SC_OPCODE_Z_TEST_MS, - ocAggregate = SC_OPCODE_AGGREGATE, - ocTTest = SC_OPCODE_T_TEST, - ocTTest_MS = SC_OPCODE_T_TEST_MS, - ocRank = SC_OPCODE_RANK, - ocPercentile = SC_OPCODE_PERCENTILE, - ocPercentrank = SC_OPCODE_PERCENT_RANK, - ocPercentile_Inc = SC_OPCODE_PERCENTILE_INC, - ocPercentrank_Inc = SC_OPCODE_PERCENT_RANK_INC, - ocQuartile_Inc = SC_OPCODE_QUARTILE_INC, - ocRank_Eq = SC_OPCODE_RANK_EQ, - ocPercentile_Exc = SC_OPCODE_PERCENTILE_EXC, - ocPercentrank_Exc = SC_OPCODE_PERCENT_RANK_EXC, - ocQuartile_Exc = SC_OPCODE_QUARTILE_EXC, - ocRank_Avg = SC_OPCODE_RANK_AVG, - ocLarge = SC_OPCODE_LARGE, - ocSmall = SC_OPCODE_SMALL, - ocFrequency = SC_OPCODE_FREQUENCY, - ocQuartile = SC_OPCODE_QUARTILE, - ocNormInv = SC_OPCODE_NORM_INV, - ocNormInv_MS = SC_OPCODE_NORM_INV_MS, - ocConfidence = SC_OPCODE_CONFIDENCE, - ocConfidence_N = SC_OPCODE_CONFIDENCE_N, - ocConfidence_T = SC_OPCODE_CONFIDENCE_T, - ocFTest = SC_OPCODE_F_TEST, - ocFTest_MS = SC_OPCODE_F_TEST_MS, - ocTrimMean = SC_OPCODE_TRIM_MEAN, - ocProb = SC_OPCODE_PROB, - ocCorrel = SC_OPCODE_CORREL, - ocCovar = SC_OPCODE_COVAR, - ocCovarianceP = SC_OPCODE_COVARIANCE_P, - ocCovarianceS = SC_OPCODE_COVARIANCE_S, - ocPearson = SC_OPCODE_PEARSON, - ocRSQ = SC_OPCODE_RSQ, - ocSTEYX = SC_OPCODE_STEYX, - ocSlope = SC_OPCODE_SLOPE, - ocIntercept = SC_OPCODE_INTERCEPT, - ocTrend = SC_OPCODE_TREND, - ocGrowth = SC_OPCODE_GROWTH, - ocLinest = SC_OPCODE_LINEST, - ocLogest = SC_OPCODE_LOGEST, - ocForecast = SC_OPCODE_FORECAST, - ocForecast_ETS_ADD = SC_OPCODE_FORECAST_ETS_ADD, - ocForecast_ETS_SEA = SC_OPCODE_FORECAST_ETS_SEA, - ocForecast_ETS_MUL = SC_OPCODE_FORECAST_ETS_MUL, - ocForecast_ETS_PIA = SC_OPCODE_FORECAST_ETS_PIA, - ocForecast_ETS_PIM = SC_OPCODE_FORECAST_ETS_PIM, - ocForecast_ETS_STA = SC_OPCODE_FORECAST_ETS_STA, - ocForecast_ETS_STM = SC_OPCODE_FORECAST_ETS_STM, - ocForecast_LIN = SC_OPCODE_FORECAST_LIN, - ocChiInv = SC_OPCODE_CHI_INV, - ocChiInv_MS = SC_OPCODE_CHI_INV_MS, - ocGammaDist = SC_OPCODE_GAMMA_DIST, - ocGammaDist_MS = SC_OPCODE_GAMMA_DIST_MS, - ocGammaInv = SC_OPCODE_GAMMA_INV, - ocGammaInv_MS = SC_OPCODE_GAMMA_INV_MS, - ocTInv = SC_OPCODE_T_INV, - ocTInv_2T = SC_OPCODE_T_INV_2T, - ocTInv_MS = SC_OPCODE_T_INV_MS, - ocFInv = SC_OPCODE_F_INV, - ocFInv_LT = SC_OPCODE_F_INV_LT, - ocFInv_RT = SC_OPCODE_F_INV_RT, - ocChiTest = SC_OPCODE_CHI_TEST, - ocChiTest_MS = SC_OPCODE_CHI_TEST_MS, - ocLogInv = SC_OPCODE_LOG_INV, - ocLogInv_MS = SC_OPCODE_LOG_INV_MS, - ocTableOp = SC_OPCODE_TABLE_OP, - ocBetaDist = SC_OPCODE_BETA_DIST, - ocBetaInv = SC_OPCODE_BETA_INV, - ocBetaDist_MS = SC_OPCODE_BETA_DIST_MS, - ocBetaInv_MS = SC_OPCODE_BETA_INV_MS, - // Bit functions - ocBitAnd = SC_OPCODE_BITAND, - ocBitOr = SC_OPCODE_BITOR, - ocBitXor = SC_OPCODE_BITXOR, - ocBitRshift = SC_OPCODE_BITRSHIFT, - ocBitLshift = SC_OPCODE_BITLSHIFT, + ocHypGeomDist = 312, + ocLogNormDist = 313, + ocTDist = 314, + ocFDist = 315, + ocChiDist = 316, + ocWeibull = 317, + ocNegBinomVert = 318, + ocCritBinom = 319, + ocKurt = 320, + ocHarMean = 321, + ocGeoMean = 322, + ocStandard = 323, + ocAveDev = 324, + ocSkew = 325, + ocDevSq = 326, + ocMedian = 327, + ocModalValue = 328, + ocZTest = 329, + ocTTest = 330, + ocRank = 331, + ocPercentile = 332, + ocPercentrank = 333, + ocLarge = 334, + ocSmall = 335, + ocFrequency = 336, + ocQuartile = 337, + ocNormInv = 338, + ocConfidence = 339, + ocFTest = 340, + ocTrimMean = 341, + ocProb = 342, + ocCorrel = 343, + ocCovar = 344, + ocPearson = 345, + ocRSQ = 346, + ocSTEYX = 347, + ocSlope = 348, + ocIntercept = 349, + ocTrend = 350, + ocGrowth = 351, + ocLinest = 352, + ocLogest = 353, + ocForecast = 354, + ocChiInv = 355, + ocGammaDist = 356, + ocGammaInv = 357, + ocTInv = 358, + ocFInv = 359, + ocChiTest = 360, + ocLogInv = 361, + ocTableOp = 362, + ocBetaDist = 363, + ocBetaInv = 364, // miscellaneous - ocWeek = SC_OPCODE_WEEK, - ocIsoWeeknum = SC_OPCODE_ISOWEEKNUM, - ocWeeknumOOo = SC_OPCODE_WEEKNUM_OOO, - ocGetDayOfWeek = SC_OPCODE_GET_DAY_OF_WEEK, - ocNetWorkdays = SC_OPCODE_NETWORKDAYS, - ocNetWorkdays_MS = SC_OPCODE_NETWORKDAYS_MS, - ocWorkday_MS = SC_OPCODE_WORKDAY_MS, - ocNoName = SC_OPCODE_NO_NAME, - ocStyle = SC_OPCODE_STYLE, - ocDde = SC_OPCODE_DDE, - ocBase = SC_OPCODE_BASE, - ocSheet = SC_OPCODE_SHEET, - ocSheets = SC_OPCODE_SHEETS, - ocMinA = SC_OPCODE_MIN_A, - ocMaxA = SC_OPCODE_MAX_A, - ocAverageA = SC_OPCODE_AVERAGE_A, - ocStDevA = SC_OPCODE_ST_DEV_A, - ocStDevPA = SC_OPCODE_ST_DEV_P_A, - ocVarA = SC_OPCODE_VAR_A, - ocVarPA = SC_OPCODE_VAR_P_A, - ocEasterSunday = SC_OPCODE_EASTERSUNDAY, - ocDecimal = SC_OPCODE_DECIMAL, - ocConvertOOo = SC_OPCODE_CONVERT_OOO, - ocRoman = SC_OPCODE_ROMAN, - ocHyperLink = SC_OPCODE_HYPERLINK, - ocGetPivotData = SC_OPCODE_GET_PIVOT_DATA, - ocEuroConvert = SC_OPCODE_EUROCONVERT, - ocFilterXML = SC_OPCODE_FILTERXML, - ocWebservice = SC_OPCODE_WEBSERVICE, - ocColor = SC_OPCODE_COLOR, - ocErf_MS = SC_OPCODE_ERF_MS, - ocErfc_MS = SC_OPCODE_ERFC_MS, - ocEncodeURL = SC_OPCODE_ENCODEURL, - ocFourier = SC_OPCODE_FOURIER, - ocRandbetweenNV = SC_OPCODE_RANDBETWEEN_NV, - ocFilter = SC_OPCODE_FILTER, - ocSort = SC_OPCODE_SORT, - ocSortBy = SC_OPCODE_SORTBY, - ocMatSequence = SC_OPCODE_MAT_SEQUENCE, - ocRandArray = SC_OPCODE_RANDARRAY, - ocChooseCols = SC_OPCODE_CHOOSECOLS, - ocChooseRows = SC_OPCODE_CHOOSEROWS, - ocDrop = SC_OPCODE_DROP, - ocExpand = SC_OPCODE_EXPAND, - ocHStack = SC_OPCODE_HSTACK, - ocVStack = SC_OPCODE_VSTACK, - ocTake = SC_OPCODE_TAKE, - ocTextAfter = SC_OPCODE_TEXTAFTER, - ocTextBefore = SC_OPCODE_TEXTBEFORE, - ocTextSplit = SC_OPCODE_TEXTSPLIT, - ocToCol = SC_OPCODE_TOCOL, - ocToRow = SC_OPCODE_TOROW, - ocUnique = SC_OPCODE_UNIQUE, - ocWrapCols = SC_OPCODE_WRAPCOLS, - ocWrapRows = SC_OPCODE_WRAPROWS, + ocWeek = 365, + ocGetDayOfWeek = 366, + ocNoName = 367, + ocStyle = 368, + ocDde = 369, + ocBase = 370, + ocSheet = 371, + ocSheets = 372, + ocMinA = 373, + ocMaxA = 374, + ocAverageA = 375, + ocStDevA = 376, + ocStDevPA = 377, + ocVarA = 378, + ocVarPA = 379, + ocEasterSunday = 380, + ocDecimal = 381, + ocConvertOOo = 382, + ocRoman = 383, + ocMIRR = 384, + ocCell = 385, + ocISPMT = 386, + ocHyperLink = 387, + ocXLookup = 388, + ocXMatch = 389, + ocGetPivotData = 390, + ocEuroConvert = 391, + ocNumberValue = 392, + ocChiSqDist = 393, + ocChiSqInv = 394, + // Bit functions + ocBitAnd = 395, + ocBitOr = 396, + ocBitXor = 397, + ocBitRshift = 398, + ocBitLshift = 399, + ocGetDateDif = 400, + ocXor = 401, + ocAverageIf = 402, + ocSumIfs = 403, + ocAverageIfs = 404, + ocCountIfs = 405, + ocSkewp = 406, + ocLenB = 407, + ocRightB = 408, + ocLeftB = 409, + ocMidB = 410, + ocFilterXML = 411, + ocWebservice = 412, + ocCovarianceS = 413, + ocCovarianceP = 414, + ocStDevP_MS = 415, + ocStDevS = 416, + ocVarP_MS = 417, + ocVarS = 418, + ocBetaDist_MS = 419, + ocBetaInv_MS = 420, + ocBinomDist_MS = 421, + ocBinomInv = 422, + ocChiDist_MS = 423, + ocChiInv_MS = 424, + ocChiTest_MS = 425, + ocChiSqDist_MS = 426, + ocChiSqInv_MS = 427, + ocConfidence_N = 428, + ocConfidence_T = 429, + ocFDist_LT = 430, + ocFDist_RT = 431, + ocFInv_LT = 432, + ocFInv_RT = 433, + ocFTest_MS = 434, + ocExpDist_MS = 435, + ocHypGeomDist_MS = 436, + ocPoissonDist_MS = 437, + ocWeibull_MS = 438, + ocGammaDist_MS = 439, + ocGammaInv_MS = 440, + ocLogNormDist_MS = 441, + ocLogInv_MS = 442, + ocNormDist_MS = 443, + ocNormInv_MS = 444, + ocStdNormDist_MS = 445, + ocSNormInv_MS = 446, + ocTDist_MS = 447, + ocTDist_RT = 448, + ocTDist_2T = 449, + ocTInv_2T = 450, + ocTInv_MS = 451, + ocTTest_MS = 452, + ocPercentile_Inc = 453, + ocPercentrank_Inc = 454, + ocQuartile_Inc = 455, + ocRank_Eq = 456, + ocPercentile_Exc = 457, + ocPercentrank_Exc = 458, + ocQuartile_Exc = 459, + ocRank_Avg = 460, + ocModalValue_MS = 461, + ocModalValue_Multi = 462, + ocNegBinomDist_MS = 463, + ocZTest_MS = 464, + ocCeil_MS = 465, + ocCeil_ISO = 466, + ocFloor_MS = 467, + ocNetWorkdays_MS = 468, + ocWorkday_MS = 469, + ocAggregate = 470, + ocColor = 471, + ocCeil_Math = 472, + ocCeil_Precise = 473, + ocNetWorkdays = 474, + ocFloor_Math = 475, + ocFloor_Precise = 476, + ocRawSubtract = 477, + ocWeeknumOOo = 478, + ocForecast_ETS_ADD = 479, + ocForecast_ETS_SEA = 480, + ocForecast_ETS_MUL = 481, + ocForecast_ETS_PIA = 482, + ocForecast_ETS_PIM = 483, + ocForecast_ETS_STA = 484, + ocForecast_ETS_STM = 485, + ocForecast_LIN = 486, + ocConcat_MS = 487, + ocTextJoin_MS = 488, + ocIfs_MS = 489, + ocSwitch_MS = 490, + ocMinIfs_MS = 491, + ocMaxIfs_MS = 492, + ocRoundSig = 493, + ocReplaceB = 494, + ocFindB = 495, + ocSearchB = 496, + ocRegex = 497, + ocFourier = 498, + ocRandbetweenNV = 499, + ocFilter = 500, + ocSort = 501, + ocSortBy = 502, + ocMatSequence = 503, + ocRandArray = 504, + ocChooseCols = 505, + ocChooseRows = 506, + ocDrop = 507, + ocExpand = 508, + ocHStack = 509, + ocVStack = 510, + ocTake = 511, + ocTextAfter = 512, + ocTextBefore = 513, + ocTextSplit = 514, + ocToCol = 515, + ocToRow = 516, + ocUnique = 517, + ocWrapCols = 518, + ocWrapRows = 519, + ocUDExternal = 520, /* User-defined external function */ + ocByCol = 521, + ocByRow = 522, + ocMakeArray = 523, + ocMap = 524, + ocReduce = 525, + ocScan = 526, + ocArrayToText = 527, + ocStopTwoParameters = 528, /* last function with two or more parameters' OpCode + 1 */ + + ocStopFunction = ocStopTwoParameters, /* last function's OpCode + 1 */ + ocLastOpcodeId = ocStopFunction - 1, /* last OpCode */ + // internal stuff - ocInternalBegin = SC_OPCODE_INTERNAL_BEGIN, - ocTTT = SC_OPCODE_TTT, - ocDebugVar = SC_OPCODE_DEBUG_VAR, - ocInternalEnd = SC_OPCODE_INTERNAL_END, + ocInternalBegin = 9999, + ocTTT = 9999, + ocDebugVar = 10000, + ocInternalEnd = 10000, // from here on ExtraData - ocDataToken1 = SC_OPCODE_DATA_TOKEN_1, + ocDataToken1 = 10001, // no OpCode - ocNone = SC_OPCODE_NONE + ocNone = 0xFFFF }; +// Whether the opcode is one of the two whitespace token forms. +constexpr bool isWhitespaceOpCode(OpCode eOp) { return eOp == ocSpaces || eOp == ocWhitespace; } + +// Whether the opcode is a unary operator. +constexpr bool isUnaryOperatorOpCode(OpCode eOp) +{ + return ocStartUnaryOperators <= eOp && eOp < ocStopUnaryOperators; +} + +// Whether the opcode is a binary operator. +constexpr bool isBinaryOperatorOpCode(OpCode eOp) +{ + return ocStartBinaryOperators <= eOp && eOp < ocStopBinaryOperators; +} + // Only to be used for debugging output. No guarantee of stability of the // return value. @@ -550,11 +615,13 @@ inline std::string OpCodeEnumToString(OpCode eCode) case ocPush: return "Push"; case ocStop: return "Stop"; case ocExternal: return "External"; + case ocUDExternal: return "UDExternal"; case ocName: return "Name"; case ocIf: return "If"; case ocIfError: return "IfError"; case ocIfNA: return "IfNA"; case ocChoose: return "Choose"; + case ocLet: return "Let"; case ocOpen: return "Open"; case ocClose: return "Close"; case ocTableRefOpen: return "TableRefOpen"; @@ -591,6 +658,7 @@ inline std::string OpCodeEnumToString(OpCode eCode) case ocErrName: return "ErrName"; case ocErrNum: return "ErrNum"; case ocErrNA: return "ErrNA"; + case ocErrSpill: return "ErrSpill"; case ocAdd: return "Add"; case ocSub: return "Sub"; case ocMul: return "Mul"; @@ -609,9 +677,12 @@ inline std::string OpCodeEnumToString(OpCode eCode) case ocIntersect: return "Intersect"; case ocUnion: return "Union"; case ocRange: return "Range"; + case ocCall: return "Call"; + case ocSpill: return "SpilledRange"; case ocNot: return "Not"; case ocNeg: return "Neg"; case ocNegSub: return "NegSub"; + case ocSingleValue: return "SingleValue"; case ocPi: return "Pi"; case ocRandom: return "Random"; case ocRandomNV: return "RandomNV"; @@ -1024,13 +1095,22 @@ inline std::string OpCodeEnumToString(OpCode eCode) case ocToCol: return "ToCol"; case ocToRow: return "ToRow"; case ocUnique: return "Unique"; - case ocLet: return "Let"; case ocWrapCols: return "WrapCols"; case ocWrapRows: return "WrapRows"; + case ocLambda: return "Lambda"; + case ocIsOmitted: return "IsOmitted"; + case ocByCol: return "ByCol"; + case ocByRow: return "ByRow"; + case ocMakeArray: return "MakeArray"; + case ocMap: return "Map"; + case ocReduce: return "Reduce"; + case ocScan: return "Scan"; + case ocArrayToText: return "ArrayToText"; case ocTTT: return "TTT"; case ocDebugVar: return "DebugVar"; case ocDataToken1: return "DataToken1"; case ocNone: return "None"; + default: assert(false); return "???"; } std::ostringstream os; os << static_cast(eCode); diff --git a/include/formula/token.hxx b/include/formula/token.hxx index 33af5264acd9..3c8818d06606 100644 --- a/include/formula/token.hxx +++ b/include/formula/token.hxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ enum StackVar : sal_uInt8 svDouble, svString, svStringName, + svCallable, svDPFieldName, svSingleRef, svDoubleRef, @@ -95,6 +97,7 @@ inline std::string StackVarEnumToString(StackVar const e) case svDouble: return "Double"; case svString: return "String"; case svStringName: return "StringName"; + case svCallable: return "Callable"; case svDPFieldName: return "DPFieldName"; case svSingleRef: return "SingleRef"; case svDoubleRef: return "DoubleRef"; @@ -211,38 +214,8 @@ public: Any other non-overridden method pops up an assertion. */ - virtual sal_uInt8 GetByte() const; - virtual void SetByte( sal_uInt8 n ); virtual ParamClass GetInForceArray() const; virtual void SetInForceArray( ParamClass c ); - virtual double GetDouble() const; - virtual void SetDouble(double fValue); - virtual sal_Int16 GetDoubleType() const; - virtual void SetDoubleType( sal_Int16 nType ); - virtual const svl::SharedString & GetString() const; - virtual void SetString( const svl::SharedString& rStr ); - virtual sal_uInt16 GetIndex() const; - virtual void SetIndex( sal_uInt16 n ); - virtual sal_Int16 GetSheet() const; - virtual void SetSheet( sal_Int16 n ); - virtual sal_Unicode GetChar() const; - virtual short* GetJump() const; - virtual const OUString& GetExternal() const; - virtual FormulaToken* GetFAPOrigToken() const; - virtual FormulaError GetError() const; - virtual void SetError( FormulaError ); - - virtual const ScSingleRefData* GetSingleRef() const; - virtual ScSingleRefData* GetSingleRef(); - virtual const ScComplexRefData* GetDoubleRef() const; - virtual ScComplexRefData* GetDoubleRef(); - virtual const ScSingleRefData* GetSingleRef2() const; - virtual ScSingleRefData* GetSingleRef2(); - virtual const ScMatrix* GetMatrix() const; - virtual ScMatrix* GetMatrix(); - virtual ScJumpMatrix* GetJumpMatrix() const; - virtual const std::vector* GetRefList() const; - virtual std::vector* GetRefList(); virtual FormulaToken* Clone() const { return new FormulaToken(*this); } @@ -278,37 +251,33 @@ public: nByte( r.nByte ), cChar( r.cChar ) {} virtual FormulaToken* Clone() const override { return new FormulaSpaceToken(*this); } - virtual sal_uInt8 GetByte() const override; - virtual sal_Unicode GetChar() const override; + sal_uInt8 GetByte() const; + sal_Unicode GetChar() const; virtual bool operator==( const FormulaToken& rToken ) const override; }; -class FORMULA_DLLPUBLIC FormulaByteToken : public FormulaToken +class FORMULA_DLLPUBLIC FormulaByteToken final : public FormulaToken { private: - sal_uInt8 nByte; + sal_uInt8 mnByte; ParamClass eInForceArray; -protected: - FormulaByteToken( OpCode e, sal_uInt8 n, StackVar v, ParamClass c ) : - FormulaToken( v,e ), nByte( n ), - eInForceArray( c ) {} public: FormulaByteToken( OpCode e, sal_uInt8 n, ParamClass c ) : - FormulaToken( svByte,e ), nByte( n ), + FormulaToken( svByte,e ), mnByte( n ), eInForceArray( c ) {} FormulaByteToken( OpCode e, sal_uInt8 n ) : - FormulaToken( svByte,e ), nByte( n ), + FormulaToken( svByte,e ), mnByte( n ), eInForceArray( ParamClass::Unknown ) {} FormulaByteToken( OpCode e ) : - FormulaToken( svByte,e ), nByte( 0 ), + FormulaToken( svByte,e ), mnByte( 0 ), eInForceArray( ParamClass::Unknown ) {} FormulaByteToken( const FormulaByteToken& r ) : - FormulaToken( r ), nByte( r.nByte ), + FormulaToken( r ), mnByte( r.mnByte ), eInForceArray( r.eInForceArray ) {} virtual FormulaToken* Clone() const override { return new FormulaByteToken(*this); } - virtual sal_uInt8 GetByte() const override final; - virtual void SetByte( sal_uInt8 n ) override final; + sal_uInt8 GetByte() const { return mnByte; } + void SetByte( sal_uInt8 n ) { mnByte = n; } virtual ParamClass GetInForceArray() const override final; virtual void SetInForceArray( ParamClass c ) override final; virtual bool operator==( const FormulaToken& rToken ) const override; @@ -317,19 +286,20 @@ public: // A special token for the FormulaAutoPilot only. Keeps a reference pointer of // the token of which it was created for comparison. -class FORMULA_DLLPUBLIC FormulaFAPToken final : public FormulaByteToken +class FORMULA_DLLPUBLIC FormulaFAPToken final : public FormulaToken { private: + sal_uInt8 mnByte; FormulaTokenRef pOrigToken; public: FormulaFAPToken( OpCode e, sal_uInt8 n, FormulaToken* p ) : - FormulaByteToken( e, n, svFAP, ParamClass::Unknown ), - pOrigToken( p ) {} + FormulaToken(svFAP, e), mnByte(n), pOrigToken( p ) {} FormulaFAPToken( const FormulaFAPToken& r ) : - FormulaByteToken( r ), pOrigToken( r.pOrigToken ) {} + FormulaToken( r ), mnByte(r.mnByte), pOrigToken( r.pOrigToken ) {} virtual FormulaToken* Clone() const override { return new FormulaFAPToken(*this); } - virtual FormulaToken* GetFAPOrigToken() const override; + FormulaToken* GetFAPOrigToken() const; + sal_uInt8 GetByte() const { return mnByte; } virtual bool operator==( const FormulaToken& rToken ) const override; }; @@ -344,9 +314,9 @@ public: FormulaToken( r ), fDouble( r.fDouble ) {} virtual FormulaToken* Clone() const override { return new FormulaDoubleToken(*this); } - virtual double GetDouble() const override final { return fDouble; } - virtual void SetDouble(double fValue) override final { fDouble = fValue; } - virtual sal_Int16 GetDoubleType() const override; ///< always returns 0 for "not typed" + double GetDouble() const { return fDouble; } + void SetDouble(double fValue) { fDouble = fValue; } + virtual sal_Int16 GetDoubleType() const; ///< always returns 0 for "not typed" virtual bool operator==( const FormulaToken& rToken ) const override; }; @@ -365,37 +335,43 @@ public: virtual FormulaToken* Clone() const override { return new FormulaTypedDoubleToken(*this); } virtual sal_Int16 GetDoubleType() const override; - virtual void SetDoubleType( sal_Int16 nType ) override; + void SetDoubleType( sal_Int16 nType ); virtual bool operator==( const FormulaToken& rToken ) const override; }; -class FORMULA_DLLPUBLIC FormulaStringToken final : public FormulaToken +class FORMULA_DLLPUBLIC FormulaStringToken : public FormulaToken { svl::SharedString maString; +protected: + // constructor for FormulaStringOpToken to use + FormulaStringToken( OpCode e, svl::SharedString r ); public: FormulaStringToken( svl::SharedString r ); FormulaStringToken( const FormulaStringToken& r ); virtual FormulaToken* Clone() const override; - virtual const svl::SharedString & GetString() const override; - virtual void SetString( const svl::SharedString& rStr ) override; + const svl::SharedString & GetString() const { return maString; } + void SetString( const svl::SharedString& rStr ); virtual bool operator==( const FormulaToken& rToken ) const override; }; /** Identical to FormulaStringToken, but with explicit OpCode instead of implicit ocPush, and an optional sal_uInt8 for ocBad tokens. */ -class FORMULA_DLLPUBLIC FormulaStringOpToken final : public FormulaByteToken +class FORMULA_DLLPUBLIC FormulaStringOpToken final : public FormulaStringToken { - svl::SharedString maString; + sal_uInt8 nByte; + ParamClass eInForceArray; public: FormulaStringOpToken( OpCode e, svl::SharedString r ); FormulaStringOpToken( const FormulaStringOpToken& r ); virtual FormulaToken* Clone() const override; - virtual const svl::SharedString & GetString() const override; - virtual void SetString( const svl::SharedString& rStr ) override; + sal_uInt8 GetByte() const { return nByte; } + void SetByte( sal_uInt8 n ) { nByte = n; } + virtual ParamClass GetInForceArray() const override final { return eInForceArray; } + virtual void SetInForceArray( ParamClass c ) override final { eInForceArray = c; } virtual bool operator==( const FormulaToken& rToken ) const override; }; @@ -403,16 +379,31 @@ public: class FORMULA_DLLPUBLIC FormulaStringNameToken final : public FormulaToken { svl::SharedString maString; + bool mIsOptional; public: - FormulaStringNameToken(StackVar eTypeP, svl::SharedString r); + FormulaStringNameToken(StackVar eTypeP, svl::SharedString r, bool isOptional = false); FormulaStringNameToken(const FormulaStringNameToken& r); virtual FormulaToken* Clone() const override; - virtual const svl::SharedString& GetString() const override; - virtual void SetString(const svl::SharedString& rStr) override; + const svl::SharedString& GetString() const { return maString; } + bool GetIsOptional() const { return mIsOptional; } + void SetIsOptional(bool isOptional) { mIsOptional = isOptional; } virtual bool operator==(const FormulaToken& rToken) const override; }; +// A data-pilot field name is stored in a FormulaStringNameToken too, so both +// svStringName and svDPFieldName identify one. +inline const FormulaStringNameToken* GetStringNameToken(const FormulaToken* p) +{ + const StackVar eType = p->GetType(); + if (eType == svStringName || eType == svDPFieldName) + { + assert(dynamic_cast(p)); + return static_cast(p); + } + return nullptr; +} + class FORMULA_DLLPUBLIC FormulaIndexToken final : public FormulaToken { @@ -426,30 +417,36 @@ public: FormulaToken( r ), nIndex( r.nIndex ), mnSheet( r.mnSheet ) {} virtual FormulaToken* Clone() const override { return new FormulaIndexToken(*this); } - virtual sal_uInt16 GetIndex() const override; - virtual void SetIndex( sal_uInt16 n ) override; - virtual sal_Int16 GetSheet() const override; - virtual void SetSheet( sal_Int16 n ) override; + sal_uInt16 GetIndex() const; + void SetIndex( sal_uInt16 n ); + sal_Int16 GetSheet() const; + void SetSheet( sal_Int16 n ); virtual bool operator==( const FormulaToken& rToken ) const override; }; -class FORMULA_DLLPUBLIC FormulaExternalToken final : public FormulaByteToken +class FORMULA_DLLPUBLIC FormulaExternalToken final : public FormulaToken { private: - OUString aExternal; + sal_uInt8 mnByte; + ParamClass eInForceArray; + OUString aExternal; public: FormulaExternalToken( OpCode e, sal_uInt8 n, OUString r ) : - FormulaByteToken( e, n, svExternal, ParamClass::Unknown ), + FormulaToken( svExternal, e), mnByte(n), eInForceArray( ParamClass::Unknown ), aExternal(std::move( r )) {} FormulaExternalToken( OpCode e, OUString r ) : - FormulaByteToken( e, 0, svExternal, ParamClass::Unknown ), + FormulaToken( svExternal, e), mnByte(0), eInForceArray( ParamClass::Unknown ), aExternal(std::move( r )) {} FormulaExternalToken( const FormulaExternalToken& r ) : - FormulaByteToken( r ), aExternal( r.aExternal ) {} + FormulaToken( r ), mnByte(r.mnByte), eInForceArray(r.eInForceArray), aExternal( r.aExternal ) {} virtual FormulaToken* Clone() const override { return new FormulaExternalToken(*this); } - virtual const OUString& GetExternal() const override; + const OUString& GetExternal() const; + sal_uInt8 GetByte() const { return mnByte; } + void SetByte( sal_uInt8 n ) { mnByte = n; } + virtual ParamClass GetInForceArray() const override final { return eInForceArray; } + virtual void SetInForceArray( ParamClass c ) override final { eInForceArray = c; } virtual bool operator==( const FormulaToken& rToken ) const override; }; @@ -463,8 +460,6 @@ public: FormulaToken( r ) {} virtual FormulaToken* Clone() const override { return new FormulaMissingToken(*this); } - virtual double GetDouble() const override; - virtual const svl::SharedString & GetString() const override; virtual bool operator==( const FormulaToken& rToken ) const override; }; @@ -490,7 +485,8 @@ public: memcpy( pJump.get(), r.pJump.get(), (r.pJump[0] + 1) * sizeof(short) ); } virtual ~FormulaJumpToken() override; - virtual short* GetJump() const override; + const short* GetJump() const { return pJump.get(); } + short* GetJump() { return pJump.get(); } virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new FormulaJumpToken(*this); } virtual ParamClass GetInForceArray() const override; @@ -523,8 +519,8 @@ public: FormulaToken( r ), nError( r.nError) {} virtual FormulaToken* Clone() const override { return new FormulaErrorToken(*this); } - virtual FormulaError GetError() const override; - virtual void SetError( FormulaError nErr ) override; + FormulaError GetError() const; + void SetError( FormulaError nErr ); virtual bool operator==( const FormulaToken& rToken ) const override; // we do some performance stuff in ScInterpreter::PushError that needs this @@ -536,6 +532,21 @@ public: }; +// Only created from within the interpreter +class FORMULA_DLLPUBLIC FormulaCallableToken final : public FormulaToken +{ +private: + FormulaCallableRef mpCallable; +public: + FormulaCallableToken( FormulaCallableRef pCallable ) : + FormulaToken( svCallable ), mpCallable(pCallable) {} + FormulaCallableToken( const FormulaCallableToken& r ) = default; + virtual FormulaToken* Clone() const override { return new FormulaCallableToken(*this); } + FormulaCallableRef GetCallable() const; + virtual bool operator==( const FormulaToken& rToken ) const override; +}; + + } // formula /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx index 8c7b9c4434e8..fbc1b26ea3eb 100644 --- a/include/formula/tokenarray.hxx +++ b/include/formula/tokenarray.hxx @@ -233,7 +233,7 @@ class FORMULA_DLLPUBLIC FormulaTokenArray { protected: std::unique_ptr pCode; // Token code array - FormulaToken** pRPN; // RPN array + std::unique_ptr pRPN; // RPN array sal_uInt16 nLen; // Length of token array sal_uInt16 nRPN; // Length of RPN array FormulaError nError; // Error code @@ -242,13 +242,14 @@ protected: bool mbFromRangeName :1; // If this array originates from a named expression bool mbShareable :1; // Whether or not it can be shared with adjacent cells. bool mbFinalized :1; // Whether code arrays have their final used size and no more tokens can be added. + bool mbDynamicArrayFunction :1; // If a dynamic-array function occurs in the formula (i.e. UNIQUE, FILTER, SORT) protected: void Assign( const FormulaTokenArray& ); void Assign( sal_uInt16 nCode, FormulaToken **pTokens ); void Move( FormulaTokenArray&& ); - /// Also used by the compiler. The token MUST had been allocated with new! + /// Also used by the compiler. The token MUST have been allocated with new! FormulaToken* Add( FormulaToken* ); public: @@ -258,7 +259,7 @@ public: CODE_AND_RPN ///< replacement in pCode and pRPN }; - /** Also used by the compiler. The token MUST had been allocated with new! + /** Also used by the compiler. The token MUST have been allocated with new! @param nOffset Absolute offset in pCode of the token to be replaced. @param eMode @@ -323,7 +324,7 @@ public: return pCode[nIdx]; } - /// Peek at nIdx-1 if not out of bounds, decrements nIdx if successful. Returns NULL if not. + /// Peek at nIdx-1 if not out of bounds, decrements nIdx if successful. Returns nullptr if not. FormulaToken* PeekPrev( sal_uInt16 & nIdx ) const; /// Return the opcode at pCode[nIdx-1], ocNone if nIdx-1 is out of bounds @@ -336,7 +337,6 @@ public: } FormulaToken* FirstRPNToken() const; - FormulaToken* LastRPNToken() const; bool HasReferences() const; @@ -359,9 +359,18 @@ public: /// Assign pRPN to point to a newly created array filled with the data from pData void CreateNewRPNArrayFromData( FormulaToken** pData, sal_uInt16 nSize ) { - pRPN = new FormulaToken*[ nSize ]; + pRPN = std::make_unique(nSize); nRPN = nSize; - memcpy( pRPN, pData, nSize * sizeof( FormulaToken* ) ); + memcpy( pRPN.get(), pData, nSize * sizeof( FormulaToken* ) ); + } + + // Assign pCode to point to a newly created array filled with data; the array is sized exactly + // to size, so it is final: + void CreateNewCodeArrayFromData(FormulaToken ** data, sal_uInt16 size) { + pCode = std::make_unique(size); + nLen = size; + memcpy(pCode.get(), data, size * sizeof (FormulaToken *)); + mbFinalized = true; } FormulaToken** GetArray() const { return pCode.get(); } @@ -371,11 +380,11 @@ public: return FormulaTokenArrayStandardRange(pCode.get(), nLen); } - FormulaToken** GetCode() const { return pRPN; } + FormulaToken** GetCode() const { return pRPN.get(); } FormulaTokenArrayStandardRange RPNTokens() const { - return FormulaTokenArrayStandardRange(pRPN, nRPN); + return FormulaTokenArrayStandardRange(pRPN.get(), nRPN); } FormulaTokenArrayReferencesRange References() const @@ -390,6 +399,9 @@ public: void SetHyperLink( bool bVal ) { bHyperLink = bVal; } bool IsHyperLink() const { return bHyperLink; } + void SetDynamicArrayFunction(bool bValue) { mbDynamicArrayFunction = bValue; } + bool HasDynamicArrayFunction() const { return mbDynamicArrayFunction; } + ScRecalcMode GetRecalcMode() const { return nMode; } void SetCombinedBitsRecalcMode( ScRecalcMode nBits ) @@ -479,7 +491,7 @@ public: FormulaToken* AddToken( const FormulaToken& ); FormulaToken* AddString( const svl::SharedString& rStr ); - FormulaToken* AddStringName( const svl::SharedString& rStr ); + FormulaToken* AddStringName(const svl::SharedString& rString, bool bOptional = false); FormulaToken* AddDPFieldName( const svl::SharedString& rStr ); FormulaToken* AddDouble( double fVal ); void AddExternal( const sal_Unicode* pStr ); @@ -576,8 +588,8 @@ public: void Jump( short nStart, short nNext, short nStop = SHRT_MAX ); void Push( const FormulaTokenArray* ); void Pop(); - void FrontPop(); void Lambda( bool bOpt ); + bool IsLambda() const; /** Reconstruct the iterator afresh from a token array */ @@ -646,7 +658,6 @@ public: FormulaToken* Next(); FormulaToken* NextNoSpaces(); FormulaToken* GetNextName(); - FormulaToken* GetNextStringNameRPN(); FormulaToken* GetNextDPFieldNameRPN(); FormulaToken* GetNextReference(); FormulaToken* GetNextReferenceRPN(); diff --git a/include/formula/types.hxx b/include/formula/types.hxx index 983b64127acb..7b96fbb80fe2 100644 --- a/include/formula/types.hxx +++ b/include/formula/types.hxx @@ -24,8 +24,10 @@ namespace formula { class FormulaToken; +class FormulaCallable; typedef ::boost::intrusive_ptr FormulaTokenRef; typedef ::boost::intrusive_ptr FormulaConstTokenRef; +typedef ::boost::intrusive_ptr FormulaCallableRef; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/framework/desktop.hxx b/include/framework/desktop.hxx index b6bee117b9bc..83559e31ea11 100644 --- a/include/framework/desktop.hxx +++ b/include/framework/desktop.hxx @@ -63,8 +63,8 @@ enum ELoadState }; /*-************************************************************************************************************ - @short implement the topframe of frame tree - @descr This is the root of the frame tree. The desktop has no window, is not visible but he is the logical + @short implements the top frame of the frame tree + @descr This is the root of the frame tree. The desktop has no window, is not visible but it is the logical "masternode" to build the hierarchy. @implements XInterface @@ -134,20 +134,20 @@ class FWK_DLLPUBLIC Desktop final : private cppu::BaseMutex, /** @interface XDesktop - @short try to shutdown these desktop environment. + @short try to shut down this desktop environment. @descr Will try to close all frames. If at least one frame could not be closed successfully termination will be stopped. - Registered termination listener will be taken into account - also. As special feature some of our registered listener - are well known by its UNO implementation name. They are handled - different to all other listener. + Registered termination listeners will be taken into account + also. As a special feature some of our registered listeners + are well known by their UNO implementation name. They are handled + differently to all other listeners. Btw: Desktop.terminate() was designed in the past to be used - within an UI based environment. So it's allowed e.g. to + within a UI based environment. So it's allowed e.g. to call XController.suspend() here. If UI isn't an option ... please - use XCloseable.close() at these desktop implementation. + use XCloseable.close() at this desktop implementation. ... if it will be supported in the future .-)) @seealso XTerminateListener @@ -166,10 +166,10 @@ class FWK_DLLPUBLIC Desktop final : private cppu::BaseMutex, @short add a listener for termination events - @descr Additional to adding normal listener these method was implemented special. + @descr In addition to adding normal listeners this method was implemented specially. Every listener will be asked for its uno implementation name. Some of them are well known... and the corresponding listener won't be added - to the container of "normal listener". Those listener will be set as special + to the container of "normal listeners". Those listeners will be set as a special member. see e.g. member m_xSfxTerminator @@ -187,10 +187,10 @@ class FWK_DLLPUBLIC Desktop final : private cppu::BaseMutex, @short remove a listener from this container. - @descr Additional to removing normal listener these method was implemented special. + @descr In addition to removing normal listeners this method was implemented specially. Every listener will be asked for its uno implementation name. - Some of them are well known... and the corresponding listener was set as special member. - Now those special member will be reset also. + Some of them are well known... and the corresponding listener was set as a special member. + Now that special member will be reset also. see e.g. member m_xSfxTerminator @seealso terminate() @@ -383,21 +383,21 @@ class FWK_DLLPUBLIC Desktop final : private cppu::BaseMutex, /** when true, the call came from session manager * the method is Desktop::terminateQuickstarterToo() - * this the only one place where set this to true - * In this case, when one frame break, not make - * question for other, the break of shutdown or logout - * can be only once. - * In Desktop::impl_closeFrames would be test and break + * this is the only place where this is set to true + * In this case, when one frame breaks, don't ask + * questions for others, the break of shutdown or logout + * can happen only once. + * In Desktop::impl_closeFrames it would be tested and break * the loop and reset to false */ bool m_bSession; - css::uno::Reference< css::uno::XComponentContext > m_xContext; /// reference to factory, which has create this instance + css::uno::Reference< css::uno::XComponentContext > m_xContext; /// reference to factory, which has created this instance FrameContainer m_aChildTaskContainer; /// array of child tasks (children of desktop are tasks; and tasks are also frames - But pure frames are not accepted!) comphelper::OMultiTypeInterfaceContainerHelper2 m_aListenerContainer; /// container for ALL Listener rtl::Reference< OFrames > m_xFramesHelper; /// helper for XFrames, XIndexAccess, XElementAccess and implementation of a childcontainer! rtl::Reference< InterceptionHelper > m_xDispatchHelper; /// helper to dispatch something for new tasks, created by "_blank"! - ELoadState m_eLoadState; /// hold information about state of asynchron loading of component for loadComponentFromURL()! + ELoadState m_eLoadState; /// hold information about state of asynchronous loading of component for loadComponentFromURL()! bool m_bSuspendQuickstartVeto; /// don't ask quickstart for a veto std::unique_ptr m_xCommandOptions; /// ref counted class to support disabling commands defined by configuration file OUString m_sName; @@ -419,23 +419,23 @@ class FWK_DLLPUBLIC Desktop final : private cppu::BaseMutex, /** special terminate listener which loads images asynchronous for current open documents. * Because internally it uses blocking system APIs... it can't be guaranteed that * running jobs can be cancelled successfully if the corresponding document will be closed... - * it will not hinder those documents on closing. Instead it let all jobs running... + * it will not hinder those documents on closing. Instead it lets all jobs run... * but at least on terminate we have to wait for all those blocked requests. - * So these implementation must be a special terminate listener too .-( + * So this implementation must be a special terminate listener too .-( */ css::uno::Reference< css::frame::XTerminateListener > m_xSWThreadManager; /** special terminate listener shutting down the SfxApplication. - * Because these desktop instance closes documents and informs listener + * Because this desktop instance closes documents and informs listeners * only... it does not really shutdown the whole application. * * Btw: that wouldn't be possible by design... because Desktop.terminate() * has to return a boolean value about success... it can't really shutdown the * process .-) * - * So we uses a trick: a special listener (exactly these one here) listen for notifyTermination() - * and shutdown the process asynchronous. But desktop has to make this special - * notification as really last one ... Otherwise it can happen that asynchronous + * So we use a trick: a special listener (exactly this one here) listens for notifyTermination() + * and shuts down the process asynchronously. But desktop has to make this special + * notification as really the last one ... Otherwise it can happen that asynchronous * shutdown will be faster than all other code around Desktop.terminate() .-)) */ css::uno::Reference< css::frame::XTerminateListener > m_xSfxTerminator; diff --git a/include/framework/generictoolbarcontroller.hxx b/include/framework/generictoolbarcontroller.hxx index b041260d0ca7..9d23dd03444f 100644 --- a/include/framework/generictoolbarcontroller.hxx +++ b/include/framework/generictoolbarcontroller.hxx @@ -42,8 +42,9 @@ class UNLESS_MERGELIBS(FWK_DLLPUBLIC) GenericToolbarController final : public sv const OUString& aCommand ); virtual ~GenericToolbarController() override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using svt::ToolboxController::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // XToolbarController virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override; @@ -77,8 +78,9 @@ public: const css::uno::Reference& rParentWindow, const OUString& rModuleName); - // XComponent - void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using svt::ToolboxController::disposing; + void disposing(std::unique_lock& rGuard) override; // XStatusListener void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& rEvent) override; diff --git a/include/framework/titlehelper.hxx b/include/framework/titlehelper.hxx index d9c8590834cc..8c0e6014e30c 100644 --- a/include/framework/titlehelper.hxx +++ b/include/framework/titlehelper.hxx @@ -64,7 +64,7 @@ class UNLESS_MERGELIBS_MORE(FWK_DLLPUBLIC) TitleHelper final : /** set an outside component which uses this container and must be set as source of all broadcasted messages, exceptions. - It's holded weak only so we do not need any complex dispose sessions. + It's held weak only so we do not need any complex dispose sessions. Note: Passing NULL as parameter will be allowed. It will reset the internal member reference only. @@ -72,7 +72,7 @@ class UNLESS_MERGELIBS_MORE(FWK_DLLPUBLIC) TitleHelper final : @param xOwner the new owner of this collection. @param xNumbers - provides the right string and number for an untitled component. + provides the right string and number for an untitled component. */ TitleHelper(css::uno::Reference< css::uno::XComponentContext > xContext, const css::uno::Reference< css::uno::XInterface >& xOwner, @@ -157,7 +157,7 @@ class UNLESS_MERGELIBS_MORE(FWK_DLLPUBLIC) TitleHelper final : /** provides parts of our own title and we listen there for changes too. */ css::uno::WeakReference< css::frame::XTitle > m_xSubTitle; - /** if it's set to sal_True the member m_sTitle has not to be changed internally. + /** if it's set to true the member m_sTitle must not be changed internally. It was set from outside and so outside code has to make sure it will be updated. */ @@ -169,7 +169,7 @@ class UNLESS_MERGELIBS_MORE(FWK_DLLPUBLIC) TitleHelper final : /** knows the leased number which must be used for untitled components. */ ::sal_Int32 m_nLeasedNumber; - /** contains all title change listener */ + /** contains all title change listeners */ comphelper::OInterfaceContainerHelper4 m_aTitleChangeListeners; }; diff --git a/include/i18nlangtag/applelangid.hxx b/include/i18nlangtag/applelangid.hxx deleted file mode 100644 index ed617eba25dc..000000000000 --- a/include/i18nlangtag/applelangid.hxx +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- 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/. - */ - -//as seen at http://www.microsoft.com/typography/otspec/name.htm - -#ifndef INCLUDED_I18NLANGTAG_APPLELANGID_H -#define INCLUDED_I18NLANGTAG_APPLELANGID_H - -#include -class LanguageTag; - -enum class AppleLanguageId : unsigned short -{ - ENGLISH =0, - FRENCH =1, - GERMAN =2, - ITALIAN =3, - DUTCH =4, - SWEDISH =5, - SPANISH =6, - DANISH =7, - PORTUGUESE =8, - NORWEGIAN =9, - HEBREW =10, - JAPANESE =11, - ARABIC =12, - FINNISH =13, - GREEK =14, - ICELANDIC =15, - MALTESE =16, - TURKISH =17, - CROATIAN =18, - CHINESE_TRADITIONAL =19, - URDU =20, - HINDI =21, - THAI =22, - KOREAN =23, - LITHUANIAN =24, - POLISH =25, - HUNGARIAN =26, - ESTONIAN =27, - LATVIAN =28, - SAMI =29, - FAROESE =30, - FARSI =31, - RUSSIAN =32, - CHINESE_SIMPLIFIED =33, - FLEMISH =34, - IRISH_GAELIC =35, - ALBANIAN =36, - ROMANIAN =37, - CZECH =38, - SLOVAK =39, - SLOVENIAN =40, - YIDDISH =41, - SERBIAN =42, - MACEDONIAN =43, - BULGARIAN =44, - UKRAINIAN =45, - BYELORUSSIAN =46, - UZBEK =47, - KAZAKH =48, - AZERI_CYRILLIC =49, - AZERI_ARABIC =50, - ARMENIAN =51, - GEORGIAN =52, - MOLDAVIAN =53, - KIRGHIZ =54, - TAJIKI =55, - TURKMEN =56, - MONGOLIAN_MONGOLIAN =57, - MONGOLIAN_CYRILLIC =58, - PASHTO =59, - KURDISH =60, - KASHMIRI =61, - SINDHI =62, - TIBETAN =63, - NEPALI =64, - SANSKRIT =65, - MARATHI =66, - BENGALI =67, - ASSAMESE =68, - GUJARATI =69, - PUNJABI =70, - ORIYA =71, - MALAYALAM =72, - KANNADA =73, - TAMIL =74, - TELUGU =75, - SINHALESE =76, - BURMESE =77, - KHMER =78, - LAO =79, - VIETNAMESE =80, - INDONESIAN =81, - TAGALONG =82, - MALAY_LATIN =83, - MALAY_ARABIC =84, - AMHARIC =85, - TIGRINYA =86, - GALLA =87, - SOMALI =88, - SWAHILI =89, - KINYARWANDA =90, - RUNDI =91, - NYANJA =92, - MALAGASY =93, - ESPERANTO =94, - WELSH =128, - BASQUE =129, - CATALAN =130, - LATIN =131, - QUENCHUA =132, - GUARANI =133, - AYMARA =134, - TATAR =135, - UIGHUR =136, - DZONGKHA =137, - JAVANESE_LATIN =138, - SUNDANESE_LATIN =139, - GALICIAN =140, - AFRIKAANS =141, - BRETON =142, - INUKTITUT =143, - SCOTTISH_GAELIC =144, - MANX_GAELIC =145, - IRISH_GAELIC_WITH_DOT_ABOVE =146, - TONGAN =147, - GREEK_POLYTONIC =148, - GREENLANDIC =149, - AZERI_LATIN =150, -}; - -/** Init LanguageTag with Apple LanguageId */ -I18NLANGTAG_DLLPUBLIC LanguageTag makeLanguageTagFromAppleLanguageId(AppleLanguageId nLanguage); - - -#endif /* INCLUDED_I18NLANGTAG_APPLELANGID_H */ - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/jsuno/detail/dllapi.hxx b/include/jsuno/detail/dllapi.hxx new file mode 100644 index 000000000000..f84b636c3c9f --- /dev/null +++ b/include/jsuno/detail/dllapi.hxx @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +#if defined LO_DLLIMPLEMENTATION_JSUNO +#define LO_DLLPUBLIC_JSUNO SAL_DLLPUBLIC_EXPORT +#else +#define LO_DLLPUBLIC_JSUNO SAL_DLLPUBLIC_IMPORT +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/jsuno/jsuno.hxx b/include/jsuno/jsuno.hxx new file mode 100644 index 000000000000..65276d1952a0 --- /dev/null +++ b/include/jsuno/jsuno.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include + +#include + +#include +#include + +namespace com::sun::star::uno +{ +class XInterface; +} + +namespace jsuno +{ +typedef std::span>> VariableList; + +// @return JSON-stringified result (empty string for a value that JSON.stringify drops: `undefined`, +// a function, or a symbol) +// +// @param aGlobalVariables A list of variables to define in the global scope in the script. +// +// @throws css.script.provider.ScriptExceptionRaisedException +LO_DLLPUBLIC_JSUNO OUString execute(OUString const& script, + VariableList aGlobalVariables = VariableList()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/jvmaccess/unovirtualmachine.hxx b/include/jvmaccess/unovirtualmachine.hxx index 1b424dba9c6a..b1a3b519a258 100644 --- a/include/jvmaccess/unovirtualmachine.hxx +++ b/include/jvmaccess/unovirtualmachine.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_JVMACCESS_UNOVIRTUALMACHINE_HXX -#define INCLUDED_JVMACCESS_UNOVIRTUALMACHINE_HXX +#pragma once #include #include @@ -95,6 +94,4 @@ private: }; } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/o3tl/float_int_conversion.hxx b/include/o3tl/float_int_conversion.hxx index 76b8edabba0a..ed4dd46d1d48 100644 --- a/include/o3tl/float_int_conversion.hxx +++ b/include/o3tl/float_int_conversion.hxx @@ -51,14 +51,6 @@ template constexpr I saturating_cast(F f) return std::numeric_limits::max(); return f; } - -// Return `value` of floating-point type `F` rounded to the nearest integer away from zero (which -// can be useful in calls to convertsToAtLeast/Most(roundAway(x), n), to reject x that are -// smaller/larger than n because they have a fractional part): -template F roundAway(F value) -{ - return value >= 0 ? std::ceil(value) : std::floor(value); -} } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/o3tl/lazy_update.hxx b/include/o3tl/lazy_update.hxx deleted file mode 100644 index 6f9325dfd17e..000000000000 --- a/include/o3tl/lazy_update.hxx +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- 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_O3TL_LAZY_UPDATE_HXX -#define INCLUDED_O3TL_LAZY_UPDATE_HXX - -#include - -namespace o3tl -{ - /** Update output object lazily - - This template collects data in input type, and updates the - output type with the given update functor, but only if the - output is requested. Useful if updating is expensive, or input - changes frequently, but output is only comparatively seldom - used. - - @example -
    -LazyUpdate myValue(F);
    -*myValue = newInput;
    -myValue->updateInput( this, that, those );
    -
    -output( *myValue );
    -        
    - or -
    -output( myValue.getOutValue() );
    -        
    - if the compiler does not recognize the const context. - */ - template class LazyUpdate { - public: - LazyUpdate(Func func): func_(std::move(func)), input_(), dirty_(true) {} - - In const & getInValue() const { return input_; } - - Out const & getOutValue() const { return update(); } - - In & operator *() { - dirty_ = true; - return input_; - } - - In * operator ->() { - dirty_ = true; - return &input_; - } - - Out const & operator *() const { return update(); } - - Out const * operator ->() const { return &update(); } - - private: - Out const & update() const { - if (dirty_) { - output_ = func_(input_); - dirty_ = false; - } - return output_; - } - - Func const func_; - In input_; - mutable Out output_; - mutable bool dirty_; - }; -} - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/o3tl/lru_map.hxx b/include/o3tl/lru_map.hxx index 64428d568f64..65268ea85b4d 100644 --- a/include/o3tl/lru_map.hxx +++ b/include/o3tl/lru_map.hxx @@ -205,7 +205,7 @@ public: checkLRUMaxSize(); } - list_const_iterator_t insert(key_value_pair_t& rPair) + void insert(key_value_pair_t& rPair) { map_iterator_t i = mLruMap.find(rPair.first); @@ -230,11 +230,9 @@ public: mLruList.splice(mLruList.begin(), mLruList, i->second); checkLRUItemUpdate(); } - - return mLruList.cbegin(); } - list_const_iterator_t insert(key_value_pair_t&& rPair) + void insert(key_value_pair_t&& rPair) { map_iterator_t i = mLruMap.find(rPair.first); @@ -258,8 +256,6 @@ public: mLruList.splice(mLruList.begin(), mLruList, i->second); checkLRUItemUpdate(); } - - return mLruList.cbegin(); } list_const_iterator_t find(const Key& key) @@ -305,12 +301,6 @@ public: return mLruMap.size(); } - size_t empty() const - { - assert(mLruMap.empty() == mLruList.empty()); - return mLruMap.empty(); - } - // size_t total_size() const; - only if custom ValueSize void clear() diff --git a/include/o3tl/sorted_vector.hxx b/include/o3tl/sorted_vector.hxx index 7afcf4782c25..dedd7ad3b6d3 100644 --- a/include/o3tl/sorted_vector.hxx +++ b/include/o3tl/sorted_vector.hxx @@ -289,7 +289,7 @@ public: private: static bool compare_equal( const Value& v1, const Value& v2 ) - { // Synthetize == check from < check for std::unique asserts above. + { // Synthesize == check from < check for std::unique asserts above. return !Compare()( v1, v2 ) && !Compare()( v2, v1 ); } diff --git a/include/oox/core/filterbase.hxx b/include/oox/core/filterbase.hxx index 73af247ae6a2..2877246a8714 100644 --- a/include/oox/core/filterbase.hxx +++ b/include/oox/core/filterbase.hxx @@ -236,6 +236,8 @@ public: bool isExportTemplate() const; + bool isExportSlideShow() const; + protected: virtual css::uno::Reference< css::io::XInputStream > implGetInputStream( comphelper::SequenceAsHashMap& rMediaDesc ) const; diff --git a/include/oox/core/xmlfilterbase.hxx b/include/oox/core/xmlfilterbase.hxx index 0a3525ba536e..17b691a371b7 100644 --- a/include/oox/core/xmlfilterbase.hxx +++ b/include/oox/core/xmlfilterbase.hxx @@ -72,8 +72,8 @@ class FastParser; struct XmlFilterBaseImpl; using ShapePairs - = std::map, css::uno::Reference>; -using NamedShapePairs = std::map; + = std::unordered_map, css::uno::Reference>; +using NamedShapePairs = std::unordered_map; class OOX_DLLPUBLIC XmlFilterBase : public FilterBase { @@ -225,14 +225,14 @@ public: void SetMaxDocId(sal_Int32 maxDocId) { mnMaxDocId = maxDocId; } - /** Write the document properties into into the current OPC package. + /** Write the document properties into the current OPC package. @param xProperties The document properties to export. */ void exportDocumentProperties( const css::uno::Reference< css::document::XDocumentProperties >& xProperties, bool bSecurityOptOpenReadOnly ); /** Write the customXml entries we are preserving (xlsx and pptx only). */ - void exportCustomFragments(); + void exportCustomFragments(const sax_fastparser::FSHelperPtr& pFS); /** Read the document properties and also the customXml entries (xlsx and pptx only). */ void importDocumentProperties(); diff --git a/include/oox/crypto/AgileEngine.hxx b/include/oox/crypto/AgileEngine.hxx index 7124333c2efc..6f27ef871f8f 100644 --- a/include/oox/crypto/AgileEngine.hxx +++ b/include/oox/crypto/AgileEngine.hxx @@ -63,7 +63,6 @@ struct OOX_DLLPUBLIC AgileEncryptionParameters enum class AgileEncryptionPreset { - AES_128_SHA1, AES_128_SHA384, AES_192_SHA384, AES_256_SHA512, diff --git a/include/oox/drawingml/chart/datasourcemodel.hxx b/include/oox/drawingml/chart/datasourcemodel.hxx index 7cc52208e6a0..673e4d972a89 100644 --- a/include/oox/drawingml/chart/datasourcemodel.hxx +++ b/include/oox/drawingml/chart/datasourcemodel.hxx @@ -37,8 +37,9 @@ struct DataSequenceModel typedef ::std::map< sal_Int32, css::uno::Any > AnyMap; AnyMap maData; /// Map of values, indexed by point identifier. - OUString maFormula; /// Formula reference, e.g. into a spreadsheet. - OUString maFormatCode; /// Number format for double values. + OUString maFormula; /// Formula reference, e.g. into a spreadsheet. + OUString maNFormula; /// Formula reference for a element + OUString maFormatCode; /// Number format for double values. sal_Int32 mnPointCount; /// Number of points in this series source. sal_Int32 mnLevelCount; /// Number of category levels. SvNumFormatType meFormatType; /// Type of number format in maFormatCode. @@ -58,7 +59,28 @@ struct DataSourceModel ~DataSourceModel(); }; -enum class DataSourceType: sal_Int32; +/// Dimension/data source type. The STR_ and NUM_ values correspond to chartex +/// ST_StringDimensionType and ST_NumericDimensionType, respectively. STR_CAT +/// and NUM_VAL are also used by traditional (non-chartex) charts. +enum class DataSourceType: sal_Int32 +{ + UNKNOWN = 0, + + // String dimension types (strDim) + STR_CAT, /// "cat" - categories (also used by traditional charts) + STR_COLORSTR, /// "colorStr" - color strings + STR_ENTITYID, /// "entityId" - entity identifiers + // Numeric dimension types (numDim) + NUM_VAL, /// "val" - numeric values (also used by traditional charts) + NUM_X, /// "x" - x-axis values + NUM_Y, /// "y" - y-axis values + NUM_SIZE, /// "size" - size values (e.g. sunburst, treemap) + NUM_COLORVAL, /// "colorVal" - color values (e.g. region map) + // Non-dimension types (traditional charts only) + POINTS, /// Data point size (e.g. bubble size in bubble charts). + DATALABELS, /// Data point labels. +}; + // Data source for chartex struct DataSourceCxModel @@ -77,6 +99,18 @@ struct DataSourceCxModel }; +/// Convert chartex XML attributes to a DataSourceType. +/// @param bNumeric true for numDim, false for strDim +/// @param rType the type attribute value (e.g. "val", "cat", "size") +DataSourceType dataSourceTypeFromCx(bool bNumeric, std::u16string_view rType); + +/// Convert a DataSourceType back to chartex XML element/attribute info. +/// @param eType the DataSourceType +/// @param rbNumeric set to true for numDim, false for strDim +/// @param rsType set to the type attribute value +/// @return false if eType is not a dimension type (POINTS, DATALABELS) +bool dataSourceTypeToCx(DataSourceType eType, bool& rbNumeric, OUString& rsType); + } // namespace oox::drawingml::chart #endif diff --git a/include/oox/drawingml/diagram/diagramhelper_oox.hxx b/include/oox/drawingml/diagram/diagramhelper_oox.hxx index 7b1ff709fb51..b150a9b770c1 100644 --- a/include/oox/drawingml/diagram/diagramhelper_oox.hxx +++ b/include/oox/drawingml/diagram/diagramhelper_oox.hxx @@ -75,7 +75,7 @@ public: virtual void reLayout() override; // get text representation of data tree - virtual OUString getDiagramString() const override; + OUString getDiagramString() const; // get children of provided data node // use empty string for top-level nodes diff --git a/include/oox/drawingml/graphicshapecontext.hxx b/include/oox/drawingml/graphicshapecontext.hxx index cd736271b725..4aeb3140ff2a 100644 --- a/include/oox/drawingml/graphicshapecontext.hxx +++ b/include/oox/drawingml/graphicshapecontext.hxx @@ -50,6 +50,7 @@ public: private: bool mbEmbedShapesInChart; + OUString maName; ::oox::core::ContextHandler2Helper* mpParent; }; @@ -71,7 +72,7 @@ class DiagramGraphicDataContext final : public ShapeContext { public: - DiagramGraphicDataContext( ::oox::core::ContextHandler2Helper const & rParent, const ShapePtr& pShapePtr ); + DiagramGraphicDataContext( ::oox::core::ContextHandler2Helper const & rParent, const ShapePtr& pShapePtr, const OUString& rName ); virtual ~DiagramGraphicDataContext() override; virtual ::oox::core::ContextHandlerRef onCreateContext( ::sal_Int32 Element, const ::oox::AttributeList& rAttribs ) override; diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx index 59f5e2a9e33d..68647b7906df 100644 --- a/include/oox/drawingml/shape.hxx +++ b/include/oox/drawingml/shape.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include #include #include #include @@ -79,7 +80,7 @@ struct ShapeStyleRef ShapeStyleRef() : mnThemedIdx(0) {} }; -typedef ::std::map< sal_Int32, ShapeStyleRef > ShapeStyleRefMap; +typedef ::std::unordered_map< sal_Int32, ShapeStyleRef > ShapeStyleRefMap; /** Additional information for a chart embedded in a drawing shape. */ struct ChartShapeInfo @@ -90,6 +91,14 @@ struct ChartShapeInfo explicit ChartShapeInfo( bool bEmbedShapes ) : mbEmbedShapes( bEmbedShapes ) {} }; +/// How much of a referenced shape's text the shape referencing it takes over. +enum class ReferencedShapeText +{ + All, ///< the paragraphs and how they are formatted + FormattingOnly, ///< how they are formatted, but none of the paragraphs themselves + Nothing +}; + /// Attributes for a linked textbox. struct LinkedTxbxAttr { @@ -174,6 +183,7 @@ public: void setDescription( const OUString& rDescr ) { msDescription = rDescr; } void setDecorative(bool const isDecorative) { m_isDecorative = isDecorative; } void setMacro(const OUString& rMacro) { msMacro = rMacro; } + void setMacroExtUrl(const OUString& rUrl) { msMacroExtUrl = rUrl; } void setTextLinkAttr(const OUString& rTextLink) { msTextLink = rTextLink; } void setFLocksText(bool bFLocksText) { mbFLocksText = bFLocksText; } void setFPublished(bool bFPublished) { mbFPublished = bFPublished; } @@ -222,7 +232,8 @@ public: const css::uno::Reference< css::drawing::XShape > & getXShape() const { return mxShape; } - SAL_DLLPRIVATE void applyShapeReference( const Shape& rReferencedShape, bool bUseText = true ); + SAL_DLLPRIVATE void applyShapeReference( const Shape& rReferencedShape, + ReferencedShapeText eText = ReferencedShapeText::All ); const ::std::vector& getExtDrawings() const { return maExtDrawings; } void addExtDrawingRelId( const OUString &rRelId ) { maExtDrawings.push_back( rRelId ); } @@ -249,6 +260,9 @@ public: bool isLinkedTxbx() const { return mbHasLinkedTxbx; }; void setCustomPrompt( bool bValue ) { mbHasCustomPrompt = bValue; } bool getCustomPrompt() const { return mbHasCustomPrompt; } + /** Whether the text this shape carries is a placeholder's prompt rather than content the + author typed. Only a presentation knows the difference, so it answers for itself. */ + virtual bool holdsPromptText() const { return false; } void setZOrder(sal_Int32 nZOrder) { mnZOrder = nZOrder; } @@ -272,7 +286,7 @@ public: /// Changes reference semantics to value semantics for fill properties. SAL_DLLPRIVATE void cloneFillProperties(); - SAL_DLLPRIVATE void keepDiagramDrawing(::oox::core::XmlFilterBase& rFilterBase, const OUString& rFragmentPath); + void keepDiagramDrawing(::oox::core::XmlFilterBase& rFilterBase, const OUString& rFragmentPath); // Allows preparation of a local Diagram helper && propagate an eventually // existing one to the data holder object later @@ -387,6 +401,8 @@ protected: /* specifies the custom function associated with the object. "macro" attribute for element */ OUString msMacro; + /* If msMacro is an external reference this stores the absolute URL of the external workbook */ + OUString msMacroExtUrl; /* specifies a formula linking to spreadsheet cell data. "textlink" attribute for element */ OUString msTextLink; @@ -447,7 +463,7 @@ private: /// Aspect ratio for an in-diagram shape. double mfAspectRatio = 0; - /// Number of child shapes to be layouted vertically inside org chart in-diagram shape. + /// Number of child shapes to be laid out vertically inside org chart in-diagram shape. sal_Int32 mnVerticalShapesCount = 0; // Is this a connector shape? diff --git a/include/oox/export/DMLPresetShapeExport.hxx b/include/oox/export/DMLPresetShapeExport.hxx index 7103175d2ce6..bec79491df4b 100644 --- a/include/oox/export/DMLPresetShapeExport.hxx +++ b/include/oox/export/DMLPresetShapeExport.hxx @@ -94,9 +94,6 @@ private: typedef AdjustmentPointValueBase XAdjustmentValue; typedef AdjustmentPointValueBase YAdjustmentValue; - // Returns true, if the shape has adjusting points - bool HasHandleValue() const; - // Returns true if the shape flipped. bool IsXFlipped() const { return m_bIsFlipped.first; }; bool IsYFlipped() const { return m_bIsFlipped.second; }; diff --git a/include/oox/export/ThemeExport.hxx b/include/oox/export/ThemeExport.hxx index 91c4b57ad8e8..90abaf6b1d2c 100644 --- a/include/oox/export/ThemeExport.hxx +++ b/include/oox/export/ThemeExport.hxx @@ -9,6 +9,7 @@ #pragma once +#include #include #include #include @@ -47,7 +48,7 @@ public: void writeComplexColor(model::ComplexColor const& rComplexColor); private: - bool writeColorSet(model::Theme const& rTheme); + void writeColorSet(std::shared_ptr const& rColorSet); bool writeFontScheme(model::FontScheme const& rFontScheme); bool writeFormatScheme(model::FormatScheme const& rFormatScheme); diff --git a/include/oox/export/chartexport.hxx b/include/oox/export/chartexport.hxx index b049a92aadba..2e35946c8e0e 100644 --- a/include/oox/export/chartexport.hxx +++ b/include/oox/export/chartexport.hxx @@ -77,21 +77,23 @@ namespace oox::drawingml { struct LabelPlacementParam; -enum AxesType +enum AxisType { - AXIS_PRIMARY_X = 1, - AXIS_PRIMARY_Y = 2, - AXIS_PRIMARY_Z = 3, - AXIS_SECONDARY_X = 4, - AXIS_SECONDARY_Y = 5 + AXIS_PRIMARY_X, + AXIS_PRIMARY_Y, + AXIS_PRIMARY_Z, + AXIS_SECONDARY_X, + AXIS_SECONDARY_Y, + AXIS_CATEGORY, // used for chartex + AXIS_VALUE // used for chartex }; -struct AxisIdPair{ - AxesType nAxisType; +struct AxisIdPair { + AxisType nAxisType; sal_Int32 nAxisId; sal_Int32 nCrossAx; - AxisIdPair(AxesType nType, sal_Int32 nId, sal_Int32 nAx) + AxisIdPair(AxisType nType, sal_Int32 nId, sal_Int32 nAx) : nAxisType(nType) , nAxisId(nId) , nCrossAx(nAx) @@ -143,6 +145,16 @@ public: bool mbLinkToExternalData = true; private: + struct ChartDimInfo + { + OUString sFormula; + OUString sNFormula; + OUString sDimTypeStr; // "val", "cat", "size", etc. + bool bIsNumeric = false; + bool bHasInfo = false; // true if chartex properties were found + }; + + sal_Int32 mnXmlNamespace; sal_Int32 mnSeriesCount; css::uno::Reference< css::frame::XModel > mxChartModel; @@ -151,7 +163,7 @@ private: std::shared_ptr mpURLTransformer; // members filled by InitRangeSegmentationProperties (retrieved from DataProvider) - bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false + bool mbHasCategoryLabels; // if the categories are only automatically generated this will be false //css::uno::Reference< css::drawing::XShapes > mxAdditionalShapes; css::uno::Reference< css::chart2::data::XDataSequence > mxCategoriesValues; @@ -201,6 +213,7 @@ private: void exportBitmapFill( const css::uno::Reference< css::beans::XPropertySet >& xPropSet ); void exportHatch(const css::uno::Reference& xPropSet); void exportDataTable( ); + ChartDimInfo getChartDimInfo( const css::uno::Reference& xSeq); void exportAreaChart( const css::uno::Reference< css::chart2::XChartType >& xChartType ); void exportBarChart( const css::uno::Reference< css::chart2::XChartType >& xChartType ); @@ -235,7 +248,7 @@ private: void exportVaryColors(const css::uno::Reference& xChartType); void exportCandleStickSeries( const css::uno::Sequence>& aSeriesSeq, - bool& rPrimaryAxes, sal_uInt32& nIdx); + bool& rPrimaryAxes); void exportSeriesText( const css::uno::Reference< css::chart2::data::XDataSequence >& xValueSeq, bool bIsChartex ); @@ -245,6 +258,8 @@ private: const css::uno::Reference< css::chart2::data::XDataSequence >& xValueSeq, sal_Int32 nValueType = XML_val ); void exportShapeProps( const css::uno::Reference< css::beans::XPropertySet >& xPropSet, sal_Int32 nNS); + static bool hasExplicitSpPr( + const css::uno::Reference< css::beans::XPropertySet >& xPropSet); void exportDataPoints( const css::uno::Reference< css::beans::XPropertySet >& xSeriesProperties, sal_Int32 nSeriesLength, sal_Int32 eChartType ); @@ -262,7 +277,8 @@ private: void exportManualLayout(const css::chart2::RelativePosition& rPos, const css::chart2::RelativeSize& rSize, const bool bIsExcludingDiagramPositioning); - void exportAxes( bool bIsChartex ); + void exportAxes_chart(); + void exportAxes_chartex(); void exportAxis(const AxisIdPair& rAxisIdPair, bool bIsChartex); void exportOneAxis_chart( @@ -280,7 +296,9 @@ private: const css::uno::Reference< css::beans::XPropertySet >& xMinorGrid, sal_Int32 nAxisType, const AxisIdPair& rAxisIdPair); - void createAxes(bool bPrimaryAxes, bool bCheckCombinedAxes, bool bIsChartex); + void createAxes_chart(bool bPrimaryAxes, bool bCheckCombinedAxes); + void createAxes_chartex( + const css::uno::Reference& xSeries); void exportView3D(); bool isDeep3dChart(); @@ -314,6 +332,8 @@ private: sal_Int32 nLabelIndex, DataLabelsRange& rDLblsRange, bool bIsChartex); + static void writeChartDim(const ::sax_fastparser::FSHelperPtr& pFS, const ChartDimInfo& rInfo, + bool *bIsCat /* output var: is this category data? */); public: OOX_DLLPUBLIC ChartExport( sal_Int32 nXmlNamespace, ::sax_fastparser::FSHelperPtr pFS, css::uno::Reference< css::frame::XModel > const & xModel, @@ -334,6 +354,6 @@ public: OOX_DLLPUBLIC OUString GetExternalDataPath() const; }; -} +} // namespace oox::drawingml /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/oox/export/chartgeographyexport.hxx b/include/oox/export/chartgeographyexport.hxx new file mode 100644 index 000000000000..be2945673097 --- /dev/null +++ b/include/oox/export/chartgeographyexport.hxx @@ -0,0 +1,23 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include +#include + +namespace oox::drawingml::chart +{ +void exportGeography(const css::uno::Reference& xSeriesProp, + const sax_fastparser::FSHelperPtr& pFS); + +} // namespace oox::drawingml::chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index e616b558dc3d..c0903b2f8a6d 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -114,6 +114,8 @@ public: virtual OUString getTransformedString(const OUString& rURL) const; virtual bool isExternalURL(const OUString& rURL) const; + + virtual sal_Int32 getExternalLinkIndex(const OUString& rUrl) const; }; // Our rotation is counter-clockwise and is in 100ths of a degree. @@ -272,7 +274,11 @@ public: , meDocumentType(eDocumentType) {} - OUString writeToStorage(Graphic const& rGraphic, bool bRelPathToMedia = false, TypeHint eHint = TypeHint::Detect); + // bReturnPath: + // false: it calls addRelation and returns the new RelationID. + // true: it writes no relation and returns the relativePath of the Image + // version using true can be used to export existing DiagramImageRels + OUString writeToStorage(Graphic const& rGraphic, bool bRelPathToMedia = false, TypeHint eHint = TypeHint::Detect, bool bReturnPath = false); void writeBlip(Graphic const& rGraphic, std::vector const& rEffects); void writeSvgExtension(OUString const& rSvgRelId); @@ -293,7 +299,7 @@ class DrawingML { private: - /// To specify where write eg. the images to (like 'ppt', or 'word' - according to the OPC). + /// To specify where to write eg. the images to (like 'ppt', or 'word' - according to the OPC). DocumentType meDocumentType; /// Parent exporter, used for text callback. DMLTextExport* mpTextExport; @@ -314,6 +320,7 @@ protected: /// True when DiagramReplacementVisualization is exported bool mbDiagaramExport; + bool mbDiagaramReplacementExport; bool mbEmbedFonts = false; @@ -375,6 +382,10 @@ public: /// The application-specific text exporter callback, if there is one. DMLTextExport* GetTextExport() { return mpTextExport; } + /// get/set mbDiagaramReplacementExport + void setDiagaramReplacementExport(bool bNew) { mbDiagaramReplacementExport = bNew; } + bool isDiagaramReplacementExport() const { return mbDiagaramReplacementExport;} + /// get/set mbDiagaramExport void setDiagaramExport(bool bNew) { mbDiagaramExport = bNew; } bool isDiagaramExport() const { return mbDiagaramExport;} @@ -382,9 +393,16 @@ public: void SetParent(const css::uno::Reference& xShape) { m_xParent = xShape; } void SetBackgroundDark(bool bIsDark) { mbIsBackgroundDark = bIsDark; } + /// If bRelPathToMedia is true add "../" to image folder path while adding the image relationship OOX_DLLPUBLIC OUString writeGraphicToStorage(const Graphic &rGraphic , bool bRelPathToMedia = false, GraphicExport::TypeHint eHint = GraphicExport::TypeHint::Detect); + /// specialized version of writeGraphicToStorage for writing existing DiagramImageRels, look for + // DomMapFlag::OOXDrawingImageRels and DomMapFlag::OOXDataImageRels. It writes data for *existing* + // relations that were imported and not touched. It returns the path of the image, *not* a new + // relation ID. That way already existing images can be re-used and shared. + OOX_DLLPUBLIC OUString writeImageRelToStorage(const Graphic &rGraphic); + void WriteColor( ::Color nColor, sal_Int32 nAlpha = MAX_PERCENT ); void WriteColor( const OUString& sColorSchemeName, const css::uno::Sequence< css::beans::PropertyValue >& aTransformations, sal_Int32 nAlpha = MAX_PERCENT ); void WriteColor( const ::Color nColor, const css::uno::Sequence< css::beans::PropertyValue >& aTransformations, sal_Int32 nAlpha = MAX_PERCENT ); @@ -507,6 +525,14 @@ public: const css::uno::Reference& rXShape, const SdrObjCustomShape& rSdrObjCustomShape); void WriteEmptyCustomGeometry(); + /** Writes a graphic object's clip polygon as the shape's own geometry. + + Returns false when the shape has no clip polygon, so that the caller can write the geometry + it would have written anyway. + */ + OOX_DLLPUBLIC bool WriteGraphicClipCustomGeometry( + const css::uno::Reference& rXPropSet, + const css::awt::Size& rSize); void WritePolyPolygon(const css::uno::Reference& rXShape, const bool bClosed); OOX_DLLPUBLIC void WriteFill(const css::uno::Reference& xPropSet, @@ -526,8 +552,7 @@ public: OOX_DLLPUBLIC void WriteDiagram(const css::uno::Reference& rXShape, sal_Int32 nDiagramId, sal_Int32 nShapeId = -1); void writeDiagramImageRels(const css::uno::Sequence>& xRelSeq, - const css::uno::Reference& xOutStream, - std::u16string_view sGrabBagProperyName, int nDiagramId); + const css::uno::Reference& xOutStream); void writeDiagramHlinkRels(const css::uno::Sequence>& xRelSeq, const css::uno::Reference& xOutStream); static void WriteFromTo(const css::uno::Reference& rXShape, const css::awt::Size& aPageSize, @@ -541,8 +566,6 @@ public: static sal_Unicode SubstituteBullet( sal_Unicode cBulletId, css::awt::FontDescriptor& rFontDesc ); - static ::Color ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity ); - static const char* GetAlignment(css::style::ParagraphAdjust nAlignment, bool bRTL, bool bPlaceHolder); diff --git a/include/oox/export/shapes.hxx b/include/oox/export/shapes.hxx index a75334c4f94f..f0e359727b60 100644 --- a/include/oox/export/shapes.hxx +++ b/include/oox/export/shapes.hxx @@ -123,7 +123,7 @@ public: WriteCustomShape( const css::uno::Reference< css::drawing::XShape >& xShape ); ShapeExport& WriteEllipseShape( const css::uno::Reference< css::drawing::XShape >& xShape ); - ShapeExport& + virtual ShapeExport& WriteGraphicObjectShape( const css::uno::Reference< css::drawing::XShape >& xShape ); ShapeExport& WriteGroupShape( const css::uno::Reference< css::drawing::XShape >& xShape ); @@ -178,7 +178,9 @@ public: * @return *this */ ShapeExport& WriteShape( const css::uno::Reference< css::drawing::XShape >& xShape ); - ShapeExport& WriteTextBox( const css::uno::Reference< css::uno::XInterface >& xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles = false ); + /** @param bText false writes the body properties and an empty paragraph, for a shape whose + text belongs to the application rather than to the file - a placeholder's prompt. */ + ShapeExport& WriteTextBox( const css::uno::Reference< css::uno::XInterface >& xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles = false, bool bText = true ); virtual ShapeExport& WriteTextShape( const css::uno::Reference< css::drawing::XShape >& xShape ); ShapeExport& @@ -197,6 +199,7 @@ public: void WriteTableCellBorders(const css::uno::Reference< css::beans::XPropertySet >& rXPropSet); sal_Int32 GetNewShapeID( const css::uno::Reference< css::drawing::XShape >& rShape ); + sal_Int32 GetTmpShapeID(); sal_Int32 GetShapeID( const css::uno::Reference< css::drawing::XShape >& rShape ); static sal_Int32 GetShapeID( const css::uno::Reference< css::drawing::XShape >& rShape, ShapeHashMap* pShapeMap ); }; diff --git a/include/oox/helper/graphichelper.hxx b/include/oox/helper/graphichelper.hxx index 87e7e85c9415..b543de814c85 100644 --- a/include/oox/helper/graphichelper.hxx +++ b/include/oox/helper/graphichelper.hxx @@ -36,6 +36,7 @@ struct WmfExternal; class OutputDevice; +class ImpGraphic; namespace com::sun::star { namespace awt { struct Point; } @@ -52,6 +53,10 @@ namespace oox { /** Provides helper functions for colors, device measurement conversion, graphics, and graphic objects handling. */ + +typedef std::tuple, sal_Int32, sal_Int32, sal_Int16> ColorChangeKey; +typedef std::map> ColorChangeCache; + class OOX_DLLPUBLIC GraphicHelper { public: @@ -140,6 +145,10 @@ public: void setGraphicMapper(css::uno::Reference const & rxGraphicMapper); void initializeGraphicMapperIfNeeded() const; + + css::uno::Reference getCachedColorChangeGraphic(const ColorChangeKey& rKey) const; + void addGraphicToColorChangeCache(const ColorChangeKey& rKey, const css::uno::Reference& xGraphic) const; + private: css::uno::Reference< css::uno::XComponentContext > mxContext; @@ -151,6 +160,7 @@ private: double mfPixelPerHmmX; ///< Number of screen pixels per 1/100 mm in X direction. double mfPixelPerHmmY; ///< Number of screen pixels per 1/100 mm in Y direction. css::uno::Reference mxGraphicMapper; + mutable ColorChangeCache maColorChangeCache; }; diff --git a/include/oox/helper/propertyset.hxx b/include/oox/helper/propertyset.hxx index 676ec4cebf82..6b6435598fe4 100644 --- a/include/oox/helper/propertyset.hxx +++ b/include/oox/helper/propertyset.hxx @@ -107,8 +107,6 @@ public: template< typename Type > bool setProperty( sal_Int32 nPropId, const Type& rValue ) { return setAnyProperty( nPropId, css::uno::Any( rValue ) ); } - bool setProperty( sal_Int32 nPropId, ::Color rValue ) - { return setAnyProperty( nPropId, css::uno::Any( rValue ) ); } /** Puts the passed properties into the property set. Tries to use the XMultiPropertySet interface. @param rPropNames The property names. MUST be ordered alphabetically. diff --git a/include/oox/mathml/importutils.hxx b/include/oox/mathml/importutils.hxx index 8aae6fe318b7..39133528e98a 100644 --- a/include/oox/mathml/importutils.hxx +++ b/include/oox/mathml/importutils.hxx @@ -6,8 +6,8 @@ * 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/. */ -#ifndef INCLUDED_OOX_MATHML_IMPORTUTILS_HXX -#define INCLUDED_OOX_MATHML_IMPORTUTILS_HXX + +#pragma once #include #include @@ -250,6 +250,4 @@ inline sal_Unicode XmlStream::Tag::attribute(int t, sal_Unicode def) const } // namespace -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/oox/ppt/pptshape.hxx b/include/oox/ppt/pptshape.hxx index e8fe6fbae4b5..77aa6cc1f00f 100644 --- a/include/oox/ppt/pptshape.hxx +++ b/include/oox/ppt/pptshape.hxx @@ -45,9 +45,9 @@ namespace oox::ppt { class PPTShape final : public oox::drawingml::Shape { OUString msModelId; // fallback dgs smartart shape reference - ShapeLocation meShapeLocation; // placeholdershapes (mnSubType != 0) on Master are never displayed - bool mbReferenced; // placeholdershapes on Layout are displayed only, if they are not referenced - // placeholdershapes on Slide are displayed always + ShapeLocation meShapeLocation; // placeholder shapes (mnSubType != 0) on Master are never displayed + bool mbReferenced; // placeholder shapes on Layout are displayed only if they are not referenced + // placeholder shapes on Slide are always displayed oox::drawingml::ShapePtr mpPlaceholder; /// Set if spPr tag is non empty for the shape bool mbHasNoninheritedShapeProperties; @@ -74,6 +74,12 @@ public: ::oox::drawingml::ShapeIdMap* pShapeMap ); ShapeLocation getShapeLocation() const { return meShapeLocation; }; + /** A placeholder states its prompt as text on a layout or a master; on a slide the same text + is what the author typed into it. */ + virtual bool holdsPromptText() const override + { + return mnSubType != 0 && meShapeLocation != Slide; + } void setReferenced( bool bReferenced ){ mbReferenced = bReferenced; }; void setPlaceholder(const oox::drawingml::ShapePtr& pPlaceholder) { mpPlaceholder = pPlaceholder; } void setModelId( const OUString& rId ) { msModelId = rId; } diff --git a/include/oox/ppt/presentationfragmenthandler.hxx b/include/oox/ppt/presentationfragmenthandler.hxx index 254bb50eebff..2cdd822be4d1 100644 --- a/include/oox/ppt/presentationfragmenthandler.hxx +++ b/include/oox/ppt/presentationfragmenthandler.hxx @@ -20,6 +20,7 @@ #ifndef INCLUDED_OOX_PPT_PRESENTATIONFRAGMENTHANDLER_HXX #define INCLUDED_OOX_PPT_PRESENTATIONFRAGMENTHANDLER_HXX +#include #include #include @@ -50,19 +51,31 @@ public: private: void importSlide( const ::oox::core::FragmentHandlerRef& rSlideFragmentHandler, const oox::ppt::SlidePersistPtr& rPersist ); - void importSlide(sal_uInt32 nSlide, bool bFirstSlide, bool bImportNotes); + void importSlide(sal_uInt32 nSlide, sal_Int32 nPagesImported, bool bImportNotes); void importMasterSlides(); void importMasterSlide(const css::uno::Reference& xModel, ::oox::ppt::PowerPointImport& rFilter, const OUString& rMasterFragmentPath); void saveThemeToGrabBag(const oox::drawingml::ThemePtr& pThemePtr, sal_Int32 nThemeIdx); void saveColorMapToGrabBag(const oox::drawingml::ClrMapPtr& pClrMapPtr); + void saveLayoutColorMapToGrabBag(const oox::drawingml::ClrMapPtr& pClrMapPtr, + sal_Int32 nMasterIndex); void importCustomSlideShow(std::vector& rCustomShowList); static void importSlideNames(const ::oox::core::XmlFilterBase& rFilter, const std::vector& rSlidePersist); + void saveSections(); + + struct SectionData + { + OUString maName; + OUString maId; + std::vector maSldIdList; + }; std::vector< OUString > maSlideMasterVector; std::vector< OUString > maSlidesVector; std::vector< OUString > maNotesMasterVector; + std::unordered_map< sal_Int32, sal_Int32 > maSlideIdToIndexMap; + std::vector< SectionData > maSectionList; ::oox::drawingml::TextListStylePtr mpTextListStyle; css::awt::Size maSlideSize; @@ -74,6 +87,7 @@ private: bool mbCommentAuthorsRead; // read commentAuthors.xml only once bool mbEmbedTrueTypeFonts = false; + bool mbInSectionExtension = false; }; } diff --git a/include/oox/ppt/slidepersist.hxx b/include/oox/ppt/slidepersist.hxx index d5b07909c3d7..4750be7d1069 100644 --- a/include/oox/ppt/slidepersist.hxx +++ b/include/oox/ppt/slidepersist.hxx @@ -90,7 +90,6 @@ public: const oox::drawingml::ClrMapPtr& getClrMap() const { return mpClrMapPtr; } void setBackgroundProperties( const oox::drawingml::FillPropertiesPtr& rFillPropertiesPtr ){ mpBackgroundPropertiesPtr = rFillPropertiesPtr; } - const oox::drawingml::FillPropertiesPtr& getBackgroundProperties() const { return mpBackgroundPropertiesPtr; } oox::drawingml::Color& getBackgroundColor() { return maBackgroundColor; } bool isMasterPage() const { return mbMaster; } @@ -117,6 +116,11 @@ public: void createBackground( const oox::core::XmlFilterBase& rFilterBase ); void applyTextStyles( const oox::core::XmlFilterBase& rFilterBase ); + /// Release import-side shape data after createXShapes has pushed + /// everything into the core model. + void releaseShapes(); + + std::map< OUString, css::uno::Reference< css::animations::XAnimationNode > >& getAnimNodesMap() { return maAnimNodesMap; }; css::uno::Reference getAnimationNode(const OUString& sId) const; ::oox::drawingml::ShapePtr getShape( const OUString & id ) { return maShapeMap[ id ]; } @@ -125,6 +129,8 @@ public: CommentList& getCommentsList() { return maCommentsList; } CommentAuthorList& getCommentAuthors() { return maCommentAuthors; } + const OUString& getTitleText() const { return maTitleText; } + void createConnectorShapeConnection(const oox::drawingml::ShapePtr& pConnector); private: @@ -155,6 +161,8 @@ private: std::map< OUString, css::uno::Reference< css::animations::XAnimationNode > > maAnimNodesMap; std::map< OUString, ::oox::drawingml::ShapePtr > maShapeMap; + OUString maTitleText; + // slide comments CommentList maCommentsList; CommentAuthorList maCommentAuthors; diff --git a/include/oox/token/relationship.hxx b/include/oox/token/relationship.hxx index 56640076f854..e454330c64d9 100644 --- a/include/oox/token/relationship.hxx +++ b/include/oox/token/relationship.hxx @@ -40,6 +40,8 @@ enum class Relationship DRAWING, ENDNOTES, EXTERNALLINKPATH, + MISSINGEXTERNALLINKPATH, + XLSTARTUPEXTERNALLINKPATH, FONT, FONTTABLE, FOOTER, @@ -59,6 +61,7 @@ enum class Relationship PRESPROPS, SETTINGS, SHAREDSTRINGS, + SHEETMETADATA, SLIDE, SLIDELAYOUT, SLIDEMASTER, @@ -68,9 +71,12 @@ enum class Relationship VIDEO, AUDIO, VMLDRAWING, + WEBSETTINGS, WORDVBADATA, WORKSHEET, XMLMAPS, + THREADEDCOMMENT, + PERSON, NUM_ENTRIES // last, unused }; diff --git a/include/oox/vml/vmlshape.hxx b/include/oox/vml/vmlshape.hxx index c960d9d8da46..23e8641f8834 100644 --- a/include/oox/vml/vmlshape.hxx +++ b/include/oox/vml/vmlshape.hxx @@ -85,6 +85,7 @@ struct ShapeTypeModel OUString maFlip; ///< Flip type of the shape (can be "x" or "y"). bool mbAutoHeight; ///< If true, the height value is a minimum value (mostly used for textboxes) bool mbVisible; ///< Visible or Hidden + bool mbHorizontalRule = false; ///< o:hr, a horizontal rule with its own layout rules OUString maWrapStyle; ///< Wrapping mode for text. OUString maArcsize; ///< round rectangles arc size OUString maEditAs; ///< Edit As type (e.g. "canvas" etc) @@ -106,7 +107,7 @@ struct ShapeTypeModel OUString maWrapDistanceRight; ///< Distance from the right side of the shape to the text that wraps around it. OUString maWrapDistanceTop; ///< Distance from the top of the shape to the text that wraps around it. OUString maWrapDistanceBottom; ///< Distance from the bottom of the shape to the text that wraps around it. - std::optional moCropBottom; ///< Specifies the how much to crop the image from the bottom up as a fraction of picture size. + std::optional moCropBottom; ///< Specifies how much to crop the image from the bottom up as a fraction of picture size. std::optional moCropLeft; ///< Specifies how much to crop the image from the left in as a fraction of picture size. std::optional moCropRight; ///< Specifies how much to crop the image from the right in as a fraction of picture size. std::optional moCropTop; ///< Specifies how much to crop the image from the top down as a fraction of picture size. diff --git a/include/oox/vml/vmlshapecontainer.hxx b/include/oox/vml/vmlshapecontainer.hxx index a7cd961ad6b7..40fc00f9654d 100644 --- a/include/oox/vml/vmlshapecontainer.hxx +++ b/include/oox/vml/vmlshapecontainer.hxx @@ -79,11 +79,6 @@ public: Searches in all group shapes too. */ const ShapeBase* getShapeById( const OUString& rShapeId ) const; - /** Searches for a shape by using the passed functor that takes a constant - reference of a ShapeBase object. */ - template< typename Functor > - const ShapeBase* findShape( const Functor& rFunctor ) const; - /** (Word only) Returns the last shape in the collection, if it is after the last mark from pushMark(), and removes it. @@ -132,13 +127,6 @@ std::shared_ptr ShapeContainer::createShape() return xShape; } -template< typename Functor > -const ShapeBase* ShapeContainer::findShape( const Functor& rFunctor ) const -{ - return maShapes.findIf( rFunctor ).get(); -} - - } // namespace oox::vml #endif diff --git a/include/oox/vml/vmltextbox.hxx b/include/oox/vml/vmltextbox.hxx index 66e1e7273769..39b5e106b709 100644 --- a/include/oox/vml/vmltextbox.hxx +++ b/include/oox/vml/vmltextbox.hxx @@ -53,7 +53,8 @@ struct OOX_DLLPUBLIC TextFontModel std::optional< OUString > moNameComplex; ///< Complex font name. std::optional< OUString > moColor; ///< Font color, HTML encoded, sort of. std::optional< sal_Int32 > monSize; ///< Font size in twips. - std::optional< sal_Int32 > monUnderline; ///< Single or double underline. + std::optional mobUnderline; ///< Underlined text. + std::optional moUnderlineClass; ///< Font record naming the underline style. std::optional< sal_Int32 > monEscapement; ///< Subscript or superscript. std::optional< bool > mobBold; std::optional< bool > mobItalic; diff --git a/include/opencl/platforminfo.hxx b/include/opencl/platforminfo.hxx index 4cfaf8c8986b..b8b6c3e836c3 100644 --- a/include/opencl/platforminfo.hxx +++ b/include/opencl/platforminfo.hxx @@ -17,7 +17,7 @@ #include #include -// Struct that describs an actual instance of an OpenCL device +// Struct that describes an actual instance of an OpenCL device struct OpenCLDeviceInfo { @@ -32,7 +32,7 @@ struct OpenCLDeviceInfo OpenCLDeviceInfo(); }; -// Struct that describs an actual instance of an OpenCL platform implementation +// Struct that describes an actual instance of an OpenCL platform implementation struct OpenCLPlatformInfo { diff --git a/include/osl/detail/android-bootstrap.h b/include/osl/detail/android-bootstrap.h index 169f3efaf282..5a5c7fcbd82d 100644 --- a/include/osl/detail/android-bootstrap.h +++ b/include/osl/detail/android-bootstrap.h @@ -35,10 +35,6 @@ int lo_apk_closedir(lo_apk_dir *dirp); int lo_apk_lstat(const char *path, struct stat *statp); -/// "libreofficekit_" prefix, because it is exported from the .so, when we are -/// initializing the JNI externally. -void libreofficekit_set_javavm(JavaVM *vm); - JavaVM *lo_get_javavm(void); const char *lo_get_app_data_dir(void); diff --git a/include/osl/detail/component-mapping.h b/include/osl/detail/component-mapping.h index 64c967019ba0..9c09ce6a0f9f 100644 --- a/include/osl/detail/component-mapping.h +++ b/include/osl/detail/component-mapping.h @@ -18,10 +18,10 @@ extern "C" { /* On iOS and perhaps Android static linking of the LO code into one * executable (on Android, into one shared library) is used. In order to get - * the needed UNO component linked in, the "main" code for an app needs to - * implement the lo_get_libmap() function to map UNO component library names - * as produced in a build for iOS (like configmgr.uno.a or libsclo.a) to the - * corresponding component_getFactory functions. + * the needed UNO components linked in, the "main" code for an app needs to + * implement the lo_get_factory_map() and lo_get_constructor_map() functions + * to map UNO component library names as produced in a build for iOS (like + * configmgr.uno.a or libsclo.a) to the corresponding component_getFactory functions. */ typedef struct { diff --git a/include/osl/detail/emscripten-bootstrap.h b/include/osl/detail/emscripten-bootstrap.h index 580964253377..ae1b51a61fbc 100644 --- a/include/osl/detail/emscripten-bootstrap.h +++ b/include/osl/detail/emscripten-bootstrap.h @@ -9,7 +9,7 @@ #pragma once -#if defined(EMSCRIPTEN) +#if defined(__EMSCRIPTEN__) #ifdef __cplusplus extern "C" { @@ -21,6 +21,6 @@ const char *lo_get_app_data_dir(void); } #endif -#endif // EMSCRIPTEN +#endif // __EMSCRIPTEN__ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/osl/doublecheckedlocking.h b/include/osl/doublecheckedlocking.h index f89ab362055b..e00e788910bd 100644 --- a/include/osl/doublecheckedlocking.h +++ b/include/osl/doublecheckedlocking.h @@ -39,7 +39,7 @@ extern "C" { empty. This is a macro instead of a (C++ inline) function to allow for maximum performance in both C and C++. - If possible, use the rtl_Instance template instead of explicitly spelling + If possible, use the rtl::Instance template instead of explicitly spelling out the double-checked locking pattern. There are few cases where you will have to spell it out explicitly (e.g., the logic of a certain instance of the pattern is too complex to be mapped to the template, or diff --git a/include/osl/endian.h b/include/osl/endian.h index 8dd5387c0b84..00ad2352f740 100644 --- a/include/osl/endian.h +++ b/include/osl/endian.h @@ -67,7 +67,7 @@ extern "C" { # elif defined _BIG_ENDIAN # define OSL_BIGENDIAN # endif -#elif defined EMSCRIPTEN +#elif defined __EMSCRIPTEN__ # define OSL_LITENDIAN #else # error "Target platform not specified !" diff --git a/include/osl/file.h b/include/osl/file.h index 07d2beb2ae1f..2179f531e3aa 100644 --- a/include/osl/file.h +++ b/include/osl/file.h @@ -44,7 +44,7 @@ system. There are a few main goals: -1. The path specifications always has to be absolute. Any usage of relative +1. The path specifications always have to be absolute. Any usage of relative path specifications is forbidden. Exceptions are osl_getSystemPathFromFileURL, osl_getFileURLFromSystemPath and osl_getAbsoluteFileURL. Most operating systems provide a "Current Directory" per process. This is the reason why @@ -52,8 +52,8 @@ relative path specifications can cause problems in multithreading environments. 2. Proprietary notations of file paths are not supported. Every path notation -must the file URL specification. File URLs must be encoded in UTF8 and after -that escaped. Although the URL parameter is a unicode string, the must +must follow the file URL specification. File URLs must be encoded in UTF8 and after +that escaped. Although the URL parameter is a unicode string, it must contain only ASCII characters. 3. The caller cannot get any information whether a file system is case @@ -129,7 +129,7 @@ typedef enum { osl_File_E_ILSEQ, /*!< invalid or incomplete byte sequence of multibyte char found */ osl_File_E_NOLINK, /*!< link has been severed */ osl_File_E_MULTIHOP, /*!< remote resource is not directly available */ - osl_File_E_USERS, /*!< file quote system is confused as there are too many users */ + osl_File_E_USERS, /*!< file quota system is confused as there are too many users */ osl_File_E_OVERFLOW, /*!< value too large for defined data type */ osl_File_E_NOTREADY, /*!< device not ready */ osl_File_E_invalidError, /*!< unmapped error: always last entry in enum! */ @@ -298,7 +298,7 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_acquireDirectoryItem( SAL_DLLPUBLIC oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item ); -/** Determine if two directory items point the same underlying file +/** Determine if two directory items point to the same underlying file The comparison is done first by URL, and then by resolving links to find the target, and finally by comparing inodes on unix. @@ -509,7 +509,7 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( @retval osl_File_E_NODEV no such device @retval osl_File_E_NOENT no such file or directory @retval osl_File_E_FAULT bad address - @retval osl_FilE_E_INTR function call was interrupted + @retval osl_File_E_INTR function call was interrupted @retval osl_File_E_IO on I/O errors @retval osl_File_E_MULTIHOP multihop attempted @retval osl_File_E_NOLINK link has been severed @@ -612,7 +612,7 @@ typedef struct _oslVolumeInfo { @retval osl_File_E_NOENT no such file or directory @retval osl_File_E_ACCES permission denied @retval osl_File_E_LOOP too many symbolic links encountered - @retval ols_File_E_FAULT Bad address + @retval osl_File_E_FAULT Bad address @retval osl_File_E_IO on I/O errors @retval osl_File_E_NOSYS function not implemented @retval osl_File_E_MULTIHOP multihop attempted @@ -676,7 +676,7 @@ typedef void *oslFileHandle; @retval osl_File_E_NFILE too many open files in the system @retval osl_File_E_DQUOT quota exceeded @retval osl_File_E_EXIST file exists - @retval osl_FilE_E_INTR function call was interrupted + @retval osl_File_E_INTR function call was interrupted @retval osl_File_E_IO on I/O errors @retval osl_File_E_MULTIHOP multihop attempted @retval osl_File_E_NOLINK link has been severed @@ -748,7 +748,7 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_getFilePos( /** Set the file size of an open file. Sets the file size of an open file. The file can be truncated or enlarged by the function. - The position of the file pointer is not affeced by this function. + The position of the file pointer is not affected by this function. @param[in] Handle Handle to a file received by a previous call to osl_openFile(). @@ -772,7 +772,7 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_setFileSize( /** Get the file size of an open file. Gets the file size of an open file. - The position of the file pointer is not affeced by this function. + The position of the file pointer is not affected by this function. @param[in] Handle Handle to a file received by a previous call to osl_openFile(). @@ -1121,7 +1121,7 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_readLine( @retval osl_File_E_INVAL The value of the input parameter is invalid @retval osl_File_E_BADF The file associated with the given file handle is not open for writing @retval osl_File_E_IO An I/O error occurred - @retval osl_File_E_NOSPC There is no enough space on the target device + @retval osl_File_E_NOSPC There is not enough space on the target device @retval osl_File_E_ROFS The file associated with the given file handle is located on a read only file system @retval osl_File_E_TIMEDOUT A remote connection timed out. This may happen when a file is on a remote location @@ -1165,7 +1165,7 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_closeFile( oslFileHandle Handle ); @retval osl_File_E_DQUOT quota exceeded @retval osl_File_E_LOOP too many symbolic links encountered @retval osl_File_E_FAULT bad address - @retval osl_FileE_IO on I/O errors + @retval osl_File_E_IO on I/O errors @retval osl_File_E_MLINK too many links @retval osl_File_E_MULTIHOP multihop attempted @retval osl_File_E_NOLINK link has been severed @@ -1262,9 +1262,9 @@ typedef void (SAL_CALL *oslDirectoryCreationCallbackFunc)(void* pData, rtl_uStri @retval osl_File_E_None On success @retval osl_File_E_INVAL The format of the parameters was not valid @retval osl_File_E_ACCES Permission denied - @retval osl_File_E_EXIST The final node of the specified directory path already exist + @retval osl_File_E_EXIST The final node of the specified directory path already exists @retval osl_File_E_NAMETOOLONG The name of the specified directory path exceeds the maximum allowed length - @retval osl_File_E_NOTDIR A component of the specified directory path already exist as file in any part of the directory path + @retval osl_File_E_NOTDIR A component of the specified directory path already exists as a file in any part of the directory path @retval osl_File_E_ROFS Read-only file system @retval osl_File_E_NOSPC No space left on device @retval osl_File_E_DQUOT Quota exceeded @@ -1349,7 +1349,7 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_copyFile( Full qualified URL of the source file. @param[in] pustrDestFileURL - Full qualified URL of the destination file. An existing directory is NOT a valid destination ! + Full qualified URL of the destination file. An existing directory is NOT a valid destination! @retval osl_File_E_None on success @retval osl_File_E_INVAL the format of the parameters was not valid @@ -1389,9 +1389,9 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_moveFile( SAL_DLLPUBLIC oslFileError SAL_CALL osl_getCanonicalName( rtl_uString *pustrRequestedURL, rtl_uString **ppustrValidURL); -/** Convert a path relative to a given directory into an full qualified file URL. +/** Convert a path relative to a given directory into a fully qualified file URL. - Convert a path relative to a given directory into an full qualified file URL. + Convert a path relative to a given directory into a fully qualified file URL. The function resolves symbolic links if possible and path ellipses, so on success the resulting absolute path is fully resolved. @@ -1404,7 +1404,7 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_getCanonicalName( If pustrRelativeFileURL denotes an absolute path pustrBaseDirectoryURL will be ignored. @param[out] ppustrAbsoluteFileURL - On success it receives the full qualified absolute file URL. + On success it receives the fully qualified absolute file URL. @retval osl_File_E_None on success @retval osl_File_E_INVAL the format of the parameters was not valid @@ -1595,12 +1595,12 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_getTempDirURL( responsible for removing the file on success. Description of the different pHandle, ppustrTempFileURL parameter combinations. - pHandle is 0 and ppustrTempDirURL is 0 - this combination is invalid - pHandle is not 0 and ppustrTempDirURL is 0 - a handle to the open file + pHandle is 0 and ppustrTempFileURL is 0 - this combination is invalid + pHandle is not 0 and ppustrTempFileURL is 0 - a handle to the open file will be returned on success and the file will be automatically removed on close. - pHandle is 0 and ppustrTempDirURL is not 0 - the name of the file will be returned, + pHandle is 0 and ppustrTempFileURL is not 0 - the name of the file will be returned, the caller is responsible for opening, closing and removing the file. - pHandle is not 0 and ppustrTempDirURL is not 0 - a handle to the open file as well as + pHandle is not 0 and ppustrTempFileURL is not 0 - a handle to the open file as well as the file name will be returned, the caller is responsible for closing and removing the file. @@ -1639,7 +1639,7 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_createTempFile( /** Move a file to a new destination or rename it, taking old file's identity (if exists). - Moves or renames a file, replacing an existing file if exist. If the old file existed, + Moves or renames a file, replacing an existing file if it exists. If the old file existed, moved file's metadata, e.g. creation time (on FSes which keep files' creation time) or ACLs, are set to old one's (to keep the old file's identity) - currently this is only implemented fully on Windows; on other platforms, this is mostly equivalent to osl_moveFile. diff --git a/include/osl/file.hxx b/include/osl/file.hxx index 1f1121d547e2..8cfded475327 100644 --- a/include/osl/file.hxx +++ b/include/osl/file.hxx @@ -132,9 +132,9 @@ public: return static_cast< RC >( osl_getCanonicalName( ustrRequestedURL.pData, &ustrValidURL.pData ) ); } - /** Convert a path relative to a given directory into an full qualified file URL. + /** Convert a path relative to a given directory into a fully qualified file URL. - Convert a path relative to a given directory into an full qualified file URL. + Convert a path relative to a given directory into a fully qualified file URL. The function resolves symbolic links if possible and path ellipses, so on success the resulting absolute path is fully resolved. @@ -147,7 +147,7 @@ public: If ustrRelativeFileURL denotes an absolute path ustrBaseDirectoryURL will be ignored. @param[out] ustrAbsoluteFileURL - On success it receives the full qualified absolute file URL. + On success it receives the fully qualified absolute file URL. @retval E_None on success @retval E_INVAL the format of the parameters was not valid @@ -1072,7 +1072,7 @@ public: /** Set the file size of an open file. Sets the file size of an open file. The file can be truncated or enlarged by the function. - The position of the file pointer is not affeced by this function. + The position of the file pointer is not affected by this function. @param[in] uSize New size in bytes. @@ -1094,7 +1094,7 @@ public: /** Get the file size of an open file. Gets the file size of an open file. - The position of the file pointer is not affeced by this function. + The position of the file pointer is not affected by this function. @param[out] rSize Current size in bytes. diff --git a/include/osl/interlck.h b/include/osl/interlck.h index f0a39e52c74e..338277c7f738 100644 --- a/include/osl/interlck.h +++ b/include/osl/interlck.h @@ -49,8 +49,8 @@ typedef sal_Int32 oslInterlockedCount; */ SAL_DLLPUBLIC oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount); -/** Decrement the count variable addressed by pCount. - @param pCount Address of count variable +/** Decrements the count variable addressed by pCount. + @param pCount Address of count variable. @return The adjusted value of the count variable. */ SAL_DLLPUBLIC oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount); diff --git a/include/package/InflateZstd.hxx b/include/package/InflateZstd.hxx deleted file mode 100644 index ea627565b9b5..000000000000 --- a/include/package/InflateZstd.hxx +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include -#include -#include -#include - -namespace ZipUtils -{ -class DLLPUBLIC_PACKAGE InflateZstd : public Inflater -{ -private: - bool bFinished; - sal_Int32 nLastInflateError; - css::uno::Sequence sInBuffer; - ZSTD_DCtx* pDCtx; - ZSTD_inBuffer inBuffer; - bool bStreamInitialized; - - sal_Int32 doInflateBytes(css::uno::Sequence& rBuffer, sal_Int32 nNewOffset, - sal_Int32 nNewLength); - -public: - explicit InflateZstd(bool bNoWrap = false); - virtual ~InflateZstd() override; - - virtual void setInput(const css::uno::Sequence& rBuffer) override; - virtual bool needsDictionary() const override { return false; } - virtual bool finished() const override { return bFinished; } - virtual sal_Int32 doInflateSegment(css::uno::Sequence& rBuffer, sal_Int32 nNewOffset, - sal_Int32 nNewLength) override; - virtual void end() override final; - virtual sal_Int32 getLastInflateError() const override { return nLastInflateError; } -}; - -} // namespace ZipUtils - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/postmac.h b/include/postmac.h index bfeb88dfd34c..1108c685ab23 100644 --- a/include/postmac.h +++ b/include/postmac.h @@ -21,5 +21,6 @@ #undef Size #undef TimeValue #undef TimeRecord +#undef UInt /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/premac.h b/include/premac.h index 5a2707d19617..dc76edade8a4 100644 --- a/include/premac.h +++ b/include/premac.h @@ -21,5 +21,6 @@ #define Size MacOSSize #define TimeValue MacOSTimeValue #define TimeRecord MacOSTimeRecord +#define UInt MacOSUInt /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/registry/types.hxx b/include/registry/types.hxx index 820e342a7323..7c073b24b294 100644 --- a/include/registry/types.hxx +++ b/include/registry/types.hxx @@ -71,7 +71,7 @@ enum RTTypeClass RT_TYPE_SERVICE, /** specifies that the blob represents a singleton type (a named object) - which refers exactly one existing service. + which refers to exactly one existing service. */ RT_TYPE_SINGLETON, @@ -228,7 +228,7 @@ union RTConstValueUnion { /** specifies the mode of a method. - A method can be synchron or asynchron (oneway). The const attribute for + A method can be synchronous or asynchronous (oneway). The const attribute for methods was removed so that the const values are deprecated. */ enum class RTMethodMode @@ -242,7 +242,7 @@ enum class RTMethodMode /// @deprecated ONEWAY_CONST, - /// indicated the synchronous mode of a method + /// indicates the synchronous mode of a method TWOWAY, /// @deprecated @@ -267,7 +267,7 @@ enum class RTMethodMode /** specifies the mode of a parameter. - There are three parameter modes which have impact of the handling of the + There are three parameter modes which have an impact on the handling of the parameter in the UNO bridges and the UNO code generation. */ enum RTParamMode @@ -281,7 +281,7 @@ enum RTParamMode /// indicates a pure out parameter which is used by reference RT_PARAM_OUT = 2, - /// indicates a in and out parameter which is used also by reference + /// indicates an in and out parameter which is used also by reference RT_PARAM_INOUT = 3, /** @@ -304,7 +304,7 @@ enum class RTReferenceType /// the reference type is unknown INVALID, - /** the service support the interface that means an implementation of this + /** the service supports the interface that means an implementation of this service must implement this interface. */ SUPPORTS, diff --git a/include/rtl/byteseq.h b/include/rtl/byteseq.h index 2acb9b745d9a..cede228b5e2c 100644 --- a/include/rtl/byteseq.h +++ b/include/rtl/byteseq.h @@ -68,7 +68,7 @@ SAL_DLLPUBLIC void SAL_CALL rtl_byte_sequence_release( sal_Sequence *pSequence ) SAL_THROW_EXTERN_C(); -/** Constructs a bytes sequence with length nLength. All bytes are set to zero. +/** Constructs a byte sequence with length nLength. All bytes are set to zero. @param ppSequence inout sequence; on entry *ppSequence may be null, otherwise it is released; after the call, *ppSequence contains the newly constructed sequence @@ -78,7 +78,7 @@ SAL_DLLPUBLIC void SAL_CALL rtl_byte_sequence_construct( sal_Sequence **ppSequence , sal_Int32 nLength ) SAL_THROW_EXTERN_C(); -/** Constructs a bytes sequence with length nLength. The data is not initialized. +/** Constructs a byte sequence with length nLength. The data is not initialized. @param ppSequence inout sequence; on entry *ppSequence may be null, otherwise it is released; after the call, *ppSequence contains the newly constructed sequence @@ -120,7 +120,7 @@ SAL_DLLPUBLIC sal_Bool SAL_CALL rtl_byte_sequence_equals( /** Returns the data array pointer of the sequence. @return read-pointer to the data array of the sequence. If rtl_byte_sequence_reference2One() - has been called before, the pointer may be casted to a non const pointer and + has been called before, the pointer may be cast to a non const pointer and the sequence may be modified */ SAL_DLLPUBLIC const sal_Int8 *SAL_CALL rtl_byte_sequence_getConstArray( @@ -222,7 +222,7 @@ public: /** Constructor: Creates a sequence from a C-Handle without acquiring the handle, thus taking over ownership. Eitherway the handle is released by the destructor. - This ctor is useful, when working with a c-interface (it safes a pair of + This ctor is useful, when working with a c-interface (it saves a pair of acquire and release call and is thus a performance optimization only). @param pSequence sequence handle to be taken over @@ -295,7 +295,7 @@ public: @return true if both sequences are equal, false otherwise */ inline bool SAL_CALL operator == ( const ByteSequence & rSeq ) const; - /** Unequality operator: Compares two sequences. + /** Inequality operator: Compares two sequences. @param rSeq another byte sequence (right side) @return false if both sequences are equal, true otherwise diff --git a/include/rtl/string.hxx b/include/rtl/string.hxx index 26b4e2515085..7535f4281702 100644 --- a/include/rtl/string.hxx +++ b/include/rtl/string.hxx @@ -148,8 +148,6 @@ public: }; }; -#if !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) - namespace detail { template struct OStringHolder { @@ -160,8 +158,6 @@ template struct OStringHolder { #endif -#endif - /* ======================================================================= */ /** @@ -199,12 +195,12 @@ public: /** New string containing no characters. */ -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY constexpr #endif OString() { -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY pData = const_cast(&empty.str); #else pData = NULL; @@ -217,13 +213,13 @@ public: @param str an OString. */ -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY constexpr #endif OString( const OString & str ) { pData = str.pData; -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY if (std::is_constant_evaluated()) { //TODO: We would want to // @@ -244,13 +240,10 @@ public: @param str an OString. @since LibreOffice 5.2 */ -#if !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) constexpr -#endif OString( OString && str ) noexcept { pData = str.pData; -#if !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) if (std::is_constant_evaluated()) { //TODO: We would want to // @@ -260,7 +253,6 @@ public: // anonymous union with active member `more` is not allowed in a constant expression. return; } -#endif str.pData = nullptr; rtl_string_new( &str.pData ); } @@ -395,7 +387,7 @@ public: /// @endcond #endif -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY // For operator ""_tstr: template constexpr OString(detail::OStringHolder const & holder): pData(const_cast(&holder.literal.str)) {} @@ -471,12 +463,12 @@ public: /** Release the string data. */ -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY constexpr #endif ~OString() { -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY if (std::is_constant_evaluated()) { //TODO: We would want to // @@ -1221,6 +1213,66 @@ public: } #endif + /** + Check whether this string starts with a given character. + + @param ch the character to be compared + + @return true if and only if the given character appears at the start of this string + + @since LibreOffice 26.8 + */ + bool startsWith(char ch) const + { + return !isEmpty() && pData->buffer[0] == ch; + } + + /** + Check whether this string starts with a given character. + + @param ch the character to be compared + + @param rest if this function returns true, then assign a + copy of the remainder of this string to *rest. + + @return true if and only if the given character appears at the start of this string + + @since LibreOffice 26.8 + */ + bool startsWith(char ch, OString* rest) const { + assert(rest); + bool b = startsWith(ch); + + if (b) + *rest = copy(1); + + return b; + } + +#if defined LIBO_INTERNAL_ONLY + /** + Check whether this string starts with a given character. + + @param ch the character to be compared + + @param rest if this function returns true, then assign a + copy of the remainder of this string to *rest. + + @return true if and only if the given character appears at the start of this string + + @since LibreOffice 26.8 + */ + bool startsWith(char ch, std::string_view* rest) const { + assert(rest); + bool b = startsWith(ch); + + if (b) + *rest = subView(1); + + return b; + } +#endif + #if defined LIBO_INTERNAL_ONLY /** Check whether this string starts with a given string, ignoring the case of @@ -1595,6 +1647,66 @@ public: && matchL(str, strLength, getLength() - strLength); } + /** + Check whether this string ends with a given character. + + @param ch the character to be compared + + @return true if and only if the given character appears at the end of this string + + @since LibreOffice 26.8 + */ + bool endsWith(char ch) const + { + return !isEmpty() && pData->buffer[pData->length - 1] == ch; + } + + /** + Check whether this string ends with a given character. + + @param ch the character to be compared + + @param rest if this function returns true, then assign a + copy of the remainder of this string to *rest. + + @return true if and only if the given character appears at the end of this string + + @since LibreOffice 26.8 + */ + bool endsWith(char ch, OString* rest) const { + assert(rest); + bool b = endsWith(ch); + + if (b) + *rest = copy(0, pData->length - 1); + + return b; + } + +#if defined LIBO_INTERNAL_ONLY + /** + Check whether this string ends with a given character. + + @param ch the character to be compared + + @param rest if this function returns true, then assign a + copy of the remainder of this string to *rest. + + @return true if and only if the given character appears at the end of this string + + @since LibreOffice 26.8 + */ + bool endsWith(char ch, std::string_view* rest) const { + assert(rest); + bool b = endsWith(ch); + + if (b) + *rest = subView(0, pData->length - 1); + + return b; + } +#endif + friend bool operator == ( const OString& rStr1, const OString& rStr2 ) { return rStr1.equals(rStr2); } friend bool operator != ( const OString& rStr1, const OString& rStr2 ) @@ -2616,7 +2728,7 @@ public: #endif private: -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY static constexpr auto empty = OStringLiteral(""); // [-loplugin:ostr] #endif }; @@ -2737,7 +2849,7 @@ using ::rtl::OStringLiteral; using RepeatedChar = ::rtl::RepeatedChar_t; #endif -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY template< #if defined RTL_STRING_UNITTEST diff --git a/include/rtl/ustring.hxx b/include/rtl/ustring.hxx index 8fd6954bee8d..e6eb0e19bd26 100644 --- a/include/rtl/ustring.hxx +++ b/include/rtl/ustring.hxx @@ -29,15 +29,11 @@ #include #include #include -#include -#include #include #include #if defined LIBO_INTERNAL_ONLY #include -#include -#include #endif #include "rtl/math.h" @@ -178,12 +174,12 @@ public: /** New string containing no characters. */ -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY constexpr #endif OUString() { -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY pData = const_cast(&empty.str); #else pData = NULL; @@ -195,13 +191,13 @@ public: @param str an OUString. */ -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY constexpr #endif OUString( const OUString & str ) { pData = str.pData; -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY if (std::is_constant_evaluated()) { //TODO: We would want to // @@ -222,13 +218,10 @@ public: @param str an OUString. @since LibreOffice 5.2 */ -#if !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) constexpr -#endif OUString( OUString && str ) noexcept { pData = str.pData; -#if !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) if (std::is_constant_evaluated()) { //TODO: We would want to // @@ -238,7 +231,6 @@ public: // anonymous union with active member `more` is not allowed in a constant expression. return; } -#endif str.pData = nullptr; rtl_uString_new( &str.pData ); } @@ -429,7 +421,7 @@ public: /// @endcond #endif -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY // For operator ""_tstr: template OUString(detail::OStringHolder const & holder) { pData = nullptr; @@ -534,12 +526,12 @@ public: /** Release the string data. */ -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY constexpr #endif ~OUString() { -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY if (std::is_constant_evaluated()) { //TODO: We would want to // @@ -1622,6 +1614,66 @@ public: } #endif + /** + Check whether this string starts with a given character. + + @param ch the character to be compared + + @return true if and only if the given character appears at the start of this string + + @since LibreOffice 26.8 + */ + bool startsWith(sal_Unicode ch) const + { + return !isEmpty() && pData->buffer[0] == ch; + } + + /** + Check whether this string starts with a given character. + + @param ch the character to be compared + + @param rest if this function returns true, then assign a + copy of the remainder of this string to *rest. + + @return true if and only if the given character appears at the start of this string + + @since LibreOffice 26.8 + */ + bool startsWith(sal_Unicode ch, OUString* rest) const { + assert(rest); + bool b = startsWith(ch); + + if (b) + *rest = copy(1); + + return b; + } + +#if defined LIBO_INTERNAL_ONLY + /** + Check whether this string starts with a given character. + + @param ch the character to be compared + + @param rest if this function returns true, then assign a + copy of the remainder of this string to *rest. + + @return true if and only if the given character appears at the start of this string + + @since LibreOffice 26.8 + */ + bool startsWith(sal_Unicode ch, std::u16string_view* rest) const { + assert(rest); + bool b = startsWith(ch); + + if (b) + *rest = subView(1); + + return b; + } +#endif + /** Check whether this string starts with a given string, ignoring the case of ASCII letters. @@ -1829,6 +1881,66 @@ public: } #endif + /** + Check whether this string ends with a given character. + + @param ch the character to be compared + + @return true if and only if the given character appears at the end of this string + + @since LibreOffice 26.8 + */ + bool endsWith(sal_Unicode ch) const + { + return !isEmpty() && pData->buffer[pData->length - 1] == ch; + } + + /** + Check whether this string ends with a given character. + + @param ch the character to be compared + + @param rest if this function returns true, then assign a + copy of the remainder of this string to *rest. + + @return true if and only if the given character appears at the end of this string + + @since LibreOffice 26.8 + */ + bool endsWith(sal_Unicode ch, OUString* rest) const { + assert(rest); + bool b = endsWith(ch); + + if (b) + *rest = copy(0, pData->length - 1); + + return b; + } + +#if defined LIBO_INTERNAL_ONLY + /** + Check whether this string ends with a given character. + + @param ch the character to be compared + + @param rest if this function returns true, then assign a + copy of the remainder of this string to *rest. + + @return true if and only if the given character appears at the end of this string + + @since LibreOffice 26.8 + */ + bool endsWith(sal_Unicode ch, std::u16string_view* rest) const { + assert(rest); + bool b = endsWith(ch); + + if (b) + *rest = subView(0, pData->length - 1); + + return b; + } +#endif + #if defined LIBO_INTERNAL_ONLY /** @overload @@ -3757,7 +3869,7 @@ private: return *this; } -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY static constexpr auto empty = OUStringLiteral(u""); // [-loplugin:ostr] #endif }; @@ -3952,7 +4064,7 @@ using ::rtl::Concat2View; using RepeatedUChar = ::rtl::RepeatedChar_t; #endif -#if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) +#if defined LIBO_INTERNAL_ONLY template< #if defined RTL_STRING_UNITTEST @@ -3997,7 +4109,6 @@ struct hash<::rtl::OUString> } -#if !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) /** * static empty string object, handy for returning from functions where the function is * returning a "const OUString &" @@ -4005,7 +4116,6 @@ struct hash<::rtl::OUString> * @since LibreOffice 25.2 */ static inline constexpr ::rtl::OUString EMPTY_OUSTRING = u""_ustr; -#endif #endif /// @endcond diff --git a/include/rtl/uuid.h b/include/rtl/uuid.h index e65c5e12b422..8f95f4ea667f 100644 --- a/include/rtl/uuid.h +++ b/include/rtl/uuid.h @@ -71,7 +71,7 @@ SAL_DLLPUBLIC void SAL_CALL rtl_createUuid(

    Note: lexical ordering is not temporal ordering!

    - Note: For equalnesschecking, a memcmp(pUUID1,pUUID2,16) is more efficient + Note: For equality checking, a memcmp(pUUID1,pUUID2,16) is more efficient @return

      @@ -129,12 +129,12 @@ SAL_DLLPUBLIC void SAL_CALL rtl_createNamedUuid( /* Predefined Namespaces - (Use them the following way : sal_uInt8 aNsDNS[16]) = RTL_UUID_NAMESPACE_DNS; + (Use them the following way : sal_uInt8 aNsDNS[16] = RTL_UUID_NAMESPACE_DNS;) */ /** namespace DNS

      - (Use them the following way : sal_uInt8 aNsDNS[16]) = RTL_UUID_NAMESPACE_DNS; + (Use them the following way : sal_uInt8 aNsDNS[16] = RTL_UUID_NAMESPACE_DNS;)

      6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ #define RTL_UUID_NAMESPACE_DNS {\ diff --git a/include/sal/alloca.h b/include/sal/alloca.h index 3e0c94942516..87df55c9f99f 100644 --- a/include/sal/alloca.h +++ b/include/sal/alloca.h @@ -25,7 +25,7 @@ #define INCLUDED_SAL_ALLOCA_H #if defined(__sun) || defined(LINUX) || defined(ANDROID) || defined(HAIKU) || defined(MACOSX) \ - || defined(IOS) || defined(EMSCRIPTEN) + || defined(IOS) || defined(__EMSCRIPTEN__) #ifndef INCLUDED_ALLOCA_H #include diff --git a/include/sal/backtrace.hxx b/include/sal/backtrace.hxx index 5f44e5e01d2d..cfeed34f1163 100644 --- a/include/sal/backtrace.hxx +++ b/include/sal/backtrace.hxx @@ -14,7 +14,6 @@ #include "sal/saldllapi.h" #include "sal/types.h" #include "rtl/ustring.hxx" -#include /// @cond INTERNAL /** diff --git a/include/sal/config.h b/include/sal/config.h index f666fed23897..b2b71b26295c 100644 --- a/include/sal/config.h +++ b/include/sal/config.h @@ -83,7 +83,7 @@ #define SAL_CONFIGFILE(name) name "rc" #endif -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ #define SAL_UNX #define SAL_DLLEXTENSION ".bc" #define SAL_EXEEXTENSION "" diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox index c63d7650e5fe..826bdcea52ef 100644 --- a/include/sal/log-areas.dox +++ b/include/sal/log-areas.dox @@ -149,12 +149,14 @@ certain functionality. @li @c sc.core.formulacell - ScFormulaCell and group @li @c sc.core.formulagroup @li @c sc.core.grouparealistener - sc::FormulaGroupAreaListener +@li @c sc.eppt - SmartArt/Diagram export @li @c sc.filter - Calc filter @li @c sc.lok.docsize @li @c sc.lok.header @li @c sc.lok.poshelper @li @c sc.opencl - OpenCL-related stuff in general @li @c sc.opencl.source - Generated OpenCL source code +@li @c sc.op - Calc operations @li @c sc.orcus @li @c sc.orcus.autofilter @li @c sc.orcus.condformat @@ -495,13 +497,13 @@ certain functionality. @li @c vcl.control @li @c vcl.ct - CoreText-using code for macOS and iOS @li @c vcl.debugevent -@li @c vcl.driver Graphics driver handling +@li @c vcl.driver - Graphics driver handling @li @c vcl.emf - EMF/EMF+ processing @li @c vcl.filter @li @c vcl.filter.webp +@li @c vcl.filter.jxl @li @c vcl.fonts - font-specific code @li @c vcl.fonts.detail -@li @c vcl.fonts.cff - CFF font subsetting-specific code @li @c vcl.gdi - the GDI part of VCL, devices, bitmaps, etc. @li @c vcl.gdi.wndproc - Windows Procedure part of VCL @li @c vcl.gdi.fontmetric diff --git a/include/sal/log.hxx b/include/sal/log.hxx index 825f3526b669..785e48d59ade 100644 --- a/include/sal/log.hxx +++ b/include/sal/log.hxx @@ -219,7 +219,7 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) { #if defined _LIBCPP_VERSION \ || (defined _GLIBCXX_RELEASE \ && (_GLIBCXX_RELEASE >= 12 || (_GLIBCXX_RELEASE == 11 && __GLIBCXX__ > 20210428))) \ - || (defined _MSC_VER && _MSC_VER >= 1915) + || (defined _MSC_VER) #define SAL_STREAM(stream) \ (::std::ostringstream() << stream).str() #else diff --git a/include/sal/types.h b/include/sal/types.h index 8e6acb634c4b..3bd5b8fb2cea 100644 --- a/include/sal/types.h +++ b/include/sal/types.h @@ -689,7 +689,7 @@ template< typename T1, typename T2 > inline T1 static_int_cast(T2 n) { /** Annotate pointer-returning functions to indicate that such a pointer is never nullptr. - Note that MSVC supports this feature via it's SAL _Ret_notnull_ + Note that MSVC supports this feature via its SAL _Ret_notnull_ annotation, but since it's in a completely different place on the function declaration, it's a little hard to support both. diff --git a/include/salhelper/timer.hxx b/include/salhelper/timer.hxx index 3fa81785aefe..3dc91083bcf3 100644 --- a/include/salhelper/timer.hxx +++ b/include/salhelper/timer.hxx @@ -152,7 +152,7 @@ public: */ sal_Bool SAL_CALL isExpired() const; - /** Does pTimer expires before us? + /** Does pTimer expire before us? */ sal_Bool SAL_CALL expiresBefore( const Timer* pTimer ) const; @@ -164,7 +164,7 @@ public: */ void SAL_CALL setRemainingTime( const TTimeValue& Remaining ); - /** Set the time to fire to 'now' + Remaining with repeat interveal + /** Set the time to fire to 'now' + Remaining with repeat interval * Repeat. */ void SAL_CALL setRemainingTime( const TTimeValue& Remaining, const TTimeValue& Repeat ); @@ -177,7 +177,7 @@ public: */ TTimeValue SAL_CALL getRemainingTime() const; - /** Internal method to shutdown the timer thread + /** Internal method to shut down the timer thread */ static void SAL_CALL joinThread(); @@ -205,7 +205,7 @@ protected: */ TTimeValue m_aExpired; - /** holds the time interveal of successive expirations. + /** holds the time interval of successive expirations. */ TTimeValue m_aRepeatDelta; diff --git a/include/sax/tools/converter.hxx b/include/sax/tools/converter.hxx index 8368a490b250..b3b971e795c4 100644 --- a/include/sax/tools/converter.hxx +++ b/include/sax/tools/converter.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SAX_TOOLS_CONVERTER_HXX -#define INCLUDED_SAX_TOOLS_CONVERTER_HXX +#pragma once #include @@ -331,6 +330,4 @@ public: } -#endif // INCLUDED_SAX_TOOLS_CONVERTER_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/LokControlHandler.hxx b/include/sfx2/LokControlHandler.hxx index d7b7316f3b58..9fbd8c9938e9 100644 --- a/include/sfx2/LokControlHandler.hxx +++ b/include/sfx2/LokControlHandler.hxx @@ -162,15 +162,20 @@ public: rDevice.SetOutputSizePixel(aOutputSize, /*bErase*/ false); auto popIt = rDevice.ScopedPush(vcl::PushFlags::MAPMODE); - MapMode aDeviceMapMode(rDevice.GetMapMode()); - const double scale = conversionFract(o3tl::Length::px, o3tl::Length::twip); - double scaleX = double(aOutputSize.Width()) / rTileRect.GetWidth() * scale; - double scaleY = double(aOutputSize.Height()) / rTileRect.GetHeight() * scale; - aDeviceMapMode.SetScaleX(scaleX); - aDeviceMapMode.SetScaleY(scaleY); - aDeviceMapMode.SetMapUnit(MapUnit::MapPixel); - rDevice.SetMapMode(aDeviceMapMode); + double scaleX(0.0); + double scaleY(0.0); + if (rTileRect.GetWidth() && rTileRect.GetHeight()) + { + MapMode aDeviceMapMode(rDevice.GetMapMode()); + const double scale = conversionFract(o3tl::Length::px, o3tl::Length::twip); + scaleX = double(aOutputSize.Width()) / rTileRect.GetWidth() * scale; + scaleY = double(aOutputSize.Height()) / rTileRect.GetHeight() * scale; + aDeviceMapMode.SetScaleX(scaleX); + aDeviceMapMode.SetScaleY(scaleY); + aDeviceMapMode.SetMapUnit(MapUnit::MapPixel); + rDevice.SetMapMode(aDeviceMapMode); + } o3tl::Length eControlUnitLength = MapToO3tlLength(rMainWindow.GetMapMode().GetMapUnit()); SdrObjListIter aIterator(pPage, SdrIterMode::Flat); diff --git a/include/sfx2/basedlgs.hxx b/include/sfx2/basedlgs.hxx index a4e90d4b2dc2..53b79e22c394 100644 --- a/include/sfx2/basedlgs.hxx +++ b/include/sfx2/basedlgs.hxx @@ -24,7 +24,6 @@ #include #include #include -//#include class SfxTabPage; class SfxBindings; @@ -67,8 +66,6 @@ class SFX2_DLLPUBLIC SfxModelessDialogController : public SfxDialogController SfxModelessDialogController(SfxModelessDialogController&) = delete; void operator =(SfxModelessDialogController&) = delete; - void Init(SfxBindings *pBindinx, SfxChildWindow *pCW); - protected: SfxModelessDialogController(SfxBindings*, SfxChildWindow* pChildWin, weld::Window* pParent, const OUString& rUIXMLDescription, const OUString& rID); @@ -76,7 +73,7 @@ protected: public: virtual ~SfxModelessDialogController() override; - void Initialize (SfxChildWinInfo const * pInfo); + void Initialize(const SfxChildWinInfo& rInfo); bool IsClosing() const; virtual void Close() override; virtual void EndDialog(int nResponse) override; diff --git a/include/sfx2/bindings.hxx b/include/sfx2/bindings.hxx index fae284799723..722320ad4588 100644 --- a/include/sfx2/bindings.hxx +++ b/include/sfx2/bindings.hxx @@ -181,7 +181,7 @@ public: css::uno::Reference < css::frame::XDispatch > GetDispatch( const SfxSlot*, const css::util::URL& aURL, bool bMasterCommand ); SAL_DLLPRIVATE void ContextChanged_Impl(); - SAL_DLLPRIVATE void Execute_Impl( SfxRequest& rReq, const SfxSlot* pSlot, SfxShell* pShell ); + SAL_DLLPRIVATE void Execute_Impl(SfxRequest& rReq, const SfxSlot* pSlot, SfxShell& rShell); SAL_DLLPRIVATE void DeleteControllers_Impl(); SAL_DLLPRIVATE SfxDispatcher* GetDispatcher_Impl() { return pDispatcher; } SAL_DLLPRIVATE void ClearCache_Impl( sal_uInt16 nSlotId ); diff --git a/include/sfx2/childwin.hxx b/include/sfx2/childwin.hxx index 2aa5d36510ee..4deb2324819a 100644 --- a/include/sfx2/childwin.hxx +++ b/include/sfx2/childwin.hxx @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -63,7 +64,7 @@ struct SAL_DLLPUBLIC_RTTI SfxChildWinInfo { OUString aExtraString; OUString aModule; - OUString aWinState; + vcl::WindowData aWinState; Point aPos; Size aSize; SfxChildWindowFlags nFlags; @@ -78,10 +79,9 @@ struct SAL_DLLPUBLIC_RTTI SfxChildWinInfo }; // ChildWindow factory methods -typedef std::unique_ptr (*SfxChildWinCtor)( vcl::Window *pParentWindow, - sal_uInt16 nId, - SfxBindings *pBindings, - SfxChildWinInfo *pInfo); +typedef std::unique_ptr (*SfxChildWinCtor)(vcl::Window* pParentWindow, + sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); struct SFX2_DLLPUBLIC SfxChildWinFactory { @@ -100,17 +100,16 @@ extern SFX2_DLLPUBLIC bool ParentIsFloatingWindow(const vcl::Window *pParent); class SFX2_DLLPUBLIC SfxChildWindow { VclPtr m_pParent; // parent window (Topwindow) - VclPtr pWindow; // actual contents - std::unique_ptr< SfxChildWindow_Impl> pImpl; // Implementation data - std::shared_ptr xController; // actual contents - SfxChildAlignment eChildAlignment; // Current css::drawing::Alignment - // Another window in pWindow - sal_uInt16 nType; // ChildWindow-Id + VclPtr m_pWindow; // actual contents + std::unique_ptr m_pImpl; // Implementation data + std::shared_ptr m_xController; // actual contents + SfxChildAlignment m_eChildAlignment; // Current css::drawing::Alignment + sal_uInt16 m_nType; // ChildWindow-Id SAL_DLLPRIVATE void ClearWorkwin(); protected: - void SetWindow(const VclPtr& p) { pWindow = p; } - SfxChildWindow(vcl::Window *pParentWindow, sal_uInt16 nId); + void SetWindow(const VclPtr& p) { m_pWindow = p; } + SfxChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId); public: virtual ~SfxChildWindow(); @@ -118,29 +117,29 @@ public: // the constructor was called (e.g. to avoid calling virtual methods in the constructor) virtual void Initialize() {} void Destroy(); - vcl::Window* GetWindow() const - { return pWindow; } - void SetController(const std::shared_ptr& controller) { xController = controller; } - void ClearController() { xController.reset(); } - std::shared_ptr& GetController() { return xController; } - const std::shared_ptr& GetController() const { return xController; } + vcl::Window* GetWindow() const { return m_pWindow; } + void SetController(const std::shared_ptr& controller) + { + m_xController = controller; + } + std::shared_ptr& GetController() { return m_xController; } + const std::shared_ptr& GetController() const { return m_xController; } vcl::Window* GetParent() const { return m_pParent; } - SfxChildAlignment GetAlignment() const - { return eChildAlignment; } + SfxChildAlignment GetAlignment() const { return m_eChildAlignment; } void SetAlignment(SfxChildAlignment eAlign); virtual void Hide(); virtual void Show( ShowFlags nFlags ); sal_uInt16 GetPosition() const; - sal_uInt16 GetType() const - { return nType; } + sal_uInt16 GetType() const { return m_nType; } virtual SfxChildWinInfo GetInfo() const; void SaveStatus(const SfxChildWinInfo& rInfo); static void RegisterChildWindow(SfxModule*, const SfxChildWinFactory&); - static std::unique_ptr CreateChildWindow( sal_uInt16, vcl::Window*, SfxBindings*, SfxChildWinInfo &); + static std::unique_ptr CreateChildWindow(sal_uInt16, vcl::Window*, SfxBindings&, + SfxChildWinInfo&); void SetHideNotDelete( bool bOn ); bool IsHideNotDelete() const; bool IsVisible() const; @@ -164,7 +163,7 @@ const int nCloseResponseToJustHide = -42; #define SFX_DECL_CHILDWINDOW(Class) \ public : \ static std::unique_ptr CreateImpl(vcl::Window *pParent, sal_uInt16 nId, \ - SfxBindings *pBindings, SfxChildWinInfo* pInfo ); \ + SfxBindings& rBindings, SfxChildWinInfo& rInfo); \ static void RegisterChildWindow (bool bVisible=false, SfxModule *pMod=nullptr, SfxChildWindowFlags nFlags=SfxChildWindowFlags::NONE); \ virtual SfxChildWinInfo GetInfo() const override @@ -180,9 +179,9 @@ const int nCloseResponseToJustHide = -42; #define SFX_IMPL_POS_CHILDWINDOW(Class, MyID, Pos) \ std::unique_ptr Class::CreateImpl( vcl::Window *pParent, \ - sal_uInt16 nId, SfxBindings *pBindings, SfxChildWinInfo* pInfo ) \ + sal_uInt16 nId, SfxBindings& rBindings, SfxChildWinInfo& rInfo) \ { \ - return std::make_unique(pParent, nId, pBindings, pInfo);\ + return std::make_unique(pParent, nId, rBindings, rInfo);\ } \ void Class::RegisterChildWindow (bool bVis, SfxModule *pMod, SfxChildWindowFlags nFlags) \ { \ diff --git a/include/sfx2/devtools/DevelopmentToolChildWindow.hxx b/include/sfx2/devtools/DevelopmentToolChildWindow.hxx index d78ac5c2e2ce..7c9d6aafa3ca 100644 --- a/include/sfx2/devtools/DevelopmentToolChildWindow.hxx +++ b/include/sfx2/devtools/DevelopmentToolChildWindow.hxx @@ -20,8 +20,8 @@ class SAL_WARN_UNUSED SFX2_DLLPUBLIC DevelopmentToolChildWindow final : public S { SFX_DECL_CHILDWINDOW_WITHID(DevelopmentToolChildWindow); - DevelopmentToolChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings* pBindings, - SfxChildWinInfo* pInfo); + DevelopmentToolChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/dinfdlg.hxx b/include/sfx2/dinfdlg.hxx index 63a81ed283d8..5bfbc538fdbe 100644 --- a/include/sfx2/dinfdlg.hxx +++ b/include/sfx2/dinfdlg.hxx @@ -34,10 +34,18 @@ #include #include +#include +#include +#include #include +#include #include +#include +#include +#include #include #include +#include #include #include diff --git a/include/sfx2/docfilt.hxx b/include/sfx2/docfilt.hxx index 9a40ae25b8b9..c18b7ac1866d 100644 --- a/include/sfx2/docfilt.hxx +++ b/include/sfx2/docfilt.hxx @@ -78,7 +78,6 @@ public: bool IsOwnFormat() const { return bool(nFormatType & SfxFilterFlags::OWN); } /// If the filter supports digital signatures. bool GetSupportsSigning() const { return bool(nFormatType & SfxFilterFlags::SUPPORTSSIGNING); } - bool GetGpgEncryption() const { return bool(nFormatType & SfxFilterFlags::GPGENCRYPTION); } bool IsOwnTemplateFormat() const { return bool(nFormatType & SfxFilterFlags::TEMPLATEPATH); } bool IsMSOFormat() const { diff --git a/include/sfx2/dockwin.hxx b/include/sfx2/dockwin.hxx index b1d77e71e481..ee72ee9a6ed9 100644 --- a/include/sfx2/dockwin.hxx +++ b/include/sfx2/dockwin.hxx @@ -23,8 +23,7 @@ #include #include #include -#include - +#include #include #include @@ -44,12 +43,12 @@ protected: std::unique_ptr m_xContainer; private: - tools::Rectangle aInnerRect; - tools::Rectangle aOuterRect; - SfxBindings* pBindings; - Size aFloatSize; - SfxChildWindow* pMgr; - std::unique_ptr< SfxDockingWindow_Impl > pImpl; + tools::Rectangle m_aInnerRect; + tools::Rectangle m_aOuterRect; + SfxBindings& m_rBindings; + Size m_aFloatSize; + SfxChildWindow* m_pMgr; + std::unique_ptr m_pImpl; SfxDockingWindow(SfxDockingWindow const &) = delete; SfxDockingWindow& operator =(SfxDockingWindow const &) = delete; @@ -71,34 +70,34 @@ protected: virtual bool Close() override; virtual void Move() override; - SAL_DLLPRIVATE SfxChildWindow* GetChildWindow_Impl() { return pMgr; } + SAL_DLLPRIVATE SfxChildWindow* GetChildWindow_Impl() { return m_pMgr; } public: - SfxDockingWindow( SfxBindings *pBindings, - SfxChildWindow *pCW, - vcl::Window* pParent, - WinBits nWinBits); - SfxDockingWindow( SfxBindings *pBindings, - SfxChildWindow *pCW, - vcl::Window* pParent, - const OUString& rID, const OUString& rUIXMLDescription ); - virtual ~SfxDockingWindow() override; + SfxDockingWindow(SfxBindings& rBindings, SfxChildWindow* pCW, vcl::Window* pParent, + WinBits nWinBits); + SfxDockingWindow(SfxBindings& rBindings, SfxChildWindow* pCW, vcl::Window* pParent, + const OUString& rID, const OUString& rUIXMLDescription); + virtual ~SfxDockingWindow() override; + virtual void dispose() override; - void Initialize (SfxChildWinInfo* pInfo); + void Initialize(SfxChildWinInfo& rInfo); virtual void FillInfo(SfxChildWinInfo&) const; virtual void StateChanged( StateChangedType nStateChange ) override; void SetDockingRects(const tools::Rectangle& rOuter, const tools::Rectangle& rInner) - { aInnerRect = rInner; aOuterRect = rOuter; } - const tools::Rectangle& GetInnerRect() const { return aInnerRect; } - const tools::Rectangle& GetOuterRect() const { return aOuterRect; } - SfxBindings& GetBindings() const { return *pBindings; } - sal_uInt16 GetType() const { return pMgr->GetType(); } - SfxChildAlignment GetAlignment() const { return pMgr->GetAlignment(); } - void SetAlignment(SfxChildAlignment eAlign) { pMgr->SetAlignment(eAlign); } - const Size& GetFloatingSize() const { return aFloatSize; } - void SetFloatingSize(const Size& rSize) { aFloatSize=rSize; } + { + m_aInnerRect = rInner; + m_aOuterRect = rOuter; + } + const tools::Rectangle& GetInnerRect() const { return m_aInnerRect; } + const tools::Rectangle& GetOuterRect() const { return m_aOuterRect; } + SfxBindings& GetBindings() const { return m_rBindings; } + sal_uInt16 GetType() const { return m_pMgr->GetType(); } + SfxChildAlignment GetAlignment() const { return m_pMgr->GetAlignment(); } + void SetAlignment(SfxChildAlignment eAlign) { m_pMgr->SetAlignment(eAlign); } + const Size& GetFloatingSize() const { return m_aFloatSize; } + void SetFloatingSize(const Size& rSize) { m_aFloatSize = rSize; } void SetMinOutputSizePixel( const Size& rSize ); const Size& GetMinOutputSizePixel() const; @@ -117,10 +116,8 @@ public: class SfxDockingWrapper final : public SfxChildWindow { public: - SfxDockingWrapper( vcl::Window* pParent , - sal_uInt16 nId , - SfxBindings* pBindings , - SfxChildWinInfo* pInfo ); + SfxDockingWrapper(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); SFX_DECL_CHILDWINDOW(SfxDockingWrapper); }; diff --git a/include/sfx2/infobar.hxx b/include/sfx2/infobar.hxx index 36377f1f38bc..52da46a02fc6 100644 --- a/include/sfx2/infobar.hxx +++ b/include/sfx2/infobar.hxx @@ -62,11 +62,11 @@ public: class SFX2_DLLPUBLIC SfxInfoBarContainerChild final : public SfxChildWindow { private: - SfxBindings* m_pBindings; + SfxBindings& m_rBindings; public: - SfxInfoBarContainerChild(vcl::Window* pParent, sal_uInt16 nId, SfxBindings* pBindings, - SfxChildWinInfo* pInfo); + SfxInfoBarContainerChild(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); virtual ~SfxInfoBarContainerChild() override; SFX_DECL_CHILDWINDOW_WITHID(SfxInfoBarContainerChild); diff --git a/include/sfx2/linkmgr.hxx b/include/sfx2/linkmgr.hxx index 1af8e7263197..c66f072a00de 100644 --- a/include/sfx2/linkmgr.hxx +++ b/include/sfx2/linkmgr.hxx @@ -59,7 +59,7 @@ class SFX2_DLLPUBLIC LinkManager SvBaseLinks aLinkTbl; SvLinkSources aServerTbl; - SfxObjectShell *pPersist; // LinkMgr must be release before SfxObjectShell + SfxObjectShell *pPersist; // LinkMgr must be released before SfxObjectShell bool InsertLink( SvBaseLink* pLink, SvBaseLinkObjectType nObjType, SfxLinkUpdateMode nUpdateType, const OUString* pName ); @@ -129,8 +129,6 @@ public: static SvLinkSourceRef CreateObj( SvBaseLink const * ); void UpdateAllLinks(bool bAskUpdate, - bool bUpdateGrfLinks, - weld::Window* pParentWin, OUString const & referer); // Call for list of links (eg for link-dialog) diff --git a/include/sfx2/linksrc.hxx b/include/sfx2/linksrc.hxx index 7fc3eaf42415..2196a9542f62 100644 --- a/include/sfx2/linksrc.hxx +++ b/include/sfx2/linksrc.hxx @@ -77,9 +77,9 @@ public: const OUString & rMimeType, bool bSynchron = false ); - // sal_True => waitinmg for data + // true => waiting for data virtual bool IsPending() const; - // sal_True => data complete loaded + // true => data completely loaded virtual bool IsDataComplete() const; virtual void Edit(weld::Window *, SvBaseLink *, const Link& rEndEditHdl); diff --git a/include/sfx2/listview.hxx b/include/sfx2/listview.hxx index 20a79d647095..345e7c5ac54a 100644 --- a/include/sfx2/listview.hxx +++ b/include/sfx2/listview.hxx @@ -16,11 +16,6 @@ namespace weld class TreeIter; } -enum class TemplateViewMode -{ - ListView, - ThumbnailView -}; struct ListViewItem; class ListView @@ -32,20 +27,6 @@ public: void AppendItem(const OUString& rId, const OUString& rTitle, const OUString& rSubtitle, const OUString& rPath, bool bDefault); - void AppendRow(const OUString& rImage, const OUString& rTitle, const OUString& rSubtitle, - const OUString& rApplication, const OUString& rModify, const OUString& rSize, - const OUString& rId); - - void UpdateRow(int nIndex, const OUString& rImage, const OUString& rTitle, - const OUString& rSubtitle, const OUString& rApplication, const OUString& rModify, - const OUString& rSize, const OUString& rId); - - void ReloadRows(); - - bool UpdateRows(); - - void sortColumn(const int col); - void sort(); void clearListView(); @@ -85,6 +66,21 @@ protected: int get_index(sal_uInt16 nId) const { return mxTreeView->find_id(OUString::number(nId)); } +private: + void AppendRow(const OUString& rImage, const OUString& rTitle, const OUString& rSubtitle, + const OUString& rApplication, const OUString& rModify, const OUString& rSize, + const OUString& rId); + + void UpdateRow(int nIndex, const OUString& rImage, const OUString& rTitle, + const OUString& rSubtitle, const OUString& rApplication, const OUString& rModify, + const OUString& rSize, const OUString& rId); + + void ReloadRows(); + + bool UpdateRows(); + + void sortColumn(const int col); + DECL_LINK(ColumnClickedHdl, const int, void); DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString); diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index 5379e4114f98..83dbab214076 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -129,22 +129,12 @@ public: static void setAccessibilityState(int nId, bool nEnabled); // Set the readonly state of the view. static void setViewReadOnly(int nId, bool readOnly); - // In readonly view, can user add / modify comments or not. - static void setAllowChangeComments(int nId, bool allow); - // In readonly view, can user accept / reject tracked changes or not. - static void setAllowManageRedlines(int nId, bool allow); /// Get the language used by the loading view (used for all save operations). static const LanguageTag & getLoadLanguage(); /// Set the language used by the loading view (used for all save operations). static void setLoadLanguage(const OUString& rBcp47LanguageTag); /// Set the locale for the given view. static void setViewLocale(int nId, const OUString& rBcp47LanguageTag); - /// Set the language and locale for the given view. - static void setViewLanguageAndLocale(int nId, const OUString& rBcp47LanguageTag); - /// Get the device form factor that should be used for a new view. - static LOKDeviceFormFactor getDeviceFormFactor(); - /// Set the device form factor that should be used for a new view. - static void setDeviceFormFactor(std::u16string_view rDeviceFormFactor); /// Set color preview state for the given view. static void setColorPreviewState(int nId, bool nEnabled); diff --git a/include/sfx2/msg.hxx b/include/sfx2/msg.hxx index 7d6a39ef88e6..3f188a823e9b 100644 --- a/include/sfx2/msg.hxx +++ b/include/sfx2/msg.hxx @@ -143,9 +143,9 @@ SFX_DECL_TYPE(11); SFX_DECL_TYPE(13); // for SwAddPrinterItem, Sd... SFX_DECL_TYPE(14); -SFX_DECL_TYPE(15); // for SvxHyphenZoneItem SFX_DECL_TYPE(16); // for SwDocDisplayItem SFX_DECL_TYPE(17); // for SvxAddressItem +SFX_DECL_TYPE(18); // for SvxHyphenZoneItem SFX_DECL_TYPE(23); // for SvxSearchItem // all SfxTypes must be in this header diff --git a/include/sfx2/navigat.hxx b/include/sfx2/navigat.hxx index febdefa81745..a6823be6d8f6 100644 --- a/include/sfx2/navigat.hxx +++ b/include/sfx2/navigat.hxx @@ -34,8 +34,8 @@ public: class SFX2_DLLPUBLIC SfxNavigator : public SfxDockingWindow { public: - SfxNavigator(SfxBindings* pBindings, SfxChildWindow* pChildWin, - vcl::Window* pParent, SfxChildWinInfo* pInfo); + SfxNavigator(SfxBindings& rBindings, SfxChildWindow* pChildWin, vcl::Window* pParent, + SfxChildWinInfo& rInfo); }; #endif diff --git a/include/sfx2/newstyle.hxx b/include/sfx2/newstyle.hxx index ebf5a3b66ee9..3afb82ea96a5 100644 --- a/include/sfx2/newstyle.hxx +++ b/include/sfx2/newstyle.hxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/include/sfx2/notebookbar/SfxNotebookBar.hxx b/include/sfx2/notebookbar/SfxNotebookBar.hxx index 21a518689d87..8dc6fa5d329a 100644 --- a/include/sfx2/notebookbar/SfxNotebookBar.hxx +++ b/include/sfx2/notebookbar/SfxNotebookBar.hxx @@ -70,11 +70,6 @@ public: private: static bool m_bLock; static bool m_bHide; - - static void ResetActiveToolbarModeToDefault(vcl::EnumContext::Application eApp); - static void RemoveCurrentLOKWrapper(); - - DECL_DLLPRIVATE_STATIC_LINK(SfxNotebookBar, VclDisposeHdl, const SfxViewShell*, void); }; } // namespace sfx2 diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx index 6a48055818f5..0ec2d07a66f7 100644 --- a/include/sfx2/objsh.hxx +++ b/include/sfx2/objsh.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,7 @@ namespace sfx { class IDocumentModelAccessor; } namespace sfx { class AccessibilityIssueCollection; } namespace com::sun::star::awt { class XWindow; } +namespace com::sun::star::beans { class XPropertySet; } namespace com::sun::star::beans { struct PropertyValue; } namespace com::sun::star::document { struct CmisVersion; } namespace com::sun::star::document { class XDocumentProperties; } @@ -196,11 +198,14 @@ private: SfxMedium * pMedium; // Description of the file for example // storage that contains the object SfxObjectCreateMode eCreateMode; // Purpose of the object - bool bHasName :1; // sal_True := existing object, - // sal_False := new object + bool bHasName :1; // true := existing object, + // false := new object bool bIsInGenerateThumbnail; //optimize thumbnail generate and store procedure to improve odt saving performance, i120030 bool mbAvoidRecentDocs; ///< Avoid adding to the recent documents list, if not necessary. bool bRememberSignature; // Do we want to remember the signature. + bool bPendingLinkUpdateInfobar; + std::vector, OUString>> + maDeferredFormControlImages; enum TriState {undefined, yes, no}; TriState mbContinueImportOnFilterExceptions = undefined; // try to import as much as possible @@ -338,6 +343,18 @@ public: bool SwitchPersistence( const css::uno::Reference< css::embed::XStorage >& xStorage ); virtual void UpdateLinks(); + virtual void PerformLinkUpdate(); + void SetPendingLinkUpdateInfobar() { bPendingLinkUpdateInfobar = true; } + void CheckPendingLinkUpdateInfobar(); + void ShowLinkUpdateInfobar(); + void AddDeferredFormControlImage( + const css::uno::Reference& rxControl, + const OUString& rURL); + const std::vector, OUString>>& + GetDeferredFormControlImages() const + { return maDeferredFormControlImages; } + void ClearDeferredFormControlImages() + { maDeferredFormControlImages.clear(); } virtual bool LoadExternal( SfxMedium& rMedium ); bool IsConfigOptionsChecked() const; void SetConfigOptionsChecked( bool bChecked ); @@ -385,6 +402,7 @@ public: SignatureState GetScriptingSignatureState(); void SignScriptingContent(weld::Window* pDialogParent, const std::function& rCallback); DECL_DLLPRIVATE_LINK(SignDocumentHandler, weld::Button&, void); + DECL_DLLPRIVATE_LINK(AllowLinksUpdateHdl, weld::Button&, void); virtual std::shared_ptr CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet& rItemSet); @@ -422,6 +440,9 @@ public: static bool UnTrustedScript(const OUString& rScriptURL); + /// Check if script URL whitelist exists, and if so, if current script url is part of it + static bool isScriptURLAllowed(const OUString& rScriptURL); + static bool isScriptAccessAllowed(const css::uno::Reference& rScriptContext); SvKeyValueIterator* GetHeaderAttributes(); @@ -546,7 +567,7 @@ public: returns the Title just like MB now would display it in the History - 10 bis USHRT_MAX + 10 to USHRT_MAX provides the 'nMaxLength' of the logical file name including the path (remote => css::util::URL) @@ -696,7 +717,7 @@ public: sal_Int32 nVersion, bool bTemplate = false) const = 0; - // change recording and respective passwword protection for Writer and Calc + // change recording and respective password protection for Writer and Calc // slots available for Writer: FN_REDLINE_ON, FN_REDLINE_ON // slots used for Calc: FID_CHG_RECORD, SID_CHG_PROTECT virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr, bool bRecordAllViews = true) const; diff --git a/include/sfx2/opengrf.hxx b/include/sfx2/opengrf.hxx index 7e3a4d42b53d..368fa836940f 100644 --- a/include/sfx2/opengrf.hxx +++ b/include/sfx2/opengrf.hxx @@ -21,6 +21,7 @@ #include #include #include +#include namespace com::sun::star::ui::dialogs { class XFilePickerControlAccess; } namespace com::sun::star::uno { template class Reference; } @@ -42,6 +43,8 @@ public: void SetPath( const OUString& rPath, bool bLinkState ); OUString GetPath() const; + css::uno::Sequence< OUString > GetSelectedFiles() const; + void setMultiSelect(bool bEnable); ErrCode GetGraphic(Graphic&) const; diff --git a/include/sfx2/pageids.hxx b/include/sfx2/pageids.hxx index 97b9df8d868a..0fc1966db397 100644 --- a/include/sfx2/pageids.hxx +++ b/include/sfx2/pageids.hxx @@ -56,7 +56,6 @@ #define RID_SVXPAGE_APPEARANCE (RID_SVX_START + 247) #define RID_SVXPAGE_BASICIDE_OPTIONS (RID_SVX_START + 209) #define RID_SVXPAGE_LANGTOOL_OPTIONS (RID_SVX_START + 210) -#define RID_SVXPAGE_DEEPL_OPTIONS (RID_SVX_START + 211) // Resource-Id's ------------------------------------------------------------ diff --git a/include/sfx2/passwd.hxx b/include/sfx2/passwd.hxx index f976fad3c057..69d7f759798d 100644 --- a/include/sfx2/passwd.hxx +++ b/include/sfx2/passwd.hxx @@ -20,10 +20,14 @@ #include #include +#include #include #include +#include +#include +#include #include -#include +#include #include #include @@ -91,7 +95,7 @@ private: DECL_DLLPRIVATE_LINK(OKHdl, weld::Button&, void); DECL_DLLPRIVATE_LINK(ShowHdl, weld::Toggleable&, void); DECL_DLLPRIVATE_LINK(InsertTextHdl, OUString&, bool); - DECL_DLLPRIVATE_LINK(EditModifyHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(EditModifyHdl, weld::TextWidget&, void); void ModifyHdl(); void SetPasswdText(); diff --git a/include/sfx2/quickfind.hxx b/include/sfx2/quickfind.hxx index 914606eeb05e..23b64516d16c 100644 --- a/include/sfx2/quickfind.hxx +++ b/include/sfx2/quickfind.hxx @@ -25,8 +25,8 @@ public: class SFX2_DLLPUBLIC SfxQuickFind : public SfxDockingWindow { public: - SfxQuickFind(SfxBindings* pBindings, SfxChildWindow* pChildWin, vcl::Window* pParent, - SfxChildWinInfo* pInfo); + SfxQuickFind(SfxBindings& rBindings, SfxChildWindow* pChildWin, vcl::Window* pParent, + SfxChildWinInfo& rInfo); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/safemode.hxx b/include/sfx2/safemode.hxx index 34602c4ea68c..5f698f259471 100644 --- a/include/sfx2/safemode.hxx +++ b/include/sfx2/safemode.hxx @@ -20,29 +20,29 @@ class SFX2_DLLPUBLIC SafeMode { public: /** - * Write a flag file to the user profile indicating that the next launch should be in safe mode. + * Write a flag file to the user profile indicating that the next launch should be in troubleshoot mode. * * @return Whether the file could be written successfully */ static bool putFlag(); /** - * Check the existence of the safe mode flag file. + * Check the existence of the troubleshoot mode flag file. * - * @return Whether the flag file for the safe mode exists + * @return Whether the flag file for the troubleshoot mode exists */ static bool hasFlag(); /** - * Remove the flag file for the safe mode. + * Remove the flag file for the troubleshoot mode. * * @return Whether the flag file could be removed successfully */ static bool removeFlag(); /** - * Write a flag to the user profile indicating that we are currently restarting from safe mode - - * that means we don't want to enter safe mode again. + * Write a flag to the user profile indicating that we are currently restarting from troubleshoot mode - + * that means we don't want to enter troubleshoot mode again. * * @return Whether the file could be written successfully */ @@ -63,7 +63,7 @@ public: static bool removeRestartFlag(); private: - /** Returns the path of the safe mode flag file.*/ + /** Returns the path of the troubleshoot mode flag file.*/ static OUString getFilePath(const OUString& sFilename); }; } diff --git a/include/sfx2/sfxdlg.hxx b/include/sfx2/sfxdlg.hxx index 69f0f230b45f..9aad3164ed84 100644 --- a/include/sfx2/sfxdlg.hxx +++ b/include/sfx2/sfxdlg.hxx @@ -115,6 +115,9 @@ protected: public: virtual OUString GetScriptURL() const = 0; virtual void SetRunLabel() = 0; + // Return the model containing the selected script, or a null reference if the script isn’t + // embedded in a document. + virtual css::uno::Reference GetScriptModel() const = 0; }; class AbstractMacroManagerDialog : virtual public VclAbstractDialog @@ -125,6 +128,9 @@ protected: public: virtual OUString GetScriptURL() const = 0; virtual void LoadLastUsedMacro() const = 0; + // Return the model containing the selected script, or a null reference if the script isn’t + // embedded in a document. + virtual css::uno::Reference GetScriptModel() const = 0; }; namespace com::sun::star::frame { class XFrame; } diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc index 0cca69e3b251..d2ffb9aee2bf 100644 --- a/include/sfx2/sfxsids.hrc +++ b/include/sfx2/sfxsids.hrc @@ -112,7 +112,6 @@ class SvxZoomItem; #define SID_TIPOFTHEDAY (SID_SFX_START + 407) // free (SID_SFX_START + 410) -#define SID_SEND_FEEDBACK (SID_SFX_START + 421) #define SID_Q_AND_A (SID_SFX_START + 422) #define SID_DOCUMENTATION (SID_SFX_START + 423) #define SID_DONATION (SID_SFX_START + 424) @@ -121,16 +120,15 @@ class SvxZoomItem; #define SID_CREDITS (SID_SFX_START + 427) #define SID_HYPHENATIONMISSING (SID_SFX_START + 428) -#define SID_SHOW_LICENSE (SID_SFX_START + 1683) -#define SID_SHOW_CREDITS (SID_SFX_START + 1711) +#define SID_SHOW_LICENSE (SID_SFX_START + 1695) // default-ids for document #define SID_NEWDOC (SID_SFX_START + 500) #define SID_OPENDOC (SID_SFX_START + 501) #define SID_OPENREMOTE (SID_SFX_START + 517) #define SID_OPENURL (SID_SFX_START + 596) +#define SID_OPENTEMPLATE (SID_SFX_START + 597) #define SID_JUMPTOMARK TypedWhichId(SID_SFX_START + 598) -#define SID_OPENTEMPLATE (SID_SFX_START + 594) #define SID_SAVEASDOC TypedWhichId(SID_SFX_START + 502) #define SID_SAVEASREMOTE (SID_SFX_START + 516) #define SID_SAVESIMPLE (SID_SFX_START + 518) @@ -163,8 +161,6 @@ class SvxZoomItem; #define SID_DIRECTEXPORTDOCASPDF (SID_SFX_START + 1674) #define SID_EXPORTDOCASEPUB (SID_SFX_START + 1677) #define SID_DIRECTEXPORTDOCASEPUB (SID_SFX_START + 1678) -#define SID_REDACTDOC (SID_SFX_START + 1732) -#define SID_AUTOREDACTDOC (SID_SFX_START + 1736) #define SID_UPDATEDOCMODE TypedWhichId(SID_SFX_START + 1668) #define SID_CHECKOUT TypedWhichId(SID_SFX_START + 512) #define SID_CANCELCHECKOUT TypedWhichId(SID_SFX_START + 513) @@ -224,7 +220,7 @@ class SvxZoomItem; #define SID_VIEW_DATA_SOURCE_BROWSER TypedWhichId(SID_SFX_START + 1660) #define SID_UNPACK TypedWhichId(SID_SFX_START + 1662) // (SID_SFX_START + 1663) used further down -#define SID_ATTR_TARGETLANG_STR (SID_SFX_START + 1664) +// (SID_SFX_START + 1664) was SID_ATTR_TARGETLANG_STR introduced with e20d2de7836da52dbf9e528d1043b1e188097bfd #define SID_GO_TO_PAGE (SID_SFX_START + 1665) #define SID_OUTPUTSTREAM TypedWhichId(SID_SFX_START + 1666) #define SID_IMAGE_ORIENTATION TypedWhichId(SID_SFX_START + 1667) @@ -280,9 +276,6 @@ class SvxZoomItem; #define SID_NO_THUMBNAIL (SID_SFX_START + 1730) #define SID_LOCK_CONTENT_EXTRACTION TypedWhichId(SID_SFX_START + 1731) #define SID_LOCK_EXPORT TypedWhichId(SID_SFX_START + 1732) -// Used to export a temporary file for preview in Mail Merge Wizard, where saving the data source is -// not required for preview, but interferes with not-yet-saved embedded data source for main document. -#define SID_NO_EMBEDDED_DS TypedWhichId(SID_SFX_START + 1731) #define SID_IS_REDACT_MODE (SID_SFX_START + 1733) #define SID_REDACTION_STYLE (SID_SFX_START + 1734) #define SID_DIALOG_PARENT TypedWhichId(SID_SFX_START + 1735) @@ -302,6 +295,12 @@ class SvxZoomItem; #define SID_MACROMANAGER (SID_SFX_START + 1750) #define SID_EXPORTDIRECTORY TypedWhichId(SID_SFX_START + 1751) #define SID_EXTENSION_MANAGER TypedWhichId(SID_SFX_START + 1752) +// Used to export a temporary file for preview in Mail Merge Wizard, where saving the data source is +// not required for preview, but interferes with not-yet-saved embedded data source for main document. +#define SID_NO_EMBEDDED_DS TypedWhichId(SID_SFX_START + 1753) +#define SID_SHOW_CREDITS (SID_SFX_START + 1754) +#define SID_REDACTDOC (SID_SFX_START + 1755) +#define SID_AUTOREDACTDOC (SID_SFX_START + 1756) // SID_SFX_free_END (SID_SFX_START + 3999) #define SID_OPEN_NEW_VIEW TypedWhichId(SID_SFX_START + 520) @@ -335,7 +334,7 @@ class SvxZoomItem; #define SID_DOCINFO_AUTHOR TypedWhichId(SID_SFX_START + 593) #define SID_DOCINFO_MAJOR (SID_SFX_START + 594) #define SID_NEWDOCDIRECT TypedWhichId(SID_SFX_START + 537) -#define SID_DOCFRAME (SID_SFX_START + 598) +#define SID_DOCFRAME (SID_SFX_START + 600) #define SID_TARGETNAME TypedWhichId(SID_SFX_START + 560) #define SID_POSTDATA TypedWhichId(SID_SFX_START + 1536) #define SID_DONELINK (SID_SFX_START + 646) @@ -401,7 +400,7 @@ class SvxZoomItem; #define SID_CLASSIFICATION_APPLY (SID_SFX_START + 672) #define SID_WATERMARK TypedWhichId(SID_SFX_START + 676) #define SID_WATERMARK_FONT TypedWhichId(SID_SFX_START + 677) -#define SID_WATERMARK_TRANSPARENCY TypedWhichId(SID_SFX_START + 805) +#define SID_WATERMARK_TRANSPARENCY TypedWhichId(SID_SFX_START + 819) #define SID_WATERMARK_COLOR TypedWhichId(SID_SFX_START + 806) #define SID_WATERMARK_ANGLE TypedWhichId(SID_SFX_START + 807) @@ -599,7 +598,8 @@ class SvxZoomItem; #define SID_HYPERLINK_SETLINK TypedWhichId(SID_SVX_START + 362) #define SID_INFOBAR (SID_SVX_START + 365) #define SID_NAVIGATOR (SID_SVX_START + 366) -#define SID_QUICKFIND (SID_SVX_START + 367) +// CAUTION! Range <367 .. 369> is used in include/svx/svxids.hrc +#define SID_QUICKFIND (SID_SVX_START + 370) #define SID_ZOOM_NEXT (SID_SVX_START + 402) #define SID_ZOOM_PREV (SID_SVX_START + 403) #define SID_INET_DLG (SID_SVX_START + 416) @@ -694,7 +694,7 @@ class SvxZoomItem; #define FN_NOUPDATE TypedWhichId(FN_PARAM+67) #define FN_FAX (SID_SW_START + 28) /* Fax */ -#define SID_KEYFUNC_START (SID_SC_START + 521) +#define SID_KEYFUNC_START (SID_SC_START + 525) #define SID_CURSORDOWN_SEL (SID_KEYFUNC_START + 0) #define SID_CURSORUP_SEL (SID_KEYFUNC_START + 1) #define SID_CURSORLEFT_SEL (SID_KEYFUNC_START + 2) diff --git a/include/sfx2/sidebar/Deck.hxx b/include/sfx2/sidebar/Deck.hxx index ee2a86b1f4f0..3798cf6e63f1 100644 --- a/include/sfx2/sidebar/Deck.hxx +++ b/include/sfx2/sidebar/Deck.hxx @@ -74,12 +74,8 @@ public: virtual void DataChanged(const DataChangedEvent& rEvent) override; - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; - sal_Int32 GetMinimalWidth() const { return mnMinimalWidth; } - static void LOKSendSidebarFullUpdate(); - private: void RequestLayoutInternal(); diff --git a/include/sfx2/sidebar/Panel.hxx b/include/sfx2/sidebar/Panel.hxx index 3f7d7b475659..fa52d5b0fd72 100644 --- a/include/sfx2/sidebar/Panel.hxx +++ b/include/sfx2/sidebar/Panel.hxx @@ -89,7 +89,6 @@ public: SAL_DLLPRIVATE PanelTitleBar* GetTitleBar() const; SAL_DLLPRIVATE weld::Box* GetContents() const; - SAL_DLLPRIVATE const weld::Box* GetContainer() const { return mxContainer.get(); } SAL_DLLPRIVATE void Show(bool bShow); bool IsTitleBarOptional() const { return mbIsTitleBarOptional; } SAL_DLLPRIVATE void SetUIElement(const css::uno::Reference& rxElement); @@ -103,7 +102,6 @@ public: bool IsExpanded() const { return mbIsExpanded; } SAL_DLLPRIVATE bool HasIdPredicate(std::u16string_view rsId) const; const OUString& GetId() const { return msPanelId; } - const OUString& GetTitle() const { return msTitle; } void TriggerDeckLayouting(); SAL_DLLPRIVATE void SetHeightPixel(int nHeight); @@ -140,8 +138,6 @@ private: std::unique_ptr mxTitleBar; std::unique_ptr mxContents; css::uno::Reference mxXWindow; - - DECL_DLLPRIVATE_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void); }; typedef std::vector> SharedPanelContainer; diff --git a/include/sfx2/sidebar/PanelLayout.hxx b/include/sfx2/sidebar/PanelLayout.hxx index 24878a36c449..a8608a169c5b 100644 --- a/include/sfx2/sidebar/PanelLayout.hxx +++ b/include/sfx2/sidebar/PanelLayout.hxx @@ -10,13 +10,17 @@ #pragma once #include -#include +#include +#include class DataChangedEvent; class VclSimpleEvent; namespace sfx2 { namespace sidebar { class Panel; } } -namespace tools { class JsonWriter; } -namespace weld { class Builder; } +namespace weld +{ +class Builder; +class Window; +} /// This class is the base for the Widget Layout-based sidebar panels. class SFX2_DLLPUBLIC PanelLayout @@ -27,20 +31,15 @@ protected: sfx2::sidebar::Panel* m_pPanel; virtual void DataChanged(const DataChangedEvent& rEvent); - virtual void DumpAsPropertyTree(tools::JsonWriter&); virtual weld::Window* GetFrameWeld() const; private: DECL_DLLPRIVATE_LINK(DataChangedEventListener, VclSimpleEvent&, void); - DECL_DLLPRIVATE_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void); public: PanelLayout(weld::Widget* pParent, const OUString& rID, const OUString& rUIXMLDescription); - PanelLayout(weld::Widget* pParent, const OUString& rID, const OUString& rUIXMLDescription, - sal_uInt64 nWindowId); - void SetPanel(sfx2::sidebar::Panel* pPanel); virtual ~PanelLayout(); diff --git a/include/sfx2/sidebar/SidebarChildWindow.hxx b/include/sfx2/sidebar/SidebarChildWindow.hxx index 279aa79b5f2d..5fb7fe9984c4 100644 --- a/include/sfx2/sidebar/SidebarChildWindow.hxx +++ b/include/sfx2/sidebar/SidebarChildWindow.hxx @@ -32,8 +32,8 @@ namespace sfx2::sidebar { class SFX2_DLLPUBLIC SidebarChildWindow final : public SfxChildWindow { public: - SidebarChildWindow(vcl::Window* pParent, sal_uInt16 nId, - SfxBindings* pBindings, SfxChildWinInfo* pInfo); + SidebarChildWindow(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); SFX_DECL_CHILDWINDOW_WITHID(SidebarChildWindow); diff --git a/include/sfx2/sidebar/SidebarDockingWindow.hxx b/include/sfx2/sidebar/SidebarDockingWindow.hxx index 84b87b837611..cebf41dd4ce1 100644 --- a/include/sfx2/sidebar/SidebarDockingWindow.hxx +++ b/include/sfx2/sidebar/SidebarDockingWindow.hxx @@ -33,7 +33,7 @@ class SidebarController; class SFX2_DLLPUBLIC SidebarDockingWindow final : public SfxDockingWindow { public: - SidebarDockingWindow(SfxBindings* pBindings, SidebarChildWindow& rChildWindow, + SidebarDockingWindow(SfxBindings& rBindings, SidebarChildWindow& rChildWindow, vcl::Window* pParent, WinBits nBits); virtual ~SidebarDockingWindow() override; virtual void dispose() override; diff --git a/include/sfx2/strings.hrc b/include/sfx2/strings.hrc index 105b8008aabf..5e39f1147611 100644 --- a/include/sfx2/strings.hrc +++ b/include/sfx2/strings.hrc @@ -147,6 +147,13 @@ #define STR_DDE_ERROR NC_("STR_DDE_ERROR", "DDE link to %1 for %2 area %3 are not available.") #define STR_SECURITY_WARNING_NO_HYPERLINKS NC_("STR_SECURITY_WARNING_NO_HYPERLINKS", "For security reasons, the hyperlink cannot be executed.\nThe stated address will not be opened.") #define RID_SECURITY_WARNING_TITLE NC_("RID_SECURITY_WARNING_TITLE", "Security Warning") +/*infobar for allowing links to update or not*/ +#define STR_INFOBAR_LINKS_DISABLED NC_("STR_INFOBAR_LINKS_DISABLED", "Automatic update of external links has been disabled.") +/*infobar button for allowing links to update*/ +#define STR_INFOBAR_ALLOW_UPDATING NC_("STR_INFOBAR_ALLOW_UPDATING", "Allow updating") +/*tooltip for the "Allow updating" infobar button*/ +#define STR_INFOBAR_ALLOW_UPDATING_TOOLTIP NC_("STR_INFOBAR_ALLOW_UPDATING_TOOLTIP", "Only allow updating if you trust this document.") +#define STR_INFOBAR_ALLOW_UPDATING_TOOLTIP_DISABLED NC_("STR_INFOBAR_ALLOW_UPDATING_TOOLTIP_DISABLED", "Active content is disabled in the security settings. It is not possible to allow updating.") #define RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE NC_("RID_SVXSTR_XMLSEC_QUERY_LOSINGSIGNATURE", "Saving will remove all existing signatures.\nDo you want to continue saving the document?") #define RID_SVXSTR_XMLSEC_QUERY_LOSINGSCRIPTINGSIGNATURE NC_("RID_SVXSTR_XMLSEC_QUERY_LOSINGSCRIPTINGSIGNATURE", "Saving with password will remove all existing scripting signatures, and (depending on macro security settings) macros in the document may no longer be runnable.\nDo you want to continue saving the document with password?") #define RID_SVXSTR_XMLSEC_QUERY_SAVEBEFORESIGN NC_("RID_SVXSTR_XMLSEC_QUERY_SAVEBEFORESIGN", "The document has to be saved before it can be signed.\nDo you want to save the document?") @@ -218,7 +225,7 @@ #define STR_SFX_EXPLORERFILE_BUTTONINSERT NC_("STR_SFX_EXPLORERFILE_BUTTONINSERT", "~Insert") #define STR_SFX_IMPORT_ALL_IMAGES NC_("STR_SFX_IMPORT_ALL_IMAGES", "") #define STR_PB_SAVEACOPY NC_("STR_PB_SAVEACOPY", "Save a Copy") -#define STR_PB_COMPAREDOC NC_("STR_PB_COMPAREDOC", "Compare to Original Document") +#define STR_PB_COMPAREDOC NC_("STR_PB_COMPAREDOC", "Compare with") #define STR_PB_MERGEDOC NC_("STR_PB_MERGEDOC", "Merge with") #define STR_SFX_NEWOFFICEDOC NC_("STR_SFX_NEWOFFICEDOC", "%PRODUCTNAME document") @@ -272,6 +279,7 @@ #define STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE NC_("STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE", "You can also try to ignore the lock and open the file for editing.") #define STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN NC_("STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN", "Open ~Copy") #define STR_QUERY_OPENASTEMPLATE_OPEN_BTN NC_("STR_QUERY_OPENASTEMPLATE_OPEN_BTN", "~Open") +#define STR_NEW_FROM_TEMPLATE NC_("STR_NEW_FROM_TEMPLATE", "New From Template") #define STR_REPAIREDDOCUMENT NC_("STR_REPAIREDDOCUMENT", " (repaired document)") #define STR_NONCHECKEDOUT_DOCUMENT NC_("STR_NONCHECKEDOUT_DOCUMENT", "This document is not checked out on the server.") #define STR_GET_INVOLVED_TEXT NC_("STR_GET_INVOLVED_TEXT", "Help us make %PRODUCTNAME even better!") @@ -317,8 +325,11 @@ #define STR_MACROS_DISABLED_SIGNATURE_INVALID NC_("STR_MACROS_DISABLED_SIGNATURE_INVALID", "Macros are signed, but at least one signature has problems.") #define STR_MACROS_DISABLED_CONTENT_UNSIGNED NC_("STR_MACROS_DISABLED_CONTENT_UNSIGNED", "Macros are signed, but the document (containing document events) is not signed.") #define STR_MACROS NC_("STR_MACROS", "Show Macros") +#define STR_CANNOTRUNMACRO NC_("STR_CANNOTRUNMACRO", "For security reasons, you cannot run this macro.\n\nFor more information, check the security settings.") #define STR_SECURITY_OPTIONS NC_("STR_MACROS", "Show Security Options") #define STR_EVENTS NC_("STR_EVENTS", "Show Events") +#define STR_VCLGEN_TITLE NC_("STR_VCLGEN_TITLE", "Fallback UI controls in use") +#define STR_VCLGEN_TEXT NC_("STR_VCLGEN_TEXT", "Look for a desktop environment integration package offered by your distribution.") // Translators: default Impress template names #define STR_TEMPLATE_NAME1 NC_("STR_TEMPLATE_NAME1", "Grey Elegant") diff --git a/include/sfx2/tabdlg.hxx b/include/sfx2/tabdlg.hxx index 048cbaefaf8f..61f0dd0857ba 100644 --- a/include/sfx2/tabdlg.hxx +++ b/include/sfx2/tabdlg.hxx @@ -42,7 +42,11 @@ typedef const WhichRangesContainer & (*GetTabPageRanges)(); // provides internat struct TabDlg_Impl; -namespace weld { class Notebook; } +namespace weld +{ +class Notebook; +class SizeGroup; +} #define RET_USER 100 @@ -188,7 +192,6 @@ public: weld::Button* GetStandardButton() const { return m_xBaseFmtBtn.get(); } weld::Button* GetApplyButton() const { return m_xApplyBtn.get(); } weld::Button* GetResetButton() const { return m_xResetBtn.get(); } - void RemoveResetButton(); void RemoveStandardButton(); virtual short run() override; diff --git a/include/sfx2/tbxctrl.hxx b/include/sfx2/tbxctrl.hxx index b73241e8d86c..e9fc76f7e611 100644 --- a/include/sfx2/tbxctrl.hxx +++ b/include/sfx2/tbxctrl.hxx @@ -87,8 +87,9 @@ protected: virtual VclPtr CreateItemWindow(vcl::Window *pParent); public: - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using svt::ToolboxController::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // new controller API // XStatusListener diff --git a/include/sfx2/templatedlg.hxx b/include/sfx2/templatedlg.hxx index fe03b9d1a584..c97c855b6126 100644 --- a/include/sfx2/templatedlg.hxx +++ b/include/sfx2/templatedlg.hxx @@ -18,8 +18,9 @@ #include #include +#include +#include #include -#include #include @@ -36,18 +37,11 @@ class XModel; namespace weld { class ComboBox; -} -namespace weld -{ class Entry; -} -namespace weld -{ -class TreeView; -} -namespace weld -{ class MenuButton; +class TextWidget; +class TreeView; +class Window; } class SFX2_DLLPUBLIC SfxTemplateManagerDlg : public weld::GenericDialogController @@ -95,7 +89,7 @@ protected: SAL_DLLPRIVATE void SearchUpdate(); - DECL_DLLPRIVATE_LINK(SearchUpdateHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(SearchUpdateHdl, weld::TextWidget&, void); DECL_DLLPRIVATE_LINK(GetFocusHdl, weld::Widget&, void); DECL_DLLPRIVATE_LINK(LoseFocusHdl, weld::Widget&, void); DECL_DLLPRIVATE_LINK(ImplUpdateDataHdl, Timer*, void); @@ -107,7 +101,6 @@ protected: SAL_DLLPRIVATE void OnTemplateImportCategory(std::u16string_view sCategory); // static void OnTemplateLink (); - SAL_DLLPRIVATE void OnTemplateOpen(); SAL_DLLPRIVATE void OnTemplateExport(); SAL_DLLPRIVATE void OnTemplateState(const TemplateViewItem* pItem); @@ -163,7 +156,7 @@ private: std::unique_ptr mxOKButton; public: - DECL_LINK(NewCategoryEditHdl, weld::Entry&, void); + DECL_LINK(NewCategoryEditHdl, weld::TextWidget&, void); DECL_LINK(SelectCategoryHdl, weld::ItemView&, void); void SetCategoryLBEntries(std::vector names); diff --git a/include/sfx2/templatedlglocalview.hxx b/include/sfx2/templatedlglocalview.hxx index fe6ddc84f0eb..c36fb36a92b2 100644 --- a/include/sfx2/templatedlglocalview.hxx +++ b/include/sfx2/templatedlglocalview.hxx @@ -11,6 +11,12 @@ #include #include +enum class TemplateViewMode +{ + ListView, + ThumbnailView +}; + class TemplateDlgLocalView final : public TemplateLocalView, public ListView { friend class TemplateDlgLocalViewUIObject; @@ -42,6 +48,8 @@ public: bool IsVisible() const; + void GrabFocus(); + void connect_focus_rect(const Link& rLink) { GetDrawingArea()->connect_focus_rect(rLink); diff --git a/include/sfx2/thumbnailview.hxx b/include/sfx2/thumbnailview.hxx index fe4196f44519..70260a5bfd1a 100644 --- a/include/sfx2/thumbnailview.hxx +++ b/include/sfx2/thumbnailview.hxx @@ -303,12 +303,15 @@ protected: tools::Long mnVItemSpace; // Vertical spacing between rows, -1 to use excess unused height split up between items tools::Long mnVisLines; tools::Long mnLines; + tools::Long mnPinnedSeparatorY; // tdf#38742 - vertical position of the separator line between pinned/unpinned items + tools::Long mnPinnedSeparatorMargin; // tdf#38742 - horizontal margin of the pinned separator sal_uInt16 mnCols; sal_uInt16 mnFirstLine; bool mbScroll : 1; // Whether we need to scroll bool mbAllowVScrollBar : 1; // Whether to show a visible scrollbar bool mbHasVisibleItems : 1; + bool mbHasPinnedSeparator : 1; // tdf#38742 - whether to draw a separator line after the pinned items bool mbShowTooltips : 1; bool mbDrawMnemonics : 1; bool mbSelectOnFocus : 1; diff --git a/include/sfx2/thumbnailviewitem.hxx b/include/sfx2/thumbnailviewitem.hxx index 515f69f654c2..aca60d42179b 100644 --- a/include/sfx2/thumbnailviewitem.hxx +++ b/include/sfx2/thumbnailviewitem.hxx @@ -121,9 +121,10 @@ public: const tools::Long nPadding, sal_uInt32 nMaxTextLength, const ThumbnailItemAttributes *pAttrs); - virtual void Paint (drawinglayer::processor2d::BaseProcessor2D *pProcessor, - const ThumbnailItemAttributes *pAttrs); - void addTextPrimitives (const OUString& rText, const ThumbnailItemAttributes *pAttrs, Point aPos, drawinglayer::primitive2d::Primitive2DContainer& rSeq); + virtual void Paint(drawinglayer::processor2d::BaseProcessor2D* pProcessor, + const ThumbnailItemAttributes& rAttrs); + void addTextPrimitives(const OUString& rText, const ThumbnailItemAttributes& rAttrs, Point aPos, + drawinglayer::primitive2d::Primitive2DContainer& rSeq); static rtl::Reference createBorderLine (const basegfx::B2DPolygon &rPolygon); diff --git a/include/sfx2/viewfrm.hxx b/include/sfx2/viewfrm.hxx index a3d9781d0e2e..8a25aa39a73f 100644 --- a/include/sfx2/viewfrm.hxx +++ b/include/sfx2/viewfrm.hxx @@ -92,6 +92,7 @@ private: SAL_DLLPRIVATE static void InitInterface_Impl(); SAL_DLLPRIVATE void AppendContainsMacrosInfobar(); + SAL_DLLPRIVATE bool AppendGenericVCLInfobar(); public: SAL_DLLPRIVATE static void SetViewFrame( SfxViewFrame* ); diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index 08d5a3160cf8..0d102a586b2d 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -108,38 +108,24 @@ namespace o3tl template<> struct typed_flags : is_typed_flags {}; } -/* [Description] - - The SfxViewShell flags control the behavior of SfxViewShell for the - duration of its lifetime. They are defined in the constructor of - . -*/ - -enum class LOKDeviceFormFactor -{ - UNKNOWN = 0, - DESKTOP = 1, - TABLET = 2, - MOBILE = 3 -}; - class SfxViewFactory; #define SFX_DECL_VIEWFACTORY(Class) \ private: \ - static SfxViewFactory *s_pFactory; \ + static std::unique_ptr s_pFactory; \ public: \ static SfxViewShell *CreateInstance(SfxViewFrame& rFrame, SfxViewShell *pOldView); \ static void RegisterFactory( SfxInterfaceId nPrio ); \ - static SfxViewFactory*Factory() { return s_pFactory; } \ + static SfxViewFactory*Factory() { return s_pFactory.get(); } \ static void InitFactory() #define SFX_IMPL_NAMED_VIEWFACTORY(Class, AsciiViewName) \ - SfxViewFactory* Class::s_pFactory; \ + std::unique_ptr Class::s_pFactory; \ SfxViewShell* Class::CreateInstance(SfxViewFrame& rFrame, SfxViewShell *pOldView) \ { return new Class(rFrame, pOldView); } \ void Class::RegisterFactory( SfxInterfaceId nPrio ) \ { \ - s_pFactory = new SfxViewFactory(&CreateInstance,nPrio,AsciiViewName);\ + assert(!s_pFactory && "initialising this twice will leak memory"); \ + s_pFactory = std::make_unique(&CreateInstance,nPrio,AsciiViewName); \ InitFactory(); \ } \ void Class::InitFactory() @@ -172,7 +158,6 @@ friend class SfxPrinterController; LanguageTag maLOKLanguageTag; LanguageTag maLOKLocale; std::unique_ptr mpCalendar; - LOKDeviceFormFactor maLOKDeviceFormFactor; bool mbLOKAccessibilityEnabled; rtl::Reference mpLOKDocumentFocusListener; std::unordered_set mvLOKBlockedCommandList; @@ -219,8 +204,6 @@ private: LOKDocumentFocusListener& GetLOKDocumentFocusListener(); const LOKDocumentFocusListener& GetLOKDocumentFocusListener() const; bool lokReadOnlyView : 1 = false; // When true, this is a LOK readonly view - bool allowChangeComments : 1 = false; // Allow editing comments in readonly view mode - bool allowManageRedlines : 1 = false; // Allow accepting/rejecting changes in readonly view mode public: @@ -246,10 +229,6 @@ public: void SetLokReadOnlyView(bool readOnlyView) { lokReadOnlyView = readOnlyView; }; bool IsLokReadOnlyView() const { return lokReadOnlyView; }; - void SetAllowChangeComments(bool allow) { allowChangeComments = allow; } - bool IsAllowChangeComments() const { return allowChangeComments; } - void SetAllowManageRedlines(bool allow) { allowManageRedlines = allow; } - bool IsAllowManageRedlines() const { return allowManageRedlines; } // Misc @@ -261,7 +240,7 @@ public: */ virtual bool PrepareClose( bool bUI = true ); virtual OUString GetSelectionText( bool bCompleteWords = false, bool bOnlyASample = false ); - virtual bool HasSelection( bool bText = true ) const; + virtual bool HasSelection(bool bMustHaveText) const; virtual SdrView* GetDrawView() const; void AddSubShell( SfxShell& rShell ); @@ -475,14 +454,6 @@ public: void SetLOKLanguageAndLocale(const OUString& rBcp47LanguageTag); /// Get the LibreOfficeKit calendar of this view. CalendarWrapper& GetLOKCalendar(); - /// Get the form factor of the device where the lok client is running. - LOKDeviceFormFactor GetLOKDeviceFormFactor() const { return maLOKDeviceFormFactor; } - /// Check if the lok client is running on a desktop machine. - bool isLOKDesktop() const { return maLOKDeviceFormFactor == LOKDeviceFormFactor::DESKTOP; } - /// Check if the lok client is running on a tablet. - bool isLOKTablet() const { return maLOKDeviceFormFactor == LOKDeviceFormFactor::TABLET; } - /// Check if the lok client is running on a mobile device. - bool isLOKMobilePhone() const { return maLOKDeviceFormFactor == LOKDeviceFormFactor::MOBILE; } virtual tools::Rectangle getLOKVisibleArea() const { return tools::Rectangle(); } diff --git a/include/svl/fstathelper.hxx b/include/svl/fstathelper.hxx index e90ca798a7ea..abea92a7c950 100644 --- a/include/svl/fstathelper.hxx +++ b/include/svl/fstathelper.hxx @@ -43,12 +43,6 @@ SVL_DLLPUBLIC bool GetModifiedDateTimeOfFile( const OUString& rURL, UCB.IsContent. */ SVL_DLLPUBLIC bool IsDocument( const OUString& rURL ); - -/** Return if under the URL a folder exist. This is only a wrapper for the - UCB.isFolder. -*/ -SVL_DLLPUBLIC bool IsFolder( const OUString& rURL ); - } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svl/hint.hxx b/include/svl/hint.hxx index ce7ec1896ee1..4db15660a9ce 100644 --- a/include/svl/hint.hxx +++ b/include/svl/hint.hxx @@ -132,6 +132,7 @@ enum class SfxHintId { ScEditView, ScUnoRefUndo, ScBulkData, + ScRefErrorCreated, // SC accessibility hints ScAccTableChanged, diff --git a/include/svl/inettype.hxx b/include/svl/inettype.hxx index f57ca1b927ad..8000ae63bb70 100644 --- a/include/svl/inettype.hxx +++ b/include/svl/inettype.hxx @@ -65,7 +65,7 @@ inline constexpr OUString CONTENT_TYPE_STR_APP_MSPPOINT = u"application/x-mspowe inline constexpr OUString CONTENT_TYPE_STR_APP_MSWORD_TEMPL = u"application/x-msword-template"_ustr; inline constexpr OUString CONTENT_TYPE_STR_APP_MSWORD = u"application/x-msword"_ustr; inline constexpr OUString CONTENT_TYPE_STR_APP_STARCALC = u"application/x-starcalc"_ustr; -inline constexpr OUString CONTENT_TYPE_STR_APP_STARCHART = u"application/x-starchart;"_ustr; +inline constexpr OUString CONTENT_TYPE_STR_APP_STARCHART = u"application/x-starchart"_ustr; inline constexpr OUString CONTENT_TYPE_STR_APP_STARDRAW = u"application/x-stardraw"_ustr; inline constexpr OUString CONTENT_TYPE_STR_APP_STARHELP = u"application/x-starhelp"_ustr; inline constexpr OUString CONTENT_TYPE_STR_APP_STARIMAGE = u"application/x-starimage"_ustr; @@ -111,7 +111,7 @@ inline constexpr OUString CONTENT_TYPE_STR_TEXT_VCARD = u"text/x-vCard"_ustr; inline constexpr OUString CONTENT_TYPE_STR_VIDEO_MSVIDEO = u"video/x-msvideo"_ustr; inline constexpr OUString CONTENT_TYPE_STR_VIDEO_THEORA = u"video/theora"_ustr; inline constexpr OUString CONTENT_TYPE_STR_VIDEO_VDO = u"video/vdo"_ustr; -inline constexpr OUString CONTENT_TYPE_STR_VIDEO_WEBM = u"audio/webm"_ustr; +inline constexpr OUString CONTENT_TYPE_STR_VIDEO_WEBM = u"video/webm"_ustr; inline constexpr OUString CONTENT_TYPE_STR_X_STARMAIL = u"x-starmail"_ustr; inline constexpr OUString CONTENT_TYPE_STR_X_VRML = u"x-world/x-vrml"_ustr; inline constexpr OUString CONTENT_TYPE_STR_APP_VND_SUN_XML_WRITER @@ -166,6 +166,7 @@ enum INetContentType CONTENT_TYPE_AUDIO_WEBM, CONTENT_TYPE_IMAGE_GIF, CONTENT_TYPE_IMAGE_JPEG, + CONTENT_TYPE_IMAGE_JXL, CONTENT_TYPE_IMAGE_PCX, CONTENT_TYPE_IMAGE_PNG, CONTENT_TYPE_IMAGE_TIFF, diff --git a/include/svl/itempool.hxx b/include/svl/itempool.hxx index 39e3060f1f88..7409515f6a80 100644 --- a/include/svl/itempool.hxx +++ b/include/svl/itempool.hxx @@ -198,7 +198,6 @@ private: assert(false && "missing bounds check before use"); return 0; } - sal_uInt16 GetSize_Impl() const { return mnEnd - mnStart + 1; } SfxItemPool* getTargetPool(sal_uInt16 nWhich) const; // moved to private: use the access methods, e.g. NeedsSurrogateSupport @@ -258,7 +257,6 @@ public: virtual MapUnit GetMetric( sal_uInt16 nWhich ) const; void SetDefaultMetric( MapUnit eNewMetric ); - MapUnit GetDefaultMetric() const { return eDefMetric; } /** Request string representation of pool items. diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx index 8e5a3b63b76d..3cf68d03a4d9 100644 --- a/include/svl/itemset.hxx +++ b/include/svl/itemset.hxx @@ -303,18 +303,4 @@ private: virtual const SfxPoolItem* PutImpl( const SfxPoolItem&, bool bPassingOwnership ) override; }; - -// Was: Allocate the items array inside the object, to reduce allocation cost. -// NOTE: No longer needed with unordered_set, but there are 560+ places to -// replace/adapt, so keep it for now. -// To adapt, there is the static makeFixedSfxItemSet member in SfxItemSet. Did -// that in one place to check functionality (easy hack...?) -template -class SfxItemSetFixed final : public SfxItemSet -{ -public: - SfxItemSetFixed( SfxItemPool& rPool) - : SfxItemSet(rPool, WhichRangesContainer(svl::Items_t{})){}//, -}; - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svl/lockfilecommon.hxx b/include/svl/lockfilecommon.hxx index 8a261809c8c3..85485de0d8cb 100644 --- a/include/svl/lockfilecommon.hxx +++ b/include/svl/lockfilecommon.hxx @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -67,6 +68,8 @@ public: static OUString GetOOOUserName(); static OUString GetCurrentLocalTime(); static LockFileEntry GenerateOwnEntry(); + static OUString FormatDateTime(const OUString& aTimeStr, + LanguageType eLang = LANGUAGE_SYSTEM); static INetURLObject ResolveLinks( const INetURLObject& aDocURL ); }; diff --git a/include/svl/numformat.hxx b/include/svl/numformat.hxx index cbc29416df5a..de8b74c4aab3 100644 --- a/include/svl/numformat.hxx +++ b/include/svl/numformat.hxx @@ -55,6 +55,10 @@ public: /// Do the CallBack to ColorTable Color* GetUserDefColor(sal_uInt16 nIndex) const; + /// Idem but in reverse (we want the index from Color) + void SetColorIndexLink(const Link& rColorIndexCallBack); + sal_Int32 GetUserDefColorIndex(const Color& rColor) const; + /// Change language/country, also input and format scanner void ChangeIntl(LanguageType eLnge); /// Change the reference null date @@ -530,7 +534,7 @@ public: NfKeywordTable matches the locale with which the SvNumberFormatter instance was created and initialized. - This function preliminary exists for unit tests and otherwise is + This function primarily exists for unit tests and otherwise is pretty much useless. */ const NfKeywordTable& GetKeywords(sal_uInt32 nKey); @@ -556,6 +560,7 @@ private: SvNFLanguageData m_aCurrentLanguage; OnDemandNativeNumberWrapper m_xNatNum; // Native number service loaded on demand Link aColorLink; // User defined color table CallBack + Link aColorIndexLink; // User defined color table Callback (reverse) SVL_DLLPRIVATE static sal_uInt16 nSystemCurrencyPosition; SVL_DLLPRIVATE static SvNumberFormatterRegistry_Impl* pFormatterRegistry; diff --git a/include/svl/poolitem.hxx b/include/svl/poolitem.hxx index 1027ed1de445..871285a4b6a3 100644 --- a/include/svl/poolitem.hxx +++ b/include/svl/poolitem.hxx @@ -189,6 +189,7 @@ enum class SfxItemType : sal_uInt16 SdrEdgeNode2VertDistItemType, SdrFractionItemType, SdrGrafBlueItemType, + SdrGrafClipPolyPolygonItemType, SdrGrafContrastItemType, SdrGrafCropItemType, SdrGrafGamma100ItemType, @@ -658,8 +659,6 @@ public: bool isSetItem() const { return m_bIsSetItem; } bool isShareable() const { return m_bShareable; } bool isNameOrIndex() const { return m_bNameOrIndex; } - bool isPooled() const { return GetRefCount() > 0; } - // version that allows nullptrs static bool areSame(const SfxPoolItem* pItem1, const SfxPoolItem* pItem2); @@ -790,12 +789,12 @@ private: virtual void remove(const SfxPoolItem&) = 0; }; -// offering a default implementation that can be use for +// offering a default implementation that can be used for // each SfxPoolItem (except when !isShareable()). It just // uses an unordered_set holding ptrs to SfxPoolItems added // and SfxPoolItem::operator== to linearly search for one. // Thus this is not the fastest, but as fast as old 'pooled' -// stuff - better use an intelligent, pro-Item implementation +// stuff - better use an intelligent, per-Item implementation // that does e.g. hashing or whatever might be feasible for // that specific Item (see other derivations) class SVL_DLLPUBLIC DefaultItemInstanceManager final : public ItemInstanceManager diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx index 2f8757da1911..159837bf4419 100644 --- a/include/svl/undo.hxx +++ b/include/svl/undo.hxx @@ -67,6 +67,9 @@ public: virtual bool Merge( SfxUndoAction *pNextAction ); virtual OUString GetComment() const; + virtual void SetComment(const OUString& rStr); + virtual void SetObjDescription(const OUString& rStr); + virtual OUString GetRepeatComment(SfxRepeatTarget&) const; /// ID of the view shell that created this undo action. virtual ViewShellId GetViewShellId() const; @@ -148,12 +151,13 @@ public: virtual bool Merge( SfxUndoAction *pNextAction ) override; virtual OUString GetComment() const override; + void SetComment(const OUString& rComment) override; + /// See SfxUndoAction::GetViewShellId(). ViewShellId GetViewShellId() const override; virtual OUString GetRepeatComment(SfxRepeatTarget&) const override; sal_uInt16 GetId() const; - void SetComment(const OUString& rComment); void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; @@ -196,6 +200,9 @@ public: SfxUndoManager( size_t nMaxUndoActionCount = 20 ); virtual ~SfxUndoManager(); + void SetUndoComment(const OUString& rComment); + void SetUndoComment(const OUString& rComment, const OUString& rObjDescr); + void SetMaxUndoActionCount( size_t nMaxUndoActionCount ); size_t GetMaxUndoActionCount() const; virtual void AddUndoAction( std::unique_ptr pAction, bool bTryMerg=false ); diff --git a/include/svtools/DocumentToGraphicRenderer.hxx b/include/svtools/DocumentToGraphicRenderer.hxx index 9f8eadc7927c..61480042592b 100644 --- a/include/svtools/DocumentToGraphicRenderer.hxx +++ b/include/svtools/DocumentToGraphicRenderer.hxx @@ -26,10 +26,10 @@ #include -namespace com :: sun :: star :: awt { class XToolkit; } -namespace com :: sun :: star :: frame { class XModel; } -namespace com :: sun :: star :: lang { class XComponent; } -namespace com :: sun :: star :: view { class XRenderable; } +namespace com::sun::star::awt { class XToolkit; } +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::lang { class XComponent; } +namespace com::sun::star::view { class XRenderable; } namespace com::sun::star { namespace drawing { diff --git a/include/svtools/PlaceEditDialog.hxx b/include/svtools/PlaceEditDialog.hxx index c4565475566e..13daeaf41e31 100644 --- a/include/svtools/PlaceEditDialog.hxx +++ b/include/svtools/PlaceEditDialog.hxx @@ -11,9 +11,11 @@ #include #include +#include #include #include -#include +#include +#include #include #include @@ -22,10 +24,8 @@ class Place; class DetailsContainer; namespace weld { +class Button; class ComboBox; -} -namespace weld -{ class SpinButton; } @@ -99,11 +99,11 @@ private: DECL_DLLPRIVATE_LINK(OKHdl, weld::Button&, void); DECL_DLLPRIVATE_LINK(DelHdl, weld::Button&, void); DECL_DLLPRIVATE_LINK(EditHdl, DetailsContainer*, void); - DECL_DLLPRIVATE_LINK(ModifyHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(ModifyHdl, weld::TextWidget&, void); void SelectType(bool bSkipSeparator); DECL_DLLPRIVATE_LINK(SelectTypeHdl, weld::ComboBox&, void); - DECL_DLLPRIVATE_LINK(EditLabelHdl, weld::Entry&, void); - DECL_DLLPRIVATE_LINK(EditUsernameHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(EditLabelHdl, weld::TextWidget&, void); + DECL_DLLPRIVATE_LINK(EditUsernameHdl, weld::TextWidget&, void); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svtools/acceleratorexecute.hxx b/include/svtools/acceleratorexecute.hxx index 2da8f887f588..654c2cea5647 100644 --- a/include/svtools/acceleratorexecute.hxx +++ b/include/svtools/acceleratorexecute.hxx @@ -27,12 +27,12 @@ #include namespace com::sun::star::awt { struct KeyEvent; } -namespace com :: sun :: star :: frame { class XDispatchProvider; } -namespace com :: sun :: star :: frame { class XFrame; } -namespace com :: sun :: star :: frame { class XModel; } -namespace com :: sun :: star :: ui { class XAcceleratorConfiguration; } -namespace com :: sun :: star :: uno { class XComponentContext; } -namespace com :: sun :: star :: util { class XURLTransformer; } +namespace com::sun::star::frame { class XDispatchProvider; } +namespace com::sun::star::frame { class XFrame; } +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::ui { class XAcceleratorConfiguration; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::util { class XURLTransformer; } namespace vcl { class KeyCode; } diff --git a/include/svtools/addresstemplate.hxx b/include/svtools/addresstemplate.hxx index bfbe2d601beb..04337f8aac91 100644 --- a/include/svtools/addresstemplate.hxx +++ b/include/svtools/addresstemplate.hxx @@ -27,11 +27,11 @@ #include -namespace com :: sun :: star :: container { class XNameAccess; } -namespace com :: sun :: star :: sdbc { class XDataSource; } -namespace com :: sun :: star :: sdb { class XDatabaseContext; } -namespace com :: sun :: star :: uno { class XComponentContext; } -namespace com :: sun :: star :: util { struct AliasProgrammaticPair; } +namespace com::sun::star::container { class XNameAccess; } +namespace com::sun::star::sdbc { class XDataSource; } +namespace com::sun::star::sdb { class XDatabaseContext; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::util { struct AliasProgrammaticPair; } namespace weld { class Button; } namespace weld { class ComboBox; } @@ -52,10 +52,10 @@ namespace svt const css::uno::Reference< css::uno::XComponentContext >& _rxORB ); /** if you use this ctor, the dialog -

      • will not store it's data in the configuration (nor initially retrieve it from there)
      • -
      • will not allow to change the data source name
      • -
      • will not allow to change the table name
      • -
      • will not allow to call the data source administration dialog
      • +
        • will not store its data in the configuration (nor initially retrieve it from there)
        • +
        • will not allow changing the data source name
        • +
        • will not allow changing the table name
        • +
        • will not allow calling the data source administration dialog
        @param _rxORB diff --git a/include/svtools/bindablecontrolhelper.hxx b/include/svtools/bindablecontrolhelper.hxx index 39db62590b48..b1134985aca9 100644 --- a/include/svtools/bindablecontrolhelper.hxx +++ b/include/svtools/bindablecontrolhelper.hxx @@ -22,8 +22,8 @@ #include #include -namespace com :: sun :: star :: frame { class XModel; } -namespace com :: sun :: star :: uno { class XInterface; } +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::uno { class XInterface; } namespace com::sun::star::uno { template class Reference; } namespace svt diff --git a/include/svtools/brwbox.hxx b/include/svtools/brwbox.hxx index 4ef28bcf77dc..6e4221f0752c 100644 --- a/include/svtools/brwbox.hxx +++ b/include/svtools/brwbox.hxx @@ -42,6 +42,11 @@ class ScrollAdaptor; class MeasureStatusBar; enum class AccessibleBrowseBoxObjType; +namespace com::sun::star::accessibility +{ +class XAccessible; +} + namespace weld { class Scrollbar; } @@ -259,7 +264,7 @@ class SVT_DLLPUBLIC BrowseBox friend class BrowserDataWin; public: - typedef ::std::map> THeaderCellMap; + typedef std::map> THeaderCellMap; static const sal_uInt16 HandleColumnId = 0; @@ -381,17 +386,16 @@ private: SAL_DLLPRIVATE void SetToggledSelectedColumn(sal_uInt16 _nSelectedColumnId); /// @see AccessibleBrowseBox::getHeaderBar - css::uno::Reference + rtl::Reference getAccessibleHeaderBar(AccessibleBrowseBoxObjType _eObjType); - css::uno::Reference + rtl::Reference getAccessibleHeaderCell(BrowseBox::THeaderCellMap& _raHeaderCells, sal_Int32 _nPos, AccessibleBrowseBoxObjType _eType, - const css::uno::Reference& _rParent); + const rtl::Reference& rpParent); /// @see AccessibleBrowseBox::getTable - css::uno::Reference - getAccessibleTable(); + rtl::Reference getAccessibleTable(); protected: bool m_bNavigationBar; @@ -481,7 +485,7 @@ public: virtual void GetFocus() override; virtual void Resize() override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Command( const CommandEvent& rEvt ) override; virtual void StartDrag( sal_Int8 _nAction, const Point& _rPosPixel ) override; @@ -716,17 +720,15 @@ public: /** Creates the accessible object of a row header. @param nRow The row index of the header. - @return The XAccessible interface of the specified row header. */ - virtual css::uno::Reference< - css::accessibility::XAccessible > - CreateAccessibleRowHeader( sal_Int32 nRow ) override; + @return The accessible of the specified row header. */ + virtual rtl::Reference + CreateAccessibleRowHeader(sal_Int32 nRow) override; /** Creates the accessible object of a column header. @param nColumnId The column ID of the header. - @return The XAccessible interface of the specified column header. */ - virtual css::uno::Reference< - css::accessibility::XAccessible > - CreateAccessibleColumnHeader( sal_uInt16 nColumnPos ) override; + @return The accessible of the specified column header. */ + virtual rtl::Reference + CreateAccessibleColumnHeader(sal_uInt16 nColumnPos) override; /** Converts a point relative to the data window origin to a cell address. @param rnRow Out-parameter that takes the row index. @@ -811,7 +813,6 @@ public: virtual void GetAllSelectedColumns( css::uno::Sequence< sal_Int32 >& _rColumns ) const override; virtual bool IsCellVisible( sal_Int32 _nRow, sal_uInt16 _nColumn ) const override; virtual OUString GetAccessibleCellText(sal_Int32 _nRow, sal_uInt16 _nColPos) const override; - virtual bool GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr, int nIndex, int nLen, std::vector< tools::Rectangle >& rVector ) override; virtual tools::Rectangle GetWindowExtentsRelative(const vcl::Window& rRelativeWindow) const override; virtual void GrabFocus() override; virtual rtl::Reference GetAccessible() override; diff --git a/include/svtools/confirmationdlg.hxx b/include/svtools/confirmationdlg.hxx new file mode 100644 index 000000000000..412cee594add --- /dev/null +++ b/include/svtools/confirmationdlg.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include +#include + +class SVT_DLLPUBLIC ConfirmationDlg +{ +public: + template + static bool Query(weld::Window* pParent, const OUString& rTitle, const OUString& rText, + const OUString& rQuestion, const OUString& rYesLabel = u""_ustr, + const OUString& rNoLabel = u""_ustr) + { + const bool bHideShowAgain = ConfigurationLocalizedProperty::isReadOnly(); + + if (ConfigurationLocalizedProperty::get()) + { + QueryDialog aDialog(pParent, rTitle, rText, rQuestion, bHideShowAgain); + if (!rYesLabel.isEmpty()) + aDialog.SetYesLabel(rYesLabel); + if (!rNoLabel.isEmpty()) + aDialog.SetNoLabel(rNoLabel); + + short nResult = aDialog.run(); + + if (aDialog.DontShowAgain() && !bHideShowAgain) + { + std::shared_ptr aBatch( + comphelper::ConfigurationChanges::create()); + ConfigurationLocalizedProperty::set(false, aBatch); + aBatch->commit(); + } + + return nResult == RET_YES; + } + else + return true; // don't ask and assume yes + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/svtools/ctrlbox.hxx b/include/svtools/ctrlbox.hxx index adc43f8fa1f9..52495e1f4d68 100644 --- a/include/svtools/ctrlbox.hxx +++ b/include/svtools/ctrlbox.hxx @@ -25,14 +25,20 @@ #include #include #include +#include #include #include -#include #include -namespace weld { class Builder; } -namespace weld { class CustomWeld; } +namespace weld +{ +class Builder; +class Button; +class CustomWeld; +class TreeIter; +class TreeView; +} class Bitmap; class FontList; @@ -252,18 +258,17 @@ public: virtual void GrabFocus() override; private: + SVT_DLLPRIVATE Image GetLineImage(const ImpLineListData& rLineListData); + SVT_DLLPRIVATE ScopedVclPtr GetLineImage(int nIndex); - SVT_DLLPRIVATE void ImpGetLine( tools::Long nLine1, tools::Long nLine2, tools::Long nDistance, - Color nColor1, Color nColor2, Color nColorDist, - SvxBorderLineStyle nStyle, Bitmap& rBmp ); - - DECL_DLLPRIVATE_LINK(ValueSelectHdl, ValueSet*, void); + DECL_DLLPRIVATE_LINK(ItemActivatedHdl, const weld::TreeIter&, bool); DECL_DLLPRIVATE_LINK(ToggleHdl, weld::Toggleable&, void); DECL_DLLPRIVATE_LINK(NoneHdl, weld::Button&, void); DECL_DLLPRIVATE_LINK(StyleUpdatedHdl, weld::Widget&, void); void UpdateEntries(); + void HandleEntrySelection(); void UpdatePreview(); SvtLineListBox( const SvtLineListBox& ) = delete; @@ -271,8 +276,7 @@ private: std::unique_ptr m_xControl; std::unique_ptr m_xNoneButton; - std::unique_ptr m_xLineSet; - std::unique_ptr m_xLineSetWin; + std::unique_ptr m_xLineTreeView; std::vector> m_vLineList; tools::Long m_nWidth; @@ -363,12 +367,9 @@ public: void connect_key_press(const Link& rLink) { m_xComboBox->connect_key_press(rLink); } void connect_popup_toggled(const Link& rLink){ m_xComboBox->connect_popup_toggled(rLink); } void connect_live_preview(const Link& rLink) { m_aLivePreviewHdl = rLink; } - int get_active() const { return m_xComboBox->get_active(); } OUString get_active_text() const { return m_xComboBox->get_active_text(); } void set_active_or_entry_text(const OUString& rText); void set_active(int nPos) { m_xComboBox->set_active(nPos); } - int get_count() const { return m_xComboBox->get_count(); } - OUString get_text(int nIndex) const { return m_xComboBox->get_text(nIndex); } void set_sensitive(bool bSensitive) { m_xComboBox->set_sensitive(bSensitive); } void save_value() { m_xComboBox->save_value(); } OUString const& get_saved_value() const { return m_xComboBox->get_saved_value(); } @@ -378,7 +379,6 @@ public: void grab_focus() { m_xComboBox->grab_focus(); } bool has_focus() const { return m_xComboBox->has_focus(); } void connect_entry_activate(const Link& rLink) { m_xComboBox->connect_entry_activate(rLink); } - void connect_get_property_tree(const Link& rLink) { m_xComboBox->connect_get_property_tree(rLink); } void set_entry_width_chars(int nWidth) { m_xComboBox->set_entry_width_chars(nWidth); } void set_size_request(int nWidth, int nHeight) { m_xComboBox->set_size_request(nWidth, nHeight); } int get_max_mru_count() const { return m_xComboBox->get_max_mru_count(); } @@ -415,6 +415,7 @@ public: m_aLastStyle = rText; m_xComboBox->set_active_text(rText); } + void set_active_or_entry_text(const OUString& rText); void set_size_request(int nWidth, int nHeight) { m_xComboBox->set_size_request(nWidth, nHeight); } void append_text(const OUString& rStr) { m_xComboBox->append_text(rStr); } @@ -494,18 +495,14 @@ public: void set_sensitive(bool bSensitive) { m_xComboBox->set_sensitive(bSensitive); } void set_size_request(int nWidth, int nHeight) { m_xComboBox->set_size_request(nWidth, nHeight); } - int get_active() const { return m_xComboBox->get_active(); } int get_value() const; void set_value(int nValue); void save_value() { m_nSavedValue = get_value(); } int get_saved_value() const { return m_nSavedValue; } bool get_value_changed_from_saved() const { return get_value() != get_saved_value(); } - int get_count() const { return m_xComboBox->get_count(); } - OUString get_text(int i) const { return m_xComboBox->get_text(i); } bool has_focus() const { return m_xComboBox->has_focus(); } void connect_entry_activate(const Link& rLink) { m_xComboBox->connect_entry_activate(rLink); } void disable_entry_completion() { m_xComboBox->set_entry_completion(false, false); } - void connect_get_property_tree(const Link& rLink) { m_xComboBox->connect_get_property_tree(rLink); } weld::Widget* getWidget() { return m_xComboBox.get(); } diff --git a/include/svtools/ctrltool.hxx b/include/svtools/ctrltool.hxx index a03729253fec..3662a20bd5e7 100644 --- a/include/svtools/ctrltool.hxx +++ b/include/svtools/ctrltool.hxx @@ -170,6 +170,8 @@ public: const OUString& GetBoldItalicStr() const { return maBoldItalic; } const OUString& GetStyleName( FontWeight eWeight, FontItalic eItalic ) const; OUString GetStyleName( const FontMetric& rFontMetric ) const; + OUString GetFaceStyleName( std::u16string_view rName, + const OUString& rStyleName ) const; FontMetric Get( const OUString& rName, const OUString& rStyleName ) const; diff --git a/include/svtools/dlgname.hxx b/include/svtools/dlgname.hxx index 2de6266bebb6..a46b957fd2c3 100644 --- a/include/svtools/dlgname.hxx +++ b/include/svtools/dlgname.hxx @@ -20,13 +20,16 @@ #include #include +#include +#include #include #include #include +#include #include #include #include -#include +#include /// Dialog for editing a name class SVT_DLLPUBLIC SvxNameDialog final : public weld::GenericDialogController @@ -40,7 +43,7 @@ private: Link m_aCheckNameHdl; Link m_aCheckNameTooltipHdl; - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); public: SvxNameDialog(weld::Window* pWindow, const OUString& rName, const OUString& rDesc, @@ -119,7 +122,7 @@ private: // callback link for name uniqueness Link aCheckNameHdl; - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); public: // constructor diff --git a/include/svtools/editbrowsebox.hxx b/include/svtools/editbrowsebox.hxx index 600714adb88a..3ab74a4367f1 100644 --- a/include/svtools/editbrowsebox.hxx +++ b/include/svtools/editbrowsebox.hxx @@ -28,1103 +28,1015 @@ #include #include #include +#include +#include +#include #include #include +#include #include #include +#include #include +#include #include #include // EditBrowseBoxFlags (EBBF) enum class EditBrowseBoxFlags { - NONE = 0x0000, -/** if this bit is _not_ set, the handle column will be invalidated upon + NONE = 0x0000, + /** if this bit is _not_ set, the handle column will be invalidated upon changing the row in the browse box. This is for forcing the row picture to be repainted. If you do not have row pictures or text, you don't need this invalidation, then you would specify this bit to prevent flicker -*/ - NO_HANDLE_COLUMN_CONTENT = 0x0001, -/** set this bit to activate the cell on a MouseButtonDown, not a MouseButtonUp event - */ - ACTIVATE_ON_BUTTONDOWN = 0x0002, -/** if this bit is set and EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT is _not_ set, the handle + */ + NO_HANDLE_COLUMN_CONTENT = 0x0001, + /** set this bit to activate the cell on a MouseButtonDown, not a MouseButtonUp event + */ + ACTIVATE_ON_BUTTONDOWN = 0x0002, + /** if this bit is set and EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT is _not_ set, the handle column is drawn with the text contained in column 0 instead of an image -*/ - HANDLE_COLUMN_TEXT = 0x0004, + */ + HANDLE_COLUMN_TEXT = 0x0004, -/** If this bit is set, tab traveling is somewhat modified
        + /** If this bit is set, tab traveling is somewhat modified
        If the control gets the focus because the user pressed the TAB key, then the first or last cell (depending on whether the traveling was cycling forward or backward) gets activated. @see Window::GetGetFocusFlags @see GETFOCUS_* -*/ - SMART_TAB_TRAVEL = 0x0008, + */ + SMART_TAB_TRAVEL = 0x0008, }; namespace o3tl { - template<> struct typed_flags : is_typed_flags {}; +template <> struct typed_flags : is_typed_flags +{ +}; } namespace svt { - class ControlBase; +class ControlBase; - class SVT_DLLPUBLIC CellController : public SvRefBase +class SVT_DLLPUBLIC CellController : public SvRefBase +{ + friend class EditBrowseBox; + Link maModifyHdl; + + VclPtr pWindow; + bool bSuspended; // if the window is hidden and disabled + +public: + CellController(ControlBase* pW); + virtual ~CellController() override; + + ControlBase& GetWindow() const { return *pWindow; } + + virtual void SaveValue() = 0; + virtual bool IsValueChangedFromSaved() const = 0; + + // commit any current changes. Especially, do any reformatting you need (from input formatting + // to output formatting) here + virtual void CommitModifications(); + + // suspending the controller is not cumulative! + void suspend(); + void resume(); + bool isSuspended() const { return bSuspended; } + +protected: + virtual bool MoveAllowed(const KeyEvent& rEvt) const; + void SetModifyHdl(const Link& rLink) { maModifyHdl = rLink; } + virtual void ActivatingMouseEvent(const BrowserMouseEvent& rEvt, bool bUp); + virtual void callModifyHdl() { maModifyHdl.Call(nullptr); } +}; + +typedef tools::SvRef CellControllerRef; + +//= IEditImplementation + +class SVT_DLLPUBLIC IEditImplementation +{ +public: + virtual ~IEditImplementation() = 0; + + virtual ControlBase& GetControl() = 0; + + virtual OUString GetText(LineEnd aSeparator) const = 0; + virtual void SetText(const OUString& _rStr) = 0; + + virtual bool IsReadOnly() const = 0; + virtual void SetReadOnly(bool bReadOnly) = 0; + + virtual sal_Int32 GetMaxTextLen() const = 0; + virtual void SetMaxTextLen(sal_Int32 _nMaxLen) = 0; + + virtual Selection GetSelection() const = 0; + virtual void SetSelection(const Selection& _rSelection) = 0; + + virtual void ReplaceSelected(const OUString& _rStr) = 0; + virtual OUString GetSelected(LineEnd aSeparator) const = 0; + + virtual bool IsValueChangedFromSaved() const = 0; + virtual void SaveValue() = 0; + + virtual bool CanUp() const = 0; + virtual bool CanDown() const = 0; + + virtual void Cut() = 0; + virtual void Copy() = 0; + virtual void Paste() = 0; + + // sets a link to call when the text is changed by the user + void SetModifyHdl(const Link& rLink) { m_aModify1Hdl = rLink; } + + // sets an additional link to call when the text is changed by the user + void SetAuxModifyHdl(const Link& rLink) { m_aModify2Hdl = rLink; } + +private: + Link m_aModify1Hdl; + Link m_aModify2Hdl; + +protected: + void CallModifyHdls() { - friend class EditBrowseBox; - Link maModifyHdl; + m_aModify1Hdl.Call(nullptr); + m_aModify2Hdl.Call(nullptr); + } +}; - VclPtr pWindow; - bool bSuspended; // if the window is hidden and disabled +class SVT_DLLPUBLIC ControlBase : public InterimItemWindow +{ +public: + ControlBase(BrowserDataWin* pParent, const OUString& rUIXMLDescription, const OUString& rID); - public: + virtual void SetEditableReadOnly(bool bReadOnly); - CellController(ControlBase* pW); - virtual ~CellController() override; + virtual bool ProcessKey(const KeyEvent& rKEvt); - ControlBase& GetWindow() const { return *pWindow; } + virtual void SetPointFont(const vcl::Font& rFont) = 0; - virtual void SaveValue() = 0; - virtual bool IsValueChangedFromSaved() const = 0; + // chain after the FocusInHdl + void SetFocusInHdl(const Link& rHdl) { m_aFocusInHdl = rHdl; } - // commit any current changes. Especially, do any reformatting you need (from input formatting - // to output formatting) here - virtual void CommitModifications(); + // chain after the FocusOutHdl + void SetFocusOutHdl(const Link& rHdl) { m_aFocusOutHdl = rHdl; } - // suspending the controller is not cumulative! - void suspend( ); - void resume( ); - bool isSuspended( ) const { return bSuspended; } + void SetMousePressHdl(const Link& rHdl) { m_aMousePressHdl = rHdl; } - protected: - virtual bool MoveAllowed(const KeyEvent& rEvt) const; - void SetModifyHdl(const Link& rLink) { maModifyHdl = rLink; } - virtual void ActivatingMouseEvent(const BrowserMouseEvent& rEvt, bool bUp); - virtual void callModifyHdl() { maModifyHdl.Call(nullptr); } - }; - - typedef tools::SvRef CellControllerRef; - - - //= IEditImplementation - - class SVT_DLLPUBLIC IEditImplementation + void SetMouseReleaseHdl(const Link& rHdl) { - public: - virtual ~IEditImplementation() = 0; + m_aMouseReleaseHdl = rHdl; + } - virtual ControlBase& GetControl() = 0; + void SetMouseMoveHdl(const Link& rHdl) { m_aMouseMoveHdl = rHdl; } - virtual OUString GetText( LineEnd aSeparator ) const = 0; - virtual void SetText( const OUString& _rStr ) = 0; + void SetKeyInputHdl(const Link& rHdl) { m_aKeyInputHdl = rHdl; } - virtual bool IsReadOnly() const = 0; - virtual void SetReadOnly( bool bReadOnly ) = 0; + void SetKeyReleaseHdl(const Link& rHdl) { m_aKeyReleaseHdl = rHdl; } - virtual sal_Int32 GetMaxTextLen() const = 0; - virtual void SetMaxTextLen( sal_Int32 _nMaxLen ) = 0; + rtl::Reference CreateAccessible() override; - virtual Selection GetSelection() const = 0; - virtual void SetSelection( const Selection& _rSelection ) = 0; +protected: + DECL_DLLPRIVATE_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_DLLPRIVATE_LINK(KeyReleaseHdl, const KeyEvent&, bool); + DECL_DLLPRIVATE_LINK(FocusInHdl, weld::Widget&, void); + DECL_DLLPRIVATE_LINK(FocusOutHdl, weld::Widget&, void); + DECL_DLLPRIVATE_LINK(MousePressHdl, const MouseEvent&, bool); + DECL_DLLPRIVATE_LINK(MouseReleaseHdl, const MouseEvent&, bool); + DECL_DLLPRIVATE_LINK(MouseMoveHdl, const MouseEvent&, bool); - virtual void ReplaceSelected( const OUString& _rStr ) = 0; - virtual OUString GetSelected( LineEnd aSeparator ) const = 0; +private: + Link m_aFocusInHdl; + Link m_aFocusOutHdl; + Link m_aMousePressHdl; + Link m_aMouseReleaseHdl; + Link m_aMouseMoveHdl; + Link m_aKeyInputHdl; + Link m_aKeyReleaseHdl; +}; - virtual bool IsValueChangedFromSaved() const = 0; - virtual void SaveValue() = 0; +class SVT_DLLPUBLIC EditControlBase : public ControlBase +{ +public: + EditControlBase(BrowserDataWin* pParent); - virtual bool CanUp() const = 0; - virtual bool CanDown() const = 0; - - virtual void Cut() = 0; - virtual void Copy() = 0; - virtual void Paste() = 0; - - // sets a link to call when the text is changed by the user - void SetModifyHdl(const Link& rLink) - { - m_aModify1Hdl = rLink; - } - - // sets an additional link to call when the text is changed by the user - void SetAuxModifyHdl(const Link& rLink) - { - m_aModify2Hdl = rLink; - } - - private: - Link m_aModify1Hdl; - Link m_aModify2Hdl; - - protected: - void CallModifyHdls() - { - m_aModify1Hdl.Call(nullptr); - m_aModify2Hdl.Call(nullptr); - } - }; - - class SVT_DLLPUBLIC ControlBase : public InterimItemWindow + virtual void SetEditableReadOnly(bool bReadOnly) override { - public: - ControlBase(BrowserDataWin* pParent, const OUString& rUIXMLDescription, const OUString& rID); + m_pEntry->set_editable(!bReadOnly); + } - virtual void SetEditableReadOnly(bool bReadOnly); + virtual void SetPointFont(const vcl::Font& rFont) override { m_pEntry->set_font(rFont); } - virtual bool ProcessKey(const KeyEvent& rKEvt); + virtual void dispose() override; - virtual void SetPointFont(const vcl::Font& rFont) = 0; + weld::Entry& get_widget() { return *m_pEntry; } - // chain after the FocusInHdl - void SetFocusInHdl(const Link& rHdl) - { - m_aFocusInHdl = rHdl; - } + virtual void connect_changed(const Link& rLink) = 0; + virtual void connect_focus_in(const Link& rLink) = 0; + virtual void connect_focus_out(const Link& rLink) = 0; + virtual void connect_key_press(const Link& rLink) = 0; - // chain after the FocusOutHdl - void SetFocusOutHdl(const Link& rHdl) - { - m_aFocusOutHdl = rHdl; - } +protected: + void InitEditControlBase(weld::Entry* pEntry); - void SetMousePressHdl(const Link& rHdl) - { - m_aMousePressHdl = rHdl; - } +private: + weld::Entry* m_pEntry; +}; - void SetMouseReleaseHdl(const Link& rHdl) - { - m_aMouseReleaseHdl = rHdl; - } +class SVT_DLLPUBLIC EditControl : public EditControlBase +{ +public: + EditControl(BrowserDataWin* pParent); - void SetMouseMoveHdl(const Link& rHdl) - { - m_aMouseMoveHdl = rHdl; - } + virtual void dispose() override; - void SetKeyInputHdl(const Link& rHdl) - { - m_aKeyInputHdl = rHdl; - } - - void SetKeyReleaseHdl(const Link& rHdl) - { - m_aKeyReleaseHdl = rHdl; - } - - rtl::Reference CreateAccessible() override; - - protected: - DECL_DLLPRIVATE_LINK(KeyInputHdl, const KeyEvent&, bool); - DECL_DLLPRIVATE_LINK(KeyReleaseHdl, const KeyEvent&, bool); - DECL_DLLPRIVATE_LINK(FocusInHdl, weld::Widget&, void); - DECL_DLLPRIVATE_LINK(FocusOutHdl, weld::Widget&, void); - DECL_DLLPRIVATE_LINK(MousePressHdl, const MouseEvent&, bool); - DECL_DLLPRIVATE_LINK(MouseReleaseHdl, const MouseEvent&, bool); - DECL_DLLPRIVATE_LINK(MouseMoveHdl, const MouseEvent&, bool); - private: - Link m_aFocusInHdl; - Link m_aFocusOutHdl; - Link m_aMousePressHdl; - Link m_aMouseReleaseHdl; - Link m_aMouseMoveHdl; - Link m_aKeyInputHdl; - Link m_aKeyReleaseHdl; - }; - - class SVT_DLLPUBLIC EditControlBase : public ControlBase + virtual void connect_changed(const Link& rLink) override { - public: - EditControlBase(BrowserDataWin* pParent); + m_xWidget->connect_changed(rLink); + } - virtual void SetEditableReadOnly(bool bReadOnly) override - { - m_pEntry->set_editable(!bReadOnly); - } - - virtual void SetPointFont(const vcl::Font& rFont) override - { - m_pEntry->set_font(rFont); - } - - virtual void dispose() override; - - weld::Entry& get_widget() { return *m_pEntry; } - - virtual void connect_changed(const Link& rLink) = 0; - virtual void connect_focus_in(const Link& rLink) = 0; - virtual void connect_focus_out(const Link& rLink) = 0; - virtual void connect_key_press(const Link& rLink) = 0; - - protected: - void InitEditControlBase(weld::Entry* pEntry); - - private: - weld::Entry* m_pEntry; - }; - - class SVT_DLLPUBLIC EditControl : public EditControlBase + virtual void connect_focus_in(const Link& rLink) override { - public: - EditControl(BrowserDataWin* pParent); + m_xWidget->connect_focus_in(rLink); + } - virtual void dispose() override; - - virtual void connect_changed(const Link& rLink) override - { - m_xWidget->connect_changed(rLink); - } - - virtual void connect_focus_in(const Link& rLink) override - { - m_xWidget->connect_focus_in(rLink); - } - - virtual void connect_focus_out(const Link& rLink) override - { - m_xWidget->connect_focus_out(rLink); - } - - virtual void connect_key_press(const Link& rLink) override - { - m_xWidget->connect_key_press(rLink); - } - - protected: - std::unique_ptr m_xWidget; - }; - - class SVT_DLLPUBLIC EntryImplementation final : public IEditImplementation + virtual void connect_focus_out(const Link& rLink) override { - EditControlBase& m_rEdit; - int m_nMaxTextLen; + m_xWidget->connect_focus_out(rLink); + } - DECL_LINK(ModifyHdl, weld::Entry&, void); - public: - EntryImplementation(EditControlBase& rEdit) - : m_rEdit(rEdit) - , m_nMaxTextLen(0) - { - m_rEdit.connect_changed(LINK(this, EntryImplementation, ModifyHdl)); - } + virtual void connect_key_press(const Link& rLink) override + { + m_xWidget->connect_key_press(rLink); + } - virtual ControlBase& GetControl() override - { - return m_rEdit; - } +protected: + std::unique_ptr m_xWidget; +}; - virtual OUString GetText( LineEnd /*aSeparator*/ ) const override - { - // ignore the line end - this base implementation does not support it - return m_rEdit.get_widget().get_text(); - } +class SVT_DLLPUBLIC EntryImplementation final : public IEditImplementation +{ + EditControlBase& m_rEdit; + int m_nMaxTextLen; - virtual void SetText( const OUString& _rStr ) override - { - return m_rEdit.get_widget().set_text(_rStr); - } + DECL_LINK(ModifyHdl, weld::TextWidget&, void); - virtual bool IsReadOnly() const override - { - return !m_rEdit.get_widget().get_editable(); - } +public: + EntryImplementation(EditControlBase& rEdit) + : m_rEdit(rEdit) + , m_nMaxTextLen(0) + { + m_rEdit.connect_changed(LINK(this, EntryImplementation, ModifyHdl)); + } - virtual void SetReadOnly( bool bReadOnly ) override - { - m_rEdit.SetEditableReadOnly(bReadOnly); - } + virtual ControlBase& GetControl() override { return m_rEdit; } - virtual sal_Int32 GetMaxTextLen() const override - { - return m_nMaxTextLen; - } + virtual OUString GetText(LineEnd /*aSeparator*/) const override + { + // ignore the line end - this base implementation does not support it + return m_rEdit.get_widget().get_text(); + } - virtual void SetMaxTextLen( sal_Int32 nMaxLen ) override - { - m_nMaxTextLen = nMaxLen; - m_rEdit.get_widget().set_max_length(m_nMaxTextLen); - } + virtual void SetText(const OUString& _rStr) override + { + return m_rEdit.get_widget().set_text(_rStr); + } - virtual Selection GetSelection() const override - { - int nStartPos, nEndPos; - m_rEdit.get_widget().get_selection_bounds(nStartPos, nEndPos); - return Selection(nStartPos, nEndPos); - } + virtual bool IsReadOnly() const override { return !m_rEdit.get_widget().get_editable(); } - virtual void SetSelection( const Selection& rSelection ) override - { - auto nMin = rSelection.Min(); - auto nMax = rSelection.Max(); - m_rEdit.get_widget().select_region(nMin < 0 ? 0 : nMin, nMax == SELECTION_MAX ? -1 : nMax); - } + virtual void SetReadOnly(bool bReadOnly) override { m_rEdit.SetEditableReadOnly(bReadOnly); } - virtual void ReplaceSelected( const OUString& rStr ) override - { - m_rEdit.get_widget().replace_selection(rStr); - } + virtual sal_Int32 GetMaxTextLen() const override { return m_nMaxTextLen; } - virtual OUString GetSelected( LineEnd /*aSeparator*/ ) const override - // ignore the line end - this base implementation does not support it - { - int nStartPos, nEndPos; - weld::Entry& rEntry = m_rEdit.get_widget(); - rEntry.get_selection_bounds(nStartPos, nEndPos); - return rEntry.get_text().copy(std::min(nStartPos, nEndPos), std::abs(nEndPos - nStartPos)); - } + virtual void SetMaxTextLen(sal_Int32 nMaxLen) override + { + m_nMaxTextLen = nMaxLen; + m_rEdit.get_widget().set_max_length(m_nMaxTextLen); + } - virtual bool IsValueChangedFromSaved() const override - { - return m_rEdit.get_widget().get_value_changed_from_saved(); - } + virtual Selection GetSelection() const override + { + int nStartPos, nEndPos; + m_rEdit.get_widget().get_selection_bounds(nStartPos, nEndPos); + return Selection(nStartPos, nEndPos); + } - virtual void SaveValue() override - { - m_rEdit.get_widget().save_value(); - } + virtual void SetSelection(const Selection& rSelection) override + { + auto nMin = rSelection.Min(); + auto nMax = rSelection.Max(); + m_rEdit.get_widget().select_region(nMin < 0 ? 0 : nMin, nMax == SELECTION_MAX ? -1 : nMax); + } - virtual bool CanUp() const override - { - return false; - } + virtual void ReplaceSelected(const OUString& rStr) override + { + m_rEdit.get_widget().replace_selection(rStr); + } - virtual bool CanDown() const override - { - return false; - } + virtual OUString GetSelected(LineEnd /*aSeparator*/) const override + // ignore the line end - this base implementation does not support it + { + int nStartPos, nEndPos; + weld::Entry& rEntry = m_rEdit.get_widget(); + rEntry.get_selection_bounds(nStartPos, nEndPos); + return rEntry.get_text().copy(std::min(nStartPos, nEndPos), std::abs(nEndPos - nStartPos)); + } - virtual void Cut() override - { - m_rEdit.get_widget().cut_clipboard(); - } + virtual bool IsValueChangedFromSaved() const override + { + return m_rEdit.get_widget().get_value_changed_from_saved(); + } - virtual void Copy() override - { - m_rEdit.get_widget().copy_clipboard(); - } + virtual void SaveValue() override { m_rEdit.get_widget().save_value(); } - virtual void Paste() override - { - m_rEdit.get_widget().paste_clipboard(); - } - }; + virtual bool CanUp() const override { return false; } - //= MultiLineTextCell + virtual bool CanDown() const override { return false; } - /** a multi line edit which can be used in a cell of an EditBrowseBox + virtual void Cut() override { m_rEdit.get_widget().cut_clipboard(); } + + virtual void Copy() override { m_rEdit.get_widget().copy_clipboard(); } + + virtual void Paste() override { m_rEdit.get_widget().paste_clipboard(); } +}; + +//= MultiLineTextCell + +/** a multi line edit which can be used in a cell of an EditBrowseBox */ - class SVT_DLLPUBLIC MultiLineTextCell final : public ControlBase +class SVT_DLLPUBLIC MultiLineTextCell final : public ControlBase +{ +public: + MultiLineTextCell(BrowserDataWin* pParent); + + virtual void SetEditableReadOnly(bool bReadOnly) override { - public: - MultiLineTextCell(BrowserDataWin* pParent); + m_xWidget->set_editable(!bReadOnly); + } - virtual void SetEditableReadOnly(bool bReadOnly) override - { - m_xWidget->set_editable(!bReadOnly); - } + virtual void SetPointFont(const vcl::Font& rFont) override { m_xWidget->set_font(rFont); } - virtual void SetPointFont(const vcl::Font& rFont) override - { - m_xWidget->set_font(rFont); - } + virtual void GetFocus() override; - virtual void GetFocus() override; + virtual void dispose() override; - virtual void dispose() override; + void connect_changed(const Link& rLink) + { + m_xWidget->connect_changed(rLink); + } - void connect_changed(const Link& rLink) - { - m_xWidget->connect_changed(rLink); - } + weld::TextView& get_widget() { return *m_xWidget; } - weld::TextView& get_widget() { return *m_xWidget; } +private: + std::unique_ptr m_xWidget; - private: - std::unique_ptr m_xWidget; + virtual bool ProcessKey(const KeyEvent& rKEvt) override; +}; - virtual bool ProcessKey(const KeyEvent& rKEvt) override; +class SVT_DLLPUBLIC MultiLineEditImplementation final : public IEditImplementation +{ + MultiLineTextCell& m_rEdit; + int m_nMaxTextLen; + + DECL_LINK(ModifyHdl, weld::TextWidget&, void); + +public: + MultiLineEditImplementation(MultiLineTextCell& rEdit) + : m_rEdit(rEdit) + , m_nMaxTextLen(0) + { + m_rEdit.connect_changed(LINK(this, MultiLineEditImplementation, ModifyHdl)); + } + + virtual ControlBase& GetControl() override { return m_rEdit; } + + virtual OUString GetText(LineEnd aSeparator) const override; + + virtual void SetText(const OUString& rStr) override + { + return m_rEdit.get_widget().set_text(rStr); + } + + virtual bool IsReadOnly() const override { return !m_rEdit.get_widget().get_editable(); } + + virtual void SetReadOnly(bool bReadOnly) override { m_rEdit.SetEditableReadOnly(bReadOnly); } + + virtual sal_Int32 GetMaxTextLen() const override { return m_nMaxTextLen; } + + virtual void SetMaxTextLen(sal_Int32 nMaxLen) override + { + m_nMaxTextLen = nMaxLen; + m_rEdit.get_widget().set_max_length(m_nMaxTextLen); + } + + virtual Selection GetSelection() const override + { + int nStartPos, nEndPos; + m_rEdit.get_widget().get_selection_bounds(nStartPos, nEndPos); + return Selection(nStartPos, nEndPos); + } + + virtual void SetSelection(const Selection& rSelection) override + { + auto nMin = rSelection.Min(); + auto nMax = rSelection.Max(); + m_rEdit.get_widget().select_region(nMin < 0 ? 0 : nMin, nMax == SELECTION_MAX ? -1 : nMax); + } + + virtual void ReplaceSelected(const OUString& rStr) override + { + m_rEdit.get_widget().replace_selection(rStr); + } + + virtual OUString GetSelected(LineEnd aSeparator) const override; + + virtual bool IsValueChangedFromSaved() const override + { + return m_rEdit.get_widget().get_value_changed_from_saved(); + } + + virtual void SaveValue() override { m_rEdit.get_widget().save_value(); } + + virtual bool CanUp() const override { return m_rEdit.get_widget().can_move_cursor_with_up(); } + + virtual bool CanDown() const override + { + return m_rEdit.get_widget().can_move_cursor_with_down(); + } + + virtual void Cut() override { m_rEdit.get_widget().cut_clipboard(); } + + virtual void Copy() override { m_rEdit.get_widget().copy_clipboard(); } + + virtual void Paste() override { m_rEdit.get_widget().paste_clipboard(); } +}; + +//= EditCellController +class SVT_DLLPUBLIC EditCellController : public CellController +{ + IEditImplementation* m_pEditImplementation; + bool m_bOwnImplementation; // did we create m_pEditImplementation? + +public: + EditCellController(EditControlBase* _pEdit); + EditCellController(IEditImplementation* _pImplementation); + virtual ~EditCellController() override; + + const IEditImplementation* GetEditImplementation() const { return m_pEditImplementation; } + IEditImplementation* GetEditImplementation() { return m_pEditImplementation; } + + virtual bool IsValueChangedFromSaved() const override; + virtual void SaveValue() override; + + void Modify() { ModifyHdl(nullptr); } + +protected: + virtual bool MoveAllowed(const KeyEvent& rEvt) const override; + +private: + DECL_LINK(ModifyHdl, LinkParamNone*, void); +}; + +//= CheckBoxControl +class SVT_DLLPUBLIC CheckBoxControl final : public ControlBase +{ + std::unique_ptr m_xBox; + weld::TriStateEnabled m_aModeState; + Link m_aToggleLink; + Link m_aModify1Hdl; + Link m_aModify2Hdl; + +public: + CheckBoxControl(BrowserDataWin* pParent); + virtual ~CheckBoxControl() override; + virtual void dispose() override; + + virtual void SetPointFont(const vcl::Font& rFont) override; + + void SetToggleHdl(const Link& rHdl) { m_aToggleLink = rHdl; } + + // sets a link to call when the text is changed by the user + void SetModifyHdl(const Link& rHdl) { m_aModify1Hdl = rHdl; } + + // sets an additional link to call when the text is changed by the user + void SetAuxModifyHdl(const Link& rLink) { m_aModify2Hdl = rLink; } + + void SetState(TriState eState); + TriState GetState() const { return m_xBox->get_state(); } + + void EnableTriState(bool bTriState); + + weld::CheckButton& GetBox() { return *m_xBox; }; + + // for pseudo-click when initially clicking in a cell activates + // the cell and performs a state change on the button as if + // it was clicked on + void Clicked(); + +private: + DECL_DLLPRIVATE_LINK(OnToggle, weld::Toggleable&, void); + + void CallModifyHdls() + { + m_aModify1Hdl.Call(nullptr); + m_aModify2Hdl.Call(nullptr); + } +}; + +//= CheckBoxCellController +class SVT_DLLPUBLIC CheckBoxCellController final : public CellController +{ +public: + CheckBoxCellController(CheckBoxControl* pWin); + weld::CheckButton& GetCheckBox() const; + + virtual bool IsValueChangedFromSaved() const override; + virtual void SaveValue() override; + +private: + virtual void ActivatingMouseEvent(const BrowserMouseEvent& rEvt, bool bUp) override; + DECL_DLLPRIVATE_LINK(ModifyHdl, LinkParamNone*, void); +}; + +//= ComboBoxControl +class SVT_DLLPUBLIC ComboBoxControl final : public ControlBase +{ +private: + std::unique_ptr m_xWidget; + Link m_aModify1Hdl; + Link m_aModify2Hdl; + + friend class ComboBoxCellController; + +public: + ComboBoxControl(BrowserDataWin* pParent); + + virtual void SetPointFont(const vcl::Font& rFont) override; + + virtual void SetEditableReadOnly(bool bReadOnly) override + { + m_xWidget->set_entry_editable(!bReadOnly); + } + + weld::ComboBox& get_widget() { return *m_xWidget; } + + // sets a link to call when the selection is changed by the user + void SetModifyHdl(const Link& rHdl) { m_aModify1Hdl = rHdl; } + + // sets an additional link to call when the selection is changed by the user + // bool arg is true when triggered interactively by the user + void SetAuxModifyHdl(const Link& rLink) { m_aModify2Hdl = rLink; } + + void TriggerAuxModify() { m_aModify2Hdl.Call(false); } + + virtual void dispose() override; + +private: + DECL_DLLPRIVATE_LINK(SelectHdl, weld::ComboBox&, void); + + void CallModifyHdls() + { + m_aModify1Hdl.Call(nullptr); + m_aModify2Hdl.Call(true); + } +}; + +//= ComboBoxCellController +class SVT_DLLPUBLIC ComboBoxCellController final : public CellController +{ +public: + ComboBoxCellController(ComboBoxControl* pParent); + weld::ComboBox& GetComboBox() const + { + return static_cast(GetWindow()).get_widget(); + } + + virtual bool IsValueChangedFromSaved() const override; + virtual void SaveValue() override; + +private: + virtual bool MoveAllowed(const KeyEvent& rEvt) const override; + DECL_DLLPRIVATE_LINK(ModifyHdl, LinkParamNone*, void); +}; + +//= ListBoxControl +class SVT_DLLPUBLIC ListBoxControl final : public ControlBase +{ +private: + std::unique_ptr m_xWidget; + Link m_aModify1Hdl; + Link m_aModify2Hdl; + + friend class ListBoxCellController; + +public: + ListBoxControl(BrowserDataWin* pParent); + + virtual void SetPointFont(const vcl::Font& rFont) override; + + weld::ComboBox& get_widget() { return *m_xWidget; } + + // sets a link to call when the selection is changed by the user + void SetModifyHdl(const Link& rHdl) { m_aModify1Hdl = rHdl; } + + // sets an additional link to call when the selection is changed, + // bool arg is true when triggered interactively by the user + void SetAuxModifyHdl(const Link& rLink) { m_aModify2Hdl = rLink; } + + void TriggerAuxModify() { m_aModify2Hdl.Call(false); } + + virtual void dispose() override; + +private: + DECL_DLLPRIVATE_LINK(SelectHdl, weld::ComboBox&, void); + + void CallModifyHdls() + { + m_aModify1Hdl.Call(nullptr); + m_aModify2Hdl.Call(true); + } +}; + +//= ListBoxCellController +class SVT_DLLPUBLIC ListBoxCellController : public CellController +{ +public: + ListBoxCellController(ListBoxControl* pParent); + weld::ComboBox& GetListBox() const + { + return static_cast(GetWindow()).get_widget(); + } + + virtual bool IsValueChangedFromSaved() const override; + virtual void SaveValue() override; + +protected: + virtual bool MoveAllowed(const KeyEvent& rEvt) const override; + +private: + DECL_DLLPRIVATE_LINK(ListBoxSelectHdl, LinkParamNone*, void); +}; + +class SVT_DLLPUBLIC FormattedControlBase : public EditControlBase +{ +public: + FormattedControlBase(BrowserDataWin* pParent, bool bSpinVariant); + + virtual void dispose() override; + + virtual void connect_changed(const Link& rLink) override; + virtual void connect_focus_in(const Link& rLink) override; + virtual void connect_focus_out(const Link& rLink) override; + virtual void connect_key_press(const Link& rLink) override; + + weld::EntryFormatter& get_formatter(); + +protected: + bool m_bSpinVariant; + std::unique_ptr m_xEntry; + std::unique_ptr m_xSpinButton; + std::unique_ptr m_xEntryFormatter; + + void InitFormattedControlBase(); +}; + +class SVT_DLLPUBLIC FormattedControl final : public FormattedControlBase +{ +public: + FormattedControl(BrowserDataWin* pParent, bool bSpinVariant); +}; + +class SVT_DLLPUBLIC DoubleNumericControl final : public FormattedControlBase +{ +public: + DoubleNumericControl(BrowserDataWin* pParent, bool bSpinVariant); +}; + +class SVT_DLLPUBLIC LongCurrencyControl final : public FormattedControlBase +{ +public: + LongCurrencyControl(BrowserDataWin* pParent, bool bSpinVariant); +}; + +class SVT_DLLPUBLIC TimeControl final : public FormattedControlBase +{ +public: + TimeControl(BrowserDataWin* pParent, bool bSpinVariant); +}; + +class SVT_DLLPUBLIC DateControl final : public FormattedControlBase +{ +public: + DateControl(BrowserDataWin* pParent, bool bDropDown); + + void SetDate(const Date& rDate); + + virtual void SetEditableReadOnly(bool bReadOnly) override; + + virtual void dispose() override; + +private: + std::unique_ptr m_xMenuButton; + std::unique_ptr m_xCalendarBuilder; + std::unique_ptr m_xTopLevel; + std::unique_ptr m_xCalendar; + std::unique_ptr m_xExtras; + std::unique_ptr m_xTodayBtn; + std::unique_ptr m_xNoneBtn; + + DECL_DLLPRIVATE_LINK(ToggleHdl, weld::Toggleable&, void); + DECL_DLLPRIVATE_LINK(ActivateHdl, weld::Calendar&, void); + DECL_DLLPRIVATE_LINK(ImplClickHdl, weld::Button&, void); +}; + +class SVT_DLLPUBLIC PatternControl final : public EditControlBase +{ +public: + PatternControl(BrowserDataWin* pParent); + + weld::PatternFormatter& get_formatter() { return *m_xEntryFormatter; } + + virtual void connect_changed(const Link& rLink) override; + virtual void connect_focus_in(const Link& rLink) override; + virtual void connect_focus_out(const Link& rLink) override; + virtual void connect_key_press(const Link& rLink) override; + + virtual void dispose() override; + +private: + std::unique_ptr m_xWidget; + std::unique_ptr m_xEntryFormatter; +}; + +//= FormattedFieldCellController +class SVT_DLLPUBLIC FormattedFieldCellController final : public EditCellController +{ +public: + FormattedFieldCellController(FormattedControlBase* _pFormatted); + + virtual void CommitModifications() override; +}; + +//= EditBrowserHeader +class SVT_DLLPUBLIC EditBrowserHeader : public BrowserHeader +{ +public: + EditBrowserHeader(BrowseBox* pParent, WinBits nWinBits = WB_BUTTONSTYLE) + : BrowserHeader(pParent, nWinBits) + { + } + +protected: + virtual void DoubleClick() override; +}; + +//= EditBrowseBox +class SVT_DLLPUBLIC EditBrowseBox : public BrowseBox +{ + friend class EditBrowserHeader; + + enum BrowseInfo + { + COLSELECT = 1, + ROWSELECT = 2, + ROWCHANGE = 4, + COLCHANGE = 8 }; - class SVT_DLLPUBLIC MultiLineEditImplementation final : public IEditImplementation +public: + enum class RowStatus { - MultiLineTextCell& m_rEdit; - int m_nMaxTextLen; - - DECL_LINK(ModifyHdl, weld::TextView&, void); - public: - MultiLineEditImplementation(MultiLineTextCell& rEdit) - : m_rEdit(rEdit) - , m_nMaxTextLen(0) - { - m_rEdit.connect_changed(LINK(this, MultiLineEditImplementation, ModifyHdl)); - } - - virtual ControlBase& GetControl() override - { - return m_rEdit; - } - - virtual OUString GetText(LineEnd aSeparator) const override; - - virtual void SetText(const OUString& rStr) override - { - return m_rEdit.get_widget().set_text(rStr); - } - - virtual bool IsReadOnly() const override - { - return !m_rEdit.get_widget().get_editable(); - } - - virtual void SetReadOnly( bool bReadOnly ) override - { - m_rEdit.SetEditableReadOnly(bReadOnly); - } - - virtual sal_Int32 GetMaxTextLen() const override - { - return m_nMaxTextLen; - } - - virtual void SetMaxTextLen( sal_Int32 nMaxLen ) override - { - m_nMaxTextLen = nMaxLen; - m_rEdit.get_widget().set_max_length(m_nMaxTextLen); - } - - virtual Selection GetSelection() const override - { - int nStartPos, nEndPos; - m_rEdit.get_widget().get_selection_bounds(nStartPos, nEndPos); - return Selection(nStartPos, nEndPos); - } - - virtual void SetSelection( const Selection& rSelection ) override - { - auto nMin = rSelection.Min(); - auto nMax = rSelection.Max(); - m_rEdit.get_widget().select_region(nMin < 0 ? 0 : nMin, nMax == SELECTION_MAX ? -1 : nMax); - } - - virtual void ReplaceSelected( const OUString& rStr ) override - { - m_rEdit.get_widget().replace_selection(rStr); - } - - virtual OUString GetSelected( LineEnd aSeparator ) const override; - - virtual bool IsValueChangedFromSaved() const override - { - return m_rEdit.get_widget().get_value_changed_from_saved(); - } - - virtual void SaveValue() override - { - m_rEdit.get_widget().save_value(); - } - - virtual bool CanUp() const override - { - return m_rEdit.get_widget().can_move_cursor_with_up(); - } - - virtual bool CanDown() const override - { - return m_rEdit.get_widget().can_move_cursor_with_down(); - } - - virtual void Cut() override - { - m_rEdit.get_widget().cut_clipboard(); - } - - virtual void Copy() override - { - m_rEdit.get_widget().copy_clipboard(); - } - - virtual void Paste() override - { - m_rEdit.get_widget().paste_clipboard(); - } + CLEAN, + CURRENT, + CURRENTNEW, + MODIFIED, + NEW, + DELETED, + PRIMARYKEY, + CURRENT_PRIMARYKEY, + FILTER, + HEADERFOOTER, }; +private: + EditBrowseBox(EditBrowseBox const&) = delete; + EditBrowseBox& operator=(EditBrowseBox const&) = delete; - //= EditCellController - class SVT_DLLPUBLIC EditCellController : public CellController + class SAL_DLLPRIVATE BrowserMouseEventPtr { - IEditImplementation* m_pEditImplementation; - bool m_bOwnImplementation; // did we create m_pEditImplementation? + std::unique_ptr pEvent; + bool bDown; public: - EditCellController( EditControlBase* _pEdit ); - EditCellController( IEditImplementation* _pImplementation ); - virtual ~EditCellController( ) override; - - const IEditImplementation* GetEditImplementation( ) const { return m_pEditImplementation; } - IEditImplementation* GetEditImplementation( ) { return m_pEditImplementation; } - - virtual bool IsValueChangedFromSaved() const override; - virtual void SaveValue() override; - - void Modify() + BrowserMouseEventPtr() + : bDown(false) { - ModifyHdl(nullptr); } - protected: - virtual bool MoveAllowed(const KeyEvent& rEvt) const override; - private: - DECL_LINK(ModifyHdl, LinkParamNone*, void); - }; + bool Is() const { return pEvent != nullptr; } + bool IsDown() const { return bDown; } + const BrowserMouseEvent* operator->() const { return pEvent.get(); } - //= CheckBoxControl - class SVT_DLLPUBLIC CheckBoxControl final : public ControlBase + SVT_DLLPUBLIC void Clear(); + void Set(const BrowserMouseEvent* pEvt, bool bIsDown); + } aMouseEvent; + + CellControllerRef aController, aOldController; + + ImplSVEvent *nStartEvent, *nEndEvent, *nCellModifiedEvent; // event ids + VclPtr m_pFocusWhileRequest; + // In ActivateCell, we grab the focus asynchronously, but if between requesting activation + // and the asynchronous event the focus has changed, we won't grab it for ourself. + + sal_Int32 nPaintRow; // row being painted + sal_Int32 nEditRow; + sal_uInt16 nEditCol; + + bool bHasFocus : 1; + mutable bool bPaintStatus : 1; // paint a status (image) in the handle column + bool bActiveBeforeTracking; + + VclPtr pCheckBoxPaint; + + EditBrowseBoxFlags m_nBrowserFlags; + + rtl::Reference m_pActiveCell; + + VclPtr pHeader; + +protected: + BrowserMouseEventPtr& getMouseEvent() { return aMouseEvent; } + +protected: + EditBrowserHeader* GetHeaderBar() const { return pHeader; } + + virtual VclPtr CreateHeaderBar(BrowseBox* pParent) override; + + // if you want to have an own header ... + virtual VclPtr imp_CreateHeaderBar(BrowseBox* pParent); + + virtual void ColumnMoved(sal_uInt16 nId) override; + virtual void ColumnResized(sal_uInt16 nColId) override; + virtual void Resize() override; + virtual void ArrangeControls(sal_uInt16& nX, sal_uInt16 nY); + virtual bool SeekRow(sal_Int32 nRow) override; + + virtual void GetFocus() override; + virtual void LoseFocus() override; + virtual void KeyInput(const KeyEvent& rEvt) override; + virtual void MouseButtonDown(const BrowserMouseEvent& rEvt) override; + virtual void MouseButtonUp(const BrowserMouseEvent& rEvt) override; + virtual void StateChanged(StateChangedType nType) override; + virtual void DataChanged(const DataChangedEvent& rDCEvt) override; + + using BrowseBox::MouseButtonUp; + using BrowseBox::MouseButtonDown; + + virtual bool PreNotify(NotifyEvent& rNEvt) override; + virtual bool EventNotify(NotifyEvent& rNEvt) override; + + virtual void EndScroll() override; + + // should be used instead of GetFieldRectPixel, 'cause this method here takes into account the borders + tools::Rectangle GetCellRect(sal_Int32 nRow, sal_uInt16 nColId, + bool bRelToBrowser = true) const; + virtual sal_uInt32 GetTotalCellWidth(sal_Int32 nRow, sal_uInt16 nColId); + sal_uInt32 GetAutoColumnWidth(sal_uInt16 nColId); + + virtual void PaintStatusCell(OutputDevice& rDev, const tools::Rectangle& rRect) const; + virtual void PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect, + sal_uInt16 nColId) const = 0; + + virtual RowStatus GetRowStatus(sal_Int32 nRow) const; + + virtual void RowHeightChanged() override; + + // callbacks for the data window + virtual void ImplStartTracking() override; + virtual void ImplEndTracking() override; + + // when changing a row: + // CursorMoving: cursor is being moved, but GetCurRow() still provides the old row + virtual bool CursorMoving(sal_Int32 nNewRow, sal_uInt16 nNewCol); + + // cursor has been moved + virtual void CursorMoved() override; + + virtual void CellModified(); // called whenever a cell has been modified + virtual bool + SaveModified(); // called whenever a cell should be left, and its content should be saved + // return sal_False prevents leaving the cell + virtual bool SaveRow(); // commit the current row + + virtual bool IsModified() const { - std::unique_ptr m_xBox; - weld::TriStateEnabled m_aModeState; - Link m_aToggleLink; - Link m_aModify1Hdl; - Link m_aModify2Hdl; + return aController.is() && aController->IsValueChangedFromSaved(); + } - public: - CheckBoxControl(BrowserDataWin* pParent); - virtual ~CheckBoxControl() override; - virtual void dispose() override; + virtual CellController* GetController(sal_Int32 nRow, sal_uInt16 nCol); + virtual void InitController(CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol); + static void ResizeController(CellControllerRef const& rController, const tools::Rectangle&); + virtual void DoubleClick(const BrowserMouseEvent&) override; - virtual void SetPointFont(const vcl::Font& rFont) override; + void ActivateCell() { ActivateCell(GetCurRow(), GetCurColumnId()); } - void SetToggleHdl(const Link& rHdl) {m_aToggleLink = rHdl;} + // retrieve the image for the row status + Image GetImage(RowStatus) const; - // sets a link to call when the text is changed by the user - void SetModifyHdl(const Link& rHdl) - { - m_aModify1Hdl = rHdl; - } + // inserting columns + // if you don't set a width, this will be calculated automatically + // if the id isn't set the smallest unused will do it ... + virtual sal_uInt16 AppendColumn(const OUString& rName, sal_uInt16 nWidth, + sal_uInt16 nPos = HEADERBAR_APPEND, + sal_uInt16 nId = sal_uInt16(-1)); - // sets an additional link to call when the text is changed by the user - void SetAuxModifyHdl(const Link& rLink) - { - m_aModify2Hdl = rLink; - } + // called whenever (Shift)Tab or Enter is pressed. If true is returned, these keys + // result in traveling to the next or to th previous cell + virtual bool IsTabAllowed(bool bForward) const; - void SetState(TriState eState); - TriState GetState() const { return m_xBox->get_state(); } + virtual bool IsCursorMoveAllowed(sal_Int32 nNewRow, sal_uInt16 nNewColId) const override; - void EnableTriState(bool bTriState); + void PaintTristate(const tools::Rectangle& rRect, const TriState& eState, + bool _bEnabled = true) const; - weld::CheckButton& GetBox() {return *m_xBox;}; + void AsynchGetFocus(); + // secure starting of StartEditHdl - // for pseudo-click when initially clicking in a cell activates - // the cell and performs a state change on the button as if - // it was clicked on - void Clicked(); +public: + EditBrowseBox(vcl::Window* pParent, EditBrowseBoxFlags nBrowserFlags, WinBits nBits, + BrowserMode nMode = BrowserMode::NONE); + virtual ~EditBrowseBox() override; + virtual void dispose() override; - private: - DECL_DLLPRIVATE_LINK(OnToggle, weld::Toggleable&, void); + bool IsEditing() const { return aController.is(); } + void InvalidateStatusCell(sal_Int32 nRow) { RowModified(nRow, 0); } + void InvalidateHandleColumn(); - void CallModifyHdls() - { - m_aModify1Hdl.Call(nullptr); - m_aModify2Hdl.Call(nullptr); - } - }; + // late construction + virtual void Init(); + virtual void RemoveRows(); + virtual void Dispatch(BrowserDispatchId eId); - //= CheckBoxCellController - class SVT_DLLPUBLIC CheckBoxCellController final : public CellController - { - public: + const CellControllerRef& Controller() const { return aController; } + EditBrowseBoxFlags GetBrowserFlags() const { return m_nBrowserFlags; } + void SetBrowserFlags(EditBrowseBoxFlags nFlags); - CheckBoxCellController(CheckBoxControl* pWin); - weld::CheckButton& GetCheckBox() const; + virtual void ActivateCell(sal_Int32 nRow, sal_uInt16 nCol, bool bSetCellFocus = true); + virtual void DeactivateCell(bool bUpdate = true); + // Children --------------------------------------------------------------- - virtual bool IsValueChangedFromSaved() const override; - virtual void SaveValue() override; + /** @return The count of additional controls of the control area. */ + virtual sal_Int32 GetAccessibleControlCount() const override; - private: - virtual void ActivatingMouseEvent(const BrowserMouseEvent& rEvt, bool bUp) override; - DECL_DLLPRIVATE_LINK(ModifyHdl, LinkParamNone*, void); - }; - - //= ComboBoxControl - class SVT_DLLPUBLIC ComboBoxControl final : public ControlBase - { - private: - std::unique_ptr m_xWidget; - Link m_aModify1Hdl; - Link m_aModify2Hdl; - - friend class ComboBoxCellController; - - public: - ComboBoxControl(BrowserDataWin* pParent); - - virtual void SetPointFont(const vcl::Font& rFont) override; - - virtual void SetEditableReadOnly(bool bReadOnly) override - { - m_xWidget->set_entry_editable(!bReadOnly); - } - - weld::ComboBox& get_widget() { return *m_xWidget; } - - // sets a link to call when the selection is changed by the user - void SetModifyHdl(const Link& rHdl) - { - m_aModify1Hdl = rHdl; - } - - // sets an additional link to call when the selection is changed by the user - // bool arg is true when triggered interactively by the user - void SetAuxModifyHdl(const Link& rLink) - { - m_aModify2Hdl = rLink; - } - - void TriggerAuxModify() - { - m_aModify2Hdl.Call(false); - } - - virtual void dispose() override; - - private: - DECL_DLLPRIVATE_LINK(SelectHdl, weld::ComboBox&, void); - - void CallModifyHdls() - { - m_aModify1Hdl.Call(nullptr); - m_aModify2Hdl.Call(true); - } - }; - - //= ComboBoxCellController - class SVT_DLLPUBLIC ComboBoxCellController final : public CellController - { - public: - - ComboBoxCellController(ComboBoxControl* pParent); - weld::ComboBox& GetComboBox() const { return static_cast(GetWindow()).get_widget(); } - - virtual bool IsValueChangedFromSaved() const override; - virtual void SaveValue() override; - - private: - virtual bool MoveAllowed(const KeyEvent& rEvt) const override; - DECL_DLLPRIVATE_LINK(ModifyHdl, LinkParamNone*, void); - }; - - //= ListBoxControl - class SVT_DLLPUBLIC ListBoxControl final : public ControlBase - { - private: - std::unique_ptr m_xWidget; - Link m_aModify1Hdl; - Link m_aModify2Hdl; - - friend class ListBoxCellController; - - public: - ListBoxControl(BrowserDataWin* pParent); - - virtual void SetPointFont(const vcl::Font& rFont) override; - - weld::ComboBox& get_widget() { return *m_xWidget; } - - // sets a link to call when the selection is changed by the user - void SetModifyHdl(const Link& rHdl) - { - m_aModify1Hdl = rHdl; - } - - // sets an additional link to call when the selection is changed, - // bool arg is true when triggered interactively by the user - void SetAuxModifyHdl(const Link& rLink) - { - m_aModify2Hdl = rLink; - } - - void TriggerAuxModify() - { - m_aModify2Hdl.Call(false); - } - - virtual void dispose() override; - private: - DECL_DLLPRIVATE_LINK(SelectHdl, weld::ComboBox&, void); - - void CallModifyHdls() - { - m_aModify1Hdl.Call(nullptr); - m_aModify2Hdl.Call(true); - } - }; - - //= ListBoxCellController - class SVT_DLLPUBLIC ListBoxCellController : public CellController - { - public: - - ListBoxCellController(ListBoxControl* pParent); - weld::ComboBox& GetListBox() const { return static_cast(GetWindow()).get_widget(); } - - virtual bool IsValueChangedFromSaved() const override; - virtual void SaveValue() override; - - protected: - virtual bool MoveAllowed(const KeyEvent& rEvt) const override; - private: - DECL_DLLPRIVATE_LINK(ListBoxSelectHdl, LinkParamNone*, void); - }; - - class SVT_DLLPUBLIC FormattedControlBase : public EditControlBase - { - public: - FormattedControlBase(BrowserDataWin* pParent, bool bSpinVariant); - - virtual void dispose() override; - - virtual void connect_changed(const Link& rLink) override; - virtual void connect_focus_in(const Link& rLink) override; - virtual void connect_focus_out(const Link& rLink) override; - virtual void connect_key_press(const Link& rLink) override; - - weld::EntryFormatter& get_formatter(); - - protected: - bool m_bSpinVariant; - std::unique_ptr m_xEntry; - std::unique_ptr m_xSpinButton; - std::unique_ptr m_xEntryFormatter; - - void InitFormattedControlBase(); - }; - - class SVT_DLLPUBLIC FormattedControl final : public FormattedControlBase - { - public: - FormattedControl(BrowserDataWin* pParent, bool bSpinVariant); - }; - - class SVT_DLLPUBLIC DoubleNumericControl final : public FormattedControlBase - { - public: - DoubleNumericControl(BrowserDataWin* pParent, bool bSpinVariant); - }; - - class SVT_DLLPUBLIC LongCurrencyControl final : public FormattedControlBase - { - public: - LongCurrencyControl(BrowserDataWin* pParent, bool bSpinVariant); - }; - - class SVT_DLLPUBLIC TimeControl final : public FormattedControlBase - { - public: - TimeControl(BrowserDataWin* pParent, bool bSpinVariant); - }; - - class SVT_DLLPUBLIC DateControl final : public FormattedControlBase - { - public: - DateControl(BrowserDataWin* pParent, bool bDropDown); - - void SetDate(const Date& rDate); - - virtual void SetEditableReadOnly(bool bReadOnly) override; - - virtual void dispose() override; - private: - std::unique_ptr m_xMenuButton; - std::unique_ptr m_xCalendarBuilder; - std::unique_ptr m_xTopLevel; - std::unique_ptr m_xCalendar; - std::unique_ptr m_xExtras; - std::unique_ptr m_xTodayBtn; - std::unique_ptr m_xNoneBtn; - - DECL_DLLPRIVATE_LINK(ToggleHdl, weld::Toggleable&, void); - DECL_DLLPRIVATE_LINK(ActivateHdl, weld::Calendar&, void); - DECL_DLLPRIVATE_LINK(ImplClickHdl, weld::Button&, void); - }; - - class SVT_DLLPUBLIC PatternControl final : public EditControlBase - { - public: - PatternControl(BrowserDataWin* pParent); - - weld::PatternFormatter& get_formatter() { return *m_xEntryFormatter; } - - virtual void connect_changed(const Link& rLink) override; - virtual void connect_focus_in(const Link& rLink) override; - virtual void connect_focus_out(const Link& rLink) override; - virtual void connect_key_press(const Link& rLink) override; - - virtual void dispose() override; - private: - std::unique_ptr m_xWidget; - std::unique_ptr m_xEntryFormatter; - }; - - //= FormattedFieldCellController - class SVT_DLLPUBLIC FormattedFieldCellController final : public EditCellController - { - public: - FormattedFieldCellController( FormattedControlBase* _pFormatted ); - - virtual void CommitModifications() override; - }; - - //= EditBrowserHeader - class SVT_DLLPUBLIC EditBrowserHeader : public BrowserHeader - { - public: - EditBrowserHeader( BrowseBox* pParent, WinBits nWinBits = WB_BUTTONSTYLE ) - :BrowserHeader(pParent, nWinBits){} - - protected: - virtual void DoubleClick() override; - }; - - - //= EditBrowseBox - class SVT_DLLPUBLIC EditBrowseBox: public BrowseBox - { - friend class EditBrowserHeader; - - enum BrowseInfo - { - COLSELECT = 1, - ROWSELECT = 2, - ROWCHANGE = 4, - COLCHANGE = 8 - }; - - public: - enum RowStatus - { - CLEAN = 0, - CURRENT = 1, - CURRENTNEW = 2, - MODIFIED = 3, - NEW = 4, - DELETED = 5, - PRIMARYKEY = 6, - CURRENT_PRIMARYKEY = 7, - FILTER = 8, - HEADERFOOTER = 9 - }; - - private: - EditBrowseBox(EditBrowseBox const &) = delete; - EditBrowseBox& operator=(EditBrowseBox const &) = delete; - - class SAL_DLLPRIVATE BrowserMouseEventPtr - { - std::unique_ptr pEvent; - bool bDown; - - public: - BrowserMouseEventPtr() - : bDown(false) - { - } - - bool Is() const {return pEvent != nullptr;} - bool IsDown() const {return bDown;} - const BrowserMouseEvent* operator->() const {return pEvent.get();} - - SVT_DLLPUBLIC void Clear(); - void Set(const BrowserMouseEvent* pEvt, bool bIsDown); - } aMouseEvent; - - CellControllerRef aController, - aOldController; - - ImplSVEvent * nStartEvent, * nEndEvent, * nCellModifiedEvent; // event ids - VclPtr m_pFocusWhileRequest; - // In ActivateCell, we grab the focus asynchronously, but if between requesting activation - // and the asynchronous event the focus has changed, we won't grab it for ourself. - - sal_Int32 nPaintRow; // row being painted - sal_Int32 nEditRow; - sal_uInt16 nEditCol; - - bool bHasFocus : 1; - mutable bool bPaintStatus : 1; // paint a status (image) in the handle column - bool bActiveBeforeTracking; - - VclPtr pCheckBoxPaint; - - EditBrowseBoxFlags m_nBrowserFlags; - - rtl::Reference m_pActiveCell; - void clearActiveCell(); - - protected: - VclPtr pHeader; - - BrowserMouseEventPtr& getMouseEvent() { return aMouseEvent; } - - protected: - BrowserHeader* GetHeaderBar() const {return pHeader;} - - virtual VclPtr CreateHeaderBar(BrowseBox* pParent) override; - - // if you want to have an own header ... - virtual VclPtr imp_CreateHeaderBar(BrowseBox* pParent); - - virtual void ColumnMoved(sal_uInt16 nId) override; - virtual void ColumnResized(sal_uInt16 nColId) override; - virtual void Resize() override; - virtual void ArrangeControls(sal_uInt16& nX, sal_uInt16 nY); - virtual bool SeekRow(sal_Int32 nRow) override; - - virtual void GetFocus() override; - virtual void LoseFocus() override; - virtual void KeyInput(const KeyEvent& rEvt) override; - virtual void MouseButtonDown(const BrowserMouseEvent& rEvt) override; - virtual void MouseButtonUp(const BrowserMouseEvent& rEvt) override; - virtual void StateChanged( StateChangedType nType ) override; - virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; - - using BrowseBox::MouseButtonUp; - using BrowseBox::MouseButtonDown; - - virtual bool PreNotify(NotifyEvent& rNEvt ) override; - virtual bool EventNotify(NotifyEvent& rNEvt) override; - - virtual void EndScroll() override; - - // should be used instead of GetFieldRectPixel, 'cause this method here takes into account the borders - tools::Rectangle GetCellRect(sal_Int32 nRow, sal_uInt16 nColId, bool bRelToBrowser = true) const; - virtual sal_uInt32 GetTotalCellWidth(sal_Int32 nRow, sal_uInt16 nColId); - sal_uInt32 GetAutoColumnWidth(sal_uInt16 nColId); - - virtual void PaintStatusCell(OutputDevice& rDev, const tools::Rectangle& rRect) const; - virtual void PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColId) const = 0; - - virtual RowStatus GetRowStatus(sal_Int32 nRow) const; - - virtual void RowHeightChanged() override; - - // callbacks for the data window - virtual void ImplStartTracking() override; - virtual void ImplEndTracking() override; - - // when changing a row: - // CursorMoving: cursor is being moved, but GetCurRow() still provides the old row - virtual bool CursorMoving(sal_Int32 nNewRow, sal_uInt16 nNewCol); - - // cursor has been moved - virtual void CursorMoved() override; - - virtual void CellModified(); // called whenever a cell has been modified - virtual bool SaveModified(); // called whenever a cell should be left, and it's content should be saved - // return sal_False prevents leaving the cell - virtual bool SaveRow(); // commit the current row - - virtual bool IsModified() const {return aController.is() && aController->IsValueChangedFromSaved();} - - virtual CellController* GetController(sal_Int32 nRow, sal_uInt16 nCol); - virtual void InitController(CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol); - static void ResizeController(CellControllerRef const & rController, const tools::Rectangle&); - virtual void DoubleClick(const BrowserMouseEvent&) override; - - void ActivateCell() { ActivateCell(GetCurRow(), GetCurColumnId()); } - - // retrieve the image for the row status - Image GetImage(RowStatus) const; - - // inserting columns - // if you don't set a width, this will be calculated automatically - // if the id isn't set the smallest unused will do it ... - virtual sal_uInt16 AppendColumn(const OUString& rName, sal_uInt16 nWidth, sal_uInt16 nPos = HEADERBAR_APPEND, sal_uInt16 nId = sal_uInt16(-1)); - - // called whenever (Shift)Tab or Enter is pressed. If true is returned, these keys - // result in traveling to the next or to th previous cell - virtual bool IsTabAllowed(bool bForward) const; - - virtual bool IsCursorMoveAllowed(sal_Int32 nNewRow, sal_uInt16 nNewColId) const override; - - void PaintTristate(const tools::Rectangle& rRect, const TriState& eState, bool _bEnabled=true) const; - - void AsynchGetFocus(); - // secure starting of StartEditHdl - - public: - EditBrowseBox(vcl::Window* pParent, EditBrowseBoxFlags nBrowserFlags, WinBits nBits, BrowserMode nMode = BrowserMode::NONE ); - virtual ~EditBrowseBox() override; - virtual void dispose() override; - - bool IsEditing() const {return aController.is();} - void InvalidateStatusCell(sal_Int32 nRow) {RowModified(nRow, 0);} - void InvalidateHandleColumn(); - - // late construction - virtual void Init(); - virtual void RemoveRows(); - virtual void Dispatch(BrowserDispatchId eId); - - const CellControllerRef& Controller() const { return aController; } - EditBrowseBoxFlags GetBrowserFlags() const { return m_nBrowserFlags; } - void SetBrowserFlags(EditBrowseBoxFlags nFlags); - - virtual void ActivateCell(sal_Int32 nRow, sal_uInt16 nCol, bool bSetCellFocus = true); - virtual void DeactivateCell(bool bUpdate = true); - // Children --------------------------------------------------------------- - - /** @return The count of additional controls of the control area. */ - virtual sal_Int32 GetAccessibleControlCount() const override; - - /** Creates the accessible object of an additional control. + /** Creates the accessible object of an additional control. @param nIndex The 0-based index of the control. @return The accessible object of the specified control. */ - virtual rtl::Reference - CreateAccessibleControl(sal_Int32 nIndex) override; + virtual rtl::Reference + CreateAccessibleControl(sal_Int32 nIndex) override; - /** Sets focus to current cell of the data table. */ - virtual void GrabTableFocus() override; + /** Sets focus to current cell of the data table. */ + virtual void GrabTableFocus() override; - virtual tools::Rectangle GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex) override; - virtual sal_Int32 GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint) override; + virtual tools::Rectangle GetFieldCharacterBounds(sal_Int32 _nRow, sal_Int32 _nColumnPos, + sal_Int32 nIndex) override; + virtual sal_Int32 GetFieldIndexAtPoint(sal_Int32 _nRow, sal_Int32 _nColumnPos, + const Point& _rPoint) override; - virtual bool ProcessKey(const KeyEvent& rEvt) override; + virtual bool ProcessKey(const KeyEvent& rEvt) override; - virtual void ChildFocusIn() override; - virtual void ChildFocusOut() override; + virtual void ChildFocusIn() override; + virtual void ChildFocusOut() override; - rtl::Reference - CreateAccessibleCheckBoxCell(sal_Int32 _nRow, sal_uInt16 _nColumnPos, - const TriState& eState); - bool ControlHasFocus() const; - protected: - // creates the accessible which wraps the active cell - void implCreateActiveAccessible( ); + rtl::Reference + CreateAccessibleCheckBoxCell(sal_Int32 _nRow, sal_uInt16 _nColumnPos, const TriState& eState); + bool ControlHasFocus() const; - private: - virtual void PaintField(vcl::RenderContext& rDev, const tools::Rectangle& rRect, - sal_uInt16 nColumnId ) const override; - using Control::ImplInitSettings; - SVT_DLLPRIVATE void ImplInitSettings( bool bFont, bool bForeground, bool bBackground ); - SVT_DLLPRIVATE void DetermineFocus( const GetFocusFlags _nGetFocusFlags = GetFocusFlags::NONE); - inline void EnableAndShow() const; +protected: + // creates the accessible which wraps the active cell + void implCreateActiveAccessible(); - SVT_DLLPRIVATE void implActivateCellOnMouseEvent(const BrowserMouseEvent& _rEvt, bool _bUp); +private: + virtual void PaintField(vcl::RenderContext& rDev, const tools::Rectangle& rRect, + sal_uInt16 nColumnId) const override; + using Control::ImplInitSettings; + SVT_DLLPRIVATE void ImplInitSettings(bool bFont, bool bForeground, bool bBackground); + SVT_DLLPRIVATE void DetermineFocus(const GetFocusFlags _nGetFocusFlags = GetFocusFlags::NONE); + inline void EnableAndShow() const; - DECL_DLLPRIVATE_LINK( ModifyHdl, LinkParamNone*, void ); - DECL_DLLPRIVATE_LINK( StartEditHdl, void*, void ); - DECL_DLLPRIVATE_LINK( EndEditHdl, void*, void ); - DECL_DLLPRIVATE_LINK( CellModifiedHdl, void*, void ); - }; + SVT_DLLPRIVATE void implActivateCellOnMouseEvent(const BrowserMouseEvent& _rEvt, bool _bUp); + DECL_DLLPRIVATE_LINK(ModifyHdl, LinkParamNone*, void); + DECL_DLLPRIVATE_LINK(StartEditHdl, void*, void); + DECL_DLLPRIVATE_LINK(EndEditHdl, void*, void); + DECL_DLLPRIVATE_LINK(CellModifiedHdl, void*, void); +}; -} // namespace svt +} // namespace svt /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svtools/embedhlp.hxx b/include/svtools/embedhlp.hxx index d9e99dc199a0..830bb92a9f9f 100644 --- a/include/svtools/embedhlp.hxx +++ b/include/svtools/embedhlp.hxx @@ -29,7 +29,7 @@ class MapMode; class Size; class SvStream; -namespace com :: sun :: star :: io { class XInputStream; } +namespace com::sun::star::io { class XInputStream; } namespace comphelper { diff --git a/include/svtools/embedtransfer.hxx b/include/svtools/embedtransfer.hxx index 03e41bcf1592..709a569a5b32 100644 --- a/include/svtools/embedtransfer.hxx +++ b/include/svtools/embedtransfer.hxx @@ -24,7 +24,7 @@ #include #include -namespace com :: sun :: star :: embed { class XEmbeddedObject; } +namespace com::sun::star::embed { class XEmbeddedObject; } class SVT_DLLPUBLIC SvEmbedTransferHelper final : public TransferableHelper { diff --git a/include/svtools/extcolorcfg.hxx b/include/svtools/extcolorcfg.hxx index 1b1f4a9d0b08..760cd081acae 100644 --- a/include/svtools/extcolorcfg.hxx +++ b/include/svtools/extcolorcfg.hxx @@ -53,7 +53,6 @@ public: const OUString& getName() const { return m_sName; } const OUString& getDisplayName() const { return m_sDisplayName; } Color getColor() const { return m_nColor; } - Color getDefaultColor() const { return m_nDefaultColor; } void setColor(Color _nColor) { m_nColor = _nColor; } }; diff --git a/include/svtools/genericunodialog.hxx b/include/svtools/genericunodialog.hxx index f0794766bd1b..d61018b22849 100644 --- a/include/svtools/genericunodialog.hxx +++ b/include/svtools/genericunodialog.hxx @@ -30,8 +30,8 @@ #include #include -namespace com :: sun :: star :: awt { class XWindow; } -namespace com :: sun :: star :: uno { class XComponentContext; } +namespace com::sun::star::awt { class XWindow; } +namespace com::sun::star::uno { class XComponentContext; } namespace weld { class DialogController; } diff --git a/include/svtools/imagemgr.hxx b/include/svtools/imagemgr.hxx index 0b2425c24b8d..3e4e2225a923 100644 --- a/include/svtools/imagemgr.hxx +++ b/include/svtools/imagemgr.hxx @@ -40,6 +40,7 @@ enum class SvImageId { HTML = START + 63, JPG = START + 64, WEBP = START + 65, + JXL = START + 66, Math = START + 68, MathTemplate = START + 69, File = START + 74, diff --git a/include/svtools/imageresourceaccess.hxx b/include/svtools/imageresourceaccess.hxx index c73331609af8..e4bf9f274e5e 100644 --- a/include/svtools/imageresourceaccess.hxx +++ b/include/svtools/imageresourceaccess.hxx @@ -28,8 +28,8 @@ #include #include -namespace com :: sun :: star :: io { class XInputStream; } -namespace com :: sun :: star :: uno { class XComponentContext; } +namespace com::sun::star::io { class XInputStream; } +namespace com::sun::star::uno { class XComponentContext; } namespace com::sun::star::uno { template class Reference; } class SvStream; diff --git a/include/svtools/javacontext.hxx b/include/svtools/javacontext.hxx index 462aaddc13ef..a4f94c2d9b9f 100644 --- a/include/svtools/javacontext.hxx +++ b/include/svtools/javacontext.hxx @@ -24,7 +24,7 @@ #include -namespace com :: sun :: star :: task { class XInteractionHandler; } +namespace com::sun::star::task { class XInteractionHandler; } namespace svt { diff --git a/include/svtools/langtab.hxx b/include/svtools/langtab.hxx index 032832935a18..9cb6cd510052 100644 --- a/include/svtools/langtab.hxx +++ b/include/svtools/langtab.hxx @@ -32,7 +32,7 @@ public: /** Obtain the UI name for a LanguageType of a language/locale (string resource STR_ARR_SVT_LANGUAGE_TABLE). */ - static OUString GetLanguageString( const LanguageType eType ); + static const OUString& GetLanguageString( const LanguageType eType ); /** Obtain the LanguageType for a UI name of a language/locale (string resource STR_ARR_SVT_LANGUAGE_TABLE). */ diff --git a/include/svtools/openfiledroptargetlistener.hxx b/include/svtools/openfiledroptargetlistener.hxx index 3bfae4878359..78a8fe86dc95 100644 --- a/include/svtools/openfiledroptargetlistener.hxx +++ b/include/svtools/openfiledroptargetlistener.hxx @@ -29,7 +29,7 @@ #include -namespace com :: sun :: star :: frame { class XFrame; } +namespace com::sun::star::frame { class XFrame; } namespace com::sun::star::uno { class XComponentContext; diff --git a/include/svtools/parhtml.hxx b/include/svtools/parhtml.hxx index a5a353022720..fb28ccb3f3e0 100644 --- a/include/svtools/parhtml.hxx +++ b/include/svtools/parhtml.hxx @@ -25,7 +25,7 @@ #include #include -namespace com :: sun :: star :: uno { template class Reference; } +namespace com::sun::star::uno { template class Reference; } namespace com::sun::star { namespace document { diff --git a/include/svtools/popupmenucontrollerbase.hxx b/include/svtools/popupmenucontrollerbase.hxx index 228fd5bd4c8f..dc898bdf24b2 100644 --- a/include/svtools/popupmenucontrollerbase.hxx +++ b/include/svtools/popupmenucontrollerbase.hxx @@ -34,9 +34,9 @@ #include #include -namespace com :: sun :: star :: frame { class XFrame; } -namespace com :: sun :: star :: uno { class XComponentContext; } -namespace com :: sun :: star :: util { class XURLTransformer; } +namespace com::sun::star::frame { class XFrame; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::util { class XURLTransformer; } class VCLXPopupMenu; namespace svt diff --git a/include/svtools/popupwindowcontroller.hxx b/include/svtools/popupwindowcontroller.hxx index 4f1b84f67d69..440cc105b126 100644 --- a/include/svtools/popupwindowcontroller.hxx +++ b/include/svtools/popupwindowcontroller.hxx @@ -68,8 +68,9 @@ public: virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override = 0; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using PopupWindowController_Base::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // XStatusListener virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& Event) override; diff --git a/include/svtools/prnsetup.hxx b/include/svtools/prnsetup.hxx index ffae83c63af7..656f8bd07f57 100644 --- a/include/svtools/prnsetup.hxx +++ b/include/svtools/prnsetup.hxx @@ -21,8 +21,10 @@ #include #include +#include #include #include +#include #include class QueueInfo; diff --git a/include/svtools/querydelete.hxx b/include/svtools/querydelete.hxx index 8e6522e9b1e6..87289fa011d4 100644 --- a/include/svtools/querydelete.hxx +++ b/include/svtools/querydelete.hxx @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include namespace svtools diff --git a/cui/source/inc/querydialog.hxx b/include/svtools/querydialog.hxx similarity index 68% rename from cui/source/inc/querydialog.hxx rename to include/svtools/querydialog.hxx index 2d607eaf06f8..3a7d6021b04a 100644 --- a/cui/source/inc/querydialog.hxx +++ b/include/svtools/querydialog.hxx @@ -18,10 +18,15 @@ */ #pragma once +#include +#include +#include #include -#include +#include +#include +#include -class QueryDialog final : public weld::GenericDialogController +class SVT_DLLPUBLIC QueryDialog final : public weld::GenericDialogController { private: std::unique_ptr m_pTitle; @@ -31,13 +36,16 @@ private: std::unique_ptr m_pCheckBox; std::unique_ptr m_pYes; std::unique_ptr m_pNo; + std::unique_ptr m_pYesLarge; + std::unique_ptr m_pNoLarge; public: QueryDialog(weld::Window* pParent, const OUString& sTitle, const OUString& sText, - const OUString& sQuestion, bool bShowAgain = true); - bool ShowAgain() const { return m_pCheckBox->get_active(); } - void SetYesLabel(const OUString& sLabel) { m_pYes->set_label(sLabel); } - void SetNoLabel(const OUString& sLabel) { m_pNo->set_label(sLabel); } + const OUString& sQuestion, bool bHideShowAgain = false); + bool DontShowAgain() const { return m_pCheckBox->get_active(); } + void SetYesLabel(const OUString& rLabel); + void SetNoLabel(const OUString& rLabel); // empty to hide the button + void SetTypeWarn(); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svtools/restartdialog.hxx b/include/svtools/restartdialog.hxx index c56b23e25723..90563804bda6 100644 --- a/include/svtools/restartdialog.hxx +++ b/include/svtools/restartdialog.hxx @@ -13,7 +13,7 @@ #include -namespace com :: sun :: star :: uno { template class Reference; } +namespace com::sun::star::uno { template class Reference; } namespace weld { class Window; } namespace com::sun::star::uno { @@ -59,6 +59,9 @@ enum RestartReason { // For the Calculation settings changes to take effect, // %PRODUCTNAME must be restarted: RESTART_REASON_CALCULATION, + // For the High Contrast setting change to take effect, + // %PRODUCTNAME must be restarted: + RESTART_REASON_HIGH_CONTRAST, // No particular reason: RESTART_REASON_NONE }; diff --git a/include/svtools/scriptedtext.hxx b/include/svtools/scriptedtext.hxx index 553cd9ba62e7..93e99e6781fc 100644 --- a/include/svtools/scriptedtext.hxx +++ b/include/svtools/scriptedtext.hxx @@ -24,8 +24,8 @@ #include -namespace com :: sun :: star :: i18n { class XBreakIterator; } -namespace com :: sun :: star :: uno { template class Reference; } +namespace com::sun::star::i18n { class XBreakIterator; } +namespace com::sun::star::uno { template class Reference; } class OutputDevice; namespace vcl { class Font; } diff --git a/include/svtools/scrolladaptor.hxx b/include/svtools/scrolladaptor.hxx index ee3e906a24ae..26bff7cb0c2c 100644 --- a/include/svtools/scrolladaptor.hxx +++ b/include/svtools/scrolladaptor.hxx @@ -57,9 +57,6 @@ public: void SetScrollHdl(const Link& rLink); void SetMouseReleaseHdl(const Link& rLink); - // what is it - bool IsHoriScroll() const { return m_bHori; } - ScrollType GetScrollType() const; virtual void EnableRTL(bool bEnable = true) override; diff --git a/include/svtools/statusbarcontroller.hxx b/include/svtools/statusbarcontroller.hxx index 65ad766a34ed..5b9efc105467 100644 --- a/include/svtools/statusbarcontroller.hxx +++ b/include/svtools/statusbarcontroller.hxx @@ -26,13 +26,13 @@ #include #include -namespace com :: sun :: star :: awt { class XWindow; } -namespace com :: sun :: star :: beans { struct PropertyValue; } -namespace com :: sun :: star :: frame { class XDispatch; } -namespace com :: sun :: star :: frame { class XFrame; } -namespace com :: sun :: star :: ui { class XStatusbarItem; } -namespace com :: sun :: star :: uno { class XComponentContext; } -namespace com :: sun :: star :: util { class XURLTransformer; } +namespace com::sun::star::awt { class XWindow; } +namespace com::sun::star::beans { struct PropertyValue; } +namespace com::sun::star::frame { class XDispatch; } +namespace com::sun::star::frame { class XFrame; } +namespace com::sun::star::ui { class XStatusbarItem; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::util { class XURLTransformer; } namespace tools { class Rectangle; } namespace svt diff --git a/include/svtools/strings.hrc b/include/svtools/strings.hrc index 2cfa054b8345..0e0c8b9eaf27 100644 --- a/include/svtools/strings.hrc +++ b/include/svtools/strings.hrc @@ -235,7 +235,7 @@ #define STR_SVT_PRNDLG_JOBCOUNT NC_("STR_SVT_PRNDLG_JOBCOUNT", "%d documents") #define STR_NO_FIELD_SELECTION NC_("STR_NO_FIELD_SELECTION", "") -#define STR_FIELD_COMPANY NC_("STR_FIELD_COMPANY", "Company") +#define STR_FIELD_COMPANY NC_("STR_FIELD_COMPANY", "Organization") #define STR_FIELD_DEPARTMENT NC_("STR_FIELD_DEPARTMENT", "Department") #define STR_FIELD_FIRSTNAME NC_("STR_FIELD_FIRSTNAME", "First name") #define STR_FIELD_LASTNAME NC_("STR_FIELD_LASTNAME", "Last name") diff --git a/include/svtools/tabbar.hxx b/include/svtools/tabbar.hxx index 93880c820298..8d220b3aecc2 100644 --- a/include/svtools/tabbar.hxx +++ b/include/svtools/tabbar.hxx @@ -216,7 +216,7 @@ IsEditModeCanceled - This method can be used in the EndRenaming() GetEditPageId - With this method, the tab that is being/has been renamed is queried in the Renaming handlers. -StartRenaming() - This handler is called when the EditMode hast been +StartRenaming() - This handler is called when the EditMode has been started using StartEditMode(). GetEditPageId() can be used to query which Tab should be renamed. false should be returned if the EditMod should diff --git a/include/svtools/toolbarmenu.hxx b/include/svtools/toolbarmenu.hxx index 4280eb4eda4a..d263e7c7e541 100644 --- a/include/svtools/toolbarmenu.hxx +++ b/include/svtools/toolbarmenu.hxx @@ -26,8 +26,8 @@ #include #include -namespace com :: sun :: star :: frame { class XFrame; } -namespace com :: sun :: star :: frame { struct FeatureStateEvent; } +namespace com::sun::star::frame { class XFrame; } +namespace com::sun::star::frame { struct FeatureStateEvent; } namespace svt { class FrameStatusListener; } namespace weld { class Builder; } namespace weld { class Container; } diff --git a/include/svtools/toolboxcontroller.hxx b/include/svtools/toolboxcontroller.hxx index 63b89eb3a5b6..5454406c6875 100644 --- a/include/svtools/toolboxcontroller.hxx +++ b/include/svtools/toolboxcontroller.hxx @@ -26,23 +26,19 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include #include #include #include #include -namespace com :: sun :: star :: frame { class XDispatch; } -namespace com :: sun :: star :: frame { class XFrame; } -namespace com :: sun :: star :: frame { class XLayoutManager; } -namespace com :: sun :: star :: uno { class XComponentContext; } -namespace com :: sun :: star :: util { class XURLTransformer; } +namespace com::sun::star::frame { class XDispatch; } +namespace com::sun::star::frame { class XFrame; } +namespace com::sun::star::frame { class XLayoutManager; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::util { class XURLTransformer; } namespace weld { class Builder; } namespace weld { class Toolbar; } @@ -51,18 +47,23 @@ class ToolBox; namespace svt { + class ToolboxController; +} -typedef cppu::WeakImplHelper< +// extern template otherwise the ref-counting magic here ends up duplicated across multiple libraries +extern template class SAL_DLLPUBLIC_TEMPLATE comphelper::OPropertyArrayUsageHelper; + +namespace svt +{ + +typedef comphelper::WeakComponentImplHelper< css::frame::XStatusListener, css::frame::XToolbarController, - css::lang::XInitialization, css::util::XUpdatable, - css::lang::XComponent > + css::lang::XInitialization, css::util::XUpdatable > ToolboxController_Base; class SVT_DLLPUBLIC ToolboxController : - public ToolboxController_Base, - public ::comphelper::OMutexAndBroadcastHelper, - public ::comphelper::OPropertyContainer, - public ::comphelper::OPropertyArrayUsageHelper< ToolboxController > + public ::comphelper::OPropertyContainerImplHelper< + ToolboxController_Base, ToolboxController > { private: bool m_bSupportVisible; @@ -80,25 +81,13 @@ class SVT_DLLPUBLIC ToolboxController : void updateStatus( const OUString& rCommandURL ); void updateStatus(); - // XInterface - virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& rType ) override; - virtual void SAL_CALL acquire() noexcept override; - virtual void SAL_CALL release() noexcept override; - virtual css::uno::Sequence SAL_CALL getTypes() override; - // XInitialization virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) override; // XUpdatable virtual void SAL_CALL update() override; - // XComponent - virtual void SAL_CALL dispose() override; - virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override; - virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& rListener ) override; - // XEventListener - using cppu::OPropertySetHelper::disposing; virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override; // XStatusListener @@ -110,12 +99,6 @@ class SVT_DLLPUBLIC ToolboxController : virtual void SAL_CALL doubleClick() override; virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createPopupWindow() override; virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override; - // OPropertySetHelper - virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue ) override; - virtual sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any& rConvertedValue, css::uno::Any& rOldValue, sal_Int32 nHandle, const css::uno::Any& rValue) override; - // XPropertySet - virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override; - virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; // OPropertyArrayUsageHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; @@ -130,6 +113,9 @@ class SVT_DLLPUBLIC ToolboxController : bool IsInSidebar() const { return m_bSidebar; } protected: + // weak component / custom disposal + virtual void disposing(std::unique_lock& rGuard) override; + bool getToolboxId( ToolBoxItemId& rItemId, ToolBox** ppToolBox ); struct Listener { @@ -172,14 +158,12 @@ class SVT_DLLPUBLIC ToolboxController : const css::uno::Reference< css::awt::XWindow >& getParent() const { return m_xParentWindow;} bool m_bInitialized, - m_bDisposed, m_bSidebar; ToolBoxItemId m_nToolBoxId; css::uno::Reference< css::frame::XFrame > m_xFrame; css::uno::Reference< css::uno::XComponentContext > m_xContext; OUString m_aCommandURL; URLToDispatchMap m_aListenerMap; - comphelper::OMultiTypeInterfaceContainerHelper2 m_aListenerContainer; /// container for ALL Listener css::uno::Reference< css::awt::XWindow > m_xParentWindow; css::uno::Reference< css::util::XURLTransformer > m_xUrlTransformer; diff --git a/include/svtools/unoevent.hxx b/include/svtools/unoevent.hxx index 825280e16b8a..5937aa743acf 100644 --- a/include/svtools/unoevent.hxx +++ b/include/svtools/unoevent.hxx @@ -25,7 +25,7 @@ #include #include -namespace com :: sun :: star :: uno { class XInterface; } +namespace com::sun::star::uno { class XInterface; } class SvxMacroTableDtor; class SvxMacroItem; diff --git a/include/svtools/unoimap.hxx b/include/svtools/unoimap.hxx index 64816db4be91..026c78c019b4 100644 --- a/include/svtools/unoimap.hxx +++ b/include/svtools/unoimap.hxx @@ -21,7 +21,7 @@ #include -namespace com :: sun :: star :: uno { class XInterface; } +namespace com::sun::star::uno { class XInterface; } namespace com::sun::star::uno { template class Reference; } class ImageMap; diff --git a/include/svtools/valueset.hxx b/include/svtools/valueset.hxx index 8e69b8ed8ae1..9081fab3ae6a 100644 --- a/include/svtools/valueset.hxx +++ b/include/svtools/valueset.hxx @@ -76,12 +76,6 @@ WB_DOUBLEBORDER Items will be bordered twice. Additionally WB_ITEMBORDER recognizable. WB_NAMEFIELD There is a namefield, where the name of an item will be shown. -WB_NONEFIELD There is a NoSelection field which can be selected if - 0 is passed along with SelectItem. Respectively - GetSelectedItemId() returns 0 if this field or nothing - is selected. This field shows the text which is specified - by SetText() respectively no one, if no text was set. With - SetNoSelection() the selection can be disabled. WB_VSCROLL A scrollbar will be always shown. The visible number of lines have to be specified with SetLineCount() if this flag is set. @@ -171,7 +165,6 @@ to be set (before Show) with SetStyle(). #define WB_ITEMBORDER (WinBits(0x00010000)) #define WB_DOUBLEBORDER (WinBits(0x00020000)) #define WB_NAMEFIELD (WinBits(0x00040000)) -#define WB_NONEFIELD (WinBits(0x00080000)) #define WB_FLATVALUESET (WinBits(0x02000000)) #define WB_NO_DIRECTSELECT (WinBits(0x04000000)) #define WB_MENUSTYLEVALUESET (WinBits(0x08000000)) @@ -185,9 +178,7 @@ private: ScopedVclPtr maVirDev; rtl::Reference mxAccessible; std::vector> mItemList; - std::unique_ptr mpNoneItem; std::unique_ptr mxScrolledWindow; - tools::Rectangle maNoneItemRect; tools::Rectangle maItemListRect; tools::Long mnItemWidth; tools::Long mnItemHeight; @@ -225,7 +216,8 @@ private: friend class ValueSetAcc; SVT_DLLPRIVATE void ImplDeleteItems(); - SVT_DLLPRIVATE void ImplFormatItem(vcl::RenderContext const & rRenderContext, ValueSetItem* pItem, tools::Rectangle aRect); + SVT_DLLPRIVATE void ImplFormatItem(vcl::RenderContext const& rRenderContext, + ValueSetItem& rItem, tools::Rectangle aRect); SVT_DLLPRIVATE void ImplDrawItemText(vcl::RenderContext& rRenderContext, const OUString& rStr); // nItemId is the item to draw selected, but if nothing is selected something else may be drawn as selected instead, the item to draw // selected is returned @@ -283,7 +275,6 @@ public: virtual void Select(); virtual void UserDraw( const UserDrawEvent& rUDEvt ); - OUString const & GetText() const { return maText; } void SetText(const OUString& rText) { maText = rText; } void SetStyle(WinBits nStyle); WinBits GetStyle() const { return mnStyle; } @@ -344,7 +335,6 @@ public: { return mbNoSelection; } - sal_uInt16 GetHighlightedItemId() const { return mnHighItemId; } void SetItemImage( sal_uInt16 nItemId, const Image& rImage ); Image GetItemImage( sal_uInt16 nItemId ) const; diff --git a/include/unotools/viewoptions.hxx b/include/svtools/viewoptions.hxx similarity index 96% rename from include/unotools/viewoptions.hxx rename to include/svtools/viewoptions.hxx index 68865730b118..9b22a4e27d76 100644 --- a/include/unotools/viewoptions.hxx +++ b/include/svtools/viewoptions.hxx @@ -16,13 +16,13 @@ * 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_UNOTOOLS_VIEWOPTIONS_HXX -#define INCLUDED_UNOTOOLS_VIEWOPTIONS_HXX +#pragma once -#include #include #include #include +#include +#include namespace com::sun::star::beans { struct NamedValue; } namespace com::sun::star::container { class XNameAccess; } @@ -92,7 +92,7 @@ enum class EViewType @devstatus ready to use *//*-*************************************************************************************************************/ -class SAL_WARN_UNUSED UNOTOOLS_DLLPUBLIC SvtViewOptions final +class SAL_WARN_UNUSED SVT_DLLPUBLIC SvtViewOptions final { // public methods @@ -144,14 +144,12 @@ class SAL_WARN_UNUSED UNOTOOLS_DLLPUBLIC SvtViewOptions final /*-**************************************************************************************************** @short use it to set/get the window state of your view @descr These value describe position/size and some other states of a window. - Use it with right vcl methods directly. Normally it's not necessary to - parse given string! @seealso vcl methods *//*-*****************************************************************************************************/ - OUString GetWindowState( ) const; - void SetWindowState( const OUString& sState ); + vcl::WindowData GetWindowState() const; + void SetWindowState(const vcl::WindowData& rState); /*-**************************************************************************************************** @short use it to set/get the page number which was the last active one @@ -219,6 +217,4 @@ class SAL_WARN_UNUSED UNOTOOLS_DLLPUBLIC SvtViewOptions final css::uno::Reference< css::container::XNameAccess > m_xSet; }; // class SvtViewOptions -#endif // INCLUDED_UNOTOOLS_VIEWOPTIONS_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/AccessibleControlShape.hxx b/include/svx/AccessibleControlShape.hxx index 38333ca4218a..76ca52e26db7 100644 --- a/include/svx/AccessibleControlShape.hxx +++ b/include/svx/AccessibleControlShape.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SVX_ACCESSIBLECONTROLSHAPE_HXX -#define INCLUDED_SVX_ACCESSIBLECONTROLSHAPE_HXX +#pragma once #include #include @@ -195,6 +194,4 @@ private: } // end of namespace accessibility -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/AccessibleGraphicShape.hxx b/include/svx/AccessibleGraphicShape.hxx index 789149d0d1a9..1be1b95a13c5 100644 --- a/include/svx/AccessibleGraphicShape.hxx +++ b/include/svx/AccessibleGraphicShape.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SVX_ACCESSIBLEGRAPHICSHAPE_HXX -#define INCLUDED_SVX_ACCESSIBLEGRAPHICSHAPE_HXX +#pragma once #include #include @@ -70,6 +69,4 @@ private: } // end of namespace accessibility -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/AccessibleOLEShape.hxx b/include/svx/AccessibleOLEShape.hxx index b594666d3354..7c08dbb6e596 100644 --- a/include/svx/AccessibleOLEShape.hxx +++ b/include/svx/AccessibleOLEShape.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SVX_ACCESSIBLEOLESHAPE_HXX -#define INCLUDED_SVX_ACCESSIBLEOLESHAPE_HXX +#pragma once #include #include @@ -74,6 +73,4 @@ private: } // end of namespace accessibility -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/AccessibleShape.hxx b/include/svx/AccessibleShape.hxx index dea2791af431..7f29652854aa 100644 --- a/include/svx/AccessibleShape.hxx +++ b/include/svx/AccessibleShape.hxx @@ -17,9 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ - -#ifndef INCLUDED_SVX_ACCESSIBLESHAPE_HXX -#define INCLUDED_SVX_ACCESSIBLESHAPE_HXX +#pragma once #include #include @@ -381,6 +379,4 @@ private: } // end of namespace accessibility -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/AccessibleShapeInfo.hxx b/include/svx/AccessibleShapeInfo.hxx index 1860c5259169..867f2da7cb4e 100644 --- a/include/svx/AccessibleShapeInfo.hxx +++ b/include/svx/AccessibleShapeInfo.hxx @@ -17,10 +17,11 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SVX_ACCESSIBLESHAPEINFO_HXX -#define INCLUDED_SVX_ACCESSIBLESHAPEINFO_HXX +#pragma once #include +#include +#include #include namespace com::sun::star { @@ -55,8 +56,7 @@ public: /** The accessible parent object of the shape. */ - css::uno::Reference< - css::accessibility::XAccessible> mxParent; + rtl::Reference mpParent; /** This object that may be realized by the same implementation as that of that of mxParent can be used to modify @@ -67,21 +67,15 @@ public: /** Copy the given values into the members described above. */ - AccessibleShapeInfo ( - css::uno::Reference< - css::drawing::XShape> xShape, - css::uno::Reference< - css::accessibility::XAccessible> xParent, - IAccessibleParent* pChildrenManager); + AccessibleShapeInfo(css::uno::Reference xShape, + const rtl::Reference& rpParent, + IAccessibleParent* pChildrenManager); /** Copy the given values into the members described above. The accessible parent implementation object is set to NULL. */ - AccessibleShapeInfo ( - css::uno::Reference< - css::drawing::XShape> xShape, - css::uno::Reference< - css::accessibility::XAccessible> xParent); + AccessibleShapeInfo(css::uno::Reference xShape, + const rtl::Reference& rpParent); ~AccessibleShapeInfo(); @@ -92,6 +86,4 @@ private: } // end of namespace accessibility -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/AccessibleShapeTreeInfo.hxx b/include/svx/AccessibleShapeTreeInfo.hxx index f50061ad47f4..243326eaf009 100644 --- a/include/svx/AccessibleShapeTreeInfo.hxx +++ b/include/svx/AccessibleShapeTreeInfo.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SVX_ACCESSIBLESHAPETREEINFO_HXX -#define INCLUDED_SVX_ACCESSIBLESHAPETREEINFO_HXX +#pragma once #include #include @@ -196,6 +195,4 @@ private: } // end of namespace accessibility -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/AccessibleTextHelper.hxx b/include/svx/AccessibleTextHelper.hxx index e28667b72838..ac15e6ffc643 100644 --- a/include/svx/AccessibleTextHelper.hxx +++ b/include/svx/AccessibleTextHelper.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SVX_ACCESSIBLETEXTHELPER_HXX -#define INCLUDED_SVX_ACCESSIBLETEXTHELPER_HXX +#pragma once #include #include @@ -91,14 +90,14 @@ class AccessibleTextHelper_Impl; events. Generally, be prepared that when sending any of these events via SvxEditSource::GetBroadcaster() broadcaster, the AccessibleTextHelper will call the SvxEditSource and their - forwarder to update it's state. Avoid being inconsistent in + forwarder to update its state. Avoid being inconsistent in the facts you tell in the events, e.g. when sending a SfxHintId::TextParaInserted event, the SvxEditSource::GetTextForwarder().GetParagraphCount() should already include the newly inserted paragraph. @attention All public methods must not be called with any - mutex hold, except when calling from the main thread (with + mutex held, except when calling from the main thread (which holds the solar mutex), unless stated otherwise. This is because they themselves might need the solar mutex in addition to the object mutex, and the ordering of the locking must be: @@ -377,6 +376,4 @@ private: } // end of namespace accessibility -#endif // INCLUDED_SVX_ACCESSIBLETEXTHELPER_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/ActionDescriptionProvider.hxx b/include/svx/ActionDescriptionProvider.hxx index 25f0088eaeb6..fbea347f219b 100644 --- a/include/svx/ActionDescriptionProvider.hxx +++ b/include/svx/ActionDescriptionProvider.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SVX_ACTIONDESCRIPTIONPROVIDER_HXX -#define INCLUDED_SVX_ACTIONDESCRIPTIONPROVIDER_HXX +#pragma once #include #include @@ -51,6 +50,4 @@ public: , std::u16string_view rObjectName ); }; -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/ClassificationDialog.hxx b/include/svx/ClassificationDialog.hxx index b3464972ada4..d8d470aba115 100644 --- a/include/svx/ClassificationDialog.hxx +++ b/include/svx/ClassificationDialog.hxx @@ -12,11 +12,16 @@ #define INCLUDED_SVX_CLASSIFICATIONDIALOG_HXX #include + +#include #include #include #include +#include +#include +#include #include -#include +#include #include #include #include diff --git a/include/svx/ClassificationField.hxx b/include/svx/ClassificationField.hxx index a7402bf82883..aa92d9fa0aec 100644 --- a/include/svx/ClassificationField.hxx +++ b/include/svx/ClassificationField.hxx @@ -44,12 +44,6 @@ public: { } - /// Returns the text to display, which is the Abbreviated Name, if provided, otherwise Name. - OUString const & getDisplayText() const - { - return !msAbbreviatedName.isEmpty() ? msAbbreviatedName : msName; - } - bool operator==(const ClassificationResult& rOther) const { return (meType == rOther.meType && diff --git a/include/svx/ColorIconView.hxx b/include/svx/ColorIconView.hxx new file mode 100644 index 000000000000..feb5ff1f8a21 --- /dev/null +++ b/include/svx/ColorIconView.hxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include + +class VirtualDevice; + +namespace weld +{ +class IconView; +class ItemView; +class TreeIter; +} + +class SVXCORE_DLLPUBLIC ColorIconView : public IColorSet +{ + std::unique_ptr m_pIconView; + + Link m_aColorActivatedHdl; + Link m_aSelectionChangedHdl; + + DECL_LINK(ItemActivatedHdl, const weld::TreeIter&, bool); + DECL_LINK(SelectionChangedHdl, weld::ItemView&, void); + +public: + ColorIconView(std::unique_ptr pIconView); + virtual ~ColorIconView() = default; + + virtual void insert(int nIndex, const Color& rColor, const OUString& rColorName) override; + virtual int getItemCount() const override; + + Color getColor(int nIndex) const; + OUString getColorName(int nIndex) const; + + int get_selected_index() const; + void select(int nIndex); + void unselect_all(); + + void remove(int nIndex); + virtual void clear() override; + + void grab_focus(); + + void set_sensitive(bool bSensitive); + + void set_help_id(const OUString& rName); + + void setColorActivatedHdl(const Link& rLink) + { + m_aColorActivatedHdl = rLink; + } + +private: + ScopedVclPtr createIcon(const Color& rColor); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/svx/ColorSets.hxx b/include/svx/ColorSets.hxx index 372243424956..58d40f08270a 100644 --- a/include/svx/ColorSets.hxx +++ b/include/svx/ColorSets.hxx @@ -10,12 +10,13 @@ #pragma once #include +#include #include namespace svx { -class SVXCORE_DLLPUBLIC ColorSets +class SVXCORE_DLLPUBLIC ColorSets : public SfxBroadcaster { private: std::vector maColorSets; diff --git a/include/svx/FileExportedDialog.hxx b/include/svx/FileExportedDialog.hxx index 82768f5cabef..99e851ce5b21 100644 --- a/include/svx/FileExportedDialog.hxx +++ b/include/svx/FileExportedDialog.hxx @@ -7,8 +7,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include #include -#include +#include +#include #include class SVX_DLLPUBLIC FileExportedDialog final : public weld::GenericDialogController diff --git a/include/svx/GenericCheckDialog.hxx b/include/svx/GenericCheckDialog.hxx index 42157efe2dc7..149fd3d6594f 100644 --- a/include/svx/GenericCheckDialog.hxx +++ b/include/svx/GenericCheckDialog.hxx @@ -12,9 +12,12 @@ #include #include +#include #include +#include #include -#include +#include +#include namespace svx { diff --git a/include/svx/GenericDropDownFieldDialog.hxx b/include/svx/GenericDropDownFieldDialog.hxx deleted file mode 100644 index c69b05e04265..000000000000 --- a/include/svx/GenericDropDownFieldDialog.hxx +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include -#include -#include -#include - -class SVX_DLLPUBLIC GenericDropDownFieldDialog : public weld::GenericDialogController -{ - std::unique_ptr m_xComboBox; - -public: - GenericDropDownFieldDialog(weld::Widget* pParent, const OUString& rTitle); - GenericDropDownFieldDialog(weld::Widget* pParent, const OUString& rTitle, - const std::vector& rItems); - - void InsertItem(OUString aText); - void SetActiveItem(sal_uInt32 nPos) { m_xComboBox->set_active(nPos); } - OUString GetSelectedItem() { return m_xComboBox->get_active_text(); } -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/svx/IColorSet.hxx b/include/svx/IColorSet.hxx new file mode 100644 index 000000000000..8827a4ba3d77 --- /dev/null +++ b/include/svx/IColorSet.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include +#include + +class XColorList; + +class SVXCORE_DLLPUBLIC IColorSet +{ +public: + virtual void insert(int nIndex, const Color& rColor, const OUString& rColorName) = 0; + virtual int getItemCount() const = 0; + virtual void clear() = 0; + + void addEntriesForXColorList(const XColorList& rXColorList); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/svx/Palette.hxx b/include/svx/Palette.hxx index abc57423aca0..c83cb74dc72b 100644 --- a/include/svx/Palette.hxx +++ b/include/svx/Palette.hxx @@ -21,11 +21,10 @@ #include #include +#include #include -class SvxColorValueSet; - typedef std::function ColorSelectFunction; class Palette @@ -38,7 +37,7 @@ public: virtual const OUString& GetName() = 0; virtual const OUString& GetPath() = 0; - virtual void LoadColorSet(SvxColorValueSet& rColorSet) = 0; + virtual void LoadColorSet(IColorSet& rColorSet) = 0; virtual bool IsValid() = 0; }; diff --git a/include/svx/PaletteManager.hxx b/include/svx/PaletteManager.hxx index 574dae22d679..983c68fd6b0f 100644 --- a/include/svx/PaletteManager.hxx +++ b/include/svx/PaletteManager.hxx @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -35,11 +36,6 @@ namespace tools { class JsonWriter; } class SVXCORE_DLLPUBLIC PaletteManager : public std::enable_shared_from_this { - struct ColorEntry { - OUString hexCode; - OUString name; - }; - const sal_uInt16 mnMaxRecentColors; sal_uInt16 mnNumOfPalettes; @@ -63,8 +59,8 @@ public: PaletteManager(const PaletteManager&) = delete; PaletteManager& operator=(const PaletteManager&) = delete; void LoadPalettes(); - void ReloadColorSet(SvxColorValueSet& rColorSet); - void ReloadRecentColorSet(SvxColorValueSet& rColorSet); + void ReloadColorSet(IColorSet& rColorSet); + void ReloadRecentColorSet(IColorSet& rColorSet); std::vector GetPaletteList(); void SetPalette(sal_Int32 nPos, bool bPosOnly = false); sal_Int32 GetPalette() const; @@ -72,8 +68,6 @@ public: OUString GetPaletteName(); const OUString & GetSelectedPalettePath(); - tools::Long GetColorCount() const; - tools::Long GetRecentColorCount() const; void AddRecentColor(const Color& rRecentColor, const OUString& rColorName, bool bFront = true); void SetSplitButtonColor(const NamedColor& rColor); @@ -84,14 +78,10 @@ public: bool IsThemePaletteSelected() const; - static bool GetThemeAndEffectIndex(sal_uInt16 nItemId, sal_uInt16& rThemeIndex, sal_uInt16& rEffectIndex); + static bool GetThemeAndEffectIndex(sal_uInt16 nItemIndex, sal_uInt16& rThemeIndex, sal_uInt16& rEffectIndex); bool GetLumModOff(sal_uInt16 nThemeIndex, sal_uInt16 nEffect, sal_Int16& rLumMod, sal_Int16& rLumOff); static void DispatchColorCommand(const OUString& aCommand, const NamedColor& rColor); - - /// Appends node for Document Colors into the ptree - static void generateJSON(tools::JsonWriter& aTree, const std::set& rColors); - static void generateColorNamesJSON(tools::JsonWriter& aTree); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/ParaSpacingControl.hxx b/include/svx/ParaSpacingControl.hxx index 1ed39c067762..d8dd0524956d 100644 --- a/include/svx/ParaSpacingControl.hxx +++ b/include/svx/ParaSpacingControl.hxx @@ -65,7 +65,8 @@ public: ParaLRSpacingControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx); virtual ~ParaLRSpacingControl() override; - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + virtual void disposing(std::unique_lock& rGuard) override; virtual void StateChangedAtToolBoxControl(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState) override; @@ -79,7 +80,7 @@ public: virtual void SAL_CALL acquire() noexcept override; - virtual void SAL_CALL disposing(const ::css::lang::EventObject&) override; + virtual void SAL_CALL disposing(const ::css::lang::EventObject& rEvent) override; virtual void SAL_CALL release() noexcept override; diff --git a/include/svx/SvxColorChildWindow.hxx b/include/svx/SvxColorChildWindow.hxx index e76e2fe0f9ad..0cd1a3272030 100644 --- a/include/svx/SvxColorChildWindow.hxx +++ b/include/svx/SvxColorChildWindow.hxx @@ -27,9 +27,8 @@ */ class SVX_DLLPUBLIC SvxColorChildWindow final : public SfxChildWindow { - public: - SvxColorChildWindow( vcl::Window*, sal_uInt16, SfxBindings*, - SfxChildWinInfo* ); +public: + SvxColorChildWindow(vcl::Window*, sal_uInt16, SfxBindings&, SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID(SvxColorChildWindow); }; diff --git a/include/svx/SvxNumOptionsTabPageHelper.hxx b/include/svx/SvxNumOptionsTabPageHelper.hxx index a64d879b0c15..e07546e7c3cc 100644 --- a/include/svx/SvxNumOptionsTabPageHelper.hxx +++ b/include/svx/SvxNumOptionsTabPageHelper.hxx @@ -21,7 +21,6 @@ #include #include -#include #include using namespace css::uno; diff --git a/include/svx/SvxPresetListBox.hxx b/include/svx/SvxPresetListBox.hxx deleted file mode 100644 index 4767c4f3ea14..000000000000 --- a/include/svx/SvxPresetListBox.hxx +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- 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 . - */ - -#pragma once - -#include -#include -#include - -class SVXCORE_DLLPUBLIC SvxPresetListBox : public ValueSet -{ -private: - static constexpr sal_uInt32 s_nColCount = 3; - Size m_aIconSize; - sal_uInt16 mnContextMenuItemId; - Link maRenameHdl; - Link maDeleteHdl; - - void OnMenuItemSelected(std::u16string_view rIdent); - - template< typename ListType, typename EntryType > - void FillPresetListBoxImpl(ListType& pList, sal_uInt32 nStartIndex); - -public: - SvxPresetListBox(std::unique_ptr pWindow); - - virtual void Resize() override; - virtual bool Command(const CommandEvent& rEvent) override; - virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; - Size const & GetIconSize() const { return m_aIconSize; } - sal_uInt16 GetContextMenuItemId() const { return mnContextMenuItemId; } - - void SetRenameHdl( const Link& rLink ) - { - maRenameHdl = rLink; - } - void SetDeleteHdl( const Link& rLink ) - { - maDeleteHdl = rLink; - } - - void FillPresetListBox(XGradientList& pList, sal_uInt32 nStartIndex = 1); - void FillPresetListBox(XHatchList& pList, sal_uInt32 nStartIndex = 1); - void FillPresetListBox(XBitmapList& pList, sal_uInt32 nStartIndex = 1); - void FillPresetListBox(XPatternList& pList, sal_uInt32 nStartIndex = 1); - void DrawLayout(); -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/TableAutoFmt.hxx b/include/svx/TableAutoFmt.hxx index 213e4105871f..ba7ea4efccd3 100644 --- a/include/svx/TableAutoFmt.hxx +++ b/include/svx/TableAutoFmt.hxx @@ -202,6 +202,10 @@ public: virtual size_t size() const = 0; void ResetParent(std::u16string_view rName); + /** Translate built-in table style names between programmatic name and localized UI name. */ + static OUString MapProgToUIName(std::u16string_view rProgName); + static OUString MapUIToProgName(std::u16string_view rUIName); + static const SfxItemPropertySet& GetTablePropertySet(); bool Load(bool bWriter); diff --git a/include/svx/ThemeColorsToolBoxControl.hxx b/include/svx/ThemeColorsToolBoxControl.hxx index 0a6c2fc29cab..7bad67b95567 100644 --- a/include/svx/ThemeColorsToolBoxControl.hxx +++ b/include/svx/ThemeColorsToolBoxControl.hxx @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -20,7 +21,8 @@ // Used to put theme colors pane to the notebookbar class SVX_DLLPUBLIC ThemeColorsPaneWrapper final : public InterimItemWindow, - public svx::ThemeColorsPaneBase + public svx::ThemeColorsPaneBase, + public SfxListener { private: css::uno::Reference m_xFrame; @@ -31,7 +33,8 @@ public: virtual ~ThemeColorsPaneWrapper() override; virtual void dispose() override; void SetOptimalSize(); - void refreshThemeColors(); + + void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override; DECL_LINK(SelectionChangedHdl, weld::ItemView&, void); @@ -39,8 +42,10 @@ protected: void onColorSetActivated() override; }; -class SVX_DLLPUBLIC ThemeColorsToolBoxControl final - : public cppu::ImplInheritanceHelper +using ThemeColorsToolBoxControl_Base + = cppu::ImplInheritanceHelper; + +class SVX_DLLPUBLIC ThemeColorsToolBoxControl final : public ThemeColorsToolBoxControl_Base { VclPtr m_xVclBox; @@ -52,12 +57,12 @@ public: virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& rEvent) override; // XToolbarController - virtual void SAL_CALL initialize(const css::uno::Sequence& rArguments) override; virtual css::uno::Reference SAL_CALL createItemWindow(const css::uno::Reference& rParent) override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using ThemeColorsToolBoxControl_Base::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // XUpdatable virtual void SAL_CALL update() override; diff --git a/include/svx/annotation/Annotation.hxx b/include/svx/annotation/Annotation.hxx index 0effccfc1022..a22dea30c3db 100644 --- a/include/svx/annotation/Annotation.hxx +++ b/include/svx/annotation/Annotation.hxx @@ -88,6 +88,15 @@ struct SVXCORE_DLLPUBLIC AnnotationData OUString m_Initials; css::util::DateTime m_DateTime; OUString m_Text; + + /// Threaded-comment participation. Set by filters that support + /// per-annotation reply/resolve (currently only the PDF filter). + bool m_Threaded = false; + /// Resolved / done flag. Only meaningful when m_Threaded is true. + bool m_Resolved = false; + /// GetId() of the parent annotation; 0 means "thread root". + /// Only meaningful when m_Threaded is true. + sal_uInt64 m_ParentId = 0; }; /** Annotation object, responsible for handling of the annotation. @@ -117,6 +126,11 @@ protected: CreationInfo maCreationInfo; + // Threaded-comment metadata; see AnnotationData for semantics. + bool m_Threaded = false; + bool m_Resolved = false; + sal_uInt64 m_ParentId = 0; + std::unique_ptr createUndoAnnotation(); public: @@ -165,6 +179,20 @@ public: CreationInfo const& getCreationInfo() { return maCreationInfo; } void setCreationInfo(CreationInfo const& rCreationInfo) { maCreationInfo = rCreationInfo; } + /// Returns true if this annotation participates in the threaded-comments + /// feature (currently set only by the PDF filter). + bool IsThreaded() const { return m_Threaded; } + void SetThreaded(bool bThreaded); + + /// Returns the resolved/done flag. Only meaningful if IsThreaded(). + bool IsResolved() const { return m_Resolved; } + void SetResolved(bool bResolved); + + /// GetId() of the parent annotation in the thread; 0 means "root". + /// Only meaningful if IsThreaded(). + sal_uInt64 GetParentId() const { return m_ParentId; } + void SetParentId(sal_uInt64 nParentId); + SdrObject* findAnnotationObject(); virtual rtl::Reference clone(SdrPage* pTargetPage) = 0; diff --git a/include/svx/bmpmask.hxx b/include/svx/bmpmask.hxx index 9447aac07c74..db62f5b2711f 100644 --- a/include/svx/bmpmask.hxx +++ b/include/svx/bmpmask.hxx @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -67,10 +69,8 @@ public: class SAL_WARN_UNUSED SVX_DLLPUBLIC SvxBmpMaskChildWindow final : public SfxChildWindow { - public: - SvxBmpMaskChildWindow( vcl::Window*, - sal_uInt16, SfxBindings*, - SfxChildWinInfo* ); +public: + SvxBmpMaskChildWindow(vcl::Window*, sal_uInt16, SfxBindings&, SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID(SvxBmpMaskChildWindow); }; @@ -148,8 +148,7 @@ class SAL_WARN_UNUSED SVX_DLLPUBLIC SvxBmpMask final : public SfxDockingWindow const Color& rColor ); public: - - SvxBmpMask(SfxBindings *pBindinx, SfxChildWindow *pCW, vcl::Window* pParent); + SvxBmpMask(SfxBindings& rBindings, SfxChildWindow* pCW, vcl::Window* pParent); virtual ~SvxBmpMask() override; virtual void dispose() override; diff --git a/include/svx/charmap.hxx b/include/svx/charmap.hxx index 6c0be4bce165..5f159788f8bc 100644 --- a/include/svx/charmap.hxx +++ b/include/svx/charmap.hxx @@ -36,7 +36,6 @@ #include #include #include -#include namespace com::sun::star { namespace accessibility { class XAccessible; } diff --git a/include/svx/colorbox.hxx b/include/svx/colorbox.hxx index 3bec63464404..50a6a71f12ee 100644 --- a/include/svx/colorbox.hxx +++ b/include/svx/colorbox.hxx @@ -12,7 +12,6 @@ #include #include -#include #include class ColorListBox; @@ -48,7 +47,7 @@ private: void createColorWindow(); void LockWidthRequest(int nWidthRequest); int CalcBestWidthRequest(); - ColorWindow* getColorWindow() const; + ColorWindow& getColorWindow() const; DECL_DLLPRIVATE_LINK(ToggleHdl, weld::Toggleable&, void); @@ -69,8 +68,8 @@ public: void SelectEntry(const NamedColor& rColor); void SelectEntry(const Color& rColor); - void SetNoSelection() { getColorWindow()->SetNoSelection(); } - bool IsNoSelection() const { return getColorWindow()->IsNoSelection(); } + void SetNoSelection() { getColorWindow().SetNoSelection(); } + bool IsNoSelection() const { return getColorWindow().IsNoSelection(); } void SetAutoDisplayColor(const Color& rColor) { m_aAutoDisplayColor = rColor; } @@ -96,6 +95,9 @@ public: m_xButton->connect_focus_out(rLink); } weld::MenuButton& get_widget() { return *m_xButton; } + + // move the color window content into pTarget for inline embedding + void EmbedColorWindowContent(weld::Container* pTarget); }; #endif diff --git a/include/svx/colorwindow.hxx b/include/svx/colorwindow.hxx index 87120763d911..fa3bf1cf1206 100644 --- a/include/svx/colorwindow.hxx +++ b/include/svx/colorwindow.hxx @@ -21,9 +21,10 @@ #include #include -#include +#include #include #include +#include #include typedef std::function TopLevelParentFunction; @@ -90,25 +91,25 @@ private: TopLevelParentFunction maTopLevelParentFunction; ColorSelectFunction maColorSelectFunction; - std::unique_ptr mxColorSet; - std::unique_ptr mxRecentColorSet; + ColorIconView maColorIconView; + ColorIconView maRecentColorIconView; std::unique_ptr mxPaletteListBox; std::unique_ptr mxButtonAutoColor; std::unique_ptr mxButtonNoneColor; std::unique_ptr mxButtonPicker; std::unique_ptr mxAutomaticSeparator; - std::unique_ptr mxColorSetWin; - std::unique_ptr mxRecentColorSetWin; weld::Button* mpDefaultButton; - DECL_DLLPRIVATE_LINK(SelectHdl, ValueSet*, void); + DECL_DLLPRIVATE_LINK(ColorSelectHdl, const Color&, void); + DECL_DLLPRIVATE_LINK(RecentColorSelectHdl, const Color&, void); DECL_DLLPRIVATE_LINK(SelectPaletteHdl, weld::ComboBox&, void); DECL_DLLPRIVATE_LINK(AutoColorClickHdl, weld::Button&, void); DECL_DLLPRIVATE_LINK(OpenPickerClickHdl, weld::Button&, void); - static bool SelectValueSetEntry(SvxColorValueSet* pColorSet, const Color& rColor); - static NamedColor GetSelectEntryColor(ValueSet const * pColorSet); + static bool SelectIconViewEntry(ColorIconView& rColorIconView, const Color& rColor); + static NamedColor GetSelectEntryColor(const ColorIconView& rColorIconView); NamedColor GetAutoColor() const; + void ApplySelectedColor(ColorIconView& rColorIconView); public: ColorWindow(OUString rCommand, diff --git a/include/svx/compressgraphicdialog.hxx b/include/svx/compressgraphicdialog.hxx index e2855c92e278..d8e8d0c27e24 100644 --- a/include/svx/compressgraphicdialog.hxx +++ b/include/svx/compressgraphicdialog.hxx @@ -23,10 +23,15 @@ #include #include #include +#include +#include #include #include +#include +#include +#include #include -#include +#include #include class SdrGrafObj; diff --git a/include/svx/contdlg.hxx b/include/svx/contdlg.hxx index cb3034fd6636..7a7b51fc0046 100644 --- a/include/svx/contdlg.hxx +++ b/include/svx/contdlg.hxx @@ -41,7 +41,7 @@ class Graphic; class SAL_WARN_UNUSED SVX_DLLPUBLIC SvxContourDlgChildWindow final : public SfxChildWindow { public: - SvxContourDlgChildWindow( vcl::Window*, sal_uInt16, SfxBindings*, SfxChildWinInfo const * ); + SvxContourDlgChildWindow(vcl::Window*, sal_uInt16, SfxBindings&, const SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID( SvxContourDlgChildWindow ); }; diff --git a/include/svx/ctredlin.hxx b/include/svx/ctredlin.hxx index d67e1ce63231..c733f0f9ea60 100644 --- a/include/svx/ctredlin.hxx +++ b/include/svx/ctredlin.hxx @@ -28,12 +28,16 @@ #include #include #include +#include +#include #include +#include #include #include +#include #include #include -#include + #include namespace utl { @@ -190,7 +194,7 @@ class SAL_WARN_UNUSED SVX_DLLPUBLIC SvxTPFilter final : public SvxTPage DECL_DLLPRIVATE_LINK( SelDateHdl, weld::ComboBox&, void ); DECL_DLLPRIVATE_LINK( RowEnableHdl, weld::Toggleable&, void ); DECL_DLLPRIVATE_LINK( TimeHdl, weld::Button&, void ); - DECL_DLLPRIVATE_LINK( ModifyHdl, weld::Entry&, void ); + DECL_DLLPRIVATE_LINK(ModifyHdl, weld::TextWidget&, void); DECL_DLLPRIVATE_LINK( ModifyListBoxHdl, weld::ComboBox&, void ); DECL_DLLPRIVATE_LINK( ModifyDate, SvtCalendarBox&, void ); DECL_DLLPRIVATE_LINK( ModifyTime, weld::FormattedSpinButton&, void ); diff --git a/include/svx/cuicharmap.hxx b/include/svx/cuicharmap.hxx index 93c96a2f3063..b56dd1f54cdd 100644 --- a/include/svx/cuicharmap.hxx +++ b/include/svx/cuicharmap.hxx @@ -18,11 +18,12 @@ */ #pragma once +#include #include #include #include +#include #include -#include #include #include #include @@ -120,12 +121,12 @@ private: DECL_DLLPRIVATE_LINK(ReturnKeypressOnCharHdl, SvxShowCharSet&, void); DECL_DLLPRIVATE_LINK(FavClickHdl, SvxShowCharSet&, void); DECL_DLLPRIVATE_LINK(SearchCharHighlightHdl, SvxShowCharSet&, void); - DECL_DLLPRIVATE_LINK(DecimalCodeChangeHdl, weld::Entry&, void); - DECL_DLLPRIVATE_LINK(HexCodeChangeHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(DecimalCodeChangeHdl, weld::TextWidget&, void); + DECL_DLLPRIVATE_LINK(HexCodeChangeHdl, weld::TextWidget&, void); DECL_DLLPRIVATE_LINK(CharFocusHdl, const CharAndFont&, void); DECL_DLLPRIVATE_LINK(InsertClickHdl, weld::Button&, void); DECL_DLLPRIVATE_LINK(FavSelectHdl, weld::Button&, void); - DECL_DLLPRIVATE_LINK(SearchUpdateHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(SearchUpdateHdl, weld::TextWidget&, void); DECL_DLLPRIVATE_LINK(SearchFieldGetFocusHdl, weld::Widget&, void); DECL_DLLPRIVATE_LINK(UpdateFavHdl, void*, void); diff --git a/include/svx/dbaexchange.hxx b/include/svx/dbaexchange.hxx index f6407f7208b7..9d16fdfa3342 100644 --- a/include/svx/dbaexchange.hxx +++ b/include/svx/dbaexchange.hxx @@ -77,7 +77,7 @@ namespace svx /** construct the transferable from a DatabaseForm component and a field name @param _rxForm - the form which is bound to the data source which's field is to be dragged + the form which is bound to the data source whose field is to be dragged @param _rFieldName the name of the field to be dragged diff --git a/include/svx/diagram/DiagramHelper_svx.hxx b/include/svx/diagram/DiagramHelper_svx.hxx index b733daa09b3c..4f4d7bd16928 100644 --- a/include/svx/diagram/DiagramHelper_svx.hxx +++ b/include/svx/diagram/DiagramHelper_svx.hxx @@ -104,9 +104,6 @@ public: // re-create XShapes virtual void reLayout() = 0; - // get text representation of data tree - virtual OUString getDiagramString() const = 0; - // get children of provided data node // use empty string for top-level nodes // returns vector of (id, text) @@ -124,7 +121,6 @@ public: virtual void applyDiagramDataState(const std::shared_ptr& rState) = 0; bool UseDiagramThemeData() const { return mbUseDiagramThemeData; } - bool UseDiagramModelData() const { return mbUseDiagramModelData; } bool ForceThemePtrRecreation() const { return mbForceThemePtrRecreation; }; // connect/disconnect to/from Group diff --git a/include/svx/dialog/TableAutoFmtDlg.hxx b/include/svx/dialog/TableAutoFmtDlg.hxx index 7ff81467c1ca..c687586b237a 100644 --- a/include/svx/dialog/TableAutoFmtDlg.hxx +++ b/include/svx/dialog/TableAutoFmtDlg.hxx @@ -19,9 +19,12 @@ #pragma once +#include +#include #include #include #include +#include #include "TableAutoFmtPreview.hxx" class SVX_DLLPUBLIC SvxTableAutoFmtDlg : public weld::GenericDialogController diff --git a/include/svx/dialog/TableStylesDlg.hxx b/include/svx/dialog/TableStylesDlg.hxx index 84318842c031..d5b043e4d133 100644 --- a/include/svx/dialog/TableStylesDlg.hxx +++ b/include/svx/dialog/TableStylesDlg.hxx @@ -20,11 +20,17 @@ #include #include +#include #include #include #include #include +namespace weld +{ +class IconView; +} + class SVX_DLLPUBLIC SvxTableStylesDlg : public weld::GenericDialogController { private: @@ -40,7 +46,7 @@ private: enum BorderLayout { - TABLE_NO_BORDERS = 1, + TABLE_NO_BORDERS = 0, TABLE_LEFT_BORDER, TABLE_RIGHT_BORDER, TABLE_LEFT_RIGHT_BORDERS, @@ -73,8 +79,7 @@ private: std::unique_ptr m_xBorderColor; std::unique_ptr m_xTextColor; std::unique_ptr m_xBorderStyle; - std::unique_ptr m_xBorderSelector; - std::unique_ptr m_xBorderSelectorWin; + std::unique_ptr m_xBorderSelector; std::unique_ptr mxWndPreview; std::unique_ptr m_xElementBox; std::unique_ptr m_xNameEntry; @@ -96,7 +101,7 @@ private: DECL_LINK(TextStyleHdl, const OUString&, void); DECL_LINK(HorAlignHdl, const OUString&, void); DECL_LINK(VerAlignHdl, const OUString&, void); - DECL_LINK(BorderLayoutSelHdl, ValueSet*, void); + DECL_LINK(BorderLayoutItemActivatedHdl, const weld::TreeIter&, bool); DECL_LINK(BorderStyleHdl, SvtLineListBox&, void); DECL_LINK(PaddingHdl, weld::MetricSpinButton&, void); DECL_LINK(OkayHdl, weld::Button&, void); diff --git a/include/svx/dialog/ThemeColorEditDialog.hxx b/include/svx/dialog/ThemeColorEditDialog.hxx index 77b300211bee..7ca47b0c304b 100644 --- a/include/svx/dialog/ThemeColorEditDialog.hxx +++ b/include/svx/dialog/ThemeColorEditDialog.hxx @@ -14,7 +14,8 @@ #include #include #include -#include +#include + #include class ColorListBox; diff --git a/include/svx/dialog/ThemeColorsPaneBase.hxx b/include/svx/dialog/ThemeColorsPaneBase.hxx index 869cb1558493..aad51a3295fb 100644 --- a/include/svx/dialog/ThemeColorsPaneBase.hxx +++ b/include/svx/dialog/ThemeColorsPaneBase.hxx @@ -10,7 +10,6 @@ #pragma once #include -#include #include #include #include diff --git a/include/svx/dialog/ThemeDialog.hxx b/include/svx/dialog/ThemeDialog.hxx index caba5a768936..614bd0459c3f 100644 --- a/include/svx/dialog/ThemeDialog.hxx +++ b/include/svx/dialog/ThemeDialog.hxx @@ -10,9 +10,9 @@ #pragma once #include +#include #include #include -#include #include #include #include diff --git a/include/svx/dialog/gotodlg.hxx b/include/svx/dialog/gotodlg.hxx index 7deba5c6c46d..2d83e1c23091 100644 --- a/include/svx/dialog/gotodlg.hxx +++ b/include/svx/dialog/gotodlg.hxx @@ -21,8 +21,9 @@ #include #include +#include #include -#include +#include namespace svx { diff --git a/include/svx/dlgctl3d.hxx b/include/svx/dlgctl3d.hxx index 51c3c352c8e2..92e7c3fd6742 100644 --- a/include/svx/dlgctl3d.hxx +++ b/include/svx/dlgctl3d.hxx @@ -20,8 +20,9 @@ #ifndef INCLUDED_SVX_DLGCTL3D_HXX #define INCLUDED_SVX_DLGCTL3D_HXX +#include +#include #include -#include #include #include #include diff --git a/include/svx/dlgctrl.hxx b/include/svx/dlgctrl.hxx index e4b18db3b233..1f62f2a23c14 100644 --- a/include/svx/dlgctrl.hxx +++ b/include/svx/dlgctrl.hxx @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/include/svx/f3dchild.hxx b/include/svx/f3dchild.hxx index 1cd46695bef7..f83469969861 100644 --- a/include/svx/f3dchild.hxx +++ b/include/svx/f3dchild.hxx @@ -32,7 +32,7 @@ class SAL_WARN_UNUSED SVX_DLLPUBLIC Svx3DChildWindow final : public SfxChildWindow { public: - Svx3DChildWindow(vcl::Window*, sal_uInt16, SfxBindings*, SfxChildWinInfo*); + Svx3DChildWindow(vcl::Window*, sal_uInt16, SfxBindings&, SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID(Svx3DChildWindow); }; diff --git a/include/svx/fillbitmaplink.hxx b/include/svx/fillbitmaplink.hxx new file mode 100644 index 000000000000..48ef03a74700 --- /dev/null +++ b/include/svx/fillbitmaplink.hxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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/. + */ +#ifndef INCLUDED_SVX_FILLBITMAPLINK_HXX +#define INCLUDED_SVX_FILLBITMAPLINK_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SdrModel; +class SdrObject; +class SdrPage; +class SfxItemPool; +class SfxStyleSheet; +class XFillBitmapItem; + +namespace com::sun::star::beans +{ +class XPropertySet; +} + +namespace sfx2 +{ +class LinkManager; +} + +// Returns the origin URL if rItem carries a deferred graphic +// (GraphicType::Default with non-empty originURL), otherwise empty. +SVXCORE_DLLPUBLIC OUString getDeferredOriginURL(const XFillBitmapItem& rItem); + +// Returns true if the pool contains any XATTR_FILLBITMAP items with +// unresolved remote URLs (GraphicType::Default with non-empty originURL). +SVXCORE_DLLPUBLIC bool hasDeferredFillBitmapLinks(const SfxItemPool& rPool); + +namespace sdr +{ +// Owns one sfx2::SvBaseLink per host (SdrObject or SdrPage background) that +// currently holds a deferred remote XFillBitmapItem, registered as soon as the +// item is set on the host (SdrObject via AttributeProperties::ItemChange, +// SdrPage via SdrPageProperties::PutItem) rather than by a later pool scan. A +// model that wants this enables it by holding a tracker; host attribute changes +// then route through onFillBitmapURLChanged. Each link writes the fetched +// graphic back only to its own host and is bound to the host lifetime via +// sdr::ObjectUser / sdr::PageUser, so it never outlives the host and the entry +// can be updated or broken individually in Edit, Links to External Files. +class SVXCORE_DLLPUBLIC FillBitmapLinkTracker +{ +public: + explicit FillBitmapLinkTracker(SdrModel& rModel); + ~FillBitmapLinkTracker(); + + // rNewURL is the deferred origin URL of the new item, or empty when the + // item is absent, already resolved, or the host is going away. The + // SfxStyleSheet host covers a fill shared by every object or page using + // that style (e.g. an Impress slide background on the Background style), + // the drawing-layer counterpart of a fill on a Writer paragraph style. + void onFillBitmapURLChanged(SdrObject& rObj, std::u16string_view rNewURL); + void onFillBitmapURLChanged(SdrPage& rPage, std::u16string_view rNewURL); + void onFillBitmapURLChanged(SfxStyleSheet& rStyle, std::u16string_view rNewURL); + + // Suppress the onFillBitmapURLChanged that a link's own write-back of the + // resolved graphic would otherwise raise for its host. The host is held by + // its own type so a write-back is matched only against the same host type. + template void setUpdatingHost(Host* pHost) { m_aUpdatingHost = pHost; } + void clearUpdatingHost() { m_aUpdatingHost = std::monostate{}; } + +private: + template + void onURLChangedImpl(std::map>& rMap, Host& rHost, + std::u16string_view rNewURL); + + template bool isUpdatingHost(Host* pHost) const + { + auto const* ppHost = std::get_if(&m_aUpdatingHost); + return ppHost && *ppHost == pHost; + } + + SdrModel& m_rModel; + /// std::monostate is there to indicate no host is being updated + std::variant m_aUpdatingHost; + std::map> m_aObjLinks; + std::map> m_aPageLinks; + std::map> m_aStyleLinks; +}; +} + +// Register links for form controls with deferred remote image URLs. +// Each entry is a (weak control reference, URL) pair. Dead references +// are silently skipped. When updated, ImageURL is set on the control +// to trigger the fetch. +SVXCORE_DLLPUBLIC void registerDeferredFormImageLinks( + const std::vector, OUString>>& + rEntries, + sfx2::LinkManager& rLinkMgr); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/svx/fillctrl.hxx b/include/svx/fillctrl.hxx index 1718b02c909c..03fe556c92c5 100644 --- a/include/svx/fillctrl.hxx +++ b/include/svx/fillctrl.hxx @@ -90,7 +90,6 @@ private: DECL_LINK(AttrKeyInputHdl, const KeyEvent&, bool); DECL_LINK(TypeKeyInputHdl, const KeyEvent&, bool); DECL_LINK(ColorKeyInputHdl, const KeyEvent&, bool); - DECL_STATIC_LINK(FillControl, DumpAsPropertyTreeHdl, tools::JsonWriter&, void); DECL_LINK(AttrFocusHdl, weld::Widget&, void); DECL_LINK(TypeFocusHdl, weld::Widget&, void); diff --git a/include/svx/float3d.hxx b/include/svx/float3d.hxx index 6725f41327e1..3c6b56a9c038 100644 --- a/include/svx/float3d.hxx +++ b/include/svx/float3d.hxx @@ -24,10 +24,14 @@ #include #include #include +#include #include +#include +#include #include +#include #include -#include +#include #include #include #include @@ -253,9 +257,8 @@ private: virtual void Resize() override; public: - Svx3DWin( SfxBindings* pBindings, SfxChildWindow *pCW, - vcl::Window* pParent ); - virtual ~Svx3DWin() override; + Svx3DWin(SfxBindings& rBindings, SfxChildWindow* pCW, vcl::Window* pParent); + virtual ~Svx3DWin() override; virtual void dispose() override; void InitColorLB(); diff --git a/include/svx/fmgridcl.hxx b/include/svx/fmgridcl.hxx index 1b07a29a5d82..f06e5057b1e4 100644 --- a/include/svx/fmgridcl.hxx +++ b/include/svx/fmgridcl.hxx @@ -16,8 +16,8 @@ * 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_SVX_FMGRIDCL_HXX -#define INCLUDED_SVX_FMGRIDCL_HXX + +#pragma once #include #include @@ -149,7 +149,7 @@ public: protected: virtual void Command(const CommandEvent& rEvt) override; - virtual VclPtr imp_CreateHeaderBar(BrowseBox* pParent) override; + virtual VclPtr imp_CreateHeaderBar(BrowseBox* pParent) override; virtual tools::Long QueryMinimumRowHeight() override; virtual void RowHeightChanged() override; virtual void ColumnResized(sal_uInt16 nId) override; @@ -195,6 +195,4 @@ protected: bool isColumnSelected(DbGridColumn const * _pColumn) const; }; -#endif // INCLUDED_SVX_FMGRIDCL_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/fontwork.hxx b/include/svx/fontwork.hxx index 5d019478d981..9db1d171bc23 100644 --- a/include/svx/fontwork.hxx +++ b/include/svx/fontwork.hxx @@ -23,9 +23,9 @@ #include #include #include +#include #include #include -#include class ColorListBox; @@ -63,8 +63,8 @@ public: class SAL_WARN_UNUSED SVX_DLLPUBLIC SvxFontWorkChildWindow final : public SfxChildWindow { - public: - SvxFontWorkChildWindow(vcl::Window*, sal_uInt16, SfxBindings*, SfxChildWinInfo*); +public: + SvxFontWorkChildWindow(vcl::Window*, sal_uInt16, SfxBindings&, SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID(SvxFontWorkChildWindow); }; @@ -133,8 +133,7 @@ class SAL_WARN_UNUSED SvxFontWorkDialog final : public SfxDockingWindow virtual SfxChildAlignment CheckAlignment( SfxChildAlignment eActAlign, SfxChildAlignment eAlign ) override; public: - SvxFontWorkDialog(SfxBindings *pBinding, SfxChildWindow *pCW, - vcl::Window* pParent); + SvxFontWorkDialog(SfxBindings& rBindings, SfxChildWindow* pCW, vcl::Window* pParent); virtual ~SvxFontWorkDialog() override; virtual void dispose() override; }; diff --git a/include/svx/fontworkgallery.hxx b/include/svx/fontworkgallery.hxx index 5cfe03a00028..cc0bfcf1c5b0 100644 --- a/include/svx/fontworkgallery.hxx +++ b/include/svx/fontworkgallery.hxx @@ -22,10 +22,12 @@ #define INCLUDED_SVX_FONTWORKGALLERY_HXX #include +#include #include #include #include -#include +#include + #include #include #include diff --git a/include/svx/frmdirlbox.hxx b/include/svx/frmdirlbox.hxx index 0124c73642be..04b595d9434b 100644 --- a/include/svx/frmdirlbox.hxx +++ b/include/svx/frmdirlbox.hxx @@ -21,7 +21,6 @@ #define INCLUDED_SVX_FRMDIRLBOX_HXX #include -#include #include #include diff --git a/include/svx/frmsel.hxx b/include/svx/frmsel.hxx index 33443f121214..bf8e8c1f424c 100644 --- a/include/svx/frmsel.hxx +++ b/include/svx/frmsel.hxx @@ -158,7 +158,11 @@ public: // accessibility - css::uno::Reference getAccessibleParent() const { return GetDrawingArea()->get_accessible_parent(); } + rtl::Reference getAccessibleParent() const + { + return GetDrawingArea()->get_accessible_parent(); + } + virtual rtl::Reference CreateAccessible() override; a11yrelationset get_accessible_relation_set() const { return GetDrawingArea()->get_accessible_relation_set(); } diff --git a/include/svx/gallery1.hxx b/include/svx/gallery1.hxx index 99eee5da951c..576bacec734e 100644 --- a/include/svx/gallery1.hxx +++ b/include/svx/gallery1.hxx @@ -127,7 +127,7 @@ public: bool HasTheme( std::u16string_view rThemeName ); SAL_DLLPRIVATE OUString GetThemeName( sal_uInt32 nThemeId ) const; - bool CreateTheme( const OUString& rThemeName ); + bool CreateTheme( const OUString& rThemeName, sal_uInt32 nId = 0U ); void RenameTheme( const OUString& rOldName, const OUString& rNewName ); bool RemoveTheme( const OUString& rThemeName ); diff --git a/include/svx/gridctrl.hxx b/include/svx/gridctrl.hxx index 90e93e455dea..e6f5ef1d7703 100644 --- a/include/svx/gridctrl.hxx +++ b/include/svx/gridctrl.hxx @@ -290,7 +290,7 @@ private: BrowserMode m_nMode; sal_Int32 m_nCurrentPos; // Current position; ImplSVEvent * m_nDeleteEvent; // EventId for asynchronous deletion of rows - DbGridControlOptions m_nOptions; // What is the able to do (Insert, Update, Delete) + DbGridControlOptions m_nOptions; // What is it able to do (Insert, Update, Delete) // default readonly DbGridControlOptions m_nOptionMask; // the mask of options to be enabled in setDataSource // (with respect to the data source capabilities) @@ -589,7 +589,7 @@ protected: void DisconnectFromFields(); void implAdjustInSolarThread(bool _bRows); - // calls AdjustRows or AdjustDataSource, synchron if the caller is running in the solar thread, else asynchron + // calls AdjustRows or AdjustDataSource, synchronous if the caller is running in the solar thread, else asynchronous protected: void ImplInitWindow( const InitWindowFacet _eInitWhat ); @@ -597,7 +597,7 @@ protected: DECL_DLLPRIVATE_LINK(RearrangeHdl, Timer*, void); DECL_DLLPRIVATE_LINK(OnAsyncAdjust, void*, void); - // if the param is != NULL, AdjustRows will be called, else AdjustDataSource + // if the param is != nullptr, AdjustRows will be called, else AdjustDataSource private: using BrowseBox::InsertHandleColumn; diff --git a/include/svx/hdft.hxx b/include/svx/hdft.hxx index 47c5a05ef0f0..218131370287 100644 --- a/include/svx/hdft.hxx +++ b/include/svx/hdft.hxx @@ -21,9 +21,11 @@ #include +#include +#include +#include +#include #include -#include - #include #include #include @@ -67,6 +69,7 @@ protected: std::unique_ptr m_xTurnOnBox; std::unique_ptr m_xCntSharedBox; std::unique_ptr m_xCntSharedFirstBox; + std::unique_ptr m_xCntNoFirstBox; std::unique_ptr m_xLMLbl; std::unique_ptrm_xLMEdit; std::unique_ptr m_xRMLbl; @@ -84,6 +87,7 @@ protected: void InitHandler(); void TurnOn(const weld::Toggleable* pButton); DECL_LINK(TurnOnHdl, weld::Toggleable&, void); + DECL_LINK(FirstPageHdl, weld::Toggleable&, void); DECL_DLLPRIVATE_LINK(BackgroundHdl, weld::Button&, void); DECL_DLLPRIVATE_LINK(ValueChangeHdl, weld::MetricSpinButton&, void); void RangeHdl(); diff --git a/include/svx/hlnkitem.hxx b/include/svx/hlnkitem.hxx index 8dac1de40f92..9da3558591a0 100644 --- a/include/svx/hlnkitem.hxx +++ b/include/svx/hlnkitem.hxx @@ -47,19 +47,22 @@ enum SvxLinkInsertMode class SVX_DLLPUBLIC SvxHyperlinkItem final : public SfxPoolItem { - OUString sName; - OUString sURL; - OUString sTarget; - SvxLinkInsertMode eType; - OUString sReplacementText; + OUString m_sName; + OUString m_sURL; + OUString m_sTarget; + SvxLinkInsertMode m_eType; + OUString m_sReplacementText; bool m_showName = true; bool m_showText = true; - OUString sIntName; - std::unique_ptr pMacroTable; + OUString m_sIntName; + std::unique_ptr m_pMacroTable; - HyperDialogEvent nMacroEvents; + HyperDialogEvent m_nMacroEvents; + + /// When turning selected text into a hyperlink, ignore m_sName, it's only a hint. + bool m_bTextIsHint = false; public: static SfxPoolItem* CreateDefault(); @@ -67,7 +70,7 @@ public: DECLARE_ITEM_TYPE_FUNCTION(SvxHyperlinkItem) SvxHyperlinkItem( TypedWhichId _nWhich = SID_HYPERLINK_GETLINK ): SfxPoolItem(_nWhich ) - { eType = HLINK_DEFAULT; nMacroEvents=HyperDialogEvent::NONE; }; + { m_eType = HLINK_DEFAULT; m_nMacroEvents=HyperDialogEvent::NONE; }; SvxHyperlinkItem( const SvxHyperlinkItem& rHyperlinkItem ); virtual bool operator==( const SfxPoolItem& ) const override; @@ -75,35 +78,36 @@ public: virtual bool QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const override; virtual bool PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId ) override; - const OUString& GetName() const { return sName; } - void SetName(const OUString& rName) { sName = rName; } + const OUString& GetName() const { return m_sName; } + void SetName(const OUString& rName) { m_sName = rName; } - const OUString& GetURL() const { return sURL; } - void SetURL(const OUString& rURL) { sURL = rURL; } + const OUString& GetURL() const { return m_sURL; } + void SetURL(const OUString& rURL) { m_sURL = rURL; } - const OUString& GetIntName () const { return sIntName; } - void SetIntName(const OUString& rIntName) { sIntName = rIntName; } + const OUString& GetIntName () const { return m_sIntName; } + void SetIntName(const OUString& rIntName) { m_sIntName = rIntName; } - const OUString& GetTargetFrame() const { return sTarget; } - void SetTargetFrame(const OUString& rTarget) { sTarget = rTarget; } + const OUString& GetTargetFrame() const { return m_sTarget; } + void SetTargetFrame(const OUString& rTarget) { m_sTarget = rTarget; } void SetShowName(const bool show) { m_showName = show; } void SetShowText(const bool show) { m_showText = show; } - SvxLinkInsertMode GetInsertMode() const { return eType; } - void SetInsertMode( SvxLinkInsertMode eNew ) { eType = eNew; } + SvxLinkInsertMode GetInsertMode() const { return m_eType; } + void SetInsertMode( SvxLinkInsertMode eNew ) { m_eType = eNew; } void SetMacro( HyperDialogEvent nEvent, const SvxMacro& rMacro ); void SetMacroTable( const SvxMacroTableDtor& rTbl ); - const SvxMacroTableDtor* GetMacroTable() const { return pMacroTable.get(); } + const SvxMacroTableDtor* GetMacroTable() const { return m_pMacroTable.get(); } - void SetMacroEvents (const HyperDialogEvent nEvents) { nMacroEvents = nEvents; } - HyperDialogEvent GetMacroEvents() const { return nMacroEvents; } + void SetMacroEvents (const HyperDialogEvent nEvents) { m_nMacroEvents = nEvents; } + HyperDialogEvent GetMacroEvents() const { return m_nMacroEvents; } - const OUString& GetReplacementText() const { return sReplacementText; } + const OUString& GetReplacementText() const { return m_sReplacementText; } + bool GetTextIsHint() const { return m_bTextIsHint; } }; #endif diff --git a/include/svx/hyperdlg.hxx b/include/svx/hyperdlg.hxx index c625f66e2894..6ac1cb4df0dc 100644 --- a/include/svx/hyperdlg.hxx +++ b/include/svx/hyperdlg.hxx @@ -37,8 +37,8 @@ private: VclPtr mpDlg; public: - SvxHlinkDlgWrapper( vcl::Window*pParent, sal_uInt16 nId, - SfxBindings* pBindings, SfxChildWinInfo* pInfo ); + SvxHlinkDlgWrapper(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); virtual ~SvxHlinkDlgWrapper() override; SFX_DECL_CHILDWINDOW_WITHID(SvxHlinkDlgWrapper); diff --git a/include/svx/imapdlg.hxx b/include/svx/imapdlg.hxx index 5a31351a377a..dc18d9badb15 100644 --- a/include/svx/imapdlg.hxx +++ b/include/svx/imapdlg.hxx @@ -53,9 +53,8 @@ typedef ::std::vector< OUString > TargetList; class SVX_DLLPUBLIC SvxIMapDlgChildWindow final : public SfxChildWindow { - public: - - SvxIMapDlgChildWindow( vcl::Window*, sal_uInt16, SfxBindings*, SfxChildWinInfo const * ); +public: + SvxIMapDlgChildWindow(vcl::Window*, sal_uInt16, SfxBindings&, const SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID( SvxIMapDlgChildWindow ); @@ -111,7 +110,7 @@ class SVX_DLLPUBLIC SvxIMapDlg final : public SfxModelessDialogController DECL_DLLPRIVATE_LINK( MousePosHdl, GraphCtrl*, void ); DECL_DLLPRIVATE_LINK( GraphSizeHdl, GraphCtrl*, void ); DECL_DLLPRIVATE_LINK( URLModifyHdl, weld::ComboBox&, void ); - DECL_DLLPRIVATE_LINK( EntryModifyHdl, weld::Entry&, void ); + DECL_DLLPRIVATE_LINK(EntryModifyHdl, weld::TextWidget&, void); DECL_DLLPRIVATE_LINK( URLLoseFocusHdl, weld::Widget&, void ); DECL_DLLPRIVATE_LINK( UpdateHdl, Timer *, void ); DECL_DLLPRIVATE_LINK( StateHdl, GraphCtrl*, void ); diff --git a/include/svx/labelitemwindow.hxx b/include/svx/labelitemwindow.hxx index 23554e20d8e6..14a4319698f2 100644 --- a/include/svx/labelitemwindow.hxx +++ b/include/svx/labelitemwindow.hxx @@ -9,8 +9,10 @@ #pragma once +#include +#include +#include #include -#include #include enum class LabelItemWindowType diff --git a/include/svx/langbox.hxx b/include/svx/langbox.hxx index c11d88d96794..325d81d7c486 100644 --- a/include/svx/langbox.hxx +++ b/include/svx/langbox.hxx @@ -25,7 +25,6 @@ #include #include #include -#include #include enum class SvxLanguageListFlags @@ -93,7 +92,6 @@ public: LanguageType get_saved_active_id() const { return m_eSavedLanguage; } bool get_active_id_changed_from_saved() const { return m_eSavedLanguage != get_active_id(); } void hide() { m_xControl->hide(); } - void set_visible(bool bShow) { m_xControl->set_visible(bShow); } void set_size_request(int nWidth, int nHeight) { m_xControl->set_size_request(nWidth, nHeight); } void set_width_chars(int nChars) { m_xControl->set_entry_width_chars(nChars); } void set_sensitive(bool bSensitive) { m_xControl->set_sensitive(bSensitive); } diff --git a/include/svx/linkwarn.hxx b/include/svx/linkwarn.hxx index 494dae58c83e..6419850cce09 100644 --- a/include/svx/linkwarn.hxx +++ b/include/svx/linkwarn.hxx @@ -20,8 +20,8 @@ #ifndef INCLUDED_SVX_LINKWARN_HXX #define INCLUDED_SVX_LINKWARN_HXX +#include #include -#include #include class SVX_DLLPUBLIC SvxLinkWarningDialog final : public weld::MessageDialogController diff --git a/include/svx/optgrid.hxx b/include/svx/optgrid.hxx index c891b38e974c..04d35012899f 100644 --- a/include/svx/optgrid.hxx +++ b/include/svx/optgrid.hxx @@ -23,10 +23,14 @@ #include #include -namespace weld { class CheckButton; } -namespace weld { class MetricSpinButton; } -namespace weld { class SpinButton; } -namespace weld { class Widget; } +namespace weld +{ +class CheckButton; +class MetricSpinButton; +class SpinButton; +class Toggleable; +class Widget; +} class SVX_DLLPUBLIC SvxOptionsGrid { diff --git a/include/svx/pagenumberlistbox.hxx b/include/svx/pagenumberlistbox.hxx index 43cef0463a45..baa166802538 100644 --- a/include/svx/pagenumberlistbox.hxx +++ b/include/svx/pagenumberlistbox.hxx @@ -23,7 +23,6 @@ #include #include #include -#include class SVXCORE_DLLPUBLIC SvxPageNumberListBox { diff --git a/include/svx/papersizelistbox.hxx b/include/svx/papersizelistbox.hxx index c31e60073022..2be2c4442823 100644 --- a/include/svx/papersizelistbox.hxx +++ b/include/svx/papersizelistbox.hxx @@ -23,7 +23,6 @@ #include #include #include -#include enum class PaperSizeApp { @@ -47,10 +46,10 @@ public: { m_xControl->connect_changed(rLink); } - int get_active() const { return m_xControl->get_active(); } void clear() { m_xControl->clear(); } void save_value() { return m_xControl->save_value(); } bool get_value_changed_from_saved() const { return m_xControl->get_value_changed_from_saved(); } + void set_tooltip_text(const OUString& rTip) { m_xControl->set_tooltip_text(rTip); } weld::ComboBox& get_widget() const { return *m_xControl; } }; diff --git a/include/svx/passwd.hxx b/include/svx/passwd.hxx index 5799f250e0f4..544c000d85f7 100644 --- a/include/svx/passwd.hxx +++ b/include/svx/passwd.hxx @@ -22,7 +22,9 @@ #include #include #include +#include #include +#include class UNLESS_MERGELIBS_MORE(SVX_DLLPUBLIC) SvxPasswordDialog final : public SfxDialogController { @@ -39,7 +41,7 @@ private: std::unique_ptr m_xOKBtn; DECL_DLLPRIVATE_LINK(ButtonHdl, weld::Button&, void); - DECL_DLLPRIVATE_LINK(EditModifyHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(EditModifyHdl, weld::TextWidget&, void); public: SvxPasswordDialog(weld::Window* pParent, bool bDisableOldPassword); diff --git a/include/svx/relfld.hxx b/include/svx/relfld.hxx index 21f1125e2795..2fb6fd2cdcbf 100644 --- a/include/svx/relfld.hxx +++ b/include/svx/relfld.hxx @@ -23,7 +23,6 @@ #include #include #include -#include #include class SVX_DLLPUBLIC SvxRelativeField @@ -40,7 +39,7 @@ private: bool m_bNegativeEnabled; bool m_bFontRelativeMode; - DECL_DLLPRIVATE_LINK(ModifyHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(ModifyHdl, weld::TextWidget&, void); public: SvxRelativeField(std::unique_ptr pControl); diff --git a/include/svx/rubydialog.hxx b/include/svx/rubydialog.hxx index 2685bf3f2062..73d7c454260d 100644 --- a/include/svx/rubydialog.hxx +++ b/include/svx/rubydialog.hxx @@ -25,8 +25,11 @@ #include #include #include +#include #include +#include #include +#include #include #include @@ -49,7 +52,7 @@ public: class SVX_DLLPUBLIC SvxRubyChildWindow final : public SfxChildWindow { public: - SvxRubyChildWindow( vcl::Window*, sal_uInt16, SfxBindings*, SfxChildWinInfo const * ); + SvxRubyChildWindow(vcl::Window*, sal_uInt16, SfxBindings&, const SfxChildWinInfo&); SFX_DECL_CHILDWINDOW( SvxRubyChildWindow ); }; @@ -107,7 +110,7 @@ class SvxRubyDialog final : public SfxModelessDialogController DECL_LINK(PositionHdl_Impl, weld::ComboBox&, void); DECL_LINK(AdjustHdl_Impl, weld::ComboBox&, void); DECL_LINK(CharStyleHdl_Impl, weld::ComboBox&, void); - DECL_LINK(EditModifyHdl_Impl, weld::Entry&, void); + DECL_LINK(EditModifyHdl_Impl, weld::TextWidget&, void); DECL_LINK(EditFocusHdl_Impl, weld::Widget&, void); DECL_LINK(KeyUpDownHdl_Impl, const KeyEvent&, bool); DECL_LINK(KeyUpDownTabHdl_Impl, const KeyEvent&, bool); diff --git a/include/svx/sdrpagewindow.hxx b/include/svx/sdrpagewindow.hxx index bc9ee7d2c87f..ceaf4a7fa703 100644 --- a/include/svx/sdrpagewindow.hxx +++ b/include/svx/sdrpagewindow.hxx @@ -65,7 +65,7 @@ public: // OVERLAYMANAGER rtl::Reference< sdr::overlay::OverlayManager > const & GetOverlayManager() const; - // #i72752# allow patcing SdrPaintWindow from SdrPageView::DrawLayer if needed + // #i72752# allow patching SdrPaintWindow from SdrPageView::DrawLayer if needed [[nodiscard]] SdrPaintWindow* patchPaintWindow(SdrPaintWindow& rPaintWindow); void unpatchPaintWindow(SdrPaintWindow* pPreviousPaintWindow); diff --git a/include/svx/sidebar/AreaPropertyPanelBase.hxx b/include/svx/sidebar/AreaPropertyPanelBase.hxx index fb5ea3e4fa3b..ea99f0850cec 100644 --- a/include/svx/sidebar/AreaPropertyPanelBase.hxx +++ b/include/svx/sidebar/AreaPropertyPanelBase.hxx @@ -34,8 +34,11 @@ #include #include #include +#include #include +#include #include +#include #include class ToolbarUnoDispatcher; @@ -104,6 +107,7 @@ public: private: void Initialize(); + void ShowTransparency(const bool bDoShow); protected: const css::uno::Reference& mxFrame; diff --git a/include/svx/sidebar/AreaTransparencyGradientPopup.hxx b/include/svx/sidebar/AreaTransparencyGradientPopup.hxx index 570986d02180..95b867ce209f 100644 --- a/include/svx/sidebar/AreaTransparencyGradientPopup.hxx +++ b/include/svx/sidebar/AreaTransparencyGradientPopup.hxx @@ -21,7 +21,6 @@ #include #include #include -#include #include class XFillFloatTransparenceItem; diff --git a/include/svx/sidebar/InspectorTextPanel.hxx b/include/svx/sidebar/InspectorTextPanel.hxx index de67685a80db..2e588d0e699b 100644 --- a/include/svx/sidebar/InspectorTextPanel.hxx +++ b/include/svx/sidebar/InspectorTextPanel.hxx @@ -24,6 +24,8 @@ #include #include +#include + namespace svx::sidebar { struct TreeNode diff --git a/include/svx/sidebar/LinePropertyPanelBase.hxx b/include/svx/sidebar/LinePropertyPanelBase.hxx index d17a24f78451..fbeb7434d504 100644 --- a/include/svx/sidebar/LinePropertyPanelBase.hxx +++ b/include/svx/sidebar/LinePropertyPanelBase.hxx @@ -18,9 +18,9 @@ */ #pragma once +#include #include #include -#include #include #include #include diff --git a/include/svx/sidebar/LineWidthPopup.hxx b/include/svx/sidebar/LineWidthPopup.hxx index f1544d3142d8..e796a73922c5 100644 --- a/include/svx/sidebar/LineWidthPopup.hxx +++ b/include/svx/sidebar/LineWidthPopup.hxx @@ -20,9 +20,9 @@ #include #include +#include #include #include -#include #include #include diff --git a/include/svx/srchdlg.hxx b/include/svx/srchdlg.hxx index efec53e9f97d..448d0d58f8d9 100644 --- a/include/svx/srchdlg.hxx +++ b/include/svx/srchdlg.hxx @@ -27,7 +27,16 @@ #include #include #include +#include +#include #include +#include +#include +#include +#include +#include +#include + #include #include @@ -98,8 +107,8 @@ class SVX_DLLPUBLIC SvxSearchDialogWrapper final : public SfxChildWindow { std::shared_ptr m_dialog; public: - SvxSearchDialogWrapper( vcl::Window*pParent, sal_uInt16 nId, - SfxBindings* pBindings, SfxChildWinInfo const * pInfo ); + SvxSearchDialogWrapper(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + const SfxChildWinInfo& rInfo); virtual ~SvxSearchDialogWrapper () override; SvxSearchDialog *getDialog () { return m_dialog.get();} @@ -152,7 +161,6 @@ private: bool m_bWriter; bool m_bSearch; bool m_bFormat; - bool m_bReplaceBackwards; SearchOptionFlags m_nOptions; bool m_bSet; bool m_bConstruct; diff --git a/include/svx/strings.hrc b/include/svx/strings.hrc index 3ba17481f7e3..054b85be5533 100644 --- a/include/svx/strings.hrc +++ b/include/svx/strings.hrc @@ -677,6 +677,7 @@ #define RID_SVXSTR_COLOR_PINK NC_("RID_SVXSTR_COLOR_PINK", "Pink") #define RID_SVXSTR_COLOR_TURQUOISE NC_("RID_SVXSTR_COLOR_TURQUOISE", "Turquoise") /* 16 old AutoFormat Table Styles */ +#define RID_SVXSTR_TBLAFMT_DEFAULT_STYLE NC_("RID_SVXSTR_TBLAFMT_DEFAULT_STYLE", "Default Style") #define RID_SVXSTR_TBLAFMT_3D NC_("RID_SVXSTR_TBLAFMT_3D", "3D") #define RID_SVXSTR_TBLAFMT_BLACK1 NC_("RID_SVXSTR_TBLAFMT_BLACK1", "Black 1") #define RID_SVXSTR_TBLAFMT_BLACK2 NC_("RID_SVXSTR_TBLAFMT_BLACK2", "Black 2") @@ -1038,7 +1039,6 @@ #define RID_SVXSTR_EXPORT_GRAPHIC_TITLE NC_("RID_SVXSTR_EXPORT_GRAPHIC_TITLE", "Image Export") #define RID_SVXSTR_SAVEAS_IMAGE NC_("RID_SVXSTR_SAVEAS_IMAGE", "Save as Image") -#define RID_SVXSTR_PASTE_AS_DIALOG_TITLE NC_("RID_SVXSTR_PASTE_AS_DIALOG_TITLE", "Paste As") // Strings for the Draw Dialog -------------------------------------------- #define RID_SVX_3D_UNDO_EXCHANGE_PASTE NC_("RID_SVX_3D_UNDO_EXCHANGE_PASTE", "Insert object(s)") @@ -1426,6 +1426,7 @@ #define STR_IMAGE_CAPACITY_WITH_REDUCTION NC_("STR_IMAGE_CAPACITY_WITH_REDUCTION", "$(CAPACITY) KiB ($(REDUCTION)% reduction)") #define STR_IMAGE_GIF NC_("STR_IMAGE_GIF", "GIF image") #define STR_IMAGE_JPEG NC_("STR_IMAGE_JPEG", "JPEG image") +#define STR_IMAGE_JXL NC_("STR_IMAGE_JXL", "JPEG XL image") #define STR_IMAGE_PNG NC_("STR_IMAGE_PNG", "PNG image") #define STR_IMAGE_TIFF NC_("STR_IMAGE_TIFF", "TIFF image") #define STR_IMAGE_WMF NC_("STR_IMAGE_WMF", "WMF image") @@ -1478,6 +1479,7 @@ // Used in the Slide Setup dialog of Impress #define STR_SLIDE_NUMBERS NC_("STR_SLIDE_NUMBERS", "Slide numbers:") +#define STR_RESIZE_ALL_SLIDES NC_("STR_RESIZE_ALL_SLIDES", "Resize all slides") // String for saving modified image (instead of original) #define RID_SVXSTR_SAVE_MODIFIED_IMAGE NC_("RID_SVXSTR_SAVE_MODIFIED_IMAGE", "The image has been modified. By default the original image will be saved.\nDo you want to save the modified version instead?") @@ -1837,6 +1839,11 @@ #define RID_SVXSTR_PAGEDIR_RTL_VERT NC_("RID_SVXSTR_PAGEDIR_RTL_VERT", "Right-to-left (vertical)") #define RID_SVXSTR_PAGEDIR_LTR_VERT NC_("RID_SVXSTR_PAGEDIR_LTR_VERT", "Left-to-right (vertical)") #define RID_SVXSTR_PAGEDIR_LTR_BTT_VERT NC_("RID_SVXSTR_PAGEDIR_LTR_BTT_VERT", "Bottom-to-top, left-to-right (vertical)") +// page gutter +#define RID_SVXSTR_PAGEGUTTER_LEFT NC_("RID_SVXSTR_PAGEGUTTER_LEFT", "Left") +#define RID_SVXSTR_PAGEGUTTER_INNER NC_("RID_SVXSTR_PAGEGUTTER_INNER", "Inner") +#define RID_SVXSTR_PAGEGUTTER_RIGHT NC_("RID_SVXSTR_PAGEGUTTER_RIGHT", "Right") +#define RID_SVXSTR_PAGEGUTTER_OUTER NC_("RID_SVXSTR_PAGEGUTTER_OUTER", "Outer") #define RID_SVXSTR_FONTWORK NC_("RID_SVXSTR_FONTWORK", "Text along Path...") @@ -1905,6 +1912,11 @@ #define STR_WARNING_GRAPHIC_PIXEL_COUNT_LOW NC_("STR_WARNING_GRAPHIC_PIXEL_COUNT_LOW", "Image '%NAME%' has too few pixels for the current size (%DPIX% x %DPIY% DPI)") #define STR_WARNING_GRAPHIC_PIXEL_COUNT_HIGH NC_("STR_WARNING_GRAPHIC_PIXEL_COUNT_HIGH", "Image '%NAME%' has too many pixels for the current size (%DPIX% x %DPIY% DPI)") +/*-------------------------------------------------------------------- + Description: Statusbar popup menu in Calc. + --------------------------------------------------------------------*/ +#define RID_SVXSTR_COPY_VALUES NC_("RID_SVXSTR_COPY_VALUES", "Copy values") + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/svddef.hxx b/include/svx/svddef.hxx index 115b60a0ae3c..775d69a48a2d 100644 --- a/include/svx/svddef.hxx +++ b/include/svx/svddef.hxx @@ -83,6 +83,7 @@ class SdrEdgeNode2GlueDistItem; class SdrEdgeNode2HorzDistItem; class SdrEdgeNode2VertDistItem; class SdrGrafBlueItem; +class SdrGrafClipPolyPolygonItem; class SdrGrafContrastItem; class SdrGrafCropItem; class SdrGrafGamma100Item; @@ -251,29 +252,30 @@ inline constexpr TypedWhichId SDRATTR_EDGELINE2DELTA inline constexpr TypedWhichId SDRATTR_EDGELINE3DELTA (SDRATTR_EDGE_FIRST +10); // 1106 inline constexpr sal_uInt16 SDRATTR_EDGE_LAST (SDRATTR_EDGELINE3DELTA); // 1106 -inline constexpr sal_uInt16 SDRATTR_MEASURE_FIRST (SDRATTR_EDGE_LAST + 1); // 1107 -inline constexpr TypedWhichId SDRATTR_MEASUREKIND (SDRATTR_MEASURE_FIRST+ 0); // 1107 -inline constexpr TypedWhichId SDRATTR_MEASURETEXTHPOS (SDRATTR_MEASURE_FIRST+ 1); // 1108 -inline constexpr TypedWhichId SDRATTR_MEASURETEXTVPOS (SDRATTR_MEASURE_FIRST+ 2); // 1109 -inline constexpr TypedWhichId SDRATTR_MEASURELINEDIST (SDRATTR_MEASURE_FIRST+ 3); // 1110 -inline constexpr TypedWhichId SDRATTR_MEASUREHELPLINEOVERHANG (SDRATTR_MEASURE_FIRST+ 4); // 1111 -inline constexpr TypedWhichId SDRATTR_MEASUREHELPLINEDIST (SDRATTR_MEASURE_FIRST+ 5); // 1112 -inline constexpr TypedWhichId SDRATTR_MEASUREHELPLINE1LEN (SDRATTR_MEASURE_FIRST+ 6); // 1113 -inline constexpr TypedWhichId SDRATTR_MEASUREHELPLINE2LEN (SDRATTR_MEASURE_FIRST+ 7); // 1114 -inline constexpr TypedWhichId SDRATTR_MEASUREBELOWREFEDGE (SDRATTR_MEASURE_FIRST+ 8); // 1115 -inline constexpr TypedWhichId SDRATTR_MEASURETEXTROTA90 (SDRATTR_MEASURE_FIRST+ 9); // 1116 -inline constexpr TypedWhichId SDRATTR_MEASURETEXTUPSIDEDOWN (SDRATTR_MEASURE_FIRST+10); // 1117 -inline constexpr TypedWhichId SDRATTR_MEASUREOVERHANG (SDRATTR_MEASURE_FIRST+11); // 1118 -inline constexpr TypedWhichId SDRATTR_MEASUREUNIT (SDRATTR_MEASURE_FIRST+12); // 1119 -inline constexpr TypedWhichId SDRATTR_MEASURESCALE (SDRATTR_MEASURE_FIRST+13); // 1120 -inline constexpr TypedWhichId SDRATTR_MEASURESHOWUNIT (SDRATTR_MEASURE_FIRST+14); // 1121 -inline constexpr TypedWhichId SDRATTR_MEASUREFORMATSTRING (SDRATTR_MEASURE_FIRST+15); // 1122 -inline constexpr TypedWhichId SDRATTR_MEASURETEXTAUTOANGLE (SDRATTR_MEASURE_FIRST+16); // 1123 -inline constexpr TypedWhichId SDRATTR_MEASURETEXTAUTOANGLEVIEW (SDRATTR_MEASURE_FIRST+17); // 1124 -inline constexpr TypedWhichId SDRATTR_MEASURETEXTISFIXEDANGLE (SDRATTR_MEASURE_FIRST+18); // 1125 -inline constexpr TypedWhichId SDRATTR_MEASURETEXTFIXEDANGLE (SDRATTR_MEASURE_FIRST+19); // 1126 -inline constexpr TypedWhichId SDRATTR_MEASUREDECIMALPLACES (SDRATTR_MEASURE_FIRST+20); // 1127 -inline constexpr sal_uInt16 SDRATTR_MEASURE_LAST (SDRATTR_MEASUREDECIMALPLACES); // 1127 +inline constexpr sal_uInt16 SDRATTR_MEASURE_FIRST (SDRATTR_EDGE_LAST + 1); // 1107 +inline constexpr TypedWhichId SDRATTR_MEASUREKIND (SDRATTR_MEASURE_FIRST+ 0); // 1107 +inline constexpr TypedWhichId SDRATTR_MEASURETEXTHPOS (SDRATTR_MEASURE_FIRST+ 1); // 1108 +inline constexpr TypedWhichId SDRATTR_MEASURETEXTVPOS (SDRATTR_MEASURE_FIRST+ 2); // 1109 +inline constexpr TypedWhichId SDRATTR_MEASURELINEDIST (SDRATTR_MEASURE_FIRST+ 3); // 1110 +inline constexpr TypedWhichId SDRATTR_MEASUREHELPLINEOVERHANG (SDRATTR_MEASURE_FIRST+ 4); // 1111 +inline constexpr TypedWhichId SDRATTR_MEASUREHELPLINEDIST (SDRATTR_MEASURE_FIRST+ 5); // 1112 +inline constexpr TypedWhichId SDRATTR_MEASUREHELPLINE1LEN (SDRATTR_MEASURE_FIRST+ 6); // 1113 +inline constexpr TypedWhichId SDRATTR_MEASUREHELPLINE2LEN (SDRATTR_MEASURE_FIRST+ 7); // 1114 +inline constexpr TypedWhichId SDRATTR_MEASUREBELOWREFEDGE (SDRATTR_MEASURE_FIRST+ 8); // 1115 +inline constexpr TypedWhichId SDRATTR_MEASURETEXTROTA90 (SDRATTR_MEASURE_FIRST+ 9); // 1116 +inline constexpr TypedWhichId SDRATTR_MEASURETEXTUPSIDEDOWN (SDRATTR_MEASURE_FIRST+10); // 1117 +inline constexpr TypedWhichId SDRATTR_MEASUREOVERHANG (SDRATTR_MEASURE_FIRST+11); // 1118 +inline constexpr TypedWhichId SDRATTR_MEASUREUNIT (SDRATTR_MEASURE_FIRST+12); // 1119 +inline constexpr TypedWhichId SDRATTR_MEASURESCALE (SDRATTR_MEASURE_FIRST+13); // 1120 +inline constexpr TypedWhichId SDRATTR_MEASURESHOWUNIT (SDRATTR_MEASURE_FIRST+14); // 1121 +inline constexpr TypedWhichId SDRATTR_MEASUREFORMATSTRING (SDRATTR_MEASURE_FIRST+15); // 1122 +inline constexpr TypedWhichId SDRATTR_MEASURETEXTAUTOANGLE (SDRATTR_MEASURE_FIRST+16); // 1123 +inline constexpr TypedWhichId SDRATTR_MEASURETEXTAUTOANGLEVIEW (SDRATTR_MEASURE_FIRST+17); // 1124 +inline constexpr TypedWhichId SDRATTR_MEASURETEXTISFIXEDANGLE (SDRATTR_MEASURE_FIRST+18); // 1125 +inline constexpr TypedWhichId SDRATTR_MEASURETEXTFIXEDANGLE (SDRATTR_MEASURE_FIRST+19); // 1126 +inline constexpr TypedWhichId SDRATTR_MEASUREDECIMALPLACES (SDRATTR_MEASURE_FIRST+20); // 1127 +inline constexpr TypedWhichId SDRATTR_MEASUREAUTODECIMALPLACES (SDRATTR_MEASURE_FIRST+21); // 1128 +inline constexpr sal_uInt16 SDRATTR_MEASURE_LAST (SDRATTR_MEASUREAUTODECIMALPLACES); // 1128 inline constexpr sal_uInt16 SDRATTR_CIRC_FIRST (SDRATTR_MEASURE_LAST+ 1); // 1128 inline constexpr TypedWhichId SDRATTR_CIRCKIND (SDRATTR_CIRC_FIRST+ 0); // 1128 @@ -333,125 +335,126 @@ inline constexpr TypedWhichId SDRATTR_GRAFTRANSPARENCE inline constexpr TypedWhichId SDRATTR_GRAFINVERT (SDRATTR_GRAF_FIRST+7); // 1174 inline constexpr TypedWhichId SDRATTR_GRAFMODE (SDRATTR_GRAF_FIRST+8); // 1175 inline constexpr TypedWhichId SDRATTR_GRAFCROP (SDRATTR_GRAF_FIRST+9); // 1176 -inline constexpr sal_uInt16 SDRATTR_GRAF_LAST (SDRATTR_GRAFCROP); // 1176 +inline constexpr TypedWhichId SDRATTR_GRAFCLIPPOLYPOLYGON (SDRATTR_GRAF_FIRST+10); // 1177 +inline constexpr sal_uInt16 SDRATTR_GRAF_LAST (SDRATTR_GRAFCLIPPOLYPOLYGON); // 1177 -inline constexpr sal_uInt16 SDRATTR_3D_FIRST (SDRATTR_GRAF_LAST + 1); // 1177 +inline constexpr sal_uInt16 SDRATTR_3D_FIRST (SDRATTR_GRAF_LAST + 1); // 1178 -inline constexpr sal_uInt16 SDRATTR_3DOBJ_FIRST (SDRATTR_3D_FIRST); // 1177 -inline constexpr TypedWhichId SDRATTR_3DOBJ_PERCENT_DIAGONAL (SDRATTR_3DOBJ_FIRST + 0); // 1177 -inline constexpr TypedWhichId SDRATTR_3DOBJ_BACKSCALE (SDRATTR_3DOBJ_FIRST + 1); // 1178 -inline constexpr TypedWhichId SDRATTR_3DOBJ_DEPTH (SDRATTR_3DOBJ_FIRST + 2); // 1179 -inline constexpr TypedWhichId SDRATTR_3DOBJ_HORZ_SEGS (SDRATTR_3DOBJ_FIRST + 3); // 1180 -inline constexpr TypedWhichId SDRATTR_3DOBJ_VERT_SEGS (SDRATTR_3DOBJ_FIRST + 4); // 1181 -inline constexpr TypedWhichId SDRATTR_3DOBJ_END_ANGLE (SDRATTR_3DOBJ_FIRST + 5); // 1182 -inline constexpr TypedWhichId SDRATTR_3DOBJ_DOUBLE_SIDED (SDRATTR_3DOBJ_FIRST + 6); // 1183 -inline constexpr TypedWhichId SDRATTR_3DOBJ_NORMALS_KIND (SDRATTR_3DOBJ_FIRST + 7); // 1184 -inline constexpr TypedWhichId SDRATTR_3DOBJ_NORMALS_INVERT (SDRATTR_3DOBJ_FIRST + 8); // 1185 -inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_PROJ_X (SDRATTR_3DOBJ_FIRST + 9); // 1186 -inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_PROJ_Y (SDRATTR_3DOBJ_FIRST + 10); // 1187 -inline constexpr TypedWhichId SDRATTR_3DOBJ_SHADOW_3D (SDRATTR_3DOBJ_FIRST + 11); // 1188 -inline constexpr TypedWhichId SDRATTR_3DOBJ_MAT_COLOR (SDRATTR_3DOBJ_FIRST + 12); // 1189 -inline constexpr TypedWhichId SDRATTR_3DOBJ_MAT_EMISSION (SDRATTR_3DOBJ_FIRST + 13); // 1190 -inline constexpr TypedWhichId SDRATTR_3DOBJ_MAT_SPECULAR (SDRATTR_3DOBJ_FIRST + 14); // 1191 -inline constexpr TypedWhichId SDRATTR_3DOBJ_MAT_SPECULAR_INTENSITY (SDRATTR_3DOBJ_FIRST + 15); // 1192 -inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_KIND (SDRATTR_3DOBJ_FIRST + 16); // 1193 -inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_MODE (SDRATTR_3DOBJ_FIRST + 17); // 1194 -inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_FILTER (SDRATTR_3DOBJ_FIRST + 18); // 1195 +inline constexpr sal_uInt16 SDRATTR_3DOBJ_FIRST (SDRATTR_3D_FIRST); // 1178 +inline constexpr TypedWhichId SDRATTR_3DOBJ_PERCENT_DIAGONAL (SDRATTR_3DOBJ_FIRST + 0); // 1178 +inline constexpr TypedWhichId SDRATTR_3DOBJ_BACKSCALE (SDRATTR_3DOBJ_FIRST + 1); // 1179 +inline constexpr TypedWhichId SDRATTR_3DOBJ_DEPTH (SDRATTR_3DOBJ_FIRST + 2); // 1180 +inline constexpr TypedWhichId SDRATTR_3DOBJ_HORZ_SEGS (SDRATTR_3DOBJ_FIRST + 3); // 1181 +inline constexpr TypedWhichId SDRATTR_3DOBJ_VERT_SEGS (SDRATTR_3DOBJ_FIRST + 4); // 1182 +inline constexpr TypedWhichId SDRATTR_3DOBJ_END_ANGLE (SDRATTR_3DOBJ_FIRST + 5); // 1183 +inline constexpr TypedWhichId SDRATTR_3DOBJ_DOUBLE_SIDED (SDRATTR_3DOBJ_FIRST + 6); // 1184 +inline constexpr TypedWhichId SDRATTR_3DOBJ_NORMALS_KIND (SDRATTR_3DOBJ_FIRST + 7); // 1185 +inline constexpr TypedWhichId SDRATTR_3DOBJ_NORMALS_INVERT (SDRATTR_3DOBJ_FIRST + 8); // 1186 +inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_PROJ_X (SDRATTR_3DOBJ_FIRST + 9); // 1187 +inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_PROJ_Y (SDRATTR_3DOBJ_FIRST + 10); // 1188 +inline constexpr TypedWhichId SDRATTR_3DOBJ_SHADOW_3D (SDRATTR_3DOBJ_FIRST + 11); // 1189 +inline constexpr TypedWhichId SDRATTR_3DOBJ_MAT_COLOR (SDRATTR_3DOBJ_FIRST + 12); // 1190 +inline constexpr TypedWhichId SDRATTR_3DOBJ_MAT_EMISSION (SDRATTR_3DOBJ_FIRST + 13); // 1191 +inline constexpr TypedWhichId SDRATTR_3DOBJ_MAT_SPECULAR (SDRATTR_3DOBJ_FIRST + 14); // 1192 +inline constexpr TypedWhichId SDRATTR_3DOBJ_MAT_SPECULAR_INTENSITY (SDRATTR_3DOBJ_FIRST + 15); // 1193 +inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_KIND (SDRATTR_3DOBJ_FIRST + 16); // 1194 +inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_MODE (SDRATTR_3DOBJ_FIRST + 17); // 1195 +inline constexpr TypedWhichId SDRATTR_3DOBJ_TEXTURE_FILTER (SDRATTR_3DOBJ_FIRST + 18); // 1196 // #107245# New items for 3d objects use former range SDRATTR_3DOBJ_RESERVED_01 // up to SDRATTR_3DOBJ_RESERVED_05 -inline constexpr TypedWhichId SDRATTR_3DOBJ_SMOOTH_NORMALS (SDRATTR_3DOBJ_FIRST + 19); // 1196 -inline constexpr TypedWhichId SDRATTR_3DOBJ_SMOOTH_LIDS (SDRATTR_3DOBJ_FIRST + 20); // 1197 -inline constexpr TypedWhichId SDRATTR_3DOBJ_CHARACTER_MODE (SDRATTR_3DOBJ_FIRST + 21); // 1198 -inline constexpr TypedWhichId SDRATTR_3DOBJ_CLOSE_FRONT (SDRATTR_3DOBJ_FIRST + 22); // 1199 -inline constexpr TypedWhichId SDRATTR_3DOBJ_CLOSE_BACK (SDRATTR_3DOBJ_FIRST + 23); // 1200 +inline constexpr TypedWhichId SDRATTR_3DOBJ_SMOOTH_NORMALS (SDRATTR_3DOBJ_FIRST + 19); // 1197 +inline constexpr TypedWhichId SDRATTR_3DOBJ_SMOOTH_LIDS (SDRATTR_3DOBJ_FIRST + 20); // 1198 +inline constexpr TypedWhichId SDRATTR_3DOBJ_CHARACTER_MODE (SDRATTR_3DOBJ_FIRST + 21); // 1199 +inline constexpr TypedWhichId SDRATTR_3DOBJ_CLOSE_FRONT (SDRATTR_3DOBJ_FIRST + 22); // 1200 +inline constexpr TypedWhichId SDRATTR_3DOBJ_CLOSE_BACK (SDRATTR_3DOBJ_FIRST + 23); // 1201 // #i28528# // Added extra Item (Bool) for chart2 to be able to show reduced line geometry -inline constexpr TypedWhichId SDRATTR_3DOBJ_REDUCED_LINE_GEOMETRY (SDRATTR_3DOBJ_FIRST + 24); // 1201 +inline constexpr TypedWhichId SDRATTR_3DOBJ_REDUCED_LINE_GEOMETRY (SDRATTR_3DOBJ_FIRST + 24); // 1202 -inline constexpr sal_uInt16 SDRATTR_3DOBJ_LAST (SDRATTR_3DOBJ_REDUCED_LINE_GEOMETRY); // 1201 +inline constexpr sal_uInt16 SDRATTR_3DOBJ_LAST (SDRATTR_3DOBJ_REDUCED_LINE_GEOMETRY); // 1202 -inline constexpr sal_uInt16 SDRATTR_3DSCENE_FIRST (SDRATTR_3DOBJ_LAST + 1); // 1202 -inline constexpr TypedWhichId SDRATTR_3DSCENE_PERSPECTIVE (SDRATTR_3DSCENE_FIRST + 0); // 1202 -inline constexpr TypedWhichId SDRATTR_3DSCENE_DISTANCE (SDRATTR_3DSCENE_FIRST + 1); // 1203 -inline constexpr TypedWhichId SDRATTR_3DSCENE_FOCAL_LENGTH (SDRATTR_3DSCENE_FIRST + 2); // 1204 -inline constexpr TypedWhichId SDRATTR_3DSCENE_TWO_SIDED_LIGHTING (SDRATTR_3DSCENE_FIRST + 3); // 1205 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_1 (SDRATTR_3DSCENE_FIRST + 4); // 1206 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_2 (SDRATTR_3DSCENE_FIRST + 5); // 1207 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_3 (SDRATTR_3DSCENE_FIRST + 6); // 1208 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_4 (SDRATTR_3DSCENE_FIRST + 7); // 1209 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_5 (SDRATTR_3DSCENE_FIRST + 8); // 1210 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_6 (SDRATTR_3DSCENE_FIRST + 9); // 1211 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_7 (SDRATTR_3DSCENE_FIRST + 10); // 1212 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_8 (SDRATTR_3DSCENE_FIRST + 11); // 1213 -inline constexpr TypedWhichId SDRATTR_3DSCENE_AMBIENTCOLOR (SDRATTR_3DSCENE_FIRST + 12); // 1214 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_1 (SDRATTR_3DSCENE_FIRST + 13); // 1215 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_2 (SDRATTR_3DSCENE_FIRST + 14); // 1216 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_3 (SDRATTR_3DSCENE_FIRST + 15); // 1217 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_4 (SDRATTR_3DSCENE_FIRST + 16); // 1218 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_5 (SDRATTR_3DSCENE_FIRST + 17); // 1219 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_6 (SDRATTR_3DSCENE_FIRST + 18); // 1220 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_7 (SDRATTR_3DSCENE_FIRST + 19); // 1221 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_8 (SDRATTR_3DSCENE_FIRST + 20); // 1222 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_1 (SDRATTR_3DSCENE_FIRST + 21); // 1223 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_2 (SDRATTR_3DSCENE_FIRST + 22); // 1224 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_3 (SDRATTR_3DSCENE_FIRST + 23); // 1225 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_4 (SDRATTR_3DSCENE_FIRST + 24); // 1226 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_5 (SDRATTR_3DSCENE_FIRST + 25); // 1227 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_6 (SDRATTR_3DSCENE_FIRST + 26); // 1228 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_7 (SDRATTR_3DSCENE_FIRST + 27); // 1229 -inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_8 (SDRATTR_3DSCENE_FIRST + 28); // 1230 -inline constexpr TypedWhichId SDRATTR_3DSCENE_SHADOW_SLANT (SDRATTR_3DSCENE_FIRST + 29); // 1231 -inline constexpr TypedWhichId SDRATTR_3DSCENE_SHADE_MODE (SDRATTR_3DSCENE_FIRST + 30); // 1232 -inline constexpr sal_uInt16 SDRATTR_3DSCENE_LAST (SDRATTR_3DSCENE_SHADE_MODE); // 1232 -inline constexpr sal_uInt16 SDRATTR_3D_LAST (SDRATTR_3DSCENE_LAST); // 1232 +inline constexpr sal_uInt16 SDRATTR_3DSCENE_FIRST (SDRATTR_3DOBJ_LAST + 1); // 1203 +inline constexpr TypedWhichId SDRATTR_3DSCENE_PERSPECTIVE (SDRATTR_3DSCENE_FIRST + 0); // 1203 +inline constexpr TypedWhichId SDRATTR_3DSCENE_DISTANCE (SDRATTR_3DSCENE_FIRST + 1); // 1204 +inline constexpr TypedWhichId SDRATTR_3DSCENE_FOCAL_LENGTH (SDRATTR_3DSCENE_FIRST + 2); // 1205 +inline constexpr TypedWhichId SDRATTR_3DSCENE_TWO_SIDED_LIGHTING (SDRATTR_3DSCENE_FIRST + 3); // 1206 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_1 (SDRATTR_3DSCENE_FIRST + 4); // 1207 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_2 (SDRATTR_3DSCENE_FIRST + 5); // 1208 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_3 (SDRATTR_3DSCENE_FIRST + 6); // 1209 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_4 (SDRATTR_3DSCENE_FIRST + 7); // 1210 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_5 (SDRATTR_3DSCENE_FIRST + 8); // 1211 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_6 (SDRATTR_3DSCENE_FIRST + 9); // 1212 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_7 (SDRATTR_3DSCENE_FIRST + 10); // 1213 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTCOLOR_8 (SDRATTR_3DSCENE_FIRST + 11); // 1214 +inline constexpr TypedWhichId SDRATTR_3DSCENE_AMBIENTCOLOR (SDRATTR_3DSCENE_FIRST + 12); // 1215 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_1 (SDRATTR_3DSCENE_FIRST + 13); // 1216 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_2 (SDRATTR_3DSCENE_FIRST + 14); // 1217 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_3 (SDRATTR_3DSCENE_FIRST + 15); // 1218 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_4 (SDRATTR_3DSCENE_FIRST + 16); // 1219 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_5 (SDRATTR_3DSCENE_FIRST + 17); // 1220 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_6 (SDRATTR_3DSCENE_FIRST + 18); // 1221 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_7 (SDRATTR_3DSCENE_FIRST + 19); // 1222 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTON_8 (SDRATTR_3DSCENE_FIRST + 20); // 1223 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_1 (SDRATTR_3DSCENE_FIRST + 21); // 1224 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_2 (SDRATTR_3DSCENE_FIRST + 22); // 1225 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_3 (SDRATTR_3DSCENE_FIRST + 23); // 1226 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_4 (SDRATTR_3DSCENE_FIRST + 24); // 1227 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_5 (SDRATTR_3DSCENE_FIRST + 25); // 1228 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_6 (SDRATTR_3DSCENE_FIRST + 26); // 1229 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_7 (SDRATTR_3DSCENE_FIRST + 27); // 1230 +inline constexpr TypedWhichId SDRATTR_3DSCENE_LIGHTDIRECTION_8 (SDRATTR_3DSCENE_FIRST + 28); // 1231 +inline constexpr TypedWhichId SDRATTR_3DSCENE_SHADOW_SLANT (SDRATTR_3DSCENE_FIRST + 29); // 1232 +inline constexpr TypedWhichId SDRATTR_3DSCENE_SHADE_MODE (SDRATTR_3DSCENE_FIRST + 30); // 1233 +inline constexpr sal_uInt16 SDRATTR_3DSCENE_LAST (SDRATTR_3DSCENE_SHADE_MODE); // 1233 +inline constexpr sal_uInt16 SDRATTR_3D_LAST (SDRATTR_3DSCENE_LAST); // 1233 -inline constexpr sal_uInt16 SDRATTR_CUSTOMSHAPE_FIRST (SDRATTR_3D_LAST + 1); // 1233 -inline constexpr TypedWhichId SDRATTR_CUSTOMSHAPE_ENGINE (SDRATTR_CUSTOMSHAPE_FIRST + 0); // 1233 -inline constexpr TypedWhichId SDRATTR_CUSTOMSHAPE_DATA (SDRATTR_CUSTOMSHAPE_FIRST + 1); // 1234 -inline constexpr TypedWhichId SDRATTR_CUSTOMSHAPE_GEOMETRY (SDRATTR_CUSTOMSHAPE_FIRST + 2); // 1235 -inline constexpr sal_uInt16 SDRATTR_CUSTOMSHAPE_LAST (SDRATTR_CUSTOMSHAPE_GEOMETRY); // 1235 +inline constexpr sal_uInt16 SDRATTR_CUSTOMSHAPE_FIRST (SDRATTR_3D_LAST + 1); // 1234 +inline constexpr TypedWhichId SDRATTR_CUSTOMSHAPE_ENGINE (SDRATTR_CUSTOMSHAPE_FIRST + 0); // 1234 +inline constexpr TypedWhichId SDRATTR_CUSTOMSHAPE_DATA (SDRATTR_CUSTOMSHAPE_FIRST + 1); // 1235 +inline constexpr TypedWhichId SDRATTR_CUSTOMSHAPE_GEOMETRY (SDRATTR_CUSTOMSHAPE_FIRST + 2); // 1236 +inline constexpr sal_uInt16 SDRATTR_CUSTOMSHAPE_LAST (SDRATTR_CUSTOMSHAPE_GEOMETRY); // 1236 -inline constexpr sal_uInt16 SDRATTR_TABLE_FIRST (SDRATTR_CUSTOMSHAPE_LAST+1); // 1236 -inline constexpr TypedWhichId SDRATTR_TABLE_BORDER (SDRATTR_TABLE_FIRST+0); // 1236 -inline constexpr TypedWhichId SDRATTR_TABLE_BORDER_INNER (SDRATTR_TABLE_FIRST+1); // 1237 -inline constexpr TypedWhichId SDRATTR_TABLE_BORDER_TLBR (SDRATTR_TABLE_FIRST+2); // 1238 -inline constexpr TypedWhichId SDRATTR_TABLE_BORDER_BLTR (SDRATTR_TABLE_FIRST+3); // 1239 -inline constexpr TypedWhichId SDRATTR_TABLE_TEXT_ROTATION (SDRATTR_TABLE_FIRST+4); // 1240 -inline constexpr TypedWhichId SDRATTR_TABLE_CELL_GRABBAG (SDRATTR_TABLE_FIRST+5); // 1241 -inline constexpr sal_uInt16 SDRATTR_TABLE_LAST (SDRATTR_TABLE_CELL_GRABBAG); // 1241 +inline constexpr sal_uInt16 SDRATTR_TABLE_FIRST (SDRATTR_CUSTOMSHAPE_LAST+1); // 1237 +inline constexpr TypedWhichId SDRATTR_TABLE_BORDER (SDRATTR_TABLE_FIRST+0); // 1237 +inline constexpr TypedWhichId SDRATTR_TABLE_BORDER_INNER (SDRATTR_TABLE_FIRST+1); // 1238 +inline constexpr TypedWhichId SDRATTR_TABLE_BORDER_TLBR (SDRATTR_TABLE_FIRST+2); // 1239 +inline constexpr TypedWhichId SDRATTR_TABLE_BORDER_BLTR (SDRATTR_TABLE_FIRST+3); // 1240 +inline constexpr TypedWhichId SDRATTR_TABLE_TEXT_ROTATION (SDRATTR_TABLE_FIRST+4); // 1241 +inline constexpr TypedWhichId SDRATTR_TABLE_CELL_GRABBAG (SDRATTR_TABLE_FIRST+5); // 1242 +inline constexpr sal_uInt16 SDRATTR_TABLE_LAST (SDRATTR_TABLE_CELL_GRABBAG); // 1242 -inline constexpr sal_uInt16 SDRATTR_GLOW_FIRST (SDRATTR_TABLE_LAST+1); // 1242 -inline constexpr TypedWhichId SDRATTR_GLOW_RADIUS(SDRATTR_GLOW_FIRST+0); // 1242 -inline constexpr TypedWhichId SDRATTR_GLOW_COLOR (SDRATTR_GLOW_FIRST+1); // 1243 -inline constexpr TypedWhichId SDRATTR_GLOW_TRANSPARENCY(SDRATTR_GLOW_FIRST+2); // 1244 -inline constexpr sal_uInt16 SDRATTR_GLOW_LAST(SDRATTR_GLOW_TRANSPARENCY); // 1244 +inline constexpr sal_uInt16 SDRATTR_GLOW_FIRST (SDRATTR_TABLE_LAST+1); // 1243 +inline constexpr TypedWhichId SDRATTR_GLOW_RADIUS(SDRATTR_GLOW_FIRST+0); // 1243 +inline constexpr TypedWhichId SDRATTR_GLOW_COLOR (SDRATTR_GLOW_FIRST+1); // 1244 +inline constexpr TypedWhichId SDRATTR_GLOW_TRANSPARENCY(SDRATTR_GLOW_FIRST+2); // 1245 +inline constexpr sal_uInt16 SDRATTR_GLOW_LAST(SDRATTR_GLOW_TRANSPARENCY); // 1245 -inline constexpr sal_uInt16 SDRATTR_SOFTEDGE_FIRST(SDRATTR_GLOW_LAST+1); // 1245 -inline constexpr TypedWhichId SDRATTR_SOFTEDGE_RADIUS(SDRATTR_SOFTEDGE_FIRST+0); // 1245 -inline constexpr sal_uInt16 SDRATTR_SOFTEDGE_LAST(SDRATTR_SOFTEDGE_RADIUS); // 1245 +inline constexpr sal_uInt16 SDRATTR_SOFTEDGE_FIRST(SDRATTR_GLOW_LAST+1); // 1246 +inline constexpr TypedWhichId SDRATTR_SOFTEDGE_RADIUS(SDRATTR_SOFTEDGE_FIRST+0); // 1246 +inline constexpr sal_uInt16 SDRATTR_SOFTEDGE_LAST(SDRATTR_SOFTEDGE_RADIUS); // 1246 -inline constexpr sal_uInt16 SDRATTR_GLOW_TEXT_FIRST(SDRATTR_SOFTEDGE_LAST+1); // 1246 -inline constexpr TypedWhichId SDRATTR_GLOW_TEXT_RADIUS(SDRATTR_GLOW_TEXT_FIRST+0); // 1246 -inline constexpr TypedWhichId SDRATTR_GLOW_TEXT_COLOR(SDRATTR_GLOW_TEXT_FIRST+1); // 1247 -inline constexpr TypedWhichId SDRATTR_GLOW_TEXT_TRANSPARENCY(SDRATTR_GLOW_TEXT_FIRST+2);// 1248 -inline constexpr sal_uInt16 SDRATTR_GLOW_TEXT_LAST(SDRATTR_GLOW_TEXT_TRANSPARENCY); // 1248 +inline constexpr sal_uInt16 SDRATTR_GLOW_TEXT_FIRST(SDRATTR_SOFTEDGE_LAST+1); // 1247 +inline constexpr TypedWhichId SDRATTR_GLOW_TEXT_RADIUS(SDRATTR_GLOW_TEXT_FIRST+0); // 1247 +inline constexpr TypedWhichId SDRATTR_GLOW_TEXT_COLOR(SDRATTR_GLOW_TEXT_FIRST+1); // 1248 +inline constexpr TypedWhichId SDRATTR_GLOW_TEXT_TRANSPARENCY(SDRATTR_GLOW_TEXT_FIRST+2);// 1249 +inline constexpr sal_uInt16 SDRATTR_GLOW_TEXT_LAST(SDRATTR_GLOW_TEXT_TRANSPARENCY); // 1249 -inline constexpr sal_uInt16 SDRATTR_TEXTCOLUMNS_FIRST(SDRATTR_GLOW_TEXT_LAST+1); // 1249 -inline constexpr TypedWhichId SDRATTR_TEXTCOLUMNS_NUMBER(SDRATTR_TEXTCOLUMNS_FIRST+0); // 1249 -inline constexpr TypedWhichId SDRATTR_TEXTCOLUMNS_SPACING(SDRATTR_TEXTCOLUMNS_FIRST+1); // 1250 -inline constexpr sal_uInt16 SDRATTR_TEXTCOLUMNS_LAST(SDRATTR_TEXTCOLUMNS_SPACING); // 1250 +inline constexpr sal_uInt16 SDRATTR_TEXTCOLUMNS_FIRST(SDRATTR_GLOW_TEXT_LAST+1); // 1250 +inline constexpr TypedWhichId SDRATTR_TEXTCOLUMNS_NUMBER(SDRATTR_TEXTCOLUMNS_FIRST+0); // 1250 +inline constexpr TypedWhichId SDRATTR_TEXTCOLUMNS_SPACING(SDRATTR_TEXTCOLUMNS_FIRST+1); // 1251 +inline constexpr sal_uInt16 SDRATTR_TEXTCOLUMNS_LAST(SDRATTR_TEXTCOLUMNS_SPACING); // 1251 -inline constexpr sal_uInt16 SDRATTR_WRITINGMODE2_FIRST(SDRATTR_TEXTCOLUMNS_LAST+1);// 1251 -inline constexpr TypedWhichId SDRATTR_WRITINGMODE2(SDRATTR_WRITINGMODE2_FIRST+0); // 1251 -inline constexpr sal_uInt16 SDRATTR_WRITINGMODE2_LAST(SDRATTR_WRITINGMODE2); // 1251 +inline constexpr sal_uInt16 SDRATTR_WRITINGMODE2_FIRST(SDRATTR_TEXTCOLUMNS_LAST+1);// 1252 +inline constexpr TypedWhichId SDRATTR_WRITINGMODE2(SDRATTR_WRITINGMODE2_FIRST+0); // 1252 +inline constexpr sal_uInt16 SDRATTR_WRITINGMODE2_LAST(SDRATTR_WRITINGMODE2); // 1252 -inline constexpr sal_uInt16 SDRATTR_EDGEOOXMLCURVE_FIRST(SDRATTR_WRITINGMODE2_LAST+1);// 1252 -inline constexpr TypedWhichId SDRATTR_EDGEOOXMLCURVE(SDRATTR_EDGEOOXMLCURVE_FIRST+0); // 1252 -inline constexpr sal_uInt16 SDRATTR_EDGEOOXMLCURVE_LAST(SDRATTR_EDGEOOXMLCURVE); // 1252 +inline constexpr sal_uInt16 SDRATTR_EDGEOOXMLCURVE_FIRST(SDRATTR_WRITINGMODE2_LAST+1);// 1253 +inline constexpr TypedWhichId SDRATTR_EDGEOOXMLCURVE(SDRATTR_EDGEOOXMLCURVE_FIRST+0); // 1253 +inline constexpr sal_uInt16 SDRATTR_EDGEOOXMLCURVE_LAST(SDRATTR_EDGEOOXMLCURVE); // 1253 -inline constexpr sal_uInt16 SDRATTR_END (SDRATTR_EDGEOOXMLCURVE_LAST); // 1252 +inline constexpr sal_uInt16 SDRATTR_END (SDRATTR_EDGEOOXMLCURVE_LAST); // 1253 #endif // INCLUDED_SVX_SVDDEF_HXX diff --git a/include/svx/svdedtv.hxx b/include/svx/svdedtv.hxx index 8ffb06286ad0..8e3c4c8f9d3f 100644 --- a/include/svx/svdedtv.hxx +++ b/include/svx/svdedtv.hxx @@ -55,7 +55,7 @@ enum class SdrInsertFlags { NONE = 0x0000, DONTMARK = 0x0001, /* object will not be marked (the actual marking remains) */ - ADDMARK = 0x0002, /* object will be added an existing selection */ + ADDMARK = 0x0002, /* object will be added to an existing selection */ SETDEFATTR = 0x0004, /* actual attributes (+StyleSheet) are assigned to the object */ SETDEFLAYER = 0x0008, /* actual layer is assigned to the object */ }; @@ -89,7 +89,7 @@ protected: bool m_bOrthoDesiredOnMarked : 1; bool m_bOneOrMoreMovable : 1; // at least one object is moveable bool m_bMoreThanOneNoMovRot : 1; // more than one object is not movable nor turnable (Crook) - bool m_bContortionPossible : 1; // all polygones (grouped if necessary) + bool m_bContortionPossible : 1; // all polygons (grouped if necessary) bool m_bMoveAllowed : 1; bool m_bResizeFreeAllowed : 1; bool m_bResizePropAllowed : 1; @@ -120,7 +120,7 @@ protected: // converts an object, when positive it removes the old one from its List // and inserts the new one instead. including Undo. - // Nor MarkEntry nor ModelChgBroadcast is created. + // Neither MarkEntry nor ModelChgBroadcast is created. SAL_DLLPRIVATE rtl::Reference ImpConvertOneObj(SdrObject* pObj, bool bPath, bool bLineToArea); // set both flags: bToTopPossible and bToBtmPossible. @@ -270,7 +270,7 @@ public: // Unite several objects to a polygon: // - rectangles/circles/text... are implicitly converted. - // - polygones are closed automatically + // - polygons are closed automatically // - attributes and layer are taken from the first object marked // (thus from lowest Z-order). // - group objects are included when all (!) member objects of @@ -293,7 +293,7 @@ public: // Decompose marked polypolygon objects into polygons. // Grouped objects are searched and decomposed, if all member objects are PathObjs. - // bMakeLines=TRUE: all polygones are decomposed into single lines resp. bezier segments + // bMakeLines=TRUE: all polygons are decomposed into single lines resp. bezier segments void DismantleMarkedObjects(bool bMakeLines=false); bool IsCombinePossible(bool bNoPolyPoly=false) const; bool IsDismantlePossible(bool bMakeLines=false) const; @@ -363,7 +363,7 @@ public: bool IsUnGroupPossible() const { ForcePossibilities(); return m_bUnGroupPossible; } bool IsGroupEnterPossible() const { ForcePossibilities(); return m_bGrpEnterPossible; } - // Convert marked objects to polygones/Beziercurves. The bool-functions + // Convert marked objects to polygons/Beziercurves. The bool-functions // return sal_True, if at least one marked object could be converted. // Also member objects of group objects are converted. // For a better description see: SdrObj.HXX @@ -423,7 +423,7 @@ public: // If one or more objects of the type SdrGrafObj or SdrOle2Obj // are marked and these are capable to deliver a StarView-metafile, - // this methods converts the metafile to a drawing object. + // this method converts the metafile to a drawing object. // The SdrGrafObjs/SdrOle2Objs are replaced by the new objects. void DoImportMarkedMtf(SvdProgressInfo *pProgrInfo=nullptr); bool IsImportMtfPossible() const { ForcePossibilities(); return m_bImportMtfPossible; } diff --git a/include/svx/svdmark.hxx b/include/svx/svdmark.hxx index 2f09cf11029a..2608050166f0 100644 --- a/include/svx/svdmark.hxx +++ b/include/svx/svdmark.hxx @@ -214,8 +214,6 @@ public: // All Entries are copied! SdrMarkList& operator=(const SdrMarkList& rLst); - - bool isDiagramBackgroundShapeSelected() const; }; diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx index a9c337b4716c..06c61a9a942c 100644 --- a/include/svx/svdmodel.hxx +++ b/include/svx/svdmodel.hxx @@ -78,6 +78,11 @@ namespace model class Theme; } +namespace sdr +{ +class FillBitmapLinkTracker; +} + constexpr const sal_Unicode DEGREE_CHAR = u'\x00B0'; /* U+00B0 DEGREE SIGN */ @@ -176,6 +181,7 @@ protected: SfxStyleSheet* m_pDefaultStyleSheet; SfxStyleSheet* mpDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj; // #i119287# sfx2::LinkManager* m_pLinkManager; // LinkManager + std::unique_ptr m_pFillBitmapLinkTracker; std::deque> m_aUndoStack; std::deque> m_aRedoStack; std::unique_ptr m_pCurrentUndoGroup; // For multi-level @@ -352,7 +358,13 @@ public: void SetDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj(SfxStyleSheet* pDefSS) { mpDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj = pDefSS; } sfx2::LinkManager* GetLinkManager() { return m_pLinkManager; } - void SetLinkManager( sfx2::LinkManager* pLinkMgr ) { m_pLinkManager = pLinkMgr; } + // Setting a LinkManager also creates the per-host fill bitmap link tracker, + // so any drawing model with a LinkManager tracks deferred remote fill + // bitmaps (registered as the item is set via AttributeProperties::ItemChange + // / SdrPageProperties::PutItem) rather than by a later pool scan. + void SetLinkManager( sfx2::LinkManager* pLinkMgr ); + + sdr::FillBitmapLinkTracker* GetFillBitmapLinkTracker() const { return m_pFillBitmapLinkTracker.get(); } ::comphelper::IEmbeddedHelper* GetPersist() const { return m_pEmbeddedHelper; } void SetPersist( ::comphelper::IEmbeddedHelper *p ) { m_pEmbeddedHelper = p; } diff --git a/include/svx/svdmrkv.hxx b/include/svx/svdmrkv.hxx index e9e97c4ca5ac..8484dc5b2e65 100644 --- a/include/svx/svdmrkv.hxx +++ b/include/svx/svdmrkv.hxx @@ -178,7 +178,7 @@ protected: SAL_DLLPRIVATE bool ImpIsFrameHandles() const; SAL_DLLPRIVATE OUString ImpGetDescriptionString(TranslateId pStrCacheID, ImpGetDescriptionOptions nOpt=ImpGetDescriptionOptions::NONE) const; - // Generates a string including degrees symbol, from an angel specification in 1/100deg + // Generates a string including degrees symbol, from an angle specification in 1/100deg SAL_DLLPRIVATE bool ImpMarkPoint(SdrHdl* pHdl, SdrMark* pMark, bool bUnmark); virtual bool MarkPoints(const tools::Rectangle* pRect, bool bUnmark); bool MarkGluePoints(const tools::Rectangle* pRect, bool bUnmark); @@ -268,7 +268,7 @@ public: const std::vector& GetTransitiveHullOfMarkedObjects() const { return maSdrViewSelection.GetAllMarkedObjects(); } - // mechanism to complete disable handles at the view. Handles will be hidden and deleted + // mechanism to completely disable handles at the view. Handles will be hidden and deleted // when set, no new ones created, no interaction allowed. Handles will be recreated and shown // when reset. Default is false. void hideMarkHandles(); @@ -306,7 +306,7 @@ public: bool MarkNextObj(const Point& rPnt, short nTol, bool bPrev); // Mark all objects within a rectangular area - // Just objects are marked which are inclosed completely + // Just objects are marked which are enclosed completely void MarkObj(const tools::Rectangle& rRect, bool bUnmark); void MarkObj(SdrObject* pObj, SdrPageView* pPV, bool bUnmark = false, bool bDoNoSetMarkHdl = false, std::vector && rSubSelections = std::vector()); @@ -373,7 +373,7 @@ public: // SdrPageView, which should be defined correctly always. // Alternatively a gluepoint may be characterized by a SdrHdl. // In this case the SdrHdl instance consists of all required information. - // And in this case, the gluepoint are always is marked by enforcement + // And in this case, the gluepoint is always marked by enforcement // (Handlers are just situated at marked gluepoints ) // Attention: With each change of the gluepoint status the handle list is re-calculated. // All previously saved SdrHdl* became invalid by this, the same with the point IDs! diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx index d6d37780b032..351f3ff7101e 100644 --- a/include/svx/svdobj.hxx +++ b/include/svx/svdobj.hxx @@ -239,8 +239,14 @@ public: bool isDiagramTextNode() const; bool removeDiagramNode(); + // temporary check if to use AdvancedDiagramFeatures + static bool useAdvancedDiagramFeatures(); + +protected: + void resetViewContact(); + private: - // check if a ObjectName is set and it is in DiagramModelID syntax + // check if an ObjectName is set and it is in DiagramModelID syntax bool ObjectNameIsDiagramModelID(); friend class SdrObjListIter; @@ -363,6 +369,20 @@ public: virtual OUString GetDescription() const; virtual void SetDecorative(bool isDecorative); virtual bool IsDecorative() const; + // tdf#167714 a "standard horizontal rule", which is laid out and cropped its own way. + // This says which kind of object this is, not how it looks: it belongs to creating a rule and + // is read-only afterwards, never toggled on an existing shape, so no undo action reverses it. + void SetHorizontalRule(bool isHorizontalRule) { m_bHorizontalRule = isHorizontalRule; } + // The flag lives in a graphic style, which can be shared or applied to anything, so it is + // honoured only for the two shapes a rule can be made of: a filled bar (the shaded rule) and + // a picture (a picture rule). On an ellipse, a group or a custom shape it would ask for a + // layout that makes no sense. + bool IsHorizontalRule() const + { + const SdrObjKind eKind = GetObjIdentifier(); + return m_bHorizontalRule + && (eKind == SdrObjKind::Rectangle || eKind == SdrObjKind::Graphic); + } // Object representing an annotation bool isAnnotationObject() const { return bool(mpAnnotationData); } @@ -492,7 +512,7 @@ public: // FullDrag support. This is for standard interactions and for SdrObjOwn // support. If supportsFullDrag() returns true, getFullDragClone has to - // return a cloned SdrObject (who's ownership it loses) at which modifications + // return a cloned SdrObject (whose ownership it loses) at which modifications // like Move(), Scale(), etc or applySpecialDrag() will be executed. That // object will be visualized on overlay for full drag, but should not be // part of the model, thus not changing anything since it's only a temporary @@ -922,6 +942,9 @@ protected: bool mbLineIsOutsideGeometry : 1; // #i25616# bool mbSupportTextIndentingOnLineWidthChange : 1; + + bool m_bHorizontalRule = false; + // custom prompt text for empty presentation object OUString m_aCustomPromptText; diff --git a/include/svx/svdocapt.hxx b/include/svx/svdocapt.hxx index daf57752cce6..4b0f593a147e 100644 --- a/include/svx/svdocapt.hxx +++ b/include/svx/svdocapt.hxx @@ -92,6 +92,7 @@ public: // for calc: fixed note tail position. void SetFixedTail() { mbFixedTail = true; } + bool IsFixedTail() const { return mbFixedTail; } SAL_DLLPRIVATE virtual OUString TakeObjNameSingul() const override; SAL_DLLPRIVATE virtual OUString TakeObjNamePlural() const override; diff --git a/include/svx/svdogrp.hxx b/include/svx/svdogrp.hxx index 54ffade2f166..08de5020cba7 100644 --- a/include/svx/svdogrp.hxx +++ b/include/svx/svdogrp.hxx @@ -31,6 +31,7 @@ public: // Basic DiagramHelper support virtual bool isDiagram() const override; virtual const std::shared_ptr< svx::diagram::DiagramHelper_svx >& getDiagramHelper() const override; + void resetDiagramHelper(const std::shared_ptr< svx::diagram::DiagramHelper_svx >& rDiagramHelper = nullptr); // return DiagramSubSelection if exists. This will always return // a valid SdrObject* to allow to use this as a loop-through-call @@ -43,9 +44,7 @@ private: Point maRefPoint; // Reference point inside the object group - // Allow *only* DiagramHelper itself to set this internal reference to - // tightly control usage - friend class svx::diagram::DiagramHelper_svx; + // the DiagramHelper if this SdrObjGroup host a Diagram std::shared_ptr< svx::diagram::DiagramHelper_svx > mp_DiagramHelper; public: diff --git a/include/svx/svdomedia.hxx b/include/svx/svdomedia.hxx index 0b705c9d3e08..9869758d6d74 100644 --- a/include/svx/svdomedia.hxx +++ b/include/svx/svdomedia.hxx @@ -27,10 +27,12 @@ namespace sdr::contact { class ViewContactOfSdrMediaObj; } namespace com::sun::star::graphic { class XGraphic; } +class SdrMediaLink; class SVXCORE_DLLPUBLIC SdrMediaObj final : public SdrRectObj { friend class sdr::contact::ViewContactOfSdrMediaObj; + friend class SdrMediaLink; private: // protected destructor - due to final, make private @@ -59,6 +61,12 @@ public: void setURL(const OUString& rURL, const OUString& rReferer); const OUString& getURL() const; + // An external media reference the user picked in this session is allowed on its own, in + // the same way as a presentation sound the user picks. A reference that arrived with the + // document is allowed only by the document-wide link update permission. + void setLinkAllowed(bool bAllowed); + bool isLinkAllowed() const; + /// Returns the URL to the temporary extracted media file. const OUString& getTempURL() const; @@ -76,6 +84,17 @@ public: private: SAL_DLLPRIVATE void mediaPropertiesChanged( const ::avmedia::MediaItem& rNewState ); SAL_DLLPRIVATE virtual std::unique_ptr CreateObjectSpecificViewContact() override; + SAL_DLLPRIVATE virtual void handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage) override; + + // Register an external media reference as a document link, so it takes + // part in the normal link update permission just like a linked graphic. + // Media stored inside the document is not a link and is left alone. + SAL_DLLPRIVATE void ImpRegisterLink(); + SAL_DLLPRIVATE void ImpDeregisterLink(); + + // Fetch a snapshot frame from the media URL. The caller decides + // whether a fetch is allowed. + SAL_DLLPRIVATE void grabSnapshot(const OUString& rRealURL) const; struct Impl; std::unique_ptr m_xImpl; diff --git a/include/svx/svdoole2.hxx b/include/svx/svdoole2.hxx index 5ec520fdd359..63707fc8d6f7 100644 --- a/include/svx/svdoole2.hxx +++ b/include/svx/svdoole2.hxx @@ -24,6 +24,7 @@ #include #include +#include #include namespace com::sun::star { @@ -165,6 +166,16 @@ public: void DisconnectFileLink_Impl(); void CheckFileLink_Impl(); + // Register a deferred link during import when the document has not yet + // prompted the user about link updates. The actual embedded object will be + // created when the user confirms via UpdateAllLinks + void SetDeferredLink(const OUString& rLinkURL, + const css::uno::Sequence& rMediaDescriptor); + bool CompleteDeferredLink(); + bool HasDeferredLink() const; + + void SyncObjVisualArea(const css::uno::Reference& xObj); + // allows to transfer the graphics to the object helper void SetGraphicToObj( const Graphic& aGraphic ); void SetGraphicToObj( const css::uno::Reference< css::io::XInputStream >& xGrStream, diff --git a/include/svx/svdotable.hxx b/include/svx/svdotable.hxx index f11460e2da9c..17ebb8692a8c 100644 --- a/include/svx/svdotable.hxx +++ b/include/svx/svdotable.hxx @@ -151,6 +151,8 @@ public: const SfxItemSet& GetActiveCellItemSet() const; + virtual std::optional GetActiveTextBackgroundColor(const SdrText* pSdrText) const override; + void setTableStyle( const css::uno::Reference< css::container::XIndexAccess >& xAutoFormatStyle ); const css::uno::Reference< css::container::XIndexAccess >& getTableStyle() const; diff --git a/include/svx/svdotext.hxx b/include/svx/svdotext.hxx index 4d18337edca2..0a7d9db01fc5 100644 --- a/include/svx/svdotext.hxx +++ b/include/svx/svdotext.hxx @@ -365,6 +365,9 @@ public: bool IsTextEditActive() const { return mpEditingOutliner != nullptr; } + /** Returns the background color behind the given text for auto color calculation.*/ + virtual std::optional GetActiveTextBackgroundColor(const SdrText* pSdrText) const; + /** returns the currently active text. */ virtual SdrText* getActiveText() const; diff --git a/include/svx/svdpage.hxx b/include/svx/svdpage.hxx index ca05dfba74e2..06b3a05e1736 100644 --- a/include/svx/svdpage.hxx +++ b/include/svx/svdpage.hxx @@ -239,7 +239,7 @@ private: std::optional>> mxNavigationOrder; bool mbObjOrdNumsDirty; bool mbRectsDirty; - /// This flag is when the mpNavigation list has been changed but + /// This flag is when the mxNavigationOrder list has been changed but /// the indices of the referenced SdrObjects still have their old values. bool mbIsNavigationOrderDirty; @@ -331,8 +331,6 @@ private: void ImpAddStyleSheet(SfxStyleSheet& rNewStyleSheet); SdrPageProperties& operator=(const SdrPageProperties& rCandidate) = delete; - - void sendLOKitThemeChangedCallback(); public: // construct/destruct SdrPageProperties(SdrPage& rSdrPage); @@ -460,7 +458,7 @@ protected: virtual css::uno::Reference< css::uno::XInterface > createUnoPage(); // Copying of pages is split into two parts: construction and copying of page objects, - // because the copying might need access to fully initialized page. CloneSdrPage() is responsible + // because the copying might need access to a fully initialized page. CloneSdrPage() is responsible // to call lateInit() after copy-construction of a new object. Any initialization in derived // classes that needs access to the page objects must be deferred to lateInit. And it must // call lateInit() of its parent class. @@ -520,6 +518,10 @@ public: virtual bool RestoreDefaultText(SdrObject* pObj, const OUString& rStr); + /** Called when an object on this page stops being an empty presentation object, which is where + a presentation learns that content reached a placeholder. */ + virtual void onEmptyPresObjFilled(SdrObject& rObj); + protected: void TRG_ImpMasterPageRemoved(const SdrPage& rRemovedPage); diff --git a/include/svx/svdpntv.hxx b/include/svx/svdpntv.hxx index e54325f68fc2..cbe1d542c9d4 100644 --- a/include/svx/svdpntv.hxx +++ b/include/svx/svdpntv.hxx @@ -515,7 +515,6 @@ public: /// the loading there. When such an object is done loading, it is displayed. /// TODO: Only works at the moment, if SwapGraphics is enabled in the model. /// The default = false flag is non-persistent - bool IsSwapAsynchron() const { return mbSwapAsynchron; } void SetSwapAsynchron(bool bJa=true) { mbSwapAsynchron=bJa; } virtual bool KeyInput(const KeyEvent& rKEvt, vcl::Window* pWin); diff --git a/include/svx/svdtrans.hxx b/include/svx/svdtrans.hxx index a85edb82beee..57586ead7350 100644 --- a/include/svx/svdtrans.hxx +++ b/include/svx/svdtrans.hxx @@ -231,8 +231,6 @@ public: FrPair(const double& rX, const double& rY) : m_aX(rX),m_aY(rY) {} FrPair(tools::Long nMul, tools::Long nDiv) = delete; FrPair(tools::Long xMul, tools::Long xDiv, tools::Long yMul, tools::Long yDiv): m_aX(double(xMul)/xDiv),m_aY(double(yMul)/yDiv) {} - double X() const { return m_aX; } - double Y() const { return m_aY; } double& X() { return m_aX; } double& Y() { return m_aY; } }; diff --git a/include/svx/svdundo.hxx b/include/svx/svdundo.hxx index 15d09ecea84a..fe99c2cc8d18 100644 --- a/include/svx/svdundo.hxx +++ b/include/svx/svdundo.hxx @@ -106,9 +106,10 @@ public: SdrUndoAction* GetAction(sal_Int32 nNum) const { return maActions[nNum].get(); } void AddAction(std::unique_ptr pAct); - void SetComment(const OUString& rStr) { m_aComment=rStr; } - void SetObjDescription(const OUString& rStr) { m_aObjDescription=rStr; } + virtual void SetComment(const OUString& rStr) override; + virtual void SetObjDescription(const OUString& rStr) override; virtual OUString GetComment() const override; + virtual OUString GetSdrRepeatComment() const override; virtual void Undo() override; diff --git a/include/svx/svxids.hrc b/include/svx/svxids.hrc index 237205995053..0aadd1c3eba1 100644 --- a/include/svx/svxids.hrc +++ b/include/svx/svxids.hrc @@ -86,6 +86,7 @@ class XFillGradientItem; #define MID_HLINK_TYPE 0x72 #define MID_HLINK_TEXT 0x73 #define MID_HLINK_REPLACEMENTTEXT 0x74 +#define MID_HLINK_TEXTISHINT 0x75 #define MID_VIEWLAYOUT_COLUMNS 0x77 #define MID_VIEWLAYOUT_BOOKMODE 0x78 @@ -231,7 +232,7 @@ class XFillGradientItem; #define SID_ATTR_PAGE_ORIENTATION TypedWhichId( SID_SVX_START + 53 ) #define SID_ATTR_PAGE_PAPERBIN TypedWhichId( SID_SVX_START + 54 ) // this is used both as a SfxBoolItem(sd/source/ui/func/fupage.cxx) and as a SfxStringItem(sw/source/uibase/utlui/uitool.cxx) -#define SID_ATTR_PAGE_EXT1 ( SID_SVX_START + 55 ) +#define SID_ATTR_PAGE_EXT1 TypedWhichId( SID_SVX_START + 55 ) #define SID_ATTR_PAGE_EXT2 TypedWhichId( SID_SVX_START + 56 ) #define SID_ATTR_PAGE_HEADERSET TypedWhichId( SID_SVX_START + 57 ) #define SID_ATTR_PAGE_FOOTERSET TypedWhichId( SID_SVX_START + 58 ) @@ -261,7 +262,7 @@ class XFillGradientItem; #define SID_ATTR_TRANSFORM_ROT_X TypedWhichId( SID_SVX_START + 93 ) #define SID_ATTR_TRANSFORM_ROT_Y TypedWhichId( SID_SVX_START + 94 ) #define SID_ATTR_TRANSFORM_ANGLE TypedWhichId( SID_SVX_START + 95 ) -#define SID_ATTR_TRANSFORM_DELTA_ANGLE TypedWhichId( SID_SVX_START + 96 ) +#define SID_ATTR_TRANSFORM_DELTA_ANGLE TypedWhichId( SID_SVX_START + 251 ) // CAUTION! Range <96..100> used by SFX2 (!) #define SID_SIZE_ALL ( SID_SVX_START + 101 ) #define SID_DRAW_LINE ( SID_SVX_START + 102 ) @@ -603,7 +604,7 @@ class XFillGradientItem; #define SID_FM_FILECONTROL ( SID_SVX_START + 605 ) //( SID_SVX_START + 606 ) is used by SID_DRAWTBX_REDACTED_EXPORT #define SID_FM_NAVIGATIONBAR ( SID_SVX_START + 607 ) -#define SID_FM_TRANSLATE ( SID_SVX_START + 608 ) +// was SID_FM_TRANSLATE introduced with e20d2de7836da52dbf9e528d1043b1e188097bfd //FREE #define SID_FM_DELETEROWS ( SID_SVX_START + 610 ) //FREE @@ -909,7 +910,8 @@ class XFillGradientItem; #define SID_OPTIONS_DATABASES ( SID_SVX_START + 1060 ) #define SID_OPEN_SMARTTAGMENU TypedWhichId( SID_SVX_START + 1061 ) -// CAUTION! Range <1062 .. 1069> used by include/sfx2/sfxsids.hrc +// CAUTION! Range <1062 .. 1068> used by include/sfx2/sfxsids.hrc +// CAUTION! 1069 used by include/editeng/editids.hrc #define SID_TABLE_MERGE_CELLS ( SID_SVX_START + 1070 ) #define SID_TABLE_SPLIT_CELLS ( SID_SVX_START + 1071 ) @@ -936,7 +938,7 @@ class XFillGradientItem; // 1092 is used out of order below #define SID_OBJECT_MIRROR ( SID_SVX_START + 1093 ) -#define SID_DELETE_POSTIT ( SID_SVX_START + 1094 ) +#define SID_DELETE_POSTIT TypedWhichId( SID_SVX_START + 1094 ) #define SID_NEXT_POSTIT ( SID_SVX_START + 1095 ) #define SID_PREVIOUS_POSTIT ( SID_SVX_START + 1096 ) #define SID_DELETEALL_POSTIT ( SID_SVX_START + 1097 ) @@ -1125,8 +1127,10 @@ class XFillGradientItem; #define SID_RESET_AUTOFORMATS ( SID_SVX_START + 1258 ) +#define SID_ATTR_PAGE_NO_FIRST ( SID_SVX_START + 1259 ) + // IMPORTANT NOTE: adjust SID_SVX_FIRSTFREE, when adding new slot id -#define SID_SVX_FIRSTFREE ( SID_SVX_START + 1257 + 1 ) +#define SID_SVX_FIRSTFREE ( SID_SVX_START + 1259 + 1 ) // Overflow check for slot IDs #if SID_SVX_FIRSTFREE > SID_SVX_END diff --git a/include/svx/svxitems.hrc b/include/svx/svxitems.hrc index a882a37b5d86..fc6221070a90 100644 --- a/include/svx/svxitems.hrc +++ b/include/svx/svxitems.hrc @@ -40,6 +40,7 @@ const std::pair RID_ATTR_NAMES[] = { NC_("RID_ATTR_NAMES", "Font weight") , SID_ATTR_CHAR_WEIGHT }, { NC_("RID_ATTR_NAMES", "Shadowed") , SID_ATTR_CHAR_SHADOWED }, { NC_("RID_ATTR_NAMES", "Individual words") , SID_ATTR_CHAR_WORDLINEMODE }, + // To translators: Outline refers to the lines of the shape of a character { NC_("RID_ATTR_NAMES", "Outline") , SID_ATTR_CHAR_CONTOUR }, { NC_("RID_ATTR_NAMES", "Strikethrough") , SID_ATTR_CHAR_STRIKEOUT }, { NC_("RID_ATTR_NAMES", "Underline") , SID_ATTR_CHAR_UNDERLINE }, diff --git a/include/svx/tbcontrl.hxx b/include/svx/tbcontrl.hxx index e9dd731a83e2..74c6b19e875b 100644 --- a/include/svx/tbcontrl.hxx +++ b/include/svx/tbcontrl.hxx @@ -87,7 +87,7 @@ to distinguish whether a new style or a new color has been set - GetFillColor() == COL_BLACK -> GetStyle() , + GetFillColor() == COL_BLACK -> GetStyle(), GetFillColor() == COL_WHITE -> GetColor() SvxFrameToolBoxControl @@ -146,8 +146,10 @@ class PaletteManager; namespace svx { class ToolboxButtonColorUpdaterBase; } namespace sfx { struct CurrencyID; } -class SvxStyleToolBoxControl final : public cppu::ImplInheritanceHelper +using SvxStyleToolBoxControl_Base = cppu::ImplInheritanceHelper; + +class SvxStyleToolBoxControl final : public SvxStyleToolBoxControl_Base { struct Impl; std::unique_ptr m_pImpl; @@ -168,8 +170,9 @@ public: // XUpdatable virtual void SAL_CALL update() override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using SvxStyleToolBoxControl_Base::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; @@ -255,7 +258,7 @@ public: * Static method used by SvxNumberFormatShell::GetCurrencySymbols

        * * @param rList output: labels in the combo box - * @param bFlag input: true means that we add the default currency in the combox + * @param bFlag input: true means that we add the default currency in the combobox * @param rCurrencyList output: list of the currency positions in SvxCurrencyToolBoxControl::CurrencySymbols vector * @see SvxNumberFormatShell::GetCurrencySymbols **/ diff --git a/include/svx/theme/IThemeColorChanger.hxx b/include/svx/theme/IThemeColorChanger.hxx index 035494f12324..a0d54bc1bff1 100644 --- a/include/svx/theme/IThemeColorChanger.hxx +++ b/include/svx/theme/IThemeColorChanger.hxx @@ -19,14 +19,7 @@ class SVXCORE_DLLPUBLIC IThemeColorChanger { public: virtual ~IThemeColorChanger() = default; - void apply(std::shared_ptr const& pColorSet) - { - doApply(pColorSet); - svx::theme::notifyLOK(pColorSet, std::set()); - } - -private: - virtual void doApply(std::shared_ptr const& pColorSet) = 0; + virtual void apply(std::shared_ptr const& pColorSet) = 0; }; } // end svx namespace diff --git a/include/svx/theme/ThemeColorChangerCommon.hxx b/include/svx/theme/ThemeColorChangerCommon.hxx index 9fa3f4376ddc..d3c0272b9b1f 100644 --- a/include/svx/theme/ThemeColorChangerCommon.hxx +++ b/include/svx/theme/ThemeColorChangerCommon.hxx @@ -22,10 +22,6 @@ namespace theme { SVXCORE_DLLPUBLIC void updateSdrObject(model::ColorSet const& rColorSet, SdrObject* pObject, SdrView* pView, SfxUndoManager* pUndoManager = nullptr); - -/// Sends to the LOK updated palettes -SVXCORE_DLLPUBLIC void notifyLOK(std::shared_ptr const& pColorSet, - const std::set& rDocumentColors); } } // end svx namespace diff --git a/include/svx/theme/ThemeColorPaletteManager.hxx b/include/svx/theme/ThemeColorPaletteManager.hxx index a2d45c19f492..98765acd2a8c 100644 --- a/include/svx/theme/ThemeColorPaletteManager.hxx +++ b/include/svx/theme/ThemeColorPaletteManager.hxx @@ -65,7 +65,6 @@ class UNLESS_MERGELIBS(SVXCORE_DLLPUBLIC) ThemeColorPaletteManager final public: ThemeColorPaletteManager(std::shared_ptr const& pColorSet); ThemePaletteCollection generate(); - void generateJSON(tools::JsonWriter& aTree); }; } // end svx namespace diff --git a/include/svx/txencbox.hxx b/include/svx/txencbox.hxx index 15244d72e49e..d219e003c2f9 100644 --- a/include/svx/txencbox.hxx +++ b/include/svx/txencbox.hxx @@ -21,7 +21,6 @@ #include #include -#include #include #include diff --git a/include/svx/uiobject.hxx b/include/svx/uiobject.hxx deleted file mode 100644 index d1cc1c45377a..000000000000 --- a/include/svx/uiobject.hxx +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- 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/. - */ - -#ifndef INCLUDED_SVX_UIOBJECT_HXX -#define INCLUDED_SVX_UIOBJECT_HXX - -#include - -#include - -#include - -class SvxColorValueSet; - -class SvxColorValueSetUIObject final : public DrawingAreaUIObject -{ - SvxColorValueSet* mpColorSet; - -public: - - SvxColorValueSetUIObject(vcl::Window* pColorSetWin); - - virtual void execute(const OUString& rAction, - const StringMap& rParameters) override; - - static std::unique_ptr create(vcl::Window* pWindow); - - virtual StringMap get_state() override; - -private: - - OUString get_name() const override; -}; - - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/unobrushitemhelper.hxx b/include/svx/unobrushitemhelper.hxx index 142008764621..3cdb904129ea 100644 --- a/include/svx/unobrushitemhelper.hxx +++ b/include/svx/unobrushitemhelper.hxx @@ -26,20 +26,27 @@ class SfxItemSet; // Helper function definitions for UNO API fallbacks to replace SvxBrushItem. The // idea is to have fallbacks to create a SvxBrushItem if needed for backwards compatibility -// if needed from the SfxItemSet and vice versa. This is used in cases where e.g. UNO API +// from the SfxItemSet and vice versa. This is used in cases where e.g. UNO API // accesses to slots in the SvxBrushItem are used (see cases in SvxBrushItem::QueryValue // and SvxBrushItem::PutValue as MID_BACK_COLOR and similar). // To make this work, a cycle of creating a SvxBrushItem from a SfxItemSet, changing a value // using PutValue, putting back to the SfxItemSet should create the *same* SvxBrushItem // the next time this will be created using getSvxBrushItemFromSourceSet. For more details, -// see comments at the implementations of that two methods. +// see comments at the implementations of those two methods. // Set the equivalent in the range [XATTR_FILL_FIRST .. XATTR_FILL_LAST] in the given // SfxItemSet to create the same FillStyle as is expressed by the given SvxBrushItem. // This method will reset all items in the XATTR_FILL_* range first. +// rReferer is the name of the document the brush came from, or an empty string when no +// document named it. SVXCORE_DLLPUBLIC void setSvxBrushItemAsFillAttributesToTargetSet( const SvxBrushItem& rBrush, - SfxItemSet& rToSet); + SfxItemSet& rToSet, + OUString const& rReferer); + +// The file name carried by the active document shell, or an empty string when there is no +// active shell or the shell has no file name. +SVXCORE_DLLPUBLIC OUString getActiveDocumentLinkReferer(); // Create a SvxBrushItem as close as possible to the settings in the DrawingLayer // items in the range [XATTR_FILL_FIRST .. XATTR_FILL_LAST]. Since this is not 100% diff --git a/include/svx/unoshprp.hxx b/include/svx/unoshprp.hxx index 358576ac23ce..66b593646d6b 100644 --- a/include/svx/unoshprp.hxx +++ b/include/svx/unoshprp.hxx @@ -200,6 +200,7 @@ #define OWN_ATTR_HYPERLINK (OWN_ATTR_VALUE_START+108) #define OWN_ATTR_MISC_OBJ_DECORATIVE (OWN_ATTR_VALUE_START+109) #define OWN_ATTR_OBJ_ISEMPTYPRESOBJ (OWN_ATTR_VALUE_START+110) +#define OWN_ATTR_MISC_OBJ_HORIZONTAL_RULE (OWN_ATTR_VALUE_START+111) // ATTENTION: current maximum is OWN_ATTR_VALUE_START+120 svx; when adding values, update // OWN_ATTR_VALUE_END in include/svl/solar.hrc accordingly @@ -380,6 +381,7 @@ { UNO_NAME_MISC_OBJ_TITLE, OWN_ATTR_MISC_OBJ_TITLE , ::cppu::UnoType::get(), 0, 0}, \ { UNO_NAME_MISC_OBJ_DESCRIPTION, OWN_ATTR_MISC_OBJ_DESCRIPTION , ::cppu::UnoType::get(), 0, 0}, \ { u"Decorative"_ustr, OWN_ATTR_MISC_OBJ_DECORATIVE, ::cppu::UnoType::get(), 0, 0}, \ + { u"HorizontalRule"_ustr, OWN_ATTR_MISC_OBJ_HORIZONTAL_RULE, ::cppu::UnoType::get(), 0, 0}, \ { UNO_NAME_HYPERLINK, OWN_ATTR_HYPERLINK, ::cppu::UnoType::get(), 0, 0}, \ { u"WritingMode"_ustr, SDRATTR_WRITINGMODE2, ::cppu::UnoType::get(), 0, 0}, @@ -471,6 +473,7 @@ #define SPECIAL_GRAPHOBJ_PROPERTIES \ SPECIAL_GRAPHOBJ_PROPERTIES_DEFAULTS \ { UNO_NAME_GRAPHIC_GRAPHICCROP, SDRATTR_GRAFCROP , ::cppu::UnoType::get(), 0, 0 }, \ + { UNO_NAME_GRAPHIC_GRAPHICCLIPPOLYPOLYGON, SDRATTR_GRAFCLIPPOLYPOLYGON, ::cppu::UnoType::get(), 0, 0 }, \ { UNO_NAME_GRAPHOBJ_REPLACEMENT_GRAPHIC, OWN_ATTR_REPLACEMENT_GRAPHIC, cppu::UnoType::get() , 0, 0}, \ { UNO_NAME_GRAPHOBJ_REPLACEMENT_MODEL , OWN_ATTR_REPLACEMENT_MODEL, cppu::UnoType::get() , 0, 0}, \ { UNO_NAME_GRAPHOBJ_GRAFSTREAMURL, OWN_ATTR_GRAFSTREAMURL , ::cppu::UnoType::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, \ diff --git a/include/svx/xtable.hxx b/include/svx/xtable.hxx index 4819fba2ca3f..2b9f36249d7a 100644 --- a/include/svx/xtable.hxx +++ b/include/svx/xtable.hxx @@ -311,7 +311,6 @@ public: class SVXCORE_DLLPUBLIC XHatchList final : public XPropertyList { private: - Bitmap CreateBitmap(tools::Long nIndex, const Size& rSize) const; virtual Bitmap CreateBitmapForUI(tools::Long nIndex) override; public: XHatchList(const OUString& rPath, const OUString& rReferer); @@ -319,7 +318,7 @@ public: void Replace(std::unique_ptr pEntry, tools::Long nIndex); XHatchEntry* GetHatch(tools::Long nIndex) const; - Bitmap GetBitmapForPreview(tools::Long nIndex, const Size& rSize); + Bitmap CreateBitmap(tools::Long nIndex, const Size& rSize) const; virtual css::uno::Reference< css::container::XNameContainer > createInstance() override; virtual bool Create() override; @@ -328,7 +327,6 @@ public: class SVXCORE_DLLPUBLIC XGradientList final : public XPropertyList { private: - Bitmap CreateBitmap(tools::Long nIndex, const Size& rSize) const; virtual Bitmap CreateBitmapForUI(tools::Long nIndex) override; public: @@ -337,7 +335,7 @@ public: void Replace(std::unique_ptr pEntry, tools::Long nIndex); XGradientEntry* GetGradient(tools::Long nIndex) const; - Bitmap GetBitmapForPreview(tools::Long nIndex, const Size& rSize); + Bitmap CreateBitmap(tools::Long nIndex, const Size& rSize) const; virtual css::uno::Reference< css::container::XNameContainer > createInstance() override; virtual bool Create() override; @@ -346,7 +344,6 @@ public: class SVXCORE_DLLPUBLIC XBitmapList final : public XPropertyList { private: - Bitmap CreateBitmap( tools::Long nIndex, const Size& rSize ) const; virtual Bitmap CreateBitmapForUI(tools::Long nIndex) override; public: @@ -354,7 +351,7 @@ public: : XPropertyList(XPropertyListType::Bitmap, rPath, rReferer) {} XBitmapEntry* GetBitmap(tools::Long nIndex) const; - Bitmap GetBitmapForPreview(tools::Long nIndex, const Size& rSize); + Bitmap CreateBitmap(tools::Long nIndex, const Size& rSize) const; virtual css::uno::Reference< css::container::XNameContainer > createInstance() override; virtual bool Create() override; @@ -363,7 +360,6 @@ public: class SVXCORE_DLLPUBLIC XPatternList final : public XPropertyList { private: - Bitmap CreateBitmap( tools::Long nIndex, const Size& rSize ) const; virtual Bitmap CreateBitmapForUI(tools::Long nIndex) override; public: @@ -371,7 +367,7 @@ public: : XPropertyList(XPropertyListType::Pattern, rPath, rReferer) {} XBitmapEntry* GetBitmap(tools::Long nIndex) const; - Bitmap GetBitmapForPreview(tools::Long nIndex, const Size& rSize); + Bitmap CreateBitmap(tools::Long nIndex, const Size& rSize) const; virtual css::uno::Reference< css::container::XNameContainer > createInstance() override; virtual bool Create() override; diff --git a/include/systools/curlinit.hxx b/include/systools/curlinit.hxx index d97f84a80f8f..26e46d223165 100644 --- a/include/systools/curlinit.hxx +++ b/include/systools/curlinit.hxx @@ -36,7 +36,7 @@ static void InitCurl_easy(CURL* const pCURL) if (path == nullptr) { SAL_WARN("ucb.ucp.webdav.curl", "no OpenSSL CA certificate bundle found"); -#if !defined(EMSCRIPTEN) +#if !defined(__EMSCRIPTEN__) throw css::uno::RuntimeException(u"no OpenSSL CA certificate bundle found"_ustr); #endif } diff --git a/include/test/screenshot_test.hxx b/include/test/screenshot_test.hxx index 480524400478..adce4a8aca54 100644 --- a/include/test/screenshot_test.hxx +++ b/include/test/screenshot_test.hxx @@ -15,7 +15,8 @@ #include #include #include -#include +#include + #include #include diff --git a/include/test/unoapi_test.hxx b/include/test/unoapi_test.hxx index 151ce29247cf..b3ad79cc9009 100644 --- a/include/test/unoapi_test.hxx +++ b/include/test/unoapi_test.hxx @@ -45,6 +45,7 @@ enum class TestFilter DOTX, EPUB, FODG, + FODP, FODS, FODT, HTML_CALC, @@ -64,6 +65,7 @@ enum class TestFilter POTX, PPT, PPTM, + PPSX, PPTX, PPTX_2007, RTF, @@ -92,6 +94,7 @@ const std::unordered_map TestFilterNames{ { TestFilter::DOTX, u"MS Word 2007 XML Template"_ustr }, { TestFilter::EPUB, u"EPUB"_ustr }, { TestFilter::FODG, u"OpenDocument Drawing Flat XML"_ustr }, + { TestFilter::FODP, u"OpenDocument Presentation Flat XML"_ustr }, { TestFilter::FODS, u"OpenDocument Spreadsheet Flat XML"_ustr }, { TestFilter::FODT, u"OpenDocument Text Flat XML"_ustr }, { TestFilter::HTML_CALC, u"HTML (StarCalc)"_ustr }, @@ -111,6 +114,7 @@ const std::unordered_map TestFilterNames{ { TestFilter::POTX, u"Impress Office Open XML Template"_ustr }, { TestFilter::PPT, u"MS PowerPoint 97"_ustr }, { TestFilter::PPTM, u"Impress MS PowerPoint 2007 XML VBA"_ustr }, + { TestFilter::PPSX, u"Impress MS PowerPoint 2007 XML AutoPlay"_ustr }, { TestFilter::PPTX, u"Impress Office Open XML"_ustr }, { TestFilter::PPTX_2007, u"Impress MS PowerPoint 2007 XML"_ustr }, { TestFilter::RTF, u"Rich Text Format"_ustr }, @@ -179,7 +183,9 @@ public: const css::uno::Sequence& rParams = {}, const char* pPassword = nullptr); - std::unique_ptr parsePDFExport(const OString& rPassword = OString()); + std::unique_ptr + parsePDFExport(const std::shared_ptr& rPDFium, + const OString& rPassword = OString()); void createTempCopy(std::u16string_view fileName); diff --git a/include/test/xmltesttools.hxx b/include/test/xmltesttools.hxx index b60da3a09fe2..291c7bee377e 100644 --- a/include/test/xmltesttools.hxx +++ b/include/test/xmltesttools.hxx @@ -32,6 +32,8 @@ public: static xmlDocUniquePtr dumpAndParse(const MetafileXmlDump& rDumper, const GDIMetaFile& rGDIMetaFile); static xmlDocUniquePtr dumpAndParse(const GDIMetaFile& rGDIMetaFile); // using default dumper + static void dumpToFile(const MetafileXmlDump& rDumper, const + GDIMetaFile& rGDIMetaFile, const OUString& rFileName); protected: XmlTestTools(); diff --git a/include/toolkit/controls/unocontrol.hxx b/include/toolkit/controls/unocontrol.hxx index b406a728ff83..a76d74383f6a 100644 --- a/include/toolkit/controls/unocontrol.hxx +++ b/include/toolkit/controls/unocontrol.hxx @@ -32,8 +32,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include @@ -60,12 +61,11 @@ struct UnoControlComponentInfos struct UnoControl_Data; -typedef ::cppu::WeakAggImplHelper9 < css::awt::XControl +typedef ::cppu::WeakAggImplHelper8 < css::awt::XControl , css::awt::XWindow2 , css::awt::XView , css::beans::XPropertiesChangeListener , css::lang::XServiceInfo - , css::accessibility::XAccessible , css::util::XModeChangeBroadcaster , css::awt::XUnitConversion , css::awt::XStyleSettingsSupplier @@ -92,8 +92,8 @@ protected: css::uno::Reference< css::awt::XControlModel > mxModel; css::uno::Reference< css::awt::XGraphics > mxGraphics; - css::uno::WeakReferenceHelper - maAccessibleContext; /// our most recent XAccessibleContext instance + /// our most recent accessible + unotools::WeakReference mpAccessible; bool mbDisposePeer; bool mbRefreshingPeer; @@ -118,8 +118,7 @@ protected: void ImplLockPropertyChangeNotification( const OUString& rPropertyName, bool bLock ); void ImplLockPropertyChangeNotifications( const css::uno::Sequence< OUString >& rPropertyNames, bool bLock ); - void DisposeAccessibleContext(css::uno::Reference< - css::lang::XComponent> const& xContext); + void DisposeAccessibleContext(const rtl::Reference& rpAccessible); void setPeer( const css::uno::Reference< css::awt::XVclWindowPeer >& _xPeer) { @@ -199,9 +198,6 @@ public: sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; - // XAccessible - virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override; - // XModeChangeBroadcaster virtual void SAL_CALL addModeChangeListener( const css::uno::Reference< css::util::XModeChangeListener >& _rxListener ) override; virtual void SAL_CALL removeModeChangeListener( const css::uno::Reference< css::util::XModeChangeListener >& _rxListener ) override; @@ -217,6 +213,7 @@ public: // XStyleSettingsSupplier virtual css::uno::Reference< css::awt::XStyleSettings > SAL_CALL getStyleSettings() override; + rtl::Reference getAccessible(); css::uno::Reference< css::awt::XVclWindowPeer > getVclWindowPeer(); protected: diff --git a/include/tools/color.hxx b/include/tools/color.hxx index e2834dad5fdb..473eb1a297b3 100644 --- a/include/tools/color.hxx +++ b/include/tools/color.hxx @@ -28,11 +28,6 @@ namespace color { -constexpr sal_uInt32 extractRGB(sal_uInt32 nColorNumber) -{ - return nColorNumber & 0x00FFFFFF; -} - constexpr sal_uInt8 ColorChannelMerge(sal_uInt8 nDst, sal_uInt8 nSrc, sal_uInt8 nSrcTrans) { return sal_uInt8(((sal_Int32(nDst) - nSrc) * nSrcTrans + ((nSrc << 8) | nDst)) >> 8); diff --git a/include/tools/cpuid.hxx b/include/tools/cpuid.hxx index 4f309ff11e96..e8207d63b046 100644 --- a/include/tools/cpuid.hxx +++ b/include/tools/cpuid.hxx @@ -62,41 +62,6 @@ TOOLS_DLLPUBLIC bool isCpuInstructionSetSupported(InstructionSetFlags eInstructi */ TOOLS_DLLPUBLIC OUString instructionSetSupportedString(); -/** Check if SSE2 is supported by the CPU - */ -inline bool hasSSE2() -{ - return isCpuInstructionSetSupported(InstructionSetFlags::SSE2); -} - -/** Check if SSSE3 is supported by the CPU - */ -inline bool hasSSSE3() -{ - return isCpuInstructionSetSupported(InstructionSetFlags::SSSE3); -} - -/** Check if AVX is supported by the CPU - */ -inline bool hasAVX() -{ - return isCpuInstructionSetSupported(InstructionSetFlags::AVX); -} - -/** Check if AVX2 is supported by the CPU - */ -inline bool hasAVX2() -{ - return isCpuInstructionSetSupported(InstructionSetFlags::AVX2); -} - -/** Check if AVX512F is supported by the CPU - */ -inline bool hasAVX512F() -{ - return isCpuInstructionSetSupported(InstructionSetFlags::AVX512F); -} - /** Check if Hyper Threading is supported */ inline bool hasHyperThreading() diff --git a/include/tools/fract.hxx b/include/tools/fract.hxx index 0eb3ba2694ff..b01b49d49945 100644 --- a/include/tools/fract.hxx +++ b/include/tools/fract.hxx @@ -70,12 +70,6 @@ public: void ReduceInaccurate( unsigned nSignificantBits ); - /// Multiply the two fractions represented here and reduce inaccuracy to 32-bits, used by vcl - static Fraction MakeFraction(tools::Long nN1, tools::Long nN2, tools::Long nD1, tools::Long nD2); - - // Compute value usable as hash. - size_t GetHashValue() const; - TOOLS_DLLPUBLIC friend Fraction operator+( const Fraction& rVal1, const Fraction& rVal2 ); TOOLS_DLLPUBLIC friend Fraction operator-( const Fraction& rVal1, const Fraction& rVal2 ); TOOLS_DLLPUBLIC friend Fraction operator*( const Fraction& rVal1, const Fraction& rVal2 ); diff --git a/include/tools/json_writer.hxx b/include/tools/json_writer.hxx index 2977f7f8c231..3fbcab4686a7 100644 --- a/include/tools/json_writer.hxx +++ b/include/tools/json_writer.hxx @@ -20,7 +20,7 @@ * * (1) Minimal allocations/re-allocations/copying * (2) Small/simple JSON documents - * (3) ascii property names + * (3) ASCII property names */ namespace tools { @@ -52,16 +52,12 @@ public: void put(std::u16string_view pPropName, std::u16string_view rPropValue); void put(std::string_view pPropName, const OUString& rPropValue); - // Assumes utf-8 property value encoding + // Assumes UTF-8 property value encoding void put(std::string_view pPropName, std::string_view rPropValue); void put(std::string_view pPropName, const char* pPropVal) { put(pPropName, std::string_view(pPropVal)); } - template void put(std::string_view pPropName, const char (&pPropVal)[N]) - { - put(pPropName, std::string_view(pPropVal, N)); - } template , int> = 0> void put(std::string_view pPropName, N n) diff --git a/include/tools/multisel.hxx b/include/tools/multisel.hxx index edb572acb18e..e485c4c882ae 100644 --- a/include/tools/multisel.hxx +++ b/include/tools/multisel.hxx @@ -22,7 +22,6 @@ #include #include -#include #include #include diff --git a/include/tools/urlobj.hxx b/include/tools/urlobj.hxx index 33af8104dc0f..92bf58dc4e24 100644 --- a/include/tools/urlobj.hxx +++ b/include/tools/urlobj.hxx @@ -425,8 +425,6 @@ public: bool SetUser(std::u16string_view rTheUser) { return setUser(rTheUser, RTL_TEXTENCODING_UTF8); } - inline bool SetPass(std::u16string_view rThePassword); - // Host and Port: bool HasPort() const { return m_aPort.isPresent(); } @@ -441,9 +439,6 @@ public: sal_uInt32 GetPort() const; - bool SetHost(std::u16string_view rTheHost) - { return setHost(rTheHost, RTL_TEXTENCODING_UTF8); } - bool SetPort(sal_uInt32 nThePort); // Path: @@ -1046,10 +1041,6 @@ private: EncodeMechanism eMechanism, rtl_TextEncoding eCharset, bool bNetBiosName, OUStringBuffer* pCanonic); - bool setHost( - std::u16string_view rTheHost, - rtl_TextEncoding eCharset); - // Path: TOOLS_DLLPRIVATE static bool parsePath( @@ -1253,13 +1244,6 @@ inline bool INetURLObject::translateToInternal(std::u16string_view eDecodeMechanism, eCharset); } -inline bool INetURLObject::SetPass(std::u16string_view rThePassword) -{ - return rThePassword.empty() ? - clearPassword() : - setPassword(rThePassword, RTL_TEXTENCODING_UTF8); -} - inline bool INetURLObject::SetParam(std::u16string_view rTheQuery, EncodeMechanism eMechanism, rtl_TextEncoding eCharset) diff --git a/include/uno/sequence2.h b/include/uno/sequence2.h index bf74a6170d1e..7d2df662f2ad 100644 --- a/include/uno/sequence2.h +++ b/include/uno/sequence2.h @@ -74,7 +74,7 @@ CPPU_DLLPUBLIC void SAL_CALL uno_type_sequence_assign( @param len number of elements @param acquire function called each time an interface needs to be acquired; defaults (0) to uno - @return false, if memoray allocation has failed + @return false, if memory allocation has failed */ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_sequence_construct( uno_Sequence ** ppSequence, @@ -91,7 +91,7 @@ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_sequence_construct( @param len number of elements @param acquire function called each time an interface needs to be acquired; defaults (0) to uno - @return false, if memoray allocation has failed + @return false, if memory allocation has failed */ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_type_sequence_construct( uno_Sequence ** ppSequence, @@ -110,7 +110,7 @@ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_type_sequence_construct( be acquired; defaults (0) to uno @param release function called each time an interface needs to be released; defaults (0) to uno - @return false, if memoray allocation has failed + @return false, if memory allocation has failed */ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_sequence_reference2One( uno_Sequence ** ppSequence, @@ -128,7 +128,7 @@ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_sequence_reference2One( be acquired; defaults (0) to uno @param release function called each time an interface needs to be released; defaults (0) to uno - @return false, if memoray allocation has failed + @return false, if memory allocation has failed */ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_type_sequence_reference2One( uno_Sequence ** ppSequence, @@ -147,7 +147,7 @@ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_type_sequence_reference2One( be acquired; defaults (0) to uno @param release function called each time an interface needs to be released; defaults (0) to uno - @return false, if memoray allocation has failed + @return false, if memory allocation has failed */ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_sequence_realloc( uno_Sequence ** ppSequence, @@ -166,7 +166,7 @@ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_sequence_realloc( be acquired; defaults (0) to uno @param release function called each time an interface needs to be released; defaults (0) to uno - @return false, if memoray allocation has failed + @return false, if memory allocation has failed */ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_type_sequence_realloc( uno_Sequence ** ppSequence, @@ -180,7 +180,7 @@ CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_type_sequence_realloc( @param sequence must be non-null, sequence->nRefCount must be zero @param type the type of the sequence, must be non-null - @param release function called each time an interface needs to be release, + @param release function called each time an interface needs to be released, must be non-null @since LibreOffice 4.4 diff --git a/include/unotools/accessiblerelationsethelper.hxx b/include/unotools/accessiblerelationsethelper.hxx index affb859a2fb1..f2737b5b5dda 100644 --- a/include/unotools/accessiblerelationsethelper.hxx +++ b/include/unotools/accessiblerelationsethelper.hxx @@ -64,7 +64,7 @@ public: the given index. @param nIndex - This index specifies the relatio to return. + This index specifies the relation to return. @return For a valid index, i.e. inside the range 0 to the number of @@ -94,7 +94,7 @@ public: The type of the relation to return. @return - If a relation with the given type could be found than (a copy + If a relation with the given type could be found then (a copy of) this relation is returned. Otherwise a relation with the type INVALID is returned. */ diff --git a/include/unotools/charclass.hxx b/include/unotools/charclass.hxx index 00fb7b80e028..92487dfd5ba3 100644 --- a/include/unotools/charclass.hxx +++ b/include/unotools/charclass.hxx @@ -97,15 +97,6 @@ public: ((nType & ~nCharClassNumericTypeMask) == 0); } - /// whether type is pure alphanumeric or not, e.g. return of getCharacterType() - static bool isAlphaNumericType( sal_Int32 nType ) - { - return ((nType & (nCharClassAlphaType | - nCharClassNumericType)) != 0) && - ((nType & ~(nCharClassAlphaTypeMask | - nCharClassNumericTypeMask)) == 0); - } - /// whether type is pure letter or not, e.g. return of getCharacterType() static bool isLetterType( sal_Int32 nType ) { diff --git a/include/unotools/confignode.hxx b/include/unotools/confignode.hxx index c3ad98f626dd..0582e29e2d62 100644 --- a/include/unotools/confignode.hxx +++ b/include/unotools/confignode.hxx @@ -205,7 +205,6 @@ namespace utl @param _rxConfProvider configuration provider to use when retrieving the node. @param _rPath path to the node the object should represent - @param _nDepth depth for node retrieval @param _eMode specifies which privileges should be applied when retrieving the node @see createWithServiceFactory @@ -213,7 +212,6 @@ namespace utl static OConfigurationTreeRoot createWithProvider( const css::uno::Reference< css::lang::XMultiServiceFactory >& _rxConfProvider, const OUString& _rPath, - sal_Int32 _nDepth, CREATION_MODE _eMode ); @@ -226,11 +224,10 @@ namespace utl @see createWithProvider @param _rxContext service factory to use to create the configuration provider. @param _rPath path to the node the object should represent - @param _nDepth depth for node retrieval @param _eMode specifies which privileges should be applied when retrieving the node */ static OConfigurationTreeRoot createWithComponentContext(const css::uno::Reference< css::uno::XComponentContext >& _rxContext, - const OUString& _rPath, sal_Int32 _nDepth = -1, CREATION_MODE _eMode = CM_UPDATABLE); + const OUString& _rPath, CREATION_MODE _eMode = CM_UPDATABLE); /** tolerant version of the createWithServiceFactory @@ -239,7 +236,7 @@ namespace utl given node path does not exist) are still asserted.

        */ static OConfigurationTreeRoot tryCreateWithComponentContext( const css::uno::Reference< css::uno::XComponentContext >& rxContext, - const OUString& _rPath, sal_Int32 _nDepth = -1, CREATION_MODE _eMode = CM_UPDATABLE ); + const OUString& _rPath, CREATION_MODE _eMode = CM_UPDATABLE ); /** commit all changes made on the subtree the object is the root for

        All changes made on any OConfigurationNode object retrieved (maybe indirect) from this root diff --git a/include/unotools/configvaluecontainer.hxx b/include/unotools/configvaluecontainer.hxx index aa6b14534f4c..df5123b6038f 100644 --- a/include/unotools/configvaluecontainer.hxx +++ b/include/unotools/configvaluecontainer.hxx @@ -78,14 +78,11 @@ namespace utl @param _nAccessFlags specifies different aspects of the configuration aspect to be created, e.g. it's update mode etc.
        See the CVC_xxx constants for what you can use here. - @param _nLevels - specifies the number of levels to access under the node given by _pConfigLocation */ OConfigurationValueContainer( const css::uno::Reference< css::uno::XComponentContext >& _rxORB, std::mutex& _rAccessSafety, - const OUString& _rConfigLocation, - const sal_Int32 _nLevels + const OUString& _rConfigLocation ); /// dtor @@ -139,8 +136,7 @@ namespace utl private: /// implements the ctors void implConstruct( - const OUString& _rConfigLocation, - const sal_Int32 _nLevels + const OUString& _rConfigLocation ); /// registers a value container diff --git a/include/unotools/linguprops.hxx b/include/unotools/linguprops.hxx index 3130157a5a3b..320da4f56d4f 100644 --- a/include/unotools/linguprops.hxx +++ b/include/unotools/linguprops.hxx @@ -50,6 +50,7 @@ inline constexpr OUString UPN_HYPH_ZONE_SPREAD = u"HyphZoneSpread inline constexpr OUString UPN_HYPH_KEEP = u"HyphKeep"_ustr; inline constexpr OUString UPN_HYPH_KEEP_TYPE = u"HyphKeepType"_ustr; inline constexpr OUString UPN_HYPH_KEEP_LINE = u"HyphKeepLine"_ustr; +inline constexpr OUString UPN_HYPH_LEVEL = u"HyphKeepLevel"_ustr; // UNO property names for Lingu // (those not covered by the SpellChecker and Hyphenator @@ -125,6 +126,7 @@ inline constexpr OUString UPN_IS_GRAMMAR_INTERACTIVE = u"IsInteractiveG #define UPH_HYPH_COMPOUND_MIN_LEADING 40 #define UPH_HYPH_COMPOUND_MIN_TRAILING 41 #define UPH_HYPH_KEEP_LINE 42 +#define UPH_HYPH_LEVEL 43 #ifdef __GNUC__ #pragma GCC diagnostic pop diff --git a/include/unotools/localedatawrapper.hxx b/include/unotools/localedatawrapper.hxx index c667691d7d56..c3d1a11f1e30 100644 --- a/include/unotools/localedatawrapper.hxx +++ b/include/unotools/localedatawrapper.hxx @@ -246,8 +246,6 @@ public: { return getOneLocaleItem( css::i18n::LocaleItem::LONG_DATE_DAY_SEPARATOR ); } const OUString& getLongDateMonthSep() const { return getOneLocaleItem( css::i18n::LocaleItem::LONG_DATE_MONTH_SEPARATOR ); } - const OUString& getLongDateYearSep() const - { return getOneLocaleItem( css::i18n::LocaleItem::LONG_DATE_YEAR_SEPARATOR ); } /** A wrapper around rtl::math::stringToDouble() using the locale dependent decimal separator, group separator, and if needed decimal separator diff --git a/include/unotools/tempfile.hxx b/include/unotools/tempfile.hxx index 6496af78a219..5603e24bbf17 100644 --- a/include/unotools/tempfile.hxx +++ b/include/unotools/tempfile.hxx @@ -279,14 +279,14 @@ The extension string may be f.e. ".txt" or "", if no extension string is given, @param pExtension String representing filename extension @param bCreateParentDirs If rLeadingChars contains a slash, this will create the required parent directories. - @param concatFunc Optional parameter to change the way the counter is added onto the character. + @param rConcatFunc Optional parameter to change the way the counter is added onto the character. Default is to just add the number immediately after the name, e.g. "abc0" "abc1" etc. */ UNOTOOLS_DLLPUBLIC OUString CreateTempURL( std::u16string_view rLeadingChars, bool _bStartWithZero = true, std::u16string_view pExtension = {}, const OUString* pParent = nullptr, bool bCreateParentDirs = false, - std::function concatFunc + const std::function& rConcatFunc = [](OUString aName, OUString token) -> OUString { return aName + token; }); /** diff --git a/include/unotools/useroptions.hxx b/include/unotools/useroptions.hxx index a50b53c352ce..02fe7725f2b7 100644 --- a/include/unotools/useroptions.hxx +++ b/include/unotools/useroptions.hxx @@ -79,8 +79,6 @@ public: OUString GetSigningKey () const; OUString GetEncryptionKey () const; bool GetEncryptToSelf () const; - OUString GetSigningKeyDisplayName () const; - OUString GetEncryptionKeyDisplayName () const; OUString GetFullName () const; diff --git a/include/vbahelper/vbaeventshelperbase.hxx b/include/vbahelper/vbaeventshelperbase.hxx index e1fd3f14bac9..d60c23f440b6 100644 --- a/include/vbahelper/vbaeventshelperbase.hxx +++ b/include/vbahelper/vbaeventshelperbase.hxx @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -44,13 +45,13 @@ namespace com::sun::star { class SfxObjectShell; -typedef ::cppu::WeakImplHelper< +typedef ::cppu::WeakComponentImplHelper< css::script::vba::XVBAEventProcessor, css::document::XEventListener, css::util::XChangesListener, css::lang::XServiceInfo > VbaEventsHelperBase_BASE; -class VBAHELPER_DLLPUBLIC VbaEventsHelperBase : public VbaEventsHelperBase_BASE +class VBAHELPER_DLLPUBLIC VbaEventsHelperBase : public cppu::BaseMutex, public VbaEventsHelperBase_BASE { public: VbaEventsHelperBase( @@ -69,9 +70,13 @@ public: // lang::XEventListener virtual void SAL_CALL disposing( const css::lang::EventObject& rEvent ) override; + using WeakComponentImplHelperBase::disposing; sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override; + // ::cppu::OComponentHelper + virtual void SAL_CALL disposing() override; + // little helpers --------------------------------------------------------- bool hasModule(const OUString& rModuleName); @@ -217,7 +222,6 @@ private: EventHandlerPathMap maEventPaths; css::uno::Reference< css::script::vba::XVBAModuleInfo > mxModuleInfos; OUString maLibraryName; - bool mbDisposed; }; diff --git a/include/vcl/BitmapInfoAccess.hxx b/include/vcl/BitmapInfoAccess.hxx index dece92e76a2d..68da38efd344 100644 --- a/include/vcl/BitmapInfoAccess.hxx +++ b/include/vcl/BitmapInfoAccess.hxx @@ -151,7 +151,6 @@ public: : moAccess(rBitmap) { } - BitmapScopedInfoAccess() {} BitmapScopedInfoAccess& operator=(const Bitmap& rBitmap) { diff --git a/include/vcl/BitmapTools.hxx b/include/vcl/BitmapTools.hxx index 27b78ceb230d..21687e86bf47 100644 --- a/include/vcl/BitmapTools.hxx +++ b/include/vcl/BitmapTools.hxx @@ -17,8 +17,12 @@ #if ENABLE_CAIRO_CANVAS #include #endif +#include #include #include +#include +#include +#include class AlphaMask; class BitmapColor; @@ -44,6 +48,31 @@ VCL_DLLPUBLIC lookup_table const & get_unpremultiply_table(); VCL_DLLPUBLIC sal_uInt8 unpremultiply(sal_uInt8 c, sal_uInt8 a); VCL_DLLPUBLIC sal_uInt8 premultiply(sal_uInt8 c, sal_uInt8 a); +/** Byte offsets of channels within a 4-byte pixel. */ +struct ScanlineChannelOffsets +{ + sal_uInt8 nBlue; + sal_uInt8 nGreen; + sal_uInt8 nRed; + sal_uInt8 nAlpha; +}; + +/** For a premultiplied 32-bit truecolor scanline format (ABGR/ARGB/BGRA/RGBA), return the byte offsets */ +VCL_DLLPUBLIC std::optional +get32BitTcChannelOffsets(ScanlineFormat eFormat); + +/** Reduce an index modulo nEntryCount, so the result is below nEntryCount. + + A count of zero has no valid index to give, so the index comes back as it came in. +*/ +sal_uInt8 sanitizePaletteIndex(sal_uInt8 nIndex, std::size_t nEntryCount); + +/** The colour that nIndex names in rvPalette, with the index reduced to fit the palette. + + An empty palette names no colour, so black stands in. +*/ +const Color& sanitizedPaletteColor(std::vector const& rvPalette, sal_uInt8 nIndex); + Bitmap VCL_DLLPUBLIC loadFromName(const OUString& rFileName, const ImageLoadFlags eFlags = ImageLoadFlags::NONE); void loadFromSvg(SvStream& rStream, const OUString& sPath, Bitmap& rBitmap, double fScaleFactor); @@ -61,7 +90,9 @@ Bitmap VCL_DLLPUBLIC CreateFromData(sal_uInt8 const *pData, sal_Int8 nBitsPerPixel, bool bReversColors = false, bool bReverseAlpha = false); +#if defined(_WIN32) && !USE_HEADLESS_CODE void VCL_DLLPUBLIC fillWithData(sal_uInt8* pData, Bitmap const& rBitmap); +#endif Bitmap VCL_DLLPUBLIC CreateFromData( RawBitmap && data ); @@ -81,7 +112,7 @@ VCL_DLLPUBLIC void DrawAndClipBitmap(const Point& rPos, const Size& rSize, const VCL_DLLPUBLIC css::uno::Sequence< sal_Int8 > GetMaskDIB(Bitmap const & aBmp); /** - * @param data will be filled with alpha data, if xBitmap is alpha/transparent image + * @param data will be filled with alpha data, if rBitmap is an alpha/transparent image * @param bHasAlpha will be set to true if resulting surface has alpha **/ VCL_DLLPUBLIC void CanvasCairoExtractBitmapData( Bitmap const & rBitmap, unsigned char*& data, bool& bHasAlpha, tools::Long& rnWidth, tools::Long& rnHeight ); diff --git a/include/vcl/InterimItemWindow.hxx b/include/vcl/InterimItemWindow.hxx index 4d21244df6c1..a65e8e6ee80f 100644 --- a/include/vcl/InterimItemWindow.hxx +++ b/include/vcl/InterimItemWindow.hxx @@ -43,7 +43,7 @@ public: bool ControlHasFocus() const; - virtual void Draw(OutputDevice* pDevice, const Point& rPos, + virtual void Draw(OutputDevice& rDevice, const Point& rPos, SystemTextColorFlags nFlags) override; void SetPriority(TaskPriority nPriority); @@ -55,7 +55,7 @@ protected: // of this control on reaching pass the last child. This is suitable when // the Control is the toplevel control and has no siblings or parent InterimItemWindow(vcl::Window* pParent, const OUString& rUIXMLDescription, const OUString& rID, - bool bAllowCycleFocusOut = true, sal_uInt64 nLOKWindowId = 0); + bool bAllowCycleFocusOut = true); void InitControlBase(weld::Widget* pWidget); @@ -84,7 +84,7 @@ private: DECL_DLLPRIVATE_LINK(DoLayout, Timer*, void); - virtual void ImplPaintToDevice(::OutputDevice* pTargetOutDev, const Point& rPos) override; + virtual void ImplPaintToDevice(OutputDevice& rTargetOutDev, const Point& rPos) override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/Platform.hxx b/include/vcl/Platform.hxx index 279fdf760f78..08ec1be1c19a 100644 --- a/include/vcl/Platform.hxx +++ b/include/vcl/Platform.hxx @@ -15,6 +15,7 @@ enum class Platform Xcb, WASM, Windows, + Mac, Other }; diff --git a/include/vcl/TaskStopwatch.hxx b/include/vcl/TaskStopwatch.hxx index b27b3a316abe..9991f7f994c8 100644 --- a/include/vcl/TaskStopwatch.hxx +++ b/include/vcl/TaskStopwatch.hxx @@ -93,23 +93,6 @@ public: m_nStartTicks = tools::Time::GetSystemTicks(); m_nIterStartTicks = m_nStartTicks; } - - /** - * Sets the input events, which should also "exceed" the stopwatch. - * - * Per default this ignores the VclInputFlags::TIMER. - */ - void setInputStop(VclInputFlags eInputStop = eDefaultInputStop) { m_eInputStop = eInputStop; } - VclInputFlags inputStop() const { return m_eInputStop; } - - /** - * Sets the time considered the acceptable maximum for a task to run - * - * This is an orientation for long time background jobs to yield to - * the scheduler, so Idle task don't starve each other too much. - **/ - static unsigned int timeSlice() { return m_nTimeSlice; } - static void setTimeSlice(unsigned int nTimeSlice) { m_nTimeSlice = nTimeSlice; } }; #endif // INCLUDED_VCL_TASK_STOPWATCH_HXX diff --git a/include/vcl/WeldedTabbedNotebookbar.hxx b/include/vcl/WeldedTabbedNotebookbar.hxx deleted file mode 100644 index 1f3448c7a219..000000000000 --- a/include/vcl/WeldedTabbedNotebookbar.hxx +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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/. - */ - -#ifndef INCLUDED_SFX2_NOTEBOOKBAR_WRITERTABBEDNOTEBOOKBAR_HXX -#define INCLUDED_SFX2_NOTEBOOKBAR_WRITERTABBEDNOTEBOOKBAR_HXX - -#include -#include -#include -#include -#include -#include - -namespace com::sun::star::frame -{ -class XFrame; -} - -/** - * Welded wrapper for NotebookBar used for online -*/ -class UNLESS_MERGELIBS(VCL_DLLPUBLIC) WeldedTabbedNotebookbar -{ - std::unique_ptr m_xBuilder; - - std::unique_ptr m_xContainer; - std::unique_ptr m_xWeldedToolbar; - -public: - WeldedTabbedNotebookbar(const VclPtr& pContainerWindow, - const OUString& rUIFilePath, - const css::uno::Reference& rFrame, - sal_uInt64 nWindowId); - - weld::Toolbar& getWeldedToolbar() { return *m_xWeldedToolbar; } - weld::Builder& getBuilder() { return *m_xBuilder; } -}; - -#endif // INCLUDED_SFX2_NOTEBOOKBAR_SFXNOTEBOOKBAR_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/abstdlg.hxx b/include/vcl/abstdlg.hxx index 7c0f1f732c6f..07aaff8c612b 100644 --- a/include/vcl/abstdlg.hxx +++ b/include/vcl/abstdlg.hxx @@ -43,7 +43,7 @@ namespace weld /** * Some things multiple-inherit from VclAbstractDialog and OutputDevice, -* so we need to use virtual inheritance to keep the referencing counting +* so we need to use virtual inheritance to keep the reference counting * OK. */ class VCL_DLLPUBLIC VclAbstractDialog : public virtual VclReferenceBase @@ -157,16 +157,6 @@ protected: virtual ~AbstractDiagramDialog() override = default; }; -class VCL_DLLPUBLIC AbstractQueryDialog : public VclAbstractDialog -{ -protected: - virtual ~AbstractQueryDialog() override = default; -public: - virtual bool ShowAgain() const = 0; - virtual void SetYesLabel(const OUString& sLabel) = 0; - virtual void SetNoLabel(const OUString& sLabel) = 0; -}; - class VCL_DLLPUBLIC VclAbstractDialogFactory { public: @@ -210,11 +200,6 @@ public: weld::Window* pParent, SdrObjGroup& rDiagram) = 0; - virtual VclPtr CreateQueryDialog( - weld::Window* pParent, - const OUString& sTitle, const OUString& sText, const OUString& sQuestion, - bool bShowAgain) = 0; - #ifdef _WIN32 virtual VclPtr CreateFileExtCheckDialog(weld::Window* _pParent, const OUString& sTitle, const OUString& sMsg) diff --git a/include/vcl/accessibility/AccessibleBrowseBox.hxx b/include/vcl/accessibility/AccessibleBrowseBox.hxx index 75c7750e6c98..dc12519e2d61 100644 --- a/include/vcl/accessibility/AccessibleBrowseBox.hxx +++ b/include/vcl/accessibility/AccessibleBrowseBox.hxx @@ -70,13 +70,6 @@ protected: /** Grabs the focus to the BrowseBox. */ virtual void SAL_CALL grabFocus() override; - // XServiceInfo - - /** @return - The name of this class. - */ - virtual OUString SAL_CALL getImplementationName() override; - public: // helper functions /** commitHeaderBarEvent commit the event at all listeners of the column/row header bar diff --git a/include/vcl/accessibility/AccessibleBrowseBoxBase.hxx b/include/vcl/accessibility/AccessibleBrowseBoxBase.hxx index d8093eb1c721..d640632c4414 100644 --- a/include/vcl/accessibility/AccessibleBrowseBoxBase.hxx +++ b/include/vcl/accessibility/AccessibleBrowseBoxBase.hxx @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -42,8 +41,7 @@ namespace vcl { /** The BrowseBox accessible objects inherit from this base class. It implements basic functionality for various Accessibility interfaces. */ class VCL_DLLPUBLIC AccessibleBrowseBoxBase - : public cppu::ImplInheritanceHelper + : public cppu::ImplInheritanceHelper { public: /** Constructor sets specified name and description. If the constant of a @@ -143,17 +141,6 @@ public: */ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& rPoint ) override; - // XServiceInfo - - /** @return Whether the specified service is supported by this class. */ - virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) override; - - /** @return A list of all supported services. */ - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; - - /* Derived classes have to implement: - - getImplementationName. */ - // helper methods /** @return The BrowseBox object type. */ diff --git a/include/vcl/accessibility/AccessibleBrowseBoxCheckBoxCell.hxx b/include/vcl/accessibility/AccessibleBrowseBoxCheckBoxCell.hxx index 5e9ec10d7540..dad8d3af1858 100644 --- a/include/vcl/accessibility/AccessibleBrowseBoxCheckBoxCell.hxx +++ b/include/vcl/accessibility/AccessibleBrowseBoxCheckBoxCell.hxx @@ -47,7 +47,6 @@ public: // XAccessibleContext virtual sal_Int64 SAL_CALL getAccessibleChildCount( ) override; virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int64 i ) override; - virtual OUString SAL_CALL getImplementationName() override; virtual sal_Int64 SAL_CALL getAccessibleIndexInParent( ) override; diff --git a/include/vcl/accessibility/AccessibleBrowseBoxHeaderBar.hxx b/include/vcl/accessibility/AccessibleBrowseBoxHeaderBar.hxx index c7203159bd27..b92f0f46ae92 100644 --- a/include/vcl/accessibility/AccessibleBrowseBoxHeaderBar.hxx +++ b/include/vcl/accessibility/AccessibleBrowseBoxHeaderBar.hxx @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -38,10 +39,9 @@ public: @param rBrowseBox The BrowseBox control. @param eObjType One of the two allowed types AccessibleBrowseBoxObjType::RowHeaderBar or AccessibleBrowseBoxObjType::ColumnHeaderBar. */ - AccessibleBrowseBoxHeaderBar( - const css::uno::Reference< css::accessibility::XAccessible >& rxParent, - ::vcl::IAccessibleTableProvider& rBrowseBox, - AccessibleBrowseBoxObjType eObjType ); + AccessibleBrowseBoxHeaderBar(const rtl::Reference& rpParent, + ::vcl::IAccessibleTableProvider& rBrowseBox, + AccessibleBrowseBoxObjType eObjType); private: virtual ~AccessibleBrowseBoxHeaderBar() override; @@ -130,11 +130,6 @@ public: /** Removes the specified row/column from the selection. */ virtual void SAL_CALL deselectAccessibleChild( sal_Int64 nSelectedChildIndex ) override; - // XServiceInfo - - /** @return The name of this class. */ - virtual OUString SAL_CALL getImplementationName() override; - private: // internal virtual methods diff --git a/include/vcl/accessibility/AccessibleBrowseBoxHeaderCell.hxx b/include/vcl/accessibility/AccessibleBrowseBoxHeaderCell.hxx index 545f9a55f334..d5f9d61c832a 100644 --- a/include/vcl/accessibility/AccessibleBrowseBoxHeaderCell.hxx +++ b/include/vcl/accessibility/AccessibleBrowseBoxHeaderCell.hxx @@ -26,9 +26,9 @@ class VCL_DLLPUBLIC AccessibleBrowseBoxHeaderCell final : public AccessibleBrows sal_Int32 m_nColumnRowId; public: AccessibleBrowseBoxHeaderCell(sal_Int32 _nColumnRowId, - const css::uno::Reference< css::accessibility::XAccessible >& rxParent, - ::vcl::IAccessibleTableProvider& _rBrowseBox, - AccessibleBrowseBoxObjType _eObjType); + const rtl::Reference& rpParent, + ::vcl::IAccessibleTableProvider& _rBrowseBox, + AccessibleBrowseBoxObjType _eObjType); /** @return The count of visible children. */ virtual sal_Int64 SAL_CALL getAccessibleChildCount() override; @@ -47,11 +47,6 @@ public: return getType() == AccessibleBrowseBoxObjType::RowHeaderCell; } - /** @return - The name of this class. - */ - virtual OUString SAL_CALL getImplementationName() override; - /** Return a bitset of states of the current object. */ sal_Int64 implCreateStateSet() override; diff --git a/include/vcl/accessibility/AccessibleBrowseBoxTable.hxx b/include/vcl/accessibility/AccessibleBrowseBoxTable.hxx index f1040f47eb32..e1a0f0eb6a30 100644 --- a/include/vcl/accessibility/AccessibleBrowseBoxTable.hxx +++ b/include/vcl/accessibility/AccessibleBrowseBoxTable.hxx @@ -28,9 +28,8 @@ class AccessibleBrowseBoxTable : public AccessibleBrowseBoxTableBase { public: - AccessibleBrowseBoxTable( - const css::uno::Reference< css::accessibility::XAccessible >& rxParent, - ::vcl::IAccessibleTableProvider& rBrowseBox ); + AccessibleBrowseBoxTable(const rtl::Reference& rpParent, + ::vcl::IAccessibleTableProvider& rBrowseBox); protected: virtual ~AccessibleBrowseBoxTable() override; @@ -92,11 +91,6 @@ public: /** @return TRUE, if the specified cell is selected. */ virtual sal_Bool SAL_CALL isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn ) override; - // XServiceInfo - - /** @return The name of this class. */ - virtual OUString SAL_CALL getImplementationName() override; - protected: // internal virtual methods diff --git a/include/vcl/accessibility/AccessibleBrowseBoxTableBase.hxx b/include/vcl/accessibility/AccessibleBrowseBoxTableBase.hxx index 633ff2175eb9..7c362901262e 100644 --- a/include/vcl/accessibility/AccessibleBrowseBoxTableBase.hxx +++ b/include/vcl/accessibility/AccessibleBrowseBoxTableBase.hxx @@ -37,13 +37,12 @@ public: implSetName() and implSetDescription() (in Ctor) or later via setAccessibleName() and setAccessibleDescription() (these methods notify the listeners about the change). - @param rxParent XAccessible interface of the parent object. + @param rpParent Accessible of the parent object. @param rBrowseBox The BrowseBox control. @param eObjType Type of BrowseBox object. */ - AccessibleBrowseBoxTableBase( - const css::uno::Reference< css::accessibility::XAccessible >& rxParent, - ::vcl::IAccessibleTableProvider& rBrowseBox, - AccessibleBrowseBoxObjType eObjType ); + AccessibleBrowseBoxTableBase(const rtl::Reference& rpParent, + vcl::IAccessibleTableProvider& rBrowseBox, + AccessibleBrowseBoxObjType eObjType); protected: virtual ~AccessibleBrowseBoxTableBase() override = default; @@ -114,11 +113,6 @@ public: - getAccessibleCellAt, - isAccessibleSelected. */ - // XServiceInfo - - /* Derived classes have to implement: - - getImplementationName */ - protected: // internal virtual methods diff --git a/include/vcl/accessibility/AccessibleBrowseBoxTableCell.hxx b/include/vcl/accessibility/AccessibleBrowseBoxTableCell.hxx index 66d61c228a4c..e022016fd5fc 100644 --- a/include/vcl/accessibility/AccessibleBrowseBoxTableCell.hxx +++ b/include/vcl/accessibility/AccessibleBrowseBoxTableCell.hxx @@ -46,11 +46,6 @@ public: /** @return The index of this object among the parent's children. */ virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override; - /** @return - The name of this class. - */ - virtual OUString SAL_CALL getImplementationName() override; - /** @return The count of visible children. */ diff --git a/include/vcl/accessibility/vclxaccessiblecomponent.hxx b/include/vcl/accessibility/vclxaccessiblecomponent.hxx index d4d304c49898..d71fc0490f96 100644 --- a/include/vcl/accessibility/vclxaccessiblecomponent.hxx +++ b/include/vcl/accessibility/vclxaccessiblecomponent.hxx @@ -20,7 +20,6 @@ #pragma once #include -#include #include #include @@ -37,8 +36,7 @@ namespace utl { class AccessibleRelationSetHelper; } -class VCL_DLLPUBLIC VCLXAccessibleComponent - : public cppu::ImplInheritanceHelper +class VCL_DLLPUBLIC VCLXAccessibleComponent : public comphelper::OAccessible { private: VclPtr m_xWindow; @@ -67,11 +65,6 @@ public: virtual void SAL_CALL disposing() override; - // XServiceInfo - virtual OUString SAL_CALL getImplementationName() override; - virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) override; - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; - // css::accessibility::XAccessibleContext sal_Int64 SAL_CALL getAccessibleChildCount( ) override; css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int64 i ) override; diff --git a/include/vcl/accessibletableprovider.hxx b/include/vcl/accessibletableprovider.hxx index a2ee87dd9e9c..3ace21226bd1 100644 --- a/include/vcl/accessibletableprovider.hxx +++ b/include/vcl/accessibletableprovider.hxx @@ -26,7 +26,6 @@ class Point; enum class AccessibleBrowseBoxObjType; namespace comphelper { class OAccessible; } -namespace com::sun::star::accessibility { class XAccessible; } namespace com::sun::star::uno { template class Sequence; } namespace com::sun::star::uno { template class Reference; } namespace rtl { template class Reference; } @@ -72,7 +71,7 @@ public: virtual OUString GetColumnDescription( sal_uInt16 _nColumnPos ) const = 0; /** @return , if the object has a row header. */ - virtual bool HasRowHeader() const = 0; //GetColumnId + virtual bool HasRowHeader() const = 0; virtual bool GoToCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos ) = 0; virtual void SetNoSelection() = 0; @@ -98,8 +97,9 @@ public: virtual rtl::Reference CreateAccessibleCell(sal_Int32 _nRow, sal_uInt16 _nColumnPos) = 0; - virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleRowHeader( sal_Int32 _nRow ) = 0; - virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleColumnHeader( sal_uInt16 _nColumnPos ) = 0; + virtual rtl::Reference CreateAccessibleRowHeader(sal_Int32 _nRow) = 0; + virtual rtl::Reference + CreateAccessibleColumnHeader(sal_uInt16 _nColumnPos) = 0; virtual sal_Int32 GetAccessibleControlCount() const = 0; virtual rtl::Reference CreateAccessibleControl(sal_Int32 _nIndex) = 0; @@ -116,9 +116,6 @@ public: virtual void FillAccessibleStateSetForCell( sal_Int64& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const = 0; virtual void GrabTableFocus() = 0; - // OutputDevice - virtual bool GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr, int nIndex, int nLen, std::vector< tools::Rectangle >& rVector ) = 0; - // Window virtual tools::Rectangle GetWindowExtentsRelative(const vcl::Window& rRelativeWindow) const = 0; virtual void GrabFocus() = 0; diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx index e06693cf6c35..ddec325ab21d 100644 --- a/include/vcl/bitmap.hxx +++ b/include/vcl/bitmap.hxx @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -101,6 +102,13 @@ class SalBitmap; namespace basegfx { class SystemDependentDataHolder; } +#if USE_HEADLESS_CODE +typedef struct _cairo_surface cairo_surface_t; +namespace cairo { + typedef std::shared_ptr CairoSurfaceSharedPtr; +} +#endif + struct BitmapSystemData { #if defined(_WIN32) @@ -630,7 +638,7 @@ public: const css::uno::Reference< css::rendering::XBitmapCanvas > &xBitmapCanvas, const Size &rSize ); - SAL_DLLPRIVATE void ChangeColorAlpha( sal_uInt8 cIndexFrom, sal_Int8 nAlphaTo ); + SAL_DLLPRIVATE void ChangeColorAlpha( BitmapColor aColorFrom, sal_Int8 nAlphaTo ); /** * Adds a constant value to the alpha layer @@ -699,8 +707,6 @@ public: [[nodiscard]] static Bitmap AutoScaleBitmap( Bitmap const & rBitmap, const tools::Long aStandardSize ); - SAL_DLLPRIVATE void Draw( OutputDevice* pOutDev, - const Point& rDestPt ) const; void Draw( OutputDevice* pOutDev, const Point& rDestPt, const Size& rDestSize ) const; @@ -723,7 +729,7 @@ public: void DumpAsPng(const char* pFileName = nullptr) const; #if USE_HEADLESS_CODE - void* tryToGetCairoSurface() const; + cairo::CairoSurfaceSharedPtr tryToGetCairoSurface() const; #endif private: diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx index 7a7a5e05bba0..5fa5dca17caf 100644 --- a/include/vcl/builder.hxx +++ b/include/vcl/builder.hxx @@ -176,24 +176,6 @@ private: sal_uInt16 m_nLastMenuItemId; - /* The renderer/column structure in .ui files for GtkTreeView is a set - of compromise rules of expressing a layout in gtk terms which the - vcl equivalent is also able to do. - - The GtkInstanceTreeView ctor has some more details of that. - - The ui files end up containing information as to what each TreeView - is limited to, whether it will be used as a tree or a list and - whether there are multiple columns or not, so here we extract enough - of that information in the generic loader to determine what type of - role this TreeView has. - */ - sal_uInt16 m_nTreeViewRenderers; - sal_uInt16 m_nTreeViewExpanders; - sal_uInt16 m_nTreeViewColumnCount; - bool m_bTreeViewSeenTextInColumn; - bool m_bTreeHasHeader; - VclParserState(); }; diff --git a/include/vcl/builderbase.hxx b/include/vcl/builderbase.hxx index 553d64c16edf..143db80fa655 100644 --- a/include/vcl/builderbase.hxx +++ b/include/vcl/builderbase.hxx @@ -125,7 +125,6 @@ protected: stringmap handleAtkObject(xmlreader::XmlReader& reader) const; std::vector handleItems(xmlreader::XmlReader& reader) const; static void handleListStore(xmlreader::XmlReader& reader); - void handleRow(xmlreader::XmlReader& reader, const OUString& rID); void addAdjustment(const OUString& sID, Adjustment&& rAdjustment); const Adjustment* get_adjustment_by_name(const OUString& sID) const; diff --git a/include/vcl/builderpage.hxx b/include/vcl/builderpage.hxx index cf37cc9ba249..9b4b03363cba 100644 --- a/include/vcl/builderpage.hxx +++ b/include/vcl/builderpage.hxx @@ -10,7 +10,7 @@ #ifndef INCLUDED_VCL_BUILDERPAGE_HXX #define INCLUDED_VCL_BUILDERPAGE_HXX -#include +#include namespace weld { @@ -25,7 +25,7 @@ class VCL_DLLPUBLIC BuilderPage { public: BuilderPage(weld::Widget* pParent, weld::DialogController* pController, - const OUString& rUIXMLDescription, const OUString& rID, bool bIsMobile = false); + const OUString& rUIXMLDescription, const OUString& rID); virtual ~BuilderPage(); /* The title of the page, in an Assistant the dialog may append this page title to the diff --git a/include/vcl/canvastools.hxx b/include/vcl/canvastools.hxx index 29231610cba2..b738a36b748b 100644 --- a/include/vcl/canvastools.hxx +++ b/include/vcl/canvastools.hxx @@ -161,6 +161,7 @@ namespace vcl::unotools tools::Rectangle VCL_DLLPUBLIC rectangleFromB2IRectangle( const basegfx::B2IRange& ); basegfx::B2IPoint VCL_DLLPUBLIC b2IPointFromPoint(const Point&); basegfx::B2IRectangle VCL_DLLPUBLIC b2IRectangleFromRectangle(const tools::Rectangle&); + basegfx::B2IRectangle VCL_DLLPUBLIC b2IRectangleFromClosedRectangle(const tools::Rectangle&); } diff --git a/include/vcl/embeddedfontsmanager.hxx b/include/vcl/embeddedfontsmanager.hxx index 95a3580898f5..d54cc7ba8c88 100644 --- a/include/vcl/embeddedfontsmanager.hxx +++ b/include/vcl/embeddedfontsmanager.hxx @@ -44,7 +44,8 @@ public: */ static OUString fontFileUrl( std::u16string_view familyName, FontFamily family, FontItalic italic, - FontWeight weight, FontPitch pitch, FontRights rights ); + FontWeight weight, FontPitch pitch, FontRights rights, + std::u16string_view subFamilyName = {} ); /** Reads a font from the input stream, saves it to a temporary font file and adds it to the list of diff --git a/include/vcl/filter/PDFiumLibrary.hxx b/include/vcl/filter/PDFiumLibrary.hxx index 5aec6636de44..b7386593071c 100644 --- a/include/vcl/filter/PDFiumLibrary.hxx +++ b/include/vcl/filter/PDFiumLibrary.hxx @@ -49,6 +49,13 @@ inline constexpr OString constDictionaryKeyModificationDate = "M"_ostr; inline constexpr OString constDictionaryKeyInteriorColor = "IC"_ostr; inline constexpr OString constDictionaryKey_DefaultStyle = "DS"_ostr; inline constexpr OString constDictionaryKey_RichContent = "RC"_ostr; +// PDF markup-annotation keys: /IRT links a reply to its parent annotation; +// /RT says whether /IRT is a reply ("R", default) or a grouping ("Group"); +// /State + /StateModel describe the annotation's review/marked state. +inline constexpr OString constDictionaryKey_InReplyTo = "IRT"_ostr; +inline constexpr OString constDictionaryKey_ReplyType = "RT"_ostr; +inline constexpr OString constDictionaryKey_State = "State"_ostr; +inline constexpr OString constDictionaryKey_StateModel = "StateModel"_ostr; class PDFiumBitmap; class PDFiumDocument; @@ -153,6 +160,8 @@ public: virtual ~PDFiumAnnotation() = default; virtual PDFAnnotationSubType getSubType() = 0; virtual basegfx::B2DRectangle getRectangle() = 0; + /// Value of the /F (annotation flags) entry; 0 if absent. + virtual int getFlags() = 0; virtual bool hasKey(OString const& rKey) = 0; virtual PDFObjectType getValueType(OString const& rKey) = 0; virtual OUString getString(OString const& rKey) = 0; diff --git a/include/vcl/filter/SvmReader.hxx b/include/vcl/filter/SvmReader.hxx index d7f47ad84383..1d7422b55977 100644 --- a/include/vcl/filter/SvmReader.hxx +++ b/include/vcl/filter/SvmReader.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include class Color; class GDIMetaFile; @@ -36,13 +37,20 @@ class SvmReader private: SvStream& mrStream; + // running product of the map mode scales read so far + double mfCumulativeMapScaleX; + double mfCumulativeMapScaleY; + void ReadColor(::Color& rColor); + bool CheckMapScale(const MapMode& rMapMode); + public: VCL_DLLPUBLIC SvmReader(SvStream& rIStm); - VCL_DLLPUBLIC SvStream& Read(GDIMetaFile& rMetaFile, ImplMetaReadData* pData = nullptr); - rtl::Reference MetaActionHandler(ImplMetaReadData* pData); + VCL_DLLPUBLIC SvStream& Read(GDIMetaFile& rMetaFile); + SvStream& Read(GDIMetaFile& rMetaFile, ImplMetaReadData& rData); + rtl::Reference MetaActionHandler(ImplMetaReadData& rData); rtl::Reference LineColorHandler(); rtl::Reference FillColorHandler(); rtl::Reference RectHandler(); @@ -57,10 +65,10 @@ public: rtl::Reference PolyLineHandler(); rtl::Reference PolygonHandler(); rtl::Reference PolyPolygonHandler(); - rtl::Reference TextHandler(const ImplMetaReadData* pData); - rtl::Reference TextArrayHandler(const ImplMetaReadData* pData); - rtl::Reference StretchTextHandler(const ImplMetaReadData* pData); - rtl::Reference TextRectHandler(const ImplMetaReadData* pData); + rtl::Reference TextHandler(const ImplMetaReadData& rData); + rtl::Reference TextArrayHandler(const ImplMetaReadData& rData); + rtl::Reference StretchTextHandler(const ImplMetaReadData& rData); + rtl::Reference TextRectHandler(const ImplMetaReadData& rData); rtl::Reference TextLineHandler(); rtl::Reference BmpHandler(); rtl::Reference BmpScaleHandler(); @@ -85,13 +93,13 @@ public: rtl::Reference OverlineColorHandler(); rtl::Reference TextAlignHandler(); rtl::Reference MapModeHandler(); - rtl::Reference FontHandler(ImplMetaReadData* pData); + rtl::Reference FontHandler(ImplMetaReadData& rData); rtl::Reference PushHandler(); rtl::Reference PopHandler(); rtl::Reference RasterOpHandler(); rtl::Reference TransparentHandler(); - rtl::Reference FloatTransparentHandler(ImplMetaReadData* pData); - rtl::Reference EPSHandler(); + rtl::Reference FloatTransparentHandler(ImplMetaReadData& rData); + rtl::Reference EPSHandler(ImplMetaReadData& rData); rtl::Reference RefPointHandler(); rtl::Reference CommentHandler(); rtl::Reference LayoutModeHandler(); diff --git a/include/vcl/filter/pdfdocument.hxx b/include/vcl/filter/pdfdocument.hxx index b7ce0b1b339b..226e0318711d 100644 --- a/include/vcl/filter/pdfdocument.hxx +++ b/include/vcl/filter/pdfdocument.hxx @@ -89,9 +89,6 @@ class VCL_DLLPUBLIC PDFObjectElement final : public PDFElement std::vector> m_aElements; /// Uncompressed buffer of an object in an object stream. std::unique_ptr m_pStreamBuffer; - /// List of all reference elements inside this object's dictionary and - /// nested dictionaries. - std::vector m_aDictionaryReferences; bool m_bParsed; @@ -115,8 +112,6 @@ public: PDFNameElement* GetNameElement() const; /// Get access to the parsed key-value items from the object dictionary. const std::map& GetDictionaryItems(); - SAL_DLLPRIVATE const std::vector& GetDictionaryReferences() const; - SAL_DLLPRIVATE void AddDictionaryReference(PDFReferenceElement* pReference); SAL_DLLPRIVATE void SetArray(PDFArrayElement* pArrayElement); SAL_DLLPRIVATE void SetStream(PDFStreamElement* pStreamElement); /// Access to the stream of the object, if it has any. @@ -170,8 +165,6 @@ class VCL_DLLPUBLIC PDFReferenceElement final : public PDFElement int m_fGenerationValue; /// Location after the 'R' token. sal_uInt64 m_nOffset = 0; - /// The element providing the object number. - PDFNumberElement& m_rObject; public: PDFReferenceElement(PDFDocument& rDoc, PDFNumberElement& rObject, @@ -184,7 +177,6 @@ public: int GetObjectValue() const; int GetGenerationValue() const; SAL_DLLPRIVATE sal_uInt64 GetOffset() const; - SAL_DLLPRIVATE PDFNumberElement& GetObjectElement() const; void writeString(OStringBuffer& rBuffer) override { @@ -231,15 +223,10 @@ public: const OString& GetValue() const; SAL_DLLPRIVATE sal_uInt64 GetLocation() const; sal_uInt64 GetLength() const { return m_aValue.getLength(); } - - void writeString(OStringBuffer& rBuffer) override - { - rBuffer.append("/"); - rBuffer.append(m_aValue); - } + void writeString(OStringBuffer& rBuffer) override; }; -/// Dictionary object: a set key-value pairs. +/// Dictionary object: a set of key-value pairs. class VCL_DLLPUBLIC PDFDictionaryElement final : public PDFElement { /// Key-value pairs when the dictionary is a nested value. @@ -321,7 +308,7 @@ class XRefEntry * stored. */ sal_uInt64 m_nOffset = 0; - /// Are changed as part of an incremental update?. + /// Changed as part of an incremental update. bool m_bDirty = false; public: @@ -554,8 +541,8 @@ public: SAL_DLLPRIVATE void ReadXRef(SvStream& rStream); SAL_DLLPRIVATE void ReadXRefStream(SvStream& rStream); SAL_DLLPRIVATE static void SkipWhitespace(SvStream& rStream); - /// Instead of all whitespace, just skip CR and NL characters. - SAL_DLLPRIVATE static void SkipLineBreaks(SvStream& rStream); + /// Skip one end of line, which is CR, or NL, or CR followed by NL. + SAL_DLLPRIVATE static void SkipEndOfLine(SvStream& rStream); SAL_DLLPRIVATE size_t GetObjectOffset(size_t nIndex) const; const std::vector>& GetElements() const; std::vector GetPages(); @@ -601,6 +588,7 @@ public: SAL_DLLPRIVATE bool writeBufferBytes(const void* pBuffer, sal_uInt64 nBytes) override; void checkAndEnableStreamEncryption(sal_Int32 /*nObject*/) override {} void disableStreamEncryption() override {} + sal_uInt64 calculateStreamSize(sal_uInt64 const nDataSize) const override { return nDataSize; } }; /// The trailer singleton is at the end of the doc. diff --git a/include/vcl/filter/pdfobjectcontainer.hxx b/include/vcl/filter/pdfobjectcontainer.hxx index 308ec65cae83..f0e29142e771 100644 --- a/include/vcl/filter/pdfobjectcontainer.hxx +++ b/include/vcl/filter/pdfobjectcontainer.hxx @@ -39,9 +39,11 @@ public: virtual void disableStreamEncryption() = 0; + virtual sal_uInt64 calculateStreamSize(sal_uInt64 nDataSize) const = 0; + protected: ~PDFObjectContainer() noexcept = default; }; -} +} // namespace vcl /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/font.hxx b/include/vcl/font.hxx index dbaa2c0a1847..366440ea3790 100644 --- a/include/vcl/font.hxx +++ b/include/vcl/font.hxx @@ -109,9 +109,8 @@ public: const Size& GetFontSize() const; void SetFontHeight( tools::Long nHeight ); tools::Long GetFontHeight() const; - void SetAverageFontWidth( tools::Long nWidth ); - tools::Long GetAverageFontWidth() const; - SAL_DLLPRIVATE const Size& GetAverageFontSize() const; + void SetFontWidth( tools::Long nWidth ); + tools::Long GetFontWidth() const; SAL_DLLPRIVATE const FontFamily& GetFontFamily() const; // tdf#127471 for corrections on EMF/WMF we need the AvgFontWidth in Windows-specific notation diff --git a/include/vcl/font/Variation.hxx b/include/vcl/font/Variation.hxx index a524c3840cbd..ea7d555d1407 100644 --- a/include/vcl/font/Variation.hxx +++ b/include/vcl/font/Variation.hxx @@ -27,6 +27,15 @@ struct VCL_DLLPUBLIC Variation } }; +struct VCL_DLLPUBLIC VariationAxis +{ + uint32_t nTag = 0; + OUString aName; + float fMinValue = 0; + float fDefaultValue = 0; + float fMaxValue = 0; +}; + VCL_DLLPUBLIC std::vector VariationsFromString(std::u16string_view rString); VCL_DLLPUBLIC OUString VariationsToString(const std::vector& rVariations); diff --git a/include/vcl/formatter.hxx b/include/vcl/formatter.hxx index 7eac35a6bf23..d3d9d26de205 100644 --- a/include/vcl/formatter.hxx +++ b/include/vcl/formatter.hxx @@ -338,7 +338,6 @@ protected: virtual bool CheckText(const OUString&) const { return true; } void ImplSetTextImpl(const OUString& rNew, Selection const * pNewSel); - void ImplSetValue(double dValue, bool bForce); bool ImplGetValue(double& dNewVal); void ImplSetFormatKey(sal_uLong nFormatKey); diff --git a/include/vcl/gfxlink.hxx b/include/vcl/gfxlink.hxx index 55e294aba70e..33b033357ce5 100644 --- a/include/vcl/gfxlink.hxx +++ b/include/vcl/gfxlink.hxx @@ -48,12 +48,13 @@ enum class GfxLinkType NativeMov = 10, NativeBmp = 11, NativePdf = 12, - NativeWebp = 13, // If a new type is added, make sure to change NativeLast too + NativeWebp = 13, + NativeJxl = 14, // If a new type is added, make sure to change NativeLast too // Alias for when the first native type starts and last native // type ends. NativeFirst = NativeGif, - NativeLast = NativeWebp, + NativeLast = NativeJxl, }; class Graphic; @@ -76,7 +77,7 @@ private: public: GfxLink(); - explicit GfxLink(BinaryDataContainer aDataConainer, GfxLinkType nType); + explicit GfxLink(BinaryDataContainer aDataContainer, GfxLinkType nType); bool operator==( const GfxLink& ) const; diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx index 4598b1bcedb3..c3f015941c45 100644 --- a/include/vcl/graph.hxx +++ b/include/vcl/graph.hxx @@ -90,6 +90,7 @@ private: public: SAL_DLLPRIVATE ImpGraphic* ImplGetImpGraphic() const { return mxImpGraphic.get(); } + SAL_DLLPRIVATE std::shared_ptr ImplGetSharedImpGraphic() const { return mxImpGraphic; } Graphic(); SAL_DLLPRIVATE Graphic(std::shared_ptr const & rGfxLink, sal_Int32 nPageIndex = 0); diff --git a/include/vcl/graphic/GraphicMetadata.hxx b/include/vcl/graphic/GraphicMetadata.hxx index b01e38c8cfab..63a94c485823 100644 --- a/include/vcl/graphic/GraphicMetadata.hxx +++ b/include/vcl/graphic/GraphicMetadata.hxx @@ -38,6 +38,7 @@ enum class GraphicFileFormat PSD = 0x000f, EPS = 0x0010, WEBP = 0x0011, + JXL = 0x0012, MOV = 0x00e0, PDF = 0x00e1, DXF = 0x00f1, diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx index 26b9ab60479c..9350c08be72d 100644 --- a/include/vcl/graphicfilter.hxx +++ b/include/vcl/graphicfilter.hxx @@ -81,6 +81,7 @@ namespace o3tl #define IMP_GIF "SVIGIF" #define IMP_PNG "SVIPNG" #define IMP_JPEG "SVIJPEG" +#define IMP_JXL "SVIJXL" #define IMP_XBM "SVIXBM" #define IMP_XPM "SVIXPM" #define IMP_SVG "SVISVG" @@ -106,6 +107,7 @@ namespace o3tl #define EXP_EMF "SVEMF" #define EXP_EMZ "SVEMZ" #define EXP_JPEG "SVEJPEG" +#define EXP_JXL "SVEJXL" #define EXP_SVG "SVESVG" #define EXP_SVGZ "SVESVGZ" #define EXP_PDF "SVEPDF" @@ -120,6 +122,7 @@ namespace o3tl inline constexpr OUString BMP_SHORTNAME = u"BMP"_ustr; inline constexpr OUString GIF_SHORTNAME = u"GIF"_ustr; inline constexpr OUString JPG_SHORTNAME = u"JPG"_ustr; +inline constexpr OUString JXL_SHORTNAME = u"JXL"_ustr; inline constexpr OUString MET_SHORTNAME = u"MET"_ustr; inline constexpr OUString PCT_SHORTNAME = u"PCT"_ustr; inline constexpr OUString PNG_SHORTNAME = u"PNG"_ustr; @@ -141,6 +144,7 @@ class VCL_DLLPUBLIC GraphicDescriptor final SAL_DLLPRIVATE bool ImpDetectBMP( SvStream& rStm, bool bExtendedInfo ); SAL_DLLPRIVATE bool ImpDetectGIF( SvStream& rStm, bool bExtendedInfo ); SAL_DLLPRIVATE bool ImpDetectJPG( SvStream& rStm, bool bExtendedInfo ); + SAL_DLLPRIVATE bool ImpDetectJXL( SvStream& rStm, bool bExtendedInfo ); SAL_DLLPRIVATE bool ImpDetectPCD( SvStream& rStm, bool bExtendedInfo ); SAL_DLLPRIVATE bool ImpDetectPCX( SvStream& rStm ); SAL_DLLPRIVATE bool ImpDetectPNG( SvStream& rStm, bool bExtendedInfo ); @@ -223,7 +227,7 @@ public: /** @return whether image supports alpha values for translucent colours */ bool IsAlpha() const { return aMetadata.mbIsAlpha; } - /** @return filter number that is needed by the GraphFilter to read this format */ + /** @return filter short name that is needed by GraphicFilter to read this format */ static OUString GetImportFormatShortName( GraphicFileFormat nFormat ); }; @@ -319,6 +323,7 @@ public: BinaryDataContainer & rpGraphicContent); SAL_DLLPRIVATE static ErrCode readJPEG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, GraphicFilterImportFlags nImportFlags); + SAL_DLLPRIVATE static ErrCode readJXL(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); SAL_DLLPRIVATE static ErrCode readSVG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, BinaryDataContainer & rpGraphicContent); SAL_DLLPRIVATE static ErrCode readXBM(SvStream & rStream, Graphic & rGraphic); diff --git a/include/vcl/headbar.hxx b/include/vcl/headbar.hxx index 80db48c56913..4757af7c7870 100644 --- a/include/vcl/headbar.hxx +++ b/include/vcl/headbar.hxx @@ -191,12 +191,13 @@ enum class HeaderBarItemBits FLAT = 0x0800, DOWNARROW = 0x1000, UPARROW = 0x2000, + HIDDEN = 0x4000, STDSTYLE = LEFT | LEFTIMAGE | CLICKABLE, }; namespace o3tl { - template<> struct typed_flags : is_typed_flags {}; + template<> struct typed_flags : is_typed_flags {}; } #define HEADERBAR_APPEND (sal_uInt16(0xFFFF)) @@ -258,7 +259,7 @@ public: virtual void MouseMove( const MouseEvent& rMEvt ) override; virtual void Tracking( const TrackingEvent& rTEvt ) override; virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos,SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Resize() override; virtual void Command( const CommandEvent& rCEvt ) override; virtual void RequestHelp( const HelpEvent& rHEvt ) override; @@ -291,6 +292,9 @@ public: void SetItemSize( sal_uInt16 nItemId, tools::Long nNewSize ); tools::Long GetItemSize( sal_uInt16 nItemId ) const; + // Note that to make an item visible, the width must also be set to a non-zero value + void SetItemVisible( sal_uInt16 nItemId, bool bVisible ); + bool GetItemVisible( sal_uInt16 nItemId) const; void SetItemBits( sal_uInt16 nItemId, HeaderBarItemBits nNewBits ); HeaderBarItemBits GetItemBits( sal_uInt16 nItemId ) const; diff --git a/include/vcl/hexcolorcontrol.hxx b/include/vcl/hexcolorcontrol.hxx index a303e6175d74..aa7509cd9027 100644 --- a/include/vcl/hexcolorcontrol.hxx +++ b/include/vcl/hexcolorcontrol.hxx @@ -41,7 +41,7 @@ private: ImplSVEvent* m_nAsyncModifyEvent; DECL_DLLPRIVATE_STATIC_LINK(HexColorControl, ImplProcessInputHdl, OUString&, bool); - DECL_DLLPRIVATE_LINK(ImplProcessModifyHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(ImplProcessModifyHdl, weld::TextWidget&, void); DECL_DLLPRIVATE_LINK(OnAsyncModifyHdl, void*, void); public: HexColorControl(std::unique_ptr pEdit); diff --git a/include/vcl/jsdialog/executor.hxx b/include/vcl/jsdialog/executor.hxx deleted file mode 100644 index c13a95350352..000000000000 --- a/include/vcl/jsdialog/executor.hxx +++ /dev/null @@ -1,200 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class LOKTrigger -{ -public: - static void trigger_changed(weld::TextView& rView) { rView.signal_changed(); } - - static void trigger_changed(weld::Entry& rEdit) { rEdit.signal_changed(); } - - static void trigger_activated(weld::Entry& rEdit) { rEdit.signal_activated(); } - - static void trigger_changed(weld::ComboBox& rComboBox) { rComboBox.signal_changed(); } - - static void trigger_changed(weld::TreeView& rTreeView) { rTreeView.signal_selection_changed(); } - - static void trigger_editing_done(weld::TreeView& rTreeView, - const weld::TreeView::iter_string& rIterText) - { - rTreeView.signal_editing_done(rIterText); - } - - static void trigger_changed(weld::IconView& rIconView) { rIconView.signal_selection_changed(); } - - static void trigger_scrollv(weld::ScrolledWindow& rScrolledWindow) - { - rScrolledWindow.signal_vadjustment_value_changed(); - } - - static void trigger_scrollh(weld::ScrolledWindow& rScrolledWindow) - { - rScrolledWindow.signal_hadjustment_value_changed(); - } - - static void trigger_toggled(weld::Toggleable& rButton) { rButton.signal_toggled(); } - - static void trigger_row_activated(weld::TreeView& rTreeView) - { - if (std::unique_ptr pSelected = rTreeView.get_selected()) - rTreeView.signal_item_activated(*pSelected); - } - - static void trigger_popup_menu(weld::TreeView& rTreeView, const CommandEvent& rCommand) - { - rTreeView.signal_command(rCommand); - } - - static void trigger_column_clicked(weld::TreeView& rTreeView, int nColumn) - { - rTreeView.signal_column_clicked(nColumn); - } - - static void trigger_activated(weld::Menu& rMenu, const OUString& rIdent) - { - rMenu.signal_activate(rIdent); - } - - static void trigger_item_activated(weld::IconView& rIconView) - { - if (std::unique_ptr pSelected = rIconView.get_selected()) - rIconView.signal_item_activated(*pSelected); - } - - static void trigger_clicked(weld::Toolbar& rToolbar, const OUString& rIdent) - { - rToolbar.signal_clicked(rIdent); - } - - static void trigger_clicked(weld::Button& rButton) { rButton.signal_clicked(); } - - static void trigger_click(weld::DrawingArea& rDrawingArea, const Point& rPos) - { - rDrawingArea.click(rPos); - } - - static void trigger_dblclick(weld::DrawingArea& rDrawingArea, const Point& rPos) - { - rDrawingArea.dblclick(rPos); - } - - static void trigger_mouse_up(weld::DrawingArea& rDrawingArea, const Point& rPos) - { - rDrawingArea.mouse_up(rPos); - } - - static void trigger_mouse_down(weld::DrawingArea& rDrawingArea, const Point& rPos) - { - rDrawingArea.mouse_down(rPos); - } - - static void trigger_mouse_move(weld::DrawingArea& rDrawingArea, const Point& rPos) - { - rDrawingArea.mouse_move(rPos); - } - - static void trigger_mouse_press(weld::IconView& rIconView, const MouseEvent& rEvent) - { - rIconView.signal_mouse_press(rEvent); - } - - static void trigger_selected(weld::MenuButton& rButton, const OUString& rIdent) - { - rButton.signal_selected(rIdent); - } - - static void trigger_selected(weld::Calendar& rCalendar) { rCalendar.signal_selected(); } - - static void trigger_activated(weld::Calendar& rCalendar) { rCalendar.signal_activated(); } - - static void trigger_value_changed(weld::SpinButton& rSpinButton) - { - rSpinButton.signal_value_changed(); - } - - static void trigger_value_changed(weld::FormattedSpinButton& rSpinButton) - { - rSpinButton.signal_value_changed(); - } - - static void trigger_closed(weld::Popover& rPopover) { rPopover.popdown(); } - - static void trigger_key_press(const weld::Widget& rWidget, const KeyEvent& rEvent) - { - rWidget.m_aKeyPressHdl.Call(rEvent); - } - - static void trigger_key_release(const weld::Widget& rWidget, const KeyEvent& rEvent) - { - rWidget.m_aKeyReleaseHdl.Call(rEvent); - } - - static void command(weld::DrawingArea& rArea, const CommandEvent& rCmd) - { - rArea.signal_command(rCmd); - } - - static void enter_page(const weld::Notebook& rNotebook, const OUString& rPage) - { - rNotebook.m_aEnterPageHdl.Call(rPage); - } - - static void leave_page(const weld::Notebook& rNotebook, const OUString& rPage) - { - rNotebook.m_aLeavePageHdl.Call(rPage); - } - - static bool activate_link(weld::LinkButton& rLinkButton) - { - return rLinkButton.signal_activate_link(); - } -}; - -namespace jsdialog -{ -// type used to store key-value pairs to put in the generated messages -typedef std::unordered_map ActionDataMap; - -VCL_DLLPUBLIC void SendNavigatorForView(const sal_uInt64 nShellId); -VCL_DLLPUBLIC void SendSidebarForView(const sal_uInt64 nShellId); -VCL_DLLPUBLIC void SendQuickFindForView(const sal_uInt64 nShellId); - -/// execute action on a widget -VCL_DLLPUBLIC bool ExecuteAction(const OUString& nWindowId, const OUString& rWidget, - const StringMap& rData); -/// send full update message to the client -VCL_DLLPUBLIC void SendFullUpdate(const OUString& nWindowId, const OUString& rWidget); -/// send action message to the client -VCL_DLLPUBLIC void SendAction(const OUString& nWindowId, const OUString& rWidget, - std::unique_ptr pData); -VCL_DLLPUBLIC StringMap jsonToStringMap(const char* pJSON); -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/layout.hxx b/include/vcl/layout.hxx index bd2b46b23708..098621985ae5 100644 --- a/include/vcl/layout.hxx +++ b/include/vcl/layout.hxx @@ -95,7 +95,6 @@ public: return m_bVerticalContainer; } virtual bool set_property(const OUString &rKey, const OUString &rValue) override; - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; protected: virtual sal_uInt16 getDefaultAccessibleRole() const override; void accumulateMaxes(const Size &rChildSize, Size &rSize) const; @@ -211,7 +210,6 @@ public: { } virtual bool set_property(const OUString &rKey, const OUString &rValue) override; - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; protected: virtual Size calculateRequisition() const override; virtual void setAllocation(const Size &rAllocation) override; @@ -327,7 +325,6 @@ private: Size calculateRequisitionForSpacings(sal_Int32 nRowSpacing, sal_Int32 nColSpacing) const; virtual Size calculateRequisition() const override; virtual void setAllocation(const Size &rAllocation) override; - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; public: VclGrid(vcl::Window *pParent) : VclContainer(pParent) @@ -439,7 +436,6 @@ public: virtual const vcl::Window *get_child() const override; vcl::Window *get_label_widget(); const vcl::Window *get_label_widget() const; - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; private: virtual Size calculateRequisition() const override; virtual void setAllocation(const Size &rAllocation) override; @@ -466,7 +462,6 @@ public: const vcl::Window *get_label_widget() const; virtual void StateChanged(StateChangedType nType) override; void SetExpandedHdl( const Link& rLink ) { maExpandedHdl = rLink; } - virtual void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; virtual FactoryFunction GetUITestFactory() const override; private: virtual Size calculateRequisition() const override; @@ -495,7 +490,6 @@ public: //to override it void setUserManagedScrolling(bool bUserManagedScrolling) { m_bUserManagedScrolling = bUserManagedScrolling;} void doSetAllocation(const Size &rAllocation, bool bRetryOnFailure); - virtual void DumpAsPropertyTree(::tools::JsonWriter& rJsonWriter) override; private: virtual Size calculateRequisition() const override; virtual void setAllocation(const Size &rAllocation) override; @@ -768,7 +762,6 @@ public: m_xTransferHelper = rHelper; m_nDragAction = eDNDConstants; } - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; }; //Get first window of a pTopLevel window as diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx index 5f3b82372391..00033de19b4c 100644 --- a/include/vcl/menu.hxx +++ b/include/vcl/menu.hxx @@ -54,7 +54,6 @@ enum class VclEventId; namespace com::sun::star::awt { class XPopupMenu; } namespace comphelper { class OAccessible; } -namespace tools { class JsonWriter; } namespace vcl { @@ -400,8 +399,6 @@ public: */ const OUString& get_id() const { return maID; } - virtual void DumpAsPropertyTree(tools::JsonWriter&) const; - private: rtl::Reference CreateAccessible(); }; diff --git a/include/vcl/metaact.hxx b/include/vcl/metaact.hxx index c00cfe6ba7ef..72555a0b9869 100644 --- a/include/vcl/metaact.hxx +++ b/include/vcl/metaact.hxx @@ -894,7 +894,7 @@ public: SAL_DLLPRIVATE virtual void Execute( OutputDevice* pOut ) override; SAL_DLLPRIVATE virtual rtl::Reference Clone() const override; - MetaGradientAction( const tools::Rectangle& rRect, Gradient aGradient ); + VCL_DLLPUBLIC MetaGradientAction( const tools::Rectangle& rRect, Gradient aGradient ); SAL_DLLPRIVATE virtual void Move( tools::Long nHorzMove, tools::Long nVertMove ) override; SAL_DLLPRIVATE virtual void Scale( double fScaleX, double fScaleY ) override; @@ -948,7 +948,7 @@ public: SAL_DLLPRIVATE virtual void Execute( OutputDevice* pOut ) override; SAL_DLLPRIVATE virtual rtl::Reference Clone() const override; - MetaHatchAction( tools::PolyPolygon aPolyPoly, const Hatch& rHatch ); + VCL_DLLPUBLIC MetaHatchAction( tools::PolyPolygon aPolyPoly, const Hatch& rHatch ); SAL_DLLPRIVATE virtual void Move( tools::Long nHorzMove, tools::Long nVertMove ) override; SAL_DLLPRIVATE virtual void Scale( double fScaleX, double fScaleY ) override; @@ -1291,7 +1291,7 @@ private: // tdf#127471 for import correction of own wrong written EMF/WMF files allow correction // of FontScale after import. Only from there, so use a friend here and keep the method private friend class emfio::ScaledFontDetectCorrectHelper; - void correctFontScale(tools::Long nNewFontScale) { maFont.SetAverageFontWidth(nNewFontScale); } + void correctFontScale(tools::Long nNewFontScale) { maFont.SetFontWidth(nNewFontScale); } public: MetaFontAction(MetaFontAction const &) = default; diff --git a/include/vcl/notebookbar/notebookbar.hxx b/include/vcl/notebookbar/notebookbar.hxx index c393c86098ae..099182bc023b 100644 --- a/include/vcl/notebookbar/notebookbar.hxx +++ b/include/vcl/notebookbar/notebookbar.hxx @@ -16,7 +16,6 @@ class NotebookBarContextChangeEventListener; class NotebookbarContextControl; -class SfxViewShell; struct NotebookBarAddonsItem; /// This implements Widget Layout-based notebook-like menu bar. @@ -43,21 +42,15 @@ public: void SetupListener(bool bListen); - bool IsWelded() const { return m_bIsWelded; } - VclPtr& GetMainContainer() { return m_xVclContentArea; } const OUString & GetUIFilePath() const { return m_sUIXMLDescription; } - void SetDisposeCallback(const Link rDisposeCallback, const SfxViewShell* pViewShell); private: VclPtr m_pSystemWindow; rtl::Reference m_pEventListener; std::vector m_pContextContainers; - const SfxViewShell* m_pViewShell; - VclPtr m_xVclContentArea; - bool m_bIsWelded; OUString m_sUIXMLDescription; - Link m_rDisposeLink; + const OUString m_sModule; AllSettings DefaultSettings; diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index 457466b74514..edbd7bc1c78c 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -87,6 +88,7 @@ struct SalTwoRect; class Printer; class VCLXGraphics; class SalLayoutGlyphs; +class CoordinateMapper; enum class AddFontSubstituteFlags; enum class AntialiasingFlags; @@ -152,7 +154,8 @@ void AdjustTwoRect( SalTwoRect& rTwoRect, const tools::Rectangle& rValidSrcRect class OutputDevice; -namespace vcl { +namespace vcl +{ typedef OutputDevice RenderContext; } @@ -187,26 +190,15 @@ private: std::unique_ptr mpOutDevData; std::vector< VCLXGraphics* >* mpUnoGraphicsList; vcl::ExtOutDevData* mpExtOutDevData; + mutable std::unique_ptr mpMapper; + // The canvas interface for this output device. Is persistent after the first GetCanvas() call mutable css::uno::WeakReference< css::rendering::XCanvas > mxCanvas; - /// Additional output pixel offset, applied in LogicToPixel (used by SetPixelOffset/GetPixelOffset) - tools::Long mnOutOffOrigX; - /// Additional output offset in _logical_ coordinates, applied in PixelToLogic (used by SetPixelOffset/GetPixelOffset) - tools::Long mnOutOffLogicX; - /// Additional output pixel offset, applied in LogicToPixel (used by SetPixelOffset/GetPixelOffset) - tools::Long mnOutOffOrigY; - /// Additional output offset in _logical_ coordinates, applied in PixelToLogic (used by SetPixelOffset/GetPixelOffset) - tools::Long mnOutOffLogicY; /// Output offset for device output in pixel (pseudo window offset within window system's frames) tools::Long mnOutOffX; /// Output offset for device output in pixel (pseudo window offset within window system's frames) tools::Long mnOutOffY; - tools::Long mnOutWidth; - tools::Long mnOutHeight; - sal_Int32 mnDPIX; - sal_Int32 mnDPIY; - sal_Int32 mnDPIScalePercentage; ///< For HiDPI displays, we want to draw elements for a percentage larger /// font specific text alignment offsets in pixel units mutable tools::Long mnTextOffX; mutable tools::Long mnTextOffY; @@ -214,7 +206,6 @@ private: mutable tools::Long mnEmphasisDescent; DrawModeFlags mnDrawMode; vcl::text::ComplexTextLayoutFlags mnTextLayoutMode; - ImplMapRes maMapRes; const OutDevType meOutDevType; OutDevViewType meOutDevViewType; vcl::Region maRegion; // contains the clip region, see SetClipRegion(...) @@ -227,12 +218,10 @@ private: RasterOp meRasterOp; Wallpaper maBackground; std::optional moSettings; - MapMode maMapMode; Point maRefPoint; AntialiasingFlags mnAntialiasing; LanguageType meTextLanguage; - mutable bool mbMap : 1; mutable bool mbClipRegion : 1; mutable bool mbBackground : 1; mutable bool mbOutput : 1; @@ -307,16 +296,16 @@ public: virtual sal_uInt16 GetBitCount() const; - Size GetOutputSizePixel() const - { return Size( mnOutWidth, mnOutHeight ); } - tools::Long GetOutputWidthPixel() const { return mnOutWidth; } - tools::Long GetOutputHeightPixel() const { return mnOutHeight; } - tools::Long GetOutOffXPixel() const { return mnOutOffX; } - tools::Long GetOutOffYPixel() const { return mnOutOffY; } - SAL_DLLPRIVATE void SetOutOffXPixel(tools::Long nOutOffX); - SAL_DLLPRIVATE void SetOutOffYPixel(tools::Long nOutOffY); - Point GetOutputOffPixel() const - { return Point( mnOutOffX, mnOutOffY ); } + Size GetOutputSizePixel() const; + tools::Long GetOutputWidthPixel() const; + tools::Long GetOutputHeightPixel() const; + void SetOutputWidthPixel(tools::Long nWidth); + void SetOutputHeightPixel(tools::Long nHeight); + tools::Long GetDeviceOriginX() const; + tools::Long GetDeviceOriginY() const; + void SetDeviceOriginX(tools::Long nOutOffX); + void SetDeviceOriginY(tools::Long nOutOffY); + Point GetOutputOffPixel() const; tools::Rectangle GetOutputRectPixel() const { return tools::Rectangle(GetOutputOffPixel(), GetOutputSizePixel() ); } @@ -380,26 +369,20 @@ public: @returns x-axis DPI value */ - SAL_DLLPRIVATE sal_Int32 GetDPIX() const { return mnDPIX; } + sal_Int32 GetDPIX() const; /** Get the output device's DPI y-axis value. @returns y-axis DPI value */ - SAL_DLLPRIVATE sal_Int32 GetDPIY() const { return mnDPIY; } + sal_Int32 GetDPIY() const; - SAL_DLLPRIVATE void SetDPIX( sal_Int32 nDPIX ) { mnDPIX = nDPIX; } - SAL_DLLPRIVATE void SetDPIY( sal_Int32 nDPIY ) { mnDPIY = nDPIY; } + void SetDPIX(sal_Int32 nDPIX); + void SetDPIY(sal_Int32 nDPIY); - float GetDPIScaleFactor() const - { - return mnDPIScalePercentage / 100.0f; - } - - sal_Int32 GetDPIScalePercentage() const - { - return mnDPIScalePercentage; - } + float GetDPIScaleFactor() const; + sal_Int32 GetDPIScalePercentage() const; + void SetDPIScalePercentage(float nPercent); OutDevType GetOutDevType() const { return meOutDevType; } virtual bool IsVirtual() const; @@ -1029,6 +1012,16 @@ public: sal_uLong nLayoutWidth = 0, KernArraySpan aDXArray = KernArraySpan(), std::span pKashidaArray = {} ) const; + /** Get outlines for raw glyph IDs (bypassing text shaping). + Returns one B2DPolyPolygon per glyph. The outlines are in the + OutputDevice's logical coordinates: this function internally + disables MapMode so the font's numeric size is treated as + pixels, which makes the returned outline values numerically + match whatever unit the font size was set in (e.g. with + MapMode 100thMM, outlines are in 100thMM). */ + bool GetGlyphOutlines( const sal_uInt32* pGlyphIds, sal_Int32 nGlyphs, + basegfx::B2DPolyPolygonVector& rOutlines ) const; + OUString GetEllipsisString( const OUString& rStr, tools::Long nMaxWidth, DrawTextFlags nStyle = DrawTextFlags::EndEllipsis ) const; @@ -1185,7 +1178,15 @@ public: bool IsFontAvailable( std::u16string_view rFontName ) const; - bool AddTempDevFont( const OUString& rFileURL, const OUString& rFontName ); + bool GetTypographicFontName( std::u16string_view rRequestedFamily, + FontWeight eWeight, FontWidth eWidth, FontItalic eItalic, + OUString& rOutFamily, OUString& rOutSubfamily ) const; + bool GetLegacyFontName( std::u16string_view rTypoFamily, + std::u16string_view rSubfamily, + FontWeight eWeight, FontItalic eItalic, + OUString& rOutLegacyName ) const; + + bool AddTempDevFont(const OUString& rFileURL, const OUString& rFontName) const; bool RemoveTempDevFont( const OUString& rFileURL, const OUString& rFontName ); void RefreshFontData( const bool bNewFontLists ); @@ -1196,9 +1197,12 @@ public: bool GetFontCapabilities( vcl::FontCapabilities& rFontCapabilities ) const; bool GetFontFeatures(std::vector& rFontFeatures) const; + bool GetFontVariationAxes(std::vector& rAxes) const; bool GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr, int nIndex, int nLen, std::vector< tools::Rectangle >& rVector ) const; + bool SupportsOpenTypeMath() const; + double GetOpenTypeMathConstant(vcl::OpenTypeMathConstant aConstant) const; sal_Int32 HasGlyphs( const vcl::Font& rFont, std::u16string_view rStr, sal_Int32 nIndex = 0, sal_Int32 nLen = -1 ) const; @@ -1576,26 +1580,23 @@ protected: public: void EnableMapMode( bool bEnable = true ); - bool IsMapModeEnabled() const { return mbMap; } + bool IsMapModeEnabled() const; void SetMapMode(); void SetMapMode( const MapMode& rNewMapMode ); void SetRelativeMapMode( const MapMode& rNewMapMode ); virtual void SetMetafileMapMode(const MapMode& rNewMapMode, bool bIsRecord); - const MapMode& GetMapMode() const { return maMapMode; } + const MapMode& GetMapMode() const; + + basegfx::B2DHomMatrix GetViewTransformation() const; + basegfx::B2DHomMatrix GetViewTransformation(const MapMode& rMapMode) const; + basegfx::B2DHomMatrix GetInverseViewTransformation() const; + basegfx::B2DHomMatrix GetInverseViewTransformation(const MapMode& rMapMode) const; protected: virtual void ImplInitMapModeObjects(); public: - // #i75163# - basegfx::B2DHomMatrix GetViewTransformation() const; - basegfx::B2DHomMatrix GetInverseViewTransformation() const; - - SAL_DLLPRIVATE basegfx::B2DHomMatrix GetViewTransformation( const MapMode& rMapMode ) const; - basegfx::B2DHomMatrix GetInverseViewTransformation( const MapMode& rMapMode ) const; - - /** Set an offset in pixel This method offsets every drawing operation that converts its @@ -1626,14 +1627,14 @@ public: @return the current offset in pixel */ - SAL_WARN_UNUSED_RESULT Size GetPixelOffset() const { return Size(mnOutOffOrigX, mnOutOffOrigY);} + SAL_WARN_UNUSED_RESULT Size GetPixelOffset() const; SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point& rLogicPt) const; SAL_WARN_UNUSED_RESULT Size LogicToPixel(const Size& rLogicSize) const; SAL_WARN_UNUSED_RESULT tools::Rectangle LogicToPixel(const tools::Rectangle& rLogicRect) const; SAL_WARN_UNUSED_RESULT SAL_DLLPRIVATE tools::Polygon LogicToPixel(const tools::Polygon& rLogicPoly) const; SAL_WARN_UNUSED_RESULT SAL_DLLPRIVATE tools::PolyPolygon LogicToPixel(const tools::PolyPolygon& rLogicPolyPoly) const; - SAL_WARN_UNUSED_RESULT SAL_DLLPRIVATE basegfx::B2DPolyPolygon LogicToPixel(const basegfx::B2DPolyPolygon& rLogicPolyPoly) const; + SAL_WARN_UNUSED_RESULT basegfx::B2DPolyPolygon LogicToPixel(const basegfx::B2DPolyPolygon& rLogicPolyPoly) const; SAL_WARN_UNUSED_RESULT vcl::Region LogicToPixel(const vcl::Region& rLogicRegion)const; SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point& rLogicPt, const MapMode& rMapMode) const; SAL_WARN_UNUSED_RESULT Size LogicToPixel(const Size& rLogicSize, const MapMode& rMapMode) const; @@ -1700,7 +1701,7 @@ public: @returns Rectangle based on physical device pixel coordinates and units. */ - SAL_DLLPRIVATE tools::Rectangle ImplLogicToDevicePixel( const tools::Rectangle& rLogicRect ) const; + SAL_DLLPRIVATE tools::Rectangle LogicToDevicePixel(const tools::Rectangle& rLogicRect) const; /** Convert a logical point to a physical point on the device. @@ -1708,8 +1709,8 @@ public: @returns Physical point on the device. */ - SAL_DLLPRIVATE Point ImplLogicToDevicePixel( const Point& rLogicPt ) const; - SAL_DLLPRIVATE basegfx::B2DPoint ImplLogicToDeviceSubPixel(const Point& rLogicPt) const; + SAL_DLLPRIVATE Point LogicToDevicePixel(const Point& rLogicPt) const; + SAL_DLLPRIVATE basegfx::B2DPoint LogicToDeviceSubPixel(const Point& rLogicPt) const; /** Convert a logical width to a width in units of device pixels. @@ -1721,9 +1722,10 @@ public: @returns Width in units of device pixels. */ - SAL_DLLPRIVATE tools::Long ImplLogicWidthToDevicePixel( tools::Long nWidth ) const; - SAL_DLLPRIVATE double ImplLogicWidthToDeviceSubPixel(tools::Long nWidth) const; + SAL_DLLPRIVATE tools::Long LogicWidthToDevicePixel(tools::Long nWidth) const; + SAL_DLLPRIVATE double LogicWidthToDeviceSubPixel(tools::Long nWidth) const; +protected: /** Convert a logical height to a height in units of device pixels. To get the number of device pixels, it must calculate the Y-DPI of the device and @@ -1734,10 +1736,10 @@ public: @returns Height in units of device pixels. */ - SAL_DLLPRIVATE tools::Long ImplLogicHeightToDevicePixel( tools::Long nHeight ) const; - SAL_DLLPRIVATE double ImplLogicHeightToDeviceSubPixel(tools::Long nHeight) const; + tools::Long LogicHeightToDevicePixel(tools::Long nHeight) const; + SAL_DLLPRIVATE double LogicHeightToDeviceSubPixel(tools::Long nHeight) const; - SAL_DLLPRIVATE Point SubPixelToLogic(const basegfx::B2DPoint& rDevicePt) const; + SAL_DLLPRIVATE Point SubPixelToLogic(const basegfx::B2DPoint& rDevicePt) const; /** Convert device pixels to a width in logical units. @@ -1748,7 +1750,7 @@ public: @returns Width in logical units. */ - SAL_DLLPRIVATE tools::Long ImplDevicePixelToLogicWidth( tools::Long nWidth ) const; + SAL_DLLPRIVATE tools::Long DevicePixelToLogicWidth(tools::Long nWidth) const; /** Convert device pixels to a height in logical units. @@ -1759,8 +1761,9 @@ public: @returns Height in logical units. */ - SAL_DLLPRIVATE tools::Long ImplDevicePixelToLogicHeight( tools::Long nHeight ) const; + SAL_DLLPRIVATE tools::Long DevicePixelToLogicHeight(tools::Long nHeight) const; +private: /** Convert a logical size to the size on the physical device. @param rLogicSize Const reference to a size in logical units @@ -1817,45 +1820,6 @@ public: */ SAL_DLLPRIVATE vcl::Region ImplPixelToDevicePixel( const vcl::Region& rRegion ) const; - /** Invalidate the view transformation. - - @since AOO bug 75163 (OpenOffice.org 2.4.3 - OOH 680 milestone 212) - */ - SAL_DLLPRIVATE void ImplInvalidateViewTransform(); - - /** Get device transformation. - - @since AOO bug 75163 (OpenOffice.org 2.4.3 - OOH 680 milestone 212) - */ - SAL_DLLPRIVATE basegfx::B2DHomMatrix ImplGetDeviceTransformation() const; - -private: - /** Convert a logical X coordinate to a device pixel's X coordinate. - - To get the device's X coordinate, it must calculate the mapping offset - coordinate X position (if there is one - if not then it just adds - the pseudo-window offset to the logical X coordinate), the X-DPI of - the device and the mapping's X scaling factor. - - @param nX Logical X coordinate - - @returns Device's X pixel coordinate - */ - SAL_DLLPRIVATE tools::Long ImplLogicXToDevicePixel( tools::Long nX ) const; - - /** Convert a logical Y coordinate to a device pixel's Y coordinate. - - To get the device's Y coordinate, it must calculate the mapping offset - coordinate Y position (if there is one - if not then it just adds - the pseudo-window offset to the logical Y coordinate), the Y-DPI of - the device and the mapping's Y scaling factor. - - @param nY Logical Y coordinate - - @returns Device's Y pixel coordinate - */ - SAL_DLLPRIVATE tools::Long ImplLogicYToDevicePixel( tools::Long nY ) const; - SAL_DLLPRIVATE double ImplDevicePixelToLogicWidthDouble(double nWidth) const; SAL_DLLPRIVATE double ImplDevicePixelToLogicHeightDouble(double nHeight) const; diff --git a/include/vcl/outdev/OpenTypeMathConstant.hxx b/include/vcl/outdev/OpenTypeMathConstant.hxx new file mode 100644 index 000000000000..b282a56c091d --- /dev/null +++ b/include/vcl/outdev/OpenTypeMathConstant.hxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +namespace vcl +{ +enum OpenTypeMathConstant +{ + // The order of the constants must match the order of the fields + // defined in the MATH table. + ScriptPercentScaleDown, + ScriptScriptPercentScaleDown, + DelimitedSubFormulaMinHeight, + DisplayOperatorMinHeight, + MathLeading, + AxisHeight, + AccentBaseHeight, + FlattenedAccentBaseHeight, + SubscriptShiftDown, + SubscriptTopMax, + SubscriptBaselineDropMin, + SuperscriptShiftUp, + SuperscriptShiftUpCramped, + SuperscriptBottomMin, + SuperscriptBaselineDropMax, + SubSuperscriptGapMin, + SuperscriptBottomMaxWithSubscript, + SpaceAfterScript, + UpperLimitGapMin, + UpperLimitBaselineRiseMin, + LowerLimitGapMin, + LowerLimitBaselineDropMin, + StackTopShiftUp, + StackTopDisplayStyleShiftUp, + StackBottomShiftDown, + StackBottomDisplayStyleShiftDown, + StackGapMin, + StackDisplayStyleGapMin, + StretchStackTopShiftUp, + StretchStackBottomShiftDown, + StretchStackGapAboveMin, + StretchStackGapBelowMin, + FractionNumeratorShiftUp, + FractionNumeratorDisplayStyleShiftUp, + FractionDenominatorShiftDown, + FractionDenominatorDisplayStyleShiftDown, + FractionNumeratorGapMin, + FractionNumDisplayStyleGapMin, + FractionRuleThickness, + FractionDenominatorGapMin, + FractionDenomDisplayStyleGapMin, + SkewedFractionHorizontalGap, + SkewedFractionVerticalGap, + OverbarVerticalGap, + OverbarRuleThickness, + OverbarExtraAscender, + UnderbarVerticalGap, + UnderbarRuleThickness, + UnderbarExtraDescender, + RadicalVerticalGap, + RadicalDisplayStyleVerticalGap, + RadicalRuleThickness, + RadicalExtraAscender, + RadicalKernBeforeDegree, + RadicalKernAfterDegree, + RadicalDegreeBottomRaisePercent +}; +} \ No newline at end of file diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx index 40054651ea1e..629c8223d893 100644 --- a/include/vcl/pdfread.hxx +++ b/include/vcl/pdfread.hxx @@ -80,6 +80,22 @@ struct PDFGraphicAnnotation pdf::PDFAnnotationSubType meSubType; std::shared_ptr mpMarker; + + /// Raw /F value (annotation flags bitfield). 0 if absent. + int mnFlags = 0; + /// Pdfium index of this annotation on its page. Indices are page-scoped; PDF spec requires + /// /IRT parents to live on the same page as the referring annotation, so a per-page map is + /// sufficient to resolve them. + int mnPdfiumIndex = -1; + /// Pdfium index of the parent annotation (/IRT) on the same page; -1 if root (no /IRT) or + /// if the PDF is malformed and /IRT pointed to a different page. + int mnParentPdfiumIndex = -1; + /// /RT (reply type): "R" = reply (default), "Group" = grouped with parent but not a reply. + OUString maReplyType = u"R"_ustr; + /// Raw /State value (e.g. "Marked", "Unmarked", "Accepted", "Completed"). + OUString maState; + /// Raw /StateModel value ("Marked" or "Review"). + OUString maStateModel; }; class PDFGraphicResult @@ -113,9 +129,17 @@ public: /// Import PDF as Graphic images (1 per page), but not loaded yet. /// Returns the number of pages read. -VCL_DLLPUBLIC size_t ImportPDFUnloaded(const OUString& rURL, - std::vector& rGraphics); -VCL_DLLPUBLIC size_t ImportPDFUnloaded(SvStream& rStream, std::vector& rGraphics); +/// xInteractionHandler and rPassword let an encrypted (and/or too-new) PDF be +/// decrypted for the version downgrade - the password is used directly when +/// given, otherwise the handler is asked. +VCL_DLLPUBLIC size_t ImportPDFUnloaded( + const OUString& rURL, std::vector& rGraphics, + const css::uno::Reference& xInteractionHandler = nullptr, + const OUString& rPassword = OUString()); +VCL_DLLPUBLIC size_t ImportPDFUnloaded( + SvStream& rStream, std::vector& rGraphics, + const css::uno::Reference& xInteractionHandler = nullptr, + const OUString& rPassword = OUString()); } #endif // INCLUDED_VCL_SOURCE_FILTER_IPDF_PDFREAD_HXX diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx index a61ae22a95b1..800b4eba3d48 100644 --- a/include/vcl/pdfwriter.hxx +++ b/include/vcl/pdfwriter.hxx @@ -877,9 +877,6 @@ public: void DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap, const Graphic& rGraphic ); - void DrawBitmap( const Point& rDestPt, const Size& rDestSize, - const Bitmap& rBitmap ); - void DrawGradient( const tools::Rectangle& rRect, const Gradient& rGradient ); void DrawGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient ); diff --git a/include/vcl/print.hxx b/include/vcl/print.hxx index c6e923ad4f16..f8dcaaaba393 100644 --- a/include/vcl/print.hxx +++ b/include/vcl/print.hxx @@ -260,7 +260,6 @@ public: const Size& GetPaperSizePixel() const { return maPaperSize; } Size GetPaperSize() const { return PixelToLogic( maPaperSize ); } - SAL_DLLPRIVATE Size GetPaperSize( int nPaper ) const; const Point& GetPageOffsetPixel() const { return maPageOffset; } Point GetPageOffset() const { return PixelToLogic( maPageOffset ); } diff --git a/include/vcl/rendercontext/ImplMapRes.hxx b/include/vcl/rendercontext/ImplMapRes.hxx index 93713c000e01..8a042eb2ff8d 100644 --- a/include/vcl/rendercontext/ImplMapRes.hxx +++ b/include/vcl/rendercontext/ImplMapRes.hxx @@ -20,10 +20,17 @@ #pragma once #include +#include + +class MapMode; struct ImplMapRes { ImplMapRes() = default; + void SetMapRes(const o3tl::Length eUnit); + void CalcMapResolution(const MapMode& rMapMode, tools::Long nDPIX, tools::Long nDPIY); + ImplMapRes ResolveMapRes(const MapMode* pMode, const MapMode& rDefaultMapMode, bool bMap, + tools::Long nDPIX, tools::Long nDPIY); tools::Long mnMapOfsX = 0; ///< Offset in X direction tools::Long mnMapOfsY = 0; ///< Offset in Y direction diff --git a/include/vcl/salctype.hxx b/include/vcl/salctype.hxx index c52128aef51d..37a2aefe61f6 100644 --- a/include/vcl/salctype.hxx +++ b/include/vcl/salctype.hxx @@ -31,6 +31,7 @@ enum class ConvertDataFormat BMP, GIF, JPG, + JXL, MET, PCT, PNG, diff --git a/include/vcl/salnativewidgets.hxx b/include/vcl/salnativewidgets.hxx index 903ddfccc29d..02addc5d83a2 100644 --- a/include/vcl/salnativewidgets.hxx +++ b/include/vcl/salnativewidgets.hxx @@ -47,7 +47,7 @@ enum class ControlType { Editbox = 30, // Control that allows text entry, but without the usual border // Has to be handled separately, because this one cannot handle -// ControlPart::HasBackgroundTexture, which is drawn in the edit box'es +// ControlPart::HasBackgroundTexture, which is drawn in the edit box's // border window. EditboxNoBorder = 31, // Control that allows text entry @@ -87,7 +87,7 @@ enum class ControlType { MenuPopup = 121, Progress = 131, // Progress bar for the intro window -// (aka splash screen), in case some +// (aka splash screen), in case someone // wants native progress bar in the // application but not for the splash // screen (used in desktop/) @@ -97,7 +97,7 @@ enum class ControlType { Tooltip = 140, // to draw the implemented theme WindowBackground = 150, -//to draw border of frames natively +// to draw border of frames natively Frame = 160, // for nodes in listviews // used in svtools/source/contnr/svtreebx.cxx @@ -313,7 +313,7 @@ class VCL_DLLPUBLIC TabPaneValue final : public ImplControlValue public: tools::Rectangle m_aTabHeaderRect; tools::Rectangle m_aSelectedTabRect; - // increased tab size, so it'll overlab the frame rect when drawing + // increased tab size, so it'll overlap the frame rect when drawing // static value, as there is currently no sane way to return additional data static int m_nOverlap; diff --git a/include/vcl/settings.hxx b/include/vcl/settings.hxx index 0a8cc7fb3f30..7e2dd91083b2 100644 --- a/include/vcl/settings.hxx +++ b/include/vcl/settings.hxx @@ -447,7 +447,6 @@ public: const Color& GetInactiveTabColor() const; void SetAlternatingRowColor(const Color& rColor); - SAL_DLLPRIVATE const Color& GetAlternatingRowColor() const; void SetHighContrastMode(bool bHighContrast ); bool GetHighContrastMode() const; @@ -576,7 +575,6 @@ public: void SetToolbarIconSize( ToolbarIconSize nSize ); ToolbarIconSize GetToolbarIconSize() const; - SAL_DLLPRIVATE Size GetToolbarIconSizePixel() const; /** Set the icon theme to use. */ void SetIconTheme(const OUString&); diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx index d009221a4053..288758ee70a7 100644 --- a/include/vcl/svapp.hxx +++ b/include/vcl/svapp.hxx @@ -1237,22 +1237,12 @@ public: ///@} - /** Set safe mode to enabled */ + /** Set troubleshoot mode to enabled */ static void EnableSafeMode(); - /** Determines if safe mode is enabled */ + /** Determines if troubleshoot mode is enabled */ static bool IsSafeModeEnabled(); - /** Collect what .ui files are used*/ - static void EnableUICoverage(bool bEnable); - - /** Report on what .ui files were used*/ - static void UICoverageReport(tools::JsonWriter& rJson, - /*LibreOfficeKitDocumentType*/ int eDocType, - bool linguisticDataAvailable); - - ///@} - /** Get the desktop environment the process is currently running in @returns The desktop environment @@ -1333,13 +1323,14 @@ public: // For vclbootstrapprotector: static void setDeInitHook(Link const & hook); - static std::unique_ptr CreateBuilder(weld::Widget* pParent, const OUString &rUIFile, bool bMobile = false, sal_uInt64 nLOKWindowId = 0); + static std::unique_ptr CreateBuilder(weld::Widget* pParent, const OUString &rUIFile); // For the duration of vcl parent windows - static std::unique_ptr CreateInterimBuilder(vcl::Window* pParent, const OUString &rUIFile, bool bAllowCycleFocusOut, sal_uInt64 nLOKWindowId = 0); + static std::unique_ptr + CreateInterimBuilder(vcl::Window* pParent, const OUString& rUIFile, bool bAllowCycleFocusOut); - static weld::MessageDialog* CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, - VclButtonsType eButtonType, const OUString& rPrimaryMessage, - const ILibreOfficeKitNotifier* pNotifier = nullptr); + static std::unique_ptr + CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, + VclButtonsType eButtonType, const OUString& rPrimaryMessage); static weld::Window* GetFrameWeld(const css::uno::Reference& rWindow); diff --git a/include/vcl/syswin.hxx b/include/vcl/syswin.hxx index 90147f5b1d25..3c4428de2f48 100644 --- a/include/vcl/syswin.hxx +++ b/include/vcl/syswin.hxx @@ -160,8 +160,6 @@ protected: WindowType eType, const char* pIdleDebugName, bool transferableIdle = false); SAL_DLLPRIVATE void loadUI(vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription, const css::uno::Reference &rFrame = css::uno::Reference()); - SAL_DLLPRIVATE void SetWindowState(const vcl::WindowData& rData); - virtual void settingOptimalLayoutSize(Window *pBox); SAL_DLLPRIVATE void DoInitialLayout(); @@ -200,8 +198,8 @@ public: SAL_DLLPRIVATE void SetMaxOutputSizePixel( const Size& rSize ); SAL_DLLPRIVATE const Size& GetMaxOutputSizePixel() const; - void SetWindowState(std::u16string_view rStr); - OUString GetWindowState(vcl::WindowDataMask nMask = vcl::WindowDataMask::All) const; + void SetWindowState(const vcl::WindowData& rData); + vcl::WindowData GetWindowState(vcl::WindowDataMask nMask = vcl::WindowDataMask::All) const; void SetMenuBar(MenuBar* pMenuBar); MenuBar* GetMenuBar() const { return mpMenuBar; } @@ -218,7 +216,6 @@ public: VclPtr const & GetNotebookBar() const; TaskPaneList* GetTaskPaneList(); - SAL_DLLPRIVATE void GetWindowState(vcl::WindowData& rData) const; virtual void SetText( const OUString& rStr ) override; virtual OUString GetText() const override; diff --git a/include/vcl/tabctrl.hxx b/include/vcl/tabctrl.hxx index 28987536ad9c..09636a7b52a7 100644 --- a/include/vcl/tabctrl.hxx +++ b/include/vcl/tabctrl.hxx @@ -169,8 +169,6 @@ public: virtual void queue_resize(StateChangedType eReason = StateChangedType::Layout) override; virtual bool set_property(const OUString &rKey, const OUString &rValue) override; - - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; }; class NotebookBar; diff --git a/include/vcl/tabpage.hxx b/include/vcl/tabpage.hxx index 2ea45400f3ff..9b0ea3b8a75f 100644 --- a/include/vcl/tabpage.hxx +++ b/include/vcl/tabpage.hxx @@ -49,7 +49,7 @@ public: virtual void dispose() override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void StateChanged( StateChangedType nStateChange ) override; virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; diff --git a/include/vcl/tabs.hrc b/include/vcl/tabs.hrc index b3053d658fe7..147e3dcdbd75 100644 --- a/include/vcl/tabs.hrc +++ b/include/vcl/tabs.hrc @@ -65,6 +65,7 @@ inline constexpr TabData RID_TAB_TEXTGRID{ NC_("RID_TAB_TEXTGRID", "Text Grid"), // list inline constexpr TabData RID_TAB_UNOORDERED{ NC_("RID_TAB_UNOORDERED", "Unordered"), u"defaultbullet.png"_ustr }; inline constexpr TabData RID_TAB_ORDERED{ NC_("RID_TAB_ORDERED", "Ordered"), u"defaultnumbering.png"_ustr }; +// Translators: Outline as in an overview inline constexpr TabData RID_TAB_OUTLINE{ NC_("RID_TAB_OUTLINE", "Outline"), u"setoutline.png"_ustr }; inline constexpr TabData RID_TAB_IMAGE{ NC_("RID_TAB_IMAGE", "Image"), u"imagebutton.png"_ustr }; inline constexpr TabData RID_TAB_CUSTOMIZE{ NC_("RID_TAB_CUSTOMIZE", "Customize"), u"developmenttoolsdockingwindow.png"_ustr }; @@ -150,7 +151,7 @@ inline constexpr TabData RID_TAB_MENUS{ NC_("RID_TAB_MENUS", "Menus"), u"menubar inline constexpr TabData RID_TAB_TOOLBARS{ NC_("RID_TAB_TOOLBARS", "Toolbars"), u"showtoolbar.png"_ustr }; inline constexpr TabData RID_TAB_NOTEBOOKBARS{ NC_("RID_TAB_NOTEBOOKBARS", "Notebookbars"), u"toggletabbarvisibility.png"_ustr }; inline constexpr TabData RID_TAB_CONTEXTMENUS{ NC_("RID_TAB_CONTEXTMENUS", "Context Menus"), u"listbox.png"_ustr }; -inline constexpr TabData RID_TAB_KEYBOARD{ NC_("RID_TAB_KEYBOARD", "Keyboard"), u"underline.png"_ustr }; +inline constexpr TabData RID_TAB_KEYBOARD{ NC_("RID_TAB_KEYBOARD", "Keyboard"), u"shortcutkeysdialog.png"_ustr }; inline constexpr TabData RID_TAB_EVENTS{ NC_("RID_TAB_EVENTS", "Events"), u"choosemacro.png"_ustr }; // ui mode inline constexpr TabData RID_TAB_UIMODE{ NC_("RID_TAB_UIMODE", "UI Mode"), u"toggletabbarvisibility.png"_ustr }; diff --git a/include/vcl/themecolors.hxx b/include/vcl/themecolors.hxx index 74bdbe4cf508..9e31c2fd8611 100644 --- a/include/vcl/themecolors.hxx +++ b/include/vcl/themecolors.hxx @@ -43,7 +43,6 @@ class VCL_DLLPUBLIC ThemeColors public: static ThemeColors& GetThemeColors() { return m_aThemeColors; } - static void SetThemeColors(const ThemeColors& rThemeColors) { m_aThemeColors = rThemeColors; } static bool IsThemeCached() { return m_bIsThemeCached; } static void SetThemeCached(bool bCached) { m_bIsThemeCached = bCached; } @@ -147,7 +146,6 @@ public: const Color& GetMenuHighlightColor() const { return m_aMenuHighlightColor; } const Color& GetMenuHighlightTextColor() const { return m_aMenuhighlightTextColor; } const Color& GetMenuBorderColor() const { return m_aMenuBorderColor; } - const Color& GetInactiveColor() const { return m_aInactiveColor; } const Color& GetInactiveTextColor() const { return m_aInactiveTextColor; } const Color& GetInactiveBorderColor() const { return m_aInactiveBorderColor; } const OUString& GetThemeName() const { return m_sThemeName; } diff --git a/include/vcl/toolbox.hxx b/include/vcl/toolbox.hxx index 26077c7b44f3..fe3652d34d6f 100644 --- a/include/vcl/toolbox.hxx +++ b/include/vcl/toolbox.hxx @@ -509,8 +509,6 @@ public: void SetToolBoxTextPosition( ToolBoxTextPosition ePosition ); void SetLineSpacing(bool b) { mbLineSpacing = b; } - - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; }; inline void ToolBox::CheckItem( ToolBoxItemId nItemId, bool bCheck ) diff --git a/include/vcl/toolkit/MenuButton.hxx b/include/vcl/toolkit/MenuButton.hxx index 8aaf61d0584f..7b8a4dde39a1 100644 --- a/include/vcl/toolkit/MenuButton.hxx +++ b/include/vcl/toolkit/MenuButton.hxx @@ -84,8 +84,6 @@ public: virtual FactoryFunction GetUITestFactory() const override; void SetCurItemId(); - - virtual void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/toolkit/button.hxx b/include/vcl/toolkit/button.hxx index e6c1572d2290..bc1feb0dfcaf 100644 --- a/include/vcl/toolkit/button.hxx +++ b/include/vcl/toolkit/button.hxx @@ -102,8 +102,6 @@ public: virtual FactoryFunction GetUITestFactory() const override; - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; - protected: /// Handler for click, in case we want the button to handle uno commands (.uno:Something). @@ -133,7 +131,7 @@ public: virtual void KeyInput( const KeyEvent& rKEvt ) override; virtual void KeyUp( const KeyEvent& rKEvt ) override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Resize() override; virtual void GetFocus() override; virtual void LoseFocus() override; @@ -177,8 +175,6 @@ public: return mbIsAction; } - void DumpAsPropertyTree(tools::JsonWriter&) override; - bool isToggleButton() { return mbIsToggleButton; } void setToggleButton(bool bIsToggleButton) { mbIsToggleButton = bIsToggleButton; } @@ -332,7 +328,7 @@ public: virtual void KeyInput( const KeyEvent& rKEvt ) override; virtual void KeyUp( const KeyEvent& rKEvt ) override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Resize() override; virtual void GetFocus() override; virtual void LoseFocus() override; @@ -368,9 +364,6 @@ public: virtual bool set_property(const OUString &rKey, const OUString &rValue) override; virtual void ShowFocus(const tools::Rectangle& rRect) override; - /// Button has additional stuff that we need to dump too. - void DumpAsPropertyTree(tools::JsonWriter&) override; - virtual FactoryFunction GetUITestFactory() const override; }; @@ -438,7 +431,7 @@ public: virtual void KeyInput( const KeyEvent& rKEvt ) override; virtual void KeyUp( const KeyEvent& rKEvt ) override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Resize() override; virtual void GetFocus() override; virtual void LoseFocus() override; @@ -489,9 +482,6 @@ public: SAL_DLLPRIVATE void group(RadioButton &rOther); virtual void ShowFocus(const tools::Rectangle& rRect) override; - /// Button has additional stuff that we need to dump too. - void DumpAsPropertyTree(tools::JsonWriter&) override; - virtual FactoryFunction GetUITestFactory() const override; }; diff --git a/include/vcl/toolkit/calendar.hxx b/include/vcl/toolkit/calendar.hxx index dfda5b5bed2c..307981084cb9 100644 --- a/include/vcl/toolkit/calendar.hxx +++ b/include/vcl/toolkit/calendar.hxx @@ -27,7 +27,8 @@ #include #include -#include +#include +#include class FloatingWindow; struct ImplCFieldFloatWin; diff --git a/include/vcl/toolkit/combobox.hxx b/include/vcl/toolkit/combobox.hxx index f2d3527dc52e..5407e9924b2e 100644 --- a/include/vcl/toolkit/combobox.hxx +++ b/include/vcl/toolkit/combobox.hxx @@ -88,7 +88,7 @@ public: virtual rtl::Reference CreateAccessible() override; - virtual void Draw( OutputDevice* pDev, const Point& rPos,SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Resize() override; virtual bool EventNotify( NotifyEvent& rNEvt ) override; virtual void StateChanged( StateChangedType nType ) override; @@ -222,8 +222,6 @@ public: virtual bool set_property(const OUString &rKey, const OUString &rValue) override; virtual FactoryFunction GetUITestFactory() const override; - - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/toolkit/dialog.hxx b/include/vcl/toolkit/dialog.hxx index a75467a2dacd..2acc477bf39f 100644 --- a/include/vcl/toolkit/dialog.hxx +++ b/include/vcl/toolkit/dialog.hxx @@ -92,7 +92,7 @@ public: protected: explicit Dialog( WindowType eType ); - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void settingOptimalLayoutSize(Window *pBox) override; protected: @@ -110,7 +110,6 @@ public: virtual bool EventNotify( NotifyEvent& rNEvt ) override; virtual void StateChanged( StateChangedType nStateChange ) override; virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; - virtual void PixelInvalidate(const tools::Rectangle* pRectangle) override; virtual void queue_resize(StateChangedType eReason = StateChangedType::Layout) override; virtual bool set_property(const OUString &rKey, const OUString &rValue) override; @@ -153,14 +152,11 @@ public: void Activate() override; void SetInstallLOKNotifierHdl(const Link& rLink); - void SetLOKTunnelingState(bool bEnabled); void add_button(PushButton* pButton, int nResponse, bool bTransferOwnership); void set_default_response(int nResponse); int get_default_response() const; vcl::Window* get_widget_for_response(int nResponse); - - void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/toolkit/edit.hxx b/include/vcl/toolkit/edit.hxx index 36ca40d3b9e7..c731c0b4bbe7 100644 --- a/include/vcl/toolkit/edit.hxx +++ b/include/vcl/toolkit/edit.hxx @@ -155,7 +155,7 @@ public: virtual void KeyInput( const KeyEvent& rKEvt ) override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; virtual void Resize() override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void GetFocus() override; virtual void LoseFocus() override; virtual void Tracking( const TrackingEvent& rTEvt ) override; @@ -246,8 +246,6 @@ public: bool IsPassword() const { return mbPassword; } bool IsActivePopup() const { return mbActivePopup; } - - virtual void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/toolkit/field.hxx b/include/vcl/toolkit/field.hxx index e1f3b9e9d316..b9dfede08193 100644 --- a/include/vcl/toolkit/field.hxx +++ b/include/vcl/toolkit/field.hxx @@ -232,7 +232,6 @@ public: SAL_DLLPRIVATE virtual bool set_property(const OUString &rKey, const OUString &rValue) override; SAL_DLLPRIVATE virtual void dispose() override; - SAL_DLLPRIVATE virtual void DumpAsPropertyTree(tools::JsonWriter&) override; SAL_DLLPRIVATE virtual FactoryFunction GetUITestFactory() const override; }; diff --git a/include/vcl/toolkit/fixed.hxx b/include/vcl/toolkit/fixed.hxx index fb1452fabf02..5264b624b05c 100644 --- a/include/vcl/toolkit/fixed.hxx +++ b/include/vcl/toolkit/fixed.hxx @@ -33,6 +33,7 @@ class VCL_DLLPUBLIC FixedText : public Control private: sal_Int32 m_nMaxWidthChars; sal_Int32 m_nMinWidthChars; + mutable tools::Long m_nLastAllocatedWidth {-1}; VclPtr m_pMnemonicWindow; using Control::ImplInitSettings; @@ -62,7 +63,7 @@ public: virtual void ApplySettings(vcl::RenderContext& rRenderContext) override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Resize() override; virtual void StateChanged( StateChangedType nType ) override; virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; @@ -85,7 +86,6 @@ public: virtual void LoseFocus() override; virtual void ApplySettings(vcl::RenderContext&) override; - virtual void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; }; class UNLESS_MERGELIBS(VCL_DLLPUBLIC) FixedLine final : public Control @@ -109,13 +109,12 @@ public: virtual void ApplySettings(vcl::RenderContext&) override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Resize() override; virtual void StateChanged( StateChangedType nType ) override; virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; virtual Size GetOptimalSize() const override; - virtual void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; }; class VCL_DLLPUBLIC FixedBitmap final : public Control @@ -135,7 +134,8 @@ public: SAL_DLLPRIVATE virtual void ApplySettings(vcl::RenderContext&) override; SAL_DLLPRIVATE virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - SAL_DLLPRIVATE virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + SAL_DLLPRIVATE virtual void Draw(OutputDevice& rDev, const Point& rPos, + SystemTextColorFlags nFlags) override; SAL_DLLPRIVATE virtual void Resize() override; SAL_DLLPRIVATE virtual void StateChanged( StateChangedType nType ) override; SAL_DLLPRIVATE virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; @@ -163,7 +163,8 @@ public: SAL_DLLPRIVATE virtual void ApplySettings(vcl::RenderContext&) override; SAL_DLLPRIVATE virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - SAL_DLLPRIVATE virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + SAL_DLLPRIVATE virtual void Draw(OutputDevice& rDev, const Point& rPos, + SystemTextColorFlags nFlags) override; SAL_DLLPRIVATE virtual void Resize() override; SAL_DLLPRIVATE virtual void StateChanged( StateChangedType nType ) override; SAL_DLLPRIVATE virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; @@ -174,8 +175,6 @@ public: const Image& GetModeImage( ) const { return maImage;} SAL_DLLPRIVATE virtual bool set_property(const OUString &rKey, const OUString &rValue) override; - - SAL_DLLPRIVATE void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/toolkit/fmtfield.hxx b/include/vcl/toolkit/fmtfield.hxx index 9babaa74f909..a13085c6882c 100644 --- a/include/vcl/toolkit/fmtfield.hxx +++ b/include/vcl/toolkit/fmtfield.hxx @@ -50,8 +50,6 @@ public: void SetValueFromString(const OUString& rStr); // currently used by online - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; - virtual FactoryFunction GetUITestFactory() const override; Formatter& GetFormatter(); diff --git a/include/vcl/toolkit/group.hxx b/include/vcl/toolkit/group.hxx index 81e595ec2da5..59638b9a0830 100644 --- a/include/vcl/toolkit/group.hxx +++ b/include/vcl/toolkit/group.hxx @@ -48,7 +48,7 @@ public: explicit GroupBox( vcl::Window* pParent, WinBits nStyle ); virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Resize() override; virtual void StateChanged( StateChangedType nType ) override; virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; diff --git a/include/vcl/toolkit/imgctrl.hxx b/include/vcl/toolkit/imgctrl.hxx index 20b1863a0071..4127b3bd79e8 100644 --- a/include/vcl/toolkit/imgctrl.hxx +++ b/include/vcl/toolkit/imgctrl.hxx @@ -40,7 +40,7 @@ public: ::sal_Int16 GetScaleMode() const { return mnScaleMode; } virtual void Resize() override; - virtual void Draw( OutputDevice* pDev, const Point& rPos,SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; virtual void GetFocus() override; virtual void LoseFocus() override; diff --git a/include/vcl/toolkit/lstbox.hxx b/include/vcl/toolkit/lstbox.hxx index f0d9563fac0f..4a3ca54d8e3e 100644 --- a/include/vcl/toolkit/lstbox.hxx +++ b/include/vcl/toolkit/lstbox.hxx @@ -126,7 +126,8 @@ public: virtual rtl::Reference CreateAccessible() override; SAL_DLLPRIVATE virtual void ApplySettings(vcl::RenderContext& rRenderContext) override; - SAL_DLLPRIVATE virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + SAL_DLLPRIVATE virtual void Draw(OutputDevice& rDev, const Point& rPos, + SystemTextColorFlags nFlags) override; SAL_DLLPRIVATE virtual void Resize() override; SAL_DLLPRIVATE virtual bool PreNotify( NotifyEvent& rNEvt ) override; SAL_DLLPRIVATE virtual void StateChanged( StateChangedType nType ) override; @@ -256,8 +257,6 @@ public: SAL_DLLPRIVATE virtual bool set_property(const OUString &rKey, const OUString &rValue) override; SAL_DLLPRIVATE virtual FactoryFunction GetUITestFactory() const override; - - SAL_DLLPRIVATE virtual void DumpAsPropertyTree(tools::JsonWriter&) override; }; class UNLESS_MERGELIBS(VCL_DLLPUBLIC) MultiListBox final : public ListBox diff --git a/include/vcl/toolkit/prgsbar.hxx b/include/vcl/toolkit/prgsbar.hxx index 48b368f0e7c8..983a12d6689d 100644 --- a/include/vcl/toolkit/prgsbar.hxx +++ b/include/vcl/toolkit/prgsbar.hxx @@ -68,14 +68,9 @@ private: bool mbCalcNew; BarStyle meBarStyle; - using Window::ImplInit; - SAL_DLLPRIVATE void ImplInit(); SAL_DLLPRIVATE void ImplInitSettings( bool bFont, bool bForeground, bool bBackground ); SAL_DLLPRIVATE void ImplDrawProgress(vcl::RenderContext& rRenderContext, sal_uInt16 nNewPerc); -protected: - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; - public: ProgressBar( vcl::Window* pParent, WinBits nWinBits, BarStyle eBarStyle ); diff --git a/include/vcl/toolkit/scrbar.hxx b/include/vcl/toolkit/scrbar.hxx index ae0449136aec..4f78fec7a3fc 100644 --- a/include/vcl/toolkit/scrbar.hxx +++ b/include/vcl/toolkit/scrbar.hxx @@ -98,7 +98,7 @@ public: virtual void Tracking(const TrackingEvent& rTEvt) override; virtual void KeyInput(const KeyEvent& rKEvt) override; virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; - virtual void Draw(OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void Move() override; virtual void Resize() override; virtual void StateChanged(StateChangedType nType) override; diff --git a/include/vcl/toolkit/spin.hxx b/include/vcl/toolkit/spin.hxx index 13443e8e5ba2..2e8737a6b720 100644 --- a/include/vcl/toolkit/spin.hxx +++ b/include/vcl/toolkit/spin.hxx @@ -58,7 +58,7 @@ public: virtual void Resize() override; virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - virtual void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; virtual void MouseButtonUp( const MouseEvent& rMEvt ) override; virtual void MouseMove( const MouseEvent& rMEvt ) override; diff --git a/include/vcl/toolkit/spinfld.hxx b/include/vcl/toolkit/spinfld.hxx index 8a8df700b323..76338467c252 100644 --- a/include/vcl/toolkit/spinfld.hxx +++ b/include/vcl/toolkit/spinfld.hxx @@ -45,7 +45,8 @@ public: SAL_DLLPRIVATE virtual void MouseButtonUp( const MouseEvent& rMEvt ) override; SAL_DLLPRIVATE virtual void MouseMove( const MouseEvent& rMEvt ) override; SAL_DLLPRIVATE virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; - SAL_DLLPRIVATE virtual void Draw( OutputDevice* pDev, const Point& rPos,SystemTextColorFlags nFlags ) override; + SAL_DLLPRIVATE virtual void Draw(OutputDevice& rDev, const Point& rPos, + SystemTextColorFlags nFlags) override; SAL_DLLPRIVATE virtual void Resize() override; SAL_DLLPRIVATE virtual void StateChanged( StateChangedType nType ) override; SAL_DLLPRIVATE virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; diff --git a/include/vcl/toolkit/svlbitm.hxx b/include/vcl/toolkit/svlbitm.hxx index 54599da0b915..14ddf1961a93 100644 --- a/include/vcl/toolkit/svlbitm.hxx +++ b/include/vcl/toolkit/svlbitm.hxx @@ -23,7 +23,6 @@ #error "don't use this in new code" #endif -#include #include #include #include @@ -32,8 +31,6 @@ #include class SvTreeListEntry; -class SvLBoxButton; - enum class SvBmp { @@ -58,46 +55,6 @@ namespace o3tl template<> struct typed_flags : is_typed_flags {}; } -class SvLBoxButtonData -{ -private: - Link aLink; - Size m_aSize; - bool bDataOk; - std::map aBmps; - - SvTreeListEntry* m_pEntry; - SvLBoxButton* m_pBox; - bool m_bShowRadioButton; - - void SetWidthAndHeight(); -public: - // include creating default images (CheckBox or RadioButton) - SvLBoxButtonData(const Control& rControlForSettings, bool _bRadioBtn); - - ~SvLBoxButtonData(); - - static SvBmp GetIndex( SvItemStateFlags nItemState ); - const Size & GetSize(); - void SetLink( const Link& rLink) { aLink=rLink; } - bool IsRadio() const; - // as buttons are not derived from LinkHdl - void CallLink(); - - void StoreButtonState(SvTreeListEntry* pActEntry, SvLBoxButton* pActBox); - static SvButtonState ConvertToButtonState( SvItemStateFlags nItemFlags ); - - SvTreeListEntry* GetActEntry() const; - SvLBoxButton* GetActBox() const; - - Image& GetImage(SvBmp eIndex) { return aBmps.at(eIndex); } - - void SetDefaultImages(const Control& rControlForSettings); - // set images according to the color scheme of the Control -}; - -// ********************************************************************** - class UNLESS_MERGELIBS(VCL_DLLPUBLIC) SvLBoxString : public SvLBoxItem { private: @@ -114,7 +71,7 @@ public: virtual ~SvLBoxString() override; virtual SvLBoxItemType GetType() const override; - virtual void InitViewData(SvTreeListBox& rView, SvTreeListEntry* pEntry, + virtual void InitViewData(SvTreeListBox& rView, SvTreeListEntry& rEntry, SvViewDataItem* pViewData = nullptr) override; virtual int CalcWidth(const SvTreeListBox& rView) const override; @@ -125,7 +82,6 @@ public: bool IsEmphasized() const { return mbEmphasized; } void SetCustomRender() { mbCustom = true; } - bool IsCustomRender() const { return mbCustom; } const OUString& GetText() const { @@ -144,101 +100,17 @@ public: virtual std::unique_ptr Clone(SvLBoxItem const * pSource) const override; }; -class SvLBoxButton final : public SvLBoxItem -{ - bool isVis; - SvLBoxButtonData* pData; - SvItemStateFlags nItemFlags; - - static void ImplAdjustBoxSize( Size& io_rCtrlSize, ControlType i_eType, vcl::RenderContext const & pRenderContext); -public: - // An SvLBoxButton can be of two different kinds: an - // enabled checkbox (the normal kind), or a static image - // (see SV_BMP_STATICIMAGE; nFlags are effectively ignored - // for that kind). - SvLBoxButton( SvLBoxButtonData* pBData ); - SvLBoxButton(); - virtual ~SvLBoxButton() override; - virtual void InitViewData(SvTreeListBox& rView, SvTreeListEntry* pEntry, - SvViewDataItem* pViewData = nullptr) override; - - virtual SvLBoxItemType GetType() const override; - void ClickHdl( SvTreeListEntry* ); - - virtual void Paint(const Point& rPos, - SvTreeListBox& rOutDev, - vcl::RenderContext& rRenderContext, - const SvViewDataEntry* pView, - const SvTreeListEntry& rEntry) override; - - virtual std::unique_ptr Clone(SvLBoxItem const * pSource) const override; - - SvItemStateFlags GetButtonFlags() const - { - return nItemFlags; - } - bool IsStateChecked() const - { - return bool(nItemFlags & SvItemStateFlags::CHECKED); - } - bool IsStateUnchecked() const - { - return bool(nItemFlags & SvItemStateFlags::UNCHECKED); - } - bool IsStateTristate() const - { - return bool(nItemFlags & SvItemStateFlags::TRISTATE); - } - bool IsStateHilighted() const - { - return bool(nItemFlags & SvItemStateFlags::HIGHLIGHTED); - } - void SetStateChecked(); - void SetStateUnchecked(); - void SetStateTristate(); - void SetStateHilighted(bool bHilight); -}; - -inline void SvLBoxButton::SetStateChecked() -{ - nItemFlags &= SvItemStateFlags::HIGHLIGHTED; - nItemFlags |= SvItemStateFlags::CHECKED; -} - -inline void SvLBoxButton::SetStateUnchecked() -{ - nItemFlags &= SvItemStateFlags::HIGHLIGHTED; - nItemFlags |= SvItemStateFlags::UNCHECKED; -} -inline void SvLBoxButton::SetStateTristate() -{ - nItemFlags &= SvItemStateFlags::HIGHLIGHTED; - nItemFlags |= SvItemStateFlags::TRISTATE; -} -inline void SvLBoxButton::SetStateHilighted( bool bHilight ) -{ - if ( bHilight ) - nItemFlags |= SvItemStateFlags::HIGHLIGHTED; - else - nItemFlags &= ~SvItemStateFlags::HIGHLIGHTED; -} - class UNLESS_MERGELIBS(VCL_DLLPUBLIC) SvLBoxContextBmp : public SvLBoxItem { Image m_aImage1; Image m_aImage2; - bool m_bExpanded; - public: - SvLBoxContextBmp(const Image& aBmp1, - const Image& aBmp2, - bool bExpanded); - SvLBoxContextBmp(); + SvLBoxContextBmp(const Image& aBmp1, const Image& aBmp2); virtual ~SvLBoxContextBmp() override; virtual SvLBoxItemType GetType() const override; - virtual void InitViewData(SvTreeListBox& rView, SvTreeListEntry* pEntry, + virtual void InitViewData(SvTreeListBox& rView, SvTreeListEntry& rEntry, SvViewDataItem* pViewData = nullptr) override; virtual void Paint(const Point& rPos, SvTreeListBox& rOutDev, diff --git a/include/vcl/toolkit/svtabbx.hxx b/include/vcl/toolkit/svtabbx.hxx deleted file mode 100644 index 372efe963bff..000000000000 --- a/include/vcl/toolkit/svtabbx.hxx +++ /dev/null @@ -1,247 +0,0 @@ -/* -*- 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 . - */ - -#pragma once - -#if !defined(VCL_DLLIMPLEMENTATION) && !defined(TOOLKIT_DLLIMPLEMENTATION) && !defined(VCL_INTERNALS) -#error "don't use this in new code" -#endif - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -enum class SvTabListBoxRole -{ - Unknown, - Tree, // hierarchical, single-column - TreeGrid, // hierarchical, multi-column - ListBox, // flat, single-column - Grid // flat, multi-column -}; - -class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTabListBox : public SvTreeListBox -{ -private: - std::vector mvTabList; - OUString aCurEntry; - SvTabListBoxRole m_eRole; - -protected: - static std::u16string_view GetToken( std::u16string_view sStr, sal_Int32 &nIndex ); - - virtual void SetTabs() override; - virtual void InitEntry(SvTreeListEntry*, const OUString&, const Image&, const Image&) override; - - OUString GetTabEntryText( sal_uInt32 nPos, sal_uInt16 nCol ) const; - SvTreeListEntry* GetEntryOnPos( sal_uInt32 _nEntryPos ) const; - SvTreeListEntry* GetChildOnPos( SvTreeListEntry* _pParent, sal_uInt32 _nEntryPos, sal_uInt32& _rPos ) const; - -public: - SvTabListBox( vcl::Window* pParent, WinBits ); - virtual ~SvTabListBox() override; - virtual void dispose() override; - void SetTabs(const std::vector& rTabPositions); - void SetTabWidth(sal_uInt16 nTab, tools::Long tabWidth); - using SvTreeListBox::GetTab; - tools::Long GetLogicTab( sal_uInt16 nTab ); - - virtual SvTreeListEntry* InsertEntry( const OUString& rText, SvTreeListEntry* pParent = nullptr, - bool bChildrenOnDemand = false, - sal_uInt32 nPos=TREELIST_APPEND, OUString* pUserData = nullptr ) override; - - virtual SvTreeListEntry* InsertEntryToColumn( const OUString&, SvTreeListEntry* pParent, - sal_uInt32 nPos, sal_uInt16 nCol, OUString* pUserData = nullptr ); - - virtual OUString GetEntryText( SvTreeListEntry* pEntry ) const override; - static OUString GetEntryText( const SvTreeListEntry*, sal_uInt16 nCol ); - OUString GetEntryText( sal_uInt32 nPos, sal_uInt16 nCol = 0xffff ) const; - using SvTreeListBox::SetEntryText; - OUString GetCellText( sal_uInt32 nPos, sal_uInt16 nCol ) const; - - void SetTabAlignCenter(sal_uInt16 nTab); - void SetTabEditable( sal_uInt16 nTab, bool bEditable ); - void SetTabVisible( sal_uInt16 nTab, bool bVisible ); - bool GetTabVisible( sal_uInt16 nTab ); - - void SetRole(SvTabListBoxRole e) { m_eRole = e; } - - virtual void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; -}; - -// class SvHeaderTabListBox --------------------------------------------------- - -class HeaderBar; -namespace vcl { - struct SvHeaderTabListBoxImpl; -} -class AccessibleBrowseBoxHeaderCell; - -class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvHeaderTabListBox final : public SvTabListBox, public vcl::IAccessibleTableProvider -{ -private: - bool m_bFirstPaint; - VclPtr m_xHeaderBar; - rtl::Reference m_xAccessible; - std::vector> m_aAccessibleChildren; - - Link m_aEditingEntryHdl; - Link m_aEditedEntryHdl; - - DECL_DLLPRIVATE_LINK( ScrollHdl_Impl, SvTreeListBox*, void ); - DECL_DLLPRIVATE_LINK( CreateAccessibleHdl_Impl, HeaderBar*, void ); - - void RecalculateAccessibleChildren(); - -public: - SvHeaderTabListBox(vcl::Window* pParent, WinBits nBits, HeaderBar* pHeaderBar); - virtual ~SvHeaderTabListBox() override; - virtual void dispose() override; - - virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& ) override; - - HeaderBar* GetHeaderBar(); - static bool IsItemChecked( SvTreeListEntry* pEntry, sal_uInt16 nCol ); - - virtual SvTreeListEntry* InsertEntryToColumn( const OUString&, SvTreeListEntry* pParent, - sal_uInt32 nPos, sal_uInt16 nCol, OUString* pUserData = nullptr ) override; - virtual void Insert(SvTreeListEntry* pEnt, SvTreeListEntry* pPar, - sal_uInt32 nPos = TREELIST_APPEND) override; - virtual void Insert(SvTreeListEntry* pEntry, sal_uInt32 nRootPos = TREELIST_APPEND) override; - - // Accessible ------------------------------------------------------------- - - bool IsCellCheckBox( sal_Int32 _nRow, sal_uInt16 _nColumn, TriState& _rState ) const; - - /** @return The count of the rows. */ - virtual sal_Int32 GetRowCount() const override; - /** @return The count of the columns. */ - virtual sal_uInt16 GetColumnCount() const override; - - /** @return The position of the current row. */ - virtual sal_Int32 GetCurrRow() const override; - /** @return The position of the current column. */ - virtual sal_uInt16 GetCurrColumn() const override; - - /** @return The description of a row. - @param _nRow The row which description is in demand. */ - virtual OUString GetRowDescription( sal_Int32 _nRow ) const override; - /** @return The description of a column. - @param _nColumn The column which description is in demand. */ - virtual OUString GetColumnDescription( sal_uInt16 _nColumn ) const override; - - /** @return , if the object has a row header. */ - virtual bool HasRowHeader() const override; //GetColumnId - /** @return , if the object can focus a cell. */ - virtual bool GoToCell( sal_Int32 _nRow, sal_uInt16 _nColumn ) override; - - virtual void SetNoSelection() override; - using SvTabListBox::SelectAll; - virtual void SelectAll() override; - virtual void SelectRow( sal_Int32 _nRow, bool _bSelect = true, bool bExpand = true ) override; - virtual void SelectColumn( sal_uInt16 _nColumn, bool _bSelect = true ) override; - virtual sal_Int32 GetSelectedRowCount() const override; - virtual sal_Int32 GetSelectedColumnCount() const override; - /** @return , if the row is selected. */ - virtual bool IsRowSelected( sal_Int32 _nRow ) const override; - virtual bool IsColumnSelected( sal_Int32 _nColumn ) const override; - virtual void GetAllSelectedRows( css::uno::Sequence< sal_Int32 >& _rRows ) const override; - virtual void GetAllSelectedColumns( css::uno::Sequence< sal_Int32 >& _rColumns ) const override; - - /** @return , if the cell is visible. */ - virtual bool IsCellVisible( sal_Int32 _nRow, sal_uInt16 _nColumn ) const override; - virtual OUString GetAccessibleCellText( sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const override; - - virtual tools::Rectangle calcHeaderRect(bool _bIsColumnBar) override; - virtual tools::Rectangle calcTableRect() override; - virtual tools::Rectangle calcFieldRectPixel(sal_Int32 _nRow, sal_uInt16 _nColumn, bool _bIsHeader) override; - - rtl::Reference CreateAccessibleCell(sal_Int32 _nRow, - sal_uInt16 _nColumn) override; - virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleRowHeader( sal_Int32 _nRow ) override; - virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleColumnHeader( sal_uInt16 _nColumnPos ) override; - - virtual sal_Int32 GetAccessibleControlCount() const override; - rtl::Reference CreateAccessibleControl(sal_Int32 _nIndex) override; - virtual bool ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint ) override; - - virtual bool ConvertPointToCellAddress( sal_Int32& _rnRow, sal_uInt16& _rnColPos, const Point& _rPoint ) override; - virtual bool ConvertPointToRowHeader( sal_Int32& _rnRow, const Point& _rPoint ) override; - virtual bool ConvertPointToColumnHeader( sal_uInt16& _rnColPos, const Point& _rPoint ) override; - - virtual OUString GetAccessibleObjectName( AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos = -1 ) const override; - virtual OUString GetAccessibleObjectDescription( AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos = -1 ) const override; - virtual vcl::Window* GetWindowInstance() override; - - virtual void FillAccessibleStateSet( sal_Int64& _rStateSet, AccessibleBrowseBoxObjType _eType ) const override; - virtual void FillAccessibleStateSetForCell( sal_Int64& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumn ) const override; - virtual void GrabTableFocus() override; - - // OutputDevice - virtual bool GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr, int nIndex, int nLen, std::vector< tools::Rectangle >& rVector ) override; - - // Window - virtual tools::Rectangle GetWindowExtentsRelative(const vcl::Window& rRelativeWindow) const override; - virtual void GrabFocus() override; - virtual rtl::Reference GetAccessible() override; - /** Creates and returns the accessible object of the whole BrowseBox. */ - virtual rtl::Reference CreateAccessible() override; - virtual vcl::Window* GetAccessibleParentWindow() const override; - - virtual tools::Rectangle GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex) override; - virtual sal_Int32 GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint) override; - - virtual void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override; - - void SetEditingEntryHdl(const Link& rLink) - { - m_aEditingEntryHdl = rLink; - } - - void SetEditedEntryHdl(const Link& rLink) - { - m_aEditedEntryHdl = rLink; - } - - //the default NotifyStartDrag is weird to me, and defaults to enabling all - //possibilities when drag starts, while restricting it to some subset of - //the configured drag drop mode would make more sense to me, but I'm not - //going to change the baseclass - virtual DragDropMode NotifyStartDrag() override { return GetDragDropMode(); } - - virtual bool EditingEntry(SvTreeListEntry* pEntry) override - { - return m_aEditingEntryHdl.Call(pEntry); - } - - virtual bool EditedEntry(SvTreeListEntry* pEntry, const OUString& rNewText) override - { - return m_aEditedEntryHdl.Call(IterString(pEntry, rNewText)); - } -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/toolkit/treelist.hxx b/include/vcl/toolkit/treelist.hxx index f3e9d88ff564..45dfc543a267 100644 --- a/include/vcl/toolkit/treelist.hxx +++ b/include/vcl/toolkit/treelist.hxx @@ -35,17 +35,15 @@ enum class SvListAction { - INSERTED = 1, - REMOVING = 2, - REMOVED = 3, - MOVING = 4, - MOVED = 5, - CLEARING = 6, - INSERTED_TREE = 7, - INVALIDATE_ENTRY = 8, - RESORTING = 9, - RESORTED = 10, - CLEARED = 11 + INSERTED, + REMOVING, + REMOVED, + MOVING, + MOVED, + INSERTED_TREE, + INVALIDATE_ENTRY, + RESORTING, + RESORTED, }; class SvTreeListBox; @@ -68,36 +66,38 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeList final friend class SvTreeListBox; SvTreeListBox& mrOwnerListView; - sal_uInt32 nEntryCount; + sal_uInt32 m_nEntryCount; - Link aCloneLink; - Link aCompareLink; - SvSortMode eSortMode; + Link m_aCloneLink; + Link m_aCompareLink; + SvSortMode m_eSortMode; - bool bAbsPositionsValid; + bool m_bAbsPositionsValid; bool mbEnableInvalidate; + std::unique_ptr m_pRootItem; + SvTreeListEntry* FirstVisible() const { return First(); } - SvTreeListEntry* NextVisible(const SvTreeListBox*, SvTreeListEntry* pEntry, + SvTreeListEntry* NextVisible(const SvTreeListBox& rView, SvTreeListEntry* pEntry, sal_uInt16* pDepth = nullptr) const; - SvTreeListEntry* PrevVisible(const SvTreeListBox*, SvTreeListEntry* pEntry) const; - SvTreeListEntry* LastVisible(const SvTreeListBox*) const; - SvTreeListEntry* NextVisible(const SvTreeListBox*, SvTreeListEntry* pEntry, + SvTreeListEntry* PrevVisible(const SvTreeListBox& rView, SvTreeListEntry* pEntry) const; + SvTreeListEntry* LastVisible(const SvTreeListBox& rView) const; + SvTreeListEntry* NextVisible(const SvTreeListBox& rView, SvTreeListEntry* pEntry, sal_uInt16& rDelta) const; - SvTreeListEntry* PrevVisible(const SvTreeListBox*, SvTreeListEntry* pEntry, + SvTreeListEntry* PrevVisible(const SvTreeListBox& rView, SvTreeListEntry* pEntry, sal_uInt16& rDelta) const; - bool IsEntryVisible(const SvTreeListBox*, SvTreeListEntry* pEntry) const; - SvTreeListEntry* GetEntryAtVisPos(const SvTreeListBox*, sal_uInt32 nVisPos) const; - sal_uInt32 GetVisiblePos(const SvTreeListBox*, SvTreeListEntry const* pEntry) const; - sal_uInt32 GetVisibleCount(SvTreeListBox*) const; - sal_uInt32 GetVisibleChildCount(const SvTreeListBox*, SvTreeListEntry* pParent) const; + bool IsEntryVisible(const SvTreeListBox& rView, SvTreeListEntry* pEntry) const; + SvTreeListEntry* GetEntryAtVisPos(const SvTreeListBox& rView, sal_uInt32 nVisPos) const; + sal_uInt32 GetVisiblePos(const SvTreeListBox& rView, SvTreeListEntry const* pEntry) const; + sal_uInt32 GetVisibleCount(SvTreeListBox& rView) const; + sal_uInt32 GetVisibleChildCount(const SvTreeListBox& rView, SvTreeListEntry* pParent) const; - SvTreeListEntry* FirstSelected(const SvTreeListBox*) const; - SvTreeListEntry* NextSelected(const SvTreeListBox*, SvTreeListEntry* pEntry) const; + SvTreeListEntry* FirstSelected(const SvTreeListBox& rView) const; + SvTreeListEntry* NextSelected(const SvTreeListBox& rView, SvTreeListEntry* pEntry) const; - sal_uInt32 GetChildSelectionCount(const SvTreeListBox*, SvTreeListEntry* pParent) const; + sal_uInt32 GetChildSelectionCount(const SvTreeListBox& rView, SvTreeListEntry* pParent) const; SAL_DLLPRIVATE void SetAbsolutePositions(); @@ -122,34 +122,28 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeList final SvTreeList(const SvTreeList&) = delete; SvTreeList& operator= (const SvTreeList&) = delete; - std::unique_ptr pRootItem; - public: SvTreeList() = delete; SvTreeList(SvTreeListBox&); ~SvTreeList(); - void Broadcast(SvListAction nActionId, SvTreeListEntry* pEntry = nullptr); + void Broadcast(SvListAction eAction, SvTreeListEntry* pEntry = nullptr); void EnableInvalidate( bool bEnable ); bool IsEnableInvalidate() const { return mbEnableInvalidate; } // Notify all Listeners - void InvalidateEntry( SvTreeListEntry* ); + void InvalidateEntry(SvTreeListEntry& rEntry); - sal_uInt32 GetEntryCount() const { return nEntryCount; } + sal_uInt32 GetEntryCount() const { return m_nEntryCount; } SvTreeListEntry* First() const; SvTreeListEntry* Next( SvTreeListEntry* pEntry, sal_uInt16* pDepth=nullptr ) const; SvTreeListEntry* Last() const; SvTreeListEntry* FirstChild(const SvTreeListEntry* pParent) const; - void Insert(SvTreeListEntry* pEntry, SvTreeListEntry* pPar, sal_uInt32 nPos = TREELIST_APPEND); - void Insert(SvTreeListEntry* pEntry, sal_uInt32 nRootPos = TREELIST_APPEND) - { - Insert(pEntry, pRootItem.get(), nRootPos); - } + void Insert(SvTreeListEntry* pEntry, sal_uInt32 nPos, SvTreeListEntry* pPar); void InsertTree( SvTreeListEntry* pTree, SvTreeListEntry* pTargetParent, sal_uInt32 nListPos ); @@ -158,7 +152,7 @@ public: // Creates ChildList if needed sal_uInt32 Move( SvTreeListEntry* pSource, SvTreeListEntry* pTargetParent, sal_uInt32 nListPos); - sal_uInt32 Copy( SvTreeListEntry* pSource, SvTreeListEntry* pTargetParent, sal_uInt32 nListPos); + sal_uInt32 Copy(SvTreeListEntry& rSource, SvTreeListEntry* pTargetParent, sal_uInt32 nListPos); bool Remove( const SvTreeListEntry* pEntry ); void Clear(); @@ -168,11 +162,9 @@ public: SvTreeListEntry* GetEntry( sal_uInt32 nRootPos ) const; SvTreeListEntry* GetEntryAtAbsPos( sal_uInt32 nAbsPos ) const; - const SvTreeListEntry* GetParent( const SvTreeListEntry* pEntry ) const; - SvTreeListEntry* GetParent( SvTreeListEntry* pEntry ); + SvTreeListEntry* GetParent(const SvTreeListEntry* pEntry) const; const SvTreeListEntries& GetChildList( SvTreeListEntry* pParent ) const; - SvTreeListEntries& GetChildList( SvTreeListEntry* pParent ); sal_uInt32 GetAbsPos( const SvTreeListEntry* pEntry ) const; static sal_uInt32 GetRelPos( const SvTreeListEntry* pChild ); @@ -184,19 +176,18 @@ public: // The Model calls the Clone Link to clone Entries. // Thus we do not need to derive from the Model if we derive from SvTreeListEntry. // The Handler needs to return a SvTreeListEntry* - SvTreeListEntry* Clone( SvTreeListEntry* pEntry, sal_uInt32& nCloneCount ) const; - void SetCloneLink( const Link& rLink ) - { aCloneLink=rLink; } + SvTreeListEntry* Clone(SvTreeListEntry& rEntry, sal_uInt32& nCloneCount) const; + void SetCloneLink(const Link& rLink) + { + m_aCloneLink = rLink; + } - const Link& GetCloneLink() const - { return aCloneLink; } + SvTreeListEntry* CloneEntry(SvTreeListEntry& rSource) const; // Calls the Clone Link - SvTreeListEntry* CloneEntry( SvTreeListEntry* pSource ) const; // Calls the Clone Link - - void SetSortMode( SvSortMode eMode ) { eSortMode = eMode; } - SvSortMode GetSortMode() const { return eSortMode; } + void SetSortMode(SvSortMode eMode) { m_eSortMode = eMode; } + SvSortMode GetSortMode() const { return m_eSortMode; } sal_Int32 Compare(const SvTreeListEntry* pLeft, const SvTreeListEntry* pRight) const; - void SetCompareHdl( const Link& rLink ) { aCompareLink = rLink; } + void SetCompareHdl(const Link& rLink) { m_aCompareLink = rLink; } void Resort(); }; diff --git a/include/vcl/toolkit/treelistbox.hxx b/include/vcl/toolkit/treelistbox.hxx index 6fd64d4fa2d4..f85979c31c9b 100644 --- a/include/vcl/toolkit/treelistbox.hxx +++ b/include/vcl/toolkit/treelistbox.hxx @@ -126,20 +126,21 @@ public: virtual ~SvLBoxItem(); virtual SvLBoxItemType GetType() const = 0; virtual int CalcWidth(const SvTreeListBox& rView) const; - int GetWidth(const SvTreeListBox& rView, const SvTreeListEntry* pEntry) const; - int GetWidth(const SvTreeListBox& rView, const SvViewDataEntry* pData, + int GetWidth(const SvTreeListBox& rView, const SvTreeListEntry& rEntry) const; + int GetWidth(const SvTreeListBox& rView, const SvViewDataEntry& rData, sal_uInt16 nItemPos) const; - int GetHeight(const SvTreeListBox& rView, const SvTreeListEntry* pEntry) const; - static int GetHeight(const SvViewDataEntry* pData, sal_uInt16 nItemPos); + int GetHeight(const SvTreeListBox& rView, const SvTreeListEntry& rEntry) const; + static int GetHeight(const SvViewDataEntry& rData, sal_uInt16 nItemPos); void Enable(bool bEnabled) { mbDisabled = !bEnabled; } bool isEnable() const { return !mbDisabled; } virtual void Paint(const Point& rPos, SvTreeListBox& rOutDev, vcl::RenderContext& rRenderContext, const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) = 0; - virtual void InitViewData(SvTreeListBox& rView, SvTreeListEntry* pEntry, - // If != 0: this Pointer must be used! - // If == 0: it needs to be retrieved via the View - SvViewDataItem* pViewData = nullptr) = 0; + virtual void InitViewData(SvTreeListBox& rView, SvTreeListEntry& rEntry, + // If != 0: this Pointer must be used! + // If == 0: it needs to be retrieved via the View + SvViewDataItem* pViewData = nullptr) + = 0; // View-dependent data is not cloned virtual std::unique_ptr Clone(SvLBoxItem const * pSource) const = 0; }; @@ -148,11 +149,9 @@ enum class DragDropMode { NONE = 0x0000, CTRL_MOVE = 0x0001, - APP_COPY = 0x0004, // Entries may be dropped via the uppermost Entry // The DropTarget is 0 in that case ENABLE_TOP = 0x0010, - ALL = 0x0015, }; namespace o3tl { @@ -176,7 +175,20 @@ struct SvTreeListBoxImpl; typedef std::pair svtree_measure_args; typedef std::tuple svtree_render_args; -typedef std::pair IterString; + +struct EntryItemText +{ + SvTreeListEntry& m_rEntry; + const SvLBoxItem& m_rItem; + OUString m_sText; + + EntryItemText(SvTreeListEntry& rEntry, const SvLBoxItem& rItem, const OUString& rText) + : m_rEntry(rEntry) + , m_rItem(rItem) + , m_sText(rText) + { + } +}; class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListBox : public Control, public DropTargetHelper, @@ -191,7 +203,6 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListBox : public Control, friend class SalInstanceTreeView; friend class SalInstanceEntryTreeView; friend class SvTreeList; - friend class JSTreeView; using SvDataTable = std::unordered_map; SvDataTable m_DataTable; // Mapping SvTreeListEntry -> ViewData @@ -208,15 +219,11 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListBox : public Control, Link m_aExpandingHdl; Link m_aSelectHdl; Link m_aDeselectHdl; - Link m_aTooltipHdl; + Link m_aModelChangedHdl; + Link m_aTooltipHdl; Link m_aCustomRenderHdl; Link m_aCustomMeasureHdl; - Image m_aPrevInsertedExpBmp; - Image m_aPrevInsertedColBmp; - Image m_aCurInsertedExpBmp; - Image m_aCurInsertedColBmp; - short m_nContextBmpWidthMax; short m_nEntryHeightOffs; short m_nIndent; @@ -224,16 +231,15 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListBox : public Control, sal_uInt16 m_nFirstSelTab; sal_uInt16 m_nLastSelTab; tools::Long mnCheckboxItemWidth; - bool mbContextBmpExpanded; bool mbQuickSearch; // Enables type-ahead search in the check list box. bool mbActivateOnSingleClick; // Make single click "activate" a row like a double-click normally does bool mbCustomEntryRenderer; // Used to define if the list entries are updated on demand bool mbHoverSelection; // Make mouse over a row "select" a row like a single-click normally does bool mbSelectingByHover; // true during "Select" if it was due to hover bool mbIsTextColumEnabled; // true if the property name text-column is enabled - sal_Int8 mnClicksToToggle; // 0 == Click on a row not toggle its checkbox. - // 1 == Every click on row toggle its checkbox. - // 2 == First click select, second click toggle. + sal_Int8 mnClicksToToggle; // 0 == Click on a row does not toggle its checkbox. + // 1 == Every click on row toggles its checkbox. + // 2 == First click selects, second click toggles. SvTreeListEntry* m_pHdlEntry; @@ -267,12 +273,11 @@ protected: std::unique_ptr m_pEdCtrl; private: - DECL_DLLPRIVATE_LINK( CheckButtonClick, SvLBoxButtonData *, void ); DECL_DLLPRIVATE_LINK( TextEditEndedHdl_Impl, SvInplaceEdit2&, void ); // Handler that is called by TreeList to clone an Entry - DECL_DLLPRIVATE_LINK( CloneHdl_Impl, SvTreeListEntry*, SvTreeListEntry* ); + DECL_DLLPRIVATE_STATIC_LINK(SvTreeListBox, CloneHdl_Impl, SvTreeListEntry&, SvTreeListEntry*); - void ExpandListEntry(SvTreeListEntry* pParent); + void ExpandListEntry(SvTreeListEntry& rParent); void CollapseListEntry(SvTreeListEntry* pParent); bool SelectListEntry(SvTreeListEntry* pEntry, bool bSelect); @@ -282,9 +287,9 @@ private: void ActionMoving(SvTreeListEntry* pEntry); void ActionMoved(); - void ActionInserted(SvTreeListEntry* pEntry); - void ActionInsertedTree(SvTreeListEntry* pEntry); - void ActionRemoving(SvTreeListEntry* pEntry); + void ActionInserted(SvTreeListEntry& rEntry); + void ActionInsertedTree(SvTreeListEntry& rEntry); + void ActionRemoving(SvTreeListEntry& pEntry); // Handler and methods for Drag - finished handler. // The Handle retrieved by GetDragFinishedHdl can be set on the @@ -298,7 +303,7 @@ private: // after a checkbox entry is inserted, use this to get its width to support // autowidth for the 1st checkbox column - SAL_DLLPRIVATE void CheckBoxInserted(SvTreeListEntry* pEntry); + SAL_DLLPRIVATE void CheckBoxInserted(SvTreeListEntry& rEntry); SAL_DLLPRIVATE void DrawCustomEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const SvTreeListEntry& rEntry); SAL_DLLPRIVATE Size MeasureCustomEntry(vcl::RenderContext& rRenderContext, const SvTreeListEntry& rEntry) const; @@ -326,31 +331,18 @@ protected: // Invalidate children on enable/disable virtual void StateChanged( StateChangedType eType ) override; - virtual void Insert(SvTreeListEntry* pEnt, SvTreeListEntry* pPar, - sal_uInt32 nPos = TREELIST_APPEND); - virtual void Insert(SvTreeListEntry* pEntry, sal_uInt32 nRootPos = TREELIST_APPEND); + void Insert(SvTreeListEntry* pEntry, sal_uInt32 nPos, SvTreeListEntry* pParent = nullptr); // In-place editing void EditText( const OUString&, const tools::Rectangle&,const Selection&); void CancelTextEditing(); // InitViewData is called right after CreateViewData - // The Entry is has not yet been added to the View in InitViewData! - virtual void InitViewData(SvViewDataEntry*, SvTreeListEntry* pEntry); + // The Entry has not yet been added to the View in InitViewData! + void InitViewData(SvViewDataEntry& rViewData, SvTreeListEntry& rEntry); // Calls InitViewData for all Items void RecalcViewData(); - // Handler and methods for Drag - finished handler. This link can be set - // to the TransferDataContainer. The AddBox/RemoveBox methods must be - // called before the StartDrag call. - // The Remove will be called from the handler, which then calls DragFinish. - // The Remove is also called in the DTOR of the SvTreeListBox - - // so it can't be called for a deleted object. - Link GetDragFinishedHdl() const; - - // For asynchronous D'n'D - sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt, SvTreeListBox* pSourceView ); - void OnCurrentEntryChanged(); // ISearchableStringList @@ -366,40 +358,40 @@ public: sal_uInt32 GetVisibleCount() const { - return m_pModel->GetVisibleCount(const_cast(this)); + return m_pModel->GetVisibleCount(const_cast(*this)); } SvTreeListEntry* FirstVisible() const { return m_pModel->FirstVisible(); } SvTreeListEntry* NextVisible(SvTreeListEntry* pEntry) const { - return m_pModel->NextVisible(this, pEntry); + return m_pModel->NextVisible(*this, pEntry); } SvTreeListEntry* PrevVisible(SvTreeListEntry* pEntry) const { - return m_pModel->PrevVisible(this, pEntry); + return m_pModel->PrevVisible(*this, pEntry); } - SvTreeListEntry* LastVisible() const { return m_pModel->LastVisible(this); } + SvTreeListEntry* LastVisible() const { return m_pModel->LastVisible(*this); } SvTreeListEntry* NextVisible(SvTreeListEntry* pEntry, sal_uInt16& rDelta) const { - return m_pModel->NextVisible(this, pEntry, rDelta); + return m_pModel->NextVisible(*this, pEntry, rDelta); } SvTreeListEntry* PrevVisible(SvTreeListEntry* pEntry, sal_uInt16& rDelta) const { - return m_pModel->PrevVisible(this, pEntry, rDelta); + return m_pModel->PrevVisible(*this, pEntry, rDelta); } sal_uInt32 GetSelectionCount() const; - SvTreeListEntry* FirstSelected() const { return m_pModel->FirstSelected(this); } + SvTreeListEntry* FirstSelected() const { return m_pModel->FirstSelected(*this); } SvTreeListEntry* NextSelected(SvTreeListEntry* pEntry) const { - return m_pModel->NextSelected(this, pEntry); + return m_pModel->NextSelected(*this, pEntry); } SvTreeListEntry* GetEntryAtAbsPos(sal_uInt32 nAbsPos) const @@ -409,7 +401,7 @@ public: SvTreeListEntry* GetEntryAtVisPos(sal_uInt32 nVisPos) const { - return m_pModel->GetEntryAtVisPos(this, nVisPos); + return m_pModel->GetEntryAtVisPos(*this, nVisPos); } sal_uInt32 GetAbsPos(SvTreeListEntry const* pEntry) const @@ -419,25 +411,25 @@ public: sal_uInt32 GetVisiblePos(SvTreeListEntry const* pEntry) const { - return m_pModel->GetVisiblePos(this, pEntry); + return m_pModel->GetVisiblePos(*this, pEntry); } sal_uInt32 GetVisibleChildCount(SvTreeListEntry* pParent) const { - return m_pModel->GetVisibleChildCount(this, pParent); + return m_pModel->GetVisibleChildCount(*this, pParent); } bool IsEntryVisible(SvTreeListEntry* pEntry) const { - return m_pModel->IsEntryVisible(this, pEntry); + return m_pModel->IsEntryVisible(*this, pEntry); } bool IsExpanded(SvTreeListEntry* pEntry) const; bool IsAllExpanded(SvTreeListEntry* pEntry) const; bool IsSelected(const SvTreeListEntry* pEntry) const; void SetEntryFocus(SvTreeListEntry* pEntry, bool bFocus); - const SvViewDataEntry* GetViewData(const SvTreeListEntry* pEntry) const; - SvViewDataEntry* GetViewData(SvTreeListEntry* pEntry); + const SvViewDataEntry& GetViewData(const SvTreeListEntry* pEntry) const; + SvViewDataEntry& GetViewData(SvTreeListEntry* pEntry); bool HasViewData() const; SvTreeList* GetModel() const { return m_pModel.get(); } @@ -453,7 +445,6 @@ public: bool CopySelection( SvTreeListBox* pSource, SvTreeListEntry* pTarget ); bool MoveSelectionCopyFallbackPossible( SvTreeListBox* pSource, SvTreeListEntry* pTarget, bool bAllowCopyFallback ); - void RemoveSelection(); /** * Removes the entry along with all of its descendants */ @@ -476,11 +467,12 @@ public: sal_uInt32 GetChildCount( SvTreeListEntry const * pParent ) const; sal_uInt32 GetLevelChildCount( const SvTreeListEntry* pParent ) const; - SvViewDataEntry* GetViewDataEntry( SvTreeListEntry const * pEntry ) const; - SvViewDataItem* GetViewDataItem(SvTreeListEntry const *, SvLBoxItem const *); - const SvViewDataItem* GetViewDataItem(const SvTreeListEntry*, const SvLBoxItem*) const; + SvViewDataEntry& GetViewDataEntry(const SvTreeListEntry& rEntry) const; + SvViewDataItem& GetViewDataItem(const SvTreeListEntry& rEntry, const SvLBoxItem& rItem); + const SvViewDataItem& GetViewDataItem(const SvTreeListEntry& rEntry, + const SvLBoxItem& rItem) const; - OUString GetEntryTooltip(SvTreeListEntry* pEntry) const; + OUString GetEntryTooltip(SvTreeListEntry& rEntry) const; VclPtr GetEditWidget() const; // for UITest bool IsInplaceEditingEnabled() const @@ -502,7 +494,8 @@ public: } void SetExpandingHdl(const Link& rNewHdl) { m_aExpandingHdl = rNewHdl; } void SetExpandedHdl(const Link& rNewHdl) { m_aExpandedHdl = rNewHdl; } - void SetTooltipHdl(const Link& rLink) { m_aTooltipHdl = rLink; } + void SetModelChangedHdl(const Link& rLink) { m_aModelChangedHdl = rLink; } + void SetTooltipHdl(const Link& rLink) { m_aTooltipHdl = rLink; } void SetCustomRenderHdl(const Link& rLink) { m_aCustomRenderHdl = rLink; @@ -517,11 +510,12 @@ public: void SelectHdl(); void DeselectHdl(); bool DoubleClickHdl(); + void ModelChangedHdl(); SvTreeListEntry* GetHdlEntry() const { return m_pHdlEntry; } // Is called for an Entry that gets expanded with the Flag // ENTRYFLAG_CHILDREN_ON_DEMAND set. - virtual void RequestingChildren( SvTreeListEntry* pParent ); + virtual void RequestingChildren(SvTreeListEntry& rParent); // Drag & Drop // New D'n'D API @@ -531,7 +525,7 @@ public: virtual DragDropMode NotifyStartDrag(); virtual void DragFinished( sal_Int8 nDropAction ); - SvTreeListEntry* CloneEntry( SvTreeListEntry* pSource ); + static SvTreeListEntry* CloneEntry(const SvTreeListEntry& rSource); // Return value: TRISTATE_TRUE == Ok, TRISTATE_FALSE == Cancel, TRISTATE_INDET == Ok and Make visible moved entry TriState NotifyMoving( @@ -551,10 +545,10 @@ public: virtual rtl::Reference CreateAccessible() override; /** Calculate and return the bounding rectangle of an entry. - @param pEntry + @param rEntry The entry. @return The bounding rectangle of an entry. */ - tools::Rectangle GetBoundingRect(const SvTreeListEntry* pEntry); + tools::Rectangle GetBoundingRect(const SvTreeListEntry& rEntry); SvTreeFlags GetTreeFlags() const { return m_nTreeFlags; } @@ -569,20 +563,17 @@ public: SAL_DLLPRIVATE Image const & GetExpandedNodeBmp( ) const; protected: - - virtual void CalcEntryHeight(SvTreeListEntry const* pEntry); + virtual void CalcEntryHeight(const SvTreeListEntry& rEntry); void AdjustEntryHeight( const Image& rBmp ); SAL_DLLPRIVATE void AdjustEntryHeight(); - SAL_DLLPRIVATE void ImpEntryInserted( SvTreeListEntry* pEntry ); + SAL_DLLPRIVATE void ImpEntryInserted(SvTreeListEntry& rEntry); SAL_DLLPRIVATE void PaintEntry1( SvTreeListEntry&, tools::Long nLine, vcl::RenderContext& rRenderContext ); - SAL_DLLPRIVATE void InitTreeView(); SAL_DLLPRIVATE void ImplInitStyle(); void SetupDragOrigin(); - void EditItemText( SvTreeListEntry* pEntry, SvLBoxString* pItem, - const Selection& ); + void EditItemText(SvTreeListEntry& rEntry, SvLBoxString& rItem, const Selection&); void EditedText(const OUString&); // Recalculate all tabs depending on TreeListStyle and Bitmap sizes @@ -594,10 +585,7 @@ protected: SvLBoxTab* GetFirstDynamicTab( sal_uInt16& rTabPos ) const; SvLBoxTab* GetFirstTab( SvLBoxTabFlags nFlagMask, sal_uInt16& rTabPos ); void GetLastTab( SvLBoxTabFlags nFlagMask, sal_uInt16& rTabPos ); - SvLBoxTab* GetTab( SvTreeListEntry const *, SvLBoxItem const * ) const; - void ClearTabList(); - - virtual void InitEntry(SvTreeListEntry*, const OUString&, const Image&, const Image&); + SvLBoxTab* GetTab(const SvTreeListEntry&, const SvLBoxItem&) const; void NotifyScrolled(); void SetScrolledHdl(const Link& rLink) { m_aScrolledHdl = rLink; } @@ -612,8 +600,6 @@ protected: virtual void ApplySettings(vcl::RenderContext& rRenderContext) override; - void CallImplEventListeners(VclEventId nEvent, void* pData); - void ImplEditEntry( SvTreeListEntry* pEntry ); void AdjustEntryHeightAndRecalc(); @@ -627,43 +613,20 @@ public: void EnableCheckButton(SvLBoxButtonData&); - /** Returns the default image which clients should use for expanded nodes, to have a consistent user - interface experience in the whole product. - */ - static const Image& GetDefaultExpandedNodeImage( ); - - /** Returns the default image which clients should use for expanded nodes, to have a consistent user - interface experience in the whole product. - */ - static const Image& GetDefaultCollapsedNodeImage( ); - /** Sets default bitmaps for collapsed and expanded nodes. */ void SetNodeDefaultImages(); - virtual SvTreeListEntry* InsertEntry( const OUString& rText, SvTreeListEntry* pParent = nullptr, - bool bChildrenOnDemand = false, - sal_uInt32 nPos=TREELIST_APPEND, OUString* pUserData = nullptr); - - const Image& GetDefaultExpandedEntryBmp( ) const; - const Image& GetDefaultCollapsedEntryBmp( ) const; - - void SetDefaultExpandedEntryBmp( const Image& rBmp ); - void SetDefaultCollapsedEntryBmp( const Image& rBmp ); - void SetCheckButtonState( SvTreeListEntry*, SvButtonState ); SvButtonState GetCheckButtonState( SvTreeListEntry* ) const; - bool GetCheckButtonEnabled(SvTreeListEntry* pEntry) const; - void SetEntryText(SvTreeListEntry*, const OUString& ); - void SetExpandedEntryBmp( SvTreeListEntry* _pEntry, const Image& _rImage ); - void SetCollapsedEntryBmp( SvTreeListEntry* _pEntry, const Image& _rImage ); + void SetEntryText(SvTreeListEntry& rEntry, const OUString& rStr); + void SetExpandedEntryBmp(SvTreeListEntry& rEntry, const Image& _rImage); + void SetCollapsedEntryBmp(SvTreeListEntry& rEntry, const Image& _rImage); virtual OUString GetEntryText( SvTreeListEntry* pEntry ) const; - static const Image& GetExpandedEntryBmp(const SvTreeListEntry* _pEntry ); - static const Image& GetCollapsedEntryBmp(const SvTreeListEntry* _pEntry ); - - void CheckButtonHdl(); + static const Image& GetExpandedEntryBmp(const SvTreeListEntry& rEntry); + static const Image& GetCollapsedEntryBmp(const SvTreeListEntry& rEntry); void SetSublistOpenWithLeftRight(); // open/close sublist with cursor left/right @@ -671,7 +634,8 @@ public: // Edits the Entry's first StringItem, 0 == Cursor void EditEntry( SvTreeListEntry* pEntry ); virtual bool EditingEntry( SvTreeListEntry* pEntry ); - virtual bool EditedEntry( SvTreeListEntry* pEntry, const OUString& rNewText ); + virtual bool EditedEntry(SvTreeListEntry& rEntry, const SvLBoxItem& rItem, + const OUString& rNewText); virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; @@ -683,13 +647,13 @@ public: virtual void LoseFocus() override; void SetUpdateMode( bool ); - virtual void ModelHasCleared(); - virtual void ModelHasInserted(SvTreeListEntry* pEntry); - virtual void ModelHasInsertedTree(SvTreeListEntry* pEntry); - virtual void ModelIsMoving(SvTreeListEntry* pSource); - virtual void ModelHasMoved(SvTreeListEntry* pSource); - virtual void ModelIsRemoving(SvTreeListEntry* pEntry); - virtual void ModelHasRemoved(SvTreeListEntry* pEntry); + void ModelHasCleared(); + void ModelHasInserted(SvTreeListEntry& rEntry); + void ModelHasInsertedTree(SvTreeListEntry& rEntry); + void ModelIsMoving(SvTreeListEntry* pSource); + void ModelHasMoved(SvTreeListEntry* pSource); + void ModelIsRemoving(SvTreeListEntry& rEntry); + void ModelHasRemoved(SvTreeListEntry& rEntry); void ModelHasEntryInvalidated(SvTreeListEntry* pEntry); void ScrollOutputArea( short nDeltaEntries ); @@ -712,7 +676,7 @@ public: virtual tools::Rectangle GetFocusRect(const SvTreeListEntry*, tools::Long nLine ); // Respects indentation tools::Long GetTabPos(const SvTreeListEntry*, const SvLBoxTab*) const; - void InvalidateEntry( SvTreeListEntry* ); + void InvalidateEntry(SvTreeListEntry& rEntry); SvLBoxItem* GetItem( SvTreeListEntry*, tools::Long nX, SvLBoxTab** ppTab); SvLBoxItem* GetItem( SvTreeListEntry*, tools::Long nX ); std::pair GetItemPos(SvTreeListEntry* pEntry, sal_uInt16 nTabIdx); @@ -720,7 +684,7 @@ public: void SetDragDropMode( DragDropMode ); void SetSelectionMode( SelectionMode ); - bool Expand( SvTreeListEntry* pParent ); + bool Expand(SvTreeListEntry& rParent); bool Collapse( SvTreeListEntry* pParent ); bool Select( SvTreeListEntry* pEntry, bool bSelect=true ); sal_uInt32 SelectChildren( const SvTreeListEntry* pParent, bool bSelect ); @@ -736,7 +700,7 @@ public: sal_Int32 DefaultCompare(const SvLBoxString* pLeftText, const SvLBoxString* pRightText); DECL_DLLPRIVATE_LINK( DefaultCompare, const SvSortData&, sal_Int32 ); - void ModelNotification(SvListAction nActionId, SvTreeListEntry* pEntry); + void ModelNotification(SvListAction eAction, SvTreeListEntry* pEntry); SvTreeListEntry* GetFirstEntryInView() const; SvTreeListEntry* GetNextEntryInView(SvTreeListEntry*) const; @@ -751,18 +715,15 @@ public: // Make single click "activate" a row like a double-click normally does void SetActivateOnSingleClick(bool bEnable) { mbActivateOnSingleClick = bEnable; } - bool GetActivateOnSingleClick() const { return mbActivateOnSingleClick; } void SetCustomEntryRenderer(bool bEnable) { mbCustomEntryRenderer = bEnable; } - bool GetCustomEntryRenderer() const { return mbCustomEntryRenderer; } // Make mouse over a row "select" a row like a single-click normally does void SetHoverSelection(bool bEnable) { mbHoverSelection = bEnable; } bool GetHoverSelection() const { return mbHoverSelection; } - // to get enable or disable the text-column + // to enable or disable the text-column void SetTextColumnEnabled(bool bEnable) { mbIsTextColumEnabled = bEnable; } - bool IsTextColumnEnabled() const { return mbIsTextColumEnabled; } // only true during Select if the Select is due to a Hover bool IsSelectDueToHover() const { return mbSelectingByHover; } diff --git a/include/vcl/toolkit/treelistentry.hxx b/include/vcl/toolkit/treelistentry.hxx index f6664469e833..d59b0dd6090e 100644 --- a/include/vcl/toolkit/treelistentry.hxx +++ b/include/vcl/toolkit/treelistentry.hxx @@ -58,14 +58,12 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListEntry friend class SvTreeList; friend class SvTreeListBox; - typedef std::vector> ItemsType; - SvTreeListEntry* pParent; SvTreeListEntries m_Children; sal_uInt32 nAbsPos; sal_uInt32 nListPos; sal_uInt32 mnExtraIndent; - ItemsType m_Items; + std::vector> m_Items; OUString* pUserData; SvTLEntryFlags nEntryFlags; std::optional mxTextColor; @@ -81,8 +79,6 @@ private: void operator=(SvTreeListEntry const&) = delete; public: - static const size_t ITEM_NOT_FOUND = SAL_MAX_SIZE; - SvTreeListEntry(); virtual ~SvTreeListEntry(); @@ -92,7 +88,7 @@ public: const SvTreeListEntries& GetChildEntries() const { return m_Children; } - void Clone(SvTreeListEntry* pSource); + void Clone(const SvTreeListEntry& rSource); size_t ItemCount() const; @@ -105,7 +101,7 @@ public: SvLBoxItem& GetItem( size_t nPos ); const SvLBoxItem* GetFirstItem(SvLBoxItemType eType) const; SvLBoxItem* GetFirstItem(SvLBoxItemType eType); - size_t GetPos( const SvLBoxItem* pItem ) const; + size_t GetPos(const SvLBoxItem& rItem) const; OUString* GetUserData() const { return pUserData; } void SetUserData(OUString* pPtr); void EnableChildrenOnDemand( bool bEnable=true ); diff --git a/include/vcl/toolkit/unowrap.hxx b/include/vcl/toolkit/unowrap.hxx index 9d1231919229..32ade46be2b3 100644 --- a/include/vcl/toolkit/unowrap.hxx +++ b/include/vcl/toolkit/unowrap.hxx @@ -39,9 +39,6 @@ namespace com::sun::star::awt { class XWindow; class XVclWindowPeer; } -namespace com::sun::star::accessibility { - class XAccessible; -} class VCL_DLLPUBLIC UnoWrapperBase { diff --git a/include/vcl/toolkit/vclmedit.hxx b/include/vcl/toolkit/vclmedit.hxx index 746fd681ca8b..7302fd0d3c9d 100644 --- a/include/vcl/toolkit/vclmedit.hxx +++ b/include/vcl/toolkit/vclmedit.hxx @@ -155,7 +155,7 @@ public: Size CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const; void GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const; - void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override; + void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags) override; void DisableSelectionOnFocus(); @@ -168,8 +168,6 @@ public: virtual FactoryFunction GetUITestFactory() const override; virtual bool set_property(const OUString &rKey, const OUString &rValue) override; - - virtual void DumpAsPropertyTree(tools::JsonWriter&) override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/transfer.hxx b/include/vcl/transfer.hxx index fd837b4088d6..4b85b6c48325 100644 --- a/include/vcl/transfer.hxx +++ b/include/vcl/transfer.hxx @@ -43,7 +43,6 @@ #include namespace com::sun::star::datatransfer::clipboard { class XClipboard; } -namespace com::sun::star::datatransfer::dnd { class XDragGestureRecognizer; } namespace com::sun::star::io { class XInputStream; } namespace com::sun::star::datatransfer::dnd { class XDropTarget; } @@ -51,6 +50,7 @@ template class Link; enum class SotClipboardFormatId : sal_uInt32; class Bitmap; +class DNDListenerContainer; class GDIMetaFile; class Graphic; class ImageMap; @@ -395,7 +395,7 @@ private: private: std::mutex maMutex; - css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > mxDragGestureRecognizer; + rtl::Reference mpDNDListenerContainer; rtl::Reference< DragSourceHelper::DragGestureListener > mxDragGestureListener; diff --git a/include/vcl/uitest/uiobject.hxx b/include/vcl/uitest/uiobject.hxx index f7a15e9211c6..5c3369da97e1 100644 --- a/include/vcl/uitest/uiobject.hxx +++ b/include/vcl/uitest/uiobject.hxx @@ -527,8 +527,6 @@ class IconViewUIObject final : public TreeListUIObject public: IconViewUIObject(const VclPtr& xIconView); - virtual StringMap get_state() override; - static std::unique_ptr create(vcl::Window* pWindow); private: diff --git a/include/vcl/vclenum.hxx b/include/vcl/vclenum.hxx index f32ce771590d..5159b8421417 100644 --- a/include/vcl/vclenum.hxx +++ b/include/vcl/vclenum.hxx @@ -224,7 +224,10 @@ enum VclResponseType RET_RETRY = 4, RET_IGNORE = 5, RET_CLOSE = 7, - RET_HELP = 10 + // The following responses do not close the dialog, but are used + // to identify buttons that need special handling + RET_HELP = 10, + RET_RESET = 11, }; enum class VclButtonsType diff --git a/include/vcl/weld/Box.hxx b/include/vcl/weld/Box.hxx new file mode 100644 index 000000000000..eb9c1a0b5985 --- /dev/null +++ b/include/vcl/weld/Box.hxx @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC Box : virtual public Container +{ +public: + // Moves child to a new position in the list of children + virtual void reorder_child(weld::Widget* pWidget, int position) = 0; + // Sort ok/cancel etc buttons in platform order + virtual void sort_native_button_order() = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Builder.hxx b/include/vcl/weld/Builder.hxx index d749fd555503..92231ca369c2 100644 --- a/include/vcl/weld/Builder.hxx +++ b/include/vcl/weld/Builder.hxx @@ -22,6 +22,7 @@ class OAccessible; } enum class FieldUnit : sal_uInt16; +enum class VclSizeGroupMode; namespace weld { @@ -122,7 +123,7 @@ public: virtual std::unique_ptr weld_popover(const OUString& id) = 0; virtual std::unique_ptr weld_toolbar(const OUString& id) = 0; virtual std::unique_ptr weld_scrollbar(const OUString& id) = 0; - virtual std::unique_ptr create_size_group() = 0; + virtual std::unique_ptr create_size_group(VclSizeGroupMode eMode) = 0; /* return a Dialog suitable to take a screenshot of containing the contents of the .ui file. If the toplevel element is a dialog, that will be returned diff --git a/include/vcl/weld/Button.hxx b/include/vcl/weld/Button.hxx new file mode 100644 index 000000000000..1314ba546ae9 --- /dev/null +++ b/include/vcl/weld/Button.hxx @@ -0,0 +1,64 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace com::sun::star::graphic +{ +class XGraphic; +} +class Color; +class VirtualDevice; + +namespace vcl +{ +class Font; +} + +namespace weld +{ +class VCL_DLLPUBLIC Button : virtual public Widget +{ +protected: + Link m_aClickHdl; + + void signal_clicked() { m_aClickHdl.Call(*this); } + +public: + virtual void set_label(const OUString& rText) = 0; + // pDevice, the image for the button, or nullptr to unset + virtual void set_image(VirtualDevice* pDevice) = 0; + virtual void set_image(const css::uno::Reference& rImage) = 0; + virtual void set_from_icon_name(const OUString& rIconName) = 0; + virtual OUString get_label() const = 0; + void clicked() { signal_clicked(); } + + // font size is in points, not pixels, e.g. see Window::[G]etPointFont + virtual void set_font(const vcl::Font& rFont) = 0; + + /* Sometimes, a widget should behave like a button (activate on click, + accept keyboard focus, etc), but look entirely different. + + pDevice, the custom look to use, or nullptr to unset. + + Typically doing this is ill advised. Consider using + set_accessible_name if you do. */ + virtual void set_custom_button(VirtualDevice* pDevice) = 0; + + virtual void connect_clicked(const Link& rLink) { m_aClickHdl = rLink; } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/weld/Calendar.hxx b/include/vcl/weld/Calendar.hxx new file mode 100644 index 000000000000..d53fe63345f2 --- /dev/null +++ b/include/vcl/weld/Calendar.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +class Date; + +namespace weld +{ +class VCL_DLLPUBLIC Calendar : virtual public Widget +{ + Link m_aSelectedHdl; + Link m_aActivatedHdl; + +protected: + void signal_selected() + { + if (notify_events_disabled()) + return; + m_aSelectedHdl.Call(*this); + } + + void signal_activated() + { + if (notify_events_disabled()) + return; + m_aActivatedHdl.Call(*this); + } + +public: + void connect_selected(const Link& rLink) { m_aSelectedHdl = rLink; } + void connect_activated(const Link& rLink) { m_aActivatedHdl = rLink; } + + virtual void set_date(const Date& rDate) = 0; + virtual Date get_date() const = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/CheckButton.hxx b/include/vcl/weld/CheckButton.hxx new file mode 100644 index 000000000000..f47fe0a1f4a3 --- /dev/null +++ b/include/vcl/weld/CheckButton.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC CheckButton : virtual public Toggleable +{ +protected: + virtual void do_set_state(TriState eState) = 0; + +public: + // must override Toggleable::get_state to support TRISTATE_INDET + virtual TriState get_state() const override = 0; + + void set_state(TriState eState) + { + disable_notify_events(); + do_set_state(eState); + enable_notify_events(); + } + + virtual void do_set_active(bool bActive) override final + { + do_set_state(bActive ? TRISTATE_TRUE : TRISTATE_FALSE); + } + + virtual bool get_active() const override final { return get_state() == TRISTATE_TRUE; } + + virtual void set_label(const OUString& rText) = 0; + virtual OUString get_label() const = 0; + virtual void set_label_wrap(bool wrap) = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/ComboBox.hxx b/include/vcl/weld/ComboBox.hxx index 1f1155fa85f2..cca64c95507b 100644 --- a/include/vcl/weld/ComboBox.hxx +++ b/include/vcl/weld/ComboBox.hxx @@ -10,7 +10,15 @@ #pragma once #include -#include +#include +#include + +class OutputDevice; + +namespace vcl +{ +typedef OutputDevice RenderContext; +} namespace weld { @@ -56,8 +64,6 @@ protected: Link m_aEntryActivateHdl; Link m_aEntryInsertTextHdl; - friend class ::LOKTrigger; - void signal_changed() { if (notify_events_disabled()) @@ -82,6 +88,7 @@ protected: = 0; virtual void do_set_active(int pos) = 0; virtual void do_set_active_id(const OUString& rStr) = 0; + virtual void do_set_entry_text(const OUString& rStr) = 0; public: void insert(int pos, const OUString& rStr, const OUString* pId, const OUString* pIconName, @@ -161,7 +168,7 @@ public: //entry related virtual bool has_entry() const = 0; virtual void set_entry_message_type(EntryMessageType eType) = 0; - virtual void set_entry_text(const OUString& rStr) = 0; + void set_entry_text(const OUString& rStr); virtual void set_entry_width_chars(int nChars) = 0; virtual void set_entry_max_length(int nChars) = 0; virtual void select_entry_region(int nStartPos, int nEndPos) = 0; diff --git a/include/vcl/weld/Container.hxx b/include/vcl/weld/Container.hxx new file mode 100644 index 000000000000..0ef98185e0dd --- /dev/null +++ b/include/vcl/weld/Container.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace com::sun::star::awt +{ +class XWindow; +} + +namespace weld +{ +class VCL_DLLPUBLIC Container : virtual public Widget +{ + Link m_aContainerFocusChangedHdl; + +protected: + void signal_container_focus_changed() { m_aContainerFocusChangedHdl.Call(*this); } + +public: + // remove from old container and add to new container in one go + // new container can be null to just remove from old container + virtual void move(weld::Widget* pWidget, weld::Container* pNewParent) = 0; + // create an XWindow as a child of this container. The XWindow is + // suitable to contain css::awt::XControl items + virtual css::uno::Reference CreateChildFrame() = 0; + // rLink is called when the focus transitions from a widget outside the container + // to a widget inside the container or vice versa + virtual void connect_container_focus_changed(const Link& rLink) + { + m_aContainerFocusChangedHdl = rLink; + } + // causes a child of the container to have the keyboard focus + virtual void child_grab_focus() = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/DateFormatter.hxx b/include/vcl/weld/DateFormatter.hxx new file mode 100644 index 000000000000..d95b4cfd1f65 --- /dev/null +++ b/include/vcl/weld/DateFormatter.hxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +#include + +class CalendarWrapper; +class Date; + +enum class ExtDateFieldFormat; + +namespace weld +{ +class VCL_DLLPUBLIC DateFormatter final : public EntryFormatter +{ +public: + DateFormatter(weld::Entry& rEntry); + + void SetMin(const Date& rNewMin); + void SetMax(const Date& rNewMax); + + void SetDate(const Date& rNewDate); + Date GetDate(); + + void SetExtDateFormat(ExtDateFieldFormat eFormat); + void SetShowDateCentury(bool bShowCentury); + + virtual ~DateFormatter() override; + +private: + DECL_DLLPRIVATE_LINK(FormatOutputHdl, double, std::optional); + DECL_DLLPRIVATE_LINK(ParseInputHdl, const OUString&, Formatter::ParseResult); + + SAL_DLLPRIVATE void Init(); + SAL_DLLPRIVATE CalendarWrapper& GetCalendarWrapper() const; + + SAL_DLLPRIVATE OUString FormatNumber(int nValue) const; + + ExtDateFieldFormat m_eFormat; + mutable std::unique_ptr m_xCalendarWrapper; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Dialog.hxx b/include/vcl/weld/Dialog.hxx index e9091b6e3cce..b73daf3db814 100644 --- a/include/vcl/weld/Dialog.hxx +++ b/include/vcl/weld/Dialog.hxx @@ -10,10 +10,13 @@ #pragma once #include -#include +#include namespace weld { +class Button; +class DialogController; + class VCL_DLLPUBLIC Dialog : virtual public Window { private: @@ -22,8 +25,6 @@ private: const std::function& func) = 0; - DECL_LINK(CommandHdl, const CommandEvent&, bool); - protected: virtual bool signal_command(const CommandEvent& rCEvt); diff --git a/include/vcl/weld/DialogController.hxx b/include/vcl/weld/DialogController.hxx index cb670a777fa8..6e11339e7229 100644 --- a/include/vcl/weld/DialogController.hxx +++ b/include/vcl/weld/DialogController.hxx @@ -49,7 +49,7 @@ protected: public: GenericDialogController(weld::Widget* pParent, const OUString& rUIFile, - const OUString& rDialogId, bool bMobile = false); + const OUString& rDialogId); virtual Dialog* getDialog() override; virtual ~GenericDialogController() override; }; @@ -81,7 +81,6 @@ public: void set_primary_text(const OUString& rText); OUString get_primary_text() const; void set_secondary_text(const OUString& rText); - OUString get_secondary_text() const; void set_default_response(int nResponse); }; } diff --git a/include/vcl/weld/DoubleNumericFormatter.hxx b/include/vcl/weld/DoubleNumericFormatter.hxx new file mode 100644 index 000000000000..63f5450da0dc --- /dev/null +++ b/include/vcl/weld/DoubleNumericFormatter.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class Entry; +class FormattedSpinButton; + +class UNLESS_MERGELIBS(VCL_DLLPUBLIC) DoubleNumericFormatter final : public EntryFormatter +{ +public: + DoubleNumericFormatter(weld::Entry& rEntry); + DoubleNumericFormatter(weld::FormattedSpinButton& rSpinButton); + + SAL_DLLPRIVATE virtual ~DoubleNumericFormatter() override; + +private: + SAL_DLLPRIVATE virtual bool CheckText(const OUString& sText) const override; + + SAL_DLLPRIVATE virtual void FormatChanged(FORMAT_CHANGE_TYPE nWhat) override; + SAL_DLLPRIVATE void ResetConformanceTester(); + + std::unique_ptr m_pNumberValidator; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/DrawingArea.hxx b/include/vcl/weld/DrawingArea.hxx index 243ed8469d94..4a2fbb4a0d0d 100644 --- a/include/vcl/weld/DrawingArea.hxx +++ b/include/vcl/weld/DrawingArea.hxx @@ -10,7 +10,30 @@ #pragma once #include -#include +#include + +#include + +class InputContext; +class OutputDevice; +enum class PointerStyle; + +using a11yrelationset = css::uno::Reference; + +namespace comphelper +{ +class OAccessible; +} + +namespace rtl +{ +template class Reference; +} + +namespace vcl +{ +typedef OutputDevice RenderContext; +} namespace weld { @@ -88,19 +111,6 @@ public: virtual rtl::Reference get_accessible_parent() = 0; virtual a11yrelationset get_accessible_relation_set() = 0; virtual AbsoluteScreenPixelPoint get_accessible_location_on_screen() = 0; - -private: - friend class ::LOKTrigger; - - virtual void click(const Point&) = 0; - - virtual void dblclick(const Point&){}; - - virtual void mouse_up(const Point&){}; - - virtual void mouse_down(const Point&){}; - - virtual void mouse_move(const Point&){}; }; } diff --git a/include/vcl/weld/Entry.hxx b/include/vcl/weld/Entry.hxx index 0b62cece5d83..5b7b82b728c4 100644 --- a/include/vcl/weld/Entry.hxx +++ b/include/vcl/weld/Entry.hxx @@ -10,6 +10,7 @@ #pragma once #include +#include #include enum class TxtAlign; @@ -19,16 +20,9 @@ namespace weld class VCL_DLLPUBLIC Entry : virtual public TextWidget { protected: - Link m_aChangeHdl; Link m_aInsertTextHdl; Link m_aActivateHdl; - friend class ::LOKTrigger; - - void signal_changed(); - - void signal_activated(); - public: virtual void set_width_chars(int nChars) = 0; virtual int get_width_chars() const = 0; @@ -42,7 +36,6 @@ public: virtual void set_overwrite_mode(bool bOn) = 0; virtual bool get_overwrite_mode() const = 0; - virtual void connect_changed(const Link& rLink) { m_aChangeHdl = rLink; } void connect_insert_text(const Link& rLink) { m_aInsertTextHdl = rLink; } // callback returns true to indicated no further processing of activate wanted void connect_activate(const Link& rLink) { m_aActivateHdl = rLink; } diff --git a/include/vcl/weld/EntryFormatter.hxx b/include/vcl/weld/EntryFormatter.hxx new file mode 100644 index 000000000000..a8cec87b52d2 --- /dev/null +++ b/include/vcl/weld/EntryFormatter.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class Entry; +class FormattedSpinButton; +class TextWidget; +class Widget; + +class VCL_DLLPUBLIC EntryFormatter : public Formatter +{ +public: + EntryFormatter(weld::Entry& rEntry); + EntryFormatter(weld::FormattedSpinButton& rSpinButton); + + weld::Entry& get_widget() { return m_rEntry; } + + // public Formatter overrides, drives interactions with the Entry + SAL_DLLPRIVATE virtual Selection GetEntrySelection() const override; + SAL_DLLPRIVATE virtual OUString GetEntryText() const override; + SAL_DLLPRIVATE virtual void SetEntryText(const OUString& rText, const Selection& rSel) override; + SAL_DLLPRIVATE virtual void SetEntryTextColor(const Color* pColor) override; + SAL_DLLPRIVATE virtual SelectionOptions GetEntrySelectionOptions() const override; + SAL_DLLPRIVATE virtual void FieldModified() override; + + // public Formatter overrides, drives optional SpinButton settings + SAL_DLLPRIVATE virtual void ClearMinValue() override; + SAL_DLLPRIVATE virtual void SetMinValue(double dMin) override; + SAL_DLLPRIVATE virtual void ClearMaxValue() override; + SAL_DLLPRIVATE virtual void SetMaxValue(double dMin) override; + + SAL_DLLPRIVATE virtual void SetSpinSize(double dStep) override; + + void SetEntrySelectionOptions(SelectionOptions eOptions) { m_eOptions = eOptions; } + + /* EntryFormatter will set listeners to "changed" and "focus-out" of the + Entry so users that want to add their own listeners to those must set + them through this formatter and not directly on that entry. + + If EntryFormatter is used with a weld::FormattedSpinButton this is + handled transparently by the FormattedSpinButton for the user and the + handlers can be set on the FormattedSpinButton + */ + void connect_changed(const Link& rLink) { m_aModifyHdl = rLink; } + void connect_focus_out(const Link& rLink) { m_aFocusOutHdl = rLink; } + + SAL_DLLPRIVATE virtual ~EntryFormatter() override; + +private: + weld::Entry& m_rEntry; + weld::FormattedSpinButton* m_pSpinButton; + Link m_aModifyHdl; + Link m_aFocusOutHdl; + SelectionOptions m_eOptions; + DECL_DLLPRIVATE_LINK(ModifyHdl, weld::TextWidget&, void); + DECL_DLLPRIVATE_LINK(FocusOutHdl, weld::Widget&, void); + SAL_DLLPRIVATE void Init(); + + // private Formatter overrides + SAL_DLLPRIVATE virtual void UpdateCurrentValue(double dCurrentValue) override; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/comphelper/markdown.hxx b/include/vcl/weld/EntryMessageType.hxx similarity index 75% rename from include/comphelper/markdown.hxx rename to include/vcl/weld/EntryMessageType.hxx index 308423c9085e..f2b153c94869 100644 --- a/include/comphelper/markdown.hxx +++ b/include/vcl/weld/EntryMessageType.hxx @@ -9,12 +9,14 @@ #pragma once -#include -#include - -namespace comphelper +namespace weld { -COMPHELPER_DLLPUBLIC bool IsMarkdownData(const OUString& rData); +enum class EntryMessageType +{ + Normal, + Warning, + Error, +}; } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/EntryTreeView.hxx b/include/vcl/weld/EntryTreeView.hxx index e7d3a948591a..f9918ea7910f 100644 --- a/include/vcl/weld/EntryTreeView.hxx +++ b/include/vcl/weld/EntryTreeView.hxx @@ -24,7 +24,7 @@ class VCL_DLLPUBLIC EntryTreeView : virtual public ComboBox { private: DECL_DLLPRIVATE_LINK(ClickHdl, weld::ItemView&, void); - DECL_DLLPRIVATE_LINK(ModifyHdl, weld::Entry&, void); + DECL_DLLPRIVATE_LINK(ModifyHdl, weld::TextWidget&, void); protected: std::unique_ptr m_xEntry; @@ -36,6 +36,8 @@ protected: m_xTreeView->insert(pos, rStr, pId, pIconName, pImageSurface); } + virtual void do_set_entry_text(const OUString& rStr) override { m_xEntry->set_text(rStr); } + public: EntryTreeView(std::unique_ptr xEntry, std::unique_ptr xTreeView); @@ -88,7 +90,6 @@ public: { m_xEntry->set_message_type(eType); } - virtual void set_entry_text(const OUString& rStr) override { m_xEntry->set_text(rStr); } virtual void set_entry_width_chars(int nChars) override { m_xEntry->set_width_chars(nChars); } virtual void set_entry_max_length(int nChars) override { m_xEntry->set_max_length(nChars); } virtual void select_entry_region(int nStartPos, int nEndPos) override diff --git a/include/vcl/weld/Expander.hxx b/include/vcl/weld/Expander.hxx new file mode 100644 index 000000000000..d98e58a73660 --- /dev/null +++ b/include/vcl/weld/Expander.hxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC Expander : virtual public Widget +{ + Link m_aExpandedHdl; + +protected: + void signal_expanded() { m_aExpandedHdl.Call(*this); } + +public: + virtual void set_label(const OUString& rText) = 0; + virtual OUString get_label() const = 0; + virtual bool get_expanded() const = 0; + virtual void set_expanded(bool bExpand) = 0; + + void connect_expanded(const Link& rLink) { m_aExpandedHdl = rLink; } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/FormattedSpinButton.hxx b/include/vcl/weld/FormattedSpinButton.hxx index 2b6ad2fe7b6e..1aaab39ba1fc 100644 --- a/include/vcl/weld/FormattedSpinButton.hxx +++ b/include/vcl/weld/FormattedSpinButton.hxx @@ -12,6 +12,8 @@ #include #include +class Formatter; + namespace weld { class EntryFormatter; @@ -20,8 +22,6 @@ class EntryFormatter; // are managed by a more complex Formatter which can support doubles. class VCL_DLLPUBLIC FormattedSpinButton : virtual public Entry { - friend class ::LOKTrigger; - Link m_aValueChangedHdl; protected: diff --git a/include/linguistic/translate.hxx b/include/vcl/weld/Frame.hxx similarity index 64% rename from include/linguistic/translate.hxx rename to include/vcl/weld/Frame.hxx index 0d5643f056c1..e29805d10dd1 100644 --- a/include/linguistic/translate.hxx +++ b/include/vcl/weld/Frame.hxx @@ -8,13 +8,18 @@ */ #pragma once -#include -#include -namespace linguistic +#include +#include + +namespace weld { -LNG_DLLPUBLIC OString Translate(const OString& rTargetLang, const OString& rAPIUrl, - const OString& rAuthKey, const OString& rData); -} // namespace +class VCL_DLLPUBLIC Frame : virtual public Container +{ +public: + virtual void set_label(const OUString& rText) = 0; + virtual OUString get_label() const = 0; +}; +} /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Grid.hxx b/include/vcl/weld/Grid.hxx new file mode 100644 index 000000000000..e86e3acdeaf4 --- /dev/null +++ b/include/vcl/weld/Grid.hxx @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC Grid : virtual public Container +{ +public: + virtual void set_child_left_attach(weld::Widget& rWidget, int nAttach) = 0; + virtual int get_child_left_attach(weld::Widget& rWidget) const = 0; + virtual void set_child_column_span(weld::Widget& rWidget, int nCols) = 0; + virtual void set_child_top_attach(weld::Widget& rWidget, int nAttach) = 0; + virtual int get_child_top_attach(weld::Widget& rWidget) const = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/IconView.hxx b/include/vcl/weld/IconView.hxx index 97d9faddf079..098a6381e500 100644 --- a/include/vcl/weld/IconView.hxx +++ b/include/vcl/weld/IconView.hxx @@ -12,17 +12,16 @@ #include #include +class Bitmap; + namespace weld { typedef std::tuple encoded_image_query; class VCL_DLLPUBLIC IconView : virtual public ItemView { - friend class ::LOKTrigger; - protected: Link m_aQueryTooltipHdl; - Link m_aGetPropertyTreeElemHdl; OUString signal_query_tooltip(const TreeIter& rIter) const { @@ -66,11 +65,6 @@ public: insert(-1, &rStr, &rId, &rImage, nullptr); } - void append(const OUString& rId, const OUString& rStr, const Bitmap* pImage) - { - insert(-1, &rStr, &rId, pImage, nullptr); - } - void append_separator(const OUString& rId) { insert_separator(-1, &rId); } virtual void connect_query_tooltip(const Link& rLink) @@ -78,26 +72,20 @@ public: m_aQueryTooltipHdl = rLink; } - // 0: OUString, 1: TreeIter, returns true if supported - virtual void connect_get_image(const Link& rLink) - { - m_aGetPropertyTreeElemHdl = rLink; - } - virtual int count_selected_items() const = 0; virtual void set_image(int pos, VirtualDevice& rDevice) = 0; virtual void set_text(int pos, const OUString& rText) = 0; virtual void set_item_accessible_name(int pos, const OUString& rName) = 0; - virtual void set_item_tooltip_text(int pos, const OUString& rToolTip) = 0; - tools::Rectangle get_rect(int pos) const; + virtual void set_item_tooltip_text(int pos, const OUString& rToolTip) = 0; + OUString get_item_tooltip_text(int pos) const; + virtual OUString get_item_tooltip_text(const TreeIter& rIter) const = 0; + virtual tools::Rectangle get_rect(const TreeIter& rIter) const = 0; std::unique_ptr get_item_at_pos(const Point& rPos); - virtual OUString get_text(const TreeIter& rIter) const = 0; - void scroll_to_item(const TreeIter& rIter) { disable_notify_events(); diff --git a/include/vcl/weld/Image.hxx b/include/vcl/weld/Image.hxx new file mode 100644 index 000000000000..7d1742e667a3 --- /dev/null +++ b/include/vcl/weld/Image.hxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +class VirtualDevice; + +namespace com::sun::star::graphic +{ +class XGraphic; +} + +namespace weld +{ +class VCL_DLLPUBLIC Image : virtual public Widget +{ +public: + virtual void set_from_icon_name(const OUString& rIconName) = 0; + virtual void set_image(VirtualDevice* pDevice) = 0; + virtual void set_image(const css::uno::Reference& rImage) = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/ItemView.hxx b/include/vcl/weld/ItemView.hxx index 1c4b09cef02f..c82dd40f8652 100644 --- a/include/vcl/weld/ItemView.hxx +++ b/include/vcl/weld/ItemView.hxx @@ -11,7 +11,7 @@ #include #include -#include +#include namespace weld { @@ -55,7 +55,7 @@ public: void set_id(int pos, const OUString& rId); virtual void set_id(const TreeIter& rIter, const OUString& rId) = 0; - virtual OUString get_selected_id() const = 0; + OUString get_selected_id() const; virtual OUString get_selected_text() const = 0; virtual std::unique_ptr get_selected() const = 0; @@ -87,7 +87,6 @@ public: virtual void selected_foreach(const std::function& func) = 0; void save_value() { m_sSavedValue = get_selected_text(); } - OUString const& get_saved_value() const { return m_sSavedValue; } bool get_value_changed_from_saved() const { return m_sSavedValue != get_selected_text(); } /* An item/row is "activated" when the user double clicks a treeview row or IconView item. diff --git a/include/vcl/weld/Label.hxx b/include/vcl/weld/Label.hxx new file mode 100644 index 000000000000..2c28351be7c1 --- /dev/null +++ b/include/vcl/weld/Label.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +enum class LabelType +{ + Normal, + Warning, + Error, + Title, // this is intended to be used against the background set by set_title_background +}; + +class VCL_DLLPUBLIC Label : virtual public Widget +{ +public: + virtual void set_label(const OUString& rText) = 0; + virtual OUString get_label() const = 0; + virtual void set_mnemonic_widget(Widget* pTarget) = 0; + // font size is in points, not pixels, e.g. see Window::[G]etPointFont + virtual void set_font(const vcl::Font& rFont) = 0; + virtual void set_label_type(LabelType eType) = 0; + /* + If you want to set a warning or error state, see set_label_type + instead. + */ + virtual void set_font_color(const Color& rColor) = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/LevelBar.hxx b/include/vcl/weld/LevelBar.hxx new file mode 100644 index 000000000000..67e247ea6937 --- /dev/null +++ b/include/vcl/weld/LevelBar.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC LevelBar : virtual public Widget +{ +public: + /// Sets LevelBar fill percentage. + /// @param fPercentage bar's fill percentage, [0.0, 100.0] + virtual void set_percentage(double fPercentage) = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/LinkButton.hxx b/include/vcl/weld/LinkButton.hxx new file mode 100644 index 000000000000..29dd6cb16b11 --- /dev/null +++ b/include/vcl/weld/LinkButton.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC LinkButton : virtual public Widget +{ + Link m_aActivateLinkHdl; + +protected: + bool signal_activate_link() { return m_aActivateLinkHdl.Call(*this); } + +public: + virtual void set_label(const OUString& rText) = 0; + virtual OUString get_label() const = 0; + virtual void set_label_wrap(bool wrap) = 0; + virtual void set_uri(const OUString& rUri) = 0; + virtual OUString get_uri() const = 0; + + void connect_activate_link(const Link& rLink) { m_aActivateLinkHdl = rLink; } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/LongCurrencyFormatter.hxx b/include/vcl/weld/LongCurrencyFormatter.hxx new file mode 100644 index 000000000000..86e7fc919b3b --- /dev/null +++ b/include/vcl/weld/LongCurrencyFormatter.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +#include + +namespace weld +{ +class Entry; +class FormattedSpinButton; + +class VCL_DLLPUBLIC LongCurrencyFormatter final : public EntryFormatter +{ +public: + LongCurrencyFormatter(weld::Entry& rEntry); + LongCurrencyFormatter(weld::FormattedSpinButton& rSpinButton); + + void SetUseThousandSep(bool b); + void SetCurrencySymbol(const OUString& rStr); + + SAL_DLLPRIVATE virtual ~LongCurrencyFormatter() override; + +private: + DECL_DLLPRIVATE_LINK(FormatOutputHdl, double, std::optional); + DECL_DLLPRIVATE_LINK(ParseInputHdl, const OUString&, Formatter::ParseResult); + + SAL_DLLPRIVATE void Init(); + + OUString m_aCurrencySymbol; + bool m_bThousandSep; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Menu.hxx b/include/vcl/weld/Menu.hxx index 06dfe7fbe4e9..ab0424b04c17 100644 --- a/include/vcl/weld/Menu.hxx +++ b/include/vcl/weld/Menu.hxx @@ -10,14 +10,18 @@ #pragma once #include -#include +#include +#include + +namespace com::sun::star::graphic +{ +class XGraphic; +} namespace weld { class VCL_DLLPUBLIC Menu { - friend class ::LOKTrigger; - Link m_aActivateHdl; protected: diff --git a/include/vcl/weld/MenuButton.hxx b/include/vcl/weld/MenuButton.hxx index 137f9469658a..d1002a5e113b 100644 --- a/include/vcl/weld/MenuButton.hxx +++ b/include/vcl/weld/MenuButton.hxx @@ -10,14 +10,12 @@ #pragma once #include -#include +#include namespace weld { class VCL_DLLPUBLIC MenuButton : virtual public ToggleButton { - friend class ::LOKTrigger; - Link m_aSelectHdl; protected: @@ -38,10 +36,6 @@ public: { insert_item(-1, rId, rStr, nullptr, nullptr, TRISTATE_TRUE); } - void append_item_radio(const OUString& rId, const OUString& rStr) - { - insert_item(-1, rId, rStr, nullptr, nullptr, TRISTATE_FALSE); - } void append_item(const OUString& rId, const OUString& rStr, const OUString& rImage) { insert_item(-1, rId, rStr, &rImage, nullptr, TRISTATE_INDET); diff --git a/include/vcl/weld/MetricSpinButton.hxx b/include/vcl/weld/MetricSpinButton.hxx index a1c4422d668c..dd4206dd4a49 100644 --- a/include/vcl/weld/MetricSpinButton.hxx +++ b/include/vcl/weld/MetricSpinButton.hxx @@ -33,17 +33,7 @@ class VCL_DLLPUBLIC MetricSpinButton final void update_width_chars(); public: - MetricSpinButton(std::unique_ptr pSpinButton, FieldUnit eSrcUnit) - : m_eSrcUnit(eSrcUnit) - , m_xSpinButton(std::move(pSpinButton)) - { - update_width_chars(); - m_xSpinButton->set_value_formatter(LINK(this, MetricSpinButton, spin_button_output)); - m_xSpinButton->set_text_parser(LINK(this, MetricSpinButton, spin_button_input)); - m_xSpinButton->connect_value_changed( - LINK(this, MetricSpinButton, spin_button_value_changed)); - m_xSpinButton->set_text(format_number(m_xSpinButton->get_value())); - } + MetricSpinButton(std::unique_ptr pSpinButton, FieldUnit eSrcUnit); static OUString MetricToString(FieldUnit rUnit); @@ -51,6 +41,11 @@ public: void set_unit(FieldUnit eUnit); + void select_region(int nStartPos, int nEndPos) + { + m_xSpinButton->select_region(nStartPos, nEndPos); + } + sal_Int64 convert_value_to(sal_Int64 nValue, FieldUnit eValueUnit) const { return ConvertValue(nValue, m_eSrcUnit, eValueUnit); @@ -71,15 +66,6 @@ public: return convert_value_to(m_xSpinButton->get_value(), eDestUnit); } - // typically you only need to call this if set_text (e.g. with "") was - // previously called to display some arbitrary text instead of the - // formatted value and now you want to show it as formatted again - void reformat() - { - const OUString sText = format_number(m_xSpinButton->get_value()); - m_xSpinButton->set_text(sText); - } - void set_range(sal_Int64 min, sal_Int64 max, FieldUnit eValueUnit) { min = convert_value_from(min, eValueUnit); diff --git a/include/vcl/weld/Notebook.hxx b/include/vcl/weld/Notebook.hxx index 1dc3898fb3e0..9cfe4da0d90d 100644 --- a/include/vcl/weld/Notebook.hxx +++ b/include/vcl/weld/Notebook.hxx @@ -10,14 +10,12 @@ #pragma once #include -#include +#include namespace weld { class VCL_DLLPUBLIC Notebook : virtual public Widget { - friend class ::LOKTrigger; - protected: Link m_aLeavePageHdl; Link m_aEnterPageHdl; diff --git a/include/vcl/weld/Paned.hxx b/include/vcl/weld/Paned.hxx index ca49dbc961d9..14c597c16e57 100644 --- a/include/vcl/weld/Paned.hxx +++ b/include/vcl/weld/Paned.hxx @@ -10,7 +10,6 @@ #pragma once #include -#include namespace weld { diff --git a/include/vcl/weld/PatternFormatter.hxx b/include/vcl/weld/PatternFormatter.hxx new file mode 100644 index 000000000000..a575695d0223 --- /dev/null +++ b/include/vcl/weld/PatternFormatter.hxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC PatternFormatter final +{ +public: + PatternFormatter(weld::Entry& rEntry); + ~PatternFormatter(); + + weld::Entry& get_widget() { return m_rEntry; } + + void SetMask(const OString& rEditMask, const OUString& rLiteralMask); + void SetStrictFormat(bool bStrict); + void ReformatAll(); + + /* PatternFormatter will set listeners to "changed", "focus-out", "focus-in" + and "key-press" of the Entry so users that want to add their own listeners + to those must set them through this formatter and not directly on that entry. + */ + void connect_changed(const Link& rLink) { m_aModifyHdl = rLink; } + void connect_focus_out(const Link& rLink) { m_aFocusOutHdl = rLink; } + void connect_focus_in(const Link& rLink) { m_aFocusInHdl = rLink; } + void connect_key_press(const Link& rLink) { m_aKeyPressHdl = rLink; } + + SAL_DLLPRIVATE void Modify(); + +private: + weld::Entry& m_rEntry; + Link m_aModifyHdl; + Link m_aFocusInHdl; + Link m_aFocusOutHdl; + Link m_aKeyPressHdl; + bool m_bStrictFormat; + bool m_bSameMask; + bool m_bReformat; + bool m_bInPattKeyInput; + OString m_aEditMask; + OUString m_aLiteralMask; + + SAL_DLLPRIVATE void EntryGainFocus(); + SAL_DLLPRIVATE void EntryLostFocus(); + DECL_DLLPRIVATE_LINK(ModifyHdl, weld::TextWidget&, void); + DECL_DLLPRIVATE_LINK(FocusInHdl, weld::Widget&, void); + DECL_DLLPRIVATE_LINK(FocusOutHdl, weld::Widget&, void); + DECL_DLLPRIVATE_LINK(KeyInputHdl, const KeyEvent&, bool); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Placement.hxx b/include/vcl/weld/Placement.hxx new file mode 100644 index 000000000000..f14b40028971 --- /dev/null +++ b/include/vcl/weld/Placement.hxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +namespace weld +{ +enum class Placement +{ + Under, + End +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Popover.hxx b/include/vcl/weld/Popover.hxx index af7734e65ca4..2c8ab6e22a02 100644 --- a/include/vcl/weld/Popover.hxx +++ b/include/vcl/weld/Popover.hxx @@ -10,14 +10,13 @@ #pragma once #include -#include +#include +#include namespace weld { class VCL_DLLPUBLIC Popover : virtual public Container { - friend class ::LOKTrigger; - private: Link m_aCloseHdl; diff --git a/include/vcl/weld/ProgressBar.hxx b/include/vcl/weld/ProgressBar.hxx new file mode 100644 index 000000000000..b9954e86451d --- /dev/null +++ b/include/vcl/weld/ProgressBar.hxx @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC ProgressBar : virtual public Widget +{ +public: + //0-100 + virtual void set_percentage(int value) = 0; + virtual OUString get_text() const = 0; + virtual void set_text(const OUString& rText) = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/RadioButton.hxx b/include/vcl/weld/RadioButton.hxx new file mode 100644 index 000000000000..b23971c317e0 --- /dev/null +++ b/include/vcl/weld/RadioButton.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC RadioButton : virtual public Toggleable +{ +public: + virtual void set_label(const OUString& rText) = 0; + virtual OUString get_label() const = 0; + virtual void set_label_wrap(bool wrap) = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Scale.hxx b/include/vcl/weld/Scale.hxx new file mode 100644 index 000000000000..d4cbb6d1557a --- /dev/null +++ b/include/vcl/weld/Scale.hxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC Scale : virtual public Widget +{ + Link m_aValueChangedHdl; + +protected: + void signal_value_changed() { m_aValueChangedHdl.Call(*this); } + +public: + virtual void set_value(int value) = 0; + virtual int get_value() const = 0; + virtual void set_range(int min, int max) = 0; + + virtual void set_increments(int step, int page) = 0; + virtual void get_increments(int& step, int& page) const = 0; + + void connect_value_changed(const Link& rLink) { m_aValueChangedHdl = rLink; } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/ScreenshotEntry.hxx b/include/vcl/weld/ScreenshotEntry.hxx new file mode 100644 index 000000000000..5d7696195c58 --- /dev/null +++ b/include/vcl/weld/ScreenshotEntry.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +#include + +namespace weld +{ +class VCL_DLLPUBLIC ScreenShotEntry +{ +public: + ScreenShotEntry(OUString aHelpId, const basegfx::B2IRange& rB2IRange) + : msHelpId(std::move(aHelpId)) + , maB2IRange(rB2IRange) + { + } + + const basegfx::B2IRange& getB2IRange() const { return maB2IRange; } + + const OUString& GetHelpId() const { return msHelpId; } + +private: + OUString msHelpId; + basegfx::B2IRange maB2IRange; +}; + +typedef std::vector ScreenShotCollection; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Scrollbar.hxx b/include/vcl/weld/Scrollbar.hxx index e8948be202d5..c114b1493430 100644 --- a/include/vcl/weld/Scrollbar.hxx +++ b/include/vcl/weld/Scrollbar.hxx @@ -10,7 +10,7 @@ #pragma once #include -#include +#include enum class ScrollType; @@ -24,9 +24,6 @@ protected: void signal_adjustment_value_changed() { m_aValueChangeHdl.Call(*this); } public: - virtual void adjustment_configure(int value, int lower, int upper, int step_increment, - int page_increment, int page_size) - = 0; virtual int adjustment_get_value() const = 0; virtual void adjustment_set_value(int value) = 0; virtual int adjustment_get_upper() const = 0; diff --git a/include/vcl/weld/ScrolledWindow.hxx b/include/vcl/weld/ScrolledWindow.hxx index 543e4c4b3160..5167ec8fbab0 100644 --- a/include/vcl/weld/ScrolledWindow.hxx +++ b/include/vcl/weld/ScrolledWindow.hxx @@ -10,7 +10,7 @@ #pragma once #include -#include +#include enum class VclPolicyType; @@ -18,8 +18,6 @@ namespace weld { class VCL_DLLPUBLIC ScrolledWindow : virtual public Widget { - friend class ::LOKTrigger; - Link m_aVValueChangeHdl; Link m_aHValueChangeHdl; @@ -29,8 +27,7 @@ protected: public: virtual void hadjustment_configure(int value, int upper, int step_increment, int page_increment, - int page_size) - = 0; + int page_size); virtual int hadjustment_get_value() const = 0; virtual void hadjustment_set_value(int value) = 0; virtual int hadjustment_get_upper() const = 0; @@ -47,8 +44,7 @@ public: } virtual void vadjustment_configure(int value, int upper, int step_increment, int page_increment, - int page_size) - = 0; + int page_size); virtual int vadjustment_get_value() const = 0; virtual void vadjustment_set_value(int value) = 0; virtual int vadjustment_get_upper() const = 0; diff --git a/include/vcl/weld/SizeGroup.hxx b/include/vcl/weld/SizeGroup.hxx new file mode 100644 index 000000000000..762caa57b8fa --- /dev/null +++ b/include/vcl/weld/SizeGroup.hxx @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC SizeGroup +{ +public: + virtual void add_widget(weld::Widget* pWidget) = 0; + virtual ~SizeGroup() {} +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/SpinButton.hxx b/include/vcl/weld/SpinButton.hxx index d07140c35efd..6e6509148cdf 100644 --- a/include/vcl/weld/SpinButton.hxx +++ b/include/vcl/weld/SpinButton.hxx @@ -18,8 +18,6 @@ namespace weld { class VCL_DLLPUBLIC SpinButton : virtual public Entry { - friend class ::LOKTrigger; - Link m_aValueChangedHdl; Link m_aFormatValueHdl; Link> m_aParseTextHdl; diff --git a/vcl/source/weld/Widget.cxx b/include/vcl/weld/Spinner.hxx similarity index 75% rename from vcl/source/weld/Widget.cxx rename to include/vcl/weld/Spinner.hxx index 5995f9f84afd..69cfcbf72272 100644 --- a/vcl/source/weld/Widget.cxx +++ b/include/vcl/weld/Spinner.hxx @@ -7,13 +7,19 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + +#include #include namespace weld { -void Widget::connect_get_property_tree(const Link&) {} - -void Widget::get_property_tree(tools::JsonWriter&) {} +class VCL_DLLPUBLIC Spinner : virtual public Widget +{ +public: + virtual void start() = 0; + virtual void stop() = 0; +}; } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/TextView.hxx b/include/vcl/weld/TextView.hxx index d75d666804f3..b57da29c0610 100644 --- a/include/vcl/weld/TextView.hxx +++ b/include/vcl/weld/TextView.hxx @@ -18,14 +18,9 @@ namespace weld { class VCL_DLLPUBLIC TextView : virtual public TextWidget { - friend class ::LOKTrigger; - protected: - Link m_aChangeHdl; Link m_aVValueChangeHdl; - void signal_changed() { m_aChangeHdl.Call(*this); } - void signal_vadjustment_value_changed() { m_aVValueChangeHdl.Call(*this); } public: @@ -34,8 +29,6 @@ public: virtual void set_max_length(int nChars) = 0; int get_height_rows(int nRows) const; - void connect_changed(const Link& rLink) { m_aChangeHdl = rLink; } - // returns true if pressing up would move the cursor // doesn't matter if that move is to a previous line or to the start of the // current line just so long as the cursor would move diff --git a/include/vcl/weld/TextWidget.hxx b/include/vcl/weld/TextWidget.hxx index 6f48f2d9e145..816b04996166 100644 --- a/include/vcl/weld/TextWidget.hxx +++ b/include/vcl/weld/TextWidget.hxx @@ -10,7 +10,7 @@ #pragma once #include -#include +#include namespace weld { @@ -21,8 +21,10 @@ private: OUString m_sSavedValue; protected: + Link m_aChangeHdl; Link m_aCursorPositionHdl; + void signal_changed(); void signal_cursor_position(); virtual void do_set_text(const OUString& rText) = 0; @@ -70,6 +72,7 @@ public: OUString const& get_saved_value() const { return m_sSavedValue; } bool get_value_changed_from_saved() const { return m_sSavedValue != get_text(); } + virtual void connect_changed(const Link& rLink) { m_aChangeHdl = rLink; } virtual void connect_cursor_position(const Link& rLink) { m_aCursorPositionHdl = rLink; diff --git a/include/vcl/weld/TimeFormatter.hxx b/include/vcl/weld/TimeFormatter.hxx new file mode 100644 index 000000000000..0ec10e9389ea --- /dev/null +++ b/include/vcl/weld/TimeFormatter.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include + +#include + +enum class ExtTimeFieldFormat; +enum class TimeFieldFormat : sal_Int32; +enum class TimeFormat; + +namespace weld +{ +class Entry; +class FormattedSpinButton; + +class VCL_DLLPUBLIC TimeFormatter final : public EntryFormatter +{ +public: + TimeFormatter(weld::Entry& rEntry); + TimeFormatter(weld::FormattedSpinButton& rSpinButton); + + void SetExtFormat(ExtTimeFieldFormat eFormat); + void SetDuration(bool bDuration); + void SetTimeFormat(TimeFieldFormat eTimeFormat); + + void SetMin(const tools::Time& rNewMin); + void SetMax(const tools::Time& rNewMax); + + void SetTime(const tools::Time& rNewTime); + tools::Time GetTime(); + + virtual ~TimeFormatter() override; + +private: + DECL_DLLPRIVATE_LINK(FormatOutputHdl, double, std::optional); + DECL_DLLPRIVATE_LINK(ParseInputHdl, const OUString&, Formatter::ParseResult); + DECL_DLLPRIVATE_LINK(CursorChangedHdl, weld::TextWidget&, void); + + SAL_DLLPRIVATE void Init(); + + SAL_DLLPRIVATE static tools::Time ConvertValue(int nValue); + SAL_DLLPRIVATE static int ConvertValue(const tools::Time& rTime); + + SAL_DLLPRIVATE OUString FormatNumber(int nValue) const; + + TimeFieldFormat m_eFormat; + TimeFormat m_eTimeFormat; + bool m_bDuration; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/ToggleButton.hxx b/include/vcl/weld/ToggleButton.hxx new file mode 100644 index 000000000000..d51b5d04b8bb --- /dev/null +++ b/include/vcl/weld/ToggleButton.hxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC ToggleButton : virtual public Button, virtual public Toggleable +{ +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Toggleable.hxx b/include/vcl/weld/Toggleable.hxx new file mode 100644 index 000000000000..c473daa3e243 --- /dev/null +++ b/include/vcl/weld/Toggleable.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC Toggleable : virtual public Widget +{ +protected: + Link m_aToggleHdl; + TriState m_eSavedValue = TRISTATE_FALSE; + + void signal_toggled() + { + if (notify_events_disabled()) + return; + m_aToggleHdl.Call(*this); + } + + virtual void do_set_active(bool active) = 0; + +public: + void set_active(bool active) + { + disable_notify_events(); + do_set_active(active); + enable_notify_events(); + } + + virtual bool get_active() const = 0; + + virtual TriState get_state() const + { + if (get_active()) + return TRISTATE_TRUE; + return TRISTATE_FALSE; + } + + void save_state() { m_eSavedValue = get_state(); } + TriState get_saved_state() const { return m_eSavedValue; } + bool get_state_changed_from_saved() const { return m_eSavedValue != get_state(); } + + virtual void connect_toggled(const Link& rLink) { m_aToggleHdl = rLink; } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Toolbar.hxx b/include/vcl/weld/Toolbar.hxx index 182d5e16067e..c534157d68f2 100644 --- a/include/vcl/weld/Toolbar.hxx +++ b/include/vcl/weld/Toolbar.hxx @@ -10,7 +10,12 @@ #pragma once #include -#include +#include + +namespace com::sun::star::graphic +{ +class XGraphic; +} namespace vcl { @@ -27,8 +32,6 @@ class VCL_DLLPUBLIC Toolbar : virtual public Widget Link m_aToggleMenuHdl; protected: - friend class ::LOKTrigger; - void signal_clicked(const OUString& rIdent) { m_aClickHdl.Call(rIdent); } void signal_toggle_menu(const OUString& rIdent) { m_aToggleMenuHdl.Call(rIdent); } @@ -45,7 +48,6 @@ public: virtual void set_item_help_id(const OUString& rIdent, const OUString& rHelpId) = 0; virtual bool get_item_visible(const OUString& rIdent) const = 0; virtual void set_item_label(const OUString& rIdent, const OUString& rLabel) = 0; - virtual OUString get_item_label(const OUString& rIdent) const = 0; virtual void set_item_tooltip_text(const OUString& rIdent, const OUString& rTip) = 0; virtual OUString get_item_tooltip_text(const OUString& rIdent) const = 0; virtual void set_item_icon_name(const OUString& rIdent, const OUString& rIconName) = 0; diff --git a/include/vcl/weld/TransportAsXWindow.hxx b/include/vcl/weld/TransportAsXWindow.hxx new file mode 100644 index 000000000000..765b2432395e --- /dev/null +++ b/include/vcl/weld/TransportAsXWindow.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +#include + +namespace weld +{ +class Builder; + +typedef comphelper::WeakComponentImplHelper TransportAsXWindow_Base; + +class VCL_DLLPUBLIC TransportAsXWindow : public TransportAsXWindow_Base +{ +private: + weld::Widget* m_pWeldWidget; + weld::Builder* m_pWeldWidgetBuilder; + + comphelper::OInterfaceContainerHelper4 m_aWindowListeners; + comphelper::OInterfaceContainerHelper4 m_aKeyListeners; + comphelper::OInterfaceContainerHelper4 m_aFocusListeners; + comphelper::OInterfaceContainerHelper4 m_aMouseListeners; + comphelper::OInterfaceContainerHelper4 m_aMotionListeners; + comphelper::OInterfaceContainerHelper4 m_aPaintListeners; + +public: + TransportAsXWindow(weld::Widget* pWeldWidget, weld::Builder* pWeldWidgetBuilder = nullptr); + + weld::Widget* getWidget() const { return m_pWeldWidget; } + + weld::Builder* getBuilder() const { return m_pWeldWidgetBuilder; } + + virtual void clear(); + + // css::awt::XWindow + void SAL_CALL setPosSize(sal_Int32, sal_Int32, sal_Int32, sal_Int32, sal_Int16) override; + + css::awt::Rectangle SAL_CALL getPosSize() override; + + void SAL_CALL setVisible(sal_Bool bVisible) override; + + void SAL_CALL setEnable(sal_Bool bSensitive) override; + + void SAL_CALL setFocus() override; + + void SAL_CALL + addWindowListener(const css::uno::Reference& rListener) override; + + void SAL_CALL + removeWindowListener(const css::uno::Reference& rListener) override; + + void SAL_CALL + addFocusListener(const css::uno::Reference& rListener) override; + + void SAL_CALL + removeFocusListener(const css::uno::Reference& rListener) override; + + void SAL_CALL + addKeyListener(const css::uno::Reference& rListener) override; + + void SAL_CALL + removeKeyListener(const css::uno::Reference& rListener) override; + + void SAL_CALL + addMouseListener(const css::uno::Reference& rListener) override; + + void SAL_CALL + removeMouseListener(const css::uno::Reference& rListener) override; + + void SAL_CALL addMouseMotionListener( + const css::uno::Reference& rListener) override; + + void SAL_CALL removeMouseMotionListener( + const css::uno::Reference& rListener) override; + + void SAL_CALL + addPaintListener(const css::uno::Reference& rListener) override; + + void SAL_CALL + removePaintListener(const css::uno::Reference& rListener) override; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/TreeView.hxx b/include/vcl/weld/TreeView.hxx index 6294f97e2af2..5467d063e20b 100644 --- a/include/vcl/weld/TreeView.hxx +++ b/include/vcl/weld/TreeView.hxx @@ -12,9 +12,20 @@ #include #include +class OutputDevice; enum class SelectionMode; enum class TxtAlign; +namespace com::sun::star::graphic +{ +class XGraphic; +} + +namespace vcl +{ +typedef OutputDevice RenderContext; +} + namespace weld { enum class ColumnToggleType @@ -30,21 +41,34 @@ enum class ColumnToggleType */ class VCL_DLLPUBLIC TreeView : virtual public ItemView { - friend class ::LOKTrigger; - public: typedef std::pair iter_col; - typedef std::pair iter_string; + + struct IterColText + { + const weld::TreeIter& m_rIter; + int m_nColumn; + OUString m_sText; + + public: + IterColText(const weld::TreeIter& rIter, int nColumn, const OUString& rText) + : m_rIter(rIter) + , m_nColumn(nColumn) + , m_sText(rText) + { + } + }; + // OUString is the id of the row, it may be null to measure the height of a generic line typedef std::pair get_size_args; typedef std::tuple render_args; private: - Link m_aColumnClickedHdl; + Link m_aColumnHeaderClickedHdl; Link m_aRadioToggleHdl; Link m_aEditingStartedHdl; - Link m_aEditingDoneHdl; + Link m_aEditingDoneHdl; // if handler returns false, the expansion of the row is refused Link m_aExpandingHdl; // if handler returns false, the collapse of the row is refused @@ -59,7 +83,7 @@ protected: std::function m_aCustomSort; protected: - void signal_column_clicked(int nColumn) { m_aColumnClickedHdl.Call(nColumn); } + void signal_column_header_clicked(int nColumn) { m_aColumnHeaderClickedHdl.Call(nColumn); } bool signal_expanding(const TreeIter& rIter) { return !m_aExpandingHdl.IsSet() || m_aExpandingHdl.Call(rIter); @@ -82,11 +106,16 @@ protected: m_aModelChangedHdl.Call(*this); } - void signal_toggled(const iter_col& rIterCol) { m_aRadioToggleHdl.Call(rIterCol); } + void signal_toggled(const iter_col& rIterCol) + { + if (notify_events_disabled()) + return; + m_aRadioToggleHdl.Call(rIterCol); + } bool signal_editing_started(const TreeIter& rIter) { return m_aEditingStartedHdl.Call(rIter); } - bool signal_editing_done(const iter_string& rIterText) + bool signal_editing_done(const IterColText& rIterText) { return m_aEditingDoneHdl.Call(rIterText); } @@ -119,8 +148,10 @@ protected: = 0; virtual void do_insert_separator(int pos, const OUString& rId) = 0; using weld::ItemView::do_set_cursor; + virtual void do_set_toggle(const TreeIter& rIter, TriState bOn, int col = -1) = 0; virtual void do_set_cursor(int pos) = 0; virtual void do_scroll_to_row(const TreeIter& rIter) = 0; + virtual int do_iter_n_children(const TreeIter& rIter) const = 0; virtual bool do_iter_children(TreeIter& rIter) const = 0; virtual void do_set_children_on_demand(const TreeIter& rIter, bool bChildrenOnDemand) = 0; virtual void do_remove_selection() = 0; @@ -187,13 +218,30 @@ public: // Argument is a pair of iter, col describing the toggled node void connect_toggled(const Link& rLink) { m_aRadioToggleHdl = rLink; } - void connect_column_clicked(const Link& rLink) { m_aColumnClickedHdl = rLink; } + void connect_column_header_clicked(const Link& rLink) + { + m_aColumnHeaderClickedHdl = rLink; + } void connect_model_changed(const Link& rLink) { m_aModelChangedHdl = rLink; } - // call before inserting any content and connecting to toggle signals, - // an pre-inserted checkbutton column will exist at the start of every row - // inserted after this call which can be accessed with col index -1 - virtual void enable_toggle_buttons(ColumnToggleType eType) = 0; + /** + * Call before inserting any content and connecting to toggle signals, + * a pre-inserted checkbutton column will exist at the start of every row + * inserted after this call which can be accessed with col index -1 + * + * (For the corresponding GtkTreeView definition in the .ui file, the first GtkTreeViewColumn + * must contain a leading GtkCellRendererToggle to be used for this, in addition + * to a renderer for the content referred to by the regular column index of 0.) + */ + virtual void enable_toggle_buttons() = 0; + + /** + * Set the type of all toggle buttons used in the TreeView. + * (By default, check buttons are used.) + * + * Call before inserting any entries. + */ + virtual void set_toggle_button_type(ColumnToggleType eType) = 0; virtual void set_clicks_to_toggle(int nToggleBehavior) = 0; @@ -209,12 +257,11 @@ public: void set_sensitive(int row, bool bSensitive, int col = -1); virtual void set_sensitive(const TreeIter& rIter, bool bSensitive, int col = -1) = 0; - bool get_sensitive(int row, int col) const; virtual bool get_sensitive(const TreeIter& rIter, int col) const = 0; // col index -1 sets the expander toggle, enable_toggle_buttons must have been called to create that column void set_toggle(int row, TriState eState, int col = -1); - virtual void set_toggle(const TreeIter& rIter, TriState bOn, int col = -1) = 0; + void set_toggle(const TreeIter& rIter, TriState bOn, int col = -1); // col index -1 gets the expander toggle, enable_toggle_buttons must have been called to create that column TriState get_toggle(int row, int col = -1) const; @@ -317,7 +364,7 @@ public: virtual int iter_compare(const TreeIter& rIterA, const TreeIter& rIterB) const; bool iter_has_child(const TreeIter& rIter) const; // returns the number of direct children rIter has - virtual int iter_n_children(const TreeIter& rIter) const = 0; + int iter_n_children(const TreeIter& rIter) const; //visually indent this row as if it was at get_iter_depth() + nIndentLevel virtual void set_extra_row_indent(const TreeIter& rIter, int nIndentLevel) = 0; @@ -345,7 +392,8 @@ public: const std::function& func, const weld::TreeIter* pParent = nullptr, const std::vector* pFixedWidths = nullptr, - bool bGoingToSetText = false) + bool bGoingToSetText = false, + bool bForceForwardInsert = false) = 0; /* expanding on-demand node details @@ -399,7 +447,7 @@ public: // rStartLink returns true to allow editing, false to disallow // rEndLink returns true to accept the edit, false to reject virtual void connect_editing(const Link& rStartLink, - const Link& rEndLink) + const Link& rEndLink) { assert(rStartLink.IsSet() == rEndLink.IsSet() && "should be both on or both off"); m_aEditingStartedHdl = rStartLink; @@ -449,6 +497,8 @@ public: virtual void set_centered_column(int nCol) = 0; virtual OUString get_column_title(int nColumn) const = 0; virtual void set_column_title(int nColumn, const OUString& rTitle) = 0; + + virtual bool get_column_visible(int nColumn) const = 0; virtual void set_column_visible(int nColumn, bool bVisible) = 0; int get_checkbox_column_width() const { return get_approximate_digit_width() * 3 + 6; } @@ -494,8 +544,6 @@ public: = 0; virtual void unset_drag_dest_row() = 0; virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const = 0; - virtual tools::Rectangle get_cell_area(const weld::TreeIter& rIter, - const int nColumn) const = 0; // for dragging and dropping between TreeViews, return the active source virtual TreeView* get_drag_source() const = 0; diff --git a/include/vcl/weld/TriStateEnabled.hxx b/include/vcl/weld/TriStateEnabled.hxx new file mode 100644 index 000000000000..dcd2185bbdc9 --- /dev/null +++ b/include/vcl/weld/TriStateEnabled.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +struct VCL_DLLPUBLIC TriStateEnabled +{ + TriState eState; + bool bTriStateEnabled; + TriStateEnabled() + : eState(TRISTATE_INDET) + , bTriStateEnabled(true) + { + } + void CheckButtonToggled(CheckButton& rToggle); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/WaitObject.hxx b/include/vcl/weld/WaitObject.hxx new file mode 100644 index 000000000000..2a1d15a6738d --- /dev/null +++ b/include/vcl/weld/WaitObject.hxx @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace weld +{ +class VCL_DLLPUBLIC WaitObject +{ +private: + weld::Widget* m_pWindow; + +public: + WaitObject(weld::Widget* pWindow); + ~WaitObject(); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/Widget.hxx b/include/vcl/weld/Widget.hxx index 3f1673f76d57..d7449f1c5969 100644 --- a/include/vcl/weld/Widget.hxx +++ b/include/vcl/weld/Widget.hxx @@ -41,31 +41,22 @@ class Font; } template class VclPtr; -namespace tools -{ -class JsonWriter; -} - -class LOKTrigger; - namespace weld { class Container; class VCL_DLLPUBLIC Widget { - friend class ::LOKTrigger; - int m_nBlockNotify = 0; Link m_aCommandHdl; + Link m_aSizeAllocateHdl; protected: Link m_aFocusInHdl; Link m_aFocusOutHdl; Link m_aMnemonicActivateHdl; Link m_aStyleUpdatedHdl; - Link m_aSizeAllocateHdl; Link m_aKeyPressHdl; Link m_aKeyReleaseHdl; Link m_aMousePressHdl; @@ -174,17 +165,13 @@ public: virtual void set_help_id(const OUString& rName) = 0; virtual void set_hexpand(bool bExpand) = 0; - virtual bool get_hexpand() const = 0; virtual void set_vexpand(bool bExpand) = 0; - virtual bool get_vexpand() const = 0; virtual void set_margin_top(int nMargin) = 0; virtual void set_margin_bottom(int nMargin) = 0; virtual void set_margin_start(int nMargin) = 0; virtual void set_margin_end(int nMargin) = 0; - virtual int get_margin_top() const = 0; - virtual int get_margin_bottom() const = 0; virtual int get_margin_start() const = 0; virtual int get_margin_end() const = 0; @@ -354,9 +341,6 @@ public: virtual css::uno::Reference get_drop_target() = 0; virtual css::uno::Reference get_clipboard() const = 0; - virtual void connect_get_property_tree(const Link& rLink); - virtual void get_property_tree(tools::JsonWriter& rJsonWriter); - // render the widget to an output device virtual void draw(OutputDevice& rOutput, const Point& rPos, const Size& rSizePixel) = 0; diff --git a/include/vcl/weld/Window.hxx b/include/vcl/weld/Window.hxx new file mode 100644 index 000000000000..1b97144143f3 --- /dev/null +++ b/include/vcl/weld/Window.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +struct SystemEnvData; + +namespace vcl +{ +class WindowData; +enum class WindowDataMask; +} + +namespace weld +{ +class VCL_DLLPUBLIC Window : virtual public Container +{ +protected: + Link m_aHelpRequestHdl; + +public: + virtual void set_title(const OUString& rTitle) = 0; + virtual OUString get_title() const = 0; + virtual void window_move(int x, int y) = 0; + virtual bool get_resizable() const = 0; + virtual Size get_size() const = 0; + virtual Point get_position() const = 0; + + // returns whether the widget that has focus is within this Window + // (its very possible to move this to weld::Container if that becomes + // desirable) + virtual bool has_toplevel_focus() const = 0; + virtual void present() = 0; + + virtual void set_window_state(const vcl::WindowData& rState) = 0; + virtual vcl::WindowData get_window_state(vcl::WindowDataMask nMask) const = 0; + + virtual css::uno::Reference GetXWindow() = 0; + + void connect_help(const Link& rLink) { m_aHelpRequestHdl = rLink; } + + virtual SystemEnvData get_system_data() const = 0; + + virtual void resize_to_request() = 0; + + // collect positions of widgets and their help ids for screenshot purposes + virtual ScreenShotCollection collect_screenshot_data() = 0; + + // render the widget to an output device + virtual VclPtr screenshot() = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/weld/customweld.hxx b/include/vcl/weld/customweld.hxx index 91a27976d75e..ac348a4fedf0 100644 --- a/include/vcl/weld/customweld.hxx +++ b/include/vcl/weld/customweld.hxx @@ -14,7 +14,6 @@ #include #include #include -#include class InputContext; @@ -65,7 +64,6 @@ public: virtual tools::Rectangle GetFocusRect() { return tools::Rectangle(); } virtual FactoryFunction GetUITestFactory() const { return nullptr; } virtual OUString RequestHelp(tools::Rectangle&) { return OUString(); } - OUString GetHelpText() const { return m_pDrawingArea->get_tooltip_text(); } Size const& GetOutputSizePixel() const { return m_aSize; } void SetOutputSizePixel(const Size& rSize) { m_aSize = rSize; } virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) { m_pDrawingArea = pDrawingArea; } @@ -116,7 +114,6 @@ public: } void CaptureMouse() { m_pDrawingArea->grab_mouse(); } bool IsMouseCaptured() const { return m_pDrawingArea->has_mouse_grab(); } - Point GetPointerPosPixel() const { return m_pDrawingArea->get_pointer_position(); } void EnableRTL(bool bEnable) { m_pDrawingArea->set_direction(bEnable); } bool IsRTLEnabled() const { return m_pDrawingArea->get_direction(); } void ReleaseMouse() { m_pDrawingArea->release_mouse(); } @@ -198,10 +195,6 @@ public: CustomWeld(weld::Builder& rBuilder, const OUString& rDrawingId, CustomWidgetController& rWidgetController); void queue_draw() { m_xDrawingArea->queue_draw(); } - void queue_draw_area(int x, int y, int width, int height) - { - m_xDrawingArea->queue_draw_area(x, y, width, height); - } void set_size_request(int nWidth, int nHeight) { m_xDrawingArea->set_size_request(nWidth, nHeight); @@ -211,11 +204,9 @@ public: void set_margin_top(int nMargin) { m_xDrawingArea->set_margin_top(nMargin); } void set_margin_bottom(int nMargin) { m_xDrawingArea->set_margin_bottom(nMargin); } void set_sensitive(bool bSensitive) { m_xDrawingArea->set_sensitive(bSensitive); } - bool get_sensitive() const { return m_xDrawingArea->get_sensitive(); } bool get_visible() const { return m_xDrawingArea->get_visible(); } void set_visible(bool bVisible) { m_xDrawingArea->set_visible(bVisible); } void set_help_id(const OUString& rHelpId) { m_xDrawingArea->set_help_id(rHelpId); } - void set_tooltip_text(const OUString& rTip) { m_xDrawingArea->set_tooltip_text(rTip); } }; } diff --git a/include/vcl/weld/weld.hxx b/include/vcl/weld/weld.hxx deleted file mode 100644 index fdb0c31a8e37..000000000000 --- a/include/vcl/weld/weld.hxx +++ /dev/null @@ -1,519 +0,0 @@ -/* -*- 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/. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -namespace com::sun::star::awt -{ -class XWindow; -} -namespace com::sun::star::datatransfer::clipboard -{ -class XClipboard; -} -namespace com::sun::star::datatransfer::dnd -{ -class XDropTarget; -} -namespace com::sun::star::graphic -{ -class XGraphic; -} -namespace comphelper -{ -class OAccessible; -} -namespace rtl -{ -template class Reference; -} -typedef css::uno::Reference a11yrelationset; -enum class PointerStyle; -enum class VclSizeGroupMode; -class Color; -class CommandEvent; -class Date; -class Formatter; -class InputContext; -class KeyEvent; -class MouseEvent; -class TransferDataContainer; -class OutputDevice; -class VirtualDevice; -struct SystemEnvData; -class Bitmap; - -namespace vcl -{ -class ILibreOfficeKitNotifier; -typedef OutputDevice RenderContext; -class Font; -enum class WindowDataMask; -} -template class VclPtr; - -namespace tools -{ -class JsonWriter; -} - -class LOKTrigger; - -namespace weld -{ -class Container; -class DialogController; -class EntryTreeView; -class IconView; -class MetricSpinButton; -class TreeView; - -class VCL_DLLPUBLIC Container : virtual public Widget -{ - Link m_aContainerFocusChangedHdl; - -protected: - void signal_container_focus_changed() { m_aContainerFocusChangedHdl.Call(*this); } - -public: - // remove from old container and add to new container in one go - // new container can be null to just remove from old container - virtual void move(weld::Widget* pWidget, weld::Container* pNewParent) = 0; - // create an XWindow as a child of this container. The XWindow is - // suitable to contain css::awt::XControl items - virtual css::uno::Reference CreateChildFrame() = 0; - // rLink is called when the focus transitions from a widget outside the container - // to a widget inside the container or vice versa - virtual void connect_container_focus_changed(const Link& rLink) - { - m_aContainerFocusChangedHdl = rLink; - } - // causes a child of the container to have the keyboard focus - virtual void child_grab_focus() = 0; -}; - -class VCL_DLLPUBLIC Box : virtual public Container -{ -public: - // Moves child to a new position in the list of children - virtual void reorder_child(weld::Widget* pWidget, int position) = 0; - // Sort ok/cancel etc buttons in platform order - virtual void sort_native_button_order() = 0; -}; - -class VCL_DLLPUBLIC Grid : virtual public Container -{ -public: - virtual void set_child_left_attach(weld::Widget& rWidget, int nAttach) = 0; - virtual int get_child_left_attach(weld::Widget& rWidget) const = 0; - virtual void set_child_column_span(weld::Widget& rWidget, int nCols) = 0; - virtual void set_child_top_attach(weld::Widget& rWidget, int nAttach) = 0; - virtual int get_child_top_attach(weld::Widget& rWidget) const = 0; -}; - -class VCL_DLLPUBLIC Frame : virtual public Container -{ -public: - virtual void set_label(const OUString& rText) = 0; - virtual OUString get_label() const = 0; -}; - -class VCL_DLLPUBLIC ScreenShotEntry -{ -public: - ScreenShotEntry(OUString aHelpId, const basegfx::B2IRange& rB2IRange) - : msHelpId(std::move(aHelpId)) - , maB2IRange(rB2IRange) - { - } - - const basegfx::B2IRange& getB2IRange() const { return maB2IRange; } - - const OUString& GetHelpId() const { return msHelpId; } - -private: - OUString msHelpId; - basegfx::B2IRange maB2IRange; -}; - -typedef std::vector ScreenShotCollection; - -class VCL_DLLPUBLIC Window : virtual public Container -{ -protected: - Link m_aHelpRequestHdl; - -public: - virtual void set_title(const OUString& rTitle) = 0; - virtual OUString get_title() const = 0; - virtual void window_move(int x, int y) = 0; - virtual bool get_resizable() const = 0; - virtual Size get_size() const = 0; - virtual Point get_position() const = 0; - - // returns whether the widget that has focus is within this Window - // (its very possible to move this to weld::Container if that becomes - // desirable) - virtual bool has_toplevel_focus() const = 0; - virtual void present() = 0; - - virtual void set_window_state(const OUString& rStr) = 0; - virtual OUString get_window_state(vcl::WindowDataMask nMask) const = 0; - - virtual css::uno::Reference GetXWindow() = 0; - - void connect_help(const Link& rLink) { m_aHelpRequestHdl = rLink; } - - virtual SystemEnvData get_system_data() const = 0; - - virtual void resize_to_request() = 0; - - // collect positions of widgets and their help ids for screenshot purposes - virtual ScreenShotCollection collect_screenshot_data() = 0; - - // render the widget to an output device - virtual VclPtr screenshot() = 0; - - virtual const vcl::ILibreOfficeKitNotifier* GetLOKNotifier() = 0; -}; - -class VCL_DLLPUBLIC WaitObject -{ -private: - weld::Widget* m_pWindow; - -public: - WaitObject(weld::Widget* pWindow) - : m_pWindow(pWindow) - { - if (m_pWindow) - m_pWindow->set_busy_cursor(true); - } - ~WaitObject() - { - if (m_pWindow) - m_pWindow->set_busy_cursor(false); - } -}; - -inline OUString toId(const void* pValue) -{ - return OUString::number(reinterpret_cast(pValue)); -} - -template T fromId(const OUString& rValue) -{ - return reinterpret_cast(rValue.toUInt64()); -} - -enum class EntryMessageType -{ - Normal, - Warning, - Error, -}; - -class VCL_DLLPUBLIC Button : virtual public Widget -{ - friend class ::LOKTrigger; - -protected: - Link m_aClickHdl; - - void signal_clicked() { m_aClickHdl.Call(*this); } - -public: - virtual void set_label(const OUString& rText) = 0; - // pDevice, the image for the button, or nullptr to unset - virtual void set_image(VirtualDevice* pDevice) = 0; - virtual void set_image(const css::uno::Reference& rImage) = 0; - virtual void set_from_icon_name(const OUString& rIconName) = 0; - virtual OUString get_label() const = 0; - void clicked() { signal_clicked(); } - bool is_custom_handler_set() { return m_aClickHdl.IsSet(); } - - // font size is in points, not pixels, e.g. see Window::[G]etPointFont - virtual void set_font(const vcl::Font& rFont) = 0; - - /* Sometimes, a widget should behave like a button (activate on click, - accept keyboard focus, etc), but look entirely different. - - pDevice, the custom look to use, or nullptr to unset. - - Typically doing this is ill advised. Consider using - set_accessible_name if you do. */ - virtual void set_custom_button(VirtualDevice* pDevice) = 0; - - virtual void connect_clicked(const Link& rLink) { m_aClickHdl = rLink; } -}; - -class VCL_DLLPUBLIC Toggleable : virtual public Widget -{ - friend class ::LOKTrigger; - -protected: - Link m_aToggleHdl; - TriState m_eSavedValue = TRISTATE_FALSE; - - void signal_toggled() - { - if (notify_events_disabled()) - return; - m_aToggleHdl.Call(*this); - } - - virtual void do_set_active(bool active) = 0; - -public: - void set_active(bool active) - { - disable_notify_events(); - do_set_active(active); - enable_notify_events(); - } - - virtual bool get_active() const = 0; - - virtual TriState get_state() const - { - if (get_active()) - return TRISTATE_TRUE; - return TRISTATE_FALSE; - } - - void save_state() { m_eSavedValue = get_state(); } - TriState get_saved_state() const { return m_eSavedValue; } - bool get_state_changed_from_saved() const { return m_eSavedValue != get_state(); } - - virtual void connect_toggled(const Link& rLink) { m_aToggleHdl = rLink; } -}; - -class VCL_DLLPUBLIC ToggleButton : virtual public Button, virtual public Toggleable -{ - friend class ::LOKTrigger; -}; - -class VCL_DLLPUBLIC CheckButton : virtual public Toggleable -{ -protected: - virtual void do_set_state(TriState eState) = 0; - -public: - // must override Toggleable::get_state to support TRISTATE_INDET - virtual TriState get_state() const override = 0; - - void set_state(TriState eState) - { - disable_notify_events(); - do_set_state(eState); - enable_notify_events(); - } - - virtual void do_set_active(bool bActive) override final - { - do_set_state(bActive ? TRISTATE_TRUE : TRISTATE_FALSE); - } - - virtual bool get_active() const override final { return get_state() == TRISTATE_TRUE; } - - virtual void set_label(const OUString& rText) = 0; - virtual OUString get_label() const = 0; - virtual void set_label_wrap(bool wrap) = 0; -}; - -struct VCL_DLLPUBLIC TriStateEnabled -{ - TriState eState; - bool bTriStateEnabled; - TriStateEnabled() - : eState(TRISTATE_INDET) - , bTriStateEnabled(true) - { - } - void CheckButtonToggled(CheckButton& rToggle); -}; - -class VCL_DLLPUBLIC RadioButton : virtual public Toggleable -{ -public: - virtual void set_label(const OUString& rText) = 0; - virtual OUString get_label() const = 0; - virtual void set_label_wrap(bool wrap) = 0; -}; - -class VCL_DLLPUBLIC LinkButton : virtual public Widget -{ - friend class ::LOKTrigger; - - Link m_aActivateLinkHdl; - -protected: - bool signal_activate_link() { return m_aActivateLinkHdl.Call(*this); } - -public: - virtual void set_label(const OUString& rText) = 0; - virtual OUString get_label() const = 0; - virtual void set_label_wrap(bool wrap) = 0; - virtual void set_uri(const OUString& rUri) = 0; - virtual OUString get_uri() const = 0; - - void connect_activate_link(const Link& rLink) { m_aActivateLinkHdl = rLink; } -}; - -class VCL_DLLPUBLIC Scale : virtual public Widget -{ - Link m_aValueChangedHdl; - -protected: - void signal_value_changed() { m_aValueChangedHdl.Call(*this); } - -public: - virtual void set_value(int value) = 0; - virtual int get_value() const = 0; - virtual void set_range(int min, int max) = 0; - - virtual void set_increments(int step, int page) = 0; - virtual void get_increments(int& step, int& page) const = 0; - - void connect_value_changed(const Link& rLink) { m_aValueChangedHdl = rLink; } -}; - -class VCL_DLLPUBLIC Spinner : virtual public Widget -{ -public: - virtual void start() = 0; - virtual void stop() = 0; -}; - -class VCL_DLLPUBLIC ProgressBar : virtual public Widget -{ -public: - //0-100 - virtual void set_percentage(int value) = 0; - virtual OUString get_text() const = 0; - virtual void set_text(const OUString& rText) = 0; -}; - -class VCL_DLLPUBLIC LevelBar : virtual public Widget -{ -public: - /// Sets LevelBar fill percentage. - /// @param fPercentage bar's fill percentage, [0.0, 100.0] - virtual void set_percentage(double fPercentage) = 0; -}; - -class VCL_DLLPUBLIC Image : virtual public Widget -{ -public: - virtual void set_from_icon_name(const OUString& rIconName) = 0; - virtual void set_image(VirtualDevice* pDevice) = 0; - virtual void set_image(const css::uno::Reference& rImage) = 0; -}; - -class VCL_DLLPUBLIC Calendar : virtual public Widget -{ - friend class ::LOKTrigger; - - Link m_aSelectedHdl; - Link m_aActivatedHdl; - -protected: - void signal_selected() - { - if (notify_events_disabled()) - return; - m_aSelectedHdl.Call(*this); - } - - void signal_activated() - { - if (notify_events_disabled()) - return; - m_aActivatedHdl.Call(*this); - } - -public: - void connect_selected(const Link& rLink) { m_aSelectedHdl = rLink; } - void connect_activated(const Link& rLink) { m_aActivatedHdl = rLink; } - - virtual void set_date(const Date& rDate) = 0; - virtual Date get_date() const = 0; -}; - -enum class LabelType -{ - Normal, - Warning, - Error, - Title, // this is intended to be used against the background set by set_title_background -}; - -class VCL_DLLPUBLIC Label : virtual public Widget -{ -public: - virtual void set_label(const OUString& rText) = 0; - virtual OUString get_label() const = 0; - virtual void set_mnemonic_widget(Widget* pTarget) = 0; - // font size is in points, not pixels, e.g. see Window::[G]etPointFont - virtual void set_font(const vcl::Font& rFont) = 0; - virtual void set_label_type(LabelType eType) = 0; - /* - If you want to set a warning or error state, see set_label_type - instead. - */ - virtual void set_font_color(const Color& rColor) = 0; -}; - -class VCL_DLLPUBLIC Expander : virtual public Widget -{ - Link m_aExpandedHdl; - -protected: - void signal_expanded() { m_aExpandedHdl.Call(*this); } - -public: - virtual void set_label(const OUString& rText) = 0; - virtual OUString get_label() const = 0; - virtual bool get_expanded() const = 0; - virtual void set_expanded(bool bExpand) = 0; - - void connect_expanded(const Link& rLink) { m_aExpandedHdl = rLink; } -}; - -enum class Placement -{ - Under, - End -}; - -class VCL_DLLPUBLIC SizeGroup -{ -public: - virtual void add_widget(weld::Widget* pWidget) = 0; - // the default mode is VclSizeGroupMode::Horizontal - virtual void set_mode(VclSizeGroupMode eMode) = 0; - virtual ~SizeGroup() {} -}; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/weld/weldutils.hxx b/include/vcl/weld/weldutils.hxx index 08ac5b16d1c6..9934c2633938 100644 --- a/include/vcl/weld/weldutils.hxx +++ b/include/vcl/weld/weldutils.hxx @@ -9,24 +9,17 @@ #pragma once -#include #include #include #include -#include #include -#include #include #include -#include -class CalendarWrapper; - -enum class ExtDateFieldFormat; -enum class ExtTimeFieldFormat; +class CommandEvent; +class MouseEvent; +class OutputDevice; enum class SelectionOptions; -enum class TimeFieldFormat : sal_Int32; -enum class TimeFormat; namespace com::sun::star::frame { @@ -44,154 +37,18 @@ class Time; namespace vcl { +class Font; class Window; } namespace weld { -class Builder; -class Entry; -class FormattedSpinButton; +class Button; class TextWidget; class TreeIter; class TreeView; - -typedef comphelper::WeakComponentImplHelper TransportAsXWindow_Base; - -class VCL_DLLPUBLIC TransportAsXWindow : public TransportAsXWindow_Base -{ -private: - weld::Widget* m_pWeldWidget; - weld::Builder* m_pWeldWidgetBuilder; - - comphelper::OInterfaceContainerHelper4 m_aWindowListeners; - comphelper::OInterfaceContainerHelper4 m_aKeyListeners; - comphelper::OInterfaceContainerHelper4 m_aFocusListeners; - comphelper::OInterfaceContainerHelper4 m_aMouseListeners; - comphelper::OInterfaceContainerHelper4 m_aMotionListeners; - comphelper::OInterfaceContainerHelper4 m_aPaintListeners; - -public: - TransportAsXWindow(weld::Widget* pWeldWidget, weld::Builder* pWeldWidgetBuilder = nullptr) - : m_pWeldWidget(pWeldWidget) - , m_pWeldWidgetBuilder(pWeldWidgetBuilder) - { - } - - weld::Widget* getWidget() const { return m_pWeldWidget; } - - weld::Builder* getBuilder() const { return m_pWeldWidgetBuilder; } - - virtual void clear() - { - m_pWeldWidget = nullptr; - m_pWeldWidgetBuilder = nullptr; - } - - // css::awt::XWindow - void SAL_CALL setPosSize(sal_Int32, sal_Int32, sal_Int32, sal_Int32, sal_Int16) override - { - throw css::uno::RuntimeException(u"not implemented"_ustr); - } - - css::awt::Rectangle SAL_CALL getPosSize() override - { - throw css::uno::RuntimeException(u"not implemented"_ustr); - } - - void SAL_CALL setVisible(sal_Bool bVisible) override { m_pWeldWidget->set_visible(bVisible); } - - void SAL_CALL setEnable(sal_Bool bSensitive) override - { - m_pWeldWidget->set_sensitive(bSensitive); - } - - void SAL_CALL setFocus() override { m_pWeldWidget->grab_focus(); } - - void SAL_CALL - addWindowListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aWindowListeners.addInterface(g, rListener); - } - - void SAL_CALL - removeWindowListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aWindowListeners.removeInterface(g, rListener); - } - - void SAL_CALL - addFocusListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aFocusListeners.addInterface(g, rListener); - } - - void SAL_CALL - removeFocusListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aFocusListeners.removeInterface(g, rListener); - } - - void SAL_CALL - addKeyListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aKeyListeners.addInterface(g, rListener); - } - - void SAL_CALL - removeKeyListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aKeyListeners.removeInterface(g, rListener); - } - - void SAL_CALL - addMouseListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aMouseListeners.addInterface(g, rListener); - } - - void SAL_CALL - removeMouseListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aMouseListeners.removeInterface(g, rListener); - } - - void SAL_CALL addMouseMotionListener( - const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aMotionListeners.addInterface(g, rListener); - } - - void SAL_CALL removeMouseMotionListener( - const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aMotionListeners.removeInterface(g, rListener); - } - - void SAL_CALL - addPaintListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aPaintListeners.addInterface(g, rListener); - } - - void SAL_CALL - removePaintListener(const css::uno::Reference& rListener) override - { - std::unique_lock g(m_aMutex); - m_aPaintListeners.removeInterface(g, rListener); - } -}; +class Widget; +class Window; // don't export to avoid duplicate WeakImplHelper definitions with MSVC class SAL_DLLPUBLIC_TEMPLATE WidgetStatusListener_Base @@ -225,206 +82,6 @@ public: void dispose(); }; -class VCL_DLLPUBLIC EntryFormatter : public Formatter -{ -public: - EntryFormatter(weld::Entry& rEntry); - EntryFormatter(weld::FormattedSpinButton& rSpinButton); - - weld::Entry& get_widget() { return m_rEntry; } - - // public Formatter overrides, drives interactions with the Entry - SAL_DLLPRIVATE virtual Selection GetEntrySelection() const override; - SAL_DLLPRIVATE virtual OUString GetEntryText() const override; - SAL_DLLPRIVATE virtual void SetEntryText(const OUString& rText, const Selection& rSel) override; - SAL_DLLPRIVATE virtual void SetEntryTextColor(const Color* pColor) override; - SAL_DLLPRIVATE virtual SelectionOptions GetEntrySelectionOptions() const override; - SAL_DLLPRIVATE virtual void FieldModified() override; - - // public Formatter overrides, drives optional SpinButton settings - SAL_DLLPRIVATE virtual void ClearMinValue() override; - SAL_DLLPRIVATE virtual void SetMinValue(double dMin) override; - SAL_DLLPRIVATE virtual void ClearMaxValue() override; - SAL_DLLPRIVATE virtual void SetMaxValue(double dMin) override; - - SAL_DLLPRIVATE virtual void SetSpinSize(double dStep) override; - - void SetEntrySelectionOptions(SelectionOptions eOptions) { m_eOptions = eOptions; } - - /* EntryFormatter will set listeners to "changed" and "focus-out" of the - Entry so users that want to add their own listeners to those must set - them through this formatter and not directly on that entry. - - If EntryFormatter is used with a weld::FormattedSpinButton this is - handled transparently by the FormattedSpinButton for the user and the - handlers can be set on the FormattedSpinButton - */ - void connect_changed(const Link& rLink) { m_aModifyHdl = rLink; } - void connect_focus_out(const Link& rLink) { m_aFocusOutHdl = rLink; } - - SAL_DLLPRIVATE virtual ~EntryFormatter() override; - -private: - weld::Entry& m_rEntry; - weld::FormattedSpinButton* m_pSpinButton; - Link m_aModifyHdl; - Link m_aFocusOutHdl; - SelectionOptions m_eOptions; - DECL_DLLPRIVATE_LINK(ModifyHdl, weld::Entry&, void); - DECL_DLLPRIVATE_LINK(FocusOutHdl, weld::Widget&, void); - SAL_DLLPRIVATE void Init(); - - // private Formatter overrides - SAL_DLLPRIVATE virtual void UpdateCurrentValue(double dCurrentValue) override; -}; - -class UNLESS_MERGELIBS(VCL_DLLPUBLIC) DoubleNumericFormatter final : public EntryFormatter -{ -public: - DoubleNumericFormatter(weld::Entry& rEntry); - DoubleNumericFormatter(weld::FormattedSpinButton& rSpinButton); - - SAL_DLLPRIVATE virtual ~DoubleNumericFormatter() override; - -private: - SAL_DLLPRIVATE virtual bool CheckText(const OUString& sText) const override; - - SAL_DLLPRIVATE virtual void FormatChanged(FORMAT_CHANGE_TYPE nWhat) override; - SAL_DLLPRIVATE void ResetConformanceTester(); - - std::unique_ptr m_pNumberValidator; -}; - -class VCL_DLLPUBLIC LongCurrencyFormatter final : public EntryFormatter -{ -public: - LongCurrencyFormatter(weld::Entry& rEntry); - LongCurrencyFormatter(weld::FormattedSpinButton& rSpinButton); - - void SetUseThousandSep(bool b); - void SetCurrencySymbol(const OUString& rStr); - - SAL_DLLPRIVATE virtual ~LongCurrencyFormatter() override; - -private: - DECL_DLLPRIVATE_LINK(FormatOutputHdl, double, std::optional); - DECL_DLLPRIVATE_LINK(ParseInputHdl, const OUString&, Formatter::ParseResult); - - SAL_DLLPRIVATE void Init(); - - OUString m_aCurrencySymbol; - bool m_bThousandSep; -}; - -class VCL_DLLPUBLIC TimeFormatter final : public EntryFormatter -{ -public: - TimeFormatter(weld::Entry& rEntry); - TimeFormatter(weld::FormattedSpinButton& rSpinButton); - - void SetExtFormat(ExtTimeFieldFormat eFormat); - void SetDuration(bool bDuration); - void SetTimeFormat(TimeFieldFormat eTimeFormat); - - void SetMin(const tools::Time& rNewMin); - void SetMax(const tools::Time& rNewMax); - - void SetTime(const tools::Time& rNewTime); - tools::Time GetTime(); - - virtual ~TimeFormatter() override; - -private: - DECL_DLLPRIVATE_LINK(FormatOutputHdl, double, std::optional); - DECL_DLLPRIVATE_LINK(ParseInputHdl, const OUString&, Formatter::ParseResult); - DECL_DLLPRIVATE_LINK(CursorChangedHdl, weld::TextWidget&, void); - - SAL_DLLPRIVATE void Init(); - - SAL_DLLPRIVATE static tools::Time ConvertValue(int nValue); - SAL_DLLPRIVATE static int ConvertValue(const tools::Time& rTime); - - SAL_DLLPRIVATE OUString FormatNumber(int nValue) const; - - TimeFieldFormat m_eFormat; - TimeFormat m_eTimeFormat; - bool m_bDuration; -}; - -class VCL_DLLPUBLIC DateFormatter final : public EntryFormatter -{ -public: - DateFormatter(weld::Entry& rEntry); - - void SetMin(const Date& rNewMin); - void SetMax(const Date& rNewMax); - - void SetDate(const Date& rNewDate); - Date GetDate(); - - void SetExtDateFormat(ExtDateFieldFormat eFormat); - void SetShowDateCentury(bool bShowCentury); - - virtual ~DateFormatter() override; - -private: - DECL_DLLPRIVATE_LINK(FormatOutputHdl, double, std::optional); - DECL_DLLPRIVATE_LINK(ParseInputHdl, const OUString&, Formatter::ParseResult); - DECL_DLLPRIVATE_LINK(CursorChangedHdl, weld::Entry&, void); - - SAL_DLLPRIVATE void Init(); - SAL_DLLPRIVATE CalendarWrapper& GetCalendarWrapper() const; - - SAL_DLLPRIVATE OUString FormatNumber(int nValue) const; - - ExtDateFieldFormat m_eFormat; - mutable std::unique_ptr m_xCalendarWrapper; -}; - -class VCL_DLLPUBLIC PatternFormatter final -{ -public: - PatternFormatter(weld::Entry& rEntry); - ~PatternFormatter(); - - weld::Entry& get_widget() { return m_rEntry; } - - void SetMask(const OString& rEditMask, const OUString& rLiteralMask); - void SetStrictFormat(bool bStrict); - void ReformatAll(); - - /* PatternFormatter will set listeners to "changed", "focus-out", "focus-in" - and "key-press" of the Entry so users that want to add their own listeners - to those must set them through this formatter and not directly on that entry. - */ - void connect_changed(const Link& rLink) { m_aModifyHdl = rLink; } - void connect_focus_out(const Link& rLink) { m_aFocusOutHdl = rLink; } - void connect_focus_in(const Link& rLink) { m_aFocusInHdl = rLink; } - void connect_key_press(const Link& rLink) { m_aKeyPressHdl = rLink; } - - SAL_DLLPRIVATE void Modify(); - -private: - weld::Entry& m_rEntry; - Link m_aModifyHdl; - Link m_aFocusInHdl; - Link m_aFocusOutHdl; - Link m_aKeyPressHdl; - bool m_bStrictFormat; - bool m_bSameMask; - bool m_bReformat; - bool m_bInPattKeyInput; - OString m_aEditMask; - OUString m_aLiteralMask; - - SAL_DLLPRIVATE void EntryGainFocus(); - SAL_DLLPRIVATE void EntryLostFocus(); - DECL_DLLPRIVATE_LINK(ModifyHdl, weld::Entry&, void); - DECL_DLLPRIVATE_LINK(FocusInHdl, weld::Widget&, void); - DECL_DLLPRIVATE_LINK(FocusOutHdl, weld::Widget&, void); - DECL_DLLPRIVATE_LINK(KeyInputHdl, const KeyEvent&, bool); -}; - class VCL_DLLPUBLIC ButtonPressRepeater final : public std::enable_shared_from_this { @@ -468,6 +125,16 @@ public: ReorderingDropTarget(weld::TreeView& rTreeView); }; +inline OUString toId(const void* pValue) +{ + return OUString::number(reinterpret_cast(pValue)); +} + +template T fromId(const OUString& rValue) +{ + return reinterpret_cast(rValue.toUInt64()); +} + // get the row the iterator is on VCL_DLLPUBLIC size_t GetAbsPos(const weld::TreeView& rTreeView, const weld::TreeIter& rIter); diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx index eef0cdc434fc..770a13d84881 100644 --- a/include/vcl/window.hxx +++ b/include/vcl/window.hxx @@ -94,7 +94,6 @@ namespace svt { class PopupWindowControllerImpl; } namespace weld { class Window; } template class VclPtr; -namespace tools { class JsonWriter; } // Type for GetWindow() enum class GetWindowType @@ -671,7 +670,7 @@ private: SAL_DLLPRIVATE bool ImplStopDnd(); SAL_DLLPRIVATE void ImplStartDnd(); - virtual void ImplPaintToDevice( ::OutputDevice* pTargetOutDev, const Point& rPos ); + virtual void ImplPaintToDevice(OutputDevice& rTargetOutDev, const Point& rPos); protected: // Single argument ctors shall be explicit. @@ -713,7 +712,7 @@ public: SAL_DLLPRIVATE void Erase(vcl::RenderContext& rRenderContext); - virtual void Draw( ::OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ); + virtual void Draw(OutputDevice& rDev, const Point& rPos, SystemTextColorFlags nFlags); virtual void Move(); virtual void Resize(); virtual void Activate(); @@ -747,7 +746,6 @@ public: WindowExtendedStyle GetExtendedStyle() const; void SetType( WindowType eType ); WindowType GetType() const; - std::string_view GetTypeName() const; bool IsFormControl() const; void SetFormControl(bool bFormControl); bool IsSystemWindow() const; @@ -1091,9 +1089,6 @@ public: /// check if LOK Window container is empty SAL_DLLPRIVATE static bool IsLOKWindowsEmpty(); - /// Dumps itself and potentially its children to a property tree, to be written easily to JSON. - virtual void DumpAsPropertyTree(tools::JsonWriter&); - /// Use OS specific way to bring user attention to current window virtual void FlashWindow() const; @@ -1407,7 +1402,7 @@ public: bool IsNativeWidgetEnabled() const; // a helper method for a Control's Draw method - void PaintToDevice( ::OutputDevice* pDevice, const Point& rPos ); + void PaintToDevice(OutputDevice& rDevice, const Point& rPos); // Keyboard access functions @@ -1443,7 +1438,6 @@ public: SAL_DLLPRIVATE void SetHelpHdl(const Link& rLink); SAL_DLLPRIVATE void SetMnemonicActivateHdl(const Link& rLink); void SetModalHierarchyHdl(const Link& rLink); - SAL_DLLPRIVATE void SetDumpAsPropertyTreeHdl(const Link& rLink); Size GetOutputSizePixel() const; SAL_DLLPRIVATE tools::Rectangle GetOutputRectPixel() const; @@ -1484,8 +1478,8 @@ public: TextRectInfo* pInfo = nullptr, const vcl::TextLayoutCommon* _pTextLayout = nullptr ) const; float GetDPIScaleFactor() const; - tools::Long GetOutOffXPixel() const; - tools::Long GetOutOffYPixel() const; + tools::Long GetDeviceOriginX() const; + tools::Long GetDeviceOriginY() const; void EnableMapMode( bool bEnable = true ); bool IsMapModeEnabled() const; diff --git a/include/vcl/windowstate.hxx b/include/vcl/windowstate.hxx index fdae315f9324..3db21fd09928 100644 --- a/include/vcl/windowstate.hxx +++ b/include/vcl/windowstate.hxx @@ -83,7 +83,7 @@ public: , mnMaximizedHeight(0) { } - WindowData(std::u16string_view rStr); + explicit WindowData(std::u16string_view rStr); // serialize values to a string (the original WindowState representation) OUString toStr() const; diff --git a/include/vcl/wizardmachine.hxx b/include/vcl/wizardmachine.hxx index 7966829b1810..70421c6b79a9 100644 --- a/include/vcl/wizardmachine.hxx +++ b/include/vcl/wizardmachine.hxx @@ -23,6 +23,7 @@ #include #include #include +#include #include struct WizPageData; diff --git a/include/xmloff/SoundReference.hxx b/include/xmloff/SoundReference.hxx new file mode 100644 index 000000000000..3bd673ecbb98 --- /dev/null +++ b/include/xmloff/SoundReference.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace xmloff +{ +/** A presentation sound carried across the UNO boundary as an object: the + source URL together with the runtime allowed state. Allowed is decided this + session and is never written to the document. + + Header-only and placed under the shared include tree so it can be built + from the layers below the draw model as well. +*/ +class SoundReference final : public cppu::WeakImplHelper +{ + OUString maURL; + bool mbAllowed; + +public: + SoundReference(OUString aURL, bool bAllowed) + : maURL(std::move(aURL)) + , mbAllowed(bAllowed) + { + } + + OUString SAL_CALL getURL() override { return maURL; } + sal_Bool SAL_CALL getAllowed() override { return mbAllowed; } +}; + +// A sound URL that points inside the document package, the same scheme the +// slideshow sound player treats as in-package media. Any other non-empty URL is +// a link to a file outside the document. +inline bool isPackageSoundURL(const OUString& rURL) +{ + return rURL.startsWithIgnoreAsciiCase(u"vnd.sun.star.Package:"); +} + +// Wrap a sound URL as a source value for an animation audio node. A sound inside +// the document package is always allowed; only an external link waits for the +// user to allow it. +inline css::uno::Any makeSoundSource(const OUString& rURL, bool bAllowed = false) +{ + return css::uno::Any(css::uno::Reference( + new SoundReference(rURL, bAllowed || isPackageSoundURL(rURL)))); +} + +// The source URL of an animation audio node, or empty when the source is not a +// sound (for example a media shape). A bare string URL, the way a source was set +// before it carried the allowed state, is returned as it is. +inline OUString getSoundURL(const css::uno::Any& rSource) +{ + css::uno::Reference xSound; + if (rSource >>= xSound) + return xSound.is() ? xSound->getURL() : OUString(); + OUString sURL; + if (rSource >>= sURL) + return sURL; + return OUString(); +} + +// Whether the sound carried by rSource has been allowed this session. Only a +// SoundReference, set where the sound enters the model, carries that decision. +// Anything else (a bare string set the old way, or a source that is not a sound) +// is treated as not allowed, so an unaudited sound is guarded like an external one. +inline bool getSoundAllowed(const css::uno::Any& rSource) +{ + css::uno::Reference xSound; + if (rSource >>= xSound) + return xSound.is() && xSound->getAllowed(); + return false; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/xmloff/XMLTextMasterPageContext.hxx b/include/xmloff/XMLTextMasterPageContext.hxx index a2b6cfd42b6f..21f888ca6087 100644 --- a/include/xmloff/XMLTextMasterPageContext.hxx +++ b/include/xmloff/XMLTextMasterPageContext.hxx @@ -36,6 +36,8 @@ class XMLOFF_DLLPUBLIC XMLTextMasterPageContext : public SvXMLStyleContext OUString m_sFollow; OUString m_sPageMasterName; OUString m_sDrawingPageStyle; + OUString m_sIsFirstPageFooterEnabled; + OUString m_sIsFirstPageHeaderEnabled; css::uno::Reference < css::style::XStyle > m_xStyle; diff --git a/include/xmloff/families.hxx b/include/xmloff/families.hxx index 79a0e558e9d4..ec83e26152d1 100644 --- a/include/xmloff/families.hxx +++ b/include/xmloff/families.hxx @@ -16,8 +16,8 @@ * 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_XMLOFF_FAMILIES_HXX -#define INCLUDED_XMLOFF_FAMILIES_HXX + +#pragma once #include @@ -110,6 +110,4 @@ enum class XmlStyleFamily }; -#endif // INCLUDED_XMLOFF_FAMILIES_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/xmloff/formlayerexport.hxx b/include/xmloff/formlayerexport.hxx index 823e99875104..603612283675 100644 --- a/include/xmloff/formlayerexport.hxx +++ b/include/xmloff/formlayerexport.hxx @@ -78,7 +78,7 @@ namespace xmloff

        The page the control belongs to must have been examined and sought to.

        @param _rxControl - the control which's id should be retrieved. Must not be . + the control whose id should be retrieved. Must not be . @see examineForms @see seekPage @@ -93,7 +93,7 @@ namespace xmloff do not have a number style. In this case, an empty string is returned.

        @param _rxControl - the control which's id should be retrieved. Must not be . + the control whose number style should be retrieved. Must not be . @see examineForms @see seekPage diff --git a/include/xmloff/formlayerimport.hxx b/include/xmloff/formlayerimport.hxx index 18566b958d45..2179f7ff26a7 100644 --- a/include/xmloff/formlayerimport.hxx +++ b/include/xmloff/formlayerimport.hxx @@ -106,7 +106,7 @@ namespace xmloff /** sets the given number style on the given control @param _rxControlModel - the control model which's style is to be set + the control model whose style is to be set @param _rControlNumberStyleName the style name for the control's number style */ @@ -118,7 +118,7 @@ namespace xmloff /** to be called when the document has been completely imported

        For some documents (currently: only some spreadsheet documents) it's necessary - do to a post processing, since not all information from the file can be processed + to do post processing, since not all information from the file can be processed if the document is not completed, yet.

        */ SAL_DLLPRIVATE void documentDone( ); diff --git a/include/xmloff/shapeexport.hxx b/include/xmloff/shapeexport.hxx index d014fb8fe662..2d32c9c9af03 100644 --- a/include/xmloff/shapeexport.hxx +++ b/include/xmloff/shapeexport.hxx @@ -91,7 +91,7 @@ enum class XmlShapeType DrawFrameShape, // "com.sun.star.drawing.FrameShape" DrawCaptionShape, // "com.sun.star.drawing.CaptionShape" DrawAppletShape, // "com.sun.star.drawing.AppletShape" - DrawPluginShape, // "com.sun.star.drawing.PlugginShape" + DrawPluginShape, // "com.sun.star.drawing.PluginShape" Draw3DSceneObject, // "com.sun.star.drawing.Shape3DSceneObject" Draw3DCubeObject, // "com.sun.star.drawing.Shape3DCubeObject" @@ -194,6 +194,8 @@ private: SAL_DLLPRIVATE void ImpExportGluePoints( const css::uno::Reference< css::drawing::XShape >& xShape ); SAL_DLLPRIVATE void ImpExportSignatureLine(const css::uno::Reference& xShape); SAL_DLLPRIVATE void ImpExportQRCode(const css::uno::Reference& xShape); + SAL_DLLPRIVATE void + ImpExportGraphicClipPoly(const css::uno::Reference& xShape); // single shape exporters SAL_DLLPRIVATE void ImpExportGroupShape( const css::uno::Reference< css::drawing::XShape >& xShape, XMLShapeExportFlags nFeatures = SEF_DEFAULT, css::awt::Point* pRefPoint = nullptr ); diff --git a/include/xmloff/txtimppr.hxx b/include/xmloff/txtimppr.hxx index ca01450d825f..376c2763b9a4 100644 --- a/include/xmloff/txtimppr.hxx +++ b/include/xmloff/txtimppr.hxx @@ -59,7 +59,7 @@ public: SvXMLImport& rImport ); virtual ~XMLTextImportPropertyMapper() override; - /** This method is called when all attributes have benn processed. It may be used to remove items that are incomplete */ + /** This method is called when all attributes have been processed. It may be used to remove items that are incomplete */ virtual void finished( ::std::vector< XMLPropertyState >& rProperties, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const override; diff --git a/include/xmloff/xmlimppr.hxx b/include/xmloff/xmlimppr.hxx index ecee9ceefeb0..08e866c8af2b 100644 --- a/include/xmloff/xmlimppr.hxx +++ b/include/xmloff/xmlimppr.hxx @@ -110,7 +110,7 @@ public: const SvXMLUnitConverter& rUnitConverter, const SvXMLNamespaceMap& rNamespaceMap ) const; - /** This method is called when all attributes have benn processed. It may be used to remove items that are incomplete */ + /** This method is called when all attributes have been processed. It may be used to remove items that are incomplete */ virtual void finished( ::std::vector< XMLPropertyState >& rProperties, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const; diff --git a/include/xmloff/xmlnamespace.hxx b/include/xmloff/xmlnamespace.hxx index 91ff2aae4cf3..2534fbd128c5 100644 --- a/include/xmloff/xmlnamespace.hxx +++ b/include/xmloff/xmlnamespace.hxx @@ -88,12 +88,12 @@ constexpr sal_uInt16 XML_NAMESPACE_CHART_EXT = XML_NAMESPACE_EXT_BASE + 2; constexpr sal_uInt16 XML_NAMESPACE_DRAW_EXT = XML_NAMESPACE_EXT_BASE + 3; constexpr sal_uInt16 XML_NAMESPACE_CALC_EXT = XML_NAMESPACE_EXT_BASE + 4; constexpr sal_uInt16 XML_NAMESPACE_LO_EXT = XML_NAMESPACE_EXT_BASE + 5; +constexpr sal_uInt16 XML_NAMESPACE_COL_EXT = XML_NAMESPACE_EXT_BASE + 6; // experimental ODF extended namespaces -constexpr sal_uInt16 XML_NAMESPACE_FIELD = XML_NAMESPACE_EXT_BASE + 6; -constexpr sal_uInt16 XML_NAMESPACE_CSS3TEXT = XML_NAMESPACE_EXT_BASE + 7; // CSS Text Level 3 -constexpr sal_uInt16 XML_NAMESPACE_FORMX = XML_NAMESPACE_EXT_BASE + 8; // form interop extensions - +constexpr sal_uInt16 XML_NAMESPACE_FIELD = XML_NAMESPACE_EXT_BASE + 7; +constexpr sal_uInt16 XML_NAMESPACE_CSS3TEXT = XML_NAMESPACE_EXT_BASE + 8; // CSS Text Level 3 +constexpr sal_uInt16 XML_NAMESPACE_FORMX = XML_NAMESPACE_EXT_BASE + 9; // form interop extensions // namespaces for OOo formats constexpr sal_uInt16 XML_NAMESPACE_OOO_BASE = 60; diff --git a/include/xmloff/xmlnumfi.hxx b/include/xmloff/xmlnumfi.hxx index c6a3159d796e..7cb3617fdb62 100644 --- a/include/xmloff/xmlnumfi.hxx +++ b/include/xmloff/xmlnumfi.hxx @@ -188,6 +188,7 @@ public: bool HasLongDoW() const { return m_bHasLongDoW; } void SetHasLongDoW(bool bSet) { m_bHasLongDoW = bSet; } + bool IsAutoOrder() const { return m_bAutoOrder; } void SetHasTrailingEmptyText(bool bSet) { m_bHasTrailingEmptyText = bSet; } void UpdateCalendar( const OUString& rNewCalendar ); diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx index 85ea12c0478c..abf0ec8e73ff 100644 --- a/include/xmloff/xmltoken.hxx +++ b/include/xmloff/xmltoken.hxx @@ -28,7 +28,7 @@ /** * Handling of tokens in XML: * - * This header defines te enum ::xmloff::token::XMLTokenEnum containing one + * This header defines the enum ::xmloff::token::XMLTokenEnum containing one * value for every fixed string used in our XML files. * * Usage: @@ -177,6 +177,10 @@ namespace xmloff::token { XML_N_FIELD, XML_NP_FIELD, + // Collabora extensions + XML_NP_COL_EXT, + XML_N_COL_EXT, + // units XML_UNIT_M, XML_UNIT_CM, @@ -331,6 +335,8 @@ namespace xmloff::token { XML_BIBLIOGRAPHY_MARK, XML_BIBLIOGRAPHY_SOURCE, XML_BIBLIOGRAPHY_TYPE, + XML_BIN_COUNT, + XML_BIN_WIDTH, XML_BIND_STYLES_TO_CONTENT, XML_BITMAP, XML_BITMAP_TABLE, @@ -531,6 +537,7 @@ namespace xmloff::token { XML_COPY_STYLES, XML_CORNER_RADIUS, XML_CORRECT, + XML_CORRELATION_CIRCLE, XML_COS, XML_COSH, XML_COT, @@ -895,6 +902,8 @@ namespace xmloff::token { XML_FONT_STYLE_NAME_ASIAN, XML_FONT_STYLE_NAME_COMPLEX, XML_FONT_VARIATION_SETTINGS, + XML_FONT_VARIATION_SETTINGS_ASIAN, + XML_FONT_VARIATION_SETTINGS_COMPLEX, XML_FONT_VARIANT, XML_FONT_WEIGHT, XML_FONT_WEIGHT_ASIAN, @@ -920,6 +929,7 @@ namespace xmloff::token { XML_FONTWORK_STYLE, XML_FOOTER, XML_FOOTER_FIRST, + XML_IS_FIRST_PAGE_FOOTER_ENABLED, XML_FOOTER_LEFT, XML_FOOTER_STYLE, XML_FOOTER_VISIBLE, @@ -955,6 +965,7 @@ namespace xmloff::token { XML_FRAME_MARGIN_VERTICAL, XML_FRAME_NAME, XML_FRAME_START_MARGIN, + XML_FREQUENCY_TYPE, XML_FREEZE, XML_FREEZE_POSITION, XML_FROM_ANOTHER_TABLE, @@ -1002,6 +1013,7 @@ namespace xmloff::token { XML_GRADIENTTRANSFORM, XML_GRAND_TOTAL, XML_GRAPHIC, + XML_GRAPHIC_CLIP_POLY, XML_GRAY, XML_GREEN, XML_GREYSCALE, @@ -1021,6 +1033,7 @@ namespace xmloff::token { XML_HATCHSTYLE_TRIPLE, XML_HEADER, XML_HEADER_FIRST, + XML_IS_FIRST_PAGE_HEADER_ENABLED, XML_HEADER_LEFT, XML_HEADER_STYLE, XML_HEADERS, @@ -1039,6 +1052,7 @@ namespace xmloff::token { XML_HIDE_TEXT, XML_HIGHLIGHTED_RANGE, XML_HINT, + XML_HISTOGRAM, XML_HORIZONTAL, XML_HORIZONTALSTRIKE, XML_HORIZONTAL_LINES, @@ -1078,6 +1092,7 @@ namespace xmloff::token { XML_HYPHENATION_ZONE_SPREAD, XML_HYPHENATION_COMPOUND_REMAIN_CHAR_COUNT, XML_HYPHENATION_COMPOUND_PUSH_CHAR_COUNT, + XML_HYPHENATION_LEVEL, XML_I, XML_ICON, XML_ICON_SET, @@ -1484,6 +1499,7 @@ namespace xmloff::token { XML_OUTSET, XML_OUTSIDE, XML_OVERFLOW_BEHAVIOR, + XML_OVERFLOW_BIN_VALUE, XML_OVERLAP, XML_OVERLAY, XML_P, @@ -1540,6 +1556,9 @@ namespace xmloff::token { XML_PERCENTAGE, XML_PERCENTAGE_STYLE, XML_PERSPECTIVE, + XML_PERSON, + XML_PERSON_ID, + XML_PERSONS, XML_PHDTHESIS, XML_PHONG, XML_PHYSICS_ANIMATION_START_VELOCITY_X, @@ -1548,6 +1567,8 @@ namespace xmloff::token { XML_PHYSICS_ANIMATION_BOUNCINESS, XML_PIE_OFFSET, XML_PLACEHOLDER, + XML_PLACEHOLDER_CLASS, + XML_PLACEHOLDER_PROMPT, XML_PLACEHOLDER_TYPE, XML_PLACING, XML_PLAIN_NUMBER, @@ -1660,6 +1681,7 @@ namespace xmloff::token { XML_REPEAT_ROW, XML_REPEATED, XML_REPLACE, + XML_REPLY, XML_REPORT_TYPE, XML_RESTART_ON_PAGE, XML_REVISION, @@ -1723,7 +1745,9 @@ namespace xmloff::token { XML_SECONDS, XML_SECTION, XML_SECTION_DESC, + XML_SECTION_LIST, XML_SECTION_NAME, + XML_SECTION_SLIDE, XML_SECTION_SOURCE, XML_SELECT_PAGE, XML_SELECT_PROTECTED_CELLS, @@ -1845,6 +1869,7 @@ namespace xmloff::token { XML_SPECULAR_COLOR, XML_SPEED, XML_SPHERE, + XML_SPILL, XML_SPIRAL, XML_SPIRAL_IN, XML_SPIRAL_INWARD_LEFT, @@ -2038,6 +2063,7 @@ namespace xmloff::token { XML_THICK, XML_THIN, XML_THREE_DIMENSIONAL, + XML_THREADED_COMMENT, XML_THUMBNAIL, XML_TICK_MARKS_MAJOR_INNER, XML_TICK_MARKS_MAJOR_OUTER, @@ -2101,6 +2127,7 @@ namespace xmloff::token { XML_SUGGESTED_SIGNER_NAME, XML_SUGGESTED_SIGNER_TITLE, XML_WAVE, + XML_UNDERFLOW_BIN_VALUE, XML_UNFORMATTED_TEXT, XML_UNION, XML_UNIT, @@ -2136,6 +2163,7 @@ namespace xmloff::token { XML_USE_WINDOW_FONT_COLOR, XML_USED_HIERARCHY, XML_USER_DEFINED, + XML_USER_ID, XML_USER_FIELD_DECL, XML_USER_FIELD_DECLS, XML_USER_FIELD_GET, @@ -2148,6 +2176,8 @@ namespace xmloff::token { XML_USER_INDEX_SOURCE, XML_USER_TRANSFORMED, XML_USERNAME, + XML_USE_OVERFLOW_BIN, + XML_USE_UNDERFLOW_BIN, XML_VALIDATION, XML_VALUE, XML_VALUE_TYPE, @@ -3449,6 +3479,7 @@ namespace xmloff::token { XML_PROPERTY_MAPPING, XML_PROVIDER, + XML_PROVIDER_ID, XML_DATA_MAPPINGS, XML_DATA_MAPPING, XML_DATA_FREQUENCY, @@ -3535,6 +3566,8 @@ namespace xmloff::token { XML_PAGE_CONTENT_BOTTOM, XML_MARGIN_GUTTER, + XML_MIN_PAGE_MARGIN_TOP, + XML_MIN_PAGE_MARGIN_BOTTOM, XML_LOCAL_URL, XML_TARGET_TYPE, @@ -3598,6 +3631,8 @@ namespace xmloff::token { XML_ASIAN, XML_COMPLEX, + XML_HORIZONTAL_RULE, + XML_TOKEN_END }; diff --git a/include/xmloff/xmltypes.hxx b/include/xmloff/xmltypes.hxx index e734251d0a84..8e7175ee6895 100644 --- a/include/xmloff/xmltypes.hxx +++ b/include/xmloff/xmltypes.hxx @@ -35,11 +35,11 @@ #define MID_FLAG_MASK 0x00003fff -// Import only: In general, properties may not throw exception, but +// Import only: In general, properties may not throw an exception, but // this one may. If it throws an IllegalArgumentException, it will be // silently ignored. This should be used for properties whose values // cannot be checked. (E.g., the printer paper tray: The tray names -// are different for all printers, and we don't know ahead whether a +// are different for all printers, and we don't know ahead of time whether a // printer supports the trays in the current document.) #define MID_FLAG_PROPERTY_MAY_THROW 0x00100000 @@ -60,7 +60,7 @@ // the current value to the importXML call. #define MID_FLAG_MERGE_PROPERTY 0x01000000 -// Import only: there are more entries for the same xml attribute existing +// Import only: there are more entries for the same xml attribute #define MID_FLAG_MULTI_PROPERTY 0x02000000 // the map entry denotes the name of an element item @@ -139,7 +139,7 @@ #define XML_TYPE_NBOOL 0x0000200f // !true/false #define XML_TYPE_COLORTRANSPARENT 0x00002010 // Colors or "transparent" #define XML_TYPE_ISTRANSPARENT 0x00002011 // "transparent" -#define XML_TYPE_BUILDIN_CMP_ONLY 0x00002012 // Only buildin comparison is required, so no handler exists +#define XML_TYPE_BUILDIN_CMP_ONLY 0x00002012 // Only built-in comparison is required, so no handler exists #define XML_TYPE_NUMBER8_NONE 0x00002013 // 123 and "no-limit" for 0 #define XML_TYPE_NUMBER16_NONE 0x00002014 // 123 and "no-limit" for 0 #define XML_TYPE_COLOR_MODE 0x00002015 diff --git a/instsetoo_native/CustomTarget_install.mk b/instsetoo_native/CustomTarget_install.mk index 5c2bfd4ce462..a0930f431947 100644 --- a/instsetoo_native/CustomTarget_install.mk +++ b/instsetoo_native/CustomTarget_install.mk @@ -108,6 +108,7 @@ $(gb_Make_JobLimiter): $(SRCDIR)/solenv/bin/job-limiter.cpp # packaging (since packaging the main installer takes longer than packaging sdk and all helppacks # even with the reduced parallelism (the higher the parallelism, the higher the chance for random # failures during the cscript call to WiLangId.vbs) +$(instsetoo_installer_targets): export FAKEROOT:=$(FAKEROOT) $(instsetoo_installer_targets): $(SRCDIR)/solenv/bin/make_installer.pl \ $(foreach ulf,$(instsetoo_ULFLIST),$(gb_CustomTarget_workdir)/instsetoo_native/install/win_ulffiles/$(ulf).ulf) \ $(if $(filter-out WNT,$(OS)),\ diff --git a/io/test/stm/marktest.cxx b/io/test/stm/marktest.cxx index 0dd01a7f7747..6538fd2cc411 100644 --- a/io/test/stm/marktest.cxx +++ b/io/test/stm/marktest.cxx @@ -235,7 +235,7 @@ void OMarkableOutputStreamTest::testSimple( const Reference< XOutputStream > rOutput->writeBytes( seqWrite ); } - ERROR_ASSERT( 0 == rInput->available() , "bytes available though mark is holded" ); + ERROR_ASSERT( 0 == rInput->available() , "bytes available though mark is held" ); ERROR_ASSERT( nMax*seqWrite.getLength() == rMarkable->offsetToMark( nMark ) , "offsetToMark failure" ); diff --git a/javaunohelper/source/juhx-export-functions.hxx b/javaunohelper/source/juhx-export-functions.hxx index 569822f2c53a..3215a59db326 100644 --- a/javaunohelper/source/juhx-export-functions.hxx +++ b/javaunohelper/source/juhx-export-functions.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_JAVAUNOHELPER_SOURCE_JUHX_EXPORT_FUNCTIONS_HXX -#define INCLUDED_JAVAUNOHELPER_SOURCE_JUHX_EXPORT_FUNCTIONS_HXX +#pragma once #include @@ -39,6 +38,4 @@ Java_com_sun_star_comp_helper_SharedLibraryLoader_component_1writeInfo; } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/javaunohelper/source/juhx-export-types.hxx b/javaunohelper/source/juhx-export-types.hxx index 8e2783452274..0018510f0694 100644 --- a/javaunohelper/source/juhx-export-types.hxx +++ b/javaunohelper/source/juhx-export-types.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_JAVAUNOHELPER_SOURCE_JUHX_EXPORT_TYPES_HXX -#define INCLUDED_JAVAUNOHELPER_SOURCE_JUHX_EXPORT_TYPES_HXX +#pragma once #include @@ -47,6 +46,4 @@ typedef jboolean JAVAUNOHELPER_DETAIL_CALLCONV Func_writeInfo( } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/javaunohelper/source/vm.hxx b/javaunohelper/source/vm.hxx index 6681dfffac21..23f842b0382b 100644 --- a/javaunohelper/source/vm.hxx +++ b/javaunohelper/source/vm.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_JAVAUNOHELPER_SOURCE_VM_HXX -#define INCLUDED_JAVAUNOHELPER_SOURCE_VM_HXX +#pragma once #include @@ -50,6 +49,4 @@ install_vm_singleton( } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/jsuno/CppunitTest_jsuno_execute.mk b/jsuno/CppunitTest_jsuno_execute.mk new file mode 100644 index 000000000000..a4af0bafbd57 --- /dev/null +++ b/jsuno/CppunitTest_jsuno_execute.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/. +# +# Contributor(s): +# Copyright the Collabora Office contributors. + +$(eval $(call gb_CppunitTest_CppunitTest,jsuno_execute)) + +$(eval $(call gb_CppunitTest_add_exception_objects,jsuno_execute, \ + jsuno/qa/unit/execute \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,jsuno_execute, \ + jsuno \ + sal \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,jsuno_execute)) + +$(eval $(call gb_CppunitTest_use_ure,jsuno_execute)) + +# vim: set noet sw=4 ts=4: diff --git a/jsuno/CppunitTest_jsuno_testuno.mk b/jsuno/CppunitTest_jsuno_testuno.mk new file mode 100644 index 000000000000..d2486e47ec7b --- /dev/null +++ b/jsuno/CppunitTest_jsuno_testuno.mk @@ -0,0 +1,29 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,jsuno_testuno)) + +$(eval $(call gb_CppunitTest_add_exception_objects,jsuno_testuno, \ + jsuno/qa/unit/testuno \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,jsuno_testuno, \ + jsuno \ + sal \ +)) + +$(eval $(call gb_CppunitTest_use_components,jsuno_testuno, \ + unotest/source/embindtest/embindtest \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,jsuno_testuno)) + +$(eval $(call gb_CppunitTest_use_ure,jsuno_testuno)) + +# vim: set noet sw=4 ts=4: diff --git a/jsuno/Library_jsuno.mk b/jsuno/Library_jsuno.mk new file mode 100644 index 000000000000..fdba53ac4f7f --- /dev/null +++ b/jsuno/Library_jsuno.mk @@ -0,0 +1,32 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Library_Library,jsuno)) + +$(eval $(call gb_Library_add_defs,jsuno,-DLO_DLLIMPLEMENTATION_JSUNO)) + +$(eval $(call gb_Library_add_exception_objects,jsuno, \ + jsuno/source/jsuno \ + jsuno/source/rhinocompatibility \ +)) + +$(eval $(call gb_Library_use_externals,jsuno, \ + quickjs \ +)) + +$(eval $(call gb_Library_use_libraries,jsuno, \ + comphelper \ + cppu \ + cppuhelper \ + sal \ +)) + +$(eval $(call gb_Library_use_sdk_api,jsuno)) + +# vim: set noet sw=4 ts=4: diff --git a/jsuno/Makefile b/jsuno/Makefile new file mode 100644 index 000000000000..d5aa252aa8c3 --- /dev/null +++ b/jsuno/Makefile @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +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/jsuno/Module_jsuno.mk b/jsuno/Module_jsuno.mk new file mode 100644 index 000000000000..1e32e4928014 --- /dev/null +++ b/jsuno/Module_jsuno.mk @@ -0,0 +1,21 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Module_Module,jsuno)) + +$(eval $(call gb_Module_add_targets,jsuno, \ + Library_jsuno \ +)) + +$(eval $(call gb_Module_add_check_targets,jsuno, \ + $(if $(ENABLE_EMBINDTEST_UNO),CppunitTest_jsuno_testuno) \ + CppunitTest_jsuno_execute \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/jsuno/README.md b/jsuno/README.md new file mode 100644 index 000000000000..8df84ae80db2 --- /dev/null +++ b/jsuno/README.md @@ -0,0 +1 @@ +QuickJS-based JS UNO support diff --git a/jsuno/qa/extras/common.js b/jsuno/qa/extras/common.js new file mode 100644 index 000000000000..7387d9c39f68 --- /dev/null +++ b/jsuno/qa/extras/common.js @@ -0,0 +1,29 @@ +/* + * 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/. + */ + +function assertError(code, exceptionMessage) +{ + try + { + code(); + } + catch (error) + { + if (error != exceptionMessage) + { + console.log("Exception message mismatch:\n" + + "Expected: " + exceptionMessage + "\n" + + "Actual: " + error); + } + console.assert(error == exceptionMessage); + return; + } + + console.log("exception expected but none was thrown"); + console.assert(false); +} diff --git a/jsuno/qa/extras/test.js b/jsuno/qa/extras/test.js new file mode 100644 index 000000000000..fc944a83e29a --- /dev/null +++ b/jsuno/qa/extras/test.js @@ -0,0 +1,828 @@ +/* + * 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/. + */ + +console.assert(uno.type.void.toString() == 'void'); +console.assert(uno.type.boolean.toString() == 'boolean'); +console.assert(uno.type.byte.toString() == 'byte'); +console.assert(uno.type.short.toString() == 'short'); +console.assert(uno.type.unsigned_short.toString() == 'unsigned short'); +console.assert(uno.type.long.toString() == 'long'); +console.assert(uno.type.unsigned_long.toString() == 'unsigned long'); +console.assert(uno.type.hyper.toString() == 'hyper'); +console.assert(uno.type.unsigned_hyper.toString() == 'unsigned hyper'); +console.assert(uno.type.float.toString() == 'float'); +console.assert(uno.type.double.toString() == 'double'); +console.assert(uno.type.char.toString() == 'char'); +console.assert(uno.type.string.toString() == 'string'); +console.assert(uno.type.type.toString() == 'type'); +console.assert(uno.type.any.toString() == 'any'); +console.assert(uno.type.sequence(uno.type.sequence(uno.type.string)).toString() == '[][]string'); +console.assert( + uno.type.sequence(uno.type.enum(uno.idl.org.libreoffice.embindtest.Enum)).toString() + == '[]org.libreoffice.embindtest.Enum'); +console.assert( + uno.type.enum(uno.idl.org.libreoffice.embindtest.Enum).toString() == 'org.libreoffice.embindtest.Enum'); +console.assert( + uno.type.struct(uno.idl.org.libreoffice.embindtest.Struct).toString() + == 'org.libreoffice.embindtest.Struct'); +console.assert( + uno.type.struct( + uno.idl.org.libreoffice.embindtest.Template, + [uno.type.any, uno.type.struct(uno.idl.org.libreoffice.embindtest.StructString)]).toString() + == 'org.libreoffice.embindtest.Template'); +console.assert( + uno.type.exception(uno.idl.org.libreoffice.embindtest.Exception).toString() + == 'org.libreoffice.embindtest.Exception'); +console.assert( + uno.type.interface(uno.idl.org.libreoffice.embindtest.XTest).toString() + == 'org.libreoffice.embindtest.XTest'); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.Boolean === true); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.Byte === -12); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.Short === -1234); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.UnsignedShort === 54321); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.Long === -123456); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.UnsignedLong === 3456789012); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.Hyper === -123456789n); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.UnsignedHyper === 9876543210n); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.Float === -10.25); +console.assert(uno.idl.org.libreoffice.embindtest.Constants.Double === 100.5); +const test = uno.idl.org.libreoffice.embindtest.Test.create(uno.componentContext); +{ + const v = test.getBoolean(); + console.log(v); + console.assert(v === true); + console.assert(test.isBoolean(true)); +} +{ + const v = test.getByte(); + console.log(v); + console.assert(v === -12); + console.assert(test.isByte(-12)); +} +{ + const v = test.getShort(); + console.log(v); + console.assert(v === -1234); + console.assert(test.isShort(-1234)); +} +{ + const v = test.getUnsignedShort(); + console.log(v); + console.assert(v === 54321); + console.assert(test.isUnsignedShort(54321)); +} +{ + const v = test.getLong(); + console.log(v); + console.assert(v === -123456); + console.assert(test.isLong(-123456)); +} +{ + const v = test.getUnsignedLong(); + console.log(v); + console.assert(v === 3456789012); + console.assert(test.isUnsignedLong(3456789012)); +} +{ + const v = test.getHyper(); + console.log(v); + console.assert(v === -123456789n); + console.assert(test.isHyper(-123456789n)); +} +{ + const v = test.getUnsignedHyper(); + console.log(v); + console.assert(v === 9876543210n); + console.assert(test.isUnsignedHyper(9876543210n)); +} +{ + const v = test.getFloat(); + console.log(v); + console.assert(v === -10.25); + console.assert(test.isFloat(-10.25)); +} +{ + const v = test.getDouble(); + console.log(v); + console.assert(v === 100.5); + console.assert(test.isDouble(100.5)); +} +{ + const v = test.getChar(); + console.log(v); + console.assert(v === 'Ö'); + console.assert(test.isChar('Ö')); +} +{ + const v = test.getString(); + console.log(v); + console.assert(v === 'hä'); + console.assert(test.isString('hä')); +} +{ + const v = test.getType(); + console.log(v); + console.assert(v.toString() === 'long'); + console.assert(test.isType(v)); + console.assert(test.isType(uno.type.long)); +} +{ + const v = test.getEnum(); + console.log(v); + console.assert(v === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(test.isEnum(uno.idl.org.libreoffice.embindtest.Enum.E_2)); +} +{ + const v = test.getStruct(); + console.log(v); + console.assert(v.m1 === true); + console.assert(v.m2 === -12); + console.assert(v.m3 === -1234); + console.assert(v.m4 === 54321); + console.assert(v.m5 === -123456); + console.assert(v.m6 === 3456789012); + console.assert(v.m7 === -123456789n); + console.assert(v.m8 === 9876543210n); + console.assert(v.m9 === -10.25); + console.assert(v.m10 === 100.5); + console.assert(v.m11 === 'Ö'); + console.assert(v.m12 === 'hä'); + console.assert(v.m13.toString() === 'long'); + console.assert(v.m14 === -123456); + console.assert(v.m15.length === 3); + console.assert(v.m15[0] === 'foo'); + console.assert(v.m15[1] === 'barr'); + console.assert(v.m15[2] === 'bazzz'); + console.assert(v.m16 === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v.m17.m === -123456); + console.assert(v.m18.m1.m === 'foo'); + console.assert(v.m18.m2 === -123456); + console.assert(v.m18.m3 === -123456); + console.assert(v.m18.m4.m === 'barr'); + console.assert(uno.sameUnoObject(v.m19, test)); + console.assert(test.isStruct( + new uno.idl.org.libreoffice.embindtest.Struct({ + m1: true, m2: -12, m3: -1234, m4: 54321, m5: -123456, m6: 3456789012, + m7: -123456789n, m8: 9876543210n, m9: -10.25, m10: 100.5, m11: 'Ö', m12: 'hä', + m13: uno.type.long, m14: -123456, m15: ['foo', 'barr', 'bazzz'], + m16: uno.idl.org.libreoffice.embindtest.Enum.E_2, + m17: new uno.idl.org.libreoffice.embindtest.StructLong({m: -123456}), + m18: new uno.idl.org.libreoffice.embindtest.Template( + [uno.type.any, + uno.type.struct( + uno.idl.org.libreoffice.embindtest.StructString)], + {m1: new uno.idl.org.libreoffice.embindtest.StructString({m: 'foo'}), + m2: -123456, m3: -123456, + m4: new uno.idl.org.libreoffice.embindtest.StructString({m: 'barr'})}), + m19: test}))); + console.assert(test.isStruct({ + m1: true, m2: -12, m3: -1234, m4: 54321, m5: -123456, m6: 3456789012, + m7: -123456789n, m8: 9876543210n, m9: -10.25, m10: 100.5, m11: 'Ö', m12: 'hä', + m13: uno.type.long, m14: -123456, m15: ['foo', 'barr', 'bazzz'], + m16: uno.idl.org.libreoffice.embindtest.Enum.E_2, m17: {m: -123456}, + m18: {m1: {m: 'foo'}, m2: -123456, m3: -123456, m4: {m: 'barr'}}, m19: test})); + const def = new uno.idl.org.libreoffice.embindtest.Struct(); + console.assert(def.m1 === false); + console.assert(def.m2 === 0); + console.assert(def.m3 === 0); + console.assert(def.m4 === 0); + console.assert(def.m5 === 0); + console.assert(def.m6 === 0); + console.assert(def.m7 === 0n); + console.assert(def.m8 === 0n); + console.assert(def.m9 === 0); + console.assert(def.m10 === 0); + console.assert(def.m11 === '\0'); + console.assert(def.m12 === ''); + console.assert(def.m13.toString() === 'void'); + console.assert(def.m14 === undefined); + console.assert(def.m15.length === 0); + console.assert(def.m16 === uno.idl.org.libreoffice.embindtest.Enum.E_10); + console.assert(def.m17.m === 0); + console.assert(def.m18.m1.m === ''); + console.assert(def.m18.m2 === 0); + console.assert(def.m18.m3 === undefined); + console.assert(def.m18.m4.m === ''); + console.assert(def.m19 === null); +} + +{ + const v = test.getTemplate(); + console.log(v); + console.assert(v.m1.m === 'foo'); + console.assert(v.m2 === -123456); + console.assert(v.m3 === -123456); + console.assert(v.m4.m === 'barr'); + console.assert(test.isTemplate( + new uno.idl.org.libreoffice.embindtest.Template( + [uno.type.any, uno.type.struct(uno.idl.org.libreoffice.embindtest.StructString)], + {m1: new uno.idl.org.libreoffice.embindtest.StructString({m: 'foo'}), + m2: -123456, m3: -123456, + m4: new uno.idl.org.libreoffice.embindtest.StructString({m: 'barr'})}))); + console.assert(test.isTemplate( + {m1: {m: 'foo'}, m2: -123456, m3: -123456, m4: {m: 'barr'}})); + const def = new uno.idl.org.libreoffice.embindtest.Template( + [uno.type.any, uno.type.struct(uno.idl.org.libreoffice.embindtest.StructString)]); + console.assert(def.m1.m === ''); + console.assert(def.m2 === 0); + console.assert(def.m3 === undefined); + console.assert(def.m4.m === ''); +} +{ + const v = test.getAnyVoid(); + console.log(v); + console.assert(v === undefined); + console.assert(test.isAnyVoid(undefined)); + console.assert(test.isAnyVoid(new uno.Any(uno.type.void))); +} +{ + const v = test.getAnyBoolean(); + console.log(v); + console.assert(v === true); + console.assert(test.isAnyBoolean(true)); + console.assert(test.isAnyBoolean(new uno.Any(uno.type.boolean, true))); +} +{ + const v = test.getAnyByte(); + console.log(v); + console.assert(v === -12); + console.assert(test.isAnyByte(new uno.Any(uno.type.byte, -12))); +} +{ + const v = test.getAnyShort(); + console.log(v); + console.assert(v === -1234); + console.assert(test.isAnyShort(new uno.Any(uno.type.short, -1234))); +} +{ + const v = test.getAnyUnsignedShort(); + console.log(v); + console.assert(v === 54321); + console.assert(test.isAnyUnsignedShort(new uno.Any(uno.type.unsigned_short, 54321))); +} +{ + const v = test.getAnyLong(); + console.log(v); + console.assert(v === -123456); + console.assert(test.isAnyLong(-123456)); + console.assert(test.isAnyLong(new uno.Any(uno.type.long, -123456))); +} +{ + const v = test.getAnyUnsignedLong(); + console.log(v); + console.assert(v === 3456789012); + console.assert(test.isAnyUnsignedLong(3456789012)); + console.assert(test.isAnyUnsignedLong(new uno.Any(uno.type.unsigned_long, 3456789012))); +} +{ + const v = test.getAnyHyper(); + console.log(v); + console.assert(v === -123456789n); + console.assert(test.isAnyHyper(-123456789n)); + console.assert(test.isAnyHyper(new uno.Any(uno.type.hyper, -123456789n))); +} +{ + const v = test.getAnyUnsignedHyper(); + console.log(v); + console.assert(v === 9876543210n); + console.assert(test.isAnyUnsignedHyper(new uno.Any(uno.type.unsigned_hyper, 9876543210n))); +} +{ + const v = test.getAnyFloat(); + console.log(v); + console.assert(v === -10.25); + console.assert(test.isAnyFloat(new uno.Any(uno.type.float, -10.25))); +} +{ + const v = test.getAnyDouble(); + console.log(v); + console.assert(v === 100.5); + console.assert(test.isAnyDouble(100.5)); + console.assert(test.isAnyDouble(new uno.Any(uno.type.double, 100.5))); +} +{ + const v = test.getAnyChar(); + console.log(v); + console.assert(v === 'Ö'); + console.assert(test.isAnyChar(new uno.Any(uno.type.char, 'Ö'))); +} +{ + const v = test.getAnyString(); + console.log(v); + console.assert(v === 'hä'); + console.assert(test.isAnyString('hä')); + console.assert(test.isAnyString(new uno.Any(uno.type.string, 'hä'))); +} +{ + const v = test.getAnyType(); + console.log(v); + console.assert(v.toString() === 'long'); + console.assert(test.isAnyType(uno.type.long)); + console.assert(test.isAnyType(new uno.Any(uno.type.type, uno.type.long))); +} +{ + const v = test.getAnySequence(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === 'foo'); + console.assert(v[1] === 'barr'); + console.assert(v[2] === 'bazzz'); + console.assert(test.isAnySequence( + new uno.Any(uno.type.sequence(uno.type.string), ['foo', 'barr', 'bazzz']))); +} +{ + const v = test.getAnyEnum(); + console.log(v); + console.assert(v === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(test.isAnyEnum(uno.idl.org.libreoffice.embindtest.Enum.E_2)); + console.assert(test.isAnyEnum( + new uno.Any( + uno.type.enum(uno.idl.org.libreoffice.embindtest.Enum), + uno.idl.org.libreoffice.embindtest.Enum.E_2))); +} +{ + const v = test.getAnyStruct(); + console.log(v); + console.assert(v.m1 === true); + console.assert(v.m2 === -12); + console.assert(v.m3 === -1234); + console.assert(v.m4 === 54321); + console.assert(v.m5 === -123456); + console.assert(v.m6 === 3456789012); + console.assert(v.m7 === -123456789n); + console.assert(v.m8 === 9876543210n); + console.assert(v.m9 === -10.25); + console.assert(v.m10 === 100.5); + console.assert(v.m11 === 'Ö'); + console.assert(v.m12 === 'hä'); + console.assert(v.m13.toString() === 'long'); + console.assert(v.m14 === -123456); + console.assert(v.m15.length === 3); + console.assert(v.m15[0] === 'foo'); + console.assert(v.m15[1] === 'barr'); + console.assert(v.m15[2] === 'bazzz'); + console.assert(v.m16 === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v.m17.m === -123456); + console.assert(v.m18.m1.m === 'foo'); + console.assert(v.m18.m2 === -123456); + console.assert(v.m18.m3 === -123456); + console.assert(v.m18.m4.m === 'barr'); + console.assert(uno.sameUnoObject(v.m19, test)); + console.assert(test.isAnyStruct( + new uno.idl.org.libreoffice.embindtest.Struct( + {m1: true, m2: -12, m3: -1234, m4: 54321, m5: -123456, m6: 3456789012, + m7: -123456789n, m8: 9876543210n, m9: -10.25, m10: 100.5, m11: 'Ö', m12: 'hä', + m13: uno.type.long, m14: -123456, m15: ['foo', 'barr', 'bazzz'], + m16: uno.idl.org.libreoffice.embindtest.Enum.E_2, + m17: new uno.idl.org.libreoffice.embindtest.StructLong({m: -123456}), + m18: new uno.idl.org.libreoffice.embindtest.Template( + [uno.type.any, uno.type.struct(uno.idl.org.libreoffice.embindtest.StructString)], + {m1: new uno.idl.org.libreoffice.embindtest.StructString({m: 'foo'}), + m2: -123456, m3: -123456, + m4: new uno.idl.org.libreoffice.embindtest.StructString({m: 'barr'})}), + m19: test}))); + console.assert(test.isAnyStruct( + new uno.Any( + uno.type.struct(uno.idl.org.libreoffice.embindtest.Struct), + {m1: true, m2: -12, m3: -1234, m4: 54321, m5: -123456, m6: 3456789012, m7: -123456789n, + m8: 9876543210n, m9: -10.25, m10: 100.5, m11: 'Ö', m12: 'hä', m13: uno.type.long, + m14: -123456, m15: ['foo', 'barr', 'bazzz'], + m16: uno.idl.org.libreoffice.embindtest.Enum.E_2, m17: {m: -123456}, + m18: {m1: {m: 'foo'}, m2: -123456, m3: -123456, m4: {m: 'barr'}}, m19: test}))); +} + +{ + const v = test.getAnyException(); + console.log(v); + console.assert(v.Message.startsWith('error')); + console.assert(v.Context === null); + console.assert(v.m1 === -123456); + console.assert(v.m2 === 100.5); + console.assert(v.m3 === 'hä'); + console.assert(test.isAnyException( + new uno.idl.org.libreoffice.embindtest.Exception( + {Message: 'error', m1: -123456, m2: 100.5, m3: 'hä'}))); + console.assert(test.isAnyException( + new uno.Any( + uno.type.exception(uno.idl.org.libreoffice.embindtest.Exception), + {Message: 'error', Context: null, m1: -123456, m2: 100.5, m3: 'hä'}))); +} +{ + const v = test.getAnyInterface(); + console.log(v); + console.assert(uno.sameUnoObject(v, test)); + console.assert(test.isAnyInterface( + new uno.Any(uno.type.interface(uno.idl.org.libreoffice.embindtest.XTest), test))); +} +{ + const v = test.getSequenceBoolean(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === true); + console.assert(v[1] === true); + console.assert(v[2] === false); + console.assert(test.isSequenceBoolean([true, true, false])); +} +{ + const v = test.getSequenceByte(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === -12); + console.assert(v[1] === 1); + console.assert(v[2] === 12); + console.assert(test.isSequenceByte([-12, 1, 12])); +} +{ + const v = test.getSequenceShort(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === -1234); + console.assert(v[1] === 1); + console.assert(v[2] === 1234); + console.assert(test.isSequenceShort([-1234, 1, 1234])); +} +{ + const v = test.getSequenceUnsignedShort(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === 1); + console.assert(v[1] === 10); + console.assert(v[2] === 54321); + console.assert(test.isSequenceUnsignedShort([1, 10, 54321])); +} +{ + const v = test.getSequenceLong(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === -123456); + console.assert(v[1] === 1); + console.assert(v[2] === 123456); + console.assert(test.isSequenceLong([-123456, 1, 123456])); +} +{ + const v = test.getSequenceUnsignedLong(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === 1); + console.assert(v[1] === 10); + console.assert(v[2] === 3456789012); + console.assert(test.isSequenceUnsignedLong([1, 10, 3456789012])); +} +{ + const v = test.getSequenceHyper(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === -123456789n); + console.assert(v[1] === 1n); + console.assert(v[2] === 123456789n); + console.assert(test.isSequenceHyper([-123456789n, 1n, 123456789n])); +} +{ + const v = test.getSequenceUnsignedHyper(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === 1n); + console.assert(v[1] === 10n); + console.assert(v[2] === 9876543210n); + console.assert(test.isSequenceUnsignedHyper([1n, 10n, 9876543210n])); +} +{ + const v = test.getSequenceFloat(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === -10.25); + console.assert(v[1] === 1.5); + console.assert(v[2] === 10.75); + console.assert(test.isSequenceFloat([-10.25, 1.5, 10.75])); +} +{ + const v = test.getSequenceDouble(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === -100.5); + console.assert(v[1] === 1.25); + console.assert(v[2] === 100.75); + console.assert(test.isSequenceDouble([-100.5, 1.25, 100.75])); +} +{ + const v = test.getSequenceChar(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === 'a'); + console.assert(v[1] === 'B'); + console.assert(v[2] === 'Ö'); + console.assert(test.isSequenceChar(['a', 'B', 'Ö'])); +} +{ + const v = test.getSequenceString(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === 'foo'); + console.assert(v[1] === 'barr'); + console.assert(v[2] === 'bazzz'); + console.assert(test.isSequenceString(['foo', 'barr', 'bazzz'])); +} +{ + const v = test.getSequenceType(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0].toString() === 'long'); + console.assert(v[1].toString() === 'void'); + console.assert(v[2].toString() === '[]org.libreoffice.embindtest.Enum'); + console.assert(test.isSequenceType([ + uno.type.long, uno.type.void, + uno.type.sequence(uno.type.enum(uno.idl.org.libreoffice.embindtest.Enum))])); +} +{ + let v = test.getSequenceAny(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === -123456); + console.assert(v[1] === undefined); + console.assert(v[2].length === 3); + console.assert(v[2][0] === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v[2][1] === uno.idl.org.libreoffice.embindtest.Enum.E3); + console.assert(v[2][2] === uno.idl.org.libreoffice.embindtest.Enum.E_10); + console.assert(test.isSequenceAny([ + -123456, undefined, + new uno.Any( + uno.type.sequence(uno.type.enum(uno.idl.org.libreoffice.embindtest.Enum)), + [uno.idl.org.libreoffice.embindtest.Enum.E_2, + uno.idl.org.libreoffice.embindtest.Enum.E3, + uno.idl.org.libreoffice.embindtest.Enum.E_10])])); +} +{ + const v = test.getSequenceSequenceString(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0].length === 0); + console.assert(v[1].length === 2); + console.assert(v[1][0] === 'foo'); + console.assert(v[1][1] === 'barr'); + console.assert(v[2].length === 1); + console.assert(v[2][0] === 'baz'); + console.assert(test.isSequenceSequenceString([[], ['foo', 'barr'], ['baz']])); +} +{ + const v = test.getSequenceEnum(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0] === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v[1] === uno.idl.org.libreoffice.embindtest.Enum.E3); + console.assert(v[2] === uno.idl.org.libreoffice.embindtest.Enum.E_10); + console.assert(test.isSequenceEnum([ + uno.idl.org.libreoffice.embindtest.Enum.E_2, uno.idl.org.libreoffice.embindtest.Enum.E3, + uno.idl.org.libreoffice.embindtest.Enum.E_10])); +} + +{ + const v = test.getSequenceStruct(); + console.log(v); + console.assert(v.length === 3); + console.assert(v[0].m1 === true); + console.assert(v[0].m2 === -12); + console.assert(v[0].m3 === -1234); + console.assert(v[0].m4 === 1); + console.assert(v[0].m5 === -123456); + console.assert(v[0].m6 === 1); + console.assert(v[0].m7 === -123456789n); + console.assert(v[0].m8 === 1n); + console.assert(v[0].m9 === -10.25); + console.assert(v[0].m10 === -100.5); + console.assert(v[0].m11 === 'a'); + console.assert(v[0].m12 === 'hä'); + console.assert(v[0].m13.toString() === 'long'); + console.assert(v[0].m14 === -123456); + console.assert(v[0].m15.length === 0); + console.assert(v[0].m16 === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v[0].m17.m === -123456); + console.assert(v[0].m18.m1.m === 'foo'); + console.assert(v[0].m18.m2 === -123456); + console.assert(v[0].m18.m3 === -123456); + console.assert(v[0].m18.m4.m === 'barr'); + console.assert(uno.sameUnoObject(v[0].m19, test)); + console.assert(v[1].m1 === true); + console.assert(v[1].m2 === 1); + console.assert(v[1].m3 === 1); + console.assert(v[1].m4 === 10); + console.assert(v[1].m5 === 1); + console.assert(v[1].m6 === 10); + console.assert(v[1].m7 === 1n); + console.assert(v[1].m8 === 10n); + console.assert(v[1].m9 === 1.5); + console.assert(v[1].m10 === 1.25); + console.assert(v[1].m11 === 'B'); + console.assert(v[1].m12 === 'barr'); + console.assert(v[1].m13.toString() === 'void'); + console.assert(v[1].m14 === undefined); + console.assert(v[1].m15.length === 2); + console.assert(v[1].m15[0] === 'foo'); + console.assert(v[1].m15[1] === 'barr'); + console.assert(v[1].m16 === uno.idl.org.libreoffice.embindtest.Enum.E3); + console.assert(v[1].m17.m === 1); + console.assert(v[1].m18.m1.m === 'baz'); + console.assert(v[1].m18.m2 === 1); + console.assert(v[1].m18.m3 === undefined); + console.assert(v[1].m18.m4.m === 'foo'); + console.assert(v[1].m19 === null); + console.assert(v[2].m1 === false); + console.assert(v[2].m2 === 12); + console.assert(v[2].m3 === 1234); + console.assert(v[2].m4 === 54321); + console.assert(v[2].m5 === 123456); + console.assert(v[2].m6 === 3456789012); + console.assert(v[2].m7 === 123456789n); + console.assert(v[2].m8 === 9876543210n); + console.assert(v[2].m9 === 10.75); + console.assert(v[2].m10 === 100.75); + console.assert(v[2].m11 === 'Ö'); + console.assert(v[2].m12 === 'bazzz'); + console.assert(v[2].m13.toString() === '[]org.libreoffice.embindtest.Enum'); + console.assert(v[2].m14.length === 3); + console.assert(v[2].m14[0] === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v[2].m14[1] === uno.idl.org.libreoffice.embindtest.Enum.E3); + console.assert(v[2].m14[2] === uno.idl.org.libreoffice.embindtest.Enum.E_10); + console.assert(v[2].m15.length === 1); + console.assert(v[2].m15[0] === 'baz'); + console.assert(v[2].m16 === uno.idl.org.libreoffice.embindtest.Enum.E_10); + console.assert(v[2].m17.m === 123456); + console.assert(v[2].m18.m1.m === 'barr'); + console.assert(v[2].m18.m2 === 123456); + console.assert(v[2].m18.m3.length === 3); + console.assert(v[2].m18.m3[0] === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v[2].m18.m3[1] === uno.idl.org.libreoffice.embindtest.Enum.E3); + console.assert(v[2].m18.m3[2] === uno.idl.org.libreoffice.embindtest.Enum.E_10); + console.assert(v[2].m18.m4.m === 'bazz'); + console.assert(uno.sameUnoObject(v[2].m19, test)); + console.assert(test.isSequenceStruct([ + {m1: true, m2: -12, m3: -1234, m4: 1, m5: -123456, m6: 1, m7: -123456789n, m8: 1n, + m9: -10.25, m10: -100.5, m11: 'a', m12: 'hä', m13: uno.type.long, m14: -123456, m15: [], + m16: uno.idl.org.libreoffice.embindtest.Enum.E_2, m17: {m: -123456}, + m18: {m1: {m: 'foo'}, m2: -123456, m3: -123456, m4: {m: 'barr'}}, m19: test}, + {m1: true, m2: 1, m3: 1, m4: 10, m5: 1, m6: 10, m7: 1n, m8: 10n, m9: 1.5, m10: 1.25, + m11: 'B', m12: 'barr', m13: uno.type.void, m14: undefined, m15: ['foo', 'barr'], + m16: uno.idl.org.libreoffice.embindtest.Enum.E3, m17: {m: 1}, + m18: {m1: {m: 'baz'}, m2: 1, m3: undefined, m4: {m: 'foo'}}, m19: null}, + {m1: false, m2: 12, m3: 1234, m4: 54321, m5: 123456, m6: 3456789012, m7: 123456789n, + m8: 9876543210n, m9: 10.75, m10: 100.75, m11: 'Ö', m12: 'bazzz', + m13: uno.type.sequence(uno.type.enum(uno.idl.org.libreoffice.embindtest.Enum)), + m14: new uno.Any( + uno.type.sequence(uno.type.enum(uno.idl.org.libreoffice.embindtest.Enum)), + [uno.idl.org.libreoffice.embindtest.Enum.E_2, uno.idl.org.libreoffice.embindtest.Enum.E3, + uno.idl.org.libreoffice.embindtest.Enum.E_10]), + m15: ['baz'], m16: uno.idl.org.libreoffice.embindtest.Enum.E_10, m17: {m: 123456}, + m18: {m1: {m: 'barr'}, m2: 123456, + m3: new uno.Any( + uno.type.sequence(uno.type.enum(uno.idl.org.libreoffice.embindtest.Enum)), + [uno.idl.org.libreoffice.embindtest.Enum.E_2, uno.idl.org.libreoffice.embindtest.Enum.E3, + uno.idl.org.libreoffice.embindtest.Enum.E_10]), + m4: {m: 'bazz'}}, + m19: test}])); +} +{ + const v = test.getNull(); + console.log(v); + console.assert(v === null); + console.assert(test.isNull(null)); +} +{ + const v1 = {}; + const v2 = {}; + const v3 = {}; + const v4 = {}; + const v5 = {}; + const v6 = {}; + const v7 = {}; + const v8 = {}; + const v9 = {}; + const v10 = {}; + const v11 = {}; + const v12 = {}; + const v13 = {}; + const v14 = {}; + const v15 = {}; + const v16 = {}; + const v17 = {}; + const v18 = {}; + test.getOut( + v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18); + console.assert(v1.val === true); + console.assert(v2.val === -12); + console.assert(v3.val === -1234); + console.assert(v4.val === 54321); + console.assert(v5.val === -123456); + console.assert(v6.val === 3456789012); + console.assert(v7.val === -123456789n); + console.assert(v8.val === 9876543210n); + console.assert(v9.val === -10.25); + console.assert(v10.val === 100.5); + console.assert(v11.val === 'Ö'); + console.assert(v12.val === 'hä'); + console.assert(v13.val.toString() === 'long'); + console.assert(v14.val === -123456) + console.assert(v15.val.length === 3); + console.assert(v15.val[0] === 'foo'); + console.assert(v15.val[1] === 'barr'); + console.assert(v15.val[2] === 'bazzz'); + console.assert(v16.val === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v17.val.m1 === true); + console.assert(v17.val.m2 === -12); + console.assert(v17.val.m3 === -1234); + console.assert(v17.val.m4 === 54321); + console.assert(v17.val.m5 === -123456); + console.assert(v17.val.m6 === 3456789012); + console.assert(v17.val.m7 === -123456789n); + console.assert(v17.val.m8 === 9876543210n); + console.assert(v17.val.m9 === -10.25); + console.assert(v17.val.m10 === 100.5); + console.assert(v17.val.m11 === 'Ö'); + console.assert(v17.val.m12 === 'hä'); + console.assert(v17.val.m13.toString() === 'long'); + console.assert(v17.val.m14 === -123456); + console.assert(v17.val.m15.length === 3); + console.assert(v17.val.m15[0] === 'foo'); + console.assert(v17.val.m15[1] === 'barr'); + console.assert(v17.val.m15[2] === 'bazzz'); + console.assert(v17.val.m16 === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v17.val.m17.m === -123456); + console.assert(v17.val.m18.m1.m === 'foo'); + console.assert(v17.val.m18.m2 === -123456); + console.assert(v17.val.m18.m3 === -123456); + console.assert(v17.val.m18.m4.m === 'barr'); + console.assert(uno.sameUnoObject(v17.val.m19, test)); + console.assert(uno.sameUnoObject(v18.val, test)); +} + +try { + test.throwRuntimeException(); + console.assert(false); +} catch (e) { + console.assert(e instanceof uno.idl.com.sun.star.uno.RuntimeException); + console.assert(e.Message.startsWith('test')); +} +try { + throw new uno.idl.com.sun.star.lang.WrappedTargetException( + {Message: 'wrapped', Context: test, + TargetException: new uno.idl.com.sun.star.uno.RuntimeException({ + Message: 'test', Context: test})}); + console.assert(false); +} catch (e) { + console.assert(e instanceof uno.idl.com.sun.star.lang.WrappedTargetException); + console.assert(e.Message.startsWith('wrapped')); + console.assert(uno.sameUnoObject(e.Context, test)); + console.assert(e.TargetException instanceof uno.idl.com.sun.star.uno.RuntimeException); + console.assert(e.TargetException.Message.startsWith('test')); + console.assert(uno.sameUnoObject(e.TargetException.Context, test)); +} +console.assert(test.StringAttribute === 'hä'); +test.StringAttribute = 'foo'; +console.assert(test.StringAttribute === 'foo'); +{ + const s = uno.idl.org.libreoffice.embindtest.theSingleton(uno.componentContext); + const v = s.getString(); + console.assert(v === 'this is a string from XStringFactory'); +} +{ + const s = uno.idl.org.libreoffice.embindtest.ImplicitConstructor.create(uno.componentContext); + const v = s.getArguments(); + console.assert(v.length === 0); +} +{ + const s = uno.idl.org.libreoffice.embindtest.ExplicitConstructors.multipleArguments( + uno.componentContext, -123456, 'hä', -10.25); + const v = s.getArguments(); + console.assert(v.length === 3); + console.assert(v[0] === -123456); + console.assert(v[1] === 'hä'); + console.assert(v[2] === -10.25); +} +{ + const s = uno.idl.org.libreoffice.embindtest.ExplicitConstructors.interfaceArgument( + uno.componentContext, test); + const v = s.getArguments(); + console.assert(v.length === 1); + console.assert(uno.sameUnoObject(v[0], test)); +} + +{ + const s = uno.idl.org.libreoffice.embindtest.ExplicitConstructors.restArgument( + uno.componentContext, -123456, undefined, + new uno.Any( + uno.type.sequence(uno.type.enum(uno.idl.org.libreoffice.embindtest.Enum)), + [uno.idl.org.libreoffice.embindtest.Enum.E_2, + uno.idl.org.libreoffice.embindtest.Enum.E3, + uno.idl.org.libreoffice.embindtest.Enum.E_10]));; + const v = s.getArguments(); + console.assert(v.length === 3); + console.assert(v[0] === -123456); + console.assert(v[1] === undefined); + console.assert(v[2].length === 3); + console.assert(v[2][0] === uno.idl.org.libreoffice.embindtest.Enum.E_2); + console.assert(v[2][1] === uno.idl.org.libreoffice.embindtest.Enum.E3); + console.assert(v[2][2] === uno.idl.org.libreoffice.embindtest.Enum.E_10); +} diff --git a/jsuno/qa/extras/testmissingparams.js b/jsuno/qa/extras/testmissingparams.js new file mode 100644 index 000000000000..989274c141d5 --- /dev/null +++ b/jsuno/qa/extras/testmissingparams.js @@ -0,0 +1,28 @@ +/* + * 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/. + */ + +assertError(function() { console.assert() }, + "Error: missing argument to console.assert"); +assertError(function() { uno.type.sequence() }, + "Error: missing argument to uno.type.sequence"); +assertError(function() { uno.type.enum() }, + "Error: missing argument to uno.type.enum"); +assertError(function() { uno.type.struct() }, + "Error: missing argument to uno.type.struct"); +assertError(function() { uno.type.exception() }, + "Error: missing argument to uno.type.exception"); +assertError(function() { uno.type.interface() }, + "Error: missing argument to uno.type.interface"); +assertError(function() { uno.idl.org.libreoffice.embindtest.theSingleton() }, + "Error: missing argument to getSingleton"); +assertError(function() { new uno.Any() }, + "Error: missing argument to uno.Any constructor"); +assertError(function() { uno.sameUnoObject() }, + "Error: missing argument to uno.sameUnoObject"); +assertError(function() { uno.sameUnoObject(1) }, + "Error: missing argument to uno.sameUnoObject"); diff --git a/jsuno/qa/extras/testrhinocompatibility.js b/jsuno/qa/extras/testrhinocompatibility.js new file mode 100644 index 000000000000..45eb717b3539 --- /dev/null +++ b/jsuno/qa/extras/testrhinocompatibility.js @@ -0,0 +1,33 @@ +/* + * 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/. + */ + +// Check that we can access UNO entities with the Packages alias +console.assert(Packages.org.libreoffice.embindtest.Constants.Short === -1234); + +assertError(function() { importClass() }, + "TypeError: cannot read property 'getImportClassName' of undefined"); + +console.assert(Packages.org.libreoffice.embindtest.XTest.getImportClassName() == "XTest"); +console.assert(Packages.org.libreoffice.embindtest.Enum.getImportClassName() == "Enum"); +console.assert(Packages.org.getImportClassName() == "org"); +console.assert(Packages.org.libreoffice.embindtest.getImportClassName() == "embindtest"); + +importClass(Packages.org.libreoffice.embindtest.XTest); +console.assert(XTest == Packages.org.libreoffice.embindtest.XTest); +importClass(Packages.org.libreoffice.embindtest.Enum); +console.assert(Enum == Packages.org.libreoffice.embindtest.Enum); +importClass(Packages.org.libreoffice.embindtest); +console.assert(embindtest == Packages.org.libreoffice.embindtest); + +importClass(Packages.com.sun.star.uno.UnoRuntime); + +let test = uno.idl.org.libreoffice.embindtest.Test.create(uno.componentContext); +let xTest = UnoRuntime.queryInterface(XTest, test); +console.assert(uno.sameUnoObject(xTest, test)); + +console.assert(UnoRuntime.queryInterface(XTest, uno.componentContext) === undefined); diff --git a/jsuno/qa/unit/execute.cxx b/jsuno/qa/unit/execute.cxx new file mode 100644 index 000000000000..35cfe2560fd4 --- /dev/null +++ b/jsuno/qa/unit/execute.cxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Contributor(s): + * Copyright the Collabora Office contributors. + */ + +#include + +#include +#include +#include + +#include +#include +#include + +namespace +{ +class Execute : public CppUnit::TestFixture +{ +public: + void testReturnValue() + { + CPPUNIT_ASSERT_EQUAL(u"42"_ustr, jsuno::execute(u"42"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"true"_ustr, jsuno::execute(u"true"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"\"hello\""_ustr, jsuno::execute(u"'hello'"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"null"_ustr, jsuno::execute(u"null"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"[1,2,3]"_ustr, jsuno::execute(u"[1, 2, 3]"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"{\"a\":1,\"b\":\"two\"}"_ustr, + jsuno::execute(u"({a: 1, b: 'two'})"_ustr)); + CPPUNIT_ASSERT_EQUAL(u""_ustr, jsuno::execute(u"undefined"_ustr)); + CPPUNIT_ASSERT_EQUAL(u""_ustr, jsuno::execute(u"(function () {})"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"42"_ustr, + jsuno::execute(u"(function () { return 42; }).apply(null, [])"_ustr)); + try + { + jsuno::execute(u"1n"_ustr); + CPPUNIT_FAIL("expected ScriptExceptionRaisedException"); + } + catch (css::script::provider::ScriptExceptionRaisedException const& e) + { + CPPUNIT_ASSERT_EQUAL(u"TypeError"_ustr, e.exceptionType); + } + } + + void testThrows() + { + try + { + jsuno::execute(u"throw new Error('boom')"_ustr); + CPPUNIT_FAIL("expected ScriptExceptionRaisedException"); + } + catch (css::script::provider::ScriptExceptionRaisedException const& e) + { + CPPUNIT_ASSERT(e.Message.startsWith("boom")); + CPPUNIT_ASSERT_EQUAL(u""_ustr, e.scriptName); + CPPUNIT_ASSERT_EQUAL(u"JavaScript"_ustr, e.language); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), e.lineNum); + CPPUNIT_ASSERT_EQUAL(u"Error"_ustr, e.exceptionType); + } + try + { + jsuno::execute(u"throw new TypeError('bad type')"_ustr); + CPPUNIT_FAIL("expected ScriptExceptionRaisedException"); + } + catch (css::script::provider::ScriptExceptionRaisedException const& e) + { + CPPUNIT_ASSERT(e.Message.startsWith("bad type")); + CPPUNIT_ASSERT_EQUAL(u"TypeError"_ustr, e.exceptionType); + } + try + { + jsuno::execute(u"@@@ not valid JS"_ustr); + CPPUNIT_FAIL("expected ScriptExceptionRaisedException"); + } + catch (css::script::provider::ScriptExceptionRaisedException const& e) + { + CPPUNIT_ASSERT_EQUAL(u"SyntaxError"_ustr, e.exceptionType); + } + try + { + jsuno::execute(u"throw 'plain string'"_ustr); + CPPUNIT_FAIL("expected ScriptExceptionRaisedException"); + } + catch (css::script::provider::ScriptExceptionRaisedException const& e) + { + CPPUNIT_ASSERT(e.Message.startsWith("plain string")); + CPPUNIT_ASSERT_EQUAL(u""_ustr, e.exceptionType); + } + } + + CPPUNIT_TEST_SUITE(Execute); + CPPUNIT_TEST(testReturnValue); + CPPUNIT_TEST(testThrows); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(Execute); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/jsuno/qa/unit/testuno.cxx b/jsuno/qa/unit/testuno.cxx new file mode 100644 index 000000000000..44b844a97f90 --- /dev/null +++ b/jsuno/qa/unit/testuno.cxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include + +#include +#include + +namespace +{ +class TestUno : public CppUnit::TestFixture +{ + void appendFileContents(std::u16string_view sFilename, std::string& sOutput); + void executeScript(std::u16string_view sScriptName); + +public: + void test() { executeScript(u"test.js"); } + void testMissingParams() { executeScript(u"testmissingparams.js"); } + void testRhinoCompatibility() { executeScript(u"testrhinocompatibility.js"); } + + CPPUNIT_TEST_SUITE(TestUno); + CPPUNIT_TEST(test); + CPPUNIT_TEST(testMissingParams); + CPPUNIT_TEST(testRhinoCompatibility); + CPPUNIT_TEST_SUITE_END(); +}; + +void TestUno::appendFileContents(std::u16string_view sFilename, std::string& sOutput) +{ + OUString sSrcPath = o3tl::getEnvironment(u"SRC_ROOT"_ustr); + CPPUNIT_ASSERT_MESSAGE("SRC_ROOT env variable not set", !sSrcPath.isEmpty()); + + // Remove any trailing slash + sSrcPath.endsWith('/', &sSrcPath); + + OUString sPath = sSrcPath + "/jsuno/qa/extras/" + sFilename; + OString sPathUtf8 = OUStringToOString(sPath, RTL_TEXTENCODING_UTF8); + + try + { + std::ifstream ifs(sPathUtf8.getStr()); + ifs.exceptions(std::ifstream::failbit); + sOutput.append((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); + } + catch (const std::ios_base::failure& rFail) + { + std::cerr << sPathUtf8 << ": " << rFail.what() << std::endl; + CPPUNIT_FAIL("error loading test script"); + } +} + +void TestUno::executeScript(std::u16string_view sScriptName) +{ + std::string sSourceUtf8; + + appendFileContents(u"common.js", sSourceUtf8); + appendFileContents(sScriptName, sSourceUtf8); + + OUString sSource = OStringToOUString(sSourceUtf8, RTL_TEXTENCODING_UTF8); + jsuno::execute(sSource); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestUno); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/jsuno/source/jsuno.cxx b/jsuno/source/jsuno.cxx new file mode 100644 index 000000000000..633140e3d28b --- /dev/null +++ b/jsuno/source/jsuno.cxx @@ -0,0 +1,2883 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jsvalue.hxx" +#include "rhinocompatibility.hxx" + +namespace +{ +using jsuno::ValueRef; + +struct JsException +{ +}; + +class AtomRef +{ +public: + AtomRef(JSRuntime* rt) + : rt_(rt) + , atom_(JS_ATOM_NULL) + { + } + + AtomRef(JSContext* ctx, JSAtom atom) + : rt_(JS_GetRuntime(ctx)) + , atom_(atom) + { + } + + ~AtomRef() { JS_FreeAtomRT(rt_, atom_); } + + AtomRef& operator=(JSAtom atom) + { + std::swap(atom_, atom); + JS_FreeAtomRT(rt_, atom); + return *this; + } + + operator JSAtom() const { return atom_; } + +private: + AtomRef(AtomRef const&) = delete; + AtomRef(AtomRef&&) = delete; + void operator=(AtomRef const&) = delete; + void operator=(AtomRef&&) = delete; + + JSRuntime* rt_; + JSAtom atom_; +}; + +class UniqueCString8 +{ +public: + UniqueCString8(JSContext* ctx, char const* ptr) + : ctx_(ctx) + , ptr_(ptr) + { + } + + ~UniqueCString8() { JS_FreeCString(ctx_, ptr_); } + + char const* get() const { return ptr_; } + +private: + UniqueCString8(UniqueCString8 const&) = delete; + UniqueCString8(UniqueCString8&&) = delete; + void operator=(UniqueCString8 const&) = delete; + void operator=(UniqueCString8&&) = delete; + + JSContext* ctx_; + char const* ptr_; +}; + +class UniqueCString16 +{ +public: + UniqueCString16(JSContext* ctx, std::uint16_t const* ptr) + : ctx_(ctx) + , ptr_(ptr) + { + } + + ~UniqueCString16() { JS_FreeCStringUTF16(ctx_, ptr_); } + + char16_t const* get() const { return reinterpret_cast(ptr_); } + +private: + UniqueCString16(UniqueCString16 const&) = delete; + UniqueCString16(UniqueCString16&&) = delete; + void operator=(UniqueCString16 const&) = delete; + void operator=(UniqueCString16&&) = delete; + + JSContext* ctx_; + std::uint16_t const* ptr_; +}; + +ValueRef createDefaultValue(JSContext* ctx, css::uno::Type const& type); +css::uno::Any fromJs(JSContext* ctx, css::uno::Type const& type, JSValueConst val); +JSValue invokeUno(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic, + JSValueConst* func_data); +ValueRef mapTypeToJs(JSContext* ctx, css::uno::Type const& type); +ValueRef toJs(JSContext* ctx, css::uno::Any const& value); + +#if defined DBG_UTIL +class Counter +{ +public: + ~Counter() { assert(count_ == 0); } + + void inc() + { + assert(count_ != std::numeric_limits::max()); + ++count_; + } + + void dec() + { + assert(count_ != 0); + --count_; + } + +private: + std::uintptr_t count_ = 0; +}; +#endif + +struct RuntimeData +{ + RuntimeData(JSRuntime* rt) + : symbolIteratorAtom(rt) + { + } + + void clear() { symbolIteratorAtom = JS_ATOM_NULL; } + + JSClassID pointerClassId = 0; + JSClassID wrapperClassId = 0; + JSClassID enumeratorClassId = 0; + JSClassID compoundClassId = 0; + JSClassID typeClassId = 0; + JSClassID enumClassId = 0; + JSClassID structClassId = 0; + JSClassID exceptionClassId = 0; + JSClassID interfaceClassId = 0; + JSClassID ctorClassId = 0; + JSClassID singletonClassId = 0; + JSClassID moduleClassId = 0; + + AtomRef symbolIteratorAtom; + +#if defined DBG_UTIL + Counter toFinalize; +#endif +}; + +RuntimeData* getRuntimeData(JSRuntime* rt) +{ + return static_cast(JS_GetRuntimeOpaque(rt)); +} + +RuntimeData* getRuntimeData(JSContext* ctx) { return getRuntimeData(JS_GetRuntime(ctx)); } + +struct WrapperData +{ + WrapperData(JSContext* ctx, const css::uno::Reference& obj) + : methodCache(ctx) + , interface(obj) + { + } + + // A lazily-created object used as a hash table for caching methods + ValueRef methodCache; + css::uno::Reference interface; +}; + +struct ModuleData +{ + ModuleData(JSContext* ctx, const OUString& rName) + : memberCache(ctx) + , name(rName) + { + } + + // A lazily-created object used as a hash table for caching members of the module + ValueRef memberCache; + // The fully qualified name of the module + OUString name; +}; + +template JSValue callFromJs(JSContext* ctx, F&& f) +{ + try + { + return f(); + } + catch (JsException) + { + return JS_EXCEPTION; + } + catch (css::uno::Exception) + { + auto const e = cppu::getCaughtException(); + ValueRef val = toJs(ctx, e); + return JS_Throw(ctx, val.release()); + } + catch (std::exception& e) + { + return JS_ThrowPlainError(ctx, "std exception: %s", e.what()); + } +} + +// A stripped-down and modified version of (which only +// takes a single argument and aborts when the assertion is not met), just enough for using it in +// jsunit/qa/unit/testuno.cxx: +JSValue consoleAssert(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, argc, argv] { + if (argc < 1) + return JS_ThrowPlainError(ctx, "missing argument to console.assert"); + auto const ok = JS_ToBool(ctx, argv[0]); + if (ok == -1) + { + throw JsException(); + } + if (ok == 0) + { + ValueRef const errorCtor(ctx, JS_GetPropertyStr(ctx, JS_GetGlobalObject(ctx), "Error")); + assert(!JS_IsException(errorCtor)); + ValueRef const err(ctx, JS_CallConstructor(ctx, errorCtor, 0, nullptr)); + assert(!JS_IsException(err)); + ValueRef const stack(ctx, JS_GetPropertyStr(ctx, err, "stack")); + assert(!JS_IsException(stack)); + UniqueCString8 const s(ctx, JS_ToCString(ctx, stack)); + assert(s.get() != nullptr); + std::cerr << "console.assert at: " << s.get() << "\n"; + std::abort(); + } + return JS_UNDEFINED; + }); +} + +// A stripped-down version of (which simply prints all its +// arguments, not using the logic): +JSValue consoleLog(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, argc, argv] { + OUStringBuffer buf("console.log:"); + for (int i = 0; i != argc; ++i) + { + std::size_t n; + UniqueCString16 const s(ctx, JS_ToCStringLenUTF16(ctx, &n, argv[i])); + if (s.get() == nullptr) + { + throw JsException(); + } + buf.append(OUString::Concat(" ") + std::u16string_view(s.get(), n)); + } + buf.append('\n'); + std::cout << buf.makeStringAndClear() << std::flush; + return JS_UNDEFINED; + }); +} + +rtl_uString* stringAcquire(OUString const& id) +{ + rtl_uString_acquire(id.pData); + return id.pData; +} + +void pointerFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + delete static_cast( + JS_GetOpaque(val, getRuntimeData(rt)->pointerClassId)); +} + +JSValue enumerationIteratorNext(JSContext* ctx, JSValueConst, int, JSValueConst*, int, + JSValueConst* func_data) +{ + return callFromJs(ctx, [ctx, func_data] { + WrapperData* wrapperData = static_cast( + JS_GetOpaque2(ctx, func_data[0], getRuntimeData(ctx)->wrapperClassId)); + if (wrapperData == nullptr) + return JS_EXCEPTION; + + css::uno::Reference en(wrapperData->interface, + css::uno::UNO_QUERY_THROW); + ValueRef val(ctx, JS_NewObject(ctx)); + if (en->hasMoreElements()) + { + JS_SetPropertyStr(ctx, val, "value", toJs(ctx, en->nextElement()).release()); + JS_SetPropertyStr(ctx, val, "done", JS_FALSE); + } + else + { + JS_SetPropertyStr(ctx, val, "value", JS_UNDEFINED); + JS_SetPropertyStr(ctx, val, "done", JS_TRUE); + } + return val.release(); + }); +} + +JSValue enumerationIterator(JSContext* ctx, JSValueConst this_val, int, JSValueConst*) +{ + return callFromJs(ctx, [ctx, this_val] { + ValueRef iter(ctx, JS_NewObject(ctx)); + JS_SetPropertyStr(ctx, iter, "next", + JS_NewCFunctionData(ctx, enumerationIteratorNext, 0, 0, 1, + const_cast(&this_val))); + return iter.release(); + }); +} + +int cacheAndReturnWrapperMethod(JSContext* ctx, WrapperData* wrapperData, + JSPropertyDescriptor* desc, JSAtom atom, ValueRef val) +{ + if (JS_IsUninitialized(wrapperData->methodCache)) + { + wrapperData->methodCache = JS_NewObject(ctx); + if (JS_IsException(wrapperData->methodCache)) + return -1; + } + if (JS_SetProperty(ctx, wrapperData->methodCache, atom, val.dup()) == -1) + return -1; + + if (desc) + { + desc->flags = 0; + desc->value = val.release(); + desc->getter = JS_UNDEFINED; + desc->setter = JS_UNDEFINED; + } + return int(true); +} + +int wrapperGetOwnProperty(JSContext* ctx, JSPropertyDescriptor* desc, JSValueConst obj, JSAtom atom) +{ + try + { + WrapperData* wrapperData = static_cast( + JS_GetOpaque2(ctx, obj, getRuntimeData(ctx)->wrapperClassId)); + if (wrapperData == nullptr) + return -1; + + // Check if we already have a cached value for this atom + if (!JS_IsUninitialized(wrapperData->methodCache)) + { + ValueRef cachedValue(ctx, JS_GetProperty(ctx, wrapperData->methodCache, atom)); + if (!JS_IsUndefined(cachedValue)) + { + if (desc) + { + desc->flags = 0; + desc->value = cachedValue.release(); + desc->getter = JS_UNDEFINED; + desc->setter = JS_UNDEFINED; + } + return int(true); + } + } + + if (atom == getRuntimeData(ctx)->symbolIteratorAtom) + { + css::uno::Reference en(wrapperData->interface, + css::uno::UNO_QUERY); + if (!en.is()) + { + return int(false); + } + ValueRef val(ctx, JS_NewCFunction(ctx, enumerationIterator, "[Symbol.iterator]", 0)); + return cacheAndReturnWrapperMethod(ctx, wrapperData, desc, atom, std::move(val)); + } + + css::uno::Reference invoke( + css::script::Invocation::create(comphelper::getProcessComponentContext()) + ->createInstanceWithArguments({ css::uno::Any(wrapperData->interface) }), + css::uno::UNO_QUERY_THROW); + css::script::InvocationInfo info; + try + { + info = invoke->getInfoForName(OUString::fromUtf8(JS_AtomToCString(ctx, atom)), false); + } + catch (css::lang::IllegalArgumentException) + { + return int(false); + } + switch (info.eMemberType) + { + case css::script::MemberType_METHOD: + { + ValueRef data(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->pointerClassId)); + [[maybe_unused]] auto const e + = JS_SetOpaque(data, new css::script::InvocationInfo(info)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + ValueRef val(ctx, JS_NewCFunctionData(ctx, invokeUno, info.aParamTypes.getLength(), + 0, 1, data.ptr())); + + return cacheAndReturnWrapperMethod(ctx, wrapperData, desc, atom, std::move(val)); + } + case css::script::MemberType_PROPERTY: + if (desc) + { + desc->flags = 0; + desc->value = toJs(ctx, invoke->getValue(info.aName)).release(); + desc->getter = JS_UNDEFINED; + desc->setter = JS_UNDEFINED; + } + return int(true); + default: + O3TL_UNREACHABLE; + } + } + catch (JsException) + { + return -1; + } + catch (css::uno::Exception) + { + auto const e = cppu::getCaughtException(); + ValueRef val = toJs(ctx, e); + JS_Throw(ctx, val.release()); + return -1; + } +} + +int wrapperSetProperty(JSContext* ctx, JSValueConst obj, JSAtom atom, JSValueConst value, + JSValueConst, int flags) +{ + try + { + ValueRef const v(ctx, JS_AtomToString(ctx, atom)); + if (JS_IsString(v)) + { + WrapperData* wrapperData = static_cast( + JS_GetOpaque2(ctx, obj, getRuntimeData(ctx)->wrapperClassId)); + if (wrapperData == nullptr) + return -1; + + css::uno::Reference invoke( + css::script::Invocation::create(comphelper::getProcessComponentContext()) + ->createInstanceWithArguments({ css::uno::Any(wrapperData->interface) }), + css::uno::UNO_QUERY_THROW); + css::script::InvocationInfo info; + auto prop = false; + try + { + info = invoke->getInfoForName(OUString::fromUtf8(JS_AtomToCString(ctx, atom)), + false); + prop = info.eMemberType == css::script::MemberType_PROPERTY; + } + catch (css::lang::IllegalArgumentException) + { + } + if (prop) + { + invoke->setValue(info.aName, fromJs(ctx, info.aType, value)); + return 1; + } + } + return JS_DefinePropertyValue(ctx, obj, atom, JS_DupValue(ctx, value), + JS_PROP_C_W_E | (flags & JS_PROP_THROW)); + } + catch (JsException) + { + return -1; + } + catch (css::uno::Exception) + { + auto const e = cppu::getCaughtException(); + ValueRef val(ctx, toJs(ctx, e).release()); + JS_Throw(ctx, val.release()); + return -1; + } + catch (std::exception& e) + { + JS_ThrowPlainError(ctx, "std exception: %s", e.what()); + return -1; + } +} + +void wrapperGCMark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* markFunc) +{ + WrapperData* wrapperData + = static_cast(JS_GetOpaque(val, getRuntimeData(rt)->wrapperClassId)); + if (wrapperData != nullptr) + JS_MarkValue(rt, wrapperData->methodCache, markFunc); +} + +void wrapperFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + WrapperData* wrapperData + = static_cast(JS_GetOpaque(val, getRuntimeData(rt)->wrapperClassId)); + assert(wrapperData); + delete wrapperData; +} + +JSValue wrapperToString(JSContext* ctx, JSValueConst this_val, int, JSValueConst*) +{ + return callFromJs(ctx, [ctx, this_val] { + WrapperData* wrapperData = static_cast( + JS_GetOpaque2(ctx, this_val, getRuntimeData(ctx)->wrapperClassId)); + if (wrapperData == nullptr) + return JS_EXCEPTION; + + std::ostringstream s; + s << wrapperData->interface; + return JS_NewString(ctx, s.str().c_str()); + }); +} + +JSValue wrapUnoObject(JSContext* ctx, css::uno::Reference const& obj) +{ + if (!obj.is()) + { + return JS_NULL; + } + auto const val = JS_NewObjectClass(ctx, getRuntimeData(ctx)->wrapperClassId); + [[maybe_unused]] auto const e = JS_SetOpaque(val, new WrapperData(ctx, obj)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + return val; +} + +JSValue importClassNameFromFullName(JSContext* ctx, std::u16string_view fullName) +{ + std::size_t lastDot = fullName.find_last_of(u'.'); + std::u16string_view shortName + = lastDot == std::u16string_view::npos ? fullName : fullName.substr(lastDot + 1); + return JS_NewStringUTF16(ctx, reinterpret_cast(shortName.data()), + shortName.length()); +} + +JSValue interfaceGetImportClassName(JSContext* ctx, JSValueConst this_val, int, JSValueConst*) +{ + typelib_TypeDescriptionReference* typeRef = static_cast( + JS_GetOpaque2(ctx, this_val, getRuntimeData(ctx)->interfaceClassId)); + if (typeRef == nullptr) + return JS_EXCEPTION; + + return importClassNameFromFullName(ctx, OUString(typeRef->pTypeName)); +} + +struct EnumeratorData +{ + css::uno::Type type; + sal_Int32 value; + OUString name; +}; + +void enumeratorFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + delete static_cast( + JS_GetOpaque(val, getRuntimeData(rt)->enumeratorClassId)); +} + +JSValue enumeratorToString(JSContext* ctx, JSValueConst this_val, int, JSValueConst*) +{ + return callFromJs(ctx, [ctx, this_val] { + auto const data = static_cast( + JS_GetOpaque(this_val, getRuntimeData(ctx)->enumeratorClassId)); + OUString const s(data->type.getTypeName() + "." + data->name); + return JS_NewStringUTF16(ctx, reinterpret_cast(s.getStr()), + s.getLength()); + }); +} + +void compoundFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + typelib_typedescriptionreference_release(static_cast( + JS_GetOpaque(val, getRuntimeData(rt)->compoundClassId))); +} + +typelib_TypeDescriptionReference* typeAcquire(css::uno::Type const& type) +{ + auto const ref = type.getTypeLibType(); + typelib_typedescriptionreference_acquire(ref); + return ref; +} + +void typeFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + typelib_typedescriptionreference_release(static_cast( + JS_GetOpaque(val, getRuntimeData(rt)->typeClassId))); +} + +JSValue typeToString(JSContext* ctx, JSValueConst this_val, int, JSValueConst*) +{ + return callFromJs(ctx, [ctx, this_val] { + auto const name + = css::uno::Type(static_cast( + JS_GetOpaque(this_val, getRuntimeData(ctx)->typeClassId))) + .getTypeName(); + return JS_NewStringUTF16(ctx, reinterpret_cast(name.getStr()), + name.getLength()); + }); +} + +void setTypeProperty(JSContext* ctx, JSValueConst obj, char const* prop, css::uno::Type const& type) +{ + ValueRef val(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->typeClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(val, typeAcquire(type)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + JS_SetPropertyStr(ctx, obj, prop, val.release()); +} + +JSValue unoTypeSequence(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, argc, argv] { + if (argc < 1) + return JS_ThrowPlainError(ctx, "missing argument to uno.type.sequence"); + if (JS_GetClassID(argv[0]) != getRuntimeData(ctx)->typeClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO TYPE VALUE"); + throw JsException(); + } + css::uno::Type const type( + css::uno::TypeClass_SEQUENCE, + "[]" + + css::uno::Type(static_cast( + JS_GetOpaque(argv[0], getRuntimeData(ctx)->typeClassId))) + .getTypeName()); + ValueRef val(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->typeClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(val, typeAcquire(type)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + return val.release(); + }); +} + +JSValue unoTypeEnum(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, argc, argv] { + if (argc < 1) + return JS_ThrowPlainError(ctx, "missing argument to uno.type.enum"); + if (JS_GetClassID(argv[0]) != getRuntimeData(ctx)->enumClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO TYPE VALUE"); + throw JsException(); + } + css::uno::Type const type(static_cast( + JS_GetOpaque(argv[0], getRuntimeData(ctx)->enumClassId))); + ValueRef val(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->typeClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(val, typeAcquire(type)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + return val.release(); + }); +} + +JSValue unoTypeStruct(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, argc, argv] { + if (argc < 1) + return JS_ThrowPlainError(ctx, "missing argument to uno.type.struct"); + ValueRef data(ctx, JS_GetPropertyStr(ctx, argv[0], "'data")); + if (JS_IsException(data)) + { + throw JsException(); + } + if (JS_GetClassID(data) != getRuntimeData(ctx)->structClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO TYPE VALUE"); + throw JsException(); + } + css::uno::Reference td(static_cast( + JS_GetOpaque(data, getRuntimeData(ctx)->structClassId))); + OUStringBuffer buf(td->getName()); + auto const params = td->getTypeParameters(); + if (params.hasElements()) + { + if (argc < 2) + { + JS_ThrowSyntaxError(ctx, "TODO: MISSING TYPE ARGUMENTS"); + throw JsException(); + } + if (!JS_IsArray(argv[1])) + { + JS_ThrowTypeError(ctx, "TODO: BAD TYPE ARGUMENTS"); + throw JsException(); + } + ValueRef len1(ctx, JS_GetPropertyStr(ctx, argv[1], "length")); + if (JS_IsException(len1)) + { + throw JsException(); + } + std::int64_t len2; + auto const e = JS_ToInt64(ctx, &len2, len1); + if (e != 0) + { + throw JsException(); + } + if (len2 != params.getLength()) + { + JS_ThrowTypeError(ctx, "TODO: BAD TYPE ARGUMENTS"); + throw JsException(); + } + buf.append('<'); + for (sal_Int32 i = 0; i != params.getLength(); ++i) + { + if (i != 0) + { + buf.append(','); + } + ValueRef arg(ctx, JS_GetPropertyInt64(ctx, argv[1], i)); + if (JS_IsException(arg)) + { + throw JsException(); + } + if (JS_GetClassID(arg) != getRuntimeData(ctx)->typeClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD TYPE ARGUMENT"); + throw JsException(); + } + css::uno::Type argType(static_cast( + JS_GetOpaque(arg, getRuntimeData(ctx)->typeClassId))); + switch (argType.getTypeClass()) + { + case css::uno::TypeClass_VOID: + case css::uno::TypeClass_UNSIGNED_SHORT: + case css::uno::TypeClass_UNSIGNED_LONG: + case css::uno::TypeClass_UNSIGNED_HYPER: + case css::uno::TypeClass_EXCEPTION: + JS_ThrowTypeError(ctx, "TODO: BAD TYPE ARGUMENT"); + throw JsException(); + default: + break; + } + buf.append(argType.getTypeName()); + } + buf.append('>'); + } + css::uno::Type const type(td->getTypeClass(), buf.makeStringAndClear()); + ValueRef val(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->typeClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(val, typeAcquire(type)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + return val.release(); + }); +} + +JSValue unoTypeException(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, argc, argv] { + if (argc < 1) + return JS_ThrowPlainError(ctx, "missing argument to uno.type.exception"); + ValueRef data(ctx, JS_GetPropertyStr(ctx, argv[0], "'data")); + if (JS_IsException(data)) + { + throw JsException(); + } + if (JS_GetClassID(data) != getRuntimeData(ctx)->exceptionClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO TYPE VALUE"); + throw JsException(); + } + css::uno::Type const type(static_cast( + JS_GetOpaque(data, getRuntimeData(ctx)->exceptionClassId))); + ValueRef val(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->typeClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(val, typeAcquire(type)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + return val.release(); + }); +} + +JSValue unoTypeInterface(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, argc, argv] { + if (argc < 1) + return JS_ThrowPlainError(ctx, "missing argument to uno.type.interface"); + if (JS_GetClassID(argv[0]) != getRuntimeData(ctx)->interfaceClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO TYPE VALUE"); + throw JsException(); + } + css::uno::Type const type(static_cast( + JS_GetOpaque(argv[0], getRuntimeData(ctx)->interfaceClassId))); + ValueRef val(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->typeClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(val, typeAcquire(type)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + return val.release(); + }); +} + +JSValue enumGetImportClassName(JSContext* ctx, JSValueConst this_val, int, JSValueConst*) +{ + typelib_TypeDescriptionReference* typeRef = static_cast( + JS_GetOpaque2(ctx, this_val, getRuntimeData(ctx)->enumClassId)); + if (typeRef == nullptr) + return JS_EXCEPTION; + + return importClassNameFromFullName(ctx, OUString(typeRef->pTypeName)); +} + +void enumFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + typelib_typedescriptionreference_release(static_cast( + JS_GetOpaque(val, getRuntimeData(rt)->enumClassId))); +} + +void structFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + static_cast( + JS_GetOpaque(val, getRuntimeData(rt)->structClassId)) + ->release(); +} + +JSValue structCtor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, new_target, argc, argv] { + ValueRef data(ctx, JS_GetPropertyStr(ctx, new_target, "'data")); + if (JS_IsException(data)) + { + throw JsException(); + } + css::uno::Reference td(static_cast( + JS_GetOpaque(data, getRuntimeData(ctx)->structClassId))); + int argIdx = 0; + auto const params = td->getTypeParameters(); + std::vector typeArgs; + OUStringBuffer buf(td->getName()); + if (params.hasElements()) + { + assert(!td->getBaseType()); + if (argc < 1) + { + JS_ThrowSyntaxError(ctx, "TODO: MISSING TYPE ARGUMENTS"); + throw JsException(); + } + if (!JS_IsArray(argv[0])) + { + JS_ThrowTypeError(ctx, "TODO: BAD TYPE ARGUMENTS"); + throw JsException(); + } + ValueRef len1(ctx, JS_GetPropertyStr(ctx, argv[0], "length")); + if (JS_IsException(len1)) + { + throw JsException(); + } + std::int64_t len2; + auto const e = JS_ToInt64(ctx, &len2, len1); + if (e != 0) + { + throw JsException(); + } + if (len2 != params.getLength()) + { + JS_ThrowTypeError(ctx, "TODO: BAD TYPE ARGUMENTS"); + throw JsException(); + } + buf.append('<'); + for (std::int64_t i = 0; i != len2; ++i) + { + if (i != 0) + { + buf.append(','); + } + ValueRef arg(ctx, JS_GetPropertyInt64(ctx, argv[0], i)); + if (JS_IsException(arg)) + { + throw JsException(); + } + if (JS_GetClassID(arg) != getRuntimeData(ctx)->typeClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD TYPE ARGUMENT"); + throw JsException(); + } + css::uno::Type argType(static_cast( + JS_GetOpaque(arg, getRuntimeData(ctx)->typeClassId))); + switch (argType.getTypeClass()) + { + case css::uno::TypeClass_VOID: + case css::uno::TypeClass_UNSIGNED_SHORT: + case css::uno::TypeClass_UNSIGNED_LONG: + case css::uno::TypeClass_UNSIGNED_HYPER: + case css::uno::TypeClass_EXCEPTION: + JS_ThrowTypeError(ctx, "TODO: BAD TYPE ARGUMENT"); + throw JsException(); + default: + break; + } + typeArgs.push_back(argType); + buf.append(argType.getTypeName()); + } + buf.append('>'); + ++argIdx; + } + css::uno::Type type(css::uno::TypeClass_STRUCT, buf.makeStringAndClear()); + ValueRef proto(ctx, JS_GetPropertyStr(ctx, new_target, "prototype")); + if (JS_IsException(proto)) + { + throw JsException(); + } + ValueRef obj(ctx, JS_NewObjectProtoClass(ctx, proto, getRuntimeData(ctx)->compoundClassId)); + if (JS_IsException(obj)) + { + throw JsException(); + } + JS_SetOpaque(obj, typeAcquire(type)); +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + for (css::uno::Reference ctd( + td, css::uno::UNO_QUERY_THROW); + ;) + { + auto const memberNames = ctd->getMemberNames(); + auto const memberTypes = ctd->getMemberTypes(); + assert(memberNames.getLength() == memberTypes.getLength()); + for (sal_Int32 i = 0; i != memberNames.getLength(); ++i) + { + auto const name = memberNames[i].toUtf8(); + AtomRef const a(ctx, JS_NewAtomLen(ctx, name.getStr(), name.getLength())); + assert(a != JS_ATOM_NULL); //TODO + ValueRef val(ctx); + int has = 0; + if (argc > argIdx) + { + has = JS_HasProperty(ctx, argv[argIdx], a); + if (has == -1) + { + throw JsException(); + } + if (has == 1) + { + val = JS_GetProperty(ctx, argv[argIdx], a); + if (JS_IsException(val)) + { + throw JsException(); + } + } + } + if (has == 0) + { + css::uno::Type memType; + if (memberTypes[i]->getTypeClass() == css::uno::TypeClass_UNKNOWN) + { + sal_Int32 j = 0; + for (auto const& param : params) + { + if (memberTypes[i]->getName() == param) + { + break; + } + ++j; + } + assert(o3tl::make_unsigned(j) < typeArgs.size()); + memType = typeArgs[j]; + } + else + { + memType = css::uno::Type(memberTypes[i]->getTypeClass(), + memberTypes[i]->getName()); + } + val = createDefaultValue(ctx, memType); + } + JS_SetProperty(ctx, obj, a, val.release()); + } + auto const base = ctd->getBaseType(); + if (!base.is()) + { + break; + } + ctd.set(base, css::uno::UNO_QUERY_THROW); + } + return obj.release(); + }); +} + +void exceptionFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + typelib_typedescriptionreference_release(static_cast( + JS_GetOpaque(val, getRuntimeData(rt)->exceptionClassId))); +} + +JSValue exceptionCtor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, new_target, argc, argv] { + ValueRef data(ctx, JS_GetPropertyStr(ctx, new_target, "'data")); + if (JS_IsException(data)) + { + throw JsException(); + } + css::uno::Type const type(static_cast( + JS_GetOpaque(data, getRuntimeData(ctx)->exceptionClassId))); + css::uno::TypeDescription desc(type); + auto compDesc = reinterpret_cast(desc.get()); + ValueRef proto(ctx, JS_GetPropertyStr(ctx, new_target, "prototype")); + if (JS_IsException(proto)) + { + throw JsException(); + } + ValueRef obj(ctx, JS_NewObjectProtoClass(ctx, proto, getRuntimeData(ctx)->compoundClassId)); + if (JS_IsException(obj)) + { + throw JsException(); + } + JS_SetOpaque(obj, typeAcquire(type)); +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + for (;;) + { + for (sal_Int32 i = 0; i != compDesc->nMembers; ++i) + { + auto const name = OUString::unacquired(&compDesc->ppMemberNames[i]).toUtf8(); + AtomRef const a(ctx, JS_NewAtomLen(ctx, name.getStr(), name.getLength())); + assert(a != JS_ATOM_NULL); //TODO + ValueRef val(ctx); + int has = 0; + if (argc >= 1) + { + has = JS_HasProperty(ctx, argv[0], a); + if (has == -1) + { + throw JsException(); + } + if (has == 1) + { + val = JS_GetProperty(ctx, argv[0], a); + if (JS_IsException(val)) + { + throw JsException(); + } + } + } + if (has == 0) + { + val = createDefaultValue(ctx, compDesc->ppTypeRefs[i]); + } + JS_SetProperty(ctx, obj, a, val.release()); + } + compDesc = compDesc->pBaseTypeDescription; + if (compDesc == nullptr) + { + break; + } + } + return obj.release(); + }); +} + +void interfaceFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + typelib_typedescriptionreference_release(static_cast( + JS_GetOpaque(val, getRuntimeData(rt)->interfaceClassId))); +} + +struct CtorData +{ + OUString service; + css::uno::Reference ctor; +}; + +void ctorFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + delete static_cast(JS_GetOpaque(val, getRuntimeData(rt)->ctorClassId)); +} + +JSValue createService(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv, int, + JSValueConst* func_data) +{ + return callFromJs(ctx, [ctx, argc, argv, func_data] { + auto const data + = static_cast(JS_GetOpaque(func_data[0], getRuntimeData(ctx)->ctorClassId)); + auto const params = data->ctor->getParameters(); + auto const variadic + = params.hasElements() && params[params.getLength() - 1]->isRestParameter(); + if (variadic ? (argc < params.getLength()) : (argc != params.getLength() + 1)) + { + JS_ThrowSyntaxError(ctx, "TODO: BAD NUMBER OF ARGUMENTS"); + throw JsException(); + } + css::uno::Reference context( + fromJs(ctx, cppu::UnoType::get(), argv[0]), + css::uno::UNO_QUERY_THROW); + css::uno::Sequence args(argc - 1); + for (sal_Int32 i = 0; i != params.getLength(); ++i) + { + assert(params[i]->isIn()); + assert(!params[i]->isOut()); + if (params[i]->isRestParameter()) + { + assert(i == params.getLength() - 1); + for (sal_Int32 j = i; j != argc - 1; ++j) + { + args.getArray()[j] = fromJs(ctx, + css::uno::Type(params[i]->getType()->getTypeClass(), + params[i]->getType()->getName()), + argv[j + 1]); + } + } + else + { + args.getArray()[i] = fromJs(ctx, + css::uno::Type(params[i]->getType()->getTypeClass(), + params[i]->getType()->getName()), + argv[i + 1]); + } + } + css::uno::Reference ifc( + data->ctor->isDefaultConstructor() + ? context->getServiceManager()->createInstanceWithContext(data->service, context) + : context->getServiceManager()->createInstanceWithArgumentsAndContext( + data->service, args, context), + css::uno::UNO_SET_THROW); + return toJs(ctx, css::uno::Any(ifc)).release(); + }); +} + +void singletonFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + rtl_uString_release( + static_cast(JS_GetOpaque(val, getRuntimeData(rt)->singletonClassId))); +} + +JSValue getSingleton(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv, int, + JSValueConst* func_data) +{ + return callFromJs(ctx, [ctx, argc, argv, func_data] { + if (argc < 1) + return JS_ThrowPlainError(ctx, "missing argument to getSingleton"); + auto const s = static_cast( + JS_GetOpaque(func_data[0], getRuntimeData(ctx)->singletonClassId)); + css::uno::Reference context( + fromJs(ctx, cppu::UnoType::get(), argv[0]), + css::uno::UNO_QUERY_THROW); + css::uno::Reference ifc( + context->getValueByName("/singletons/" + OUString::unacquired(&s)), + css::uno::UNO_QUERY_THROW); + return toJs(ctx, css::uno::Any(ifc)).release(); + }); +} + +JSValue moduleGetImportClassName(JSContext* ctx, JSValueConst this_val, int, JSValueConst*) +{ + ModuleData* moduleData = static_cast( + JS_GetOpaque2(ctx, this_val, getRuntimeData(ctx)->moduleClassId)); + if (moduleData == nullptr) + return JS_EXCEPTION; + + return importClassNameFromFullName(ctx, moduleData->name); +} + +void moduleGCMark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* markFunc) +{ + ModuleData* moduleData + = static_cast(JS_GetOpaque(val, getRuntimeData(rt)->moduleClassId)); + if (moduleData != nullptr) + JS_MarkValue(rt, moduleData->memberCache, markFunc); +} + +void moduleFinalizer(JSRuntime* rt, JSValueConst val) +{ +#if defined DBG_UTIL + getRuntimeData(rt)->toFinalize.dec(); +#endif + ModuleData* moduleData + = static_cast(JS_GetOpaque(val, getRuntimeData(rt)->moduleClassId)); + assert(moduleData); + delete moduleData; +} + +ValueRef moduleGetOwnPropertyUncached(JSContext* ctx, const OUString& id) +{ + // Special hack for rhino compatibility + if (id == u"com.sun.star.uno.UnoRuntime") + return jsuno::rhino_compatibility::createUnoRuntime(ctx); + + css::uno::Reference mgr( + comphelper::getProcessComponentContext()->getValueByName( + u"/singletons/com.sun.star.reflection.theTypeDescriptionManager"_ustr), + css::uno::UNO_QUERY_THROW); + if (!mgr->hasByHierarchicalName(id)) + { + return ValueRef(ctx, JS_UNDEFINED); + } + + css::uno::Reference td(mgr->getByHierarchicalName(id), + css::uno::UNO_QUERY_THROW); + auto const tc = td->getTypeClass(); + ValueRef val(ctx); + switch (tc) + { + case css::uno::TypeClass_ENUM: + { + css::uno::Type type(tc, id); + val = JS_NewObjectClass(ctx, getRuntimeData(ctx)->enumClassId); + [[maybe_unused]] auto e = JS_SetOpaque(val, typeAcquire(type)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + css::uno::TypeDescription desc(type); + auto const enumDesc = reinterpret_cast(desc.get()); + for (sal_Int32 i = 0; i != enumDesc->nEnumValues; ++i) + { + ValueRef val2(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->enumeratorClassId)); + e = JS_SetOpaque( + val2, new EnumeratorData{ type, enumDesc->pEnumValues[i], + OUString::unacquired(&enumDesc->ppEnumNames[i]) }); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + JS_SetPropertyStr(ctx, val, + OUString::unacquired(&enumDesc->ppEnumNames[i]).toUtf8().getStr(), + val2.release()); + } + break; + } + case css::uno::TypeClass_STRUCT: + { + css::uno::Reference std( + td, css::uno::UNO_QUERY_THROW); + assert(!std->getTypeArguments().hasElements()); + ValueRef proto(ctx, JS_NewObject(ctx)); + assert(!JS_IsException(proto)); //TODO + val = JS_NewCFunction2(ctx, structCtor, "TODO", 0, JS_CFUNC_constructor, 0); + assert(!JS_IsException(val)); //TODO + JS_SetConstructor(ctx, val, proto); + ValueRef data(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->structClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(data, std.get()); + assert(e == 0); //TODO + std->acquire(); +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + JS_DefinePropertyValueStr(ctx, val, "'data", data.release(), 0); + break; + } + case css::uno::TypeClass_EXCEPTION: + { + ValueRef proto(ctx, JS_NewObject(ctx)); + assert(!JS_IsException(proto)); //TODO + val = JS_NewCFunction2(ctx, exceptionCtor, "TODO", 0, JS_CFUNC_constructor, 0); + assert(!JS_IsException(val)); //TODO + JS_SetConstructor(ctx, val, proto); + ValueRef data(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->exceptionClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(data, typeAcquire(css::uno::Type(tc, id))); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + JS_DefinePropertyValueStr(ctx, val, "'data", data.release(), 0); + break; + } + case css::uno::TypeClass_INTERFACE: + { + val = JS_NewObjectClass(ctx, getRuntimeData(ctx)->interfaceClassId); + [[maybe_unused]] auto const e = JS_SetOpaque(val, typeAcquire(css::uno::Type(tc, id))); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + break; + } + case css::uno::TypeClass_MODULE: + { + val = JS_NewObjectClass(ctx, getRuntimeData(ctx)->moduleClassId); + [[maybe_unused]] auto const e = JS_SetOpaque(val, new ModuleData(ctx, id)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + break; + } + case css::uno::TypeClass_CONSTANTS: + { + val = JS_NewObject(ctx); + if (JS_IsException(val)) + return val; + + css::uno::Reference cstd( + td, css::uno::UNO_QUERY_THROW); + for (auto const& ctd : cstd->getConstants()) + { + ValueRef con = toJs(ctx, ctd->getConstantValue()); + auto const name = ctd->getName(); + auto const n = name.lastIndexOf('.'); + if (JS_SetPropertyStr(ctx, val, name.copy(n + 1).toUtf8().getStr(), con.release()) + == -1) + { + return ValueRef(ctx, JS_EXCEPTION); + } + } + break; + } + case css::uno::TypeClass_SERVICE: + { + css::uno::Reference std( + td, css::uno::UNO_QUERY_THROW); + if (!std->isSingleInterfaceBased()) + { + val = JS_UNDEFINED; + break; + } + val = JS_NewObject(ctx); + if (JS_IsException(val)) + { + return val; + } + for (auto const& ctor : std->getConstructors()) + { + ValueRef data(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->ctorClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(data, new CtorData{ id, ctor }); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + ValueRef fun(ctx, JS_NewCFunctionData(ctx, createService, + ctor->getParameters().getLength() + 1, 0, 1, + data.ptr())); + if (JS_IsException(fun)) + { + return fun; + } + if (JS_SetPropertyStr( + ctx, val, + ctor->isDefaultConstructor() ? "create" : ctor->getName().toUtf8().getStr(), + fun.release()) + == -1) + { + return ValueRef(ctx, JS_EXCEPTION); + } + } + break; + } + case css::uno::TypeClass_SINGLETON: + { + ValueRef data(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->singletonClassId)); + [[maybe_unused]] auto const e = JS_SetOpaque(data, stringAcquire(id)); + assert(e == 0); //TODO +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + val = JS_NewCFunctionData(ctx, getSingleton, 1, 0, 1, data.ptr()); + break; + } + case css::uno::TypeClass_TYPEDEF: + val = JS_UNDEFINED; + break; + default: + O3TL_UNREACHABLE; + } + + return val; +} + +int moduleGetOwnProperty(JSContext* ctx, JSPropertyDescriptor* propertyDesc, JSValueConst obj, + JSAtom atom) +{ + ModuleData* moduleData + = static_cast(JS_GetOpaque2(ctx, obj, getRuntimeData(ctx)->moduleClassId)); + if (moduleData == nullptr) + return -1; + + // Check if we already have a cached value for this atom + if (!JS_IsUninitialized(moduleData->memberCache)) + { + ValueRef cachedValue(ctx, JS_GetProperty(ctx, moduleData->memberCache, atom)); + if (!JS_IsUndefined(cachedValue)) + { + if (propertyDesc) + { + propertyDesc->flags = 0; + propertyDesc->value = cachedValue.release(); + propertyDesc->getter = JS_UNDEFINED; + propertyDesc->setter = JS_UNDEFINED; + } + return int(true); + } + } + + OUStringBuffer buf(moduleData->name); + if (!buf.isEmpty()) + { + buf.append('.'); + } + buf.append(OUString::fromUtf8(JS_AtomToCString(ctx, atom))); + auto const id = buf.makeStringAndClear(); + + ValueRef val = moduleGetOwnPropertyUncached(ctx, id); + + if (JS_IsUninitialized(val) || JS_IsUndefined(val)) + return int(false); + if (JS_IsException(val)) + return -1; + + if (JS_IsUninitialized(moduleData->memberCache)) + { + moduleData->memberCache = JS_NewObject(ctx); + if (JS_IsException(moduleData->memberCache)) + return -1; + } + if (JS_SetProperty(ctx, moduleData->memberCache, atom, val.dup()) == -1) + return -1; + + if (propertyDesc) + { + propertyDesc->flags = 0; + propertyDesc->value = val.release(); + propertyDesc->getter = JS_UNDEFINED; + propertyDesc->setter = JS_UNDEFINED; + } + return int(true); +} + +ValueRef getUnoidlRepresentation(JSContext* ctx, std::u16string_view id) +{ + ValueRef const global(ctx, JS_GetGlobalObject(ctx)); + ValueRef const uno(ctx, JS_GetPropertyStr(ctx, global, "uno")); + assert(JS_IsObject(uno)); + ValueRef obj(ctx, JS_GetPropertyStr(ctx, uno, "idl")); + assert(JS_IsObject(obj)); + std::size_t idx = 0; + do + { + ValueRef next( + ctx, + JS_GetPropertyStr(ctx, obj, OUString(o3tl::getToken(id, u'.', idx)).toUtf8().getStr())); + assert(JS_IsObject(next)); //TODO + obj = std::move(next); + } while (idx != std::u16string_view::npos); + return obj; +} + +ValueRef createDefaultValue(JSContext* ctx, css::uno::Type const& type) +{ + switch (type.getTypeClass()) + { + case css::uno::TypeClass_BOOLEAN: + return ValueRef(ctx, JS_NewBool(ctx, false)); + case css::uno::TypeClass_BYTE: + case css::uno::TypeClass_SHORT: + case css::uno::TypeClass_UNSIGNED_SHORT: + case css::uno::TypeClass_LONG: + case css::uno::TypeClass_UNSIGNED_LONG: + case css::uno::TypeClass_FLOAT: + case css::uno::TypeClass_DOUBLE: + return ValueRef(ctx, JS_NewInt32(ctx, 0)); + case css::uno::TypeClass_HYPER: + case css::uno::TypeClass_UNSIGNED_HYPER: + return ValueRef(ctx, JS_NewBigInt64(ctx, 0)); + case css::uno::TypeClass_CHAR: + return ValueRef(ctx, JS_NewStringLen(ctx, "\0", 1)); + case css::uno::TypeClass_STRING: + return ValueRef(ctx, JS_NewString(ctx, "")); + case css::uno::TypeClass_TYPE: + return mapTypeToJs(ctx, cppu::UnoType::get()); + case css::uno::TypeClass_ANY: + return ValueRef(ctx, JS_UNDEFINED); + case css::uno::TypeClass_SEQUENCE: + return ValueRef(ctx, JS_NewArray(ctx)); + case css::uno::TypeClass_ENUM: + { + css::uno::TypeDescription desc(type); + auto const enumDesc = reinterpret_cast(desc.get()); + auto val = getUnoidlRepresentation( + ctx, Concat2View(type.getTypeName() + "." + + OUString::unacquired(&enumDesc->ppEnumNames[0]))); + assert(JS_GetClassID(val) == getRuntimeData(ctx)->enumeratorClassId); //TODO + return val; + } + case css::uno::TypeClass_STRUCT: + { + auto const id = type.getTypeName(); + auto n = id.indexOf('<'); + auto const rep = getUnoidlRepresentation(ctx, n == -1 ? id : id.subView(0, n)); + ValueRef val(ctx); + if (n == -1) + { + val = JS_CallConstructor(ctx, rep, 0, nullptr); + if (JS_IsException(val)) + { + throw JsException(); + } + } + else + { + ValueRef args(ctx, JS_NewArray(ctx)); + if (JS_IsException(args)) + { + throw JsException(); + } + std::uint32_t arg = 0; + assert(id.endsWith(">")); + sal_Int32 nest = 0; + ++n; + css::uno::Reference mgr( + comphelper::getProcessComponentContext()->getValueByName( + u"/singletons/com.sun.star.reflection.theTypeDescriptionManager"_ustr), + css::uno::UNO_QUERY_THROW); + for (sal_Int32 i = n;; ++i) + { + if (i == id.getLength() - 1 || (nest == 0 && id[i] == ',')) + { + assert(nest == 0); + css::uno::Reference td( + mgr->getByHierarchicalName(id.copy(n, i - n)), + css::uno::UNO_QUERY_THROW); + if (JS_SetPropertyUint32( + ctx, args, arg++, + mapTypeToJs(ctx, css::uno::Type(td->getTypeClass(), td->getName())) + .release()) + == -1) + { + throw JsException(); + } + if (i == id.getLength() - 1) + { + break; + } + n = i + 1; + } + else if (id[i] == '<') + { + ++nest; + } + else if (id[i] == '>') + { + assert(nest != 0); + --nest; + } + } + val = JS_CallConstructor(ctx, rep, 1, args.ptr()); + if (JS_IsException(val)) + { + throw JsException(); + } + } + return val; + } + case css::uno::TypeClass_INTERFACE: + return ValueRef(ctx, JS_NULL); + default: + O3TL_UNREACHABLE; + } +} + +JSValue unoAny(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, new_target, argc, argv] { + if (argc < 1) + return JS_ThrowPlainError(ctx, "missing argument to uno.Any constructor"); + ValueRef proto(ctx, JS_GetPropertyStr(ctx, new_target, "prototype")); + if (JS_IsException(proto)) + { + throw JsException(); + } + ValueRef obj(ctx, JS_NewObjectProto(ctx, proto)); + if (JS_IsException(obj)) + { + throw JsException(); + } + JS_SetPropertyStr(ctx, obj, "type", JS_DupValue(ctx, argv[0])); + JS_SetPropertyStr(ctx, obj, "val", argc == 1 ? JS_UNDEFINED : JS_DupValue(ctx, argv[1])); + return obj.release(); + }); +} + +css::uno::Any fromJsString(JSContext* ctx, JSValueConst val) +{ + std::size_t n; + UniqueCString16 const p(ctx, JS_ToCStringLenUTF16(ctx, &n, val)); + if (p.get() == nullptr) + { + throw JsException(); + } + if (n > std::numeric_limits::max()) + { + JS_ThrowRangeError(ctx, "Bad UNO string value"); + throw JsException(); + } + OUString s(p.get(), n); + //TODO: check for valid UTF-16 + return css::uno::Any(s); +} + +css::uno::Any fromJsSequence(JSContext* ctx, css::uno::Type const& type, JSValueConst val) +{ + if (!JS_IsArray(val)) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO SEQUENCE VALUE"); + throw JsException(); + } + ValueRef len1(ctx, JS_GetPropertyStr(ctx, val, "length")); + if (JS_IsException(len1)) + { + throw JsException(); + } + std::int64_t len2; + auto const e = JS_ToInt64(ctx, &len2, len1); + if (e != 0) + { + throw JsException(); + } + if (len2 < 0 || len2 > std::numeric_limits::max()) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO SEQUENCE VALUE"); + throw JsException(); + } + css::uno::TypeDescription desc(type); + css::uno::TypeDescription elemDesc( + reinterpret_cast(desc.get())->pType); + uno_Sequence* seq; + uno_sequence_construct(&seq, desc.get(), nullptr, len2, css::uno::cpp_acquire); + for (std::int64_t i = 0; i != len2; ++i) + { + ValueRef elem(ctx, JS_GetPropertyInt64(ctx, val, i)); + if (JS_IsException(elem)) + { + uno_type_sequence_destroy(seq, desc.get()->pWeakRef, css::uno::cpp_release); + throw JsException(); + } + auto const any = fromJs(ctx, elemDesc.get()->pWeakRef, elem); + uno_copyData( + seq->elements + (i * elemDesc.get()->nSize), + const_cast(type == cppu::UnoType>::get() + ? &any + : any.getValue()), + elemDesc.get(), css::uno::cpp_acquire); + } + return { &seq, type }; +} + +css::uno::Any fromJsEnum(JSContext* ctx, JSValueConst val) +{ + if (JS_GetClassID(val) != getRuntimeData(ctx)->enumeratorClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO ENUM VALUE"); + throw JsException(); + } + auto const data = static_cast( + JS_GetOpaque(val, getRuntimeData(ctx)->enumeratorClassId)); + return { &data->value, data->type }; +} + +css::uno::Any fromJsInterface(JSContext* ctx, css::uno::Type const& type, JSValueConst val) +{ + if (JS_IsNull(val)) + { + return { nullptr, type }; + } + if (JS_GetClassID(val) != getRuntimeData(ctx)->wrapperClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO ENUM VALUE"); + throw JsException(); + } + WrapperData* wrapperData + = static_cast(JS_GetOpaque2(ctx, val, getRuntimeData(ctx)->wrapperClassId)); + if (wrapperData == nullptr) + throw JsException(); + auto const a = wrapperData->interface->queryInterface(type); + if (!a.hasValue()) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO INTERFACE VALUE"); + throw JsException(); + } + return a; +} + +css::uno::Any fromJs(JSContext* ctx, css::uno::Type const& type, JSValueConst val) +{ + switch (type.getTypeClass()) + { + case css::uno::TypeClass_VOID: + return {}; + case css::uno::TypeClass_BOOLEAN: + { + auto const n = JS_ToBool(ctx, val); + assert(n != -1); + return css::uno::Any(n == 1); + } + case css::uno::TypeClass_BYTE: + { + double n; + auto const e = JS_ToFloat64(ctx, &n, val); + if (e != 0) + { + throw JsException(); + } + n = std::trunc(n); + if (n < SAL_MIN_INT8 || n > SAL_MAX_INT8) + { + JS_ThrowRangeError(ctx, "Bad UNO byte val %f", n); + throw JsException(); + } + return css::uno::Any(static_cast(n)); + } + case css::uno::TypeClass_SHORT: + { + double n; + auto const e = JS_ToFloat64(ctx, &n, val); + if (e != 0) + { + throw JsException(); + } + n = std::trunc(n); + if (n < SAL_MIN_INT16 || n > SAL_MAX_INT16) + { + JS_ThrowRangeError(ctx, "Bad UNO short value %f", n); + throw JsException(); + } + return css::uno::Any(static_cast(n)); + } + case css::uno::TypeClass_UNSIGNED_SHORT: + { + double n; + auto const e = JS_ToFloat64(ctx, &n, val); + if (e != 0) + { + throw JsException(); + } + n = std::trunc(n); + if (n < 0 || n > SAL_MAX_UINT16) + { + JS_ThrowRangeError(ctx, "Bad UNO unsigned short value %f", n); + throw JsException(); + } + return css::uno::Any(static_cast(n)); + } + case css::uno::TypeClass_LONG: + { + double n; + auto const e = JS_ToFloat64(ctx, &n, val); + if (e != 0) + { + throw JsException(); + } + n = std::trunc(n); + if (n < SAL_MIN_INT32 || n > SAL_MAX_INT32) + { + JS_ThrowRangeError(ctx, "Bad UNO short value %f", n); + throw JsException(); + } + return css::uno::Any(static_cast(n)); + } + case css::uno::TypeClass_UNSIGNED_LONG: + { + double n; + auto const e = JS_ToFloat64(ctx, &n, val); + if (e != 0) + { + throw JsException(); + } + n = std::trunc(n); + if (n < 0 || n > SAL_MAX_UINT32) + { + JS_ThrowRangeError(ctx, "Bad UNO unsigned long value %f", n); + throw JsException(); + } + return css::uno::Any(static_cast(n)); + } + case css::uno::TypeClass_HYPER: + { + ValueRef const check(ctx, JS_Eval(ctx, + RTL_CONSTASCII_STRINGPARAM( + "(v) => v >= -(2n ** 63n) && v < 2n ** 63n"), + "", JS_EVAL_TYPE_GLOBAL)); + ValueRef const res(ctx, JS_Call(ctx, check, JS_NULL, 1, &val)); + if (JS_IsException(res)) + { + throw JsException(); + } + auto const ok = JS_ToBool(ctx, res); + assert(ok != -1); + if (ok == 0) + { + JS_ThrowRangeError(ctx, "Bad UNO hyper value"); + throw JsException(); + } + std::int64_t n; + [[maybe_unused]] auto const e = JS_ToBigInt64(ctx, &n, val); + assert(e == 0); + return css::uno::Any(static_cast(n)); + } + case css::uno::TypeClass_UNSIGNED_HYPER: + { + ValueRef const check( + ctx, JS_Eval(ctx, RTL_CONSTASCII_STRINGPARAM("(v) => v >= 0n && v < 2n ** 64n"), + "", JS_EVAL_TYPE_GLOBAL)); + ValueRef const res(ctx, JS_Call(ctx, check, JS_NULL, 1, &val)); + if (JS_IsException(res)) + { + throw JsException(); + } + auto const ok = JS_ToBool(ctx, res); + assert(ok != -1); + if (ok == 0) + { + JS_ThrowRangeError(ctx, "Bad UNO unsigned hyper value"); + throw JsException(); + } + std::uint64_t n; + [[maybe_unused]] auto const e = JS_ToBigUint64(ctx, &n, val); + assert(e == 0); + return css::uno::Any(static_cast(n)); + } + case css::uno::TypeClass_FLOAT: + { + double n; + auto const e = JS_ToFloat64(ctx, &n, val); + if (e != 0) + { + throw JsException(); + } + return css::uno::Any(static_cast(n)); + } + case css::uno::TypeClass_DOUBLE: + { + double n; + auto const e = JS_ToFloat64(ctx, &n, val); + if (e != 0) + { + throw JsException(); + } + return css::uno::Any(n); + } + case css::uno::TypeClass_CHAR: + { + std::size_t n; + UniqueCString16 const p(ctx, JS_ToCStringLenUTF16(ctx, &n, val)); + if (p.get() == nullptr) + { + throw JsException(); + } + if (n != 1) + { + JS_ThrowRangeError(ctx, "Bad UNO char value"); + throw JsException(); + } + auto const c = p.get()[0]; + return css::uno::Any(char16_t(c)); + } + case css::uno::TypeClass_STRING: + return fromJsString(ctx, val); + case css::uno::TypeClass_TYPE: + if (JS_GetClassID(val) != getRuntimeData(ctx)->typeClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD UNO TYPE VALUE"); + throw JsException(); + } + return css::uno::Any(css::uno::Type(static_cast( + JS_GetOpaque(val, getRuntimeData(ctx)->typeClassId)))); + case css::uno::TypeClass_ANY: + if (JS_IsUndefined(val)) + { + return {}; + } + if (JS_IsBool(val)) + { + auto const b = JS_ToBool(ctx, val); + if (b == -1) + { + throw JsException(); + } + return css::uno::Any(b == 1); + } + if (JS_IsNumber(val)) + { + double n; + [[maybe_unused]] auto const e = JS_ToFloat64(ctx, &n, val); //TODO + assert(e == 0); //TODO + if (n == std::trunc(n)) + { + if (n >= SAL_MIN_INT32 && n <= SAL_MAX_INT32) + { + return css::uno::Any(sal_Int32(n)); + } + if (n >= 0 && n <= SAL_MAX_UINT32) + { + return css::uno::Any(sal_uInt32(n)); + } + } + return css::uno::Any(n); + } + if (JS_IsBigInt(val)) + { + ValueRef const check1(ctx, JS_Eval(ctx, + RTL_CONSTASCII_STRINGPARAM( + "(v) => v >= -(2n ** 63n) && v < 2n ** 63n"), + "", JS_EVAL_TYPE_GLOBAL)); + ValueRef const res1(ctx, JS_Call(ctx, check1, JS_NULL, 1, &val)); + if (JS_IsException(res1)) + { + throw JsException(); + } + auto const ok1 = JS_ToBool(ctx, res1); + assert(ok1 != -1); + if (ok1 == 1) + { + std::int64_t n; + [[maybe_unused]] auto const e = JS_ToBigInt64(ctx, &n, val); + assert(e == 0); + return css::uno::Any(static_cast(n)); + } + ValueRef const check2( + ctx, JS_Eval(ctx, RTL_CONSTASCII_STRINGPARAM("(v) => v >= 0n && v < 2n ** 64n"), + "", JS_EVAL_TYPE_GLOBAL)); + ValueRef const res2(ctx, JS_Call(ctx, check2, JS_NULL, 1, &val)); + if (JS_IsException(res2)) + { + throw JsException(); + } + auto const ok2 = JS_ToBool(ctx, res2); + assert(ok2 != -1); + if (ok2 == 1) + { + std::uint64_t n; + [[maybe_unused]] auto const e = JS_ToBigUint64(ctx, &n, val); + assert(e == 0); + return css::uno::Any(static_cast(n)); + } + JS_ThrowRangeError(ctx, "Bad BigInt UNO any value"); + throw JsException(); + } + if (JS_IsString(val)) + { + return fromJsString(ctx, val); + } + if (JS_IsArray(val)) + { + return fromJsSequence(ctx, cppu::UnoType>::get(), + val); + } + if (JS_IsNull(val)) + { + return css::uno::Any(css::uno::Reference()); + } + if (JS_IsObject(val)) + { + if (JS_GetClassID(val) == getRuntimeData(ctx)->wrapperClassId) + { + return fromJsInterface(ctx, cppu::UnoType::get(), val); + } + if (JS_GetClassID(val) == getRuntimeData(ctx)->enumeratorClassId) + { + return fromJsEnum(ctx, val); + } + if (JS_GetClassID(val) == getRuntimeData(ctx)->compoundClassId) + { + return fromJs(ctx, + css::uno::Type(static_cast( + JS_GetOpaque(val, getRuntimeData(ctx)->compoundClassId))), + val); + } + if (JS_GetClassID(val) == getRuntimeData(ctx)->typeClassId) + { + return css::uno::Any( + css::uno::Type(static_cast( + JS_GetOpaque(val, getRuntimeData(ctx)->typeClassId)))); + } + ValueRef const global(ctx, JS_GetGlobalObject(ctx)); + if (JS_IsException(global)) + { + throw JsException(); + } + ValueRef const uno(ctx, JS_GetPropertyStr(ctx, global, "uno")); + if (JS_IsException(uno)) + { + throw JsException(); + } + ValueRef const anyCtor(ctx, JS_GetPropertyStr(ctx, uno, "Any")); + if (JS_IsException(anyCtor)) + { + throw JsException(); + } + auto const isAny = JS_IsInstanceOf(ctx, val, anyCtor); + if (isAny == -1) + { + throw JsException(); + } + if (isAny == 1) + { + ValueRef const anyType(ctx, JS_GetPropertyStr(ctx, val, "type")); + if (JS_IsException(anyType)) + { + throw JsException(); + } + ValueRef const anyVal(ctx, JS_GetPropertyStr(ctx, val, "val")); + if (JS_IsException(anyVal)) + { + throw JsException(); + } + if (JS_GetClassID(anyType) != getRuntimeData(ctx)->typeClassId) + { + JS_ThrowTypeError(ctx, "TODO: BAD ANY TYPE VALUE"); + throw JsException(); + } + return fromJs(ctx, + css::uno::Type(static_cast( + JS_GetOpaque(anyType, getRuntimeData(ctx)->typeClassId))), + anyVal); + } + } + JS_ThrowRangeError(ctx, "TODO: BAD UNO ANY VALUE"); + throw JsException(); + case css::uno::TypeClass_SEQUENCE: + return fromJsSequence(ctx, type, val); + case css::uno::TypeClass_ENUM: + return fromJsEnum(ctx, val); + case css::uno::TypeClass_STRUCT: + case css::uno::TypeClass_EXCEPTION: + { + css::uno::TypeDescription desc(type); + auto compDesc = reinterpret_cast(desc.get()); + std::vector mems; + for (;;) + { + for (sal_Int32 i = 0; i != compDesc->nMembers; ++i) + { + auto const name = OUString::unacquired(&compDesc->ppMemberNames[i]).toUtf8(); + AtomRef const a(ctx, JS_NewAtomLen(ctx, name.getStr(), name.getLength())); + assert(a != JS_ATOM_NULL); //TODO + auto const has = JS_HasProperty(ctx, val, a); + if (has == -1) + { + throw JsException(); + } + if (has == 0) + { + if (compDesc->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_ANY) + { + mems.emplace_back(); + } + else + { + css::uno::TypeDescription memDesc(compDesc->ppTypeRefs[i]); + memDesc.makeComplete(); + std::vector buf(memDesc.get()->nSize, 0); + uno_constructData(buf.data(), memDesc.get()); + mems.emplace_back(buf.data(), css::uno::Type(compDesc->ppTypeRefs[i])); + uno_destructData(buf.data(), memDesc.get(), css::uno::cpp_release); + } + } + else + { + ValueRef mem(ctx, JS_GetProperty(ctx, val, a)); + if (JS_IsException(mem)) + { + throw JsException(); + } + mems.push_back(fromJs(ctx, compDesc->ppTypeRefs[i], mem)); + } + } + compDesc = compDesc->pBaseTypeDescription; + if (compDesc == nullptr) + { + break; + } + } + auto const buf = rtl_allocateMemory(desc.get()->nSize); + std::size_t mem = 0; + for (compDesc = reinterpret_cast(desc.get());;) + { + for (sal_Int32 i = 0; i != compDesc->nMembers; ++i) + { + css::uno::TypeDescription memDesc(compDesc->ppTypeRefs[i]); + uno_copyData(static_cast(buf) + compDesc->pMemberOffsets[i], + const_cast(compDesc->ppTypeRefs[i]->eTypeClass + == typelib_TypeClass_ANY + ? &mems[mem] + : mems[mem].getValue()), + memDesc.get(), css::uno::cpp_acquire); + ++mem; + } + compDesc = compDesc->pBaseTypeDescription; + if (compDesc == nullptr) + { + break; + } + } + return { buf, type }; + } + case css::uno::TypeClass_INTERFACE: + return fromJsInterface(ctx, type, val); + default: + O3TL_UNREACHABLE; + } +} + +ValueRef mapTypeToJs(JSContext* ctx, css::uno::Type const& type) +{ + switch (type.getTypeClass()) + { + case css::uno::TypeClass_VOID: + case css::uno::TypeClass_BOOLEAN: + case css::uno::TypeClass_BYTE: + case css::uno::TypeClass_SHORT: + case css::uno::TypeClass_UNSIGNED_SHORT: + case css::uno::TypeClass_LONG: + case css::uno::TypeClass_UNSIGNED_LONG: + case css::uno::TypeClass_HYPER: + case css::uno::TypeClass_UNSIGNED_HYPER: + case css::uno::TypeClass_FLOAT: + case css::uno::TypeClass_DOUBLE: + case css::uno::TypeClass_CHAR: + case css::uno::TypeClass_STRING: + case css::uno::TypeClass_TYPE: + case css::uno::TypeClass_ANY: + { + ValueRef const global(ctx, JS_GetGlobalObject(ctx)); + ValueRef const uno(ctx, JS_GetPropertyStr(ctx, global, "uno")); + assert(JS_IsObject(uno)); + ValueRef typeObj(ctx, JS_GetPropertyStr(ctx, uno, "type")); + assert(JS_IsObject(typeObj)); + ValueRef val(ctx, + JS_GetPropertyStr(ctx, typeObj, type.getTypeName().toUtf8().getStr())); + assert(JS_GetClassID(val) == getRuntimeData(ctx)->typeClassId); //TODO + return val; + } + case css::uno::TypeClass_SEQUENCE: + { + css::uno::TypeDescription desc(type); + css::uno::TypeDescription elemDesc( + reinterpret_cast(desc.get())->pType); + auto elem = mapTypeToJs(ctx, elemDesc.get()->pWeakRef); + ValueRef val(ctx, unoTypeSequence(ctx, JS_NULL, 1, elem.ptr())); + if (JS_IsException(val)) + { + throw JsException(); + } + return val; + } + case css::uno::TypeClass_ENUM: + { + auto rep = getUnoidlRepresentation(ctx, type.getTypeName()); + ValueRef val(ctx, unoTypeEnum(ctx, JS_NULL, 1, rep.ptr())); + if (JS_IsException(val)) + { + throw JsException(); + } + return val; + } + case css::uno::TypeClass_STRUCT: + { + auto rep = getUnoidlRepresentation(ctx, type.getTypeName()); + ValueRef val(ctx, unoTypeStruct(ctx, JS_NULL, 1, rep.ptr())); + if (JS_IsException(val)) + { + throw JsException(); + } + return val; + } + case css::uno::TypeClass_EXCEPTION: + { + auto rep = getUnoidlRepresentation(ctx, type.getTypeName()); + ValueRef val(ctx, unoTypeException(ctx, JS_NULL, 1, rep.ptr())); + if (JS_IsException(val)) + { + throw JsException(); + } + return val; + } + case css::uno::TypeClass_INTERFACE: + { + auto rep = getUnoidlRepresentation(ctx, type.getTypeName()); + ValueRef val(ctx, unoTypeInterface(ctx, JS_NULL, 1, rep.ptr())); + if (JS_IsException(val)) + { + throw JsException(); + } + return val; + } + default: + O3TL_UNREACHABLE; + } +} + +ValueRef toJs(JSContext* ctx, css::uno::Type const& type, void const* value) +{ + switch (type.getTypeClass()) + { + case css::uno::TypeClass_VOID: + return ValueRef(ctx, JS_UNDEFINED); + case css::uno::TypeClass_BOOLEAN: + return ValueRef(ctx, JS_NewBool(ctx, *static_cast(value))); + case css::uno::TypeClass_BYTE: + return ValueRef(ctx, JS_NewInt32(ctx, *static_cast(value))); + case css::uno::TypeClass_SHORT: + return ValueRef(ctx, JS_NewInt32(ctx, *static_cast(value))); + case css::uno::TypeClass_UNSIGNED_SHORT: + return ValueRef(ctx, JS_NewInt32(ctx, *static_cast(value))); + case css::uno::TypeClass_LONG: + return ValueRef(ctx, JS_NewInt32(ctx, *static_cast(value))); + case css::uno::TypeClass_UNSIGNED_LONG: + return ValueRef(ctx, JS_NewUint32(ctx, *static_cast(value))); + case css::uno::TypeClass_HYPER: + return ValueRef(ctx, JS_NewBigInt64(ctx, *static_cast(value))); + case css::uno::TypeClass_UNSIGNED_HYPER: + return ValueRef(ctx, JS_NewBigUint64(ctx, *static_cast(value))); + case css::uno::TypeClass_FLOAT: + return ValueRef(ctx, JS_NewFloat64(ctx, *static_cast(value))); + case css::uno::TypeClass_DOUBLE: + return ValueRef(ctx, JS_NewFloat64(ctx, *static_cast(value))); + case css::uno::TypeClass_CHAR: + { + auto const s = *static_cast(value); + return ValueRef(ctx, + JS_NewStringUTF16(ctx, reinterpret_cast(&s), 1)); + } + case css::uno::TypeClass_STRING: + { + auto const& s = OUString::unacquired(static_cast(value)); + return ValueRef( + ctx, JS_NewStringUTF16(ctx, reinterpret_cast(s.getStr()), + s.getLength())); + } + case css::uno::TypeClass_TYPE: + return mapTypeToJs(ctx, *static_cast(value)); + case css::uno::TypeClass_ANY: + { + auto const any = static_cast(value); + return toJs(ctx, *reinterpret_cast(&any->pType), any->pData); + } + case css::uno::TypeClass_SEQUENCE: + { + auto const seq = *static_cast(value); + css::uno::TypeDescription desc(type); + css::uno::TypeDescription elemDesc( + reinterpret_cast(desc.get())->pType); + std::vector refs; + for (sal_Int32 i = 0; i != seq->nElements; ++i) + { + refs.push_back(toJs(ctx, elemDesc.get()->pWeakRef, + seq->elements + (i * elemDesc.get()->nSize))); + } + std::vector vals; + for (auto& ref : refs) + { + vals.push_back(ref); + } + ValueRef arr(ctx, JS_NewArrayFrom(ctx, vals.size(), vals.data())); + for (auto& ref : refs) + { + ref.release(); + } + if (JS_IsException(arr)) + { + throw JsException(); + } + return arr; + } + case css::uno::TypeClass_ENUM: + { + auto const val = *static_cast(value); + css::uno::TypeDescription desc(type); + auto const enumDesc = reinterpret_cast(desc.get()); + sal_Int32 i = 0; + for (; i != enumDesc->nEnumValues; ++i) + { + if (enumDesc->pEnumValues[i] == val) + { + break; + } + } + assert(i != enumDesc->nEnumValues); //TODO + auto obj = getUnoidlRepresentation( + ctx, Concat2View(type.getTypeName() + "." + + OUString::unacquired(&enumDesc->ppEnumNames[i]))); + assert(JS_GetClassID(obj) == getRuntimeData(ctx)->enumeratorClassId); //TODO + return obj; + } + case css::uno::TypeClass_STRUCT: + case css::uno::TypeClass_EXCEPTION: + { + ValueRef mems(ctx, JS_NewObject(ctx)); + if (JS_IsException(mems)) + { + throw JsException(); + } + css::uno::TypeDescription desc(type); + auto compDesc = reinterpret_cast(desc.get()); + for (;;) + { + for (sal_Int32 i = 0; i != compDesc->nMembers; ++i) + { + auto mem + = toJs(ctx, compDesc->ppTypeRefs[i], + static_cast(value) + compDesc->pMemberOffsets[i]); + if (JS_SetPropertyStr( + ctx, mems, + OUString::unacquired(&compDesc->ppMemberNames[i]).toUtf8().getStr(), + mem.release()) + == -1) + { + throw JsException(); + } + } + compDesc = compDesc->pBaseTypeDescription; + if (compDesc == nullptr) + { + break; + } + } + auto const id = type.getTypeName(); + auto n = id.indexOf('<'); + auto const rep = getUnoidlRepresentation(ctx, n == -1 ? id : id.subView(0, n)); + ValueRef val(ctx); + if (n == -1) + { + val = JS_CallConstructor(ctx, rep, 1, mems.ptr()); + if (JS_IsException(val)) + { + throw JsException(); + } + } + else + { + ValueRef args(ctx, JS_NewArray(ctx)); + if (JS_IsException(args)) + { + throw JsException(); + } + std::uint32_t arg = 0; + assert(id.endsWith(">")); + sal_Int32 nest = 0; + ++n; + css::uno::Reference mgr( + comphelper::getProcessComponentContext()->getValueByName( + u"/singletons/com.sun.star.reflection.theTypeDescriptionManager"_ustr), + css::uno::UNO_QUERY_THROW); + for (sal_Int32 i = n;; ++i) + { + if (i == id.getLength() - 1 || (nest == 0 && id[i] == ',')) + { + assert(nest == 0); + css::uno::Reference td( + mgr->getByHierarchicalName(id.copy(n, i - n)), + css::uno::UNO_QUERY_THROW); + if (JS_SetPropertyUint32( + ctx, args, arg++, + mapTypeToJs(ctx, css::uno::Type(td->getTypeClass(), td->getName())) + .release()) + == -1) + { + throw JsException(); + } + if (i == id.getLength() - 1) + { + break; + } + n = i + 1; + } + else if (id[i] == '<') + { + ++nest; + } + else if (id[i] == '>') + { + assert(nest != 0); + --nest; + } + } + JSValueConst argv[] = { args, mems }; + val = JS_CallConstructor(ctx, rep, 2, argv); + if (JS_IsException(val)) + { + throw JsException(); + } + } + return val; + } + case css::uno::TypeClass_INTERFACE: + return ValueRef(ctx, + wrapUnoObject(ctx, *static_cast(value))); + default: + O3TL_UNREACHABLE; + } +} + +ValueRef toJs(JSContext* ctx, css::uno::Any const& value) +{ + return toJs(ctx, value.getValueType(), value.getValue()); +} + +JSValue sameUnoObject(JSContext* ctx, JSValueConst, int argc, JSValueConst* argv) +{ + return callFromJs(ctx, [ctx, argc, argv] { + if (argc < 2) + return JS_ThrowPlainError(ctx, "missing argument to uno.sameUnoObject"); + return JS_NewBool( + ctx, + *o3tl::forceAccess>( + fromJsInterface(ctx, cppu::UnoType::get(), argv[0])) + == *o3tl::forceAccess>( + fromJsInterface(ctx, cppu::UnoType::get(), argv[1]))); + }); +} + +JSValue invokeUno(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int, + JSValueConst* func_data) +{ + return callFromJs(ctx, [ctx, this_val, argc, argv, func_data] { + auto const info = static_cast( + JS_GetOpaque(func_data[0], getRuntimeData(ctx)->pointerClassId)); + if (argc != info->aParamTypes.getLength()) + { + JS_ThrowSyntaxError(ctx, "TODO: BAD NUMBER OF ARGUMENTS"); + throw JsException(); + } + css::uno::Sequence args(info->aParamTypes.getLength()); + for (int i = 0; i != argc; ++i) + { + if (info->aParamModes[i] == css::reflection::ParamMode_OUT) + { + continue; + } + ValueRef arg(ctx); + if (info->aParamModes[i] == css::reflection::ParamMode_IN) + { + arg = JS_DupValue(ctx, argv[i]); + } + else + { + AtomRef const a(ctx, JS_NewAtom(ctx, "val")); + assert(a != JS_ATOM_NULL); //TODO + auto const has = JS_HasProperty(ctx, argv[i], a); + if (has == -1) + { + throw JsException(); + } + if (has == 0) + { + JS_ThrowTypeError(ctx, "TODO: BAD INOUT ARG"); + throw JsException(); + } + arg = JS_GetProperty(ctx, argv[i], a); + if (JS_IsException(arg)) + { + throw JsException(); + } + } + args.getArray()[i] = fromJs(ctx, info->aParamTypes[i], arg); + } + css::uno::Sequence outParamIndex; //TODO + css::uno::Sequence outParam; + ValueRef ret(ctx); + try + { + WrapperData* wrapperData = static_cast( + JS_GetOpaque2(ctx, this_val, getRuntimeData(ctx)->wrapperClassId)); + if (wrapperData == nullptr) + throw JsException(); + + ret = toJs( + ctx, + css::uno::Reference( + css::script::Invocation::create(comphelper::getProcessComponentContext()) + ->createInstanceWithArguments({ css::uno::Any(wrapperData->interface) }), + css::uno::UNO_QUERY_THROW) + ->invoke(info->aName, args, outParamIndex, outParam)); + } + catch (css::reflection::InvocationTargetException e) + { + cppu::throwException(e.TargetException); + } + assert(outParamIndex.getLength() == outParam.getLength()); + for (sal_Int32 i = 0; i != outParamIndex.getLength(); ++i) + { + auto out = toJs(ctx, outParam[i]); + if (JS_SetPropertyStr(ctx, argv[outParamIndex[i]], "val", out.release()) == -1) + { + throw JsException(); + } + } + return ret.release(); + }); +} + +struct ExceptionData +{ + OUString type; + OUString message; +}; + +ExceptionData extractExceptionData(JSContext* ctx, ValueRef const& err) +{ + ExceptionData exc; + bool haveMessage = false; + if (JS_IsObject(err)) + { + ValueRef const nameVal(ctx, JS_GetPropertyStr(ctx, err, "name")); + if (JS_IsString(nameVal)) + { + std::size_t n; + UniqueCString16 const p(ctx, JS_ToCStringLenUTF16(ctx, &n, nameVal)); + if (p.get() != nullptr) + { + exc.type = OUString(p.get(), n); + } + } + ValueRef const msgVal(ctx, JS_GetPropertyStr(ctx, err, "message")); + if (JS_IsString(msgVal)) + { + std::size_t n; + UniqueCString16 const p(ctx, JS_ToCStringLenUTF16(ctx, &n, msgVal)); + if (p.get() != nullptr) + { + exc.message = OUString(p.get(), n); + haveMessage = true; + } + } + } + if (!haveMessage) + { + ValueRef const str(ctx, JS_ToString(ctx, err)); + if (!JS_IsException(str)) + { + std::size_t n; + UniqueCString16 const p(ctx, JS_ToCStringLenUTF16(ctx, &n, str)); + if (p.get() != nullptr) + { + exc.message = OUString(p.get(), n); + } + } + } + return exc; +} + +void initializeTypePrototype(JSContext* ctx) +{ + static const JSCFunctionListEntry functions[] = { + JS_CFUNC_DEF("toString", 0, typeToString), + }; + + ValueRef proto(ctx, JS_NewObject(ctx)); + JS_SetPropertyFunctionList(ctx, proto, functions, SAL_N_ELEMENTS(functions)); + + JS_SetClassProto(ctx, getRuntimeData(ctx)->typeClassId, proto.release()); +} + +void initializeEnumPrototype(JSContext* ctx) +{ + static const JSCFunctionListEntry functions[] = { + JS_CFUNC_DEF("getImportClassName", 0, enumGetImportClassName), + }; + + ValueRef proto(ctx, JS_NewObject(ctx)); + JS_SetPropertyFunctionList(ctx, proto, functions, SAL_N_ELEMENTS(functions)); + + JS_SetClassProto(ctx, getRuntimeData(ctx)->enumClassId, proto.release()); +} + +void initializeEnumeratorPrototype(JSContext* ctx) +{ + static const JSCFunctionListEntry functions[] = { + JS_CFUNC_DEF("toString", 0, enumeratorToString), + }; + + ValueRef proto(ctx, JS_NewObject(ctx)); + JS_SetPropertyFunctionList(ctx, proto, functions, SAL_N_ELEMENTS(functions)); + + JS_SetClassProto(ctx, getRuntimeData(ctx)->enumeratorClassId, proto.release()); +} + +void initializeWrapperPrototype(JSContext* ctx) +{ + static const JSCFunctionListEntry functions[] = { + JS_CFUNC_DEF("toString", 0, wrapperToString), + }; + + ValueRef proto(ctx, JS_NewObject(ctx)); + JS_SetPropertyFunctionList(ctx, proto, functions, SAL_N_ELEMENTS(functions)); + + JS_SetClassProto(ctx, getRuntimeData(ctx)->wrapperClassId, proto.release()); +} + +void initializeInterfacePrototype(JSContext* ctx) +{ + static const JSCFunctionListEntry functions[] = { + JS_CFUNC_DEF("getImportClassName", 0, interfaceGetImportClassName), + }; + + ValueRef proto(ctx, JS_NewObject(ctx)); + JS_SetPropertyFunctionList(ctx, proto, functions, SAL_N_ELEMENTS(functions)); + + JS_SetClassProto(ctx, getRuntimeData(ctx)->interfaceClassId, proto.release()); +} + +void initializeModulePrototype(JSContext* ctx) +{ + static const JSCFunctionListEntry functions[] = { + JS_CFUNC_DEF("getImportClassName", 0, moduleGetImportClassName), + }; + + ValueRef proto(ctx, JS_NewObject(ctx)); + JS_SetPropertyFunctionList(ctx, proto, functions, SAL_N_ELEMENTS(functions)); + + JS_SetClassProto(ctx, getRuntimeData(ctx)->moduleClassId, proto.release()); +} +} + +OUString jsuno::execute(OUString const& script, VariableList aGlobalVariables) +{ + auto const rt = JS_NewRuntime(); + JS_SetRuntimeOpaque(rt, new RuntimeData(rt)); + JS_NewClassID(rt, &getRuntimeData(rt)->pointerClassId); + JSClassDef pointerClass{ "InternalPointer", pointerFinalizer, nullptr, nullptr, nullptr }; + [[maybe_unused]] auto e = JS_NewClass(rt, getRuntimeData(rt)->pointerClassId, &pointerClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->wrapperClassId); + JSClassExoticMethods wrapperMethods{ + wrapperGetOwnProperty, nullptr /*TODO*/, nullptr, nullptr, nullptr, nullptr, + wrapperSetProperty + }; + JSClassDef wrapperClass{ "UnoWrapper", wrapperFinalizer, wrapperGCMark, nullptr, + &wrapperMethods }; + e = JS_NewClass(rt, getRuntimeData(rt)->wrapperClassId, &wrapperClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->enumeratorClassId); + JSClassDef enumeratorClass{ "UnoidlEnumerator", enumeratorFinalizer, nullptr, nullptr, + nullptr }; + e = JS_NewClass(rt, getRuntimeData(rt)->enumeratorClassId, &enumeratorClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->compoundClassId); + JSClassDef compoundClass{ "UnoStruct", compoundFinalizer, nullptr, nullptr, nullptr }; + e = JS_NewClass(rt, getRuntimeData(rt)->compoundClassId, &compoundClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->typeClassId); + JSClassDef typeClass{ "UnoType", typeFinalizer, nullptr, nullptr, nullptr }; + e = JS_NewClass(rt, getRuntimeData(rt)->typeClassId, &typeClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->enumClassId); + JSClassDef enumClass{ "UnoidlEnumType", enumFinalizer, nullptr, nullptr, nullptr }; + e = JS_NewClass(rt, getRuntimeData(rt)->enumClassId, &enumClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->structClassId); + JSClassDef structClass{ "UnoidlStructType", structFinalizer, nullptr, nullptr, nullptr }; + e = JS_NewClass(rt, getRuntimeData(rt)->structClassId, &structClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->exceptionClassId); + JSClassDef exceptionClass{ "UnoidlExceptionType", exceptionFinalizer, nullptr, nullptr, + nullptr }; + e = JS_NewClass(rt, getRuntimeData(rt)->exceptionClassId, &exceptionClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->interfaceClassId); + JSClassDef interfaceClass{ "UnoidlInterfaceType", interfaceFinalizer, nullptr, nullptr, + nullptr }; + e = JS_NewClass(rt, getRuntimeData(rt)->interfaceClassId, &interfaceClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->ctorClassId); + JSClassDef ctorClass{ "UnoidlSingleton", ctorFinalizer, nullptr, nullptr, nullptr }; + e = JS_NewClass(rt, getRuntimeData(rt)->ctorClassId, &ctorClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->singletonClassId); + JSClassDef singletonClass{ "UnoidlSingleton", singletonFinalizer, nullptr, nullptr, nullptr }; + e = JS_NewClass(rt, getRuntimeData(rt)->singletonClassId, &singletonClass); + assert(e == 0); //TODO + JS_NewClassID(rt, &getRuntimeData(rt)->moduleClassId); + JSClassExoticMethods moduleMethods{ + moduleGetOwnProperty, nullptr /*TODO*/, nullptr, nullptr, nullptr, nullptr, nullptr + }; + JSClassDef moduleClass{ "UnoidlModule", moduleFinalizer, moduleGCMark, nullptr, + &moduleMethods }; + e = JS_NewClass(rt, getRuntimeData(rt)->moduleClassId, &moduleClass); + assert(e == 0); //TODO + auto const ctx = JS_NewContext(rt); + initializeTypePrototype(ctx); + initializeEnumeratorPrototype(ctx); + initializeEnumPrototype(ctx); + initializeWrapperPrototype(ctx); + initializeInterfacePrototype(ctx); + initializeModulePrototype(ctx); + std::optional exc; + OUString result; + { + ValueRef const global(ctx, JS_GetGlobalObject(ctx)); + getRuntimeData(ctx)->symbolIteratorAtom = JS_ValueToAtom( + ctx, ValueRef(ctx, JS_GetPropertyStr( + ctx, ValueRef(ctx, JS_GetPropertyStr(ctx, global, "Symbol")), + "iterator"))); + ValueRef console(ctx, JS_NewObject(ctx)); + JS_SetPropertyStr(ctx, console, "assert", JS_NewCFunction(ctx, consoleAssert, "assert", 1)); + JS_SetPropertyStr(ctx, console, "log", JS_NewCFunction(ctx, consoleLog, "log", 0)); + JS_SetPropertyStr(ctx, global, "console", console.release()); + ValueRef uno(ctx, JS_NewObject(ctx)); + ValueRef type(ctx, JS_NewObject(ctx)); + setTypeProperty(ctx, type, "void", cppu::UnoType::get()); + setTypeProperty(ctx, type, "boolean", cppu::UnoType::get()); + setTypeProperty(ctx, type, "byte", cppu::UnoType::get()); + setTypeProperty(ctx, type, "short", cppu::UnoType::get()); + setTypeProperty(ctx, type, "unsigned_short", cppu::UnoType::get()); + setTypeProperty(ctx, type, "long", cppu::UnoType::get()); + setTypeProperty(ctx, type, "unsigned_long", cppu::UnoType::get()); + setTypeProperty(ctx, type, "hyper", cppu::UnoType::get()); + setTypeProperty(ctx, type, "unsigned_hyper", cppu::UnoType::get()); + setTypeProperty(ctx, type, "float", cppu::UnoType::get()); + setTypeProperty(ctx, type, "double", cppu::UnoType::get()); + setTypeProperty(ctx, type, "char", cppu::UnoType::get()); + setTypeProperty(ctx, type, "string", cppu::UnoType::get()); + setTypeProperty(ctx, type, "type", cppu::UnoType::get()); + setTypeProperty(ctx, type, "any", cppu::UnoType::get()); + JS_SetPropertyStr(ctx, type, "sequence", + JS_NewCFunction(ctx, unoTypeSequence, "sequence", 1)); + JS_SetPropertyStr(ctx, type, "enum", JS_NewCFunction(ctx, unoTypeEnum, "enum", 1)); + JS_SetPropertyStr(ctx, type, "struct", JS_NewCFunction(ctx, unoTypeStruct, "struct", 1)); + JS_SetPropertyStr(ctx, type, "exception", + JS_NewCFunction(ctx, unoTypeException, "exception", 1)); + JS_SetPropertyStr(ctx, type, "interface", + JS_NewCFunction(ctx, unoTypeInterface, "interface", 1)); + JS_SetPropertyStr(ctx, uno, "type", type.release()); + ValueRef idl(ctx, JS_NewObjectClass(ctx, getRuntimeData(ctx)->moduleClassId)); + e = JS_SetOpaque(idl, new ModuleData(ctx, u""_ustr)); +#if defined DBG_UTIL + getRuntimeData(ctx)->toFinalize.inc(); +#endif + assert(e == 0); //TODO + JS_SetPropertyStr(ctx, uno, "idl", idl.release()); + ValueRef anyProto(ctx, JS_NewObject(ctx)); + assert(!JS_IsException(anyProto)); //TODO + ValueRef anyCtor(ctx, JS_NewCFunction2(ctx, unoAny, "Any", 1, JS_CFUNC_constructor, 0)); + assert(!JS_IsException(anyCtor)); //TODO + JS_SetConstructor(ctx, anyCtor, anyProto); + JS_SetPropertyStr(ctx, uno, "Any", anyCtor.release()); + JS_SetPropertyStr(ctx, uno, "sameUnoObject", + JS_NewCFunction(ctx, sameUnoObject, "sameUnoObject", 2)); + JS_SetPropertyStr(ctx, uno, "componentContext", + wrapUnoObject(ctx, comphelper::getProcessComponentContext())); + JS_SetPropertyStr(ctx, global, "uno", uno.release()); + rhino_compatibility::setUp(ctx); + + for (const auto& rVariable : aGlobalVariables) + JS_SetPropertyStr(ctx, global, rVariable.first, wrapUnoObject(ctx, rVariable.second)); + + auto const input = script.toUtf8(); + ValueRef const evalRes( + ctx, JS_Eval(ctx, input.getStr(), input.getLength(), "", JS_EVAL_TYPE_GLOBAL)); + if (JS_IsException(evalRes)) + { + //TODO: reconstruct UNO exceptions + ValueRef const err(ctx, JS_GetException(ctx)); + assert(!JS_IsException(err)); //TODO? + exc = extractExceptionData(ctx, err); + } + else + { + ValueRef const json(ctx, JS_JSONStringify(ctx, evalRes, JS_UNDEFINED, JS_UNDEFINED)); + if (JS_IsException(json)) + { + // JSON.stringify itself can throw, e.g. on BigInt values or circular references: + ValueRef const err(ctx, JS_GetException(ctx)); + assert(!JS_IsException(err)); //TODO? + exc = extractExceptionData(ctx, err); + } + else if (!JS_IsUndefined(json)) + { + // Values that JSON.stringify drops (undefined, functions, symbols) come back as + // JS_UNDEFINED, for which we use an empty OUString: + std::size_t n; + UniqueCString16 const p(ctx, JS_ToCStringLenUTF16(ctx, &n, json)); + if (p.get() != nullptr) + { + result = OUString(p.get(), n); + } + } + } + } + JS_FreeContext(ctx); + std::unique_ptr data(getRuntimeData(rt)); + data->clear(); + JS_FreeRuntime(rt); + if (exc) + { + throw css::script::provider::ScriptExceptionRaisedException( + exc->message, {}, u""_ustr, u"JavaScript"_ustr, -1, exc->type); + } + return result; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/jsuno/source/jsvalue.hxx b/jsuno/source/jsvalue.hxx new file mode 100644 index 000000000000..68954597ea22 --- /dev/null +++ b/jsuno/source/jsvalue.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace jsuno +{ +class ValueRef +{ +public: + ValueRef(JSRuntime* rt, JSValue val = JS_UNINITIALIZED) + : rt_(rt) + , val_(val) + { + } + + ValueRef(JSContext* ctx, JSValue val = JS_UNINITIALIZED) + : ValueRef(JS_GetRuntime(ctx), val) + { + } + + ValueRef(ValueRef&& ref) + : rt_(ref.rt_) + , val_(ref.val_) + { + ref.val_ = JS_UNINITIALIZED; + } + + ~ValueRef() { JS_FreeValueRT(rt_, val_); } + + ValueRef& operator=(ValueRef&& ref) + { + assert(rt_ == ref.rt_); + JS_FreeValueRT(rt_, val_); + val_ = ref.val_; + ref.val_ = JS_UNINITIALIZED; + return *this; + } + + ValueRef& operator=(JSValue val) + { + JS_FreeValueRT(rt_, val_); + val_ = val; + return *this; + } + + operator JSValueConst() const { return val_; } + + JSValue dup() const { return JS_DupValueRT(rt_, val_); } + + JSValue release() + { + auto const val = val_; + val_ = JS_UNINITIALIZED; + return val; + } + + JSValue* ptr() { return &val_; } + +private: + ValueRef(ValueRef const&) = delete; + void operator=(ValueRef const&) = delete; + + JSRuntime* rt_; + JSValue val_; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/jsuno/source/rhinocompatibility.cxx b/jsuno/source/rhinocompatibility.cxx new file mode 100644 index 000000000000..ce497e7eb2fa --- /dev/null +++ b/jsuno/source/rhinocompatibility.cxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "rhinocompatibility.hxx" + +#include +#include + +#include "jsvalue.hxx" + +namespace jsuno::rhino_compatibility +{ +namespace +{ +JSValue importClass(JSContext* pContext, JSValueConst, int, JSValueConst* argv) +{ + JSAtom pGetImportClassName = JS_NewAtom(pContext, "getImportClassName"); + + jsuno::ValueRef sShortName(pContext, + JS_Invoke(pContext, argv[0], pGetImportClassName, 0, nullptr)); + JS_FreeAtom(pContext, pGetImportClassName); + + if (JS_IsException(sShortName)) + return JS_EXCEPTION; + + JSAtom pAtom = JS_ValueToAtom(pContext, sShortName); + if (pAtom == JS_ATOM_NULL) + return JS_EXCEPTION; + + const jsuno::ValueRef xGlobal(pContext, JS_GetGlobalObject(pContext)); + int nRet = JS_SetProperty(pContext, xGlobal, pAtom, JS_DupValue(pContext, argv[0])); + JS_FreeAtom(pContext, pAtom); + + return nRet == -1 ? JS_EXCEPTION : JS_UNDEFINED; +} + +JSValue unoRuntimeGetImportClassName(JSContext* pContext, JSValueConst, int, JSValueConst*) +{ + return JS_NewString(pContext, "UnoRuntime"); +} + +JSValue queryInterface(JSContext* pContext, JSValueConst, int, JSValueConst* argv) +{ + // Redirect UnoRuntime.queryInterface(a, b) to b.queryInterface(uno.type.interface(a)) + + jsuno::ValueRef xUnoTypeInterface(pContext, JS_GetGlobalObject(pContext)); + + for (const auto part : std::array{ "uno", "type", "interface" }) + { + JSAtom pAtom = JS_NewAtom(pContext, part); + xUnoTypeInterface = JS_GetProperty(pContext, xUnoTypeInterface, pAtom); + JS_FreeAtom(pContext, pAtom); + + if (JS_IsException(xUnoTypeInterface)) + return JS_EXCEPTION; + } + + jsuno::ValueRef xType(pContext, JS_Call(pContext, xUnoTypeInterface, JS_NULL, 1, argv)); + if (JS_IsException(xType)) + return JS_EXCEPTION; + + JSAtom pAtom = JS_NewAtom(pContext, "queryInterface"); + JSValueConst args[] = { xType }; + jsuno::ValueRef xRet(pContext, JS_Invoke(pContext, argv[1], pAtom, SAL_N_ELEMENTS(args), args)); + JS_FreeAtom(pContext, pAtom); + + return xRet.release(); +} +} + +void setUp(JSContext* pContext) +{ + // Make “Packages” an alias for “uno.idl” + const jsuno::ValueRef xGlobal(pContext, JS_GetGlobalObject(pContext)); + const jsuno::ValueRef xUno(pContext, JS_GetPropertyStr(pContext, xGlobal, "uno")); + assert(JS_IsObject(xUno)); + jsuno::ValueRef xIdl(pContext, JS_GetPropertyStr(pContext, xUno, "idl")); + assert(JS_IsObject(xIdl)); + JS_SetPropertyStr(pContext, xGlobal, "Packages", xIdl.release()); + + jsuno::ValueRef xImportClass(pContext, + JS_NewCFunction(pContext, importClass, "importClass", 1)); + JS_SetPropertyStr(pContext, xGlobal, "importClass", xImportClass.release()); +} + +jsuno::ValueRef createUnoRuntime(JSContext* pContext) +{ + jsuno::ValueRef xObject(pContext, JS_NewObject(pContext)); + if (JS_IsException(xObject)) + return xObject; + + static const JSCFunctionListEntry functions[] = { + JS_CFUNC_DEF("queryInterface", 2, queryInterface), + JS_CFUNC_DEF("getImportClassName", 0, unoRuntimeGetImportClassName), + }; + + ValueRef proto(pContext, JS_NewObject(pContext)); + JS_SetPropertyFunctionList(pContext, xObject, functions, SAL_N_ELEMENTS(functions)); + + return xObject; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/jsuno/source/rhinocompatibility.hxx b/jsuno/source/rhinocompatibility.hxx new file mode 100644 index 000000000000..4840b10c4999 --- /dev/null +++ b/jsuno/source/rhinocompatibility.hxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include "jsvalue.hxx" + +namespace jsuno::rhino_compatibility +{ +void setUp(JSContext* pContext); +jsuno::ValueRef createUnoRuntime(JSContext* pContext); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/jvmaccess/source/classpath.cxx b/jvmaccess/source/classpath.cxx index 95915196bad9..bb0b16bc0220 100644 --- a/jvmaccess/source/classpath.cxx +++ b/jvmaccess/source/classpath.cxx @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -76,6 +77,14 @@ jobjectArray jvmaccess::ClassPath::translateToUrls( nullptr, anyEx ); } } + css::uno::Reference< css::uri::XUriReference > uriRef( + css::uri::UriReferenceFactory::create(context)->parse(url)); + if (!uriRef.is() || !uriRef->getScheme().equalsIgnoreAsciiCase("file")) + { + throw css::lang::IllegalArgumentException( + "non-local Java class path entry: " + url, + css::uno::Reference< css::uno::XInterface >(), 0); + } jvalue arg; arg.l = environment->NewString( reinterpret_cast< jchar const * >(url.getStr()), diff --git a/jvmfwk/inc/fwkbase.hxx b/jvmfwk/inc/fwkbase.hxx index 61c3fa500138..b3ddd24f303d 100644 --- a/jvmfwk/inc/fwkbase.hxx +++ b/jvmfwk/inc/fwkbase.hxx @@ -16,8 +16,8 @@ * 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_JVMFWK_INC_FWKBASE_HXX -#define INCLUDED_JVMFWK_INC_FWKBASE_HXX + +#pragma once #include @@ -125,6 +125,4 @@ bool wasJavaSelectedInSameProcess(); OUString getApplicationClassPath(); } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/jvmfwk/inc/libxmlutil.hxx b/jvmfwk/inc/libxmlutil.hxx index 2599cff50596..5c298fd9f4da 100644 --- a/jvmfwk/inc/libxmlutil.hxx +++ b/jvmfwk/inc/libxmlutil.hxx @@ -16,8 +16,8 @@ * 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_JVMFWK_INC_LIBXMLUTIL_HXX -#define INCLUDED_JVMFWK_INC_LIBXMLUTIL_HXX + +#pragma once #include @@ -96,6 +96,5 @@ public: operator OString() { return reinterpret_cast(_object); } }; } -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/jvmfwk/inc/vendorplugin.hxx b/jvmfwk/inc/vendorplugin.hxx index 4c24903baa19..e0605d549097 100644 --- a/jvmfwk/inc/vendorplugin.hxx +++ b/jvmfwk/inc/vendorplugin.hxx @@ -18,8 +18,8 @@ */ /** @HTML */ -#ifndef INCLUDED_JVMFWK_INC_VENDORPLUGIN_HXX -#define INCLUDED_JVMFWK_INC_VENDORPLUGIN_HXX + +#pragma once #include #include @@ -240,6 +240,4 @@ javaPluginError jfw_plugin_startJavaVirtualMachine( */ javaPluginError jfw_plugin_existJRE(const JavaInfo *pInfo, bool *exist); -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/jvmfwk/plugins/sunmajor/pluginlib/sunjavaplugin.cxx b/jvmfwk/plugins/sunmajor/pluginlib/sunjavaplugin.cxx index 8031d426b6e8..3d1bb161b595 100644 --- a/jvmfwk/plugins/sunmajor/pluginlib/sunjavaplugin.cxx +++ b/jvmfwk/plugins/sunmajor/pluginlib/sunjavaplugin.cxx @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -577,7 +578,7 @@ static void do_msvcr_magic(OUString const &jvm_dll) }; char const* importName = reinterpret_cast(dos_hdr) + imports->Name + VAtoPhys; sal_Int32 importNameLen = rtl_str_getLength(importName); - for (size_t i = 0; i < SAL_N_ELEMENTS(msvcrts); ++i) + for (size_t i = 0; i < std::size(msvcrts); ++i) { if (0 == rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths( msvcrts[i].data(), msvcrts[i].size(), diff --git a/jvmfwk/plugins/sunmajor/pluginlib/sunversion.cxx b/jvmfwk/plugins/sunmajor/pluginlib/sunversion.cxx index 16a1e14f3662..6092ec746f7a 100644 --- a/jvmfwk/plugins/sunmajor/pluginlib/sunversion.cxx +++ b/jvmfwk/plugins/sunmajor/pluginlib/sunversion.cxx @@ -57,7 +57,7 @@ bool SunVersion::init(const char *szVersion) int nPartPos = 0; char buf[128]; - //char must me a number 0 - 999 and no leading + //char must be a number 0 - 999 and no leading while (true) { if (pCur < pEnd && rtl::isAsciiDigit(static_cast(*pCur))) diff --git a/jvmfwk/plugins/sunmajor/pluginlib/util.cxx b/jvmfwk/plugins/sunmajor/pluginlib/util.cxx index 995bda5084bf..6807f3574fc6 100644 --- a/jvmfwk/plugins/sunmajor/pluginlib/util.cxx +++ b/jvmfwk/plugins/sunmajor/pluginlib/util.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1162,21 +1163,21 @@ void addJavaInfosDirScan( #else // MACOSX OUString excMessage = u"[Java framework] sunjavaplugin: " "Error in function addJavaInfosDirScan in util.cxx."_ustr; - int cJavaNames= SAL_N_ELEMENTS(g_arJavaNames); + int cJavaNames = static_cast(std::size(g_arJavaNames)); std::unique_ptr sarJavaNames(new OUString[cJavaNames]); OUString *arNames = sarJavaNames.get(); for(int i= 0; i < cJavaNames; i++) arNames[i] = OUString(g_arJavaNames[i], strlen(g_arJavaNames[i]), RTL_TEXTENCODING_UTF8); - int cSearchPaths= SAL_N_ELEMENTS(g_arSearchPaths); + int cSearchPaths = static_cast(std::size(g_arSearchPaths)); std::unique_ptr sarPathNames(new OUString[cSearchPaths]); OUString *arPaths = sarPathNames.get(); for(int c = 0; c < cSearchPaths; c++) arPaths[c] = OUString(g_arSearchPaths[c], strlen(g_arSearchPaths[c]), RTL_TEXTENCODING_UTF8); - int cCollectDirs = SAL_N_ELEMENTS(g_arCollectDirs); + int cCollectDirs = static_cast(std::size(g_arCollectDirs)); std::unique_ptr sarCollectDirs(new OUString[cCollectDirs]); OUString *arCollectDirs = sarCollectDirs.get(); for(int d = 0; d < cCollectDirs; d++) diff --git a/l10ntools/source/cfgmerge.cxx b/l10ntools/source/cfgmerge.cxx index f1afb41f0cfd..b331f158b76a 100644 --- a/l10ntools/source/cfgmerge.cxx +++ b/l10ntools/source/cfgmerge.cxx @@ -169,9 +169,6 @@ void CfgParser::AddText( pStackData->sText[ rIsoLang ] = rText; } -#if defined _MSC_VER -#pragma warning(disable: 4702) // unreachable code, bug in MSVC2015, it thinks the std::exit is unreachable -#endif void CfgParser::ExecuteAnalyzedToken( int nToken, char *pToken ) { OString sToken( pToken ); diff --git a/l10ntools/source/localize.cxx b/l10ntools/source/localize.cxx index 29e482270c85..fbc4202f0001 100644 --- a/l10ntools/source/localize.cxx +++ b/l10ntools/source/localize.cxx @@ -334,7 +334,6 @@ bool includeProject(std::string_view rProject) { "reportdesign", "sc", "scaddins", - "sccomp", "scp2", "sd", "sdext", diff --git a/l10ntools/source/treemerge.cxx b/l10ntools/source/treemerge.cxx index 5dc6455e7018..e04cec2179fd 100644 --- a/l10ntools/source/treemerge.cxx +++ b/l10ntools/source/treemerge.cxx @@ -25,7 +25,7 @@ namespace { - // Extract strings from nodes on all level recursively + // Extract strings from nodes on all levels recursively void lcl_ExtractLevel( const xmlDocPtr pSource, const xmlNodePtr pRoot, const xmlChar* pNodeName, PoOfstream& rPOStream ) @@ -87,7 +87,7 @@ namespace OString::Concat(rXhpRoot) + sID.subView(sID.indexOf('/', nAfterSlash)); xmlDocPtr pXhpFile = xmlParseFile( sXhpPath.getStr() ); - // if xhpfile is missing than put this topic into comment + // if xhpfile is missing then put this topic into comment if ( !pXhpFile ) { xmlNodePtr pTemp = pReturn; @@ -235,7 +235,7 @@ void TreeParser::Extract( const OString& rPOFile ) if( !aPOStream.isOpen() ) { std::cerr - << "Treex error: Cannot open po file for extract: " + << "Treex error: Cannot open po file for extraction: " << rPOFile << std::endl; return; } diff --git a/l10ntools/source/xrmmerge.cxx b/l10ntools/source/xrmmerge.cxx index cd0500d14f87..d1453625b46c 100644 --- a/l10ntools/source/xrmmerge.cxx +++ b/l10ntools/source/xrmmerge.cxx @@ -397,7 +397,8 @@ void XRMResMerge::WorkOnDesc( sSearch = "xlink:href=\""_ostr; sReplace = sSearch; - const OString sLocDescFilename = sDescFilename.replaceFirst( "en-US"_ostr, sCur); + // for cases like desc_en_US.txt or desc_en-US.txt + const OString sLocDescFilename = sDescFilename.replaceFirst( "en-US"_ostr, sCur).replaceFirst( "en_US"_ostr, sCur); sSearch += sDescFilename; sReplace += sLocDescFilename; diff --git a/librelogo/README.md b/librelogo/README.md index 1cbc48611c16..47de8049b231 100644 --- a/librelogo/README.md +++ b/librelogo/README.md @@ -1,3 +1,3 @@ # LibreLogo Programming Language -LibreLogo is a Logo-like programming language with interactive vectorgraphics for education and DTP +LibreLogo is a Logo-like programming language with interactive vector graphics for education and DTP diff --git a/librelogo/source/LibreLogo/LibreLogo.py b/librelogo/source/LibreLogo/LibreLogo.py index e018d33ebdd1..85786dd20606 100644 --- a/librelogo/source/LibreLogo/LibreLogo.py +++ b/librelogo/source/LibreLogo/LibreLogo.py @@ -17,6 +17,7 @@ import itertools import threading import time as __time__ from math import pi, sin, cos, asin, hypot +from math import log10, sqrt # noqa: F401 from com.sun.star.awt import Point as __Point__ from com.sun.star.awt import Gradient as __Gradient__ @@ -203,6 +204,7 @@ __match_fontfeatures__ = re.compile( r"(', r'', r'<(i|em)>', r'', '', '', r'<(s|del)>', r'', '', '', '', '', r'<(fontcolor) ([^<>]*)>', r'', r'<(fillcolor) ([^<>]*)>', r'', r'<(fontfamily) ([^<>]*)>', r'', r'<(fontfeature) ([^<>]*)>', r']*)>', r'<(fontheight) ([^<>]*)>', r'']] +__lastdialogmessage__ = "" class __Doc__: def __init__(self, doc): @@ -373,6 +375,7 @@ def Print(s): __checkhalt__() def MessageBox(parent, message, title, msgtype = "messbox", buttons = __OK__): + global __lastdialogmessage__ msgtypes = ("messbox", "infobox", "errorbox", "warningbox", "querybox") if msgtype not in msgtypes: msgtype = "messbox" @@ -384,7 +387,7 @@ def MessageBox(parent, message, title, msgtype = "messbox", buttons = __OK__): d.WindowAttributes = buttons tk = parent.getToolkit() msgbox = tk.createWindow(d) - msgbox.MessageText = message + msgbox.MessageText = __lastdialogmessage__ = message if title: msgbox.CaptionText = title return msgbox.execute() @@ -611,6 +614,10 @@ class LogoProgram(threading.Thread): def __is_alive__(): return __thread__ is not None +# to check the message of the last dialog (MessageBox) presented by LibreLogo +def __last_dialog_message__(): + return __lastdialogmessage__ + def __encodestring__(m): __strings__.append(re.sub("(\\[^\\]|\\\\(?=[‘’“”»」』]))", "", m.group(2))) # replace the string with the numbered identifier _s_0___, _s_1___, ... @@ -1408,7 +1415,7 @@ def __get_HTML_format__(orig_st): if bit > 5 and (tag in extra_data): if bit == 9 and len(m.group(2)) > 0: # create a new list to keep the extra data of the previous characters, - # and remove the last occurance of the feature + # and remove the last occurrence of the feature z = list(extra_data[tag]) for j in reversed(range(len(z))): if z[j].startswith(m.group(2)): @@ -1894,6 +1901,7 @@ def __loadlang__(lang, a): if i[0:3] not in ["LIB", "ERR", "PT", "INC", "MM", "CM", "HOU", "DEG"] and i not in __STRCONST__: # uppercase native commands a[i] = a[i].upper() repcount = a['REPCOUNT'].split('|')[0] + repcount = re.sub("[ .']", '_', repcount) loopi = itertools.count() loop = lambda r: "%(i)s = 1\n%(orig)s%(j)s = %(i)s\n%(i)s += 1\n" % \ { "i": repcount + str(next(loopi)), "j": repcount, "orig": re.sub( r"(?ui)(?(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 298315d173ab..b9c8e3cf7704 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -1475,7 +1475,6 @@ callback (gpointer pData) case LOK_CALLBACK_CELL_SELECTION_AREA: case LOK_CALLBACK_CELL_AUTO_FILL_AREA: case LOK_CALLBACK_TABLE_SELECTED: - case LOK_CALLBACK_JSDIALOG: case LOK_CALLBACK_CALC_FUNCTION_LIST: case LOK_CALLBACK_TAB_STOP_LIST: case LOK_CALLBACK_FORM_FIELD_BUTTON: @@ -1493,7 +1492,6 @@ callback (gpointer pData) case LOK_CALLBACK_A11Y_CARET_CHANGED: case LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED: case LOK_CALLBACK_A11Y_FOCUSED_CELL_CHANGED: - case LOK_CALLBACK_COLOR_PALETTES: case LOK_CALLBACK_DOCUMENT_PASSWORD_RESET: case LOK_CALLBACK_A11Y_EDITING_IN_SELECTION_STATE: case LOK_CALLBACK_A11Y_SELECTION_CHANGED: diff --git a/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx b/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx index 7436455fadb0..f997a44b8873 100644 --- a/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx +++ b/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx @@ -166,7 +166,7 @@ void Hyphenator::ensureLocales() aSuppLocales = comphelper::containerToSequence(aLocalesVec); //! For each dictionary and each locale we need a separate entry. - //! If this results in more than one dictionary per locale than (for now) + //! If this results in more than one dictionary per locale then (for now) //! it is undefined which dictionary gets used. //! In the future the implementation should support using several dictionaries //! for one locale. @@ -429,7 +429,7 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo // pa: fields contain stems resulted by compound word analysis of non-dictionary words // hy: fields contain hyphenation data of dictionary (compound) words Reference< XSpellAlternatives > xTmpRes; - bool bAnalyzed = false; // enough the analyse once the word + bool bAnalyzed = false; // enough to analyse once the word bool bCompoundHyphenation = true; // try to hyphenate compound words better OUString sStems; // processed result of the compound word analysis, e.g. com|pound|word sal_Int32 nSuffixLen = 0; // do not remove break points in suffixes @@ -471,6 +471,7 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo // also skip hyphenation inside compound constituents right before constituent boundaries in compound words // or always skip hyphenation inside compound constituents, if minCompoundTrail == 0 // if both minCompoundLead and minCompoundTrail == 0, don't hyphenate inside suffixes, too + // if both minCompoundLead and minCompoundTrail >= 99, don't hyphenate inside suffixes, too if ( bCompoundHyphenation && (nCompoundHyphenationPos > -1 || minCompoundLead == 0 || minCompoundTrail > 2 || minCompoundTrail == 0 ) && // check minimal distance from the left constituent boundary ( ( minCompoundLead > 2 && i - nCompoundHyphenationPos < minCompoundLead ) || @@ -478,7 +479,8 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo ( minCompoundTrail > 2 && i - nCompoundHyphenationPos < minCompoundTrail ) || // special value: zero compound limit means forbidden hyphenation // inside (stems of) compound constituents - minCompoundLead == 0 || minCompoundTrail == 0 ) ) + minCompoundLead == 0 || minCompoundTrail == 0 || + minCompoundLead >= 99 || minCompoundTrail >= 99 ) ) { uno::Reference< XLinguServiceManager2 > xLngSvcMgr( GetLngSvcMgr_Impl() ); uno::Reference< XSpellChecker1 > xSpell; @@ -566,21 +568,58 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo break; } + // handle verb and leg-, legesleg- prefixes (Hungarian-only) + sal_Int32 nPrefixLen = 0; + if ( LANGUAGE_HUNGARIAN == nLanguage && sStems.isEmpty() ) + { + if ( aWord.startsWith(u"leg") && + morph.indexOf(u"ip:leg_") > -1 ) + { + sStems = aWord.replaceAt(3, 0, u"||"); + nPrefixLen = 5; + } + else if ( aWord.startsWith(u"legesleg") && + morph.indexOf(u"ip:legesleg_") > -1 ) + { + sStems = aWord.replaceAt(0, 8, u"leges||leg||"); + nPrefixLen = 12; + } + + if ( sStems.isEmpty() ) + { + static constexpr OUString sVERB_PREFIX = u"ip:PREF sp:"_ustr; + nPa = morph.indexOf(sVERB_PREFIX); + if ( nPa > -1 ) + { + nPa += sVERB_PREFIX.getLength(); + OUString sVerbPrefix = morph.getToken(0, ' ', nPa); + nPrefixLen = sVerbPrefix.getLength(); + if ( aWord.startsWith(sVerbPrefix) ) + sStems = aWord.replaceAt(nPrefixLen++, 0, u"|"); + } + } + } + // only hy:, but not pa: - if ( sStems.isEmpty() ) + if ( sStems.isEmpty() || nPrefixLen > 0 ) { // check hy: (pre-defined hyphenation) sal_Int32 nHy = morph.indexOf(" hy:"); if (nHy > -1) { - sStems = morph.getToken(1, ' ', nHy).copy(3); - if ( sStems.indexOf('|') == -1 && sStems.indexOf('-') == -1 ) + OUString sHy(morph.getToken(1, ' ', nHy).copy(3)); + if ( sHy.indexOf('|') == -1 && sHy.indexOf('-') == -1 ) { - if ( sal_Int32 nBreak = o3tl::toInt32(sStems) ) + if ( sal_Int32 nBreak = o3tl::toInt32(sHy) ) { - if ( nBreak < aWord.getLength() ) - sStems += OUString::Concat(aWord.subView(0, nBreak)) + u"|" + - aWord.subView(nBreak); + if ( sStems.isEmpty() ) + sStems = aWord; + else + // correction for Hungarian (e.g. "leg||meg|lepőbb") + nBreak += nPrefixLen; + if ( nBreak < sStems.getLength() ) + sStems = OUString::Concat(sStems.subView(0, nBreak)) + u"|" + + sStems.subView(nBreak); } } } @@ -589,7 +628,23 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo } } + // handle string separated by |, e.g "program hy:pro|gram" + // + // hyphenation at special lead/trail combinations over compound splitting + // + // +: hyphenation, -: no hyphenation + // + // lead | trail || non-compound | first constituent | suffix | + // ----------------------------------------------------------- + // 0 | 0 || + | + | - | + // 0 | x || + | + | + | + // x | 0 || + | + | + | + // x | x || + | + | + | + // 0 | 99<= || - | - | + | + // 99<= | 0 || - | - | + | + // 99<= | 99<= || - | - | - | + // if ( sStems.indexOf('|') > -1 ) { sal_Int32 nLetters = 0; // count not separator characters @@ -613,13 +668,15 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo // too close to the left break point or special case? ( i - nCompoundHyphenationPos < minCompoundLead || minCompoundLead == 0 ) && // there is a stem boundary before the actual break point - nSepPos > -1 && + // or special values: disable hyphenation in the first constituent, too + ( nSepPos > -1 || minCompoundLead == 99 || minCompoundTrail == 99 ) && // and the break point is within a stem, i.e. not in the // suffix of the last stem or both minCompoundLead and // minCompoundTrail == 0, i.e. hyphenation is allowed only // at compound constituent boundaries ( i < aWord.getLength() - nSuffixLen - 1 || - ( minCompoundLead == 0 && minCompoundTrail == 0) ) && + ( minCompoundLead == 0 && minCompoundTrail == 0 ) || + ( minCompoundLead >= 99 && minCompoundTrail >= 99 ) ) && // and it is not another stem boundary j + 1 < sStems.getLength() && ( sStems[j] != u'|' || @@ -630,7 +687,7 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo continue; } // skip break points near before the stem boundaries - // (hit is not mandatory, only compondhit, because the + // (hit is not mandatory, only compoundhit, because the // compound boundary can be after the lead limit) if (!hit && // too close to the right break point? @@ -640,7 +697,8 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo // minCompoundTrail == 0, i.e. hyphenation is allowed only // at compound constituent boundaries ( i < aWord.getLength() - nSuffixLen - 1 || - ( minCompoundLead == 0 && minCompoundTrail == 0) ) && + ( minCompoundLead == 0 && minCompoundTrail == 0) || + ( minCompoundLead >= 99 && minCompoundTrail >= 99 ) ) && // and it is a stem boundary j + 1 < sStems.getLength() && sStems[j+1] == u'|' && // the previous break point is not a boundary @@ -654,8 +712,15 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo bPrevCompound = nSepPos == j || nSepPos == j - 1; } else + { // not a compound word + + // special value: 99<= : if it is not a compound word, do not hyphenate it + if ( minCompoundLead >= 99 || minCompoundTrail >= 99 ) + return nullptr; + bCompoundHyphenation = false; + } } else // no SPELLML support, no morphological analysis diff --git a/lingucomponent/source/spellcheck/spell/sspellimp.cxx b/lingucomponent/source/spellcheck/spell/sspellimp.cxx index 153ce18ec2be..db1beb9a7d65 100644 --- a/lingucomponent/source/spellcheck/spell/sspellimp.cxx +++ b/lingucomponent/source/spellcheck/spell/sspellimp.cxx @@ -48,6 +48,7 @@ #include #include +#include #include #include #include @@ -228,19 +229,10 @@ sal_Bool SAL_CALL SpellChecker::hasLocale(const Locale& rLocale) { MutexGuard aGuard( GetLinguMutex() ); - bool bRes = false; if (!m_aSuppLocales.hasElements()) getLocales(); - for (auto const& suppLocale : m_aSuppLocales) - { - if (rLocale == suppLocale) - { - bRes = true; - break; - } - } - return bRes; + return (std::ranges::find(m_aSuppLocales, rLocale) != m_aSuppLocales.end()); } #define SPELL_NON_ASCII_APOSTROPHE 1 << 10 diff --git a/linguistic/Library_lng.mk b/linguistic/Library_lng.mk index 4991163ed070..2cc4e317067c 100644 --- a/linguistic/Library_lng.mk +++ b/linguistic/Library_lng.mk @@ -77,7 +77,6 @@ $(eval $(call gb_Library_add_exception_objects,lng,\ linguistic/source/spelldsp \ linguistic/source/spelldta \ linguistic/source/thesdsp \ - $(if $(ENABLE_CURL),linguistic/source/translate) \ )) # vim: set noet sw=4 ts=4: diff --git a/linguistic/source/hyphdsp.cxx b/linguistic/source/hyphdsp.cxx index d04c3a9b668b..654e2d833695 100644 --- a/linguistic/source/hyphdsp.cxx +++ b/linguistic/source/hyphdsp.cxx @@ -287,7 +287,7 @@ Reference< XHyphenatedWord > SAL_CALL { OUString aChkWord( rWord ); - // replace typographical apostroph by ascii apostroph + // replace typographical apostrophe by ascii apostrophe OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() ); DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpected length of quotation mark" ); if (!aSingleQuote.isEmpty()) @@ -422,7 +422,7 @@ Reference< XHyphenatedWord > SAL_CALL { OUString aChkWord( rWord ); - // replace typographical apostroph by ascii apostroph + // replace typographical apostrophe by ascii apostrophe OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() ); DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpected length of quotation mark" ); if (!aSingleQuote.isEmpty()) @@ -547,7 +547,7 @@ Reference< XPossibleHyphens > SAL_CALL { OUString aChkWord( rWord ); - // replace typographical apostroph by ascii apostroph + // replace typographical apostrophe by ascii apostrophe OUString aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() ); DBG_ASSERT( 1 == aSingleQuote.getLength(), "unexpected length of quotation mark" ); if (!aSingleQuote.isEmpty()) diff --git a/linguistic/source/lngopt.cxx b/linguistic/source/lngopt.cxx index 3c845b2b9d3d..11c7699414a8 100644 --- a/linguistic/source/lngopt.cxx +++ b/linguistic/source/lngopt.cxx @@ -18,6 +18,7 @@ */ +#include #include #include "lngopt.hxx" #include @@ -87,7 +88,7 @@ struct WID_Name } -//! order of entries is import (see LinguOptions::GetName) +//! order of entries is important (see LinguOptions::GetName) //! since the WID is used as index in this table! constexpr WID_Name aWID_Name[] = { @@ -125,7 +126,7 @@ OUString LinguOptions::GetName( sal_Int32 nWID ) OUString aRes; - if (0 <= nWID && o3tl::make_unsigned(nWID) < SAL_N_ELEMENTS(aWID_Name) + if (0 <= nWID && o3tl::make_unsigned(nWID) < std::size(aWID_Name) && aWID_Name[ nWID ].nWID == nWID) aRes = aWID_Name[nWID].aPropertyName; else diff --git a/linguistic/source/lngsvcmgr.cxx b/linguistic/source/lngsvcmgr.cxx index 2666b6b9230d..e3cd738ff51b 100644 --- a/linguistic/source/lngsvcmgr.cxx +++ b/linguistic/source/lngsvcmgr.cxx @@ -578,7 +578,7 @@ namespace std::vector aRes; aRes.reserve(rCfgSvcs.getLength()); - std::copy_if(rCfgSvcs.begin(), rCfgSvcs.end(), std::back_inserter(aRes), + std::ranges::copy_if(rCfgSvcs, std::back_inserter(aRes), [&rAvailSvcs](const OUString& entry) { return lcl_SeqHasString(rAvailSvcs, entry); }); return comphelper::containerToSequence(aRes); @@ -591,7 +591,7 @@ namespace std::vector aRes; aRes.reserve(rAvailSvcs.getLength()); - std::copy_if(rAvailSvcs.begin(), rAvailSvcs.end(), std::back_inserter(aRes), + std::ranges::copy_if(rAvailSvcs, std::back_inserter(aRes), [&rLastFoundSvcs](const OUString& rEntry) { return !rEntry.isEmpty() && !lcl_FindEntry( rEntry, rLastFoundSvcs ); }); @@ -612,7 +612,7 @@ namespace // new found services at the end for (const Sequence< OUString > &rSeq : { rCfgSvcs, rNewSvcs }) { - std::copy_if(rSeq.begin(), rSeq.end(), std::back_inserter(aRes), lVecNotHasString); + std::ranges::copy_if(rSeq, std::back_inserter(aRes), lVecNotHasString); } return comphelper::containerToSequence(aRes); diff --git a/linguistic/source/misc2.cxx b/linguistic/source/misc2.cxx index 6464a0cbce74..4c9e3c7fb9a5 100644 --- a/linguistic/source/misc2.cxx +++ b/linguistic/source/misc2.cxx @@ -119,10 +119,10 @@ static std::vector< OUString > GetMultiPaths_Impl( auto lPathIsNotEmpty = [](const OUString& rPath) { return !rPath.isEmpty(); }; if (nPathFlags & DictionaryPathFlags::USER) - std::copy_if(std::cbegin(aUserPaths), std::cend(aUserPaths), std::back_inserter(aRes), lPathIsNotEmpty); + std::ranges::copy_if(aUserPaths, std::back_inserter(aRes), lPathIsNotEmpty); if (nPathFlags & DictionaryPathFlags::INTERNAL) - std::copy_if(std::cbegin(aInternalPaths), std::cend(aInternalPaths), std::back_inserter(aRes), lPathIsNotEmpty); + std::ranges::copy_if(aInternalPaths, std::back_inserter(aRes), lPathIsNotEmpty); } return aRes; diff --git a/linguistic/source/spelldsp.hxx b/linguistic/source/spelldsp.hxx index a479f7bc7296..44714eeaa8c6 100644 --- a/linguistic/source/spelldsp.hxx +++ b/linguistic/source/spelldsp.hxx @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/linguistic/source/translate.cxx b/linguistic/source/translate.cxx deleted file mode 100644 index acc811e63f2d..000000000000 --- a/linguistic/source/translate.cxx +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace linguistic -{ -OString Translate(const OString& rTargetLang, const OString& rAPIUrl, const OString& rAuthKey, - const OString& rData) -{ - constexpr tools::Long CURL_TIMEOUT = 10L; - - std::unique_ptr> curl(curl_easy_init(), - [](CURL* p) { curl_easy_cleanup(p); }); - - ::InitCurl_easy(curl.get()); - - (void)curl_easy_setopt(curl.get(), CURLOPT_URL, rAPIUrl.getStr()); - (void)curl_easy_setopt(curl.get(), CURLOPT_FAILONERROR, 1L); - (void)curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, CURL_TIMEOUT); - - std::string response_body; - (void)curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, - +[](void* buffer, size_t size, size_t nmemb, void* userp) -> size_t { - if (!userp) - return 0; - std::string* response = static_cast(userp); - size_t real_size = size * nmemb; - response->append(static_cast(buffer), real_size); - return real_size; - }); - (void)curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, static_cast(&response_body)); - OString aLang(curl_easy_escape(curl.get(), rTargetLang.getStr(), rTargetLang.getLength())); - OString aAuthKey(curl_easy_escape(curl.get(), rAuthKey.getStr(), rAuthKey.getLength())); - OString aData(curl_easy_escape(curl.get(), rData.getStr(), rData.getLength())); - OString aPostData("auth_key=" + aAuthKey + "&target_lang=" + aLang + "&text=" + aData); - - (void)curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, aPostData.getStr()); - CURLcode cc = curl_easy_perform(curl.get()); - if (cc != CURLE_OK) - { - SAL_WARN("linguistic", - "Translate: CURL perform returned with error: " << static_cast(cc)); - return {}; - } - tools::Long nStatusCode; - curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &nStatusCode); - if (nStatusCode != 200) - { - SAL_WARN("linguistic", - "Translate: CURL request returned with status code: " << nStatusCode); - return {}; - } - // parse the response - boost::property_tree::ptree root; - std::stringstream aStream(response_body.data()); - boost::property_tree::read_json(aStream, root); - boost::property_tree::ptree& translations = root.get_child("translations"); - size_t size = translations.size(); - if (size <= 0) - { - SAL_WARN("linguistic", "Translate: API did not return any translations"); - return {}; - } - // take the first one - const boost::property_tree::ptree& translation = translations.begin()->second; - const std::string text = translation.get("text"); - return OString(text); -} -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/linguistic/workben/sprophelp.cxx b/linguistic/workben/sprophelp.cxx index f6326ba55fee..b9f77fe51159 100644 --- a/linguistic/workben/sprophelp.cxx +++ b/linguistic/workben/sprophelp.cxx @@ -18,6 +18,7 @@ */ +#include #include #include "linguistic/misc.hxx" @@ -175,7 +176,7 @@ static const char *aSP[] = PropertyHelper_Spell::PropertyHelper_Spell( const Reference< XInterface > & rxSource, Reference< XPropertySet > &rxPropSet ) : - PropertyChgHelper ( rxSource, rxPropSet, aSP, SAL_N_ELEMENTS(aSP) ) + PropertyChgHelper ( rxSource, rxPropSet, aSP, static_cast(std::size(aSP)) ) { SetDefault(); sal_Int32 nLen = GetPropNames().getLength(); diff --git a/lotuswordpro/inc/xfilter/xfparastyle.hxx b/lotuswordpro/inc/xfilter/xfparastyle.hxx index ac16d3ba1f0b..e71870cefa2a 100644 --- a/lotuswordpro/inc/xfilter/xfparastyle.hxx +++ b/lotuswordpro/inc/xfilter/xfparastyle.hxx @@ -56,8 +56,8 @@ /************************************************************************* * @file * Styles for paragraph. - * Styles for paragraph may include many style,include font,indent,margin, - * shadow,line height,and so on. + * Styles for paragraph may include many styles, including font, indent, margin, + * shadow, line height, and so on. ************************************************************************/ #ifndef INCLUDED_LOTUSWORDPRO_INC_XFILTER_XFPARASTYLE_HXX #define INCLUDED_LOTUSWORDPRO_INC_XFILTER_XFPARASTYLE_HXX @@ -89,7 +89,7 @@ class XFBGImage; /** * @brief - * Style object for aragraph. + * Style object for paragraph. */ class XFParaStyle : public XFStyle { @@ -114,7 +114,7 @@ public: /** * @descr set the paragraph default font. * @param font object to be set. Font object is deleted by font-factory, so - * don't delete it in the destructure function of para style. + * don't delete it in the destructor function of para style. */ void SetFont(rtl::Reference const & font); @@ -125,14 +125,14 @@ public: /** * @descr Set the indent of the paragraph. This is the indent for - the first line. + * the first line. * @param indent value of the first-line indent. */ void SetIndent(double indent ); /** * @descr Set the padding of the paragraph. This is the distance - between the border and the top of the text. + * between the border and the top of the text. * @param indent value of the padding. */ void SetPadding(double left, double right, double top, double bottom); @@ -140,7 +140,7 @@ public: /** * @descr Set the Margins of the paragraph. * @param -1: don't change. - other: set value. + * other: set value. */ void SetMargins(double left, double right,double top=-1, double bottom=-1); @@ -152,7 +152,7 @@ public: /** * @descr Set the shadow of the paragraph. There are 4 positions, you - can find it in the definition of enumShadowPos. + * can find it in the definition of enumShadowPos. * @param pos * @param offset the distance between the paragraph border and the shadow. * @param color color to fill the shadow. @@ -161,8 +161,8 @@ public: /** * @descr The borders is complex, so you have to create one before use. - Very few paragraphs will already have borders property, this way - we can save much memory. + * Very few paragraphs will already have borders property, this way + * we can save much memory. * @param pBorders borders of the paragraph, please reference the XFBorders. */ void SetBorders(XFBorders *pBorders); @@ -189,12 +189,12 @@ public: /** * @descr Set background image of the paragraph. - * @param image the background image to set. + * @param rImage the background image to set. */ void SetBackImage(std::unique_ptr& rImage); /** - * descr You can only set one break property for every para style object. + * @descr You can only set one break property for every para style object. */ void SetBreaks(enumXFBreaks breaks); diff --git a/lotuswordpro/qa/cppunit/import_test.cxx b/lotuswordpro/qa/cppunit/import_test.cxx index 547c8883ee9d..6c318f9409e1 100644 --- a/lotuswordpro/qa/cppunit/import_test.cxx +++ b/lotuswordpro/qa/cppunit/import_test.cxx @@ -39,7 +39,7 @@ CPPUNIT_TEST_FIXTURE(LotusWordProTest, testtdf33787OrderedBullets) // A. Lettered bullet uppercase 1 (A.) // B. Lettered bullet uppercase 2 (B.) // C. Lettered bullet uppercase 3 (C.) - // It is also make sure that nested and skipped bullets are working correctly: + // It also makes sure that nested and skipped bullets are working correctly: // 1) Numbered bullet w/ bracket one (1)) // Skipped bullet // 2) Numbered bullet w/ bracket two (2)) @@ -54,7 +54,7 @@ CPPUNIT_TEST_FIXTURE(LotusWordProTest, testtdf33787OrderedBullets) uno::Reference xPara(xParaEnum->nextElement(), uno::UNO_QUERY); OUString aListLabelString; xPara->getPropertyValue(u"ListLabelString"_ustr) >>= aListLabelString; - // Make sure the list start from 1. + // Make sure the list starts from 1. CPPUNIT_ASSERT_EQUAL(u"1."_ustr, aListLabelString); xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY); xPara->getPropertyValue(u"ListLabelString"_ustr) >>= aListLabelString; @@ -69,7 +69,7 @@ CPPUNIT_TEST_FIXTURE(LotusWordProTest, testtdf33787OrderedBullets) xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY); xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY); xPara->getPropertyValue(u"ListLabelString"_ustr) >>= aListLabelString; - // Make sure the list start from i. + // Make sure the list starts from i. CPPUNIT_ASSERT_EQUAL(u"i."_ustr, aListLabelString); xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY); @@ -85,7 +85,7 @@ CPPUNIT_TEST_FIXTURE(LotusWordProTest, testtdf33787OrderedBullets) xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY); xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY); xPara->getPropertyValue(u"ListLabelString"_ustr) >>= aListLabelString; - // Make sure the list start from I. + // Make sure the list starts from I. CPPUNIT_ASSERT_EQUAL(u"I."_ustr, aListLabelString); xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY); @@ -185,7 +185,7 @@ CPPUNIT_TEST_FIXTURE(LotusWordProTest, paragraphProperties) xPropertySet3->getPropertyValue(u"CharUnderline"_ustr) >>= nCharUnderline; CPPUNIT_ASSERT_EQUAL(awt::FontUnderline::SINGLE, nCharUnderline); - // striked through + // struck through uno::Reference const xParagraph4(xParaEnum->nextElement(), uno::UNO_QUERY_THROW); uno::Reference xPropertySet4(xParagraph4, uno::UNO_QUERY); diff --git a/lotuswordpro/source/filter/explode.cxx b/lotuswordpro/source/filter/explode.cxx index 72d0a8925557..e815544d75c7 100644 --- a/lotuswordpro/source/filter/explode.cxx +++ b/lotuswordpro/source/filter/explode.cxx @@ -177,7 +177,7 @@ sal_uInt32 Decompression::ReadBits(sal_uInt16 iCount, sal_uInt32 & nBits) return 1; } - /* load at least need bits into val */ + /* load at least needed bits into val */ sal_uInt32 val = m_nCurrent4Byte; /* bit accumulator */ while (m_nBitsLeft < iCount) { @@ -192,11 +192,11 @@ sal_uInt32 Decompression::ReadBits(sal_uInt16 iCount, sal_uInt32 & nBits) m_nBitsLeft += 8; } - /* drop need bits and update buffer, always zero to seven bits left */ + /* drop needed bits and update buffer, always zero to seven bits left */ m_nCurrent4Byte = val >> iCount; m_nBitsLeft -= iCount; - /* return need bits, zeroing the bits above that */ + /* return needed bits, zeroing the bits above that */ nBits = val & ((1U << iCount) - 1); return 0; @@ -248,7 +248,7 @@ sal_Int32 Decompression::explode() continue; } // if the bit is 1 we have here a length/distance pair: - // -decode a number with Hufmman Tree #1; variable bit length, result is 0x00 .. 0x0F -> L1 + // -decode a number with Huffman Tree #1; variable bit length, result is 0x00 .. 0x0F -> L1 sal_uInt32 L1 = Decode(m_Tree1.get()); sal_uInt32 Length; if (L1 <= 7) @@ -273,7 +273,7 @@ sal_Int32 Decompression::explode() break; } - // - decode another number with Hufmann Tree #2 giving result 0x00..0x3F -> D1 + // - decode another number with Huffman Tree #2 giving result 0x00..0x3F -> D1 sal_uInt32 D1 = Decode(m_Tree2.get()); sal_uInt32 D2; if (Length == 2) diff --git a/lotuswordpro/source/filter/lwpfootnote.cxx b/lotuswordpro/source/filter/lwpfootnote.cxx index c413659cf6ff..6f87741dbc38 100644 --- a/lotuswordpro/source/filter/lwpfootnote.cxx +++ b/lotuswordpro/source/filter/lwpfootnote.cxx @@ -131,7 +131,7 @@ void LwpFribFootnote::XFConvert(XFContentContainer* pCont) } /** - * @descr Get foonote object + * @descr Get footnote object */ LwpFootnote* LwpFribFootnote::GetFootnote() { @@ -148,7 +148,7 @@ LwpFootnote::LwpFootnote(LwpObjectHeader const& objHdr, LwpSvStream* pStrm) LwpFootnote::~LwpFootnote() {} /** - * @descr Read foonote object + * @descr Read footnote object */ void LwpFootnote::Read() { @@ -212,7 +212,7 @@ LwpCellLayout* LwpFootnote::GetCellLayout() } /** - * @descr Get division which footnote table contains current footnote content, copy from lwp source code + * @descr Get division whose footnote table contains current footnote content, copy from lwp source code */ LwpDocument* LwpFootnote::GetFootnoteTableDivision() { @@ -287,7 +287,7 @@ LwpDocument* LwpFootnote::GetFootnoteTableDivision() } /** - * @descr Get division which endnote table contains current endnote content, copy from lwp source code + * @descr Get division whose endnote table contains current endnote content, copy from lwp source code */ LwpDocument* LwpFootnote::GetEndnoteDivision(LwpDocument* pPossible) { @@ -378,7 +378,7 @@ LwpContent* LwpFootnote::FindFootnoteContent() { LwpContent* pContent = dynamic_cast(m_Content.obj().get()); //if the content has layout, the content has footnote contents; - //or looking for the celllayout and return the footnote contents. + //or look for the celllayout and return the footnote contents. if (pContent && pContent->GetLayout(nullptr).is()) return pContent; diff --git a/lotuswordpro/source/filter/lwpfribtext.cxx b/lotuswordpro/source/filter/lwpfribtext.cxx index 11a23bbda4ae..04e966786d7f 100644 --- a/lotuswordpro/source/filter/lwpfribtext.cxx +++ b/lotuswordpro/source/filter/lwpfribtext.cxx @@ -108,7 +108,7 @@ void LwpFribText::XFConvert(XFContentContainer* pXFPara,LwpStory* pStory) } /** - * @short: Reading mothed of paranumber frib. + * @short: Reading method of paranumber frib. * @param: pObjStrm wordpro object stream. * @param: len length of the frib */ @@ -134,7 +134,7 @@ LwpFribDocVar::~LwpFribDocVar() { } /** - * @short: Reading mothed of document variable frib. + * @short: Reading method of document variable frib. * @param: pObjStrm wordpro object stream. * @param: len length of the frib */ diff --git a/lotuswordpro/source/filter/lwpnotes.cxx b/lotuswordpro/source/filter/lwpnotes.cxx index 273013dba18a..91bc8bd69435 100644 --- a/lotuswordpro/source/filter/lwpnotes.cxx +++ b/lotuswordpro/source/filter/lwpnotes.cxx @@ -88,7 +88,7 @@ void LwpFribNote::RegisterNewStyle() { //register font style LwpFrib::RegisterStyle(m_pPara->GetFoundry()); - //register foonote style + //register note style pLayout->SetFoundry(m_pPara->GetFoundry()); pLayout->DoRegisterStyle(); } @@ -207,7 +207,7 @@ OUString LwpNoteLayout::GetAuthor() return m_UserName.str(); } } - //if username is null or writerspace, get username from noteheaderlayout + //if username is null or whitespace, get username from noteheaderlayout LwpNoteHeaderLayout* pTextLayout = static_cast(FindChildByType(LWP_NOTEHEADER_LAYOUT)); if (pTextLayout) diff --git a/lotuswordpro/source/filter/lwppagelayout.cxx b/lotuswordpro/source/filter/lwppagelayout.cxx index d782e3d5404d..a487f4b83417 100644 --- a/lotuswordpro/source/filter/lwppagelayout.cxx +++ b/lotuswordpro/source/filter/lwppagelayout.cxx @@ -720,7 +720,7 @@ bool LwpPageLayout::operator<(LwpPageLayout& Other) { if (pThisPara == pOtherPara) { - //If the two layouts in the same para, compare which layout is earlied according to frib order + //If the two layouts in the same para, compare which layout is earlier according to frib order return pThisPara->ComparePagePosition(this, &Other); } else @@ -812,14 +812,14 @@ void LwpHeaderLayout::ParseMargins(XFHeaderStyle* ph1) //left margin in SODC: the space from the left edge of body to the left edge of header double left = GetMarginsValue(MARGIN_LEFT) - (parent ? parent->GetMarginsValue(MARGIN_LEFT) : 0); - if (left <= 0) //The left margin in SODC can not be minus value + if (left <= 0) //The left margin in SODC can not be a negative value { left = -1; } - //left margin in SODC: the space from the right edge of header to the right edge of body + //right margin in SODC: the space from the right edge of header to the right edge of body double right = GetMarginsValue(MARGIN_RIGHT) - (parent ? parent->GetMarginsValue(MARGIN_RIGHT) : 0); - if (right <= 0) //The right margin in SODC can not be minus value + if (right <= 0) //The right margin in SODC can not be a negative value { right = -1; } @@ -959,7 +959,7 @@ void LwpFooterLayout::RegisterStyle(XFPageMaster* pm1) void LwpFooterLayout::ParseMargins(XFFooterStyle* pFooterStyle) { - //Set height: from top of header to top of body, including the spacing between header and body + //Set height: from bottom of footer to bottom of body, including the spacing between footer and body double height = GetGeometryHeight() - GetMarginsValue(MARGIN_BOTTOM); if (IsAutoGrowUp()) { @@ -974,13 +974,13 @@ void LwpFooterLayout::ParseMargins(XFFooterStyle* pFooterStyle) LwpMiddleLayout* parent = dynamic_cast(GetParent().obj().get()); double left = GetMarginsValue(MARGIN_LEFT) - (parent ? parent->GetMarginsValue(MARGIN_LEFT) : 0); - if (left <= 0) //The left margin in SODC can not be minus value + if (left <= 0) //The left margin in SODC can not be a negative value { left = -1; } double right = GetMarginsValue(MARGIN_RIGHT) - (parent ? parent->GetMarginsValue(MARGIN_RIGHT) : 0); - if (right <= 0) //The left margin in SODC can not be minus value + if (right <= 0) //The right margin in SODC can not be a negative value { right = -1; } diff --git a/lotuswordpro/source/filter/lwppara1.cxx b/lotuswordpro/source/filter/lwppara1.cxx index cfd801cc07f4..32dba4e28a2f 100644 --- a/lotuswordpro/source/filter/lwppara1.cxx +++ b/lotuswordpro/source/filter/lwppara1.cxx @@ -549,7 +549,7 @@ bool LwpPara::operator< (LwpPara const & Other) } /** -* @descr: If the two layouts in the same para, compare which layout is earlied according to frib order +* @descr: If the two layouts are in the same para, compare which layout is earlier according to frib order * */ bool LwpPara::ComparePagePosition(LwpVirtualLayout const * pPreLayout, LwpVirtualLayout const * pNextLayout) diff --git a/lotuswordpro/source/filter/lwpstory.cxx b/lotuswordpro/source/filter/lwpstory.cxx index 540afd3dc661..8de8757c07b1 100644 --- a/lotuswordpro/source/filter/lwpstory.cxx +++ b/lotuswordpro/source/filter/lwpstory.cxx @@ -233,10 +233,7 @@ void LwpStory::SortPageLayout() //put all the sorted layouts into list m_LayoutList.clear(); - for (auto const& layout : aLayoutList) - { - m_LayoutList.push_back(layout); - } + m_LayoutList.insert(m_LayoutList.end(), aLayoutList.begin(), aLayoutList.end()); } /************************************************************************** diff --git a/lotuswordpro/source/filter/xfilter/xfheaderstyle.cxx b/lotuswordpro/source/filter/xfilter/xfheaderstyle.cxx index 68882274171a..137aa18ef2aa 100644 --- a/lotuswordpro/source/filter/xfilter/xfheaderstyle.cxx +++ b/lotuswordpro/source/filter/xfilter/xfheaderstyle.cxx @@ -55,7 +55,7 @@ ************************************************************************/ /************************************************************************* * @file - * Header style,exist in page-master object. + * Header style, exist in page-master object. ************************************************************************/ #include #include diff --git a/lotuswordpro/source/filter/xfilter/xftabstyle.cxx b/lotuswordpro/source/filter/xfilter/xftabstyle.cxx index c3da354f7066..b099bae812ca 100644 --- a/lotuswordpro/source/filter/xfilter/xftabstyle.cxx +++ b/lotuswordpro/source/filter/xfilter/xftabstyle.cxx @@ -55,7 +55,7 @@ ************************************************************************/ /************************************************************************* * @file - * Tab style for paragraph.include tab offset and tab char properties. + * Tab style for paragraph. Include tab offset and tab char properties. ************************************************************************/ #include "xftabstyle.hxx" #include diff --git a/lotuswordpro/source/filter/xfilter/xftextspan.cxx b/lotuswordpro/source/filter/xfilter/xftextspan.cxx index c3ea62ace9f3..c0e7273608b1 100644 --- a/lotuswordpro/source/filter/xfilter/xftextspan.cxx +++ b/lotuswordpro/source/filter/xfilter/xftextspan.cxx @@ -55,7 +55,7 @@ ************************************************************************/ /************************************************************************* * @file - * An span of text with style. + * A span of text with style. ************************************************************************/ #include #include diff --git a/o3tl/README.md b/o3tl/README.md index dccfc6028d91..94b6d1b96951 100644 --- a/o3tl/README.md +++ b/o3tl/README.md @@ -17,12 +17,6 @@ to boost, but isn't as of now)." A copy-on-write wrapper. -- `[git:include/o3tl/lazy_update.hxx]` - - This template collects data in input type, and updates the output type with the given update functor, - but only if the output is requested. Useful if updating is expensive, or input changes frequently, but - output is only comparatively seldom used. - - `[git:include/o3tl/vector_pool.hxx]` Simple vector-based memory pool allocator. diff --git a/o3tl/qa/cow_wrapper_clients.cxx b/o3tl/qa/cow_wrapper_clients.cxx index a72e8a50275f..f2c40315ae72 100644 --- a/o3tl/qa/cow_wrapper_clients.cxx +++ b/o3tl/qa/cow_wrapper_clients.cxx @@ -31,7 +31,6 @@ public: int getValue() const { return mnValue; } bool operator==( const cow_wrapper_client2_impl& rRHS ) const { return mnValue == rRHS.mnValue; } - bool operator!=( const cow_wrapper_client2_impl& rRHS ) const { return mnValue != rRHS.mnValue; } bool operator<( const cow_wrapper_client2_impl& rRHS ) const { return mnValue < rRHS.mnValue; } private: @@ -106,10 +105,6 @@ bool cow_wrapper_client2::operator==( const cow_wrapper_client2& rRHS ) const { return maImpl == rRHS.maImpl; } -bool cow_wrapper_client2::operator!=( const cow_wrapper_client2& rRHS ) const -{ - return maImpl != rRHS.maImpl; -} bool cow_wrapper_client2::operator<( const cow_wrapper_client2& rRHS ) const { return maImpl < rRHS.maImpl; @@ -184,10 +179,6 @@ bool cow_wrapper_client3::operator==( const cow_wrapper_client3& rRHS ) const { return maImpl == rRHS.maImpl; } -bool cow_wrapper_client3::operator!=( const cow_wrapper_client3& rRHS ) const -{ - return maImpl != rRHS.maImpl; -} bool cow_wrapper_client3::operator<( const cow_wrapper_client3& rRHS ) const { return maImpl < rRHS.maImpl; @@ -232,10 +223,6 @@ bool cow_wrapper_client4::operator==( const cow_wrapper_client4& rRHS ) const { return maImpl == rRHS.maImpl; } -bool cow_wrapper_client4::operator!=( const cow_wrapper_client4& rRHS ) const -{ - return maImpl != rRHS.maImpl; -} bool cow_wrapper_client4::operator<( const cow_wrapper_client4& rRHS ) const { return maImpl < rRHS.maImpl; @@ -287,10 +274,6 @@ bool cow_wrapper_client5::operator==( const cow_wrapper_client5& rSrc ) const { return maImpl == rSrc.maImpl; } -bool cow_wrapper_client5::operator!=( const cow_wrapper_client5& rSrc ) const { - return maImpl != rSrc.maImpl; -} - } // namespace o3tltests /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/o3tl/qa/cow_wrapper_clients.hxx b/o3tl/qa/cow_wrapper_clients.hxx index 7421ec0f0e75..6c2b33dae1e9 100644 --- a/o3tl/qa/cow_wrapper_clients.hxx +++ b/o3tl/qa/cow_wrapper_clients.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_O3TL_QA_COW_WRAPPER_CLIENTS_HXX -#define INCLUDED_O3TL_QA_COW_WRAPPER_CLIENTS_HXX +#pragma once #include #include @@ -50,7 +49,6 @@ public: void swap( cow_wrapper_client1& r ) { o3tl::swap(maImpl, r.maImpl); } bool operator==( const cow_wrapper_client1& rRHS ) const { return maImpl == rRHS.maImpl; } - bool operator!=( const cow_wrapper_client1& rRHS ) const { return maImpl != rRHS.maImpl; } bool operator<( const cow_wrapper_client1& rRHS ) const { return maImpl < rRHS.maImpl; } private: @@ -84,7 +82,6 @@ public: void swap( cow_wrapper_client2& r ); bool operator==( const cow_wrapper_client2& rRHS ) const; - bool operator!=( const cow_wrapper_client2& rRHS ) const; bool operator<( const cow_wrapper_client2& rRHS ) const; private: @@ -115,7 +112,6 @@ public: void swap( cow_wrapper_client3& r ); bool operator==( const cow_wrapper_client3& rRHS ) const; - bool operator!=( const cow_wrapper_client3& rRHS ) const; bool operator<( const cow_wrapper_client3& rRHS ) const; private: @@ -139,7 +135,6 @@ public: bool is_default() const; bool operator==( const cow_wrapper_client4& rRHS ) const; - bool operator!=( const cow_wrapper_client4& rRHS ) const; bool operator<( const cow_wrapper_client4& rRHS ) const; private: @@ -192,7 +187,6 @@ public: sal_uInt32 use_count() const { return maImpl.use_count(); } bool operator==( const cow_wrapper_client5& rRHS ) const; - bool operator!=( const cow_wrapper_client5& rRHS ) const; private: o3tl::cow_wrapper< int, BogusRefCountPolicy > maImpl; @@ -207,6 +201,4 @@ inline std::basic_ostream & operator <<( } // namespace o3tltests -#endif // INCLUDED_O3TL_QA_COW_WRAPPER_CLIENTS_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/o3tl/qa/test-cow_wrapper.cxx b/o3tl/qa/test-cow_wrapper.cxx index b5d4936d5d7d..d4d2d739e368 100644 --- a/o3tl/qa/test-cow_wrapper.cxx +++ b/o3tl/qa/test-cow_wrapper.cxx @@ -246,7 +246,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(cow_wrapper_test); CPPUNIT_TEST(testCowWrapper); diff --git a/o3tl/qa/test-sorted_vector.cxx b/o3tl/qa/test-sorted_vector.cxx index f993ab80a302..559cb4950bee 100644 --- a/o3tl/qa/test-sorted_vector.cxx +++ b/o3tl/qa/test-sorted_vector.cxx @@ -301,7 +301,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(sorted_vector_test); CPPUNIT_TEST(testBasics); diff --git a/o3tl/qa/test-typed_flags.cxx b/o3tl/qa/test-typed_flags.cxx index ef6e4faaedce..cc9e516c192d 100644 --- a/o3tl/qa/test-typed_flags.cxx +++ b/o3tl/qa/test-typed_flags.cxx @@ -58,7 +58,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(typed_flags_test); CPPUNIT_TEST(testBasics); diff --git a/o3tl/qa/test-vector_pool.cxx b/o3tl/qa/test-vector_pool.cxx index 6e739ebcd18f..4d765fa607d8 100644 --- a/o3tl/qa/test-vector_pool.cxx +++ b/o3tl/qa/test-vector_pool.cxx @@ -74,7 +74,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(vector_pool_test); CPPUNIT_TEST(testPoolBasics); diff --git a/odk/CustomTarget_build-examples_java.mk b/odk/CustomTarget_build-examples_java.mk index 675d35ce2330..c8cef347aa7b 100644 --- a/odk/CustomTarget_build-examples_java.mk +++ b/odk/CustomTarget_build-examples_java.mk @@ -24,6 +24,7 @@ my_example_dirs_java = \ DevelopersGuide/FirstSteps/HelloTextTableShape/java \ DevelopersGuide/Forms \ DevelopersGuide/GUI \ + DevelopersGuide/OfficeBean \ DevelopersGuide/OfficeDev \ DevelopersGuide/OfficeDev/Clipboard/java \ DevelopersGuide/OfficeDev/DesktopEnvironment \ diff --git a/odk/Module_odk.mk b/odk/Module_odk.mk index d30c7164776a..b1350c69eba8 100644 --- a/odk/Module_odk.mk +++ b/odk/Module_odk.mk @@ -30,6 +30,7 @@ $(eval $(call gb_Module_add_targets,odk,\ Package_share_readme \ Package_share_readme_generated \ Package_scripts \ + $(if $(ENABLE_DOTNET),Package_dotnet) \ )) ifeq ($(OS),WNT) diff --git a/odk/Package_dotnet.mk b/odk/Package_dotnet.mk new file mode 100644 index 000000000000..166541bde59a --- /dev/null +++ b/odk/Package_dotnet.mk @@ -0,0 +1,27 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Package_Package,odk_dotnet,$(INSTROOT))) + +$(eval $(call gb_Package_set_outdir,odk_dotnet,$(INSTDIR))) + +$(eval $(call gb_Package_add_files,odk_dotnet,$(SDKDIRNAME)/dotnet,\ + $(LIBO_SHARE_DOTNET_FOLDER)/net_basetypes.dll \ + $(LIBO_SHARE_DOTNET_FOLDER)/net_bridge.dll \ + $(LIBO_SHARE_DOTNET_FOLDER)/net_bridge.runtimeconfig.json \ + $(LIBO_SHARE_DOTNET_FOLDER)/net_oootypes.dll \ + $(LIBO_SHARE_DOTNET_FOLDER)/net_uretypes.dll \ +)) + +$(eval $(call gb_Package_add_files,odk_dotnet,$(SDKDIRNAME)/dotnet,\ + $(SDKDIRNAME)/dotnet/LibreOffice.Bindings.0.1.0.nupkg \ + $(SDKDIRNAME)/dotnet/nuget.config \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/odk/Package_examples.mk b/odk/Package_examples.mk index 92c9b6918503..b58041202541 100644 --- a/odk/Package_examples.mk +++ b/odk/Package_examples.mk @@ -250,6 +250,12 @@ $(eval $(call gb_Package_add_files_with_dir,odk_examples,$(SDKDIRNAME)/examples, DevelopersGuide/GUI/UnoMenu.java \ DevelopersGuide/GUI/UnoMenu2.java \ DevelopersGuide/GUI/oologo.gif \ + DevelopersGuide/OfficeBean/Makefile \ + DevelopersGuide/OfficeBean/OOoBeanViewer.java \ + DevelopersGuide/OfficeBean/OfficeIconColor16.jpg \ + DevelopersGuide/OfficeBean/OfficeIconColor32.jpg \ + DevelopersGuide/OfficeBean/OfficeIconMono16.jpg \ + DevelopersGuide/OfficeBean/OfficeIconMono32.jpg \ DevelopersGuide/OfficeDev/Clipboard/java/Clipboard.java \ DevelopersGuide/OfficeDev/Clipboard/java/ClipboardListener.java \ DevelopersGuide/OfficeDev/Clipboard/java/ClipboardOwner.java \ diff --git a/odk/examples/DevelopersGuide/Components/Addons/JobsAddon/AsyncJob.java b/odk/examples/DevelopersGuide/Components/Addons/JobsAddon/AsyncJob.java index c47244b9abbb..cbe7a641751b 100644 --- a/odk/examples/DevelopersGuide/Components/Addons/JobsAddon/AsyncJob.java +++ b/odk/examples/DevelopersGuide/Components/Addons/JobsAddon/AsyncJob.java @@ -80,11 +80,11 @@ public class AsyncJob extends WeakBase implements XServiceInfo, XAsyncJob *
      • generic job configuration data
      • *
      • job specific configuration data
      • *
      • some environment information
      • - *
      • may optional arguments of a corresponding dispatch request
      • + *
      • optional arguments of a corresponding dispatch request
      • *
      * - * @params xListener - * callback to the executor of this job, which control our life time + * @param xListener + * callback to the executor of this job, which controls our life time * * @throws com.sun.star.lang.IllegalArgumentException * if given argument list seems to be wrong @@ -179,7 +179,7 @@ public class AsyncJob extends WeakBase implements XServiceInfo, XAsyncJob com.sun.star.beans.NamedValue aDispatchResult = null; com.sun.star.beans.NamedValue aSaveRequest = null; - // SaveArguments will be made everytimes! + // SaveArguments will be made every time! c = 1; if (lJobConfig==null) @@ -243,7 +243,7 @@ public class AsyncJob extends WeakBase implements XServiceInfo, XAsyncJob * is shown as title of the info box. * * @param sMessage - * included the message body, which is shown as info. + * includes the message body, which is shown as info. */ private void showInfoModal( com.sun.star.awt.XWindow xParent , @@ -258,7 +258,7 @@ public class AsyncJob extends WeakBase implements XServiceInfo, XAsyncJob m_xCmpCtx.getServiceManager().createInstanceWithContext("com.sun.star.awt.Toolkit", m_xCmpCtx)); - // describe the info box ini its parameters + // describe the info box in its parameters com.sun.star.awt.WindowDescriptor aDescriptor = new com.sun.star.awt.WindowDescriptor(); aDescriptor.WindowServiceName = "infobox"; aDescriptor.Bounds = new com.sun.star.awt.Rectangle(0,0,300,200); @@ -334,7 +334,7 @@ public class AsyncJob extends WeakBase implements XServiceInfo, XAsyncJob * contains some environment information * * @param lDynamicData - * contains optional data of a might corresponding dispatch() request + * contains optional data of a corresponding dispatch() request */ private String formatOutArgs(com.sun.star.beans.NamedValue[] lGenericConfig, diff --git a/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/csharp/FirstLoadComponent.cs b/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/csharp/FirstLoadComponent.cs index 9205d030a642..99c082accf9a 100644 --- a/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/csharp/FirstLoadComponent.cs +++ b/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/csharp/FirstLoadComponent.cs @@ -73,7 +73,7 @@ try // Uncomment to load a Calc file as template //xSpreadsheetComponent = xComponentLoader.loadComponentFromURL( - // "file:///c:/temp/DataAnalysys.ods", "_blank", 0, loadProps); + // "file:///c:/temp/DataAnalysis.ods", "_blank", 0, loadProps); // Example usage of XEnumerationAccess XCellRangesQuery xCellQuery = sheet.castOrDefault(); @@ -96,4 +96,4 @@ catch (UnoException e) Console.Error.WriteLine(e.Message); return 1; -} \ No newline at end of file +} diff --git a/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/cxx/FirstLoadComponent.cxx b/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/cxx/FirstLoadComponent.cxx index 79493e2e5ed0..8747dcddf82f 100644 --- a/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/cxx/FirstLoadComponent.cxx +++ b/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/cxx/FirstLoadComponent.cxx @@ -114,7 +114,7 @@ SAL_IMPLEMENT_MAIN() // load calc file as a template // xSpreadsheetComponent = xComponentLoader->loadComponentFromURL( - // "file:///c:/temp/DataAnalysys.ods", "_blank", 0, loadProps); + // "file:///c:/temp/DataAnalysis.ods", "_blank", 0, loadProps); // ********************************************************* // example for use of XEnumerationAccess diff --git a/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/java/FirstLoadComponent.java b/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/java/FirstLoadComponent.java index 70e531df3d4b..f722e3e5d0e6 100644 --- a/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/java/FirstLoadComponent.java +++ b/odk/examples/DevelopersGuide/FirstSteps/FirstLoadComponent/java/FirstLoadComponent.java @@ -128,7 +128,7 @@ public class FirstLoadComponent { // load calc file as template //xSpreadsheetComponent = xComponentLoader.loadComponentFromURL( - // "file:///c:/temp/DataAnalysys.ods", "_blank", 0, loadProps); + // "file:///c:/temp/DataAnalysis.ods", "_blank", 0, loadProps); // ********************************************************* // example for use of XEnumerationAccess diff --git a/odk/examples/DevelopersGuide/FirstSteps/HelloTextTableShape/cxx/HelloTextTableShape.cxx b/odk/examples/DevelopersGuide/FirstSteps/HelloTextTableShape/cxx/HelloTextTableShape.cxx index b9f2a11ae528..c88c0a7768fa 100644 --- a/odk/examples/DevelopersGuide/FirstSteps/HelloTextTableShape/cxx/HelloTextTableShape.cxx +++ b/odk/examples/DevelopersGuide/FirstSteps/HelloTextTableShape/cxx/HelloTextTableShape.cxx @@ -145,7 +145,7 @@ void useWriter() Reference xTextContent(bookmark, UNO_QUERY_THROW); xText->insertTextContent(xText->getEnd(), xTextContent, false); - //query BookmarksSupplier + // query BookmarksSupplier Reference xBookmarksSupplier(xWriterComponent, UNO_QUERY_THROW); Reference xNamedBookmarks = xBookmarksSupplier->getBookmarks(); Any foundBookmark = xNamedBookmarks->getByName("MyUniqueBookmarkName"); @@ -221,7 +221,7 @@ void useCalc() void useDraw() { - //create new draw document and insert ractangle shape + // create new draw document and insert rectangle shape Reference xDrawComponent = newDocComponent("sdraw"); Reference xDrawPagesSupplier(xDrawComponent, UNO_QUERY_THROW); diff --git a/odk/examples/DevelopersGuide/FirstSteps/HelloTextTableShape/java/HelloTextTableShape.java b/odk/examples/DevelopersGuide/FirstSteps/HelloTextTableShape/java/HelloTextTableShape.java index 2ea20e61b61f..4442f8253b0c 100644 --- a/odk/examples/DevelopersGuide/FirstSteps/HelloTextTableShape/java/HelloTextTableShape.java +++ b/odk/examples/DevelopersGuide/FirstSteps/HelloTextTableShape/java/HelloTextTableShape.java @@ -157,7 +157,7 @@ public class HelloTextTableShape { XTextContent.class, bookmark ); xText.insertTextContent ( xText.getEnd(), xTextContent, false ); - //query BookmarksSupplier + // query BookmarksSupplier XBookmarksSupplier xBookmarksSupplier = (XBookmarksSupplier)UnoRuntime.queryInterface( XBookmarksSupplier.class, xWriterComponent); XNameAccess xNamedBookmarks = xBookmarksSupplier.getBookmarks(); @@ -208,7 +208,7 @@ public class HelloTextTableShape { XIndexAccess.class, sheets); Object sheet = xIndexedSheets.getByIndex(0); - //get cell A2 in first sheet + // get cell A2 in first sheet XCellRange xSpreadsheetCells = UnoRuntime.queryInterface( XCellRange.class, sheet); XCell xCell = xSpreadsheetCells.getCellByPosition(0,1); @@ -259,7 +259,7 @@ public class HelloTextTableShape { protected void useDraw() throws java.lang.Exception { try { - //create new draw document and insert ractangle shape + // create new draw document and insert rectangle shape XComponent xDrawComponent = newDocComponent("sdraw"); XDrawPagesSupplier xDrawPagesSupplier = UnoRuntime.queryInterface( diff --git a/odk/examples/DevelopersGuide/Forms/DocumentHelper.java b/odk/examples/DevelopersGuide/Forms/DocumentHelper.java index abfda37c450e..c068dde45b75 100644 --- a/odk/examples/DevelopersGuide/Forms/DocumentHelper.java +++ b/odk/examples/DevelopersGuide/Forms/DocumentHelper.java @@ -157,7 +157,7 @@ public class DocumentHelper /* ------------------------------------------------------------------ */ /** creates a form which is a sibling of the given form @param aForm - A sinbling of the to be created form. + A sibling of the to be created form. @param sInitialName The initial name of the form. May be null, in this case the default (which @@ -259,7 +259,7 @@ public class DocumentHelper xReturn = UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( 0 ) ); - // Note that this is no really error-proof code: If the document model does not support the + // Note that this is not really error-proof code: If the document model does not support the // XDrawPagesSupplier interface, or if the pages collection returned is empty, this will break. } diff --git a/odk/examples/DevelopersGuide/OfficeBean/Makefile b/odk/examples/DevelopersGuide/OfficeBean/Makefile new file mode 100644 index 000000000000..c57c6b6260ac --- /dev/null +++ b/odk/examples/DevelopersGuide/OfficeBean/Makefile @@ -0,0 +1,92 @@ +#************************************************************************* +# +# The Contents of this file are made available subject to the terms of +# the BSD license. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of Sun Microsystems, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#************************************************************************** + +# Builds the OOoBean of the Developers Guide + +PRJ=../../.. +SETTINGS=$(PRJ)/settings + +include $(SETTINGS)/settings.mk +include $(SETTINGS)/std.mk + +# Define non-platform/compiler specific settings +OUT_COMP_CLASS = $(OUT_CLASS)/OOoBeanViewer + +PACKAGE = org/libreoffice/sdk/examples/developers_guide/office_bean + +JAVAFILES = \ + OOoBeanViewer.java \ + +CLASSFILES = $(patsubst %.java,$(OUT_COMP_CLASS)/$(PACKAGE)/%.class,$(JAVAFILES)) + +SDK_CLASSPATH = $(subst $(EMPTYSTRING) $(PATH_SEPARATOR),$(PATH_SEPARATOR),\ + $(PATH_SEPARATOR)$(URE_CLASSES_DIR)/libreoffice.jar\ + $(PATH_SEPARATOR)$(OFFICE_CLASSES_DIR)/officebean.jar\ + $(PATH_SEPARATOR)$(OUT_COMP_CLASS)) + +# Targets +.PHONY: ALL +ifeq "$(OS)" "MACOSX" +ALL : + @printf 'This example does not work on macOS\n' +else +ALL : \ + OOoBeanViewer +endif + +include $(SETTINGS)/stdtarget.mk + +$(CLASSFILES) : $(JAVAFILES) + -$(MKDIR) $(subst /,$(PS),$(@D)) + javac $(JAVAC_FLAGS) -classpath "$(SDK_CLASSPATH)" -d $(OUT_COMP_CLASS) $(JAVAFILES) + +OOoBeanViewer: $(CLASSFILES) + @echo -------------------------------------------------------------------------------- + @echo Please use the following command to execute the example! + @echo - + @echo $(MAKE) OOoBeanViewer.run + @echo -------------------------------------------------------------------------------- + +%.run: $(CLASSFILES) + export SAL_USE_VCLPLUGIN=gen && \ + export LD_LIBRARY_PATH="$(OO_SDK_JAVA_HOME)/lib" && \ + $(SDK_JAVA) --enable-native-access=ALL-UNNAMED -classpath "$(SDK_CLASSPATH)" $(subst /,.,$(PACKAGE)).$(basename $@) + +%.dbg: $(JAR1_JAR) + jdb -classpath "$(SDK_CLASSPATH)" $(subst /,.,$(PACKAGE)).$(basename $@) + +.PHONY: clean +clean : + -$(DELRECURSIVE) $(subst /,$(PS),$(OUT_COMP_CLASS)) + diff --git a/odk/examples/DevelopersGuide/OfficeBean/OOoBeanViewer.java b/odk/examples/DevelopersGuide/OfficeBean/OOoBeanViewer.java new file mode 100644 index 000000000000..e2fe5540edbf --- /dev/null +++ b/odk/examples/DevelopersGuide/OfficeBean/OOoBeanViewer.java @@ -0,0 +1,407 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * The Contents of this file are made available subject to the terms of + * the BSD license. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Sun Microsystems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *************************************************************************/ + +package org.libreoffice.sdk.examples.developers_guide.office_bean; + +import com.sun.star.comp.beans.OOoBean; +import javax.swing.filechooser.*; +import javax.swing.*; +import java.io.*; + +/* A simple Applet that contains the SimpleBean. + * + * This applet is a sample implementation of the + * LibreOffice OfficeBean. + * When initially loaded the application has two buttons + * one for opening an existent file and one to open + * a blank document of a given type supported by + * LibreOffice eg. Writer, Calc, Impress, ... + * + */ + +public class OOoBeanViewer extends java.awt.Panel +{ + + /** + * Private variables declaration - GUI components + */ + private java.awt.Panel rightPanel; + private java.awt.Panel bottomPanel; + private javax.swing.JButton closeButton; + private javax.swing.JButton terminateButton; + private javax.swing.JButton newDocumentButton; + private javax.swing.JPopupMenu documentTypePopUp; + private javax.swing.JCheckBox menuBarButton; + private javax.swing.JCheckBox mainBarButton; + private javax.swing.JCheckBox toolBarButton; + private javax.swing.JCheckBox statusBarButton; + private javax.swing.JButton storeDocumentButton; + private javax.swing.JButton loadDocumentButton; + private javax.swing.JButton syswinButton; + private JTextField documentURLTextField; + private JMenuItem item; + private JFileChooser fileChooser; + private byte buffer[]; + + /** + * Private variables declaration - SimpleBean variables + */ + private OOoBean aBean; + + /** + * Initialize the example UI + */ + public void init() + { + //The aBean needs to be initialized to add it to the applet + aBean = new OOoBean(); + + //Initialize GUI components + rightPanel = new java.awt.Panel(); + bottomPanel = new java.awt.Panel(); + closeButton = new javax.swing.JButton("close"); + terminateButton = new javax.swing.JButton("terminate"); + newDocumentButton = new javax.swing.JButton("new document..."); + documentTypePopUp = new javax.swing.JPopupMenu(); + storeDocumentButton = new javax.swing.JButton("store to buffer"); + loadDocumentButton = new javax.swing.JButton("load from buffer"); + syswinButton = new javax.swing.JButton("release/acquire"); + + menuBarButton = new javax.swing.JCheckBox("MenuBar"); + menuBarButton.setSelected( aBean.isMenuBarVisible() ); + + mainBarButton = new javax.swing.JCheckBox("MainBar"); + mainBarButton.setSelected( aBean.isStandardBarVisible() ); + + toolBarButton = new javax.swing.JCheckBox("ToolBar"); + toolBarButton.setSelected( aBean.isToolBarVisible() ); + + statusBarButton = new javax.swing.JCheckBox("StatusBar"); + statusBarButton.setSelected( aBean.isStatusBarVisible() ); + + documentURLTextField = new javax.swing.JTextField(); + + //Set up the Popup Menu to create a blank document + documentTypePopUp.setToolTipText("Create an empty document"); + + item = documentTypePopUp.add("Text Document"); + item.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + createBlankDoc("private:factory/swriter", + "New text document"); + } + }); + + item = documentTypePopUp.add("Presentation Document"); + item.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + createBlankDoc("private:factory/simpress", + "New presentation document"); + } + }); + + item = documentTypePopUp.add("Drawing Document"); + item.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + createBlankDoc("private:factory/sdraw", + "New drawing document"); + } + }); + + item = documentTypePopUp.add("Formula Document"); + item.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + createBlankDoc("private:factory/smath", + "New formula document"); + } + }); + + item = documentTypePopUp.add("Spreadsheet Document"); + item.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + createBlankDoc("private:factory/scalc", + "New spreadsheet document"); + } + }); + + syswinButton.addActionListener( + new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + try + { + aBean.releaseSystemWindow(); + aBean.aquireSystemWindow(); + } + catch ( com.sun.star.comp.beans.NoConnectionException aExc ) + {} + catch ( com.sun.star.comp.beans.SystemWindowException aExc ) + {} + } + }); + + storeDocumentButton.addActionListener( + new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + try + { + buffer = aBean.storeToByteArray( null, null ); + } + catch ( Throwable aExc ) + { + System.err.println( "storeToBuffer failed: " + aExc ); + aExc.printStackTrace( System.err ); + } + } + }); + + loadDocumentButton.addActionListener( + new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + try + { + aBean.loadFromByteArray( buffer, null ); + } + catch ( Throwable aExc ) + { + System.err.println( "loadFromBuffer failed: " + aExc ); + aExc.printStackTrace( System.err ); + } + } + }); + + closeButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + close(); + } + }); + + terminateButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + terminate(); + } + }); + + newDocumentButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + documentTypePopUp.show((java.awt.Component)evt.getSource(), 0,0); + } + }); + + menuBarButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + aBean.setMenuBarVisible( !aBean.isMenuBarVisible() ); + } + }); + + mainBarButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + aBean.setStandardBarVisible( !aBean.isStandardBarVisible() ); + } + }); + + toolBarButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + aBean.setToolBarVisible( !aBean.isToolBarVisible() ); + } + }); + + statusBarButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + aBean.setStatusBarVisible( !aBean.isStatusBarVisible() ); + } + }); + + documentURLTextField.setEditable(false); + documentURLTextField.setPreferredSize(new java.awt.Dimension(200, 30)); + + rightPanel.setLayout( new java.awt.GridLayout(10,1) ); + rightPanel.add(closeButton); + rightPanel.add(terminateButton); + rightPanel.add(newDocumentButton); + rightPanel.add(storeDocumentButton); + rightPanel.add(loadDocumentButton); + rightPanel.add(syswinButton); + rightPanel.add(menuBarButton); + rightPanel.add(mainBarButton); + rightPanel.add(toolBarButton); + rightPanel.add(statusBarButton); + + //bottomPanel.setLayout( new java.awt.GridLayout(1,1) ); + bottomPanel.setLayout( new java.awt.BorderLayout() ); + bottomPanel.add(documentURLTextField); + + setLayout(new java.awt.BorderLayout()); + + add(aBean, java.awt.BorderLayout.CENTER); + add(rightPanel, java.awt.BorderLayout.EAST); + add(bottomPanel, java.awt.BorderLayout.SOUTH); + } + + /** + * Create a blank document of type desc + * + * @param url The private internal URL of the LibreOffice + * document describing the document + * @param desc A description of the document to be created + */ + private void createBlankDoc(String url, String desc) + { + //Create a blank document + try + { + documentURLTextField.setText(desc); + //Get the office process to load the URL + aBean.loadFromURL( url, null ); + + aBean.aquireSystemWindow(); + } + catch ( com.sun.star.comp.beans.SystemWindowException aExc ) + { + System.err.println( "OOoBeanViewer.1:" ); + aExc.printStackTrace(); + } + catch ( com.sun.star.comp.beans.NoConnectionException aExc ) + { + System.err.println( "OOoBeanViewer.2:" ); + aExc.printStackTrace(); + } + catch ( Exception aExc ) + { + System.err.println( "OOoBeanViewer.3:" ); + aExc.printStackTrace(); + //return; + } + } + + /** closes the bean viewer, leaves OOo running. + */ + private void close() + { + setVisible(false); + aBean.stopOOoConnection(); + System.exit(0); + } + + /** closes the bean viewer and tries to terminate OOo. + */ + private void terminate() + { + setVisible(false); + com.sun.star.frame.XDesktop xDesktop = null; + try { + xDesktop = aBean.getOOoDesktop(); + } + catch ( com.sun.star.comp.beans.NoConnectionException aExc ) {} // ignore + aBean.stopOOoConnection(); + if ( xDesktop != null ) + xDesktop.terminate(); + System.exit(0); + } + + /** + * An ExitListener listening for windowClosing events + */ + private class ExitListener extends java.awt.event.WindowAdapter + { + /** + * windowClosed + * + * @param e A WindowEvent for a closed Window event + */ + public void windowClosed( java.awt.event.WindowEvent e) + { + close(); + } + + /** + * windowClosing for a closing window event + * + * @param e A WindowEvent for a closing window event + */ + public void windowClosing( java.awt.event.WindowEvent e) + { + ((java.awt.Window)e.getSource()).dispose(); + } + } + + public static void main(String args[]) + { + java.awt.Frame frame = new java.awt.Frame("LibreOffice Demo"); + OOoBeanViewer aViewer = new OOoBeanViewer(); + + frame.setLayout(new java.awt.BorderLayout()); + + frame.addWindowListener( aViewer.new ExitListener() ); + + aViewer.init(); + + frame.add(aViewer); + frame.setLocation( 200, 200 ); + frame.setSize( 800, 480 ); + frame.show(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/odk/examples/DevelopersGuide/OfficeBean/OfficeIconColor16.jpg b/odk/examples/DevelopersGuide/OfficeBean/OfficeIconColor16.jpg new file mode 100644 index 000000000000..cd9c5a602eff Binary files /dev/null and b/odk/examples/DevelopersGuide/OfficeBean/OfficeIconColor16.jpg differ diff --git a/odk/examples/DevelopersGuide/OfficeBean/OfficeIconColor32.jpg b/odk/examples/DevelopersGuide/OfficeBean/OfficeIconColor32.jpg new file mode 100644 index 000000000000..ccab06b516a7 Binary files /dev/null and b/odk/examples/DevelopersGuide/OfficeBean/OfficeIconColor32.jpg differ diff --git a/odk/examples/DevelopersGuide/OfficeBean/OfficeIconMono16.jpg b/odk/examples/DevelopersGuide/OfficeBean/OfficeIconMono16.jpg new file mode 100644 index 000000000000..cd9c5a602eff Binary files /dev/null and b/odk/examples/DevelopersGuide/OfficeBean/OfficeIconMono16.jpg differ diff --git a/odk/examples/DevelopersGuide/OfficeBean/OfficeIconMono32.jpg b/odk/examples/DevelopersGuide/OfficeBean/OfficeIconMono32.jpg new file mode 100644 index 000000000000..ccab06b516a7 Binary files /dev/null and b/odk/examples/DevelopersGuide/OfficeBean/OfficeIconMono32.jpg differ diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/CustomizeView.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/CustomizeView.java index f19429585472..96d2d387ab11 100644 --- a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/CustomizeView.java +++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/CustomizeView.java @@ -46,7 +46,7 @@ public class CustomizeView extends JPanel implements IShutdownListener { /** - * These const URL's describe feature for toggling some properties of loaded document. + * These const URL's describe features for toggling some properties of loaded document. * Dispatch it with the corresponding parameter to the frame. */ private static final String FEATUREURL_MENUBAR = "slot:6661" ; @@ -93,7 +93,7 @@ public class CustomizeView extends JPanel /** * ctor - * Create view controls on startup and initialize it. + * Create view controls on startup and initialize them. * We don't start listening here. see setFrame()! */ CustomizeView() @@ -121,7 +121,7 @@ public class CustomizeView extends JPanel /** * set new frame for this view - * We start listening for frame action/status and click events instandly. + * We start listening for frame action/status and click events instantly. * If an event occurs, we use it to synchronize our controls * with states of a (maybe) new document view of this frame. * @@ -165,9 +165,9 @@ public class CustomizeView extends JPanel /* * react for click events of the used check boxes * We use our internal set dispatch objects to - * call it. This calls toggle the menu/object- or toolbar. - * Note: Because we are listener status events too - hopefully - * we get a notification, if toggling was successfully or not. + * call it. These calls toggle the menu/object- or toolbar. + * Note: Because we are listening for status events too - hopefully + * we get a notification, whether toggling was successful or not. * We use this information to update our check boxes again. * But such update doesn't force (hopefully) an action event. Otherwise * we can produce a never ending recursion! @@ -186,7 +186,7 @@ public class CustomizeView extends JPanel /** * ctor - * It initialize an instance of this class only. + * It initializes an instance of this class only. */ private ClickListener( String sURL , String sProp , @@ -204,7 +204,7 @@ public class CustomizeView extends JPanel * Such events occur, if someone clicked the * JCheckBox control, on which we are registered. * Such events do not occur, if we set it programmatically - * (e.g. if we get status events to -> see class StatusListener too) + * (e.g. if we get status events too -> see class StatusListener too) * * @param aEvent * describes the check box and its state @@ -247,7 +247,7 @@ public class CustomizeView extends JPanel * and forget his reference. * * @param aEvent - * describes the source which fire this event + * describes the source which fires this event * Must be our internal saved frame. Otherwise * somewhere know us without a registration ... */ @@ -263,7 +263,7 @@ public class CustomizeView extends JPanel /** - * If this java application shutdown - we must cancel all current existing + * If this java application shuts down - we must cancel all current existing * listener connections. Otherwise the office will run into some * DisposedExceptions if it tries to use these forgotten listener references. * And of course it can die doing that. diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/FunctionHelper.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/FunctionHelper.java index fa24cde96e33..ee37a4603b6a 100644 --- a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/FunctionHelper.java +++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/FunctionHelper.java @@ -48,25 +48,25 @@ import java.net.*; /** * Is a collection of basic features. * This helper shows different functionality of framework api - * in an example manner. You can use the follow ones: + * in an example manner. You can use the following ones: * (1) parse URL's * (2) create frames (inside/outside a java application) * (3) dispatches (with[out] notifications) * (4) loading/saving documents * (5) convert documents to HTML (if possible) - * (6) close documents (and her frames) correctly + * (6) close documents (and their frames) correctly * * There exist some other helper functionality too, which * doesn't use or demonstrate the office api: - * (a) getting file names by using a file chosser + * (a) getting file names by using a file chooser */ public class FunctionHelper { /** - * This convert a URL (formatted as a string) to a struct com.sun.star.util.URL. - * It use a special service to do that: the URLTransformer. + * This converts a URL (formatted as a string) to a struct com.sun.star.util.URL. + * It uses a special service to do that: the URLTransformer. * Because some API calls need it and it's not allowed to set "Complete" * part of the util struct only. The URL must be parsed. * @@ -128,13 +128,13 @@ public class FunctionHelper /** * create a new empty target frame * Attention: Currently we must use special service com.sun.star.frame.Task instead of Frame. - * Because desktop environment accept this special frame type only as direct children. - * Note - This service will be deprecated and must be replaces by com.sun.star.frame.Frame in - * further versions. To feature prove we use both service names. If for new versions - * the deprecated one not exist we get an empty frame, we can try to use the new service. + * Because desktop environment accepts this special frame type only as direct children. + * Note - This service will be deprecated and must be replaced by com.sun.star.frame.Frame in + * further versions. To future proof we use both service names. If for new versions + * the deprecated one does not exist and we get an empty frame, we can try to use the new service. * - * @param xSMGR - * we need the remote service manager to create this task/frame service + * @param xCtx + * we need the component context to create this task/frame service * * @return [com.sun.star.frame.XFrame] * the new created frame reference in case of success or null otherwise @@ -181,7 +181,7 @@ public class FunctionHelper * to transport it to the remote office toolkit and get a child office * window. * This is the old way. It's better to use the second one - but to be - * future prove this old one should be tried too. + * future proof this old one should be tried too. * - it's possible to pass the native window handle directly to the toolkit. * A special interface method was enabled to accept that. * @@ -189,8 +189,8 @@ public class FunctionHelper * - try to use second creation mode (directly using of the window handle) * - if it failed ... use the old way by packing the handle inside an object * - * @param xSMGR - * we need a service manager to be able to create remote office + * @param xCtx + * we need a component context to be able to create remote office * services * * @param aParentView @@ -325,14 +325,14 @@ public class FunctionHelper /** - * This method create a new empty child frame on desktop instance of remote office. - * It use a special JNI functionality to pass the office XWindow over a java window. + * This method creates a new empty child frame on desktop instance of remote office. + * It uses a special JNI functionality to pass the office XWindow over a java window. * This java window can be inserted into another java window container for complex layouting. * If this parent java window isn't used, a top level system window will be created. * The resulting office frame isn't plugged into this java application. * * @param sName - * name to set it on the new created frame + * name to set on the new created frame * * @param aParentView * java window which should be used as parent window of new created office frame window @@ -427,9 +427,9 @@ public class FunctionHelper /** * Dispatch a URL to given frame. * Caller can register himself for following status events for dispatched - * URL too. But nobody guarantee that such notifications will occur. - * (see dispatchWithNotification() if you interest on that) - * The returned dispatch object should be hold alive by caller + * URL too. But nobody guarantees that such notifications will occur. + * (see dispatchWithNotification() if you are interested in that) + * The returned dispatch object should be held alive by caller * till he doesn't need it any longer. Otherwise the dispatcher can(!) * die by decreasing his refcount. * @@ -596,8 +596,8 @@ public class FunctionHelper { // Check for supported model functionality. // Normally the application documents (text, spreadsheet ...) do so - // but some other ones (e.g. db components) doesn't do that. - // They can't be save then. + // but some other ones (e.g. db components) don't do that. + // They can't be saved then. com.sun.star.frame.XModel xModel = UnoRuntime.queryInterface( com.sun.star.frame.XModel.class, xDocument); @@ -634,11 +634,11 @@ public class FunctionHelper /** - * It try to export given document in HTML format. + * It tries to export given document in HTML format. * Current document will be converted to HTML and moved to new place on disk. * A "new" file will be created by given URL (may be overwritten - * if it already exist). Right filter will be used automatically if factory of - * this document support it. If no valid filter can be found for export, + * if it already exists). Right filter will be used automatically if factory of + * this document supports it. If no valid filter can be found for export, * nothing will be done here. * * @param xDocument document which should be exported @@ -813,7 +813,7 @@ public class FunctionHelper * * should represent a unique frame name, which currently isn't * used inside the remote office frame tree - * (Couldn't guaranteed for a real multithreaded environment. + * (Couldn't be guaranteed for a real multithreaded environment. * But we try it ...) */ private static final String BASEFRAMENAME = "Desk View "; @@ -881,7 +881,7 @@ public class FunctionHelper int nDecision = JFileChooser.CANCEL_OPTION; JFileChooser aChooser = null; - // set last visited directory on new file chosser + // set last visited directory on new file chooser // (if this information is available) if( maLastDir==null ) aChooser = new JFileChooser(); diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Interceptor.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Interceptor.java index 380f8da3cf5d..9c2432c4fbfc 100644 --- a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Interceptor.java +++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Interceptor.java @@ -45,15 +45,15 @@ import com.sun.star.uno.UnoRuntime; /* * This class can be used to intercept dispatched URL's * on any frame used in this demo application. - * It intercept all URL's which try to create a new empty frame. + * It intercepts all URL's which try to create a new empty frame. * (e.g. "private:factory/swriter") * Nobody can guarantee that this interception will be really used - - * because another interceptor (registered at a later time then this one!) + * because another interceptor (registered at a later time than this one!) * will be called before this one. * Implementation is executed inside a new thread to prevent application - * against possible deadlocks. This deadlocks can occur if + * against possible deadlocks. These deadlocks can occur if * synchronous/asynchronous ... normal ones and oneway calls are mixed. - * Notifications of listener will be oneway mostly - her reactions can + * Notifications of listener will be oneway mostly - their reactions can * be synchronous then. => deadlocks are possible */ public class Interceptor implements com.sun.star.frame.XFrameActionListener, @@ -349,7 +349,7 @@ public class Interceptor implements com.sun.star.frame.XFrameActionListener, * These functions are used to build a list of interceptor objects * connected in both ways. * Searching for a right interceptor is made by forwarding any request - * from toppest master to lowest slave of this hierarchy. + * from topmost master to lowest slave of this hierarchy. * If an interceptor wish to handle the request he can break that * and return himself as a dispatcher. */ @@ -560,8 +560,8 @@ public class Interceptor implements com.sun.star.frame.XFrameActionListener, * call this interceptor directly without calling his masters before, IF(!) * following rules will be true: * (1) every master supports this optional interface too - * (2) nobody of these masters wish to intercept same URL then this one - * This interceptor wish to intercept creation of new documents. + * (2) nobody of these masters wishes to intercept same URL as this one + * This interceptor wishes to intercept creation of new documents. */ public String[] getInterceptedURLs() { @@ -571,14 +571,14 @@ public class Interceptor implements com.sun.star.frame.XFrameActionListener, /* - * This class listen on the intercepted frame to free all used resources on closing. + * This class listens on the intercepted frame to free all used resources on closing. * We forget the reference to the frame only here. Deregistration - * isn't necessary here - because this frame dies and wish to be forgotten. + * isn't necessary here - because this frame dies and wishes to be forgotten. * * @param aSource * must be our internal saved frame, on which we listen for frame action events */ - public /*ONEAY*/ void disposing(/*IN*/ com.sun.star.lang.EventObject aSource) + public /*ONE-WAY*/ void disposing(/*IN*/ com.sun.star.lang.EventObject aSource) { synchronized(this) { diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusListener.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusListener.java index f037949b0590..dc7ce4ebd5c7 100644 --- a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusListener.java +++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusListener.java @@ -47,18 +47,18 @@ import com.sun.star.uno.UnoRuntime; // __________ Implementation __________ /** - * reacts for status events we listen for + * reacts to status events we listen for * We listen for status events to update our UI. * To know which event must be used for which UI control * we use a special class to do that. Otherwise we have * to guess it ... * - * Further we are frame action listener too. + * Further we are frame action listeners too. * So we can update our status listener connections and - * internal holded dispatch object automatically. + * internal held dispatch object automatically. * * Another reason for such extra class for listening: - * Most listener callbacks are asynchronous [oneay] requests. + * Most listener callbacks are asynchronous [one-way] requests. * And it's not allowed to call back synchronously there. * So we must start threads for updating something internally. * @@ -73,7 +73,7 @@ class StatusListener implements com.sun.star.frame.XStatusListener, /** * @member m_rControl reference to the UI control, which should be updated * @member m_sTrueText this text will be shown at the used UI control as description for an enabled status - * @member m_sFalseText this text will be shown at the used UI control as description for an disabled status + * @member m_sFalseText this text will be shown at the used UI control as description for a disabled status * @member m_xDispatch if we listen for status events, we must hold the dispatch object alive! * @member m_xFrame reference to the frame, which can provide new dispatch objects if it's necessary to update it * @member m_aURL and of course we must be registered for a special URL @@ -95,7 +95,7 @@ class StatusListener implements com.sun.star.frame.XStatusListener, /** * ctor - * It initialize an instance of this class only. + * It initializes an instance of this class only. * We set all necessary information on our internal member - that's it */ StatusListener( /*IN*/ Component rControl , @@ -111,7 +111,7 @@ class StatusListener implements com.sun.star.frame.XStatusListener, m_bIsStatusListener = false ; m_bIsActionListener = false ; m_bDead = false ; - // to be perform - we parse the given URL one times only + // to be perform - we parse the given URL one time only // and use it till we die ... m_aURL = FunctionHelper.parseURL(sURL); } @@ -124,7 +124,7 @@ class StatusListener implements com.sun.star.frame.XStatusListener, * update our internal saved dispatch object on which we listen * for status events. So we can do it automatically. The outside code * mustn't check such things. We can work with one frame, - * till it die. It doesn't matter if he will be used for different + * till it dies. It doesn't matter if it will be used for different * load/save or any other requests. We will be up to date every time. */ public void startListening() @@ -185,10 +185,10 @@ class StatusListener implements com.sun.star.frame.XStatusListener, /** * This is the callback method for such frame action events, we listen for. - * Because it's a oneway method we start a thread as reaction. This thread call + * Because it's a oneway method we start a thread as reaction. This thread calls * us back and we can do necessary things there. * But we shouldn't start such action - if it's not really necessary. - * So we check before, if we are interested on this event really. + * So we check before, if we are interested in this event really. * * @see #impl_frameAction * @@ -247,7 +247,7 @@ class StatusListener implements com.sun.star.frame.XStatusListener, // Then we should colorize it gray... m_rControl.setEnabled(aEvent.IsEnabled); - // Only if status is enabled we can look for his value! + // Only if status is enabled we can look for its value! if (aEvent.IsEnabled) { // look for the right type of the UI control @@ -382,14 +382,14 @@ class StatusListener implements com.sun.star.frame.XStatusListener, /** * callback for disposing events - * Our dispatch or frame object inform us about his following dead ... + * Our dispatch or frame object informs us about his following death ... * So we must forget his reference. But it's not necessary to * remove listener connections here. Because the broadcaster - * forget us automatically. The only thing we have to do: release + * forgets us automatically. The only thing we have to do: release * his reference and let him die! * * @param aEvent - * describes the source which fire this event + * describes the source which fires this event * Must be our internal saved dispatch or frame. Otherwise * somewhere know us without a registration ... */ @@ -418,7 +418,7 @@ class StatusListener implements com.sun.star.frame.XStatusListener, /** - * If this java application shutdown - we must cancel all current existing + * If this java application shuts down - we must cancel all current existing * listener connections. Otherwise the office will run into some * DisposedExceptions if it tries to use these forgotten listener references. * And of course it can die doing that. diff --git a/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleHyphenator.java b/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleHyphenator.java index 4fcd413a723b..c46ffd836a38 100644 --- a/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleHyphenator.java +++ b/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleHyphenator.java @@ -214,7 +214,7 @@ public class SampleHyphenator extends ComponentBase implements return null; // linguistic is currently not allowed to throw exceptions - // thus we return null fwhich means 'word cannot be hyphenated' + // thus we return null which means 'word cannot be hyphenated' if (!hasLocale( aLocale )) return null; @@ -465,7 +465,7 @@ public class SampleHyphenator extends ComponentBase implements * Returns a factory for creating the service. * This method is called by the JavaLoader *

      - * @return returns a XComponentServiceFactory for creating the component + * @return returns an XSingleComponentFactory for creating the component * @param aImplName the name of the implementation for which a service is desired * @see com.sun.star.comp.loader.JavaLoader */ diff --git a/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleSpellChecker.java b/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleSpellChecker.java index 9608929932fa..beb46a6ac23e 100644 --- a/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleSpellChecker.java +++ b/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleSpellChecker.java @@ -315,7 +315,7 @@ public class SampleSpellChecker extends ComponentBase implements return null; // linguistic is currently not allowed to throw exceptions - // thus we return null fwhich means 'word cannot be spelled' + // thus we return null which means 'word cannot be spelled' if (!hasLocale( aLocale )) return null; @@ -420,7 +420,7 @@ public class SampleSpellChecker extends ComponentBase implements * Returns a factory for creating the service. * This method is called by the JavaLoader *

      - * @return returns a XSingleComponentFactory for creating the component + * @return returns an XSingleComponentFactory for creating the component * @param aImplName the name of the implementation for which a service is desired * @see com.sun.star.comp.loader.JavaLoader */ diff --git a/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleThesaurus.java b/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleThesaurus.java index 420d85d481aa..4369b433e8bc 100644 --- a/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleThesaurus.java +++ b/odk/examples/DevelopersGuide/OfficeDev/Linguistic/SampleThesaurus.java @@ -170,7 +170,7 @@ public class SampleThesaurus extends ComponentBase implements return null; // linguistic is currently not allowed to throw exceptions - // thus we return null fwhich means 'word cannot be looked up' + // thus we return null which means 'word cannot be looked up' if (!hasLocale( aLocale )) return null; @@ -270,7 +270,7 @@ public class SampleThesaurus extends ComponentBase implements * Returns a factory for creating the service. * This method is called by the JavaLoader *

      - * @return returns a XSingleComponentFactory for creating the component + * @return returns an XSingleComponentFactory for creating the component * @param aImplName the name of the implementation for which a service is desired * @see com.sun.star.comp.loader.JavaLoader */ diff --git a/odk/examples/DevelopersGuide/Text/TextDocuments.java b/odk/examples/DevelopersGuide/Text/TextDocuments.java index 2ccd270e281d..3613443d453e 100644 --- a/odk/examples/DevelopersGuide/Text/TextDocuments.java +++ b/odk/examples/DevelopersGuide/Text/TextDocuments.java @@ -103,7 +103,7 @@ import com.sun.star.view.XPrintable; public class TextDocuments { - // adjust these constant to your local printer! + // adjust these constants to your local printer! private static String sOutputDir; private static final String aPrinterName = "\\\\so-print\\xml3sof"; @@ -724,7 +724,7 @@ public class TextDocuments { insertIntoCell( "C1", "Third Column", xTable ); insertIntoCell( "D1", "Results", xTable ); - // Insert random numbers into the first this three cells of each + // Insert random numbers into the first three cells of each // remaining row xTable.getCellByName( "A2" ).setValue( getRandomDouble() ); xTable.getCellByName( "B2" ).setValue( getRandomDouble() ); @@ -856,7 +856,7 @@ public class TextDocuments { // We want the background to be light blue xTableProps.setPropertyValue( "BackColor", Integer.valueOf(13421823)); - // Inser the table into the document + // Insert the table into the document mxDocText.insertTextContent( mxDocCursor, xTable, false); // Get an XIndexAccess to all table rows @@ -890,7 +890,7 @@ public class TextDocuments { XText.class, xTable.getCellByName ( sCellName ) ); // Set the cell contents of the current cell to be - //the name of the of an autotext group + // the name of an autotext group xCellText.setString ( aGroupNames[i] ); // Access the autotext group with this name @@ -1518,7 +1518,7 @@ public class TextDocuments { xParas[1].setPropertyValue ( "NumberingLevel", Short.valueOf((short) 1)); // Set the third paragraph that was inserted to a numbering level of - // 0 (thus it will have 'Chars Upper Letter' style numbering) + // 0 (thus it will have 'Roman Upper' style numbering) xParas[2].setPropertyValue ( "NumberingLevel", Short.valueOf((short) 0)); } catch (Exception e) diff --git a/odk/examples/DevelopersGuide/UCB/DataStreamComposer.java b/odk/examples/DevelopersGuide/UCB/DataStreamComposer.java index ce6edae31998..92a97c9d9b03 100644 --- a/odk/examples/DevelopersGuide/UCB/DataStreamComposer.java +++ b/odk/examples/DevelopersGuide/UCB/DataStreamComposer.java @@ -60,7 +60,7 @@ public class DataStreamComposer { * -workdir=... (optional) * See Help (method printCmdLineUsage()). * Without the arguments a new connection to a - * running office cannot created. + * running office cannot be created. */ public DataStreamComposer( String args[] ) throws java.lang.Exception { @@ -94,7 +94,7 @@ public class DataStreamComposer { * Write the document data stream of a document content. * *@param sourceURL Source URL - *@return true if data stream successfully seted, false otherwise + *@return true if data stream successfully set, false otherwise */ public boolean setDataStream( String sourceURL ) throws com.sun.star.ucb.CommandAbortedException, @@ -116,7 +116,7 @@ public class DataStreamComposer { /** * Write the document data stream of a document content... * - *@return boolean Returns true if data stream successfully seted, false otherwise + *@return boolean Returns true if data stream successfully set, false otherwise */ public boolean setDataStream( XInputStream stream ) throws com.sun.star.ucb.CommandAbortedException, com.sun.star.uno.Exception { diff --git a/odk/examples/DevelopersGuide/UCB/PropertiesComposer.java b/odk/examples/DevelopersGuide/UCB/PropertiesComposer.java index 1ebc9cbaab79..498336c5b0e0 100644 --- a/odk/examples/DevelopersGuide/UCB/PropertiesComposer.java +++ b/odk/examples/DevelopersGuide/UCB/PropertiesComposer.java @@ -63,7 +63,7 @@ public class PropertiesComposer { * -workdir=... (optional) * See Help (method printCmdLineUsage()). * Without the arguments a new connection to a - * running office cannot created. + * running office cannot be created. */ public PropertiesComposer( String args[] ) throws java.lang.Exception { @@ -83,7 +83,7 @@ public class PropertiesComposer { * See Constructor. * *@return Object[] Returns null or instance object of com.sun.star.uno.Any - * if values successfully seted, properties otherwise + * if values successfully set, properties otherwise */ public Object[] setProperties() throws com.sun.star.ucb.CommandAbortedException, com.sun.star.uno.Exception { @@ -96,7 +96,7 @@ public class PropertiesComposer { * Set values of the properties. * *@return Object[] Returns null or instance object of com.sun.star.uno.Any - * if values successfully seted, properties otherwise + * if values successfully set, properties otherwise */ public Object[] setProperties( ArrayList properties, ArrayList propertiesValues ) throws com.sun.star.ucb.CommandAbortedException, com.sun.star.uno.Exception { diff --git a/odk/examples/DevelopersGuide/examples.html b/odk/examples/DevelopersGuide/examples.html index 2564c2d322e7..bd9b652b4495 100644 --- a/odk/examples/DevelopersGuide/examples.html +++ b/odk/examples/DevelopersGuide/examples.html @@ -161,13 +161,21 @@ Content Broker (UCB) - Graphical User Interfaces + Office Bean Scripting Framework + + + Graphical User Interfaces + + + @@ -2655,6 +2663,60 @@ configuration in various ways. + + + + + + + + + + +
      + + + + + + + +
      Office +Bean example
      +
      + + + + + + + + + + + +
      ExampleDescription
      OOoBeanViewerShows how to use the OOoBean +embedded in a Java AWT component. It shows how to load and store +documents as well as how to control toolbar visibility.
      +
      + + + + + + + + diff --git a/odk/examples/cpp/complextoolbarcontrols/MyProtocolHandler.cxx b/odk/examples/cpp/complextoolbarcontrols/MyProtocolHandler.cxx index 3fd70340aebc..067c18ec36a1 100644 --- a/odk/examples/cpp/complextoolbarcontrols/MyProtocolHandler.cxx +++ b/odk/examples/cpp/complextoolbarcontrols/MyProtocolHandler.cxx @@ -198,11 +198,11 @@ Sequence< ::rtl::OUString > SAL_CALL MyProtocolHandler::getSupportedServiceNames void SAL_CALL BaseDispatch::dispatch( const URL& aURL, const Sequence < PropertyValue >& lArgs ) { /* It's necessary to hold this object alive, till this method finishes. - May the outside dispatch cache (implemented by the menu/toolbar!) - forget this instance during de-/activation of frames (focus!). + Maybe the outside dispatch cache (implemented by the menu/toolbar!) + forgets this instance during de-/activation of frames (focus!). E.g. An open db beamer in combination with the My-Dialog - can force such strange situation :-( + can force such a strange situation :-( */ Reference< XInterface > xSelfHold(static_cast< XDispatch* >(this), UNO_QUERY); @@ -252,7 +252,7 @@ void SAL_CALL BaseDispatch::dispatch( const URL& aURL, const Sequence < Property } } - // create new URL to address the combox box + // create a new URL to address the combobox URL aCmdURL; aCmdURL.Path = "ComboboxCmd"; aCmdURL.Protocol = "vnd.demo.complextoolbarcontrols.demoaddon:"; diff --git a/odk/examples/java/ConverterServlet/README b/odk/examples/java/ConverterServlet/README index ea59b80b43c0..d3b1d0d3bb11 100644 --- a/odk/examples/java/ConverterServlet/README +++ b/odk/examples/java/ConverterServlet/README @@ -21,7 +21,7 @@ Installation instructions: server. You can download the Servlet API from http://java.sun.com/products/servlet/index.html . 4. Use your GNU make (http://www.gnu.org) to build the servlet class. 5. Make the servlet class known to your web server. - The example creates also a WAR file which can be easy deployed in a Tomcat server. + The example creates also a WAR file which can be easily deployed in a Tomcat server. 5.1 Browse the 'Tomcat Web Application Manager' 5.2 Navigate into the section 'Upload a WAR file to install' 5.3 Browse to your generated WAR file and select it diff --git a/odk/examples/java/Inspector/SourceCodeGenerator.java b/odk/examples/java/Inspector/SourceCodeGenerator.java index 9ff6ad7933dd..49aa7f868c6a 100644 --- a/odk/examples/java/Inspector/SourceCodeGenerator.java +++ b/odk/examples/java/Inspector/SourceCodeGenerator.java @@ -468,7 +468,7 @@ public class SourceCodeGenerator { sTypeString = m_xLanguageSourceCodeGenerator.getdoubleTypeDescription(); break; case TypeClass.SEQUENCE_value: - //TODO consider mulitdimensional Arrays + //TODO consider multidimensional Arrays XTypeDescription xTypeDescription = Introspector.getIntrospector().getReferencedType(_sTypeName); if (xTypeDescription != null){ sTypeString = getTypeString(xTypeDescription.getName(), xTypeDescription.getTypeClass(), _bAsHeaderSourceCode); @@ -583,7 +583,7 @@ private class UnoObjectDefinition{ int nTypeClass = _aTypeClass.getValue(); switch(nTypeClass){ case TypeClass.SEQUENCE_value: - //TODO consider mulitdimensional Arrays + //TODO consider multidimensional Arrays XTypeDescription xTypeDescription = Introspector.getIntrospector().getReferencedType(getTypeName()); if (xTypeDescription != null){ sCentralVariableStemName = getCentralVariableStemName(xTypeDescription.getTypeClass()); @@ -674,7 +674,7 @@ private class UnoObjectDefinition{ sVariableStemName = "s" + m_sCentralVariableStemName; break; case TypeClass.SEQUENCE_value: - //TODO consider mulitdimensional Arrays + //TODO consider multidimensional Arrays XTypeDescription xTypeDescription = Introspector.getIntrospector().getReferencedType(getTypeName()); if (xTypeDescription != null){ sVariableStemName = getVariableStemName(xTypeDescription.getTypeClass()); diff --git a/odk/examples/java/MinimalComponent/MinimalComponent.java b/odk/examples/java/MinimalComponent/MinimalComponent.java index b8efbafcc429..64204db00363 100644 --- a/odk/examples/java/MinimalComponent/MinimalComponent.java +++ b/odk/examples/java/MinimalComponent/MinimalComponent.java @@ -57,7 +57,7 @@ public class MinimalComponent { private static final String __serviceName = "org.openoffice.MinimalComponent"; - /** The initial component contextr, that gives access to + /** The initial component context, that gives access to * the service manager, supported singletons, ... * It's often later used */ @@ -68,8 +68,8 @@ public class MinimalComponent { */ private XMultiComponentFactory m_xMCF; - /** The constructor of the inner class has a XMultiServiceFactory parameter. - * @param xCompContext A special service factory + /** The constructor of the inner class has an XComponentContext parameter. + * @param xCompContext A special component context * could be introduced while initializing. */ public _MinimalComponent(XComponentContext xCompContext) { @@ -104,7 +104,7 @@ public class MinimalComponent { return getServiceNames(); } - /** This method is a simple helper function to used in the + /** This method is a simple helper function to be used in the * static component initialisation functions as well as in * getSupportedServiceNames. */ @@ -135,7 +135,7 @@ public class MinimalComponent { * Gives a factory for creating the service. * This method is called by the JavaLoader *

      - * @return returns a XSingleComponentFactory for creating + * @return returns an XSingleComponentFactory for creating * the component * @param sImplName the name of the implementation for which a * service is desired diff --git a/odk/examples/java/ToDo/ToDo.java b/odk/examples/java/ToDo/ToDo.java index 36d0d7eece6a..8c6f23784f1c 100644 --- a/odk/examples/java/ToDo/ToDo.java +++ b/odk/examples/java/ToDo/ToDo.java @@ -82,7 +82,7 @@ public class ToDo { */ private static final String __serviceName = "org.openoffice.ToDo"; - /** The initial component contextr, that gives access to + /** The initial component context, that gives access to * the service manager, supported singletons, ... * It's often later used */ @@ -111,7 +111,7 @@ public class ToDo { private static final String STRING_SEPARATOR = "/"; - /** The constructor of the inner class has a XComponenContext parameter. + /** The constructor of the inner class has an XComponentContext parameter. * @param xCompContext the initial component context */ public ToDoImpl(XComponentContext xCompContext) { @@ -559,8 +559,8 @@ public class ToDo { intRow,ToDoImpl.INT_COLUMN_ENDDATE)); } else { - // Set the start date with the absolute s - // tart date + // Set the start date with the absolute + // start date gregCalStartDate = (GregorianCalendar) gregCalAbsoluteStartDate.clone(); } @@ -912,7 +912,7 @@ public class ToDo { * Gives a factory for creating the service. * This method is called by the JavaLoader *

      - * @return returns a XSingleComponentFactory for creating + * @return returns an XSingleComponentFactory for creating * the component * @param sImplName the name of the implementation for which a * service is desired diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index 280f24e20774..ab9cdc791ce8 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -45,6 +45,7 @@ $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,com/sun/star/awt,\ ContainerWindowProvider \ DialogProvider \ DialogProvider2 \ + FontVariations \ MenuBar \ Pointer \ PopupMenu \ @@ -478,34 +479,7 @@ $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,com/sun/star/xml/xslt,\ XSLTTransformer \ )) - -$(eval $(call gb_UnoApi_add_idlfiles_noheader,offapi,com/sun/star/accessibility,\ - AccessibleContext \ -)) $(eval $(call gb_UnoApi_add_idlfiles_noheader,offapi,com/sun/star/awt,\ - AccessibleButton \ - AccessibleCheckBox \ - AccessibleComboBox \ - AccessibleEdit \ - AccessibleFixedText \ - AccessibleList \ - AccessibleListBox \ - AccessibleMenu \ - AccessibleMenuBar \ - AccessibleMenuItem \ - AccessibleMenuSeparator \ - AccessiblePopupMenu \ - AccessibleRadioButton \ - AccessibleScrollBar \ - AccessibleStatusBar \ - AccessibleStatusBarItem \ - AccessibleTabBar \ - AccessibleTabBarPage \ - AccessibleTabBarPageList \ - AccessibleTabControl \ - AccessibleTabPage \ - AccessibleTextField \ - AccessibleWindow \ AnimatedImagesControl \ AnimatedImagesControlModel \ RoadmapItem \ @@ -599,10 +573,12 @@ $(eval $(call gb_UnoApi_add_idlfiles_noheader,offapi,com/sun/star/chart,\ ChartTitle \ ChartTwoAxisXSupplier \ ChartTwoAxisYSupplier \ + CorrelationCircleDiagram \ Diagram \ Dim3DDiagram \ DonutDiagram \ FilledNetDiagram \ + HistogramDiagram \ LineDiagram \ NetDiagram \ PieDiagram \ @@ -617,7 +593,7 @@ $(eval $(call gb_UnoApi_add_idlfiles_noheader,offapi,com/sun/star/chart2,\ ChartDocumentWrapper \ ChartType \ ChartTypeManager \ - ChartTypeTemplate\ + ChartTypeTemplate \ CoordinateSystem \ CoordinateSystemType \ DataPoint \ @@ -740,7 +716,6 @@ $(eval $(call gb_UnoApi_add_idlfiles_noheader,offapi,com/sun/star/document,\ )) $(eval $(call gb_UnoApi_add_idlfiles_noheader,offapi,com/sun/star/drawing,\ AccessibleDrawDocumentView \ - AccessibleImageBullet \ AppletShape \ Background \ BitmapTable \ @@ -1678,6 +1653,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/awt,\ FocusChangeReason \ FocusEvent \ FontDescriptor \ + FontVariationAxis \ FontEmphasisMark \ FontFamily \ FontPitch \ @@ -1780,6 +1756,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/awt,\ XFont \ XFont2 \ XFontMappingUse \ + XFontVariations \ XFontMappingUseItem \ XGraphics \ XGraphics2 \ @@ -2347,9 +2324,6 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/drawing,\ XSlideSorterSelectionSupplier \ XUniversalShapeDescriptor \ )) -$(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/drawing/framework,\ - AnchorBindingMode \ -)) $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/embed,\ Actions \ Aspects \ @@ -2918,6 +2892,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/presentation,\ XSlideShowListener \ XSlideShowNavigationListener \ XSlideShowView \ + XSoundReference \ XTransition \ XTransitionFactory \ )) @@ -3017,7 +2992,6 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/rendering,\ XMtfRenderer \ XParametricPolyPolygon2D \ XPolyPolygon2D \ - XSimpleCanvas \ XSprite \ XSpriteCanvas \ XTextLayout \ @@ -3091,6 +3065,11 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/script/browse,\ BrowseNodeTypes \ XBrowseNode \ XBrowseNodeFactory \ + XCopyableBrowseNode \ + XCreatableBrowseNode \ + XDeletableBrowseNode \ + XEditableBrowseNode \ + XRenamableBrowseNode \ )) $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/script/provider,\ ScriptErrorRaisedException \ @@ -3359,6 +3338,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/sheet,\ DataResult \ DataResultFlags \ DimensionFlags \ + ExternalLinkRelType \ ExternalLinkInfo \ ExternalLinkType \ ExternalReference \ @@ -3379,7 +3359,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/sheet,\ FunctionArgument \ FunctionCategory \ GeneralFunction \ - GeneralFunction2 \ + GeneralFunction2 \ GoalResult \ IconSetFormatEntry \ IconSetType \ @@ -4389,8 +4369,11 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,org/libreoffice/embindtest, \ Template \ XArgumentStore \ XAttributes \ + XPassthrough \ XStringFactory \ XTest \ + theMethodToString \ + thePassthrough \ theSingleton \ )) $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,org/libreoffice/embindtest, \ diff --git a/offapi/com/sun/star/accessibility/AccessibleContext.idl b/offapi/com/sun/star/accessibility/AccessibleContext.idl deleted file mode 100644 index f95fd64a140c..000000000000 --- a/offapi/com/sun/star/accessibility/AccessibleContext.idl +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module accessibility { - - interface XAccessibleContext; - interface XAccessibleEventBroadcaster; - -/** Central service of the Accessibility API that gives access to various - facets of an object's content. - -

      This service has to be implemented by every class that represents the - actual accessibility information of another UNO service. It exposes two - kinds of information: A tree structure in which all accessible objects - are organized can be navigated in freely. It typically represents - spatial relationship of one object containing a set of children like a - dialog box contains a set of buttons. Additionally the - XAccessibleContext interface of this service exposes - methods that provide access to the actual object's content. This can be - the object's role, name, description, and so on.

      - - @see XAccessibleContext - - @since OOo 1.1.2 -*/ -service AccessibleContext -{ - interface XAccessibleContext; - - /** is implemented by accessible contexts that supports broadcasting of - accessible events. - - @see AccessibleEventObject - @see AccessibleEventId - */ - [optional] interface XAccessibleEventBroadcaster; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/accessibility/XMSAAService.idl b/offapi/com/sun/star/accessibility/XMSAAService.idl index 9c8094a311e6..73ae1e5ace45 100644 --- a/offapi/com/sun/star/accessibility/XMSAAService.idl +++ b/offapi/com/sun/star/accessibility/XMSAAService.idl @@ -28,7 +28,7 @@ interface XMSAAService : ::com::sun::star::lang::XComponent @return A reference to the object that contains the actual accessibility information. - @see AccessibleContext + @see XAccessibleContext */ hyper getAccObjectPtr([in] hyper hWnd, [in] hyper lParam, [in] hyper wParam); }; diff --git a/offapi/com/sun/star/awt/AccessibleButton.idl b/offapi/com/sun/star/awt/AccessibleButton.idl deleted file mode 100644 index 69c90bd870f7..000000000000 --- a/offapi/com/sun/star/awt/AccessibleButton.idl +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a button. - - @since OOo 1.1.2 - */ -service AccessibleButton -{ - /** This interface gives access to the structural information of a button: - -
        -
      • Role: The role of a button is - com::sun::star::accessibility::AccessibleRole::PUSH_BUTTON.
      • -
      • Name: The name of a button is its localized label.
      • -
      • Description: The description of a button is its localized - help text.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent is the window that contains the button.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::CHECKABLE - is set if the object is checkable, i.e. can be checked.
        • -
        • com::sun::star::accessibility::AccessibleStateType::CHECKED - is set if the object is currently checked.
        • -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::PRESSED - is set if the object is currently pressed.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives read-only access to the text representation - of a button. - */ - interface ::com::sun::star::accessibility::XAccessibleText; - - /** This interface gives access to the actions that can be executed for - a button. The supported actions for a button are: -
        -
      • click
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleAction; - - /** This interface gives access to the numerical value of a button, - which is related to the button's - com::sun::star::accessibility::AccessibleStateType::PRESSED state. - */ - interface ::com::sun::star::accessibility::XAccessibleValue; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleCheckBox.idl b/offapi/com/sun/star/awt/AccessibleCheckBox.idl deleted file mode 100644 index a8934139006f..000000000000 --- a/offapi/com/sun/star/awt/AccessibleCheckBox.idl +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a check box. - - @since OOo 1.1.2 - */ -service AccessibleCheckBox -{ - /** This interface gives access to the structural information of a - check box: - -
        -
      • Role: The role of a check box is - com::sun::star::accessibility::AccessibleRole::CHECK_BOX.
      • -
      • Name: The name of a check box is its localized label.
      • -
      • Description: The description of a check box is its localized - help text.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent is the window that contains the check box.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::CHECKABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::CHECKED - is set if the object is currently checked.
        • -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives read-only access to the text representation - of a check box. - */ - interface ::com::sun::star::accessibility::XAccessibleText; - - /** This interface gives access to the actions that can be executed for - a check box. The supported actions for a check box are: -
        -
      • click
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleAction; - - /** This interface gives access to the numerical value of a - check box, which is related to the check box state: - -
      -        0: not checked
      -        1: checked
      -        2: don't know
      -        
      - */ - interface ::com::sun::star::accessibility::XAccessibleValue; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleComboBox.idl b/offapi/com/sun/star/awt/AccessibleComboBox.idl deleted file mode 100644 index 76f77258e211..000000000000 --- a/offapi/com/sun/star/awt/AccessibleComboBox.idl +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module accessibility { - - interface XAccessibleText; - interface XAccessibleExtendedComponent; - interface XAccessibleComponent; - -}; }; }; }; - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a combo box. - - @see com::sun::star::accessibility::AccessibleContext - @see com::sun::star::accessibility::XAccessibleComponent - @see com::sun::star::accessibility::XAccessibleExtendedComponent - @since OOo 1.1.2 -*/ -service AccessibleComboBox -{ - /** This interface gives access to the structural information of a combo box: - -
        -
      • Role: The role of a combo box is - com::sun::star::accessibility::AccessibleRole::COMBO_BOX.
      • -
      • Name: The name of a combo box is its localized label.
      • -
      • Description: The description of a combo box is its localized - help text.
      • -
      • Children: There exists two children. - The first is a com::sun::star::awt::AccessibleTextField - and the 2nd is a com::sun::star::awt::AccessibleList.
      • -
      • Parent: The parent is the window that contains the combo box.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ACTIVE - is set if a child has currently the focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::RESIZABLE - is set if the object can be resized.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - - service com::sun::star::accessibility::AccessibleContext; - - interface com::sun::star::accessibility::XAccessibleComponent; - interface com::sun::star::accessibility::XAccessibleExtendedComponent; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleEdit.idl b/offapi/com/sun/star/awt/AccessibleEdit.idl deleted file mode 100644 index 2a9526744bd8..000000000000 --- a/offapi/com/sun/star/awt/AccessibleEdit.idl +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for an edit. - - @since OOo 1.1.2 - */ -service AccessibleEdit -{ - /** This interface gives access to the structural information of an edit: - -
        -
      • Role: The role of an edit is - com::sun::star::accessibility::AccessibleRole::TEXT. - If the text content of the edit is password protected - the role is - com::sun::star::accessibility::AccessibleRole::PASSWORD_TEXT.
      • -
      • Name: If the relation of type - com::sun::star::accessibility::AccessibleRelationType::LABELED_BY - is set, the name of the edit is the localized label of the target - object, otherwise there is no name.
      • -
      • Description: The description of an edit is its localized - help text.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent is the window that contains the edit.
      • -
      • Relations: The relations supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleRelationType::LABELED_BY - is set if the object is labeled by one or more target - objects.
        • -
        -
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::EDITABLE - is set - if the content of the object can be changed by the user.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives read-only access to the text representation - of an edit. - */ - interface ::com::sun::star::accessibility::XAccessibleText; - - /** This interface extends the - com::sun::star::accessibility::XAccessibleText - interface and gives read and write access to the text representation - of an edit. - */ - interface ::com::sun::star::accessibility::XAccessibleEditableText; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleFixedText.idl b/offapi/com/sun/star/awt/AccessibleFixedText.idl deleted file mode 100644 index 28099f50b74b..000000000000 --- a/offapi/com/sun/star/awt/AccessibleFixedText.idl +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a fixed text. - - @since OOo 1.1.2 - */ -service AccessibleFixedText -{ - /** This interface gives access to the structural information of a - fixed text: - -
        -
      • Role: The role of a fixed text is - com::sun::star::accessibility::AccessibleRole::LABEL.
      • -
      • Name: The name of a fixed text is its localized label.
      • -
      • Description: The description of a fixed text is its localized - help text.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent is the window that contains the fixed text.
      • -
      • Relations: The relations supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleRelationType::LABEL_FOR - is set if the object is a label for one or more target - objects.
        • -
        -
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::MULTI_LINE - is set if the object contains multiple lines of text.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives read-only access to the text representation - of a fixed text. - */ - interface ::com::sun::star::accessibility::XAccessibleText; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleList.idl b/offapi/com/sun/star/awt/AccessibleList.idl deleted file mode 100644 index dc5b4e00ba7d..000000000000 --- a/offapi/com/sun/star/awt/AccessibleList.idl +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module accessibility { - - interface XAccessible; - interface XAccessibleExtendedComponent; - interface XAccessibleComponent; - interface XAccessibleSelection; - -}; }; }; }; - -module com { module sun { module star { module awt { - - - -/** Accessible lists are used by combo boxes as container for - the list items. - - @see com::sun::star::accessibility::AccessibleContext - - @see com::sun::star::accessibility::XAccessibleComponent - @see com::sun::star::accessibility::XAccessibleExtendedComponent - @see ::com::sun::star::accessibility::XAccessibleSelection - - @since OOo 1.1.2 -*/ -service AccessibleList -{ - /** This interface gives access to the structural information of a list: - -
        -
      • Role: The role of a list is - ::com::sun::star::accessibility::AccessibleRole::LIST.
      • -
      • Name: The name of a list is its localized label.
      • -
      • Description: The description of a list is its localized - help text.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ACTIVE - is set if a child has currently the focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::RESIZABLE - is set if the object can be resized.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::MULTI_SELECTABLE - is set if the list supports multi selection.
        • -
        • com::sun::star::accessibility::AccessibleStateType::MANAGES_DESCENDANTS - is always set. - The children are transient.
        • -
        -
      • -
      - */ - service com::sun::star::accessibility::AccessibleContext; - - interface com::sun::star::accessibility::XAccessibleComponent; - interface com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** Support of the com::sun::star::accessibility::XAccessible interface may be - discontinued in the future. - */ - interface com::sun::star::accessibility::XAccessible; - - /** This interface gives access to the selectable children of a - list. - */ - interface com::sun::star::accessibility::XAccessibleSelection; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleListBox.idl b/offapi/com/sun/star/awt/AccessibleListBox.idl deleted file mode 100644 index 1c343cbeb40b..000000000000 --- a/offapi/com/sun/star/awt/AccessibleListBox.idl +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module accessibility { - - interface XAccessibleSelection; - interface XAccessibleExtendedComponent; - interface XAccessibleComponent; - -}; }; }; }; - -module com { module sun { module star { module awt { -/** specifies accessibility support for a list box. - - @see com::sun::star::accessibility::AccessibleContext - - @see com::sun::star::accessibility::XAccessibleComponent - @see com::sun::star::accessibility::XAccessibleExtendedComponent - - @since OOo 1.1.2 -*/ -service AccessibleListBox -{ - /** This interface gives access to the structural information of a list box: - -
        -
      • Role: The role of a list box is - com::sun::star::accessibility::AccessibleRole::PANEL.
      • -
      • Name: The name of a list box is its localized label.
      • -
      • Description: The description of a list box is its localized - help text.
      • -
      • Children: There exists one child. - It is of type com::sun::star::awt::AccessibleList.
      • -
      • Parent: The parent is the window that contains the list box.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ACTIVE - is set if a child has currently the focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::RESIZABLE - is set if the object can be resized.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - service com::sun::star::accessibility::AccessibleContext; - - interface com::sun::star::accessibility::XAccessibleComponent; - interface com::sun::star::accessibility::XAccessibleExtendedComponent; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleMenu.idl b/offapi/com/sun/star/awt/AccessibleMenu.idl deleted file mode 100644 index 276b4b7a77f3..000000000000 --- a/offapi/com/sun/star/awt/AccessibleMenu.idl +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a menu. - - @since OOo 1.1.2 - */ -service AccessibleMenu -{ - /** This interface gives access to the structural information of a menu: - -
        -
      • Role: The role of a menu is - com::sun::star::accessibility::AccessibleRole::MENU.
      • -
      • Name: The name of a menu is the localized item text.
      • -
      • Description: The description of a menu is its localized - help text.
      • -
      • Children: The children of a menu are menus, menu items or - menu separators, whose accessible context supports the services - AccessibleMenu, AccessibleMenuItem or - AccessibleMenuSeparator.
      • -
      • Parent: The parent of a menu is a menu bar, a pop-up menu or - a menu, whose accessible context supports the services - AccessibleMenuBar, AccessiblePopupMenu - or AccessibleMenu.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::ARMED - is set if the object is highlighted.
        • -
        • com::sun::star::accessibility::AccessibleStateType::CHECKABLE - is set if the object is checkable, i.e. can be checked.
        • -
        • com::sun::star::accessibility::AccessibleStateType::CHECKED - is set if the object is currently checked.
        • -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::OPAQUE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTED - is set if the object is selected.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives read-only access to the text representation - of a menu. - */ - interface ::com::sun::star::accessibility::XAccessibleText; - - /** This interface gives access to the actions that can be executed for - a menu. The supported actions for a menu are: -
        -
      • select
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleAction; - - /** This interface gives access to the numerical value of a - menu, which is related to the menu's - com::sun::star::accessibility::AccessibleStateType::SELECTED state. - */ - interface ::com::sun::star::accessibility::XAccessibleValue; - - /** This interface gives access to the selectable children of a - menu. - */ - interface ::com::sun::star::accessibility::XAccessibleSelection; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleMenuBar.idl b/offapi/com/sun/star/awt/AccessibleMenuBar.idl deleted file mode 100644 index d36a42534a6d..000000000000 --- a/offapi/com/sun/star/awt/AccessibleMenuBar.idl +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a menu bar. - - @since OOo 1.1.2 - */ -service AccessibleMenuBar -{ - /** This interface gives access to the structural information of a - menu bar: - -
        -
      • Role: The role of a menu bar is - com::sun::star::accessibility::AccessibleRole::MENU_BAR.
      • -
      • Name: There is no name.
      • -
      • Description: The description of a menu bar is its localized - help text.
      • -
      • Children: The children of a menu bar are menus, menu items or - menu separators, whose accessible context supports the services - AccessibleMenu, AccessibleMenuItem or - AccessibleMenuSeparator.
      • -
      • Parent: The parent is the window that contains the menu bar.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::OPAQUE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives access to the selectable children of a - menu bar. - */ - interface ::com::sun::star::accessibility::XAccessibleSelection; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleMenuItem.idl b/offapi/com/sun/star/awt/AccessibleMenuItem.idl deleted file mode 100644 index ef86f72009f4..000000000000 --- a/offapi/com/sun/star/awt/AccessibleMenuItem.idl +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a menu item. - - @since OOo 1.1.2 - */ -service AccessibleMenuItem -{ - /** This interface gives access to the structural information of a - menu item: - -
        -
      • Role: The role of a menu item is - com::sun::star::accessibility::AccessibleRole::MENU_ITEM.
      • -
      • Name: The name of a menu item is the localized item text.
      • -
      • Description: The description of a menu item is its localized - help text.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent of a menu item is a menu bar, a pop-up menu or - a menu, whose accessible context supports the services - AccessibleMenuBar, AccessiblePopupMenu - or AccessibleMenu.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::ARMED - is set if the object is highlighted.
        • -
        • com::sun::star::accessibility::AccessibleStateType::CHECKABLE - is set if the object is checkable, i.e. can be checked.
        • -
        • com::sun::star::accessibility::AccessibleStateType::CHECKED - is set if the object is currently checked.
        • -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::OPAQUE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTED - is set if the object is selected.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives read-only access to the text representation - of a menu item. - */ - interface ::com::sun::star::accessibility::XAccessibleText; - - /** This interface gives access to the actions that can be executed for - a menu item. The supported actions for a menu item are: -
        -
      • select
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleAction; - - /** This interface gives access to the numerical value of a - menu item, which is related to the menu item's - com::sun::star::accessibility::AccessibleStateType::SELECTED state. - */ - interface ::com::sun::star::accessibility::XAccessibleValue; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleMenuSeparator.idl b/offapi/com/sun/star/awt/AccessibleMenuSeparator.idl deleted file mode 100644 index b44015e0456d..000000000000 --- a/offapi/com/sun/star/awt/AccessibleMenuSeparator.idl +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a menu separator. - - @since OOo 1.1.2 - */ -service AccessibleMenuSeparator -{ - /** This interface gives access to the structural information of a - menu separator: - -
        -
      • Role: The role of a menu separator is - com::sun::star::accessibility::AccessibleRole::SEPARATOR.
      • -
      • Name: There is no name.
      • -
      • Description: There is no description.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent of a menu separator is a menu bar, - a pop-up menu or a menu, whose accessible context supports the - services AccessibleMenuBar, - AccessiblePopupMenu or - AccessibleMenu.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • -
        • -
        • com::sun::star::accessibility::AccessibleStateType::OPAQUE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTED - is set if the object is selected.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessiblePopupMenu.idl b/offapi/com/sun/star/awt/AccessiblePopupMenu.idl deleted file mode 100644 index 035189839e17..000000000000 --- a/offapi/com/sun/star/awt/AccessiblePopupMenu.idl +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a pop-up menu. - - @since OOo 1.1.2 - */ -service AccessiblePopupMenu -{ - /** This interface gives access to the structural information of a - pop-up menu: - -
        -
      • Role: The role of a pop-up menu is - com::sun::star::accessibility::AccessibleRole::POPUP_MENU.
      • -
      • Name: There is no name.
      • -
      • Description: The description of a pop-up menu is its localized - help text.
      • -
      • Children: The children of a pop-up menu are menus, menu items or - menu separators, whose accessible context supports the services - AccessibleMenu, AccessibleMenuItem or - AccessibleMenuSeparator.
      • -
      • Parent: The parent is the window that contains the pop-up menu.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::OPAQUE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives access to the selectable children of a - pop-up menu. - */ - interface ::com::sun::star::accessibility::XAccessibleSelection; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleRadioButton.idl b/offapi/com/sun/star/awt/AccessibleRadioButton.idl deleted file mode 100644 index 8c49b6a7c64a..000000000000 --- a/offapi/com/sun/star/awt/AccessibleRadioButton.idl +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a radio button. - - @since OOo 1.1.2 - */ -service AccessibleRadioButton -{ - /** This interface gives access to the structural information of a - radio button: - -
        -
      • Role: The role of a radio button is - com::sun::star::accessibility::AccessibleRole::RADIO_BUTTON.
      • -
      • Name: The name of a radio button is its localized label.
      • -
      • Description: The description of a radio button is its localized - help text.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent is the window that contains the radio button.
      • -
      • Relations: The relations supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleRelationType::MEMBER_OF - is set if the object is a member of a group of one or more - target objects.
        • -
        -
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::CHECKABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::CHECKED - is set if the object is currently checked.
        • -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives read-only access to the text representation - of a radio button. - */ - interface ::com::sun::star::accessibility::XAccessibleText; - - /** This interface gives access to the actions that can be executed for - a radio button. The supported actions for a radio button are: -
        -
      • click
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleAction; - - /** This interface gives access to the numerical value of a - radio button, which is related to the radio button's - com::sun::star::accessibility::AccessibleStateType::CHECKED state. - */ - interface ::com::sun::star::accessibility::XAccessibleValue; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleScrollBar.idl b/offapi/com/sun/star/awt/AccessibleScrollBar.idl deleted file mode 100644 index ddb035b427dc..000000000000 --- a/offapi/com/sun/star/awt/AccessibleScrollBar.idl +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a scroll bar. - - @since OOo 1.1.2 - */ -service AccessibleScrollBar -{ - /** This interface gives access to the structural information of a - scroll bar: - -
        -
      • Role: The role of a scroll bar is - com::sun::star::accessibility::AccessibleRole::SCROLL_BAR.
      • -
      • Name: There is no name.
      • -
      • Description: The description of a scroll bar is its localized - help text.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent is the window that contains the scroll bar.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::HORIZONTAL - is set if the orientation of the object is horizontal.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VERTICAL - is set if the orientation of the object is vertical.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives access to the actions that can be executed for - a scroll bar. The supported actions for a scroll bar are: -
        -
      • decrementLine
      • -
      • incrementLine
      • -
      • decrementBlock
      • -
      • incrementBlock
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleAction; - - /** This interface gives access to the numerical value of a scroll bar, - which is related to the position of the scroll bar thumb. - */ - interface ::com::sun::star::accessibility::XAccessibleValue; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleStatusBar.idl b/offapi/com/sun/star/awt/AccessibleStatusBar.idl deleted file mode 100644 index afb31ddb07b8..000000000000 --- a/offapi/com/sun/star/awt/AccessibleStatusBar.idl +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a status bar. - - @since OOo 1.1.2 - */ -service AccessibleStatusBar -{ - /** This interface gives access to the structural information of a - status bar: - -
        -
      • Role: The role of a status bar is - com::sun::star::accessibility::AccessibleRole::STATUS_BAR.
      • -
      • Name: There is no name.
      • -
      • Description: There is no description.
      • -
      • Children: The children of a status bar are status bar items, - whose accessible context supports the service - AccessibleStatusBarItem.
      • -
      • Parent: The parent is the window that contains the status bar.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleStatusBarItem.idl b/offapi/com/sun/star/awt/AccessibleStatusBarItem.idl deleted file mode 100644 index 8bbc9daf35c9..000000000000 --- a/offapi/com/sun/star/awt/AccessibleStatusBarItem.idl +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a status bar item. - - @since OOo 1.1.2 - */ -service AccessibleStatusBarItem -{ - /** This interface gives access to the structural information of a - status bar item: - -
        -
      • Role: The role of a status bar item is - com::sun::star::accessibility::AccessibleRole::LABEL.
      • -
      • Name: The name of a status bar item is its localized - configuration name.
      • -
      • Description: The description of a status bar item is - its localized help text.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent of a status bar item is the status bar, - whose accessible context supports the service - AccessibleStatusBar.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives read-only access to the text representation - of the status bar item. - */ - interface ::com::sun::star::accessibility::XAccessibleText; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleTabBar.idl b/offapi/com/sun/star/awt/AccessibleTabBar.idl deleted file mode 100644 index 9af9fce4f129..000000000000 --- a/offapi/com/sun/star/awt/AccessibleTabBar.idl +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a tabbar. - - @since OOo 1.1.2 - */ -service AccessibleTabBar -{ - /** This interface gives access to the structural information of a - tabbar: - -
        -
      • Role: The role of a tabbar is - com::sun::star::accessibility::AccessibleRole::PANEL.
      • -
      • Name: There is no name.
      • -
      • Description: The description of a tabbar is its localized - help text.
      • -
      • Children: The children of a tabbar are tabbar buttons, - the tabbar sizer and the tabbar page list, - whose accessible context supports the service - AccessibleTabBarPageList.
      • -
      • Parent: The parent is the window that contains the - tabbar.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::RESIZABLE - is set if the size of the object is not fixed.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleTabBarPage.idl b/offapi/com/sun/star/awt/AccessibleTabBarPage.idl deleted file mode 100644 index f1a0aeb2c711..000000000000 --- a/offapi/com/sun/star/awt/AccessibleTabBarPage.idl +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a tabbar page. - - @since OOo 1.1.2 - */ -service AccessibleTabBarPage -{ - /** This interface gives access to the structural information of a - tabbar page: - -
        -
      • Role: The role of a tabbar page is - com::sun::star::accessibility::AccessibleRole::PAGE_TAB.
      • -
      • Name: The name of a tabbar page is the localized - tabbar page text.
      • -
      • Description: The description of a tabbar page is its localized - help text.
      • -
      • Children: There are no children.
      • -
      • Parent: The parent of a tabbar page is the tabbar page list, - whose accessible context supports the service - AccessibleTabBarPageList.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTED - is set if the object is selected.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleTabBarPageList.idl b/offapi/com/sun/star/awt/AccessibleTabBarPageList.idl deleted file mode 100644 index 98cb27a2f2da..000000000000 --- a/offapi/com/sun/star/awt/AccessibleTabBarPageList.idl +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a tabbar page list. - - @since OOo 1.1.2 - */ -service AccessibleTabBarPageList -{ - /** This interface gives access to the structural information of a - tabbar page list: - -
        -
      • Role: The role of a tabbar page list is - com::sun::star::accessibility::AccessibleRole::PAGE_TAB_LIST.
      • -
      • Name: There is no name.
      • -
      • Description: There is no description.
      • -
      • Children: The children of a tabbar page list are tabbar pages, - whose accessible context supports the service - AccessibleTabBarPage.
      • -
      • Parent: The parent of a tabbar page list is the tabbar, - whose accessible context supports the service - AccessibleTabBar.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives access to the selectable children of a - tabbar page list. - */ - interface ::com::sun::star::accessibility::XAccessibleSelection; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleTabControl.idl b/offapi/com/sun/star/awt/AccessibleTabControl.idl deleted file mode 100644 index f77f2c3ded91..000000000000 --- a/offapi/com/sun/star/awt/AccessibleTabControl.idl +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a tab control. - - @since OOo 1.1.2 - */ -service AccessibleTabControl -{ - /** This interface gives access to the structural information of a - tab control: - -
        -
      • Role: The role of a tab control is - com::sun::star::accessibility::AccessibleRole::PAGE_TAB_LIST.
      • -
      • Name: There is no name.
      • -
      • Description: The description of a tab control is its localized - help text.
      • -
      • Children: The children of a tab control are tab pages, - whose accessible context supports the service - AccessibleTabPage.
      • -
      • Parent: The parent is the window that contains the - tab control.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives access to the selectable children of a - tab control. - */ - interface ::com::sun::star::accessibility::XAccessibleSelection; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleTabPage.idl b/offapi/com/sun/star/awt/AccessibleTabPage.idl deleted file mode 100644 index 3ca99229fcad..000000000000 --- a/offapi/com/sun/star/awt/AccessibleTabPage.idl +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a tab page. - - @since OOo 1.1.2 - */ -service AccessibleTabPage -{ - /** This interface gives access to the structural information of a - tab page: - -
        -
      • Role: The role of a tab page is - com::sun::star::accessibility::AccessibleRole::PAGE_TAB.
      • -
      • Name: The name of a tab page is the localized tab page text.
      • -
      • Description: The description of a tab page is its localized - help text.
      • -
      • Children: The child of a tab page is a panel.
      • -
      • Parent: The parent of a tab page is the tab control, - whose accessible context supports the service - AccessibleTabControl.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SELECTED - is set if the object is selected.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - - interface ::com::sun::star::accessibility::XAccessibleComponent; - - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; - - /** This interface gives read-only access to the text representation - of a tab page. - */ - interface ::com::sun::star::accessibility::XAccessibleText; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleTextField.idl b/offapi/com/sun/star/awt/AccessibleTextField.idl deleted file mode 100644 index d2098ef8b176..000000000000 --- a/offapi/com/sun/star/awt/AccessibleTextField.idl +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- 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 . - */ - - -module com { module sun { module star { module accessibility { - - interface XAccessibleExtendedComponent; - interface XAccessibleComponent; - interface XAccessibleText; - -}; }; }; }; - -module com { module sun { module star { module awt { - - -/** Text fields are like edit fields as described by the - AccessibleEdit service but without the ability to edit the - text. - @see com::sun::star::accessibility::AccessibleContext - @see com::sun::star::accessibility::XAccessibleComponent - @see com::sun::star::accessibility::XAccessibleExtendedComponent - @see com::sun::star::accessibility::XAccessibleText - - @since OOo 1.1.2 -*/ -service AccessibleTextField -{ - /** This interface gives access to the structural information of a text field: - -
        -
      • Role: The role of a text field is - com::sun::star::accessibility::AccessibleRole::TEXT.
      • -
      • Name: The name of a text field is its localized label.
      • -
      • Description: The description of a text field is its localized - help text.
      • -
      • Children: There exists no children.
      • -
      • Parent: The parent is the window that contains the text field.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ACTIVE - is set if a child has currently the focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::RESIZABLE - is set if the object can be resized.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - - service com::sun::star::accessibility::AccessibleContext; - - /** This interface gives read-only access to the text representation - of a text field. - */ - interface com::sun::star::accessibility::XAccessibleText; - interface com::sun::star::accessibility::XAccessibleComponent; - interface com::sun::star::accessibility::XAccessibleExtendedComponent; - -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/AccessibleWindow.idl b/offapi/com/sun/star/awt/AccessibleWindow.idl deleted file mode 100644 index ac739f1ad04f..000000000000 --- a/offapi/com/sun/star/awt/AccessibleWindow.idl +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- 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 . - */ - -module com { module sun { module star { module awt { - -/** specifies accessibility support for a window. - - @since OOo 1.1.2 - */ -service AccessibleWindow -{ - /** This interface gives access to the structural information of a window: - -
        -
      • Role: The role of a window is not fixed. A window may have - one of the following roles: -
          -
        • com::sun::star::accessibility::AccessibleRole::DIALOG
        • -
        • com::sun::star::accessibility::AccessibleRole::FRAME
        • -
        • com::sun::star::accessibility::AccessibleRole::LAYERED_PANE
        • -
        • com::sun::star::accessibility::AccessibleRole::PANEL
        • -
        • com::sun::star::accessibility::AccessibleRole::ROOT_PANE
        • -
        • com::sun::star::accessibility::AccessibleRole::SCROLL_PANE
        • -
        • com::sun::star::accessibility::AccessibleRole::SPLIT_PANE
        • -
        • com::sun::star::accessibility::AccessibleRole::WINDOW
        • -
        • ...
        • -
        -
      • -
      • Name: The name of a window is its localized title.
      • -
      • Description: The description of a window is its localized - help text.
      • -
      • Children: The children of a window are the child windows.
      • -
      • Parent: The parent of a window is the parent window.
      • -
      • Relations: There are no relations.
      • -
      • States: The states supported by this service are -
          -
        • com::sun::star::accessibility::AccessibleStateType::ACTIVE - is set if the object is currently the active object.
        • -
        • com::sun::star::accessibility::AccessibleStateType::DEFUNC - is set if the object has already been disposed - and subsequent calls to this object result in - com::sun::star::lang::DisposedException - exceptions.
        • -
        • com::sun::star::accessibility::AccessibleStateType::ENABLED - is set if the object is enabled.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSABLE - is always set.
        • -
        • com::sun::star::accessibility::AccessibleStateType::FOCUSED - is set if the object currently has the keyboard focus.
        • -
        • com::sun::star::accessibility::AccessibleStateType::MODAL - is set if the object is modal.
        • -
        • com::sun::star::accessibility::AccessibleStateType::RESIZABLE - is set if the size of the object is not fixed.
        • -
        • com::sun::star::accessibility::AccessibleStateType::SHOWING - is set if the object is displayed on the screen.
        • -
        • com::sun::star::accessibility::AccessibleStateType::VISIBLE - is always set.
        • -
        -
      • -
      - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - interface ::com::sun::star::accessibility::XAccessibleEventBroadcaster; - interface ::com::sun::star::accessibility::XAccessibleComponent; - interface ::com::sun::star::accessibility::XAccessibleExtendedComponent; -}; - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/FontVariationAxis.idl b/offapi/com/sun/star/awt/FontVariationAxis.idl new file mode 100644 index 000000000000..6a5cd7e21c83 --- /dev/null +++ b/offapi/com/sun/star/awt/FontVariationAxis.idl @@ -0,0 +1,45 @@ +/* -*- 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/. + */ + + +module com { module sun { module star { module awt { + + +/** describes a single variation axis of a variable font. + + @since LibreOffice 25.8 + */ +struct FontVariationAxis +{ + /** the four-character OpenType axis tag, e.g. "wght" or "wdth". + */ + string Tag; + + /** the human-readable axis name as defined by the font, in the UI + language if available. + */ + string Name; + + /** the smallest value the axis accepts. + */ + double MinValue; + + /** the axis value used when no explicit setting is supplied. + */ + double DefaultValue; + + /** the largest value the axis accepts. + */ + double MaxValue; +}; + + +}; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/FontVariations.idl b/offapi/com/sun/star/awt/FontVariations.idl new file mode 100644 index 000000000000..0c222b52703d --- /dev/null +++ b/offapi/com/sun/star/awt/FontVariations.idl @@ -0,0 +1,28 @@ +/* -*- 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/. + */ + + +module com { module sun { module star { module awt { + + +/** provides access to OpenType variation axis information for + installed font families. + +

      Intended for use by scripts and extensions that build a UI to + edit + com::sun::star::style::CharacterProperties::CharFontVariations.

      + + @since LibreOffice 25.8 + */ +service FontVariations: XFontVariations; + + +}; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/XAnimatedImages.idl b/offapi/com/sun/star/awt/XAnimatedImages.idl index bb4c8975b8d3..28289494309d 100644 --- a/offapi/com/sun/star/awt/XAnimatedImages.idl +++ b/offapi/com/sun/star/awt/XAnimatedImages.idl @@ -21,7 +21,7 @@ module com { module sun { module star { module awt { -/** allows administrating a set of images, to be displayed as animated seres. +/** allows administrating a set of images, to be displayed as animated series.

      Components implementing this interface maintain a variable number of image sets. Components displaying those images will choose the best-fitting image set depending on the available space, and possibly other diff --git a/offapi/com/sun/star/awt/XFontVariations.idl b/offapi/com/sun/star/awt/XFontVariations.idl new file mode 100644 index 000000000000..18847b6823ec --- /dev/null +++ b/offapi/com/sun/star/awt/XFontVariations.idl @@ -0,0 +1,30 @@ +/* -*- 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/. + */ + + +module com { module sun { module star { module awt { + + +/** queries variation axis information for a font by family name. + + @since LibreOffice 25.8 + */ +interface XFontVariations +{ + /** returns the list of variation axes supported by the given font + family, or an empty sequence for non-variable fonts and unknown + family names. + */ + sequence getFontVariationAxes([in] string FontName); +}; + + +}; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/chart/CorrelationCircleDiagram.idl b/offapi/com/sun/star/chart/CorrelationCircleDiagram.idl new file mode 100644 index 000000000000..875268c26547 --- /dev/null +++ b/offapi/com/sun/star/chart/CorrelationCircleDiagram.idl @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 com { module sun { module star { module chart { + +/** a service for correlation circle plots. + +

      Each series holds one feature column together with the two dimension + columns every series shares, and stands for one point, at the correlation of + the feature with each of the two dimensions.

      + */ +service CorrelationCircleDiagram +{ + service com::sun::star::chart::Diagram; + service com::sun::star::chart::ChartAxisXSupplier; + service com::sun::star::chart::ChartTwoAxisYSupplier; +}; + +}; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/com/sun/star/chart/HistogramDiagram.idl b/offapi/com/sun/star/chart/HistogramDiagram.idl new file mode 100644 index 000000000000..67b30ef0fda6 --- /dev/null +++ b/offapi/com/sun/star/chart/HistogramDiagram.idl @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +module com { module sun { module star { module chart { + +/** This is a service for histogram diagrams. */ +service HistogramDiagram +{ + service com::sun::star::chart::Diagram; + service com::sun::star::chart::ChartStatistics; + service com::sun::star::chart::ChartAxisXSupplier; + service com::sun::star::chart::ChartTwoAxisYSupplier; + + /** Specifies the width of each bin in the histogram. */ + [property] double BinWidth; + + /** Specifies the number of bins in the histogram. */ + [property] long BinCount; + + /** Specifies the type of frequency representation (count or density). */ + [property] long FrequencyType; + + /** Specifies whether to use an underflow bin for values below the first bin. */ + [property] boolean UseUnderflowBin; + [property] double UnderflowBinValue; + + /** Specifies whether to use an overflow bin for values above the last bin. */ + [property] boolean UseOverflowBin; + [property] double OverflowBinValue; +}; + +}; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/chart2/data/XDatabaseDataProvider.idl b/offapi/com/sun/star/chart2/data/XDatabaseDataProvider.idl index b604b60d2d52..a580337aec1b 100644 --- a/offapi/com/sun/star/chart2/data/XDatabaseDataProvider.idl +++ b/offapi/com/sun/star/chart2/data/XDatabaseDataProvider.idl @@ -57,7 +57,7 @@ interface XDatabaseDataProvider

      These columns are typically the foreign key fields of the parent report. The values of these columns are used to identify the data for the subreport. Each time the parent report changes its current row, the subreport requeries - it's data based on the values of the master fields.

      + its data based on the values of the master fields.

      If the report is no sub report (e.g. its parent is not a report itself), this property is not evaluated.

      @@ -74,7 +74,7 @@ interface XDatabaseDataProvider the corresponding master field.
      Alternatively, you could simply base your report on the table invoices, and add the column name cust_ref to the DetailFields. In this case, - and implicit filter clause WHERE cust_ref = :<new_param_name> will + an implicit filter clause WHERE cust_ref = :<new_param_name> will be created, and the artificial parameter will be filled from the corresponding master field.
      If a string in this property denotes both a column name and a parameter name, it @@ -95,7 +95,7 @@ interface XDatabaseDataProvider means in case the #Command specifies an SQL statement, the inherited com::sun::star::sdbc::RowSet::EscapeProcessing becomes relevant:
      - It then can be to used to specify whether the SQL statement should be analyzed on the + It then can be used to specify whether the SQL statement should be analyzed on the client side before sending it to the database server.
      The default value for com::sun::star::sdbc::RowSet::EscapeProcessing is `TRUE`. By switching it to `FALSE`, you can pass backend-specific SQL statements, diff --git a/offapi/com/sun/star/drawing/AccessibleImageBullet.idl b/offapi/com/sun/star/drawing/AccessibleImageBullet.idl deleted file mode 100644 index 69e310ba36ea..000000000000 --- a/offapi/com/sun/star/drawing/AccessibleImageBullet.idl +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- 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 . - */ - - - -module com { module sun { module star { module drawing { - - -/** The accessible view of an image bullet. - - @since OOo 1.1.2 - */ -service AccessibleImageBullet -{ - /** This interface gives access to an image bullet within a text - paragraph fragment that is at least partially visible on the - screen. - -
        -
      • The parent returned by - ::com::sun::star::accessibility::XAccessibleContext::getAccessibleParent() - is the accessible object of a text paragraph. -
      • There are no children returned by - ::com::sun::star::accessibility::XAccessibleContext::getAccessibleChild(). -
      • The role is - ::com::sun::star::accessibility::AccessibleRole::GRAPHIC. -
      • The name is "image bullet" (or the equivalent term - in application's language). -
      • The description contains the term "image bullet" (or the equivalent - term in application's language) and the number of the paragraph - within this bullet appears. -
      • There are no relations. -
      • The following states are supported by the - accessible state bitset returned by - ::com::sun::star::accessibility::XAccessibleContext::getAccessibleStateSet(). -
          -
        • ::com::sun::star::accessibility::AccessibleStateType::DEFUNC - (indicates that - the document window has been closed or the image bullet - is not existing any longer). -
        • ::com::sun::star::accessibility::AccessibleStateType::ENABLED - (always contained) -
        • ::com::sun::star::accessibility::AccessibleStateType::SHOWING -
        • ::com::sun::star::accessibility::AccessibleStateType::VISIBLE -
        • ::com::sun::star::accessibility::AccessibleStateType::INVALID -
        -
      - - */ - interface ::com::sun::star::accessibility::XAccessibleContext; - - /** This interface describes the graphical representation of an image - bullet. - */ - interface ::com::sun::star::accessibility::XAccessibleComponent; - -}; - - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/form/XSubmitListener.idl b/offapi/com/sun/star/form/XSubmitListener.idl index 44ae39b818c3..ba436bd31eb9 100644 --- a/offapi/com/sun/star/form/XSubmitListener.idl +++ b/offapi/com/sun/star/form/XSubmitListener.idl @@ -36,10 +36,10 @@ published interface XSubmitListener: com::sun::star::lang::XEventListener { - /** is invoked when a component is about to submit it's data. + /** is invoked when a component is about to submit its data. @param Event - the event happened + the event that happened @returns `TRUE` when submitting was approved, otherwise `FALSE`. diff --git a/offapi/com/sun/star/form/component/DataForm.idl b/offapi/com/sun/star/form/component/DataForm.idl index ed0ff3eb7d17..758bd8bbd456 100644 --- a/offapi/com/sun/star/form/component/DataForm.idl +++ b/offapi/com/sun/star/form/component/DataForm.idl @@ -69,7 +69,7 @@ published service DataForm

      One main difference between XLoadable::load() and com::sun::star::sdbc::XRowSet::execute() is that if you use the former, the row set is positioned on the first record, while in the latter case - it is position before the it.

      + it is positioned before it.

      */ interface com::sun::star::form::XLoadable; @@ -108,7 +108,7 @@ published service DataForm

      These columns are typically the foreign key fields of the parent form. The values of these columns are used to identify the data for the subform. Each time the parent form changes its current row, the subform requeries - it's data based on the values of the master fields.

      + its data based on the values of the master fields.

      If the form is no sub form (e.g. its parent is not a form itself), this property is not evaluated.

      @@ -126,7 +126,7 @@ published service DataForm the corresponding master field.
      Alternatively, you could simply base your form on the table invoices, and add the column name cust_ref to the DetailFields. In this case, - and implicit filter clause WHERE cust_ref = :<new_param_name> will + an implicit filter clause WHERE cust_ref = :<new_param_name> will be created, and the artificial parameter will be filled from the corresponding master field.
      If a string in this property denotes both a column name and a parameter name, it diff --git a/offapi/com/sun/star/presentation/XSoundReference.idl b/offapi/com/sun/star/presentation/XSoundReference.idl new file mode 100644 index 000000000000..fd9644cf2221 --- /dev/null +++ b/offapi/com/sun/star/presentation/XSoundReference.idl @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 com { module sun { module star { module presentation { + + +/** A sound a presentation refers to: the slide-transition sound, an animation + sound, or a click-action sound. + + It carries the source URL and the allowed state together as one value. + Allowed is runtime state, decided this session and never stored in the + document. +*/ +interface XSoundReference +{ + /** The source of the sound. A vnd.sun.star.Package: URL is content inside + the document; any other non-empty URL is a link to an external file. + */ + [attribute, readonly] string URL; + + /** True when this sound has been allowed this session. A sound inside the + document package is always allowed; an external sound is allowed once the + user permits it, either for the whole document or for this one sound. + */ + [attribute, readonly] boolean Allowed; +}; + + +}; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/rendering/XSimpleCanvas.idl b/offapi/com/sun/star/rendering/XSimpleCanvas.idl deleted file mode 100644 index 528647573bd3..000000000000 --- a/offapi/com/sun/star/rendering/XSimpleCanvas.idl +++ /dev/null @@ -1,233 +0,0 @@ -/* -*- 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 . - */ - - -module com { module sun { module star { module rendering { - -interface XCanvas; -interface XCanvasFont; -interface XBitmap; -interface XGraphicDevice; -interface XPolyPolygon2D; - -/** Provides the basic graphical output operations for a canvas.

      - - This interface is a simplified version of the XCanvas - interface. It holds explicit state, i.e. the pen and fill color, - the current transformation, clip and font are persistently - remembered.

      - - In contrast to the XCanvas interface, XSimpleCanvas - does not distinguish between stroke and fill operations; instead, - switching between stroke and fill (or taking both) works by - setting appropriate pen and fill colors.

      - */ -interface XSimpleCanvas: com::sun::star::uno::XInterface -{ - /** Select a font.

      - - This method selects the specified font (or a close substitute) - as the current font for text output.

      - - @param sFontName - The name of the font (like e.g. Arial) - - @param size - The size of the font (note that this is not the usual points - unit, but in the same coordinate system as the other rendering - operations - usually, device pixel). - - @param bold - When true, selected font is bold. - - @param italic - When true, selected font is italic - */ - void selectFont( [in] string sFontName, [in]double size, [in] boolean bold, [in] boolean italic ); - - - /** Sets the color used by line and text operations.

      - - To disable stroking, simply set this color to something with - zero alpha (i.e. fully transparent).

      - - @param nsRgbaColor - RGBA color tuple, interpreted in the sRGB color space. - */ - void setPenColor( [in] com::sun::star::util::Color nsRgbaColor ); - - - /** Sets the fill color.

      - - To disable filling, simply set this color to something with - zero alpha (i.e. fully transparent).

      - - @param nsRgbaColor - RGBA color tuple, interpreted in the sRGB color space. - */ - void setFillColor( [in] com::sun::star::util::Color nsRgbaColor ); - - - /** Sets the clip to the specified rectangle.

      - */ - void setRectClip( [in] ::com::sun::star::geometry::RealRectangle2D aRect ); - - - /** Set the current transform matrix.

      - */ - void setTransformation( [in] ::com::sun::star::geometry::AffineMatrix2D aTransform ); - - - /** Sets a single pixel on the canvas.

      - */ - void drawPixel( [in] ::com::sun::star::geometry::RealPoint2D aPoint ); - - - /** Draws a line on the canvas.

      - */ - void drawLine( [in] ::com::sun::star::geometry::RealPoint2D aStartPoint, - [in] ::com::sun::star::geometry::RealPoint2D aEndPoint ); - - - /** Draws a rectangle on the canvas.

      - */ - void drawRect( [in] ::com::sun::star::geometry::RealRectangle2D aRect ); - - - /** Draws a poly-polygon on the canvas.

      - */ - void drawPolyPolygon( [in] XPolyPolygon2D xPolyPolygon ); - - - /** Draws text on the canvas.

      - - @param aText - Text to render. The text color is the current pen color. - - @param aOutPos - Output position of the text. This is the left or right edge, - depending on nTextDirection. Output position is always - relative to the font baseline. - - @param nTextDirection - A value from the TextDirection collection, - denoting the main writing direction for this string. The main - writing direction determines the origin of the text output, - i.e. the left edge for left-to-right and the right edge for - right-to-left text. - */ - void drawText( [in] StringContext aText, - [in] ::com::sun::star::geometry::RealPoint2D aOutPos, - [in] byte nTextDirection ); - - - /** Draws the bitmap on the canvas.

      - - @param xBitmap - Bitmap to render - - @param aLeftTop - Left, top position of the bitmap on the destination canvas. - */ - void drawBitmap( [in] XBitmap xBitmap, - [in] ::com::sun::star::geometry::RealPoint2D aLeftTop ); - - - /** Request the associated graphic device for this canvas.

      - - A graphic device provides methods specific to the underlying - output device capabilities, which are common for all canvases - rendering to such a device. This includes device resolution, - color space, or bitmap formats.

      - - @return the associated XGraphicDevice. - */ - XGraphicDevice getDevice(); - - - /** Query the underlying XCanvas.

      - - @return the canvas interface this object is internally based - on. - */ - XCanvas getCanvas(); - - - /** Request the font metrics of the current font.

      - - @return the font metrics of the currently selected font. - */ - FontMetrics getFontMetrics(); - - - /** Retrieve currently selected font.

      - - @return the font instance that's currently used for rendering - text. - */ - XCanvasFont getCurrentFont(); - - - /** Retrieve color currently used for lines. - */ - com::sun::star::util::Color getCurrentPenColor(); - - - /** Retrieve color currently used for fills - */ - com::sun::star::util::Color getCurrentFillColor(); - - - /** Retrieve current clip rect - */ - com::sun::star::geometry::RealRectangle2D getCurrentClipRect(); - - - /** Retrieve current transformation matrix - */ - com::sun::star::geometry::AffineMatrix2D getCurrentTransformation(); - - - /** Retrieve view state.

      - - @return the view state, that would generate matching output, - when rendering to an XCanvas instead. - */ - ViewState getCurrentViewState(); - - - /** Retrieve render state.

      - - @param bUseFillColor - When true, the Color member of the RenderState is initialized - with the current fill color; when false, the current pen color - is used. - - @return the render state, that would generate matching output, - when rendering to an XCanvas instead. - */ - RenderState getCurrentRenderState( [in] boolean bUseFillColor ); - - -}; - - -}; }; }; }; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/report/XReportComponent.idl b/offapi/com/sun/star/report/XReportComponent.idl index 4d8a29926d33..b609b8950398 100644 --- a/offapi/com/sun/star/report/XReportComponent.idl +++ b/offapi/com/sun/star/report/XReportComponent.idl @@ -120,7 +120,7 @@ interface XReportComponent

      These columns are typically the foreign key fields of the parent report. The values of these columns are used to identify the data for the subreport. Each time the parent report changes its current row, the subreport requeries - it's data based on the values of the master fields.

      + its data based on the values of the master fields.

      If the report is no sub report (e.g. its parent is not a report itself), this property is not evaluated.

      @@ -141,7 +141,7 @@ interface XReportComponent the corresponding master field.
      Alternatively, you could simply base your report on the table invoices, and add the column name cust_ref to the DetailFields. In this case, - and implicit filter clause WHERE cust_ref = :<new_param_name> will + an implicit filter clause WHERE cust_ref = :<new_param_name> will be created, and the artificial parameter will be filled from the corresponding master field.
      If a string in this property denotes both a column name and a parameter name, it diff --git a/offapi/com/sun/star/script/browse/BrowseNode.idl b/offapi/com/sun/star/script/browse/BrowseNode.idl index 09f0c38bbeb1..438b1621c268 100644 --- a/offapi/com/sun/star/script/browse/BrowseNode.idl +++ b/offapi/com/sun/star/script/browse/BrowseNode.idl @@ -24,16 +24,20 @@ module com { module browse { /** - This service provides access to the Macros and Macro containers via the - XBrowseNode interface. XInvocation is an optional interface that is used - to execute macros, or to create/delete/rename macros or macro containers. + This service provides access to the Macros and Macro containers + via the XBrowseNode interface. The optional interfaces are used to + copy/create/delete/rename/edit macros or macro containers. @since OOo 2.0 */ service BrowseNode { interface ::com::sun::star::script::browse::XBrowseNode; - [ optional ] interface ::com::sun::star::script::XInvocation; + [ optional ] interface XCopyableBrowseNode; + [ optional ] interface XCreatableBrowseNode; + [ optional ] interface XDeletableBrowseNode; + [ optional ] interface XEditableBrowseNode; + [ optional ] interface XRenamableBrowseNode; }; }; diff --git a/offapi/com/sun/star/script/browse/XBrowseNode.idl b/offapi/com/sun/star/script/browse/XBrowseNode.idl index 4321702f3a7f..fa6d7b491a45 100644 --- a/offapi/com/sun/star/script/browse/XBrowseNode.idl +++ b/offapi/com/sun/star/script/browse/XBrowseNode.idl @@ -20,11 +20,11 @@ module com { module sun { module star { module script { module browse { /** This interface represents a node in the hierarchy used to browse - available scripts. - Objects implementing this interface are expected to also implement - com.sun.star.beans.XPropertySet and, optionally, - com.sun.star.script.XInvocation (see the Developer's Guide for - more details). + available scripts. Objects implementing this interface are + expected to also implement com.sun.star.beans.XPropertySet and, + optionally, XCreatableBrowseNode, XDeletableBrowseNode, + XEditableBrowseNode and XRenamableBrowseNode (see the Developer's + Guide for more details). */ interface XBrowseNode : ::com::sun::star::uno::XInterface { diff --git a/offapi/com/sun/star/script/browse/XCopyableBrowseNode.idl b/offapi/com/sun/star/script/browse/XCopyableBrowseNode.idl new file mode 100644 index 000000000000..5a1b1008019d --- /dev/null +++ b/offapi/com/sun/star/script/browse/XCopyableBrowseNode.idl @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module com { module sun { module star { module script { module browse { + +/** + An optional interface that can be added to implementations of XBrowseNode in order to make the + node copyable. + + Since LibreOffice 27.2 +*/ +interface XCopyableBrowseNode +{ + /** + * @returns whether this node can be used as the source for a copy operation. + */ + boolean isCopyableNode(); + + /** + * @returns whether this node can be copied to be a child of the destination node. + * + * @param parentNode - The parent to copy this node to. + */ + boolean nodeCanBeCopiedTo([in] XBrowseNode parentNode); + + /** + * Copy the node. + */ + XBrowseNode copyNode([in] XBrowseNode parentNode) + raises(com::sun::star::uno::Exception); +}; + +}; }; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/com/sun/star/script/browse/XCreatableBrowseNode.idl b/offapi/com/sun/star/script/browse/XCreatableBrowseNode.idl new file mode 100644 index 000000000000..471abb856891 --- /dev/null +++ b/offapi/com/sun/star/script/browse/XCreatableBrowseNode.idl @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module com { module sun { module star { module script { module browse { + +/** + An optional interface that can be added to implementations of XBrowseNode to allow creating child + nodes of this node. + + Since LibreOffice 27.2 +*/ +interface XCreatableBrowseNode +{ + /** + * @returns whether new nodes can be created under this node. + */ + boolean isCreatableNode(); + + /** + * Creates a new child node of this node. + * + * @returns the created node. + */ + XBrowseNode createNode([in] string newName); +}; + +}; }; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/com/sun/star/script/browse/XDeletableBrowseNode.idl b/offapi/com/sun/star/script/browse/XDeletableBrowseNode.idl new file mode 100644 index 000000000000..dc426ac28dae --- /dev/null +++ b/offapi/com/sun/star/script/browse/XDeletableBrowseNode.idl @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module com { module sun { module star { module script { module browse { + +/** + An optional interface that can be added to implementations of XBrowseNode in order to make the + node deletable. + + Since LibreOffice 27.2 +*/ +interface XDeletableBrowseNode +{ + /** + * @returns whether this node can be deleted. + */ + boolean isDeletableNode(); + + /** + * Deletes the node. + * + * @returns whether the delete succeeded. + */ + boolean deleteNode(); +}; + +}; }; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/com/sun/star/script/browse/XEditableBrowseNode.idl b/offapi/com/sun/star/script/browse/XEditableBrowseNode.idl new file mode 100644 index 000000000000..d63588d56152 --- /dev/null +++ b/offapi/com/sun/star/script/browse/XEditableBrowseNode.idl @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module com { module sun { module star { module script { module browse { + +/** + An optional interface that can be added to implementations of XBrowseNode in order to make the + node editable. + + Since LibreOffice 27.2 +*/ +interface XEditableBrowseNode +{ + /** + * @returns whether this node can be edited. + */ + boolean isEditableNode(); + + /** + * Edits the node. + * + * @returns whether starting the editor succeeded. + */ + boolean editNode(); +}; + +}; }; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/com/sun/star/script/browse/XRenamableBrowseNode.idl b/offapi/com/sun/star/script/browse/XRenamableBrowseNode.idl new file mode 100644 index 000000000000..3c9ccdf3f40e --- /dev/null +++ b/offapi/com/sun/star/script/browse/XRenamableBrowseNode.idl @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module com { module sun { module star { module script { module browse { + +/** + An optional interface that can be added to implementations of XBrowseNode in order to make the + node renamable. + + Since LibreOffice 27.2 +*/ +interface XRenamableBrowseNode +{ + /** + * @returns whether this node can be renamed. + */ + boolean isRenamableNode(); + + /** + * Renames the node. + * + * @returns the renamed node. + */ + XBrowseNode renameNode([in] string newName); +}; + +}; }; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/com/sun/star/sheet/ConditionEntryType.idl b/offapi/com/sun/star/sheet/ConditionEntryType.idl index 0266e6721474..5b717850c87b 100644 --- a/offapi/com/sun/star/sheet/ConditionEntryType.idl +++ b/offapi/com/sun/star/sheet/ConditionEntryType.idl @@ -20,6 +20,14 @@ constants ConditionEntryType const long ICONSET = 3; const long DATE = 4; + + /** A color scale conditional format with a min and a max + */ + const long COLORSCALE2 = 5; + + /** A color scale conditional format with a min, a middle and a max + */ + const long COLORSCALE3 = 6; }; diff --git a/svx/source/stbctrls/stbctrls.h b/offapi/com/sun/star/sheet/ExternalLinkRelType.idl similarity index 68% rename from svx/source/stbctrls/stbctrls.h rename to offapi/com/sun/star/sheet/ExternalLinkRelType.idl index 3b12d6f9500b..37d40608b143 100644 --- a/svx/source/stbctrls/stbctrls.h +++ b/offapi/com/sun/star/sheet/ExternalLinkRelType.idl @@ -16,20 +16,25 @@ * 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_SVX_SOURCE_STBCTRLS_STBCTRLS_H -#define INCLUDED_SVX_SOURCE_STBCTRLS_STBCTRLS_H -// IDs as in SUBTOTAL_FUNC of Calc +module com { module sun { module star { module sheet { -#define PSZ_FUNC_AVG 1 -#define PSZ_FUNC_COUNT2 3 -#define PSZ_FUNC_COUNT 2 -#define PSZ_FUNC_MAX 4 -#define PSZ_FUNC_MIN 5 -#define PSZ_FUNC_SUM 9 -#define PSZ_FUNC_SELECTION_COUNT 13 -#define PSZ_FUNC_NONE 16 +/** Constants designating the type of an external link relationship + added via XExternalDocLinks::addSpecialDocLink(). + */ +constants ExternalLinkRelType +{ -#endif + /** The external document path is missing. + */ + const short PATH_MISSING = 0; + + /** The external document is in Excel's Startup folder. + */ + const short XL_STARTUP = 1; + +}; + +}; }; }; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/sheet/ExternalLinkType.idl b/offapi/com/sun/star/sheet/ExternalLinkType.idl index b9b3382599d6..f69a7f625cd1 100644 --- a/offapi/com/sun/star/sheet/ExternalLinkType.idl +++ b/offapi/com/sun/star/sheet/ExternalLinkType.idl @@ -50,6 +50,10 @@ constants ExternalLinkType */ const long SPECIAL = 4; + /** Missing external document. + */ + const long MISSINGDOCUMENT = 5; + }; diff --git a/offapi/com/sun/star/sheet/FormulaMapGroup.idl b/offapi/com/sun/star/sheet/FormulaMapGroup.idl index c7c0b4f60b2c..d577eb00b0b2 100644 --- a/offapi/com/sun/star/sheet/FormulaMapGroup.idl +++ b/offapi/com/sun/star/sheet/FormulaMapGroup.idl @@ -52,6 +52,9 @@ constants FormulaMapGroup /** Functions */ const long FUNCTIONS = 0x00000010; + /** Error constants */ + const long ERROR_CONSTANTS = 0x00000020; + /** All groups except SPECIAL */ const long ALL_EXCEPT_SPECIAL = 0x7fffffff; }; diff --git a/offapi/com/sun/star/sheet/XExternalDocLinks.idl b/offapi/com/sun/star/sheet/XExternalDocLinks.idl index 3789b24cf6cf..5f755f7011d0 100644 --- a/offapi/com/sun/star/sheet/XExternalDocLinks.idl +++ b/offapi/com/sun/star/sheet/XExternalDocLinks.idl @@ -40,6 +40,7 @@ interface XExternalDocLinks @return com::sun::star::sheet::XExternalDocLink external document link instance */ com::sun::star::sheet::XExternalDocLink addDocLink( [in] string aDocName ); + com::sun::star::sheet::XExternalDocLink addSpecialDocLink( [in] string aDocName, [in] short nLinkType); }; }; }; }; }; diff --git a/offapi/com/sun/star/style/ParagraphProperties.idl b/offapi/com/sun/star/style/ParagraphProperties.idl index bef8f8113357..36ae0d4a5312 100644 --- a/offapi/com/sun/star/style/ParagraphProperties.idl +++ b/offapi/com/sun/star/style/ParagraphProperties.idl @@ -630,6 +630,20 @@ published service ParagraphProperties @since LibreOffice 26.8 */ [optional, property] boolean ParaComposer; + + /** specifies a percent value on the Less Hyphenation .. Better Spacing + range, resulting in different paragraph layout depending also on + ParaWordSpacingMinimum and ParaWordSpacingMaximum. + +

      It takes a percent value between [0, 100].

      + + @see ParaWordSpacingMinimum + + @see ParaWordSpacingMaximum + + @since LibreOffice 27.2 + */ + [optional, property] long ParaHyphenationLevel; }; diff --git a/offapi/com/sun/star/text/TextPortion.idl b/offapi/com/sun/star/text/TextPortion.idl index 74b9dbc76e56..93dfcaf4c548 100644 --- a/offapi/com/sun/star/text/TextPortion.idl +++ b/offapi/com/sun/star/text/TextPortion.idl @@ -117,7 +117,7 @@ published service TextPortion /** contains whether the portion is the start of the portion.

      This is used for portions which are represented by - 2 TextPortion objects (e.g., DocmentIndexMark).

      + 2 TextPortion objects (e.g., DocumentIndexMark).

      */ [optional, readonly, property] boolean IsStart; diff --git a/offapi/com/sun/star/ucb/HelpContent.idl b/offapi/com/sun/star/ucb/HelpContent.idl index e52268e95fa2..d41532a05319 100644 --- a/offapi/com/sun/star/ucb/HelpContent.idl +++ b/offapi/com/sun/star/ucb/HelpContent.idl @@ -67,7 +67,7 @@ published service HelpContent
      • string ContentType ( read-only, - ""application/vnd.sun.star.help" ) + "application/vnd.sun.star.help" )
      • boolean IsReadOnly ( read-only, always "true" ) @@ -82,7 +82,7 @@ published service HelpContent string Title ( read-only, content title )
      • - string MediaType ( read only, either "image/gif", "text/plain", + string MediaType ( read-only, either "image/gif", "text/plain", "text/html" or "text/css" )
      • @@ -98,15 +98,15 @@ published service HelpContent contains the anchor names belonging to the index )
      • - sequence<sequence<string>> KeywordTitleForRef ( read-only, , only if IsFolder is true, + sequence<sequence<string>> KeywordTitleForRef ( read-only, only if IsFolder is true, contains the titles of the documents in which the keywords are found. )
      • - sequence<string> SearchScopes ( read only, , only if IsFolder is true, + sequence<string> SearchScopes ( read-only, only if IsFolder is true, contains the scopes in which to search ).
      • - string AnchorName ( readonly, only if content is has media type "text/html". + string AnchorName ( read-only, only if content has media type "text/html" ).
      diff --git a/offapi/com/sun/star/ucb/HierarchyDataReadWriteAccess.idl b/offapi/com/sun/star/ucb/HierarchyDataReadWriteAccess.idl index 0b49f23ec85a..55fbc3c83ef2 100644 --- a/offapi/com/sun/star/ucb/HierarchyDataReadWriteAccess.idl +++ b/offapi/com/sun/star/ucb/HierarchyDataReadWriteAccess.idl @@ -39,7 +39,7 @@ published service HierarchyDataReadWriteAccess must remove data members. However, the mandatory data members (Title, TargetURL, Children) must never be removable. -

      Replacing and getting values must be supported be every data node. +

      Replacing and getting values must be supported by every data node. */ interface com::sun::star::container::XNameContainer; @@ -47,7 +47,7 @@ published service HierarchyDataReadWriteAccess

      com::sun::star::lang::XSingleServiceFactory::createInstance() will create a new empty hierarchy data node. After it was created - it's data members can be filled. Last, the node can be inserted as child + its data members can be filled. Last, the node can be inserted as child of another node using com::sun::star::container::XNameContainer::insertByName(). diff --git a/offapi/com/sun/star/util/XComplexColor.idl b/offapi/com/sun/star/util/XComplexColor.idl index 83c5b5b1f081..c2f10e92b124 100644 --- a/offapi/com/sun/star/util/XComplexColor.idl +++ b/offapi/com/sun/star/util/XComplexColor.idl @@ -25,12 +25,6 @@ interface XComplexColor /** resolve the color */ Color resolveColor([in] com::sun::star::util::XTheme xTheme); - - /** String representation of the complex color. - - @since LibreOffice 26.2 - */ - string getRepresentation(); }; }; }; }; }; diff --git a/offapi/org/libreoffice/embindtest/XPassthrough.idl b/offapi/org/libreoffice/embindtest/XPassthrough.idl new file mode 100644 index 000000000000..b2d9254ebd37 --- /dev/null +++ b/offapi/org/libreoffice/embindtest/XPassthrough.idl @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module org { module libreoffice { module embindtest { + +interface XPassthrough { + // @returns the argument unchanged + com::sun::star::uno::XInterface passthrough([in] com::sun::star::uno::XInterface interfaceIn); +}; + +}; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/org/libreoffice/embindtest/theMethodToString.idl b/offapi/org/libreoffice/embindtest/theMethodToString.idl new file mode 100644 index 000000000000..834eeb1d65d4 --- /dev/null +++ b/offapi/org/libreoffice/embindtest/theMethodToString.idl @@ -0,0 +1,16 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module org { module libreoffice { module embindtest { + +singleton theMethodToString: com::sun::star::script::XInvocation; + +}; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/org/libreoffice/embindtest/thePassthrough.idl b/offapi/org/libreoffice/embindtest/thePassthrough.idl new file mode 100644 index 000000000000..939c0d78daf1 --- /dev/null +++ b/offapi/org/libreoffice/embindtest/thePassthrough.idl @@ -0,0 +1,16 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module org { module libreoffice { module embindtest { + +singleton thePassthrough: XPassthrough; + +}; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/officecfg/CppunitTest_officecfg_accelerator_key_checker_test.mk b/officecfg/CppunitTest_officecfg_accelerator_key_checker_test.mk new file mode 100644 index 000000000000..84f3f125a8d2 --- /dev/null +++ b/officecfg/CppunitTest_officecfg_accelerator_key_checker_test.mk @@ -0,0 +1,44 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,officecfg_accelerator_key_checker_test)) + +$(eval $(call gb_CppunitTest_add_exception_objects,officecfg_accelerator_key_checker_test, \ + officecfg/qa/acceleratorkeychecker \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,officecfg_accelerator_key_checker_test, \ + cppu \ + cppuhelper \ + sal \ + subsequenttest \ + test \ + unotest \ + utl \ + vcl \ + tl \ +)) + +$(eval $(call gb_CppunitTest_use_api,officecfg_accelerator_key_checker_test, \ + udkapi \ + offapi \ + oovbaapi \ +)) + +$(eval $(call gb_CppunitTest_use_externals,officecfg_accelerator_key_checker_test, \ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_ure,officecfg_accelerator_key_checker_test)) +$(eval $(call gb_CppunitTest_use_vcl,officecfg_accelerator_key_checker_test,services)) +$(eval $(call gb_CppunitTest_use_rdb,officecfg_accelerator_key_checker_test,services)) +$(eval $(call gb_CppunitTest_use_configuration,officecfg_accelerator_key_checker_test)) + +# vim: set noet sw=4 ts=4: diff --git a/officecfg/Module_officecfg.mk b/officecfg/Module_officecfg.mk index 326ae1580714..1d0e0fff857c 100644 --- a/officecfg/Module_officecfg.mk +++ b/officecfg/Module_officecfg.mk @@ -28,6 +28,7 @@ $(eval $(call gb_Module_add_targets,officecfg,\ $(eval $(call gb_Module_add_check_targets,officecfg,\ CppunitTest_officecfg_cppheader_test \ + CppunitTest_officecfg_accelerator_key_checker_test \ )) # vim: set noet sw=4 ts=4: diff --git a/officecfg/qa/acceleratorkeychecker.cxx b/officecfg/qa/acceleratorkeychecker.cxx new file mode 100644 index 000000000000..8a988141e2f0 --- /dev/null +++ b/officecfg/qa/acceleratorkeychecker.cxx @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace +{ +class AcceleratorKeyCheckerTest : public UnoApiTest +{ +public: + AcceleratorKeyCheckerTest() + : UnoApiTest(u"/officecfg/util"_ustr) + { + } + +private: + void testAcceleratorKeyChecker(); + + CPPUNIT_TEST_SUITE(AcceleratorKeyCheckerTest); + CPPUNIT_TEST(testAcceleratorKeyChecker); + CPPUNIT_TEST_SUITE_END(); +}; + +css::uno::Reference +findChildNode(const css::uno::Reference& xNode, + const std::u16string_view sName) +{ + for (const auto& xChildNode : xNode->getChildNodes()) + { + if (xChildNode->getName() == sName) + return xChildNode; + } + + CPPUNIT_FAIL(OUString(u"Couldn’t find child node "_ustr + sName).toUtf8().getStr()); +} + +// Tries running the script contained in the AcceleratorKeyChecker utility document +void AcceleratorKeyCheckerTest::testAcceleratorKeyChecker() +{ + // Make sure that dialogs are fatal so that if the script reports + // an error then the test will fail + DialogCancelMode nOldDialogCancelMode = Application::GetDialogCancelMode(); + comphelper::ScopeGuard g( + [nOldDialogCancelMode]() { Application::SetDialogCancelMode(nOldDialogCancelMode); }); + Application::SetDialogCancelMode(DialogCancelMode::Fatal); + + loadFromFile(u"AcceleratorKeyChecker.fodt"); + + // Get the script provider for BASIC macros in the document + css::uno::Sequence aArgs(1); + aArgs.getArray()[0] <<= u"vnd.sun.star.tdoc:/1"_ustr; + + css::uno::Reference xRootNode( + m_xFactory->createInstanceWithArgumentsAndContext( + "com.sun.star.script.provider.ScriptProviderForBasic", aArgs, m_xContext), + css::uno::UNO_QUERY_THROW); + + // Get the browse node for the testmenus macro + css::uno::Reference xBrowseNode + = findChildNode(xRootNode, u"AcceleratorKeyCheck"); + xBrowseNode = findChildNode(xBrowseNode, u"__testMenu"); + xBrowseNode = findChildNode(xBrowseNode, u"testmenus"); + + // Get the URI for the macro + css::uno::Reference xNodeProperties(xBrowseNode, + css::uno::UNO_QUERY_THROW); + css::uno::Any value = xNodeProperties->getPropertyValue(u"URI"_ustr); + OUString sURI; + CPPUNIT_ASSERT(value >>= sURI); + + // Get the XScript for the macro from the script provider + css::uno::Reference xScriptProvider( + xRootNode, css::uno::UNO_QUERY_THROW); + css::uno::Reference xScript = xScriptProvider->getScript(sURI); + + // Run the macro + css::uno::Sequence aParams; + css::uno::Sequence aOutParamIndex; + css::uno::Sequence aOutParam; + xScript->invoke(aParams, aOutParamIndex, aOutParam); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(AcceleratorKeyCheckerTest); + +} // namespace + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/officecfg/registry/data/org/openoffice/Office/Accelerators.xcu b/officecfg/registry/data/org/openoffice/Office/Accelerators.xcu index 0b698c01a48f..5dbfa3fec53b 100644 --- a/officecfg/registry/data/org/openoffice/Office/Accelerators.xcu +++ b/officecfg/registry/data/org/openoffice/Office/Accelerators.xcu @@ -2406,12 +2406,6 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input .uno:DefaultNumbering - - - L10N SHORTCUTS - NO TRANSLATE - .uno:InsertTable - - L10N SHORTCUTS - NO TRANSLATE @@ -2864,9 +2858,9 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input L10N SHORTCUTS - NO TRANSLATE + .uno:InsertTable .uno:SubScript .uno:CenterPara - .uno:DesignerDialog @@ -3950,12 +3944,6 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input .uno:DefaultNumbering - - - L10N SHORTCUTS - NO TRANSLATE - .uno:InsertTable - - L10N SHORTCUTS - NO TRANSLATE @@ -4402,9 +4390,9 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input L10N SHORTCUTS - NO TRANSLATE + .uno:InsertTable .uno:SubScript .uno:CenterPara - .uno:DesignerDialog @@ -4753,12 +4741,6 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input .uno:DefaultNumbering - - - L10N SHORTCUTS - NO TRANSLATE - .uno:InsertTable - - L10N SHORTCUTS - NO TRANSLATE @@ -5228,9 +5210,9 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input L10N SHORTCUTS - NO TRANSLATE + .uno:InsertTable .uno:SubScript .uno:CenterPara - .uno:DesignerDialog @@ -5555,12 +5537,6 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input .uno:DefaultNumbering - - - L10N SHORTCUTS - NO TRANSLATE - .uno:InsertTable - - L10N SHORTCUTS - NO TRANSLATE @@ -6006,9 +5982,9 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input L10N SHORTCUTS - NO TRANSLATE + .uno:InsertTable .uno:SubScript .uno:CenterPara - .uno:DesignerDialog @@ -6489,12 +6465,6 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input .uno:DefaultNumbering - - - L10N SHORTCUTS - NO TRANSLATE - .uno:InsertTable - - L10N SHORTCUTS - NO TRANSLATE @@ -6978,9 +6948,7 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input L10N SHORTCUTS - NO TRANSLATE - .uno:SubScript - .uno:CenterPara - .uno:DesignerDialog + .uno:InsertTable @@ -7366,12 +7334,6 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input .uno:DefaultNumbering - - - L10N SHORTCUTS - NO TRANSLATE - .uno:InsertTable - - L10N SHORTCUTS - NO TRANSLATE @@ -7824,9 +7786,9 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input L10N SHORTCUTS - NO TRANSLATE + .uno:InsertTable .uno:SubScript .uno:CenterPara - .uno:DesignerDialog diff --git a/officecfg/registry/data/org/openoffice/Office/Common.xcu b/officecfg/registry/data/org/openoffice/Office/Common.xcu index 22224887cff4..335b35fed9f1 100644 --- a/officecfg/registry/data/org/openoffice/Office/Common.xcu +++ b/officecfg/registry/data/org/openoffice/Office/Common.xcu @@ -336,9 +336,6 @@ - - https://hub.libreoffice.org/send-feedback/ - https://hub.libreoffice.org/forum/ diff --git a/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu index 9ebb762e3b0b..ac24f84be166 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu @@ -35,11 +35,6 @@ Number Format Type - - - Current Sheet View - - Flip Horizontally @@ -2197,6 +2192,7 @@ ~AutoOutline + Outline refers to an automatic grouping of cells 1 @@ -2637,6 +2633,79 @@ 1 + + + Accept Formula + + + Finalizes the formula entered in the formula bar + + + 1 + + + + + Start Formula + + + Set input focus on the formula bar, if open + + + 1 + + + + + Orientation + + + Change page orientation to portrait or landscape + + + 1 + + + + + Grid Lines + Used in the print tab of the Calc tabbed UI when looking at a print preview + + + Print grid lines + Used in the print tab of the Calc tabbed UI when looking at a print preview + + + + + Col/Row Header + Used in the print tab of the Calc tabbed UI when looking at a print preview + + + Print column and row header + Used in the print tab of the Calc tabbed UI when looking at a print preview + + + + + Comments + Used in the print tab of the Calc tabbed UI when looking at a print preview + + + Print comments + Used in the print tab of the Calc tabbed UI when looking at a print preview + + + + + Zero Values + Used in the print tab of the Calc tabbed UI when looking at a print preview + + + Print zero values + Used in the print tab of the Calc tabbed UI when looking at a print preview + + @@ -2733,6 +2802,7 @@ ~Group and Outline + Outline refers to an automatic grouping of cells 1 @@ -2807,22 +2877,6 @@ 1 - - - Switch To Next Sheet View - - - 1 - - - - - Switch To Previous Sheet View - - - 1 - - Select Sheet View @@ -3237,6 +3291,14 @@ Open the Functions Deck + + + Find Values + + + Find text in values, to search in formulas use the dialog + + diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu index 8c1e90092f03..3e4b0a304e82 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu @@ -1096,17 +1096,6 @@ com.sun.star.comp.sd.InsertSlideController - - - - .uno:SlideTransitionsPane - - - com.sun.star.presentation.PresentationDocument - - - com.sun.star.comp.sd.SlideTransitionsToolBoxControl - diff --git a/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu index 4defbc77139f..e46d53eea7f7 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu @@ -143,6 +143,28 @@ 1 + + + Sho~w Page + + + 1 + + + .uno:ShowSlide + + + + + ~Hide Page + + + 1 + + + .uno:HideSlide + + Te~xt Attributes... @@ -439,11 +461,6 @@ Master Slides - - - ~Connector... - - S~lide Show Settings... @@ -777,6 +794,16 @@ 1 + + + Copy Slide + + + + + Paste Slide + + E~xternal Links... @@ -801,6 +828,7 @@ ~Outline + Outline refers to a mode that shows an overview of the slides 1 @@ -1202,6 +1230,36 @@ 1 + + + Add Section + + + + + Remove Section + + + + + Remove Section & Slides + + + + + Rename Section... + + + + + Move Section Up + + + + + Move Section Down + + Delete Layer @@ -2338,14 +2396,6 @@ Presentation ~Object... - - - Hanging Indent - - - 1 - - Export Redacted PDF (Black) diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu index 1b1af5583b5a..00aa9987f5e9 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu @@ -1797,15 +1797,12 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 - Find Values - - - Find text in values, to search in formulas use the dialog + Find Text - Find Next + Find Next (F3) 1 @@ -1813,7 +1810,7 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 - Find Previous + Find Previous (Shift+F3) 1 @@ -3108,12 +3105,15 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 Outline Format + Outline as in the style of list ~Outline Format + Outline as in the style of list Select Outline Format + Outline as in the style of list 15 @@ -3135,6 +3135,14 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 1 + + + ~Connector Attributes + + + 1 + + Dimen~sions... @@ -3518,14 +3526,6 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 1 - - - Slide Transitions - - - 1 - - Date Field @@ -3820,7 +3820,7 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 - Open Hyperlink + Open Hyperlin~k 1 @@ -4099,6 +4099,7 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 ~Remove Outline + Outline refers to a group of cells @@ -5353,6 +5354,14 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 7 + + + Hanging Indent + + + 1 + + Curves and Polygons @@ -5762,14 +5771,6 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 Optio~n Bar - - - Send Feedback - - - 1 - - ~Get Help Online @@ -5826,6 +5827,11 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 %PRODUCTNAME Credits + + + Credits Online + + Status ~Bar @@ -7127,6 +7133,14 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 1 + + + Security Options + + + 1 + + @@ -7842,7 +7856,7 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 - ~Restart in Safe Mode... + ~Restart in Troubleshoot Mode... 1 diff --git a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu index 60eacde2cc73..4b905b02120e 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu @@ -38,6 +38,17 @@ 1 + + + ~Draft View + + + ~Draft + + + 1 + + Insert Header @@ -262,7 +273,7 @@ Reject but Track and Move to Next - Reject tracked change but keep it and select the next one + Reject change (keep as tracked) and select the next one 1 @@ -287,7 +298,7 @@ Reject but Track All - Reject all tracked changes but keep them + Reject all changes (keep as tracked) 1 @@ -337,7 +348,7 @@ Reject but Track - Reject tracked change but keep it + Reject change (keep as tracked) 1 @@ -1282,6 +1293,9 @@ Appl~y + + 1 + @@ -1573,14 +1587,6 @@ 1 - - - Translate... - - - 1 - - Co~lumns... @@ -2120,11 +2126,16 @@ 1 + + + .uno:UpdateFields?UnlockSoftFixed:bool=1 + + + Update ~Fields + + - ~Fields - - Update ~Fields @@ -3173,11 +3184,6 @@ 1 - - - Add Unknown Words - - Horizontal Scroll Bar @@ -4311,6 +4317,9 @@ Orientation + + Change page orientation to portrait or landscape + 1 @@ -4331,14 +4340,6 @@ 1 - - - Hanging Indent - - - 1 - - Watermark... diff --git a/officecfg/registry/data/org/openoffice/VCL.xcu b/officecfg/registry/data/org/openoffice/VCL.xcu index a1fad048ff51..b135ba92cffb 100644 --- a/officecfg/registry/data/org/openoffice/VCL.xcu +++ b/officecfg/registry/data/org/openoffice/VCL.xcu @@ -856,25 +856,6 @@ - - - Agency FB - - - Agency FB - - - Normal,SansSerif - - - - - Agdasima - - - Normal,SansSerif - - albanyamt;albany;liberationsans;arial;nimbussansl;helvetica;lucidasans;lucida;geneva;helmet;sansserif;nimbussans;andalesansui;arialunicodems;lucidaunicode @@ -1124,20 +1105,9 @@ Normal,SansSerif - - - Baskerville Old Face - - - Baskerville Old Face - - - Normal,Serif - - - Bacasime Antique;thorndaleamt;thorndale;timesnewroman;nimbusromanno9l;times;timesroman;newyork;timmons;serif;lucidaserif;lucidabright;roman;nimbusromanno9;bookman;itcbookman;garamond;garamondmt;palatino + thorndaleamt;thorndale;timesnewroman;nimbusromanno9l;times;timesroman;newyork;timmons;serif;lucidaserif;lucidabright;roman;nimbusromanno9;bookman;itcbookman;garamond;garamondmt;palatino @@ -1186,17 +1156,6 @@ CJK,CJK_KR - - - Berlin Sans FB - - - Berlin Sans FB - - - Normal,SansSerif - - thorndaleamt;thorndale;timesnewroman;nimbusromanno9l;times;timesroman;newyork;timmons;serif;lucidaserif;lucidabright;roman;nimbusromanno9;bookman;itcbookman;garamond;garamondmt;palatino @@ -1214,14 +1173,6 @@ Normal,Serif - - - Belanosima - - - Normal,SansSerif - - dejavusans @@ -1426,17 +1377,6 @@ Normal,SansSerif - - - Cooper Black - - - Cooper Black - - - Normal,Serif - - Normal,SansSerif,Fixed @@ -1447,14 +1387,6 @@ Normal,Serif - - - Caprasimo - - - Normal,Serif - - Normal,SansSerif @@ -3126,7 +3058,7 @@ - Lugrasimo;zapfchancery;itczapfchancery;monotypecorsiva;corsiva;chancery;chanceryl;lucidacalligraphy;lucidahandwriting;palacescript;palacescriptmt;arioso;shelley;andymt;comicsansms;andy;kidprint; + zapfchancery;itczapfchancery;monotypecorsiva;corsiva;chancery;chanceryl;lucidacalligraphy;lucidahandwriting;palacescript;palacescriptmt;arioso;shelley;andymt;comicsansms;andy;kidprint; @@ -3177,7 +3109,7 @@ - Lumanosimo;andymt;comicsansms;andy;kidprint;zapfchancery;itczapfchancery;monotypecorsiva;corsiva;chancery;chanceryl;lucidacalligraphy;lucidahandwriting;palacescript;palacescriptmt;arioso;shelley + andymt;comicsansms;andy;kidprint;zapfchancery;itczapfchancery;monotypecorsiva;corsiva;chancery;chanceryl;lucidacalligraphy;lucidahandwriting;palacescript;palacescriptmt;arioso;shelley @@ -3192,14 +3124,6 @@ Italic,Script,Handwriting - - - Lunasima - - - Normal,SansSerif - - albanyamt;albany;arial;nimbussansl;helvetica;lucidasans;lucida;geneva;helmet;sansserif;nimbussans;andalesansui;arialunicodems;lucidaunicode @@ -3302,39 +3226,6 @@ Normal,Fixed,Typewriter - - - Lucida Calligraphy - - - Lucida Calligraphy - - - Italic,Script,Chancery - - - - - Lucida Grande - - - Lucida Grande - - - Normal,SansSerif - - - - - Lucida Handwriting - - - Lucida Handwriting - - - Italic,Script,Handwriting - - starsymbol;opensymbol;starbats;wingdings;zapfdingbats;itczapfdingbats;monotypesorts;dingbats;lucidadingbats;lucidasansdingbats;webdings;symbol;standardsymbols;standardsymbolsl;andalesansui;arialunicodems;lucidaunicode diff --git a/officecfg/registry/schema/org/openoffice/Inet.xcs b/officecfg/registry/schema/org/openoffice/Inet.xcs index c88b846da76b..9526e744b250 100644 --- a/officecfg/registry/schema/org/openoffice/Inet.xcs +++ b/officecfg/registry/schema/org/openoffice/Inet.xcs @@ -57,34 +57,6 @@ - - - - Specifies the name of the FTP proxy server. - Not used anymore - - - - - - - - Specifies the port of the FTP proxy server. - Not used anymore - - - - - Specifies the minimum allowed port number. - - - - - Specifies the maximum allowed port number. - - - - diff --git a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs index 1f85aab91333..26c8e6cd75e8 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs @@ -721,6 +721,13 @@ true + + + Specifies whether a warning infobar will appear when deleting cells breaks references in other cells. + + + false + Toggles the scroll lock behavior allowing to disable it for special keyboards @@ -926,10 +933,10 @@ Contains settings for DBF Import dialog - + - Charset/Language - + Encoding/Language + -1 @@ -938,10 +945,10 @@ Contains settings for DBF Export dialog - + - Charset/Language - + Encoding/Language + -1 @@ -950,10 +957,10 @@ Contains setting for Text CSV Export - + - Char Set - + Encoding/Language + -1 @@ -1165,7 +1172,7 @@ - If true, Calc preserves previous content of cells when pasting empty ones. If false, Calc delete content of previous cells. + If true, Calc preserves previous content of cells when pasting empty ones. If false, Calc deletes content of previous cells. true @@ -1279,7 +1286,7 @@ - If true, Calc preserves previous content of cells when pasting empty ones. If false, Calc delete content of previous cells. + If true, Calc preserves previous content of cells when pasting empty ones. If false, Calc deletes content of previous cells. false @@ -1307,6 +1314,18 @@ + + + Contains settings for copying cells to the clipboard. + + + + If true (default), the copied cell range is shrunk to the data area, omitting empty cells at the leading and trailing edges of the selection. Set to false to preserve the full selection including empty border cells. + + + true + + Contains settings that affect cell calculation. @@ -1758,39 +1777,6 @@ false - - - Contains settings for MS Excel import. - - - - Specifies the factor for multiplying the column width when importing Excel documents from Biff 5 format. - - - - - - Specifies the minimum allowed value. - - - - 1.0 - - - - Specifies the factor for multiplying the row height when importing Excel documents from Biff 5 format. - - - - - - Specifies the minimum allowed value. - - - - 1.0 - - @@ -1973,7 +1959,7 @@ - Insert link for the cell, instead of text fields in a cell.(Excel interopability options) + Insert link for the cell, instead of text fields in a cell.(Excel interoperability options) false diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs index e2506f843218..3b70c74e86ad 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs @@ -92,402 +92,6 @@ - - - Describes the characteristics of a font. - - - - Specifies the exact name of the font ("Arial", "Courier", - "Frutiger"). - - - - - Specifies the height of the font in the measure of the - destination. - - - - - Specifies the width of the font in the measure of the - destination. - - - - - Specifies the style name of the font ("Bold", "Italic", "Italic - Bold"). - - - - - Specifies the general style of the font. - - - - - DONTKNOW - - - - - DECORATIVE - - - - - MODERN - - - - - ROMAN - - - - - SCRIPT - - - - - SWISS - - - - - SYSTEM - - - - - DONTKNOW - - - - - - - Specifies the character set which is supported by the - font. - - - - - DONTKNOW - - - - - ANSI - - - - - MAC - - - - - IBMPC_437 - - - - - IBMPC_850 - - - - - IBMPC_860 - - - - - IBMPC_861 - - - - - IBMPC_863 - - - - - IBMPC_865 - - - - - SYSTEM - - - - - SYMBOL - - - - - - - Specifies the pitch of the font. - - - - - DONTKNOW - - - - - FIXED - - - - - VARIABLE - - - - - - - Specifies the character width. Depending on the specified width, - a font that supports this width may be selected. [UNIT=%]. - - - - - Specifies the thickness of the line. - - - - - Specifies if there is a character slant (italic). - - - - - NONE - - - - - OBLIQUE - - - - - ITALIC - - - - - DONTKNOW - - - - - REVERSE_OBLIQUE - - - - - REVERSE_ITALIC - - - - - - - Specifies the type of underline. - - - - - NONE - - - - - SINGLE - - - - - DOUBLE - - - - - DOTTED - - - - - DONTKNOW - - - - - DASH - - - - - LONGDASH - - - - - DASHDOT - - - - - DASHDOTDOT - - - - - SMALLWAVE - - - - - WAVE - - - - - DOUBLEWAVE - - - - - BOLD - - - - - BOLDDOTTED - - - - - BOLDDASH - - - - - BOLDLONGDASH - - - - - BOLDDASHDOT - - - - - BOLDDASHDOTDOT - - - - - BOLDWAVE - - - - - - - Specifies the type of strikeout. - - - - - NONE - - - - - SINGLE - - - - - DOUBLE - - - - - DONTKNOW - - - - - BOLD - - - - - SLASH - - - - - X - - - - - - - Specifies the rotation of the font. [UNIT=degree]. - - - - - Specifies if a kerning table is available (for requesting). For - selecting, specifies if the kerning table is to be used. - - - - - Specifies if only words get underlined. - - - - - Specifies the technology of the font representation. - - - - - DONTKNOW - - - - - RASTER - - - - - DEVICE - - - - - SCALABLE - - - - - Contains settings for the font replacement. @@ -669,11 +273,11 @@ false - + - Specifies if Skia rendering should be used in VCL backends - supporting it. This one forces the use of Skia software rendering - instead of trying to use the graphics driver. + Specifies if Skia hardware acceleration should be used in VCL backends + supporting it. This one forces the use of Skia hardware acceleration instead of + Skia software rendering. false @@ -699,7 +303,7 @@ export - can save potentially huge amount of CPU time on re-compressing the same JPEG image over and over again. - 15 + 64 @@ -1034,7 +638,7 @@ Specifies the maximum allowed luminance the system's selection - color may have. When the colorfetched from the system is brighter + color may have. When the color fetched from the system is brighter (luminance is bigger), it will be scaled to a luminance of exactly this given value. true + + + + Specifies if x’s in Esperanto text should become circumflexes, for example “cxu” becomes “ĉu”. + + + true + @@ -1838,11 +1450,6 @@ Contains all help bookmarks. - - - Specifies the URL used with the UNO command SendFeedback (SID_SEND_FEEDBACK). - - Specifies the URL opened per click on the brand image at the start center. @@ -5626,6 +5233,14 @@ 0 + + + + Specifies which transparency at which module and dialog color are merged for + the notebookbar. Use 0 for full module and 255 for full dialog. + + 150 + @@ -6884,6 +6499,35 @@ true + + + Contains settings for Styles drop down control. + + + + Specifies if the default styles are shown in the list. + + true + + + + Specifies if the used styles are shown in the list. + + true + + + + Specifies if the favourite styles are shown in the list. + + true + + + + Specifies if the user defined styles are shown in the list. + + true + + Contains settings related to PackageKit (Unix only). diff --git a/officecfg/registry/schema/org/openoffice/Office/Compatibility.xcs b/officecfg/registry/schema/org/openoffice/Office/Compatibility.xcs index ceac1168629c..22bb901fb9e5 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Compatibility.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Compatibility.xcs @@ -62,12 +62,6 @@ false - - - Use OpenOffice.org 1.1 line spacing - - false - Add paragraph and table spacing at bottom of table cells @@ -182,6 +176,12 @@ false + + + Place the line spacing gap below the line: aesthetically balanced, consistent, and interoperable + + true + Adjust spaces to half the width of ideographic spaces, using Word-compatible rules diff --git a/officecfg/registry/schema/org/openoffice/Office/Draw.xcs b/officecfg/registry/schema/org/openoffice/Office/Draw.xcs index 04bb62c04548..5a774549693d 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Draw.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Draw.xcs @@ -71,6 +71,14 @@ true + + + + Indicates whether the mouse wheel zooms instead of scrolling and Control plus the mouse wheel scrolls instead of zooming. + + + false + @@ -440,14 +448,6 @@ Contains the specification of how to force object positions and sizes to predefined locations in relation to other objects. - - - - Indicates whether to snap an object when moved to the next grid point. - - - false - diff --git a/officecfg/registry/schema/org/openoffice/Office/Impress.xcs b/officecfg/registry/schema/org/openoffice/Office/Impress.xcs index ead87b0fe4a1..7bdb5cb9f5ad 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Impress.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Impress.xcs @@ -697,14 +697,6 @@ Specifies how to force object positions and sizes to predefined locations in relation to other objects. - - - - Indicates whether to snap an object when moved to the next grid point. - - - true - diff --git a/officecfg/registry/schema/org/openoffice/Office/Linguistic.xcs b/officecfg/registry/schema/org/openoffice/Office/Linguistic.xcs index 8fcb6a3ccd62..1da9958f5763 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Linguistic.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Linguistic.xcs @@ -415,28 +415,6 @@ - - - Contains translation relevant settings. - - - - Contains DeepL API relevant settings. - - - - Deepl Translator API URL - - - - - - Deepl Translator API URL Authkey - - - - - Contains hyphenation relevant settings. diff --git a/officecfg/registry/schema/org/openoffice/Office/PresenterScreen.xcs b/officecfg/registry/schema/org/openoffice/Office/PresenterScreen.xcs index 917ae8930248..52412c365211 100644 --- a/officecfg/registry/schema/org/openoffice/Office/PresenterScreen.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/PresenterScreen.xcs @@ -59,7 +59,7 @@ - The file name of the mask bitmap. Use red for pixel outside of + The file name of the mask bitmap. Use red for pixels outside of the border and blue for inside pixels. @@ -90,8 +90,8 @@ - Color that is used as replacement for the bitmap when the later - can for some reason not be used. + Color that is used as replacement for the bitmap when the latter + cannot be used for some reason. @@ -497,14 +497,6 @@ default theme is 'DefaultTheme' - - - Name of the parent theme. Values not supplied in this theme - are taken from the parent theme. Empty string or missing - mean default theme. - - - Color or bitmap that is used to paint the diff --git a/officecfg/registry/schema/org/openoffice/Office/UI/Infobar.xcs b/officecfg/registry/schema/org/openoffice/Office/UI/Infobar.xcs index 5e652b482419..867e64fd7b73 100644 --- a/officecfg/registry/schema/org/openoffice/Office/UI/Infobar.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/UI/Infobar.xcs @@ -72,6 +72,12 @@ true + + + Whether an Infobar is shown when the generic VCL is used. + + true + diff --git a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs index 1d4b93cac434..eef8fdf64290 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs @@ -2202,6 +2202,13 @@ true + + + Specifies whether typing replaces the selected text. + + + true + @@ -4098,6 +4105,14 @@ true + + + + Specifies if x’s in Esperanto text should become circumflexes, for example “cxu” becomes “ĉu”. + + + true + @@ -5353,6 +5368,12 @@ 0 + + + Specifies whether the Navigate By control also selects the content type in the Navigator list box and vice versa. + + true + @@ -5932,34 +5953,6 @@ Contains settings for the WinWord filter. - - - Specifies the flags for controlling the import of WinWord 1.0 documents. - - - - - Off - - - - - TAG_FLD - - - - - ALLOW_FLD_CR - - - - - DONT_HARD_PROTECT - - - - 0 - Specifies the flags for importing WinWord documents. @@ -6217,40 +6210,6 @@ 0 - - - Specifies the distance between the footnote and the main text [UNIT=1/100 mm]. - - 0 - - - - Specifies several flags for exporting (for debugging). - - - - - Off - - - - - WWFL_ULSPACE_LIKE_SWG - - - - - WWFL_NO_GRAF - - - - - WWFL_NO_OLE - - - - 0 - If true yields to digits marked as CTL script to be imported as Hindi digits. diff --git a/officecfg/registry/schema/org/openoffice/Setup.xcs b/officecfg/registry/schema/org/openoffice/Setup.xcs index de6740bdbf2f..0c4759ba6bf4 100644 --- a/officecfg/registry/schema/org/openoffice/Setup.xcs +++ b/officecfg/registry/schema/org/openoffice/Setup.xcs @@ -183,7 +183,7 @@ 0 - + Specifies the ID of the style filter (Stylist) for the diff --git a/officecfg/util/AcceleratorKeyChecker.fodt b/officecfg/util/AcceleratorKeyChecker.fodt index e40928c28a10..71e14e9c829e 100644 --- a/officecfg/util/AcceleratorKeyChecker.fodt +++ b/officecfg/util/AcceleratorKeyChecker.fodt @@ -345,8 +345,10 @@ End Sub Function getAccessibleContextOfDocument(oDoc) Dim oContainerWindow As Object +Dim oAccessible as Object oContainerWindow = oDoc.getCurrentController().getFrame().getContainerWindow() - getAccessibleContextOfDocument = oContainerWindow.getAccessibleContext() + oAccessible = oContainerWindow.getProperty("XAccessible") + getAccessibleContextOfDocument = oAccessible.getAccessibleContext() End Function Function makeKeyStrokeReadable(oKeyStroke, Optional bIgnoreAltModifier) diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk index 74b9dc3f2aaa..66f1ad7256c5 100644 --- a/oox/Library_oox.mk +++ b/oox/Library_oox.mk @@ -92,6 +92,7 @@ $(eval $(call gb_Library_set_componentfile,oox,oox/util/oox,services)) ifeq (,$(ENABLE_WASM_STRIP_CHART)) $(eval $(call gb_Library_add_exception_objects,oox,\ oox/source/export/chartexport \ + oox/source/export/chartgeographyexport \ oox/source/drawingml/chart/axiscontext \ oox/source/drawingml/chart/axisconverter \ oox/source/drawingml/chart/axismodel \ @@ -106,6 +107,9 @@ $(eval $(call gb_Library_add_exception_objects,oox,\ oox/source/drawingml/chart/datasourceconverter \ oox/source/drawingml/chart/datasourcemodel \ oox/source/drawingml/chart/datatablecontext \ + oox/source/drawingml/chart/geographycontext \ + oox/source/drawingml/chart/geographyconverter \ + oox/source/drawingml/chart/geographymodel \ oox/source/drawingml/chart/datatableconverter \ oox/source/drawingml/chart/modelbase \ oox/source/drawingml/chart/objectformatter \ diff --git a/oox/inc/drawingml/chart/axisconverter.hxx b/oox/inc/drawingml/chart/axisconverter.hxx index 6efa3af6262e..0558abd3fb45 100644 --- a/oox/inc/drawingml/chart/axisconverter.hxx +++ b/oox/inc/drawingml/chart/axisconverter.hxx @@ -29,6 +29,7 @@ namespace com::sun::star { namespace oox::drawingml::chart { +enum class ChartType : sal_Int32; struct AxisDispUnitsModel; @@ -60,7 +61,8 @@ public: void convertFromModel( const css::uno::Reference& rxCoordSystem, RefVector& rTypeGroups, const AxisModel* pCrossingAxis, - sal_Int32 nAxesSetIdx, sal_Int32 nAxisIdx, bool bUseFixedInnerSize ); + sal_Int32 nAxesSetIdx, sal_Int32 nAxisIdx, bool bUseFixedInnerSize, + ChartType eCT); }; diff --git a/oox/inc/drawingml/chart/axismodel.hxx b/oox/inc/drawingml/chart/axismodel.hxx index 0c1799276083..c32a6e3569ea 100644 --- a/oox/inc/drawingml/chart/axismodel.hxx +++ b/oox/inc/drawingml/chart/axismodel.hxx @@ -43,6 +43,12 @@ struct AxisDispUnitsModel ~AxisDispUnitsModel(); }; +enum class ChartType : sal_Int32 { + C_2007, // 2007 chart + C_OTHER, // later chart + CX // later chartex +}; + struct AxisModel { typedef ModelRef< Shape > ShapeRef; @@ -56,11 +62,13 @@ struct AxisModel AxisDispUnitsRef mxDispUnits; /// Axis units label. ShapeRef mxMajorGridLines; /// Major grid lines formatting. ShapeRef mxMinorGridLines; /// Minor grid lines formatting. - NumberFormat maNumberFormat; /// Number format for axis tick labels. + std::optional maNumberFormat; /// Number format for axis tick labels. + std::optional mobCatNotVal; /// True if cat axis, false if val axis (for chartex) std::optional< double > mofCrossesAt; /// Position on this axis where another axis crosses. std::optional< double > mofMajorUnit; /// Unit for major tick marks on date/value axis. std::optional< double > mofMinorUnit; /// Unit for minor tick marks on date/value axis. std::optional< double > mofLogBase; /// Logarithmic base for logarithmic axes. + std::optional< double > mofGapWidth; /// Gap width ratio (chartex catScaling). std::optional< double > mofMax; /// Maximum axis value. std::optional< double > mofMin; /// Minimum axis value. std::optional< sal_Int32 > monBaseTimeUnit; /// Base time unit shown on a date axis. @@ -83,8 +91,10 @@ struct AxisModel bool mbAuto; /// True = automatic selection of text/date axis type. bool mbDeleted; /// True = axis has been deleted manually. bool mbNoMultiLevel; /// True = no multi-level categories supported. + bool mbMajorGridLinesHasSpPr; /// True = imported cx:majorGridlines had an spPr child. + bool mbMinorGridLinesHasSpPr; /// True = imported cx:minorGridlines had an spPr child. - explicit AxisModel( sal_Int32 nTypeId, bool bMSO2007Doc ); + explicit AxisModel( sal_Int32 nTypeId, enum ChartType eCT ); ~AxisModel(); }; diff --git a/oox/inc/drawingml/chart/datasourceconverter.hxx b/oox/inc/drawingml/chart/datasourceconverter.hxx index eb404e046389..716729ea6df9 100644 --- a/oox/inc/drawingml/chart/datasourceconverter.hxx +++ b/oox/inc/drawingml/chart/datasourceconverter.hxx @@ -21,6 +21,7 @@ #define INCLUDED_OOX_DRAWINGML_CHART_DATASOURCECONVERTER_HXX #include +#include namespace com::sun::star { namespace chart2::data { class XDataSequence; } @@ -28,7 +29,6 @@ namespace com::sun::star { namespace oox::drawingml::chart { - struct DataSequenceModel; class DataSequenceConverter final : public ConverterBase< DataSequenceModel > @@ -37,9 +37,11 @@ public: explicit DataSequenceConverter( const ConverterRoot& rParent, DataSequenceModel& rModel ); virtual ~DataSequenceConverter() override; - /** Creates a data sequence object from the contained formula link. */ + /** Creates a data sequence object from the contained formula link. + @param oDimType If set, stores this as the ChartExDimType property. */ css::uno::Reference< css::chart2::data::XDataSequence > - createDataSequence( const OUString& rRole ); + createDataSequence( const OUString& rRole, + DataSourceType eDimType ); }; @@ -51,9 +53,11 @@ public: explicit DataSourceConverter( const ConverterRoot& rParent, DataSourceModel& rModel ); virtual ~DataSourceConverter() override; - /** Creates a data sequence object from the contained series data. */ + /** Creates a data sequence object from the contained series data. + @param oDimType If set, forwarded to DataSequenceConverter. */ css::uno::Reference< css::chart2::data::XDataSequence > - createDataSequence( const OUString& rRole ); + createDataSequence( const OUString& rRole, + DataSourceType eDimType ); }; diff --git a/oox/inc/drawingml/chart/geographycontext.hxx b/oox/inc/drawingml/chart/geographycontext.hxx new file mode 100644 index 000000000000..439b7fef5ab9 --- /dev/null +++ b/oox/inc/drawingml/chart/geographycontext.hxx @@ -0,0 +1,43 @@ +/* -*- 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/. + */ + +#pragma once + +#include + +namespace oox::drawingml::chart +{ +struct GeographyModel; +struct GeoLocationQueryResultModel; +struct GeoDataEntityQueryResultModel; +struct GeoDataPointToEntityQueryResultModel; +struct GeoChildEntitiesQueryResultModel; +struct GeoParentEntitiesQueryResultModel; + +class GeographyContext final : public ::oox::core::ContextHandler2 +{ +public: + explicit GeographyContext(::oox::core::ContextHandler2Helper& rParent, GeographyModel& rModel); + + virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; + virtual void onCharacters(const OUString& rChars) override; + +private: + GeographyModel& mrModel; + GeoLocationQueryResultModel* mpCurLocResult = nullptr; + GeoDataEntityQueryResultModel* mpCurDataResult = nullptr; + GeoDataPointToEntityQueryResultModel* mpCurPtResult = nullptr; + GeoChildEntitiesQueryResultModel* mpCurChildResult = nullptr; + GeoParentEntitiesQueryResultModel* mpCurParentResult = nullptr; +}; + +} // namespace oox::drawingml::chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/inc/drawingml/chart/geographyconverter.hxx b/oox/inc/drawingml/chart/geographyconverter.hxx new file mode 100644 index 000000000000..6fc09816414b --- /dev/null +++ b/oox/inc/drawingml/chart/geographyconverter.hxx @@ -0,0 +1,34 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include + +namespace oox +{ +class PropertySet; +} + +namespace oox::drawingml::chart +{ +struct GeographyModel; +struct GeoClearModel; + +void convertGeography(const GeographyModel& rModel, PropertySet& rSeriesProp); + +css::uno::Sequence geoClearToPropertyValues(const GeoClearModel& rModel); + +GeoClearModel +geoClearFromPropertyValues(const css::uno::Sequence& rProps); + +} // namespace oox::drawingml::chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/inc/drawingml/chart/geographymodel.hxx b/oox/inc/drawingml/chart/geographymodel.hxx new file mode 100644 index 000000000000..e653d347cddf --- /dev/null +++ b/oox/inc/drawingml/chart/geographymodel.hxx @@ -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/. + */ + +#pragma once + +#include +#include +#include +#include + +namespace oox::drawingml::chart +{ +// ST_GeoProjectionType +enum class GeoProjectionType : sal_Int32 +{ + Mercator, + Miller, + Robinson, + Albers, +}; + +// ST_GeoMappingLevel +enum class GeoMappingLevel : sal_Int32 +{ + DataOnly, + PostalCode, + County, + State, + CountryRegion, + CountryRegionList, + World, + Autodetect, +}; + +GeoProjectionType geoProjectionTypeFromString(std::u16string_view rStr); +OUString geoProjectionTypeToString(GeoProjectionType eType); + +GeoMappingLevel geoMappingLevelFromString(std::u16string_view rStr); +OUString geoMappingLevelToString(GeoMappingLevel eLevel); +struct GeoAddressModel +{ + std::optional mosAddress1; + std::optional mosCountryRegion; + std::optional mosAdminDistrict1; + std::optional mosAdminDistrict2; + std::optional mosPostalCode; + std::optional mosLocality; + std::optional mosIsoCountryCode; +}; + +struct GeoLocationQueryModel +{ + std::optional mosCountryRegion; + std::optional mosAdminDistrict1; + std::optional mosAdminDistrict2; + std::optional mosPostalCode; + std::optional mosEntityType; +}; + +struct GeoLocationModel +{ + std::optional mosLatitude; + std::optional mosLongitude; + std::optional mosEntityName; + std::optional mosEntityType; + std::optional mxAddress; +}; + +struct GeoLocationQueryResultModel +{ + std::optional mxQuery; + std::vector maLocations; +}; + +struct GeoDataEntityQueryModel +{ + std::optional mosEntityType; + std::optional mosEntityId; +}; + +struct GeoPolygonModel +{ + std::optional mosPolygonId; + std::optional mosNumPoints; + std::optional mosPcaRings; +}; + +struct GeoCopyrightModel +{ + OUString msText; +}; + +struct GeoDataModel +{ + std::optional mosEntityName; + std::optional mosEntityId; + std::optional mosEast; + std::optional mosWest; + std::optional mosNorth; + std::optional mosSouth; + std::vector maPolygons; + std::vector maCopyrights; +}; + +struct GeoDataEntityQueryResultModel +{ + std::optional mxQuery; + std::optional mxData; +}; + +struct GeoDataPointQueryModel +{ + std::optional mosEntityType; + std::optional mosLatitude; + std::optional mosLongitude; +}; + +struct GeoDataPointToEntityQueryModel +{ + std::optional mosEntityType; + std::optional mosEntityId; +}; + +struct GeoDataPointToEntityQueryResultModel +{ + std::optional mxPointQuery; + std::optional mxEntityQuery; +}; + +struct GeoChildEntitiesQueryModel +{ + std::optional mosEntityId; + std::vector maEntityTypes; +}; + +struct GeoHierarchyEntityModel +{ + std::optional mosEntityName; + std::optional mosEntityId; + std::optional mosEntityType; +}; + +struct GeoChildEntitiesQueryResultModel +{ + std::optional mxQuery; + std::vector maEntities; +}; + +struct GeoParentEntitiesQueryModel +{ + std::optional mosEntityId; +}; + +struct GeoEntityModel +{ + std::optional mosEntityName; + std::optional mosEntityType; +}; + +struct GeoParentEntityModel +{ + std::optional mosEntityId; +}; + +struct GeoParentEntitiesQueryResultModel +{ + std::optional mxQuery; + std::optional mxEntity; + std::optional mxParentEntity; +}; + +struct GeoClearModel +{ + std::vector maLocResults; + std::vector maDataResults; + std::vector maPtResults; + std::vector maChildResults; + std::vector maParentResults; +}; + +struct GeoCacheModel +{ + std::optional mosProvider; + std::optional mosBinary; + std::optional mxClear; +}; + +struct GeographyModel +{ + std::optional moeProjectionType; + std::optional moeViewedRegionType; + std::optional mosCultureLanguage; + std::optional mosCultureRegion; + std::optional mosAttribution; + std::optional mxGeoCache; +}; + +} // namespace oox::drawingml::chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/inc/drawingml/chart/plotareamodel.hxx b/oox/inc/drawingml/chart/plotareamodel.hxx index 8f1528465d46..e7dd5dc4db50 100644 --- a/oox/inc/drawingml/chart/plotareamodel.hxx +++ b/oox/inc/drawingml/chart/plotareamodel.hxx @@ -67,6 +67,7 @@ struct PlotAreaModel DataTableRef mxDataTable; /// Data table of the plot area. sal_Int32 mnCurSeriesIdx = 0; /// For populating the series index + ChartType meCT = ChartType::C_OTHER; explicit PlotAreaModel(); ~PlotAreaModel(); diff --git a/oox/inc/drawingml/chart/seriesmodel.hxx b/oox/inc/drawingml/chart/seriesmodel.hxx index 21b1df810fb3..df171a308c1d 100644 --- a/oox/inc/drawingml/chart/seriesmodel.hxx +++ b/oox/inc/drawingml/chart/seriesmodel.hxx @@ -24,6 +24,7 @@ #include #include +#include namespace oox::drawingml::chart { @@ -185,6 +186,8 @@ struct BinningModel std::optional> maBinSizeOrCount; std::optional meIntervalClosed; // Which side of an interval is closed + std::optional mfUnderflow; + std::optional mfOverflow; explicit BinningModel(); }; @@ -195,14 +198,21 @@ struct LayoutPropsModel // There's also a CT_Aggregation but no content given BinningRef mxBinning; // Binning settings. -}; -enum class DataSourceType: sal_Int32 -{ - CATEGORIES, /// Data point categories. - VALUES, /// Data point values. - POINTS, /// Data point size (e.g. bubble size in bubble charts). - DATALABELS, /// Data point labels. + // Chartex visibility flags, from CT_SeriesElementVisibilities + std::optional mobVisibilityConnectorLines; + std::optional mobVisibilityMeanLine; + std::optional mobVisibilityMeanMarker; + std::optional mobVisibilityNonoutliers; + std::optional mobVisibilityOutliers; + + // Chartex layoutPr: label layout, statistics, subtotals + std::optional mosParentLabelLayout; + std::optional mosRegionLabelLayout; + std::optional mosQuartileMethod; + std::vector maSubtotalIndices; + + std::optional mxGeography; }; struct SeriesModel @@ -233,6 +243,7 @@ struct SeriesModel sal_Int32 mnMarkerSize; /// Size of the series line marker (2...72). sal_Int32 mnMarkerSymbol; /// Series line marker symbol. sal_Int32 mnOrder; /// Series order. + sal_Int32 mnTypeId; /// Chart type sal_Int32 mnDataId; /// Reference to correct data chunk (chartex) bool mbBubble3d; /// True = show bubbles with 3D shade. bool mbInvertNeg; /// True = invert negative data points. @@ -240,8 +251,14 @@ struct SeriesModel std::vector maAxisIds; /// List of axis identifiers used // (Only used by chartex) + std::optional + monOwnerIdx; /// cx:series/@ownerIdx (chartex): + /// zero-based index of the series + /// in the same plotAreaRegion whose + /// data this series shares. When + /// set, no cx:dataId is emitted. - explicit SeriesModel(bool bMSO2007Doc); + explicit SeriesModel(bool bMSO2007Doc, sal_Int32 nTypeId = -1); ~SeriesModel(); }; diff --git a/oox/inc/drawingml/chart/titleconverter.hxx b/oox/inc/drawingml/chart/titleconverter.hxx index f72103f82e1f..f3d781a4f204 100644 --- a/oox/inc/drawingml/chart/titleconverter.hxx +++ b/oox/inc/drawingml/chart/titleconverter.hxx @@ -59,6 +59,7 @@ private: }; +enum class ChartType : sal_Int32; struct TitleModel; class TitleConverter final : public ConverterBase< TitleModel > @@ -71,6 +72,7 @@ public: void convertFromModel( const css::uno::Reference< css::chart2::XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType, + ChartType eCT, sal_Int32 nMainIdx = -1, sal_Int32 nSubIdx = -1 ); }; @@ -85,7 +87,7 @@ public: /** Creates a legend object and attaches it at the passed diagram. */ void convertFromModel( - const css::uno::Reference< css::chart2::XDiagram >& rxDiagram ); + const css::uno::Reference< css::chart2::XDiagram >& rxDiagram, ChartType eCT ); private: void legendEntriesFormatting(const css::uno::Reference& rxDiagram); diff --git a/oox/inc/drawingml/chart/typegroupconverter.hxx b/oox/inc/drawingml/chart/typegroupconverter.hxx index c013153ec0a3..8e347f1f5171 100644 --- a/oox/inc/drawingml/chart/typegroupconverter.hxx +++ b/oox/inc/drawingml/chart/typegroupconverter.hxx @@ -106,6 +106,9 @@ struct TypeGroupInfo bool mbSwappedAxesSet; /// True = X axis and Y axis are swapped. bool mbSupportsStacking; /// True = data points can be stacked on each other. bool mbPictureOptions; /// True = bitmaps support options from c:pictureOptions. + bool mbShiftedCatPos; /// True = default category axis position is shifted + /// This can get overridden in AxisConverter::convertFromModel() + bool mb3dShiftedCatPos; /// True = default category axis position is shifted for 3d charts }; const TypeGroupInfo& GetTypeGroupInfo( TypeId eType ); @@ -153,7 +156,7 @@ public: /** Returns series title, if the chart type group contains only one single series. */ OUString getSingleSeriesTitle() const; - /** Returns true, if the chart contains only one series and have title textbox (even empty). */ + /** Returns true, if the chart contains only one series and has a title textbox (even empty). */ bool isSingleSeriesTitle() const; /** Creates a coordinate system according to the contained chart type. */ diff --git a/oox/inc/drawingml/chart/typegroupmodel.hxx b/oox/inc/drawingml/chart/typegroupmodel.hxx index 5a37797e1b25..5184908883d4 100644 --- a/oox/inc/drawingml/chart/typegroupmodel.hxx +++ b/oox/inc/drawingml/chart/typegroupmodel.hxx @@ -74,6 +74,8 @@ struct TypeGroupModel bool mbSmooth; /// True = smooth lines in line charts. bool mbVaryColors; /// True = different automatic colors for each point. bool mbWireframe; /// True = wireframe surface chart, false = filled surface chart. + /// True = this type group should be imported as histogram type - TYPEID_HISTO + bool mbForceHistogram = false; explicit TypeGroupModel( sal_Int32 nTypeId, bool bMSO2007Doc ); ~TypeGroupModel(); diff --git a/oox/qa/unit/CryptoTest.cxx b/oox/qa/unit/CryptoTest.cxx index 90a56620ce56..fd946f86cbb7 100644 --- a/oox/qa/unit/CryptoTest.cxx +++ b/oox/qa/unit/CryptoTest.cxx @@ -175,52 +175,6 @@ void CryptoTest::testAgileEncryptionInfoWritingAndParsing() OUString aPassword(u"Password"_ustr); std::vector aKeyDataSalt; - { // Preset AES128 - SHA1 - SvMemoryStream aEncryptionInfo; - { - oox::crypto::AgileEngine aEngine; - - aEngine.setPreset(oox::crypto::AgileEncryptionPreset::AES_128_SHA1); - aEngine.setupEncryption(aPassword); - aKeyDataSalt = aEngine.getInfo().keyDataSalt; - - oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream( - new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true); - - aEngine.writeEncryptionInfo(aBinaryEncryptionInfoOutputStream); - aBinaryEncryptionInfoOutputStream.close(); - - CPPUNIT_ASSERT_EQUAL(sal_uInt64(996), aEncryptionInfo.GetSize()); - } - - aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN); - - { - oox::crypto::AgileEngine aEngine; - - uno::Reference xInputStream( - new utl::OSeekableInputStreamWrapper(aEncryptionInfo)); - - xInputStream->skipBytes(4); // Encryption type -> Agile - - CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream)); - - oox::crypto::AgileEncryptionInfo& rInfo = aEngine.getInfo(); - CPPUNIT_ASSERT_EQUAL(sal_Int32(100000), rInfo.spinCount); - CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.saltSize); - CPPUNIT_ASSERT_EQUAL(sal_Int32(128), rInfo.keyBits); - CPPUNIT_ASSERT_EQUAL(sal_Int32(20), rInfo.hashSize); - CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.blockSize); - CPPUNIT_ASSERT_EQUAL(u"AES"_ustr, rInfo.cipherAlgorithm); - CPPUNIT_ASSERT_EQUAL(u"ChainingModeCBC"_ustr, rInfo.cipherChaining); - CPPUNIT_ASSERT_EQUAL(u"SHA1"_ustr, rInfo.hashAlgorithm); - CPPUNIT_ASSERT_EQUAL(toString(aKeyDataSalt), toString(rInfo.keyDataSalt)); - - CPPUNIT_ASSERT_EQUAL(false, aEngine.decryptAndCheckVerifierHash(u"Wrong")); - CPPUNIT_ASSERT_EQUAL(true, aEngine.decryptAndCheckVerifierHash(aPassword)); - } - } - { // Preset AES128 - SHA384 SvMemoryStream aEncryptionInfo; { diff --git a/oox/qa/unit/data/tdf154074_freeConnector.pptx b/oox/qa/unit/data/tdf154074_freeConnector.pptx new file mode 100644 index 000000000000..ded412c2faca Binary files /dev/null and b/oox/qa/unit/data/tdf154074_freeConnector.pptx differ diff --git a/oox/qa/unit/helper.cxx b/oox/qa/unit/helper.cxx index d9739e925dc3..a60f6547b83e 100644 --- a/oox/qa/unit/helper.cxx +++ b/oox/qa/unit/helper.cxx @@ -43,7 +43,7 @@ CPPUNIT_TEST_FIXTURE(Test, testImportTifCrop) // Without the accompanying fix in place, this failed with: // - Expected: 3928 // - Actual : 24553 - // i.e. lazy-loading lead to some unexpected crop rectangle, the image was not readable. + // i.e. lazy-loading led to some unexpected crop rectangle, the image was not readable. CPPUNIT_ASSERT_EQUAL(static_cast(3928), aCrop.Top); CPPUNIT_ASSERT_EQUAL(static_cast(6660), aCrop.Bottom); CPPUNIT_ASSERT_EQUAL(static_cast(1732), aCrop.Left); diff --git a/oox/qa/unit/shape.cxx b/oox/qa/unit/shape.cxx index f1d9fb90045d..e1bd0654923a 100644 --- a/oox/qa/unit/shape.cxx +++ b/oox/qa/unit/shape.cxx @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -145,6 +148,55 @@ CPPUNIT_TEST_FIXTURE(OoxShapeTest, testElbowConnectors) CPPUNIT_ASSERT_EQUAL(sal_Int32(-805), nEdgeLineDelta); } +CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf154074FreeConnector) +{ + // Bent connectors that are not connected to a shape at both ends carry a pre-authored path that + // must be kept as-is rather than re-routed - re-routing from the endpoints would produce a + // different shape. Before this was fixed the free end was re-routed and escaped into the wrong + // direction, dropping a corner so the arrow ended in empty space. Now the authored OOXML path + // is imposed directly. + loadFromFile(u"tdf154074_freeConnector.pptx"); + + uno::Reference xDrawPagesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY); + + // Assert that the connector's edge track is exactly the authored elbow. Checking the point + // positions (not just the point count) is essential: for the both-ends-unconnected bentConnector3 + // the pre-fix path also had 2 corners, just escaping into the wrong direction, so a point count + // alone would not detect the bug. The values are in 1/100 mm; the start/end points are the + // authored connector ends, the inner points are the bends. + auto assertTrack = [&xDrawPage](sal_Int32 nShapeIndex, + const std::vector& rExpected) { + uno::Reference xConnector(xDrawPage->getByIndex(nShapeIndex), + uno::UNO_QUERY); + auto* pEdgeObj = dynamic_cast(SdrObject::getSdrObjectFromXShape(xConnector)); + CPPUNIT_ASSERT(pEdgeObj); + const basegfx::B2DPolyPolygon aTrack(pEdgeObj->GetEdgeTrackPath()); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(1), aTrack.count()); + const basegfx::B2DPolygon aPoly(aTrack.getB2DPolygon(0)); + CPPUNIT_ASSERT_EQUAL(static_cast(rExpected.size()), aPoly.count()); + for (size_t i = 0; i < rExpected.size(); ++i) + { + CPPUNIT_ASSERT_DOUBLES_EQUAL(rExpected[i].getX(), aPoly.getB2DPoint(i).getX(), 2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(rExpected[i].getY(), aPoly.getB2DPoint(i).getY(), 2); + } + }; + + // Index 0 is the rounded rectangle. + + // Index 1: a bentConnector4 connected to the rectangle at its start only (stCxn, no endCxn). It + // draws a 3-corner elbow (5 points); the start point is the top gluepoint of the rectangle. + // Without the fix the free end was routed with only 2 corners. + assertTrack( + 1, { { 11382, 9646 }, { 11382, 9011 }, { 5379, 9011 }, { 5379, 14251 }, { 3235, 14251 } }); + + // Index 2: a rotated bentConnector3 that is not connected at either end. It draws a 2-corner + // elbow (4 points). Without the fix it also had 2 corners, but escaped into the wrong direction, + // so these coordinates differ from the pre-fix ones. + assertTrack(2, { { 18551, 12062 }, { 18551, 11462 }, { 23442, 11462 }, { 23442, 8957 } }); +} + CPPUNIT_TEST_FIXTURE(OoxShapeTest, testCurvedConnectors) { loadFromFile(u"curvedConnectors.pptx"); @@ -179,9 +231,12 @@ CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf165180_standardConnectorsECMA) uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + // The two bentConnector3 are not connected to a shape at either end, so their pre-authored path + // is kept as-is (imposed directly) rather than re-routed, and no EdgeLine deltas are used + // (tdf#154074). The remaining connectors are glued at both ends and keep using EdgeLine deltas. sal_Int32 aEdgeValue[] = { -1352, -2457, 2402, // bentConnector5 - 3977, 0, 0, // bentConnector3 - -2899, 0, 0, // bentConnector3 + 0, 0, 0, // bentConnector3 (free, path imposed) + 0, 0, 0, // bentConnector3 (free, path imposed) -1260, 4612, 0, // bentConnector4 -1431, -2642, 0, // bentConnector4 3831, 3438, -1578 }; // bentConnector5 @@ -215,9 +270,12 @@ CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf165180_standardConnectorsISO29500) uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + // The two bentConnector3 are not connected to a shape at either end, so their pre-authored path + // is kept as-is (imposed directly) rather than re-routed, and no EdgeLine deltas are used + // (tdf#154074). The remaining connectors are glued at both ends and keep using EdgeLine deltas. sal_Int32 aEdgeValue[] = { -1352, -2457, 2402, // bentConnector5 - 3977, 0, 0, // bentConnector3 - -2899, 0, 0, // bentConnector3 + 0, 0, 0, // bentConnector3 (free, path imposed) + 0, 0, 0, // bentConnector3 (free, path imposed) -1260, 4612, 0, // bentConnector4 -1431, -2642, 0, // bentConnector4 3831, 3438, -1578 }; // bentConnector5 @@ -255,16 +313,33 @@ CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf164623) uno::Reference xShape(xDrawPage->getByIndex(2), uno::UNO_QUERY); uno::Reference xShapeProps(xShape, uno::UNO_QUERY); CPPUNIT_ASSERT(xShapeProps->getPropertySetInfo()->hasPropertyByName(u"EdgeKind"_ustr)); - xShapeProps->getPropertyValue(UNO_NAME_EDGELINE1DELTA) >>= nEdgeLineDelta; - // Without the fix in place, this test would have failed with - // - Expected: -662 - // - Actual : 3370 - CPPUNIT_ASSERT_EQUAL(sal_Int32(-662), nEdgeLineDelta); + // This bentConnector3 is connected to a shape at its end only; its start is free and its adjust + // value stretches the elbow beyond the frame. Because it is not glued at both ends, its + // pre-authored path is kept as-is (imposed directly) rather than re-routed, and no EdgeLine + // deltas are used (tdf#154074). Previously it was approximated via EdgeLine1Delta (tdf#164623). + xShapeProps->getPropertyValue(UNO_NAME_EDGELINE1DELTA) >>= nEdgeLineDelta; + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nEdgeLineDelta); xShapeProps->getPropertyValue(UNO_NAME_EDGELINE2DELTA) >>= nEdgeLineDelta; CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nEdgeLineDelta); xShapeProps->getPropertyValue(UNO_NAME_EDGELINE3DELTA) >>= nEdgeLineDelta; CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nEdgeLineDelta); + + // The authored bentConnector3 draws a 2-corner elbow (4 points). Checking the point positions + // (not just the count) ensures the imposed path has the right direction: the pre-fix path also + // had 2 corners. The end point is the top gluepoint of the connected rectangle. + auto* pEdgeObj = dynamic_cast(SdrObject::getSdrObjectFromXShape(xShape)); + CPPUNIT_ASSERT(pEdgeObj); + const basegfx::B2DPolygon aPoly(pEdgeObj->GetEdgeTrackPath().getB2DPolygon(0)); + const std::vector aExpected{ + { 2754, 11161 }, { 2754, 5084 }, { 4192, 5084 }, { 4192, 5746 } + }; + CPPUNIT_ASSERT_EQUAL(static_cast(aExpected.size()), aPoly.count()); + for (size_t i = 0; i < aExpected.size(); ++i) + { + CPPUNIT_ASSERT_DOUBLES_EQUAL(aExpected[i].getX(), aPoly.getB2DPoint(i).getX(), 2.0); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aExpected[i].getY(), aPoly.getB2DPoint(i).getY(), 2.0); + } } CPPUNIT_TEST_FIXTURE(OoxShapeTest, testGroupTransform) diff --git a/oox/source/core/filterbase.cxx b/oox/source/core/filterbase.cxx index 5542b7de26fa..76538d670ecd 100644 --- a/oox/source/core/filterbase.cxx +++ b/oox/source/core/filterbase.cxx @@ -157,6 +157,8 @@ struct FilterBaseImpl bool mbExportTemplate; + bool mbExportSlideShow; + /// @throws RuntimeException explicit FilterBaseImpl( const Reference< XComponentContext >& rxContext ); @@ -169,7 +171,8 @@ FilterBaseImpl::FilterBaseImpl( const Reference< XComponentContext >& rxContext meVersion(ECMA_376_1ST_EDITION), mxComponentContext( rxContext, UNO_SET_THROW ), mbExportVBA(false), - mbExportTemplate(false) + mbExportTemplate(false), + mbExportSlideShow(false) { } @@ -436,6 +439,7 @@ void SAL_CALL FilterBase::initialize( const Sequence< Any >& rArgs ) sal_Int32 nFlags(0); rVal.Value >>= nFlags; mxImpl->mbExportTemplate = bool(static_cast(nFlags) & SfxFilterFlags::TEMPLATE); + mxImpl->mbExportSlideShow = bool(static_cast(nFlags) & SfxFilterFlags::STARTPRESENTATION); } } } @@ -590,6 +594,11 @@ bool FilterBase::isExportTemplate() const return mxImpl->mbExportTemplate; } +bool FilterBase::isExportSlideShow() const +{ + return mxImpl->mbExportSlideShow; +} + } // namespace oox::core /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx index 4db78e8472b1..efba14953cb0 100644 --- a/oox/source/core/xmlfilterbase.cxx +++ b/oox/source/core/xmlfilterbase.cxx @@ -161,6 +161,9 @@ const Sequence< beans::Pair< OUString, sal_Int32 > >& NamespaceIds() {u"http://schemas.microsoft.com/office/drawing/2016/SVG/main"_ustr, NMSP_asvg}, {u"http://schemas.microsoft.com/office/drawing/2014/chartex"_ustr, NMSP_cx}, {u"http://schemas.microsoft.com/office/drawing/2012/chartStyle"_ustr, NMSP_cs}, + {u"http://schemas.microsoft.com/office/spreadsheetml/2019/namedsheetviews"_ustr, NMSP_xnsv}, + {u"http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments"_ustr, NMSP_xthreaded}, + {u"http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray"_ustr, NMSP_xda}, }; return SINGLETON; }; @@ -223,7 +226,7 @@ XmlFilterBase::~XmlFilterBase() // their stuff (creating objects, setting attributes, ...) on being destroyed. // They get destroyed by setting a new DocumentHandler. This also happens in // the following implicit destruction chain of ~XmlFilterBaseImpl, but in that - // case it's member RelationsMap maRelationsMap will be destroyed, but maybe + // case its member RelationsMap maRelationsMap will be destroyed, but maybe // still be used by ~FragmentHandler -> crash. mxImpl->maFastParser.clearDocumentHandler(); } @@ -339,7 +342,7 @@ OUString getStrictRelationshipOfficeDocType(std::u16string_view rPart) OUString XmlFilterBase::getFragmentPathFromFirstTypeFromOfficeDoc( std::u16string_view rPart ) { - // importRelations() caches the relations map for subsequence calls + // importRelations() caches the relations map for subsequent calls const OUString aTransitionalRelationshipType = getTransitionalRelationshipOfficeDocType(rPart); OUString aFragment = importRelations( OUString() )->getFragmentPathFromFirstType( aTransitionalRelationshipType ); if(aFragment.isEmpty()) @@ -1180,7 +1183,7 @@ void XmlFilterBase::importCustomFragments(css::uno::Reference> aCustomXmlDomList; std::vector> aCustomXmlDomPropsList; - //FIXME: Ideally, we should get these the relations, but it seems that is not consistently set. + //FIXME: Ideally, we should get these from the relations, but it seems that is not consistently set. // In some cases it's stored in the workbook relationships, which is unexpected. So we discover them directly. for (int i = 1; ; ++i) { @@ -1211,7 +1214,7 @@ void XmlFilterBase::importCustomFragments(css::uno::Reference xModel = getModel(); uno::Reference xPropSet(xModel, uno::UNO_QUERY_THROW); @@ -1266,7 +1269,8 @@ void XmlFilterBase::exportCustomFragments() const OUString fragmentPath = "customXml/item" + OUString::number(j+1) + ".xml"; if (customXmlDom.is()) { - addRelation(oox::getRelationship(Relationship::CUSTOMXML), Concat2View("../" + fragmentPath)); + addRelation(pFS->getOutputStream(), oox::getRelationship(Relationship::CUSTOMXML), + Concat2View("../" + fragmentPath)); uno::Reference serializer(customXmlDom, uno::UNO_QUERY); uno::Reference writer = xml::sax::Writer::create(comphelper::getProcessComponentContext()); diff --git a/oox/source/crypto/AgileEngine.cxx b/oox/source/crypto/AgileEngine.cxx index 9599b492e5b9..51c4d37265dc 100644 --- a/oox/source/crypto/AgileEngine.cxx +++ b/oox/source/crypto/AgileEngine.cxx @@ -20,12 +20,12 @@ #include #include -#include #include #include #include #include +#include #include #include #include @@ -318,12 +318,13 @@ namespace bool generateBytes(std::vector & rBytes, sal_Int32 nSize) { + assert(0 <= nSize && o3tl::make_unsigned(nSize) <= rBytes.size()); + if (nSize <= 0) + return false; + size_t nMax = std::min(rBytes.size(), size_t(nSize)); - for (size_t i = 0; i < nMax; ++i) - { - rBytes[i] = sal_uInt8(comphelper::rng::uniform_uint_distribution(0, 0xFF)); - } + (void)rtl_random_getBytes(nullptr, rBytes.data(), nMax); return true; } @@ -730,9 +731,7 @@ bool AgileEngine::encryptEncryptionKey(std::u16string_view rPassword) bool AgileEngine::setupEncryption(OUString const & rPassword) { - if (meEncryptionPreset == AgileEncryptionPreset::AES_128_SHA1) - setupEncryptionParameters({ 100000, 16, 128, 20, 16, u"AES"_ustr, u"ChainingModeCBC"_ustr, u"SHA1"_ustr }); - else if (meEncryptionPreset == AgileEncryptionPreset::AES_128_SHA384) + if (meEncryptionPreset == AgileEncryptionPreset::AES_128_SHA384) setupEncryptionParameters({ 100000, 16, 128, 48, 16, u"AES"_ustr, u"ChainingModeCBC"_ustr, u"SHA384"_ustr }); else if (meEncryptionPreset == AgileEncryptionPreset::AES_192_SHA384) setupEncryptionParameters({ 100000, 16, 192, 48, 16, u"AES"_ustr, u"ChainingModeCBC"_ustr, u"SHA384"_ustr }); diff --git a/oox/source/crypto/DocumentEncryption.cxx b/oox/source/crypto/DocumentEncryption.cxx index dd0b4a3e42fb..caecde6f5435 100644 --- a/oox/source/crypto/DocumentEncryption.cxx +++ b/oox/source/crypto/DocumentEncryption.cxx @@ -73,7 +73,7 @@ bool DocumentEncryption::encrypt() if (!xSeekable.is()) return false; - xSeekable->seek(0); // seek to begin of the document stream + xSeekable->seek(0); // seek to the beginning of the document stream if (!mrOleStorage.isStorage()) return false; diff --git a/oox/source/crypto/StrongEncryptionDataSpace.cxx b/oox/source/crypto/StrongEncryptionDataSpace.cxx index 976b407fb7e9..929147263234 100644 --- a/oox/source/crypto/StrongEncryptionDataSpace.cxx +++ b/oox/source/crypto/StrongEncryptionDataSpace.cxx @@ -29,7 +29,7 @@ namespace oox::crypto { StrongEncryptionDataSpace::StrongEncryptionDataSpace(const Reference& rxContext) : mxContext(rxContext) - , mCryptoEngine(new Standard2007Engine) + , mCryptoEngine(new AgileEngine) { } diff --git a/oox/source/drawingml/chart/axiscontext.cxx b/oox/source/drawingml/chart/axiscontext.cxx index f34a41d926f4..2424281b33a3 100644 --- a/oox/source/drawingml/chart/axiscontext.cxx +++ b/oox/source/drawingml/chart/axiscontext.cxx @@ -33,6 +33,36 @@ namespace oox::drawingml::chart { using ::oox::core::ContextHandlerRef; using ::oox::core::ContextHandler2Helper; +namespace { + +// Variant of ShapePrWrapperContext that also records whether a cx:spPr +// child was actually encountered. Used to round-trip the distinction +// between (no formatting) and +// .... +class ChartexGridLinesContext final : public ContextBase +{ +public: + explicit ChartexGridLinesContext(ContextHandler2Helper& rParent, + Shape& rModel, bool& rHasSpPr) + : ContextBase(rParent, rModel), mrHasSpPr(rHasSpPr) {} + + virtual ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList&) override + { + if (isRootElement() && nElement == CX_TOKEN(spPr)) + { + mrHasSpPr = true; + return new ShapePropertiesContext(*this, mrModel); + } + return nullptr; + } + +private: + bool& mrHasSpPr; +}; + +} // anonymous namespace + AxisDispUnitsContext::AxisDispUnitsContext( ContextHandler2Helper& rParent, AxisDispUnitsModel& rModel ) : ContextBase< AxisDispUnitsModel >( rParent, rModel ) { @@ -126,7 +156,8 @@ ContextHandlerRef AxisContextBase::onCreateContext( sal_Int32 nElement, const At mrModel.mnMinorTickMark = rAttribs.getToken( XML_val, bMSO2007Doc ? XML_none : XML_cross ); return nullptr; case C_TOKEN( numFmt ): - mrModel.maNumberFormat.setAttributes( rAttribs ); + mrModel.maNumberFormat = NumberFormat(); + mrModel.maNumberFormat.value().setAttributes( rAttribs ); return nullptr; case C_TOKEN( scaling ): return this; @@ -309,23 +340,15 @@ ContextHandlerRef CxAxisContext::onCreateContext( sal_Int32 nElement, const Attr if( isRootElement() ) switch( nElement ) { case CX_TOKEN(catScaling) : - // TODO: figure out how to get gapWidth attribute to the right place + mrModel.mobCatNotVal = true; + mrModel.mofGapWidth = rAttribs.getDouble(XML_gapWidth); return nullptr; case CX_TOKEN(valScaling) : - if (rAttribs.hasAttribute(XML_max)) { - mrModel.mofMax = rAttribs.getDouble(XML_max); - } - if (rAttribs.hasAttribute(XML_min)) { - mrModel.mofMin = rAttribs.getDouble(XML_min); - } - /* TODO: need to implement AttributeList method - if (rAttribs.hasAttribute(XML_majorUnit)) { - mrModel.mofMajorUnit = rAttribs.getValAxisUnit(XML_majorUnit); - } - if (rAttribs.hasAttribute(XML_minorUnit)) { - mrModel.mofMinorUnit = rAttribs.getValAxisUnit(XML_minorUnit); - } - */ + mrModel.mobCatNotVal = false; + mrModel.mofMax = rAttribs.getDouble(XML_max); + mrModel.mofMin = rAttribs.getDouble(XML_min); + mrModel.mofMajorUnit = rAttribs.getDouble(XML_majorUnit); + mrModel.mofMinorUnit = rAttribs.getDouble(XML_minorUnit); return nullptr; case CX_TOKEN(title): { @@ -334,24 +357,35 @@ ContextHandlerRef CxAxisContext::onCreateContext( sal_Int32 nElement, const Attr return new TitleContext( *this, mrModel.mxTitle.create(nDefaultRotation) ); } case CX_TOKEN(units) : - // TODO + // Chartex flattens c:dispUnits/c:builtInUnit into a single + // cx:units element with a "unit" attribute. Map directly onto + // the AxisDispUnitsModel so the chart2 axis ends up with the + // matching DisplayUnits/BuiltInUnit properties via + // AxisDispUnitsConverter. + mrModel.mxDispUnits.create().mnBuiltInUnit + = rAttribs.getString(XML_unit, OUString()); return nullptr; case CX_TOKEN(majorGridlines): - return new ShapePrWrapperContext( *this, mrModel.mxMajorGridLines.create() ); + return new ChartexGridLinesContext( *this, + mrModel.mxMajorGridLines.create(), + mrModel.mbMajorGridLinesHasSpPr ); case CX_TOKEN(minorGridlines): - return new ShapePrWrapperContext( *this, mrModel.mxMinorGridLines.create() ); + return new ChartexGridLinesContext( *this, + mrModel.mxMinorGridLines.create(), + mrModel.mbMinorGridLinesHasSpPr ); case CX_TOKEN(majorTickMarks): - mrModel.mnMajorTickMark = rAttribs.getToken( XML_type, XML_cross ); + mrModel.mnMajorTickMark = rAttribs.getToken( XML_type, XML_none ); return nullptr; case CX_TOKEN(minorTickMarks): - mrModel.mnMinorTickMark = rAttribs.getToken( XML_type, XML_cross ); + mrModel.mnMinorTickMark = rAttribs.getToken( XML_type, XML_none ); return nullptr; case CX_TOKEN(tickLabels) : mrModel.mnTickLabelPos = XML_nextTo; // Is this the right default? // TODO (contents is only an extLst) return nullptr; case CX_TOKEN(numFmt): - mrModel.maNumberFormat.setAttributes( rAttribs ); + mrModel.maNumberFormat = NumberFormat(); + mrModel.maNumberFormat.value().setAttributes( rAttribs ); return nullptr; case CX_TOKEN(spPr): return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); diff --git a/oox/source/drawingml/chart/axisconverter.cxx b/oox/source/drawingml/chart/axisconverter.cxx index 8c65da8e88b0..5262f9028723 100644 --- a/oox/source/drawingml/chart/axisconverter.cxx +++ b/oox/source/drawingml/chart/axisconverter.cxx @@ -32,8 +32,13 @@ #include #include #include +#include #include #include +#include +#include +#include +#include #include #include #include @@ -109,7 +114,7 @@ sal_Int32 lclGetTickMark( sal_Int32 nToken ) } /** - * The groups is of percent type only when all of its members are of percent + * The group is of percent type only when all of its members are of percent * type. */ bool isPercent( const RefVector& rTypeGroups ) @@ -141,7 +146,8 @@ AxisConverter::~AxisConverter() void AxisConverter::convertFromModel(const Reference& rxCoordSystem, RefVector& rTypeGroups, const AxisModel* pCrossingAxis, sal_Int32 nAxesSetIdx, - sal_Int32 nAxisIdx, bool bUseFixedInnerSize) + sal_Int32 nAxisIdx, bool bUseFixedInnerSize, + ChartType eCT) { if (rTypeGroups.empty()) return; @@ -155,6 +161,55 @@ void AxisConverter::convertFromModel(const Reference& rxCoord const TypeGroupInfo& rTypeInfo = rTypeGroups.front()->getTypeInfo(); ObjectFormatter& rFormatter = getFormatter(); + Reference< ::com::sun::star::chart2::data::XLabeledDataSequence > xHistogramCategories; + if( nAxisIdx == API_X_AXIS && rTypeInfo.meTypeId == TYPEID_HISTO && rxCoordSystem.is() ) + { + try + { + Reference< XChartTypeContainer > xChartTypeContainer(rxCoordSystem, UNO_QUERY_THROW); + const Sequence< Reference< XChartType > > aChartTypes = xChartTypeContainer->getChartTypes(); + + if( aChartTypes.getLength() == 1 ) + { + Reference< XDataSeriesContainer > xSeriesContainer(aChartTypes[0], UNO_QUERY); + if( xSeriesContainer.is() ) + { + const Sequence< Reference< XDataSeries > > aSeries = xSeriesContainer->getDataSeries(); + if( aSeries.getLength() == 1 ) + { + Reference< data::XDataSource > xDataSource(aSeries[0], UNO_QUERY); + if( xDataSource.is() ) + { + const Sequence< Reference< data::XLabeledDataSequence > > aDataSeqs + = xDataSource->getDataSequences(); + + for( const auto& xSeq : aDataSeqs ) + { + if( !xSeq.is() || !xSeq->getValues().is() ) + continue; + + Reference< XPropertySet > xSeqProps(xSeq->getValues(), UNO_QUERY); + if( !xSeqProps.is() ) + continue; + + OUString aRole; + xSeqProps->getPropertyValue(u"Role"_ustr) >>= aRole; + if( aRole == "categories" ) + { + xHistogramCategories = xSeq; + break; + } + } + } + } + } + } + } + catch( const Exception& ) + { + } + } + // create the axis object (always) xAxis.set( createInstance( u"com.sun.star.chart2.Axis"_ustr ), UNO_QUERY_THROW ); PropertySet aAxisProp( xAxis ); @@ -166,6 +221,43 @@ void AxisConverter::convertFromModel(const Reference& rxCoord // show axis labels aAxisProp.setProperty( PROP_DisplayLabels, mrModel.mnTickLabelPos != XML_none ); aAxisProp.setProperty( PROP_LabelPosition, lclGetLabelPosition( mrModel.mnTickLabelPos ) ); + // Track whether the axis had explicit spPr/txPr (before radar override creates one) + if (mrModel.mxShapeProp.is()) + aAxisProp.setProperty(PROP_HasExplicitSpPr, true); + if (mrModel.mxTextProp.is()) + aAxisProp.setProperty(PROP_HasExplicitTxPr, true); + + // Chartex only: preserve the cx:axis id so export can re-emit it and + // so series-to-axis links can be reconstructed from the chart2 model. + if (eCT == ChartType::CX && mrModel.mnAxisId >= 0) { + aAxisProp.setProperty(PROP_AxisId, mrModel.mnAxisId); + if (mrModel.mobCatNotVal) { + aAxisProp.setProperty(PROP_CatNotVal, mrModel.mobCatNotVal.value()); + } + // Chartex only: preserve cx:valScaling attributes verbatim. The + // chart2 ScaleData round-trip loses these when the axis is the + // secondary value axis of a combined chart (e.g. paretoLine), + // because Auto* flags get re-derived from explicit increments. + if (mrModel.mofMin.has_value()) + aAxisProp.setProperty(PROP_ChartexValMin, mrModel.mofMin.value()); + if (mrModel.mofMax.has_value()) + aAxisProp.setProperty(PROP_ChartexValMax, mrModel.mofMax.value()); + if (mrModel.mofMajorUnit.has_value()) + aAxisProp.setProperty(PROP_ChartexMajorUnit, mrModel.mofMajorUnit.value()); + if (mrModel.mofMinorUnit.has_value()) + aAxisProp.setProperty(PROP_ChartexMinorUnit, mrModel.mofMinorUnit.value()); + + // Chartex only: preserve cx:units/@unit. AxisDispUnitsConverter + // still feeds BuiltInUnit/DisplayUnits, but those don't survive + // the trip to the secondary axis on some chart layouts. + if (mrModel.mxDispUnits.is() + && !mrModel.mxDispUnits->mnBuiltInUnit.isEmpty()) + { + aAxisProp.setProperty(PROP_ChartexUnit, + mrModel.mxDispUnits->mnBuiltInUnit); + } + } + // no X axis line in radar charts if( (nAxisIdx == API_X_AXIS) && (rTypeInfo.meTypeCategory == TYPECATEGORY_RADAR) ) mrModel.mxShapeProp.getOrCreate().getLineProperties().maLineFill.moFillType = XML_noFill; @@ -175,15 +267,28 @@ void AxisConverter::convertFromModel(const Reference& rxCoord ObjectFormatter::convertTextRotation( aAxisProp, mrModel.mxTextProp, true ); // tick mark style - aAxisProp.setProperty( PROP_MajorTickmarks, lclGetTickMark( mrModel.mnMajorTickMark ) ); - aAxisProp.setProperty( PROP_MinorTickmarks, lclGetTickMark( mrModel.mnMinorTickMark ) ); + sal_Int32 nTickStyle = lclGetTickMark( mrModel.mnMajorTickMark ); + if (nTickStyle != XML_none) { + aAxisProp.setProperty( PROP_MajorTickmarks, nTickStyle ); + }; + nTickStyle = lclGetTickMark( mrModel.mnMinorTickMark ); + if (nTickStyle != XML_none) { + aAxisProp.setProperty( PROP_MinorTickmarks, nTickStyle ); + }; + aAxisProp.setProperty( PROP_MarkPosition, cssc::ChartAxisMarkPosition_AT_AXIS ); // main grid PropertySet aGridProp( xAxis->getGridProperties() ); aGridProp.setProperty( PROP_Show, mrModel.mxMajorGridLines.is() ); if( mrModel.mxMajorGridLines.is() ) + { rFormatter.convertFrameFormatting( aGridProp, mrModel.mxMajorGridLines, OBJECTTYPE_MAJORGRIDLINE ); + // Chartex round-trip: remember whether the imported gridlines + // element carried an explicit cx:spPr child. + if (eCT == ChartType::CX && mrModel.mbMajorGridLinesHasSpPr) + aGridProp.setProperty(PROP_HasExplicitSpPr, true); + } // sub grid Sequence< Reference< XPropertySet > > aSubGridPropSeq = xAxis->getSubGridProperties(); @@ -192,7 +297,11 @@ void AxisConverter::convertFromModel(const Reference& rxCoord PropertySet aSubGridProp( aSubGridPropSeq[ 0 ] ); aSubGridProp.setProperty( PROP_Show, mrModel.mxMinorGridLines.is() ); if( mrModel.mxMinorGridLines.is() ) + { rFormatter.convertFrameFormatting( aSubGridProp, mrModel.mxMinorGridLines, OBJECTTYPE_MINORGRIDLINE ); + if (eCT == ChartType::CX && mrModel.mbMinorGridLinesHasSpPr) + aSubGridProp.setProperty(PROP_HasExplicitSpPr, true); + } } // axis type and X axis categories ------------------------------------ @@ -213,17 +322,25 @@ void AxisConverter::convertFromModel(const Reference& rxCoord /* TODO: create main category axis labels once, while InternalDataProvider can not handle different category names on the primary and secondary category axis. */ if( nAxesSetIdx == 0 ) - aScaleData.Categories = rTypeGroups.front()->createCategorySequence(); + { + // Histogram labels are generated bin ranges on the data series. Use those + // regenerated labels for the X axis instead of keeping stale axis categories + // or synthesizing generic "1", "2", ... labels. + if( rTypeInfo.meTypeId == TYPEID_HISTO && xHistogramCategories.is() ) + aScaleData.Categories = xHistogramCategories; + else + aScaleData.Categories = rTypeGroups.front()->createCategorySequence(); + } /* set default ShiftedCategoryPosition values for some charttype, because the XML can contain wrong CrossBetween value, if came from MSO */ - if( rTypeGroups.front()->is3dChart() && (rTypeInfo.meTypeId == TYPEID_BAR || rTypeInfo.meTypeId == TYPEID_HORBAR || rTypeInfo.meTypeId == TYPEID_STOCK) ) - aScaleData.ShiftedCategoryPosition = true; - else if( rTypeInfo.meTypeId == TYPEID_RADARLINE || rTypeInfo.meTypeId == TYPEID_RADARAREA ) + if( rTypeGroups.front()->is3dChart()) { + aScaleData.ShiftedCategoryPosition = rTypeInfo.mb3dShiftedCatPos; + } else if( rTypeInfo.meTypeId == TYPEID_RADARLINE || rTypeInfo.meTypeId == TYPEID_RADARAREA ) aScaleData.ShiftedCategoryPosition = false; else if( pCrossingAxis->mnCrossBetween != -1 ) /*because of backwards compatibility*/ aScaleData.ShiftedCategoryPosition = pCrossingAxis->mnCrossBetween == XML_between; - else if( rTypeInfo.meTypeCategory == TYPECATEGORY_BAR || rTypeInfo.meTypeId == TYPEID_LINE || rTypeInfo.meTypeId == TYPEID_STOCK ) - aScaleData.ShiftedCategoryPosition = true; + else + aScaleData.ShiftedCategoryPosition = rTypeInfo.mbShiftedCatPos; } else { @@ -330,7 +447,7 @@ void AxisConverter::convertFromModel(const Reference& rxCoord } else if( !mrModel.mofMinorUnit.has_value() ) { - // tdf#114168 If minor unit is not set then set interval to 5, as MS Excel do. + // tdf#114168 If minor unit is not set then set interval to 5, as MS Excel does. rIntervalCount <<= static_cast< sal_Int32 >( 5 ); } } @@ -359,7 +476,9 @@ void AxisConverter::convertFromModel(const Reference& rxCoord // number format ------------------------------------------------------ if( !mrModel.mbDeleted && aScaleData.AxisType != cssc2::AxisType::SERIES ) { - getFormatter().convertNumberFormat(aAxisProp, mrModel.maNumberFormat, true); + if (mrModel.maNumberFormat) { + getFormatter().convertNumberFormat(aAxisProp, mrModel.maNumberFormat.value(), true); + } } // position of crossing axis ------------------------------------------ @@ -391,7 +510,7 @@ void AxisConverter::convertFromModel(const Reference& rxCoord && (mrModel.mnAxisPos == XML_l || mrModel.mnAxisPos == XML_r)) mrModel.mxTitle->mnDefaultRotation = 0; TitleConverter aTitleConv( *this, *mrModel.mxTitle ); - aTitleConv.convertFromModel( xTitled, OoxResId(STR_DIAGRAM_AXISTITLE), OBJECTTYPE_AXISTITLE, nAxesSetIdx, nAxisIdx ); + aTitleConv.convertFromModel( xTitled, OoxResId(STR_DIAGRAM_AXISTITLE), OBJECTTYPE_AXISTITLE, eCT, nAxesSetIdx, nAxisIdx ); } // axis data unit label ----------------------------------------------- @@ -411,6 +530,28 @@ void AxisConverter::convertFromModel(const Reference& rxCoord { OSL_FAIL( "AxisConverter::convertFromModel - cannot insert axis into coordinate system" ); } + + // chartex catScaling gapWidth: set on all chart types' GapwidthSequence + if( mrModel.mofGapWidth.has_value() && rxCoordSystem.is() ) + { + try + { + Reference< XChartTypeContainer > xCTCnt( rxCoordSystem, UNO_QUERY ); + if( xCTCnt.is() ) + { + sal_Int32 nGapWidth = static_cast< sal_Int32 >( mrModel.mofGapWidth.value() * 100.0 + 0.5 ); + Sequence< sal_Int32 > aGapSeq{ nGapWidth, nGapWidth }; + for( const com::sun::star::uno::Reference & rChartType : xCTCnt->getChartTypes() ) + { + PropertySet aTypeProp( rChartType ); + aTypeProp.setProperty( PROP_GapwidthSequence, aGapSeq ); + } + } + } + catch( Exception& ) + { + } + } } AxisDispUnitsConverter::AxisDispUnitsConverter( const ConverterRoot& rParent, AxisDispUnitsModel& rModel ) : diff --git a/oox/source/drawingml/chart/axismodel.cxx b/oox/source/drawingml/chart/axismodel.cxx index 0159810dfc1f..14241c48266b 100644 --- a/oox/source/drawingml/chart/axismodel.cxx +++ b/oox/source/drawingml/chart/axismodel.cxx @@ -31,7 +31,7 @@ AxisDispUnitsModel::~AxisDispUnitsModel() { } -AxisModel::AxisModel( sal_Int32 nTypeId, bool bMSO2007Doc ) : +AxisModel::AxisModel( sal_Int32 nTypeId, enum ChartType eCT) : mnAxisId( -1 ), mnAxisPos( XML_TOKEN_INVALID ), mnCrossAxisId( -1 ), @@ -39,9 +39,13 @@ AxisModel::AxisModel( sal_Int32 nTypeId, bool bMSO2007Doc ) : mnCrossMode( XML_autoZero ), mnLabelAlign( XML_ctr ), mnLabelOffset( 100 ), - mnMajorTickMark( bMSO2007Doc ? XML_out : XML_cross ), + mnMajorTickMark( eCT == ChartType::C_2007 ? XML_out : + eCT == ChartType::C_OTHER ? XML_cross : + XML_none), mnMajorTimeUnit( XML_days ), - mnMinorTickMark( bMSO2007Doc ? XML_none : XML_cross ), + mnMinorTickMark( eCT == ChartType::C_2007 ? XML_out : + eCT == ChartType::C_OTHER ? XML_cross : + XML_none), mnMinorTimeUnit( XML_days ), mnOrientation( XML_minMax ), mnTickLabelPos( XML_nextTo ), @@ -50,7 +54,9 @@ AxisModel::AxisModel( sal_Int32 nTypeId, bool bMSO2007Doc ) : mnTypeId( nTypeId ), mbAuto( false ), mbDeleted( false ), - mbNoMultiLevel( false ) + mbNoMultiLevel( false ), + mbMajorGridLinesHasSpPr( false ), + mbMinorGridLinesHasSpPr( false ) { } diff --git a/oox/source/drawingml/chart/chartspaceconverter.cxx b/oox/source/drawingml/chart/chartspaceconverter.cxx index 1161a5b5898c..c4ec6427344b 100644 --- a/oox/source/drawingml/chart/chartspaceconverter.cxx +++ b/oox/source/drawingml/chart/chartspaceconverter.cxx @@ -151,10 +151,16 @@ void ChartSpaceConverter::convertFromModel( const Reference< XShapes >& rxExtern derived converters may create an external data provider) */ getChartConverter().createDataProvider( getChartDocument() ); + const ChartType eCT = mrModel.mxPlotArea.is() + ? mrModel.mxPlotArea->meCT : ChartType::C_OTHER; + // formatting of the chart background. The default fill style varies with applications. PropertySet aBackPropSet( getChartDocument()->getPageBackground() ); getFormatter().convertFrameFormatting( aBackPropSet, mrModel.mxShapeProp, OBJECTTYPE_CHARTSPACE ); + if (mrModel.mxPlotArea.is() && mrModel.mxShapeProp.is()) + aBackPropSet.setProperty(PROP_HasExplicitSpPr, true); + bool bMSO2007Doc = getFilter().isMSO2007Document(); // convert plot area (container of all chart type groups) PlotAreaConverter aPlotAreaConv( *this, mrModel.mxPlotArea.getOrCreate() ); @@ -201,7 +207,7 @@ void ChartSpaceConverter::convertFromModel( const Reference< XShapes >& rxExtern aAutoTitle = OoxResId(STR_DIAGRAM_TITLE); Reference< XTitled > xTitled( getChartDocument(), UNO_QUERY_THROW ); TitleConverter aTitleConv( *this, mrModel.mxTitle.getOrCreate() ); - aTitleConv.convertFromModel( xTitled, aAutoTitle, OBJECTTYPE_CHARTTITLE ); + aTitleConv.convertFromModel( xTitled, aAutoTitle, OBJECTTYPE_CHARTTITLE, eCT ); } } catch( Exception& ) @@ -212,7 +218,7 @@ void ChartSpaceConverter::convertFromModel( const Reference< XShapes >& rxExtern if( xDiagram.is() && mrModel.mxLegend.is() ) { LegendConverter aLegendConv( *this, *mrModel.mxLegend ); - aLegendConv.convertFromModel( xDiagram ); + aLegendConv.convertFromModel( xDiagram, eCT ); } // treatment of missing values @@ -312,23 +318,23 @@ void ChartSpaceConverter::convertFromModel( const Reference< XShapes >& rxExtern if ( mrModel.mbPivotChart ) { PropertySet aProps( getChartDocument() ); - aProps.setProperty( PROP_DisableDataTableDialog , true ); - aProps.setProperty( PROP_DisableComplexChartTypes , true ); + aProps.setProperty( PROP_DisableDataTableDialog, true ); + aProps.setProperty( PROP_DisableComplexChartTypes, true ); } - if(!mrModel.maSheetPath.isEmpty() ) + if (!mrModel.maSheetPath.isEmpty()) { Reference< css::chart::XChartDocument > xChartDoc( getChartDocument(), UNO_QUERY ); PropertySet aProps( xChartDoc->getDiagram() ); - aProps.setProperty( PROP_ExternalData , uno::Any(mrModel.maSheetPath) ); + aProps.setProperty( PROP_ExternalData, uno::Any(mrModel.maSheetPath) ); } if (mrModel.mbDate1904) { - util::DateTime aNullDate(0,0,0,0,1,1,1904, false); + util::DateTime aNullDate(0, 0, 0, 0, 1, 1, 1904, false); Any aAny; aAny <<= aNullDate; Reference< css::chart::XChartDocument > xChartDoc( getChartDocument(), UNO_QUERY ); - Reference< beans::XPropertySet > xDocPropSet(xChartDoc, UNO_QUERY ); + Reference< beans::XPropertySet > xDocPropSet(xChartDoc, UNO_QUERY); xDocPropSet->setPropertyValue(u"NullDate"_ustr, aAny); } } diff --git a/oox/source/drawingml/chart/datasourcecontext.cxx b/oox/source/drawingml/chart/datasourcecontext.cxx index 2532b6ad866d..4e1368a3f4f3 100644 --- a/oox/source/drawingml/chart/datasourcecontext.cxx +++ b/oox/source/drawingml/chart/datasourcecontext.cxx @@ -85,6 +85,7 @@ ContextHandlerRef DoubleSequenceContext::onCreateContext( sal_Int32 nElement, co case CX_TOKEN(numDim) : switch (nElement) { case CX_TOKEN(f): + case CX_TOKEN(nf): return this; case CX_TOKEN(lvl): mrModel.mnPointCount = rAttribs.getInteger(XML_ptCount, -1); @@ -111,6 +112,9 @@ void DoubleSequenceContext::onCharacters( const OUString& rChars ) case CX_TOKEN( f ): mrModel.maFormula = rChars; break; + case CX_TOKEN( nf ): + mrModel.maNFormula = rChars; + break; case C_TOKEN( formatCode ): mrModel.maFormatCode = rChars; break; @@ -284,6 +288,7 @@ ContextHandlerRef StringSequenceContext::onCreateContext( sal_Int32 nElement, co case CX_TOKEN(strDim) : switch (nElement) { case CX_TOKEN(f): + case CX_TOKEN(nf): return this; case CX_TOKEN(lvl): mrModel.mnPointCount = rAttribs.getInteger(XML_ptCount, -1); @@ -301,6 +306,9 @@ void StringSequenceContext::onCharacters( const OUString& rChars ) case CX_TOKEN( f ): mrModel.maFormula = rChars; break; + case CX_TOKEN( nf ): + mrModel.maNFormula = rChars; + break; case C15_TOKEN( f ): if (mbReadC15) mrModel.maFormula = rChars; @@ -398,33 +406,20 @@ ContextHandlerRef DataSourceCxContext::onCreateContext(sal_Int32 nElement, const { assert(paCurSource); OUString sType = rAttribs.getString(XML_type, "val"); - if (sType == "cat") { - DataSourceModel& rDataModel = paCurSource->create(DataSourceType::CATEGORIES); - return new DoubleSequenceContext(*this, - rDataModel.mxDataSeq.create()); - } else { - // default is VALUES - DataSourceModel& rDataModel = paCurSource->create(DataSourceType::VALUES); - return new DoubleSequenceContext(*this, - rDataModel.mxDataSeq.create()); - } - break; + DataSourceType eDimType = dataSourceTypeFromCx(true, sType); + DataSourceModel& rDataModel = paCurSource->create(eDimType); + return new DoubleSequenceContext(*this, + rDataModel.mxDataSeq.create()); } case CX_TOKEN(strDim) : { assert(paCurSource); OUString sType = rAttribs.getString(XML_type, "cat"); - if (sType == "val") { - DataSourceModel& rDataModel = paCurSource->create(DataSourceType::VALUES); - return new StringSequenceContext(*this, - rDataModel.mxDataSeq.create()); - } else { - // default is CATEGORIES - DataSourceModel& rDataModel = paCurSource->create(DataSourceType::CATEGORIES); - return new StringSequenceContext(*this, - rDataModel.mxDataSeq.create()); - } + DataSourceType eDimType = dataSourceTypeFromCx(false, sType); + DataSourceModel& rDataModel = paCurSource->create(eDimType); + return new StringSequenceContext(*this, + rDataModel.mxDataSeq.create()); } } break; diff --git a/oox/source/drawingml/chart/datasourceconverter.cxx b/oox/source/drawingml/chart/datasourceconverter.cxx index 4598572b4723..ba325e760adb 100644 --- a/oox/source/drawingml/chart/datasourceconverter.cxx +++ b/oox/source/drawingml/chart/datasourceconverter.cxx @@ -39,7 +39,8 @@ DataSequenceConverter::~DataSequenceConverter() { } -Reference< XDataSequence > DataSequenceConverter::createDataSequence( const OUString& rRole ) +Reference< XDataSequence > DataSequenceConverter::createDataSequence( + const OUString& rRole, DataSourceType eDimType ) { // create data sequence from data source model (virtual call at chart converter) Reference< XDataSequence > xDataSeq; @@ -83,6 +84,14 @@ Reference< XDataSequence > DataSequenceConverter::createDataSequence( const OUSt if (nKey >= 0) aSeqProp.setProperty(PROP_NumberFormatKey, nKey); + // store chartex dimension info for round-trip export + if (eDimType != DataSourceType::UNKNOWN) + aSeqProp.setProperty(PROP_ChartExDimType, static_cast(eDimType)); + if (!mrModel.maFormula.isEmpty()) + aSeqProp.setProperty(PROP_ChartExFormula, mrModel.maFormula); + if (!mrModel.maNFormula.isEmpty()) + aSeqProp.setProperty(PROP_ChartExNFormula, mrModel.maNFormula); + return xDataSeq; } @@ -95,13 +104,14 @@ DataSourceConverter::~DataSourceConverter() { } -Reference< XDataSequence > DataSourceConverter::createDataSequence( const OUString& rRole ) +Reference< XDataSequence > DataSourceConverter::createDataSequence( + const OUString& rRole, DataSourceType eDimType ) { Reference< XDataSequence > xDataSeq; if( mrModel.mxDataSeq.is() ) { DataSequenceConverter aDataSeqConv( *this, *mrModel.mxDataSeq ); - xDataSeq = aDataSeqConv.createDataSequence( rRole ); + xDataSeq = aDataSeqConv.createDataSequence( rRole, eDimType ); } return xDataSeq; } diff --git a/oox/source/drawingml/chart/datasourcemodel.cxx b/oox/source/drawingml/chart/datasourcemodel.cxx index 51514437d33d..c7bca4d5f75f 100644 --- a/oox/source/drawingml/chart/datasourcemodel.cxx +++ b/oox/source/drawingml/chart/datasourcemodel.cxx @@ -18,6 +18,7 @@ */ #include +#include #include namespace oox::drawingml::chart { @@ -41,6 +42,42 @@ DataSourceModel::~DataSourceModel() { } +DataSourceType dataSourceTypeFromCx(bool bNumeric, std::u16string_view rType) +{ + if (bNumeric) + { + if (rType == u"val") return DataSourceType::NUM_VAL; + if (rType == u"x") return DataSourceType::NUM_X; + if (rType == u"y") return DataSourceType::NUM_Y; + if (rType == u"size") return DataSourceType::NUM_SIZE; + if (rType == u"colorVal") return DataSourceType::NUM_COLORVAL; + return DataSourceType::NUM_VAL; // default for numDim + } + else + { + if (rType == u"cat") return DataSourceType::STR_CAT; + if (rType == u"colorStr") return DataSourceType::STR_COLORSTR; + if (rType == u"entityId") return DataSourceType::STR_ENTITYID; + return DataSourceType::STR_CAT; // default for strDim + } +} + +bool dataSourceTypeToCx(DataSourceType eType, bool& rbNumeric, OUString& rsType) +{ + switch (eType) + { + case DataSourceType::STR_CAT: rbNumeric = false; rsType = "cat"; return true; + case DataSourceType::STR_COLORSTR: rbNumeric = false; rsType = "colorStr"; return true; + case DataSourceType::STR_ENTITYID: rbNumeric = false; rsType = "entityId"; return true; + case DataSourceType::NUM_VAL: rbNumeric = true; rsType = "val"; return true; + case DataSourceType::NUM_X: rbNumeric = true; rsType = "x"; return true; + case DataSourceType::NUM_Y: rbNumeric = true; rsType = "y"; return true; + case DataSourceType::NUM_SIZE: rbNumeric = true; rsType = "size"; return true; + case DataSourceType::NUM_COLORVAL: rbNumeric = true; rsType = "colorVal"; return true; + default: return false; + } +} + } // namespace oox::drawingml::chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/chart/geographycontext.cxx b/oox/source/drawingml/chart/geographycontext.cxx new file mode 100644 index 000000000000..896bf72b1759 --- /dev/null +++ b/oox/source/drawingml/chart/geographycontext.cxx @@ -0,0 +1,323 @@ +/* -*- 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 +#include +#include +#include +#include + +namespace oox::drawingml::chart +{ +using ::oox::core::ContextHandlerRef; + +GeographyContext::GeographyContext(::oox::core::ContextHandler2Helper& rParent, + GeographyModel& rModel) + : ContextHandler2(rParent) + , mrModel(rModel) +{ +} + +// Handle the CT_Geography complex type in the chartex schema +ContextHandlerRef GeographyContext::onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) +{ + switch (getCurrentElement()) + { + case CX_TOKEN(geography): + switch (nElement) + { + case CX_TOKEN(geoCache): + mrModel.mxGeoCache.emplace(); + mrModel.mxGeoCache->mosProvider = rAttribs.getString(XML_provider); + return this; + } + break; + + case CX_TOKEN(geoCache): + switch (nElement) + { + case CX_TOKEN(binary): + return this; + case CX_TOKEN(clear): + mrModel.mxGeoCache->mxClear.emplace(); + return this; + } + break; + + case CX_TOKEN(clear): + switch (nElement) + { + case CX_TOKEN(geoLocationQueryResults): + case CX_TOKEN(geoDataEntityQueryResults): + case CX_TOKEN(geoDataPointToEntityQueryResults): + case CX_TOKEN(geoChildEntitiesQueryResults): + case CX_TOKEN(geoParentEntitiesQueryResults): + return this; + } + break; + + case CX_TOKEN(geoLocationQueryResults): + if (nElement == CX_TOKEN(geoLocationQueryResult)) + { + auto& rClear = *mrModel.mxGeoCache->mxClear; + rClear.maLocResults.emplace_back(); + mpCurLocResult = &rClear.maLocResults.back(); + return this; + } + break; + + case CX_TOKEN(geoLocationQueryResult): + switch (nElement) + { + case CX_TOKEN(geoLocationQuery): + { + mpCurLocResult->mxQuery.emplace(); + auto& q = *mpCurLocResult->mxQuery; + q.mosCountryRegion = rAttribs.getString(XML_countryRegion); + q.mosAdminDistrict1 = rAttribs.getString(XML_adminDistrict1); + q.mosAdminDistrict2 = rAttribs.getString(XML_adminDistrict2); + q.mosPostalCode = rAttribs.getString(XML_postalCode); + q.mosEntityType = rAttribs.getString(XML_entityType); + return nullptr; + } + case CX_TOKEN(geoLocations): + return this; + } + break; + + case CX_TOKEN(geoLocations): + if (nElement == CX_TOKEN(geoLocation)) + { + mpCurLocResult->maLocations.emplace_back(); + auto& loc = mpCurLocResult->maLocations.back(); + loc.mosLatitude = rAttribs.getString(XML_latitude); + loc.mosLongitude = rAttribs.getString(XML_longitude); + loc.mosEntityName = rAttribs.getString(XML_entityName); + loc.mosEntityType = rAttribs.getString(XML_entityType); + return this; + } + break; + + case CX_TOKEN(geoLocation): + if (nElement == CX_TOKEN(address)) + { + auto& loc = mpCurLocResult->maLocations.back(); + loc.mxAddress.emplace(); + auto& a = *loc.mxAddress; + a.mosAddress1 = rAttribs.getString(XML_address1); + a.mosCountryRegion = rAttribs.getString(XML_countryRegion); + a.mosAdminDistrict1 = rAttribs.getString(XML_adminDistrict1); + a.mosAdminDistrict2 = rAttribs.getString(XML_adminDistrict2); + a.mosPostalCode = rAttribs.getString(XML_postalCode); + a.mosLocality = rAttribs.getString(XML_locality); + a.mosIsoCountryCode = rAttribs.getString(XML_isoCountryCode); + return nullptr; + } + break; + + case CX_TOKEN(geoDataEntityQueryResults): + if (nElement == CX_TOKEN(geoDataEntityQueryResult)) + { + auto& rClear = *mrModel.mxGeoCache->mxClear; + rClear.maDataResults.emplace_back(); + mpCurDataResult = &rClear.maDataResults.back(); + return this; + } + break; + + case CX_TOKEN(geoDataEntityQueryResult): + switch (nElement) + { + case CX_TOKEN(geoDataEntityQuery): + { + mpCurDataResult->mxQuery.emplace(); + auto& q = *mpCurDataResult->mxQuery; + q.mosEntityType = rAttribs.getString(XML_entityType); + q.mosEntityId = rAttribs.getString(XML_entityId); + return nullptr; + } + case CX_TOKEN(geoData): + { + mpCurDataResult->mxData.emplace(); + auto& d = *mpCurDataResult->mxData; + d.mosEntityName = rAttribs.getString(XML_entityName); + d.mosEntityId = rAttribs.getString(XML_entityId); + d.mosEast = rAttribs.getString(XML_east); + d.mosWest = rAttribs.getString(XML_west); + d.mosNorth = rAttribs.getString(XML_north); + d.mosSouth = rAttribs.getString(XML_south); + return this; + } + } + break; + + case CX_TOKEN(geoData): + switch (nElement) + { + case CX_TOKEN(geoPolygons): + return this; + case CX_TOKEN(copyrights): + return this; + } + break; + + case CX_TOKEN(geoPolygons): + if (nElement == CX_TOKEN(geoPolygon)) + { + auto& d = *mpCurDataResult->mxData; + d.maPolygons.emplace_back(); + auto& p = d.maPolygons.back(); + p.mosPolygonId = rAttribs.getString(XML_polygonId); + p.mosNumPoints = rAttribs.getString(XML_numPoints); + p.mosPcaRings = rAttribs.getString(XML_pcaRings); + return nullptr; + } + break; + + case CX_TOKEN(copyrights): + if (nElement == CX_TOKEN(copyright)) + return this; + break; + + case CX_TOKEN(geoDataPointToEntityQueryResults): + if (nElement == CX_TOKEN(geoDataPointToEntityQueryResult)) + { + auto& rClear = *mrModel.mxGeoCache->mxClear; + rClear.maPtResults.emplace_back(); + mpCurPtResult = &rClear.maPtResults.back(); + return this; + } + break; + + case CX_TOKEN(geoDataPointToEntityQueryResult): + switch (nElement) + { + case CX_TOKEN(geoDataPointQuery): + { + mpCurPtResult->mxPointQuery.emplace(); + auto& q = *mpCurPtResult->mxPointQuery; + q.mosEntityType = rAttribs.getString(XML_entityType); + q.mosLatitude = rAttribs.getString(XML_latitude); + q.mosLongitude = rAttribs.getString(XML_longitude); + return nullptr; + } + case CX_TOKEN(geoDataPointToEntityQuery): + { + mpCurPtResult->mxEntityQuery.emplace(); + auto& q = *mpCurPtResult->mxEntityQuery; + q.mosEntityType = rAttribs.getString(XML_entityType); + q.mosEntityId = rAttribs.getString(XML_entityId); + return nullptr; + } + } + break; + + case CX_TOKEN(geoChildEntitiesQueryResults): + if (nElement == CX_TOKEN(geoChildEntitiesQueryResult)) + { + auto& rClear = *mrModel.mxGeoCache->mxClear; + rClear.maChildResults.emplace_back(); + mpCurChildResult = &rClear.maChildResults.back(); + return this; + } + break; + + case CX_TOKEN(geoChildEntitiesQueryResult): + switch (nElement) + { + case CX_TOKEN(geoChildEntitiesQuery): + { + mpCurChildResult->mxQuery.emplace(); + mpCurChildResult->mxQuery->mosEntityId = rAttribs.getString(XML_entityId); + return this; + } + case CX_TOKEN(geoChildEntities): + return this; + } + break; + + case CX_TOKEN(geoChildEntitiesQuery): + if (nElement == CX_TOKEN(geoChildTypes)) + return this; + break; + + case CX_TOKEN(geoChildTypes): + if (nElement == CX_TOKEN(entityType)) + return this; + break; + + case CX_TOKEN(geoChildEntities): + if (nElement == CX_TOKEN(geoHierarchyEntity)) + { + mpCurChildResult->maEntities.emplace_back(); + auto& e = mpCurChildResult->maEntities.back(); + e.mosEntityName = rAttribs.getString(XML_entityName); + e.mosEntityId = rAttribs.getString(XML_entityId); + e.mosEntityType = rAttribs.getString(XML_entityType); + return nullptr; + } + break; + + case CX_TOKEN(geoParentEntitiesQueryResults): + if (nElement == CX_TOKEN(geoParentEntitiesQueryResult)) + { + auto& rClear = *mrModel.mxGeoCache->mxClear; + rClear.maParentResults.emplace_back(); + mpCurParentResult = &rClear.maParentResults.back(); + return this; + } + break; + + case CX_TOKEN(geoParentEntitiesQueryResult): + switch (nElement) + { + case CX_TOKEN(geoParentEntitiesQuery): + mpCurParentResult->mxQuery.emplace(); + mpCurParentResult->mxQuery->mosEntityId = rAttribs.getString(XML_entityId); + return nullptr; + case CX_TOKEN(geoEntity): + mpCurParentResult->mxEntity.emplace(); + mpCurParentResult->mxEntity->mosEntityName = rAttribs.getString(XML_entityName); + mpCurParentResult->mxEntity->mosEntityType = rAttribs.getString(XML_entityType); + return nullptr; + case CX_TOKEN(geoParentEntity): + mpCurParentResult->mxParentEntity.emplace(); + mpCurParentResult->mxParentEntity->mosEntityId + = rAttribs.getString(XML_entityId); + return nullptr; + } + break; + } + return nullptr; +} + +// Handle character data +void GeographyContext::onCharacters(const OUString& rChars) +{ + switch (getCurrentElement()) + { + case CX_TOKEN(binary): + if (mrModel.mxGeoCache.has_value()) + mrModel.mxGeoCache->mosBinary = rChars; + break; + case CX_TOKEN(copyright): + if (mpCurDataResult && mpCurDataResult->mxData.has_value()) + mpCurDataResult->mxData->maCopyrights.push_back({ rChars }); + break; + case CX_TOKEN(entityType): + if (mpCurChildResult && mpCurChildResult->mxQuery.has_value()) + mpCurChildResult->mxQuery->maEntityTypes.push_back(rChars); + break; + } +} + +} // namespace oox::drawingml::chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/chart/geographyconverter.cxx b/oox/source/drawingml/chart/geographyconverter.cxx new file mode 100644 index 000000000000..9abfa059eaf8 --- /dev/null +++ b/oox/source/drawingml/chart/geographyconverter.cxx @@ -0,0 +1,792 @@ +/* -*- 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 +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace oox::drawingml::chart +{ +namespace +{ +uno::Sequence addressToProps(const GeoAddressModel& rAddr) +{ + std::vector aVec; + if (rAddr.mosAddress1.has_value()) + aVec.push_back({ u"address1"_ustr, 0, uno::Any(*rAddr.mosAddress1), + beans::PropertyState_DIRECT_VALUE }); + if (rAddr.mosCountryRegion.has_value()) + aVec.push_back({ u"countryRegion"_ustr, 0, uno::Any(*rAddr.mosCountryRegion), + beans::PropertyState_DIRECT_VALUE }); + if (rAddr.mosAdminDistrict1.has_value()) + aVec.push_back({ u"adminDistrict1"_ustr, 0, uno::Any(*rAddr.mosAdminDistrict1), + beans::PropertyState_DIRECT_VALUE }); + if (rAddr.mosAdminDistrict2.has_value()) + aVec.push_back({ u"adminDistrict2"_ustr, 0, uno::Any(*rAddr.mosAdminDistrict2), + beans::PropertyState_DIRECT_VALUE }); + if (rAddr.mosPostalCode.has_value()) + aVec.push_back({ u"postalCode"_ustr, 0, uno::Any(*rAddr.mosPostalCode), + beans::PropertyState_DIRECT_VALUE }); + if (rAddr.mosLocality.has_value()) + aVec.push_back({ u"locality"_ustr, 0, uno::Any(*rAddr.mosLocality), + beans::PropertyState_DIRECT_VALUE }); + if (rAddr.mosIsoCountryCode.has_value()) + aVec.push_back({ u"isoCountryCode"_ustr, 0, uno::Any(*rAddr.mosIsoCountryCode), + beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoAddressModel addressFromProps(const uno::Sequence& rProps) +{ + GeoAddressModel aAddr; + for (const auto& rProp : rProps) + { + OUString sVal; + if (!(rProp.Value >>= sVal)) + continue; + if (rProp.Name == "address1") + aAddr.mosAddress1 = sVal; + else if (rProp.Name == "countryRegion") + aAddr.mosCountryRegion = sVal; + else if (rProp.Name == "adminDistrict1") + aAddr.mosAdminDistrict1 = sVal; + else if (rProp.Name == "adminDistrict2") + aAddr.mosAdminDistrict2 = sVal; + else if (rProp.Name == "postalCode") + aAddr.mosPostalCode = sVal; + else if (rProp.Name == "locality") + aAddr.mosLocality = sVal; + else if (rProp.Name == "isoCountryCode") + aAddr.mosIsoCountryCode = sVal; + } + return aAddr; +} + +uno::Sequence locationToProps(const GeoLocationModel& rLoc) +{ + std::vector aVec; + if (rLoc.mosLatitude.has_value()) + aVec.push_back({ u"latitude"_ustr, 0, uno::Any(*rLoc.mosLatitude), + beans::PropertyState_DIRECT_VALUE }); + if (rLoc.mosLongitude.has_value()) + aVec.push_back({ u"longitude"_ustr, 0, uno::Any(*rLoc.mosLongitude), + beans::PropertyState_DIRECT_VALUE }); + if (rLoc.mosEntityName.has_value()) + aVec.push_back({ u"entityName"_ustr, 0, uno::Any(*rLoc.mosEntityName), + beans::PropertyState_DIRECT_VALUE }); + if (rLoc.mosEntityType.has_value()) + aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rLoc.mosEntityType), + beans::PropertyState_DIRECT_VALUE }); + if (rLoc.mxAddress.has_value()) + aVec.push_back({ u"address"_ustr, 0, uno::Any(addressToProps(*rLoc.mxAddress)), + beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoLocationModel locationFromProps(const uno::Sequence& rProps) +{ + GeoLocationModel aLoc; + for (const auto& rProp : rProps) + { + if (rProp.Name == "latitude") + { + OUString s; + if (rProp.Value >>= s) + aLoc.mosLatitude = s; + } + else if (rProp.Name == "longitude") + { + OUString s; + if (rProp.Value >>= s) + aLoc.mosLongitude = s; + } + else if (rProp.Name == "entityName") + { + OUString s; + if (rProp.Value >>= s) + aLoc.mosEntityName = s; + } + else if (rProp.Name == "entityType") + { + OUString s; + if (rProp.Value >>= s) + aLoc.mosEntityType = s; + } + else if (rProp.Name == "address") + { + uno::Sequence aInner; + if (rProp.Value >>= aInner) + aLoc.mxAddress = addressFromProps(aInner); + } + } + return aLoc; +} + +uno::Sequence locQueryToProps(const GeoLocationQueryModel& rQ) +{ + std::vector aVec; + if (rQ.mosCountryRegion.has_value()) + aVec.push_back({ u"countryRegion"_ustr, 0, uno::Any(*rQ.mosCountryRegion), + beans::PropertyState_DIRECT_VALUE }); + if (rQ.mosAdminDistrict1.has_value()) + aVec.push_back({ u"adminDistrict1"_ustr, 0, uno::Any(*rQ.mosAdminDistrict1), + beans::PropertyState_DIRECT_VALUE }); + if (rQ.mosAdminDistrict2.has_value()) + aVec.push_back({ u"adminDistrict2"_ustr, 0, uno::Any(*rQ.mosAdminDistrict2), + beans::PropertyState_DIRECT_VALUE }); + if (rQ.mosPostalCode.has_value()) + aVec.push_back({ u"postalCode"_ustr, 0, uno::Any(*rQ.mosPostalCode), + beans::PropertyState_DIRECT_VALUE }); + if (rQ.mosEntityType.has_value()) + aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rQ.mosEntityType), + beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoLocationQueryModel locQueryFromProps(const uno::Sequence& rProps) +{ + GeoLocationQueryModel aQ; + for (const auto& rProp : rProps) + { + OUString s; + if (!(rProp.Value >>= s)) + continue; + if (rProp.Name == "countryRegion") + aQ.mosCountryRegion = s; + else if (rProp.Name == "adminDistrict1") + aQ.mosAdminDistrict1 = s; + else if (rProp.Name == "adminDistrict2") + aQ.mosAdminDistrict2 = s; + else if (rProp.Name == "postalCode") + aQ.mosPostalCode = s; + else if (rProp.Name == "entityType") + aQ.mosEntityType = s; + } + return aQ; +} + +uno::Sequence locResultToProps(const GeoLocationQueryResultModel& rR) +{ + std::vector aVec; + if (rR.mxQuery.has_value()) + aVec.push_back({ u"query"_ustr, 0, uno::Any(locQueryToProps(*rR.mxQuery)), + beans::PropertyState_DIRECT_VALUE }); + std::vector> aLocs; + for (const auto& rLoc : rR.maLocations) + aLocs.push_back(locationToProps(rLoc)); + if (!aLocs.empty()) + aVec.push_back({ u"locations"_ustr, 0, uno::Any(comphelper::containerToSequence(aLocs)), + beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoLocationQueryResultModel locResultFromProps(const uno::Sequence& rProps) +{ + GeoLocationQueryResultModel aR; + for (const auto& rProp : rProps) + { + if (rProp.Name == "query") + { + uno::Sequence aInner; + if (rProp.Value >>= aInner) + aR.mxQuery = locQueryFromProps(aInner); + } + else if (rProp.Name == "locations") + { + uno::Sequence> aArr; + if (rProp.Value >>= aArr) + for (const auto& rL : aArr) + aR.maLocations.push_back(locationFromProps(rL)); + } + } + return aR; +} + +uno::Sequence polygonToProps(const GeoPolygonModel& rP) +{ + std::vector aVec; + if (rP.mosPolygonId.has_value()) + aVec.push_back({ u"polygonId"_ustr, 0, uno::Any(*rP.mosPolygonId), + beans::PropertyState_DIRECT_VALUE }); + if (rP.mosNumPoints.has_value()) + aVec.push_back({ u"numPoints"_ustr, 0, uno::Any(*rP.mosNumPoints), + beans::PropertyState_DIRECT_VALUE }); + if (rP.mosPcaRings.has_value()) + aVec.push_back( + { u"pcaRings"_ustr, 0, uno::Any(*rP.mosPcaRings), beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoPolygonModel polygonFromProps(const uno::Sequence& rProps) +{ + GeoPolygonModel aP; + for (const auto& rProp : rProps) + { + OUString s; + if (!(rProp.Value >>= s)) + continue; + if (rProp.Name == "polygonId") + aP.mosPolygonId = s; + else if (rProp.Name == "numPoints") + aP.mosNumPoints = s; + else if (rProp.Name == "pcaRings") + aP.mosPcaRings = s; + } + return aP; +} + +uno::Sequence geoDataToProps(const GeoDataModel& rD) +{ + std::vector aVec; + if (rD.mosEntityName.has_value()) + aVec.push_back({ u"entityName"_ustr, 0, uno::Any(*rD.mosEntityName), + beans::PropertyState_DIRECT_VALUE }); + if (rD.mosEntityId.has_value()) + aVec.push_back( + { u"entityId"_ustr, 0, uno::Any(*rD.mosEntityId), beans::PropertyState_DIRECT_VALUE }); + if (rD.mosEast.has_value()) + aVec.push_back( + { u"east"_ustr, 0, uno::Any(*rD.mosEast), beans::PropertyState_DIRECT_VALUE }); + if (rD.mosWest.has_value()) + aVec.push_back( + { u"west"_ustr, 0, uno::Any(*rD.mosWest), beans::PropertyState_DIRECT_VALUE }); + if (rD.mosNorth.has_value()) + aVec.push_back( + { u"north"_ustr, 0, uno::Any(*rD.mosNorth), beans::PropertyState_DIRECT_VALUE }); + if (rD.mosSouth.has_value()) + aVec.push_back( + { u"south"_ustr, 0, uno::Any(*rD.mosSouth), beans::PropertyState_DIRECT_VALUE }); + if (!rD.maPolygons.empty()) + { + std::vector> aPolys; + for (const auto& rP : rD.maPolygons) + aPolys.push_back(polygonToProps(rP)); + aVec.push_back({ u"polygons"_ustr, 0, uno::Any(comphelper::containerToSequence(aPolys)), + beans::PropertyState_DIRECT_VALUE }); + } + if (!rD.maCopyrights.empty()) + { + std::vector aCR; + for (const auto& rC : rD.maCopyrights) + aCR.push_back(rC.msText); + aVec.push_back({ u"copyrights"_ustr, 0, uno::Any(comphelper::containerToSequence(aCR)), + beans::PropertyState_DIRECT_VALUE }); + } + return comphelper::containerToSequence(aVec); +} + +GeoDataModel geoDataFromProps(const uno::Sequence& rProps) +{ + GeoDataModel aD; + for (const auto& rProp : rProps) + { + if (rProp.Name == "polygons") + { + uno::Sequence> aArr; + if (rProp.Value >>= aArr) + for (const auto& rP : aArr) + aD.maPolygons.push_back(polygonFromProps(rP)); + } + else if (rProp.Name == "copyrights") + { + uno::Sequence aArr; + if (rProp.Value >>= aArr) + for (const auto& rC : aArr) + aD.maCopyrights.push_back({ rC }); + } + else + { + OUString s; + if (!(rProp.Value >>= s)) + continue; + if (rProp.Name == "entityName") + aD.mosEntityName = s; + else if (rProp.Name == "entityId") + aD.mosEntityId = s; + else if (rProp.Name == "east") + aD.mosEast = s; + else if (rProp.Name == "west") + aD.mosWest = s; + else if (rProp.Name == "north") + aD.mosNorth = s; + else if (rProp.Name == "south") + aD.mosSouth = s; + } + } + return aD; +} + +uno::Sequence dataEntityQueryToProps(const GeoDataEntityQueryModel& rQ) +{ + std::vector aVec; + if (rQ.mosEntityType.has_value()) + aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rQ.mosEntityType), + beans::PropertyState_DIRECT_VALUE }); + if (rQ.mosEntityId.has_value()) + aVec.push_back( + { u"entityId"_ustr, 0, uno::Any(*rQ.mosEntityId), beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoDataEntityQueryModel dataEntityQueryFromProps(const uno::Sequence& rProps) +{ + GeoDataEntityQueryModel aQ; + for (const auto& rProp : rProps) + { + OUString s; + if (!(rProp.Value >>= s)) + continue; + if (rProp.Name == "entityType") + aQ.mosEntityType = s; + else if (rProp.Name == "entityId") + aQ.mosEntityId = s; + } + return aQ; +} + +uno::Sequence dataEntityResultToProps(const GeoDataEntityQueryResultModel& rR) +{ + std::vector aVec; + if (rR.mxQuery.has_value()) + aVec.push_back({ u"query"_ustr, 0, uno::Any(dataEntityQueryToProps(*rR.mxQuery)), + beans::PropertyState_DIRECT_VALUE }); + if (rR.mxData.has_value()) + aVec.push_back({ u"data"_ustr, 0, uno::Any(geoDataToProps(*rR.mxData)), + beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoDataEntityQueryResultModel +dataEntityResultFromProps(const uno::Sequence& rProps) +{ + GeoDataEntityQueryResultModel aR; + for (const auto& rProp : rProps) + { + uno::Sequence aInner; + if (!(rProp.Value >>= aInner)) + continue; + if (rProp.Name == "query") + aR.mxQuery = dataEntityQueryFromProps(aInner); + else if (rProp.Name == "data") + aR.mxData = geoDataFromProps(aInner); + } + return aR; +} + +uno::Sequence ptQueryToProps(const GeoDataPointQueryModel& rQ) +{ + std::vector aVec; + if (rQ.mosEntityType.has_value()) + aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rQ.mosEntityType), + beans::PropertyState_DIRECT_VALUE }); + if (rQ.mosLatitude.has_value()) + aVec.push_back( + { u"latitude"_ustr, 0, uno::Any(*rQ.mosLatitude), beans::PropertyState_DIRECT_VALUE }); + if (rQ.mosLongitude.has_value()) + aVec.push_back({ u"longitude"_ustr, 0, uno::Any(*rQ.mosLongitude), + beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoDataPointQueryModel ptQueryFromProps(const uno::Sequence& rProps) +{ + GeoDataPointQueryModel aQ; + for (const auto& rProp : rProps) + { + OUString s; + if (!(rProp.Value >>= s)) + continue; + if (rProp.Name == "entityType") + aQ.mosEntityType = s; + else if (rProp.Name == "latitude") + aQ.mosLatitude = s; + else if (rProp.Name == "longitude") + aQ.mosLongitude = s; + } + return aQ; +} + +uno::Sequence ptEntityQueryToProps(const GeoDataPointToEntityQueryModel& rQ) +{ + std::vector aVec; + if (rQ.mosEntityType.has_value()) + aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rQ.mosEntityType), + beans::PropertyState_DIRECT_VALUE }); + if (rQ.mosEntityId.has_value()) + aVec.push_back( + { u"entityId"_ustr, 0, uno::Any(*rQ.mosEntityId), beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoDataPointToEntityQueryModel +ptEntityQueryFromProps(const uno::Sequence& rProps) +{ + GeoDataPointToEntityQueryModel aQ; + for (const auto& rProp : rProps) + { + OUString s; + if (!(rProp.Value >>= s)) + continue; + if (rProp.Name == "entityType") + aQ.mosEntityType = s; + else if (rProp.Name == "entityId") + aQ.mosEntityId = s; + } + return aQ; +} + +uno::Sequence ptResultToProps(const GeoDataPointToEntityQueryResultModel& rR) +{ + std::vector aVec; + if (rR.mxPointQuery.has_value()) + aVec.push_back({ u"pointQuery"_ustr, 0, uno::Any(ptQueryToProps(*rR.mxPointQuery)), + beans::PropertyState_DIRECT_VALUE }); + if (rR.mxEntityQuery.has_value()) + aVec.push_back({ u"entityQuery"_ustr, 0, uno::Any(ptEntityQueryToProps(*rR.mxEntityQuery)), + beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoDataPointToEntityQueryResultModel +ptResultFromProps(const uno::Sequence& rProps) +{ + GeoDataPointToEntityQueryResultModel aR; + for (const auto& rProp : rProps) + { + uno::Sequence aInner; + if (!(rProp.Value >>= aInner)) + continue; + if (rProp.Name == "pointQuery") + aR.mxPointQuery = ptQueryFromProps(aInner); + else if (rProp.Name == "entityQuery") + aR.mxEntityQuery = ptEntityQueryFromProps(aInner); + } + return aR; +} + +uno::Sequence childQueryToProps(const GeoChildEntitiesQueryModel& rQ) +{ + std::vector aVec; + if (rQ.mosEntityId.has_value()) + aVec.push_back( + { u"entityId"_ustr, 0, uno::Any(*rQ.mosEntityId), beans::PropertyState_DIRECT_VALUE }); + if (!rQ.maEntityTypes.empty()) + aVec.push_back({ u"entityTypes"_ustr, 0, + uno::Any(comphelper::containerToSequence(rQ.maEntityTypes)), + beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoChildEntitiesQueryModel childQueryFromProps(const uno::Sequence& rProps) +{ + GeoChildEntitiesQueryModel aQ; + for (const auto& rProp : rProps) + { + if (rProp.Name == "entityId") + { + OUString s; + if (rProp.Value >>= s) + aQ.mosEntityId = s; + } + else if (rProp.Name == "entityTypes") + { + uno::Sequence aArr; + if (rProp.Value >>= aArr) + for (const auto& rS : aArr) + aQ.maEntityTypes.push_back(rS); + } + } + return aQ; +} + +uno::Sequence hierarchyEntityToProps(const GeoHierarchyEntityModel& rE) +{ + std::vector aVec; + if (rE.mosEntityName.has_value()) + aVec.push_back({ u"entityName"_ustr, 0, uno::Any(*rE.mosEntityName), + beans::PropertyState_DIRECT_VALUE }); + if (rE.mosEntityId.has_value()) + aVec.push_back( + { u"entityId"_ustr, 0, uno::Any(*rE.mosEntityId), beans::PropertyState_DIRECT_VALUE }); + if (rE.mosEntityType.has_value()) + aVec.push_back({ u"entityType"_ustr, 0, uno::Any(*rE.mosEntityType), + beans::PropertyState_DIRECT_VALUE }); + return comphelper::containerToSequence(aVec); +} + +GeoHierarchyEntityModel hierarchyEntityFromProps(const uno::Sequence& rProps) +{ + GeoHierarchyEntityModel aE; + for (const auto& rProp : rProps) + { + OUString s; + if (!(rProp.Value >>= s)) + continue; + if (rProp.Name == "entityName") + aE.mosEntityName = s; + else if (rProp.Name == "entityId") + aE.mosEntityId = s; + else if (rProp.Name == "entityType") + aE.mosEntityType = s; + } + return aE; +} + +uno::Sequence childResultToProps(const GeoChildEntitiesQueryResultModel& rR) +{ + std::vector aVec; + if (rR.mxQuery.has_value()) + aVec.push_back({ u"query"_ustr, 0, uno::Any(childQueryToProps(*rR.mxQuery)), + beans::PropertyState_DIRECT_VALUE }); + if (!rR.maEntities.empty()) + { + std::vector> aArr; + for (const auto& rE : rR.maEntities) + aArr.push_back(hierarchyEntityToProps(rE)); + aVec.push_back({ u"entities"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)), + beans::PropertyState_DIRECT_VALUE }); + } + return comphelper::containerToSequence(aVec); +} + +GeoChildEntitiesQueryResultModel +childResultFromProps(const uno::Sequence& rProps) +{ + GeoChildEntitiesQueryResultModel aR; + for (const auto& rProp : rProps) + { + if (rProp.Name == "query") + { + uno::Sequence aInner; + if (rProp.Value >>= aInner) + aR.mxQuery = childQueryFromProps(aInner); + } + else if (rProp.Name == "entities") + { + uno::Sequence> aArr; + if (rProp.Value >>= aArr) + for (const auto& rE : aArr) + aR.maEntities.push_back(hierarchyEntityFromProps(rE)); + } + } + return aR; +} + +uno::Sequence parentResultToProps(const GeoParentEntitiesQueryResultModel& rR) +{ + std::vector aVec; + if (rR.mxQuery.has_value()) + { + std::vector aQ; + if (rR.mxQuery->mosEntityId.has_value()) + aQ.push_back({ u"entityId"_ustr, 0, uno::Any(*rR.mxQuery->mosEntityId), + beans::PropertyState_DIRECT_VALUE }); + aVec.push_back({ u"query"_ustr, 0, uno::Any(comphelper::containerToSequence(aQ)), + beans::PropertyState_DIRECT_VALUE }); + } + if (rR.mxEntity.has_value()) + { + std::vector aE; + if (rR.mxEntity->mosEntityName.has_value()) + aE.push_back({ u"entityName"_ustr, 0, uno::Any(*rR.mxEntity->mosEntityName), + beans::PropertyState_DIRECT_VALUE }); + if (rR.mxEntity->mosEntityType.has_value()) + aE.push_back({ u"entityType"_ustr, 0, uno::Any(*rR.mxEntity->mosEntityType), + beans::PropertyState_DIRECT_VALUE }); + aVec.push_back({ u"entity"_ustr, 0, uno::Any(comphelper::containerToSequence(aE)), + beans::PropertyState_DIRECT_VALUE }); + } + if (rR.mxParentEntity.has_value()) + { + std::vector aP; + if (rR.mxParentEntity->mosEntityId.has_value()) + aP.push_back({ u"entityId"_ustr, 0, uno::Any(*rR.mxParentEntity->mosEntityId), + beans::PropertyState_DIRECT_VALUE }); + aVec.push_back({ u"parentEntity"_ustr, 0, uno::Any(comphelper::containerToSequence(aP)), + beans::PropertyState_DIRECT_VALUE }); + } + return comphelper::containerToSequence(aVec); +} + +GeoParentEntitiesQueryResultModel +parentResultFromProps(const uno::Sequence& rProps) +{ + GeoParentEntitiesQueryResultModel aR; + for (const auto& rProp : rProps) + { + uno::Sequence aInner; + if (!(rProp.Value >>= aInner)) + continue; + if (rProp.Name == "query") + { + aR.mxQuery.emplace(); + for (const auto& rQ : aInner) + { + OUString s; + if (rQ.Name == "entityId" && (rQ.Value >>= s)) + aR.mxQuery->mosEntityId = s; + } + } + else if (rProp.Name == "entity") + { + aR.mxEntity.emplace(); + for (const auto& rE : aInner) + { + OUString s; + if (!(rE.Value >>= s)) + continue; + if (rE.Name == "entityName") + aR.mxEntity->mosEntityName = s; + else if (rE.Name == "entityType") + aR.mxEntity->mosEntityType = s; + } + } + else if (rProp.Name == "parentEntity") + { + aR.mxParentEntity.emplace(); + for (const auto& rP : aInner) + { + OUString s; + if (rP.Name == "entityId" && (rP.Value >>= s)) + aR.mxParentEntity->mosEntityId = s; + } + } + } + return aR; +} + +} // anonymous namespace + +uno::Sequence geoClearToPropertyValues(const GeoClearModel& rModel) +{ + std::vector aVec; + + if (!rModel.maLocResults.empty()) + { + std::vector> aArr; + for (const auto& rR : rModel.maLocResults) + aArr.push_back(locResultToProps(rR)); + aVec.push_back({ u"locResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)), + beans::PropertyState_DIRECT_VALUE }); + } + if (!rModel.maDataResults.empty()) + { + std::vector> aArr; + for (const auto& rR : rModel.maDataResults) + aArr.push_back(dataEntityResultToProps(rR)); + aVec.push_back({ u"dataResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)), + beans::PropertyState_DIRECT_VALUE }); + } + if (!rModel.maPtResults.empty()) + { + std::vector> aArr; + for (const auto& rR : rModel.maPtResults) + aArr.push_back(ptResultToProps(rR)); + aVec.push_back({ u"ptResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)), + beans::PropertyState_DIRECT_VALUE }); + } + if (!rModel.maChildResults.empty()) + { + std::vector> aArr; + for (const auto& rR : rModel.maChildResults) + aArr.push_back(childResultToProps(rR)); + aVec.push_back({ u"childResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)), + beans::PropertyState_DIRECT_VALUE }); + } + if (!rModel.maParentResults.empty()) + { + std::vector> aArr; + for (const auto& rR : rModel.maParentResults) + aArr.push_back(parentResultToProps(rR)); + aVec.push_back({ u"parentResults"_ustr, 0, uno::Any(comphelper::containerToSequence(aArr)), + beans::PropertyState_DIRECT_VALUE }); + } + + return comphelper::containerToSequence(aVec); +} + +GeoClearModel geoClearFromPropertyValues(const uno::Sequence& rProps) +{ + GeoClearModel aModel; + for (const auto& rProp : rProps) + { + if (rProp.Name == "locResults") + { + uno::Sequence> aArr; + if (rProp.Value >>= aArr) + for (const auto& rR : aArr) + aModel.maLocResults.push_back(locResultFromProps(rR)); + } + else if (rProp.Name == "dataResults") + { + uno::Sequence> aArr; + if (rProp.Value >>= aArr) + for (const auto& rR : aArr) + aModel.maDataResults.push_back(dataEntityResultFromProps(rR)); + } + else if (rProp.Name == "ptResults") + { + uno::Sequence> aArr; + if (rProp.Value >>= aArr) + for (const auto& rR : aArr) + aModel.maPtResults.push_back(ptResultFromProps(rR)); + } + else if (rProp.Name == "childResults") + { + uno::Sequence> aArr; + if (rProp.Value >>= aArr) + for (const auto& rR : aArr) + aModel.maChildResults.push_back(childResultFromProps(rR)); + } + else if (rProp.Name == "parentResults") + { + uno::Sequence> aArr; + if (rProp.Value >>= aArr) + for (const auto& rR : aArr) + aModel.maParentResults.push_back(parentResultFromProps(rR)); + } + } + return aModel; +} + +void convertGeography(const GeographyModel& rModel, PropertySet& rSeriesProp) +{ + if (rModel.moeProjectionType.has_value()) + rSeriesProp.setProperty(PROP_GeographyProjectionType, + static_cast(*rModel.moeProjectionType)); + if (rModel.moeViewedRegionType.has_value()) + rSeriesProp.setProperty(PROP_GeographyViewedRegionType, + static_cast(*rModel.moeViewedRegionType)); + if (rModel.mosCultureLanguage.has_value()) + rSeriesProp.setProperty(PROP_GeographyCultureLanguage, *rModel.mosCultureLanguage); + if (rModel.mosCultureRegion.has_value()) + rSeriesProp.setProperty(PROP_GeographyCultureRegion, *rModel.mosCultureRegion); + if (rModel.mosAttribution.has_value()) + rSeriesProp.setProperty(PROP_GeographyAttribution, *rModel.mosAttribution); + + if (rModel.mxGeoCache.has_value()) + { + const auto& rCache = *rModel.mxGeoCache; + if (rCache.mosProvider.has_value()) + rSeriesProp.setProperty(PROP_GeoCacheProvider, *rCache.mosProvider); + if (rCache.mosBinary.has_value()) + rSeriesProp.setProperty(PROP_GeoCacheBinary, *rCache.mosBinary); + if (rCache.mxClear.has_value()) + rSeriesProp.setProperty(PROP_GeoCacheClearData, + geoClearToPropertyValues(*rCache.mxClear)); + } +} + +} // namespace oox::drawingml::chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/chart/geographymodel.cxx b/oox/source/drawingml/chart/geographymodel.cxx new file mode 100644 index 000000000000..27b181c5b6b4 --- /dev/null +++ b/oox/source/drawingml/chart/geographymodel.cxx @@ -0,0 +1,86 @@ +/* -*- 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 + +namespace oox::drawingml::chart +{ +GeoProjectionType geoProjectionTypeFromString(std::u16string_view rStr) +{ + if (rStr == u"miller") + return GeoProjectionType::Miller; + if (rStr == u"robinson") + return GeoProjectionType::Robinson; + if (rStr == u"albers") + return GeoProjectionType::Albers; + return GeoProjectionType::Mercator; +} + +OUString geoProjectionTypeToString(GeoProjectionType eType) +{ + switch (eType) + { + case GeoProjectionType::Miller: + return u"miller"_ustr; + case GeoProjectionType::Robinson: + return u"robinson"_ustr; + case GeoProjectionType::Albers: + return u"albers"_ustr; + case GeoProjectionType::Mercator: + return u"mercator"_ustr; + } + return u"mercator"_ustr; +} + +GeoMappingLevel geoMappingLevelFromString(std::u16string_view rStr) +{ + if (rStr == u"postalCode") + return GeoMappingLevel::PostalCode; + if (rStr == u"county") + return GeoMappingLevel::County; + if (rStr == u"state") + return GeoMappingLevel::State; + if (rStr == u"countryRegion") + return GeoMappingLevel::CountryRegion; + if (rStr == u"countryRegionList") + return GeoMappingLevel::CountryRegionList; + if (rStr == u"world") + return GeoMappingLevel::World; + if (rStr == u"autodetect") + return GeoMappingLevel::Autodetect; + return GeoMappingLevel::DataOnly; +} + +OUString geoMappingLevelToString(GeoMappingLevel eLevel) +{ + switch (eLevel) + { + case GeoMappingLevel::PostalCode: + return u"postalCode"_ustr; + case GeoMappingLevel::County: + return u"county"_ustr; + case GeoMappingLevel::State: + return u"state"_ustr; + case GeoMappingLevel::CountryRegion: + return u"countryRegion"_ustr; + case GeoMappingLevel::CountryRegionList: + return u"countryRegionList"_ustr; + case GeoMappingLevel::World: + return u"world"_ustr; + case GeoMappingLevel::Autodetect: + return u"autodetect"_ustr; + case GeoMappingLevel::DataOnly: + return u"dataOnly"_ustr; + } + return u"dataOnly"_ustr; +} + +} // namespace oox::drawingml::chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/chart/plotareacontext.cxx b/oox/source/drawingml/chart/plotareacontext.cxx index 3d509617bb43..aaa6d2ce9a38 100644 --- a/oox/source/drawingml/chart/plotareacontext.cxx +++ b/oox/source/drawingml/chart/plotareacontext.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -122,6 +123,9 @@ ContextHandlerRef PlotAreaContext::onCreateContext( sal_Int32 nElement, [[maybe_ switch( getCurrentElement() ) { case C_TOKEN( plotArea ): + + mrModel.meCT = bMSO2007Doc ? ChartType::C_2007 : ChartType::C_OTHER; + switch( nElement ) { case C_TOKEN( area3DChart ): @@ -151,13 +155,13 @@ ContextHandlerRef PlotAreaContext::onCreateContext( sal_Int32 nElement, [[maybe_ return new SurfaceTypeGroupContext( *this, mrModel.maTypeGroups.create( nElement, bMSO2007Doc ) ); case C_TOKEN( catAx ): - return new CatAxisContext( *this, mrModel.maAxes.create( nElement, bMSO2007Doc ) ); + return new CatAxisContext( *this, mrModel.maAxes.create( nElement, mrModel.meCT ) ); case C_TOKEN( dateAx ): - return new DateAxisContext( *this, mrModel.maAxes.create( nElement, bMSO2007Doc ) ); + return new DateAxisContext( *this, mrModel.maAxes.create( nElement, mrModel.meCT ) ); case C_TOKEN( serAx ): - return new SerAxisContext( *this, mrModel.maAxes.create( nElement, bMSO2007Doc ) ); + return new SerAxisContext( *this, mrModel.maAxes.create( nElement, mrModel.meCT ) ); case C_TOKEN( valAx ): - return new ValAxisContext( *this, mrModel.maAxes.create( nElement, bMSO2007Doc ) ); + return new ValAxisContext( *this, mrModel.maAxes.create( nElement, mrModel.meCT ) ); case C_TOKEN( layout ): return new LayoutContext( *this, mrModel.mxLayout.create() ); @@ -168,6 +172,9 @@ ContextHandlerRef PlotAreaContext::onCreateContext( sal_Int32 nElement, [[maybe_ } break; case CX_TOKEN(plotArea) : + + mrModel.meCT = ChartType::CX; + switch (nElement) { case CX_TOKEN(plotAreaRegion) : return this; @@ -175,14 +182,7 @@ ContextHandlerRef PlotAreaContext::onCreateContext( sal_Int32 nElement, [[maybe_ if (rAttribs.hasAttribute(XML_id)) { sal_Int32 nId = rAttribs.getInteger(XML_id, -1); // TODO: also handle attribute "hidden" - - // Add the id to the axis id list in the (fictitious) - // type group - std::shared_ptr aTGM = - mrModel.maTypeGroups.get(mrModel.maTypeGroups.size() - 1); - aTGM->maAxisIds.push_back(nId); - - return new CxAxisContext(*this, mrModel.maAxes.create(nElement, false), nId); + return new CxAxisContext(*this, mrModel.maAxes.create(nElement, mrModel.meCT), nId); } else { return nullptr; } @@ -233,7 +233,13 @@ ContextHandlerRef PlotAreaContext::onCreateContext( sal_Int32 nElement, [[maybe_ mrModel.maTypeGroups.create(nTypeId, false); std::shared_ptr aTGM = mrModel.maTypeGroups.get(mrModel.maTypeGroups.size() - 1); - return new ChartexSeriesContext(*this, aTGM->maSeries.create(false), mrModel.mnCurSeriesIdx++); + SeriesModel& rSeries = + aTGM->maSeries.create(false, nTypeId); + if (rAttribs.hasAttribute(XML_ownerIdx)) + rSeries.monOwnerIdx + = rAttribs.getInteger(XML_ownerIdx, 0); + return new ChartexSeriesContext(*this, + rSeries, mrModel.mnCurSeriesIdx++); } return nullptr; case CX_TOKEN(plotSurface) : diff --git a/oox/source/drawingml/chart/plotareaconverter.cxx b/oox/source/drawingml/chart/plotareaconverter.cxx index 95496906fdea..8b9d6d1a7741 100644 --- a/oox/source/drawingml/chart/plotareaconverter.cxx +++ b/oox/source/drawingml/chart/plotareaconverter.cxx @@ -74,7 +74,8 @@ public: sal_Int32 nAxesSetIdx, DataSourceCxModel::DataMap& raSourceMap, bool bSupportsVaryColorsByPoint, - bool bUseFixedInnerSize ); + bool bUseFixedInnerSize, + ChartType eCT); /** Returns the automatic chart title if the axes set contains only one series. */ const OUString& getAutomaticTitle() const { return maAutoTitle; } @@ -104,19 +105,54 @@ AxesSetConverter::AxesSetConverter( const ConverterRoot& rParent, AxesSetModel& { } -ModelRef< AxisModel > lclGetOrCreateAxis( const AxesSetModel::AxisMap& rFromAxes, sal_Int32 nAxisIdx, sal_Int32 nDefTypeId, bool bMSO2007Doc ) +ModelRef< AxisModel > lclGetOrCreateAxis( const AxesSetModel::AxisMap& rFromAxes, sal_Int32 nAxisIdx, sal_Int32 nDefTypeId, ChartType eCT ) { ModelRef< AxisModel > xAxis = rFromAxes.get( nAxisIdx ); if( !xAxis ) - xAxis.create( nDefTypeId, bMSO2007Doc ).mbDeleted = true; // missing axis is invisible + xAxis.create( nDefTypeId, eCT ).mbDeleted = true; // missing axis is invisible return xAxis; } +bool lclHasTypeGroupWithLayout(const AxesSetModel::TypeGroupVector& rTypeGroups, sal_Int32 nToken) +{ + for (auto const& typeGroup : rTypeGroups) + if (typeGroup && typeGroup->mnTypeId == nToken) + return true; + return false; +} + void AxesSetConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, View3DModel& rView3DModel, sal_Int32 nAxesSetIdx, DataSourceCxModel::DataMap& raSourceMap, - bool bSupportsVaryColorsByPoint, bool bUseFixedInnerSize) + bool bSupportsVaryColorsByPoint, bool bUseFixedInnerSize, + ChartType eCT) { + // chartex clusteredColumn + is how a histogram is stored in OOXML. + // But the same markup also appears on the clusteredColumn sub-chart of a + // paretoLine, which must not be reclassified. The difference is visible only at + // this level, where we see all sibling type groups. + { + const bool bHasParetoSibling + = lclHasTypeGroupWithLayout(mrModel.maTypeGroups, CX_TOKEN(paretoLine)); + if (!bHasParetoSibling) + { + for (auto const& typeGroup : mrModel.maTypeGroups) + { + if (!typeGroup || typeGroup->mnTypeId != CX_TOKEN(clusteredColumn)) + continue; + for (auto const& rxSeries : typeGroup->maSeries) + { + if (rxSeries && rxSeries->mxLayoutPr.is() + && rxSeries->mxLayoutPr->mxBinning.is()) + { + typeGroup->mbForceHistogram = true; + break; + } + } + } + } + } + // create type group converter objects for all type groups typedef RefVector< TypeGroupConverter > TypeGroupConvVector; TypeGroupConvVector aTypeGroups; @@ -173,36 +209,38 @@ void AxesSetConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, if( xCoordSystem.is() ) { // Transfer any (chartex) data, specified at the chartSpace level, - // into the appropriate series. This needs to happen before the - // calls to AxisConverter::convertFromModel() below. - for (auto const& typeGroup : aTypeGroups) { + // into the appropriate series. Must happen before convertFromModel + // so the series data is available when data series are created. + for (auto const& typeGroup : aTypeGroups) typeGroup->moveDataToSeries(raSourceMap); - } - - bool bMSO2007Doc = getFilter().isMSO2007Document(); - // convert all axes (create missing axis models) - ModelRef< AxisModel > xXAxis = lclGetOrCreateAxis( mrModel.maAxes, API_X_AXIS, rFirstTypeGroup.getTypeInfo().mbCategoryAxis ? C_TOKEN( catAx ) : C_TOKEN( valAx ), bMSO2007Doc ); - ModelRef< AxisModel > xYAxis = lclGetOrCreateAxis( mrModel.maAxes, API_Y_AXIS, C_TOKEN( valAx ), bMSO2007Doc ); - - AxisConverter aXAxisConv( *this, *xXAxis ); - aXAxisConv.convertFromModel(xCoordSystem, aTypeGroups, xYAxis.get(), nAxesSetIdx, - API_X_AXIS, bUseFixedInnerSize); - AxisConverter aYAxisConv( *this, *xYAxis ); - aYAxisConv.convertFromModel(xCoordSystem, aTypeGroups, xXAxis.get(), nAxesSetIdx, - API_Y_AXIS, bUseFixedInnerSize); - - if( rFirstTypeGroup.isDeep3dChart() ) - { - ModelRef< AxisModel > xZAxis = lclGetOrCreateAxis( mrModel.maAxes, API_Z_AXIS, C_TOKEN( serAx ), bMSO2007Doc ); - AxisConverter aZAxisConv( *this, *xZAxis ); - aZAxisConv.convertFromModel(xCoordSystem, aTypeGroups, nullptr, nAxesSetIdx, - API_Z_AXIS, bUseFixedInnerSize); - } // convert all chart type groups, this converts all series data and formatting for (auto const& typeGroup : aTypeGroups) typeGroup->convertFromModel( rxDiagram, xCoordSystem, - nAxesSetIdx,bSupportsVaryColorsByPoint ); + nAxesSetIdx, bSupportsVaryColorsByPoint ); + + // convert all axes (create missing axis models) + ModelRef< AxisModel > xXAxis = lclGetOrCreateAxis( mrModel.maAxes, + API_X_AXIS, rFirstTypeGroup.getTypeInfo().mbCategoryAxis ? + C_TOKEN( catAx ) : C_TOKEN( valAx ), eCT ); + ModelRef< AxisModel > xYAxis = lclGetOrCreateAxis( mrModel.maAxes, + API_Y_AXIS, C_TOKEN( valAx ), eCT ); + + AxisConverter aXAxisConv( *this, *xXAxis ); + aXAxisConv.convertFromModel(xCoordSystem, aTypeGroups, xYAxis.get(), nAxesSetIdx, + API_X_AXIS, bUseFixedInnerSize, eCT); + AxisConverter aYAxisConv( *this, *xYAxis ); + aYAxisConv.convertFromModel(xCoordSystem, aTypeGroups, xXAxis.get(), nAxesSetIdx, + API_Y_AXIS, bUseFixedInnerSize, eCT); + + if( rFirstTypeGroup.isDeep3dChart() ) + { + ModelRef< AxisModel > xZAxis = lclGetOrCreateAxis( + mrModel.maAxes, API_Z_AXIS, C_TOKEN( serAx ), eCT ); + AxisConverter aZAxisConv( *this, *xZAxis ); + aZAxisConv.convertFromModel(xCoordSystem, aTypeGroups, nullptr, nAxesSetIdx, + API_Z_AXIS, bUseFixedInnerSize, eCT); + } } } catch( Exception& ) @@ -374,6 +412,116 @@ void PlotAreaConverter::convertFromModel( View3DModel& rView3DModel, } } + // Transfer the series-level axis ids, given in chartex, to the + // type group. This doesn't work if there are multiple series + // per type group, but I don't think that should happen. + for (auto const& typeGroup : mrModel.maTypeGroups) + { + if( !typeGroup->maSeries.empty() ) + { + for (auto const& elemSeries : typeGroup->maSeries) { + // First fill in any implicit axes. MS Office produces files + // where some series axis ids are implicit. Make those explicit. + switch (elemSeries->mnTypeId) { + case CX_TOKEN(boxWhisker): + case CX_TOKEN(clusteredColumn): + case CX_TOKEN(paretoLine): + case CX_TOKEN(waterfall): + { + bool bNeedCat = false, bNeedVal = false; + // Should have two axes, one category and one value + // (though they may be hidden) + if (elemSeries->maAxisIds.size() == 0) { + bNeedCat = bNeedVal = true; + } else if (elemSeries->maAxisIds.size() == 1) { + assert(aAxisMap[elemSeries->maAxisIds[0]]->mobCatNotVal.has_value()); + bool bCatNotVal = aAxisMap[elemSeries->maAxisIds[0]]->mobCatNotVal.value(); + if (bCatNotVal) { + // have cat, need val + bNeedVal = true; + } else { + // have val, need cat + bNeedCat = true; + } + } else if (elemSeries->maAxisIds.size() == 2) { + assert(aAxisMap[elemSeries->maAxisIds[0]]->mobCatNotVal.has_value()); + assert(aAxisMap[elemSeries->maAxisIds[1]]->mobCatNotVal.has_value()); + [[maybe_unused]] bool bCatNotVal0 = aAxisMap[elemSeries->maAxisIds[0]]->mobCatNotVal.value(); + [[maybe_unused]] bool bCatNotVal1 = aAxisMap[elemSeries->maAxisIds[1]]->mobCatNotVal.value(); + + // There should be one cat axis and one val axis + assert((bCatNotVal0 && !bCatNotVal1) || (!bCatNotVal0 && bCatNotVal1)); + + } else { + // more than two axes: don't know what to do with this + assert(false); + } + + if (bNeedCat) { + // Add the first cat axis + for (const auto& [nId, aAxisModel] : aAxisMap) { + if (aAxisModel->mobCatNotVal.has_value() && + aAxisModel->mobCatNotVal.value()) { + elemSeries->maAxisIds.push_back(nId); + break; + } + } + } + if (bNeedVal) { + // Add the first cat axis + for (const auto& [nId, aAxisModel] : aAxisMap) { + if (aAxisModel->mobCatNotVal.has_value() && + !aAxisModel->mobCatNotVal.value()) { + elemSeries->maAxisIds.push_back(nId); + break; + } + } + } + break; + } + case CX_TOKEN(funnel): + { + bool bNeedCat = false; + // Should have one category axis (though it may be hidden) + // Funnel never seems to have a value axis + if (elemSeries->maAxisIds.size() == 0) { + bNeedCat = true; + } else if (elemSeries->maAxisIds.size() == 1) { + assert(aAxisMap[elemSeries->maAxisIds[0]]->mobCatNotVal.has_value()); + [[maybe_unused]] bool bCatNotVal = aAxisMap[elemSeries->maAxisIds[0]]->mobCatNotVal.value(); + + assert(bCatNotVal); + } else { + // more than one axis: don't know what to do with this + assert(false); + } + + if (bNeedCat) { + // Add the first cat axis + for (const auto& [nId, aAxisModel] : aAxisMap) { + if (aAxisModel->mobCatNotVal.has_value() && + aAxisModel->mobCatNotVal.value()) { + elemSeries->maAxisIds.push_back(nId); + break; + } + } + } + break; + } + default: + break; + } + + if (typeGroup->maAxisIds.empty()) { + if (!elemSeries->maAxisIds.empty()) { + assert(typeGroup->maSeries.size() == 1); + typeGroup->maAxisIds = elemSeries->maAxisIds; + } + } + } + } + } + // group the type group models into different axes sets typedef ModelVector< AxesSetModel > AxesSetVector; AxesSetVector aAxesSets; @@ -412,8 +560,9 @@ void PlotAreaConverter::convertFromModel( View3DModel& rView3DModel, pAxesSet->maTypeGroups.push_back( typeGroup ); // collect the maximum series index for automatic series formatting - for (auto const& elemSeries : typeGroup->maSeries) + for (auto const& elemSeries : typeGroup->maSeries) { nMaxSeriesIdx = ::std::max( nMaxSeriesIdx, elemSeries->mnIndex ); + } } } getFormatter().setMaxSeriesIndex( nMaxSeriesIdx ); @@ -438,7 +587,8 @@ void PlotAreaConverter::convertFromModel( View3DModel& rView3DModel, { AxesSetConverter aAxesSetConv(*this, *axesSet); aAxesSetConv.convertFromModel(xDiagram, rView3DModel, nAxesSetIdx, - rDataCxModel.maSourceMap, bSupportsVaryColorsByPoint, bUseFixedInnerSize); + rDataCxModel.maSourceMap, bSupportsVaryColorsByPoint, + bUseFixedInnerSize, mrModel.meCT); if(nAxesSetIdx == nStartAxesSetIdx) { maAutoTitle = aAxesSetConv.getAutomaticTitle(); @@ -465,6 +615,9 @@ void PlotAreaConverter::convertFromModel( View3DModel& rView3DModel, { PropertySet aPropSet( xDiagram->getWall() ); getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, OBJECTTYPE_PLOTAREA2D ); + + if (mrModel.meCT == ChartType::CX && mrModel.mxShapeProp.is()) + aPropSet.setProperty(PROP_HasExplicitSpPr, true); } } @@ -500,6 +653,6 @@ void PlotAreaConverter::convertPositionFromModel() } } -} // namespace oox +} // namespace oox::drawingml::chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/chart/seriescontext.cxx b/oox/source/drawingml/chart/seriescontext.cxx index 946e1f47aa32..23a9aa02979e 100644 --- a/oox/source/drawingml/chart/seriescontext.cxx +++ b/oox/source/drawingml/chart/seriescontext.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -81,7 +82,13 @@ ContextHandlerRef lclDataLabelSharedCreateContext( ContextHandler2& rContext, case CX_TOKEN( txPr ): return new TextBodyContext( rContext, orModel.mxTextProp.create() ); case CX_TOKEN( visibility ): - return nullptr; // TODO + // chartex has no legend key or percentage labels + orModel.mobShowSerName = rAttribs.getBool( XML_seriesName, false ); + orModel.mobShowCatName = rAttribs.getBool( XML_categoryName, false ); + orModel.mobShowVal = rAttribs.getBool( XML_value, true ); + orModel.mobShowLegendKey = false; + orModel.mobShowPercent = false; + return nullptr; } return nullptr; } @@ -168,6 +175,24 @@ ContextHandlerRef DataLabelsContext::onCreateContext( sal_Int32 nElement, const { case C_TOKEN( dLbl ): return new DataLabelContext( *this, mrModel.maPointLabels.create(mrModel, bMSO2007Doc) ); + case CX_TOKEN( dataLabel ): + { + DataLabelModel& rLabel = mrModel.maPointLabels.create( mrModel, bMSO2007Doc ); + rLabel.mnIndex = rAttribs.getInteger( XML_idx, -1 ); + rLabel.monLabelPos = rAttribs.getToken( XML_pos ); + // set MSO defaults + rLabel.mobShowSerName = false; + rLabel.mobShowCatName = false; + rLabel.mobShowVal = true; + return new DataLabelContext( *this, rLabel ); + } + case CX_TOKEN( dataLabelHidden ): + { + DataLabelModel& rLabel = mrModel.maPointLabels.create( mrModel, bMSO2007Doc ); + rLabel.mnIndex = rAttribs.getInteger( XML_idx, -1 ); + rLabel.mbDeleted = true; + return nullptr; + } case C_TOKEN( leaderLines ): return new ShapePrWrapperContext( *this, mrModel.mxLeaderLines.create() ); case C_TOKEN( showLeaderLines ): @@ -483,7 +508,7 @@ ContextHandlerRef AreaSeriesContext::onCreateContext( sal_Int32 nElement, const switch( nElement ) { case C_TOKEN( cat ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::CATEGORIES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) ); case C_TOKEN( errBars ): return new ErrorBarContext( *this, mrModel.maErrorBars.create(bMSO2007Doc) ); case C_TOKEN( dLbls ): @@ -493,7 +518,7 @@ ContextHandlerRef AreaSeriesContext::onCreateContext( sal_Int32 nElement, const case C_TOKEN( trendline ): return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) ); case C_TOKEN( val ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::VALUES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) ); } break; } @@ -518,7 +543,7 @@ ContextHandlerRef BarSeriesContext::onCreateContext( sal_Int32 nElement, const A switch( nElement ) { case C_TOKEN( cat ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::CATEGORIES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) ); case C_TOKEN( dLbls ): return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) ); case C_TOKEN( dPt ): @@ -536,7 +561,7 @@ ContextHandlerRef BarSeriesContext::onCreateContext( sal_Int32 nElement, const A case C_TOKEN( trendline ): return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) ); case C_TOKEN( val ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::VALUES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) ); } break; } @@ -577,9 +602,9 @@ ContextHandlerRef BubbleSeriesContext::onCreateContext( sal_Int32 nElement, cons case C_TOKEN( trendline ): return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) ); case C_TOKEN( xVal ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::CATEGORIES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) ); case C_TOKEN( yVal ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::VALUES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) ); } break; } @@ -604,7 +629,7 @@ ContextHandlerRef LineSeriesContext::onCreateContext( sal_Int32 nElement, const switch( nElement ) { case C_TOKEN( cat ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::CATEGORIES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) ); case C_TOKEN( dLbls ): return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) ); case C_TOKEN( dPt ): @@ -619,7 +644,7 @@ ContextHandlerRef LineSeriesContext::onCreateContext( sal_Int32 nElement, const case C_TOKEN( trendline ): return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) ); case C_TOKEN( val ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::VALUES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) ); } break; } @@ -644,7 +669,7 @@ ContextHandlerRef PieSeriesContext::onCreateContext( sal_Int32 nElement, const A switch( nElement ) { case C_TOKEN( cat ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::CATEGORIES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) ); case C_TOKEN( dLbls ): return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) ); case C_TOKEN( dPt ): @@ -653,7 +678,7 @@ ContextHandlerRef PieSeriesContext::onCreateContext( sal_Int32 nElement, const A mrModel.mnExplosion = rAttribs.getInteger( XML_val, 0 ); return nullptr; case C_TOKEN( val ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::VALUES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) ); } break; } @@ -678,7 +703,7 @@ ContextHandlerRef RadarSeriesContext::onCreateContext( sal_Int32 nElement, const switch( nElement ) { case C_TOKEN( cat ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::CATEGORIES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) ); case C_TOKEN( dLbls ): return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) ); case C_TOKEN( dPt ): @@ -689,7 +714,7 @@ ContextHandlerRef RadarSeriesContext::onCreateContext( sal_Int32 nElement, const mrModel.mbSmooth = rAttribs.getBool( XML_val, bMSO2007Doc ); return nullptr; case C_TOKEN( val ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::VALUES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) ); } break; } @@ -727,9 +752,9 @@ ContextHandlerRef ScatterSeriesContext::onCreateContext( sal_Int32 nElement, con case C_TOKEN( trendline ): return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) ); case C_TOKEN( xVal ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::CATEGORIES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) ); case C_TOKEN( yVal ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::VALUES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) ); } break; } @@ -753,9 +778,9 @@ ContextHandlerRef SurfaceSeriesContext::onCreateContext( sal_Int32 nElement, con switch( nElement ) { case C_TOKEN( cat ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::CATEGORIES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) ); case C_TOKEN( val ): - return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::VALUES ) ); + return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) ); } break; } @@ -793,7 +818,7 @@ ContextHandlerRef BinningContext::onCreateContext( sal_Int32 nElement, const Att { switch( getCurrentElement() ) { - case CX_TOKEN( layoutPr ): + case CX_TOKEN(binning): switch( nElement ) { case CX_TOKEN( binSize ): @@ -806,6 +831,7 @@ ContextHandlerRef BinningContext::onCreateContext( sal_Int32 nElement, const Att // TODO return nullptr; } + break; } return ContextBase::onCreateContext( nElement, rAttribs ); } @@ -830,13 +856,17 @@ ContextHandlerRef LayoutPropsContext::onCreateContext( sal_Int32 nElement, const switch( nElement ) { case CX_TOKEN( parentLabelLayout ): - // TODO + mrModel.mosParentLabelLayout = rAttribs.getString( XML_val ); return nullptr; case CX_TOKEN( regionLabelLayout ): - // TODO + mrModel.mosRegionLabelLayout = rAttribs.getString( XML_val ); return nullptr; case CX_TOKEN( visibility ): - // TODO + mrModel.mobVisibilityConnectorLines = rAttribs.getBool( XML_connectorLines ); + mrModel.mobVisibilityMeanLine = rAttribs.getBool( XML_meanLine ); + mrModel.mobVisibilityMeanMarker = rAttribs.getBool( XML_meanMarker ); + mrModel.mobVisibilityNonoutliers = rAttribs.getBool( XML_nonoutliers ); + mrModel.mobVisibilityOutliers = rAttribs.getBool( XML_outliers ); return nullptr; case CX_TOKEN( aggregation ): // The schema gives an empty definition for this type?? @@ -845,29 +875,57 @@ ContextHandlerRef LayoutPropsContext::onCreateContext( sal_Int32 nElement, const case CX_TOKEN( binning ): { BinningModel& rB = mrModel.mxBinning.create(); - if (rAttribs.getString( XML_intervalClosed ) == "l") { + if (rAttribs.getString( XML_intervalClosed ) == "l") + { rB.meIntervalClosed = BinningModel::ClosedSide::L; - } else if (rAttribs.getString( XML_intervalClosed ) == "r") { - rB.meIntervalClosed = BinningModel::ClosedSide::R; - } else { - assert(false); // no other options } - // TODO: Also handle attributes underflow, overflow + else if (rAttribs.getString( XML_intervalClosed ) == "r") + { + rB.meIntervalClosed = BinningModel::ClosedSide::R; + } + // intervalClosed is optional in OOXML chartex + rB.mfUnderflow = rAttribs.getDouble(XML_underflow); + rB.mfOverflow = rAttribs.getDouble(XML_overflow); return new BinningContext( *this, rB ); } case CX_TOKEN( geography ): - // TODO - return nullptr; + { + auto& rGeo = mrModel.mxGeography.emplace(); + std::optional sPT = rAttribs.getString( XML_projectionType ); + if (sPT.has_value()) + rGeo.moeProjectionType = geoProjectionTypeFromString( *sPT ); + std::optional sVR = rAttribs.getString( XML_viewedRegionType ); + if (sVR.has_value()) + rGeo.moeViewedRegionType = geoMappingLevelFromString( *sVR ); + rGeo.mosCultureLanguage = rAttribs.getString( XML_cultureLanguage ); + rGeo.mosCultureRegion = rAttribs.getString( XML_cultureRegion ); + rGeo.mosAttribution = rAttribs.getString( XML_attribution ); + return new GeographyContext( *this, *mrModel.mxGeography ); + } case CX_TOKEN( statistics ): - // TODO + mrModel.mosQuartileMethod = rAttribs.getString( XML_quartileMethod ); return nullptr; case CX_TOKEN( subtotals ): - // TODO - return nullptr; + return this; case CX_TOKEN( extLst ): // TODO return nullptr; } + break; + case CX_TOKEN( subtotals ): + switch( nElement ) + { + case CX_TOKEN( idx ): + { + sal_Int32 nVal = rAttribs.getInteger( XML_val, -1 ); + if (nVal >= 0) + mrModel.maSubtotalIndices.push_back( nVal ); + return nullptr; + } + default: + return nullptr; + } + break; } return ContextBase::onCreateContext( nElement, rAttribs ); } @@ -901,7 +959,15 @@ ContextHandlerRef ChartexSeriesContext::onCreateContext( sal_Int32 nElement, con case CX_TOKEN( dataPt ): return new DataPointContext( *this, mrModel.maPoints.create(false) ); case CX_TOKEN( dataLabels ): - return new DataLabelsContext( *this, mrModel.mxLabels.create(false) ); + { + DataLabelsModel& rLabels = mrModel.mxLabels.create(false); + rLabels.monLabelPos = rAttribs.getToken( XML_pos ); + // set MSO defaults + rLabels.mobShowSerName = false; + rLabels.mobShowCatName = false; + rLabels.mobShowVal = true; + return new DataLabelsContext( *this, rLabels ); + } case CX_TOKEN( dataId ): mrModel.mnDataId = rAttribs.getInteger(XML_val, -1); return nullptr; @@ -911,6 +977,7 @@ ContextHandlerRef ChartexSeriesContext::onCreateContext( sal_Int32 nElement, con mrModel.maAxisIds.push_back( rAttribs.getInteger( XML_val, -1 ) ); return nullptr; } + break; } return SeriesContextBase::onCreateContext( nElement, rAttribs ); } diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx index 93e90d9e882a..545c9fbcc2f8 100644 --- a/oox/source/drawingml/chart/seriesconverter.cxx +++ b/oox/source/drawingml/chart/seriesconverter.cxx @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -72,14 +73,15 @@ namespace { Reference< XLabeledDataSequence > lclCreateLabeledDataSequence( const ConverterRoot& rParent, DataSourceModel* pValues, const OUString& rRole, - TextModel* pTitle = nullptr ) + TextModel* pTitle = nullptr, + DataSourceType eDimType = DataSourceType::UNKNOWN ) { // create data sequence for values Reference< XDataSequence > xValueSeq; if( pValues ) { DataSourceConverter aSourceConv( rParent, *pValues ); - xValueSeq = aSourceConv.createDataSequence( rRole ); + xValueSeq = aSourceConv.createDataSequence( rRole, eDimType ); } // create data sequence for title @@ -816,12 +818,28 @@ SeriesConverter::~SeriesConverter() Reference< XLabeledDataSequence > SeriesConverter::createCategorySequence( const OUString& rRole ) { - return createLabeledDataSequence(DataSourceType::CATEGORIES, rRole, false); + return createLabeledDataSequence(DataSourceType::STR_CAT, rRole, false); } Reference< XLabeledDataSequence > SeriesConverter::createValueSequence( const OUString& rRole ) { - return createLabeledDataSequence( DataSourceType::VALUES, rRole, true ); + if (mrModel.maSources.has(DataSourceType::NUM_VAL)) + return createLabeledDataSequence( DataSourceType::NUM_VAL, rRole, true ); + + // For chartex charts, the numeric dimension may not be type "val". + // Try other numeric dimension types. + static const DataSourceType aNumTypes[] = { + DataSourceType::NUM_SIZE, DataSourceType::NUM_COLORVAL, + DataSourceType::NUM_X, DataSourceType::NUM_Y, + }; + for (DataSourceType eType : aNumTypes) + { + if (mrModel.maSources.has(eType)) + return createLabeledDataSequence(eType, rRole, true); + } + + // Nothing found; try NUM_VAL anyway (will return empty sequence) + return createLabeledDataSequence( DataSourceType::NUM_VAL, rRole, true ); } Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConverter& rTypeGroup, bool bVaryColorsByPoint ) @@ -903,6 +921,12 @@ Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConve ObjectFormatter& rFormatter = getFormatter(); ObjectType eObjType = rTypeGroup.getSeriesObjectType(); bool bMSO2007Doc = getFilter().isMSO2007Document(); + + if (mrModel.mxShapeProp.is()) + { + aSeriesProp.setProperty(PROP_HasExplicitFill, true); + } + if( rTypeInfo.mbPictureOptions ) rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(bMSO2007Doc), eObjType, mrModel.mnIndex ); else @@ -944,6 +968,10 @@ Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConve aPointConv.convertFromModel( xDataSeries, rTypeGroup, mrModel ); } + // Track whether the series itself had data labels (not inherited from type group) + if (mrModel.mxLabels.is()) + aSeriesProp.setProperty(PROP_HasDataLabels, true); + /* Series data label settings. If and only if the series does not contain a c:dLbls element, then the c:dLbls element of the parent chart type is used (data label settings of the parent chart type are *not* merged @@ -954,7 +982,7 @@ Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConve if( xLabels->maNumberFormat.maFormatCode.isEmpty() ) { // Use number format code from Value series - DataSourceModel* pValues = mrModel.maSources.get( DataSourceType::VALUES ).get(); + DataSourceModel* pValues = mrModel.maSources.get( DataSourceType::NUM_VAL ).get(); if( pValues ) xLabels->maNumberFormat.maFormatCode = pValues->mxDataSeq->maFormatCode; } @@ -963,14 +991,63 @@ Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConve } // Layout properties - if (mrModel.mxLayoutPr.is() && mrModel.mxLayoutPr->mxBinning.is()) { - ModelRef xBinning = mrModel.mxLayoutPr->mxBinning; + if (mrModel.mxLayoutPr.is()) + { + SeriesModel::LayoutPropsRef &rLPR = mrModel.mxLayoutPr; + if (rLPR->mxBinning.is()) { + ModelRef xBinning = rLPR->mxBinning; - if (xBinning->meIntervalClosed) { - sal_uInt32 nBinSideChar = xBinning->meIntervalClosed.value() == - BinningModel::ClosedSide::L ? 'l' : 'r'; - aSeriesProp.setProperty(PROP_IntervalClosed, nBinSideChar); + if (xBinning->meIntervalClosed) { + sal_uInt32 nBinSideChar = xBinning->meIntervalClosed.value() == + BinningModel::ClosedSide::L ? 'l' : 'r'; + aSeriesProp.setProperty(PROP_IntervalClosed, nBinSideChar); + } } + // chartex series layout visibility + if (rLPR->mobVisibilityConnectorLines.has_value()) + aSeriesProp.setProperty(PROP_ConnectorLines, rLPR->mobVisibilityConnectorLines.value()); + if (rLPR->mobVisibilityMeanLine.has_value()) + aSeriesProp.setProperty(PROP_MeanLine, rLPR->mobVisibilityMeanLine.value()); + if (rLPR->mobVisibilityMeanMarker.has_value()) + aSeriesProp.setProperty(PROP_MeanMarker, rLPR->mobVisibilityMeanMarker.value()); + if (rLPR->mobVisibilityNonoutliers.has_value()) + aSeriesProp.setProperty(PROP_Nonoutliers, rLPR->mobVisibilityNonoutliers.value()); + if (rLPR->mobVisibilityOutliers.has_value()) + aSeriesProp.setProperty(PROP_Outliers, rLPR->mobVisibilityOutliers.value()); + + // chartex other series layout properties: parentLabelLayout, regionLabelLayout, statistics, subtotals + if (rLPR->mosParentLabelLayout.has_value()) + aSeriesProp.setProperty(PROP_ParentLabelLayout, rLPR->mosParentLabelLayout.value()); + if (rLPR->mosRegionLabelLayout.has_value()) + aSeriesProp.setProperty(PROP_RegionLabelLayout, rLPR->mosRegionLabelLayout.value()); + if (rLPR->mosQuartileMethod.has_value()) + aSeriesProp.setProperty(PROP_QuartileMethod, rLPR->mosQuartileMethod.value()); + if (!rLPR->maSubtotalIndices.empty()) + aSeriesProp.setProperty(PROP_SubtotalIndices, + comphelper::containerToSequence(rLPR->maSubtotalIndices)); + + if (rLPR->mxGeography.has_value()) + { + aSeriesProp.setProperty(PROP_HasGeography, true); + convertGeography(*rLPR->mxGeography, aSeriesProp); + } + } + + // Chartex only: preserve the cx:axisId list from the series so export + // can emit the matching cx:axisId children and the right number of + // cx:axis elements. + if (!mrModel.maAxisIds.empty()) + { + aSeriesProp.setProperty(PROP_ChartexAxisIds, + comphelper::containerToSequence(mrModel.maAxisIds)); + } + + // Chartex only: preserve cx:series/@ownerIdx so export emits the same + // attribute and suppresses cx:dataId for this series. + if (mrModel.monOwnerIdx.has_value()) + { + aSeriesProp.setProperty(PROP_ChartexOwnerIdx, + mrModel.monOwnerIdx.value()); } return xDataSeries; @@ -983,7 +1060,7 @@ Reference< XLabeledDataSequence > SeriesConverter::createLabeledDataSequence( { DataSourceModel* pValues = mrModel.maSources.get( eSourceType ).get(); TextModel* pTitle = bUseTextLabel ? mrModel.mxText.get() : nullptr; - return lclCreateLabeledDataSequence( *this, pValues, rRole, pTitle ); + return lclCreateLabeledDataSequence( *this, pValues, rRole, pTitle, eSourceType ); } } // namespace oox diff --git a/oox/source/drawingml/chart/seriesmodel.cxx b/oox/source/drawingml/chart/seriesmodel.cxx index bad98728c239..d7a2d845db36 100644 --- a/oox/source/drawingml/chart/seriesmodel.cxx +++ b/oox/source/drawingml/chart/seriesmodel.cxx @@ -112,12 +112,13 @@ BinningModel::BinningModel() : { } -SeriesModel::SeriesModel(bool bMSO2007Doc) : +SeriesModel::SeriesModel(bool bMSO2007Doc, sal_Int32 nTypeId) : mnExplosion( 0 ), mnIndex( -1 ), mnMarkerSize( 5 ), mnMarkerSymbol( XML_auto ), mnOrder( -1 ), + mnTypeId(nTypeId), mnDataId(-1), mbBubble3d( !bMSO2007Doc ), mbInvertNeg( !bMSO2007Doc ), diff --git a/oox/source/drawingml/chart/titleconverter.cxx b/oox/source/drawingml/chart/titleconverter.cxx index f26cc75a966e..2c65bbe3bb64 100644 --- a/oox/source/drawingml/chart/titleconverter.cxx +++ b/oox/source/drawingml/chart/titleconverter.cxx @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -65,7 +66,7 @@ Reference< XDataSequence > TextConverter::createDataSequence( const OUString& rR if( mrModel.mxDataSeq.is() ) { DataSequenceConverter aDataSeqConv( *this, *mrModel.mxDataSeq ); - xDataSeq = aDataSeqConv.createDataSequence( rRole ); + xDataSeq = aDataSeqConv.createDataSequence( rRole, DataSourceType::UNKNOWN ); } return xDataSeq; } @@ -186,7 +187,7 @@ TitleConverter::~TitleConverter() { } -void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx ) +void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType, ChartType eCT, sal_Int32 nMainIdx, sal_Int32 nSubIdx ) { if( !rxTitled.is() ) return; @@ -209,6 +210,10 @@ void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, con PropertySet aPropSet( xTitle ); getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, eObjType ); + if (eCT == ChartType::CX && mrModel.mxShapeProp.is()) { + aPropSet.setProperty(PROP_HasExplicitSpPr, true); + } + // frame rotation OSL_ENSURE( !mrModel.mxTextProp || !rText.mxTextBody, "TitleConverter::convertFromModel - multiple text properties" ); ModelRef< TextBody > xTextProp = mrModel.mxTextProp.is() ? mrModel.mxTextProp : rText.mxTextBody; @@ -231,7 +236,7 @@ LegendConverter::~LegendConverter() { } -void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram ) +void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, ChartType eCT ) { if( !rxDiagram.is() ) return; @@ -254,7 +259,7 @@ void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram ) cssc2::LegendPosition eLegendPos = cssc2::LegendPosition_LINE_END; cssc::ChartLegendExpansion eLegendExpand = cssc::ChartLegendExpansion_CUSTOM; RelativePosition eRelPos; - bool bTopRight=false; + bool bTopRight = false; switch( mrModel.mnPosition ) { case XML_l: @@ -267,9 +272,9 @@ void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram ) break; case XML_tr: // top-right not supported eRelPos.Primary = 1; - eRelPos.Secondary =0; + eRelPos.Secondary = 0; eRelPos.Anchor = Alignment_TOP_RIGHT; - bTopRight=true; + bTopRight = true; break; case XML_t: eLegendPos = cssc2::LegendPosition_PAGE_START; @@ -280,7 +285,7 @@ void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram ) eLegendExpand = cssc::ChartLegendExpansion_WIDE; break; } - bool bManualLayout=false; + bool bManualLayout = false; // manual positioning and size if( mrModel.mxLayout ) { @@ -298,12 +303,16 @@ void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram ) aPropSet.setProperty( PROP_Expansion, eLegendExpand ); if (bTopRight && !bManualLayout) - aPropSet.setProperty( PROP_RelativePosition , Any(eRelPos)); + aPropSet.setProperty( PROP_RelativePosition, Any(eRelPos)); aPropSet.setProperty(PROP_Overlay, mrModel.mbOverlay); if (mrModel.maLegendEntries.size() > 0) legendEntriesFormatting(rxDiagram); + + if (eCT == ChartType::CX && mrModel.mxShapeProp.is()) { + aPropSet.setProperty(PROP_HasExplicitSpPr, true); + } } catch( Exception& ) { diff --git a/oox/source/drawingml/chart/typegroupconverter.cxx b/oox/source/drawingml/chart/typegroupconverter.cxx index 2e2868ef1bbd..0ffb0cdba06a 100644 --- a/oox/source/drawingml/chart/typegroupconverter.cxx +++ b/oox/source/drawingml/chart/typegroupconverter.cxx @@ -19,6 +19,10 @@ #include +#include +#include +#include +#include #include #include #include @@ -81,37 +85,39 @@ const char SERVICE_CHART2_REGIONMAP[] = "com.sun.star.chart2.RegionMapChartType" const char SERVICE_CHART2_SUNBURST[] = "com.sun.star.chart2.SunburstChartType"; const char SERVICE_CHART2_TREEMAP[] = "com.sun.star.chart2.TreemapChartType"; const char SERVICE_CHART2_WATERFALL[] = "com.sun.star.chart2.WaterfallChartType"; +const char SERVICE_CHART2_HISTO[] = "com.sun.star.chart2.HistogramChartType"; namespace csscd = css::chart::DataLabelPlacement; const TypeGroupInfo spTypeInfos[] = { - // type-id type-category service varied-point-color default label pos polar area2d 1stvis xcateg swap stack picopt - { TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true }, - { TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, true, true, true }, - { TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, true, false, true, false }, - { TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, false, true, false, true, false, true, false }, - { TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, false, false, false, true, false, true, false }, - { TYPEID_RADARLINE, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, false, false, true, false, false, false }, - { TYPEID_RADARAREA, TYPECATEGORY_RADAR, SERVICE_CHART2_FILLEDNET, VARPOINTMODE_NONE, csscd::OUTSIDE, true, true, false, true, false, false, false }, - { TYPEID_PIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false }, - { TYPEID_DOUGHNUT, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, false, true, false, false, false }, - { TYPEID_OFPIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false }, - { TYPEID_SCATTER, TYPECATEGORY_SCATTER, SERVICE_CHART2_SCATTER, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, false, false, false, false }, - { TYPEID_BUBBLE, TYPECATEGORY_SCATTER, SERVICE_CHART2_BUBBLE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, true, false, false, false, false, false }, - { TYPEID_SURFACE, TYPECATEGORY_SURFACE, SERVICE_CHART2_SURFACE, VARPOINTMODE_NONE, csscd::RIGHT, false, true, false, true, false, false, false }, - { TYPEID_FUNNEL, TYPECATEGORY_FUNNEL, SERVICE_CHART2_FUNNEL, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false }, - { TYPEID_BOXWHISKER,TYPECATEGORY_BOXWHISKER, SERVICE_CHART2_BOXWHISKER, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false }, - { TYPEID_CLUSTEREDCOLUMN,TYPECATEGORY_CLUSTEREDCOLUMN, SERVICE_CHART2_CLUSTEREDCOLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false }, - { TYPEID_PARETOLINE,TYPECATEGORY_PARETOLINE, SERVICE_CHART2_PARETOLINE, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false }, - { TYPEID_REGIONMAP, TYPECATEGORY_REGIONMAP, SERVICE_CHART2_REGIONMAP, VARPOINTMODE_NONE, csscd::OUTSIDE, false, true, false, true, false, false, false }, - { TYPEID_SUNBURST, TYPECATEGORY_SUNBURST, SERVICE_CHART2_SUNBURST, VARPOINTMODE_MULTI, csscd::OUTSIDE, false, true, false, true, false, false, false }, - { TYPEID_TREEMAP, TYPECATEGORY_TREEMAP, SERVICE_CHART2_TREEMAP, VARPOINTMODE_MULTI, csscd::OUTSIDE, false, true, false, true, false, false, false }, - { TYPEID_WATERFALL, TYPECATEGORY_WATERFALL, SERVICE_CHART2_WATERFALL, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false } + // type-id type-category service varied-point-color default label pos polar area2d 1stvis xcateg swap stack picopt shftcat 3dshftcat + { TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, true, true }, + { TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, true, true, true, true, true }, + { TYPEID_HISTO, TYPECATEGORY_HISTO, SERVICE_CHART2_HISTO, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, false, false}, + { TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, true, false, true, false, true, false}, + { TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, false, true, false, true, false, true, false, false, false}, + { TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, false, false, false, true, false, true, false, true, true }, + { TYPEID_RADARLINE, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, false, false, true, false, false, false, false, false}, + { TYPEID_RADARAREA, TYPECATEGORY_RADAR, SERVICE_CHART2_FILLEDNET, VARPOINTMODE_NONE, csscd::OUTSIDE, true, true, false, true, false, false, false, false, false}, + { TYPEID_PIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false, false, false}, + { TYPEID_DOUGHNUT, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, false, true, false, false, false, false, false}, + { TYPEID_OFPIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, true, true, true, true, false, false, false, false, false}, + { TYPEID_SCATTER, TYPECATEGORY_SCATTER, SERVICE_CHART2_SCATTER, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, false, false, false, false, false, false}, + { TYPEID_BUBBLE, TYPECATEGORY_SCATTER, SERVICE_CHART2_BUBBLE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, true, false, false, false, false, false, false, false}, + { TYPEID_SURFACE, TYPECATEGORY_SURFACE, SERVICE_CHART2_SURFACE, VARPOINTMODE_NONE, csscd::RIGHT, false, true, false, true, false, false, false, false, false}, + { TYPEID_FUNNEL, TYPECATEGORY_FUNNEL, SERVICE_CHART2_FUNNEL, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, true, false, false, true, false}, + { TYPEID_BOXWHISKER,TYPECATEGORY_BOXWHISKER, SERVICE_CHART2_BOXWHISKER, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false}, + { TYPEID_CLUSTEREDCOLUMN,TYPECATEGORY_CLUSTEREDCOLUMN, SERVICE_CHART2_CLUSTEREDCOLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false}, + { TYPEID_PARETOLINE,TYPECATEGORY_PARETOLINE, SERVICE_CHART2_PARETOLINE, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false}, + { TYPEID_REGIONMAP, TYPECATEGORY_REGIONMAP, SERVICE_CHART2_REGIONMAP, VARPOINTMODE_NONE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false}, + { TYPEID_SUNBURST, TYPECATEGORY_SUNBURST, SERVICE_CHART2_SUNBURST, VARPOINTMODE_MULTI, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false}, + { TYPEID_TREEMAP, TYPECATEGORY_TREEMAP, SERVICE_CHART2_TREEMAP, VARPOINTMODE_MULTI, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false}, + { TYPEID_WATERFALL, TYPECATEGORY_WATERFALL, SERVICE_CHART2_WATERFALL, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, false, false, false, false} }; const TypeGroupInfo saUnknownTypeInfo = - { TYPEID_UNKNOWN, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true }; + { TYPEID_UNKNOWN, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, false, false}; const TypeGroupInfo& lclGetTypeInfoFromTypeId( TypeId eTypeId ) { @@ -215,6 +221,15 @@ TypeGroupConverter::TypeGroupConverter( const ConverterRoot& rParent, TypeGroupM default:; } + // In OOXML chartex, histogram is represented as clusteredColumn with + // . The decision whether this + // is a histogram or the clusteredColumn half of a paretoLine compound chart + // is made by the plot-area converter, which has sibling type-group visibility. + if (eTypeId == TYPEID_CLUSTEREDCOLUMN && mrModel.mbForceHistogram) + { + eTypeId = TYPEID_HISTO; + } + // set the chart type info struct for the current chart type maTypeInfo = lclGetTypeInfoFromTypeId( eTypeId ); } @@ -313,18 +328,33 @@ Reference< XLabeledDataSequence > TypeGroupConverter::createCategorySequence() first series, even if it was empty. */ for (auto const& elem : mrModel.maSeries) { - if( elem->maSources.has( DataSourceType::CATEGORIES ) ) + if( elem->maSources.has( DataSourceType::STR_CAT ) ) { SeriesConverter aSeriesConv(*this, *elem); xLabeledSeq = aSeriesConv.createCategorySequence( u"categories"_ustr ); if (xLabeledSeq.is()) break; } - else if( nMaxValues <= 0 && elem->maSources.has( DataSourceType::VALUES ) ) + else if( nMaxValues <= 0 ) { - DataSourceModel *pValues = elem->maSources.get( DataSourceType::VALUES ).get(); - if( pValues->mxDataSeq.is() ) - nMaxValues = pValues->mxDataSeq->maData.size(); + // Check all numeric dimension types for point count + static const DataSourceType aNumTypes[] = { + DataSourceType::NUM_VAL, DataSourceType::NUM_SIZE, + DataSourceType::NUM_COLORVAL, DataSourceType::NUM_X, + DataSourceType::NUM_Y, + }; + for (DataSourceType eType : aNumTypes) + { + if (elem->maSources.has(eType)) + { + DataSourceModel *pValues = elem->maSources.get(eType).get(); + if (pValues->mxDataSeq.is()) + { + nMaxValues = pValues->mxDataSeq->maData.size(); + break; + } + } + } } } /* n#839727 Create Category Sequence when none are found */ @@ -333,9 +363,9 @@ Reference< XLabeledDataSequence > TypeGroupConverter::createCategorySequence() nMaxValues = 2; typedef RefVector SeriesModelVector; SeriesModelVector::value_type aModel = mrModel.maSeries.get(0); - if (!aModel->maSources.has(DataSourceType::CATEGORIES)) + if (!aModel->maSources.has(DataSourceType::STR_CAT)) { - DataSourceModel &aSrc = aModel->maSources.create( DataSourceType::CATEGORIES ); + DataSourceModel &aSrc = aModel->maSources.create( DataSourceType::STR_CAT ); DataSequenceModel &aSeq = aSrc.mxDataSeq.create(); aSeq.mnPointCount = nMaxValues; for( sal_Int32 i = 0; i < nMaxValues; i++ ) @@ -365,6 +395,63 @@ void TypeGroupConverter::convertFromModel( const Reference< XDiagram >& rxDiagra // additional properties PropertySet aDiaProp( rxDiagram ); PropertySet aTypeProp( xChartType ); + + if (maTypeInfo.meTypeId == TYPEID_HISTO) + { + Reference xTypePropSet(xChartType, UNO_QUERY); + if (xTypePropSet.is()) + { + for (const auto& rxSeriesModel : mrModel.maSeries) + { + if (!rxSeriesModel || !rxSeriesModel->mxLayoutPr.is() + || !rxSeriesModel->mxLayoutPr->mxBinning.is()) + { + continue; + } + + const BinningModel& rBinning = *rxSeriesModel->mxLayoutPr->mxBinning; + + if (rBinning.maBinSizeOrCount) + { + if (std::holds_alternative(*rBinning.maBinSizeOrCount)) + { + xTypePropSet->setPropertyValue( + u"BinWidth"_ustr, + uno::Any(std::get(*rBinning.maBinSizeOrCount))); + xTypePropSet->setPropertyValue( + u"FrequencyType"_ustr, + uno::Any(sal_Int32(1))); + } + else + { + xTypePropSet->setPropertyValue( + u"BinCount"_ustr, + uno::Any(static_cast( + std::get(*rBinning.maBinSizeOrCount)))); + xTypePropSet->setPropertyValue( + u"FrequencyType"_ustr, + uno::Any(sal_Int32(2))); + } + } + if (rBinning.mfUnderflow) + { + xTypePropSet->setPropertyValue(u"UseUnderflowBin"_ustr, uno::Any(true)); + xTypePropSet->setPropertyValue(u"UnderflowBinValue"_ustr, + uno::Any(*rBinning.mfUnderflow)); + } + + if (rBinning.mfOverflow) + { + xTypePropSet->setPropertyValue(u"UseOverflowBin"_ustr, uno::Any(true)); + xTypePropSet->setPropertyValue(u"OverflowBinValue"_ustr, + uno::Any(*rBinning.mfOverflow)); + } + + break; + } + } + } + switch( maTypeInfo.meTypeCategory ) { case TYPECATEGORY_BAR: @@ -509,6 +596,23 @@ void TypeGroupConverter::convertFromModel( const Reference< XDiagram >& rxDiagra xChartTypeCont->addChartType(xChartType); } + if (maTypeInfo.meTypeId == TYPEID_HISTO) + { + Reference const& xChartDoc = getChartDocument(); + Reference xChartTypeManager( + xChartDoc.is() ? xChartDoc->getChartTypeManager() : nullptr); + Reference xTemplateFactory( + xChartTypeManager, UNO_QUERY); + if (xTemplateFactory.is()) + { + Reference xTemplate( + xTemplateFactory->createInstance(u"com.sun.star.chart2.template.Histogram"_ustr), + UNO_QUERY); + if (xTemplate.is()) + xTemplate->changeDiagram(rxDiagram); + } + } + // set existence of bar connector lines at diagram (only in stacked 2D bar charts) if( mrModel.mxSerLines.is() && !mb3dChart && (maTypeInfo.meTypeCategory == TYPECATEGORY_BAR) && (isStacked() || isPercent()) ) aDiaProp.setProperty( PROP_ConnectBars, true ); @@ -703,6 +807,6 @@ void TypeGroupConverter::insertDataSeries( const Reference< XChartType >& rxChar } } -} // namespace oox +} // namespace oox::drawingml::chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/drawingml/color.cxx b/oox/source/drawingml/color.cxx index e366af32900f..c8af21a88ded 100644 --- a/oox/source/drawingml/color.cxx +++ b/oox/source/drawingml/color.cxx @@ -496,7 +496,8 @@ void Color::addChartTintTransformation( double fTint ) void Color::addExcelTintTransformation(double fTint) { - sal_Int32 nValue = std::round(std::abs(fTint) * 100'000.0); + sal_Int32 nValue = getLimitedValue( + std::round(std::abs(fTint) * 100'000.0), 0, MAX_PERCENT); if (fTint > 0.0) { maTransforms.emplace_back(model::TransformationType::LumMod, 100'000 - nValue); diff --git a/oox/source/drawingml/connectorhelper.cxx b/oox/source/drawingml/connectorhelper.cxx index 1b4ee8a51b8c..5d24df505aa9 100644 --- a/oox/source/drawingml/connectorhelper.cxx +++ b/oox/source/drawingml/connectorhelper.cxx @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,92 @@ using namespace ::com::sun::star; +namespace +{ +// Builds the OOXML connector guide points in Hmm, absolute coordinates: the start point, the +// bend/control points and the end point, computed from the adjustment values and the shape's +// size, position, rotation and flip. For bent connectors this polygon is the exact rendered path; +// for curved connectors it is the control polygon the curve follows (which is why the draggable +// handles sit at the same places for both). Returns an empty polygon for connectors that have no +// handles (bentConnector2 / curvedConnector2) and for non-connector shapes. +// This backs both getOOXHandlePositionsHmm() (handles are the inner-segment midpoints) and the +// authored-path import for connectors that cannot be routed (tdf#154074). +basegfx::B2DPolygon getOOXConnectorPointsHmm(const oox::drawingml::ShapePtr& pConnector) +{ + basegfx::B2DPolygon aPolygon; + if (!pConnector) + return aPolygon; + + // Convert string attribute to number. Default 50000 (50%, i.e. the bend at the midpoint) if + // missing, which is the preset default in presetShapeDefinitions.xml. Unit is 1/100000 of the + // shape size. + std::vector aAdjustmentOOXVec; + for (size_t i = 0; i < 3; i++) + { + if (i < pConnector->getConnectorAdjustments().size()) + aAdjustmentOOXVec.push_back(pConnector->getConnectorAdjustments()[i].toInt32()); + else + aAdjustmentOOXVec.push_back(50000); + } + + const double fWidth = pConnector->getSize().Width; // EMU + const double fHeight = pConnector->getSize().Height; // EMU + const double fPosX = pConnector->getPosition().X; // EMU + const double fPosY = pConnector->getPosition().Y; // EMU + + // Points in the untransformed preset, first segment horizontal, start point at (0|0). These + // match the path in presetShapeDefinitions.xml; bent and curved connectors share the same + // points. + const OUString& rName = pConnector->getConnectorName(); + if (rName == u"bentConnector3"_ustr || rName == u"curvedConnector3"_ustr) + { + const double fX1 = aAdjustmentOOXVec[0] / 100000.0 * fWidth; + aPolygon.append({ 0.0, 0.0 }); + aPolygon.append({ fX1, 0.0 }); + aPolygon.append({ fX1, fHeight }); + aPolygon.append({ fWidth, fHeight }); + } + else if (rName == u"bentConnector4"_ustr || rName == u"curvedConnector4"_ustr) + { + const double fX1 = aAdjustmentOOXVec[0] / 100000.0 * fWidth; + const double fY2 = aAdjustmentOOXVec[1] / 100000.0 * fHeight; + aPolygon.append({ 0.0, 0.0 }); + aPolygon.append({ fX1, 0.0 }); + aPolygon.append({ fX1, fY2 }); + aPolygon.append({ fWidth, fY2 }); + aPolygon.append({ fWidth, fHeight }); + } + else if (rName == u"bentConnector5"_ustr || rName == u"curvedConnector5"_ustr) + { + const double fX1 = aAdjustmentOOXVec[0] / 100000.0 * fWidth; + const double fY2 = aAdjustmentOOXVec[1] / 100000.0 * fHeight; + const double fX3 = aAdjustmentOOXVec[2] / 100000.0 * fWidth; + aPolygon.append({ 0.0, 0.0 }); + aPolygon.append({ fX1, 0.0 }); + aPolygon.append({ fX1, fY2 }); + aPolygon.append({ fX3, fY2 }); + aPolygon.append({ fX3, fHeight }); + aPolygon.append({ fWidth, fHeight }); + } + else + return aPolygon; + + // The preset layout is turned into the actual layout by flipping and rotating around the center. + basegfx::B2DHomMatrix aTransform; + const basegfx::B2DPoint aB2DCenter(fWidth / 2.0, fHeight / 2.0); + aTransform.translate(-aB2DCenter); + aTransform *= ConnectorHelper::getConnectorTransformMatrix(pConnector); + aTransform.translate(aB2DCenter); + aTransform.translate(fPosX, fPosY); // make absolute + + aPolygon.transform(aTransform); + + constexpr double fEmuToHmm = o3tl::convert(1.0, o3tl::Length::emu, o3tl::Length::mm100); + aPolygon.transform(basegfx::utils::createScaleB2DHomMatrix(fEmuToHmm, fEmuToHmm)); + return aPolygon; +} +} + // These shapes have no gluepoints defined in their mso_CustomShape struct, thus the gluepoint // adaption to default gluepoints will be done. Other shapes having no gluepoint defined in the // mso_CustomShape struct, have gluepoints in order top-left-bottom-right in OOXML. But the shapes @@ -118,86 +205,13 @@ void ConnectorHelper::getOOXHandlePositionsHmm(const oox::drawingml::ShapePtr& p { rHandlePositions.clear(); - if (!pConnector) - return; - - if (pConnector->getConnectorName() == u"bentConnector2"_ustr - || pConnector->getConnectorName() == u"curvedConnector2"_ustr) - return; // These have no handles. - - // Convert string attribute to number. Set default 50000 if missing. - std::vector aAdjustmentOOXVec; // 1/100000 of shape size - for (size_t i = 0; i < 3; i++) - { - if (i < pConnector->getConnectorAdjustments().size()) - aAdjustmentOOXVec.push_back(pConnector->getConnectorAdjustments()[i].toInt32()); - else - aAdjustmentOOXVec.push_back(50000); - } - - // Handle positions depend on EdgeKind and ShapeSize. bendConnector and curvedConnector use the - // same handle positions. The formulas here correspond to guides in the bendConnector in - // presetShapeDefinitions.xml. - const double fWidth = pConnector->getSize().Width; // EMU - const double fHeight = pConnector->getSize().Height; // EMU - const double fPosX = pConnector->getPosition().X; // EMU - const double fPosY = pConnector->getPosition().Y; // EMU - - if (pConnector->getConnectorName() == u"bentConnector3"_ustr - || pConnector->getConnectorName() == u"curvedConnector3"_ustr) - { - double fAdj1 = aAdjustmentOOXVec[0]; - double fX1 = fAdj1 / 100000.0 * fWidth; - double fY1 = fHeight / 2.0; - rHandlePositions.push_back({ fX1, fY1 }); - } - else if (pConnector->getConnectorName() == u"bentConnector4"_ustr - || pConnector->getConnectorName() == u"curvedConnector4"_ustr) - { - double fAdj1 = aAdjustmentOOXVec[0]; - double fAdj2 = aAdjustmentOOXVec[1]; - double fX1 = fAdj1 / 100000.0 * fWidth; - double fX2 = (fX1 + fWidth) / 2.0; - double fY2 = fAdj2 / 100000.0 * fHeight; - double fY1 = fY2 / 2.0; - rHandlePositions.push_back({ fX1, fY1 }); - rHandlePositions.push_back({ fX2, fY2 }); - } - else if (pConnector->getConnectorName() == u"bentConnector5"_ustr - || pConnector->getConnectorName() == u"curvedConnector5"_ustr) - { - double fAdj1 = aAdjustmentOOXVec[0]; - double fAdj2 = aAdjustmentOOXVec[1]; - double fAdj3 = aAdjustmentOOXVec[2]; - double fX1 = fAdj1 / 100000.0 * fWidth; - double fX3 = fAdj3 / 100000.0 * fWidth; - double fX2 = (fX1 + fX3) / 2.0; - double fY2 = fAdj2 / 100000.0 * fHeight; - double fY1 = fY2 / 2.0; - double fY3 = (fHeight + fY2) / 2.0; - rHandlePositions.push_back({ fX1, fY1 }); - rHandlePositions.push_back({ fX2, fY2 }); - rHandlePositions.push_back({ fX3, fY3 }); - } - - // The presetGeometry has the first segment horizontal and start point left/top with - // coordinates (0|0). Other layouts are done by flipping and rotating. - basegfx::B2DHomMatrix aTransform; - const basegfx::B2DPoint aB2DCenter(fWidth / 2.0, fHeight / 2.0); - aTransform.translate(-aB2DCenter); - aTransform *= getConnectorTransformMatrix(pConnector); - aTransform.translate(aB2DCenter); - - // Make coordinates absolute - aTransform.translate(fPosX, fPosY); - - // Actually transform the handle coordinates - for (auto& rElem : rHandlePositions) - rElem *= aTransform; - - // Convert EMU -> Hmm - for (auto& rElem : rHandlePositions) - rElem /= 360.0; + // The draggable handles sit at the midpoints of the connector's inner segments, i.e. every + // segment except the first (leaving the start point) and the last (entering the end point). + // bentConnector2 / curvedConnector2 have no inner segment and thus no handle. This is the same + // relation getLOBentHandlePositionsHmm() uses to read the handles off the svx edge track. + const basegfx::B2DPolygon aPoints(getOOXConnectorPointsHmm(pConnector)); + for (sal_uInt32 i = 1; i + 2 < aPoints.count(); ++i) + rHandlePositions.push_back((aPoints.getB2DPoint(i) + aPoints.getB2DPoint(i + 1)) / 2.0); } void ConnectorHelper::getLOBentHandlePositionsHmm(const oox::drawingml::ShapePtr& pConnector, @@ -383,27 +397,68 @@ void ConnectorHelper::applyBentHandleAdjustments(oox::drawingml::ShapePtr pConne if (!xPropSet.is()) return; - std::vector aOOXMLHandles; - ConnectorHelper::getOOXHandlePositionsHmm(pConnector, aOOXMLHandles); - std::vector aLODefaultHandles; - ConnectorHelper::getLOBentHandlePositionsHmm(pConnector, aLODefaultHandles); + // A connector that is glued to a shape at both ends has no independently stored path: its route + // follows from the two endpoints, so we let svx route it and transfer the OOXML handle positions + // onto that route as EdgeLine deltas. + // When a connector is not glued at both ends, the file instead stores its actual drawn path + // (preset geometry plus adjustments, in a bounding box that may have been resized by hand). We + // must keep that path as authored rather than re-route it: orthogonal routing is heuristic, so + // re-routing from the endpoints would produce a different shape - it differs between applications + // and changes as the algorithms evolve, and PowerPoint likewise keeps the drawn path and does not + // reroute such connectors when they are moved or resized. So we impose the authored OOXML path + // directly (tdf#154074). + uno::Reference xStartShape; + uno::Reference xEndShape; + xPropSet->getPropertyValue(u"StartShape"_ustr) >>= xStartShape; + xPropSet->getPropertyValue(u"EndShape"_ustr) >>= xEndShape; - if (aOOXMLHandles.size() == aLODefaultHandles.size()) + if (xStartShape.is() && xEndShape.is()) { - bool bUseYforHori - = basegfx::fTools::equalZero(getConnectorTransformMatrix(pConnector).get(0, 0)); - for (size_t i = 0; i < aOOXMLHandles.size(); i++) + std::vector aOOXMLHandles; + ConnectorHelper::getOOXHandlePositionsHmm(pConnector, aOOXMLHandles); + std::vector aLODefaultHandles; + ConnectorHelper::getLOBentHandlePositionsHmm(pConnector, aLODefaultHandles); + + if (aOOXMLHandles.size() == aLODefaultHandles.size()) { - basegfx::B2DVector aDiff(aOOXMLHandles[i] - aLODefaultHandles[i]); - sal_Int32 nDiff; - if ((i == 1 && !bUseYforHori) || (i != 1 && bUseYforHori)) - nDiff = basegfx::fround(aDiff.getY()); - else - nDiff = basegfx::fround(aDiff.getX()); - xPropSet->setPropertyValue("EdgeLine" + OUString::number(i + 1) + "Delta", - uno::Any(nDiff)); + bool bUseYforHori + = basegfx::fTools::equalZero(getConnectorTransformMatrix(pConnector).get(0, 0)); + for (size_t i = 0; i < aOOXMLHandles.size(); i++) + { + basegfx::B2DVector aDiff(aOOXMLHandles[i] - aLODefaultHandles[i]); + sal_Int32 nDiff; + if ((i == 1 && !bUseYforHori) || (i != 1 && bUseYforHori)) + nDiff = basegfx::fround(aDiff.getY()); + else + nDiff = basegfx::fround(aDiff.getX()); + xPropSet->setPropertyValue("EdgeLine" + OUString::number(i + 1) + "Delta", + uno::Any(nDiff)); + } } + return; } + + SdrEdgeObj* pEdgeObj = dynamic_cast(SdrObject::getSdrObjectFromXShape(xConnector)); + if (!pEdgeObj) + return; + + basegfx::B2DPolygon aPolygon(getOOXConnectorPointsHmm(pConnector)); // Hmm + if (aPolygon.count() < 2) + return; + + // The polygon is in Hmm, but the edge track lives in the model's map unit (e.g. Twips in a text + // document). Convert if needed. + const MapUnit eMapUnit = pEdgeObj->getSdrModelFromSdrObject().GetItemPool().GetMetric(0); + if (eMapUnit != MapUnit::Map100thMM) + { + const auto eTo = MapToO3tlLength(eMapUnit); + if (eTo == o3tl::Length::invalid) + return; + const double fConvert(o3tl::convert(1.0, o3tl::Length::mm100, eTo)); + aPolygon.transform(basegfx::utils::createScaleB2DHomMatrix(fConvert, fConvert)); + } + + pEdgeObj->SetEdgeTrackPath(basegfx::B2DPolyPolygon(aPolygon)); } void ConnectorHelper::applyCurvedHandleAdjustments(oox::drawingml::ShapePtr pConnector) diff --git a/oox/source/drawingml/diagram/datamodel_oox.cxx b/oox/source/drawingml/diagram/datamodel_oox.cxx index 26d1d168adc7..1ab4265ac0bd 100644 --- a/oox/source/drawingml/diagram/datamodel_oox.cxx +++ b/oox/source/drawingml/diagram/datamodel_oox.cxx @@ -74,6 +74,7 @@ void DiagramData_oox::writeDiagramReplacement(DrawingML& rOriginalDrawingML, con ::oox::core::XmlFilterBase* pOriginalFB(rOriginalDrawingML.GetFB()); ShapeExport aShapeExport(XML_dsp, rTarget, nullptr, pOriginalFB, rOriginalDrawingML.GetDocumentType(), rOriginalDrawingML.GetTextExport(), true); aShapeExport.setDiagaramExport(true); + aShapeExport.setDiagaramReplacementExport(true); const sal_Int32 nCount(xShapes->getCount()); // write header infos @@ -86,6 +87,13 @@ void DiagramData_oox::writeDiagramReplacement(DrawingML& rOriginalDrawingML, con FSNS(XML_xmlns, XML_a), aNsDml); rTarget->startElementNS(XML_dsp, XML_spTree); + // nvGrpSpPr and grpSpPr elements are mandatory even if empty. + rTarget->startElementNS(XML_dsp, XML_nvGrpSpPr); + rTarget->singleElementNS(XML_dsp, XML_cNvPr, XML_id, "0", XML_name, ""); + rTarget->singleElementNS(XML_dsp, XML_cNvGrpSpPr); + rTarget->endElementNS(XML_dsp, XML_nvGrpSpPr); + rTarget->singleElementNS(XML_dsp, XML_grpSpPr); + for ( sal_Int32 i = 0; i < nCount; ++i ) { uno::Reference< drawing::XShape > xShape; @@ -123,6 +131,10 @@ void DiagramData_oox::writeDiagramData(DrawingML& rOriginalDrawingML, const sax_ FSNS(XML_xmlns, XML_dgm), aNsDmlDiagram, FSNS(XML_xmlns, XML_a), aNsDml); + // need to use a full ShapeExport to get the correct DocumentType support if SW export + ShapeExport aShapeExport(XML_dsp, rTarget, nullptr, pOriginalFB, rOriginalDrawingML.GetDocumentType(), rOriginalDrawingML.GetTextExport(), true); + aShapeExport.setDiagaramExport(true); + // write PointList rTarget->startElementNS(XML_dgm, XML_ptLst); for (auto& rPoint : getPoints()) @@ -181,12 +193,24 @@ void DiagramData_oox::writeDiagramData(DrawingML& rOriginalDrawingML, const sax_ } } + // element is before element + if (bWriteFill) + { + rTarget->startElementNS(XML_dgm, XML_spPr); + aShapeExport.WriteFill( xProps, xAssociatedShape->getSize()); + + rTarget->endElementNS(XML_dgm, XML_spPr); + } + else + { + // write empty fill + rTarget->singleElementNS(XML_dgm, XML_spPr); + } + if (bWriteText) { rTarget->startElementNS(XML_dgm, XML_t); - DrawingML aTempML(rTarget, pOriginalFB); - aTempML.setDiagaramExport(true); - aTempML.WriteText(xAssociatedShape, false, true, XML_a); + aShapeExport.WriteText(xAssociatedShape, false, true, XML_a); rTarget->endElementNS(XML_dgm, XML_t); } else @@ -211,22 +235,6 @@ void DiagramData_oox::writeDiagramData(DrawingML& rOriginalDrawingML, const sax_ } } - if (bWriteFill) - { - rTarget->startElementNS(XML_dgm, XML_spPr); - - DrawingML aTempML(rTarget, pOriginalFB); - aTempML.setDiagaramExport(true); - aTempML.WriteFill( xProps, xAssociatedShape->getSize()); - - rTarget->endElementNS(XML_dgm, XML_spPr); - } - else - { - // write empty fill - rTarget->singleElementNS(XML_dgm, XML_spPr); - } - rTarget->endElementNS(XML_dgm, XML_pt); } @@ -255,17 +263,30 @@ void DiagramData_oox::writeDiagramData(DrawingML& rOriginalDrawingML, const sax_ if (xBgShape.is()) { - // if we have the BGShape as XShape, export using a temp DrawingML which uses - // the target file combined with the XmlFilterBase representing the ongoing Diagram export - DrawingML aTempML(rTarget, pOriginalFB); - aTempML.setDiagaramExport(true); + // use created temporary ShapeExport with correct DocumentType uno::Reference xProps(xBgShape, uno::UNO_QUERY); - aTempML.WriteFill( xProps, xBgShape->getSize()); + aShapeExport.WriteFill( xProps, xBgShape->getSize()); } rTarget->endElementNS(XML_dgm, XML_bg); - rTarget->singleElementNS(XML_dgm, XML_whole); + bool bBGLineStyleWritten(false); + if (xBgShape.is()) + { + uno::Reference xProps(xBgShape, uno::UNO_QUERY); + bBGLineStyleWritten = xProps->getPropertyValue(u"LineStyle"_ustr) != drawing::LineStyle_NONE; + + if (bBGLineStyleWritten) + { + rTarget->startElementNS(XML_dgm, XML_whole); + aShapeExport.WriteOutline( xProps ); + // aShapeExport.WriteLineArrow( xProps, false); + rTarget->endElementNS(XML_dgm, XML_whole); + } + } + + if (!bBGLineStyleWritten) + rTarget->singleElementNS(XML_dgm, XML_whole); // write ExtList & it's contents // Note: I *tried* to use XML_dsp and xmlns:dsp, but these are not defined, thus @@ -291,12 +312,14 @@ void DiagramData_oox::writeDiagramData(DrawingML& rOriginalDrawingML, const sax_ DiagramData_oox::DiagramData_oox() : svx::diagram::DiagramData_svx() , mpBackgroundShapeFillProperties( std::make_shared() ) +, mpBackgroundShapeLineProperties( std::make_shared() ) { } DiagramData_oox::DiagramData_oox(DiagramData_oox const& rSource) : svx::diagram::DiagramData_svx(rSource) , mpBackgroundShapeFillProperties(rSource.mpBackgroundShapeFillProperties) +, mpBackgroundShapeLineProperties(rSource.mpBackgroundShapeLineProperties) , maPointShapeMap() { } @@ -304,6 +327,7 @@ DiagramData_oox::DiagramData_oox(DiagramData_oox const& rSource) DiagramData_oox::DiagramData_oox(const boost::property_tree::ptree& rDiagramModel) : svx::diagram::DiagramData_svx(rDiagramModel) , mpBackgroundShapeFillProperties( std::make_shared() ) +, mpBackgroundShapeLineProperties( std::make_shared() ) { } diff --git a/oox/source/drawingml/diagram/datamodel_oox.hxx b/oox/source/drawingml/diagram/datamodel_oox.hxx index 1a0cfbb79758..8fb2010079b3 100644 --- a/oox/source/drawingml/diagram/datamodel_oox.hxx +++ b/oox/source/drawingml/diagram/datamodel_oox.hxx @@ -50,6 +50,7 @@ public: virtual void buildDiagramDataModel(bool bClearOoxShapes); FillPropertiesPtr& getBackgroundShapeFillProperties() { return mpBackgroundShapeFillProperties; } + LinePropertiesPtr& getBackgroundShapeLineProperties() { return mpBackgroundShapeLineProperties; } #ifdef DBG_UTIL virtual void dump() const; #endif @@ -67,6 +68,9 @@ private: // - FillStyle for Diagram Background (empty constructed, may stay empty) FillPropertiesPtr mpBackgroundShapeFillProperties; + // - LineStyle for Diagram Background (empty constructed, may stay empty) + LinePropertiesPtr mpBackgroundShapeLineProperties; + // temporary processing data, deleted when using build(). Association // map between oox::drawingml::Shape and svx::diagram::Point ModelData PointShapeMap maPointShapeMap; diff --git a/oox/source/drawingml/diagram/datamodelcontext.cxx b/oox/source/drawingml/diagram/datamodelcontext.cxx index 34307b9d6d93..62bbfa8c3bbc 100644 --- a/oox/source/drawingml/diagram/datamodelcontext.cxx +++ b/oox/source/drawingml/diagram/datamodelcontext.cxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -330,6 +331,35 @@ private: OoxDiagramDataPtr mpDataModel; }; +// CT_WholeFormatting (Line attributes for BackgroundShape) +class WholeFormattingContext + : public ContextHandler2 +{ +public: + WholeFormattingContext( ContextHandler2Helper const & rParent, OoxDiagramDataPtr const& pModel ) + : ContextHandler2( rParent ) + , mpDataModel( pModel ) + { + assert( pModel && "the data model MUST NOT be NULL" ); + } + + virtual ContextHandlerRef + onCreateContext( sal_Int32 aElementToken, + const AttributeList& rAttribs ) override + { + switch( aElementToken ) + { + case A_TOKEN( ln ): + return new LinePropertiesContext( *this, rAttribs, *mpDataModel->getBackgroundShapeLineProperties(), nullptr, false ); + default: + break; + } + return this; + } +private: + OoxDiagramDataPtr mpDataModel; +}; + } DataModelContext::DataModelContext( ContextHandler2Helper const& rParent, @@ -365,8 +395,7 @@ DataModelContext::onCreateContext( ::sal_Int32 aElement, return new BackgroundFormattingContext( *this, mpDataModel ); case DGM_TOKEN( whole ): // CT_WholeE2oFormatting - // TODO - return nullptr; + return new WholeFormattingContext( *this, mpDataModel ); case DGM_TOKEN( extLst ): case A_TOKEN( ext ): break; diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index a298c3e55b31..7f129ed08d41 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,8 @@ void SmartArtDiagram::createShapeHierarchyFromModel( const ShapePtr & pParentSha pBackground->setSize(pParentShape->getSize()); if (mpData->getBackgroundShapeFillProperties()) pBackground->getFillProperties() = *mpData->getBackgroundShapeFillProperties(); + if (mpData->getBackgroundShapeLineProperties()) + pBackground->getLineProperties() = *mpData->getBackgroundShapeLineProperties(); // create and set ModelID for BackgroundShape to allow later association getData()->setBackgroundShapeModelID(OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8)); @@ -285,9 +288,7 @@ void SmartArtDiagram::resetOOXDomValues(svx::diagram::DomMapFlags aDomMapFlags) bool SmartArtDiagram::checkMinimalDataDoms() const { // check if re-creation is activated - static bool bActivateAdvancedDiagramFeatures(nullptr != std::getenv("ACTIVATE_ADVANCED_DIAGRAM_FEATURES")); - - if (!bActivateAdvancedDiagramFeatures && maDiagramPRDomMap.end() == maDiagramPRDomMap.find(svx::diagram::DomMapFlag::OOXData)) + if (!SdrObject::useAdvancedDiagramFeatures() && maDiagramPRDomMap.end() == maDiagramPRDomMap.find(svx::diagram::DomMapFlag::OOXData)) return false; if (maDiagramPRDomMap.end() == maDiagramPRDomMap.find(svx::diagram::DomMapFlag::OOXLayout)) @@ -312,7 +313,7 @@ void SmartArtDiagram::writeDiagramOOXData(DrawingML& rOriginalDrawingML, uno::Re getData()->writeDiagramData(rOriginalDrawingML, aFS, rDrawingRelId); // this call is *important*, without it xDocBuilder->parse below fails and some strange - // and wrong assertion gets thrown in ~FastSerializerHelper that shall get called + // and wrong assertion gets thrown in ~FastSerializerHelper that shall get called xOutputStream->closeOutput(); #ifdef DBG_UTIL @@ -352,7 +353,7 @@ void SmartArtDiagram::writeDiagramOOXDrawing(DrawingML& rOriginalDrawingML, uno: getData()->writeDiagramReplacement(rOriginalDrawingML, aFS); // this call is *important*, without it xDocBuilder->parse below fails and some strange - // and wrong assertion gets thrown in ~FastSerializerHelper that shall get called + // and wrong assertion gets thrown in ~FastSerializerHelper that shall get called xOutputStream->closeOutput(); #ifdef DBG_UTIL @@ -418,7 +419,7 @@ void SmartArtDiagram::addDiagramModelData(boost::property_tree::ptree& rTarget) // needs to be created. // Similar with OOXDrawing: This contains parts of ModelData, e.g. Text and // Attributes represented by the XShapes/Sdrobjects, so for internal formats - // this is not needed to be saved. This also true for OOXDrawingImageRels + // this is not needed to be saved. This is also true for OOXDrawingImageRels // and OOXDrawingHlinkRels. // We *do* import OOXLayoutDomTree/ModelInfo and this is used in the layouting // mechanism (reLayout), but it is not changed. We could add an export of that @@ -439,7 +440,7 @@ void SmartArtDiagram::addDiagramModelData(boost::property_tree::ptree& rTarget) } using ShapePairs - = std::map, uno::Reference>; + = std::unordered_map, uno::Reference>; void SmartArtDiagram::syncDiagramFontHeights() { diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index ca999d8e440e..98910bd581c5 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -2021,18 +2021,6 @@ bool LayoutNode::setupShape( const SmartArtDiagram& rDgm, const ShapePtr& rShape return true; } -const LayoutNode* LayoutNode::getParentLayoutNode() const -{ - for (LayoutAtomPtr pAtom = getParent(); pAtom; pAtom = pAtom->getParent()) - { - auto pLayoutNode = dynamic_cast(pAtom.get()); - if (pLayoutNode) - return pLayoutNode; - } - - return nullptr; -} - void ShapeAtom::accept( LayoutAtomVisitor& rVisitor ) { rVisitor.visit(*this); diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx index 5053a8174bae..1e5061d745ad 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx @@ -348,8 +348,6 @@ public: { mpExistingShape = pShape; } const ShapePtr& getExistingShape() const { return mpExistingShape; } - const std::vector & getNodeShapes() const - { return mpNodeShapes; } void addNodeShape(const ShapePtr& pShape) { mpNodeShapes.push_back(pShape); } @@ -357,8 +355,6 @@ public: const svx::diagram::Point* pPresNode, sal_Int32 nCurrIdx ) const; - const LayoutNode* getParentLayoutNode() const; - private: VarMap mVariables; OUString msMoveWith; diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx index cd8213433f01..17f7cfc4b722 100644 --- a/oox/source/drawingml/fillproperties.cxx +++ b/oox/source/drawingml/fillproperties.cxx @@ -212,9 +212,8 @@ Reference lclApplyBlackWhiteEffect(const BlipFillProperties& aBlipProp Bitmap aBitmap(aGraphic.GetBitmap()); if (aBitmap.HasAlpha()) { - const AlphaMask aMask(aBitmap.CreateAlphaMask()); + auto [aTmpBmp, aMask] = aBitmap.SplitIntoColorAndAlpha(); - Bitmap aTmpBmp(aBitmap.CreateColorBitmap()); BitmapFilter::Filter(aTmpBmp, BitmapMonochromeFilter{ nThreshold }); aReturnGraphic = ::Graphic(Bitmap(aTmpBmp, aMask)); @@ -264,9 +263,18 @@ Reference< XGraphic > lclCheckAndApplyChangeColorTransform(const BlipFillPropert } } + const ColorChangeKey aKey(aGraphic.ImplGetSharedImpGraphic(), static_cast(nFromColor), static_cast(nToColor), nToTransparence); + Reference xCachedGraphic = rGraphicHelper.getCachedColorChangeGraphic(aKey); + if (xCachedGraphic.is()) + return xCachedGraphic; + uno::Reference xTransformer(aBlipProps.mxFillGraphic, uno::UNO_QUERY); if (xTransformer.is()) - return xTransformer->colorChange(xGraphic, sal_Int32(nFromColor), nTolerance, sal_Int32(nToColor), nToAlpha); + { + uno::Reference xResult = xTransformer->colorChange(xGraphic, static_cast(nFromColor), nTolerance, static_cast(nToColor), nToAlpha); + rGraphicHelper.addGraphicToColorChangeCache(aKey, xResult); + return xResult; + } } } return xGraphic; @@ -443,13 +451,16 @@ void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelp rPropMap.setProperty( ShapeProperty::FillTransparency, maFillColor.getTransparency() ); model::ComplexColor aComplexColor; - if (aFillColor == nPhClr) + // It's a theme color if there's no explicit color given in the + // input, and the resolved color is the same as the placeholder + // color. + if (aFillColor == nPhClr && !moFillType.has_value()) { aComplexColor.setThemeColor(model::convertToThemeColorType(nPhClrTheme)); } else { - aComplexColor = maFillColor.getComplexColor(); + aComplexColor = maFillColor.createComplexColor(rGraphicHelper, nPhClrTheme); OUString sColorName = getBestSolidColor().getSchemeColorName(); sal_Int32 nToken = Color::getColorMapToken(sColorName); if (nToken != -1) @@ -477,6 +488,8 @@ void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelp // convert to BColorStops, check for contained transparency for (const auto& rCandidate : maGradientProps.maGradientStops) { + // TODO: oox::drawingml::Color does not support transforms + // (lumMod, etc). So those get lost at this point. const ::Color aColor(rCandidate.second.getColor(rGraphicHelper, nPhClr)); aColorStops.addStop(rCandidate.first, aColor.getBColor()); bContainsTransparency = bContainsTransparency || rCandidate.second.hasTransparency(); @@ -493,7 +506,7 @@ void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelp } // prepare BGradient with some defaults - // CAUTION: This used awt::Gradient2 before who's empty constructor + // CAUTION: This used awt::Gradient2 before whose empty constructor // (see workdir/UnoApiHeadersTarget/offapi/normal/com/sun/ // star/awt/Gradient.hpp) initializes all to zeros, so reflect // this here. OTOH set all that were set, e.g. Start/EndIntens @@ -652,7 +665,7 @@ void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelp aGraphCrop.Bottom = o3tl::convert(aFillRect.Y2, aOriginalSize.Height, MAX_PERCENT); bool bHasCropValues = aGraphCrop.Left != 0 || aGraphCrop.Right !=0 || aGraphCrop.Top != 0 || aGraphCrop.Bottom != 0; - // Negative GraphicCrop values means "crop" here. + // Negative GraphicCrop values mean "crop" here. bool bNeedCrop = aGraphCrop.Left <= 0 && aGraphCrop.Right <= 0 && aGraphCrop.Top <= 0 && aGraphCrop.Bottom <= 0; if (bHasCropValues) @@ -860,7 +873,7 @@ void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelpe if(mbIsCustomShape) { - // Positive GraphicCrop values means "crop" here. + // Positive GraphicCrop values mean "crop" here. if (aGraphCrop.Left > 0 || aGraphCrop.Right > 0 || aGraphCrop.Top > 0 || aGraphCrop.Bottom > 0) xGraphic = lclCropGraphic(xGraphic, CropQuotientsFromSrcRect(oClipRect)); } @@ -874,7 +887,7 @@ void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelpe rPropMap.setProperty(PROP_FillBitmapMode, BitmapMode_STRETCH); // It is a bitmap filled and rotated graphic. - // When custom shape is rotated, bitmap have to be rotated too. + // When custom shape is rotated, bitmap has to be rotated too. // Only in extruded mode the bitmap is transformed together with the shape if(rPropMap.hasProperty(PROP_RotateAngle) && !mbIsExtruded) { @@ -882,7 +895,7 @@ void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelpe xGraphic = lclRotateGraphic(xGraphic, Degree10(nAngle/10) ); } - // We have not core feature that flips graphic in the shape. + // We have no core feature that flips graphic in the shape. // Here we are applying flip property to bitmap directly. if((bFlipH || bFlipV) && !mbIsExtruded) xGraphic = lclMirrorGraphic(xGraphic, bFlipH, bFlipV ); diff --git a/oox/source/drawingml/fontworkhelpers.cxx b/oox/source/drawingml/fontworkhelpers.cxx index 24ffdf84e808..4d31c0cead30 100644 --- a/oox/source/drawingml/fontworkhelpers.cxx +++ b/oox/source/drawingml/fontworkhelpers.cxx @@ -1304,30 +1304,30 @@ void FontworkHelpers::createCharInteropGrabBagUpdatesFromShapeProps( bHasTransparenceGradient); pGrabBagStack->push(u"gradFill"_ustr); pGrabBagStack->push(u"gsLst"_ustr); - for (auto it = aColorMap.begin(); it != aColorMap.end(); ++it) + for (const auto & [ nPos, rColors ] : aColorMap) { pGrabBagStack->push(u"gs"_ustr); pGrabBagStack->push(u"attributes"_ustr); - pGrabBagStack->addInt32(u"pos"_ustr, (*it).first); + pGrabBagStack->addInt32(u"pos"_ustr, nPos); pGrabBagStack->pop(); - if ((*it).second.TTColor.getThemeColorType() == model::ThemeColorType::Unknown) + if (rColors.TTColor.getThemeColorType() == model::ThemeColorType::Unknown) { pGrabBagStack->push(u"srgbClr"_ustr); pGrabBagStack->push(u"attributes"_ustr); - pGrabBagStack->addString(u"val"_ustr, (*it).second.RGBColor.AsRGBHexString()); + pGrabBagStack->addString(u"val"_ustr, rColors.RGBColor.AsRGBHexString()); pGrabBagStack->pop(); // maCurrentElement:'srgbClr', maPropertyList:'attributes' } else { pGrabBagStack->push(u"schemeClr"_ustr); pGrabBagStack->push(u"attributes"_ustr); - pGrabBagStack->addString( - u"val"_ustr, lcl_getW14MarkupStringForThemeColor((*it).second.TTColor)); + pGrabBagStack->addString(u"val"_ustr, + lcl_getW14MarkupStringForThemeColor(rColors.TTColor)); pGrabBagStack->pop(); // maCurrentElement:'schemeClr', maPropertyList:'attributes' } - lcl_addColorTransformationToGrabBagStack((*it).second.TTColor, pGrabBagStack); + lcl_addColorTransformationToGrabBagStack(rColors.TTColor, pGrabBagStack); pGrabBagStack->pop(); // maCurrentElement:'gs', maPropertyList:'attributes', 'srgbClr' or 'schemeClr' pGrabBagStack->pop(); // maCurrentElement:'gsLst', maPropertyList: at least two 'gs' diff --git a/oox/source/drawingml/graphicshapecontext.cxx b/oox/source/drawingml/graphicshapecontext.cxx index 3e82b9c956f0..1164fb2b2fad 100644 --- a/oox/source/drawingml/graphicshapecontext.cxx +++ b/oox/source/drawingml/graphicshapecontext.cxx @@ -140,6 +140,7 @@ ContextHandlerRef GraphicShapeContext::onCreateContext( sal_Int32 aElementToken, GraphicalObjectFrameContext::GraphicalObjectFrameContext( ContextHandler2Helper& rParent, const ShapePtr& pMasterShapePtr, const ShapePtr& pShapePtr, bool bEmbedShapesInChart ) : ShapeContext( rParent, pMasterShapePtr, pShapePtr ), mbEmbedShapesInChart( bEmbedShapesInChart ), + maName(), mpParent(&rParent) { } @@ -150,7 +151,13 @@ ContextHandlerRef GraphicalObjectFrameContext::onCreateContext( sal_Int32 aEleme { // CT_ShapeProperties case XML_nvGraphicFramePr: // CT_GraphicalObjectFrameNonVisual + return this; + case XML_cNvPr: + { + // read Diagram's name + maName = rAttribs.getStringDefaulted(XML_name); break; + } case XML_xfrm: // CT_Transform2D return new Transform2DContext( *this, rAttribs, *mpShapePtr ); case XML_graphic: // CT_GraphicalObject @@ -164,7 +171,7 @@ ContextHandlerRef GraphicalObjectFrameContext::onCreateContext( sal_Int32 aEleme return new OleObjectGraphicDataContext( *this, mpShapePtr ); else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/diagram" || sUri == "http://purl.oclc.org/ooxml/drawingml/diagram" ) - return new DiagramGraphicDataContext( *this, mpShapePtr ); + return new DiagramGraphicDataContext( *this, mpShapePtr, maName ); else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/chart" || sUri == "http://purl.oclc.org/ooxml/drawingml/chart" ) return new ChartGraphicDataContext( *this, mpShapePtr, mbEmbedShapesInChart ); @@ -277,9 +284,11 @@ void OleObjectGraphicDataContext::onEndElement() } } -DiagramGraphicDataContext::DiagramGraphicDataContext( ContextHandler2Helper const & rParent, const ShapePtr& pShapePtr ) +DiagramGraphicDataContext::DiagramGraphicDataContext( ContextHandler2Helper const & rParent, const ShapePtr& pShapePtr, const OUString& rName ) : ShapeContext( rParent, ShapePtr(), pShapePtr ) { + if (!rName.isEmpty()) + pShapePtr->setName(rName); pShapePtr->setDiagramType(); } diff --git a/oox/source/drawingml/scene3dhelper.cxx b/oox/source/drawingml/scene3dhelper.cxx index 5764ed1a0b53..21b80063e6b8 100644 --- a/oox/source/drawingml/scene3dhelper.cxx +++ b/oox/source/drawingml/scene3dhelper.cxx @@ -366,7 +366,7 @@ void Scene3DHelper::addProjectionGeometryToMap( fFov = std::clamp(fFov, 0.5, 179.5); // 15976 = 25000 * tan(32.5°) as in legacy. Better ideas to calculate the distance are // welcome. - aViewPoint.PositionZ = 15976.0 / tan(basegfx::deg2rad(fFov / 2.0)); + aViewPoint.PositionZ = 15976.0 / tan(basegfx::deg2rad<2>(fFov)); } else aViewPoint.PositionZ = aPrstCameraValuesArray[mnPrstCameraIndex].mfViewPointZ; @@ -748,8 +748,8 @@ void lcl_ApplyShapeRotationToLights(std::vector& rLightDirVe aTransform.rotate(0.0, 0.0, -fZ); aTransform.rotate(0.0, -fY, 0.0); aTransform.rotate(fX, 0.0, 0.0); - for (auto it = rLightDirVec.begin(); it != rLightDirVec.end(); ++it) - (*it) *= aTransform; + for (auto& rDir : rLightDirVec) + rDir *= aTransform; } /** Applies the light rig rotation to the directions of the individual lights diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index 8298cbcca9c4..c034616c6168 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -19,6 +19,9 @@ #include +#include +#include + #include #include #include @@ -84,6 +87,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -102,6 +109,9 @@ #include #include +#include +#include +#include #include #include #include @@ -305,7 +315,7 @@ void Shape::migrateDiagramHelperToNewShape(const ShapePtr& pTarget) if(pTarget->mpDiagramHelper) { - // this should no happen, but if there is already a helper, clean it up + // this should not happen, but if there is already a helper, clean it up delete pTarget->mpDiagramHelper; pTarget->mpDiagramHelper = nullptr; } @@ -437,7 +447,7 @@ void Shape::addShape( if (isWPGChild() && xShape) { - // This is a wps shape and it is the child of the WPG, now copy the + // This is a wps shape and it is the child of the WPG, now copy // the text body properties to the xshape. Reference xChildWPSProperties(xShape, uno::UNO_QUERY); @@ -487,12 +497,32 @@ void Shape::addShape( // set DiagramHelper at SdrObjGroup propagateDiagramHelper(); - // Check if this is the PPTX import, so far converting SmartArt to a non-editable - // metafile is only implemented for DOCX. - bool bPowerPoint = dynamic_cast(&rFilterBase) != nullptr; + // SmartArtToShapes == true means to get the Group while false did + // convert that content to a GraphicObject containing a metafile, + // and false is the default. + // When we have AdvancedDiagramFeatures this destroys part of the model + // that is in that group hosting the diagram and it's hierarchy. + // At the same time there are UnitTests that use false, but still do want + // to export the unchanged diagram, so it is not possible to just + // delete the DiagramHelper_svx again, that would also make the + // original data DomTrees vanish. + // I think best solution is to not convert to graphic object at + // all when AdvancedDiagramFeatures are active, that just makes + // no longer sense when we want to be able to do more with the + // diagram - and is also already deactivated for Draw/Ipress + if (!SdrObject::useAdvancedDiagramFeatures()) + { + // Check if this is the PPTX import, so far converting SmartArt to a non-editable + // metafile is only implemented for DOCX. + bool bPowerPoint = dynamic_cast(&rFilterBase) != nullptr; - if (!officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::get() && !bPowerPoint) - convertSmartArtToMetafile( rFilterBase ); + if (!officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::get() && !bPowerPoint) + convertSmartArtToMetafile( rFilterBase ); + } + // propagateDiagramHelper() already synced and cleared the font + // heights map via syncDiagramFontHeights(). Reset the filter's + // raw pointer so it cannot dangle if the Diagram is freed later. + rFilterBase.setDiagramFontHeights(nullptr); } NamedShapePairs* pNamedShapePairs = rFilterBase.getDiagramFontHeights(); @@ -543,14 +573,19 @@ void Shape::setTextBox(bool bTextBox) mbTextBox = bTextBox; } -void Shape::applyShapeReference( const Shape& rReferencedShape, bool bUseText ) +void Shape::applyShapeReference(const Shape& rReferencedShape, ReferencedShapeText eText) { SAL_INFO("oox.drawingml", "Shape::applyShapeReference: apply '" << rReferencedShape.msId << "' to '" << msId << "'"); - if ( rReferencedShape.mpTextBody && bUseText ) + if ( !rReferencedShape.mpTextBody || eText == ReferencedShapeText::Nothing ) + mpTextBody.reset(); + else if ( eText == ReferencedShapeText::All ) mpTextBody = std::make_shared( *rReferencedShape.mpTextBody ); else - mpTextBody.reset(); + // This constructor takes the text properties and the list style, and leaves the paragraphs + // behind. Sharing the pointer instead would hand those over as well, and dropping the body + // altogether costs the inherited properties, which a placeholder needs to be laid out. + mpTextBody = std::make_shared( rReferencedShape.mpTextBody ); maShapeProperties = rReferencedShape.maShapeProperties; mpShapeRefLinePropPtr = std::make_shared( rReferencedShape.getActualLineProperties(nullptr) ); mpShapeRefFillPropPtr = std::make_shared( rReferencedShape.getActualFillProperties(nullptr, nullptr) ); @@ -900,6 +935,185 @@ void lcl_RotateAtCenter(basegfx::B2DHomMatrix& aTransformation, sal_Int32 nMSORo return; } +/** Reads a as a clip polygon, in the shape's own coordinates and 1/100 mm. + + A placeholder that is clipped to an outline carries that outline as custom geometry, which an + image shape has nowhere to keep - GraphicClipPolyPolygon is where it goes. Only literal + coordinates are read: a path driven by guides or formulas needs the whole custom-shape + machinery, and returning nothing then leaves the shape rectangular, as it was before. + */ +std::optional +lcl_getClipPolygon(CustomShapeProperties& rProperties, const awt::Rectangle& rShapeRect) +{ + const std::vector& rPaths = rProperties.getPath2DList(); + if (rPaths.empty()) + return {}; + + auto readValue = [](const drawing::EnhancedCustomShapeParameter& rParameter, double& rfValue) + { + if (rParameter.Type != drawing::EnhancedCustomShapeParameterType::NORMAL) + return false; + if (double fValue; rParameter.Value >>= fValue) + rfValue = fValue; + else if (sal_Int32 nValue; rParameter.Value >>= nValue) + rfValue = nValue; + else + return false; + return true; + }; + + // The segments of every path arrive in one list, each path's ended by an ENDSUBPATH, while the + // points belong to the path they were read with - so the two are walked in step. + std::vector aPaths; + basegfx::B2DPolyPolygon aPath; + basegfx::B2DPolygon aContour; + size_t nPath = 0; + size_t nPoint = 0; + + auto takePoint = [&](basegfx::B2DPoint& rPoint) + { + if (nPath >= rPaths.size() || nPoint >= rPaths[nPath].parameter.size()) + return false; + const Path2D& rCurrent = rPaths[nPath]; + double fX = 0.0; + double fY = 0.0; + if (rCurrent.w <= 0 || rCurrent.h <= 0 + || !readValue(rCurrent.parameter[nPoint].First, fX) + || !readValue(rCurrent.parameter[nPoint].Second, fY)) + return false; + ++nPoint; + rPoint = basegfx::B2DPoint(fX * rShapeRect.Width / rCurrent.w, + fY * rShapeRect.Height / rCurrent.h); + return true; + }; + + auto endContour = [&]() + { + if (aContour.count()) + { + aContour.setClosed(true); + aPath.append(aContour); + } + aContour.clear(); + }; + + bool bPathIsFilled = true; + + auto endPath = [&]() + { + endContour(); + // A path that paints nothing covers nothing: PowerPoint leaves it out of the clip, which + // three renders differing only in this attribute confirm. How the outline is stroked says + // nothing about the area, so nostroke is not this. + if (aPath.count() && bPathIsFilled) + aPaths.push_back(aPath); + aPath.clear(); + bPathIsFilled = true; + ++nPath; + nPoint = 0; + }; + + for (const drawing::EnhancedCustomShapeSegment& rSegment : rProperties.getSegments()) + { + basegfx::B2DPoint aPoint; + switch (rSegment.Command) + { + case drawing::EnhancedCustomShapeSegmentCommand::MOVETO: + endContour(); + if (!takePoint(aPoint)) + return {}; + aContour.append(aPoint); + break; + case drawing::EnhancedCustomShapeSegmentCommand::LINETO: + for (sal_Int32 i = 0; i < rSegment.Count; ++i) + { + if (!aContour.count() || !takePoint(aPoint)) + return {}; + aContour.append(aPoint); + } + break; + case drawing::EnhancedCustomShapeSegmentCommand::CURVETO: + for (sal_Int32 i = 0; i < rSegment.Count; ++i) + { + basegfx::B2DPoint aFirst; + basegfx::B2DPoint aSecond; + if (!aContour.count() || !takePoint(aFirst) || !takePoint(aSecond) + || !takePoint(aPoint)) + return {}; + aContour.appendBezierSegment(aFirst, aSecond, aPoint); + } + break; + case drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO: + // A quadratic curve is exactly the cubic one whose two controls sit two thirds of + // the way from each end towards the single control the file gives. + for (sal_Int32 i = 0; i < rSegment.Count; ++i) + { + basegfx::B2DPoint aControl; + if (!aContour.count() || !takePoint(aControl) || !takePoint(aPoint)) + return {}; + const basegfx::B2DPoint aFrom(aContour.getB2DPoint(aContour.count() - 1)); + aContour.appendBezierSegment(aFrom + (aControl - aFrom) * (2.0 / 3.0), + aPoint + (aControl - aPoint) * (2.0 / 3.0), + aPoint); + } + break; + case drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH: + endPath(); + break; + case drawing::EnhancedCustomShapeSegmentCommand::NOFILL: + bPathIsFilled = false; + break; + case drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH: + // Shading and stroking say nothing about the area a path covers. + case drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE: + case drawing::EnhancedCustomShapeSegmentCommand::DARKEN: + case drawing::EnhancedCustomShapeSegmentCommand::DARKENLESS: + case drawing::EnhancedCustomShapeSegmentCommand::LIGHTEN: + case drawing::EnhancedCustomShapeSegmentCommand::LIGHTENLESS: + break; + default: + return {}; + } + } + endPath(); + + if (aPaths.empty()) + return {}; + + // The contours of one path are filled by the even-odd rule - two that overlap leave a hole, + // which is what PowerPoint draws - and that is the rule a clip is applied with, so one path is + // kept exactly as it was read. + basegfx::B2DPolyPolygon aClip(aPaths.front()); + if (aPaths.size() > 1) + { + // Paths, in contrast, are filled one by one, so the shape covers what they cover together. + // Combining them needs each path's own area first, which is that even-odd rule spelled out + // as a boolean expression over its contours. + auto contour = [](const basegfx::B2DPolyPolygon& rPath, sal_uInt32 nIndex) + { + // The operations below expect their operands oriented, which is what preparing does. + return basegfx::utils::prepareForPolygonOperation( + basegfx::B2DPolyPolygon(rPath.getB2DPolygon(nIndex))); + }; + + auto areaOf = [&contour](const basegfx::B2DPolyPolygon& rPath) + { + basegfx::B2DPolyPolygon aArea(contour(rPath, 0)); + for (sal_uInt32 i = 1; i < rPath.count(); ++i) + aArea = basegfx::utils::solvePolygonOperationXor(aArea, contour(rPath, i)); + return aArea; + }; + + aClip = areaOf(aPaths.front()); + for (size_t i = 1; i < aPaths.size(); ++i) + aClip = basegfx::utils::solvePolygonOperationOr(aClip, areaOf(aPaths[i])); + } + + drawing::PolyPolygonBezierCoords aCoords; + basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(aClip, aCoords); + return aCoords; +} + Degree100 lcl_MSORotateAngleToAPIAngle(const sal_Int32 nMSORotationAngle) { // Converts a shape rotation angle from MSO to angle for API property RotateAngle @@ -1348,6 +1562,10 @@ Reference< XShape > const & Shape::createAndInsert( { putPropertyToGrabBag(u"mso-sp-macro"_ustr, Any(msMacro)); } + if (!msMacroExtUrl.isEmpty()) + { + putPropertyToGrabBag(u"mso-sp-macro-url"_ustr, Any(msMacroExtUrl)); + } if (!msTextLink.isEmpty()) { putPropertyToGrabBag(u"mso-sp-textlink"_ustr, Any(msTextLink)); @@ -2199,12 +2417,20 @@ Reference< XShape > const & Shape::createAndInsert( aPropertySet.setAnyProperty( PROP_VertOrientPosition, Any( maPosition.Y ) ); } - // Make sure to not set text to placeholders. Doing it here would eventually call - // SvxTextEditSourceImpl::UpdateData, SdrObject::SetEmptyPresObj(false), and that - // would make the object behave like a standard outline object. - // TODO/FIXME: support custom prompt text in placeholders. if (rServiceName == "com.sun.star.presentation.GraphicObjectShape") - mpTextBody.reset(); + { + // A prompt reaches the object through the CustomPromptText property, not as text; what + // a slide's placeholder holds is content. + if (holdsPromptText()) + mpTextBody.reset(); + + // The custom geometry of a picture placeholder is the outline it is clipped to. An + // image shape has no geometry of its own to put it in, so it becomes a clip polygon; + // making the shape a custom shape instead, as a cropped image does, would cost the + // placeholder its identity. + if (auto oClip = lcl_getClipPolygon(*mpCustomShapePropertiesPtr, aShapeRectHmm)) + aPropertySet.setAnyProperty(PROP_GraphicClipPolyPolygon, Any(*oClip)); + } // in some cases, we don't have any text body. if( mpTextBody && ( !pPlaceholder || !mpTextBody->isEmpty() ) ) @@ -2882,23 +3108,19 @@ uno::Sequence< uno::Sequence< uno::Any > > Shape::resolveRelationshipsOfTypeFro auto pxRelListTemp = xRelListTemp.getArray(); for (auto const& imageRel : *xImageRels) { - uno::Sequence diagramRelTuple(3); + uno::Sequence diagramRelTuple(2); auto pdiagramRelTuple = diagramRelTuple.getArray(); - // [0] => RID, [1] => InputStream [2] => extension + // diagramDataRelTuple[0] => RID, + // diagramDataRelTuple[1] => XGraphic OUString sRelId = imageRel.second.maId; pdiagramRelTuple[0] <<= sRelId; OUString sTarget = xImageRels->getFragmentPathFromRelId(sRelId); - uno::Reference xImageInputStrm( - rFilter.openInputStream(sTarget), uno::UNO_SET_THROW); - StreamDataSequence dataSeq; - if (rFilter.importBinaryData(dataSeq, sTarget)) - { - pdiagramRelTuple[1] <<= dataSeq; - } - - pdiagramRelTuple[2] <<= sTarget.copy(sTarget.lastIndexOf(".")); + // changed to no longer hold binary data of graphic, but XGraphic directly + uno::Reference xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic(sTarget); + if (xGraphic) + pdiagramRelTuple[1] <<= xGraphic; pxRelListTemp[counter] = std::move(diagramRelTuple); ++counter; diff --git a/oox/source/drawingml/shapegroupcontext.cxx b/oox/source/drawingml/shapegroupcontext.cxx index 4f78358e9c95..43acd519a971 100644 --- a/oox/source/drawingml/shapegroupcontext.cxx +++ b/oox/source/drawingml/shapegroupcontext.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -99,10 +100,24 @@ ContextHandlerRef ShapeGroupContext::onCreateContext( sal_Int32 aElementToken, c return new ShapeGroupContext( *this, mpGroupShapePtr, std::make_shared( "com.sun.star.drawing.GroupShape" ) ); case XML_sp: // shape case XML_wsp: + { // Don't set default character height for WPS shapes, Writer has its // own way to set the default, and if we don't set it here, editing // properly inherits it. - return new ShapeContext( *this, mpGroupShapePtr, std::make_shared( "com.sun.star.drawing.CustomShape", getBaseToken(aElementToken) == XML_sp ) ); + + auto pShape = std::make_shared( "com.sun.star.drawing.CustomShape", getBaseToken(aElementToken) == XML_sp ); + const OUString aModelID(rAttribs.getStringDefaulted( XML_modelId )); + + // not sure if this is needed in Writer import, it *is* used in Impress import + // pShape->setModelId(aModelID); + + // also set DataModelID to have these also available for the imported + // replacement visualization. This is key to allow changes to + // DiagramHelper model changes + pShape->setDiagramDataModelID(aModelID); + + return new ShapeContext( *this, mpGroupShapePtr, std::move(pShape) ); + } case XML_pic: // CT_Picture return new GraphicShapeContext( *this, mpGroupShapePtr, std::make_shared( "com.sun.star.drawing.GraphicObjectShape" ) ); case XML_graphicFrame: // CT_GraphicalObjectFrame diff --git a/oox/source/drawingml/shapepropertiescontext.cxx b/oox/source/drawingml/shapepropertiescontext.cxx index 619f19ed3387..16814cfc76f2 100644 --- a/oox/source/drawingml/shapepropertiescontext.cxx +++ b/oox/source/drawingml/shapepropertiescontext.cxx @@ -55,6 +55,8 @@ ContextHandlerRef ShapePropertiesContext::onCreateContext( sal_Int32 aElementTok // GeometryGroup case A_TOKEN( custGeom ): // custom geometry "CT_CustomGeometry2D" + // We got a custom geometry, forget the geometry inherited from the placeholder shape. + mrShape.getCustomShapeProperties() = std::make_shared(); return new CustomShapeGeometryContext( *this, *mrShape.getCustomShapeProperties() ); case A_TOKEN( prstGeom ): // preset geometry "CT_PresetGeometry2D" diff --git a/oox/source/drawingml/table/predefined-table-styles.cxx b/oox/source/drawingml/table/predefined-table-styles.cxx index 95d166fd3694..72a8b1907b6b 100644 --- a/oox/source/drawingml/table/predefined-table-styles.cxx +++ b/oox/source/drawingml/table/predefined-table-styles.cxx @@ -18,8 +18,8 @@ using namespace oox::drawingml::table; /* tdf#107604 * There are predefined table styles that have a - * style id (in ppt/slides/slidex.xml) but does not have - * corresponding style definition (ppt/tableStyles.xml). + * style id (in ppt/slides/slidex.xml) but do not have + * a corresponding style definition (ppt/tableStyles.xml). * So we should create those styles here for this case. * There are 74 predefined styles and many different * variables. A style map was created by examining all @@ -228,6 +228,10 @@ void insertBorderLine(TableStylePart& aTableStylePart, sal_Int32 nToken, std::unique_ptr CreateTableStyle(const OUString& styleId) { + auto it = mStyleIdMap.find(styleId); + if (it == mStyleIdMap.end()) + return nullptr; + std::unique_ptr pTableStyle; pTableStyle.reset(new TableStyle()); @@ -424,7 +428,6 @@ std::unique_ptr CreateTableStyle(const OUString& styleId) // Start to handle all style groups. - auto it = mStyleIdMap.find(styleId); OUString style_name = it->second.first; OUString accent_name = it->second.second; diff --git a/oox/source/drawingml/table/tablecell.cxx b/oox/source/drawingml/table/tablecell.cxx index 34467a1e1bce..6fd0c5189d0d 100644 --- a/oox/source/drawingml/table/tablecell.cxx +++ b/oox/source/drawingml/table/tablecell.cxx @@ -412,7 +412,7 @@ void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, cons } } } - if ( ( nRow == 0 ) && ( nColumn == 0 ) ) + if (rProperties.isFirstRow() && rProperties.isFirstCol() && nRow == 0 && nColumn == 0) { applyTableStylePart( rFilterBase, aFillProperties, aTextStyleProps, aLinePropertiesLeft, @@ -425,7 +425,7 @@ void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, cons aLinePropertiesBottomLeftToTopRight, rTable.getNwCell() ); } - if ( ( nRow == nMaxRow ) && ( nColumn == 0 ) ) + if (rProperties.isLastRow() && rProperties.isFirstCol() && nRow == nMaxRow && nColumn == 0) { applyTableStylePart( rFilterBase, aFillProperties, aTextStyleProps, aLinePropertiesLeft, @@ -438,7 +438,7 @@ void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, cons aLinePropertiesBottomLeftToTopRight, rTable.getSwCell() ); } - if ( ( nRow == 0 ) && ( nColumn == nMaxColumn ) ) + if (rProperties.isFirstRow() && rProperties.isLastCol() && nRow == 0 && nColumn == nMaxColumn) { applyTableStylePart( rFilterBase, aFillProperties, aTextStyleProps, aLinePropertiesLeft, @@ -451,7 +451,8 @@ void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, cons aLinePropertiesBottomLeftToTopRight, rTable.getNeCell() ); } - if ( ( nRow == nMaxRow ) && ( nColumn == nMaxColumn ) ) + if (rProperties.isLastRow() && rProperties.isLastCol() && nRow == nMaxRow + && nColumn == nMaxColumn) { applyTableStylePart( rFilterBase, aFillProperties, aTextStyleProps, aLinePropertiesLeft, diff --git a/oox/source/drawingml/textfield.cxx b/oox/source/drawingml/textfield.cxx index 1c9641996cdd..fd48d75b7980 100644 --- a/oox/source/drawingml/textfield.cxx +++ b/oox/source/drawingml/textfield.cxx @@ -54,8 +54,8 @@ TextField::TextField() namespace { -/** instantiate the textfields. Because of semantics difference between - * OpenXML and OpenOffice, some OpenXML field might cause two fields to be created. +/** instantiate the textfields. Because of semantic differences between + * OpenXML and OpenOffice, some OpenXML fields might cause two fields to be created. * @param aFields the created fields. The list is empty if no field has been created. * @param xModel the model * @param sType the OpenXML field type. @@ -215,7 +215,9 @@ SvxDateFormat TextField::getLODateFormat(std::u16string_view rDateTimeType) if( aDateTimeNum.empty() ) // "datetime" return SvxDateFormat::StdSmall; - int nDateTimeNum = o3tl::toInt32(aDateTimeNum); + // "datetimeFigureOut", which is what PowerPoint writes in a date placeholder, is an alias of + // datetime1: MS-OI29500 part 1, 21.1.2.2.4 (fld). + int nDateTimeNum = aDateTimeNum == u"FigureOut" ? 1 : o3tl::toInt32(aDateTimeNum); switch( nDateTimeNum ) { diff --git a/oox/source/drawingml/textparagraphproperties.cxx b/oox/source/drawingml/textparagraphproperties.cxx index 1ad2b5b71869..2b8cd33e27f5 100644 --- a/oox/source/drawingml/textparagraphproperties.cxx +++ b/oox/source/drawingml/textparagraphproperties.cxx @@ -20,6 +20,8 @@ #include #include +#include + #include #include #include @@ -443,20 +445,36 @@ void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase* p if ( nNumberingType != NumberingType::NUMBER_NONE ) { - if ( noParaLeftMargin ) + if ( noFirstLineIndentation ) + { + // DrawingML 'indent' is signed (< 0 hanging, > 0 first-line) and relative to 'marL'. + // editeng's numbering can only represent a bullet that hangs to the left + // (FirstLineOffset <= 0) and never sits at a negative position. Map (marL, indent) the + // way PowerPoint lays it out: clamp the bullet to >= 0 and place the text |indent| to its + // right, so the bullet->text gap survives even when marL < |indent| (e.g. marL == 0). + // This is identical to the previous naive mapping whenever marL >= |indent| (the normal + // hanging bullet); it only corrects the marL < |indent| and positive-indent cases that + // used to collapse the gap (and which feed editeng an out-of-contract numbering rule). + const sal_Int32 nMarL = noParaLeftMargin.value_or(0); + const sal_Int32 nIndent = *noFirstLineIndentation; + const sal_Int32 nAbsIndent = nIndent < 0 ? -nIndent : nIndent; + const sal_Int32 nBulletX = std::max(0, std::min(nMarL, nMarL + nIndent)); + + // Force Paragraph property as zero - impress seems to use the value from previous + // (non) bullet line if not set to zero explicitly :( + aPropSet.setProperty( PROP_ParaLeftMargin, 0); + aPropSet.setProperty( PROP_ParaFirstLineIndent, 0); + rioBulletMap.setProperty( PROP_LeftMargin, nBulletX + nAbsIndent); + rioBulletMap.setProperty( PROP_FirstLineOffset, -nAbsIndent); + noParaLeftMargin.reset(); + noFirstLineIndentation.reset(); + } + else if ( noParaLeftMargin ) { aPropSet.setProperty( PROP_ParaLeftMargin, 0); rioBulletMap.setProperty( PROP_LeftMargin, *noParaLeftMargin); noParaLeftMargin.reset(); } - if ( noFirstLineIndentation ) - { - // Force Paragraph property as zero - impress seems to use the value from previous - // (non) bullet line if not set to zero explicitly :( - aPropSet.setProperty( PROP_ParaFirstLineIndent, 0); - rioBulletMap.setProperty( PROP_FirstLineOffset, *noFirstLineIndentation); - noFirstLineIndentation.reset(); - } if ( nNumberingType != NumberingType::BITMAP && !rioBulletMap.hasProperty( PROP_BulletColor ) && pFilterBase ) rioBulletMap.setProperty( PROP_BulletColor, maTextCharacterProperties.maFillProperties.getBestSolidColor().getColor( pFilterBase->getGraphicHelper())); } diff --git a/oox/source/drawingml/textrun.cxx b/oox/source/drawingml/textrun.cxx index 1160e36e4cf4..40abf899aa0e 100644 --- a/oox/source/drawingml/textrun.cxx +++ b/oox/source/drawingml/textrun.cxx @@ -81,7 +81,7 @@ sal_Int32 TextRun::insertAt( if ( aTextCharacterProps.moHeight.has_value() ) nCharHeight = aTextCharacterProps.moHeight.value(); else - // UNO API has the character height as float, DML has it as int, but in hundreds. + // UNO API has the character height as float, DML has it as int, but in hundredths. aTextCharacterProps.moHeight = static_cast(nDefaultCharHeight * 100); aTextCharacterProps.pushToPropSet( aPropSet, rFilterBase ); diff --git a/oox/source/drawingml/transform2dcontext.cxx b/oox/source/drawingml/transform2dcontext.cxx index 63d197abb81b..25b3129c8d79 100644 --- a/oox/source/drawingml/transform2dcontext.cxx +++ b/oox/source/drawingml/transform2dcontext.cxx @@ -352,7 +352,7 @@ ContextHandlerRef Transform2DContext::onCreateContext( sal_Int32 aElementToken, if (!aXfrmCenter.equal(aPresetCenter)) { - double fAngleRad = basegfx::deg2rad(nAngleDiff / 60000.0); + double fAngleRad = basegfx::deg2rad<60000>(nAngleDiff); basegfx::B2DHomMatrix aRotMatrix( basegfx::utils::createRotateAroundPoint(aPresetCenter, -fAngleRad)); basegfx::B2DPoint aNewCenter(aRotMatrix * aXfrmCenter); diff --git a/oox/source/export/ColorExportUtils.cxx b/oox/source/export/ColorExportUtils.cxx index 86bb2f0298aa..bd4fd987a8ea 100644 --- a/oox/source/export/ColorExportUtils.cxx +++ b/oox/source/export/ColorExportUtils.cxx @@ -45,7 +45,7 @@ sal_Int32 convertThemeColorTypeToExcelThemeNumber(model::ThemeColorType eType) if (eType == model::ThemeColorType::Unknown) return -1; - // Change position of text1 and text2 and background1 and background2 - needed because of an bug in excel, where + // Change position of text1 and text2 and background1 and background2 - needed because of a bug in Excel, where // the text and background index positions are switched. // 0 -> 1, 1 -> 0 // 2 -> 3, 3 -> 2 diff --git a/oox/source/export/DMLPresetShapeExport.cxx b/oox/source/export/DMLPresetShapeExport.cxx index 3e383ac13d8b..f2755731dedc 100644 --- a/oox/source/export/DMLPresetShapeExport.cxx +++ b/oox/source/export/DMLPresetShapeExport.cxx @@ -91,8 +91,6 @@ DMLPresetShapeExporter::~DMLPresetShapeExporter(){ // Do nothing }; -bool DMLPresetShapeExporter::HasHandleValue() const { return m_bHasHandleValues; } - const OUString& DMLPresetShapeExporter::GetShapeType() const { return m_sPresetShapeType; } const css::uno::Sequence>& diff --git a/oox/source/export/ThemeExport.cxx b/oox/source/export/ThemeExport.cxx index 986f804df6e1..e22d6c9f2caf 100644 --- a/oox/source/export/ThemeExport.cxx +++ b/oox/source/export/ThemeExport.cxx @@ -59,11 +59,12 @@ void ThemeExport::write(OUString const& rPath, model::Theme const& rTheme) mpFS->startElementNS(XML_a, XML_themeElements); - const auto& pColorSet = rTheme.getColorSet(); - - mpFS->startElementNS(XML_a, XML_clrScheme, XML_name, pColorSet->getName()); - writeColorSet(rTheme); - mpFS->endElementNS(XML_a, XML_clrScheme); + if (const auto& pColorSet = rTheme.getColorSet()) + { + mpFS->startElementNS(XML_a, XML_clrScheme, XML_name, pColorSet->getName()); + writeColorSet(pColorSet); + mpFS->endElementNS(XML_a, XML_clrScheme); + } model::FontScheme const& rFontScheme = rTheme.getFontScheme(); mpFS->startElementNS(XML_a, XML_fontScheme, XML_name, rFontScheme.getName()); @@ -122,6 +123,11 @@ bool ThemeExport::writeFontScheme(model::FontScheme const& rFontScheme) fillAttrList(aAttrList, rFontScheme.getMajorComplex()); mpFS->singleElementNS(XML_a, XML_cs, aAttrList); } + for (auto const& rSupplementalFont : rFontScheme.getMajorSupplementalFontList()) + { + mpFS->singleElementNS(XML_a, XML_font, XML_script, rSupplementalFont.maScript, XML_typeface, + rSupplementalFont.maTypeface); + } mpFS->endElementNS(XML_a, XML_majorFont); @@ -142,6 +148,11 @@ bool ThemeExport::writeFontScheme(model::FontScheme const& rFontScheme) fillAttrList(aAttrList, rFontScheme.getMinorComplex()); mpFS->singleElementNS(XML_a, XML_cs, aAttrList); } + for (auto const& rSupplementalFont : rFontScheme.getMinorSupplementalFontList()) + { + mpFS->singleElementNS(XML_a, XML_font, XML_script, rSupplementalFont.maScript, XML_typeface, + rSupplementalFont.maTypeface); + } mpFS->endElementNS(XML_a, XML_minorFont); @@ -152,6 +163,7 @@ namespace { constexpr auto constTransformTypeTokenMap = frozen::make_unordered_map({ + { model::TransformationType::SatMod, XML_satMod }, { model::TransformationType::Tint, XML_tint }, { model::TransformationType::Shade, XML_shade }, { model::TransformationType::LumMod, XML_lumMod }, @@ -875,23 +887,19 @@ bool ThemeExport::writeFormatScheme(model::FormatScheme const& rFormatScheme) return true; } -bool ThemeExport::writeColorSet(model::Theme const& rTheme) +void ThemeExport::writeColorSet(std::shared_ptr const& rColorSet) { static constexpr auto constTokenArray = std::to_array( { XML_dk1, XML_lt1, XML_dk2, XML_lt2, XML_accent1, XML_accent2, XML_accent3, XML_accent4, XML_accent5, XML_accent6, XML_hlink, XML_folHlink }); - const auto& pColorSet = rTheme.getColorSet(); - if (!pColorSet) - return false; - for (auto nToken : constTokenArray) { auto iterator = constTokenMap.find(nToken); if (iterator != constTokenMap.end()) { model::ThemeColorType eColorType = iterator->second; - Color aColor = pColorSet->getColor(eColorType); + Color aColor = rColorSet->getColor(eColorType); mpFS->startElementNS(XML_a, nToken); if (!aColor.IsTransparent()) mpFS->singleElementNS(XML_a, XML_srgbClr, XML_val, @@ -911,8 +919,6 @@ bool ThemeExport::writeColorSet(model::Theme const& rTheme) mpFS->endElementNS(XML_a, nToken); } } - - return true; } } // end namespace oox diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index 2d33ffa1569c..c23878a9df91 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -22,13 +22,19 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include +#include +#include +#include #include #include @@ -127,6 +133,7 @@ #include #include +#include using namespace css; using namespace css::uno; @@ -217,8 +224,8 @@ std::vector > > splitDataSeriesByAxis(co rAxisSeriesSeq.realloc(nLength + 1); rAxisSeriesSeq.getArray()[nLength] = xSeries; } - // if the first series attached to secondary axis, then export those series first, which are attached to primary axis - // also the MS Office export every time in this order + // if the first series is attached to the secondary axis, then export those series first which are attached to the primary axis; + // MS Office also exports in this order every time if (aSplitSeries.size() > 1 && nAxisIndexOfFirstSeries == 1) { std::swap(aSplitSeries[0], aSplitSeries[1]); @@ -227,7 +234,6 @@ std::vector > > splitDataSeriesByAxis(co return aSplitSeries; } - } // unnamed namespace static Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( @@ -550,6 +556,8 @@ constexpr auto constChartTypeMap = frozen::make_unordered_mapstartElementNS(XML_mc, XML_Fallback); - pFS->startElementNS(XML_xdr, XML_sp, XML_macro, "", XML_textlink, ""); - pFS->startElementNS(XML_xdr, XML_nvSpPr); - pFS->singleElementNS(XML_xdr, XML_cNvPr, XML_id, "0", XML_name, ""); - pFS->startElementNS(XML_xdr, XML_cNvSpPr); + pFS->startElementNS(nNS, XML_sp, + XML_macro, sax_fastparser::UseIf("", nNS == XML_xdr), + XML_textlink, sax_fastparser::UseIf("", nNS == XML_xdr)); + pFS->startElementNS(nNS, XML_nvSpPr); + pFS->singleElementNS(nNS, XML_cNvPr, XML_id, "0", XML_name, ""); + pFS->startElementNS(nNS, XML_cNvSpPr); pFS->singleElementNS(XML_a, XML_spLocks, XML_noTextEdit, "1"); - pFS->endElementNS(XML_xdr, XML_cNvSpPr); - pFS->endElementNS(XML_xdr, XML_nvSpPr); - pFS->startElementNS(XML_xdr, XML_spPr); + pFS->endElementNS(nNS, XML_cNvSpPr); + + if (nNS == XML_p) + pFS->singleElementNS(nNS, XML_nvPr); + + pFS->endElementNS(nNS, XML_nvSpPr); + pFS->startElementNS(nNS, XML_spPr); pFS->startElementNS(XML_a, XML_xfrm); pFS->singleElementNS(XML_a, XML_off, XML_x, "6600825", XML_y, "2533650"); pFS->singleElementNS(XML_a, XML_ext, XML_cx, "4572000", XML_cy, "2743200"); @@ -887,8 +917,8 @@ static void writeChartexAlternateContent(FSHelperPtr pFS) pFS->singleElementNS(XML_a, XML_prstClr, XML_val, "green"); pFS->endElementNS(XML_a, XML_solidFill); pFS->endElementNS(XML_a, XML_ln); - pFS->endElementNS(XML_xdr, XML_spPr); - pFS->startElementNS(XML_xdr, XML_txBody); + pFS->endElementNS(nNS, XML_spPr); + pFS->startElementNS(nNS, XML_txBody); pFS->singleElementNS(XML_a, XML_bodyPr, XML_vertOverflow, "clip", XML_horzOverflow, "clip"); pFS->singleElementNS(XML_a, XML_lstStyle); pFS->startElementNS(XML_a, XML_p); @@ -903,8 +933,8 @@ static void writeChartexAlternateContent(FSHelperPtr pFS) pFS->endElementNS(XML_a, XML_t); pFS->endElementNS(XML_a, XML_r); pFS->endElementNS(XML_a, XML_p); - pFS->endElementNS(XML_xdr, XML_txBody); - pFS->endElementNS(XML_xdr, XML_sp); + pFS->endElementNS(nNS, XML_txBody); + pFS->endElementNS(nNS, XML_sp); } namespace { @@ -1230,7 +1260,8 @@ void ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nI if (bIsChartex) { pFS->endElementNS(XML_mc, XML_Choice); - writeChartexAlternateContent(pFS); + DocumentType eDocType = GetDocumentType(); + writeChartexAlternateContent(pFS, eDocType); pFS->endElementNS(XML_mc, XML_Fallback); pFS->endElementNS(XML_mc, XML_AlternateContent); @@ -1341,19 +1372,19 @@ void ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nI if (!aCSS->maEntryList.empty()) { // use the stored data in the document model - static const std::map aMethMap { + static constexpr auto aMethMap = frozen::make_unordered_map ({ { model::ColorStyleMethod::CYCLE, "cycle" }, { model::ColorStyleMethod::WITHIN_LINEAR, "withinLinear" }, { model::ColorStyleMethod::ACROSS_LINEAR, "acrossLinear" }, { model::ColorStyleMethod::WITHIN_LINEAR_REVERSED, "withinLinearReversed" }, { model::ColorStyleMethod::ACROSS_LINEAR_REVERSED, "acrossLinearReversed" } - }; + }); for (const model::ColorStyleEntry& rCStyleEntry : aCSS->maEntryList) { pFS->startElement(FSNS(XML_cs, XML_colorStyle), FSNS( XML_xmlns, XML_cs ), pFB->getNamespaceURL(OOX_NS(cs)), FSNS( XML_xmlns, XML_a ), pFB->getNamespaceURL(OOX_NS(dml)), - XML_meth, aMethMap.at(rCStyleEntry.meMethod).c_str(), + XML_meth, aMethMap.at(rCStyleEntry.meMethod), XML_id, OUString::number(rCStyleEntry.mnId)); ThemeExport aTE(mpFB, GetDocumentType(), pFS); @@ -1373,6 +1404,16 @@ void ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nI pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "accent1"); + pFS->singleElement(FSNS(XML_a, XML_schemeClr), + XML_val, "accent2"); + pFS->singleElement(FSNS(XML_a, XML_schemeClr), + XML_val, "accent3"); + pFS->singleElement(FSNS(XML_a, XML_schemeClr), + XML_val, "accent4"); + pFS->singleElement(FSNS(XML_a, XML_schemeClr), + XML_val, "accent5"); + pFS->singleElement(FSNS(XML_a, XML_schemeClr), + XML_val, "accent6"); pFS->endElement(FSNS(XML_cs, XML_colorStyle)); } @@ -1463,25 +1504,38 @@ void ChartExport::exportChartSpace( const Reference< css::chart::XChartDocument FSNS( XML_xmlns, XML_r ), pFB->getNamespaceURL(OOX_NS(officeRel))); } - if( !bIncludeTable ) + if (!bIsChartex) { - // TODO:external data - } - else - { - Reference< XPropertySet > xPropSet(xChartDoc, UNO_QUERY); - Any aNullDate = xPropSet->getPropertyValue("NullDate"); - util::DateTime aDate; - if ((aNullDate >>= aDate) && (aDate.Year == 1904 && aDate.Month == 1 && aDate.Day == 1)) + if( !bIncludeTable ) { - pFS->singleElement(FSNS(XML_c, XML_date1904), XML_val, "1"); + // TODO:external data } else { - pFS->singleElement(FSNS(XML_c, XML_date1904), XML_val, "0"); + Reference< XPropertySet > xPropSet(xChartDoc, UNO_QUERY); + Any aNullDate = xPropSet->getPropertyValue("NullDate"); + util::DateTime aDate; + if ((aNullDate >>= aDate) && (aDate.Year == 1904 && aDate.Month == 1 && aDate.Day == 1)) + { + pFS->singleElement(FSNS(XML_c, XML_date1904), XML_val, "1"); + } + else + { + pFS->singleElement(FSNS(XML_c, XML_date1904), XML_val, "0"); + } } } + Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY ); + mxDiagram.set( xChartDoc->getDiagram() ); + if( xNewDoc.is()) { + mxNewDiagram.set( xNewDoc->getFirstDiagram()); + } + + // We're not to the plotArea yet, but we need some of the stuff that gets + // set up in InitPlotArea() in order to do the chartex data export. + InitPlotArea( ); + // TODO: get the correct editing language if (bIsChartex) { // chartData @@ -1516,7 +1570,7 @@ void ChartExport::exportChartSpace( const Reference< css::chart::XChartDocument // TODO: printSettings // TODO: text properties Reference< XPropertySet > xPropSet = xChartDoc->getArea(); - if( xPropSet.is() ) + if( xPropSet.is() && (!bIsChartex || hasExplicitSpPr(xPropSet)) ) exportShapeProps( xPropSet, nChartNS ); // TODO for chartex @@ -1533,6 +1587,68 @@ void ChartExport::exportChartSpace( const Reference< css::chart::XChartDocument pFS->endElement( FSNS( nChartNS, XML_chartSpace ) ); } +void ChartExport::writeChartDim(const sax_fastparser::FSHelperPtr& pFS, + const ChartDimInfo& rInfo, + bool *bIsCat /* output var: is this category data? */) +{ + sal_Int32 nDimToken = rInfo.bIsNumeric ? FSNS(XML_cx, XML_numDim) : FSNS(XML_cx, XML_strDim); + + if (bIsCat) { + *bIsCat = (rInfo.sDimTypeStr == "cat"); + } + + pFS->startElement(nDimToken, XML_type, rInfo.sDimTypeStr); + + pFS->startElement(FSNS(XML_cx, XML_f)); + pFS->writeEscaped(rInfo.sFormula); + pFS->endElement(FSNS(XML_cx, XML_f)); + + if (!rInfo.sNFormula.isEmpty()) + { + pFS->startElement(FSNS(XML_cx, XML_nf)); + pFS->writeEscaped(rInfo.sNFormula); + pFS->endElement(FSNS(XML_cx, XML_nf)); + } + + pFS->endElement(nDimToken); +} + +ChartExport::ChartDimInfo ChartExport::getChartDimInfo( + const Reference& xSeq) +{ + using namespace oox::drawingml::chart; + ChartDimInfo aInfo; + if (!xSeq.is()) + return aInfo; + Reference xProp(xSeq, uno::UNO_QUERY); + if (!xProp.is()) + return aInfo; + Reference xPropInfo(xProp->getPropertySetInfo()); + if (!xPropInfo.is()) + return aInfo; + + if (GetProperty(xProp, u"ChartExDimType"_ustr)) + { + sal_Int32 nDimType = 0; + mAny >>= nDimType; + auto eDimType = static_cast(nDimType); + if (dataSourceTypeToCx(eDimType, aInfo.bIsNumeric, aInfo.sDimTypeStr)) + aInfo.bHasInfo = true; + } + + if (GetProperty(xProp, u"ChartExFormula"_ustr)) + { + mAny >>= aInfo.sFormula; + } + + if (GetProperty(xProp, u"ChartExNFormula"_ustr)) + { + mAny >>= aInfo.sNFormula; + } + + return aInfo; +} + void ChartExport::exportData_chartex( [[maybe_unused]] const Reference< css::chart::XChartDocument >& xChartDoc) { Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( mxNewDiagram, uno::UNO_QUERY ); @@ -1615,86 +1731,132 @@ void ChartExport::exportData_chartex( [[maybe_unused]] const Reference< css::cha // The data id needs to agree with the id in exportSeries(). See DATA_ID_COMMENT pFS->startElement(FSNS(XML_cx, XML_data), XML_id, OUString::number(nSeriesIndex)); - // .xlsx chartex files seem to have this magical "_xlchart..." string, - // and no explicit data, while .docx and .pptx contain the literal data, - // as well as a ../embeddings file (which LO doesn't seem to produce). - // But there's probably a smarter way to determine which pathway to take - // than based on document type. - if (GetDocumentType() == DOCUMENT_XLSX) { - // Just hard-coding this for now + // For XLSX, chartex files use formula references (e.g. "_xlchart.v1.0") + // rather than literal data. For DOCX/PPTX, literal data is embedded. + // If dimension info was stored during import, use it for both paths. + // + // Try to export stored dimension info from all data sequences. + bool bExportedFromProperties = false; + if (GetDocumentType() == DOCUMENT_XLSX) + { + bool bCatWritten = false; + // Iterate all data sequences and output each dimension + // using the stored chartex properties. + for (sal_Int32 i = 0; i < aSeqCnt.getLength(); ++i) + { + Reference xSeq(aSeqCnt[i]->getValues()); + ChartDimInfo aInfo = getChartDimInfo(xSeq); + if (aInfo.bHasInfo && !aInfo.sFormula.isEmpty()) + { + writeChartDim(pFS, aInfo, &bCatWritten); + bExportedFromProperties = true; + } + } + // We should write at least one set of category data, so + // if we didn't, also check the categories sequence. + // This again is a bit of a hack, due to the lack of + // consistency in where we store data. + if (!bCatWritten) { + if (mxCategoriesValues.is()) + { + ChartDimInfo aCatInfo = getChartDimInfo(mxCategoriesValues); + if (aCatInfo.bHasInfo && !aCatInfo.sFormula.isEmpty()) + { + writeChartDim(pFS, aCatInfo, nullptr); + bExportedFromProperties = true; + } + } + } + } - sal_Int32 nSuffixVal = nSeriesIndex; + if (!bExportedFromProperties && GetDocumentType() == DOCUMENT_XLSX) + { + // Fallback: hard-coded formulas for charts not imported from chartex - // Output category data formula for some chart types. - // (This is completely hacky) - if (eChartType == chart::TYPEID_SUNBURST || - eChartType == chart::TYPEID_TREEMAP) { - pFS->startElement(FSNS(XML_cx, XML_strDim), XML_type, "cat"); + // _xlchart.v1.N is only valid when workbook.xml has a matching hidden + // definedName. For new histograms, write the raw values-y range directly. + if (eChartType == chart::TYPEID_HISTO) + { + OUString aCellRange = xValueSeq.is() ? xValueSeq->getSourceRangeRepresentation() : OUString(); + aCellRange = parseFormula(aCellRange); + + pFS->startElement(FSNS(XML_cx, XML_numDim), XML_type, "val"); + + pFS->startElement(FSNS(XML_cx, XML_f)); + pFS->writeEscaped(aCellRange); + pFS->endElement(FSNS(XML_cx, XML_f)); + + pFS->endElement(FSNS(XML_cx, XML_numDim)); + } + else + { + sal_Int32 nSuffixVal = nSeriesIndex; + + if (eChartType == chart::TYPEID_SUNBURST || + eChartType == chart::TYPEID_TREEMAP) + { + pFS->startElement(FSNS(XML_cx, XML_strDim), XML_type, "cat"); + pFS->startElement(FSNS(XML_cx, XML_f)); + + std::string sFormulaId = "_xlchart.v1."; + sFormulaId.append(std::to_string(nSuffixVal)); + + pFS->writeEscaped(sFormulaId); + + pFS->endElement(FSNS(XML_cx, XML_f)); + pFS->endElement(FSNS(XML_cx, XML_strDim)); + + ++nSuffixVal; + } + + // Set the ST_NumericDimensionType. For some (stupid?) + // reason, MSO requires the value data for sunburst and + // treemap to be type "size", while for most other chart + // types it's of type "val". + std::string sNumDimType; + if (eChartType == chart::TYPEID_SUNBURST || + eChartType == chart::TYPEID_TREEMAP) + { + sNumDimType = "size"; + } + else + { + sNumDimType = "val"; + } + + pFS->startElement(FSNS(XML_cx, XML_numDim), XML_type, + sNumDimType.c_str()); pFS->startElement(FSNS(XML_cx, XML_f)); - std::string sFormulaId = "_xlchart.v1."; + std::string sFormulaId; + switch( eChartType ) + { + case chart::TYPEID_BOXWHISKER: + case chart::TYPEID_CLUSTEREDCOLUMN: + case chart::TYPEID_PARETOLINE: + case chart::TYPEID_SUNBURST: + case chart::TYPEID_TREEMAP: + case chart::TYPEID_WATERFALL: + sFormulaId = "_xlchart.v1."; + break; + case chart::TYPEID_FUNNEL: + sFormulaId = "_xlchart.v2."; + break; + case chart::TYPEID_REGIONMAP: + sFormulaId = "_xlchart.v5."; + break; + default: + assert(false); + break; + } sFormulaId.append(std::to_string(nSuffixVal)); - pFS->writeEscaped(sFormulaId); - pFS->endElement(FSNS(XML_cx, XML_f)); - pFS->endElement(FSNS(XML_cx, XML_strDim)); - - ++nSuffixVal; + pFS->endElement(FSNS(XML_cx, XML_numDim)); } - - // Set the ST_NumericDimensionType. For some (stupid?) - // reason, MSO requires the value data for sunburst and - // treemap to be type "size", while for most other chart - // types it's of type "val". - std::string sNumDimType; - if (eChartType == chart::TYPEID_SUNBURST || - eChartType == chart::TYPEID_TREEMAP) { - sNumDimType = "size"; - } else { - sNumDimType = "val"; - } - - // Now output value data formula - pFS->startElement(FSNS(XML_cx, XML_numDim), XML_type, - sNumDimType.c_str()); - pFS->startElement(FSNS(XML_cx, XML_f)); - - // Set the formula value based on the chart type. This - // is just a hack. It obviously should be based on the - // identifier for the actual data (either as imported or - // created within LO). TODO - std::string sFormulaId; - switch( eChartType ) - { - case chart::TYPEID_BOXWHISKER: - case chart::TYPEID_CLUSTEREDCOLUMN: - case chart::TYPEID_PARETOLINE: - case chart::TYPEID_SUNBURST: - case chart::TYPEID_TREEMAP: - case chart::TYPEID_WATERFALL: - sFormulaId = "_xlchart.v1."; - break; - case chart::TYPEID_FUNNEL: - sFormulaId = "_xlchart.v2."; - break; - case chart::TYPEID_REGIONMAP: - sFormulaId = "_xlchart.v5."; - break; - default: - assert(false); - break; - } - // Append the id value, which seems (?) to be what - // follows the period in the string. E.g., for id=2 we - // might end up with "_xlchart.v1.2" - sFormulaId.append(std::to_string(nSuffixVal)); - - pFS->writeEscaped(sFormulaId); - - pFS->endElement(FSNS(XML_cx, XML_f)); - pFS->endElement(FSNS(XML_cx, XML_numDim)); - } else { // PPTX, DOCX + } + else if (GetDocumentType() != DOCUMENT_XLSX) + { // PPTX, DOCX OUString aCellRange = mxCategoriesValues.is() ? mxCategoriesValues->getSourceRangeRepresentation() : OUString(); #undef OUTPUT_SPLIT_CATEGORIES // do we need this or not? TODO #ifdef OUTPUT_SPLIT_CATEGORIES @@ -1754,14 +1916,27 @@ void ChartExport::exportData_chartex( [[maybe_unused]] const Reference< css::cha // === Output the categories if (bWriteDateCategories) { - std::vector aDateCategories = lcl_getAllValuesFromSequence(xValueSeq); + // The category values live in the categories + // sequence, not the series values. Fall back to + // the value sequence only when no categories are + // present. + std::vector aDateCategories = lcl_getAllValuesFromSequence( + mxCategoriesValues.is() ? mxCategoriesValues : xValueSeq); const sal_Int32 ptCount = aDateCategories.size(); pFS->startElement(FSNS(XML_cx, XML_numDim), XML_type, "x"); // is "x" right? // TODO: check this pFS->startElement(FSNS(XML_cx, XML_f)); - pFS->writeEscaped(aCellRange); + + Reference xSeq(aSeqCnt[0]->getValues()); + ChartDimInfo aInfo = getChartDimInfo(xSeq); + if (aInfo.bHasInfo && !aInfo.sFormula.isEmpty()) { + pFS->writeEscaped(aInfo.sFormula); + } else { + pFS->writeEscaped(aCellRange); + } + pFS->endElement(FSNS(XML_cx, XML_f)); pFS->startElement(FSNS(XML_cx, XML_lvl), @@ -1781,8 +1956,14 @@ void ChartExport::exportData_chartex( [[maybe_unused]] const Reference< css::cha } else { + // The category labels live in the categories + // sequence, not the series values. Fall back to + // the value sequence only when no categories are + // present. std::vector aCategories; - lcl_fillCategoriesIntoStringVector(xValueSeq, aCategories); + lcl_fillCategoriesIntoStringVector( + mxCategoriesValues.is() ? mxCategoriesValues : xValueSeq, + aCategories); const sal_Int32 ptCount = aCategories.size(); // TODO: shouldn't have "cat" hard-coded here: @@ -1790,7 +1971,14 @@ void ChartExport::exportData_chartex( [[maybe_unused]] const Reference< css::cha pFS->startElement(FSNS(XML_cx, XML_strDim), XML_type, "cat"); pFS->startElement(FSNS(XML_cx, XML_f)); - pFS->writeEscaped(aCellRange); + + ChartDimInfo aInfo = getChartDimInfo(mxCategoriesValues.is() ? mxCategoriesValues : xValueSeq); + if (aInfo.bHasInfo && !aInfo.sFormula.isEmpty()) { + pFS->writeEscaped(aInfo.sFormula); + } else { + pFS->writeEscaped(aCellRange); + } + pFS->endElement(FSNS(XML_cx, XML_f)); pFS->startElement(FSNS(XML_cx, XML_lvl), XML_ptCount, OString::number(ptCount)); @@ -1813,7 +2001,16 @@ void ChartExport::exportData_chartex( [[maybe_unused]] const Reference< css::cha // TODO: need to handle XML_multiLvlStrRef according to aCellRange pFS->startElement(FSNS(XML_cx, XML_f)); - pFS->writeEscaped( aCellRange ); + + // Get the stored formula reference + Reference xSeq(aSeqCnt[0]->getValues()); // TODO + ChartDimInfo aInfo = getChartDimInfo(xSeq); + if (aInfo.bHasInfo && !aInfo.sFormula.isEmpty()) { + pFS->writeEscaped(aInfo.sFormula); + } else { + pFS->writeEscaped(aCellRange); + } + pFS->endElement( FSNS( XML_cx, XML_f ) ); ::std::vector< double > aValues = lcl_getAllValuesFromSequence( xValueSeq ); @@ -2015,12 +2212,6 @@ void ChartExport::exportAdditionalShapes( const Reference< css::chart::XChartDoc void ChartExport::exportChart( const Reference< css::chart::XChartDocument >& xChartDoc, bool bIsChartex) { - Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY ); - mxDiagram.set( xChartDoc->getDiagram() ); - if( xNewDoc.is()) { - mxNewDiagram.set( xNewDoc->getFirstDiagram()); - } - // get Properties of ChartDocument bool bHasMainTitle = false; bool bHasLegend = false; @@ -2074,7 +2265,6 @@ void ChartExport::exportChart( const Reference< css::chart::XChartDocument >& xC pFS->singleElement(FSNS(XML_c, XML_autoTitleDeleted), XML_val, "1"); } - InitPlotArea( ); if( mbIs3DChart ) { if (!bIsChartex) { @@ -2346,7 +2536,13 @@ void ChartExport::exportLegend( const Reference< css::chart::XChartDocument >& x } // shape properties - exportShapeProps( xProp, bIsChartex ? XML_cx : XML_c ); + if (bIsChartex) { + if (hasExplicitSpPr(xProp)) { + exportShapeProps( xProp, XML_cx ); + } + } else { + exportShapeProps( xProp, XML_c ); + } // draw-chart:txPr text properties exportTextProps( xProp, bIsChartex ); @@ -2409,8 +2605,9 @@ void ChartExport::exportTitle( const Reference< XShape >& xShape, bool bIsCharte } if (bIsChartex) { - // shape properties - if( xPropSet.is() ) + // shape properties - only when the source had an explicit cx:spPr, + // since the chartex schema makes spPr optional. + if (hasExplicitSpPr(xPropSet)) { exportShapeProps(xPropSet, XML_cx); } @@ -2604,7 +2801,7 @@ void ChartExport::exportPlotArea(const Reference< css::chart::XChartDocument >& pFS->singleElement(FSNS(XML_c, XML_barDir), XML_val, "col"); pFS->singleElement(FSNS(XML_c, XML_grouping), XML_val, "clustered"); pFS->singleElement(FSNS(XML_c, XML_varyColors), XML_val, "0"); - createAxes(true, false, false); + createAxes_chart(true, false); pFS->endElement(FSNS(XML_c, XML_barChart)); } @@ -2654,6 +2851,7 @@ void ChartExport::exportPlotArea(const Reference< css::chart::XChartDocument >& break; } case chart::TYPEID_CLUSTEREDCOLUMN: + case chart::TYPEID_HISTO: { exportChartex( xChartType, "clusteredColumn" ); break; @@ -2770,7 +2968,11 @@ void ChartExport::exportPlotArea(const Reference< css::chart::XChartDocument >& } //Axis Data - exportAxes(bIsChartex); + if (bIsChartex) { + exportAxes_chartex(); + } else { + exportAxes_chart(); + } if (!bIsChartex) { // Data Table @@ -2803,7 +3005,8 @@ void ChartExport::exportPlotArea(const Reference< css::chart::XChartDocument >& { xWallPropSet->setPropertyValue( u"LineStyle"_ustr, uno::Any(drawing::LineStyle_NONE) ); } - exportShapeProps( xWallPropSet, bIsChartex ? XML_cx : XML_c ); + if (!bIsChartex || hasExplicitSpPr(xWallPropSet)) + exportShapeProps( xWallPropSet, bIsChartex ? XML_cx : XML_c ); } } @@ -2913,6 +3116,28 @@ void ChartExport::exportFill( const Reference< XPropertySet >& xPropSet ) if (aTransparenceGradient.StartColor == 0xffffff && aTransparenceGradient.EndColor == 0xffffff) aFillStyle = FillStyle_NONE; } + + model::ComplexColor aComplexColor; + if (GetProperty(xPropSet, u"FillComplexColor"_ustr)) { + uno::Reference xCC; + mAny >>= xCC; + aComplexColor = model::color::getFromXComplexColor(xCC); + } + + // The following restriction to solidFill is not correct. Any color that's + // the default scheme color (e.g., as a gradient fill stop) shouldn't be + // exported. However, we lose transforms on gradient fills (and maybe other + // color usage), so we can't tell what should be equivalent to the default + // scheme color in that context. See FillProperties::pushToPropMap(). So + // play it safe and don't try to handle that here. TODO + if (aFillStyle == FillStyle_SOLID && + aComplexColor.getType() == model::ColorType::Theme && + aComplexColor.getTransformations().empty()) { + // If we're dealing with a theme color, then we don't want to export the + // explicit value. We want it to remain implicit, as a theme. + return; + } + switch( aFillStyle ) { case FillStyle_SOLID: @@ -3156,7 +3381,7 @@ void ChartExport::exportAreaChart( const Reference< chart2::XChartType >& xChart if (splitDataSeries.hasElements()) exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); - createAxes(bPrimaryAxes, false, false); + createAxes_chart(bPrimaryAxes, true); //exportAxesId(bPrimaryAxes); pFS->endElement(FSNS(XML_c, nTypeId)); @@ -3260,7 +3485,7 @@ void ChartExport::exportBarChart(const Reference< chart2::XChartType >& xChartTy } } - createAxes(bPrimaryAxes, false, false); + createAxes_chart(bPrimaryAxes, true); pFS->endElement(FSNS(XML_c, nTypeId)); } @@ -3285,7 +3510,7 @@ void ChartExport::exportBubbleChart( const Reference< chart2::XChartType >& xCha if (splitDataSeries.hasElements()) exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); - createAxes(bPrimaryAxes, false, false); + createAxes_chart(bPrimaryAxes, true); pFS->endElement(FSNS(XML_c, XML_bubbleChart)); } @@ -3303,8 +3528,6 @@ void ChartExport::exportChartex( const Reference< chart2::XChartType >& xChartTy if (!splitDataSeries.hasElements()) continue; - createAxes(true, false, true); - //exportVaryColors(xChartType); exportSeries_chartex(xChartType, splitDataSeries, sTypeName); @@ -3442,7 +3665,7 @@ void ChartExport::exportLineChart( const Reference< chart2::XChartType >& xChart pFS->singleElement(FSNS(XML_c, XML_marker), XML_val, marker); } - createAxes(bPrimaryAxes, true, false); + createAxes_chart(bPrimaryAxes, true); pFS->endElement( FSNS( XML_c, nTypeId ) ); } @@ -3487,7 +3710,7 @@ void ChartExport::exportRadarChart( const Reference< chart2::XChartType >& xChar exportVaryColors(xChartType); bool bPrimaryAxes = true; exportAllSeries(xChartType, bPrimaryAxes); - createAxes(bPrimaryAxes, false, false); + createAxes_chart(bPrimaryAxes, true); pFS->endElement( FSNS( XML_c, XML_radarChart ) ); } @@ -3517,7 +3740,7 @@ void ChartExport::exportScatterChartSeries( const Reference< chart2::XChartType bool bPrimaryAxes = true; if (pSeries) exportSeries_chart(xChartType, *pSeries, bPrimaryAxes); - createAxes(bPrimaryAxes, false, false); + createAxes_chart(bPrimaryAxes, true); //exportAxesId(bPrimaryAxes); pFS->endElement( FSNS( XML_c, XML_scatterChart ) ); @@ -3549,14 +3772,13 @@ void ChartExport::exportStockChart( const Reference< chart2::XChartType >& xChar aSplitDataSeries.push_back({}); } - sal_uInt32 nIdx = 0; for (const auto& splitDataSeries : aSplitDataSeries) { pFS->startElement(FSNS(XML_c, XML_stockChart)); bool bPrimaryAxes = true; if (splitDataSeries.hasElements()) - exportCandleStickSeries(splitDataSeries, bPrimaryAxes, nIdx); + exportCandleStickSeries(splitDataSeries, bPrimaryAxes); // export stock properties Reference< css::chart::XStatisticDisplay > xStockPropProvider(mxDiagram, uno::UNO_QUERY); @@ -3566,7 +3788,7 @@ void ChartExport::exportStockChart( const Reference< chart2::XChartType >& xChar exportUpDownBars(xChartType); } - createAxes(bPrimaryAxes, false, false); + createAxes_chart(bPrimaryAxes, true); pFS->endElement(FSNS(XML_c, XML_stockChart)); } @@ -3641,7 +3863,7 @@ void ChartExport::exportSurfaceChart( const Reference< chart2::XChartType >& xCh exportVaryColors(xChartType); bool bPrimaryAxes = true; exportAllSeries(xChartType, bPrimaryAxes); - createAxes(bPrimaryAxes, false, false); + createAxes_chart(bPrimaryAxes, true); pFS->endElement( FSNS( XML_c, nTypeId ) ); } @@ -3894,7 +4116,28 @@ void ChartExport::exportSeries_chartex( const Reference& xCh if( xSource.is()) { FSHelperPtr pFS = GetFS(); - pFS->startElement(FSNS(XML_cx, XML_series), XML_layoutId, sTypeName); + + // Chartex only: a series may share data with another series in the + // same plotAreaRegion via cx:series/@ownerIdx. When present, the + // schema requires that no cx:dataId child be emitted. + std::optional oOwnerIdx; + { + Reference xSeriesProp(rSeries, uno::UNO_QUERY); + if (xSeriesProp.is()) + { + uno::Any aVal = xSeriesProp->getPropertyValue( + u"ChartexOwnerIdx"_ustr); + sal_Int32 nVal = 0; + if (aVal >>= nVal) + oOwnerIdx = nVal; + } + } + + pFS->startElement(FSNS(XML_cx, XML_series), + XML_layoutId, sTypeName, + XML_ownerIdx, oOwnerIdx.has_value() + ? OString::number(*oOwnerIdx) + : std::optional()); Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt( xSource->getDataSequences()); @@ -3934,40 +4177,220 @@ void ChartExport::exportSeries_chartex( const Reference& xCh rSeries, getModel() ); if( xOldPropSet.is() ) { - exportShapeProps( xOldPropSet, XML_cx ); + bool bHasExplicitFill = false; + xOldPropSet->getPropertyValue(u"HasExplicitFill"_ustr) >>= bHasExplicitFill; + + if (bHasExplicitFill) + { + exportShapeProps( xOldPropSet, XML_cx ); + } } - DataLabelsRange aDLblsRange; - // export data labels - exportDataLabels(rSeries, nSeriesLength, eChartType, aDLblsRange, true); + if (aChartType != "com.sun.star.chart2.HistogramChartType") + { + DataLabelsRange aDLblsRange; + // export data labels only if the series had them on import + bool bHasDataLabels = false; + if (xOldPropSet.is()) + xOldPropSet->getPropertyValue(u"HasDataLabels"_ustr) >>= bHasDataLabels; + if (bHasDataLabels) + exportDataLabels(rSeries, nSeriesLength, eChartType, aDLblsRange, true); + } // dataId links to the correct data set in the . See - // DATA_ID_COMMENT - pFS->singleElement(FSNS(XML_cx, XML_dataId), XML_val, - OString::number(nSeriesCnt++)); + // DATA_ID_COMMENT. When the series uses ownerIdx, it shares the + // owner series's data and no dataId is emitted; keep nSeriesCnt + // aligned with the chartData entries by not incrementing it. + if (!oOwnerIdx.has_value()) + { + pFS->singleElement(FSNS(XML_cx, XML_dataId), XML_val, + OString::number(nSeriesCnt++)); + } // layoutPr - PropertySet aSeriesProp(rSeries); - sal_uInt32 nIntervalClosedChar = '\0'; - if (aSeriesProp.getProperty(nIntervalClosedChar, PROP_IntervalClosed)) { - pFS->startElement(FSNS(XML_cx, XML_layoutPr)); + // Maybe factor this into another function. TODO + Reference xSeriesProp(rSeries, uno::UNO_QUERY); + if (xSeriesProp.is()) + { + OUString sParentLabelLayout; + uno::Any aParentLL = xSeriesProp->getPropertyValue(u"ParentLabelLayout"_ustr); + bool bHasParentLL = (aParentLL >>= sParentLabelLayout); - switch (nIntervalClosedChar) { - case 'l' : - pFS->singleElement(FSNS(XML_cx, XML_binning), XML_intervalClosed, "l"); - break; - case 'r' : - pFS->singleElement(FSNS(XML_cx, XML_binning), XML_intervalClosed, "r"); - break; - default: - assert(false); - break; + OUString sRegionLabelLayout; + uno::Any aRegionLL = xSeriesProp->getPropertyValue(u"RegionLabelLayout"_ustr); + bool bHasRegionLL = (aRegionLL >>= sRegionLabelLayout); + + uno::Any aConnLines = xSeriesProp->getPropertyValue(u"ConnectorLines"_ustr); + uno::Any aMeanLine = xSeriesProp->getPropertyValue(u"MeanLine"_ustr); + uno::Any aMeanMarker = xSeriesProp->getPropertyValue(u"MeanMarker"_ustr); + uno::Any aNonoutliers = xSeriesProp->getPropertyValue(u"Nonoutliers"_ustr); + uno::Any aOutliers = xSeriesProp->getPropertyValue(u"Outliers"_ustr); + bool bHasVisibility = aConnLines.hasValue() || aMeanLine.hasValue() + || aMeanMarker.hasValue() || aNonoutliers.hasValue() + || aOutliers.hasValue(); + + OUString sQuartileMethod; + uno::Any aQM = xSeriesProp->getPropertyValue(u"QuartileMethod"_ustr); + bool bHasQM = (aQM >>= sQuartileMethod); + + uno::Sequence aSubtotalIndices; + uno::Any aSubtotals = xSeriesProp->getPropertyValue(u"SubtotalIndices"_ustr); + bool bHasSubtotals = (aSubtotals >>= aSubtotalIndices); + + uno::Any aIntervalClosed = xSeriesProp->getPropertyValue( u"IntervalClosed"_ustr); + const bool bHasIC = aIntervalClosed.hasValue(); + + bool bHasGeography = false; + xSeriesProp->getPropertyValue(u"HasGeography"_ustr) >>= bHasGeography; + + sal_Int32 nFrequencyType = 0; + double fBinWidth = 0.0; + sal_Int32 nBinCount = 0; + bool bHasBinWidth = false; + bool bHasBinCount = false; + bool bUseUnderflowBin = false; + bool bUseOverflowBin = false; + double fUnderflowBinValue = 0.0; + double fOverflowBinValue = 0.0; + bool bHasUnderflowBinValue = false; + bool bHasOverflowBinValue = false; + if (aChartType == "com.sun.star.chart2.HistogramChartType") + { + Reference xChartTypePropSet(xChartType, uno::UNO_QUERY); + if (xChartTypePropSet.is()) + { + xChartTypePropSet->getPropertyValue(u"FrequencyType"_ustr) >>= nFrequencyType; + bHasBinWidth = + (xChartTypePropSet->getPropertyValue(u"BinWidth"_ustr) >>= fBinWidth); + bHasBinCount = + (xChartTypePropSet->getPropertyValue(u"BinCount"_ustr) >>= nBinCount); + + xChartTypePropSet->getPropertyValue(u"UseUnderflowBin"_ustr) >>= bUseUnderflowBin; + xChartTypePropSet->getPropertyValue(u"UseOverflowBin"_ustr) >>= bUseOverflowBin; + + bHasUnderflowBinValue + = (xChartTypePropSet->getPropertyValue(u"UnderflowBinValue"_ustr) >>= fUnderflowBinValue); + bHasOverflowBinValue + = (xChartTypePropSet->getPropertyValue(u"OverflowBinValue"_ustr) >>= fOverflowBinValue); + } } - pFS->endElement(FSNS(XML_cx, XML_layoutPr)); + bool bHasAny = bHasParentLL || bHasRegionLL || bHasVisibility + || bHasQM || bHasSubtotals || bHasIC || bHasGeography + || aChartType == "com.sun.star.chart2.HistogramChartType"; + if (bHasAny) + { + pFS->startElement(FSNS(XML_cx, XML_layoutPr)); + + if (bHasParentLL) + pFS->singleElement(FSNS(XML_cx, XML_parentLabelLayout), + XML_val, sParentLabelLayout); + + if (bHasRegionLL) + pFS->singleElement(FSNS(XML_cx, XML_regionLabelLayout), + XML_val, sRegionLabelLayout); + + if (bHasVisibility) + { + bool bConnLines = false, bMeanLine = false, + bMeanMarker = false, bNonoutliers = false, + bOutliers = false; + bool bHasConnLines = (aConnLines >>= bConnLines); + bool bHasMeanLine = (aMeanLine >>= bMeanLine); + bool bHasMeanMarker = (aMeanMarker >>= bMeanMarker); + bool bHasNonoutliers = (aNonoutliers >>= bNonoutliers); + bool bHasOutliers = (aOutliers >>= bOutliers); + + pFS->singleElement(FSNS(XML_cx, XML_visibility), + XML_connectorLines, bHasConnLines ? ToPsz10(bConnLines) : nullptr, + XML_meanLine, bHasMeanLine ? ToPsz10(bMeanLine) : nullptr, + XML_meanMarker, bHasMeanMarker ? ToPsz10(bMeanMarker) : nullptr, + XML_nonoutliers, bHasNonoutliers ? ToPsz10(bNonoutliers) : nullptr, + XML_outliers, bHasOutliers ? ToPsz10(bOutliers) : nullptr); + + } + + if (bHasGeography) + oox::drawingml::chart::exportGeography(xSeriesProp, pFS); + + if (aChartType == "com.sun.star.chart2.HistogramChartType") + { + // histogram wraps bin-size/bin-count children + const char* pIntervalClosed = nullptr; + if (bHasIC) + { + sal_uInt32 nIntervalClosedChar = '\0'; + aIntervalClosed >>= nIntervalClosedChar; + if (nIntervalClosedChar == 'l') + pIntervalClosed = "l"; + else if (nIntervalClosedChar == 'r') + pIntervalClosed = "r"; + } + + auto pBinningAttrs = sax_fastparser::FastSerializerHelper::createAttrList(); + + if (pIntervalClosed) + pBinningAttrs->add(XML_intervalClosed, pIntervalClosed); + + if (bUseUnderflowBin && bHasUnderflowBinValue) + pBinningAttrs->add(XML_underflow, OString::number(fUnderflowBinValue)); + + if (bUseOverflowBin && bHasOverflowBinValue) + pBinningAttrs->add(XML_overflow, OString::number(fOverflowBinValue)); + + pFS->startElement(FSNS(XML_cx, XML_binning), pBinningAttrs); + + if (nFrequencyType == 1 && bHasBinWidth) + { + pFS->singleElement(FSNS(XML_cx, XML_binSize), XML_val, + OString::number(fBinWidth)); + } + else if (nFrequencyType == 2 && bHasBinCount) + { + pFS->singleElement(FSNS(XML_cx, XML_binCount), XML_val, + OString::number(nBinCount)); + } + + pFS->endElement(FSNS(XML_cx, XML_binning)); + } + else if (bHasIC) + { + // non-histogram (BoxWhisker): self-closing + sal_uInt32 nIntervalClosedChar = '\0'; + aIntervalClosed >>= nIntervalClosedChar; + + switch (nIntervalClosedChar) { + case 'l' : + pFS->singleElement(FSNS(XML_cx, XML_binning), XML_intervalClosed, "l"); + break; + case 'r' : + pFS->singleElement(FSNS(XML_cx, XML_binning), XML_intervalClosed, "r"); + break; + default: + assert(false); + break; + } + } + + if (bHasQM) + pFS->singleElement(FSNS(XML_cx, XML_statistics), + XML_quartileMethod, sQuartileMethod); + + if (bHasSubtotals) + { + pFS->startElement(FSNS(XML_cx, XML_subtotals)); + for (sal_Int32 nIdx : aSubtotalIndices) + pFS->singleElement(FSNS(XML_cx, XML_idx), + XML_val, OString::number(nIdx)); + pFS->endElement(FSNS(XML_cx, XML_subtotals)); + } + + pFS->endElement(FSNS(XML_cx, XML_layoutPr)); + } } // axisId + createAxes_chartex(rSeries); // extLst @@ -3977,7 +4400,7 @@ void ChartExport::exportSeries_chartex( const Reference& xCh } void ChartExport::exportCandleStickSeries( - const Sequence>& aSeriesSeq, bool& rPrimaryAxes, sal_uInt32& nIdx) + const Sequence>& aSeriesSeq, bool& rPrimaryAxes) { for( const Reference< chart2::XDataSeries >& xSeries : aSeriesSeq ) { @@ -4006,8 +4429,8 @@ void ChartExport::exportCandleStickSeries( FSHelperPtr pFS = GetFS(); pFS->startElement(FSNS(XML_c, XML_ser)); - pFS->singleElement(FSNS(XML_c, XML_idx), XML_val, OString::number(++nIdx)); - pFS->singleElement(FSNS(XML_c, XML_order), XML_val, OString::number(nIdx)); + pFS->singleElement(FSNS(XML_c, XML_idx), XML_val, OString::number(mnSeriesCount)); + pFS->singleElement(FSNS(XML_c, XML_order), XML_val, OString::number(mnSeriesCount++)); // export label if( xLabelSeq.is() ) @@ -4232,6 +4655,21 @@ void ChartExport::exportShapeProps( const Reference< XPropertySet >& xPropSet, pFS->endElement( FSNS( nNS, XML_spPr ) ); } +bool ChartExport::hasExplicitSpPr(const Reference& xPropSet) +{ + if (!xPropSet.is()) + return false; + bool bHasSpPr = false; + try + { + xPropSet->getPropertyValue(u"HasExplicitSpPr"_ustr) >>= bHasSpPr; + } + catch (const uno::Exception&) + { + } + return bHasSpPr; +} + void ChartExport::exportTextProps(const Reference& xPropSet, bool bIsChartex) { @@ -4332,7 +4770,7 @@ void ChartExport::InitPlotArea( ) } } -void ChartExport::exportAxes( bool bIsChartex ) +void ChartExport::exportAxes_chart() { sal_Int32 nSize = maAxes.size(); // let's export the axis types in the right order @@ -4341,11 +4779,18 @@ void ChartExport::exportAxes( bool bIsChartex ) for ( sal_Int32 nIdx = 0; nIdx < nSize; nIdx++ ) { if (nSortIdx == maAxes[nIdx].nAxisType) - exportAxis( maAxes[nIdx], bIsChartex ); + exportAxis( maAxes[nIdx], false); } } } +void ChartExport::exportAxes_chartex() +{ + for (const AxisIdPair& aIdPair : maAxes) { + exportAxis(aIdPair, true); + } +} + namespace { sal_Int32 getXAxisTypeByChartType(sal_Int32 eChartType) @@ -4414,6 +4859,7 @@ void ChartExport::exportAxis(const AxisIdPair& rAxisIdPair, bool bIsChartex) switch( rAxisIdPair.nAxisType ) { case AXIS_PRIMARY_X: + case AXIS_CATEGORY: { Reference< css::chart::XAxisXSupplier > xAxisXSupp( mxDiagram, uno::UNO_QUERY ); if( xAxisXSupp.is()) @@ -4425,16 +4871,21 @@ void ChartExport::exportAxis(const AxisIdPair& rAxisIdPair, bool bIsChartex) if( bHasXAxisMinorGrid ) xMinorGrid = xAxisXSupp->getXHelpGrid(); - nAxisType = lcl_getCategoryAxisType(mxNewDiagram, 0, 0); - if( nAxisType != -1 ) - nAxisType = getRealXAxisType(nAxisType); - else - nAxisType = getXAxisTypeByChartType( getChartType() ); + if (rAxisIdPair.nAxisType == AXIS_CATEGORY) { + nAxisType = XML_catAx; + } else { + nAxisType = lcl_getCategoryAxisType(mxNewDiagram, 0, 0); + if( nAxisType != -1 ) + nAxisType = getRealXAxisType(nAxisType); + else + nAxisType = getXAxisTypeByChartType( getChartType() ); + } // FIXME: axPos, need to check axis direction sAxPos = "b"; break; } case AXIS_PRIMARY_Y: + case AXIS_VALUE: { Reference< css::chart::XAxisYSupplier > xAxisYSupp( mxDiagram, uno::UNO_QUERY ); if( xAxisYSupp.is()) @@ -4514,8 +4965,70 @@ void ChartExport::exportAxis(const AxisIdPair& rAxisIdPair, bool bIsChartex) } if (bIsChartex) { - exportOneAxis_chartex(xAxisProp, xAxisTitle, xMajorGrid, xMinorGrid, nAxisType, - rAxisIdPair); + // The XAxisXSupplier / XAxisYSupplier wrappers above always return + // the primary axis for AXIS_CATEGORY / AXIS_VALUE entries, which is + // wrong for chartex (where each is one of potentially many + // value axes, identified by cx:axisId). Look up the matching chart2 + // axis directly so chartex-preserved properties on the secondary + // value axis don't get masked by the primary axis's values. + Reference xRealAxisProp = xAxisProp; + Reference xRealMajorGrid = xMajorGrid; + Reference xRealMinorGrid = xMinorGrid; + try + { + Reference xCooSysCnt( + mxNewDiagram, uno::UNO_QUERY); + if (xCooSysCnt.is()) + { + bool bFound = false; + const auto aCooSysSeq = xCooSysCnt->getCoordinateSystems(); + for (const auto& xCooSys : aCooSysSeq) + { + if (bFound) + break; + const sal_Int32 nDim = xCooSys->getDimension(); + for (sal_Int32 i = 0; i < nDim && !bFound; ++i) + { + const sal_Int32 nMaxAxIdx + = xCooSys->getMaximumAxisIndexByDimension(i); + for (sal_Int32 j = 0; j <= nMaxAxIdx && !bFound; ++j) + { + Reference xAxis + = xCooSys->getAxisByDimension(i, j); + Reference xAxisLookup(xAxis, + uno::UNO_QUERY); + if (!xAxisLookup.is()) + continue; + sal_Int32 nStoredId = -1; + try + { + xAxisLookup->getPropertyValue(u"AxisId"_ustr) + >>= nStoredId; + } + catch (const uno::Exception&) + { + continue; + } + if (nStoredId == rAxisIdPair.nAxisId) + { + xRealAxisProp = xAxisLookup; + xRealMajorGrid = xAxis->getGridProperties(); + Sequence> aSubGrids + = xAxis->getSubGridProperties(); + if (aSubGrids.hasElements()) + xRealMinorGrid = aSubGrids[0]; + bFound = true; + } + } + } + } + } + } + catch (const uno::Exception&) + { + } + exportOneAxis_chartex(xRealAxisProp, xAxisTitle, xRealMajorGrid, + xRealMinorGrid, nAxisType, rAxisIdPair); } else { exportOneAxis_chart(xAxisProp, xAxisTitle, xMajorGrid, xMinorGrid, nAxisType, sAxPos, rAxisIdPair); @@ -4887,49 +5400,89 @@ void ChartExport::exportOneAxis_chartex( // ==== catScaling/valScaling switch (nAxisType) { case XML_catAx: - pFS->singleElement(FSNS(XML_cx, XML_catScaling) /* TODO: handle gapWidth */); + { + // Get gapWidth from the chart type's GapwidthSequence property + std::optional oGapWidth; + try + { + Reference xCooSysCnt(mxNewDiagram, uno::UNO_QUERY); + if (xCooSysCnt.is()) + { + auto aCooSysSeq = xCooSysCnt->getCoordinateSystems(); + if (aCooSysSeq.hasElements()) + { + Reference xCTCnt(aCooSysSeq[0], uno::UNO_QUERY); + if (xCTCnt.is()) + { + auto aChartTypes = xCTCnt->getChartTypes(); + if (aChartTypes.hasElements()) + { + Reference xTypeProp(aChartTypes[0], uno::UNO_QUERY); + if (xTypeProp.is() && GetProperty(xTypeProp, u"GapwidthSequence"_ustr)) + { + uno::Sequence aGapSeq; + mAny >>= aGapSeq; + if (aGapSeq.hasElements()) + oGapWidth = aGapSeq[0] / 100.0; + } + } + } + } + } + } + catch (uno::Exception&) + { + } + + if (oGapWidth.has_value()) + pFS->singleElement(FSNS(XML_cx, XML_catScaling), + XML_gapWidth, OString::number(*oGapWidth)); + else + pFS->singleElement(FSNS(XML_cx, XML_catScaling)); + } break; case XML_valAx: { - bool bAutoMax = false; - double dMax = 0; // Make VS happy - bool bMaxSpecified = false; - if(GetProperty( xAxisProp, u"AutoMax"_ustr ) ) - mAny >>= bAutoMax; - - if( !bAutoMax && (GetProperty( xAxisProp, u"Max"_ustr ) ) ) + // Only emit a cx:valScaling attribute when it was explicitly + // set on the source. We read the chartex-preserved values + // first; if they are unset we treat the attribute as auto and + // omit it, rather than synthesizing one from chart2 defaults + // (which would inject e.g. minorUnit="0.2" into round-tripped + // empty valScaling elements). + auto readOptDouble = [&xAxisProp](const OUString& rName) + -> std::optional { - mAny >>= dMax; - bMaxSpecified = true; - } + if (!xAxisProp.is()) + return std::nullopt; + try + { + uno::Any aVal = xAxisProp->getPropertyValue(rName); + double d = 0; + if (aVal >>= d) + return d; + } + catch (const uno::Exception&) + { + } + return std::nullopt; + }; + std::optional oMax = readOptDouble(u"ChartexValMax"_ustr); + std::optional oMin = readOptDouble(u"ChartexValMin"_ustr); + std::optional oMajor = readOptDouble(u"ChartexMajorUnit"_ustr); + std::optional oMinor = readOptDouble(u"ChartexMinorUnit"_ustr); - bool bAutoMin = false; - double dMin = 0; // Make VS happy - bool bMinSpecified = false; - if(GetProperty( xAxisProp, u"AutoMin"_ustr ) ) - mAny >>= bAutoMin; - - if( !bAutoMin && (GetProperty( xAxisProp, u"Min"_ustr ) ) ) + auto asAttr = [](std::optional oVal) -> std::optional { - mAny >>= dMin; - bMinSpecified = true; - } - - // TODO: handle majorUnit/minorUnit in the following - if (bMaxSpecified && bMinSpecified) { - pFS->singleElement(FSNS(XML_cx, XML_valScaling), - XML_max, OString::number(dMax), - XML_min, OString::number(dMin)); - } else if (!bMaxSpecified && bMinSpecified) { - pFS->singleElement(FSNS(XML_cx, XML_valScaling), - XML_min, OString::number(dMin)); - } else if (bMaxSpecified && !bMinSpecified) { - pFS->singleElement(FSNS(XML_cx, XML_valScaling), - XML_max, OString::number(dMax)); - } else { - pFS->singleElement(FSNS(XML_cx, XML_valScaling)); - } + if (oVal.has_value()) + return OString::number(*oVal); + return std::nullopt; + }; + pFS->singleElement(FSNS(XML_cx, XML_valScaling), + XML_max, asAttr(oMax), + XML_min, asAttr(oMin), + XML_majorUnit, asAttr(oMajor), + XML_minorUnit, asAttr(oMinor)); } break; default: @@ -4943,64 +5496,93 @@ void ChartExport::exportOneAxis_chartex( } // ==== units - if (GetProperty( xAxisProp, u"DisplayUnits"_ustr ) ) + // Chartex collapses c:dispUnits/c:builtInUnit into a self-closing + // cx:units element carrying the unit token on a "unit" attribute. The + // chartex-preserved string takes precedence; for axes that never had a + // cx:units we fall back to BuiltInUnit (set, for instance, when the + // chart was originally a c-namespace chart). + OUString aUnitVal; + if (xAxisProp.is()) + { + try + { + xAxisProp->getPropertyValue(u"ChartexUnit"_ustr) >>= aUnitVal; + } + catch (const uno::Exception&) + { + } + } + if (aUnitVal.isEmpty() && GetProperty( xAxisProp, u"DisplayUnits"_ustr )) { bool bDisplayUnits = false; mAny >>= bDisplayUnits; - if (bDisplayUnits) + if (bDisplayUnits && GetProperty( xAxisProp, u"BuiltInUnit"_ustr )) + mAny >>= aUnitVal; + } + if (!aUnitVal.isEmpty()) + pFS->singleElement(FSNS(XML_cx, XML_units), XML_unit, aUnitVal); + + // ==== majorGridlines / minorGridlines + // Two round-trip concerns: + // 1) The gridlines element is emitted only when the imported axis had + // one, signaled by the "Show" flag on the grid property set + // (axisconverter sets Show = mxMajor/MinorGridLines.is()). + // 2) When the source gridlines had no , we must not emit one + // either; an empty gridlines element means "use default + // formatting" and a synthesized spPr would silently restyle the + // grid on round-trip. + auto exportChartexGridLines = [this, pFS](const Reference& xGrid, + sal_Int32 nTag) + { + if (!xGrid.is()) + return; + bool bShow = false; + try { - if (GetProperty( xAxisProp, u"BuiltInUnit"_ustr )) - { - OUString aVal; - mAny >>= aVal; - if(!aVal.isEmpty()) - { - pFS->startElement(FSNS(XML_cx, XML_units)); + xGrid->getPropertyValue(u"Show"_ustr) >>= bShow; + } + catch (const uno::Exception&) + { + } + if (!bShow) + return; - pFS->startElement(FSNS(XML_cx, XML_unitsLabel)); + if (hasExplicitSpPr(xGrid)) + { + pFS->startElement(FSNS(XML_cx, nTag)); + exportShapeProps(xGrid, XML_cx); + pFS->endElement(FSNS(XML_cx, nTag)); + } + else + { + pFS->singleElement(FSNS(XML_cx, nTag)); + } + }; + exportChartexGridLines(xMajorGrid, XML_majorGridlines); + exportChartexGridLines(xMinorGrid, XML_minorGridlines); - lcl_writeChartexString(pFS, aVal); + // ==== majorTickMarks + if (GetProperty( xAxisProp, u"MajorTickmarks"_ustr ) ) + { + sal_Int32 nValue = 0; + mAny >>= nValue; - pFS->endElement(FSNS(XML_cx, XML_unitsLabel)); - - pFS->endElement( FSNS( XML_cx, XML_units ) ); - } - } + if (nValue >= 0) { + pFS->singleElement(FSNS(XML_cx, XML_majorTickMarks), XML_type, + getTickMarkLocStr(nValue)); } } - // ==== majorGridlines - if( xMajorGrid.is()) - { - pFS->startElement(FSNS(XML_cx, XML_majorGridlines)); - exportShapeProps( xMajorGrid, XML_cx ); - pFS->endElement( FSNS( XML_cx, XML_majorGridlines ) ); - } - - // ==== minorGridlines - if( xMinorGrid.is()) - { - pFS->startElement(FSNS(XML_cx, XML_minorGridlines)); - exportShapeProps( xMinorGrid, XML_cx ); - pFS->endElement( FSNS( XML_cx, XML_minorGridlines ) ); - } - - // ==== majorTickMarks - if (GetProperty( xAxisProp, u"Marks"_ustr ) ) - { - sal_Int32 nValue = 0; - mAny >>= nValue; - pFS->singleElement(FSNS(XML_cx, XML_majorTickMarks), XML_type, - getTickMarkLocStr(nValue)); - } - // ==== minorTickMarks - if (GetProperty( xAxisProp, u"HelpMarks"_ustr ) ) + if (GetProperty( xAxisProp, u"MinorTickmarks"_ustr ) ) { sal_Int32 nValue = 0; mAny >>= nValue; - pFS->singleElement(FSNS(XML_cx, XML_minorTickMarks), XML_type, - getTickMarkLocStr(nValue)); + + if (nValue >= 0) { + pFS->singleElement(FSNS(XML_cx, XML_minorTickMarks), XML_type, + getTickMarkLocStr(nValue)); + } } // ==== tickLabels @@ -5036,11 +5618,16 @@ void ChartExport::exportOneAxis_chartex( XML_formatCode, aNumberFormatString, XML_sourceLinked, bLinkedNumFmt ? "1" : "0"); - // ==== spPr - exportShapeProps( xAxisProp, XML_cx ); + // ==== spPr (only if the axis had one on import) + if (hasExplicitSpPr(xAxisProp)) + exportShapeProps( xAxisProp, XML_cx ); - // ==== txPr - exportTextProps(xAxisProp, true); + // ==== txPr (only if the axis had one on import) + bool bHasTxPr = false; + if (xAxisProp.is()) + xAxisProp->getPropertyValue(u"HasExplicitTxPr"_ustr) >>= bHasTxPr; + if (bHasTxPr) + exportTextProps(xAxisProp, true); pFS->endElement( FSNS( XML_cx, XML_axis ) ); } @@ -5296,7 +5883,12 @@ void ChartExport::writeLabelProperties( exportTextProps(xPropSet, bIsChartex); // c:txPr - if (!bIsChartex) { + if (bIsChartex) { + pFS->singleElement(FSNS(XML_cx, XML_visibility), + XML_seriesName, ToPsz10(aLabel.ShowSeriesName), + XML_categoryName, ToPsz10(aLabel.ShowCategoryName), + XML_value, ToPsz10(aLabel.ShowNumber)); + } else { // In chartex label position is an attribute of cx:dataLabel if (rLabelParam.mbExport) { @@ -5360,12 +5952,6 @@ void ChartExport::exportDataLabels( FSHelperPtr pFS = GetFS(); - if (bIsChartex) { - pFS->startElement(FSNS(XML_cx, XML_dataLabels)); - } else { - pFS->startElement(FSNS(XML_c, XML_dLbls)); - } - uno::Sequence aAttrLabelIndices; xPropSet->getPropertyValue(u"AttributedDataPoints"_ustr) >>= aAttrLabelIndices; @@ -5424,6 +6010,27 @@ void ChartExport::exportDataLabels( ; } + if (bIsChartex) { + sal_Int32 nLabelPlacement = aParam.meDefault; + if (aParam.mbExport + && (xPropSet->getPropertyValue(u"LabelPlacement"_ustr) >>= nLabelPlacement) + && aParam.maAllowedValues.count(nLabelPlacement)) + { + pFS->startElement(FSNS(XML_cx, XML_dataLabels), + XML_pos, toOOXMLPlacement(nLabelPlacement)); + } else { + pFS->startElement(FSNS(XML_cx, XML_dataLabels)); + } + } else { + pFS->startElement(FSNS(XML_c, XML_dLbls)); + } + + // In CT_DataLabels the group-level label properties precede the + // cx:dataLabel children + if (bIsChartex) + writeLabelProperties(xPropSet, aParam, -1, rDLblsRange, true); + + std::vector aHiddenLabelIndices; for (const sal_Int32 nIdx : aAttrLabelIndices) { uno::Reference xLabelPropSet = xSeries->getDataPointByIndex(nIdx); @@ -5432,17 +6039,27 @@ void ChartExport::exportDataLabels( continue; if (bIsChartex) { - if (aParam.mbExport) + chart2::DataPointLabel aPointLabel; + if ((xLabelPropSet->getPropertyValue(u"Label"_ustr) >>= aPointLabel) + && !aPointLabel.ShowNumber && !aPointLabel.ShowNumberInPercent + && !aPointLabel.ShowCategoryName && !aPointLabel.ShowLegendSymbol + && !aPointLabel.ShowCustomLabel && !aPointLabel.ShowSeriesName) { - sal_Int32 nLabelPlacement = aParam.meDefault; - if (xPropSet->getPropertyValue(u"LabelPlacement"_ustr) >>= nLabelPlacement) - { - if (!aParam.maAllowedValues.count(nLabelPlacement)) - nLabelPlacement = aParam.meDefault; - pFS->startElement(FSNS(XML_cx, XML_dataLabel), - XML_idx, OString::number(nIdx), - XML_pos, toOOXMLPlacement(nLabelPlacement)); - } + // In CT_DataLabels the cx:dataLabelHidden elements follow the + // cx:dataLabel elements + aHiddenLabelIndices.push_back(nIdx); + continue; + } + + sal_Int32 nLabelPlacement = aParam.meDefault; + if (aParam.mbExport + && (xLabelPropSet->getPropertyValue(u"LabelPlacement"_ustr) >>= nLabelPlacement)) + { + if (!aParam.maAllowedValues.count(nLabelPlacement)) + nLabelPlacement = aParam.meDefault; + pFS->startElement(FSNS(XML_cx, XML_dataLabel), + XML_idx, OString::number(nIdx), + XML_pos, toOOXMLPlacement(nLabelPlacement)); } else { pFS->startElement(FSNS(XML_cx, XML_dataLabel), XML_idx, OString::number(nIdx)); } @@ -5484,31 +6101,47 @@ void ChartExport::exportDataLabels( // Individual label property that overwrites the baseline. writeLabelProperties(xLabelPropSet, aParam, nIdx, rDLblsRange, bIsChartex); - pFS->endElement(FSNS(XML_c, XML_dLbl)); + if (bIsChartex) + pFS->endElement(FSNS(XML_cx, XML_dataLabel)); + else + pFS->endElement(FSNS(XML_c, XML_dLbl)); } - // Baseline label properties for all labels. - writeLabelProperties(xPropSet, aParam, -1, rDLblsRange, bIsChartex); + for (const sal_Int32 nIdx : aHiddenLabelIndices) + pFS->singleElement(FSNS(XML_cx, XML_dataLabelHidden), XML_idx, OString::number(nIdx)); if (!bIsChartex) { + // Baseline label properties for all labels. + writeLabelProperties(xPropSet, aParam, -1, rDLblsRange, false); + bool bShowLeaderLines = false; xPropSet->getPropertyValue(u"ShowCustomLeaderLines"_ustr) >>= bShowLeaderLines; - pFS->singleElement(FSNS(XML_c, XML_showLeaderLines), XML_val, ToPsz10(bShowLeaderLines)); - // Export LeaderLine properties - // TODO: import all kind of LeaderLine props (not just LineColor/LineWidth) - if (bShowLeaderLines) + bool bIsPieOrDoughnut = eChartType == chart::TYPEID_PIE + || eChartType == chart::TYPEID_DOUGHNUT; + + // showLeaderLines and leaderLines are only valid inside dLbls for + // pie and doughnut charts per the OOXML schema. Writing them for + // other chart types (e.g. barChart) causes Excel to crash. + if (bIsPieOrDoughnut) { - pFS->startElement(FSNS(XML_c, XML_leaderLines)); - pFS->startElement(FSNS(XML_c, XML_spPr)); - WriteOutline(xPropSet, getModel()); - pFS->endElement(FSNS(XML_c, XML_spPr)); - pFS->endElement(FSNS(XML_c, XML_leaderLines)); + pFS->singleElement(FSNS(XML_c, XML_showLeaderLines), + XML_val, ToPsz10(bShowLeaderLines)); + + // Export LeaderLine properties + // TODO: import all kind of LeaderLine props (not just LineColor/LineWidth) + if (bShowLeaderLines) + { + pFS->startElement(FSNS(XML_c, XML_leaderLines)); + pFS->startElement(FSNS(XML_c, XML_spPr)); + WriteOutline(xPropSet, getModel()); + pFS->endElement(FSNS(XML_c, XML_spPr)); + pFS->endElement(FSNS(XML_c, XML_leaderLines)); + } } - - // Export leader line - if( eChartType != chart::TYPEID_PIE ) + else { + // For non-pie/doughnut charts, use the c15 extension for leader lines. pFS->startElement(FSNS(XML_c, XML_extLst)); pFS->startElement(FSNS(XML_c, XML_ext), XML_uri, "{CE6537A1-D6FC-4f65-9D91-7224C49458BB}", FSNS(XML_xmlns, XML_c15), GetFB()->getNamespaceURL(OOX_NS(c15))); pFS->singleElement(FSNS(XML_c15, XML_showLeaderLines), XML_val, ToPsz10(bShowLeaderLines)); @@ -5659,48 +6292,151 @@ void ChartExport::exportDataPoints( } // Generalized axis output -void ChartExport::createAxes(bool bPrimaryAxes, bool bCheckCombinedAxes, bool bIsChartex) +void ChartExport::createAxes_chart(bool bPrimaryAxes, bool bCheckCombinedAxes) { - sal_Int32 nAxisIdx, nAxisIdy; - bool bPrimaryAxisExists = false; - bool bSecondaryAxisExists = false; - // let's check which axis already exists and which axis is attached to the actual dataseries - if (maAxes.size() >= 2) + sal_Int32 nAxisIdx = -1, nAxisIdy = -1; + bool bCreateAxes = true; + + // tdf#114181 keep axes of combined charts - search for existing pairs + if (bCheckCombinedAxes) { - bPrimaryAxisExists = bPrimaryAxes && maAxes[1].nAxisType == AXIS_PRIMARY_Y; - bSecondaryAxisExists = !bPrimaryAxes && maAxes[1].nAxisType == AXIS_SECONDARY_Y; + const AxisType eWantedX = bPrimaryAxes ? AXIS_PRIMARY_X : AXIS_SECONDARY_X; + const AxisType eWantedY = bPrimaryAxes ? AXIS_PRIMARY_Y : AXIS_SECONDARY_Y; + + sal_Int32 nFoundX = -1, nFoundY = -1; + for (const auto& rAxis : maAxes) + { + if (rAxis.nAxisType == eWantedX) + nFoundX = rAxis.nAxisId; + else if (rAxis.nAxisType == eWantedY) + nFoundY = rAxis.nAxisId; + } + + if (nFoundX != -1 && nFoundY != -1) + { + bCreateAxes = false; + nAxisIdx = nFoundX; + nAxisIdy = nFoundY; + } } - // tdf#114181 keep axes of combined charts - if ( bCheckCombinedAxes && ( bPrimaryAxisExists || bSecondaryAxisExists ) ) - { - nAxisIdx = maAxes[0].nAxisId; - nAxisIdy = maAxes[1].nAxisId; - } - else + + if (bCreateAxes) { nAxisIdx = lcl_generateRandomValue(); nAxisIdy = lcl_generateRandomValue(); - AxesType eXAxis = bPrimaryAxes ? AXIS_PRIMARY_X : AXIS_SECONDARY_X; - AxesType eYAxis = bPrimaryAxes ? AXIS_PRIMARY_Y : AXIS_SECONDARY_Y; + AxisType eXAxis = bPrimaryAxes ? AXIS_PRIMARY_X : AXIS_SECONDARY_X; + AxisType eYAxis = bPrimaryAxes ? AXIS_PRIMARY_Y : AXIS_SECONDARY_Y; maAxes.emplace_back( eXAxis, nAxisIdx, nAxisIdy ); maAxes.emplace_back( eYAxis, nAxisIdy, nAxisIdx ); } - if (!bIsChartex) { - // Export IDs - FSHelperPtr pFS = GetFS(); - pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdx)); - pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdy)); - if (mbHasZAxis) + // Export IDs + FSHelperPtr pFS = GetFS(); + + pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdx)); + pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdy)); + if (mbHasZAxis) + { + sal_Int32 nAxisIdz = 0; + if( isDeep3dChart() ) { - sal_Int32 nAxisIdz = 0; - if( isDeep3dChart() ) - { - nAxisIdz = lcl_generateRandomValue(); - maAxes.emplace_back( AXIS_PRIMARY_Z, nAxisIdz, nAxisIdy ); - } - pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdz)); + nAxisIdz = lcl_generateRandomValue(); + maAxes.emplace_back( AXIS_PRIMARY_Z, nAxisIdz, nAxisIdy ); } + pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdz)); + } +} + +void ChartExport::createAxes_chartex( + const Reference& xSeries) +{ + FSHelperPtr pFS = GetFS(); + + // Use the cx:axisId list preserved on the data series at import. + // For axis-less chartex types (regionMap, sunburst, treemap) the + // sequence is empty, so no and no are emitted. + uno::Sequence aAxisIds; + Reference xSeriesProp(xSeries, uno::UNO_QUERY); + if (xSeriesProp.is()) + { + try + { + xSeriesProp->getPropertyValue(u"ChartexAxisIds"_ustr) >>= aAxisIds; + } + catch (const uno::Exception&) + { + } + } + + if (!aAxisIds.hasElements()) + return; + + for (sal_Int32 nAxisId : aAxisIds) + { + pFS->singleElement(FSNS(XML_cx, XML_axisId), XML_val, + OString::number(nAxisId)); + + // Each axis appears in maAxes (and therefore in output) + // exactly once across all series. + bool bKnown = std::any_of(maAxes.begin(), maAxes.end(), + [nAxisId](const AxisIdPair& rPair) + { return rPair.nAxisId == nAxisId; }); + if (bKnown) + continue; + + // Find the axis type by walking through and + // matching the AxisId property we stored at import. + AxisType eAxisType = AXIS_CATEGORY; + try + { + Reference xCooSysCnt( + mxNewDiagram, uno::UNO_QUERY); + if (xCooSysCnt.is()) + { + bool bFound = false; + const auto aCooSysSeq = xCooSysCnt->getCoordinateSystems(); + for (const auto& xCooSys : aCooSysSeq) + { + if (bFound) + break; + const sal_Int32 nDim = xCooSys->getDimension(); + for (sal_Int32 i = 0; i < nDim && !bFound; ++i) + { + const sal_Int32 nMaxAxIdx = xCooSys->getMaximumAxisIndexByDimension(i); + for (sal_Int32 j = 0; j <= nMaxAxIdx && !bFound; ++j) + { + Reference xAxis = xCooSys->getAxisByDimension(i, j); + Reference xAxisProp( xAxis, uno::UNO_QUERY); + if (!xAxisProp.is()) + continue; + sal_Int32 nStoredId = -1; + try + { + xAxisProp->getPropertyValue(u"AxisId"_ustr) >>= nStoredId; + } + catch (const uno::Exception&) + { + continue; + } + if (nStoredId == nAxisId) + { + bool bCatNotVal = false; + xAxisProp->getPropertyValue(u"CatNotVal"_ustr) >>= bCatNotVal; + eAxisType = bCatNotVal ? AXIS_CATEGORY : AXIS_VALUE; + bFound = true; + } + } + } + } + } + } + catch (const uno::Exception&) + { + } + + // nCrossAx is unused for chartex ( has no crossAx field), + // so the value passed for the third parameter is irrelevant + maAxes.emplace_back(eAxisType, nAxisId, -1); } } @@ -6230,6 +6966,7 @@ bool ChartExport::isChartexNotChartNS(NamespaceAbbrev *peNS) const break; case chart::TYPEID_BOXWHISKER: case chart::TYPEID_CLUSTEREDCOLUMN: + case chart::TYPEID_HISTO: case chart::TYPEID_PARETOLINE: case chart::TYPEID_SUNBURST: case chart::TYPEID_TREEMAP: diff --git a/oox/source/export/chartgeographyexport.cxx b/oox/source/export/chartgeographyexport.cxx new file mode 100644 index 000000000000..2ebf4d059bd7 --- /dev/null +++ b/oox/source/export/chartgeographyexport.cxx @@ -0,0 +1,346 @@ +/* -*- 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 +#include +#include +#include +#include + +// Code for exporting content in a chartex chart, used for the +// regionMap chart type. + +using namespace ::com::sun::star; + +namespace oox::drawingml::chart +{ +namespace +{ +const char* toNullableStr(const std::optional& rOpt, OString& rBuf) +{ + if (!rOpt.has_value()) + return nullptr; + rBuf = rOpt->toUtf8(); + return rBuf.getStr(); +} + +void writeAddress(const GeoAddressModel& rAddr, const sax_fastparser::FSHelperPtr& pFS) +{ + OString b1, b2, b3, b4, b5, b6, b7; + pFS->singleElement( + FSNS(XML_cx, XML_address), XML_address1, toNullableStr(rAddr.mosAddress1, b1), + XML_countryRegion, toNullableStr(rAddr.mosCountryRegion, b2), XML_adminDistrict1, + toNullableStr(rAddr.mosAdminDistrict1, b3), XML_adminDistrict2, + toNullableStr(rAddr.mosAdminDistrict2, b4), XML_postalCode, + toNullableStr(rAddr.mosPostalCode, b5), XML_locality, toNullableStr(rAddr.mosLocality, b6), + XML_isoCountryCode, toNullableStr(rAddr.mosIsoCountryCode, b7)); +} + +void writeLocResults(const std::vector& rResults, + const sax_fastparser::FSHelperPtr& pFS) +{ + if (rResults.empty()) + return; + pFS->startElement(FSNS(XML_cx, XML_geoLocationQueryResults)); + for (const auto& rR : rResults) + { + pFS->startElement(FSNS(XML_cx, XML_geoLocationQueryResult)); + if (rR.mxQuery.has_value()) + { + const auto& q = *rR.mxQuery; + OString b1, b2, b3, b4, b5; + pFS->singleElement(FSNS(XML_cx, XML_geoLocationQuery), XML_countryRegion, + toNullableStr(q.mosCountryRegion, b1), XML_adminDistrict1, + toNullableStr(q.mosAdminDistrict1, b2), XML_adminDistrict2, + toNullableStr(q.mosAdminDistrict2, b3), XML_postalCode, + toNullableStr(q.mosPostalCode, b4), XML_entityType, + toNullableStr(q.mosEntityType, b5)); + } + if (!rR.maLocations.empty()) + { + pFS->startElement(FSNS(XML_cx, XML_geoLocations)); + for (const auto& rLoc : rR.maLocations) + { + OString b1, b2, b3, b4; + if (rLoc.mxAddress.has_value()) + { + pFS->startElement(FSNS(XML_cx, XML_geoLocation), XML_latitude, + toNullableStr(rLoc.mosLatitude, b1), XML_longitude, + toNullableStr(rLoc.mosLongitude, b2), XML_entityName, + toNullableStr(rLoc.mosEntityName, b3), XML_entityType, + toNullableStr(rLoc.mosEntityType, b4)); + writeAddress(*rLoc.mxAddress, pFS); + pFS->endElement(FSNS(XML_cx, XML_geoLocation)); + } + else + { + pFS->singleElement(FSNS(XML_cx, XML_geoLocation), XML_latitude, + toNullableStr(rLoc.mosLatitude, b1), XML_longitude, + toNullableStr(rLoc.mosLongitude, b2), XML_entityName, + toNullableStr(rLoc.mosEntityName, b3), XML_entityType, + toNullableStr(rLoc.mosEntityType, b4)); + } + } + pFS->endElement(FSNS(XML_cx, XML_geoLocations)); + } + pFS->endElement(FSNS(XML_cx, XML_geoLocationQueryResult)); + } + pFS->endElement(FSNS(XML_cx, XML_geoLocationQueryResults)); +} + +void writeDataResults(const std::vector& rResults, + const sax_fastparser::FSHelperPtr& pFS) +{ + if (rResults.empty()) + return; + pFS->startElement(FSNS(XML_cx, XML_geoDataEntityQueryResults)); + for (const auto& rR : rResults) + { + pFS->startElement(FSNS(XML_cx, XML_geoDataEntityQueryResult)); + if (rR.mxQuery.has_value()) + { + OString b1, b2; + pFS->singleElement(FSNS(XML_cx, XML_geoDataEntityQuery), XML_entityType, + toNullableStr(rR.mxQuery->mosEntityType, b1), XML_entityId, + toNullableStr(rR.mxQuery->mosEntityId, b2)); + } + if (rR.mxData.has_value()) + { + const auto& d = *rR.mxData; + OString b1, b2, b3, b4, b5, b6; + pFS->startElement( + FSNS(XML_cx, XML_geoData), XML_entityName, toNullableStr(d.mosEntityName, b1), + XML_entityId, toNullableStr(d.mosEntityId, b2), XML_east, + toNullableStr(d.mosEast, b3), XML_west, toNullableStr(d.mosWest, b4), XML_north, + toNullableStr(d.mosNorth, b5), XML_south, toNullableStr(d.mosSouth, b6)); + + if (!d.maPolygons.empty()) + { + pFS->startElement(FSNS(XML_cx, XML_geoPolygons)); + for (const auto& rP : d.maPolygons) + { + OString pb1, pb2, pb3; + pFS->singleElement(FSNS(XML_cx, XML_geoPolygon), XML_polygonId, + toNullableStr(rP.mosPolygonId, pb1), XML_numPoints, + toNullableStr(rP.mosNumPoints, pb2), XML_pcaRings, + toNullableStr(rP.mosPcaRings, pb3)); + } + pFS->endElement(FSNS(XML_cx, XML_geoPolygons)); + } + + if (!d.maCopyrights.empty()) + { + pFS->startElement(FSNS(XML_cx, XML_copyrights)); + for (const auto& rC : d.maCopyrights) + { + pFS->startElement(FSNS(XML_cx, XML_copyright)); + pFS->writeEscaped(rC.msText); + pFS->endElement(FSNS(XML_cx, XML_copyright)); + } + pFS->endElement(FSNS(XML_cx, XML_copyrights)); + } + + pFS->endElement(FSNS(XML_cx, XML_geoData)); + } + pFS->endElement(FSNS(XML_cx, XML_geoDataEntityQueryResult)); + } + pFS->endElement(FSNS(XML_cx, XML_geoDataEntityQueryResults)); +} + +void writePtResults(const std::vector& rResults, + const sax_fastparser::FSHelperPtr& pFS) +{ + if (rResults.empty()) + return; + pFS->startElement(FSNS(XML_cx, XML_geoDataPointToEntityQueryResults)); + for (const auto& rR : rResults) + { + pFS->startElement(FSNS(XML_cx, XML_geoDataPointToEntityQueryResult)); + if (rR.mxPointQuery.has_value()) + { + OString b1, b2, b3; + pFS->singleElement(FSNS(XML_cx, XML_geoDataPointQuery), XML_entityType, + toNullableStr(rR.mxPointQuery->mosEntityType, b1), XML_latitude, + toNullableStr(rR.mxPointQuery->mosLatitude, b2), XML_longitude, + toNullableStr(rR.mxPointQuery->mosLongitude, b3)); + } + if (rR.mxEntityQuery.has_value()) + { + OString b1, b2; + pFS->singleElement(FSNS(XML_cx, XML_geoDataPointToEntityQuery), XML_entityType, + toNullableStr(rR.mxEntityQuery->mosEntityType, b1), XML_entityId, + toNullableStr(rR.mxEntityQuery->mosEntityId, b2)); + } + pFS->endElement(FSNS(XML_cx, XML_geoDataPointToEntityQueryResult)); + } + pFS->endElement(FSNS(XML_cx, XML_geoDataPointToEntityQueryResults)); +} + +void writeChildResults(const std::vector& rResults, + const sax_fastparser::FSHelperPtr& pFS) +{ + if (rResults.empty()) + return; + pFS->startElement(FSNS(XML_cx, XML_geoChildEntitiesQueryResults)); + for (const auto& rR : rResults) + { + pFS->startElement(FSNS(XML_cx, XML_geoChildEntitiesQueryResult)); + if (rR.mxQuery.has_value()) + { + OString b1; + pFS->startElement(FSNS(XML_cx, XML_geoChildEntitiesQuery), XML_entityId, + toNullableStr(rR.mxQuery->mosEntityId, b1)); + if (!rR.mxQuery->maEntityTypes.empty()) + { + pFS->startElement(FSNS(XML_cx, XML_geoChildTypes)); + for (const auto& rT : rR.mxQuery->maEntityTypes) + { + pFS->startElement(FSNS(XML_cx, XML_entityType)); + pFS->writeEscaped(rT); + pFS->endElement(FSNS(XML_cx, XML_entityType)); + } + pFS->endElement(FSNS(XML_cx, XML_geoChildTypes)); + } + pFS->endElement(FSNS(XML_cx, XML_geoChildEntitiesQuery)); + } + if (!rR.maEntities.empty()) + { + pFS->startElement(FSNS(XML_cx, XML_geoChildEntities)); + for (const auto& rE : rR.maEntities) + { + OString b1, b2, b3; + pFS->singleElement(FSNS(XML_cx, XML_geoHierarchyEntity), XML_entityName, + toNullableStr(rE.mosEntityName, b1), XML_entityId, + toNullableStr(rE.mosEntityId, b2), XML_entityType, + toNullableStr(rE.mosEntityType, b3)); + } + pFS->endElement(FSNS(XML_cx, XML_geoChildEntities)); + } + pFS->endElement(FSNS(XML_cx, XML_geoChildEntitiesQueryResult)); + } + pFS->endElement(FSNS(XML_cx, XML_geoChildEntitiesQueryResults)); +} + +void writeParentResults(const std::vector& rResults, + const sax_fastparser::FSHelperPtr& pFS) +{ + if (rResults.empty()) + return; + pFS->startElement(FSNS(XML_cx, XML_geoParentEntitiesQueryResults)); + for (const auto& rR : rResults) + { + pFS->startElement(FSNS(XML_cx, XML_geoParentEntitiesQueryResult)); + if (rR.mxQuery.has_value()) + { + OString b1; + pFS->singleElement(FSNS(XML_cx, XML_geoParentEntitiesQuery), XML_entityId, + toNullableStr(rR.mxQuery->mosEntityId, b1)); + } + if (rR.mxEntity.has_value()) + { + OString b1, b2; + pFS->singleElement(FSNS(XML_cx, XML_geoEntity), XML_entityName, + toNullableStr(rR.mxEntity->mosEntityName, b1), XML_entityType, + toNullableStr(rR.mxEntity->mosEntityType, b2)); + } + if (rR.mxParentEntity.has_value()) + { + OString b1; + pFS->singleElement(FSNS(XML_cx, XML_geoParentEntity), XML_entityId, + toNullableStr(rR.mxParentEntity->mosEntityId, b1)); + } + pFS->endElement(FSNS(XML_cx, XML_geoParentEntitiesQueryResult)); + } + pFS->endElement(FSNS(XML_cx, XML_geoParentEntitiesQueryResults)); +} + +} // anonymous namespace + +void exportGeography(const uno::Reference& xSeriesProp, + const sax_fastparser::FSHelperPtr& pFS) +{ + if (!xSeriesProp.is()) + return; + + sal_Int32 nProjType = 0, nViewedRegion = 0; + OUString sCultureLanguage, sCultureRegion, sAttribution; + uno::Any aPT = xSeriesProp->getPropertyValue(u"GeographyProjectionType"_ustr); + uno::Any aVR = xSeriesProp->getPropertyValue(u"GeographyViewedRegionType"_ustr); + uno::Any aCL = xSeriesProp->getPropertyValue(u"GeographyCultureLanguage"_ustr); + uno::Any aCR = xSeriesProp->getPropertyValue(u"GeographyCultureRegion"_ustr); + uno::Any aAT = xSeriesProp->getPropertyValue(u"GeographyAttribution"_ustr); + + bool bHasPT = (aPT >>= nProjType); + bool bHasVR = (aVR >>= nViewedRegion); + bool bHasCL = (aCL >>= sCultureLanguage); + bool bHasCR = (aCR >>= sCultureRegion); + bool bHasAT = (aAT >>= sAttribution); + + OUString sProjStr, sViewedStr; + if (bHasPT) + sProjStr = geoProjectionTypeToString(static_cast(nProjType)); + if (bHasVR) + sViewedStr = geoMappingLevelToString(static_cast(nViewedRegion)); + + if (!bHasPT && !bHasVR && !bHasCL && !bHasCR && !bHasAT) + return; + + pFS->startElement(FSNS(XML_cx, XML_geography), XML_projectionType, + bHasPT ? sProjStr.toUtf8().getStr() : nullptr, XML_viewedRegionType, + bHasVR ? sViewedStr.toUtf8().getStr() : nullptr, XML_cultureLanguage, + bHasCL ? sCultureLanguage.toUtf8().getStr() : nullptr, XML_cultureRegion, + bHasCR ? sCultureRegion.toUtf8().getStr() : nullptr, XML_attribution, + bHasAT ? sAttribution.toUtf8().getStr() : nullptr); + + // Handle the geoCache child element + OUString sProvider; + uno::Any aProvider = xSeriesProp->getPropertyValue(u"GeoCacheProvider"_ustr); + bool bHasProvider = (aProvider >>= sProvider); + + OUString sBinary; + uno::Any aBinary = xSeriesProp->getPropertyValue(u"GeoCacheBinary"_ustr); + bool bHasBinary = (aBinary >>= sBinary); + + uno::Sequence aClearData; + uno::Any aClear = xSeriesProp->getPropertyValue(u"GeoCacheClearData"_ustr); + bool bHasClear = (aClear >>= aClearData) && aClearData.hasElements(); + + if (bHasProvider || bHasBinary || bHasClear) + { + pFS->startElement(FSNS(XML_cx, XML_geoCache), XML_provider, + bHasProvider ? sProvider.toUtf8().getStr() : nullptr); + + if (bHasBinary) + { + pFS->startElement(FSNS(XML_cx, XML_binary)); + pFS->writeEscaped(sBinary); + pFS->endElement(FSNS(XML_cx, XML_binary)); + } + else if (bHasClear) + { + GeoClearModel aClearModel = geoClearFromPropertyValues(aClearData); + + pFS->startElement(FSNS(XML_cx, XML_clear)); + writeLocResults(aClearModel.maLocResults, pFS); + writeDataResults(aClearModel.maDataResults, pFS); + writePtResults(aClearModel.maPtResults, pFS); + writeChildResults(aClearModel.maChildResults, pFS); + writeParentResults(aClearModel.maParentResults, pFS); + pFS->endElement(FSNS(XML_cx, XML_clear)); + } + + pFS->endElement(FSNS(XML_cx, XML_geoCache)); + } + + pFS->endElement(FSNS(XML_cx, XML_geography)); +} + +} // namespace oox::drawingml::chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index dad687ffe2aa..afdbb12509cf 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -123,6 +124,7 @@ #include #include #include +#include #include #include #include @@ -204,6 +206,11 @@ bool URLTransformer::isExternalURL(const OUString& rURL) const return bExternal; } +sal_Int32 URLTransformer::getExternalLinkIndex(const OUString& /*rUrl*/) const +{ + return 0; +} + GraphicExportCache& GraphicExportCache::get() { static GraphicExportCache staticGraphicExportCache; @@ -261,6 +268,7 @@ DrawingML::DrawingML(::sax_fastparser::FSHelperPtr pFS, ::oox::core::XmlFilterBa , mbIsBackgroundDark(false) , mbPlaceholder(false) , mbDiagaramExport(false) + , mbDiagaramReplacementExport(false) { uno::Reference xSettings(pFB->getModelFactory()->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY); if (xSettings.is()) @@ -509,7 +517,7 @@ void DrawingML::WriteSolidFill( const Reference< XPropertySet >& rXPropSet ) bNeedGradientFill = !aTransparenceGradient.GetColorStops().isSingleColor(aSingleColor); // we no longer need to 'guess' if FillTransparenceGradient is used by - // comparing it's 1st color to COL_BLACK after having tested that the + // comparing its 1st color to COL_BLACK after having tested that the // FillTransparenceGradientName is set if (!bNeedGradientFill) { @@ -627,13 +635,6 @@ void DrawingML::WriteGradientStop(double fOffset, const basegfx::BColor& rColor, mpFS->endElementNS( XML_a, XML_gs ); } -::Color DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity ) -{ - return ::Color(ColorTransparency, ( ( ( nColor & 0xff ) * nIntensity ) / 100 ) - | ( ( ( ( ( nColor & 0xff00 ) >> 8 ) * nIntensity ) / 100 ) << 8 ) - | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 )); -} - void DrawingML::WriteGradientFill( const Reference< XPropertySet >& rXPropSet ) { if (!GetProperty(rXPropSet, u"FillGradient"_ustr)) @@ -661,7 +662,7 @@ void DrawingML::WriteGradientFill( const Reference< XPropertySet >& rXPropSet ) // only for DOCX. if (aOriginalGradient == aGradient && GetDocumentType() == DOCUMENT_DOCX) { - // If we have no gradient stops that means original gradient were defined by a theme. + // If we have no gradient stops that means original gradient was defined by a theme. if( aGradientStops.hasElements() ) { mpFS->startElementNS(XML_a, XML_gradFill, XML_rotWithShape, "0"); @@ -1135,7 +1136,7 @@ void DrawingML::WriteOutline( const Reference& rXPropSet, Referenc bool bIsRelative(aLineDash.Style == DashStyle_RECTRELATIVE || aLineDash.Style == DashStyle_ROUNDRELATIVE); if ( bIsRelative && aLineDash.Dots == 1) - { // The length were tweaked on import in case of prstDash. Revert it here. + { // The lengths were tweaked on import in case of prstDash. Revert it here. sal_uInt32 nDotLen = aLineDash.DotLen; sal_uInt32 nDashLen = aLineDash.DashLen; sal_uInt32 nDistance = aLineDash.Distance; @@ -1147,7 +1148,7 @@ void DrawingML::WriteOutline( const Reference& rXPropSet, Referenc nDashLen += 99; } // LO uses length 0 for 100%, if the attribute is missing in ODF. - // Other applications might write 100%. Make is unique for the conditions. + // Other applications might write 100%. Make it unique for the conditions. if (nDotLen == 0) nDotLen = 100; if (nDashLen == 0 && aLineDash.Dashes > 0) @@ -1624,7 +1625,7 @@ OUString GraphicExport::writeNewSvgEntryToStorage(const Graphic& rGraphic, bool return sPath; } -OUString GraphicExport::writeToStorage(const Graphic& rGraphic, bool bRelPathToMedia, TypeHint eHint) +OUString GraphicExport::writeToStorage(const Graphic& rGraphic, bool bRelPathToMedia, TypeHint eHint, bool bReturnPath) { OUString sPath; @@ -1646,8 +1647,10 @@ OUString GraphicExport::writeToStorage(const Graphic& rGraphic, bool bRelPathToM return OUString(); // couldn't store } - OUString sRelId = mpFilterBase->addRelation(mpFS->getOutputStream(), oox::getRelationship(Relationship::IMAGE), sPath); + if (bReturnPath) + return sPath; + OUString sRelId = mpFilterBase->addRelation(mpFS->getOutputStream(), oox::getRelationship(Relationship::IMAGE), sPath); return sRelId; } @@ -1656,6 +1659,15 @@ std::shared_ptr DrawingML::createGraphicExport() return std::make_shared(mpFS, mpFB, meDocumentType); } +OUString DrawingML::writeImageRelToStorage(const Graphic &rGraphic) +{ + const auto& pVectorGraphicDataPtr = rGraphic.getVectorGraphicData(); + const bool bIsSVG(pVectorGraphicDataPtr && pVectorGraphicDataPtr->getType() == VectorGraphicDataType::Svg); + GraphicExport aExporter(mpFS, mpFB, meDocumentType); + + return aExporter.writeToStorage(rGraphic, isDiagaramExport(), bIsSVG ? GraphicExport::TypeHint::SVG : GraphicExport::TypeHint::Detect, true); +} + OUString DrawingML::writeGraphicToStorage(const Graphic& rGraphic , bool bRelPathToMedia, GraphicExport::TypeHint eHint) { GraphicExport aExporter(mpFS, mpFB, meDocumentType); @@ -1887,7 +1899,10 @@ void DrawingML::WriteBlipFill(const Reference& rXPropSet, const aw bool bWriteMode = false; if (sURLPropName == "FillBitmap" || sURLPropName == "BackGraphic") bWriteMode = true; - WriteXGraphicBlipFill(rXPropSet, xGraphic, nXmlNamespace, bWriteMode, false, rSize); + + // we need to use bRelPathToMedia when DiagramExport and it contains media data + // or links + WriteXGraphicBlipFill(rXPropSet, xGraphic, nXmlNamespace, bWriteMode, isDiagaramExport(), rSize); } } @@ -2282,7 +2297,10 @@ void DrawingML::WriteTransformation(const Reference< XShape >& xShape, const too sal_Int32 nLeft = rRect.Left(); sal_Int32 nTop = rRect.Top(); - if (GetDocumentType() == DOCUMENT_DOCX && !m_xParent.is()) + + // do *not* fallback to (0, 0) again when in DiagaramReplacementExport, that + // works more like a GraphicReplacement ObjectHierarchy snippet + if (GetDocumentType() == DOCUMENT_DOCX && !m_xParent.is() && !isDiagaramReplacementExport()) { nLeft = 0; nTop = 0; @@ -2841,6 +2859,19 @@ void DrawingML::WriteRunProperties(const Reference& rRun, sal_Int3 } } + auto getExportFontName = [](const OUString& rTypeface, const OUString& rStyleName) -> OUString + { + if (rStyleName.isEmpty()) + return rTypeface; + if (OutputDevice* pDev = Application::GetDefaultDevice()) + { + OUString aLegacy; + if (pDev->GetLegacyFontName(rTypeface, rStyleName, WEIGHT_DONTKNOW, ITALIC_DONTKNOW, aLegacy)) + return aLegacy; + } + return rTypeface; + }; + if (GetProperty(rXPropSet, u"CharFontName"_ustr)) { const char* const pitch = nullptr; @@ -2849,6 +2880,11 @@ void DrawingML::WriteRunProperties(const Reference& rRun, sal_Int3 mAny >>= usTypeface; + OUString usStyleName; + if (GetProperty(rXPropSet, u"CharFontStyleName"_ustr)) + mAny >>= usStyleName; + usTypeface = getExportFontName(usTypeface, usStyleName); + if (!mbEmbedFonts || EmbeddedFontsManager::isCommonFont(usTypeface)) { OUString aSubstName( GetSubsFontName( usTypeface, SubsFontFlags::ONLYONE | SubsFontFlags::MS ) ); @@ -2871,6 +2907,13 @@ void DrawingML::WriteRunProperties(const Reference& rRun, sal_Int3 OUString usTypeface; mAny >>= usTypeface; + + OUString usStyleName; + if (GetDirectProperty(rXPropSet, rXPropState, + bComplex ? u"CharFontStyleNameComplex"_ustr : u"CharFontStyleNameAsian"_ustr)) + mAny >>= usStyleName; + usTypeface = getExportFontName(usTypeface, usStyleName); + if (!mbEmbedFonts || EmbeddedFontsManager::isCommonFont(usTypeface)) { OUString aSubstName( GetSubsFontName( usTypeface, SubsFontFlags::ONLYONE | SubsFontFlags::MS ) ); @@ -2988,6 +3031,12 @@ OUString DrawingML::GetFieldValue( const css::uno::Reference< css::text::XTextRa rXPropSet->getPropertyValue(UNO_TC_PROP_NUMFORMAT) >>= nNumFmt; aFieldValue = GetDatetimeTypeFromDate(static_cast(nNumFmt)); } + else if(aFieldKind == "DateTime") + { + // The date/time field of a header/footer area carries no format of its own - + // the page holds it - and "datetime" seems a perfect fit (see MS-OI29500). + aFieldValue = u"datetime"_ustr; + } else if(aFieldKind == "ExtTime") { sal_Int32 nNumFmt = -1; @@ -4167,15 +4216,8 @@ void DrawingML::WriteBodyProps(const css::uno::Reference< css::uno::XInterface > sWritingMode = "vert270"; else if (nTextPreRotateAngle == -180 || nTextPreRotateAngle == 180) { -#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif nTextRotateAngleDeg100 = NormAngle18000(nTextRotateAngleDeg100.value_or(0_deg100) + 18000_deg100); -#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12 -#pragma GCC diagnostic pop -#endif // ToDo: Examine insets. They might need rotation too. Check diagrams (SmartArt). } else @@ -4216,15 +4258,8 @@ void DrawingML::WriteBodyProps(const css::uno::Reference< css::uno::XInterface > std::optional sTextRotateAngleMSUnit; if (nTextRotateAngleDeg100.has_value()) -#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif sTextRotateAngleMSUnit = oox::drawingml::calcRotationValue(nTextRotateAngleDeg100.value().get()); -#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12 -#pragma GCC diagnostic pop -#endif // Prepare attributes 'anchor' and 'anchorCtr' // LibreOffice has 12 value sets, MS Office only 6. We map them so, that it reverses the @@ -4572,6 +4607,10 @@ void DrawingML::WriteText(const Reference& rXIface, bool bBodyPr, bo if (bBodyPr) { WriteBodyProps(rXIface, nXmlNamespace, bIsFontworkShape, nTop, nBottom, nLeft, nRight); + } + else + { + mpFS->singleElementNS(XML_a, XML_bodyPr); } // end of bodyPr Reference< XEnumerationAccess > access( xXText, UNO_QUERY ); @@ -4988,7 +5027,7 @@ bool IsValidOOXMLFormula(std::u16string_view sFormula) for (sal_Int16 i = 1; i < nSize; i++) { OUString sVal = strTokens[i]; - if (builtInVariables.find(sVal) != builtInVariables.end()) + if (builtInVariables.contains(sVal)) continue; // valid built-in variable // TODO: recognize valid 'guide name' pointing to other equations or adjustments @@ -5783,6 +5822,86 @@ void DrawingML::WriteEmptyCustomGeometry() mpFS->endElementNS(XML_a, XML_custGeom); } +bool DrawingML::WriteGraphicClipCustomGeometry(const Reference& rXPropSet, + const awt::Size& rSize) +{ + if (!rXPropSet.is() + || !rXPropSet->getPropertySetInfo()->hasPropertyByName( + u"GraphicClipPolyPolygon"_ustr)) + return false; + + drawing::PolyPolygonBezierCoords aClip; + if (!(rXPropSet->getPropertyValue(u"GraphicClipPolyPolygon"_ustr) >>= aClip) + || !aClip.Coordinates.hasElements()) + return false; + + mpFS->startElementNS(XML_a, XML_custGeom); + mpFS->singleElementNS(XML_a, XML_avLst); + mpFS->singleElementNS(XML_a, XML_gdLst); + mpFS->singleElementNS(XML_a, XML_ahLst); + mpFS->singleElementNS(XML_a, XML_rect, XML_l, "0", XML_t, "0", XML_r, "r", XML_b, "b"); + mpFS->startElementNS(XML_a, XML_pathLst); + + // The polygon is in the shape's own coordinates, so the path spans the shape and a point needs + // no conversion. All the contours share one path, which is what subtracts the areas they + // overlap - that is how a frame with a hole in it is described. + mpFS->startElementNS(XML_a, XML_path, XML_w, OString::number(rSize.Width), XML_h, + OString::number(rSize.Height)); + + auto writePoint = [this](const awt::Point& rPoint) { + mpFS->singleElementNS(XML_a, XML_pt, XML_x, OString::number(rPoint.X), XML_y, + OString::number(rPoint.Y)); + }; + + for (sal_Int32 nContour = 0; nContour < aClip.Coordinates.getLength(); ++nContour) + { + const Sequence& rPoints = aClip.Coordinates[nContour]; + // A contour may carry no flags at all; every point is then an ordinary one. + const Sequence aNoFlags; + const Sequence& rFlags + = nContour < aClip.Flags.getLength() ? aClip.Flags[nContour] : aNoFlags; + if (!rPoints.hasElements()) + continue; + + mpFS->startElementNS(XML_a, XML_moveTo); + writePoint(rPoints[0]); + mpFS->endElementNS(XML_a, XML_moveTo); + + for (sal_Int32 nPoint = 1; nPoint < rPoints.getLength(); ++nPoint) + { + const bool bControl = nPoint < rFlags.getLength() + && rFlags[nPoint] == drawing::PolygonFlags_CONTROL; + if (!bControl) + { + mpFS->startElementNS(XML_a, XML_lnTo); + writePoint(rPoints[nPoint]); + mpFS->endElementNS(XML_a, XML_lnTo); + continue; + } + + // A curve is two control points and the point they lead to. The one that closes a + // contour leads back to the point the contour started from and states no end point of + // its own, so the start point answers for it. + if (nPoint + 1 >= rPoints.getLength()) + break; + const bool bClosing = nPoint + 2 >= rPoints.getLength(); + mpFS->startElementNS(XML_a, XML_cubicBezTo); + writePoint(rPoints[nPoint]); + writePoint(rPoints[nPoint + 1]); + writePoint(bClosing ? rPoints[0] : rPoints[nPoint + 2]); + mpFS->endElementNS(XML_a, XML_cubicBezTo); + nPoint += 2; + } + + mpFS->singleElementNS(XML_a, XML_close); + } + + mpFS->endElementNS(XML_a, XML_path); + mpFS->endElementNS(XML_a, XML_pathLst); + mpFS->endElementNS(XML_a, XML_custGeom); + return true; +} + // version for SdrPathObj void DrawingML::WritePolyPolygon(const css::uno::Reference& rXShape, const bool bClosed) @@ -6857,7 +6976,6 @@ void DrawingML::WriteDiagram(const css::uno::Reference& rX uno::Reference drawingDom; rIDiagramHelper->getOOXDomValue(svx::diagram::DomMapFlag::OOXDrawing) >>= drawingDom; static bool bForceAlwaysReCreate(nullptr != std::getenv("FORCE_RECREATE_DIAGRAM_DATADOMS")); - static bool bActivateAdvancedDiagramFeatures(nullptr != std::getenv("ACTIVATE_ADVANCED_DIAGRAM_FEATURES")); // check if re-creation is forced (for test purposes) if (drawingDom && bForceAlwaysReCreate) @@ -6877,7 +6995,7 @@ void DrawingML::WriteDiagram(const css::uno::Reference& rX const OUString sRelationCompPrefix(GetRelationCompPrefix()); const OUString sDir(GetComponentDir()); - if (bActivateAdvancedDiagramFeatures || drawingDom.is()) + if (SdrObject::useAdvancedDiagramFeatures() || drawingDom.is()) { // only add Relation if we write a DrawingDom drawingRelId = mpFB->addRelation( @@ -6885,14 +7003,14 @@ void DrawingML::WriteDiagram(const css::uno::Reference& rX Concat2View(sRelationCompPrefix + drawingFileName)); } - if (!drawingDom && bActivateAdvancedDiagramFeatures) + if (!drawingDom && SdrObject::useAdvancedDiagramFeatures()) { // no drawingDom exists, so it was either not originally imported or the // Diagram was changed, so it got deleted. write drawingDom directly as // sub-content uno::Reference xOutputStream = mpFB->openFragmentStream( sDir + "/" + drawingFileName, - u"application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml"_ustr); + u"application/vnd.ms-office.drawingml.diagramDrawing+xml"_ustr); if (xOutputStream) pAdvancedDiagramHelper->writeDiagramOOXDrawing(*this, xOutputStream); @@ -6947,24 +7065,30 @@ void DrawingML::WriteDiagram(const css::uno::Reference& rX } else { - mpFS->startElementNS(XML_p, XML_nvGraphicFramePr); + // use correct XmlNamespace, other DocumentType is DOCUMENT_XLSX + const bool isPPTX(DOCUMENT_PPTX == GetDocumentType()); + const sal_Int32 nXmlNamespace(isPPTX ? XML_p : XML_xdr); + mpFS->startElementNS(nXmlNamespace, XML_nvGraphicFramePr); - mpFS->singleElementNS(XML_p, XML_cNvPr, pDocPrAttrList); - mpFS->singleElementNS(XML_p, XML_cNvGraphicFramePr); + mpFS->singleElementNS(nXmlNamespace, XML_cNvPr, pDocPrAttrList); + mpFS->singleElementNS(nXmlNamespace, XML_cNvGraphicFramePr); - mpFS->startElementNS(XML_p, XML_nvPr); - mpFS->startElementNS(XML_p, XML_extLst); - // change tracking extension - required in PPTX - mpFS->startElementNS(XML_p, XML_ext, XML_uri, "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}"); - mpFS->singleElementNS(XML_p14, XML_modId, - FSNS(XML_xmlns, XML_p14), mpFB->getNamespaceURL(OOX_NS(p14)), - XML_val, - OString::number(comphelper::rng::uniform_uint_distribution(1, SAL_MAX_UINT32))); - mpFS->endElementNS(XML_p, XML_ext); - mpFS->endElementNS(XML_p, XML_extLst); - mpFS->endElementNS(XML_p, XML_nvPr); + if (isPPTX) + { + mpFS->startElementNS(nXmlNamespace, XML_nvPr); + mpFS->startElementNS(nXmlNamespace, XML_extLst); + // change tracking extension - required in PPTX + mpFS->startElementNS(nXmlNamespace, XML_ext, XML_uri, "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}"); + mpFS->singleElementNS(XML_p14, XML_modId, + FSNS(XML_xmlns, XML_p14), mpFB->getNamespaceURL(OOX_NS(p14)), + XML_val, + OString::number(comphelper::rng::uniform_uint_distribution(1, SAL_MAX_UINT32))); + mpFS->endElementNS(nXmlNamespace, XML_ext); + mpFS->endElementNS(nXmlNamespace, XML_extLst); + mpFS->endElementNS(nXmlNamespace, XML_nvPr); + } - mpFS->endElementNS(XML_p, XML_nvGraphicFramePr); + mpFS->endElementNS(nXmlNamespace, XML_nvGraphicFramePr); // store size and position of background shape instead of group shape // as some shapes may be outside @@ -6977,7 +7101,7 @@ void DrawingML::WriteDiagram(const css::uno::Reference& rX awt::Size aSize = xShapeBg->getSize(); WriteTransformation( xShapeBg, tools::Rectangle(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height)), - XML_p, false, false, 0, false); + nXmlNamespace, false, false, 0, false); } mpFS->startElementNS(XML_a, XML_graphic); @@ -7021,8 +7145,8 @@ void DrawingML::WriteDiagram(const css::uno::Reference& rX { if (!drawingRelId.isEmpty()) { - // NOTE: drawingRelId may be empty if bActivateAdvancedDiagramFeatures is - // set, see comments above + // NOTE: drawingRelId may be empty if SdrObject::useAdvancedDiagramFeatures() + // is set, see comments above // the original and unchanged dataDom contains a reference to the drawing // relation. We need to update it with the new generated relation value // before writing the dom to the file @@ -7062,7 +7186,7 @@ void DrawingML::WriteDiagram(const css::uno::Reference& rX >>= xDataHlinkRelSeq; // write the associated Images and rels for data file - writeDiagramImageRels(xDataImageRelSeq, xDataOutputStream, u"OOXDiagramDataRels", nDiagramId); + writeDiagramImageRels(xDataImageRelSeq, xDataOutputStream); writeDiagramHlinkRels(xDataHlinkRelSeq, xDataOutputStream); } @@ -7112,14 +7236,13 @@ void DrawingML::WriteDiagram(const css::uno::Reference& rX >>= xDrawingHlinkRelSeq; // write the associated Images and rels for data file - writeDiagramImageRels(xDrawingImageRelSeq, xDrawingOutputStream, u"OOXDiagramDrawingRels", nDiagramId); + writeDiagramImageRels(xDrawingImageRelSeq, xDrawingOutputStream); writeDiagramHlinkRels(xDrawingHlinkRelSeq, xDrawingOutputStream); } } void DrawingML::writeDiagramImageRels(const uno::Sequence>& xRelSeq, - const uno::Reference& xOutStream, - std::u16string_view sGrabBagProperyName, int nDiagramId) + const uno::Reference& xOutStream) { // add image relationships of OOXData, SmartArtDiagram OUString sType(oox::getRelationship(Relationship::IMAGE)); @@ -7131,49 +7254,31 @@ void DrawingML::writeDiagramImageRels(const uno::Sequence RID, - // diagramDataRelTuple[1] => xInputStream - // diagramDataRelTuple[2] => extension + // diagramDataRelTuple[1] => XGraphic const uno::Sequence& diagramDataRelTuple = xRelSeq[j]; OUString sRelId; - OUString sExtension; diagramDataRelTuple[0] >>= sRelId; - diagramDataRelTuple[2] >>= sExtension; - OUString sContentType; - if (sExtension.equalsIgnoreAsciiCase(".WMF")) - sContentType = "image/x-wmf"; - else - sContentType = OUString::Concat("image/") + sExtension.subView(1); sRelId = sRelId.copy(3); - StreamDataSequence dataSeq; - diagramDataRelTuple[1] >>= dataSeq; - uno::Reference dataImagebin( - new ::comphelper::SequenceInputStream(dataSeq)); + // get XGraphic + uno::Reference xGraphic; + diagramDataRelTuple[1] >>= xGraphic; - //nDiagramId is used to make the name unique irrespective of the number of smart arts. - OUString sFragment = OUString::Concat("media/") + sGrabBagProperyName - + OUString::number(nDiagramId) + "_" - + OUString::number(j) + sExtension; - - PropertySet aProps(xOutStream); - aProps.setAnyProperty(PROP_RelId, uno::Any(sRelId.toInt32())); - - mpFB->addRelation(xOutStream, sType, Concat2View("../" + sFragment)); - - OUString sDir = GetComponentDir(); - uno::Reference xBinOutStream - = mpFB->openFragmentStream(sDir + "/" + sFragment, sContentType); - - try + if (xGraphic) { - comphelper::OStorageHelper::CopyInputToOutput(dataImagebin, xBinOutStream); + // write to Storage and get relative path back + ::Graphic aGraphic(xGraphic); + const OUString sFragment = writeImageRelToStorage(aGraphic); + + PropertySet aProps(xOutStream); + aProps.setAnyProperty(PROP_RelId, uno::Any(sRelId.toInt32())); + + if (GetDocumentType() == DOCUMENT_DOCX) + mpFB->addRelation(xOutStream, sType, Concat2View("../" + sFragment)); + else + mpFB->addRelation(xOutStream, sType, sFragment); } - catch (const uno::Exception&) - { - TOOLS_WARN_EXCEPTION("oox.drawingml", "DrawingML::writeDiagramRels Failed to copy grabbaged Image"); - } - dataImagebin->closeInput(); } } diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx index 205c2abdfa76..f443344265dc 100644 --- a/oox/source/export/shapes.cxx +++ b/oox/source/export/shapes.cxx @@ -506,11 +506,15 @@ ShapeExport& ShapeExport::WriteGroupShape(const uno::Reference& // non visual properties if (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes) { - pFS->startElementNS(mnXmlNamespace, XML_nvGrpSpPr); - pFS->startElementNS(mnXmlNamespace, XML_cNvPr, - XML_id, OString::number(GetNewShapeID(xShape)), - XML_name, GetShapeName(xShape)); uno::Reference const xShapeProps(xShape, uno::UNO_QUERY_THROW); + bool isVisible = true ; + if( GetProperty(xShapeProps, u"Visible"_ustr)) + mAny >>= isVisible; + + pFS->startElementNS(mnXmlNamespace, XML_nvGrpSpPr); + pFS->startElementNS(mnXmlNamespace, XML_cNvPr, XML_id, + OString::number(GetNewShapeID(xShape)), XML_name, GetShapeName(xShape), + XML_hidden, sax_fastparser::UseIf("1", !isVisible)); AddExtLst(pFS, xShapeProps); pFS->endElementNS(mnXmlNamespace, XML_cNvPr); pFS->singleElementNS(mnXmlNamespace, XML_cNvGrpSpPr); @@ -751,7 +755,7 @@ static OUString lcl_GetTarget(const css::uno::Reference& xMo sTarget = "slide" + OUString::number(i + 1) + ".xml"; break; } - else // If URL is linked to a shape, assign it's slide as target + else // If URL is linked to a shape, assign its slide as target { Reference xShapes = xDrawPage; sal_uInt32 nShapes = xShapes->getCount(); @@ -873,16 +877,19 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape ) rtl::Reference pAttrListSp = sax_fastparser::FastSerializerHelper::createAttrList(); + OUString sMacroUrl, sMacro; for (auto const& it : aGrabBagProps) { // export macro attribute of element if (it.Name == u"mso-sp-macro"_ustr) { - OUString sMacro; it.Value >>= sMacro; - if (!sMacro.isEmpty()) - pAttrListSp->add(XML_macro, sMacro); + } + if (it.Name == u"mso-sp-macro-url"_ustr) + { + it.Value >>= sMacroUrl; + continue; } // export textlink attribute of element @@ -912,6 +919,19 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape ) } } + if (!sMacro.isEmpty()) + { + if (sMacro.startsWith("[") && !sMacroUrl.isEmpty()) + { + sal_Int32 nClose = sMacro.indexOf(']'); + sal_Int32 nNewIdx = mpURLTransformer->getExternalLinkIndex(sMacroUrl); + if (nClose > 0 && nNewIdx > 0) + sMacro = "[" + OUString::number(nNewIdx) + sMacro.subView(nClose); + } + + pAttrListSp->add(XML_macro, sMacro); + } + if (isDiagaramExport()) { // add evtl. used DiagramDataModelID if DiagramExport @@ -1462,11 +1482,12 @@ void ShapeExport::WriteGraphicObjectShapePart( const Reference< XShape >& xShape if (GetProperty(xShapeProps, u"OnClick"_ustr)) mAny >>= eClickAction; - pFS->startElementNS( mnXmlNamespace, XML_cNvPr, - XML_id, OString::number(GetNewShapeID(xShape)), - XML_name, GetShapeName(xShape), - XML_descr, sax_fastparser::UseIf(sDescr, !sDescr.isEmpty()), - XML_hidden, sax_fastparser::UseIf("1", !bVisible)); + sal_Int32 nShapeId = GetShapeID(xShape) == -1 ? GetNewShapeID(xShape) : GetTmpShapeID(); + + pFS->startElementNS(mnXmlNamespace, XML_cNvPr, XML_id, OString::number(nShapeId), XML_name, + GetShapeName(xShape), XML_descr, + sax_fastparser::UseIf(sDescr, !sDescr.isEmpty()), XML_hidden, + sax_fastparser::UseIf("1", !bVisible)); if (eClickAction != presentation::ClickAction_NONE) { @@ -2312,7 +2333,7 @@ static bool lcl_isTextBox(const Reference& xIface) return aTextBox.get(); } -ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles ) +ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles, bool bText ) { // In case this shape has an associated textbox, then export that, and we're done. if (GetDocumentType() == DOCUMENT_DOCX && !mbUserShapes && GetTextExport()) @@ -2333,8 +2354,11 @@ ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, s pFS->startElementNS(nXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_txBody : XML_txbx)); - WriteText(xIface, /*bBodyPr=*/(GetDocumentType() != DOCUMENT_DOCX || mbUserShapes), /*bText=*/true, + WriteText(xIface, /*bBodyPr=*/(GetDocumentType() != DOCUMENT_DOCX || mbUserShapes), bText, /*nXmlNamespace=*/0, /*bWritePropertiesAsLstStyles=*/bWritePropertiesAsLstStyles); + if (!bText) + // A text body holds at least one paragraph, and an empty one says the shape has no text + pFS->singleElementNS(XML_a, XML_p); pFS->endElementNS( nXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_txBody : XML_txbx) ); if (GetDocumentType() == DOCUMENT_DOCX && !mbUserShapes) WriteText( xIface, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace ); @@ -2597,7 +2621,7 @@ void ShapeExport::WriteTableCellProperties(const Reference< XPropertySet>& xCell void ShapeExport::WriteBorderLine(const sal_Int32 xml_line_element, const BorderLine2& rBorderLine) { // While importing the table cell border line width, it converts EMU->Hmm then divided result by 2. -// To get original value of LineWidth need to multiple by 2. +// To get original value of LineWidth need to multiply by 2. sal_Int32 nBorderWidth = rBorderLine.LineWidth; nBorderWidth *= 2; nBorderWidth = oox::drawingml::convertHmmToEmu( nBorderWidth ); @@ -3117,10 +3141,14 @@ sal_Int32 ShapeExport::GetNewShapeID( const Reference< XShape >& rXShape ) auto it = mpShapeMap->find(rXShape); if (it == mpShapeMap->end()) (*mpShapeMap)[rXShape] = nID; + else + nID = it->second; return nID; } +sal_Int32 ShapeExport::GetTmpShapeID() { return GetFB()->GetUniqueId(); } + sal_Int32 ShapeExport::GetShapeID( const Reference< XShape >& rXShape ) { return GetShapeID( rXShape, mpShapeMap ); diff --git a/oox/source/helper/graphichelper.cxx b/oox/source/helper/graphichelper.cxx index e31f1b23c52f..8c3914fb7991 100644 --- a/oox/source/helper/graphichelper.cxx +++ b/oox/source/helper/graphichelper.cxx @@ -326,6 +326,21 @@ void GraphicHelper::initializeGraphicMapperIfNeeded() const } } +Reference +GraphicHelper::getCachedColorChangeGraphic(const ColorChangeKey& rKey) const +{ + auto it = maColorChangeCache.find(rKey); + if (it != maColorChangeCache.end()) + return it->second; + return Reference(); +} + +void GraphicHelper::addGraphicToColorChangeCache( + const ColorChangeKey& rKey, const Reference& xGraphic) const +{ + maColorChangeCache[rKey] = xGraphic; +} + } // namespace oox /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/helper/propertymap.cxx b/oox/source/helper/propertymap.cxx index 2a311ddc9826..b8f5ca9a939f 100644 --- a/oox/source/helper/propertymap.cxx +++ b/oox/source/helper/propertymap.cxx @@ -183,7 +183,7 @@ PropertyMap::PropertyMap() : bool PropertyMap::hasProperty( sal_Int32 nPropId ) const { - return maProperties.find( nPropId ) != maProperties.end(); + return maProperties.contains(nPropId); } bool PropertyMap::setAnyProperty( sal_Int32 nPropId, const Any& rValue ) diff --git a/oox/source/ole/vbacontrol.cxx b/oox/source/ole/vbacontrol.cxx index f6b30ee12da9..923c3aabff3e 100644 --- a/oox/source/ole/vbacontrol.cxx +++ b/oox/source/ole/vbacontrol.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -861,6 +862,7 @@ void VbaUserForm::importForm( const Reference< XNameContainer >& rxDialogLib, OSL_ENSURE( !rxDialogLib->hasByName( aFormName ), "VbaUserForm::importForm - multiple dialogs with equal name" ); ContainerHelper::insertByName( rxDialogLib, aFormName, Any( xDialogSource ) ); } + comphelper::disposeComponent(xDialogModel); } catch(const Exception& ) { diff --git a/oox/source/ppt/pptgraphicshapecontext.cxx b/oox/source/ppt/pptgraphicshapecontext.cxx index b918c6b0e8b2..a0fdc03b5b50 100644 --- a/oox/source/ppt/pptgraphicshapecontext.cxx +++ b/oox/source/ppt/pptgraphicshapecontext.cxx @@ -134,7 +134,8 @@ ContextHandlerRef PPTGraphicShapeContext::onCreateContext( sal_Int32 aElementTok } if ( pPlaceholder ) { - bool bUseText = true; + using oox::drawingml::ReferencedShapeText; + ReferencedShapeText eText = ReferencedShapeText::All; switch( pPlaceholder->getSubType() ) { case XML_title : @@ -153,11 +154,11 @@ ContextHandlerRef PPTGraphicShapeContext::onCreateContext( sal_Int32 aElementTok case XML_media : case XML_sldImg : case XML_pic : - bUseText = false; + eText = ReferencedShapeText::Nothing; } pPlaceholder->getShapeProperties().setAnyProperty( PROP_URL, mpShapePtr->getShapeProperties().getProperty(PROP_URL)); - mpShapePtr->applyShapeReference( *pPlaceholder, bUseText ); + mpShapePtr->applyShapeReference( *pPlaceholder, eText ); PPTShape* pPPTShape = dynamic_cast< PPTShape* >( pPlaceholder.get() ); if ( pPPTShape ) pPPTShape->setReferenced( true ); diff --git a/oox/source/ppt/pptimport.cxx b/oox/source/ppt/pptimport.cxx index 0bab6e8b8f23..c1da573536c5 100644 --- a/oox/source/ppt/pptimport.cxx +++ b/oox/source/ppt/pptimport.cxx @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -223,6 +222,7 @@ sal_Bool SAL_CALL PowerPointImport::filter( const Sequence< PropertyValue >& rDe { {"IsPPTM", uno::Any(exportVBA())}, {"IsTemplate", uno::Any(isExportTemplate())}, + {"IsSlideShow", uno::Any(isExportSlideShow())}, })); Reference aFactory(getComponentContext()->getServiceManager(), UNO_QUERY_THROW); diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx index 1b763a83c144..7caad2017c2f 100644 --- a/oox/source/ppt/pptshape.cxx +++ b/oox/source/ppt/pptshape.cxx @@ -90,7 +90,7 @@ static const char* lclDebugSubType( sal_Int32 nType ) case XML_hdr : return "hdr"; case XML_ftr : - return "frt"; + return "ftr"; case XML_sldNum : return "sldNum"; case XML_sldImg : @@ -379,16 +379,15 @@ void PPTShape::addShape( sServiceName = "com.sun.star.presentation.TableShape"; break; case XML_pic : - if (meShapeLocation == Layout) - sServiceName = sOutlinerShapeService; - else - sServiceName = "com.sun.star.presentation.GraphicObjectShape"; + // is a real picture placeholder on both + // slides and layouts, so the layout's type survives PPTX + // round-trip and slide-side inheritance can resolve it. + sServiceName = "com.sun.star.presentation.GraphicObjectShape"; break; case XML_media : - if (meShapeLocation == Layout) - sServiceName = sOutlinerShapeService; - else - sServiceName = "com.sun.star.presentation.MediaShape"; + // As with XML_pic, a real media placeholder on both slides and layouts, so + // the layout's type survives the round-trip and a slide can resolve it. + sServiceName = "com.sun.star.presentation.MediaShape"; break; default: if (mnSubType && meShapeLocation == Layout) @@ -712,7 +711,7 @@ namespace // Function to find placeholder (ph) for a shape. No idea how MSO implements this, but // this order seems to work quite well -// (probably it's unnecessary complicated / wrong. i.e. tdf#104202): +// (probably it's unnecessarily complicated / wrong. i.e. tdf#104202): // 1. ph with nFirstSubType and the same oSubTypeIndex // 2. ph with nFirstSubType // 3. ph with nSecondSubType and the same oSubTypeIndex diff --git a/oox/source/ppt/pptshapecontext.cxx b/oox/source/ppt/pptshapecontext.cxx index 40ade6a2ca05..1ac7506873df 100644 --- a/oox/source/ppt/pptshapecontext.cxx +++ b/oox/source/ppt/pptshapecontext.cxx @@ -158,7 +158,17 @@ ContextHandlerRef PPTShapeContext::onCreateContext( sal_Int32 aElementToken, con { SAL_INFO("oox.ppt","shape " << mpShapePtr->getId() << " will get shape reference " << pPlaceholder->getId() << " applied"); - mpShapePtr->applyShapeReference( *pPlaceholder ); + // A layout placeholder's text is a prompt, and a prompt is + // not the slide's content: taking it would fill the + // placeholder and stop it offering what it is for. An + // authored prompt reaches the shape through + // CustomPromptText instead. + using oox::drawingml::ReferencedShapeText; + const ReferencedShapeText eText + = eShapeLocation == Slide + ? ReferencedShapeText::FormattingOnly + : ReferencedShapeText::All; + mpShapePtr->applyShapeReference( *pPlaceholder, eText ); PPTShape* pPPTShape = dynamic_cast< PPTShape* >( pPlaceholder.get() ); if ( pPPTShape ) pPPTShape->setReferenced( true ); diff --git a/oox/source/ppt/pptshapegroupcontext.cxx b/oox/source/ppt/pptshapegroupcontext.cxx index 139f716c273b..a28e4745f91e 100644 --- a/oox/source/ppt/pptshapegroupcontext.cxx +++ b/oox/source/ppt/pptshapegroupcontext.cxx @@ -106,7 +106,7 @@ ContextHandlerRef PPTShapeGroupContext::onCreateContext( sal_Int32 aElementToken case PPT_TOKEN( sp ): // Shape { auto pShape = std::make_shared( meShapeLocation, u"com.sun.star.drawing.CustomShape"_ustr ); - bool bUseBgFill = rAttribs.getBool(XML_useBgFill, false); + const bool bUseBgFill(rAttribs.getBool(XML_useBgFill, false)); pShape->getFillProperties().moUseBgFill = bUseBgFill; if (bUseBgFill) { diff --git a/oox/source/ppt/presentationfragmenthandler.cxx b/oox/source/ppt/presentationfragmenthandler.cxx index 4e6d7edd510e..f23f9c0a8077 100644 --- a/oox/source/ppt/presentationfragmenthandler.cxx +++ b/oox/source/ppt/presentationfragmenthandler.cxx @@ -17,6 +17,10 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + +#include + #include #include #include @@ -108,6 +112,73 @@ sal_Int32 getPredefinedClrTokens(PredefinedClrSchemeId eID) return XML_TOKEN_INVALID; return iterator->second; } + +/** Reads a slide master's */ +class SldLayoutIdListFragmentHandler final : public FragmentHandler2 +{ +public: + SldLayoutIdListFragmentHandler(XmlFilterBase& rFilter, const OUString& rFragmentPath, + std::vector& rRelIds) + : FragmentHandler2(rFilter, rFragmentPath) + , mrRelIds(rRelIds) + { + } + + ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList& rAttribs) override + { + switch (nElement) + { + case PPT_TOKEN(sldMaster): + case PPT_TOKEN(sldLayoutIdLst): + return this; + case PPT_TOKEN(sldLayoutId): + mrRelIds.push_back(rAttribs.getStringDefaulted(R_TOKEN(id))); + break; + } + return nullptr; + } + +private: + std::vector& mrRelIds; +}; + +/** The layouts of a slide master, in the order the master lists them. + + The relations carry no order at all: a relationship id is opaque, and a producer may assign any + id to any part. */ +std::vector getLayoutFragmentPaths(XmlFilterBase& rFilter, + const OUString& rMasterFragmentPath, + const Relations& rMasterRelations) +{ + std::vector aRelIds; + rFilter.importFragment( + new SldLayoutIdListFragmentHandler(rFilter, rMasterFragmentPath, aRelIds)); + + std::vector aPaths; + std::unordered_set aNamedRelIds; + for (const OUString& rRelId : aRelIds) + { + OUString aPath = rMasterRelations.getFragmentPathFromRelId(rRelId); + if (aPath.isEmpty()) + continue; + + aPaths.push_back(aPath); + aNamedRelIds.insert(rRelId); + } + + // A layout the list does not name still gets its master page, as it did before the list was + // consulted at all. + for (const auto& [rRelId, rRelation] : rMasterRelations) + { + if (!rRelation.maType.endsWith("relationships/slideLayout") + || aNamedRelIds.contains(rRelId)) + continue; + + aPaths.push_back(rMasterRelations.getFragmentPathFromRelation(rRelation)); + } + + return aPaths; +} } // end anonymous ns PresentationFragmentHandler::PresentationFragmentHandler(XmlFilterBase& rFilter, const OUString& rFragmentPath) @@ -133,19 +204,9 @@ void PresentationFragmentHandler::importSlideNames(const XmlFilterBase& rFilter, sal_Int32 nMaxPages = rSlidePersist.size(); for (sal_Int32 nPage = 0; nPage < nMaxPages; nPage++) { - auto aShapeMap = rSlidePersist[nPage]->getShapeMap(); - auto aIter = std::find_if(aShapeMap.begin(), aShapeMap.end(), - [](const std::pair& element) { - auto pShapePtr = element.second; - return (pShapePtr - && (pShapePtr->getSubType() == XML_title - || pShapePtr->getSubType() == XML_ctrTitle)); - }); - if (aIter != aShapeMap.end()) + OUString aTitleText = rSlidePersist[nPage]->getTitleText(); + if (!aTitleText.isEmpty()) { - OUString aTitleText; - Reference xText(aIter->second->getXShape(), UNO_QUERY_THROW); - aTitleText = xText->getString(); // just a magic value but we don't want to drop out slide names which are too long if (aTitleText.getLength() > 63) aTitleText = aTitleText.copy(0, 63); @@ -223,20 +284,15 @@ void PresentationFragmentHandler::importMasterSlide(const Reference xMasterPage; Reference< drawing::XMasterPagesSupplier > xMPS( xModel, uno::UNO_QUERY_THROW ); Reference< drawing::XDrawPages > xMasterPages( xMPS->getMasterPages(), uno::UNO_SET_THROW ); RelationsRef xMasterRelations = rFilter.importRelations( rMasterFragmentPath ); - for (const auto& rEntry : *xMasterRelations) + for (const OUString& aLayoutFragmentPath : + getLayoutFragmentPaths(rFilter, rMasterFragmentPath, *xMasterRelations)) { - if (!rEntry.second.maType.endsWith("relationships/slideLayout")) - continue; - - aLayoutFragmentPath = xMasterRelations->getFragmentPathFromRelation(rEntry.second); - sal_Int32 nIndex; if( rFilter.getMasterPages().empty() ) { @@ -287,12 +343,24 @@ void PresentationFragmentHandler::importMasterSlide(const ReferencegetClrMap(); + saveColorMapToGrabBag(pMasterClrMap); + rFilter.importFragment( new LayoutFragmentHandler( rFilter, aLayoutFragmentPath, pMasterPersistPtr ) ); + + // Check if layout had a color map override (clrMap changed during layout import) + if (pMasterPersistPtr->getClrMap() != pMasterClrMap && pMasterPersistPtr->getClrMap()) + { + saveLayoutColorMapToGrabBag(pMasterPersistPtr->getClrMap(), nIndex); + } + pMasterPersistPtr->createBackground( rFilter ); pMasterPersistPtr->createXShapes( rFilter ); - saveColorMapToGrabBag(pMasterPersistPtr->getClrMap()); - uno::Reference< beans::XPropertySet > xSet(pMasterPersistPtr->getPage(), uno::UNO_QUERY_THROW); xSet->setPropertyValue(u"SlideLayout"_ustr, Any(pMasterPersistPtr->getLayoutFromValueToken())); @@ -424,6 +492,123 @@ void PresentationFragmentHandler::saveColorMapToGrabBag(const oox::drawingml::Cl } } +void PresentationFragmentHandler::saveSections() +{ + if (maSectionList.empty()) + return; + + try + { + uno::Reference xDocProps(getFilter().getModel(), uno::UNO_QUERY); + if (!xDocProps.is()) + return; + + // Get draw pages to resolve slide IDs to page names + uno::Reference xDPS(getFilter().getModel(), uno::UNO_QUERY); + if (!xDPS.is()) + return; + uno::Reference xDrawPages(xDPS->getDrawPages()); + if (!xDrawPages.is()) + return; + + // Build a sequence of sections, each section containing name, id, and slide names + std::vector aSectionsList; + for (size_t i = 0; i < maSectionList.size(); ++i) + { + const SectionData& rSection = maSectionList[i]; + + // Convert slide IDs to page names (stable across edits) + std::vector aSlideNames; + for (sal_Int32 nSldId : rSection.maSldIdList) + { + auto it = maSlideIdToIndexMap.find(nSldId); + if (it != maSlideIdToIndexMap.end()) + { + sal_Int32 nIndex = it->second; + if (nIndex < xDrawPages->getCount()) + { + uno::Reference xPage; + xDrawPages->getByIndex(nIndex) >>= xPage; + uno::Reference xNamed(xPage, uno::UNO_QUERY); + if (xNamed.is()) + aSlideNames.push_back(xNamed->getName()); + } + } + } + + uno::Sequence aSectionProps{ + comphelper::makePropertyValue(u"Name"_ustr, rSection.maName), + comphelper::makePropertyValue(u"Id"_ustr, rSection.maId), + comphelper::makePropertyValue(u"SlideNameList"_ustr, + comphelper::containerToSequence(aSlideNames)) + }; + + aSectionsList.push_back( + comphelper::makePropertyValue(u"Section"_ustr + OUString::number(i), aSectionProps)); + } + + xDocProps->setPropertyValue(u"SlideSections"_ustr, + uno::Any(comphelper::containerToSequence(aSectionsList))); + } + catch (const uno::Exception&) + { + SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveSections failed"); + } +} + +void PresentationFragmentHandler::saveLayoutColorMapToGrabBag( + const oox::drawingml::ClrMapPtr& pClrMapPtr, + sal_Int32 nMasterIndex) +{ + if (!pClrMapPtr) + return; + + try + { + uno::Reference xDocProps(getFilter().getModel(), uno::UNO_QUERY); + if (xDocProps.is()) + { + uno::Reference xPropsInfo = xDocProps->getPropertySetInfo(); + + static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr; + if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName)) + { + static constexpr auto constTokenArray = std::to_array({ + XML_bg1, XML_tx1, XML_bg2, XML_tx2, + XML_accent1, XML_accent2, XML_accent3, XML_accent4, + XML_accent5, XML_accent6, XML_hlink, XML_folHlink + }); + + comphelper::SequenceAsHashMap aGrabBag( + xDocProps->getPropertyValue(aGrabBagPropName)); + + std::vector aClrMapList; + size_t nColorMapSize = constTokenArray.size(); + aClrMapList.reserve(nColorMapSize); + for (size_t i = 0; i < nColorMapSize; ++i) + { + sal_Int32 nToken = constTokenArray[i]; + pClrMapPtr->getColorMap(nToken); + aClrMapList.push_back( + comphelper::makePropertyValue(OUString::number(i), nToken)); + } + + // Build key: "OOXLayoutClrMapOvr_" + OUString sKey = "OOXLayoutClrMapOvr_" + OUString::number(nMasterIndex); + + aGrabBag[sKey] <<= comphelper::containerToSequence(aClrMapList); + + xDocProps->setPropertyValue(aGrabBagPropName, + uno::Any(aGrabBag.getAsConstPropertyValueList())); + } + } + } + catch (const uno::Exception&) + { + SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveLayoutColorMapToGrabBag, Failed to save grab bag"); + } +} + void PresentationFragmentHandler::importMasterSlides() { OUString aMasterFragmentPath; @@ -437,7 +622,7 @@ void PresentationFragmentHandler::importMasterSlides() } } -void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage, bool bImportNotesPage) +void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, sal_Int32 nPagesImported, bool bImportNotesPage) { PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() ); @@ -450,13 +635,13 @@ void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage try { - if( bFirstPage ) + if( !nPagesImported ) { xDrawPages->getByIndex( 0 ) >>= xSlide; importMasterSlides(); } else - xSlide = xDrawPages->insertNewByIndex( xDrawPages->getCount() ); + xSlide = xDrawPages->insertNewByIndex( nPagesImported ); OUString aSlideFragmentPath = getFragmentPathFromRelId( maSlidesVector[ nSlide ] ); if( !aSlideFragmentPath.isEmpty() ) @@ -503,6 +688,7 @@ void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage importSlide( xSlideFragmentHandler, pSlidePersistPtr ); pSlidePersistPtr->createBackground( rFilter ); pSlidePersistPtr->createXShapes( rFilter ); + pSlidePersistPtr->releaseShapes(); if(bImportNotesPage) { @@ -524,6 +710,7 @@ void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage importSlide( xNotesFragmentHandler, pNotesPersistPtr ); pNotesPersistPtr->createBackground( rFilter ); pNotesPersistPtr->createXShapes( rFilter ); + pNotesPersistPtr->releaseShapes(); } } } @@ -649,12 +836,14 @@ void PresentationFragmentHandler::finalizeImport() if ( rxStatusIndicator.is() ) rxStatusIndicator->setValue((nPagesImported * 10000) / aRangeEnumerator.size()); - importSlide(elem, !nPagesImported, bImportNotesPages); + importSlide(elem, nPagesImported, bImportNotesPages); nPagesImported++; } importSlideNames( rFilter, rFilter.getDrawPages()); if (!maCustomShowList.empty()) importCustomSlideShow(maCustomShowList); + + saveSections(); } catch( uno::Exception& ) { @@ -694,8 +883,13 @@ void PresentationFragmentHandler::finalizeImport() maSlideMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) ); return this; case PPT_TOKEN( sldId ): + { maSlidesVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) ); + sal_Int32 nSldId = rAttribs.getInteger( XML_id, 0 ); + if ( nSldId ) + maSlideIdToIndexMap[ nSldId ] = maSlidesVector.size() - 1; return this; + } case PPT_TOKEN( notesMasterId ): maNotesMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) ); return this; @@ -714,6 +908,49 @@ void PresentationFragmentHandler::finalizeImport() uno::Reference xDocSettings(getFilter().getModelFactory()->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY); return new EmbeddedFontListContext(*this, mbEmbedTrueTypeFonts, xDocSettings); } + case PPT_TOKEN( extLst ): + return this; + case PPT_TOKEN( ext ): + { + mbInSectionExtension = false; + // https://learn.microsoft.com/en-us/openspecs/office_standards/ms-pptx/1f21a089-944d-410b-bd47-4f5e692c2532 + static constexpr OUString aSectionExtUri + = u"{521415D9-36F7-43E2-AB2F-B90AF26B5E84}"_ustr; + OUString sUri = rAttribs.getStringDefaulted( XML_uri ); + if ( sUri == aSectionExtUri ) + { + mbInSectionExtension = true; + return this; + } + return nullptr; + } + case P14_TOKEN( sectionLst ): + if ( !mbInSectionExtension ) + return nullptr; + return this; + case P14_TOKEN( section ): + { + if ( !mbInSectionExtension ) + return nullptr; + SectionData aSection; + aSection.maName = rAttribs.getStringDefaulted( XML_name ); + aSection.maId = rAttribs.getStringDefaulted( XML_id ); + maSectionList.push_back( std::move(aSection) ); + return this; + } + case P14_TOKEN( sldIdLst ): + if ( !mbInSectionExtension ) + return nullptr; + return this; + case P14_TOKEN( sldId ): + { + if ( !mbInSectionExtension || maSectionList.empty() ) + return nullptr; + sal_Int32 nSldId = rAttribs.getInteger( XML_id, 0 ); + if ( nSldId ) + maSectionList.back().maSldIdList.push_back( nSldId ); + return this; + } case PPT_TOKEN( modifyVerifier ): OUString sAlgorithmClass = rAttribs.getStringDefaulted(XML_cryptAlgorithmClass); OUString sAlgorithmType = rAttribs.getStringDefaulted(XML_cryptAlgorithmType); diff --git a/oox/source/ppt/slidefragmenthandler.cxx b/oox/source/ppt/slidefragmenthandler.cxx index 4403d4597810..f7e5c63539ed 100644 --- a/oox/source/ppt/slidefragmenthandler.cxx +++ b/oox/source/ppt/slidefragmenthandler.cxx @@ -229,9 +229,12 @@ SlideFragmentHandler::~SlideFragmentHandler() break; case PPT_TOKEN( pos ): - mpSlidePersistPtr->getCommentsList().cmLst.back().setPoint( - rAttribs.getStringDefaulted(XML_x), - rAttribs.getStringDefaulted(XML_y)); + if (!mpSlidePersistPtr->getCommentsList().cmLst.empty()) + { + mpSlidePersistPtr->getCommentsList().cmLst.back().setPoint( + rAttribs.getStringDefaulted(XML_x), + rAttribs.getStringDefaulted(XML_y)); + } break; case PPT_TOKEN( cmAuthor ): diff --git a/oox/source/ppt/slidepersist.cxx b/oox/source/ppt/slidepersist.cxx index 5ec9913e80a8..0ae7d4ec0f7c 100644 --- a/oox/source/ppt/slidepersist.cxx +++ b/oox/source/ppt/slidepersist.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -88,6 +90,25 @@ SlidePersist::~SlidePersist() { } +void SlidePersist::releaseShapes() +{ + for (const auto& [sId, pShape] : maShapeMap) + { + if (pShape + && (pShape->getSubType() == XML_title || pShape->getSubType() == XML_ctrTitle)) + { + css::uno::Reference xText(pShape->getXShape(), css::uno::UNO_QUERY); + if (xText.is()) + maTitleText = xText->getString(); + if (!maTitleText.isEmpty()) + break; + } + } + maShapesPtr.reset(); + maShapeMap.clear(); + mpBackgroundPropertiesPtr.reset(); +} + // the list 'const PPTXLayoutInfo aLayoutInfo[...]' used in PowerPointExport // likely needs to be updated after any changes here sal_Int16 SlidePersist::getLayoutFromValueToken() const diff --git a/oox/source/ppt/timenode.cxx b/oox/source/ppt/timenode.cxx index 1e0aa84ce036..88d644817697 100644 --- a/oox/source/ppt/timenode.cxx +++ b/oox/source/ppt/timenode.cxx @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +42,7 @@ #include #include #include +#include #include #include @@ -363,7 +366,31 @@ namespace oox::ppt { if (xCommand.is()) xCommand->setTarget(aValue); if (xAudio.is()) - xAudio->setSource(aValue); + { + // a sound source is a URL, a media object source + // is a shape; wrap a URL so it carries its + // allowed state + OUString sSoundURL; + if (aValue >>= sSoundURL) + { + xAudio->setSource(xmloff::makeSoundSource(sSoundURL)); + // A sound outside the document package is a + // link the model tracks; tell the model so + // it knows to look for one. + if (!sSoundURL.isEmpty() + && !xmloff::isPackageSoundURL(sSoundURL)) + { + Reference xModelProps( + rFilter.getModel(), UNO_QUERY); + if (xModelProps.is()) + xModelProps->setPropertyValue( + u"HasExternalAnimationSoundLink"_ustr, + Any(true)); + } + } + else + xAudio->setSource(aValue); + } } break; case NP_SUBITEM: diff --git a/oox/source/ppt/timetargetelementcontext.cxx b/oox/source/ppt/timetargetelementcontext.cxx index 06fa6d2473a5..2f99169ab5ba 100644 --- a/oox/source/ppt/timetargetelementcontext.cxx +++ b/oox/source/ppt/timetargetelementcontext.cxx @@ -133,6 +133,16 @@ namespace oox::ppt { { mpTarget->mnType = XML_sndTgt; + // a sound whose relationship points outside the package stays + // a reference to that location; only its URL is imported here + OUString aExternalURL = getRelations().getExternalTargetFromRelId( + rAttribs.getStringDefaulted(R_TOKEN(embed))); + if (!aExternalURL.isEmpty()) + { + mpTarget->msValue = aExternalURL; + break; + } + #if HAVE_FEATURE_AVMEDIA OUString srcFile = drawingml::getEmbeddedWAVAudioFile(getRelations(), rAttribs); Reference diff --git a/oox/source/shape/ShapeContextHandler.cxx b/oox/source/shape/ShapeContextHandler.cxx index 68dad0f0df51..510a1b0b4c5c 100644 --- a/oox/source/shape/ShapeContextHandler.cxx +++ b/oox/source/shape/ShapeContextHandler.cxx @@ -221,7 +221,7 @@ ShapeContextHandler::getDiagramShapeContext() auto pFragmentHandler = std::make_shared(*mxShapeFilterBase, msRelationFragmentPath); mpShape = std::make_shared(); mpShape->setSize(maSize); - mxDiagramShapeContext.set(new DiagramGraphicDataContext(*pFragmentHandler, mpShape)); + mxDiagramShapeContext.set(new DiagramGraphicDataContext(*pFragmentHandler, mpShape, EMPTY_OUSTRING)); } return mxDiagramShapeContext; diff --git a/oox/source/token/namespaces-strict.txt b/oox/source/token/namespaces-strict.txt index 39a7f22c2920..401b81021097 100644 --- a/oox/source/token/namespaces-strict.txt +++ b/oox/source/token/namespaces-strict.txt @@ -109,9 +109,15 @@ a16 http://schemas.microsoft.com/office/drawing/2014/main adec http://schemas.microsoft.com/office/drawing/2017/decorative asvg http://schemas.microsoft.com/office/drawing/2016/SVG/main +xnsv http://schemas.microsoft.com/office/spreadsheetml/2019/namedsheetviews +xthreaded http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments +xda http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray # xls14Lst for features introduced by excel 2010 xls14Lst http://schemas.microsoft.com/office/spreadsheetml/2009/9/main # LibreOffice's own extensions loext http://schemas.libreoffice.org/ + +# Collabora extensions +coext urn:com:collaboraoffice:names:experimental:ooxml:xmlns:coext:1.0 diff --git a/oox/source/token/namespaces.hxx.tail b/oox/source/token/namespaces.hxx.tail index a95dd9db7b16..9700b034f192 100644 --- a/oox/source/token/namespaces.hxx.tail +++ b/oox/source/token/namespaces.hxx.tail @@ -68,6 +68,8 @@ inline sal_Int32 getNamespace( sal_Int32 nToken ) { return nToken & NMSP_MASK; } #define WPC_TOKEN(token) OOX_TOKEN(wpc, token) #define CX_TOKEN(token) OOX_TOKEN(cx, token) #define CS_TOKEN(token) OOX_TOKEN(cs, token) +#define XNSV_TOKEN(token) OOX_TOKEN(xnsv, token) +#define XTHREADED_TOKEN(token) OOX_TOKEN(xthreaded, token) } // namespace oox diff --git a/oox/source/token/namespaces.txt b/oox/source/token/namespaces.txt index 9617c747360a..9c7c896b850b 100644 --- a/oox/source/token/namespaces.txt +++ b/oox/source/token/namespaces.txt @@ -107,9 +107,15 @@ a16 http://schemas.microsoft.com/office/drawing/2014/main adec http://schemas.microsoft.com/office/drawing/2017/decorative asvg http://schemas.microsoft.com/office/drawing/2016/SVG/main +xnsv http://schemas.microsoft.com/office/spreadsheetml/2019/namedsheetviews +xthreaded http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments +xda http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray # xls14Lst for features introduced by excel 2010 xls14Lst http://schemas.microsoft.com/office/spreadsheetml/2009/9/main # LibreOffice's own extensions loext http://schemas.libreoffice.org/ + +# Collabora extensions +coext urn:com:collaboraoffice:names:experimental:ooxml:xmlns:coext:1.0 diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt index 3601d90a2753..2a646422bd07 100644 --- a/oox/source/token/properties.txt +++ b/oox/source/token/properties.txt @@ -18,6 +18,7 @@ AttachedAxisIndex AutoFilter AutoShowInfo Autocomplete +AxisId BackColor BackColorTransparency BackGraphicLocation @@ -48,12 +49,23 @@ BulletFontName BulletRelSize CLSID CalcAsShown +CatNotVal CellBackColor CellProtection CellStyle CenterHorizontally CenterVertically Change +ChartExDimType +ChartExFormula +ChartExNFormula +ChartexAxisIds +ChartexMajorUnit +ChartexMinorUnit +ChartexOwnerIdx +ChartexUnit +ChartexValMax +ChartexValMin CharBackColor CharBackgroundComplexColor CharCaseMap @@ -112,6 +124,7 @@ CompileEnglish ComplexColor ConditionalFormat ConnectBars +ConnectorLines ContainsHeader Coordinates CopyBack @@ -234,6 +247,14 @@ FromWordArt Function GapwidthSequence GenerateVbaEvents +GeoCacheBinary +GeoCacheClearData +GeoCacheProvider +GeographyAttribution +GeographyCultureLanguage +GeographyCultureRegion +GeographyProjectionType +GeographyViewedRegionType Geometry3D GlowEffect GlowEffectRadius @@ -242,6 +263,7 @@ GradientName HatchName Graphic GraphicBitmap +GraphicClipPolyPolygon GraphicColorMode GraphicCrop GraphicSize @@ -252,6 +274,11 @@ HScroll Handles HasAutoShowInfo HasColumnRowHeaders +HasDataLabels +HasExplicitFill +HasExplicitSpPr +HasExplicitTxPr +HasGeography HasHorizontalScrollBar HasLayoutInfo HasMainTitle @@ -280,6 +307,7 @@ HoriJustifyMethod HoriOrient HoriOrientPosition HoriOrientRelation +HorizontalRule HorizontalSplitMode HorizontalSplitPositionTwips Hyperlink @@ -366,6 +394,8 @@ MajorTickmarks MarkPosition MaxFieldCount MaxTextLen +MeanLine +MeanMarker MediaType MediaMimeType MediaURL @@ -386,6 +416,7 @@ MultiSelection Name NamedRanges NegativeError +Nonoutliers NullDate NumberFormat NumberFormatKey @@ -401,6 +432,7 @@ Orientation Origin OutputPosition Outline +Outliers OverlapSequence Overlay PageScale @@ -421,6 +453,7 @@ ParaRightMargin ParaTabStops ParaTabStopDefaultDistance ParaTopMargin +ParentLabelLayout Path PercentageNumberFormat PersistName @@ -451,6 +484,7 @@ ProgressValueMax ProgressValueMin ProjectionMode Protected +QuartileMethod RadiusRangeMaximum RadiusRangeMinimum RangeXMaximum @@ -467,6 +501,7 @@ Reference ReferenceDevice ReferenceSheet RefreshPeriod +RegionLabelLayout RegularExpressions RelId RelativeHeight @@ -574,6 +609,7 @@ StringItemList StyleIndex SubPieType SubViewSize +SubtotalIndices Subtotals Suffix Surround diff --git a/oox/source/token/relationship.inc b/oox/source/token/relationship.inc index dee443a5fd6c..dc207817a2be 100644 --- a/oox/source/token/relationship.inc +++ b/oox/source/token/relationship.inc @@ -20,6 +20,8 @@ {Relationship::DRAWING, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"}, {Relationship::ENDNOTES, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes"}, {Relationship::EXTERNALLINKPATH, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath"}, +{Relationship::MISSINGEXTERNALLINKPATH, u"http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlPathMissing"}, +{Relationship::XLSTARTUPEXTERNALLINKPATH, u"http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlStartup"}, {Relationship::FONT, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/font"}, {Relationship::FONTTABLE, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"}, {Relationship::FOOTER, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"}, @@ -39,6 +41,7 @@ {Relationship::PRESPROPS, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/presProps"}, {Relationship::SETTINGS, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"}, {Relationship::SHAREDSTRINGS, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"}, +{Relationship::SHEETMETADATA, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata"}, {Relationship::SLIDE, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"}, {Relationship::SLIDELAYOUT, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}, {Relationship::SLIDEMASTER, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster"}, @@ -48,6 +51,9 @@ {Relationship::VIDEO, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/video"}, {Relationship::AUDIO, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/audio"}, {Relationship::VMLDRAWING, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"}, +{Relationship::WEBSETTINGS, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings"}, {Relationship::WORDVBADATA, u"http://schemas.microsoft.com/office/2006/relationships/wordVbaData"}, {Relationship::WORKSHEET, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"}, -{Relationship::XMLMAPS, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/xmlMaps"} +{Relationship::XMLMAPS, u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/xmlMaps"}, +{Relationship::THREADEDCOMMENT, u"http://schemas.microsoft.com/office/2017/10/relationships/threadedComment"}, +{Relationship::PERSON, u"http://schemas.microsoft.com/office/2017/10/relationships/person"}, diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt index 3f388e65856e..2f85c218fb94 100644 --- a/oox/source/token/tokens.txt +++ b/oox/source/token/tokens.txt @@ -387,6 +387,7 @@ TextHAlign TextVAlign Theater ThesisType +ThreadedComments Title TitlesOfParts Top @@ -479,6 +480,8 @@ add additionalCharacteristics additive addlxml +address +address1 addressBook addressFieldName adec @@ -489,6 +492,8 @@ adjustColumnWidth adjustLineHeightInTable adjustRightInd adjusthandles +adminDistrict1 +adminDistrict2 administrators advAuto advClick @@ -529,6 +534,7 @@ allDrilled allLines allPages allPts +allStyles allUniqueName allowBlank allowOverlap @@ -694,6 +700,7 @@ attr attrName attrNameLst attribute +attribution audio audioCd audioFile @@ -861,6 +868,7 @@ bentConnector4 bentConnector5 bentUpArrow bestFit +bestFitOnly between bevel bevelB @@ -883,6 +891,7 @@ bilevel billions binCount binSize +binary binning birds birdsFlight @@ -1123,6 +1132,7 @@ category categoryAxis categoryEl categoryIdx +categoryName ccw ccwIn ccwOut @@ -1333,6 +1343,7 @@ colorsDefHdr colorsDefHdrLst cols column +columnFilter columnSort comb combine @@ -1358,6 +1369,7 @@ compact compactData compass compat +compatExt compatLnSpc compatMode compatSetting @@ -1394,6 +1406,7 @@ connections connectloc connectlocs connector +connectorLines connectortype connecttype consecutive @@ -1442,6 +1455,8 @@ coordorigin coordsize copies copy +copyright +copyrights coral coreProperties corner @@ -1455,6 +1470,7 @@ countASubtotal countBy countNums countSubtotal +countryRegion couponCutoutDashes couponCutoutDots cover @@ -1513,6 +1529,8 @@ ctrlPr cube cubicBezTo culture +cultureLanguage +cultureRegion cup curly current @@ -1589,6 +1607,7 @@ customRollUp customSheetView customSheetViews customStyle +customStyles customView customWidth customWorkbookView @@ -1626,6 +1645,7 @@ dLblPos dLbls dPr dPt +dT dTable dark1 dark2 @@ -1677,6 +1697,7 @@ dataFields dataId dataLabel dataLabelCallout +dataLabelHidden dataLabels dataModel dataModelExt @@ -2049,6 +2070,7 @@ dxfs dy dyaOrig dynamicAddress +dynamicArrayProperties dynamicFilter dz e @@ -2067,6 +2089,7 @@ eachPage eachSect earth1 earth2 +east eastAsia eastAsiaTheme eastAsianLayout @@ -2159,6 +2182,9 @@ entr entries entry entryMacro +entityId +entityName +entityType envelopes eol eq @@ -2223,6 +2249,8 @@ extrusionOk extrusioncolor extrusionok f +fCollapsed +fDynamic fHdr fLocksText fLocksWithSheet @@ -2282,6 +2310,7 @@ filltype film filter filterColumn +filterId filterMode filterPrivacy filterUnique @@ -2401,7 +2430,6 @@ followColorScheme followSib followedHyperlink font -font4 fontAlgn fontColor fontId @@ -2521,6 +2549,33 @@ gear6 gear9 gems general +geoCache +geoChildEntities +geoChildEntitiesQuery +geoChildEntitiesQueryResult +geoChildEntitiesQueryResults +geoChildTypes +geoData +geoDataEntityQuery +geoDataEntityQueryResult +geoDataEntityQueryResults +geoDataPointQuery +geoDataPointToEntityQuery +geoDataPointToEntityQueryResult +geoDataPointToEntityQueryResults +geoEntity +geoHierarchyEntity +geoLocation +geoLocationQuery +geoLocationQueryResult +geoLocationQueryResults +geoLocations +geoParentEntitiesQuery +geoParentEntitiesQueryResult +geoParentEntitiesQueryResults +geoParentEntity +geoPolygon +geoPolygons geography gfxdata ghostCol @@ -2687,6 +2742,7 @@ headerSource headers headersInLastRefresh heading +headingStyles headings heart heartBalloon @@ -2869,6 +2925,7 @@ inactiveCaptionText includeHiddenRowCol includeNewItemsInFilter includePrintSettings +inclusive ind indefinite indent @@ -2946,6 +3003,7 @@ isLgl isNarration isPhoto iscomment +isoCountryCode isometricBottomDown isometricBottomUp isometricLeftDown @@ -3053,6 +3111,7 @@ lat latentStyles latin latinLnBrk +latitude lavender lavenderBlush lawnGreen @@ -3243,6 +3302,7 @@ local localConnection localRefresh localSheetId +locality location lock lockRevision @@ -3257,6 +3317,7 @@ log logBase lon long +longitude longCurve longFileNames longText @@ -3421,6 +3482,8 @@ measureFilter measureGroup measureGroups measures +meanLine +meanMarker med medAquamarine medBlue @@ -3564,6 +3627,8 @@ name nameLen namespaceUri namespaceuri +namedSheetView +namedSheetViews narHorz narVert narrow @@ -3654,6 +3719,7 @@ nodePh nodeType nodeVertAlign nonAsst +nonoutliers nonAutoSortDefault nonIsoscelesTrapezoid nonNegativeInteger @@ -3667,6 +3733,7 @@ normal normalViewPr normalizeH normalizedString +north northwest notBeside notBetween @@ -3692,6 +3759,7 @@ notesViewPr nothing np ns +nsvFilter nsid null num @@ -3707,6 +3775,7 @@ numIdMacAtCleanup numLit numPicBullet numPicBulletId +numPoints numPr numRef numRestart @@ -3721,6 +3790,7 @@ numberOfShades numberStoredAsText numbering numberingChange +numberingStyles nvCxnSpPr nvGraphicFramePr nvGrpSpPr @@ -3869,6 +3939,7 @@ outlineViewPr outset outside outsideMargin +outliers oval ovals over @@ -3877,10 +3948,12 @@ overflow overflowPunct overhead overlap +overlapping overlay override overrideClrMapping overwriteClear +ownerIdx owners p p14 @@ -3946,6 +4019,7 @@ parameter parameterType parameters parent +parentId parentLabelLayout parentSet paretoLine @@ -3969,6 +4043,7 @@ pattFill pattern patternFill patternType +pcaRings pct pct10 pct12 @@ -4021,6 +4096,9 @@ persistStorage persistStream persistStreamInit persistence +person +personId +personList personal personalCompose personalReply @@ -4119,6 +4197,7 @@ points polar poly polyline +polygonId portrait pos posEven @@ -4131,6 +4210,7 @@ positiveInteger post postSp postageStamp +postalCode powder powderBlue power @@ -4195,6 +4275,7 @@ product productSubtotal progId progress +projectionType prompt promptTitle promptedSolutions @@ -4209,6 +4290,8 @@ protectedRange protectedRanges protection provid +provider +providerId proxy prst prstClr @@ -4257,6 +4340,7 @@ quadBezTo quadrants qualifier quarter +quartileMethod quarters query queryCache @@ -4607,6 +4691,8 @@ seconds sectEnd sectPr sectPrChange +section +sectionLst securityDescriptor seek segments @@ -4632,6 +4718,7 @@ seriesAxis seriesEl seriesIdx seriesLine +seriesName serverCommand serverField serverFill @@ -4923,6 +5010,8 @@ sortBy sortByTuple sortCondition sortMethod +sortRule +sortRules sortState sortType sorterViewPr @@ -4936,6 +5025,7 @@ sourceObject sourceRef sourceSheetId sourceType +south southwest sp sp3d @@ -5113,6 +5203,7 @@ stylePaneSortMethod styleSet styleSheet styles +stylesInUse stylisticSets sub subDoc @@ -5126,10 +5217,10 @@ subject subscript subsetted subtotal -subtotals subtotalCaption subtotalHiddenItems subtotalTop +subtotals suff suggestedsigner suggestedsigner2 @@ -5205,6 +5296,7 @@ tableCellInsert tableColumn tableColumnId tableColumns +tableId tablePart tableParts tableRowDelete @@ -5420,6 +5512,7 @@ thisWeek thisYear thistle thousands +threadedComment threeDEmboss threeDEngrave threePt @@ -5599,6 +5692,7 @@ unboundColumnsRight uncheckedState undOvr underDot +underflow underlineTabInNumList underscore undo @@ -5614,6 +5708,7 @@ uniqueName uniqueParent uniqueTag uniqueValues +unit units unitsLabel unknown @@ -5667,6 +5762,7 @@ useWord2002TableStyleRules useWord97LineBreakRules useXSLTWhenSaving user +userId userA userB userC @@ -5777,11 +5873,13 @@ view3D viewMergedData viewPr viewpoint +viewedRegionType viewpointorigin vine violet visibility visible +visibleStyles visualTotals vm vml @@ -5846,6 +5944,7 @@ wedgeEllipseCallout wedgeRectCallout wedgeRoundRectCallout weight +west wgp wheat wheel @@ -5920,6 +6019,7 @@ xMode xSplit xVal xWindow +xda xdr xf xfDxf diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx index bf4a06c32993..367803ac2d72 100644 --- a/oox/source/vml/vmlshape.cxx +++ b/oox/source/vml/vmlshape.cxx @@ -806,6 +806,9 @@ Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes // TextFrames already have relative width/height feature... but currently not working // in the way we need. + if (maTypeModel.mbHorizontalRule) + PropertySet(xShape).setAnyProperty(PROP_HorizontalRule, Any(true)); + // Set the relative width / height if any if ( !maTypeModel.maWidthPercent.isEmpty( ) ) { @@ -1001,15 +1004,24 @@ Reference< XShape > SimpleShape::createPictureObject(const Reference< XShapes >& const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper(); lcl_SetAnchorType(aPropSet, maTypeModel, rGraphicHelper); - const sal_Int32 nWrapDistanceLeft = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maWrapDistanceLeft, 0, true, true); - const sal_Int32 nWrapDistanceRight = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maWrapDistanceRight, 0, true, true); const sal_Int32 nWrapDistanceTop = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maWrapDistanceTop, 0, false, true); const sal_Int32 nWrapDistanceBottom = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maWrapDistanceBottom, 0, false, true); - aPropSet.setProperty(PROP_LeftMargin, uno::Any(nWrapDistanceLeft)); - aPropSet.setProperty(PROP_RightMargin, uno::Any(nWrapDistanceRight)); aPropSet.setProperty(PROP_TopMargin, uno::Any(nWrapDistanceTop)); aPropSet.setProperty(PROP_BottomMargin, uno::Any(nWrapDistanceBottom)); + // 9pt default left and right wrap distances for Word files + const bool bIsMSO = mrDrawing.getFilter().isMSODocument(); + const OUString aWordWrapDefault = OUString::number(0x0001BE7C); + auto decodeOrDefault = [&](const OUString& rVal, bool bPixelX) -> sal_Int32 { + if (!rVal.isEmpty()) + return ConversionHelper::decodeMeasureToHmm(rGraphicHelper, rVal, 0, bPixelX, true); + if (bIsMSO) + return ConversionHelper::decodeMeasureToHmm(rGraphicHelper, aWordWrapDefault, 0, bPixelX, false); + return 0; + }; + aPropSet.setProperty(PROP_LeftMargin, uno::Any(decodeOrDefault(maTypeModel.maWrapDistanceLeft, true))); + aPropSet.setProperty(PROP_RightMargin, uno::Any(decodeOrDefault(maTypeModel.maWrapDistanceRight, true))); + if (maTypeModel.moCropBottom.has_value() || maTypeModel.moCropLeft.has_value() || maTypeModel.moCropRight.has_value() || maTypeModel.moCropTop.has_value()) { text::GraphicCrop aGraphicCrop; @@ -1604,6 +1616,6 @@ Reference< XShape > GroupShape::implConvertAndInsert( const Reference< XShapes > return xGroupShape; } -} // namespace oox +} // namespace oox::vml /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx index 01e2054bb078..9672a57eb720 100644 --- a/oox/source/vml/vmlshapecontext.cxx +++ b/oox/source/vml/vmlshapecontext.cxx @@ -386,6 +386,7 @@ ShapeTypeContext::ShapeTypeContext(ContextHandler2Helper const & rParent, OUString hrpct = rAttribs.getString( O_TOKEN( hrpct ), u"1000"_ustr ); if( hrpct != "0" ) mrTypeModel.maWidthPercent = OUString::number( hrpct.toInt32() ); + mrTypeModel.mbHorizontalRule = true; mrTypeModel.maWrapDistanceLeft = "0"; mrTypeModel.maWrapDistanceRight = "0"; mrTypeModel.maPositionHorizontal = rAttribs.getString( O_TOKEN( hralign ), u"left"_ustr ); @@ -621,7 +622,7 @@ ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const Attri u"com.sun.star.drawing.TextShape"_ustr); } else - // FIXME: without this we does not handle some properties like shadow + // FIXME: without this we do not handle some properties like shadow dynamic_cast(mrShape).setService(u"com.sun.star.text.TextFrame"_ustr); } return new TextBoxContext( *this, mrShapeModel.createTextBox(mrShape.getTypeModel()), rAttribs, @@ -807,6 +808,6 @@ ControlShapeContext::ControlShapeContext( ::oox::core::ContextHandler2Helper con rShapes.getDrawing().registerControl(aInfo); } -} // namespace oox +} // namespace oox::vml /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/vml/vmltextboxcontext.cxx b/oox/source/vml/vmltextboxcontext.cxx index f180e79375ba..98e519cac137 100644 --- a/oox/source/vml/vmltextboxcontext.cxx +++ b/oox/source/vml/vmltextboxcontext.cxx @@ -51,8 +51,9 @@ TextPortionContext::TextPortionContext( ContextHandler2Helper const & rParent, maFont.monSize = rAttribs.getInteger( XML_size ); break; case XML_u: - OSL_ENSURE( !maFont.monUnderline, "TextPortionContext::TextPortionContext - nested elements" ); - maFont.monUnderline = (rAttribs.getToken( XML_class, XML_TOKEN_INVALID ) == XML_font4) ? XML_double : XML_single; + OSL_ENSURE( !maFont.mobUnderline.has_value(), "TextPortionContext::TextPortionContext - nested elements" ); + maFont.mobUnderline = true; + maFont.moUnderlineClass = rAttribs.getXString(XML_class); break; case XML_sub: case XML_sup: diff --git a/opencl/source/openclwrapper.cxx b/opencl/source/openclwrapper.cxx index 00f248e109af..db322ada32df 100644 --- a/opencl/source/openclwrapper.cxx +++ b/opencl/source/openclwrapper.cxx @@ -17,11 +17,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include @@ -66,14 +66,12 @@ namespace OString generateMD5(const void* pData, size_t length) { - sal_uInt8 pBuffer[RTL_DIGEST_LENGTH_MD5]; - rtlDigestError aError = rtl_digest_MD5(pData, length, - pBuffer, RTL_DIGEST_LENGTH_MD5); - SAL_WARN_IF(aError != rtl_Digest_E_None, "opencl", "md5 generation failed"); + ::std::vector hash{ + ::comphelper::Hash::calculateHash(pData, length, ::comphelper::HashType::MD5)}; OStringBuffer aBuffer(length * 2); const char* const pString = "0123456789ABCDEF"; - for(sal_uInt8 val : pBuffer) + for(sal_uInt8 val : hash) { aBuffer.append(OStringChar(pString[val/16]) + OStringChar(pString[val%16])); } diff --git a/package/Library_package2.mk b/package/Library_package2.mk index bb7f36eb802f..d57e3027b2a5 100644 --- a/package/Library_package2.mk +++ b/package/Library_package2.mk @@ -59,7 +59,6 @@ $(eval $(call gb_Library_add_exception_objects,package2,\ package/source/zipapi/InflaterBytesZlib \ package/source/zipapi/InflaterBytesZstd \ package/source/zipapi/InflateZlib \ - package/source/zipapi/InflateZstd \ package/source/zipapi/sha1context \ package/source/zipapi/ThreadedDeflater \ package/source/zipapi/XBufferedThreadedStream \ diff --git a/package/source/zipapi/InflateZstd.cxx b/package/source/zipapi/InflateZstd.cxx deleted file mode 100644 index 9016a39ea7fa..000000000000 --- a/package/source/zipapi/InflateZstd.cxx +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include -#include - -using namespace com::sun::star::uno; -using namespace ZipUtils; - -InflateZstd::InflateZstd(bool) - : bFinished(false) - , nLastInflateError(0) - , pDCtx(ZSTD_createDCtx()) - , bStreamInitialized(false) -{ - if (!pDCtx) - { - nLastInflateError = static_cast(ZSTD_error_memory_allocation); - } - inBuffer = { nullptr, 0, 0 }; -} - -InflateZstd::~InflateZstd() { end(); } - -void InflateZstd::setInput(const Sequence& rBuffer) -{ - if (!pDCtx) - { - bStreamInitialized = false; - return; - } - sInBuffer = rBuffer; - inBuffer.src = sInBuffer.getConstArray(); - inBuffer.size = sInBuffer.getLength(); - inBuffer.pos = 0; - bStreamInitialized = true; -} - -sal_Int32 InflateZstd::doInflateSegment(Sequence& rBuffer, sal_Int32 nNewOffset, - sal_Int32 nNewLength) -{ - if (nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > rBuffer.getLength()) - return 0; - - return doInflateBytes(rBuffer, nNewOffset, nNewLength); -} - -void InflateZstd::end() -{ - if (pDCtx) - { - ZSTD_freeDCtx(pDCtx); - pDCtx = nullptr; - } - bStreamInitialized = false; - inBuffer = { nullptr, 0, 0 }; -} - -sal_Int32 InflateZstd::doInflateBytes(Sequence& rBuffer, sal_Int32 nNewOffset, - sal_Int32 nNewLength) -{ - if (bFinished) - { - return 0; - } - if (!pDCtx || !bStreamInitialized) - { - nLastInflateError = 1; - return 0; - } - nLastInflateError = 0; - ZSTD_outBuffer outBuffer - = { rBuffer.getArray() + nNewOffset, static_cast(nNewLength), 0 }; - size_t ret = ZSTD_decompressStream(pDCtx, &outBuffer, &inBuffer); - if (ZSTD_isError(ret)) - { - nLastInflateError = static_cast(ret); - ZSTD_DCtx_reset(pDCtx, ZSTD_reset_session_only); - return 0; - } - if (ret == 0) - bFinished = true; - - return static_cast(outBuffer.pos); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/package/source/zipapi/XBufferedThreadedStream.cxx b/package/source/zipapi/XBufferedThreadedStream.cxx index ea7c270ebea6..34f8a6573996 100644 --- a/package/source/zipapi/XBufferedThreadedStream.cxx +++ b/package/source/zipapi/XBufferedThreadedStream.cxx @@ -9,6 +9,8 @@ #include "XBufferedThreadedStream.hxx" +#include + using namespace css::uno; namespace { @@ -147,7 +149,7 @@ sal_Int32 SAL_CALL XBufferedThreadedStream::readBytes( Sequence< sal_Int8 >& rDa } const sal_Int32 limit = std::min( nPendingBytes, pBuffer.getLength() - mnOffset ); - memcpy( &pData[i], &pBuffer[mnOffset], limit ); + std::copy_n(&pBuffer[mnOffset], limit, &pData[i]); nPendingBytes -= limit; mnOffset += limit; @@ -173,7 +175,7 @@ sal_Int32 XBufferedThreadedStream::readSomeBytes( sal_Int8* pData, sal_Int32 nBy return nAvailableSize - nPendingBytes; const sal_Int32 limit = std::min( nPendingBytes, pBuffer.getLength() - mnOffset ); - memcpy( &pData[i], &pBuffer[mnOffset], limit ); + std::copy_n(&pBuffer[mnOffset], limit, &pData[i]); nPendingBytes -= limit; mnOffset += limit; diff --git a/package/source/zipapi/XUnbufferedStream.cxx b/package/source/zipapi/XUnbufferedStream.cxx index 73c89ae9ebf2..08f5c7ae2fcf 100644 --- a/package/source/zipapi/XUnbufferedStream.cxx +++ b/package/source/zipapi/XUnbufferedStream.cxx @@ -186,7 +186,8 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa { sal_Int16 nHeadRead = static_cast< sal_Int16 >(( nRequestedBytes > mnHeaderToRead ? mnHeaderToRead : nRequestedBytes )); - memcpy ( aData.getArray(), maHeader.getConstArray() + maHeader.getLength() - mnHeaderToRead, nHeadRead ); + std::copy_n(maHeader.getConstArray() + maHeader.getLength() - mnHeaderToRead, + nHeadRead, aData.getArray()); mnHeaderToRead = mnHeaderToRead - nHeadRead; if ( nHeadRead < nRequestedBytes ) diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index be59ebfe1570..7a8536a41a8f 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -728,7 +728,7 @@ uno::Reference< XInputStream > ZipFile::createStreamForZipEntry( if (!bUseBufferedStream) return xSrcStream; -#ifndef EMSCRIPTEN +#ifndef __EMSCRIPTEN__ static const sal_Int32 nThreadingThreshold = 10000; // "encrypted-package" is the only data stream, no point in threading it diff --git a/package/source/zippackage/ZipPackageBuffer.cxx b/package/source/zippackage/ZipPackageBuffer.cxx index 0e7615de193f..4364230c8226 100644 --- a/package/source/zippackage/ZipPackageBuffer.cxx +++ b/package/source/zippackage/ZipPackageBuffer.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -50,7 +51,7 @@ sal_Int32 SAL_CALL ZipPackageBuffer::readBytes( Sequence< sal_Int8 >& aData, sal nBytesToRead = static_cast < sal_Int32 > (m_nEnd - m_nCurrent); aData.realloc ( nBytesToRead ); - memcpy(aData.getArray(), m_aBuffer.getConstArray() + m_nCurrent, nBytesToRead); + std::copy_n(m_aBuffer.getConstArray() + m_nCurrent, nBytesToRead, aData.getArray()); m_nCurrent +=nBytesToRead; return nBytesToRead; } @@ -93,7 +94,8 @@ void SAL_CALL ZipPackageBuffer::writeBytes( const Sequence< sal_Int8 >& aData ) m_aBuffer.realloc ( static_cast < sal_Int32 > ( m_nBufferSize ) ); m_bMustInitBuffer = false; } - memcpy( m_aBuffer.getArray() + m_nCurrent, aData.getConstArray(), static_cast < sal_Int32 > (nDataLen)); + std::copy_n(aData.getConstArray(), static_cast(nDataLen), + m_aBuffer.getArray() + m_nCurrent); m_nCurrent+=nDataLen; if (m_nCurrent>m_nEnd) m_nEnd = m_nCurrent; diff --git a/postprocess/CustomTarget_images.mk b/postprocess/CustomTarget_images.mk index 95853291aa0a..e65cd7a15678 100644 --- a/postprocess/CustomTarget_images.mk +++ b/postprocess/CustomTarget_images.mk @@ -23,7 +23,7 @@ $(eval $(call gb_CustomTarget_register_targets,postprocess/images,\ $(packimages_DIR)/images.zip : DEFAULT_THEME := $(true) $(packimages_DIR)/images_%.zip : DEFAULT_THEME := -# tdf#124023 make links.txt depend on phony sorted.lst depend +# tdf#124023 make links.txt depend on phony sorted.lst # so this is evaluated every time $(packimages_DIR)/%_links.txt : $(packimages_DIR)/sorted.lst @if test -f "$(SRCDIR)/icon-themes/$*/links.txt"; then \ @@ -62,7 +62,8 @@ $(packimages_DIR)/images_%.zip : \ -L $(packimages_DIR)/$*_links.txt \ -s $< -o $@ \ $(if $(findstring s,$(MAKEFLAGS)),> /dev/null) && \ - rm -rf $${ILSTFILE}) + rm -rf $${ILSTFILE} \ + $(call gb_Helper_make_zip_deterministic,$@)) $(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),PRL) # turn the #defines foo "resource.png" of hlst into the final ilst format @@ -99,7 +100,7 @@ packimages_icon_themes := $(filter %/,$(wildcard $(SRCDIR)/icon-themes/*/)) # on the full list, and similarly the recursive filtering call from the initial # version of the patch also fails on windows for some reason # so don't try to be clever and do it in this awkward/tedious way. -# all this does is filtering everything for png/svg files that have /cmd/ as +# all this does is filter everything for png/svg files that have /cmd/ as # part of their path and then replacing the path to the theme-directory with # %MODULE% - the surrounding sort not only sorts the lists, but gets rid of # duplicate filenames that are left after the %MODULE% replacement diff --git a/postprocess/Module_postprocess.mk b/postprocess/Module_postprocess.mk index 2f7290b23094..8d81c6148640 100644 --- a/postprocess/Module_postprocess.mk +++ b/postprocess/Module_postprocess.mk @@ -35,7 +35,7 @@ $(eval $(call gb_Module_add_targets,postprocess,\ endif # For configurations that use fontconfig (cf. inclusion of -# vcl/unx/generic/fontmanager/fontconfig.cxx in Library_vcl), add +# vcl/unx/generic/font/fontconfig.cxx in Library_vcl), add # instdir/share/fonts/truetype/fc_local.conf when it shall # contain content from at least one of external/more_fonts/fc_local.snippet # (conditional on MORE_FONTS in BUILD_TYPE) and diff --git a/postprocess/packimages/README b/postprocess/packimages/README index e5f498c3e42e..c955e7dce5f3 100644 --- a/postprocess/packimages/README +++ b/postprocess/packimages/README @@ -5,10 +5,10 @@ This script takes several sources of information: * the list of images used in every .src file that is compiled * the configuration XML describing every command that is used -* [[packimages/pack/image-sort.lst]] which provides a profile based +* [[postprocess/packimages/image-sort.lst]] which provides a profile-based ordering of images. -It then tries to pack the images together into the .zip file into an +It then tries to pack the images together into the .zip file in an order that matches / is similar to that which we want at run-time, ie. an entire toolbar's images should (ideally) be next to each other in a nice linear run, to reduce LibreOffice's working set, and improve diff --git a/postprocess/qa/services.cxx b/postprocess/qa/services.cxx index be123dc67fe1..4a9f46601cb1 100644 --- a/postprocess/qa/services.cxx +++ b/postprocess/qa/services.cxx @@ -317,7 +317,7 @@ void Test::createInstance( CPPUNIT_FAIL( OString( "instantiating \"" + msg(implementationName) + "\" via \"" - + msg(name) + "\" caused " + msg(a.getValueTypeName()) + " \"" + + msg(name) + "\" caused " + msg(a.getValueTypeName()) + " \"" + msg(e.Message) + "\"") .getStr()); } diff --git a/postprocess/signing/signing.pl b/postprocess/signing/signing.pl index 7d18de8ac80e..cd69a40820be 100644 --- a/postprocess/signing/signing.pl +++ b/postprocess/signing/signing.pl @@ -184,7 +184,7 @@ sub exec_single_sign #11.07.2007 09:05 sub exec_multi_sign #11.07.2007 08:56 ############################################################################ { - # sign multiple file with one command line + # sign multiple files with one command line my $files_to_sign = shift; my $commandline_base = shift; # contains whole stuff without the file name my $commandline = $commandline_base; # contains stuff which will be executed @@ -242,7 +242,7 @@ sub usage #09.07.2007 08:39 print "\t -e filename\t\t\tFile which contains a list of files which don't have to be signed.\n"; print "\t -f pfx_filename\t\t\"Personal Information Exchange\" file.\n"; print "\t -p password\t\t\tPassword for \"Personal Information Exchange\" file.\n"; - print "\t -t timestamp\t\t\tTimestamp URL e.g. \"http://timestamp.verisign.com/scripts/timstamp.dll\"\n"; + print "\t -t timestamp\t\t\tTimestamp URL e.g. \"http://timestamp.verisign.com/scripts/timestamp.dll\"\n"; print "\t -l log_filename\t\tFile for logging.\n"; print "\t -v\t\t\t\tVerbose.\n"; } ##usage diff --git a/pyuno/Module_pyuno.mk b/pyuno/Module_pyuno.mk index e3356bd985ac..f69e89fa791c 100644 --- a/pyuno/Module_pyuno.mk +++ b/pyuno/Module_pyuno.mk @@ -54,6 +54,7 @@ $(eval $(call gb_Module_add_subsequentcheck_targets,pyuno, \ PythonTest_pyuno_pytests_testcollections \ PythonTest_pyuno_pytests_insertremovecells \ $(if $(ENABLE_EMBINDTEST_UNO),PythonTest_pyuno_pytests_embindtest) \ + PythonTest_pyuno_pytests_testofficehelper \ )) endif # DISABLE_PYTHON diff --git a/pyuno/PythonTest_pyuno_pytests_embindtest.mk b/pyuno/PythonTest_pyuno_pytests_embindtest.mk index 978e06ecf15e..66a9b76af450 100644 --- a/pyuno/PythonTest_pyuno_pytests_embindtest.mk +++ b/pyuno/PythonTest_pyuno_pytests_embindtest.mk @@ -11,8 +11,10 @@ $(eval $(call gb_PythonTest_PythonTest,pyuno_pytests_embindtest)) $(eval $(call gb_PythonTest_add_modules,pyuno_pytests_embindtest,$(SRCDIR)/pyuno/qa/pytests, \ embindtest \ + passthrough \ serviceconstructors \ singleton \ + xinvocation \ )) # vim: set noet sw=4 ts=4: diff --git a/pyuno/PythonTest_pyuno_pytests_testofficehelper.mk b/pyuno/PythonTest_pyuno_pytests_testofficehelper.mk index 77aac9d0f00b..ec4aae4ce6c4 100644 --- a/pyuno/PythonTest_pyuno_pytests_testofficehelper.mk +++ b/pyuno/PythonTest_pyuno_pytests_testofficehelper.mk @@ -10,4 +10,9 @@ $(eval $(call gb_PythonTest_PythonTest,pyuno_pytests_testofficehelper)) $(eval $(call gb_PythonTest_add_modules,pyuno_pytests_testofficehelper,$(SRCDIR)/pyuno/qa/pytests,\ testofficehelper \ )) -# vim: set noet sw=4 ts=4: \ No newline at end of file + +$(eval $(call gb_PythonTest_set_defs,pyuno_pytests_testofficehelper,\ + UNO_PATH="$(INSTROOT)/$(LIBO_BIN_FOLDER)" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/pyuno/qa/pytests/passthrough.py b/pyuno/qa/pytests/passthrough.py new file mode 100644 index 000000000000..06ec12c09e79 --- /dev/null +++ b/pyuno/qa/pytests/passthrough.py @@ -0,0 +1,32 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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 unittest +import unohelper +import org.libreoffice.unotest +from org.libreoffice.embindtest import thePassthrough + +class MyUnoObject(unohelper.Base): + pass + +class PassthroughTest(unittest.TestCase): + def test_passthrough(self): + ctx = org.libreoffice.unotest.pyuno.getComponentContext() + + # Instantiate a Python object that exposes an UNO interface + my_uno_object = MyUnoObject() + + # If we pass it through an UNO interface and back we should get exactly the same python + # object back. + returned_uno_object = thePassthrough.get(ctx).passthrough(my_uno_object) + + self.assertEqual(id(my_uno_object), id(returned_uno_object)) + + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/pyuno/qa/pytests/testofficehelper.py b/pyuno/qa/pytests/testofficehelper.py index be2c99d8daf8..2d697fc88b4d 100644 --- a/pyuno/qa/pytests/testofficehelper.py +++ b/pyuno/qa/pytests/testofficehelper.py @@ -1,42 +1,43 @@ import unittest -from officehelper import bootstrap, BootstrapException +from officehelper import bootstrap, BootstrapException, SessionManager +from com.sun.star.frame import theDesktop + +import itertools class OfficeHelperTest(unittest.TestCase): """officehelper.py must provide: - Support of Windows, Mac OS X & GNU/Linux distributions - Customizable connection with 'delays' **kwarg - Reporting to console with 'report' **kwarg - Memory cleanup from soffice service - extra features may be: - Python source documentation - """ - def test_default_config(self): - # Check default timeout and number of attempts - # Stop LibreOffice running service - ctx = bootstrap() # Default settings suffice to initialize the service - #time.sleep(10) # gve - if ctx: # stop soffice as a service - smgr = ctx.getServiceManager() - desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx) - desktop.terminate() - self.assertTrue(ctx) # check for failure + - Support of Windows, Mac OS X & GNU/Linux distributions + - Customizable connection with 'delays' **kwarg + - Reporting to console with 'report' **kwarg + - Memory cleanup from soffice service + - Process cleanup using SessionManager context manager + + extra features may be: + Python source documentation """ def test_kwargs(self): - # Wait differently for LO to start, request context 10 times + # Wait differently for LO to start, requesting the context an infinite number of times with + # a one second delay between each request. We need to have a long delay to allow for slow + # startup times under heavy load on Jenkins. # Report processing in console - ctx = bootstrap(delays=[1,]*10, report=print) - if ctx: # stop soffice as a service - smgr = ctx.getServiceManager() - desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx) - desktop.terminate() + ctx = bootstrap(delays=itertools.repeat(1), report=print) self.assertTrue(ctx) + # stop soffice as a service + desktop = theDesktop.get(ctx) + desktop.terminate() def test_exception(self): # Raise BootstrapException and stop ALL PRESENT LibreOffice running services with self.assertRaises(BootstrapException): bootstrap(delays=[0,], report=print) # delays=[0,] must raise BootstrapException + def test_session_manager(self): + # Start/Stop a LibreOffice `randomly named` pipe service + # The infinite number of delays are added to allow for slow startup times under heavy load + # on Jenkins. + with SessionManager(delays=itertools.repeat(1)) as ctx: + self.assertTrue(theDesktop.get(ctx)) if __name__ == "__main__": @@ -47,4 +48,4 @@ if __name__ == "__main__": # ~ help(bootstrap) # ~ exit() -# vim: set shiftwidth=4 softtabstop=4 expandtab +# vim: set shiftwidth=4 softtabstop=4 expandtab \ No newline at end of file diff --git a/pyuno/qa/pytests/xinvocation.py b/pyuno/qa/pytests/xinvocation.py new file mode 100644 index 000000000000..61ae20c8cfde --- /dev/null +++ b/pyuno/qa/pytests/xinvocation.py @@ -0,0 +1,27 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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 unittest +import org.libreoffice.unotest +from org.libreoffice.embindtest import theMethodToString + + +class XInvocationTest(unittest.TestCase): + # Tests that pyuno can handle an object that implements XInvocation. See tdf#173114 + def test_xinvocation(self): + ctx = org.libreoffice.unotest.pyuno.getComponentContext() + + xMethodToString = theMethodToString.get(ctx) + + # The MethodToString service implements all methods via XInvocation and just returns the + # name of the method as a string. + self.assertEqual(xMethodToString.myMadeUpMethod(), "myMadeUpMethod") + + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/pyuno/source/module/pyuno.cxx b/pyuno/source/module/pyuno.cxx index 76f06d289304..c090ab721f90 100644 --- a/pyuno/source/module/pyuno.cxx +++ b/pyuno/source/module/pyuno.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include @@ -58,6 +60,7 @@ using com::sun::star::lang::XSingleServiceFactory; using com::sun::star::lang::XServiceInfo; using com::sun::star::lang::XTypeProvider; using com::sun::star::lang::XUnoTunnel; +using com::sun::star::script::XInvocation; using com::sun::star::script::XInvocation2; using com::sun::star::container::XEnumeration; using com::sun::star::container::XEnumerationAccess; @@ -459,7 +462,7 @@ PyObject *PyUNO_str( PyObject * self ) return PyUnicode_FromString( buf.getStr() ); } -static PyObject* PyUNO_dir (PyObject* self) +PyObject* PyUNO_dir (PyObject* self) { PyUNO* me = reinterpret_cast(self); @@ -468,12 +471,16 @@ static PyObject* PyUNO_dir (PyObject* self) try { - oo_member_list = me->members->xInvocation->getMemberNames (); - member_list = PyList_New (oo_member_list.getLength ()); - for (int i = 0; i < oo_member_list.getLength (); i++) + if (Reference xInvocation2(me->members->xInvocation, UNO_QUERY); + xInvocation2.is()) { - // setitem steals a reference - PyList_SetItem (member_list, i, ustring2PyString(oo_member_list[i]).getAcquired() ); + oo_member_list = xInvocation2->getMemberNames (); + member_list = PyList_New (oo_member_list.getLength ()); + for (int i = 0; i < oo_member_list.getLength (); i++) + { + // setitem steals a reference + PyList_SetItem (member_list, i, ustring2PyString(oo_member_list[i]).getAcquired() ); + } } } catch( const RuntimeException &e ) @@ -1722,17 +1729,22 @@ PyRef PyUNO_new ( const Any &targetInterface, const Reference &ssf ) { - Reference xInvocation; + Reference xInvocation; { PyThreadDetach antiguard; xInvocation.set( ssf->createInstanceWithArguments( Sequence( &targetInterface, 1 ) ), css::uno::UNO_QUERY_THROW ); - auto that = comphelper::getFromUnoTunnel( - xInvocation->getIntrospection()->queryAdapter(cppu::UnoType::get())); - if( that ) - return that->getWrappedObject(); + if (Reference xIntrospectionAccess + = xInvocation->getIntrospection(); + xIntrospectionAccess.is()) + { + auto that = comphelper::getFromUnoTunnel( + xIntrospectionAccess->queryAdapter(cppu::UnoType::get())); + if( that ) + return that->getWrappedObject(); + } } if( !Py_IsInitialized() ) throw RuntimeException(); diff --git a/pyuno/source/module/pyuno_callable.cxx b/pyuno/source/module/pyuno_callable.cxx index 2c802aa70ef8..62f1c89bc111 100644 --- a/pyuno/source/module/pyuno_callable.cxx +++ b/pyuno/source/module/pyuno_callable.cxx @@ -21,13 +21,13 @@ #include #include -#include +#include using com::sun::star::uno::Sequence; using com::sun::star::uno::Reference; using com::sun::star::uno::Any; using com::sun::star::uno::RuntimeException; -using com::sun::star::script::XInvocation2; +using com::sun::star::script::XInvocation; namespace pyuno { @@ -35,7 +35,7 @@ namespace { struct PyUNO_callable_Internals { - Reference xInvocation; + Reference xInvocation; OUString methodName; }; @@ -254,7 +254,7 @@ static PyTypeObject PyUNO_callable_Type = }; PyRef PyUNO_callable_new ( - const Reference &my_inv, + const Reference &my_inv, const OUString & methodName ) { PyUNO_callable* self; diff --git a/pyuno/source/module/pyuno_except.cxx b/pyuno/source/module/pyuno_except.cxx index 1097c2f193a5..4a4bdddae533 100644 --- a/pyuno/source/module/pyuno_except.cxx +++ b/pyuno/source/module/pyuno_except.cxx @@ -232,7 +232,8 @@ static PyRef createClassForSingleton( // name of the service is stored via a closure. OUString singletonName = xSingleton->getName(); PyRef makeGetter = getObjectFromUnoModule(runtime, "_uno_make_singleton_getter"); - PyRef getter = PyObject_CallOneArg(makeGetter.get(), ustring2PyString(singletonName).get()); + PyRef getter = PyObject_CallFunctionObjArgs( + makeGetter.get(), ustring2PyString(singletonName).get(), nullptr); PyObject_SetAttrString(ret.get(), "get", getter.get()); diff --git a/pyuno/source/module/pyuno_impl.hxx b/pyuno/source/module/pyuno_impl.hxx index 245cecbc7832..c8a12f1b82ae 100644 --- a/pyuno/source/module/pyuno_impl.hxx +++ b/pyuno/source/module/pyuno_impl.hxx @@ -58,7 +58,7 @@ namespace com::sun::star::lang { class XSingleServiceFactory; } namespace com::sun::star::reflection { class XIdlReflection; } namespace com::sun::star::reflection { class XServiceConstructorDescription; } namespace com::sun::star::reflection { class XServiceTypeDescription2; } -namespace com::sun::star::script { class XInvocation2; } +namespace com::sun::star::script { class XInvocation; } namespace com::sun::star::script { class XInvocationAdapterFactory2; } namespace com::sun::star::script { class XTypeConverter; } @@ -130,7 +130,7 @@ PyRef PyUNOStruct_new ( struct PyUNOInternals { - css::uno::Reference xInvocation; + css::uno::Reference xInvocation; css::uno::Any wrappedObject; }; @@ -178,7 +178,7 @@ OUString pyString2ustring( PyObject *str ); void raiseInvocationTargetExceptionWhenNeeded( const Runtime &runtime ); PyRef PyUNO_callable_new ( - const css::uno::Reference &xInv, + const css::uno::Reference &xInv, const OUString &methodName ); PyRef PyUNO_service_constructor_new( @@ -216,6 +216,8 @@ PyRef getObjectFromUnoModule( const Runtime &runtime, const char * object ); bool isInterfaceClass( const Runtime &, PyObject *obj ); bool isInstanceOfStructOrException( PyObject *obj); +PyObject* PyUNO_dir(PyObject* self); + struct RuntimeCargo { css::uno::Reference< css::lang::XSingleServiceFactory > xInvocation; @@ -262,7 +264,6 @@ class Adapter : public cppu::WeakImplHelper< private: css::uno::Sequence< sal_Int16 > getOutIndexes( const OUString & functionName ); -public: public: Adapter( PyRef obj, const css::uno::Sequence< css::uno::Type > & types ); diff --git a/pyuno/source/module/pyuno_module.cxx b/pyuno/source/module/pyuno_module.cxx index b1eb13ec659c..75b354dd76ac 100644 --- a/pyuno/source/module/pyuno_module.cxx +++ b/pyuno/source/module/pyuno_module.cxx @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include @@ -63,7 +63,7 @@ using com::sun::star::uno::TypeDescription; using com::sun::star::uno::XComponentContext; using com::sun::star::container::NoSuchElementException; using com::sun::star::reflection::XIdlClass; -using com::sun::star::script::XInvocation2; +using com::sun::star::script::XInvocation; using namespace pyuno; @@ -139,7 +139,7 @@ public: /// @throws RuntimeException void fillStruct( - const Reference< XInvocation2 > &inv, + const Reference< XInvocation > &inv, typelib_CompoundTypeDescription *pCompType, PyObject *initializer, PyObject *kwinitializer, @@ -202,7 +202,7 @@ OUString getLibDirImpl() { OUString libDir; - // workarounds the $(ORIGIN) until it is available + // workaround the $(ORIGIN) until it is available if (Module::getUrlFromAddress(reinterpret_cast(getLibDir), libDir)) { libDir = libDir.copy(0, libDir.lastIndexOf('/')); @@ -486,7 +486,7 @@ static PyObject *createUnoStructHelper( PyRef returnCandidate( PyUNOStruct_new( IdlStruct, c->xInvocation ) ); PyUNO *me = reinterpret_cast( returnCandidate.get() ); TypeDescription desc( typeName ); - OSL_ASSERT( desc.is() ); // could already instantiate an XInvocation2 ! + OSL_ASSERT( desc.is() ); // could already instantiate an XInvocation ! typelib_CompoundTypeDescription *pCompType = reinterpret_cast(desc.get()); @@ -592,7 +592,7 @@ static PyObject *getConstantByName( typeName) >>= td)) { - throw RuntimeException( "pyuno.getConstantByName: " + typeName + "is not a constant" ); + throw RuntimeException( "pyuno.getConstantByName: " + typeName + " is not a constant" ); } PyRef constant = runtime.any2PyObject( td->getConstantValue() ); ret = constant.getAcquired(); diff --git a/pyuno/source/module/pyuno_runtime.cxx b/pyuno/source/module/pyuno_runtime.cxx index 48121acc6aff..a7df85951d7c 100644 --- a/pyuno/source/module/pyuno_runtime.cxx +++ b/pyuno/source/module/pyuno_runtime.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include @@ -39,7 +41,7 @@ #include #include #include -#include +#include #include #include #include @@ -582,6 +584,11 @@ PyRef Runtime::any2PyObject (const Any &a ) const if (!tmp_interface.is ()) return Py_None; + // If the interface is actually wrapping a Python object then reuse the underlying object + // instead + if (Adapter *pAdapter = comphelper::getFromUnoTunnel(tmp_interface)) + return pAdapter->getWrappedObject(); + return PyUNO_new( a, getImpl()->cargo->xInvocation ); } default: diff --git a/pyuno/source/module/pyuno_struct.cxx b/pyuno/source/module/pyuno_struct.cxx index 2e94fbe5f98e..06643b0c4f8c 100644 --- a/pyuno/source/module/pyuno_struct.cxx +++ b/pyuno/source/module/pyuno_struct.cxx @@ -17,12 +17,14 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include #include #include -#include +#include #include #include "pyuno_impl.hxx" @@ -35,7 +37,7 @@ using com::sun::star::uno::TypeClass; using com::sun::star::uno::RuntimeException; using com::sun::star::uno::Exception; using com::sun::star::lang::XSingleServiceFactory; -using com::sun::star::script::XInvocation2; +using com::sun::star::script::XInvocation; using com::sun::star::beans::XMaterialHolder; namespace pyuno @@ -93,30 +95,6 @@ static PyObject *PyUNOStruct_repr( PyObject *self ) return ret; } -static PyObject* PyUNOStruct_dir( PyObject *self ) -{ - PyUNO *me = reinterpret_cast( self ); - - PyObject* member_list = nullptr; - - try - { - member_list = PyList_New( 0 ); - const css::uno::Sequence aMemberNames = me->members->xInvocation->getMemberNames(); - for( const auto& aMember : aMemberNames ) - { - // setitem steals a reference - PyList_Append( member_list, ustring2PyString( aMember ).getAcquired() ); - } - } - catch( const RuntimeException &e ) - { - raisePyExceptionWithAny( Any(e) ); - } - - return member_list; -} - static PyObject* PyUNOStruct_getattr( PyObject* self, char* name ) { PyUNO *me = reinterpret_cast( self ); @@ -290,7 +268,7 @@ static PyMethodDef PyUNOStructMethods[] = #pragma clang diagnostic ignored "-Wcast-function-type-mismatch" #endif #endif - {"__dir__", reinterpret_cast(PyUNOStruct_dir), METH_NOARGS, nullptr}, + {"__dir__", reinterpret_cast(PyUNO_dir), METH_NOARGS, nullptr}, #if defined __clang__ #if __has_warning("-Wcast-function-type-mismatch") #pragma clang diagnostic pop @@ -393,7 +371,7 @@ PyRef PyUNOStruct_new ( const Any &targetInterface, const Reference &ssf ) { - Reference xInvocation; + Reference xInvocation; { PyThreadDetach antiguard; diff --git a/pyuno/source/officehelper.py b/pyuno/source/officehelper.py index ef2657fa304e..bd28d0a829cd 100644 --- a/pyuno/source/officehelper.py +++ b/pyuno/source/officehelper.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- # # This file is part of the LibreOffice project. @@ -28,6 +29,7 @@ This module supports the following environments: A configurable time-out allows to wait for LibO process to be completed. Multiple attempts can be set in order to connect to LibO as a service. Specific versions of the office suite can be started. +`SessionManager` class takes care of process memory cleanup. Instructions: 1. Include one of the below examples in your Python macro 2. Run your LibreOffice script from your preferred IDE @@ -38,6 +40,8 @@ Exceptions: OSError - in `bootstrap` BootstrapException - in `bootstrap` NoConnectException - in `bootstrap` +Classes: + `SessionManager` Functions: `bootstrap` `retry` decorator @@ -62,12 +66,41 @@ import time import uno from com.sun.star.connection import NoConnectException from com.sun.star.uno import Exception as UnoException +from com.sun.star.frame import theDesktop class BootstrapException(UnoException): pass +class SessionManager(): + r""" Bootstrap an 'LibreOffice' service via a Python + `context manager` taking care of process cleanup + Examples: + i. Start LO as a service, get its remote component context + >>> import officehelper + >>> with SessionManager() as ctx: + >>> # your code goes here + """ + def __init__(self, soffice=None, delays=(1, 3, 5, 7)): + self.pgm = soffice + self.retries = delays + self.ctx = None # ComponentContext + + def __enter__(self): + # get the uno component context from the PyUNO runtime + self.ctx = bootstrap(soffice=self.pgm, delays=self.retries, report=print) + return self.ctx # PyUNO is up & running + def __exit__(self, type,value,traceback): + #print(type,value,traceback) + if not self.ctx: + return False # Exceptions get raised + desktop = theDesktop.get(self.ctx) + if not desktop: + return False # Exceptions get raised + desktop.terminate() # Stop soffice as a service + return False # Exceptions get raised + def retry(delays=(0, 1, 5, 30, 180, 600, 3600), exception=Exception, report=lambda *args: None): @@ -94,7 +127,6 @@ def retry(delays=(0, 1, 5, 30, 180, 600, 3600), return wrapped return wrapper - def bootstrap(soffice=None, delays=(1, 3, 5, 7), report=lambda *args: None): # 4 connection attempts; sleeping 1, 3, 5 and 7 seconds # no report to console @@ -104,59 +136,60 @@ def bootstrap(soffice=None, delays=(1, 3, 5, 7), report=lambda *args: None): directly returns the remote component context, from whereon you can get the ServiceManager by calling getServiceManager() on the returned object. - Examples: i. Start LO as a service, get its remote component context - - import officehelper - ctx = officehelper.bootstrap() - # your code goes here - + >>> import officehelper + >>> ctx = officehelper.bootstrap() + >>> # your code goes here ii. Wait longer for LO to start, request context multiples times + Report processing in console - - import officehelper as oh - ctx = oh.bootstrap(delays=(5,10,15,20),report=print) # wait 5, 10, 15 and 20 sec. - # your code goes here - + >>> import officehelper as oh + >>> ctx = oh.bootstrap(delays=(5,10,15,20),report=print) # wait 5, 10, 15 and 20 sec. + >>> # your code goes here iii. Use a specific LibreOffice copy - - from officehelper import bootstrap - ctx = bootstrap(soffice=r"USB:\PortableApps\libO-7.6\App\libreoffice\program\soffice.exe") - # your code goes here + >>> from officehelper import bootstrap + >>> ctx = bootstrap(soffice=r"USB:\PortableApps\libO-7.6\App\libreoffice\program\soffice.exe") + >>> # your code goes here """ try: process = None # used in except clause if soffice: # soffice fully qualified path as parm sOffice = soffice else: # soffice script used on *ix, Mac; soffice.exe used on Win + sOffice = "soffice" if "UNO_PATH" in os.environ: - sOffice = os.environ["UNO_PATH"] - else: - sOffice = "" # let's hope for the best - sOffice = os.path.join(sOffice, "soffice") - if platform.startswith("win"): - sOffice += ".exe" - sOffice = '"' + sOffice + '"' # accommodate ' ' spaces in filename + sOffice = os.path.join(os.environ["UNO_PATH"], sOffice) elif platform == "darwin": # any other un-hardcoded suggestion? sOffice = "/Applications/LibreOffice.App/Contents/MacOS/soffice" + + # Intercept and correct the path for LODE macOS build environments + if platform == "darwin": + if "instdir/program/soffice" in sOffice and not os.path.exists(sOffice): + sOffice = sOffice.replace( + "instdir/program/soffice", + "instdir/LibreOfficeDev.app/Contents/MacOS/soffice" + ) + + if platform.startswith("win"): + sOffice += ".exe" + # Generate a random pipe name. random.seed() sPipeName = "uno" + str(random.random())[2:] # Start the office process - connect_string = ''.join(['pipe,name=', sPipeName, ';urp;']) - command = ' '.join([sOffice, '--nologo', '--nodefault', '--accept="' + connect_string + '"']) + connect_string = f"pipe,name={sPipeName};urp;" + command = [sOffice, '--nologo', '--nodefault', f"--accept={connect_string}"] if platform.startswith("win") or platform == "darwin": - process = subprocess.Popen(command, shell=True) + process = subprocess.Popen(command) elif platform == "linux": # Use a process group to enable proper termination - process = subprocess.Popen(command, shell=True, preexec_fn=os.setsid) + process = subprocess.Popen(command, preexec_fn=os.setsid) else: raise OSError # Connect to a started office instance xLocalContext = uno.getComponentContext() resolver = xLocalContext.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", xLocalContext) - sConnect = "".join(['uno:', connect_string, 'StarOffice.ComponentContext']) + sConnect = f"uno:{connect_string}StarOffice.ComponentContext" @retry(delays=delays, exception=NoConnectException, report=report) @@ -164,13 +197,12 @@ def bootstrap(soffice=None, delays=(1, 3, 5, 7), report=lambda *args: None): return resolver.resolve(sConnect) # may raise NoConnectException ctx = resolve() return ctx - except Exception: time.sleep(10) if process: # clean memory from soffice running process if platform.startswith("win") or platform == "darwin": process.terminate() # Send termination signal - elif platform == "linux": + elif platform == "linux": os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send termination signal to process group raise BootstrapException diff --git a/qadevOOo/Jar_OOoRunner.mk b/qadevOOo/Jar_OOoRunner.mk index eef8350f6f9f..d59e62ebca5d 100644 --- a/qadevOOo/Jar_OOoRunner.mk +++ b/qadevOOo/Jar_OOoRunner.mk @@ -340,7 +340,6 @@ $(eval $(call gb_Jar_add_sourcefiles,OOoRunner,\ qadevOOo/tests/java/ifc/drawing/_TextShapeDescriptor \ qadevOOo/tests/java/ifc/drawing/_XConnectorShape \ qadevOOo/tests/java/ifc/drawing/_XControlShape \ - qadevOOo/tests/java/ifc/drawing/_XDrawPageDuplicator \ qadevOOo/tests/java/ifc/drawing/_XDrawPages \ qadevOOo/tests/java/ifc/drawing/_XDrawPagesSupplier \ qadevOOo/tests/java/ifc/drawing/_XDrawPageSupplier \ @@ -348,7 +347,6 @@ $(eval $(call gb_Jar_add_sourcefiles,OOoRunner,\ qadevOOo/tests/java/ifc/drawing/_XGluePointsSupplier \ qadevOOo/tests/java/ifc/drawing/_XLayerManager \ qadevOOo/tests/java/ifc/drawing/_XLayerSupplier \ - qadevOOo/tests/java/ifc/drawing/_XMasterPagesSupplier \ qadevOOo/tests/java/ifc/drawing/_XMasterPageTarget \ qadevOOo/tests/java/ifc/drawing/_XShape \ qadevOOo/tests/java/ifc/drawing/_XShapeBinder \ @@ -764,7 +762,6 @@ $(eval $(call gb_Jar_add_sourcefiles,OOoRunner,\ qadevOOo/tests/java/mod/_dbaccess/OSingleSelectQueryComposer \ qadevOOo/tests/java/mod/_dbaccess/OSQLMessageDialog \ qadevOOo/tests/java/mod/_dbaccess/SbaXGridControl \ - qadevOOo/tests/java/mod/_dbaccess/TableWindowAccessibility \ qadevOOo/tests/java/mod/_dbpool/OConnectionPool \ qadevOOo/tests/java/mod/_defreg/NestedRegistry \ qadevOOo/tests/java/mod/_dtrans/generic \ @@ -1022,10 +1019,6 @@ $(eval $(call gb_Jar_add_sourcefiles,OOoRunner,\ qadevOOo/tests/java/mod/_streams/uno/ObjectOutputStream \ qadevOOo/tests/java/mod/_streams/uno/Pipe \ qadevOOo/tests/java/mod/_streams/uno/Pump \ - qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBox \ - qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxHeaderBar \ - qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxHeaderCell \ - qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxTable \ qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxTableCell \ qadevOOo/tests/java/mod/_svtools/AccessibleIconChoiceCtrl \ qadevOOo/tests/java/mod/_svtools/AccessibleIconChoiceCtrlEntry \ @@ -1146,8 +1139,6 @@ $(eval $(call gb_Jar_add_sourcefiles,OOoRunner,\ qadevOOo/tests/java/mod/_toolkit/AccessibleComboBox \ qadevOOo/tests/java/mod/_toolkit/AccessibleDropDownComboBox \ qadevOOo/tests/java/mod/_toolkit/AccessibleEdit \ - qadevOOo/tests/java/mod/_toolkit/AccessibleList \ - qadevOOo/tests/java/mod/_toolkit/AccessibleListBox \ qadevOOo/tests/java/mod/_toolkit/AccessibleListItem \ qadevOOo/tests/java/mod/_toolkit/AccessibleMenu \ qadevOOo/tests/java/mod/_toolkit/AccessibleMenuBar \ diff --git a/qadevOOo/objdsc/dbaccess/org.openoffice.comp.dbu.TableWindowAccessibility.csv b/qadevOOo/objdsc/dbaccess/org.openoffice.comp.dbu.TableWindowAccessibility.csv deleted file mode 100644 index 9cf267ba35dc..000000000000 --- a/qadevOOo/objdsc/dbaccess/org.openoffice.comp.dbu.TableWindowAccessibility.csv +++ /dev/null @@ -1,13 +0,0 @@ -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"addEventListener()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"removeEventListener()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessible";"getAccessibleContext()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChildCount()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChild()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleParent()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleIndexInParent()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRole()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleDescription()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleName()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRelationSet()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleStateSet()" -"TableWindowAccessibility";"com::sun::star::accessibility::XAccessibleContext";"getLocale()" diff --git a/qadevOOo/objdsc/sd/com.sun.star.comp.office.SdXImpressDocument.csv b/qadevOOo/objdsc/sd/com.sun.star.comp.office.SdXImpressDocument.csv index 6eb60af3bfd7..f1361cceffd9 100644 --- a/qadevOOo/objdsc/sd/com.sun.star.comp.office.SdXImpressDocument.csv +++ b/qadevOOo/objdsc/sd/com.sun.star.comp.office.SdXImpressDocument.csv @@ -25,7 +25,6 @@ "SdXImpressDocument";"com::sun::star::frame::XStorable";"store()" "SdXImpressDocument";"com::sun::star::frame::XStorable";"storeAsURL()" "SdXImpressDocument";"com::sun::star::frame::XStorable";"storeToURL()" -"SdXImpressDocument";"com::sun::star::drawing::XDrawPageDuplicator";"duplicate()" "SdXImpressDocument";"com::sun::star::document::XEventsSupplier#optional";"getEvents()" "SdXImpressDocument";"com::sun::star::util::XModifiable";"isModified()" "SdXImpressDocument";"com::sun::star::util::XModifiable";"setModified()" @@ -57,4 +56,3 @@ "SdXImpressDocument";"com::sun::star::frame::XModel";"getCurrentSelection()" "SdXImpressDocument";"com::sun::star::util::XModifyBroadcaster";"addModifyListener()" "SdXImpressDocument";"com::sun::star::util::XModifyBroadcaster";"removeModifyListener()" -"SdXImpressDocument";"com::sun::star::drawing::XMasterPagesSupplier";"getMasterPages()" diff --git a/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBox.csv b/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBox.csv deleted file mode 100644 index 2a2583c4dfca..000000000000 --- a/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBox.csv +++ /dev/null @@ -1,12 +0,0 @@ -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"addEventListener()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"removeEventListener()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChildCount()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChild()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleParent()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleIndexInParent()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRole()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleDescription()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleName()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRelationSet()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleStateSet()" -"AccessibleBrowseBox";"com::sun::star::accessibility::XAccessibleContext";"getLocale()" diff --git a/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBoxHeaderBar.csv b/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBoxHeaderBar.csv deleted file mode 100644 index cef9cd976788..000000000000 --- a/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBoxHeaderBar.csv +++ /dev/null @@ -1,12 +0,0 @@ -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"addEventListener()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"removeEventListener()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChildCount()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChild()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleParent()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleIndexInParent()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRole()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleDescription()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleName()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRelationSet()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleStateSet()" -"AccessibleBrowseBoxHeaderBar";"com::sun::star::accessibility::XAccessibleContext";"getLocale()" diff --git a/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBoxHeaderCell.csv b/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBoxHeaderCell.csv deleted file mode 100644 index 536898df0cb2..000000000000 --- a/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBoxHeaderCell.csv +++ /dev/null @@ -1,12 +0,0 @@ -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"addEventListener()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"removeEventListener()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChildCount()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChild()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleParent()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleIndexInParent()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRole()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleDescription()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleName()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRelationSet()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleStateSet()" -"AccessibleBrowseBoxHeaderCell";"com::sun::star::accessibility::XAccessibleContext";"getLocale()" diff --git a/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBoxTable.csv b/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBoxTable.csv deleted file mode 100644 index 20d115adf057..000000000000 --- a/qadevOOo/objdsc/svtools/com.sun.star.comp.svtools.AccessibleBrowseBoxTable.csv +++ /dev/null @@ -1,12 +0,0 @@ -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"addEventListener()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"removeEventListener()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChildCount()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChild()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleParent()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleIndexInParent()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRole()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleDescription()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleName()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRelationSet()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleStateSet()" -"AccessibleBrowseBoxTable";"com::sun::star::accessibility::XAccessibleContext";"getLocale()" diff --git a/qadevOOo/objdsc/toolkit/com.sun.star.comp.toolkit.AccessibleList.csv b/qadevOOo/objdsc/toolkit/com.sun.star.comp.toolkit.AccessibleList.csv deleted file mode 100644 index 4952e9f2b1dc..000000000000 --- a/qadevOOo/objdsc/toolkit/com.sun.star.comp.toolkit.AccessibleList.csv +++ /dev/null @@ -1,31 +0,0 @@ -"AccessibleList";"com::sun::star::accessibility::XAccessibleExtendedComponent";"getTitledBorderText()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleExtendedComponent";"getToolTipText()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"addEventListener()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"removeEventListener()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleComponent";"containsPoint()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleComponent";"getAccessibleAtPoint()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleComponent";"getBounds()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleComponent";"getLocation()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleComponent";"getLocationOnScreen()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleComponent";"getSize()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleComponent";"grabFocus()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleComponent";"getForeground()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleComponent";"getBackground()" -"AccessibleList";"com::sun::star::accessibility::XAccessible";"getAccessibleContext()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleSelection";"selectAccessibleChild()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleSelection";"isAccessibleChildSelected()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleSelection";"clearAccessibleSelection()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleSelection";"selectAllAccessibleChildren()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleSelection";"getSelectedAccessibleChildCount()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleSelection";"getSelectedAccessibleChild()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleSelection";"deselectAccessibleChild()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChildCount()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChild()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleParent()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleIndexInParent()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRole()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleDescription()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleName()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRelationSet()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleStateSet()" -"AccessibleList";"com::sun::star::accessibility::XAccessibleContext";"getLocale()" diff --git a/qadevOOo/objdsc/toolkit/com.sun.star.comp.toolkit.AccessibleListBox.csv b/qadevOOo/objdsc/toolkit/com.sun.star.comp.toolkit.AccessibleListBox.csv deleted file mode 100644 index 819e661c184a..000000000000 --- a/qadevOOo/objdsc/toolkit/com.sun.star.comp.toolkit.AccessibleListBox.csv +++ /dev/null @@ -1,23 +0,0 @@ -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleExtendedComponent";"getTitledBorderText()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleExtendedComponent";"getToolTipText()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"addEventListener()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleEventBroadcaster#optional";"removeEventListener()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleComponent";"containsPoint()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleComponent";"getAccessibleAtPoint()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleComponent";"getBounds()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleComponent";"getLocation()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleComponent";"getLocationOnScreen()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleComponent";"getSize()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleComponent";"grabFocus()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleComponent";"getForeground()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleComponent";"getBackground()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChildCount()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleChild()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleParent()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleIndexInParent()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRole()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleDescription()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleName()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleRelationSet()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getAccessibleStateSet()" -"AccessibleListBox";"com::sun::star::accessibility::XAccessibleContext";"getLocale()" diff --git a/qadevOOo/runner/org/openoffice/RunnerService.java b/qadevOOo/runner/org/openoffice/RunnerService.java index f61638c4702f..e0cfef1b6525 100644 --- a/qadevOOo/runner/org/openoffice/RunnerService.java +++ b/qadevOOo/runner/org/openoffice/RunnerService.java @@ -163,7 +163,7 @@ public class RunnerService implements XJob, XServiceInfo, /** * Function for reading all supported services * - * @return An aaray with all supported service names + * @return An array with all supported service names * @see com.sun.star.lang.XServiceInfo */ public String[] getSupportedServiceNames() { @@ -256,7 +256,7 @@ public class RunnerService implements XJob, XServiceInfo, * Gives a factory for creating the service. * This method is called by the JavaLoader *

      - * @return returns a XSingleServiceFactory for creating the component + * @return returns an XSingleServiceFactory for creating the component * @param implName the name of the implementation for which a service is desired * @param multiFactory the service manager to be used if needed * @param regKey the registryKey diff --git a/qadevOOo/testdocs/backend/org/openoffice/JavaSystemBackend.java b/qadevOOo/testdocs/backend/org/openoffice/JavaSystemBackend.java index 98aee0e1e326..72cf2ce186e4 100644 --- a/qadevOOo/testdocs/backend/org/openoffice/JavaSystemBackend.java +++ b/qadevOOo/testdocs/backend/org/openoffice/JavaSystemBackend.java @@ -77,7 +77,7 @@ public class JavaSystemBackend implements XSingleLayerStratum, XTypeProvider, /** * Function for reading all supported services * - * @return An aaray with all supported service names + * @return An array with all supported service names * @see com.sun.star.lang.XServiceInfo */ public String[] getSupportedServiceNames() { @@ -131,7 +131,7 @@ public class JavaSystemBackend implements XSingleLayerStratum, XTypeProvider, * Gives a factory for creating the service. * This method is called by the JavaLoader *

      - * @return returns a XSingleServiceFactory for creating the component + * @return returns an XSingleServiceFactory for creating the component * @param implName the name of the implementation for which a service is desired * @param multiFactory the service manager to be used if needed * @param regKey the registryKey @@ -215,7 +215,7 @@ public class JavaSystemBackend implements XSingleLayerStratum, XTypeProvider, "com.sun.star.comp.configuration.backend.LayerDescriber")); } catch (com.sun.star.uno.Exception e) { throw new com.sun.star.lang.NullPointerException(e, - "exception while creating LayerDesccriber"); + "exception while creating LayerDescriber"); } if (xLayerContentDescriber == null) { diff --git a/qadevOOo/testdocs/qadevlibs/source/com/sun/star/cmp/MyPersistObject.java b/qadevOOo/testdocs/qadevlibs/source/com/sun/star/cmp/MyPersistObject.java index 1eb08d140d33..2cf6bf863f88 100644 --- a/qadevOOo/testdocs/qadevlibs/source/com/sun/star/cmp/MyPersistObject.java +++ b/qadevOOo/testdocs/qadevlibs/source/com/sun/star/cmp/MyPersistObject.java @@ -293,7 +293,7 @@ public class MyPersistObject implements XPersistObject, XTypeProvider, /** * Function for reading all supported services * - * @return An aaray with all supported service names + * @return An array with all supported service names * @see com.sun.star.lang.XServiceInfo */ public String[] getSupportedServiceNames() { @@ -306,7 +306,7 @@ public class MyPersistObject implements XPersistObject, XTypeProvider, * Gives a factory for creating the service. * This method is called by the JavaLoader *

      - * @return returns a XSingleServiceFactory for creating the component + * @return returns an XSingleServiceFactory for creating the component * @param implName the name of the implementation for which a service is desired * @param multiFactory the service manager to be used if needed * @param regKey the registryKey diff --git a/qadevOOo/tests/java/ifc/accessibility/_XAccessibleComponent.java b/qadevOOo/tests/java/ifc/accessibility/_XAccessibleComponent.java index 8faccfe447bc..304d3d2f1827 100644 --- a/qadevOOo/tests/java/ifc/accessibility/_XAccessibleComponent.java +++ b/qadevOOo/tests/java/ifc/accessibility/_XAccessibleComponent.java @@ -221,6 +221,10 @@ public class _XAccessibleComponent extends MultiMethodTest { continue; } + if (chBnd.Width == 0 || chBnd.Height == 0) { + continue; + } + log.println("Checking child with bounds " + "(" + chBnd.X + "," + chBnd.Y + "),(" + chBnd.Width + "," + chBnd.Height + "): " + diff --git a/qadevOOo/tests/java/ifc/accessibility/_XAccessibleContext.java b/qadevOOo/tests/java/ifc/accessibility/_XAccessibleContext.java index 91e3b5ccc5af..894e3f0c7bcc 100644 --- a/qadevOOo/tests/java/ifc/accessibility/_XAccessibleContext.java +++ b/qadevOOo/tests/java/ifc/accessibility/_XAccessibleContext.java @@ -59,7 +59,7 @@ public class _XAccessibleContext extends MultiMethodTest { /** * Calls the method and stores the number of children.

      - * Has OK status if non-negative number rutrned. + * Has OK status if a non-negative number is returned. */ public void _getAccessibleChildCount() { childCount = oObj.getAccessibleChildCount(); @@ -70,8 +70,8 @@ public class _XAccessibleContext extends MultiMethodTest { /** * Tries to get every child and checks its parent.

      * - * Has OK status if parent of every child - * and the tested component are the same objects. + * Has OK status if the parent of every child + * and the tested component are the same object. * * The following method tests are to be completed successfully before : *

        @@ -190,7 +190,7 @@ public class _XAccessibleContext extends MultiMethodTest { * it with tested component.

        * * Has OK status if the parent's child and the tested - * component are the same objects. + * component are the same object. * * The following method tests are to be completed successfully before : *

          @@ -238,7 +238,7 @@ public class _XAccessibleContext extends MultiMethodTest { /** * Get the accessible role of component.

          * - * Has OK status if non-negative number rutrned. + * Has OK status if a non-negative number is returned. */ public void _getAccessibleRole() { short role = oObj.getAccessibleRole(); @@ -249,7 +249,7 @@ public class _XAccessibleContext extends MultiMethodTest { /** * Get the accessible name of the component.

          * - * Has OK status if the name has non-zero length. + * Has OK status if the name is not null. */ public void _getAccessibleName() { String name = oObj.getAccessibleName(); @@ -260,7 +260,7 @@ public class _XAccessibleContext extends MultiMethodTest { /** * Get the accessible description of the component.

          * - * Has OK status if the description has non-zero length. + * Has OK status if the description is not null. */ public void _getAccessibleDescription() { String descr = oObj.getAccessibleDescription(); diff --git a/qadevOOo/tests/java/ifc/accessibility/_XAccessibleEditableText.java b/qadevOOo/tests/java/ifc/accessibility/_XAccessibleEditableText.java index d8cb81adcb2e..f59ae221f97b 100644 --- a/qadevOOo/tests/java/ifc/accessibility/_XAccessibleEditableText.java +++ b/qadevOOo/tests/java/ifc/accessibility/_XAccessibleEditableText.java @@ -42,7 +42,7 @@ import com.sun.star.beans.PropertyValue; *

        • 'XAccessibleEditableText.hasAttr' * (of type Boolean): * Indicates whether or not the text has changeable attributes. - * E.g. text within writer document have attributes which can + * E.g. text within writer document has attributes which can * be changed, while the text within edit field has fixed * attributes.

          * If the relation is false then the component @@ -62,7 +62,7 @@ public class _XAccessibleEditableText extends MultiMethodTest { /** * Indicates whether or not the text has changeable attributes. - * E.g. text within writer document have attributes which can + * E.g. text within writer document has attributes which can * be changed, while the text within edit field has fixed * attributes. */ @@ -85,7 +85,7 @@ public class _XAccessibleEditableText extends MultiMethodTest { /** * Calls the method with the wrong indexes and with the correct indexes. - * Stores cutted text in the variable pasteText. + * Stores cut text in the variable pasteText. * Has OK status if exceptions were thrown for the wrong indexes, * if exception wasn't thrown for the correct indexes. */ @@ -145,7 +145,7 @@ public class _XAccessibleEditableText extends MultiMethodTest { /** * Calls the method with the wrong indexes and with the correct indexes. * Has OK status if exceptions were thrown for the wrong indexes, - * if exception wasn't thrown for the correct indexes and if cutted text was + * if exception wasn't thrown for the correct indexes and if cut text was * pasted. * The following method tests are to be executed before: *

            @@ -475,7 +475,7 @@ public class _XAccessibleEditableText extends MultiMethodTest { res &= (changeableAttr && locRes) || (!changeableAttr && !locRes); if (changeableAttr) { - log.print("checking that new attributes was set..."); + log.print("checking that new attributes were set..."); PropertyValue[] newAttrs = oObj.getCharacterAttributes(0, new String[]{""}); locRes = ValueComparer.equalValue(attrs, newAttrs); log.println(locRes); diff --git a/qadevOOo/tests/java/ifc/accessibility/_XAccessibleValue.java b/qadevOOo/tests/java/ifc/accessibility/_XAccessibleValue.java index 865e8884d53f..aa3d2504c316 100644 --- a/qadevOOo/tests/java/ifc/accessibility/_XAccessibleValue.java +++ b/qadevOOo/tests/java/ifc/accessibility/_XAccessibleValue.java @@ -124,14 +124,6 @@ public class _XAccessibleValue extends MultiMethodTest { boolean result = true ; boolean partResult=true; - String noMax = "com.sun.star.comp.toolkit.AccessibleScrollBar"; - String implName = util.utils.getImplName(oObj); - - if (tEnv.getObjRelation("ValueNotPersistent")!=null) { - log.println("Excluded since it works like AccessibleAction"); - tRes.tested("setCurrentValue()",Status.skipped(true)); - return; - } if (anotherFromGroup == null) { double newVal = curVal + 1; @@ -168,14 +160,6 @@ public class _XAccessibleValue extends MultiMethodTest { log.println("Result max value is " + resVal); partResult = Math.abs(maxVal - resVal) < 0.00001; - if (implName.equals(noMax)) { - log.println("If one sets the maximum value of a scroll bar with XScrollBar::setMaximum(),"+ - "then XScrollBar::getValue() returns the maximum value minus the visible size of"+ - "the thumb"); - //using arbitrary Value, since we can't determine the resulting value - partResult = resVal > 10; - } - result &=partResult; log.println("\t works: "+partResult); @@ -192,13 +176,6 @@ public class _XAccessibleValue extends MultiMethodTest { resVal = getDoubleValue(oObj.getCurrentValue()); log.println("Result max value is " + resVal); partResult = Math.abs(maxVal - resVal) < 0.00001; - if (implName.equals(noMax)) { - log.println("If one sets the maximum value of a scroll bar with XScrollBar::setMaximum(),"+ - "then XScrollBar::getValue() returns the maximum value minus the visible size of"+ - "the thumb"); - //using arbitrary Value, since we can't determine the resulting value - partResult = resVal > 10; - } result &=partResult; log.println("\t works: "+partResult); diff --git a/qadevOOo/tests/java/ifc/awt/_XComboBox.java b/qadevOOo/tests/java/ifc/awt/_XComboBox.java index 37bf4e324233..85bed8b60802 100644 --- a/qadevOOo/tests/java/ifc/awt/_XComboBox.java +++ b/qadevOOo/tests/java/ifc/awt/_XComboBox.java @@ -135,7 +135,7 @@ public class _XComboBox extends MultiMethodTest { } /** - * Adds one two items to the last position and check the number of + * Adds two items to the last position and check the number of * items after addition.

            * Has OK status if the number of items increased by 2.

            * The following method tests are to be executed before : @@ -157,7 +157,7 @@ public class _XComboBox extends MultiMethodTest { /** * Gets the current number of items and tries to remove them all * then checks number of items.

            - * Has OK status if no items remains.

            + * Has OK status if no items remain.

            * The following method tests are to be executed before : *

              *
            • getItems
            • @@ -190,7 +190,7 @@ public class _XComboBox extends MultiMethodTest { /** * After addItem and addItems methods * test the following items must exist {..., "Item1", "Item2", "Item3"} - * Retrieves the item from the position which was ititially the last.

              + * Retrieves the item from the position which was initially the last.

              * Has OK status if the "Item1" was retrieved.

              * The following method tests are to be executed before : *

                diff --git a/qadevOOo/tests/java/ifc/awt/_XListBox.java b/qadevOOo/tests/java/ifc/awt/_XListBox.java index 6c6ddd6b247e..4b60d769e41d 100644 --- a/qadevOOo/tests/java/ifc/awt/_XListBox.java +++ b/qadevOOo/tests/java/ifc/awt/_XListBox.java @@ -156,7 +156,7 @@ public class _XListBox extends MultiMethodTest { } /** - * Adds one two items to the last position and check the number of + * Adds two items to the last position and check the number of * items after addition.

                * Has OK status if the number of items increased by 2.

                * The following method tests are to be executed before : @@ -178,7 +178,7 @@ public class _XListBox extends MultiMethodTest { /** * Gets the current number of items and tries to remove them all * then checks number of items.

                - * Has OK status if no items remains.

                + * Has OK status if no items remain.

                * The following method tests are to be executed before : *

                  *
                • getItems
                • @@ -215,7 +215,7 @@ public class _XListBox extends MultiMethodTest { /** * After addItem and addItems methods * test the following items must exist {..., "Item1", "Item2", "Item3"} - * Retrieves the item from the position which was ititially the last.

                  + * Retrieves the item from the position which was initially the last.

                  * Has OK status if the "Item1" was retrieved.

                  * The following method tests are to be executed before : *

                    diff --git a/qadevOOo/tests/java/ifc/chart/_XChartDataArray.java b/qadevOOo/tests/java/ifc/chart/_XChartDataArray.java index 5021657ea99e..046eb90a2e7f 100644 --- a/qadevOOo/tests/java/ifc/chart/_XChartDataArray.java +++ b/qadevOOo/tests/java/ifc/chart/_XChartDataArray.java @@ -150,9 +150,9 @@ public class _XChartDataArray extends MultiMethodTest { } /** - * Test calls the method and compare returned values with values restored + * Test calls the method and compares returned values with values restored * after method setColumnDescriptions.

                    - * Has OK status if the returned values equils to restored values.

                    + * Has OK status if the returned values are equal to restored values.

                    * The following method tests are to be completed successfully before : *

                      *
                    • setData : to set and restore new values
                    • @@ -176,9 +176,9 @@ public class _XChartDataArray extends MultiMethodTest { } /** - * Test calls the method and compare returned values with values restored + * Test calls the method and compares returned values with values restored * after method setRowDescriptions.

                      - * Has OK status if the returned values equils to restored values.

                      + * Has OK status if the returned values are equal to restored values.

                      * The following method tests are to be completed successfully before : *

                        *
                      • setData : to set and restore new values
                      • @@ -202,9 +202,9 @@ public class _XChartDataArray extends MultiMethodTest { } /** - * Test calls the method and compare returned values with values restored + * Test calls the method and compares returned values with values restored * after method setData.

                        - * Has OK status if the returned values equils to restored values.

                        + * Has OK status if the returned values are equal to restored values.

                        * The following method tests are to be completed successfully before : *

                          *
                        • setData : to set and restore new values
                        • diff --git a/qadevOOo/tests/java/ifc/container/_XIndexContainer.java b/qadevOOo/tests/java/ifc/container/_XIndexContainer.java index 9b3a23f97409..b0e63f6b4a44 100644 --- a/qadevOOo/tests/java/ifc/container/_XIndexContainer.java +++ b/qadevOOo/tests/java/ifc/container/_XIndexContainer.java @@ -34,7 +34,7 @@ import com.sun.star.lang.IndexOutOfBoundsException; * This test needs the following object relations : *
                            *
                          • 'INSTANCE1', ..., 'INSTANCEN' : N relations -* which represents objects to be inserted. See below +* which represent objects to be inserted. See below * for more information.
                          • *
                          • 'XIndexContainerINDEX' : For internal test * usage. Contains current thread number.
                          • @@ -43,21 +43,21 @@ import com.sun.star.lang.IndexOutOfBoundsException; *

                              * XIndexContainer needs n ObjectRelations "INSTANCEn" , where n=1, ..., * THRCNT.

                              -* When this interface tested by different threads, it must use different +* When this interface is tested by different threads, it must use different * instances to insert/remove - one for each thread. *

                              * That's why we use objRelation "XIndexContainerINDEX" to store the number of -* last taken instance. If there is no such relation, it initialize with 1. +* last taken instance. If there is no such relation, it initializes with 1. *

                              -* This ObjectRelations should be necessary to create an Object, -* which is insertable by insterByIndex() +* These ObjectRelations should be necessary to create an Object, +* which is insertable by insertByIndex() * INSTANCEn are n Objectrelations so that every thread can insert its own -* object. n depends on the variable THRCNT which and comes from API.INI +* object. n depends on the variable THRCNT and comes from API.INI *

                              * Why that: * If you insert the same Object by insertByIndex() several times you * don't insert the Object several times. The first insertByIndex() inserts -* the Object to the Container but all other insertByIndex() changes +* the Object into the Container but all other insertByIndex() calls change * the Index in the Container because it's the same Object.

                              * Test is multithread compliant.

                              * @see com.sun.star.container.XIndexContainer @@ -72,7 +72,7 @@ public class _XIndexContainer extends MultiMethodTest { * First tries to insert proper object. Second tries to insert * null value. For each test thread different objects are inserted * on different indexes. For example for the first started test index - * is 0 and object is get from relation 'INSTANCE1', and so on.

                              + * is 0 and object is retrieved from relation 'INSTANCE1', and so on.

                              * Has OK status if in the first case getByIndex * method returns non null value and in the second * IndexOutOfBoundsException was thrown. @@ -106,13 +106,13 @@ public class _XIndexContainer extends MultiMethodTest { result &= oObj.getByIndex(Index) != null ; log.println("insertByIndex(\""+Index+"\")...OK"); } catch (com.sun.star.lang.IndexOutOfBoundsException e) { - log.println("insertByIndex(\""+Index+"\"): " + e + " FLASE"); + log.println("insertByIndex(\""+Index+"\"): " + e + " FALSE"); result = false; } catch (com.sun.star.lang.IllegalArgumentException e) { - log.println("insertByIndex(\""+Index+"\"): " + e + " FLASE"); + log.println("insertByIndex(\""+Index+"\"): " + e + " FALSE"); result = false; } catch (com.sun.star.lang.WrappedTargetException e) { - log.println("insertByIndex(\""+Index+"\"): " + e + " FLASE"); + log.println("insertByIndex(\""+Index+"\"): " + e + " FALSE"); result = false; } diff --git a/qadevOOo/tests/java/ifc/drawing/_XDrawPageDuplicator.java b/qadevOOo/tests/java/ifc/drawing/_XDrawPageDuplicator.java deleted file mode 100644 index 75073765b3f5..000000000000 --- a/qadevOOo/tests/java/ifc/drawing/_XDrawPageDuplicator.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 . - */ - -package ifc.drawing; - -import lib.MultiMethodTest; - -import com.sun.star.drawing.XDrawPage; -import com.sun.star.drawing.XDrawPageDuplicator; -import com.sun.star.drawing.XDrawPages; -import com.sun.star.drawing.XDrawPagesSupplier; -import com.sun.star.uno.AnyConverter; -import com.sun.star.uno.Type; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XInterface; - - -/** -* Testing com.sun.star.drawing.XDrawPageDuplicator -* interface methods : -*

                                -*
                              • duplicate()
                              • -*

                              -* The object tested must implement -* XDrawPagesSupplier interface to have access to draw -* pages collection.

                              -* Test is NOT multithread compliant.

                              -* After test completion object environment has to be recreated. -* @see com.sun.star.drawing.XDrawPageDuplicator -*/ -public class _XDrawPageDuplicator extends MultiMethodTest { - public XDrawPageDuplicator oObj = null; - - /** - * First queries object tested for XDrawPagesSupplier - * interface and obtains one draw page from document. Then it - * tries to duplicate it.

                              - * Has OK status if the method returns not null value and - * this value is not equal to the page which was duplicated.

                              - */ - public void _duplicate(){ - boolean result = false; - XInterface testobj = tEnv.getTestObject(); - XDrawPagesSupplier PS = UnoRuntime.queryInterface(XDrawPagesSupplier.class, testobj); - XDrawPages DPs = PS.getDrawPages(); - XDrawPage DP = null; - try { - DP = (XDrawPage) AnyConverter.toObject( - new Type(XDrawPage.class),DPs.getByIndex(0)); - } catch (com.sun.star.lang.WrappedTargetException e) { - log.println("Exception occurred while testing: " + e); - } catch (com.sun.star.lang.IndexOutOfBoundsException e) { - log.println("Exception occurred while testing: " + e); - } catch (com.sun.star.lang.IllegalArgumentException e) { - log.println("Exception occurred while testing: " + e); - } - - if (DP != null) { - XDrawPage newPage = oObj.duplicate(DP); - result = (newPage != null) && !(newPage.equals(DP)); - } - tRes.tested("duplicate()", result); - } - -} - diff --git a/qadevOOo/tests/java/ifc/drawing/_XMasterPagesSupplier.java b/qadevOOo/tests/java/ifc/drawing/_XMasterPagesSupplier.java deleted file mode 100644 index 313f0f142500..000000000000 --- a/qadevOOo/tests/java/ifc/drawing/_XMasterPagesSupplier.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 . - */ - -package ifc.drawing; - -import lib.MultiMethodTest; - -import com.sun.star.drawing.XDrawPages; -import com.sun.star.drawing.XMasterPagesSupplier; - -/** -* Testing com.sun.star.drawing.XMasterPagesSupplier -* interface methods : -*

                                -*
                              • getMasterPages()
                              • -*

                              -* Test is NOT multithread compliant.

                              -* @see com.sun.star.drawing.XMasterPagesSupplier -*/ -public class _XMasterPagesSupplier extends MultiMethodTest{ - public XMasterPagesSupplier oObj = null; - - /** - * Test calls the method.

                              - * Has OK status if the value returned is not null. - */ - public void _getMasterPages(){ - boolean result = false; - XDrawPages DrawPages = null; - - log.println("get the MasterPages"); - - DrawPages = oObj.getMasterPages(); - result = DrawPages != null; - - tRes.tested("getMasterPages()",result); - } -} - diff --git a/qadevOOo/tests/java/ifc/frame/_XSynchronousFrameLoader.java b/qadevOOo/tests/java/ifc/frame/_XSynchronousFrameLoader.java index b56d9d89d20b..b96b02415cc1 100644 --- a/qadevOOo/tests/java/ifc/frame/_XSynchronousFrameLoader.java +++ b/qadevOOo/tests/java/ifc/frame/_XSynchronousFrameLoader.java @@ -42,11 +42,11 @@ import com.sun.star.util.XURLTransformer; * This test needs the following object relations : *

                                *
                              • 'FrameLoader.URL' (of type String): - * a url of component to be loaded
                              • + * a url of the component to be loaded *
                              • 'FrameLoader.Frame' (optional) * (of type com.sun.star.frame.XFrame): - * a target frame where component to be loaded. If this - * relation is omitted then a text document created and its + * a target frame where component is to be loaded. If this + * relation is omitted then a text document is created and its * frame is used.
                              • *

                                  * @@ -61,7 +61,7 @@ public class _XSynchronousFrameLoader extends MultiMethodTest { /** * Retrieves all relations. If optional relation - * FrameLoader.Frame not found + * FrameLoader.Frame is not found, * creates a new document and obtains its frame for loading.

                                  * * Also MediaDescriptor is created using @@ -101,7 +101,7 @@ public class _XSynchronousFrameLoader extends MultiMethodTest { (XURLTransformer.class, o) ; } catch ( com.sun.star.uno.Exception e ) { - // Some exception occurs.FAILED + // Some exception occurred. FAILED e.printStackTrace( log ); throw new StatusException( "Couldn't create a document.", e ); } @@ -122,7 +122,7 @@ public class _XSynchronousFrameLoader extends MultiMethodTest { /** - * Tries to load component to a frame.

                                  + * Tries to load a component into a frame.

                                  * Has OK status if true is returned. */ public void _load() { @@ -132,11 +132,11 @@ public class _XSynchronousFrameLoader extends MultiMethodTest { } /** - * Tries to load component to a frame in separate thread to + * Tries to load component to a frame in a separate thread to * avoid blocking of the current thread and immediately * cancels loading.

                                  * - * Has OK status if flase is returned, + * Has OK status if false is returned, * i.e. loading was not completed. */ public void _cancel() { diff --git a/qadevOOo/tests/java/ifc/i18n/_XTransliteration.java b/qadevOOo/tests/java/ifc/i18n/_XTransliteration.java index 49ee580d3b32..022c49cbb7bd 100644 --- a/qadevOOo/tests/java/ifc/i18n/_XTransliteration.java +++ b/qadevOOo/tests/java/ifc/i18n/_XTransliteration.java @@ -71,7 +71,7 @@ public class _XTransliteration extends MultiMethodTest { } /** - * Calls the method for load IGNORE_CASE module and checks the name returned + * Calls the method to load IGNORE_CASE module and checks the name returned * by the method getName.

                                  * Has OK status if the method getName returns the * string "case ignore (generic)". @@ -91,7 +91,7 @@ public class _XTransliteration extends MultiMethodTest { * Loads LOWERCASE_UPPERCASE module and checks the current * name of object.

                                  * - * Has OK status if the name of the object is equals to + * Has OK status if the name of the object is equal to * 'lower_to_upper(generic)' */ public void _loadModuleNew() { @@ -109,7 +109,7 @@ public class _XTransliteration extends MultiMethodTest { } /** - * Calls the method for load LOWERCASE_UPPERCASE module and + * Calls the method to load LOWERCASE_UPPERCASE module and * checks the name returned by the method getName.

                                  * Has OK status if the method getName returns the * string "lower_to_upper(generic)". @@ -126,7 +126,7 @@ public class _XTransliteration extends MultiMethodTest { } /** - * Calls the method for load UPPERCASE_LOWERCASE module and + * Calls the method to load UPPERCASE_LOWERCASE module and * checks the name returned by the method getName.

                                  * Has OK status if the method getName returns the * string "upper_to_lower(generic)". @@ -276,10 +276,10 @@ public class _XTransliteration extends MultiMethodTest { * substrings, and without of bounds offset and length * parameters.

                                  * - * Has OK status if comparings of equal substrings - * always return 0, if comparisons of none equal returns + * Has OK status if comparisons of equal substrings + * always return 0, if comparisons of non-equal returns * proper value according to lexicographical order and if - * comparisons with invalid parameters return none 0 value. + * comparisons with invalid parameters return non-zero value. */ public void _compareSubstring() { oObj.loadModule(TransliterationModules.LOWERCASE_UPPERCASE, loc); @@ -308,7 +308,7 @@ public class _XTransliteration extends MultiMethodTest { } /** - * Performs tesing of two substrings. Also testing of opposite + * Performs testing of two substrings. Also testing of opposite * substrings order performed. * @return true if substrings are equal and returned * value is 0 for both orders, @@ -352,9 +352,9 @@ public class _XTransliteration extends MultiMethodTest { * Test performed for sets of equal strings and not equal * strings.

                                  * - * Has OK status if comparings of equal strings - * always return 0 and if comparisons of none equal returns - * proper value according to lexicographical order . + * Has OK status if comparisons of equal strings + * always return 0 and if comparisons of non-equal returns + * proper value according to lexicographical order. */ public void _compareString() { oObj.loadModule(TransliterationModules.LOWERCASE_UPPERCASE, loc); @@ -379,7 +379,7 @@ public class _XTransliteration extends MultiMethodTest { } /** - * Performs tesing of two strings. If the expected value is not 0 + * Performs testing of two strings. If the expected value is not 0 * (i.e. strings are not equal), then also testing of opposite * strings order performed. * @return true if strings are equal and returned diff --git a/qadevOOo/tests/java/ifc/sheet/_TableAutoFormatField.java b/qadevOOo/tests/java/ifc/sheet/_TableAutoFormatField.java index 305d3e219371..212e31f6785b 100644 --- a/qadevOOo/tests/java/ifc/sheet/_TableAutoFormatField.java +++ b/qadevOOo/tests/java/ifc/sheet/_TableAutoFormatField.java @@ -78,7 +78,7 @@ public class _TableAutoFormatField extends MultiPropertyTest { /** * Only some values can be used (which identify font name). * In this property value is changed from 'Times New Roman' - * to 'Courier' and viceversa. + * to 'Courier' and vice-versa. */ public void _CharFontName() { testProperty("CharFontName", new PropertyTester() { @@ -90,7 +90,7 @@ public class _TableAutoFormatField extends MultiPropertyTest { } /** - * Locale values are predefined and can't be arbitrary changed. + * Locale values are predefined and can't be arbitrarily changed. * In this property value is changed from ('de', 'DE', '') * to ('es', 'ES', '') and vice versa. */ diff --git a/qadevOOo/tests/java/mod/_dbaccess/OQueryDesign.java b/qadevOOo/tests/java/mod/_dbaccess/OQueryDesign.java index 1124d12f96d7..37df97995f35 100644 --- a/qadevOOo/tests/java/mod/_dbaccess/OQueryDesign.java +++ b/qadevOOo/tests/java/mod/_dbaccess/OQueryDesign.java @@ -170,7 +170,7 @@ public class OQueryDesign extends TestCase { } // finish method getTestEnvironment private XInitialization getUninitializedObj(TestParameters Param) throws Exception { - // creating an object which ist not initialized + // creating an object which is not initialized // get a model of a DataSource Object oDBC = null; @@ -220,5 +220,5 @@ public class OQueryDesign extends TestCase { } -} // finish class oDatasourceBrowser +} // finish class OQueryDesign diff --git a/qadevOOo/tests/java/mod/_dbaccess/TableWindowAccessibility.java b/qadevOOo/tests/java/mod/_dbaccess/TableWindowAccessibility.java deleted file mode 100644 index 384edb85b47e..000000000000 --- a/qadevOOo/tests/java/mod/_dbaccess/TableWindowAccessibility.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * 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 . - */ -package mod._dbaccess; - -import java.io.PrintWriter; - -import lib.Status; -import lib.StatusException; -import lib.TestCase; -import lib.TestEnvironment; -import lib.TestParameters; -import util.AccessibilityTools; - -import com.sun.star.accessibility.AccessibleRole; -import com.sun.star.accessibility.XAccessible; -import com.sun.star.accessibility.XAccessibleComponent; -import com.sun.star.awt.Point; -import com.sun.star.awt.XWindow; -import com.sun.star.beans.PropertyValue; -import com.sun.star.beans.XPropertySet; -import com.sun.star.container.XNameAccess; -import com.sun.star.container.XNameContainer; -import com.sun.star.frame.XModel; -import com.sun.star.frame.XStorable; -import com.sun.star.lang.XComponent; -import com.sun.star.lang.XMultiServiceFactory; -import com.sun.star.sdb.XDocumentDataSource; -import com.sun.star.sdb.XQueryDefinitionsSupplier; -import com.sun.star.sdbc.XConnection; -import com.sun.star.sdbc.XIsolatedConnection; -import com.sun.star.sdbc.XStatement; -import com.sun.star.ucb.XSimpleFileAccess; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XInterface; -import java.awt.Robot; -import java.awt.event.InputEvent; -import util.DesktopTools; -import util.utils; - -/** - * Object implements the following interfaces : - *

                                    - *
                                  • ::com::sun::star::accessibility::XAccessible
                                  • - *
                                  • ::com::sun::star::accessibility::XAccessibleContext - *
                                  • - *
                                  • ::com::sun::star::accessibility::XAccessibleEventBroadcaster - *
                                  • - *
                                  - *

                                  - * - * @see com.sun.star.accessibility.XAccessible - * @see com.sun.star.accessibility.XAccessibleContext - * @see com.sun.star.accessibility.XAccessibleEventBroadcaster - * @see ifc.accessibility._XAccessible - * @see ifc.accessibility._XAccessibleContext - * @see ifc.accessibility._XAccessibleEventBroadcaster - */ -public class TableWindowAccessibility extends TestCase { - XWindow xWindow = null; - String aFile = ""; - XIsolatedConnection isolConnection = null; - XComponent QueryComponent = null; - String user = ""; - String password = ""; - - /** - * Creates a new DataSource and stores it. Creates a connection and using it - * creates two tables in database. Creates a new query and adds it to - * DefinitionContainer. Opens the QueryComponent.with loadComponentFromURL - * and gets the object with the role PANEL and the implementation name that - * contains TabelViewAccessibility - * - * @param Param - * test parameters - * @param log - * writer to log information while testing - * @return - * @throws StatusException - * @see TestEnvironment - */ - @Override - protected TestEnvironment createTestEnvironment(TestParameters Param, - PrintWriter log) throws Exception { - XInterface oObj = null; - - Param.getMSF().createInstance("com.sun.star.sdb.DatabaseContext"); - Object oDBSource = Param.getMSF() - .createInstance("com.sun.star.sdb.DataSource"); - Object newQuery = Param.getMSF().createInstance( - "com.sun.star.sdb.QueryDefinition"); - Param.getMSF().createInstance("com.sun.star.awt.Toolkit"); - - String mysqlURL = (String) Param.get("mysql.url"); - - if (mysqlURL == null) { - throw new StatusException( - Status.failed("Couldn't get 'mysql.url' from ini-file")); - } - - user = (String) Param.get("jdbc.user"); - password = (String) Param.get("jdbc.password"); - - if ((user == null) || (password == null)) { - throw new StatusException( - Status.failed("Couldn't get 'jdbc.user' or 'jdbc.password' from ini-file")); - } - - PropertyValue[] info = new PropertyValue[2]; - info[0] = new PropertyValue(); - info[0].Name = "user"; - info[0].Value = user; - info[1] = new PropertyValue(); - info[1].Name = "password"; - info[1].Value = password; - - XPropertySet propSetDBSource = UnoRuntime.queryInterface( - XPropertySet.class, oDBSource); - - propSetDBSource.setPropertyValue("URL", mysqlURL); - propSetDBSource.setPropertyValue("Info", info); - - log.println("writing database file ..."); - XDocumentDataSource xDDS = UnoRuntime.queryInterface( - XDocumentDataSource.class, oDBSource); - XStorable store = UnoRuntime.queryInterface(XStorable.class, - xDDS.getDatabaseDocument()); - aFile = utils.getOfficeTemp(Param.getMSF()) + "TableWindow.odb"; - log.println("... filename will be " + aFile); - store.storeAsURL(aFile, new PropertyValue[] {}); - log.println("... done"); - - isolConnection = UnoRuntime.queryInterface(XIsolatedConnection.class, - oDBSource); - - final String tbl_name1 = "tst_table1"; - final String tbl_name2 = "tst_table2"; - final String col_name1 = "id1"; - final String col_name2 = "id2"; - - util.utils.waitForEventIdle(Param.getMSF()); - XConnection connection = isolConnection.getIsolatedConnection(user, password); - XStatement statement = connection.createStatement(); - statement.executeUpdate("drop table if exists " + tbl_name1); - statement.executeUpdate("drop table if exists " + tbl_name2); - statement.executeUpdate("create table " + tbl_name1 + " (" - + col_name1 + " int)"); - statement.executeUpdate("create table " + tbl_name2 + " (" - + col_name2 + " int)"); - - XQueryDefinitionsSupplier querySuppl = UnoRuntime.queryInterface( - XQueryDefinitionsSupplier.class, oDBSource); - - XNameAccess defContainer = querySuppl.getQueryDefinitions(); - - XPropertySet queryProp = UnoRuntime.queryInterface(XPropertySet.class, - newQuery); - - final String query = "select * from " + tbl_name1 + ", " + tbl_name2 - + " where " + tbl_name1 + "." + col_name1 + "=" + tbl_name2 - + "." + col_name2; - queryProp.setPropertyValue("Command", query); - - XNameContainer queryContainer = UnoRuntime.queryInterface( - XNameContainer.class, defContainer); - - queryContainer.insertByName("Query1", newQuery); - store.store(); - connection.close(); - - PropertyValue[] loadProps = new PropertyValue[3]; - loadProps[0] = new PropertyValue(); - loadProps[0].Name = "QueryDesignView"; - loadProps[0].Value = Boolean.TRUE; - - loadProps[1] = new PropertyValue(); - loadProps[1].Name = "CurrentQuery"; - loadProps[1].Value = "Query1"; - - loadProps[2] = new PropertyValue(); - loadProps[2].Name = "DataSource"; - loadProps[2].Value = oDBSource; - - QueryComponent = DesktopTools.loadDoc(Param.getMSF(), - ".component:DB/QueryDesign", loadProps); - - xWindow = UnoRuntime.queryInterface(XModel.class, QueryComponent) - .getCurrentController().getFrame().getContainerWindow(); - - XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow); - - AccessibilityTools.printAccessibleTree(log, xRoot, - Param.getBool(util.PropertyName.DEBUG_IS_ACTIVE)); - - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, - AccessibleRole.PANEL, "", "TableWindowAccessibility"); - - log.println("ImplementationName " + util.utils.getImplName(oObj)); - - log.println("creating TestEnvironment ... done"); - - TestEnvironment tEnv = new TestEnvironment(oObj); - - util.utils.waitForEventIdle(Param.getMSF()); - - XAccessibleComponent accComp = UnoRuntime.queryInterface( - XAccessibleComponent.class, oObj); - - final Point point = accComp.getLocationOnScreen(); - - tEnv.addObjRelation( - "EventProducer", - new ifc.accessibility._XAccessibleEventBroadcaster.EventProducer() { - public void fireEvent() { - try { - Robot rob = new Robot(); - rob.mouseMove(point.X + 2, point.Y + 7); - rob.mousePress(InputEvent.BUTTON1_MASK); - rob.mouseMove(point.X + 400, point.Y); - rob.mouseRelease(InputEvent.BUTTON1_MASK); - } catch (java.awt.AWTException e) { - System.out.println("desired child doesn't exist"); - } - } - }); - - return tEnv; - } // finish method getTestEnvironment - - /** - * Closes all open documents. - */ - @Override - protected void cleanup(TestParameters Param, PrintWriter log) { - try { - - log.println("closing QueryComponent ..."); - DesktopTools.closeDoc(QueryComponent); - log.println("... done"); - XMultiServiceFactory xMSF = Param.getMSF(); - Object sfa = xMSF - .createInstance("com.sun.star.comp.ucb.SimpleFileAccess"); - XSimpleFileAccess xSFA = UnoRuntime.queryInterface( - XSimpleFileAccess.class, sfa); - log.println("deleting database file"); - xSFA.kill(aFile); - log.println("Could delete file " + aFile + ": " - + !xSFA.exists(aFile)); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/qadevOOo/tests/java/mod/_sc/ScAccessiblePreviewTable.java b/qadevOOo/tests/java/mod/_sc/ScAccessiblePreviewTable.java index fece4f3d1786..25e5e10886a5 100644 --- a/qadevOOo/tests/java/mod/_sc/ScAccessiblePreviewTable.java +++ b/qadevOOo/tests/java/mod/_sc/ScAccessiblePreviewTable.java @@ -166,7 +166,7 @@ public class ScAccessiblePreviewTable extends TestCase { XAccessibleContext zoomIn = AccessibilityTools.getAccessibleObjectForRole(xRoot,AccessibleRole.PUSH_BUTTON, "Zoom In"); - log.println("Getting \"" + zoomIn.getAccessibleName() + "\" which is a \"" + UnoRuntime.queryInterface(com.sun.star.lang.XServiceInfo.class, zoomIn).getImplementationName() + "\""); + log.println("Getting \"" + zoomIn.getAccessibleName()); final XAccessibleAction pressZoom = UnoRuntime.queryInterface(XAccessibleAction.class, zoomIn); tEnv.addObjRelation("EventProducer", diff --git a/qadevOOo/tests/java/mod/_stm/Pump.java b/qadevOOo/tests/java/mod/_stm/Pump.java index d53d6ea1efa7..5a4201992663 100644 --- a/qadevOOo/tests/java/mod/_stm/Pump.java +++ b/qadevOOo/tests/java/mod/_stm/Pump.java @@ -55,11 +55,11 @@ public class Pump extends TestCase { /** * Creating a TestEnvironment for the interfaces to be tested. * Creates an instance of the service com.sun.star.io.Pump. - * Settings up input and output streams for the created pump. + * Setting up input and output streams for the created pump. * Object relations created : *

                                    *
                                  • 'InputStream' for - * {@link ifc.io._XActiveDataSource}(an input stream to set)
                                  • + * {@link ifc.io._XActiveDataSink}(an input stream to set) *
                                  • 'OutputStream' for * {@link ifc.io._XActiveDataSource}(an output stream to set)
                                  • *
                                  @@ -105,7 +105,7 @@ public class Pump extends TestCase { * which a simple string consists. */ private static class MyInput implements XInputStream { - String str = "Pump tesing string" ; + String str = "Pump testing string" ; public int readBytes(byte[][] bytes, int len) throws NotConnectedException{ diff --git a/qadevOOo/tests/java/mod/_streams/uno/Pump.java b/qadevOOo/tests/java/mod/_streams/uno/Pump.java index 85669fbcc3fd..1a48285c26f4 100644 --- a/qadevOOo/tests/java/mod/_streams/uno/Pump.java +++ b/qadevOOo/tests/java/mod/_streams/uno/Pump.java @@ -55,11 +55,11 @@ public class Pump extends TestCase { /** * Creating a TestEnvironment for the interfaces to be tested. * Creates an instance of the service com.sun.star.io.Pump. - * Settings up input and output streams for the created pump. + * Setting up input and output streams for the created pump. * Object relations created : *
                                    *
                                  • 'InputStream' for - * {@link ifc.io._XActiveDataSource}(an input stream to set)
                                  • + * {@link ifc.io._XActiveDataSink}(an input stream to set) *
                                  • 'OutputStream' for * {@link ifc.io._XActiveDataSource}(an output stream to set)
                                  • *
                                  @@ -103,7 +103,7 @@ public class Pump extends TestCase { * which a simple string consists. */ private static class MyInput implements XInputStream { - String str = "Pump tesing string" ; + String str = "Pump testing string" ; public int readBytes(byte[][] bytes, int len) throws NotConnectedException{ diff --git a/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBox.java b/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBox.java deleted file mode 100644 index 2bba0293ef45..000000000000 --- a/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBox.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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 . - */ -package mod._svtools; - -import java.io.PrintWriter; - -import lib.TestCase; -import lib.TestEnvironment; -import lib.TestParameters; -import util.AccessibilityTools; -import util.DesktopTools; -import util.SOfficeFactory; - -import com.sun.star.accessibility.AccessibleRole; -import com.sun.star.accessibility.XAccessible; -import com.sun.star.awt.XWindow; -import com.sun.star.beans.PropertyValue; -import com.sun.star.frame.XController; -import com.sun.star.frame.XDesktop; -import com.sun.star.frame.XDispatch; -import com.sun.star.frame.XDispatchProvider; -import com.sun.star.frame.XFrame; -import com.sun.star.frame.XModel; -import com.sun.star.text.XTextDocument; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XInterface; -import com.sun.star.util.URL; -import com.sun.star.view.XSelectionSupplier; - -public class AccessibleBrowseBox extends TestCase { - - static XDesktop xDesktop; - static XTextDocument xTextDoc; - - /** - * Creates the Desktop service (com.sun.star.frame.Desktop). - */ - @Override - protected void initialize(TestParameters Param, PrintWriter log) throws Exception { - xDesktop = DesktopTools.createDesktop(Param.getMSF()); - } - - /** - * Disposes the document, if exists, created in - * createTestEnvironment method. - */ - @Override - protected void cleanup(TestParameters Param, PrintWriter log) { - - log.println("disposing xTextDoc"); - - if (xTextDoc != null) { - xTextDoc.dispose(); - } - } - - /** - * Called to create an instance of TestEnvironment with an - * object to test and related objects. Subclasses should implement this - * method to provide the implementation and related objects. The method is - * called from getTestEnvironment(). - * - * @param tParam test parameters - * @param log writer to log information while testing - * - * @see TestEnvironment - * @see #getTestEnvironment - */ - @Override - protected TestEnvironment createTestEnvironment(TestParameters tParam, PrintWriter log) throws Exception { - - log.println("creating a test environment"); - - if (xTextDoc != null) { - xTextDoc.dispose(); // get a soffice factory object - } - SOfficeFactory SOF = SOfficeFactory.getFactory(tParam.getMSF()); - - log.println("creating a text document"); - xTextDoc = SOF.createTextDoc(null); - - util.utils.waitForEventIdle(tParam.getMSF()); - - XModel aModel1 = UnoRuntime.queryInterface(XModel.class, xTextDoc); - - XController secondController = aModel1.getCurrentController(); - - - XDispatchProvider aProv = UnoRuntime.queryInterface(XDispatchProvider.class, - secondController); - - XDispatch getting = null; - - log.println("opening DatasourceBrowser"); - URL the_url = new URL(); - the_url.Complete = ".component:DB/DataSourceBrowser"; - getting = aProv.queryDispatch(the_url, "_beamer", 12); - PropertyValue[] noArgs = new PropertyValue[0]; - getting.dispatch(the_url, noArgs); - - util.utils.waitForEventIdle(tParam.getMSF()); - - XFrame the_frame1 = xDesktop.getCurrentFrame(); - - if (the_frame1 == null) { - log.println("Current frame was not found !!!"); - } - - XFrame the_frame2 = the_frame1.findFrame("_beamer", 4); - - the_frame2.setName("DatasourceBrowser"); - - XInterface oObj = null; - - final XSelectionSupplier xSelect = UnoRuntime.queryInterface( - XSelectionSupplier.class, the_frame2.getController()); - - PropertyValue[] params = new PropertyValue[]{new PropertyValue(), new PropertyValue(), new PropertyValue()}; - params[0].Name = "DataSourceName"; - params[0].Value = "Bibliography"; - params[1].Name = "CommandType"; - params[1].Value = Integer.valueOf(com.sun.star.sdb.CommandType.TABLE); - params[2].Name = "Command"; - params[2].Value = "biblio"; - - final PropertyValue[] fParams = params; - - util.utils.waitForEventIdle(tParam.getMSF()); - - XWindow xWindow = secondController.getFrame().getContainerWindow(); - - XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow); - - AccessibilityTools.printAccessibleTree(log, xRoot, tParam.getBool(util.PropertyName.DEBUG_IS_ACTIVE)); - - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.PANEL, "", "AccessibleBrowseBox"); - - log.println("ImplementationName: " + util.utils.getImplName(oObj)); - - TestEnvironment tEnv = new TestEnvironment(oObj); - - - tEnv.addObjRelation("EventProducer", - new ifc.accessibility._XAccessibleEventBroadcaster.EventProducer() { - - public void fireEvent() { - try { - xSelect.select(fParams); - } catch (com.sun.star.lang.IllegalArgumentException e) { - e.printStackTrace(); - } - } - }); - - return tEnv; - } -} diff --git a/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxHeaderBar.java b/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxHeaderBar.java deleted file mode 100644 index a19e6107666b..000000000000 --- a/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxHeaderBar.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * 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 . - */ -package mod._svtools; - -import com.sun.star.view.XSelectionSupplier; - -import java.awt.Robot; -import java.awt.event.InputEvent; -import java.io.PrintWriter; - -import lib.TestCase; -import lib.TestEnvironment; -import lib.TestParameters; -import util.AccessibilityTools; -import util.DesktopTools; -import util.SOfficeFactory; - -import com.sun.star.accessibility.AccessibleRole; -import com.sun.star.accessibility.XAccessible; -import com.sun.star.accessibility.XAccessibleComponent; -import com.sun.star.awt.Point; -import com.sun.star.awt.XWindow; -import com.sun.star.beans.PropertyValue; -import com.sun.star.frame.XController; -import com.sun.star.frame.XDesktop; -import com.sun.star.frame.XDispatch; -import com.sun.star.frame.XDispatchProvider; -import com.sun.star.frame.XFrame; -import com.sun.star.frame.XModel; -import com.sun.star.text.XTextDocument; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XInterface; -import com.sun.star.util.URL; - - -/** - * Test for object that implements the following interfaces : - *
                                    - *
                                  • - * ::com::sun::star::accessibility::XAccessibleContext - *
                                  • - *
                                  • - * ::com::sun::star::accessibility::XAccessibleEventBroadcaster - *
                                  • - *

                                  - * - * @see com.sun.star.accessibility.XAccessibleEventBroadcaster - * @see com.sun.star.accessibility.XAccessibleContext - * @see ifc.accessibility._XAccessibleEventBroadcaster - * @see ifc.accessibility._XAccessibleContext - */ -public class AccessibleBrowseBoxHeaderBar extends TestCase { - static XDesktop xDesktop; - static XTextDocument xTextDoc; - - /** - * Creates the Desktop service (com.sun.star.frame.Desktop). - */ - @Override - protected void initialize(TestParameters Param, PrintWriter log) throws Exception { - xDesktop = DesktopTools.createDesktop(Param.getMSF()); - } - - /** - * Disposes the document, if exists, created in - * createTestEnvironment method. - */ - @Override - protected void cleanup(TestParameters Param, PrintWriter log) { - log.println("disposing xTextDoc"); - - if (xTextDoc != null) { - xTextDoc.dispose(); - } - } - - /** - * Creates a text document. Opens the DataSource browser. - * Creates an instance of the service com.sun.star.awt.Toolkit - * and gets active top window. Then obtains an accessible object with - * the role AccessibleRole.TABLE. - * Object relations created : - *

                                    - *
                                  • 'EventProducer' for - * {@link ifc.accessibility._XAccessibleEventBroadcaster}: - *
                                  • - *
                                  - * - * @param tParam test parameters - * @param log writer to log information while testing - * - * @see com.sun.star.awt.Toolkit - * @see com.sun.star.accessibility.AccessibleRole - * @see ifc.accessibility._XAccessibleEventBroadcaster - * @see com.sun.star.accessibility.XAccessibleEventBroadcaster - */ - @Override - protected TestEnvironment createTestEnvironment(TestParameters tParam, - PrintWriter log) throws Exception { - log.println("creating a test environment"); - - if (xTextDoc != null) { - xTextDoc.dispose(); - } - - // get a soffice factory object - SOfficeFactory SOF = SOfficeFactory.getFactory( tParam.getMSF()); - - log.println("creating a text document"); - xTextDoc = SOF.createTextDoc(null); - - util.utils.waitForEventIdle(tParam.getMSF()); - - XModel aModel1 = UnoRuntime.queryInterface(XModel.class, - xTextDoc); - - XController secondController = aModel1.getCurrentController(); - - XDispatchProvider aProv = UnoRuntime.queryInterface( - XDispatchProvider.class, - secondController); - - XDispatch getting = null; - - log.println("opening DatasourceBrowser"); - - URL the_url = new URL(); - the_url.Complete = ".component:DB/DataSourceBrowser"; - getting = aProv.queryDispatch(the_url, "_beamer", 12); - - // an XSelectionSupplier at the controller -> call with params - PropertyValue[] noArgs = new PropertyValue[0]; - getting.dispatch(the_url, noArgs); - - PropertyValue[] params = new PropertyValue[3]; - PropertyValue param1 = new PropertyValue(); - param1.Name = "DataSourceName"; - param1.Value = "Bibliography"; - params[0] = param1; - - PropertyValue param2 = new PropertyValue(); - param2.Name = "CommandType"; - param2.Value = Integer.valueOf(com.sun.star.sdb.CommandType.TABLE); - params[1] = param2; - - PropertyValue param3 = new PropertyValue(); - param3.Name = "Command"; - param3.Value = "biblio"; - params[2] = param3; - - util.utils.waitForEventIdle(tParam.getMSF()); - - XFrame the_frame1 = xDesktop.getCurrentFrame(); - - if (the_frame1 == null) { - log.println("Current frame was not found !!!"); - } - - XFrame the_frame2 = the_frame1.findFrame("_beamer", 4); - - the_frame2.setName("DatasourceBrowser"); - - XController xCont = the_frame2.getController(); - - XSelectionSupplier xSelect = UnoRuntime.queryInterface( - XSelectionSupplier.class, xCont); - - xSelect.select(params); - - XInterface oObj = null; - - XWindow xWindow = secondController.getFrame().getContainerWindow(); - - XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow); - - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.TABLE); - - AccessibilityTools.printAccessibleTree(log, xRoot, tParam.getBool(util.PropertyName.DEBUG_IS_ACTIVE)); - log.println("ImplementationName: " + util.utils.getImplName(oObj)); - - TestEnvironment tEnv = new TestEnvironment(oObj); - - util.utils.waitForEventIdle(tParam.getMSF()); - - XAccessibleComponent accComp = UnoRuntime.queryInterface( - XAccessibleComponent.class, - oObj); - final Point point = accComp.getLocationOnScreen(); - - util.utils.waitForEventIdle(tParam.getMSF()); - - tEnv.addObjRelation("EventProducer", - new ifc.accessibility._XAccessibleEventBroadcaster.EventProducer() { - public void fireEvent() { - try { - Robot rob = new Robot(); - rob.mouseMove(point.X + 5, point.Y + 5); - rob.mousePress(InputEvent.BUTTON1_MASK); - } catch (java.awt.AWTException e) { - System.out.println("couldn't fire event"); - } - } - }); - - return tEnv; - } -} diff --git a/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxHeaderCell.java b/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxHeaderCell.java deleted file mode 100644 index e050458ecc09..000000000000 --- a/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxHeaderCell.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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 . - */ - -package mod._svtools; - -import com.sun.star.view.XSelectionSupplier; - -import java.io.PrintWriter; - -import lib.TestCase; -import lib.TestEnvironment; -import lib.TestParameters; -import util.AccessibilityTools; -import util.DesktopTools; -import util.SOfficeFactory; - -import com.sun.star.accessibility.AccessibleRole; -import com.sun.star.accessibility.XAccessible; -import com.sun.star.awt.XWindow; -import com.sun.star.beans.PropertyValue; -import com.sun.star.frame.XController; -import com.sun.star.frame.XDesktop; -import com.sun.star.frame.XDispatch; -import com.sun.star.frame.XDispatchProvider; -import com.sun.star.frame.XFrame; -import com.sun.star.frame.XModel; -import com.sun.star.lang.XInitialization; -import com.sun.star.text.XTextDocument; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XInterface; -import com.sun.star.util.URL; - -/** - * Test for object that implements the following interfaces : - *
                                    - *
                                  • - * ::com::sun::star::accessibility::XAccessibleContext - *
                                  • - *
                                  • - * ::com::sun::star::accessibility::XAccessibleEventBroadcaster - *
                                  • - *

                                  - * - * @see com.sun.star.accessibility.XAccessibleEventBroadcaster - * @see com.sun.star.accessibility.XAccessibleContext - * @see ifc.accessibility._XAccessibleEventBroadcaster - * @see ifc.accessibility._XAccessibleContext - */ -public class AccessibleBrowseBoxHeaderCell extends TestCase { - - static XDesktop the_Desk; - static XTextDocument xTextDoc; - - /** - * Creates the Desktop service (com.sun.star.frame.Desktop). - */ - @Override - protected void initialize(TestParameters Param, PrintWriter log) throws Exception { - the_Desk = UnoRuntime.queryInterface( - XDesktop.class, DesktopTools.createDesktop(Param.getMSF())); - } - - /** - * Disposes the document, if exists, created in - * createTestEnvironment method. - */ - @Override - protected void cleanup( TestParameters Param, PrintWriter log) { - - log.println("disposing xTextDoc"); - - if (xTextDoc != null) { - xTextDoc.dispose(); - } - } - - /** - * Creates a text document. Opens the DataSource browser and loads - * the table. Creates an instance of the service - * com.sun.star.awt.Toolkit and gets active top window. - * Then obtains an accessible object with the role - * AccessibleRole.UNKNOWN and with the name - * "Identifier". - * Object relations created : - *

                                    - *
                                  • 'EventProducer' for - * {@link ifc.accessibility._XAccessibleEventBroadcaster}: - * method fireEvent() is empty because object is transient - *
                                  • - *
                                  - * - * @param tParam test parameters - * @param log writer to log information while testing - * - * @see com.sun.star.awt.Toolkit - * @see com.sun.star.accessibility.AccessibleRole - * @see ifc.accessibility._XAccessibleEventBroadcaster - * @see com.sun.star.accessibility.XAccessibleEventBroadcaster - */ - @Override - protected TestEnvironment createTestEnvironment( - TestParameters tParam, PrintWriter log) throws Exception { - - log.println( "creating a test environment" ); - - if (xTextDoc != null) xTextDoc.dispose(); - - // get a soffice factory object - SOfficeFactory SOF = SOfficeFactory.getFactory( tParam.getMSF()); - - log.println( "creating a text document" ); - xTextDoc = SOF.createTextDoc(null); - - util.utils.waitForEventIdle(tParam.getMSF()); - - XModel aModel1 = UnoRuntime.queryInterface(XModel.class, xTextDoc); - - XController secondController = aModel1.getCurrentController(); - - XDispatchProvider aProv = UnoRuntime. - queryInterface(XDispatchProvider.class, secondController); - - XDispatch getting = null; - - log.println( "opening DatasourceBrowser" ); - URL the_url = new URL(); - the_url.Complete = ".component:DB/DataSourceBrowser"; - getting = aProv.queryDispatch(the_url, "_beamer", 12); - PropertyValue[] noArgs = new PropertyValue[0]; - getting.dispatch(the_url, noArgs); - - util.utils.waitForEventIdle(tParam.getMSF()); - - XFrame the_frame1 = the_Desk.getCurrentFrame(); - - if (the_frame1 == null) { - log.println("Current frame was not found !!!"); - } - - XFrame the_frame2 = the_frame1.findFrame("_beamer", 4); - - the_frame2.setName("DatasourceBrowser"); - - XInterface oObj = null; - - UnoRuntime.queryInterface( - XInitialization.class, the_frame2.getController()); - - PropertyValue[] params = new PropertyValue[3]; - PropertyValue param1 = new PropertyValue(); - param1.Name = "DataSourceName"; - param1.Value = "Bibliography"; - params[0] = param1; - PropertyValue param2 = new PropertyValue(); - param2.Name = "CommandType"; - param2.Value = Integer.valueOf(com.sun.star.sdb.CommandType.TABLE); - params[1] = param2; - PropertyValue param3 = new PropertyValue(); - param3.Name = "Command"; - param3.Value = "biblio"; - params[2] = param3; - - XController xCont = the_frame2.getController(); - - XSelectionSupplier xSelect = UnoRuntime.queryInterface( - XSelectionSupplier.class, xCont); - - xSelect.select(params); - - XWindow xWindow = secondController.getFrame().getContainerWindow(); - - XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow); - - AccessibilityTools.printAccessibleTree(log, xRoot, tParam.getBool(util.PropertyName.DEBUG_IS_ACTIVE)); - - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, - AccessibleRole.ROW_HEADER); - - log.println("ImplementationName: "+ util.utils.getImplName(oObj)); - - TestEnvironment tEnv = new TestEnvironment(oObj); - - tEnv.addObjRelation("EventProducer", - new ifc.accessibility._XAccessibleEventBroadcaster.EventProducer(){ - public void fireEvent() { - } - }); - - return tEnv; - } - -} diff --git a/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxTable.java b/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxTable.java deleted file mode 100644 index 49f42f4c624b..000000000000 --- a/qadevOOo/tests/java/mod/_svtools/AccessibleBrowseBoxTable.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * 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 . - */ -package mod._svtools; - -import com.sun.star.view.XSelectionSupplier; - -import java.io.PrintWriter; - -import lib.TestCase; -import lib.TestEnvironment; -import lib.TestParameters; -import util.AccessibilityTools; -import util.DesktopTools; -import util.SOfficeFactory; - -import com.sun.star.accessibility.AccessibleRole; -import com.sun.star.accessibility.XAccessible; -import com.sun.star.awt.XWindow; -import com.sun.star.beans.PropertyValue; -import com.sun.star.frame.XController; -import com.sun.star.frame.XDesktop; -import com.sun.star.frame.XDispatch; -import com.sun.star.frame.XDispatchProvider; -import com.sun.star.frame.XFrame; -import com.sun.star.frame.XModel; -import com.sun.star.text.XTextDocument; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XInterface; -import com.sun.star.util.URL; - - -/** - * Test for object that implements the following interfaces : - *
                                    - *
                                  • - * ::com::sun::star::accessibility::XAccessibleContext - *
                                  • - *
                                  • - * ::com::sun::star::accessibility::XAccessibleEventBroadcaster - *
                                  • - *

                                  - * - * @see com.sun.star.accessibility.XAccessibleEventBroadcaster - * @see com.sun.star.accessibility.XAccessibleContext - * @see ifc.accessibility._XAccessibleEventBroadcaster - * @see ifc.accessibility._XAccessibleContext - */ -public class AccessibleBrowseBoxTable extends TestCase { - static XDesktop the_Desk; - static XTextDocument xTextDoc; - - /** - * Creates the Desktop service (com.sun.star.frame.Desktop). - */ - @Override - protected void initialize(TestParameters Param, PrintWriter log) throws Exception { - the_Desk = UnoRuntime.queryInterface(XDesktop.class, - DesktopTools.createDesktop( - Param.getMSF())); - } - - /** - * Disposes the document, if exists, created in - * createTestEnvironment method. - */ - @Override - protected void cleanup(TestParameters Param, PrintWriter log) { - log.println("disposing xTextDoc"); - - if (xTextDoc != null) { - xTextDoc.dispose(); - } - } - - /** - * Creates a text document. Opens the DataSource browser. - * Creates an instance of the service - * com.sun.star.awt.Toolkit and gets active top window. - * Then obtains an accessible object with the role - * AccessibleRole.TABLE and with the name - * "Table". - * Object relations created : - *

                                    - *
                                  • 'EventProducer' for - * {@link ifc.accessibility._XAccessibleEventBroadcaster}: - * method fireEvent() is empty because object is transient - *
                                  • - *
                                  - * - * @param tParam test parameters - * @param log writer to log information while testing - * - * @see com.sun.star.awt.Toolkit - * @see com.sun.star.accessibility.AccessibleRole - * @see ifc.accessibility._XAccessibleEventBroadcaster - * @see com.sun.star.accessibility.XAccessibleEventBroadcaster - */ - @Override - protected TestEnvironment createTestEnvironment(TestParameters tParam, - PrintWriter log) throws Exception { - log.println("creating a test environment"); - - if (xTextDoc != null) { - xTextDoc.dispose(); - } - - // get a soffice factory object - SOfficeFactory SOF = SOfficeFactory.getFactory( - tParam.getMSF()); - - log.println("creating a text document"); - xTextDoc = SOF.createTextDoc(null); - - util.utils.waitForEventIdle(tParam.getMSF()); - - XModel aModel1 = UnoRuntime.queryInterface(XModel.class, - xTextDoc); - - XController secondController = aModel1.getCurrentController(); - - XDispatchProvider aProv = UnoRuntime.queryInterface( - XDispatchProvider.class, - secondController); - - XDispatch getting = null; - - log.println("opening DatasourceBrowser"); - - URL the_url = new URL(); - the_url.Complete = ".component:DB/DataSourceBrowser"; - getting = aProv.queryDispatch(the_url, "_beamer", 12); - - PropertyValue[] noArgs = new PropertyValue[0]; - getting.dispatch(the_url, noArgs); - - util.utils.waitForEventIdle(tParam.getMSF()); - - XFrame the_frame1 = the_Desk.getCurrentFrame(); - - if (the_frame1 == null) { - log.println("Current frame was not found !!!"); - } - - XFrame the_frame2 = the_frame1.findFrame("_beamer", 4); - XController xCont = the_frame2.getController(); - - the_frame2.setName("DatasourceBrowser"); - - final PropertyValue[] params = new PropertyValue[3]; - PropertyValue param1 = new PropertyValue(); - param1.Name = "DataSourceName"; - param1.Value = "Bibliography"; - params[0] = param1; - - PropertyValue param2 = new PropertyValue(); - param2.Name = "CommandType"; - param2.Value = Integer.valueOf(com.sun.star.sdb.CommandType.TABLE); - params[1] = param2; - - PropertyValue param3 = new PropertyValue(); - param3.Name = "Command"; - param3.Value = "biblio"; - params[2] = param3; - - final XSelectionSupplier xSelect = UnoRuntime.queryInterface( - XSelectionSupplier.class, xCont); - - - XInterface oObj = null; - - XWindow xWindow = secondController.getFrame().getContainerWindow(); - - XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow); - - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.TABLE, - "Table"); - - log.println("ImplementationName: " + util.utils.getImplName(oObj)); - - TestEnvironment tEnv = new TestEnvironment(oObj); - - tEnv.addObjRelation("EventProducer", - new ifc.accessibility._XAccessibleEventBroadcaster.EventProducer() { - public void fireEvent() { - try { - xSelect.select(params); - } catch (com.sun.star.lang.IllegalArgumentException ex) { - } - } - }); - - return tEnv; - } -} diff --git a/qadevOOo/tests/java/mod/_toolkit/AccessibleComboBox.java b/qadevOOo/tests/java/mod/_toolkit/AccessibleComboBox.java index 5e04b73da9f2..568216707592 100644 --- a/qadevOOo/tests/java/mod/_toolkit/AccessibleComboBox.java +++ b/qadevOOo/tests/java/mod/_toolkit/AccessibleComboBox.java @@ -141,8 +141,6 @@ public class AccessibleComboBox extends TestCase { oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.PANEL, "", "AccessibleComboBox"); - log.println("ImplementationName " + utils.getImplName(oObj)); - TestEnvironment tEnv = new TestEnvironment(oObj); final XAccessibleComponent acomp = UnoRuntime.queryInterface( diff --git a/qadevOOo/tests/java/mod/_toolkit/AccessibleList.java b/qadevOOo/tests/java/mod/_toolkit/AccessibleList.java deleted file mode 100644 index f88b7dbe13d8..000000000000 --- a/qadevOOo/tests/java/mod/_toolkit/AccessibleList.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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 . - */ -package mod._toolkit; - -import com.sun.star.accessibility.AccessibleRole; -import com.sun.star.accessibility.XAccessible; -import com.sun.star.accessibility.XAccessibleAction; -import com.sun.star.accessibility.XAccessibleComponent; -import com.sun.star.accessibility.XAccessibleContext; -import com.sun.star.accessibility.XAccessibleSelection; -import com.sun.star.awt.XExtendedToolkit; -import com.sun.star.awt.XWindow; -import com.sun.star.beans.PropertyValue; -import com.sun.star.frame.XController; -import com.sun.star.frame.XDispatch; -import com.sun.star.frame.XDispatchProvider; -import com.sun.star.frame.XModel; -import com.sun.star.lang.XMultiServiceFactory; -import com.sun.star.text.XTextDocument; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XInterface; -import com.sun.star.util.URL; -import com.sun.star.util.XURLTransformer; - -import java.io.PrintWriter; - -import lib.TestCase; -import lib.TestEnvironment; -import lib.TestParameters; -import util.AccessibilityTools; -import util.SOfficeFactory; -import util.utils; - - -public class AccessibleList extends TestCase { - private static XTextDocument xTextDoc = null; - private static XAccessibleAction action = null; - private static XMultiServiceFactory msf = null; - - /** - * Opens 'Insert Hyperlink' dialog using document dispatch provider. - * Finds active top window (the dialog - * window) and finds button 'Close' (for closing this dialog when - * disposing) walking through the accessible component tree. - * Then the TREE component is found and the 'New Document' tab is - * selected to make list box visible. After that list box is obtained. - */ - @Override - protected TestEnvironment createTestEnvironment(TestParameters Param, - PrintWriter log) throws Exception { - XInterface oObj = (XInterface) msf.createInstance("com.sun.star.awt.Toolkit"); - - XExtendedToolkit tk = UnoRuntime.queryInterface( - XExtendedToolkit.class, oObj); - - util.utils.waitForEventIdle(Param.getMSF()); - - XModel aModel1 = UnoRuntime.queryInterface(XModel.class, - xTextDoc); - - XController secondController = aModel1.getCurrentController(); - - XDispatchProvider aProv = UnoRuntime.queryInterface( - XDispatchProvider.class, - secondController); - - XURLTransformer urlTransf = null; - - XInterface transf = (XInterface) msf.createInstance( - "com.sun.star.util.URLTransformer"); - urlTransf = UnoRuntime.queryInterface( - XURLTransformer.class, transf); - - XDispatch getting = null; - log.println("opening HyperlinkDialog"); - - URL[] url = new URL[1]; - url[0] = new URL(); - url[0].Complete = ".uno:HyperlinkDialog"; - urlTransf.parseStrict(url); - getting = aProv.queryDispatch(url[0], "", 0); - - PropertyValue[] noArgs = new PropertyValue[0]; - getting.dispatch(url[0], noArgs); - - XWindow xWindow = UnoRuntime.queryInterface(XWindow.class, - tk.getActiveTopWindow()); - - XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow); - - - AccessibilityTools.printAccessibleTree(log, xRoot, Param.getBool(util.PropertyName.DEBUG_IS_ACTIVE)); - // obtaining 'Close' button - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.PUSH_BUTTON, - "Close"); - action = UnoRuntime.queryInterface( - XAccessibleAction.class, oObj); - - // Selecting 'New Document' tab - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.TREE); - - XAccessibleSelection xAccSel = UnoRuntime.queryInterface( - XAccessibleSelection.class, - oObj); - xAccSel.selectAccessibleChild(3); - util.utils.waitForEventIdle(Param.getMSF()); - - log.println("# Getting the ListBox"); - - XAccessibleContext parent = AccessibilityTools.getAccessibleObjectForRole(xRoot, - AccessibleRole.PANEL, - "", - "com.sun.star.comp.toolkit.AccessibleListBox"); - - log.println("# Getting the first child"); - - try { - oObj = parent.getAccessibleChild(0); - } catch (com.sun.star.lang.IndexOutOfBoundsException e) { - } - - log.println("ImplementationName " + utils.getImplName(oObj)); - - TestEnvironment tEnv = new TestEnvironment(oObj); - - tEnv.addObjRelation("XAccessibleSelection.multiSelection", - Boolean.FALSE); - - final XAccessibleComponent acomp = UnoRuntime.queryInterface( - XAccessibleComponent.class, - oObj); - final XAccessibleComponent acomp1 = UnoRuntime.queryInterface( - XAccessibleComponent.class, - action); - - tEnv.addObjRelation("EventProducer", - new ifc.accessibility._XAccessibleEventBroadcaster.EventProducer() { - public void fireEvent() { - System.out.println("Grabbing focus ... "); - acomp1.grabFocus(); - acomp.grabFocus(); - } - }); - - return tEnv; - } - - /** - * Closes dialog using action of button 'Close' - */ - @Override - protected void cleanup(TestParameters Param, PrintWriter log) { - log.println(" Closing dialog ... "); - - try { - action.doAccessibleAction(0); - } catch (com.sun.star.lang.IndexOutOfBoundsException ioe) { - log.println("Couldn't close dialog"); - } catch (com.sun.star.lang.DisposedException de) { - log.println("Dialog already disposed"); - } - - util.DesktopTools.closeDoc(xTextDoc); - } - - /** - * Creates writer document - */ - @Override - protected void initialize(TestParameters Param, PrintWriter log) throws Exception { - msf = Param.getMSF(); - - SOfficeFactory SOF = SOfficeFactory.getFactory(msf); - xTextDoc = SOF.createTextDoc(null); - } -} \ No newline at end of file diff --git a/qadevOOo/tests/java/mod/_toolkit/AccessibleListBox.java b/qadevOOo/tests/java/mod/_toolkit/AccessibleListBox.java deleted file mode 100644 index dcbef787f591..000000000000 --- a/qadevOOo/tests/java/mod/_toolkit/AccessibleListBox.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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 . - */ -package mod._toolkit; - -import com.sun.star.accessibility.AccessibleRole; -import com.sun.star.accessibility.XAccessible; -import com.sun.star.accessibility.XAccessibleAction; -import com.sun.star.accessibility.XAccessibleComponent; -import com.sun.star.accessibility.XAccessibleSelection; -import com.sun.star.awt.XExtendedToolkit; -import com.sun.star.awt.XWindow; -import com.sun.star.beans.PropertyValue; -import com.sun.star.frame.XController; -import com.sun.star.frame.XDispatch; -import com.sun.star.frame.XDispatchProvider; -import com.sun.star.frame.XModel; -import com.sun.star.text.XTextDocument; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XInterface; -import com.sun.star.util.URL; -import com.sun.star.util.XURLTransformer; - -import java.io.PrintWriter; - -import lib.TestCase; -import lib.TestEnvironment; -import lib.TestParameters; -import util.AccessibilityTools; -import util.SOfficeFactory; -import util.utils; - - -/** - * Test for object which is represented accessible component - * of 'File type' list box situated in 'Insert Hyperlink' - * dialog on tab 'New Document'.

                                  - * - * Object implements the following interfaces : - *

                                    - *
                                  • ::com::sun::star::accessibility::XAccessibleExtendedComponent
                                  • - *
                                  • ::com::sun::star::accessibility::XAccessibleEventBroadcaster
                                  • - *
                                  • ::com::sun::star::accessibility::XAccessibleComponent
                                  • - *
                                  • ::com::sun::star::accessibility::XAccessibleSelection
                                  • - *
                                  • ::com::sun::star::accessibility::XAccessibleContext
                                  • - *

                                  - * - * @see com.sun.star.accessibility.XAccessibleExtendedComponent - * @see com.sun.star.accessibility.XAccessibleEventBroadcaster - * @see com.sun.star.accessibility.XAccessibleComponent - * @see com.sun.star.accessibility.XAccessibleSelection - * @see com.sun.star.accessibility.XAccessibleContext - * @see ifc.accessibility._XAccessibleExtendedComponent - * @see ifc.accessibility._XAccessibleEventBroadcaster - * @see ifc.accessibility._XAccessibleComponent - * @see ifc.accessibility._XAccessibleSelection - * @see ifc.accessibility._XAccessibleContext - */ -public class AccessibleListBox extends TestCase { - private static XTextDocument xTextDoc = null; - private static XAccessibleAction action = null; - - /** - * Opens 'Insert Hyperlink' dialog using document dispatch provider. - * Finds active top window (the dialog - * window) and finds button 'Close' (for closing this dialog when - * disposing) walking through the accessible component tree. - * Then the TREE component is found and the 'New Document' tab is - * selected to make list box visible. After that list box is obtained. - */ - @Override - protected TestEnvironment createTestEnvironment(TestParameters Param, - PrintWriter log) throws Exception { - XInterface oObj = (XInterface) Param.getMSF().createInstance( - "com.sun.star.awt.Toolkit"); - - XExtendedToolkit tk = UnoRuntime.queryInterface( - XExtendedToolkit.class, oObj); - - util.utils.waitForEventIdle(Param.getMSF()); - - XModel aModel1 = UnoRuntime.queryInterface(XModel.class, - xTextDoc); - - XController secondController = aModel1.getCurrentController(); - - XDispatchProvider aProv = UnoRuntime.queryInterface( - XDispatchProvider.class, - secondController); - - XURLTransformer urlTransf = null; - - XInterface transf = (XInterface) Param.getMSF().createInstance( - "com.sun.star.util.URLTransformer"); - urlTransf = UnoRuntime.queryInterface( - XURLTransformer.class, transf); - - XDispatch getting = null; - log.println("opening HyperlinkDialog"); - - URL[] url = new URL[1]; - url[0] = new URL(); - url[0].Complete = ".uno:HyperlinkDialog"; - urlTransf.parseStrict(url); - getting = aProv.queryDispatch(url[0], "", 0); - - PropertyValue[] noArgs = new PropertyValue[0]; - getting.dispatch(url[0], noArgs); - - util.utils.waitForEventIdle(Param.getMSF()); - - XWindow xWindow = UnoRuntime.queryInterface(XWindow.class, - tk.getActiveTopWindow()); - - XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow); - - AccessibilityTools.printAccessibleTree(log, xRoot, Param.getBool(util.PropertyName.DEBUG_IS_ACTIVE)); - - - // obtaining 'Close' button - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.PUSH_BUTTON, - "Close"); - action = UnoRuntime.queryInterface( - XAccessibleAction.class, oObj); - - // Selecting 'New Document' tab - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.TREE); - - XAccessibleSelection xAccSel = UnoRuntime.queryInterface( - XAccessibleSelection.class, - oObj); - xAccSel.selectAccessibleChild(3); - util.utils.waitForEventIdle(Param.getMSF()); - - oObj = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.PANEL, "", - "com.sun.star.comp.toolkit.AccessibleListBox"); - - Object list = AccessibilityTools.getAccessibleObjectForRole(AccessibilityTools.SearchedAccessible, - AccessibleRole.LIST); - - log.println("ImplementationName " + utils.getImplName(oObj)); - - TestEnvironment tEnv = new TestEnvironment(oObj); - - final XAccessibleComponent acomp = UnoRuntime.queryInterface( - XAccessibleComponent.class, - list); - final XAccessibleComponent acomp1 = UnoRuntime.queryInterface( - XAccessibleComponent.class, - action); - - tEnv.addObjRelation("EventProducer", - new ifc.accessibility._XAccessibleEventBroadcaster.EventProducer() { - public void fireEvent() { - System.out.println("Grabbing focus ... "); - acomp1.grabFocus(); - acomp.grabFocus(); - } - }); - - return tEnv; - } - - /** - * Closes dialog using action of button 'Close' - */ - @Override - protected void cleanup(TestParameters Param, PrintWriter log) { - log.println(" Closing dialog ... "); - - try { - action.doAccessibleAction(0); - } catch (com.sun.star.lang.IndexOutOfBoundsException ioe) { - log.println("Couldn't close dialog"); - } catch (com.sun.star.lang.DisposedException de) { - log.println("Dialog already disposed"); - } - - util.DesktopTools.closeDoc(xTextDoc); - } - - /** - * Creates writer document - */ - @Override - protected void initialize(TestParameters Param, PrintWriter log) throws Exception { - SOfficeFactory SOF = SOfficeFactory.getFactory( - Param.getMSF()); - xTextDoc = SOF.createTextDoc(null); - } -} \ No newline at end of file diff --git a/qadevOOo/tests/java/mod/_toolkit/AccessibleMenuSeparator.java b/qadevOOo/tests/java/mod/_toolkit/AccessibleMenuSeparator.java index 48e14436f3fc..1a3b571504b1 100644 --- a/qadevOOo/tests/java/mod/_toolkit/AccessibleMenuSeparator.java +++ b/qadevOOo/tests/java/mod/_toolkit/AccessibleMenuSeparator.java @@ -65,9 +65,7 @@ public class AccessibleMenuSeparator extends TestCase { private static XMultiServiceFactory msf = null; /** - * Finds first accessible component with role SEPARATOR - * and implementation name AccessibleMenuSeparator - * walking through the accessible component tree of a document. + * Finds accessible menu separator. */ @Override protected TestEnvironment createTestEnvironment(TestParameters Param, @@ -138,4 +136,4 @@ public class AccessibleMenuSeparator extends TestCase { protected void cleanup(TestParameters Param, PrintWriter log) { util.DesktopTools.closeDoc(xTextDoc); } -} \ No newline at end of file +} diff --git a/readlicense_oo/license/CREDITS.fodt b/readlicense_oo/license/CREDITS.fodt index 4703a4954d06..a30440843f3d 100644 --- a/readlicense_oo/license/CREDITS.fodt +++ b/readlicense_oo/license/CREDITS.fodt @@ -1,13 +1,13 @@ - - Credits » LibreOfficeCreditscontributorscodersdevelopersCredits for the LibreOffice development/coding.LibreOffice/26.2.1.2$Linux_X86_64 LibreOffice_project/8399f6259d8c87f40e7255cdb3c9b958f5e089482012-02-20T22:17:18.060000000PT14M12S3JUebjoxEpqXoQcpltWRTwzBZEEHtch3wApdhgiQPFiA + + Credits » LibreOfficeCreditscontributorscodersdevelopersCredits for the LibreOffice development/coding.LibreOffice/26.8.0.3$Linux_X86_64 LibreOffice_project/bce0998afefdbc355585ca324285661a2170ba772012-02-20T22:17:18.060000000PT14M12S3JUebjoxEpqXoQcpltWRTwzBZEEHtch3wApdhgiQPFiA - 1392 + 3198 501 - 51613 - 29212 + 41965 + 23179 true true @@ -16,16 +16,16 @@ 3323 3434 501 - 1392 - 52112 - 30602 + 3198 + 42464 + 26375 0 0 false 100 false false - 0,0,3435,1897;1;,,,; + 0,0,2888,1555;1;,,,; false false false @@ -43,6 +43,7 @@ 0 false false + true true false false @@ -160,7 +161,7 @@ false true - 15338648 + 15764230 true false false @@ -192,11 +193,11 @@ - + - + @@ -271,7 +272,7 @@ - + @@ -279,11 +280,11 @@ - + - + @@ -383,37 +384,34 @@ - + - + - + - + - + - - - - + - + - + - + @@ -421,6 +419,9 @@ + + + @@ -464,24 +465,24 @@ - + - + - + - + - + - + @@ -492,13 +493,13 @@ - - - - + + + + @@ -866,7 +867,7 @@ Credits - 2189 individuals contributed to OpenOffice.org (and whose contributions were imported into LibreOffice) or LibreOffice until 2026-03-16 02:31:12. + 2246 individuals contributed to OpenOffice.org (and whose contributions were imported into LibreOffice) or LibreOffice until 2026-09-16 12:56:00. * marks developers whose first contributions happened after 2010-09-28. Developers committing code since 2010-09-28 @@ -879,7 +880,7 @@ Ruediger TimmCommits: 82464Joined: 2000-10-10 - Caolán McNamaraCommits: 37536Joined: 2000-10-10 + Caolán McNamaraCommits: 37825Joined: 2000-10-10 Kurt ZenkerCommits: 31752Joined: 2000-09-25 @@ -896,27 +897,30 @@ Vladimir GlazunovCommits: 25434Joined: 2000-12-04 - Stephan BergmannCommits: 21530Joined: 2000-10-04 + Stephan BergmannCommits: 21770Joined: 2000-10-04 - *Noel GrandinCommits: 20794Joined: 2011-12-12 + *Noel GrandinCommits: 20936Joined: 2011-12-12 - Miklos VajnaCommits: 10459Joined: 2010-07-29 + Miklos VajnaCommits: 10493Joined: 2010-07-29 Ivo HinkelmannCommits: 9480Joined: 2002-09-09 - Tor LillqvistCommits: 9232Joined: 2010-03-23 + Tor LillqvistCommits: 9233Joined: 2010-03-23 - Michael StahlCommits: 8681Joined: 2008-06-16 + Michael StahlCommits: 8771Joined: 2008-06-16 + + *Michael WeghornCommits: 6335Joined: 2014-09-10 + Kohei YoshidaCommits: 5587Joined: 2009-06-19 @@ -926,30 +930,27 @@ *Markus MohrhardCommits: 5230Joined: 2011-03-17 + + Frank Schoenheit [fs]Commits: 5008Joined: 2000-09-19 - - - *Michael WeghornCommits: 4903Joined: 2014-09-10 + *Andrea GelminiCommits: 4991Joined: 2014-10-30 - *Mike KaganskiCommits: 4853Joined: 2015-04-26 + *Mike KaganskiCommits: 4990Joined: 2015-04-26 - *Andrea GelminiCommits: 4572Joined: 2014-10-30 - - - *Xisco FauliCommits: 4205Joined: 2011-02-06 + *Xisco FauliCommits: 4561Joined: 2011-02-06 - *Julien NabetCommits: 4031Joined: 2010-11-04 + *Julien NabetCommits: 4152Joined: 2010-11-04 - *Tomaž VajngerlCommits: 3797Joined: 2012-06-02 + *Tomaž VajngerlCommits: 4064Joined: 2012-06-02 David TardonCommits: 3648Joined: 2009-11-12 @@ -966,21 +967,21 @@ Ocke Janssen [oj]Commits: 2850Joined: 2000-09-20 - Oliver SpechtCommits: 2698Joined: 2000-09-21 + Oliver SpechtCommits: 2702Joined: 2000-09-21 - Jan HolesovskyCommits: 2684Joined: 2009-06-23 + Jan HolesovskyCommits: 2686Joined: 2009-06-23 + + *Olivier HallotCommits: 2660Joined: 2010-10-25 + Mathias BauerCommits: 2580Joined: 2000-09-20 - *Olivier HallotCommits: 2554Joined: 2010-10-25 - - - Michael MeeksCommits: 2543Joined: 2004-08-05 + Michael MeeksCommits: 2546Joined: 2004-08-05 Bjoern MichaelsenCommits: 2510Joined: 2009-10-14 @@ -994,7 +995,7 @@ *Thomas ArnholdCommits: 2176Joined: 2011-01-16 - *Andras TimarCommits: 2099Joined: 2010-10-02 + *Andras TimarCommits: 2160Joined: 2010-10-02 Philipp Lohmann [pl]Commits: 2089Joined: 2000-09-21 @@ -1005,44 +1006,47 @@ Christian LippkaCommits: 1805Joined: 2000-09-25 - Armin Le Grand (allotropia)Commits: 1788Joined: 2000-09-25 + Armin Le Grand (allotropia)Commits: 1789Joined: 2000-09-22 *Matúš KukanCommits: 1712Joined: 2011-04-06 - *Christopher SherlockCommits: 1630Joined: 2013-02-25 + *Christopher SherlockCommits: 1675Joined: 2013-02-25 - Christian LohmaierCommits: 1500Joined: 2008-06-01 + *Gabor KelemenCommits: 1573Joined: 2013-06-18 + + + Christian LohmaierCommits: 1559Joined: 2008-06-01 + + + Thorsten BehrensCommits: 1535Joined: 2001-04-25 *Takeshi AbeCommits: 1486Joined: 2010-11-08 + + *Matteo CasalinCommits: 1476Joined: 2011-11-13 - Thorsten BehrensCommits: 1442Joined: 2001-04-25 - - - - - *Szymon KłosCommits: 1357Joined: 2014-03-22 + *Samuel MehrbrodtCommits: 1405Joined: 2011-06-08 - *Samuel MehrbrodtCommits: 1350Joined: 2011-06-08 + *Szymon KłosCommits: 1364Joined: 2014-03-22 Fridrich ŠtrbaCommits: 1340Joined: 2007-02-22 + + Thomas Lange [tl]Commits: 1310Joined: 2000-09-22 - - Niklas NebelCommits: 1296Joined: 2000-09-19 @@ -1052,27 +1056,24 @@ *Tamás ZolnaiCommits: 1229Joined: 2012-08-06 + + *andreas kainzCommits: 1228Joined: 2015-03-18 - - Daniel Rentz [dr]Commits: 1206Joined: 2000-09-28 - *Gabor KelemenCommits: 1163Joined: 2013-06-18 + *Khaled HosnyCommits: 1132Joined: 2011-01-28 *Lionel Elie MamaneCommits: 1051Joined: 2011-01-15 - - *László NémethCommits: 1036Joined: 2010-09-29 - - *Khaled HosnyCommits: 975Joined: 2011-01-28 + *László NémethCommits: 1049Joined: 2010-09-29 *Johnny_MCommits: 968Joined: 2016-05-12 @@ -1106,57 +1107,57 @@ Sven JacobiCommits: 850Joined: 2000-09-21 - Herbert DürrCommits: 827Joined: 2000-10-17 + *Justin LuthCommits: 848Joined: 2018-04-21 - Martin GallweyCommits: 827Joined: 2000-11-08 + Herbert DürrCommits: 827Joined: 2000-10-17 - *Justin LuthCommits: 794Joined: 2018-04-21 + Martin GallweyCommits: 827Joined: 2000-11-08 Mikhail VoytenkoCommits: 793Joined: 2001-01-16 - Carsten DriesnerCommits: 748Joined: 2000-10-06 + *Heiko TietzeCommits: 759Joined: 2016-10-06 - Joachim LingnerCommits: 745Joined: 2000-10-05 + Carsten DriesnerCommits: 748Joined: 2000-10-06 + + Joachim LingnerCommits: 745Joined: 2000-10-05 + *Katarina BehrensCommits: 745Joined: 2010-10-13 *Andrzej HuntCommits: 743Joined: 2012-03-27 + + *Jim RaykowskiCommits: 742Joined: 2017-04-16 + + + Andre FischerCommits: 730Joined: 2001-02-06 Release EngineeringCommits: 728Joined: 2008-10-02 - - - - *Jim RaykowskiCommits: 719Joined: 2017-04-16 - *Zdeněk CrhonekCommits: 714Joined: 2016-05-19 - *Heiko TietzeCommits: 680Joined: 2016-10-06 - - - Joerg Skottke [jsk]Commits: 678Joined: 2008-06-17 + *Rizal MuttaqinCommits: 684Joined: 2018-05-21 - *Rizal MuttaqinCommits: 672Joined: 2018-05-21 + Joerg Skottke [jsk]Commits: 678Joined: 2008-06-17 *Joseph PowersCommits: 658Joined: 2010-10-15 @@ -1173,21 +1174,21 @@ Ingrid HalamaCommits: 639Joined: 2001-01-19 - *Justin LuthCommits: 626Joined: 2014-09-30 + *Justin LuthCommits: 627Joined: 2014-09-30 - *Seth ChaiklinCommits: 618Joined: 2019-11-13 + Rene EngelhardCommits: 619Joined: 2005-03-14 - Rene EngelhardCommits: 611Joined: 2005-03-14 + *Seth ChaiklinCommits: 619Joined: 2019-11-13 - *Rafael DominguezCommits: 606Joined: 2011-02-13 + *Adolfo Jayme BarrientosCommits: 613Joined: 2013-06-21 - *Adolfo Jayme BarrientosCommits: 590Joined: 2013-06-21 + *Rafael DominguezCommits: 606Joined: 2011-02-13 *Jochen NitschkeCommits: 587Joined: 2016-02-02 @@ -1197,6 +1198,9 @@ + + *Balazs VargaCommits: 563Joined: 2018-07-05 + Thomas Benisch [tbe]Commits: 551Joined: 2000-10-23 @@ -1204,30 +1208,38 @@ Jürgen SchmidtCommits: 512Joined: 2000-10-09 - *Peter FoleyCommits: 489Joined: 2011-09-04 - - - *jan IversenCommits: 474Joined: 2015-11-03 + *Justin LuthCommits: 495Joined: 2020-02-03 - *Jean-Pierre LedureCommits: 471Joined: 2013-10-12 + *Peter FoleyCommits: 489Joined: 2011-09-04 + + + *Jean-Pierre LedureCommits: 483Joined: 2013-10-12 + + + *jan IversenCommits: 474Joined: 2015-11-03 Andreas BregasCommits: 470Joined: 2000-09-25 + + + + *Andreas HeinischCommits: 425Joined: 2019-05-13 + *Henry CastroCommits: 417Joined: 2015-01-09 - *Justin LuthCommits: 409Joined: 2020-02-03 + *Bogdan BuzeaCommits: 413Joined: 2022-11-01 - - *Ashod NakashianCommits: 405Joined: 2015-01-07 + + *Marco CecchettiCommits: 400Joined: 2011-04-14 @@ -1235,85 +1247,74 @@ *Rafael LimaCommits: 399Joined: 2020-11-13 - *Bogdan BuzeaCommits: 394Joined: 2022-11-01 + *Arnaud VERSINICommits: 395Joined: 2010-10-05 - - Dirk VoelzkeCommits: 392Joined: 2000-11-27 - - *Arnaud VERSINICommits: 389Joined: 2010-10-05 - + + *Laurent BPCommits: 389Joined: 2011-08-31 *Ivan TimofeevCommits: 380Joined: 2011-09-16 - - Oliver-Rainer WittmannCommits: 372Joined: 2002-08-09 Martin HollmichelCommits: 371Joined: 2000-09-19 + + *Muhammet KaraCommits: 367Joined: 2016-03-20 *Pranav KantCommits: 366Joined: 2015-03-01 - - Matthias Huetsch [mhu]Commits: 360Joined: 2000-09-28 - *Andreas HeinischCommits: 353Joined: 2019-05-13 - - - *Stanislav HoracekCommits: 341Joined: 2012-12-09 - - - Patrick LubyCommits: 335Joined: 2000-09-21 + *Stanislav HoracekCommits: 342Joined: 2012-12-09 + + Patrick LubyCommits: 335Joined: 2000-09-21 + *David OstrovskyCommits: 334Joined: 2012-04-01 - *Regina HenschelCommits: 318Joined: 2010-11-04 + *Regina HenschelCommits: 322Joined: 2010-11-04 + + *Ilmari LauhakangasCommits: 316Joined: 2017-04-15 + + + Radek DoulikCommits: 305Joined: 2010-05-03 *Mark HungCommits: 305Joined: 2014-11-04 - - - - *Ilmari LauhakangasCommits: 301Joined: 2017-04-15 - *Chr. RossmanithCommits: 300Joined: 2011-01-03 - - *Balazs VargaCommits: 286Joined: 2022-06-29 - *August SodoraCommits: 285Joined: 2011-10-18 - *Vasily MelenchukCommits: 278Joined: 2015-01-27 + Bartosz KosiorekCommits: 281Joined: 2010-09-17 - Bartosz KosiorekCommits: 277Joined: 2010-09-17 + *Vasily MelenchukCommits: 278Joined: 2015-01-27 *Siqi LiuCommits: 277Joined: 2013-04-13 @@ -1326,33 +1327,33 @@ Lars LanghansCommits: 260Joined: 2000-09-22 - - *Gabor KelemenCommits: 254Joined: 2023-02-14 - Muthu SubramanianCommits: 250Joined: 2010-08-25 *Robert Antoni Buj GelonchCommits: 247Joined: 2014-06-11 + + *Dennis FrancisCommits: 227Joined: 2018-11-15 + - - *Dennis FrancisCommits: 219Joined: 2018-11-15 - *Winfried DonkersCommits: 217Joined: 2011-11-11 - *Tamas BunthCommits: 203Joined: 2016-03-08 + *Aron BudeaCommits: 208Joined: 2014-12-22 - Ingo SchmidtCommits: 202Joined: 2004-02-05 + *Pranam LashkariCommits: 207Joined: 2020-04-03 + + + *Tamas BunthCommits: 203Joined: 2016-03-08 - *Stephan BergmannCommits: 202Joined: 2025-06-18 + Ingo SchmidtCommits: 202Joined: 2004-02-05 *Arkadiy IllarionovCommits: 201Joined: 2017-01-15 @@ -1372,46 +1373,46 @@ *Marcos Paulo de SouzaCommits: 191Joined: 2012-09-26 - Giuseppe CastagnoCommits: 187Joined: 2007-12-09 + *HosseinCommits: 190Joined: 2021-06-29 - *Pranam LashkariCommits: 185Joined: 2020-04-03 + Giuseppe CastagnoCommits: 187Joined: 2007-12-09 - - *Aron BudeaCommits: 183Joined: 2014-12-22 - - - *HosseinCommits: 183Joined: 2021-06-29 - *Tünde TóthCommits: 178Joined: 2019-03-14 *François TigeotCommits: 176Joined: 2011-01-31 + + *Jonathan ClarkCommits: 176Joined: 2024-04-12 + + + *Tibor NagyCommits: 174Joined: 2020-04-01 + - - *Tibor NagyCommits: 172Joined: 2020-04-01 - *Philipp RiemerCommits: 171Joined: 2012-05-25 - *Balazs VargaCommits: 165Joined: 2018-07-05 + *Patrick LubyCommits: 169Joined: 2024-02-11 - - *Patrick LubyCommits: 161Joined: 2024-02-11 - - - *Nigel HawkinsCommits: 160Joined: 2010-10-28 - *Jonathan ClarkCommits: 154Joined: 2024-04-12 + *Karthik GodhaCommits: 159Joined: 2025-10-09 + + + + + *Dr. David Alan GilbertCommits: 153Joined: 2020-09-12 + + + *Alain RomedenneCommits: 153Joined: 2021-02-17 *Gert FallerCommits: 151Joined: 2010-10-25 @@ -1427,31 +1428,28 @@ *Sarper AkdemirCommits: 150Joined: 2020-01-26 - - *Gabor KelemenCommits: 145Joined: 2025-06-27 - Gregor Hartmann<ghCommits: 141Joined: 2000-10-12 - - *Matthias FreundCommits: 141Joined: 2013-02-08 + + *Tomáš ChvátalCommits: 140Joined: 2011-07-27 - - *Alain RomedenneCommits: 140Joined: 2021-02-17 - *Artur DryomovCommits: 137Joined: 2013-03-14 - - + + *Neil RobertsCommits: 136Joined: 2026-03-25 + *Sophia SchroederCommits: 135Joined: 2018-04-07 + + *Serge KrotCommits: 132Joined: 2015-10-25 @@ -1461,10 +1459,13 @@ *Dante DMCommits: 132Joined: 2020-06-22 + + *panoskorovesisCommits: 131Joined: 2021-06-09 + - *panoskorovesisCommits: 131Joined: 2021-06-09 + *Laurent BallandCommits: 131Joined: 2022-06-19 *Jesús CorriusCommits: 130Joined: 2010-10-07 @@ -1487,12 +1488,12 @@ *haochenCommits: 126Joined: 2013-10-10 - Takashi OnoCommits: 122Joined: 2009-12-10 + *Simon CheneryCommits: 123Joined: 2024-11-22 - *Laurent BallandCommits: 122Joined: 2022-06-19 + Takashi OnoCommits: 122Joined: 2009-12-10 *Sebastian SpaethCommits: 119Joined: 2010-09-28 @@ -1501,41 +1502,38 @@ *Douglas MenckenCommits: 119Joined: 2013-12-11 - *Dr. David Alan GilbertCommits: 119Joined: 2020-09-12 + *Alain RomedenneCommits: 117Joined: 2019-02-25 - - *Simon CheneryCommits: 119Joined: 2024-11-22 - - - *Alain RomedenneCommits: 117Joined: 2019-02-25 - Kalman Szalai - KAMICommits: 116Joined: 2010-09-14 - *Joren De CuyperCommits: 114Joined: 2013-01-07 + *Attila SzűcsCommits: 115Joined: 2020-06-29 - - - *Attila SzűcsCommits: 114Joined: 2020-06-29 + *Joren De CuyperCommits: 114Joined: 2013-01-07 *Dennis FrancisCommits: 113Joined: 2015-04-15 + + *I-Jui (Ray) SungCommits: 112Joined: 2013-09-30 *Akshay DeepCommits: 110Joined: 2016-01-23 - - + + *Sahil GautamCommits: 109Joined: 2023-07-19 + *Louis-Francis Ratté-BoulianneCommits: 102Joined: 2014-10-29 + + *Rishabh KumarCommits: 100Joined: 2015-02-13 @@ -1545,11 +1543,11 @@ *Juergen FunkCommits: 99Joined: 2014-09-17 - - *Roman KuznetsovCommits: 99Joined: 2018-10-23 + + *Paris OplopoiosCommits: 99Joined: 2021-03-07 @@ -1559,6 +1557,9 @@ *Laurent GodardCommits: 93Joined: 2011-05-06 + + *Gökay ŞatırCommits: 92Joined: 2019-12-24 + @@ -1567,17 +1568,14 @@ *Varun DhallCommits: 91Joined: 2015-03-07 - - *Thorsten BehrensCommits: 91Joined: 2020-12-19 - *Krisztian PinterCommits: 90Joined: 2013-02-18 - - *Philipp HoferCommits: 90Joined: 2020-11-06 + + *Albert ThuswaldnerCommits: 89Joined: 2011-01-26 @@ -1587,11 +1585,11 @@ *Daniel BankstonCommits: 88Joined: 2012-04-03 - - *Korrawit PruegsanusakCommits: 87Joined: 2011-05-28 + + *Adam CoCommits: 86Joined: 2013-04-28 @@ -1601,52 +1599,55 @@ *Javier FernandezCommits: 84Joined: 2013-03-06 - - Tobias KrauseCommits: 83Joined: 2007-10-02 + + *Minh NgoCommits: 83Joined: 2013-05-02 *Patrick LubyCommits: 83Joined: 2022-12-03 - - *Karthik GodhaCommits: 83Joined: 2025-10-09 - - - *Ricardo MontaniaCommits: 82Joined: 2012-08-18 *Steve FanningCommits: 78Joined: 2020-04-20 + + + + *Mohit MaratheCommits: 77Joined: 2024-03-20 + *Neil RobertsCommits: 77Joined: 2025-08-18 *Tobias MadlCommits: 74Joined: 2014-09-15 - - - - *Balazs VargaCommits: 74Joined: 2025-07-04 - *Gergo MocsiCommits: 72Joined: 2013-02-14 + + *weigaoCommits: 72Joined: 2014-05-07 Thorsten BosbachCommits: 70Joined: 2008-06-18 + + *Heiko TietzeCommits: 70Joined: 2019-09-08 + + + *Kevin SuoCommits: 69Joined: 2020-10-10 + - *Kevin SuoCommits: 69Joined: 2020-10-10 + *Jaume PujantellCommits: 69Joined: 2023-03-03 *Michaël LefèvreCommits: 68Joined: 2011-02-22 @@ -1669,27 +1670,24 @@ *Jelle van der WaaCommits: 66Joined: 2013-06-16 - *Heiko TietzeCommits: 66Joined: 2019-09-08 + *Rohan KumarCommits: 65Joined: 2016-02-23 - - *Jaume PujantellCommits: 66Joined: 2023-03-03 - - - *Rohan KumarCommits: 65Joined: 2016-02-23 - *Kohei YoshidaCommits: 65Joined: 2019-08-12 *tageziCommits: 63Joined: 2015-09-16 - - *Mohammed Abdul AzeemCommits: 63Joined: 2016-02-08 + + *WeblateCommits: 63Joined: 2023-12-13 + + + *Rosemary SebastianCommits: 62Joined: 2015-06-23 @@ -1699,64 +1697,56 @@ *Martin HoskenCommits: 61Joined: 2011-02-25 - - *Pierre-Eric Pelloux-PrayerCommits: 61Joined: 2012-06-20 - - *Michael StahlCommits: 61Joined: 2025-06-25 - + + Oliver Craemer [oc]Commits: 60Joined: 2009-10-23 *Jaskaran SinghCommits: 60Joined: 2016-02-18 - - Marc Neumann [msc]Commits: 59Joined: 2008-06-20 *shiming zhangCommits: 59Joined: 2013-11-04 + + *Simon SteinbeissCommits: 59Joined: 2015-06-01 *Ahmed ElShreifCommits: 59Joined: 2019-06-10 - - - - *WeblateCommits: 59Joined: 2023-12-13 - *yiming juCommits: 57Joined: 2013-11-01 *matteocamCommits: 56Joined: 2014-02-25 + + + + *Martin SrebotnjakCommits: 55Joined: 2010-12-19 + *Niklas JohanssonCommits: 55Joined: 2011-11-07 - - *Matthew J. FrancisCommits: 55Joined: 2014-08-25 *Paris OplopoiosCommits: 55Joined: 2022-10-17 - - *Sahil GautamCommits: 55Joined: 2024-11-20 - + + Nikolai PretzellCommits: 54Joined: 2001-03-09 - - *Mihály PalenikCommits: 54Joined: 2013-07-11 @@ -1766,11 +1756,11 @@ *Jim RaykowskiCommits: 54Joined: 2019-05-11 + + *Rob SneldersCommits: 53Joined: 2011-02-08 - - *Martin KepplingerCommits: 53Joined: 2011-02-18 @@ -1780,13 +1770,13 @@ *Lior KaplanCommits: 52Joined: 2010-10-05 - - *Efe Gürkan YALAMANCommits: 52Joined: 2012-08-01 - - *Mohit MaratheCommits: 52Joined: 2025-07-15 + *Efe Gürkan YALAMANCommits: 52Joined: 2012-08-01 + + + *Kurt NordbackCommits: 52Joined: 2025-03-05 *Will ThompsonCommits: 51Joined: 2012-03-21 @@ -1794,16 +1784,13 @@ *Faisal M. Al-OtaibiCommits: 51Joined: 2012-06-25 - - *Cao Cuong NgoCommits: 51Joined: 2013-03-04 - - *Rachit GuptaCommits: 51Joined: 2014-01-18 + *Cao Cuong NgoCommits: 51Joined: 2013-03-04 - *Martin SrebotnjakCommits: 50Joined: 2010-12-19 + *Rachit GuptaCommits: 51Joined: 2014-01-18 *Ptyl DragonCommits: 50Joined: 2013-05-09 @@ -1813,6 +1800,9 @@ + + *Dan WilliamsCommits: 49Joined: 2025-12-06 + *Marcel MetzCommits: 48Joined: 2011-12-05 @@ -1822,11 +1812,11 @@ *mingli juCommits: 48Joined: 2013-11-05 + + *Emmanuel Gil PeyrotCommits: 48Joined: 2015-11-19 - - *Marco A.G.PintoCommits: 48Joined: 2018-07-16 @@ -1836,9 +1826,6 @@ *J. Graeme LingardCommits: 47Joined: 2010-09-29 - - *Gökay ŞatırCommits: 47Joined: 2020-08-08 - @@ -1858,17 +1845,20 @@ *Mihai VargaCommits: 46Joined: 2014-02-27 + + *Armin Le Grand (collabora)Commits: 46Joined: 2025-07-07 + mb93783Commits: 45Joined: 2009-07-15 *Eilidh McAdamCommits: 45Joined: 2011-03-10 + + *Christophe JAILLETCommits: 45Joined: 2012-06-14 - - *Susobhan GhoshCommits: 45Joined: 2016-01-03 @@ -1878,11 +1868,11 @@ *Szabolcs TothCommits: 45Joined: 2019-08-07 + + Volker Ahrendt [va]Commits: 44Joined: 2002-04-15 - - *Daniel RobertsonCommits: 44Joined: 2015-06-27 @@ -1892,67 +1882,67 @@ *Philippe JungCommits: 43Joined: 2015-05-01 + + *Damjan JovanovicCommits: 43Joined: 2015-08-26 - - *Daniel Arato (NISZ)Commits: 43Joined: 2020-08-24 + + *Ujjawal KumarCommits: 43Joined: 2026-02-11 + *Peter JentschCommits: 42Joined: 2011-01-07 + + *Mark WielaardCommits: 42Joined: 2013-05-13 *Sébastien Le RayCommits: 41Joined: 2011-02-10 - - *Christian M. HellerCommits: 41Joined: 2013-02-24 *Tsutomu UchinoCommits: 41Joined: 2014-01-08 + + *Francisco SaitoCommits: 40Joined: 2011-03-21 *Grzegorz AraminowiczCommits: 40Joined: 2019-03-08 - - *Skyler GreyCommits: 40Joined: 2022-08-19 *Adam SeskunasCommits: 40Joined: 2023-08-29 + + *Kayo HamidCommits: 39Joined: 2010-10-09 *Marc-André LaverdièreCommits: 39Joined: 2011-06-21 - - *minwangCommits: 39Joined: 2013-11-04 *Valentin KettnerCommits: 38Joined: 2014-03-17 - - *Gökay ŞatırCommits: 38Joined: 2019-12-24 - + + *Shivam Kumar SinghCommits: 38Joined: 2020-01-15 - - *Stéphane GuillouCommits: 38Joined: 2023-01-03 @@ -1962,25 +1952,25 @@ *abdulmajeed ahmedCommits: 37Joined: 2012-07-07 + + *Jennifer LiebelCommits: 37Joined: 2014-08-29 - - *Ayhan YalçınsoyCommits: 37Joined: 2019-12-20 - *Samuel MehrbrodtCommits: 37Joined: 2025-07-21 + *Devansh VarshneyCommits: 37Joined: 2024-01-07 *Guillaume PousselCommits: 36Joined: 2010-12-22 + + *Radu IoanCommits: 36Joined: 2012-08-17 - - *Vinaya MandkeCommits: 36Joined: 2013-02-08 @@ -1990,11 +1980,11 @@ *Priyanka GaikwadCommits: 36Joined: 2013-11-12 + + *Ilhan YesilCommits: 36Joined: 2018-04-11 - - *Aurimas FišerasCommits: 35Joined: 2010-10-11 @@ -2004,11 +1994,11 @@ *Santiago MartinezCommits: 35Joined: 2012-01-20 + + *xukai liuCommits: 35Joined: 2013-11-01 - - *dechuangCommits: 35Joined: 2013-11-04 @@ -2018,11 +2008,11 @@ *Łukasz HryniukCommits: 35Joined: 2015-01-02 + + *Mark PageCommits: 35Joined: 2016-04-29 - - *DaeHyun SungCommits: 35Joined: 2018-05-19 @@ -2032,28 +2022,36 @@ *Andreas MantkeCommits: 34Joined: 2010-09-29 + + *Laurent AlonsoCommits: 34Joined: 2011-10-23 - - *Rodolfo Ribeiro GomesCommits: 34Joined: 2012-12-19 *Steve YinCommits: 34Joined: 2013-11-14 + + *Bayram ÇiçekCommits: 34Joined: 2023-10-17 + + + + + *Ujjawal KumarCommits: 34Joined: 2025-01-09 + *Cor NouwsCommits: 33Joined: 2011-11-19 *Yogesh BharateCommits: 33Joined: 2013-10-11 - - *Dennis RoczekCommits: 33Joined: 2015-06-09 + + *Aleksei NikiforovCommits: 33Joined: 2018-10-31 @@ -2061,27 +2059,27 @@ *Matt KCommits: 33Joined: 2021-02-26 - *Bayram ÇiçekCommits: 33Joined: 2023-10-17 - - - - - *Armin Le Grand (collabora)Commits: 33Joined: 2025-07-07 + *Moritz DugeCommits: 33Joined: 2024-04-03 *GokulCommits: 32Joined: 2012-07-10 + + *Vishv BrahmbhattCommits: 32Joined: 2013-01-28 *Arnold DumasCommits: 32Joined: 2016-02-14 - - + + *Jakub TrzebiatowskiCommits: 32Joined: 2016-03-07 + *Colomban WendlingCommits: 32Joined: 2017-03-15 + + *Dmitriy ShilinCommits: 32Joined: 2018-11-30 @@ -2091,20 +2089,9 @@ *Kurt NordbackCommits: 32Joined: 2022-05-28 - - *Patrick LubyCommits: 32Joined: 2023-11-20 - - *Moritz DugeCommits: 32Joined: 2024-04-03 - - - *Ujjawal KumarCommits: 32Joined: 2025-01-09 - - - *Sahil GautamCommits: 32Joined: 2025-06-22 - @@ -2124,17 +2111,20 @@ *Rashesh PadiaCommits: 31Joined: 2022-01-24 + + *Javiya Vivekkumar DineshbhaiCommits: 31Joined: 2023-12-10 + *Kenneth VenkenCommits: 30Joined: 2010-10-15 *Wols ListsCommits: 30Joined: 2010-11-07 + + *Christoph HerzogCommits: 30Joined: 2011-01-07 - - *Manal AlhassounCommits: 30Joined: 2012-09-10 @@ -2144,16 +2134,13 @@ *Isamu MogiCommits: 30Joined: 2013-04-27 - - *muleiCommits: 30Joined: 2013-11-01 - - *keremCommits: 30Joined: 2015-10-12 + *muleiCommits: 30Joined: 2013-11-01 - *Jakub TrzebiatowskiCommits: 30Joined: 2016-03-07 + *keremCommits: 30Joined: 2015-10-12 *Daniel SilvaCommits: 30Joined: 2017-09-24 @@ -2166,29 +2153,29 @@ *homeboy445Commits: 30Joined: 2020-12-09 - - *Javiya Vivekkumar DineshbhaiCommits: 30Joined: 2023-12-10 - *RMZeroFourCommits: 30Joined: 2024-03-17 - - *Kurt NordbackCommits: 30Joined: 2025-03-05 - - - *Harri PitkänenCommits: 29Joined: 2010-10-04 *Elton ChungCommits: 29Joined: 2012-01-31 + + *xinjiangCommits: 29Joined: 2013-11-04 *Matthias SeidelCommits: 29Joined: 2017-02-18 + + *Rafał DobrakowskiCommits: 29Joined: 2023-02-09 + + + *Manish BeraCommits: 29Joined: 2024-11-28 + @@ -2285,10 +2272,13 @@ *Leonard SasseCommits: 26Joined: 2024-03-27 - *Kurosawa TakeshiCommits: 25Joined: 2011-01-04 + *ApurvR20Commits: 26Joined: 2026-07-13 + + *Kurosawa TakeshiCommits: 25Joined: 2011-01-04 + *Tomofumi YagiCommits: 25Joined: 2011-10-20 @@ -2298,11 +2288,11 @@ *VortCommits: 25Joined: 2014-01-21 + + *aleksandar-stefanovicCommits: 25Joined: 2016-12-29 - - *George BatemanCommits: 25Joined: 2020-08-04 @@ -2312,16 +2302,13 @@ *Pedro GiffuniCommits: 24Joined: 2011-10-28 - - *Uray M. JánosCommits: 24Joined: 2012-07-17 - - *Sumit ChauhanCommits: 24Joined: 2018-12-04 + *Uray M. JánosCommits: 24Joined: 2012-07-17 - *Rafał DobrakowskiCommits: 24Joined: 2023-02-09 + *Sumit ChauhanCommits: 24Joined: 2018-12-04 *Robert RothCommits: 23Joined: 2010-10-31 @@ -2429,9 +2416,6 @@ - - *Sahil GautamCommits: 20Joined: 2023-07-19 - *prrvchrCommits: 20Joined: 2023-07-27 @@ -2441,11 +2425,11 @@ *Karthik GodhaCommits: 20Joined: 2025-03-04 - - Xiaofei ZhangCommits: 19Joined: 2010-06-28 + + *Lennard WasserthalCommits: 19Joined: 2012-08-11 @@ -2455,11 +2439,11 @@ *Sven WehnerCommits: 19Joined: 2014-01-11 - - *Ravindra VidhateCommits: 19Joined: 2014-01-30 + + *Aleksas PantechovskisCommits: 19Joined: 2016-03-03 @@ -2469,10 +2453,13 @@ *Onur YilmazCommits: 19Joined: 2019-12-18 + + *Czeber László ÁdámCommits: 19Joined: 2023-02-27 + - *Czeber László ÁdámCommits: 19Joined: 2023-02-27 + *shlok3640Commits: 19Joined: 2025-12-02 Hanno Meyer-ThurowCommits: 18Joined: 2010-09-16 @@ -2495,10 +2482,13 @@ *Federico BassiniCommits: 18Joined: 2016-10-06 - *Mert TümerCommits: 18Joined: 2018-01-08 + *Furkan Ahmet KaraCommits: 18Joined: 2017-10-21 + + *Mert TümerCommits: 18Joined: 2018-01-08 + *Zdibák ZoltánCommits: 18Joined: 2018-10-13 @@ -2508,73 +2498,70 @@ *Mark HungCommits: 18Joined: 2022-05-01 + + *Povilas KanapickasCommits: 18Joined: 2022-08-24 - - + + *Aya JamalCommits: 18Joined: 2025-12-09 + *Alfonso EusebioCommits: 17Joined: 2011-01-16 *Bálint DózsaCommits: 17Joined: 2011-02-10 + + *Olivier RCommits: 17Joined: 2011-08-01 *Jian Hong ChengCommits: 17Joined: 2012-06-26 - - *navin patidarCommits: 17Joined: 2013-01-06 *Umesh KadamCommits: 17Joined: 2014-01-10 + + *melikeyurtogluCommits: 17Joined: 2015-10-09 *Francisco Adrián SánchezCommits: 17Joined: 2016-10-07 - - *Thomas BeckCommits: 17Joined: 2017-03-27 *Kshitij PathaniaCommits: 17Joined: 2017-09-28 + + *Vikas MahatoCommits: 17Joined: 2017-12-31 *Martin van ZijlCommits: 17Joined: 2018-02-26 - - *Alain RomedenneCommits: 17Joined: 2018-12-19 *Mesut ÇifciCommits: 17Joined: 2019-12-18 + + *Bayram ÇiçekCommits: 17Joined: 2020-11-23 *Sahil GautamCommits: 17Joined: 2024-03-03 - - - - *Mohit MaratheCommits: 17Joined: 2024-03-24 - - - *shlok3640Commits: 17Joined: 2025-12-02 - Florian ReuterCommits: 16Joined: 2010-09-14 @@ -2629,19 +2616,16 @@ *Luv SharmaCommits: 16Joined: 2023-12-31 - *Devansh VarshneyCommits: 16Joined: 2024-01-07 - - - *Manish BeraCommits: 16Joined: 2024-11-28 + *sharkCommits: 16Joined: 2026-01-12 Octavio AlvarezCommits: 15Joined: 2010-09-13 - - *Luke SymesCommits: 15Joined: 2010-10-01 + + *Povilas KanapickasCommits: 15Joined: 2010-10-18 @@ -2651,11 +2635,11 @@ *Yifan JCommits: 15Joined: 2010-12-16 - - *Cosimo CecchiCommits: 15Joined: 2011-11-02 + + *Alexander BergmannCommits: 15Joined: 2012-01-13 @@ -2665,11 +2649,11 @@ *Nikhil WalvekarCommits: 15Joined: 2013-11-01 - - *Alex HenrieCommits: 15Joined: 2014-03-05 + + *Heena GuptaCommits: 15Joined: 2014-06-17 @@ -2679,11 +2663,11 @@ *Andreas BrandnerCommits: 15Joined: 2017-09-04 - - *Armin Le GrandCommits: 15Joined: 2018-02-15 + + *Stéphane GuillouCommits: 15Joined: 2021-01-22 @@ -2691,40 +2675,57 @@ *Ross JohnsonCommits: 15Joined: 2021-09-13 - *LeMoyne CastleCommits: 14Joined: 2010-10-25 + *Irgaliev AminCommits: 15Joined: 2023-05-03 + + + *David HasheCommits: 15Joined: 2025-01-15 + + *Vissarion FisikopoulosCommits: 15Joined: 2026-04-29 + + + *LeMoyne CastleCommits: 14Joined: 2010-10-25 + *Tim HardeckCommits: 14Joined: 2011-11-03 *Björgvin RagnarssonCommits: 14Joined: 2012-02-13 + + *Zhe WangCommits: 14Joined: 2012-06-20 *Sun YingCommits: 14Joined: 2012-08-16 - - *Juan PiccaCommits: 14Joined: 2014-07-23 *Zsolt BölönyCommits: 14Joined: 2015-01-10 + + *Gökhan GurbetoğluCommits: 14Joined: 2016-06-06 *Nickson ThandaCommits: 14Joined: 2018-03-25 + + *Méven CarCommits: 14Joined: 2024-01-09 + + + *Jesus SolisCommits: 14Joined: 2025-03-27 + - *Dan WilliamsCommits: 14Joined: 2025-12-06 + *Asim RazaCommits: 14Joined: 2026-04-25 *Prashant ShahCommits: 13Joined: 2010-10-10 @@ -2782,19 +2783,19 @@ *Shantanu OakCommits: 13Joined: 2025-01-05 - - *David HasheCommits: 13Joined: 2025-01-15 - *Parth RaiyaniCommits: 13Joined: 2025-04-02 *siddhisalunkhe1998Commits: 13Joined: 2025-10-13 + + *Ethan GarciaCommits: 13Joined: 2026-03-10 + - *sharkCommits: 13Joined: 2026-01-12 + *Ben UrbanCommits: 13Joined: 2026-06-03 *Jani MonosesCommits: 12Joined: 2010-10-30 @@ -2866,17 +2867,20 @@ *Silvery FreakzCommits: 12Joined: 2025-10-16 + + *Daniel LeeCommits: 12Joined: 2025-10-27 + Mox SoiniCommits: 11Joined: 2008-04-04 Frank PetersCommits: 11Joined: 2010-05-20 + + *Jonas Finnemann JensenCommits: 11Joined: 2010-10-01 - - *René KjellerupCommits: 11Joined: 2010-10-14 @@ -2886,11 +2890,11 @@ *David BolenCommits: 11Joined: 2012-03-07 + + *Jung-uk KimCommits: 11Joined: 2012-08-13 - - *Enrico Weigelt, metux ITSCommits: 11Joined: 2012-11-14 @@ -2900,11 +2904,11 @@ *Sean YoungCommits: 11Joined: 2013-05-16 + + *Krunoslav ŠebetićCommits: 11Joined: 2013-07-18 - - *Charu TyagiCommits: 11Joined: 2014-06-25 @@ -2914,11 +2918,11 @@ *Jun NogataCommits: 11Joined: 2015-01-07 + + *Phillip SzCommits: 11Joined: 2015-03-16 - - *nadithCommits: 11Joined: 2016-07-14 @@ -2928,11 +2932,11 @@ *Fakabbir AminCommits: 11Joined: 2017-01-29 + + *jmzambonCommits: 11Joined: 2017-05-19 - - *Manuj VashistCommits: 11Joined: 2017-12-10 @@ -2942,11 +2946,11 @@ *Abhyudaya SharmaCommits: 11Joined: 2018-03-19 + + *Daniel LohmannCommits: 11Joined: 2019-12-18 - - *Srijan BhatiaCommits: 11Joined: 2020-05-30 @@ -2956,11 +2960,11 @@ *shubham656Commits: 11Joined: 2020-11-07 + + *AnshuCommits: 11Joined: 2020-11-09 - - *Jeff HuangCommits: 11Joined: 2021-04-12 @@ -2970,9 +2974,6 @@ *Patrick LubyCommits: 11Joined: 2023-02-28 - - *Irgaliev AminCommits: 11Joined: 2023-05-03 - @@ -2981,17 +2982,14 @@ *Akshay Kumar DubeyCommits: 11Joined: 2025-01-10 - - *Daniel LeeCommits: 11Joined: 2025-10-27 - *Timo HeinoCommits: 10Joined: 2010-11-22 - - *Luke PetrolekasCommits: 10Joined: 2011-02-12 + + *Theo van KlaverenCommits: 10Joined: 2011-03-10 @@ -3001,11 +2999,11 @@ *Kristian RietveldCommits: 10Joined: 2011-10-15 - - *David VogtCommits: 10Joined: 2012-02-05 + + *Jianyuan LiCommits: 10Joined: 2012-08-16 @@ -3015,11 +3013,11 @@ *Benjamin NiCommits: 10Joined: 2015-04-02 - - *Arul MichaelCommits: 10Joined: 2016-01-05 + + *Chirag ManwaniCommits: 10Joined: 2016-02-16 @@ -3029,11 +3027,11 @@ *Kiyotaka NishiboriCommits: 10Joined: 2017-08-27 - - *Rahul GurungCommits: 10Joined: 2018-08-26 + + *Mark RobbinsonCommits: 10Joined: 2019-01-02 @@ -3043,11 +3041,11 @@ *Jussi PakkanenCommits: 10Joined: 2020-02-22 - - *Michael WarnerCommits: 10Joined: 2020-05-24 + + *tusharCommits: 10Joined: 2021-01-10 @@ -3057,11 +3055,11 @@ *Balazs SanthaCommits: 10Joined: 2021-02-26 - - *GaldamCommits: 10Joined: 2022-09-07 + + *Theppitak KaroonboonyananCommits: 10Joined: 2022-11-25 @@ -3071,263 +3069,291 @@ *Marc MondesirCommits: 10Joined: 2024-09-18 + + *Alin Andrei AbahnenceiCommits: 10Joined: 2024-11-27 + - *Alin Andrei AbahnenceiCommits: 10Joined: 2024-11-27 + *Jan RheinländerCommits: 10Joined: 2025-01-18 + + + *Aryan MishraCommits: 10Joined: 2026-03-18 + + + *Muhammad NaeemCommits: 10Joined: 2026-04-26 *Mattias JohnssonCommits: 9Joined: 2010-10-18 + + *Surendran MahendranCommits: 9Joined: 2010-11-05 *Steven ButlerCommits: 9Joined: 2011-01-07 - - *Robinson TryonCommits: 9Joined: 2012-06-21 *Mihkel TõnnovCommits: 9Joined: 2012-07-02 + + *Michael DunphyCommits: 9Joined: 2013-04-18 *Dinesh PatilCommits: 9Joined: 2014-03-12 - - *Matthew PottageCommits: 9Joined: 2014-07-26 *Deena FrancisCommits: 9Joined: 2014-07-29 + + *Ryan McCoskrieCommits: 9Joined: 2014-09-14 *Aybuke OzdemirCommits: 9Joined: 2015-10-07 - - *skswalesCommits: 9Joined: 2016-05-06 *apurvapriyadarshiCommits: 9Joined: 2016-05-27 + + *pv2kCommits: 9Joined: 2016-11-28 *Adam KovacsCommits: 9Joined: 2018-08-16 - - *Scott ClarkeCommits: 9Joined: 2019-06-07 *Canberk TURANCommits: 9Joined: 2020-01-25 + + *Chris MayoCommits: 9Joined: 2020-05-08 *Pedro Pinto SilvaCommits: 9Joined: 2020-06-16 - - *Venetia FurtadoCommits: 9Joined: 2023-06-16 - *Méven CarCommits: 9Joined: 2024-01-09 + *Patrick LubyCommits: 9Joined: 2024-02-18 + + *kubakCommits: 9Joined: 2024-04-23 *Deepanshu SharmaCommits: 9Joined: 2024-08-08 - - *Juraj ŠarinayCommits: 9Joined: 2025-01-16 *Devashish GuptaCommits: 9Joined: 2025-03-19 + + *ManishCommits: 9Joined: 2025-03-26 + + *Sergey AnisimovCommits: 9Joined: 2025-10-03 + *Okhuomon AjayiCommits: 9Joined: 2025-10-20 + + *Saburo YoshidaCommits: 9Joined: 2025-11-20 + + + *Swarnadeep PaulCommits: 9Joined: 2026-01-24 + + + *AsmatZahra-codeCommits: 9Joined: 2026-04-29 + Fong LinCommits: 8Joined: 2010-09-14 Jody GoldbergCommits: 8Joined: 2010-09-15 + + *Michael CallahanCommits: 8Joined: 2010-12-06 *Robert DargaudCommits: 8Joined: 2011-04-12 - - *Jenei GáborCommits: 8Joined: 2011-07-29 *Terrence EngerCommits: 8Joined: 2011-10-27 + + *Daisuke NishinoCommits: 8Joined: 2011-11-06 *Tomcsik BenceCommits: 8Joined: 2012-01-14 - - *Jonathan AdamsCommits: 8Joined: 2012-03-16 *Norah A. AbanumayCommits: 8Joined: 2012-07-30 + + *Jean-Tiare Le BigotCommits: 8Joined: 2012-08-08 *Timothy PearsonCommits: 8Joined: 2012-08-18 - - *Ahmad H. Al HarthiCommits: 8Joined: 2012-12-31 *karthCommits: 8Joined: 2013-01-07 + + *Ádám Csaba KirályCommits: 8Joined: 2013-02-28 *Brian FraserCommits: 8Joined: 2013-09-03 - - *RajashriCommits: 8Joined: 2013-12-06 *Keith CurtisCommits: 8Joined: 2013-12-20 + + *SouravCommits: 8Joined: 2014-03-15 *Thomas ViehmannCommits: 8Joined: 2014-08-15 - - *Nathan YeeCommits: 8Joined: 2015-01-01 *Ursache VladimirCommits: 8Joined: 2015-02-10 + + *Sean DavisCommits: 8Joined: 2015-06-01 *HeiherCommits: 8Joined: 2015-07-07 - - *IanCommits: 8Joined: 2015-08-06 *Matus UzakCommits: 8Joined: 2016-02-22 + + *Christian BarthCommits: 8Joined: 2017-06-25 *ShinnokCommits: 8Joined: 2017-09-06 - - *Guilhem MoulinCommits: 8Joined: 2018-02-05 *Alain RomedenneCommits: 8Joined: 2018-11-29 + + *Rasmus JonssonCommits: 8Joined: 2019-03-20 *Artur NeumannCommits: 8Joined: 2019-06-11 - - *Gabriel MaseiCommits: 8Joined: 2020-09-02 *Ouyang LeyanCommits: 8Joined: 2020-09-06 + + *diwanshu885Commits: 8Joined: 2020-10-30 *Gökhan ÖzeloğluCommits: 8Joined: 2020-11-21 - - *Balaharipreetha MuthuCommits: 8Joined: 2020-12-04 *4k5h1tCommits: 8Joined: 2021-08-26 + + *Juan C. SanzCommits: 8Joined: 2021-09-03 *Dhiraj HoldenCommits: 8Joined: 2021-11-30 - - *jsalaCommits: 8Joined: 2022-06-19 - - *Patrick LubyCommits: 8Joined: 2024-02-18 - *Shardul Vikram SinghCommits: 8Joined: 2024-12-29 - - *Aya JamalCommits: 8Joined: 2025-12-09 - - *Swarnadeep PaulCommits: 8Joined: 2026-01-24 + *Sampath-1984Commits: 8Joined: 2025-10-27 + + *Jan LuethiCommits: 8Joined: 2026-02-21 + + + *Paolo BenvenutoCommits: 8Joined: 2026-02-23 + + + *Parag NemadeCommits: 8Joined: 2026-06-09 + + + *Thies PierdolaCommits: 7Joined: 2011-01-28 @@ -3337,11 +3363,11 @@ *Samuel CantrellCommits: 7Joined: 2011-06-11 - - *Alex McMurchy1917Commits: 7Joined: 2011-08-14 + + *Christoph LutzCommits: 7Joined: 2011-09-06 @@ -3351,11 +3377,11 @@ *Gert van ValkenhoefCommits: 7Joined: 2012-02-14 - - *Brennan VincentCommits: 7Joined: 2012-04-02 + + *Wang LeiCommits: 7Joined: 2012-06-14 @@ -3365,11 +3391,11 @@ *Christopher CopitsCommits: 7Joined: 2012-09-19 - - *Mathias MichelCommits: 7Joined: 2012-11-19 + + *Eric SeynaeveCommits: 7Joined: 2013-02-04 @@ -3379,11 +3405,11 @@ *Roi IllouzCommits: 7Joined: 2013-10-20 - - *Stefan RingCommits: 7Joined: 2014-01-09 + + *Trent MacAlpineCommits: 7Joined: 2014-03-06 @@ -3393,11 +3419,11 @@ *Giuseppe BilottaCommits: 7Joined: 2014-09-09 - - *V Stuart FooteCommits: 7Joined: 2014-12-04 + + *RaalCommits: 7Joined: 2014-12-31 @@ -3407,11 +3433,11 @@ *Feyza YavuzCommits: 7Joined: 2015-10-04 - - *iremCommits: 7Joined: 2015-10-11 + + *slackaCommits: 7Joined: 2016-07-30 @@ -3421,81 +3447,95 @@ *Tiago SantosCommits: 7Joined: 2016-08-12 - - *HieronymousCommits: 7Joined: 2016-10-13 + + *Ulrich GemkowCommits: 7Joined: 2016-10-27 *Marina LatiniCommits: 7Joined: 2016-11-10 - - *Furkan Ahmet KaraCommits: 7Joined: 2017-10-21 - - - *Vincas DargisCommits: 7Joined: 2018-01-21 *Hamish McIntyre-BhattyCommits: 7Joined: 2018-10-10 + + *BugraCommits: 7Joined: 2020-01-30 *Ahmet Hakan ÇelikCommits: 7Joined: 2021-03-07 - - - - *Gökay ŞatırCommits: 7Joined: 2021-03-14 - *BaiXiaochunCommits: 7Joined: 2021-06-27 *Pragat PandyaCommits: 7Joined: 2022-02-01 + + *Liu HaoCommits: 7Joined: 2022-08-14 - - *Juan c. SanzCommits: 7Joined: 2023-03-06 + + *Mihai VasiliuCommits: 7Joined: 2023-09-21 + *Ankit_JaipuriarCommits: 7Joined: 2023-09-22 + + *Zainab AbbasiCommits: 7Joined: 2024-04-10 *HakimOtteyCommits: 7Joined: 2024-04-13 - - *Adesola SamuelCommits: 7Joined: 2024-10-14 *kkasliwalCommits: 7Joined: 2024-12-21 + + *Nam BuiCommits: 7Joined: 2025-03-07 - *Jesus SolisCommits: 7Joined: 2025-03-27 + *Aleksi KallioCommits: 7Joined: 2025-05-21 + + + *Jason WhitmoreCommits: 7Joined: 2025-08-13 + + + *Mo AmrCommits: 7Joined: 2026-02-12 - *Sergey AnisimovCommits: 7Joined: 2025-10-03 + *madhuraCommits: 7Joined: 2026-02-19 + + *Aristeidis PalamarasCommits: 7Joined: 2026-03-23 + + + *Asad TauqeerCommits: 7Joined: 2026-04-26 + + + *alohapeakinaCommits: 7Joined: 2026-05-13 + + + *Phil BordelonCommits: 6Joined: 2010-09-30 @@ -3505,11 +3545,11 @@ *Alexander O. AnisimovCommits: 6Joined: 2010-11-06 - - *Daniel Di MarcoCommits: 6Joined: 2010-11-15 + + *shiraharaCommits: 6Joined: 2011-01-28 @@ -3519,11 +3559,11 @@ *Anurag JainCommits: 6Joined: 2011-04-05 - - *Thomas CollertonCommits: 6Joined: 2011-11-18 + + *Joan MontanéCommits: 6Joined: 2013-02-22 @@ -3533,11 +3573,11 @@ *Anurag KanungoCommits: 6Joined: 2013-04-19 - - *tianyaoCommits: 6Joined: 2013-11-09 + + *Jeroen NijhofCommits: 6Joined: 2014-05-01 @@ -3547,11 +3587,11 @@ *Michel RenonCommits: 6Joined: 2015-05-19 - - *Fabio BusoCommits: 6Joined: 2015-11-01 + + *Sedat AkCommits: 6Joined: 2015-11-08 @@ -3561,11 +3601,11 @@ *Ricardo PalomaresCommits: 6Joined: 2016-01-16 - - *baltasarqCommits: 6Joined: 2016-02-24 + + *Steven GuoCommits: 6Joined: 2016-03-02 @@ -3575,11 +3615,11 @@ *RosenCommits: 6Joined: 2016-08-04 - - *giaccoCommits: 6Joined: 2016-10-11 + + *abdulwdCommits: 6Joined: 2016-12-22 @@ -3589,10 +3629,13 @@ *Jean-Sebastien BevilacquaCommits: 6Joined: 2017-02-09 + + *udareechkCommits: 6Joined: 2017-09-20 + - *udareechkCommits: 6Joined: 2017-09-20 + *Franklin WengCommits: 6Joined: 2018-02-28 *Kemal AyhanCommits: 6Joined: 2019-12-18 @@ -3629,15 +3672,15 @@ *Leonid RyzhovCommits: 6Joined: 2022-11-17 - *Luigi IucciCommits: 6Joined: 2023-05-17 + *Đoàn Trần Công DanhCommits: 6Joined: 2022-11-27 - *Yli875Commits: 6Joined: 2023-08-29 + *Luigi IucciCommits: 6Joined: 2023-05-17 - *Mihai VasiliuCommits: 6Joined: 2023-09-21 + *Yli875Commits: 6Joined: 2023-08-29 *AkshayWarrierCommits: 6Joined: 2024-01-19 @@ -3664,20 +3707,31 @@ *Vaibhav SinghCommits: 6Joined: 2025-09-04 - - *Sampath-1984Commits: 6Joined: 2025-10-27 - *AnamayNarkarCommits: 6Joined: 2026-01-12 - *Gil ForcadaCommits: 5Joined: 2010-09-28 + *s-AustinAveryCommits: 6Joined: 2026-03-20 + + + *Mehul SharmaCommits: 6Joined: 2026-03-24 + + *Jakub TrzebiatowskiCommits: 6Joined: 2026-04-05 + + + *Brian YoonCommits: 6Joined: 2026-05-13 + + + *Gil ForcadaCommits: 5Joined: 2010-09-28 + *David HobleyCommits: 5Joined: 2010-10-04 + + *Bernhard RosenkraenzerCommits: 5Joined: 2010-11-01 @@ -3687,11 +3741,11 @@ *Tobias RosenbergerCommits: 5Joined: 2011-01-31 - - *Jeffrey ChangCommits: 5Joined: 2011-06-01 + + *ericb2Commits: 5Joined: 2011-10-30 @@ -3701,11 +3755,11 @@ *Gustavo Buzzatti PachecoCommits: 5Joined: 2011-12-15 - - *Wei Ming KhooCommits: 5Joined: 2012-02-17 + + *Lionel DricotCommits: 5Joined: 2012-06-04 @@ -3715,11 +3769,11 @@ *Bence BabatiCommits: 5Joined: 2012-08-13 - - *Pavel JaníkCommits: 5Joined: 2012-11-29 + + *Werner KoernerCommits: 5Joined: 2012-12-11 @@ -3729,11 +3783,11 @@ *Miguel GomezCommits: 5Joined: 2013-04-02 - - *pje335_NLCommits: 5Joined: 2013-05-10 + + *Ciorba EdmondCommits: 5Joined: 2013-06-11 @@ -3743,11 +3797,11 @@ *MÁTÉ GergelyCommits: 5Joined: 2013-07-19 - - *Timothy MarkleCommits: 5Joined: 2014-01-31 + + *Jan KantertCommits: 5Joined: 2014-06-12 @@ -3757,11 +3811,11 @@ *Berk GurekenCommits: 5Joined: 2015-10-01 - - *dtmCommits: 5Joined: 2016-02-11 + + *Yossi ZahnCommits: 5Joined: 2016-11-25 @@ -3771,106 +3825,98 @@ *Huzaifa IftikharCommits: 5Joined: 2016-12-19 - - *tamsil1amani3Commits: 5Joined: 2016-12-22 + + *Lukas RöllinCommits: 5Joined: 2017-02-06 *Paul MenzelCommits: 5Joined: 2017-05-17 - - *Franklin WengCommits: 5Joined: 2018-02-28 - - - *Corentin NoëlCommits: 5Joined: 2019-09-20 *Tolunay DündarCommits: 5Joined: 2019-12-18 + + *Eda Nur VarCommits: 5Joined: 2020-01-25 *Yukio SiraichiCommits: 5Joined: 2020-03-09 - - *Oleg ShchelykalnovCommits: 5Joined: 2020-03-28 *Tomofumi YagiCommits: 5Joined: 2020-09-12 + + *Umut Emre BayramogluCommits: 5Joined: 2020-11-21 *Georgy LitvinovCommits: 5Joined: 2020-12-16 - - *Suhaas JoshiCommits: 5Joined: 2021-01-04 *Batmunkh DorjgotovCommits: 5Joined: 2021-04-27 + + *Baran AytasCommits: 5Joined: 2021-08-22 *Ismael LucenoCommits: 5Joined: 2021-09-29 - - *flywireCommits: 5Joined: 2021-11-12 *zhutyraCommits: 5Joined: 2022-02-01 + + *Deep17Commits: 5Joined: 2022-02-20 *Siddhant ChaudharyCommits: 5Joined: 2022-03-11 - - *Skyler GreyCommits: 5Joined: 2022-07-27 *Sam JamesCommits: 5Joined: 2022-09-02 + + *SatyaCommits: 5Joined: 2022-09-05 *Andrea RosettiCommits: 5Joined: 2022-09-15 - - - - *Đoàn Trần Công DanhCommits: 5Joined: 2022-11-27 - *ektagoel12Commits: 5Joined: 2023-01-19 *Bayram ÇiçekCommits: 5Joined: 2023-03-09 + + *khushishikhuCommits: 5Joined: 2023-10-13 - - *Eli SchwartzCommits: 5Joined: 2023-12-13 @@ -3880,11 +3926,11 @@ *Keldin Maldonado (KNM)Commits: 5Joined: 2024-01-29 + + *Sujatro BhadraCommits: 5Joined: 2024-03-04 - - *Aaron BourdeauxCommits: 5Joined: 2024-03-25 @@ -3894,13 +3940,13 @@ *RoshCommits: 5Joined: 2024-11-04 - - *Johann LORBERCommits: 5Joined: 2024-12-04 - - *Saburo YoshidaCommits: 5Joined: 2025-11-20 + *Johann LORBERCommits: 5Joined: 2024-12-04 + + + *Dan WilliamsCommits: 5Joined: 2025-09-16 *DanielCommits: 5Joined: 2025-11-21 @@ -3908,339 +3954,350 @@ *seyoufi22Commits: 5Joined: 2025-11-24 + + + + *Chiggy WiggyCommits: 5Joined: 2025-12-05 + *RHUSHYA.K.CCommits: 5Joined: 2026-02-09 + + *Liam ConnorsCommits: 5Joined: 2026-03-09 + + + *Rashmi RashmiCommits: 5Joined: 2026-03-13 + - *Mo AmrCommits: 5Joined: 2026-02-12 + *Nguyen Minh TienCommits: 5Joined: 2026-03-17 - *madhuraCommits: 5Joined: 2026-02-19 + *David RosenfeldCommits: 5Joined: 2026-03-25 + + *Brandon NhepCommits: 5Joined: 2026-05-28 + + + *MariosCommits: 5Joined: 2026-07-16 + + + *Florian BircherCommits: 4Joined: 2010-10-16 *Andrew C. E. DentCommits: 4Joined: 2010-10-24 - - *Santiago AlessandriCommits: 4Joined: 2010-11-11 *Maja DjordjevicCommits: 4Joined: 2011-01-06 + + *An LeendersCommits: 4Joined: 2011-01-25 *Alexander ThurgoodCommits: 4Joined: 2011-01-26 - - *ClioCommits: 4Joined: 2011-01-30 *Michael MuenchCommits: 4Joined: 2011-02-13 + + *Pantelis KoukousoulasCommits: 4Joined: 2011-03-14 *Samphan RaruenromCommits: 4Joined: 2011-03-24 - - *Andreas BeckerCommits: 4Joined: 2011-04-04 *Roland BaudinCommits: 4Joined: 2011-05-16 + + *André SchnabelCommits: 4Joined: 2011-05-31 *Tom TromeyCommits: 4Joined: 2011-08-11 - - *Wolfgang PechlanerCommits: 4Joined: 2011-09-04 *Cheng-Chia TsengCommits: 4Joined: 2012-01-16 + + *Kate GossCommits: 4Joined: 2012-02-11 *Mariana MarasoiuCommits: 4Joined: 2012-03-14 - - *Yong Lin MaCommits: 4Joined: 2012-06-07 *Raimundo MouraCommits: 4Joined: 2012-06-16 + + *Florian ReisingerCommits: 4Joined: 2012-06-22 *Nicholas ShanksCommits: 4Joined: 2012-09-04 - - *tinoCommits: 4Joined: 2012-12-03 *XiaoliCommits: 4Joined: 2013-03-23 + + *Sameer DeshmukhCommits: 4Joined: 2013-04-20 *Zheng FanCommits: 4Joined: 2013-04-22 - - *Elie RouxCommits: 4Joined: 2013-05-29 *Nourah.AlShoeibiCommits: 4Joined: 2013-07-07 + + *Honza HavlíčekCommits: 4Joined: 2013-07-27 *Andrea PescettiCommits: 4Joined: 2013-10-07 - - *Robert CampbellCommits: 4Joined: 2013-11-13 *Ulrich KitzingerCommits: 4Joined: 2013-11-30 + + *Ken BiondiCommits: 4Joined: 2014-03-05 *Jeffrey StedfastCommits: 4Joined: 2014-07-26 - - *Simon DannerCommits: 4Joined: 2014-08-02 *Kevin SuoCommits: 4Joined: 2014-11-06 + + *Aleksandr AndreevCommits: 4Joined: 2015-04-20 *Derrick RochaCommits: 4Joined: 2015-08-26 - - *Sahasranaman M SCommits: 4Joined: 2015-10-04 *ccshellerCommits: 4Joined: 2015-10-08 + + *pasqual milvaquesCommits: 4Joined: 2015-12-02 *aqcoderCommits: 4Joined: 2015-12-13 - - *Burcin AkalinCommits: 4Joined: 2015-12-18 *Kumar ThangavelCommits: 4Joined: 2016-01-04 + + *erdemdemirkapiCommits: 4Joined: 2016-01-30 *coypuCommits: 4Joined: 2016-02-03 - - *Tim EvesCommits: 4Joined: 2016-02-23 *GurkaranCommits: 4Joined: 2016-03-17 + + *Fabio BiocchettiCommits: 4Joined: 2016-10-21 *Gaurav DhingraCommits: 4Joined: 2016-12-03 - - *Patrick JaapCommits: 4Joined: 2017-01-30 *Piotr DrągCommits: 4Joined: 2017-03-05 + + *Fyodor YemelyanenkoCommits: 4Joined: 2017-08-21 *Olivier TilloyCommits: 4Joined: 2018-01-08 - - *Jon NermutCommits: 4Joined: 2018-01-20 *Jozsef SzakacsCommits: 4Joined: 2018-11-07 + + *Andrew UdvareCommits: 4Joined: 2019-01-08 *Aleyna DoğrucanCommits: 4Joined: 2019-12-28 - - *Efdal İncesuCommits: 4Joined: 2020-01-25 *Faruk DemirbaşCommits: 4Joined: 2020-01-25 + + *Hakan BakacakCommits: 4Joined: 2020-01-26 *Burak BalaCommits: 4Joined: 2020-01-26 - - *Mohamed SamehCommits: 4Joined: 2020-02-11 *Fred KruseCommits: 4Joined: 2020-03-02 + + *Deb Barkley-YeungCommits: 4Joined: 2020-08-19 *Gokce KulerCommits: 4Joined: 2020-10-20 - - *VishwasCommits: 4Joined: 2020-12-31 *Aditya Pratap SinghCommits: 4Joined: 2021-02-01 + + *dipanshu124Commits: 4Joined: 2021-02-12 *HosseinCommits: 4Joined: 2021-03-23 - - *tobiasCommits: 4Joined: 2021-06-03 *Gopi Krishna MenonCommits: 4Joined: 2021-06-07 + + *Harshita NagCommits: 4Joined: 2021-06-25 *YildirayCommits: 4Joined: 2021-08-08 - - *ehsanCommits: 4Joined: 2022-07-01 *PoonamShokeenCommits: 4Joined: 2022-07-21 + + *Sebastian Andrzej SiewiorCommits: 4Joined: 2023-01-24 *RasenkaiCommits: 4Joined: 2023-01-27 - - *Adoche OnajiCommits: 4Joined: 2023-01-30 *nirnayCommits: 4Joined: 2023-02-25 + + *Arvind KCommits: 4Joined: 2023-03-02 *Yousef_RabiaCommits: 4Joined: 2023-03-07 - - *Dan HorákCommits: 4Joined: 2023-09-01 *Jeff HuangCommits: 4Joined: 2023-11-07 + + *seturajCommits: 4Joined: 2024-01-21 *Tuukka OravaCommits: 4Joined: 2024-02-05 - - *U-AMANDAQUARESMA\quareCommits: 4Joined: 2024-04-01 *Printf DebuggingCommits: 4Joined: 2024-04-05 + + *افشین ‌Commits: 4Joined: 2025-02-02 *Ahmed KhaledCommits: 4Joined: 2025-03-12 - - - - *Jason WhitmoreCommits: 4Joined: 2025-08-13 - - - *Dan WilliamsCommits: 4Joined: 2025-09-16 - *Akaki DzidziguriCommits: 4Joined: 2025-11-20 @@ -4256,422 +4313,433 @@ *MeloveCommits: 4Joined: 2026-01-27 - *Paolo BenvenutoCommits: 4Joined: 2026-02-23 + *ChrisCommits: 4Joined: 2026-03-08 - *ChrisCommits: 4Joined: 2026-03-08 + *Krunal BaraskarCommits: 4Joined: 2026-03-12 - *Ethan GarciaCommits: 4Joined: 2026-03-10 + *Neil S PatelCommits: 4Joined: 2026-03-16 + + + *Muhammad AmmarCommits: 4Joined: 2026-04-25 + + + *Tulio MacedoCommits: 4Joined: 2026-08-06 Keith StribleyCommits: 3Joined: 2010-06-29 + + *Jacopo NespoloCommits: 3Joined: 2010-10-01 *Alan DuCommits: 3Joined: 2010-10-12 - - *Gioele BarabucciCommits: 3Joined: 2010-11-18 *Xuacu SaturioCommits: 3Joined: 2010-12-19 + + *Pascal UllrichCommits: 3Joined: 2010-12-28 *Jonathan AquilinaCommits: 3Joined: 2011-01-18 - - *Michael KochCommits: 3Joined: 2011-01-21 *Jan DarmochwalCommits: 3Joined: 2011-01-27 + + *Chris Carpenter(mordocai)Commits: 3Joined: 2011-02-02 *Tantai TanakanokCommits: 3Joined: 2011-02-09 - - *David NalleyCommits: 3Joined: 2011-03-03 *Guto MaiaCommits: 3Joined: 2011-03-18 + + *Anthony DurityCommits: 3Joined: 2011-04-18 *Dimitri DucCommits: 3Joined: 2011-04-19 - - *Mike EberdtCommits: 3Joined: 2011-07-12 *Florian Allmann-RahnCommits: 3Joined: 2011-08-22 + + *Dmitry AshkadovCommits: 3Joined: 2011-08-29 *Michael BauerCommits: 3Joined: 2011-11-23 - - *Sérgio MarquesCommits: 3Joined: 2011-11-25 *Stefan HeinemannCommits: 3Joined: 2012-02-16 + + *Cameron PaulCommits: 3Joined: 2012-02-27 *Tom ThorogoodCommits: 3Joined: 2012-02-28 - - *Stephan van den AkkerCommits: 3Joined: 2012-06-07 *Benjamin DrungCommits: 3Joined: 2012-06-08 + + *Mathieu VonlanthenCommits: 3Joined: 2012-07-19 *Bertrand LorentzCommits: 3Joined: 2012-08-03 - - *Oliver GüntherCommits: 3Joined: 2012-08-09 *Istvan TuriCommits: 3Joined: 2012-08-16 + + *Jeremy BrownCommits: 3Joined: 2012-09-19 *Peter BaumgartenCommits: 3Joined: 2012-11-24 - - *Markus MaierCommits: 3Joined: 2012-11-25 *Marina PlakalovicCommits: 3Joined: 2012-12-14 + + *Dávid VastagCommits: 3Joined: 2013-02-04 *Stefan SchickCommits: 3Joined: 2013-02-18 - - *Petr KrausCommits: 3Joined: 2013-03-26 *Golnaz IrannejadCommits: 3Joined: 2013-04-02 + + *vjinochCommits: 3Joined: 2013-04-09 *Jason HulmeCommits: 3Joined: 2013-06-05 - - *Nagy AkosCommits: 3Joined: 2013-06-27 *Gabriele BulfonCommits: 3Joined: 2013-07-05 + + *Haidong LianCommits: 3Joined: 2013-07-24 *Tobias MuellerCommits: 3Joined: 2014-02-10 - - *Peter Senna TschudinCommits: 3Joined: 2014-05-26 *Brij Mohan Lal SrivastavaCommits: 3Joined: 2014-11-12 + + *Renato FerreiraCommits: 3Joined: 2014-11-15 *Popa Adrian MariusCommits: 3Joined: 2015-03-23 - - *Matthew NichollsCommits: 3Joined: 2015-04-01 *Linus BehrensCommits: 3Joined: 2015-04-23 + + *Marek DoleželCommits: 3Joined: 2015-07-06 *Simon LongCommits: 3Joined: 2015-07-08 - - *Lucas SatabinCommits: 3Joined: 2015-08-25 *n.r.pearsonCommits: 3Joined: 2015-09-09 + + *Sergey FukanchikCommits: 3Joined: 2015-09-17 *AlexFCommits: 3Joined: 2015-11-12 - - *Giovanni CaligarisCommits: 3Joined: 2015-11-30 *Mayank GuptaCommits: 3Joined: 2016-03-11 + + *Johannes BergCommits: 3Joined: 2016-08-03 *drazilCommits: 3Joined: 2016-08-27 - - *Jacek FraczekCommits: 3Joined: 2016-10-05 *liongoldCommits: 3Joined: 2016-11-21 + + *John Paul Adrian GlaubitzCommits: 3Joined: 2016-11-27 *bansan85Commits: 3Joined: 2016-12-21 - - *Dimitri BouronCommits: 3Joined: 2016-12-22 *Ivan SafonovCommits: 3Joined: 2017-07-13 + + *Gabriel ChiquiniCommits: 3Joined: 2017-10-01 *Bán RóbertCommits: 3Joined: 2017-10-25 - - *Mark VecsernyesCommits: 3Joined: 2017-11-15 *Gergely TarsolyCommits: 3Joined: 2017-11-28 + + *Ahmed GHANMICommits: 3Joined: 2017-11-30 *Abhishek ShrivastavaCommits: 3Joined: 2018-01-17 - - *TelestoCommits: 3Joined: 2018-01-22 *Bartosz KosiorekCommits: 3Joined: 2018-02-07 + + *Shubham VermaCommits: 3Joined: 2018-02-17 *Laurent GodardCommits: 3Joined: 2018-04-24 - - *Ulkem KasapogluCommits: 3Joined: 2018-07-04 *Salih SariyarCommits: 3Joined: 2019-02-09 + + *Omer Fatih CelikCommits: 3Joined: 2019-02-10 *Meryem EzberCommits: 3Joined: 2019-02-10 - - *Andrés MaldonadoCommits: 3Joined: 2019-02-21 *EL-SHREIFCommits: 3Joined: 2019-02-24 + + *Stepas ToliautasCommits: 3Joined: 2019-12-16 *Michel ThomasCommits: 3Joined: 2020-02-01 - - *nienzuCommits: 3Joined: 2020-02-19 *Julian KalinowskiCommits: 3Joined: 2020-03-31 + + *Ian Barkley-YeungCommits: 3Joined: 2020-04-06 *Pierre MartyCommits: 3Joined: 2020-04-17 - - *Eivind SamsethCommits: 3Joined: 2020-05-16 *yakovruCommits: 3Joined: 2020-06-17 + + *mariamfahmyCommits: 3Joined: 2020-10-16 *Leo WangCommits: 3Joined: 2020-10-18 - - *Gizem OzgunCommits: 3Joined: 2020-10-23 *Ismael OleaCommits: 3Joined: 2020-10-28 + + *Tarun SharmaCommits: 3Joined: 2021-01-14 *Zeynep YavuzCommits: 3Joined: 2021-08-02 - - *Natalia GavrilovaCommits: 3Joined: 2021-09-24 *Verne-LaiCommits: 3Joined: 2021-10-01 + + *Renwa HiwaCommits: 3Joined: 2022-02-09 *Tushar JhamCommits: 3Joined: 2022-02-21 - - *YomnasalamaCommits: 3Joined: 2022-03-28 *mostafa-elsharnobyCommits: 3Joined: 2022-03-28 + + *Isha_DesaiCommits: 3Joined: 2022-04-06 *Shady MohamedCommits: 3Joined: 2022-04-11 - - *Aman JhaCommits: 3Joined: 2022-04-15 *AshSincCommits: 3Joined: 2022-05-19 + + *wujiahuanCommits: 3Joined: 2022-07-27 *RakielleCommits: 3Joined: 2022-10-14 - - *Calvince OtienoCommits: 3Joined: 2022-10-14 *Supriyo PaulCommits: 3Joined: 2023-03-02 + + *Vinit AgarwalCommits: 3Joined: 2023-03-06 *gilssonnCommits: 3Joined: 2023-05-10 - - *EMartinGubeCommits: 3Joined: 2023-07-20 *t-aswathCommits: 3Joined: 2023-09-13 + + *Matthew KoganCommits: 3Joined: 2023-10-13 *AmosAidooCommits: 3Joined: 2023-11-21 - - + + *Dev LoCommits: 3Joined: 2023-12-05 + *Steven Casey (SMCode)Commits: 3Joined: 2024-02-13 + + *anish.deshpandeCommits: 3Joined: 2024-02-22 @@ -4681,11 +4749,11 @@ *Omkar Santosh NikamCommits: 3Joined: 2024-04-10 - - *MelvinYGCommits: 3Joined: 2024-10-17 + + *Lorenzo LovatoCommits: 3Joined: 2024-10-26 @@ -4695,22 +4763,14 @@ *LeSci-0x1Commits: 3Joined: 2024-11-01 + + *Jim ChenCommits: 3Joined: 2025-03-24 + - - *Jan RheinländerCommits: 3Joined: 2025-01-18 - - - *Mohit MaratheCommits: 3Joined: 2025-02-19 - - - *Aleksi KallioCommits: 3Joined: 2025-05-21 - *Oscar Megía LópezCommits: 3Joined: 2025-05-31 - - *Bojidar MarinovCommits: 3Joined: 2025-07-10 @@ -4720,11 +4780,11 @@ *Manas TodiCommits: 3Joined: 2025-08-10 + + *mkt1Commits: 3Joined: 2025-09-11 - - *Jussi SuominenCommits: 3Joined: 2025-09-28 @@ -4734,893 +4794,907 @@ *Yui NguyenCommits: 3Joined: 2025-11-09 - - *praweshmCommits: 3Joined: 2025-11-13 - - *Chiggy WiggyCommits: 3Joined: 2025-12-05 + *praweshmCommits: 3Joined: 2025-11-13 *Didier VidalCommits: 3Joined: 2026-01-01 - *Ujjawal KumarCommits: 3Joined: 2026-02-11 + *Carlos RicaCommits: 3Joined: 2026-02-07 - *Krunal BaraskarCommits: 3Joined: 2026-03-12 + *Ivan Vladimirovich KuznetsovCommits: 3Joined: 2026-02-16 + + *Dmitriy UsovCommits: 3Joined: 2026-03-20 + + + *Michael MarklCommits: 3Joined: 2026-04-03 + + + *Wodsfort DragonCommits: 3Joined: 2026-04-11 + + + *Yoon6Commits: 3Joined: 2026-04-17 + + + + + *JanayeJacksonCommits: 3Joined: 2026-05-21 + + + *Andrey OvsyhnoCommits: 3Joined: 2026-07-08 + Loiseleur MichelCommits: 2Joined: 2010-09-14 *Justin MalcolmCommits: 2Joined: 2010-09-29 + + *Seo SanghyeonCommits: 2Joined: 2010-09-29 *Sean McNamaraCommits: 2Joined: 2010-09-29 - - *Robert SedakCommits: 2Joined: 2010-10-05 *Sean McMurrayCommits: 2Joined: 2010-10-20 + + *Nadav VinikCommits: 2Joined: 2010-10-21 *Marcin eXine MCommits: 2Joined: 2010-11-02 - - *Dwayne BaileyCommits: 2Joined: 2010-11-03 *Christoph NoackCommits: 2Joined: 2010-12-13 + + *Sophie GautierCommits: 2Joined: 2010-12-19 *Ed DeanCommits: 2Joined: 2011-01-14 - - *Jonathan CallenCommits: 2Joined: 2011-01-29 *Karsten GerloffCommits: 2Joined: 2011-02-06 + + *Jean Charles PapinCommits: 2Joined: 2011-02-11 *Tobias KranzCommits: 2Joined: 2011-02-17 - - *Matthias KloseCommits: 2Joined: 2011-03-01 *Michael NattererCommits: 2Joined: 2011-04-08 + + *Cyril RoelandtCommits: 2Joined: 2011-04-26 *Kelly AndersonCommits: 2Joined: 2011-05-31 - - *Michal SvecCommits: 2Joined: 2011-07-12 *Mohammad ElahiCommits: 2Joined: 2011-08-27 + + *Takashi NakamotoCommits: 2Joined: 2011-08-28 *Andreu Correa CasablancaCommits: 2Joined: 2011-09-11 - - *Jan HubickaCommits: 2Joined: 2011-09-12 *Arno TeigsethCommits: 2Joined: 2011-09-14 + + *Maxim IorshCommits: 2Joined: 2011-10-05 *Emanuele FiaCommits: 2Joined: 2011-11-02 - - *Yury TarasievichCommits: 2Joined: 2011-11-23 *Mateusz ZasuwikCommits: 2Joined: 2011-12-20 + + *Milos SramekCommits: 2Joined: 2012-01-20 *Andreas SchierlCommits: 2Joined: 2012-01-30 - - *PKEuSCommits: 2Joined: 2012-02-05 *UrmasCommits: 2Joined: 2012-02-13 + + *Bartolomé Sánchez SaladoCommits: 2Joined: 2012-02-18 *Greggory HernandezCommits: 2Joined: 2012-02-22 - - *William GathoyeCommits: 2Joined: 2012-02-28 *Karthik A PadmanabhanCommits: 2Joined: 2012-03-31 + + *Mark WolfCommits: 2Joined: 2012-04-04 *Andrew HigginsonCommits: 2Joined: 2012-04-10 - - *Abeer SethiCommits: 2Joined: 2012-04-12 *Ferran VidalCommits: 2Joined: 2012-04-21 + + *Vicente VendrellCommits: 2Joined: 2012-04-23 *David SteeleCommits: 2Joined: 2012-04-24 - - *Jose Santiago Jimenez SarmientoCommits: 2Joined: 2012-04-24 *Marc GarciaCommits: 2Joined: 2012-05-04 + + *Martyn RussellCommits: 2Joined: 2012-06-07 *Jesso Clarence MuruganCommits: 2Joined: 2012-06-23 - - *Ward van WanrooijCommits: 2Joined: 2012-06-25 *Yuri DarioCommits: 2Joined: 2012-07-18 + + *Horacio FernandesCommits: 2Joined: 2012-07-20 *Andras BartekCommits: 2Joined: 2012-08-06 - - *Daniel HerdeCommits: 2Joined: 2012-08-09 *Johann MessnerCommits: 2Joined: 2012-08-28 + + *Flex LiuCommits: 2Joined: 2012-09-04 *Sergey FarbotkaCommits: 2Joined: 2012-09-21 - - *Louis PossozCommits: 2Joined: 2012-10-26 *Christos StrubulisCommits: 2Joined: 2012-12-09 + + *Arne de BruijnCommits: 2Joined: 2012-12-11 *Milan CrhaCommits: 2Joined: 2013-02-07 - - *Adam MrózCommits: 2Joined: 2013-02-24 *Gregg KingCommits: 2Joined: 2013-02-26 + + *Benedikt MorbachCommits: 2Joined: 2013-03-10 *Moritz KuettCommits: 2Joined: 2013-03-23 - - *Akash ShetyeCommits: 2Joined: 2013-03-23 *Janit AnjariaCommits: 2Joined: 2013-04-19 + + *mmeof2Commits: 2Joined: 2013-05-03 *Donizete WaterkemperCommits: 2Joined: 2013-05-23 - - *Rolf HemmerlingCommits: 2Joined: 2013-06-15 *Jing XianCommits: 2Joined: 2013-06-26 + + *Chris HoppeCommits: 2Joined: 2013-06-27 *Ri GangHuCommits: 2Joined: 2013-07-28 - - *Neil MooreCommits: 2Joined: 2013-08-09 *Viktor VargaCommits: 2Joined: 2013-08-28 + + *Janos FaragoCommits: 2Joined: 2013-09-03 *Richard HughesCommits: 2Joined: 2013-10-01 - - *Mathieu ParentCommits: 2Joined: 2013-10-14 *Jagan LokanathaCommits: 2Joined: 2013-11-19 + + *Anderson RobertoCommits: 2Joined: 2014-01-15 *Martin LiškaCommits: 2Joined: 2014-03-26 - - *Bisal NayalCommits: 2Joined: 2014-05-07 *Hussian AlamriCommits: 2Joined: 2014-05-14 + + *Mukhiddin YusupovCommits: 2Joined: 2014-05-19 *Clarence GuoCommits: 2Joined: 2014-05-26 - - *Hideki IkedaCommits: 2Joined: 2014-06-25 *Boris EgorovCommits: 2Joined: 2014-09-08 + + *YiiChang YenCommits: 2Joined: 2014-10-16 *Vinicius VendraminiCommits: 2Joined: 2014-10-22 - - *Naruhiko OgasawaraCommits: 2Joined: 2014-10-25 *Daniel StoneCommits: 2Joined: 2014-10-29 + + *Supreme AryalCommits: 2Joined: 2014-12-04 *Gary HoustonCommits: 2Joined: 2014-12-15 - - *Mark WilliamsCommits: 2Joined: 2014-12-17 *Clément LassieurCommits: 2Joined: 2014-12-21 + + *Rimas KudelisCommits: 2Joined: 2015-01-06 *dbeurleCommits: 2Joined: 2015-01-12 - - *Kishor BhatCommits: 2Joined: 2015-01-28 *gamebusterzCommits: 2Joined: 2015-02-19 + + *Piet van OostrumCommits: 2Joined: 2015-03-12 *Laszlo Kis-AdamCommits: 2Joined: 2015-03-12 - - *Markus WernigCommits: 2Joined: 2015-03-18 *Jingtao YanCommits: 2Joined: 2015-03-23 + + *Austin ChenCommits: 2Joined: 2015-03-25 *Valter MuraCommits: 2Joined: 2015-06-07 - - *Carlos LuqueCommits: 2Joined: 2015-07-16 *Lubosz SarneckiCommits: 2Joined: 2015-08-20 + + *alexey.chemichevCommits: 2Joined: 2015-11-18 *Sheikha AL-HinaiCommits: 2Joined: 2015-12-28 - - *Yogesh DesaiCommits: 2Joined: 2016-01-05 *Kenneth KoskiCommits: 2Joined: 2016-02-20 + + *ackepenekCommits: 2Joined: 2016-02-21 *Martin NathansenCommits: 2Joined: 2016-04-18 - - *Michal KubecekCommits: 2Joined: 2016-06-02 *Mike SaundersCommits: 2Joined: 2016-06-20 + + *Akash DeshpandeCommits: 2Joined: 2016-08-13 *Sophie SuCommits: 2Joined: 2016-08-27 - - *sllCommits: 2Joined: 2016-09-06 *Pierre LepageCommits: 2Joined: 2016-11-05 + + *Tibor MógerCommits: 2Joined: 2016-12-06 *G_ZoltanCommits: 2Joined: 2016-12-27 - - *George KorepanovCommits: 2Joined: 2017-01-06 *Jeremy BichaCommits: 2Joined: 2017-02-06 + + *JeevanCommits: 2Joined: 2017-03-04 *blendergeekCommits: 2Joined: 2017-04-08 - - *Alexey VlasovCommits: 2Joined: 2017-04-12 *fxwanCommits: 2Joined: 2017-05-15 + + *Yash SrivastavCommits: 2Joined: 2017-06-20 *Sabin FrandesCommits: 2Joined: 2017-09-15 - - *Your NameCommits: 2Joined: 2017-10-09 *G??bor KoruhelyCommits: 2Joined: 2017-10-25 + + *Furkan TokacCommits: 2Joined: 2017-10-25 *Timotej LazarCommits: 2Joined: 2017-11-22 - - *martinb214Commits: 2Joined: 2017-11-28 *Jon NermutCommits: 2Joined: 2018-01-13 + + *Denis ArnaudCommits: 2Joined: 2018-01-16 *brian houston morrowCommits: 2Joined: 2018-01-24 - - *Dmitri KharchevCommits: 2Joined: 2018-01-27 *Andika TriwidadaCommits: 2Joined: 2018-02-15 + + *Victor MireyevCommits: 2Joined: 2018-05-04 *Kevin DubrulleCommits: 2Joined: 2018-07-07 - - *George WoodCommits: 2Joined: 2018-07-25 *Réka CsékeiCommits: 2Joined: 2018-10-09 + + *Simon QuigleyCommits: 2Joined: 2018-10-11 *Mark DoboCommits: 2Joined: 2018-10-20 - - *Izabela BakollariCommits: 2Joined: 2018-10-27 *Alyssa RossCommits: 2Joined: 2018-11-18 + + *Tóth AttilaCommits: 2Joined: 2018-12-30 *Patrik VasCommits: 2Joined: 2018-12-31 - - *Dawid GanCommits: 2Joined: 2019-01-09 *Sass DávidCommits: 2Joined: 2019-01-09 + + *kaishu-sahuCommits: 2Joined: 2019-01-27 *Phil KrylovCommits: 2Joined: 2019-02-10 - - *Muzaffer Kadir YILMAZCommits: 2Joined: 2019-02-10 *Alexander FarrowCommits: 2Joined: 2019-03-19 + + *Jaromir WysogladCommits: 2Joined: 2019-03-27 *Rtch90Commits: 2Joined: 2019-04-22 - - *DarkByt31Commits: 2Joined: 2019-04-22 *wishawaCommits: 2Joined: 2019-04-29 + + *Cor NouwsCommits: 2Joined: 2019-05-23 *DaeHyun SungCommits: 2Joined: 2019-06-01 - - *John ZhangCommits: 2Joined: 2019-09-23 *Mayank SumanCommits: 2Joined: 2019-10-03 + + *shameempkCommits: 2Joined: 2019-10-09 *Mattia RizzoloCommits: 2Joined: 2019-10-23 - - *Batuhan Görkem BenzerCommits: 2Joined: 2019-12-18 *Desmin AlpaslanCommits: 2Joined: 2019-12-18 + + *Luca CarlonCommits: 2Joined: 2020-01-11 *Bjoern KirchhoffCommits: 2Joined: 2020-01-15 - - *Burak BalaCommits: 2Joined: 2020-01-25 *Marina LatiniCommits: 2Joined: 2020-02-11 + + *Kris van der MerweCommits: 2Joined: 2020-02-16 *AlanTangCommits: 2Joined: 2020-02-25 - - *jamesCommits: 2Joined: 2020-02-28 *Andrew Lee (李健秋)Commits: 2Joined: 2020-03-07 + + *Jean-Louis FuchsCommits: 2Joined: 2020-03-10 *shivammoreCommits: 2Joined: 2020-03-18 - - *FatihCommits: 2Joined: 2020-04-23 *Yunusemre ŞentürkCommits: 2Joined: 2020-05-14 + + *Ilkyu JuCommits: 2Joined: 2020-08-08 *Nnamani EzinneCommits: 2Joined: 2020-08-22 - - *Luke DixonCommits: 2Joined: 2020-08-30 *Sven LüppkenCommits: 2Joined: 2020-10-30 + + *TRaXInCommits: 2Joined: 2020-11-10 *Zeynep İnkayaCommits: 2Joined: 2020-11-21 - - *Gül ToksözCommits: 2Joined: 2020-11-21 *Bartu BayazıtCommits: 2Joined: 2020-11-21 + + *Mücahid AydinCommits: 2Joined: 2020-11-21 *ShyamPraveenSinghCommits: 2Joined: 2020-11-24 - - *DuP-491Commits: 2Joined: 2020-12-13 *siddheshpatil777Commits: 2Joined: 2020-12-19 + + *halfhiddencodeCommits: 2Joined: 2020-12-26 *princesinghtomarCommits: 2Joined: 2020-12-28 - - *AlchemistCommits: 2Joined: 2020-12-31 *Quentin PAGÈSCommits: 2Joined: 2021-01-06 + + *ShobhitCommits: 2Joined: 2021-01-30 *Quan NguyenCommits: 2Joined: 2021-02-09 - - *Eyal RozenbergCommits: 2Joined: 2021-02-13 *Buse OrakCommits: 2Joined: 2021-02-13 + + *MoazCommits: 2Joined: 2021-02-21 *Winston Min TjongCommits: 2Joined: 2021-03-02 - - *PanosCommits: 2Joined: 2021-03-23 *rounakCommits: 2Joined: 2021-03-31 + + *sarynasserCommits: 2Joined: 2021-04-10 *Mihail BalabanovCommits: 2Joined: 2021-04-11 - - *haru-02Commits: 2Joined: 2021-04-21 *Sabyasachi BhoiCommits: 2Joined: 2021-07-22 + + *HuilinCommits: 2Joined: 2021-07-24 *oguzbalkayaCommits: 2Joined: 2021-08-03 - - *Ankur KhandelwalCommits: 2Joined: 2021-08-09 *Karan AbrolCommits: 2Joined: 2021-08-11 + + *Aleś BułojčykCommits: 2Joined: 2021-09-27 *Emanuel SchorschCommits: 2Joined: 2021-10-04 - - *HarjotCommits: 2Joined: 2021-11-17 *Pesi TaototoCommits: 2Joined: 2021-12-05 + + *Sinduja YCommits: 2Joined: 2022-02-07 *Kunal PawarCommits: 2Joined: 2022-02-10 - - *psidiumcodeCommits: 2Joined: 2022-02-15 *Gautham KrishnanCommits: 2Joined: 2022-03-01 + + *Rizal MuttaqinCommits: 2Joined: 2022-04-05 *Vincent ReherCommits: 2Joined: 2022-04-06 - - *LukasCommits: 2Joined: 2022-04-20 *nazanin yadiCommits: 2Joined: 2022-06-03 + + *Nathan Pratta TeodosioCommits: 2Joined: 2022-06-21 *Mahdi TizabiCommits: 2Joined: 2022-06-25 - - *Stanislav LopatinCommits: 2Joined: 2022-08-07 *Emmanuel PeterCommits: 2Joined: 2022-10-13 + + *insanetreeCommits: 2Joined: 2022-10-17 *Nalini Prasad DashCommits: 2Joined: 2022-10-23 - - *Emanuele GoldoniCommits: 2Joined: 2022-11-07 *Tarcísio Ladeia de OliveiraCommits: 2Joined: 2022-11-22 + + *DowwdyJCommits: 2Joined: 2023-01-17 *PLCommits: 2Joined: 2023-01-28 - - *Uday SharmaCommits: 2Joined: 2023-02-11 *Matti TyrväinenCommits: 2Joined: 2023-02-13 + + *niket1322gitCommits: 2Joined: 2023-02-22 *Abdallah ElhdadCommits: 2Joined: 2023-03-02 - - *MoazAlaaCommits: 2Joined: 2023-03-05 *adityasingh22Commits: 2Joined: 2023-03-08 + + *Jani SaranpääCommits: 2Joined: 2023-03-22 *Khaled HosnyCommits: 2Joined: 2023-07-10 - - *Deepika GoyalCommits: 2Joined: 2023-08-17 *Tobias KokolakisCommits: 2Joined: 2023-08-26 + + *Bayram ÇiçekCommits: 2Joined: 2023-08-30 *Adam Eric FallonCommits: 2Joined: 2023-08-31 - - *Cosmin HumeniucCommits: 2Joined: 2023-09-21 *Achintya SharmaCommits: 2Joined: 2023-11-23 - - *Dev LoCommits: 2Joined: 2023-12-05 - + + *Declan FodorCommits: 2Joined: 2023-12-23 - - *zephCommits: 2Joined: 2024-02-06 @@ -5630,11 +5704,11 @@ *AntonyCommits: 2Joined: 2024-03-14 + + *Juan José GonzálezCommits: 2Joined: 2024-04-04 - - *colton GarrettCommits: 2Joined: 2024-04-15 @@ -5644,53 +5718,53 @@ *Peter HagenCommits: 2Joined: 2024-07-05 + + + + *Lars JødalCommits: 2Joined: 2024-07-17 + *Per99Commits: 2Joined: 2024-07-29 - - *Eloi MontañésCommits: 2Joined: 2024-08-01 *Usman AkinyemiCommits: 2Joined: 2024-10-03 + + *Chizoba ODINAKACommits: 2Joined: 2024-10-16 *Muluh MG GodsonCommits: 2Joined: 2024-10-17 - - *Jack HonourCommits: 2Joined: 2024-10-23 *anonymotterCommits: 2Joined: 2024-11-28 + + *asif196Commits: 2Joined: 2025-01-21 *Bingwu ZhangCommits: 2Joined: 2025-02-07 - - *Kukee ThooCommits: 2Joined: 2025-03-11 *ArsalanKhan04Commits: 2Joined: 2025-03-13 + + *Mohamed ZaghloulCommits: 2Joined: 2025-03-20 - - *Jim ChenCommits: 2Joined: 2025-03-24 - - - *Celia Palacios Gómez TagleCommits: 2Joined: 2025-04-07 @@ -5700,11 +5774,11 @@ *Mateusz WlazłowskiCommits: 2Joined: 2025-04-27 + + *Babacea AlexandruCommits: 2Joined: 2025-05-15 - - *Stefan DorneanuCommits: 2Joined: 2025-05-16 @@ -5714,14 +5788,8 @@ *Buo-ren Lin (OSSII)Commits: 2Joined: 2025-07-03 - - *Tibor NagyCommits: 2Joined: 2025-07-11 - - - *Thorsten BehrensCommits: 2Joined: 2025-07-18 - *Teemu PöytäniemiCommits: 2Joined: 2025-08-31 @@ -5731,11 +5799,11 @@ *toadkarterCommits: 2Joined: 2025-09-09 - - *JMaravalhasSilvaCommits: 2Joined: 2025-10-13 + + *Jussi SuominenCommits: 2Joined: 2025-11-02 @@ -5745,24 +5813,58 @@ *Vincent CARPENTIERCommits: 2Joined: 2025-12-02 - - *Ion RusnacCommits: 2Joined: 2025-12-06 + + *Michael OttoCommits: 2Joined: 2026-01-08 + + *Masayuki IizukaCommits: 2Joined: 2026-01-15 + *Dustin HoeppnerCommits: 2Joined: 2026-01-27 - *KashifCommits: 2Joined: 2026-02-18 + *OUBOUSKEN ILYASCommits: 2Joined: 2026-02-08 - *Jan LuethiCommits: 2Joined: 2026-02-21 + *KashifCommits: 2Joined: 2026-02-18 + + + *yaswantpenapakaCommits: 2Joined: 2026-03-12 + + + *iwritepeomCommits: 2Joined: 2026-03-26 + + + *Piotr OsadaCommits: 2Joined: 2026-04-01 + + + + + *Bhumi TalwarCommits: 2Joined: 2026-04-20 + + + *CassieLXCommits: 2Joined: 2026-04-23 + + + *Denis A. Altoé FalquetoCommits: 2Joined: 2026-07-14 + + + *Sofia GazizovaCommits: 2Joined: 2026-07-17 + + + + + *Niko MyllymäkiCommits: 2Joined: 2026-08-03 + + + *Noel GrandinCommits: 2Joined: 2026-08-24 *NeilBrownCommits: 1Joined: 2010-09-28 @@ -5770,11 +5872,11 @@ *Alexandr N. ZamaraevCommits: 1Joined: 2010-10-01 + + *Nick SavageCommits: 1Joined: 2010-10-01 - - *Neil StalkerCommits: 1Joined: 2010-10-02 @@ -5784,11 +5886,11 @@ *Denis LackovicCommits: 1Joined: 2010-10-05 + + *krishnan parthasarathiCommits: 1Joined: 2010-10-07 - - *Rubén JáñezCommits: 1Joined: 2010-10-11 @@ -5798,11 +5900,11 @@ *Wolfgang SilbermayrCommits: 1Joined: 2010-10-21 + + *Adrià Cereto MassaguéCommits: 1Joined: 2010-10-26 - - *Kalman KemenczyCommits: 1Joined: 2010-10-28 @@ -5812,11 +5914,11 @@ *Christopher BackhouseCommits: 1Joined: 2010-12-06 + + *pavelCommits: 1Joined: 2010-12-10 - - *camilleCommits: 1Joined: 2010-12-13 @@ -5826,11 +5928,11 @@ *Paolo PozzanCommits: 1Joined: 2010-12-19 + + *Dan CorneanuCommits: 1Joined: 2010-12-29 - - *armijnCommits: 1Joined: 2010-12-30 @@ -5840,11 +5942,11 @@ *Andy HearnCommits: 1Joined: 2011-01-09 + + *Nikita OfitserovCommits: 1Joined: 2011-01-10 - - *Guillaume FillolCommits: 1Joined: 2011-01-29 @@ -5854,11 +5956,11 @@ *Andreas SliwkaCommits: 1Joined: 2011-02-06 + + *Andrey TurkinCommits: 1Joined: 2011-02-09 - - *Danny RobertsCommits: 1Joined: 2011-02-18 @@ -5868,11 +5970,11 @@ *Rafael CabralCommits: 1Joined: 2011-03-31 + + *Alberto RuizCommits: 1Joined: 2011-03-31 - - *Paulo JoséCommits: 1Joined: 2011-04-01 @@ -5882,11 +5984,11 @@ *Maxime CôtéCommits: 1Joined: 2011-04-19 + + *Chris CheneyCommits: 1Joined: 2011-04-27 - - *Jan NieuwenhuizenCommits: 1Joined: 2011-04-28 @@ -5896,11 +5998,11 @@ *Marcel HBCommits: 1Joined: 2011-05-03 + + *William LachanceCommits: 1Joined: 2011-06-08 - - *Jeff AignerCommits: 1Joined: 2011-06-09 @@ -5910,11 +6012,11 @@ *Dolives BenoitCommits: 1Joined: 2011-07-04 + + *Ta Duc TungCommits: 1Joined: 2011-08-08 - - *Christophe StrobbeCommits: 1Joined: 2011-08-09 @@ -5924,11 +6026,11 @@ *Hugo Beauzée-LuyssenCommits: 1Joined: 2011-09-28 + + *Bernhard M. WiedemannCommits: 1Joined: 2011-10-17 - - *Stefan WeigelCommits: 1Joined: 2011-10-17 @@ -5938,11 +6040,11 @@ *Andrew WestCommits: 1Joined: 2011-10-21 + + *Matt PrattCommits: 1Joined: 2011-11-02 - - *Karl KoehlerCommits: 1Joined: 2011-11-11 @@ -5952,11 +6054,11 @@ *Roman EiseleCommits: 1Joined: 2011-11-23 + + *Serg BormantCommits: 1Joined: 2011-11-28 - - *Juan Pablo Martínez CortésCommits: 1Joined: 2011-11-28 @@ -5966,11 +6068,11 @@ *Vincent PovirkCommits: 1Joined: 2011-12-19 + + *Moritz BechlerCommits: 1Joined: 2011-12-19 - - *James CCommits: 1Joined: 2011-12-20 @@ -5980,11 +6082,11 @@ *Victor LeeCommits: 1Joined: 2011-12-24 + + *Joshua CogliatiCommits: 1Joined: 2012-01-06 - - *Kenneth AafløyCommits: 1Joined: 2012-01-11 @@ -5994,11 +6096,11 @@ *Da'angh KhagarothCommits: 1Joined: 2012-01-16 + + *Ankitkumar Rameshchandra PatelCommits: 1Joined: 2012-01-20 - - *Martin RichardCommits: 1Joined: 2012-01-31 @@ -6008,11 +6110,11 @@ *Daniel MihalyiCommits: 1Joined: 2012-02-06 + + *Carsten NiehausCommits: 1Joined: 2012-02-09 - - *Masataka ShinkeCommits: 1Joined: 2012-02-15 @@ -6022,11 +6124,11 @@ *Juergen SteinhilberCommits: 1Joined: 2012-03-05 + + *Italo VignoliCommits: 1Joined: 2012-03-09 - - *Karan DesaiCommits: 1Joined: 2012-04-01 @@ -6036,11 +6138,11 @@ *Aldo Román NureñaCommits: 1Joined: 2012-04-09 + + *Laureano G. LindeCommits: 1Joined: 2012-04-15 - - *Udo SchuermannCommits: 1Joined: 2012-04-16 @@ -6050,11 +6152,11 @@ *Jaime NavarroCommits: 1Joined: 2012-04-20 + + *Florent GallaireCommits: 1Joined: 2012-04-21 - - *Vicente Rafael Estevez VacasCommits: 1Joined: 2012-04-22 @@ -6064,11 +6166,11 @@ *Javier Silva SanahujaCommits: 1Joined: 2012-04-23 + + *Xavi Escriche GalindoCommits: 1Joined: 2012-04-24 - - *Jose ManuelCommits: 1Joined: 2012-04-25 @@ -6078,11 +6180,11 @@ *Javier CatalaCommits: 1Joined: 2012-04-26 + + *Jordi MallachCommits: 1Joined: 2012-05-03 - - *Gordon LackCommits: 1Joined: 2012-05-09 @@ -6092,11 +6194,11 @@ *Ionut BiruCommits: 1Joined: 2012-05-14 + + *Alberto FerreiraCommits: 1Joined: 2012-06-08 - - *Travis CarterCommits: 1Joined: 2012-06-22 @@ -6106,11 +6208,11 @@ *Phil HartCommits: 1Joined: 2012-06-29 + + *Kevin PengCommits: 1Joined: 2012-07-20 - - *Tim-Philipp MüllerCommits: 1Joined: 2012-07-29 @@ -6120,11 +6222,11 @@ *Joseph BrownCommits: 1Joined: 2012-08-14 + + *Kevin HausmannCommits: 1Joined: 2012-08-17 - - *Dave RichardsCommits: 1Joined: 2012-08-22 @@ -6134,11 +6236,11 @@ *Marco BiscaroCommits: 1Joined: 2012-08-27 + + *Nico WeyandCommits: 1Joined: 2012-09-02 - - *Douglas Rodrigues de AlmeidaCommits: 1Joined: 2012-09-15 @@ -6148,11 +6250,11 @@ *Andrew RistCommits: 1Joined: 2012-10-05 + + *Neven ĆosićCommits: 1Joined: 2012-10-08 - - *Chen ZuoJunCommits: 1Joined: 2012-10-08 @@ -6162,11 +6264,11 @@ *LesterCommits: 1Joined: 2012-10-23 + + *Mathieu DCommits: 1Joined: 2012-11-19 - - *Naser SharifiCommits: 1Joined: 2012-11-26 @@ -6176,11 +6278,11 @@ *Olivier PlotonCommits: 1Joined: 2012-12-12 + + *pkoroau pkoroauCommits: 1Joined: 2012-12-20 - - *Quentin PradetCommits: 1Joined: 2012-12-21 @@ -6190,11 +6292,11 @@ *Dennis E. HamiltonCommits: 1Joined: 2013-01-19 + + *OKANO TakayoshiCommits: 1Joined: 2013-01-29 - - *Mark WrightCommits: 1Joined: 2013-02-09 @@ -6204,11 +6306,11 @@ *Andrew BranchCommits: 1Joined: 2013-02-20 + + *Martin BrownCommits: 1Joined: 2013-02-23 - - *Hamza AbdelkebirCommits: 1Joined: 2013-02-23 @@ -6218,11 +6320,11 @@ *Kenneth BeckCommits: 1Joined: 2013-03-02 + + *Jiri BlechaCommits: 1Joined: 2013-03-02 - - *Gábor NyersCommits: 1Joined: 2013-03-02 @@ -6232,11 +6334,11 @@ *Ondřej SmržCommits: 1Joined: 2013-03-10 + + *Steven MeyerCommits: 1Joined: 2013-03-13 - - *vincentCommits: 1Joined: 2013-03-22 @@ -6246,11 +6348,11 @@ *Jacqueline RahemipourCommits: 1Joined: 2013-03-23 + + *Lucian ConstantinCommits: 1Joined: 2013-03-24 - - *Tomas TurekCommits: 1Joined: 2013-03-24 @@ -6260,11 +6362,11 @@ *Hansgerd SchneiderCommits: 1Joined: 2013-04-02 + + *Honza MinarikCommits: 1Joined: 2013-04-03 - - *Ashish BanerjeeCommits: 1Joined: 2013-04-04 @@ -6274,11 +6376,11 @@ *Jakub GolebiewskiCommits: 1Joined: 2013-04-09 + + *Pavel KacerCommits: 1Joined: 2013-04-11 - - *tinderboxCommits: 1Joined: 2013-04-11 @@ -6288,11 +6390,11 @@ *Ota ChasákCommits: 1Joined: 2013-04-24 + + *Jan BobisudCommits: 1Joined: 2013-04-29 - - *Yohei YukawaCommits: 1Joined: 2013-05-06 @@ -6302,11 +6404,11 @@ *Jonathan SchultzCommits: 1Joined: 2013-05-22 + + *Neil Voss (fourier)Commits: 1Joined: 2013-05-24 - - *Tim RichardsonCommits: 1Joined: 2013-06-04 @@ -6316,11 +6418,11 @@ *Jean-François Fortin TamCommits: 1Joined: 2013-06-10 + + *Benjamin OtteCommits: 1Joined: 2013-06-15 - - *Peng GaoCommits: 1Joined: 2013-06-16 @@ -6330,11 +6432,11 @@ *Alaa.BukhariCommits: 1Joined: 2013-07-04 + + *Erik AuerswaldCommits: 1Joined: 2013-07-09 - - *Reem.ALotaibiCommits: 1Joined: 2013-07-25 @@ -6344,11 +6446,11 @@ *Srijan ChoudharyCommits: 1Joined: 2013-08-10 + + *AdrienCommits: 1Joined: 2013-08-18 - - *Stefano FacchiniCommits: 1Joined: 2013-08-22 @@ -6358,11 +6460,11 @@ *Raymond WellsCommits: 1Joined: 2013-09-02 + + *Danny BrownCommits: 1Joined: 2013-09-18 - - *Henning DiedlerCommits: 1Joined: 2013-11-02 @@ -6372,11 +6474,11 @@ *Rolf KoetterCommits: 1Joined: 2013-11-05 + + *yjw9012Commits: 1Joined: 2013-12-30 - - *Ayantha RandikaCommits: 1Joined: 2014-01-23 @@ -6386,11 +6488,11 @@ *J. Fernando LagrangeCommits: 1Joined: 2014-02-02 + + *christianjuCommits: 1Joined: 2014-02-10 - - *Mathias SuppCommits: 1Joined: 2014-02-25 @@ -6400,11 +6502,11 @@ *Jason GerlowskiCommits: 1Joined: 2014-03-07 + + *roopak12345Commits: 1Joined: 2014-03-09 - - *Manas JoshiCommits: 1Joined: 2014-03-17 @@ -6414,11 +6516,11 @@ *Milan ZelenkaCommits: 1Joined: 2014-03-26 + + *Hannah LyhneCommits: 1Joined: 2014-04-01 - - *Aditya KaleCommits: 1Joined: 2014-04-01 @@ -6428,11 +6530,11 @@ *Michal HorakCommits: 1Joined: 2014-04-21 + + *Alex GulyásCommits: 1Joined: 2014-04-27 - - *Apostolos SyropoulosCommits: 1Joined: 2014-05-07 @@ -6442,11 +6544,11 @@ *Shreyansh GandhiCommits: 1Joined: 2014-06-10 + + *Damien ChambeCommits: 1Joined: 2014-06-15 - - *Robin KumarCommits: 1Joined: 2014-06-17 @@ -6456,11 +6558,11 @@ *Fahad Al-SaidiCommits: 1Joined: 2014-07-16 + + *Martin OwensCommits: 1Joined: 2014-07-27 - - *Heiko ScheidtCommits: 1Joined: 2014-08-03 @@ -6470,11 +6572,11 @@ *Audrey TangCommits: 1Joined: 2014-08-05 + + *Hiroto KagotaniCommits: 1Joined: 2014-08-19 - - *Jörg SonnenbergerCommits: 1Joined: 2014-08-28 @@ -6484,11 +6586,11 @@ *Babu VincentCommits: 1Joined: 2014-09-19 + + *Seyeong KimCommits: 1Joined: 2014-10-06 - - *Lennart PoetteringCommits: 1Joined: 2014-10-09 @@ -6498,11 +6600,11 @@ *Ruggero CyrilleCommits: 1Joined: 2014-10-18 + + *Victor PortellaCommits: 1Joined: 2014-11-05 - - *Jonathan RiddellCommits: 1Joined: 2014-11-22 @@ -6512,11 +6614,11 @@ *galbarnissanCommits: 1Joined: 2014-12-03 + + *Mattias PõldaruCommits: 1Joined: 2014-12-06 - - *Juan A. Suarez RomeroCommits: 1Joined: 2014-12-15 @@ -6526,11 +6628,11 @@ *Pieter AdriaensenCommits: 1Joined: 2014-12-21 + + *Andreas K. Huettel (dilfridge)Commits: 1Joined: 2015-01-04 - - *Péter SzathmáryCommits: 1Joined: 2015-01-07 @@ -6540,11 +6642,11 @@ *Michael KovarikCommits: 1Joined: 2015-01-07 + + *ZirkCommits: 1Joined: 2015-01-07 - - *Simon WilperCommits: 1Joined: 2015-01-24 @@ -6554,11 +6656,11 @@ *Michael HornCommits: 1Joined: 2015-03-21 + + *Karthick Prasad GunasekaranCommits: 1Joined: 2015-03-22 - - *robert BabiakCommits: 1Joined: 2015-03-25 @@ -6568,11 +6670,11 @@ *Jorge Cunha MendesCommits: 1Joined: 2015-04-03 + + *Sujith SudhakaranCommits: 1Joined: 2015-04-07 - - *Petr GajdosCommits: 1Joined: 2015-04-07 @@ -6582,11 +6684,11 @@ *massinissaHamidiCommits: 1Joined: 2015-05-07 + + *Yurii KolesnykovCommits: 1Joined: 2015-05-10 - - *Sam TukeCommits: 1Joined: 2015-05-21 @@ -6596,11 +6698,11 @@ *Antoine CœurCommits: 1Joined: 2015-06-11 + + *Jihui ChoiCommits: 1Joined: 2015-06-22 - - *Raj NatarajanCommits: 1Joined: 2015-07-23 @@ -6610,11 +6712,11 @@ *Fernando PiraniCommits: 1Joined: 2015-08-04 + + *Nathan WellsCommits: 1Joined: 2015-09-03 - - *Joan ParaisoCommits: 1Joined: 2015-09-25 @@ -6624,11 +6726,11 @@ *Timothée IsnardCommits: 1Joined: 2015-10-11 + + *marstayCommits: 1Joined: 2015-10-18 - - *GhasanCommits: 1Joined: 2015-11-09 @@ -6638,11 +6740,11 @@ *Keigo KawamuraCommits: 1Joined: 2015-11-16 + + *Steve HartCommits: 1Joined: 2015-11-17 - - *Reto SchneiderCommits: 1Joined: 2015-11-20 @@ -6652,11 +6754,11 @@ *Nicola PovoleriCommits: 1Joined: 2015-11-28 + + *Paolo BernardiCommits: 1Joined: 2015-11-30 - - *Pierre SauterCommits: 1Joined: 2015-12-01 @@ -6666,11 +6768,11 @@ *Johannes HaufCommits: 1Joined: 2015-12-31 + + *Debarshi RayCommits: 1Joined: 2016-01-08 - - *shubhamtibraCommits: 1Joined: 2016-01-16 @@ -6680,11 +6782,11 @@ *Gabriele PonzoCommits: 1Joined: 2016-01-29 + + *Marc BessièresCommits: 1Joined: 2016-01-29 - - *Christoph BrillCommits: 1Joined: 2016-02-09 @@ -6694,11 +6796,11 @@ *Apachev IvanCommits: 1Joined: 2016-03-08 + + *HaidongWuCommits: 1Joined: 2016-03-09 - - *Mohamed ThabetCommits: 1Joined: 2016-03-13 @@ -6708,11 +6810,11 @@ *Alexandru MoscuCommits: 1Joined: 2016-03-18 + + *Gleb MishchenkoCommits: 1Joined: 2016-03-22 - - *JBurantCommits: 1Joined: 2016-04-05 @@ -6722,11 +6824,11 @@ *Seraphime KirkovskiCommits: 1Joined: 2016-04-29 + + *Nurhak ALTINCommits: 1Joined: 2016-05-01 - - *PeterCommits: 1Joined: 2016-05-03 @@ -6736,11 +6838,11 @@ *Sam TygierCommits: 1Joined: 2016-05-22 + + *Helena SvobodovaCommits: 1Joined: 2016-05-25 - - *Zhengqiang WangCommits: 1Joined: 2016-06-02 @@ -6750,11 +6852,11 @@ *emahaldar/emCommits: 1Joined: 2016-06-13 + + *Otto KekäläinenCommits: 1Joined: 2016-07-03 - - *Julian MehneCommits: 1Joined: 2016-08-04 @@ -6764,11 +6866,11 @@ *Yan PashkovskyCommits: 1Joined: 2016-08-12 + + *rpmbuildCommits: 1Joined: 2016-08-15 - - *Zenaan HarknessCommits: 1Joined: 2016-08-22 @@ -6778,11 +6880,11 @@ *Ilya PonamarevCommits: 1Joined: 2016-10-05 + + *JookiaCommits: 1Joined: 2016-10-08 - - *Mirco RondiniCommits: 1Joined: 2016-10-10 @@ -6792,11 +6894,11 @@ *Шиповський РоманCommits: 1Joined: 2016-10-28 + + *Tamás GulácsiCommits: 1Joined: 2016-11-11 - - *Owen GenatCommits: 1Joined: 2016-11-20 @@ -6806,11 +6908,11 @@ *n5xgdhCommits: 1Joined: 2016-12-04 + + *Justn LavoieCommits: 1Joined: 2016-12-30 - - *thvalloisCommits: 1Joined: 2017-01-03 @@ -6820,11 +6922,11 @@ *Aleix PolCommits: 1Joined: 2017-01-19 + + *yellowflash104Commits: 1Joined: 2017-02-12 - - *Mike GorseCommits: 1Joined: 2017-03-11 @@ -6834,11 +6936,11 @@ *ComputingDwarfCommits: 1Joined: 2017-03-12 + + *Umang JainCommits: 1Joined: 2017-03-13 - - *udaycoderCommits: 1Joined: 2017-03-14 @@ -6848,11 +6950,11 @@ *Andreas SägerCommits: 1Joined: 2017-03-26 + + *Gabriel HerreraCommits: 1Joined: 2017-04-05 - - *Werner TietzCommits: 1Joined: 2017-04-11 @@ -6862,11 +6964,11 @@ *Catherine VanceCommits: 1Joined: 2017-04-17 + + *Naeil ZOUEIDICommits: 1Joined: 2017-04-26 - - *frederic vromanCommits: 1Joined: 2017-05-12 @@ -6876,11 +6978,11 @@ *Arianna MascioliniCommits: 1Joined: 2017-05-29 + + *Francesco GradiCommits: 1Joined: 2017-05-29 - - *dcvbCommits: 1Joined: 2017-07-06 @@ -6890,11 +6992,11 @@ *Luke DellerCommits: 1Joined: 2017-07-12 + + *Aditya DewanCommits: 1Joined: 2017-07-15 - - *serdarot5Commits: 1Joined: 2017-08-05 @@ -6904,11 +7006,11 @@ *Dinh LeCommits: 1Joined: 2017-09-05 + + *66kesara99Commits: 1Joined: 2017-09-23 - - *Stoyan DimitrovCommits: 1Joined: 2017-10-01 @@ -6918,11 +7020,11 @@ *Matti LehtonenCommits: 1Joined: 2017-10-07 + + *Tjipke van der HeideCommits: 1Joined: 2017-10-12 - - *Kristóf UmannCommits: 1Joined: 2017-10-25 @@ -6932,11 +7034,11 @@ *Suhail AlkowaileetCommits: 1Joined: 2017-12-25 + + *Dominique LeuenbergerCommits: 1Joined: 2018-01-05 - - *Gabriele PonzoCommits: 1Joined: 2018-02-06 @@ -6946,11 +7048,11 @@ *ReshmaCommits: 1Joined: 2018-03-09 + + *HrishabhCommits: 1Joined: 2018-03-10 - - *Álex PuchadesCommits: 1Joined: 2018-03-14 @@ -6960,11 +7062,11 @@ *Nithin Kumar PadavuCommits: 1Joined: 2018-04-07 + + *Kevin Brubeck UnhammerCommits: 1Joined: 2018-04-14 - - *Heiko TietzeCommits: 1Joined: 2018-04-16 @@ -6974,11 +7076,11 @@ *Fred KruseCommits: 1Joined: 2018-05-28 + + *orbeaCommits: 1Joined: 2018-06-01 - - *Louis SautierCommits: 1Joined: 2018-06-10 @@ -6988,11 +7090,11 @@ *SalimHabchiCommits: 1Joined: 2018-07-11 + + *Caio B. SilvaCommits: 1Joined: 2018-07-23 - - *U-Vladimir\VadimCommits: 1Joined: 2018-08-05 @@ -7002,11 +7104,11 @@ *Bijan TabatabaiCommits: 1Joined: 2018-08-26 + + *Leo MoonsCommits: 1Joined: 2018-08-26 - - *AlicVBCommits: 1Joined: 2018-10-17 @@ -7016,11 +7118,11 @@ *Howard JohnsonCommits: 1Joined: 2018-11-25 + + *Rizal MuttaqinCommits: 1Joined: 2018-12-18 - - *Çağrı DolazCommits: 1Joined: 2018-12-30 @@ -7030,11 +7132,11 @@ *Andreas SturmlechnerCommits: 1Joined: 2019-01-08 + + *KomalCommits: 1Joined: 2019-01-12 - - *Ajay MahatoCommits: 1Joined: 2019-01-21 @@ -7044,11 +7146,11 @@ *Yusuf SonmezCommits: 1Joined: 2019-02-10 + + *Michael SchroederCommits: 1Joined: 2019-02-25 - - *Sainal ShahCommits: 1Joined: 2019-03-10 @@ -7058,11 +7160,11 @@ *VaibhavCommits: 1Joined: 2019-03-17 + + *kushagrakasliwal1Commits: 1Joined: 2019-03-18 - - *Greg VeldmanCommits: 1Joined: 2019-03-24 @@ -7072,11 +7174,11 @@ *Jason BurnsCommits: 1Joined: 2019-04-08 + + *RegisCommits: 1Joined: 2019-04-09 - - *Milutin SmiljanicCommits: 1Joined: 2019-04-19 @@ -7086,11 +7188,11 @@ *Jens CarlCommits: 1Joined: 2019-05-27 + + *Jay BinghamCommits: 1Joined: 2019-06-03 - - *Jim MacArthurCommits: 1Joined: 2019-06-11 @@ -7100,11 +7202,11 @@ *Kovács László ZoltánCommits: 1Joined: 2019-08-07 + + *Vipul GuptaCommits: 1Joined: 2019-08-09 - - *Kovács László ZoltánCommits: 1Joined: 2019-08-13 @@ -7114,11 +7216,11 @@ *Tim BartlettCommits: 1Joined: 2019-08-19 + + *Nicolas FellaCommits: 1Joined: 2019-09-01 - - *Dennis SchriddeCommits: 1Joined: 2019-10-04 @@ -7128,11 +7230,11 @@ *Rasmus ThomsenCommits: 1Joined: 2019-10-26 + + *Martin MilataCommits: 1Joined: 2019-12-04 - - *shashikdmCommits: 1Joined: 2019-12-08 @@ -7142,11 +7244,11 @@ *Sıla GençCommits: 1Joined: 2019-12-20 + + *ertoCommits: 1Joined: 2019-12-20 - - *Andrés MaldonadoCommits: 1Joined: 2019-12-26 @@ -7156,11 +7258,11 @@ *Elzem AtayCommits: 1Joined: 2020-01-04 + + *Louis MeyratCommits: 1Joined: 2020-01-12 - - *Cumali ToprakCommits: 1Joined: 2020-01-27 @@ -7170,11 +7272,11 @@ *Emiliano VavassoriCommits: 1Joined: 2020-02-04 + + *praneshulleriCommits: 1Joined: 2020-02-11 - - *Adam MajerCommits: 1Joined: 2020-02-19 @@ -7184,11 +7286,11 @@ *Matteo CasalinCommits: 1Joined: 2020-03-04 + + *TJ HoltCommits: 1Joined: 2020-03-12 - - *So YanaiharaCommits: 1Joined: 2020-03-21 @@ -7198,11 +7300,11 @@ *Wyatt TurnerCommits: 1Joined: 2020-03-26 + + *mikiCommits: 1Joined: 2020-04-09 - - *Alexander VolkovCommits: 1Joined: 2020-04-09 @@ -7212,11 +7314,11 @@ *Pavel KlevakinCommits: 1Joined: 2020-04-17 + + *Markus KellerCommits: 1Joined: 2020-05-01 - - *Martin WhitakerCommits: 1Joined: 2020-05-08 @@ -7226,11 +7328,11 @@ *Igor PoboikoCommits: 1Joined: 2020-05-22 + + *Muhammet KaraCommits: 1Joined: 2020-05-24 - - *Ilia SheshukovCommits: 1Joined: 2020-06-04 @@ -7240,11 +7342,11 @@ *Yakov ReztsovCommits: 1Joined: 2020-06-15 + + *Pranam LashkariCommits: 1Joined: 2020-06-20 - - *Shiro KawaiCommits: 1Joined: 2020-06-26 @@ -7254,11 +7356,11 @@ *Octavio AlvarezCommits: 1Joined: 2020-07-16 + + *tgds03Commits: 1Joined: 2020-08-16 - - *ramtk6726Commits: 1Joined: 2020-08-16 @@ -7268,11 +7370,11 @@ *HochwasserCommits: 1Joined: 2020-09-17 + + *Felix WiegandCommits: 1Joined: 2020-09-25 - - *Travis StewartCommits: 1Joined: 2020-10-01 @@ -7282,11 +7384,11 @@ *NikhilCommits: 1Joined: 2020-10-04 + + *DanielCommits: 1Joined: 2020-10-10 - - *Platon PronkoCommits: 1Joined: 2020-10-19 @@ -7296,11 +7398,11 @@ *Betül İnceCommits: 1Joined: 2020-10-22 + + *Jeff LawCommits: 1Joined: 2020-11-03 - - *ArdaCommits: 1Joined: 2020-11-21 @@ -7310,11 +7412,11 @@ *Henrik KarlssonCommits: 1Joined: 2020-11-26 + + *ganeshdevareCommits: 1Joined: 2020-11-29 - - *Edward LynchCommits: 1Joined: 2020-11-29 @@ -7324,11 +7426,11 @@ *gar SoulCommits: 1Joined: 2020-12-08 + + *cseguraCommits: 1Joined: 2021-01-03 - - *Isah BllacaCommits: 1Joined: 2021-01-08 @@ -7338,11 +7440,11 @@ *Antje KazimiersCommits: 1Joined: 2021-01-30 + + *Linus HeckemannCommits: 1Joined: 2021-02-07 - - *vipbuoyCommits: 1Joined: 2021-02-14 @@ -7352,11 +7454,11 @@ *Victor KukshievCommits: 1Joined: 2021-02-18 + + *heet-2312Commits: 1Joined: 2021-03-01 - - *JohnCommits: 1Joined: 2021-03-04 @@ -7366,11 +7468,11 @@ *Mani KumarCommits: 1Joined: 2021-03-17 + + *arpit1912Commits: 1Joined: 2021-03-19 - - *pekka-devCommits: 1Joined: 2021-03-21 @@ -7380,11 +7482,11 @@ *bykiviCommits: 1Joined: 2021-03-23 + + *Aritz ErkiagaCommits: 1Joined: 2021-03-25 - - *anirudh4583Commits: 1Joined: 2021-03-26 @@ -7394,25 +7496,25 @@ *Felipe LemaCommits: 1Joined: 2021-04-01 - - *Oleksii MakhotinCommits: 1Joined: 2021-04-06 - - *Vatsal32Commits: 1Joined: 2021-04-07 + *Oleksii MakhotinCommits: 1Joined: 2021-04-06 - *Carmen Bianca BakkerCommits: 1Joined: 2021-04-11 + *Vatsal32Commits: 1Joined: 2021-04-07 - *Steve FanningCommits: 1Joined: 2021-04-11 + *Carmen Bianca BakkerCommits: 1Joined: 2021-04-11 + + *Steve FanningCommits: 1Joined: 2021-04-11 + + + *Joshua WilliamsCommits: 1Joined: 2021-05-22 - - *MarcoFalkeCommits: 1Joined: 2021-06-03 @@ -7422,11 +7524,11 @@ *YakovlevAlCommits: 1Joined: 2021-07-15 + + *Rishav ChattopadhyaCommits: 1Joined: 2021-10-23 - - *mwarnerCommits: 1Joined: 2021-11-25 @@ -7436,11 +7538,11 @@ *Urja RannikkoCommits: 1Joined: 2021-12-05 + + *Krzysztof HałasaCommits: 1Joined: 2021-12-29 - - *altCommits: 1Joined: 2022-01-04 @@ -7450,11 +7552,11 @@ *yaldaCommits: 1Joined: 2022-01-25 + + *javierde22Commits: 1Joined: 2022-01-30 - - *jwtiyar narimanCommits: 1Joined: 2022-02-14 @@ -7464,11 +7566,11 @@ *Łukasz LeszkoCommits: 1Joined: 2022-03-17 + + *Lemures LemniscatiCommits: 1Joined: 2022-03-17 - - *Sarrah BastawalaCommits: 1Joined: 2022-03-21 @@ -7478,11 +7580,11 @@ *Zain IftikharCommits: 1Joined: 2022-04-16 + + *hasban12138Commits: 1Joined: 2022-04-28 - - *Daniel Kamil KozarCommits: 1Joined: 2022-05-03 @@ -7492,25 +7594,25 @@ *Diane LeighCommits: 1Joined: 2022-06-18 + + *Mahdyar M. M. SadeghiCommits: 1Joined: 2022-06-22 - - - *Mahkame ArabgariCommits: 1Joined: 2022-06-22 + *Mahkame ArabgariCommits: 1Joined: 2022-06-22 - *ParsaCommits: 1Joined: 2022-06-25 + *ParsaCommits: 1Joined: 2022-06-25 - *Amir HCommits: 1Joined: 2022-06-25 - - - *m.hashemianCommits: 1Joined: 2022-06-29 + *Amir HCommits: 1Joined: 2022-06-25 + + *m.hashemianCommits: 1Joined: 2022-06-29 + *am.farajiCommits: 1Joined: 2022-07-09 @@ -7520,11 +7622,11 @@ *Ali_AbdollahianCommits: 1Joined: 2022-07-10 + + *Arman RezaeiCommits: 1Joined: 2022-07-11 - - *Thierry EmeryCommits: 1Joined: 2022-08-08 @@ -7534,11 +7636,11 @@ *cutamarCommits: 1Joined: 2022-08-28 + + *Aleksa SavicCommits: 1Joined: 2022-09-02 - - *Ling YangCommits: 1Joined: 2022-09-07 @@ -7548,11 +7650,11 @@ *Nalini Prasad DashCommits: 1Joined: 2022-10-04 + + *Martin SchumannCommits: 1Joined: 2022-10-10 - - *Hemant Kumar SinghCommits: 1Joined: 2022-10-18 @@ -7562,11 +7664,11 @@ *sahilbutoal08Commits: 1Joined: 2022-10-30 + + *Amarjargal GundjalamCommits: 1Joined: 2022-10-31 - - *zonnebloempjeCommits: 1Joined: 2022-11-03 @@ -7576,11 +7678,11 @@ *Jonas EyovCommits: 1Joined: 2022-11-18 + + *ahsmhaCommits: 1Joined: 2022-12-26 - - *Brett T. WardenCommits: 1Joined: 2022-12-30 @@ -7590,11 +7692,11 @@ *ShulhanCommits: 1Joined: 2023-01-12 + + *Devansh JainCommits: 1Joined: 2023-02-04 - - *Greg KelesidisCommits: 1Joined: 2023-02-04 @@ -7604,11 +7706,11 @@ *gokulakrishnan-shankarCommits: 1Joined: 2023-02-16 + + *WANG XueruiCommits: 1Joined: 2023-02-17 - - *Sarthak RoyCommits: 1Joined: 2023-02-23 @@ -7618,11 +7720,11 @@ *Angelle LegerCommits: 1Joined: 2023-03-10 + + *DrGigioSanCommits: 1Joined: 2023-03-14 - - *Nabeel SiddiquiCommits: 1Joined: 2023-03-19 @@ -7632,11 +7734,11 @@ *jpuronahCommits: 1Joined: 2023-04-03 + + *Patrick LubyCommits: 1Joined: 2023-05-04 - - *Cip CipricusCommits: 1Joined: 2023-05-15 @@ -7646,11 +7748,11 @@ *Martin JamborCommits: 1Joined: 2023-06-07 + + *Michel WeimerskirchCommits: 1Joined: 2023-06-09 - - *Joel PuronahoCommits: 1Joined: 2023-06-13 @@ -7660,11 +7762,11 @@ *Denis SorotnikCommits: 1Joined: 2023-08-08 + + *Dung.SagaCommits: 1Joined: 2023-09-06 - - *Cristina MustateaCommits: 1Joined: 2023-09-21 @@ -7674,11 +7776,11 @@ *PowerinnoCommits: 1Joined: 2023-09-23 + + *Willian PessoaCommits: 1Joined: 2023-10-12 - - *Federico Gallo HerosaCommits: 1Joined: 2023-10-13 @@ -7688,11 +7790,11 @@ *U-DESKTOP-CETSUCA\sigmaCommits: 1Joined: 2023-11-06 + + *Frank SteinerCommits: 1Joined: 2023-11-23 - - *Ricardo DoninoCommits: 1Joined: 2023-12-07 @@ -7702,11 +7804,11 @@ *Shachar ShemeshCommits: 1Joined: 2023-12-29 + + *Jamie DouglassCommits: 1Joined: 2024-01-01 - - *alisafayaCommits: 1Joined: 2024-01-07 @@ -7716,11 +7818,11 @@ *Hassan SajjadCommits: 1Joined: 2024-01-29 + + *Adlair Cerecedo-MendezCommits: 1Joined: 2024-01-30 - - *Kevin OttensCommits: 1Joined: 2024-02-02 @@ -7730,11 +7832,11 @@ *tbalajCommits: 1Joined: 2024-03-04 + + *Jonah JanzenCommits: 1Joined: 2024-03-07 - - *Fridrich StrbaCommits: 1Joined: 2024-03-12 @@ -7744,9 +7846,6 @@ *wilmhitCommits: 1Joined: 2024-03-17 - - *Mohit MaratheCommits: 1Joined: 2024-03-20 - @@ -7766,20 +7865,17 @@ *richtrimbleCommits: 1Joined: 2024-06-11 - - *Lars JødalCommits: 1Joined: 2024-07-17 - *Sven GöthelCommits: 1Joined: 2024-08-02 *Evaggelou PanagiotisCommits: 1Joined: 2024-08-06 - - *TH HuangCommits: 1Joined: 2024-08-12 + + *Gülşah KöseCommits: 1Joined: 2024-08-20 @@ -7789,11 +7885,11 @@ *Abraham Samuel AdekunleCommits: 1Joined: 2024-10-12 - - *Barry-Thomas-Paul: MossCommits: 1Joined: 2024-10-14 + + *Abrar EmadCommits: 1Joined: 2024-10-16 @@ -7803,11 +7899,11 @@ *Chris GillCommits: 1Joined: 2024-10-17 - - *Lue_lueitaCommits: 1Joined: 2024-10-25 + + *ZOKCommits: 1Joined: 2024-10-26 @@ -7817,11 +7913,11 @@ *Andre HerbstCommits: 1Joined: 2024-11-03 - - *Harris PopalCommits: 1Joined: 2024-11-05 + + *Ariel DarshanCommits: 1Joined: 2024-11-10 @@ -7831,11 +7927,11 @@ *Sloane VaznovaCommits: 1Joined: 2024-11-17 - - *Avramoniu CalinCommits: 1Joined: 2024-11-27 + + *Daniel FrantesCommits: 1Joined: 2024-12-04 @@ -7845,11 +7941,11 @@ *Robert MuirCommits: 1Joined: 2024-12-18 - - *Alexandre Sena CoelhoCommits: 1Joined: 2024-12-30 + + *Taichi HaradaguchiCommits: 1Joined: 2024-12-31 @@ -7859,11 +7955,11 @@ *sid-sgCommits: 1Joined: 2025-01-11 - - *Chika StarksCommits: 1Joined: 2025-01-21 + + *shrey_223Commits: 1Joined: 2025-02-11 @@ -7873,11 +7969,11 @@ *langtyCommits: 1Joined: 2025-03-08 - - *Muhammad DanishCommits: 1Joined: 2025-03-08 + + *AhmedHamed3699Commits: 1Joined: 2025-03-11 @@ -7887,11 +7983,11 @@ *Haokun WuCommits: 1Joined: 2025-03-22 - - *Rohan SinhaCommits: 1Joined: 2025-03-30 + + *Emmanuel DreyfusCommits: 1Joined: 2025-04-10 @@ -7901,11 +7997,11 @@ *Vlad EneCommits: 1Joined: 2025-04-26 - - *Musuroi David-GabrielCommits: 1Joined: 2025-05-08 + + *Sebastian NeaguCommits: 1Joined: 2025-05-09 @@ -7915,11 +8011,11 @@ *Alexandru DiaconuCommits: 1Joined: 2025-05-11 - - *marus087Commits: 1Joined: 2025-05-12 + + *Razvan DegeratuCommits: 1Joined: 2025-05-13 @@ -7929,11 +8025,11 @@ *Rania AminaCommits: 1Joined: 2025-05-13 - - *sshheebbeeCommits: 1Joined: 2025-06-09 + + *Laurent DEBOMYCommits: 1Joined: 2025-06-11 @@ -7943,11 +8039,11 @@ *Adam JonesCommits: 1Joined: 2025-07-19 - - *Alex BereaCommits: 1Joined: 2025-07-30 + + *sahibjotCommits: 1Joined: 2025-07-31 @@ -7957,11 +8053,11 @@ *JaapCommits: 1Joined: 2025-08-03 - - *Nilesh PatraCommits: 1Joined: 2025-08-18 + + *noahCommits: 1Joined: 2025-10-02 @@ -7971,11 +8067,11 @@ *Nastasie Raul-IonutCommits: 1Joined: 2025-10-15 - - *Shantanu OakCommits: 1Joined: 2025-10-23 + + *tuanornCommits: 1Joined: 2025-10-26 @@ -7985,11 +8081,11 @@ *MishaCommits: 1Joined: 2025-11-06 - - *Vissarion FisikopoulosCommits: 1Joined: 2025-11-12 + + *NguyenCommits: 1Joined: 2025-11-15 @@ -7999,11 +8095,11 @@ *Neacsa LeonardCommits: 1Joined: 2025-11-22 - - *NicuCommits: 1Joined: 2025-11-29 + + *sebastiangm15Commits: 1Joined: 2025-12-01 @@ -8013,11 +8109,11 @@ *Teodora StefanCommits: 1Joined: 2025-12-03 - - *Elena LivadaruCommits: 1Joined: 2025-12-06 + + *Alexandru VasilescuCommits: 1Joined: 2025-12-07 @@ -8027,27 +8123,13 @@ *Aditya LohuniCommits: 1Joined: 2025-12-28 - - *Jonathan WakelyCommits: 1Joined: 2026-01-14 - - *Masayuki IizukaCommits: 1Joined: 2026-01-15 - - - *TriyambakCommits: 1Joined: 2026-01-20 - - - *OUBOUSKEN ILYASCommits: 1Joined: 2026-02-08 - - *Moritz DugeCommits: 1Joined: 2026-02-08 - - - *Ivan Vladimirovich KuznetsovCommits: 1Joined: 2026-02-16 + *TriyambakCommits: 1Joined: 2026-01-20 *Māris NartišsCommits: 1Joined: 2026-02-18 @@ -8055,6 +8137,9 @@ *Vaasu KCommits: 1Joined: 2026-02-21 + + *Tomaž VajngerlCommits: 1Joined: 2026-02-23 + @@ -8064,28 +8149,140 @@ *Thomas RogenmoserCommits: 1Joined: 2026-02-23 - *Jonas GreifenhainCommits: 1Joined: 2026-03-04 + *Tomaž VajngerlCommits: 1Joined: 2026-03-02 - *Liam ConnorsCommits: 1Joined: 2026-03-09 + *Jonas GreifenhainCommits: 1Joined: 2026-03-04 + + *Rachit AroraCommits: 1Joined: 2026-03-05 + *lancebordCommits: 1Joined: 2026-03-11 - *yaswantpenapakaCommits: 1Joined: 2026-03-12 + *Saburo YoshidaCommits: 1Joined: 2026-03-13 - *RashmiCommits: 1Joined: 2026-03-13 + *Garv GuptaCommits: 1Joined: 2026-03-17 - - + + + + *Shubham ShrivastavCommits: 1Joined: 2026-03-18 + + + *RaquelZuelkeCommits: 1Joined: 2026-03-22 + + + *Shoaib SamimCommits: 1Joined: 2026-03-23 + + + *LinuxUserGDCommits: 1Joined: 2026-03-28 + + + + + *bl4ze4447Commits: 1Joined: 2026-04-04 + + + *prajwalshelarCommits: 1Joined: 2026-04-05 + + + *Robert MarcanoCommits: 1Joined: 2026-04-06 + + + *Ferdinand GassauerCommits: 1Joined: 2026-04-13 + + + + + *Thomas TempelmannCommits: 1Joined: 2026-04-16 + + + *SapphireCommits: 1Joined: 2026-04-25 + + + *Sara NitaCommits: 1Joined: 2026-04-25 + + + *subhanigcCommits: 1Joined: 2026-04-26 + + + + + *Cristina CretuCommits: 1Joined: 2026-04-26 + + + *zanairaCommits: 1Joined: 2026-04-27 + + + *Mihnea JianuCommits: 1Joined: 2026-04-30 + + + *fatimaahmedCommits: 1Joined: 2026-05-02 + + + + + *Alexandru OgrezeanuCommits: 1Joined: 2026-05-06 + + + *Rareș-Constantin RîjnițăCommits: 1Joined: 2026-05-08 + + + *DamianAlexandruGusatuCommits: 1Joined: 2026-05-08 + + + *Bianca MilitaruCommits: 1Joined: 2026-05-09 + + + + + *Jean-Michel HautboisCommits: 1Joined: 2026-05-09 + + + *Noel GrandinCommits: 1Joined: 2026-05-10 + + + *Lucas-Adrian NegreaCommits: 1Joined: 2026-05-12 + + + *Michael MasseeCommits: 1Joined: 2026-05-12 + + + + + *Dmitry KulikovCommits: 1Joined: 2026-07-23 + + + *anubhavjha0812Commits: 1Joined: 2026-08-04 + + + *Süleyman ÇobanCommits: 1Joined: 2026-08-05 + + + *SundaramCommits: 1Joined: 2026-08-09 + + + + + *Ramil NurmanovCommits: 1Joined: 2026-08-19 + + + *Lars BungumCommits: 1Joined: 2026-08-22 + + + *janCommits: 1Joined: 2026-09-01 + + + *Henry CastroCommits: 1Joined: 2026-09-07 - Contributors to bundled templates + Contributors to bundled templates @@ -8093,7 +8290,7 @@ - *Laurent BallandCommits: 78Joined: 2023-06-02 + *Laurent BallandCommits: 83Joined: 2023-06-02 *Laurent BPCommits: 60Joined: 2015-11-19 @@ -8151,17 +8348,20 @@ *Yousuf PhilipsCommits: 2Joined: 2016-10-18 + + *Gabor KelemenCommits: 2Joined: 2023-08-10 + *Francisco SaitoCommits: 1Joined: 2011-03-29 *Michael MuenchCommits: 1Joined: 2011-06-09 + + *Michael StahlCommits: 1Joined: 2012-03-23 - - *Stefan Knorr (astron)Commits: 1Joined: 2012-07-16 @@ -8171,11 +8371,11 @@ *Péter SzathmáryCommits: 1Joined: 2015-01-07 + + *Edmund LaugassonCommits: 1Joined: 2015-01-07 - - *Michael KovarikCommits: 1Joined: 2015-01-07 @@ -8185,11 +8385,11 @@ *Tomaž VajngerlCommits: 1Joined: 2015-04-22 + + *Mike KaganskiCommits: 1Joined: 2019-03-13 - - *Rizal MuttaqinCommits: 1Joined: 2020-05-04 @@ -8199,9 +8399,6 @@ *Henry CastroCommits: 1Joined: 2023-02-20 - - *Gabor KelemenCommits: 1Joined: 2023-08-10 - @@ -8213,8 +8410,8 @@ *Xisco FauliCommits: 1Joined: 2025-06-26 - - *Gabor KelemenCommits: 1Joined: 2025-07-03 + + @@ -8389,7 +8586,7 @@ Gerd WeissCommits: 45Joined: 2007-04-26 - Armin TheissenCommits: 44Joined: 2000-09-22 + Armin TheissenCommits: 43Joined: 2000-10-25 @@ -8680,12 +8877,12 @@ gh93821Commits: 1Joined: 2010-04-09 - + - Contributors to bundled templates + Contributors to bundled templates @@ -8724,7 +8921,7 @@ Volker Ahrendt [va]Commits: 2Joined: 2002-05-29 - + @@ -8741,7 +8938,7 @@ Do note that LibreOffice used to be divided into 20 git repositories. Pushing a change into all repositories will be counted as 20 commits as there is no way to distinguish this from 20 separate commits. Total contributions to the TDF Wiki - 3025 individuals contributed: + 3059 individuals contributed: @@ -8749,69 +8946,69 @@ - Beluga (89228) + Beluga (89586) - Hrbrgr (73729) + Hrbrgr (78979) - Marric (29476) + Marric (29529) + + + Bammbamm7 (27736) + + + + + HanV (25847) SteenRønnow (25769) - - - HanV (25651) + Raal (25241) - Bammbamm7 (25104) - - - Raal (24964) - - - Manuelf (21243) + Manuelf (21250) - Akurery (17952) + Akurery (18382) - Bantoniof (13289) + Bantoniof (13458) - Filmsi (10684) + Filmsi (10957) Pierre-yves samyn (10099) + + Jayme Barrientos, Adolfo (9858) + K-j (9376) - Jayme Barrientos, Adolfo (9095) - - - Gautier, Sophie (8871) + Gautier, Sophie (8936) Stevefanning (8845) + + Roczek, Dennis (8494) + Penny (8374) - Roczek, Dennis (8334) - - - Nobu (7634) + Nobu (7841) Kelemeng (6993) @@ -8821,17 +9018,20 @@ Goncharuk, Lera (5436) + + VMelnik (5410) + Nogata Jun (5322) - Yaron (4860) - - - Balland-Poirier, Laurent (4669) + Balland-Poirier, Laurent (4959) + + Yaron (4887) + Kü (4614) @@ -8839,10 +9039,7 @@ Uroveits (4573) - Kompilainenn (4464) - - - VMelnik (4448) + Kompilainenn (4467) @@ -8850,7 +9047,7 @@ Martin187 (4220) - Noorikhah, Hossein (3925) + Noorikhah, Hossein (3937) Tagezibot (3924) @@ -8867,7 +9064,7 @@ Brumla132 (3708) - Ady (3320) + Ady (3322) Jeanweber (3303) @@ -8878,10 +9075,10 @@ Rizmut (3295) - Hibagonsan (3073) + Prcek (3085) - Prcek (2958) + Hibagonsan (3073) TseRig (2777) @@ -8889,44 +9086,44 @@ - LibreOfficiant (2690) + Hallot, Olivier (2746) - Hallot, Olivier (2660) + LibreOfficiant (2723) - LobaLuna (2463) + LobaLuna (2636) - Lyzbet (2440) + Lyzbet (2511) + + Enoki (2427) + PlateauWolf (2423) - X1sc0 (2353) + X1sc0 (2402) Ronnie rg8888 (2352) - - Horáček, Stanislav (2349) - - Enoki (2322) + Horáček, Stanislav (2349) Diegoperesmarques (2207) - Bielefeld, Rainer (2077) + Junmeguro (2150) - Junmeguro (1977) + Bielefeld, Rainer (2077) @@ -8934,7 +9131,7 @@ Effenberger, Florian (1811) - Henschel, Regina (1733) + Henschel, Regina (1742) Haradaguchi, Taichi (1568) @@ -8959,7 +9156,7 @@ - GerryT (1381) + GerryT (1382) ManuelBax (1262) @@ -8968,7 +9165,7 @@ Naruoga (1239) - Buzzatti Pacheco, Gustavo (1211) + Buzzatti Pacheco, Gustavo (1214) @@ -8987,33 +9184,36 @@ - So (1115) + Firelinux (1127) + + + Tietze, Heiko (1122) + + + So (1121) Haas, Uwe (1095) - - Tietze, Heiko (1079) - - - Clement21.philippe (1076) - - Firelinux (1048) + Clement21.philippe (1076) E.le-gall (1027) - Ostrovsky, David (1011) + TseRigs (1027) - Novak, Nino (976) + Ostrovsky, David (1011) + + Novak, Nino (976) + Meeks, Michael (964) @@ -9023,67 +9223,67 @@ Guillou, Stéphane (895) + + LLAP016 (875) + + Drodriguez (853) + + + RobertG (852) + + + Mike.saunders (838) + - RobertG (843) + Kees538 (835) Elianedomingos (834) - - Mike.saunders (817) - H-k (804) - - - - Kees538 (795) - Behrens, Thorsten (751) + + Drew (748) Maintenance script (747) - - Mantke, Andreas (742) + + Lachend (736) + + + Teo91 (733) - McNamara, Caolán (730) + McNamara, Caolán (732) Jmpierre (729) - - - - Drodriguez (725) - Valjanovickova (715) + + Vajna, Miklos (709) - - Lachend (700) - - - Iversen, Jan (693) @@ -9093,25 +9293,25 @@ Floris v (661) + + Hazel (639) - - Sam m (613) - Elmau (609) + Elmau (610) Jlv (603) - - Lohmaier, Christian (597) - + + Lohmaier, Christian (602) + Jmadero (596) @@ -9121,39 +9321,53 @@ Dhsung (559) + + ChristophNoack (549) - - Paulo (546) + + Bpeel (540) + JO3EMC (537) + + Kaganski, Mike (522) Knorr, Stefan (521) - - + + Petr-valach (520) + Davidnelson (517) + + Foote, V Stuart (515) - Stahl, Michael (504) + Kitaygrad (512) - Reisinger, Florian (491) + Lj LO (512) + + + Stahl, Michael (504) + + Reisinger, Florian (491) + Elcico (482) @@ -9163,9 +9377,6 @@ Jana.urbanova (478) - - Petr-valach (476) - @@ -9174,17 +9385,14 @@ Hellotheworld (471) - - Kitaygrad (466) - Sefran (466) - - Philips, Yousuf (462) + + Holešovský, Jan (451) @@ -9194,19 +9402,22 @@ Eskroni (437) + + Rmfaile (436) + - Rmfaile (436) + Timotheonb (432) Kara, Muhammet (429) - Timotheonb (429) + Naniud (429) - Libo02 (422) + Libo02 (425) @@ -9220,7 +9431,7 @@ Yoshida, Kohei (419) - Kosiorek, Bartosz (409) + Kosiorek, Bartosz (418) @@ -9234,10 +9445,13 @@ Schiavinatto (401) - Mohrhard, Markus (397) + Herissongrognon (398) + + Mohrhard, Markus (397) + AndrasTimar (394) @@ -9247,9 +9461,6 @@ Tardon, David (388) - - Naniud (388) - @@ -9258,17 +9469,14 @@ Roman (384) - - Herissongrognon (382) - Opensoftpl (381) - - StefanW (379) + + LenkaD (377) @@ -9278,11 +9486,11 @@ Felipeviggiano (371) - - Thackert (359) + + Mayan Tigger (347) @@ -9292,11 +9500,11 @@ Cheche (336) - - Vpanter (333) + + Pruegsanusak, Korrawit (330) @@ -9306,13 +9514,16 @@ Wget (323) - - Arranna (322) + + - Fpy (308) + Fpy (309) + + + Mbalabanov (309) Donaldo (305) @@ -9325,17 +9536,20 @@ Bergmann, Stephan (304) + + YALÇINSOY, Ayhan (300) + Ysabeau (299) Mars (295) + + Lillqvist, Tor (294) - - Tseng, Cheng-Chia (294) @@ -9345,11 +9559,11 @@ Librelegal (292) + + Emanuel A. Marcatinco B. (290) - - Vignoli, Italo (287) @@ -9359,13 +9573,10 @@ Krypton (283) - - HARA (279) - - YALÇINSOY, Ayhan (269) + HARA (279) Epix (268) @@ -9378,9 +9589,6 @@ - - Mbalabanov (265) - Lodahl (264) @@ -9390,11 +9598,11 @@ Twistios (259) - - SophieSipasseuth (256) + + Remarques (252) @@ -9404,11 +9612,11 @@ Adrianoafonso (246) - - Nemeth (246) + + Óvári (246) @@ -9418,6 +9626,9 @@ Franklin (242) + + Jeanmi2403 (241) + @@ -9426,17 +9637,14 @@ EricBright (238) - - Jeanmi2403 (237) - Steve (237) - - Valtermura (234) + + Hogue (233) @@ -9446,11 +9654,11 @@ Mesho (233) - - Bosdonnat, Cédric (231) + + Bedipp (226) @@ -9460,11 +9668,11 @@ Kerwyn (221) - - Almusaireae (219) + + Kkwet38 (218) @@ -9474,42 +9682,45 @@ Khirano (215) - - Latini, Marina (213) - - Lj LO (213) - + + Babinecm (212) Jodi999 (211) - - ZuzuN (208) Andreschnabel (207) + + Daveb (207) XsLiDian (203) - - + + Ponzo, Gabriele (200) + Kirk (200) + + Steinzeit (200) + + Tjhietala (198) + Wheatbix (198) @@ -9519,10 +9730,10 @@ - Tjhietala (193) + Schulz, Charles-H. (191) - Schulz, Charles-H. (191) + AndikaTriwidada (190) DmitryBowie (188) @@ -9552,17 +9763,14 @@ Madl, Tobias (175) - - Ponzo, Gabriele (173) - Det (172) - - Fridrich (172) + + Luizheli (172) @@ -9572,17 +9780,20 @@ N.yadi (171) - - Furusho (170) + + Pitkänen, Harri (169) Jiang, Yifan (168) + + Den kho (167) + Scoelho (166) @@ -9598,19 +9809,19 @@ Ckhe1215 (162) - AndikaTriwidada (161) + See (160) - - See (160) - Snelders, Rob (159) Hagar Delest (159) + + Jstnlth (157) + Veronika.zacna (155) @@ -9630,6 +9841,9 @@ + + Zolnai, Tamás (152) + Goodlinuxuser (151) @@ -9639,16 +9853,10 @@ Slacka (150) - - Stephan.ficht (150) - - Zolnai, Tamás (150) - - - Jstnlth (149) + Stephan.ficht (150) Herzog, Christoph (149) @@ -9656,11 +9864,11 @@ Momo50 (148) - - Chris-hoh (147) + + Back69 (146) @@ -9670,11 +9878,11 @@ Mipmap (144) - - Guilhem (141) + + Michelr (141) @@ -9684,11 +9892,11 @@ Nabet, Julien (140) - - Gurbetoğlu, Gökhan (139) + + De Cuyper, Joren (138) @@ -9698,11 +9906,11 @@ Rutilus (138) - - Abe, Takeshi (138) + + Heliojsf (137) @@ -9712,11 +9920,11 @@ Pepeleduin (137) - - Norah (135) + + Shunesburg69 (135) @@ -9726,11 +9934,11 @@ Filhocf (132) - - Llunak (132) + + Davydych (131) @@ -9740,11 +9948,11 @@ Richteruwe (131) - - Mxodo (130) + + Michel, Mathias (129) @@ -9754,11 +9962,11 @@ Ki Drupadi (127) - - Nik (127) + + Baffclan (126) @@ -9768,22 +9976,28 @@ JARF (123) - - Krackedpress (123) + + Psluk (123) Igor001 (122) + + Piotr285 (122) + Trapezus (122) + + ButterflyOfFire (121) + MariusConstantinPopa (121) @@ -9793,28 +10007,36 @@ Liebel, Jennifer (119) + + Phorious (118) - - + + PrasantaHembram (118) + Ipitl (117) Lqju96 (117) + + Spaeth, Sebastian (115) Markers (114) - - Massimo.zaffaina (113) + + Weghorn, Michael (113) + + + PulkitKrishna00 (113) @@ -9824,11 +10046,11 @@ Marcus Gama (112) - - MichaMuc (112) + + Paour (112) @@ -9838,25 +10060,25 @@ Bachka (111) - - Dougvigliazzi (111) + + Medieval (111) - - Weghorn, Michael (111) - Monthoflibreoffice bot (110) - - Dededudu (108) + + Mingu03 (108) + + + Nyucel (108) @@ -9866,11 +10088,11 @@ Irdi (106) - - Bitsfritz (104) + + Klaibson (104) @@ -9880,39 +10102,39 @@ Pechlaner, Wolfgang (102) - - JZA (101) - - Piotr285 (101) - + + Quikee (101) WillZ (100) - - Android272 (99) JeHa (99) + + AlanC (98) Fišeras, Aurimas (97) - - + + Geraldg (96) + Dan (95) + + Lucaeva03 (95) @@ -9922,227 +10144,230 @@ Boopalan (94) - - - - Geraldg (94) - Köse, Gülşah (94) + + Barbora (93) MagicFab (93) - - Andreasg (92) Lekle (92) + + Atalanttore (90) Frombenny (90) - - Richv2 (90) Zeki (89) + + Catalin Festila (88) Hertel, Jesper (88) - - Milos (87) Paulojose (87) + + Pomodoren (87) Omori (86) - - Steve- - (86) Eddy (85) + + Evy (84) Jfnif (84) - - KorrawitBot (84) Santhab (84) + + Enio.gemmo (83) - ButterflyOfFire (82) + PhL38Fr (83) - - Ogervasi (82) JamesWalker (81) + + Xosé (80) 80686 (79) - - KeithCu (79) Kjh000121 (79) + + Laveni (79) CharlieRamirezAnimationStudiosMX (78) - - Jwtiyar (78) Marcio Oliveira (78) + + Northwoods35 (78) Ocleyr2lalune (78) - - Uwealtmann (78) Socetk (77) + + Tommy.WU (77) Albino (75) - - K.K.Ashisuto (75) Emoreno (74) + + Lbalbalba (74) Namikawamisaki (73) - - Rachel618 (73) Castermans, Luc (72) + + Grgml (72) Aury88 (71) - - RalfHB (71) Sawakaze (71) + + Al-Harthi, Ahmad Hussein (70) Jo7ueb (70) - - Malhassoun (69) Moonju (69) + + Freetank (68) Fábio Farias (68) - - Gghh (68) SoNick RND (68) + + Ptux (67) + + Xperro (67) + Karbasion, Bersam (65) - - Bmcs (65) + + Kabe (65) StanG (65) + + Chealer (64) + Glogowski, Jan-Marek (64) @@ -10190,6 +10415,9 @@ + + Juanjosegzl (61) + Arnaudlecam (60) @@ -10199,16 +10427,13 @@ Grandin, Noel (60) - - Jlgrenar (60) - - Montané, Joan (60) + Jlgrenar (60) - Juanjosegzl (60) + Montané, Joan (60) OctopusET (60) @@ -10218,6 +10443,9 @@ + + Ledure, Jean-Pierre (59) + Justman10000 (59) @@ -10227,11 +10455,11 @@ Camillem (58) + + Neel, Daniel (58) - - Kougen250T (58) @@ -10241,9 +10469,6 @@ Kukan, Matúš (58) - - Ledure, Jean-Pierre (57) - @@ -10252,17 +10477,14 @@ Bubli (56) - - Chealer (56) - Davefilms (56) - - Glen.reesor (56) + + Tomoyuki, Kubota (56) @@ -10272,17 +10494,20 @@ Ramtk6726 (56) - - Hunt, Andrzej (55) + + Fifh (55) Jrahemipour (55) + + Sotrud nik (55) + Brockendorph (54) @@ -10309,13 +10534,16 @@ Sunny2038 (53) - Lendo (52) + Kheyyam (52) - Petrizzo (52) + Lendo (52) + + Petrizzo (52) + ArnoldSchiller (51) @@ -10325,11 +10553,11 @@ Jaani (51) + + Quoifleur (51) - - Agd (50) @@ -10339,11 +10567,11 @@ Paz (50) + + Ronaldo (50) - - SeoYeonJin (50) @@ -10353,11 +10581,11 @@ Magliocchetti, Riccardo (49) + + Serbul (49) - - Vardomescro (49) @@ -10367,39 +10595,39 @@ Lviktoria (48) - - Mateusdemelo (48) - + + Mateusdemelo (48) + + + A012-alex (47) + + + Arnaud versini (47) + Dagobert 78 (47) + + Jhannine20 (47) - - PrasantaHembram (47) - Quest-88 (47) - - Buj Gelonch, Robert Antoni (47) Amtliz (46) - - Arnaud versini (46) - + + FloF (46) - - Ikks (46) @@ -10409,41 +10637,38 @@ Sk94 (46) + + Sveinki (46) - - + + Budea, Áron (45) + Bfo (45) Kghbln (45) + + Hosny, Khaled (45) Lua (45) - - Meskobalazs (45) - - Mingu03 (45) - Jung, Philippe (45) - - Robwestein (45) - - Budea, Áron (44) + Robwestein (45) Bhorst (44) @@ -10515,17 +10740,20 @@ Cawe (41) + + Gilward Kukel (41) + Joey (41) Marklh9 (41) + + Pedlino (41) - - Raniaamina (41) @@ -10535,23 +10763,34 @@ Kraucer (40) - - Gilward Kukel (39) - + + Bittin (39) + + + Jimwormold (39) + PaxGourou (39) Valdirbarbosa (39) + + Enervation (38) Kłos, Szymon (38) + + M42 (38) + + + Mike888 (38) + @@ -10603,30 +10842,41 @@ RegisPerdreau (37) - Sistemo2021 (37) + Sidi (37) - Sherlock, Chris (37) + Sistemo2021 (37) + + Sherlock, Chris (37) + + + Wodsfort (37) + Caco13 (36) Danishka (36) + + + + EyalRozenberg (36) + Patheticcockroach (36) Sci citation (36) - - Thep (36) + + Yan Pashkovsky (36) @@ -10636,11 +10886,11 @@ Andreas ka (35) - - Liongold (35) + + Marinello, Marco (35) @@ -10650,36 +10900,28 @@ Nora (35) - - Pingping111 (35) + + Stalker08 (35) Subramanian, Muthu (35) - - Kheyyam (34) - - - Skagh1750 (34) Bormant (33) + + Davidlamhauge (33) - - EyalRozenberg (33) - - - FelipeAle (33) @@ -10689,11 +10931,11 @@ Lmartinezh (33) + + Mateus.m.luna (33) - - Ngoclong19 (33) @@ -10703,11 +10945,11 @@ Pereriksson (33) + + Ptoye (33) - - Rafi (33) @@ -10717,11 +10959,11 @@ Alexanderwerner (32) + + Clio (32) - - Daud (32) @@ -10731,11 +10973,11 @@ Laquin (32) + + Lenochod (32) - - Dryomov, Artur (32) @@ -10745,11 +10987,11 @@ Vulcain (32) + + Xuacu (32) - - Alkos85 (31) @@ -10759,11 +11001,11 @@ H (31) + + IvanM (31) - - Kant, Pranav (31) @@ -10773,11 +11015,11 @@ Am97 (30) + + Maose (30) - - Njsg (30) @@ -10787,11 +11029,11 @@ Speck (30) + + Tclovis (30) - - Thardeck (30) @@ -10801,11 +11043,11 @@ Cida.Coltro (29) + + Darbe (29) - - EdvaldoSCruz (29) @@ -10815,11 +11057,11 @@ Haaninjo (29) + + RodolfoRG (29) - - Серж (29) @@ -10829,42 +11071,50 @@ Riemer, Philipp (28) + + Lutch (28) - - PaoloPelloni (28) + + Vasiliu, Mihai Alexandru (28) + المسيكين (28) + + Marcofilippozzi (27) Marcos Paulo de Souza (27) - - Micm (27) PeppinoLib (27) + + Sarojdhakal (27) Thuswaldner, Albert (27) - - Alayaran (26) + + DrRobotto (26) + + + Eresus (26) @@ -10874,6 +11124,9 @@ Fanch (26) + + Jclark (26) + @@ -10953,13 +11206,16 @@ Schröder, Sophia (25) - Winniemiel05 (25) + Webmink (25) - Magee, Timothy (24) + Winniemiel05 (25) + + Magee, Timothy (24) + Brlin (24) @@ -10969,11 +11225,11 @@ Gaianer (24) + + Gérard24 (24) - - Ksoviero (24) @@ -10983,25 +11239,25 @@ Olivier (24) + + Usbee (24) - - Hamurcu (23) + + Jdittrich (23) + Keymap19 (23) - - Lostinthiswhirlpool (23) - - - M42 (23) - + + Lostinthiswhirlpool (23) + Olorin (23) @@ -11011,11 +11267,11 @@ Squenson (23) + + TaeWong (23) - - Team One (23) @@ -11025,16 +11281,13 @@ Tommy27 (23) - - Toxitom (23) - - Trueriver (23) + Toxitom (23) - Webmink (23) + Trueriver (23) Youngman, Anthony W. (23) @@ -11068,139 +11321,150 @@ JChimene (22) - Lothar.becker (22) + Laitei (22) + + Lothar.becker (22) + Gmicsko (21) Johannes (21) + + LibreOfficeUser25 (21) + + + Liusiqi43 (21) Logisch dede (21) - - Pinto, Marco A.G. (21) Monastirsky, Maxim (21) + + Necdetyucel (21) Puster (21) - - Shiko (21) Svante (21) + + Twistappel (21) WalterPape (21) - - Wayra (21) Bugmenot (20) + + Dennisfrancis (20) Doležal, Vojtěch (20) - - Grasip (20) Grzesiek a (20) + + HeinF (20) Icobgr (20) - - Funk, Juergen (20) Kendram (20) + + LLyaudet (20) Mattsturgeon (20) - - PRosmaninho (20) Pandajbc (20) + + Vdragon (20) Vmalep (20) - - Webham (20) XMatence (20) + + Yorick (20) Zapata (20) - - Zipjebt (20) A-zakh (19) + + Chernik (19) Clarice Vigliazzi (19) - - + + Giosal (19) + Guateconexion (19) + + Houbsi (19) @@ -11210,11 +11474,11 @@ Jem (19) - - Juergenfenn (19) + + Kentarch (19) @@ -11224,36 +11488,28 @@ PeeWee (19) - - Shantanuo (19) + + Ionita, Teodor-Mircea (19) - - Sotrud nik (19) - Xiaoransun (19) - - - - DrRobotto (18) - Ehsan.movahed (18) Hidayet (18) + + Jstaerk (18) - - Narayan (18) @@ -11263,11 +11519,11 @@ Power, Noel (18) + + Richard (18) - - Serge Krot (18) @@ -11277,11 +11533,11 @@ UriHerrera (18) + + Vuhung (18) - - Yusufketen (18) @@ -11291,11 +11547,11 @@ Akerbeltz (17) + + Bvarga91 (17) - - Chd (17) @@ -11305,11 +11561,11 @@ Dlmoretz (17) + + Ertsey, Andor (17) - - Guilherme.vanz (17) @@ -11319,11 +11575,11 @@ Kingu (17) + + Tõnnov, Mihkel (17) - - Prrvchr (17) @@ -11333,11 +11589,11 @@ Sohyun99 (17) + + Taken (17) - - Uli.l (17) @@ -11347,11 +11603,11 @@ Yumakino (17) + + Беломир (17) - - Airon90 (16) @@ -11361,11 +11617,11 @@ Dhersh (16) + + Elucches (16) - - Janus (16) @@ -11375,11 +11631,11 @@ Oweng (16) + + P.Guimberteau (16) - - PauGNU (16) @@ -11389,20 +11645,17 @@ Ristoi (16) + + Smarquespt (16) - - Smrabelo (16) TPJ (16) - - Wodsfort (16) - APerson (15) @@ -11464,6 +11717,9 @@ + + Ravi (15) + Royerjy (15) @@ -11473,11 +11729,11 @@ Ulf hamburg (15) + + Yecril21pl (15) - - 暗影遺言 (15) @@ -11487,11 +11743,11 @@ AliIsingor (14) + + Brett (14) - - Darkcircle (14) @@ -11501,11 +11757,11 @@ Fina (14) + + Francis59 (14) - - Guuml (14) @@ -11515,9 +11771,6 @@ Lfernandocarvalho (14) - - LibreOfficeUser25 (14) - @@ -11593,20 +11846,17 @@ Gallaecio (13) - - Jclark (13) - Jobo (13) Kadekilo (13) - - Leomota (13) + + Ljelly (13) @@ -11616,11 +11866,11 @@ Mabbb (13) - - Mikeyy (13) + + Mortense (13) @@ -11630,302 +11880,294 @@ Pete Boyd (13) - - - - Ravi (13) - S.Gecko (13) + + Samtuke (13) Sanyii (13) - - Simplicity Instinct (13) Susanne (13) + + ThierryM (13) Tnishiki (13) - - Tusharrai2017 (13) Vivaelcelta (13) + + Vkkodali (13) A8 (12) - - Alfabech (12) And471 (12) + + AustinW (12) Bhaskar (12) - - Cepiloth (12) Chris2020 (12) + + Cono (12) Cralin (12) - - Debring (12) Al-Otaibi, Faisal M. (12) + + Halan (12) Immanuelg (12) - - Kikopb (12) Krabina (12) + + Šebetić, Krunoslav (12) Godard, Laurent (12) - - Mapasc (12) Rimkus, Modestas (12) + + Nandar (12) Pcapeluto (12) - - Gupta, Rachit (12) Raruenrom, Samphan (12) + + Möller, Sören — spelled Soeren Moeller in some patches (12) Staticsafe (12) - - Melenchuk, Vasily (12) Veerh01 (12) + + 翼之靈歌 (12) Bryanquigley (11) - - Cdan (11) ChristopheS (11) + + Dajare (11) Ebraminio (11) - - Eduaraujo (11) Francoisa (11) + + Gokul, S (11) Hub (11) - - Johnny M (11) Kallecarl (11) + + Kolbjoern (11) Ksso (11) - - Leatherbottle (11) Luiz Henrique Natalino (11) + + MNeto (11) Pearson, Timothy (11) - - Marco c (11) Marcuskgosi (11) + + NON (11) Johansson, Niklas (11) - - Nuernbergerj (11) PaoloVecchi (11) + + Rogeniobelem (11) Salmaan (11) - - Spyros (11) Sunk8 (11) + + Gomez, Andres (11) Vrlivre (11) - - Zentrocdot (11) Zero0w (11) + + Aeusebio (10) Algotruneman (10) - - Antonio.duailibe (10) Castagno, Giuseppe (10) + + Blargh (10) ChrSchultz (10) - - Diginin (10) Eagles051387 (10) + + Eduardogula (10) Eficheux (10) - - El7r (10) J.baer (10) - - Jdittrich (10) - + + Joacim (10) - - Kadertarlan (10) @@ -11935,11 +12177,11 @@ Linuxuser330250 (10) + + Lionlinux (10) - - Mesutcfc (10) @@ -11949,11 +12191,11 @@ Mikalai (10) + + Morvan (10) - - Mpumrlova (10) @@ -11963,11 +12205,11 @@ Olea (10) + + Otto (10) - - Predatorix (10) @@ -11977,140 +12219,148 @@ Ronja (10) + + Rpr (10) - - Tatat (10) + + Tigranz (10) + Tomg (10) + + Ttocsmij (10) Twstdude0to1 (10) - - User8192 (10) Wlenon (10) + + §chinagl (10) Al-Abdulrazzaq, Abdulmajeed (9) - - Agger (9) Aicra (9) + + Brandner, Andreas (9) AtkinsSJ (9) - - Camargo (9) Cnuss (9) + + Compressor nickel (9) Crazyskeggy (9) - - Dupreyb (9) Fatdf (9) + + Gibi (9) GisbertFriege (9) - - Goranrakic (9) Jim-BobHarris (9) + + Jonatoni (9) Jopsen (9) - - Jowyta (9) Karmavil (9) + + Duge, Moritz (9) Kscanne (9) - - Lapetec (9) Lexeii (9) + + Mapper (9) Marco (9) - - Meo (9) MertTumer (9) + + Mhonline (9) Msaffron (9) - - + + Nezhasantaizi (9) + Ohnemax (9) + + Onting (9) @@ -12120,11 +12370,11 @@ Milvaques, Pasqual (9) - - Foley, Peter (9) + + Pixpray (9) @@ -12134,11 +12384,11 @@ Rantaro (9) - - Raykowj (9) + + Rogawa (9) @@ -12148,11 +12398,11 @@ Spacebat (9) - - Therabi (9) + + Urdulizer (9) @@ -12162,11 +12412,11 @@ Zhangxiaofei (9) - - ميدو (9) + + Alexxed (8) @@ -12176,10 +12426,13 @@ AndreasL (8) + + Ausserirdischegesund (8) + - Ausserirdischegesund (8) + CassieLX (8) Cocofan (8) @@ -12209,17 +12462,20 @@ Horst (8) + + InspiringNameGoesHere (8) + Israel Chaves (8) JR (8) + + Jiero (8) - - Jrsiqueira (8) @@ -12229,70 +12485,78 @@ Hoffimann Mendes, Júlio (8) + + + + Kachelkaiser (8) + Dywan, Christian (8) - - Kednar (8) Rietveld, Kristian (8) + + Lee (8) Leigh, Jack (8) - - Leo.h.hildebrandt (8) LucasLibre (8) + + Luisgulo (8) Manj k (8) - - Mrmox2 (8) NightMonkey (8) + + NirajanPant (8) Osnola (8) - - Paulo.tavares (8) Perro (8) + + Peterpall (8) Ricardolau (8) - - + + Taraijpn (8) + Thejack (8) + + Tibbylickle (8) @@ -12302,11 +12566,11 @@ UserUnknown (8) - - Vbkaisetsu (8) + + VlhOwn (8) @@ -12316,11 +12580,11 @@ Yakusha (8) - - Yellow.h (8) + + Yostane (8) @@ -12330,11 +12594,11 @@ Ahiijny (7) - - Andrea.soragna (7) + + Bastik (7) @@ -12344,11 +12608,11 @@ Berrykevin (7) - - Bjherbison (7) + + Bookman900 (7) @@ -12358,11 +12622,11 @@ Capiscuas (7) - - Chin Zee Yuen (7) + + Ciaran (7) @@ -12372,11 +12636,11 @@ Drose (7) - - Esbardu (7) + + Bateman, George (7) @@ -12386,11 +12650,11 @@ Hunter, Kevin (7) - - Ingotian (7) + + Levith (7) @@ -12400,11 +12664,11 @@ M1cky (7) - - Mariosv (7) + + Marton (7) @@ -12414,11 +12678,11 @@ Mcobit (7) - - MephistoBooks (7) + + Francis, Matthew (7) @@ -12428,11 +12692,11 @@ Ndduong (7) - - Nemo bis (7) + + Christener, Nicolas (7) @@ -12442,11 +12706,11 @@ Opensas (7) - - PeaceByJesus (7) + + Polte (7) @@ -12456,11 +12720,11 @@ Rodo (7) - - Scottclarke (7) + + Shady (7) @@ -12470,6 +12734,9 @@ Simosx (7) + + Tobbi (7) + @@ -12503,17 +12770,20 @@ Alpha (6) + + Anjefu (6) + Armin Dänzer (6) Asian flower (6) + + Higginson, Andrew (6) - - Barend (6) @@ -12523,13 +12793,10 @@ Bruno (6) - - Cagatayyigit (6) - - CassieLX (6) + Cagatayyigit (6) Cccfr (6) @@ -12622,13 +12889,10 @@ Infoprof (6) - InspiringNameGoesHere (6) + Iplaw67 (6) - - Iplaw67 (6) - Timofeev, Ivan (6) @@ -12638,11 +12902,11 @@ Jeffersonx (6) - - Kawichi (6) + + Levlazinskiy (6) @@ -12652,11 +12916,11 @@ Linzushi (6) - - Lpranam (6) + + MaggieT (6) @@ -12666,11 +12930,11 @@ Manas (6) - - Manop (6) + + Mas (6) @@ -12680,11 +12944,11 @@ Mmetz (6) - - Monnom (6) + + Ndlsas (6) @@ -12694,11 +12958,11 @@ Only you (6) - - Os cib (6) + + PLNET (6) @@ -12708,11 +12972,11 @@ Pescetti (6) - - Peter Chastain (6) + + Peterhuang1kimo (6) @@ -12722,11 +12986,11 @@ Rotaj (6) - - S8321414 (6) + + Goyal, Shubham (6) @@ -12736,11 +13000,11 @@ Sukit (6) - - Sumitcn (6) + + Telesto (6) @@ -12750,10 +13014,13 @@ Thorwil (6) + + TiagoSantos (6) + - TiagoSantos (6) + Ttrolka (6) Tyree (6) @@ -13203,17 +13470,20 @@ Cam AW (4) + + ChiggyWiggy (4) + Clairedwood (4) ConquerorsHaki (4) + + Crankybot (4) - - CyrilBeaussier (4) @@ -13223,11 +13493,11 @@ Deivan (4) + + Dmerker (4) - - DmitryRamones (4) @@ -13237,11 +13507,11 @@ Dragon (4) + + Robertson, Daniel (4) - - Eisaks (4) @@ -13251,11 +13521,11 @@ FlorianW (4) + + Fmolinero (4) - - Ftigeot (4) @@ -13265,11 +13535,11 @@ Gmasei (4) + + Gmjs (4) - - GwenaelQ (4) @@ -13279,11 +13549,11 @@ Hidemune (4) + + ImperfectlyInformed (4) - - Izabela (4) @@ -13293,11 +13563,11 @@ Jamesleader (4) + + Jessefrgsmith (4) - - Jiehong (4) @@ -13307,11 +13577,11 @@ Jjpalacios (4) + + JnRouvignac (4) - - Jonata (4) @@ -13321,11 +13591,11 @@ Jonnygrant (4) + + Jooste (4) - - Joriki (4) @@ -13335,11 +13605,11 @@ Le Bigot, Jean-Tiare (4) + + Kemalayhan (4) - - Lethargilistic (4) @@ -13349,11 +13619,11 @@ M.m.mozffart (4) + + Haggag, Muhammad (4) - - MPascual (4) @@ -13363,11 +13633,11 @@ Marinela (4) + + Mikedoherty ca (4) - - Mondeep18 (4) @@ -13377,11 +13647,11 @@ Mortgage01 (4) + + NGHLibreOffice (4) - - O.villani (4) @@ -13391,11 +13661,11 @@ Orson69 (4) + + Oscar90210 (4) - - Paolopoz (4) @@ -13405,11 +13675,11 @@ PatrickJ (4) + + PaulRoos (4) - - Pegasus (4) @@ -13419,11 +13689,11 @@ Pgassmann (4) + + Philj (4) - - Phillip.davis (4) @@ -13433,11 +13703,11 @@ Pjacquod (4) + + Prolog.guy (4) - - Psao (4) @@ -13447,11 +13717,11 @@ Randolphgamo (4) + + Rebahozkoc (4) - - Reyn100 (4) @@ -13461,11 +13731,11 @@ RjR (4) + + Rodhos (4) - - Sasha (4) @@ -13475,11 +13745,11 @@ Selimseker (4) + + Stevenmw (4) - - Surat (4) @@ -13489,11 +13759,11 @@ Tempelorg (4) + + Tex2002ans (4) - - Thetic (4) @@ -13503,11 +13773,11 @@ Tlequire (4) + + Txwikinger (4) - - Ufas (4) @@ -13517,11 +13787,11 @@ Urhixidur (4) + + Uzadmin (4) - - V., Artem (4) @@ -13531,11 +13801,11 @@ Wikiuser (4) + + Williamjmorenor (4) - - Wpeixoto (4) @@ -13545,11 +13815,11 @@ AbhilashSingh (3) + + Adept (3) - - Aexyn (3) @@ -13559,11 +13829,11 @@ Jain, Atishay (3) + + Alex.simoes (3) - - Alexsfagundes (3) @@ -13573,11 +13843,11 @@ Andrey Usov (3) + + Antanasb (3) - - Ariete (3) @@ -13587,11 +13857,11 @@ Armin (3) + + Armin W. (3) - - Arthur Zennig (3) @@ -13601,11 +13871,11 @@ Baena (3) + + Bellerophon2 (3) - - Benjwgarner (3) @@ -13615,11 +13885,11 @@ Bindassanant (3) + + Bodhi-Baum (3) - - Bootingman (3) @@ -13629,11 +13899,11 @@ Prajapati, Gautam (3) + + Brub (3) - - Burdakov (3) @@ -13643,11 +13913,11 @@ Canberkturan (3) + + Castro (3) - - Charu (3) @@ -13657,11 +13927,11 @@ ChrisConCas (3) + + Claudiosegovia (3) - - Cmorgan (3) @@ -13671,112 +13941,120 @@ Csena5 (3) + + D0ugparker (3) - - DaSch (3) DanShearer (3) + + Dandv (3) + + + Beurle, Darcy (3) Bankston, Daniel (3) - - Dilip (3) Dircules (3) + + Donbrookman (3) Dubyk (3) - - Dung.saga (3) EdgeE (3) + + Edz (3) Eeha0120 (3) - - Eisa01 (3) Elproferoman (3) + + Schorsch, Emanuel (3) ErSey (3) - - Eric.ficheux (3) Ericatamiris (3) + + Estebanmonge (3) Farukuzun (3) - - Ferlodev (3) Fofr11 (3) + + Fraang (3) Franzjakob (3) - - Frob tea (3) Fulldecent (3) + + FunkyPenguin (3) + + Georg3014 (3) + Gkarthikreddi (3) - - Gokcen (3) + + Gouchi (3) @@ -13786,11 +14064,11 @@ Hansgerd.schneider (3) - - Nag,Harshita (3) + + Herrmarder (3) @@ -13800,11 +14078,11 @@ Hwpplayer1 (3) - - IanL (3) + + Imanuelr10 (3) @@ -13814,11 +14092,11 @@ It-christian (3) - - IvanMM (3) + + JDM (3) @@ -13828,11 +14106,11 @@ Jcrben (3) - - Jennifer.park (3) + + Jessemoreirao (3) @@ -13842,11 +14120,11 @@ Jhbn (3) - - Jo Cab (3) + + Joe312213 (3) @@ -13856,11 +14134,11 @@ Jomonbre (3) - - Joseroberto (3) + + Juanpabl (3) @@ -13870,11 +14148,11 @@ K Karthikeyan (3) - - Katasisc (3) + + Kbiondi (3) @@ -13884,11 +14162,11 @@ Kevinob (3) - - Kfogel (3) + + Khunshan (3) @@ -13898,11 +14176,11 @@ Kkrothapalli (3) - - Knordback (3) + + LO Rob (3) @@ -13912,11 +14190,11 @@ LewisCowles (3) - - Libcub (3) + + LucaCappelletti (3) @@ -13926,11 +14204,11 @@ Lupp (3) - - Luuk (3) + + Machey (3) @@ -13940,11 +14218,11 @@ Margott (3) - - Marializ (3) + + Masaki tamakoshi (3) @@ -13954,11 +14232,11 @@ Mattias (3) - - Maxwell (3) + + Measure for Measure (3) @@ -13968,11 +14246,11 @@ Meryemezber (3) - - Mhoes (3) + + Mhsmsantos (3) @@ -13982,11 +14260,11 @@ Mike98 (3) - - Minion3665 (3) + + Nak47 (3) @@ -13996,11 +14274,11 @@ Neookano (3) - - NickWingate (3) + + NicksonT (3) @@ -14010,11 +14288,11 @@ Niconil (3) - - Ragnarsson, Björgvin (3) + + Nloira (3) @@ -14024,11 +14302,11 @@ OOarthurOo (3) - - Steinbeiß, Simon (3) + + Ojeremyj (3) @@ -14038,11 +14316,11 @@ Oprea luci (3) - - Paintdog (3) + + Paolobenve (3) @@ -14052,11 +14330,11 @@ Pr410 (3) - - Prakash72 (3) + + Rajatvijay (3) @@ -14066,11 +14344,11 @@ Rapha.ksf (3) - - Rauloliverpaes (3) + + Bevilacqua, Jean-Sébastien (3) @@ -14080,11 +14358,11 @@ Reyhane (3) - - Rick (3) + + Robert.E.A.Harvey (3) @@ -14094,10 +14372,13 @@ Rosemary (3) + + Rparth07 (3) + - Rparth07 (3) + SZ475 (3) Sander Klootwijk (3) @@ -14138,9 +14419,6 @@ - - Vasiliu, Mihai Alexandru (3) - Skinnerbird (3) @@ -14150,11 +14428,11 @@ Soliac (3) - - Songchuan (3) + + Soued031 (3) @@ -14164,11 +14442,11 @@ StefanU (3) - - SteveKelem (3) + + Steveo o (3) @@ -14178,11 +14456,11 @@ Suren (3) - - Sushils (3) + + Taylor46 (3) @@ -14192,11 +14470,11 @@ TheWebalyst (3) - - Tiagosilva.anps (3) + + Tibornagy (3) @@ -14206,11 +14484,11 @@ Tititou36 (3) - - Kumar, Tarun (3) + + Toki (3) @@ -14220,11 +14498,11 @@ ToniB (3) - - Toxifier (3) + + TrnsltLife (3) @@ -14234,11 +14512,11 @@ Ubap (3) - - Kitzinger, Ulrich (3) + + Underdog (3) @@ -14248,11 +14526,11 @@ Vinctor (3) - - Vladasavy (3) + + Vljubovic (3) @@ -14262,11 +14540,11 @@ Khoo, Wei Ming (3) - - WesPeacock (3) + + Xaker1 (3) @@ -14276,11 +14554,11 @@ Yukawa (3) - - Kolesnykov, Yurii (3) + + Yvon Henel (3) @@ -14290,11 +14568,11 @@ Zaxebo1 (3) - - ترجمان05 (3) + + さかみのかさね (3) @@ -14304,11 +14582,11 @@ AdamPrado8 (2) - - AdrianValdez4 (2) + + Adsha (2) @@ -14318,11 +14596,11 @@ Aggelalex (2) - - Alan (2) + + Ale2017 (2) @@ -14332,11 +14610,11 @@ Alina12345 (2) - - Alisha (2) + + AlmedaFrancis (2) @@ -14346,11 +14624,11 @@ Amunizp (2) - - AmyCarney5 (2) + + Anasiic (2) @@ -14360,11 +14638,11 @@ AndresChandia (2) - - Andrew (2) + + AndrewKuhn7 (2) @@ -14374,11 +14652,11 @@ Andthebrain (2) - - Anipeter (2) + + Anjar (2) @@ -14388,11 +14666,11 @@ AnnabelMcmullen (2) - - AnnunciationGunn (2) + + Anonimus (2) @@ -14402,11 +14680,11 @@ Jain, Anurag (2) - - Aplatypus (2) + + ApostlesSheldon (2) @@ -14416,11 +14694,11 @@ Asal (2) - - Ashaneba (2) + + Nakashian, Ashod (2) @@ -14430,17 +14708,20 @@ Ozdemir, Aybuke (2) - - BZT42 (2) + + Le Garrec, Vincent (2) Baole.fang (2) + + Benurban (2) + BernardMeza9 (2) @@ -14488,9 +14769,6 @@ - - Bpeel (2) - Bram (2) @@ -14500,11 +14778,11 @@ BridgetJarvis (2) - - Bruceschaller (2) + + BryantMclean6 (2) @@ -14514,11 +14792,11 @@ C0bb3r (2) - - C1pr1an (2) + + CallieMvzap (2) @@ -14528,11 +14806,11 @@ CamilleMccarthy (2) - - CandidoRutherford (2) + + CapistranOleary (2) @@ -14542,11 +14820,11 @@ CaraDang6 (2) - - Carlosr (2) + + CarolinaCalling (2) @@ -14556,11 +14834,11 @@ CarrollRico2 (2) - - Iacob, Catalin (2) + + CavesGill8 (2) @@ -14570,11 +14848,11 @@ Cgrosdemange (2) - - Chabermu (2) + + ChanieSnow2 (2) @@ -14584,11 +14862,11 @@ ChrisBarth (2) - - ChrzcicielCampbell (2) + + Cipriano (2) @@ -14598,11 +14876,11 @@ Cl-r (2) - - ClariceThorne (2) + + ClaudiaCramer (2) @@ -14612,11 +14890,11 @@ McDonald, Jason C. (2) - - Codingmicha (2) + + Colabo (2) @@ -14626,11 +14904,11 @@ Coogor (2) - - CoralieCarr7 (2) + + Crxssi (2) @@ -14640,11 +14918,11 @@ Cvk (2) - - CyrillicEscobedo (2) + + Cœur, Antoine (2) @@ -14654,11 +14932,11 @@ Dairdev (2) - - DaisieQuigley (2) + + Damascene (2) @@ -14668,11 +14946,11 @@ Danese (2) - - Danielt998 (2) + + Danthedev (2) @@ -14682,11 +14960,11 @@ David4you (2) - - Davidlee (2) + + Bolen, David (2) @@ -14696,11 +14974,11 @@ Debugercz (2) - - DelinaRomano5 (2) + + DellePoole7 (2) @@ -14710,11 +14988,11 @@ Dennis' Spam test account (2) - - Denytracom (2) + + Devilcynthy (2) @@ -14724,11 +15002,11 @@ Diazbastian (2) - - Retout, Tim (2) + + Django (2) @@ -14738,11 +15016,11 @@ Domasj (2) - - Domsau2 (2) + + DonaldBryant7 (2) @@ -14752,11 +15030,11 @@ DrDrack (2) - - Röllin, Lukas (2) + + Duiliodias (2) @@ -14766,11 +15044,11 @@ Montañés, Eloi (2) - - EarleSiegel7 (2) + + Ed (2) @@ -14780,11 +15058,11 @@ Eduardoarandah (2) - - Edwardcottreau (2) + + Efdali (2) @@ -14794,11 +15072,11 @@ Ejep520 (2) - - Sánchez, Bartolomé (2) + + Eldan (2) @@ -14808,11 +15086,11 @@ Elixir (2) - - EllieBowers3 (2) + + ElmaGray6 (2) @@ -14822,11 +15100,11 @@ ElsieMacias7 (2) - - Emily (2) + + EmperorErnst5 (2) @@ -14836,11 +15114,11 @@ EnosKraus6 (2) - - Erdalronahi (2) + + Eren (2) @@ -14850,11 +15128,11 @@ Erikcht (2) - - Ersteinmal (2) + + ErwinHammond3 (2) @@ -14864,11 +15142,11 @@ EssieKeller8 (2) - - EsterEngland7 (2) + + EthylCardenas (2) @@ -14878,11 +15156,11 @@ FannyTillman8 (2) - - FateHarrington (2) + + Fbartels (2) @@ -14892,11 +15170,11 @@ Fcojavmc (2) - - Feldo (2) + + Ffinlo (2) @@ -14906,11 +15184,11 @@ FlorenceGrossman (2) - - FlorenceKim1 (2) + + FordRhodes5 (2) @@ -14920,11 +15198,11 @@ FredaDowning7 (2) - - Fukanchik, Sergey (2) + + Fyodor, Yemelyanenko (2) @@ -14934,11 +15212,11 @@ Gauste (2) - - Gautamsahil1947 (2) + + GayeRossetti (2) @@ -14948,11 +15226,11 @@ GeoffLawrence (2) - - GeorgiannaOchoa (2) + + Gerardgiraud (2) @@ -14962,11 +15240,11 @@ GertieEllington (2) - - GiertrudaLehman (2) + + Girvinh (2) @@ -14976,11 +15254,11 @@ Glanbeav (2) - - Glococo (2) + + Gmealer (2) @@ -14990,11 +15268,11 @@ Gortazar (2) - - GraciaNorwood (2) + + Grakic (2) @@ -15004,11 +15282,11 @@ Gualtiero (2) - - Guillem (2) + + Hacmiranda (2) @@ -15018,11 +15296,11 @@ HannaEspinoza (2) - - HardyBurris1 (2) + + HarleyWatkins (2) @@ -15032,11 +15310,11 @@ Hector (2) - - Hedaja (2) + + Hellpé (2) @@ -15046,11 +15324,11 @@ Hemmerling (2) - - Jensen, Henrik (2) + + HeriberDacomb (2) @@ -15060,11 +15338,11 @@ Herronrobertson (2) - - HershelPeterson (2) + + IIIYates8 (2) @@ -15074,11 +15352,11 @@ Iannz (2) - - IkeVasquez9 (2) + + IlaRoberts4 (2) @@ -15088,6 +15366,9 @@ InezFinney8 (2) + + Interpretingvale (2) + @@ -15800,10 +16081,13 @@ R.Yu. (2) - Rahul050 (2) + Radiatore (2) + + Rahul050 (2) + Rbecke (2) @@ -15813,11 +16097,11 @@ ReginaldMcgraw (2) + + RenniePrescott (2) - - RetaStern5 (2) @@ -15827,11 +16111,11 @@ RiceBurger3 (2) + + Ritlay (2) - - Rmarquardt (2) @@ -15841,11 +16125,11 @@ RollandHannah (2) + + RosaliaFair4 (2) - - RosannaPaul7 (2) @@ -15855,11 +16139,11 @@ RoyFokker (2) + + RoyShelton7 (2) - - Ryan (2) @@ -15869,11 +16153,11 @@ SDann22 (2) + + Sagar.libo (2) - - Sahasranaman M S (2) @@ -15883,11 +16167,11 @@ SamBenavides5 (2) + + Sankarshan (2) - - SavinaShaffer (2) @@ -15897,11 +16181,11 @@ Seanyoung (2) + + SebastianNorth (2) - - Sebutler (2) @@ -15911,11 +16195,11 @@ Sfeuser (2) + + Sgrotz (2) - - Shaforostoff (2) @@ -15925,11 +16209,11 @@ Shaun.schutte (2) + + Shitamo (2) - - SidneyArredondo (2) @@ -15939,11 +16223,11 @@ Silwol (2) + + Simplecontrast (2) - - Sjshaffer (2) @@ -15953,11 +16237,11 @@ Kasztenny, Adam (2) + + Sockseight (2) - - Soothsilver (2) @@ -15967,11 +16251,11 @@ Sshelagh (2) + + Sshi (2) - - Ssorgatem (2) @@ -15981,11 +16265,11 @@ Stappers (2) + + Weiberg, Stefan (2) - - Stephan66 (2) @@ -15995,11 +16279,11 @@ Stuarta0 (2) + + Sturm (2) - - Sungkhum (2) @@ -16009,11 +16293,11 @@ SusanSwain3 (2) + + Sven.fischer.de (2) - - Swazmo (2) @@ -16023,11 +16307,11 @@ Synanceia (Pierre) (2) + + Tauon (2) - - Techal (2) @@ -16037,11 +16321,11 @@ TeresaMacias3 (2) + + Teresavillegas1 (2) - - TheaGallardo8 (2) @@ -16051,11 +16335,11 @@ TheophilusHess (2) + + Thomase (2) - - Thomeck (2) @@ -16065,11 +16349,11 @@ Tim1075 (2) + + Timeshifter (2) - - Timj (2) @@ -16079,11 +16363,11 @@ Tolunaydundar (2) + + TomaMora8 (2) - - Tomkeb (2) @@ -16093,11 +16377,11 @@ TressieCulver (2) + + Tsimonq2 (2) - - TuMadre (2) @@ -16107,11 +16391,11 @@ Tux40000 (2) + + Unhammer (2) - - Unknown 32 (2) @@ -16121,11 +16405,11 @@ ValessioBrito (2) + + VanHogan7 (2) - - Dhall, Varun (2) @@ -16135,11 +16419,11 @@ VerneDodd5 (2) + + VeronaXiong3 (2) - - VeronicaGrimes (2) @@ -16149,11 +16433,11 @@ Viper550 (2) + + VirginArredondo (2) - - VladimirBassett (2) @@ -16163,11 +16447,11 @@ VladislavA (2) + + Volker (2) - - VolodymyraGagnon (2) @@ -16177,11 +16461,11 @@ WaclawaSavage (2) + + WalentynaPatrick (2) - - WallaceSolano (2) @@ -16191,112 +16475,120 @@ WashingtonOakley (2) + + Watermelons (2) - - + + Weirdo (2) + WeronikaKeene (2) Wertie (2) + + Wi24rd (2) WikiImporter (2) - - WilhelminaEaton (2) WincentyMorrison (2) + + Wirelessben (2) Wkn (2) - - Wulei (2) Xdelatour (2) + + Xoristzatziki (2) Yalda (2) - - Yaw (2) ZiriaKo (2) + + ZoraWinkler1 (2) 流星依旧 (2) - - 29jm (1) A H (1) + + A.jadiba (1) AJW (1) - - AaronPeterson (1) Abdulaziz A Alayed (1) + + Absolute Garcinia (1) Acagastya (1) - - Kepenek, Ahmet Can (1) AdalberDesailll (1) + + + + Adaz (1) + Adlard.matthew (1) Aevora (1) - - Agradecido (1) + + Ainurshakirov (1) @@ -16306,11 +16598,11 @@ Sudheer Kumar, Akshit (1) - - Alagris (1) + + Alavec (1) @@ -16320,11 +16612,11 @@ Aleks (1) - - Aleksio Kverka (1) + + Henrie, Alex (1) @@ -16334,11 +16626,11 @@ Alex38-68 (1) - - Alex80 (1) + + AlexF (1) @@ -16348,11 +16640,11 @@ AlexPS (1) - - Alexandrevicenzi (1) + + Alexandri (1) @@ -16362,11 +16654,11 @@ Alexis 0071 (1) - - Alexis Wilke (1) + + Alexnivan (1) @@ -16376,11 +16668,11 @@ Aleyna.sare (1) - - Ali (1) + + AlphonsDen (1) @@ -16390,11 +16682,11 @@ Alverne (1) - - Amacater (1) + + Andarilhobotto (1) @@ -16404,11 +16696,11 @@ AndreasEk (1) - - AndreasK (1) + + AndreasNeudecker (1) @@ -16418,11 +16710,11 @@ Andriazdk2177 (1) - - AniVar (1) + + AnimyosFox (1) @@ -16432,11 +16724,11 @@ Ankur, Khandelwal (1) - - AntoineVe (1) + + Antonello Lobianco (1) @@ -16446,11 +16738,11 @@ Anurag kanungo (1) - - Apfelsaft (1) + + Priyadarshi, Apurva (1) @@ -16460,11 +16752,11 @@ Ari (1) - - ArielleWx (1) + + Arkonide (1) @@ -16474,11 +16766,11 @@ Arnaudc (1) - - Arnoldu (1) + + Teigseth, Arno (1) @@ -16488,11 +16780,11 @@ ArturNeumann (1) - - Arulm (1) + + Asiersar (1) @@ -16502,11 +16794,11 @@ Astalaseven (1) - - Aszucs (1) + + Atpnguyen (1) @@ -16516,11 +16808,11 @@ AundreaPqf (1) - - Aung77 (1) + + Averell7 (1) @@ -16530,11 +16822,11 @@ B3t (1) - - BLAZE (1) + + Bailiwick (1) @@ -16544,11 +16836,11 @@ Bami (1) - - Bandera (1) + + BarryLovegrove (1) @@ -16558,11 +16850,11 @@ Bburak (1) - - Bckurera (1) + + Khorram, Behrad (1) @@ -16572,11 +16864,11 @@ Bestdating (1) - - Beyoken (1) + + Beznogov (1) @@ -16586,11 +16878,11 @@ Bgloberman (1) - - Bgranados (1) + + Bhumikasethi (1) @@ -16600,168 +16892,171 @@ BillyBurke (1) - - Biofool (1) - - Bittin (1) - + + Bjossir (1) Bkg2018 (1) - - BlakeGartrell (1) BlancheBelstead (1) + + BlancheClopton (1) Blandyna (1) - - Boboo (1) Bojidar-bg (1) + + Bolo (1) Borowcm (1) - - Bortis (1) Sowden, Brad (1) + + BrentHawthorne (1) BridgettC (1) - - Brinzing, Oliver (1) BroderiHolyman (1) + + Brolin (1) Bruce101 (1) - - BryceBrassell (1) BryceMoorhouse (1) + + Budo (1) Burcin (1) - - Bureken (1) Burger.ga (1) + + Buzea.bogdan (1) Bwi (1) - - Bzsolt (1) BáthoryPéter (1) + + CalebSommer (1) CalebWgypcu (1) - - Paul, Cameron (1) Capira (1) + + CarloASilva (1) Carlos (1) - - Carlos.gilaranz (1) Castarco (1) + + Cathy (1) CedricQ73ktehvp (1) - - Ceeve (1) Cesera (1) + + ChantalWalker (1) Charkins (1) - - CharlesJenkins (1) Chatjoe (1) + + + + Chheyden (1) + + + Chibiberu (1) + Chmilblick (1) @@ -17666,6 +17961,9 @@ + + JohnVeness (1) + Johnplay2 (1) @@ -17675,11 +17973,11 @@ Jonatanpc8 (1) + + JonelleFritz (1) - - Wu, Haidong (1) @@ -17689,11 +17987,11 @@ Jorge Rodríguez Fonseca (1) + + Jorgemendes (1) - - JoseGatica (1) @@ -17703,11 +18001,11 @@ Joshun (1) + + José Eduardo (1) - - Jp.santi (1) @@ -17717,11 +18015,11 @@ Clarke, James (1) + + JudeMcCafferty (1) - - Juergen (1) @@ -17731,11 +18029,11 @@ Picca, Juan (1) + + Jurajsarinay (1) - - Jwcampbell (1) @@ -17745,11 +18043,11 @@ KNM (1) + + Kader (1) - - Kapoorsahab (1) @@ -17759,11 +18057,11 @@ Bhat, Kishor (1) + + Keith Long (1) - - Kenb (1) @@ -17773,11 +18071,11 @@ Kenton3255 (1) + + Kintaro (1) - - Kiyotaka Nishibori (1) @@ -17787,11 +18085,11 @@ Kkremitzki (1) + + Knobo (1) - - Koeleman (1) @@ -17801,11 +18099,11 @@ Kosmous (1) + + KourtneNester (1) - - Kr1shna (1) @@ -17815,11 +18113,11 @@ Kumar, Thangavel (1) + + Kying (1) - - LKPSharylptwsdo (1) @@ -17829,11 +18127,11 @@ LOFF (1) + + LaPingvino (1) - - Laskov (1) @@ -17843,11 +18141,11 @@ LaverneNavarret (1) + + LavinaVandermar (1) - - LazyDesertMan (1) @@ -17857,11 +18155,11 @@ Learner (1) + + Liammoy (1) - - Libreleo (1) @@ -17871,11 +18169,11 @@ Likoski (1) + + LillieNlowccx (1) - - Lineinthesand (1) @@ -17885,11 +18183,11 @@ Litishia (1) + + Liturgist (1) - - Llalllal1 (1) @@ -17899,11 +18197,11 @@ Lobillo (1) + + Lonaowna (1) - - Lopp Rs (1) @@ -17913,11 +18211,11 @@ Lplatypus (1) + + Luca (1) - - Lucas Filho (1) @@ -17927,11 +18225,11 @@ Luiz Cláudio (1) + + Luiz Rezende (1) - - Luke (1) @@ -17941,11 +18239,11 @@ M1ndfr3ak (1) + + ME-ON1 (1) - - MJW (1) @@ -17955,11 +18253,11 @@ Mabel7997eelu (1) + + Macroni23 (1) - - Maemst (1) @@ -17969,11 +18267,11 @@ Magmag (1) + + Mahdiekrani (1) - - Mahmudul (1) @@ -17983,11 +18281,11 @@ Manveru1986 (1) + + Rizzolo, Mattia (1) - - Marado (1) @@ -17997,11 +18295,11 @@ MarcK (1) + + MarcelProut (1) - - MarcoZ (1) @@ -18011,11 +18309,11 @@ Marcosalex (1) + + Marcosps (1) - - MargoBergman (1) @@ -18025,11 +18323,11 @@ Mariano Gaudix (1) + + MarkWielaaard (1) - - Markcoomes (1) @@ -18039,11 +18337,11 @@ MarthaWaterman (1) + + Martinvanzijl (1) - - Marwan (1) @@ -18053,11 +18351,11 @@ Masakim-icraft (1) + + Massao (1) - - Mastizada (1) @@ -18067,11 +18365,11 @@ Matt K (1) + + MattTheGeek (1) - - Campanelli, Matteo (1) @@ -18081,252 +18379,260 @@ Mau (1) + + + + Maverick74 (1) + MavropaliasG (1) - - Maxjf1 (1) Mazinho (1) + + Bechler, Moritz (1) Mblume3 (1) - - Doležel, Marek (1) Megan44Dgxg (1) + + Melikeyurtoglu (1) Menturi (1) - - MeskoBalazs (1) Mete0r (1) + + Meven (1) Mhaehnel (1) - - Mhcrnl (1) Mhenriday (1) + + Mibm123 (1) Michaelwood (1) - - Michka B (1) Midomidi2013 (1) + + MiguelKastner (1) Miguelteixeira (1) - - Miguelverdu (1) Mike-y (1) + + MikeLittle (1) Mikolg (1) - - MilagroWilkerso (1) Milanbv (1) + + Miles (1) Minarja4 (1) - - Mirsad (1) Miurahr (1) + + Mixer (1) Mixstah (1) - - Mlager (1) Mmeof (1) + + Moaz eldfrawy (1) Moberg (1) - - Mohammedzalta (1) Mohsenzl (1) + + Monikayadav (1) Herbst, André (1) - - Morenonatural (1) Soini, Mox (1) + + Mrund (1) Muhammadsufyanzainalabidin (1) - - Mw (1) Myan (1) + + MyraBlacklow (1) N3rd4i (1) - - NEOhidra (1) NNe8Lx2gc (1) + + Nanotron (1) Naomiobbard (1) - - Nattu (1) Ncaio (1) + + Nedrichards (1) NellieSMWX (1) - - Neteler (1) Nevanos (1) + + Ngoswami (1) Nickko (1) - - Nicolas tala (1) Nilss (1) + + Nithin.padavu (1) Ngo, Minh (1) - - Nnino2 (1) Norty (1) + + + + Norwest16125 (1) + Notafish (1) NotesTracker (1) - - Nouiurm (1) + + Norbert X (1) @@ -18336,11 +18642,11 @@ Obook (1) - - Oclei (1) + + Oig (1) @@ -18350,11 +18656,11 @@ Okusi (1) - - Omansmith (1) + + Omerta (1) @@ -18364,11 +18670,11 @@ Oosterkamp (1) - - Opestawon (1) + + OppZ (1) @@ -18378,11 +18684,11 @@ Orrd (1) - - Osoitz (1) + + Otrembad (1) @@ -18392,11 +18698,11 @@ Ouyang.leyan (1) - - Anderson, Owen (1) + + Esen, Özcan (1) @@ -18406,11 +18712,11 @@ Öztürk, Emre (1) - - P12tic (1) + + PBsoft (1) @@ -18420,11 +18726,11 @@ Padenton (1) - - PamalaDorsch (1) + + Pankaj (1) @@ -18434,11 +18740,11 @@ Pascal pipo (1) - - Passerpunt (1) + + Pastim (1) @@ -18448,11 +18754,11 @@ Paulolima (1) - - Pelambrera (1) + + PelinKuran (1) @@ -18462,11 +18768,11 @@ Pertsa (1) - - Nowee, Peter (1) + + Vorel, Petr (1) @@ -18476,11 +18782,11 @@ Phb.nbnet.nb.ca (1) - - Pherjung (1) + + PhilDur (1) @@ -18490,11 +18796,11 @@ PhilipTimms (1) - - Philipp.weissenbacher (1) + + Philippe43 (1) @@ -18504,11 +18810,11 @@ Phomes (1) - - Paraiso, Joan (1) + + Pi (1) @@ -18518,11 +18824,11 @@ Piero (1) - - PieterDeBruijn (1) + + Pietro.caballeri (1) @@ -18532,11 +18838,11 @@ Piratu (1) - - Piternoize (1) + + Pjotr (1) @@ -18546,11 +18852,11 @@ Plastique (1) - - Plastovicka (1) + + Moscu, Alexandru (1) @@ -18560,11 +18866,11 @@ Por (1) - - Carter, Travis (1) + + Privacidad (1) @@ -18574,11 +18880,11 @@ Psauthor (1) - - Psmits (1) + + Psychicread531 (1) @@ -18588,11 +18894,11 @@ Pwz266266 (1) - - Illarionov, Arkadiy (1) + + Qiguo (1) @@ -18602,11 +18908,11 @@ Quick8130 (1) - - Quickbooktech (1) + + Qwe (1) @@ -18616,249 +18922,250 @@ RabbitFrank (1) - - - - Radiatore (1) - Rahuldeshmukh101 (1) + + Rainy (1) Ramonturner (1) - - Randallperry (1) Rash419 (1) + + Ratajs (1) Ratias (1) - - Rcampbelllaos (1) RebeccaToscano (1) + + Retodomax (1) Rettichschnidi (1) - - RexRTEJnlzus (1) Rholler (1) + + Rich (1) Richardprins (1) - - RickieHpejt (1) Riessmi (1) + + Rif (1) Rifkiaz (1) - - Rimas (1) Ringlerloje (1) + + Rion (1) Ritzema, Brent (1) - - Rizobix (1) Kondratenko, Rostislav (1) + + Robert Wetzlmayr (1) Robineh (1) - - Robustchao (1) Rockers (1) + + Rodney78 (1) Rogach (1) - - Deshmukh, Rohit (1) Rokejulianlockhart (1) + + Rombert (1) Ron1 (1) - - Ronakkothari123 (1) Ronny (1) + + Roscoe5731 (1) Rosemarie (1) - - Rpott (1) Rsedak (1) + + RuleAndLine (1) Rvr (1) - - Ryho (1) ONODERA, Ryo (1) + + S.t.e.p.h (1) Sakura286 (1) - - SallyMorales (1) Samanicute (1) + + Sambhav2612 (1) Tygier, Sam (1) - - Sandeeps (1) Sanipache (1) + + Saracans (1) Sariyar (1) - - Satya kompella (1) Sbar1 (1) + + Sautier, Louis (1) Schrillesbunteshamburg (1) - - Scno (1) Sctenebro (1) + + + Scw189 (1) Sdc (1) - - Ak, Sedat (1) Senopen (1) + + Serdarot5 (1) Seriouslaughbore (1) - - + + ShadSterling (1) + Shay030 (1) + + ShaynaMan (1) @@ -18868,11 +19175,11 @@ Shore, Shimon (1) - - Shin en (1) + + Chaurasia, Shobhit (1) @@ -18882,11 +19189,11 @@ ShyamPraveenSingh (1) - - Siddhant (1) + + Siegi (1) @@ -18896,11 +19203,11 @@ Silvia (1) - - Simoc (1) + + Simonbr (1) @@ -18910,10 +19217,13 @@ Smalalur (1) + + Socialmitchell (1) + - Socialmitchell (1) + Solisj (1) Son Sonson (1) @@ -18926,6 +19236,9 @@ + + Spannm (1) + SpeedyGonsales (1) @@ -18935,252 +19248,260 @@ Spreadsheetsorter (1) + + Srijanani (1) - - + + Stellastar (1) + Steve271 (1) Stewart75H (1) + + Stonehubmn (1) StuartHalliday (1) - - Subhash (1) Supportex (1) + + SusieVeasley (1) Svalo (1) - - SvenHornung (1) Svend-ev (1) + + Sviola (1) Svtlichnijj (1) - - Sébastien C. (1) T-otsuki (1) + + TAQSamueld (1) Paul, McQuade (1) - - Talueses (1) Tanguy k (1) + + Thanakanok, Tantai (1) TateGunning (1) - - TaylorSlemp (1) Techsquirrel (1) + + TeganCreswick (1) Tegas (1) - - Testsflirt (1) Tgmiller1 (1) + + The Magpie (1) ThePokehach (1) - - Thephilosoft (1) Thhuang (1) + + Thom (1) Thor574 (1) - - ThudDriver (1) Thumindu (1) + + Tifroumi (1) Tigerbeard (1) - - Tilt (1) Tmongkol (1) + + Tomasdd (1) TomofumiYagi (1) - - Viehmann, Thomas (1) Tpokorra (1) + + Transcend (1) Trebledcliff (1) - - TrevorPfe (1) Trondtr (1) + + Ttv20 (1) Tuliouel (1) - - Tuping (1) Thibault, Vallois (1) + + USERNAME-ENDUNOM (1) Jain, Umang (1) - - Udit Sharma (1) Shahid, Umair (1) + + Vincent, Brennan (1) Unho (1) - - UrmasD (1) UrsulaHorrell (1) + + Ushabtay (1) VIPSylar (1) - - VPUJamikajklq (1) Vandenoever (1) + + Veeven (1) Vera Cavalcante (1) - - VernaSchulze (1) Vincentvikram (1) + + Vinkas (1) Virus009 (1) - - + + VocalCapybara76 (1) + WOBFriedauk (1) + + Wadrian (1) @@ -19190,11 +19511,11 @@ WandaSingletary (1) - - Wastl (1) + + Waynemcl (1) @@ -19204,143 +19525,135 @@ Wedeluxe (1) - - - - Weirdo (1) - Wes (1) + + Westantenna (1) Wet (1) - - Wezchlebaty (1) Wilhelm (1) + + William Avery (1) Williewortel (1) - - Klausner, Thomas (1) Woulouf (1) + + Tjong, Winston Min (1) XSXKristin (1) - - Baudin, Lucas (1) Xbones (1) + + XeroxMe (1) Xsdcfghjk (1) - - Suhail Alkowaileet (1) Bingwu Zhang (1) + + XtinaS (1) Xtrusia (1) - - Xuenhua (1) Yangyiji (1) + + YaroslavRutledge (1) Yazu (1) - - Yeliztaneroglu (1) Desai, Yogesh (1) + + Yoshiharu Kawai (1) Yowbooks (1) - - YvanM (1) Yy y ja jp (1) + + Bölöny, Zsolt (1) ZBMCallumbwire (1) - - - Zangune (1) Zibi (1) + + Zizzle (1) Zonnebloempje (1) - - 鄒延 (1) - - + + - - If you want to replace your Wiki user name with your full name, go to this wiki page and add yourself to the name mapping list. diff --git a/readlicense_oo/license/license.xml b/readlicense_oo/license/license.xml index c8c61d1a2465..405d8a213c35 100644 --- a/readlicense_oo/license/license.xml +++ b/readlicense_oo/license/license.xml @@ -171,6 +171,29 @@ copies of this file in any form for internal or external distribution as long as this notice remains attached.

                                  +
                                  +

                                  brotli

                                  +

                                  The following software may be included in this product: brotli.

                                  +

                                  brotli code is covered by the MIT license:

                                  +
                                  +

                                  Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.

                                  +

                                  Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions:

                                  +

                                  The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software.

                                  +

                                  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE.

                                  +
                                  +

                                  Bzip2

                                  The following software may be included in this product: bzip2, a free and open-source file compression @@ -600,6 +623,41 @@ "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

                                  +
                                  +

                                  highway

                                  +

                                  The following software may be included in this product: highway. highway + is dual-licensed under the Apache License 2.0 or the BSD 3-Clause + License.

                                  +

                                  Jump to Apache License Version + 2.0

                                  +

                                  BSD 3-Clause License

                                  +

                                  Copyright (c) The Highway Project Authors. All rights reserved.

                                  +

                                  Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met:

                                  +
                                    +
                                  1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer.
                                  2. +
                                  3. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution.
                                  4. +
                                  5. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission.
                                  6. +
                                  +

                                  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

                                  +

                                  HSQLDB

                                  The following software may be included in this product: HSQLDB. Use of any of this software is governed by @@ -659,7 +717,7 @@

                                  Jump to LGPL Version 2.1

                                  Jump to MPL Version 1.1

                                  -
                                  +

                                  Hyphen

                                  The following software may be included in this product: Hyphen. Use of any of this software is governed by the terms of the license below:

                                  @@ -840,7 +898,7 @@ by the terms of the license below:

                                  Jump to MPL Version 2.0

                                  -
                                  +

                                  libexttextcat

                                  The following software may be included in this product: libexttextcat. Use of any of this software is governed by the terms of the license below:

                                  @@ -1116,6 +1174,36 @@
                                • This notice may not be removed or altered from any source distribution.
                                • +
                                  +

                                  libjxl

                                  +

                                  The following software may be included in this product: libjxl. libjxl + is licensed under the BSD 3-Clause License.

                                  +

                                  BSD 3-Clause License

                                  +

                                  Copyright (c) the JPEG XL Project Authors.

                                  +

                                  All rights reserved.

                                  +

                                  Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met:

                                  +
                                    +
                                  1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer.
                                  2. +
                                  3. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution.
                                  4. +
                                  5. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission.
                                  6. +
                                  +

                                  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

                                  +

                                  liblangtag

                                  The following software may be included in this product: liblangtag. Use of any of this software is governed @@ -1402,7 +1490,7 @@

                                  Jump to LGPL Version 2.1

                                  Jump to MPL Version 2.0

                                  -
                                  +

                                  libxml2

                                  The following software may be included in this product: libxml2. Use of any of this software is governed by the terms of the license below:

                                  @@ -1483,12 +1571,6 @@ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

                                  -
                                  -

                                  lpsolve

                                  -

                                  The following software may be included in this product: lpsolve. Use of any of this software is governed by - the terms of the license below:

                                  -

                                  Jump to LGPL Version 2.1

                                  -

                                  lzma

                                  liblzma is under the BSD Zero Clause License (0BSD)

                                  @@ -1977,23 +2059,23 @@ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

                                  -

                                  Raptor RDF Parser Library

                                  -

                                  The following software may be included in this product: Raptor RDF Parser Library. Use of any of this software - is governed by the terms of the license below:

                                  -

                                  Copyright (C) 2000-2008 David Beckett
                                  - Copyright (C) 2000-2005 University of Bristol. All Rights Reserved.

                                  -

                                  All the licenses below are alternatives and if you select one license, that one alone applies.

                                  -

                                  Jump to LGPL Version 2.1

                                  -

                                  Jump to Apache License Version 2.0

                                  -

                                  Rasqal RDF Query Library

                                  -

                                  The following software may be included in this product: Rasqal RDF Query Library. Use of any of this software is - governed by the terms of the license below:

                                  -

                                  Copyright (C) 2000-2008 David Beckett
                                  - Copyright (C) 2000-2005 University of Bristol. All Rights Reserved.

                                  -

                                  All the licenses below are alternatives and if you select one license, that one alone applies.

                                  -

                                  Jump to LGPL Version 2.1

                                  -

                                  Jump to Apache License Version 2.0

                                  +

                                  Raptor RDF Parser Library

                                  +

                                  The following software may be included in this product: Raptor RDF Parser Library. Use of any of this software + is governed by the terms of the license below:

                                  +

                                  Copyright (C) 2000-2008 David Beckett
                                  + Copyright (C) 2000-2005 University of Bristol. All Rights Reserved.

                                  +

                                  All the licenses below are alternatives and if you select one license, that one alone applies.

                                  +

                                  Jump to LGPL Version 2.1

                                  +

                                  Jump to Apache License Version 2.0

                                  +

                                  Rasqal RDF Query Library

                                  +

                                  The following software may be included in this product: Rasqal RDF Query Library. Use of any of this software is + governed by the terms of the license below:

                                  +

                                  Copyright (C) 2000-2008 David Beckett
                                  + Copyright (C) 2000-2005 University of Bristol. All Rights Reserved.

                                  +

                                  All the licenses below are alternatives and if you select one license, that one alone applies.

                                  +

                                  Jump to LGPL Version 2.1

                                  +

                                  Jump to Apache License Version 2.0

                                  Redland RDF Application Framework

                                  The following software may be included in this product: Redland RDF Application Framework. Use of any of this software is governed by the terms of the license below:

                                  @@ -2428,13 +2510,6 @@

                                  Fonts

                                  -

                                  Agdasima

                                  -

                                  The following software may be included in this product: Agdasima fonts. Use of any of this software is governed - by the terms of the license below:

                                  -

                                  Copyright 2023 The Agdasima Project Authors (https://github.com/docrepair-fonts/agdasima-fonts).

                                  -

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, - and is also available with a FAQ at: http://scripts.sil.org/OFL

                                  -

                                  Jump to SIL Open Font License, Version 1.1

                                  Alef

                                  Copyright (c) 2012, HaGilda & Mushon Zer-Aviv (<http://hagilda.com|info@hagilda.com>), with Reserved Font Name Alef Regular.

                                  @@ -2446,33 +2521,10 @@

                                  Copyright (c) 2010-2017, Khaled Hosny (<khaledhosny@eglug.org>)

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1 as shown below.

                                  Jump to SIL Open Font License, Version 1.1

                                  -

                                  Bacasime Antique

                                  -

                                  The following software may be included in this product: Bacasime Antique fonts. Use of any of this software is governed - by the terms of the license below:

                                  -

                                  Copyright 2023 The Bacasime Antique Project Authors (https://github.com/docrepair-fonts/bacasime-antique-fonts), - with Reserved Font Name "Playfair".

                                  -

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, - and is also available with a FAQ at: http://scripts.sil.org/OFL

                                  -

                                  Jump to SIL Open Font License, Version 1.1

                                  -

                                  Belanosima

                                  -

                                  The following software may be included in this product: Belanosima fonts. Use of any of this software is governed - by the terms of the license below:

                                  -

                                  Copyright 2023 The Belanosima Project Authors (https://github.com/docrepair-fonts/belanosima-fonts), - with Reserved Font Name "Josefin Sans".

                                  -

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, - and is also available with a FAQ at: http://scripts.sil.org/OFL

                                  -

                                  Jump to SIL Open Font License, Version 1.1

                                  Caladea

                                  Copyright (c) 2012 Huerta Tipográfica

                                  This Font Software is licensed under the Apache License, Version 2.0 as shown below.

                                  Jump to Apache License Version 2.0

                                  -

                                  Caprasimo

                                  -

                                  The following software may be included in this product: Caprasimo fonts. Use of any of this software is governed - by the terms of the license below:

                                  -

                                  Copyright 2023 The Caprasimo Project Authors (https://github.com/docrepair-fonts/caprasimo-fonts).

                                  -

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, - and is also available with a FAQ at: http://scripts.sil.org/OFL

                                  -

                                  Jump to SIL Open Font License, Version 1.1

                                  Carlito

                                  Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Carlito".

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1 as shown below.

                                  @@ -2773,27 +2825,6 @@

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL

                                  Jump to SIL Open Font License, Version 1.1

                                  -

                                  Lugrasimo

                                  -

                                  The following software may be included in this product: Lugrasimo fonts. Use of any of this software is governed - by the terms of the license below:

                                  -

                                  Copyright 2023 The Lugrasimo Project Authors (https://github.com/docrepair-fonts/lugrasimo-fonts).

                                  -

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, - and is also available with a FAQ at: http://scripts.sil.org/OFL

                                  -

                                  Jump to SIL Open Font License, Version 1.1

                                  -

                                  Lumanosimo

                                  -

                                  The following software may be included in this product: Lumanosimo fonts. Use of any of this software is governed - by the terms of the license below:

                                  -

                                  Copyright 2023 The Lumanosimo Project Authors (https://github.com/docrepair-fonts/lumanosimo-fonts).

                                  -

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, - and is also available with a FAQ at: http://scripts.sil.org/OFL

                                  -

                                  Jump to SIL Open Font License, Version 1.1

                                  -

                                  Lunasima

                                  -

                                  The following software may be included in this product: Lunasima fonts. Use of any of this software is governed - by the terms of the license below:

                                  -

                                  Copyright 2023 The Lunasima Project Authors (https://github.com/docrepair-fonts/lunasima-fonts).

                                  -

                                  This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, - and is also available with a FAQ at: http://scripts.sil.org/OFL

                                  -

                                  Jump to SIL Open Font License, Version 1.1

                                  Noto

                                  The following software may be included in this product: Google Noto fonts. Use of any of this software is governed by the terms of the license below:

                                  @@ -2825,7 +2856,7 @@

                                  The following software may be included in this product: Afrikaans spelling dictionary. Use of any of this software is governed by the terms of the license below:

                                  Afrikaans Wordlist

                                  -

                                  The Afrikaans wordlist used by MySpell is made up of multiple wordlists. These are wither in the public +

                                  The Afrikaans wordlist used by MySpell is made up of multiple wordlists. These are either in the public domain, are used with the authors permission or are licensed under the LGPL. The majority of the words are derived from the Nieuwoudt and Viljoen list.

                                  The Nieuwoudt list was first published in this form in 1993 by Bernard A Nieuwoudt. Contact details: origen diff --git a/readlicense_oo/license/license_html.xsl b/readlicense_oo/license/license_html.xsl index ed84527928a1..f249f58e3985 100644 --- a/readlicense_oo/license/license_html.xsl +++ b/readlicense_oo/license/license_html.xsl @@ -9,12 +9,14 @@ + + + not(contains(concat(' ',$build_type,' '),$word)) and + not(contains(concat(' ',$no_mpl_subset,' '),$word)) and + not(contains(concat(' ',$os,' '),$word)) and + not(contains(concat(' ',$themes,' '),$word)) and @class)"> diff --git a/readlicense_oo/license/license_plain_text.xsl b/readlicense_oo/license/license_plain_text.xsl index 7ff3c20bf89e..7e90fa6a06a8 100644 --- a/readlicense_oo/license/license_plain_text.xsl +++ b/readlicense_oo/license/license_plain_text.xsl @@ -19,12 +19,14 @@ + + + not(contains(concat(' ',$build_type,' '),$word)) and + not(contains(concat(' ',$no_mpl_subset,' '),$word)) and + not(contains(concat(' ',$os,' '),$word)) and + not(contains(concat(' ',$themes,' '),$word)) and @class)"> diff --git a/registry/tools/regview.cxx b/registry/tools/regview.cxx index 0a77ddd9431d..e9b210745f0e 100644 --- a/registry/tools/regview.cxx +++ b/registry/tools/regview.cxx @@ -70,7 +70,7 @@ int __cdecl main( int argc, char * argv[] ) } else { - fprintf(stderr, "key \"%s\" not exists in registry \"%s\"\n", + fprintf(stderr, "key \"%s\" does not exist in registry \"%s\"\n", argv[2], argv[1]); } } diff --git a/reportbuilder/java/org/libreoffice/report/pentaho/SOReportJobFactory.java b/reportbuilder/java/org/libreoffice/report/pentaho/SOReportJobFactory.java index a83631261891..4325f7f41e4e 100644 --- a/reportbuilder/java/org/libreoffice/report/pentaho/SOReportJobFactory.java +++ b/reportbuilder/java/org/libreoffice/report/pentaho/SOReportJobFactory.java @@ -91,7 +91,7 @@ public class SOReportJobFactory "org.libreoffice.report.pentaho.SOReportJobFactory"; private final PropertySetMixin m_prophlp; /** - * The initial component contextr, that gives access to the service manager, supported singletons, ... It's + * The initial component context, that gives access to the service manager, supported singletons, ... It's * often later used */ private final XComponentContext m_cmpCtx; @@ -132,7 +132,7 @@ public class SOReportJobFactory } /** - * This method is a simple helper function to used in the static component initialisation functions as well as + * This method is a simple helper function to be used in the static component initialisation functions as well as * in getSupportedServiceNames. */ private static String[] getServiceNames() diff --git a/reportbuilder/java/org/libreoffice/report/pentaho/output/text/TextRawReportTarget.java b/reportbuilder/java/org/libreoffice/report/pentaho/output/text/TextRawReportTarget.java index 302e6908914b..7f279356c8a9 100644 --- a/reportbuilder/java/org/libreoffice/report/pentaho/output/text/TextRawReportTarget.java +++ b/reportbuilder/java/org/libreoffice/report/pentaho/output/text/TextRawReportTarget.java @@ -347,7 +347,7 @@ public class TextRawReportTarget extends OfficeDocumentReportTarget // This is a rather cheap solution to the problem. In a sane world, we would have to feed the // footer multiple times. Right now, we simply rely on the balancing, which should make sure that - // the column's content are evenly distributed. + // the columns' contents are evenly distributed. final XmlWriter writer = getXmlWriter(); final AttributeList attrs = new AttributeList(); attrs.setAttribute(OfficeNamespaces.TEXT_NS, OfficeToken.STYLE_NAME, generateSectionStyle(numberOfColumns)); @@ -932,7 +932,7 @@ public class TextRawReportTarget extends OfficeDocumentReportTarget if (addKeepWithNext) { tableProps.setAttribute(OfficeNamespaces.FO_NS, KEEP_WITH_NEXT, ALWAYS); - // A keep-with-next does not work, if the may-break-betweek rows is not set to false .. + // A keep-with-next does not work, if the may-break-between rows is not set to false .. } } attrs.setAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME, style.getStyleName()); @@ -957,7 +957,7 @@ public class TextRawReportTarget extends OfficeDocumentReportTarget final OfficeStyle style = deriveStyle(OfficeToken.TABLE, styleName); final Element tableProps = produceFirstChild(style, OfficeNamespaces.STYLE_NS, TABLE_PROPERTIES); - // A keep-with-next does not work, if the may-break-betweek rows is not set to false .. + // A keep-with-next does not work, if the may-break-between rows is not set to false .. tableProps.setAttribute(OfficeNamespaces.STYLE_NS, MAY_BREAK_BETWEEN_ROWS, OfficeToken.FALSE); final String hasGroupFooter = (String) attrs.getAttribute(JFreeReportInfo.REPORT_NAMESPACE, "has-group-footer"); if (hasGroupFooter != null && hasGroupFooter.equals(OfficeToken.TRUE)) diff --git a/reportdesign/CppunitTest_reportdesign_dialogs_test.mk b/reportdesign/CppunitTest_reportdesign_dialogs_test.mk index 7f0bccf2064a..15ddb5fe25c4 100644 --- a/reportdesign/CppunitTest_reportdesign_dialogs_test.mk +++ b/reportdesign/CppunitTest_reportdesign_dialogs_test.mk @@ -17,12 +17,6 @@ $(eval $(call gb_CppunitTest_add_exception_objects,reportdesign_dialogs_test, \ $(eval $(call gb_CppunitTest_use_sdk_api,reportdesign_dialogs_test)) -$(eval $(call gb_CppunitTest_set_include,desktop_dialogs_test,\ - -I$(SRCDIR)/reportdesign/source/inc \ - -I$(SRCDIR)/reportdesign/inc \ - $$(INCLUDE) \ -)) - $(eval $(call gb_CppunitTest_use_libraries,reportdesign_dialogs_test, \ basegfx \ comphelper \ diff --git a/reportdesign/Library_rpt.mk b/reportdesign/Library_rpt.mk index 4a3d7e3e10c3..a4b7d306e252 100644 --- a/reportdesign/Library_rpt.mk +++ b/reportdesign/Library_rpt.mk @@ -97,6 +97,7 @@ $(eval $(call gb_Library_add_exception_objects,rpt,\ reportdesign/source/filter/xml/xmlCondPrtExpr \ reportdesign/source/filter/xml/xmlControlProperty \ reportdesign/source/filter/xml/xmlExport \ + reportdesign/source/filter/xml/xmlExport2 \ reportdesign/source/filter/xml/xmlExportDocumentHandler \ reportdesign/source/filter/xml/xmlfilter \ reportdesign/source/filter/xml/xmlFixedContent \ diff --git a/reportdesign/inc/ReportDefinition.hxx b/reportdesign/inc/ReportDefinition.hxx index 1d5fc5ebc86d..18f9d54dfa96 100644 --- a/reportdesign/inc/ReportDefinition.hxx +++ b/reportdesign/inc/ReportDefinition.hxx @@ -177,6 +177,8 @@ namespace reportdesign create(css::uno::Reference< css::uno::XComponentContext > const & xContext); css::uno::Reference< css::uno::XComponentContext > getContext(); + void setUseRPTTags(bool bUseRPTTags); + bool getUseRPTTags(); private: /** abstract SdrModel provider */ diff --git a/reportdesign/inc/ReportVisitor.hxx b/reportdesign/inc/ReportVisitor.hxx index cdbb6c2e43b5..6a98cda2f8bd 100644 --- a/reportdesign/inc/ReportVisitor.hxx +++ b/reportdesign/inc/ReportVisitor.hxx @@ -16,8 +16,8 @@ * 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_REPORTDESIGN_INC_REPORTVISITOR_HXX -#define INCLUDED_REPORTDESIGN_INC_REPORTVISITOR_HXX + +#pragma once #include #include "dllapi.h" @@ -59,6 +59,4 @@ namespace reportdesign } // namespace reportdesign -#endif // INCLUDED_REPORTDESIGN_INC_REPORTVISITOR_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/inc/pch/precompiled_rpt.hxx b/reportdesign/inc/pch/precompiled_rpt.hxx index 3b85ebe481d9..861e186abe9b 100644 --- a/reportdesign/inc/pch/precompiled_rpt.hxx +++ b/reportdesign/inc/pch/precompiled_rpt.hxx @@ -249,7 +249,6 @@ #include #include #include -#include #include #include #include diff --git a/reportdesign/inc/pch/precompiled_rptui.hxx b/reportdesign/inc/pch/precompiled_rptui.hxx index fe643f3a9976..fd3e6ad8faaa 100644 --- a/reportdesign/inc/pch/precompiled_rptui.hxx +++ b/reportdesign/inc/pch/precompiled_rptui.hxx @@ -159,7 +159,6 @@ #include #include #include -#include #include #include #include @@ -336,11 +335,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include diff --git a/reportdesign/inc/reportformula.hxx b/reportdesign/inc/reportformula.hxx index 6075c460f398..43ab827306ee 100644 --- a/reportdesign/inc/reportformula.hxx +++ b/reportdesign/inc/reportformula.hxx @@ -95,6 +95,8 @@ namespace rptui which indicates a field or an expression. */ OUString getBracketedFieldOrExpression() const; + OUString getFormulaName() const; + bool containsBracketedField() const; }; diff --git a/reportdesign/inc/xmlExport.hxx b/reportdesign/inc/xmlExport.hxx index 67ec9cebf317..f1a351fb0850 100644 --- a/reportdesign/inc/xmlExport.hxx +++ b/reportdesign/inc/xmlExport.hxx @@ -80,7 +80,7 @@ public: typedef ::std::vector< ::std::pair< bool, TRow > > TGrid; typedef ::std::map< Reference ,TGrid > TSectionsGrid; typedef ::std::map< Reference ,Reference > TGroupFunctionMap; -private: +protected: TSectionsGrid m_aSectionsGrid; TPropertyStyleMap m_aAutoStyleNames; @@ -101,20 +101,20 @@ private: rtl::Reference m_pReportDefinition; bool m_bAllreadyFilled; - void exportReport(const Reference& _xReportDefinition); /// + virtual void exportReport(const Reference& _xReportDefinition); /// void exportReportAttributes(const Reference& _xReport); void exportFunctions(const Reference& _xFunctions); /// void exportFunction(const Reference< XFunction>& _xFunction); void exportMasterDetailFields(const Reference& _xReportComponent); - void exportComponent(const Reference& _xReportComponent); - void exportGroup(const Reference& _xReportDefinition,sal_Int32 _nPos,bool _bExportAutoStyle = false); - void exportStyleName(XPropertySet* _xProp,comphelper::AttributeList& _rAtt,const OUString& _sName); - void exportSection(const Reference& _xProp,bool bHeader = false); + virtual void exportComponent(const Reference& _xReportComponent); + virtual void exportGroup(const Reference& _xReportDefinition,sal_Int32 _nPos,bool _bExportAutoStyle = false); + virtual void exportStyleName(XPropertySet* _xProp,comphelper::AttributeList& _rAtt,const OUString& _sName); + virtual void exportSection(const Reference& _xProp,bool bHeader = false); void exportContainer(const Reference< XSection>& _xSection); void exportShapes(const Reference< XSection>& _xSection,bool _bAddParagraph = true); void exportTableColumns(const Reference< XSection>& _xSection); void exportSectionAutoStyle(const Reference& _xProp); - void exportReportElement(const Reference& _xReportElement); + virtual void exportReportElement(const Reference& _xReportElement); void exportFormatConditions(const Reference& _xReportElement); void exportAutoStyle(XPropertySet* _xProp,const Reference& _xParentFormattedField = Reference()); void exportAutoStyle(const Reference& _xProp); @@ -126,7 +126,7 @@ private: bool exportFormula(enum ::xmloff::token::XMLTokenEnum eName,const OUString& _sFormula); void exportGroupsExpressionAsFunction(const Reference< XGroups>& _xGroups); static OUString convertFormula(const OUString& _sFormula); - void handleTextElement(const Reference& xElement, bool bShapeHandled, + virtual void handleTextElement(const Reference& xElement, bool bShapeHandled, const Reference< XSection>& _xSection); void handleNumberFormat(const Reference& xFormattedField); void handleEToken(const Reference& xReportElement, @@ -135,7 +135,6 @@ private: virtual void SetBodyAttributes() override; -protected: virtual void ExportStyles_( bool bUsed ) override; virtual void ExportAutoStyles_() override; @@ -164,6 +163,9 @@ public: createMetaExporter(const Reference& rxContext); static rtl::Reference createExportFilter(const Reference& rxContext); + + static void lcl_adjustColumnSpanOverRows(ORptExport::TSectionsGrid& _rGrid); + static void lcl_calculate(const ::std::vector& _aPosX,const ::std::vector& _aPosY,ORptExport::TGrid& _rColumns); }; diff --git a/reportdesign/inc/xmlExport2.hxx b/reportdesign/inc/xmlExport2.hxx new file mode 100644 index 000000000000..4a607157ad23 --- /dev/null +++ b/reportdesign/inc/xmlExport2.hxx @@ -0,0 +1,103 @@ +/* -*- 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 . + */ + +#pragma once + +#include "xmlExport.hxx" +#include +#include "reportformula.hxx" +#include +#include + +namespace rptxml +{ +using namespace com::sun::star::sdbc; + +class ORptExecuteExport : public ORptExport +{ +public: + ORptExecuteExport(const Reference& _rxContext, + OUString const& implementationName, SvXMLExportFlags nExportFlag); + + virtual ~ORptExecuteExport() override; + +protected: + Reference m_xCalcComponent; // keep-alive for FormulaParser + Reference m_xFormulaParser; + Reference m_xRow; + + void exportGroupsExpressionAsFunction(const Reference& _xGroups); + static OUString getColumnNameString(const Reference& _xReportDefinition); + static OUString getStringFromAny(Any& aAnswer); + static Any callFunction(const Sequence& aArgs, const OUString& sFuncName); + static sal_Int32 getColumnNum(std::u16string_view sColumnName, Reference& xRow); + bool exportFormula(const OUString& _sFormula); + static Reference + getResultSet(const Reference& _xReportDefinition); + // _rOuterBoundary marks, per row, whether an already-processed outer group + // changed there; a set entry forces this group to also break at that row, + // even if its own tracked value happens to coincide with the previous row's. + static std::vector findSubGroups(const Reference& _xGroup, + const Reference& _xResultSet, + const std::vector& _rOuterBoundary); + template + static sal_Int32 compare(T& _value, T& _groupOnValue, sal_Int32& _i, + const Reference& _xResultSet, bool bForceBreak = false); + static sal_Int32 compareQuartal(sal_uInt16 _aMonth, sal_uInt16& _aGroupOnMonth, sal_Int32& _i, + const Reference& _xResultSet, + bool bForceBreak = false); + // Unrelated to (and does not override) ORptExport::exportGroup() below — + // same name because it plays the same conceptual role for the execute + // path, but a different signature, since it doesn't need per-group + // recursion. The `using` declaration silences -Woverloaded-virtual, + // which would otherwise flag this name as hiding the base overload. + using ORptExport::exportGroup; + void exportGroup(const Reference& _xReportDefinition, + bool _bExportAutoStyle = false); + virtual void exportReport(const Reference& _xReportDefinition) override; + virtual void exportStyleName(XPropertySet* _xProp, comphelper::AttributeList& _rAtt, + const OUString& _sName) override; + virtual void + exportReportElement(const Reference& _xReportElement) override; + virtual void exportSection(const Reference& _xProp, bool bHeader = false) override; + virtual void exportComponent(const Reference& _xReportComponent) override; + virtual void handleTextElement(const Reference& xElement, bool bShapeHandled, + const Reference& _xSection) override; + virtual void ExportContent_() override; + +public: + const rtl::Reference& GetCellStylePropertyMapper() const + { + return m_xCellStylesPropertySetMapper; + } + + // Helper methods to create exporters + static rtl::Reference + createSettingsExporter(const Reference& rxContext); + static rtl::Reference + createStylesExporter(const Reference& rxContext); + static rtl::Reference + createMetaExporter(const Reference& rxContext); + static rtl::Reference + createExportFilter(const Reference& rxContext); +}; + +} // rptxml + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/qa/unit/ReportDesignBasicTests.cxx b/reportdesign/qa/unit/ReportDesignBasicTests.cxx index 8ea734552f66..2e475e22ee20 100644 --- a/reportdesign/qa/unit/ReportDesignBasicTests.cxx +++ b/reportdesign/qa/unit/ReportDesignBasicTests.cxx @@ -22,6 +22,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -33,6 +40,10 @@ public: void testLoadingAndSaving(const OUString& rFilterName, const OUString& rReportName, const Reference& xComponentLoader, const Reference& xActiveConnection); + OUString renderReportText(const OUString& rReportName, + const Reference& xComponentLoader, + const Reference& xActiveConnection, + bool bCppReportBuilder); }; CPPUNIT_TEST_FIXTURE(RptBasicTest, roundTripTest) @@ -115,6 +126,149 @@ CPPUNIT_TEST_FIXTURE(RptBasicTest, multiGroupingSameFieldIntervals) } } +CPPUNIT_TEST_FIXTURE(RptBasicTest, nestedGroupBoundary) +{ + // Reproduces a bug where the C++ ReportBuilder path (SAL_ENABLE_PENTAHO_FREE_REPORTBUILDER=1) + // failed to open a new nested group when an inner group's own value coincidentally repeats + // across an outer group's boundary (e.g. Region changes from "North" to "South", but + // SaleMonth's value stays 6 on both sides of that boundary). The nested group's header/footer + // must still appear at the outer boundary and not silently merge the two groups. + // + // ODB file: table "Sales" (Region, SaleMonth, Amount), report "Sales" grouped by + // Region (outer) then SaleMonth (inner, each-value grouping), with a "SaleMonth" label in + // the inner group header. The Java/Pentaho path is treated as the reference/correct output. + loadURLCopy(u"nested_group_boundary.odb"); + + Reference xModel(mxComponent, UNO_QUERY_THROW); + Reference xController(xModel->getCurrentController()); + Reference xUI(xController, UNO_QUERY_THROW); + + xUI->connect(); + Reference xActiveConnection = xUI->getActiveConnection(); + + Reference xSupp(xModel, UNO_QUERY_THROW); + Reference xNameAccess = xSupp->getReportDocuments(); + const Sequence aReportNames(xNameAccess->getElementNames()); + CPPUNIT_ASSERT(aReportNames.hasElements()); + + Reference xComponentLoader(xNameAccess, UNO_QUERY_THROW); + + OUString sPentahoText + = renderReportText(aReportNames[0], xComponentLoader, xActiveConnection, false); + OUString sCppText + = renderReportText(aReportNames[0], xComponentLoader, xActiveConnection, true); + + auto countOccurrences = [](const OUString& rText, std::u16string_view rNeedle) { + sal_Int32 nCount = 0; + sal_Int32 nPos = 0; + while ((nPos = rText.indexOf(rNeedle, nPos)) != -1) + { + ++nCount; + nPos += rNeedle.size(); + } + return nCount; + }; + + sal_Int32 nPentahoHeaders = countOccurrences(sPentahoText, u"SaleMonth"); + sal_Int32 nCppHeaders = countOccurrences(sCppText, u"SaleMonth"); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "C++ ReportBuilder path lost a nested SaleMonth group boundary at a Region change", + nPentahoHeaders, nCppHeaders); +} + +CPPUNIT_TEST_FIXTURE(RptBasicTest, emptyCommandNoCrash) +{ + // Executing a report with no Command (query/table) set must fail cleanly + // (IllegalArgumentException) under the C++ ReportBuilder path, same as the + // Pentaho path already does - not reach the undefined behavior that used to + // sit behind an unguarded empty-column-list access in getColumnNameString(). + loadURLCopy(u"nested_group_boundary.odb"); + + Reference xModel(mxComponent, UNO_QUERY_THROW); + Reference xController(xModel->getCurrentController()); + Reference xUI(xController, UNO_QUERY_THROW); + + xUI->connect(); + Reference xActiveConnection = xUI->getActiveConnection(); + + Reference xSupp(xModel, UNO_QUERY_THROW); + Reference xNameAccess = xSupp->getReportDocuments(); + const Sequence aReportNames(xNameAccess->getElementNames()); + CPPUNIT_ASSERT(aReportNames.hasElements()); + + Reference xSubDoc(xNameAccess->getByName(aReportNames[0]), UNO_QUERY_THROW); + Reference xReportDef(xSubDoc->openDesign(), UNO_QUERY_THROW); + xReportDef->setCommand(u""_ustr); + xSubDoc->store(); + xSubDoc->close(); + + const OUString sVarName(u"SAL_ENABLE_PENTAHO_FREE_REPORTBUILDER"_ustr); + osl_setEnvironment(sVarName.pData, u"1"_ustr.pData); + comphelper::ScopeGuard aEnvGuard([&sVarName] { osl_clearEnvironment(sVarName.pData); }); + + ::comphelper::NamedValueCollection aLoadArgs; + aLoadArgs.put(u"ActiveConnection"_ustr, xActiveConnection); + Reference xComponentLoader(xNameAccess, UNO_QUERY_THROW); + + CPPUNIT_ASSERT_THROW(xComponentLoader->loadComponentFromURL(aReportNames[0], u"_blank"_ustr, 0, + aLoadArgs.getPropertyValues()), + lang::IllegalArgumentException); +} + +OUString RptBasicTest::renderReportText(const OUString& rReportName, + const Reference& xComponentLoader, + const Reference& xActiveConnection, + bool bCppReportBuilder) +{ + const OUString sVarName(u"SAL_ENABLE_PENTAHO_FREE_REPORTBUILDER"_ustr); + if (bCppReportBuilder) + osl_setEnvironment(sVarName.pData, u"1"_ustr.pData); + else + osl_clearEnvironment(sVarName.pData); + comphelper::ScopeGuard aEnvGuard([&sVarName] { osl_clearEnvironment(sVarName.pData); }); + + ::comphelper::NamedValueCollection aLoadArgs; + aLoadArgs.put(u"ActiveConnection"_ustr, xActiveConnection); + + Reference xComponent = xComponentLoader->loadComponentFromURL( + rReportName, u"_blank"_ustr, 0, aLoadArgs.getPropertyValues()); + + Reference xTextDoc(xComponent, UNO_QUERY_THROW); + OUStringBuffer sText(xTextDoc->getText()->getString()); + + // Report sections are laid out as Writer tables (one per section instance), not as plain + // body-text paragraphs, so the body text alone is empty - collect every table cell's text too. + Reference xTablesSupp(xComponent, UNO_QUERY); + if (xTablesSupp.is()) + { + Reference xTables(xTablesSupp->getTextTables()); + if (xTables.is()) + { + const Sequence aTableNames = xTables->getElementNames(); + for (const OUString& rTableName : aTableNames) + { + Reference xTable(xTables->getByName(rTableName), UNO_QUERY); + if (!xTable.is()) + continue; + const Sequence aCellNames = xTable->getCellNames(); + for (const OUString& rCellName : aCellNames) + { + Reference xCellText(xTable->getCellByName(rCellName), UNO_QUERY); + if (xCellText.is()) + sText.append(xCellText->getString()); + } + } + } + } + + Reference xCloseable(xComponent, UNO_QUERY); + if (xCloseable.is()) + xCloseable->close(true); + + return sText.makeStringAndClear(); +} + void RptBasicTest::testLoadingAndSaving(const OUString& rFilterName, const OUString& rReportName, const Reference& xComponentLoader, const Reference& xActiveConnection) diff --git a/reportdesign/qa/unit/data/nested_group_boundary.odb b/reportdesign/qa/unit/data/nested_group_boundary.odb new file mode 100644 index 000000000000..d60b2745985a Binary files /dev/null and b/reportdesign/qa/unit/data/nested_group_boundary.odb differ diff --git a/reportdesign/source/core/api/Functions.cxx b/reportdesign/source/core/api/Functions.cxx index 4ac080febf1f..f8857d95ba70 100644 --- a/reportdesign/source/core/api/Functions.cxx +++ b/reportdesign/source/core/api/Functions.cxx @@ -38,7 +38,7 @@ OFunctions::OFunctions(const uno::Reference< report::XFunctionsSupplier >& _xPar { } -// TODO: VirtualFunctionFinder: This is virtual function! +// TODO: VirtualFunctionFinder: This is a virtual function! OFunctions::~OFunctions() { @@ -49,7 +49,7 @@ void SAL_CALL OFunctions::dispose() cppu::WeakComponentImplHelperBase::dispose(); } -// TODO: VirtualFunctionFinder: This is virtual function! +// TODO: VirtualFunctionFinder: This is a virtual function! void SAL_CALL OFunctions::disposing() { diff --git a/reportdesign/source/core/api/ReportDefinition.cxx b/reportdesign/source/core/api/ReportDefinition.cxx index 9663d1c83f97..2559c7524707 100644 --- a/reportdesign/source/core/api/ReportDefinition.cxx +++ b/reportdesign/source/core/api/ReportDefinition.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -510,6 +511,7 @@ struct OReportDefinitionImpl bool m_bModified; bool m_bEscapeProcessing; bool m_bSetModifiedEnabled; + bool m_bUseRPTTags; explicit OReportDefinitionImpl(::osl::Mutex& _aMutex) :m_aStorageChangeListeners(_aMutex) @@ -530,6 +532,7 @@ struct OReportDefinitionImpl ,m_bModified(false) ,m_bEscapeProcessing(true) ,m_bSetModifiedEnabled( true ) + ,m_bUseRPTTags(true) {} }; @@ -1302,8 +1305,11 @@ void SAL_CALL OReportDefinition::storeToStorage( const uno::Reference< embed::XS static constexpr OUString sPropName = u"MediaType"_ustr; OUString sOldMediaType; xProp->getPropertyValue(sPropName) >>= sOldMediaType; - if ( !xProp->getPropertyValue(sPropName).hasValue() || sOldMediaType.isEmpty() || MIMETYPE_OASIS_OPENDOCUMENT_REPORT != sOldMediaType ) - xProp->setPropertyValue( sPropName, uno::Any(MIMETYPE_OASIS_OPENDOCUMENT_REPORT) ); + if (m_pImpl->m_bUseRPTTags) // save a report + { + if ( !xProp->getPropertyValue(sPropName).hasValue() || sOldMediaType.isEmpty() || MIMETYPE_OASIS_OPENDOCUMENT_REPORT != sOldMediaType ) + xProp->setPropertyValue( sPropName, uno::Any(MIMETYPE_OASIS_OPENDOCUMENT_REPORT) ); + } } /** property map for export info set */ @@ -1341,31 +1347,61 @@ void SAL_CALL OReportDefinition::storeToStorage( const uno::Reference< embed::XS pDelegatorArguments[nArgsLen++] <<= xObjectResolver; uno::Reference xCom(getXWeak(),uno::UNO_QUERY); + bool bOk; // Try to write to settings.xml, meta.xml, and styles.xml; only really care about success of // write to content.xml (keeping logic of commit 94ccba3eebc83b58e74e18f0e028c6a995ce6aa6) - xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"settings.xml"_ustr)); - rtl::Reference pSettingsExporter - = rptxml::ORptExport::createSettingsExporter(m_aProps->m_xContext); - WriteThroughComponent(xCom, u"settings.xml"_ustr, pSettingsExporter, aDelegatorArguments, + if (m_pImpl->m_bUseRPTTags) // save a report + { + xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"settings.xml"_ustr)); + rtl::Reference pSettingsExporter + = rptxml::ORptExport::createSettingsExporter(m_aProps->m_xContext); + WriteThroughComponent(xCom, u"settings.xml"_ustr, pSettingsExporter, aDelegatorArguments, _xStorageToSaveTo); - xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"meta.xml"_ustr)); - rtl::Reference pMetaExporter - = rptxml::ORptExport::createMetaExporter(m_aProps->m_xContext); - WriteThroughComponent(xCom, u"meta.xml"_ustr, pMetaExporter, aDelegatorArguments, + xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"meta.xml"_ustr)); + rtl::Reference pMetaExporter + = rptxml::ORptExport::createMetaExporter(m_aProps->m_xContext); + WriteThroughComponent(xCom, u"meta.xml"_ustr, pMetaExporter, aDelegatorArguments, _xStorageToSaveTo); - xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"styles.xml"_ustr)); - rtl::Reference pStylesExporter - = rptxml::ORptExport::createStylesExporter(m_aProps->m_xContext); - WriteThroughComponent(xCom, u"styles.xml"_ustr, pStylesExporter, aDelegatorArguments, + xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"styles.xml"_ustr)); + rtl::Reference pStylesExporter + = rptxml::ORptExport::createStylesExporter(m_aProps->m_xContext); + WriteThroughComponent(xCom, u"styles.xml"_ustr, pStylesExporter, aDelegatorArguments, _xStorageToSaveTo); - xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"content.xml"_ustr)); - rtl::Reference pExportFilter - = rptxml::ORptExport::createExportFilter(m_aProps->m_xContext); - bool bOk = WriteThroughComponent(xCom, u"content.xml"_ustr, pExportFilter, aDelegatorArguments, - _xStorageToSaveTo); + xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"content.xml"_ustr)); + rtl::Reference pExportFilter + = rptxml::ORptExport::createExportFilter(m_aProps->m_xContext); + bOk = WriteThroughComponent(xCom, u"content.xml"_ustr, pExportFilter, aDelegatorArguments, + _xStorageToSaveTo); + } + else // execute a report + { + xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"settings.xml"_ustr)); + rtl::Reference pSettingsExporter + = rptxml::ORptExecuteExport::createSettingsExporter(m_aProps->m_xContext); + WriteThroughComponent(xCom, u"settings.xml"_ustr, pSettingsExporter, aDelegatorArguments, + _xStorageToSaveTo); + + xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"meta.xml"_ustr)); + rtl::Reference pMetaExporter + = rptxml::ORptExecuteExport::createMetaExporter(m_aProps->m_xContext); + WriteThroughComponent(xCom, u"meta.xml"_ustr, pMetaExporter, aDelegatorArguments, + _xStorageToSaveTo); + + xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"styles.xml"_ustr)); + rtl::Reference pStylesExporter + = rptxml::ORptExecuteExport::createStylesExporter(m_aProps->m_xContext); + WriteThroughComponent(xCom, u"styles.xml"_ustr, pStylesExporter, aDelegatorArguments, + _xStorageToSaveTo); + + xInfoSet->setPropertyValue(u"StreamName"_ustr, uno::Any(u"content.xml"_ustr)); + rtl::Reference pExportFilter + = rptxml::ORptExecuteExport::createExportFilter(m_aProps->m_xContext); + bOk = WriteThroughComponent(xCom, u"content.xml"_ustr, pExportFilter, aDelegatorArguments, + _xStorageToSaveTo); + } uno::Any aImage; uno::Reference< embed::XVisualObject > xCurrentController(getCurrentController(),uno::UNO_QUERY); @@ -2622,6 +2658,14 @@ uno::Reference< document::XUndoManager > SAL_CALL OReportDefinition::getUndoMana return m_pImpl->m_pUndoManager; } +void OReportDefinition::setUseRPTTags(bool bUseRPTTags) { + m_pImpl->m_bUseRPTTags = bUseRPTTags; +} + +bool OReportDefinition::getUseRPTTags() { + return m_pImpl->m_bUseRPTTags; +} + }// namespace reportdesign /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/core/api/ReportEngineJFree.cxx b/reportdesign/source/core/api/ReportEngineJFree.cxx index b98f4a92af36..9619d9426d23 100644 --- a/reportdesign/source/core/api/ReportEngineJFree.cxx +++ b/reportdesign/source/core/api/ReportEngineJFree.cxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -164,16 +165,6 @@ OUString OReportEngineJFree::getNewOutputName() if ( pFilter ) sExt = ::comphelper::string::stripStart(pFilter->GetDefaultExtension(), '*'); - uno::Reference< embed::XStorage > xTemp = OStorageHelper::GetTemporaryStorage(/*sFileTemp,embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,*/ m_xContext); - utl::DisposableComponent aTemp(xTemp); - uno::Sequence< beans::PropertyValue > aEmpty; - uno::Reference< beans::XPropertySet> xStorageProp(xTemp,uno::UNO_QUERY); - if ( xStorageProp.is() ) - { - xStorageProp->setPropertyValue( s_sMediaType, uno::Any(sMimeType)); - } - m_pReport->storeToStorage(xTemp, aEmpty); // store to temp file because it may contain information which isn't in the database yet. - OUString sName = m_pReport->getCaption(); if ( sName.isEmpty() ) sName = m_pReport->getName(); @@ -193,39 +184,63 @@ OUString OReportEngineJFree::getNewOutputName() uno::Reference< embed::XStorage > xOut = OStorageHelper::GetStorageFromURL(sFileURL,embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, m_xContext); utl::DisposableComponent aOut(xOut); + uno::Sequence< beans::PropertyValue > aEmpty; + uno::Reference< beans::XPropertySet> xStorageProp(xOut,uno::UNO_QUERY); xStorageProp.set(xOut,uno::UNO_QUERY); if ( xStorageProp.is() ) { xStorageProp->setPropertyValue( s_sMediaType, uno::Any(sMimeType)); } - // some meta data - SvtUserOptions aUserOpts; - OUString sAuthor = aUserOpts.GetFirstName() + - " " + - aUserOpts.GetLastName(); - - uno::Sequence< beans::NamedValue > aConvertedProperties{ - {u"InputStorage"_ustr, uno::Any(xTemp) }, - {u"OutputStorage"_ustr, uno::Any(xOut) }, - {PROPERTY_REPORTDEFINITION, uno::Any(uno::Reference(m_pReport)) }, - {PROPERTY_ACTIVECONNECTION, uno::Any(m_xActiveConnection) }, - {PROPERTY_MAXROWS, uno::Any(m_nMaxRows) }, - {u"Author"_ustr, uno::Any(sAuthor) }, - {u"Title"_ustr, uno::Any(m_pReport->getCaption()) } - }; - OUString sOutputName; - // create job factory and initialize - const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_xContext); - uno::Reference xJob(m_xContext->getServiceManager()->createInstanceWithContext(sReportEngineServiceName,m_xContext),uno::UNO_QUERY_THROW); - if (!m_pReport->getCommand().isEmpty()) + // Set SAL_ENABLE_PENTAHO_FREE_REPORTBUILDER=1 to use the C++ ReportBuilder path + const char* pEnv = getenv("SAL_ENABLE_PENTAHO_FREE_REPORTBUILDER"); + const bool bCppReportBuilder = (pEnv && pEnv[0] == '1' && pEnv[1] == '\0'); + if (bCppReportBuilder) { - xJob->execute(aConvertedProperties); - if ( xStorageProp.is() ) + // C++ ReportBuilder path: uses ORptExecuteExport for direct export with data + if (!m_pReport->getCommand().isEmpty()) { - sOutputName = sFileURL; + m_pReport->setUseRPTTags(false); + comphelper::ScopeGuard aRestoreRPTTags( + [this]() { m_pReport->setUseRPTTags(true); }); + m_pReport->storeToStorage(xOut, aEmpty); + if ( xStorageProp.is() ) + sOutputName = sFileURL; + } + } + else + { + // Default Java (Pentaho) path: creates temp storage, executes report job + uno::Reference< embed::XStorage > xTemp = OStorageHelper::GetTemporaryStorage(m_xContext); + utl::DisposableComponent aTemp(xTemp); + m_pReport->storeToStorage(xTemp, aEmpty); + + // some meta data + SvtUserOptions aUserOpts; + OUString sAuthor = aUserOpts.GetFirstName() + + " " + + aUserOpts.GetLastName(); + + uno::Sequence< beans::NamedValue > aConvertedProperties{ + {u"InputStorage"_ustr, uno::Any(xTemp) }, + {u"OutputStorage"_ustr, uno::Any(xOut) }, + {PROPERTY_REPORTDEFINITION, uno::Any(uno::Reference(m_pReport)) }, + {PROPERTY_ACTIVECONNECTION, uno::Any(m_xActiveConnection) }, + {PROPERTY_MAXROWS, uno::Any(m_nMaxRows) }, + {u"Author"_ustr, uno::Any(sAuthor) }, + {u"Title"_ustr, uno::Any(m_pReport->getCaption()) } + }; + + // create job factory and initialize + const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_xContext); + uno::Reference xJob(m_xContext->getServiceManager()->createInstanceWithContext(sReportEngineServiceName,m_xContext),uno::UNO_QUERY_THROW); + if (!m_pReport->getCommand().isEmpty()) + { + xJob->execute(aConvertedProperties); + if ( xStorageProp.is() ) + sOutputName = sFileURL; } } diff --git a/reportdesign/source/core/misc/reportformula.cxx b/reportdesign/source/core/misc/reportformula.cxx index 21e01a289908..ff3c18455a45 100644 --- a/reportdesign/source/core/misc/reportformula.cxx +++ b/reportdesign/source/core/misc/reportformula.cxx @@ -115,6 +115,23 @@ namespace rptui return "=" + getUndecoratedContent(); } + OUString ReportFormula::getFormulaName() const + { + if (getType() == BindType::Expression) + { + const OUString& sCompleteFormula = getExpression(); + const sal_Int32 nBeginParenthIndex = sCompleteFormula.indexOf('('); + if (nBeginParenthIndex == -1) + return sCompleteFormula; + return sCompleteFormula.copy(0, nBeginParenthIndex); + } + return u""_ustr; + } + + bool ReportFormula::containsBracketedField() const + { + return m_sCompleteFormula.indexOf(u"[") != -1 && m_sCompleteFormula.indexOf(u"]") != -1; + } } // namespace rptui diff --git a/reportdesign/source/filter/xml/xmlExport.cxx b/reportdesign/source/filter/xml/xmlExport.cxx index b617e2f4176c..8eace7e44678 100644 --- a/reportdesign/source/filter/xml/xmlExport.cxx +++ b/reportdesign/source/filter/xml/xmlExport.cxx @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -82,7 +83,7 @@ namespace rptxml } -static void lcl_adjustColumnSpanOverRows(ORptExport::TSectionsGrid& _rGrid) +void ORptExport::lcl_adjustColumnSpanOverRows(ORptExport::TSectionsGrid& _rGrid) { for (auto& rEntry : _rGrid) { @@ -359,7 +360,7 @@ void ORptExport::exportReportElement(const Reference& _xRep exportComponent(_xReportElement); } -static void lcl_calculate(const ::std::vector& _aPosX,const ::std::vector& _aPosY,ORptExport::TGrid& _rColumns) +void ORptExport::lcl_calculate(const ::std::vector& _aPosX,const ::std::vector& _aPosY,ORptExport::TGrid& _rColumns) { sal_Int32 nCountX = _aPosX.size() - 1; sal_Int32 nCountY = _aPosY.size() - 1; @@ -646,6 +647,7 @@ void ORptExport::exportSection(const Reference& _xSection,bool bHeader SvXMLElementExport aPrintExpr(*this,XML_NAMESPACE_REPORT, XML_CONDITIONAL_PRINT_EXPRESSION, true, false); } + exportTableColumns(_xSection); exportContainer(_xSection); } @@ -668,8 +670,6 @@ void ORptExport::exportContainer(const Reference< XSection>& _xSection) { OSL_ENSURE(_xSection.is(),"Section is NULL -> GPF"); - exportTableColumns(_xSection); - TSectionsGrid::const_iterator aFind = m_aSectionsGrid.find(_xSection); OSL_ENSURE(aFind != m_aSectionsGrid.end(),"ORptExport::exportContainer: Section not found in grid!"); if ( aFind == m_aSectionsGrid.end() ) @@ -883,6 +883,7 @@ void ORptExport::handleTextElement(const Reference& xElement, bool } // write in handleEToken + SvXMLElementExport aComponents(*this,XML_NAMESPACE_REPORT, eToken, false, false); handleEToken(xReportElement, xReportDefinition, xSection, eToken); } } @@ -890,8 +891,6 @@ void ORptExport::handleTextElement(const Reference& xElement, bool void ORptExport::handleEToken(const Reference& xReportElement, const Reference& xReportDefinition, const Reference& xSection, const XMLTokenEnum& eToken) { - // write - SvXMLElementExport aComponents(*this,XML_NAMESPACE_REPORT, eToken, false, false); if ( eToken == XML_FIXED_CONTENT ) exportParagraph(xReportElement); if ( xReportElement.is() ) diff --git a/reportdesign/source/filter/xml/xmlExport2.cxx b/reportdesign/source/filter/xml/xmlExport2.cxx new file mode 100644 index 000000000000..80590a9e7764 --- /dev/null +++ b/reportdesign/source/filter/xml/xmlExport2.cxx @@ -0,0 +1,991 @@ +/* -*- 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 +#include + +#include +#include "xmlHelper.hxx" +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rptxml +{ +using namespace xmloff; +using namespace comphelper; +using namespace ::com::sun::star; +using namespace ::com::sun::star::report; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; + +ORptExecuteExport::ORptExecuteExport(const Reference& _rxContext, + OUString const& implementationName, + SvXMLExportFlags nExportFlag) + : ORptExport(_rxContext, implementationName, nExportFlag) +{ + // The FormulaParser service requires a Calc document context. + // Keep the hidden document alive for the lifetime of this exporter. + uno::Reference xFactory = _rxContext->getServiceManager(); + uno::Reference xServiceFactory(xFactory, uno::UNO_QUERY); + m_xCalcComponent.set( + xServiceFactory->createInstance(u"com.sun.star.comp.Calc.SpreadsheetDocument"_ustr), + css::uno::UNO_QUERY_THROW); + uno::Reference xSM(m_xCalcComponent, css::uno::UNO_QUERY_THROW); + m_xFormulaParser.set(xSM->createInstance(u"com.sun.star.sheet.FormulaParser"_ustr), UNO_QUERY); + + Reference xParserProps(m_xFormulaParser, uno::UNO_QUERY); + xParserProps->setPropertyValue(u"FormulaConvention"_ustr, + uno::Any(css::sheet::AddressConvention::XL_OOX)); + xParserProps->setPropertyValue(u"RefConventionChartOOXML"_ustr, uno::Any(true)); +} + +ORptExecuteExport::~ORptExecuteExport() +{ + // Release the FormulaParser before disposing the Calc document it depends on + m_xFormulaParser.clear(); + if (m_xCalcComponent.is()) + m_xCalcComponent->dispose(); +} + +void ORptExecuteExport::exportReport(const Reference& _xReportDefinition) +{ + if (!_xReportDefinition.is()) + return; + + if (_xReportDefinition->getReportHeaderOn()) + exportSection(_xReportDefinition->getReportHeader()); + + if (_xReportDefinition->getPageHeaderOn()) + { + OUStringBuffer sValue; + sal_Int16 nRet = _xReportDefinition->getPageHeaderOption(); + const SvXMLEnumMapEntry* aXML_EnumMap = OXMLHelper::GetReportPrintOptions(); + if (SvXMLUnitConverter::convertEnum(sValue, nRet, aXML_EnumMap)) + AddAttribute(XML_NAMESPACE_REPORT, XML_PAGE_PRINT_OPTION, sValue.makeStringAndClear()); + + exportSection(_xReportDefinition->getPageHeader(), true); + } + + // Detail section gets generated + exportGroup(_xReportDefinition, false); + + if (_xReportDefinition->getPageFooterOn()) + { + OUStringBuffer sValue; + sal_Int16 nRet = _xReportDefinition->getPageFooterOption(); + const SvXMLEnumMapEntry* aXML_EnumMap = OXMLHelper::GetReportPrintOptions(); + if (SvXMLUnitConverter::convertEnum(sValue, nRet, aXML_EnumMap)) + AddAttribute(XML_NAMESPACE_REPORT, XML_PAGE_PRINT_OPTION, sValue.makeStringAndClear()); + + exportSection(_xReportDefinition->getPageFooter(), true); + } + if (_xReportDefinition->getReportFooterOn()) + exportSection(_xReportDefinition->getReportFooter()); +} + +void ORptExecuteExport::exportReportElement(const Reference& _xReportElement) +{ + assert(_xReportElement.is() && "_xReportElement is NULL -> GPF"); + if (!_xReportElement->getPrintWhenGroupChange()) + AddAttribute(XML_NAMESPACE_REPORT, XML_PRINT_WHEN_GROUP_CHANGE, XML_FALSE); + + if (!_xReportElement->getPrintRepeatedValues()) + AddAttribute(XML_NAMESPACE_REPORT, XML_PRINT_REPEATED_VALUES, XML_FALSE); + + if (_xReportElement->getCount()) + { + exportFormatConditions(_xReportElement); + } + + OUString sExpr = _xReportElement->getConditionalPrintExpression(); + if (!sExpr.isEmpty()) + { + ORptExport::exportFormula(XML_FORMULA, sExpr); + SvXMLElementExport aPrintExpr(*this, XML_NAMESPACE_REPORT, XML_CONDITIONAL_PRINT_EXPRESSION, + true, true); + } +} + +void ORptExecuteExport::exportSection(const Reference& _xSection, bool bHeader) +{ + assert(_xSection.is() && "Section is NULL -> GPF"); + AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, _xSection->getName()); + + if (!bHeader) + { + OUStringBuffer sValue; + sal_Int16 nRet = _xSection->getForceNewPage(); + const SvXMLEnumMapEntry* aXML_EnumMap = OXMLHelper::GetForceNewPageOptions(); + if (SvXMLUnitConverter::convertEnum(sValue, nRet, aXML_EnumMap)) + AddAttribute(XML_NAMESPACE_REPORT, XML_FORCE_NEW_PAGE, sValue.makeStringAndClear()); + + nRet = _xSection->getNewRowOrCol(); + if (SvXMLUnitConverter::convertEnum(sValue, nRet, aXML_EnumMap)) + AddAttribute(XML_NAMESPACE_REPORT, XML_FORCE_NEW_COLUMN, sValue.makeStringAndClear()); + if (_xSection->getKeepTogether()) + AddAttribute(XML_NAMESPACE_REPORT, XML_KEEP_TOGETHER, XML_TRUE); + } + + exportStyleName(_xSection.get(), GetAttrList(), m_sTableStyle); + + /// TODO export as table layout + SvXMLElementExport aComponents(*this, XML_NAMESPACE_TABLE, XML_TABLE, true, true); + + OUString sExpr = _xSection->getConditionalPrintExpression(); + if (!sExpr.isEmpty()) + { + ORptExport::exportFormula(XML_FORMULA, sExpr); + SvXMLElementExport aPrintExpr(*this, XML_NAMESPACE_REPORT, XML_CONDITIONAL_PRINT_EXPRESSION, + true, false); + } + exportTableColumns(_xSection); + exportContainer(_xSection); +} + +void ORptExecuteExport::handleTextElement(const Reference& xElement, + bool bShapeHandled, const Reference& _xSection) +{ + if (!bShapeHandled) + exportShapes(_xSection, false); + + uno::Reference xShape(xElement, uno::UNO_QUERY); + uno::Reference xFixedLine(xElement, uno::UNO_QUERY); + if (!xShape.is() && !xFixedLine.is()) + { + Reference xReportElement(xElement, uno::UNO_QUERY); + Reference xReportDefinition(xElement, uno::UNO_QUERY); + Reference xImage(xElement, uno::UNO_QUERY); + Reference xSection(xElement, uno::UNO_QUERY); + + XMLTokenEnum eToken = XML_SECTION; + bool bExportData = false; + bool bPageSet = false; + if (xElement->supportsService(SERVICE_FIXEDTEXT)) + { + eToken = XML_FIXED_CONTENT; + } + else if (xElement->supportsService(SERVICE_FORMATTEDFIELD)) + { + eToken = XML_FORMATTED_TEXT; + bExportData = true; + } + else if (xElement->supportsService(SERVICE_IMAGECONTROL)) + { + eToken = XML_IMAGE; + OUString sTargetLocation = xImage->getImageURL(); + if (!sTargetLocation.isEmpty()) + { + sTargetLocation = GetRelativeReference(sTargetLocation); + AddAttribute(XML_NAMESPACE_FORM, XML_IMAGE_DATA, sTargetLocation); + } + bExportData = true; + OUStringBuffer sValue; + const SvXMLEnumMapEntry* aXML_ImageScaleEnumMap + = OXMLHelper::GetImageScaleOptions(); + if (SvXMLUnitConverter::convertEnum(sValue, xImage->getScaleMode(), + aXML_ImageScaleEnumMap)) + AddAttribute(XML_NAMESPACE_REPORT, XML_SCALE, sValue.makeStringAndClear()); + } + else if (xReportDefinition.is()) + { + eToken = XML_SUB_DOCUMENT; + } + if (bExportData) + { + SvXMLElementExport aParagraphContent(*this, XML_NAMESPACE_TEXT, XML_P, false, false); + bool bPrevCharIsSpace = false; + + rptui::ReportFormula aFormula(xReportElement->getDataField()); + + // Field + if (aFormula.getType() == rptui::ReportFormula::BindType::Field && aFormula.isValid()) + GetTextParagraphExport()->exportCharacterData( + m_xRow->getString(getColumnNum(aFormula.getFieldName(), m_xRow)), + bPrevCharIsSpace); + + // Expression + if (aFormula.getType() == rptui::ReportFormula::BindType::Expression + && aFormula.isValid()) + { + OUStringBuffer aFormulaCopy(aFormula.getExpression()); + //TODO sort out bPageSet + bPageSet = false; //? Making this false for now, need to investigate + + // A BracketedField is a database column + // Get the column name(s) from the Formula and substitute the value + if (aFormula.containsBracketedField()) + { + while (aFormulaCopy.indexOf(u"[") != -1 && aFormulaCopy.indexOf(u"]") != -1) + { + sal_Int32 nBeginBracketIndex = aFormulaCopy.indexOf(u"["); + sal_Int32 nEndBracketIndex = aFormulaCopy.indexOf(u"]") + 1; + OUString sFieldName = aFormulaCopy + .copy(nBeginBracketIndex + 1, + (nEndBracketIndex - 2) - nBeginBracketIndex) + .toString(); + // TODO: Need checking here to make sure the FieldName is an actual Database Column name + aFormulaCopy.remove(nBeginBracketIndex, + nEndBracketIndex - nBeginBracketIndex); + aFormulaCopy.insert(nBeginBracketIndex, + m_xRow->getString(getColumnNum(sFieldName, m_xRow))); + } + bPageSet = exportFormula(aFormulaCopy.toString()); + } + else + bPageSet = exportFormula(aFormula.getExpression()); + } + if (bPageSet) + eToken = XML_FIXED_CONTENT; + else if (eToken == XML_IMAGE) + AddAttribute(XML_NAMESPACE_REPORT, XML_PRESERVE_IRI, + xImage->getPreserveIRI() ? XML_TRUE : XML_FALSE); + } + + handleEToken(xReportElement, xReportDefinition, xSection, eToken); + } +} + +bool ORptExecuteExport::exportFormula(const OUString& _sFormula) +{ + const OUString sFieldData = ORptExport::convertFormula(_sFormula); + + sal_Int32 nPageNumberIndex = sFieldData.indexOf("PageNumber()"); + sal_Int32 nPageCountIndex = sFieldData.indexOf("PageCount()"); + bool bRet = nPageNumberIndex != -1 || nPageCountIndex != -1; + + Sequence aTokens + = m_xFormulaParser->parseFormula(_sFormula, table::CellAddress(0, 0, 0)); + + ::std::vector vParams; + + // Collect parameters + if (aTokens.getLength() != -1) + { + for (sal_Int32 i = 0; i < aTokens.getLength(); i++) + { + if (aTokens[i].OpCode == 0) + { + vParams.push_back(aTokens[i].Data); + } + } + } + + const Sequence aParams = comphelper::containerToSequence(vParams); + + if (!bRet) + { + // Extract the function name from the actual formula string being evaluated, + // not from the original (possibly unsubstituted) ReportFormula object + //TODO if the functions parameters are not formatted correctly we get an ugly + // xml formatting error + const sal_Int32 nParen = _sFormula.indexOf('('); + if (nParen != -1) + { + const OUString sFuncName = _sFormula.copy(0, nParen); + Any aAnswer = callFunction(aParams, sFuncName); + bool bPrevCharIsSpace = false; + OUString aRet = getStringFromAny(aAnswer); + GetTextParagraphExport()->exportCharacterData(aRet, bPrevCharIsSpace); + } + } + return bRet; +} + +void ORptExecuteExport::exportComponent(const Reference& _xReportComponent) +{ + OSL_ENSURE(_xReportComponent.is(), "No component interface!"); + if (!_xReportComponent.is()) + return; + + AddAttribute(XML_NAMESPACE_DRAW, XML_NAME, _xReportComponent->getName()); +} + +void ORptExecuteExport::exportStyleName(XPropertySet* _xProp, comphelper::AttributeList& _rAtt, + const OUString& _sName) +{ + Reference xFind(_xProp); + TPropertyStyleMap::const_iterator aFind = m_aAutoStyleNames.find(xFind); + if (aFind != m_aAutoStyleNames.end()) + { + _rAtt.AddAttribute(_sName, aFind->second); + } +} + +void ORptExecuteExport::exportGroup(const Reference& _xReportDefinition, + bool _bExportAutoStyle) +{ + if (!_xReportDefinition.is()) + return; + + Reference xGroups = _xReportDefinition->getGroups(); + if (!xGroups.is()) + return; + + Reference xResultSet = getResultSet(m_pReportDefinition); + Reference xRow(xResultSet, UNO_QUERY); + m_xRow = xRow; + + if (xGroups->getCount() > 0) + { + std::vector> vSubGroups; + // Rows where an already-processed outer group changed; passed to each + // subsequent (inner) group so its boundaries are forced to align with + // its outer group's, even on a coincidental own-value repeat. + std::vector vOuterBoundary; + for (sal_Int32 i = 0; i < xGroups->getCount(); ++i) + { + // The database driver sets the ResultSet type, so we can't be sure + // that we can set it to SCROLL_XXX, i.e. we can't rewind the ResultSet + // so use a second ResultSet here as a workaround + Reference xResultSet2 = getResultSet(_xReportDefinition); + Reference xGroup(xGroups->getByIndex(i), uno::UNO_QUERY); + std::vector vThisGroup = findSubGroups(xGroup, xResultSet2, vOuterBoundary); + + if (vOuterBoundary.empty() && !vThisGroup.empty()) + vOuterBoundary.assign(vThisGroup.size(), false); + for (size_t nRow = 1; nRow < vThisGroup.size(); ++nRow) + if (vThisGroup[nRow] != vThisGroup[nRow - 1]) + vOuterBoundary[nRow] = true; + + vSubGroups.push_back(std::move(vThisGroup)); + } + + std::vector vPrevSubGroup(vSubGroups.size(), 0); + sal_Int32 counter = 0; + + while (xResultSet->next()) + { + for (size_t nGroupNum = 0; nGroupNum < vSubGroups.size(); ++nGroupNum) + { + Reference xGroup(xGroups->getByIndex(nGroupNum), uno::UNO_QUERY); + + // Empty expression, single implicit group: header on first row only + if (vSubGroups[nGroupNum].empty()) + { + if (xResultSet->isFirst() && xGroup->getHeaderOn()) + { + if (_bExportAutoStyle) + exportSectionAutoStyle(xGroup->getHeader()); + else + exportSection(xGroup->getHeader()); + } + continue; + } + + if (xResultSet->isFirst()) + { + if (xGroup->getHeaderOn()) + { + if (_bExportAutoStyle) + exportSectionAutoStyle(xGroup->getHeader()); + else + exportSection(xGroup->getHeader()); + } + } + else if (vSubGroups[nGroupNum][counter] != vPrevSubGroup[nGroupNum]) + { + vPrevSubGroup[nGroupNum] = vSubGroups[nGroupNum][counter]; + if (xGroup->getHeaderOn()) + { + if (_bExportAutoStyle) + exportSectionAutoStyle(xGroup->getHeader()); + else + exportSection(xGroup->getHeader()); + } + } + } + + exportSection(_xReportDefinition->getDetail()); + + for (sal_Int32 nGroupNum = vSubGroups.size() - 1; nGroupNum >= 0; --nGroupNum) + { + Reference xGroup(xGroups->getByIndex(nGroupNum), uno::UNO_QUERY); + + // Empty expression, single implicit group: footer on last row only + if (vSubGroups[nGroupNum].empty()) + { + if (xResultSet->isLast() && xGroup->getFooterOn()) + { + if (_bExportAutoStyle) + exportSectionAutoStyle(xGroup->getFooter()); + else + exportSection(xGroup->getFooter()); + } + continue; + } + + if (xResultSet->isLast()) + { + if (xGroup->getFooterOn()) + { + if (_bExportAutoStyle) + exportSectionAutoStyle(xGroup->getFooter()); + else + exportSection(xGroup->getFooter()); + } + } + else if (vSubGroups[nGroupNum][counter + 1] != vPrevSubGroup[nGroupNum]) + { + if (xGroup->getFooterOn()) + { + if (_bExportAutoStyle) + exportSectionAutoStyle(xGroup->getFooter()); + else + exportSection(xGroup->getFooter()); + } + } + } + ++counter; + } + } + else if (_bExportAutoStyle) + { + while (xResultSet->next()) + { + exportSectionAutoStyle(_xReportDefinition->getDetail()); + } + } + else + { + while (xResultSet->next()) + { + exportSection(_xReportDefinition->getDetail(), false); + } + } +} + +void ORptExecuteExport::ExportContent_() { exportReport(m_pReportDefinition); } + +void ORptExecuteExport::exportGroupsExpressionAsFunction(const Reference& _xGroups) +{ + if (!_xGroups.is()) + return; + + uno::Reference xFunctions = _xGroups->getReportDefinition()->getFunctions(); + const sal_Int32 nCount = _xGroups->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference xGroup(_xGroups->getByIndex(i), uno::UNO_QUERY_THROW); + const ::sal_Int16 nGroupOn = xGroup->getGroupOn(); + if (nGroupOn != report::GroupOn::DEFAULT) + { + uno::Reference xFunction = xFunctions->createFunction(); + OUString sFunction, sPrefix, sPostfix; + OUString sExpression = xGroup->getExpression(); + OUString sFunctionName; + OUString sInitialFormula; + switch (nGroupOn) + { + case report::GroupOn::PREFIX_CHARACTERS: + sFunction = "LEFT"; + sPrefix = ";" + OUString::number(xGroup->getGroupInterval()); + break; + case report::GroupOn::YEAR: + sFunction = "YEAR"; + break; + case report::GroupOn::QUARTAL: + sFunction = "INT((MONTH"; + sPostfix = "-1)/3)+1"; + sFunctionName = "QUARTAL_" + sExpression; + break; + case report::GroupOn::MONTH: + sFunction = "MONTH"; + break; + case report::GroupOn::WEEK: + sFunction = "WEEK"; + break; + case report::GroupOn::DAY: + sFunction = "DAY"; + break; + case report::GroupOn::HOUR: + sFunction = "HOUR"; + break; + case report::GroupOn::MINUTE: + sFunction = "MINUTE"; + break; + case report::GroupOn::INTERVAL: + { + sFunction = "INT"; + uno::Reference xCountFunction = xFunctions->createFunction(); + xCountFunction->setInitialFormula( + beans::Optional(true, u"rpt:0"_ustr)); + OUString sCountName = sFunction + "_count_" + sExpression; + xCountFunction->setName(sCountName); + xCountFunction->setFormula("rpt:[" + sCountName + "] + 1"); + exportFunction(xCountFunction); + sExpression = sCountName; + // The reference to sCountName in the formula of sFunctionName refers to the *old* value + // so we need to expand the formula of sCountName + sPrefix = " + 1) / " + OUString::number(xGroup->getGroupInterval()); + sFunctionName = sFunction + "_" + sExpression; + sFunction += "("; + sInitialFormula = "rpt:0"; + } + break; + default:; + } + if (sFunctionName.isEmpty()) + sFunctionName = sFunction + "_" + sExpression; + if (!sFunction.isEmpty()) + { + const sal_Unicode pReplaceChars[] + = { '(', ')', ';', ',', '+', '-', '[', ']', '/', '*' }; + for (sal_Unicode ch : pReplaceChars) + sFunctionName = sFunctionName.replace(ch, '_'); + + xFunction->setName(sFunctionName); + if (!sInitialFormula.isEmpty()) + xFunction->setInitialFormula(beans::Optional(true, sInitialFormula)); + sFunction = "rpt:" + sFunction + "([" + sExpression + "]"; + + if (!sPrefix.isEmpty()) + sFunction += sPrefix; + sFunction += ")"; + if (!sPostfix.isEmpty()) + sFunction += sPostfix; + xFunction->setFormula(sFunction); + exportFunction(xFunction); + m_aGroupFunctionMap.emplace(xGroup, xFunction); + } + } + } +} + +rtl::Reference +ORptExecuteExport::createSettingsExporter(const Reference& rxContext) +{ + return new ORptExecuteExport(rxContext, u"com.sun.star.comp.report.XMLSettingsExporter"_ustr, + SvXMLExportFlags::SETTINGS); +} + +rtl::Reference +ORptExecuteExport::createStylesExporter(const Reference& rxContext) +{ + return new ORptExecuteExport(rxContext, u"com.sun.star.comp.report.XMLStylesExporter"_ustr, + SvXMLExportFlags::STYLES | SvXMLExportFlags::MASTERSTYLES + | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::FONTDECLS + | SvXMLExportFlags::OASIS); +} + +rtl::Reference +ORptExecuteExport::createMetaExporter(const Reference& rxContext) +{ + return new ORptExecuteExport(rxContext, u"com.sun.star.comp.report.XMLMetaExporter"_ustr, + SvXMLExportFlags::META); +} + +rtl::Reference +ORptExecuteExport::createExportFilter(const Reference& rxContext) +{ + return new ORptExecuteExport(rxContext, u"com.sun.star.comp.report.ExportFilter"_ustr, + SvXMLExportFlags::CONTENT | SvXMLExportFlags::AUTOSTYLES + | SvXMLExportFlags::FONTDECLS); +} + +// A helper function that is given a Column Name and returns the Column Number +sal_Int32 ORptExecuteExport::getColumnNum(std::u16string_view sColumnName, Reference& xRow) +{ + Reference xColumns(xRow, UNO_QUERY); + if (!xColumns.is()) + return -1; + Reference xColumnAccess(xColumns->getColumns()); + Sequence sColumnNames = xColumnAccess->getElementNames(); + for (sal_Int32 i = 0; i < sColumnNames.getLength(); i++) + { + if (sColumnNames[i] == sColumnName) + return i + 1; //database columns start at 1 + } + return -1; +} + +// A helper function to build a list of comma-separated Column Names +// To be used in a SQL statement +OUString +ORptExecuteExport::getColumnNameString(const Reference& _xReportDefinition) +{ + Reference xHoldAlive; + uno::Reference xColumns; + xColumns = dbtools::getFieldsByCommandDescriptor(_xReportDefinition->getActiveConnection(), + _xReportDefinition->getCommandType(), + _xReportDefinition->getCommand(), xHoldAlive); + OUString sColumnNameList; + Sequence sColumnNames = xColumns->getElementNames(); + if (!sColumnNames.hasElements()) + return sColumnNameList; + + for (sal_Int32 i = 0; i < sColumnNames.getLength() - 1; i++) + { + sColumnNameList = sColumnNameList + u"\""_ustr + sColumnNames[i] + u"\", "_ustr; + } + sColumnNameList + = sColumnNameList + u"\""_ustr + sColumnNames[sColumnNames.getLength() - 1] + u"\""_ustr; + return sColumnNameList; +} + +Any ORptExecuteExport::callFunction(const Sequence& aArgs, const OUString& sFuncName) +{ + Reference xFunc; + Reference xFactory(getProcessServiceFactory()); + if (xFactory.is()) + { + xFunc.set(xFactory->createInstance(u"com.sun.star.sheet.FunctionAccess"_ustr), + UNO_QUERY_THROW); + } + Any aRet = xFunc->callFunction(sFuncName, aArgs); + return aRet; +} + +OUString ORptExecuteExport::getStringFromAny(Any& aAnswer) +{ + OUString aRet; + switch (aAnswer.getValueTypeClass()) + { + case uno::TypeClass_STRING: + { + aAnswer >>= aRet; + break; + } + case uno::TypeClass_DOUBLE: + { + double nAnswer; + aAnswer >>= nAnswer; + aRet = OUString::number(nAnswer); + break; + } + default: + { + OSL_FAIL("Unrecognized return Type in ReportDesign"); + } + } + return aRet; +} + +Reference +ORptExecuteExport::getResultSet(const Reference& _xReportDefinition) +{ + Reference xConnection = _xReportDefinition->getActiveConnection(); + Reference xStatement = xConnection->createStatement(); + OUString sCommand = _xReportDefinition->getCommand(); + + OUString sColumnNames = getColumnNameString(_xReportDefinition); + + Reference xGroups = _xReportDefinition->getGroups(); + sal_Int32 nCount = xGroups.is() ? xGroups->getCount() : 0; + + OUString sOrderByStatement; + + if (nCount > 0) + { + bool bFirst = true; + for (sal_Int32 nPos = 0; nPos < nCount; ++nPos) + { + Reference xGroup(xGroups->getByIndex(nPos), uno::UNO_QUERY); + const OUString sField = xGroup->getExpression(); + + if (sField.isEmpty()) + continue; + + if (bFirst) + { + sOrderByStatement = u" ORDER BY "_ustr; + bFirst = false; + } + else + sOrderByStatement += u", "_ustr; + + sOrderByStatement += u"\""_ustr + sField + u"\""_ustr + + (xGroup->getSortAscending() ? u" ASC"_ustr : u" DESC"_ustr); + } + } + + // The report's command can name a table, a stored query, or be a free-form + // SQL statement; each needs different treatment to end up in the FROM + // clause of a valid SELECT. + OUString sFromClause; + switch (_xReportDefinition->getCommandType()) + { + case sdb::CommandType::TABLE: + { + OUString sCatalog, sSchema, sTable; + dbtools::qualifiedNameComponents(xConnection->getMetaData(), sCommand, sCatalog, + sSchema, sTable, + dbtools::EComposeRule::InDataManipulation); + sFromClause + = dbtools::composeTableNameForSelect(xConnection, sCatalog, sSchema, sTable); + break; + } + case sdb::CommandType::QUERY: + { + OUString sQueryCommand; + Reference xQueriesAccess(xConnection, UNO_QUERY); + Reference xQueries( + xQueriesAccess.is() ? xQueriesAccess->getQueries() : nullptr); + if (xQueries.is() && xQueries->hasByName(sCommand)) + { + Reference xQuery(xQueries->getByName(sCommand), UNO_QUERY); + if (xQuery.is()) + xQuery->getPropertyValue(u"Command"_ustr) >>= sQueryCommand; + } + sFromClause = u"("_ustr + sQueryCommand + u") AS \"T_ReportSource\""_ustr; + break; + } + default: // sdb::CommandType::COMMAND: sCommand is already a full SQL statement + sFromClause = u"("_ustr + sCommand + u") AS \"T_ReportSource\""_ustr; + break; + } + + Reference xResultSet = xStatement->executeQuery( + u"SELECT "_ustr + sColumnNames + u" FROM "_ustr + sFromClause + sOrderByStatement); + + return xResultSet; +} + +template +sal_Int32 ORptExecuteExport::compare(T& _value, T& _groupOnValue, sal_Int32& _i, + const Reference& _xResultSet, bool bForceBreak) +{ + if (_value != _groupOnValue || bForceBreak) + { + _groupOnValue = _value; + if (!_xResultSet->isFirst()) + ++_i; + } + return _i; +} + +sal_Int32 ORptExecuteExport::compareQuartal(sal_uInt16 _aMonth, sal_uInt16& _aGroupOnMonth, + sal_Int32& _i, const Reference& _xResultSet, + bool bForceBreak) +{ + sal_uInt16 nQuarter = std::ceil(_aMonth / 3.0); + if (_xResultSet->isFirst()) + _aGroupOnMonth = std::ceil(_aGroupOnMonth / 3.0); + return compare(nQuarter, _aGroupOnMonth, _i, _xResultSet, bForceBreak); +} + +std::vector ORptExecuteExport::findSubGroups(const Reference& _xGroup, + const Reference& _xResultSet, + const std::vector& _rOuterBoundary) +{ + const ::sal_Int16 nGroupOn = _xGroup->getGroupOn(); + + OUString sExp = _xGroup->getExpression(); + if (sExp.isEmpty()) + return std::vector(); + + sal_Int32 nInterval = _xGroup->getGroupInterval(); + + Reference xRow(_xResultSet, UNO_QUERY); + OUString sRow; + OUString sCurrentGroupOn; + std::vector vSubGroups = {}; + sal_Int32 i = 0; + sal_Int32 nRepeater = 0; + sal_Int32 nRow = 0; + css::util::Date aDate; + css::util::Date aCurrentGroupOnDate; + css::util::DateTime aDateTime; + css::util::DateTime aCurrentGroupOnDateTime; + sal_uInt16 nGroupOnMonthOfYear = 0; + + while (_xResultSet->next()) + { + // If an outer (already-processed) group changed at this row, this + // group must also break here even if its own value is the same as the previous row's. + const bool bForceBreak + = o3tl::make_unsigned(nRow) < _rOuterBoundary.size() && _rOuterBoundary[nRow]; + + // Currently the UI will allow the user to GroupOn date values + // (Month, Day, etc.) if the table column is a time value. The + // current behavior in this case is to lump all the values into + // one group - see each date related case statement for details. + switch (nGroupOn) + { + case report::GroupOn::PREFIX_CHARACTERS: + { + sRow = xRow->getString(getColumnNum(sExp, xRow)).copy(0, nInterval); + vSubGroups.push_back(compare(sRow, sCurrentGroupOn, i, _xResultSet, bForceBreak)); + break; + } + case report::GroupOn::DEFAULT: + { + sRow = xRow->getString(getColumnNum(sExp, xRow)); + vSubGroups.push_back(compare(sRow, sCurrentGroupOn, i, _xResultSet, bForceBreak)); + break; + } + // There is an option to set the interval when + // grouping on YEAR in the UI, the GroupOn::YEAR + // seems to override the GroupON::PREFIX_CHARACTERS + case report::GroupOn::YEAR: + { + try + { + aDate = xRow->getDate(getColumnNum(sExp, xRow)); + vSubGroups.push_back( + compare(aDate.Year, aCurrentGroupOnDate.Year, i, _xResultSet, bForceBreak)); + } + catch (const com::sun::star::uno::Exception&) + { + vSubGroups.push_back(0); + } + break; + } + case report::GroupOn::QUARTAL: + { + try + { + aDate = xRow->getDate(getColumnNum(sExp, xRow)); + vSubGroups.push_back(compareQuartal(aDate.Month, aCurrentGroupOnDate.Month, i, + _xResultSet, bForceBreak)); + } + catch (const com::sun::star::uno::Exception&) + { + vSubGroups.push_back(0); + } + break; + } + case report::GroupOn::MONTH: + { + try + { + aDate = xRow->getDate(getColumnNum(sExp, xRow)); + vSubGroups.push_back(compare(aDate.Month, aCurrentGroupOnDate.Month, i, + _xResultSet, bForceBreak)); + } + catch (const com::sun::star::uno::Exception&) + { + vSubGroups.push_back(0); + } + break; + } + case report::GroupOn::WEEK: + { + try + { + aDate = xRow->getDate(getColumnNum(sExp, xRow)); + Date aD(aDate.Day, aDate.Month, aDate.Year); + sal_uInt16 nMonthOfYear = aD.GetWeekOfYear(); + vSubGroups.push_back( + compare(nMonthOfYear, nGroupOnMonthOfYear, i, _xResultSet, bForceBreak)); + } + catch (const com::sun::star::uno::Exception&) + { + vSubGroups.push_back(0); + } + break; + } + case report::GroupOn::DAY: + { + try + { + aDate = xRow->getDate(getColumnNum(sExp, xRow)); + vSubGroups.push_back( + compare(aDate.Day, aCurrentGroupOnDate.Day, i, _xResultSet, bForceBreak)); + } + catch (const com::sun::star::uno::Exception&) + { + vSubGroups.push_back(0); + } + break; + } + case report::GroupOn::HOUR: + { + try + { + aDateTime = xRow->getTimestamp(getColumnNum(sExp, xRow)); + vSubGroups.push_back(compare(aDateTime.Hours, aCurrentGroupOnDateTime.Hours, i, + _xResultSet, bForceBreak)); + } + catch (const com::sun::star::uno::Exception&) + { + vSubGroups.push_back(0); + } + break; + } + case report::GroupOn::MINUTE: + { + try + { + aDateTime = xRow->getTimestamp(getColumnNum(sExp, xRow)); + vSubGroups.push_back(compare(aDateTime.Minutes, aCurrentGroupOnDateTime.Minutes, + i, _xResultSet, bForceBreak)); + } + catch (const com::sun::star::uno::Exception&) + { + vSubGroups.push_back(0); + } + break; + } + case report::GroupOn::INTERVAL: + { + if (nRepeater == nInterval || bForceBreak) + { + if (!_xResultSet->isFirst()) + ++i; + nRepeater = 0; + } + vSubGroups.push_back(i); + ++nRepeater; + // Current default behavior for interval = 0 + // is for the first row to be one group and + // all the other rows are their own group + if (nInterval == sal_Int32(0)) + { + i = 1; + nRepeater = -1; + } + break; + } + } + ++nRow; + } + return vSubGroups; +} + +} // rptxml + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/dlg/AddField.cxx b/reportdesign/source/ui/dlg/AddField.cxx index 3e8194dc1200..1578c7ce2c60 100644 --- a/reportdesign/source/ui/dlg/AddField.cxx +++ b/reportdesign/source/ui/dlg/AddField.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include diff --git a/reportdesign/source/ui/dlg/Condition.hxx b/reportdesign/source/ui/dlg/Condition.hxx index 648635acc154..040fd89b695b 100644 --- a/reportdesign/source/ui/dlg/Condition.hxx +++ b/reportdesign/source/ui/dlg/Condition.hxx @@ -27,11 +27,14 @@ #include #include #include +#include #include +#include #include +#include #include #include -#include +#include #include diff --git a/reportdesign/source/ui/dlg/Formula.cxx b/reportdesign/source/ui/dlg/Formula.cxx index a44f66bf4d46..53c4f8da8e8b 100644 --- a/reportdesign/source/ui/dlg/Formula.cxx +++ b/reportdesign/source/ui/dlg/Formula.cxx @@ -17,11 +17,11 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include #include #include #include #include +#include #include #include #include @@ -51,7 +51,7 @@ FormulaDialog::FormulaDialog(weld::Window* pParent , const OUString& _sFormula , css::uno::Reference < css::beans::XPropertySet > _xRowSet , svl::SharedStringPool& rStrPool ) - : FormulaModalDialog( pParent, _pFunctionMgr.get(),this) + : FormulaModalDialog(pParent, _pFunctionMgr.get(), *this) ,m_aFunctionManager(_pFunctionMgr) ,m_xFormulaData(new FormEditData()) ,m_xRowSet(std::move(_xRowSet)) diff --git a/reportdesign/source/ui/dlg/GroupsSorting.cxx b/reportdesign/source/ui/dlg/GroupsSorting.cxx index a57e12e31ea1..e2aad6391afc 100644 --- a/reportdesign/source/ui/dlg/GroupsSorting.cxx +++ b/reportdesign/source/ui/dlg/GroupsSorting.cxx @@ -566,20 +566,21 @@ void OFieldExpressionControl::PaintCell( OutputDevice& rDev, const tools::Rectan EditBrowseBox::RowStatus OFieldExpressionControl::GetRowStatus(sal_Int32 nRow) const { if (nRow >= 0 && nRow == m_nDataPos) - return EditBrowseBox::CURRENT; + return RowStatus::CURRENT; if ( nRow != BROWSER_ENDOFSELECTION && nRow < static_cast(m_aGroupPositions.size()) && m_aGroupPositions[nRow] != NO_GROUP ) { try { uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]); - return (xGroup->getHeaderOn() || xGroup->getFooterOn())? EditBrowseBox::HEADERFOOTER : EditBrowseBox::CLEAN; + return (xGroup->getHeaderOn() || xGroup->getFooterOn()) ? RowStatus::HEADERFOOTER + : RowStatus::CLEAN; } catch(uno::Exception&) { TOOLS_WARN_EXCEPTION( "reportdesign", "Exception caught while try to get a group!"); } } - return EditBrowseBox::CLEAN; + return RowStatus::CLEAN; } // XContainerListener diff --git a/reportdesign/source/ui/dlg/Navigator.cxx b/reportdesign/source/ui/dlg/Navigator.cxx index 216a0deea5dd..ea344b5eebc0 100644 --- a/reportdesign/source/ui/dlg/Navigator.cxx +++ b/reportdesign/source/ui/dlg/Navigator.cxx @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/reportdesign/source/ui/inc/AddField.hxx b/reportdesign/source/ui/inc/AddField.hxx index ea52f56a96aa..93ff257d50b8 100644 --- a/reportdesign/source/ui/inc/AddField.hxx +++ b/reportdesign/source/ui/inc/AddField.hxx @@ -33,8 +33,7 @@ #include #include #include -#include - +#include #include #include "ColumnInfo.hxx" diff --git a/reportdesign/source/ui/inc/CondFormat.hxx b/reportdesign/source/ui/inc/CondFormat.hxx index 12782c56c6c1..1ab4a501ea81 100644 --- a/reportdesign/source/ui/inc/CondFormat.hxx +++ b/reportdesign/source/ui/inc/CondFormat.hxx @@ -21,9 +21,11 @@ #define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_CONDFORMAT_HXX #include +#include #include #include -#include +#include + #include namespace rptui diff --git a/reportdesign/source/ui/inc/DateTime.hxx b/reportdesign/source/ui/inc/DateTime.hxx index d5a9738f3491..c24cf6124105 100644 --- a/reportdesign/source/ui/inc/DateTime.hxx +++ b/reportdesign/source/ui/inc/DateTime.hxx @@ -18,9 +18,13 @@ */ #pragma once +#include +#include #include #include -#include +#include +#include + #include #include #include diff --git a/reportdesign/source/ui/inc/GroupsSorting.hxx b/reportdesign/source/ui/inc/GroupsSorting.hxx index 3eb4a12427c8..84aaf897963b 100644 --- a/reportdesign/source/ui/inc/GroupsSorting.hxx +++ b/reportdesign/source/ui/inc/GroupsSorting.hxx @@ -27,10 +27,12 @@ #include #include #include +#include #include +#include #include #include -#include +#include #include namespace rptui diff --git a/reportdesign/source/ui/inc/Navigator.hxx b/reportdesign/source/ui/inc/Navigator.hxx index 64a22bd0e482..71ef5bf3ab44 100644 --- a/reportdesign/source/ui/inc/Navigator.hxx +++ b/reportdesign/source/ui/inc/Navigator.hxx @@ -21,7 +21,8 @@ #include #include -#include +#include + #include namespace rptui diff --git a/reportdesign/source/ui/inc/PageNumber.hxx b/reportdesign/source/ui/inc/PageNumber.hxx index 5eac2f95b203..ce67e04fac8f 100644 --- a/reportdesign/source/ui/inc/PageNumber.hxx +++ b/reportdesign/source/ui/inc/PageNumber.hxx @@ -19,9 +19,12 @@ #ifndef INCLUDED_REPORTDESIGN_SOURCE_UI_INC_PAGENUMBER_HXX #define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_PAGENUMBER_HXX +#include #include #include -#include +#include +#include + #include namespace rptui diff --git a/reportdesign/source/ui/inc/UITools.hxx b/reportdesign/source/ui/inc/UITools.hxx index 84a5801997a0..dca4389eef75 100644 --- a/reportdesign/source/ui/inc/UITools.hxx +++ b/reportdesign/source/ui/inc/UITools.hxx @@ -114,7 +114,7 @@ namespace rptui const css::uno::Sequence< css::beans::NamedValue >& _rSettings ); - /** notifySystemWindow adds or remove the given window _pToRegister at the Systemwindow found when search _pWindow. + /** notifySystemWindow adds or removes the given window _pToRegister at the Systemwindow found when searching _pWindow. @param pWindow The window which is used to search for the SystemWindow. @param pToRegister @@ -130,7 +130,7 @@ namespace rptui const sal_Int16 ISOVER_IGNORE_CUSTOMSHAPES = 1; - /** checks whether the given rectangle overlapps another OUnoObject object in that view. + /** checks whether the given rectangle overlaps another OUnoObject object in that view. * * \param _rRect * \param _rPage @@ -141,7 +141,7 @@ namespace rptui SdrObject* isOver(const tools::Rectangle& _rRect,SdrPage const & _rPage,SdrView const & _rView,bool _bAllObjects, rtl::Reference _pIgnoreList[], int _nIgnoreListLength); - /** checks whether the given OUnoObject object rectangle overlapps another object in that view. + /** checks whether the given OUnoObject object rectangle overlaps another object in that view. * * \param _pObj * \param _rPage @@ -157,7 +157,7 @@ namespace rptui /** ensures that no control overlaps the given one. * - * \param pControl the control which should place in the section without overlapping + * \param pControl the control which should be placed in the section without overlapping * \param _pReportSection the section * \param _bInsert sal_True when the control should be inserted, otherwise not. */ diff --git a/reportdesign/source/ui/inc/dlgpage.hxx b/reportdesign/source/ui/inc/dlgpage.hxx index 7b680840b16a..9fb09180c03b 100644 --- a/reportdesign/source/ui/inc/dlgpage.hxx +++ b/reportdesign/source/ui/inc/dlgpage.hxx @@ -20,6 +20,7 @@ #define INCLUDED_REPORTDESIGN_SOURCE_UI_INC_DLGPAGE_HXX #include +#include namespace rptui { diff --git a/reportdesign/source/ui/inspection/GeometryHandler.cxx b/reportdesign/source/ui/inspection/GeometryHandler.cxx index d95d04798f80..c0b61d65be14 100644 --- a/reportdesign/source/ui/inspection/GeometryHandler.cxx +++ b/reportdesign/source/ui/inspection/GeometryHandler.cxx @@ -68,7 +68,8 @@ #include #include #include -#include +#include +#include #include #include diff --git a/reportdesign/source/ui/report/DesignView.cxx b/reportdesign/source/ui/report/DesignView.cxx index 4fac73d6e049..f014c46335e7 100644 --- a/reportdesign/source/ui/report/DesignView.cxx +++ b/reportdesign/source/ui/report/DesignView.cxx @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/reportdesign/source/ui/report/ReportController.cxx b/reportdesign/source/ui/report/ReportController.cxx index 4f8059134f28..9a4778661f9b 100644 --- a/reportdesign/source/ui/report/ReportController.cxx +++ b/reportdesign/source/ui/report/ReportController.cxx @@ -69,6 +69,7 @@ #include #include +#include #include #include @@ -122,8 +123,8 @@ #include #include #include +#include #include -#include #include #include @@ -2954,6 +2955,10 @@ uno::Reference< frame::XModel > SAL_CALL OReportController::getModel() return m_xReportDefinition; } +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 16 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif uno::Reference< sdbc::XRowSet > const & OReportController::getRowSet() { OSL_PRECOND( m_xReportDefinition.is(), "OReportController::getRowSet: no report definition?!" ); @@ -2988,6 +2993,9 @@ uno::Reference< sdbc::XRowSet > const & OReportController::getRowSet() return m_xRowSet; } +#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 16 +#pragma GCC diagnostic pop +#endif void OReportController::insertGraphic() { @@ -4231,7 +4239,7 @@ void OReportController::openZoomDialog() try { - SfxItemSetFixed aDescriptor(*pPool); + SfxItemSet aDescriptor(SfxItemSet::makeFixedSfxItemSet (*pPool)); // fill it SvxZoomItem aZoomItem( m_eZoomType, m_nZoomValue, SID_ATTR_ZOOM ); aZoomItem.SetValueSet(SvxZoomEnableFlags::N100|SvxZoomEnableFlags::WHOLEPAGE|SvxZoomEnableFlags::PAGEWIDTH); diff --git a/reportdesign/source/ui/report/ScrollHelper.cxx b/reportdesign/source/ui/report/ScrollHelper.cxx index 13bb334a2587..48a6a6f22a61 100644 --- a/reportdesign/source/ui/report/ScrollHelper.cxx +++ b/reportdesign/source/ui/report/ScrollHelper.cxx @@ -124,7 +124,7 @@ Size OScrollWindowHelper::ResizeScrollBars() { bChanged = false; - // does we need a vertical ScrollBar + // do we need a vertical ScrollBar if ( aOutPixSz.Width() < m_aTotalPixelSize.Width() && !bHVisible ) { bHVisible = true; @@ -132,7 +132,7 @@ Size OScrollWindowHelper::ResizeScrollBars() bChanged = true; } - // does we need a horizontal ScrollBar + // do we need a horizontal ScrollBar if ( aOutPixSz.Height() < m_aTotalPixelSize.Height() && !bVVisible ) { bVVisible = true; diff --git a/reportdesign/source/ui/report/dlgedfunc.cxx b/reportdesign/source/ui/report/dlgedfunc.cxx index 185beca7d5d5..1c698558f220 100644 --- a/reportdesign/source/ui/report/dlgedfunc.cxx +++ b/reportdesign/source/ui/report/dlgedfunc.cxx @@ -526,7 +526,7 @@ void DlgEdFunc::checkMovementAllowed(const MouseEvent& rMEvt) } if (m_rView.IsDragResize()) { - // we resize the object don't resize to above sections + // when we resize the object, don't resize to above sections if ( aPnt.Y() < 0 ) { aPnt.setY( 0 ); @@ -576,7 +576,7 @@ bool DlgEdFunc::isRectangleHit(const MouseEvent& rMEvt) if (rDragStat.GetDragMethod() != nullptr) { SdrObjListIter aIter(m_pParent->getPage(),SdrIterMode::DeepNoGroups); - // loop through all marked objects and check if there new rect overlapps an old one. + // loop through all marked objects and check if their new rect overlaps an old one. for (;;) { SdrObject* pObjIter = aIter.Next(); @@ -759,7 +759,7 @@ bool DlgEdFuncInsert::MouseMove( const MouseEvent& rMEvt ) { if ( m_rView.IsDragResize() ) { - // we resize the object don't resize to above sections + // when we resize the object, don't resize to above sections if ( aPos.Y() < 0 ) { aPos.setY( 0 ); @@ -877,7 +877,7 @@ bool DlgEdFuncSelect::MouseMove( const MouseEvent& rMEvt ) { if ( m_rView.IsDragResize() ) { - // we resize the object don't resize to above sections + // when we resize the object, don't resize to above sections if ( aPnt.Y() < 0 ) { aPnt.setY( 0 ); diff --git a/reportdesign/source/ui/report/propbrw.cxx b/reportdesign/source/ui/report/propbrw.cxx index aa17237b9052..976eeb91f8fc 100644 --- a/reportdesign/source/ui/report/propbrw.cxx +++ b/reportdesign/source/ui/report/propbrw.cxx @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include diff --git a/reportdesign/uiconfig/dbreport/menubar/menubar.xml b/reportdesign/uiconfig/dbreport/menubar/menubar.xml index 2838f320815e..684a9214216e 100644 --- a/reportdesign/uiconfig/dbreport/menubar/menubar.xml +++ b/reportdesign/uiconfig/dbreport/menubar/menubar.xml @@ -21,28 +21,28 @@ - - - + + + - + - - - + + + - + - - + + - + - + @@ -51,224 +51,224 @@ - - + + - - - + + + - + - - - + + + - + - - - - + + + + - - + + - + - + - - - + + + - - - + + + - - + + - - + + - + - - + + - - + + - + - - - + + + - + - + - - - - + + + + - - - + + + - + - - - + + + - - - + + + - - - + + + - + - - + + - + - + - + - - - - + + + + - - + + - + - + - + - - - - - - + + + + + + - + - + - - - - + + + + - - + + - + - - - + + + - - - + + + - + - - + + - - + + - + - + - + - + - + - - - - + + + + - + - - - + + + - + - + @@ -276,20 +276,19 @@ - + - - + - + - + diff --git a/reportdesign/uiconfig/dbreport/ui/backgrounddialog.ui b/reportdesign/uiconfig/dbreport/ui/backgrounddialog.ui index 48fe97f37efb..193211f71ad8 100644 --- a/reportdesign/uiconfig/dbreport/ui/backgrounddialog.ui +++ b/reportdesign/uiconfig/dbreport/ui/backgrounddialog.ui @@ -106,7 +106,7 @@ - reset + reset ok cancel help diff --git a/reportdesign/uiconfig/dbreport/ui/chardialog.ui b/reportdesign/uiconfig/dbreport/ui/chardialog.ui index 44de1512a74a..f8d1902a9e5c 100644 --- a/reportdesign/uiconfig/dbreport/ui/chardialog.ui +++ b/reportdesign/uiconfig/dbreport/ui/chardialog.ui @@ -105,7 +105,7 @@ - reset + reset ok cancel help diff --git a/reportdesign/uiconfig/dbreport/ui/pagedialog.ui b/reportdesign/uiconfig/dbreport/ui/pagedialog.ui index 9f195099a1cc..ec73bc451469 100644 --- a/reportdesign/uiconfig/dbreport/ui/pagedialog.ui +++ b/reportdesign/uiconfig/dbreport/ui/pagedialog.ui @@ -106,7 +106,7 @@ - reset + reset ok cancel help diff --git a/ridljar/com/sun/star/lib/uno/environments/remote/JobQueue.java b/ridljar/com/sun/star/lib/uno/environments/remote/JobQueue.java index 25b9c48d8656..4f6b12d5777b 100644 --- a/ridljar/com/sun/star/lib/uno/environments/remote/JobQueue.java +++ b/ridljar/com/sun/star/lib/uno/environments/remote/JobQueue.java @@ -26,7 +26,7 @@ import com.sun.star.lang.DisposedException; /** * The JobQueue implements a queue for jobs. * - *

                                  For every jobs thread id exists a job queue which is registered + *

                                  For every job's thread id exists a job queue which is registered * at the ThreadPool.

                                  * *

                                  A JobQueue is split into a sync job queue and an async job queue. @@ -168,7 +168,7 @@ public class JobQueue { -- _ref_count; if(_ref_count <= 0) { - // only synchronous queues needs to be removed . + // only synchronous queues need to be removed. if( _sync_jobQueue == null ) _javaThreadPoolFactory.removeJobQueue(this); @@ -221,7 +221,7 @@ public class JobQueue { } } - // always wait for asynchron jobqueue to be finished ! + // always wait for asynchronous jobqueue to be finished ! if(job != null && _async_jobQueue != null) { synchronized(_async_jobQueue) { // wait for async queue to be empty and last job to be done diff --git a/ridljar/source/libreoffice/module-info.java b/ridljar/source/libreoffice/module-info.java index 24e014e4f3bb..e27d80510c2f 100644 --- a/ridljar/source/libreoffice/module-info.java +++ b/ridljar/source/libreoffice/module-info.java @@ -42,7 +42,6 @@ module org.libreoffice.uno exports com.sun.star.deployment.ui; exports com.sun.star.document; exports com.sun.star.drawing; - exports com.sun.star.drawing.framework; exports com.sun.star.embed; exports com.sun.star.form; exports com.sun.star.form.binding; diff --git a/rust_uno/CustomTarget_cargo.mk b/rust_uno/CustomTarget_cargo.mk index c7f56870f419..7f5afeaf5b8a 100644 --- a/rust_uno/CustomTarget_cargo.mk +++ b/rust_uno/CustomTarget_cargo.mk @@ -22,6 +22,6 @@ $(call gb_CustomTarget_get_clean_target,rust_uno/cargo): $(call gb_Helper_abbreviate_dirs,\ rm -rf $(gb_CustomTarget_workdir)/rust_uno/cargo && \ rm -f $(call gb_CustomTarget_get_target,rust_uno/cargo)) - rm -fr $(SRCDIR)/rust_uno/Cargo.lock $(SRCDIR)/rust_uno/target + rm -fr $(SRCDIR)/rust_uno/target # vim: set noet sw=4 ts=4: diff --git a/rust_uno/src/core/any.rs b/rust_uno/src/core/any.rs index 7e307239720b..90b4273a29ff 100644 --- a/rust_uno/src/core/any.rs +++ b/rust_uno/src/core/any.rs @@ -34,6 +34,7 @@ use crate::ffi::uno_any::*; /// /// Any provides a safe, memory-managed interface to LibreOffice's native /// any type. It automatically handles reference counting and memory cleanup. +#[repr(transparent)] pub struct Any { inner: uno_Any, } diff --git a/rust_uno/src/core/oustring.rs b/rust_uno/src/core/oustring.rs index 23433330490e..3d25c8f644d9 100644 --- a/rust_uno/src/core/oustring.rs +++ b/rust_uno/src/core/oustring.rs @@ -36,6 +36,7 @@ use crate::ffi::sal_types::*; /// OUString provides a safe, memory-managed interface to LibreOffice's native /// string type. It automatically handles reference counting and memory cleanup, /// and provides conversions to/from standard Rust string types. +#[repr(transparent)] pub struct OUString { inner: NonNull, } diff --git a/rust_uno/src/core/sequence.rs b/rust_uno/src/core/sequence.rs index f9d8a237b0a2..2fe75666f392 100644 --- a/rust_uno/src/core/sequence.rs +++ b/rust_uno/src/core/sequence.rs @@ -37,6 +37,7 @@ use std::ptr::NonNull; /// /// Sequence provides a safe, memory-managed interface to LibreOffice's native /// Sequence type. It automatically handles reference counting and memory cleanup. +#[repr(transparent)] pub struct Sequence { inner: NonNull, } diff --git a/rust_uno/src/core/type.rs b/rust_uno/src/core/type.rs index 21363952ddcf..a86c0c3e837e 100644 --- a/rust_uno/src/core/type.rs +++ b/rust_uno/src/core/type.rs @@ -54,6 +54,7 @@ use std::ptr; /// )); /// ``` #[allow(non_snake_case)] // _pType follows FFI naming conventions +#[repr(transparent)] pub struct Type { /// C typelib reference pointer _pType: *mut typelib_TypeDescriptionReference, diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c index 0af8cfbb4cd3..d1ecd810ab19 100644 --- a/sal/android/lo-bootstrap.c +++ b/sal/android/lo-bootstrap.c @@ -897,13 +897,6 @@ Java_org_libreoffice_android_Bootstrap_address_1of_1direct_1byte_1buffer(JNIEnv return (jlong) (intptr_t) (*env)->GetDirectBufferAddress(env, bbuffer); } -__attribute__ ((visibility("default"))) -void -libreofficekit_set_javavm(JavaVM *vm) -{ - the_java_vm = vm; -} - __attribute__ ((visibility("default"))) JavaVM * lo_get_javavm(void) diff --git a/sal/osl/all/filepath.cxx b/sal/osl/all/filepath.cxx index afba01739b1b..f05abc913e26 100644 --- a/sal/osl/all/filepath.cxx +++ b/sal/osl/all/filepath.cxx @@ -73,7 +73,7 @@ oslFileError SAL_CALL osl_abbreviateSystemPath( rtl_uString *ustrSystemPath, rtl break; } - /* Now abbreviate file component */ + /* Now abbreviate the file component */ while ( uPathWidth + uFileWidth > uMaxWidth ) { @@ -93,7 +93,7 @@ oslFileError SAL_CALL osl_abbreviateSystemPath( rtl_uString *ustrSystemPath, rtl rtl_uString_newConcat( pustrCompacted, ustrPath, ustrFile ); - /* Event now if path was compacted to ".../..." it can be too large */ + /* Even now if path was compacted to ".../..." it can be too large */ uPathWidth += uFileWidth; diff --git a/sal/osl/unx/backtraceapi.cxx b/sal/osl/unx/backtraceapi.cxx index 1a39af42afe8..64a5800d57e5 100644 --- a/sal/osl/unx/backtraceapi.cxx +++ b/sal/osl/unx/backtraceapi.cxx @@ -203,16 +203,20 @@ OUString sal::backtrace_to_string(BacktraceState* backtraceState) { Dl_info dli; void* addr = backtraceState->buffer[i]; - std::unique_lock guard(frameCacheMutex); - auto it = frameCache.find(addr); - bool found = it != frameCache.end(); - guard.unlock(); - if( found ) + bool found = false; { - frameData[ i ].info = it->second; - frameData[ i ].handled = true; + // The cache evicts its oldest entry when a new one arrives, so copy the string out + // while the lock is held. + std::lock_guard guard(frameCacheMutex); + auto it = frameCache.find(addr); + if (it != frameCache.end()) + { + frameData[ i ].info = it->second; + frameData[ i ].handled = true; + found = true; + } } - else if (dladdr(addr, &dli) != 0) + if (!found && dladdr(addr, &dli) != 0) { if (dli.dli_fname && dli.dli_fbase) { diff --git a/sal/osl/unx/file_url.cxx b/sal/osl/unx/file_url.cxx index 2c470e1011af..d74953512ffa 100644 --- a/sal/osl/unx/file_url.cxx +++ b/sal/osl/unx/file_url.cxx @@ -746,7 +746,7 @@ namespace { /** No separate error code if unicode to text conversion or getcwd fails because for the - caller there is no difference why a file could not be found in CDW + caller there is no difference why a file could not be found in CWD */ bool find_in_CWD(const OUString& file_path, OUString& result) { @@ -756,8 +756,8 @@ namespace if (osl_getProcessWorkingDir(&cwd_url.pData) == osl_Process_E_None) { OUString cwd; - FileBase::getSystemPathFromFileURL(cwd_url, cwd); - bfound = osl::searchPath(file_path, cwd, result); + if (FileBase::getSystemPathFromFileURL(cwd_url, cwd) == FileBase::E_None) + bfound = osl::searchPath(file_path, cwd, result); } return bfound; } diff --git a/sal/osl/unx/module.cxx b/sal/osl/unx/module.cxx index 0da54f475847..29166f1f538f 100644 --- a/sal/osl/unx/module.cxx +++ b/sal/osl/unx/module.cxx @@ -31,23 +31,21 @@ #include #include "file_url.hxx" -static bool getModulePathFromAddress(void * address, rtl_String ** path) +#include + +static std::optional getModulePathFromAddress(void* address) { - bool result = false; + std::optional oPath; #if HAVE_UNIX_DLAPI Dl_info dl_info; - - result = dladdr(address, &dl_info) != 0; - - if (result) + if (dladdr(address, &dl_info) != 0) { - rtl_string_newFromStr(path, dl_info.dli_fname); + oPath = OString(dl_info.dli_fname); } #else (void) address; - (void) path; #endif - return result; + return oPath; } #ifndef DISABLE_DYNLOADING @@ -117,25 +115,17 @@ oslModule osl_loadModuleRelativeAscii( if (relativePath[0] == '/') { return osl_loadModuleAscii(relativePath, mode); } - rtl_String * path = nullptr; - rtl_String * suffix = nullptr; oslModule module; - if (!getModulePathFromAddress( - reinterpret_cast< void * >(baseModule), &path)) - { + std::optional oPath = getModulePathFromAddress(reinterpret_cast(baseModule)); + if (!oPath.has_value()) return nullptr; - } - rtl_string_newFromStr_WithLength( - &path, path->buffer, - (rtl_str_lastIndexOfChar_WithLength(path->buffer, path->length, '/') - + 1)); + + OString sPath = oPath->copy(0, oPath->lastIndexOf('/') + 1); + /* cut off everything after the last slash; should the original path contain no slash, the resulting path is the empty string */ - rtl_string_newFromStr(&suffix, relativePath); - rtl_string_newConcat(&path, path, suffix); - rtl_string_release(suffix); - module = osl_loadModuleAscii(path->buffer, mode); - rtl_string_release(path); + sPath += relativePath; + module = osl_loadModuleAscii(sPath.getStr(), mode); return module; } @@ -250,12 +240,12 @@ osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName) sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl) { bool result = false; - rtl_String * path = nullptr; - if (getModulePathFromAddress(addr, &path)) + std::optional oPath = getModulePathFromAddress(addr); + if (oPath.has_value()) { rtl_string2UString(ppLibraryUrl, - path->buffer, - path->length, + oPath->getStr(), + oPath->getLength(), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS); @@ -276,7 +266,6 @@ sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibr << OUString::unacquired(ppLibraryUrl) << ") failed with " << e); result = false; } - rtl_string_release(path); } return result; } diff --git a/sal/osl/unx/mutex.cxx b/sal/osl/unx/mutex.cxx index afc35fbb812f..e6e34879f275 100644 --- a/sal/osl/unx/mutex.cxx +++ b/sal/osl/unx/mutex.cxx @@ -57,7 +57,7 @@ oslMutex SAL_CALL osl_createMutex() nRet = pthread_mutex_init(&(pMutex->mutex), &aMutexAttr); if ( nRet != 0 ) { - SAL_WARN("sal.osl.mutex", "pthread_muxex_init failed: " << UnixErrnoString(nRet)); + SAL_WARN("sal.osl.mutex", "pthread_mutex_init failed: " << UnixErrnoString(nRet)); free(pMutex); pMutex = nullptr; diff --git a/sal/osl/unx/nlsupport.cxx b/sal/osl/unx/nlsupport.cxx index 263439e3097e..9964d6e1400c 100644 --- a/sal/osl/unx/nlsupport.cxx +++ b/sal/osl/unx/nlsupport.cxx @@ -30,7 +30,7 @@ #include "nlsupport.hxx" // these share a lot, so use one define -#if defined(LINUX) || defined(EMSCRIPTEN) || defined(__sun) || \ +#if defined(LINUX) || defined(__EMSCRIPTEN__) || defined(__sun) || \ defined(FREEBSD) || defined(OPENBSD) || defined(DRAGONFLY) || defined(NETBSD) #define LO_COMMON_NLS_ARCHS 1 #else @@ -282,7 +282,7 @@ static const Pair nl_language_list[] = { /* XXX MS-874 is an extension to tis620, so this is not * really equivalent */ -#elif defined(LINUX) || defined(EMSCRIPTEN) +#elif defined(LINUX) || defined(__EMSCRIPTEN__) #if !defined(CODESET) #define CODESET _NL_CTYPE_CODESET_NAME diff --git a/sal/osl/unx/process_impl.cxx b/sal/osl/unx/process_impl.cxx index 07eb239045ff..12a8a7add551 100644 --- a/sal/osl/unx/process_impl.cxx +++ b/sal/osl/unx/process_impl.cxx @@ -95,7 +95,7 @@ namespace { oslProcessError bootstrap_getExecutableFile(rtl_uString ** ppFileURL) { -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ // Just return some dummy file: URL for now to see what happens OUString fileURL = "vnd.sun.star.pathname:/instdir/program/soffice"; rtl_uString_acquire(fileURL.pData); diff --git a/sal/osl/unx/security.cxx b/sal/osl/unx/security.cxx index 733aa0dfc6bf..47272d850dd9 100644 --- a/sal/osl/unx/security.cxx +++ b/sal/osl/unx/security.cxx @@ -103,8 +103,7 @@ static oslSecurityImpl * growSecurityImpl( } p = static_cast(realloc(impl, n)); if (p != nullptr) { - // coverity[overrun-buffer-arg] - theoretically massive n is not due to - // a negative parameter being interpreted as unsigned + // coverity[overrun-buffer-arg : FALSE] - n is the size just passed to realloc memset (p, 0, n); } } @@ -128,7 +127,7 @@ oslSecurity SAL_CALL osl_getCurrentSecurity() if (p == nullptr) { return nullptr; } -#if (defined(IOS) && defined(X86_64)) || defined(EMSCRIPTEN) +#if (defined(IOS) && defined(X86_64)) || defined(__EMSCRIPTEN__) // getpwuid_r() does not work in the iOS simulator (void) found; char * buffer = p->m_buffer; @@ -141,7 +140,7 @@ oslSecurity SAL_CALL osl_getCurrentSecurity() buffer += strlen(buffer) + 1; p->m_pPasswd.pw_uid = geteuid(); p->m_pPasswd.pw_gid = getegid(); -#if !defined(EMSCRIPTEN) +#if !defined(__EMSCRIPTEN__) p->m_pPasswd.pw_change = 0; strcpy(buffer, ""); p->m_pPasswd.pw_class = buffer; diff --git a/sal/osl/unx/system.cxx b/sal/osl/unx/system.cxx index eba4fe01c6c5..960e14b20d81 100644 --- a/sal/osl/unx/system.cxx +++ b/sal/osl/unx/system.cxx @@ -148,7 +148,7 @@ int macxp_resolveAlias(char *path, int buflen) #endif /* NO_PTHREAD_RTL */ -//might be useful on other platforms, but doesn't compiler under MACOSX anyway +//might be useful on other platforms, but doesn't compile under MACOSX anyway #if defined(__GNUC__) && defined(LINUX) //force the __data_start symbol to exist in any executables that link against //libuno_sal so that dlopening of the libgcj provided libjvm.so on some diff --git a/sal/osl/unx/system.hxx b/sal/osl/unx/system.hxx index 078fa348905e..f349170ed29b 100644 --- a/sal/osl/unx/system.hxx +++ b/sal/osl/unx/system.hxx @@ -209,7 +209,7 @@ int macxp_resolveAlias(char *path, int buflen); # define NO_PTHREAD_RTL #endif -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ # include # include # include @@ -231,7 +231,7 @@ int macxp_resolveAlias(char *path, int buflen); !defined(__sun) && !defined(MACOSX) && \ !defined(OPENBSD) && !defined(DRAGONFLY) && \ !defined(IOS) && !defined(ANDROID) && \ - !defined(HAIKU) && !defined(EMSCRIPTEN) + !defined(HAIKU) && !defined(__EMSCRIPTEN__) # error "Target platform not specified!" #endif diff --git a/sal/osl/unx/uunxapi.cxx b/sal/osl/unx/uunxapi.cxx index 6af6fbb61a4d..a406b8e3408a 100644 --- a/sal/osl/unx/uunxapi.cxx +++ b/sal/osl/unx/uunxapi.cxx @@ -222,7 +222,7 @@ template<> OUString fromOString(OString const & s) template bool realpath_(const T& pstrFileName, T& ppstrResolvedName) { OString fn = toOString(pstrFileName); -#if defined ANDROID || defined(EMSCRIPTEN) +#if defined ANDROID || defined(__EMSCRIPTEN__) #if defined ANDROID if (fn == "/assets" || fn.startsWith("/assets/")) #else @@ -236,7 +236,7 @@ template bool realpath_(const T& pstrFileName, T& ppstrResolvedName) return true; } -#endif // ANDROID || EMSCRIPTEN +#endif // ANDROID || __EMSCRIPTEN__ #ifdef MACOSX fn = macxp_resolveAliasAndConvert(fn); diff --git a/sal/osl/w32/file.cxx b/sal/osl/w32/file.cxx index 302e4e1e6dd9..9855acf4fc1b 100644 --- a/sal/osl/w32/file.cxx +++ b/sal/osl/w32/file.cxx @@ -622,15 +622,15 @@ oslFileError SAL_CALL osl_openFile( if (result != osl_File_E_None) return result; - // tdf126742 use FILE_SHARE_WRITE to get closer to non-Windows platform behaviour, - // for details and discussion see task please - DWORD dwAccess = GENERIC_READ, dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE, dwCreation = 0; + DWORD dwAccess = GENERIC_READ, dwShare = FILE_SHARE_READ, dwCreation = 0; if (uFlags & osl_File_OpenFlag_Write) dwAccess |= GENERIC_WRITE; + else + dwShare |= FILE_SHARE_WRITE; if (uFlags & osl_File_OpenFlag_NoLock) - dwShare |= FILE_SHARE_DELETE; + dwShare |= FILE_SHARE_WRITE | FILE_SHARE_DELETE; if (uFlags & osl_File_OpenFlag_Create) dwCreation |= CREATE_NEW; diff --git a/sal/osl/w32/random.cxx b/sal/osl/w32/random.cxx index 27ee14fdd6d4..9263b24b61c3 100644 --- a/sal/osl/w32/random.cxx +++ b/sal/osl/w32/random.cxx @@ -48,7 +48,7 @@ bool osl_get_system_random_data(char* buffer, size_t desired_len) desired_len -= 4; } } - /* deal with the partial int reminder to fill */ + /* deal with the partial int remainder to fill */ if (desired_len) { if (rand_s(&val)) diff --git a/sal/qa/OStringBuffer/rtl_OStringBuffer.cxx b/sal/qa/OStringBuffer/rtl_OStringBuffer.cxx index 9692d9fb2910..6657145f78cc 100644 --- a/sal/qa/OStringBuffer/rtl_OStringBuffer.cxx +++ b/sal/qa/OStringBuffer/rtl_OStringBuffer.cxx @@ -3791,12 +3791,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -3814,12 +3814,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -3837,12 +3837,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -3860,12 +3860,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -3975,12 +3975,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -3998,12 +3998,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -4021,12 +4021,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -4044,12 +4044,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -4251,12 +4251,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -4274,12 +4274,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -4297,12 +4297,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -4320,12 +4320,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -4435,12 +4435,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -4458,12 +4458,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -4481,12 +4481,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -4504,12 +4504,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -4711,12 +4711,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -4734,12 +4734,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -4757,12 +4757,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -4780,12 +4780,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -4895,12 +4895,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -4918,12 +4918,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -4941,12 +4941,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -4964,12 +4964,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -5171,12 +5171,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -5194,12 +5194,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -5217,12 +5217,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -5240,12 +5240,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -5355,12 +5355,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -5378,12 +5378,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -5401,12 +5401,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -5424,12 +5424,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -5631,12 +5631,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -5654,12 +5654,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -5677,12 +5677,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -5700,12 +5700,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -5815,12 +5815,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -5838,12 +5838,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -5861,12 +5861,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -5884,12 +5884,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -7377,12 +7377,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -7401,12 +7401,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -7425,12 +7425,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -7449,12 +7449,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -7567,12 +7567,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -7591,12 +7591,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -7615,12 +7615,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -7639,12 +7639,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -7852,12 +7852,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -7876,12 +7876,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -7900,12 +7900,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -7924,12 +7924,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -8042,12 +8042,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -8066,12 +8066,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -8090,12 +8090,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -8114,12 +8114,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -8327,12 +8327,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -8351,12 +8351,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -8375,12 +8375,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -8399,12 +8399,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -8517,12 +8517,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -8541,12 +8541,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -8565,12 +8565,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -8589,12 +8589,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -8802,12 +8802,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -8826,12 +8826,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -8850,12 +8850,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -8874,12 +8874,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -8992,12 +8992,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -9016,12 +9016,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -9040,12 +9040,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -9064,12 +9064,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -9277,12 +9277,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -9301,12 +9301,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -9325,12 +9325,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -9349,12 +9349,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int32, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -9467,12 +9467,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -9491,12 +9491,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -9515,12 +9515,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -9539,12 +9539,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int32, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int32, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -10481,12 +10481,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -10504,12 +10504,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -10527,12 +10527,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -10550,12 +10550,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -10665,12 +10665,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -10688,12 +10688,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -10711,12 +10711,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -10734,12 +10734,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -10941,12 +10941,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -10964,12 +10964,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -10987,12 +10987,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -11010,12 +11010,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -11125,12 +11125,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -11148,12 +11148,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -11171,12 +11171,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -11194,12 +11194,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -11401,12 +11401,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -11424,12 +11424,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -11447,12 +11447,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -11470,12 +11470,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -11585,12 +11585,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -11608,12 +11608,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -11631,12 +11631,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -11654,12 +11654,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -11861,12 +11861,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -11884,12 +11884,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -11907,12 +11907,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -11930,12 +11930,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -12045,12 +12045,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -12068,12 +12068,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -12091,12 +12091,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -12114,12 +12114,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -12321,12 +12321,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -12344,12 +12344,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -12367,12 +12367,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -12390,12 +12390,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -12505,12 +12505,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -12528,12 +12528,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -12551,12 +12551,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -12574,12 +12574,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -14067,12 +14067,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -14091,12 +14091,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -14115,12 +14115,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -14139,12 +14139,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[0]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -14257,12 +14257,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -14281,12 +14281,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -14305,12 +14305,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -14329,12 +14329,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[0]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[0]", expVal.getLength(), aStrBuf.getLength() ); @@ -14542,12 +14542,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -14566,12 +14566,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -14590,12 +14590,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -14614,12 +14614,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[1]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -14732,12 +14732,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -14756,12 +14756,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -14780,12 +14780,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -14804,12 +14804,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[1]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[1]", expVal.getLength(), aStrBuf.getLength() ); @@ -15017,12 +15017,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -15041,12 +15041,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -15065,12 +15065,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -15089,12 +15089,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[2]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -15207,12 +15207,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -15231,12 +15231,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -15255,12 +15255,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -15279,12 +15279,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[2]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[2]", expVal.getLength(), aStrBuf.getLength() ); @@ -15492,12 +15492,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -15516,12 +15516,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -15540,12 +15540,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -15564,12 +15564,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[3]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -15682,12 +15682,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -15706,12 +15706,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -15730,12 +15730,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -15754,12 +15754,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[3]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[3]", expVal.getLength(), aStrBuf.getLength() ); @@ -15967,12 +15967,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -15991,12 +15991,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -16015,12 +16015,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -16039,12 +16039,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 8)_006_negative_kRadixOctol for arrOUS[4]", + "append(sal_Int64, radix 8)_006_negative_kRadixOctal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -16157,12 +16157,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -16181,12 +16181,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -16205,12 +16205,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); @@ -16229,12 +16229,12 @@ namespace rtl_OStringBuffer CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal, OString(aStrBuf.getStr()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE ( - "append(sal_Int64, radix 16)_006_negative_kRadixHexdecimal for arrOUS[4]", + "append(sal_Int64, radix 16)_006_negative_kRadixHexadecimal for arrOUS[4]", expVal.getLength(), aStrBuf.getLength() ); diff --git a/sal/qa/osl/file/osl_File_Const.h b/sal/qa/osl/file/osl_File_Const.h index 46f6264dc56c..e7d3ec62e8a5 100644 --- a/sal/qa/osl/file/osl_File_Const.h +++ b/sal/qa/osl/file/osl_File_Const.h @@ -54,9 +54,9 @@ extern "C" { #endif -// common used string resource -// these common used string will be used as assist resource in test -// they are mostly OS independent, some of the resource can be reused +// commonly used string resources +// these commonly used strings will be used as assistant resources in test +// they are mostly OS independent, some of the resources can be reused // so, a common test data repository will be better since it can be // shared among all test code @@ -67,11 +67,11 @@ const char pBuffer_Blank[] = ""; // OS dependent/independent definitions/includes // we use FILE_PREFIX for URL prefix, // TEST_PLATFORM for test platform initial, -// TEST_PLATFORM_ROOT for root dir in comrresponding platform, -// TEST_PLATFORM_TEMP for temp dir in comrresponding platform, -// PATH_LIST_DELIMITER for separator of path list in comrresponding platform, -// PATH_SEPARATOR for separator in URL or system path in comrresponding platform, -// PATH_MAX/MAX_PATH for max path length in comrresponding platform, +// TEST_PLATFORM_ROOT for root dir in corresponding platform, +// TEST_PLATFORM_TEMP for temp dir in corresponding platform, +// PATH_LIST_DELIMITER for separator of path list in corresponding platform, +// PATH_SEPARATOR for separator in URL or system path in corresponding platform, +// PATH_MAX/MAX_PATH for max path length in corresponding platform, // OS independent const definition @@ -124,7 +124,7 @@ OUString aTempDirectoryURL(getTempDirectoryURL_()); OUString aUserDirectorySys( aTempDirectorySys + "" ); OUString aUserDirectoryURL( aTempDirectoryURL + "" ); -// common used URL:temp, canonical, root, relative, link,etc +// commonly used URLs: temp, canonical, root, relative, link, etc. OUString aCanURL1( aTempDirectoryURL + "/canonical.name" ); OUString aCanURL2( @@ -150,7 +150,7 @@ OUString aRelURL5( aTempDirectoryURL + "/./../" ); OUString aLnkURL1( aTempDirectoryURL + "/link.file" ); OUString aHidURL1( u".hiddenfile"_ustr ); -// common used System Path:temp, root,etc +// commonly used System Paths: temp, root, etc. OUString aRootSys( u"" TEST_PLATFORM_ROOT ""_ustr); OUString aSysPath1( aTempDirectorySys + "/system.path" ); diff --git a/sal/qa/rtl/cipher/rtl_cipher.cxx b/sal/qa/rtl/cipher/rtl_cipher.cxx index 3844c5613bd3..9bff514394ea 100644 --- a/sal/qa/rtl/cipher/rtl_cipher.cxx +++ b/sal/qa/rtl/cipher/rtl_cipher.cxx @@ -46,7 +46,7 @@ public: void create_002() { rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmInvalid, rtl_Cipher_ModeECB); - CPPUNIT_ASSERT_EQUAL_MESSAGE("create provide wrong object.", static_cast(nullptr), aCipher); + CPPUNIT_ASSERT_EQUAL_MESSAGE("create provides wrong object.", static_cast(nullptr), aCipher); } void create_003() { @@ -61,7 +61,7 @@ public: void create_004() { rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmInvalid, rtl_Cipher_ModeCBC); - CPPUNIT_ASSERT_EQUAL_MESSAGE("create provide wrong object.", static_cast(nullptr), aCipher); + CPPUNIT_ASSERT_EQUAL_MESSAGE("create provides wrong object.", static_cast(nullptr), aCipher); } void create_005() { @@ -72,22 +72,22 @@ public: void create_006() { rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmInvalid, rtl_Cipher_ModeStream); - CPPUNIT_ASSERT_EQUAL_MESSAGE("create provide wrong object.", static_cast(nullptr), aCipher); + CPPUNIT_ASSERT_EQUAL_MESSAGE("create provides wrong object.", static_cast(nullptr), aCipher); } void create_007() { rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeInvalid); - CPPUNIT_ASSERT_EQUAL_MESSAGE("create provide wrong object.", static_cast(nullptr), aCipher); + CPPUNIT_ASSERT_EQUAL_MESSAGE("create provides wrong object.", static_cast(nullptr), aCipher); } void create_008() { rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmInvalid, rtl_Cipher_ModeInvalid); - CPPUNIT_ASSERT_EQUAL_MESSAGE("create provide wrong object.", static_cast(nullptr), aCipher); + CPPUNIT_ASSERT_EQUAL_MESSAGE("create provides wrong object.", static_cast(nullptr), aCipher); } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(create); CPPUNIT_TEST(create_001); @@ -134,12 +134,12 @@ public: void createBF_004() { rtlCipher aCipher = rtl_cipher_createBF(rtl_Cipher_ModeInvalid); - CPPUNIT_ASSERT_EQUAL_MESSAGE("create provide wrong object.", static_cast(nullptr), aCipher); + CPPUNIT_ASSERT_EQUAL_MESSAGE("create provides wrong object.", static_cast(nullptr), aCipher); // rtl_cipher_destroy(aCipher); } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(createBF); CPPUNIT_TEST(createBF_001); @@ -284,7 +284,7 @@ public: } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(decode); CPPUNIT_TEST(decode_001); @@ -301,7 +301,7 @@ public: } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(decodeBF); CPPUNIT_TEST(decodeBF_001); @@ -324,7 +324,7 @@ public: } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(destroy); CPPUNIT_TEST(destroy_001); @@ -349,7 +349,7 @@ public: } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(destroyBF); CPPUNIT_TEST(destroyBF_001); @@ -421,7 +421,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(encode); CPPUNIT_TEST(encode_001); @@ -437,7 +437,7 @@ public: } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(encodeBF); CPPUNIT_TEST(encodeBF_001); @@ -555,7 +555,7 @@ public: } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(init); CPPUNIT_TEST(init_001); @@ -576,7 +576,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(initBF); CPPUNIT_TEST(initBF_001); diff --git a/sal/qa/rtl/crc32/rtl_crc32.cxx b/sal/qa/rtl/crc32/rtl_crc32.cxx index 34b900f8555b..7114c141766b 100644 --- a/sal/qa/rtl/crc32/rtl_crc32.cxx +++ b/sal/qa/rtl/crc32/rtl_crc32.cxx @@ -55,7 +55,7 @@ public: nCRC = rtl_crc32(nCRC, buf, num); - CPPUNIT_ASSERT_MESSAGE("buffer contain 2 empty bytes, crc is zero", nCRC != 0); + CPPUNIT_ASSERT_MESSAGE("buffer contains 2 empty bytes, crc is zero", nCRC != 0); } void rtl_crc32_002_1() @@ -67,7 +67,7 @@ public: nCRC = rtl_crc32(nCRC, buf, num); - CPPUNIT_ASSERT_MESSAGE("buffer contain 3 empty bytes, crc is zero", nCRC != 0); + CPPUNIT_ASSERT_MESSAGE("buffer contains 3 empty bytes, crc is zero", nCRC != 0); } /** @@ -93,7 +93,7 @@ public: CPPUNIT_ASSERT_MESSAGE("checksum should differ for buf1 and buf2", nCRC1 != nCRC2); } - /** check if the crc32 only use as much values, as given + /** check if the crc32 only uses as many values as given * */ void rtl_crc32_003_1() @@ -110,10 +110,10 @@ public: nCRC2 = rtl_crc32(nCRC2, buf2, num2); - CPPUNIT_ASSERT_EQUAL_MESSAGE("checksum leave it's bounds", nCRC2, nCRC1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("checksum leaves its bounds", nCRC2, nCRC1); } - /** check if the crc32 differ at same content in reverse order + /** check if the crc32 differs with same content in reverse order * */ void rtl_crc32_003_2() @@ -135,7 +135,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(test); CPPUNIT_TEST(rtl_crc32_001); diff --git a/sal/qa/rtl/digest/rtl_digest.cxx b/sal/qa/rtl/digest/rtl_digest.cxx index 2244d98e3cc7..3c610d4bc6eb 100644 --- a/sal/qa/rtl/digest/rtl_digest.cxx +++ b/sal/qa/rtl/digest/rtl_digest.cxx @@ -238,7 +238,7 @@ public: if (!bClearSalt) { - // wilful contamination + // willful contamination pSaltData[0] = 1; } diff --git a/sal/qa/rtl/locale/rtl_locale.cxx b/sal/qa/rtl/locale/rtl_locale.cxx index 2bc04c14fa6b..c0b74bf3de43 100644 --- a/sal/qa/rtl/locale/rtl_locale.cxx +++ b/sal/qa/rtl/locale/rtl_locale.cxx @@ -45,12 +45,12 @@ public: void getDefault_001() { rtl_Locale* pData = rtl_locale_getDefault(); - CPPUNIT_ASSERT_MESSAGE("locale must not null", pData != nullptr); + CPPUNIT_ASSERT_MESSAGE("locale must not be null", pData != nullptr); } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(getDefault); CPPUNIT_TEST(getDefault_001); @@ -77,14 +77,14 @@ public: { rtl_locale_setDefault(u"en", u"US", u""); rtl_Locale* pData = rtl_locale_getDefault(); - CPPUNIT_ASSERT_MESSAGE("locale must not null", pData != nullptr); + CPPUNIT_ASSERT_MESSAGE("locale must not be null", pData != nullptr); // be sure to not GPF } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(setDefault); CPPUNIT_TEST(setDefault_001); @@ -117,7 +117,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(getLanguage); CPPUNIT_TEST(getLanguage_001); @@ -151,7 +151,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(getCountry); CPPUNIT_TEST(getCountry_001); @@ -185,7 +185,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(getVariant); CPPUNIT_TEST(getVariant_001); @@ -219,7 +219,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(hashCode); CPPUNIT_TEST(hashCode_001); @@ -259,7 +259,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(equals); CPPUNIT_TEST(equals_001); diff --git a/sal/qa/rtl/math/test-std-math.cxx b/sal/qa/rtl/math/test-std-math.cxx index b56144c95e21..fb0064720b3a 100644 --- a/sal/qa/rtl/math/test-std-math.cxx +++ b/sal/qa/rtl/math/test-std-math.cxx @@ -24,9 +24,9 @@ #include /* -In tdf#148430, we try to replace rtl math functions to std functions, -this unit test is to demonstrate this replacement will not change -the behavior of code and no other unexpected results. +In tdf#148430, we try to replace rtl math functions with std functions, +this unit test is to demonstrate that this replacement will not change +the behavior of the code and produce no unexpected results. You can see more discussions in https://gerrit.libreoffice.org/c/core/+/138294. */ diff --git a/sal/qa/rtl/ostring/rtl_OString2.cxx b/sal/qa/rtl/ostring/rtl_OString2.cxx index 2044750848c3..cb25d4920d33 100644 --- a/sal/qa/rtl/ostring/rtl_OString2.cxx +++ b/sal/qa/rtl/ostring/rtl_OString2.cxx @@ -166,7 +166,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(valueOf); CPPUNIT_TEST(valueOf_float_test_001); @@ -237,7 +237,7 @@ public: CPPUNIT_ASSERT (is_double_equal(1.0, 1.00000000001) == false); CPPUNIT_ASSERT (is_double_equal(1.0, 1.000000000001) == false); CPPUNIT_ASSERT (is_double_equal(1.0, 1.0000000000001) == false); - // we check til 14 values after comma + // we check till 14 values after comma CPPUNIT_ASSERT (is_double_equal(1.0, 1.00000000000001) == true); CPPUNIT_ASSERT (is_double_equal(1.0, 1.000000000000001) == true); CPPUNIT_ASSERT (is_double_equal(1.0, 1.0000000000000001) == true); @@ -309,7 +309,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toDouble); CPPUNIT_TEST(toDouble_selftest); @@ -475,7 +475,7 @@ public: sal_Bool bRes = check_replaceAt(new OString("Java desktop system"), new OString("Sun "), new OString("Java desktop system"), -4, 8 ); - CPPUNIT_ASSERT_MESSAGE("navigate index", bRes == sal_True); + CPPUNIT_ASSERT_MESSAGE("negative index", bRes == sal_True); } void replaceAt_005() { @@ -501,8 +501,8 @@ CPPUNIT_TEST_SUITE_REGISTRATION(rtl_OString::replaceAt); } // namespace rtl_OString -// this macro creates an empty function, which will called by the RegisterAllFunctions() -// to let the user the possibility to also register some functions by hand. +// this macro creates an empty function, which will be called by RegisterAllFunctions() +// to give the user the possibility to also register some functions by hand. CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/ostring/rtl_str.cxx b/sal/qa/rtl/ostring/rtl_str.cxx index 834559f7cfb0..00775c9f86cb 100644 --- a/sal/qa/rtl/ostring/rtl_str.cxx +++ b/sal/qa/rtl/ostring/rtl_str.cxx @@ -58,7 +58,7 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(compare); CPPUNIT_TEST(compare_001); @@ -107,7 +107,7 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(compareIgnoreAsciiCase); CPPUNIT_TEST(compare_001); @@ -184,7 +184,7 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(shortenedCompareIgnoreAsciiCase_WithLength); CPPUNIT_TEST(compare_000); @@ -195,7 +195,7 @@ namespace rtl_str CPPUNIT_TEST(compare_003); CPPUNIT_TEST(compare_004); CPPUNIT_TEST_SUITE_END(); - }; // class compare + }; // class shortenedCompareIgnoreAsciiCase_WithLength class hashCode : public CppUnit::TestFixture { @@ -231,14 +231,14 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(hashCode); CPPUNIT_TEST(hashCode_001); CPPUNIT_TEST(hashCode_002); CPPUNIT_TEST(hashCode_003); CPPUNIT_TEST_SUITE_END(); - }; // class compare + }; // class hashCode class indexOfChar : public CppUnit::TestFixture { @@ -276,14 +276,14 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(indexOfChar); CPPUNIT_TEST(indexOfChar_000); CPPUNIT_TEST(indexOfChar_001); CPPUNIT_TEST(indexOfChar_002); CPPUNIT_TEST_SUITE_END(); - }; // class compare + }; // class indexOfChar class lastIndexOfChar : public CppUnit::TestFixture { @@ -321,7 +321,7 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(lastIndexOfChar); CPPUNIT_TEST(lastIndexOfChar_000); @@ -367,14 +367,14 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(indexOfStr); CPPUNIT_TEST(indexOfStr_000); CPPUNIT_TEST(indexOfStr_001); CPPUNIT_TEST(indexOfStr_002); CPPUNIT_TEST_SUITE_END(); - }; // class compare + }; // class indexOfStr class lastIndexOfStr : public CppUnit::TestFixture { @@ -423,7 +423,7 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(lastIndexOfStr); CPPUNIT_TEST(lastIndexOfStr_000); @@ -452,7 +452,7 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(replaceChar); CPPUNIT_TEST(replaceChar_001); @@ -483,13 +483,13 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(replaceChar_WithLength); CPPUNIT_TEST(replaceChar_WithLength_000); CPPUNIT_TEST(replaceChar_WithLength_001); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class replaceChar_WithLength class toAsciiLowerCase : public CppUnit::TestFixture { @@ -510,12 +510,12 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toAsciiLowerCase); CPPUNIT_TEST(toAsciiLowerCase_001); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class toAsciiLowerCase class toAsciiLowerCase_WithLength : public CppUnit::TestFixture { @@ -542,13 +542,13 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toAsciiLowerCase_WithLength); CPPUNIT_TEST(toAsciiLowerCase_WithLength_000); CPPUNIT_TEST(toAsciiLowerCase_WithLength_001); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class toAsciiLowerCase_WithLength class toAsciiUpperCase : public CppUnit::TestFixture { @@ -569,12 +569,12 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toAsciiUpperCase); CPPUNIT_TEST(toAsciiUpperCase_001); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class toAsciiUpperCase class toAsciiUpperCase_WithLength : public CppUnit::TestFixture { @@ -601,13 +601,13 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toAsciiUpperCase_WithLength); CPPUNIT_TEST(toAsciiUpperCase_WithLength_000); CPPUNIT_TEST(toAsciiUpperCase_WithLength_001); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class toAsciiUpperCase_WithLength class trim_WithLength : public CppUnit::TestFixture { @@ -665,7 +665,7 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(trim_WithLength); CPPUNIT_TEST(trim_WithLength_000); @@ -690,7 +690,7 @@ namespace rtl_str // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(valueOfChar); CPPUNIT_TEST(valueOfChar_001); diff --git a/sal/qa/rtl/ostring/rtl_string.cxx b/sal/qa/rtl/ostring/rtl_string.cxx index 71c709519264..b1d2f3c8f813 100644 --- a/sal/qa/rtl/ostring/rtl_string.cxx +++ b/sal/qa/rtl/ostring/rtl_string.cxx @@ -52,7 +52,7 @@ namespace rtl_string } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(getLength); CPPUNIT_TEST(getLength_000); @@ -84,7 +84,7 @@ namespace rtl_string } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(newFromString); // CPPUNIT_TEST(newFromString_000); @@ -146,7 +146,7 @@ namespace rtl_string // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(convertUStringToString); CPPUNIT_TEST(convertUStringToString_001); @@ -162,8 +162,8 @@ CPPUNIT_TEST_SUITE_REGISTRATION(rtl_string::getLength); CPPUNIT_TEST_SUITE_REGISTRATION(rtl_string::newFromString); CPPUNIT_TEST_SUITE_REGISTRATION(rtl_string::convertUStringToString); -// this macro creates an empty function, which will called by the RegisterAllFunctions() -// to let the user the possibility to also register some functions by hand. +// this macro creates an empty function, which will be called by RegisterAllFunctions() +// to give the user the possibility to also register some functions by hand. CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/oustring/rtl_OUString2.cxx b/sal/qa/rtl/oustring/rtl_OUString2.cxx index 505d4d7c701a..49dfbb8ce21e 100644 --- a/sal/qa/rtl/oustring/rtl_OUString2.cxx +++ b/sal/qa/rtl/oustring/rtl_OUString2.cxx @@ -183,7 +183,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(number); CPPUNIT_TEST(number_float_test_001); @@ -276,7 +276,7 @@ public: CPPUNIT_ASSERT (!is_double_equal(1.0, 1.00000000001)); CPPUNIT_ASSERT (!is_double_equal(1.0, 1.000000000001)); CPPUNIT_ASSERT (!is_double_equal(1.0, 1.0000000000001)); - // we check til 15 values after comma + // we check till 15 values after comma CPPUNIT_ASSERT (is_double_equal(1.0, 1.00000000000001)); CPPUNIT_ASSERT (is_double_equal(1.0, 1.000000000000001)); CPPUNIT_ASSERT (is_double_equal(1.0, 1.0000000000000001)); @@ -336,7 +336,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toDouble); CPPUNIT_TEST(toDouble_selftest); @@ -460,7 +460,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toFloat); CPPUNIT_TEST(toFloat_selftest); @@ -622,7 +622,7 @@ public: } void lastIndexOf_test_salunicode_offset_002() { - // search for 's', start pos is last occur from search behind, found (17) + // search for 's', start pos is last occurrence from search behind, found (17) sal_Unicode cuChar = L's'; lastIndexOf_salunicode_offset(u"the sun sun java system"_ustr, cuChar, 17, 19); } @@ -635,7 +635,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(lastIndexOf); CPPUNIT_TEST(lastIndexOf_test_oustring_001); @@ -828,7 +828,7 @@ public: void intern() { - // The empty string is 'static' a special case ... + // The empty string is 'static', a special case ... OUString().intern(); OUString::intern( "",strlen(""),RTL_TEXTENCODING_ASCII_US ); @@ -837,7 +837,7 @@ public: CPPUNIT_ASSERT_EQUAL_MESSAGE( "string contents", u"foo"_ustr, aFooIntern); CPPUNIT_ASSERT_EQUAL_MESSAGE("string length", static_cast(3), aFooIntern.getLength()); // We have to dup due to no atomic 'intern' bit-set operation - CPPUNIT_ASSERT_MESSAGE("intern dups", aFoo.pData != aFooIntern.pData); + CPPUNIT_ASSERT_MESSAGE("intern duplicates", aFoo.pData != aFooIntern.pData); // Test interning lots of things int i; diff --git a/sal/qa/rtl/oustring/rtl_ustr.cxx b/sal/qa/rtl/oustring/rtl_ustr.cxx index 7932da98c840..2315a6c94c91 100644 --- a/sal/qa/rtl/oustring/rtl_ustr.cxx +++ b/sal/qa/rtl/oustring/rtl_ustr.cxx @@ -59,7 +59,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(compare); CPPUNIT_TEST(compare_001); @@ -108,7 +108,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(compareIgnoreAsciiCase); CPPUNIT_TEST(compare_001); @@ -185,7 +185,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(shortenedCompareIgnoreAsciiCase_WithLength); CPPUNIT_TEST(compare_000); @@ -196,7 +196,7 @@ namespace rtl_ustr CPPUNIT_TEST(compare_003); CPPUNIT_TEST(compare_004); CPPUNIT_TEST_SUITE_END(); -}; // class compare +}; // class shortenedCompareIgnoreAsciiCase_WithLength // // @@ -240,7 +240,7 @@ namespace rtl_ustr // // // Change the following lines only, if you add, remove or rename // // member functions of the current class, -// // because these macros are need by auto register mechanism. +// // because these macros are needed by auto register mechanism. // // CPPUNIT_TEST_SUITE(hashCode); // CPPUNIT_TEST(hashCode_000); @@ -286,7 +286,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(indexOfChar); CPPUNIT_TEST(indexOfChar_000); @@ -331,7 +331,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(lastIndexOfChar); CPPUNIT_TEST(lastIndexOfChar_000); @@ -382,14 +382,14 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(indexOfStr); CPPUNIT_TEST(indexOfStr_000); CPPUNIT_TEST(indexOfStr_001); CPPUNIT_TEST(indexOfStr_002); CPPUNIT_TEST_SUITE_END(); - }; // class compare + }; // class indexOfStr class lastIndexOfStr : public CppUnit::TestFixture { @@ -438,7 +438,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(lastIndexOfStr); CPPUNIT_TEST(lastIndexOfStr_000); @@ -463,7 +463,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(replaceChar); CPPUNIT_TEST(replaceChar_001); @@ -501,14 +501,14 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(replaceChar_WithLength); CPPUNIT_TEST(replaceChar_WithLength_000); CPPUNIT_TEST(replaceChar_WithLength_001); CPPUNIT_TEST(replaceChar_WithLength_002); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class replaceChar_WithLength class toAsciiLowerCase : public CppUnit::TestFixture { @@ -525,12 +525,12 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toAsciiLowerCase); CPPUNIT_TEST(toAsciiLowerCase_001); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class toAsciiLowerCase class toAsciiLowerCase_WithLength : public CppUnit::TestFixture { @@ -552,13 +552,13 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toAsciiLowerCase_WithLength); CPPUNIT_TEST(toAsciiLowerCase_WithLength_000); CPPUNIT_TEST(toAsciiLowerCase_WithLength_001); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class toAsciiLowerCase_WithLength class toAsciiUpperCase : public CppUnit::TestFixture { @@ -575,12 +575,12 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toAsciiUpperCase); CPPUNIT_TEST(toAsciiUpperCase_001); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class toAsciiUpperCase class toAsciiUpperCase_WithLength : public CppUnit::TestFixture { @@ -603,13 +603,13 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(toAsciiUpperCase_WithLength); CPPUNIT_TEST(toAsciiUpperCase_WithLength_000); CPPUNIT_TEST(toAsciiUpperCase_WithLength_001); CPPUNIT_TEST_SUITE_END(); - }; // class replaceChar + }; // class toAsciiUpperCase_WithLength class trim_WithLength : public CppUnit::TestFixture { @@ -673,7 +673,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(trim_WithLength); CPPUNIT_TEST(trim_WithLength_000); @@ -698,7 +698,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(valueOfChar); CPPUNIT_TEST(valueOfChar_001); @@ -832,7 +832,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(ascii_shortenedCompareIgnoreAsciiCase_WithLength); CPPUNIT_TEST(ascii_shortenedCompareIgnoreAsciiCase_WithLength_000); @@ -894,7 +894,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(ascii_compareIgnoreAsciiCase_WithLength); CPPUNIT_TEST(ascii_compareIgnoreAsciiCase_WithLength_000); @@ -937,7 +937,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(ascii_compare); CPPUNIT_TEST(ascii_compare_001); @@ -1006,7 +1006,7 @@ namespace rtl_ustr // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(ascii_compareIgnoreAsciiCase); CPPUNIT_TEST(ascii_compareIgnoreAsciiCase_001); @@ -1041,7 +1041,7 @@ namespace rtl_ustr CPPUNIT_TEST_SUITE(getToken); CPPUNIT_TEST(getToken_000); CPPUNIT_TEST_SUITE_END(); - }; // class ascii_compareIgnoreAsciiCase + }; // class getToken CPPUNIT_TEST_SUITE_REGISTRATION(rtl_ustr::compare); CPPUNIT_TEST_SUITE_REGISTRATION(rtl_ustr::compareIgnoreAsciiCase); diff --git a/sal/qa/rtl/random/rtl_random.cxx b/sal/qa/rtl/random/rtl_random.cxx index fb4be759a578..ed2e4c4bb820 100644 --- a/sal/qa/rtl/random/rtl_random.cxx +++ b/sal/qa/rtl/random/rtl_random.cxx @@ -43,7 +43,7 @@ public: rtlRandomPool aPool = rtl_random_createPool(); - // LLA: seems to be that another test is not possible for createPool() + // LLA: it seems that no other test is possible for createPool() CPPUNIT_ASSERT_MESSAGE("create failed", aPool != nullptr); rtl_random_destroyPool(aPool); @@ -51,7 +51,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(createPool); CPPUNIT_TEST(createPool_001); @@ -72,14 +72,14 @@ public: { rtlRandomPool aPool = rtl_random_createPool(); - // LLA: seems to be that another test is not possible for createPool() + // LLA: it seems that no other test is possible for createPool() CPPUNIT_ASSERT_MESSAGE("create failed", aPool != nullptr); rtl_random_destroyPool(aPool); } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(destroyPool); CPPUNIT_TEST(destroyPool_000); @@ -130,7 +130,7 @@ public: // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(addBytes); CPPUNIT_TEST(addBytes_000); @@ -303,7 +303,7 @@ public: aStat.build(nCountMax); aStat.print(); - CPPUNIT_ASSERT_MESSAGE("deviation should be less average", aStat.getMaxDeviation() < aStat.getAverage()); + CPPUNIT_ASSERT_MESSAGE("deviation should be less than average", aStat.getMaxDeviation() < aStat.getAverage()); rtl_random_destroyPool(aPool); } @@ -335,14 +335,14 @@ public: aStat.build(nCountMax * nBufLen); aStat.print(); - CPPUNIT_ASSERT_MESSAGE("deviation should be less average", aStat.getMaxDeviation() < aStat.getAverage()); + CPPUNIT_ASSERT_MESSAGE("deviation should be less than average", aStat.getMaxDeviation() < aStat.getAverage()); rtl_random_destroyPool(aPool); } // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(getBytes); CPPUNIT_TEST(getBytes_000); diff --git a/sal/qa/rtl/ref/rtl_ref.cxx b/sal/qa/rtl/ref/rtl_ref.cxx index 388aa1e26ed4..dec5fdb60a9f 100644 --- a/sal/qa/rtl/ref/rtl_ref.cxx +++ b/sal/qa/rtl/ref/rtl_ref.cxx @@ -35,7 +35,7 @@ public: m_bIncFlag = false; } else - CPPUNIT_FAIL("RC was incremented when in should not have been"); + CPPUNIT_FAIL("RC was incremented when it should not have been"); } void release() { --m_nRef; } diff --git a/sal/qa/rtl/strings/test_ostring.cxx b/sal/qa/rtl/strings/test_ostring.cxx index 1937edf6863b..597cae93e8b7 100644 --- a/sal/qa/rtl/strings/test_ostring.cxx +++ b/sal/qa/rtl/strings/test_ostring.cxx @@ -21,11 +21,15 @@ private: void testStartsWithIgnoreAsciiCase(); void testCompareTo(); void testUtf8StringLiterals(); + void testStartsWithChar(); + void testEndsWithChar(); CPPUNIT_TEST_SUITE(Test); CPPUNIT_TEST(testStartsWithIgnoreAsciiCase); CPPUNIT_TEST(testCompareTo); CPPUNIT_TEST(testUtf8StringLiterals); + CPPUNIT_TEST(testStartsWithChar); + CPPUNIT_TEST(testEndsWithChar); CPPUNIT_TEST_SUITE_END(); }; @@ -116,6 +120,72 @@ void Test::testUtf8StringLiterals() CPPUNIT_ASSERT_EQUAL(97, int(static_cast(sIn[2]))); } +void Test::testStartsWithChar() +{ + CPPUNIT_ASSERT(!""_ostr.startsWith('.')); + CPPUNIT_ASSERT("."_ostr.startsWith('.')); + CPPUNIT_ASSERT(".foo"_ostr.startsWith('.')); + CPPUNIT_ASSERT(!"."_ostr.startsWith('?')); + CPPUNIT_ASSERT(!".foo"_ostr.startsWith('?')); + + { + OString rest = "not_changed"_ostr; + CPPUNIT_ASSERT(!"foo"_ostr.startsWith('p', &rest)); + CPPUNIT_ASSERT_EQUAL("not_changed"_ostr, rest); + } + + { + OString rest = "must_change"_ostr; + CPPUNIT_ASSERT("/removed_slash"_ostr.startsWith('/', &rest)); + CPPUNIT_ASSERT_EQUAL("removed_slash"_ostr, rest); + } + + { + std::string_view rest = "not_changed"; + CPPUNIT_ASSERT(!"foo"_ostr.startsWith('p', &rest)); + CPPUNIT_ASSERT_EQUAL("not_changed"_ostr, OString(rest)); + } + + { + std::string_view rest = "must_change"; + CPPUNIT_ASSERT("/removed_slash"_ostr.startsWith('/', &rest)); + CPPUNIT_ASSERT_EQUAL("removed_slash"_ostr, OString(rest)); + } +} + +void Test::testEndsWithChar() +{ + CPPUNIT_ASSERT(!""_ostr.endsWith('.')); + CPPUNIT_ASSERT("."_ostr.endsWith('.')); + CPPUNIT_ASSERT("foo."_ostr.endsWith('.')); + CPPUNIT_ASSERT(!"."_ostr.endsWith('?')); + CPPUNIT_ASSERT(!"foo."_ostr.endsWith('?')); + + { + OString rest = "not_changed"_ostr; + CPPUNIT_ASSERT(!"foo"_ostr.endsWith('p', &rest)); + CPPUNIT_ASSERT_EQUAL("not_changed"_ostr, rest); + } + + { + OString rest = "must_change"_ostr; + CPPUNIT_ASSERT("removed_slash/"_ostr.endsWith('/', &rest)); + CPPUNIT_ASSERT_EQUAL("removed_slash"_ostr, rest); + } + + { + std::string_view rest = "not_changed"; + CPPUNIT_ASSERT(!"foo"_ostr.endsWith('p', &rest)); + CPPUNIT_ASSERT_EQUAL("not_changed"_ostr, OString(rest)); + } + + { + std::string_view rest = "must_change"; + CPPUNIT_ASSERT("removed_slash/"_ostr.endsWith('/', &rest)); + CPPUNIT_ASSERT_EQUAL("removed_slash"_ostr, OString(rest)); + } +} + CPPUNIT_TEST_SUITE_REGISTRATION(Test); } diff --git a/sal/qa/rtl/strings/test_oustring_endswith.cxx b/sal/qa/rtl/strings/test_oustring_endswith.cxx index 9ec08fa55045..6439bc498e47 100644 --- a/sal/qa/rtl/strings/test_oustring_endswith.cxx +++ b/sal/qa/rtl/strings/test_oustring_endswith.cxx @@ -33,9 +33,11 @@ class EndsWith: public CppUnit::TestFixture { private: void endsWith(); + void endsWithChar(); CPPUNIT_TEST_SUITE(EndsWith); CPPUNIT_TEST(endsWith); + CPPUNIT_TEST(endsWithChar); CPPUNIT_TEST_SUITE_END(); }; @@ -107,4 +109,39 @@ void test::oustring::EndsWith::endsWith() } } +void test::oustring::EndsWith::endsWithChar() +{ + CPPUNIT_ASSERT(!u""_ustr.endsWith('.')); + CPPUNIT_ASSERT(u"."_ustr.endsWith('.')); + CPPUNIT_ASSERT(u"foo."_ustr.endsWith('.')); + CPPUNIT_ASSERT(u"aĥ"_ustr.endsWith(u'ĥ')); + CPPUNIT_ASSERT(!u"."_ustr.endsWith('?')); + CPPUNIT_ASSERT(!u"foo."_ustr.endsWith('?')); + CPPUNIT_ASSERT(!u"aĥ"_ustr.endsWith(u'ĉ')); + + { + OUString rest = u"not_changed"_ustr; + CPPUNIT_ASSERT(!u"foo"_ustr.endsWith('p', &rest)); + CPPUNIT_ASSERT_EQUAL(u"not_changed"_ustr, rest); + } + + { + OUString rest = u"must_change"_ustr; + CPPUNIT_ASSERT(u"removed_slash/"_ustr.endsWith('/', &rest)); + CPPUNIT_ASSERT_EQUAL(u"removed_slash"_ustr, rest); + } + + { + std::u16string_view rest = u"not_changed"; + CPPUNIT_ASSERT(!u"foo"_ustr.endsWith('p', &rest)); + CPPUNIT_ASSERT_EQUAL(u"not_changed"_ustr, OUString(rest)); + } + + { + std::u16string_view rest = u"must_change"; + CPPUNIT_ASSERT(u"removed_slash/"_ustr.endsWith('/', &rest)); + CPPUNIT_ASSERT_EQUAL(u"removed_slash"_ustr, OUString(rest)); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_oustring_startswith.cxx b/sal/qa/rtl/strings/test_oustring_startswith.cxx index e27310b82461..b1668a8cde81 100644 --- a/sal/qa/rtl/strings/test_oustring_startswith.cxx +++ b/sal/qa/rtl/strings/test_oustring_startswith.cxx @@ -17,9 +17,11 @@ class StartsWith: public CppUnit::TestFixture { private: void startsWith(); + void startsWithChar(); CPPUNIT_TEST_SUITE(StartsWith); CPPUNIT_TEST(startsWith); + CPPUNIT_TEST(startsWithChar); CPPUNIT_TEST_SUITE_END(); }; @@ -34,4 +36,39 @@ void test::oustring::StartsWith::startsWith() CPPUNIT_ASSERT( !u"foobar"_ustr.startsWith( "oo" )); } +void test::oustring::StartsWith::startsWithChar() +{ + CPPUNIT_ASSERT(!u""_ustr.startsWith('.')); + CPPUNIT_ASSERT(u"."_ustr.startsWith('.')); + CPPUNIT_ASSERT(u".foo"_ustr.startsWith('.')); + CPPUNIT_ASSERT(u"ĉu?"_ustr.startsWith(u'ĉ')); + CPPUNIT_ASSERT(!u"."_ustr.startsWith('?')); + CPPUNIT_ASSERT(!u".foo"_ustr.startsWith('?')); + CPPUNIT_ASSERT(!u"ĉu?"_ustr.startsWith(u'ĥ')); + + { + OUString rest = u"not_changed"_ustr; + CPPUNIT_ASSERT(!u"foo"_ustr.startsWith('p', &rest)); + CPPUNIT_ASSERT_EQUAL(u"not_changed"_ustr, rest); + } + + { + OUString rest = u"must_change"_ustr; + CPPUNIT_ASSERT(u"/removed_slash"_ustr.startsWith('/', &rest)); + CPPUNIT_ASSERT_EQUAL(u"removed_slash"_ustr, rest); + } + + { + std::u16string_view rest = u"not_changed"; + CPPUNIT_ASSERT(!u"foo"_ustr.startsWith('p', &rest)); + CPPUNIT_ASSERT_EQUAL(u"not_changed"_ustr, OUString(rest)); + } + + { + std::u16string_view rest = u"must_change"; + CPPUNIT_ASSERT(u"/removed_slash"_ustr.startsWith('/', &rest)); + CPPUNIT_ASSERT_EQUAL(u"removed_slash"_ustr, OUString(rest)); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/textenc/rtl_tencinfo.cxx b/sal/qa/rtl/textenc/rtl_tencinfo.cxx index 123b8f12325f..b5c31e7e8fa3 100644 --- a/sal/qa/rtl/textenc/rtl_tencinfo.cxx +++ b/sal/qa/rtl/textenc/rtl_tencinfo.cxx @@ -33,10 +33,10 @@ namespace { const char *pCharSet = rtl_getBestMimeCharsetFromTextEncoding(eIn); rtl_TextEncoding eTextEnc = rtl_getTextEncodingFromMimeCharset(pCharSet); - CPPUNIT_ASSERT_EQUAL_MESSAGE("rtl_getBestMimeCharsetFromTextEncoding && rtl_getTextEncodingFromMimeCharset differdiffer", eOut, eTextEnc ); + CPPUNIT_ASSERT_EQUAL_MESSAGE("rtl_getBestMimeCharsetFromTextEncoding && rtl_getTextEncodingFromMimeCharset differ", eOut, eTextEnc ); } - // the defines for the follows test could be found in file inc/rtl/textenc.h + // the defines for the following test can be found in file inc/rtl/textenc.h void MimeCharsetFromTextEncoding_MS_1252() { diff --git a/sal/qa/rtl/uuid/rtl_Uuid.cxx b/sal/qa/rtl/uuid/rtl_Uuid.cxx index e7b524db89fb..e58b5fe34931 100644 --- a/sal/qa/rtl/uuid/rtl_Uuid.cxx +++ b/sal/qa/rtl/uuid/rtl_Uuid.cxx @@ -110,7 +110,7 @@ public: sal_uInt8 pNamedUUID[16], pNamedUUID2[16]; - // Same name does generate the same uuid + // Same name generates the same uuid rtl_String *pName = nullptr; rtl_string_newFromStr( &pName , "this is a bla.blubs.DNS-Name" ); rtl_createNamedUuid( pNamedUUID , NameSpace_DNS , pName ); @@ -119,22 +119,22 @@ public: CPPUNIT_ASSERT_EQUAL_MESSAGE( "Same name should generate the same uuid", sal_Int32(0), rtl_compareUuid( pNamedUUID , pNamedUUID2 ) ); CPPUNIT_ASSERT_MESSAGE( "Same name should generate the same uuid", ! memcmp( pNamedUUID , pPriorCalculatedUUID , 16 ) ); - // Different names does not generate the same uuid + // Different names do not generate the same uuid rtl_string_newFromStr( &pName , "this is a bla.blubs.DNS-Namf" ); rtl_createNamedUuid( pNamedUUID2 , NameSpace_DNS , pName ); - CPPUNIT_ASSERT_MESSAGE("Different names does not generate the same uuid.", memcmp( pNamedUUID , pNamedUUID2 , 16 ) ); + CPPUNIT_ASSERT_MESSAGE("Different names do not generate the same uuid.", memcmp( pNamedUUID , pNamedUUID2 , 16 ) ); - // the same name with different namespace uuid produces different uuids + // The same name with different namespace uuid produces different uuids rtl_createNamedUuid( pNamedUUID , NameSpace_URL , pName ); - CPPUNIT_ASSERT_MESSAGE( " same name with different namespace uuid produces different uuids", memcmp( pNamedUUID , pNamedUUID2 , 16 )); - CPPUNIT_ASSERT_MESSAGE( " same name with different namespace uuid produces different uuids", rtl_compareUuid( pNamedUUID , pNamedUUID2 ) != 0); + CPPUNIT_ASSERT_MESSAGE( "Same name with different namespace uuid produces different uuids", memcmp( pNamedUUID , pNamedUUID2 , 16 )); + CPPUNIT_ASSERT_MESSAGE( "Same name with different namespace uuid produces different uuids", rtl_compareUuid( pNamedUUID , pNamedUUID2 ) != 0); - //test compareUuid + // test compareUuid if ( rtl_compareUuid( pNamedUUID , pNamedUUID2 ) > 0 ) - { CPPUNIT_ASSERT_MESSAGE( " compare uuids", rtl_compareUuid( pNamedUUID2 , pNamedUUID ) < 0); + { CPPUNIT_ASSERT_MESSAGE( "compare uuids", rtl_compareUuid( pNamedUUID2 , pNamedUUID ) < 0); } else - CPPUNIT_ASSERT_MESSAGE( " compare uuids", rtl_compareUuid( pNamedUUID2 , pNamedUUID ) > 0); + CPPUNIT_ASSERT_MESSAGE( "compare uuids", rtl_compareUuid( pNamedUUID2 , pNamedUUID ) > 0); rtl_string_release( pName ); } diff --git a/sal/qa/systools/test_comtools.cxx b/sal/qa/systools/test_comtools.cxx index 291670bde966..6e1627538b93 100644 --- a/sal/qa/systools/test_comtools.cxx +++ b/sal/qa/systools/test_comtools.cxx @@ -127,7 +127,7 @@ namespace test_comtools CPPUNIT_ASSERT_EQUAL_MESSAGE("COMReference should be empty", static_cast(nullptr), r.get()); r = comObjectSource(); - CPPUNIT_ASSERT_MESSAGE("COMReference should be empty", r.get() != nullptr); + CPPUNIT_ASSERT_MESSAGE("COMReference should not be empty", r.get() != nullptr); CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong reference count 1 is expected", ULONG(1), reinterpret_cast(r.get())->GetRefCount()); } @@ -218,7 +218,7 @@ namespace test_comtools // Change the following lines only, if you add, remove or rename // member functions of the current class, - // because these macros are need by auto register mechanism. + // because these macros are needed by auto register mechanism. CPPUNIT_TEST_SUITE(test_COMReference); CPPUNIT_TEST(default_ctor); @@ -240,7 +240,7 @@ namespace test_comtools CPPUNIT_TEST_SUITE_REGISTRATION(test_comtools::test_COMReference); -} // namespace rtl_OUString +} // namespace test_comtools CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sal/rtl/bootstrap.cxx b/sal/rtl/bootstrap.cxx index 56005632192f..7073ba6aa1e8 100644 --- a/sal/rtl/bootstrap.cxx +++ b/sal/rtl/bootstrap.cxx @@ -45,7 +45,7 @@ #include #endif -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ #include #endif @@ -226,7 +226,7 @@ static OUString getIniFileName(bool overriding) { ? OUString("vnd.sun.star.pathname:/assets/fundamental.override.ini") : OUString("vnd.sun.star.pathname:/assets/rc"); resolvePathnameUrl(&fileName); -#elif defined(EMSCRIPTEN) +#elif defined(__EMSCRIPTEN__) fileName = overriding ? OUString("vnd.sun.star.pathname:/instdir/program/fundamental.override.ini") : OUString("vnd.sun.star.pathname:/instdir/program/sofficerc"); @@ -505,7 +505,7 @@ bool Bootstrap_Impl::getValue( return true; } -#if defined ANDROID || defined EMSCRIPTEN +#if defined ANDROID || defined __EMSCRIPTEN__ if (key == "APP_DATA_DIR") { const char *app_data_dir = lo_get_app_data_dir(); diff --git a/sal/textenc/convertisciidevangari.cxx b/sal/textenc/convertisciidevangari.cxx index cf39721446eb..62c68a723cce 100644 --- a/sal/textenc/convertisciidevangari.cxx +++ b/sal/textenc/convertisciidevangari.cxx @@ -367,7 +367,7 @@ sal_Size UnicodeToIsciiDevanagari::convert(sal_Unicode const* pSrcBuf, sal_Size goto done; } - // Linearly searching through the ranges if probably fastest, assuming + // Linearly searching through the ranges is probably fastest, assuming // that most converted characters belong to the ASCII subset: for (size_t i = 0; i < entries; ++i) { diff --git a/sal/textenc/convertsimple.cxx b/sal/textenc/convertsimple.cxx index 2738acc13be1..eec6dc908e22 100644 --- a/sal/textenc/convertsimple.cxx +++ b/sal/textenc/convertsimple.cxx @@ -16,6 +16,8 @@ #include "handleundefinedunicodetotextchar.hxx" #include "tenchelp.hxx" +#include + #define IMPL_MAX_REPLACECHAR 5 namespace { @@ -326,7 +328,7 @@ sal_uInt16 ImplGetReplaceChar( sal_Unicode c ) const ImplReplaceCharData* pCharData; nLow = 0; - nHigh = SAL_N_ELEMENTS( aImplRepCharTab ) - 1; + nHigh = std::size( aImplRepCharTab ) - 1; do { nMid = (nLow+nHigh)/2; @@ -418,7 +420,7 @@ const sal_uInt16* ImplGetReplaceString( sal_Unicode c ) const ImplReplaceCharStrData* pCharData; nLow = 0; - nHigh = SAL_N_ELEMENTS( aImplRepCharStrTab ) - 1; + nHigh = std::size( aImplRepCharStrTab ) - 1; do { nMid = (nLow+nHigh)/2; diff --git a/sal/textenc/convertsinglebytetobmpunicode.cxx b/sal/textenc/convertsinglebytetobmpunicode.cxx index 1fa9be11dab5..99837a67ae5d 100644 --- a/sal/textenc/convertsinglebytetobmpunicode.cxx +++ b/sal/textenc/convertsinglebytetobmpunicode.cxx @@ -126,7 +126,7 @@ sal_Size rtl_textenc_convertBmpUnicodeToSingleByte( goto bad_input; } assert(rtl::isUnicodeScalarValue(c)); - // Linearly searching through the ranges if probably fastest, assuming + // Linearly searching through the ranges is probably fastest, assuming // that most converted characters belong to the ASCII subset: for (std::size_t i = 0; i < entries; ++i) { if (c < ranges[i].unicode) { diff --git a/sal/textenc/handleundefinedunicodetotextchar.cxx b/sal/textenc/handleundefinedunicodetotextchar.cxx index 78b2464b70c6..58479ac24185 100644 --- a/sal/textenc/handleundefinedunicodetotextchar.cxx +++ b/sal/textenc/handleundefinedunicodetotextchar.cxx @@ -98,14 +98,14 @@ bool sal::detail::textenc::handleUndefinedUnicodeToTextChar( } } - /* Should this character ignored (Private, Non Spacing, Control) */ + /* Should this character be ignored (Private, Non Spacing, Control) */ if ( ImplIsUnicodeIgnoreChar( c, nFlags ) ) { (*ppSrcBuf)++; return true; } - /* Surrogates Characters should result in */ + /* Surrogate Characters should result in */ /* one replacement character */ if (rtl::isHighSurrogate(c)) { diff --git a/salhelper/test/Symbols/samplelib.hxx b/salhelper/test/Symbols/samplelib.hxx index 99dc0f6f774a..a89dc0b64d54 100644 --- a/salhelper/test/Symbols/samplelib.hxx +++ b/salhelper/test/Symbols/samplelib.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SALHELPER_TEST_SYMBOLS_SAMPLELIB_HXX -#define INCLUDED_SALHELPER_TEST_SYMBOLS_SAMPLELIB_HXX +#pragma once #include @@ -35,6 +34,4 @@ typedef SampleLib_Api* (*InitSampleLib_Api)(void); sal_Int32 funcA(sal_Int32 a); double funcB(double a); -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sax/qa/cppunit/xmlimport.cxx b/sax/qa/cppunit/xmlimport.cxx index d71cbb480984..8245f546f3c8 100644 --- a/sax/qa/cppunit/xmlimport.cxx +++ b/sax/qa/cppunit/xmlimport.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -360,7 +361,7 @@ void XMLImportTest::setUp() uno::UNO_QUERY_THROW); xInit->initialize({ uno::Any(xTokenHandler) }); - sal_Int32 nNamespaceCount = SAL_N_ELEMENTS(DummyTokenHandler::namespaceURIs); + sal_Int32 nNamespaceCount = static_cast(std::size(DummyTokenHandler::namespaceURIs)); uno::Sequence namespaceArgs( nNamespaceCount + 1 ); auto p_namespaceArgs = namespaceArgs.getArray(); p_namespaceArgs[0] <<= u"registerNamespaces"_ustr; diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx index 32dc46506617..898d54d85051 100644 --- a/sax/source/fastparser/fastparser.cxx +++ b/sax/source/fastparser/fastparser.cxx @@ -828,7 +828,7 @@ void FastSaxParserImpl::parseStream(const InputSource& rStructSource) rEntity.mxDocumentHandler->startDocument(); } -#ifdef EMSCRIPTEN +#ifdef __EMSCRIPTEN__ rEntity.mbEnableThreads = false; #else if (!getenv("SAX_DISABLE_THREADS") && !m_bDisableThreadedParser) diff --git a/sax/source/tools/fastserializer.cxx b/sax/source/tools/fastserializer.cxx index 54039859539a..33db4745bead 100644 --- a/sax/source/tools/fastserializer.cxx +++ b/sax/source/tools/fastserializer.cxx @@ -761,13 +761,14 @@ namespace sax_fastparser { if ( bAppend ) { // append the rMerge to the rTop - memcpy( rTop.getArray() + nTopLen, pMerge, nMergeLen ); + std::copy_n(pMerge, nMergeLen, rTop.getArray() + nTopLen); } else { // prepend the rMerge to the rTop - memmove( rTop.getArray() + nMergeLen, rTop.getConstArray(), nTopLen ); - memcpy( rTop.getArray(), pMerge, nMergeLen ); + std::copy_backward(rTop.getConstArray(), rTop.getConstArray() + nTopLen, + rTop.getArray() + nMergeLen + nTopLen); + std::copy_n(pMerge, nMergeLen, rTop.getArray()); } } diff --git a/sc/CppunitTest_sc_color_scale_api.mk b/sc/CppunitTest_sc_color_scale_api.mk new file mode 100644 index 000000000000..fcfbbe0e67b0 --- /dev/null +++ b/sc/CppunitTest_sc_color_scale_api.mk @@ -0,0 +1,77 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,sc_color_scale_api)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sc_color_scale_api)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sc_color_scale_api, \ + sc/qa/extras/color_scale_api \ +)) + +$(eval $(call gb_CppunitTest_use_externals,sc_color_scale_api, \ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sc_color_scale_api, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + drawinglayercore \ + editeng \ + for \ + forui \ + i18nlangtag \ + msfilter \ + oox \ + sal \ + salhelper \ + sax \ + sb \ + sc \ + scqahelper \ + sfx \ + sot \ + subsequenttest \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tk \ + tl \ + ucbhelper \ + unotest \ + utl \ + $(call gb_Helper_optional,SCRIPTING, \ + vbahelper) \ + vcl \ + xo \ +)) + +$(eval $(call gb_CppunitTest_set_include,sc_color_scale_api,\ + -I$(SRCDIR)/sc/inc \ + -I$(SRCDIR)/sc/qa/unit \ + -I$(SRCDIR)/sc/source/ui/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,sc_color_scale_api)) + +$(eval $(call gb_CppunitTest_use_ure,sc_color_scale_api)) +$(eval $(call gb_CppunitTest_use_vcl,sc_color_scale_api)) + +$(eval $(call gb_CppunitTest_use_rdb,sc_color_scale_api,services)) + +$(eval $(call gb_CppunitTest_use_configuration,sc_color_scale_api)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/CppunitTest_sc_copypaste.mk b/sc/CppunitTest_sc_copypaste.mk index 3beac9a67222..d83e2fe45965 100644 --- a/sc/CppunitTest_sc_copypaste.mk +++ b/sc/CppunitTest_sc_copypaste.mk @@ -23,6 +23,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sc_copypaste, \ comphelper \ cppu \ cppuhelper \ + editeng \ i18nlangtag \ sal \ sc \ diff --git a/sc/CppunitTest_sc_dynamic_array_functions_test.mk b/sc/CppunitTest_sc_dynamic_array_functions_test.mk new file mode 100644 index 000000000000..36ea8374aa98 --- /dev/null +++ b/sc/CppunitTest_sc_dynamic_array_functions_test.mk @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# Copyright the LibreOffice contributors. +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 sc_functions_test,dynamic_array)) + +# vim: set noet sw=4 ts=4: diff --git a/sccomp/AllLangMoTarget_scc.mk b/sc/CppunitTest_sc_lambda_functions_test.mk similarity index 74% rename from sccomp/AllLangMoTarget_scc.mk rename to sc/CppunitTest_sc_lambda_functions_test.mk index 9bbbb1b5c14a..04751d482d27 100644 --- a/sccomp/AllLangMoTarget_scc.mk +++ b/sc/CppunitTest_sc_lambda_functions_test.mk @@ -5,9 +5,8 @@ # 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_AllLangMoTarget_AllLangMoTarget,scc)) - -$(eval $(call gb_AllLangMoTarget_set_polocation,scc,sccomp)) +$(eval $(call sc_functions_test,lambda)) # vim: set noet sw=4 ts=4: diff --git a/sc/CppunitTest_sc_named_sheet_views_import_export_test.mk b/sc/CppunitTest_sc_named_sheet_views_import_export_test.mk new file mode 100644 index 000000000000..a7a7d27fee9e --- /dev/null +++ b/sc/CppunitTest_sc_named_sheet_views_import_export_test.mk @@ -0,0 +1,71 @@ +# -*- 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,sc_named_sheet_views_import_export_test)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sc_named_sheet_views_import_export_test)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sc_named_sheet_views_import_export_test, \ + sc/qa/unit/NamedSheetViewsImportExportTest \ +)) + +$(eval $(call gb_CppunitTest_use_externals,sc_named_sheet_views_import_export_test, \ + boost_headers \ + mdds_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sc_named_sheet_views_import_export_test, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + sal \ + salhelper \ + sax \ + sc \ + scqahelper \ + sfx \ + subsequenttest \ + test \ + tl \ + unotest \ + utl \ + vcl \ +)) + +$(eval $(call gb_CppunitTest_set_include,sc_named_sheet_views_import_export_test,\ + -I$(SRCDIR)/sc/source/ui/inc \ + -I$(SRCDIR)/sc/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_api,sc_named_sheet_views_import_export_test,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,sc_named_sheet_views_import_export_test)) + +$(eval $(call gb_CppunitTest_use_ure,sc_named_sheet_views_import_export_test)) +$(eval $(call gb_CppunitTest_use_vcl,sc_named_sheet_views_import_export_test)) + +$(eval $(call gb_CppunitTest_use_rdb,sc_named_sheet_views_import_export_test,services)) + +$(eval $(call gb_CppunitTest_use_components,sc_named_sheet_views_import_export_test)) + +$(eval $(call gb_CppunitTest_use_configuration,sc_named_sheet_views_import_export_test)) + +$(eval $(call gb_CppunitTest_add_arguments,sc_named_sheet_views_import_export_test, \ + -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/CppunitTest_sc_oox_helpers_test.mk b/sc/CppunitTest_sc_oox_helpers_test.mk new file mode 100644 index 000000000000..1c2072d6700a --- /dev/null +++ b/sc/CppunitTest_sc_oox_helpers_test.mk @@ -0,0 +1,74 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# Copyright the LibreOffice contributors. +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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,sc_oox_helpers_test)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sc_oox_helpers_test)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sc_oox_helpers_test, \ + sc/qa/unit/RedundantParenthesesStripperTest \ +)) + +$(eval $(call gb_CppunitTest_use_externals,sc_oox_helpers_test, \ + boost_headers \ + mdds_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sc_oox_helpers_test, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + docmodel \ + sal \ + salhelper \ + sax \ + sc \ + scfilt \ + scqahelper \ + sfx \ + subsequenttest \ + test \ + tl \ + unotest \ + utl \ + vcl \ +)) + +$(eval $(call gb_CppunitTest_set_include,sc_oox_helpers_test,\ + -I$(SRCDIR)/sc/source/ui/inc \ + -I$(SRCDIR)/sc/source/filter/inc \ + -I$(SRCDIR)/sc/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_api,sc_oox_helpers_test,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,sc_oox_helpers_test)) + +$(eval $(call gb_CppunitTest_use_ure,sc_oox_helpers_test)) +$(eval $(call gb_CppunitTest_use_vcl,sc_oox_helpers_test)) + +$(eval $(call gb_CppunitTest_use_rdb,sc_oox_helpers_test,services)) + +$(eval $(call gb_CppunitTest_use_components,sc_oox_helpers_test)) + +$(eval $(call gb_CppunitTest_use_configuration,sc_oox_helpers_test)) + +$(eval $(call gb_CppunitTest_add_arguments,sc_oox_helpers_test, \ + -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/CppunitTest_sc_sheetview_test.mk b/sc/CppunitTest_sc_sheetview_test.mk index 80a2e54fec05..acfa9f300bd0 100644 --- a/sc/CppunitTest_sc_sheetview_test.mk +++ b/sc/CppunitTest_sc_sheetview_test.mk @@ -44,6 +44,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sc_sheetview_test, \ $(eval $(call gb_CppunitTest_use_externals,sc_sheetview_test,\ boost_headers \ libxml2 \ + mdds_headers \ )) $(eval $(call gb_CppunitTest_set_include,sc_sheetview_test,\ diff --git a/sc/CppunitTest_sc_solver.mk b/sc/CppunitTest_sc_solver.mk new file mode 100644 index 000000000000..ee545c8477b3 --- /dev/null +++ b/sc/CppunitTest_sc_solver.mk @@ -0,0 +1,42 @@ +# -*- 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,sc_solver)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sc_solver,\ + sc/qa/unit/solver \ +)) + +$(eval $(call gb_CppunitTest_add_defs,sc_solver,\ + $(if $(ENABLE_COINMP), -DENABLE_COINMP) \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sc_solver,\ + cppu \ + sal \ + test \ + unotest \ +)) + +$(eval $(call gb_CppunitTest_set_include,sc_solver,\ + -I$(SRCDIR)/sc/inc \ + $$(INCLUDE) \ +)) + + +$(eval $(call gb_CppunitTest_use_sdk_api,sc_solver)) + +$(eval $(call gb_CppunitTest_use_ure,sc_solver)) +$(eval $(call gb_CppunitTest_use_vcl,sc_solver)) + +$(eval $(call gb_CppunitTest_use_rdb,sc_solver,services)) + +$(eval $(call gb_CppunitTest_use_configuration,sc_solver)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/CppunitTest_sc_subsequent_export_test6.mk b/sc/CppunitTest_sc_subsequent_export_test6.mk new file mode 100644 index 000000000000..b537426fccf8 --- /dev/null +++ b/sc/CppunitTest_sc_subsequent_export_test6.mk @@ -0,0 +1,12 @@ +# -*- 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 sc_subsequent_test,export_test6)) + +# vim: set noet sw=4 ts=4: diff --git a/sccomp/CppunitTest_sccomp_swarmsolvertest.mk b/sc/CppunitTest_sc_swarmsolvertest.mk similarity index 57% rename from sccomp/CppunitTest_sccomp_swarmsolvertest.mk rename to sc/CppunitTest_sc_swarmsolvertest.mk index c1966a5fce66..73c69d0c1c2c 100644 --- a/sccomp/CppunitTest_sccomp_swarmsolvertest.mk +++ b/sc/CppunitTest_sc_swarmsolvertest.mk @@ -7,17 +7,17 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # -$(eval $(call gb_CppunitTest_CppunitTest,sccomp_swarmsolvertest)) +$(eval $(call gb_CppunitTest_CppunitTest,sc_swarmsolvertest)) -$(eval $(call gb_CppunitTest_add_exception_objects,sccomp_swarmsolvertest,\ - sccomp/qa/unit/SwarmSolverTest \ +$(eval $(call gb_CppunitTest_add_exception_objects,sc_swarmsolvertest,\ + sc/qa/unit/SwarmSolverTest \ )) -$(eval $(call gb_CppunitTest_use_externals,sccomp_swarmsolvertest,\ +$(eval $(call gb_CppunitTest_use_externals,sc_swarmsolvertest,\ libxml2 \ )) -$(eval $(call gb_CppunitTest_use_libraries,sccomp_swarmsolvertest,\ +$(eval $(call gb_CppunitTest_use_libraries,sc_swarmsolvertest,\ basegfx \ comphelper \ cppu \ @@ -55,18 +55,19 @@ $(eval $(call gb_CppunitTest_use_libraries,sccomp_swarmsolvertest,\ $(gb_UWINAPI) \ )) -$(eval $(call gb_CppunitTest_set_include,sccomp_swarmsolvertest,\ +$(eval $(call gb_CppunitTest_set_include,sc_swarmsolvertest,\ -I$(SRCDIR)/sc/inc \ + -I$(SRCDIR)/sc/source/solver \ $$(INCLUDE) \ )) -$(eval $(call gb_CppunitTest_use_sdk_api,sccomp_swarmsolvertest)) +$(eval $(call gb_CppunitTest_use_sdk_api,sc_swarmsolvertest)) -$(eval $(call gb_CppunitTest_use_ure,sccomp_swarmsolvertest)) -$(eval $(call gb_CppunitTest_use_vcl,sccomp_swarmsolvertest)) +$(eval $(call gb_CppunitTest_use_ure,sc_swarmsolvertest)) +$(eval $(call gb_CppunitTest_use_vcl,sc_swarmsolvertest)) -$(eval $(call gb_CppunitTest_use_rdb,sccomp_swarmsolvertest,services)) +$(eval $(call gb_CppunitTest_use_rdb,sc_swarmsolvertest,services)) -$(eval $(call gb_CppunitTest_use_configuration,sccomp_swarmsolvertest)) +$(eval $(call gb_CppunitTest_use_configuration,sc_swarmsolvertest)) # vim: set noet sw=4 ts=4: diff --git a/external/lpsolve/Module_lpsolve.mk b/sc/CppunitTest_sc_ucalc_spilled_range.mk similarity index 64% rename from external/lpsolve/Module_lpsolve.mk rename to sc/CppunitTest_sc_ucalc_spilled_range.mk index e0094f609c7d..6a271d43724d 100644 --- a/external/lpsolve/Module_lpsolve.mk +++ b/sc/CppunitTest_sc_ucalc_spilled_range.mk @@ -1,4 +1,5 @@ # -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* # # This file is part of the LibreOffice project. # @@ -6,13 +7,8 @@ # 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,lpsolve)) - -$(eval $(call gb_Module_add_targets,lpsolve,\ - UnpackedTarball_lpsolve \ - ExternalPackage_lpsolve \ - ExternalProject_lpsolve \ -)) +$(eval $(call sc_ucalc_test,_spilled_range)) # vim: set noet sw=4 ts=4: diff --git a/sc/CppunitTest_sc_ucalc_tablestyles.mk b/sc/CppunitTest_sc_ucalc_tablestyles.mk new file mode 100644 index 000000000000..963d9e225a8c --- /dev/null +++ b/sc/CppunitTest_sc_ucalc_tablestyles.mk @@ -0,0 +1,70 @@ +# -*- 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,sc_ucalc_tablestyles)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sc_ucalc_tablestyles)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sc_ucalc_tablestyles, \ + sc/qa/unit/ucalc_tablestyles \ +)) + +$(eval $(call gb_CppunitTest_use_externals,sc_ucalc_tablestyles, \ + boost_headers \ + mdds_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sc_ucalc_tablestyles, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + docmodel \ + editeng \ + sal \ + salhelper \ + sax \ + sc \ + svl \ + scqahelper \ + sfx \ + svxcore \ + subsequenttest \ + test \ + tl \ + unotest \ + utl \ + vcl \ +)) + +$(eval $(call gb_CppunitTest_set_include,sc_ucalc_tablestyles,\ + -I$(SRCDIR)/sc/source/ui/inc \ + -I$(SRCDIR)/sc/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_api,sc_ucalc_tablestyles,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,sc_ucalc_tablestyles)) +$(eval $(call gb_CppunitTest_use_ure,sc_ucalc_tablestyles)) +$(eval $(call gb_CppunitTest_use_vcl,sc_ucalc_tablestyles)) +$(eval $(call gb_CppunitTest_use_rdb,sc_ucalc_tablestyles,services)) +$(eval $(call gb_CppunitTest_use_components,sc_ucalc_tablestyles)) +$(eval $(call gb_CppunitTest_use_configuration,sc_ucalc_tablestyles)) +$(eval $(call gb_CppunitTest_add_arguments,sc_ucalc_tablestyles, \ + -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 1d37082a2add..3b9bffd444d5 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -202,6 +202,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/core/data/stlsheet \ sc/source/core/data/subtotalparam \ sc/source/core/data/tabbgcolor \ + sc/source/core/data/TableContentCopier \ sc/source/core/data/table1 \ sc/source/core/data/table2 \ sc/source/core/data/table3 \ @@ -209,12 +210,14 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/core/data/table5 \ sc/source/core/data/table6 \ sc/source/core/data/table7 \ + sc/source/core/data/TableStyleGenerator \ sc/source/core/data/tablestyle \ sc/source/core/data/tabprotection \ sc/source/core/data/types \ sc/source/core/data/userdat \ sc/source/core/data/validat \ sc/source/core/data/pivot/PivotTableResultTraverser \ + sc/source/core/data/pivot/StyleOutput \ sc/source/core/tool/addincfg \ sc/source/core/tool/addincol \ sc/source/core/tool/addinhelpid \ @@ -225,6 +228,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/core/tool/arraysumSSE2 \ sc/source/core/tool/autoform \ sc/source/core/tool/calcconfig \ + sc/source/core/tool/callable \ sc/source/core/tool/callform \ sc/source/core/tool/cellform \ sc/source/core/tool/cellkeytranslator \ @@ -511,7 +515,6 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/ui/miscdlgs/datatableview \ sc/source/ui/miscdlgs/highred \ sc/source/ui/miscdlgs/mergecellsdialog \ - sc/source/ui/miscdlgs/onlyactivesheetsaveddlg \ sc/source/ui/miscdlgs/optsolver \ sc/source/ui/miscdlgs/protectiondlg \ sc/source/ui/miscdlgs/duplicaterecordsdlg \ @@ -531,6 +534,50 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/ui/navipi/navcitem \ sc/source/ui/navipi/navipi \ sc/source/ui/navipi/scenwnd \ + sc/source/ui/operation/ApplyAttributesOperation \ + sc/source/ui/operation/AutoFormatOperation \ + sc/source/ui/operation/ChangeIndentOperation \ + sc/source/ui/operation/ChangeSparklineGroupAttributesOperation \ + sc/source/ui/operation/ChangeSparklineOperation \ + sc/source/ui/operation/ClearItemsOperation \ + sc/source/ui/operation/ConvertFormulaToValueOperation \ + sc/source/ui/operation/CreatePivotTableOperation \ + sc/source/ui/operation/ReplacePivotTableOperation \ + sc/source/ui/operation/DeleteCellOperation \ + sc/source/ui/operation/DeleteCellsOperation \ + sc/source/ui/operation/DeleteContentOperation \ + sc/source/ui/operation/DeleteSparklineGroupOperation \ + sc/source/ui/operation/DeleteSparklineOperation \ + sc/source/ui/operation/EnterMatrixOperation \ + sc/source/ui/operation/FillAutoOperation \ + sc/source/ui/operation/FillSeriesOperation \ + sc/source/ui/operation/FillSimpleOperation \ + sc/source/ui/operation/GroupSparklinesOperation \ + sc/source/ui/operation/InsertCellsOperation \ + sc/source/ui/operation/InsertNameListOperation \ + sc/source/ui/operation/InsertSheetViewOperation \ + sc/source/ui/operation/InsertSparklinesOperation \ + sc/source/ui/operation/InsertThreadedCommentOperation \ + sc/source/ui/operation/MergeCellsOperation \ + sc/source/ui/operation/MoveBlockOperation \ + sc/source/ui/operation/MultipleOpsOperation \ + sc/source/ui/operation/Operation \ + sc/source/ui/operation/OperationType \ + sc/source/ui/operation/PivotTableOperation \ + sc/source/ui/operation/QueryOperation \ + sc/source/ui/operation/RemovePivotTableOperation \ + sc/source/ui/operation/ReplaceNoteTextOperation \ + sc/source/ui/operation/SetEditTextOperation \ + sc/source/ui/operation/SetNoteTextOperation \ + sc/source/ui/operation/SetFormulaOperation \ + sc/source/ui/operation/SetNormalStringOperation \ + sc/source/ui/operation/SetStringOperation \ + sc/source/ui/operation/SetValueOperation \ + sc/source/ui/operation/SubTotalsOperation \ + sc/source/ui/operation/SortOperation \ + sc/source/ui/operation/TransliterateTextOperation \ + sc/source/ui/operation/UngroupSparklinesOperation \ + sc/source/ui/operation/UpdatePivotTableOperation \ sc/source/ui/pagedlg/areasdlg \ sc/source/ui/pagedlg/tphfedit \ sc/source/ui/sidebar/AlignmentPropertyPanel \ @@ -580,6 +627,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/ui/undo/undoolk \ sc/source/ui/undo/undorangename \ sc/source/ui/undo/undosort \ + sc/source/ui/undo/UndoSheetViewSortData \ sc/source/ui/undo/undostyl \ sc/source/ui/undo/undotab \ sc/source/ui/undo/undoutil \ @@ -590,6 +638,8 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/ui/undo/UndoUngroupSparklines \ sc/source/ui/undo/UndoGroupSparklines \ sc/source/ui/undo/UndoEditSparkline \ + sc/source/ui/undo/UndoInsertSheetView \ + sc/source/ui/undo/UndoSpillPivotTable \ sc/source/ui/undo/UndoThemeChange \ sc/source/ui/unoobj/ChartRangeSelectionListener \ sc/source/ui/unoobj/addruno \ diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk index 941d0bc36998..d5cd1bdb0238 100644 --- a/sc/Library_scfilt.mk +++ b/sc/Library_scfilt.mk @@ -132,6 +132,7 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\ sc/source/filter/excel/xltools \ sc/source/filter/excel/xltracer \ sc/source/filter/excel/xlview \ + sc/source/filter/excel/export/NamedSheetViews \ sc/source/filter/excel/export/SparklineExt \ sc/source/filter/excel/export/ExportTools \ sc/source/filter/ftools/fapihelper \ @@ -172,12 +173,15 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\ sc/source/filter/oox/chartsheetfragment \ sc/source/filter/oox/commentsbuffer \ sc/source/filter/oox/commentsfragment \ + sc/source/filter/oox/personsfragment \ + sc/source/filter/oox/threadedcommentsfragment \ + sc/source/filter/oox/NamedSheetViewFragment \ + sc/source/filter/oox/NamedSheetViewImporter \ sc/source/filter/oox/condformatbuffer \ sc/source/filter/oox/condformatcontext \ sc/source/filter/oox/connectionsbuffer \ sc/source/filter/oox/connectionsfragment \ sc/source/filter/oox/defnamesbuffer \ - sc/source/filter/oox/defaulttablestyles \ sc/source/filter/oox/drawingbase \ sc/source/filter/oox/drawingfragment \ sc/source/filter/oox/excelchartconverter \ diff --git a/sccomp/Library_solver.mk b/sc/Library_solver.mk similarity index 77% rename from sccomp/Library_solver.mk rename to sc/Library_solver.mk index 1eeac011f2da..d2dbf705fcc5 100644 --- a/sccomp/Library_solver.mk +++ b/sc/Library_solver.mk @@ -19,18 +19,18 @@ $(eval $(call gb_Library_Library,solver)) -$(eval $(call gb_Library_set_componentfile,solver,sccomp/source/solver/solver,services)) +$(eval $(call gb_Library_set_componentfile,solver,sc/source/solver/solver,services)) $(eval $(call gb_Library_add_componentimpls,solver, \ $(if $(ENABLE_COINMP),coinmp) \ - $(if $(ENABLE_LPSOLVE),lpsolve) \ )) $(eval $(call gb_Library_use_sdk_api,solver)) $(eval $(call gb_Library_set_include,solver,\ $$(INCLUDE) \ - -I$(SRCDIR)/sccomp/inc \ + -I$(SRCDIR)/sc/inc \ + -I$(SRCDIR)/sc/source/solver \ )) $(eval $(call gb_Library_use_libraries,solver,\ @@ -38,20 +38,22 @@ $(eval $(call gb_Library_use_libraries,solver,\ cppu \ cppuhelper \ sal \ + sc \ utl \ i18nlangtag \ )) $(eval $(call gb_Library_use_externals,solver,\ + boost_headers \ coinmp \ - lpsolve \ )) $(eval $(call gb_Library_add_exception_objects,solver,\ - sccomp/source/solver/SwarmSolver \ - sccomp/source/solver/SolverComponent \ - $(if $(ENABLE_COINMP), sccomp/source/solver/CoinMPSolver) \ - $(if $(ENABLE_LPSOLVE), sccomp/source/solver/LpsolveSolver) \ + sc/source/solver/SwarmSolver \ + sc/source/solver/SolverComponent \ + $(if $(ENABLE_COINMP), sc/source/solver/CoinMPSolver) \ + $(if $(ENABLE_COINMP), sc/source/solver/CoinMPModel) \ + $(if $(ENABLE_COINMP), sc/source/solver/SlpSolver) \ )) # vim: set noet sw=4 ts=4: diff --git a/sc/Module_sc.mk b/sc/Module_sc.mk index ec14b7faef51..859a87326b42 100644 --- a/sc/Module_sc.mk +++ b/sc/Module_sc.mk @@ -20,6 +20,7 @@ $(eval $(call gb_Module_add_targets,sc,\ Library_scd \ Library_scfilt \ Library_scui \ + Library_solver \ $(call gb_Helper_optional,OPENCL,Package_opencl) \ Package_res_xml \ UIConfig_scalc \ @@ -29,6 +30,11 @@ $(eval $(call gb_Module_add_l10n_targets,sc,\ AllLangMoTarget_sc \ )) +$(eval $(call gb_Module_add_check_targets,sc,\ + CppunitTest_sc_solver \ + $(if $(and $(filter INTEL,$(CPUNAME)),$(filter -fsanitize=%,$(gb_CXX))),,$(if $(filter SCRIPTING,$(BUILD_TYPE)),CppunitTest_sc_swarmsolvertest)) \ +)) + ifneq ($(filter SCRIPTING,$(BUILD_TYPE)),) $(eval $(call gb_Module_add_targets,sc,\ @@ -48,8 +54,10 @@ $(eval $(call gb_Module_add_check_targets,sc,\ CppunitTest_sc_ucalc_copypaste \ CppunitTest_sc_ucalc_datatransformation \ CppunitTest_sc_ucalc_document_themes \ + CppunitTest_sc_ucalc_tablestyles \ CppunitTest_sc_ucalc_formula \ CppunitTest_sc_ucalc_formula2 \ + CppunitTest_sc_ucalc_spilled_range \ CppunitTest_sc_ucalc_parallelism \ CppunitTest_sc_ucalc_pivottable \ CppunitTest_sc_ucalc_rangelst \ @@ -59,13 +67,14 @@ $(eval $(call gb_Module_add_check_targets,sc,\ CppunitTest_sc_ucalc_solver \ CppunitTest_sc_ucalc_sort \ CppunitTest_sc_filters_test \ + CppunitTest_sc_oox_helpers_test \ CppunitTest_sc_mark_test \ CppunitTest_sc_core \ CppunitTest_sc_basic_types_test \ CppunitTest_sc_dataprovider \ CppunitTest_sc_cache_test \ CppunitTest_sc_parallelism \ - CppunitTest_sc_shapetest \ + CppunitTest_sc_shapetest \ )) endif @@ -80,6 +89,7 @@ endif $(eval $(call gb_Module_add_slowcheck_targets,sc, \ CppunitTest_sc_anchor_test \ + CppunitTest_sc_color_scale_api \ CppunitTest_sc_cond_format \ CppunitTest_sc_cond_format_merge \ CppunitTest_sc_copypaste \ @@ -90,18 +100,20 @@ $(eval $(call gb_Module_add_slowcheck_targets,sc, \ CppunitTest_sc_pdf_export \ CppunitTest_sc_pivottable_filters_test \ CppunitTest_sc_pivottable_formats_import_export_test \ + CppunitTest_sc_named_sheet_views_import_export_test \ CppunitTest_sc_scriptforge_test \ CppunitTest_sc_sparkline_test \ CppunitTest_sc_subsequent_filters_test \ CppunitTest_sc_subsequent_filters_test2 \ CppunitTest_sc_subsequent_filters_test3 \ CppunitTest_sc_subsequent_filters_test4 \ - CppunitTest_sc_subsequent_filters_test5 \ + CppunitTest_sc_subsequent_filters_test5 \ CppunitTest_sc_subsequent_export_test \ CppunitTest_sc_subsequent_export_test2 \ CppunitTest_sc_subsequent_export_test3 \ CppunitTest_sc_subsequent_export_test4 \ CppunitTest_sc_subsequent_export_test5 \ + CppunitTest_sc_subsequent_export_test6 \ CppunitTest_sc_uicalc \ CppunitTest_sc_uicalc2 \ CppunitTest_sc_vba_macro_test \ @@ -129,11 +141,13 @@ $(eval $(call gb_Module_add_slowcheck_targets,sc, \ CppunitTest_sc_datetime_functions_test \ CppunitTest_sc_financial_functions_test \ CppunitTest_sc_information_functions_test \ + CppunitTest_sc_lambda_functions_test \ CppunitTest_sc_logical_functions_test \ CppunitTest_sc_mathematical_functions_test \ CppunitTest_sc_spreadsheet_functions_test \ CppunitTest_sc_statistical_functions_test \ CppunitTest_sc_text_functions_test \ + CppunitTest_sc_dynamic_array_functions_test \ CppunitTest_sc_annotationobj \ CppunitTest_sc_annotationshapeobj \ CppunitTest_sc_annotationsobj \ @@ -252,8 +266,8 @@ $(eval $(call gb_Module_add_subsequentcheck_targets,sc,\ JunitTest_sc_unoapi_4 \ JunitTest_sc_unoapi_6 \ JunitTest_sc_unoapi_7 \ - CppunitTest_sc_opencl-1 \ - CppunitTest_sc_opencl-2 \ + $(call gb_Helper_optional,OPENCL,CppunitTest_sc_opencl-1) \ + $(call gb_Helper_optional,OPENCL,CppunitTest_sc_opencl-2) \ )) $(eval $(call gb_Module_add_perfcheck_targets,sc,\ @@ -287,6 +301,7 @@ $(eval $(call gb_Module_add_uicheck_targets,sc,\ UITest_goalSeek \ UITest_protect \ UITest_sc_options \ + UITest_sc_vba \ UITest_validity \ UITest_key_f4 \ UITest_textCase \ @@ -304,9 +319,10 @@ $(eval $(call gb_Module_add_uicheck_targets,sc,\ UITest_calc_tests9 \ UITest_function_wizard \ UITest_manual_tests \ + UITest_sc_styleui \ )) -ifneq ($(or $(ENABLE_LPSOLVE),$(ENABLE_COINMP)),) +ifneq ($(ENABLE_COINMP),) $(eval $(call gb_Module_add_uicheck_targets,sc,\ UITest_solver \ )) diff --git a/sc/README.Lambda.md b/sc/README.Lambda.md new file mode 100644 index 000000000000..4ca1efcf1215 --- /dev/null +++ b/sc/README.Lambda.md @@ -0,0 +1,130 @@ +# `LAMBDA` + +The `LAMBDA` operator builds a callable function out of a Calc formula. + +## Using `LAMBDA` + +* `LAMBDA` expects a list of parameter names, followed by an expression. + +* All parameter names must be valid identifiers, and must not match any names +already defined by Calc, nor any possible cell references. Identifiers are not +case-sensitive. Identifiers must start with a letter, and may contain only +letters, numbers, and underscores (`_`). + +* You may specify no parameters, if you want the function to operate the same +way every time it is called (this may be useful if its expression includes +volatile operators such as `RAND` or `TIME`). + +* The result of a `LAMBDA` is a function. Don't expect that to show up in the +spreadsheet in any useful way! You must call the function to use it. + +* Call a `LAMBDA` function just like you call a built-in function: put the name +of the function (either a named range, a cell reference, or the `LAMBDA` +expression itself) into your formula before a pair of parentheses containing the +arguments you want to pass to the function. + +* If you are nesting one `LAMBDA` inside another, you may use the same parameter +name in both (if you really want - this can easily make things hard to read!). +The innermost `LAMBDA` specifying a parameter of a given name applies at each +level of scope. This also works with `LET`. + +* A function can call itself (this is called recursion), but you must be able to +refer to it from within the function. For example, if cell `A1` is a `LAMBDA` +formula, the body of the `LAMBDA` can call itself by referring to `A1`. You can +name your `LAMBDA` cell to make this easier to read. + +* If you want your `LAMBDA` function to permit optional parameters, enclose +those parameter names (in the parameter list, not in the body) in brackets, like +this: +> =LAMBDA(name1, name2, [name3], [name4], expression) + +* `ISOMITTED` can be used within a `LAMBDA` body to detect whether an optional +parameter was provided or omitted. + +* Optional parameters must not appear before any required parameters in the +parameter list. Your parameters can appear in any order inside the body. + +### Examples + +(This form is permitted, but not recommended, as it is difficult to read.) + +> `A1`: `=LAMBDA(a,b,a+b)(3*5,7/(6+4))` + +`A1` will show `15.7` (=`(3*5)+(7/(6+4))` ) + +--- + +> `A1`: `=LAMBDA(a,b,a+b)` +> +> `B1`: `=A1(3*5, 7/(6+4))` + +`B1` will show `15.7` + +--- + +If `MY_SUM` is `A1`: + +> `A1`: `=LAMBDA(a,b,a+b)` +> +> `B1`: `=MY_SUM(3*5,7/(6+4))` + +`B1` will show `15.7` + +--- + +If `FACT` is `A1`: + +> `A1`: `=LAMBDA(n,IF(n>1,n*FACT(n-1),1))` +> +> `B1`: `=FACT(5)` + +`B1` will show `120` (`FACT` duplicates the functionality of the built-in +`FACTORIAL` function, but is less efficient) + +## How it Works + +* The `ocLambda` `OpCode` corresponds to the `LAMBDA` operator + +* `ocLambda` is set up as a jump `OpCode`, meaning that it has special rules for +what parameters are evaluated, and when. + +* The first stage of the compiler tokenizes the elements of the `LAMBDA` +expression, like any other. It also looks for the lambda parameters, and interns +them as identifiers. + +* The second stage of the compiler sets up the jump table with the parameters +and body. It also looks for any parameters between +`ocTableRefOpen`/`ocTableRefClose` (which correspond to brackets), and sets +`mIsOptional` for those parameters. + +* The `ocLambda` is built in the compiled code as a sequence consisting of the +`ocLambda` token itself, then the parameter names (`svStringName`) separated by +`ocSep`, followed by another `ocSep`, then the lambda body, with `ocClose` at +the end. The jump table points to the `ocLambda`, each `ocSep`, and the +`ocClose`, which allows the interpreter to find each parameter name (the +`ocLambda` and `ocSep`s except the last), the body (the last `ocSep`), and the +position where execution continues (`ocClose`). + +* When interpreted, `ocLambda` causes a `ScFormulaFunction` to be built using +the contents of the jump table. At this point all parameters are counted, and +that information is passed on to the next step. + +* `ScFormulaFunction`'s constructor clones the lambda body and saves the +interpreter's contextual information, then locates each use of each parameter in +the scope of that identifier in the body and makes note of where it is. + +* When a `ScFormulaFunction` is called via `ScInterpreter::ScCall`, it builds a +new interpreter out of the saved context, performs the replacements specified, +and executes the interpreter to obtain a result. This means that the `LAMBDA` +body is executed in the same context that the `LAMBDA` appeared in. + +* `ocLambda` is itself nonvolatile, and overrides any volatility in its body, +since the `LAMBDA` never produces a different callable, no matter what functions +appear in the body. + +* The presence of an enclosing `LAMBDA` also prevents circular references from +being a problem, as the body of a `LAMBDA` is not executed until the cell +containing it already has a value. This allows recursion. + +* `LAMBDA` does not currently check for infinite recursion; avoid recursive +calls that can cause such a loop. diff --git a/sc/README.md b/sc/README.md index 0bcdf7b2180a..6bbec63d59eb 100644 --- a/sc/README.md +++ b/sc/README.md @@ -83,8 +83,6 @@ https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocume * Information Functions * COUNTIF * COUNTIFS -* Lambda Functions - * LET * Lookup Functions * HLOOKUP * LOOKUP diff --git a/sc/UIConfig_scalc.mk b/sc/UIConfig_scalc.mk index 69483d0faa4f..2b508d492154 100644 --- a/sc/UIConfig_scalc.mk +++ b/sc/UIConfig_scalc.mk @@ -171,7 +171,6 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\ sc/uiconfig/scalc/ui/notebookbar_groups \ sc/uiconfig/scalc/ui/notebookbar_groupedbar_full \ sc/uiconfig/scalc/ui/notebookbar_groupedbar_compact \ - sc/uiconfig/scalc/ui/notebookbar_online \ sc/uiconfig/scalc/ui/numberbox \ sc/uiconfig/scalc/ui/managenamesdialog \ sc/uiconfig/scalc/ui/mergecellsdialog \ @@ -190,7 +189,6 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\ sc/uiconfig/scalc/ui/multipleoperationsdialog \ sc/uiconfig/scalc/ui/navigatorpanel \ sc/uiconfig/scalc/ui/nosolutiondialog \ - sc/uiconfig/scalc/ui/onlyactivesheetsaveddialog \ sc/uiconfig/scalc/ui/optcalculatepage \ sc/uiconfig/scalc/ui/optchangespage \ sc/uiconfig/scalc/ui/optcompatibilitypage \ diff --git a/sc/UITest_sc_styleui.mk b/sc/UITest_sc_styleui.mk new file mode 100644 index 000000000000..408560d0d39a --- /dev/null +++ b/sc/UITest_sc_styleui.mk @@ -0,0 +1,19 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_UITest_UITest,sc_styleui)) +$(eval $(call gb_UITest_add_modules,sc_styleui,$(SRCDIR)/sc/qa/uitest,\ + styleui/ \ +)) +$(eval $(call gb_UITest_set_defs,sc_styleui, \ + TDOC="$(SRCDIR)/sc/qa/uitest/data" \ +)) +$(eval $(call gb_UITest_avoid_oneprocess,sc_styleui)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/UITest_sc_vba.mk b/sc/UITest_sc_vba.mk new file mode 100644 index 000000000000..392f0f113145 --- /dev/null +++ b/sc/UITest_sc_vba.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_UITest_UITest,sc_vba)) + +$(eval $(call gb_UITest_add_modules,sc_vba,$(SRCDIR)/sc/qa/uitest,\ + vba/ \ +)) + +$(eval $(call gb_UITest_set_defs,sc_vba, \ + TDOC="$(SRCDIR)/sc/qa/uitest/data" \ +)) + +# vim: set noet sw=4 ts=4: \ No newline at end of file diff --git a/sc/common_unoapi_tests.mk b/sc/common_unoapi_tests.mk index 34cc34e45a71..c643672dc518 100644 --- a/sc/common_unoapi_tests.mk +++ b/sc/common_unoapi_tests.mk @@ -22,7 +22,7 @@ $(eval $(call gb_CppunitTest_use_externals,sc_$(1), \ $(eval $(call gb_Library_use_common_precompiled_header,sc_$(1))) $(eval $(call gb_CppunitTest_add_defs,sc_$(1),\ - $(if $(ENABLE_LPSOLVE), -DENABLE_LPSOLVE) \ + $(if $(ENABLE_COINMP), -DENABLE_COINMP) \ )) $(eval $(call gb_CppunitTest_add_exception_objects,sc_$(1), \ diff --git a/sc/functions_setup.mk b/sc/functions_setup.mk index 2a0c78c8fca9..80ea4d57b4ff 100644 --- a/sc/functions_setup.mk +++ b/sc/functions_setup.mk @@ -22,6 +22,7 @@ $(eval $(call gb_CppunitTest_use_externals,sc_$(1)_functions_test, \ boost_headers \ mdds_headers \ md4c \ + libxml2 \ )) $(eval $(call gb_CppunitTest_use_libraries,sc_$(1)_functions_test, \ @@ -44,6 +45,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sc_$(1)_functions_test, \ scqahelper \ sfx \ sot \ + subsequenttest \ svl \ svt \ svx \ diff --git a/sc/inc/FilterData.hxx b/sc/inc/FilterData.hxx index 82e161738087..6dbbfd7d854b 100644 --- a/sc/inc/FilterData.hxx +++ b/sc/inc/FilterData.hxx @@ -84,6 +84,8 @@ public: SCROW countVisibleRows(SCROW nStartRow, SCROW nEndRow) const; SCCOL countVisibleCols(SCCOL nStartCol, SCCOL nEndCol) const; SCCOLROW lastHiddenColRow(SCCOLROW nPos, bool bCol) const; + + const ScFlatBoolColSegments& getHiddenCols() const { return *mpHiddenCols; } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/MatrixResizeGuard.hxx b/sc/inc/MatrixResizeGuard.hxx new file mode 100644 index 000000000000..85f9a1a92d25 --- /dev/null +++ b/sc/inc/MatrixResizeGuard.hxx @@ -0,0 +1,48 @@ +/* -*- 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/. + */ + +#pragma once + +#include "document.hxx" + +namespace sc +{ +/** + * Pushes a matrix-resize guard for the lifetime of this object, then drains + * any pending resizes queued during the guarded iteration when we go out of + * scope. + * + * Use at every scope that iterates the cell store while Interpret() may + * run on visited cells. + */ +class MatrixResizeGuard +{ + ScDocument& mrDoc; + +public: + explicit MatrixResizeGuard(ScDocument& rDoc) + : mrDoc(rDoc) + { + mrDoc.PushMatrixResizeGuard(); + } + + ~MatrixResizeGuard() + { + mrDoc.PopMatrixResizeGuard(); + if (mrDoc.HasPendingMatrixResizes() && !mrDoc.IsMatrixResizeGuarded()) + mrDoc.ProcessPendingMatrixResizes(); + } + + MatrixResizeGuard(const MatrixResizeGuard&) = delete; + MatrixResizeGuard& operator=(const MatrixResizeGuard&) = delete; +}; + +} // namespace sc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/SheetView.hxx b/sc/inc/SheetView.hxx index bfec055cdcba..f4c7d5536f21 100644 --- a/sc/inc/SheetView.hxx +++ b/sc/inc/SheetView.hxx @@ -11,37 +11,69 @@ #include "scdllapi.h" #include "types.hxx" +#include #include #include "SheetViewTypes.hxx" +#include "sortparam.hxx" #include #include +#include class ScTable; namespace sc { +/** Contains the information of an performed sort action */ +struct SC_DLLPUBLIC SortOrderInfo +{ + SCCOL mnFirstColumn = -1; + SCCOL mnLastColumn = -1; + SCROW mnFirstRow = -1; + SCROW mnLastRow = -1; + std::vector maOrder; // Remember the sort order + std::vector maKeyStates; // Each column sort information +}; + /** Stores the sort order and can reverse the sorting of rows (unsorting). */ struct SC_DLLPUBLIC SortOrderReverser { public: - SCROW mnFirstRow; - SCROW mnLastRow; - std::vector maOrder; + SortOrderInfo maSortInfo; /** Reverse the sort for the input row and output the unsorted row. * * Uses the sort order. The row must be between range of [first row, last row] * or it will return the input row without modification. **/ - SCROW unsort(SCROW nRow) const; - SCROW resort(SCROW nRow) const; + SCROW unsort(SCROW nRow, SCCOL nColumn) const; + SCROW resort(SCROW nRow, SCCOL nColumn) const; /** Adds or combines the order indices. * * Adds the indices if none are present, or combines the indices if the order indices * were already added previously. **/ - void addOrderIndices(std::vector const& rOrder, SCROW firstRow, SCROW lastRow); + void addOrderIndices(SortOrderInfo const& rSortInfo); + + /** Update data when rows are inserted. */ + void insertedRows(SCROW nStartRow, SCROW nRowCount); + + /** Update data when rows are deleted. */ + void deletedRows(SCROW nStartRow, SCROW nRowCount); + + /** Update data when columns are inserted. */ + void insertedColumns(SCCOL nStartCol, SCCOL nColCount); + + /** Update data when columns are deleted. */ + void deletedColumns(SCCOL nStartCol, SCCOL nColCount); +}; + +/** Sort data holder. */ +struct SC_DLLPUBLIC SheetViewSortData +{ + SortOrderReverser maSortOrder; + ReorderParam maOriginalReorderParams; + ScSortParam maSortParam; }; /** Stores information of a sheet view. @@ -53,38 +85,92 @@ class SC_DLLPUBLIC SheetView { private: ScTable* mpTable = nullptr; - bool mbSynced = true; OUString maName; - - std::optional moSortOrder; SheetViewID mnID; + // GUIDs + OString maGUID; + OString maFilterGUID; + + /** Sort data - nullptr when no sort has been performed. */ + std::shared_ptr mpSortData; + + /** Ensure sort data is allocated. */ + SheetViewSortData& ensureSortData(); + + void adjustReorderParamsForInsertRows(SCROW nStartRow, SCROW nRowCount); + void adjustReorderParamsForInsertColumns(SCCOL nStartCol, SCCOL nColCount); + void adjustReorderParamsForDeleteRows(SCROW nStartRow, SCROW nRowCount); + void adjustReorderParamsForDeleteColumns(SCCOL nStartCol, SCCOL nColCount); + + void adjustSortParamForInsertRows(SCROW nStartRow, SCROW nRowCount); + void adjustSortParamForInsertColumns(SCCOL nStartCol, SCCOL nColCount); + void adjustSortParamForDeleteRows(SCROW nStartRow, SCROW nRowCount); + void adjustSortParamForDeleteColumns(SCCOL nStartCol, SCCOL nColCount); + public: SheetView(ScTable* pTable, OUString const& rName, SheetViewID nID); ScTable* getTablePointer() const; SCTAB getTableNumber() const; + SheetViewID getID() const { return mnID; } - OUString const& GetName() { return maName; } + OUString const& GetName() const { return maName; } + void SetName(OUString const& rName) { maName = rName; } - /** A sheet view is valid if the pointer to the table is set */ - bool isValid() const; + OString const& GetGUID() const { return maGUID; } + void SetGUID(OString const& rGUID) { maGUID = rGUID; } - /** Mark the sheet view as unsynced (not synced). */ - void unsync() { mbSynced = false; } + OString const& GetFilterGUID() const { return maFilterGUID; } + void SetFilterGUID(OString const& rGUID) { maFilterGUID = rGUID; } - /** Is the sheet view synced with its default view. */ - bool isSynced() const { return mbSynced; } - - std::optional const& getSortOrder() const { return moSortOrder; } + SortOrderReverser const* getSortOrder() const; + void resetSortOrder(); /** Adds or combines the order indices. * * Adds the indices if none are present, or combines the indices if the order indices * were already added previously. **/ - void addOrderIndices(std::vector const& rOrder, SCROW firstRow, SCROW lastRow); + void addOrderIndices(SortOrderInfo const& rSortInfo); + + /** Merges the reorder parameters */ + void mergeReorderParameters(ReorderParam const& rReorderParameters); + ReorderParam const* getReorderParameters() const; + + /** Reverses the complete (sheet view and default view) sorting order for the input row */ + SCROW reverseSortingToDefaultView(SCROW nRow, SCCOL nColumn) const; + + /** Converts a row from the default view to the row in this sheet view, taking sorting data into account. */ + SCROW reverseDefaultViewToSheetView(SCROW nRow, SCCOL nColumn) const; + + /** Update stored sort ranges when rows are inserted. */ + void insertedRows(SCROW nStartRow, SCROW nRowCount); + + /** Update stored sort ranges when rows are deleted. */ + void deletedRows(SCROW nStartRow, SCROW nRowCount); + + /** Update stored sort ranges when columns are inserted. */ + void insertedColumns(SCCOL nStartCol, SCCOL nColCount); + + /** Update stored sort ranges when columns are deleted. */ + void deletedColumns(SCCOL nStartCol, SCCOL nColCount); + + /** Last used sort parameters */ + ScSortParam const* getSortParam() const; + + /** Remember last used sort parameters when sheet view was sorted. */ + void setSortParam(ScSortParam const& rSortParam); + + /** Reset all sort data. */ + void resetSortData(); + + /** Capture current sort state (and deep copy). */ + std::shared_ptr captureSortData() const; + + /** Restore sort state from a previous capture. */ + void restoreSortData(std::shared_ptr const& pData); }; } diff --git a/sc/inc/SheetViewManager.hxx b/sc/inc/SheetViewManager.hxx index 205f08feb682..2b982df7b8f4 100644 --- a/sc/inc/SheetViewManager.hxx +++ b/sc/inc/SheetViewManager.hxx @@ -16,19 +16,33 @@ #include #include #include +#include class ScTable; namespace sc { +/** Captured sort data for a default view.*/ +struct SC_DLLPUBLIC DefaultViewSortData +{ + SortOrderReverser maSortOrder; + /// Per sheet view sort data - only populated in captured snapshots. + std::vector>> maSheetViewSortData; +}; + /** Manager and the holder of the sheet views for a sheet. */ class SC_DLLPUBLIC SheetViewManager { private: std::vector> maViews; + size_t mnSheetViewCount = 0; sal_Int32 maNameCounter = 0; - std::optional moSortOrder; + /** Sort data for a default view. Null when no sort. */ + std::shared_ptr mpSortData; + + /** Ensure sort data is allocated. */ + DefaultViewSortData& ensureSortData(); bool isValidSheetViewID(SheetViewID nID) const { @@ -37,6 +51,64 @@ private: OUString generateName(); + /** Forward iterator over valid (non-null) sheet views only. */ + class SheetViewIterator + { + private: + using VectorIterator = std::vector>::const_iterator; + VectorIterator maCurrentIt; + VectorIterator maEndIt; + + void skipEmpty() + { + while (maCurrentIt != maEndIt && !(*maCurrentIt)) + { + maCurrentIt++; + } + } + + public: + SheetViewIterator(VectorIterator aBegin, VectorIterator aEnd) + : maCurrentIt(aBegin) + , maEndIt(aEnd) + { + skipEmpty(); + } + + SheetView& operator*() const { return **maCurrentIt; } + + SheetViewIterator& operator++() + { + maCurrentIt++; + skipEmpty(); + return *this; + } + + bool operator==(SheetViewIterator const& rOther) const + { + return maCurrentIt == rOther.maCurrentIt; + } + }; + + /** Wrapper for SheetViewIterator so it is possible to use it with range-for loops. */ + class SheetViewRange + { + std::vector> const& mrViews; + + public: + SheetViewRange(std::vector> const& rViews) + : mrViews(rViews) + { + } + + SheetViewIterator begin() const + { + return SheetViewIterator(mrViews.begin(), mrViews.end()); + } + + SheetViewIterator end() const { return SheetViewIterator(mrViews.end(), mrViews.end()); } + }; + public: SheetViewManager(); @@ -47,29 +119,41 @@ public: std::shared_ptr get(SheetViewID nID) const; /** True if there are no sheet views. */ - bool isEmpty() const { return maViews.empty(); } + bool isEmpty() const { return mnSheetViewCount == 0; } + + /** Number of sheet views. */ + size_t size() const { return mnSheetViewCount; } /** Remove the sheet view with the ID. True if successful. */ bool remove(SheetViewID nID); - /** Remove all sheet views. */ - void removeAll(); - - /** Return the list of sheet views. */ - std::vector> const& getSheetViews() const { return maViews; } - - /** Calculate the next sheet view ID from the current ID. */ - SheetViewID getNextSheetView(SheetViewID nID); - - /** Calculate the previous sheet view ID from the current ID. */ - SheetViewID getPreviousSheetView(SheetViewID nID); - - void unsyncAllSheetViews(); + /** Returns a range that iterates only over valid (non-null) sheet views. */ + SheetViewRange iterateValidSheetViews() const { return SheetViewRange(maViews); } static OUString defaultViewName(); - std::optional const& getSortOrder() const { return moSortOrder; } - void addOrderIndices(std::vector const& rOrder, SCROW firstRow, SCROW lastRow); + SortOrderReverser const* getSortOrder() const; + void addOrderIndices(SortOrderInfo const& rSortInfo); + + void mergeReorderParameters(ReorderParam const& rReorderParameters); + + /** Update when rows are inserted. */ + void insertedRows(SCROW nStartRow, SCROW nRowCount); + + /** Update when rows are deleted. */ + void deletedRows(SCROW nStartRow, SCROW nRowCount); + + /** Update when columns are inserted. */ + void insertedColumns(SCCOL nStartCol, SCCOL nColCount); + + /** Update when columns are deleted. */ + void deletedColumns(SCCOL nStartCol, SCCOL nColCount); + + /** Capture sort data (deep copy).*/ + std::shared_ptr captureSortData() const; + + /** Restore sort data from a previous capture. */ + void restoreSortData(std::shared_ptr const& pData); }; } diff --git a/sc/inc/SolverSettings.hxx b/sc/inc/SolverSettings.hxx index 58edd20f30f2..da13f65addb2 100644 --- a/sc/inc/SolverSettings.hxx +++ b/sc/inc/SolverSettings.hxx @@ -38,7 +38,7 @@ enum SolverParameter SP_LO_ENGINE, // Engine name used in LO SP_MS_ENGINE, // Engine ID used in MSO SP_INTEGER, // Assume all variables are integer (0: no, 1: yes) - // LpSolve, CoinMP and SwarmSolver + // CoinMP and SwarmSolver SP_NON_NEGATIVE, // Assume non negativity (1: yes, 2: no) SP_EPSILON_LEVEL, // Epsilon level SP_LIMIT_BBDEPTH, // Branch and bound depth @@ -230,7 +230,6 @@ private: // Maps LO solver implementation names to MS engine codes std::map SolverNamesToExcelEngines = { { "com.sun.star.comp.Calc.CoinMPSolver", "2" }, // Simplex LP - { "com.sun.star.comp.Calc.LpsolveSolver", "2" }, // Simplex LP { "com.sun.star.comp.Calc.SwarmSolver", "1" }, // GRG Nonlinear { "com.sun.star.comp.Calc.NLPSolver.DEPSSolverImpl", "3" }, // DEPS { "com.sun.star.comp.Calc.NLPSolver.SCOSolverImpl", "3" } // SCO diff --git a/sc/inc/TableContentCopier.hxx b/sc/inc/TableContentCopier.hxx new file mode 100644 index 000000000000..7f6f324d7d6d --- /dev/null +++ b/sc/inc/TableContentCopier.hxx @@ -0,0 +1,44 @@ +/* -*- 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/. + */ + +#pragma once + +#include "address.hxx" +#include "global.hxx" + +class ScDocument; +class ScTable; +class ScMarkData; + +namespace sc +{ +struct RefUpdateInsertTabContext; + +/** Copies the content of one table (sheet) to another within the same document. */ +class TableContentCopier +{ + ScDocument& mrDoc; + const SCTAB mnSourceTabNo; + const SCTAB mnTargetTabNo; + ScTable* const mpSourceTab; + ScTable* const mpTargetTab; + +public: + TableContentCopier(ScDocument& rDoc, SCTAB nSourceTabNo, SCTAB nTargetTabNo); + + ~TableContentCopier(); + + void performCopy(const ScMarkData* pOnlyMarked, ScCloneFlags nCloneFlags, + SCTAB nPreviousSourceTabNo = -1); + void updateReferencesAfterTabInsertion(RefUpdateInsertTabContext& rContext); +}; + +} // namespace sc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/TableStyleGenerator.hxx b/sc/inc/TableStyleGenerator.hxx new file mode 100644 index 000000000000..bd5d2748e508 --- /dev/null +++ b/sc/inc/TableStyleGenerator.hxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "scdllapi.h" + +namespace model +{ +class ColorSet; +} +class ScDocument; + +/// Generates the 60 default OOXML table styles from the ECMA-376 spec data, +/// resolving theme-relative colors against the given ColorSet. +/// +/// The generation is split internally into discrete steps: resolveColors, +/// buildFills, buildBorders, buildFonts, buildDxfPatterns, and assembleTableStyles. +class SC_DLLPUBLIC ScTableStyleGenerator +{ +public: + static void generateDefaultStyles(ScDocument& rDoc, const model::ColorSet& rColorSet); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx index 3203579125b1..eb61946dc679 100644 --- a/sc/inc/address.hxx +++ b/sc/inc/address.hxx @@ -19,6 +19,7 @@ #pragma once +#include #include #include @@ -516,6 +517,11 @@ public: aStart.SetInvalid(); aEnd.SetInvalid(); } + void SetTab( SCTAB nTab ) + { + aStart.SetTab( nTab ); + aEnd.SetTab( nTab ); + } bool IsValid() const { return aStart.IsValid() && aEnd.IsValid(); @@ -723,46 +729,35 @@ inline bool ScRange::Intersects( const ScRange& rRange ) const inline size_t ScRange::hashArea() const { -#if SAL_TYPES_SIZEOFPOINTER == 8 - // 12 bits for the columns and 20 bits for the rows - return - (static_cast(aStart.Row()) << 44) ^ - (static_cast(aStart.Col()) << 32) ^ - (static_cast(aEnd.Col()) << 20) ^ - static_cast(aEnd.Row()); -#else - // Assume that there are not that many ranges with identical corners so we - // won't have too many collisions. Also assume that more lower row and - // column numbers are used so that there are not too many conflicts with - // the columns hashed into the values, and that start row and column - // usually don't exceed certain values. High bits are not masked off and - // may overlap with lower bits of other values, e.g. if start column is - // greater than assumed. - return - (static_cast(aStart.Row()) << 26) ^ // start row <= 2^6 - (static_cast(aStart.Col()) << 21) ^ // start column <= 2^5 - (static_cast(aEnd.Col()) << 15) ^ // end column <= 2^6 - static_cast(aEnd.Row()); // end row <= 2^15 -#endif + // Mix all four corners into the hash so each one affects its low-order bits, + // which are what determine the bucket index in a hash table. The previous + // shift+xor parked the start column/row in high bits, so ranges that share + // the same end corner but differ only in the start corner - e.g. a relative + // named range resolving to A1:X, A2:X, A3:X, ... or repeated large LOOKUP() + // areas - all hashed to a single bucket, turning unordered_set insert/find + // into O(n). tdf#164843 + size_t h = 0; + o3tl::hash_combine(h, aStart.Row()); + o3tl::hash_combine(h, aStart.Col()); + o3tl::hash_combine(h, aEnd.Col()); + o3tl::hash_combine(h, aEnd.Row()); + return h; } inline size_t ScRange::hashStartColumn() const { -#if SAL_TYPES_SIZEOFPOINTER == 8 - // 20 bits for the rows - return - (static_cast(aStart.Col()) << 40) ^ - (static_cast(aStart.Row()) << 20) ^ - static_cast(aEnd.Row()); -#else - // Assume that for the start row more lower row numbers are used so that - // there are not too many conflicts with the column hashed into the higher - // values. - return - (static_cast(aStart.Col()) << 24) ^ // start column <= 2^8 - (static_cast(aStart.Row()) << 16) ^ // start row <= 2^8 - static_cast(aEnd.Row()); -#endif + // As in hashArea(): mix the fields so each one affects the low-order bits + // that determine the bucket index. The previous shift+xor parked the start + // column/row in high bits, so ranges that share the same end row but differ + // only in the start corner hashed to a single bucket and made the lookup and + // range caches O(n) per probe. Keyed on the start column and the row span + // (end column intentionally omitted - lookups are on the first column). + // tdf#164843 + size_t h = 0; + o3tl::hash_combine(h, aStart.Col()); + o3tl::hash_combine(h, aStart.Row()); + o3tl::hash_combine(h, aEnd.Row()); + return h; } [[nodiscard]] inline bool ValidRange( const ScRange& rRange, SCCOL nMaxCol, SCROW nMaxRow ) @@ -950,4 +945,12 @@ inline OUString ScColToAlpha( SCCOL nCol ) /// get column number of A..IV... string bool AlphaToCol(const ScDocument& rDoc, SCCOL& rCol, std::u16string_view rStr); +inline std::ostream& operator<<(std::ostream& rStrm, const ScRange& rRange) +{ + rStrm << "ScRange(" << rRange.aStart.Col() << "," << rRange.aStart.Row() << "," + << rRange.aStart.Tab() << "," << rRange.aEnd.Col() << "," << rRange.aEnd.Row() << "," + << rRange.aEnd.Tab() << ")"; + return rStrm; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/callable.hxx b/sc/inc/callable.hxx new file mode 100644 index 000000000000..3089ea565cd2 --- /dev/null +++ b/sc/inc/callable.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 . + */ + +#pragma once + +#include + +#include +#include + +#include +#include +#include "tokenarray.hxx" +#include + +class ScDocument; +class ScAddress; +class ScFormulaCell; +struct ScInterpreterContext; +class ScDocShell; +class SbMethod; +class SbModule; + +/// a callable macro +class SAL_DLLPUBLIC_RTTI ScMacroFunction : public formula::FormulaCallable +{ +private: + FormulaError mnError; + ScDocShell* mpDocShell; + SbMethod* mpMethod; + SbModule* mpModule; + OUString maMacroStr; + OUString maBasicStr; + bool mbInvalid; + +public: + ScMacroFunction(const ScMacroFunction&) = default; + ScMacroFunction(const ScInterpreter& rInterpreter, const OUString& aMacro); + virtual OpCode GetOpCode() const override { return ocMacro; } + bool IsValid() const { return !mbInvalid; } + FormulaError GetError() const { return mnError; } + ScDocShell* GetDocumentShell() const { return mpDocShell; } + SbMethod* GetMethod() const { return mpMethod; } + SbModule* GetModule() const { return mpModule; } + const OUString& GetMacroStr() const { return maMacroStr; } + const OUString& GetBasicStr() const { return maBasicStr; } +}; + +/// a callable closure from a formula +class SAL_DLLPUBLIC_RTTI ScFormulaFunction : public formula::FormulaCallable +{ +private: + // ScInterpreter context data + ScDocument* mpDoc; + const ScAddress maPos; + ScFormulaCell* mpCell; + ScInterpreterContext* mpContext; + + // the body (code) of the lambda + ScTokenArray maLambdaBody; + // for each parameter, a list of positions where it appears in the body + std::vector> maReplacementPositions; + short mnRequiredParams; + +public: + ScFormulaFunction(const ScFormulaFunction&) = default; + ScFormulaFunction(const ScInterpreter& rInterpreter, const std::vector& rLambdaParams, + short nRequiredParams, const ScTokenArray& rLambdaBody, short nBodyStart, + short nBodyEnd); + + virtual OpCode GetOpCode() const override { return ocLambda; } + + ScDocument& GetDocument() const { return *mpDoc; } + ScAddress GetAddress() const { return maPos; } + ScFormulaCell* GetFormulaCell() const { return mpCell; } + ScInterpreterContext& GetContext() const { return *mpContext; } + const ScTokenArray& GetLambdaBody() const { return maLambdaBody; } + sal_Int32 GetNumParams() const { return maReplacementPositions.size(); } + const std::forward_list& GetReplacementPositions(sal_Int32 nParam) const + { + return maReplacementPositions[nParam]; + } + short GetNumRequiredParams() const { return mnRequiredParams; } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx index b618efa31a4d..fbd4a7b07ceb 100644 --- a/sc/inc/cellvalue.hxx +++ b/sc/inc/cellvalue.hxx @@ -51,7 +51,8 @@ public: SC_DLLPUBLIC void set( double fValue ); SC_DLLPUBLIC void set( const svl::SharedString& rStr ); - void set( const EditTextObject& rEditText ); + SC_DLLPUBLIC void set( const EditTextObject& rEditText ); + SC_DLLPUBLIC void set( EditTextObject&& rEditText ); SC_DLLPUBLIC void set( std::unique_ptr ); SC_DLLPUBLIC void set( ScFormulaCell* pFormula ); diff --git a/sc/inc/chart2uno.hxx b/sc/inc/chart2uno.hxx index 24cc0c3d0f8e..131ef0fb0618 100644 --- a/sc/inc/chart2uno.hxx +++ b/sc/inc/chart2uno.hxx @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -48,6 +49,8 @@ #include #include +using oox::drawingml::chart::DataSourceType; + namespace com::sun::star::chart2::data { class XLabeledDataSequence; } class ScDocument; @@ -366,6 +369,9 @@ private: // properties css::chart2::data::DataSequenceRole m_aRole; bool m_bIncludeHiddenCells; + DataSourceType m_eDimType; + OUString m_sFormula; // from + OUString m_sNFormula; // from // internals sal_Int64 m_nObjectId; diff --git a/sc/inc/chartuno.hxx b/sc/inc/chartuno.hxx index b09ba9243c24..47351dd66c94 100644 --- a/sc/inc/chartuno.hxx +++ b/sc/inc/chartuno.hxx @@ -22,8 +22,6 @@ #include "rangelst.hxx" #include #include -#include -#include #include #include @@ -32,7 +30,8 @@ #include #include #include -#include + +#include #include class ScDocShell; @@ -88,20 +87,16 @@ public: virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; }; -typedef ::comphelper::WeakComponentImplHelper< - css::table::XTableChart, - css::document::XEmbeddedObjectSupplier, - css::container::XNamed, - css::lang::XServiceInfo > ScChartObj_Base; - -typedef ::comphelper::OPropertyContainer2 ScChartObj_PBase; -typedef ::comphelper::OPropertyArrayUsageHelper< ScChartObj > ScChartObj_PABase; - -class ScChartObj final : - public ScChartObj_Base - ,public ScChartObj_PBase - ,public ScChartObj_PABase - ,public SfxListener +using ScChartObj_Base = comphelper::OPropertyContainerImplHelper< + comphelper::WeakComponentImplHelper< + css::table::XTableChart, + css::document::XEmbeddedObjectSupplier, + css::container::XNamed, + css::lang::XServiceInfo>, + class ScChartObj>; +class ScChartObj final + : public ScChartObj_Base, + public SfxListener { private: ScDocShell* pDocShell; @@ -111,14 +106,11 @@ private: void Update_Impl( const ScRangeListRef& rRanges, bool bColHeaders, bool bRowHeaders ); void GetData_Impl( ScRangeListRef& rRanges, bool& rColHeaders, bool& rRowHeaders ) const; - // ::comphelper::OPropertySetHelper - virtual ::cppu::IPropertyArrayHelper& getInfoHelper() override; - virtual void setFastPropertyValue_NoBroadcast( std::unique_lock& rGuard, sal_Int32 nHandle, const css::uno::Any& rValue ) override; - using ::comphelper::OPropertySetHelper::getFastPropertyValue; - virtual void getFastPropertyValue( std::unique_lock& rGuard, css::uno::Any& rValue, sal_Int32 nHandle ) const override; - - // ::comphelper::OPropertyArrayUsageHelper + // ::comphelper::OPropertyImplHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override; + virtual void setFastPropertyValue_NoBroadcast( std::unique_lock& rGuard, sal_Int32 nHandle, const css::uno::Any& rValue ) override; + using ScChartObj_Base::getFastPropertyValue; + virtual void getFastPropertyValue( std::unique_lock& rGuard, css::uno::Any& rValue, sal_Int32 nHandle ) const override; public: ScChartObj(ScDocShell* pDocSh, SCTAB nT, OUString aN); @@ -126,15 +118,6 @@ public: virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; - // XInterface - DECLARE_XINTERFACE() - - // XTypeProvider - DECLARE_XTYPEPROVIDER() - - // XComponent - using ScChartObj_Base::disposing; - // XTableChart virtual sal_Bool SAL_CALL getHasColumnHeaders() override; virtual void SAL_CALL setHasColumnHeaders( sal_Bool bHasColumnHeaders ) override; @@ -156,9 +139,6 @@ public: virtual OUString SAL_CALL getImplementationName() override; virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; - - // XPropertySet - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/chgtrack.hxx b/sc/inc/chgtrack.hxx index 259d79b786e1..ae51f67e7ef6 100644 --- a/sc/inc/chgtrack.hxx +++ b/sc/inc/chgtrack.hxx @@ -1115,7 +1115,8 @@ public: sal_uLong AddLoadedGenerated( const ScCellValue& rNewCell, const ScBigRange& aBigRange, const OUString& sNewValue ); // only to use in the XML import - void AppendLoaded( std::unique_ptr pAppend ); // this is only for the XML import public, it should be protected + // returns false if the action number is already in use, in which case the new duplicate is dropped + bool AppendLoaded( std::unique_ptr pAppend ); // this is only for the XML import public, it should be protected void SetActionMax(sal_uLong nTempActionMax) { nActionMax = nTempActionMax; } // only to use in the XML import diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 2dbe56c08006..5ffa042b0a71 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -138,6 +138,7 @@ public: void SetAttrEntries(std::vector && vNewData); const ScPatternAttr* GetPattern( SCROW nRow ) const; + const ScPatternAttr* GetPatternRange( SCROW& rStartRow, SCROW& rEndRow, SCROW nRow ) const; const ScPatternAttr* GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const; void ApplySelectionStyle(const ScStyleSheet& rStyle, SCROW nTop, SCROW nBottom); void ApplySelectionCache(ScItemPoolCache& rCache, SCROW nStartRow, SCROW nEndRow, @@ -367,7 +368,7 @@ public: void CopyToColumn( sc::CopyToDocContext& rCxt, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, ScColumn& rColumn, const ScMarkData* pMarkData = nullptr, bool bAsLink = false, - bool bGlobalNamesToLocal = false ) const; + ScCloneFlags nCloneFlags = ScCloneFlags::Default ) const; void UndoToColumn( sc::CopyToDocContext& rCxt, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, @@ -389,9 +390,11 @@ public: SCROW nRow, SCTAB nTab, const OUString& rString, formula::FormulaGrammar::AddressConvention eConv, const ScSetStringParam* pParam = nullptr ); - void SetEditText( SCROW nRow, std::unique_ptr pEditText ); + void SetEditText( SCROW nRow, std::unique_ptr aEditText ); + void SetEditText( SCROW nRow, EditTextObject aEditText ); void SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, std::unique_ptr pEditText ); void SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, const EditTextObject& rEditText ); + void SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, EditTextObject&& rEditText ); void SetEditText( SCROW nRow, const EditTextObject& rEditText, const SfxItemPool* pEditPool ); void SetFormula( SCROW nRow, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram ); void SetFormula( SCROW nRow, const OUString& rFormula, formula::FormulaGrammar::Grammar eGram ); @@ -597,6 +600,7 @@ public: bool GetDataEntries( SCROW nRow, std::set& rStrings) const; void UpdateInsertTabAbs(SCTAB nNewPos); + void AdjustRelativeTabRefs(SCTAB nOldTab, SCTAB nNewTab, sc::TargetTabState eMode); bool TestTabRefAbs(SCTAB nTable) const; bool GetNextSpellingCell(SCROW& nRow, bool bInSel, const ScMarkData& rData) const; @@ -611,8 +615,6 @@ public: void EndListening( SvtListener& rLst, SCROW nRow ); void StartListening( sc::StartListeningContext& rCxt, const ScAddress& rAddress, SvtListener& rListener ); void EndListening( sc::EndListeningContext& rCxt, const ScAddress& rAddress, SvtListener& rListener ); - void StartListeningSingleRefFormulaCells( sc::StartListeningContext& rCxt, const ScSingleRefData* pRef, - const ScAddress& rAddress, ScFormulaCell** pp, ScFormulaCell** ppEnd ); void StartListeners( sc::StartListeningContext& rCxt, bool bAll ); void SetDirtyIfPostponed(); void BroadcastRecalcOnRefMove(); @@ -669,7 +671,7 @@ public: void BroadcastCells( const std::vector& rRows, SfxHintId nHint ); void BroadcastRows( SCROW nStartRow, SCROW nEndRow, SfxHintId nHint ); - // Spaklines + // Sparklines sc::SparklineCell* GetSparklineCell(SCROW nRow); void CreateSparklineCell(SCROW nRow, std::shared_ptr const& pSparkline); void DeleteSparklineCells(sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2); @@ -966,6 +968,11 @@ inline const ScPatternAttr* ScColumnData::GetPattern( SCROW nRow ) const return pAttrArray->GetPattern( nRow ); } +inline const ScPatternAttr* ScColumnData::GetPatternRange( SCROW& rStartRow, SCROW& rEndRow, SCROW nRow ) const +{ + return pAttrArray->GetPatternRange( rStartRow, rEndRow, nRow ); +} + inline const SfxPoolItem& ScColumnData::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const { return pAttrArray->GetPattern( nRow )->GetItem(nWhich); @@ -1028,7 +1035,7 @@ inline void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt inline void ScColumn::SetPattern( SCROW nRow, const CellAttributeHolder& rHolder ) { - return pAttrArray->SetPattern( nRow, rHolder ); + pAttrArray->SetPattern( nRow, rHolder ); } inline void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPattern ) diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index e0d5b56ee959..414628683db7 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -138,7 +138,7 @@ public: } sharedstring; ScMatrix* pMat; FormulaError nError; - short nJump[ FORMULA_MAXPARAMS + 1 ]; // If/Choose/Let token + short nJump[ FORMULA_MAXPARAMS + 1 ]; // If/Choose/Let/Lambda token }; OUString maExternalName; // depending on the opcode, this is either the external, or the external name, or the external table name @@ -167,7 +167,7 @@ public: void SetExternalSingleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef ); void SetExternalDoubleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef ); void SetExternalName( sal_uInt16 nFileId, const OUString& rName ); - void SetExternal(const OUString& rStr); + void SetExternal(const OUString& rStr, OpCode eCode = ocExternal); /** If the token is a non-external reference, determine if the reference is valid. If the token is an external reference, return true. Else return @@ -301,6 +301,8 @@ private: bool mbRewind; // whether symbol is to be rewound to some step during lexical analysis bool mbRefConventionChartOOXML; // whether to use special ooxml chart syntax in case of OOXML reference convention, // when parsing a formula string. [0]!GlobalNamedRange, LocalSheet!LocalNamedRange + bool mbOptionalLocalName = false; // true when the local name just resolved was a LAMBDA optional + // parameter, written with the _xlop. prefix instead of _xlpm. std::vector maExternalFiles; std::vector maTabNames; /// sheet names mangled for the current grammar for output @@ -351,10 +353,10 @@ private: std::vector NextSymbol(bool bInArray); - bool ParseValue( const OUString& ); + bool ParseValue( const OUString&, bool bInArray = false ); bool ParseOpCode( const OUString&, bool bInArray ); bool ParseOpCode2( std::u16string_view ); - bool ParseString(); + bool ParseLiteralString(); bool ParseReference( const OUString& rSymbol, const OUString* pErrRef = nullptr ); bool ParseSingleReference( const OUString& rSymbol, const OUString* pErrRef = nullptr ); bool ParseDoubleReference( const OUString& rSymbol, const OUString* pErrRef = nullptr ); @@ -362,12 +364,11 @@ private: bool ParsePredetectedErrRefReference( const OUString& rName, const OUString* pErrRef ); bool ParseMacro( const OUString& ); bool ParseNamedRange( const OUString&, bool onlyCheck = false ); - bool ParseLambdaFuncName( const OUString& ); + bool ParseLocalName( const OUString& ); bool ParseExternalNamedRange( const OUString& rSymbol, bool& rbInvalidExternalNameRange ); bool ParseDBRange( const OUString& ); bool ParseDPFieldName( const OUString& ); bool ParseColRowName( const OUString& ); - bool ParseBoolean( const OUString& ); void AutoCorrectParsedSymbol(); const ScRangeData* GetRangeData( SCTAB& rSheet, const OUString& rUpperName ) const; @@ -375,11 +376,8 @@ private: void SetRelNameReference(); /** Obtain range data for ocName token, global or sheet local. - - Prerequisite: rToken is a FormulaIndexToken so IsGlobal() and - GetIndex() can be called on it. We don't check with RTTI. */ - ScRangeData* GetRangeData( const formula::FormulaToken& pToken ) const; + ScRangeData* GetRangeData( const formula::FormulaIndexToken& pToken ) const; bool HasPossibleNamedRangeConflict(SCTAB nTab) const; @@ -497,8 +495,8 @@ public: void SetExtendedErrorDetection( ExtendedErrorDetection eVal ) { meExtendedErrorDetection = eVal; } - bool IsCorrected() const { return bCorrected; } - const OUString& GetCorrectedFormula() const { return aCorrectedFormula; } + bool IsCorrected() const { return mbCorrected; } + const OUString& GetCorrectedFormula() const { return maCorrectedFormula; } /** * Tokenize formula expression string into an array of tokens. diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx index 35252a185067..f38b81cc999e 100644 --- a/sc/inc/conditio.hxx +++ b/sc/inc/conditio.hxx @@ -34,8 +34,6 @@ #include #include #include -#include -#include #include #include @@ -303,7 +301,7 @@ public: } }; -class SAL_DLLPUBLIC_RTTI ScConditionEntry : public ScFormatEntry, public CacheOwner +class SAL_DLLPUBLIC_RTTI ScConditionEntry : public ScFormatEntry { // stored data: ScConditionMode eOp; @@ -325,9 +323,6 @@ class SAL_DLLPUBLIC_RTTI ScConditionEntry : public ScFormatEntry, public CacheOw OUString aSrcString; // formula source position as text during XML import std::unique_ptr pFCell1; std::unique_ptr pFCell2; - typedef o3tl::lru_map> RelRefCells; - std::unique_ptr xRelRefCells1; - std::unique_ptr xRelRefCells2; bool bRelRef1; bool bRelRef2; bool bFirstRun; @@ -351,8 +346,6 @@ class SAL_DLLPUBLIC_RTTI ScConditionEntry : public ScFormatEntry, public CacheOw bool IsValidStr( const OUString& rArg, const ScAddress& rPos ) const; void StartListening(); - static std::unique_ptr makeRelRefCells(); - public: ScConditionEntry( ScConditionMode eOper, const OUString& rExpr1, const OUString& rExpr2, @@ -408,10 +401,6 @@ public: virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) override; virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ) override; - virtual bool dropCaches() override; - virtual void dumpState(rtl::OStringBuffer& rState) override; - virtual OUString getCacheName() const override; - bool MarkUsedExternalReferences() const; virtual Type GetType() const override { return eConditionType; } diff --git a/sc/inc/datamapper.hxx b/sc/inc/datamapper.hxx index 984e6cc81219..c1c273325d7c 100644 --- a/sc/inc/datamapper.hxx +++ b/sc/inc/datamapper.hxx @@ -72,8 +72,6 @@ private: public: ExternalDataSource(OUString aURL, OUString aProvider, ScDocument* pDoc); - void setUpdateFrequency(double nUpdateFrequency); - void setID(const OUString& rID); void setURL(const OUString& rURL); void setProvider(const OUString& rProvider); @@ -96,7 +94,7 @@ public: class SC_DLLPUBLIC ExternalDataMapper { - //ScDocument& mrDoc; + ScDocument& mrDoc; std::vector maDataSources; public: diff --git a/sc/inc/dbdata.hxx b/sc/inc/dbdata.hxx index aefa68a7c8e1..e8247f0907d8 100644 --- a/sc/inc/dbdata.hxx +++ b/sc/inc/dbdata.hxx @@ -89,6 +89,11 @@ struct TableColumnAttributes std::optional maTotalsRowLabel = std::nullopt; std::optional maTotalsFunction = std::nullopt; std::optional maCustomFunction = std::nullopt; + // Whether the totals row cell for this column holds any value at all, whether or + // not that value ended up producing a label or a function above. A column whose + // totals row cell is empty is not the same as a column whose cell holds content + // that this class chose not to describe as a label or a function. + bool mbHasContent = false; }; // xmlColumnPr attributes @@ -212,6 +217,11 @@ public: void GetArea(SCTAB& rTab, SCCOL& rCol1, SCROW& rRow1, SCCOL& rCol2, SCROW& rRow2) const; SC_DLLPUBLIC void GetArea(ScRange& rRange) const; void SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); + void SetArea(ScRange const& rRange) + { + SetArea(rRange.aStart.Tab(), rRange.aStart.Col(), rRange.aStart.Row(), + rRange.aEnd.Col(), rRange.aEnd.Row()); + } void MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCCOL nUpdateCol = -1); void SetByRow(bool bByR) { bByRow = bByR; } @@ -231,7 +241,7 @@ public: const OUString& GetTableType() const { return aTableType; } void SetContainer( ScDBDataContainerBase* pContainer ) { mpContainer = pContainer; } - /** Returns header row range if has headers, else invalid range. */ + /** Returns header row range if it has headers, else invalid range. */ ScRange GetHeaderArea() const; void StartTableColumnNamesListener(); void EndTableColumnNamesListener(); @@ -249,7 +259,7 @@ public: /** Refresh/update the column names with the header row's cell contents within the given range. */ - void RefreshTableColumnNames( ScDocument& rDoc, const ScRange& rRange ); + void RefreshTableColumnNames( ScDocument& rDoc, const ScRangeList& rRangeList ); /** Finds the column named rName and returns the corresponding offset within the table. @@ -260,8 +270,8 @@ public: */ sal_Int32 GetColumnNameOffset( const OUString& rName ) const; - /** Returns table column name if nCol is within column range and name - is stored, else empty string. */ + /** Returns table column name if nCol is within column range and the name + is stored, else an empty string. */ const OUString & GetTableColumnName( SCCOL nCol ) const; OUString GetSourceString() const; @@ -319,13 +329,11 @@ public: SCCOL nDx, SCROW nDy, SCTAB nDz); void ExtendDataArea(const ScDocument& rDoc); - void ExtendBackColorArea(const ScDocument& rDoc); void CalcSaveFilteredCount(SCSIZE nNonFilteredRowCount); void GetFilterSelCount(SCSIZE& nSelected, SCSIZE& nTotal); SC_DLLPUBLIC void SetTableStyleInfo(const ScTableStyleParam& rParams); SC_DLLPUBLIC const ScTableStyleParam* GetTableStyleInfo() const; - void RemoveTableStyleInfo(); static ScSubTotalFunc GetSubTotalFuncFromString(std::u16string_view sFunction); static OUString GetStringFromSubTotalFunc(ScSubTotalFunc eFunc); diff --git a/sc/source/filter/inc/defaulttablestyles.hxx b/sc/inc/defaulttablestyledata.hxx similarity index 57% rename from sc/source/filter/inc/defaulttablestyles.hxx rename to sc/inc/defaulttablestyledata.hxx index 2cd524f30249..2c12fb9a95c6 100644 --- a/sc/source/filter/inc/defaulttablestyles.hxx +++ b/sc/inc/defaulttablestyledata.hxx @@ -7,10 +7,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include -#include "stylesbuffer.hxx" +#pragma once -// structs used by the script generated code from the original OOXML spec +#include "tablestyle.hxx" + +// POD structs used by the script-generated constexpr data in defaulttablestyles.inc +// (generated from the ECMA-376 presetTableStyles.xml by generate_ooxml_tablestyle_info.py) struct ThemeColor { @@ -27,7 +29,6 @@ struct Font struct Fill { int nFgColorId; - int nBgColorId; }; enum class BorderElementStyle @@ -67,37 +68,20 @@ struct TableStyleElement int nDxfId; }; +enum class TableStyleCategory +{ + Light, + Medium, + Dark +}; + struct TableStyle { const char* pName; + TableStyleCategory eCategory; + int nNumber; size_t nElements; int pTableStyleElementIds[9]; }; -// the actual import class - -class DefaultOOXMLTableStyles : public oox::xls::WorkbookHelper -{ -private: - std::vector maColors; - oox::xls::FillVector maFills; - oox::xls::BorderVector maBorders; - oox::xls::FontVector maFonts; - - oox::xls::DxfVector maDxfs; - - void importColors(); - void importFills(); - void importBorderElement(oox::xls::BorderRef xBorder, sal_Int32 nBorderElement, - sal_Int32 nBorderElementId); - void importBorders(); - void importFonts(); - void importDxfs(); - void importTableStyle(const TableStyle& rTableStyleInfo); - -public: - DefaultOOXMLTableStyles(const oox::xls::WorkbookHelper& rHelper); - void importTableStyles(); -}; - /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/inc/dispuno.hxx b/sc/inc/dispuno.hxx index 54b809c4e581..d0fa87f5da9f 100644 --- a/sc/inc/dispuno.hxx +++ b/sc/inc/dispuno.hxx @@ -36,7 +36,7 @@ class ScDispatchProviderInterceptor final : public cppu::WeakImplHelper< { ScTabViewShell* pViewShell; - /// the component which's dispatches we're intercepting + /// the component whose dispatches we're intercepting css::uno::Reference< css::frame::XDispatchProviderInterception> m_xIntercepted; /// chaining diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx index 0737bed223ec..711fd2d42e65 100644 --- a/sc/inc/dociter.hxx +++ b/sc/inc/dociter.hxx @@ -24,6 +24,7 @@ #include "global.hxx" #include "scdllapi.h" #include "cellvalue.hxx" +#include "patattr.hxx" #include "mtvelements.hxx" #include "queryparam.hxx" #include "attarray.hxx" @@ -280,7 +281,7 @@ public: const ScPatternAttr* GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow1, SCROW& rRow2 ); }; -class ScHorizontalCellIterator // walk through all non empty cells in an area +class ScHorizontalCellIterator // walk through all non-empty cells in an area { // row by row struct ColParam { @@ -391,12 +392,12 @@ private: SCCOL nAttrCol1; SCCOL nAttrCol2; SCROW nAttrRow; - const ScPatternAttr* pPattern; + CellAttributeHolder maPattern; SCCOL nFoundStartCol; // results after GetNext SCCOL nFoundEndCol; SCROW nFoundRow; - const ScPatternAttr* pFoundPattern; + CellAttributeHolder maFoundPattern; ScRefCellValue maFoundCell; @@ -410,7 +411,7 @@ public: SCCOL GetStartCol() const { return nFoundStartCol; } SCCOL GetEndCol() const { return nFoundEndCol; } SCROW GetRow() const { return nFoundRow; } - const ScPatternAttr* GetPattern() const { return pFoundPattern; } + const ScPatternAttr* GetPattern() const { return maFoundPattern.getScPatternAttr(); } const ScRefCellValue& GetCell() const { return maFoundCell;} }; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 218b85ee88ec..7689fe40a990 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -53,6 +53,7 @@ #include #include #include +#include #include #include "markdata.hxx" @@ -68,10 +69,12 @@ namespace oox namespace xls { class Connection; + struct QueryTableModel; } } typedef oox::RefVector ConnectionVector; +typedef std::vector> QueryTableModelVector; class Timer; @@ -89,8 +92,8 @@ class SharedStringPool; namespace tools { class Guid; } -namespace sc { - +namespace sc +{ struct BroadcasterState; struct FormulaGroupContext; class StartListeningContext; @@ -114,7 +117,13 @@ class ExternalDataMapper; class Sparkline; class SparklineGroup; class SparklineList; +class SheetView; class SheetViewManager; +class AutoCalcSwitch; +struct RefUpdateDeleteTabContext; +struct RefUpdateMoveTabContext; +struct RefUpdateInsertTabContext; +struct RefErrorContext; } class OutputDevice; @@ -201,6 +210,7 @@ class ScEditDataArray; class EditTextObject; struct ScRefCellValue; class ScPostIt; +struct ScPersonData; struct ScSubTotalParam; struct ScQueryParam; class ScHint; @@ -219,6 +229,8 @@ namespace sc { typedef std::map IconSetBitmapMap; +class TableContentCopier; + } namespace com::sun::star { @@ -262,15 +274,15 @@ enum ScDocumentMode enum CommentCaptionState { - ALLSHOWN, // All comments captions are shown - ALLHIDDEN, // All comments captions are hidden - MIXED // There are comments in shown and hidden. + ALLSHOWN, // All comment captions are shown + ALLHIDDEN, // All comment captions are hidden + MIXED // There are comments in shown and hidden states. }; enum RangeNameScope { GLOBAL, // A range name can be defined - SHEET // with two scope on Manage Names dialog. + SHEET // with two scopes on Manage Names dialog. }; /// Represents the type of sheet geometry data. @@ -351,10 +363,10 @@ friend class ScColumn; friend struct ScRefCellValue; friend class ScDocumentImport; friend class sc::EditTextIterator; +friend class sc::TableContentCopier; friend struct ScMutationGuard; friend struct ScMutationDisable; - public: enum class HardRecalcState { @@ -381,6 +393,21 @@ public: return maConnectionVector; } + void setSheetQueryTables(SCTAB nTab, QueryTableModelVector aIn) + { + maSheetQueryTables[nTab] = std::move(aIn); + } + const QueryTableModelVector* getSheetQueryTables(SCTAB nTab) const + { + auto it = maSheetQueryTables.find(nTab); + return it == maSheetQueryTables.end() ? nullptr : &it->second; + } + bool hasAnyQueryTables() const { return !maSheetQueryTables.empty(); } + + void UpdateQueryTables(const sc::RefUpdateInsertTabContext& rCxt); + void UpdateQueryTables(const sc::RefUpdateDeleteTabContext& rCxt); + void UpdateQueryTables(const sc::RefUpdateMoveTabContext& rCxt); + private: rtl::Reference mxPoolHelper; @@ -457,6 +484,7 @@ private: std::unique_ptr pConditionalFormatDialogMode; std::unique_ptr pAutoNameCache; // for automatic name lookup during CompileXML + std::vector maPersonList; // persons for threaded comments std::unique_ptr pPreviewFont; // convert to std::unique_ptr or whatever ScStyleSheet* pPreviewCellStyle; @@ -477,6 +505,8 @@ private: ScGoalSeekSettings maGoalSeekSettings; ConnectionVector maConnectionVector; + std::map maSheetQueryTables; + public: /// list of ScInterpreterTableOpParams currently in use std::vector m_TableOpList; @@ -497,6 +527,7 @@ private: sal_uInt64 nXMLImportedFormulaCount; // progress count during XML import sal_uInt16 nInterpretLevel; // >0 if in interpreter sal_uInt16 nMacroInterpretLevel; // >0 if macro in interpreter + sal_uInt16 nCallableInterpretLevel = 0; // depth of nested callable (LAMBDA) evaluation sal_uInt16 nInterpreterTableOpLevel; // >0 if in interpreter TableOp ScDocumentThreadSpecific maNonThreaded; @@ -592,6 +623,24 @@ private: std::set maSubTotalCells; + // Addresses of array formula origins currently in #SPILL! state. + // Used to efficiently re-check those formulas after cell content changes. + std::unordered_set maSpilledFormulaCells; + + // Origins of dynamic array formulas that have auto expanded past 1x1. + // A blocker placed inside one of these matrix ranges via undo/redo or + // any other path that bypasses ResolveSpilledOutputs must re-collapse + // the matrix. The additional fix-up pass walks this set looking for + // foreign data sitting in the declared range. + std::unordered_set maExpandedDynamicArrays; + + // Origins of matrix formulas queued for a deferred resize (expand, + // contract, or collapse-on-#SPILL!). + std::unordered_set maPendingMatrixResizes; + + // Non-zero while a caller is iterating the cell store in a way that + // cannot tolerate insertions/removals; guards ProcessPendingMatrixResizes. + int mnMatrixResizeGuard = 0; bool mbEmbedFonts : 1; bool mbEmbedUsedFontsOnly : 1; @@ -660,6 +709,7 @@ public: SC_DLLPUBLIC sal_uInt64 GetFormulaGroupCount() const; // all cells sal_uInt64 GetCodeCount() const; // RPN-Code in formulas DECL_LINK( GetUserDefinedColor, sal_uInt16, Color* ); + DECL_LINK( GetUserDefinedColorIndex, const Color&, sal_Int32 ); public: SC_DLLPUBLIC ScDocument( ScDocumentMode eMode = SCDOCMODE_DOCUMENT, @@ -734,7 +784,7 @@ public: SC_DLLPUBLIC void SetAllRangeNames(const std::map& rRangeMap); SC_DLLPUBLIC void GetRangeNameMap(std::map& rRangeName); SC_DLLPUBLIC ScRangeName* GetRangeName(SCTAB nTab) const; - SC_DLLPUBLIC ScRangeName* GetRangeName() const; + SC_DLLPUBLIC ScRangeName& GetRangeName() const; void SetRangeName(SCTAB nTab, std::unique_ptr pNew); void SetRangeName( std::unique_ptr pNewRangeName ); bool IsAddressInRangeName( RangeNameScope eScope, const ScAddress& rAddress); @@ -906,10 +956,60 @@ public: SCROW nRow2, SCTAB nTab) const; void RefreshDirtyTableColumnNames(); SC_DLLPUBLIC sc::ExternalDataMapper& GetExternalDataMapper(); + /** True when the document holds at least one external data mapping. Checks + without creating the mapper, so it stays cheap for documents that have + none. */ + SC_DLLPUBLIC bool HasDataProviderMappings() const; + + /** True when the document holds anything that fetches content from outside + the document and so needs the user to agree before it updates. */ + SC_DLLPUBLIC bool HasExternalLinks() const; SC_DLLPUBLIC const ScRangeData* GetRangeAtBlock( const ScRange& rBlock, OUString& rName, bool* pSheetLocal = nullptr ) const; + // Spilled array formula tracking. + void MarkFormulaSpilled(const ScAddress& rPos) { maSpilledFormulaCells.insert(rPos); } + void UnmarkFormulaSpilled(const ScAddress& rPos) { maSpilledFormulaCells.erase(rPos); } + bool IsFormulaSpilled(const ScAddress& rPos) const + { + return maSpilledFormulaCells.contains(rPos); + } + const std::unordered_set& GetSpilledFormulaCells() const { return maSpilledFormulaCells; } + + // Expanded dynamic array tracking. + void MarkExpandedDynamicArray(const ScAddress& rPosition) + { + maExpandedDynamicArrays.insert(rPosition); + } + void UnmarkExpandedDynamicArray(const ScAddress& rPosition) + { + maExpandedDynamicArrays.erase(rPosition); + } + const std::unordered_set& GetExpandedDynamicArrays() const + { + return maExpandedDynamicArrays; + } + /// Collect every tracked expanded matrix master position that falls + /// inside rRange on any selected tab. + SC_DLLPUBLIC std::vector CollectExpandedDynamicArraysInRange( + const ScMarkData& rMark, const ScRange& rRange) const; + + /// Returns true if any non-origin cell in rRange holds data that isn't + /// one of its reference cells. + SC_DLLPUBLIC bool HasMatrixBlocker(const ScRange& rRange) const; + + // Pending matrix resize tracking (expand, contract, or collapse-on-spill). + void MarkPendingMatrixResize(const ScAddress& rPos) { maPendingMatrixResizes.insert(rPos); } + bool HasPendingMatrixResizes() const { return !maPendingMatrixResizes.empty(); } + void ProcessPendingMatrixResizes(); + + // Guards ProcessPendingMatrixResizes from mutating the cell store during + // an active iteration. Use sc::MatrixResizeGuard at the iteration scope. + void PushMatrixResizeGuard() { ++mnMatrixResizeGuard; } + void PopMatrixResizeGuard() { --mnMatrixResizeGuard; } + bool IsMatrixResizeGuarded() const { return mnMatrixResizeGuard > 0; } + SC_DLLPUBLIC bool HasPivotTable() const; SC_DLLPUBLIC ScDPCollection* GetDPCollection(); SC_DLLPUBLIC const ScDPCollection* GetDPCollection() const; @@ -968,7 +1068,6 @@ public: SC_DLLPUBLIC SCROW MaxRow() const { return mxSheetLimits->mnMaxRow; } SC_DLLPUBLIC SCCOL GetMaxColCount() const { return mxSheetLimits->GetMaxColCount(); } SC_DLLPUBLIC SCROW GetMaxRowCount() const { return mxSheetLimits->GetMaxRowCount(); } - SC_DLLPUBLIC const OUString & MaxRowAsString() const { return mxSheetLimits->MaxRowAsString(); } SC_DLLPUBLIC const OUString & MaxColAsString() const { return mxSheetLimits->MaxColAsString(); } ScSheetLimits& GetSheetLimits() const { return *mxSheetLimits; } [[nodiscard]] bool ValidCol(SCCOL nCol) const { return ::ValidCol(nCol, mxSheetLimits->mnMaxCol); } @@ -1053,8 +1152,10 @@ public: SC_DLLPUBLIC bool RenameTab( SCTAB nTab, const OUString& rName, bool bExternalDocument = false ); bool MoveTab( SCTAB nOldPos, SCTAB nNewPos, ScProgress* pProgress = nullptr ); - SC_DLLPUBLIC bool CopyTab( SCTAB nOldPos, SCTAB nNewPos, - const ScMarkData* pOnlyMarked = nullptr ); + SC_DLLPUBLIC bool CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyMarked = nullptr ); + + bool OverwriteContent(SCTAB nSourceTabNo, SCTAB nTargetTabNo); + SC_DLLPUBLIC bool TransferTab(ScDocument& rSrcDoc, SCTAB nSrcPos, SCTAB nDestPos, bool bInsertNew = true, bool bResultsOnly = false ); @@ -1112,7 +1213,6 @@ public: on first call. */ ScFormulaParserPool& GetFormulaParserPool() const; - bool HasAreaLinks() const; void UpdateExternalRefLinks(weld::Window* pWin); void UpdateAreaLinks(); @@ -1228,6 +1328,7 @@ public: * This is very important.

                                  */ SC_DLLPUBLIC bool SetEditText( const ScAddress& rPos, std::unique_ptr pEditText ); + SC_DLLPUBLIC bool SetEditText( const ScAddress& rPos, EditTextObject aEditText ); void SetEditText( const ScAddress& rPos, const EditTextObject& rEditText, const SfxItemPool* pEditPool ); SC_DLLPUBLIC void SetEditText( const ScAddress& rPos, const OUString& rStr ); SC_DLLPUBLIC SCROW GetFirstEditTextRow( const ScRange& rRange ) const; @@ -1268,7 +1369,19 @@ public: const ScMarkData& rMark, const OUString& rFormula, const ScTokenArray* p = nullptr, - const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ); + const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT, + bool bDynamicArrayMaster = false); + /** Returns true if any cell inside input range (rRange) other than the cells + already covered by the declared nDeclCols x nDeclRows sub-range holds any + data. */ + SC_DLLPUBLIC bool IsMatrixSpillBlocked(const ScRange& rRange, + SCCOL nDeclCols = 1, + SCROW nDeclRows = 1) const; + /** Resize an existing matrix formula at input position to the given dimensions. + Updates the matrix cell token, creates reference cells in newly covered + positions, and clears cells that fall outside the new range. */ + SC_DLLPUBLIC void ResizeMatrixFormula(const ScAddress& rOrigin, SCCOL nNewCols, + SCROW nNewRows); SC_DLLPUBLIC void InsertTableOp(const ScTabOpParam& rParam, // multi-operation SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark); @@ -1336,7 +1449,7 @@ public: */ sc::MultiDataCellState HasMultipleDataCells( const ScRange& rRange ) const; - // Spaklines + // Sparklines /** Returns sparkline at the address if it exists */ SC_DLLPUBLIC std::shared_ptr GetSparkline(ScAddress const & rPosition); SC_DLLPUBLIC bool HasSparkline(ScAddress const & rPosition); @@ -1386,6 +1499,12 @@ public: bool ContainsNotesInRange( const ScRangeList& rRange ) const; + // Person list (for threaded comments, [MS-XLSX] section 2.1.19) + SC_DLLPUBLIC void AddPerson(const ScPersonData& rPerson); + SC_DLLPUBLIC const ScPersonData* GetPersonById(const OUString& rId) const; + const std::vector& GetPersonList() const { return maPersonList; } + std::vector& GetPersonList() { return maPersonList; } + SC_DLLPUBLIC void SetDrawPageSize(SCTAB nTab); bool IsMerged( const ScAddress& rPos ) const; @@ -1594,13 +1713,6 @@ public: SCCOL& rEndCol, SCROW& rEndRow, bool bIncludeOld, bool bOnlyDown ) const; - /** - * Return the extended area containing at least all contiguous cells - * having background color. - */ - SC_DLLPUBLIC void GetBackColorArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, - SCCOL& rEndCol, SCROW& rEndRow ) const; - /** * Returns true if there is a non-empty subrange in the range given as input. * In that case it also modifies rRange to largest subrange that does not @@ -1794,7 +1906,8 @@ public: ScDocument* pRefUndoDoc, ScDocument* pClipDoc, bool bResetCut = true, bool bAsLink = false, bool bIncludeFiltered = true, bool bSkipEmptyCells = false, - const ScRangeList* pDestRanges = nullptr ); + const ScRangeList* pDestRanges = nullptr, + bool bPreserveDestProtection = false ); void CopyMultiRangeFromClip(const ScAddress& rDestPos, const ScMarkData& rMark, InsertDeleteFlags nInsFlag, ScDocument* pClipDoc, @@ -2408,16 +2521,30 @@ public: /* Sheet View */ /** Creates a new sheet view for the table, using the sheet view table */ - std::pair CreateNewSheetView(SCTAB nTab); + SC_DLLPUBLIC std::pair CreateNewSheetView(SCTAB nTab); /** Return the sheet view table for the ID */ SCTAB GetSheetViewNumber(SCTAB nTab, sc::SheetViewID nID); - bool HasSheetViews(SCTAB nTab) const; SC_DLLPUBLIC std::shared_ptr GetSheetViewManager(SCTAB nTable); /** Is a holder of the sheet view data */ SC_DLLPUBLIC bool IsSheetViewHolder(SCTAB nTab) const; + SC_DLLPUBLIC SCTAB GetDefaultViewTableNumber(SCTAB nTab) const; + + /** Returns the sheet view ID for a given tab. */ + SC_DLLPUBLIC sc::SheetViewID GetTableSheetViewID(SCTAB nTab) const; + + /** Returns the sheet view for a sheet view tab, or nullptr. */ + SC_DLLPUBLIC std::shared_ptr GetSheetView(SCTAB nTab); + + /** Synchronizes all sheet views for the given default view table. + * + * Specifically, it goes through all sheet views and overwrites the + * content of the sheet view table with the content of default view table, + * then reapplies the sheet views' sorting and filtering for the auto-filter. + */ + void SyncSheetViews(SCTAB nDefaultViewTable); private: ScDocument(const ScDocument& r) = delete; @@ -2470,6 +2597,11 @@ public: */ void Broadcast( const ScHint& rHint ); + /** Broadcast SfxHintId::ScRefErrorCreated for a completed reference + update pass, if any #REF! errors were created. No-op if the + context reports no errors. */ + void BroadcastRefError( const sc::RefErrorContext& rCtx ); + void BroadcastCells( const ScRange& rRange, SfxHintId nHint, bool bBroadcastSingleBroadcasters = true ); /// only area, no cell broadcast @@ -2555,6 +2687,17 @@ public: if ( nMacroInterpretLevel ) nMacroInterpretLevel--; } + sal_uInt16 GetCallableInterpretLevel() const { return nCallableInterpretLevel; } + void IncCallableInterpretLevel() + { + if (nCallableInterpretLevel < USHRT_MAX) + nCallableInterpretLevel++; + } + void DecCallableInterpretLevel() + { + if (nCallableInterpretLevel) + nCallableInterpretLevel--; + } bool IsInInterpreterTableOp() const { return nInterpreterTableOpLevel != 0; } void IncInterpreterTableOpLevel() { @@ -2635,7 +2778,7 @@ public: SC_DLLPUBLIC ScFieldEditEngine& GetEditEngine(); SC_DLLPUBLIC ScNoteEditEngine& GetNoteEngine(); - std::unique_ptr CreateSharedStringTextObject( const svl::SharedString& rSS ); + EditTextObject CreateSharedStringTextObject( const svl::SharedString& rSS ); std::unique_ptr const & GetRefreshTimerControlAddress() const { return pRefreshTimerControl; } @@ -2725,7 +2868,6 @@ public: void DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, const ScAddress& rTopPos, SCROW nLength ); std::optional GetColumnIterator( SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const; - void CreateColumnIfNotExists( SCTAB nTab, SCCOL nCol ); SC_DLLPUBLIC void StoreTabToCache(SCTAB nTab, SvStream& rStrm) const; SC_DLLPUBLIC void RestoreTabFromCache(SCTAB nTab, SvStream& rStream); @@ -2774,7 +2916,6 @@ public: SC_DLLPUBLIC bool HasTableStyles() const; private: - /** * Use this class as a locale variable to merge number formatter from * another document, and set NULL pointer to pFormatExchangeList when @@ -2809,6 +2950,8 @@ private: const ScRange& r, SCCOL nDx, SCROW nDy, SCTAB nDz ); void CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks); + void CopyDBsToClip(ScDocument* pClipDoc, const ScRangeList& rClipRanges, const ScMarkData* pMarks); + void CopyDBsFromClip(const ScRange& rDestRange, const ScRange& rClipRange, const ScDocument* pClipDoc); bool HasPartOfMerged( const ScRange& rRange ); @@ -2842,6 +2985,36 @@ private: typedef std::unique_ptr> ScDocumentUniquePtr; +namespace sc +{ +/** Guard for a BeginDrawUndo() capture window. + * Opens on construction, drains on destruction. If an undo action + * consumes the window in between, the destructor's drain is + * a harmless no-op. */ +class DrawUndoGuard +{ + ScDocument* mpDoc; + +public: + DrawUndoGuard(ScDocument& rDoc, bool bEnabled) + : mpDoc(bEnabled ? &rDoc : nullptr) + { + if (mpDoc) + mpDoc->BeginDrawUndo(); + } + ~DrawUndoGuard() + { + if (mpDoc) + { + if (auto* pLayer = mpDoc->GetDrawLayer()) + (void)pLayer->GetCalcUndo(); + } + } + DrawUndoGuard(const DrawUndoGuard&) = delete; + DrawUndoGuard& operator=(const DrawUndoGuard&) = delete; +}; +} // end sc namespace + /** * Instantiate this to ensure that subsequent modification of * the document will cause an assertion failure while this is diff --git a/sc/inc/documentimport.hxx b/sc/inc/documentimport.hxx index 2ffc75d67b82..d5dcc71c874b 100644 --- a/sc/inc/documentimport.hxx +++ b/sc/inc/documentimport.hxx @@ -112,8 +112,11 @@ public: void setFormulaCell(const ScAddress& rPos, std::unique_ptr pArray); void setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCell); + /// When the saved file recorded the matrix in a #SPILL! state, pass + /// bCheckForSpill=true. void setMatrixCells( - const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGrammar); + const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGrammar, + bool bCheckForSpill = false); void setTableOpCells(const ScRange& rRange, const ScTabOpParam& rParam); diff --git a/sc/inc/documentlinkmgr.hxx b/sc/inc/documentlinkmgr.hxx index de36ec40fa81..843b6a84d6ec 100644 --- a/sc/inc/documentlinkmgr.hxx +++ b/sc/inc/documentlinkmgr.hxx @@ -53,7 +53,7 @@ public: bool idleCheckLinks(); bool hasDdeLinks() const; - bool hasDdeOrOleOrWebServiceLinks() const; + bool hasUpdatableLinks() const; bool hasExternalRefLinks() const; bool updateDdeOrOleOrWebServiceLinks(weld::Window* pWin); @@ -61,9 +61,6 @@ public: void updateDdeLink( std::u16string_view rAppl, std::u16string_view rTopic, std::u16string_view rItem ); size_t getDdeLinkCount() const; - -private: - bool hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, bool bWebService) const; }; } diff --git a/sc/inc/dpdimsave.hxx b/sc/inc/dpdimsave.hxx index 940a4527b6f1..90571b0d85ba 100644 --- a/sc/inc/dpdimsave.hxx +++ b/sc/inc/dpdimsave.hxx @@ -79,7 +79,8 @@ public: (rDimension must be a different dimension from the one which contains this)*/ void RemoveElementsFromGroups( ScDPSaveGroupDimension& rDimension ) const; - void ConvertElementsToItems(SvNumberFormatter* pFormatter) const; + void ConvertElementsToItems(SvNumberFormatter* pFormatter, + const ScDPCache::ScDPItemDataVec& rSourceItems) const; bool HasInGroup(const ScDPItemData& rItem) const; }; @@ -230,8 +231,6 @@ public: ScDPDimCalcSaveData(); ScDPDimCalcSaveData(const ScDPDimCalcSaveData&) = default; - bool operator==(const ScDPDimCalcSaveData& r) const; - void WriteToCache(ScDPCache& rCache, const std::vector& rGroupFieldNames = {}) const; diff --git a/sc/inc/dpfilteredcache.hxx b/sc/inc/dpfilteredcache.hxx index 2dfe3663883e..f7a3690af0bd 100644 --- a/sc/inc/dpfilteredcache.hxx +++ b/sc/inc/dpfilteredcache.hxx @@ -108,9 +108,7 @@ public: sal_Int32 getColSize() const; sal_Int32 getCalculatedColumnCount() const; - void addCalculatedField(const std::shared_ptr& pField); bool isCalculatedField(sal_Int32 nDim) const; - OUString getCalculatedFieldName(sal_Int32 nDim) const; OUString getCalculation(sal_Int32 nDim) const; const ScTokenArray* getCalculationToken(sal_Int32 nDim) const; diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 03271c1fac51..132775ea3385 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -137,6 +137,7 @@ private: bool mbSettingsChanged : 1; bool mbEnableGetPivotData : 1; bool mbHideHeader : 1 = false; + bool mbSpillError : 1 = false; sc::PivotTableStyleInfo maStyleInfo; @@ -165,7 +166,13 @@ public: SC_DLLPUBLIC void ReloadGroupTableData(); - SC_DLLPUBLIC void Output( const ScAddress& rPos ); + /** Render the pivot table at input position. When bCheckForSpill is true, + first verify the output range is unblocked. If blocked, write #SPILL! + into input position, mark the object's spill state, and return false. + Otherwise write the table and return true. */ + SC_DLLPUBLIC bool Output(const ScAddress& rPos, bool bCheckForSpill = false); + bool HasSpillError() const; + void SetSpillError(bool bSpillError) { mbSpillError = bSpillError; } ScRange GetNewOutputRange( bool& rOverflow ); SC_DLLPUBLIC ScRange GetOutputRangeByType( sal_Int32 nType ); @@ -437,7 +444,7 @@ public: SC_DLLPUBLIC ScDPObject& operator[](size_t nIndex); SC_DLLPUBLIC const ScDPObject& operator[](size_t nIndex) const; - ScDPObject* GetByName(std::u16string_view rName) const; + SC_DLLPUBLIC ScDPObject* GetByName(std::u16string_view rName) const; void DeleteOnTab( SCTAB nTab ); void UpdateReference( UpdateRefMode eUpdateRefMode, @@ -455,6 +462,9 @@ public: OUString CreateNewName() const; void FreeTable(const ScDPObject* pDPObj); + + /** Deletes all pivot tables on the input tab. */ + void DeleteByTab(SCTAB nTab); SC_DLLPUBLIC ScDPObject* InsertNewTable(std::unique_ptr pDPObj); SC_DLLPUBLIC bool HasTable(const ScDPObject* pDPObj) const; diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx index 29423ab66c57..385d50ede7df 100644 --- a/sc/inc/dpoutput.hxx +++ b/sc/inc/dpoutput.hxx @@ -44,14 +44,15 @@ namespace com::sun::star::sheet { namespace tools { class Rectangle; } class ScDocument; struct ScDPOutLevelData; -class ScDPOutputImpl; class ScDPObject; +namespace sc::pivot { class StyleOutput; } class ScDPOutput { private: ScDocument* mpDocument; sc::FormatOutput maFormatOutput; + std::unique_ptr mpStyleOutput; css::uno::Reference mxSource; ScAddress maStartPos; std::vector mpColFields; @@ -89,6 +90,7 @@ private: bool mbHasCompactRowField:1; // true: at least one of the row fields has compact layout. bool mbExpandCollapse:1; // true: show expand/collapse buttons bool mbHideHeader : 1; + bool mbSpillError : 1 = false; // true: output range blocked by non-empty cells void DataCell( SCCOL nCol, SCROW nRow, SCTAB nTab, const css::sheet::DataResult& rData ); @@ -113,8 +115,8 @@ private: sal_Int32 GetRowFieldCompact(SCCOL nColQuery, SCROW nRowQuery) const; void outputPageFields(SCTAB nTab); - void outputColumnHeaders(SCTAB nTab, ScDPOutputImpl& rOutputImpl); - void outputRowHeader(SCTAB nTab, ScDPOutputImpl& rOutputImpl); + void outputColumnHeaders(SCTAB nTab); + void outputRowHeader(SCTAB nTab); void outputDataResults(SCTAB nTab); public: @@ -127,9 +129,11 @@ public: void SetPosition( const ScAddress& rPos ); void Output(); //! Refresh? + void Output(const ScRange& rOldRange, bool bCheckForSpill); ScRange GetOutputRange( sal_Int32 nRegionType = css::sheet::DataPilotOutputRangeType::WHOLE ); sal_Int32 GetHeaderRows() const; bool HasError(); // range overflow or exception from source + bool HasSpillError() const { return mbSpillError; } void GetPositionData(const ScAddress& rPos, css::sheet::DataPilotTablePositionData& rPosData); diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx index 4fb8b7dbf8d5..63458164a054 100644 --- a/sc/inc/dpsave.hxx +++ b/sc/inc/dpsave.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include #include #include @@ -272,7 +273,7 @@ public: ScDPSaveData& operator= ( const ScDPSaveData& r ); - bool operator== ( const ScDPSaveData& r ) const; + SC_DLLPUBLIC bool operator==(const ScDPSaveData& r) const; SC_DLLPUBLIC bool hasFormats(); SC_DLLPUBLIC sc::PivotTableFormats const& getFormats(); @@ -401,4 +402,10 @@ private: void DimensionsChanged(); }; +inline std::ostream& operator<<(std::ostream& rStrm, const ScDPSaveData& rData) +{ + rStrm << "SaveData[dimensions = " << rData.GetDimensions().size() << "]"; + return rStrm; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/dptabres.hxx b/sc/inc/dptabres.hxx index 640f056088a0..f71854d4195b 100644 --- a/sc/inc/dptabres.hxx +++ b/sc/inc/dptabres.hxx @@ -32,6 +32,7 @@ #include #include #include +#include #include namespace com::sun::star::sheet { struct DataResult; } @@ -43,6 +44,7 @@ class ScDPDimension; class ScDPLevel; class ScDPMember; class ScDPResultMember; +class ScDPResultMemberFull; class ScDPResultVisibilityData; class ScTokenArray; @@ -334,6 +336,306 @@ public: class ScDPResultMember { +public: + virtual ~ScDPResultMember() = default; + + void InitFrom(const ::std::vector& ppDim, + const ::std::vector& ppLev, size_t nPos, ScDPInitState& rInitState, + bool bInitChild = true); + + virtual void LateInitFrom(LateInitParams& rParams, const ::std::vector& pItemData, + size_t nPos, ScDPInitState& rInitState) = 0; + + virtual void ResetChildDimension() = 0; + + void CheckShowEmpty(bool bShow = false); + + OUString GetName() const; + + OUString GetDisplayName(bool bLocaleIndependent) const; + + virtual const ScDPResultData* GetResultData() const = 0; + + ScDPItemData FillItemData() const; + + virtual bool IsAutoHidden() const = 0; + + virtual bool GetForceSubTotal() const = 0; + + virtual bool IsInitialized() const = 0; + + bool IsValid() const; + + bool IsVisible() const; + + tools::Long GetSize(tools::Long nMeasure) const; + + virtual bool HasHiddenDetails() const = 0; + + virtual void SetHasHiddenDetails() = 0; + + bool IsSubTotalInTitle(tools::Long nMeasure) const; + + tools::Long GetSubTotalCount(tools::Long* pUserSubStart = nullptr) const; + + bool IsNamedItem(SCROW nIndex) const; + + bool IsValidEntry(const ::std::vector& aMembers) const; + + virtual bool GetHasElements() const = 0; + + virtual void SetHasElements() = 0; + + virtual void SetInitialized() = 0; + + virtual void SetAutoHidden() = 0; + + virtual sal_uInt16 GetMemberStep(void) = 0; + + virtual void SetMemberStep(sal_uInt16 nStep) = 0; + + virtual void + ProcessData(const ::std::vector& aChildMembers, const ScDPResultDimension* pDataDim, + const ::std::vector& aDataMembers, const ::std::vector& aValues) = 0; + + void FillMemberResults(css::uno::Sequence* pSequences, + tools::Long& rPos, tools::Long nMeasure, bool bRoot, + const OUString* pMemberName, const OUString* pMemberCaption); + + void FillDataResults(const ScDPResultMember* pRefMember, ScDPResultFilterContext& rFilterCxt, + css::uno::Sequence>& rSequence, + tools::Long nMeasure) const; + + void UpdateDataResults(const ScDPResultMember* pRefMember, tools::Long nMeasure) const; + + void UpdateRunningTotals(ScDPResultMember* pRefMember, tools::Long nMeasure, + ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals) const; + + void SortMembers(ScDPResultMember* pRefMember); + + virtual void DoAutoShow(ScDPResultMember* pRefMember) = 0; + + virtual void ResetResults() = 0; + +#if DUMP_PIVOT_TABLE + virtual void DumpState(const ScDPResultMember* pRefMember, ScDocument* pDoc, + ScAddress& rPos) const = 0; + virtual void Dump(int nIndent) const = 0; +#endif + + virtual const ScDPResultDimension* GetChildDimension() const = 0; + virtual ScDPResultDimension* GetChildDimension() = 0; + + virtual ScDPDataMember* GetDataRoot() const = 0; + + virtual const ScDPDimension* GetParentDim() const = 0; + virtual const ScDPLevel* GetParentLevel() const = 0; + virtual const ScDPMember* GetDPMember() const = 0; + + virtual SCROW GetOrder() const = 0; + + bool IsRoot() const { return GetParentLevel() == nullptr; } + + SCROW GetDataId() const; + + virtual ScDPAggData* GetColTotal(tools::Long nMeasure) = 0; + + void FillVisibilityData(ScDPResultVisibilityData& rData); +}; + +class ScDPResultMemberSlim : public ScDPResultMember +{ + friend ScDPResultDimension; // For promotion +private: + // When adding fields here, update ScDPResultDimension::Promote + ScDPResultDimension* mpOurDimension; + const ScDPMember* mpMemberDesc; + SCROW mnOrder; + bool bmHasElements : 1; + bool bmHasHiddenDetails : 1; + bool bmInitialized : 1; + bool bmPromoted : 1; + + // Called when 'mpPromoted' meaning someone with this object pointer is + // calling a member even though a previous call has promoted it. + // Note this is const since we know we're not changing the current (old) object + ScDPResultMember* GetPromote() const; + + // Called when something decides it needs to be promoted, typically when something + // is getting set. Note this is NOT const since the bmPromoted flag needs + // to be set. + // The 'sReason' is purely to let debugging be used to track the reason + // for promotions + ScDPResultMember* Promote(const char* sReason); + +public: + ScDPResultMemberSlim(ScDPResultDimension* pRDimension, const ScDPParentDimData& rParentDimData); + // Just for array new + ScDPResultMemberSlim(); + + bool GetHasElements() const override + { + if (bmPromoted) + return GetPromote()->GetHasElements(); + return bmHasElements; + }; + + bool HasHiddenDetails() const override + { + if (bmPromoted) + return GetPromote()->HasHiddenDetails(); + return bmHasHiddenDetails; + } + + void LateInitFrom(LateInitParams& rParams, const ::std::vector& pItemData, size_t nPos, + ScDPInitState& rInitState) override + { + Promote("LateInitFrom")->LateInitFrom(rParams, pItemData, nPos, rInitState); + } + + void ResetChildDimension() override + { + // We don't store the child dimension, so promote + Promote("ResetChildDimension")->ResetChildDimension(); + } + + void SetAutoHidden() override { Promote("SetAutoHidden")->SetAutoHidden(); } + + void SetHasElements() override + { + if (bmPromoted) + return GetPromote()->SetHasElements(); + bmHasElements = true; + } + + void SetHasHiddenDetails() override + { + if (bmPromoted) + return GetPromote()->SetHasHiddenDetails(); + bmHasHiddenDetails = true; + } + + void SetInitialized() override + { + if (bmPromoted) + return GetPromote()->SetInitialized(); + bmInitialized = true; + } + + bool GetForceSubTotal() const override + { + if (bmPromoted) + return GetPromote()->GetForceSubTotal(); + // Never set in Slim + return false; + } + + ScDPDataMember* GetDataRoot() const override + { + if (bmPromoted) + return GetPromote()->GetDataRoot(); + // Slim doesn't store the data root, if one was set we would have been promoted + return nullptr; + } + + bool IsAutoHidden() const override + { + if (bmPromoted) + return GetPromote()->IsAutoHidden(); + // Slim doesn't store Auto hidden + return false; + } + + sal_uInt16 GetMemberStep() override + { + if (bmPromoted) + return GetPromote()->GetMemberStep(); + // We don't store this in the slim version, it's always + // 1 unless promoted + return 1; + } + + void SetMemberStep(sal_uInt16 nStep) override + { + if (bmPromoted) + return GetPromote()->SetMemberStep(nStep); + // We don't actually store this in the slim version, we just + // promote if it's ever non-1 + if (nStep != 1) + return Promote("SetMemberStep")->SetMemberStep(nStep); + // OK, it is 1 - do nothing + } + + void ProcessData(const ::std::vector& aChildMembers, const ScDPResultDimension* pDataDim, + const ::std::vector& aDataMembers, + const ::std::vector& aValues) override + { + // Looks pretty complicated and needs pDataRoot, lets try + // Promoting for now + Promote("ProcessData")->ProcessData(aChildMembers, pDataDim, aDataMembers, aValues); + } + + void DoAutoShow(ScDPResultMember* pRefMember) override + { + Promote("DoAutoShow")->DoAutoShow(pRefMember); + } + + void ResetResults() override { Promote("ResetResults")->ResetResults(); } + + const ScDPResultDimension* GetChildDimension() const override + { + if (bmPromoted) + return GetPromote()->GetChildDimension(); + // Slim doesn't store a child pointer, if one was set we would have been promoted + return nullptr; + } + + ScDPResultDimension* GetChildDimension() override + { + if (bmPromoted) + return GetPromote()->GetChildDimension(); + // Slim doesn't store a child pointer, if one was set we would have been promoted + return nullptr; + } + + const ScDPDimension* GetParentDim() const override; + const ScDPLevel* GetParentLevel() const override; + + const ScDPMember* GetDPMember() const override + { + if (bmPromoted) + return GetPromote()->GetDPMember(); + return mpMemberDesc; + } + + bool IsInitialized() const override + { + if (bmPromoted) + return GetPromote()->IsInitialized(); + return bmInitialized; + }; + + const ScDPResultData* GetResultData() const override; + + SCROW GetOrder() const override + { + // mnOrder is never changed, and on promotion is passed to new version + return mnOrder; + } + + ScDPAggData* GetColTotal(tools::Long nMeasure) override + { + return Promote("GetColTotal")->GetColTotal(nMeasure); + } + +#if DUMP_PIVOT_TABLE + void DumpState(const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos) const override; + void Dump(int nIndent) const override; +#endif +}; + +class ScDPResultMemberFull : public ScDPResultMember +{ private: const ScDPResultData* pResultData; ScDPParentDimData aParentDimData; @@ -348,61 +650,39 @@ private: bool bAutoHidden:1; public: - ScDPResultMember( - const ScDPResultData* pData, const ScDPParentDimData& rParentDimData ); //! Ref - ScDPResultMember( const ScDPResultData* pData, bool bForceSub ); - ~ScDPResultMember(); + ScDPResultMemberFull(const ScDPResultData* pData, + const ScDPParentDimData& rParentDimData); //! Ref + ScDPResultMemberFull(const ScDPResultData* pData, bool bForceSub); + ~ScDPResultMemberFull(); - void InitFrom( const ::std::vector& ppDim, - const ::std::vector& ppLev, - size_t nPos, - ScDPInitState& rInitState, - bool bInitChild = true ); void LateInitFrom( LateInitParams& rParams, const ::std::vector< SCROW >& pItemData, size_t nPos, ScDPInitState& rInitState); - void CheckShowEmpty( bool bShow = false ); - OUString GetName() const; - OUString GetDisplayName( bool bLocaleIndependent ) const; + const ScDPResultData* GetResultData() const { return pResultData; } - ScDPItemData FillItemData() const; - bool IsValid() const; - bool IsVisible() const; - tools::Long GetSize(tools::Long nMeasure) const; + bool IsAutoHidden() const { return bAutoHidden; }; + bool GetForceSubTotal() const { return bForceSubTotal; }; + bool IsInitialized() const { return bInitialized; }; // bHasHiddenDetails is set only if the "show details" flag is off, // and there was a child dimension to skip bool HasHiddenDetails() const { return bHasHiddenDetails; } - bool IsSubTotalInTitle(tools::Long nMeasure) const; - - tools::Long GetSubTotalCount( tools::Long* pUserSubStart = nullptr ) const; - - bool IsNamedItem( SCROW nIndex ) const; - bool IsValidEntry( const ::std::vector< SCROW >& aMembers ) const; + void SetHasHiddenDetails() { bHasHiddenDetails = true; } + bool GetHasElements() const { return bHasElements; }; void SetHasElements() { bHasElements = true; } + void SetInitialized() { bInitialized = true; } void SetAutoHidden() { bAutoHidden = true; } + sal_uInt16 GetMemberStep(void) { return nMemberStep; } + void SetMemberStep(sal_uInt16 nStep) { nMemberStep = nStep; } + void ProcessData( const ::std::vector& aChildMembers, const ScDPResultDimension* pDataDim, const ::std::vector& aDataMembers, const ::std::vector& aValues ); - void FillMemberResults( - css::uno::Sequence< css::sheet::MemberResult>* pSequences, - tools::Long& rPos, tools::Long nMeasure, bool bRoot, const OUString* pMemberName, const OUString* pMemberCaption ); - void FillDataResults( - const ScDPResultMember* pRefMember, - ScDPResultFilterContext& rFilterCxt, - css::uno::Sequence< css::uno::Sequence< css::sheet::DataResult> >& rSequence, - tools::Long nMeasure) const; - - void UpdateDataResults( const ScDPResultMember* pRefMember, tools::Long nMeasure ) const; - void UpdateRunningTotals( ScDPResultMember* pRefMember, tools::Long nMeasure, - ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const; - - void SortMembers( ScDPResultMember* pRefMember ); void DoAutoShow( ScDPResultMember* pRefMember ); void ResetResults(); @@ -417,17 +697,15 @@ public: const ScDPResultDimension* GetChildDimension() const { return pChildDimension.get(); } ScDPResultDimension* GetChildDimension() { return pChildDimension.get(); } + void ResetChildDimension(); + ScDPDataMember* GetDataRoot() const { return pDataRoot.get(); } const ScDPDimension* GetParentDim() const { return aParentDimData.mpParentDim; } //! Ref const ScDPLevel* GetParentLevel() const { return aParentDimData.mpParentLevel; } //! Ref const ScDPMember* GetDPMember()const { return aParentDimData.mpMemberDesc; } //! Ref SCROW GetOrder() const { return aParentDimData.mnOrder; } //! Ref - bool IsRoot() const { return GetParentLevel() == nullptr; } - SCROW GetDataId( ) const ; ScDPAggData* GetColTotal( tools::Long nMeasure ); - - void FillVisibilityData(ScDPResultVisibilityData& rData) const; }; class ScDPDataMember @@ -468,14 +746,15 @@ public: tools::Long nMeasure, bool bIsSubTotalRow, const ScDPSubTotalState& rSubState) const; - void UpdateDataRow( const ScDPResultMember* pRefMember, tools::Long nMeasure, bool bIsSubTotalRow, - const ScDPSubTotalState& rSubState ); - void UpdateRunningTotals( ScDPResultMember* pRefMember, tools::Long nMeasure, bool bIsSubTotalRow, - const ScDPSubTotalState& rSubState, ScDPRunningTotalState& rRunning, - ScDPRowTotals& rTotals, const ScDPResultMember& rRowParent ); + void UpdateDataRow(const ScDPResultMember* pRefMember, tools::Long nMeasure, + bool bIsSubTotalRow, const ScDPSubTotalState& rSubState); + void UpdateRunningTotals(ScDPResultMember* pRefMember, tools::Long nMeasure, + bool bIsSubTotalRow, const ScDPSubTotalState& rSubState, + ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals, + const ScDPResultMember& rRowParent); - void SortMembers( ScDPResultMember* pRefMember ); - void DoAutoShow( ScDPResultMember* pRefMember ); + void SortMembers(ScDPResultMember* pRefMember); + void DoAutoShow(ScDPResultMember* pRefMember); void ResetResults(); @@ -500,11 +779,19 @@ class ScDPResultDimension { public: typedef std::vector> MemberArray; - typedef std::unordered_map MemberHash; + typedef std::unique_ptr> MemberSlimArray; + private: const ScDPResultData* pResultData; + // Used when we allocate a full set of Slim + MemberSlimArray mpaMemberSlimArray; + // Used both in non-Slim cases and after Slim get promoted MemberArray maMemberArray; - MemberHash maMemberHash; + + // Used during 'Promote' of ScDPResultMember + ScDPDimension* mpDimension; + ScDPLevel* mpLevel; + OUString aDimensionName; //! or ptr to IntDimension? tools::Long nSortMeasure; ScMemberSortOrder aMemberOrder; // used when sorted by measure @@ -559,14 +846,14 @@ public: css::sheet::DataResult> >& rSequence, tools::Long nMeasure) const; - void UpdateDataResults( const ScDPResultMember* pRefMember, tools::Long nMeasure ) const; - void UpdateRunningTotals( ScDPResultMember* pRefMember, tools::Long nMeasure, - ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const; + void UpdateDataResults(const ScDPResultMember* pRefMember, tools::Long nMeasure) const; + void UpdateRunningTotals(ScDPResultMember* pRefMember, tools::Long nMeasure, + ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals) const; - void SortMembers( ScDPResultMember* pRefMember ); + void SortMembers(ScDPResultMember* pRefMember); tools::Long GetSortedIndex( tools::Long nUnsorted ) const; - void DoAutoShow( ScDPResultMember* pRefMember ); + void DoAutoShow(ScDPResultMember* pRefMember); void ResetResults(); @@ -592,6 +879,7 @@ public: const ScMemberSortOrder& GetMemberOrder() const { return aMemberOrder; } ScMemberSortOrder& GetMemberOrder() { return aMemberOrder; } + const ScDPResultData* GetResultData() const { return pResultData; } bool IsDataLayout() const { return bIsDataLayout; } const OUString& GetName() const { return aDimensionName; } @@ -605,9 +893,21 @@ public: tools::Long GetAutoMeasure() const { return nAutoMeasure; } tools::Long GetAutoCount() const { return nAutoCount; } - ScDPResultDimension* GetFirstChildDimension() const; + ScDPResultDimension* GetFirstChildDimension(); - void FillVisibilityData(ScDPResultVisibilityData& rData) const; + void FillVisibilityData(ScDPResultVisibilityData& rData); + + // Called by an ScDPResultMemberSlim which has already been promoted + // but something with an older pointer calls one of its member functions + ScDPResultMember* GetPromote(SCROW nOrder) const; + + // Called by an ScDPResultMemberSlim when a member function needs + // to do something which Slim can't represent + ScDPResultMember* Promote(ScDPResultMemberSlim* pSlim, SCROW nOrder); + + // Called by an ScDPResultMemberSlim to get its parent information + ScDPDimension* GetParentDimForResult() { return mpDimension; }; + ScDPLevel* GetParentLevelForResult() { return mpLevel; }; }; class ScDPDataDimension diff --git a/sc/inc/dptabsrc.hxx b/sc/inc/dptabsrc.hxx index 6496d808360c..778f3d3412eb 100644 --- a/sc/inc/dptabsrc.hxx +++ b/sc/inc/dptabsrc.hxx @@ -239,8 +239,6 @@ public: void CountChanged(); - void InsertEmptyDimension( sal_Int32 nPos ); - // XNameAccess virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override; @@ -288,7 +286,6 @@ public: ScDPDimension(const ScDPDimension&) = delete; ScDPDimension& operator=(const ScDPDimension&) = delete; - void SetDimension(sal_Int32 nPos) { nDim = nPos; } sal_Int32 GetDimension() const { return nDim; } // dimension index in source sal_Int32 GetSourceDim() const { return nSourceDim; } // >=0 if dup'ed @@ -298,8 +295,6 @@ public: const std::optional & GetLayoutName() const; const std::optional & GetSubtotalName() const; - const std::optional& getCalculation() const; - // XNamed virtual OUString SAL_CALL getName() override; virtual void SAL_CALL setName( const OUString& aName ) override; diff --git a/sc/inc/editutil.hxx b/sc/inc/editutil.hxx index a0f2c6ec9e97..a920502376c2 100644 --- a/sc/inc/editutil.hxx +++ b/sc/inc/editutil.hxx @@ -64,12 +64,12 @@ public: */ SC_DLLPUBLIC static OUString GetString( const EditTextObject& rEditText, const ScDocument& rDoc ); - static std::unique_ptr CreateURLObjectFromURL( + static EditTextObject CreateURLObjectFromURL( ScDocument& rDoc, const OUString& rURL, const OUString& rText ); static void RemoveCharAttribs( EditTextObject& rEditText, const ScPatternAttr& rAttr ); - static std::unique_ptr Clone( const EditTextObject& rSrc, ScDocument& rDestDoc ); + static EditTextObject Clone( const EditTextObject& rSrc, ScDocument& rDestDoc ); static OUString GetCellFieldValue( const SvxFieldData& rFieldData, const ScDocument* pDoc, std::optional* ppTextColor, std::optional* ppFldLineStyle ); diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx index 815ee77e158d..dce677a8ae59 100644 --- a/sc/inc/externalrefmgr.hxx +++ b/sc/inc/externalrefmgr.hxx @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -433,6 +434,8 @@ public: OUString maRelativeName; OUString maFilterName; OUString maFilterOptions; + bool mbPathMissing = false; /// true if external relation is (xlPathMissing). + bool mbXlStartup = false; /// true if path is relative to XLSTART folder. void maybeCreateRealFileName(std::u16string_view rOwnDocName); }; @@ -589,6 +592,10 @@ public: SC_DLLPUBLIC void convertToAbsName(OUString& rFile) const; SC_DLLPUBLIC sal_uInt16 getExternalFileId(const OUString& rFile); + /** Stores the drawing-shape macro */ + SC_DLLPUBLIC void addDrawingMacros(sal_uInt16 nFileId, const OUString& rName); + SC_DLLPUBLIC const std::map>& getDrawingMacros() const; + /** * It returns a pointer to the name of the URI associated with a given * external file ID. In case the original document has moved, it returns @@ -647,6 +654,12 @@ public: */ void setFilterData(sal_uInt16 nFileId, const OUString& rFilterName, const OUString& rOptions); + SC_DLLPUBLIC bool isPathMissing(sal_uInt16 nFileId); + void setPathMissing(sal_uInt16 nFileId); + + SC_DLLPUBLIC bool isXlStartup(sal_uInt16 nFileId); + SC_DLLPUBLIC void setXlStartup(sal_uInt16 nFileId); + void clear(); bool hasExternalData() const; @@ -862,6 +875,10 @@ private: bool mbSkipUnusedFileIds = false; std::vector maConvertFileIdToUsedFileId; + /** External references discovered in drawing-shape macros. + File ID is 0-based (matches getExternalFileId). */ + std::map> maDrawingMacros; + bool mbDocTimerEnabled:1; AutoTimer maSrcDocTimer; diff --git a/sc/inc/fillinfo.hxx b/sc/inc/fillinfo.hxx index b34bc52281ec..11169388ee4b 100644 --- a/sc/inc/fillinfo.hxx +++ b/sc/inc/fillinfo.hxx @@ -114,8 +114,7 @@ struct ScBasicCellInfo struct ScCellInfo { ScCellInfo() - : pPatternAttr(nullptr) - , pConditionSet(nullptr) + : pConditionSet(nullptr) , pTableFormatSet(nullptr) , pDataBar(nullptr) , pIconSet(nullptr) @@ -150,7 +149,13 @@ struct ScCellInfo ScRefCellValue maCell; - const ScPatternAttr* pPatternAttr; + // This is not ideal, both for efficiency and correctness. + // (a) It costs cycles to ref-count the underlying ScPatternAttr here. + // (b) We can also end up pointing at an incorrect ScPatternAttr. + // This is because, during painting, calculation side-effects can end up mutating the underlying cell + // attributes. Rather than pay the cost of fetching the right thing repeatedly during painting, we + // tolerate a little bit of (hopefully) temporary incorrectness. + CellAttributeHolder pPatternAttr; const SfxItemSet* pConditionSet; const SfxItemSet* pTableFormatSet; std::optional mxColorScale; @@ -185,6 +190,8 @@ struct ScCellInfo bool bPivotCollapseButton : 1; // dp compact layout collapse button bool bPivotExpandButton : 1; // dp compact layout expand button bool bPivotPopupButtonMulti : 1; // dp button with popup arrow for multiple fields + + const ScPatternAttr* getPatternAttr() const { return pPatternAttr.getScPatternAttr(); } }; const SCCOL SC_ROTMAX_NONE = SCCOL_MAX; diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index c11fcea7efe5..7538505d0180 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -137,6 +138,13 @@ private: bool mbIsExtRef : 1; // has references in ScExternalRefManager; never cleared after set bool mbSeenInPath : 1; // For detecting cycle involving formula groups and singleton formulacells bool mbFreeFlying : 1; // Cell is out of sheets interpreted, like in conditional format + // Matrix master that recomputes its range at interpret time. False on a + // static array master, which keeps its declared range frozen. + bool mbDynamicArrayMaster : 1 = false; + // True if the cell is allowed to auto-promote to a dynamic-array + // master. False keeps the cell as a plain single-cell formula that + // returns the upper-left of any array result. + bool mbAutoDynamicArrayEligible : 1 = false; ScMatrixMode cMatrixFlag : 8; sal_uInt16 nSeenInIteration : 16; // Iteration cycle in which the cell was last encountered SvNumFormatType nFormatType : 16; @@ -198,7 +206,7 @@ public: /** * Transfer the ownership of the passed token array instance to the - * formula cell being constructed. The caller must not pass a NULL + * formula cell being constructed. The caller must not pass a nullptr * token array pointer. */ SC_DLLPUBLIC ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos, std::unique_ptr pArray, @@ -214,10 +222,10 @@ public: ScMatrixMode = ScMatrixMode::NONE ); /** With formula string and grammar to compile with. - formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that + formula::FormulaGrammar::GRAM_DEFAULT effectively is formula::FormulaGrammar::GRAM_NATIVE_UI that also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefore uses the address convention associated with rPos::nTab by default. */ - ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos, + SC_DLLPUBLIC ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos, const OUString& rFormula, const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT, ScMatrixMode cMatInd = ScMatrixMode::NONE ); @@ -265,7 +273,7 @@ public: bool MarkUsedExternalReferences(); // Returns true if the cell was interpreted as part of the formula group. // The parameters may limit which subset of the formula group should be interpreted, if possible. - bool Interpret(SCROW nStartOffset = -1, SCROW nEndOffset = -1); + SC_DLLPUBLIC bool Interpret(SCROW nStartOffset = -1, SCROW nEndOffset = -1); bool IsIterCell() const { return bIsIterCell; } sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; } @@ -318,6 +326,7 @@ public: void UpdateInsertTab( const sc::RefUpdateInsertTabContext& rCxt ); void UpdateInsertTabAbs(SCTAB nTable); + void AdjustRelativeTabRefs(SCTAB nOldTab, SCTAB nNewTab, sc::TargetTabState eMode); void UpdateDeleteTab( const sc::RefUpdateDeleteTabContext& rCxt ); void UpdateMoveTab( const sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo ); bool TestTabRefAbs(SCTAB nTable); @@ -332,8 +341,12 @@ public: SC_DLLPUBLIC bool IsValue(); // also true if formula::svEmptyCell bool IsValueNoError(); bool IsValueNoError() const; + SC_DLLPUBLIC bool IsString(); + SC_DLLPUBLIC bool IsCallable(); SC_DLLPUBLIC double GetValue(); SC_DLLPUBLIC const svl::SharedString & GetString(); + SC_DLLPUBLIC formula::FormulaCallableRef GetCallable(); + SC_DLLPUBLIC formula::FormulaTokenRef CloneResultToken(); /** * Get a numeric value without potentially triggering re-calculation. @@ -344,6 +357,21 @@ public: * Get a string value without potentially triggering re-calculation. */ const svl::SharedString & GetRawString() const; + + /** + * Get a callable value without potentially triggering re-calculation. + */ + formula::FormulaCallableRef GetRawCallable() const; + /** + * Get a value without potentially triggering re-calculation. May return nullptr if the + * result is not a token. + */ + formula::FormulaConstTokenRef GetRawResultToken() const; + /** + * Get a copy of the token without potentially triggering re-calculation. Will not + * return nullptr, but the caller is responsible for the reference. + */ + formula::FormulaTokenRef CloneRawResultToken() const; const ScMatrix* GetMatrix(); SC_DLLPUBLIC bool GetMatrixOrigin( const ScDocument& rDoc, ScAddress& rPos ) const; void GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows ); @@ -354,6 +382,17 @@ public: SC_DLLPUBLIC sc::FormulaResultValue GetResult(); SC_DLLPUBLIC sc::FormulaResultValue GetResult() const; ScMatrixMode GetMatrixFlag() const { return cMatrixFlag;} + bool IsDynamicArrayMaster() const { return mbDynamicArrayMaster; } + SC_DLLPUBLIC void SetDynamicArrayMaster( bool bDynamic ); + SC_DLLPUBLIC void ResolveImplicitIntersection(); + // Run this on the bare token array before it is wrapped in a cell. + // The cell constructor finalizes the parse array. Once finalized, + // appending a new token silently no-ops. The document and position + // arguments compile a missing RPN so the array-intent walk has the + // post-fix order it needs. + SC_DLLPUBLIC static void ResolveImplicitIntersection(ScTokenArray& rCode, ScDocument& rDoc, + const ScAddress& rPos); + void SetAutoDynamicArrayEligible( bool bEligible ) { mbAutoDynamicArrayEligible = bEligible; } ScTokenArray* GetCode() { return pCode;} const ScTokenArray* GetCode() const { return pCode;} @@ -430,8 +469,13 @@ public: /* Sets just the result to error */ void SetResultError( FormulaError n ); + /** Mark this dynamic array master into #SPILL! state. This collapses + the declared dimensions to 1x1, sets a re-evaluable result error, + and registers the cell for later re-evaluation. */ + void MarkAsSpilled(); + SC_DLLPUBLIC bool IsHyperLinkCell() const; - std::unique_ptr CreateURLObject(); + EditTextObject CreateURLObject(); SC_DLLPUBLIC void GetURLResult( OUString& rURL, OUString& rCellText ); /** Determines whether or not the result string contains more than one paragraph */ diff --git a/sc/inc/formulaopt.hxx b/sc/inc/formulaopt.hxx index 8adc26be5106..0f57336abecf 100644 --- a/sc/inc/formulaopt.hxx +++ b/sc/inc/formulaopt.hxx @@ -73,7 +73,6 @@ public: static void GetDefaultFormulaSeparators(OUString& rSepArg, OUString& rSepArrayCol, OUString& rSepArrayRow); bool operator== ( const ScFormulaOptions& rOpt ) const; - bool operator!= ( const ScFormulaOptions& rOpt ) const; }; // item for the dialog / options page diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx index 44aab47acd44..947a35c40950 100644 --- a/sc/inc/formularesult.hxx +++ b/sc/inc/formularesult.hxx @@ -22,6 +22,7 @@ #include "global.hxx" #include "calcmacros.hxx" #include +#include #include #include @@ -117,6 +118,9 @@ public: /** May be NULL if SetToken() did so, also if type formula::svDouble or formula::svError! */ formula::FormulaConstTokenRef GetToken() const; + /** Caller owns the reference to the token; will not be NULL */ + formula::FormulaTokenRef CloneToken() const; + /** Return upper left token if formula::svMatrixCell, else return GetToken(). May be NULL if SetToken() did so, also if type formula::svDouble or formula::svError! */ formula::FormulaConstTokenRef GetCellResultToken() const; @@ -143,6 +147,14 @@ public: bool IsValueNoError() const; + /** Test for cell result type formula::svString, including upper left if + formula::svMatrixCell. */ + bool IsString() const; + + /** Test for cell result type formula::svCallable, including upper left if + formula::svMatrixCell. */ + bool IsCallable() const; + /** Determines whether or not the result is a string containing more than one paragraph */ bool IsMultiline() const; @@ -174,6 +186,9 @@ public: upper left formula::svString, else empty string. */ const svl::SharedString & GetString() const; + /** Return callable if type formula::svCallable, else nullptr. */ + formula::FormulaCallableRef GetCallable() const; + /** Return matrix if type formula::svMatrixCell and ScMatrix present, else NULL. */ ScConstMatrixRef GetMatrix() const; diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx index 4ad10ec35902..3bdfe5e4d802 100644 --- a/sc/inc/global.hxx +++ b/sc/inc/global.hxx @@ -281,11 +281,16 @@ enum class ScCloneFlags{ /** If set, global named expressions will be converted to sheet-local named expressions. */ - NamesToLocal = 0x0004 + NamesToLocal = 0x0004, + + /** If set, cross-sheet references will be adjusted during copying to + compensate for the difference of the tab index between source and + destination cells. */ + AdjustCrossSheetRefs = 0x0008 }; namespace o3tl { - template<> struct typed_flags : is_typed_flags {}; + template<> struct typed_flags : is_typed_flags {}; } enum CellType @@ -590,6 +595,7 @@ public: static void ClearAutoFormat(); //BugId 54209 static LegacyFuncCollection* GetLegacyFuncCollection(); SC_DLLPUBLIC static ScUnoAddInCollection* GetAddInCollection(); + SC_DLLPUBLIC static bool IsValidExternal(const OUString& rAddIn); SC_DLLPUBLIC static ScUserList& GetUserList(); static void SetUserList( const ScUserList* pNewList ); /** @@ -696,8 +702,8 @@ public: */ SC_DLLPUBLIC static const sal_Unicode* FindUnquoted( const sal_Unicode* pString, sal_Unicode cChar ); - static rtl_TextEncoding GetCharsetValue( std::u16string_view rCharSet ); - static OUString GetCharsetString( rtl_TextEncoding eVal ); + static rtl_TextEncoding GetEncodingValue( std::u16string_view rEncoding ); + static OUString GetEncodingString( rtl_TextEncoding eVal ); /// a "ReadOnly" formatter for UNO/XML export static SvNumberFormatter* GetEnglishFormatter(); diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc index 0fd827f8db10..ab57077239c7 100644 --- a/sc/inc/globstr.hrc +++ b/sc/inc/globstr.hrc @@ -64,7 +64,9 @@ #define STR_UNDO_OUTLINELEVEL NC_("STR_UNDO_OUTLINELEVEL", "Select outline level") #define STR_UNDO_DOOUTLINEBLK NC_("STR_UNDO_DOOUTLINEBLK", "View Details") #define STR_UNDO_REDOOUTLINEBLK NC_("STR_UNDO_REDOOUTLINEBLK", "Hide details") +// To translators: Outline refers to a group of cells #define STR_UNDO_REMOVEALLOTLNS NC_("STR_UNDO_REMOVEALLOTLNS", "Clear Outline") +// To translators: Outline refers to a group of cells #define STR_UNDO_AUTOOUTLINE NC_("STR_UNDO_AUTOOUTLINE", "AutoOutline") #define STR_UNDO_SUBTOTALS NC_("STR_UNDO_SUBTOTALS", "Subtotals") #define STR_UNDO_TABLETOTALS NC_("STR_UNDO_TABLETOTALS", "Table Total Row") @@ -156,6 +158,7 @@ #define STR_PIVOT_MOVENOTALLOWED NC_("STR_PIVOT_MOVENOTALLOWED", "The data range can not be deleted.") #define STR_PIVOT_ERROR NC_("STR_PIVOT_ERROR", "Error creating the pivot table.") #define STR_PIVOT_NOTEMPTY NC_("STR_PIVOT_NOTEMPTY", "The destination range is not empty. Overwrite existing contents?") +#define STR_PIVOT_SPILL NC_("STR_PIVOT_SPILL", "Pivot table output blocked by non-empty cells in the destination range.") #define STR_PIVOT_REMOVE_PIVOTCHART NC_("STR_PIVOT_REMOVE_PIVOTCHART", "Deleting the pivot table will also remove any associated pivot charts.\nDo you want to proceed?") #define STR_DATAPILOT_SUBTOTAL NC_("STR_DATAPILOT_SUBTOTAL", "The source range contains subtotals which may distort the results. Use it anyway?") #define STR_PIVOT_TOTAL NC_("STR_PIVOT_TOTAL", "Total") @@ -171,7 +174,7 @@ #define STR_SELCOUNT NC_("STR_SELCOUNT", "Selected: %1, %2") // STR_SELCOUNT_ROWARG is %1 of STR_SELCOUNT. %d of STR_SELCOUNT_ROWARG is number of rows #define STR_SELCOUNT_ROWARG NNC_("STR_SELCOUNT_ROWARG", "%d row", "%d rows") -// STR_SELCOUNT_COLARG is %2 of STR_SELCOUNT. %d of STR_SELCOUNT_ROWARG is number of columns +// STR_SELCOUNT_COLARG is %2 of STR_SELCOUNT. %d of STR_SELCOUNT_COLARG is number of columns #define STR_SELCOUNT_COLARG NNC_("STR_SELCOUNT_COLARG", "%d column", "%d columns") #define STR_FILTER_SELCOUNT NC_("STR_FILTER_SELCOUNT", "%1 of %2 records found") #define STR_COLUMN NC_("STR_COLUMN", "Column") @@ -233,6 +236,8 @@ #define STR_MATRIXFRAGMENTERR NC_("STR_MATRIXFRAGMENTERR", "You cannot change only part of an array.") #define STR_PAGEHEADER NC_("STR_PAGEHEADER", "Header") #define STR_PAGEFOOTER NC_("STR_PAGEFOOTER", "Footer") +#define STR_HF_ENABLE_HEADER NC_("STR_HF_ENABLE_HEADER", "Enable Header") +#define STR_HF_ENABLE_FOOTER NC_("STR_HF_ENABLE_FOOTER", "Enable Footer") #define STR_TOO_MANY_COLUMNS_DATA_FORM NC_("STR_TOO_MANY_COLUMNS_DATA_FORM", "Too many columns in the data form.") /* BEGIN error constants and error strings. */ @@ -260,7 +265,7 @@ #define STR_LONG_ERR_ILL_ARG NC_("STR_LONG_ERR_ILL_ARG", "Error: Invalid argument") #define STR_LONG_ERR_ILL_PAR NC_("STR_LONG_ERR_ILL_PAR", "Error in parameter list") #define STR_LONG_ERR_ILL_CHAR NC_("STR_LONG_ERR_ILL_CHAR", "Error: Invalid character") -#define STR_LONG_ERR_PAIR NC_("STR_LONG_ERR_PAIR", "Error: in bracketing") +#define STR_LONG_ERR_PAIR NC_("STR_LONG_ERR_PAIR", "Error in bracketing") #define STR_LONG_ERR_OP_EXP NC_("STR_LONG_ERR_OP_EXP", "Error: Operator missing") #define STR_LONG_ERR_VAR_EXP NC_("STR_LONG_ERR_VAR_EXP", "Error: Variable missing") #define STR_LONG_ERR_CODE_OVF NC_("STR_LONG_ERR_CODE_OVF", "Error: Formula overflow") @@ -269,6 +274,7 @@ #define STR_LONG_ERR_MATRIX_SIZE NC_("STR_LONG_ERR_MATRIX_SIZE", "Error: Array or matrix size") #define STR_LONG_ERR_CIRC_REF NC_("STR_LONG_ERR_CIRC_REF", "Error: Circular reference") #define STR_LONG_ERR_NO_CONV NC_("STR_LONG_ERR_NO_CONV", "Error: Calculation does not converge") +#define STR_LONG_ERR_NOT_FUNC NC_("STR_LONG_ERR_NOT_FUNC", "Error: Attempted to call non-function") /* END error constants and error strings. */ #define STR_CELL_FILTER NC_("STR_CELL_FILTER", "Filter") @@ -371,7 +377,6 @@ #define STR_DOC_PRINTED NC_("STR_DOC_PRINTED", "Printed") #define STR_BY NC_("STR_BY", "by") #define STR_ON NC_("STR_ON", "on") -#define STR_RELOAD_TABLES NC_("STR_RELOAD_TABLES", "Automatic update of external links has been disabled.") #define STR_TRUST_DOCUMENT_WARNING NC_("STR_TRUST_DOCUMENT_WARNING", "Are you sure you trust this document?") #define STR_WEBSERVICE_WITH_LINKS_WARNING NC_("STR_WEBSERVICE_WITH_LINKS_WARNING", "Links to remote locations can be constructed that transmit local data to the remote server.") #define STR_REIMPORT_AFTER_LOAD NC_("STR_REIMPORT_AFTER_LOAD", "This file contains queries. The results of these queries were not saved.\nDo you want these queries to be repeated?") @@ -395,6 +400,7 @@ #define STR_QUICKHELP_REF NC_("STR_QUICKHELP_REF", "%1 R × %2 C") #define STR_FUNCTIONLIST_MORE NC_("STR_FUNCTIONLIST_MORE", "More...") #define STR_ERR_INVALID_AREA NC_("STR_ERR_INVALID_AREA", "Invalid range") +#define STR_ERR_HIDDEN_SHEET NC_("STR_ERR_HIDDEN_SHEET", "Target sheet is hidden") #define STR_CHARTTITLE NC_("STR_CHARTTITLE", "Chart Title") #define STR_AXISTITLE NC_("STR_AXISTITLE", "Axis Title") // Templates for data pilot tables. @@ -566,6 +572,7 @@ #define STR_QUERY_PIVOTTABLE_DELTAB NNC_("STR_QUERY_PIVOTTABLE_DELTAB", "The selected sheet contains source data of related pivot tables that will be lost.", "The %d selected sheets contain source data of related pivot tables that will be lost.") #define STR_ERR_NAME_INVALID_CELL_REF NC_("STR_ERR_NAME_INVALID_CELL_REF", "Invalid name. Reference to a cell, or a range of cells not allowed.") #define STR_ERR_LONG_LINK_FORMULA_NEEDING_CHECK NC_("STR_ERR_LONG_LINK_FORMULA_NEEDING_CHECK", "External content disabled.") +#define STR_LONG_ERR_SPILL NC_("STR_LONG_ERR_SPILL", "Error: Array result could not expand because it would overwrite non-empty cells.") #define STR_TEXTORIENTANGLE NC_("STR_TEXTORIENTANGLE", "Text orientation angle") #define STR_SHRINKTOFITCELL_ON NC_("STR_SHRINKTOFITCELL_ON", "Shrink to fit cell: On") #define STR_SHRINKTOFITCELL_OFF NC_("STR_SHRINKTOFITCELL_OFF", "Shrink to fit cell: Off") @@ -585,6 +592,7 @@ #define STR_UNDO_EDIT_SPARKLINE NC_("STR_UNDO_EDIT_SPARKLINE", "Edit Sparkline") #define STR_UNDO_THEME_CHANGE NC_("STR_UNDO_THEME_CHANGE", "Theme Change") #define STR_UNDO_THEME_COLOR_CHANGE NC_("STR_UNDO_THEME_COLOR_CHANGE", "Theme Color Change") +#define STR_UNDO_INSERT_SHEET_VIEW NC_("STR_UNDO_INSERT_SHEET_VIEW", "Insert Sheet View") #define STR_ERR_INSERT_CELLS NC_("STR_ERR_INSERT_CELLS", "Failed to insert cells") #define STR_SOLVER_ENGINE NC_("STR_SOLVER_ENGINE", "Solver Engine:") #define STR_SENSITIVITY NC_("STR_SENSITIVITY", "Sensitivity") @@ -605,6 +613,11 @@ #define STR_SHEET_VIEW_DEFAULT_VIEW_NAME NC_("STR_SHEET_VIEW_DEFAULT_VIEW_NAME", "Default View") #define STR_SHEET_VIEW_TEMPORARY_NAME_TEMPLATE NC_("STR_SHEET_VIEW_TEMPORARY_NAME_TEMPLATE", "Temporary View %1") +#define STR_WARN_ONLYACTIVESHEET_TITLE NC_("STR_WARN_ONLYACTIVESHEET_TITLE", "Warning") +#define STR_WARN_ONLYACTIVESHEET_TEXT NC_("STR_WARN_ONLYACTIVESHEET_TEXT", "Only the active sheet was saved.") +#define STR_WARN_ONLYACTIVESHEET_QUEST NC_("STR_WARN_ONLYACTIVESHEET_QUEST", "You are saving in the CSV text format, which means multiple sheets cannot be handled.") +#define STR_WARN_ONLYACTIVESHEET_BUTTON NC_("STR_WARN_ONLYACTIVESHEET_BUTTON", "Okay") + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/helpids.h b/sc/inc/helpids.h index 4bb54ea59eaf..fa74a8a3125e 100644 --- a/sc/inc/helpids.h +++ b/sc/inc/helpids.h @@ -353,6 +353,13 @@ inline constexpr OUString HID_FUNC_RGP = u"SC_HID_FUNC_RGP"_ustr; inline constexpr OUString HID_FUNC_RKP = u"SC_HID_FUNC_RKP"_ustr; inline constexpr OUString HID_FUNC_TREND = u"SC_HID_FUNC_TREND"_ustr; inline constexpr OUString HID_FUNC_VARIATION = u"SC_HID_FUNC_VARIATION"_ustr; +inline constexpr OUString HID_FUNC_IS_OMITTED_MS = u"SC_HID_FUNC_IS_OMITTED_MS"_ustr; +inline constexpr OUString HID_FUNC_BYCOL_MS = u"SC_HID_FUNC_BYCOL_MS"_ustr; +inline constexpr OUString HID_FUNC_BYROW_MS = u"SC_HID_FUNC_BYROW_MS"_ustr; +inline constexpr OUString HID_FUNC_MAKEARRAY_MS = u"SC_HID_FUNC_MAKEARRAY_MS"_ustr; +inline constexpr OUString HID_FUNC_MAP_MS = u"SC_HID_FUNC_MAP_MS"_ustr; +inline constexpr OUString HID_FUNC_REDUCE_MS = u"SC_HID_FUNC_REDUCE_MS"_ustr; +inline constexpr OUString HID_FUNC_SCAN_MS = u"SC_HID_FUNC_SCAN_MS"_ustr; inline constexpr OUString HID_FUNC_ANZAHL = u"SC_HID_FUNC_ANZAHL"_ustr; inline constexpr OUString HID_FUNC_ANZAHL2 = u"SC_HID_FUNC_ANZAHL2"_ustr; @@ -616,5 +623,7 @@ inline constexpr OUString HID_FUNC_UNIQUE_MS = u"SC_HID_FUNC_UNIQUE_MS"_ustr; inline constexpr OUString HID_FUNC_LET_MS = u"SC_HID_FUNC_LET_MS"_ustr; inline constexpr OUString HID_FUNC_WRAPCOLS_MS = u"SC_HID_FUNC_WRAPCOLS_MS"_ustr; inline constexpr OUString HID_FUNC_WRAPROWS_MS = u"SC_HID_FUNC_WRAPROWS_MS"_ustr; +inline constexpr OUString HID_FUNC_ARRAYTOTEXT_MS = u"SC_HID_FUNC_ARRAYTOTEXT_MS"_ustr; +inline constexpr OUString HID_FUNC_LAMBDA_MS = u"SC_HID_FUNC_LAMBDA_MS"_ustr; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/kahan.hxx b/sc/inc/kahan.hxx index 9616a6e9e76b..3dcb5e23dfc0 100644 --- a/sc/inc/kahan.hxx +++ b/sc/inc/kahan.hxx @@ -119,7 +119,7 @@ public: } /** - * Substracts a value to the sum using Kahan summation. + * Subtracts a value from the sum using Kahan summation. * @param fSum */ inline void subtract(const KahanSum& fSum) { add(-fSum); } diff --git a/sc/inc/linkuno.hxx b/sc/inc/linkuno.hxx index 855bb228432d..8bc979c250a0 100644 --- a/sc/inc/linkuno.hxx +++ b/sc/inc/linkuno.hxx @@ -437,6 +437,9 @@ public: virtual css::uno::Reference< css::sheet::XExternalDocLink > SAL_CALL addDocLink( const OUString& aDocName ) override; + virtual css::uno::Reference + SAL_CALL addSpecialDocLink(const OUString& aDocName, sal_Int16 nLinkType) override; + // XNameAccess virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override; diff --git a/sc/inc/miscuno.hxx b/sc/inc/miscuno.hxx index 075bf0046185..c54cf4aba645 100644 --- a/sc/inc/miscuno.hxx +++ b/sc/inc/miscuno.hxx @@ -143,6 +143,8 @@ public: const OUString& rName, sal_Int16 nDefault ); static sal_Int32 GetLongProperty( const css::uno::Reference< css::beans::XPropertySet>& xProp, const OUString& rName ); + static double GetDoubleProperty(const css::uno::Reference& xProp, + const OUString& rName, double fDefault = 0.0); template static EnumT GetEnumProperty( const css::uno::Reference< css::beans::XPropertySet>& xProp, const OUString& rName, EnumT nDefault ) diff --git a/sc/inc/mtvfunctions.hxx b/sc/inc/mtvfunctions.hxx index 75245ed9b2a2..47df2f88b392 100644 --- a/sc/inc/mtvfunctions.hxx +++ b/sc/inc/mtvfunctions.hxx @@ -373,28 +373,6 @@ ProcessElements1( return it; }; -template -void ProcessElements2(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse) -{ - typename StoreT::size_type nTopRow = 0, nDataSize = 0; - typename StoreT::iterator it = rStore.begin(), itEnd = rStore.end(); - for (; it != itEnd; ++it, nTopRow += nDataSize) - { - nDataSize = it->size; - switch (it->type) - { - case Blk1::block_type: - EachElem(*it, rFuncElem); - break; - case Blk2::block_type: - EachElem(*it, rFuncElem); - break; - default: - rFuncElse(it->type, nTopRow, nDataSize); - } - } -} - template void ProcessElements2Reverse(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse) { diff --git a/sc/inc/patattr.hxx b/sc/inc/patattr.hxx index 99aafa7d7c4e..d263a7b8c38f 100644 --- a/sc/inc/patattr.hxx +++ b/sc/inc/patattr.hxx @@ -70,6 +70,7 @@ class SC_DLLPUBLIC CellAttributeHelper final typedef std::unordered_map, o3tl::sorted_vector, RegisteredAttrMapHash> RegisteredAttrMap; SfxItemPool& mrSfxItemPool; + ScDocument* mpDocument; mutable ScPatternAttr* mpDefaultCellAttribute; mutable RegisteredAttrMap maRegisteredCellAttributes; mutable const ScPatternAttr* mpLastHit; @@ -80,11 +81,12 @@ class SC_DLLPUBLIC CellAttributeHelper final void doUnregister(const ScPatternAttr& rCandidate); public: - explicit CellAttributeHelper(SfxItemPool& rSfxItemPool); + explicit CellAttributeHelper(SfxItemPool& rSfxItemPool, ScDocument* pDocument = nullptr); ~CellAttributeHelper(); const ScPatternAttr& getDefaultCellAttribute() const; SfxItemPool& GetPool() const { return mrSfxItemPool; } + ScDocument* GetDocument() const { return mpDocument; } void CellStyleDeleted(const ScStyleSheet& rStyle); void CellStyleCreated(const ScDocument& rDoc, const OUString& rName); diff --git a/sc/inc/pch/precompiled_sc.hxx b/sc/inc/pch/precompiled_sc.hxx index c2ce76e8ea6c..6cec4de0a63e 100644 --- a/sc/inc/pch/precompiled_sc.hxx +++ b/sc/inc/pch/precompiled_sc.hxx @@ -154,7 +154,6 @@ #include #include #include -#include #include #include #include @@ -332,7 +331,6 @@ #include #include #include -#include #include #include #include @@ -538,7 +536,6 @@ #include #include #include -#include #include #include #include diff --git a/sc/inc/pch/precompiled_scui.hxx b/sc/inc/pch/precompiled_scui.hxx index 502a197c17df..2041fb6033b0 100644 --- a/sc/inc/pch/precompiled_scui.hxx +++ b/sc/inc/pch/precompiled_scui.hxx @@ -37,7 +37,6 @@ #include #include #include -#include #endif // PCH_LEVEL >= 2 #if PCH_LEVEL >= 3 #include diff --git a/sc/inc/pivot.hxx b/sc/inc/pivot.hxx index 8d3edba969fc..f06c4165dde0 100644 --- a/sc/inc/pivot.hxx +++ b/sc/inc/pivot.hxx @@ -84,6 +84,7 @@ struct ScDPLabelData bool mbDataLayout:1; bool mbRepeatItemLabels:1; bool mbCalculatedField:1; + bool mbIsDateDimension:1; ///< true = Source values are dates/times. struct Member { @@ -91,6 +92,8 @@ struct ScDPLabelData OUString maLayoutName; bool mbVisible; bool mbShowDetails; + double mfValue; ///< raw value (e.g. date serial), only meaningful when mbHasValue is true. + bool mbHasValue; Member(); diff --git a/sc/inc/pivot/PivotTableFormatOutput.hxx b/sc/inc/pivot/PivotTableFormatOutput.hxx index 42fe614451ad..22dbe11247af 100644 --- a/sc/inc/pivot/PivotTableFormatOutput.hxx +++ b/sc/inc/pivot/PivotTableFormatOutput.hxx @@ -45,6 +45,8 @@ struct FormatOutputField OUString aName; sal_Int32 nIndex = -1; bool bMatchesAll = false; + bool bSelected = true; + bool bHasSubtotal = false; bool bSet = false; }; @@ -54,6 +56,9 @@ struct FormatOutputEntry FormatType eType = FormatType::None; std::optional onTab = std::nullopt; std::shared_ptr pPattern; + bool bGrandRow = false; + bool bGrandColumn = false; + std::optional oOffset = std::nullopt; std::vector aRowOutputFields; std::vector aColumnOutputFields; @@ -90,6 +95,8 @@ class FormatOutput private: ScDPObject& mrObject; + bool tryHandleGrandTotals(ScDocument& rDocument, sc::FormatOutputEntry const& rEntry); + public: FormatOutput(ScDPObject& rObject) : mrObject(rObject) @@ -102,6 +109,15 @@ public: std::vector maRowLines; std::vector maColumnLines; + SCROW mnGrandTotalRow = -1; + SCCOL mnGrandTotalColumn = -1; + SCCOL mnTabStartColumn = -1; + SCROW mnTabStartRow = -1; + SCCOL mnDataStartColumn = -1; + SCROW mnDataStartRow = -1; + SCCOL mnTabEndColumn = -1; + SCROW mnTabEndRow = -1; + void setFormats(sc::PivotTableFormats const& rPivotTableFormats) { mpFormats.reset(new sc::PivotTableFormats(rPivotTableFormats)); @@ -113,6 +129,23 @@ public: void insertEmptyDataColumn(SCCOL nColPos, SCROW nRowPos); + void setGrandTotalPositions(SCROW nGrandTotalRow, SCCOL nGrandTotalColumn) + { + mnGrandTotalRow = nGrandTotalRow; + mnGrandTotalColumn = nGrandTotalColumn; + } + + void setDataArea(SCCOL nTabStartColumn, SCROW nTabStartRow, SCCOL nDataStartColumn, + SCROW nDataStartRow, SCCOL nTabEndColumn, SCROW nTabEndRow) + { + mnTabStartColumn = nTabStartColumn; + mnTabStartRow = nTabStartRow; + mnDataStartColumn = nDataStartColumn; + mnDataStartRow = nDataStartRow; + mnTabEndColumn = nTabEndColumn; + mnTabEndRow = nTabEndRow; + } + void apply(ScDocument& rDocument); void prepare(SCTAB nTab, std::vector const& rColumnFields, std::vector const& rRowFields, bool bColumnFieldIsDataOnly); diff --git a/sc/inc/pivot/PivotTableFormats.hxx b/sc/inc/pivot/PivotTableFormats.hxx index d569c6167e1f..4979f3d3c394 100644 --- a/sc/inc/pivot/PivotTableFormats.hxx +++ b/sc/inc/pivot/PivotTableFormats.hxx @@ -12,6 +12,7 @@ #include #include #include +#include #include namespace sc @@ -27,9 +28,10 @@ enum class FormatType /** Information to make a selection in the pivot table. */ struct Selection { - bool bSelected = false; + bool bSelected = true; sal_Int32 nField = 0; std::vector nIndices; + bool bHasSubtotal = false; }; /** Holds cell pattern attributes and a selection information to which cells in the pivot table @@ -41,9 +43,11 @@ struct PivotTableFormat bool bDataOnly = true; bool bLabelOnly = false; - bool bSelected = false; bool bOutline = false; + bool bGrandRow = false; + bool bGrandColumn = false; std::optional oFieldPosition = std::nullopt; + std::optional oOffset = std::nullopt; std::vector aSelections; std::shared_ptr pPattern; @@ -59,8 +63,6 @@ class PivotTableFormats public: void add(PivotTableFormat const& rPivotTableFormat) { maFormats.push_back(rPivotTableFormat); } - size_t size() const { return maFormats.size(); } - std::vector const& getVector() const { return maFormats; } }; } diff --git a/sc/inc/pivot/PivotTableResultTraverser.hxx b/sc/inc/pivot/PivotTableResultTraverser.hxx index fc47e595ac19..cd74e1ac90bb 100644 --- a/sc/inc/pivot/PivotTableResultTraverser.hxx +++ b/sc/inc/pivot/PivotTableResultTraverser.hxx @@ -18,12 +18,6 @@ namespace sc { -namespace pivot -{ -SC_DLLPUBLIC css::uno::Any -getMemberForLevel(css::uno::Reference const& xLevel, OUString const& rName); -} - /** Visitor interface for traversing the pivot table result tree structure. * * Defines the functions that are triggered with data, when the tree is traversed. diff --git a/sc/inc/pivot/StyleOutput.hxx b/sc/inc/pivot/StyleOutput.hxx new file mode 100644 index 000000000000..2e5ff7763c7a --- /dev/null +++ b/sc/inc/pivot/StyleOutput.hxx @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * 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 . + */ + +#pragma once + +#include +#include +#include + +#include + +class ScDocument; + +namespace sc::pivot +{ +/** Cell positions that describe the layout of the pivot table output area. + * + * The whole table spans from the tab start to the tab end position. The data (result) cells + * start at the data start position; the cells left of the data start column hold the row + * field members and the cells above the data start row hold the column field members, which + * begin at the member start position. */ +struct Geometry +{ + SCTAB mnTab = -1; + SCCOL mnTabStartCol = -1; + SCROW mnTabStartRow = -1; + SCCOL mnMemberStartCol = -1; + SCROW mnMemberStartRow = -1; + SCCOL mnDataStartCol = -1; + SCROW mnDataStartRow = -1; + SCCOL mnTabEndCol = -1; + SCROW mnTabEndRow = -1; + + size_t mnColumnFieldCount = 0; + size_t mnRowFieldCount = 0; +}; + +/** A cell with a field caption. When bFrame is true, the cell is part of the table area and + * carries a thin frame around it. */ +struct FieldCell +{ + SCCOL nCol = -1; + SCROW nRow = -1; + bool bFrame = false; +}; + +/** A cell holding the selected value of a page field. */ +struct PageFieldValueCell +{ + SCCOL nCol = -1; + SCROW nRow = -1; +}; + +/** One member of a column field, spanning the columns nStartCol to nEndCol in the header row + * nRow. nField is the position of the field among the column fields. */ +struct ColumnMemberSpan +{ + size_t nField = 0; + SCCOL nStartCol = -1; + SCCOL nEndCol = -1; + SCROW nRow = -1; +}; + +/** One member of a row field, spanning the rows nStartRow to nEndRow in the header column + * nCol. nField is the position of the field among the row fields. */ +struct RowMemberSpan +{ + size_t nField = 0; + SCCOL nCol = -1; + SCROW nStartRow = -1; + SCROW nEndRow = -1; +}; + +/** A column holding subtotal results. The header cells reach from nStartRow down to the row + * above the data start row, and the result cells fill the column below. bGrandTotal is true + * for the grand total column. */ +struct SubtotalColumn +{ + SCCOL nCol = -1; + SCROW nStartRow = -1; + bool bGrandTotal = false; +}; + +/** A row holding subtotal results. The header cells reach from nStartCol to the column left + * of the data start column, and the result cells fill the row to the right. bGrandTotal is + * true for the grand total row. */ +struct SubtotalRow +{ + SCROW nRow = -1; + SCCOL nStartCol = -1; + bool bGrandTotal = false; +}; + +/** A row field member cell with indented content. The indent value is in twips. */ +struct Indent +{ + SCCOL nCol = -1; + SCROW nRow = -1; + tools::Long nIndent = 0; +}; + +/** A row field member cell that shows an expand or collapse button. */ +struct Expander +{ + SCCOL nCol = -1; + SCROW nRow = -1; + ScMF nFlags = ScMF::NONE; +}; + +/** Collects the sections of a pivot table while the table content is written to the sheet, and + * then draws the whole visual formatting of the pivot table (block frames, member indents and + * the expand and collapse buttons) in one pass over the collected sections. */ +class StyleOutput +{ +private: + ScDocument& mrDocument; + + Geometry maGeometry; + + std::vector maFieldCells; + std::vector maPageFieldValueCells; + std::vector maColumnMemberSpans; + std::vector maRowMemberSpans; + std::vector maSubtotalColumns; + std::vector maSubtotalRows; + std::vector maIndentCells; + std::vector maExpanderCells; + +public: + StyleOutput(ScDocument& rDocument) + : mrDocument(rDocument) + { + } + + void setGeometry(Geometry const& rGeometry) { maGeometry = rGeometry; } + + void addFieldCell(SCCOL nCol, SCROW nRow, bool bFrame) + { + maFieldCells.push_back(FieldCell{ nCol, nRow, bFrame }); + } + + void addPageFieldValueCell(SCCOL nCol, SCROW nRow) + { + maPageFieldValueCells.push_back(PageFieldValueCell{ nCol, nRow }); + } + + void addColumnMemberSpan(size_t nField, SCCOL nStartCol, SCCOL nEndCol, SCROW nRow) + { + maColumnMemberSpans.push_back(ColumnMemberSpan{ nField, nStartCol, nEndCol, nRow }); + } + + void addRowMemberSpan(size_t nField, SCCOL nCol, SCROW nStartRow, SCROW nEndRow) + { + maRowMemberSpans.push_back(RowMemberSpan{ nField, nCol, nStartRow, nEndRow }); + } + + void addSubtotalColumn(SCCOL nCol, SCROW nStartRow, bool bGrandTotal) + { + maSubtotalColumns.push_back(SubtotalColumn{ nCol, nStartRow, bGrandTotal }); + } + + void addSubtotalRow(SCROW nRow, SCCOL nStartCol, bool bGrandTotal) + { + maSubtotalRows.push_back(SubtotalRow{ nRow, nStartCol, bGrandTotal }); + } + + void addIndent(SCCOL nCol, SCROW nRow, tools::Long nIndent) + { + maIndentCells.push_back(Indent{ nCol, nRow, nIndent }); + } + + void addExpander(SCCOL nCol, SCROW nRow, ScMF nFlags) + { + maExpanderCells.push_back(Expander{ nCol, nRow, nFlags }); + } + + void clear(); + void apply(); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/inc/postit.hxx b/sc/inc/postit.hxx index 2e54e64c44b5..e945bfa168db 100644 --- a/sc/inc/postit.hxx +++ b/sc/inc/postit.hxx @@ -27,6 +27,7 @@ #include #include +#include class EditTextObject; class OutlinerParaObject; @@ -37,6 +38,35 @@ class ScDocument; namespace tools { class Rectangle; } struct ScCaptionInitData; +/** A single entry in a threaded comment (root or reply). + Maps to CT_ThreadedComment in [MS-XLSX] section 2.6.205. */ +struct ScThreadedCommentEntry +{ + OUString maGuid; /// Unique ID (ST_Guid). + OUString maPersonId; /// Reference to person in ScDocument person list. + OUString maDateTime; /// ISO 8601 / xsd:dateTime (UTC). + OUString maText; /// Text of this entry. +}; + +/** Threaded-comment metadata attached to a ScPostIt. + When present the note participates in the Excel "threaded comments" feature. */ +struct ScThreadedCommentData +{ + ScThreadedCommentEntry maRoot; /// Root entry (guid, personId, dateTime). + bool mbDone = false; /// Resolved / done flag. + std::vector maReplies; /// Reply chain. +}; + +/** Person metadata for threaded comments. + Maps to CT_Person in [MS-XLSX] section 2.6.203. */ +struct ScPersonData +{ + OUString maId; /// Unique person GUID. + OUString maDisplayName; /// Display name. + OUString maUserId; /// Provider-specific user ID. + OUString maProviderId; /// Identity provider ID. +}; + /** Internal data for a cell annotation. */ struct ScNoteData { @@ -157,6 +187,16 @@ public: static OString NoteRangeToJsonString(const ScDocument& rDoc, const ScAddress& rPos); + /** Returns true if this note has been resolved (threaded comment "done" flag). */ + bool IsResolved() const { return mpThreadedCommentData && mpThreadedCommentData->mbDone; } + /** Sets the resolved state. Creates threaded comment data if not yet present. */ + void SetResolved(bool bResolved); + + /** Returns the threaded comment data, or nullptr if this is a classic note. */ + const ScThreadedCommentData* GetThreadedCommentData() const { return mpThreadedCommentData.get(); } + /** Sets (replaces) the threaded comment data. Pass nullptr to remove. */ + SC_DLLPUBLIC void SetThreadedCommentData(std::unique_ptr pData); + private: ScPostIt( const ScPostIt& ) = delete; ScPostIt& operator=( const ScPostIt& ) = delete; @@ -172,6 +212,7 @@ private: ScDocument& mrDoc; /// Parent document containing the note. mutable ScNoteData maNoteData; /// Note data with pointer to caption object. sal_uInt32 mnPostItId; + std::unique_ptr mpThreadedCommentData; /// Threaded comment metadata (nullable). }; class GenerateNoteCaption diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx index ad130549cb0f..9193ae4d9e1c 100644 --- a/sc/inc/queryentry.hxx +++ b/sc/inc/queryentry.hxx @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -55,7 +56,7 @@ struct SC_DLLPUBLIC ScQueryEntry final bool operator== (const Item& r) const; }; - typedef std::vector QueryItemsType; + typedef boost::container::small_vector QueryItemsType; bool bDoQuery; SCCOLROW nField; diff --git a/sc/inc/queryparam.hxx b/sc/inc/queryparam.hxx index 913050521232..0d9bf09338c1 100644 --- a/sc/inc/queryparam.hxx +++ b/sc/inc/queryparam.hxx @@ -24,6 +24,7 @@ #include "queryentry.hxx" #include "types.hxx" +#include #include #include @@ -64,10 +65,8 @@ struct SAL_DLLPUBLIC_RTTI ScQueryParamBase void FillInExcelSyntax( svl::SharedStringPool& rPool, const OUString& aCellStr, SCSIZE nIndex, ScInterpreterContext* pContext ); -protected: - typedef std::vector EntriesType; - -public: + static constexpr size_t MAXQUERY = 8; + typedef boost::container::small_vector EntriesType; typedef EntriesType::const_iterator const_iterator; const_iterator begin() const; diff --git a/sc/inc/rangelst.hxx b/sc/inc/rangelst.hxx index f1d33eb63024..0044a68afbe4 100644 --- a/sc/inc/rangelst.hxx +++ b/sc/inc/rangelst.hxx @@ -71,7 +71,6 @@ public: const ScRange* Find( const ScAddress& ) const; ScRange* Find( const ScAddress& ); bool operator==( const ScRangeList& ) const; - bool operator!=( const ScRangeList& r ) const; bool Intersects( const ScRange& ) const; bool Contains( const ScRange& ) const; sal_uInt64 GetCellCount() const; diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx index 881a2e876bda..799a22e0a246 100644 --- a/sc/inc/rangenam.hxx +++ b/sc/inc/rangenam.hxx @@ -68,7 +68,7 @@ public: private: OUString aName; - OUString aUpperName; // #i62977# for faster searching (aName is never modified after ctor) + OUString aUpperName; // #i62977# for faster searching, always the upper-case form of aName OUString maNewName; ///< used for formulas after changing names in the dialog std::unique_ptr pCode; @@ -104,6 +104,11 @@ public: * copies. */ ScRangeData( const ScRangeData& rScRangeData, ScDocument* pDocument = nullptr, const ScAddress* pPos = nullptr ); + /** Takes the values of rData, including the name and the index, and + moves the token code out of rData. The document reference is kept + unchanged. */ + ScRangeData& operator=( ScRangeData&& rData ); + SC_DLLPUBLIC ~ScRangeData(); bool operator== (const ScRangeData& rData) const; @@ -219,7 +224,7 @@ public: void UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY); /** Compile those names that couldn't be resolved during loading and - inserting because they may have referred a name that was inserted later. + inserting because they may have referred to a name that was inserted later. */ void CompileUnresolvedXML( sc::CompileFormulaContext& rCxt ); @@ -250,9 +255,9 @@ public: bool empty() const { return m_Data.empty(); } /** Insert object into set. - @ATTENTION: The underlying ::std::map::insert(p) takes - ownership of p and if it can't insert it deletes the object! So, if - this insert here returns false the object where p pointed to is gone! + If an entry with the same upper-case name already exists, the values + of p are moved into that existing entry and pointers held to the + existing entry stay valid. @param bReuseFreeIndex If the ScRangeData p points to has an index value of 0: @@ -260,8 +265,11 @@ public: If `FALSE` then assign a new index slot. The Manage Names dialog uses this so that deleting and adding ranges in the same run is guaranteed to not reuse previously assigned indexes. + + @return the entry that now holds the values of p, or nullptr if p + was null. */ - SC_DLLPUBLIC bool insert( ScRangeData* p, bool bReuseFreeIndex = true ); + SC_DLLPUBLIC ScRangeData* insert( std::unique_ptr p, bool bReuseFreeIndex = true ); void erase(const ScRangeData& r); void erase(const OUString& rName); diff --git a/sc/inc/rangeutl.hxx b/sc/inc/rangeutl.hxx index 2f23f84432cb..28b8ec0dc96a 100644 --- a/sc/inc/rangeutl.hxx +++ b/sc/inc/rangeutl.hxx @@ -256,7 +256,7 @@ public: class SC_DLLPUBLIC ScAreaNameIterator { private: - ScRangeName* pRangeName; + ScRangeName& rRangeName; ScDBCollection* pDBCollection; ScRangeName::const_iterator maRNPos; ScRangeName::const_iterator maRNEnd; @@ -283,7 +283,7 @@ struct SC_DLLPUBLIC ScRangeUpdater deleted sheets, within the deleted range to the front of that or set to 0 (as there is always at least one sheet in a document) if the position would result in a negative value, e.g. if position was 0 and (only) - sheet 0 is deleted it would had become -1. + sheet 0 is deleted it would have become -1. */ static void UpdateDeleteTab(ScAddress& rAddr, const sc::RefUpdateDeleteTabContext& rCxt); }; diff --git a/sc/inc/refdata.hxx b/sc/inc/refdata.hxx index b4740417b98c..3e2ab3023f3e 100644 --- a/sc/inc/refdata.hxx +++ b/sc/inc/refdata.hxx @@ -111,7 +111,6 @@ public: static void PutInOrder( ScSingleRefData& rRef1, ScSingleRefData& rRef2, const ScAddress& rPos ); bool operator==( const ScSingleRefData& ) const; - bool operator!=( const ScSingleRefData& ) const; #if DEBUG_FORMULA_COMPILER void Dump( int nIndent = 0 ) const; diff --git a/sc/inc/reftokenhelper.hxx b/sc/inc/reftokenhelper.hxx index e0e3e0f68c07..8445311043dd 100644 --- a/sc/inc/reftokenhelper.hxx +++ b/sc/inc/reftokenhelper.hxx @@ -28,6 +28,7 @@ class ScDocument; class ScRangeList; struct ScComplexRefData; +struct ScSingleRefData; namespace ScRefTokenHelper { @@ -62,6 +63,8 @@ namespace ScRefTokenHelper ScTokenRef createRefToken(const ScDocument& rDoc, const ScAddress& rAddr); ScTokenRef createRefToken(const ScDocument& rDoc, const ScRange& rRange); + + SC_DLLPUBLIC ScSingleRefData* getSingleRef(formula::FormulaToken*); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/refupdatecontext.hxx b/sc/inc/refupdatecontext.hxx index 7789dfdc3a9e..147bbfa7bcd5 100644 --- a/sc/inc/refupdatecontext.hxx +++ b/sc/inc/refupdatecontext.hxx @@ -45,6 +45,18 @@ private: UpdatedNamesType maUpdatedNames; }; +/** + * Accumulates information about #REF! errors created during a single + * reference-update pass (e.g. one row/column/sheet deletion). Lives on + * the RefUpdate*Context for the duration of that operation; its value + * is passed to the UI layer via an ScHint after the pass completes. + */ +struct RefErrorContext +{ + bool mbErrorCreated = false; + ScAddress maFormulaCell; ///< first formula cell with new #REF! error +}; + /** * Context for reference update during shifting, moving or copying of cell * ranges. @@ -83,6 +95,11 @@ struct RefUpdateContext ColumnBlockPositionSet* mpBlockPos; // not owning + /// First #REF! error created by this update pass, if any. + /// Mutable because it is output accumulated during traversal, + /// not part of the logical input configuration. + mutable RefErrorContext maRefErrors; + RefUpdateContext(ScDocument& rDoc, ScDocument* pClipdoc = nullptr); bool isInserted() const; @@ -135,6 +152,11 @@ struct SC_DLLPUBLIC RefUpdateDeleteTabContext SCTAB mnSheets; UpdatedRangeNames maUpdatedNames; + /// First #REF! error created by this sheet-delete pass, if any. + /// Mutable because it is output accumulated during traversal, + /// not part of the logical input configuration. + mutable RefErrorContext maRefErrors; + RefUpdateDeleteTabContext(ScDocument& rDoc, SCTAB nInsertPos, SCTAB nSheets); }; diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc index 82f78f6607f0..8c196db2a58f 100644 --- a/sc/inc/sc.hrc +++ b/sc/inc/sc.hrc @@ -136,7 +136,6 @@ class SvxZoomSliderItem; #define SID_DRAW_NOTEEDIT (SC_VIEW_START + 81) #define SID_CHOOSE_DESIGN (SC_VIEW_START + 82) -#define SID_EURO_CONVERTER (SC_VIEW_START + 83) //See include/sfx2/sfxsids.hrc for reserved usage of (SC_VIEW_START + 84) #define SID_EXTERNAL_SOURCE (SC_VIEW_START + 85) @@ -287,12 +286,11 @@ class SvxZoomSliderItem; #define FID_TOGGLEFORMULA (VIEW_MENU_START + 10) #define FID_NEW_SHEET_VIEW (VIEW_MENU_START + 11) #define FID_REMOVE_SHEET_VIEW (VIEW_MENU_START + 12) -#define FID_SWITCH_TO_NEXT_SHEET_VIEW (VIEW_MENU_START + 13) -#define FID_SWITCH_TO_PREVIOUS_SHEET_VIEW (VIEW_MENU_START + 14) +// FREE (VIEW_MENU_START + 13) +// FREE (VIEW_MENU_START + 14) #define FID_EXIT_SHEET_VIEW (VIEW_MENU_START + 15) #define FID_SELECT_SHEET_VIEW (VIEW_MENU_START + 16) -#define FID_CURRENT_SHEET_VIEW TypedWhichId(VIEW_MENU_START + 17) - +// FREE (VIEW_MENU_START + 17) #define FID_CHG_ACCEPT (VIEW_MENU_START + 18)// DANGER DIRTY ID #define FID_CHG_COMMENT (VIEW_MENU_START + 19)// DANGER DIRTY ID @@ -467,6 +465,8 @@ class SvxZoomSliderItem; #define SID_INSERT_MATRIX (SID_API_SLOTS+1) #define SID_DELETE_NOTE (SID_API_SLOTS+2) +#define SID_INSERT_THREADED_COMMENT (SID_API_SLOTS+3) +#define SID_RESOLVE_THREADED_COMMENT (SID_API_SLOTS+4) #define SID_PREVIEW_START (SID_API_SLOTS+20) #define SID_PREVIEW_NEXT (SID_PREVIEW_START) @@ -476,7 +476,11 @@ class SvxZoomSliderItem; #define SID_PREVIEW_CLOSE (SID_PREVIEW_START+7) #define SID_PREVIEW_MARGIN (SID_PREVIEW_START+8) #define SID_PREVIEW_SCALINGFACTOR TypedWhichId(SID_PREVIEW_START+9) -#define SID_PREVIEW_END (SID_PREVIEW_START+10) +#define SID_TOGGLEPRINTGRID (SID_PREVIEW_START+10) +#define SID_TOGGLEPRINTCOLROWHEADER (SID_PREVIEW_START+11) +#define SID_TOGGLEPRINTCOMMENTS (SID_PREVIEW_START+12) +#define SID_TOGGLEPRINTZEROVALUES (SID_PREVIEW_START+13) +#define SID_PREVIEW_END (SID_PREVIEW_START+14) // with SID_KEYFUNC_START defined in include/sfx2/sfxsids.hrc there is a risk of // adding entries that cause an overlap here @@ -642,6 +646,7 @@ static_assert(SID_PREVIEW_END < SID_KEYFUNC_START, "calc slots ids trampling inf #define SID_DATABASE_SETTINGS (SID_NEW_SLOTS+119) #define SID_INSERT_CALCTABLE (SID_NEW_SLOTS+120) #define SID_REMOVE_CALCTABLE (SID_NEW_SLOTS+121) +#define SID_TABLE_STYLES (SID_NEW_SLOTS+122) // idl parameter diff --git a/sc/inc/scabstdlg.hxx b/sc/inc/scabstdlg.hxx index cf9537f46d69..647fb6df8c56 100644 --- a/sc/inc/scabstdlg.hxx +++ b/sc/inc/scabstdlg.hxx @@ -536,7 +536,6 @@ public: virtual VclPtr CreateScTabBgColorDlg(weld::Window* pParent, const OUString& rTitle, //Dialog Title - const OUString& rTabBgColorNoColorText, //Label for no tab color const Color& rDefaultColor) = 0; //Currently selected Color virtual VclPtr CreateScImportOptionsDlg(weld::Window* pParent, bool bAscii, diff --git a/sc/inc/scfuncs.hrc b/sc/inc/scfuncs.hrc index 6c765c304bf9..e0ffbe28472b 100644 --- a/sc/inc/scfuncs.hrc +++ b/sc/inc/scfuncs.hrc @@ -33,4426 +33,4522 @@ */ // -=*# Resource for function DCOUNT #*=- -const TranslateId SC_OPCODE_DB_COUNT_ARY[] = +const TranslateId ocDB_COUNT_ARY[] = { - NC_("SC_OPCODE_DB_COUNT", "Counts the cells of a data range whose contents match the search criteria."), - NC_("SC_OPCODE_DB_COUNT", "Database"), - NC_("SC_OPCODE_DB_COUNT", "The range of cells containing data."), - NC_("SC_OPCODE_DB_COUNT", "Database field"), - NC_("SC_OPCODE_DB_COUNT", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_COUNT", "Search criteria"), - NC_("SC_OPCODE_DB_COUNT", "Defines the cell range containing the search criteria.") + NC_("ocDB_COUNT", "Counts the cells of a data range whose contents match the search criteria."), + NC_("ocDB_COUNT", "Database"), + NC_("ocDB_COUNT", "The range of cells containing data."), + NC_("ocDB_COUNT", "Database field"), + NC_("ocDB_COUNT", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_COUNT", "Search criteria"), + NC_("ocDB_COUNT", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DCOUNTA #*=- -const TranslateId SC_OPCODE_DB_COUNT_2_ARY[] = +const TranslateId ocDB_COUNT_2_ARY[] = { - NC_("SC_OPCODE_DB_COUNT_2", "Counts all non-blank cells of a data range where the content corresponds to the search criteria."), - NC_("SC_OPCODE_DB_COUNT_2", "Database"), - NC_("SC_OPCODE_DB_COUNT_2", "The range of cells containing data."), - NC_("SC_OPCODE_DB_COUNT_2", "Database field"), - NC_("SC_OPCODE_DB_COUNT_2", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_COUNT_2", "Search criteria"), - NC_("SC_OPCODE_DB_COUNT_2", "Defines the cell range containing the search criteria.") + NC_("ocDB_COUNT_2", "Counts all non-blank cells of a data range where the content corresponds to the search criteria."), + NC_("ocDB_COUNT_2", "Database"), + NC_("ocDB_COUNT_2", "The range of cells containing data."), + NC_("ocDB_COUNT_2", "Database field"), + NC_("ocDB_COUNT_2", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_COUNT_2", "Search criteria"), + NC_("ocDB_COUNT_2", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DAVERAGE #*=- -const TranslateId SC_OPCODE_DB_AVERAGE_ARY[] = +const TranslateId ocDB_AVERAGE_ARY[] = { - NC_("SC_OPCODE_DB_AVERAGE", "Returns the average value of all the cells of a data range whose contents match the search criteria."), - NC_("SC_OPCODE_DB_AVERAGE", "Database"), - NC_("SC_OPCODE_DB_AVERAGE", "The range of cells containing data."), - NC_("SC_OPCODE_DB_AVERAGE", "Database field"), - NC_("SC_OPCODE_DB_AVERAGE", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_AVERAGE", "Search criteria"), - NC_("SC_OPCODE_DB_AVERAGE", "Defines the cell range containing the search criteria.") + NC_("ocDB_AVERAGE", "Returns the average value of all the cells of a data range whose contents match the search criteria."), + NC_("ocDB_AVERAGE", "Database"), + NC_("ocDB_AVERAGE", "The range of cells containing data."), + NC_("ocDB_AVERAGE", "Database field"), + NC_("ocDB_AVERAGE", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_AVERAGE", "Search criteria"), + NC_("ocDB_AVERAGE", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DGET #*=- -const TranslateId SC_OPCODE_DB_GET_ARY[] = +const TranslateId ocDB_GET_ARY[] = { - NC_("SC_OPCODE_DB_GET", "Defines the contents of the cell of a data range which matches the search criteria."), - NC_("SC_OPCODE_DB_GET", "Database"), - NC_("SC_OPCODE_DB_GET", "The range of cells containing data."), - NC_("SC_OPCODE_DB_GET", "Database field"), - NC_("SC_OPCODE_DB_GET", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_GET", "Search criteria"), - NC_("SC_OPCODE_DB_GET", "Defines the cell range containing the search criteria.") + NC_("ocDB_GET", "Defines the contents of the cell of a data range which matches the search criteria."), + NC_("ocDB_GET", "Database"), + NC_("ocDB_GET", "The range of cells containing data."), + NC_("ocDB_GET", "Database field"), + NC_("ocDB_GET", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_GET", "Search criteria"), + NC_("ocDB_GET", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DMAX #*=- -const TranslateId SC_OPCODE_DB_MAX_ARY[] = +const TranslateId ocDB_MAX_ARY[] = { - NC_("SC_OPCODE_DB_MAX", "Returns the maximum value from all of the cells of a data range which correspond to the search criteria."), - NC_("SC_OPCODE_DB_MAX", "Database"), - NC_("SC_OPCODE_DB_MAX", "The range of cells containing data."), - NC_("SC_OPCODE_DB_MAX", "Database field"), - NC_("SC_OPCODE_DB_MAX", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_MAX", "Search criteria"), - NC_("SC_OPCODE_DB_MAX", "Defines the cell range containing the search criteria.") + NC_("ocDB_MAX", "Returns the maximum value from all of the cells of a data range which correspond to the search criteria."), + NC_("ocDB_MAX", "Database"), + NC_("ocDB_MAX", "The range of cells containing data."), + NC_("ocDB_MAX", "Database field"), + NC_("ocDB_MAX", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_MAX", "Search criteria"), + NC_("ocDB_MAX", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DMIN #*=- -const TranslateId SC_OPCODE_DB_MIN_ARY[] = +const TranslateId ocDB_MIN_ARY[] = { - NC_("SC_OPCODE_DB_MIN", "Returns the minimum of all cells of a data range where the contents correspond to the search criteria."), - NC_("SC_OPCODE_DB_MIN", "Database"), - NC_("SC_OPCODE_DB_MIN", "The range of cells containing data."), - NC_("SC_OPCODE_DB_MIN", "Database field"), - NC_("SC_OPCODE_DB_MIN", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_MIN", "Search criteria"), - NC_("SC_OPCODE_DB_MIN", "Defines the cell range containing the search criteria.") + NC_("ocDB_MIN", "Returns the minimum of all cells of a data range where the contents correspond to the search criteria."), + NC_("ocDB_MIN", "Database"), + NC_("ocDB_MIN", "The range of cells containing data."), + NC_("ocDB_MIN", "Database field"), + NC_("ocDB_MIN", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_MIN", "Search criteria"), + NC_("ocDB_MIN", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DPRODUCT #*=- -const TranslateId SC_OPCODE_DB_PRODUCT_ARY[] = +const TranslateId ocDB_PRODUCT_ARY[] = { - NC_("SC_OPCODE_DB_PRODUCT", "Multiplies all cells of a data range where the contents match the search criteria."), - NC_("SC_OPCODE_DB_PRODUCT", "Database"), - NC_("SC_OPCODE_DB_PRODUCT", "The range of cells containing data."), - NC_("SC_OPCODE_DB_PRODUCT", "Database field"), - NC_("SC_OPCODE_DB_PRODUCT", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_PRODUCT", "Search criteria"), - NC_("SC_OPCODE_DB_PRODUCT", "Defines the cell range containing the search criteria.") + NC_("ocDB_PRODUCT", "Multiplies all cells of a data range where the contents match the search criteria."), + NC_("ocDB_PRODUCT", "Database"), + NC_("ocDB_PRODUCT", "The range of cells containing data."), + NC_("ocDB_PRODUCT", "Database field"), + NC_("ocDB_PRODUCT", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_PRODUCT", "Search criteria"), + NC_("ocDB_PRODUCT", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DSTDEV #*=- -const TranslateId SC_OPCODE_DB_STD_DEV_ARY[] = +const TranslateId ocDB_STD_DEV_ARY[] = { - NC_("SC_OPCODE_DB_STD_DEV", "Calculates the standard deviation of all cells in a data range whose contents match the search criteria."), - NC_("SC_OPCODE_DB_STD_DEV", "Database"), - NC_("SC_OPCODE_DB_STD_DEV", "The range of cells containing data."), - NC_("SC_OPCODE_DB_STD_DEV", "Database field"), - NC_("SC_OPCODE_DB_STD_DEV", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_STD_DEV", "Search criteria"), - NC_("SC_OPCODE_DB_STD_DEV", "Defines the cell range containing the search criteria.") + NC_("ocDB_STD_DEV", "Calculates the standard deviation of all cells in a data range whose contents match the search criteria."), + NC_("ocDB_STD_DEV", "Database"), + NC_("ocDB_STD_DEV", "The range of cells containing data."), + NC_("ocDB_STD_DEV", "Database field"), + NC_("ocDB_STD_DEV", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_STD_DEV", "Search criteria"), + NC_("ocDB_STD_DEV", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DSTDEVP #*=- -const TranslateId SC_OPCODE_DB_STD_DEV_P_ARY[] = +const TranslateId ocDB_STD_DEV_P_ARY[] = { - NC_("SC_OPCODE_DB_STD_DEV_P", "Returns the standard deviation with regards to the population of all cells of a data range matching the search criteria."), - NC_("SC_OPCODE_DB_STD_DEV_P", "Database"), - NC_("SC_OPCODE_DB_STD_DEV_P", "The range of cells containing data."), - NC_("SC_OPCODE_DB_STD_DEV_P", "Database field"), - NC_("SC_OPCODE_DB_STD_DEV_P", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_STD_DEV_P", "Search criteria"), - NC_("SC_OPCODE_DB_STD_DEV_P", "Defines the cell range containing the search criteria.") + NC_("ocDB_STD_DEV_P", "Returns the standard deviation with regards to the population of all cells of a data range matching the search criteria."), + NC_("ocDB_STD_DEV_P", "Database"), + NC_("ocDB_STD_DEV_P", "The range of cells containing data."), + NC_("ocDB_STD_DEV_P", "Database field"), + NC_("ocDB_STD_DEV_P", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_STD_DEV_P", "Search criteria"), + NC_("ocDB_STD_DEV_P", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DSUM #*=- -const TranslateId SC_OPCODE_DB_SUM_ARY[] = +const TranslateId ocDB_SUM_ARY[] = { - NC_("SC_OPCODE_DB_SUM", "Adds all the cells of a data range where the contents match the search criteria."), - NC_("SC_OPCODE_DB_SUM", "Database"), - NC_("SC_OPCODE_DB_SUM", "The range of cells containing data."), - NC_("SC_OPCODE_DB_SUM", "Database field"), - NC_("SC_OPCODE_DB_SUM", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_SUM", "Search criteria"), - NC_("SC_OPCODE_DB_SUM", "Defines the cell range containing the search criteria.") + NC_("ocDB_SUM", "Adds all the cells of a data range where the contents match the search criteria."), + NC_("ocDB_SUM", "Database"), + NC_("ocDB_SUM", "The range of cells containing data."), + NC_("ocDB_SUM", "Database field"), + NC_("ocDB_SUM", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_SUM", "Search criteria"), + NC_("ocDB_SUM", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DVAR #*=- -const TranslateId SC_OPCODE_DB_VAR_ARY[] = +const TranslateId ocDB_VAR_ARY[] = { - NC_("SC_OPCODE_DB_VAR", "Determines the variance of all the cells in a data range where the contents match the search criteria."), - NC_("SC_OPCODE_DB_VAR", "Database"), - NC_("SC_OPCODE_DB_VAR", "The range of cells containing data."), - NC_("SC_OPCODE_DB_VAR", "Database field"), - NC_("SC_OPCODE_DB_VAR", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_VAR", "Search criteria"), - NC_("SC_OPCODE_DB_VAR", "Defines the cell range containing the search criteria.") + NC_("ocDB_VAR", "Determines the variance of all the cells in a data range where the contents match the search criteria."), + NC_("ocDB_VAR", "Database"), + NC_("ocDB_VAR", "The range of cells containing data."), + NC_("ocDB_VAR", "Database field"), + NC_("ocDB_VAR", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_VAR", "Search criteria"), + NC_("ocDB_VAR", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DVARP #*=- -const TranslateId SC_OPCODE_DB_VAR_P_ARY[] = +const TranslateId ocDB_VAR_P_ARY[] = { - NC_("SC_OPCODE_DB_VAR_P", "Determines variance of a population based on all cells in a data range where contents match the search criteria."), - NC_("SC_OPCODE_DB_VAR_P", "Database"), - NC_("SC_OPCODE_DB_VAR_P", "The range of cells containing data."), - NC_("SC_OPCODE_DB_VAR_P", "Database field"), - NC_("SC_OPCODE_DB_VAR_P", "Indicates which database field (column) is to be used for the search criteria."), - NC_("SC_OPCODE_DB_VAR_P", "Search criteria"), - NC_("SC_OPCODE_DB_VAR_P", "Defines the cell range containing the search criteria.") + NC_("ocDB_VAR_P", "Determines variance of a population based on all cells in a data range where contents match the search criteria."), + NC_("ocDB_VAR_P", "Database"), + NC_("ocDB_VAR_P", "The range of cells containing data."), + NC_("ocDB_VAR_P", "Database field"), + NC_("ocDB_VAR_P", "Indicates which database field (column) is to be used for the search criteria."), + NC_("ocDB_VAR_P", "Search criteria"), + NC_("ocDB_VAR_P", "Defines the cell range containing the search criteria.") }; // -=*# Resource for function DATE #*=- -const TranslateId SC_OPCODE_GET_DATE_ARY[] = +const TranslateId ocGET_DATE_ARY[] = { - NC_("SC_OPCODE_GET_DATE", "Provides an internal number for the date given."), - NC_("SC_OPCODE_GET_DATE", "Year"), - NC_("SC_OPCODE_GET_DATE", "An integer between 1583 and 9956 or 0 and 99 (19xx or 20xx depending on the defined option)."), - NC_("SC_OPCODE_GET_DATE", "Month"), - NC_("SC_OPCODE_GET_DATE", "An integer between 1 and 12 representing the month."), - NC_("SC_OPCODE_GET_DATE", "Day"), - NC_("SC_OPCODE_GET_DATE", "An integer between 1 and 31 representing the day of the month.") + NC_("ocGET_DATE", "Provides an internal number for the date given."), + NC_("ocGET_DATE", "Year"), + NC_("ocGET_DATE", "An integer between 1583 and 9956 or 0 and 99 (19xx or 20xx depending on the defined option)."), + NC_("ocGET_DATE", "Month"), + NC_("ocGET_DATE", "An integer between 1 and 12 representing the month. Values out of bounds will roll over the date, computing the result by adding months and days as necessary."), + NC_("ocGET_DATE", "Day"), + NC_("ocGET_DATE", "An integer between 1 and 31 representing the day of the month. Values out of bounds will roll over the date, computing the result by adding months and days as necessary.") }; // -=*# Resource for function DATE_VALUE #*=- -const TranslateId SC_OPCODE_GET_DATE_VALUE_ARY[] = +const TranslateId ocGET_DATE_VALUE_ARY[] = { - NC_("SC_OPCODE_GET_DATE_VALUE", "Returns an internal number for a text having a possible date format."), - NC_("SC_OPCODE_GET_DATE_VALUE", "Text"), - NC_("SC_OPCODE_GET_DATE_VALUE", "A text enclosed in quotation marks which returns a date in a %PRODUCTNAME date format.") + NC_("ocGET_DATE_VALUE", "Returns an internal number for a text having a possible date format."), + NC_("ocGET_DATE_VALUE", "Text"), + NC_("ocGET_DATE_VALUE", "A text enclosed in quotation marks which returns a date in a %PRODUCTNAME date format.") }; // -=*# Resource for function DAY #*=- -const TranslateId SC_OPCODE_GET_DAY_ARY[] = +const TranslateId ocGET_DAY_ARY[] = { - NC_("SC_OPCODE_GET_DAY", "Returns the sequential date of the month as an integer (1-31) in relation to the date value."), - NC_("SC_OPCODE_GET_DAY", "Number"), - NC_("SC_OPCODE_GET_DAY", "The internal number for the date.") + NC_("ocGET_DAY", "Returns the sequential date of the month as an integer (1-31) in relation to the date value."), + NC_("ocGET_DAY", "Number"), + NC_("ocGET_DAY", "The internal number for the date.") }; // -=*# Resource for function DAYS360 #*=- -const TranslateId SC_OPCODE_GET_DIFF_DATE_360_ARY[] = +const TranslateId ocGET_DIFF_DATE_360_ARY[] = { - NC_("SC_OPCODE_GET_DIFF_DATE_360", "Calculates the number of days between two dates based on a 360-day year."), - NC_("SC_OPCODE_GET_DIFF_DATE_360", "Date 1"), - NC_("SC_OPCODE_GET_DIFF_DATE_360", "The start date for calculating the difference in days."), - NC_("SC_OPCODE_GET_DIFF_DATE_360", "Date 2"), - NC_("SC_OPCODE_GET_DIFF_DATE_360", "The end date for calculating the difference in days."), - NC_("SC_OPCODE_GET_DIFF_DATE_360", "Type"), - NC_("SC_OPCODE_GET_DIFF_DATE_360", "Method used to form differences: Type = 0 denotes US method (NASD), Type = 1 denotes the European method.") + NC_("ocGET_DIFF_DATE_360", "Calculates the number of days between two dates based on a 360-day year."), + NC_("ocGET_DIFF_DATE_360", "Date 1"), + NC_("ocGET_DIFF_DATE_360", "The start date for calculating the difference in days."), + NC_("ocGET_DIFF_DATE_360", "Date 2"), + NC_("ocGET_DIFF_DATE_360", "The end date for calculating the difference in days."), + NC_("ocGET_DIFF_DATE_360", "Type"), + NC_("ocGET_DIFF_DATE_360", "Method used to form differences: Type = 0 denotes US method (NASD), Type = 1 denotes the European method.") }; // -=*# Resource for function NETWORKDAYS #*=- -const TranslateId SC_OPCODE_NETWORKDAYS_ARY[] = +const TranslateId ocNETWORKDAYS_ARY[] = { - NC_("SC_OPCODE_NETWORKDAYS", "Returns the number of workdays between two dates using arguments to indicate weekenddays and holidays."), - NC_("SC_OPCODE_NETWORKDAYS", "Start date"), - NC_("SC_OPCODE_NETWORKDAYS", "Start date for calculation."), - NC_("SC_OPCODE_NETWORKDAYS", "End date"), - NC_("SC_OPCODE_NETWORKDAYS", "End date for calculation."), - NC_("SC_OPCODE_NETWORKDAYS", "List of dates"), - NC_("SC_OPCODE_NETWORKDAYS", "Optional set of one or more dates to be considered as holiday."), - NC_("SC_OPCODE_NETWORKDAYS", "Array"), - NC_("SC_OPCODE_NETWORKDAYS", "Optional list of numbers to indicate working (0) and weekend (non-zero) days. When omitted, weekend is Saturday and Sunday.") + NC_("ocNETWORKDAYS", "Returns the number of workdays between two dates using arguments to indicate weekenddays and holidays."), + NC_("ocNETWORKDAYS", "Start date"), + NC_("ocNETWORKDAYS", "Start date for calculation."), + NC_("ocNETWORKDAYS", "End date"), + NC_("ocNETWORKDAYS", "End date for calculation."), + NC_("ocNETWORKDAYS", "List of dates"), + NC_("ocNETWORKDAYS", "Optional set of one or more dates to be considered as holiday."), + NC_("ocNETWORKDAYS", "Array"), + NC_("ocNETWORKDAYS", "Optional list of numbers to indicate working (0) and weekend (non-zero) days. When omitted, weekend is Saturday and Sunday.") }; // -=*# Resource for function NETWORKDAYS.INTL #*=- -const TranslateId SC_OPCODE_NETWORKDAYS_MS_ARY[] = +const TranslateId ocNETWORKDAYS_MS_ARY[] = { - NC_("SC_OPCODE_NETWORKDAYS_MS", "Returns the number of workdays between two dates using arguments to indicate weekend days and holidays."), - NC_("SC_OPCODE_NETWORKDAYS_MS", "Start date"), - NC_("SC_OPCODE_NETWORKDAYS_MS", "Start date for calculation."), - NC_("SC_OPCODE_NETWORKDAYS_MS", "End date"), - NC_("SC_OPCODE_NETWORKDAYS_MS", "End date for calculation."), - NC_("SC_OPCODE_NETWORKDAYS_MS", "Number or string"), - NC_("SC_OPCODE_NETWORKDAYS_MS", "Optional number or string to indicate when weekends occur. When omitted, weekend is Saturday and Sunday."), - NC_("SC_OPCODE_NETWORKDAYS_MS", "Array"), - NC_("SC_OPCODE_NETWORKDAYS_MS", "Optional set of one or more dates to be considered as holiday.") + NC_("ocNETWORKDAYS_MS", "Returns the number of workdays between two dates using arguments to indicate weekend days and holidays."), + NC_("ocNETWORKDAYS_MS", "Start date"), + NC_("ocNETWORKDAYS_MS", "Start date for calculation."), + NC_("ocNETWORKDAYS_MS", "End date"), + NC_("ocNETWORKDAYS_MS", "End date for calculation."), + NC_("ocNETWORKDAYS_MS", "Number or string"), + NC_("ocNETWORKDAYS_MS", "Optional number or string to indicate when weekends occur. When omitted, weekend is Saturday and Sunday."), + NC_("ocNETWORKDAYS_MS", "Array"), + NC_("ocNETWORKDAYS_MS", "Optional set of one or more dates to be considered as holiday.") }; // -=*# Resource for function WORKDAY.INTL #*=- -const TranslateId SC_OPCODE_WORKDAY_MS_ARY[] = +const TranslateId ocWORKDAY_MS_ARY[] = { - NC_("SC_OPCODE_WORKDAY_MS", "Returns the serial number of the date before or after a number of workdays using arguments to indicate weekend days and holidays."), - NC_("SC_OPCODE_WORKDAY_MS", "Start date"), - NC_("SC_OPCODE_WORKDAY_MS", "Start date for calculation."), - NC_("SC_OPCODE_WORKDAY_MS", "Days"), - NC_("SC_OPCODE_WORKDAY_MS", "The number of workdays before or after start date."), - NC_("SC_OPCODE_WORKDAY_MS", "Number or string"), - NC_("SC_OPCODE_WORKDAY_MS", "Optional number or string to indicate when weekends occur. When omitted, weekend is Saturday and Sunday."), - NC_("SC_OPCODE_WORKDAY_MS", "Array"), - NC_("SC_OPCODE_WORKDAY_MS", "Optional set of one or more dates to be considered as holiday.") + NC_("ocWORKDAY_MS", "Returns the serial number of the date before or after a number of workdays using arguments to indicate weekend days and holidays."), + NC_("ocWORKDAY_MS", "Start date"), + NC_("ocWORKDAY_MS", "Start date for calculation."), + NC_("ocWORKDAY_MS", "Days"), + NC_("ocWORKDAY_MS", "The number of workdays before or after start date."), + NC_("ocWORKDAY_MS", "Number or string"), + NC_("ocWORKDAY_MS", "Optional number or string to indicate when weekends occur. When omitted, weekend is Saturday and Sunday."), + NC_("ocWORKDAY_MS", "Array"), + NC_("ocWORKDAY_MS", "Optional set of one or more dates to be considered as holiday.") }; // -=*# Resource for function HOUR #*=- -const TranslateId SC_OPCODE_GET_HOUR_ARY[] = +const TranslateId ocGET_HOUR_ARY[] = { - NC_("SC_OPCODE_GET_HOUR", "Determines the sequential number of the hour of the day (0-23) for the time value."), - NC_("SC_OPCODE_GET_HOUR", "Number"), - NC_("SC_OPCODE_GET_HOUR", "Internal time value") + NC_("ocGET_HOUR", "Determines the sequential number of the hour of the day (0-23) for the time value."), + NC_("ocGET_HOUR", "Number"), + NC_("ocGET_HOUR", "Internal time value") }; // -=*# Resource for function MINUTE #*=- -const TranslateId SC_OPCODE_GET_MIN_ARY[] = +const TranslateId ocGET_MIN_ARY[] = { - NC_("SC_OPCODE_GET_MIN", "Determines the sequential number for the minute of the hour (0-59) for the time value."), - NC_("SC_OPCODE_GET_MIN", "Number"), - NC_("SC_OPCODE_GET_MIN", "Internal time value.") + NC_("ocGET_MIN", "Determines the sequential number for the minute of the hour (0-59) for the time value."), + NC_("ocGET_MIN", "Number"), + NC_("ocGET_MIN", "Internal time value.") }; // -=*# Resource for function MONTH #*=- -const TranslateId SC_OPCODE_GET_MONTH_ARY[] = +const TranslateId ocGET_MONTH_ARY[] = { - NC_("SC_OPCODE_GET_MONTH", "Determines the sequential number of a month of the year (1-12) for the date value."), - NC_("SC_OPCODE_GET_MONTH", "Number"), - NC_("SC_OPCODE_GET_MONTH", "The internal number of the date.") + NC_("ocGET_MONTH", "Determines the sequential number of a month of the year (1-12) for the date value."), + NC_("ocGET_MONTH", "Number"), + NC_("ocGET_MONTH", "The internal number of the date.") }; // -=*# Resource for function NOW #*=- -const TranslateId SC_OPCODE_GET_ACT_TIME_ARY[] = +const TranslateId ocGET_ACT_TIME_ARY[] = { - NC_("SC_OPCODE_GET_ACT_TIME", "Determines the current time of the computer.") + NC_("ocGET_ACT_TIME", "Determines the current time of the computer.") }; // -=*# Resource for function SECOND #*=- -const TranslateId SC_OPCODE_GET_SEC_ARY[] = +const TranslateId ocGET_SEC_ARY[] = { - NC_("SC_OPCODE_GET_SEC", "Determines the sequential number of the second of a minute (0-59) for the time value."), - NC_("SC_OPCODE_GET_SEC", "Number"), - NC_("SC_OPCODE_GET_SEC", "The internal time value.") + NC_("ocGET_SEC", "Determines the sequential number of the second of a minute (0-59) for the time value."), + NC_("ocGET_SEC", "Number"), + NC_("ocGET_SEC", "The internal time value.") }; // -=*# Resource for function TIME #*=- -const TranslateId SC_OPCODE_GET_TIME_ARY[] = +const TranslateId ocGET_TIME_ARY[] = { - NC_("SC_OPCODE_GET_TIME", "Determines a time value from the details for hour, minute and second."), - NC_("SC_OPCODE_GET_TIME", "Hour"), - NC_("SC_OPCODE_GET_TIME", "The integer for the hour."), - NC_("SC_OPCODE_GET_TIME", "Minute"), - NC_("SC_OPCODE_GET_TIME", "The integer for the minute."), - NC_("SC_OPCODE_GET_TIME", "Second"), - NC_("SC_OPCODE_GET_TIME", "The integer for the second.") + NC_("ocGET_TIME", "Determines a time value from the details for hour, minute and second."), + NC_("ocGET_TIME", "Hour"), + NC_("ocGET_TIME", "The integer for the hour."), + NC_("ocGET_TIME", "Minute"), + NC_("ocGET_TIME", "The integer for the minute."), + NC_("ocGET_TIME", "Second"), + NC_("ocGET_TIME", "The integer for the second.") }; // -=*# Resource for function TIMEVALUE #*=- -const TranslateId SC_OPCODE_GET_TIME_VALUE_ARY[] = +const TranslateId ocGET_TIME_VALUE_ARY[] = { - NC_("SC_OPCODE_GET_TIME_VALUE", "Returns a sequential number for a text shown in a possible time entry format."), - NC_("SC_OPCODE_GET_TIME_VALUE", "Text"), - NC_("SC_OPCODE_GET_TIME_VALUE", "A text enclosed in quotation marks which returns a time in a %PRODUCTNAME time format.") + NC_("ocGET_TIME_VALUE", "Returns a sequential number for a text shown in a possible time entry format."), + NC_("ocGET_TIME_VALUE", "Text"), + NC_("ocGET_TIME_VALUE", "A text enclosed in quotation marks which returns a time in a %PRODUCTNAME time format.") }; // -=*# Resource for function TODAY #*=- -const TranslateId SC_OPCODE_GET_ACT_DATE_ARY[] = +const TranslateId ocGET_ACT_DATE_ARY[] = { - NC_("SC_OPCODE_GET_ACT_DATE", "Determines the current date of the computer.") + NC_("ocGET_ACT_DATE", "Determines the current date of the computer.") }; // -=*# Resource for function WEEKDAY #*=- -const TranslateId SC_OPCODE_GET_DAY_OF_WEEK_ARY[] = +const TranslateId ocGET_DAY_OF_WEEK_ARY[] = { - NC_("SC_OPCODE_GET_DAY_OF_WEEK", "Returns the day of the week for the date value as an integer."), - NC_("SC_OPCODE_GET_DAY_OF_WEEK", "Number"), - NC_("SC_OPCODE_GET_DAY_OF_WEEK", "The internal number for the date."), - NC_("SC_OPCODE_GET_DAY_OF_WEEK", "Type"), - NC_("SC_OPCODE_GET_DAY_OF_WEEK", "Fixes the beginning of the week and the type of calculation to be used.") + NC_("ocGET_DAY_OF_WEEK", "Returns the day of the week for the date value as an integer."), + NC_("ocGET_DAY_OF_WEEK", "Number"), + NC_("ocGET_DAY_OF_WEEK", "The internal number for the date."), + NC_("ocGET_DAY_OF_WEEK", "Type"), + NC_("ocGET_DAY_OF_WEEK", "Fixes the beginning of the week and the type of calculation to be used.") }; // -=*# Resource for function YEAR #*=- -const TranslateId SC_OPCODE_GET_YEAR_ARY[] = +const TranslateId ocGET_YEAR_ARY[] = { - NC_("SC_OPCODE_GET_YEAR", "Returns the year of a date value as an integer."), - NC_("SC_OPCODE_GET_YEAR", "Number"), - NC_("SC_OPCODE_GET_YEAR", "Internal number of the date.") + NC_("ocGET_YEAR", "Returns the year of a date value as an integer."), + NC_("ocGET_YEAR", "Number"), + NC_("ocGET_YEAR", "Internal number of the date.") }; // -=*# Resource for function DAYS #*=- -const TranslateId SC_OPCODE_GET_DIFF_DATE_ARY[] = +const TranslateId ocGET_DIFF_DATE_ARY[] = { - NC_("SC_OPCODE_GET_DIFF_DATE", "Calculates the number of days between two dates."), - NC_("SC_OPCODE_GET_DIFF_DATE", "Date 2"), - NC_("SC_OPCODE_GET_DIFF_DATE", "The end date for calculating the difference in days."), - NC_("SC_OPCODE_GET_DIFF_DATE", "Date 1"), - NC_("SC_OPCODE_GET_DIFF_DATE", "The start date for calculating the difference in days.") + NC_("ocGET_DIFF_DATE", "Calculates the number of days between two dates."), + NC_("ocGET_DIFF_DATE", "Date 2"), + NC_("ocGET_DIFF_DATE", "The end date for calculating the difference in days."), + NC_("ocGET_DIFF_DATE", "Date 1"), + NC_("ocGET_DIFF_DATE", "The start date for calculating the difference in days.") }; // -=*# Resource for function DATEDIF #*=- -const TranslateId SC_OPCODE_GET_DATEDIF_ARY[] = +const TranslateId ocGET_DATEDIF_ARY[] = { - NC_("SC_OPCODE_GET_DATEDIF", "Returns the number of whole days, months or years between 'start date' and 'end date'."), - NC_("SC_OPCODE_GET_DATEDIF", "Start date"), - NC_("SC_OPCODE_GET_DATEDIF", "The start date."), - NC_("SC_OPCODE_GET_DATEDIF", "End date"), - NC_("SC_OPCODE_GET_DATEDIF", "The end date."), - NC_("SC_OPCODE_GET_DATEDIF", "Interval"), - NC_("SC_OPCODE_GET_DATEDIF", "Interval to be calculated. Can be \"d\", \"m\", \"y\", \"ym\", \"md\" or \"yd\".") + NC_("ocGET_DATEDIF", "Returns the number of whole days, months or years between 'start date' and 'end date'."), + NC_("ocGET_DATEDIF", "Start date"), + NC_("ocGET_DATEDIF", "The start date."), + NC_("ocGET_DATEDIF", "End date"), + NC_("ocGET_DATEDIF", "The end date."), + NC_("ocGET_DATEDIF", "Interval"), + NC_("ocGET_DATEDIF", "Interval to be calculated. Can be \"d\", \"m\", \"y\", \"ym\", \"md\" or \"yd\".") }; // -=*# Resource for function WEEKNUM #*=- -const TranslateId SC_OPCODE_WEEK_ARY[] = +const TranslateId ocWEEK_ARY[] = { - NC_("SC_OPCODE_WEEK", "Calculates the calendar week corresponding to the given date."), - NC_("SC_OPCODE_WEEK", "Number"), - NC_("SC_OPCODE_WEEK", "The internal number of the date."), - NC_("SC_OPCODE_WEEK", "Mode"), - NC_("SC_OPCODE_WEEK", "Indicates the first day of the week and when week 1 starts.") + NC_("ocWEEK", "Calculates the calendar week corresponding to the given date."), + NC_("ocWEEK", "Number"), + NC_("ocWEEK", "The internal number of the date."), + NC_("ocWEEK", "Mode"), + NC_("ocWEEK", "Indicates the first day of the week and when week 1 starts.") }; // -=*# Resource for function ISOWEEKNUM #*=- -const TranslateId SC_OPCODE_ISOWEEKNUM_ARY[] = +const TranslateId ocISOWEEKNUM_ARY[] = { - NC_("SC_OPCODE_ISOWEEKNUM", "Calculates the ISO 8601 calendar week for the given date."), - NC_("SC_OPCODE_ISOWEEKNUM", "Number"), - NC_("SC_OPCODE_ISOWEEKNUM", "The internal number of the date.") + NC_("ocISOWEEKNUM", "Calculates the ISO 8601 calendar week for the given date."), + NC_("ocISOWEEKNUM", "Number"), + NC_("ocISOWEEKNUM", "The internal number of the date.") }; -const TranslateId SC_OPCODE_WEEKNUM_OOO_ARY[] = +const TranslateId ocWEEKNUM_OOO_ARY[] = { - NC_("SC_OPCODE_WEEKNUM_OOO", "Calculates the calendar week corresponding to the given date.\nThis function only provides interoperability with %PRODUCTNAME 5.0 and earlier and OpenOffice.org."), - NC_("SC_OPCODE_WEEKNUM_OOO", "Number"), - NC_("SC_OPCODE_WEEKNUM_OOO", "The internal number of the date."), - NC_("SC_OPCODE_WEEKNUM_OOO", "Mode"), - NC_("SC_OPCODE_WEEKNUM_OOO", "Indicates the first day of the week (1 = Sunday, other values = Monday).") + NC_("ocWEEKNUM_OOO", "Calculates the calendar week corresponding to the given date.\nThis function only provides interoperability with %PRODUCTNAME 5.0 and earlier and OpenOffice.org."), + NC_("ocWEEKNUM_OOO", "Number"), + NC_("ocWEEKNUM_OOO", "The internal number of the date."), + NC_("ocWEEKNUM_OOO", "Mode"), + NC_("ocWEEKNUM_OOO", "Indicates the first day of the week (1 = Sunday, other values = Monday).") }; // -=*# Resource for function EASTERSUNDAY #*=- -const TranslateId SC_OPCODE_EASTERSUNDAY_ARY[] = +const TranslateId ocEASTERSUNDAY_ARY[] = { - NC_("SC_OPCODE_EASTERSUNDAY", "Calculates the date of Easter Sunday in a given year."), - NC_("SC_OPCODE_EASTERSUNDAY", "Year"), - NC_("SC_OPCODE_EASTERSUNDAY", "An integer between 1583 and 9956, or 0 and 99 (19xx or 20xx depending on the option set).") + NC_("ocEASTERSUNDAY", "Calculates the date of Easter Sunday in a given year."), + NC_("ocEASTERSUNDAY", "Year"), + NC_("ocEASTERSUNDAY", "An integer between 1583 and 9956, or 0 and 99 (19xx or 20xx depending on the option set).") }; // -=*# Resource for function PV #*=- -const TranslateId SC_OPCODE_PV_ARY[] = +const TranslateId ocPV_ARY[] = { - NC_("SC_OPCODE_PV", "Present value. Calculates the present value of an investment."), - NC_("SC_OPCODE_PV", "Rate"), - NC_("SC_OPCODE_PV", "The rate of interest for the period given."), - NC_("SC_OPCODE_PV", "NPER"), - NC_("SC_OPCODE_PV", "The payment period. The total number of periods in which the annuity is paid."), - NC_("SC_OPCODE_PV", "PMT"), - NC_("SC_OPCODE_PV", "Regular payments. The constant amount of annuity that is paid in each period."), - NC_("SC_OPCODE_PV", "FV"), - NC_("SC_OPCODE_PV", "Future value. The value (final value) to be attained after the last payment."), - NC_("SC_OPCODE_PV", "Type"), - NC_("SC_OPCODE_PV", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") + NC_("ocPV", "Present value. Calculates the present value of an investment."), + NC_("ocPV", "Rate"), + NC_("ocPV", "The rate of interest for the period given."), + NC_("ocPV", "NPER"), + NC_("ocPV", "The payment period. The total number of periods in which the annuity is paid."), + NC_("ocPV", "PMT"), + NC_("ocPV", "Regular payments. The constant amount of annuity that is paid in each period."), + NC_("ocPV", "FV"), + NC_("ocPV", "Future value. The value (final value) to be attained after the last payment."), + NC_("ocPV", "Type"), + NC_("ocPV", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") }; // -=*# Resource for function FV #*=- -const TranslateId SC_OPCODE_FV_ARY[] = +const TranslateId ocFV_ARY[] = { - NC_("SC_OPCODE_FV", "Future value. Returns the future value of an investment based on regular payments and a constant interest rate."), - NC_("SC_OPCODE_FV", "Rate"), - NC_("SC_OPCODE_FV", "The rate of interest per period."), - NC_("SC_OPCODE_FV", "NPER"), - NC_("SC_OPCODE_FV", "Payment period. The total number of periods in which the annuity (pension) is paid."), - NC_("SC_OPCODE_FV", "PMT"), - NC_("SC_OPCODE_FV", "Regular payments. The constant annuity to be paid in each period."), - NC_("SC_OPCODE_FV", "PV"), - NC_("SC_OPCODE_FV", "Present value. The current value of a series of payments"), - NC_("SC_OPCODE_FV", "Type"), - NC_("SC_OPCODE_FV", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") + NC_("ocFV", "Future value. Returns the future value of an investment based on regular payments and a constant interest rate."), + NC_("ocFV", "Rate"), + NC_("ocFV", "The rate of interest per period."), + NC_("ocFV", "NPER"), + NC_("ocFV", "Payment period. The total number of periods in which the annuity (pension) is paid."), + NC_("ocFV", "PMT"), + NC_("ocFV", "Regular payments. The constant annuity to be paid in each period."), + NC_("ocFV", "PV"), + NC_("ocFV", "Present value. The current value of a series of payments"), + NC_("ocFV", "Type"), + NC_("ocFV", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") }; // -=*# Resource for function NPER #*=- -const TranslateId SC_OPCODE_NPER_ARY[] = +const TranslateId ocNPER_ARY[] = { - NC_("SC_OPCODE_NPER", "Payment period. Calculates the number of payment periods for an investment based on regular payments and a constant interest rate."), - NC_("SC_OPCODE_NPER", "Rate"), - NC_("SC_OPCODE_NPER", "The rate of interest per period."), - NC_("SC_OPCODE_NPER", "PMT"), - NC_("SC_OPCODE_NPER", "Regular payments. The constant annuity to be paid in each period."), - NC_("SC_OPCODE_NPER", "PV"), - NC_("SC_OPCODE_NPER", "Present value. The current value of a series of payments"), - NC_("SC_OPCODE_NPER", "FV"), - NC_("SC_OPCODE_NPER", "Future value. The value (end value) to be attained after the final payment."), - NC_("SC_OPCODE_NPER", "Type"), - NC_("SC_OPCODE_NPER", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") + NC_("ocNPER", "Payment period. Calculates the number of payment periods for an investment based on regular payments and a constant interest rate."), + NC_("ocNPER", "Rate"), + NC_("ocNPER", "The rate of interest per period."), + NC_("ocNPER", "PMT"), + NC_("ocNPER", "Regular payments. The constant annuity to be paid in each period."), + NC_("ocNPER", "PV"), + NC_("ocNPER", "Present value. The current value of a series of payments"), + NC_("ocNPER", "FV"), + NC_("ocNPER", "Future value. The value (end value) to be attained after the final payment."), + NC_("ocNPER", "Type"), + NC_("ocNPER", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") }; // -=*# Resource for function PMT #*=- -const TranslateId SC_OPCODE_PMT_ARY[] = +const TranslateId ocPMT_ARY[] = { - NC_("SC_OPCODE_PMT", "Regular payments. Returns the periodic payment of an annuity, based on regular payments and a fixed periodic interest rate."), - NC_("SC_OPCODE_PMT", "Rate"), - NC_("SC_OPCODE_PMT", "The rate of interest per period."), - NC_("SC_OPCODE_PMT", "NPER"), - NC_("SC_OPCODE_PMT", "Payment period. The total number of periods in which the annuity (pension) is paid."), - NC_("SC_OPCODE_PMT", "PV"), - NC_("SC_OPCODE_PMT", "Present value. The current value of a series of payments"), - NC_("SC_OPCODE_PMT", "FV"), - NC_("SC_OPCODE_PMT", "Future value. The value (end value) to be attained after the final payment."), - NC_("SC_OPCODE_PMT", "Type"), - NC_("SC_OPCODE_PMT", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") + NC_("ocPMT", "Regular payments. Returns the periodic payment of an annuity, based on regular payments and a fixed periodic interest rate."), + NC_("ocPMT", "Rate"), + NC_("ocPMT", "The rate of interest per period."), + NC_("ocPMT", "NPER"), + NC_("ocPMT", "Payment period. The total number of periods in which the annuity (pension) is paid."), + NC_("ocPMT", "PV"), + NC_("ocPMT", "Present value. The current value of a series of payments"), + NC_("ocPMT", "FV"), + NC_("ocPMT", "Future value. The value (end value) to be attained after the final payment."), + NC_("ocPMT", "Type"), + NC_("ocPMT", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") }; // -=*# Resource for function RATE #*=- -const TranslateId SC_OPCODE_RATE_ARY[] = +const TranslateId ocRATE_ARY[] = { - NC_("SC_OPCODE_RATE", "Calculates the constant interest rate of an investment with regular payments."), - NC_("SC_OPCODE_RATE", "NPER"), - NC_("SC_OPCODE_RATE", "Payment period. The total number of periods in which the annuity (pension) is paid."), - NC_("SC_OPCODE_RATE", "PMT"), - NC_("SC_OPCODE_RATE", "Regular payments. The constant annuity to be paid in each period."), - NC_("SC_OPCODE_RATE", "PV"), - NC_("SC_OPCODE_RATE", "Present value. The current value of a series of payments"), - NC_("SC_OPCODE_RATE", "FV"), - NC_("SC_OPCODE_RATE", "Future value. The value (end value) to be attained after the final payment."), - NC_("SC_OPCODE_RATE", "Type"), - NC_("SC_OPCODE_RATE", "Type = 1 denotes due at the beginning of the period, = 0 at the end."), - NC_("SC_OPCODE_RATE", "Guess"), - NC_("SC_OPCODE_RATE", "Guess. The estimate of the interest rate for the iterative calculating method.") + NC_("ocRATE", "Calculates the constant interest rate of an investment with regular payments."), + NC_("ocRATE", "NPER"), + NC_("ocRATE", "Payment period. The total number of periods in which the annuity (pension) is paid."), + NC_("ocRATE", "PMT"), + NC_("ocRATE", "Regular payments. The constant annuity to be paid in each period."), + NC_("ocRATE", "PV"), + NC_("ocRATE", "Present value. The current value of a series of payments"), + NC_("ocRATE", "FV"), + NC_("ocRATE", "Future value. The value (end value) to be attained after the final payment."), + NC_("ocRATE", "Type"), + NC_("ocRATE", "Type = 1 denotes due at the beginning of the period, = 0 at the end."), + NC_("ocRATE", "Guess"), + NC_("ocRATE", "Guess. The estimate of the interest rate for the iterative calculating method.") }; // -=*# Resource for function IPMT #*=- -const TranslateId SC_OPCODE_IPMT_ARY[] = +const TranslateId ocIPMT_ARY[] = { - NC_("SC_OPCODE_IPMT", "Compounded interest. Calculates the interest payment on the principal for an investment with regular payments and a constant interest rate for a given period."), - NC_("SC_OPCODE_IPMT", "Rate"), - NC_("SC_OPCODE_IPMT", "The rate of interest per period."), - NC_("SC_OPCODE_IPMT", "Period"), - NC_("SC_OPCODE_IPMT", "Periods. The periods for which the compounded interest is to be calculated. P = 1 denotes for the first period, P = NPER for the last one."), - NC_("SC_OPCODE_IPMT", "NPER"), - NC_("SC_OPCODE_IPMT", "Payment period. The total number of periods in which the annuity (pension) is paid."), - NC_("SC_OPCODE_IPMT", "PV"), - NC_("SC_OPCODE_IPMT", "Present value. The current value of a series of payments"), - NC_("SC_OPCODE_IPMT", "FV"), - NC_("SC_OPCODE_IPMT", "Future value. The value (end value) to be attained after the final payment."), - NC_("SC_OPCODE_IPMT", "Type"), - NC_("SC_OPCODE_IPMT", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") + NC_("ocIPMT", "Compounded interest. Calculates the interest payment on the principal for an investment with regular payments and a constant interest rate for a given period."), + NC_("ocIPMT", "Rate"), + NC_("ocIPMT", "The rate of interest per period."), + NC_("ocIPMT", "Period"), + NC_("ocIPMT", "Periods. The periods for which the compounded interest is to be calculated. P = 1 denotes for the first period, P = NPER for the last one."), + NC_("ocIPMT", "NPER"), + NC_("ocIPMT", "Payment period. The total number of periods in which the annuity (pension) is paid."), + NC_("ocIPMT", "PV"), + NC_("ocIPMT", "Present value. The current value of a series of payments"), + NC_("ocIPMT", "FV"), + NC_("ocIPMT", "Future value. The value (end value) to be attained after the final payment."), + NC_("ocIPMT", "Type"), + NC_("ocIPMT", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") }; // -=*# Resource for function PPMT #*=- -const TranslateId SC_OPCODE_PPMT_ARY[] = +const TranslateId ocPPMT_ARY[] = { - NC_("SC_OPCODE_PPMT", "Repayment. Calculates the repayment amount for a period for an investment whereby the payments are at regular intervals and the interest rate constant."), - NC_("SC_OPCODE_PPMT", "Rate"), - NC_("SC_OPCODE_PPMT", "The interest rate per period."), - NC_("SC_OPCODE_PPMT", "Period"), - NC_("SC_OPCODE_PPMT", "Period. The period for which the repayments are to be calculated. Per = 1 denotes for the first period, P = NPER for the last"), - NC_("SC_OPCODE_PPMT", "NPER"), - NC_("SC_OPCODE_PPMT", "The payment period. The total number of periods in which the annuity (pension) is paid."), - NC_("SC_OPCODE_PPMT", "PV"), - NC_("SC_OPCODE_PPMT", "The present value. The present value or the amount the annuity is currently worth."), - NC_("SC_OPCODE_PPMT", "FV"), - NC_("SC_OPCODE_PPMT", "Future value. The value (end value) attained after the last payment has been made."), - NC_("SC_OPCODE_PPMT", "Type"), - NC_("SC_OPCODE_PPMT", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") + NC_("ocPPMT", "Repayment. Calculates the repayment amount for a period for an investment whereby the payments are at regular intervals and the interest rate constant."), + NC_("ocPPMT", "Rate"), + NC_("ocPPMT", "The interest rate per period."), + NC_("ocPPMT", "Period"), + NC_("ocPPMT", "Period. The period for which the repayments are to be calculated. Per = 1 denotes for the first period, P = NPER for the last"), + NC_("ocPPMT", "NPER"), + NC_("ocPPMT", "The payment period. The total number of periods in which the annuity (pension) is paid."), + NC_("ocPPMT", "PV"), + NC_("ocPPMT", "The present value. The present value or the amount the annuity is currently worth."), + NC_("ocPPMT", "FV"), + NC_("ocPPMT", "Future value. The value (end value) attained after the last payment has been made."), + NC_("ocPPMT", "Type"), + NC_("ocPPMT", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") }; // -=*# Resource for function CUMPRINC #*=- -const TranslateId SC_OPCODE_CUM_PRINC_ARY[] = +const TranslateId ocCUM_PRINC_ARY[] = { - NC_("SC_OPCODE_CUM_PRINC", "Cumulative capital. Calculates the total amount of the repayment share in a period for an investment with constant interest rate."), - NC_("SC_OPCODE_CUM_PRINC", "Rate"), - NC_("SC_OPCODE_CUM_PRINC", "The rate of interest per period."), - NC_("SC_OPCODE_CUM_PRINC", "NPER"), - NC_("SC_OPCODE_CUM_PRINC", "Payment period. The total number of periods in which the annuity (pension) is paid."), - NC_("SC_OPCODE_CUM_PRINC", "PV"), - NC_("SC_OPCODE_CUM_PRINC", "The present value. The present value or the amount the annuity is currently worth."), - NC_("SC_OPCODE_CUM_PRINC", "S"), - NC_("SC_OPCODE_CUM_PRINC", "The start period. The first period to be taken into account. S = 1 denotes the very first period."), - NC_("SC_OPCODE_CUM_PRINC", "E"), - NC_("SC_OPCODE_CUM_PRINC", "End period. The last period to be taken into account."), - NC_("SC_OPCODE_CUM_PRINC", "Type"), - NC_("SC_OPCODE_CUM_PRINC", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") + NC_("ocCUM_PRINC", "Cumulative capital. Calculates the total amount of the repayment share in a period for an investment with constant interest rate."), + NC_("ocCUM_PRINC", "Rate"), + NC_("ocCUM_PRINC", "The rate of interest per period."), + NC_("ocCUM_PRINC", "NPER"), + NC_("ocCUM_PRINC", "Payment period. The total number of periods in which the annuity (pension) is paid."), + NC_("ocCUM_PRINC", "PV"), + NC_("ocCUM_PRINC", "The present value. The present value or the amount the annuity is currently worth."), + NC_("ocCUM_PRINC", "S"), + NC_("ocCUM_PRINC", "The start period. The first period to be taken into account. S = 1 denotes the very first period."), + NC_("ocCUM_PRINC", "E"), + NC_("ocCUM_PRINC", "End period. The last period to be taken into account."), + NC_("ocCUM_PRINC", "Type"), + NC_("ocCUM_PRINC", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") }; // -=*# Resource for function CUMIPMT #*=- -const TranslateId SC_OPCODE_CUM_IPMT_ARY[] = +const TranslateId ocCUM_IPMT_ARY[] = { - NC_("SC_OPCODE_CUM_IPMT", "Cumulative compounded interest. Calculates the total amount of the interest share in a period for an investment with a constant interest rate."), - NC_("SC_OPCODE_CUM_IPMT", "Rate"), - NC_("SC_OPCODE_CUM_IPMT", "The rate of interest per period."), - NC_("SC_OPCODE_CUM_IPMT", "NPER"), - NC_("SC_OPCODE_CUM_IPMT", "Payment period. The total number of periods in which the annuity (pension) is paid."), - NC_("SC_OPCODE_CUM_IPMT", "PV"), - NC_("SC_OPCODE_CUM_IPMT", "The present value. The present value or the amount the annuity is currently worth."), - NC_("SC_OPCODE_CUM_IPMT", "S"), - NC_("SC_OPCODE_CUM_IPMT", "The start period. The first period to be taken into account. S = 1 denotes the very first period."), - NC_("SC_OPCODE_CUM_IPMT", "E"), - NC_("SC_OPCODE_CUM_IPMT", "The end period. The last period to be taken into account."), - NC_("SC_OPCODE_CUM_IPMT", "Type"), - NC_("SC_OPCODE_CUM_IPMT", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") + NC_("ocCUM_IPMT", "Cumulative compounded interest. Calculates the total amount of the interest share in a period for an investment with a constant interest rate."), + NC_("ocCUM_IPMT", "Rate"), + NC_("ocCUM_IPMT", "The rate of interest per period."), + NC_("ocCUM_IPMT", "NPER"), + NC_("ocCUM_IPMT", "Payment period. The total number of periods in which the annuity (pension) is paid."), + NC_("ocCUM_IPMT", "PV"), + NC_("ocCUM_IPMT", "The present value. The present value or the amount the annuity is currently worth."), + NC_("ocCUM_IPMT", "S"), + NC_("ocCUM_IPMT", "The start period. The first period to be taken into account. S = 1 denotes the very first period."), + NC_("ocCUM_IPMT", "E"), + NC_("ocCUM_IPMT", "The end period. The last period to be taken into account."), + NC_("ocCUM_IPMT", "Type"), + NC_("ocCUM_IPMT", "Type = 1 denotes due at the beginning of the period, = 0 at the end.") }; // -=*# Resource for function SYD #*=- -const TranslateId SC_OPCODE_SYD_ARY[] = +const TranslateId ocSYD_ARY[] = { - NC_("SC_OPCODE_SYD", "Calculates the arithmetically declining value of an asset (depreciation) for a specified period."), - NC_("SC_OPCODE_SYD", "Cost"), - NC_("SC_OPCODE_SYD", "Acquisition costs. The initial cost of the asset."), - NC_("SC_OPCODE_SYD", "Salvage"), - NC_("SC_OPCODE_SYD", "Salvage: The remaining value of the asset at the end of its life."), - NC_("SC_OPCODE_SYD", "Life"), - NC_("SC_OPCODE_SYD", "Useful life. The number of periods in the useful life of the asset."), - NC_("SC_OPCODE_SYD", "Period"), - NC_("SC_OPCODE_SYD", "Period. The depreciation period which must have the same time unit as average useful life.") + NC_("ocSYD", "Calculates the arithmetically declining value of an asset (depreciation) for a specified period."), + NC_("ocSYD", "Cost"), + NC_("ocSYD", "Acquisition costs. The initial cost of the asset."), + NC_("ocSYD", "Salvage"), + NC_("ocSYD", "Salvage: The remaining value of the asset at the end of its life."), + NC_("ocSYD", "Life"), + NC_("ocSYD", "Useful life. The number of periods in the useful life of the asset."), + NC_("ocSYD", "Period"), + NC_("ocSYD", "Period. The depreciation period which must have the same time unit as average useful life.") }; // -=*# Resource for function SLN #*=- -const TranslateId SC_OPCODE_SLN_ARY[] = +const TranslateId ocSLN_ARY[] = { - NC_("SC_OPCODE_SLN", "Calculates the linear depreciation per period."), - NC_("SC_OPCODE_SLN", "Cost"), - NC_("SC_OPCODE_SLN", "Acquisition cost. The initial cost of an asset."), - NC_("SC_OPCODE_SLN", "Salvage"), - NC_("SC_OPCODE_SLN", "Salvage: The remaining value of the asset at the end of its life."), - NC_("SC_OPCODE_SLN", "Life"), - NC_("SC_OPCODE_SLN", "Useful life. The number of periods in the useful life of the asset.") + NC_("ocSLN", "Calculates the linear depreciation per period."), + NC_("ocSLN", "Cost"), + NC_("ocSLN", "Acquisition cost. The initial cost of an asset."), + NC_("ocSLN", "Salvage"), + NC_("ocSLN", "Salvage: The remaining value of the asset at the end of its life."), + NC_("ocSLN", "Life"), + NC_("ocSLN", "Useful life. The number of periods in the useful life of the asset.") }; // -=*# Resource for function DDB #*=- -const TranslateId SC_OPCODE_DDB_ARY[] = +const TranslateId ocDDB_ARY[] = { - NC_("SC_OPCODE_DDB", "Calculates the depreciation of an asset for a specific period using the double-declining balance method or declining balance factor."), - NC_("SC_OPCODE_DDB", "Cost"), - NC_("SC_OPCODE_DDB", "Acquisition costs. The initial cost of the asset."), - NC_("SC_OPCODE_DDB", "Salvage"), - NC_("SC_OPCODE_DDB", "Salvage: The remaining value of the asset at the end of its life."), - NC_("SC_OPCODE_DDB", "Life"), - NC_("SC_OPCODE_DDB", "Useful life. The number of periods in the useful life of the asset."), - NC_("SC_OPCODE_DDB", "Period"), - NC_("SC_OPCODE_DDB", "Period. The depreciation period in the same time unit as the average useful life entry."), - NC_("SC_OPCODE_DDB", "Factor"), - NC_("SC_OPCODE_DDB", "Factor. The factor for balance decline. F = 2 means a double declining balance factor") + NC_("ocDDB", "Calculates the depreciation of an asset for a specific period using the double-declining balance method or declining balance factor."), + NC_("ocDDB", "Cost"), + NC_("ocDDB", "Acquisition costs. The initial cost of the asset."), + NC_("ocDDB", "Salvage"), + NC_("ocDDB", "Salvage: The remaining value of the asset at the end of its life."), + NC_("ocDDB", "Life"), + NC_("ocDDB", "Useful life. The number of periods in the useful life of the asset."), + NC_("ocDDB", "Period"), + NC_("ocDDB", "Period. The depreciation period in the same time unit as the average useful life entry."), + NC_("ocDDB", "Factor"), + NC_("ocDDB", "Factor. The factor for balance decline. F = 2 means a double declining balance factor") }; // -=*# Resource for function DB #*=- -const TranslateId SC_OPCODE_DB_ARY[] = +const TranslateId ocDB_ARY[] = { - NC_("SC_OPCODE_DB", "Returns the real depreciation of an asset for a specified period using the fixed-declining balance method."), - NC_("SC_OPCODE_DB", "Cost"), - NC_("SC_OPCODE_DB", "Acquisition costs: The initial cost of the asset."), - NC_("SC_OPCODE_DB", "Salvage"), - NC_("SC_OPCODE_DB", "Salvage: The remaining value of the asset at the end of its life."), - NC_("SC_OPCODE_DB", "Life"), - NC_("SC_OPCODE_DB", "Useful life. The number of periods in the useful life of the asset."), - NC_("SC_OPCODE_DB", "Period"), - NC_("SC_OPCODE_DB", "Periods: The period for which the depreciation is calculated. The time unit used for period must be the same as that for the useful life."), - NC_("SC_OPCODE_DB", "Month"), - NC_("SC_OPCODE_DB", "Months: The number of months in the first year of depreciation.") + NC_("ocDB", "Returns the real depreciation of an asset for a specified period using the fixed-declining balance method."), + NC_("ocDB", "Cost"), + NC_("ocDB", "Acquisition costs: The initial cost of the asset."), + NC_("ocDB", "Salvage"), + NC_("ocDB", "Salvage: The remaining value of the asset at the end of its life."), + NC_("ocDB", "Life"), + NC_("ocDB", "Useful life. The number of periods in the useful life of the asset."), + NC_("ocDB", "Period"), + NC_("ocDB", "Periods: The period for which the depreciation is calculated. The time unit used for period must be the same as that for the useful life."), + NC_("ocDB", "Month"), + NC_("ocDB", "Months: The number of months in the first year of depreciation.") }; // -=*# Resource for function VDB #*=- -const TranslateId SC_OPCODE_VBD_ARY[] = +const TranslateId ocVBD_ARY[] = { - NC_("SC_OPCODE_VBD", "Variable declining balance. Returns the declining balance depreciation for a particular period."), - NC_("SC_OPCODE_VBD", "Cost"), - NC_("SC_OPCODE_VBD", "Cost. The initial cost of the asset."), - NC_("SC_OPCODE_VBD", "Salvage"), - NC_("SC_OPCODE_VBD", "Salvage. The salvage value of an asset at the end of its useful life."), - NC_("SC_OPCODE_VBD", "Life"), - NC_("SC_OPCODE_VBD", "Useful life. The number of periods in the useful life of the asset."), - NC_("SC_OPCODE_VBD", "Start"), - NC_("SC_OPCODE_VBD", "Start. The first period for depreciation in the same time unit as the useful life."), - NC_("SC_OPCODE_VBD", "End"), - NC_("SC_OPCODE_VBD", "End. The last period of the depreciation using the same time unit as for the useful life."), - NC_("SC_OPCODE_VBD", "Factor"), - NC_("SC_OPCODE_VBD", "Factor. The factor for the reduction of the depreciation. Factor = 2 denotes double rate depreciation."), - NC_("SC_OPCODE_VBD", "NoSwitch"), - NC_("SC_OPCODE_VBD", "NoSwitch = 0 denotes switch to linear depreciation, NoSwitch = 1 do not switch.") + NC_("ocVBD", "Variable declining balance. Returns the declining balance depreciation for a particular period."), + NC_("ocVBD", "Cost"), + NC_("ocVBD", "Cost. The initial cost of the asset."), + NC_("ocVBD", "Salvage"), + NC_("ocVBD", "Salvage. The salvage value of an asset at the end of its useful life."), + NC_("ocVBD", "Life"), + NC_("ocVBD", "Useful life. The number of periods in the useful life of the asset."), + NC_("ocVBD", "Start"), + NC_("ocVBD", "Start. The first period for depreciation in the same time unit as the useful life."), + NC_("ocVBD", "End"), + NC_("ocVBD", "End. The last period of the depreciation using the same time unit as for the useful life."), + NC_("ocVBD", "Factor"), + NC_("ocVBD", "Factor. The factor for the reduction of the depreciation. Factor = 2 denotes double rate depreciation."), + NC_("ocVBD", "NoSwitch"), + NC_("ocVBD", "NoSwitch = 0 denotes switch to linear depreciation, NoSwitch = 1 do not switch.") }; // -=*# Resource for function EFFECT #*=- -const TranslateId SC_OPCODE_EFFECT_ARY[] = +const TranslateId ocEFFECT_ARY[] = { - NC_("SC_OPCODE_EFFECT", "Calculates the annual net interest rate for a nominal interest rate."), - NC_("SC_OPCODE_EFFECT", "NOM"), - NC_("SC_OPCODE_EFFECT", "Nominal interest"), - NC_("SC_OPCODE_EFFECT", "P"), - NC_("SC_OPCODE_EFFECT", "Periods. The number of interest payments per year.") + NC_("ocEFFECT", "Calculates the annual net interest rate for a nominal interest rate."), + NC_("ocEFFECT", "NOM"), + NC_("ocEFFECT", "Nominal interest"), + NC_("ocEFFECT", "P"), + NC_("ocEFFECT", "Periods. The number of interest payments per year.") }; // -=*# Resource for function NOMINAL #*=- -const TranslateId SC_OPCODE_NOMINAL_ARY[] = +const TranslateId ocNOMINAL_ARY[] = { - NC_("SC_OPCODE_NOMINAL", "Calculates the yearly nominal interest rate as an effective interest rate."), - NC_("SC_OPCODE_NOMINAL", "Effective rate"), - NC_("SC_OPCODE_NOMINAL", "The effective interest rate"), - NC_("SC_OPCODE_NOMINAL", "NPER"), - NC_("SC_OPCODE_NOMINAL", "Periods. The number of interest payment per year.") + NC_("ocNOMINAL", "Calculates the yearly nominal interest rate as an effective interest rate."), + NC_("ocNOMINAL", "Effective rate"), + NC_("ocNOMINAL", "The effective interest rate"), + NC_("ocNOMINAL", "NPER"), + NC_("ocNOMINAL", "Periods. The number of interest payment per year.") }; // -=*# Resource for function NPV #*=- -const TranslateId SC_OPCODE_NPV_ARY[] = +const TranslateId ocNPV_ARY[] = { - NC_("SC_OPCODE_NPV", "Net present value. Calculates the net present value of an investment based on a series of periodic payments and a discount rate."), - NC_("SC_OPCODE_NPV", "Rate"), - NC_("SC_OPCODE_NPV", "The rate of discount for one period."), - NC_("SC_OPCODE_NPV", "Value "), - NC_("SC_OPCODE_NPV", "Value 1, value 2,... are arguments representing payments and income.") + NC_("ocNPV", "Net present value. Calculates the net present value of an investment based on a series of periodic payments and a discount rate."), + NC_("ocNPV", "Rate"), + NC_("ocNPV", "The rate of discount for one period."), + NC_("ocNPV", "Value "), + NC_("ocNPV", "Value 1, value 2,... are arguments representing payments and income.") }; // -=*# Resource for function IRR #*=- -const TranslateId SC_OPCODE_IRR_ARY[] = +const TranslateId ocIRR_ARY[] = { - NC_("SC_OPCODE_IRR", "Returns the actuarial rate of interest of an investment excluding costs or profits."), - NC_("SC_OPCODE_IRR", "Values"), - NC_("SC_OPCODE_IRR", "An array or reference to cells whose contents correspond to the payments."), - NC_("SC_OPCODE_IRR", "Guess"), - NC_("SC_OPCODE_IRR", "Guess. An estimated value of the rate of return to be used for the iteration calculation.") + NC_("ocIRR", "Returns the actuarial rate of interest of an investment excluding costs or profits."), + NC_("ocIRR", "Values"), + NC_("ocIRR", "An array or reference to cells whose contents correspond to the payments."), + NC_("ocIRR", "Guess"), + NC_("ocIRR", "Guess. An estimated value of the rate of return to be used for the iteration calculation.") }; // -=*# Resource for function MIRR #*=- -const TranslateId SC_OPCODE_MIRR_ARY[] = +const TranslateId ocMIRR_ARY[] = { - NC_("SC_OPCODE_MIRR", "Returns the modified internal rate of return for a series of investments."), - NC_("SC_OPCODE_MIRR", "Values"), - NC_("SC_OPCODE_MIRR", "An array or reference to cells whose contents correspond to the payments."), - NC_("SC_OPCODE_MIRR", "Investment"), - NC_("SC_OPCODE_MIRR", "Interest rate for investments (the negative values in the array)."), - NC_("SC_OPCODE_MIRR", "Reinvest rate"), - NC_("SC_OPCODE_MIRR", "Interest rate for reinvestments (the positive values in the array).") + NC_("ocMIRR", "Returns the modified internal rate of return for a series of investments."), + NC_("ocMIRR", "Values"), + NC_("ocMIRR", "An array or reference to cells whose contents correspond to the payments."), + NC_("ocMIRR", "Investment"), + NC_("ocMIRR", "Interest rate for investments (the negative values in the array)."), + NC_("ocMIRR", "Reinvest rate"), + NC_("ocMIRR", "Interest rate for reinvestments (the positive values in the array).") }; // -=*# Resource for function ISPMT #*=- -const TranslateId SC_OPCODE_ISPMT_ARY[] = +const TranslateId ocISPMT_ARY[] = { - NC_("SC_OPCODE_ISPMT", "Returns the amount of interest for constant amortization rates."), - NC_("SC_OPCODE_ISPMT", "Rate"), - NC_("SC_OPCODE_ISPMT", "Interest rate for a single amortization rate."), - NC_("SC_OPCODE_ISPMT", "Period"), - NC_("SC_OPCODE_ISPMT", "Number of amortization periods for the calculation of the interest."), - NC_("SC_OPCODE_ISPMT", "Total periods"), - NC_("SC_OPCODE_ISPMT", "Sum total of amortization periods."), - NC_("SC_OPCODE_ISPMT", "Investment"), - NC_("SC_OPCODE_ISPMT", "Amount of the investment.") + NC_("ocISPMT", "Returns the amount of interest for constant amortization rates."), + NC_("ocISPMT", "Rate"), + NC_("ocISPMT", "Interest rate for a single amortization rate."), + NC_("ocISPMT", "Period"), + NC_("ocISPMT", "Number of amortization periods for the calculation of the interest."), + NC_("ocISPMT", "Total periods"), + NC_("ocISPMT", "Sum total of amortization periods."), + NC_("ocISPMT", "Investment"), + NC_("ocISPMT", "Amount of the investment.") }; // -=*# Resource for function PDURATION #*=- -const TranslateId SC_OPCODE_PDURATION_ARY[] = +const TranslateId ocPDURATION_ARY[] = { - NC_("SC_OPCODE_PDURATION", "Duration. Calculates the number of periods required by an investment to attain the desired value."), - NC_("SC_OPCODE_PDURATION", "Rate"), - NC_("SC_OPCODE_PDURATION", "The constant rate of interest."), - NC_("SC_OPCODE_PDURATION", "PV"), - NC_("SC_OPCODE_PDURATION", "The present value. The current value of the investment."), - NC_("SC_OPCODE_PDURATION", "FV"), - NC_("SC_OPCODE_PDURATION", "The future value of the investment.") + NC_("ocPDURATION", "Duration. Calculates the number of periods required by an investment to attain the desired value."), + NC_("ocPDURATION", "Rate"), + NC_("ocPDURATION", "The constant rate of interest."), + NC_("ocPDURATION", "PV"), + NC_("ocPDURATION", "The present value. The current value of the investment."), + NC_("ocPDURATION", "FV"), + NC_("ocPDURATION", "The future value of the investment.") }; // -=*# Resource for function RRI #*=- -const TranslateId SC_OPCODE_RRI_ARY[] = +const TranslateId ocRRI_ARY[] = { - NC_("SC_OPCODE_RRI", "Interest. Calculates the interest rate which represents the rate of return from an investment."), - NC_("SC_OPCODE_RRI", "Periods"), - NC_("SC_OPCODE_RRI", "The number of periods used in the calculation."), - NC_("SC_OPCODE_RRI", "PV"), - NC_("SC_OPCODE_RRI", "Present value. The current value of the investment."), - NC_("SC_OPCODE_RRI", "FV"), - NC_("SC_OPCODE_RRI", "The future value of the investment.") + NC_("ocRRI", "Interest. Calculates the interest rate which represents the rate of return from an investment."), + NC_("ocRRI", "Periods"), + NC_("ocRRI", "The number of periods used in the calculation."), + NC_("ocRRI", "PV"), + NC_("ocRRI", "Present value. The current value of the investment."), + NC_("ocRRI", "FV"), + NC_("ocRRI", "The future value of the investment.") }; // -=*# Resource for function ISREF #*=- -const TranslateId SC_OPCODE_IS_REF_ARY[] = +const TranslateId ocIS_REF_ARY[] = { - NC_("SC_OPCODE_IS_REF", "Returns TRUE if value is a reference."), - NC_("SC_OPCODE_IS_REF", "Value"), - NC_("SC_OPCODE_IS_REF", "The value to be tested.") + NC_("ocIS_REF", "Returns TRUE if value is a reference."), + NC_("ocIS_REF", "Value"), + NC_("ocIS_REF", "The value to be tested.") }; // -=*# Resource for function ISERR #*=- -const TranslateId SC_OPCODE_IS_ERR_ARY[] = +const TranslateId ocIS_ERR_ARY[] = { - NC_("SC_OPCODE_IS_ERR", "Returns TRUE if the value is an error value not equal to #N/A."), - NC_("SC_OPCODE_IS_ERR", "Value"), - NC_("SC_OPCODE_IS_ERR", "The value to be tested.") + NC_("ocIS_ERR", "Returns TRUE if the value is an error value not equal to #N/A."), + NC_("ocIS_ERR", "Value"), + NC_("ocIS_ERR", "The value to be tested.") }; // -=*# Resource for function ISERROR #*=- -const TranslateId SC_OPCODE_IS_ERROR_ARY[] = +const TranslateId ocIS_ERROR_ARY[] = { - NC_("SC_OPCODE_IS_ERROR", "Returns TRUE if the value is an error value."), - NC_("SC_OPCODE_IS_ERROR", "Value"), - NC_("SC_OPCODE_IS_ERROR", "The value to be tested.") + NC_("ocIS_ERROR", "Returns TRUE if the value is an error value."), + NC_("ocIS_ERROR", "Value"), + NC_("ocIS_ERROR", "The value to be tested.") }; // -=*# Resource for function ISBLANK #*=- -const TranslateId SC_OPCODE_IS_EMPTY_ARY[] = +const TranslateId ocIS_EMPTY_ARY[] = { - NC_("SC_OPCODE_IS_EMPTY", "Returns TRUE if value refers to an empty cell."), - NC_("SC_OPCODE_IS_EMPTY", "Value"), - NC_("SC_OPCODE_IS_EMPTY", "The value to be tested.") + NC_("ocIS_EMPTY", "Returns TRUE if value refers to an empty cell."), + NC_("ocIS_EMPTY", "Value"), + NC_("ocIS_EMPTY", "The value to be tested.") }; // -=*# Resource for function ISLOGICAL #*=- -const TranslateId SC_OPCODE_IS_LOGICAL_ARY[] = +const TranslateId ocIS_LOGICAL_ARY[] = { - NC_("SC_OPCODE_IS_LOGICAL", "Returns TRUE if the value carries a logical number format."), - NC_("SC_OPCODE_IS_LOGICAL", "Value"), - NC_("SC_OPCODE_IS_LOGICAL", "The value to be tested.") + NC_("ocIS_LOGICAL", "Returns TRUE if the value carries a logical number format."), + NC_("ocIS_LOGICAL", "Value"), + NC_("ocIS_LOGICAL", "The value to be tested.") }; // -=*# Resource for function ISNA #*=- -const TranslateId SC_OPCODE_IS_NV_ARY[] = +const TranslateId ocIS_NV_ARY[] = { - NC_("SC_OPCODE_IS_NV", "Returns TRUE if value equals #N/A."), - NC_("SC_OPCODE_IS_NV", "Value"), - NC_("SC_OPCODE_IS_NV", "The value to be tested.") + NC_("ocIS_NV", "Returns TRUE if value equals #N/A."), + NC_("ocIS_NV", "Value"), + NC_("ocIS_NV", "The value to be tested.") }; // -=*# Resource for function ISNONTEXT #*=- -const TranslateId SC_OPCODE_IS_NON_STRING_ARY[] = +const TranslateId ocIS_NON_STRING_ARY[] = { - NC_("SC_OPCODE_IS_NON_STRING", "Returns TRUE if the value is not text."), - NC_("SC_OPCODE_IS_NON_STRING", "Value"), - NC_("SC_OPCODE_IS_NON_STRING", "The value to be tested.") + NC_("ocIS_NON_STRING", "Returns TRUE if the value is not text."), + NC_("ocIS_NON_STRING", "Value"), + NC_("ocIS_NON_STRING", "The value to be tested.") }; // -=*# Resource for function ISTEXT #*=- -const TranslateId SC_OPCODE_IS_STRING_ARY[] = +const TranslateId ocIS_STRING_ARY[] = { - NC_("SC_OPCODE_IS_STRING", "Returns TRUE if value is text."), - NC_("SC_OPCODE_IS_STRING", "Value"), - NC_("SC_OPCODE_IS_STRING", "The value to be tested.") + NC_("ocIS_STRING", "Returns TRUE if value is text."), + NC_("ocIS_STRING", "Value"), + NC_("ocIS_STRING", "The value to be tested.") }; // -=*# Resource for function ISNUMBER #*=- -const TranslateId SC_OPCODE_IS_VALUE_ARY[] = +const TranslateId ocIS_VALUE_ARY[] = { - NC_("SC_OPCODE_IS_VALUE", "Returns TRUE if value is a number."), - NC_("SC_OPCODE_IS_VALUE", "Value"), - NC_("SC_OPCODE_IS_VALUE", "The value to be tested.") + NC_("ocIS_VALUE", "Returns TRUE if value is a number."), + NC_("ocIS_VALUE", "Value"), + NC_("ocIS_VALUE", "The value to be tested.") }; // -=*# Resource for function ISFORMULA #*=- -const TranslateId SC_OPCODE_IS_FORMULA_ARY[] = +const TranslateId ocIS_FORMULA_ARY[] = { - NC_("SC_OPCODE_IS_FORMULA", "Returns TRUE if the cell is a formula cell."), - NC_("SC_OPCODE_IS_FORMULA", "Reference"), - NC_("SC_OPCODE_IS_FORMULA", "The cell to be tested.") + NC_("ocIS_FORMULA", "Returns TRUE if the cell is a formula cell."), + NC_("ocIS_FORMULA", "Reference"), + NC_("ocIS_FORMULA", "The cell to be tested.") }; // -=*# Resource for function FORMULA #*=- -const TranslateId SC_OPCODE_FORMULA_ARY[] = +const TranslateId ocFORMULA_ARY[] = { - NC_("SC_OPCODE_FORMULA", "Returns the formula of a formula cell."), - NC_("SC_OPCODE_FORMULA", "Reference"), - NC_("SC_OPCODE_FORMULA", "The formula cell.") + NC_("ocFORMULA", "Returns the formula of a formula cell."), + NC_("ocFORMULA", "Reference"), + NC_("ocFORMULA", "The formula cell.") }; // -=*# Resource for function N #*=- -const TranslateId SC_OPCODE_N_ARY[] = +const TranslateId ocN_ARY[] = { - NC_("SC_OPCODE_N", "Converts a value to a number."), - NC_("SC_OPCODE_N", "Value"), - NC_("SC_OPCODE_N", "The value to be interpreted as a number.") + NC_("ocN", "Converts a value to a number."), + NC_("ocN", "Value"), + NC_("ocN", "The value to be interpreted as a number.") }; // -=*# Resource for function NA #*=- -const TranslateId SC_OPCODE_NO_VALUE_ARY[] = +const TranslateId ocNO_VALUE_ARY[] = { - NC_("SC_OPCODE_NO_VALUE", "Not available. Returns the error value #N/A.") + NC_("ocNO_VALUE", "Not available. Returns the error value #N/A.") }; // -=*# Resource for function TYPE #*=- -const TranslateId SC_OPCODE_TYPE_ARY[] = +const TranslateId ocTYPE_ARY[] = { - NC_("SC_OPCODE_TYPE", "Returns the data type of a value (1 = number, 2 = text, 4 = Boolean value, 8 = formula, 16 = error value, 64 = array)."), - NC_("SC_OPCODE_TYPE", "Value"), - NC_("SC_OPCODE_TYPE", "The value for which the data type is to be determined.") + NC_("ocTYPE", "Returns the data type of a value (1 = number, 2 = text, 4 = Boolean value, 8 = formula, 16 = error value, 64 = array)."), + NC_("ocTYPE", "Value"), + NC_("ocTYPE", "The value for which the data type is to be determined.") }; // -=*# Resource for function CELL #*=- -const TranslateId SC_OPCODE_CELL_ARY[] = +const TranslateId ocCELL_ARY[] = { - NC_("SC_OPCODE_CELL", "Determines information about address, formatting or contents of a cell."), - NC_("SC_OPCODE_CELL", "Info type"), - NC_("SC_OPCODE_CELL", "String that specifies the type of information."), - NC_("SC_OPCODE_CELL", "Reference"), - NC_("SC_OPCODE_CELL", "The position of the cell you want to examine.") + NC_("ocCELL", "Determines information about address, formatting or contents of a cell."), + NC_("ocCELL", "Info type"), + NC_("ocCELL", "String that specifies the type of information."), + NC_("ocCELL", "Reference"), + NC_("ocCELL", "The position of the cell you want to examine.") }; // -=*# Resource for function CURRENT #*=- -const TranslateId SC_OPCODE_CURRENT_ARY[] = +const TranslateId ocCURRENT_ARY[] = { - NC_("SC_OPCODE_CURRENT", "Calculates the current value of the formula at the present location.") + NC_("ocCURRENT", "Calculates the current value of the formula at the present location.") }; // -=*# Resource for function FALSE #*=- -const TranslateId SC_OPCODE_FALSE_ARY[] = +const TranslateId ocFALSE_ARY[] = { - NC_("SC_OPCODE_FALSE", "Defines the logical value as FALSE.") + NC_("ocFALSE", "Defines the logical value as FALSE.") }; // -=*# Resource for function NOT #*=- -const TranslateId SC_OPCODE_NOT_ARY[] = +const TranslateId ocNOT_ARY[] = { - NC_("SC_OPCODE_NOT", "Reverses the value of the argument."), - NC_("SC_OPCODE_NOT", "Logical value"), - NC_("SC_OPCODE_NOT", "An expression that can be either TRUE or FALSE.") + NC_("ocNOT", "Reverses the value of the argument."), + NC_("ocNOT", "Logical value"), + NC_("ocNOT", "An expression that can be either TRUE or FALSE.") }; // -=*# Resource for function TRUE #*=- -const TranslateId SC_OPCODE_TRUE_ARY[] = +const TranslateId ocTRUE_ARY[] = { - NC_("SC_OPCODE_TRUE", "Returns the logical value TRUE.") + NC_("ocTRUE", "Returns the logical value TRUE.") }; // -=*# Resource for function IF #*=- -const TranslateId SC_OPCODE_IF_ARY[] = +const TranslateId ocIF_ARY[] = { - NC_("SC_OPCODE_IF", "Specifies a logical test to be performed."), - NC_("SC_OPCODE_IF", "Test"), - NC_("SC_OPCODE_IF", "Any value or expression which can be either TRUE or FALSE."), - NC_("SC_OPCODE_IF", "Then value"), - NC_("SC_OPCODE_IF", "The result of the function if the logical test returns a TRUE."), - NC_("SC_OPCODE_IF", "Otherwise value"), - NC_("SC_OPCODE_IF", "The result of the function if the logical test returns FALSE.") + NC_("ocIF", "Specifies a logical test to be performed."), + NC_("ocIF", "Test"), + NC_("ocIF", "Any value or expression which can be either TRUE or FALSE."), + NC_("ocIF", "Then value"), + NC_("ocIF", "The result of the function if the logical test returns a TRUE."), + NC_("ocIF", "Otherwise value"), + NC_("ocIF", "The result of the function if the logical test returns FALSE.") }; // -=*# Resource for function IFERROR #*=- -const TranslateId SC_OPCODE_IF_ERROR_ARY[] = +const TranslateId ocIF_ERROR_ARY[] = { - NC_("SC_OPCODE_IF_ERROR", "Returns value if not an error value, else alternative."), - NC_("SC_OPCODE_IF_ERROR", "Value"), - NC_("SC_OPCODE_IF_ERROR", "The value to be calculated."), - NC_("SC_OPCODE_IF_ERROR", "Alternative value"), - NC_("SC_OPCODE_IF_ERROR", "The alternative to be returned, should value be an error value.") + NC_("ocIF_ERROR", "Returns value if not an error value, else alternative."), + NC_("ocIF_ERROR", "Value"), + NC_("ocIF_ERROR", "The value to be calculated."), + NC_("ocIF_ERROR", "Alternative value"), + NC_("ocIF_ERROR", "The alternative to be returned, should value be an error value.") }; // -=*# Resource for function IFNA #*=- -const TranslateId SC_OPCODE_IF_NA_ARY[] = +const TranslateId ocIF_NA_ARY[] = { - NC_("SC_OPCODE_IF_NA", "Returns value if not a #N/A error, else alternative."), - NC_("SC_OPCODE_IF_NA", "Value"), - NC_("SC_OPCODE_IF_NA", "The value to be calculated."), - NC_("SC_OPCODE_IF_NA", "Alternative value"), - NC_("SC_OPCODE_IF_NA", "The alternative to be returned, should value be a #N/A error.") + NC_("ocIF_NA", "Returns value if not a #N/A error, else alternative."), + NC_("ocIF_NA", "Value"), + NC_("ocIF_NA", "The value to be calculated."), + NC_("ocIF_NA", "Alternative value"), + NC_("ocIF_NA", "The alternative to be returned, should value be a #N/A error.") }; // -=*# Resource for function OR #*=- -const TranslateId SC_OPCODE_OR_ARY[] = +const TranslateId ocOR_ARY[] = { - NC_("SC_OPCODE_OR", "Returns TRUE if an argument is TRUE."), - NC_("SC_OPCODE_OR", "Logical value "), - NC_("SC_OPCODE_OR", "Logical value 1, logical value 2,... are conditions to be tested and which return either TRUE or FALSE.") + NC_("ocOR", "Returns TRUE if an argument is TRUE."), + NC_("ocOR", "Logical value "), + NC_("ocOR", "Logical value 1, logical value 2,... are conditions to be tested and which return either TRUE or FALSE.") }; // -=*# Resource for function XOR #*=- -const TranslateId SC_OPCODE_XOR_ARY[] = +const TranslateId ocXOR_ARY[] = { - NC_("SC_OPCODE_XOR", "Returns TRUE if an odd number of arguments evaluates to TRUE."), - NC_("SC_OPCODE_XOR", "Logical value "), - NC_("SC_OPCODE_XOR", "Logical value 1, logical value 2, ... are conditions to be tested and which return either TRUE or FALSE.") + NC_("ocXOR", "Returns TRUE if an odd number of arguments evaluates to TRUE."), + NC_("ocXOR", "Logical value "), + NC_("ocXOR", "Logical value 1, logical value 2, ... are conditions to be tested and which return either TRUE or FALSE.") }; // -=*# Resource for function AND #*=- -const TranslateId SC_OPCODE_AND_ARY[] = +const TranslateId ocAND_ARY[] = { - NC_("SC_OPCODE_AND", "Returns TRUE if all arguments are TRUE."), - NC_("SC_OPCODE_AND", "Logical value "), - NC_("SC_OPCODE_AND", "Logical value 1, logical value 2;...are conditions to be tested and each returns either TRUE or FALSE.") + NC_("ocAND", "Returns TRUE if all arguments are TRUE."), + NC_("ocAND", "Logical value "), + NC_("ocAND", "Logical value 1, logical value 2;...are conditions to be tested and each returns either TRUE or FALSE.") }; // -=*# Resource for function ABS #*=- -const TranslateId SC_OPCODE_ABS_ARY[] = +const TranslateId ocABS_ARY[] = { - NC_("SC_OPCODE_ABS", "Absolute value of a number."), - NC_("SC_OPCODE_ABS", "Number"), - NC_("SC_OPCODE_ABS", "The number whose absolute value is to be returned.") + NC_("ocABS", "Absolute value of a number."), + NC_("ocABS", "Number"), + NC_("ocABS", "The number whose absolute value is to be returned.") }; // -=*# Resource for function POWER #*=- -const TranslateId SC_OPCODE_POWER_ARY[] = +const TranslateId ocPOWER_ARY[] = { - NC_("SC_OPCODE_POWER", "Returns a^b, base a raised to the power of exponent b."), - NC_("SC_OPCODE_POWER", "Base"), - NC_("SC_OPCODE_POWER", "The base a of the power a^b."), - NC_("SC_OPCODE_POWER", "Exponent"), - NC_("SC_OPCODE_POWER", "The exponent b of the power a^b.") + NC_("ocPOWER", "Returns a^b, base a raised to the power of exponent b."), + NC_("ocPOWER", "Base"), + NC_("ocPOWER", "The base a of the power a^b."), + NC_("ocPOWER", "Exponent"), + NC_("ocPOWER", "The exponent b of the power a^b.") }; // -=*# Resource for function COUNTBLANK #*=- -const TranslateId SC_OPCODE_COUNT_EMPTY_CELLS_ARY[] = +const TranslateId ocCOUNT_EMPTY_CELLS_ARY[] = { - NC_("SC_OPCODE_COUNT_EMPTY_CELLS", "Counts the blank cells in a specified range."), - NC_("SC_OPCODE_COUNT_EMPTY_CELLS", "Range"), - NC_("SC_OPCODE_COUNT_EMPTY_CELLS", "The range in which empty cells are to be counted.") + NC_("ocCOUNT_EMPTY_CELLS", "Counts the blank cells in a specified range."), + NC_("ocCOUNT_EMPTY_CELLS", "Range"), + NC_("ocCOUNT_EMPTY_CELLS", "The range in which empty cells are to be counted.") }; // -=*# Resource for function PI #*=- -const TranslateId SC_OPCODE_PI_ARY[] = +const TranslateId ocPI_ARY[] = { - NC_("SC_OPCODE_PI", "Returns the value of the number Pi.") + NC_("ocPI", "Returns the value of the number Pi.") }; // -=*# Resource for function SUM #*=- -const TranslateId SC_OPCODE_SUM_ARY[] = +const TranslateId ocSUM_ARY[] = { - NC_("SC_OPCODE_SUM", "Returns the sum of all arguments."), - NC_("SC_OPCODE_SUM", "Number "), - NC_("SC_OPCODE_SUM", "Number 1, number 2, ... are arguments whose total is to be calculated.") + NC_("ocSUM", "Returns the sum of all arguments."), + NC_("ocSUM", "Number "), + NC_("ocSUM", "Number 1, number 2, ... are arguments whose total is to be calculated.") }; // -=*# Resource for function SUMSQ #*=- -const TranslateId SC_OPCODE_SUM_SQ_ARY[] = +const TranslateId ocSUM_SQ_ARY[] = { - NC_("SC_OPCODE_SUM_SQ", "Returns the sum of the squares of the arguments."), - NC_("SC_OPCODE_SUM_SQ", "Number "), - NC_("SC_OPCODE_SUM_SQ", "Number 1, number 2,... are arguments for which the sum of the squares is to be calculated.") + NC_("ocSUM_SQ", "Returns the sum of the squares of the arguments."), + NC_("ocSUM_SQ", "Number "), + NC_("ocSUM_SQ", "Number 1, number 2,... are arguments for which the sum of the squares is to be calculated.") }; // -=*# Resource for function PRODUCT #*=- -const TranslateId SC_OPCODE_PRODUCT_ARY[] = +const TranslateId ocPRODUCT_ARY[] = { - NC_("SC_OPCODE_PRODUCT", "Multiplies the arguments."), - NC_("SC_OPCODE_PRODUCT", "Number "), - NC_("SC_OPCODE_PRODUCT", "Number 1, number 2, ... are arguments to be multiplied and a result returned.") + NC_("ocPRODUCT", "Multiplies the arguments."), + NC_("ocPRODUCT", "Number "), + NC_("ocPRODUCT", "Number 1, number 2, ... are arguments to be multiplied and a result returned.") }; // -=*# Resource for function SUMIF #*=- -const TranslateId SC_OPCODE_SUM_IF_ARY[] = +const TranslateId ocSUM_IF_ARY[] = { - NC_("SC_OPCODE_SUM_IF", "Totals the arguments that meet the condition."), - NC_("SC_OPCODE_SUM_IF", "Range"), - NC_("SC_OPCODE_SUM_IF", "The range to be evaluated by the criteria given."), - NC_("SC_OPCODE_SUM_IF", "Criteria"), - NC_("SC_OPCODE_SUM_IF", "The criteria to be applied to the range."), - NC_("SC_OPCODE_SUM_IF", "Sum range"), - NC_("SC_OPCODE_SUM_IF", "The range from which the values are to be totalled.") + NC_("ocSUM_IF", "Totals the arguments that meet the condition."), + NC_("ocSUM_IF", "Range"), + NC_("ocSUM_IF", "The range to be evaluated by the criteria given."), + NC_("ocSUM_IF", "Criteria"), + NC_("ocSUM_IF", "The criteria to be applied to the range."), + NC_("ocSUM_IF", "Sum range"), + NC_("ocSUM_IF", "The range from which the values are to be totalled.") }; // -=*# Resource for function AVERAGEIF #*=- -const TranslateId SC_OPCODE_AVERAGE_IF_ARY[] = +const TranslateId ocAVERAGE_IF_ARY[] = { - NC_("SC_OPCODE_AVERAGE_IF", "Averages the arguments that meet the conditions."), - NC_("SC_OPCODE_AVERAGE_IF", "Range"), - NC_("SC_OPCODE_AVERAGE_IF", "The range to be evaluated by the criteria given."), - NC_("SC_OPCODE_AVERAGE_IF", "Criteria"), - NC_("SC_OPCODE_AVERAGE_IF", "The criteria to be applied to the range."), - NC_("SC_OPCODE_AVERAGE_IF", "Average range"), - NC_("SC_OPCODE_AVERAGE_IF", "The range from which the values are to be averaged.") + NC_("ocAVERAGE_IF", "Averages the arguments that meet the conditions."), + NC_("ocAVERAGE_IF", "Range"), + NC_("ocAVERAGE_IF", "The range to be evaluated by the criteria given."), + NC_("ocAVERAGE_IF", "Criteria"), + NC_("ocAVERAGE_IF", "The criteria to be applied to the range."), + NC_("ocAVERAGE_IF", "Average range"), + NC_("ocAVERAGE_IF", "The range from which the values are to be averaged.") }; -const TranslateId SC_OPCODE_SUM_IFS_ARY[] = +const TranslateId ocSUM_IFS_ARY[] = { - NC_("SC_OPCODE_SUM_IFS", "Totals the values of cells in a range that meet multiple criteria in multiple ranges."), - NC_("SC_OPCODE_SUM_IFS", "Sum range"), - NC_("SC_OPCODE_SUM_IFS", "The range from which the values are to be totalled."), - NC_("SC_OPCODE_SUM_IFS", "Range "), - NC_("SC_OPCODE_SUM_IFS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), - NC_("SC_OPCODE_SUM_IFS", "Criteria "), - NC_("SC_OPCODE_SUM_IFS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") + NC_("ocSUM_IFS", "Totals the values of cells in a range that meet multiple criteria in multiple ranges."), + NC_("ocSUM_IFS", "Sum range"), + NC_("ocSUM_IFS", "The range from which the values are to be totalled."), + NC_("ocSUM_IFS", "Range "), + NC_("ocSUM_IFS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), + NC_("ocSUM_IFS", "Criteria "), + NC_("ocSUM_IFS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") }; // -=*# Resource for function AVERAGEIFS #*=- -const TranslateId SC_OPCODE_AVERAGE_IFS_ARY[] = +const TranslateId ocAVERAGE_IFS_ARY[] = { - NC_("SC_OPCODE_AVERAGE_IFS", "Averages the value of the cells that meet multiple criteria in multiple ranges."), - NC_("SC_OPCODE_AVERAGE_IFS", "Average range"), - NC_("SC_OPCODE_AVERAGE_IFS", "The range from which the values are to be averaged."), - NC_("SC_OPCODE_AVERAGE_IFS", "Range "), - NC_("SC_OPCODE_AVERAGE_IFS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), - NC_("SC_OPCODE_AVERAGE_IFS", "Criteria "), - NC_("SC_OPCODE_AVERAGE_IFS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") + NC_("ocAVERAGE_IFS", "Averages the value of the cells that meet multiple criteria in multiple ranges."), + NC_("ocAVERAGE_IFS", "Average range"), + NC_("ocAVERAGE_IFS", "The range from which the values are to be averaged."), + NC_("ocAVERAGE_IFS", "Range "), + NC_("ocAVERAGE_IFS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), + NC_("ocAVERAGE_IFS", "Criteria "), + NC_("ocAVERAGE_IFS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") }; // -=*# Resource for function COUNTIFS #*=- -const TranslateId SC_OPCODE_COUNT_IFS_ARY[] = +const TranslateId ocCOUNT_IFS_ARY[] = { - NC_("SC_OPCODE_COUNT_IFS", "Counts the cells that meet multiple criteria in multiple ranges."), - NC_("SC_OPCODE_COUNT_IFS", "Range "), - NC_("SC_OPCODE_COUNT_IFS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), - NC_("SC_OPCODE_COUNT_IFS", "Criteria "), - NC_("SC_OPCODE_COUNT_IFS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") + NC_("ocCOUNT_IFS", "Counts the cells that meet multiple criteria in multiple ranges."), + NC_("ocCOUNT_IFS", "Range "), + NC_("ocCOUNT_IFS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), + NC_("ocCOUNT_IFS", "Criteria "), + NC_("ocCOUNT_IFS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") }; // -=*# Resource for function COUNTIF #*=- -const TranslateId SC_OPCODE_COUNT_IF_ARY[] = +const TranslateId ocCOUNT_IF_ARY[] = { - NC_("SC_OPCODE_COUNT_IF", "Counts the arguments which meet the set conditions."), - NC_("SC_OPCODE_COUNT_IF", "Range"), - NC_("SC_OPCODE_COUNT_IF", "The range of cells to be evaluated by the criteria given."), - NC_("SC_OPCODE_COUNT_IF", "Criteria"), - NC_("SC_OPCODE_COUNT_IF", "The criteria to be applied to the range.") + NC_("ocCOUNT_IF", "Counts the arguments which meet the set conditions."), + NC_("ocCOUNT_IF", "Range"), + NC_("ocCOUNT_IF", "The range of cells to be evaluated by the criteria given."), + NC_("ocCOUNT_IF", "Criteria"), + NC_("ocCOUNT_IF", "The criteria to be applied to the range.") }; // -=*# Resource for function SQRT #*=- -const TranslateId SC_OPCODE_SQRT_ARY[] = +const TranslateId ocSQRT_ARY[] = { - NC_("SC_OPCODE_SQRT", "Returns the square root of a number."), - NC_("SC_OPCODE_SQRT", "Number"), - NC_("SC_OPCODE_SQRT", "A positive value for which the square root is to be calculated.") + NC_("ocSQRT", "Returns the square root of a number."), + NC_("ocSQRT", "Number"), + NC_("ocSQRT", "A positive value for which the square root is to be calculated.") }; // -=*# Resource for function RAND #*=- -const TranslateId SC_OPCODE_RANDOM_ARY[] = +const TranslateId ocRANDOM_ARY[] = { - NC_("SC_OPCODE_RANDOM", "Returns a random number between 0 and 1.") + NC_("ocRANDOM", "Returns a random number between 0 and 1.") }; // -=*# Resource for function ISEVEN #*=- -const TranslateId SC_OPCODE_IS_EVEN_ARY[] = +const TranslateId ocIS_EVEN_ARY[] = { - NC_("SC_OPCODE_IS_EVEN", "Returns TRUE if the value truncated to integer is even."), - NC_("SC_OPCODE_IS_EVEN", "Value"), - NC_("SC_OPCODE_IS_EVEN", "The value to be tested.") + NC_("ocIS_EVEN", "Returns TRUE if the value truncated to integer is even."), + NC_("ocIS_EVEN", "Value"), + NC_("ocIS_EVEN", "The value to be tested.") }; // -=*# Resource for function ISODD #*=- -const TranslateId SC_OPCODE_IS_ODD_ARY[] = +const TranslateId ocIS_ODD_ARY[] = { - NC_("SC_OPCODE_IS_ODD", "Returns TRUE if the value truncated to integer is odd."), - NC_("SC_OPCODE_IS_ODD", "Value"), - NC_("SC_OPCODE_IS_ODD", "The value to be tested.") + NC_("ocIS_ODD", "Returns TRUE if the value truncated to integer is odd."), + NC_("ocIS_ODD", "Value"), + NC_("ocIS_ODD", "The value to be tested.") }; // -=*# Resource for function COMBIN #*=- -const TranslateId SC_OPCODE_COMBIN_ARY[] = +const TranslateId ocCOMBIN_ARY[] = { - NC_("SC_OPCODE_COMBIN", "Calculates the number of combinations for elements without repetition."), - NC_("SC_OPCODE_COMBIN", "Number 1"), - NC_("SC_OPCODE_COMBIN", "The total number of elements."), - NC_("SC_OPCODE_COMBIN", "Number 2"), - NC_("SC_OPCODE_COMBIN", "The number of elements selected.") + NC_("ocCOMBIN", "Calculates the number of combinations for elements without repetition."), + NC_("ocCOMBIN", "Number 1"), + NC_("ocCOMBIN", "The total number of elements."), + NC_("ocCOMBIN", "Number 2"), + NC_("ocCOMBIN", "The number of elements selected.") }; // -=*# Resource for function COMBINA #*=- -const TranslateId SC_OPCODE_COMBIN_A_ARY[] = +const TranslateId ocCOMBIN_A_ARY[] = { - NC_("SC_OPCODE_COMBIN_A", "Calculates the number of combinations of elements including repetition."), - NC_("SC_OPCODE_COMBIN_A", "Number 1"), - NC_("SC_OPCODE_COMBIN_A", "The total number of elements."), - NC_("SC_OPCODE_COMBIN_A", "Number 2"), - NC_("SC_OPCODE_COMBIN_A", "The number of elements selected.") + NC_("ocCOMBIN_A", "Calculates the number of combinations of elements including repetition."), + NC_("ocCOMBIN_A", "Number 1"), + NC_("ocCOMBIN_A", "The total number of elements."), + NC_("ocCOMBIN_A", "Number 2"), + NC_("ocCOMBIN_A", "The number of elements selected.") }; // -=*# Resource for function ARCCOS #*=- -const TranslateId SC_OPCODE_ARC_COS_ARY[] = +const TranslateId ocARC_COS_ARY[] = { - NC_("SC_OPCODE_ARC_COS", "Returns the arccosine of a number."), - NC_("SC_OPCODE_ARC_COS", "Number"), - NC_("SC_OPCODE_ARC_COS", "A value between -1 and 1 for which the arccosine is to be returned.") + NC_("ocARC_COS", "Returns the arccosine of a number."), + NC_("ocARC_COS", "Number"), + NC_("ocARC_COS", "A value between -1 and 1 for which the arccosine is to be returned.") }; // -=*# Resource for function ARCSIN #*=- -const TranslateId SC_OPCODE_ARC_SIN_ARY[] = +const TranslateId ocARC_SIN_ARY[] = { - NC_("SC_OPCODE_ARC_SIN", "Returns the arcsine of a number."), - NC_("SC_OPCODE_ARC_SIN", "Number"), - NC_("SC_OPCODE_ARC_SIN", "A value between -1 and 1 for which the arcsine is to be returned.") + NC_("ocARC_SIN", "Returns the arcsine of a number."), + NC_("ocARC_SIN", "Number"), + NC_("ocARC_SIN", "A value between -1 and 1 for which the arcsine is to be returned.") }; // -=*# Resource for function ARCCOSHYP #*=- -const TranslateId SC_OPCODE_ARC_COS_HYP_ARY[] = +const TranslateId ocARC_COS_HYP_ARY[] = { - NC_("SC_OPCODE_ARC_COS_HYP", "Returns the inverse hyperbolic cosine of a number."), - NC_("SC_OPCODE_ARC_COS_HYP", "Number"), - NC_("SC_OPCODE_ARC_COS_HYP", "A value greater than or equal to 1 for which the inverse hyperbolic cosine is to be returned.") + NC_("ocARC_COS_HYP", "Returns the inverse hyperbolic cosine of a number."), + NC_("ocARC_COS_HYP", "Number"), + NC_("ocARC_COS_HYP", "A value greater than or equal to 1 for which the inverse hyperbolic cosine is to be returned.") }; // -=*# Resource for function ARCSINHYP #*=- -const TranslateId SC_OPCODE_ARC_SIN_HYP_ARY[] = +const TranslateId ocARC_SIN_HYP_ARY[] = { - NC_("SC_OPCODE_ARC_SIN_HYP", "Returns the inverse hyperbolic sine of a number."), - NC_("SC_OPCODE_ARC_SIN_HYP", "Number"), - NC_("SC_OPCODE_ARC_SIN_HYP", "The value for which the inverse hyperbolic sine is to be returned.") + NC_("ocARC_SIN_HYP", "Returns the inverse hyperbolic sine of a number."), + NC_("ocARC_SIN_HYP", "Number"), + NC_("ocARC_SIN_HYP", "The value for which the inverse hyperbolic sine is to be returned.") }; // -=*# Resource for function ARCCOT #*=- -const TranslateId SC_OPCODE_ARC_COT_ARY[] = +const TranslateId ocARC_COT_ARY[] = { - NC_("SC_OPCODE_ARC_COT", "Returns the inverse cotangent of a number."), - NC_("SC_OPCODE_ARC_COT", "Number"), - NC_("SC_OPCODE_ARC_COT", "The value for which the inverse cotangent is to be returned.") + NC_("ocARC_COT", "Returns the inverse cotangent of a number."), + NC_("ocARC_COT", "Number"), + NC_("ocARC_COT", "The value for which the inverse cotangent is to be returned.") }; // -=*# Resource for function ARCTAN #*=- -const TranslateId SC_OPCODE_ARC_TAN_ARY[] = +const TranslateId ocARC_TAN_ARY[] = { - NC_("SC_OPCODE_ARC_TAN", "Returns the arctangent of a number."), - NC_("SC_OPCODE_ARC_TAN", "Number"), - NC_("SC_OPCODE_ARC_TAN", "The value for which the arctangent is to be returned.") + NC_("ocARC_TAN", "Returns the arctangent of a number."), + NC_("ocARC_TAN", "Number"), + NC_("ocARC_TAN", "The value for which the arctangent is to be returned.") }; // -=*# Resource for function ARCCOTHYP #*=- -const TranslateId SC_OPCODE_ARC_COT_HYP_ARY[] = +const TranslateId ocARC_COT_HYP_ARY[] = { - NC_("SC_OPCODE_ARC_COT_HYP", "Returns the inverse hyperbolic cotangent of a number."), - NC_("SC_OPCODE_ARC_COT_HYP", "Number"), - NC_("SC_OPCODE_ARC_COT_HYP", "A value smaller than -1 or greater than 1 for which the inverse hyperbolic cotangent is to be returned.") + NC_("ocARC_COT_HYP", "Returns the inverse hyperbolic cotangent of a number."), + NC_("ocARC_COT_HYP", "Number"), + NC_("ocARC_COT_HYP", "A value smaller than -1 or greater than 1 for which the inverse hyperbolic cotangent is to be returned.") }; // -=*# Resource for function ARCTANHYP #*=- -const TranslateId SC_OPCODE_ARC_TAN_HYP_ARY[] = +const TranslateId ocARC_TAN_HYP_ARY[] = { - NC_("SC_OPCODE_ARC_TAN_HYP", "Returns the inverse hyperbolic tangent of a number."), - NC_("SC_OPCODE_ARC_TAN_HYP", "Number"), - NC_("SC_OPCODE_ARC_TAN_HYP", "A value between -1 and 1 for which the inverse hyperbolic tangent is to be returned.") + NC_("ocARC_TAN_HYP", "Returns the inverse hyperbolic tangent of a number."), + NC_("ocARC_TAN_HYP", "Number"), + NC_("ocARC_TAN_HYP", "A value between -1 and 1 for which the inverse hyperbolic tangent is to be returned.") }; // -=*# Resource for function COS #*=- -const TranslateId SC_OPCODE_COS_ARY[] = +const TranslateId ocCOS_ARY[] = { - NC_("SC_OPCODE_COS", "Returns the cosine of a number."), - NC_("SC_OPCODE_COS", "Number"), - NC_("SC_OPCODE_COS", "The angle in the radians for which the cosine is to be returned.") + NC_("ocCOS", "Returns the cosine of a number."), + NC_("ocCOS", "Number"), + NC_("ocCOS", "The angle in the radians for which the cosine is to be returned.") }; // -=*# Resource for function SIN #*=- -const TranslateId SC_OPCODE_SIN_ARY[] = +const TranslateId ocSIN_ARY[] = { - NC_("SC_OPCODE_SIN", "Returns the sine of a number."), - NC_("SC_OPCODE_SIN", "Number"), - NC_("SC_OPCODE_SIN", "The angle in radians for which the sine is to be calculated.") + NC_("ocSIN", "Returns the sine of a number."), + NC_("ocSIN", "Number"), + NC_("ocSIN", "The angle in radians for which the sine is to be calculated.") }; // -=*# Resource for function COT #*=- -const TranslateId SC_OPCODE_COT_ARY[] = +const TranslateId ocCOT_ARY[] = { - NC_("SC_OPCODE_COT", "Returns the cotangent of a number."), - NC_("SC_OPCODE_COT", "Number"), - NC_("SC_OPCODE_COT", "The angle in radians whose cotangent value is to be returned.") + NC_("ocCOT", "Returns the cotangent of a number."), + NC_("ocCOT", "Number"), + NC_("ocCOT", "The angle in radians whose cotangent value is to be returned.") }; // -=*# Resource for function TAN #*=- -const TranslateId SC_OPCODE_TAN_ARY[] = +const TranslateId ocTAN_ARY[] = { - NC_("SC_OPCODE_TAN", "Returns the tangent of a number."), - NC_("SC_OPCODE_TAN", "Number"), - NC_("SC_OPCODE_TAN", "The angle in radians for which the tangent is to be calculated.") + NC_("ocTAN", "Returns the tangent of a number."), + NC_("ocTAN", "Number"), + NC_("ocTAN", "The angle in radians for which the tangent is to be calculated.") }; // -=*# Resource for function COSHYP #*=- -const TranslateId SC_OPCODE_COS_HYP_ARY[] = +const TranslateId ocCOS_HYP_ARY[] = { - NC_("SC_OPCODE_COS_HYP", "Returns the hyperbolic cosine of a number."), - NC_("SC_OPCODE_COS_HYP", "Number"), - NC_("SC_OPCODE_COS_HYP", "The value for which the hyperbolic cosine is to be returned.") + NC_("ocCOS_HYP", "Returns the hyperbolic cosine of a number."), + NC_("ocCOS_HYP", "Number"), + NC_("ocCOS_HYP", "The value for which the hyperbolic cosine is to be returned.") }; // -=*# Resource for function SINHYP #*=- -const TranslateId SC_OPCODE_SIN_HYP_ARY[] = +const TranslateId ocSIN_HYP_ARY[] = { - NC_("SC_OPCODE_SIN_HYP", "Returns the hyperbolic sine of a number."), - NC_("SC_OPCODE_SIN_HYP", "Number"), - NC_("SC_OPCODE_SIN_HYP", "The value for which the hyperbolic sine is to be calculated.") + NC_("ocSIN_HYP", "Returns the hyperbolic sine of a number."), + NC_("ocSIN_HYP", "Number"), + NC_("ocSIN_HYP", "The value for which the hyperbolic sine is to be calculated.") }; // -=*# Resource for function COTHYP #*=- -const TranslateId SC_OPCODE_COT_HYP_ARY[] = +const TranslateId ocCOT_HYP_ARY[] = { - NC_("SC_OPCODE_COT_HYP", "Returns the hyperbolic cotangent of a number."), - NC_("SC_OPCODE_COT_HYP", "Number"), - NC_("SC_OPCODE_COT_HYP", "A value not equal to 0 for which the hyperbolic cotangent is to be returned.") + NC_("ocCOT_HYP", "Returns the hyperbolic cotangent of a number."), + NC_("ocCOT_HYP", "Number"), + NC_("ocCOT_HYP", "A value not equal to 0 for which the hyperbolic cotangent is to be returned.") }; // -=*# Resource for function TANHYP #*=- -const TranslateId SC_OPCODE_TAN_HYP_ARY[] = +const TranslateId ocTAN_HYP_ARY[] = { - NC_("SC_OPCODE_TAN_HYP", "Returns the hyperbolic tangent of a number."), - NC_("SC_OPCODE_TAN_HYP", "Number"), - NC_("SC_OPCODE_TAN_HYP", "The value for which the hyperbolic tangent is to be calculated.") + NC_("ocTAN_HYP", "Returns the hyperbolic tangent of a number."), + NC_("ocTAN_HYP", "Number"), + NC_("ocTAN_HYP", "The value for which the hyperbolic tangent is to be calculated.") }; // -=*# Resource for function ARCTAN2 #*=- -const TranslateId SC_OPCODE_ARC_TAN_2_ARY[] = +const TranslateId ocARC_TAN_2_ARY[] = { - NC_("SC_OPCODE_ARC_TAN_2", "Returns the arctangent for the specified coordinates."), - NC_("SC_OPCODE_ARC_TAN_2", "Number X"), - NC_("SC_OPCODE_ARC_TAN_2", "The value for the X coordinate."), - NC_("SC_OPCODE_ARC_TAN_2", "Number Y"), - NC_("SC_OPCODE_ARC_TAN_2", "The value for the Y coordinate.") + NC_("ocARC_TAN_2", "Returns the arctangent for the specified coordinates."), + NC_("ocARC_TAN_2", "Number X"), + NC_("ocARC_TAN_2", "The value for the X coordinate."), + NC_("ocARC_TAN_2", "Number Y"), + NC_("ocARC_TAN_2", "The value for the Y coordinate.") }; // -=*# Resource for function CSC #*=- -const TranslateId SC_OPCODE_COSECANT_ARY[] = +const TranslateId ocCOSECANT_ARY[] = { - NC_("SC_OPCODE_COSECANT", "Return the cosecant of an angle. CSC(x)=1/SIN(x)"), - NC_("SC_OPCODE_COSECANT", "Angle"), - NC_("SC_OPCODE_COSECANT", "The angle in radians for which the cosecant is to be calculated.") + NC_("ocCOSECANT", "Return the cosecant of an angle. CSC(x)=1/SIN(x)"), + NC_("ocCOSECANT", "Angle"), + NC_("ocCOSECANT", "The angle in radians for which the cosecant is to be calculated.") }; // -=*# Resource for function SEC #*=- -const TranslateId SC_OPCODE_SECANT_ARY[] = +const TranslateId ocSECANT_ARY[] = { - NC_("SC_OPCODE_SECANT", "Return the secant of an angle. SEC(x)=1/COS(x)"), - NC_("SC_OPCODE_SECANT", "Angle"), - NC_("SC_OPCODE_SECANT", "The angle in radians for which the secant is to be calculated.") + NC_("ocSECANT", "Return the secant of an angle. SEC(x)=1/COS(x)"), + NC_("ocSECANT", "Angle"), + NC_("ocSECANT", "The angle in radians for which the secant is to be calculated.") }; // -=*# Resource for function CSCH #*=- -const TranslateId SC_OPCODE_COSECANT_HYP_ARY[] = +const TranslateId ocCOSECANT_HYP_ARY[] = { - NC_("SC_OPCODE_COSECANT_HYP", "Return the hyperbolic cosecant of a hyperbolic angle. CSCH(x)=1/SINH(x)"), - NC_("SC_OPCODE_COSECANT_HYP", "Angle"), - NC_("SC_OPCODE_COSECANT_HYP", "The hyperbolic angle in radians for which the hyperbolic cosecant is to be calculated.") + NC_("ocCOSECANT_HYP", "Return the hyperbolic cosecant of a hyperbolic angle. CSCH(x)=1/SINH(x)"), + NC_("ocCOSECANT_HYP", "Angle"), + NC_("ocCOSECANT_HYP", "The hyperbolic angle in radians for which the hyperbolic cosecant is to be calculated.") }; // -=*# Resource for function SECH #*=- -const TranslateId SC_OPCODE_SECANT_HYP_ARY[] = +const TranslateId ocSECANT_HYP_ARY[] = { - NC_("SC_OPCODE_SECANT_HYP", "Return the hyperbolic secant of a hyperbolic angle. SECH(x)=1/COSH(x)"), - NC_("SC_OPCODE_SECANT_HYP", "Angle"), - NC_("SC_OPCODE_SECANT_HYP", "The hyperbolic angle in radians for which the hyperbolic secant is to be calculated.") + NC_("ocSECANT_HYP", "Return the hyperbolic secant of a hyperbolic angle. SECH(x)=1/COSH(x)"), + NC_("ocSECANT_HYP", "Angle"), + NC_("ocSECANT_HYP", "The hyperbolic angle in radians for which the hyperbolic secant is to be calculated.") }; // -=*# Resource for function DEG #*=- -const TranslateId SC_OPCODE_DEG_ARY[] = +const TranslateId ocDEG_ARY[] = { - NC_("SC_OPCODE_DEG", "Converts a radian to degrees"), - NC_("SC_OPCODE_DEG", "Number"), - NC_("SC_OPCODE_DEG", "The angle in a radian") + NC_("ocDEG", "Converts a radian to degrees"), + NC_("ocDEG", "Number"), + NC_("ocDEG", "The angle in a radian") }; // -=*# Resource for function RAD #*=- -const TranslateId SC_OPCODE_RAD_ARY[] = +const TranslateId ocRAD_ARY[] = { - NC_("SC_OPCODE_RAD", "Converts degrees to radians"), - NC_("SC_OPCODE_RAD", "Number"), - NC_("SC_OPCODE_RAD", "The angle in degrees.") + NC_("ocRAD", "Converts degrees to radians"), + NC_("ocRAD", "Number"), + NC_("ocRAD", "The angle in degrees.") }; // -=*# Resource for function EXP #*=- -const TranslateId SC_OPCODE_EXP_ARY[] = +const TranslateId ocEXP_ARY[] = { - NC_("SC_OPCODE_EXP", "Calculates the exponent for basis e."), - NC_("SC_OPCODE_EXP", "Number"), - NC_("SC_OPCODE_EXP", "The exponent applied to base e.") + NC_("ocEXP", "Calculates the exponent for basis e."), + NC_("ocEXP", "Number"), + NC_("ocEXP", "The exponent applied to base e.") }; // -=*# Resource for function LOG #*=- -const TranslateId SC_OPCODE_LOG_ARY[] = +const TranslateId ocLOG_ARY[] = { - NC_("SC_OPCODE_LOG", "Calculates the logarithm to any specified base."), - NC_("SC_OPCODE_LOG", "Number"), - NC_("SC_OPCODE_LOG", "A value greater than 0 for which the logarithm is to be calculated."), - NC_("SC_OPCODE_LOG", "Base"), - NC_("SC_OPCODE_LOG", "The base of the logarithm. If omitted, the base is regarded as 10.") + NC_("ocLOG", "Calculates the logarithm to any specified base."), + NC_("ocLOG", "Number"), + NC_("ocLOG", "A value greater than 0 for which the logarithm is to be calculated."), + NC_("ocLOG", "Base"), + NC_("ocLOG", "The base of the logarithm. If omitted, the base is regarded as 10.") }; // -=*# Resource for function LN #*=- -const TranslateId SC_OPCODE_LN_ARY[] = +const TranslateId ocLN_ARY[] = { - NC_("SC_OPCODE_LN", "Calculates the natural logarithm of a number."), - NC_("SC_OPCODE_LN", "Number"), - NC_("SC_OPCODE_LN", "A value greater than 0 for which the natural logarithm is to be calculated.") + NC_("ocLN", "Calculates the natural logarithm of a number."), + NC_("ocLN", "Number"), + NC_("ocLN", "A value greater than 0 for which the natural logarithm is to be calculated.") }; // -=*# Resource for function LOG10 #*=- -const TranslateId SC_OPCODE_LOG10_ARY[] = +const TranslateId ocLOG10_ARY[] = { - NC_("SC_OPCODE_LOG10", "Calculates the base-10 logarithm of a number."), - NC_("SC_OPCODE_LOG10", "Number"), - NC_("SC_OPCODE_LOG10", "A value greater than 0 for which the logarithm is to be calculated.") + NC_("ocLOG10", "Calculates the base-10 logarithm of a number."), + NC_("ocLOG10", "Number"), + NC_("ocLOG10", "A value greater than 0 for which the logarithm is to be calculated.") }; // -=*# Resource for function FACT #*=- -const TranslateId SC_OPCODE_FACT_ARY[] = +const TranslateId ocFACT_ARY[] = { - NC_("SC_OPCODE_FACT", "Calculates the factorial of a number."), - NC_("SC_OPCODE_FACT", "Number"), - NC_("SC_OPCODE_FACT", "The number for which the factorial is to be calculated.") + NC_("ocFACT", "Calculates the factorial of a number."), + NC_("ocFACT", "Number"), + NC_("ocFACT", "The number for which the factorial is to be calculated.") }; // -=*# Resource for function MOD #*=- -const TranslateId SC_OPCODE_MOD_ARY[] = +const TranslateId ocMOD_ARY[] = { - NC_("SC_OPCODE_MOD", "Calculates the remainder of a division."), - NC_("SC_OPCODE_MOD", "Dividend"), - NC_("SC_OPCODE_MOD", "The number to be divided."), - NC_("SC_OPCODE_MOD", "Divisor"), - NC_("SC_OPCODE_MOD", "The number by which the dividend is divided.") + NC_("ocMOD", "Calculates the remainder of a division."), + NC_("ocMOD", "Dividend"), + NC_("ocMOD", "The number to be divided."), + NC_("ocMOD", "Divisor"), + NC_("ocMOD", "The number by which the dividend is divided.") }; // -=*# Resource for function SIGN #*=- -const TranslateId SC_OPCODE_PLUS_MINUS_ARY[] = +const TranslateId ocPLUS_MINUS_ARY[] = { - NC_("SC_OPCODE_PLUS_MINUS", "Returns the algebraic sign of a number."), - NC_("SC_OPCODE_PLUS_MINUS", "Number"), - NC_("SC_OPCODE_PLUS_MINUS", "The number for which the algebraic sign is to be determined.") + NC_("ocPLUS_MINUS", "Returns the algebraic sign of a number."), + NC_("ocPLUS_MINUS", "Number"), + NC_("ocPLUS_MINUS", "The number for which the algebraic sign is to be determined.") }; // -=*# Resource for function SUBTOTAL #*=- -const TranslateId SC_OPCODE_SUB_TOTAL_ARY[] = +const TranslateId ocSUB_TOTAL_ARY[] = { - NC_("SC_OPCODE_SUB_TOTAL", "Calculates subtotals in a spreadsheet."), - NC_("SC_OPCODE_SUB_TOTAL", "Function"), - NC_("SC_OPCODE_SUB_TOTAL", "Function index. Is an index of the possible functions Total, Max, ..."), - NC_("SC_OPCODE_SUB_TOTAL", "Range"), - NC_("SC_OPCODE_SUB_TOTAL", "The cells of the range which are to be taken into account.") + NC_("ocSUB_TOTAL", "Calculates subtotals in a spreadsheet."), + NC_("ocSUB_TOTAL", "Function"), + NC_("ocSUB_TOTAL", "Function index. Is an index of the possible functions Total, Max, ..."), + NC_("ocSUB_TOTAL", "Range"), + NC_("ocSUB_TOTAL", "The cells of the range which are to be taken into account.") }; // -=*# Resource for function AGGREGATE #*=- -const TranslateId SC_OPCODE_AGGREGATE_ARY[] = +const TranslateId ocAGGREGATE_ARY[] = { - NC_("SC_OPCODE_AGGREGATE", "Calculates an aggregate in a spreadsheet."), - NC_("SC_OPCODE_AGGREGATE", "Function"), - NC_("SC_OPCODE_AGGREGATE", "Function index. Is an index of the possible functions Total, Max, ..."), - NC_("SC_OPCODE_AGGREGATE", "Options"), - NC_("SC_OPCODE_AGGREGATE", "Option index. Is an index of the possible ignore options."), - NC_("SC_OPCODE_AGGREGATE", "Reference 1 or array"), - NC_("SC_OPCODE_AGGREGATE", "The cell(s) of the range which are to be taken into account."), - NC_("SC_OPCODE_AGGREGATE", "Reference 2..n or k "), - NC_("SC_OPCODE_AGGREGATE", "The cells of the range which are to be taken into account or mandatory 2nd argument for certain functions.") + NC_("ocAGGREGATE", "Calculates an aggregate in a spreadsheet."), + NC_("ocAGGREGATE", "Function"), + NC_("ocAGGREGATE", "Function index. Is an index of the possible functions Total, Max, ..."), + NC_("ocAGGREGATE", "Options"), + NC_("ocAGGREGATE", "Option index. Is an index of the possible ignore options."), + NC_("ocAGGREGATE", "Reference 1 or array"), + NC_("ocAGGREGATE", "The cell(s) of the range which are to be taken into account."), + NC_("ocAGGREGATE", "Reference 2..n or k "), + NC_("ocAGGREGATE", "The cells of the range which are to be taken into account or mandatory 2nd argument for certain functions.") }; // -=*# Resource for function INT #*=- -const TranslateId SC_OPCODE_INT_ARY[] = +const TranslateId ocINT_ARY[] = { - NC_("SC_OPCODE_INT", "Rounds a number down to the nearest integer."), - NC_("SC_OPCODE_INT", "Number"), - NC_("SC_OPCODE_INT", "The number to be rounded down.") + NC_("ocINT", "Rounds a number down to the nearest integer."), + NC_("ocINT", "Number"), + NC_("ocINT", "The number to be rounded down.") }; // -=*# Resource for function TRUNC #*=- -const TranslateId SC_OPCODE_TRUNC_ARY[] = +const TranslateId ocTRUNC_ARY[] = { - NC_("SC_OPCODE_TRUNC", "Truncates the decimal places of a number."), - NC_("SC_OPCODE_TRUNC", "Number"), - NC_("SC_OPCODE_TRUNC", "The number to be truncated."), - NC_("SC_OPCODE_TRUNC", "Count"), - NC_("SC_OPCODE_TRUNC", "The number of places after the decimal point that are not to be truncated.") + NC_("ocTRUNC", "Truncates the decimal places of a number."), + NC_("ocTRUNC", "Number"), + NC_("ocTRUNC", "The number to be truncated."), + NC_("ocTRUNC", "Count"), + NC_("ocTRUNC", "The number of places after the decimal point that are not to be truncated.") }; // -=*# Resource for function ROUND #*=- -const TranslateId SC_OPCODE_ROUND_ARY[] = +const TranslateId ocROUND_ARY[] = { - NC_("SC_OPCODE_ROUND", "Rounds a number to a predefined accuracy."), - NC_("SC_OPCODE_ROUND", "Number"), - NC_("SC_OPCODE_ROUND", "The number to be rounded."), - NC_("SC_OPCODE_ROUND", "Count"), - NC_("SC_OPCODE_ROUND", "The number of places to which a number is to be rounded.") + NC_("ocROUND", "Rounds a number to a predefined accuracy."), + NC_("ocROUND", "Number"), + NC_("ocROUND", "The number to be rounded."), + NC_("ocROUND", "Count"), + NC_("ocROUND", "The number of places to which a number is to be rounded.") }; // -=*# Resource for function ROUNDUP #*=- -const TranslateId SC_OPCODE_ROUND_UP_ARY[] = +const TranslateId ocROUND_UP_ARY[] = { - NC_("SC_OPCODE_ROUND_UP", "Rounds a number up to the predefined accuracy."), - NC_("SC_OPCODE_ROUND_UP", "Number"), - NC_("SC_OPCODE_ROUND_UP", "The number to be rounded up."), - NC_("SC_OPCODE_ROUND_UP", "Count"), - NC_("SC_OPCODE_ROUND_UP", "The number of places to which a number is to be rounded.") + NC_("ocROUND_UP", "Rounds a number up to the predefined accuracy."), + NC_("ocROUND_UP", "Number"), + NC_("ocROUND_UP", "The number to be rounded up."), + NC_("ocROUND_UP", "Count"), + NC_("ocROUND_UP", "The number of places to which a number is to be rounded.") }; // -=*# Resource for function ROUNDDOWN #*=- -const TranslateId SC_OPCODE_ROUND_DOWN_ARY[] = +const TranslateId ocROUND_DOWN_ARY[] = { - NC_("SC_OPCODE_ROUND_DOWN", "Rounds a number down to a predefined accuracy."), - NC_("SC_OPCODE_ROUND_DOWN", "Number"), - NC_("SC_OPCODE_ROUND_DOWN", "The number to be rounded down."), - NC_("SC_OPCODE_ROUND_DOWN", "Count"), - NC_("SC_OPCODE_ROUND_DOWN", "The number of places down to which a number is to be rounded.") + NC_("ocROUND_DOWN", "Rounds a number down to a predefined accuracy."), + NC_("ocROUND_DOWN", "Number"), + NC_("ocROUND_DOWN", "The number to be rounded down."), + NC_("ocROUND_DOWN", "Count"), + NC_("ocROUND_DOWN", "The number of places down to which a number is to be rounded.") }; // -=*# Resource for function EVEN #*=- -const TranslateId SC_OPCODE_EVEN_ARY[] = +const TranslateId ocEVEN_ARY[] = { - NC_("SC_OPCODE_EVEN", "Rounds a positive number up and negative number down to the nearest even integer."), - NC_("SC_OPCODE_EVEN", "Number"), - NC_("SC_OPCODE_EVEN", "The number to be rounded up.") + NC_("ocEVEN", "Rounds a positive number up and negative number down to the nearest even integer."), + NC_("ocEVEN", "Number"), + NC_("ocEVEN", "The number to be rounded up.") }; // -=*# Resource for function ODD #*=- -const TranslateId SC_OPCODE_ODD_ARY[] = +const TranslateId ocODD_ARY[] = { - NC_("SC_OPCODE_ODD", "Rounds a positive number up and negative number down to the nearest odd integer."), - NC_("SC_OPCODE_ODD", "Number"), - NC_("SC_OPCODE_ODD", "The number to be rounded up.") + NC_("ocODD", "Rounds a positive number up and negative number down to the nearest odd integer."), + NC_("ocODD", "Number"), + NC_("ocODD", "The number to be rounded up.") }; // -=*# Resource for function CEILING.XCL #*=- -const TranslateId SC_OPCODE_CEIL_MS_ARY[] = +const TranslateId ocCEIL_MS_ARY[] = { - NC_("SC_OPCODE_CEIL_MS", "Rounds a number away from zero to the nearest multiple of significance.\nThis function exists for interoperability with Microsoft Excel 2007 or older versions."), - NC_("SC_OPCODE_CEIL_MS", "Number"), - NC_("SC_OPCODE_CEIL_MS", "The number to be rounded up."), - NC_("SC_OPCODE_CEIL_MS", "Significance"), - NC_("SC_OPCODE_CEIL_MS", "The number to whose multiple the value is rounded.") + NC_("ocCEIL_MS", "Rounds a number away from zero to the nearest multiple of significance.\nThis function exists for interoperability with Microsoft Excel 2007 or older versions."), + NC_("ocCEIL_MS", "Number"), + NC_("ocCEIL_MS", "The number to be rounded up."), + NC_("ocCEIL_MS", "Significance"), + NC_("ocCEIL_MS", "The number to whose multiple the value is rounded.") }; // -=*# Resource for function CEILING.PRECISE #*=- -const TranslateId SC_OPCODE_CEIL_PRECISE_ARY[] = +const TranslateId ocCEIL_PRECISE_ARY[] = { - NC_("SC_OPCODE_CEIL_PRECISE", "Rounds a number up to the nearest multiple of significance, regardless of sign of significance."), - NC_("SC_OPCODE_CEIL_PRECISE", "Number"), - NC_("SC_OPCODE_CEIL_PRECISE", "The number to be rounded up."), - NC_("SC_OPCODE_CEIL_PRECISE", "Significance"), - NC_("SC_OPCODE_CEIL_PRECISE", "The number to whose multiple the value is rounded.") + NC_("ocCEIL_PRECISE", "Rounds a number up to the nearest multiple of significance, regardless of sign of significance."), + NC_("ocCEIL_PRECISE", "Number"), + NC_("ocCEIL_PRECISE", "The number to be rounded up."), + NC_("ocCEIL_PRECISE", "Significance"), + NC_("ocCEIL_PRECISE", "The number to whose multiple the value is rounded.") }; // -=*# Resource for function ISO.CEILING #*=- -const TranslateId SC_OPCODE_CEIL_ISO_ARY[] = +const TranslateId ocCEIL_ISO_ARY[] = { - NC_("SC_OPCODE_CEIL_ISO", "Rounds a number up to the nearest multiple of significance, regardless of sign of significance."), - NC_("SC_OPCODE_CEIL_ISO", "Number"), - NC_("SC_OPCODE_CEIL_ISO", "The number to be rounded up."), - NC_("SC_OPCODE_CEIL_ISO", "Significance"), - NC_("SC_OPCODE_CEIL_ISO", "The number to whose multiple the value is rounded.") + NC_("ocCEIL_ISO", "Rounds a number up to the nearest multiple of significance, regardless of sign of significance."), + NC_("ocCEIL_ISO", "Number"), + NC_("ocCEIL_ISO", "The number to be rounded up."), + NC_("ocCEIL_ISO", "Significance"), + NC_("ocCEIL_ISO", "The number to whose multiple the value is rounded.") }; // -=*# Resource for function CEILING #*=- -const TranslateId SC_OPCODE_CEIL_ARY[] = +const TranslateId ocCEIL_ARY[] = { - NC_("SC_OPCODE_CEIL", "Rounds a number up to the nearest multiple of significance."), - NC_("SC_OPCODE_CEIL", "Number"), - NC_("SC_OPCODE_CEIL", "The number to be rounded up."), - NC_("SC_OPCODE_CEIL", "Significance"), - NC_("SC_OPCODE_CEIL", "If given the number to whose multiple the value is rounded, else -1 or 1 depending on sign of Number."), - NC_("SC_OPCODE_CEIL", "Mode"), - NC_("SC_OPCODE_CEIL", "If given and not equal to zero then rounded up according to amount when a negative number and significance.") + NC_("ocCEIL", "Rounds a number up to the nearest multiple of significance."), + NC_("ocCEIL", "Number"), + NC_("ocCEIL", "The number to be rounded up."), + NC_("ocCEIL", "Significance"), + NC_("ocCEIL", "If given the number to whose multiple the value is rounded, else -1 or 1 depending on sign of Number."), + NC_("ocCEIL", "Mode"), + NC_("ocCEIL", "If given and not equal to zero then rounded up according to amount when a negative number and significance.") }; // -=*# Resource for function CEILING.MATH #*=- -const TranslateId SC_OPCODE_CEIL_MATH_ARY[] = +const TranslateId ocCEIL_MATH_ARY[] = { - NC_("SC_OPCODE_CEIL_MATH", "Rounds a number up to the nearest multiple of significance."), - NC_("SC_OPCODE_CEIL_MATH", "Number"), - NC_("SC_OPCODE_CEIL_MATH", "The number to be rounded up."), - NC_("SC_OPCODE_CEIL_MATH", "Significance"), - NC_("SC_OPCODE_CEIL_MATH", "If given the number to whose multiple the value is rounded, else 1."), - NC_("SC_OPCODE_CEIL_MATH", "Mode"), - NC_("SC_OPCODE_CEIL_MATH", "For negative numbers; if given and not equal to zero then rounds away from zero, else rounds towards zero.") + NC_("ocCEIL_MATH", "Rounds a number up to the nearest multiple of significance."), + NC_("ocCEIL_MATH", "Number"), + NC_("ocCEIL_MATH", "The number to be rounded up."), + NC_("ocCEIL_MATH", "Significance"), + NC_("ocCEIL_MATH", "If given the number to whose multiple the value is rounded, else 1."), + NC_("ocCEIL_MATH", "Mode"), + NC_("ocCEIL_MATH", "For negative numbers; if given and not equal to zero then rounds away from zero, else rounds towards zero.") }; // -=*# Resource for function FLOOR #*=- -const TranslateId SC_OPCODE_FLOOR_ARY[] = +const TranslateId ocFLOOR_ARY[] = { - NC_("SC_OPCODE_FLOOR", "Rounds number down to the nearest multiple of significance."), - NC_("SC_OPCODE_FLOOR", "Number"), - NC_("SC_OPCODE_FLOOR", "The number to be rounded down."), - NC_("SC_OPCODE_FLOOR", "Significance"), - NC_("SC_OPCODE_FLOOR", "The number to whose multiple the value is to be rounded down."), - NC_("SC_OPCODE_FLOOR", "Mode"), - NC_("SC_OPCODE_FLOOR", "If given and not equal to zero then rounded towards zero with negative number and significance.") + NC_("ocFLOOR", "Rounds number down to the nearest multiple of significance."), + NC_("ocFLOOR", "Number"), + NC_("ocFLOOR", "The number to be rounded down."), + NC_("ocFLOOR", "Significance"), + NC_("ocFLOOR", "The number to whose multiple the value is to be rounded down."), + NC_("ocFLOOR", "Mode"), + NC_("ocFLOOR", "If given and not equal to zero then rounded towards zero with negative number and significance.") }; // -=*# Resource for function FLOOR.XCL #*=- -const TranslateId SC_OPCODE_FLOOR_MS_ARY[] = +const TranslateId ocFLOOR_MS_ARY[] = { - NC_("SC_OPCODE_FLOOR_MS", "Rounds number towards zero to the nearest multiple of absolute value of significance.\nThis function exists for interoperability with Microsoft Excel 2007 or older versions."), - NC_("SC_OPCODE_FLOOR_MS", "Number"), - NC_("SC_OPCODE_FLOOR_MS", "The number to be rounded down."), - NC_("SC_OPCODE_FLOOR_MS", "Significance"), - NC_("SC_OPCODE_FLOOR_MS", "The number to whose multiple the value is to be rounded down.") + NC_("ocFLOOR_MS", "Rounds number towards zero to the nearest multiple of absolute value of significance.\nThis function exists for interoperability with Microsoft Excel 2007 or older versions."), + NC_("ocFLOOR_MS", "Number"), + NC_("ocFLOOR_MS", "The number to be rounded down."), + NC_("ocFLOOR_MS", "Significance"), + NC_("ocFLOOR_MS", "The number to whose multiple the value is to be rounded down.") }; // -=*# Resource for function FLOOR.MATH #*=- -const TranslateId SC_OPCODE_FLOOR_MATH_ARY[] = +const TranslateId ocFLOOR_MATH_ARY[] = { - NC_("SC_OPCODE_FLOOR_MATH", "Rounds number down to the nearest multiple of significance, regardless of sign of significance."), - NC_("SC_OPCODE_FLOOR_MATH", "Number"), - NC_("SC_OPCODE_FLOOR_MATH", "The number to be rounded down."), - NC_("SC_OPCODE_FLOOR_MATH", "Significance"), - NC_("SC_OPCODE_FLOOR_MATH", "The number to whose multiple the value is to be rounded down."), - NC_("SC_OPCODE_FLOOR_MATH", "Mode"), - NC_("SC_OPCODE_FLOOR_MATH", "For negative numbers; if given and not equal to or less than zero rounds towards zero.") + NC_("ocFLOOR_MATH", "Rounds number down to the nearest multiple of significance, regardless of sign of significance."), + NC_("ocFLOOR_MATH", "Number"), + NC_("ocFLOOR_MATH", "The number to be rounded down."), + NC_("ocFLOOR_MATH", "Significance"), + NC_("ocFLOOR_MATH", "The number to whose multiple the value is to be rounded down."), + NC_("ocFLOOR_MATH", "Mode"), + NC_("ocFLOOR_MATH", "For negative numbers; if given and not equal to or less than zero rounds towards zero.") }; // -=*# Resource for function FLOOR.PRECISE #*=- -const TranslateId SC_OPCODE_FLOOR_PRECISE_ARY[] = +const TranslateId ocFLOOR_PRECISE_ARY[] = { - NC_("SC_OPCODE_FLOOR_PRECISE", "Rounds number down (towards -∞) to the nearest multiple of significance."), - NC_("SC_OPCODE_FLOOR_PRECISE", "Number"), - NC_("SC_OPCODE_FLOOR_PRECISE", "The number to be rounded down."), - NC_("SC_OPCODE_FLOOR_PRECISE", "Significance"), - NC_("SC_OPCODE_FLOOR_PRECISE", "The number to whose multiple the value is to be rounded down. Sign has no meaning.") + NC_("ocFLOOR_PRECISE", "Rounds number down (towards -∞) to the nearest multiple of significance."), + NC_("ocFLOOR_PRECISE", "Number"), + NC_("ocFLOOR_PRECISE", "The number to be rounded down."), + NC_("ocFLOOR_PRECISE", "Significance"), + NC_("ocFLOOR_PRECISE", "The number to whose multiple the value is to be rounded down. Sign has no meaning.") }; // -=*# Resource for function GCD #*=- -const TranslateId SC_OPCODE_GCD_ARY[] = +const TranslateId ocGCD_ARY[] = { - NC_("SC_OPCODE_GCD", "Greatest Common Divisor"), - NC_("SC_OPCODE_GCD", "Integer "), - NC_("SC_OPCODE_GCD", "Integer 1; integer 2,... are integers for which the greatest common divisor is to be calculated.") + NC_("ocGCD", "Greatest Common Divisor"), + NC_("ocGCD", "Integer "), + NC_("ocGCD", "Integer 1; integer 2,... are integers for which the greatest common divisor is to be calculated.") }; // -=*# Resource for function LCM #*=- -const TranslateId SC_OPCODE_LCM_ARY[] = +const TranslateId ocLCM_ARY[] = { - NC_("SC_OPCODE_LCM", "Lowest common multiple"), - NC_("SC_OPCODE_LCM", "Integer "), - NC_("SC_OPCODE_LCM", "Integer 1; integer 2,... are integers whose smallest common multiple is to be calculated.") + NC_("ocLCM", "Lowest common multiple"), + NC_("ocLCM", "Integer "), + NC_("ocLCM", "Integer 1; integer 2,... are integers whose smallest common multiple is to be calculated.") }; // -=*# Resource for function TRANSPOSE #*=- -const TranslateId SC_OPCODE_MAT_TRANS_ARY[] = +const TranslateId ocMAT_TRANS_ARY[] = { - NC_("SC_OPCODE_MAT_TRANS", "Array transposition. Exchanges the rows and columns of an array."), - NC_("SC_OPCODE_MAT_TRANS", "Array"), - NC_("SC_OPCODE_MAT_TRANS", "The array in which the rows and columns have been transposed.") + NC_("ocMAT_TRANS", "Array transposition. Exchanges the rows and columns of an array."), + NC_("ocMAT_TRANS", "Array"), + NC_("ocMAT_TRANS", "The array in which the rows and columns have been transposed.") }; // -=*# Resource for function MMULT #*=- -const TranslateId SC_OPCODE_MAT_MULT_ARY[] = +const TranslateId ocMAT_MULT_ARY[] = { - NC_("SC_OPCODE_MAT_MULT", "Array multiplication. Returns the product of two arrays."), - NC_("SC_OPCODE_MAT_MULT", "Array 1"), - NC_("SC_OPCODE_MAT_MULT", "The first array for the array product."), - NC_("SC_OPCODE_MAT_MULT", "Array 2"), - NC_("SC_OPCODE_MAT_MULT", "The second array having the same number of rows as the first array has columns.") + NC_("ocMAT_MULT", "Array multiplication. Returns the product of two arrays."), + NC_("ocMAT_MULT", "Array 1"), + NC_("ocMAT_MULT", "The first array for the array product."), + NC_("ocMAT_MULT", "Array 2"), + NC_("ocMAT_MULT", "The second array having the same number of rows as the first array has columns.") }; // -=*# Resource for function MDETERM #*=- -const TranslateId SC_OPCODE_MAT_DET_ARY[] = +const TranslateId ocMAT_DET_ARY[] = { - NC_("SC_OPCODE_MAT_DET", "Returns the array determinant."), - NC_("SC_OPCODE_MAT_DET", "Array"), - NC_("SC_OPCODE_MAT_DET", "The array for which the determinant is to be determined.") + NC_("ocMAT_DET", "Returns the array determinant."), + NC_("ocMAT_DET", "Array"), + NC_("ocMAT_DET", "The array for which the determinant is to be determined.") }; // -=*# Resource for function MINVERSE #*=- -const TranslateId SC_OPCODE_MAT_INV_ARY[] = +const TranslateId ocMAT_INV_ARY[] = { - NC_("SC_OPCODE_MAT_INV", "Returns the inverse of an array."), - NC_("SC_OPCODE_MAT_INV", "Array"), - NC_("SC_OPCODE_MAT_INV", "The array to be inverted.") + NC_("ocMAT_INV", "Returns the inverse of an array."), + NC_("ocMAT_INV", "Array"), + NC_("ocMAT_INV", "The array to be inverted.") }; // -=*# Resource for function MUNIT #*=- -const TranslateId SC_OPCODE_MATRIX_UNIT_ARY[] = +const TranslateId ocMATRIX_UNIT_ARY[] = { - NC_("SC_OPCODE_MATRIX_UNIT", "Returns the unitary square array of a certain size."), - NC_("SC_OPCODE_MATRIX_UNIT", "Dimensions"), - NC_("SC_OPCODE_MATRIX_UNIT", "The size of the unitary array.") + NC_("ocMATRIX_UNIT", "Returns the unitary square array of a certain size."), + NC_("ocMATRIX_UNIT", "Dimensions"), + NC_("ocMATRIX_UNIT", "The size of the unitary array.") +}; + +// -=*# Resources for function BYCOL #*=- +const TranslateId ocBYCOL_ARY[] = +{ + NC_("ocBYCOL", "Applies a function to each column of an array. Returns a single-row array of the same width."), + NC_("ocBYCOL", "Array"), + NC_("ocBYCOL", "An array to calculate."), + NC_("ocBYCOL", "Function"), + NC_("ocBYCOL", "A function (LAMBDA or otherwise) that will be called on each column of the array.") +}; + +// -=*# Resources for function BYROW #*=- +const TranslateId ocBYROW_ARY[] = +{ + NC_("ocBYROW", "Applies a function to each row of an array. Returns a single-column array of the same height."), + NC_("ocBYROW", "Array"), + NC_("ocBYROW", "An array to calculate."), + NC_("ocBYROW", "Function"), + NC_("ocBYROW", "A function (LAMBDA or otherwise) that will be called on each row of the array.") +}; + +// -=*# Resource for function MAKEARRAY #*=- +const TranslateId ocMAKEARRAY_ARY[] = +{ + NC_("ocMAKEARRAY", "Array generation. Creates an array of certain dimensions, with generated contents."), + NC_("ocMAKEARRAY", "Rows"), + NC_("ocMAKEARRAY", "The number of rows the new array should have."), + NC_("ocMAKEARRAY", "Columns"), + NC_("ocMAKEARRAY", "The number of columns the new array should have."), + NC_("ocMAKEARRAY", "Generator"), + NC_("ocMAKEARRAY", "A LAMBDA function that is called with (row, column) values to generate each element of the array.") +}; + +// -=*# Resources for function MAP #*=- +const TranslateId ocMAP_ARY[] = +{ + NC_("ocMAP", "Results in an array where each cell is computed by applying a formula to the corresponding cells of one or more input arrays."), + NC_("ocMAP", "Array 1"), + NC_("ocMAP", "The array that provides the arguments to the formula."), + NC_("ocMAP", "Formula or Array 2"), + NC_("ocMAP", "Additional arrays or a formula expression defined by a LAMBDA function or similar. The formula or function must be the final argument of the MAP function."), + NC_("ocMAP", "Formula or Array "), + NC_("ocMAP", "Additional arrays or a formula expression defined by a LAMBDA function or similar. The formula or function must be the final argument of the MAP function.") +}; + +// -=*# Resources for function REDUCE #*=- +const TranslateId ocREDUCE_ARY[] = +{ + NC_("ocREDUCE", "Applies a custom LAMBDA function to each element in a given array and accumulates results to a single value."), + NC_("ocREDUCE", "Initial Value"), + NC_("ocREDUCE", "Optional initial value of the accumulator."), + NC_("ocREDUCE", "Array"), + NC_("ocREDUCE", "The array to be reduced."), + NC_("ocREDUCE", "Formula"), + NC_("ocREDUCE", "A formula expression or LAMBDA function that will be called on each cell of the array.") +}; + +// -=*# Resources for function SCAN #*=- +const TranslateId ocSCAN_ARY[] = +{ + NC_("ocSCAN", "Progressively applies a LAMBDA function to each element in an array and returns an array of all intermediate values."), + NC_("ocSCAN", "Initial value"), + NC_("ocSCAN", "Optional initial value of the accumulator."), + NC_("ocSCAN", "Array"), + NC_("ocSCAN", "The array to be scanned."), + NC_("ocSCAN", "Formula"), + NC_("ocSCAN", "A LAMBDA function that will be called on each cell of the array.") }; // -=*# Resource for function SUMPRODUCT #*=- -const TranslateId SC_OPCODE_SUM_PRODUCT_ARY[] = +const TranslateId ocSUM_PRODUCT_ARY[] = { - NC_("SC_OPCODE_SUM_PRODUCT", "(Inner products) Returns the sum of the products of array arguments."), - NC_("SC_OPCODE_SUM_PRODUCT", "Array "), - NC_("SC_OPCODE_SUM_PRODUCT", "Array 1, array 2, ... are arrays whose arguments are to be multiplied.") + NC_("ocSUM_PRODUCT", "(Inner products) Returns the sum of the products of array arguments."), + NC_("ocSUM_PRODUCT", "Array "), + NC_("ocSUM_PRODUCT", "Array 1, array 2, ... are arrays whose arguments are to be multiplied.") }; // -=*# Resource for function SUMX2MY2 #*=- -const TranslateId SC_OPCODE_SUM_X2MY2_ARY[] = +const TranslateId ocSUM_X2MY2_ARY[] = { - NC_("SC_OPCODE_SUM_X2MY2", "Returns the sum of the difference of squares of two arrays."), - NC_("SC_OPCODE_SUM_X2MY2", "Array X"), - NC_("SC_OPCODE_SUM_X2MY2", "First array where the square of the arguments are totalled."), - NC_("SC_OPCODE_SUM_X2MY2", "Array Y"), - NC_("SC_OPCODE_SUM_X2MY2", "Second array where the square of the arguments is to be subtracted.") + NC_("ocSUM_X2MY2", "Returns the sum of the difference of squares of two arrays."), + NC_("ocSUM_X2MY2", "Array X"), + NC_("ocSUM_X2MY2", "First array where the square of the arguments are totalled."), + NC_("ocSUM_X2MY2", "Array Y"), + NC_("ocSUM_X2MY2", "Second array where the square of the arguments is to be subtracted.") }; // -=*# Resource for function SUMX2PY2 #*=- -const TranslateId SC_OPCODE_SUM_X2DY2_ARY[] = +const TranslateId ocSUM_X2DY2_ARY[] = { - NC_("SC_OPCODE_SUM_X2DY2", "Returns the total of the square sum of two arrays."), - NC_("SC_OPCODE_SUM_X2DY2", "Array X"), - NC_("SC_OPCODE_SUM_X2DY2", "First array where the square of the arguments are totalled."), - NC_("SC_OPCODE_SUM_X2DY2", "Array Y"), - NC_("SC_OPCODE_SUM_X2DY2", "Second array where the square of the arguments is to be totalled.") + NC_("ocSUM_X2DY2", "Returns the total of the square sum of two arrays."), + NC_("ocSUM_X2DY2", "Array X"), + NC_("ocSUM_X2DY2", "First array where the square of the arguments are totalled."), + NC_("ocSUM_X2DY2", "Array Y"), + NC_("ocSUM_X2DY2", "Second array where the square of the arguments is to be totalled.") }; // -=*# Resource for function SUMXMY2 #*=- -const TranslateId SC_OPCODE_SUM_XMY2_ARY[] = +const TranslateId ocSUM_XMY2_ARY[] = { - NC_("SC_OPCODE_SUM_XMY2", "Returns the sum of squares of differences of two arrays."), - NC_("SC_OPCODE_SUM_XMY2", "Array X"), - NC_("SC_OPCODE_SUM_XMY2", "First array for forming argument differences."), - NC_("SC_OPCODE_SUM_XMY2", "Array Y"), - NC_("SC_OPCODE_SUM_XMY2", "Second array for forming the argument differences.") + NC_("ocSUM_XMY2", "Returns the sum of squares of differences of two arrays."), + NC_("ocSUM_XMY2", "Array X"), + NC_("ocSUM_XMY2", "First array for forming argument differences."), + NC_("ocSUM_XMY2", "Array Y"), + NC_("ocSUM_XMY2", "Second array for forming the argument differences.") }; // -=*# Resource for function FREQUENCY #*=- -const TranslateId SC_OPCODE_FREQUENCY_ARY[] = +const TranslateId ocFREQUENCY_ARY[] = { - NC_("SC_OPCODE_FREQUENCY", "Returns a frequency distribution as a vertical array."), - NC_("SC_OPCODE_FREQUENCY", "Data"), - NC_("SC_OPCODE_FREQUENCY", "The array of the data."), - NC_("SC_OPCODE_FREQUENCY", "Classes"), - NC_("SC_OPCODE_FREQUENCY", "The array for forming classes.") + NC_("ocFREQUENCY", "Returns a frequency distribution as a vertical array."), + NC_("ocFREQUENCY", "Data"), + NC_("ocFREQUENCY", "The array of the data."), + NC_("ocFREQUENCY", "Classes"), + NC_("ocFREQUENCY", "The array for forming classes.") }; // -=*# Resource for function LINEST #*=- -const TranslateId SC_OPCODE_LINEST_ARY[] = +const TranslateId ocLINEST_ARY[] = { - NC_("SC_OPCODE_LINEST", "Calculates parameters of the linear regression as an array."), - NC_("SC_OPCODE_LINEST", "Data Y"), - NC_("SC_OPCODE_LINEST", "The Y data array."), - NC_("SC_OPCODE_LINEST", "Data X"), - NC_("SC_OPCODE_LINEST", "The X data array."), - NC_("SC_OPCODE_LINEST", "Linear type"), - NC_("SC_OPCODE_LINEST", "If type = 0 the linears will be calculated through the zero point, or else moved linears."), - NC_("SC_OPCODE_LINEST", "Stats"), - NC_("SC_OPCODE_LINEST", "If parameter = 0 then only the regression coefficient will be calculated, otherwise other values as well.") + NC_("ocLINEST", "Calculates parameters of the linear regression as an array."), + NC_("ocLINEST", "Data Y"), + NC_("ocLINEST", "The Y data array."), + NC_("ocLINEST", "Data X"), + NC_("ocLINEST", "The X data array."), + NC_("ocLINEST", "Linear type"), + NC_("ocLINEST", "If type = 0 the linears will be calculated through the zero point, or else moved linears."), + NC_("ocLINEST", "Stats"), + NC_("ocLINEST", "If parameter = 0 then only the regression coefficient will be calculated, otherwise other values as well.") }; // -=*# Resource for function LOGEST #*=- -const TranslateId SC_OPCODE_LOGEST_ARY[] = +const TranslateId ocLOGEST_ARY[] = { - NC_("SC_OPCODE_LOGEST", "Calculates the parameters of the exponential regression curve as an array."), - NC_("SC_OPCODE_LOGEST", "Data Y"), - NC_("SC_OPCODE_LOGEST", "The Y data array."), - NC_("SC_OPCODE_LOGEST", "Data X"), - NC_("SC_OPCODE_LOGEST", "The X data array."), - NC_("SC_OPCODE_LOGEST", "Function type"), - NC_("SC_OPCODE_LOGEST", "If type = 0 then the functions will be calculated in the form of y=m^x, or also functions y=b*m^x."), - NC_("SC_OPCODE_LOGEST", "Stats"), - NC_("SC_OPCODE_LOGEST", "If parameter = 0 then only the regression coefficient will be calculated, otherwise other values as well.") + NC_("ocLOGEST", "Calculates the parameters of the exponential regression curve as an array."), + NC_("ocLOGEST", "Data Y"), + NC_("ocLOGEST", "The Y data array."), + NC_("ocLOGEST", "Data X"), + NC_("ocLOGEST", "The X data array."), + NC_("ocLOGEST", "Function type"), + NC_("ocLOGEST", "If type = 0 then the functions will be calculated in the form of y=m^x, or also functions y=b*m^x."), + NC_("ocLOGEST", "Stats"), + NC_("ocLOGEST", "If parameter = 0 then only the regression coefficient will be calculated, otherwise other values as well.") }; // -=*# Resource for function TREND #*=- -const TranslateId SC_OPCODE_TREND_ARY[] = +const TranslateId ocTREND_ARY[] = { - NC_("SC_OPCODE_TREND", "Calculates points along a regression line."), - NC_("SC_OPCODE_TREND", "Data Y"), - NC_("SC_OPCODE_TREND", "The Y data array."), - NC_("SC_OPCODE_TREND", "Data X"), - NC_("SC_OPCODE_TREND", "The X data array as the basis for the regression."), - NC_("SC_OPCODE_TREND", "New data X"), - NC_("SC_OPCODE_TREND", "The array of X data for recalculating the values."), - NC_("SC_OPCODE_TREND", "Linear type"), - NC_("SC_OPCODE_TREND", "If type = 0 the linears will be calculated through the zero point, or else moved linears.") + NC_("ocTREND", "Calculates points along a regression line."), + NC_("ocTREND", "Data Y"), + NC_("ocTREND", "The Y data array."), + NC_("ocTREND", "Data X"), + NC_("ocTREND", "The X data array as the basis for the regression."), + NC_("ocTREND", "New data X"), + NC_("ocTREND", "The array of X data for recalculating the values."), + NC_("ocTREND", "Linear type"), + NC_("ocTREND", "If type = 0 the linears will be calculated through the zero point, or else moved linears.") }; // -=*# Resource for function GROWTH #*=- -const TranslateId SC_OPCODE_GROWTH_ARY[] = +const TranslateId ocGROWTH_ARY[] = { - NC_("SC_OPCODE_GROWTH", "Calculates points on the exponential regression function."), - NC_("SC_OPCODE_GROWTH", "Data Y"), - NC_("SC_OPCODE_GROWTH", "The Y data array."), - NC_("SC_OPCODE_GROWTH", "Data X"), - NC_("SC_OPCODE_GROWTH", "The X data array as the basis for the regression."), - NC_("SC_OPCODE_GROWTH", "New data X"), - NC_("SC_OPCODE_GROWTH", "The array of X data for recalculating the values."), - NC_("SC_OPCODE_GROWTH", "Function type"), - NC_("SC_OPCODE_GROWTH", "If type = 0 then the functions will be calculated in the form of y=m^x, or also functions y=b*m^x.") + NC_("ocGROWTH", "Calculates points on the exponential regression function."), + NC_("ocGROWTH", "Data Y"), + NC_("ocGROWTH", "The Y data array."), + NC_("ocGROWTH", "Data X"), + NC_("ocGROWTH", "The X data array as the basis for the regression."), + NC_("ocGROWTH", "New data X"), + NC_("ocGROWTH", "The array of X data for recalculating the values."), + NC_("ocGROWTH", "Function type"), + NC_("ocGROWTH", "If type = 0 then the functions will be calculated in the form of y=m^x, or also functions y=b*m^x.") }; // -=*# Resource for function COUNT #*=- -const TranslateId SC_OPCODE_COUNT_ARY[] = +const TranslateId ocCOUNT_ARY[] = { - NC_("SC_OPCODE_COUNT", "Counts how many numbers are in the list of arguments."), - NC_("SC_OPCODE_COUNT", "Value "), - NC_("SC_OPCODE_COUNT", "Value 1, value 2, ... are arguments containing different data types but where only numbers are counted.") + NC_("ocCOUNT", "Counts how many numbers are in the list of arguments."), + NC_("ocCOUNT", "Value "), + NC_("ocCOUNT", "Value 1, value 2, ... are arguments containing different data types but where only numbers are counted.") }; // -=*# Resource for function COUNTA #*=- -const TranslateId SC_OPCODE_COUNT_2_ARY[] = +const TranslateId ocCOUNT_2_ARY[] = { - NC_("SC_OPCODE_COUNT_2", "Counts how many values are in the list of arguments."), - NC_("SC_OPCODE_COUNT_2", "Value "), - NC_("SC_OPCODE_COUNT_2", "Value 1, value 2, ... are arguments representing the values to be counted.") + NC_("ocCOUNT_2", "Counts how many values are in the list of arguments."), + NC_("ocCOUNT_2", "Value "), + NC_("ocCOUNT_2", "Value 1, value 2, ... are arguments representing the values to be counted.") }; // -=*# Resource for function MAX #*=- -const TranslateId SC_OPCODE_MAX_ARY[] = +const TranslateId ocMAX_ARY[] = { - NC_("SC_OPCODE_MAX", "Returns the maximum value in a list of arguments."), - NC_("SC_OPCODE_MAX", "Number "), - NC_("SC_OPCODE_MAX", "Number 1, number 2, ... are numerical arguments for which the largest number is to be determined.") + NC_("ocMAX", "Returns the maximum value in a list of arguments."), + NC_("ocMAX", "Number "), + NC_("ocMAX", "Number 1, number 2, ... are numerical arguments for which the largest number is to be determined.") }; // -=*# Resource for function MAXA #*=- -const TranslateId SC_OPCODE_MAX_A_ARY[] = +const TranslateId ocMAX_A_ARY[] = { - NC_("SC_OPCODE_MAX_A", "Returns the maximum value in a list of arguments. Text is evaluated as Zero."), - NC_("SC_OPCODE_MAX_A", "Value "), - NC_("SC_OPCODE_MAX_A", "Value 1, value 2, are arguments whose largest value is to be determined.") + NC_("ocMAX_A", "Returns the maximum value in a list of arguments. Text is evaluated as Zero."), + NC_("ocMAX_A", "Value "), + NC_("ocMAX_A", "Value 1, value 2, are arguments whose largest value is to be determined.") }; // -=*# Resource for function MIN #*=- -const TranslateId SC_OPCODE_MIN_ARY[] = +const TranslateId ocMIN_ARY[] = { - NC_("SC_OPCODE_MIN", "Returns the minimum value in a list of arguments."), - NC_("SC_OPCODE_MIN", "Number "), - NC_("SC_OPCODE_MIN", "Number 1, number 2, ... are numerical arguments for which the smallest number is to be determined.") + NC_("ocMIN", "Returns the minimum value in a list of arguments."), + NC_("ocMIN", "Number "), + NC_("ocMIN", "Number 1, number 2, ... are numerical arguments for which the smallest number is to be determined.") }; // -=*# Resource for function MINA #*=- -const TranslateId SC_OPCODE_MIN_A_ARY[] = +const TranslateId ocMIN_A_ARY[] = { - NC_("SC_OPCODE_MIN_A", "Returns the smallest value in a list of arguments. Text is evaluated as zero."), - NC_("SC_OPCODE_MIN_A", "Value "), - NC_("SC_OPCODE_MIN_A", "Value 1; value 2;... are arguments whose smallest number is to be determined.") + NC_("ocMIN_A", "Returns the smallest value in a list of arguments. Text is evaluated as zero."), + NC_("ocMIN_A", "Value "), + NC_("ocMIN_A", "Value 1; value 2;... are arguments whose smallest number is to be determined.") }; // -=*# Resource for function VAR #*=- -const TranslateId SC_OPCODE_VAR_ARY[] = +const TranslateId ocVAR_ARY[] = { - NC_("SC_OPCODE_VAR", "Calculates the variance based on a sample."), - NC_("SC_OPCODE_VAR", "Number "), - NC_("SC_OPCODE_VAR", "Number 1, number 2, ... are numerical arguments which portray a sample of a population.") + NC_("ocVAR", "Calculates the variance based on a sample."), + NC_("ocVAR", "Number "), + NC_("ocVAR", "Number 1, number 2, ... are numerical arguments which portray a sample of a population.") }; // -=*# Resource for function VAR.S #*=- -const TranslateId SC_OPCODE_VAR_S_ARY[] = +const TranslateId ocVAR_S_ARY[] = { - NC_("SC_OPCODE_VAR_S", "Calculates the variance based on a sample."), - NC_("SC_OPCODE_VAR_S", "Number "), - NC_("SC_OPCODE_VAR_S", "Number 1, number 2, ... are numerical arguments which portray a sample of a population.") + NC_("ocVAR_S", "Calculates the variance based on a sample."), + NC_("ocVAR_S", "Number "), + NC_("ocVAR_S", "Number 1, number 2, ... are numerical arguments which portray a sample of a population.") }; // -=*# Resource for function VARA #*=- -const TranslateId SC_OPCODE_VAR_A_ARY[] = +const TranslateId ocVAR_A_ARY[] = { - NC_("SC_OPCODE_VAR_A", "Returns the variance based on a sample. Text is evaluated as zero."), - NC_("SC_OPCODE_VAR_A", "Value "), - NC_("SC_OPCODE_VAR_A", "Value 1; value 2; ... are arguments representing a sample taken from the population.") + NC_("ocVAR_A", "Returns the variance based on a sample. Text is evaluated as zero."), + NC_("ocVAR_A", "Value "), + NC_("ocVAR_A", "Value 1; value 2; ... are arguments representing a sample taken from the population.") }; // -=*# Resource for function VARP #*=- -const TranslateId SC_OPCODE_VAR_P_ARY[] = +const TranslateId ocVAR_P_ARY[] = { - NC_("SC_OPCODE_VAR_P", "Calculates variance based on the entire population."), - NC_("SC_OPCODE_VAR_P", "Number "), - NC_("SC_OPCODE_VAR_P", "Number 1, number 2, ... are numerical arguments which represent a population.") + NC_("ocVAR_P", "Calculates variance based on the entire population."), + NC_("ocVAR_P", "Number "), + NC_("ocVAR_P", "Number 1, number 2, ... are numerical arguments which represent a population.") }; // -=*# Resource for function VAR.P #*=- -const TranslateId SC_OPCODE_VAR_P_MS_ARY[] = +const TranslateId ocVAR_P_MS_ARY[] = { - NC_("SC_OPCODE_VAR_P_MS", "Calculates variance based on the entire population."), - NC_("SC_OPCODE_VAR_P_MS", "Number "), - NC_("SC_OPCODE_VAR_P_MS", "Number 1, number 2, ... are numerical arguments which represent a population.") + NC_("ocVAR_P_MS", "Calculates variance based on the entire population."), + NC_("ocVAR_P_MS", "Number "), + NC_("ocVAR_P_MS", "Number 1, number 2, ... are numerical arguments which represent a population.") }; // -=*# Resource for function VARPA #*=- -const TranslateId SC_OPCODE_VAR_P_A_ARY[] = +const TranslateId ocVAR_P_A_ARY[] = { - NC_("SC_OPCODE_VAR_P_A", "Returns the variance based on the entire population. Text is evaluated as zero."), - NC_("SC_OPCODE_VAR_P_A", "Value "), - NC_("SC_OPCODE_VAR_P_A", "Value 1; value 2;... are arguments representing a population.") + NC_("ocVAR_P_A", "Returns the variance based on the entire population. Text is evaluated as zero."), + NC_("ocVAR_P_A", "Value "), + NC_("ocVAR_P_A", "Value 1; value 2;... are arguments representing a population.") }; // -=*# Resource for function STDEV #*=- -const TranslateId SC_OPCODE_ST_DEV_ARY[] = +const TranslateId ocST_DEV_ARY[] = { - NC_("SC_OPCODE_ST_DEV", "Calculates the standard deviation based on a sample."), - NC_("SC_OPCODE_ST_DEV", "Number "), - NC_("SC_OPCODE_ST_DEV", "Number 1, number 2, ... are numerical arguments which portray a sample of a population.") + NC_("ocST_DEV", "Calculates the standard deviation based on a sample."), + NC_("ocST_DEV", "Number "), + NC_("ocST_DEV", "Number 1, number 2, ... are numerical arguments which portray a sample of a population.") }; // -=*# Resource for function STDEV.S #*=- -const TranslateId SC_OPCODE_ST_DEV_S_ARY[] = +const TranslateId ocST_DEV_S_ARY[] = { - NC_("SC_OPCODE_ST_DEV_S", "Calculates the standard deviation based on a sample."), - NC_("SC_OPCODE_ST_DEV_S", "Number "), - NC_("SC_OPCODE_ST_DEV_S", "Number 1, number 2, ... are numerical arguments which portray a sample of a population.") + NC_("ocST_DEV_S", "Calculates the standard deviation based on a sample."), + NC_("ocST_DEV_S", "Number "), + NC_("ocST_DEV_S", "Number 1, number 2, ... are numerical arguments which portray a sample of a population.") }; // -=*# Resource for function STDEVA #*=- -const TranslateId SC_OPCODE_ST_DEV_A_ARY[] = +const TranslateId ocST_DEV_A_ARY[] = { - NC_("SC_OPCODE_ST_DEV_A", "Returns the standard deviation based on a sample. Text is evaluated as zero."), - NC_("SC_OPCODE_ST_DEV_A", "Value "), - NC_("SC_OPCODE_ST_DEV_A", "Value 1; value 2; ... are arguments representing a sample taken from the population.") + NC_("ocST_DEV_A", "Returns the standard deviation based on a sample. Text is evaluated as zero."), + NC_("ocST_DEV_A", "Value "), + NC_("ocST_DEV_A", "Value 1; value 2; ... are arguments representing a sample taken from the population.") }; // -=*# Resource for function STDEVP #*=- -const TranslateId SC_OPCODE_ST_DEV_P_ARY[] = +const TranslateId ocST_DEV_P_ARY[] = { - NC_("SC_OPCODE_ST_DEV_P", "Calculates the standard deviation based on the entire population."), - NC_("SC_OPCODE_ST_DEV_P", "Number "), - NC_("SC_OPCODE_ST_DEV_P", "Number 1, number 2, ... are numerical arguments which portray a population.") + NC_("ocST_DEV_P", "Calculates the standard deviation based on the entire population."), + NC_("ocST_DEV_P", "Number "), + NC_("ocST_DEV_P", "Number 1, number 2, ... are numerical arguments which portray a population.") }; // -=*# Resource for function STDEV.P #*=- -const TranslateId SC_OPCODE_ST_DEV_P_MS_ARY[] = +const TranslateId ocST_DEV_P_MS_ARY[] = { - NC_("SC_OPCODE_ST_DEV_P_MS", "Calculates the standard deviation based on the entire population."), - NC_("SC_OPCODE_ST_DEV_P_MS", "Number "), - NC_("SC_OPCODE_ST_DEV_P_MS", "Number 1, number 2, ... are numerical arguments which portray a population.") + NC_("ocST_DEV_P_MS", "Calculates the standard deviation based on the entire population."), + NC_("ocST_DEV_P_MS", "Number "), + NC_("ocST_DEV_P_MS", "Number 1, number 2, ... are numerical arguments which portray a population.") }; // -=*# Resource for function STDEVPA #*=- -const TranslateId SC_OPCODE_ST_DEV_P_A_ARY[] = +const TranslateId ocST_DEV_P_A_ARY[] = { - NC_("SC_OPCODE_ST_DEV_P_A", "Returns the standard deviation based on the entire population. Text is evaluated as zero."), - NC_("SC_OPCODE_ST_DEV_P_A", "Value "), - NC_("SC_OPCODE_ST_DEV_P_A", "Value 1; value 2;... are arguments corresponding to a population.") + NC_("ocST_DEV_P_A", "Returns the standard deviation based on the entire population. Text is evaluated as zero."), + NC_("ocST_DEV_P_A", "Value "), + NC_("ocST_DEV_P_A", "Value 1; value 2;... are arguments corresponding to a population.") }; // -=*# Resource for function AVERAGE #*=- -const TranslateId SC_OPCODE_AVERAGE_ARY[] = +const TranslateId ocAVERAGE_ARY[] = { - NC_("SC_OPCODE_AVERAGE", "Returns the average of a sample."), - NC_("SC_OPCODE_AVERAGE", "Number "), - NC_("SC_OPCODE_AVERAGE", "Number 1, number 2;...are numeric arguments representing a population sample.") + NC_("ocAVERAGE", "Returns the average of a sample."), + NC_("ocAVERAGE", "Number "), + NC_("ocAVERAGE", "Number 1, number 2;...are numeric arguments representing a population sample.") }; // -=*# Resource for function AVERAGEA #*=- -const TranslateId SC_OPCODE_AVERAGE_A_ARY[] = +const TranslateId ocAVERAGE_A_ARY[] = { - NC_("SC_OPCODE_AVERAGE_A", "Returns the average value for a sample. Text is evaluated as zero."), - NC_("SC_OPCODE_AVERAGE_A", "Value "), - NC_("SC_OPCODE_AVERAGE_A", "Value 1; value 2; ... are arguments representing a sample taken from the population.") + NC_("ocAVERAGE_A", "Returns the average value for a sample. Text is evaluated as zero."), + NC_("ocAVERAGE_A", "Value "), + NC_("ocAVERAGE_A", "Value 1; value 2; ... are arguments representing a sample taken from the population.") }; // -=*# Resource for function DEVSQ #*=- -const TranslateId SC_OPCODE_DEV_SQ_ARY[] = +const TranslateId ocDEV_SQ_ARY[] = { - NC_("SC_OPCODE_DEV_SQ", "Returns the sum of squares of deviations from the sample mean value"), - NC_("SC_OPCODE_DEV_SQ", "Number "), - NC_("SC_OPCODE_DEV_SQ", "Number 1, number 2, ... are numerical arguments which portray a sample.") + NC_("ocDEV_SQ", "Returns the sum of squares of deviations from the sample mean value"), + NC_("ocDEV_SQ", "Number "), + NC_("ocDEV_SQ", "Number 1, number 2, ... are numerical arguments which portray a sample.") }; // -=*# Resource for function AVEDEV #*=- -const TranslateId SC_OPCODE_AVE_DEV_ARY[] = +const TranslateId ocAVE_DEV_ARY[] = { - NC_("SC_OPCODE_AVE_DEV", "Returns the average of the absolute deviations of a sample from the mean."), - NC_("SC_OPCODE_AVE_DEV", "Number "), - NC_("SC_OPCODE_AVE_DEV", "Number 1, number 2;...are numerical arguments representing a sample.") + NC_("ocAVE_DEV", "Returns the average of the absolute deviations of a sample from the mean."), + NC_("ocAVE_DEV", "Number "), + NC_("ocAVE_DEV", "Number 1, number 2;...are numerical arguments representing a sample.") }; // -=*# Resource for function SKEW #*=- -const TranslateId SC_OPCODE_SKEW_ARY[] = +const TranslateId ocSKEW_ARY[] = { - NC_("SC_OPCODE_SKEW", "Returns the skewness of a distribution."), - NC_("SC_OPCODE_SKEW", "Number "), - NC_("SC_OPCODE_SKEW", "Number 1, number 2, ... are numerical arguments portraying a sample of the distribution.") + NC_("ocSKEW", "Returns the skewness of a distribution."), + NC_("ocSKEW", "Number "), + NC_("ocSKEW", "Number 1, number 2, ... are numerical arguments portraying a sample of the distribution.") }; // -=*# Resource for function SKEWP #*=- -const TranslateId SC_OPCODE_SKEWP_ARY[] = +const TranslateId ocSKEWP_ARY[] = { - NC_("SC_OPCODE_SKEWP", "Returns the skewness of a distribution using the population of a random variable."), - NC_("SC_OPCODE_SKEWP", "Number "), - NC_("SC_OPCODE_SKEWP", "Number 1, number 2, ... are numerical arguments portraying the population.") + NC_("ocSKEWP", "Returns the skewness of a distribution using the population of a random variable."), + NC_("ocSKEWP", "Number "), + NC_("ocSKEWP", "Number 1, number 2, ... are numerical arguments portraying the population.") }; // -=*# Resource for function KURT #*=- -const TranslateId SC_OPCODE_KURT_ARY[] = +const TranslateId ocKURT_ARY[] = { - NC_("SC_OPCODE_KURT", "Returns the kurtosis of a distribution."), - NC_("SC_OPCODE_KURT", "Number "), - NC_("SC_OPCODE_KURT", "Number 1, number 2, ... are numerical arguments, representing a sample of the distribution.") + NC_("ocKURT", "Returns the kurtosis of a distribution."), + NC_("ocKURT", "Number "), + NC_("ocKURT", "Number 1, number 2, ... are numerical arguments, representing a sample of the distribution.") }; // -=*# Resource for function GEOMEAN #*=- -const TranslateId SC_OPCODE_GEO_MEAN_ARY[] = +const TranslateId ocGEO_MEAN_ARY[] = { - NC_("SC_OPCODE_GEO_MEAN", "Returns the geometric mean of a sample."), - NC_("SC_OPCODE_GEO_MEAN", "Number "), - NC_("SC_OPCODE_GEO_MEAN", "Number 1, number 2, ... are numerical arguments which portray a sample.") + NC_("ocGEO_MEAN", "Returns the geometric mean of a sample."), + NC_("ocGEO_MEAN", "Number "), + NC_("ocGEO_MEAN", "Number 1, number 2, ... are numerical arguments which portray a sample.") }; // -=*# Resource for function HARMEAN #*=- -const TranslateId SC_OPCODE_HAR_MEAN_ARY[] = +const TranslateId ocHAR_MEAN_ARY[] = { - NC_("SC_OPCODE_HAR_MEAN", "Returns the harmonic mean of a sample."), - NC_("SC_OPCODE_HAR_MEAN", "Number "), - NC_("SC_OPCODE_HAR_MEAN", "Number 1, number 2, ... are numerical arguments which portray a sample.") + NC_("ocHAR_MEAN", "Returns the harmonic mean of a sample."), + NC_("ocHAR_MEAN", "Number "), + NC_("ocHAR_MEAN", "Number 1, number 2, ... are numerical arguments which portray a sample.") }; // -=*# Resource for function MODE #*=- -const TranslateId SC_OPCODE_MODAL_VALUE_ARY[] = +const TranslateId ocMODAL_VALUE_ARY[] = { - NC_("SC_OPCODE_MODAL_VALUE", "Returns the most common value in a sample."), - NC_("SC_OPCODE_MODAL_VALUE", "Number "), - NC_("SC_OPCODE_MODAL_VALUE", "Number 1, number 2, ... are numerical arguments which portray a sample.") + NC_("ocMODAL_VALUE", "Returns the most common value in a sample."), + NC_("ocMODAL_VALUE", "Number "), + NC_("ocMODAL_VALUE", "Number 1, number 2, ... are numerical arguments which portray a sample.") }; // -=*# Resource for function MODE.SNGL #*=- -const TranslateId SC_OPCODE_MODAL_VALUE_MS_ARY[] = +const TranslateId ocMODAL_VALUE_MS_ARY[] = { - NC_("SC_OPCODE_MODAL_VALUE_MS", "Returns the most common value in a sample."), - NC_("SC_OPCODE_MODAL_VALUE_MS", "Number "), - NC_("SC_OPCODE_MODAL_VALUE_MS", "Number 1, number 2, ... are numerical arguments which portray a sample.") + NC_("ocMODAL_VALUE_MS", "Returns the most common value in a sample."), + NC_("ocMODAL_VALUE_MS", "Number "), + NC_("ocMODAL_VALUE_MS", "Number 1, number 2, ... are numerical arguments which portray a sample.") }; // -=*# Resource for function MODE.MULT #*=- -const TranslateId SC_OPCODE_MODAL_VALUE_MULTI_ARY[] = +const TranslateId ocMODAL_VALUE_MULTI_ARY[] = { - NC_("SC_OPCODE_MODAL_VALUE_MULTI", "Returns the most common value in a sample."), - NC_("SC_OPCODE_MODAL_VALUE_MULTI", "Number "), - NC_("SC_OPCODE_MODAL_VALUE_MULTI", "Number 1, number 2, ... are 1 to 254 numerical arguments which portray a sample.") + NC_("ocMODAL_VALUE_MULTI", "Returns the most common value in a sample."), + NC_("ocMODAL_VALUE_MULTI", "Number "), + NC_("ocMODAL_VALUE_MULTI", "Number 1, number 2, ... are 1 to 254 numerical arguments which portray a sample.") }; // -=*# Resource for function MEDIAN #*=- -const TranslateId SC_OPCODE_MEDIAN_ARY[] = +const TranslateId ocMEDIAN_ARY[] = { - NC_("SC_OPCODE_MEDIAN", "Returns the median of a given sample."), - NC_("SC_OPCODE_MEDIAN", "Number "), - NC_("SC_OPCODE_MEDIAN", "Number 1, number 2, ... are numerical arguments which portray a sample.") + NC_("ocMEDIAN", "Returns the median of a given sample."), + NC_("ocMEDIAN", "Number "), + NC_("ocMEDIAN", "Number 1, number 2, ... are numerical arguments which portray a sample.") }; // -=*# Resource for function PERCENTILE #*=- -const TranslateId SC_OPCODE_PERCENTILE_ARY[] = +const TranslateId ocPERCENTILE_ARY[] = { - NC_("SC_OPCODE_PERCENTILE", "Returns the alpha percentile of a sample."), - NC_("SC_OPCODE_PERCENTILE", "Data"), - NC_("SC_OPCODE_PERCENTILE", "The array of the data in the sample."), - NC_("SC_OPCODE_PERCENTILE", "Alpha"), - NC_("SC_OPCODE_PERCENTILE", "The percentile value between 0 and 1, inclusive.") + NC_("ocPERCENTILE", "Returns the alpha percentile of a sample."), + NC_("ocPERCENTILE", "Data"), + NC_("ocPERCENTILE", "The array of the data in the sample."), + NC_("ocPERCENTILE", "Alpha"), + NC_("ocPERCENTILE", "The percentile value between 0 and 1, inclusive.") }; // -=*# Resource for function PERCENTILE.EXC #*=- -const TranslateId SC_OPCODE_PERCENTILE_EXC_ARY[] = +const TranslateId ocPERCENTILE_EXC_ARY[] = { - NC_("SC_OPCODE_PERCENTILE_EXC", "Returns the alpha percentile of a sample."), - NC_("SC_OPCODE_PERCENTILE_EXC", "Data"), - NC_("SC_OPCODE_PERCENTILE_EXC", "The array of the data in the sample."), - NC_("SC_OPCODE_PERCENTILE_EXC", "Alpha"), - NC_("SC_OPCODE_PERCENTILE_EXC", "The percentile value, range 0...1, exclusive.") + NC_("ocPERCENTILE_EXC", "Returns the alpha percentile of a sample."), + NC_("ocPERCENTILE_EXC", "Data"), + NC_("ocPERCENTILE_EXC", "The array of the data in the sample."), + NC_("ocPERCENTILE_EXC", "Alpha"), + NC_("ocPERCENTILE_EXC", "The percentile value, range 0...1, exclusive.") }; // -=*# Resource for function PERCENTILE.INC #*=- -const TranslateId SC_OPCODE_PERCENTILE_INC_ARY[] = +const TranslateId ocPERCENTILE_INC_ARY[] = { - NC_("SC_OPCODE_PERCENTILE_INC", "Returns the alpha percentile of a sample."), - NC_("SC_OPCODE_PERCENTILE_INC", "Data"), - NC_("SC_OPCODE_PERCENTILE_INC", "The array of the data in the sample."), - NC_("SC_OPCODE_PERCENTILE_INC", "Alpha"), - NC_("SC_OPCODE_PERCENTILE_INC", "The percentile value, range 0...1, inclusive.") + NC_("ocPERCENTILE_INC", "Returns the alpha percentile of a sample."), + NC_("ocPERCENTILE_INC", "Data"), + NC_("ocPERCENTILE_INC", "The array of the data in the sample."), + NC_("ocPERCENTILE_INC", "Alpha"), + NC_("ocPERCENTILE_INC", "The percentile value, range 0...1, inclusive.") }; // -=*# Resource for function QUARTILE #*=- -const TranslateId SC_OPCODE_QUARTILE_ARY[] = +const TranslateId ocQUARTILE_ARY[] = { - NC_("SC_OPCODE_QUARTILE", "Returns the quartile of a sample."), - NC_("SC_OPCODE_QUARTILE", "Data"), - NC_("SC_OPCODE_QUARTILE", "The array of the data in the sample."), - NC_("SC_OPCODE_QUARTILE", "Type"), - NC_("SC_OPCODE_QUARTILE", "The type of the quartile (0 = MIN, 1 = 25%, 2 = 50%, 3 = 75%, 4 = MAX).") + NC_("ocQUARTILE", "Returns the quartile of a sample."), + NC_("ocQUARTILE", "Data"), + NC_("ocQUARTILE", "The array of the data in the sample."), + NC_("ocQUARTILE", "Type"), + NC_("ocQUARTILE", "The type of the quartile (0 = MIN, 1 = 25%, 2 = 50%, 3 = 75%, 4 = MAX).") }; // -=*# Resource for function QUARTILE.EXC #*=- -const TranslateId SC_OPCODE_QUARTILE_EXC_ARY[] = +const TranslateId ocQUARTILE_EXC_ARY[] = { - NC_("SC_OPCODE_QUARTILE_EXC", "Returns the quartile of a sample."), - NC_("SC_OPCODE_QUARTILE_EXC", "Data"), - NC_("SC_OPCODE_QUARTILE_EXC", "The array of the data in the sample."), - NC_("SC_OPCODE_QUARTILE_EXC", "Type"), - NC_("SC_OPCODE_QUARTILE_EXC", "The type of the quartile (1 = 25%, 2 = 50%, 3 = 75%).") + NC_("ocQUARTILE_EXC", "Returns the quartile of a sample."), + NC_("ocQUARTILE_EXC", "Data"), + NC_("ocQUARTILE_EXC", "The array of the data in the sample."), + NC_("ocQUARTILE_EXC", "Type"), + NC_("ocQUARTILE_EXC", "The type of the quartile (1 = 25%, 2 = 50%, 3 = 75%).") }; // -=*# Resource for function QUARTILE.INC #*=- -const TranslateId SC_OPCODE_QUARTILE_INC_ARY[] = +const TranslateId ocQUARTILE_INC_ARY[] = { - NC_("SC_OPCODE_QUARTILE_INC", "Returns the quartile of a sample."), - NC_("SC_OPCODE_QUARTILE_INC", "Data"), - NC_("SC_OPCODE_QUARTILE_INC", "The array of the data in the sample."), - NC_("SC_OPCODE_QUARTILE_INC", "Type"), - NC_("SC_OPCODE_QUARTILE_INC", "The type of the quartile (0 = MIN, 1 = 25%, 2 = 50%, 3 = 75%, 4 = MAX).") + NC_("ocQUARTILE_INC", "Returns the quartile of a sample."), + NC_("ocQUARTILE_INC", "Data"), + NC_("ocQUARTILE_INC", "The array of the data in the sample."), + NC_("ocQUARTILE_INC", "Type"), + NC_("ocQUARTILE_INC", "The type of the quartile (0 = MIN, 1 = 25%, 2 = 50%, 3 = 75%, 4 = MAX).") }; // -=*# Resource for function LARGE #*=- -const TranslateId SC_OPCODE_LARGE_ARY[] = +const TranslateId ocLARGE_ARY[] = { - NC_("SC_OPCODE_LARGE", "Returns the k-th largest value of a sample."), - NC_("SC_OPCODE_LARGE", "Data"), - NC_("SC_OPCODE_LARGE", "The array of the data in the sample."), - NC_("SC_OPCODE_LARGE", "Rank c"), - NC_("SC_OPCODE_LARGE", "The ranking of the value.") + NC_("ocLARGE", "Returns the k-th largest value of a sample."), + NC_("ocLARGE", "Data"), + NC_("ocLARGE", "The array of the data in the sample."), + NC_("ocLARGE", "Rank c"), + NC_("ocLARGE", "The ranking of the value.") }; // -=*# Resource for function SMALL #*=- -const TranslateId SC_OPCODE_SMALL_ARY[] = +const TranslateId ocSMALL_ARY[] = { - NC_("SC_OPCODE_SMALL", "Returns the k-th smallest value of a sample."), - NC_("SC_OPCODE_SMALL", "Data"), - NC_("SC_OPCODE_SMALL", "The array of the data in the sample."), - NC_("SC_OPCODE_SMALL", "Rank c"), - NC_("SC_OPCODE_SMALL", "The ranking of the value.") + NC_("ocSMALL", "Returns the k-th smallest value of a sample."), + NC_("ocSMALL", "Data"), + NC_("ocSMALL", "The array of the data in the sample."), + NC_("ocSMALL", "Rank c"), + NC_("ocSMALL", "The ranking of the value.") }; // -=*# Resource for function PERCENTRANK #*=- -const TranslateId SC_OPCODE_PERCENT_RANK_ARY[] = +const TranslateId ocPERCENT_RANK_ARY[] = { - NC_("SC_OPCODE_PERCENT_RANK", "Returns the percentage rank of a value in a sample."), - NC_("SC_OPCODE_PERCENT_RANK", "Data"), - NC_("SC_OPCODE_PERCENT_RANK", "The array of the data in the sample."), - NC_("SC_OPCODE_PERCENT_RANK", "Value"), - NC_("SC_OPCODE_PERCENT_RANK", "The value for which percentage ranking is to be determined."), - NC_("SC_OPCODE_PERCENT_RANK", "Significance"), - NC_("SC_OPCODE_PERCENT_RANK", "The number of significant digits for the returned percentage: if omitted, a value of 3 is used.") + NC_("ocPERCENT_RANK", "Returns the percentage rank of a value in a sample."), + NC_("ocPERCENT_RANK", "Data"), + NC_("ocPERCENT_RANK", "The array of the data in the sample."), + NC_("ocPERCENT_RANK", "Value"), + NC_("ocPERCENT_RANK", "The value for which percentage ranking is to be determined."), + NC_("ocPERCENT_RANK", "Significance"), + NC_("ocPERCENT_RANK", "The number of significant digits for the returned percentage: if omitted, a value of 3 is used.") }; // -=*# Resource for function PERCENTRANK.EXC #*=- -const TranslateId SC_OPCODE_PERCENT_RANK_EXC_ARY[] = +const TranslateId ocPERCENT_RANK_EXC_ARY[] = { - NC_("SC_OPCODE_PERCENT_RANK_EXC", "Returns the percentage rank (0..1, exclusive) of a value in a sample."), - NC_("SC_OPCODE_PERCENT_RANK_EXC", "Data"), - NC_("SC_OPCODE_PERCENT_RANK_EXC", "The array of the data in the sample."), - NC_("SC_OPCODE_PERCENT_RANK_EXC", "Value"), - NC_("SC_OPCODE_PERCENT_RANK_EXC", "The value for which percentage ranking is to be determined."), - NC_("SC_OPCODE_PERCENT_RANK_EXC", "Significance"), - NC_("SC_OPCODE_PERCENT_RANK_EXC", "The number of significant digits for the returned percentage: if omitted, a value of 3 is used.") + NC_("ocPERCENT_RANK_EXC", "Returns the percentage rank (0..1, exclusive) of a value in a sample."), + NC_("ocPERCENT_RANK_EXC", "Data"), + NC_("ocPERCENT_RANK_EXC", "The array of the data in the sample."), + NC_("ocPERCENT_RANK_EXC", "Value"), + NC_("ocPERCENT_RANK_EXC", "The value for which percentage ranking is to be determined."), + NC_("ocPERCENT_RANK_EXC", "Significance"), + NC_("ocPERCENT_RANK_EXC", "The number of significant digits for the returned percentage: if omitted, a value of 3 is used.") }; // -=*# Resource for function PERCENTRANK.INC #*=- -const TranslateId SC_OPCODE_PERCENT_RANK_INC_ARY[] = +const TranslateId ocPERCENT_RANK_INC_ARY[] = { - NC_("SC_OPCODE_PERCENT_RANK_INC", "Returns the percentage rank (0..1, inclusive) of a value in a sample."), - NC_("SC_OPCODE_PERCENT_RANK_INC", "Data"), - NC_("SC_OPCODE_PERCENT_RANK_INC", "The array of the data in the sample."), - NC_("SC_OPCODE_PERCENT_RANK_INC", "Value"), - NC_("SC_OPCODE_PERCENT_RANK_INC", "The value for which percentage ranking is to be determined."), - NC_("SC_OPCODE_PERCENT_RANK_INC", "Significance"), - NC_("SC_OPCODE_PERCENT_RANK_INC", "The number of significant digits for the returned percentage: if omitted, a value of 3 is used.") + NC_("ocPERCENT_RANK_INC", "Returns the percentage rank (0..1, inclusive) of a value in a sample."), + NC_("ocPERCENT_RANK_INC", "Data"), + NC_("ocPERCENT_RANK_INC", "The array of the data in the sample."), + NC_("ocPERCENT_RANK_INC", "Value"), + NC_("ocPERCENT_RANK_INC", "The value for which percentage ranking is to be determined."), + NC_("ocPERCENT_RANK_INC", "Significance"), + NC_("ocPERCENT_RANK_INC", "The number of significant digits for the returned percentage: if omitted, a value of 3 is used.") }; // -=*# Resource for function RANK #*=- -const TranslateId SC_OPCODE_RANK_ARY[] = +const TranslateId ocRANK_ARY[] = { - NC_("SC_OPCODE_RANK", "Returns the ranking of a value in a sample."), - NC_("SC_OPCODE_RANK", "Value"), - NC_("SC_OPCODE_RANK", "The value for which the rank is to be determined."), - NC_("SC_OPCODE_RANK", "Data"), - NC_("SC_OPCODE_RANK", "The array of the data in the sample."), - NC_("SC_OPCODE_RANK", "Type"), - NC_("SC_OPCODE_RANK", "Sequence order: 0 or omitted means descending, any other value than 0 means ascending.") + NC_("ocRANK", "Returns the ranking of a value in a sample."), + NC_("ocRANK", "Value"), + NC_("ocRANK", "The value for which the rank is to be determined."), + NC_("ocRANK", "Data"), + NC_("ocRANK", "The array of the data in the sample."), + NC_("ocRANK", "Type"), + NC_("ocRANK", "Sequence order: 0 or omitted means descending, any other value than 0 means ascending.") }; // -=*# Resource for function RANK.EQ #*=- -const TranslateId SC_OPCODE_RANK_EQ_ARY[] = +const TranslateId ocRANK_EQ_ARY[] = { - NC_("SC_OPCODE_RANK_EQ", "Returns the ranking of a value in a sample; if more than one value has the same rank, the top rank of that set of values is returned."), - NC_("SC_OPCODE_RANK_EQ", "Value"), - NC_("SC_OPCODE_RANK_EQ", "The value for which the rank is to be determined."), - NC_("SC_OPCODE_RANK_EQ", "Data"), - NC_("SC_OPCODE_RANK_EQ", "The array of the data in the sample."), - NC_("SC_OPCODE_RANK_EQ", "Type"), - NC_("SC_OPCODE_RANK_EQ", "Sequence order: 0 or omitted means descending, any other value than 0 means ascending.") + NC_("ocRANK_EQ", "Returns the ranking of a value in a sample; if more than one value has the same rank, the top rank of that set of values is returned."), + NC_("ocRANK_EQ", "Value"), + NC_("ocRANK_EQ", "The value for which the rank is to be determined."), + NC_("ocRANK_EQ", "Data"), + NC_("ocRANK_EQ", "The array of the data in the sample."), + NC_("ocRANK_EQ", "Type"), + NC_("ocRANK_EQ", "Sequence order: 0 or omitted means descending, any other value than 0 means ascending.") }; // -=*# Resource for function RANK.AVG #*=- -const TranslateId SC_OPCODE_RANK_AVG_ARY[] = +const TranslateId ocRANK_AVG_ARY[] = { - NC_("SC_OPCODE_RANK_AVG", "Returns the ranking of a value in a sample; if more than one value has the same rank, the average rank is returned."), - NC_("SC_OPCODE_RANK_AVG", "Value"), - NC_("SC_OPCODE_RANK_AVG", "The value for which the rank is to be determined."), - NC_("SC_OPCODE_RANK_AVG", "Data"), - NC_("SC_OPCODE_RANK_AVG", "The array of the data in the sample."), - NC_("SC_OPCODE_RANK_AVG", "Type"), - NC_("SC_OPCODE_RANK_AVG", "Sequence order: 0 or omitted means descending, any other value than 0 means ascending.") + NC_("ocRANK_AVG", "Returns the ranking of a value in a sample; if more than one value has the same rank, the average rank is returned."), + NC_("ocRANK_AVG", "Value"), + NC_("ocRANK_AVG", "The value for which the rank is to be determined."), + NC_("ocRANK_AVG", "Data"), + NC_("ocRANK_AVG", "The array of the data in the sample."), + NC_("ocRANK_AVG", "Type"), + NC_("ocRANK_AVG", "Sequence order: 0 or omitted means descending, any other value than 0 means ascending.") }; // -=*# Resource for function TRIMMEAN #*=- -const TranslateId SC_OPCODE_TRIM_MEAN_ARY[] = +const TranslateId ocTRIM_MEAN_ARY[] = { - NC_("SC_OPCODE_TRIM_MEAN", "Returns the mean of a sample without including the marginal values."), - NC_("SC_OPCODE_TRIM_MEAN", "Data"), - NC_("SC_OPCODE_TRIM_MEAN", "The array of the data in the sample."), - NC_("SC_OPCODE_TRIM_MEAN", "Alpha"), - NC_("SC_OPCODE_TRIM_MEAN", "The percentage of marginal data that is not to be taken into account.") + NC_("ocTRIM_MEAN", "Returns the mean of a sample without including the marginal values."), + NC_("ocTRIM_MEAN", "Data"), + NC_("ocTRIM_MEAN", "The array of the data in the sample."), + NC_("ocTRIM_MEAN", "Alpha"), + NC_("ocTRIM_MEAN", "The percentage of marginal data that is not to be taken into account.") }; // -=*# Resource for function PROB #*=- -const TranslateId SC_OPCODE_PROB_ARY[] = +const TranslateId ocPROB_ARY[] = { - NC_("SC_OPCODE_PROB", "Returns the discrete probability of an interval."), - NC_("SC_OPCODE_PROB", "Data"), - NC_("SC_OPCODE_PROB", "The sample data array."), - NC_("SC_OPCODE_PROB", "Probability"), - NC_("SC_OPCODE_PROB", "The array of the associated probabilities."), - NC_("SC_OPCODE_PROB", "Start"), - NC_("SC_OPCODE_PROB", "The start of the value interval whose probabilities is to be totalled."), - NC_("SC_OPCODE_PROB", "End"), - NC_("SC_OPCODE_PROB", "The end of the value interval where the probabilities are to be totalled.") + NC_("ocPROB", "Returns the discrete probability of an interval."), + NC_("ocPROB", "Data"), + NC_("ocPROB", "The sample data array."), + NC_("ocPROB", "Probability"), + NC_("ocPROB", "The array of the associated probabilities."), + NC_("ocPROB", "Start"), + NC_("ocPROB", "The start of the value interval whose probabilities is to be totalled."), + NC_("ocPROB", "End"), + NC_("ocPROB", "The end of the value interval where the probabilities are to be totalled.") }; // -=*# Resource for function B #*=- -const TranslateId SC_OPCODE_B_ARY[] = +const TranslateId ocB_ARY[] = { - NC_("SC_OPCODE_B", "Returns the probability of a trial result using binomial distribution."), - NC_("SC_OPCODE_B", "Trials"), - NC_("SC_OPCODE_B", "The number of trials."), - NC_("SC_OPCODE_B", "SP"), - NC_("SC_OPCODE_B", "The individual probability of a trial result."), - NC_("SC_OPCODE_B", "T 1"), - NC_("SC_OPCODE_B", "Lower limit for the number of trials."), - NC_("SC_OPCODE_B", "T 2"), - NC_("SC_OPCODE_B", "Upper limit for the number of trials.") + NC_("ocB", "Returns the probability of a trial result using binomial distribution."), + NC_("ocB", "Trials"), + NC_("ocB", "The number of trials."), + NC_("ocB", "SP"), + NC_("ocB", "The individual probability of a trial result."), + NC_("ocB", "T 1"), + NC_("ocB", "Lower limit for the number of trials."), + NC_("ocB", "T 2"), + NC_("ocB", "Upper limit for the number of trials.") }; // -=*# Resource for function PHI #*=- -const TranslateId SC_OPCODE_PHI_ARY[] = +const TranslateId ocPHI_ARY[] = { - NC_("SC_OPCODE_PHI", "Values of the distribution function for a standard normal distribution."), - NC_("SC_OPCODE_PHI", "Number"), - NC_("SC_OPCODE_PHI", "The value for which the standard normal distribution is to be calculated.") + NC_("ocPHI", "Values of the distribution function for a standard normal distribution."), + NC_("ocPHI", "Number"), + NC_("ocPHI", "The value for which the standard normal distribution is to be calculated.") }; // -=*# Resource for function GAUSS #*=- -const TranslateId SC_OPCODE_GAUSS_ARY[] = +const TranslateId ocGAUSS_ARY[] = { - NC_("SC_OPCODE_GAUSS", "Returns the integral values of the standard normal cumulative distribution."), - NC_("SC_OPCODE_GAUSS", "Number"), - NC_("SC_OPCODE_GAUSS", "The value for which the integral value of the standard normal distribution is to be calculated.") + NC_("ocGAUSS", "Returns the integral values of the standard normal cumulative distribution."), + NC_("ocGAUSS", "Number"), + NC_("ocGAUSS", "The value for which the integral value of the standard normal distribution is to be calculated.") }; // -=*# Resource for function FISHER #*=- -const TranslateId SC_OPCODE_FISHER_ARY[] = +const TranslateId ocFISHER_ARY[] = { - NC_("SC_OPCODE_FISHER", "Returns the Fisher transformation."), - NC_("SC_OPCODE_FISHER", "Number"), - NC_("SC_OPCODE_FISHER", "The value to be transformed (-1 < VALUE < 1).") + NC_("ocFISHER", "Returns the Fisher transformation."), + NC_("ocFISHER", "Number"), + NC_("ocFISHER", "The value to be transformed (-1 < VALUE < 1).") }; // -=*# Resource for function FISHERINV #*=- -const TranslateId SC_OPCODE_FISHER_INV_ARY[] = +const TranslateId ocFISHER_INV_ARY[] = { - NC_("SC_OPCODE_FISHER_INV", "Returns the inverse of the Fisher transformation."), - NC_("SC_OPCODE_FISHER_INV", "Number"), - NC_("SC_OPCODE_FISHER_INV", "The value that is to be transformed back.") + NC_("ocFISHER_INV", "Returns the inverse of the Fisher transformation."), + NC_("ocFISHER_INV", "Number"), + NC_("ocFISHER_INV", "The value that is to be transformed back.") }; // -=*# Resource for function BINOMDIST #*=- -const TranslateId SC_OPCODE_BINOM_DIST_ARY[] = +const TranslateId ocBINOM_DIST_ARY[] = { - NC_("SC_OPCODE_BINOM_DIST", "Values of the binomial distribution."), - NC_("SC_OPCODE_BINOM_DIST", "X"), - NC_("SC_OPCODE_BINOM_DIST", "The number of successes in a series of trials."), - NC_("SC_OPCODE_BINOM_DIST", "Trials"), - NC_("SC_OPCODE_BINOM_DIST", "The total number of trials."), - NC_("SC_OPCODE_BINOM_DIST", "SP"), - NC_("SC_OPCODE_BINOM_DIST", "The success probability of a trial."), - NC_("SC_OPCODE_BINOM_DIST", "C"), - NC_("SC_OPCODE_BINOM_DIST", "Cumulated. C=0 calculates the individual probability, C=1 the cumulated probability.") + NC_("ocBINOM_DIST", "Values of the binomial distribution."), + NC_("ocBINOM_DIST", "X"), + NC_("ocBINOM_DIST", "The number of successes in a series of trials."), + NC_("ocBINOM_DIST", "Trials"), + NC_("ocBINOM_DIST", "The total number of trials."), + NC_("ocBINOM_DIST", "SP"), + NC_("ocBINOM_DIST", "The success probability of a trial."), + NC_("ocBINOM_DIST", "C"), + NC_("ocBINOM_DIST", "Cumulated. C=0 calculates the individual probability, C=1 the cumulated probability.") }; // -=*# Resource for function BINOM.DIST #*=- -const TranslateId SC_OPCODE_BINOM_DIST_MS_ARY[] = +const TranslateId ocBINOM_DIST_MS_ARY[] = { - NC_("SC_OPCODE_BINOM_DIST_MS", "Values of the binomial distribution."), - NC_("SC_OPCODE_BINOM_DIST_MS", "X"), - NC_("SC_OPCODE_BINOM_DIST_MS", "The number of successes in a series of trials."), - NC_("SC_OPCODE_BINOM_DIST_MS", "Trials"), - NC_("SC_OPCODE_BINOM_DIST_MS", "The total number of trials."), - NC_("SC_OPCODE_BINOM_DIST_MS", "SP"), - NC_("SC_OPCODE_BINOM_DIST_MS", "The success probability of a trial."), - NC_("SC_OPCODE_BINOM_DIST_MS", "C"), - NC_("SC_OPCODE_BINOM_DIST_MS", "Cumulated. C=0 calculates the individual probability, C=1 the cumulated probability.") + NC_("ocBINOM_DIST_MS", "Values of the binomial distribution."), + NC_("ocBINOM_DIST_MS", "X"), + NC_("ocBINOM_DIST_MS", "The number of successes in a series of trials."), + NC_("ocBINOM_DIST_MS", "Trials"), + NC_("ocBINOM_DIST_MS", "The total number of trials."), + NC_("ocBINOM_DIST_MS", "SP"), + NC_("ocBINOM_DIST_MS", "The success probability of a trial."), + NC_("ocBINOM_DIST_MS", "C"), + NC_("ocBINOM_DIST_MS", "Cumulated. C=0 calculates the individual probability, C=1 the cumulated probability.") }; // -=*# Resource for function NEGBINOMDIST #*=- -const TranslateId SC_OPCODE_NEG_BINOM_VERT_ARY[] = +const TranslateId ocNEG_BINOM_VERT_ARY[] = { - NC_("SC_OPCODE_NEG_BINOM_VERT", "Values of the negative binomial distribution."), - NC_("SC_OPCODE_NEG_BINOM_VERT", "X"), - NC_("SC_OPCODE_NEG_BINOM_VERT", "The number of failures in the trial range."), - NC_("SC_OPCODE_NEG_BINOM_VERT", "R"), - NC_("SC_OPCODE_NEG_BINOM_VERT", "The number of successes in the trial sequence."), - NC_("SC_OPCODE_NEG_BINOM_VERT", "SP"), - NC_("SC_OPCODE_NEG_BINOM_VERT", "The success probability of a trial.") + NC_("ocNEG_BINOM_VERT", "Values of the negative binomial distribution."), + NC_("ocNEG_BINOM_VERT", "X"), + NC_("ocNEG_BINOM_VERT", "The number of failures in the trial range."), + NC_("ocNEG_BINOM_VERT", "R"), + NC_("ocNEG_BINOM_VERT", "The number of successes in the trial sequence."), + NC_("ocNEG_BINOM_VERT", "SP"), + NC_("ocNEG_BINOM_VERT", "The success probability of a trial.") }; // -=*# Resource for function NEGBINOM.DIST #*=- -const TranslateId SC_OPCODE_NEG_BINOM_DIST_MS_ARY[] = +const TranslateId ocNEG_BINOM_DIST_MS_ARY[] = { - NC_("SC_OPCODE_NEG_BINOM_DIST_MS", "Values of the negative binomial distribution."), - NC_("SC_OPCODE_NEG_BINOM_DIST_MS", "X"), - NC_("SC_OPCODE_NEG_BINOM_DIST_MS", "The number of failures in the trial range."), - NC_("SC_OPCODE_NEG_BINOM_DIST_MS", "R"), - NC_("SC_OPCODE_NEG_BINOM_DIST_MS", "The number of successes in the trial sequence."), - NC_("SC_OPCODE_NEG_BINOM_DIST_MS", "SP"), - NC_("SC_OPCODE_NEG_BINOM_DIST_MS", "The success probability of a trial."), - NC_("SC_OPCODE_NEG_BINOM_DIST_MS", "Cumulative"), - NC_("SC_OPCODE_NEG_BINOM_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") + NC_("ocNEG_BINOM_DIST_MS", "Values of the negative binomial distribution."), + NC_("ocNEG_BINOM_DIST_MS", "X"), + NC_("ocNEG_BINOM_DIST_MS", "The number of failures in the trial range."), + NC_("ocNEG_BINOM_DIST_MS", "R"), + NC_("ocNEG_BINOM_DIST_MS", "The number of successes in the trial sequence."), + NC_("ocNEG_BINOM_DIST_MS", "SP"), + NC_("ocNEG_BINOM_DIST_MS", "The success probability of a trial."), + NC_("ocNEG_BINOM_DIST_MS", "Cumulative"), + NC_("ocNEG_BINOM_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") }; // -=*# Resource for function CRITBINOM #*=- -const TranslateId SC_OPCODE_CRIT_BINOM_ARY[] = +const TranslateId ocCRIT_BINOM_ARY[] = { - NC_("SC_OPCODE_CRIT_BINOM", "Returns the smallest value for which the cumulative binomial distribution is greater than or equal to a criterion value."), - NC_("SC_OPCODE_CRIT_BINOM", "Trials"), - NC_("SC_OPCODE_CRIT_BINOM", "The total number of trials."), - NC_("SC_OPCODE_CRIT_BINOM", "SP"), - NC_("SC_OPCODE_CRIT_BINOM", "The success probability of a trial."), - NC_("SC_OPCODE_CRIT_BINOM", "Alpha"), - NC_("SC_OPCODE_CRIT_BINOM", "The border probability that is attained or exceeded.") + NC_("ocCRIT_BINOM", "Returns the smallest value for which the cumulative binomial distribution is greater than or equal to a criterion value."), + NC_("ocCRIT_BINOM", "Trials"), + NC_("ocCRIT_BINOM", "The total number of trials."), + NC_("ocCRIT_BINOM", "SP"), + NC_("ocCRIT_BINOM", "The success probability of a trial."), + NC_("ocCRIT_BINOM", "Alpha"), + NC_("ocCRIT_BINOM", "The border probability that is attained or exceeded.") }; // -=*# Resource for function BINOM.INV #*=- -const TranslateId SC_OPCODE_BINOM_INV_ARY[] = +const TranslateId ocBINOM_INV_ARY[] = { - NC_("SC_OPCODE_BINOM_INV", "Returns the smallest value for which the cumulative binomial distribution is greater than or equal to a criterion value."), - NC_("SC_OPCODE_BINOM_INV", "Trials"), - NC_("SC_OPCODE_BINOM_INV", "The total number of trials."), - NC_("SC_OPCODE_BINOM_INV", "SP"), - NC_("SC_OPCODE_BINOM_INV", "The success probability of a trial."), - NC_("SC_OPCODE_BINOM_INV", "Alpha"), - NC_("SC_OPCODE_BINOM_INV", "The border probability that is attained or exceeded.") + NC_("ocBINOM_INV", "Returns the smallest value for which the cumulative binomial distribution is greater than or equal to a criterion value."), + NC_("ocBINOM_INV", "Trials"), + NC_("ocBINOM_INV", "The total number of trials."), + NC_("ocBINOM_INV", "SP"), + NC_("ocBINOM_INV", "The success probability of a trial."), + NC_("ocBINOM_INV", "Alpha"), + NC_("ocBINOM_INV", "The border probability that is attained or exceeded.") }; // -=*# Resource for function POISSON #*=- -const TranslateId SC_OPCODE_POISSON_DIST_ARY[] = +const TranslateId ocPOISSON_DIST_ARY[] = { - NC_("SC_OPCODE_POISSON_DIST", "Returns the Poisson distribution."), - NC_("SC_OPCODE_POISSON_DIST", "Number"), - NC_("SC_OPCODE_POISSON_DIST", "The value for which the Poisson distribution is to be calculated."), - NC_("SC_OPCODE_POISSON_DIST", "Mean"), - NC_("SC_OPCODE_POISSON_DIST", "Mean. The mean value of the Poisson distribution."), - NC_("SC_OPCODE_POISSON_DIST", "Cumulative"), - NC_("SC_OPCODE_POISSON_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") + NC_("ocPOISSON_DIST", "Returns the Poisson distribution."), + NC_("ocPOISSON_DIST", "Number"), + NC_("ocPOISSON_DIST", "The value for which the Poisson distribution is to be calculated."), + NC_("ocPOISSON_DIST", "Mean"), + NC_("ocPOISSON_DIST", "Mean. The mean value of the Poisson distribution."), + NC_("ocPOISSON_DIST", "Cumulative"), + NC_("ocPOISSON_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") }; // -=*# Resource for function POISSON.DIST #*=- -const TranslateId SC_OPCODE_POISSON_DIST_MS_ARY[] = +const TranslateId ocPOISSON_DIST_MS_ARY[] = { - NC_("SC_OPCODE_POISSON_DIST_MS", "Returns the Poisson distribution."), - NC_("SC_OPCODE_POISSON_DIST_MS", "Number"), - NC_("SC_OPCODE_POISSON_DIST_MS", "The value for which the Poisson distribution is to be calculated."), - NC_("SC_OPCODE_POISSON_DIST_MS", "Mean"), - NC_("SC_OPCODE_POISSON_DIST_MS", "Mean. The mean value of the Poisson distribution."), - NC_("SC_OPCODE_POISSON_DIST_MS", "Cumulative"), - NC_("SC_OPCODE_POISSON_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") + NC_("ocPOISSON_DIST_MS", "Returns the Poisson distribution."), + NC_("ocPOISSON_DIST_MS", "Number"), + NC_("ocPOISSON_DIST_MS", "The value for which the Poisson distribution is to be calculated."), + NC_("ocPOISSON_DIST_MS", "Mean"), + NC_("ocPOISSON_DIST_MS", "Mean. The mean value of the Poisson distribution."), + NC_("ocPOISSON_DIST_MS", "Cumulative"), + NC_("ocPOISSON_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") }; // -=*# Resource for function NORMDIST #*=- -const TranslateId SC_OPCODE_NORM_DIST_ARY[] = +const TranslateId ocNORM_DIST_ARY[] = { - NC_("SC_OPCODE_NORM_DIST", "Values of the normal distribution."), - NC_("SC_OPCODE_NORM_DIST", "Number"), - NC_("SC_OPCODE_NORM_DIST", "The value for which the normal distribution is to be calculated."), - NC_("SC_OPCODE_NORM_DIST", "Mean"), - NC_("SC_OPCODE_NORM_DIST", "The mean value. The mean value of the normal distribution."), - NC_("SC_OPCODE_NORM_DIST", "STDEV"), - NC_("SC_OPCODE_NORM_DIST", "Standard deviation. The standard deviation of the normal distribution."), - NC_("SC_OPCODE_NORM_DIST", "C"), - NC_("SC_OPCODE_NORM_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") + NC_("ocNORM_DIST", "Values of the normal distribution."), + NC_("ocNORM_DIST", "Number"), + NC_("ocNORM_DIST", "The value for which the normal distribution is to be calculated."), + NC_("ocNORM_DIST", "Mean"), + NC_("ocNORM_DIST", "The mean value. The mean value of the normal distribution."), + NC_("ocNORM_DIST", "STDEV"), + NC_("ocNORM_DIST", "Standard deviation. The standard deviation of the normal distribution."), + NC_("ocNORM_DIST", "C"), + NC_("ocNORM_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") }; // -=*# Resource for function NORM.DIST #*=- -const TranslateId SC_OPCODE_NORM_DIST_MS_ARY[] = +const TranslateId ocNORM_DIST_MS_ARY[] = { - NC_("SC_OPCODE_NORM_DIST_MS", "Values of the normal distribution."), - NC_("SC_OPCODE_NORM_DIST_MS", "Number"), - NC_("SC_OPCODE_NORM_DIST_MS", "The value for which the normal distribution is to be calculated."), - NC_("SC_OPCODE_NORM_DIST_MS", "Mean"), - NC_("SC_OPCODE_NORM_DIST_MS", "The mean value. The mean value of the normal distribution."), - NC_("SC_OPCODE_NORM_DIST_MS", "STDEV"), - NC_("SC_OPCODE_NORM_DIST_MS", "Standard deviation. The standard deviation of the normal distribution."), - NC_("SC_OPCODE_NORM_DIST_MS", "C"), - NC_("SC_OPCODE_NORM_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") + NC_("ocNORM_DIST_MS", "Values of the normal distribution."), + NC_("ocNORM_DIST_MS", "Number"), + NC_("ocNORM_DIST_MS", "The value for which the normal distribution is to be calculated."), + NC_("ocNORM_DIST_MS", "Mean"), + NC_("ocNORM_DIST_MS", "The mean value. The mean value of the normal distribution."), + NC_("ocNORM_DIST_MS", "STDEV"), + NC_("ocNORM_DIST_MS", "Standard deviation. The standard deviation of the normal distribution."), + NC_("ocNORM_DIST_MS", "C"), + NC_("ocNORM_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") }; // -=*# Resource for function NORMINV #*=- -const TranslateId SC_OPCODE_NORM_INV_ARY[] = +const TranslateId ocNORM_INV_ARY[] = { - NC_("SC_OPCODE_NORM_INV", "Values of the inverse normal distribution."), - NC_("SC_OPCODE_NORM_INV", "Number"), - NC_("SC_OPCODE_NORM_INV", "The probability value for which the inverse normal distribution is to be calculated."), - NC_("SC_OPCODE_NORM_INV", "Mean"), - NC_("SC_OPCODE_NORM_INV", "The mean value. The mean value of the normal distribution."), - NC_("SC_OPCODE_NORM_INV", "STDEV"), - NC_("SC_OPCODE_NORM_INV", "Standard deviation. The standard deviation of the normal distribution.") + NC_("ocNORM_INV", "Values of the inverse normal distribution."), + NC_("ocNORM_INV", "Number"), + NC_("ocNORM_INV", "The probability value for which the inverse normal distribution is to be calculated."), + NC_("ocNORM_INV", "Mean"), + NC_("ocNORM_INV", "The mean value. The mean value of the normal distribution."), + NC_("ocNORM_INV", "STDEV"), + NC_("ocNORM_INV", "Standard deviation. The standard deviation of the normal distribution.") }; // -=*# Resource for function NORM.INV #*=- -const TranslateId SC_OPCODE_NORM_INV_MS_ARY[] = +const TranslateId ocNORM_INV_MS_ARY[] = { - NC_("SC_OPCODE_NORM_INV_MS", "Values of the inverse normal distribution."), - NC_("SC_OPCODE_NORM_INV_MS", "Number"), - NC_("SC_OPCODE_NORM_INV_MS", "The probability value for which the inverse normal distribution is to be calculated."), - NC_("SC_OPCODE_NORM_INV_MS", "Mean"), - NC_("SC_OPCODE_NORM_INV_MS", "The mean value. The mean value of the normal distribution."), - NC_("SC_OPCODE_NORM_INV_MS", "STDEV"), - NC_("SC_OPCODE_NORM_INV_MS", "Standard deviation. The standard deviation of the normal distribution.") + NC_("ocNORM_INV_MS", "Values of the inverse normal distribution."), + NC_("ocNORM_INV_MS", "Number"), + NC_("ocNORM_INV_MS", "The probability value for which the inverse normal distribution is to be calculated."), + NC_("ocNORM_INV_MS", "Mean"), + NC_("ocNORM_INV_MS", "The mean value. The mean value of the normal distribution."), + NC_("ocNORM_INV_MS", "STDEV"), + NC_("ocNORM_INV_MS", "Standard deviation. The standard deviation of the normal distribution.") }; // -=*# Resource for function NORMSDIST #*=- -const TranslateId SC_OPCODE_STD_NORM_DIST_ARY[] = +const TranslateId ocSTD_NORM_DIST_ARY[] = { - NC_("SC_OPCODE_STD_NORM_DIST", "The values of the standard normal cumulative distribution."), - NC_("SC_OPCODE_STD_NORM_DIST", "Number"), - NC_("SC_OPCODE_STD_NORM_DIST", "The value for which the standard normal distribution is to be calculated.") + NC_("ocSTD_NORM_DIST", "The values of the standard normal cumulative distribution."), + NC_("ocSTD_NORM_DIST", "Number"), + NC_("ocSTD_NORM_DIST", "The value for which the standard normal distribution is to be calculated.") }; // -=*# Resource for function NORM.S.DIST #*=- -const TranslateId SC_OPCODE_STD_NORM_DIST_MS_ARY[] = +const TranslateId ocSTD_NORM_DIST_MS_ARY[] = { - NC_("SC_OPCODE_STD_NORM_DIST_MS", "The values of the standard normal distribution."), - NC_("SC_OPCODE_STD_NORM_DIST_MS", "Number"), - NC_("SC_OPCODE_STD_NORM_DIST_MS", "The value for which the standard normal distribution is to be calculated."), - NC_("SC_OPCODE_STD_NORM_DIST_MS", "Cumulative"), - NC_("SC_OPCODE_STD_NORM_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") + NC_("ocSTD_NORM_DIST_MS", "The values of the standard normal distribution."), + NC_("ocSTD_NORM_DIST_MS", "Number"), + NC_("ocSTD_NORM_DIST_MS", "The value for which the standard normal distribution is to be calculated."), + NC_("ocSTD_NORM_DIST_MS", "Cumulative"), + NC_("ocSTD_NORM_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") }; // -=*# Resource for function NORMSINV #*=- -const TranslateId SC_OPCODE_S_NORM_INV_ARY[] = +const TranslateId ocS_NORM_INV_ARY[] = { - NC_("SC_OPCODE_S_NORM_INV", "Values of the inverse standard normal distribution."), - NC_("SC_OPCODE_S_NORM_INV", "Number"), - NC_("SC_OPCODE_S_NORM_INV", "The probability value for which the inverse standard normal distribution is to be calculated.") + NC_("ocS_NORM_INV", "Values of the inverse standard normal distribution."), + NC_("ocS_NORM_INV", "Number"), + NC_("ocS_NORM_INV", "The probability value for which the inverse standard normal distribution is to be calculated.") }; // -=*# Resource for function NORM.S.INV #*=- -const TranslateId SC_OPCODE_S_NORM_INV_MS_ARY[] = +const TranslateId ocS_NORM_INV_MS_ARY[] = { - NC_("SC_OPCODE_S_NORM_INV_MS", "Values of the inverse standard normal distribution."), - NC_("SC_OPCODE_S_NORM_INV_MS", "Number"), - NC_("SC_OPCODE_S_NORM_INV_MS", "The probability value for which the inverse standard normal distribution is to be calculated.") + NC_("ocS_NORM_INV_MS", "Values of the inverse standard normal distribution."), + NC_("ocS_NORM_INV_MS", "Number"), + NC_("ocS_NORM_INV_MS", "The probability value for which the inverse standard normal distribution is to be calculated.") }; // -=*# Resource for function LOGNORMDIST #*=- -const TranslateId SC_OPCODE_LOG_NORM_DIST_ARY[] = +const TranslateId ocLOG_NORM_DIST_ARY[] = { - NC_("SC_OPCODE_LOG_NORM_DIST", "Values of the log normal distribution."), - NC_("SC_OPCODE_LOG_NORM_DIST", "Number"), - NC_("SC_OPCODE_LOG_NORM_DIST", "The value for which the log normal distribution is to be calculated."), - NC_("SC_OPCODE_LOG_NORM_DIST", "Mean"), - NC_("SC_OPCODE_LOG_NORM_DIST", "The mean value of the log normal distribution. It is set to 0 if omitted."), - NC_("SC_OPCODE_LOG_NORM_DIST", "STDEV"), - NC_("SC_OPCODE_LOG_NORM_DIST", "The standard deviation of the log normal distribution. It is set to 1 if omitted."), - NC_("SC_OPCODE_LOG_NORM_DIST", "Cumulative"), - NC_("SC_OPCODE_LOG_NORM_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") + NC_("ocLOG_NORM_DIST", "Values of the log normal distribution."), + NC_("ocLOG_NORM_DIST", "Number"), + NC_("ocLOG_NORM_DIST", "The value for which the log normal distribution is to be calculated."), + NC_("ocLOG_NORM_DIST", "Mean"), + NC_("ocLOG_NORM_DIST", "The mean value of the log normal distribution. It is set to 0 if omitted."), + NC_("ocLOG_NORM_DIST", "STDEV"), + NC_("ocLOG_NORM_DIST", "The standard deviation of the log normal distribution. It is set to 1 if omitted."), + NC_("ocLOG_NORM_DIST", "Cumulative"), + NC_("ocLOG_NORM_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") }; // -=*# Resource for function LOGNORM.DIST #*=- -const TranslateId SC_OPCODE_LOG_NORM_DIST_MS_ARY[] = +const TranslateId ocLOG_NORM_DIST_MS_ARY[] = { - NC_("SC_OPCODE_LOG_NORM_DIST_MS", "Values of the log normal distribution."), - NC_("SC_OPCODE_LOG_NORM_DIST_MS", "Number"), - NC_("SC_OPCODE_LOG_NORM_DIST_MS", "The value for which the log normal distribution is to be calculated."), - NC_("SC_OPCODE_LOG_NORM_DIST_MS", "Mean"), - NC_("SC_OPCODE_LOG_NORM_DIST_MS", "The mean value of the log normal distribution."), - NC_("SC_OPCODE_LOG_NORM_DIST_MS", "STDEV"), - NC_("SC_OPCODE_LOG_NORM_DIST_MS", "The standard deviation of the log normal distribution."), - NC_("SC_OPCODE_LOG_NORM_DIST_MS", "Cumulative"), - NC_("SC_OPCODE_LOG_NORM_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") + NC_("ocLOG_NORM_DIST_MS", "Values of the log normal distribution."), + NC_("ocLOG_NORM_DIST_MS", "Number"), + NC_("ocLOG_NORM_DIST_MS", "The value for which the log normal distribution is to be calculated."), + NC_("ocLOG_NORM_DIST_MS", "Mean"), + NC_("ocLOG_NORM_DIST_MS", "The mean value of the log normal distribution."), + NC_("ocLOG_NORM_DIST_MS", "STDEV"), + NC_("ocLOG_NORM_DIST_MS", "The standard deviation of the log normal distribution."), + NC_("ocLOG_NORM_DIST_MS", "Cumulative"), + NC_("ocLOG_NORM_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") }; // -=*# Resource for function LOGINV #*=- -const TranslateId SC_OPCODE_LOG_INV_ARY[] = +const TranslateId ocLOG_INV_ARY[] = { - NC_("SC_OPCODE_LOG_INV", "Values of the inverse of the lognormal distribution."), - NC_("SC_OPCODE_LOG_INV", "Number"), - NC_("SC_OPCODE_LOG_INV", "The probability value for which the inverse log normal distribution is to be calculated."), - NC_("SC_OPCODE_LOG_INV", "Mean"), - NC_("SC_OPCODE_LOG_INV", "Mean value. The mean value of the log normal distribution."), - NC_("SC_OPCODE_LOG_INV", "STDEV"), - NC_("SC_OPCODE_LOG_INV", "Standard deviation. The standard deviation of the log normal distribution.") + NC_("ocLOG_INV", "Values of the inverse of the lognormal distribution."), + NC_("ocLOG_INV", "Number"), + NC_("ocLOG_INV", "The probability value for which the inverse log normal distribution is to be calculated."), + NC_("ocLOG_INV", "Mean"), + NC_("ocLOG_INV", "Mean value. The mean value of the log normal distribution."), + NC_("ocLOG_INV", "STDEV"), + NC_("ocLOG_INV", "Standard deviation. The standard deviation of the log normal distribution.") }; // -=*# Resource for function LOGNORM.INV #*=- -const TranslateId SC_OPCODE_LOG_INV_MS_ARY[] = +const TranslateId ocLOG_INV_MS_ARY[] = { - NC_("SC_OPCODE_LOG_INV_MS", "Values of the inverse of the lognormal distribution."), - NC_("SC_OPCODE_LOG_INV_MS", "Number"), - NC_("SC_OPCODE_LOG_INV_MS", "The probability value for which the inverse log normal distribution is to be calculated."), - NC_("SC_OPCODE_LOG_INV_MS", "Mean"), - NC_("SC_OPCODE_LOG_INV_MS", "Mean value. The mean value of the log normal distribution."), - NC_("SC_OPCODE_LOG_INV_MS", "STDEV"), - NC_("SC_OPCODE_LOG_INV_MS", "Standard deviation. The standard deviation of the log normal distribution.") + NC_("ocLOG_INV_MS", "Values of the inverse of the lognormal distribution."), + NC_("ocLOG_INV_MS", "Number"), + NC_("ocLOG_INV_MS", "The probability value for which the inverse log normal distribution is to be calculated."), + NC_("ocLOG_INV_MS", "Mean"), + NC_("ocLOG_INV_MS", "Mean value. The mean value of the log normal distribution."), + NC_("ocLOG_INV_MS", "STDEV"), + NC_("ocLOG_INV_MS", "Standard deviation. The standard deviation of the log normal distribution.") }; // -=*# Resource for function EXPONDIST #*=- -const TranslateId SC_OPCODE_EXP_DIST_ARY[] = +const TranslateId ocEXP_DIST_ARY[] = { - NC_("SC_OPCODE_EXP_DIST", "Values of the exponential distribution."), - NC_("SC_OPCODE_EXP_DIST", "Number"), - NC_("SC_OPCODE_EXP_DIST", "The value to which the exponential distribution is to be calculated."), - NC_("SC_OPCODE_EXP_DIST", "Lambda"), - NC_("SC_OPCODE_EXP_DIST", "The parameters of the exponential distribution."), - NC_("SC_OPCODE_EXP_DIST", "C"), - NC_("SC_OPCODE_EXP_DIST", "Cumulated. C=0 calculates the density function, C=1 the distribution.") + NC_("ocEXP_DIST", "Values of the exponential distribution."), + NC_("ocEXP_DIST", "Number"), + NC_("ocEXP_DIST", "The value to which the exponential distribution is to be calculated."), + NC_("ocEXP_DIST", "Lambda"), + NC_("ocEXP_DIST", "The parameters of the exponential distribution."), + NC_("ocEXP_DIST", "C"), + NC_("ocEXP_DIST", "Cumulated. C=0 calculates the density function, C=1 the distribution.") }; // -=*# Resource for function EXPON.DIST #*=- -const TranslateId SC_OPCODE_EXP_DIST_MS_ARY[] = +const TranslateId ocEXP_DIST_MS_ARY[] = { - NC_("SC_OPCODE_EXP_DIST_MS", "Values of the exponential distribution."), - NC_("SC_OPCODE_EXP_DIST_MS", "Number"), - NC_("SC_OPCODE_EXP_DIST_MS", "The value to which the exponential distribution is to be calculated."), - NC_("SC_OPCODE_EXP_DIST_MS", "Lambda"), - NC_("SC_OPCODE_EXP_DIST_MS", "The parameters of the exponential distribution."), - NC_("SC_OPCODE_EXP_DIST_MS", "C"), - NC_("SC_OPCODE_EXP_DIST_MS", "Cumulated. C=0 calculates the density function, C=1 the distribution.") + NC_("ocEXP_DIST_MS", "Values of the exponential distribution."), + NC_("ocEXP_DIST_MS", "Number"), + NC_("ocEXP_DIST_MS", "The value to which the exponential distribution is to be calculated."), + NC_("ocEXP_DIST_MS", "Lambda"), + NC_("ocEXP_DIST_MS", "The parameters of the exponential distribution."), + NC_("ocEXP_DIST_MS", "C"), + NC_("ocEXP_DIST_MS", "Cumulated. C=0 calculates the density function, C=1 the distribution.") }; // -=*# Resource for function GAMMADIST #*=- -const TranslateId SC_OPCODE_GAMMA_DIST_ARY[] = +const TranslateId ocGAMMA_DIST_ARY[] = { - NC_("SC_OPCODE_GAMMA_DIST", "Returns the value of the probability density function or the cumulative distribution function for the Gamma distribution."), - NC_("SC_OPCODE_GAMMA_DIST", "Number"), - NC_("SC_OPCODE_GAMMA_DIST", "The value for which the gamma distribution is to be calculated."), - NC_("SC_OPCODE_GAMMA_DIST", "Alpha"), - NC_("SC_OPCODE_GAMMA_DIST", "The Alpha parameter of the Gamma distribution."), - NC_("SC_OPCODE_GAMMA_DIST", "Beta"), - NC_("SC_OPCODE_GAMMA_DIST", "The Beta parameter of the Gamma distribution."), - NC_("SC_OPCODE_GAMMA_DIST", "Cumulative"), - NC_("SC_OPCODE_GAMMA_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") + NC_("ocGAMMA_DIST", "Returns the value of the probability density function or the cumulative distribution function for the Gamma distribution."), + NC_("ocGAMMA_DIST", "Number"), + NC_("ocGAMMA_DIST", "The value for which the gamma distribution is to be calculated."), + NC_("ocGAMMA_DIST", "Alpha"), + NC_("ocGAMMA_DIST", "The Alpha parameter of the Gamma distribution."), + NC_("ocGAMMA_DIST", "Beta"), + NC_("ocGAMMA_DIST", "The Beta parameter of the Gamma distribution."), + NC_("ocGAMMA_DIST", "Cumulative"), + NC_("ocGAMMA_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") }; // -=*# Resource for function GAMMA.DIST #*=- -const TranslateId SC_OPCODE_GAMMA_DIST_MS_ARY[] = +const TranslateId ocGAMMA_DIST_MS_ARY[] = { - NC_("SC_OPCODE_GAMMA_DIST_MS", "Returns the value of the probability density function or the cumulative distribution function for the Gamma distribution."), - NC_("SC_OPCODE_GAMMA_DIST_MS", "Number"), - NC_("SC_OPCODE_GAMMA_DIST_MS", "The value for which the gamma distribution is to be calculated."), - NC_("SC_OPCODE_GAMMA_DIST_MS", "Alpha"), - NC_("SC_OPCODE_GAMMA_DIST_MS", "The Alpha parameter of the Gamma distribution."), - NC_("SC_OPCODE_GAMMA_DIST_MS", "Beta"), - NC_("SC_OPCODE_GAMMA_DIST_MS", "The Beta parameter of the Gamma distribution."), - NC_("SC_OPCODE_GAMMA_DIST_MS", "Cumulative"), - NC_("SC_OPCODE_GAMMA_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") + NC_("ocGAMMA_DIST_MS", "Returns the value of the probability density function or the cumulative distribution function for the Gamma distribution."), + NC_("ocGAMMA_DIST_MS", "Number"), + NC_("ocGAMMA_DIST_MS", "The value for which the gamma distribution is to be calculated."), + NC_("ocGAMMA_DIST_MS", "Alpha"), + NC_("ocGAMMA_DIST_MS", "The Alpha parameter of the Gamma distribution."), + NC_("ocGAMMA_DIST_MS", "Beta"), + NC_("ocGAMMA_DIST_MS", "The Beta parameter of the Gamma distribution."), + NC_("ocGAMMA_DIST_MS", "Cumulative"), + NC_("ocGAMMA_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") }; // -=*# Resource for function GAMMAINV #*=- -const TranslateId SC_OPCODE_GAMMA_INV_ARY[] = +const TranslateId ocGAMMA_INV_ARY[] = { - NC_("SC_OPCODE_GAMMA_INV", "Values of the inverse gamma distribution."), - NC_("SC_OPCODE_GAMMA_INV", "Number"), - NC_("SC_OPCODE_GAMMA_INV", "The probability value for which the inverse gamma distribution is to be calculated."), - NC_("SC_OPCODE_GAMMA_INV", "Alpha"), - NC_("SC_OPCODE_GAMMA_INV", "The Alpha (shape) parameter of the Gamma distribution."), - NC_("SC_OPCODE_GAMMA_INV", "Beta"), - NC_("SC_OPCODE_GAMMA_INV", "The Beta (scale) parameter of the Gamma distribution.") + NC_("ocGAMMA_INV", "Values of the inverse gamma distribution."), + NC_("ocGAMMA_INV", "Number"), + NC_("ocGAMMA_INV", "The probability value for which the inverse gamma distribution is to be calculated."), + NC_("ocGAMMA_INV", "Alpha"), + NC_("ocGAMMA_INV", "The Alpha (shape) parameter of the Gamma distribution."), + NC_("ocGAMMA_INV", "Beta"), + NC_("ocGAMMA_INV", "The Beta (scale) parameter of the Gamma distribution.") }; // -=*# Resource for function GAMMA.INV #*=- -const TranslateId SC_OPCODE_GAMMA_INV_MS_ARY[] = +const TranslateId ocGAMMA_INV_MS_ARY[] = { - NC_("SC_OPCODE_GAMMA_INV_MS", "Values of the inverse gamma distribution."), - NC_("SC_OPCODE_GAMMA_INV_MS", "Number"), - NC_("SC_OPCODE_GAMMA_INV_MS", "The probability value for which the inverse gamma distribution is to be calculated."), - NC_("SC_OPCODE_GAMMA_INV_MS", "Alpha"), - NC_("SC_OPCODE_GAMMA_INV_MS", "The Alpha (shape) parameter of the Gamma distribution."), - NC_("SC_OPCODE_GAMMA_INV_MS", "Beta"), - NC_("SC_OPCODE_GAMMA_INV_MS", "The Beta (scale) parameter of the Gamma distribution.") + NC_("ocGAMMA_INV_MS", "Values of the inverse gamma distribution."), + NC_("ocGAMMA_INV_MS", "Number"), + NC_("ocGAMMA_INV_MS", "The probability value for which the inverse gamma distribution is to be calculated."), + NC_("ocGAMMA_INV_MS", "Alpha"), + NC_("ocGAMMA_INV_MS", "The Alpha (shape) parameter of the Gamma distribution."), + NC_("ocGAMMA_INV_MS", "Beta"), + NC_("ocGAMMA_INV_MS", "The Beta (scale) parameter of the Gamma distribution.") }; // -=*# Resource for function GAMMALN #*=- -const TranslateId SC_OPCODE_GAMMA_LN_ARY[] = +const TranslateId ocGAMMA_LN_ARY[] = { - NC_("SC_OPCODE_GAMMA_LN", "Returns the natural logarithm of the gamma function."), - NC_("SC_OPCODE_GAMMA_LN", "Number"), - NC_("SC_OPCODE_GAMMA_LN", "The value for which the natural logarithm of the gamma function is to be calculated.") + NC_("ocGAMMA_LN", "Returns the natural logarithm of the gamma function."), + NC_("ocGAMMA_LN", "Number"), + NC_("ocGAMMA_LN", "The value for which the natural logarithm of the gamma function is to be calculated.") }; // -=*# Resource for function GAMMALN.PRECISE #*=- -const TranslateId SC_OPCODE_GAMMA_LN_MS_ARY[] = +const TranslateId ocGAMMA_LN_MS_ARY[] = { - NC_("SC_OPCODE_GAMMA_LN_MS", "Returns the natural logarithm of the gamma function."), - NC_("SC_OPCODE_GAMMA_LN_MS", "Number"), - NC_("SC_OPCODE_GAMMA_LN_MS", "The value for which the natural logarithm of the gamma function is to be calculated.") + NC_("ocGAMMA_LN_MS", "Returns the natural logarithm of the gamma function."), + NC_("ocGAMMA_LN_MS", "Number"), + NC_("ocGAMMA_LN_MS", "The value for which the natural logarithm of the gamma function is to be calculated.") }; // -=*# Resource for function GAMMA #*=- -const TranslateId SC_OPCODE_GAMMA_ARY[] = +const TranslateId ocGAMMA_ARY[] = { - NC_("SC_OPCODE_GAMMA", "Returns the value of the Gamma function."), - NC_("SC_OPCODE_GAMMA", "Number"), - NC_("SC_OPCODE_GAMMA", "The value for which the Gamma function is to be calculated.") + NC_("ocGAMMA", "Returns the value of the Gamma function."), + NC_("ocGAMMA", "Number"), + NC_("ocGAMMA", "The value for which the Gamma function is to be calculated.") }; // -=*# Resource for function BETADIST #*=- -const TranslateId SC_OPCODE_BETA_DIST_ARY[] = +const TranslateId ocBETA_DIST_ARY[] = { - NC_("SC_OPCODE_BETA_DIST", "Values of the beta distribution."), - NC_("SC_OPCODE_BETA_DIST", "Number"), - NC_("SC_OPCODE_BETA_DIST", "The value for which the beta distribution is to be calculated."), - NC_("SC_OPCODE_BETA_DIST", "Alpha"), - NC_("SC_OPCODE_BETA_DIST", "The Alpha parameter of the Beta distribution."), - NC_("SC_OPCODE_BETA_DIST", "Beta"), - NC_("SC_OPCODE_BETA_DIST", "The Beta parameter of the Beta distribution."), - NC_("SC_OPCODE_BETA_DIST", "Start"), - NC_("SC_OPCODE_BETA_DIST", "The starting value for the value interval of the distribution."), - NC_("SC_OPCODE_BETA_DIST", "End"), - NC_("SC_OPCODE_BETA_DIST", "The final value for the value interval of the distribution."), - NC_("SC_OPCODE_BETA_DIST", "Cumulative"), - NC_("SC_OPCODE_BETA_DIST", "0 or FALSE for probability density function, any other value or TRUE or omitted for cumulative distribution function.") + NC_("ocBETA_DIST", "Values of the beta distribution."), + NC_("ocBETA_DIST", "Number"), + NC_("ocBETA_DIST", "The value for which the beta distribution is to be calculated."), + NC_("ocBETA_DIST", "Alpha"), + NC_("ocBETA_DIST", "The Alpha parameter of the Beta distribution."), + NC_("ocBETA_DIST", "Beta"), + NC_("ocBETA_DIST", "The Beta parameter of the Beta distribution."), + NC_("ocBETA_DIST", "Start"), + NC_("ocBETA_DIST", "The starting value for the value interval of the distribution."), + NC_("ocBETA_DIST", "End"), + NC_("ocBETA_DIST", "The final value for the value interval of the distribution."), + NC_("ocBETA_DIST", "Cumulative"), + NC_("ocBETA_DIST", "0 or FALSE for probability density function, any other value or TRUE or omitted for cumulative distribution function.") }; // -=*# Resource for function BETAINV #*=- -const TranslateId SC_OPCODE_BETA_INV_ARY[] = +const TranslateId ocBETA_INV_ARY[] = { - NC_("SC_OPCODE_BETA_INV", "Values of the inverse beta distribution."), - NC_("SC_OPCODE_BETA_INV", "Number"), - NC_("SC_OPCODE_BETA_INV", "The probability value for which the inverse beta distribution is to be calculated."), - NC_("SC_OPCODE_BETA_INV", "Alpha"), - NC_("SC_OPCODE_BETA_INV", "The Alpha parameter of the Beta distribution."), - NC_("SC_OPCODE_BETA_INV", "Beta"), - NC_("SC_OPCODE_BETA_INV", "The Beta parameter of the Beta distribution."), - NC_("SC_OPCODE_BETA_INV", "Start"), - NC_("SC_OPCODE_BETA_INV", "The starting value for the value interval of the distribution."), - NC_("SC_OPCODE_BETA_INV", "End"), - NC_("SC_OPCODE_BETA_INV", "The final value for the value interval of the distribution.") + NC_("ocBETA_INV", "Values of the inverse beta distribution."), + NC_("ocBETA_INV", "Number"), + NC_("ocBETA_INV", "The probability value for which the inverse beta distribution is to be calculated."), + NC_("ocBETA_INV", "Alpha"), + NC_("ocBETA_INV", "The Alpha parameter of the Beta distribution."), + NC_("ocBETA_INV", "Beta"), + NC_("ocBETA_INV", "The Beta parameter of the Beta distribution."), + NC_("ocBETA_INV", "Start"), + NC_("ocBETA_INV", "The starting value for the value interval of the distribution."), + NC_("ocBETA_INV", "End"), + NC_("ocBETA_INV", "The final value for the value interval of the distribution.") }; // -=*# Resource for function BETA.DIST #*=- -const TranslateId SC_OPCODE_BETA_DIST_MS_ARY[] = +const TranslateId ocBETA_DIST_MS_ARY[] = { - NC_("SC_OPCODE_BETA_DIST_MS", "Values of the beta distribution."), - NC_("SC_OPCODE_BETA_DIST_MS", "Number"), - NC_("SC_OPCODE_BETA_DIST_MS", "The value for which the beta distribution is to be calculated."), - NC_("SC_OPCODE_BETA_DIST_MS", "Alpha"), - NC_("SC_OPCODE_BETA_DIST_MS", "The Alpha parameter of the Beta distribution."), - NC_("SC_OPCODE_BETA_DIST_MS", "Beta"), - NC_("SC_OPCODE_BETA_DIST_MS", "The Beta parameter of the Beta distribution."), - NC_("SC_OPCODE_BETA_DIST_MS", "Cumulative"), - NC_("SC_OPCODE_BETA_DIST_MS", "0 or FALSE for probability density function, any other value or TRUE or omitted for cumulative distribution function."), - NC_("SC_OPCODE_BETA_DIST_MS", "Start"), - NC_("SC_OPCODE_BETA_DIST_MS", "The starting value for the value interval of the distribution."), - NC_("SC_OPCODE_BETA_DIST_MS", "End"), - NC_("SC_OPCODE_BETA_DIST_MS", "The final value for the value interval of the distribution.") + NC_("ocBETA_DIST_MS", "Values of the beta distribution."), + NC_("ocBETA_DIST_MS", "Number"), + NC_("ocBETA_DIST_MS", "The value for which the beta distribution is to be calculated."), + NC_("ocBETA_DIST_MS", "Alpha"), + NC_("ocBETA_DIST_MS", "The Alpha parameter of the Beta distribution."), + NC_("ocBETA_DIST_MS", "Beta"), + NC_("ocBETA_DIST_MS", "The Beta parameter of the Beta distribution."), + NC_("ocBETA_DIST_MS", "Cumulative"), + NC_("ocBETA_DIST_MS", "0 or FALSE for probability density function, any other value or TRUE or omitted for cumulative distribution function."), + NC_("ocBETA_DIST_MS", "Start"), + NC_("ocBETA_DIST_MS", "The starting value for the value interval of the distribution."), + NC_("ocBETA_DIST_MS", "End"), + NC_("ocBETA_DIST_MS", "The final value for the value interval of the distribution.") }; // -=*# Resource for function BETA.INV #*=- -const TranslateId SC_OPCODE_BETA_INV_MS_ARY[] = +const TranslateId ocBETA_INV_MS_ARY[] = { - NC_("SC_OPCODE_BETA_INV_MS", "Values of the inverse beta distribution."), - NC_("SC_OPCODE_BETA_INV_MS", "Number"), - NC_("SC_OPCODE_BETA_INV_MS", "The probability value for which the inverse beta distribution is to be calculated."), - NC_("SC_OPCODE_BETA_INV_MS", "Alpha"), - NC_("SC_OPCODE_BETA_INV_MS", "The Alpha parameter of the Beta distribution."), - NC_("SC_OPCODE_BETA_INV_MS", "Beta"), - NC_("SC_OPCODE_BETA_INV_MS", "The Beta parameter of the Beta distribution."), - NC_("SC_OPCODE_BETA_INV_MS", "Start"), - NC_("SC_OPCODE_BETA_INV_MS", "The starting value for the value interval of the distribution."), - NC_("SC_OPCODE_BETA_INV_MS", "End"), - NC_("SC_OPCODE_BETA_INV_MS", "The final value for the value interval of the distribution.") + NC_("ocBETA_INV_MS", "Values of the inverse beta distribution."), + NC_("ocBETA_INV_MS", "Number"), + NC_("ocBETA_INV_MS", "The probability value for which the inverse beta distribution is to be calculated."), + NC_("ocBETA_INV_MS", "Alpha"), + NC_("ocBETA_INV_MS", "The Alpha parameter of the Beta distribution."), + NC_("ocBETA_INV_MS", "Beta"), + NC_("ocBETA_INV_MS", "The Beta parameter of the Beta distribution."), + NC_("ocBETA_INV_MS", "Start"), + NC_("ocBETA_INV_MS", "The starting value for the value interval of the distribution."), + NC_("ocBETA_INV_MS", "End"), + NC_("ocBETA_INV_MS", "The final value for the value interval of the distribution.") }; // -=*# Resource for function WEIBULL #*=- -const TranslateId SC_OPCODE_WEIBULL_ARY[] = +const TranslateId ocWEIBULL_ARY[] = { - NC_("SC_OPCODE_WEIBULL", "Returns the values of the Weibull distribution."), - NC_("SC_OPCODE_WEIBULL", "Number"), - NC_("SC_OPCODE_WEIBULL", "The value for which the Weibull distribution is to be calculated."), - NC_("SC_OPCODE_WEIBULL", "Alpha"), - NC_("SC_OPCODE_WEIBULL", "The Alpha parameter of the Weibull distribution."), - NC_("SC_OPCODE_WEIBULL", "Beta"), - NC_("SC_OPCODE_WEIBULL", "The Beta parameter of the Weibull distribution."), - NC_("SC_OPCODE_WEIBULL", "C"), - NC_("SC_OPCODE_WEIBULL", "Cumulated. C=0 calculates the density function, C=1 the distribution.") + NC_("ocWEIBULL", "Returns the values of the Weibull distribution."), + NC_("ocWEIBULL", "Number"), + NC_("ocWEIBULL", "The value for which the Weibull distribution is to be calculated."), + NC_("ocWEIBULL", "Alpha"), + NC_("ocWEIBULL", "The Alpha parameter of the Weibull distribution."), + NC_("ocWEIBULL", "Beta"), + NC_("ocWEIBULL", "The Beta parameter of the Weibull distribution."), + NC_("ocWEIBULL", "C"), + NC_("ocWEIBULL", "Cumulated. C=0 calculates the density function, C=1 the distribution.") }; // -=*# Resource for function WEIBULL.DIST #*=- -const TranslateId SC_OPCODE_WEIBULL_MS_ARY[] = +const TranslateId ocWEIBULL_MS_ARY[] = { - NC_("SC_OPCODE_WEIBULL_MS", "Returns the values of the Weibull distribution."), - NC_("SC_OPCODE_WEIBULL_MS", "Number"), - NC_("SC_OPCODE_WEIBULL_MS", "The value for which the Weibull distribution is to be calculated."), - NC_("SC_OPCODE_WEIBULL_MS", "Alpha"), - NC_("SC_OPCODE_WEIBULL_MS", "The Alpha parameter of the Weibull distribution."), - NC_("SC_OPCODE_WEIBULL_MS", "Beta"), - NC_("SC_OPCODE_WEIBULL_MS", "The Beta parameter of the Weibull distribution."), - NC_("SC_OPCODE_WEIBULL_MS", "C"), - NC_("SC_OPCODE_WEIBULL_MS", "Cumulated. C=0 calculates the density function, C=1 the distribution.") + NC_("ocWEIBULL_MS", "Returns the values of the Weibull distribution."), + NC_("ocWEIBULL_MS", "Number"), + NC_("ocWEIBULL_MS", "The value for which the Weibull distribution is to be calculated."), + NC_("ocWEIBULL_MS", "Alpha"), + NC_("ocWEIBULL_MS", "The Alpha parameter of the Weibull distribution."), + NC_("ocWEIBULL_MS", "Beta"), + NC_("ocWEIBULL_MS", "The Beta parameter of the Weibull distribution."), + NC_("ocWEIBULL_MS", "C"), + NC_("ocWEIBULL_MS", "Cumulated. C=0 calculates the density function, C=1 the distribution.") }; // -=*# Resource for function HYPGEOMDIST #*=- -const TranslateId SC_OPCODE_HYP_GEOM_DIST_ARY[] = +const TranslateId ocHYP_GEOM_DIST_ARY[] = { - NC_("SC_OPCODE_HYP_GEOM_DIST", "Values of the hypergeometric distribution."), - NC_("SC_OPCODE_HYP_GEOM_DIST", "X"), - NC_("SC_OPCODE_HYP_GEOM_DIST", "The number of successes in the sample."), - NC_("SC_OPCODE_HYP_GEOM_DIST", "N sample"), - NC_("SC_OPCODE_HYP_GEOM_DIST", "The size of the sample."), - NC_("SC_OPCODE_HYP_GEOM_DIST", "Successes"), - NC_("SC_OPCODE_HYP_GEOM_DIST", "The number of successes in the population."), - NC_("SC_OPCODE_HYP_GEOM_DIST", "N population"), - NC_("SC_OPCODE_HYP_GEOM_DIST", "The population size."), - NC_("SC_OPCODE_HYP_GEOM_DIST", "Cumulative"), - NC_("SC_OPCODE_HYP_GEOM_DIST", "Cumulated. TRUE calculates the cumulative distribution function, FALSE the probability mass function.") + NC_("ocHYP_GEOM_DIST", "Values of the hypergeometric distribution."), + NC_("ocHYP_GEOM_DIST", "X"), + NC_("ocHYP_GEOM_DIST", "The number of successes in the sample."), + NC_("ocHYP_GEOM_DIST", "N sample"), + NC_("ocHYP_GEOM_DIST", "The size of the sample."), + NC_("ocHYP_GEOM_DIST", "Successes"), + NC_("ocHYP_GEOM_DIST", "The number of successes in the population."), + NC_("ocHYP_GEOM_DIST", "N population"), + NC_("ocHYP_GEOM_DIST", "The population size."), + NC_("ocHYP_GEOM_DIST", "Cumulative"), + NC_("ocHYP_GEOM_DIST", "Cumulated. TRUE calculates the cumulative distribution function, FALSE the probability mass function.") }; // -=*# Resource for function HYPGEOM.DIST #*=- -const TranslateId SC_OPCODE_HYP_GEOM_DIST_MS_ARY[] = +const TranslateId ocHYP_GEOM_DIST_MS_ARY[] = { - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "Values of the hypergeometric distribution."), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "X"), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "The number of successes in the sample."), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "N sample"), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "The size of the sample."), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "Successes"), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "The number of successes in the population."), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "N population"), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "The population size."), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "Cumulative"), - NC_("SC_OPCODE_HYP_GEOM_DIST_MS", "Cumulated. TRUE calculates the cumulative distribution function, FALSE the probability mass function.") + NC_("ocHYP_GEOM_DIST_MS", "Values of the hypergeometric distribution."), + NC_("ocHYP_GEOM_DIST_MS", "X"), + NC_("ocHYP_GEOM_DIST_MS", "The number of successes in the sample."), + NC_("ocHYP_GEOM_DIST_MS", "N sample"), + NC_("ocHYP_GEOM_DIST_MS", "The size of the sample."), + NC_("ocHYP_GEOM_DIST_MS", "Successes"), + NC_("ocHYP_GEOM_DIST_MS", "The number of successes in the population."), + NC_("ocHYP_GEOM_DIST_MS", "N population"), + NC_("ocHYP_GEOM_DIST_MS", "The population size."), + NC_("ocHYP_GEOM_DIST_MS", "Cumulative"), + NC_("ocHYP_GEOM_DIST_MS", "Cumulated. TRUE calculates the cumulative distribution function, FALSE the probability mass function.") }; // -=*# Resource for function TDIST #*=- -const TranslateId SC_OPCODE_T_DIST_ARY[] = +const TranslateId ocT_DIST_ARY[] = { - NC_("SC_OPCODE_T_DIST", "Returns the t-distribution."), - NC_("SC_OPCODE_T_DIST", "Number"), - NC_("SC_OPCODE_T_DIST", "The value for which the T distribution is to be calculated."), - NC_("SC_OPCODE_T_DIST", "Degrees freedom"), - NC_("SC_OPCODE_T_DIST", "The degrees of freedom of the T distribution."), - NC_("SC_OPCODE_T_DIST", "Mode"), - NC_("SC_OPCODE_T_DIST", "Mode = 1 calculates the one-tailed test, 2 = two-tailed distribution.") + NC_("ocT_DIST", "Returns the t-distribution."), + NC_("ocT_DIST", "Number"), + NC_("ocT_DIST", "The value for which the T distribution is to be calculated."), + NC_("ocT_DIST", "Degrees of freedom"), + NC_("ocT_DIST", "The degrees of freedom of the T distribution."), + NC_("ocT_DIST", "Mode"), + NC_("ocT_DIST", "Mode = 1 calculates the one-tailed test, 2 = two-tailed distribution.") }; // -=*# Resource for function T.DIST.2T #*=- -const TranslateId SC_OPCODE_T_DIST_2T_ARY[] = +const TranslateId ocT_DIST_2T_ARY[] = { - NC_("SC_OPCODE_T_DIST_2T", "Returns the two-tailed t-distribution."), - NC_("SC_OPCODE_T_DIST_2T", "Number"), - NC_("SC_OPCODE_T_DIST_2T", "The value for which the T distribution is to be calculated."), - NC_("SC_OPCODE_T_DIST_2T", "Degrees freedom"), - NC_("SC_OPCODE_T_DIST_2T", "The degrees of freedom of the T distribution.") + NC_("ocT_DIST_2T", "Returns the two-tailed t-distribution."), + NC_("ocT_DIST_2T", "Number"), + NC_("ocT_DIST_2T", "The value for which the T distribution is to be calculated."), + NC_("ocT_DIST_2T", "Degrees of freedom"), + NC_("ocT_DIST_2T", "The degrees of freedom of the T distribution.") }; // -=*# Resource for function T.DIST #*=- -const TranslateId SC_OPCODE_T_DIST_MS_ARY[] = +const TranslateId ocT_DIST_MS_ARY[] = { - NC_("SC_OPCODE_T_DIST_MS", "Returns the t-distribution."), - NC_("SC_OPCODE_T_DIST_MS", "Number"), - NC_("SC_OPCODE_T_DIST_MS", "The value for which the T distribution is to be calculated."), - NC_("SC_OPCODE_T_DIST_MS", "Degrees freedom"), - NC_("SC_OPCODE_T_DIST_MS", "The degrees of freedom of the T distribution."), - NC_("SC_OPCODE_T_DIST_MS", "Cumulative"), - NC_("SC_OPCODE_T_DIST_MS", "True calculates the cumulative distribution function, false the probability density function.") + NC_("ocT_DIST_MS", "Returns the t-distribution."), + NC_("ocT_DIST_MS", "Number"), + NC_("ocT_DIST_MS", "The value for which the T distribution is to be calculated."), + NC_("ocT_DIST_MS", "Degrees of freedom"), + NC_("ocT_DIST_MS", "The degrees of freedom of the T distribution."), + NC_("ocT_DIST_MS", "Cumulative"), + NC_("ocT_DIST_MS", "True calculates the cumulative distribution function, false the probability density function.") }; // -=*# Resource for function T.DIST.RT #*=- -const TranslateId SC_OPCODE_T_DIST_RT_ARY[] = +const TranslateId ocT_DIST_RT_ARY[] = { - NC_("SC_OPCODE_T_DIST_RT", "Returns the right-tailed t-distribution."), - NC_("SC_OPCODE_T_DIST_RT", "Number"), - NC_("SC_OPCODE_T_DIST_RT", "The value for which the T distribution is to be calculated."), - NC_("SC_OPCODE_T_DIST_RT", "Degrees freedom"), - NC_("SC_OPCODE_T_DIST_RT", "The degrees of freedom of the T distribution.") + NC_("ocT_DIST_RT", "Returns the right-tailed t-distribution."), + NC_("ocT_DIST_RT", "Number"), + NC_("ocT_DIST_RT", "The value for which the T distribution is to be calculated."), + NC_("ocT_DIST_RT", "Degrees of freedom"), + NC_("ocT_DIST_RT", "The degrees of freedom of the T distribution.") }; // -=*# Resource for function TINV #*=- -const TranslateId SC_OPCODE_T_INV_ARY[] = +const TranslateId ocT_INV_ARY[] = { - NC_("SC_OPCODE_T_INV", "Values of the inverse t-distribution."), - NC_("SC_OPCODE_T_INV", "Number"), - NC_("SC_OPCODE_T_INV", "The probability value for which the inverse T distribution is to be calculated."), - NC_("SC_OPCODE_T_INV", "Degrees freedom"), - NC_("SC_OPCODE_T_INV", "The degrees of freedom of the T distribution.") + NC_("ocT_INV", "Values of the inverse t-distribution."), + NC_("ocT_INV", "Number"), + NC_("ocT_INV", "The probability value for which the inverse T distribution is to be calculated."), + NC_("ocT_INV", "Degrees of freedom"), + NC_("ocT_INV", "The degrees of freedom of the T distribution.") }; // -=*# Resource for function T.INV #*=- -const TranslateId SC_OPCODE_T_INV_MS_ARY[] = +const TranslateId ocT_INV_MS_ARY[] = { - NC_("SC_OPCODE_T_INV_MS", "Values of the left-tailed inverse t-distribution."), - NC_("SC_OPCODE_T_INV_MS", "Number"), - NC_("SC_OPCODE_T_INV_MS", "The probability value for which the inverse T distribution is to be calculated."), - NC_("SC_OPCODE_T_INV_MS", "Degrees freedom"), - NC_("SC_OPCODE_T_INV_MS", "The degrees of freedom of the T distribution.") + NC_("ocT_INV_MS", "Values of the left-tailed inverse t-distribution."), + NC_("ocT_INV_MS", "Number"), + NC_("ocT_INV_MS", "The probability value for which the inverse T distribution is to be calculated."), + NC_("ocT_INV_MS", "Degrees of freedom"), + NC_("ocT_INV_MS", "The degrees of freedom of the T distribution.") }; // -=*# Resource for function T.INV.2T #*=- -const TranslateId SC_OPCODE_T_INV_2T_ARY[] = +const TranslateId ocT_INV_2T_ARY[] = { - NC_("SC_OPCODE_T_INV_2T", "Values of the two-tailed inverse t-distribution."), - NC_("SC_OPCODE_T_INV_2T", "Number"), - NC_("SC_OPCODE_T_INV_2T", "The probability value for which the inverse T distribution is to be calculated."), - NC_("SC_OPCODE_T_INV_2T", "Degrees freedom"), - NC_("SC_OPCODE_T_INV_2T", "The degrees of freedom of the T distribution.") + NC_("ocT_INV_2T", "Values of the two-tailed inverse t-distribution."), + NC_("ocT_INV_2T", "Number"), + NC_("ocT_INV_2T", "The probability value for which the inverse T distribution is to be calculated."), + NC_("ocT_INV_2T", "Degrees of freedom"), + NC_("ocT_INV_2T", "The degrees of freedom of the T distribution.") }; // -=*# Resource for function FDIST #*=- -const TranslateId SC_OPCODE_F_DIST_ARY[] = +const TranslateId ocF_DIST_ARY[] = { - NC_("SC_OPCODE_F_DIST", "Values of the F probability distribution."), - NC_("SC_OPCODE_F_DIST", "Number"), - NC_("SC_OPCODE_F_DIST", "The value for which the F distribution is to be calculated."), - NC_("SC_OPCODE_F_DIST", "Degrees freedom 1"), - NC_("SC_OPCODE_F_DIST", "The degrees of freedom in the numerator of the F distribution."), - NC_("SC_OPCODE_F_DIST", "Degrees freedom 2"), - NC_("SC_OPCODE_F_DIST", "The degrees of freedom in the denominator of the F distribution.") + NC_("ocF_DIST", "Values of the F probability distribution."), + NC_("ocF_DIST", "Number"), + NC_("ocF_DIST", "The value for which the F distribution is to be calculated."), + NC_("ocF_DIST", "Degrees of freedom 1"), + NC_("ocF_DIST", "The degrees of freedom in the numerator of the F distribution."), + NC_("ocF_DIST", "Degrees of freedom 2"), + NC_("ocF_DIST", "The degrees of freedom in the denominator of the F distribution.") }; // -=*# Resource for function F.DIST #*=- -const TranslateId SC_OPCODE_F_DIST_LT_ARY[] = +const TranslateId ocF_DIST_LT_ARY[] = { - NC_("SC_OPCODE_F_DIST_LT", "Values of the left tail F probability distribution."), - NC_("SC_OPCODE_F_DIST_LT", "Number"), - NC_("SC_OPCODE_F_DIST_LT", "The value for which the F distribution is to be calculated."), - NC_("SC_OPCODE_F_DIST_LT", "Degrees freedom 1"), - NC_("SC_OPCODE_F_DIST_LT", "The degrees of freedom in the numerator of the F distribution."), - NC_("SC_OPCODE_F_DIST_LT", "Degrees freedom 2"), - NC_("SC_OPCODE_F_DIST_LT", "The degrees of freedom in the denominator of the F distribution."), - NC_("SC_OPCODE_F_DIST_LT", "Cumulative"), - NC_("SC_OPCODE_F_DIST_LT", "Cumulative distribution function (TRUE) or probability density function (FALSE).") + NC_("ocF_DIST_LT", "Values of the left tail F probability distribution."), + NC_("ocF_DIST_LT", "Number"), + NC_("ocF_DIST_LT", "The value for which the F distribution is to be calculated."), + NC_("ocF_DIST_LT", "Degrees of freedom 1"), + NC_("ocF_DIST_LT", "The degrees of freedom in the numerator of the F distribution."), + NC_("ocF_DIST_LT", "Degrees of freedom 2"), + NC_("ocF_DIST_LT", "The degrees of freedom in the denominator of the F distribution."), + NC_("ocF_DIST_LT", "Cumulative"), + NC_("ocF_DIST_LT", "Cumulative distribution function (TRUE) or probability density function (FALSE).") }; // -=*# Resource for function F.DIST.RT #*=- -const TranslateId SC_OPCODE_F_DIST_RT_ARY[] = +const TranslateId ocF_DIST_RT_ARY[] = { - NC_("SC_OPCODE_F_DIST_RT", "Values of the right tail F probability distribution."), - NC_("SC_OPCODE_F_DIST_RT", "Number"), - NC_("SC_OPCODE_F_DIST_RT", "The value for which the F distribution is to be calculated."), - NC_("SC_OPCODE_F_DIST_RT", "Degrees freedom 1"), - NC_("SC_OPCODE_F_DIST_RT", "The degrees of freedom in the numerator of the F distribution."), - NC_("SC_OPCODE_F_DIST_RT", "Degrees freedom 2"), - NC_("SC_OPCODE_F_DIST_RT", "The degrees of freedom in the denominator of the F distribution.") + NC_("ocF_DIST_RT", "Values of the right tail F probability distribution."), + NC_("ocF_DIST_RT", "Number"), + NC_("ocF_DIST_RT", "The value for which the F distribution is to be calculated."), + NC_("ocF_DIST_RT", "Degrees of freedom 1"), + NC_("ocF_DIST_RT", "The degrees of freedom in the numerator of the F distribution."), + NC_("ocF_DIST_RT", "Degrees of freedom 2"), + NC_("ocF_DIST_RT", "The degrees of freedom in the denominator of the F distribution.") }; // -=*# Resource for function FINV #*=- -const TranslateId SC_OPCODE_F_INV_ARY[] = +const TranslateId ocF_INV_ARY[] = { - NC_("SC_OPCODE_F_INV", "Values of the inverse F distribution."), - NC_("SC_OPCODE_F_INV", "Number"), - NC_("SC_OPCODE_F_INV", "The probability value for which the inverse F distribution is to be calculated."), - NC_("SC_OPCODE_F_INV", "Degrees freedom 1"), - NC_("SC_OPCODE_F_INV", "The degrees of freedom in the numerator of the F distribution."), - NC_("SC_OPCODE_F_INV", "Degrees freedom 2"), - NC_("SC_OPCODE_F_INV", "The degrees of freedom in the denominator of the F distribution.") + NC_("ocF_INV", "Values of the inverse F distribution."), + NC_("ocF_INV", "Number"), + NC_("ocF_INV", "The probability value for which the inverse F distribution is to be calculated."), + NC_("ocF_INV", "Degrees of freedom 1"), + NC_("ocF_INV", "The degrees of freedom in the numerator of the F distribution."), + NC_("ocF_INV", "Degrees of freedom 2"), + NC_("ocF_INV", "The degrees of freedom in the denominator of the F distribution.") }; // -=*# Resource for function F.INV #*=- -const TranslateId SC_OPCODE_F_INV_LT_ARY[] = +const TranslateId ocF_INV_LT_ARY[] = { - NC_("SC_OPCODE_F_INV_LT", "Values of the inverse left tail F distribution."), - NC_("SC_OPCODE_F_INV_LT", "Number"), - NC_("SC_OPCODE_F_INV_LT", "The probability value for which the inverse F distribution is to be calculated."), - NC_("SC_OPCODE_F_INV_LT", "Degrees freedom 1"), - NC_("SC_OPCODE_F_INV_LT", "The degrees of freedom in the numerator of the F distribution."), - NC_("SC_OPCODE_F_INV_LT", "Degrees freedom 2"), - NC_("SC_OPCODE_F_INV_LT", "The degrees of freedom in the denominator of the F distribution.") + NC_("ocF_INV_LT", "Values of the inverse left tail F distribution."), + NC_("ocF_INV_LT", "Number"), + NC_("ocF_INV_LT", "The probability value for which the inverse F distribution is to be calculated."), + NC_("ocF_INV_LT", "Degrees of freedom 1"), + NC_("ocF_INV_LT", "The degrees of freedom in the numerator of the F distribution."), + NC_("ocF_INV_LT", "Degrees of freedom 2"), + NC_("ocF_INV_LT", "The degrees of freedom in the denominator of the F distribution.") }; // -=*# Resource for function F.INV.RT #*=- -const TranslateId SC_OPCODE_F_INV_RT_ARY[] = +const TranslateId ocF_INV_RT_ARY[] = { - NC_("SC_OPCODE_F_INV_RT", "Values of the inverse right tail F distribution."), - NC_("SC_OPCODE_F_INV_RT", "Number"), - NC_("SC_OPCODE_F_INV_RT", "The probability value for which the inverse F distribution is to be calculated."), - NC_("SC_OPCODE_F_INV_RT", "Degrees freedom 1"), - NC_("SC_OPCODE_F_INV_RT", "The degrees of freedom in the numerator of the F distribution."), - NC_("SC_OPCODE_F_INV_RT", "Degrees freedom 2"), - NC_("SC_OPCODE_F_INV_RT", "The degrees of freedom in the denominator of the F distribution.") + NC_("ocF_INV_RT", "Values of the inverse right tail F distribution."), + NC_("ocF_INV_RT", "Number"), + NC_("ocF_INV_RT", "The probability value for which the inverse F distribution is to be calculated."), + NC_("ocF_INV_RT", "Degrees of freedom 1"), + NC_("ocF_INV_RT", "The degrees of freedom in the numerator of the F distribution."), + NC_("ocF_INV_RT", "Degrees of freedom 2"), + NC_("ocF_INV_RT", "The degrees of freedom in the denominator of the F distribution.") }; // -=*# Resource for function CHIDIST #*=- -const TranslateId SC_OPCODE_CHI_DIST_ARY[] = +const TranslateId ocCHI_DIST_ARY[] = { - NC_("SC_OPCODE_CHI_DIST", "Returns the right-tail probability of the chi-square distribution."), - NC_("SC_OPCODE_CHI_DIST", "Number"), - NC_("SC_OPCODE_CHI_DIST", "The value for which the chi square distribution is to be calculated."), - NC_("SC_OPCODE_CHI_DIST", "Degrees freedom"), - NC_("SC_OPCODE_CHI_DIST", "The degrees of freedom of the chi square distribution.") + NC_("ocCHI_DIST", "Returns the right-tail probability of the chi-square distribution."), + NC_("ocCHI_DIST", "Number"), + NC_("ocCHI_DIST", "The value for which the chi square distribution is to be calculated."), + NC_("ocCHI_DIST", "Degrees of freedom"), + NC_("ocCHI_DIST", "The degrees of freedom of the chi square distribution.") }; // -=*# Resource for function CHISQ.DIST.RT #*=- -const TranslateId SC_OPCODE_CHI_DIST_MS_ARY[] = +const TranslateId ocCHI_DIST_MS_ARY[] = { - NC_("SC_OPCODE_CHI_DIST_MS", "Returns the right-tail probability of the chi-square distribution."), - NC_("SC_OPCODE_CHI_DIST_MS", "Number"), - NC_("SC_OPCODE_CHI_DIST_MS", "The value for which the chi square distribution is to be calculated."), - NC_("SC_OPCODE_CHI_DIST_MS", "Degrees freedom"), - NC_("SC_OPCODE_CHI_DIST_MS", "The degrees of freedom of the chi square distribution.") + NC_("ocCHI_DIST_MS", "Returns the right-tail probability of the chi-square distribution."), + NC_("ocCHI_DIST_MS", "Number"), + NC_("ocCHI_DIST_MS", "The value for which the chi square distribution is to be calculated."), + NC_("ocCHI_DIST_MS", "Degrees of freedom"), + NC_("ocCHI_DIST_MS", "The degrees of freedom of the chi square distribution.") }; // -=*# Resource for function CHISQDIST #*=- -const TranslateId SC_OPCODE_CHISQ_DIST_ARY[] = +const TranslateId ocCHISQ_DIST_ARY[] = { - NC_("SC_OPCODE_CHISQ_DIST", "Returns left-tail probability of the cumulative distribution function or values of the probability density function of the chi-square distribution."), - NC_("SC_OPCODE_CHISQ_DIST", "Number"), - NC_("SC_OPCODE_CHISQ_DIST", "The value for which the probability density function or cumulative distribution function is to be calculated."), - NC_("SC_OPCODE_CHISQ_DIST", "Degrees of Freedom"), - NC_("SC_OPCODE_CHISQ_DIST", "The degrees of freedom of the chi-square distribution."), - NC_("SC_OPCODE_CHISQ_DIST", "Cumulative"), - NC_("SC_OPCODE_CHISQ_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") + NC_("ocCHISQ_DIST", "Returns left-tail probability of the cumulative distribution function or values of the probability density function of the chi-square distribution."), + NC_("ocCHISQ_DIST", "Number"), + NC_("ocCHISQ_DIST", "The value for which the probability density function or cumulative distribution function is to be calculated."), + NC_("ocCHISQ_DIST", "Degrees of freedom"), + NC_("ocCHISQ_DIST", "The degrees of freedom of the chi-square distribution."), + NC_("ocCHISQ_DIST", "Cumulative"), + NC_("ocCHISQ_DIST", "0 or FALSE calculates the probability density function. Any other value or TRUE or omitted calculates the cumulative distribution function.") }; // -=*# Resource for function CHISQ.DIST #*=- -const TranslateId SC_OPCODE_CHISQ_DIST_MS_ARY[] = +const TranslateId ocCHISQ_DIST_MS_ARY[] = { - NC_("SC_OPCODE_CHISQ_DIST_MS", "Returns left-tail probability of the cumulative distribution function or values of the probability density function of the chi-square distribution."), - NC_("SC_OPCODE_CHISQ_DIST_MS", "Number"), - NC_("SC_OPCODE_CHISQ_DIST_MS", "The value for which the probability density function or cumulative distribution function is to be calculated."), - NC_("SC_OPCODE_CHISQ_DIST_MS", "Degrees of Freedom"), - NC_("SC_OPCODE_CHISQ_DIST_MS", "The degrees of freedom of the chi-square distribution."), - NC_("SC_OPCODE_CHISQ_DIST_MS", "Cumulative"), - NC_("SC_OPCODE_CHISQ_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") + NC_("ocCHISQ_DIST_MS", "Returns left-tail probability of the cumulative distribution function or values of the probability density function of the chi-square distribution."), + NC_("ocCHISQ_DIST_MS", "Number"), + NC_("ocCHISQ_DIST_MS", "The value for which the probability density function or cumulative distribution function is to be calculated."), + NC_("ocCHISQ_DIST_MS", "Degrees of freedom"), + NC_("ocCHISQ_DIST_MS", "The degrees of freedom of the chi-square distribution."), + NC_("ocCHISQ_DIST_MS", "Cumulative"), + NC_("ocCHISQ_DIST_MS", "0 or FALSE calculates the probability density function. Any other value or TRUE calculates the cumulative distribution function.") }; // -=*# Resource for function CHIINV #*=- -const TranslateId SC_OPCODE_CHI_INV_ARY[] = +const TranslateId ocCHI_INV_ARY[] = { - NC_("SC_OPCODE_CHI_INV", "Values of the inverse of CHIDIST(x; DegreesOfFreedom)."), - NC_("SC_OPCODE_CHI_INV", "Number"), - NC_("SC_OPCODE_CHI_INV", "The probability value for which the inverse chi square distribution is to be calculated."), - NC_("SC_OPCODE_CHI_INV", "Degrees freedom"), - NC_("SC_OPCODE_CHI_INV", "The degrees of freedom of the chi square distribution.") + NC_("ocCHI_INV", "Values of the inverse of CHIDIST(x; DegreesOfFreedom)."), + NC_("ocCHI_INV", "Number"), + NC_("ocCHI_INV", "The probability value for which the inverse chi square distribution is to be calculated."), + NC_("ocCHI_INV", "Degrees of freedom"), + NC_("ocCHI_INV", "The degrees of freedom of the chi square distribution.") }; // -=*# Resource for function CHISQ.INV.RT #*=- -const TranslateId SC_OPCODE_CHI_INV_MS_ARY[] = +const TranslateId ocCHI_INV_MS_ARY[] = { - NC_("SC_OPCODE_CHI_INV_MS", "Values of the inverse of CHIDIST(x; DegreesOfFreedom)."), - NC_("SC_OPCODE_CHI_INV_MS", "Number"), - NC_("SC_OPCODE_CHI_INV_MS", "The probability value for which the inverse chi square distribution is to be calculated."), - NC_("SC_OPCODE_CHI_INV_MS", "Degrees freedom"), - NC_("SC_OPCODE_CHI_INV_MS", "The degrees of freedom of the chi square distribution.") + NC_("ocCHI_INV_MS", "Values of the inverse of CHIDIST(x; DegreesOfFreedom)."), + NC_("ocCHI_INV_MS", "Number"), + NC_("ocCHI_INV_MS", "The probability value for which the inverse chi square distribution is to be calculated."), + NC_("ocCHI_INV_MS", "Degrees of freedom"), + NC_("ocCHI_INV_MS", "The degrees of freedom of the chi square distribution.") }; // -=*# Resource for function CHISQINV #*=- -const TranslateId SC_OPCODE_CHISQ_INV_ARY[] = +const TranslateId ocCHISQ_INV_ARY[] = { - NC_("SC_OPCODE_CHISQ_INV", "Values of the inverse of CHISQDIST(x;DegreesOfFreedom;TRUE())."), - NC_("SC_OPCODE_CHISQ_INV", "Probability"), - NC_("SC_OPCODE_CHISQ_INV", "The probability value for which the inverse of the chi square distribution is to be calculated."), - NC_("SC_OPCODE_CHISQ_INV", "Degrees of Freedom"), - NC_("SC_OPCODE_CHISQ_INV", "The degrees of freedom of the chi square distribution.") + NC_("ocCHISQ_INV", "Values of the inverse of CHISQDIST(x;DegreesOfFreedom;TRUE())."), + NC_("ocCHISQ_INV", "Probability"), + NC_("ocCHISQ_INV", "The probability value for which the inverse of the chi square distribution is to be calculated."), + NC_("ocCHISQ_INV", "Degrees of freedom"), + NC_("ocCHISQ_INV", "The degrees of freedom of the chi square distribution.") }; // -=*# Resource for function CHISQ.INV #*=- -const TranslateId SC_OPCODE_CHISQ_INV_MS_ARY[] = +const TranslateId ocCHISQ_INV_MS_ARY[] = { - NC_("SC_OPCODE_CHISQ_INV_MS", "Values of the inverse of CHISQ.DIST(x;DegreesOfFreedom;TRUE())."), - NC_("SC_OPCODE_CHISQ_INV_MS", "Probability"), - NC_("SC_OPCODE_CHISQ_INV_MS", "The probability value for which the inverse of the chi square distribution is to be calculated."), - NC_("SC_OPCODE_CHISQ_INV_MS", "Degrees of Freedom"), - NC_("SC_OPCODE_CHISQ_INV_MS", "The degrees of freedom of the chi square distribution.") + NC_("ocCHISQ_INV_MS", "Values of the inverse of CHISQ.DIST(x;DegreesOfFreedom;TRUE())."), + NC_("ocCHISQ_INV_MS", "Probability"), + NC_("ocCHISQ_INV_MS", "The probability value for which the inverse of the chi square distribution is to be calculated."), + NC_("ocCHISQ_INV_MS", "Degrees of freedom"), + NC_("ocCHISQ_INV_MS", "The degrees of freedom of the chi square distribution.") }; // -=*# Resource for function STANDARDIZE #*=- -const TranslateId SC_OPCODE_STANDARD_ARY[] = +const TranslateId ocSTANDARD_ARY[] = { - NC_("SC_OPCODE_STANDARD", "Converts a random variable to a normalized value."), - NC_("SC_OPCODE_STANDARD", "Number"), - NC_("SC_OPCODE_STANDARD", "The value to be standardized."), - NC_("SC_OPCODE_STANDARD", "Mean"), - NC_("SC_OPCODE_STANDARD", "The mean value used for moving."), - NC_("SC_OPCODE_STANDARD", "STDEV"), - NC_("SC_OPCODE_STANDARD", "The standard deviation used for scaling.") + NC_("ocSTANDARD", "Converts a random variable to a normalized value."), + NC_("ocSTANDARD", "Number"), + NC_("ocSTANDARD", "The value to be standardized."), + NC_("ocSTANDARD", "Mean"), + NC_("ocSTANDARD", "The mean value used for moving."), + NC_("ocSTANDARD", "STDEV"), + NC_("ocSTANDARD", "The standard deviation used for scaling.") }; // -=*# Resource for function PERMUT #*=- -const TranslateId SC_OPCODE_PERMUT_ARY[] = +const TranslateId ocPERMUT_ARY[] = { - NC_("SC_OPCODE_PERMUT", "Returns the number of permutations for a given number of elements without repetition."), - NC_("SC_OPCODE_PERMUT", "Count 1"), - NC_("SC_OPCODE_PERMUT", "The total number of elements."), - NC_("SC_OPCODE_PERMUT", "Count 2"), - NC_("SC_OPCODE_PERMUT", "The selection number taken from the elements.") + NC_("ocPERMUT", "Returns the number of permutations for a given number of elements without repetition."), + NC_("ocPERMUT", "Count 1"), + NC_("ocPERMUT", "The total number of elements."), + NC_("ocPERMUT", "Count 2"), + NC_("ocPERMUT", "The selection number taken from the elements.") }; // -=*# Resource for function PERMUTATIONA #*=- -const TranslateId SC_OPCODE_PERMUTATION_A_ARY[] = +const TranslateId ocPERMUTATION_A_ARY[] = { - NC_("SC_OPCODE_PERMUTATION_A", "Returns the number of permutations for a given number of objects (repetition allowed)."), - NC_("SC_OPCODE_PERMUTATION_A", "Count 1"), - NC_("SC_OPCODE_PERMUTATION_A", "The total number of elements."), - NC_("SC_OPCODE_PERMUTATION_A", "Count 2"), - NC_("SC_OPCODE_PERMUTATION_A", "The selection number taken from the elements.") + NC_("ocPERMUTATION_A", "Returns the number of permutations for a given number of objects (repetition allowed)."), + NC_("ocPERMUTATION_A", "Count 1"), + NC_("ocPERMUTATION_A", "The total number of elements."), + NC_("ocPERMUTATION_A", "Count 2"), + NC_("ocPERMUTATION_A", "The selection number taken from the elements.") }; // -=*# Resource for function CONFIDENCE #*=- -const TranslateId SC_OPCODE_CONFIDENCE_ARY[] = +const TranslateId ocCONFIDENCE_ARY[] = { - NC_("SC_OPCODE_CONFIDENCE", "Returns a (1-alpha) confidence interval for a normal distribution."), - NC_("SC_OPCODE_CONFIDENCE", "Alpha"), - NC_("SC_OPCODE_CONFIDENCE", "The level of the confidence interval."), - NC_("SC_OPCODE_CONFIDENCE", "STDEV"), - NC_("SC_OPCODE_CONFIDENCE", "The standard deviation of the population."), - NC_("SC_OPCODE_CONFIDENCE", "Size"), - NC_("SC_OPCODE_CONFIDENCE", "The size of the population.") + NC_("ocCONFIDENCE", "Returns a (1-alpha) confidence interval for a normal distribution."), + NC_("ocCONFIDENCE", "Alpha"), + NC_("ocCONFIDENCE", "The level of the confidence interval."), + NC_("ocCONFIDENCE", "STDEV"), + NC_("ocCONFIDENCE", "The standard deviation of the population."), + NC_("ocCONFIDENCE", "Size"), + NC_("ocCONFIDENCE", "The size of the population.") }; // -=*# Resource for function CONFIDENCE.NORM #*=- -const TranslateId SC_OPCODE_CONFIDENCE_N_ARY[] = +const TranslateId ocCONFIDENCE_N_ARY[] = { - NC_("SC_OPCODE_CONFIDENCE_N", "Returns a (1-alpha) confidence interval for a normal distribution."), - NC_("SC_OPCODE_CONFIDENCE_N", "Alpha"), - NC_("SC_OPCODE_CONFIDENCE_N", "The level of the confidence interval."), - NC_("SC_OPCODE_CONFIDENCE_N", "STDEV"), - NC_("SC_OPCODE_CONFIDENCE_N", "The standard deviation of the population."), - NC_("SC_OPCODE_CONFIDENCE_N", "Size"), - NC_("SC_OPCODE_CONFIDENCE_N", "The size of the population.") + NC_("ocCONFIDENCE_N", "Returns a (1-alpha) confidence interval for a normal distribution."), + NC_("ocCONFIDENCE_N", "Alpha"), + NC_("ocCONFIDENCE_N", "The level of the confidence interval."), + NC_("ocCONFIDENCE_N", "STDEV"), + NC_("ocCONFIDENCE_N", "The standard deviation of the population."), + NC_("ocCONFIDENCE_N", "Size"), + NC_("ocCONFIDENCE_N", "The size of the population.") }; // -=*# Resource for function CONFIDENCE.T #*=- -const TranslateId SC_OPCODE_CONFIDENCE_T_ARY[] = +const TranslateId ocCONFIDENCE_T_ARY[] = { - NC_("SC_OPCODE_CONFIDENCE_T", "Returns a (1-alpha) confidence interval for a Student's t distribution."), - NC_("SC_OPCODE_CONFIDENCE_T", "Alpha"), - NC_("SC_OPCODE_CONFIDENCE_T", "The level of the confidence interval."), - NC_("SC_OPCODE_CONFIDENCE_T", "STDEV"), - NC_("SC_OPCODE_CONFIDENCE_T", "The standard deviation of the population."), - NC_("SC_OPCODE_CONFIDENCE_T", "Size"), - NC_("SC_OPCODE_CONFIDENCE_T", "The size of the population.") + NC_("ocCONFIDENCE_T", "Returns a (1-alpha) confidence interval for a Student's t distribution."), + NC_("ocCONFIDENCE_T", "Alpha"), + NC_("ocCONFIDENCE_T", "The level of the confidence interval."), + NC_("ocCONFIDENCE_T", "STDEV"), + NC_("ocCONFIDENCE_T", "The standard deviation of the population."), + NC_("ocCONFIDENCE_T", "Size"), + NC_("ocCONFIDENCE_T", "The size of the population.") }; // -=*# Resource for function ZTEST #*=- -const TranslateId SC_OPCODE_Z_TEST_ARY[] = +const TranslateId ocZ_TEST_ARY[] = { - NC_("SC_OPCODE_Z_TEST", "Calculates the probability of observing a z-statistic greater than the one computed based on a sample."), - NC_("SC_OPCODE_Z_TEST", "Data"), - NC_("SC_OPCODE_Z_TEST", "The given sample, drawn from a normally distributed population."), - NC_("SC_OPCODE_Z_TEST", "mu"), - NC_("SC_OPCODE_Z_TEST", "The known mean of the population."), - NC_("SC_OPCODE_Z_TEST", "sigma"), - NC_("SC_OPCODE_Z_TEST", "The known standard deviation of the population. If omitted, the standard deviation of the given sample is used.") + NC_("ocZ_TEST", "Calculates the probability of observing a z-statistic greater than the one computed based on a sample."), + NC_("ocZ_TEST", "Data"), + NC_("ocZ_TEST", "The given sample, drawn from a normally distributed population."), + NC_("ocZ_TEST", "mu"), + NC_("ocZ_TEST", "The known mean of the population."), + NC_("ocZ_TEST", "sigma"), + NC_("ocZ_TEST", "The known standard deviation of the population. If omitted, the standard deviation of the given sample is used.") }; // -=*# Resource for function Z.TEST #*=- -const TranslateId SC_OPCODE_Z_TEST_MS_ARY[] = +const TranslateId ocZ_TEST_MS_ARY[] = { - NC_("SC_OPCODE_Z_TEST_MS", "Calculates the probability of observing a z-statistic greater than the one computed based on a sample."), - NC_("SC_OPCODE_Z_TEST_MS", "Data"), - NC_("SC_OPCODE_Z_TEST_MS", "The given sample, drawn from a normally distributed population."), - NC_("SC_OPCODE_Z_TEST_MS", "mu"), - NC_("SC_OPCODE_Z_TEST_MS", "The known mean of the population."), - NC_("SC_OPCODE_Z_TEST_MS", "sigma"), - NC_("SC_OPCODE_Z_TEST_MS", "The known standard deviation of the population. If omitted, the standard deviation of the given sample is used.") + NC_("ocZ_TEST_MS", "Calculates the probability of observing a z-statistic greater than the one computed based on a sample."), + NC_("ocZ_TEST_MS", "Data"), + NC_("ocZ_TEST_MS", "The given sample, drawn from a normally distributed population."), + NC_("ocZ_TEST_MS", "mu"), + NC_("ocZ_TEST_MS", "The known mean of the population."), + NC_("ocZ_TEST_MS", "sigma"), + NC_("ocZ_TEST_MS", "The known standard deviation of the population. If omitted, the standard deviation of the given sample is used.") }; // -=*# Resource for function CHITEST #*=- -const TranslateId SC_OPCODE_CHI_TEST_ARY[] = +const TranslateId ocCHI_TEST_ARY[] = { - NC_("SC_OPCODE_CHI_TEST", "Returns the chi square independence test."), - NC_("SC_OPCODE_CHI_TEST", "Data B"), - NC_("SC_OPCODE_CHI_TEST", "The observed data array."), - NC_("SC_OPCODE_CHI_TEST", "Data E"), - NC_("SC_OPCODE_CHI_TEST", "The expected data array.") + NC_("ocCHI_TEST", "Returns the chi square independence test."), + NC_("ocCHI_TEST", "Data B"), + NC_("ocCHI_TEST", "The observed data array."), + NC_("ocCHI_TEST", "Data E"), + NC_("ocCHI_TEST", "The expected data array.") }; // -=*# Resource for function CHISQ.TEST #*=- -const TranslateId SC_OPCODE_CHI_TEST_MS_ARY[] = +const TranslateId ocCHI_TEST_MS_ARY[] = { - NC_("SC_OPCODE_CHI_TEST_MS", "Returns the chi square independence test."), - NC_("SC_OPCODE_CHI_TEST_MS", "Data B"), - NC_("SC_OPCODE_CHI_TEST_MS", "The observed data array."), - NC_("SC_OPCODE_CHI_TEST_MS", "Data E"), - NC_("SC_OPCODE_CHI_TEST_MS", "The expected data array.") + NC_("ocCHI_TEST_MS", "Returns the chi square independence test."), + NC_("ocCHI_TEST_MS", "Data B"), + NC_("ocCHI_TEST_MS", "The observed data array."), + NC_("ocCHI_TEST_MS", "Data E"), + NC_("ocCHI_TEST_MS", "The expected data array.") }; // -=*# Resource for function FTEST #*=- -const TranslateId SC_OPCODE_F_TEST_ARY[] = +const TranslateId ocF_TEST_ARY[] = { - NC_("SC_OPCODE_F_TEST", "Calculates the F test."), - NC_("SC_OPCODE_F_TEST", "Data 1"), - NC_("SC_OPCODE_F_TEST", "The first record array."), - NC_("SC_OPCODE_F_TEST", "Data 2"), - NC_("SC_OPCODE_F_TEST", "The second record array.") + NC_("ocF_TEST", "Calculates the F test."), + NC_("ocF_TEST", "Data 1"), + NC_("ocF_TEST", "The first record array."), + NC_("ocF_TEST", "Data 2"), + NC_("ocF_TEST", "The second record array.") }; // -=*# Resource for function F.TEST #*=- -const TranslateId SC_OPCODE_F_TEST_MS_ARY[] = +const TranslateId ocF_TEST_MS_ARY[] = { - NC_("SC_OPCODE_F_TEST_MS", "Calculates the F test."), - NC_("SC_OPCODE_F_TEST_MS", "Data 1"), - NC_("SC_OPCODE_F_TEST_MS", "The first record array."), - NC_("SC_OPCODE_F_TEST_MS", "Data 2"), - NC_("SC_OPCODE_F_TEST_MS", "The second record array.") + NC_("ocF_TEST_MS", "Calculates the F test."), + NC_("ocF_TEST_MS", "Data 1"), + NC_("ocF_TEST_MS", "The first record array."), + NC_("ocF_TEST_MS", "Data 2"), + NC_("ocF_TEST_MS", "The second record array.") }; // -=*# Resource for function TTEST #*=- -const TranslateId SC_OPCODE_T_TEST_ARY[] = +const TranslateId ocT_TEST_ARY[] = { - NC_("SC_OPCODE_T_TEST", "Calculates the t-test."), - NC_("SC_OPCODE_T_TEST", "Data 1"), - NC_("SC_OPCODE_T_TEST", "The first record array."), - NC_("SC_OPCODE_T_TEST", "Data 2"), - NC_("SC_OPCODE_T_TEST", "The second record array."), - NC_("SC_OPCODE_T_TEST", "Mode"), - NC_("SC_OPCODE_T_TEST", "Mode specifies the number of distribution tails to return. 1 = one-tailed, 2 = two-tailed distribution"), - NC_("SC_OPCODE_T_TEST", "Type"), - NC_("SC_OPCODE_T_TEST", "The type of the t-test.") + NC_("ocT_TEST", "Calculates the t-test."), + NC_("ocT_TEST", "Data 1"), + NC_("ocT_TEST", "The first record array."), + NC_("ocT_TEST", "Data 2"), + NC_("ocT_TEST", "The second record array."), + NC_("ocT_TEST", "Mode"), + NC_("ocT_TEST", "Mode specifies the number of distribution tails to return. 1 = one-tailed, 2 = two-tailed distribution"), + NC_("ocT_TEST", "Type"), + NC_("ocT_TEST", "The type of the t-test.") }; // -=*# Resource for function T.TEST #*=- -const TranslateId SC_OPCODE_T_TEST_MS_ARY[] = +const TranslateId ocT_TEST_MS_ARY[] = { - NC_("SC_OPCODE_T_TEST_MS", "Calculates the t-test."), - NC_("SC_OPCODE_T_TEST_MS", "Data 1"), - NC_("SC_OPCODE_T_TEST_MS", "The first record array."), - NC_("SC_OPCODE_T_TEST_MS", "Data 2"), - NC_("SC_OPCODE_T_TEST_MS", "The second record array."), - NC_("SC_OPCODE_T_TEST_MS", "Mode"), - NC_("SC_OPCODE_T_TEST_MS", "Mode specifies the number of distribution tails to return. 1 = one-tailed, 2 = two-tailed distribution"), - NC_("SC_OPCODE_T_TEST_MS", "Type"), - NC_("SC_OPCODE_T_TEST_MS", "The type of the t-test.") + NC_("ocT_TEST_MS", "Calculates the t-test."), + NC_("ocT_TEST_MS", "Data 1"), + NC_("ocT_TEST_MS", "The first record array."), + NC_("ocT_TEST_MS", "Data 2"), + NC_("ocT_TEST_MS", "The second record array."), + NC_("ocT_TEST_MS", "Mode"), + NC_("ocT_TEST_MS", "Mode specifies the number of distribution tails to return. 1 = one-tailed, 2 = two-tailed distribution"), + NC_("ocT_TEST_MS", "Type"), + NC_("ocT_TEST_MS", "The type of the t-test.") }; // -=*# Resource for function RSQ #*=- -const TranslateId SC_OPCODE_RSQ_ARY[] = +const TranslateId ocRSQ_ARY[] = { - NC_("SC_OPCODE_RSQ", "Returns the square of the Pearson product moment correlation coefficient."), - NC_("SC_OPCODE_RSQ", "Data Y"), - NC_("SC_OPCODE_RSQ", "The Y data array."), - NC_("SC_OPCODE_RSQ", "Data X"), - NC_("SC_OPCODE_RSQ", "The X data array.") + NC_("ocRSQ", "Returns the square of the Pearson product moment correlation coefficient."), + NC_("ocRSQ", "Data Y"), + NC_("ocRSQ", "The Y data array."), + NC_("ocRSQ", "Data X"), + NC_("ocRSQ", "The X data array.") }; // -=*# Resource for function INTERCEPT #*=- -const TranslateId SC_OPCODE_INTERCEPT_ARY[] = +const TranslateId ocINTERCEPT_ARY[] = { - NC_("SC_OPCODE_INTERCEPT", "Returns the intercept of the linear regression line and the Y axis."), - NC_("SC_OPCODE_INTERCEPT", "Data Y"), - NC_("SC_OPCODE_INTERCEPT", "The Y data array."), - NC_("SC_OPCODE_INTERCEPT", "Data X"), - NC_("SC_OPCODE_INTERCEPT", "The X data array.") + NC_("ocINTERCEPT", "Returns the intercept of the linear regression line and the Y axis."), + NC_("ocINTERCEPT", "Data Y"), + NC_("ocINTERCEPT", "The Y data array."), + NC_("ocINTERCEPT", "Data X"), + NC_("ocINTERCEPT", "The X data array.") }; // -=*# Resource for function SLOPE #*=- -const TranslateId SC_OPCODE_SLOPE_ARY[] = +const TranslateId ocSLOPE_ARY[] = { - NC_("SC_OPCODE_SLOPE", "Returns the slope of the linear regression line."), - NC_("SC_OPCODE_SLOPE", "Data Y"), - NC_("SC_OPCODE_SLOPE", "The Y data array."), - NC_("SC_OPCODE_SLOPE", "Data X"), - NC_("SC_OPCODE_SLOPE", "The X data array.") + NC_("ocSLOPE", "Returns the slope of the linear regression line."), + NC_("ocSLOPE", "Data Y"), + NC_("ocSLOPE", "The Y data array."), + NC_("ocSLOPE", "Data X"), + NC_("ocSLOPE", "The X data array.") }; // -=*# Resource for function STEYX #*=- -const TranslateId SC_OPCODE_STEYX_ARY[] = +const TranslateId ocSTEYX_ARY[] = { - NC_("SC_OPCODE_STEYX", "Returns the standard error of the linear regression."), - NC_("SC_OPCODE_STEYX", "Data Y"), - NC_("SC_OPCODE_STEYX", "The Y data array."), - NC_("SC_OPCODE_STEYX", "Data X"), - NC_("SC_OPCODE_STEYX", "The X data array.") + NC_("ocSTEYX", "Returns the standard error of the linear regression."), + NC_("ocSTEYX", "Data Y"), + NC_("ocSTEYX", "The Y data array."), + NC_("ocSTEYX", "Data X"), + NC_("ocSTEYX", "The X data array.") }; // -=*# Resource for function PEARSON #*=- -const TranslateId SC_OPCODE_PEARSON_ARY[] = +const TranslateId ocPEARSON_ARY[] = { - NC_("SC_OPCODE_PEARSON", "Returns the Pearson product moment correlation coefficient."), - NC_("SC_OPCODE_PEARSON", "Data 1"), - NC_("SC_OPCODE_PEARSON", "The first record array."), - NC_("SC_OPCODE_PEARSON", "Data 2"), - NC_("SC_OPCODE_PEARSON", "The second record array.") + NC_("ocPEARSON", "Returns the Pearson product moment correlation coefficient."), + NC_("ocPEARSON", "Data 1"), + NC_("ocPEARSON", "The first record array."), + NC_("ocPEARSON", "Data 2"), + NC_("ocPEARSON", "The second record array.") }; // -=*# Resource for function CORREL #*=- -const TranslateId SC_OPCODE_CORREL_ARY[] = +const TranslateId ocCORREL_ARY[] = { - NC_("SC_OPCODE_CORREL", "Returns the correlation coefficient."), - NC_("SC_OPCODE_CORREL", "Data 1"), - NC_("SC_OPCODE_CORREL", "The first record array."), - NC_("SC_OPCODE_CORREL", "Data 2"), - NC_("SC_OPCODE_CORREL", "The second record array.") + NC_("ocCORREL", "Returns the correlation coefficient."), + NC_("ocCORREL", "Data 1"), + NC_("ocCORREL", "The first record array."), + NC_("ocCORREL", "Data 2"), + NC_("ocCORREL", "The second record array.") }; // -=*# Resource for function COVAR #*=- -const TranslateId SC_OPCODE_COVAR_ARY[] = +const TranslateId ocCOVAR_ARY[] = { - NC_("SC_OPCODE_COVAR", "Calculates the population covariance."), - NC_("SC_OPCODE_COVAR", "Data 1"), - NC_("SC_OPCODE_COVAR", "The first record array."), - NC_("SC_OPCODE_COVAR", "Data 2"), - NC_("SC_OPCODE_COVAR", "The second record array.") + NC_("ocCOVAR", "Calculates the population covariance."), + NC_("ocCOVAR", "Data 1"), + NC_("ocCOVAR", "The first record array."), + NC_("ocCOVAR", "Data 2"), + NC_("ocCOVAR", "The second record array.") }; // -=*# Resource for function COVARIANCE.P #*=- -const TranslateId SC_OPCODE_COVARIANCE_P_ARY[] = +const TranslateId ocCOVARIANCE_P_ARY[] = { - NC_("SC_OPCODE_COVARIANCE_P", "Calculates the population covariance."), - NC_("SC_OPCODE_COVARIANCE_P", "Data 1"), - NC_("SC_OPCODE_COVARIANCE_P", "The first record array."), - NC_("SC_OPCODE_COVARIANCE_P", "Data 2"), - NC_("SC_OPCODE_COVARIANCE_P", "The second record array.") + NC_("ocCOVARIANCE_P", "Calculates the population covariance."), + NC_("ocCOVARIANCE_P", "Data 1"), + NC_("ocCOVARIANCE_P", "The first record array."), + NC_("ocCOVARIANCE_P", "Data 2"), + NC_("ocCOVARIANCE_P", "The second record array.") }; // -=*# Resource for function COVARIANCE.S #*=- -const TranslateId SC_OPCODE_COVARIANCE_S_ARY[] = +const TranslateId ocCOVARIANCE_S_ARY[] = { - NC_("SC_OPCODE_COVARIANCE_S", "Calculates the sample covariance."), - NC_("SC_OPCODE_COVARIANCE_S", "Data 1"), - NC_("SC_OPCODE_COVARIANCE_S", "The first record array."), - NC_("SC_OPCODE_COVARIANCE_S", "Data 2"), - NC_("SC_OPCODE_COVARIANCE_S", "The second record array.") + NC_("ocCOVARIANCE_S", "Calculates the sample covariance."), + NC_("ocCOVARIANCE_S", "Data 1"), + NC_("ocCOVARIANCE_S", "The first record array."), + NC_("ocCOVARIANCE_S", "Data 2"), + NC_("ocCOVARIANCE_S", "The second record array.") }; // -=*# Resource for function FORECAST #*=- -const TranslateId SC_OPCODE_FORECAST_ARY[] = +const TranslateId ocFORECAST_ARY[] = { - NC_("SC_OPCODE_FORECAST", "Returns a value along a linear regression"), - NC_("SC_OPCODE_FORECAST", "Value"), - NC_("SC_OPCODE_FORECAST", "The X value for which the Y value on the regression linear is to be calculated."), - NC_("SC_OPCODE_FORECAST", "Data Y"), - NC_("SC_OPCODE_FORECAST", "The Y data array."), - NC_("SC_OPCODE_FORECAST", "Data X"), - NC_("SC_OPCODE_FORECAST", "The X data array.") + NC_("ocFORECAST", "Returns a value along a linear regression"), + NC_("ocFORECAST", "Value"), + NC_("ocFORECAST", "The X value for which the Y value on the regression linear is to be calculated."), + NC_("ocFORECAST", "Data Y"), + NC_("ocFORECAST", "The Y data array."), + NC_("ocFORECAST", "Data X"), + NC_("ocFORECAST", "The X data array.") }; // -=*# Resource for function FORECAST.ETS #*=- -const TranslateId SC_OPCODE_FORECAST_ETS_ADD_ARY[] = +const TranslateId ocFORECAST_ETS_ADD_ARY[] = { - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Calculates future value(s) using additive Exponential Smoothing algorithm."), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Target"), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "The date (array) for which you want to predict a value."), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Values"), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "The data array from which you want to forecast."), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Timeline"), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "The date or numeric array; a consistent step between values is needed."), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Period length"), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Number of Samples in Period (default 1); length of the seasonal pattern."), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Data completion"), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Aggregation"), - NC_("SC_OPCODE_FORECAST_ETS_ADD", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") + NC_("ocFORECAST_ETS_ADD", "Calculates future value(s) using additive Exponential Smoothing algorithm."), + NC_("ocFORECAST_ETS_ADD", "Target"), + NC_("ocFORECAST_ETS_ADD", "The date (array) for which you want to predict a value."), + NC_("ocFORECAST_ETS_ADD", "Values"), + NC_("ocFORECAST_ETS_ADD", "The data array from which you want to forecast."), + NC_("ocFORECAST_ETS_ADD", "Timeline"), + NC_("ocFORECAST_ETS_ADD", "The date or numeric array; a consistent step between values is needed."), + NC_("ocFORECAST_ETS_ADD", "Period length"), + NC_("ocFORECAST_ETS_ADD", "Number of Samples in Period (default 1); length of the seasonal pattern."), + NC_("ocFORECAST_ETS_ADD", "Data completion"), + NC_("ocFORECAST_ETS_ADD", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), + NC_("ocFORECAST_ETS_ADD", "Aggregation"), + NC_("ocFORECAST_ETS_ADD", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") }; // -=*# Resource for function FORECAST.ETS.MULT #*=- -const TranslateId SC_OPCODE_FORECAST_ETS_MUL_ARY[] = +const TranslateId ocFORECAST_ETS_MUL_ARY[] = { - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Calculates future value(s) using multiplicative Exponential Smoothing algorithm."), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Target"), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "The date (array) for which you want to predict a value."), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Values"), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "The data array from which you want to forecast."), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Timeline"), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "The date or numeric array; a consistent step between values is needed."), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Period length"), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Number of Samples in Period (default 1); length of the seasonal pattern."), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Data completion"), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Aggregation"), - NC_("SC_OPCODE_FORECAST_ETS_MUL", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") + NC_("ocFORECAST_ETS_MUL", "Calculates future value(s) using multiplicative Exponential Smoothing algorithm."), + NC_("ocFORECAST_ETS_MUL", "Target"), + NC_("ocFORECAST_ETS_MUL", "The date (array) for which you want to predict a value."), + NC_("ocFORECAST_ETS_MUL", "Values"), + NC_("ocFORECAST_ETS_MUL", "The data array from which you want to forecast."), + NC_("ocFORECAST_ETS_MUL", "Timeline"), + NC_("ocFORECAST_ETS_MUL", "The date or numeric array; a consistent step between values is needed."), + NC_("ocFORECAST_ETS_MUL", "Period length"), + NC_("ocFORECAST_ETS_MUL", "Number of Samples in Period (default 1); length of the seasonal pattern."), + NC_("ocFORECAST_ETS_MUL", "Data completion"), + NC_("ocFORECAST_ETS_MUL", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), + NC_("ocFORECAST_ETS_MUL", "Aggregation"), + NC_("ocFORECAST_ETS_MUL", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") }; // -=*# Resource for function FORECAST.ETS.CONFINT #*=- -const TranslateId SC_OPCODE_FORECAST_ETS_PIA_ARY[] = +const TranslateId ocFORECAST_ETS_PIA_ARY[] = { - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Returns a prediction interval at the specified target value(s) for additive Exponential Smoothing method"), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Target"), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "The date (array) for which you want to predict a value."), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Values"), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "The data array from which you want to forecast."), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Timeline"), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "The date or numeric array; a consistent step between values is needed."), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Confidence level"), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Confidence level (default 0.95); value 0 to 1 (exclusive) for 0 to 100% calculated prediction interval."), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Period length"), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Number of Samples in Period (default 1); length of the seasonal pattern."), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Data completion"), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Aggregation"), - NC_("SC_OPCODE_FORECAST_ETS_PIA", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") + NC_("ocFORECAST_ETS_PIA", "Returns a prediction interval at the specified target value(s) for additive Exponential Smoothing method"), + NC_("ocFORECAST_ETS_PIA", "Target"), + NC_("ocFORECAST_ETS_PIA", "The date (array) for which you want to predict a value."), + NC_("ocFORECAST_ETS_PIA", "Values"), + NC_("ocFORECAST_ETS_PIA", "The data array from which you want to forecast."), + NC_("ocFORECAST_ETS_PIA", "Timeline"), + NC_("ocFORECAST_ETS_PIA", "The date or numeric array; a consistent step between values is needed."), + NC_("ocFORECAST_ETS_PIA", "Confidence level"), + NC_("ocFORECAST_ETS_PIA", "Confidence level (default 0.95); value 0 to 1 (exclusive) for 0 to 100% calculated prediction interval."), + NC_("ocFORECAST_ETS_PIA", "Period length"), + NC_("ocFORECAST_ETS_PIA", "Number of Samples in Period (default 1); length of the seasonal pattern."), + NC_("ocFORECAST_ETS_PIA", "Data completion"), + NC_("ocFORECAST_ETS_PIA", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), + NC_("ocFORECAST_ETS_PIA", "Aggregation"), + NC_("ocFORECAST_ETS_PIA", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") }; // -=*# Resource for function FORECAST.ETS.PI.MULT #*=- -const TranslateId SC_OPCODE_FORECAST_ETS_PIM_ARY[] = +const TranslateId ocFORECAST_ETS_PIM_ARY[] = { - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Returns a prediction interval at the specified target value(s) for multiplicative Exponential Smoothing method"), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Target"), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "The date (array) for which you want to predict a value."), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Values"), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "The data array from which you want to forecast."), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Timeline"), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "The date or numeric array; a consistent step between values is needed."), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Confidence level"), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Confidence level (default 0.95); value 0 to 1 (exclusive) for 0 to 100% calculated prediction interval."), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Period length"), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Number of Samples in Period (default 1); length of the seasonal pattern."), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Data completion"), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Aggregation"), - NC_("SC_OPCODE_FORECAST_ETS_PIM", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") + NC_("ocFORECAST_ETS_PIM", "Returns a prediction interval at the specified target value(s) for multiplicative Exponential Smoothing method"), + NC_("ocFORECAST_ETS_PIM", "Target"), + NC_("ocFORECAST_ETS_PIM", "The date (array) for which you want to predict a value."), + NC_("ocFORECAST_ETS_PIM", "Values"), + NC_("ocFORECAST_ETS_PIM", "The data array from which you want to forecast."), + NC_("ocFORECAST_ETS_PIM", "Timeline"), + NC_("ocFORECAST_ETS_PIM", "The date or numeric array; a consistent step between values is needed."), + NC_("ocFORECAST_ETS_PIM", "Confidence level"), + NC_("ocFORECAST_ETS_PIM", "Confidence level (default 0.95); value 0 to 1 (exclusive) for 0 to 100% calculated prediction interval."), + NC_("ocFORECAST_ETS_PIM", "Period length"), + NC_("ocFORECAST_ETS_PIM", "Number of Samples in Period (default 1); length of the seasonal pattern."), + NC_("ocFORECAST_ETS_PIM", "Data completion"), + NC_("ocFORECAST_ETS_PIM", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), + NC_("ocFORECAST_ETS_PIM", "Aggregation"), + NC_("ocFORECAST_ETS_PIM", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") }; // -=*# Resource for function FORECAST.ETS.SEASONALITY #*=- -const TranslateId SC_OPCODE_FORECAST_ETS_SEA_ARY[] = +const TranslateId ocFORECAST_ETS_SEA_ARY[] = { - NC_("SC_OPCODE_FORECAST_ETS_SEA", "Calculates the number of samples in period (season) using additive Exponential Triple Smoothing algorithm."), - NC_("SC_OPCODE_FORECAST_ETS_SEA", "Values"), - NC_("SC_OPCODE_FORECAST_ETS_SEA", "The data array from which you want to forecast."), - NC_("SC_OPCODE_FORECAST_ETS_SEA", "Timeline"), - NC_("SC_OPCODE_FORECAST_ETS_SEA", "The date or numeric array; a consistent step between values is needed."), - NC_("SC_OPCODE_FORECAST_ETS_SEA", "Data completion"), - NC_("SC_OPCODE_FORECAST_ETS_SEA", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), - NC_("SC_OPCODE_FORECAST_ETS_SEA", "Aggregation"), - NC_("SC_OPCODE_FORECAST_ETS_SEA", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") + NC_("ocFORECAST_ETS_SEA", "Calculates the number of samples in period (season) using additive Exponential Triple Smoothing algorithm."), + NC_("ocFORECAST_ETS_SEA", "Values"), + NC_("ocFORECAST_ETS_SEA", "The data array from which you want to forecast."), + NC_("ocFORECAST_ETS_SEA", "Timeline"), + NC_("ocFORECAST_ETS_SEA", "The date or numeric array; a consistent step between values is needed."), + NC_("ocFORECAST_ETS_SEA", "Data completion"), + NC_("ocFORECAST_ETS_SEA", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), + NC_("ocFORECAST_ETS_SEA", "Aggregation"), + NC_("ocFORECAST_ETS_SEA", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") }; // -=*# Resource for function FORECAST.ETS.STAT #*=- -const TranslateId SC_OPCODE_FORECAST_ETS_STA_ARY[] = +const TranslateId ocFORECAST_ETS_STA_ARY[] = { - NC_("SC_OPCODE_FORECAST_ETS_STA", "Returns statistical value(s) using additive Exponential Smoothing algorithm."), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Values"), - NC_("SC_OPCODE_FORECAST_ETS_STA", "The data array from which you want to forecast."), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Timeline"), - NC_("SC_OPCODE_FORECAST_ETS_STA", "The date or numeric array; a consistent step between values is needed."), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Statistic type"), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Value (1-9) or array of values, indicating which statistic will be returned for the calculated forecast"), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Period length"), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Number of Samples in Period (default 1); length of the seasonal pattern."), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Data completion"), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Aggregation"), - NC_("SC_OPCODE_FORECAST_ETS_STA", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") + NC_("ocFORECAST_ETS_STA", "Returns statistical value(s) using additive Exponential Smoothing algorithm."), + NC_("ocFORECAST_ETS_STA", "Values"), + NC_("ocFORECAST_ETS_STA", "The data array from which you want to forecast."), + NC_("ocFORECAST_ETS_STA", "Timeline"), + NC_("ocFORECAST_ETS_STA", "The date or numeric array; a consistent step between values is needed."), + NC_("ocFORECAST_ETS_STA", "Statistic type"), + NC_("ocFORECAST_ETS_STA", "Value (1-9) or array of values, indicating which statistic will be returned for the calculated forecast"), + NC_("ocFORECAST_ETS_STA", "Period length"), + NC_("ocFORECAST_ETS_STA", "Number of Samples in Period (default 1); length of the seasonal pattern."), + NC_("ocFORECAST_ETS_STA", "Data completion"), + NC_("ocFORECAST_ETS_STA", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), + NC_("ocFORECAST_ETS_STA", "Aggregation"), + NC_("ocFORECAST_ETS_STA", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") }; // -=*# Resource for function FORECAST.ETS.STAT.MULT #*=- -const TranslateId SC_OPCODE_FORECAST_ETS_STM_ARY[] = +const TranslateId ocFORECAST_ETS_STM_ARY[] = { - NC_("SC_OPCODE_FORECAST_ETS_STM", "Returns statistical value(s) using multiplicative Exponential Smoothing algorithm."), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Values"), - NC_("SC_OPCODE_FORECAST_ETS_STM", "The data array from which you want to forecast."), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Timeline"), - NC_("SC_OPCODE_FORECAST_ETS_STM", "The date or numeric array; a consistent step between values is needed."), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Statistic type"), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Value (1-9) or array of values, indicating which statistic will be returned for the calculated forecast"), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Period length"), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Number of samples in period (default 1); length of the seasonal pattern."), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Data completion"), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Aggregation"), - NC_("SC_OPCODE_FORECAST_ETS_STM", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") + NC_("ocFORECAST_ETS_STM", "Returns statistical value(s) using multiplicative Exponential Smoothing algorithm."), + NC_("ocFORECAST_ETS_STM", "Values"), + NC_("ocFORECAST_ETS_STM", "The data array from which you want to forecast."), + NC_("ocFORECAST_ETS_STM", "Timeline"), + NC_("ocFORECAST_ETS_STM", "The date or numeric array; a consistent step between values is needed."), + NC_("ocFORECAST_ETS_STM", "Statistic type"), + NC_("ocFORECAST_ETS_STM", "Value (1-9) or array of values, indicating which statistic will be returned for the calculated forecast"), + NC_("ocFORECAST_ETS_STM", "Period length"), + NC_("ocFORECAST_ETS_STM", "Number of samples in period (default 1); length of the seasonal pattern."), + NC_("ocFORECAST_ETS_STM", "Data completion"), + NC_("ocFORECAST_ETS_STM", "Data completion (default 1); 0 treats missing points as zero, 1 interpolates."), + NC_("ocFORECAST_ETS_STM", "Aggregation"), + NC_("ocFORECAST_ETS_STM", "Aggregation (default 1 = AVERAGE); method to be used to aggregate identical (time) values.") }; // -=*# Resource for function FORECAST.LINEAR #*=- -const TranslateId SC_OPCODE_FORECAST_LIN_ARY[] = +const TranslateId ocFORECAST_LIN_ARY[] = { - NC_("SC_OPCODE_FORECAST_LIN", "Returns a value along a linear regression"), - NC_("SC_OPCODE_FORECAST_LIN", "Value"), - NC_("SC_OPCODE_FORECAST_LIN", "The X value for which the Y value on the regression linear is to be calculated."), - NC_("SC_OPCODE_FORECAST_LIN", "Data Y"), - NC_("SC_OPCODE_FORECAST_LIN", "The Y data array."), - NC_("SC_OPCODE_FORECAST_LIN", "Data X"), - NC_("SC_OPCODE_FORECAST_LIN", "The X data array.") + NC_("ocFORECAST_LIN", "Returns a value along a linear regression"), + NC_("ocFORECAST_LIN", "Value"), + NC_("ocFORECAST_LIN", "The X value for which the Y value on the regression linear is to be calculated."), + NC_("ocFORECAST_LIN", "Data Y"), + NC_("ocFORECAST_LIN", "The Y data array."), + NC_("ocFORECAST_LIN", "Data X"), + NC_("ocFORECAST_LIN", "The X data array.") }; // -=*# Resource for function ADDRESS #*=- -const TranslateId SC_OPCODE_ADDRESS_ARY[] = +const TranslateId ocADDRESS_ARY[] = { - NC_("SC_OPCODE_ADDRESS", "Returns the reference to a cell as text."), - NC_("SC_OPCODE_ADDRESS", "Row"), - NC_("SC_OPCODE_ADDRESS", "The row number of the cell."), - NC_("SC_OPCODE_ADDRESS", "Column"), - NC_("SC_OPCODE_ADDRESS", "The column number of the cell."), - NC_("SC_OPCODE_ADDRESS", "ABS"), - NC_("SC_OPCODE_ADDRESS", "Specifies whether absolute or relative referencing is to be used."), - NC_("SC_OPCODE_ADDRESS", "A1"), - NC_("SC_OPCODE_ADDRESS", "The reference style: 0 or FALSE means R1C1 style, any other value or omitted means A1 style."), - NC_("SC_OPCODE_ADDRESS", "Sheet"), - NC_("SC_OPCODE_ADDRESS", "The spreadsheet name of the cell reference.") + NC_("ocADDRESS", "Returns the reference to a cell as text."), + NC_("ocADDRESS", "Row"), + NC_("ocADDRESS", "The row number of the cell."), + NC_("ocADDRESS", "Column"), + NC_("ocADDRESS", "The column number of the cell."), + NC_("ocADDRESS", "ABS"), + NC_("ocADDRESS", "Specifies whether absolute or relative referencing is to be used."), + NC_("ocADDRESS", "A1"), + NC_("ocADDRESS", "The reference style: 0 or FALSE means R1C1 style, any other value or omitted means A1 style."), + NC_("ocADDRESS", "Sheet"), + NC_("ocADDRESS", "The spreadsheet name of the cell reference.") }; // -=*# Resource for function AREAS #*=- -const TranslateId SC_OPCODE_AREAS_ARY[] = +const TranslateId ocAREAS_ARY[] = { - NC_("SC_OPCODE_AREAS", "Returns the number of individual ranges that belong to a (multiple) range."), - NC_("SC_OPCODE_AREAS", "Reference"), - NC_("SC_OPCODE_AREAS", "The reference to a (multiple) range.") + NC_("ocAREAS", "Returns the number of individual ranges that belong to a (multiple) range."), + NC_("ocAREAS", "Reference"), + NC_("ocAREAS", "The reference to a (multiple) range.") }; // -=*# Resource for function CHOOSE #*=- -const TranslateId SC_OPCODE_CHOOSE_ARY[] = +const TranslateId ocCHOOSE_ARY[] = { - NC_("SC_OPCODE_CHOOSE", "Selects a value from a list of up to 30 value arguments."), - NC_("SC_OPCODE_CHOOSE", "Index"), - NC_("SC_OPCODE_CHOOSE", "The index of the value (1..30) selected."), - NC_("SC_OPCODE_CHOOSE", "Value "), - NC_("SC_OPCODE_CHOOSE", "Value 1, value 2,... The list of arguments from which a value is chosen.") + NC_("ocCHOOSE", "Selects a value from a list of up to 30 value arguments."), + NC_("ocCHOOSE", "Index"), + NC_("ocCHOOSE", "The index of the value (1..30) selected."), + NC_("ocCHOOSE", "Value "), + NC_("ocCHOOSE", "Value 1, value 2,... The list of arguments from which a value is chosen.") }; // -=*# Resource for function COLUMNS #*=- -const TranslateId SC_OPCODE_COLUMN_ARY[] = +const TranslateId ocCOLUMN_ARY[] = { - NC_("SC_OPCODE_COLUMN", "Returns the internal column number of a reference."), - NC_("SC_OPCODE_COLUMN", "Reference"), - NC_("SC_OPCODE_COLUMN", "The reference to a cell or a range.") + NC_("ocCOLUMN", "Returns the internal column number of a reference."), + NC_("ocCOLUMN", "Reference"), + NC_("ocCOLUMN", "The reference to a cell or a range.") }; // -=*# Resource for function ROW #*=- -const TranslateId SC_OPCODE_ROW_ARY[] = +const TranslateId ocROW_ARY[] = { - NC_("SC_OPCODE_ROW", "Defines the internal row number of a reference."), - NC_("SC_OPCODE_ROW", "Reference"), - NC_("SC_OPCODE_ROW", "The reference to a cell or a range.") + NC_("ocROW", "Defines the internal row number of a reference."), + NC_("ocROW", "Reference"), + NC_("ocROW", "The reference to a cell or a range.") }; // -=*# Resource for function SHEET #*=- -const TranslateId SC_OPCODE_SHEET_ARY[] = +const TranslateId ocSHEET_ARY[] = { - NC_("SC_OPCODE_SHEET", "Returns the internal sheet number of a reference or a string."), - NC_("SC_OPCODE_SHEET", "Reference"), - NC_("SC_OPCODE_SHEET", "The reference to a cell or a range or the character string of a sheet name.") + NC_("ocSHEET", "Returns the internal sheet number of a reference or a string."), + NC_("ocSHEET", "Reference"), + NC_("ocSHEET", "The reference to a cell or a range or the character string of a sheet name.") }; // -=*# Resource for function COLUMNS #*=- -const TranslateId SC_OPCODE_COLUMNS_ARY[] = +const TranslateId ocCOLUMNS_ARY[] = { - NC_("SC_OPCODE_COLUMNS", "Returns the number of columns in an array or reference."), - NC_("SC_OPCODE_COLUMNS", "Array"), - NC_("SC_OPCODE_COLUMNS", "The array (reference) for which the number of columns is to be determined.") + NC_("ocCOLUMNS", "Returns the number of columns in an array or reference."), + NC_("ocCOLUMNS", "Array"), + NC_("ocCOLUMNS", "The array (reference) for which the number of columns is to be determined.") }; // -=*# Resource for function ROWS #*=- -const TranslateId SC_OPCODE_ROWS_ARY[] = +const TranslateId ocROWS_ARY[] = { - NC_("SC_OPCODE_ROWS", "Returns the number of rows in a reference or array."), - NC_("SC_OPCODE_ROWS", "Array"), - NC_("SC_OPCODE_ROWS", "The array (reference) for which the number of rows is to be determined.") + NC_("ocROWS", "Returns the number of rows in a reference or array."), + NC_("ocROWS", "Array"), + NC_("ocROWS", "The array (reference) for which the number of rows is to be determined.") }; // -=*# Resource for function SHEETS #*=- -const TranslateId SC_OPCODE_SHEETS_ARY[] = +const TranslateId ocSHEETS_ARY[] = { - NC_("SC_OPCODE_SHEETS", "Returns the number of sheets of a given reference. If no parameter has been entered, the total number of sheets in the document is returned."), - NC_("SC_OPCODE_SHEETS", "Reference"), - NC_("SC_OPCODE_SHEETS", "The reference to a cell or a range.") + NC_("ocSHEETS", "Returns the number of sheets of a given reference. If no parameter has been entered, the total number of sheets in the document is returned."), + NC_("ocSHEETS", "Reference"), + NC_("ocSHEETS", "The reference to a cell or a range.") }; // -=*# Resource for function HLOOKUP #*=- -const TranslateId SC_OPCODE_H_LOOKUP_ARY[] = +const TranslateId ocH_LOOKUP_ARY[] = { - NC_("SC_OPCODE_H_LOOKUP", "Horizontal search and reference to the cells located below."), - NC_("SC_OPCODE_H_LOOKUP", "Search criterion"), - NC_("SC_OPCODE_H_LOOKUP", "The value to be found in the first row."), - NC_("SC_OPCODE_H_LOOKUP", "Array"), - NC_("SC_OPCODE_H_LOOKUP", "The array or the range for the reference."), - NC_("SC_OPCODE_H_LOOKUP", "Index"), - NC_("SC_OPCODE_H_LOOKUP", "The row index in the array."), - NC_("SC_OPCODE_H_LOOKUP", "Sorted range lookup"), - NC_("SC_OPCODE_H_LOOKUP", "If the value is TRUE or not given, the search row of the array represents a series of ranges, and must be sorted in ascending order.") + NC_("ocH_LOOKUP", "Horizontal search and reference to the cells located below."), + NC_("ocH_LOOKUP", "Search criterion"), + NC_("ocH_LOOKUP", "The value to be found in the first row."), + NC_("ocH_LOOKUP", "Array"), + NC_("ocH_LOOKUP", "The array or the range for the reference."), + NC_("ocH_LOOKUP", "Index"), + NC_("ocH_LOOKUP", "The row index in the array."), + NC_("ocH_LOOKUP", "Sorted range lookup"), + NC_("ocH_LOOKUP", "If the value is TRUE or not given, the search row of the array represents a series of ranges, and must be sorted in ascending order.") }; // -=*# Resource for function VLOOKUP #*=- -const TranslateId SC_OPCODE_V_LOOKUP_ARY[] = +const TranslateId ocV_LOOKUP_ARY[] = { - NC_("SC_OPCODE_V_LOOKUP", "Vertical search and reference to indicated cells."), - NC_("SC_OPCODE_V_LOOKUP", "Search criterion"), - NC_("SC_OPCODE_V_LOOKUP", "The value to be found in the first column."), - NC_("SC_OPCODE_V_LOOKUP", "Array"), - NC_("SC_OPCODE_V_LOOKUP", "The array or range for referencing."), - NC_("SC_OPCODE_V_LOOKUP", "Index"), - NC_("SC_OPCODE_V_LOOKUP", "Column index number in the array."), - NC_("SC_OPCODE_V_LOOKUP", "Sorted range lookup"), - NC_("SC_OPCODE_V_LOOKUP", "If the value is TRUE or not given, the search column of the array represents a series of ranges, and must be sorted in ascending order.") + NC_("ocV_LOOKUP", "Vertical search and reference to indicated cells."), + NC_("ocV_LOOKUP", "Search criterion"), + NC_("ocV_LOOKUP", "The value to be found in the first column."), + NC_("ocV_LOOKUP", "Array"), + NC_("ocV_LOOKUP", "The array or range for referencing."), + NC_("ocV_LOOKUP", "Index"), + NC_("ocV_LOOKUP", "Column index number in the array."), + NC_("ocV_LOOKUP", "Sorted range lookup"), + NC_("ocV_LOOKUP", "If the value is TRUE or not given, the search column of the array represents a series of ranges, and must be sorted in ascending order.") }; // -=*# Resource for function XLOOKUP #*=- -const TranslateId SC_OPCODE_X_LOOKUP_ARY[] = +const TranslateId ocX_LOOKUP_ARY[] = { - NC_("SC_OPCODE_X_LOOKUP", "Extended vertical search and reference to indicated cells."), - NC_("SC_OPCODE_X_LOOKUP", "Search criterion"), - NC_("SC_OPCODE_X_LOOKUP", "The value to be found in the first column."), - NC_("SC_OPCODE_X_LOOKUP", "Search Array"), - NC_("SC_OPCODE_X_LOOKUP", "The array or range to search."), - NC_("SC_OPCODE_X_LOOKUP", "Result Array"), - NC_("SC_OPCODE_X_LOOKUP", "The array or range to return."), - NC_("SC_OPCODE_X_LOOKUP", "Result if not found"), - NC_("SC_OPCODE_X_LOOKUP", "If given, return given text, otherwise return #N/A."), - NC_("SC_OPCODE_X_LOOKUP", "Match Mode"), - NC_("SC_OPCODE_X_LOOKUP", "0 - Exact match. Will return #N/A if no match. (default).\n-1 - Exact match or the next smaller item.\n1 - Exact match or the next larger item.\n2 - Wildcard match.\n3 - Regular expression match."), - NC_("SC_OPCODE_X_LOOKUP", "Search Mode"), - NC_("SC_OPCODE_X_LOOKUP", "1 - Search from the first value (default).\n-1 - Search from the last value (reverse).\n2 - Binary search values sorted in ascending order.\n-2 - Binary search values sorted in descending order.") + NC_("ocX_LOOKUP", "Extended vertical search and reference to indicated cells."), + NC_("ocX_LOOKUP", "Search criterion"), + NC_("ocX_LOOKUP", "The value to be found in the first column."), + NC_("ocX_LOOKUP", "Search Array"), + NC_("ocX_LOOKUP", "The array or range to search."), + NC_("ocX_LOOKUP", "Result Array"), + NC_("ocX_LOOKUP", "The array or range to return."), + NC_("ocX_LOOKUP", "Result if not found"), + NC_("ocX_LOOKUP", "If given, return given text, otherwise return #N/A."), + NC_("ocX_LOOKUP", "Match Mode"), + NC_("ocX_LOOKUP", "0 - Exact match. Will return #N/A if no match. (default).\n-1 - Exact match or the next smaller item.\n1 - Exact match or the next larger item.\n2 - Wildcard match.\n3 - Regular expression match."), + NC_("ocX_LOOKUP", "Search Mode"), + NC_("ocX_LOOKUP", "1 - Search from the first value (default).\n-1 - Search from the last value (reverse).\n2 - Binary search values sorted in ascending order.\n-2 - Binary search values sorted in descending order.") }; // -=*# Resource for function INDEX #*=- -const TranslateId SC_OPCODE_INDEX_ARY[] = +const TranslateId ocINDEX_ARY[] = { - NC_("SC_OPCODE_INDEX", "Returns a reference to a cell from a defined range."), - NC_("SC_OPCODE_INDEX", "Reference"), - NC_("SC_OPCODE_INDEX", "The reference to a (multiple) range."), - NC_("SC_OPCODE_INDEX", "Row"), - NC_("SC_OPCODE_INDEX", "The row in the range."), - NC_("SC_OPCODE_INDEX", "Column"), - NC_("SC_OPCODE_INDEX", "The column in the range."), - NC_("SC_OPCODE_INDEX", "Range"), - NC_("SC_OPCODE_INDEX", "The index of the subrange if referring to a multiple range.") + NC_("ocINDEX", "Returns a reference to a cell from a defined range."), + NC_("ocINDEX", "Reference"), + NC_("ocINDEX", "The reference to a (multiple) range."), + NC_("ocINDEX", "Row"), + NC_("ocINDEX", "The row in the range."), + NC_("ocINDEX", "Column"), + NC_("ocINDEX", "The column in the range."), + NC_("ocINDEX", "Range"), + NC_("ocINDEX", "The index of the subrange if referring to a multiple range.") }; // -=*# Resource for function INDIRECT #*=- -const TranslateId SC_OPCODE_INDIRECT_ARY[] = +const TranslateId ocINDIRECT_ARY[] = { - NC_("SC_OPCODE_INDIRECT", "Returns the contents of a cell that is referenced in text form."), - NC_("SC_OPCODE_INDIRECT", "Reference"), - NC_("SC_OPCODE_INDIRECT", "The cell whose contents are to be evaluated is to be referenced in text form (e.g. \"A1\")."), - NC_("SC_OPCODE_INDIRECT", "A1"), - NC_("SC_OPCODE_INDIRECT", "The reference style: 0 or FALSE means R1C1 style, any other value or omitted means A1 style.") + NC_("ocINDIRECT", "Returns the contents of a cell that is referenced in text form."), + NC_("ocINDIRECT", "Reference"), + NC_("ocINDIRECT", "The cell whose contents are to be evaluated is to be referenced in text form (e.g. \"A1\")."), + NC_("ocINDIRECT", "A1"), + NC_("ocINDIRECT", "The reference style: 0 or FALSE means R1C1 style, any other value or omitted means A1 style.") }; // -=*# Resource for function LOOKUP #*=- -const TranslateId SC_OPCODE_LOOKUP_ARY[] = +const TranslateId ocLOOKUP_ARY[] = { - NC_("SC_OPCODE_LOOKUP", "Determines a value in a vector by comparison to values in another vector."), - NC_("SC_OPCODE_LOOKUP", "Search criterion"), - NC_("SC_OPCODE_LOOKUP", "The value to be used for comparison."), - NC_("SC_OPCODE_LOOKUP", "Search vector"), - NC_("SC_OPCODE_LOOKUP", "The vector (row or column) in which to search."), - NC_("SC_OPCODE_LOOKUP", "Result vector"), - NC_("SC_OPCODE_LOOKUP", "The vector (row or range) from which the value is to be determined.") + NC_("ocLOOKUP", "Determines a value in a vector by comparison to values in another vector."), + NC_("ocLOOKUP", "Search criterion"), + NC_("ocLOOKUP", "The value to be used for comparison."), + NC_("ocLOOKUP", "Search vector"), + NC_("ocLOOKUP", "The vector (row or column) in which to search."), + NC_("ocLOOKUP", "Result vector"), + NC_("ocLOOKUP", "The vector (row or range) from which the value is to be determined.") }; // -=*# Resource for function MATCH #*=- -const TranslateId SC_OPCODE_MATCH_ARY[] = +const TranslateId ocMATCH_ARY[] = { - NC_("SC_OPCODE_MATCH", "Defines a position in an array after comparing values."), - NC_("SC_OPCODE_MATCH", "Search criterion"), - NC_("SC_OPCODE_MATCH", "The value to be used for comparison."), - NC_("SC_OPCODE_MATCH", "Lookup array"), - NC_("SC_OPCODE_MATCH", "The array (range) in which the search is made."), - NC_("SC_OPCODE_MATCH", "Type"), - NC_("SC_OPCODE_MATCH", "Type can take the value 1 (first column array ascending), 0 (exact match or wildcard or regular expression match) or -1 (first column array descending) and determines the criteria to be used for comparison purposes.") + NC_("ocMATCH", "Defines a position in an array after comparing values."), + NC_("ocMATCH", "Search criterion"), + NC_("ocMATCH", "The value to be used for comparison."), + NC_("ocMATCH", "Lookup array"), + NC_("ocMATCH", "The array (range) in which the search is made."), + NC_("ocMATCH", "Type"), + NC_("ocMATCH", "Type can take the value 1 (first column array ascending), 0 (exact match or wildcard or regular expression match) or -1 (first column array descending) and determines the criteria to be used for comparison purposes.") }; // -=*# Resource for function XMATCH #*=- -const TranslateId SC_OPCODE_X_MATCH_ARY[] = +const TranslateId ocX_MATCH_ARY[] = { - NC_("SC_OPCODE_X_MATCH", "Defines a relative position in an array or range of cells after comparing values."), - NC_("SC_OPCODE_X_MATCH", "Search criterion"), - NC_("SC_OPCODE_X_MATCH", "The value to be used for comparison."), - NC_("SC_OPCODE_X_MATCH", "Search Array"), - NC_("SC_OPCODE_X_MATCH", "The array or range to search."), - NC_("SC_OPCODE_X_MATCH", "Match Mode"), - NC_("SC_OPCODE_X_MATCH", "0 - Exact match. Will return #N/A if no match. (default).\n-1 - Exact match or the next smaller item.\n1 - Exact match or the next larger item.\n2 - Wildcard match.\n3 - Regular expression match."), - NC_("SC_OPCODE_X_MATCH", "Search Mode"), - NC_("SC_OPCODE_X_MATCH", "1 - Search from the first value (default).\n-1 - Search from the last value (reverse).\n2 - Binary search values sorted in ascending order.\n-2 - Binary search values sorted in descending order.") + NC_("ocX_MATCH", "Defines a relative position in an array or range of cells after comparing values."), + NC_("ocX_MATCH", "Search criterion"), + NC_("ocX_MATCH", "The value to be used for comparison."), + NC_("ocX_MATCH", "Search Array"), + NC_("ocX_MATCH", "The array or range to search."), + NC_("ocX_MATCH", "Match Mode"), + NC_("ocX_MATCH", "0 - Exact match. Will return #N/A if no match. (default).\n-1 - Exact match or the next smaller item.\n1 - Exact match or the next larger item.\n2 - Wildcard match.\n3 - Regular expression match."), + NC_("ocX_MATCH", "Search Mode"), + NC_("ocX_MATCH", "1 - Search from the first value (default).\n-1 - Search from the last value (reverse).\n2 - Binary search values sorted in ascending order.\n-2 - Binary search values sorted in descending order.") }; // -=*# Resource for function OFFSET #*=- -const TranslateId SC_OPCODE_OFFSET_ARY[] = +const TranslateId ocOFFSET_ARY[] = { - NC_("SC_OPCODE_OFFSET", "Returns a reference which has been moved in relation to the starting point."), - NC_("SC_OPCODE_OFFSET", "Reference"), - NC_("SC_OPCODE_OFFSET", "The reference (cell) from which to base the movement."), - NC_("SC_OPCODE_OFFSET", "Rows"), - NC_("SC_OPCODE_OFFSET", "The number of rows to be moved either up or down."), - NC_("SC_OPCODE_OFFSET", "Columns"), - NC_("SC_OPCODE_OFFSET", "The number of columns that are to be moved to the left or to the right."), - NC_("SC_OPCODE_OFFSET", "Height"), - NC_("SC_OPCODE_OFFSET", "The number of rows of the moved reference."), - NC_("SC_OPCODE_OFFSET", "Width"), - NC_("SC_OPCODE_OFFSET", "The number of columns in the moved reference.") + NC_("ocOFFSET", "Returns a reference which has been moved in relation to the starting point."), + NC_("ocOFFSET", "Reference"), + NC_("ocOFFSET", "The reference (cell) from which to base the movement."), + NC_("ocOFFSET", "Rows"), + NC_("ocOFFSET", "The number of rows to be moved either up or down."), + NC_("ocOFFSET", "Columns"), + NC_("ocOFFSET", "The number of columns that are to be moved to the left or to the right."), + NC_("ocOFFSET", "Height"), + NC_("ocOFFSET", "The number of rows of the moved reference."), + NC_("ocOFFSET", "Width"), + NC_("ocOFFSET", "The number of columns in the moved reference.") }; // -=*# Resource for function ERRORTYPE #*=- -const TranslateId SC_OPCODE_ERROR_TYPE_ARY[] = +const TranslateId ocERROR_TYPE_ARY[] = { - NC_("SC_OPCODE_ERROR_TYPE", "Returns a number corresponding to an error type"), - NC_("SC_OPCODE_ERROR_TYPE", "Reference"), - NC_("SC_OPCODE_ERROR_TYPE", "The reference (cell) in which the error occurred.") + NC_("ocERROR_TYPE", "Returns a number corresponding to an error type"), + NC_("ocERROR_TYPE", "Reference"), + NC_("ocERROR_TYPE", "The reference (cell) in which the error occurred.") }; // -=*# Resource for function ERROR.TYPE #*=- -const TranslateId SC_OPCODE_ERROR_TYPE_ODF_ARY[] = +const TranslateId ocERROR_TYPE_ODF_ARY[] = { - NC_("SC_OPCODE_ERROR_TYPE_ODF", "Returns a number corresponding to one of the error values or #N/A if no error exists"), - NC_("SC_OPCODE_ERROR_TYPE_ODF", "Expression"), - NC_("SC_OPCODE_ERROR_TYPE_ODF", "The error value whose identifying number you want to find. Can be the actual error value or a reference to a cell that you want to test.") + NC_("ocERROR_TYPE_ODF", "Returns a number corresponding to one of the error values or #N/A if no error exists"), + NC_("ocERROR_TYPE_ODF", "Expression"), + NC_("ocERROR_TYPE_ODF", "The error value whose identifying number you want to find. Can be the actual error value or a reference to a cell that you want to test.") }; // -=*# Resource for function STYLE #*=- -const TranslateId SC_OPCODE_STYLE_ARY[] = +const TranslateId ocSTYLE_ARY[] = { - NC_("SC_OPCODE_STYLE", "Applies a Style to the formula cell."), - NC_("SC_OPCODE_STYLE", "Style"), - NC_("SC_OPCODE_STYLE", "The name of the Style to be applied."), - NC_("SC_OPCODE_STYLE", "Time"), - NC_("SC_OPCODE_STYLE", "The time (in seconds) that the Style is to remain valid."), - NC_("SC_OPCODE_STYLE", "Style 2"), - NC_("SC_OPCODE_STYLE", "The style to be applied after time expires.") + NC_("ocSTYLE", "Applies a Style to the formula cell."), + NC_("ocSTYLE", "Style"), + NC_("ocSTYLE", "The name of the Style to be applied."), + NC_("ocSTYLE", "Time"), + NC_("ocSTYLE", "The time (in seconds) that the Style is to remain valid."), + NC_("ocSTYLE", "Style 2"), + NC_("ocSTYLE", "The style to be applied after time expires.") }; // -=*# Resource for function DDE #*=- -const TranslateId SC_OPCODE_DDE_ARY[] = +const TranslateId ocDDE_ARY[] = { - NC_("SC_OPCODE_DDE", "Result of a DDE link."), - NC_("SC_OPCODE_DDE", "Server"), - NC_("SC_OPCODE_DDE", "The name of the server application."), - NC_("SC_OPCODE_DDE", "Topic/file"), - NC_("SC_OPCODE_DDE", "The topic or name of the file."), - NC_("SC_OPCODE_DDE", "Item/range"), - NC_("SC_OPCODE_DDE", "The item or range from which data is to be taken."), - NC_("SC_OPCODE_DDE", "Mode"), - NC_("SC_OPCODE_DDE", "Defines how data is to be converted to numbers.") + NC_("ocDDE", "Result of a DDE link."), + NC_("ocDDE", "Server"), + NC_("ocDDE", "The name of the server application."), + NC_("ocDDE", "Topic/file"), + NC_("ocDDE", "The topic or name of the file."), + NC_("ocDDE", "Item/range"), + NC_("ocDDE", "The item or range from which data is to be taken."), + NC_("ocDDE", "Mode"), + NC_("ocDDE", "Defines how data is to be converted to numbers.") }; // -=*# Resource for function HYPERLINK #*=- -const TranslateId SC_OPCODE_HYPERLINK_ARY[] = +const TranslateId ocHYPERLINK_ARY[] = { - NC_("SC_OPCODE_HYPERLINK", "Construct a Hyperlink."), - NC_("SC_OPCODE_HYPERLINK", "URL"), - NC_("SC_OPCODE_HYPERLINK", "The clickable URL."), - NC_("SC_OPCODE_HYPERLINK", "Cell text"), - NC_("SC_OPCODE_HYPERLINK", "The cell text to be displayed.") + NC_("ocHYPERLINK", "Construct a Hyperlink."), + NC_("ocHYPERLINK", "URL"), + NC_("ocHYPERLINK", "The clickable URL."), + NC_("ocHYPERLINK", "Cell text"), + NC_("ocHYPERLINK", "The cell text to be displayed.") }; // -=*# Resource for function GETPIVOTDATA #*=- -const TranslateId SC_OPCODE_GET_PIVOT_DATA_ARY[] = +const TranslateId ocGET_PIVOT_DATA_ARY[] = { - NC_("SC_OPCODE_GET_PIVOT_DATA", "Extracts value(s) from a pivot table."), - NC_("SC_OPCODE_GET_PIVOT_DATA", "Data field"), - NC_("SC_OPCODE_GET_PIVOT_DATA", "The name of the pivot table field to extract."), - NC_("SC_OPCODE_GET_PIVOT_DATA", "Pivot table"), - NC_("SC_OPCODE_GET_PIVOT_DATA", "A reference to a cell or range in the pivot table."), - NC_("SC_OPCODE_GET_PIVOT_DATA", "Field name / item"), - NC_("SC_OPCODE_GET_PIVOT_DATA", "Field name/value pair to filter the target data.") + NC_("ocGET_PIVOT_DATA", "Extracts value(s) from a pivot table."), + NC_("ocGET_PIVOT_DATA", "Data field"), + NC_("ocGET_PIVOT_DATA", "The name of the pivot table field to extract."), + NC_("ocGET_PIVOT_DATA", "Pivot table"), + NC_("ocGET_PIVOT_DATA", "A reference to a cell or range in the pivot table."), + NC_("ocGET_PIVOT_DATA", "Field name / item"), + NC_("ocGET_PIVOT_DATA", "Field name/value pair to filter the target data.") }; // -=*# Resource for function BAHTTEXT #*=- -const TranslateId SC_OPCODE_BAHTTEXT_ARY[] = +const TranslateId ocBAHTTEXT_ARY[] = { - NC_("SC_OPCODE_BAHTTEXT", "Converts a number to text (Baht)."), - NC_("SC_OPCODE_BAHTTEXT", "Number"), - NC_("SC_OPCODE_BAHTTEXT", "The number to convert.") + NC_("ocBAHTTEXT", "Converts a number to text (Baht)."), + NC_("ocBAHTTEXT", "Number"), + NC_("ocBAHTTEXT", "The number to convert.") }; // -=*# Resource for function JIS #*=- -const TranslateId SC_OPCODE_JIS_ARY[] = +const TranslateId ocJIS_ARY[] = { - NC_("SC_OPCODE_JIS", "Converts half-width ASCII and katakana characters to full-width."), - NC_("SC_OPCODE_JIS", "Text"), - NC_("SC_OPCODE_JIS", "The text to convert.") + NC_("ocJIS", "Converts half-width ASCII and katakana characters to full-width."), + NC_("ocJIS", "Text"), + NC_("ocJIS", "The text to convert.") }; // -=*# Resource for function ASC #*=- -const TranslateId SC_OPCODE_ASC_ARY[] = +const TranslateId ocASC_ARY[] = { - NC_("SC_OPCODE_ASC", "Converts full-width ASCII and katakana characters to half-width."), - NC_("SC_OPCODE_ASC", "Text"), - NC_("SC_OPCODE_ASC", "The text to convert.") + NC_("ocASC", "Converts full-width ASCII and katakana characters to half-width."), + NC_("ocASC", "Text"), + NC_("ocASC", "The text to convert.") }; // -=*# Resource for function CODE #*=- -const TranslateId SC_OPCODE_CODE_ARY[] = +const TranslateId ocCODE_ARY[] = { - NC_("SC_OPCODE_CODE", "Returns a numeric code for the first character in a text string."), - NC_("SC_OPCODE_CODE", "Text"), - NC_("SC_OPCODE_CODE", "This is the text for which the code of the first character is to be found.") + NC_("ocCODE", "Returns a numeric code for the first character in a text string."), + NC_("ocCODE", "Text"), + NC_("ocCODE", "This is the text for which the code of the first character is to be found.") }; // -=*# Resource for function DOLLAR #*=- -const TranslateId SC_OPCODE_CURRENCY_ARY[] = +const TranslateId ocCURRENCY_ARY[] = { - NC_("SC_OPCODE_CURRENCY", "Converts a number to text in currency format."), - NC_("SC_OPCODE_CURRENCY", "Value"), - NC_("SC_OPCODE_CURRENCY", "Value is a number, a reference to a cell containing a number or a formula that results in a number."), - NC_("SC_OPCODE_CURRENCY", "Decimals"), - NC_("SC_OPCODE_CURRENCY", "Decimal places. Denotes the number of digits to the right of the decimal point.") + NC_("ocCURRENCY", "Converts a number to text in currency format."), + NC_("ocCURRENCY", "Value"), + NC_("ocCURRENCY", "Value is a number, a reference to a cell containing a number or a formula that results in a number."), + NC_("ocCURRENCY", "Decimals"), + NC_("ocCURRENCY", "Decimal places. Denotes the number of digits to the right of the decimal point.") }; // -=*# Resource for function CHAR #*=- -const TranslateId SC_OPCODE_CHAR_ARY[] = +const TranslateId ocCHAR_ARY[] = { - NC_("SC_OPCODE_CHAR", "Converts a code number into a character or letter."), - NC_("SC_OPCODE_CHAR", "Number"), - NC_("SC_OPCODE_CHAR", "The code value for the character.") + NC_("ocCHAR", "Converts a code number into a character or letter."), + NC_("ocCHAR", "Number"), + NC_("ocCHAR", "The code value for the character.") }; // -=*# Resource for function CLEAN #*=- -const TranslateId SC_OPCODE_CLEAN_ARY[] = +const TranslateId ocCLEAN_ARY[] = { - NC_("SC_OPCODE_CLEAN", "Removes all nonprintable characters from text."), - NC_("SC_OPCODE_CLEAN", "Text"), - NC_("SC_OPCODE_CLEAN", "The text from which nonprintable characters are to be removed.") + NC_("ocCLEAN", "Removes all nonprintable characters from text."), + NC_("ocCLEAN", "Text"), + NC_("ocCLEAN", "The text from which nonprintable characters are to be removed.") }; // -=*# Resource for function CONCATENATE #*=- -const TranslateId SC_OPCODE_CONCAT_ARY[] = +const TranslateId ocCONCAT_ARY[] = { - NC_("SC_OPCODE_CONCAT", "Combines several text items into one."), - NC_("SC_OPCODE_CONCAT", "Text"), - NC_("SC_OPCODE_CONCAT", "Text for the concatenation.") + NC_("ocCONCAT", "Combines several text items into one."), + NC_("ocCONCAT", "Text"), + NC_("ocCONCAT", "Text for the concatenation.") }; // -=*# Resource for function CONCAT #*=- -const TranslateId SC_OPCODE_CONCAT_MS_ARY[] = +const TranslateId ocCONCAT_MS_ARY[] = { - NC_("SC_OPCODE_CONCAT_MS", "Combines several text items into one, accepts cell ranges as arguments."), - NC_("SC_OPCODE_CONCAT_MS", "Text"), - NC_("SC_OPCODE_CONCAT_MS", "Text and/or cell ranges for the concatenation.") + NC_("ocCONCAT_MS", "Combines several text items into one, accepts cell ranges as arguments."), + NC_("ocCONCAT_MS", "Text"), + NC_("ocCONCAT_MS", "Text and/or cell ranges for the concatenation.") }; // -=*# Resource for function TEXTJOIN #*=- -const TranslateId SC_OPCODE_TEXTJOIN_MS_ARY[] = +const TranslateId ocTEXTJOIN_MS_ARY[] = { - NC_("SC_OPCODE_TEXTJOIN_MS", "Combines several text items into one, accepts cell ranges as arguments. Uses delimiter between items."), - NC_("SC_OPCODE_TEXTJOIN_MS", "Delimiter"), - NC_("SC_OPCODE_TEXTJOIN_MS", "Text string to be used as delimiter."), - NC_("SC_OPCODE_TEXTJOIN_MS", "Skip empty cells"), - NC_("SC_OPCODE_TEXTJOIN_MS", "If TRUE, empty cells will be ignored."), - NC_("SC_OPCODE_TEXTJOIN_MS", "Text"), - NC_("SC_OPCODE_TEXTJOIN_MS", "Text and/or cell ranges for the concatenation.") + NC_("ocTEXTJOIN_MS", "Combines several text items into one, accepts cell ranges as arguments. Uses delimiter between items."), + NC_("ocTEXTJOIN_MS", "Delimiter"), + NC_("ocTEXTJOIN_MS", "Text string to be used as delimiter."), + NC_("ocTEXTJOIN_MS", "Skip empty cells"), + NC_("ocTEXTJOIN_MS", "If TRUE, empty cells will be ignored."), + NC_("ocTEXTJOIN_MS", "Text"), + NC_("ocTEXTJOIN_MS", "Text and/or cell ranges for the concatenation.") }; // -=*# Resource for function IFS #*=- -const TranslateId SC_OPCODE_IFS_MS_ARY[] = +const TranslateId ocIFS_MS_ARY[] = { - NC_("SC_OPCODE_IFS_MS", "Checks 1 or more conditions and returns a value corresponding to the first true condition."), - NC_("SC_OPCODE_IFS_MS", "Test"), - NC_("SC_OPCODE_IFS_MS", "Any value or expression which can be either TRUE or FALSE."), - NC_("SC_OPCODE_IFS_MS", "Result"), - NC_("SC_OPCODE_IFS_MS", "The result of the function if test is TRUE.") + NC_("ocIFS_MS", "Checks 1 or more conditions and returns a value corresponding to the first true condition."), + NC_("ocIFS_MS", "Test"), + NC_("ocIFS_MS", "Any value or expression which can be either TRUE or FALSE."), + NC_("ocIFS_MS", "Result"), + NC_("ocIFS_MS", "The result of the function if test is TRUE.") }; // -=*# Resource for function SWITCH #*=- -const TranslateId SC_OPCODE_SWITCH_MS_ARY[] = +const TranslateId ocSWITCH_MS_ARY[] = { - NC_("SC_OPCODE_SWITCH_MS", "Compares expression against list of value/result pairs, and returns result for first value that matches the expression. If expression does not match any value, a default result is returned, if it is placed as final item in parameter list without a value."), - NC_("SC_OPCODE_SWITCH_MS", "Expression"), - NC_("SC_OPCODE_SWITCH_MS", "Value to be compared against value1…valueN (N ≤ 127)"), - NC_("SC_OPCODE_SWITCH_MS", "Value"), - NC_("SC_OPCODE_SWITCH_MS", "Value to compare against expression. If no result is given, then value is returned as default result."), - NC_("SC_OPCODE_SWITCH_MS", "Result"), - NC_("SC_OPCODE_SWITCH_MS", "Value to return when corresponding value argument matches expression.") + NC_("ocSWITCH_MS", "Compares expression against list of value/result pairs, and returns result for first value that matches the expression. If expression does not match any value, a default result is returned, if it is placed as final item in parameter list without a value."), + NC_("ocSWITCH_MS", "Expression"), + NC_("ocSWITCH_MS", "Value to be compared against value1…valueN (N ≤ 127)"), + NC_("ocSWITCH_MS", "Value"), + NC_("ocSWITCH_MS", "Value to compare against expression. If no result is given, then value is returned as default result."), + NC_("ocSWITCH_MS", "Result"), + NC_("ocSWITCH_MS", "Value to return when corresponding value argument matches expression.") }; -const TranslateId SC_OPCODE_MINIFS_MS_ARY[] = +const TranslateId ocMINIFS_MS_ARY[] = { - NC_("SC_OPCODE_MINIFS_MS", "Returns the minimum value in a range that meet multiple criteria in multiple ranges."), - NC_("SC_OPCODE_MINIFS_MS", "Min range"), - NC_("SC_OPCODE_MINIFS_MS", "The range from which the minimum will be determined."), - NC_("SC_OPCODE_MINIFS_MS", "Range "), - NC_("SC_OPCODE_MINIFS_MS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), - NC_("SC_OPCODE_MINIFS_MS", "Criteria "), - NC_("SC_OPCODE_MINIFS_MS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") + NC_("ocMINIFS_MS", "Returns the minimum value in a range that meet multiple criteria in multiple ranges."), + NC_("ocMINIFS_MS", "Min range"), + NC_("ocMINIFS_MS", "The range from which the minimum will be determined."), + NC_("ocMINIFS_MS", "Range "), + NC_("ocMINIFS_MS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), + NC_("ocMINIFS_MS", "Criteria "), + NC_("ocMINIFS_MS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") }; -const TranslateId SC_OPCODE_MAXIFS_MS_ARY[] = +const TranslateId ocMAXIFS_MS_ARY[] = { - NC_("SC_OPCODE_MAXIFS_MS", "Returns the maximum value in a range that meet multiple criteria in multiple ranges."), - NC_("SC_OPCODE_MAXIFS_MS", "Max range"), - NC_("SC_OPCODE_MAXIFS_MS", "The range from which the maximum will be determined."), - NC_("SC_OPCODE_MAXIFS_MS", "Range "), - NC_("SC_OPCODE_MAXIFS_MS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), - NC_("SC_OPCODE_MAXIFS_MS", "Criteria "), - NC_("SC_OPCODE_MAXIFS_MS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") + NC_("ocMAXIFS_MS", "Returns the maximum value in a range that meet multiple criteria in multiple ranges."), + NC_("ocMAXIFS_MS", "Max range"), + NC_("ocMAXIFS_MS", "The range from which the maximum will be determined."), + NC_("ocMAXIFS_MS", "Range "), + NC_("ocMAXIFS_MS", "Range 1, range 2,... are the ranges to be evaluated by the criteria given."), + NC_("ocMAXIFS_MS", "Criteria "), + NC_("ocMAXIFS_MS", "Criteria 1, criteria 2,... are the criteria to be applied to the ranges given.") }; // -=*# Resource for function EXACT #*=- -const TranslateId SC_OPCODE_EXACT_ARY[] = +const TranslateId ocEXACT_ARY[] = { - NC_("SC_OPCODE_EXACT", "Specifies whether two texts are identical."), - NC_("SC_OPCODE_EXACT", "Text 1"), - NC_("SC_OPCODE_EXACT", "The first text to be used for comparing texts."), - NC_("SC_OPCODE_EXACT", "Text 2"), - NC_("SC_OPCODE_EXACT", "The second text for comparing texts.") + NC_("ocEXACT", "Specifies whether two texts are identical."), + NC_("ocEXACT", "Text 1"), + NC_("ocEXACT", "The first text to be used for comparing texts."), + NC_("ocEXACT", "Text 2"), + NC_("ocEXACT", "The second text for comparing texts.") }; // -=*# Resource for function FIND #*=- -const TranslateId SC_OPCODE_FIND_ARY[] = +const TranslateId ocFIND_ARY[] = { - NC_("SC_OPCODE_FIND", "Looks for a string of text within another (case sensitive)"), - NC_("SC_OPCODE_FIND", "Find text"), - NC_("SC_OPCODE_FIND", "The text to be found."), - NC_("SC_OPCODE_FIND", "Text"), - NC_("SC_OPCODE_FIND", "The text in which a search is to be made."), - NC_("SC_OPCODE_FIND", "Position"), - NC_("SC_OPCODE_FIND", "The position in the text from which the search starts.") + NC_("ocFIND", "Looks for a string of text within another (case sensitive)"), + NC_("ocFIND", "Find text"), + NC_("ocFIND", "The text to be found."), + NC_("ocFIND", "Text"), + NC_("ocFIND", "The text in which a search is to be made."), + NC_("ocFIND", "Position"), + NC_("ocFIND", "The position in the text from which the search starts.") }; // -=*# Resource for function SEARCH #*=- -const TranslateId SC_OPCODE_SEARCH_ARY[] = +const TranslateId ocSEARCH_ARY[] = { - NC_("SC_OPCODE_SEARCH", "Looks for one text value within another (not case-sensitive)."), - NC_("SC_OPCODE_SEARCH", "Find text"), - NC_("SC_OPCODE_SEARCH", "The text to be found."), - NC_("SC_OPCODE_SEARCH", "Text"), - NC_("SC_OPCODE_SEARCH", "The text in which a search is to be made."), - NC_("SC_OPCODE_SEARCH", "Position"), - NC_("SC_OPCODE_SEARCH", "The position in the text where the search is started.") + NC_("ocSEARCH", "Looks for one text value within another (not case-sensitive)."), + NC_("ocSEARCH", "Find text"), + NC_("ocSEARCH", "The text to be found."), + NC_("ocSEARCH", "Text"), + NC_("ocSEARCH", "The text in which a search is to be made."), + NC_("ocSEARCH", "Position"), + NC_("ocSEARCH", "The position in the text where the search is started.") }; // -=*# Resource for function TRIM #*=- -const TranslateId SC_OPCODE_TRIM_ARY[] = +const TranslateId ocTRIM_ARY[] = { - NC_("SC_OPCODE_TRIM", "Removes extra spaces from text."), - NC_("SC_OPCODE_TRIM", "Text"), - NC_("SC_OPCODE_TRIM", "The text in which extra spaces between words are to be deleted.") + NC_("ocTRIM", "Removes extra spaces from text."), + NC_("ocTRIM", "Text"), + NC_("ocTRIM", "The text in which extra spaces between words are to be deleted.") }; // -=*# Resource for function PROPER #*=- -const TranslateId SC_OPCODE_PROPER_ARY[] = +const TranslateId ocPROPER_ARY[] = { - NC_("SC_OPCODE_PROPER", "Capitalizes the first letter in all words."), - NC_("SC_OPCODE_PROPER", "Text"), - NC_("SC_OPCODE_PROPER", "The text in which the beginning of words are to be replaced by capital letters.") + NC_("ocPROPER", "Capitalizes the first letter in all words."), + NC_("ocPROPER", "Text"), + NC_("ocPROPER", "The text in which the beginning of words are to be replaced by capital letters.") }; // -=*# Resource for function UPPER #*=- -const TranslateId SC_OPCODE_UPPER_ARY[] = +const TranslateId ocUPPER_ARY[] = { - NC_("SC_OPCODE_UPPER", "Converts text to uppercase."), - NC_("SC_OPCODE_UPPER", "Text"), - NC_("SC_OPCODE_UPPER", "The text in which lower case letters are to be converted to capitals.") + NC_("ocUPPER", "Converts text to uppercase."), + NC_("ocUPPER", "Text"), + NC_("ocUPPER", "The text in which lower case letters are to be converted to capitals.") }; // -=*# Resource for function LOWER #*=- -const TranslateId SC_OPCODE_LOWER_ARY[] = +const TranslateId ocLOWER_ARY[] = { - NC_("SC_OPCODE_LOWER", "Converts text to lowercase."), - NC_("SC_OPCODE_LOWER", "Text"), - NC_("SC_OPCODE_LOWER", "The text in which capitals are converted to lower case letters.") + NC_("ocLOWER", "Converts text to lowercase."), + NC_("ocLOWER", "Text"), + NC_("ocLOWER", "The text in which capitals are converted to lower case letters.") }; // -=*# Resource for function VALUE #*=- -const TranslateId SC_OPCODE_VALUE_ARY[] = +const TranslateId ocVALUE_ARY[] = { - NC_("SC_OPCODE_VALUE", "Converts text to a number."), - NC_("SC_OPCODE_VALUE", "Text"), - NC_("SC_OPCODE_VALUE", "The text to be converted to a number.") + NC_("ocVALUE", "Converts text to a number."), + NC_("ocVALUE", "Text"), + NC_("ocVALUE", "The text to be converted to a number.") }; // -=*# Resource for function TEXT #*=- -const TranslateId SC_OPCODE_TEXT_ARY[] = +const TranslateId ocTEXT_ARY[] = { - NC_("SC_OPCODE_TEXT", "Converts a number to text according to a given format."), - NC_("SC_OPCODE_TEXT", "Number"), - NC_("SC_OPCODE_TEXT", "The numeric value to be converted."), - NC_("SC_OPCODE_TEXT", "Format"), - NC_("SC_OPCODE_TEXT", "The text that describes the format.") + NC_("ocTEXT", "Converts a number to text according to a given format."), + NC_("ocTEXT", "Number"), + NC_("ocTEXT", "The numeric value to be converted."), + NC_("ocTEXT", "Format"), + NC_("ocTEXT", "The text that describes the format.") }; // -=*# Resource for function T #*=- -const TranslateId SC_OPCODE_T_ARY[] = +const TranslateId ocT_ARY[] = { - NC_("SC_OPCODE_T", "Returns a value if it is text, otherwise an empty string."), - NC_("SC_OPCODE_T", "Value"), - NC_("SC_OPCODE_T", "The value to be checked and returned if it is text.") + NC_("ocT", "Returns a value if it is text, otherwise an empty string."), + NC_("ocT", "Value"), + NC_("ocT", "The value to be checked and returned if it is text.") }; // -=*# Resource for function REPLACE #*=- -const TranslateId SC_OPCODE_REPLACE_ARY[] = +const TranslateId ocREPLACE_ARY[] = { - NC_("SC_OPCODE_REPLACE", "Replaces characters within a text string with a different text string."), - NC_("SC_OPCODE_REPLACE", "Text"), - NC_("SC_OPCODE_REPLACE", "The text in which some characters are to be replaced."), - NC_("SC_OPCODE_REPLACE", "Position"), - NC_("SC_OPCODE_REPLACE", "The character position from which text is to be replaced."), - NC_("SC_OPCODE_REPLACE", "Length"), - NC_("SC_OPCODE_REPLACE", "The number of characters to be replaced."), - NC_("SC_OPCODE_REPLACE", "New text"), - NC_("SC_OPCODE_REPLACE", "The text to be inserted.") + NC_("ocREPLACE", "Replaces characters within a text string with a different text string."), + NC_("ocREPLACE", "Text"), + NC_("ocREPLACE", "The text in which some characters are to be replaced."), + NC_("ocREPLACE", "Position"), + NC_("ocREPLACE", "The character position from which text is to be replaced."), + NC_("ocREPLACE", "Length"), + NC_("ocREPLACE", "The number of characters to be replaced."), + NC_("ocREPLACE", "New text"), + NC_("ocREPLACE", "The text to be inserted.") }; // -=*# Resource for function FIXED #*=- -const TranslateId SC_OPCODE_FIXED_ARY[] = +const TranslateId ocFIXED_ARY[] = { - NC_("SC_OPCODE_FIXED", "Formats a number with a fixed number of places after the decimal point and thousands separator."), - NC_("SC_OPCODE_FIXED", "Number"), - NC_("SC_OPCODE_FIXED", "The number to be formatted."), - NC_("SC_OPCODE_FIXED", "Decimals"), - NC_("SC_OPCODE_FIXED", "Decimal places. The number of fixed decimal places that are to be displayed. Default 2."), - NC_("SC_OPCODE_FIXED", "No thousands separators"), - NC_("SC_OPCODE_FIXED", "Thousands separator. If 0 or omitted the locale group separator is used else the separator is suppressed.") + NC_("ocFIXED", "Formats a number with a fixed number of places after the decimal point and thousands separator."), + NC_("ocFIXED", "Number"), + NC_("ocFIXED", "The number to be formatted."), + NC_("ocFIXED", "Decimals"), + NC_("ocFIXED", "Decimal places. The number of fixed decimal places that are to be displayed. Default 2."), + NC_("ocFIXED", "No thousands separators"), + NC_("ocFIXED", "Thousands separator. If 0 or omitted the locale group separator is used else the separator is suppressed.") }; // -=*# Resource for function LEN #*=- -const TranslateId SC_OPCODE_LEN_ARY[] = +const TranslateId ocLEN_ARY[] = { - NC_("SC_OPCODE_LEN", "Calculates length of a text string."), - NC_("SC_OPCODE_LEN", "Text"), - NC_("SC_OPCODE_LEN", "The text in which the length is to be determined.") + NC_("ocLEN", "Calculates length of a text string."), + NC_("ocLEN", "Text"), + NC_("ocLEN", "The text in which the length is to be determined.") }; // -=*# Resource for function LEFT #*=- -const TranslateId SC_OPCODE_LEFT_ARY[] = +const TranslateId ocLEFT_ARY[] = { - NC_("SC_OPCODE_LEFT", "Returns the first character or characters of a text."), - NC_("SC_OPCODE_LEFT", "Text"), - NC_("SC_OPCODE_LEFT", "The text where the initial partial words are to be determined."), - NC_("SC_OPCODE_LEFT", "Number"), - NC_("SC_OPCODE_LEFT", "The number of characters for the start text.") + NC_("ocLEFT", "Returns the first character or characters of a text."), + NC_("ocLEFT", "Text"), + NC_("ocLEFT", "The text where the initial partial words are to be determined."), + NC_("ocLEFT", "Number"), + NC_("ocLEFT", "The number of characters for the start text.") }; // -=*# Resource for function RIGHT #*=- -const TranslateId SC_OPCODE_RIGHT_ARY[] = +const TranslateId ocRIGHT_ARY[] = { - NC_("SC_OPCODE_RIGHT", "Returns the last character or characters of a text."), - NC_("SC_OPCODE_RIGHT", "Text"), - NC_("SC_OPCODE_RIGHT", "The text in which the end partial words are to be determined."), - NC_("SC_OPCODE_RIGHT", "Number"), - NC_("SC_OPCODE_RIGHT", "The number of characters for the end text.") + NC_("ocRIGHT", "Returns the last character or characters of a text."), + NC_("ocRIGHT", "Text"), + NC_("ocRIGHT", "The text in which the end partial words are to be determined."), + NC_("ocRIGHT", "Number"), + NC_("ocRIGHT", "The number of characters for the end text.") }; // -=*# Resource for function MID #*=- -const TranslateId SC_OPCODE_MID_ARY[] = +const TranslateId ocMID_ARY[] = { - NC_("SC_OPCODE_MID", "Returns a partial text string of a text."), - NC_("SC_OPCODE_MID", "Text"), - NC_("SC_OPCODE_MID", "The text in which partial words are to be determined."), - NC_("SC_OPCODE_MID", "Start"), - NC_("SC_OPCODE_MID", "The position from which the part word is to be determined."), - NC_("SC_OPCODE_MID", "Number"), - NC_("SC_OPCODE_MID", "The number of characters for the text.") + NC_("ocMID", "Returns a partial text string of a text."), + NC_("ocMID", "Text"), + NC_("ocMID", "The text in which partial words are to be determined."), + NC_("ocMID", "Start"), + NC_("ocMID", "The position from which the part word is to be determined."), + NC_("ocMID", "Number"), + NC_("ocMID", "The number of characters for the text.") }; // -=*# Resource for function REPT #*=- -const TranslateId SC_OPCODE_REPT_ARY[] = +const TranslateId ocREPT_ARY[] = { - NC_("SC_OPCODE_REPT", "Repeats text a given number of times."), - NC_("SC_OPCODE_REPT", "Text"), - NC_("SC_OPCODE_REPT", "The text to be repeated."), - NC_("SC_OPCODE_REPT", "Number"), - NC_("SC_OPCODE_REPT", "The number of times the text is to be repeated.") + NC_("ocREPT", "Repeats text a given number of times."), + NC_("ocREPT", "Text"), + NC_("ocREPT", "The text to be repeated."), + NC_("ocREPT", "Number"), + NC_("ocREPT", "The number of times the text is to be repeated.") }; // -=*# Resource for function SUBSTITUTE #*=- -const TranslateId SC_OPCODE_SUBSTITUTE_ARY[] = +const TranslateId ocSUBSTITUTE_ARY[] = { - NC_("SC_OPCODE_SUBSTITUTE", "Substitutes new text for old text in a string."), - NC_("SC_OPCODE_SUBSTITUTE", "Text"), - NC_("SC_OPCODE_SUBSTITUTE", "The text in which partial words are to be replaced."), - NC_("SC_OPCODE_SUBSTITUTE", "Search text"), - NC_("SC_OPCODE_SUBSTITUTE", "The partial string to be (repeatedly) replaced."), - NC_("SC_OPCODE_SUBSTITUTE", "New text"), - NC_("SC_OPCODE_SUBSTITUTE", "The text which is to replace the text string."), - NC_("SC_OPCODE_SUBSTITUTE", "Occurrence"), - NC_("SC_OPCODE_SUBSTITUTE", "Which occurrence of the old text is to be replaced.") + NC_("ocSUBSTITUTE", "Substitutes new text for old text in a string."), + NC_("ocSUBSTITUTE", "Text"), + NC_("ocSUBSTITUTE", "The text in which partial words are to be replaced."), + NC_("ocSUBSTITUTE", "Search text"), + NC_("ocSUBSTITUTE", "The partial string to be (repeatedly) replaced."), + NC_("ocSUBSTITUTE", "New text"), + NC_("ocSUBSTITUTE", "The text which is to replace the text string."), + NC_("ocSUBSTITUTE", "Occurrence"), + NC_("ocSUBSTITUTE", "Which occurrence of the old text is to be replaced.") }; // -=*# Resource for function REGEX #*=- -const TranslateId SC_OPCODE_REGEX_ARY[] = +const TranslateId ocREGEX_ARY[] = { - NC_("SC_OPCODE_REGEX", "Matches and extracts or optionally replaces text using regular expressions."), - NC_("SC_OPCODE_REGEX", "Text"), - NC_("SC_OPCODE_REGEX", "The text to be operated on."), - NC_("SC_OPCODE_REGEX", "Expression"), - NC_("SC_OPCODE_REGEX", "The regular expression pattern to be matched."), - NC_("SC_OPCODE_REGEX", "Replacement"), - NC_("SC_OPCODE_REGEX", "The replacement text and references to capture groups."), - NC_("SC_OPCODE_REGEX", "Flags or Occurrence"), - NC_("SC_OPCODE_REGEX", "Text specifying option flags, \"g\" for global replacement. Or number of occurrence to match or replace.") + NC_("ocREGEX", "Matches and extracts or optionally replaces text using regular expressions."), + NC_("ocREGEX", "Text"), + NC_("ocREGEX", "The text to be operated on."), + NC_("ocREGEX", "Expression"), + NC_("ocREGEX", "The regular expression pattern to be matched."), + NC_("ocREGEX", "Replacement"), + NC_("ocREGEX", "The replacement text and references to capture groups."), + NC_("ocREGEX", "Flags or Occurrence"), + NC_("ocREGEX", "Text specifying option flags, \"g\" for global replacement. Or number of occurrence to match or replace.") }; // -=*# Resource for function BASE #*=- -const TranslateId SC_OPCODE_BASE_ARY[] = +const TranslateId ocBASE_ARY[] = { - NC_("SC_OPCODE_BASE", "Converts a positive integer to text from a number system to the base defined."), - NC_("SC_OPCODE_BASE", "Number"), - NC_("SC_OPCODE_BASE", "The number to be converted."), - NC_("SC_OPCODE_BASE", "Radix"), - NC_("SC_OPCODE_BASE", "The base number for conversion must be in the range 2 - 36."), - NC_("SC_OPCODE_BASE", "Minimum length"), - NC_("SC_OPCODE_BASE", "If the text is shorter than the specified length, zeros are added to the left of the string.") + NC_("ocBASE", "Converts a positive integer to text from a number system to the base defined."), + NC_("ocBASE", "Number"), + NC_("ocBASE", "The number to be converted."), + NC_("ocBASE", "Radix"), + NC_("ocBASE", "The base number for conversion must be in the range 2 - 36."), + NC_("ocBASE", "Minimum length"), + NC_("ocBASE", "If the text is shorter than the specified length, zeros are added to the left of the string.") }; // -=*# Resource for function DECIMAL #*=- -const TranslateId SC_OPCODE_DECIMAL_ARY[] = +const TranslateId ocDECIMAL_ARY[] = { - NC_("SC_OPCODE_DECIMAL", "Converts a text of a specified number system to a positive integer in the base given."), - NC_("SC_OPCODE_DECIMAL", "Text"), - NC_("SC_OPCODE_DECIMAL", "The text to be converted."), - NC_("SC_OPCODE_DECIMAL", "Radix"), - NC_("SC_OPCODE_DECIMAL", "The base number for conversion must be in the range 2 - 36.") + NC_("ocDECIMAL", "Converts a text of a specified number system to a positive integer in the base given."), + NC_("ocDECIMAL", "Text"), + NC_("ocDECIMAL", "The text to be converted."), + NC_("ocDECIMAL", "Radix"), + NC_("ocDECIMAL", "The base number for conversion must be in the range 2 - 36.") }; // -=*# Resource for function CONVERT_OOO #*=- -const TranslateId SC_OPCODE_CONVERT_OOO_ARY[] = +const TranslateId ocCONVERT_OOO_ARY[] = { - NC_("SC_OPCODE_CONVERT_OOO", "Converts a value according to a conversion table in the configuration (main.xcd)."), - NC_("SC_OPCODE_CONVERT_OOO", "Value"), - NC_("SC_OPCODE_CONVERT_OOO", "The value to be converted."), - NC_("SC_OPCODE_CONVERT_OOO", "Text"), - NC_("SC_OPCODE_CONVERT_OOO", "Unit from which something is converted, case-sensitive."), - NC_("SC_OPCODE_CONVERT_OOO", "Text"), - NC_("SC_OPCODE_CONVERT_OOO", "Unit into which something is converted, case-sensitive.") + NC_("ocCONVERT_OOO", "Converts a value according to a conversion table in the configuration (main.xcd)."), + NC_("ocCONVERT_OOO", "Value"), + NC_("ocCONVERT_OOO", "The value to be converted."), + NC_("ocCONVERT_OOO", "Text"), + NC_("ocCONVERT_OOO", "Unit from which something is converted, case-sensitive."), + NC_("ocCONVERT_OOO", "Text"), + NC_("ocCONVERT_OOO", "Unit into which something is converted, case-sensitive.") }; // -=*# Resource for function ROMAN #*=- -const TranslateId SC_OPCODE_ROMAN_ARY[] = +const TranslateId ocROMAN_ARY[] = { - NC_("SC_OPCODE_ROMAN", "Converts a number to a Roman numeral."), - NC_("SC_OPCODE_ROMAN", "Number"), - NC_("SC_OPCODE_ROMAN", "The number to be converted to a Roman numeral must be in the 0 - 3999 range."), - NC_("SC_OPCODE_ROMAN", "Mode"), - NC_("SC_OPCODE_ROMAN", "The more this value increases, the more the Roman numeral is simplified. The value must be in the 0 - 4 range.") + NC_("ocROMAN", "Converts a number to a Roman numeral."), + NC_("ocROMAN", "Number"), + NC_("ocROMAN", "The number to be converted to a Roman numeral must be in the 0 - 3999 range."), + NC_("ocROMAN", "Mode"), + NC_("ocROMAN", "The more this value increases, the more the Roman numeral is simplified. The value must be in the 0 - 4 range.") }; // -=*# Resource for function ARABIC #*=- -const TranslateId SC_OPCODE_ARABIC_ARY[] = +const TranslateId ocARABIC_ARY[] = { - NC_("SC_OPCODE_ARABIC", "Calculates the value of a Roman numeral."), - NC_("SC_OPCODE_ARABIC", "Text"), - NC_("SC_OPCODE_ARABIC", "The text that represents a Roman numeral.") + NC_("ocARABIC", "Calculates the value of a Roman numeral."), + NC_("ocARABIC", "Text"), + NC_("ocARABIC", "The text that represents a Roman numeral.") }; -const TranslateId SC_OPCODE_INFO_ARY[] = +const TranslateId ocINFO_ARY[] = { - NC_("SC_OPCODE_INFO", "Returns information about the environment."), - NC_("SC_OPCODE_INFO", "Text"), - NC_("SC_OPCODE_INFO", "Can be \"osversion\", \"system\", \"release\", \"numfile\", and \"recalc\".") + NC_("ocINFO", "Returns information about the environment."), + NC_("ocINFO", "Text"), + NC_("ocINFO", "Can be \"osversion\", \"system\", \"release\", \"numfile\", and \"recalc\".") }; -const TranslateId SC_OPCODE_UNICODE_ARY[] = +const TranslateId ocUNICODE_ARY[] = { - NC_("SC_OPCODE_UNICODE", "Returns the numeric code for the first Unicode character in a text string."), - NC_("SC_OPCODE_UNICODE", "Text"), - NC_("SC_OPCODE_UNICODE", "This is the text for which the code of the first character is to be found.") + NC_("ocUNICODE", "Returns the numeric code for the first Unicode character in a text string."), + NC_("ocUNICODE", "Text"), + NC_("ocUNICODE", "This is the text for which the code of the first character is to be found.") }; -const TranslateId SC_OPCODE_UNICHAR_ARY[] = +const TranslateId ocUNICHAR_ARY[] = { - NC_("SC_OPCODE_UNICHAR", "Converts a code number into a Unicode character or letter."), - NC_("SC_OPCODE_UNICHAR", "Number"), - NC_("SC_OPCODE_UNICHAR", "The code value for the character.") + NC_("ocUNICHAR", "Converts a code number into a Unicode character or letter."), + NC_("ocUNICHAR", "Number"), + NC_("ocUNICHAR", "The code value for the character.") }; -const TranslateId SC_OPCODE_EUROCONVERT_ARY[] = +const TranslateId ocEUROCONVERT_ARY[] = { - NC_("SC_OPCODE_EUROCONVERT", "Converts a value from one to another Euro currency."), - NC_("SC_OPCODE_EUROCONVERT", "Value"), - NC_("SC_OPCODE_EUROCONVERT", "The value to be converted."), - NC_("SC_OPCODE_EUROCONVERT", "From currency"), - NC_("SC_OPCODE_EUROCONVERT", "ISO 4217 code of the currency from which is converted."), - NC_("SC_OPCODE_EUROCONVERT", "To currency"), - NC_("SC_OPCODE_EUROCONVERT", "ISO 4217 code of the currency into which is converted."), - NC_("SC_OPCODE_EUROCONVERT", "Full precision"), - NC_("SC_OPCODE_EUROCONVERT", "If omitted or 0 or FALSE, the result is rounded to the decimals of To_currency. Else the result is not rounded."), - NC_("SC_OPCODE_EUROCONVERT", "Triangulation precision"), + NC_("ocEUROCONVERT", "Converts a value from one to another Euro currency."), + NC_("ocEUROCONVERT", "Value"), + NC_("ocEUROCONVERT", "The value to be converted."), + NC_("ocEUROCONVERT", "From currency"), + NC_("ocEUROCONVERT", "ISO 4217 code of the currency from which is converted."), + NC_("ocEUROCONVERT", "To currency"), + NC_("ocEUROCONVERT", "ISO 4217 code of the currency into which is converted."), + NC_("ocEUROCONVERT", "Full precision"), + NC_("ocEUROCONVERT", "If omitted or 0 or FALSE, the result is rounded to the decimals of To_currency. Else the result is not rounded."), + NC_("ocEUROCONVERT", "Triangulation precision"), /* This description uses almost all available space in the dialog, make sure translations fit in size */ - NC_("SC_OPCODE_EUROCONVERT", "If given and >=3, the intermediate result of a triangular conversion is rounded to that precision. If omitted, the result is not rounded.") + NC_("ocEUROCONVERT", "If given and >=3, the intermediate result of a triangular conversion is rounded to that precision. If omitted, the result is not rounded.") }; -const TranslateId SC_OPCODE_NUMBERVALUE_ARY[] = +const TranslateId ocNUMBERVALUE_ARY[] = { - NC_("SC_OPCODE_NUMBERVALUE", "Converts text to a number, in a locale-independent way."), - NC_("SC_OPCODE_NUMBERVALUE", "Text"), - NC_("SC_OPCODE_NUMBERVALUE", "The text to be converted to a number."), - NC_("SC_OPCODE_NUMBERVALUE", "Decimal separator"), - NC_("SC_OPCODE_NUMBERVALUE", "Defines the character used as the decimal separator."), - NC_("SC_OPCODE_NUMBERVALUE", "Group separator"), - NC_("SC_OPCODE_NUMBERVALUE", "Defines the character(s) used as the group separator.") + NC_("ocNUMBERVALUE", "Converts text to a number, in a locale-independent way."), + NC_("ocNUMBERVALUE", "Text"), + NC_("ocNUMBERVALUE", "The text to be converted to a number."), + NC_("ocNUMBERVALUE", "Decimal separator"), + NC_("ocNUMBERVALUE", "Defines the character used as the decimal separator."), + NC_("ocNUMBERVALUE", "Group separator"), + NC_("ocNUMBERVALUE", "Defines the character(s) used as the group separator.") }; -const TranslateId SC_OPCODE_BITAND_ARY[] = +const TranslateId ocBITAND_ARY[] = { - NC_("SC_OPCODE_BITAND", "Bitwise \"AND\" of two integers."), - NC_("SC_OPCODE_BITAND", "Number1"), - NC_("SC_OPCODE_BITAND", "Positive integer less than 2^48."), - NC_("SC_OPCODE_BITAND", "Number2"), - NC_("SC_OPCODE_BITAND", "Positive integer less than 2^48.") + NC_("ocBITAND", "Bitwise \"AND\" of two integers."), + NC_("ocBITAND", "Number1"), + NC_("ocBITAND", "Positive integer less than 2^48."), + NC_("ocBITAND", "Number2"), + NC_("ocBITAND", "Positive integer less than 2^48.") }; -const TranslateId SC_OPCODE_BITOR_ARY[] = +const TranslateId ocBITOR_ARY[] = { - NC_("SC_OPCODE_BITOR", "Bitwise \"OR\" of two integers."), - NC_("SC_OPCODE_BITOR", "Number1"), - NC_("SC_OPCODE_BITOR", "Positive integer less than 2^48."), - NC_("SC_OPCODE_BITOR", "Number2"), - NC_("SC_OPCODE_BITOR", "Positive integer less than 2^48.") + NC_("ocBITOR", "Bitwise \"OR\" of two integers."), + NC_("ocBITOR", "Number1"), + NC_("ocBITOR", "Positive integer less than 2^48."), + NC_("ocBITOR", "Number2"), + NC_("ocBITOR", "Positive integer less than 2^48.") }; -const TranslateId SC_OPCODE_BITXOR_ARY[] = +const TranslateId ocBITXOR_ARY[] = { - NC_("SC_OPCODE_BITXOR", "Bitwise \"exclusive OR\" of two integers."), - NC_("SC_OPCODE_BITXOR", "Number1"), - NC_("SC_OPCODE_BITXOR", "Positive integer less than 2^48."), - NC_("SC_OPCODE_BITXOR", "Number2"), - NC_("SC_OPCODE_BITXOR", "Positive integer less than 2^48.") + NC_("ocBITXOR", "Bitwise \"exclusive OR\" of two integers."), + NC_("ocBITXOR", "Number1"), + NC_("ocBITXOR", "Positive integer less than 2^48."), + NC_("ocBITXOR", "Number2"), + NC_("ocBITXOR", "Positive integer less than 2^48.") }; -const TranslateId SC_OPCODE_BITRSHIFT_ARY[] = +const TranslateId ocBITRSHIFT_ARY[] = { - NC_("SC_OPCODE_BITRSHIFT", "Bitwise right shift of an integer value."), - NC_("SC_OPCODE_BITRSHIFT", "Number"), - NC_("SC_OPCODE_BITRSHIFT", "The value to be shifted. Positive integer less than 2^48."), - NC_("SC_OPCODE_BITRSHIFT", "Shift"), - NC_("SC_OPCODE_BITRSHIFT", "The integer number of bits the value is to be shifted.") + NC_("ocBITRSHIFT", "Bitwise right shift of an integer value."), + NC_("ocBITRSHIFT", "Number"), + NC_("ocBITRSHIFT", "The value to be shifted. Positive integer less than 2^48."), + NC_("ocBITRSHIFT", "Shift"), + NC_("ocBITRSHIFT", "The integer number of bits the value is to be shifted.") }; -const TranslateId SC_OPCODE_BITLSHIFT_ARY[] = +const TranslateId ocBITLSHIFT_ARY[] = { - NC_("SC_OPCODE_BITLSHIFT", "Bitwise left shift of an integer value."), - NC_("SC_OPCODE_BITLSHIFT", "Number"), - NC_("SC_OPCODE_BITLSHIFT", "The value to be shifted. Positive integer less than 2^48."), - NC_("SC_OPCODE_BITLSHIFT", "Shift"), - NC_("SC_OPCODE_BITLSHIFT", "The integer number of bits the value is to be shifted.") + NC_("ocBITLSHIFT", "Bitwise left shift of an integer value."), + NC_("ocBITLSHIFT", "Number"), + NC_("ocBITLSHIFT", "The value to be shifted. Positive integer less than 2^48."), + NC_("ocBITLSHIFT", "Shift"), + NC_("ocBITLSHIFT", "The integer number of bits the value is to be shifted.") }; -const TranslateId SC_OPCODE_LENB_ARY[] = +const TranslateId ocLENB_ARY[] = { - NC_("SC_OPCODE_LENB", "Calculates length of a text string, with DBCS"), - NC_("SC_OPCODE_LENB", "Text"), - NC_("SC_OPCODE_LENB", "The text in which the length is to be determined.") + NC_("ocLENB", "Calculates length of a text string, with DBCS"), + NC_("ocLENB", "Text"), + NC_("ocLENB", "The text in which the length is to be determined.") }; -const TranslateId SC_OPCODE_RIGHTB_ARY[] = +const TranslateId ocRIGHTB_ARY[] = { - NC_("SC_OPCODE_RIGHTB", "Returns the last character or characters of a text,with DBCS"), - NC_("SC_OPCODE_RIGHTB", "Text"), - NC_("SC_OPCODE_RIGHTB", "The text in which the end partial words are to be determined."), - NC_("SC_OPCODE_RIGHTB", "Number"), - NC_("SC_OPCODE_RIGHTB", "The number of characters for the end text.") + NC_("ocRIGHTB", "Returns the last character or characters of a text,with DBCS"), + NC_("ocRIGHTB", "Text"), + NC_("ocRIGHTB", "The text in which the end partial words are to be determined."), + NC_("ocRIGHTB", "Number"), + NC_("ocRIGHTB", "The number of characters for the end text.") }; -const TranslateId SC_OPCODE_LEFTB_ARY[] = +const TranslateId ocLEFTB_ARY[] = { - NC_("SC_OPCODE_LEFTB", "Returns the first character or characters of a text,with DBCS"), - NC_("SC_OPCODE_LEFTB", "Text"), - NC_("SC_OPCODE_LEFTB", "The text where the initial partial words are to be determined."), - NC_("SC_OPCODE_LEFTB", "Number"), - NC_("SC_OPCODE_LEFTB", "The number of characters for the start text.") + NC_("ocLEFTB", "Returns the first character or characters of a text,with DBCS"), + NC_("ocLEFTB", "Text"), + NC_("ocLEFTB", "The text where the initial partial words are to be determined."), + NC_("ocLEFTB", "Number"), + NC_("ocLEFTB", "The number of characters for the start text.") }; -const TranslateId SC_OPCODE_MIDB_ARY[] = +const TranslateId ocMIDB_ARY[] = { - NC_("SC_OPCODE_MIDB", "Returns a partial text string of a text, with DBCS"), - NC_("SC_OPCODE_MIDB", "Text"), - NC_("SC_OPCODE_MIDB", "The text in which partial words are to be determined."), - NC_("SC_OPCODE_MIDB", "Start"), - NC_("SC_OPCODE_MIDB", "The position from which the part word is to be determined."), - NC_("SC_OPCODE_MIDB", "Number"), - NC_("SC_OPCODE_MIDB", "The number of characters for the text.") + NC_("ocMIDB", "Returns a partial text string of a text, with DBCS"), + NC_("ocMIDB", "Text"), + NC_("ocMIDB", "The text in which partial words are to be determined."), + NC_("ocMIDB", "Start"), + NC_("ocMIDB", "The position from which the part word is to be determined."), + NC_("ocMIDB", "Number"), + NC_("ocMIDB", "The number of characters for the text.") }; -const TranslateId SC_OPCODE_FILTERXML_ARY[] = +const TranslateId ocFILTERXML_ARY[] = { - NC_("SC_OPCODE_FILTERXML", "Apply an XPath expression to an XML document"), - NC_("SC_OPCODE_FILTERXML", "XML Document"), - NC_("SC_OPCODE_FILTERXML", "String containing a valid XML stream"), - NC_("SC_OPCODE_FILTERXML", "XPath expression"), - NC_("SC_OPCODE_FILTERXML", "String containing a valid XPath expression") + NC_("ocFILTERXML", "Apply an XPath expression to an XML document"), + NC_("ocFILTERXML", "XML Document"), + NC_("ocFILTERXML", "String containing a valid XML stream"), + NC_("ocFILTERXML", "XPath expression"), + NC_("ocFILTERXML", "String containing a valid XPath expression") }; -const TranslateId SC_OPCODE_COLOR_ARY[] = +const TranslateId ocCOLOR_ARY[] = { - NC_("SC_OPCODE_COLOR", "Returns an implementation defined value representing a RGBA color"), - NC_("SC_OPCODE_COLOR", "Red"), - NC_("SC_OPCODE_COLOR", "Value of red"), - NC_("SC_OPCODE_COLOR", "Green"), - NC_("SC_OPCODE_COLOR", "Value of green"), - NC_("SC_OPCODE_COLOR", "Blue"), - NC_("SC_OPCODE_COLOR", "Value of blue"), - NC_("SC_OPCODE_COLOR", "Alpha"), - NC_("SC_OPCODE_COLOR", "Value of alpha") + NC_("ocCOLOR", "Returns an implementation defined value representing a RGBA color"), + NC_("ocCOLOR", "Red"), + NC_("ocCOLOR", "Value of red"), + NC_("ocCOLOR", "Green"), + NC_("ocCOLOR", "Value of green"), + NC_("ocCOLOR", "Blue"), + NC_("ocCOLOR", "Value of blue"), + NC_("ocCOLOR", "Alpha"), + NC_("ocCOLOR", "Value of alpha") }; -const TranslateId SC_OPCODE_WEBSERVICE_ARY[] = +const TranslateId ocWEBSERVICE_ARY[] = { - NC_("SC_OPCODE_WEBSERVICE", "Get some web-content from a URI."), - NC_("SC_OPCODE_WEBSERVICE", "URI"), - NC_("SC_OPCODE_WEBSERVICE", "URI of the webservice") + NC_("ocWEBSERVICE", "Get some web-content from a URI."), + NC_("ocWEBSERVICE", "URI"), + NC_("ocWEBSERVICE", "URI of the webservice") }; -const TranslateId SC_OPCODE_ENCODEURL_ARY[] = +const TranslateId ocENCODEURL_ARY[] = { - NC_("SC_OPCODE_ENCODEURL", "Return a URL-encoded string."), - NC_("SC_OPCODE_ENCODEURL", "Text"), - NC_("SC_OPCODE_ENCODEURL", "A string to be URL-encoded") + NC_("ocENCODEURL", "Return a URL-encoded string."), + NC_("ocENCODEURL", "Text"), + NC_("ocENCODEURL", "A string to be URL-encoded") }; -const TranslateId SC_OPCODE_ERF_MS_ARY[] = +const TranslateId ocERF_MS_ARY[] = { - NC_("SC_OPCODE_ERF_MS", "Returns the error function."), - NC_("SC_OPCODE_ERF_MS", "Lower limit"), - NC_("SC_OPCODE_ERF_MS", "The lower limit for integration") + NC_("ocERF_MS", "Returns the error function."), + NC_("ocERF_MS", "Lower limit"), + NC_("ocERF_MS", "The lower limit for integration") }; -const TranslateId SC_OPCODE_ERFC_MS_ARY[] = +const TranslateId ocERFC_MS_ARY[] = { - NC_("SC_OPCODE_ERFC_MS", "Returns the complementary error function."), - NC_("SC_OPCODE_ERFC_MS", "Lower limit"), - NC_("SC_OPCODE_ERFC_MS", "The lower limit for integration") + NC_("ocERFC_MS", "Returns the complementary error function."), + NC_("ocERFC_MS", "Lower limit"), + NC_("ocERFC_MS", "The lower limit for integration") }; -const TranslateId SC_OPCODE_RAWSUBTRACT_ARY[] = +const TranslateId ocRAWSUBTRACT_ARY[] = { - NC_("SC_OPCODE_RAWSUBTRACT", "Returns the subtraction of numbers. Like a-b-c but without eliminating small roundoff errors."), - NC_("SC_OPCODE_RAWSUBTRACT", "Minuend"), - NC_("SC_OPCODE_RAWSUBTRACT", "Number from which following arguments are subtracted."), - NC_("SC_OPCODE_RAWSUBTRACT", "Subtrahend "), - NC_("SC_OPCODE_RAWSUBTRACT", "Subtrahend 1, subtrahend 2, ... are numerical arguments subtracted from the minuend.") + NC_("ocRAWSUBTRACT", "Returns the subtraction of numbers. Like a-b-c but without eliminating small roundoff errors."), + NC_("ocRAWSUBTRACT", "Minuend"), + NC_("ocRAWSUBTRACT", "Number from which following arguments are subtracted."), + NC_("ocRAWSUBTRACT", "Subtrahend "), + NC_("ocRAWSUBTRACT", "Subtrahend 1, subtrahend 2, ... are numerical arguments subtracted from the minuend.") }; // -=*# Resource for function ROUNDSIG #*=- -const TranslateId SC_OPCODE_ROUNDSIG_ARY[] = +const TranslateId ocROUNDSIG_ARY[] = { - NC_("SC_OPCODE_ROUNDSIG", "Rounds a number to predefined significant digits."), - NC_("SC_OPCODE_ROUNDSIG", "Value"), - NC_("SC_OPCODE_ROUNDSIG", "The number to be rounded."), - NC_("SC_OPCODE_ROUNDSIG", "Digits"), - NC_("SC_OPCODE_ROUNDSIG", "The number of significant digits to which value is to be rounded.") + NC_("ocROUNDSIG", "Rounds a number to predefined significant digits."), + NC_("ocROUNDSIG", "Value"), + NC_("ocROUNDSIG", "The number to be rounded."), + NC_("ocROUNDSIG", "Digits"), + NC_("ocROUNDSIG", "The number of significant digits to which value is to be rounded.") }; -const TranslateId SC_OPCODE_REPLACEB_ARY[] = +const TranslateId ocREPLACEB_ARY[] = { - NC_("SC_OPCODE_REPLACEB", "Replaces characters within a text string with a different text string, with DBCS."), - NC_("SC_OPCODE_REPLACEB", "Text"), - NC_("SC_OPCODE_REPLACEB", "The text in which some characters are to be replaced."), - NC_("SC_OPCODE_REPLACEB", "Position"), - NC_("SC_OPCODE_REPLACEB", "The character position from which text is to be replaced."), - NC_("SC_OPCODE_REPLACEB", "Length"), - NC_("SC_OPCODE_REPLACEB", "The number of characters to be replaced."), - NC_("SC_OPCODE_REPLACEB", "New text"), - NC_("SC_OPCODE_REPLACEB", "The text to be inserted.") + NC_("ocREPLACEB", "Replaces characters within a text string with a different text string, with DBCS."), + NC_("ocREPLACEB", "Text"), + NC_("ocREPLACEB", "The text in which some characters are to be replaced."), + NC_("ocREPLACEB", "Position"), + NC_("ocREPLACEB", "The character position from which text is to be replaced."), + NC_("ocREPLACEB", "Length"), + NC_("ocREPLACEB", "The number of characters to be replaced."), + NC_("ocREPLACEB", "New text"), + NC_("ocREPLACEB", "The text to be inserted.") }; // -=*# Resource for function FINDB #*=- -const TranslateId SC_OPCODE_FINDB_ARY[] = +const TranslateId ocFINDB_ARY[] = { - NC_("SC_OPCODE_FINDB", "Looks for a string of text within another (case sensitive), using byte positions."), - NC_("SC_OPCODE_FINDB", "Find text"), - NC_("SC_OPCODE_FINDB", "The text to be found."), - NC_("SC_OPCODE_FINDB", "Text"), - NC_("SC_OPCODE_FINDB", "The text in which a search is to be made."), - NC_("SC_OPCODE_FINDB", "Position"), - NC_("SC_OPCODE_FINDB", "The position in the text from which the search starts.") + NC_("ocFINDB", "Looks for a string of text within another (case sensitive), using byte positions."), + NC_("ocFINDB", "Find text"), + NC_("ocFINDB", "The text to be found."), + NC_("ocFINDB", "Text"), + NC_("ocFINDB", "The text in which a search is to be made."), + NC_("ocFINDB", "Position"), + NC_("ocFINDB", "The position in the text from which the search starts.") }; // -=*# Resource for function SEARCHB #*=- -const TranslateId SC_OPCODE_SEARCHB_ARY[] = +const TranslateId ocSEARCHB_ARY[] = { - NC_("SC_OPCODE_SEARCHB", "Looks for a string of text within another (not case sensitive), using byte positions."), - NC_("SC_OPCODE_SEARCHB", "Find text"), - NC_("SC_OPCODE_SEARCHB", "The text to be found."), - NC_("SC_OPCODE_SEARCHB", "Text"), - NC_("SC_OPCODE_SEARCHB", "The text in which a search is to be made."), - NC_("SC_OPCODE_SEARCHB", "Position"), - NC_("SC_OPCODE_SEARCHB", "The position in the text from which the search starts.") + NC_("ocSEARCHB", "Looks for a string of text within another (not case sensitive), using byte positions."), + NC_("ocSEARCHB", "Find text"), + NC_("ocSEARCHB", "The text to be found."), + NC_("ocSEARCHB", "Text"), + NC_("ocSEARCHB", "The text in which a search is to be made."), + NC_("ocSEARCHB", "Position"), + NC_("ocSEARCHB", "The position in the text from which the search starts.") }; // -=*# Resource for function FOURIER #*=- -const TranslateId SC_OPCODE_FOURIER_ARY[] = +const TranslateId ocFOURIER_ARY[] = { - NC_("SC_OPCODE_FOURIER", "Computes the Discrete Fourier Transform (DFT) of an array"), - NC_("SC_OPCODE_FOURIER", "Array"), - NC_("SC_OPCODE_FOURIER", "The array whose DFT needs to be computed. The dimensions of this array can be Nx1 or Nx2 or 1xN or 2xN."), - NC_("SC_OPCODE_FOURIER", "GroupedByColumns"), - NC_("SC_OPCODE_FOURIER", "Flag to indicate whether the array is grouped by columns or not (default TRUE)."), - NC_("SC_OPCODE_FOURIER", "Inverse"), - NC_("SC_OPCODE_FOURIER", "Flag to indicate whether an inverse DFT is to be computed (default FALSE)."), - NC_("SC_OPCODE_FOURIER", "Polar"), - NC_("SC_OPCODE_FOURIER", "Flag to indicate whether to return the results in polar form (default FALSE)."), - NC_("SC_OPCODE_FOURIER", "MinimumMagnitude"), - NC_("SC_OPCODE_FOURIER", "In case of Polar=TRUE, the frequency components below this magnitude are clipped out (default 0.0).") + NC_("ocFOURIER", "Computes the Discrete Fourier Transform (DFT) of an array"), + NC_("ocFOURIER", "Array"), + NC_("ocFOURIER", "The array whose DFT needs to be computed. The dimensions of this array can be Nx1 or Nx2 or 1xN or 2xN."), + NC_("ocFOURIER", "GroupedByColumns"), + NC_("ocFOURIER", "Flag to indicate whether the array is grouped by columns or not (default TRUE)."), + NC_("ocFOURIER", "Inverse"), + NC_("ocFOURIER", "Flag to indicate whether an inverse DFT is to be computed (default FALSE)."), + NC_("ocFOURIER", "Polar"), + NC_("ocFOURIER", "Flag to indicate whether to return the results in polar form (default FALSE)."), + NC_("ocFOURIER", "MinimumMagnitude"), + NC_("ocFOURIER", "In case of Polar=TRUE, the frequency components below this magnitude are clipped out (default 0.0).") }; // -=*# Resource for function RAND.NV #*=- -const TranslateId SC_OPCODE_RANDOM_NV_ARY[] = +const TranslateId ocRANDOM_NV_ARY[] = { - NC_("SC_OPCODE_RANDOM_NV", "Returns a random number between 0 and 1, non-volatile.") + NC_("ocRANDOM_NV", "Returns a random number between 0 and 1, non-volatile.") }; // -=*# Resource for function RANDBETWEEN.NV #*=- -const TranslateId SC_OPCODE_RANDBETWEEN_NV_ARY[] = +const TranslateId ocRANDBETWEEN_NV_ARY[] = { - NC_("SC_OPCODE_RANDBETWEEN_NV", "Returns a random integer between the specified Bottom and Top values (both inclusive), non-volatile."), - NC_("SC_OPCODE_RANDBETWEEN_NV", "Bottom"), - NC_("SC_OPCODE_RANDBETWEEN_NV", "The smallest integer that can be returned."), - NC_("SC_OPCODE_RANDBETWEEN_NV", "Top"), - NC_("SC_OPCODE_RANDBETWEEN_NV", "The largest integer that can be returned.") + NC_("ocRANDBETWEEN_NV", "Returns a random integer between the specified Bottom and Top values (both inclusive), non-volatile."), + NC_("ocRANDBETWEEN_NV", "Bottom"), + NC_("ocRANDBETWEEN_NV", "The smallest integer that can be returned."), + NC_("ocRANDBETWEEN_NV", "Top"), + NC_("ocRANDBETWEEN_NV", "The largest integer that can be returned.") }; // -=*# Resource for function FILTER #*=- -const TranslateId SC_OPCODE_FILTER_ARY[] = +const TranslateId ocFILTER_ARY[] = { - NC_("SC_OPCODE_FILTER", "Filters an array based on a Boolean (True/False) array."), - NC_("SC_OPCODE_FILTER", "Range"), - NC_("SC_OPCODE_FILTER", "The array, or range to filter."), - NC_("SC_OPCODE_FILTER", "Include"), - NC_("SC_OPCODE_FILTER", "A Boolean array whose height or width is the same as the array."), - NC_("SC_OPCODE_FILTER", "Result if empty"), - NC_("SC_OPCODE_FILTER", "The value to return if all values in the included array are empty (filter returns nothing).") + NC_("ocFILTER", "Filters an array based on a Boolean (True/False) array."), + NC_("ocFILTER", "Range"), + NC_("ocFILTER", "The array, or range to filter."), + NC_("ocFILTER", "Include"), + NC_("ocFILTER", "A Boolean array whose height or width is the same as the array."), + NC_("ocFILTER", "Result if empty"), + NC_("ocFILTER", "The value to return if all values in the included array are empty (filter returns nothing).") }; // -=*# Resource for function SORT #*=- -const TranslateId SC_OPCODE_SORT_ARY[] = +const TranslateId ocSORT_ARY[] = { - NC_("SC_OPCODE_SORT", "Sorts the contents of a range or array."), - NC_("SC_OPCODE_SORT", "Range"), - NC_("SC_OPCODE_SORT", "The range, or array to sort."), - NC_("SC_OPCODE_SORT", "Sort index"), - NC_("SC_OPCODE_SORT", "A number indicating the row or column to sort by."), - NC_("SC_OPCODE_SORT", "Sort order"), - NC_("SC_OPCODE_SORT", "A number indicating the desired sort order; 1 for ascending order (default), -1 for descending order."), - NC_("SC_OPCODE_SORT", "By col"), - NC_("SC_OPCODE_SORT", "A logical value indicating the desired sort direction; FALSE to sort by row (default), TRUE to sort by column.") + NC_("ocSORT", "Sorts the contents of a range or array."), + NC_("ocSORT", "Range"), + NC_("ocSORT", "The range, or array to sort."), + NC_("ocSORT", "Sort index"), + NC_("ocSORT", "A number indicating the row or column to sort by."), + NC_("ocSORT", "Sort order"), + NC_("ocSORT", "A number indicating the desired sort order; 1 for ascending order (default), -1 for descending order."), + NC_("ocSORT", "By col"), + NC_("ocSORT", "A logical value indicating the desired sort direction; FALSE to sort by row (default), TRUE to sort by column.") }; // -=*# Resource for function SORTBY #*=- -const TranslateId SC_OPCODE_SORTBY_ARY[] = +const TranslateId ocSORTBY_ARY[] = { - NC_("SC_OPCODE_SORTBY", "Sorts the contents of a range or array based on the values in a corresponding range or array."), - NC_("SC_OPCODE_SORTBY", "Sort range"), - NC_("SC_OPCODE_SORTBY", "The array or range to sort."), - NC_("SC_OPCODE_SORTBY", "Sort by range "), - NC_("SC_OPCODE_SORTBY", "Range 1, range 2,... are the arrays or ranges to sort on."), - NC_("SC_OPCODE_SORTBY", "Sort order "), - NC_("SC_OPCODE_SORTBY", "Order 1, order 2,... are the orders to use for sorting. 1 for ascending, -1 for descending. Default is ascending.") + NC_("ocSORTBY", "Sorts the contents of a range or array based on the values in a corresponding range or array."), + NC_("ocSORTBY", "Sort range"), + NC_("ocSORTBY", "The array or range to sort."), + NC_("ocSORTBY", "Sort by range "), + NC_("ocSORTBY", "Range 1, range 2,... are the arrays or ranges to sort on."), + NC_("ocSORTBY", "Sort order "), + NC_("ocSORTBY", "Order 1, order 2,... are the orders to use for sorting. 1 for ascending, -1 for descending. Default is ascending.") }; // -=*# Resource for function SEQUENCE #*=- -const TranslateId SC_OPCODE_MAT_SEQUENCE_ARY[] = +const TranslateId ocMAT_SEQUENCE_ARY[] = { - NC_("SC_OPCODE_MAT_SEQUENCE", "Generates a list of sequential numbers in an array, such as 1, 2, 3, 4."), - NC_("SC_OPCODE_MAT_SEQUENCE", "Rows"), - NC_("SC_OPCODE_MAT_SEQUENCE", "The number of rows to return."), - NC_("SC_OPCODE_MAT_SEQUENCE", "Columns"), - NC_("SC_OPCODE_MAT_SEQUENCE", "The number of columns to return."), - NC_("SC_OPCODE_MAT_SEQUENCE", "Start"), - NC_("SC_OPCODE_MAT_SEQUENCE", "The first number in the sequence."), - NC_("SC_OPCODE_MAT_SEQUENCE", "Step"), - NC_("SC_OPCODE_MAT_SEQUENCE", "The amount to increment each subsequent value in the array.") + NC_("ocMAT_SEQUENCE", "Generates a list of sequential numbers in an array, such as 1, 2, 3, 4."), + NC_("ocMAT_SEQUENCE", "Rows"), + NC_("ocMAT_SEQUENCE", "The number of rows to return."), + NC_("ocMAT_SEQUENCE", "Columns"), + NC_("ocMAT_SEQUENCE", "The number of columns to return."), + NC_("ocMAT_SEQUENCE", "Start"), + NC_("ocMAT_SEQUENCE", "The first number in the sequence."), + NC_("ocMAT_SEQUENCE", "Step"), + NC_("ocMAT_SEQUENCE", "The amount to increment each subsequent value in the array.") }; // -=*# Resource for function RANDARRAY #*=- -const TranslateId SC_OPCODE_RANDARRAY_ARY[] = +const TranslateId ocRANDARRAY_ARY[] = { - NC_("SC_OPCODE_RANDARRAY", "Generates an array of random numbers between two limit values."), - NC_("SC_OPCODE_RANDARRAY", "Rows"), - NC_("SC_OPCODE_RANDARRAY", "The number of rows to return."), - NC_("SC_OPCODE_RANDARRAY", "Columns"), - NC_("SC_OPCODE_RANDARRAY", "The number of columns to return."), - NC_("SC_OPCODE_RANDARRAY", "Min"), - NC_("SC_OPCODE_RANDARRAY", "The lower limit of the generated numbers."), - NC_("SC_OPCODE_RANDARRAY", "Max"), - NC_("SC_OPCODE_RANDARRAY", "The upper limit of the generated numbers."), - NC_("SC_OPCODE_RANDARRAY", "Integers"), - NC_("SC_OPCODE_RANDARRAY", "Return integer (TRUE) or decimal (FALSE) values.") + NC_("ocRANDARRAY", "Generates an array of random numbers between two limit values."), + NC_("ocRANDARRAY", "Rows"), + NC_("ocRANDARRAY", "The number of rows to return."), + NC_("ocRANDARRAY", "Columns"), + NC_("ocRANDARRAY", "The number of columns to return."), + NC_("ocRANDARRAY", "Min"), + NC_("ocRANDARRAY", "The lower limit of the generated numbers."), + NC_("ocRANDARRAY", "Max"), + NC_("ocRANDARRAY", "The upper limit of the generated numbers."), + NC_("ocRANDARRAY", "Integers"), + NC_("ocRANDARRAY", "Return integer (TRUE) or decimal (FALSE) values.") }; // -=*# Resource for function CHOOSECOLS #*=- -const TranslateId SC_OPCODE_CHOOSECOLS_ARY[] = +const TranslateId ocCHOOSECOLS_ARY[] = { - NC_("SC_OPCODE_CHOOSECOLS", "Returns the specified columns from an array."), - NC_("SC_OPCODE_CHOOSECOLS", "Array"), - NC_("SC_OPCODE_CHOOSECOLS", "The array containing the columns to be returned in the new array."), - NC_("SC_OPCODE_CHOOSECOLS", "Column "), - NC_("SC_OPCODE_CHOOSECOLS", "Column 1, Column 2,... The list of column numbers to be returned.") + NC_("ocCHOOSECOLS", "Returns the specified columns from an array."), + NC_("ocCHOOSECOLS", "Array"), + NC_("ocCHOOSECOLS", "The array containing the columns to be returned in the new array."), + NC_("ocCHOOSECOLS", "Column "), + NC_("ocCHOOSECOLS", "Column 1, Column 2,... The list of column numbers to be returned.") }; // -=*# Resource for function CHOOSEROWS #*=- -const TranslateId SC_OPCODE_CHOOSEROWS_ARY[] = +const TranslateId ocCHOOSEROWS_ARY[] = { - NC_("SC_OPCODE_CHOOSEROWS", "Returns the specified rows from an array."), - NC_("SC_OPCODE_CHOOSEROWS", "Array"), - NC_("SC_OPCODE_CHOOSEROWS", "The array containing the rows to be returned in the new array."), - NC_("SC_OPCODE_CHOOSEROWS", "Row "), - NC_("SC_OPCODE_CHOOSEROWS", "Row 1, Row 2,... The list of row numbers to be returned.") + NC_("ocCHOOSEROWS", "Returns the specified rows from an array."), + NC_("ocCHOOSEROWS", "Array"), + NC_("ocCHOOSEROWS", "The array containing the rows to be returned in the new array."), + NC_("ocCHOOSEROWS", "Row "), + NC_("ocCHOOSEROWS", "Row 1, Row 2,... The list of row numbers to be returned.") }; // -=*# Resource for function DROP #*=- -const TranslateId SC_OPCODE_DROP_ARY[] = +const TranslateId ocDROP_ARY[] = { - NC_("SC_OPCODE_DROP", "Excludes a specified number of contiguous rows or columns from the start or end of an array."), - NC_("SC_OPCODE_DROP", "Array"), - NC_("SC_OPCODE_DROP", "The array from which to drop rows or columns."), - NC_("SC_OPCODE_DROP", "Rows"), - NC_("SC_OPCODE_DROP", "The number of rows to drop. A negative value drops from the end of the array."), - NC_("SC_OPCODE_DROP", "Columns"), - NC_("SC_OPCODE_DROP", "The number of columns to drop. A negative value drops from the end of the array.") + NC_("ocDROP", "Excludes a specified number of contiguous rows or columns from the start or end of an array."), + NC_("ocDROP", "Array"), + NC_("ocDROP", "The array from which to drop rows or columns."), + NC_("ocDROP", "Rows"), + NC_("ocDROP", "The number of rows to drop. A negative value drops from the end of the array."), + NC_("ocDROP", "Columns"), + NC_("ocDROP", "The number of columns to drop. A negative value drops from the end of the array.") }; // -=*# Resource for function EXPAND #*=- -const TranslateId SC_OPCODE_EXPAND_ARY[] = +const TranslateId ocEXPAND_ARY[] = { - NC_("SC_OPCODE_EXPAND", "Expands or pads an array to specified row and column dimensions."), - NC_("SC_OPCODE_EXPAND", "Array"), - NC_("SC_OPCODE_EXPAND", "The array to expand."), - NC_("SC_OPCODE_EXPAND", "Rows"), - NC_("SC_OPCODE_EXPAND", "The number of rows in the expanded array. If missing, rows will not be expanded."), - NC_("SC_OPCODE_EXPAND", "Columns"), - NC_("SC_OPCODE_EXPAND", "The number of columns in the expanded array. If missing, columns will not be expanded."), - NC_("SC_OPCODE_EXPAND", "Pad with"), - NC_("SC_OPCODE_EXPAND", "The value with which to pad. The default is #N/A.") + NC_("ocEXPAND", "Expands or pads an array to specified row and column dimensions."), + NC_("ocEXPAND", "Array"), + NC_("ocEXPAND", "The array to expand."), + NC_("ocEXPAND", "Rows"), + NC_("ocEXPAND", "The number of rows in the expanded array. If missing, rows will not be expanded."), + NC_("ocEXPAND", "Columns"), + NC_("ocEXPAND", "The number of columns in the expanded array. If missing, columns will not be expanded."), + NC_("ocEXPAND", "Pad with"), + NC_("ocEXPAND", "The value with which to pad. The default is #N/A.") }; // -=*# Resource for function HSTACK #*=- -const TranslateId SC_OPCODE_HSTACK_ARY[] = +const TranslateId ocHSTACK_ARY[] = { - NC_("SC_OPCODE_HSTACK", "Appends arrays horizontally to create a larger array."), - NC_("SC_OPCODE_HSTACK", "Array"), - NC_("SC_OPCODE_HSTACK", "The first array to append."), - NC_("SC_OPCODE_HSTACK", "Array"), - NC_("SC_OPCODE_HSTACK", "Array 1, Array 2,... The following arrays to append. If an array has fewer rows, #N/A error will be returned in the additional rows."), + NC_("ocHSTACK", "Appends arrays horizontally to create a larger array."), + NC_("ocHSTACK", "Array"), + NC_("ocHSTACK", "The first array to append."), + NC_("ocHSTACK", "Array"), + NC_("ocHSTACK", "Array 1, Array 2,... The following arrays to append. If an array has fewer rows, #N/A error will be returned in the additional rows."), }; // -=*# Resource for function VSTACK #*=- -const TranslateId SC_OPCODE_VSTACK_ARY[] = +const TranslateId ocVSTACK_ARY[] = { - NC_("SC_OPCODE_VSTACK", "Appends arrays vertically to create a larger array."), - NC_("SC_OPCODE_VSTACK", "Array"), - NC_("SC_OPCODE_VSTACK", "The first array to append."), - NC_("SC_OPCODE_VSTACK", "Array"), - NC_("SC_OPCODE_VSTACK", "Array 1, Array 2,... The following arrays to append. If an array has fewer columns, #N/A error will be returned in the additional columns."), + NC_("ocVSTACK", "Appends arrays vertically to create a larger array."), + NC_("ocVSTACK", "Array"), + NC_("ocVSTACK", "The first array to append."), + NC_("ocVSTACK", "Array"), + NC_("ocVSTACK", "Array 1, Array 2,... The following arrays to append. If an array has fewer columns, #N/A error will be returned in the additional columns."), }; // -=*# Resource for function TAKE #*=- -const TranslateId SC_OPCODE_TAKE_ARY[] = +const TranslateId ocTAKE_ARY[] = { - NC_("SC_OPCODE_TAKE", "Returns a specified number of contiguous rows or columns from the start or end of an array."), - NC_("SC_OPCODE_TAKE", "Array"), - NC_("SC_OPCODE_TAKE", "The array from which to take rows or columns."), - NC_("SC_OPCODE_TAKE", "Rows"), - NC_("SC_OPCODE_TAKE", "The number of rows to take. A negative value takes from the end of the array."), - NC_("SC_OPCODE_TAKE", "Columns"), - NC_("SC_OPCODE_TAKE", "The number of columns to take. A negative value takes from the end of the array.") + NC_("ocTAKE", "Returns a specified number of contiguous rows or columns from the start or end of an array."), + NC_("ocTAKE", "Array"), + NC_("ocTAKE", "The array from which to take rows or columns."), + NC_("ocTAKE", "Rows"), + NC_("ocTAKE", "The number of rows to take. A negative value takes from the end of the array."), + NC_("ocTAKE", "Columns"), + NC_("ocTAKE", "The number of columns to take. A negative value takes from the end of the array.") }; // -=*# Resource for function TEXTAFTER #*=- -const TranslateId SC_OPCODE_TEXTAFTER_ARY[] = +const TranslateId ocTEXTAFTER_ARY[] = { - NC_("SC_OPCODE_TEXTAFTER", "Returns the text that occurs after a given substring or delimiter."), - NC_("SC_OPCODE_TEXTAFTER", "Text"), - NC_("SC_OPCODE_TEXTAFTER", "The original text."), - NC_("SC_OPCODE_TEXTAFTER", "Delimiter"), - NC_("SC_OPCODE_TEXTAFTER", "The delimiter. Multiple delimiters can be supplied."), - NC_("SC_OPCODE_TEXTAFTER", "Instance Number"), - NC_("SC_OPCODE_TEXTAFTER", "The instance of the delimiter after which to extract text. The default is 1. A negative number starts searching from the end."), - NC_("SC_OPCODE_TEXTAFTER", "Match Mode"), - NC_("SC_OPCODE_TEXTAFTER", "Set to 1 to perform a case-insensitive match. The default is 0."), - NC_("SC_OPCODE_TEXTAFTER", "Match End"), - NC_("SC_OPCODE_TEXTAFTER", "Set to 1 to treat the end of text as a delimiter. The default is 0."), - NC_("SC_OPCODE_TEXTAFTER", "If Not Found"), - NC_("SC_OPCODE_TEXTAFTER", "The value returned if no match is found. The default is #N/A.") + NC_("ocTEXTAFTER", "Returns the text that occurs after a given substring or delimiter."), + NC_("ocTEXTAFTER", "Text"), + NC_("ocTEXTAFTER", "The original text."), + NC_("ocTEXTAFTER", "Delimiter"), + NC_("ocTEXTAFTER", "The delimiter. Multiple delimiters can be supplied."), + NC_("ocTEXTAFTER", "Instance Number"), + NC_("ocTEXTAFTER", "The instance of the delimiter after which to extract text. The default is 1. A negative number starts searching from the end."), + NC_("ocTEXTAFTER", "Match Mode"), + NC_("ocTEXTAFTER", "Set to 1 to perform a case-insensitive match. The default is 0."), + NC_("ocTEXTAFTER", "Match End"), + NC_("ocTEXTAFTER", "Set to 1 to treat the end of text as a delimiter. The default is 0."), + NC_("ocTEXTAFTER", "If Not Found"), + NC_("ocTEXTAFTER", "The value returned if no match is found. The default is #N/A.") }; // -=*# Resource for function TEXTBEFORE #*=- -const TranslateId SC_OPCODE_TEXTBEFORE_ARY[] = +const TranslateId ocTEXTBEFORE_ARY[] = { - NC_("SC_OPCODE_TEXTBEFORE", "Returns the text that occurs before a given substring or delimiter."), - NC_("SC_OPCODE_TEXTBEFORE", "Text"), - NC_("SC_OPCODE_TEXTBEFORE", "The original text."), - NC_("SC_OPCODE_TEXTBEFORE", "Delimiter"), - NC_("SC_OPCODE_TEXTBEFORE", "The delimiter. Multiple delimiters can be supplied."), - NC_("SC_OPCODE_TEXTBEFORE", "Instance Number"), - NC_("SC_OPCODE_TEXTBEFORE", "The instance of the delimiter before which to extract text. The default is 1. A negative number starts searching from the end."), - NC_("SC_OPCODE_TEXTBEFORE", "Match Mode"), - NC_("SC_OPCODE_TEXTBEFORE", "Set to 1 to perform a case-insensitive match. The default is 0."), - NC_("SC_OPCODE_TEXTBEFORE", "Match End"), - NC_("SC_OPCODE_TEXTBEFORE", "Set to 1 to treat the end of text as a delimiter. The default is 0."), - NC_("SC_OPCODE_TEXTBEFORE", "If Not Found"), - NC_("SC_OPCODE_TEXTBEFORE", "The value returned if no match is found. The default is #N/A.") + NC_("ocTEXTBEFORE", "Returns the text that occurs before a given substring or delimiter."), + NC_("ocTEXTBEFORE", "Text"), + NC_("ocTEXTBEFORE", "The original text."), + NC_("ocTEXTBEFORE", "Delimiter"), + NC_("ocTEXTBEFORE", "The delimiter. Multiple delimiters can be supplied."), + NC_("ocTEXTBEFORE", "Instance Number"), + NC_("ocTEXTBEFORE", "The instance of the delimiter before which to extract text. The default is 1. A negative number starts searching from the end."), + NC_("ocTEXTBEFORE", "Match Mode"), + NC_("ocTEXTBEFORE", "Set to 1 to perform a case-insensitive match. The default is 0."), + NC_("ocTEXTBEFORE", "Match End"), + NC_("ocTEXTBEFORE", "Set to 1 to treat the end of text as a delimiter. The default is 0."), + NC_("ocTEXTBEFORE", "If Not Found"), + NC_("ocTEXTBEFORE", "The value returned if no match is found. The default is #N/A.") }; // -=*# Resource for function TEXTSPLIT #*=- -const TranslateId SC_OPCODE_TEXTSPLIT_ARY[] = +const TranslateId ocTEXTSPLIT_ARY[] = { - NC_("SC_OPCODE_TEXTSPLIT", "Splits text by a given delimiter to an array of multiple cells."), - NC_("SC_OPCODE_TEXTSPLIT", "Text"), - NC_("SC_OPCODE_TEXTSPLIT", "The text to split."), - NC_("SC_OPCODE_TEXTSPLIT", "Column Delimiter"), - NC_("SC_OPCODE_TEXTSPLIT", "The text to delimit the columns. Multiple delimiters can be supplied."), - NC_("SC_OPCODE_TEXTSPLIT", "Row Delimiter"), - NC_("SC_OPCODE_TEXTSPLIT", "The text to delimit the rows. Multiple delimiters can be supplied."), - NC_("SC_OPCODE_TEXTSPLIT", "Ignore Empty"), - NC_("SC_OPCODE_TEXTSPLIT", "Set to TRUE to ignore consecutive delimiters otherwise it creates an empty cell. The default is FALSE."), - NC_("SC_OPCODE_TEXTSPLIT", "Match mode"), - NC_("SC_OPCODE_TEXTSPLIT", "Set to 1 to perform a case-insensitive match. The default is 0."), - NC_("SC_OPCODE_TEXTSPLIT", "Pad with"), - NC_("SC_OPCODE_TEXTSPLIT", "The value with which to pad. The default is #N/A.") + NC_("ocTEXTSPLIT", "Splits text by a given delimiter to an array of multiple cells."), + NC_("ocTEXTSPLIT", "Text"), + NC_("ocTEXTSPLIT", "The text to split."), + NC_("ocTEXTSPLIT", "Column Delimiter"), + NC_("ocTEXTSPLIT", "The text to delimit the columns. Multiple delimiters can be supplied."), + NC_("ocTEXTSPLIT", "Row Delimiter"), + NC_("ocTEXTSPLIT", "The text to delimit the rows. Multiple delimiters can be supplied."), + NC_("ocTEXTSPLIT", "Ignore Empty"), + NC_("ocTEXTSPLIT", "Set to TRUE to ignore consecutive delimiters otherwise it creates an empty cell. The default is FALSE."), + NC_("ocTEXTSPLIT", "Match mode"), + NC_("ocTEXTSPLIT", "Set to 1 to perform a case-insensitive match. The default is 0."), + NC_("ocTEXTSPLIT", "Pad with"), + NC_("ocTEXTSPLIT", "The value with which to pad. The default is #N/A.") }; // -=*# Resource for function TOCOL #*=- -const TranslateId SC_OPCODE_TOCOL_ARY[] = +const TranslateId ocTOCOL_ARY[] = { - NC_("SC_OPCODE_TOCOL", "Transforms an array into a single column."), - NC_("SC_OPCODE_TOCOL", "Array"), - NC_("SC_OPCODE_TOCOL", "The range or array to return as a single column."), - NC_("SC_OPCODE_TOCOL", "Ignore"), - NC_("SC_OPCODE_TOCOL", "Whether to ignore certain types of values. 0 or omitted - keep all values (default). 1 - ignore blank cells. 2 - ignore cells with error. 3 - ignore blanks cells and cells with error."), - NC_("SC_OPCODE_TOCOL", "Scan by column"), - NC_("SC_OPCODE_TOCOL", "Scan the array by column. FALSE or omitted (default) - the array is scanned by row. TRUE - the array is scanned by column.") + NC_("ocTOCOL", "Transforms an array into a single column."), + NC_("ocTOCOL", "Array"), + NC_("ocTOCOL", "The range or array to return as a single column."), + NC_("ocTOCOL", "Ignore"), + NC_("ocTOCOL", "Whether to ignore certain types of values. 0 or omitted - keep all values (default). 1 - ignore blank cells. 2 - ignore cells with error. 3 - ignore blanks cells and cells with error."), + NC_("ocTOCOL", "Scan by column"), + NC_("ocTOCOL", "Scan the array by column. FALSE or omitted (default) - the array is scanned by row. TRUE - the array is scanned by column.") }; // -=*# Resource for function TOROW #*=- -const TranslateId SC_OPCODE_TOROW_ARY[] = +const TranslateId ocTOROW_ARY[] = { - NC_("SC_OPCODE_TOROW", "transforms an array into a single row."), - NC_("SC_OPCODE_TOROW", "Array"), - NC_("SC_OPCODE_TOROW", "The range or array to return as a single row."), - NC_("SC_OPCODE_TOROW", "Ignore"), - NC_("SC_OPCODE_TOROW", "Whether to ignore certain types of values. 0 or omitted - keep all values (default). 1 - ignore blank cells. 2 - ignore cells with error. 3 - ignore blanks cells and cells with error."), - NC_("SC_OPCODE_TOROW", "Scan by column"), - NC_("SC_OPCODE_TOROW", "Scan the array by column. FALSE or omitted (default) - the array is scanned by row. TRUE - the array is scanned by column.") + NC_("ocTOROW", "transforms an array into a single row."), + NC_("ocTOROW", "Array"), + NC_("ocTOROW", "The range or array to return as a single row."), + NC_("ocTOROW", "Ignore"), + NC_("ocTOROW", "Whether to ignore certain types of values. 0 or omitted - keep all values (default). 1 - ignore blank cells. 2 - ignore cells with error. 3 - ignore blanks cells and cells with error."), + NC_("ocTOROW", "Scan by column"), + NC_("ocTOROW", "Scan the array by column. FALSE or omitted (default) - the array is scanned by row. TRUE - the array is scanned by column.") }; // -=*# Resource for function UNIQUE #*=- -const TranslateId SC_OPCODE_UNIQUE_ARY[] = +const TranslateId ocUNIQUE_ARY[] = { - NC_("SC_OPCODE_UNIQUE", "Returns a list of unique values from a range or array."), - NC_("SC_OPCODE_UNIQUE", "Array"), - NC_("SC_OPCODE_UNIQUE", "The range or array from which to return unique values."), - NC_("SC_OPCODE_UNIQUE", "By col"), - NC_("SC_OPCODE_UNIQUE", "Logical value indicating how to compare data: TRUE - compares data across columns. FALSE or omitted (default) - compares data across rows."), - NC_("SC_OPCODE_UNIQUE", "Uniqueness"), - NC_("SC_OPCODE_UNIQUE", "Logical value that defines what values are considered unique: TRUE - returns values that occur only once. FALSE or omitted (default) - returns all distinct (different) values in the range or array.") + NC_("ocUNIQUE", "Returns a list of unique values from a range or array."), + NC_("ocUNIQUE", "Array"), + NC_("ocUNIQUE", "The range or array from which to return unique values."), + NC_("ocUNIQUE", "By col"), + NC_("ocUNIQUE", "Logical value indicating how to compare data: TRUE - compares data across columns. FALSE or omitted (default) - compares data across rows."), + NC_("ocUNIQUE", "Uniqueness"), + NC_("ocUNIQUE", "Logical value that defines what values are considered unique: TRUE - returns values that occur only once. FALSE or omitted (default) - returns all distinct (different) values in the range or array.") }; // -=*# Resource for function LET #*=- -const TranslateId SC_OPCODE_LET_ARY[] = +const TranslateId ocLET_ARY[] = { - NC_("SC_OPCODE_LET", "The LET function assigns names to calculation results. This allows storing intermediate calculations, values, or defining names inside a formula. These names only apply within the scope of the LET function."), - NC_("SC_OPCODE_LET", "Name 1"), - NC_("SC_OPCODE_LET", "The first name to assign. Must start with a letter. Cannot be the output of a formula or conflict with range syntax."), - NC_("SC_OPCODE_LET", "Name value "), - NC_("SC_OPCODE_LET", "Name value 1, Name value 2,... The value or calculation to assign to Name."), - NC_("SC_OPCODE_LET", "Calculation or Name "), - NC_("SC_OPCODE_LET", "A calculation that uses all names within the LET function. This must be the last argument in the LET function. Or a second Name to assign to a second Name value. If a second Name is specified, Name value 2 and Calculation or Name 3 become required.") + NC_("ocLET", "The LET function assigns names to calculation results. This allows storing intermediate calculations, values, or defining names inside a formula. These names only apply within the scope of the LET function."), + NC_("ocLET", "Name 1"), + NC_("ocLET", "The first name to assign. Must start with a letter. Cannot be the output of a formula or conflict with range syntax."), + NC_("ocLET", "Name value "), + NC_("ocLET", "Name value 1, Name value 2,... The value or calculation to assign to Name."), + NC_("ocLET", "Calculation or Name "), + NC_("ocLET", "A calculation that uses all names within the LET function. This must be the last argument in the LET function. Or a second Name to assign to a second Name value. If a second Name is specified, Name value 2 and Calculation or Name 3 become required.") }; // -=*# Resource for function WRAPCOLS #*=- -const TranslateId SC_OPCODE_WRAPCOLS_ARY[] = +const TranslateId ocWRAPCOLS_ARY[] = { - NC_("SC_OPCODE_WRAPCOLS", "Wraps the provided row or column of values by columns after a specified number of elements to form a new array."), - NC_("SC_OPCODE_WRAPCOLS", "Range"), - NC_("SC_OPCODE_WRAPCOLS", "the range to wrap."), - NC_("SC_OPCODE_WRAPCOLS", "Wrap count"), - NC_("SC_OPCODE_WRAPCOLS", "The maximum number of values for each column."), - NC_("SC_OPCODE_WRAPCOLS", "Pad with"), - NC_("SC_OPCODE_WRAPCOLS", "The value with which to pad. The default is #N/A.") + NC_("ocWRAPCOLS", "Wraps the provided row or column of values by columns after a specified number of elements to form a new array."), + NC_("ocWRAPCOLS", "Range"), + NC_("ocWRAPCOLS", "the range to wrap."), + NC_("ocWRAPCOLS", "Wrap count"), + NC_("ocWRAPCOLS", "The maximum number of values for each column."), + NC_("ocWRAPCOLS", "Pad with"), + NC_("ocWRAPCOLS", "The value with which to pad. The default is #N/A.") }; // -=*# Resource for function WRAPROWS #*=- -const TranslateId SC_OPCODE_WRAPROWS_ARY[] = +const TranslateId ocWRAPROWS_ARY[] = { - NC_("SC_OPCODE_WRAPROWS", "Wraps the provided row or column of values by rows after a specified number of elements to form a new array."), - NC_("SC_OPCODE_WRAPROWS", "Range"), - NC_("SC_OPCODE_WRAPROWS", "the range to wrap."), - NC_("SC_OPCODE_WRAPROWS", "Wrap count"), - NC_("SC_OPCODE_WRAPROWS", "The maximum number of values for each row."), - NC_("SC_OPCODE_WRAPROWS", "Pad with"), - NC_("SC_OPCODE_WRAPROWS", "The value with which to pad. The default is #N/A.") + NC_("ocWRAPROWS", "Wraps the provided row or column of values by rows after a specified number of elements to form a new array."), + NC_("ocWRAPROWS", "Range"), + NC_("ocWRAPROWS", "the range to wrap."), + NC_("ocWRAPROWS", "Wrap count"), + NC_("ocWRAPROWS", "The maximum number of values for each row."), + NC_("ocWRAPROWS", "Pad with"), + NC_("ocWRAPROWS", "The value with which to pad. The default is #N/A.") +}; + +// -=*# Resource for function ARRAYTOTEXT #*=- +const TranslateId ocARRAYTOTEXT_ARY[] = +{ + NC_("ocARRAYTOTEXT", "Returns the values of a range or array as one text string."), + NC_("ocARRAYTOTEXT", "Array"), + NC_("ocARRAYTOTEXT", "The range or array to return as text."), + NC_("ocARRAYTOTEXT", "Format"), + NC_("ocARRAYTOTEXT", "The format of the returned text. 0 or omitted - concise format, the values separated by commas (default). 1 - strict format, an array constant in braces with quoted text, comma column separators and semicolon row separators.") +}; + +// -=*# Resource for function LAMBDA #*=- +const TranslateId ocLAMBDA_ARY[] = +{ + NC_("ocLAMBDA", "Creates a custom, reusable %PRODUCTNAME function. The function accepts a set of parameters and one formula expression."), + NC_("ocLAMBDA", "Parameter 1"), + NC_("ocLAMBDA", "The name of the first parameter to the function. The name must follow the range naming rules and cannot be the output of a text formula."), + NC_("ocLAMBDA", "Formula or Parameter "), + NC_("ocLAMBDA", "An additional parameter or a formula expression. If entered as a formula, it must be the last argument of the function.") +}; + +// -=*# Resource for function ISOMITTED #*=- +const TranslateId ocIS_OMITTED_ARY[] = +{ + NC_("ocIS_OMITTED", "Reports whether a LAMBDA parameter was provided (FALSE) or omitted (TRUE). Only valid within a LAMBDA."), + NC_("ocIS_OMITTED", "Name"), + NC_("ocIS_OMITTED", "The name of the parameter to check.") }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/scstyles.hrc b/sc/inc/scstyles.hrc index f7df2db50862..357dae3b33d9 100644 --- a/sc/inc/scstyles.hrc +++ b/sc/inc/scstyles.hrc @@ -35,7 +35,7 @@ const std::pair RID_CELLSTYLEFAMILY[] = const std::pair RID_PAGESTYLEFAMILY[] = { - { NC_("RID_PAGESTYLEFAMILY", "All Styles") , SfxStyleSearchBits::All }, + { NC_("RID_PAGESTYLEFAMILY", "All Styles") , SfxStyleSearchBits::AllVisible }, { NC_("RID_PAGESTYLEFAMILY", "Hidden Styles") , SfxStyleSearchBits::Hidden }, { NC_("RID_PAGESTYLEFAMILY", "Custom Styles") , SfxStyleSearchBits::UserDefined }, { {}, SfxStyleSearchBits::Auto } diff --git a/sc/inc/segmenttree.hxx b/sc/inc/segmenttree.hxx index c980f9db56a0..24afc688e325 100644 --- a/sc/inc/segmenttree.hxx +++ b/sc/inc/segmenttree.hxx @@ -94,13 +94,23 @@ public: SCCOL mnCol2; bool mbValue; }; + class RangeIterator + { + public: + explicit RangeIterator(ScFlatBoolColSegments const& rSegs); + bool getFirst(RangeData& rRange); + bool getNext(RangeData& rRange); + + private: + ScFlatBoolColSegments const& mrSegs; + }; ScFlatBoolColSegments(SCCOL nMaxCol); ScFlatBoolColSegments(const ScFlatBoolColSegments& r); ~ScFlatBoolColSegments(); bool setTrue(SCCOL nCol1, SCCOL nCol2); bool setFalse(SCCOL nCol1, SCCOL nCol2); - bool getRangeData(SCCOL nCol, RangeData& rData); + bool getRangeData(SCCOL nCol, RangeData& rData) const; void removeSegment(SCCOL nCol1, SCCOL nCol2); void insertSegment(SCCOL nCol, SCCOL nSize); diff --git a/sc/inc/sheetlimits.hxx b/sc/inc/sheetlimits.hxx index 343d6fb4566a..302c7774468a 100644 --- a/sc/inc/sheetlimits.hxx +++ b/sc/inc/sheetlimits.hxx @@ -66,11 +66,6 @@ struct ScSheetLimits final : public salhelper::SimpleReferenceObject SCROW GetMaxRowCount() const { return mnMaxRow + 1; } // equivalent of MAXCOLCOUNT in address.hxx SCCOL GetMaxColCount() const { return mnMaxCol + 1; } - // max row number as string - const OUString& MaxRowAsString() const - { - return mnMaxRow == MAXROW ? MAXROW_STRING : MAXROW_JUMBO_STRING; - } // mac col as string ("AMJ" or "XFD") const OUString& MaxColAsString() const { diff --git a/sc/inc/sortparam.hxx b/sc/inc/sortparam.hxx index 44a8a50fbdc7..59d770f38f4b 100644 --- a/sc/inc/sortparam.hxx +++ b/sc/inc/sortparam.hxx @@ -52,10 +52,10 @@ enum class ScColorSortMode { /** Sort key state defines one way how to sort the range. * - * A range of values can be sorted in multiple way, each column a different way. + * A range of values can be sorted in multiple ways, each column a different way. * - * For example: sort column A ascending and if the column when there are same values, define that those should be - * sorted descending usign the column C. + * For example: sort column A ascending, and when there are identical values in that column, define that those should be + * sorted descending using column C. **/ struct ScSortKeyState { @@ -64,6 +64,15 @@ struct ScSortKeyState bool bAscending = true; ScColorSortMode aColorSortMode = ScColorSortMode::None; Color aColorSortColor; + + bool operator==(const ScSortKeyState& rOther) const + { + return nField == rOther.nField + && bDoSort == rOther.bDoSort + && bAscending == rOther.bAscending + && aColorSortMode == rOther.aColorSortMode + && aColorSortColor == rOther.aColorSortColor; + } }; /** Struct to hold non-data extended area, used with diff --git a/sc/inc/strings.hrc b/sc/inc/strings.hrc index 89ca3a06793a..8e64a8813caa 100644 --- a/sc/inc/strings.hrc +++ b/sc/inc/strings.hrc @@ -55,7 +55,6 @@ #define SCSTR_APDTABLE NC_("SCSTR_APDTABLE", "Append Sheet") #define SCSTR_RENAMETAB NC_("SCSTR_RENAMETAB", "Rename Sheet") #define SCSTR_SET_TAB_BG_COLOR NC_("SCSTR_SET_TAB_BG_COLOR", "Tab Color") -#define SCSTR_NO_TAB_BG_COLOR NC_("SCSTR_NO_TAB_BG_COLOR", "Default") #define SCSTR_RENAMEOBJECT NC_("SCSTR_RENAMEOBJECT", "Name Object") #define STR_INSERTGRAPHIC NC_("STR_INSERTGRAPHIC", "Insert Image") #define SCSTR_TOTAL NNC_("SCSTR_TOTAL", "One result found", "%1 results found") @@ -79,8 +78,21 @@ #define SCSTR_VALID_RANGE NC_("SCSTR_VALID_RANGE", "~Source") #define SCSTR_VALID_LIST NC_("SCSTR_VALID_LIST", "~Entries") // for dialogues: -#define SCSTR_CHARSET_USER NC_("SCSTR_CHARSET_USER", "System") -#define SCSTR_COLUMN_USER NC_("SCSTR_COLUMN_USER", "Standard;Text;Date (DMY);Date (MDY);Date (YMD);US English;Hide") +#define SCSTR_ENCODING_USER NC_("SCSTR_ENCODING_USER", "System") +// A type in the dropdown box for the column type in the CSV import dialog +#define SCSTR_COLUMN_USER_STANDARD NC_("SCSTR_COLUMN_USER", "Standard") +// A type in the dropdown box for the column type in the CSV import dialog +#define SCSTR_COLUMN_USER_TEXT NC_("SCSTR_COLUMN_USER", "Text") +// A type in the dropdown box for the column type in the CSV import dialog +#define SCSTR_COLUMN_USER_DATE_DMY NC_("SCSTR_COLUMN_USER", "Date (DMY)") +// A type in the dropdown box for the column type in the CSV import dialog +#define SCSTR_COLUMN_USER_DATE_MDY NC_("SCSTR_COLUMN_USER", "Date (MDY)") +// A type in the dropdown box for the column type in the CSV import dialog +#define SCSTR_COLUMN_USER_DATE_YMD NC_("SCSTR_COLUMN_USER", "Date (YMD)") +// A type in the dropdown box for the column type in the CSV import dialog +#define SCSTR_COLUMN_USER_US_ENGLISH NC_("SCSTR_COLUMN_USER", "US English") +// A type in the dropdown box for the column type in the CSV import dialog. Used to skip the column. +#define SCSTR_COLUMN_USER_SKIP NC_("SCSTR_COLUMN_USER", "Skip") #define SCSTR_FIELDSEP_TAB NC_("SCSTR_FIELDSEP_TAB", "Tab") #define SCSTR_FIELDSEP_SPACE NC_("SCSTR_FIELDSEP_SPACE", "space") #define SCSTR_UNDO_GRAFFILTER NC_("SCSTR_UNDO_GRAFFILTER", "Image Filter") @@ -160,7 +172,7 @@ #define SCSTR_UNDO_CELL_ANCHOR NC_("SCSTR_UNDO_CELL_ANCHOR", "Cell Anchor" ) #define SCSTR_CONDITION NC_("SCSTR_CONDITION", "Condition ") -// content description strings are also use d in ScLinkTargetsObj +// content description strings are also used in ScLinkTargetsObj #define SCSTR_CONTENT_ROOT NC_("SCSTR_CONTENT_ROOT", "Contents" ) #define SCSTR_CONTENT_TABLE NC_("SCSTR_CONTENT_TABLE", "Sheets" ) #define SCSTR_CONTENT_RANGENAME NC_("SCSTR_CONTENT_RANGENAME", "Range names" ) @@ -370,11 +382,6 @@ #define STR_MESSAGE_NODATA_IN_RANGE NC_("STR_MESSAGE_NODATA_IN_RANGE", "No data in input range.") #define STR_MESSAGE_OUTPUT_TOO_LONG NC_("STR_MESSAGE_OUTPUT_TOO_LONG", "Output is too long to write into the sheet.") #define STR_INPUT_DATA_RANGE NC_("STR_INPUT_DATA_RANGE", "Input data range") -/*infobar for allowing links to update or not*/ -#define STR_ENABLE_CONTENT NC_("STR_ENABLE_CONTENT", "Allow updating") -/*tooltip for the "Allow updating" infobar button*/ -#define STR_ENABLE_CONTENT_TOOLTIP NC_("STR_ENABLE_CONTENT_TOOLTIP", "Only allow updating if you trust this document.") -#define STR_ENABLE_CONTENT_TOOLTIP_DISABLED NC_("STR_ENABLE_CONTENT_TOOLTIP_DISABLED", "Active content is disabled in the security settings. It is not possible to allow updating.") /*Insert image dialog*/ #define STR_ANCHOR_TO_CELL NC_("STR_ANCHOR_TO_CELL", "To cell") #define STR_ANCHOR_TO_CELL_RESIZE NC_("STR_ANCHOR_TO_CELL_RESIZE", "To cell (resize with cell)") @@ -467,4 +474,14 @@ #define STR_AUTOCALC_OFF NC_("STR_AUTOCALC_OFF", "AutoCalculate: Off\nClick to enable.") +/* Table Styles */ +#define STR_TABLE_STYLE_LIGHT NC_("STR_TABLE_STYLE_LIGHT", "Table Style Light") +#define STR_TABLE_STYLE_MEDIUM NC_("STR_TABLE_STYLE_MEDIUM", "Table Style Medium") +#define STR_TABLE_STYLE_DARK NC_("STR_TABLE_STYLE_DARK", "Table Style Dark") + +/* Reference Warning Infobar */ +#define STR_REF_ERROR_TITLE NC_("STR_REF_ERROR_TITLE", "Broken References") +#define STR_REF_ERROR_MSG NC_("STR_REF_ERROR_MSG", "The deletion created reference errors in your spreadsheet. Use Undo to restore the deleted cells.") +#define STR_REF_ERROR_GOTO NC_("STR_REF_ERROR_GOTO", "Go to First Error") + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/subtotalparam.hxx b/sc/inc/subtotalparam.hxx index 3f2d904c1b8b..c7f2c463265d 100644 --- a/sc/inc/subtotalparam.hxx +++ b/sc/inc/subtotalparam.hxx @@ -71,16 +71,10 @@ struct SC_DLLPUBLIC ScSubTotalParam SCCOL& col(SCCOL n) { return subtotals()[n].first; } SCCOL col(SCCOL n) const { return subtotals()[n].first; } ScSubTotalFunc func(SCCOL n) const { return subtotals()[n].second; } - // Total Functions - std::span custfuncs() { return std::span(pCustFuncs.get(), nCustFuncs); } std::span custfuncs() const { return std::span(pCustFuncs.get(), nCustFuncs); } - SCCOL& colcust(SCCOL n) { return custfuncs()[n].first; } SCCOL colcust(SCCOL n) const { return custfuncs()[n].first; } ScTokenArray* custToken(SCCOL n) const { return custfuncs()[n].second.get(); } - // Labels - std::span sublabels() { return std::span(pSubLabels.get(), nSubLabels); } std::span sublabels() const { return std::span(pSubLabels.get(), nSubLabels); } - SCCOL& collabels(SCCOL n) { return sublabels()[n].first; } SCCOL collabels(SCCOL n) const { return sublabels()[n].first; } rtl::OUString label(SCCOL n) const { return sublabels()[n].second; } }; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 8caf02f38925..135bcb149083 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -286,6 +286,7 @@ friend class sc::ColumnSpanSet; friend class sc::RangeColumnSpanSet; friend class sc::EditTextIterator; friend class sc::FormulaGroupAreaListener; +friend class sc::TableContentCopier; public: ScTable( ScDocument& rDoc, SCTAB nNewTab, const OUString& rNewName, @@ -574,7 +575,7 @@ public: sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData, bool bAsLink, bool bColRowFlags, - bool bGlobalNamesToLocal, bool bCopyCaptions ); + ScCloneFlags nCloneFlags, bool bCopyCaptions ); void CopyCaptionsToTable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pDestTab, bool bCloneCaption ); @@ -636,9 +637,6 @@ public: void GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bIncludeOld, bool bOnlyDown ) const; - void GetBackColorArea( SCCOL& rStartCol, SCROW& rStartRow, - SCCOL& rEndCol, SCROW& rEndRow ) const; - bool GetDataAreaSubrange( ScRange& rRange ) const; bool ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow, @@ -1328,6 +1326,7 @@ private: void FillFormula( const ScFormulaCell* pSrcCell, SCCOL nDestCol, SCROW nDestRow, bool bLast ); void UpdateInsertTabAbs(SCTAB nNewPos); + void AdjustRelativeTabRefs(SCTAB nOldTab, SCTAB nNewTab, sc::TargetTabState eMode); bool GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, bool bInSel, const ScMarkData& rMark) const; bool GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, const ScMarkData& rMark ) const; @@ -1382,7 +1381,7 @@ private: * Transpose clipboard patterns * @param nCombinedStartRow start row of the combined range; * used for transposed multi range selection with row direction; - * for other cases than multi range row selection this it equal to nRow1 + * for other cases than multi range row selection this is equal to nRow1 * @param nRowDestOffset adjustment of destination row position; * used for transposed multi range row selections, otherwise 0 */ @@ -1394,7 +1393,7 @@ private: * Transpose clipboard notes * @param nCombinedStartRow start row of the combined range; * used for transposed multi range selection with row direction; - * for other cases than multi range row selection this it equal to nRow1 + * for other cases than multi range row selection this is equal to nRow1 * @param nRowDestOffset adjustment of destination row position; * used for transposed multi range row selections, otherwise 0 */ @@ -1437,7 +1436,7 @@ private: explicit VisibleDataCellIterator(const ScDocument& rDoc, ScFlatBoolRowSegments& rRowSegs, ScColumn& rColumn); /** - * Set the start row position. In case there is not visible data cell + * Set the start row position. In case there is no visible data cell * at the specified row position, it will move to the position of the * first visible data cell below that point. * diff --git a/sc/inc/tablestyle.hxx b/sc/inc/tablestyle.hxx index 81e0f9d661b7..913e78a94553 100644 --- a/sc/inc/tablestyle.hxx +++ b/sc/inc/tablestyle.hxx @@ -13,11 +13,21 @@ #include #include +#include #include "document.hxx" #include "scdllapi.h" #include "dbdata.hxx" class ScPatternAttr; +namespace model +{ +class ColorSet; +} + +namespace tools +{ +class JsonWriter; +} enum class ScTableStyleElement { @@ -84,34 +94,23 @@ public: void SetPattern(ScTableStyleElement eTableStyleElement, std::unique_ptr pPattern); - void SetTablePattern(std::unique_ptr pPattern); - void SetFirstColumnStripePattern(std::unique_ptr pPattern); - void SetSecondColumnStripePattern(std::unique_ptr pPattern); - void SetFirstRowStripePattern(std::unique_ptr pPattern); - void SetSecondRowStripePattern(std::unique_ptr pPattern); - void SetLastColumnPattern(std::unique_ptr pPattern); - void SetFirstColumnPattern(std::unique_ptr pPattern); - void SetHeaderRowPattern(std::unique_ptr pPattern); - void SetTotalRowPattern(std::unique_ptr pPattern); - void SetFirstHeaderCellPattern(std::unique_ptr pPattern); - void SetLastHeaderCellPattern(std::unique_ptr pPattern); std::map GetSetPatterns() const; - sal_Int32 GetFirstRowStripeSize() const; - sal_Int32 GetFirstColumnStripeSize() const; - sal_Int32 GetSecondRowStripeSize() const; - sal_Int32 GetSecondColumnStripeSize() const; - void SetOOXMLDefault(bool bDefault); bool IsOOXMLDefault() const; + /// Re-resolve themed colors in custom style patterns against a new ColorSet + void UpdateThemedColors(const model::ColorSet& rColorSet); + const OUString& GetName() const; const OUString& GetUIName() const; }; class SC_DLLPUBLIC ScTableStyles { + SfxBindings* mpBindings; + private: ScTableStyles(ScTableStyles const&) = delete; ScTableStyles(ScTableStyles&&) = delete; @@ -121,12 +120,19 @@ private: std::unordered_map> maTableStyles; public: - ScTableStyles(); + ScTableStyles(SfxBindings* pBindings); void AddTableStyle(std::unique_ptr pTableStyle); - void DeleteTableStyle(const OUString& rName); const ScTableStyle* GetTableStyle(const OUString& rName) const; - bool HasTableStyle() const { return maTableStyles.size() > 0; } + bool HasTableStyle() const { return !maTableStyles.empty(); } + + /// Remove all styles marked as OOXML defaults (for regeneration after theme change) + void ClearOOXMLDefaultStyles(); + + /// Update themed colors in custom (non-default) styles after a theme change + void UpdateCustomStyleThemedColors(const model::ColorSet& rColorSet); + + void generateJSON(tools::JsonWriter& rWriter) const; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/inc/textuno.hxx b/sc/inc/textuno.hxx index de9f40f81bcd..c14c9a631065 100644 --- a/sc/inc/textuno.hxx +++ b/sc/inc/textuno.hxx @@ -310,7 +310,7 @@ public: virtual ~ScEditEngineTextObj() noexcept override; void SetText( const EditTextObject& rTextObject ); - std::unique_ptr CreateTextObject(); + EditTextObject CreateTextObject(); }; // ScCellTextData: shared data between sub objects of a cell text object diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx index 996915818445..e5ec6fbeda23 100644 --- a/sc/inc/token.hxx +++ b/sc/inc/token.hxx @@ -29,9 +29,6 @@ #include "calcmacros.hxx" #include "types.hxx" -// Matrix token constants. -#define MATRIX_TOKEN_HAS_RANGE 1 - class ScJumpMatrix; class ScMatrix; struct ScSheetLimits; @@ -56,7 +53,7 @@ void DumpToken(formula::FormulaToken const & rToken); */ formula::FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, formula::FormulaToken & rTok1, formula::FormulaToken & rTok2, const ScAddress & rPos, bool bReuseDoubleRef ); -class ScSingleRefToken final : public formula::FormulaToken +class SAL_DLLPUBLIC_RTTI ScSingleRefToken final : public formula::FormulaToken { private: ScSheetLimits& mrSheetLimits; // don't use rtl::Reference to avoid ref-counting traffic @@ -64,14 +61,14 @@ private: public: ScSingleRefToken( ScSheetLimits& rLimits, const ScSingleRefData& r, OpCode e = ocPush ) : FormulaToken( formula::svSingleRef, e ), mrSheetLimits(rLimits), aSingleRef( r ) {} - virtual const ScSingleRefData* GetSingleRef() const override; - virtual ScSingleRefData* GetSingleRef() override; + const ScSingleRefData& GetSingleRef() const { return aSingleRef; } + ScSingleRefData& GetSingleRef() { return aSingleRef; } virtual bool TextEqual( const formula::FormulaToken& rToken ) const override; virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new ScSingleRefToken(*this); } }; -class ScDoubleRefToken final : public formula::FormulaToken +class SAL_DLLPUBLIC_RTTI ScDoubleRefToken final : public formula::FormulaToken { private: ScSheetLimits& mrSheetLimits; // don't use rtl::Reference to avoid ref-counting traffic @@ -79,18 +76,18 @@ private: public: ScDoubleRefToken( ScSheetLimits& rLimits, const ScComplexRefData& r, OpCode e = ocPush ) : FormulaToken( formula::svDoubleRef, e ), mrSheetLimits(rLimits), aDoubleRef( r ) {} - virtual const ScSingleRefData* GetSingleRef() const override; - virtual ScSingleRefData* GetSingleRef() override; - virtual const ScComplexRefData* GetDoubleRef() const override; - virtual ScComplexRefData* GetDoubleRef() override; - virtual const ScSingleRefData* GetSingleRef2() const override; - virtual ScSingleRefData* GetSingleRef2() override; + const ScSingleRefData& GetSingleRef() const { return aDoubleRef.Ref1; } + ScSingleRefData& GetSingleRef() { return aDoubleRef.Ref1; } + const ScComplexRefData& GetDoubleRef() const { return aDoubleRef; } + ScComplexRefData& GetDoubleRef() { return aDoubleRef; } + const ScSingleRefData& GetSingleRef2() const { return aDoubleRef.Ref2; } + ScSingleRefData& GetSingleRef2() { return aDoubleRef.Ref2; } virtual bool TextEqual( const formula::FormulaToken& rToken ) const override; virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new ScDoubleRefToken(*this); } }; -class ScMatrixToken final : public formula::FormulaToken +class SAL_DLLPUBLIC_RTTI ScMatrixToken : public formula::FormulaToken { private: ScMatrixRef pMatrix; @@ -98,10 +95,12 @@ public: ScMatrixToken( ScMatrixRef p ); ScMatrixToken( const ScMatrixToken& ); - virtual const ScMatrix* GetMatrix() const override; - virtual ScMatrix* GetMatrix() override; + SC_DLLPUBLIC const ScMatrix* GetMatrix() const; + ScMatrix* GetMatrix(); virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new ScMatrixToken(*this); } + virtual bool IsMatrixRangeToken() const { return false; } + virtual bool IsMatrixReference() const { return false; } }; /** @@ -109,26 +108,42 @@ public: * both the values in matrix form, and the range address the matrix * represents. */ -class ScMatrixRangeToken final : public formula::FormulaToken +class ScMatrixRangeToken final : public ScMatrixToken { - ScMatrixRef mpMatrix; ScComplexRefData maRef; + // The values are still the ones the cells of maRef hold. False for a matrix computed by + // an operator, which keeps the range only to say where its values sit. + bool mbReference; public: - ScMatrixRangeToken( const sc::RangeMatrix& rMat ); + ScMatrixRangeToken(sc::RangeMatrix const& rMatrix, bool bReference); ScMatrixRangeToken( const ScMatrixRangeToken& ); - virtual sal_uInt8 GetByte() const override; - virtual const ScMatrix* GetMatrix() const override; - virtual ScMatrix* GetMatrix() override; - virtual const ScComplexRefData* GetDoubleRef() const override; - virtual ScComplexRefData* GetDoubleRef() override; - virtual bool operator==( const formula::FormulaToken& rToken ) const override; + const ScComplexRefData& GetDoubleRef() const { return maRef; } virtual FormulaToken* Clone() const override; + virtual bool IsMatrixRangeToken() const override { return true; } + virtual bool IsMatrixReference() const override { return mbReference; } }; -class ScExternalSingleRefToken final : public formula::FormulaToken +class SC_DLLPUBLIC ScExternalToken : public formula::FormulaToken { sal_uInt16 mnFileId; +protected: + ScExternalToken( formula::StackVar eTypeP, OpCode e, sal_uInt16 nFileId ); +public: + ScExternalToken() = delete; + virtual ~ScExternalToken() override; + + ScExternalToken(ScExternalToken const &) = default; + ScExternalToken(ScExternalToken &&) = default; + ScExternalToken & operator =(ScExternalToken const &) = delete; // due to FormulaToken + ScExternalToken & operator =(ScExternalToken &&) = delete; // due to FormulaToken + + sal_uInt16 GetFileId() const { return mnFileId; } + virtual bool operator==( const formula::FormulaToken& rToken ) const override; +}; + +class SC_DLLPUBLIC ScExternalSingleRefToken final : public ScExternalToken +{ svl::SharedString maTabName; ScSingleRefData maSingleRef; @@ -142,17 +157,15 @@ public: ScExternalSingleRefToken & operator =(ScExternalSingleRefToken const &) = delete; // due to FormulaToken ScExternalSingleRefToken & operator =(ScExternalSingleRefToken &&) = delete; // due to FormulaToken - virtual sal_uInt16 GetIndex() const override; - virtual const svl::SharedString & GetString() const override; - virtual const ScSingleRefData* GetSingleRef() const override; - virtual ScSingleRefData* GetSingleRef() override; + const svl::SharedString & GetTableName() const { return maTabName; } + const ScSingleRefData& GetSingleRef() const { return maSingleRef; } + ScSingleRefData& GetSingleRef() { return maSingleRef; } virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new ScExternalSingleRefToken(*this); } }; -class ScExternalDoubleRefToken final : public formula::FormulaToken +class SC_DLLPUBLIC ScExternalDoubleRefToken final : public ScExternalToken { - sal_uInt16 mnFileId; svl::SharedString maTabName; // name of the first sheet ScComplexRefData maDoubleRef; @@ -166,21 +179,18 @@ public: ScExternalDoubleRefToken & operator =(ScExternalDoubleRefToken const &) = delete; // due to FormulaToken ScExternalDoubleRefToken & operator =(ScExternalDoubleRefToken &&) = delete; // due to FormulaToken - virtual sal_uInt16 GetIndex() const override; - virtual const svl::SharedString & GetString() const override; - virtual const ScSingleRefData* GetSingleRef() const override; - virtual ScSingleRefData* GetSingleRef() override; - virtual const ScSingleRefData* GetSingleRef2() const override; - virtual ScSingleRefData* GetSingleRef2() override; - virtual const ScComplexRefData* GetDoubleRef() const override; - virtual ScComplexRefData* GetDoubleRef() override; + const svl::SharedString & GetTableName() const { return maTabName; } + const ScSingleRefData& GetSingleRef() const { return maDoubleRef.Ref1; } + ScSingleRefData& GetSingleRef() { return maDoubleRef.Ref1; } + const ScSingleRefData& GetSingleRef2() const { return maDoubleRef.Ref2; } + const ScComplexRefData& GetDoubleRef() const { return maDoubleRef; } + ScComplexRefData& GetDoubleRef() { return maDoubleRef; } virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new ScExternalDoubleRefToken(*this); } }; -class ScExternalNameToken final : public formula::FormulaToken +class SAL_DLLPUBLIC_RTTI ScExternalNameToken final : public ScExternalToken { - sal_uInt16 mnFileId; svl::SharedString maName; public: @@ -193,8 +203,7 @@ public: ScExternalNameToken & operator =(ScExternalNameToken const &) = delete; // due to FormulaToken ScExternalNameToken & operator =(ScExternalNameToken &&) = delete; // due to FormulaToken - virtual sal_uInt16 GetIndex() const override; - virtual const svl::SharedString & GetString() const override; + const svl::SharedString & GetName() const { return maName; } virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new ScExternalNameToken(*this); } }; @@ -221,9 +230,8 @@ public: ScTableRefToken( const ScTableRefToken& r ); virtual ~ScTableRefToken() override; - virtual sal_uInt16 GetIndex() const override; - virtual void SetIndex( sal_uInt16 n ) override; - virtual sal_Int16 GetSheet() const override; + sal_uInt16 GetIndex() const; + void SetIndex( sal_uInt16 n ); virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new ScTableRefToken(*this); } @@ -249,9 +257,9 @@ public: ScJumpMatrixToken( std::shared_ptr p ); ScJumpMatrixToken( const ScJumpMatrixToken & ); virtual ~ScJumpMatrixToken() override; - virtual ScJumpMatrix* GetJumpMatrix() const override; + ScJumpMatrix* GetJumpMatrix() const; virtual bool operator==( const formula::FormulaToken& rToken ) const override; - virtual FormulaToken* Clone() const override { return new ScJumpMatrixToken(*this); } + virtual ScJumpMatrixToken* Clone() const override { return new ScJumpMatrixToken(*this); } }; // Only created from within the interpreter, no conversion from ScRawToken, @@ -267,10 +275,10 @@ public: explicit ScRefListToken( bool bArrayResult ) : FormulaToken( formula::svRefList ), mbArrayResult( bArrayResult ) {} bool IsArrayResult() const; - virtual const ScRefList* GetRefList() const override; - virtual ScRefList* GetRefList() override; + const ScRefList* GetRefList() const; + ScRefList* GetRefList(); virtual bool operator==( const formula::FormulaToken& rToken ) const override; - virtual FormulaToken* Clone() const override { return new ScRefListToken(*this); } + virtual ScRefListToken* Clone() const override { return new ScRefListToken(*this); } }; class ScEmptyCellToken final : public formula::FormulaToken @@ -284,8 +292,6 @@ public: bDisplayedAsString( bDisplayAsString ) {} bool IsInherited() const { return bInherited; } bool IsDisplayedAsString() const { return bDisplayedAsString; } - virtual double GetDouble() const override; - virtual const svl::SharedString & GetString() const override; virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new ScEmptyCellToken(*this); } }; @@ -293,10 +299,6 @@ public: /** Transports the result from the interpreter to the formula cell. */ class ScMatrixCellResultToken : public formula::FormulaToken { - // No non-const access implemented, silence down unxsols4 complaining about - // the public GetMatrix() hiding the one from FormulaToken. - virtual ScMatrix* GetMatrix() override; - protected: ScConstMatrixRef xMatrix; formula::FormulaConstTokenRef xUpperLeft; @@ -304,9 +306,7 @@ public: ScMatrixCellResultToken( ScConstMatrixRef pMat, const formula::FormulaToken* pUL ); ScMatrixCellResultToken( const ScMatrixCellResultToken& ); virtual ~ScMatrixCellResultToken() override; - virtual double GetDouble() const override; - virtual const svl::SharedString & GetString() const override; - virtual const ScMatrix* GetMatrix() const override; + const ScMatrix* GetMatrix() const; virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override; formula::StackVar GetUpperLeftType() const @@ -371,7 +371,7 @@ public: private: /** xUpperLeft is modifiable through SetUpperLeftDouble(), so clone it - whenever an svDouble token is assigned to. */ + whenever an svDouble token is assigned to or it is not reference counted. */ void CloneUpperLeftIfNecessary(); }; @@ -388,9 +388,9 @@ public: const OUString& GetFormula() const { return maFormula; } bool IsEmptyDisplayedAsString() const { return mbEmptyDisplayedAsString; } - virtual double GetDouble() const override; + double GetDouble() const; - virtual const svl::SharedString & GetString() const override; + const svl::SharedString & GetString() const { return maString; } virtual bool operator==( const formula::FormulaToken& rToken ) const override; virtual FormulaToken* Clone() const override { return new ScHybridCellToken(*this); } }; @@ -410,16 +410,22 @@ public: SingleDoubleRefModifier( formula::FormulaToken& rT ) { formula::StackVar eType = rT.GetType(); - if ( eType == formula::svSingleRef || eType == formula::svExternalSingleRef ) + if ( eType == formula::svSingleRef ) { - pS = rT.GetSingleRef(); + pS = &static_cast(rT).GetSingleRef(); + aDub.Ref1 = aDub.Ref2 = *pS; + pD = &aDub; + } + else if ( eType == formula::svExternalSingleRef ) + { + pS = &static_cast(rT).GetSingleRef(); aDub.Ref1 = aDub.Ref2 = *pS; pD = &aDub; } else { pS = nullptr; - pD = rT.GetDoubleRef(); + pD = &static_cast(rT).GetDoubleRef(); // coverity[uninit_member] - aDub intentionally not initialized, unnecessary because unused. } } @@ -445,10 +451,19 @@ public: const ScSingleRefData& Ref2; SingleDoubleRefProvider( const formula::FormulaToken& r ) - : Ref1( *r.GetSingleRef() ), - Ref2( (r.GetType() == formula::svDoubleRef || - r.GetType() == formula::svExternalDoubleRef) ? - r.GetDoubleRef()->Ref2 : Ref1 ) + : Ref1( r.GetType() == formula::svSingleRef + ? static_cast(r).GetSingleRef() + : r.GetType() == formula::svExternalSingleRef + ? static_cast(r).GetSingleRef() + : r.GetType() == formula::svDoubleRef + ? static_cast(r).GetSingleRef() + : static_cast(r).GetSingleRef() + ), + Ref2( r.GetType() == formula::svDoubleRef + ? static_cast(r).GetDoubleRef().Ref2 + : r.GetType() == formula::svExternalDoubleRef + ? static_cast(r).GetDoubleRef().Ref2 + : Ref1 ) {} }; diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx index 08938553ea4f..a43a577ac64e 100644 --- a/sc/inc/tokenarray.hxx +++ b/sc/inc/tokenarray.hxx @@ -39,6 +39,13 @@ struct RefUpdateResult; struct TokenStringContext; class ColRowReorderMapType; +/** If the target tab was inserted, or an existing tab was used. */ +enum class TargetTabState +{ + Existing, + Inserted, +}; + } struct ScRawToken; @@ -151,6 +158,16 @@ public: */ void AdjustAbsoluteRefs( const ScDocument& rOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCheckCopyArea ); + /** Adjust relative tab references when copying a formula to a new table. + Non-zero relative tab offsets are recalculated so they still resolve + to the original target sheet from the new position. Same-sheet + relative refs (offset 0) are not modified. + If the target tab was newly inserted, the references pointing to + tabs at or after the insertion point are additionally shifted by + one. */ + void AdjustRelativeTabRefs(SCTAB nOldTab, SCTAB nNewTab, + sc::TargetTabState eMode = sc::TargetTabState::Existing); + /** When copying a sheet-local named expression, move sheet references that point to the originating sheet to point to the new sheet instead. */ diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx index 2412a0d2b448..fc5060f2b385 100644 --- a/sc/inc/unonames.hxx +++ b/sc/inc/unonames.hxx @@ -525,7 +525,7 @@ inline constexpr OUString SC_UNO_PAGE_FTRSHARED = u"FooterIsShared"_ustr; // document settings inline constexpr OUString SC_UNO_CALCASSHOWN = u"CalcAsShown"_ustr; inline constexpr OUString SC_UNO_DEFTABSTOP = u"DefaultTabStop"_ustr; -inline constexpr OUString SC_UNO_TABSTOPDIS = u"TabStopDistance"_ustr; // is the same like the before, but only the writer name +inline constexpr OUString SC_UNO_TABSTOPDIS = u"TabStopDistance"_ustr; // same as above, but with the Writer property name inline constexpr OUString SC_UNO_IGNORECASE = u"IgnoreCase"_ustr; inline constexpr OUString SC_UNO_ITERCOUNT = u"IterationCount"_ustr; inline constexpr OUString SC_UNO_ITERENABLED = u"IsIterationEnabled"_ustr; @@ -644,6 +644,8 @@ inline constexpr OUString SC_UNO_DP_LAYOUTNAME = u"LayoutName"_ustr; inline constexpr OUString SC_UNO_DP_FIELD_SUBTOTALNAME = u"FieldSubtotalName"_ustr; inline constexpr OUString SC_UNO_DP_GRANDTOTAL_NAME = u"GrandTotalName"_ustr; inline constexpr OUString SC_UNO_DP_HAS_HIDDEN_MEMBER = u"HasHiddenMember"_ustr; +inline constexpr OUString SC_UNO_DP_MEMBER_VALUE = u"MemberValue"_ustr; +inline constexpr OUString SC_UNO_DP_MEMBER_HAS_VALUE = u"MemberHasValue"_ustr; #define SC_UNO_DP_CALCULATEDFIELD SC_UNONAME_CALCULATEDFIELD #define SC_UNO_DP_CALCULATION SC_UNONAME_CALCULATION inline constexpr OUString SC_UNO_DP_FLAGS = u"Flags"_ustr; diff --git a/sc/inc/userlist.hxx b/sc/inc/userlist.hxx index ede6e4b60ab7..69c0eed8f8ec 100644 --- a/sc/inc/userlist.hxx +++ b/sc/inc/userlist.hxx @@ -60,8 +60,7 @@ public: */ class SC_DLLPUBLIC ScUserList { - typedef std::vector DataType; - DataType maData; + std::vector maData; public: explicit ScUserList(bool initDefault = true); diff --git a/sc/qa/complex/dataPilot/_XDataPilotDescriptor.java b/sc/qa/complex/dataPilot/_XDataPilotDescriptor.java index b75267439e29..77ee6940d844 100644 --- a/sc/qa/complex/dataPilot/_XDataPilotDescriptor.java +++ b/sc/qa/complex/dataPilot/_XDataPilotDescriptor.java @@ -47,7 +47,7 @@ import lib.TestParameters; *
                                    *
                                  • 'FIELDSAMOUNT' (of type Integer): * to have number of fields
                                  • -*

                                      +*

                                    * @see com.sun.star.sheet.XDataPilotDescriptor */ public class _XDataPilotDescriptor { @@ -161,11 +161,11 @@ public class _XDataPilotDescriptor { /** * Test calls the method , checks returned value, compares - * number of fields goten from returned value and obtained by object + * number of fields gotten from returned value and obtained by object * relation 'FIELDSAMOUNT' and set property * Orientation to one of DataPilotFieldOrientation values.

                                    * Has OK status if returned value isn't null, number of fields - * goten from returned value is less than number of fields obtained by relation + * gotten from returned value is less than number of fields obtained by relation * and no exceptions were thrown.

                                    */ public boolean _getDataPilotFields(){ @@ -180,7 +180,7 @@ public class _XDataPilotDescriptor { int fieldsAmount = IA.getCount(); if (fieldsAmount < tEnvFieldsAmount) { - System.out.println("Number of fields is less than number goten by relation."); + System.out.println("Number of fields is less than number gotten by relation."); return false; } else {System.out.println("count of returned fields -- OK");} @@ -406,7 +406,7 @@ public class _XDataPilotDescriptor { e.printStackTrace(); return false ; } - System.out.println(" - FAILED (field " + fieldsNames[rem] + " was not found.") ; + System.out.println(" - FAILED (field " + fieldsNames[rem] + " was not found.)") ; return false ; } diff --git a/sc/qa/extras/color_scale_api.cxx b/sc/qa/extras/color_scale_api.cxx new file mode 100644 index 000000000000..cf2a08ae1063 --- /dev/null +++ b/sc/qa/extras/color_scale_api.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; + +namespace sc_apitest +{ +class ScColorScaleTest : public ScModelTestBase +{ +public: + ScColorScaleTest(); + + void setUp() override; + void tearDown() override; + + void testCreateColorScale2(); + void testCreateColorScale3(); + + CPPUNIT_TEST_SUITE(ScColorScaleTest); + CPPUNIT_TEST(testCreateColorScale2); + CPPUNIT_TEST(testCreateColorScale3); + CPPUNIT_TEST_SUITE_END(); + +private: + uno::Reference m_xMSF; + uno::Reference m_xDoc; + uno::Reference m_xSheets; + uno::Reference m_xSheet; + uno::Reference m_xSheetProperties; + uno::Reference m_xConditionalFormats; +}; + +ScColorScaleTest::ScColorScaleTest() + : ScModelTestBase(u"sc/qa/extras/testdocuments/"_ustr) +{ +} + +void ScColorScaleTest::setUp() +{ + ScModelTestBase::setUp(); + + createScDoc(); + + m_xMSF.set(mxComponent, uno::UNO_QUERY_THROW); + m_xDoc.set(mxComponent, uno::UNO_QUERY_THROW); + m_xSheets.set(m_xDoc->getSheets(), uno::UNO_QUERY_THROW); + m_xSheet.set(m_xSheets->getByIndex(0), uno::UNO_QUERY_THROW); + m_xSheetProperties.set(m_xSheet, uno::UNO_QUERY_THROW); + m_xConditionalFormats.set(m_xSheetProperties->getPropertyValue("ConditionalFormats"), + uno::UNO_QUERY_THROW); +} + +void ScColorScaleTest::tearDown() +{ + m_xConditionalFormats.clear(); + m_xSheetProperties.clear(); + m_xSheet.clear(); + m_xSheets.clear(); + m_xDoc.clear(); + m_xMSF.clear(); + + ScModelTestBase::tearDown(); +} + +void ScColorScaleTest::testCreateColorScale2() +{ + // Tests creating a COLORSCALE2. This should allocate two entries that we can modify. See + // tdf#171950. This also tests tdf#172333 as a side effect. + + // Set color scale conditional formatting on A1:A2 + uno::Reference xRanges( + m_xMSF->createInstance("com.sun.star.sheet.SheetCellRanges"), uno::UNO_QUERY_THROW); + table::CellRangeAddress a1a2 = { 0, 0, 0, 0, 1 }; + xRanges->addRangeAddress(a1a2, false); + m_xConditionalFormats->createByRange(xRanges); + uno::Reference xConditionalFormat + = m_xConditionalFormats->getConditionalFormats()[0]; + xConditionalFormat->createEntry(sheet::ConditionEntryType::COLORSCALE2, 0); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xConditionalFormat->getCount()); + + uno::Reference xEntry(xConditionalFormat->getByIndex(0), + uno::UNO_QUERY_THROW); + uno::Sequence> aColorScales; + CPPUNIT_ASSERT(xEntry->getPropertyValue("ColorScaleEntries") >>= aColorScales); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aColorScales.getLength()); + + aColorScales[0]->setColor(sal_Int32(COL_MAGENTA)); + aColorScales[0]->setType(sheet::ColorScaleEntryType::COLORSCALE_MIN); + + aColorScales[1]->setColor(sal_Int32(COL_BROWN)); + aColorScales[1]->setType(sheet::ColorScaleEntryType::COLORSCALE_MAX); + + // Put 50 in A1 to make a minimum value + insertStringToCell(u"A1"_ustr, u"50"); + // Put 100 in A2 to make a maximum value + insertStringToCell(u"A2"_ustr, u"100"); + + // A1 should be magenta + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 0, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 0, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 0, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_MAGENTA, aColor); + } + // A2 should be brown + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 1, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 1, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 1, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_BROWN, aColor); + } +} + +void ScColorScaleTest::testCreateColorScale3() +{ + // Tests creating a COLORSCALE3. This should allocate three entries that we can modify. See + // tdf#171950. This also tests tdf#172333 as a side effect. + + // Set color scale conditional formatting on A1:A3 + uno::Reference xRanges( + m_xMSF->createInstance("com.sun.star.sheet.SheetCellRanges"), uno::UNO_QUERY_THROW); + table::CellRangeAddress a1a3 = { 0, 0, 0, 0, 2 }; + xRanges->addRangeAddress(a1a3, false); + m_xConditionalFormats->createByRange(xRanges); + uno::Reference xConditionalFormat + = m_xConditionalFormats->getConditionalFormats()[0]; + xConditionalFormat->createEntry(sheet::ConditionEntryType::COLORSCALE3, 0); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xConditionalFormat->getCount()); + + uno::Reference xEntry(xConditionalFormat->getByIndex(0), + uno::UNO_QUERY_THROW); + uno::Sequence> aColorScales; + CPPUNIT_ASSERT(xEntry->getPropertyValue("ColorScaleEntries") >>= aColorScales); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aColorScales.getLength()); + + aColorScales[0]->setColor(sal_Int32(COL_MAGENTA)); + aColorScales[0]->setType(sheet::ColorScaleEntryType::COLORSCALE_MIN); + + aColorScales[1]->setColor(sal_Int32(COL_BROWN)); + aColorScales[1]->setType(sheet::ColorScaleEntryType::COLORSCALE_VALUE); + aColorScales[1]->setFormula("75"); + + aColorScales[2]->setColor(sal_Int32(COL_RED)); + aColorScales[2]->setType(sheet::ColorScaleEntryType::COLORSCALE_MAX); + + // Put 50 in A1 to make a minimum value + insertStringToCell(u"A1"_ustr, u"50"); + // Put 75 in A2 to make a middle value + insertStringToCell(u"A2"_ustr, u"75"); + // Put 100 in A3 to make a maximum value + insertStringToCell(u"A3"_ustr, u"100"); + + // A1 should be magenta + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 0, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 0, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 0, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_MAGENTA, aColor); + } + // A2 should be brown + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 1, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 1, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 1, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_BROWN, aColor); + } + // A3 should be red + { + ScConditionalFormat* pCondFormat = getScDoc()->GetCondFormat(0, 2, 0); + ScRefCellValue aCell(*getScDoc(), ScAddress(0, 2, 0)); + Color aColor = pCondFormat->GetData(aCell, ScAddress(0, 2, 0)).mxColorScale.value(); + CPPUNIT_ASSERT_EQUAL(COL_RED, aColor); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(ScColorScaleTest); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/qa/extras/htmlexporttest.cxx b/sc/qa/extras/htmlexporttest.cxx index b59d14802d7e..78d8929facf3 100644 --- a/sc/qa/extras/htmlexporttest.cxx +++ b/sc/qa/extras/htmlexporttest.cxx @@ -57,9 +57,26 @@ public: CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), styles.indexOf(".Default")); } + void testTdf44196_relative_href() + { + loadFromFile(u"tdf44196_relative_href.html", + { + comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML (StarCalc)"_ustr), + }); + save(TestFilter::HTML_CALC); + + htmlDocUniquePtr pDoc = parseHtml(maTempFile); + CPPUNIT_ASSERT(pDoc); + + // Without the fix in place, this test would have failed + // i.e. href attribute would have been turned into an absolute file URL + CPPUNIT_ASSERT(!getXPath(pDoc, "//a", "href").startsWith("file:")); + } + CPPUNIT_TEST_SUITE(ScHTMLExportTest); CPPUNIT_TEST(testHtmlSkipImage); CPPUNIT_TEST(testTdf155244); + CPPUNIT_TEST(testTdf44196_relative_href); CPPUNIT_TEST_SUITE_END(); }; diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx index 2fc445f25645..ad0b104c42f2 100644 --- a/sc/qa/extras/macros-test.cxx +++ b/sc/qa/extras/macros-test.cxx @@ -21,7 +21,9 @@ #include #include +#include #include +#include #include #include @@ -29,8 +31,11 @@ #include #include -#include +#include +#include #include +#include +#include #include using namespace ::com::sun::star; @@ -48,7 +53,7 @@ public: // I suppose you could say this test doesn't really belong here, OTOH // we need a full document to run the test ( it related originally to an // imported Excel VBA macro ) It's convenient and fast to unit test -// this the problem this way. Perhaps in the future there will be some sort +// the problem this way. Perhaps in the future there will be some sort // of slowcheck tests ( requiring a full document environment in the scripting // module, we could move the test there then ) - relates to fdo#67547 CPPUNIT_TEST_FIXTURE(ScMacrosTest, testMSP) @@ -465,6 +470,46 @@ CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf128218) CPPUNIT_ASSERT_EQUAL(u"Double"_ustr, aReturnValue); } +CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf102381_missing_optional_parameter) +{ + createScDoc("tdf102381_missing_optional_parameter.ods"); + ScDocument* pDoc = getScDoc(); + + // Function TestOptionalParameter(a, Optional b, Optional c) As String + // returns the concatenated parameters + pDoc->SetFormula(ScAddress(0, 0, 0), u"=TestOptionalParameter(1;2;3)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + pDoc->SetFormula(ScAddress(0, 1, 0), u"=TestOptionalParameter(1;;3)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + pDoc->SetFormula(ScAddress(0, 2, 0), u"=TestOptionalParameter(1;2)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + pDoc->SetFormula(ScAddress(0, 3, 0), u"=TestOptionalParameter(1;;)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + + CPPUNIT_ASSERT_EQUAL(u"123"_ustr, pDoc->GetString(0, 0, 0)); + // Without the fix in place, this test would have failed with: + // - Expected: 13 + // - Actual : Err:504 + // i.e. an omitted parameter did not reach the Basic function as a missing one + CPPUNIT_ASSERT_EQUAL(u"13"_ustr, pDoc->GetString(0, 1, 0)); + CPPUNIT_ASSERT_EQUAL(u"12"_ustr, pDoc->GetString(0, 2, 0)); + CPPUNIT_ASSERT_EQUAL(u"1"_ustr, pDoc->GetString(0, 3, 0)); + + // Function TestOptionalDefault(a, Optional b As String = "def") As String + // returns the concatenated parameters + pDoc->SetFormula(ScAddress(0, 4, 0), u"=TestOptionalDefault(1;)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + pDoc->SetFormula(ScAddress(0, 5, 0), u"=TestOptionalDefault(1)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + + // Without the fix in place, this test would have failed with: + // - Expected: 1def + // - Actual : Err:504 + // i.e. the default value of an omitted parameter was not applied + CPPUNIT_ASSERT_EQUAL(u"1def"_ustr, pDoc->GetString(0, 4, 0)); + CPPUNIT_ASSERT_EQUAL(u"1def"_ustr, pDoc->GetString(0, 5, 0)); +} + CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf71271) { createScDoc(); @@ -731,7 +776,7 @@ CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf107572) SCCOL startCol = 0, endCol = 4; SCROW startRow = 0, endRow = 12; - // Check autoformat has benn applied + // Check autoformat has been applied for (SCCOL col = startCol; col <= endCol; ++col) { for (SCROW row = startRow; row <= endRow; ++row) @@ -745,6 +790,40 @@ CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf107572) } } +CPPUNIT_TEST_FIXTURE(ScMacrosTest, testCool15956) +{ + // A Basic library enumerates its modules in insertion order, and that order must survive a + // save/reload unchanged: it determines the on-disk byte layout of the library index and module + // streams, which macro signatures sign over (cool#15956). + createScDoc(); + + // Deliberately non-sorted insertion order. + const OUString order[]{ u"Gamma"_ustr, u"Alpha"_ustr, u"Delta"_ustr, u"Beta"_ustr }; + + auto checkOrder = [&order](const uno::Sequence& names) { + CPPUNIT_ASSERT(std::equal(names.begin(), names.end(), std::begin(order), std::end(order))); + }; + + auto xDocScr = mxComponent.queryThrow(); + auto xLibs = xDocScr->getBasicLibraries().queryThrow(); + auto xLibrary = xLibs->createLibrary(u"TestLibrary"_ustr); + for (const OUString& rName : order) + xLibrary->insertByName(rName, uno::Any(u"Sub "_ustr + rName + u"\nEnd Sub\n"_ustr)); + + // In memory, getElementNames() must reflect insertion order. + checkOrder(xLibrary->getElementNames()); + + saveAndReload(TestFilter::ODS); + + // After the store/reload, the reloaded library keeps the same module order; + // without insertion-order preservation it came back permuted. + xDocScr = mxComponent.queryThrow(); + xLibs = xDocScr->getBasicLibraries().queryThrow(); + xLibs->loadLibrary(u"TestLibrary"_ustr); + auto xReloaded = xLibs->getByName(u"TestLibrary"_ustr).queryThrow(); + checkOrder(xReloaded->getElementNames()); +} + CPPUNIT_TEST_FIXTURE(ScMacrosTest, testShapeLayerId) { createScDoc(); @@ -998,7 +1077,7 @@ CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf47479) CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf161948NaturalSortAPI) { // Since LO 26.2 the feature natural sort is available in the API. - // Here we test, that is can be used in Basic macros. + // Here we test, that it can be used in Basic macros. createScDoc("tdf161948_NaturalSort.ods"); ScDocument* pDoc = getScDoc(); // The source has "K3", "K10", "K104", "K23", "K2" in Range A2:A6 and label in A1. diff --git a/sc/qa/extras/new_cond_format.cxx b/sc/qa/extras/new_cond_format.cxx index 91376ac41c8d..c9ae766a39b7 100644 --- a/sc/qa/extras/new_cond_format.cxx +++ b/sc/qa/extras/new_cond_format.cxx @@ -10,6 +10,9 @@ #include #include +#include +#include + #include #include #include @@ -19,6 +22,7 @@ #include #include #include +#include using namespace css; @@ -39,6 +43,7 @@ public: void testCondFormatXIndex(); void testDataBarProperties(); void testColorScaleProperties(); + void testThreadedCondFormat(); CPPUNIT_TEST_SUITE(ScConditionalFormatTest); CPPUNIT_TEST(testRequestCondFormatListFromSheet); @@ -48,6 +53,7 @@ public: CPPUNIT_TEST(testCondFormatXIndex); CPPUNIT_TEST(testDataBarProperties); CPPUNIT_TEST(testColorScaleProperties); + CPPUNIT_TEST(testThreadedCondFormat); CPPUNIT_TEST_SUITE_END(); }; @@ -431,6 +437,69 @@ void ScConditionalFormatTest::testColorScaleProperties() } } +namespace +{ +class TestThread : public salhelper::Thread +{ +public: + TestThread(const uno::Reference& xComponent, sal_Int32 nCell) + : salhelper::Thread("TestThread") + , m_xComponent(xComponent) + , m_nCell(nCell) + { + } + +protected: + void execute() override; + +private: + uno::Reference m_xComponent; + sal_Int32 m_nCell; +}; + +void TestThread::execute() +{ + uno::Reference xDoc(m_xComponent, uno::UNO_QUERY_THROW); + uno::Reference xIndex(xDoc->getSheets(), uno::UNO_QUERY_THROW); + uno::Reference xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW); + uno::Reference xCondFormats = getConditionalFormatList(xSheet); + uno::Reference xFactory(xDoc, uno::UNO_QUERY_THROW); + + // Add a conditional format to A{m_nCell} + uno::Reference xRanges( + xFactory->createInstance("com.sun.star.sheet.SheetCellRanges"), uno::UNO_QUERY_THROW); + table::CellRangeAddress a1 = { 0, m_nCell, 0, m_nCell, 0 }; + xRanges->addRangeAddress(a1, false); + xCondFormats->createByRange(xRanges); +} +} + +void ScConditionalFormatTest::testThreadedCondFormat() +{ + // Test that the API can be used from another thread without the solar mutex being held. See + // tdf#171950 comment #3. + + std::vector> aThreads; + + for (sal_Int32 i = 0; i < 10; ++i) + aThreads.emplace_back(new TestThread(mxComponent, i)); + + { + for (auto& rThread : aThreads) + rThread->launch(); + + SolarMutexReleaser aReleaser; + + for (auto& rThread : aThreads) + rThread->join(); + } + + uno::Reference xSheet = init(); + uno::Reference xCondFormats = getConditionalFormatList(xSheet); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(aThreads.size() + 4), xCondFormats->getLength()); +} + void ScConditionalFormatTest::setUp() { UnoApiTest::setUp(); diff --git a/sc/qa/extras/sccellrangesobj.cxx b/sc/qa/extras/sccellrangesobj.cxx index 337796095134..6a4df551055f 100644 --- a/sc/qa/extras/sccellrangesobj.cxx +++ b/sc/qa/extras/sccellrangesobj.cxx @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -32,6 +33,7 @@ namespace sc_apitest { class ScCellRangesObj : public UnoApiTest, public apitest::SheetCellRanges, + public apitest::XElementAccess, public apitest::XEnumerationAccess, public apitest::XFormulaQuery, public apitest::XIndent, @@ -52,6 +54,10 @@ public: // SheetCellRanges CPPUNIT_TEST(testSheetCellRangesProperties); + // XElementAccess + CPPUNIT_TEST(testGetElementType); + CPPUNIT_TEST(testHasElements); + // XEnumerationAccess CPPUNIT_TEST(testCreateEnumeration); @@ -81,6 +87,7 @@ public: ScCellRangesObj::ScCellRangesObj() : UnoApiTest(u"/sc/qa/extras/testdocuments"_ustr) + , apitest::XElementAccess(cppu::UnoType::get()) , apitest::XFormulaQuery(table::CellRangeAddress(0, 4, 1, 5, 4), table::CellRangeAddress(0, 4, 1, 5, 4)) { diff --git a/sc/qa/extras/scfunctionlistobj.cxx b/sc/qa/extras/scfunctionlistobj.cxx index 488d23f4eb21..967c0f1a2031 100644 --- a/sc/qa/extras/scfunctionlistobj.cxx +++ b/sc/qa/extras/scfunctionlistobj.cxx @@ -77,7 +77,7 @@ public: ScFunctionListObj::ScFunctionListObj() : UnoApiTest(u"/sc/qa/extras/testdocuments"_ustr) , XElementAccess(cppu::UnoType>::get()) - , XIndexAccess(418) + , XIndexAccess(427) , XNameAccess(u"IF"_ustr) , XServiceInfo(u"stardiv.StarCalc.ScFunctionListObj"_ustr, u"com.sun.star.sheet.FunctionDescriptions"_ustr) diff --git a/sc/qa/extras/scpdfexport.cxx b/sc/qa/extras/scpdfexport.cxx index b9eef4aaa512..cf6feaf2fb76 100644 --- a/sc/qa/extras/scpdfexport.cxx +++ b/sc/qa/extras/scpdfexport.cxx @@ -54,6 +54,9 @@ protected: void exportToPDFWithUnoCommands(const OUString& rRange); + void exportWholeDocumentToPDF(const std::initializer_list& filterData + = {}); + bool hasTextInPdf(const char* sText, bool& bFound); void setFont(ScFieldEditEngine& rEE, sal_Int32 nStart, sal_Int32 nEnd, @@ -166,6 +169,21 @@ void ScPDFExportTest::exportToPDFWithUnoCommands(const OUString& rRange) dispatchCommand(mxComponent, u".uno:ExportToPDF"_ustr, aDescriptor); } +void ScPDFExportTest::exportWholeDocumentToPDF( + const std::initializer_list& filterData) +{ + // Passing no "Selection" leaves the export covering every sheet of the document. + uno::Sequence aDescriptor{ + comphelper::makePropertyValue(u"FilterName"_ustr, u"calc_pdf_Export"_ustr), + comphelper::makePropertyValue(u"URL"_ustr, maTempFile.GetURL()), + comphelper::makePropertyValue(u"FilterData"_ustr, + comphelper::containerToSequence(filterData)) + }; + + uno::Reference xStorable(mxComponent, UNO_QUERY_THROW); + xStorable->storeToURL(maTempFile.GetURL(), aDescriptor); +} + void ScPDFExportTest::setFont(ScFieldEditEngine& rEE, sal_Int32 nStart, sal_Int32 nEnd, const OUString& rFontName) { @@ -188,6 +206,55 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testMediaShapeScreen_Tdf159094) exportToPDF(xModel, aRange); } +CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testHiddenSheetsWithPrintRange) +{ + std::shared_ptr pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + return; + + // Two of the four sheets are hidden, and every sheet carries a print range. + loadFromFile(u"hiddenSheetsWithPrintRange.fods"); + + exportWholeDocumentToPDF(); + + // Only the two visible sheets reach the PDF, one page each. + // Without the fix the hidden sheets were exported too, giving 4 pages. + std::unique_ptr pPdfDocument = parsePDFExport(pPDFium); + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); + + std::unique_ptr pPdfPage = pPdfDocument->openPage(0); + CPPUNIT_ASSERT_EQUAL(u"Visible1"_ustr, + pPdfPage->getObject(0)->getText(pPdfPage->getTextPage())); + + pPdfPage = pPdfDocument->openPage(1); + CPPUNIT_ASSERT_EQUAL(u"Visible2"_ustr, + pPdfPage->getObject(0)->getText(pPdfPage->getTextPage())); +} + +CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testSinglePagesWithHiddenSheets) +{ + std::shared_ptr pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + return; + + loadFromFile(u"hiddenSheetsWithPrintRange.fods"); + + exportWholeDocumentToPDF({ comphelper::makePropertyValue(u"SinglePageSheets"_ustr, true) }); + + // One page per visible sheet, in sheet order. + // Without the fix the hidden sheets were exported too, giving 4 pages. + std::unique_ptr pPdfDocument = parsePDFExport(pPDFium); + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); + + std::unique_ptr pPdfPage = pPdfDocument->openPage(0); + CPPUNIT_ASSERT_EQUAL(u"Visible sheet one"_ustr, + pPdfPage->getObject(0)->getText(pPdfPage->getTextPage())); + + pPdfPage = pPdfDocument->openPage(1); + CPPUNIT_ASSERT_EQUAL(u"Visible sheet two"_ustr, + pPdfPage->getObject(0)->getText(pPdfPage->getTextPage())); +} + CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testPopupRectangleSize_Tdf162955) { std::shared_ptr pPDFium = vcl::pdf::PDFiumLibrary::get(); @@ -204,7 +271,7 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testPopupRectangleSize_Tdf162955) exportToPDF(xModel, aRange); // Parse the export result with pdfium. - std::unique_ptr pPdfDocument = parsePDFExport(); + std::unique_ptr pPdfDocument = parsePDFExport(pPDFium); CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); // Get the first page @@ -247,7 +314,7 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testExportRange_Tdf120161) ScDocument& rDoc = xDocSh->GetDocument(); for (unsigned int r = 0; r < 1; ++r) for (unsigned int c = 0; c < 14; ++c) - rDoc.SetValue(ScAddress(c, r, 0), (r + 1) * (c + 1)); + rDoc.SetValue(c, r, 0, (r + 1) * (c + 1)); // set "Text" to H1 cell with "DejaVuSans" font ScFieldEditEngine& rEE = rDoc.GetEditEngine(); @@ -307,7 +374,7 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testExportFitToPage_Tdf103516) ScDocument& rDoc = xDocSh->GetDocument(); for (unsigned int r = 0; r < 80; ++r) for (unsigned int c = 0; c < 12; ++c) - rDoc.SetValue(ScAddress(c, r, 0), (r + 1) * (c + 1)); + rDoc.SetValue(c, r, 0, (r + 1) * (c + 1)); } // A1:G50: 2-page export @@ -710,7 +777,7 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testTdf143978) ScRange range1(0, 0, 0, 0, 1, 0); exportToPDF(xModel, range1); // Parse the export result with pdfium. - std::unique_ptr pPdfDocument = parsePDFExport(); + std::unique_ptr pPdfDocument = parsePDFExport(pPDFium); CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); // Get the first page @@ -767,7 +834,7 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testTdf120190) exportToPDF(xModel, range1); // Parse the export result with pdfium. - std::unique_ptr pPdfDocument = parsePDFExport(); + std::unique_ptr pPdfDocument = parsePDFExport(pPDFium); CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); // Get the first page @@ -818,7 +885,7 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testTdf84012) ScRange range1(0, 0, 0, 0, 0, 0); exportToPDF(xModel, range1); // Parse the export result with pdfium. - std::unique_ptr pPdfDocument = parsePDFExport(); + std::unique_ptr pPdfDocument = parsePDFExport(pPDFium); CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); // Get the first page @@ -853,7 +920,7 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testTdf78897) ScRange range1(2, 2, 0, 3, 2, 0); exportToPDF(xModel, range1); // Parse the export result with pdfium. - std::unique_ptr pPdfDocument = parsePDFExport(); + std::unique_ptr pPdfDocument = parsePDFExport(pPDFium); CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); // Get the first page @@ -870,7 +937,7 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testTdf78897) // Without the fix in place, this test would have failed with // - Expected: 11.00 11.00 // - Actual : 11.00 ### - CPPUNIT_ASSERT_EQUAL(u" 11.00 11.00"_ustr, aActualText); + CPPUNIT_ASSERT_EQUAL(u" 11.00 11.00 "_ustr, aActualText); } // just needs to not crash on export to pdf @@ -887,6 +954,12 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testForcepoint97) #if ENABLE_PDFIMPORT CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testTdf156893) { + std::shared_ptr pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + // Given a spreadsheet with a large number of rows, the whole-sheet export to PDF should export // all rows. loadFromFile(u"23000_rows.fods"); @@ -897,7 +970,7 @@ CPPUNIT_TEST_FIXTURE(ScPDFExportTest, testTdf156893) exportToPDF(xModel, range, { comphelper::makePropertyValue(u"SinglePageSheets"_ustr, true) }); // Parse the export result - auto pPdfDocument = parsePDFExport(); + auto pPdfDocument = parsePDFExport(pPDFium); CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); // Get the first page diff --git a/sc/qa/extras/scsolverobj.cxx b/sc/qa/extras/scsolverobj.cxx index b7735a7e8711..19268217748e 100644 --- a/sc/qa/extras/scsolverobj.cxx +++ b/sc/qa/extras/scsolverobj.cxx @@ -35,8 +35,10 @@ public: virtual void setUp() override; void testXSolverSettings(); +#ifdef ENABLE_COINMP void testCellAddress(const table::CellAddress& rExpected, const uno::Any& rActual); void testCellRangeAddress(const uno::Any& rExpected, const uno::Any& rActual); +#endif CPPUNIT_TEST_SUITE(ScSolverSettingsObj); CPPUNIT_TEST(testXSolverSettings); @@ -48,6 +50,7 @@ ScSolverSettingsObj::ScSolverSettingsObj() { } +#ifdef ENABLE_COINMP void ScSolverSettingsObj::testCellAddress(const table::CellAddress& rExpected, const uno::Any& rActual) { @@ -70,11 +73,12 @@ void ScSolverSettingsObj::testCellRangeAddress(const uno::Any& rExpected, const CPPUNIT_ASSERT_EQUAL(aExpectedAddress.EndRow, aActualAddress.EndRow); CPPUNIT_ASSERT_EQUAL(aExpectedAddress.EndColumn, aActualAddress.EndColumn); } +#endif // Creates a model using the XSolverSettings API checks if it is accessible via the API void ScSolverSettingsObj::testXSolverSettings() { -#ifdef ENABLE_LPSOLVE +#ifdef ENABLE_COINMP uno::Reference xDoc(mxComponent, uno::UNO_QUERY_THROW); uno::Reference xIndex(xDoc->getSheets(), uno::UNO_QUERY_THROW); uno::Reference xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW); @@ -104,7 +108,7 @@ void ScSolverSettingsObj::testXSolverSettings() xSolverModel->setConstraints(aConstraints); // Set solver engine options - xSolverModel->setEngine(u"com.sun.star.comp.Calc.LpsolveSolver"_ustr); + xSolverModel->setEngine(u"com.sun.star.comp.Calc.CoinMPSolver"_ustr); uno::Sequence aEngineOptions{ comphelper::makePropertyValue(u"Timeout"_ustr, uno::Any(static_cast(10))), comphelper::makePropertyValue(u"NonNegative"_ustr, true), @@ -116,8 +120,9 @@ void ScSolverSettingsObj::testXSolverSettings() xSolverModel->setSuppressDialog(true); xSolverModel->solve(); - // The correct solution value is 6981 (using LpsolveSolver) - CPPUNIT_ASSERT_EQUAL(static_cast(6981), xSheet->getCellByPosition(6, 6)->getValue()); + // The optimal total value for this knapsack is 6987, which fills the weight + // capacity of 1000 exactly. + CPPUNIT_ASSERT_EQUAL(static_cast(6987), xSheet->getCellByPosition(6, 6)->getValue()); // Check objective function and variable cells testCellAddress(aObjCell, xSolverModel->getObjectiveCell()); @@ -143,7 +148,7 @@ void ScSolverSettingsObj::testXSolverSettings() testCellRangeAddress(uno::Any(aRight2), aSeqConstr[1].Right); // Check solver engine options - CPPUNIT_ASSERT_EQUAL(u"com.sun.star.comp.Calc.LpsolveSolver"_ustr, xSolverModel->getEngine()); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.comp.Calc.CoinMPSolver"_ustr, xSolverModel->getEngine()); // Check solver engine options uno::Sequence aEngProps = xSolverModel->getEngineOptions(); diff --git a/sc/qa/extras/testdocuments/hiddenSheetsWithPrintRange.fods b/sc/qa/extras/testdocuments/hiddenSheetsWithPrintRange.fods new file mode 100644 index 000000000000..8255f865f49f --- /dev/null +++ b/sc/qa/extras/testdocuments/hiddenSheetsWithPrintRange.fods @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + Visible sheet one + + + + + + Hidden sheet one + + + + + + Visible sheet two + + + + + + Hidden sheet two + + + + + diff --git a/sc/qa/extras/testdocuments/tdf102381_missing_optional_parameter.ods b/sc/qa/extras/testdocuments/tdf102381_missing_optional_parameter.ods new file mode 100644 index 000000000000..5e7e4e5ff4fe Binary files /dev/null and b/sc/qa/extras/testdocuments/tdf102381_missing_optional_parameter.ods differ diff --git a/sc/qa/extras/testdocuments/tdf44196_relative_href.html b/sc/qa/extras/testdocuments/tdf44196_relative_href.html new file mode 100644 index 000000000000..2914c07d72fd --- /dev/null +++ b/sc/qa/extras/testdocuments/tdf44196_relative_href.html @@ -0,0 +1 @@ +Text diff --git a/sc/qa/extras/vba-macro-test.cxx b/sc/qa/extras/vba-macro-test.cxx index 1a9f059936e9..1db661ae9b9c 100644 --- a/sc/qa/extras/vba-macro-test.cxx +++ b/sc/qa/extras/vba-macro-test.cxx @@ -85,6 +85,8 @@ void VBAMacroTest::testMacro(std::u16string_view aFileName, const OUString& rScr if (!sFileUrl.isEmpty()) osl::File::remove(sFileUrl); } + + Scheduler::ProcessEventsToIdle(); } CPPUNIT_TEST_FIXTURE(VBAMacroTest, testSimpleCopyAndPaste) diff --git a/sc/qa/filter/html/data/html.clipboard.html b/sc/qa/filter/html/data/html.clipboard.html new file mode 100644 index 000000000000..c366b94d33f4 --- /dev/null +++ b/sc/qa/filter/html/data/html.clipboard.html @@ -0,0 +1,2 @@ +

                                    +
                                    diff --git a/sc/qa/filter/html/html.cxx b/sc/qa/filter/html/html.cxx index ee8f1ad17602..08da2dda18a4 100644 --- a/sc/qa/filter/html/html.cxx +++ b/sc/qa/filter/html/html.cxx @@ -17,12 +17,20 @@ #include #include +#include +#include #include #include +#include +#include +#include #include #include +#include +#include + using namespace com::sun::star; namespace @@ -188,8 +196,8 @@ CPPUNIT_TEST_FIXTURE(Test, testPasteSingleCell) // Given a document with '1' in A1 and '2' in B1: createScDoc(); ScDocument* pDoc = getScDoc(); - pDoc->SetValue(ScAddress(0, 0, 0), 1.0); - pDoc->SetValue(ScAddress(1, 0, 0), 2.0); + pDoc->SetValue(0, 0, 0, 1.0); + pDoc->SetValue(1, 0, 0, 2.0); // When pasting SUM(A1:B1) into C1: ScAddress aCellPos(/*nColP=*/2, /*nRowP=*/0, /*nTabP=*/0); @@ -223,7 +231,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf79298_strikeout_variants) // Verify HTML strikeout tags (, , and ) for (size_t nCol = 0; nCol < 3; ++nCol) { - const ScPatternAttr* pAttr = pDoc->GetPattern(ScAddress(0, nCol, 0)); + const ScPatternAttr* pAttr = pDoc->GetPattern(0, nCol, 0); CPPUNIT_ASSERT_MESSAGE("Failed to get cell attribute.", pAttr); const SvxCrossedOutItem& rCrossedOutItem = pAttr->GetItem(ATTR_FONT_CROSSEDOUT); CPPUNIT_ASSERT_EQUAL(FontStrikeout::STRIKEOUT_SINGLE, rCrossedOutItem.GetStrikeout()); @@ -242,7 +250,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf132770_inserted_text) // Verify HTML inserted text tag ScDocument* pDoc = getScDoc(); - const ScPatternAttr* pAttr = pDoc->GetPattern(ScAddress(0, 0, 0)); + const ScPatternAttr* pAttr = pDoc->GetPattern(0, 0, 0); CPPUNIT_ASSERT_MESSAGE("Failed to get cell attribute.", pAttr); const SvxUnderlineItem& rUnderlineItem = pAttr->GetItem(ATTR_FONT_UNDERLINE); // Without the accompanying fix in place, this tests would have failed with: @@ -360,6 +368,83 @@ CPPUNIT_TEST_FIXTURE(Test, testCopyFormula) // i.e. only the formula result was exported, not the formula. assertXPath(pHtmlDoc, "(//td)[3]", "data-sheets-formula", u"=SUM(R[-2]C:R[-1]C)"); } + +CPPUNIT_TEST_FIXTURE(Test, testHTMLEmbeddedImagePaste) +{ + class HTMLTransferable : public comphelper::WeakImplHelper + { + public: + HTMLTransferable(const OUString& url) + : m_aFileURL(url) + { + } + + // XTransferable + uno::Any SAL_CALL getTransferData(const datatransfer::DataFlavor& aFlavor) override + { + if (!isDataFlavorSupported(aFlavor)) + return {}; + SvFileStream aStream(m_aFileURL, StreamMode::READ); + uno::Sequence bytes(aStream.remainingSize()); + aStream.ReadBytes(bytes.getArray(), aStream.remainingSize()); + return uno::Any(bytes); + } + uno::Sequence SAL_CALL getTransferDataFlavors() override + { + return { getHTMLFlavor() }; + } + sal_Bool SAL_CALL isDataFlavorSupported(const datatransfer::DataFlavor& aFlavor) override + { + return aFlavor.MimeType.equalsIgnoreAsciiCase(getHTMLFlavor().MimeType); + } + + private: + OUString m_aFileURL; + + static datatransfer::DataFlavor getHTMLFlavor() + { + datatransfer::DataFlavor ret; + CPPUNIT_ASSERT(SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML, ret)); + return ret; + } + }; + + createScDoc(); + ScDocument& rDoc = *getScDoc(); + // Put HTML with embedded image data into system clipboard: + auto xContext(comphelper::getProcessComponentContext()); + auto xClipboard = xContext->getServiceManager() + ->createInstanceWithContext( + u"com.sun.star.datatransfer.clipboard.SystemClipboard"_ustr, xContext) + .queryThrow(); + xClipboard->setContents(new HTMLTransferable(createFileURL(u"html.clipboard.html")), {}); + + dispatchCommand(mxComponent, u".uno:Paste"_ustr, {}); + + ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); + CPPUNIT_ASSERT(pDrawLayer); + + const SdrPage* pPage = pDrawLayer->GetPage(0); + CPPUNIT_ASSERT(pPage); + + SdrGrafObj* pObject = dynamic_cast(pPage->GetObj(0)); + CPPUNIT_ASSERT(pObject); + CPPUNIT_ASSERT(!pObject->IsLinkedGraphic()); + + const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true); + const Graphic& rGraphic = rGraphicObj.GetGraphic(); + CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphic.GetType())); + CPPUNIT_ASSERT_EQUAL(sal_uLong(16848), rGraphic.GetSizeBytes()); + + const Bitmap& rBitmap = rGraphic.GetBitmapRef(); + const Color aBorderColor = rBitmap.GetPixelColor(4, 4); + Color aExpectedBorderColor(0x00, 0x00, 0x00); + CPPUNIT_ASSERT_EQUAL(aExpectedBorderColor, aBorderColor); + + const Color aFillColor = rBitmap.GetPixelColor(20, 20); + Color aExpectedFillColor(0xff, 0x00, 0x00); + CPPUNIT_ASSERT_EQUAL(aExpectedFillColor, aFillColor); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/qa/uitest/calc_dialogs/openDialogs.py b/sc/qa/uitest/calc_dialogs/openDialogs.py index 9f26dc91f50b..604ec26f0323 100644 --- a/sc/qa/uitest/calc_dialogs/openDialogs.py +++ b/sc/qa/uitest/calc_dialogs/openDialogs.py @@ -55,7 +55,7 @@ dialogs = [ # {"command": ".uno:SetOptimalColumnWidth", "closeButton": "cancel"}, # tested in sc/qa/uitest/textToColumns/tdf89907.py # {"command": ".uno:PageFormatDialog", "closeButton": "cancel"}, - # tested in sc/qa/uitest/pageFormat/tdf123508.py + # tested in sc/qa/uitest/pageFormat/tdf123508_format_page_scale.py {"command": ".uno:EditPrintArea", "closeButton": "cancel", "skipTestOK": True}, # tested in sc/qa/uitest/calc_tests/printRange.py # {"command": ".uno:ConditionalFormatMenu", "closeButton": "cancel"}, @@ -93,7 +93,7 @@ dialogs = [ # tested in sc/qa/uitest/calc_tests/sheetRename.py # {"command": ".uno:Move", "closeButton": "cancel"}, # tested in sc/qa/uitest/calc_tests6/moveCopySheet.py - {"command": ".uno:SetTabBgColor", "closeButton": "cancel"}, + {"command": ".uno:SetTabBgColor", "closeButton": "close", "skipTestOK": True}, {"command": ".uno:TableEvents", "closeButton": "cancel"}, # {"command": ".uno:DataSort", "closeButton": "cancel"}, # cancel button tested in sc/qa/uitest/calc_tests/sorting.py diff --git a/sc/qa/uitest/calc_tests/CellDropDownItems.py b/sc/qa/uitest/calc_tests/CellDropDownItems.py index 86fceeca2f9a..5810bc5c665a 100644 --- a/sc/qa/uitest/calc_tests/CellDropDownItems.py +++ b/sc/qa/uitest/calc_tests/CellDropDownItems.py @@ -15,22 +15,22 @@ class CellDropDownItems(UITestCase): def test_dropdownitems(self): - #This is to test Dropdown items in grid window + # This is to test Dropdown items in grid window with self.ui_test.create_doc_in_start_center("calc") as document: xCalcDoc = self.xUITest.getTopFocusWindow() gridwin = xCalcDoc.getChild("grid_window") - #select cell C10 + # select cell C10 gridwin.executeAction("SELECT", mkPropertyValues({"CELL": "C10"})) - #Open Validation Dialog + # Open Validation Dialog with self.ui_test.execute_dialog_through_command(".uno:Validation") as xDialog: - #Select List option + # Select List option xallow = xDialog.getChild("allow") select_pos(xallow, "6") - #Add items to the List + # Add items to the List xminlist = xDialog.getChild("minlist") xminlist.executeAction("TYPE", mkPropertyValues({"TEXT": "Item1"})) xminlist.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) @@ -42,13 +42,13 @@ class CellDropDownItems(UITestCase): xminlist.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) xminlist.executeAction("TYPE", mkPropertyValues({"TEXT": "Item5"})) - #Close the dialog + # Close the dialog - #Launch the Select Menu to view the list ans select first item in the list + # Launch the Select Menu to view the list and select the first item in the list gridwin = xCalcDoc.getChild("grid_window") gridwin.executeAction("LAUNCH", mkPropertyValues({"SELECTMENU": "", "COL": "2", "ROW": "9"})) - #Select the TreeList UI Object + # Select the TreeList UI Object xWin = self.xUITest.getTopFocusWindow() xlist = xWin.getChild("list") @@ -56,11 +56,11 @@ class CellDropDownItems(UITestCase): xListItem.executeAction("DOUBLECLICK" , mkPropertyValues({}) ) self.assertEqual(get_cell_by_position(document, 0, 2, 9).getString(), "Item1") - #Launch the Select Menu to view the list ans select Third item in the list + # Launch the Select Menu to view the list and select the third item in the list gridwin = xCalcDoc.getChild("grid_window") gridwin.executeAction("LAUNCH", mkPropertyValues({"SELECTMENU": "", "COL": "2", "ROW": "9"})) - #Select the TreeList UI Object + # Select the TreeList UI Object xWin = self.xUITest.getTopFocusWindow() xlist = xWin.getChild("list") @@ -68,7 +68,7 @@ class CellDropDownItems(UITestCase): xListItem.executeAction("DOUBLECLICK" , mkPropertyValues({}) ) self.assertEqual(get_cell_by_position(document, 0, 2, 9).getString(), "Item3") - #Launch the Select Menu to view the list ans select Fifth item in the list + # Launch the Select Menu to view the list and select the fifth item in the list gridwin = xCalcDoc.getChild("grid_window") gridwin.executeAction("LAUNCH", mkPropertyValues({"SELECTMENU": "", "COL": "2", "ROW": "9"})) diff --git a/sc/qa/uitest/calc_tests/cellBackgroundColorSelector.py b/sc/qa/uitest/calc_tests/cellBackgroundColorSelector.py index 1839545c7e88..5b3cd63ca4f8 100644 --- a/sc/qa/uitest/calc_tests/cellBackgroundColorSelector.py +++ b/sc/qa/uitest/calc_tests/cellBackgroundColorSelector.py @@ -33,108 +33,90 @@ class CalcCellBackgroundColorSelector(UITestCase): # Now we have the ColorPage that we can get the color selector from it xColorpage = xDialog.getChild("ColorPage") - color_selector = xColorpage.getChild("colorset") + color_selector = xColorpage.getChild("coloriconview") # For chart-palettes colors select_by_text(xpaletteselector, "Chart Palettes") - # Select Color with id 2 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "2"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "2") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "1") - self.assertEqual(get_state_as_dict(color_selector)["ColorsCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Chart 2") - self.assertEqual(get_state_as_dict(color_selector)["RGB"], "(255,66,14)") + # Select Color at index 1 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "1"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "1") + self.assertEqual(get_state_as_dict(color_selector)["Children"], "12") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Chart 2") + # ID is the RGB color value in hex + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemId"], "FF420E") - # Select Color with id 5 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "5"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "5") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "4") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Chart 5") - self.assertEqual(get_state_as_dict(color_selector)["RGB"], "(126,0,33)") + # Select Color at index 4 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "4"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "4") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Chart 5") + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemId"], "7E0021") # For libreoffice colors select_by_text(xpaletteselector, "LibreOffice") - # Select Color with id 6 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "6"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "6") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "5") - self.assertEqual(get_state_as_dict(color_selector)["ColorsCount"], "32") - self.assertEqual(get_state_as_dict(color_selector)["ColCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Green Accent") - self.assertEqual(get_state_as_dict(color_selector)["RGB"], "(44,238,14)") + # Select Color at index 5 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "5"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "5") + self.assertEqual(get_state_as_dict(color_selector)["Children"], "32") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Green Accent") + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemId"], "2CEE0E") - # Select Color with id 30 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "30"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "30") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "29") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Yellow Accent") - self.assertEqual(get_state_as_dict(color_selector)["RGB"], "(255,215,76)") + # Select Color at index 29 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "29"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "29") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Yellow Accent") + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemId"], "FFD74C") # For html colors select_by_text(xpaletteselector, "HTML") - # Select Color with id 1 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "1"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "1") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "0") - self.assertEqual(get_state_as_dict(color_selector)["ColorsCount"], "139") - self.assertEqual(get_state_as_dict(color_selector)["ColCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "White") - # Select Color with id 120 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "120"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "120") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "119") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Navy") + # Select Color at index 0 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "0"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "0") + self.assertEqual(get_state_as_dict(color_selector)["Children"], "139") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "White") + # Select Color at index 119 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "119"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "119") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Navy") # For freecolour-hlc colors select_by_text(xpaletteselector, "Freecolour HLC") - # Select Color with id 988 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "988"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "988") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "987") - self.assertEqual(get_state_as_dict(color_selector)["ColorsCount"], "1032") - self.assertEqual(get_state_as_dict(color_selector)["ColCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "HLC 350 60 10") - # Select Color with id 575 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "575"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "575") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "574") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "HLC 190 50 20") + # Select Color at index 987 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "987"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "987") + self.assertEqual(get_state_as_dict(color_selector)["Children"], "1032") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "HLC 350 60 10") + # Select Color at index 574 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "574"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "574") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "HLC 190 50 20") # For tonal colors select_by_text(xpaletteselector, "Tonal") - # Select Color with id 17 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "17"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "17") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "16") - self.assertEqual(get_state_as_dict(color_selector)["ColorsCount"], "120") - self.assertEqual(get_state_as_dict(color_selector)["ColCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Cyan 82%") - # Select Color with id 13 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "13"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "13") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Magenta 82%") + # Select Color at index 16 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "16"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "16") + self.assertEqual(get_state_as_dict(color_selector)["Children"], "120") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Cyan 82%") + # Select Color at index 12 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "12"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "12") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Magenta 82%") # For material colors select_by_text(xpaletteselector, "Material") - # Select Color with id 9 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "9"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "9") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "8") - self.assertEqual(get_state_as_dict(color_selector)["ColorsCount"], "228") - self.assertEqual(get_state_as_dict(color_selector)["ColCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Gray 800") + # Select Color at index 8 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "8"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "8") + self.assertEqual(get_state_as_dict(color_selector)["Children"], "228") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Gray 800") # For standard colors select_by_text(xpaletteselector, "Standard") - # Select Color with id 3 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "3"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "3") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "2") - self.assertEqual(get_state_as_dict(color_selector)["ColorsCount"], "120") - self.assertEqual(get_state_as_dict(color_selector)["ColCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Dark Gray 3") + # Select Color at index 2 + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "2"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "2") + self.assertEqual(get_state_as_dict(color_selector)["Children"], "120") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Dark Gray 3") @@ -158,18 +140,17 @@ class CalcCellBackgroundColorSelector(UITestCase): # recent color selector xpaletteselector = xDialog.getChild("paletteselector") xColorpage = xDialog.getChild("ColorPage") - color_selector = xColorpage.getChild("colorset") + color_selector = xColorpage.getChild("coloriconview") # For chart-palettes colors select_by_text(xpaletteselector, "Chart Palettes") - # Select Color with id 2 - color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "2"})) - self.assertEqual(get_state_as_dict(color_selector)["CurrColorId"], "2") - self.assertEqual(get_state_as_dict(color_selector)["CurrColorPos"], "1") - self.assertEqual(get_state_as_dict(color_selector)["ColorsCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColCount"], "12") - self.assertEqual(get_state_as_dict(color_selector)["ColorText"], "Chart 2") - xrgb = get_state_as_dict(color_selector)["RGB"] + # Select Color at index 1 and press Enter to activate + color_selector.executeAction("SELECT", mkPropertyValues({"POS": "1"})) + color_selector.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) + self.assertEqual(get_state_as_dict(color_selector)["SelectedItemPos"], "1") + self.assertEqual(get_state_as_dict(color_selector)["Children"], "12") + self.assertEqual(get_state_as_dict(color_selector)["SelectedEntryTooltip"], "Chart 2") + xrgb = get_state_as_dict(color_selector)["SelectedItemId"] # close the dialog after selection of the color @@ -184,14 +165,13 @@ class CalcCellBackgroundColorSelector(UITestCase): xbtncolor.executeAction("CLICK",tuple()) xColorpage = xDialog.getChild("ColorPage") - recent_color_selector = xColorpage.getChild("recentcolorset") + recent_color_selector = xColorpage.getChild("recentcoloriconview") # Select Color with id 1 - recent_color_selector.executeAction("CHOOSE", mkPropertyValues({"POS": "1"})) - self.assertEqual(get_state_as_dict(recent_color_selector)["CurrColorId"], "1") - self.assertEqual(get_state_as_dict(recent_color_selector)["CurrColorPos"], "0") - self.assertEqual(get_state_as_dict(recent_color_selector)["ColorText"], "Chart 2") - self.assertEqual(get_state_as_dict(recent_color_selector)["RGB"], xrgb) + recent_color_selector.executeAction("SELECT", mkPropertyValues({"POS": "0"})) + self.assertEqual(get_state_as_dict(recent_color_selector)["SelectedItemPos"], "0") + self.assertEqual(get_state_as_dict(recent_color_selector)["SelectedEntryTooltip"], "Chart 2") + self.assertEqual(get_state_as_dict(recent_color_selector)["SelectedItemId"], xrgb) diff --git a/sc/qa/uitest/calc_tests/formatCells.py b/sc/qa/uitest/calc_tests/formatCells.py index 1c1c39646082..07ad57fabbca 100644 --- a/sc/qa/uitest/calc_tests/formatCells.py +++ b/sc/qa/uitest/calc_tests/formatCells.py @@ -261,21 +261,23 @@ class formatCell(UITestCase): select_pos(xTabs, "5") #tab Borders linewidthmf = xDialog.getChild("linewidthmf") - xLineSet = xDialog.getChild('lineset') + lineTreeView = xDialog.getChild('linetreeview') # check line-width for default solid line - self.assertEqual('0', get_state_as_dict(xLineSet)['SelectedItemPos']) + self.assertEqual('0', get_state_as_dict(lineTreeView)['SelectedItemPos']) widthVal = get_state_as_dict(linewidthmf)["Text"] self.assertEqual(widthVal, '0.75 pt') # set line style to "double" (minimal width is taken) - xLineSet.executeAction("CHOOSE", mkPropertyValues({"POS": '16'})) + lineTreeView.executeAction("SELECT", mkPropertyValues({"POS": '6'})) + lineTreeView.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) widthVal = get_state_as_dict(linewidthmf)["Text"] # minimum predefined width is Medium (1.50 pt) self.assertEqual(widthVal, '1.50 pt') # set line style to "solid" - xLineSet.executeAction("CHOOSE", mkPropertyValues({"POS": "1"})) + lineTreeView.executeAction("SELECT", mkPropertyValues({"POS": "0"})) + lineTreeView.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) widthVal = get_state_as_dict(linewidthmf)["Text"] self.assertEqual(widthVal, '1.50 pt') @@ -287,7 +289,8 @@ class formatCell(UITestCase): self.assertEqual(widthVal, '2.25 pt') # set line style to "double" (minimal width is not taken) - xLineSet.executeAction("CHOOSE", mkPropertyValues({"POS": "8"})) + lineTreeView.executeAction("SELECT", mkPropertyValues({"POS": "6"})) + lineTreeView.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) widthVal = get_state_as_dict(linewidthmf)["Text"] self.assertEqual(widthVal, '2.25 pt') diff --git a/sc/qa/uitest/calc_tests4/tdf129162_singlepagesheets_disables_range_options.py b/sc/qa/uitest/calc_tests4/tdf129162_singlepagesheets_disables_range_options.py new file mode 100644 index 000000000000..95133a9906bc --- /dev/null +++ b/sc/qa/uitest/calc_tests4/tdf129162_singlepagesheets_disables_range_options.py @@ -0,0 +1,42 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# +#from uitest.framework import UITestCase +#from uitest.uihelper.common import get_state_as_dict +#from libreoffice.uno.propertyvalue import mkPropertyValues + +import os +from tempfile import TemporaryDirectory + +from uitest.framework import UITestCase +from uitest.uihelper.calc import enter_text_to_cell +from uitest.uihelper.common import get_state_as_dict +from libreoffice.uno.propertyvalue import mkPropertyValues +from org.libreoffice.unotest import systemPathToFileUrl + +class tdf129162(UITestCase): + def test_singlePageSheetsDisablesRangeOptions(self): + with self.ui_test.create_doc_in_start_center("calc"): + with self.ui_test.execute_dialog_through_command('.uno:ExportToPDF', close_button="cancel") as xDialog: + rangeChildren = ['all', 'pagerange', 'sheetrange', 'selection'] + + self.assertEqual("false", get_state_as_dict(xDialog.getChild('singlepagesheets'))['Selected']) + for child in rangeChildren: + self.assertEqual("true", get_state_as_dict(xDialog.getChild(child))['Enabled']) + + xDialog.getChild('singlepagesheets').executeAction('CLICK', mkPropertyValues({})) + self.assertEqual("true", get_state_as_dict(xDialog.getChild('singlepagesheets'))['Selected']) + for child in rangeChildren: + self.assertEqual("false", get_state_as_dict(xDialog.getChild(child))['Enabled']) + + xDialog.getChild('singlepagesheets').executeAction('CLICK', mkPropertyValues({})) + self.assertEqual("false", get_state_as_dict(xDialog.getChild('singlepagesheets'))['Selected']) + for child in rangeChildren: + self.assertEqual("true", get_state_as_dict(xDialog.getChild(child))['Enabled']) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/qa/uitest/calc_tests7/tdf_173269_crash_with_color_in_cell_format.py b/sc/qa/uitest/calc_tests7/tdf_173269_crash_with_color_in_cell_format.py new file mode 100644 index 000000000000..12077cf7114d --- /dev/null +++ b/sc/qa/uitest/calc_tests7/tdf_173269_crash_with_color_in_cell_format.py @@ -0,0 +1,33 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# +from uitest.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues +from libreoffice.calc.document import get_cell_by_position +from uitest.uihelper.calc import enter_text_to_cell + +class tdf173269(UITestCase): + def test_tdf173269_crash_with_color_in_cell_format(self): + + with self.ui_test.create_doc_in_start_center("calc") as calc_doc: + xCalcDoc = self.xUITest.getTopFocusWindow() + gridwin = xCalcDoc.getChild("grid_window") + + enter_text_to_cell(gridwin, "A1", "-400.02") + + with self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") as xDialog: + xformatted = xDialog.getChild("formatted") + + xformatted.executeAction("CLEAR", tuple()) + + # Without the fix in place, this test would have crashed here + xformatted.executeAction("TYPE", mkPropertyValues({"TEXT":"#.##0,00 €;[COLOR 10]-#.##0,00 €"})) + + self.assertEqual("-400.02000 €", get_cell_by_position(calc_doc, 0, 0, 0).getString()) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/qa/uitest/calc_tests8/dataProvider.py b/sc/qa/uitest/calc_tests8/dataProvider.py index 9f5b1be5bbb4..b40de499b84d 100644 --- a/sc/qa/uitest/calc_tests8/dataProvider.py +++ b/sc/qa/uitest/calc_tests8/dataProvider.py @@ -150,6 +150,8 @@ class DataProvider(UITestCase): xFileName.executeAction('TYPE', mkPropertyValues({'TEXT': xFilePath})) with self.ui_test.load_file(systemPathToFileUrl(xFilePath)) as doc2: + xAllow = self.ui_test.wait_until_child_is_available("allowupdating") + xAllow.executeAction("CLICK", tuple()) # Without the fix in place, this test would have failed with # AssertionError: 'Rank' != 'Rank|Males|Females\r' self.assertEqual("Rank", get_cell_by_position(doc2, 0, 0, 0).getString()) diff --git a/sc/qa/uitest/chart2/correlationCircle.py b/sc/qa/uitest/chart2/correlationCircle.py new file mode 100644 index 000000000000..21f44b9ffc8a --- /dev/null +++ b/sc/qa/uitest/chart2/correlationCircle.py @@ -0,0 +1,125 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- +# +# Copyright the LibreOffice contributors. +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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/. +# +from uitest.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict +from uitest.uihelper.chart import select_chart_type + +from libreoffice.uno.propertyvalue import mkPropertyValues + +FEATURES = ["length", "width", "span", "mass"] +DIMENSIONS = ["dim 1", "dim 2"] +INSTANCE_COUNT = 8 +RANGE = "$Sheet1.$A$1:$F$9" + + +class correlationCircle(UITestCase): + def fill_sheet(self, document): + sheet = document.Sheets[0] + for column, name in enumerate(FEATURES + DIMENSIONS): + sheet.getCellByPosition(column, 0).setString(name) + + for row in range(INSTANCE_COUNT): + for column in range(len(FEATURES)): + sheet.getCellByPosition(column, row + 1).setValue(row + column * 3 + 1) + for column in range(len(DIMENSIONS)): + sheet.getCellByPosition(len(FEATURES) + column, row + 1).setValue( + (row + 1) * (column + 1) * 0.25) + + def replace_text(self, xEntry, rText): + xEntry.executeAction("TYPE", mkPropertyValues({"KEYCODE": "CTRL+A"})) + xEntry.executeAction("TYPE", mkPropertyValues({"KEYCODE": "BACKSPACE"})) + xEntry.executeAction("TYPE", mkPropertyValues({"TEXT": rText})) + + def insert_correlation_circle(self, document): + with self.ui_test.execute_dialog_through_command( + ".uno:InsertObjectChart", close_button="finish") as xChartDlg: + select_chart_type(self, xChartDlg, "Correlation Circle") + + # The second wizard step holds the range. + xChartDlg.getChild("next").executeAction("CLICK", tuple()) + self.replace_text(xChartDlg.getChild("ED_RANGE"), RANGE) + + # Every column of the range before the last two is a feature, so + # the first one is not a column of instance names. + xFirstColumnAsLabel = xChartDlg.getChild("CB_FIRST_COLUMN_ASLABELS") + if get_state_as_dict(xFirstColumnAsLabel)["Selected"] == "true": + xFirstColumnAsLabel.executeAction("CLICK", tuple()) + + def roles_of_series(self, document): + xChartType = document.Sheets[0].Charts[0].getEmbeddedObject() \ + .getFirstDiagram().CoordinateSystems[0].ChartTypes[0] + return [[(sequence.getValues().Role, + sequence.getValues().getSourceRangeRepresentation()) + for sequence in series.getDataSequences()] + for series in xChartType.DataSeries] + + # The last two columns of the range hold the dimensions and every column + # before them becomes a series holding that column beside those two. + def test_correlation_circle_one_range(self): + with self.ui_test.create_doc_in_start_center("calc") as document: + self.fill_sheet(document) + self.insert_correlation_circle(document) + + aRolesPerSeries = self.roles_of_series(document) + + self.assertEqual(len(FEATURES), len(aRolesPerSeries)) + for index, aRoles in enumerate(aRolesPerSeries): + aColumn = chr(ord("A") + index) + self.assertEqual( + [("values-x", "$Sheet1.$E$2:$E$9"), + ("values-y", "$Sheet1.$F$2:$F$9"), + ("values-feature", "$Sheet1.$%s$2:$%s$9" % (aColumn, aColumn))], + aRoles) + + # Reopening the ranges of such a chart shows the range it was given. + def test_the_range_comes_back(self): + with self.ui_test.create_doc_in_start_center("calc") as document: + self.fill_sheet(document) + self.insert_correlation_circle(document) + + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + xGridWindow.executeAction("SELECT", mkPropertyValues({"OBJECT": "Object 1"})) + xGridWindow.executeAction("ACTIVATE", tuple()) + xChartWindow = self.xUITest.getTopFocusWindow().getChild("chart_window") + + with self.ui_test.execute_dialog_through_action( + xChartWindow.getChild("CID/Page="), "COMMAND", + mkPropertyValues({"COMMAND": "DataRanges"}), + close_button="cancel") as xRangesDlg: + self.assertEqual( + RANGE, get_state_as_dict(xRangesDlg.getChild("ED_RANGE"))["Text"]) + + # Leave the chart, so that the document closes the way it would + # after any other edit. + xChartWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE": "ESC"})) + + # The note about the last two columns belongs to this chart type alone. + def test_the_note_is_shown_only_for_this_type(self): + with self.ui_test.create_doc_in_start_center("calc") as document: + self.fill_sheet(document) + + with self.ui_test.execute_dialog_through_command( + ".uno:InsertObjectChart", close_button="cancel") as xChartDlg: + select_chart_type(self, xChartDlg, "Bar") + xChartDlg.getChild("next").executeAction("CLICK", tuple()) + self.assertEqual( + "false", + get_state_as_dict(xChartDlg.getChild("FT_RANGE_NOTE"))["Visible"]) + + xChartDlg.getChild("previous").executeAction("CLICK", tuple()) + select_chart_type(self, xChartDlg, "Correlation Circle") + xChartDlg.getChild("next").executeAction("CLICK", tuple()) + self.assertEqual( + "true", + get_state_as_dict(xChartDlg.getChild("FT_RANGE_NOTE"))["Visible"]) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/qa/uitest/data/tdf169110.ods b/sc/qa/uitest/data/tdf169110.ods new file mode 100644 index 000000000000..bb158058554f Binary files /dev/null and b/sc/qa/uitest/data/tdf169110.ods differ diff --git a/sc/qa/uitest/inputLine/tdf97354_formula_bar_visible_ref_dialog.py b/sc/qa/uitest/inputLine/tdf97354_formula_bar_visible_ref_dialog.py new file mode 100644 index 000000000000..afe0de929f0f --- /dev/null +++ b/sc/qa/uitest/inputLine/tdf97354_formula_bar_visible_ref_dialog.py @@ -0,0 +1,34 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# +from uitest.framework import UITestCase +from uitest.uihelper.calc import enter_text_to_cell +from uitest.uihelper.common import get_state_as_dict +from libreoffice.uno.propertyvalue import mkPropertyValues + +class tdf97354(UITestCase): + + def test_tdf97354_formula_bar_visible_ref_dialog(self): + with self.ui_test.create_doc_in_start_center("calc"): + xCalcDoc = self.xUITest.getTopFocusWindow() + gridwin = xCalcDoc.getChild("grid_window") + enter_text_to_cell(gridwin, "A1", "=1") + + xInputWin = xCalcDoc.getChild("sc_input_window") + # Re-enter cell edit mode so the content of the formula is still being edited + gridwin.executeAction("TYPE", mkPropertyValues({"KEYCODE": "F2"})) + self.assertEqual("=1", get_state_as_dict(xInputWin)["Text"]) + + with self.ui_test.execute_modeless_dialog_through_command(".uno:ConditionalFormatDialog", close_button="cancel"): + self.ui_test.wait_until_property_is_updated(xInputWin, "Enabled", "false") + + # Without the fix in place, this test would have failed with + # AssertionError: '=1' != '' + self.assertEqual("=1", get_state_as_dict(xInputWin)["Text"]) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/qa/uitest/pageFormat/tdf123508.py b/sc/qa/uitest/pageFormat/tdf123508_format_page_scale.py similarity index 100% rename from sc/qa/uitest/pageFormat/tdf123508.py rename to sc/qa/uitest/pageFormat/tdf123508_format_page_scale.py diff --git a/sc/qa/uitest/pasteSpecial/tdf171481.py b/sc/qa/uitest/pasteSpecial/tdf171481.py new file mode 100644 index 000000000000..bace4eeb21d1 --- /dev/null +++ b/sc/qa/uitest/pasteSpecial/tdf171481.py @@ -0,0 +1,55 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# +from uitest.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.calc import enter_text_to_cell +from libreoffice.calc.document import get_cell_by_position + +class tdf171481(UITestCase): + + def testUnformatted(self): + with self.ui_test.load_empty_file("calc") as document: + xCalcDoc = self.xUITest.getTopFocusWindow() + gridwin = xCalcDoc.getChild("grid_window") + + enter_text_to_cell(gridwin, "A1", "Open_new_Calc.ods") + enter_text_to_cell(gridwin, "A2", "Paste_the_following_two_lines.ods") + gridwin.executeAction("SELECT", mkPropertyValues({"RANGE": "A1:A2"})) + self.xUITest.executeCommand(".uno:Copy") + gridwin.executeAction("SELECT", mkPropertyValues({"CELL": "C1"})) + with self.ui_test.execute_dialog_through_command(".uno:PasteUnformatted", close_button="ok") as xDialog: + pass + + document = self.ui_test.get_component() + self.assertEqual("Open_new_Calc.ods", get_cell_by_position(document, 0, 2, 0).getString()) + self.assertEqual("Paste_the_following_two_lines.ods", get_cell_by_position(document, 0, 2, 1).getString()) + + def testMarkdown(self): + with self.ui_test.load_empty_file("writer") as writer_doc: + xText = writer_doc.getText() + xCursor = xText.createTextCursor() + xText.insertString(xCursor, "| 1 | 2 |\n| --- | --- |\n| 3 | 4 |", False) + + self.xUITest.executeCommand(".uno:SelectAll") + self.xUITest.executeCommand(".uno:Copy") + + with self.ui_test.load_empty_file("calc"): + frames = self.ui_test.get_frames() + frames[1].activate() + + formatProperty = mkPropertyValues({"SelectedFormat": 149}) + self.xUITest.executeCommandWithParameters(".uno:ClipboardFormatItems", formatProperty) + + document = self.ui_test.get_component() + self.assertEqual("1", get_cell_by_position(document, 0, 0, 0).getString()) + self.assertEqual("2", get_cell_by_position(document, 0, 1, 0).getString()) + self.assertEqual("3", get_cell_by_position(document, 0, 0, 1).getString()) + self.assertEqual("4", get_cell_by_position(document, 0, 1, 1).getString()) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/qa/uitest/styleui/tdf92144.py b/sc/qa/uitest/styleui/tdf92144.py new file mode 100644 index 000000000000..3756af55c4a0 --- /dev/null +++ b/sc/qa/uitest/styleui/tdf92144.py @@ -0,0 +1,167 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# +"""Tests for tdf#92144 - relative font sizes in Calc cell styles.""" + +from uitest.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict +from uitest.uihelper.common import select_pos +from uitest.uihelper.common import type_text +from libreoffice.uno.propertyvalue import mkPropertyValues + + +class tdf92144(UITestCase): + + def test_percentage_font_size_in_cell_style(self): + """Test that percentage font size is preserved in cell style.""" + with self.ui_test.create_doc_in_start_center("calc"): + + # Create a new cell style + with self.ui_test.execute_dialog_through_command( + ".uno:StyleNewByExample") as xDialog: + xStyleName = xDialog.getChild("stylename") + xStyleName.executeAction("CLEAR", tuple()) + type_text(xStyleName, "Test Percent Size") + + # Edit the style and set 80% + with self.ui_test.execute_blocking_action( + self.xUITest.executeCommandWithParameters, + args=(".uno:EditStyle", + mkPropertyValues({"Param": "Test Percent Size", + "Family": "CellStyles"}))) as xDialog: + + # Go to Font tab + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "2") + # Set percentage + xSizeField = xDialog.getChild("cbWestSize") + xSizeField.executeAction("CLEAR", tuple()) + type_text(xSizeField, "80%") + + # Reopen the style and verify it's still 80% + with self.ui_test.execute_blocking_action( + self.xUITest.executeCommandWithParameters, + args=(".uno:EditStyle", + mkPropertyValues({"Param": "Test Percent Size", + "Family": "CellStyles"}))) as xDialog: + + # Go to Font tab + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "2") + # Read the value + xSizeField = xDialog.getChild("cbWestSize") + displayed_value = get_state_as_dict(xSizeField)["Text"] + + # Verify it's still 80% (not converted to absolute value) + self.assertEqual(displayed_value, "80%", + "Percentage value was not preserved") + + def test_point_relative_font_size_in_cell_style(self): + """Test that +2pt font size is preserved in cell style.""" + with self.ui_test.create_doc_in_start_center("calc"): + + # Create a new cell style + with self.ui_test.execute_dialog_through_command( + ".uno:StyleNewByExample") as xDialog: + xStyleName = xDialog.getChild("stylename") + xStyleName.executeAction("CLEAR", tuple()) + type_text(xStyleName, "Test PtRelative Size") + + # Edit the style and set +2pt + with self.ui_test.execute_blocking_action( + self.xUITest.executeCommandWithParameters, + args=(".uno:EditStyle", + mkPropertyValues({"Param": "Test PtRelative Size", + "Family": "CellStyles"}))) as xDialog: + + # Go to Font tab + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "2") + # Set +2pt + xSizeField = xDialog.getChild("cbWestSize") + xSizeField.executeAction("CLEAR", tuple()) + type_text(xSizeField, "+2pt") + + # Reopen and verify + with self.ui_test.execute_blocking_action( + self.xUITest.executeCommandWithParameters, + args=(".uno:EditStyle", + mkPropertyValues({"Param": "Test PtRelative Size", + "Family": "CellStyles"}))) as xDialog: + + # Go to Font tab + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "2") + # Read the value + xSizeField = xDialog.getChild("cbWestSize") + displayed_value = get_state_as_dict(xSizeField)["Text"] + + # Verify it's still +2pt (accept both "+2pt" and "+2 pt") + self.assertIn(displayed_value.replace(" ", ""), ["+2pt"], + f"Expected '+2pt' or '+2 pt', got '{displayed_value}'") + + def test_negative_point_relative_font_size(self): + """Test that -2pt font size is preserved in cell style.""" + with self.ui_test.create_doc_in_start_center("calc"): + + # Create a new cell style + with self.ui_test.execute_dialog_through_command( + ".uno:StyleNewByExample") as xDialog: + xStyleName = xDialog.getChild("stylename") + xStyleName.executeAction("CLEAR", tuple()) + type_text(xStyleName, "Test NegRelative Size") + + # Edit the style and set -2pt + with self.ui_test.execute_blocking_action( + self.xUITest.executeCommandWithParameters, + args=(".uno:EditStyle", + mkPropertyValues({"Param": "Test NegRelative Size", + "Family": "CellStyles"}))) as xDialog: + + # Go to Font tab + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "2") + # Set -2pt + xSizeField = xDialog.getChild("cbWestSize") + xSizeField.executeAction("CLEAR", tuple()) + type_text(xSizeField, "-2pt") + + # Reopen and verify + with self.ui_test.execute_blocking_action( + self.xUITest.executeCommandWithParameters, + args=(".uno:EditStyle", + mkPropertyValues({"Param": "Test NegRelative Size", + "Family": "CellStyles"}))) as xDialog: + + # Go to Font tab + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "2") + # Read the value + xSizeField = xDialog.getChild("cbWestSize") + displayed_value = get_state_as_dict(xSizeField)["Text"] + + # Verify it's still -2pt (accept both "-2pt" and "-2 pt") + self.assertIn(displayed_value.replace(" ", ""), ["-2pt"], + f"Expected '-2pt' or '-2 pt', got '{displayed_value}'") + + def test_edit_root_style_relative_font_size_no_crash(self): + """Test that setting a relative font size on root Default style (no parent) does not crash.""" + with self.ui_test.create_doc_in_start_center("calc"): + with self.ui_test.execute_blocking_action( + self.xUITest.executeCommandWithParameters, + args=(".uno:EditStyle", + mkPropertyValues({"Param": "Default", + "Family": "CellStyles"}))) as xDialog: + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "2") + xSizeField = xDialog.getChild("cbWestSize") + xSizeField.executeAction("CLEAR", tuple()) + type_text(xSizeField, "80%") + + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/qa/uitest/vba/tdf169110.py b/sc/qa/uitest/vba/tdf169110.py new file mode 100644 index 000000000000..3f79c7379e5d --- /dev/null +++ b/sc/qa/uitest/vba/tdf169110.py @@ -0,0 +1,40 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# + +from uitest.framework import UITestCase +from com.sun.star.uno import Exception as UnoException +from uitest.uihelper.common import get_url_for_data_file + +class TDF169110(UITestCase): + + def test_vba_cutcopymode_corruption_with_ide(self): + # This test reproduces a regression where opening the Basic IDE + # triggered full VBA initialization during code indexing, + # corrupting the runtime state (CutCopyMode) of active scripts. + + with self.ui_test.load_file(get_url_for_data_file("tdf169110.ods")) as document: + self.xUITest.executeCommand(".uno:BasicIDEAppear") + + xScriptProvider = document.getScriptProvider() + sScriptURL = ( + "vnd.sun.star.script:" + "VBAProject.Module1.countifs_benchmark" + "?language=Basic&location=document" + ) + xScript = xScriptProvider.getScript(sScriptURL) + + try: + xScript.invoke((), (), ()) + except UnoException as e: + self.fail( + "Regression tdf#169110 reproduced: macro failed after " + f"Basic IDE/Object Browser activation: {e}" + ) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/qa/unit/GoalSeekTest.cxx b/sc/qa/unit/GoalSeekTest.cxx index b722ea1c5ad3..b3b96741d701 100644 --- a/sc/qa/unit/GoalSeekTest.cxx +++ b/sc/qa/unit/GoalSeekTest.cxx @@ -124,14 +124,14 @@ CPPUNIT_TEST_FIXTURE(ScGoalSeekTest, testTdf161616_GoalSeek_no_error_set_upon_fa CPPUNIT_ASSERT_EQUAL(DBL_MAX, res.Divergence); ScDocument* pDoc = getScDoc(); - CPPUNIT_ASSERT_EQUAL(u"250"_ustr, pDoc->GetString(ScAddress(0, 0, 0))); - CPPUNIT_ASSERT_EQUAL(u"0.25"_ustr, pDoc->GetString(ScAddress(1, 0, 0))); - CPPUNIT_ASSERT_EQUAL(u"200"_ustr, pDoc->GetString(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"250"_ustr, pDoc->GetString(0, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"0.25"_ustr, pDoc->GetString(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"200"_ustr, pDoc->GetString(2, 0, 0)); // Without the fix in place, this test would have failed with // - Expected: 0.3125 // - Actual : #N/A - CPPUNIT_ASSERT_EQUAL(u"0.3125"_ustr, pDoc->GetString(ScAddress(3, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"0.3125"_ustr, pDoc->GetString(3, 0, 0)); } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/qa/unit/NamedSheetViewsImportExportTest.cxx b/sc/qa/unit/NamedSheetViewsImportExportTest.cxx new file mode 100644 index 000000000000..0ed62bb11b06 --- /dev/null +++ b/sc/qa/unit/NamedSheetViewsImportExportTest.cxx @@ -0,0 +1,294 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#include +#include +#include + +class NamedSheetViewsImportExportTest : public UnoApiTest +{ +public: + NamedSheetViewsImportExportTest() + : UnoApiTest(u"sc/qa/unit/data"_ustr) + { + } +}; + +CPPUNIT_TEST_FIXTURE(NamedSheetViewsImportExportTest, testImportAndCheckState) +{ + loadFromFile(u"xlsx/NamedSheetViews.xlsx"); + + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + CPPUNIT_ASSERT(pModelObj); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + + // Check sheet view manager + auto pManager = pDoc->GetSheetViewManager(SCTAB(0)); + CPPUNIT_ASSERT(pManager); + // 2 sheet views for sheet 1 + CPPUNIT_ASSERT_EQUAL(size_t(2), pManager->size()); + + // 3 sheets total: Sheet1 + 2 sheet view tabs + CPPUNIT_ASSERT_EQUAL(SCTAB(3), pDoc->GetTableCount()); +} + +CPPUNIT_TEST_FIXTURE(NamedSheetViewsImportExportTest, testRoundtripXLSX) +{ + loadFromFile(u"xlsx/NamedSheetViews.xlsx"); + + // Loading is verified in a separate test so here we can assume it's fine + + save(TestFilter::XLSX); + + // Verify the exported XML structure + xmlDocUniquePtr pNsv = parseExport(u"xl/namedSheetViews/namedSheetView1.xml"_ustr); + CPPUNIT_ASSERT(pNsv); + + // Two named sheet views: "View1" and "View2" + assertXPath(pNsv, "/xnsv:namedSheetViews/xnsv:namedSheetView", 2); + assertXPath(pNsv, "/xnsv:namedSheetViews/xnsv:namedSheetView[1]", "name", u"View1"); + assertXPath(pNsv, "/xnsv:namedSheetViews/xnsv:namedSheetView[2]", "name", u"View2"); + + // View1: nsvFilter sort rule on column 2, no column filters + OString sView1 = "/xnsv:namedSheetViews/xnsv:namedSheetView[1]/xnsv:nsvFilter"_ostr; + assertXPath(pNsv, sView1, 1); + // tableId="0" marks the filter as bound to the worksheet auto-filter, not a + // formal
      . + assertXPath(pNsv, sView1, "tableId", u"0"); + assertXPath(pNsv, sView1 + "/xnsv:columnFilter", 0); + assertXPath(pNsv, sView1 + "/xnsv:sortRules/xnsv:sortRule", 1); + assertXPath(pNsv, sView1 + "/xnsv:sortRules/xnsv:sortRule", "colId", u"2"); + assertXPath(pNsv, sView1 + "/xnsv:sortRules/xnsv:sortRule/xnsv:sortCondition", "ref", u"C1:C8"); + + // View2: nsvFilter with 2 column filters and sort rule on column 0 + OString sView2 = "/xnsv:namedSheetViews/xnsv:namedSheetView[2]/xnsv:nsvFilter"_ostr; + assertXPath(pNsv, sView2, 1); + assertXPath(pNsv, sView2, "tableId", u"0"); + assertXPath(pNsv, sView2 + "/xnsv:columnFilter", 2); + + // Column filter on ID 1 + assertXPath(pNsv, sView2 + "/xnsv:columnFilter[1]", "colId", u"1"); + assertXPath(pNsv, sView2 + "/xnsv:columnFilter[1]/xnsv:filter/x:filters/x:filter", 4); + + // Column filter on ID 2 + assertXPath(pNsv, sView2 + "/xnsv:columnFilter[2]", "colId", u"2"); + assertXPath(pNsv, sView2 + "/xnsv:columnFilter[2]/xnsv:filter/x:filters/x:dateGroupItem", 3); + + // Sort rule on column 0 + assertXPath(pNsv, sView2 + "/xnsv:sortRules/xnsv:sortRule", 1); + assertXPath(pNsv, sView2 + "/xnsv:sortRules/xnsv:sortRule", "colId", u"0"); + assertXPath(pNsv, sView2 + "/xnsv:sortRules/xnsv:sortRule/xnsv:sortCondition", "ref", u"A1:A8"); +} + +CPPUNIT_TEST_FIXTURE(NamedSheetViewsImportExportTest, testRoundtripModelState) +{ + loadFromFile(u"xlsx/NamedSheetViews.xlsx"); + + // Save and reload to test full round-trip + saveAndReload(TestFilter::XLSX); + + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + CPPUNIT_ASSERT(pModelObj); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + + // Check after roundtrip + + // 3 tabs should exist + SCTAB nTabCount = pDoc->GetTableCount(); + CPPUNIT_ASSERT_EQUAL(SCTAB(3), nTabCount); + + // Tab index 0 should be visible, the sheet view tabs should be hidden + CPPUNIT_ASSERT(pDoc->IsVisible(0)); + CPPUNIT_ASSERT(!pDoc->IsVisible(1)); // sheet view 1 + CPPUNIT_ASSERT(!pDoc->IsVisible(2)); // sheet view 2 + + // Sheet view tabs should be sheet view holders + CPPUNIT_ASSERT(!pDoc->IsSheetViewHolder(0)); + CPPUNIT_ASSERT(pDoc->IsSheetViewHolder(1)); + CPPUNIT_ASSERT(pDoc->IsSheetViewHolder(2)); + + // Sheet views should exist on tab index 0 - associated with 2 sheet views + auto pManager = pDoc->GetSheetViewManager(0); + CPPUNIT_ASSERT(pManager); + CPPUNIT_ASSERT_EQUAL(size_t(2), pManager->size()); + + // Find the tab index for each view by name + SCTAB nView1Tab = -1; + SCTAB nView2Tab = -1; + for (auto& rSheetView : pManager->iterateValidSheetViews()) + { + if (rSheetView.GetName() == u"View1") + nView1Tab = rSheetView.getTableNumber(); + else if (rSheetView.GetName() == u"View2") + nView2Tab = rSheetView.getTableNumber(); + } + CPPUNIT_ASSERT(nView1Tab >= 0); + CPPUNIT_ASSERT(nView2Tab >= 0); + + // Sheet View 1: has sort on column 2 + { + ScDBData* pDBData = pDoc->GetAnonymousDBData(nView1Tab); + CPPUNIT_ASSERT(pDBData); + + ScSortParam aSortParam; + pDBData->GetSortParam(aSortParam); + CPPUNIT_ASSERT(aSortParam.maKeyState[0].bDoSort); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aSortParam.maKeyState[0].nField); + } + + // Sheet View 2: has column filters and sort on column 0, with rows filtered + { + ScDBData* pDBData = pDoc->GetAnonymousDBData(nView2Tab); + CPPUNIT_ASSERT(pDBData); + + ScQueryParam aQueryParam; + pDBData->GetQueryParam(aQueryParam); + // Should have at least one active query entry + CPPUNIT_ASSERT(aQueryParam.GetEntry(0).bDoQuery); + + ScSortParam aSortParam; + pDBData->GetSortParam(aSortParam); + CPPUNIT_ASSERT(aSortParam.maKeyState[0].bDoSort); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(0), aSortParam.maKeyState[0].nField); + + // At least one data row should be hidden by the filter + bool bHasHiddenRow = false; + for (SCROW nRow = 1; nRow <= 7; ++nRow) + { + if (pDoc->RowHidden(nRow, nView2Tab)) + { + bHasHiddenRow = true; + break; + } + } + CPPUNIT_ASSERT_MESSAGE("Sheet View 2 should have at least one filtered row", bHasHiddenRow); + } +} + +CPPUNIT_TEST_FIXTURE(NamedSheetViewsImportExportTest, testRoundtripGUIDs) +{ + loadFromFile(u"xlsx/NamedSheetViews.xlsx"); + + OString aView1GUID; + OString aView1FilterGUID; + OString aView2GUID; + OString aView2FilterGUID; + { + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + CPPUNIT_ASSERT(pModelObj); + ScDocument* pDocument = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDocument); + + auto pManager = pDocument->GetSheetViewManager(SCTAB(0)); + CPPUNIT_ASSERT(pManager); + + for (auto& rSheetView : pManager->iterateValidSheetViews()) + { + if (rSheetView.GetName() == u"View1") + { + aView1GUID = rSheetView.GetGUID(); + aView1FilterGUID = rSheetView.GetFilterGUID(); + } + else if (rSheetView.GetName() == u"View2") + { + aView2GUID = rSheetView.GetGUID(); + aView2FilterGUID = rSheetView.GetFilterGUID(); + } + } + + // Imported GUIDs must not be empty. + CPPUNIT_ASSERT(!aView1GUID.isEmpty()); + CPPUNIT_ASSERT(!aView1FilterGUID.isEmpty()); + CPPUNIT_ASSERT(!aView2GUID.isEmpty()); + CPPUNIT_ASSERT(!aView2FilterGUID.isEmpty()); + } + + save(TestFilter::XLSX); + + xmlDocUniquePtr pNsv = parseExport(u"xl/namedSheetViews/namedSheetView1.xml"_ustr); + CPPUNIT_ASSERT(pNsv); + + // Exported @id / @filterId must match the GUIDs held on the runtime SheetView + CPPUNIT_ASSERT_EQUAL( + aView1GUID, getXPath(pNsv, "/xnsv:namedSheetViews/xnsv:namedSheetView[1]", "id").toUtf8()); + CPPUNIT_ASSERT_EQUAL( + aView1FilterGUID, + getXPath(pNsv, "/xnsv:namedSheetViews/xnsv:namedSheetView[1]/xnsv:nsvFilter", "filterId") + .toUtf8()); + CPPUNIT_ASSERT_EQUAL( + aView2GUID, getXPath(pNsv, "/xnsv:namedSheetViews/xnsv:namedSheetView[2]", "id").toUtf8()); + CPPUNIT_ASSERT_EQUAL( + aView2FilterGUID, + getXPath(pNsv, "/xnsv:namedSheetViews/xnsv:namedSheetView[2]/xnsv:nsvFilter", "filterId") + .toUtf8()); +} + +CPPUNIT_TEST_FIXTURE(NamedSheetViewsImportExportTest, testMultiSheetRoundtripVisibility) +{ + loadFromFile(u"xlsx/NamedSheetViews.xlsx"); + + // After loading, the document already has 3 tabs: Sheet1 + 2 view tabs. + // Insert Sheet2 at the end so that after round-trip it tests that + // view tab creation doesn't break visibility of subsequent sheets. + { + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + CPPUNIT_ASSERT(pModelObj); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + + // Add a new tab (Sheet2) at the end + pDoc->InsertTab(pDoc->GetTableCount(), u"Sheet2"_ustr); + CPPUNIT_ASSERT_EQUAL(SCTAB(4), pDoc->GetTableCount()); + } + + // Roundtrip it + saveAndReload(TestFilter::XLSX); + + // Check the state after roundtrip + { + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + CPPUNIT_ASSERT(pModelObj); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + + // 2 Sheets, Sheet 1 has 2 sheet views + SCTAB nTabCount = pDoc->GetTableCount(); + CPPUNIT_ASSERT_EQUAL(SCTAB(4), nTabCount); + + // Sheet1 (index 0) should be visible + CPPUNIT_ASSERT(pDoc->IsVisible(0)); + + // Sheet view tabs (index 1, 2) should be hidden and should be sheet view holders + CPPUNIT_ASSERT(!pDoc->IsVisible(1)); + CPPUNIT_ASSERT(!pDoc->IsVisible(2)); + CPPUNIT_ASSERT(pDoc->IsSheetViewHolder(1)); + CPPUNIT_ASSERT(pDoc->IsSheetViewHolder(2)); + + // Sheet2 (index 3) should be visible as it's a normal sheet + CPPUNIT_ASSERT(pDoc->IsVisible(3)); + CPPUNIT_ASSERT(!pDoc->IsSheetViewHolder(3)); + + // Sheet1 (index 0) should be associated with 2 sheet views + auto pManager = pDoc->GetSheetViewManager(0); + CPPUNIT_ASSERT(pManager); + CPPUNIT_ASSERT_EQUAL(size_t(2), pManager->size()); + } +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/PivotTableFormatsImportExport.cxx b/sc/qa/unit/PivotTableFormatsImportExport.cxx index a39fb9430ec7..1438fde71b23 100644 --- a/sc/qa/unit/PivotTableFormatsImportExport.cxx +++ b/sc/qa/unit/PivotTableFormatsImportExport.cxx @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -43,417 +44,399 @@ ScAddress parseAddress(const ScDocument& rDoc, OUString const& rAddressString) return aAddress; } -Color getBackgroundColor(const ScDocument& rDoc, OUString const& rAddressString) +/** Compare pivot table output against Excel reference output below. + * The reference area starts 1 row after the pivot table ends. + * Returns empty string if all cells match, otherwise lists mismatches. */ +OUString comparePivotWithReference(ScDocument& rDocument, ScRange const& rPivotRange, + ScRange const& rReferenceRange) { - const ScPatternAttr* pPattern = rDoc.GetPattern(parseAddress(rDoc, rAddressString)); - const SvxBrushItem& rItem = pPattern->GetItem(ATTR_BACKGROUND); - return rItem.GetColor(); -} + OUString aMismatches; + SCROW nRows = rPivotRange.aEnd.Row() - rPivotRange.aStart.Row() + 1; + SCCOL nColumns = rPivotRange.aEnd.Col() - rPivotRange.aStart.Col() + 1; -Color getFontColor(const ScDocument& rDoc, OUString const& rAddressString) -{ - const ScPatternAttr* pPattern = rDoc.GetPattern(parseAddress(rDoc, rAddressString)); - const SvxColorItem& rItem = pPattern->GetItem(ATTR_FONT_COLOR); - return rItem.getColor(); -} - -bool getCellProtection(const ScDocument& rDoc, OUString const& rAddressString) -{ - const ScPatternAttr* pPattern = rDoc.GetPattern(parseAddress(rDoc, rAddressString)); - const ScProtectionAttr& rItem = pPattern->GetItem(ATTR_PROTECTION); - return rItem.GetProtection(); -} - -template OUString checkNonEmptyAddresses(ScDocument& rDoc, T const& rArrayOfAddresses) -{ - OUString aString; - for (auto const& rAddressString : rArrayOfAddresses) + for (SCROW nRow = 0; nRow < nRows; ++nRow) { - ScAddress aAddress; - aAddress.Parse(rAddressString, rDoc); - const ScPatternAttr* pPattern = rDoc.GetPattern(aAddress); - if (pPattern->GetItem(ATTR_FONT_COLOR).getColor() != COL_BLACK - || pPattern->GetItem(ATTR_BACKGROUND).GetColor() != COL_TRANSPARENT - || !pPattern->GetItem(ATTR_PROTECTION).GetProtection()) + for (SCCOL nColumn = 0; nColumn < nColumns; ++nColumn) { - aString += rAddressString + " "; + ScAddress aPivotAddress(rPivotRange.aStart.Col() + nColumn, + rPivotRange.aStart.Row() + nRow, rPivotRange.aStart.Tab()); + ScAddress aReferenceAddress(rReferenceRange.aStart.Col() + nColumn, + rReferenceRange.aStart.Row() + nRow, + rReferenceRange.aStart.Tab()); + + const ScPatternAttr* pPivotPattern = rDocument.GetPattern(aPivotAddress); + const ScPatternAttr* pReferencePattern = rDocument.GetPattern(aReferenceAddress); + + Color aPivotFontColor = pPivotPattern->GetItem(ATTR_FONT_COLOR).getColor(); + Color aReferenceFontColor = pReferencePattern->GetItem(ATTR_FONT_COLOR).getColor(); + + Color aPivotBackgroundColor = pPivotPattern->GetItem(ATTR_BACKGROUND).GetColor(); + Color aReferenceBackgroundColor + = pReferencePattern->GetItem(ATTR_BACKGROUND).GetColor(); + + OUString aCellName = aPivotAddress.Format(ScRefFlags::VALID); + + if (aPivotFontColor != aReferenceFontColor) + { + aMismatches += "Font Color: " + aCellName + + " (expected = " + aReferenceFontColor.AsRGBHexString() + + " got = " + aPivotFontColor.AsRGBHexString() + ") "; + } + if (aPivotBackgroundColor != aReferenceBackgroundColor) + { + aMismatches += "Background Color: " + aCellName + + " (expected = " + aReferenceBackgroundColor.AsRGBHexString() + + " got = " + aPivotBackgroundColor.AsRGBHexString() + ") "; + } } } - return aString; + return aMismatches; } -void assertDataFieldInRow_RowLabelColor(ScDocument& rDoc) +/** Get the pivot table output range and the reference range from DPObject */ +std::pair getPivotAndReferenceRanges(ScDocument& rDocument) { - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"G6"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getFontColor(rDoc, u"G7"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"G5"_ustr, u"H5"_ustr, u"I5"_ustr, u"J5"_ustr, u"K5"_ustr, u"H6"_ustr, u"I6"_ustr, - u"J6"_ustr, u"K6"_ustr, u"H7"_ustr, u"I7"_ustr, u"J7"_ustr, u"K7"_ustr, - }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + ScDPCollection* pDPs = rDocument.GetDPCollection(); + CPPUNIT_ASSERT(pDPs); + CPPUNIT_ASSERT(pDPs->GetCount() > 0); + ScDPObject& rDPObject = (*pDPs)[0]; + ScRange aPivotRange = rDPObject.GetOutRange(); + // Reference is the same size, starting 2 rows below the pivot table + SCROW nGap = 2; + SCROW nHeight = aPivotRange.aEnd.Row() - aPivotRange.aStart.Row() + 1; + ScRange aReferenceRange(aPivotRange.aStart.Col(), aPivotRange.aEnd.Row() + nGap, + aPivotRange.aStart.Tab(), aPivotRange.aEnd.Col(), + aPivotRange.aEnd.Row() + nGap + nHeight - 1, aPivotRange.aStart.Tab()); + return { aPivotRange, aReferenceRange }; } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, testPivotTableCellFormat_1_DataFieldInRow_RowLabelColor) { createScDoc("xlsx/pivot-table/PivotTableCellFormatsTest_1_DataFieldInRow_RowLabelColor.xlsx"); - assertDataFieldInRow_RowLabelColor(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertDataFieldInRow_RowLabelColor(*getScDoc()); -} -void assertDataFieldInRow_ColumnLabelColor(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(Color(0x00B050), getBackgroundColor(rDoc, u"H5"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"G5"_ustr, u"I5"_ustr, u"J5"_ustr, u"K5"_ustr, u"G6"_ustr, u"H6"_ustr, u"I6"_ustr, - u"J6"_ustr, u"K6"_ustr, u"G7"_ustr, u"H7"_ustr, u"I7"_ustr, u"J7"_ustr, u"K7"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_2_DataFieldInRow_ColumnLabelColor) + testPivotTableCellFormatsTest_2_DataFieldInRow_ColumnLabelColor) { createScDoc( "xlsx/pivot-table/PivotTableCellFormatsTest_2_DataFieldInRow_ColumnLabelColor.xlsx"); - assertDataFieldInRow_ColumnLabelColor(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertDataFieldInRow_ColumnLabelColor(*getScDoc()); -} - -void assertDataFieldInColumn_ColumnLabelColor(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getFontColor(rDoc, u"H4"_ustr)); - CPPUNIT_ASSERT_EQUAL(Color(0x92D050), getBackgroundColor(rDoc, u"I4"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"G4"_ustr, u"G5"_ustr, u"H5"_ustr, u"I5"_ustr, u"G6"_ustr, u"H6"_ustr, u"I6"_ustr, - u"G7"_ustr, u"H7"_ustr, u"I7"_ustr, u"G8"_ustr, u"H8"_ustr, u"I8"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_3_DataFieldInColumn_ColumnLabelColor) + testPivotTableCellFormatsTest_3_DataFieldInColumn_ColumnLabelColor) { createScDoc( "xlsx/pivot-table/PivotTableCellFormatsTest_3_DataFieldInColumn_ColumnLabelColor.xlsx"); - assertDataFieldInColumn_ColumnLabelColor(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertDataFieldInColumn_ColumnLabelColor(*getScDoc()); -} - -void assertDataFieldInColumn_DataColor(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getFontColor(rDoc, u"H6"_ustr)); - CPPUNIT_ASSERT_EQUAL(Color(0x92D050), getBackgroundColor(rDoc, u"I8"_ustr)); - - std::vector aEmptyAddresses{ - u"G4"_ustr, u"H4"_ustr, u"I4"_ustr, u"G5"_ustr, u"H5"_ustr, u"I5"_ustr, u"G6"_ustr, - u"I6"_ustr, u"G7"_ustr, u"H7"_ustr, u"I7"_ustr, u"G8"_ustr, u"H8"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_4_DataFieldInColumn_DataColor) + testPivotTableCellFormatsTest_4_DataFieldInColumn_DataColor) { createScDoc("xlsx/pivot-table/PivotTableCellFormatsTest_4_DataFieldInColumn_DataColor.xlsx"); - assertDataFieldInColumn_DataColor(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertDataFieldInColumn_DataColor(*getScDoc()); -} - -void assertDataFieldInColumnAndTwoRowFields_DataColor(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I7"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"I10"_ustr)); - CPPUNIT_ASSERT_EQUAL(Color(0x0070C0), getBackgroundColor(rDoc, u"J12"_ustr)); - - std::vector aEmptyAddresses{ - u"G4"_ustr, u"H4"_ustr, u"I4"_ustr, u"J4"_ustr, u"G5"_ustr, u"H5"_ustr, u"I5"_ustr, - u"J5"_ustr, u"G6"_ustr, u"H6"_ustr, u"I6"_ustr, u"J6"_ustr, u"G7"_ustr, u"H7"_ustr, - u"J7"_ustr, u"G8"_ustr, u"H8"_ustr, u"I8"_ustr, u"J8"_ustr, u"G9"_ustr, u"H9"_ustr, - u"I9"_ustr, u"J9"_ustr, u"G10"_ustr, u"H10"_ustr, u"J10"_ustr, u"G11"_ustr, u"H11"_ustr, - u"I11"_ustr, u"J11"_ustr, u"G12"_ustr, u"H12"_ustr, u"I12"_ustr, u"G13"_ustr, u"H13"_ustr, - u"I13"_ustr, u"J13"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_5_DataFieldInColumnAndTwoRowFields_DataColor) + testPivotTableCellFormatsTest_5_DataFieldInColumnAndTwoRowFields_DataColor) { - createScDoc("xlsx/pivot-table//" + createScDoc("xlsx/pivot-table/" "PivotTableCellFormatsTest_5_DataFieldInColumnAndTwoRowFields_DataColor.xlsx"); - assertDataFieldInColumnAndTwoRowFields_DataColor(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertDataFieldInColumnAndTwoRowFields_DataColor(*getScDoc()); -} - -void assertSingleDataFieldInColumn_DataColor(const ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"J8"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"J12"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_6_SingleDataFieldInColumn_DataColor) -{ - createScDoc( - "xlsx/pivot-table//PivotTableCellFormatsTest_6_SingleDataFieldInColumn_DataColor.xlsx"); - assertSingleDataFieldInColumn_DataColor(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertSingleDataFieldInColumn_DataColor(*getScDoc()); -} - -void assertTwoRowTwoColumnFields_DataColor(const ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I7"_ustr)); - CPPUNIT_ASSERT_EQUAL(Color(0xFFC000), getBackgroundColor(rDoc, u"J8"_ustr)); - CPPUNIT_ASSERT_EQUAL(Color(0x0070C0), getBackgroundColor(rDoc, u"J9"_ustr)); - CPPUNIT_ASSERT_EQUAL(Color(0x00B0F0), getBackgroundColor(rDoc, u"J13"_ustr)); - CPPUNIT_ASSERT_EQUAL(Color(0x92D050), getBackgroundColor(rDoc, u"K12"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"L14"_ustr)); -} - -CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_7_TwoRowTwoColumnFields_DataColor) -{ - createScDoc( - "xlsx/pivot-table//PivotTableCellFormatsTest_7_TwoRowTwoColumnFields_DataColor.xlsx"); - assertTwoRowTwoColumnFields_DataColor(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertTwoRowTwoColumnFields_DataColor(*getScDoc()); -} - -void assertDataFieldInRow_DataColor(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(Color(0x00B0F0), getBackgroundColor(rDoc, u"I6"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"K7"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"G5"_ustr, u"H5"_ustr, u"I5"_ustr, u"J5"_ustr, u"K5"_ustr, u"G6"_ustr, u"H6"_ustr, - u"J6"_ustr, u"K6"_ustr, u"G7"_ustr, u"H7"_ustr, u"I7"_ustr, u"J7"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); -}; + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); +} CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_8_DataFieldInRow_DataColor) + testPivotTableCellFormatsTest_6_SingleDataFieldInColumn_DataColor) +{ + createScDoc( + "xlsx/pivot-table/PivotTableCellFormatsTest_6_SingleDataFieldInColumn_DataColor.xlsx"); + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); + }; + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); +} + +CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, + testPivotTableCellFormatsTest_7_TwoRowTwoColumnFields_DataColor) +{ + createScDoc( + "xlsx/pivot-table/PivotTableCellFormatsTest_7_TwoRowTwoColumnFields_DataColor.xlsx"); + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); + }; + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); +} + +CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, + testPivotTableCellFormatsTest_8_DataFieldInRow_DataColor) { createScDoc("xlsx/pivot-table/PivotTableCellFormatsTest_8_DataFieldInRow_DataColor.xlsx"); - assertDataFieldInRow_DataColor(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertDataFieldInRow_DataColor(*getScDoc()); -} + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); + }; -void assertMultipleSelections(const ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I5"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I6"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I7"_ustr)); + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_9_MultipleSelections) + testPivotTableCellFormatsTest_9_MultipleSelections) { createScDoc("xlsx/pivot-table/PivotTableCellFormatsTest_9_MultipleSelections.xlsx"); - assertMultipleSelections(*getScDoc()); + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); + }; + + checkFormats(); saveAndReload(TestFilter::XLSX); - assertMultipleSelections(*getScDoc()); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_10_FormatDefinitionNotMatchingPivotTable) + testPivotTableCellFormatsTest_10_FormatDefinitionNotMatchingPivotTable) { - // The pivot table format data in this document doesn't match the pivot table data, which can produce - // a crash during loading and resolving of formats. Specifically - // Load the document, which shouldn't result in a crash createScDoc("xlsx/pivot-table/" "PivotTableCellFormatsTest_10_FormatDefinitionNotMatchingPivotTable.xlsx"); - ScDocument& rDoc = *getScDoc(); - - // Let's check the pivot table exists - ScDPCollection* pCollection = rDoc.GetDPCollection(); + ScDocument& rDocument = *getScDoc(); + ScDPCollection* pCollection = rDocument.GetDPCollection(); CPPUNIT_ASSERT_EQUAL(size_t(1), pCollection->GetCount()); - - auto aAddress = parseAddress(rDoc, u"G2"_ustr); - const ScDPObject* pDPObject = rDoc.GetDPAtCursor(aAddress); + auto aAddress = parseAddress(rDocument, u"G2"_ustr); + const ScDPObject* pDPObject = rDocument.GetDPAtCursor(aAddress); CPPUNIT_ASSERT(pDPObject); - - CPPUNIT_ASSERT_EQUAL(u"60"_ustr, rDoc.GetString(aAddress)); -} - -void assertWholeDataColumnSelected(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"G2"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"G3"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"G4"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"G5"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"G6"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"G7"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"F1"_ustr, u"G1"_ustr, u"F2"_ustr, u"F3"_ustr, u"F4"_ustr, - u"F5"_ustr, u"F6"_ustr, u"F7"_ustr, u"F8"_ustr, u"G8"_ustr, - }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + CPPUNIT_ASSERT_EQUAL(u"60"_ustr, rDocument.GetString(aAddress)); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_11_WholeDataColumnSelected) + testPivotTableCellFormatsTest_11_WholeDataColumnSelected) { createScDoc("xlsx/pivot-table/PivotTableCellFormatsTest_11_WholeDataColumnSelected.xlsx"); - assertWholeDataColumnSelected(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertWholeDataColumnSelected(*getScDoc()); -} - -void assertWholeLabelColumnSelected(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"F2"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"F3"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"F4"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"F5"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"F6"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"F7"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"F1"_ustr, u"G1"_ustr, u"G2"_ustr, u"G3"_ustr, u"G4"_ustr, - u"G5"_ustr, u"G6"_ustr, u"G7"_ustr, u"F8"_ustr, u"G8"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_12_WholeLabelColumnSelected) + testPivotTableCellFormatsTest_12_WholeLabelColumnSelected) { createScDoc("xlsx/pivot-table/PivotTableCellFormatsTest_12_WholeLabelColumnSelected.xlsx"); - assertWholeLabelColumnSelected(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertWholeLabelColumnSelected(*getScDoc()); -} - -void assertSelectionInLabelAndData(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"F5"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"G5"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"F1"_ustr, u"G1"_ustr, u"F2"_ustr, u"G2"_ustr, u"F3"_ustr, u"G3"_ustr, u"F4"_ustr, - u"G4"_ustr, u"F6"_ustr, u"G6"_ustr, u"F7"_ustr, u"G7"_ustr, u"F8"_ustr, u"G8"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_13_SelectionInLabelAndData) + testPivotTableCellFormatsTest_13_SelectionInLabelAndData) { createScDoc("xlsx/pivot-table/PivotTableCellFormatsTest_13_SelectionInLabelAndData.xlsx"); - assertSelectionInLabelAndData(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertSelectionInLabelAndData(*getScDoc()); -} - -void assertTwoRowsDataFieldInColumn_LabelColor(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I4"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"J4"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"G4"_ustr, u"H4"_ustr, u"G5"_ustr, u"H5"_ustr, u"i5"_ustr, u"j5"_ustr, u"G6"_ustr, - u"H6"_ustr, u"i6"_ustr, u"j6"_ustr, u"G7"_ustr, u"H7"_ustr, u"i7"_ustr, u"j7"_ustr, - u"G8"_ustr, u"H8"_ustr, u"i8"_ustr, u"j8"_ustr, u"G9"_ustr, u"H9"_ustr, u"i9"_ustr, - u"j9"_ustr, u"G10"_ustr, u"H10"_ustr, u"i10"_ustr, u"j10"_ustr, u"G11"_ustr, u"H11"_ustr, - u"i11"_ustr, u"j11"_ustr, u"G12"_ustr, u"H12"_ustr, u"i12"_ustr, u"j12"_ustr, u"G13"_ustr, - u"H13"_ustr, u"i13"_ustr, u"j13"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_14_TwoRowsDataFieldInColumn_LabelColor) + testPivotTableCellFormatsTest_14_TwoRowsDataFieldInColumn_LabelColor) { createScDoc("xlsx/pivot-table/" "PivotTableCellFormatsTest_14_TwoRowsDataFieldInColumn_LabelColor.xlsx"); - assertTwoRowsDataFieldInColumn_LabelColor(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertTwoRowsDataFieldInColumn_LabelColor(*getScDoc()); -} - -void assertTwoDataFieldColumns_WholeDataColumnSelected(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H2"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H3"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H4"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H5"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H6"_ustr)); - CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H7"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"F1"_ustr, u"G1"_ustr, u"H1"_ustr, u"F2"_ustr, u"G2"_ustr, - u"F3"_ustr, u"G3"_ustr, u"F4"_ustr, u"G4"_ustr, u"F5"_ustr, - u"G5"_ustr, u"F6"_ustr, u"G6"_ustr, u"F7"_ustr, u"G7"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, - PivotTableCellFormatsTest_15_TwoDataFieldColumns_WholeDataColumnSelected) + testPivotTableCellFormatsTest_15_TwoDataFieldColumns_WholeDataColumnSelected) { createScDoc("xlsx/pivot-table/" "PivotTableCellFormatsTest_15_TwoDataFieldColumns_WholeDataColumnSelected.xlsx"); - assertTwoDataFieldColumns_WholeDataColumnSelected(*getScDoc()); - saveAndReload(TestFilter::XLSX); - assertTwoDataFieldColumns_WholeDataColumnSelected(*getScDoc()); -} - -void assertFields_WithCellProtection(ScDocument& rDoc) -{ - CPPUNIT_ASSERT_EQUAL(false, getCellProtection(rDoc, u"F18"_ustr)); - CPPUNIT_ASSERT_EQUAL(false, getCellProtection(rDoc, u"F19"_ustr)); - CPPUNIT_ASSERT_EQUAL(false, getCellProtection(rDoc, u"F20"_ustr)); - CPPUNIT_ASSERT_EQUAL(false, getCellProtection(rDoc, u"G18"_ustr)); - CPPUNIT_ASSERT_EQUAL(false, getCellProtection(rDoc, u"G19"_ustr)); - CPPUNIT_ASSERT_EQUAL(false, getCellProtection(rDoc, u"G20"_ustr)); - - // Make sure the other cells have the font color or background set to default - std::vector aEmptyAddresses{ - u"F15"_ustr, u"G15"_ustr, u"F16"_ustr, u"G16"_ustr, - u"F17"_ustr, u"G17"_ustr, u"G21"_ustr, u"F21"_ustr, + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); }; - CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, aEmptyAddresses)); + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); } -CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, Pivot_Table_with_Cell_Protection) +CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, testPivotTableWithCellProtection) { createScDoc("xlsx/pivot-table/Pivot_Table_with_Cell_Protection.xlsx"); - assertFields_WithCellProtection(*getScDoc()); + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); + }; + + checkFormats(); saveAndReload(TestFilter::XLSX); - assertFields_WithCellProtection(*getScDoc()); + checkFormats(); } -CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, Pivot_Table_with_No_Source_Data) +CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, testPivotTableWithNoSourceData) { // We need to round-trip this document without crashing createScDoc("xlsx/pivot-table/PivotTableWithNoSourceData.xlsx"); saveAndReload(TestFilter::XLSX); } +CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, testPivotTableFormatsGrandTotal) +{ + createScDoc("xlsx/pivot-table/PivotTableFormatsGrandTotal.xlsx"); + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); + }; + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); +} + +CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, testPivotTableFormatsSubTotals) +{ + createScDoc("xlsx/pivot-table/PivotTableFormatsSubTotals.xlsx"); + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + auto[aPivotRange, aReferenceRange] = getPivotAndReferenceRanges(rDocument); + OUString aMismatches = comparePivotWithReference(rDocument, aPivotRange, aReferenceRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Cell format mismatches found", OUString(), aMismatches); + }; + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); +} + +CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, testTdf122473_PivotTableLabelRotation) +{ + // Contains a pivotTable with differential formatting (dxf) and direct formatting + // with only an child (textRotation) applied to two row-label cells + // ("Sum of C" rotated 90° and "Sum of D" set to stacked/vertical text). + createScDoc("xlsx/pivot-table/tdf122473_PivotTableLabelRotation.xlsx"); + auto checkFormats = [this]() { + ScDocument& rDocument = *getScDoc(); + + // Without the fix in place, this test would have failed with + // - Expected: 9000 + // - Actual : 0 + // "Sum of C" row label at F9 -> dxf 0: textRotation="90" + CPPUNIT_ASSERT_EQUAL(Degree100(9000).get(), + rDocument.GetAttr(5, 8, 0, ATTR_ROTATE_VALUE).GetValue().get()); + + // Without the fix in place, this test would have failed with + // - Expected: 1 + // - Actual : 0 + // "Sum of D" row label at F10 -> dxf 1: textRotation="255" (stacked/vertical) + CPPUNIT_ASSERT_EQUAL(true, rDocument.GetAttr(5, 9, 0, ATTR_STACKED).GetValue()); + }; + + checkFormats(); + saveAndReload(TestFilter::XLSX); + checkFormats(); +} + } // end anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/qa/unit/RedundantParenthesesStripperTest.cxx b/sc/qa/unit/RedundantParenthesesStripperTest.cxx new file mode 100644 index 000000000000..9720792bb26c --- /dev/null +++ b/sc/qa/unit/RedundantParenthesesStripperTest.cxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 "helper/qahelper.hxx" + +#include +#include +#include +#include +#include +#include + +#include +#include + +class RedundantParenthesesStripperTest : public ScModelTestBase +{ +public: + RedundantParenthesesStripperTest() + : ScModelTestBase(u"sc/qa/unit/data"_ustr) + { + } +}; + +namespace +{ +// Compile the formula with the OOXML grammar, strip the redundant +// inner parenthesis pair after every ocSingleValue, and read the +// parse array back as an OOXML formula string. +OUString stripAndPrint(ScDocument& rDocument, const OUString& rFormula) +{ + ScAddress aPosition(0, 0, 0); + ScCompiler aComp(rDocument, aPosition, formula::FormulaGrammar::GRAM_OOXML, true, false); + std::unique_ptr pArray = aComp.CompileString(rFormula); + CPPUNIT_ASSERT(pArray); + oox::xls::stripRedundantParentheses(*pArray, { ocSingleValue }); + sc::TokenStringContext aContext(rDocument, formula::FormulaGrammar::GRAM_OOXML); + return pArray->CreateString(aContext, aPosition); +} + +// Compile with the OOXML grammar, lift every _xlfn.ANCHORARRAY +// wrapper past its parenthesised operand, then read the parse +// array back in native grammar. +OUString liftAnchorArrayAndPrintNative(ScDocument& rDocument, const OUString& rFormula) +{ + ScAddress aPosition(0, 0, 0); + ScCompiler aComp(rDocument, aPosition, formula::FormulaGrammar::GRAM_OOXML, true, false); + std::unique_ptr pArray = aComp.CompileString(rFormula); + CPPUNIT_ASSERT(pArray); + oox::xls::liftAnchorArrayToPostfix(*pArray); + sc::TokenStringContext aContext(rDocument, formula::FormulaGrammar::GRAM_NATIVE); + return pArray->CreateString(aContext, aPosition); +} +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, testStripsInnerPairAroundExpression) +{ + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(A1+1)"_ustr, + stripAndPrint(*getScDoc(), u"_xlfn.SINGLE((A1+1))"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, testStripsInnerPairAroundBareReference) +{ + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(A1)"_ustr, + stripAndPrint(*getScDoc(), u"_xlfn.SINGLE((A1))"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, testLeavesSinglePairAlone) +{ + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(A1+1)"_ustr, + stripAndPrint(*getScDoc(), u"_xlfn.SINGLE(A1+1)"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, testLeavesNonSpanningInnerPair) +{ + // The (A1) covers only the left side of the addition, so the + // outer pair is the @ argument and is not redundant. + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE((A1)+B1)"_ustr, + stripAndPrint(*getScDoc(), u"_xlfn.SINGLE((A1)+B1)"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, testLeavesFunctionCallArgument) +{ + // The parentheses around A1:A4 belong to the TRANSPOSE call, not + // to a redundant wrapper. + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(TRANSPOSE(A1:A4))"_ustr, + stripAndPrint(*getScDoc(), u"_xlfn.SINGLE(TRANSPOSE(A1:A4))"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, testPeelsOneLevelOfNestedRedundantPairs) +{ + // One pass peels one level. The remaining redundant pair would + // need another invocation to drop. + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE((A1+1))"_ustr, + stripAndPrint(*getScDoc(), u"_xlfn.SINGLE(((A1+1)))"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, + testStripsAroundFunctionCallButLeavesInnerArgument) +{ + // The trigger list only covers ocSingleValue, so redundant pairs + // inside the function call stay. + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(TRANSPOSE((A1:A4)))"_ustr, + stripAndPrint(*getScDoc(), u"_xlfn.SINGLE((TRANSPOSE((A1:A4))))"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, testLeavesNonTriggerOpcodeAlone) +{ + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"SUM((A1+B1))"_ustr, stripAndPrint(*getScDoc(), u"SUM((A1+B1))"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, testLiftsAnchorArrayAroundBareReference) +{ + // _xlfn.ANCHORARRAY(A1) reads back as A1# in native grammar. + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"A1#"_ustr, + liftAnchorArrayAndPrintNative(*getScDoc(), u"_xlfn.ANCHORARRAY(A1)"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, testLiftsAnchorArrayInsideAddition) +{ + // The wrapper composes with arithmetic: _xlfn.ANCHORARRAY(A1)+10 + // reads back as A1#+10 in native grammar. + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"A1#+10"_ustr, liftAnchorArrayAndPrintNative( + *getScDoc(), u"_xlfn.ANCHORARRAY(A1)+10"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(RedundantParenthesesStripperTest, + testLiftsAnchorArrayAroundParenthesisedReference) +{ + // A parenthesised operand is taken whole: _xlfn.ANCHORARRAY(((A1))) + // reads back as ((A1))# in native grammar, with the inner + // parentheses left in place. + createScDoc(); + CPPUNIT_ASSERT_EQUAL(u"((A1))#"_ustr, liftAnchorArrayAndPrintNative( + *getScDoc(), u"_xlfn.ANCHORARRAY(((A1)))"_ustr)); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/qa/unit/SwarmSolverTest.cxx b/sc/qa/unit/SwarmSolverTest.cxx new file mode 100644 index 000000000000..9d66f55b3a89 --- /dev/null +++ b/sc/qa/unit/SwarmSolverTest.cxx @@ -0,0 +1,765 @@ +/* -*- 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 + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +using namespace css; + +namespace +{ +// Minimal data provider that drives the algorithm template without a document. +class MockProvider +{ + size_t mnDimensionality; + +public: + int mnInitCalls = 0; + + explicit MockProvider(size_t nDimensionality) + : mnDimensionality(nDimensionality) + { + } + + size_t getDimensionality() const { return mnDimensionality; } + + void initializeVariables(std::vector& rVariables, std::mt19937& rGenerator) + { + std::uniform_real_distribution aRandom(-10.0, 10.0); + rVariables.resize(mnDimensionality); + for (double& rValue : rVariables) + rValue = aRandom(rGenerator); + mnInitCalls++; + } + + // Separable, with its maximum where every variable is zero, so the swarm + // always has somewhere to move towards and improvements actually happen. + static double calculateFitness(std::vector const& rVariables) + { + double fFitness = 0.0; + for (double fValue : rVariables) + fFitness -= fValue * fValue; + return fFitness; + } + + static double clampVariable(size_t, double fValue) { return fValue; } +}; + +class SwarmSolverTest : public UnoApiTest +{ + void testUnconstrained(); + void testVariableBounded(); + void testVariableConstrained(); + void testTwoVariables(); + void testMultipleVariables(); + void testInfeasibleConstraints_Differential_Evolution(); + void testInfeasibleConstraints_Particle_Swarm(); + void testLargeObjectiveStillSolvable_Differential_Evolution(); + void testLargeObjectiveStillSolvable_Particle_Swarm(); + void testParticleSwarmResultLength(); + void testParticleSwarmVelocityNotInitializedAsPosition(); + void testUnreadableConstraintStillChecksOthers(); + void testContradictoryBoundsTerminate(); + void testUnboundedIntegerVariable(); + void testRepeatedSolveResetsState(); + void testControllersUnlockedAfterError(); + void testConstrainedLinearProgram(); + + uno::Reference + initializeSolver(table::CellAddress& rObjective, uno::Sequence& rVariables, + uno::Sequence& rConstraints, bool bMaximize); + +public: + SwarmSolverTest() + : UnoApiTest(u"sc/qa/unit/data/solver"_ustr) + { + } + + CPPUNIT_TEST_SUITE(SwarmSolverTest); + CPPUNIT_TEST(testUnconstrained); + CPPUNIT_TEST(testVariableBounded); + CPPUNIT_TEST(testVariableConstrained); + CPPUNIT_TEST(testMultipleVariables); + CPPUNIT_TEST(testTwoVariables); + CPPUNIT_TEST(testInfeasibleConstraints_Differential_Evolution); + CPPUNIT_TEST(testInfeasibleConstraints_Particle_Swarm); + CPPUNIT_TEST(testLargeObjectiveStillSolvable_Differential_Evolution); + CPPUNIT_TEST(testLargeObjectiveStillSolvable_Particle_Swarm); + CPPUNIT_TEST(testParticleSwarmResultLength); + CPPUNIT_TEST(testParticleSwarmVelocityNotInitializedAsPosition); + CPPUNIT_TEST(testUnreadableConstraintStillChecksOthers); + CPPUNIT_TEST(testContradictoryBoundsTerminate); + CPPUNIT_TEST(testUnboundedIntegerVariable); + CPPUNIT_TEST(testRepeatedSolveResetsState); + CPPUNIT_TEST(testControllersUnlockedAfterError); + CPPUNIT_TEST(testConstrainedLinearProgram); + CPPUNIT_TEST_SUITE_END(); +}; + +uno::Reference SwarmSolverTest::initializeSolver( + table::CellAddress& rObjective, uno::Sequence& rVariables, + uno::Sequence& rConstraints, bool bMaximize) +{ + uno::Reference xDocument(mxComponent, uno::UNO_QUERY_THROW); + uno::Reference xIndex(xDocument->getSheets(), uno::UNO_QUERY_THROW); + uno::Reference xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW); + + uno::Reference xSolver( + m_xContext->getServiceManager()->createInstanceWithContext( + u"com.sun.star.comp.Calc.SwarmSolver"_ustr, m_xContext), + uno::UNO_QUERY_THROW); + + xSolver->setDocument(xDocument); + xSolver->setObjective(rObjective); + xSolver->setVariables(rVariables); + xSolver->setConstraints(rConstraints); + xSolver->setMaximize(bMaximize); + + return xSolver; +} + +void SwarmSolverTest::testUnconstrained() +{ + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + + // "changing cells" - unknown variables + uno::Sequence aVariables{ { 0, 1, 0 } }; + + // constraints + uno::Sequence aConstraints; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + // test results + xSolver->solve(); + CPPUNIT_ASSERT(xSolver->getSuccess()); + uno::Sequence aSolution = xSolver->getSolution(); + + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + // It happens that the unconstrained test does not find a solution in the + // timeframe or number of generations it has available as the search space is + // too big and the values might not converge to solution. So for now just run + // the test so we know for sure the algorithm is guaranteed to finish + // and doesn't cause any seg faults. + //CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[0], .9); +} + +void SwarmSolverTest::testVariableBounded() +{ + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + + // "changing cells" - unknown variables + uno::Sequence aVariables{ { 0, 1, 0 } }; + + // constraints + uno::Sequence aConstraints{ + { /* [0] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(100.0) }, + { /* [1] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(-100.0) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + // test results + xSolver->solve(); + CPPUNIT_ASSERT(xSolver->getSuccess()); + uno::Sequence aSolution = xSolver->getSolution(); + + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[0], 1E-5); +} + +void SwarmSolverTest::testVariableConstrained() +{ + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + + // "changing cells" - unknown variables + uno::Sequence aVariables{ { 0, 1, 0 } }; + + // constraints + uno::Sequence aConstraints{ + { /* [0] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(-50000.0) }, + { /* [1] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(0.0) }, + { /* [2] Left */ table::CellAddress(0, 1, 1), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(10.0) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + // test results + xSolver->solve(); + CPPUNIT_ASSERT(xSolver->getSuccess()); + uno::Sequence aSolution = xSolver->getSolution(); + + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + // The hybrid default reaches the optimum to within a stochastic tolerance. + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.741657, aSolution[0], 1E-4); +} + +void SwarmSolverTest::testTwoVariables() +{ + loadFromFile(u"TwoVariables.ods"); + + table::CellAddress aObjective(0, 1, 5); + + // "changing cells" - unknown variables + uno::Sequence aVariables{ { 0, 1, 2 }, { 0, 1, 3 } }; + + // constraints + uno::Sequence aConstraints{ + { /* [0] Left */ table::CellAddress(0, 1, 2), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(-100.0) }, + { /* [1] Left */ table::CellAddress(0, 1, 3), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(-100.0) }, + { /* [2] Left */ table::CellAddress(0, 1, 2), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(100.0) }, + { /* [3] Left */ table::CellAddress(0, 1, 3), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(100.0) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ true); + + // test results + xSolver->solve(); + CPPUNIT_ASSERT(xSolver->getSuccess()); + uno::Sequence aSolution = xSolver->getSolution(); + + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.666667, aSolution[0], 1E-5); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.666667, aSolution[1], 1E-5); +} + +void SwarmSolverTest::testMultipleVariables() +{ + loadFromFile(u"MultiVariable.ods"); + + table::CellAddress aObjective(0, 5, 7); + + // "changing cells" - unknown variables + uno::Sequence aVariables{ + { 0, 6, 1 }, { 0, 6, 2 }, { 0, 6, 3 }, { 0, 6, 4 } + }; + + // constraints + uno::Sequence aConstraints{ + { /* [ 0] Left */ table::CellAddress(0, 1, 5), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(table::CellAddress(0, 1, 6)) }, + { /* [ 1] Left */ table::CellAddress(0, 2, 5), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(table::CellAddress(0, 2, 6)) }, + { /* [ 2] Left */ table::CellAddress(0, 3, 5), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(table::CellAddress(0, 3, 6)) }, + { /* [ 3] Left */ table::CellAddress(0, 4, 5), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(table::CellAddress(0, 4, 6)) }, + { /* [ 4] Left */ table::CellAddress(0, 6, 1), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(0.0) }, + { /* [ 5] Left */ table::CellAddress(0, 6, 2), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(0.0) }, + { /* [ 6] Left */ table::CellAddress(0, 6, 3), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(0.0) }, + { /* [ 7] Left */ table::CellAddress(0, 6, 4), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(0.0) }, + { /* [ 8] Left */ table::CellAddress(0, 6, 1), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(10000.0) }, + { /* [ 9] Left */ table::CellAddress(0, 6, 2), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(10000.0) }, + { /* [10] Left */ table::CellAddress(0, 6, 3), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(10000.0) }, + { /* [11] Left */ table::CellAddress(0, 6, 4), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(10000.0) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + uno::Reference xPropSet(xSolver, uno::UNO_QUERY_THROW); + xPropSet->setPropertyValue(u"Integer"_ustr, uno::Any(true)); + + // test results + xSolver->solve(); + CPPUNIT_ASSERT(xSolver->getSuccess()); + uno::Sequence aSolution = xSolver->getSolution(); + + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); +#if 0 + // Disable for now, needs algorithm stability improvements + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution[0], 1E-5); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[1], 1E-5); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aSolution[2], 1E-5); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution[3], 1E-5); +#endif +} + +void SwarmSolverTest::testInfeasibleConstraints_Differential_Evolution() +{ + // Regression: the solver used to report success even when no point satisfies + // the model. + + // Differential Evolution returns no candidate at all + // result is infeasible and getSuccess must be false. + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + uno::Sequence aVariables{ { 0, 1, 0 } }; + + uno::Sequence aConstraints{ + { /* [0] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(-100.0) }, + { /* [1] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(100.0) }, + // The objective B2 is 10*B1^2 - 60*B1 - 40, whose lowest value is + // -130 at B1 = 3, so forcing it below -1000 can never be met. + { /* [2] Left */ table::CellAddress(0, 1, 1), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(-1000.0) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + uno::Reference xPropSet(xSolver, uno::UNO_QUERY_THROW); + xPropSet->setPropertyValue(u"Algorithm"_ustr, uno::Any(sal_Int32(0))); + + xSolver->solve(); + + CPPUNIT_ASSERT_MESSAGE("Infeasible model must not report success", !xSolver->getSuccess()); +} + +void SwarmSolverTest::testInfeasibleConstraints_Particle_Swarm() +{ + // Regression: the solver used to report success even when no point satisfies + // the model. + + // Particle Swarm Optimization returns its starting point. + // result is infeasible and getSuccess must be false. + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + uno::Sequence aVariables{ { 0, 1, 0 } }; + + uno::Sequence aConstraints{ + { /* [0] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(-100.0) }, + { /* [1] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(100.0) }, + // The objective B2 is 10*B1^2 - 60*B1 - 40, whose lowest value is + // -130 at B1 = 3, so forcing it below -1000 can never be met. + { /* [2] Left */ table::CellAddress(0, 1, 1), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(-1000.0) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + uno::Reference xPropSet(xSolver, uno::UNO_QUERY_THROW); + xPropSet->setPropertyValue(u"Algorithm"_ustr, uno::Any(sal_Int32(1))); + + xSolver->solve(); + + CPPUNIT_ASSERT_MESSAGE("Infeasible model must not report success", !xSolver->getSuccess()); +} + +void SwarmSolverTest::testLargeObjectiveStillSolvable_Differential_Evolution() +{ + // Regression: a feasible objective below the float range used to lose to the + // infeasible penalty, so the search gave up on a solvable model. The Particle + // Swarm result also used to grow past the variable count, which the length + // check below guards. + + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + uno::Sequence aVariables{ { 0, 1, 0 } }; + + // The variable is pushed far enough out that the objective + // 10*B1^2 - 60*B1 - 40 reaches the 1e39 range, beyond what a float can + // hold. Minimizing turns that into a fitness near -1e39. The objective + // cap is a non-bounded constraint, so the upper part of the box is + // infeasible while the lower end stays feasible. + uno::Sequence aConstraints{ + { /* [0] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(1.0e19) }, + { /* [1] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(2.0e19) }, + { /* [2] Left */ table::CellAddress(0, 1, 1), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(2.0e39) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + uno::Reference xPropSet(xSolver, uno::UNO_QUERY_THROW); + xPropSet->setPropertyValue(u"Algorithm"_ustr, uno::Any(sal_Int32(0))); + + xSolver->solve(); + + CPPUNIT_ASSERT_MESSAGE("Solvable model must report success", xSolver->getSuccess()); + + uno::Sequence aSolution = xSolver->getSolution(); + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + // the returned point must lie in the feasible part of the box + CPPUNIT_ASSERT(aSolution[0] >= 1.0e19); + CPPUNIT_ASSERT(aSolution[0] <= 2.0e19); +} + +void SwarmSolverTest::testLargeObjectiveStillSolvable_Particle_Swarm() +{ + // Regression: a feasible objective below the float range used to lose to the + // infeasible penalty, so the search gave up on a solvable model. The Particle + // Swarm result also used to grow past the variable count, which the length + // check below guards. + + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + uno::Sequence aVariables{ { 0, 1, 0 } }; + + // The variable is pushed far enough out that the objective + // 10*B1^2 - 60*B1 - 40 reaches the 1e39 range, beyond what a float can + // hold. Minimizing turns that into a fitness near -1e39. The objective + // cap is a non-bounded constraint, so the upper part of the box is + // infeasible while the lower end stays feasible. + uno::Sequence aConstraints{ + { /* [0] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(1.0e19) }, + { /* [1] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(2.0e19) }, + { /* [2] Left */ table::CellAddress(0, 1, 1), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(2.0e39) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + uno::Reference xPropSet(xSolver, uno::UNO_QUERY_THROW); + xPropSet->setPropertyValue(u"Algorithm"_ustr, uno::Any(sal_Int32(1))); + + xSolver->solve(); + + CPPUNIT_ASSERT_MESSAGE("Solvable model must report success", xSolver->getSuccess()); + + uno::Sequence aSolution = xSolver->getSolution(); + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + // the returned point must lie in the feasible part of the box + CPPUNIT_ASSERT(aSolution[0] >= 1.0e19); + CPPUNIT_ASSERT(aSolution[0] <= 2.0e19); +} + +void SwarmSolverTest::testParticleSwarmResultLength() +{ + // Regression: the best-position vectors were updated with insert at the front + // instead of assign, so every improvement prepended another copy and the result + // grew past the variable count. + + MockProvider aProvider(3); + ParticleSwarmOptimizationSolver aAlgorithm(aProvider, 8); + + aAlgorithm.initialize(); + for (int i = 0; i < 20; ++i) + aAlgorithm.next(); + + CPPUNIT_ASSERT_EQUAL(size_t(3), aAlgorithm.getResult().size()); +} + +void SwarmSolverTest::testParticleSwarmVelocityNotInitializedAsPosition() +{ + // Regression: the velocity was seeded by initializeVariables, which fills it + // with a random position. Setup must call initializeVariables once per particle + // (for the position only), not twice. + + MockProvider aProvider(3); + ParticleSwarmOptimizationSolver aAlgorithm(aProvider, 8); + + aAlgorithm.initialize(); + + CPPUNIT_ASSERT_EQUAL(8, aProvider.mnInitCalls); +} + +void SwarmSolverTest::testUnreadableConstraintStillChecksOthers() +{ + // Regression: a constraint whose right hand side could not be read as a cell + // or a number used to make the feasibility check return "satisfied" for the + // whole point, hiding every later constraint. Here an unreadable constraint + // comes before an impossible one, so the model must still be reported as not + // solved. + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + uno::Sequence aVariables{ { 0, 1, 0 } }; + + // Both constraints act on the objective cell, not the variable, so they end + // up as non-bounded constraints in the order given here. + uno::Sequence aConstraints{ + // right hand side is a string, so it reads as neither a cell nor a + // number + { /* [0] Left */ table::CellAddress(0, 1, 1), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(u"not a number"_ustr) }, + // forced below the objective's global minimum of -130, so impossible + { /* [1] Left */ table::CellAddress(0, 1, 1), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(-1000.0) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + xSolver->solve(); + + CPPUNIT_ASSERT_MESSAGE("an unreadable constraint must not hide a later one", + !xSolver->getSuccess()); +} + +void SwarmSolverTest::testContradictoryBoundsTerminate() +{ + // Regression: a variable bounded below 5 and above 10 has an empty, reversed + // range. The reflection in boundVariable used to keep wrapping such a value + // without ever landing inside the range, so solve never returned. It must now + // finish and report the model as not solved. + + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + uno::Sequence aVariables{ { 0, 1, 0 } }; + + // Both act on the variable, so they fold into its bounds: lower 10, upper 5 + uno::Sequence aConstraints{ + { /* [0] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right */ uno::Any(10.0) }, + { /* [1] Left */ table::CellAddress(0, 1, 0), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(5.0) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + // The guarantee here is that solve returns at all. + xSolver->solve(); + + CPPUNIT_ASSERT_MESSAGE("A model with contradictory bounds is not solvable", + !xSolver->getSuccess()); +} + +void SwarmSolverTest::testUnboundedIntegerVariable() +{ + // Regression: an integer variable with no explicit bound kept the default + // range around the float limits. Turning those limits into a 64 bit integer + // collapsed both ends to the same value, so the whole population started at one + // point, never varied, and the search returned nothing. The variable must + // instead be seeded across a usable range and the model reported as solved. + + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + uno::Sequence aVariables{ { 0, 1, 0 } }; + + // No constraints, so the variable keeps the default unbounded range. + uno::Sequence aConstraints; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + uno::Reference xPropSet(xSolver, uno::UNO_QUERY_THROW); + xPropSet->setPropertyValue(u"Integer"_ustr, uno::Any(true)); + + xSolver->solve(); + + CPPUNIT_ASSERT_MESSAGE("An unbounded integer variable must still be solvable", + xSolver->getSuccess()); + + uno::Sequence aSolution = xSolver->getSolution(); + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + CPPUNIT_ASSERT(std::isfinite(aSolution[0])); + CPPUNIT_ASSERT_EQUAL(aSolution[0], std::trunc(aSolution[0])); +} + +void SwarmSolverTest::testRepeatedSolveResetsState() +{ + // Regression: solving twice with the same solver kept state from the first + // run. The collected constraints only ever grew and the bounds were not reset, + // so the second solve saw a leftover impossible constraint and stale bounds and + // failed on a model it should solve. + + loadFromFile(u"Simple.ods"); + + table::CellAddress aObjective(0, 1, 1); + uno::Sequence aVariables{ { 0, 1, 0 } }; + + uno::Sequence aConstraints{ + { /* Left */ table::CellAddress(0, 1, 0), + /* Op */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right*/ uno::Any(0.0) }, + { /* Left */ table::CellAddress(0, 1, 1), + /* Op */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right*/ uno::Any(-1000.0) } + }; + + // First run: a bound on the variable plus an impossible constraint on the + // objective, so it cannot be solved. + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + xSolver->solve(); + CPPUNIT_ASSERT(!xSolver->getSuccess()); + + // Second run on the same solver: a plain bounded model with minimum at 3. + // It is bounded only by its own constraints. + xSolver->setConstraints({ { /* Left */ table::CellAddress(0, 1, 0), + /* Op */ sheet::SolverConstraintOperator_GREATER_EQUAL, + /* Right*/ uno::Any(-100.0) }, + { /* Left */ table::CellAddress(0, 1, 0), + /* Op */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right*/ uno::Any(100.0) } }); + xSolver->solve(); + CPPUNIT_ASSERT_MESSAGE("The second solve must not inherit the first run's state", + xSolver->getSuccess()); + + uno::Sequence aSolution = xSolver->getSolution(); + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[0], 1E-5); +} + +void SwarmSolverTest::testControllersUnlockedAfterError() +{ + // Regression: solve locked the document controllers and only unlocked them at + // the end. A cell access in between could throw, leaving the document locked + // for good. Point a variable at a sheet that does not exist so a cell access + // throws, then check the controllers are unlocked again. + + loadFromFile(u"Simple.ods"); + + uno::Sequence aConstraints; + + table::CellAddress aObjective(0, 1, 1); + // sheet index 99 does not exist, so reading or writing this cell throws + uno::Sequence aVariables{ { 99, 1, 0 } }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ false); + + bool bThrew = false; + try + { + xSolver->solve(); + } + catch (const uno::Exception&) + { + bThrew = true; + } + + CPPUNIT_ASSERT(bThrew); + uno::Reference xDocument(mxComponent, uno::UNO_QUERY_THROW); + uno::Reference xModel(xDocument, uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_MESSAGE("Controllers must be unlocked after a failed solve", + !xModel->hasControllersLocked()); +} + +void SwarmSolverTest::testConstrainedLinearProgram() +{ + // A small linear program with two binding inequality constraints on formula + // cells. Maximize 2x + 4y subject to x + y <= 4 and x + 3y <= 6, with both + // variables in [0, 10]. The two constraints meet at x = 3, y = 1, where the + // objective reaches its maximum of 10. + + loadFromFile(u"ConstrainedLinear.fods"); + + // objective 2x + 4y is in B3 + table::CellAddress aObjective(0, 1, 2); + // x is A1, y is A2 + uno::Sequence aVariables{ { 0, 0, 0 }, { 0, 0, 1 } }; + + uno::Sequence aConstraints{ + // box bounds on the two variables + { table::CellAddress(0, 0, 0), sheet::SolverConstraintOperator_GREATER_EQUAL, + uno::Any(0.0) }, + { table::CellAddress(0, 0, 0), sheet::SolverConstraintOperator_LESS_EQUAL, uno::Any(10.0) }, + { table::CellAddress(0, 0, 1), sheet::SolverConstraintOperator_GREATER_EQUAL, + uno::Any(0.0) }, + { table::CellAddress(0, 0, 1), sheet::SolverConstraintOperator_LESS_EQUAL, uno::Any(10.0) }, + // x + y <= 4 (cell B1) + { table::CellAddress(0, 1, 0), sheet::SolverConstraintOperator_LESS_EQUAL, uno::Any(4.0) }, + // x + 3y <= 6 (cell B2) + { table::CellAddress(0, 1, 1), sheet::SolverConstraintOperator_LESS_EQUAL, uno::Any(6.0) } + }; + + uno::Reference xSolver + = initializeSolver(aObjective, aVariables, aConstraints, /*bMaximize*/ true); + + xSolver->solve(); + + CPPUNIT_ASSERT(xSolver->getSuccess()); + + uno::Sequence aSolution = xSolver->getSolution(); + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[0], 1E-3); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aSolution[1], 1E-3); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(SwarmSolverTest); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/anchor.cxx b/sc/qa/unit/anchor.cxx index 6c4cf87a3921..4432e928bcc6 100644 --- a/sc/qa/unit/anchor.cxx +++ b/sc/qa/unit/anchor.cxx @@ -74,6 +74,9 @@ void ScAnchorTest::testUndoAnchor() ScDocShell* pDocSh = dynamic_cast(pFoundShell); CPPUNIT_ASSERT(pDocSh); + // allow link updates so the linked graphic is fetched + pDocSh->getEmbeddedObjectContainer().setUserAllowsLinkUpdate(true); + // Check whether graphic imported well ScDocument& rDoc = pDocSh->GetDocument(); ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); diff --git a/sc/qa/unit/cond_format.cxx b/sc/qa/unit/cond_format.cxx index 9d1cb4964b96..4b416493ec26 100644 --- a/sc/qa/unit/cond_format.cxx +++ b/sc/qa/unit/cond_format.cxx @@ -543,8 +543,8 @@ CPPUNIT_TEST_FIXTURE(CondFormatTest, testTdf64401) } // Update values in B4 and B5 - pDoc->SetValue(ScAddress(1, 3, 0), 2.0); - pDoc->SetValue(ScAddress(1, 4, 0), 9.0); + pDoc->SetValue(1, 3, 0, 2.0); + pDoc->SetValue(1, 4, 0, 9.0); for (size_t i = 0; i < 10; ++i) { diff --git a/sc/qa/unit/copy_paste_test.cxx b/sc/qa/unit/copy_paste_test.cxx index 759f65f71f9d..2493b5b86785 100644 --- a/sc/qa/unit/copy_paste_test.cxx +++ b/sc/qa/unit/copy_paste_test.cxx @@ -21,6 +21,7 @@ #include #include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -46,6 +47,8 @@ public: void tdf137625_autofillMergedUserlist(); void tdf137624_autofillMergedMixed(); void tdf122716_rtf_portion_encoding(); + void testRTFFontHeight(); + void testHtmlImportDataUrlIncompleteBase64(); CPPUNIT_TEST_SUITE(ScCopyPasteTest); CPPUNIT_TEST(testCopyPasteXLS); @@ -64,6 +67,8 @@ public: CPPUNIT_TEST(tdf137625_autofillMergedUserlist); CPPUNIT_TEST(tdf137624_autofillMergedMixed); CPPUNIT_TEST(tdf122716_rtf_portion_encoding); + CPPUNIT_TEST(testRTFFontHeight); + CPPUNIT_TEST(testHtmlImportDataUrlIncompleteBase64); CPPUNIT_TEST_SUITE_END(); private: @@ -143,11 +148,11 @@ void ScCopyPasteTest::testTdf84411() // 2. Setup data and formulas for (unsigned int r = 0; r <= 4991; ++r) for (unsigned int c = 0; c <= 14; ++c) - pDoc->SetValue( ScAddress(c,r,0), (r+1)*(c+1) ); + pDoc->SetValue( c,r,0, (r+1)*(c+1) ); - pDoc->SetString(ScAddress(15,10000,0), u"=AVERAGE(A10001:O10001)"_ustr); - pDoc->SetString(ScAddress(16,10000,0), u"=MIN(A10001:O10001)"_ustr); - pDoc->SetString(ScAddress(17,10000,0), u"=MAX(A10001:O10001)"_ustr); + pDoc->SetString(15,10000,0, u"=AVERAGE(A10001:O10001)"_ustr); + pDoc->SetString(16,10000,0, u"=MIN(A10001:O10001)"_ustr); + pDoc->SetString(17,10000,0, u"=MAX(A10001:O10001)"_ustr); lcl_copy(u"P10001:R10001"_ustr, u"P10002:R12500"_ustr, *pDoc, pViewShell); @@ -180,7 +185,7 @@ void ScCopyPasteTest::testTdf124565() ScTabViewShell* pViewShell = getViewShell(); // Set content and height of first row - pDoc->SetString(ScAddress(0, 0, 0), u"Test"_ustr); + pDoc->SetString(0, 0, 0, u"Test"_ustr); pDoc->SetRowHeight(0, 0, 500); pDoc->SetManualHeight(0, 0, 0, true); @@ -249,8 +254,8 @@ void ScCopyPasteTest::testTdf107394() aStream.Seek(0); CPPUNIT_ASSERT(aObj.ImportStream(aStream, OUString(), SotClipboardFormatId::HTML)); - CPPUNIT_ASSERT_EQUAL(u"First"_ustr, pDoc->GetString(ScAddress(0,0,0))); - CPPUNIT_ASSERT_EQUAL(u"Very long sentence."_ustr, pDoc->GetString(ScAddress(0,1,0))); + CPPUNIT_ASSERT_EQUAL(u"First"_ustr, pDoc->GetString(0,0,0)); + CPPUNIT_ASSERT_EQUAL(u"Very long sentence."_ustr, pDoc->GetString(0,1,0)); nFirstRowHeight = pDoc->GetRowHeight(0, 0); nSecondRowHeight = pDoc->GetRowHeight(1, 0); @@ -261,8 +266,8 @@ void ScCopyPasteTest::testTdf107394() CPPUNIT_ASSERT_MESSAGE("Failed to get the undo manager.", pUndoMgr); pUndoMgr->Undo(); - CPPUNIT_ASSERT(pDoc->GetString(ScAddress(0,0,0)).isEmpty()); - CPPUNIT_ASSERT(pDoc->GetString(ScAddress(0,1,0)).isEmpty()); + CPPUNIT_ASSERT(pDoc->GetString(0,0,0).isEmpty()); + CPPUNIT_ASSERT(pDoc->GetString(0,1,0).isEmpty()); nFirstRowHeight = pDoc->GetRowHeight(0, 0); nSecondRowHeight = pDoc->GetRowHeight(1, 0); @@ -349,7 +354,7 @@ void ScCopyPasteTest::testTdf40993_fillMergedCells() ScTabViewShell* pViewShell = getViewShell(); // check content of the merged cell H11:I11 - CPPUNIT_ASSERT_EQUAL(u"1.5"_ustr, pDoc->GetString(ScAddress(7, 10, 0))); + CPPUNIT_ASSERT_EQUAL(u"1.5"_ustr, pDoc->GetString(7, 10, 0)); // fill operation on the merged cell should clone ATTR_MERGE and ATTR_MERGE_FLAG // (as long as ATTR_MERGE_FLAG has only ScMF::Hor or ScMF::Ver) @@ -474,8 +479,8 @@ void ScCopyPasteTest::testTdf88782_autofillLinearNumbersInMergedCells() { for (int nRow = 8; nRow <= 27; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 22, nRow, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol + 22, nRow, 0); double* pValue1 = pDoc->GetValueCell(ScAddress(nCol, nRow, 0)); double* pValue2 = pDoc->GetValueCell(ScAddress(nCol + 22, nRow, 0)); @@ -492,8 +497,8 @@ void ScCopyPasteTest::testTdf88782_autofillLinearNumbersInMergedCells() { for (int nRow = 30; nRow <= 35; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 16, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol, nRow + 16, 0); double* pValue1 = pDoc->GetValueCell(ScAddress(nCol, nRow, 0)); double* pValue2 = pDoc->GetValueCell(ScAddress(nCol, nRow + 16, 0)); @@ -521,8 +526,8 @@ void ScCopyPasteTest::tdf137621_autofillMergedBool() { for (int nRow = 4; nRow <= 5; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 3, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol, nRow + 3, 0); double* pValue1 = pDoc->GetValueCell(ScAddress(nCol, nRow, 0)); double* pValue2 = pDoc->GetValueCell(ScAddress(nCol, nRow + 3, 0)); @@ -550,8 +555,8 @@ void ScCopyPasteTest::tdf137205_autofillDatesInMergedCells() { for (int nRow = 5; nRow <= 7; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 5, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol, nRow + 5, 0); double* pValue1 = pDoc->GetValueCell(ScAddress(nCol, nRow, 0)); double* pValue2 = pDoc->GetValueCell(ScAddress(nCol, nRow + 5, 0)); @@ -595,8 +600,8 @@ void ScCopyPasteTest::tdf137653_137654_autofillUserlist() { for (int nRow = 5; nRow <= 7; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 4, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol, nRow + 4, 0); bHasIdx1 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow, 0), nIdx1, bMatchCase); bHasIdx2 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow + 4, 0), nIdx2, bMatchCase); @@ -612,8 +617,8 @@ void ScCopyPasteTest::tdf137653_137654_autofillUserlist() { for (int nRow = 16; nRow <= 21; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 4, nRow, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol + 4, nRow, 0); bHasIdx1 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow, 0), nIdx1, bMatchCase); bHasIdx2 = pListData->GetSubIndex(pDoc->GetString(nCol + 4, nRow, 0), nIdx2, bMatchCase); @@ -644,8 +649,8 @@ void ScCopyPasteTest::tdf113500_autofillMixed() { for (int nRow = 5; nRow <= 6; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 4, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol, nRow + 4, 0); OUString aStr1 = pDoc->GetString(nCol, nRow, 0); OUString aStr2 = pDoc->GetString(nCol, nRow + 4, 0); @@ -660,8 +665,8 @@ void ScCopyPasteTest::tdf113500_autofillMixed() { for (int nRow = 16; nRow <= 21; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 4, nRow, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol + 4, nRow, 0); OUString aStr1 = pDoc->GetString(nCol, nRow, 0); OUString aStr2 = pDoc->GetString(nCol + 4, nRow, 0); @@ -697,8 +702,8 @@ void ScCopyPasteTest::tdf137625_autofillMergedUserlist() { for (int nRow = 5; nRow <= 7; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 4, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol, nRow + 4, 0); bHasIdx1 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow, 0), nIdx1, bMatchCase); bHasIdx2 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow + 4, 0), nIdx2, bMatchCase); @@ -714,8 +719,8 @@ void ScCopyPasteTest::tdf137625_autofillMergedUserlist() { for (int nRow = 16; nRow <= 27; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 4, nRow, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol + 4, nRow, 0); bHasIdx1 = pListData->GetSubIndex(pDoc->GetString(nCol, nRow, 0), nIdx1, bMatchCase); bHasIdx2 = pListData->GetSubIndex(pDoc->GetString(nCol + 4, nRow, 0), nIdx2, bMatchCase); @@ -750,8 +755,8 @@ void ScCopyPasteTest::tdf137624_autofillMergedMixed() { for (int nRow = 5; nRow <= 7; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol, nRow + 4, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol, nRow + 4, 0); OUString aStr1 = pDoc->GetString(nCol, nRow, 0); OUString aStr2 = pDoc->GetString(nCol, nRow + 4, 0); @@ -765,8 +770,8 @@ void ScCopyPasteTest::tdf137624_autofillMergedMixed() { for (int nRow = 16; nRow <= 27; nRow++) { - CellType nType1 = pDoc->GetCellType(ScAddress(nCol, nRow, 0)); - CellType nType2 = pDoc->GetCellType(ScAddress(nCol + 4, nRow, 0)); + CellType nType1 = pDoc->GetCellType(nCol, nRow, 0); + CellType nType2 = pDoc->GetCellType(nCol + 4, nRow, 0); OUString aStr1 = pDoc->GetString(nCol, nRow, 0); OUString aStr2 = pDoc->GetString(nCol + 4, nRow, 0); @@ -802,6 +807,51 @@ void ScCopyPasteTest::tdf122716_rtf_portion_encoding() CPPUNIT_ASSERT(rtf_string.indexOf("\\u352\\'3famp\\u363\\'3fnas") >= 0); } +void ScCopyPasteTest::testRTFFontHeight() +{ + createScDoc(); + ScDocument* pDoc = getScDoc(); + ScTabViewShell* pViewShell = getViewShell(); + pDoc->SetString(0, 0, 0, u"Text"_ustr); + sal_uInt32 nHeightPt = 8; + pDoc->ApplyAttr(0, 0, 0, SvxFontHeightItem(nHeightPt * 20, 100, ATTR_FONT_HEIGHT)); + + // Select a range containing A1: + ScRange aRange(0, 0, 0, 1, 0, 0); + pViewShell->GetViewData().GetMarkData().SetMarkArea(aRange); + + // Obtain a transferable, similar to what happens on copy to clipboard: + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + auto xTransferable = pModelObj->getSelection(); + // Get the RTF data: + auto aRTF + = xTransferable->getTransferData({ u"text/rtf"_ustr, {}, cppu::UnoType::get() }); + OUString sRTF; + CPPUNIT_ASSERT(aRTF >>= sRTF); + + // Check that the font height was exported (in Half-point units) + OUString sText = "\\fs" + OUString::number(nHeightPt * 2); + CPPUNIT_ASSERT(sRTF.indexOf(sText) >= 0); +} + +void ScCopyPasteTest::testHtmlImportDataUrlIncompleteBase64() +{ + createScDoc(); + ScDocument* pDoc = getScDoc(); + + // The image carries a "data:" URL whose base64 payload ends with an + // incomplete group: "AAAAA" is one full quartet plus a dangling fifth + // character. Decoding consumes only the first four, so getData() treats + // the payload as malformed and hands back a null pointer. + ScImportExport aObj(*pDoc, ScAddress(0, 0, 0)); + char buf[] = ""; + SvMemoryStream aStream(buf, strlen(buf), StreamMode::READ); + + // Without the accompanying fix, ScHTMLLayoutParser::Image() dereferenced + // that null pointer and the import crashed. + CPPUNIT_ASSERT(aObj.ImportStream(aStream, OUString(), SotClipboardFormatId::HTML)); +} + ScCopyPasteTest::ScCopyPasteTest() : ScModelTestBase(u"/sc/qa/unit/data/"_ustr) { diff --git a/sc/qa/unit/data/123/tdf148749.123 b/sc/qa/unit/data/123/tdf148749.123 new file mode 100644 index 000000000000..5dc0e7e893c5 Binary files /dev/null and b/sc/qa/unit/data/123/tdf148749.123 differ diff --git a/sc/qa/unit/data/dataprovider/csv/mappinggate.csv b/sc/qa/unit/data/dataprovider/csv/mappinggate.csv new file mode 100644 index 000000000000..5ea2ed416fbd --- /dev/null +++ b/sc/qa/unit/data/dataprovider/csv/mappinggate.csv @@ -0,0 +1 @@ +changed diff --git a/sc/qa/unit/data/dataprovider/mappinggate.fods b/sc/qa/unit/data/dataprovider/mappinggate.fods new file mode 100644 index 000000000000..5a4368216caa --- /dev/null +++ b/sc/qa/unit/data/dataprovider/mappinggate.fods @@ -0,0 +1,19 @@ + + + + + + + + unchanged + + + + + + + + + + + diff --git a/sc/qa/unit/data/draw-image-link.fods b/sc/qa/unit/data/draw-image-link.fods new file mode 100644 index 000000000000..994b1d94b713 --- /dev/null +++ b/sc/qa/unit/data/draw-image-link.fods @@ -0,0 +1,30 @@ + + + + + + + + test + + + + + + + + + + + diff --git a/sc/qa/unit/data/draw-object-link.fods b/sc/qa/unit/data/draw-object-link.fods new file mode 100644 index 000000000000..e9beb90167df --- /dev/null +++ b/sc/qa/unit/data/draw-object-link.fods @@ -0,0 +1,30 @@ + + + + + + + + test + + + + + + + + + + + diff --git a/sc/qa/unit/data/fods/DynamicArraySpill.fods b/sc/qa/unit/data/fods/DynamicArraySpill.fods new file mode 100644 index 000000000000..0aad517a9a50 --- /dev/null +++ b/sc/qa/unit/data/fods/DynamicArraySpill.fods @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/fods/reference-union.fods b/sc/qa/unit/data/fods/reference-union.fods new file mode 100644 index 000000000000..3dc82705b133 --- /dev/null +++ b/sc/qa/unit/data/fods/reference-union.fods @@ -0,0 +1,36 @@ + + + + + + + + 1 + 2 + + 10 + 20 + + + + 3 + 4 + + 11 + 21 + + + + + 12 + 22 + + + + + + diff --git a/sc/qa/unit/data/functions/dynamic_array/xlsx/DynamicArrayFixture.xlsx b/sc/qa/unit/data/functions/dynamic_array/xlsx/DynamicArrayFixture.xlsx new file mode 100644 index 000000000000..e3c262cece91 Binary files /dev/null and b/sc/qa/unit/data/functions/dynamic_array/xlsx/DynamicArrayFixture.xlsx differ diff --git a/sc/qa/unit/data/functions/dynamic_array/xlsx/UnionSpillIntersectionOperatorTest.xlsx b/sc/qa/unit/data/functions/dynamic_array/xlsx/UnionSpillIntersectionOperatorTest.xlsx new file mode 100644 index 000000000000..6659c7f331ca Binary files /dev/null and b/sc/qa/unit/data/functions/dynamic_array/xlsx/UnionSpillIntersectionOperatorTest.xlsx differ diff --git a/sc/qa/unit/data/functions/lambda/fods/bycol.fods b/sc/qa/unit/data/functions/lambda/fods/bycol.fods new file mode 100644 index 000000000000..f9f37425c900 --- /dev/null +++ b/sc/qa/unit/data/functions/lambda/fods/bycol.fods @@ -0,0 +1,3643 @@ + + + + 2024-01-16T18:30:06.278000000PT4H54M21S105LibreOfficeDev/27.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/da8934a626c058e8f771c90ccbdc70c7ca9700382026-07-14T11:38:37.377203232 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + € + + + + - + + + € + + + + + + Kč + + + + - + + + Kč + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + € + + + + + € + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + ⌀ + + + + + € + + + - + + € + + + - € + + + + + + + + + + + + + + + + € + + + + + + € + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + € + + + + + + + ( + € + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + Kč + + + + - + + + Kč + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + Kč + + + + - + + + Kč + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + - + + € + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + + - + + € + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + € + + + - + + € + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + + + + True + + + True + + + False + + + + + + € + + + - + + € + + + - + + € + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + € + + + + + € + - + + + + + + + € + + + + - + + + € + + + + + + + + + + + € + + + + - + + € + + + + + + Kč + + + - + + + Kč + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + € + + + + + + + / + + / + + + + + + + / + + / + + + + € + + + + + + - + € + + + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - + + Kč + + + + + + + + + + ¥€ + + + + + + + + + ( + € + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + / + + / + + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + ByCol Function + + + + + + + + + + Result + + + VERDADERO + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + VERDADERO + + + Simple BYCOL formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + + Expected + + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + 21 + + + + 21 + + + + VERDADERO + + + =SUM(BYCOL({1.2.3;4.5.6}; LAMBDA(c; SUM(c)))) + + + + 11 + + + 22 + + + 33 + + + + + + 6 + + + + 6 + + + + VERDADERO + + + =BYCOL({1;2;3}; LAMBDA(c; SUM(c))) + + + + 44 + + + 55 + + + 66 + + + + + + 11 + + + + 11 + + + + VERDADERO + + + =TRANSPOSE(BYCOL({1.2.3;10.20.30}; LAMBDA(c; SUM(c)))) + + + + 77 + + + 88 + + + 99 + + + + + + 22 + + + + 22 + + + + VERDADERO + + + =TRANSPOSE(BYCOL({1.2.3;10.20.30}; LAMBDA(c; SUM(c)))) + + + + + + + 33 + + + + 33 + + + + VERDADERO + + + =TRANSPOSE(BYCOL({1.2.3;10.20.30}; LAMBDA(c; SUM(c)))) + + + + + + + 100 + + + + 100 + + + + VERDADERO + + + =BYCOL(100; LAMBDA(c; SUM(c))) + + + + + + + ABC + + + + ABC + + + + VERDADERO + + + =BYCOL("ABC"; LAMBDA(c; c)) + + + + + + + AD + + + + AD + + + + VERDADERO + + + =TRANSPOSE(BYCOL({"A"."B"."C";"D"."E"."F"}; LAMBDA(c; CONCAT(c)))) + + + + + + + BE + + + + BE + + + + VERDADERO + + + =TRANSPOSE(BYCOL({"A"."B"."C";"D"."E"."F"}; LAMBDA(c; CONCAT(c)))) + + + + + + + CF + + + + CF + + + + VERDADERO + + + =TRANSPOSE(BYCOL({"A"."B"."C";"D"."E"."F"}; LAMBDA(c; CONCAT(c)))) + + + + + + + 132 + + + 165 + + + 198 + + + 132 + + + 165 + + + 198 + + + VERDADERO + + + =BYCOL(J2:L4; LAMBDA(c; SUM(c))) + + + Column reduction over a real range + + + + + + + 11 + + + + 11 + + + + VERDADERO + + + =TRANSPOSE(BYCOL({1.2.3;10.20.30}; SUM)) + + + + + + + 22 + + + + 22 + + + + VERDADERO + + + =TRANSPOSE(BYCOL({1.2.3;10.20.30}; SUM)) + + + + + + + 33 + + + + 33 + + + + VERDADERO + + + =TRANSPOSE(BYCOL({1.2.3;10.20.30}; SUM)) + + + + + + + AD + + + + AD + + + + VERDADERO + + + =TRANSPOSE(BYCOL({"A"."B"."C";"D"."E"."F"}; CONCAT)) + + + + + + + BE + + + + BE + + + + VERDADERO + + + =TRANSPOSE(BYCOL({"A"."B"."C";"D"."E"."F"}; CONCAT)) + + + + + + + CF + + + + CF + + + + VERDADERO + + + =TRANSPOSE(BYCOL({"A"."B"."C";"D"."E"."F"}; CONCAT)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/functions/lambda/fods/byrow.fods b/sc/qa/unit/data/functions/lambda/fods/byrow.fods new file mode 100644 index 000000000000..9d8d7bc5e0a8 --- /dev/null +++ b/sc/qa/unit/data/functions/lambda/fods/byrow.fods @@ -0,0 +1,3640 @@ + + + + 2024-01-16T18:30:06.278000000PT4H51M32S104LibreOfficeDev/27.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/da8934a626c058e8f771c90ccbdc70c7ca9700382026-07-14T11:39:19.329024892 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + € + + + + - + + + € + + + + + + Kč + + + + - + + + Kč + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + € + + + + + € + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + ⌀ + + + + + € + + + - + + € + + + - € + + + + + + + + + + + + + + + + € + + + + + + € + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + € + + + + + + + ( + € + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + Kč + + + + - + + + Kč + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + Kč + + + + - + + + Kč + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + - + + € + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + + - + + € + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + € + + + - + + € + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + + + + True + + + True + + + False + + + + + + € + + + - + + € + + + - + + € + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + € + + + + + € + - + + + + + + + € + + + + - + + + € + + + + + + + + + + + € + + + + - + + € + + + + + + Kč + + + - + + + Kč + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + € + + + + + + + / + + / + + + + + + + / + + / + + + + € + + + + + + - + € + + + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - + + Kč + + + + + + + + + + ¥€ + + + + + + + + + ( + € + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + / + + / + + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + ByRow Function + + + + + + + + + + Result + + + VERDADERO + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + VERDADERO + + + Simple BYROW formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + Expected + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + 21 + + + 21 + + + VERDADERO + + + =SUM(BYROW({1.2.3;4.5.6}; LAMBDA(c; SUM(c)))) + + + + 11 + + + 22 + + + 33 + + + + + + 6 + + + 6 + + + VERDADERO + + + =BYROW({1.2.3}; LAMBDA(c; SUM(c))) + + + + 44 + + + 55 + + + 66 + + + + + + 6 + + + 6 + + + VERDADERO + + + =BYROW({1.2.3;10.20.30}; LAMBDA(c; SUM(c))) + + + + 77 + + + 88 + + + 99 + + + + + + 60 + + + 60 + + + VERDADERO + + + =BYROW({1.2.3;10.20.30}; LAMBDA(c; SUM(c))) + + + + + + + 100 + + + 100 + + + VERDADERO + + + =BYROW(100; LAMBDA(c; SUM(c))) + + + + + + + ABC + + + ABC + + + VERDADERO + + + =BYROW("ABC"; LAMBDA(c; c)) + + + + + + + ABC + + + ABC + + + VERDADERO + + + =BYROW({"A"."B"."C";"D"."E"."F"}; LAMBDA(c; CONCAT(c))) + + + + + + + DEF + + + DEF + + + VERDADERO + + + =BYROW({"A"."B"."C";"D"."E"."F"}; LAMBDA(c; CONCAT(c))) + + + + + + + 66 + + + 66 + + + VERDADERO + + + =BYROW(F2:H4; LAMBDA(c; SUM(c))) + + + Row reduction over a real range + + + + + + + 165 + + + 165 + + + VERDADERO + + + =BYROW(F2:H4; LAMBDA(c; SUM(c))) + + + + + + + 264 + + + 264 + + + VERDADERO + + + =BYROW(F2:H4; LAMBDA(c; SUM(c))) + + + + + + + 3 + + + 3 + + + VERDADERO + + + =BYROW({1.2;3.4}; LAMBDA(r; REDUCE(0; r; LAMBDA(a;v; a + v)))) + + + + + + + 7 + + + 7 + + + VERDADERO + + + =BYROW({1.2;3.4}; LAMBDA(r; REDUCE(0; r; LAMBDA(a;v; a + v)))) + + + + + + + 6 + + + 6 + + + VERDADERO + + + =BYROW({1.2.3;10.20.30}; SUM) + + + + + + + 60 + + + 60 + + + VERDADERO + + + =BYROW({1.2.3;10.20.30}; SUM) + + + + + + + ABC + + + ABC + + + VERDADERO + + + =BYROW({"A"."B"."C";"D"."E"."F"}; CONCAT) + + + + + + + DEF + + + DEF + + + VERDADERO + + + =BYROW({"A"."B"."C";"D"."E"."F"}; CONCAT) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/functions/lambda/fods/isomitted.fods b/sc/qa/unit/data/functions/lambda/fods/isomitted.fods new file mode 100644 index 000000000000..a6b2de432ad7 --- /dev/null +++ b/sc/qa/unit/data/functions/lambda/fods/isomitted.fods @@ -0,0 +1,3478 @@ + + + + 2024-01-16T18:30:06.278000000PT4H58M50S106LibreOfficeDev/27.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/da8934a626c058e8f771c90ccbdc70c7ca9700382026-07-14T11:56:12.018134142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + € + + + + - + + + € + + + + + + Kč + + + + - + + + Kč + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + € + + + + + € + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + ⌀ + + + + + € + + + - + + € + + + - € + + + + + + + + + + + + + + + + € + + + + + + € + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + € + + + + + + + ( + € + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + Kč + + + + - + + + Kč + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + Kč + + + + - + + + Kč + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + - + + € + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + + - + + € + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + € + + + - + + € + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + + + + True + + + True + + + False + + + + + + € + + + - + + € + + + - + + € + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + € + + + + + € + - + + + + + + + € + + + + - + + + € + + + + + + + + + + + € + + + + - + + € + + + + + + Kč + + + - + + + Kč + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + € + + + + + + + / + + / + + + + + + + / + + / + + + + € + + + + + + - + € + + + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - + + Kč + + + + + + + + + + ¥€ + + + + + + + + + ( + € + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + / + + / + + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + isOmitted Function + + + + + + + + + + Result + + + VERDADERO + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + VERDADERO + + + Simple ISOMITTED formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + Expected + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + 1 + + + VERDADERO + + + VERDADERO + + + =LAMBDA(x;y; ISOMITTED(x))(; 5) + + + + + + + 0 + + + FALSO + + + VERDADERO + + + =LAMBDA(x;y; ISOMITTED(x))(3; 5) + + + + + + + 0 + + + FALSO + + + VERDADERO + + + =LAMBDA(x;y; ISOMITTED(x))(3; 5) + + + + + + + 104 + + + 104 + + + VERDADERO + + + =LAMBDA(x;y; IF(ISOMITTED(x); 99; x) + y)(; 5) + + + + + + + 8 + + + 8 + + + VERDADERO + + + =LAMBDA(x;y; IF(ISOMITTED(x); 99; x) + y)(3; 5) + + + + + + + 3 + + + 3 + + + VERDADERO + + + =ERROR.TYPE(F7) + + + + #VALUE! + + + + + + + -1 + + + -1 + + + VERDADERO + + + =LAMBDA(a;b;c; IF(ISOMITTED(b); -1; b))(1; ; 3) + + + + + + + 5 + + + 5 + + + VERDADERO + + + =LAMBDA([x]; IF(ISOMITTED(x);12;5))(1) + + + TODO - Optional parameter, set + + + + + + + 12 + + + 12 + + + VERDADERO + + + =LAMBDA([x]; IF(ISOMITTED(x);12;5))() + + + TODO - Optional parameter, not set + + + + + + + 3 + + + 3 + + + VERDADERO + + + =ERROR.TYPE(F11) + + + TODO - Required parameter, not set + + + #VALUE! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/functions/lambda/fods/lambda.fods b/sc/qa/unit/data/functions/lambda/fods/lambda.fods new file mode 100644 index 000000000000..78313de53a3d --- /dev/null +++ b/sc/qa/unit/data/functions/lambda/fods/lambda.fods @@ -0,0 +1,4447 @@ + + + + 2024-01-16T18:30:06.278000000PT4H57M26S111LibreOfficeDev/27.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/da8934a626c058e8f771c90ccbdc70c7ca9700382026-07-14T12:19:52.769789866 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + € + + + + - + + + € + + + + + + Kč + + + + - + + + Kč + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + € + + + + + € + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + ⌀ + + + + + € + + + - + + € + + + - € + + + + + + + + + + + + + + + + € + + + + + + € + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + € + + + + + + + ( + € + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + Kč + + + + - + + + Kč + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + Kč + + + + - + + + Kč + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + - + + € + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + + - + + € + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + € + + + - + + € + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + + + + True + + + True + + + False + + + + + + € + + + - + + € + + + - + + € + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + € + + + + + € + - + + + + + + + € + + + + - + + + € + + + + + + + + + + + € + + + + - + + € + + + + + + Kč + + + - + + + Kč + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + € + + + + + + + / + + / + + + + + + + / + + / + + + + € + + + + + + - + € + + + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - + + Kč + + + + + + + + + + ¥€ + + + + + + + + + ( + € + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + / + + / + + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + Lambda Function + + + + + + + + + + Result + + + VERDADERO + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + VERDADERO + + + Simple LAMBDA formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + Expected + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + 2 + + + 1 + + + VERDADERO + + + =LAMBDA(1)() + + + No parameters, constant body + + + 10 + + + + + + + 2 + + + 2 + + + VERDADERO + + + =LAMBDA(a; 2)(1) + + + One unused parameter, constant body + + + 20 + + + + + + + 10 + + + 10 + + + VERDADERO + + + =LAMBDA(a; a)(F2) + + + Reference as input + + + 30 + + + + + + + 3 + + + 3 + + + VERDADERO + + + =LAMBDA(a; a)(3) + + + Value as input + + + 40 + + + + + + + 4 + + + 4 + + + VERDADERO + + + =LAMBDA(a; a * 2)(2) + + + One parameter, simple expression on it + + + + + + + 7 + + + 7 + + + VERDADERO + + + =LAMBDA(x;y; x + y)(3; 4) + + + Two parameters, arithmetic + + + + + + + 10 + + + 10 + + + VERDADERO + + + =LAMBDA(a; a + a)(5) + + + Parameter used more than once + + + + + + + 15 + + + 15 + + + VERDADERO + + + =LAMBDA(x;y; x + x * y)(3; 4) + + + Operator precedence inside the body + + + + + + + 5 + + + 5 + + + VERDADERO + + + =LAMBDA(a; IF(a > 0; a; -a))(-5) + + + Function inside the body + + + + + + + hi! + + + hi! + + + VERDADERO + + + =LAMBDA(a; a & "!")("hi") + + + String argument flowing through identity body + + + + + + + 2 + + + 2 + + + VERDADERO + + + =LAMBDA(SQRT; SQRT(SQRT))(4) + + + Name precedence matches MSO + + + + + + + 100 + + + 100 + + + VERDADERO + + + =LAMBDA(r; SUM(r))(F2:F5) + + + Range as input + + + + + + + 6 + + + 6 + + + VERDADERO + + + =LAMBDA(a;b;c; a + b + c)(1; 2; 3) + + + + + + + 0 + + + 0 + + + VERDADERO + + + =LAMBDA(a;b;c; a + b + c)(;;) + + + Unspecified value is defaulting to 0 + + + + + + + 1 + + + VERDADERO + + + VERDADERO + + + =LAMBDA(x; x > 5)(7) + + + + + + 2 + + + 2 + + + VERDADERO + + + =ERROR.TYPE(LAMBDA(x; 1 / x)(0)) + + + Div by 0 + + + + + + 3 + + + 3 + + + VERDADERO + + + =ERROR.TYPE(LAMBDA(x;y; x + y)(1)) + + + Missing required parameter + + + + + + 7 + + + 7 + + + VERDADERO + + + =LAMBDA(x; LAMBDA(y; x + y))(3)(4) + + + Nested LAMBDA + + + + + + 16 + + + 16 + + + VERDADERO + + + =LET(f; LAMBDA(x; x * x); f(4)) + + + LAMBDA in a LET function + + + + + + 6 + + + 6 + + + VERDADERO + + + =LAMBDA(a; SUM(a))({1;2;3}) + + + Array as input + + + + + + 82 + + + 82 + + + VERDADERO + + + =SUM(LAMBDA(a; a * 2)({10;11;20})) + + + Jump matrix - array input + + + + + + 200 + + + 200 + + + VERDADERO + + + =SUM(LAMBDA(a; a * 2)(F2:F5)) + + + Jump matrix - range input + + + + + + 200 + + + 200 + + + VERDADERO + + + =SUM(LAMBDA(a; a * 2)(DATARANGE)) + + + Jump matrix - named range input + + + + + + 120 + + + 120 + + + VERDADERO + + + =LET(g; LAMBDA(self;n; IF(n <= 1; 1; n * self(self; n - 1))); g(g; 5)) + + + Recursive LAMBDA + + + + + + 7 + + + 7 + + + VERDADERO + + + =PLUS2(5) + + + PLUS2 set with LAMBDA in the Name Manager + + + + + + 4 + + + 4 + + + VERDADERO + + + =SUM(4) + + + SUM LAMBDA function is set in Name Manager, make sure built-in function has priority + + + + + + 100 + + + 100 + + + VERDADERO + + + =LAMBDA(x; SUM(x))(100) + + + If you use SUM in LAMBDA, it will use the built-in function not the named LAMBDA + + + + + + 110 + + + 110 + + + VERDADERO + + + =LAMBDA(x;f; f(x))(100;SUM) + + + If you use SUM as parameter to LAMBDA, the named LAMBDA will be used instead + + + + + + 3 + + + 3 + + + VERDADERO + + + =LAMBDA(f;n; f(n))(PLUS2; 1) + + + Named lambda as parameter + + + + + + 4 + + + 4 + + + VERDADERO + + + =LAMBDA(f;n; f(n))(COUNT; {5.6.7.8}) + + + ETA-LAMBDA use in LAMBDA as parameter + + + + + + 10 + + + 10 + + + VERDADERO + + + =LAMBDA(f; f(5))(LAMBDA(x; x * 2)) + + + LAMBDA as parameter to LAMBDA + + + + + + 7 + + + 7 + + + VERDADERO + + + =LAMBDA(f;x; f(f(x)))(LAMBDA(n; n + 1); 5) + + + Call LAMBDA 2 times + + + + + + 32 + + + 32 + + + VERDADERO + + + =APPLYTWICE(LAMBDA(x; x * 2); 8) + + + Export of a named LAMBDA that takes a LAMBDA argument + + + + + + 15 + + + 15 + + + VERDADERO + + + =LAMBDA(x; x + $F$2)(5) + + + A LAMBDA body that closes over a sheet cell + + + + + + 333 + + + 333 + + + VERDADERO + + + =LAMBDA(a; LAMBDA(b; LAMBDA(c; a + b + c)))(3)(30)(300) + + + Triple curry + + + + + + 20 + + + 20 + + + VERDADERO + + + =LAMBDA(x;y; x + y)(20;) + + + Value not provided - second parameter + + + + + + 2 + + + 2 + + + VERDADERO + + + =LAMBDA(x;y; x + y)(;2) + + + Value not provided - first parameter + + + + + + 7 + + + 7 + + + VERDADERO + + + =LAMBDA(x;[y];[z]; x + y + z)(7) + + + Optional used but not set - number + + + + + + xy + + + xy + + + VERDADERO + + + =LAMBDA(x;[y];[z]; x & y & z)("xy") + + + Optional used but not set - string + + + + + + 6 + + + 6 + + + VERDADERO + + + =LAMBDA(x; LAMBDA(x; x*2)(3))(10) + + + Name shadowing - LAMBDA within LAMBDA + + + + + + 6 + + + 6 + + + VERDADERO + + + =LAMBDA(x; LAMBDA(y;x; x*2)(5;3))(10) + + + + + + 6 + + + 6 + + + VERDADERO + + + =LAMBDA(x; LET(x;3; x*2))(10) + + + Name shadowing - LET within LAMBDA + + + + + + 6 + + + 6 + + + VERDADERO + + + =LAMBDA(x; LET(y;5; x;3; x*2))(10) + + + + + + 42 + + + 42 + + + VERDADERO + + + =LAMBDA(x$; x$)(42) + + + TODO: x$ probably shouldn't be a valid name + + + + + + Err:508 + + + + VERDADERO + + + =LAMBDA(AX1; 0) + + + AX1 = cell reference name - invalid syntax + + + + + + Err:508 + + + + VERDADERO + + + =LAMBDA([x]; y; 0) + + + Optional, then required parameter - invalid syntax + + + + + + Err:509 + + + + VERDADERO + + + =LAMBDA(ab!; 0) + + + + + + Err:508 + + + + VERDADERO + + + =LAMBDA(aa#a; 0) + + + + + + Err:508 + + + + VERDADERO + + + =LAMBDA(a%; 0) + + + + + + Err:509 + + + + VERDADERO + + + =LAMBDA(#REF!; 0) + + + + + + Err:508 + + + + VERDADERO + + + =LAMBDA("x"; 0)(1) + + + + + + Err:539 + + + + VERDADERO + + + =LAMBDA(x;y;z; {x,y,z}))(1; 20; 3) + + + Can't create a literal array from parameters + + + + + + Err:514 + + + + VERDADERO + + + =F54(5) + + + + λ + + + + + + 15 + + + 15 + + + VERDADERO + + + =F55(5) + + + + λ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/functions/lambda/fods/makearray.fods b/sc/qa/unit/data/functions/lambda/fods/makearray.fods new file mode 100644 index 000000000000..5515ae6caa07 --- /dev/null +++ b/sc/qa/unit/data/functions/lambda/fods/makearray.fods @@ -0,0 +1,3681 @@ + + + + 2024-01-16T18:30:06.278000000PT4H57M40S105LibreOfficeDev/27.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/da8934a626c058e8f771c90ccbdc70c7ca9700382026-07-14T11:36:20.348084939 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + € + + + + - + + + € + + + + + + Kč + + + + - + + + Kč + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + € + + + + + € + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + ⌀ + + + + + € + + + - + + € + + + - € + + + + + + + + + + + + + + + + € + + + + + + € + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + € + + + + + + + ( + € + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + Kč + + + + - + + + Kč + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + Kč + + + + - + + + Kč + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + - + + € + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + + - + + € + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + € + + + - + + € + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + + + + True + + + True + + + False + + + + + + € + + + - + + € + + + - + + € + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + € + + + + + € + - + + + + + + + € + + + + - + + + € + + + + + + + + + + + € + + + + - + + € + + + + + + Kč + + + - + + + Kč + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + € + + + + + + + / + + / + + + + + + + / + + / + + + + € + + + + + + - + € + + + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - + + Kč + + + + + + + + + + ¥€ + + + + + + + + + ( + € + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + / + + / + + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + MakeArray Function + + + + + + + + + + Result + + + VERDADERO + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + VERDADERO + + + Simple MAKEARRAY formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + + Expected + + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + 11 + + + 21 + + + 11 + + + 21 + + + VERDADERO + + + =TRANSPOSE(MAKEARRAY(2; 3; LAMBDA(r;c; r * 10 + c))) + + + + + + + 12 + + + 22 + + + 12 + + + 22 + + + VERDADERO + + + =TRANSPOSE(MAKEARRAY(2; 3; LAMBDA(r;c; r * 10 + c))) + + + + + + + 13 + + + 23 + + + 13 + + + 23 + + + VERDADERO + + + =TRANSPOSE(MAKEARRAY(2; 3; LAMBDA(r;c; r * 10 + c))) + + + + + + + 3 + + + + 3 + + + + VERDADERO + + + =ERROR.TYPE(H5) + + + + #VALUE! + + + + + + + 2 + + + + 2 + + + + VERDADERO + + + =MAKEARRAY(2; 1; LAMBDA(r;c; r + c)) + + + + + + + 3 + + + + 3 + + + + VERDADERO + + + =MAKEARRAY(2; 1; LAMBDA(r;c; r + c)) + + + + + + + 6 + + + + 6 + + + + VERDADERO + + + =MAKEARRAY(2; 1; LAMBDA(r;c; 6)) + + + + + + + 6 + + + + 6 + + + + VERDADERO + + + =MAKEARRAY(2; 1; LAMBDA(r;c; 6)) + + + + + + + 2 + + + + 2 + + + + VERDADERO + + + =MAKEARRAY(2; 1; SUM) + + + + + + + 3 + + + + 3 + + + + VERDADERO + + + =MAKEARRAY(2; 1; SUM) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/functions/lambda/fods/map.fods b/sc/qa/unit/data/functions/lambda/fods/map.fods new file mode 100644 index 000000000000..c83a0855a120 --- /dev/null +++ b/sc/qa/unit/data/functions/lambda/fods/map.fods @@ -0,0 +1,3735 @@ + + + + 2024-01-16T18:30:06.278000000PT4H50M25S103LibreOfficeDev/27.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/da8934a626c058e8f771c90ccbdc70c7ca9700382026-07-14T11:41:42.178822676 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + € + + + + - + + + € + + + + + + Kč + + + + - + + + Kč + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + € + + + + + € + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + ⌀ + + + + + € + + + - + + € + + + - € + + + + + + + + + + + + + + + + € + + + + + + € + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + € + + + + + + + ( + € + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + Kč + + + + - + + + Kč + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + Kč + + + + - + + + Kč + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + - + + € + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + + - + + € + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + € + + + - + + € + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + + + + True + + + True + + + False + + + + + + € + + + - + + € + + + - + + € + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + € + + + + + € + - + + + + + + + € + + + + - + + + € + + + + + + + + + + + € + + + + - + + € + + + + + + Kč + + + - + + + Kč + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + € + + + + + + + / + + / + + + + + + + / + + / + + + + € + + + + + + - + € + + + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - + + Kč + + + + + + + + + + ¥€ + + + + + + + + + ( + € + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + / + + / + + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + Map Function + + + + + + + + + + Result + + + VERDADERO + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + VERDADERO + + + Simple MAP formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + Expected + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + 1 + + + 1 + + + VERDADERO + + + =MAP({1;2;3}; LAMBDA(x; x * x)) + + + + 2 + + + + + + + + 4 + + + 4 + + + VERDADERO + + + =MAP({1;2;3}; LAMBDA(x; x * x)) + + + + 5 + + + + + + + + 9 + + + 9 + + + VERDADERO + + + =MAP({1;2;3}; LAMBDA(x; x * x)) + + + + 2 + + + + + + 11 + + + 11 + + + VERDADERO + + + =MAP({1;2;3}; {10;20;30}; LAMBDA(a;b; a + b)) + + + + 1 + + + + + + 22 + + + 22 + + + VERDADERO + + + =MAP({1;2;3}; {10;20;30}; LAMBDA(a;b; a + b)) + + + + + + + + + 33 + + + 33 + + + VERDADERO + + + =MAP({1;2;3}; {10;20;30}; LAMBDA(a;b; a + b)) + + + + + + + + + A + + + A + + + VERDADERO + + + =MAP({"a";"b"}; LAMBDA(x; UPPER(x))) + + + + + + + + + B + + + B + + + VERDADERO + + + =MAP({"a";"b"}; LAMBDA(x; UPPER(x))) + + + + + + + + + 4 + + + 4 + + + VERDADERO + + + =MAP(F2:F5; LAMBDA(x; x * x)) + + + Element map over a range + + + + + + + 25 + + + 25 + + + VERDADERO + + + =MAP(F2:F5; LAMBDA(x; x * x)) + + + + + + + + + 4 + + + 4 + + + VERDADERO + + + =MAP(F2:F5; LAMBDA(x; x * x)) + + + + + + + + + 1 + + + 1 + + + VERDADERO + + + =MAP(F2:F5; LAMBDA(x; x * x)) + + + + + + + + + 2 + + + 2 + + + VERDADERO + + + =LET(double; LAMBDA(x; x * 2); MAP({1;2;3}; double)) + + + + + + + + + 4 + + + 4 + + + VERDADERO + + + =LET(double; LAMBDA(x; x * 2); MAP({1;2;3}; double)) + + + + + + + + + 6 + + + 6 + + + VERDADERO + + + =LET(double; LAMBDA(x; x * 2); MAP({1;2;3}; double)) + + + + + + + + + 1,5 + + + 1,5 + + + VERDADERO + + + =SUM(IFERROR(MAP({1.0.2}; LAMBDA(x; 1 / x)); 0)) + + + + + + 2 + + + 2 + + + VERDADERO + + + =MAP({1;2;3}; {1;2}; LAMBDA(a;b; a + b)) + + + + + + 4 + + + 4 + + + VERDADERO + + + =MAP({1;2;3}; {1;2}; LAMBDA(a;b; a + b)) + + + + + + #N/A + + + + VERDADERO + + + =MAP({1;2;3}; {1;2}; LAMBDA(a;b; a + b)) + + + + + + 7 + + + 7 + + + VERDADERO + + + =ERROR.TYPE(A20) + + + + + + A + + + A + + + VERDADERO + + + =MAP({"a";"b"}; UPPER) + + + + + + B + + + B + + + VERDADERO + + + =MAP({"a";"b"}; UPPER) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/functions/lambda/fods/reduce.fods b/sc/qa/unit/data/functions/lambda/fods/reduce.fods new file mode 100644 index 000000000000..a1fb32dc98e9 --- /dev/null +++ b/sc/qa/unit/data/functions/lambda/fods/reduce.fods @@ -0,0 +1,3668 @@ + + + + 2024-01-16T18:30:06.278000000PT4H52M50S105LibreOfficeDev/27.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/da8934a626c058e8f771c90ccbdc70c7ca9700382026-07-14T11:43:33.530697003 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + € + + + + - + + + € + + + + + + Kč + + + + - + + + Kč + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + € + + + + + € + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + ⌀ + + + + + € + + + - + + € + + + - € + + + + + + + + + + + + + + + + € + + + + + + € + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + € + + + + + + + ( + € + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + Kč + + + + - + + + Kč + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + Kč + + + + - + + + Kč + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + - + + € + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + + - + + € + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + € + + + - + + € + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + + + + True + + + True + + + False + + + + + + € + + + - + + € + + + - + + € + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + € + + + + + € + - + + + + + + + € + + + + - + + + € + + + + + + + + + + + € + + + + - + + € + + + + + + Kč + + + - + + + Kč + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + € + + + + + + + / + + / + + + + + + + / + + / + + + + € + + + + + + - + € + + + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - + + Kč + + + + + + + + + + ¥€ + + + + + + + + + ( + € + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + / + + / + + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + Reduce Function + + + + + + + + + + Result + + + VERDADERO + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + VERDADERO + + + Simple REDUCE formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + Expected + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + 10 + + + 10 + + + VERDADERO + + + =REDUCE(0; {1.2.3.4}; LAMBDA(acc;val; acc + val)) + + + + 12 + + + 3 + + + + + + + 24 + + + 24 + + + VERDADERO + + + =REDUCE(1; {1.2.3.4}; LAMBDA(acc;val; acc * val)) + + + + 14 + + + 3 + + + + + + + abc + + + abc + + + VERDADERO + + + =REDUCE(""; {"a"."b"."c"}; LAMBDA(acc;val; acc & val)) + + + + 11 + + + 5 + + + + + + + 10_abc + + + 10_abc + + + VERDADERO + + + =REDUCE(10 & "_"; {"a"."b"."c"}; LAMBDA(acc;val; acc & val)) + + + + + + + 6 + + + 6 + + + VERDADERO + + + =REDUCE(; {1.2.3}; LAMBDA(acc;val; acc + val)) + + + + + + + 26 + + + 26 + + + VERDADERO + + + =REDUCE(5; {1.2.3;4.5.6}; LAMBDA(acc;val; acc + val)) + + + REDUCE over a 2D array + + + + + + + 39 + + + 39 + + + VERDADERO + + + =REDUCE(2; F2:F4; LAMBDA(acc;val; acc + val)) + + + REDUCE over a range + + + + + + + 18 + + + 18 + + + VERDADERO + + + =REDUCE(10; UNIQUE(G2:G4); LAMBDA(acc;val; acc + val)) + + + + + + + -1 + + + -1 + + + VERDADERO + + + =IFERROR(REDUCE(0; {1.0}; LAMBDA(acc;val; acc / val)); -1) + + + + + + abc + + + abc + + + VERDADERO + + + =REDUCE(""; {"a"."b"."c"}; CONCAT) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/functions/lambda/fods/scan.fods b/sc/qa/unit/data/functions/lambda/fods/scan.fods new file mode 100644 index 000000000000..1dc3bed6f449 --- /dev/null +++ b/sc/qa/unit/data/functions/lambda/fods/scan.fods @@ -0,0 +1,3689 @@ + + + + 2024-01-16T18:30:06.278000000PT4H52M38S105LibreOfficeDev/27.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/da8934a626c058e8f771c90ccbdc70c7ca9700382026-07-14T11:45:06.521839634 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + € + + + + - + + + € + + + + + + Kč + + + + - + + + Kč + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + € + + + + + € + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + ⌀ + + + + + € + + + - + + € + + + - € + + + + + + + + + + + + + + + + € + + + + + + € + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + € + + + + + + + ( + € + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + Kč + + + + - + + + Kč + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + Kč + + + + - + + + Kč + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + - + + € + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + + - + + € + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + € + + + - + + € + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + + + + True + + + True + + + False + + + + + + € + + + - + + € + + + - + + € + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + € + + + + + € + - + + + + + + + € + + + + - + + + € + + + + + + + + + + + € + + + + - + + € + + + + + + Kč + + + - + + + Kč + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + € + + + + + + + / + + / + + + + + + + / + + / + + + + € + + + + + + - + € + + + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - + + Kč + + + + + + + + + + ¥€ + + + + + + + + + ( + € + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + / + + / + + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + Scan Function + + + + + + + + + + Result + + + VERDADERO + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + VERDADERO + + + Simple SCAN formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + Expected + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + 1 + + + 1 + + + VERDADERO + + + =TRANSPOSE(SCAN(0; {1.2.3.4}; LAMBDA(acc;val; acc + val))) + + + + + + + 3 + + + 3 + + + VERDADERO + + + =TRANSPOSE(SCAN(0; {1.2.3.4}; LAMBDA(acc;val; acc + val))) + + + + + + + 6 + + + 6 + + + VERDADERO + + + =TRANSPOSE(SCAN(0; {1.2.3.4}; LAMBDA(acc;val; acc + val))) + + + + + + + 10 + + + 10 + + + VERDADERO + + + =TRANSPOSE(SCAN(0; {1.2.3.4}; LAMBDA(acc;val; acc + val))) + + + + + + + 1 + + + 1 + + + VERDADERO + + + =TRANSPOSE(SCAN(; {1.2.3}; LAMBDA(acc;val; acc + val))) + + + + + + + 3 + + + 3 + + + VERDADERO + + + =TRANSPOSE(SCAN(; {1.2.3}; LAMBDA(acc;val; acc + val))) + + + + + + + 6 + + + 6 + + + VERDADERO + + + =TRANSPOSE(SCAN(; {1.2.3}; LAMBDA(acc;val; acc + val))) + + + + + + + aa + + + aa + + + VERDADERO + + + =SCAN("a"; {"a";"b";"c"}; LAMBDA(acc;val; acc & val)) + + + + + + + aab + + + aab + + + VERDADERO + + + =SCAN("a"; {"a";"b";"c"}; LAMBDA(acc;val; acc & val)) + + + + + + + aabc + + + aabc + + + VERDADERO + + + =SCAN("a"; {"a";"b";"c"}; LAMBDA(acc;val; acc & val)) + + + + + + + aa + + + aa + + + VERDADERO + + + =SCAN("a"; {"a";"b";"c"}; CONCAT) + + + + + + aab + + + aab + + + VERDADERO + + + =SCAN("a"; {"a";"b";"c"}; CONCAT) + + + + + + aabc + + + aabc + + + VERDADERO + + + =SCAN("a"; {"a";"b";"c"}; CONCAT) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/functions/spreadsheet/fods/arraytotext.fods b/sc/qa/unit/data/functions/spreadsheet/fods/arraytotext.fods new file mode 100644 index 000000000000..40590ce23195 --- /dev/null +++ b/sc/qa/unit/data/functions/spreadsheet/fods/arraytotext.fods @@ -0,0 +1,3563 @@ + + + + 2024-01-16T18:30:06.278000000PT4H52M46S106LibreOfficeDev/27.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/21b9909afa3fad5042f053919f69848ae82534d32026-07-22T15:46:24.953508804 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ₧ + + + - + + + ₧ + + + + + + ₧ + + + + - + + + ₧ + + + + + + € + + + + - + + + € + + + + + + Kč + + + + - + + + Kč + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + € + + + + + € + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + ⌀ + + + + + € + + + - + + € + + + - € + + + + + + + + + + + + + + + + € + + + + + + € + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + € + + + + + + + ( + € + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + Kč + + + + - + + + Kč + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + Kč + + + + - + + + Kč + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + - + + € + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + € + + + + - + + € + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + € + + + - + + € + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + + + + True + + + True + + + False + + + + + + € + + + - + + € + + + - + + € + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + € + + + + + € + - + + + + + + + € + + + + - + + + € + + + + + + + + + + + € + + + + - + + € + + + + + + Kč + + + - + + + Kč + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + € + + + + + + + / + + / + + + + + + + / + + / + + + + € + + + + + + - + € + + + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + Kč + + + - + + Kč + + + + + Kč + + + + - + + Kč + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + Kč + + + - + + + Kč + + + + - + + Kč + + + + + + + + + + ¥€ + + + + + + + + + ( + € + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + + € + + + + - + + + € + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + € + + + - + + + € + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + € + + + - + + + € + + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + € + + + - + + € + + + + + € + + + + - + + € + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + ArrayToText Function + + + + + + + + + + Result + + + TRUE + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + TRUE + + + Simple ARRAYTOTEXT formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + Expected + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + aaa, 1 + + + aaa, 1 + + + TRUE + + + =ARRAYTOTEXT(H5:I5) + + + + + + aaa, 1, TRUE, Text "ABC" + + + aaa, 1, TRUE, Text "ABC" + + + TRUE + + + =ARRAYTOTEXT(H5:I6) + + + + + + {"aaa",1;TRUE,"Text ""ABC"""} + + + {"aaa",1;TRUE,"Text ""ABC"""} + + + TRUE + + + =ARRAYTOTEXT(H5:I6, 1) + + + + + + aaa, 1, TRUE, Text "ABC", , 2.5 + + + aaa, 1, TRUE, Text "ABC", , 2.5 + + + TRUE + + + =ARRAYTOTEXT(H5:I7) + + + + + + aaa + + + 1 + + + #DIV/0! + + + + + {"aaa",1;TRUE,"Text ""ABC""";,2.5} + + + {"aaa",1;TRUE,"Text ""ABC""";,2.5} + + + TRUE + + + =ARRAYTOTEXT(H5:I7, 1) + + + + + + TRUE + + + Text "ABC" + + + + + + x + + + x + + + TRUE + + + =ARRAYTOTEXT("x") + + + + + + 2.5 + + + + + + {5} + + + {5} + + + TRUE + + + =ARRAYTOTEXT(5,1) + + + + + + + + #DIV/0! + + + + TRUE + + + =ARRAYTOTEXT(J5) + + + + + + + + + + + 1, #DIV/0! + + + 1, #DIV/0! + + + TRUE + + + =ARRAYTOTEXT(I5:J5) + + + + + + + + + + + #VALUE! + + + + TRUE + + + =ARRAYTOTEXT(H2:I5,2) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/data/functions/spreadsheet/fods/drop.fods b/sc/qa/unit/data/functions/spreadsheet/fods/drop.fods index 3026865b9d9b..4f0487d933a8 100644 --- a/sc/qa/unit/data/functions/spreadsheet/fods/drop.fods +++ b/sc/qa/unit/data/functions/spreadsheet/fods/drop.fods @@ -9,6 +9,7 @@ + @@ -17,12 +18,13 @@ + - + @@ -3297,7 +3299,7 @@ ???(???) - 00/00/0000, 00:00:00 + 00/00/0000, 00:00:00 @@ -3670,25 +3672,19 @@ - - January + + Err:502 - - 100 + + Err:502 - - 1 + + Err:502 - - January - - - 100 - - - 1 - - + + + + VERDADERO @@ -3701,25 +3697,19 @@ - - February + + Err:502 - - 150 + + Err:502 - - 2 + + Err:502 - - February - - - 150 - - - 2 - - + + + + VERDADERO @@ -3734,23 +3724,16 @@ - #N/A + Err:502 - #N/A + Err:502 - #N/A - - - #N/A - - - #N/A - - - #N/A + Err:502 + + VERDADERO @@ -3765,18 +3748,18 @@ - - + + Err:502 - - + + Err:502 - - + + Err:502 - + VERDADERO @@ -3790,25 +3773,18 @@ - - April + + Err:502 - - 250 + + Err:502 - - 4 + + Err:502 - - April - - - 250 - - - 4 - - + + + VERDADERO @@ -3822,25 +3798,19 @@ - - May + + Err:502 - - 300 + + Err:502 - - 5 + + Err:502 - - May - - - 300 - - - 5 - - + + + + VERDADERO @@ -3867,25 +3837,19 @@ - - January + + Err:502 - - 100 + + Err:502 - - 1 + + Err:502 - - January - - - 100 - - - 1 - - + + + + VERDADERO @@ -3894,25 +3858,19 @@ - - February + + Err:502 - - 150 + + Err:502 - - 2 + + Err:502 - - February - - - 150 - - - 2 - - + + + + VERDADERO @@ -3922,23 +3880,16 @@ - #N/A + Err:502 - #N/A + Err:502 - #N/A - - - #N/A - - - #N/A - - - #N/A + Err:502 + + VERDADERO @@ -3948,18 +3899,18 @@ - - + + Err:502 - - + + Err:502 - - + + Err:502 - + VERDADERO @@ -3968,25 +3919,18 @@ - - April + + Err:502 - - 250 + + Err:502 - - 4 + + Err:502 - - April - - - 250 - - - 4 - - + + + VERDADERO @@ -3995,25 +3939,19 @@ - - May + + Err:502 - - 300 + + Err:502 - - 5 + + Err:502 - - May - - - 300 - - - 5 - - + + + + VERDADERO @@ -4261,25 +4199,19 @@ - - January + + Err:502 - - 100 + + Err:502 - - 1 + + Err:502 - - January - - - 100 - - - 1 - - + + + + VERDADERO @@ -4288,25 +4220,19 @@ - - February + + Err:502 - - 150 + + Err:502 - - 2 + + Err:502 - - February - - - 150 - - - 2 - - + + + + VERDADERO @@ -4316,23 +4242,16 @@ - #N/A + Err:502 - #N/A + Err:502 - #N/A - - - #N/A - - - #N/A - - - #N/A + Err:502 + + VERDADERO @@ -4342,18 +4261,18 @@ - - + + Err:502 - - + + Err:502 - - + + Err:502 - + VERDADERO @@ -4362,25 +4281,18 @@ - - April + + Err:502 - - 250 + + Err:502 - - 4 + + Err:502 - - April - - - 250 - - - 4 - - + + + VERDADERO @@ -4389,25 +4301,19 @@ - - May + + Err:502 - - 300 + + Err:502 - - 5 + + Err:502 - - May - - - 300 - - - 5 - - + + + + VERDADERO @@ -4425,25 +4331,19 @@ - - January + + Err:502 - - 100 + + Err:502 - - 1 + + Err:502 - - January - - - 100 - - - 1 - - + + + + VERDADERO @@ -4452,25 +4352,19 @@ - - February + + Err:502 - - 150 + + Err:502 - - 2 + + Err:502 - - February - - - 150 - - - 2 - - + + + + VERDADERO @@ -4480,23 +4374,16 @@ - #N/A + Err:502 - #N/A + Err:502 - #N/A - - - #N/A - - - #N/A - - - #N/A + Err:502 + + VERDADERO @@ -4506,18 +4393,18 @@ - - + + Err:502 - - + + Err:502 - - + + Err:502 - + VERDADERO @@ -4526,25 +4413,18 @@ - - April + + Err:502 - - 250 + + Err:502 - - 4 + + Err:502 - - April - - - 250 - - - 4 - - + + + VERDADERO @@ -4553,25 +4433,19 @@ - - May + + Err:502 - - 300 + + Err:502 - - 5 + + Err:502 - - May - - - 300 - - - 5 - - + + + + VERDADERO @@ -4589,25 +4463,19 @@ - - January + + Err:502 - - 100 + + Err:502 - - 1 + + Err:502 - - January - - - 100 - - - 1 - - + + + + VERDADERO @@ -4616,25 +4484,19 @@ - - February + + Err:502 - - 150 + + Err:502 - - 2 + + Err:502 - - February - - - 150 - - - 2 - - + + + + VERDADERO @@ -4644,23 +4506,16 @@ - #N/A + Err:502 - #N/A + Err:502 - #N/A - - - #N/A - - - #N/A - - - #N/A + Err:502 + + VERDADERO @@ -4670,18 +4525,18 @@ - - + + Err:502 - - + + Err:502 - - + + Err:502 - + VERDADERO @@ -4690,25 +4545,18 @@ - - April + + Err:502 - - 250 + + Err:502 - - 4 + + Err:502 - - April - - - 250 - - - 4 - - + + + VERDADERO @@ -4717,25 +4565,19 @@ - - May + + Err:502 - - 300 + + Err:502 - - 5 + + Err:502 - - May - - - 300 - - - 5 - - + + + + VERDADERO @@ -5530,7 +5372,7 @@ - + @@ -5540,4 +5382,4 @@ - + \ No newline at end of file diff --git a/sc/qa/unit/data/functions/spreadsheet/fods/let.fods b/sc/qa/unit/data/functions/spreadsheet/fods/let.fods index 06a390722a77..4b7becd0f8fe 100644 --- a/sc/qa/unit/data/functions/spreadsheet/fods/let.fods +++ b/sc/qa/unit/data/functions/spreadsheet/fods/let.fods @@ -4741,19 +4741,999 @@ - + - - - - + + 2 + + + + 1 + + + + IGAZ + + + =LET(1) + + + No parameters, constant body + + + + 10 + + + + + + 2 + + + + 2 + + + + IGAZ + + + =LET(a;1; 2) + + + One unused parameter, constant body + + + + 20 + + + + + + 10 + + + + 10 + + + + IGAZ + + + =LET(a;N55; a) + + + Reference as input + + + + 30 + + + + + + 3 + + + + 3 + + + + IGAZ + + + =LET(a;3; a) + + + Value as input + + + + 40 + + + + + + 4 + + + + 4 + + + + IGAZ + + + =LET(a;2; a * 2) + + + One parameter, simple expression on it + - + + + 7 + + + + 7 + + + + IGAZ + + + =LET(x;3; y;4; x + y) + + + Two parameters, arithmetic + + + + + + 10 + + + + 10 + + + + IGAZ + + + =LET(a;5; a + a) + + + Parameter used more than once + + + + + + 15 + + + + 15 + + + + IGAZ + + + =LET(x;3; y;4; x + x * y) + + + Operator precedence inside the body + + + + + + 5 + + + + 5 + + + + IGAZ + + + =LET(a;-5; IF(a > 0; a; -a)) + + + Function inside the body + + + + + + hi! + + + + hi! + + + + IGAZ + + + =LET(a;"hi"; a & "!") + + + String argument flowing through identity body + + + + + + 2 + + + + 2 + + + + IGAZ + + + =LET(SQRT;4; SQRT(SQRT)) + + + Name precedence matches MSO + + + + + + 100 + + + + 100 + + + + IGAZ + + + =LET(r;N55:N58; SUM(r)) + + + Range as input + + + + + + 6 + + + + 6 + + + + IGAZ + + + =LET(a;1; b;2; c;3; a + b + c) + + + + + + 0 + + + + 0 + + + + IGAZ + + + =LET(a;; b;; c;; a + b + c) + + + Unspecified value is defaulting to 0 + + + + + + 1 + + + + IGAZ + + + + IGAZ + + + =LET(x;7; x > 5) + + + + + + 2 + + + + 2 + + + + IGAZ + + + =ERROR.TYPE(LET(x;0; 1 / x)) + + + Div by 0 + + + + + + 3 + + + + IGAZ + + + =LET(x;1; y; x + y) + + + Missing subexpression + + + + + + 7 + + + + 7 + + + + IGAZ + + + =LET(x;3; LET(y;4; x + y)) + + + Nested LET + + + + + + 16 + + + + 16 + + + + IGAZ + + + =LET(f; LAMBDA(x; x * x); f(4)) + + + LAMBDA in a LET function + + + + + + 6 + + + + 6 + + + + IGAZ + + + =LET(a;{1;2;3}; SUM(a)) + + + Array as input + + + + + + 82 + + + + 82 + + + + IGAZ + + + =SUM(LET(a;{10;11;20}; a * 2)) + + + Jump matrix - array input + + + + + + 200 + + + + 200 + + + + IGAZ + + + =SUM(LET(a;N55:N58; a * 2)) + + + Jump matrix - range input + + + + + + 200 + + + + 200 + + + + IGAZ + + + =SUM(LET(a;DATARANGE; a * 2)) + + + Jump matrix - named range input + + + + + + 120 + + + + 120 + + + + IGAZ + + + =LET(g; LAMBDA(self;n; IF(n <= 1; 1; n * self(self; n - 1))); g(g; 5)) + + + Recursive LAMBDA + + + + + + 100 + + + + 100 + + + + IGAZ + + + =LET(x;100; SUM(x)) + + + If you use SUM in LET, it will use the built-in function not the named LAMBDA + + + + + + 110 + + + + 110 + + + + IGAZ + + + =LET(x;100; f;SUM; f(x)) + + + If you use SUM as a subexpression in LET, the named LAMBDA will be used instead + + + + + + 3 + + + + 3 + + + + IGAZ + + + =LET(f;PLUS2; n;1; f(n)) + + + Named lambda as parameter + + + + + + 4 + + + + 4 + + + + IGAZ + + + =LET(f;COUNT; n;{5.6.7.8}; f(n)) + + + ETA-LAMBDA use in LET as parameter + + + + + + 10 + + + + 10 + + + + IGAZ + + + =LET(f;LAMBDA(x; x * 2); f(5)) + + + LAMBDA as parameter to LET + + + + + + 7 + + + + 7 + + + + IGAZ + + + =LET(f;LAMBDA(n; n + 1); x;5; f(f(x))) + + + Call LAMBDA 2 times + + + + + + 15 + + + + 15 + + + + IGAZ + + + =LET(x;5; x + $N$55) + + + A LET body that closes over a sheet cell + + + + + + 333 + + + + 333 + + + + IGAZ + + + =LET(a;3; LET(b;30; LET(c;300; a + b + c))) + + + Triple curry + + + + + + 20 + + + + 20 + + + + IGAZ + + + =LET(x;20; y;; x + y) + + + Value not provided - second parameter + + + + + + 2 + + + + 2 + + + + IGAZ + + + =LET(x;; y;2; x + y) + + + Value not provided - first parameter + + + + + + 6 + + + + 6 + + + + IGAZ + + + =LET(x;10; LAMBDA(x; x*2)(3)) + + + Name shadowing - LAMBDA within LET + + + + + + 6 + + + + 6 + + + + IGAZ + + + =LET(x;10; LAMBDA(y;x; x*2)(5;3)) + + + + + + 6 + + + + 6 + + + + IGAZ + + + =LET(x;10; LET(x;3; x*2)) + + + Name shadowing - LET within LET + + + + + + 6 + + + + 6 + + + + IGAZ + + + =LET(x;10; LET(y;5; x;3; x*2)) + + + + + + 42 + + + + 42 + + + + IGAZ + + + =LET(x$;42; x$) + + + TODO: x$ probably shouldn't be a valid name + + + + + + Err:508 + + + + IGAZ + + + =LET(AX1;0; 0) + + + AX1 = cell reference name - invalid syntax + + + + + + Err:509 + + + + IGAZ + + + =LET(ab!;0; 0) + + + + + + Err:508 + + + + IGAZ + + + =LET(aa#a;0; 0) + + + + + + Err:508 + + + + IGAZ + + + =LET(a%;0; 0) + + + + + + Err:509 + + + + IGAZ + + + =LET(#REF!;0; 0) + + + + + + Err:508 + + + + IGAZ + + + =LET("x";1; 0) + + + + + + Err:539 + + + + IGAZ + + + =LET(x;1; y;20; z;3; {x,y,z}) + + + Can't create a literal array from parameters + + + + + + 21 + + + + 21 + + + + VERDADERO + + + =LET(x;5;f;LAMBDA(x;x*3);f(7)) + + + more shadowing tests + + + + + + 21 + + + + 21 + + + + VERDADERO + + + =LET(x;5;f;LAMBDA(x;x*3);f(7)) + + + + + + 26 + + + + 26 + + + + VERDADERO + + + =LET(x;5;f;LAMBDA(z;z*3+x);f(7)) + + + + + + 19 + + + + 19 + + + + VERDADERO + + + =LET(x;5;LET(x;7;x*2)+x) + + + + + + 19 + + + + 19 + + + + VERDADERO + + + =LET(x;5;LET(y;1;x;7;x*2)+x) + + + + + + 68 + + + + 68 + + + + VERDADERO + + + =LET(x;5;LET(y;1;x;x+2;x*9)+x) + + + + + + + + + @@ -4772,7 +5752,11 @@ - + + + + + - \ No newline at end of file + diff --git a/sc/qa/unit/data/functions/spreadsheet/fods/take.fods b/sc/qa/unit/data/functions/spreadsheet/fods/take.fods index 1ee29fd0c124..85f4fa35bc83 100644 --- a/sc/qa/unit/data/functions/spreadsheet/fods/take.fods +++ b/sc/qa/unit/data/functions/spreadsheet/fods/take.fods @@ -9,6 +9,7 @@ + @@ -17,12 +18,13 @@ + - + @@ -3166,6 +3168,11 @@ + + + + + @@ -3297,7 +3304,7 @@ ???(???) - 00/00/0000, 00:00:00 + 00/00/0000, 00:00:00 @@ -4643,25 +4650,19 @@ - - January + + Err:502 - - 100 + + Err:502 - - 1 + + Err:502 - - January - - - 100 - - - 1 - - + + + + VERDADERO @@ -4670,25 +4671,19 @@ - - February + + Err:502 - - 150 + + Err:502 - - 2 + + Err:502 - - February - - - 150 - - - 2 - - + + + + VERDADERO @@ -4698,24 +4693,17 @@ - #N/A + Err:502 - #N/A + Err:502 - #N/A + Err:502 - - #N/A - - - #N/A - - - #N/A - - + + + VERDADERO @@ -4724,18 +4712,18 @@ - - + + Err:502 - - + + Err:502 - - + + Err:502 - + VERDADERO @@ -4744,25 +4732,18 @@ - - April + + Err:502 - - 250 + + Err:502 - - 4 + + Err:502 - - April - - - 250 - - - 4 - - + + + VERDADERO @@ -4771,25 +4752,19 @@ - - May + + Err:502 - - 300 + + Err:502 - - 5 + + Err:502 - - May - - - 300 - - - 5 - - + + + + VERDADERO @@ -5082,14 +5057,19 @@ - + + + + + + - + \ No newline at end of file diff --git a/sc/qa/unit/data/functions/spreadsheet/fods/textafter.fods b/sc/qa/unit/data/functions/spreadsheet/fods/textafter.fods index 72549f4d7e40..ed1723bbe743 100644 --- a/sc/qa/unit/data/functions/spreadsheet/fods/textafter.fods +++ b/sc/qa/unit/data/functions/spreadsheet/fods/textafter.fods @@ -10,23 +10,24 @@ - + - - + + + - + @@ -3119,7 +3120,7 @@ - + @@ -3130,7 +3131,7 @@ - + @@ -3192,13 +3193,13 @@ - + - + - + @@ -3220,7 +3221,7 @@ ???(???) - 00/00/0000, 00:00:00 + 00/00/0000, 00:00:00 @@ -3335,7 +3336,7 @@ Data - + Aiden Williams, CEO @@ -3351,7 +3352,7 @@ Williams, CEO - + VERDADERO @@ -3372,7 +3373,7 @@ CEO - + VERDADERO @@ -3391,7 +3392,7 @@ #N/A - + VERDADERO @@ -3410,7 +3411,7 @@ Lucas, Manager:1234:5678 - + VERDADERO @@ -3427,7 +3428,7 @@ Manager:1234:5678 - + VERDADERO @@ -3442,7 +3443,7 @@ #N/A - + VERDADERO @@ -3457,7 +3458,7 @@ #N/A - + VERDADERO @@ -3474,7 +3475,7 @@ Manager:1234:5678 - + VERDADERO @@ -3489,7 +3490,7 @@ Lucas, Manager:1234:5678 - + VERDADERO @@ -3502,7 +3503,7 @@ #N/A - + VERDADERO @@ -3517,7 +3518,7 @@ LucasÇÇÇManager - + VERDADERO @@ -3532,7 +3533,7 @@ Manager - + VERDADERO @@ -3546,7 +3547,7 @@ 5678 - + VERDADERO @@ -3560,7 +3561,7 @@ 5678 - + VERDADERO @@ -3574,7 +3575,7 @@ 5678 - + VERDADERO @@ -3589,7 +3590,7 @@ LucasÇÇÇManager - + VERDADERO @@ -3602,7 +3603,7 @@ #N/A - + VERDADERO @@ -3611,13 +3612,11 @@ - - Brown, Lucas, Manager:1234:5678 + + - - Brown, Lucas, Manager:1234:5678 - - + + VERDADERO @@ -3630,7 +3629,7 @@ #N/A - + VERDADERO @@ -3639,13 +3638,11 @@ - - Manager:1234:5678 + + - - Manager:1234:5678 - - + + VERDADERO @@ -3660,7 +3657,7 @@ Not Found - + VERDADERO @@ -3675,7 +3672,7 @@ Not Found - + VERDADERO @@ -3690,7 +3687,7 @@ Lucas, Manager:1234:5678 - + VERDADERO @@ -3698,14 +3695,35 @@ - + + + Brown, Lucas, Manager:1234:5678 + + + Brown, Lucas, Manager:1234:5678 + + + VERDADERO + + + =TEXTAFTER(F3; "xxx"; -1;;1) + + + + + + + + + + - + @@ -3715,4 +3733,4 @@ - + \ No newline at end of file diff --git a/sc/qa/unit/data/functions/spreadsheet/fods/textbefore.fods b/sc/qa/unit/data/functions/spreadsheet/fods/textbefore.fods index a7a33b26c6c6..f314dbc60e47 100644 --- a/sc/qa/unit/data/functions/spreadsheet/fods/textbefore.fods +++ b/sc/qa/unit/data/functions/spreadsheet/fods/textbefore.fods @@ -18,12 +18,13 @@ + - + @@ -3205,7 +3206,7 @@ ???(???) - 00/00/0000, 00:00:00 + 00/00/0000, 00:00:00 @@ -3669,14 +3670,27 @@ - + + + + + + + VERDADERO + + + =TEXTBEFORE(F3; "xxx"; -1;;1) + + + + - + @@ -3686,4 +3700,4 @@ - + \ No newline at end of file diff --git a/sc/qa/unit/data/ods/ArrayFormulasStatic.ods b/sc/qa/unit/data/ods/ArrayFormulasStatic.ods new file mode 100644 index 000000000000..e058827075a6 Binary files /dev/null and b/sc/qa/unit/data/ods/ArrayFormulasStatic.ods differ diff --git a/sc/qa/unit/data/ods/cool15769_minimal_DB_ranges.ods b/sc/qa/unit/data/ods/cool15769_minimal_DB_ranges.ods new file mode 100644 index 000000000000..8bec28137b64 Binary files /dev/null and b/sc/qa/unit/data/ods/cool15769_minimal_DB_ranges.ods differ diff --git a/sc/qa/unit/data/ods/cool15780_totals_row_content.ods b/sc/qa/unit/data/ods/cool15780_totals_row_content.ods new file mode 100644 index 000000000000..30a55eb34ca2 Binary files /dev/null and b/sc/qa/unit/data/ods/cool15780_totals_row_content.ods differ diff --git a/sc/qa/unit/data/ods/fdo30900-1.ods b/sc/qa/unit/data/ods/fdo30900-1.ods new file mode 100644 index 000000000000..2e421f917e8a Binary files /dev/null and b/sc/qa/unit/data/ods/fdo30900-1.ods differ diff --git a/sc/qa/unit/data/ods/fdo67682-2.ods b/sc/qa/unit/data/ods/fdo67682-2.ods new file mode 100644 index 000000000000..0e06d30c609c Binary files /dev/null and b/sc/qa/unit/data/ods/fdo67682-2.ods differ diff --git a/sc/qa/unit/data/ods/offsetIllegalParam.ods b/sc/qa/unit/data/ods/offsetIllegalParam.ods new file mode 100644 index 000000000000..5bef675ab0a5 Binary files /dev/null and b/sc/qa/unit/data/ods/offsetIllegalParam.ods differ diff --git a/sc/qa/unit/data/ods/ooo88173-1.ods b/sc/qa/unit/data/ods/ooo88173-1.ods new file mode 100644 index 000000000000..a85c56e620bd Binary files /dev/null and b/sc/qa/unit/data/ods/ooo88173-1.ods differ diff --git a/sc/qa/unit/data/ods/tdf140866.ods b/sc/qa/unit/data/ods/tdf140866_copy_shape_preserves_comment.ods similarity index 100% rename from sc/qa/unit/data/ods/tdf140866.ods rename to sc/qa/unit/data/ods/tdf140866_copy_shape_preserves_comment.ods diff --git a/sc/qa/unit/data/solver/ConstrainedLinear.fods b/sc/qa/unit/data/solver/ConstrainedLinear.fods new file mode 100644 index 000000000000..5954b9a23f65 --- /dev/null +++ b/sc/qa/unit/data/solver/ConstrainedLinear.fods @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/sccomp/qa/unit/data/MultiVariable.ods b/sc/qa/unit/data/solver/MultiVariable.ods similarity index 100% rename from sccomp/qa/unit/data/MultiVariable.ods rename to sc/qa/unit/data/solver/MultiVariable.ods diff --git a/sc/qa/unit/data/solver/ResourceDepletion.fods b/sc/qa/unit/data/solver/ResourceDepletion.fods new file mode 100644 index 000000000000..8af7f4da744e --- /dev/null +++ b/sc/qa/unit/data/solver/ResourceDepletion.fods @@ -0,0 +1,119 @@ + + + + + + + periods + rate + stock + discount + cost + + objective + + textractstockutilityremaining + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sccomp/qa/unit/data/Simple.ods b/sc/qa/unit/data/solver/Simple.ods similarity index 100% rename from sccomp/qa/unit/data/Simple.ods rename to sc/qa/unit/data/solver/Simple.ods diff --git a/sccomp/qa/unit/data/TwoVariables.ods b/sc/qa/unit/data/solver/TwoVariables.ods similarity index 100% rename from sccomp/qa/unit/data/TwoVariables.ods rename to sc/qa/unit/data/solver/TwoVariables.ods diff --git a/sc/qa/unit/data/xls/XlStartupExternal.xls b/sc/qa/unit/data/xls/XlStartupExternal.xls new file mode 100644 index 000000000000..b15b7f5379c5 Binary files /dev/null and b/sc/qa/unit/data/xls/XlStartupExternal.xls differ diff --git a/sc/qa/unit/data/xls/emptyAnchor.xls b/sc/qa/unit/data/xls/emptyAnchor.xls new file mode 100644 index 000000000000..1d41fec01149 Binary files /dev/null and b/sc/qa/unit/data/xls/emptyAnchor.xls differ diff --git a/sc/qa/unit/data/xls/external_named_function.xls b/sc/qa/unit/data/xls/external_named_function.xls new file mode 100644 index 000000000000..26526c28ef18 Binary files /dev/null and b/sc/qa/unit/data/xls/external_named_function.xls differ diff --git a/sc/qa/unit/data/xls/fdo55572-1.xls b/sc/qa/unit/data/xls/fdo55572-1.xls new file mode 100644 index 000000000000..f4adc24fd389 --- /dev/null +++ b/sc/qa/unit/data/xls/fdo55572-1.xls @@ -0,0 +1,242 @@ + + + + + + Uakari Software Srl + Analisi Venduto per Aliquota IVA + vers. 1.0 ( 12/01/2012) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Analisi Venduto per Aliquota IVA + + + + + + + Periodo + + + + + Da + + + 2012-10-03T00:00:00.000 + + + A + + + 2012-10-03T00:00:00.000 + + + + + Intervallo + + + + + Da + + + 00:00:00 + + + A + + + 23:59:59 + + + + + + + + + + + + + + + Created by: Uakari Report + + + + 03/10/2012 12:29 + + + 1 + + + / + + + 1 + + + + + + + + + 9 + + + + \ No newline at end of file diff --git a/sc/qa/unit/data/xls/forum-en-29552.xls b/sc/qa/unit/data/xls/forum-en-29552.xls new file mode 100644 index 000000000000..a5cae30ea7cc Binary files /dev/null and b/sc/qa/unit/data/xls/forum-en-29552.xls differ diff --git a/sc/qa/unit/data/xls/forum-fr-59757.xls b/sc/qa/unit/data/xls/forum-fr-59757.xls new file mode 100644 index 000000000000..320451cb9f44 Binary files /dev/null and b/sc/qa/unit/data/xls/forum-fr-59757.xls differ diff --git a/sc/qa/unit/data/xls/forum-mso-de-37362.xls b/sc/qa/unit/data/xls/forum-mso-de-37362.xls new file mode 100644 index 000000000000..75ea5e83b7c9 Binary files /dev/null and b/sc/qa/unit/data/xls/forum-mso-de-37362.xls differ diff --git a/sc/qa/unit/data/xls/forum-mso-de-48440.xls b/sc/qa/unit/data/xls/forum-mso-de-48440.xls new file mode 100644 index 000000000000..fc480793a0ff Binary files /dev/null and b/sc/qa/unit/data/xls/forum-mso-de-48440.xls differ diff --git a/sc/qa/unit/data/xls/forum-mso-de-49320.xls b/sc/qa/unit/data/xls/forum-mso-de-49320.xls new file mode 100644 index 000000000000..fe7a53dad01f Binary files /dev/null and b/sc/qa/unit/data/xls/forum-mso-de-49320.xls differ diff --git a/sc/qa/unit/data/xls/forum-mso-en4-102737.xls b/sc/qa/unit/data/xls/forum-mso-en4-102737.xls new file mode 100644 index 000000000000..075dc4477f82 Binary files /dev/null and b/sc/qa/unit/data/xls/forum-mso-en4-102737.xls differ diff --git a/sc/qa/unit/data/xls/forum-mso-en4-109082.xls b/sc/qa/unit/data/xls/forum-mso-en4-109082.xls new file mode 100644 index 000000000000..837eff1a1374 Binary files /dev/null and b/sc/qa/unit/data/xls/forum-mso-en4-109082.xls differ diff --git a/sc/qa/unit/data/xls/forum-mso-en4-147004.xls b/sc/qa/unit/data/xls/forum-mso-en4-147004.xls new file mode 100644 index 000000000000..ff29e1131ae9 Binary files /dev/null and b/sc/qa/unit/data/xls/forum-mso-en4-147004.xls differ diff --git a/sc/qa/unit/data/xls/forum-mso-en4-243595.xls b/sc/qa/unit/data/xls/forum-mso-en4-243595.xls new file mode 100644 index 000000000000..2ab6bdae8fad Binary files /dev/null and b/sc/qa/unit/data/xls/forum-mso-en4-243595.xls differ diff --git a/sc/qa/unit/data/xls/forum-mso-en4-258437.xls b/sc/qa/unit/data/xls/forum-mso-en4-258437.xls new file mode 100644 index 000000000000..290ed870e576 Binary files /dev/null and b/sc/qa/unit/data/xls/forum-mso-en4-258437.xls differ diff --git a/sc/qa/unit/data/xls/forum-mso-en4-368528.xls b/sc/qa/unit/data/xls/forum-mso-en4-368528.xls new file mode 100644 index 000000000000..e97c5711e49f Binary files /dev/null and b/sc/qa/unit/data/xls/forum-mso-en4-368528.xls differ diff --git a/sc/qa/unit/data/xls/pictureOrder.xls b/sc/qa/unit/data/xls/pictureOrder.xls new file mode 100644 index 000000000000..07e8a9d4508f Binary files /dev/null and b/sc/qa/unit/data/xls/pictureOrder.xls differ diff --git a/sc/qa/unit/data/xls/pivottable_dates_grouping.xls b/sc/qa/unit/data/xls/pivottable_dates_grouping.xls new file mode 100644 index 000000000000..1e85e3452187 Binary files /dev/null and b/sc/qa/unit/data/xls/pivottable_dates_grouping.xls differ diff --git a/sc/qa/unit/data/xls/pivottable_ext_grouping.xls b/sc/qa/unit/data/xls/pivottable_ext_grouping.xls new file mode 100644 index 000000000000..3c5957e40a9a Binary files /dev/null and b/sc/qa/unit/data/xls/pivottable_ext_grouping.xls differ diff --git a/sc/qa/unit/data/xls/pivottable_ext_source_fields.xls b/sc/qa/unit/data/xls/pivottable_ext_source_fields.xls new file mode 100644 index 000000000000..c17b7185107d Binary files /dev/null and b/sc/qa/unit/data/xls/pivottable_ext_source_fields.xls differ diff --git a/sc/qa/unit/data/xls/pivottable_number_grouping.xls b/sc/qa/unit/data/xls/pivottable_number_grouping.xls new file mode 100644 index 000000000000..784bb74fafe8 Binary files /dev/null and b/sc/qa/unit/data/xls/pivottable_number_grouping.xls differ diff --git a/sc/qa/unit/data/xls/user_defined_function.xls b/sc/qa/unit/data/xls/user_defined_function.xls new file mode 100644 index 000000000000..d272c1db1223 Binary files /dev/null and b/sc/qa/unit/data/xls/user_defined_function.xls differ diff --git a/sc/qa/unit/data/xlsb/pivot-table/calcfields.xlsb b/sc/qa/unit/data/xlsb/pivot-table/calcfields.xlsb index 9b89a784d88a..ca7bf35fc751 100644 Binary files a/sc/qa/unit/data/xlsb/pivot-table/calcfields.xlsb and b/sc/qa/unit/data/xlsb/pivot-table/calcfields.xlsb differ diff --git a/sc/qa/unit/data/xlsb/pivot-table/position.xlsb b/sc/qa/unit/data/xlsb/pivot-table/position.xlsb new file mode 100644 index 000000000000..5ea6bfce2241 Binary files /dev/null and b/sc/qa/unit/data/xlsb/pivot-table/position.xlsb differ diff --git a/sc/qa/unit/data/xlsx/Book1_custom.xlsx b/sc/qa/unit/data/xlsx/Book1_custom.xlsx new file mode 100644 index 000000000000..dea8e847d8e3 Binary files /dev/null and b/sc/qa/unit/data/xlsx/Book1_custom.xlsx differ diff --git a/sc/qa/unit/data/xlsx/IntersectionOperatorFixture.xlsx b/sc/qa/unit/data/xlsx/IntersectionOperatorFixture.xlsx new file mode 100644 index 000000000000..7458b80d5c67 Binary files /dev/null and b/sc/qa/unit/data/xlsx/IntersectionOperatorFixture.xlsx differ diff --git a/sc/qa/unit/data/xlsx/MissingPathExternal.xlsx b/sc/qa/unit/data/xlsx/MissingPathExternal.xlsx new file mode 100644 index 000000000000..62832b1d44d0 Binary files /dev/null and b/sc/qa/unit/data/xlsx/MissingPathExternal.xlsx differ diff --git a/sc/qa/unit/data/xlsx/NamedSheetViews.xlsx b/sc/qa/unit/data/xlsx/NamedSheetViews.xlsx new file mode 100644 index 000000000000..76abfca9a78c Binary files /dev/null and b/sc/qa/unit/data/xlsx/NamedSheetViews.xlsx differ diff --git a/sc/qa/unit/data/xlsx/SimpleSpillOperatorFixture.xlsx b/sc/qa/unit/data/xlsx/SimpleSpillOperatorFixture.xlsx new file mode 100644 index 000000000000..424b78d95ef5 Binary files /dev/null and b/sc/qa/unit/data/xlsx/SimpleSpillOperatorFixture.xlsx differ diff --git a/sc/qa/unit/data/xlsx/Spill.xlsx b/sc/qa/unit/data/xlsx/Spill.xlsx new file mode 100644 index 000000000000..a4277e8f3c61 Binary files /dev/null and b/sc/qa/unit/data/xlsx/Spill.xlsx differ diff --git a/sc/qa/unit/data/xlsx/TableEmptyHeaders.xlsx b/sc/qa/unit/data/xlsx/TableEmptyHeaders.xlsx new file mode 100644 index 000000000000..a21b0de4972c Binary files /dev/null and b/sc/qa/unit/data/xlsx/TableEmptyHeaders.xlsx differ diff --git a/sc/qa/unit/data/xlsx/TableStyleTest.xlsx b/sc/qa/unit/data/xlsx/TableStyleTest.xlsx new file mode 100644 index 000000000000..aaabd558e3e7 Binary files /dev/null and b/sc/qa/unit/data/xlsx/TableStyleTest.xlsx differ diff --git a/sc/qa/unit/data/xlsx/XlStartupExternal.xlsx b/sc/qa/unit/data/xlsx/XlStartupExternal.xlsx new file mode 100644 index 000000000000..005cc93a3579 Binary files /dev/null and b/sc/qa/unit/data/xlsx/XlStartupExternal.xlsx differ diff --git a/sc/qa/unit/data/xlsx/autofilterShowButton.xlsx b/sc/qa/unit/data/xlsx/autofilterShowButton.xlsx new file mode 100644 index 000000000000..5f48831e54ce Binary files /dev/null and b/sc/qa/unit/data/xlsx/autofilterShowButton.xlsx differ diff --git a/sc/qa/unit/data/xlsx/checkbox-form-control-align.xlsx b/sc/qa/unit/data/xlsx/checkbox-form-control-align.xlsx new file mode 100644 index 000000000000..e2acf07b00b7 Binary files /dev/null and b/sc/qa/unit/data/xlsx/checkbox-form-control-align.xlsx differ diff --git a/sc/qa/unit/data/xlsx/checkbox-form-control-font.xlsx b/sc/qa/unit/data/xlsx/checkbox-form-control-font.xlsx new file mode 100644 index 000000000000..0a94ded90322 Binary files /dev/null and b/sc/qa/unit/data/xlsx/checkbox-form-control-font.xlsx differ diff --git a/sc/qa/unit/data/xlsx/cool14390_chart_external_ref.xlsx b/sc/qa/unit/data/xlsx/cool14390_chart_external_ref.xlsx new file mode 100644 index 000000000000..36e3519e41dc Binary files /dev/null and b/sc/qa/unit/data/xlsx/cool14390_chart_external_ref.xlsx differ diff --git a/sc/qa/unit/data/xlsx/data_validation_test.xlsx b/sc/qa/unit/data/xlsx/data_validation_test.xlsx new file mode 100644 index 000000000000..28ea950a2baa Binary files /dev/null and b/sc/qa/unit/data/xlsx/data_validation_test.xlsx differ diff --git a/sc/qa/unit/data/xlsx/empty_ext_defined_name.xlsx b/sc/qa/unit/data/xlsx/empty_ext_defined_name.xlsx new file mode 100644 index 000000000000..2be478c920e3 Binary files /dev/null and b/sc/qa/unit/data/xlsx/empty_ext_defined_name.xlsx differ diff --git a/sc/qa/unit/data/xlsx/forum-mso-de-104083.xlsx b/sc/qa/unit/data/xlsx/forum-mso-de-104083.xlsx new file mode 100644 index 000000000000..db22f2fd794c Binary files /dev/null and b/sc/qa/unit/data/xlsx/forum-mso-de-104083.xlsx differ diff --git a/sc/qa/unit/data/xlsx/forum-mso-en4-134670.xlsx b/sc/qa/unit/data/xlsx/forum-mso-en4-134670.xlsx new file mode 100644 index 000000000000..2c972936aca9 Binary files /dev/null and b/sc/qa/unit/data/xlsx/forum-mso-en4-134670.xlsx differ diff --git a/sc/qa/unit/data/xlsx/forum-mso-en4-145327.xlsx b/sc/qa/unit/data/xlsx/forum-mso-en4-145327.xlsx new file mode 100644 index 000000000000..dcaa193db68c Binary files /dev/null and b/sc/qa/unit/data/xlsx/forum-mso-en4-145327.xlsx differ diff --git a/sc/qa/unit/data/xlsx/invalid-named-range.xlsx b/sc/qa/unit/data/xlsx/invalid-named-range.xlsx deleted file mode 100644 index 53feabec382f..000000000000 Binary files a/sc/qa/unit/data/xlsx/invalid-named-range.xlsx and /dev/null differ diff --git a/sc/qa/unit/data/xlsx/invalid_ext_data_validation.xlsx b/sc/qa/unit/data/xlsx/invalid_ext_data_validation.xlsx new file mode 100644 index 000000000000..a4c6d6140d33 Binary files /dev/null and b/sc/qa/unit/data/xlsx/invalid_ext_data_validation.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_10_FormatDefinitionNotMatchingPivotTable.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_10_FormatDefinitionNotMatchingPivotTable.xlsx index 7413f28e33fe..e585180421c1 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_10_FormatDefinitionNotMatchingPivotTable.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_10_FormatDefinitionNotMatchingPivotTable.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_11_WholeDataColumnSelected.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_11_WholeDataColumnSelected.xlsx index 8ba00ddf5788..c0c7173f20c5 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_11_WholeDataColumnSelected.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_11_WholeDataColumnSelected.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_12_WholeLabelColumnSelected.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_12_WholeLabelColumnSelected.xlsx index 63442d84060f..c0335ca95e80 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_12_WholeLabelColumnSelected.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_12_WholeLabelColumnSelected.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_13_SelectionInLabelAndData.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_13_SelectionInLabelAndData.xlsx index 053af3f3687b..4110d69d2d8f 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_13_SelectionInLabelAndData.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_13_SelectionInLabelAndData.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_14_TwoRowsDataFieldInColumn_LabelColor.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_14_TwoRowsDataFieldInColumn_LabelColor.xlsx index 43df4ab75130..bc8dbd0e66d6 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_14_TwoRowsDataFieldInColumn_LabelColor.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_14_TwoRowsDataFieldInColumn_LabelColor.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_15_TwoDataFieldColumns_WholeDataColumnSelected.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_15_TwoDataFieldColumns_WholeDataColumnSelected.xlsx index 7b74a09c4f04..4df4ffb1255f 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_15_TwoDataFieldColumns_WholeDataColumnSelected.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_15_TwoDataFieldColumns_WholeDataColumnSelected.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_1_DataFieldInRow_RowLabelColor.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_1_DataFieldInRow_RowLabelColor.xlsx index cd1b66f7cd06..197ed816dd86 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_1_DataFieldInRow_RowLabelColor.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_1_DataFieldInRow_RowLabelColor.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_2_DataFieldInRow_ColumnLabelColor.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_2_DataFieldInRow_ColumnLabelColor.xlsx index ea1482bd617e..81e889421d2e 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_2_DataFieldInRow_ColumnLabelColor.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_2_DataFieldInRow_ColumnLabelColor.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_3_DataFieldInColumn_ColumnLabelColor.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_3_DataFieldInColumn_ColumnLabelColor.xlsx index 462f6d1219e6..fbbae518f971 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_3_DataFieldInColumn_ColumnLabelColor.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_3_DataFieldInColumn_ColumnLabelColor.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_4_DataFieldInColumn_DataColor.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_4_DataFieldInColumn_DataColor.xlsx index e3eaf72b3ebf..a3dcdc3f4e6b 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_4_DataFieldInColumn_DataColor.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_4_DataFieldInColumn_DataColor.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_5_DataFieldInColumnAndTwoRowFields_DataColor.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_5_DataFieldInColumnAndTwoRowFields_DataColor.xlsx index 2e1d3c62296e..6f0d0b6bb977 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_5_DataFieldInColumnAndTwoRowFields_DataColor.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_5_DataFieldInColumnAndTwoRowFields_DataColor.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_6_SingleDataFieldInColumn_DataColor.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_6_SingleDataFieldInColumn_DataColor.xlsx index 4e82b47ec1e5..ccd12790ecc7 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_6_SingleDataFieldInColumn_DataColor.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_6_SingleDataFieldInColumn_DataColor.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_7_TwoRowTwoColumnFields_DataColor.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_7_TwoRowTwoColumnFields_DataColor.xlsx index 798e3bf82772..1df6fe5d49f9 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_7_TwoRowTwoColumnFields_DataColor.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_7_TwoRowTwoColumnFields_DataColor.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_8_DataFieldInRow_DataColor.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_8_DataFieldInRow_DataColor.xlsx index 7663554c501d..4ee8b13b917c 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_8_DataFieldInRow_DataColor.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_8_DataFieldInRow_DataColor.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_9_MultipleSelections.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_9_MultipleSelections.xlsx index 6ef6cbaa4274..bbdff6179e26 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_9_MultipleSelections.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableCellFormatsTest_9_MultipleSelections.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableFormatsGrandTotal.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableFormatsGrandTotal.xlsx new file mode 100644 index 000000000000..757690bddc70 Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableFormatsGrandTotal.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/PivotTableFormatsSubTotals.xlsx b/sc/qa/unit/data/xlsx/pivot-table/PivotTableFormatsSubTotals.xlsx new file mode 100644 index 000000000000..4a3d28c783fc Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot-table/PivotTableFormatsSubTotals.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/calcfields.xlsx b/sc/qa/unit/data/xlsx/pivot-table/calcfields.xlsx index fb11118d7da9..0fff67b7f4ec 100644 Binary files a/sc/qa/unit/data/xlsx/pivot-table/calcfields.xlsx and b/sc/qa/unit/data/xlsx/pivot-table/calcfields.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivot-table/tdf122473_PivotTableLabelRotation.xlsx b/sc/qa/unit/data/xlsx/pivot-table/tdf122473_PivotTableLabelRotation.xlsx new file mode 100644 index 000000000000..292f7cb05a5d Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot-table/tdf122473_PivotTableLabelRotation.xlsx differ diff --git a/sc/qa/unit/data/xlsx/pivottable_invalid_formats.xlsx b/sc/qa/unit/data/xlsx/pivottable_invalid_formats.xlsx new file mode 100644 index 000000000000..dd18774e7000 Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivottable_invalid_formats.xlsx differ diff --git a/sc/qa/unit/data/xlsx/queryTableExport.xlsx b/sc/qa/unit/data/xlsx/queryTableExport.xlsx new file mode 100644 index 000000000000..50d47ade247d Binary files /dev/null and b/sc/qa/unit/data/xlsx/queryTableExport.xlsx differ diff --git a/sc/qa/unit/data/xlsx/shape-macro-ext-ref.xlsx b/sc/qa/unit/data/xlsx/shape-macro-ext-ref.xlsx new file mode 100644 index 000000000000..fdc2d04fba5e Binary files /dev/null and b/sc/qa/unit/data/xlsx/shape-macro-ext-ref.xlsx differ diff --git a/sc/qa/unit/data/xlsx/tableStyleInnerBorders.xlsx b/sc/qa/unit/data/xlsx/tableStyleInnerBorders.xlsx new file mode 100644 index 000000000000..080899f1aefc Binary files /dev/null and b/sc/qa/unit/data/xlsx/tableStyleInnerBorders.xlsx differ diff --git a/sc/qa/unit/data/xlsx/tableref-column-linebreak.xlsx b/sc/qa/unit/data/xlsx/tableref-column-linebreak.xlsx new file mode 100644 index 000000000000..e8fffd249ef0 Binary files /dev/null and b/sc/qa/unit/data/xlsx/tableref-column-linebreak.xlsx differ diff --git a/sc/qa/unit/data/xlsx/tdf122945_TabColorProtectedSheet.xlsx b/sc/qa/unit/data/xlsx/tdf122945_TabColorProtectedSheet.xlsx new file mode 100644 index 000000000000..09558ae59710 Binary files /dev/null and b/sc/qa/unit/data/xlsx/tdf122945_TabColorProtectedSheet.xlsx differ diff --git a/sc/qa/unit/data/xlsx/tdf171828_fail_to_import_file.xlsx b/sc/qa/unit/data/xlsx/tdf171828_fail_to_import_file.xlsx new file mode 100644 index 000000000000..5a6d8d2e4ecd Binary files /dev/null and b/sc/qa/unit/data/xlsx/tdf171828_fail_to_import_file.xlsx differ diff --git a/sc/qa/unit/data/xlsx/threadedComment.xlsx b/sc/qa/unit/data/xlsx/threadedComment.xlsx new file mode 100644 index 000000000000..101bcee0beb8 Binary files /dev/null and b/sc/qa/unit/data/xlsx/threadedComment.xlsx differ diff --git a/sc/qa/unit/data/xlsx/twoCellAnchor_editAs_oneCell.xlsx b/sc/qa/unit/data/xlsx/twoCellAnchor_editAs_oneCell.xlsx new file mode 100644 index 000000000000..d5054f3b94a8 Binary files /dev/null and b/sc/qa/unit/data/xlsx/twoCellAnchor_editAs_oneCell.xlsx differ diff --git a/sc/qa/unit/data/xlsx/user_defined_function.xlsx b/sc/qa/unit/data/xlsx/user_defined_function.xlsx new file mode 100644 index 000000000000..171e4e884333 Binary files /dev/null and b/sc/qa/unit/data/xlsx/user_defined_function.xlsx differ diff --git a/sc/qa/unit/dataproviders_test.cxx b/sc/qa/unit/dataproviders_test.cxx index 2dffef0d9bac..e72531b0b6ef 100644 --- a/sc/qa/unit/dataproviders_test.cxx +++ b/sc/qa/unit/dataproviders_test.cxx @@ -10,6 +10,7 @@ #include "helper/qahelper.hxx" #include +#include #include #include #include @@ -17,6 +18,8 @@ #include #include #include +#include +#include #include @@ -34,6 +37,7 @@ public: void testBaseImport(); void testTdf169541_TwoDataMapping(); void testTdf169610_SortTransform(); + void testLinkUpdateGate(); CPPUNIT_TEST_SUITE(ScDataProvidersTest); CPPUNIT_TEST(testCSVImport); @@ -43,6 +47,7 @@ public: CPPUNIT_TEST(testBaseImport); CPPUNIT_TEST(testTdf169541_TwoDataMapping); CPPUNIT_TEST(testTdf169610_SortTransform); + CPPUNIT_TEST(testLinkUpdateGate); CPPUNIT_TEST_SUITE_END(); }; @@ -305,6 +310,41 @@ void ScDataProvidersTest::testTdf169610_SortTransform() CPPUNIT_ASSERT_EQUAL(14.0, pDoc->GetValue(5, 11, 0)); } +void ScDataProvidersTest::testLinkUpdateGate() +{ + // A data mapping loaded from a document is an external link. Its data must + // not refresh from the source file until the user allows link updating, + // the same gate that governs sheet links and area links. + createScDoc("mappinggate.fods"); + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc); + ScDocShell* pDocShell = getScDocShell(); + CPPUNIT_ASSERT(pDocShell); + + // Loading the mapping registered it as a link in the LinkManager. + auto& rDataSources = pDoc->GetExternalDataMapper().getDataSources(); + CPPUNIT_ASSERT_EQUAL(size_t(1), rDataSources.size()); + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + CPPUNIT_ASSERT(pLinkManager); + CPPUNIT_ASSERT_EQUAL(size_t(1), pLinkManager->GetLinks().size()); + + // The saved document holds "unchanged" in A1; the source file holds + // "changed". The href stored in the document is not portable, so point the + // source at the real test file before asking for an update. + rDataSources[0].setURL(createFileURL(u"csv/mappinggate.csv")); + CPPUNIT_ASSERT_EQUAL(u"unchanged"_ustr, pDoc->GetString(0, 0, 0)); + + // With updating not allowed, updating the links leaves the saved value. + pDocShell->GetEmbeddedObjectContainer().setUserAllowsLinkUpdate(false); + pLinkManager->UpdateAllLinks(false, OUString()); + CPPUNIT_ASSERT_EQUAL(u"unchanged"_ustr, pDoc->GetString(0, 0, 0)); + + // Once the user allows updating, the same update brings in the live value. + pDocShell->GetEmbeddedObjectContainer().setUserAllowsLinkUpdate(true); + pLinkManager->UpdateAllLinks(false, OUString()); + CPPUNIT_ASSERT_EQUAL(u"changed"_ustr, pDoc->GetString(0, 0, 0)); +} + ScDataProvidersTest::ScDataProvidersTest() : ScModelTestBase(u"sc/qa/unit/data/dataprovider"_ustr) { diff --git a/sc/qa/unit/functions_dynamic_array.cxx b/sc/qa/unit/functions_dynamic_array.cxx new file mode 100644 index 000000000000..6e05546be470 --- /dev/null +++ b/sc/qa/unit/functions_dynamic_array.cxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 "helper/qahelper.hxx" + +#include +#include +#include +#include + +class DynamicArrayTest : public ScModelTestBase +{ +public: + DynamicArrayTest() + : ScModelTestBase(u"sc/qa/unit/data"_ustr) + { + } +}; + +namespace +{ +// Walk column C from row 5 down to nLastRow on the given sheet. Every non-empty C cell is an +// equality comparison for that row and has to evaluate to 1. The whole column is read before +// anything is reported, so one run lists every row that disagreed instead of stopping at the +// first one, and the report says at which stage of the test they disagreed. +void assertRowChecks(ScDocument& rDocument, SCTAB nTab, SCROW nLastRow, const char* pStage = "") +{ + OString aRows; + for (SCROW nRow = 4; nRow <= nLastRow; ++nRow) + { + ScAddress aPosition(2, nRow, nTab); + if (rDocument.GetCellType(aPosition) == CELLTYPE_NONE) + continue; + if (rDocument.GetValue(aPosition) == 1.0) + continue; + if (!aRows.isEmpty()) + aRows += ", "; + // Print the two values the comparison used, so a failing row already says what we + // computed and what was expected. + OString aOurs + = OUStringToOString(rDocument.GetString(0, nRow, nTab), RTL_TEXTENCODING_UTF8); + OString aExpected + = OUStringToOString(rDocument.GetString(1, nRow, nTab), RTL_TEXTENCODING_UTF8); + aRows += "C" + OString::number(nRow + 1) + " (A=" + aOurs + " B=" + aExpected; + // The tested cell is in column F or G, depending on the layout of the row. Print + // its value and the formula it reads back as. + for (SCCOL nColumn = 5; nColumn <= 6; ++nColumn) + { + if (rDocument.GetCellType(ScAddress(nColumn, nRow, nTab)) == CELLTYPE_NONE) + continue; + aRows += OString::Concat(nColumn == 5 ? " F=" : " G=") + + OUStringToOString(rDocument.GetString(nColumn, nRow, nTab), + RTL_TEXTENCODING_UTF8); + OUString aFormula = rDocument.GetFormula(nColumn, nRow, nTab); + if (!aFormula.isEmpty()) + aRows += " [" + OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8) + "]"; + } + aRows += ")"; + } + if (aRows.isEmpty()) + return; + + OString aLabel = "Sheet" + OString::number(nTab + 1) + + " verdict cells that did not " + "evaluate to TRUE"; + if (*pStage) + aLabel += OString::Concat(" ") + pStage; + aLabel += ": " + aRows; + CPPUNIT_FAIL(aLabel.getStr()); +} +} + +CPPUNIT_TEST_FIXTURE(DynamicArrayTest, testDynamicArrayXlsxRoundTrip) +{ + createScDoc("functions/dynamic_array/xlsx/DynamicArrayFixture.xlsx"); + + auto checkVerdicts = [this]() { + ScDocument* pDocument = getScDoc(); + // Sheet 1 "CSE Array Spill Cases", master cell A3 = AND(C5:C400). + assertRowChecks(*pDocument, 0, 399); + CPPUNIT_ASSERT_EQUAL(1.0, pDocument->GetValue(ScAddress(0, 2, 0))); + // Sheet 2 "Implicit intersection Operator", master cell A3 = AND(C5:C200). + assertRowChecks(*pDocument, 1, 199); + CPPUNIT_ASSERT_EQUAL(1.0, pDocument->GetValue(ScAddress(0, 2, 1))); + // Sheet 3 "Spill Operator", master cell A3 = AND(C5:C508). + assertRowChecks(*pDocument, 2, 507); + CPPUNIT_ASSERT_EQUAL(1.0, pDocument->GetValue(ScAddress(0, 2, 2))); + }; + + // The self-checking workbook holds after import, and again after an + // XLSX save and reload. + checkVerdicts(); + saveAndReload(TestFilter::XLSX); + checkVerdicts(); +} + +CPPUNIT_TEST_FIXTURE(DynamicArrayTest, testDroppedImplicitIntersectionIsPutBack) +{ + // OOXML leaves the @ of a plain =@ref# cell out of the text, expressing it by keeping + // the cell a non-array formula, so the import puts it back. An array formula does not + // reduce its operand, so it keeps the spelling it was saved with. + createScDoc("functions/dynamic_array/xlsx/DynamicArrayFixture.xlsx"); + ScDocument* pDocument = getScDoc(); + + // "Implicit intersection Operator" F44 is a plain _xlfn.ANCHORARRAY($G$45). + CPPUNIT_ASSERT_EQUAL(u"=@$G$45#"_ustr, pDocument->GetFormula(5, 43, 1)); + + // "Spill Operator" A34 is the same call as an array formula. + CPPUNIT_ASSERT_EQUAL(u"=$H$5#"_ustr, pDocument->GetFormula(0, 33, 2)); +} + +CPPUNIT_TEST_FIXTURE(DynamicArrayTest, testUnionSpillIntersectionOperatorXlsxRoundTrip) +{ + createScDoc("functions/dynamic_array/xlsx/UnionSpillIntersectionOperatorTest.xlsx"); + + auto checkVerdicts = [this](const char* pStage) { + ScDocument* pDocument = getScDoc(); + assertRowChecks(*pDocument, 0, 200, pStage); + }; + + // J112 is the shape OOXML saves without its @, so the import puts it back. + CPPUNIT_ASSERT_EQUAL(u"=@$I$112#"_ustr, getScDoc()->GetFormula(9, 111, 0)); + + // The workbook is another application's, so the first check is against its stored + // results and each later one against ours, with the save and reload covering the export. + checkVerdicts("on import"); + getScDoc()->CalcAll(); + checkVerdicts("after a recalculation"); + saveAndReload(TestFilter::XLSX); + checkVerdicts("after a save and reload"); + getScDoc()->CalcAll(); + checkVerdicts("after a recalculation of the reloaded document"); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/qa/unit/functions_lambda.cxx b/sc/qa/unit/functions_lambda.cxx new file mode 100644 index 000000000000..aefe9b2dd02a --- /dev/null +++ b/sc/qa/unit/functions_lambda.cxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "functions_test.hxx" + +class LambdaFunctionsTest : public FunctionsTest +{ +public: + LambdaFunctionsTest(); + + void testLambdaFormulasFODS(); + + CPPUNIT_TEST_SUITE(LambdaFunctionsTest); + CPPUNIT_TEST(testLambdaFormulasFODS); + CPPUNIT_TEST_SUITE_END(); +}; + +void LambdaFunctionsTest::testLambdaFormulasFODS() +{ + OUString aDirectoryURL + = m_directories.getURLFromSrc(u"/sc/qa/unit/data/functions/lambda/fods/"); + recursiveScan( + test::pass, u"OpenDocument Spreadsheet Flat XML"_ustr, aDirectoryURL, + u"com.sun.star.comp.filter.OdfFlatXml,,com.sun.star.comp.Calc.XMLOasisImporter,com.sun.star.comp.Calc.XMLOasisExporter,,,true"_ustr, + FODS_FORMAT_TYPE, SotClipboardFormatId::NONE, 0, false); +} + +LambdaFunctionsTest::LambdaFunctionsTest() + : FunctionsTest() +{ +} + +CPPUNIT_TEST_SUITE_REGISTRATION(LambdaFunctionsTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/helper/qahelper.cxx b/sc/qa/unit/helper/qahelper.cxx index 85ed392876d0..5530dea72f0d 100644 --- a/sc/qa/unit/helper/qahelper.cxx +++ b/sc/qa/unit/helper/qahelper.cxx @@ -74,12 +74,6 @@ std::ostream& operator<<(std::ostream& rStrm, const ScAddress& rAddr) return rStrm; } -std::ostream& operator<<(std::ostream& rStrm, const ScRange& rRange) -{ - rStrm << rRange.aStart << "-" << rRange.aEnd; - return rStrm; -} - std::ostream& operator<<(std::ostream& rStrm, const ScRangeList& rList) { rStrm << "ScRangeList: \n"; @@ -209,13 +203,13 @@ void ScModelTestBase::testFormats(ScDocument* pDoc,std::u16string_view sFormat) CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be blue", COL_BLUE, aComplexColor.getFinalColor()); pPattern = pDoc->GetPattern(1,1,1); pPattern->fillFontOnly(aFont); - CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be striked out with a single line", STRIKEOUT_SINGLE, aFont.GetStrikeout()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be struck out with a single line", STRIKEOUT_SINGLE, aFont.GetStrikeout()); //some tests on sheet2 only for ods if (sFormat == u"calc8") { pPattern = pDoc->GetPattern(1,2,1); pPattern->fillFontOnly(aFont); - CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be striked out with a double line", STRIKEOUT_DOUBLE, aFont.GetStrikeout()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be struck out with a double line", STRIKEOUT_DOUBLE, aFont.GetStrikeout()); pPattern = pDoc->GetPattern(1,3,1); pPattern->fillFontOnly(aFont); CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be underlined with a dotted line", LINESTYLE_DOTTED, aFont.GetUnderline()); @@ -324,7 +318,8 @@ void ScModelTestBase::insertStringToCell(const OUString& rCell, std::u16string_v Scheduler::ProcessEventsToIdle(); } -void ScModelTestBase::insertArrayToCell(const OUString& rCell, std::u16string_view rStr) +void ScModelTestBase::insertArrayToCell(const OUString& rCell, std::u16string_view rStr, + bool bDynamicArrayMaster) { goToCell(rCell); @@ -334,6 +329,38 @@ void ScModelTestBase::insertArrayToCell(const OUString& rCell, std::u16string_vi pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_MOD1 | KEY_SHIFT | awt::Key::RETURN); pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_MOD1 | KEY_SHIFT | awt::Key::RETURN); Scheduler::ProcessEventsToIdle(); + + if (!bDynamicArrayMaster) + return; + + // The Ctrl+Shift+Enter path creates a static array master. When the + // caller asks for dynamic behaviour, opt the master into the auto- + // resize gate so the matrix grows or shrinks with the source data. + // A dirty flag plus a full recalc applies the gate to the result + // already on the cell. + ScDocShell* pDocSh = getScDocShell(); + ScDocument& rDoc = pDocSh->GetDocument(); + ScAddress aAddr; + sal_Int32 nOffset = 0; + ScRangeStringConverter::GetAddressFromString(aAddr, rCell, rDoc, + formula::FormulaGrammar::CONV_OOO, nOffset); + if (ScFormulaCell* pMaster = rDoc.GetFormulaCell(aAddr)) + { + pMaster->SetDynamicArrayMaster(true); + pMaster->SetDirty(); + rDoc.CalcAll(); + } +} + +void ScModelTestBase::clearCell(const OUString& rCell) +{ + goToCell(rCell); + + // Press DELETE on a selected cell + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::DELETE); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::DELETE); + Scheduler::ProcessEventsToIdle(); } void ScModelTestBase::insertNewSheet(const ScDocument& rDoc) @@ -521,7 +548,7 @@ bool checkOutput( SCROW nOutRowSize = e.Row() - s.Row() + 1; SCCOL nOutColSize = e.Col() - s.Col() + 1; - // Check if expected size iz smaller than actual size (and prevent a crash) + // Check if expected size is smaller than actual size (and prevent a crash) if (aCheck.size() < o3tl::make_unsigned(nOutRowSize) || aCheck[0].size() < o3tl::make_unsigned(nOutColSize)) { // Dump the arrays to console, so we can compare @@ -895,7 +922,7 @@ bool ScUcalcTestBase::insertRangeNames( aA1, ScRangeData::Type::Name, formula::FormulaGrammar::GRAM_ENGLISH); pNew->SetIndex(p->mnIndex); - bool bSuccess = pNames->insert(pNew); + bool bSuccess = pNames->insert(std::unique_ptr(pNew)); if (!bSuccess) { std::cerr << "Insertion failed." << std::endl; @@ -908,7 +935,7 @@ bool ScUcalcTestBase::insertRangeNames( OUString ScUcalcTestBase::getRangeByName(const ScDocument* pDoc, const OUString& aRangeName) { - ScRangeData* pName = pDoc->GetRangeName()->findByUpperName(aRangeName.toAsciiUpperCase()); + ScRangeData* pName = pDoc->GetRangeName().findByUpperName(aRangeName.toAsciiUpperCase()); CPPUNIT_ASSERT(pName); return pName->GetSymbol(pDoc->GetGrammar()); } diff --git a/sc/qa/unit/helper/qahelper.hxx b/sc/qa/unit/helper/qahelper.hxx index 588a6be724b1..a13833c4228b 100644 --- a/sc/qa/unit/helper/qahelper.hxx +++ b/sc/qa/unit/helper/qahelper.hxx @@ -63,8 +63,6 @@ struct RangeNameDef SCQAHELPER_DLLPUBLIC std::ostream& operator<<(std::ostream& rStrm, const ScAddress& rAddr); -SCQAHELPER_DLLPUBLIC std::ostream& operator<<(std::ostream& rStrm, const ScRange& rRange); - SCQAHELPER_DLLPUBLIC std::ostream& operator<<(std::ostream& rStrm, const ScRangeList& rList); SCQAHELPER_DLLPUBLIC std::ostream& operator<<(std::ostream& rStrm, const OpCode& rCode); @@ -179,7 +177,9 @@ public: void goToCell(const OUString& rCell); void typeString(std::u16string_view rStr); void insertStringToCell(const OUString& rCell, std::u16string_view rStr); - void insertArrayToCell(const OUString& rCell, std::u16string_view rStr); + void insertArrayToCell(const OUString& rCell, std::u16string_view rStr, + bool bDynamicArrayMaster = false); + void clearCell(const OUString& rCell); void insertNewSheet(const ScDocument& rDoc); void executeAutoSum(); void selectObjectByName(std::u16string_view rObjName); diff --git a/sc/qa/unit/helper/sctestviewcallback.cxx b/sc/qa/unit/helper/sctestviewcallback.cxx index 5e5ada18fb15..431760e6099b 100644 --- a/sc/qa/unit/helper/sctestviewcallback.cxx +++ b/sc/qa/unit/helper/sctestviewcallback.cxx @@ -326,26 +326,6 @@ void ScTestViewCallback::callbackImpl(int nType, const char* pPayload) m_aStateChanges[aCommandName] = aTree; } break; - case LOK_CALLBACK_JSDIALOG: - { - std::stringstream aStream(pPayload); - boost::property_tree::ptree aTree; - boost::property_tree::read_json(aStream, aTree); - if (aTree.get_child("jsontype").get_value() == "formulabar") - { - if (aTree.find("data") != aTree.not_found()) - { - if (aTree.get_child("data").find("separator") - != aTree.get_child("data").not_found()) - { - decimalSeparator = aTree.get_child("data") - .get_child("separator") - .get_value(); - } - } - } - } - break; } } diff --git a/sc/qa/unit/helper/sctestviewcallback.hxx b/sc/qa/unit/helper/sctestviewcallback.hxx index 78d5767649aa..7ca5028dd988 100644 --- a/sc/qa/unit/helper/sctestviewcallback.hxx +++ b/sc/qa/unit/helper/sctestviewcallback.hxx @@ -78,7 +78,6 @@ public: OString m_aHyperlinkClicked; OString m_ShapeSelection; std::map m_aStateChanges; - std::string decimalSeparator; TestLokCallbackWrapper m_callbackWrapper; ScTestViewCallback(bool bDeleteListenerOnDestruct = true); @@ -91,7 +90,6 @@ public: void ClearAllInvalids(); - SfxViewShell* getViewShell() { return mpViewShell; } ScTabViewShell* getTabViewShell() { return dynamic_cast(mpViewShell); } int getViewID() { return mnView; } }; diff --git a/sc/qa/unit/jumbosheets-test.cxx b/sc/qa/unit/jumbosheets-test.cxx index 817abef3452a..f093b1ae4b0f 100644 --- a/sc/qa/unit/jumbosheets-test.cxx +++ b/sc/qa/unit/jumbosheets-test.cxx @@ -165,7 +165,7 @@ void ScJumboSheetsTest::testRoundtripNamedRanges(const char* name, TestFilter eF ScDocument* pDoc = getScDoc(); for (const auto& range : ranges) { - ScRangeData* rangeData = pDoc->GetRangeName()->findByUpperName(range.first); + ScRangeData* rangeData = pDoc->GetRangeName().findByUpperName(range.first); CPPUNIT_ASSERT(rangeData); CPPUNIT_ASSERT_EQUAL(range.second, rangeData->GetSymbol()); } @@ -176,7 +176,7 @@ void ScJumboSheetsTest::testRoundtripNamedRanges(const char* name, TestFilter eF ScDocument* pDoc = getScDoc(); for (const auto& range : ranges) { - ScRangeData* rangeData = pDoc->GetRangeName()->findByUpperName(range.first); + ScRangeData* rangeData = pDoc->GetRangeName().findByUpperName(range.first); CPPUNIT_ASSERT(rangeData); CPPUNIT_ASSERT_EQUAL(range.second, rangeData->GetSymbol()); } @@ -227,7 +227,7 @@ void ScJumboSheetsTest::testTdf134553() // Without the fix in place, this test would have failed here CPPUNIT_ASSERT(pOleObj); - // Sorry, the charts so severely suffer from DPI dependency, that I can't find motivation + // Sorry, the charts suffer so severely from DPI dependency, that I can't find motivation // to add huge tolerances (around 350!) here to make it pass on non-default DPI, with no // guarantee that the test would have any value after that. So just skip it. // FIXME: the DPI check should be removed when either (1) the test is fixed to work with diff --git a/sc/qa/unit/opencl-test-1.cxx b/sc/qa/unit/opencl-test-1.cxx index 8426f6888cdf..c0f765537d1c 100644 --- a/sc/qa/unit/opencl-test-1.cxx +++ b/sc/qa/unit/opencl-test-1.cxx @@ -240,9 +240,7 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testSharedFormulaXLS) for (SCROW i = 23; i < 25; ++i) { double fLibre = pDoc->GetValue(2, i, 0); - //double fExcel = pDocRes->GetValue(ScAddress(2, i, 0)); - // There seems to be a bug in LibreOffice beta - ASSERT_DOUBLES_EQUAL(/*fExcel*/ 60.0, fLibre); + ASSERT_DOUBLES_EQUAL(60.0, fLibre); } for (SCROW i = 25; i < 27; ++i) @@ -298,8 +296,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaCos) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -314,8 +312,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaSinh) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -330,141 +328,141 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialFormula) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(2,i,0); - double fExcel = pDocRes->GetValue(2,i,0); + double fLibre = pDoc->GetValue(2, i, 0); + double fExcel = pDocRes->GetValue(2, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(6,i,1); - double fExcel = pDocRes->GetValue(6,i,1); + double fLibre = pDoc->GetValue(6, i, 1); + double fExcel = pDocRes->GetValue(6, i, 1); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(2,i,2); - double fExcel = pDocRes->GetValue(2,i,2); + double fLibre = pDoc->GetValue(2, i, 2); + double fExcel = pDocRes->GetValue(2, i, 2); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(6,i,3); - double fExcel = pDocRes->GetValue(6,i,3); + double fLibre = pDoc->GetValue(6, i, 3); + double fExcel = pDocRes->GetValue(6, i, 3); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(3,i,4); - double fExcel = pDocRes->GetValue(3,i,4); + double fLibre = pDoc->GetValue(3, i, 4); + double fExcel = pDocRes->GetValue(3, i, 4); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(3,i,5); - double fExcel = pDocRes->GetValue(3,i,5); + double fLibre = pDoc->GetValue(3, i, 5); + double fExcel = pDocRes->GetValue(3, i, 5); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 0; i < 10; ++i) { - double fLibre = pDoc->GetValue(5,i,6); - double fExcel = pDocRes->GetValue(5,i,6); + double fLibre = pDoc->GetValue(5, i, 6); + double fExcel = pDocRes->GetValue(5, i, 6); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 9; ++i) { - double fLibre = pDoc->GetValue(3,i,7); - double fExcel = pDocRes->GetValue(3,i,7); + double fLibre = pDoc->GetValue(3, i, 7); + double fExcel = pDocRes->GetValue(3, i, 7); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(3,i,8); - double fExcel = pDocRes->GetValue(3,i,8); + double fLibre = pDoc->GetValue(3, i, 8); + double fExcel = pDocRes->GetValue(3, i, 8); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 9; ++i) { - double fLibre = pDoc->GetValue(3,i,9); - double fExcel = pDocRes->GetValue(3,i,9); + double fLibre = pDoc->GetValue(3, i, 9); + double fExcel = pDocRes->GetValue(3, i, 9); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(2,i,10); - double fExcel = pDocRes->GetValue(2,i,10); + double fLibre = pDoc->GetValue(2, i, 10); + double fExcel = pDocRes->GetValue(2, i, 10); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(7,i,11); - double fExcel = pDocRes->GetValue(7,i,11); + double fLibre = pDoc->GetValue(7, i, 11); + double fExcel = pDocRes->GetValue(7, i, 11); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(5,i,12); - double fExcel = pDocRes->GetValue(5,i,12); + double fLibre = pDoc->GetValue(5, i, 12); + double fExcel = pDocRes->GetValue(5, i, 12); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 0; i <= 12; ++i) { - double fLibre = pDoc->GetValue(6,i,13); - double fExcel = pDocRes->GetValue(6,i,13); + double fLibre = pDoc->GetValue(6, i, 13); + double fExcel = pDocRes->GetValue(6, i, 13); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(3,i,14); - double fExcel = pDocRes->GetValue(3,i,14); + double fLibre = pDoc->GetValue(3, i, 14); + double fExcel = pDocRes->GetValue(3, i, 14); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(6,i,15); - double fExcel = pDocRes->GetValue(6,i,15); + double fLibre = pDoc->GetValue(6, i, 15); + double fExcel = pDocRes->GetValue(6, i, 15); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(6,i,16); - double fExcel = pDocRes->GetValue(6,i,16); + double fLibre = pDoc->GetValue(6, i, 16); + double fExcel = pDocRes->GetValue(6, i, 16); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 1; i <= 5; ++i) { - double fLibre = pDoc->GetValue(6,i,17); - double fExcel = pDocRes->GetValue(6,i,17); + double fLibre = pDoc->GetValue(6, i, 17); + double fExcel = pDocRes->GetValue(6, i, 17); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 0; i <= 10; ++i) { - double fLibre = pDoc->GetValue(3,i,18); - double fExcel = pDocRes->GetValue(3,i,18); + double fLibre = pDoc->GetValue(3, i, 18); + double fExcel = pDocRes->GetValue(3, i, 18); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 0; i <= 18; ++i) { - double fLibre = pDoc->GetValue(3,i,19); - double fExcel = pDocRes->GetValue(3,i,19); + double fLibre = pDoc->GetValue(3, i, 19); + double fExcel = pDocRes->GetValue(3, i, 19); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -494,8 +492,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaFisher) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -510,8 +508,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaFisherInv) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -526,8 +524,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaGamma) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -557,8 +555,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaAbs) // Verify ABS Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -606,8 +604,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaGammaLn) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -622,8 +620,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaGauss) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -638,8 +636,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaGeoMean) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -654,8 +652,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaHarMean) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(1,i,0); - double fExcel = pDocRes->GetValue(1,i,0); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -805,8 +803,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaNegbinomdist) // Check the results of formula cells in the shared formula range. for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(3,i,0); - double fExcel = pDocRes->GetValue(3,i,0); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -820,8 +818,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaSin) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -835,8 +833,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaTan) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -850,8 +848,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaTanH) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -865,8 +863,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaSqrt) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -880,8 +878,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialPriceFormula) for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(ScAddress(7, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(7, i, 0)); + double fLibre = pDoc->GetValue(7, i, 0); + double fExcel = pDocRes->GetValue(7, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -895,8 +893,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialDollarfrFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(2, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(2, i, 0)); + double fLibre = pDoc->GetValue(2, i, 0); + double fExcel = pDocRes->GetValue(2, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -910,8 +908,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialPriceDiscFormula) for (SCROW i = 0; i <= 10; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -925,8 +923,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialODDLPRICEFormula) for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(ScAddress(8, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(8, i, 0)); + double fLibre = pDoc->GetValue(8, i, 0); + double fExcel = pDocRes->GetValue(8, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -940,8 +938,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialOddlyieldFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(8, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(8, i, 0)); + double fLibre = pDoc->GetValue(8, i, 0); + double fExcel = pDocRes->GetValue(8, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -955,8 +953,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialDISCFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -970,8 +968,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialPVFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -985,8 +983,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialINTRATEFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1001,8 +999,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaStandard) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 20; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(3,i,0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1017,8 +1015,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaWeibull) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 20; ++i) { - double fLibre = pDoc->GetValue(ScAddress(4,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(4,i,0)); + double fLibre = pDoc->GetValue(4, i, 0); + double fExcel = pDocRes->GetValue(4, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fExcel == 0?1e-4:fabs(1e-4*fExcel)); } @@ -1034,8 +1032,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaPearson) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(2,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(2,i,0)); + double fLibre = pDoc->GetValue(2, i, 0); + double fExcel = pDocRes->GetValue(2, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1050,8 +1048,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaRsq) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(2,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(2,i,0)); + double fLibre = pDoc->GetValue(2, i, 0); + double fExcel = pDocRes->GetValue(2, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1065,8 +1063,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaCosh) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1081,8 +1079,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaKurt) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1096,8 +1094,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaCot) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1111,8 +1109,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaCsc) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1126,8 +1124,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaCoth) for (SCROW i = 0; i <= 15; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1141,15 +1139,15 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialXNPVFormula) for (SCROW i = 1; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(3, i, 0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 16; i <= 26; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(3, i, 0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1163,8 +1161,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaIntercept) for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(2,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(2,i,0)); + double fLibre = pDoc->GetValue(2, i, 0); + double fExcel = pDocRes->GetValue(2, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1178,8 +1176,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialAmordegrcFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(7, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(7, i, 0)); + double fLibre = pDoc->GetValue(7, i, 0); + double fExcel = pDocRes->GetValue(7, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1193,8 +1191,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialISPMTFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(4, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(4, i, 0)); + double fLibre = pDoc->GetValue(4, i, 0); + double fExcel = pDocRes->GetValue(4, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1209,8 +1207,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaMedian) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1225,8 +1223,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaNormdist) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(4,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(4,i,0)); + double fLibre = pDoc->GetValue(4, i, 0); + double fExcel = pDocRes->GetValue(4, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1241,8 +1239,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaNormsdist) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1257,8 +1255,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaPermut) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(2,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(2,i,0)); + double fLibre = pDoc->GetValue(2, i, 0); + double fExcel = pDocRes->GetValue(2, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1273,8 +1271,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaPermutation) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(2,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(2,i,0)); + double fLibre = pDoc->GetValue(2, i, 0); + double fExcel = pDocRes->GetValue(2, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1289,8 +1287,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaPhi) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1305,8 +1303,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaLogInv) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(3,i,0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1320,8 +1318,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialNPERFormula) for (SCROW i = 0; i <= 10; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1336,8 +1334,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaForecast) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(3,i,0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1351,8 +1349,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialAmorlincFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(7, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(7, i, 0)); + double fLibre = pDoc->GetValue(7, i, 0); + double fExcel = pDocRes->GetValue(7, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1366,8 +1364,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialDDBFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1380,8 +1378,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialPriceMatFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(6, i, 0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1395,8 +1393,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialFormulaReceived) // Check the results of formula cells in the shared formula range. for (SCROW i = 0; i < 10; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(5,i,0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1410,8 +1408,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialFormulaCumipmt) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(6,i,0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1425,8 +1423,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialFormulaCumprinc) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 10; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(6,i,0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1439,8 +1437,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialRRIFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(3, i, 0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1453,8 +1451,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialEFFECT_ADDFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(2, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(2, i, 0)); + double fLibre = pDoc->GetValue(2, i, 0); + double fExcel = pDocRes->GetValue(2, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1469,8 +1467,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialNominalFormula) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(3,i,0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1483,8 +1481,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialTBILLEQFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(3, i, 0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1497,8 +1495,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialTBILLPRICEFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(3, i, 0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1511,8 +1509,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialTBILLYIELDFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(3, i, 0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1525,8 +1523,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialYIELDFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(7, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(7, i, 0)); + double fLibre = pDoc->GetValue(7, i, 0); + double fExcel = pDocRes->GetValue(7, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1540,8 +1538,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialYIELDDISCFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1555,8 +1553,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialYIELDMATFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(6, i, 0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1569,8 +1567,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialPMTFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1584,8 +1582,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialDurationFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(3, i, 0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1600,8 +1598,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaLogNormDist) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(4,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(4,i,0)); + double fLibre = pDoc->GetValue(4, i, 0); + double fExcel = pDocRes->GetValue(4, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1616,8 +1614,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaArcCos) // Verify ACos Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1631,8 +1629,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialPPMTFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(6, i, 0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1646,8 +1644,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialNPVFormula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(6, i, 0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1661,8 +1659,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialDuration_ADDFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(6, i, 0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1677,8 +1675,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaNorminv) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(3,i,0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1693,8 +1691,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaNormsinv) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1709,8 +1707,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaArcCosHyp) // Verify ACosH Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1724,8 +1722,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialMDurationFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(6, i, 0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1740,8 +1738,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaArcCot) // Verify ACot Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1755,8 +1753,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialFVFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1770,8 +1768,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialDBFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1785,8 +1783,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialCouppcdFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(4, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(4, i, 0)); + double fLibre = pDoc->GetValue(4, i, 0); + double fExcel = pDocRes->GetValue(4, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1801,26 +1799,26 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathSumIfsFormula) for (SCROW i = 2; i <= 11; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(5,i,0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 2; i <= 11; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(6,i,0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 2; i <= 11; ++i) { - double fLibre = pDoc->GetValue(ScAddress(7,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(7,i,0)); + double fLibre = pDoc->GetValue(7, i, 0); + double fExcel = pDocRes->GetValue(7, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 2; i <= 11; ++i) { - double fLibre = pDoc->GetValue(ScAddress(8,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(8,i,0)); + double fLibre = pDoc->GetValue(8, i, 0); + double fExcel = pDocRes->GetValue(8, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1835,8 +1833,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaArcCotHyp) // Verify ACotH Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1848,11 +1846,11 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaArcSin) ScDocument* pDocRes = getScDoc2(); pDoc->CalcAll(); - // Verify ACotH Function + // Verify ASin Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1866,20 +1864,20 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialVDBFormula) for (SCROW i = 0; i <= 10; ++i) { - double fLibre = pDoc->GetValue(ScAddress(7, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(7, i, 0)); + double fLibre = pDoc->GetValue(7, i, 0); + double fExcel = pDocRes->GetValue(7, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 15; i <= 26; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(6, i, 0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 30; i <= 41; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1893,8 +1891,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialIPMTFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(6, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(6, i, 0)); + double fLibre = pDoc->GetValue(6, i, 0); + double fExcel = pDocRes->GetValue(6, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1909,8 +1907,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaConfidence) // Check the results of formula cells in the shared formula range. for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(3,i,0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1924,8 +1922,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialCoupncdFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(4, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(4, i, 0)); + double fLibre = pDoc->GetValue(4, i, 0); + double fExcel = pDocRes->GetValue(4, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1939,8 +1937,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinancialAccrintFormula) for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(7, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(7, i, 0)); + double fLibre = pDoc->GetValue(7, i, 0); + double fExcel = pDocRes->GetValue(7, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1955,8 +1953,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaCritBinom) // Check the results of formula cells in the shared formula range. for (SCROW i = 0; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(3,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(3,i,0)); + double fLibre = pDoc->GetValue(3, i, 0); + double fExcel = pDocRes->GetValue(3, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1971,8 +1969,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaArcSinHyp) // Verify ASinH Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -1987,8 +1985,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaArcTan) // Verify ATan Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -2003,8 +2001,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaArcTanHyp) // Verify ATanH Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -2018,8 +2016,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testFinacialNPER1Formula) for (SCROW i = 0; i <= 6; ++i) { - double fLibre = pDoc->GetValue(ScAddress(5, i, 0)); - double fExcel = pDocRes->GetValue(ScAddress(5, i, 0)); + double fLibre = pDoc->GetValue(5, i, 0); + double fExcel = pDocRes->GetValue(5, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -2034,8 +2032,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaBitAnd) // Verify BitAnd Function for (SCROW i = 1; i <= 1000; ++i) { - double fLibre = pDoc->GetValue(ScAddress(2,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(2,i,0)); + double fLibre = pDoc->GetValue(2, i, 0); + double fExcel = pDocRes->GetValue(2, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -2050,8 +2048,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaLN) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -2066,14 +2064,14 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testMathFormulaRound) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 9; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } for (SCROW i = 15; i <= 25; ++i) { - double fLibre = pDoc->GetValue(ScAddress(1,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(1,i,0)); + double fLibre = pDoc->GetValue(1, i, 0); + double fExcel = pDocRes->GetValue(1, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } @@ -2088,8 +2086,8 @@ CPPUNIT_TEST_FIXTURE(ScOpenCLTest1, testStatisticalFormulaGammaDist) // Check the results of formula cells in the shared formula range. for (SCROW i = 1; i <= 19; ++i) { - double fLibre = pDoc->GetValue(ScAddress(4,i,0)); - double fExcel = pDocRes->GetValue(ScAddress(4,i,0)); + double fLibre = pDoc->GetValue(4, i, 0); + double fExcel = pDocRes->GetValue(4, i, 0); CPPUNIT_ASSERT_DOUBLES_EQUAL(fExcel, fLibre, fabs(0.0001*fExcel)); } } diff --git a/sc/qa/unit/pivottable_filters_test.cxx b/sc/qa/unit/pivottable_filters_test.cxx index 39b00a0602d6..62f4362de5d5 100644 --- a/sc/qa/unit/pivottable_filters_test.cxx +++ b/sc/qa/unit/pivottable_filters_test.cxx @@ -317,8 +317,7 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testGetPivotDataXLS) // F3:F20. for (SCROW nRow = 2; nRow <= 19; ++nRow) - CPPUNIT_ASSERT_EQUAL(pDoc->GetValue(ScAddress(4, nRow, 1)), - pDoc->GetValue(ScAddress(5, nRow, 1))); + CPPUNIT_ASSERT_EQUAL(pDoc->GetValue(4, nRow, 1), pDoc->GetValue(5, nRow, 1)); } CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableSharedGroupXLSX) @@ -328,22 +327,22 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableSharedGroupXLSX) // Check whether right group names are imported for both tables // First table - CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(ScAddress(0, 0, 0))); - CPPUNIT_ASSERT_EQUAL(u"Csoport1"_ustr, pDoc->GetString(ScAddress(0, 1, 0))); - CPPUNIT_ASSERT_EQUAL(u"Csoport2"_ustr, pDoc->GetString(ScAddress(0, 2, 0))); - CPPUNIT_ASSERT_EQUAL(u"Csoport3"_ustr, pDoc->GetString(ScAddress(0, 3, 0))); - CPPUNIT_ASSERT_EQUAL(u"16"_ustr, pDoc->GetString(ScAddress(0, 4, 0))); - CPPUNIT_ASSERT_EQUAL(u"17"_ustr, pDoc->GetString(ScAddress(0, 5, 0))); - CPPUNIT_ASSERT_EQUAL(u"18"_ustr, pDoc->GetString(ScAddress(0, 6, 0))); + CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(0, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"Csoport1"_ustr, pDoc->GetString(0, 1, 0)); + CPPUNIT_ASSERT_EQUAL(u"Csoport2"_ustr, pDoc->GetString(0, 2, 0)); + CPPUNIT_ASSERT_EQUAL(u"Csoport3"_ustr, pDoc->GetString(0, 3, 0)); + CPPUNIT_ASSERT_EQUAL(u"16"_ustr, pDoc->GetString(0, 4, 0)); + CPPUNIT_ASSERT_EQUAL(u"17"_ustr, pDoc->GetString(0, 5, 0)); + CPPUNIT_ASSERT_EQUAL(u"18"_ustr, pDoc->GetString(0, 6, 0)); // Second table - CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(ScAddress(0, 10, 0))); - CPPUNIT_ASSERT_EQUAL(u"Csoport1"_ustr, pDoc->GetString(ScAddress(0, 11, 0))); - CPPUNIT_ASSERT_EQUAL(u"Csoport2"_ustr, pDoc->GetString(ScAddress(0, 12, 0))); - CPPUNIT_ASSERT_EQUAL(u"Csoport3"_ustr, pDoc->GetString(ScAddress(0, 13, 0))); - CPPUNIT_ASSERT_EQUAL(u"16"_ustr, pDoc->GetString(ScAddress(0, 14, 0))); - CPPUNIT_ASSERT_EQUAL(u"17"_ustr, pDoc->GetString(ScAddress(0, 15, 0))); - CPPUNIT_ASSERT_EQUAL(u"18"_ustr, pDoc->GetString(ScAddress(0, 16, 0))); + CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(0, 10, 0)); + CPPUNIT_ASSERT_EQUAL(u"Csoport1"_ustr, pDoc->GetString(0, 11, 0)); + CPPUNIT_ASSERT_EQUAL(u"Csoport2"_ustr, pDoc->GetString(0, 12, 0)); + CPPUNIT_ASSERT_EQUAL(u"Csoport3"_ustr, pDoc->GetString(0, 13, 0)); + CPPUNIT_ASSERT_EQUAL(u"16"_ustr, pDoc->GetString(0, 14, 0)); + CPPUNIT_ASSERT_EQUAL(u"17"_ustr, pDoc->GetString(0, 15, 0)); + CPPUNIT_ASSERT_EQUAL(u"18"_ustr, pDoc->GetString(0, 16, 0)); // There should be exactly 2 pivot tables and 1 cache. ScDPCollection* pDPs = pDoc->GetDPCollection(); @@ -363,20 +362,20 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableSharedDateGroupXLSX) auto testThis = [](ScDocument& rDoc) { // Check whether right date labels are imported for both tables // First table - CPPUNIT_ASSERT_EQUAL(u"a"_ustr, rDoc.GetString(ScAddress(0, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(0, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(0, 4, 1))); - CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(0, 5, 1))); - CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(0, 6, 1))); + CPPUNIT_ASSERT_EQUAL(u"a"_ustr, rDoc.GetString(0, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(0, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(0, 4, 1)); + CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(0, 5, 1)); + CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(0, 6, 1)); // TODO: check why this fails with 2005 // CPPUNIT_ASSERT_EQUAL(OUString("2007"), rDoc.GetString(ScAddress(0,7,1))); // Second table - CPPUNIT_ASSERT_EQUAL(u"a"_ustr, rDoc.GetString(ScAddress(5, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(5, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(5, 4, 1))); - CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(5, 5, 1))); - CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(5, 6, 1))); + CPPUNIT_ASSERT_EQUAL(u"a"_ustr, rDoc.GetString(5, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(5, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(5, 4, 1)); + CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(5, 5, 1)); + CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(5, 6, 1)); // TODO: check why this fails with 2005 // CPPUNIT_ASSERT_EQUAL(OUString("2007"), rDoc.GetString(ScAddress(5,7,1))); @@ -404,19 +403,19 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableSharedNestedDateGrou // Check whether right date groups are imported for both tables // First table // Years, Quarters, 'a' have compact layout so the only header contains a multi-field filter. - CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(0, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(0, 10, 1))); - CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(0, 17, 1))); - CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(0, 20, 1))); + CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(0, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(0, 10, 1)); + CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(0, 17, 1)); + CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(0, 20, 1)); // TODO: check why this fails with the empty string //CPPUNIT_ASSERT_EQUAL(OUString("2007"), rDoc.GetString(ScAddress(0,32,1))); // Second table // Years, Quarters, 'a' have compact layout so the only row header contains a multi-field filter. - CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(6, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(6, 10, 1))); - CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(6, 17, 1))); - CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(6, 20, 1))); + CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(6, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(6, 10, 1)); + CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(6, 17, 1)); + CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(6, 20, 1)); // TODO: check why this fails with the empty string //CPPUNIT_ASSERT_EQUAL(OUString("2007"), rDoc.GetString(ScAddress(6,31,1))); @@ -448,20 +447,20 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableSharedNumGroupXLSX) // Check whether right number groups are imported for both tables // First table - CPPUNIT_ASSERT_EQUAL(u"f"_ustr, pDoc->GetString(ScAddress(0, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"32674-47673"_ustr, pDoc->GetString(ScAddress(0, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"47674-62673"_ustr, pDoc->GetString(ScAddress(0, 4, 1))); - CPPUNIT_ASSERT_EQUAL(u"62674-77673"_ustr, pDoc->GetString(ScAddress(0, 5, 1))); - CPPUNIT_ASSERT_EQUAL(u"77674-92673"_ustr, pDoc->GetString(ScAddress(0, 6, 1))); - CPPUNIT_ASSERT_EQUAL(u"92674-107673"_ustr, pDoc->GetString(ScAddress(0, 7, 1))); + CPPUNIT_ASSERT_EQUAL(u"f"_ustr, pDoc->GetString(0, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"32674-47673"_ustr, pDoc->GetString(0, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"47674-62673"_ustr, pDoc->GetString(0, 4, 1)); + CPPUNIT_ASSERT_EQUAL(u"62674-77673"_ustr, pDoc->GetString(0, 5, 1)); + CPPUNIT_ASSERT_EQUAL(u"77674-92673"_ustr, pDoc->GetString(0, 6, 1)); + CPPUNIT_ASSERT_EQUAL(u"92674-107673"_ustr, pDoc->GetString(0, 7, 1)); // Second table - CPPUNIT_ASSERT_EQUAL(u"f"_ustr, pDoc->GetString(ScAddress(5, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"32674-47673"_ustr, pDoc->GetString(ScAddress(5, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"47674-62673"_ustr, pDoc->GetString(ScAddress(5, 4, 1))); - CPPUNIT_ASSERT_EQUAL(u"62674-77673"_ustr, pDoc->GetString(ScAddress(5, 5, 1))); - CPPUNIT_ASSERT_EQUAL(u"77674-92673"_ustr, pDoc->GetString(ScAddress(5, 6, 1))); - CPPUNIT_ASSERT_EQUAL(u"92674-107673"_ustr, pDoc->GetString(ScAddress(5, 7, 1))); + CPPUNIT_ASSERT_EQUAL(u"f"_ustr, pDoc->GetString(5, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"32674-47673"_ustr, pDoc->GetString(5, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"47674-62673"_ustr, pDoc->GetString(5, 4, 1)); + CPPUNIT_ASSERT_EQUAL(u"62674-77673"_ustr, pDoc->GetString(5, 5, 1)); + CPPUNIT_ASSERT_EQUAL(u"77674-92673"_ustr, pDoc->GetString(5, 6, 1)); + CPPUNIT_ASSERT_EQUAL(u"92674-107673"_ustr, pDoc->GetString(5, 7, 1)); // There should be exactly 2 pivot tables and 1 cache. ScDPCollection* pDPs = pDoc->GetDPCollection(); @@ -500,7 +499,7 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableNoColumnsLayout) } } -CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testTdf112501) +CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testTdf112501PivotCompactModePopupButtonPlacement) { createScDoc("xls/tdf112501.xls"); ScDocument* pDoc = getScDoc(); @@ -1937,7 +1936,7 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableBoolFieldFilterXLSX) ScDocument* pDoc = getScDoc(); ScDPCollection* pDPs = pDoc->GetDPCollection(); CPPUNIT_ASSERT_EQUAL(static_cast(1), pDPs->GetCount()); - CPPUNIT_ASSERT_EQUAL(u"TRUE"_ustr, pDoc->GetString(ScAddress(0, 1, 0))); //A2 + CPPUNIT_ASSERT_EQUAL(u"TRUE"_ustr, pDoc->GetString(0, 1, 0)); //A2 // Reload and check filtering of row dimensions saveAndReload(TestFilter::XLSX); @@ -2519,7 +2518,7 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableCompactLayoutXLSX) CPPUNIT_ASSERT_MESSAGE("The show expand/collapse buttons option must be true", pSaveData->GetExpandCollapse()); - CPPUNIT_ASSERT_EQUAL(u"Row Labels"_ustr, rDoc.GetString(ScAddress(10, 1, 0))); + CPPUNIT_ASSERT_EQUAL(u"Row Labels"_ustr, rDoc.GetString(10, 1, 0)); // Check some row fields const std::tuple aCases[] = { @@ -2546,8 +2545,8 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotTableCompactLayoutXLSX) } // check col fields - CPPUNIT_ASSERT_EQUAL(u"ddd"_ustr, rDoc.GetString(ScAddress(11, 1, 0))); - CPPUNIT_ASSERT_EQUAL(u"ddx"_ustr, rDoc.GetString(ScAddress(12, 1, 0))); + CPPUNIT_ASSERT_EQUAL(u"ddd"_ustr, rDoc.GetString(11, 1, 0)); + CPPUNIT_ASSERT_EQUAL(u"ddx"_ustr, rDoc.GetString(12, 1, 0)); }; createScDoc("xlsx/pivot-table/pivotcompact.xlsx"); @@ -2649,21 +2648,24 @@ static void verifyCalcFields(ScDocument* pDoc, bool bBIFF12 = false) { // Verify cell values // "SUM - Field1" - CPPUNIT_ASSERT_EQUAL(u"480"_ustr, pDoc->GetString(ScAddress(3, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"640"_ustr, pDoc->GetString(ScAddress(3, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"1160"_ustr, pDoc->GetString(ScAddress(3, 4, 1))); - CPPUNIT_ASSERT_EQUAL(u"2280"_ustr, pDoc->GetString(ScAddress(3, 5, 1))); + CPPUNIT_ASSERT_EQUAL(u"480"_ustr, pDoc->GetString(3, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"640"_ustr, pDoc->GetString(3, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"1160"_ustr, pDoc->GetString(3, 4, 1)); + CPPUNIT_ASSERT_EQUAL(u"2280"_ustr, pDoc->GetString(3, 5, 1)); // "SUM - Field2" - CPPUNIT_ASSERT_EQUAL(u"30"_ustr, pDoc->GetString(ScAddress(4, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"42"_ustr, pDoc->GetString(ScAddress(4, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"60"_ustr, pDoc->GetString(ScAddress(4, 4, 1))); - CPPUNIT_ASSERT_EQUAL(u"132"_ustr, pDoc->GetString(ScAddress(4, 5, 1))); + CPPUNIT_ASSERT_EQUAL(u"30"_ustr, pDoc->GetString(4, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"42"_ustr, pDoc->GetString(4, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"60"_ustr, pDoc->GetString(4, 4, 1)); + CPPUNIT_ASSERT_EQUAL(u"132"_ustr, pDoc->GetString(4, 5, 1)); // "SUM - Field3" - CPPUNIT_ASSERT_EQUAL(u"0"_ustr, pDoc->GetString(ScAddress(5, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"0"_ustr, pDoc->GetString(ScAddress(5, 5, 1))); + CPPUNIT_ASSERT_EQUAL(u"0"_ustr, pDoc->GetString(5, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"0"_ustr, pDoc->GetString(5, 5, 1)); // "SUM - Field4" - CPPUNIT_ASSERT_EQUAL(u"#VALUE!"_ustr, pDoc->GetString(ScAddress(6, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"#VALUE!"_ustr, pDoc->GetString(ScAddress(6, 5, 1))); + CPPUNIT_ASSERT_EQUAL(u"#VALUE!"_ustr, pDoc->GetString(6, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"#VALUE!"_ustr, pDoc->GetString(6, 5, 1)); + // "SUM - Field5" (Field5 = 'Field4'/1 — must propagate #VALUE!, not give 0) + CPPUNIT_ASSERT_EQUAL(u"#VALUE!"_ustr, pDoc->GetString(7, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"#VALUE!"_ustr, pDoc->GetString(7, 5, 1)); // Verify calculated field definitions ScDPCollection* pDPs = pDoc->GetDPCollection(); @@ -2674,7 +2676,7 @@ static void verifyCalcFields(ScDocument* pDoc, bool bBIFF12 = false) const ScDPDimCalcSaveData* pCalcData = pSaveData->GetExistingDimCalcData(); CPPUNIT_ASSERT(pCalcData); const auto& rCalcFields = pCalcData->GetCalculatedFields(); - CPPUNIT_ASSERT_EQUAL(size_t(4), rCalcFields.size()); + CPPUNIT_ASSERT_EQUAL(size_t(5), rCalcFields.size()); // Field1 = 'Field A' * 20 CPPUNIT_ASSERT_EQUAL(u"Field1"_ustr, rCalcFields[0]->maFieldName); CPPUNIT_ASSERT_EQUAL(u"='Field A'*20"_ustr, rCalcFields[0]->maCalculation); @@ -2691,6 +2693,9 @@ static void verifyCalcFields(ScDocument* pDoc, bool bBIFF12 = false) // BIFF12 formula decompilation adds space before number literal CPPUNIT_ASSERT_EQUAL(u"Field4"_ustr, rCalcFields[3]->maFieldName); CPPUNIT_ASSERT_EQUAL(bBIFF12 ? u"= 2/0"_ustr : u"=2/0"_ustr, rCalcFields[3]->maCalculation); + // Field5 = 'Field4'/1 — error-propagation regression guard + CPPUNIT_ASSERT_EQUAL(u"Field5"_ustr, rCalcFields[4]->maFieldName); + CPPUNIT_ASSERT_EQUAL(u"='Field4'/1"_ustr, rCalcFields[4]->maCalculation); } CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFields1XLSX) @@ -2722,7 +2727,7 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFields1XLSX) assertXPath(pDocXml, "/x:pivotTableDefinition/x:dataFields/x:dataField[6]", "numFmtId", u"164"); // cacheFields pDocXml = parseExport(u"xl/pivotCache/pivotCacheDefinition1.xml"_ustr); - assertXPath(pDocXml, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField", 7); + assertXPath(pDocXml, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField", 8); // cacheField - 1st calculated field assertXPath(pDocXml, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[4]", "name", u"Field1"); @@ -2751,6 +2756,13 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFields1XLSX) u"2/0"); assertXPath(pDocXml, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[7]", "databaseField", u"0"); + // cacheField - 5th calculated field (Field5 = 'Field4'/1) + assertXPath(pDocXml, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[8]", "name", + u"Field5"); + assertXPath(pDocXml, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[8]", "formula", + u"'Field4'/1"); + assertXPath(pDocXml, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[8]", "databaseField", + u"0"); } CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFields1ODS) @@ -2785,6 +2797,9 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFields1ODS) // 4th calculated field: Field4 = 2/0 assertXPath(pDocXml, aFieldPath + "[8]", "source-field-name", u"Field4"); assertXPath(pDocXml, aFieldPath + "[8]", "formula", u"of:=2/0"); + // 5th calculated field: Field5 = 'Field4'/1 + assertXPath(pDocXml, aFieldPath + "[9]", "source-field-name", u"Field5"); + assertXPath(pDocXml, aFieldPath + "[9]", "formula", u"of:='Field4'/1"); } CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFields2XLSX) @@ -2799,17 +2814,17 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFields2XLSX) // "SUM - Field1" { - CPPUNIT_ASSERT_EQUAL(u"144"_ustr, pDoc->GetString(ScAddress(1, 4, 1))); - CPPUNIT_ASSERT_EQUAL(u"320"_ustr, pDoc->GetString(ScAddress(1, 5, 1))); - CPPUNIT_ASSERT_EQUAL(u"116"_ustr, pDoc->GetString(ScAddress(1, 6, 1))); - CPPUNIT_ASSERT_EQUAL(u"2052"_ustr, pDoc->GetString(ScAddress(1, 7, 1))); + CPPUNIT_ASSERT_EQUAL(u"144"_ustr, pDoc->GetString(1, 4, 1)); + CPPUNIT_ASSERT_EQUAL(u"320"_ustr, pDoc->GetString(1, 5, 1)); + CPPUNIT_ASSERT_EQUAL(u"116"_ustr, pDoc->GetString(1, 6, 1)); + CPPUNIT_ASSERT_EQUAL(u"2052"_ustr, pDoc->GetString(1, 7, 1)); } // "SUM - Field2" { - CPPUNIT_ASSERT_EQUAL(u"288"_ustr, pDoc->GetString(ScAddress(2, 4, 1))); - CPPUNIT_ASSERT_EQUAL(u"640"_ustr, pDoc->GetString(ScAddress(2, 5, 1))); - CPPUNIT_ASSERT_EQUAL(u"232"_ustr, pDoc->GetString(ScAddress(2, 6, 1))); - CPPUNIT_ASSERT_EQUAL(u"4104"_ustr, pDoc->GetString(ScAddress(2, 7, 1))); + CPPUNIT_ASSERT_EQUAL(u"288"_ustr, pDoc->GetString(2, 4, 1)); + CPPUNIT_ASSERT_EQUAL(u"640"_ustr, pDoc->GetString(2, 5, 1)); + CPPUNIT_ASSERT_EQUAL(u"232"_ustr, pDoc->GetString(2, 6, 1)); + CPPUNIT_ASSERT_EQUAL(u"4104"_ustr, pDoc->GetString(2, 7, 1)); } } @@ -2825,34 +2840,34 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testGroupAndCalcFieldXLSX) // "a2 - group" { - CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(ScAddress(0, 3, 0))); - CPPUNIT_ASSERT_EQUAL(u"Group1"_ustr, pDoc->GetString(ScAddress(0, 4, 0))); - CPPUNIT_ASSERT_EQUAL(u"Group2"_ustr, pDoc->GetString(ScAddress(0, 5, 0))); - CPPUNIT_ASSERT_EQUAL(u"Total Result"_ustr, pDoc->GetString(ScAddress(0, 6, 0))); + CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(0, 3, 0)); + CPPUNIT_ASSERT_EQUAL(u"Group1"_ustr, pDoc->GetString(0, 4, 0)); + CPPUNIT_ASSERT_EQUAL(u"Group2"_ustr, pDoc->GetString(0, 5, 0)); + CPPUNIT_ASSERT_EQUAL(u"Total Result"_ustr, pDoc->GetString(0, 6, 0)); } // "SUM of a" { - CPPUNIT_ASSERT_EQUAL(u"45"_ustr, pDoc->GetString(ScAddress(1, 4, 0))); - CPPUNIT_ASSERT_EQUAL(u"126"_ustr, pDoc->GetString(ScAddress(1, 5, 0))); - CPPUNIT_ASSERT_EQUAL(u"171"_ustr, pDoc->GetString(ScAddress(1, 6, 0))); + CPPUNIT_ASSERT_EQUAL(u"45"_ustr, pDoc->GetString(1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(u"126"_ustr, pDoc->GetString(1, 5, 0)); + CPPUNIT_ASSERT_EQUAL(u"171"_ustr, pDoc->GetString(1, 6, 0)); } // "SUM of b" { - CPPUNIT_ASSERT_EQUAL(u"54"_ustr, pDoc->GetString(ScAddress(2, 4, 0))); - CPPUNIT_ASSERT_EQUAL(u"135"_ustr, pDoc->GetString(ScAddress(2, 5, 0))); - CPPUNIT_ASSERT_EQUAL(u"189"_ustr, pDoc->GetString(ScAddress(2, 6, 0))); + CPPUNIT_ASSERT_EQUAL(u"54"_ustr, pDoc->GetString(2, 4, 0)); + CPPUNIT_ASSERT_EQUAL(u"135"_ustr, pDoc->GetString(2, 5, 0)); + CPPUNIT_ASSERT_EQUAL(u"189"_ustr, pDoc->GetString(2, 6, 0)); } // "SUM of c" { - CPPUNIT_ASSERT_EQUAL(u"63"_ustr, pDoc->GetString(ScAddress(3, 4, 0))); - CPPUNIT_ASSERT_EQUAL(u"144"_ustr, pDoc->GetString(ScAddress(3, 5, 0))); - CPPUNIT_ASSERT_EQUAL(u"207"_ustr, pDoc->GetString(ScAddress(3, 6, 0))); + CPPUNIT_ASSERT_EQUAL(u"63"_ustr, pDoc->GetString(3, 4, 0)); + CPPUNIT_ASSERT_EQUAL(u"144"_ustr, pDoc->GetString(3, 5, 0)); + CPPUNIT_ASSERT_EQUAL(u"207"_ustr, pDoc->GetString(3, 6, 0)); } // "SUM - Field1" { - CPPUNIT_ASSERT_EQUAL(u"3402"_ustr, pDoc->GetString(ScAddress(4, 4, 0))); - CPPUNIT_ASSERT_EQUAL(u"19440"_ustr, pDoc->GetString(ScAddress(4, 5, 0))); - CPPUNIT_ASSERT_EQUAL(u"39123"_ustr, pDoc->GetString(ScAddress(4, 6, 0))); + CPPUNIT_ASSERT_EQUAL(u"3402"_ustr, pDoc->GetString(4, 4, 0)); + CPPUNIT_ASSERT_EQUAL(u"19440"_ustr, pDoc->GetString(4, 5, 0)); + CPPUNIT_ASSERT_EQUAL(u"39123"_ustr, pDoc->GetString(4, 6, 0)); } save(TestFilter::XLSX); @@ -2919,6 +2934,27 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testGroupAndCalcFieldXLSX) u"0"); } +CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testExtGroupingXLS) +{ + createScDoc("xls/pivottable_ext_grouping.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pCacheDef = parseExport(u"xl/pivotCache/pivotCacheDefinition1.xml"_ustr); + CPPUNIT_ASSERT(pCacheDef); + OUString sGroupItems + = getXPath(pCacheDef, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[@databaseField='0']" + "/x:fieldGroup/x:groupItems", + "count"); + + xmlDocUniquePtr pTable = parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr); + CPPUNIT_ASSERT(pTable); + OUString sPivotFieldItems = getXPath( + pTable, "/x:pivotTableDefinition/x:pivotFields/x:pivotField[last()]/x:items", "count"); + + CPPUNIT_ASSERT_EQUAL(sGroupItems, sPivotFieldItems); +} + CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFields1XLSB) { createScDoc("xlsb/pivot-table/calcfields.xlsb"); @@ -2931,6 +2967,51 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFields1XLSB) verifyCalcFields(pDoc, /*bBIFF12=*/true); } +CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testPivotOutputPositionXLSB) +{ + createScDoc("xlsb/pivot-table/position.xlsb"); + + ScDocShell* pDocSh = getScDocShell(); + pDocSh->ReloadAllLinks(); + ScDocument* pDoc = getScDoc(); + pDoc->CalcAll(); + CPPUNIT_ASSERT_EQUAL(u""_ustr, pDoc->GetString(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(u""_ustr, pDoc->GetString(ScAddress(1, 1, 0))); + CPPUNIT_ASSERT_EQUAL(u""_ustr, pDoc->GetString(ScAddress(2, 1, 0))); + // Without the fix the following strings would be at the 4th row. + CPPUNIT_ASSERT_EQUAL(u"Region"_ustr, pDoc->GetString(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(u"Sum of Sales"_ustr, pDoc->GetString(ScAddress(1, 2, 0))); + CPPUNIT_ASSERT_EQUAL(u"Sum of Units"_ustr, pDoc->GetString(ScAddress(2, 2, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testDatesDiscreteGrouping) +{ + createScDoc("xls/pivottable_dates_grouping.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pCacheDef = parseExport(u"xl/pivotCache/pivotCacheDefinition1.xml"_ustr); + CPPUNIT_ASSERT(pCacheDef); + + assertXPath(pCacheDef, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[last()]/" + "x:fieldGroup/x:groupItems", + "count", u"2"); +} + +CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testInvalidFormats) +{ + createScDoc("xlsx/pivottable_invalid_formats.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pDoc = parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + + // Without the fix in place, this would have failed with + // - Expected: 7 + // - Actual : 9 + assertXPath(pDoc, "/x:pivotTableDefinition/x:formats", "count", u"7"); +} + CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFieldSingleDataDimXLSX) { // Pivot table with a single calculated field as the only data dimension. @@ -2945,10 +3026,10 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFieldSingleDataDimXLSX) CPPUNIT_ASSERT(pDoc->HasPivotTable()); // Verify pivot output values at B4:B7 on sheet 0 - CPPUNIT_ASSERT_EQUAL(u"8976"_ustr, pDoc->GetString(ScAddress(1, 3, 0))); - CPPUNIT_ASSERT_EQUAL(u"9936"_ustr, pDoc->GetString(ScAddress(1, 4, 0))); - CPPUNIT_ASSERT_EQUAL(u"37408"_ustr, pDoc->GetString(ScAddress(1, 5, 0))); - CPPUNIT_ASSERT_EQUAL(u"168168"_ustr, pDoc->GetString(ScAddress(1, 6, 0))); + CPPUNIT_ASSERT_EQUAL(u"8976"_ustr, pDoc->GetString(1, 3, 0)); + CPPUNIT_ASSERT_EQUAL(u"9936"_ustr, pDoc->GetString(1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(u"37408"_ustr, pDoc->GetString(1, 5, 0)); + CPPUNIT_ASSERT_EQUAL(u"168168"_ustr, pDoc->GetString(1, 6, 0)); } CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFieldDiffAggregationXLSX) @@ -2968,23 +3049,23 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFieldDiffAggregationXLSX) // Sheet2 (SUM pivot): B3:C5 on sheet 1 // SUM of Spend: 2010=78, 2011=87, total=165 - CPPUNIT_ASSERT_EQUAL(u"78"_ustr, pDoc->GetString(ScAddress(1, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"87"_ustr, pDoc->GetString(ScAddress(1, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"165"_ustr, pDoc->GetString(ScAddress(1, 4, 1))); + CPPUNIT_ASSERT_EQUAL(u"78"_ustr, pDoc->GetString(1, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"87"_ustr, pDoc->GetString(1, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"165"_ustr, pDoc->GetString(1, 4, 1)); // Field1 = Spend * 2: 2010=156, 2011=174, total=330 - CPPUNIT_ASSERT_EQUAL(u"156"_ustr, pDoc->GetString(ScAddress(2, 2, 1))); - CPPUNIT_ASSERT_EQUAL(u"174"_ustr, pDoc->GetString(ScAddress(2, 3, 1))); - CPPUNIT_ASSERT_EQUAL(u"330"_ustr, pDoc->GetString(ScAddress(2, 4, 1))); + CPPUNIT_ASSERT_EQUAL(u"156"_ustr, pDoc->GetString(2, 2, 1)); + CPPUNIT_ASSERT_EQUAL(u"174"_ustr, pDoc->GetString(2, 3, 1)); + CPPUNIT_ASSERT_EQUAL(u"330"_ustr, pDoc->GetString(2, 4, 1)); // Sheet3 (COUNT pivot): B3:C5 on sheet 2 // COUNT of Spend: 2010=3, 2011=3, total=6 - CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pDoc->GetString(ScAddress(1, 2, 2))); - CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pDoc->GetString(ScAddress(1, 3, 2))); - CPPUNIT_ASSERT_EQUAL(u"6"_ustr, pDoc->GetString(ScAddress(1, 4, 2))); + CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pDoc->GetString(1, 2, 2)); + CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pDoc->GetString(1, 3, 2)); + CPPUNIT_ASSERT_EQUAL(u"6"_ustr, pDoc->GetString(1, 4, 2)); // Field1 must still use SUM(Spend) * 2, not COUNT(Spend) * 2 - CPPUNIT_ASSERT_EQUAL(u"156"_ustr, pDoc->GetString(ScAddress(2, 2, 2))); - CPPUNIT_ASSERT_EQUAL(u"174"_ustr, pDoc->GetString(ScAddress(2, 3, 2))); - CPPUNIT_ASSERT_EQUAL(u"330"_ustr, pDoc->GetString(ScAddress(2, 4, 2))); + CPPUNIT_ASSERT_EQUAL(u"156"_ustr, pDoc->GetString(2, 2, 2)); + CPPUNIT_ASSERT_EQUAL(u"174"_ustr, pDoc->GetString(2, 3, 2)); + CPPUNIT_ASSERT_EQUAL(u"330"_ustr, pDoc->GetString(2, 4, 2)); } CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFieldNameErrorXLSX) @@ -3011,6 +3092,32 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testCalcFieldNameErrorXLSX) CPPUNIT_ASSERT_EQUAL(u"IF(#NAME? >0,#NAME?,0)"_ustr, aFormula); } +CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testNumberGroupingXLS) +{ + createScDoc("xls/pivottable_number_grouping.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pCacheDef = parseExport(u"xl/pivotCache/pivotCacheDefinition1.xml"_ustr); + CPPUNIT_ASSERT(pCacheDef); + + assertXPath(pCacheDef, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[@databaseField='0']/" + "x:fieldGroup/x:groupItems", + "count", u"3"); +} + +CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testExtSourceFieldsXLS) +{ + createScDoc("xls/pivottable_ext_source_fields.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pDocXml = parseExport(u"xl/pivotCache/pivotCacheDefinition1.xml"_ustr); + CPPUNIT_ASSERT(pDocXml); + + // Without the fix, this would only have 7 fields + assertXPath(pDocXml, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField", 13); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/screenshots/screenshots.cxx b/sc/qa/unit/screenshots/screenshots.cxx index c6294de2a795..8765cfb8ffa9 100644 --- a/sc/qa/unit/screenshots/screenshots.cxx +++ b/sc/qa/unit/screenshots/screenshots.cxx @@ -197,9 +197,8 @@ VclPtr ScScreenshotTest::createDialogByID(sal_uInt32 nID) case 9: // "modules/scalc/ui/tabcolordialog.ui" { - pReturnDialog = mpFact->CreateScTabBgColorDlg(mpViewShell->GetFrameWeld(), - ScResId(SCSTR_SET_TAB_BG_COLOR), - ScResId(SCSTR_NO_TAB_BG_COLOR), COL_LIGHTMAGENTA ); + pReturnDialog = mpFact->CreateScTabBgColorDlg( + mpViewShell->GetFrameWeld(), ScResId(SCSTR_SET_TAB_BG_COLOR), COL_LIGHTMAGENTA); break; } diff --git a/sc/qa/unit/scshapetest.cxx b/sc/qa/unit/scshapetest.cxx index c9085999e54c..44eb5599794e 100644 --- a/sc/qa/unit/scshapetest.cxx +++ b/sc/qa/unit/scshapetest.cxx @@ -1383,12 +1383,12 @@ CPPUNIT_TEST_FIXTURE(ScShapeTest, testTdf167450_copySheet) CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aRectSource, pObjTarget->GetLogicRect(), 1); } -CPPUNIT_TEST_FIXTURE(ScShapeTest, testTdf140866) +CPPUNIT_TEST_FIXTURE(ScShapeTest, testTdf140866_copy_shape_preserves_comment) { // Load a document, which has a comment in cell $sheet2.$A$1, and a custom shape in cell // $sheet2.$B$11. When the shape from $sheet2.$B$11 was copied and pasted to $sheet2.$D$9, // the anchor position of comment is changed and after saved to ods the comment was gone. - createScDoc("ods/tdf140866.ods"); + createScDoc("ods/tdf140866_copy_shape_preserves_comment.ods"); ScDocument* pDoc = getScDoc(); // Check that we have the comment on A1 diff --git a/sc/qa/unit/solver.cxx b/sc/qa/unit/solver.cxx new file mode 100644 index 000000000000..4653a8a5bdc2 --- /dev/null +++ b/sc/qa/unit/solver.cxx @@ -0,0 +1,286 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; + +namespace { + +class LpSolverTest: public test::BootstrapFixture +{ + uno::Reference m_xDocument; + +#ifdef ENABLE_COINMP + void testCoinMPSolver(); + void testSLPSolver(); + void testSLPSolverNonlinear(); + void testSLPSolverNonlinearConstraint(); + void testSLPSolverLargeModel(); +#endif + +#ifdef ENABLE_COINMP + void testSolver(OUString const & rName); +#endif + +public: + virtual void setUp() override; + virtual void tearDown() override; + + CPPUNIT_TEST_SUITE(LpSolverTest); +#ifdef ENABLE_COINMP + CPPUNIT_TEST(testCoinMPSolver); + CPPUNIT_TEST(testSLPSolver); + CPPUNIT_TEST(testSLPSolverNonlinear); + CPPUNIT_TEST(testSLPSolverNonlinearConstraint); + CPPUNIT_TEST(testSLPSolverLargeModel); +#endif + CPPUNIT_TEST_SUITE_END(); +}; + +void LpSolverTest::setUp() +{ + test::BootstrapFixture::setUp(); + uno::Reference xComponentLoader = frame::Desktop::create(m_xContext); + uno::Reference xComponent(xComponentLoader->loadComponentFromURL( + u"private:factory/scalc"_ustr, u"_blank"_ustr, 0, + uno::Sequence < css::beans::PropertyValue >())); + m_xDocument.set(xComponent, uno::UNO_QUERY_THROW); +} + +void LpSolverTest::tearDown() +{ + uno::Reference(m_xDocument, uno::UNO_QUERY_THROW)->dispose(); + m_xDocument.clear(); + test::BootstrapFixture::tearDown(); +} + +#ifdef ENABLE_COINMP +void LpSolverTest::testCoinMPSolver() +{ + testSolver(u"com.sun.star.comp.Calc.CoinMPSolver"_ustr); +} + +// The sequential linear solver must also handle a plain linear model. +void LpSolverTest::testSLPSolver() +{ + testSolver(u"com.sun.star.comp.Calc.SLPSolver"_ustr); +} + +// A genuinely nonlinear model: minimize the parabola A1*A1 - 4*A1 + 7, which +// has its minimum at A1 = 2 with value 3. The objective lives in a formula +// cell, so the solver only sees it as a black box and must converge to 2 by +// repeated linearization. +void LpSolverTest::testSLPSolverNonlinear() +{ + uno::Reference xSheets(m_xDocument->getSheets(), + uno::UNO_QUERY_THROW); + uno::Reference xSheet(xSheets->getByIndex(0), uno::UNO_QUERY_THROW); + // B1 holds the objective as a formula of the variable A1 + xSheet->getCellByPosition(1, 0)->setFormula(u"=A1*A1-4*A1+7"_ustr); + + uno::Reference xSolver( + m_xContext->getServiceManager()->createInstanceWithContext( + u"com.sun.star.comp.Calc.SLPSolver"_ustr, m_xContext), + uno::UNO_QUERY_THROW); + + table::CellAddress aObjective(0, 1, 0); // B1 + uno::Sequence aVariables{ { 0, 0, 0 } }; // A1 + uno::Sequence aConstraints{ + { table::CellAddress(0, 0, 0), sheet::SolverConstraintOperator_GREATER_EQUAL, + uno::Any(-10.0) }, + { table::CellAddress(0, 0, 0), sheet::SolverConstraintOperator_LESS_EQUAL, + uno::Any(10.0) } + }; + + xSolver->setDocument(m_xDocument); + xSolver->setObjective(aObjective); + xSolver->setVariables(aVariables); + xSolver->setConstraints(aConstraints); + xSolver->setMaximize(false); + + xSolver->solve(); + CPPUNIT_ASSERT(xSolver->getSuccess()); + uno::Sequence aSolution = xSolver->getSolution(); + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aSolution[0], 1E-4); +} + +// A nonlinear constraint: maximize x + y subject to x*x + y*y <= 1. The optimum +// sits on the circle at x = y = 1/sqrt(2), about 0.7071. The solver linearizes +// the curved boundary at each step and must converge to that tangent point. +void LpSolverTest::testSLPSolverNonlinearConstraint() +{ + uno::Reference xSheets(m_xDocument->getSheets(), + uno::UNO_QUERY_THROW); + uno::Reference xSheet(xSheets->getByIndex(0), uno::UNO_QUERY_THROW); + // B1 holds the nonlinear constraint cell, B2 the objective + xSheet->getCellByPosition(1, 0)->setFormula(u"=A1*A1+A2*A2"_ustr); + xSheet->getCellByPosition(1, 1)->setFormula(u"=A1+A2"_ustr); + // start inside the circle, where the constraint already has a slope + xSheet->getCellByPosition(0, 0)->setValue(0.5); + xSheet->getCellByPosition(0, 1)->setValue(0.5); + + uno::Reference xSolver( + m_xContext->getServiceManager()->createInstanceWithContext( + u"com.sun.star.comp.Calc.SLPSolver"_ustr, m_xContext), + uno::UNO_QUERY_THROW); + + table::CellAddress aObjective(0, 1, 1); // B2 = x + y + uno::Sequence aVariables{ { 0, 0, 0 }, { 0, 0, 1 } }; + uno::Sequence aConstraints{ + // x*x + y*y <= 1 (cell B1) + { table::CellAddress(0, 1, 0), sheet::SolverConstraintOperator_LESS_EQUAL, + uno::Any(1.0) }, + { table::CellAddress(0, 0, 0), sheet::SolverConstraintOperator_GREATER_EQUAL, + uno::Any(-2.0) }, + { table::CellAddress(0, 0, 0), sheet::SolverConstraintOperator_LESS_EQUAL, + uno::Any(2.0) }, + { table::CellAddress(0, 0, 1), sheet::SolverConstraintOperator_GREATER_EQUAL, + uno::Any(-2.0) }, + { table::CellAddress(0, 0, 1), sheet::SolverConstraintOperator_LESS_EQUAL, + uno::Any(2.0) } + }; + + xSolver->setDocument(m_xDocument); + xSolver->setObjective(aObjective); + xSolver->setVariables(aVariables); + xSolver->setConstraints(aConstraints); + xSolver->setMaximize(true); + + xSolver->solve(); + CPPUNIT_ASSERT(xSolver->getSuccess()); + uno::Sequence aSolution = xSolver->getSolution(); + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.70710678, aSolution[0], 1E-3); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.70710678, aSolution[1], 1E-3); +} +#endif + +#ifdef ENABLE_COINMP +// A large model (100-period resource depletion) that the swarm solver cannot +// handle at all. This guards that the sequential linear solver loads it, stays +// feasible, and improves the objective. Full convergence needs faster sampling +// than is in place today, so the time limit is short and only progress is +// checked. +void LpSolverTest::testSLPSolverLargeModel() +{ + OUString aUrl + = m_directories.getURLFromSrc(u"/sc/qa/unit/data/solver/ResourceDepletion.fods"_ustr); + uno::Reference xLoader = frame::Desktop::create(m_xContext); + uno::Reference xComponent(xLoader->loadComponentFromURL( + aUrl, u"_blank"_ustr, 0, uno::Sequence())); + uno::Reference xDocument(xComponent, uno::UNO_QUERY_THROW); + uno::Reference xSheets(xDocument->getSheets(), uno::UNO_QUERY_THROW); + uno::Reference xSheet(xSheets->getByIndex(0), uno::UNO_QUERY_THROW); + + const table::CellAddress aObjective(0, 1, 6); // B7 + // objective value at the document's starting extraction path + double fInitialObjective = xSheet->getCellByPosition(1, 6)->getValue(); + + std::vector aVariableList; + std::vector aConstraintList; + for (sal_Int32 nRow = 9; nRow < 109; ++nRow) // rows 10..109 + { + aVariableList.push_back(table::CellAddress(0, 1, nRow)); // B: extraction + aConstraintList.push_back({ table::CellAddress(0, 1, nRow), + sheet::SolverConstraintOperator_GREATER_EQUAL, uno::Any(0.0) }); + // E: stock remaining after this period must not go negative + aConstraintList.push_back({ table::CellAddress(0, 4, nRow), + sheet::SolverConstraintOperator_GREATER_EQUAL, uno::Any(0.0) }); + } + uno::Sequence aVariables(aVariableList.data(), aVariableList.size()); + uno::Sequence aConstraints(aConstraintList.data(), + aConstraintList.size()); + + uno::Reference xSolver( + m_xContext->getServiceManager()->createInstanceWithContext( + u"com.sun.star.comp.Calc.SLPSolver"_ustr, m_xContext), + uno::UNO_QUERY_THROW); + uno::Reference xProperties(xSolver, uno::UNO_QUERY_THROW); + xProperties->setPropertyValue(u"Timeout"_ustr, uno::Any(sal_Int32(10))); + + xSolver->setDocument(xDocument); + xSolver->setObjective(aObjective); + xSolver->setVariables(aVariables); + xSolver->setConstraints(aConstraints); + xSolver->setMaximize(true); + + xSolver->solve(); + + CPPUNIT_ASSERT(xSolver->getSuccess()); + uno::Sequence aSolution = xSolver->getSolution(); + CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); + for (sal_Int32 i = 0; i < aSolution.getLength(); ++i) + xSheet->getCellByPosition(1, 9 + i)->setValue(aSolution[i]); + double fObjective = xSheet->getCellByPosition(1, 6)->getValue(); + CPPUNIT_ASSERT_MESSAGE("the solver must improve the objective on the large model", + fObjective > fInitialObjective); + + xComponent->dispose(); +} +#endif + +#ifdef ENABLE_COINMP +void LpSolverTest::testSolver(OUString const & rName) +{ + uno::Reference xSolver(m_xContext->getServiceManager()-> + createInstanceWithContext(rName, m_xContext), uno::UNO_QUERY_THROW); + + table::CellAddress aObjective(0, 0, 0); + + // "changing cells" - unknown variables + uno::Sequence aVariables { {0, 0, 0 } }; + + // constraints + uno::Sequence aConstraints{ + { /* Left */ table::CellAddress(0, 0, 0), + /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, + /* Right */ uno::Any(5.0) } + }; + + // initialize solver + xSolver->setDocument( m_xDocument ); + xSolver->setObjective( aObjective ); + xSolver->setVariables( aVariables ); + xSolver->setConstraints( aConstraints ); + xSolver->setMaximize( true ); + + // test results + xSolver->solve(); + CPPUNIT_ASSERT(xSolver->getSuccess()); + uno::Sequence aSolution = xSolver->getSolution(); + CPPUNIT_ASSERT_EQUAL(aSolution.getLength(), aVariables.getLength()); + CPPUNIT_ASSERT_EQUAL(5.0, aSolution[0]); + + uno::Reference xDesc(xSolver, uno::UNO_QUERY_THROW); + const OString sMessage("Empty description for " + OUStringToOString(rName, RTL_TEXTENCODING_UTF8)); + CPPUNIT_ASSERT_MESSAGE(sMessage.getStr(), !xDesc->getComponentDescription().isEmpty()); +} +#endif + +CPPUNIT_TEST_SUITE_REGISTRATION(LpSolverTest); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_export_test.cxx b/sc/qa/unit/subsequent_export_test.cxx index 2c26c3290ea9..9406049439bc 100644 --- a/sc/qa/unit/subsequent_export_test.cxx +++ b/sc/qa/unit/subsequent_export_test.cxx @@ -224,7 +224,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest, testTdf111876) CPPUNIT_ASSERT(pDoc); OUString sTarget = getXPath(pDoc, "/rels:Relationships/rels:Relationship", "Target"); - // Document is saved to the temporary directory, relative path should be different than original one + // Document is saved to the temporary directory, relative path should be different from the original one CPPUNIT_ASSERT(sTarget != "../xls/bug-fixes.xls"); } @@ -1247,7 +1247,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest, testNamedRangeBugfdo62729) createScDoc("ods/fdo62729.ods"); ScDocument* pDoc = getScDoc(); - ScRangeName* pNames = pDoc->GetRangeName(); + ScRangeName* pNames = &pDoc->GetRangeName(); //should be just a single named range CPPUNIT_ASSERT_EQUAL(size_t(1), pNames->size()); pDoc->DeleteTab(0); @@ -1257,7 +1257,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest, testNamedRangeBugfdo62729) pDoc = getScDoc(); - pNames = pDoc->GetRangeName(); + pNames = &pDoc->GetRangeName(); //after reload should still have a named range CPPUNIT_ASSERT_EQUAL(size_t(1), pNames->size()); #endif @@ -2294,6 +2294,235 @@ CPPUNIT_TEST_FIXTURE(ScExportTest, testTdf155368) assertXPath(pStyles, "/x:styleSheet/x:cellXfs/x:xf[2]/x:alignment", "wrapText", u"false"); } +CPPUNIT_TEST_FIXTURE(ScExportTest, testCombinedChartAxesCount) +{ + createScDoc("xls/forum-mso-de-37362.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pChart = parseExport(u"xl/charts/chart1.xml"_ustr); + CPPUNIT_ASSERT(pChart); + + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:catAx", 2); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:valAx", 2); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest, testCombinedChartsAxesSharing) +{ + createScDoc("xls/forum-mso-de-48440.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pChart = parseExport(u"xl/charts/chart3.xml"_ustr); + CPPUNIT_ASSERT(pChart); + + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:catAx", 1); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:valAx", 3); + + OUString barChartAxis1 + = getXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[1]", "val"); + OUString scatterChart1Axis1 + = getXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart[1]/c:axId[1]", "val"); + CPPUNIT_ASSERT_EQUAL(barChartAxis1, scatterChart1Axis1); + + OUString barChartAxis2 + = getXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[2]", "val"); + OUString scatterChart1Axis2 + = getXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart[1]/c:axId[2]", "val"); + CPPUNIT_ASSERT_EQUAL(barChartAxis2, scatterChart1Axis2); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest, testForumFr59757) +{ + createScDoc("xls/forum-fr-59757.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pChart = parseExport(u"xl/charts/chart1.xml"_ustr); + CPPUNIT_ASSERT(pChart); + + // stock chart + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:idx", "val", + u"0"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:order", "val", + u"0"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[2]/c:idx", "val", + u"1"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[2]/c:order", "val", + u"1"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[3]/c:idx", "val", + u"2"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[3]/c:order", "val", + u"2"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[4]/c:idx", "val", + u"3"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[4]/c:order", "val", + u"3"); + + // line chart + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[1]/c:idx", "val", u"4"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[1]/c:order", "val", + u"4"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[2]/c:idx", "val", u"5"); + assertXPath(pChart, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[2]/c:order", "val", + u"5"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest, testColumnBounds) +{ + createScDoc("xls/forum-mso-en4-368528.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pDoc = parseExport(u"xl/drawings/drawing1.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + assertXPathContent(pDoc, + "/xdr:wsDr/mc:AlternateContent/mc:Choice/xdr:twoCellAnchor/xdr:from/xdr:col", + u"0"); // earlier -1 + + pDoc = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + assertXPathContent(pDoc, + "/x:worksheet/mc:AlternateContent/mc:Choice/x:controls/mc:AlternateContent/" + "mc:Choice/x:control/x:controlPr/x:anchor/x:from/xdr:col", + u"0"); // earlier -1 +} + +CPPUNIT_TEST_FIXTURE(ScExportTest, testForumMsoEn4258437) +{ + createScDoc("xls/forum-mso-en4-258437.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pCache = parseExport(u"xl/pivotCache/pivotCacheDefinition1.xml"_ustr); + CPPUNIT_ASSERT(pCache); + + // earlier containsInteger was missing for cacheField="Client Bought Amount" + assertXPath(pCache, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[5]/x:sharedItems", + "containsInteger", u"1"); + + // all integer values + assertXPath(pCache, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[5]/x:sharedItems/x:n[1]", "v", + u"550"); + assertXPath(pCache, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[5]/x:sharedItems/x:n[2]", "v", + u"1100"); + assertXPath(pCache, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[5]/x:sharedItems/x:n[3]", "v", + u"2200"); + assertXPath(pCache, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[5]/x:sharedItems/x:n[4]", "v", + u"5500"); + assertXPath(pCache, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[5]/x:sharedItems/x:n[5]", "v", + u"11000"); + assertXPath(pCache, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[5]/x:sharedItems/x:n[6]", "v", + u"14300"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest, testInvalidSheetNameLength) +{ + createScDoc("xls/forum-mso-en4-109082.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pDoc = parseExport(u"xl/workbook.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + + pDoc = parseExport(u"xl/externalLinks/externalLink1.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/x:externalLink/x:externalBook/x:sheetNames/x:sheetName[1]", "val", + u".xls.xls.xls.xls.xls.xls.xlsShe"); + + pDoc = parseExport(u"xl/workbook.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + assertXPathContent(pDoc, "/x:workbook/x:definedNames/x:definedName[1]", + u"OFFSET('[1].xls.xls.xls.xls.xls.xls.xlsS-1'!$A$2,0,0,(COUNTA('[1].xls.xls." + u"xls.xls.xls.xls.xlsS-1'!$A$1:$A$1048576)-1),1)"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest, testThreadedCommentRoundtrip) +{ + createScDoc("xlsx/threadedComment.xlsx"); + + saveAndReload(TestFilter::XLSX); + ScDocument* pDoc = getScDoc(); + + // Verify the exported XLSX has tc={guid} as the legacy comment author. + xmlDocUniquePtr pXmlComments = parseExport(u"xl/comments1.xml"_ustr); + CPPUNIT_ASSERT(pXmlComments); + sal_Int32 nAuthorId + = getXPath(pXmlComments, "/x:comments/x:commentList/x:comment[@ref='A2']", "authorId") + .toInt32(); + assertXPathContent(pXmlComments, + "/x:comments/x:authors/x:author[" + OString::number(nAuthorId + 1) + "]", + u"tc={FB8EA27E-C1B6-4481-B034-193455CC7425}"); + + // Threaded comment at A2 should survive round-trip. + ScPostIt* pNote = pDoc->GetNote(0, 1, 0); + CPPUNIT_ASSERT(pNote); + // Author should be the display name after round-trip, not tc={guid}. + CPPUNIT_ASSERT_EQUAL(u"Mike Kaganski"_ustr, pNote->GetAuthor()); + + const ScThreadedCommentData* pData = pNote->GetThreadedCommentData(); + CPPUNIT_ASSERT(pData); + CPPUNIT_ASSERT_EQUAL(u"{FB8EA27E-C1B6-4481-B034-193455CC7425}"_ustr, pData->maRoot.maGuid); + CPPUNIT_ASSERT_EQUAL(u"a comment on A2"_ustr, pData->maRoot.maText); + CPPUNIT_ASSERT(!pData->mbDone); + + // Reply should survive. + CPPUNIT_ASSERT_EQUAL(size_t(1), pData->maReplies.size()); + CPPUNIT_ASSERT_EQUAL(u"A reply"_ustr, pData->maReplies[0].maText); + + // Person should survive. + const ScPersonData* pPerson = pDoc->GetPersonById(pData->maRoot.maPersonId); + CPPUNIT_ASSERT(pPerson); + CPPUNIT_ASSERT_EQUAL(u"Mike Kaganski"_ustr, pPerson->maDisplayName); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest, testThreadedCommentOdsRoundtrip) +{ + // Open xlsx with threaded comments, save as ODS, reopen — verify full data survives. + createScDoc("xlsx/threadedComment.xlsx"); + + saveAndReload(TestFilter::ODS); + ScDocument* pDoc = getScDoc(); + + // Verify the ODS XML structure in content.xml. + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + // loext:threaded-comment inside office:annotation with the correct root GUID. + const OString sTC = "//office:annotation/loext:threaded-comment" + "[@loext:id='{FB8EA27E-C1B6-4481-B034-193455CC7425}']"_ostr; + assertXPath(pXmlDoc, sTC, 1); + assertXPathContent(pXmlDoc, sTC + "/loext:text", u"a comment on A2"); + // Not resolved — loext:resolved must be absent. + assertXPath(pXmlDoc, sTC + "[@loext:resolved]", 0); + // One reply with correct text. + assertXPath(pXmlDoc, sTC + "/loext:reply", 1); + assertXPathContent(pXmlDoc, sTC + "/loext:reply/loext:text", u"A reply"); + + // loext:persons at spreadsheet body level. + assertXPath(pXmlDoc, + "//loext:persons/loext:person" + "[@loext:display-name='Mike Kaganski']", + 1); + + // Verify in-memory data after round-trip. + ScPostIt* pNote = pDoc->GetNote(0, 1, 0); + CPPUNIT_ASSERT(pNote); + + const ScThreadedCommentData* pData = pNote->GetThreadedCommentData(); + CPPUNIT_ASSERT(pData); + CPPUNIT_ASSERT_EQUAL(u"{FB8EA27E-C1B6-4481-B034-193455CC7425}"_ustr, pData->maRoot.maGuid); + CPPUNIT_ASSERT_EQUAL(u"a comment on A2"_ustr, pData->maRoot.maText); + CPPUNIT_ASSERT(!pData->mbDone); + + CPPUNIT_ASSERT_EQUAL(size_t(1), pData->maReplies.size()); + CPPUNIT_ASSERT_EQUAL(u"A reply"_ustr, pData->maReplies[0].maText); + + const ScPersonData* pPerson = pDoc->GetPersonById(pData->maRoot.maPersonId); + CPPUNIT_ASSERT(pPerson); + CPPUNIT_ASSERT_EQUAL(u"Mike Kaganski"_ustr, pPerson->maDisplayName); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_export_test2.cxx b/sc/qa/unit/subsequent_export_test2.cxx index 2cd025858d9a..3664068a6eab 100644 --- a/sc/qa/unit/subsequent_export_test2.cxx +++ b/sc/qa/unit/subsequent_export_test2.cxx @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -973,13 +975,40 @@ CPPUNIT_TEST_FIXTURE(ScExportTest2, testTdf106181) assertXPath( pDrawing, "/xdr:wsDr/mc:AlternateContent/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:nvSpPr/xdr:cNvPr", - "hidden", u"0"); + "hidden", u"1"); xmlDocUniquePtr pVmlDrawing = parseExport(u"xl/drawings/vmlDrawing1.vml"_ustr); CPPUNIT_ASSERT(pVmlDrawing); assertXPathContent(pVmlDrawing, "//xx:ClientData/xx:FmlaLink", u"$D$9"); } +CPPUNIT_TEST_FIXTURE(ScExportTest2, testDoubleCheckbox) +{ + createScDoc("ods/tdf106181.ods"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pDrawing = parseExport(u"xl/drawings/drawing1.xml"_ustr); + CPPUNIT_ASSERT(pDrawing); + + assertXPath( + pDrawing, + "/xdr:wsDr/mc:AlternateContent/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:nvSpPr/xdr:cNvPr", + "hidden", u"1"); + OUString aDrawSpid + = getXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:nvSpPr/" + "xdr:cNvPr/a:extLst/a:ext/a14:compatExt", + "spid"); + + CPPUNIT_ASSERT(!aDrawSpid.isEmpty()); + + xmlDocUniquePtr pVmlDrawing = parseExport(u"xl/drawings/vmlDrawing1.vml"_ustr); + CPPUNIT_ASSERT(pVmlDrawing); + + const OUString aVmlSpid = getXPath(pVmlDrawing, "//v:shape", "spid"); + CPPUNIT_ASSERT_EQUAL(aDrawSpid, aVmlSpid); +} + CPPUNIT_TEST_FIXTURE(ScExportTest2, testTdf145057) { createScDoc("xlsx/tdf145057.xlsx"); @@ -1608,6 +1637,322 @@ CPPUNIT_TEST_FIXTURE(ScExportTest2, testTdf137543XLSX) u"_xlfn.LET(_xlpm.first,B5:E15,_xlfn.CHOOSEROWS(_xlpm.first, 1, 3, 5, 7, 9, 11))"); } +CPPUNIT_TEST_FIXTURE(ScExportTest2, testEmptyPivotFieldsTable) +{ + createScDoc("xls/forum-mso-en4-147004.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pDoc = parseExport(u"xl/workbook.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:workbook/x:pivotCaches", 0); + + CPPUNIT_ASSERT_THROW(parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr), + css::container::NoSuchElementException); + CPPUNIT_ASSERT_THROW(parseExport(u"xl/pivotCache/pivotCacheDefinition1.xml"_ustr), + css::container::NoSuchElementException); + CPPUNIT_ASSERT_THROW(parseExport(u"xl/pivotCache/pivotCacheRecords1.xml"_ustr), + css::container::NoSuchElementException); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testOffsetIllegalParam) +{ + createScDoc("ods/offsetIllegalParam.ods"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pWorkbook = parseExport(u"xl/workbook.xml"_ustr); + CPPUNIT_ASSERT(pWorkbook); + + assertXPathContent(pWorkbook, "/x:workbook/x:definedNames/x:definedName[2]", + u"OFFSET(#REF!,0,2)"); + assertXPathContent(pWorkbook, "/x:workbook/x:definedNames/x:definedName[3]", + u"OFFSET(#REF!,0,1)"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testForumEn29552) +{ + createScDoc("xls/forum-en-29552.xls"); + save(TestFilter::XLSX); + + CPPUNIT_ASSERT_THROW(parseExport(u"xl/revisions/revisionHeaders.xml"_ustr), + css::container::NoSuchElementException); + CPPUNIT_ASSERT_THROW(parseExport(u"xl/revisions/userNames.xml"_ustr), + css::container::NoSuchElementException); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testFdo30900) +{ + createScDoc("ods/fdo30900-1.ods"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pWorkbook = parseExport(u"xl/workbook.xml"_ustr); + CPPUNIT_ASSERT(pWorkbook); + + // earlier OFFSET($A$1,1,0,COUNTA($A$2:$A$100)) + assertXPathContent(pWorkbook, "/x:workbook/x:definedNames/x:definedName[1]", + u"OFFSET(Feuille1!$A$1,1,0,COUNTA(Feuille1!$A$2:$A$100))"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testTrueFalseAsDefinedName) +{ + createScDoc("xls/forum-mso-en4-102737.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pWorkbook = parseExport(u"xl/workbook.xml"_ustr); + CPPUNIT_ASSERT(pWorkbook); + + // earlier the name was TRUE + assertXPath(pWorkbook, "/x:workbook/x:definedNames/x:definedName[2]", "name", u"_TRUE"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testPivotTableDate) +{ + createScDoc("xls/forum-mso-en4-243595.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pCache = parseExport(u"xl/pivotCache/pivotCacheDefinition1.xml"_ustr); + CPPUNIT_ASSERT(pCache); + + // earlier "1899-12-29T03:58:14" + assertXPath(pCache, "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[6]/x:sharedItems", + "minDate", u"1899-12-30T00:00:00"); + // earlier + assertXPath(pCache, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[6]/x:sharedItems/x:n[1]", "v", + u"-0.834560185185181"); + // earlier + assertXPath(pCache, + "/x:pivotCacheDefinition/x:cacheFields/x:cacheField[6]/x:sharedItems/x:n[2]", "v", + u"-0.762013888888889"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testSpillErrorRoundtripXLSX) +{ + // Place a #SPILL! error in A1 via formula and verify it round-trips through XLSX. + createScDoc(); + ScDocument* pDocument = getScDoc(); + pDocument->SetString(ScAddress(0, 0, 0), u"=#SPILL!"_ustr); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, pDocument->GetString(ScAddress(0, 0, 0))); + + saveAndReload(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row/x:c", "t", u"e"); + // The OOXML cell error vocabulary has no #SPILL! literal, so the cached + // result is written as #VALUE!. + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row/x:c/x:v", u"#VALUE!"); + + pDocument = getScDoc(); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, pDocument->GetString(ScAddress(0, 0, 0))); + ScFormulaCell* pFormulaCell = pDocument->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("Expected a formula cell after reload.", pFormulaCell != nullptr); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testSpillErrorRoundtripODS) +{ + // Place a #SPILL! error in A1 via formula and verify it round-trips through ODS. + createScDoc(); + ScDocument* pDocument = getScDoc(); + pDocument->SetString(ScAddress(0, 0, 0), u"=#SPILL!"_ustr); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, pDocument->GetString(ScAddress(0, 0, 0))); + + saveAndReload(TestFilter::ODS); + + // Verify the ODS export wrote the error correctly. + xmlDocUniquePtr pContent = parseExport(u"content.xml"_ustr); + CPPUNIT_ASSERT(pContent); + OString aCellPath = "//table:table[1]/table:table-row[1]/table:table-cell[1]"_ostr; + assertXPath(pContent, aCellPath, "value-type", u"string"); + assertXPath(pContent, aCellPath, "formula", u"of:=#SPILL!"); + assertXPath(pContent, aCellPath + "[@calcext:value-type='error']"); + + pDocument = getScDoc(); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, pDocument->GetString(ScAddress(0, 0, 0))); + ScFormulaCell* pFormulaCell = pDocument->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("Expected a formula cell after reload.", pFormulaCell != nullptr); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testArrayFormulaSpillRoundtripXLSX) +{ + // UNIQUE formula blocked by another cell. + // The formula text, the #SPILL! error, and the blocker all need to be present + // after round-trip. Clearing the blocker must expand the matrix result. + + createScDoc(); + + // Source data + insertStringToCell(u"B1"_ustr, u"10"); + insertStringToCell(u"B2"_ustr, u"20"); + insertStringToCell(u"B3"_ustr, u"30"); + insertStringToCell(u"B4"_ustr, u"40"); + + // Blocker at A2 + insertStringToCell(u"A2"_ustr, u"blocker"); + + // UNIQUE formula entered. Plain Enter (not Ctrl+Shift+Enter) so the + // cell becomes a dynamic-array master, not a classic Ctrl+Shift+Enter + // static array. + insertStringToCell(u"A1"_ustr, u"=UNIQUE(B1:B4)"); + + { + ScDocument* pDocument = getScDoc(); + ScFormulaCell* pFormulaCell = pDocument->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("UNIQUE result should be #SPILL!", pFormulaCell != nullptr); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + } + + saveAndReload(TestFilter::XLSX); + + // Verify the dynamic array metadata is written according to the specs: + // - the master cell carries cm="1" pointing at the cell metadata block. + // - xl/metadata.xml declares the XLDAPR type with fDynamic="1". + // - [Content_Types].xml registers metadata.xml. + // - the workbook relationship file references metadata.xml. + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + // Master cell carries cm="1". The formula has the dynamic array + // attribute combination t="array", aca="1", ca="1". + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[@r='A1']", "cm", u"1"); + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[@r='A1']/x:f", "t", u"array"); + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[@r='A1']/x:f", "aca", u"true"); + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[@r='A1']/x:f", "ca", u"1"); + + xmlDocUniquePtr pMetadata = parseExport(u"xl/metadata.xml"_ustr); + CPPUNIT_ASSERT_MESSAGE("xl/metadata.xml must be written", pMetadata); + + assertXPath(pMetadata, "/x:metadata/x:metadataTypes/x:metadataType", "name", u"XLDAPR"); + assertXPath(pMetadata, + "/x:metadata/x:futureMetadata[@name='XLDAPR']/x:bk/x:extLst/x:ext" + "/xda:dynamicArrayProperties", + "fDynamic", u"1"); + assertXPath(pMetadata, "/x:metadata/x:cellMetadata/x:bk/x:rc", "t", u"1"); + assertXPath(pMetadata, "/x:metadata/x:cellMetadata/x:bk/x:rc", "v", u"0"); + + xmlDocUniquePtr pContentTypes = parseExport(u"[Content_Types].xml"_ustr); + CPPUNIT_ASSERT(pContentTypes); + + assertXPath(pContentTypes, + "/ContentType:Types/ContentType:Override[@PartName='/xl/metadata.xml']", + "ContentType", + u"application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml"); + + xmlDocUniquePtr pWorkbookRels = parseExport(u"xl/_rels/workbook.xml.rels"_ustr); + CPPUNIT_ASSERT(pWorkbookRels); + assertXPath( + pWorkbookRels, "/rels:Relationships/rels:Relationship[@Target='metadata.xml']", "Type", + u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata"); + + ScDocument* pDocument = getScDoc(); + + // Blocker text must survive. + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, pDocument->GetString(ScAddress(0, 1, 0))); + + // The formula cell must still be a matrix formula carrying #SPILL! + ScFormulaCell* pFormulaCell = pDocument->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("Expected a formula cell at A1", pFormulaCell != nullptr); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pFormulaCell->GetMatrixFlag()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_MESSAGE("UNIQUE token array must keep its dynamic array flag", + pFormulaCell->GetCode()->HasDynamicArrayFunction()); + + // Clear the blocker - dynamic array must expand. + clearCell(u"A2"_ustr); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(4), nRows); + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDocument->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, pDocument->GetValue(ScAddress(0, 3, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testDynamicArraySpilledExportXLSX) +{ + // Spill.xlsx has C2 = UNIQUE(A2:A5) imported as a dynamic-array + // master that already spilled into C2:C5. Saving back to XLSX must + // write cm="1" on the master cell, t="array" with ref="C2:C5" on + // the formula, and the matching dynamic-array metadata block. + // Slave cells in the spilled range must not carry cm. + + createScDoc("xlsx/Spill.xlsx"); + + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]/x:c[@r='C2']", "cm", u"1"); + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]/x:c[@r='C2']/x:f", "t", u"array"); + assertXPath(pSheet, "/x:worksheet/x:sheetData/x:row[2]/x:c[@r='C2']/x:f", "ref", u"C2:C5"); + assertXPathNoAttribute(pSheet, "/x:worksheet/x:sheetData/x:row[3]/x:c[@r='C3']", "cm"); + assertXPathNoAttribute(pSheet, "/x:worksheet/x:sheetData/x:row[4]/x:c[@r='C4']", "cm"); + assertXPathNoAttribute(pSheet, "/x:worksheet/x:sheetData/x:row[5]/x:c[@r='C5']", "cm"); + + xmlDocUniquePtr pMetadata = parseExport(u"xl/metadata.xml"_ustr); + CPPUNIT_ASSERT_MESSAGE("xl/metadata.xml must be written", pMetadata); + assertXPath(pMetadata, + "/x:metadata/x:futureMetadata[@name='XLDAPR']/x:bk/x:extLst/x:ext" + "/xda:dynamicArrayProperties", + "fDynamic", u"1"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest2, testArrayFormulaSpillRoundtripODS) +{ + // Same scenario as testArrayFormulaSpillRoundtripXLSX but for ODS. + createScDoc(); + + insertStringToCell(u"B1"_ustr, u"10"); + insertStringToCell(u"B2"_ustr, u"20"); + insertStringToCell(u"B3"_ustr, u"30"); + insertStringToCell(u"B4"_ustr, u"40"); + + insertStringToCell(u"A2"_ustr, u"blocker"); + + // Plain Enter so the cell becomes a dynamic-array master. + insertStringToCell(u"A1"_ustr, u"=UNIQUE(B1:B4)"); + + { + ScDocument* pDocument = getScDoc(); + ScFormulaCell* pFormulaCell = pDocument->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("UNIQUE result should be #SPILL!", pFormulaCell != nullptr); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + } + + saveAndReload(TestFilter::ODS); + + ScDocument* pDocument = getScDoc(); + + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, pDocument->GetString(ScAddress(0, 1, 0))); + + ScFormulaCell* pFormulaCell = pDocument->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("Expected a formula cell at A1", pFormulaCell != nullptr); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pFormulaCell->GetMatrixFlag()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_MESSAGE("UNIQUE token array must keep its dynamic array flag", + pFormulaCell->GetCode()->HasDynamicArrayFunction()); + + clearCell(u"A2"_ustr); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(4), nRows); + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDocument->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, pDocument->GetValue(ScAddress(0, 3, 0))); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_export_test3.cxx b/sc/qa/unit/subsequent_export_test3.cxx index 97cfcb0143e5..b4ec6626920d 100644 --- a/sc/qa/unit/subsequent_export_test3.cxx +++ b/sc/qa/unit/subsequent_export_test3.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -237,7 +238,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest3, testBordersExchangeXLSX) pDoc->GetBorderLines(nCol + 2, (nRow * 2) + 8, 0, nullptr, &pLineTop, nullptr, &pLineBottom); if ((nCol < 3) && (nRow == 6)) - { // in this range no lines since minimum size to create a double is 0.5 + { // in this range there are no lines since minimum size to create a double is 0.5 CPPUNIT_ASSERT(!pLineTop); CPPUNIT_ASSERT(!pLineBottom); continue; @@ -1228,9 +1229,18 @@ void ScExportTest3::testLinkedGraphicRT(TestFilter eFormatType) const OString sFailedMessage = OString::Concat("Failed on filter: ") + TestFilterNames.at(eFormatType).toUtf8(); + // linked graphic fetch is deferred during loading, allow link + // updates and trigger the fetch before export + getScDocShell()->getEmbeddedObjectContainer().setUserAllowsLinkUpdate(true); + getScDoc()->GetLinkManager()->UpdateAllLinks(false, u""_ustr); + // Export the document and import again for a check saveAndReload(eFormatType); + // allow link updates on the reloaded document too (for ODS/XLS + // which keep the graphic as a link rather than embedding it) + getScDocShell()->getEmbeddedObjectContainer().setUserAllowsLinkUpdate(true); + // Check whether graphic imported well after export ScDocument* pDoc = getScDoc(); ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); @@ -1340,10 +1350,11 @@ CPPUNIT_TEST_FIXTURE(ScExportTest3, testAbsNamedRangeHTML) pDocSh->DoHardRecalc(); ScDocument* pDoc = getScDoc(); - ScRangeData* pRangeData = pDoc->GetRangeName()->findByUpperName(u"HTML_1"_ustr); - ScSingleRefData* pRef = pRangeData->GetCode()->FirstToken()->GetSingleRef(); + ScRangeData* pRangeData = pDoc->GetRangeName().findByUpperName(u"HTML_1"_ustr); + ScSingleRefData& rRef + = static_cast(pRangeData->GetCode()->FirstToken())->GetSingleRef(); // see tdf#119141 for the reason why this isn't Sheet1.HTML_1 - CPPUNIT_ASSERT_MESSAGE("HTML_1 is an absolute reference", !pRef->IsTabRel()); + CPPUNIT_ASSERT_MESSAGE("HTML_1 is an absolute reference", !rRef.IsTabRel()); } CPPUNIT_TEST_FIXTURE(ScExportTest3, testTdf80149) @@ -2090,6 +2101,91 @@ CPPUNIT_TEST_FIXTURE(ScExportTest3, testTdf170292) u"OFFSET(_cat1,0,2,,)"); } +CPPUNIT_TEST_FIXTURE(ScExportTest3, testPictureTagOrder) +{ + createScDoc("xls/pictureOrder.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet3.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPath(pSheet, "/x:worksheet/x:picture", 1); + assertXPath(pSheet, "/x:worksheet/mc:AlternateContent", 1); + assertXPath(pSheet, "/x:worksheet/x:picture/following-sibling::mc:AlternateContent", 1); + + pSheet = parseExport(u"xl/worksheets/sheet4.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPath(pSheet, "/x:worksheet/x:picture", 1); + assertXPath(pSheet, "/x:worksheet/mc:AlternateContent", 1); + assertXPath(pSheet, "/x:worksheet/x:picture/following-sibling::mc:AlternateContent", 1); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testRefAfterNoName) +{ + createScDoc("ods/ooo88173-1.ods"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + // earlier #NAME?$C7 + assertXPathContent(pSheet, "/x:worksheet/x:conditionalFormatting[5]/x:cfRule/x:formula", + u"#NAME?"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testfdo55572) +{ + createScDoc("xls/fdo55572-1.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pWorkbook = parseExport(u"xl/workbook.xml"_ustr); + CPPUNIT_ASSERT(pWorkbook); + + assertXPathContent( + pWorkbook, "/x:workbook/x:definedNames/x:definedName[1]", + u"'Analisi Venduto per Aliquota IV'!$L$3"); // analisi venduto per aliquota iv!r3c12 + assertXPathContent( + pWorkbook, "/x:workbook/x:definedNames/x:definedName[2]", + u"'Analisi Venduto per Aliquota IV'!$O$3"); // analisi venduto per aliquota iv!r3c15 + assertXPathContent( + pWorkbook, "/x:workbook/x:definedNames/x:definedName[3]", + u"'Analisi Venduto per Aliquota IV'!$L$5"); // analisi venduto per aliquota iv!r5c12 + assertXPathContent( + pWorkbook, "/x:workbook/x:definedNames/x:definedName[4]", + u"'Analisi Venduto per Aliquota IV'!$O$5"); // analisi venduto per aliquota iv!r5c15 + assertXPathContent( + pWorkbook, "/x:workbook/x:definedNames/x:definedName[5]", + u"'Analisi Venduto per Aliquota IV'!$A$7"); // analisi venduto per aliquota iv!r7c1 +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testEmptyTwoCellAnchor) +{ + createScDoc("xls/emptyAnchor.xls"); + save(TestFilter::XLSX); + xmlDocUniquePtr pDrawing = parseExport(u"xl/drawings/drawing1.xml"_ustr); + CPPUNIT_ASSERT(pDrawing); + /* The anchored element on sheet 1 of the doc doesn't contain any graphic + and exporting empty anchors with no graphic produces an error in excel. Hence, + we should not export the anchor at all if it doesn't contain any graphic. + */ + assertXPathContent(pDrawing, "/xdr:wsDr", u""); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest3, testForumMsoEn4145327) +{ + // regressed due to commit 7de38a6f32a0d77c33978195ee9dd22db154ad65 + createScDoc("xlsx/forum-mso-en4-145327.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pWorkbook = parseExport(u"xl/workbook.xml"_ustr); + CPPUNIT_ASSERT(pWorkbook); + + // regressed export -> REPLACE(CELL("filename",!$'1'.A1),1,FIND("]",CELL("filename",!$'1'.A1)),"")-1 + // having invalid string "!$'1'.A1" + assertXPathContent( + pWorkbook, "/x:workbook/x:definedNames/x:definedName[1]", + u"REPLACE(CELL(\"filename\",!A1),1,FIND(\"]\",CELL(\"filename\",!A1)),\"\")-1"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_export_test4.cxx b/sc/qa/unit/subsequent_export_test4.cxx index 85a22b859761..0b1a4afc91bf 100644 --- a/sc/qa/unit/subsequent_export_test4.cxx +++ b/sc/qa/unit/subsequent_export_test4.cxx @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include @@ -31,10 +33,17 @@ #include #include +#include +#include +#include +#include +#include #include #include #include +#include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -154,6 +163,61 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf120177) CPPUNIT_ASSERT_EQUAL(sGroupName1, sGroupName2); } +CPPUNIT_TEST_FIXTURE(ScExportTest4, testSingleValueDroppedOnXlsExport) +{ + // The @ implicit-intersection marker survives an XLS round trip + // even though the BIFF stream has no token for it. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + pDoc->SetFormula(ScAddress(0, 0, 0), u"=@TRANSPOSE(B1:B4)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(0, 0, 0))); + + saveAndReload(TestFilter::XLS); + + pDoc = getScDoc(); + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"=@TRANSPOSE(B1:B4)"_ustr, pDoc->GetFormula(0, 0, 0)); + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(0, 0, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testSingleValueOnArithmeticSurvivesXlsRoundTrip) +{ + // The @ marker survives an XLS round trip even when the array + // intent comes from a plain arithmetic operator on a range, not + // from a matrix function. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + pDoc->SetValue(ScAddress(0, 0, 0), 1.0); + pDoc->SetValue(ScAddress(0, 1, 0), 2.0); + pDoc->SetValue(ScAddress(0, 2, 0), 3.0); + pDoc->SetValue(ScAddress(0, 3, 0), 4.0); + + pDoc->SetFormula(ScAddress(1, 0, 0), u"=@A1:A4 + 10"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + CPPUNIT_ASSERT_EQUAL(11.0, pDoc->GetValue(ScAddress(1, 0, 0))); + + saveAndReload(TestFilter::XLS); + + pDoc = getScDoc(); + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(1, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"=@A1:A4+10"_ustr, pDoc->GetFormula(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL(11.0, pDoc->GetValue(ScAddress(1, 0, 0))); +} + CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf85553) { createScDoc("ods/tdf85553.ods"); @@ -456,9 +520,9 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf134817_HeaderFooterTextWith2SectionXL CPPUNIT_ASSERT(pDoc); assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddHeader", - u"&L&\"Abadi,Regular\"&11aaa&\"Bembo,Regular\"&20bbb"); + u"&L&\"Abadi\"&11aaa&\"Bembo\"&20bbb"); assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddFooter", - u"&R&\"Cambria,Regular\"&14camb&\"Dante,Regular\"&18dant"); + u"&R&\"Cambria\"&14camb&\"Dante\"&18dant"); } CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf121718_UseFirstPageNumberXLSX) @@ -674,7 +738,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf137000_handle_upright) { // Upright is an xml attribute of xdr:txBody/a:bodyPr. It is set when in a textbox menu we // choose, 'do not rotate this element'. Implementations are in tdf#106197 with followup - // tdf#137000. tdf#149538, tdf#149551 improve the implementation to export 'upright' instead + // tdf#137000; tdf#149538, tdf#149551 improve the implementation to export 'upright' instead // of workaround 'rot'. createScDoc("xlsx/tdf137000_export_upright.xlsx"); @@ -701,6 +765,49 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf126305_DataValidatyErrorAlert) u"information"); } +CPPUNIT_TEST_FIXTURE(ScExportTest4, testDataValidationExport) +{ + createScDoc("xlsx/data_validation_test.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + // Sheet1 has 4 data validation checks + // Without this change, some data validations didn't get exported + assertXPath(pSheet, "/x:worksheet/x:dataValidations", "count", u"4"); + CPPUNIT_ASSERT_EQUAL( + 4, countXPathNodes(pSheet, "/x:worksheet/x:dataValidations/x:dataValidation")); + + std::map aExpected{ + { u"A1"_ustr, u"Sheet2!$A$2:$A$4"_ustr }, + { u"A2"_ustr, u"Sheet2!$B$2:$B$4"_ustr }, + { u"B1"_ustr, u"INDIRECT(Sheet2!$A$1)"_ustr }, + { u"B2"_ustr, u"INDIRECT(OFFSET(Sheet2!$A$1,0,1))"_ustr }, + }; + + // Calc's export of data validity checks can differ from Excel's + // if that changes, this test needs to be updated + for (int i = 1; i <= 4; i++) + { + const OString aEntry + = "/x:worksheet/x:dataValidations/x:dataValidation[" + OString::number(i) + "]"; + + const OUString aSqref = getXPath(pSheet, aEntry, "sqref"); + const auto it = aExpected.find(aSqref); + + CPPUNIT_ASSERT_MESSAGE( + OString("Unexpected or duplicated sqref: " + aSqref.toUtf8()).getStr(), + it != aExpected.end()); + + assertXPathContent(pSheet, aEntry + "/x:formula1", it->second); + + aExpected.erase(it); + } + + CPPUNIT_ASSERT_MESSAGE("Not every data validation was exported", aExpected.empty()); +} + CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf76047_externalLink) { createScDoc("xlsx/tdf76047_externalLink.xlsx"); @@ -773,6 +880,21 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf87973_externalLinkSkipUnuseds) CPPUNIT_ASSERT(aFormula2.indexOf("87973_externalSource.ods") >= 0); } +CPPUNIT_TEST_FIXTURE(ScExportTest4, testCool14390_ChartExternalRef) +{ + createScDoc("xlsx/cool14390_chart_external_ref.xlsx"); + save(TestFilter::XLSX); + + // The only reference to rows 38-43 of the external workbook's sheet is + // the chart's own series formula, not a cell formula. Without the fix, + // ProcessExternalRangeRef never caches those cells for export, and the + // exported file's external link keeps them out of its cache. + xmlDocUniquePtr pExtLink = parseExport(u"xl/externalLinks/externalLink1.xml"_ustr); + CPPUNIT_ASSERT(pExtLink); + assertXPath(pExtLink, + "/x:externalLink/x:externalBook/x:sheetDataSet/x:sheetData[@sheetId='2']/x:row", 6); +} + CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf51022_lostPrintRange) { createScDoc("ods/tdf87973_externalLinkSkipUnuseds.ods"); @@ -1069,6 +1191,22 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testCheckboxFormControlXlsxExport) CPPUNIT_ASSERT(pDoc); assertXPathContent(pDoc, "/xml/v:shape/xx:ClientData/xx:Anchor", u"1, 22, 3, 3, 3, 30, 6, 1"); + // Without the fix, the label's font was written as a bare element + assertXPath(pDoc, "/xml/v:shape/v:textbox/div/font", "face", u"Segoe UI"); + assertXPath(pDoc, "/xml/v:shape/v:textbox/div/font", "size", u"160"); + + // Excel builds its model from the DrawingML, so the font has to reach it as well + xmlDocUniquePtr pDrawing = parseExport(u"xl/drawings/drawing1.xml"_ustr); + CPPUNIT_ASSERT(pDrawing); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:p/" + "a:r/a:rPr", + "sz", u"800"); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:p/" + "a:r/a:rPr/a:latin", + "typeface", u"Segoe UI"); + // reloaded document: make sure it still has a flat (non-3d) look uno::Reference xDrawPagesSupplier(mxComponent, UNO_QUERY_THROW); uno::Reference xIA_DrawPage( @@ -1090,6 +1228,174 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testCheckboxFormControlXlsxExport) xPropertySet->getPropertyValue(u"BackgroundColor"_ustr) >>= aColor; // without the fix, this was COL_WHITE CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, aColor); + + OUString sFontName; + xPropertySet->getPropertyValue(u"FontName"_ustr) >>= sFontName; + // without the fix, this was the control's default font + CPPUNIT_ASSERT_EQUAL(u"Segoe UI"_ustr, sFontName); + + float fFontHeight = 0; + xPropertySet->getPropertyValue(u"FontHeight"_ustr) >>= fFontHeight; + // without the fix, this was 10 - so adjacent labels overlapped + CPPUNIT_ASSERT_EQUAL(8.0f, fFontHeight); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testCheckboxFormControlFontXlsxExport) +{ + // Given two checkbox form controls, the first with a bold, italic, doubly underlined and + // struck out label, the second with a singly underlined one: + createScDoc("xlsx/checkbox-form-control-font.xlsx"); + + // When exporting to XLSX: + saveAndReload(TestFilter::XLSX); + + // Then make sure the effects are written into the label's VML markup. Without the fix, the + // element carried neither the effects nor the font name, size and colour. + xmlDocUniquePtr pDoc = parseExport(u"xl/drawings/vmlDrawing1.vml"_ustr); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/xml/v:shape[1]/v:textbox/div/font", "face", u"DejaVu Sans"); + assertXPath(pDoc, "/xml/v:shape[1]/v:textbox/div/font", "size", u"160"); + assertXPath(pDoc, "/xml/v:shape[1]/v:textbox/div/font", "color", u"#c9211e"); + // which record the class names depends on the fonts the document holds + OUString aFontId; + CPPUNIT_ASSERT(getXPath(pDoc, "/xml/v:shape[1]/v:textbox/div/font/b/i/u", "class") + .startsWith(u"font", &aFontId)); + xmlDocUniquePtr pStyles = parseExport(u"xl/styles.xml"_ustr); + CPPUNIT_ASSERT(pStyles); + const OString aRecord + = "/x:styleSheet/x:fonts/x:font[" + OString::number(aFontId.toInt32() + 1) + "]"; + assertXPath(pStyles, aRecord + "/x:u", "val", u"double"); + assertXPath(pStyles, aRecord + "/x:name", "val", u"DejaVu Sans"); + assertXPath(pStyles, aRecord + "/x:sz", "val", u"8"); + assertXPathContent(pDoc, "/xml/v:shape[1]/v:textbox/div/font/b/i/u/s", u"All effects"); + assertXPathContent(pDoc, "/xml/v:shape[2]/v:textbox/div/font/u", u"Underlined"); + assertXPathNoAttribute(pDoc, "/xml/v:shape[2]/v:textbox/div/font/u", "class"); + + // Excel builds its model from the DrawingML, so the effects have to reach it as well + xmlDocUniquePtr pDrawing = parseExport(u"xl/drawings/drawing1.xml"_ustr); + CPPUNIT_ASSERT(pDrawing); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[1]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:p/a:r/a:rPr", + "b", u"1"); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[1]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:p/a:r/a:rPr", + "i", u"1"); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[1]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:p/a:r/a:rPr", + "u", u"dbl"); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[1]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:p/a:r/a:rPr", + "strike", u"sngStrike"); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[1]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:p/a:r/a:rPr/a:solidFill/a:srgbClr", + "val", u"C9211E"); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[2]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:p/a:r/a:rPr", + "u", u"sng"); + + // reloaded document: the controls still carry the effects + auto xDrawPagesSupplier = mxComponent.queryThrow(); + auto xIA_DrawPage + = xDrawPagesSupplier->getDrawPages()->getByIndex(0).queryThrow(); + auto xControlShape = xIA_DrawPage->getByIndex(0).queryThrow(); + auto xPropertySet = xControlShape->getControl().queryThrow(); + + float fFontWeight = 0; + xPropertySet->getPropertyValue(u"FontWeight"_ustr) >>= fFontWeight; + CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, fFontWeight); + + // the control model exposes the slant as a short, not as an awt::FontSlant + sal_Int16 nFontSlant = 0; + xPropertySet->getPropertyValue(u"FontSlant"_ustr) >>= nFontSlant; + CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontSlant_ITALIC), nFontSlant); + + sal_Int16 nFontUnderline = 0; + xPropertySet->getPropertyValue(u"FontUnderline"_ustr) >>= nFontUnderline; + CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::DOUBLE), nFontUnderline); + + sal_Int16 nFontStrikeout = 0; + xPropertySet->getPropertyValue(u"FontStrikeout"_ustr) >>= nFontStrikeout; + CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontStrikeout::SINGLE), nFontStrikeout); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testCheckboxFormControlAlignXlsxExport) +{ + // Given two checkbox form controls, the first with a right and bottom aligned label, the + // second with a centered and top aligned one: + createScDoc("xlsx/checkbox-form-control-align.xlsx"); + + // When exporting to XLSX: + saveAndReload(TestFilter::XLSX); + + // Then make sure the alignment reaches the VML markup. Without the fix, TextHAlign was a + // fixed Center on a button and absent elsewhere, TextVAlign a fixed Center on every control, + // and the
      carried no style. + xmlDocUniquePtr pDoc = parseExport(u"xl/drawings/vmlDrawing1.vml"_ustr); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/xml/v:shape[1]/v:textbox/div", "style", u"text-align:right"); + assertXPathContent(pDoc, "/xml/v:shape[1]/xx:ClientData/xx:TextHAlign", u"Right"); + assertXPathContent(pDoc, "/xml/v:shape[1]/xx:ClientData/xx:TextVAlign", u"Bottom"); + assertXPath(pDoc, "/xml/v:shape[2]/v:textbox/div", "style", u"text-align:center"); + assertXPathContent(pDoc, "/xml/v:shape[2]/xx:ClientData/xx:TextHAlign", u"Center"); + // Top is Excel's default, which it writes by leaving the element out + assertXPath(pDoc, "/xml/v:shape[2]/xx:ClientData/xx:TextVAlign", 0); + + // Excel only honours the alignment when the DrawingML side agrees with the VML + xmlDocUniquePtr pDrawing = parseExport(u"xl/drawings/drawing1.xml"_ustr); + CPPUNIT_ASSERT(pDrawing); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[1]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:bodyPr", + "anchor", u"b"); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[1]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:p/a:pPr", + "algn", u"r"); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[2]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:bodyPr", + "anchor", u"t"); + assertXPath(pDrawing, + "/xdr:wsDr/mc:AlternateContent[2]/mc:Choice/xdr:twoCellAnchor/xdr:sp/xdr:txBody/" + "a:p/a:pPr", + "algn", u"ctr"); + + // reloaded document: the controls still carry the alignment + auto xDrawPagesSupplier = mxComponent.queryThrow(); + auto xIA_DrawPage + = xDrawPagesSupplier->getDrawPages()->getByIndex(0).queryThrow(); + + auto xFirstShape = xIA_DrawPage->getByIndex(0).queryThrow(); + auto xFirst = xFirstShape->getControl().queryThrow(); + sal_Int16 nAlign = 0; + xFirst->getPropertyValue(u"Align"_ustr) >>= nAlign; + CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::TextAlign::RIGHT), nAlign); + style::VerticalAlignment eVerAlign{}; + xFirst->getPropertyValue(u"VerticalAlign"_ustr) >>= eVerAlign; + CPPUNIT_ASSERT_EQUAL(style::VerticalAlignment_BOTTOM, eVerAlign); + + auto xSecondShape = xIA_DrawPage->getByIndex(1).queryThrow(); + auto xSecond = xSecondShape->getControl().queryThrow(); + xSecond->getPropertyValue(u"Align"_ustr) >>= nAlign; + CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::TextAlign::CENTER), nAlign); + xSecond->getPropertyValue(u"VerticalAlign"_ustr) >>= eVerAlign; + CPPUNIT_ASSERT_EQUAL(style::VerticalAlignment_TOP, eVerAlign); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testVMLShapeStroke) +{ + createScDoc("xlsx/checkbox-form-control.xlsx"); + saveAndReload(TestFilter::XLSX); + + xmlDocUniquePtr pDoc = parseExport(u"xl/drawings/vmlDrawing1.vml"_ustr); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/xml/v:shape", "stroked", u"f"); } CPPUNIT_TEST_FIXTURE(ScExportTest4, testButtonFormControlXlsxExport) @@ -1138,6 +1444,290 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testMacrosInXLSX_Array) assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[2]/x:c[2]/x:f", u""); } +CPPUNIT_TEST_FIXTURE(ScExportTest4, testUserDefinedFunctions_XLS) +{ + createScDoc("xls/user_defined_function.xls"); + save(TestFilter::XLSX); + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[44]/x:c[1]/x:f", + u"_xludf.Sum(B9:C42)"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testUserDefinedFunctions_XLSX) +{ + createScDoc("xlsx/user_defined_function.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[42]/x:c[1]/x:f", + u"_xludf.SUM(B9:C42)"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testUserDefinedFunctions_XLS2) +{ + createScDoc("xls/external_named_function.xls"); + save(TestFilter::XLSX); + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[2]/x:f", + u"[1]!_xludf.WEEKNUM(B2,2)-1"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testEmptyExternalDefinedNames) +{ + createScDoc("xlsx/empty_ext_defined_name.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pExt1 = parseExport(u"xl/externalLinks/externalLink1.xml"_ustr); + CPPUNIT_ASSERT(pExt1); + xmlDocUniquePtr pExt2 = parseExport(u"xl/externalLinks/externalLink2.xml"_ustr); + CPPUNIT_ASSERT(pExt2); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[3]/x:c[2]/x:f", u"[1]!HelloWorld"); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[4]/x:c[2]/x:f", + u"TRIM([2]!_xludf.SplitsItems($A1,\",\",COLUMN()-1))"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testCool16026_InvalidUserDefinedFun) +{ + createScDoc("xls/forum-mso-de-49320.xls"); + save(TestFilter::XLSX); + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + // without the fix this would fail with the following result, which produces invalid XLSX: + // - Expected: #REF!(SUM(A1:A2)) + // - Actual : _xludf.(SUM(A1:A2)) + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[3]/x:c[1]/x:f", + u"#REF!(SUM(A1:A2))"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testLocalePrefix) +{ + createScDoc("ods/fdo67682-2.ods"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pStyle = parseExport(u"xl/styles.xml"_ustr); + CPPUNIT_ASSERT(pStyle); + + // earlier "[$-407]#,##0.00\ [$€];[RED]\-#,##0.00\ [$€]" + assertXPath(pStyle, "/x:styleSheet/x:numFmts/x:numFmt[6]", "formatCode", + u"#,##0.00\\ [$€-407];[RED]\\-#,##0.00\\ [$€]"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testCool15769MinimalDBRanges) +{ + createScDoc("ods/cool15769_minimal_DB_ranges.ods"); + save(TestFilter::XLSX); + + uno::Reference xNameAccess + = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), + maTempFile.GetURL()); + // without the fix degenerate tables would have been exported to XLSX + // with only headers/totals and no content, which Excel doesn't accept + CPPUNIT_ASSERT(!xNameAccess->hasByName(u"xl/tables/table1.xml"_ustr)); + CPPUNIT_ASSERT(!xNameAccess->hasByName(u"xl/tables/table4.xml"_ustr)); + // these tables should exist regardless of the change + CPPUNIT_ASSERT(xNameAccess->hasByName(u"xl/tables/table2.xml"_ustr)); + CPPUNIT_ASSERT(xNameAccess->hasByName(u"xl/tables/table3.xml"_ustr)); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testCool15780TotalsRowNeedsContent) +{ + createScDoc("ods/cool15780_totals_row_content.ods"); + save(TestFilter::XLSX); + + // threewheadertotals has a header row, but its only column's totals row cell + // holds a plain value with no aggregate function or label, so without the fix + // it exported as a totals row Excel refused to open. + xmlDocUniquePtr pTable3 = parseExport(u"xl/tables/table3.xml"_ustr); + CPPUNIT_ASSERT(pTable3); + assertXPath(pTable3, "/x:table", "totalsRowCount", u"0"); + + // twowtotals has a totals row but no header row at all. + xmlDocUniquePtr pTable6 = parseExport(u"xl/tables/table6.xml"_ustr); + CPPUNIT_ASSERT(pTable6); + assertXPath(pTable6, "/x:table", "headerRowCount", u"0"); + assertXPath(pTable6, "/x:table", "totalsRowCount", u"0"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testSingleOperatorXlsxRoundTrip) +{ + // The @ operator round-trips through XLSX as _xlfn.SINGLE. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + // Fill A1:A3 so the @ has a real range to collapse. + pDoc->SetValue(ScAddress(0, 0, 0), 1.0); + pDoc->SetValue(ScAddress(0, 1, 0), 2.0); + pDoc->SetValue(ScAddress(0, 2, 0), 3.0); + + // Author =@(A1:A3+0) at B1. The @ collapses the array result of + // (A1:A3+0) to its first element, so B1 reads 1. + pDoc->SetFormula(ScAddress(1, 0, 0), u"=@(A1:A3+0)"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(ScAddress(1, 0, 0))); + + save(TestFilter::XLSX); + + // The saved file carries the _xlfn.SINGLE wrapper, not the bare @. + // The operand brings its own parentheses, so the result has no + // redundant outer pair. + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[2]/x:f", + u"_xlfn.SINGLE(A1:A3+0)"); + + // Reload the saved file. The importer maps _xlfn.SINGLE to the @ + // operator through the OOXML symbol table, so the formula reads + // back exactly as authored. + saveAndReload(TestFilter::XLSX); + pDoc = getScDoc(); + CPPUNIT_ASSERT_EQUAL(u"=@(A1:A3+0)"_ustr, pDoc->GetFormula(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(ScAddress(1, 0, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testSpilledRangeOperatorXlsxExport) +{ + // The # spilled-range operator exports as the _xlfn.ANCHORARRAY + // wrapper the format uses, not a bare A1# that older readers + // reject. + createScDoc(); + ScDocument* pDoc = getScDoc(); + + // A1 spills with SEQUENCE(3) into A1:A3. B1 references the spill + // range with the # postfix. + pDoc->SetFormula(ScAddress(0, 0, 0), u"=SEQUENCE(3)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + pDoc->SetFormula(ScAddress(1, 0, 0), u"=A1#"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[2]/x:f", + u"_xlfn.ANCHORARRAY(A1)"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testSingleOnSpilledRangeXlsxExport) +{ + // OOXML leaves the @ of a plain =@A1# cell out of the text and expresses it by keeping the + // cell a non-array formula, so that cell is written as a bare _xlfn.ANCHORARRAY(A1) and the + // import puts the @ back. An @ over a wider operand keeps the _xlfn.SINGLE call, which is + // what carries the meaning there. + createScDoc(); + ScDocument* pDoc = getScDoc(); + + pDoc->SetFormula(ScAddress(0, 0, 0), u"=SEQUENCE(3)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + pDoc->SetFormula(ScAddress(1, 0, 0), u"=@A1#"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + pDoc->SetFormula(ScAddress(2, 0, 0), u"=@(A1#*2)"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[2]/x:f", + u"_xlfn.ANCHORARRAY(A1)"); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[3]/x:f", + u"_xlfn.SINGLE(_xlfn.ANCHORARRAY(A1)*2)"); + + saveAndReload(TestFilter::XLSX); + pDoc = getScDoc(); + CPPUNIT_ASSERT_EQUAL(u"=@A1#"_ustr, pDoc->GetFormula(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"=@(A1#*2)"_ustr, pDoc->GetFormula(2, 0, 0)); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testParenthesizedSpilledRangeXlsxRoundTrip) +{ + // A # on an operand that is already parenthesised keeps those parentheses inside the + // wrapper, so _xlfn.ANCHORARRAY((A1)), which is what OOXML uses. The import reads that + // back as the postfix (A1)# it came from. + createScDoc(); + ScDocument* pDoc = getScDoc(); + + pDoc->SetFormula(ScAddress(0, 0, 0), u"=SEQUENCE(3)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + pDoc->SetFormula(ScAddress(1, 0, 0), u"=(A1)#"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[2]/x:f", + u"_xlfn.ANCHORARRAY((A1))"); + + saveAndReload(TestFilter::XLSX); + pDoc = getScDoc(); + CPPUNIT_ASSERT_EQUAL(u"=(A1)#"_ustr, pDoc->GetFormula(1, 0, 0)); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testIntersectedSpilledRangeXlsxRoundTrip) +{ + // OOXML writes the intersection operator as a blank and the # before its operand, so the + // two end up next to each other as "A1:A5 _xlfn.ANCHORARRAY(C1)". To read the blank back + // as the operator the import has to know that what follows yields a reference. + createScDoc(); + ScDocument* pDocument = getScDoc(); + + pDocument->SetFormula(ScAddress(1, 0, 0), u"=A1:A5!C1#"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[1]/x:f", + u"A1:A5 _xlfn.ANCHORARRAY(C1)"); + + saveAndReload(TestFilter::XLSX); + pDocument = getScDoc(); + CPPUNIT_ASSERT_EQUAL(u"=A1:A5!C1#"_ustr, pDocument->GetFormula(1, 0, 0)); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest4, testReferenceUnionXlsxRoundTrip) +{ + // OOXML spells the union operator with the same comma that separates + // arguments, so a union saves as a parenthesized list that stays one + // argument and survives the round trip. + + // F1:F3 hold =SUM(A1~B2), =AREAS(A1:A2~B1:B2) and + // =INDEX(A1:B3~D1:E3;1;1;2). + createScDoc("fods/reference-union.fods"); + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT_EQUAL(5.0, pDoc->GetValue(ScAddress(5, 0, 0))); + CPPUNIT_ASSERT_EQUAL(2.0, pDoc->GetValue(ScAddress(5, 1, 0))); + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(5, 2, 0))); + + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[1]/x:c[@r='F1']/x:f", + u"SUM((A1,B2))"); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[2]/x:c[@r='F2']/x:f", + u"AREAS((A1:A2,B1:B2))"); + assertXPathContent(pSheet, "/x:worksheet/x:sheetData/x:row[3]/x:c[@r='F3']/x:f", + u"INDEX((A1:B3,D1:E3),1,1,2)"); + + // On reload each union is still one argument, now inside the parentheses + // the save gave it, and the values are unchanged. + saveAndReload(TestFilter::XLSX); + pDoc = getScDoc(); + CPPUNIT_ASSERT_EQUAL(u"=SUM((A1~B2))"_ustr, pDoc->GetFormula(5, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"=AREAS((A1:A2~B1:B2))"_ustr, pDoc->GetFormula(5, 1, 0)); + CPPUNIT_ASSERT_EQUAL(u"=INDEX((A1:B3~D1:E3),1,1,2)"_ustr, pDoc->GetFormula(5, 2, 0)); + CPPUNIT_ASSERT_EQUAL(5.0, pDoc->GetValue(ScAddress(5, 0, 0))); + CPPUNIT_ASSERT_EQUAL(2.0, pDoc->GetValue(ScAddress(5, 1, 0))); + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(5, 2, 0))); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_export_test5.cxx b/sc/qa/unit/subsequent_export_test5.cxx index 60c525a8ffeb..335b667fba20 100644 --- a/sc/qa/unit/subsequent_export_test5.cxx +++ b/sc/qa/unit/subsequent_export_test5.cxx @@ -71,20 +71,16 @@ CPPUNIT_TEST_FIXTURE(ScExportTest5, testTdf142929_filterLessThanXLSX) assertXPath(pDoc, "//x:customFilters/x:customFilter", "operator", u"lessThan"); } -CPPUNIT_TEST_FIXTURE(ScExportTest5, testInvalidNamedRange) +CPPUNIT_TEST_FIXTURE(ScExportTest5, testQueryTableHeaders) { - // Given a document which has a named range (myname) that refers to the "1" external link, but - // the link's type is xlPathMissing, when importing that document: - createScDoc("xlsx/invalid-named-range.xlsx"); + createScDoc("xlsx/TableEmptyHeaders.xlsx"); + save(TestFilter::XLSX); - // Then make sure that named range is ignored, as "1" can't be resolved, and exporting it back - // to XLSX (without the xlPathMissing link) would corrupt the document: - uno::Reference xDocProps(mxComponent, uno::UNO_QUERY); - uno::Reference xNamedRanges( - xDocProps->getPropertyValue(u"NamedRanges"_ustr), uno::UNO_QUERY); - // Without the fix in place, this test would have failed, we didn't ignore the problematic named - // range on import. - CPPUNIT_ASSERT(!xNamedRanges->hasByName(u"myname"_ustr)); + xmlDocUniquePtr pTable = parseExport(u"xl/tables/table1.xml"_ustr); + CPPUNIT_ASSERT(pTable); + + assertXPath(pTable, "/x:table/x:tableColumns/x:tableColumn[1]", "name", u"Column1"); + assertXPath(pTable, "/x:table/x:tableColumns/x:tableColumn[2]", "name", u"Column2"); } CPPUNIT_TEST_FIXTURE(ScExportTest5, testExternalDefinedNameXLSX) @@ -742,6 +738,25 @@ CPPUNIT_TEST_FIXTURE(ScExportTest5, testAutofilterHiddenButton) } } +CPPUNIT_TEST_FIXTURE(ScExportTest5, testAutofilterShowButton) +{ + createScDoc("xlsx/autofilterShowButton.xlsx"); + saveAndReload(TestFilter::XLSX); + xmlDocUniquePtr pDocXml = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pDocXml); + + assertXPath(pDocXml, "/x:worksheet/x:autoFilter/x:filterColumn", 4); + + assertXPath(pDocXml, "/x:worksheet/x:autoFilter/x:filterColumn[1]", "colId", u"3"); + assertXPath(pDocXml, "/x:worksheet/x:autoFilter/x:filterColumn[1]", "hiddenButton", u"1"); + assertXPath(pDocXml, "/x:worksheet/x:autoFilter/x:filterColumn[2]", "colId", u"4"); + assertXPath(pDocXml, "/x:worksheet/x:autoFilter/x:filterColumn[2]", "hiddenButton", u"1"); + assertXPath(pDocXml, "/x:worksheet/x:autoFilter/x:filterColumn[3]", "colId", u"8"); + assertXPath(pDocXml, "/x:worksheet/x:autoFilter/x:filterColumn[3]", "hiddenButton", u"1"); + assertXPath(pDocXml, "/x:worksheet/x:autoFilter/x:filterColumn[4]", "colId", u"9"); + assertXPath(pDocXml, "/x:worksheet/x:autoFilter/x:filterColumn[4]", "hiddenButton", u"1"); +} + CPPUNIT_TEST_FIXTURE(ScExportTest5, testShapeStyles) { createScDoc(); @@ -964,7 +979,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest5, testTdf157318) // Check if there is one global named range CPPUNIT_ASSERT_EQUAL(static_cast(1), - static_cast(pDoc->GetRangeName()->size())); + static_cast(pDoc->GetRangeName().size())); // Check if there is one named range in the first sheet CPPUNIT_ASSERT_EQUAL(static_cast(1), @@ -1461,12 +1476,63 @@ CPPUNIT_TEST_FIXTURE(ScExportTest5, testTdf170963_row_breaks) xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); CPPUNIT_ASSERT(pSheet); const int nMaxRowBreaks = 1023; - // Original had 1026 row breaks, but the max Excel handles is 1023 - // Without the fix all 1026 got exported + // Original had 1026 row breaks, but the max Excel handles is 1023. + // Without the fix all 1026 got exported. assertXPath(pSheet, "/x:worksheet/x:rowBreaks", "count", OUString::number(nMaxRowBreaks)); CPPUNIT_ASSERT_EQUAL(nMaxRowBreaks, countXPathNodes(pSheet, "/x:worksheet/x:rowBreaks/x:brk")); } +CPPUNIT_TEST_FIXTURE(ScExportTest5, testErrorExternalsInDataValidation) +{ + createScDoc("xlsx/invalid_ext_data_validation.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pDoc = parseExport(u"xl/worksheets/sheet2.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + + assertXPathContent(pDoc, "/x:worksheet/x:dataValidations/x:dataValidation[2]/x:formula1", + u"[2]Hilfsblatt!#REF!"); + + xmlDocUniquePtr pDocXml = parseExport(u"xl/externalLinks/externalLink2.xml"_ustr); + CPPUNIT_ASSERT(pDocXml); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest5, testMissingPathExternal) +{ + createScDoc("xlsx/MissingPathExternal.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pExternalRel + = parseExport(u"xl/externalLinks/_rels/externalLink1.xml.rels"_ustr); + CPPUNIT_ASSERT(pExternalRel); + + assertXPath( + pExternalRel, "/rels:Relationships/rels:Relationship", "Type", + u"http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlPathMissing"); + assertXPath(pExternalRel, "/rels:Relationships/rels:Relationship", "Target", u"Tabelle1"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest5, testQueryTableExport) +{ + createScDoc("xlsx/queryTableExport.xlsx"); + save(TestFilter::XLSX); + + // The file has 32 queryTables; verify the first one has correct attributes + xmlDocUniquePtr pQT = parseExport(u"xl/queryTables/queryTable1.xml"_ustr); + CPPUNIT_ASSERT_MESSAGE("queryTable1.xml was not exported", pQT); + assertXPath(pQT, "/x:queryTable", "name", u"conn_with_delim"); + assertXPath(pQT, "/x:queryTable", "connectionId", u"1"); + assertXPath(pQT, "/x:queryTable", "autoFormatId", u"16"); + assertXPath(pQT, "/x:queryTable", "applyNumberFormats", u"0"); + assertXPath(pQT, "/x:queryTable", "applyFontFormats", u"1"); + assertXPath(pQT, "/x:queryTable", "applyPatternFormats", u"1"); + + // Verify connections.xml delimiter is not double-escaped + xmlDocUniquePtr pConn = parseExport(u"xl/connections.xml"_ustr); + CPPUNIT_ASSERT(pConn); + assertXPath(pConn, "/x:connections/x:connection[1]/x:textPr", "delimiter", u"_x0000_"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_export_test6.cxx b/sc/qa/unit/subsequent_export_test6.cxx new file mode 100644 index 000000000000..8e20bfef40b9 --- /dev/null +++ b/sc/qa/unit/subsequent_export_test6.cxx @@ -0,0 +1,480 @@ +/* -*- 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 "helper/qahelper.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; + +class ScExportTest6 : public ScModelTestBase +{ +public: + ScExportTest6() + : ScModelTestBase(u"sc/qa/unit/data"_ustr) + { + } +}; + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testXlStartupExternalXLS) +{ + createScDoc("xls/XlStartupExternal.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pExternalRel + = parseExport(u"xl/externalLinks/_rels/externalLink1.xml.rels"_ustr); + CPPUNIT_ASSERT(pExternalRel); + + assertXPath( + pExternalRel, "/rels:Relationships/rels:Relationship", "Type", + u"http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlStartup"); + assertXPath(pExternalRel, "/rels:Relationships/rels:Relationship", "Target", u"personal.xls"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testXlStartupExternalXLSX) +{ + createScDoc("xlsx/XlStartupExternal.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pExternalRel + = parseExport(u"xl/externalLinks/_rels/externalLink1.xml.rels"_ustr); + CPPUNIT_ASSERT(pExternalRel); + + assertXPath( + pExternalRel, "/rels:Relationships/rels:Relationship", "Type", + u"http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlStartup"); + assertXPath(pExternalRel, "/rels:Relationships/rels:Relationship", "Target", u"personal.xls"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testShapeMacroExtRef) +{ + createScDoc("xlsx/shape-macro-ext-ref.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pDrawing = parseExport(u"xl/drawings/drawing1.xml"_ustr); + CPPUNIT_ASSERT(pDrawing); + assertXPath(pDrawing, "//xdr:sp", "macro", u"[1]!Importieren"); + + xmlDocUniquePtr pExtLink = parseExport(u"xl/externalLinks/externalLink1.xml"_ustr); + CPPUNIT_ASSERT(pExtLink); + assertXPath(pExtLink, "/x:externalLink/x:externalBook/x:definedNames/x:definedName", "name", + u"Importieren"); +} + +// --- Table Style OOXML Export Tests --- + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testTableStyleDefaultExportXLSX) +{ + // Open xlsx with default table style (TableStyleMedium2), save as xlsx, verify roundtrip + createScDoc("xlsx/TableStyleTest.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pTable = parseExport(u"xl/tables/table1.xml"_ustr); + CPPUNIT_ASSERT(pTable); + + // Table style name should survive roundtrip + assertXPath(pTable, "/x:table/x:tableStyleInfo", "name", u"TableStyleMedium2"); + assertXPath(pTable, "/x:table/x:tableStyleInfo", "showRowStripes", u"1"); + assertXPath(pTable, "/x:table/x:tableStyleInfo", "showColumnStripes", u"0"); + assertXPath(pTable, "/x:table/x:tableStyleInfo", "showFirstColumn", u"0"); + assertXPath(pTable, "/x:table/x:tableStyleInfo", "showLastColumn", u"0"); + + // Verify table range includes total row + assertXPath(pTable, "/x:table", "ref", u"A1:C10"); + assertXPath(pTable, "/x:table", "totalsRowCount", u"1"); + // totalsRowShown is unnecessary and should not be exported + assertXPathNoAttribute(pTable, "/x:table", "totalsRowShown"); + + // Verify column definitions + assertXPath(pTable, "/x:table/x:tableColumns/x:tableColumn[1]", "name", u"A"); + assertXPath(pTable, "/x:table/x:tableColumns/x:tableColumn[3]", "name", u"C"); + + // Total row: Column A should have "Total" label + assertXPath(pTable, "/x:table/x:tableColumns/x:tableColumn[1]", "totalsRowLabel", u"Total"); + + // Total row: Column B should have custom function (COUNTIF) + assertXPath(pTable, "/x:table/x:tableColumns/x:tableColumn[2]", "totalsRowFunction", u"custom"); + assertXPathContent(pTable, "/x:table/x:tableColumns/x:tableColumn[2]/x:totalsRowFormula", + u"COUNTIF(Table2[B],\">5\")"); + + // Total row: Column C should have average function + assertXPath(pTable, "/x:table/x:tableColumns/x:tableColumn[3]", "totalsRowFunction", + u"average"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testTableStyleCustomExportXLSX) +{ + // Open xlsx with custom table style, save as xlsx, verify roundtrip + createScDoc("xlsx/Book1_custom.xlsx"); + save(TestFilter::XLSX); + + // Verify table style info + xmlDocUniquePtr pTable = parseExport(u"xl/tables/table1.xml"_ustr); + CPPUNIT_ASSERT(pTable); + assertXPath(pTable, "/x:table/x:tableStyleInfo", "name", u"Custom_Styles1"); + + // Verify custom style is exported in styles.xml + xmlDocUniquePtr pStyles = parseExport(u"xl/styles.xml"_ustr); + CPPUNIT_ASSERT(pStyles); + + // Custom table style should exist with correct name and 7 elements + assertXPath(pStyles, "/x:styleSheet/x:tableStyles/x:tableStyle", "name", u"Custom_Styles1"); + assertXPath(pStyles, "/x:styleSheet/x:tableStyles/x:tableStyle", "count", u"7"); + + // Verify all 7 table style elements are exported + const char* const sStylePath = "/x:styleSheet/x:tableStyles/x:tableStyle"; + assertXPath(pStyles, OString::Concat(sStylePath) + "/x:tableStyleElement[@type='wholeTable']"); + assertXPath(pStyles, OString::Concat(sStylePath) + "/x:tableStyleElement[@type='headerRow']"); + assertXPath(pStyles, OString::Concat(sStylePath) + "/x:tableStyleElement[@type='totalRow']"); + assertXPath(pStyles, OString::Concat(sStylePath) + "/x:tableStyleElement[@type='firstColumn']"); + assertXPath(pStyles, OString::Concat(sStylePath) + "/x:tableStyleElement[@type='lastColumn']"); + assertXPath(pStyles, + OString::Concat(sStylePath) + "/x:tableStyleElement[@type='firstRowStripe']"); + assertXPath(pStyles, + OString::Concat(sStylePath) + "/x:tableStyleElement[@type='firstColumnStripe']"); + + // Verify DXFs exist for the custom style elements + OUString sDxfCount = getXPath(pStyles, "/x:styleSheet/x:dxfs", "count"); + CPPUNIT_ASSERT(sDxfCount.toInt32() >= 7); + + // Verify each table style element has a valid dxfId attribute + // (DXF order may change during roundtrip, so we check by element type) + OString sWholeTable = OString::Concat(sStylePath) + "/x:tableStyleElement[@type='wholeTable']"; + OString sHeaderRow = OString::Concat(sStylePath) + "/x:tableStyleElement[@type='headerRow']"; + OString sTotalRow = OString::Concat(sStylePath) + "/x:tableStyleElement[@type='totalRow']"; + + // Each element should have a dxfId pointing to a valid DXF + sal_Int32 nWholeTableDxfId = getXPath(pStyles, sWholeTable, "dxfId").toInt32(); + sal_Int32 nHeaderRowDxfId = getXPath(pStyles, sHeaderRow, "dxfId").toInt32(); + sal_Int32 nTotalRowDxfId = getXPath(pStyles, sTotalRow, "dxfId").toInt32(); + + CPPUNIT_ASSERT(nWholeTableDxfId >= 0); + CPPUNIT_ASSERT(nHeaderRowDxfId >= 0); + CPPUNIT_ASSERT(nTotalRowDxfId >= 0); + + // All dxfIds should be different (each element has its own DXF) + CPPUNIT_ASSERT(nWholeTableDxfId != nHeaderRowDxfId); + CPPUNIT_ASSERT(nWholeTableDxfId != nTotalRowDxfId); + CPPUNIT_ASSERT(nHeaderRowDxfId != nTotalRowDxfId); + + // Verify totalRow DXF has double top border (use 1-based index: dxfId + 1) + OString sTotalRowDxf + = "/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nTotalRowDxfId + 1) + "]"; + assertXPath(pStyles, sTotalRowDxf + "/x:border/x:top", "style", u"double"); + + // Verify wholeTable DXF has thin borders + OString sWholeTableDxf + = "/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nWholeTableDxfId + 1) + "]"; + assertXPath(pStyles, sWholeTableDxf + "/x:border/x:left", "style", u"thin"); + assertXPath(pStyles, sWholeTableDxf + "/x:border/x:top", "style", u"thin"); + + // Verify firstRowStripe DXF has a fill with theme color + OString sFirstRowStripe + = OString::Concat(sStylePath) + "/x:tableStyleElement[@type='firstRowStripe']"; + sal_Int32 nFirstRowStripeDxfId = getXPath(pStyles, sFirstRowStripe, "dxfId").toInt32(); + CPPUNIT_ASSERT(nFirstRowStripeDxfId >= 0); + OString sFirstRowStripeDxf + = "/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nFirstRowStripeDxfId + 1) + "]"; + assertXPath(pStyles, sFirstRowStripeDxf + "/x:fill/x:patternFill/x:bgColor", "theme", u"9"); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testTableStyleInnerBordersExportXLSX) +{ + createScDoc("xlsx/tableStyleInnerBorders.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pStyles = parseExport(u"xl/styles.xml"_ustr); + CPPUNIT_ASSERT(pStyles); + + assertXPath(pStyles, "/x:styleSheet/x:tableStyles/x:tableStyle", "name", u"Customtablestyle"); + + // Locate the wholeTable element's DXF (the DXF order may change on roundtrip). + sal_Int32 nWholeTableDxfId + = getXPath( + pStyles, + "/x:styleSheet/x:tableStyles/x:tableStyle/x:tableStyleElement[@type='wholeTable']", + "dxfId") + .toInt32(); + CPPUNIT_ASSERT(nWholeTableDxfId >= 0); + + OString sBorder + = "/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nWholeTableDxfId + 1) + "]/x:border"; + + // The outer borders already exported correctly before the fix. + assertXPath(pStyles, sBorder + "/x:left", "style", u"thin"); + assertXPath(pStyles, sBorder + "/x:top", "style", u"thin"); + + // The inner vertical/horizontal borders must now be exported too (with their + // theme color), instead of being silently lost. + assertXPath(pStyles, sBorder + "/x:vertical", "style", u"thin"); + assertXPath(pStyles, sBorder + "/x:vertical/x:color", "theme", u"8"); + assertXPath(pStyles, sBorder + "/x:horizontal", "style", u"thin"); + assertXPath(pStyles, sBorder + "/x:horizontal/x:color", "theme", u"8"); + + sal_Int32 nHeaderRowDxfId + = getXPath( + pStyles, + "/x:styleSheet/x:tableStyles/x:tableStyle/x:tableStyleElement[@type='headerRow']", + "dxfId") + .toInt32(); + CPPUNIT_ASSERT(nHeaderRowDxfId >= 0); + OString sHdrBorder + = "/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nHeaderRowDxfId + 1) + "]/x:border"; + assertXPath(pStyles, sHdrBorder + "/x:bottom", "style", u"medium"); + assertXPath(pStyles, sHdrBorder + "/x:left", 0); + assertXPath(pStyles, sHdrBorder + "/x:right", 0); + assertXPath(pStyles, sHdrBorder + "/x:top", 0); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testTableStyleCustomRoundtripXLSX) +{ + // Open xlsx with custom table style, save and reload, verify in-memory state + createScDoc("xlsx/Book1_custom.xlsx"); + saveAndReload(TestFilter::XLSX); + + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc); + + // Verify custom table style exists in the document + ScTableStyles* pStyles = pDoc->GetTableStyles(); + CPPUNIT_ASSERT(pStyles); + CPPUNIT_ASSERT(pStyles->GetTableStyle(u"Custom_Styles1"_ustr) != nullptr); + + // Verify DB range has the custom style applied + ScDBData* pDBData = pDoc->GetDBAtArea(0, 0, 0, 3, 10); + CPPUNIT_ASSERT(pDBData); + const ScTableStyleParam* pParam = pDBData->GetTableStyleInfo(); + CPPUNIT_ASSERT(pParam); + CPPUNIT_ASSERT_EQUAL(u"Custom_Styles1"_ustr, pParam->maStyleID); + + // Verify table style options survived roundtrip + CPPUNIT_ASSERT(pParam->mbRowStripes); + CPPUNIT_ASSERT(!pParam->mbColumnStripes); + CPPUNIT_ASSERT(!pParam->mbFirstColumn); + CPPUNIT_ASSERT(!pParam->mbLastColumn); + + // Verify header and total row flags + CPPUNIT_ASSERT(pDBData->HasHeader()); + CPPUNIT_ASSERT(pDBData->HasTotals()); + + // Verify data survived roundtrip + CPPUNIT_ASSERT_EQUAL(u"Names"_ustr, pDoc->GetString(ScAddress(0, 0, 0))); // header + CPPUNIT_ASSERT_EQUAL(u"Summary"_ustr, pDoc->GetString(ScAddress(0, 10, 0))); // total label + CPPUNIT_ASSERT_EQUAL(382.0, pDoc->GetValue(ScAddress(3, 10, 0))); // SUM of Age column +} + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testValidationListNameThroughTableRef) +{ + // A list validation pointing at a name whose body is a table reference used to + // come up empty; the dropdown must list the referenced table column instead. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc); + + pDoc->SetString(ScAddress(1, 1, 0), u"Apple"_ustr); + pDoc->SetString(ScAddress(1, 2, 0), u"Banana"_ustr); + pDoc->SetString(ScAddress(1, 3, 0), u"Cherry"_ustr); + + std::unique_ptr pDB(new ScDBData(u"MyTable"_ustr, 0, 1, 1, 1, 3, true, false)); + ScDBData* pDBRaw = pDB.get(); + CPPUNIT_ASSERT(pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pDB))); + + ScTokenArray aNameTokens(*pDoc); + aNameTokens.AddTableRef(pDBRaw->GetIndex()); + auto pName + = std::make_unique(*pDoc, u"MyName"_ustr, aNameTokens, ScAddress(0, 0, 0)); + ScRangeData* pNameRaw = pName.get(); + CPPUNIT_ASSERT(pDoc->GetRangeName().insert(std::move(pName))); + + ScTokenArray aValidationTokens(*pDoc); + aValidationTokens.AddRangeName(pNameRaw->GetIndex(), -1); + + ScValidationData aValidationData(SC_VALID_LIST, ScConditionMode::Equal, &aValidationTokens, + nullptr, *pDoc, ScAddress(0, 0, 0)); + const sal_uInt32 nValidationKey = pDoc->AddValidationEntry(aValidationData); + CPPUNIT_ASSERT(nValidationKey != 0); + + ScPatternAttr aPattern(pDoc->getCellAttributeHelper()); + aPattern.GetItemSetWritable().Put(SfxUInt32Item(ATTR_VALIDDATA, nValidationKey)); + pDoc->ApplyPattern(3, 3, 0, aPattern); + + const ScValidationData* pData = pDoc->GetValidationEntry(nValidationKey); + CPPUNIT_ASSERT(pData); + std::vector aStrings; + CPPUNIT_ASSERT(pData->FillSelectionList(aStrings, ScAddress(3, 3, 0))); + CPPUNIT_ASSERT_EQUAL(size_t(3), aStrings.size()); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testValidationListNameThroughTableRefWithHeader) +{ + // A list validation pointing at a name that wraps a table reference must show + // the table's data rows, even when the table has a header row and holds + // numbers: the dropdown lists the data values in order, starting at the first. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc); + + pDoc->SetString(ScAddress(1, 0, 0), u"Score"_ustr); + pDoc->SetValue(ScAddress(1, 1, 0), 10.0); + pDoc->SetValue(ScAddress(1, 2, 0), 20.0); + pDoc->SetValue(ScAddress(1, 3, 0), 30.0); + + // Header row plus three data rows; the data part the reference resolves to + // starts one row below the header. + std::unique_ptr pDB(new ScDBData(u"MyTable"_ustr, 0, 1, 0, 1, 3, true, true)); + ScDBData* pDBRaw = pDB.get(); + CPPUNIT_ASSERT(pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pDB))); + + ScTokenArray aNameTokens(*pDoc); + aNameTokens.AddTableRef(pDBRaw->GetIndex()); + auto pName + = std::make_unique(*pDoc, u"MyName"_ustr, aNameTokens, ScAddress(0, 0, 0)); + ScRangeData* pNameRaw = pName.get(); + CPPUNIT_ASSERT(pDoc->GetRangeName().insert(std::move(pName))); + + ScTokenArray aValidationTokens(*pDoc); + aValidationTokens.AddRangeName(pNameRaw->GetIndex(), -1); + + ScValidationData aValidationData(SC_VALID_LIST, ScConditionMode::Equal, &aValidationTokens, + nullptr, *pDoc, ScAddress(0, 0, 0)); + const sal_uInt32 nValidationKey = pDoc->AddValidationEntry(aValidationData); + CPPUNIT_ASSERT(nValidationKey != 0); + + ScPatternAttr aPattern(pDoc->getCellAttributeHelper()); + aPattern.GetItemSetWritable().Put(SfxUInt32Item(ATTR_VALIDDATA, nValidationKey)); + pDoc->ApplyPattern(3, 3, 0, aPattern); + + const ScValidationData* pData = pDoc->GetValidationEntry(nValidationKey); + CPPUNIT_ASSERT(pData); + std::vector aStrings; + CPPUNIT_ASSERT(pData->FillSelectionList(aStrings, ScAddress(3, 3, 0))); + CPPUNIT_ASSERT_EQUAL(size_t(3), aStrings.size()); + CPPUNIT_ASSERT_EQUAL(u"10"_ustr, aStrings[0].GetString()); + CPPUNIT_ASSERT_EQUAL(u"20"_ustr, aStrings[1].GetString()); + CPPUNIT_ASSERT_EQUAL(u"30"_ustr, aStrings[2].GetString()); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testValidationListNameThroughTableRefColumn) +{ + // A name whose body is a column-qualified table reference like MyTable[Score] + // must list only that column's data rows, not the first column and not the + // header. Such a reference compiles to several tokens, which used to leave the + // dropdown empty. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc); + + pDoc->SetString(ScAddress(0, 0, 0), u"Name"_ustr); + pDoc->SetString(ScAddress(1, 0, 0), u"Score"_ustr); + pDoc->SetString(ScAddress(0, 1, 0), u"x"_ustr); + pDoc->SetValue(ScAddress(1, 1, 0), 10.0); + pDoc->SetString(ScAddress(0, 2, 0), u"y"_ustr); + pDoc->SetValue(ScAddress(1, 2, 0), 20.0); + pDoc->SetString(ScAddress(0, 3, 0), u"z"_ustr); + pDoc->SetValue(ScAddress(1, 3, 0), 30.0); + + // Two-column table A1:B4 with a header row. + std::unique_ptr pDB(new ScDBData(u"MyTable"_ustr, 0, 0, 0, 1, 3, true, true)); + CPPUNIT_ASSERT(pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pDB))); + + // Base the name outside the table so the column resolves to the data rows, + // not an intersecting single cell. + auto pName = std::make_unique(*pDoc, u"MyName"_ustr, u"MyTable[[Score]]"_ustr, + ScAddress(0, 5, 0), ScRangeData::Type::Name, + formula::FormulaGrammar::GRAM_NATIVE); + // A column-qualified reference is more than one token. + CPPUNIT_ASSERT(pName->GetCode()->GetLen() > 1); + ScRangeData* pNameRaw = pName.get(); + CPPUNIT_ASSERT(pDoc->GetRangeName().insert(std::move(pName))); + + ScTokenArray aValidationTokens(*pDoc); + aValidationTokens.AddRangeName(pNameRaw->GetIndex(), -1); + + ScValidationData aValidationData(SC_VALID_LIST, ScConditionMode::Equal, &aValidationTokens, + nullptr, *pDoc, ScAddress(0, 0, 0)); + const sal_uInt32 nValidationKey = pDoc->AddValidationEntry(aValidationData); + CPPUNIT_ASSERT(nValidationKey != 0); + + ScPatternAttr aPattern(pDoc->getCellAttributeHelper()); + aPattern.GetItemSetWritable().Put(SfxUInt32Item(ATTR_VALIDDATA, nValidationKey)); + pDoc->ApplyPattern(3, 3, 0, aPattern); + + const ScValidationData* pData = pDoc->GetValidationEntry(nValidationKey); + CPPUNIT_ASSERT(pData); + std::vector aStrings; + CPPUNIT_ASSERT(pData->FillSelectionList(aStrings, ScAddress(3, 3, 0))); + CPPUNIT_ASSERT_EQUAL(size_t(3), aStrings.size()); + CPPUNIT_ASSERT_EQUAL(u"10"_ustr, aStrings[0].GetString()); + CPPUNIT_ASSERT_EQUAL(u"20"_ustr, aStrings[1].GetString()); + CPPUNIT_ASSERT_EQUAL(u"30"_ustr, aStrings[2].GetString()); +} + +CPPUNIT_TEST_FIXTURE(ScExportTest6, testPivotTablesWriteRowColumnItems) +{ + createScDoc("xlsx/forum-mso-de-104083.xlsx"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pTable = parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr); + CPPUNIT_ASSERT(pTable); + + OString sPath1 = "/x:pivotTableDefinition/x:colItems/x:i[4]"_ostr; + + /* + earlier + + + + + + now + + + + */ + assertXPath(pTable, sPath1, "t", u"default"); + assertXPath(pTable, sPath1, "r", u"1"); + assertXPathChildren(pTable, sPath1, 1); + assertXPath(pTable, sPath1 + "/x:x", "v", u"1"); + + /* + earlier + // r = 1 means repeat the years and use the item at index 9 of quarters field, but quarters has only 6 items + + + + now + + + + */ + assertXPath(pTable, "/x:pivotTableDefinition/x:colItems/x:i[3]", "r", u"2"); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_filters_test.cxx b/sc/qa/unit/subsequent_filters_test.cxx index 49cade28eb60..3644f752f476 100644 --- a/sc/qa/unit/subsequent_filters_test.cxx +++ b/sc/qa/unit/subsequent_filters_test.cxx @@ -7,10 +7,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include #include #include #include #include +#include #include #include #include @@ -24,6 +27,8 @@ #include #include #include +#include +#include #include #include "helper/qahelper.hxx" @@ -44,7 +49,7 @@ void testRangeNameImpl(const ScDocument& rDoc) { //check one range data per sheet and one global more detailed //add some more checks here - ScRangeData* pRangeData = rDoc.GetRangeName()->findByUpperName(u"GLOBAL1"_ustr); + ScRangeData* pRangeData = rDoc.GetRangeName().findByUpperName(u"GLOBAL1"_ustr); CPPUNIT_ASSERT_MESSAGE("range name Global1 not found", pRangeData); double aValue = rDoc.GetValue(1, 0, 0); CPPUNIT_ASSERT_EQUAL_MESSAGE("range name Global1 should reference Sheet1.A1", 1.0, aValue); @@ -85,7 +90,7 @@ void testContentImpl(ScDocument& rDoc, bool bCheckMergedCells) OUString aString = rDoc.GetString(1, 0, 0); //check string import - CPPUNIT_ASSERT_EQUAL_MESSAGE("string imported not correctly", u"String1"_ustr, aString); + CPPUNIT_ASSERT_EQUAL_MESSAGE("string not imported correctly", u"String1"_ustr, aString); aString = rDoc.GetString(1, 1, 0); CPPUNIT_ASSERT_EQUAL_MESSAGE("string not imported correctly", u"String2"_ustr, aString); @@ -121,6 +126,39 @@ void testContentImpl(ScDocument& rDoc, bool bCheckMergedCells) } } +CPPUNIT_TEST_FIXTURE(ScFiltersTest, testDrawObjectLinkDeferred) +{ + // draw:object with non-package xlink:href must not trigger type detection + // (which fetches the URL) during import. The link is deferred until the + // user confirms link updates. Uses non-routable 192.0.2.1 so that an + // actual fetch would hang/timeout. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"draw-object-link.fods", aParams); + + const SdrOle2Obj* pOleObj = getSingleOleObject(*getScDoc(), 0); + CPPUNIT_ASSERT_MESSAGE("OLE placeholder should exist after import", pOleObj); + CPPUNIT_ASSERT_MESSAGE("OLE link should be deferred, not created during import", + pOleObj->HasDeferredLink()); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest, testDrawImageRemoteNotFetched) +{ + // draw:image with a remote xlink:href must not fetch the URL during + // import. Uses non-routable 192.0.2.1 so that an actual fetch would + // hang/timeout causing this test to fail. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"draw-image-link.fods", aParams); + + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc); +} + CPPUNIT_TEST_FIXTURE(ScFiltersTest, testContentODS) { createScDoc("ods/universal-content.ods"); @@ -259,6 +297,18 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest, testTdf150452) CPPUNIT_ASSERT_EQUAL(u"1-GE41L"_ustr, pDoc->GetString(0, 3998, 0)); } +CPPUNIT_TEST_FIXTURE(ScFiltersTest, testTdf148749_LMBCS_group_control) +{ + createScDoc("123/tdf148749.123"); + + ScDocument* pDoc = getScDoc(); + + // Without the fix in place, this test would have failed with + // - Expected: abc\ndef + //- Actual : abc-*def + CPPUNIT_ASSERT_EQUAL(u"abc\ndef"_ustr, pDoc->GetString(1, 0, 0)); +} + CPPUNIT_TEST_FIXTURE(ScFiltersTest, testTdf48731) { createScDoc("csv/tdf48731.csv"); @@ -478,12 +528,12 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest, testHiddenRangeNameODS) ScDocument* pDoc = getScDoc(); // This named range is set to "hidden" - ScRangeData* pRangeData1 = pDoc->GetRangeName()->findByUpperName(u"NAMEDRANGE1"_ustr); + ScRangeData* pRangeData1 = pDoc->GetRangeName().findByUpperName(u"NAMEDRANGE1"_ustr); CPPUNIT_ASSERT(pRangeData1); CPPUNIT_ASSERT_EQUAL(static_cast(sheet::NamedRangeFlag::HIDDEN), pRangeData1->GetUnoType() & sheet::NamedRangeFlag::HIDDEN); // This named range is visible - ScRangeData* pRangeData2 = pDoc->GetRangeName()->findByUpperName(u"NAMEDRANGE2"_ustr); + ScRangeData* pRangeData2 = pDoc->GetRangeName().findByUpperName(u"NAMEDRANGE2"_ustr); CPPUNIT_ASSERT(pRangeData2); CPPUNIT_ASSERT_EQUAL(static_cast(0), pRangeData2->GetUnoType() & sheet::NamedRangeFlag::HIDDEN); @@ -496,11 +546,11 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest, testHiddenRangeNameODS) // Check if both named ranges are hidden after saving and reloading saveAndReload(TestFilter::ODS); pDoc = getScDoc(); - pRangeData1 = pDoc->GetRangeName()->findByUpperName(u"NAMEDRANGE1"_ustr); + pRangeData1 = pDoc->GetRangeName().findByUpperName(u"NAMEDRANGE1"_ustr); CPPUNIT_ASSERT(pRangeData1); CPPUNIT_ASSERT_EQUAL(static_cast(sheet::NamedRangeFlag::HIDDEN), pRangeData1->GetUnoType() & sheet::NamedRangeFlag::HIDDEN); - pRangeData2 = pDoc->GetRangeName()->findByUpperName(u"NAMEDRANGE2"_ustr); + pRangeData2 = pDoc->GetRangeName().findByUpperName(u"NAMEDRANGE2"_ustr); CPPUNIT_ASSERT(pRangeData2); CPPUNIT_ASSERT_EQUAL(static_cast(sheet::NamedRangeFlag::HIDDEN), pRangeData2->GetUnoType() & sheet::NamedRangeFlag::HIDDEN); @@ -512,12 +562,12 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest, testHiddenRangeNameXLSX) ScDocument* pDoc = getScDoc(); // This named range is set to "hidden" - ScRangeData* pRangeData1 = pDoc->GetRangeName()->findByUpperName(u"NAMEDRANGE1"_ustr); + ScRangeData* pRangeData1 = pDoc->GetRangeName().findByUpperName(u"NAMEDRANGE1"_ustr); CPPUNIT_ASSERT(pRangeData1); CPPUNIT_ASSERT_EQUAL(static_cast(sheet::NamedRangeFlag::HIDDEN), pRangeData1->GetUnoType() & sheet::NamedRangeFlag::HIDDEN); // This named range is visible - ScRangeData* pRangeData2 = pDoc->GetRangeName()->findByUpperName(u"NAMEDRANGE2"_ustr); + ScRangeData* pRangeData2 = pDoc->GetRangeName().findByUpperName(u"NAMEDRANGE2"_ustr); CPPUNIT_ASSERT(pRangeData2); CPPUNIT_ASSERT_EQUAL(static_cast(0), pRangeData2->GetUnoType() & sheet::NamedRangeFlag::HIDDEN); @@ -525,11 +575,11 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest, testHiddenRangeNameXLSX) // Save as ODS and test if the named ranges are still with the correct hidden flag saveAndReload(TestFilter::ODS); pDoc = getScDoc(); - pRangeData1 = pDoc->GetRangeName()->findByUpperName(u"NAMEDRANGE1"_ustr); + pRangeData1 = pDoc->GetRangeName().findByUpperName(u"NAMEDRANGE1"_ustr); CPPUNIT_ASSERT(pRangeData1); CPPUNIT_ASSERT_EQUAL(static_cast(sheet::NamedRangeFlag::HIDDEN), pRangeData1->GetUnoType() & sheet::NamedRangeFlag::HIDDEN); - pRangeData2 = pDoc->GetRangeName()->findByUpperName(u"NAMEDRANGE2"_ustr); + pRangeData2 = pDoc->GetRangeName().findByUpperName(u"NAMEDRANGE2"_ustr); CPPUNIT_ASSERT(pRangeData2); CPPUNIT_ASSERT_EQUAL(static_cast(0), pRangeData2->GetUnoType() & sheet::NamedRangeFlag::HIDDEN); @@ -541,23 +591,23 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest, testHiddenNamedExpression) ScDocument* pDoc = getScDoc(); // Adds two hidden named expressions and two non-hidden named expressions - ScRangeName* pNamedRanges = pDoc->GetRangeName(); + ScRangeName* pNamedRanges = &pDoc->GetRangeName(); ScRangeData* pRangeData1 = new ScRangeData(*pDoc, u"NAME1"_ustr, u"100"_ustr); pRangeData1->AddType(ScRangeData::Type::Hidden); - pNamedRanges->insert(pRangeData1); + pNamedRanges->insert(std::unique_ptr(pRangeData1)); ScRangeData* pRangeData2 = new ScRangeData(*pDoc, u"NAME2"_ustr, u"text1"_ustr); pRangeData2->AddType(ScRangeData::Type::Hidden); - pNamedRanges->insert(pRangeData2); + pNamedRanges->insert(std::unique_ptr(pRangeData2)); ScRangeData* pRangeData3 = new ScRangeData(*pDoc, u"NAME3"_ustr, u"200"_ustr); - pNamedRanges->insert(pRangeData3); + pNamedRanges->insert(std::unique_ptr(pRangeData3)); ScRangeData* pRangeData4 = new ScRangeData(*pDoc, u"NAME4"_ustr, u"text2"_ustr); - pNamedRanges->insert(pRangeData4); + pNamedRanges->insert(std::unique_ptr(pRangeData4)); CPPUNIT_ASSERT_EQUAL(size_t(4), pNamedRanges->size()); // Save and reload to test whether the named expressions retain the hidden where applicable saveAndReload(TestFilter::ODS); pDoc = getScDoc(); - pNamedRanges = pDoc->GetRangeName(); + pNamedRanges = &pDoc->GetRangeName(); CPPUNIT_ASSERT_EQUAL(size_t(4), pNamedRanges->size()); pRangeData1 = pNamedRanges->findByUpperName(u"NAME1"_ustr); CPPUNIT_ASSERT(pRangeData1); @@ -583,12 +633,12 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest, testHiddenNamedExpressionODS) ScDocument* pDoc = getScDoc(); // The document has 2 named expressions; the first is hidden; the second is visible - ScRangeName* pNamedRanges = pDoc->GetRangeName(); - ScRangeData* pRangeData1 = pNamedRanges->findByUpperName(u"NAME1"_ustr); + ScRangeName& rNamedRanges = pDoc->GetRangeName(); + ScRangeData* pRangeData1 = rNamedRanges.findByUpperName(u"NAME1"_ustr); CPPUNIT_ASSERT(pRangeData1); CPPUNIT_ASSERT_EQUAL(ScRangeData::Type::Hidden, pRangeData1->GetType()); CPPUNIT_ASSERT_EQUAL(u"100"_ustr, pRangeData1->GetSymbol()); - ScRangeData* pRangeData2 = pNamedRanges->findByUpperName(u"NAME2"_ustr); + ScRangeData* pRangeData2 = rNamedRanges.findByUpperName(u"NAME2"_ustr); CPPUNIT_ASSERT(pRangeData2); CPPUNIT_ASSERT_EQUAL(ScRangeData::Type::Name, pRangeData2->GetType()); CPPUNIT_ASSERT_EQUAL(u"200"_ustr, pRangeData2->GetSymbol()); @@ -1610,6 +1660,157 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest, testNonAsciiWithDotXLSX) CPPUNIT_ASSERT_EQUAL(5.0, aValue); } +CPPUNIT_TEST_FIXTURE(ScFiltersTest, testCmImportSetsDynamicArrayMaster) +{ + // The cm="1" attribute on an XLSX cell lands as a dynamic-array master. + + createScDoc("xlsx/Spill.xlsx"); + ScDocument* pDoc = getScDoc(); + + // C2 carries cm="1" with t="array" ref="C2:C5", the spilled master. + ScFormulaCell* pSpilled = pDoc->GetFormulaCell(ScAddress(2, 1, 0)); + CPPUNIT_ASSERT(pSpilled); + CPPUNIT_ASSERT(pSpilled->IsDynamicArrayMaster()); + + // A2 is a plain value cell, so the document holds no formula at A2. + ScFormulaCell* pValueCell = pDoc->GetFormulaCell(ScAddress(0, 1, 0)); + CPPUNIT_ASSERT(!pValueCell); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest, testCmRoundTripXLSX) +{ + // The dynamic-array marker survives an XLSX save and reload through + // the cm="1" attribute on the master cell. + + createScDoc("xlsx/Spill.xlsx"); + + saveAndReload(TestFilter::XLSX); + + ScDocument* pDoc = getScDoc(); + + ScFormulaCell* pMaster = pDoc->GetFormulaCell(ScAddress(2, 1, 0)); + CPPUNIT_ASSERT(pMaster); + CPPUNIT_ASSERT(pMaster->IsDynamicArrayMaster()); +} +CPPUNIT_TEST_FIXTURE(ScFiltersTest, testIntersectionOperatorXlsxRoundTrip) +{ + // The fixture has A1:A4 = {42, 69, 13, 666} and three cells + // that read back the upper-left value 42 through implicit + // intersection. All three import as plain formulas, so + // GetFormula returns them without {} wrapping. The same shape + // survives an XLSX round trip. + + auto assertFormulas = [](ScDocument* pDoc) { + // C1: plain =A1:A4 range reference. No t="array" tag, so + // the cell collapses through implicit intersection at row 1. + CPPUNIT_ASSERT_EQUAL(u"=A1:A4"_ustr, pDoc->GetFormula(2, 0, 0)); + CPPUNIT_ASSERT_EQUAL(42.0, pDoc->GetValue(ScAddress(2, 0, 0))); + + // D1: t="array" wrapper around (A1:A4+0). The outer paren + // pair the writer adds is stripped on import. + CPPUNIT_ASSERT_EQUAL(u"=@(A1:A4+0)"_ustr, pDoc->GetFormula(3, 0, 0)); + CPPUNIT_ASSERT_EQUAL(42.0, pDoc->GetValue(ScAddress(3, 0, 0))); + + // E1: t="array" wrapper around TRANSPOSE(A1:A4). The + // argument is a function call, so no outer paren strip. + CPPUNIT_ASSERT_EQUAL(u"=@(TRANSPOSE(A1:A4))"_ustr, pDoc->GetFormula(4, 0, 0)); + CPPUNIT_ASSERT_EQUAL(42.0, pDoc->GetValue(ScAddress(4, 0, 0))); + }; + + createScDoc("xlsx/IntersectionOperatorFixture.xlsx"); + assertFormulas(getScDoc()); + + saveAndReload(TestFilter::XLSX); + assertFormulas(getScDoc()); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest, testArrayFormulaSpillXLSX) +{ + // D2 holds =UNIQUE(A2:A5) imported in #SPILL! state with blocker text + // "block" at D5. Clearing the blocker must auto resolve the spill and + // expand the matrix into D2:D5 with the values from A2:A5. + createScDoc("xlsx/Spill.xlsx"); + ScDocument* pDocument = getScDoc(); + + ScFormulaCell* pFormulaCell = pDocument->GetFormulaCell(ScAddress(3, 1, 0)); + CPPUNIT_ASSERT_MESSAGE("Expected a formula cell at D2.", pFormulaCell != nullptr); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, pDocument->GetString(ScAddress(3, 1, 0))); + // The blocking cell must not have been overwritten. + CPPUNIT_ASSERT_EQUAL(u"block"_ustr, pDocument->GetString(ScAddress(3, 4, 0))); + + // Clear the blocker at D5 and trigger spill resolution. + pDocument->SetString(ScAddress(3, 4, 0), u""_ustr); + getScDocShell()->ResolveSpilledOutputs(); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + // UNIQUE(A2:A5) + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(3, 1, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDocument->GetValue(ScAddress(3, 2, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(3, 3, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, pDocument->GetValue(ScAddress(3, 4, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest, testConventionalArrayFormulaSpillXLSX) +{ + // G2 holds the conventional matrix formula =A2:A5 imported in #SPILL! + // state with blocker text "block" at G5. Clearing the blocker must + // auto-resolve the spill and expand the matrix into G2:G5 with the + // values from A2:A5. + createScDoc("xlsx/Spill.xlsx"); + ScDocument* pDocument = getScDoc(); + + ScFormulaCell* pFormulaCell = pDocument->GetFormulaCell(ScAddress(6, 1, 0)); + CPPUNIT_ASSERT_MESSAGE("Expected a formula cell at G2.", pFormulaCell != nullptr); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, pDocument->GetString(ScAddress(6, 1, 0))); + // The blocking cell must not have been overwritten. + CPPUNIT_ASSERT_EQUAL(u"block"_ustr, pDocument->GetString(ScAddress(6, 4, 0))); + + // Clear the blocker at G5 and trigger spill resolution. + pDocument->SetString(ScAddress(6, 4, 0), u""_ustr); + getScDocShell()->ResolveSpilledOutputs(); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + // =A2:A5 + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(6, 1, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDocument->GetValue(ScAddress(6, 2, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(6, 3, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, pDocument->GetValue(ScAddress(6, 4, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest, testExpandedArrayCollapsesOnNewBlockerXLSX) +{ + // C2 holds =UNIQUE(A2:A5) imported as an expanded matrix into C2:C5. + // Writing a blocker into one of the reference cells must collapse + // the master back to #SPILL!, with the typed value preserved at the + // blocker position. + createScDoc("xlsx/Spill.xlsx"); + ScDocument* pDocument = getScDoc(); + ScDocShell* pDocShell = getScDocShell(); + + ScFormulaCell* pFormulaCell = pDocument->GetFormulaCell(ScAddress(2, 1, 0)); + CPPUNIT_ASSERT_MESSAGE("Expected a formula cell at C2.", pFormulaCell != nullptr); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(2, 1, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDocument->GetValue(ScAddress(2, 2, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(2, 3, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, pDocument->GetValue(ScAddress(2, 4, 0))); + + // Drop a blocker into C5 (a reference cell). + pDocShell->GetDocFunc().SetStringCell(ScAddress(2, 4, 0), u"blocker"_ustr, /*bApi*/ true); + + // The master collapses to a 1x1 #SPILL!, blocker should be preserved. + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, pDocument->GetString(ScAddress(2, 1, 0))); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, pDocument->GetString(ScAddress(2, 4, 0))); + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nRows); +} + ScFiltersTest::ScFiltersTest() : ScModelTestBase(u"sc/qa/unit/data"_ustr) { diff --git a/sc/qa/unit/subsequent_filters_test2.cxx b/sc/qa/unit/subsequent_filters_test2.cxx index f6d82f780c14..139708add9ef 100644 --- a/sc/qa/unit/subsequent_filters_test2.cxx +++ b/sc/qa/unit/subsequent_filters_test2.cxx @@ -1507,9 +1507,9 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest2, testNamedExpressionsXLSXML_Global) CPPUNIT_ASSERT_EQUAL(u"=SUM(MyRange2)"_ustr, pDoc->GetFormula(aPos.Col(), aPos.Row(), aPos.Tab())); - const ScRangeData* pRD = pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + const ScRangeData* pRD = pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pRD); - pRD = pDoc->GetRangeName()->findByUpperName(u"MYRANGE2"_ustr); + pRD = pDoc->GetRangeName().findByUpperName(u"MYRANGE2"_ustr); CPPUNIT_ASSERT(pRD); } @@ -1673,6 +1673,61 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest2, testNamedTableRef) } } +CPPUNIT_TEST_FIXTURE(ScFiltersTest2, testTableRefColumnLineBreak) +{ + createScDoc("xlsx/tableref-column-linebreak.xlsx"); + ScDocument* pDoc = getScDoc(); + + // The imported table column name keeps its real line break: the _x000a_ + // escape in the tableColumn "name" attribute is decoded on import. + const ScDBData* pData + = pDoc->GetDBCollection()->getNamedDBs().findByUpperName(u"TABLEWITHBREAK"_ustr); + CPPUNIT_ASSERT(pData); + CPPUNIT_ASSERT(!pData->GetTableColumnNames().empty()); + CPPUNIT_ASSERT_EQUAL(u"Also LONG\nBUT TWO LINES"_ustr, pData->GetTableColumnNames()[0]); + + // The structured reference keeps the real line break in its string form + // (like Excel's two-paragraph display), not an _x000a_ escape. + const OUString aTotalFormula = pDoc->GetFormula(5, 5, 0); // totals row F6 + CPPUNIT_ASSERT(aTotalFormula.indexOf(u"_x000a_") < 0); + CPPUNIT_ASSERT(aTotalFormula.indexOf('\n') >= 0); + + // Both defined names resolve to their column's 4 data cells. Without the fix + // LongNameWithBreak fails to resolve and COUNTA yields #NAME?. + pDoc->SetString(ScAddress(7, 0, 0), u"=COUNTA(LongNameNormal)"_ustr); + pDoc->SetString(ScAddress(7, 1, 0), u"=COUNTA(LongNameWithBreak)"_ustr); + pDoc->CalcAll(); + ScFormulaCell* pNormal = pDoc->GetFormulaCell(ScAddress(7, 0, 0)); + ScFormulaCell* pBreak = pDoc->GetFormulaCell(ScAddress(7, 1, 0)); + CPPUNIT_ASSERT(pNormal); + CPPUNIT_ASSERT(pBreak); + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, pNormal->GetErrCode()); + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, pBreak->GetErrCode()); + CPPUNIT_ASSERT_EQUAL(4.0, pDoc->GetValue(ScAddress(7, 0, 0))); + CPPUNIT_ASSERT_EQUAL(4.0, pDoc->GetValue(ScAddress(7, 1, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest2, testTableRefColumnLineBreakExport) +{ + createScDoc("xlsx/tableref-column-linebreak.xlsx"); + saveAndReload(TestFilter::XLSX); + ScDocument* pDoc = getScDoc(); + + const ScDBData* pData + = pDoc->GetDBCollection()->getNamedDBs().findByUpperName(u"TABLEWITHBREAK"_ustr); + CPPUNIT_ASSERT(pData); + CPPUNIT_ASSERT(!pData->GetTableColumnNames().empty()); + CPPUNIT_ASSERT_EQUAL(u"Also LONG\nBUT TWO LINES"_ustr, pData->GetTableColumnNames()[0]); + + // The defined name still resolves to its column's 4 data cells after export. + pDoc->SetString(ScAddress(7, 1, 0), u"=COUNTA(LongNameWithBreak)"_ustr); + pDoc->CalcAll(); + ScFormulaCell* pBreak = pDoc->GetFormulaCell(ScAddress(7, 1, 0)); + CPPUNIT_ASSERT(pBreak); + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, pBreak->GetErrCode()); + CPPUNIT_ASSERT_EQUAL(4.0, pDoc->GetValue(ScAddress(7, 1, 0))); +} + namespace { void testCells(const ScDocument* pDoc) @@ -1753,12 +1808,38 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest2, testTdf66377) CPPUNIT_ASSERT(pAttr); const SvxBrushItem* pExplicitBackground = pAttr->GetItemSet().GetItemIfSet(ATTR_BACKGROUND); CPPUNIT_ASSERT(!pExplicitBackground); - // Without the fix in place it would not have fail and + // Without the fix in place it would not have failed and // we would have a transparent white color set /*const Color& rColor = pExplicitBackground->GetColor(); CPPUNIT_ASSERT_EQUAL(Color(COL_TRANSPARENT), rColor);*/ } +CPPUNIT_TEST_FIXTURE(ScFiltersTest2, testTdf122945TabColorProtectedSheet) +{ + createScDoc("xlsx/tdf122945_TabColorProtectedSheet.xlsx"); + + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc->IsTabProtected(0)); + + // Without the fix in place, this test would have failed with + // - Expected: rgba[ff0000ff] (RED) + // - Actual : rgba[ffffff00] (COL_AUTO) + // i.e. the sheet protection prevented the import of the tab color + CPPUNIT_ASSERT_EQUAL(Color(0xFF0000), pDoc->GetTabBgColor(0)); + + saveAndReload(TestFilter::XLSX); + + // check that the tab color was exported correctly + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPath(pSheet, "/x:worksheet/x:sheetPr/x:tabColor", "rgb", u"FFFF0000"); + + // check that sheet protection and tab color are still present after save and reload + pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc->IsTabProtected(0)); + CPPUNIT_ASSERT_EQUAL(Color(0xFF0000), pDoc->GetTabBgColor(0)); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_filters_test3.cxx b/sc/qa/unit/subsequent_filters_test3.cxx index 0a170659482f..a48c8813f4ea 100644 --- a/sc/qa/unit/subsequent_filters_test3.cxx +++ b/sc/qa/unit/subsequent_filters_test3.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -705,6 +706,52 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testTdf150815_RepaintSparkline) CPPUNIT_ASSERT(aListener.mbCalled); } +CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testEnterDataFlagsArrayReturningFormula) +{ + // Plain Enter on =UNIQUE(B1:B4) makes the cell a dynamic-array master + // and the formula text reads back without {} wrapping. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + ScTabViewShell* pViewShell = getViewShell(); + pViewShell->EnterData(0, 0, 0, u"=UNIQUE(B1:B4)"_ustr, nullptr, /*bAutoDynamicArray*/ true); + + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pCell->GetMatrixFlag()); + CPPUNIT_ASSERT_EQUAL(u"=UNIQUE(B1:B4)"_ustr, pDoc->GetFormula(0, 0, 0)); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testEnterDataKeepsSingleValueAtTop) +{ + // The @ implicit-intersection operator opts a formula out of the + // dynamic-array auto-resize path. The typed =@UNIQUE(...) cell stays a + // plain single-value cell with no dynamic-array flag. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + ScTabViewShell* pViewShell = getViewShell(); + pViewShell->EnterData(0, 0, 0, u"=@UNIQUE(B1:B4)"_ustr, nullptr, /*bAutoDynamicArray*/ true); + + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(!pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::NONE, pCell->GetMatrixFlag()); +} + CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testTdf137091) { // Set the system locale to Turkish @@ -1350,6 +1397,17 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testAutofilterNamedRangesXLSX) CPPUNIT_ASSERT_EQUAL(OUString(), aPosStr); } +CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testTdf113596PrintRangeNameXLSX) +{ + createScDoc("xlsx/built-in_ranges.xlsx"); + ScDocument* pDoc = getScDoc(); + + ScRangeName* pNames = pDoc->GetRangeName(0); + CPPUNIT_ASSERT_MESSAGE("There should be named ranges in the sheet", pNames); + CPPUNIT_ASSERT_MESSAGE("Range name Excel_BuiltIn_Print_Area not found after XLSX import", + pNames->findByUpperName(u"EXCEL_BUILTIN_PRINT_AREA"_ustr)); +} + CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testInvalidBareBiff5) { createScDoc("xls/tdf144732.xls"); @@ -2004,6 +2062,72 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testTdf108188_pagestyle) !pStylePool->Find(ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Page)->IsUsed()); } +CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testTwoCellAnchorEditAsOneCell) +{ + createScDoc("xlsx/twoCellAnchor_editAs_oneCell.xlsx"); + + ScDocument* pDoc = getScDoc(); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + CPPUNIT_ASSERT(pDrawLayer); + const SdrPage* pPage = pDrawLayer->GetPage(0); + CPPUNIT_ASSERT(pPage); + const SdrObject* pObj = pPage->GetObj(0); + CPPUNIT_ASSERT(pObj); + + // xfrm ext: cx=4352924 EMU = 12091 1/100mm, cy=2743198 EMU = 7620 1/100mm + tools::Rectangle aRect = pObj->GetSnapRect(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(12091.0, static_cast(aRect.GetWidth()), 1.0); + CPPUNIT_ASSERT_DOUBLES_EQUAL(7620.0, static_cast(aRect.GetHeight()), 1.0); + + pPage = pDrawLayer->GetPage(1); + CPPUNIT_ASSERT(pPage); + pObj = pPage->GetObj(0); + CPPUNIT_ASSERT(pObj); + + // bounding box must correctly reflect rotation, 120 degrees CCW (240 degrees CW in Excel) + CPPUNIT_ASSERT_EQUAL((12000_deg100).get(), pObj->GetRotateAngle().get()); + aRect = pObj->GetSnapRect(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(11302.0, static_cast(aRect.GetWidth()), 1.0); + CPPUNIT_ASSERT_DOUBLES_EQUAL(12252.0, static_cast(aRect.GetHeight()), 1.0); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testThreadedCommentImport) +{ + createScDoc("xlsx/threadedComment.xlsx"); + ScDocument* pDoc = getScDoc(); + + // The sample has a threaded comment with a reply at A2, and a plain note at A5. + ScPostIt* pNote = pDoc->GetNote(0, 1, 0); + CPPUNIT_ASSERT(pNote); + // The legacy placeholder includes both root text and reply. + CPPUNIT_ASSERT(pNote->GetText().indexOf(u"a comment on A2") >= 0); + // Author should be the display name, not the tc={guid} placeholder. + CPPUNIT_ASSERT_EQUAL(u"Mike Kaganski"_ustr, pNote->GetAuthor()); + + // Threaded comment data should be attached. + const ScThreadedCommentData* pData = pNote->GetThreadedCommentData(); + CPPUNIT_ASSERT(pData); + CPPUNIT_ASSERT_EQUAL(u"{FB8EA27E-C1B6-4481-B034-193455CC7425}"_ustr, pData->maRoot.maGuid); + CPPUNIT_ASSERT_EQUAL(u"a comment on A2"_ustr, pData->maRoot.maText); + CPPUNIT_ASSERT(!pData->mbDone); // not resolved in the sample + + // The sample has one reply. + CPPUNIT_ASSERT_EQUAL(size_t(1), pData->maReplies.size()); + const auto& rReply = pData->maReplies[0]; + CPPUNIT_ASSERT_EQUAL(u"{789BBBE8-38C6-4228-9338-E9C75EB78FCF}"_ustr, rReply.maGuid); + CPPUNIT_ASSERT_EQUAL(u"A reply"_ustr, rReply.maText); + + // Person list should be populated. + const ScPersonData* pPerson = pDoc->GetPersonById(pData->maRoot.maPersonId); + CPPUNIT_ASSERT(pPerson); + CPPUNIT_ASSERT_EQUAL(u"Mike Kaganski"_ustr, pPerson->maDisplayName); + + // A5 has a plain old-style note (not a threaded comment). + ScPostIt* pPlainNote = pDoc->GetNote(0, 4, 0); + CPPUNIT_ASSERT(pPlainNote); + CPPUNIT_ASSERT(!pPlainNote->GetThreadedCommentData()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_filters_test4.cxx b/sc/qa/unit/subsequent_filters_test4.cxx index 59cd46e57466..251ab30e5902 100644 --- a/sc/qa/unit/subsequent_filters_test4.cxx +++ b/sc/qa/unit/subsequent_filters_test4.cxx @@ -460,7 +460,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testRowHeightTdf165003) CPPUNIT_ASSERT_EQUAL(256, nHeight); // this row has 90-degree rotated text, and without the fix, would have had zero height. nHeight = pDoc->GetRowHeight(++nRow, nTab, false); - CPPUNIT_ASSERT_EQUAL(582, nHeight); + CPPUNIT_ASSERT_EQUAL(567, nHeight); nHeight = pDoc->GetRowHeight(++nRow, nTab, false); CPPUNIT_ASSERT_EQUAL(256, nHeight); } @@ -644,10 +644,10 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testRichTextContentODS) && static_cast(*rAttrib.pAttr).GetLineStyle() == LINESTYLE_SINGLE; }); - CPPUNIT_ASSERT_MESSAGE("Second line should be underlined.", bHasUnderline); + CPPUNIT_ASSERT_MESSAGE("Third line should be underlined.", bHasUnderline); // URL with formats applied. For now, we'll check whether or not the - // field objects gets imported. Later we should add checks for the + // field objects get imported. Later we should add checks for the // formats. aPos.IncRow(); pEditText = pDoc->GetEditText(aPos); @@ -673,7 +673,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testRichTextContentODS) aPos.IncRow(); pEditText = pDoc->GetEditText(aPos); CPPUNIT_ASSERT_MESSAGE("Failed to retrieve edit text object.", pEditText); - CPPUNIT_ASSERT_MESSAGE("Date field item not found.", + CPPUNIT_ASSERT_MESSAGE("DocInfo title field item not found.", pEditText->HasField(text::textfield::Type::DOCINFO_TITLE)); // URL for a file in the same directory. It should be converted into an absolute URL on import. @@ -952,7 +952,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testOrcusODSStyleInterface) pStyleSheet->GetItemSet().HasItem(ATTR_FONT_CROSSEDOUT, &pItem)); pCrossedOutItem = static_cast(pItem); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Style Name7 :Error with Strikeout", STRIKEOUT_BOLD, + CPPUNIT_ASSERT_EQUAL_MESSAGE("Style Name8 :Error with Strikeout", STRIKEOUT_BOLD, pCrossedOutItem->GetStrikeout()); /* Test for Style Name "9" @@ -1230,7 +1230,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testSharedFormulaXLS) CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testSharedFormulaXLS2) { - // The following file contains shared formula whose range is inaccurate. + // The following file contains a shared formula whose range is inaccurate. // Excel can easily mess up shared formula ranges, so we need to be able // to handle these wrong ranges that Excel stores. @@ -1483,7 +1483,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testSortWithSharedFormulasODS) // Do the sorting. This should not crash. ScDocShell* pDocSh = getScDocShell(); ScDBDocFunc aFunc(*pDocSh); - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // After the sort, E2:E16 should be shared. @@ -1533,7 +1533,7 @@ void testSortWithSheetExternalReferencesODS_Impl(ScDocShell& rDocSh, SCROW nRow1 // Do the sorting. ScDBDocFunc aFunc(rDocSh); - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); rDoc.CalcAll(); @@ -1653,7 +1653,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testSortWithFormattingXLS) ScDocShell* pDocSh = getScDocShell(); ScDBDocFunc aFunc(*pDocSh); // Without the fix, sort would crash. - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); } diff --git a/sc/qa/unit/subsequent_filters_test5.cxx b/sc/qa/unit/subsequent_filters_test5.cxx index 782b038343d6..94e128b36cd7 100644 --- a/sc/qa/unit/subsequent_filters_test5.cxx +++ b/sc/qa/unit/subsequent_filters_test5.cxx @@ -14,9 +14,17 @@ #include #include #include +#include #include +#include +#include #include +#include #include +#include + +#include +#include #include @@ -98,6 +106,269 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf167134_LOOKUP_extRef) } } +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testLoextSpillImport) +{ + // A table-cell with loext:spill="true" comes back as a dynamic-array + // master and spills its result into the rows below. A cell with the + // same formula but no attribute is a plain single-value cell that + // shows only the upper-left of the result. + + createScDoc("fods/DynamicArraySpill.fods"); + + ScDocument* pDoc = getScDoc(); + + ScFormulaCell* pMarked = pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pMarked); + CPPUNIT_ASSERT(pMarked->IsDynamicArrayMaster()); + + // The master at A1 spills UNIQUE(B1:B4) into A1:A4. + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, pDoc->GetValue(ScAddress(0, 3, 0))); + + ScFormulaCell* pPlain = pDoc->GetFormulaCell(ScAddress(0, 4, 0)); + CPPUNIT_ASSERT(pPlain); + CPPUNIT_ASSERT(!pPlain->IsDynamicArrayMaster()); + + // The plain cell at A5 shows only the first value with no spill below. + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(0, 4, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, pDoc->GetCellType(ScAddress(0, 5, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testLoextSpillExportFODS) +{ + // Saving as FODS writes loext:spill="true" on the marked formula + // cell and leaves it off on the plain one. + + createScDoc("fods/DynamicArraySpill.fods"); + + save(TestFilter::FODS); + + xmlDocUniquePtr pXmlDoc = parseExportedFile(); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "//table:table/table:table-row[1]/table:table-cell[1]", "spill", u"true"); + assertXPath(pXmlDoc, "//table:table/table:table-row[1]/table:table-cell[1]", "formula", + u"of:=COM.MICROSOFT.UNIQUE([.B1:.B4])"); + + assertXPathNoAttribute(pXmlDoc, "//table:table/table:table-row[5]/table:table-cell[1]", + "spill"); + assertXPath(pXmlDoc, "//table:table/table:table-row[5]/table:table-cell[1]", "formula", + u"of:=COM.MICROSOFT.UNIQUE([.B1:.B4])"); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testPlainImplicitIntersectionResolved) +{ + // A plain non-array formula whose RPN intends to produce an + // array picks up @ in the formula text as soon as the cell is + // asked to resolve it. ODS import drives this on every plain + // non-array, non-loext:spill cell at the end of formula + // compilation. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + pDoc->SetValue(ScAddress(0, 0, 0), 1.0); + pDoc->SetValue(ScAddress(0, 1, 0), 2.0); + pDoc->SetValue(ScAddress(0, 2, 0), 3.0); + + pDoc->SetFormula(ScAddress(1, 0, 0), u"=A1:A3"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(1, 0, 0)); + CPPUNIT_ASSERT(pCell); + pCell->ResolveImplicitIntersection(); + + // The call resolves the decision in-place. No recalc needed. + CPPUNIT_ASSERT_EQUAL(u"=@A1:A3"_ustr, pDoc->GetFormula(1, 0, 0)); + pDoc->CalcAll(); + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(ScAddress(1, 0, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testPlainScalarStaysWithoutImplicitIntersection) +{ + // A plain formula whose RPN does not intend an array (a pure + // scalar like =SUM(A1:A3)) keeps its text unchanged when the + // cell is asked to resolve implicit intersection. The walk + // finds no array intent and leaves the formula alone. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + pDoc->SetValue(ScAddress(0, 0, 0), 1.0); + pDoc->SetValue(ScAddress(0, 1, 0), 2.0); + pDoc->SetValue(ScAddress(0, 2, 0), 3.0); + + pDoc->SetFormula(ScAddress(1, 0, 0), u"=SUM(A1:A3)"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(1, 0, 0)); + CPPUNIT_ASSERT(pCell); + pCell->ResolveImplicitIntersection(); + pDoc->CalcAll(); + + CPPUNIT_ASSERT_EQUAL(u"=SUM(A1:A3)"_ustr, pDoc->GetFormula(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL(6.0, pDoc->GetValue(ScAddress(1, 0, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testSpillOperatorXlsxRoundTrip) +{ + // The # spilled-range operator survives an XLSX round-trip: a + // loaded formula reads as # on its own and inside other + // functions, and still does after a save and reload. + createScDoc("xlsx/SimpleSpillOperatorFixture.xlsx"); + + auto checkSpillFormulas = [this]() { + ScDocument* pDocument = getScDoc(); + CPPUNIT_ASSERT_EQUAL(u"=B2#"_ustr, pDocument->GetFormula(2, 1, 0)); + CPPUNIT_ASSERT_EQUAL(u"=UNIQUE(B2#)"_ustr, pDocument->GetFormula(3, 1, 0)); + CPPUNIT_ASSERT_EQUAL(u"=SUM(B2#)"_ustr, pDocument->GetFormula(4, 1, 0)); + }; + + checkSpillFormulas(); + saveAndReload(TestFilter::XLSX); + checkSpillFormulas(); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testSpillOperatorOdsRoundTrip) +{ + // The # spilled-range operator survives an ODS round-trip too, on + // its own and inside other functions. + createScDoc("xlsx/SimpleSpillOperatorFixture.xlsx"); + + auto checkSpillFormulas = [this]() { + ScDocument* pDocument = getScDoc(); + CPPUNIT_ASSERT_EQUAL(u"=B2#"_ustr, pDocument->GetFormula(2, 1, 0)); + CPPUNIT_ASSERT_EQUAL(u"=UNIQUE(B2#)"_ustr, pDocument->GetFormula(3, 1, 0)); + CPPUNIT_ASSERT_EQUAL(u"=SUM(B2#)"_ustr, pDocument->GetFormula(4, 1, 0)); + }; + + checkSpillFormulas(); + saveAndReload(TestFilter::ODS); + checkSpillFormulas(); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testDynamicSpillStateExportFODS) +{ + // A dynamic-array master in spill state collapses to 1x1. FODS + // export writes it as a plain non-array formula (no matrix dims) + // carrying loext:spill="true" so a round trip can re-instate the + // master and re-check the blockers. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + // Source data and a blocker that will trigger #SPILL!. + pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + pDoc->SetString(ScAddress(0, 1, 0), u"blocker"_ustr); + + ScMarkData aMark(pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, u"=UNIQUE(B1:B4)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, true /*bDynamicArrayMaster*/); + + ScFormulaCell* pMaster = pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pMaster); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pMaster->GetErrCode())); + + save(TestFilter::FODS); + xmlDocUniquePtr pXmlDoc = parseExportedFile(); + CPPUNIT_ASSERT(pXmlDoc); + + assertXPath(pXmlDoc, "//table:table/table:table-row[1]/table:table-cell[1]", "spill", u"true"); + assertXPathNoAttribute(pXmlDoc, "//table:table/table:table-row[1]/table:table-cell[1]", + "number-matrix-columns-spanned"); + assertXPathNoAttribute(pXmlDoc, "//table:table/table:table-row[1]/table:table-cell[1]", + "number-matrix-rows-spanned"); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testLoextSpillRoundTripODS) +{ + // The dynamic-array marker and the spilled values survive an ODS + // save and reload when the file is written in the extended ODF + // flavour. + + createScDoc("fods/DynamicArraySpill.fods"); + + saveAndReload(TestFilter::ODS); + + ScDocument* pDoc = getScDoc(); + + ScFormulaCell* pMarked = pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pMarked); + CPPUNIT_ASSERT(pMarked->IsDynamicArrayMaster()); + + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, pDoc->GetValue(ScAddress(0, 3, 0))); + + ScFormulaCell* pPlain = pDoc->GetFormulaCell(ScAddress(0, 4, 0)); + CPPUNIT_ASSERT(pPlain); + CPPUNIT_ASSERT(!pPlain->IsDynamicArrayMaster()); + + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(0, 4, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, pDoc->GetCellType(ScAddress(0, 5, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testArrayFormulasStaticRoundTrip) +{ + // Static array formulas in a legacy ODS file round-trip with + // every value-check still TRUE. + + auto checkSheet = [](ScDocument* pDoc) { + // B1 = AND(C4:C52) summarises 49 per-row equality checks. + CPPUNIT_ASSERT_EQUAL(u"TRUE"_ustr, pDoc->GetString(ScAddress(1, 0, 0))); + for (SCROW nRow = 3; nRow <= 51; ++nRow) + { + OString aMessage = "C" + OString::number(nRow + 1) + " must be TRUE"; + CPPUNIT_ASSERT_EQUAL_MESSAGE(aMessage.getStr(), u"TRUE"_ustr, + pDoc->GetString(ScAddress(2, nRow, 0))); + } + + // Plain non-array cells with a bare range carry an explicit @. + CPPUNIT_ASSERT_EQUAL(u"=@H10:H13"_ustr, pDoc->GetFormula(5, 8, 0)); // F9 + CPPUNIT_ASSERT_EQUAL(u"=@H10:H13"_ustr, pDoc->GetFormula(5, 9, 0)); // F10 + CPPUNIT_ASSERT_EQUAL(u"=@H10:H13"_ustr, pDoc->GetFormula(9, 12, 0)); // J13 + + // The five matrix masters stay static (no loext:spill in the + // source file), so GetFormula keeps the {} wrapping. + struct Master + { + ScAddress maPosition; + OUString maFormula; + }; + const Master aMasters[] = { + { ScAddress(11, 15, 0), u"{=H10:H13}"_ustr }, // L16 + { ScAddress(12, 15, 0), u"{=H10:H13}"_ustr }, // M16 + { ScAddress(13, 15, 0), u"{=TRANSPOSE(TRANSPOSE(H10:H13))}"_ustr }, // N16 + { ScAddress(11, 22, 0), u"{=SORT(H10:H13)}"_ustr }, // L23 + { ScAddress(12, 22, 0), u"{=UNIQUE(H10:H13)}"_ustr }, // M23 + }; + for (const Master& rMaster : aMasters) + { + ScFormulaCell* pCell = pDoc->GetFormulaCell(rMaster.maPosition); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(!pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(rMaster.maFormula, pDoc->GetFormula(rMaster.maPosition.Col(), + rMaster.maPosition.Row(), 0)); + } + }; + + createScDoc("ods/ArrayFormulasStatic.ods"); + checkSheet(getScDoc()); + + saveAndReload(TestFilter::ODS); + checkSheet(getScDoc()); + + // No @ in any saved formula, and the matrix masters do not get + // loext:spill="true" because they stayed static. + xmlDocUniquePtr pXml = parseExport(u"content.xml"_ustr); + CPPUNIT_ASSERT(pXml); + assertXPath(pXml, "//table:table-cell[contains(@table:formula, '@')]", 0); + assertXPath(pXml, "//table:table-cell[@loext:spill='true']", 0); +} + CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf122336) { createScDoc("xlsx/tdf122336.xlsx"); @@ -128,8 +399,8 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf94627) ScDocument* pDoc = getScDoc(); - ScRangeName* pRangeName = pDoc->GetRangeName(); - ScRangeData* pRangeData = pRangeName->findByUpperName("NAME1"); + ScRangeName& rRangeName = pDoc->GetRangeName(); + ScRangeData* pRangeData = rRangeName.findByUpperName("NAME1"); CPPUNIT_ASSERT(pRangeData); OUString aFormula = pRangeData->GetSymbol(); @@ -230,7 +501,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf161948_NaturalSortSaveLoad) // parameters. ScDocShell* pDocSh = getScDocShell(); ScDBDocFunc aFunc(*pDocSh); - bool bSorted = aFunc.Sort(0, aSortParam, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortParam, true, true, true); CPPUNIT_ASSERT(bSorted); // Verify items are naturally sorted @@ -254,7 +525,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf161948_NaturalSortSaveLoad) aSortParam.eSortNumberBehavior = ScSortNumberBehavior::ALPHA_NUMERIC; pDocSh = getScDocShell(); ScDBDocFunc aFunc2(*pDocSh); - bSorted = aFunc2.Sort(0, aSortParam, true, true, true); + bSorted = aFunc2.SortTab(0, aSortParam, true, true, true); CPPUNIT_ASSERT(bSorted); // Verify items are alpha-numerically sorted @@ -285,6 +556,151 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf168589) ASSERT_DOUBLES_EQUAL(6.0, pDoc->GetValue(4, 5, 0)); } +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf171828_fail_to_import_file) +{ + // Open xlsx document, failing without the fix + createScDoc("xlsx/tdf171828_fail_to_import_file.xlsx"); + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc); + CPPUNIT_ASSERT_EQUAL(u"950"_ustr, pDoc->GetString(6, 6, 0).trim()); +} + +namespace +{ +ScDBData* findDBData(ScDocument* pDoc, const OUString& rName) +{ + ScDBCollection* pColl = pDoc->GetDBCollection(); + if (!pColl) + return nullptr; + return pColl->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rName)); +} + +void dispatchDatabaseSettings(ScTabViewShell* pViewShell, const ScDBData* pDBData, bool bTotalRow) +{ + const ScTableStyleParam* pStyleInfo = pDBData->GetTableStyleInfo(); + CPPUNIT_ASSERT(pStyleInfo); + + SfxDispatcher* pDispatcher = pViewShell->GetViewFrame().GetBindings().GetDispatcher(); + CPPUNIT_ASSERT(pDispatcher); + + ScDatabaseSettingItem aItem(pDBData->HasHeader(), bTotalRow, pStyleInfo->mbFirstColumn, + pStyleInfo->mbLastColumn, pStyleInfo->mbRowStripes, + pStyleInfo->mbColumnStripes, pDBData->HasAutoFilter(), + pStyleInfo->maStyleID); + pDispatcher->ExecuteList(SID_DATABASE_SETTINGS, SfxCallMode::SYNCHRON, { &aItem }); +} +} // anonymous namespace + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTotalRowToggle) +{ + // Load test file: Table2 with A1:C10, TableStyleMedium2, totalsRowCount=1 + // Headers: A, B, C (row 1) + // Data rows 2-9 + // Total row 10: "Total" in A10, SUBTOTAL(101,Table2[C]) in C10 + createScDoc("xlsx/TableStyleTest.xlsx"); + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT(pDoc); + + ScTabViewShell* pViewShell = getViewShell(); + CPPUNIT_ASSERT(pViewShell); + + // Move cursor into the table area + goToCell(u"A2"_ustr); + + // --- Verify initial state: total row exists --- + CPPUNIT_ASSERT_EQUAL(u"Total"_ustr, pDoc->GetString(ScAddress(0, 9, 0))); + // B10 should have custom COUNTIF formula result = 3 + CPPUNIT_ASSERT_EQUAL(3.0, pDoc->GetValue(ScAddress(1, 9, 0))); + // C10 should have SUBTOTAL formula result (average of C2:C9) with number format + double fAvgValue = pDoc->GetValue(ScAddress(2, 9, 0)); + CPPUNIT_ASSERT(fAvgValue != 0.0); + // Verify the number format (Hungarian Forint "Ft") is preserved after import + OUString aFormattedValue = pDoc->GetString(ScAddress(2, 9, 0)); + CPPUNIT_ASSERT_EQUAL(u" 2.75 Ft "_ustr, aFormattedValue); + + ScDBData* pDBData = findDBData(pDoc, u"Table2"_ustr); + CPPUNIT_ASSERT(pDBData); + CPPUNIT_ASSERT(pDBData->HasTotals()); + + // --- Toggle total row OFF --- + dispatchDatabaseSettings(pViewShell, pDBData, false); + + // Refresh DB data pointer (may have been replaced) + pDBData = findDBData(pDoc, u"Table2"_ustr); + CPPUNIT_ASSERT(pDBData); + CPPUNIT_ASSERT(!pDBData->HasTotals()); + + // Last data row should still have data + CPPUNIT_ASSERT(pDoc->GetValue(ScAddress(0, 8, 0)) != 0.0); + + // --- Toggle total row ON --- + dispatchDatabaseSettings(pViewShell, pDBData, true); + + pDBData = findDBData(pDoc, u"Table2"_ustr); + CPPUNIT_ASSERT(pDBData); + CPPUNIT_ASSERT(pDBData->HasTotals()); + + // Total row should be restored + CPPUNIT_ASSERT_EQUAL(u"Total"_ustr, pDoc->GetString(ScAddress(0, 9, 0))); + // B10 custom COUNTIF formula should be restored + CPPUNIT_ASSERT_EQUAL(3.0, pDoc->GetValue(ScAddress(1, 9, 0))); + // SUBTOTAL formula in C10 should also be restored with same value + double fRestoredValue = pDoc->GetValue(ScAddress(2, 9, 0)); + CPPUNIT_ASSERT_DOUBLES_EQUAL(fAvgValue, fRestoredValue, 0.0); + // TODO: number format (e.g. "Ft" currency) on total row cells is lost + // after toggle off/on cycle — this is a known limitation to fix later. + // CPPUNIT_ASSERT_EQUAL(u" 2.75 Ft "_ustr, pDoc->GetString(ScAddress(2, 9, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTotalRowUndoRedo) +{ + createScDoc("xlsx/TableStyleTest.xlsx"); + ScDocument* pDoc = getScDoc(); + ScTabViewShell* pViewShell = getViewShell(); + + goToCell(u"A2"_ustr); + + // Initial: total row exists + CPPUNIT_ASSERT_EQUAL(u"Total"_ustr, pDoc->GetString(ScAddress(0, 9, 0))); + double fOrigValue = pDoc->GetValue(ScAddress(2, 9, 0)); + + ScDBData* pDBData = findDBData(pDoc, u"Table2"_ustr); + CPPUNIT_ASSERT(pDBData); + + // Toggle total row OFF + dispatchDatabaseSettings(pViewShell, pDBData, false); + + pDBData = findDBData(pDoc, u"Table2"_ustr); + CPPUNIT_ASSERT(pDBData); + CPPUNIT_ASSERT(!pDBData->HasTotals()); + + // --- Undo: should restore total row --- + pDoc->GetUndoManager()->Undo(); + + pDBData = findDBData(pDoc, u"Table2"_ustr); + CPPUNIT_ASSERT(pDBData); + CPPUNIT_ASSERT(pDBData->HasTotals()); + CPPUNIT_ASSERT_EQUAL(u"Total"_ustr, pDoc->GetString(ScAddress(0, 9, 0))); + CPPUNIT_ASSERT_DOUBLES_EQUAL(fOrigValue, pDoc->GetValue(ScAddress(2, 9, 0)), 0.0); + + // --- Redo: should remove total row again --- + pDoc->GetUndoManager()->Redo(); + + pDBData = findDBData(pDoc, u"Table2"_ustr); + CPPUNIT_ASSERT(pDBData); + CPPUNIT_ASSERT(!pDBData->HasTotals()); +} + +CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testFullColumnRefs) +{ + createScDoc("xlsx/forum-mso-en4-134670.xlsx"); + ScDocument* pDoc = getScDoc(); + + CPPUNIT_ASSERT_EQUAL(u"Total # Of Companies"_ustr, pDoc->GetString(ScAddress(0, 0, 0))); + // For cell K2 the cached value is 1 + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(ScAddress(10, 1, 0))); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/tiledrendering/SheetViewTest.cxx b/sc/qa/unit/tiledrendering/SheetViewTest.cxx index 3f80cf13bba7..d6fb307de829 100644 --- a/sc/qa/unit/tiledrendering/SheetViewTest.cxx +++ b/sc/qa/unit/tiledrendering/SheetViewTest.cxx @@ -9,36 +9,396 @@ #include +#include #include #include +#include #include #include #include #include +#include +#include #include +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include using namespace css; class SheetViewTest : public ScTiledRenderingTest { protected: - static bool checkValues(ScTabViewShell* pTabView, SCCOL nCol, SCROW nStartRow, SCROW nEndRow, - std::vector const& rValues) + static ScRange getAutoFilterArea(ScDocument& rDocument, SCTAB nTab) { + ScDBData* pDBData = rDocument.GetAnonymousDBData(nTab); + CPPUNIT_ASSERT(pDBData); + CPPUNIT_ASSERT(pDBData->HasAutoFilter()); + ScRange aRange; + pDBData->GetArea(aRange); + return aRange; + } + + static OUString expectedValues(std::vector const& rValues) + { + OUString aString; + bool bFirst = true; + for (auto const& rValue : rValues) + { + if (bFirst) + { + bFirst = false; + aString = u"\""_ustr + rValue + u"\""_ustr; + } + else + aString += u", \""_ustr + rValue + u"\""_ustr; + } + return aString; + } + + static OUString getValues(ScTabViewShell* pTabView, SCCOL nCol, SCROW nStartRow, SCROW nEndRow) + { + OUString aString; + size_t nSize = nEndRow - nStartRow + 1; - if (nSize != rValues.size()) - return false; + + bool bFirst = true; for (size_t nIndex = 0; nIndex < nSize; nIndex++) { - OUString value = pTabView->GetCurrentString(nCol, nStartRow + nIndex); - if (value != rValues[nIndex]) - return false; + OUString aValue = pTabView->GetCurrentString(nCol, nStartRow + nIndex); + if (bFirst) + { + bFirst = false; + aString = u"\""_ustr + aValue + u"\""_ustr; + } + else + aString += u", \""_ustr + aValue + u"\""_ustr; } - return true; + return aString; + } + + static OUString getValues(ScDocument* pDocument, SCCOL nCol, SCROW nStartRow, SCROW nEndRow, + SCTAB nTab) + { + OUString aString; + + size_t nSize = nEndRow - nStartRow + 1; + + bool bFirst = true; + + for (size_t nIndex = 0; nIndex < nSize; nIndex++) + { + OUString aValue = pDocument->GetString({ nCol, SCROW(nStartRow + nIndex), nTab }); + if (bFirst) + { + bFirst = false; + aString = u"\""_ustr + aValue + u"\""_ustr; + } + else + aString += u", \""_ustr + aValue + u"\""_ustr; + } + + return aString; + } + + static OUString getTextWeight(ScDocument* pDocument, SCCOL nCol, SCROW nStartRow, SCROW nEndRow, + SCTAB nTab) + { + OUString aString; + + size_t nSize = nEndRow - nStartRow + 1; + + bool bFirst = true; + vcl::Font aFont; + const ScPatternAttr* pPattern; + for (size_t nIndex = 0; nIndex < nSize; nIndex++) + { + pPattern = pDocument->GetPattern(nCol, SCROW(nStartRow + nIndex), nTab); + pPattern->fillFontOnly(aFont); + OUString aWeight; + + switch (aFont.GetWeight()) + { + case WEIGHT_NORMAL: + aWeight = "N"; + break; + case WEIGHT_BOLD: + aWeight = "B"; + break; + default: + aWeight = "?"; + break; + } + + if (bFirst) + { + bFirst = false; + aString = u"\""_ustr + aWeight + u"\""_ustr; + } + else + aString += u", \""_ustr + aWeight + u"\""_ustr; + } + + return aString; + } + + static OUString getBackgroundColor(ScDocument* pDocument, SCCOL nCol, SCROW nStartRow, + SCROW nEndRow, SCTAB nTab) + { + OUString aString; + bool bFirst = true; + for (SCROW nRow = nStartRow; nRow <= nEndRow; nRow++) + { + const ScPatternAttr* pPattern = pDocument->GetPattern(nCol, nRow, nTab); + const SvxBrushItem& rBrush = pPattern->GetItem(ATTR_BACKGROUND); + OUString aColor = rBrush.GetColor().AsRGBHexString(); + if (bFirst) + { + bFirst = false; + aString = u"\""_ustr + aColor + u"\""_ustr; + } + else + aString += u", \""_ustr + aColor + u"\""_ustr; + } + return aString; + } + + // Writes to string the indent state for a row range, Y = indented, N = not indented + static OUString getIndent(ScDocument* pDocument, SCCOL nCol, SCROW nStartRow, SCROW nEndRow, + SCTAB nTab) + { + OUString aString; + bool bFirst = true; + for (SCROW nRow = nStartRow; nRow <= nEndRow; nRow++) + { + const ScPatternAttr* pPattern = pDocument->GetPattern(nCol, nRow, nTab); + const ScIndentItem& rIndent = pPattern->GetItem(ATTR_INDENT); + OUString aValue = rIndent.GetValue() > 0 ? u"Y"_ustr : u"N"_ustr; + if (bFirst) + { + bFirst = false; + aString = u"\""_ustr + aValue + u"\""_ustr; + } + else + aString += u", \""_ustr + aValue + u"\""_ustr; + } + return aString; + } + + void gotoCell(std::u16string_view aCellAddress) + { + dispatchCommand( + mxComponent, u".uno:GoToCell"_ustr, + comphelper::InitPropertySequence({ { "ToPoint", uno::Any(OUString(aCellAddress)) } })); + } + + void createNewSheetViewInCurrentView() + { + dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + } + + void insertSheet(OUString const& rName, sal_Int16 nIndex) + { + dispatchCommand(mxComponent, u".uno:Insert"_ustr, + comphelper::InitPropertySequence( + { { "Name", uno::Any(rName) }, { "Index", uno::Any(nIndex) } })); + } + + void removeSheetViewInCurrentView() + { + dispatchCommand(mxComponent, u".uno:RemoveSheetView"_ustr, {}); + } + + void sortAscendingForCell(std::u16string_view aCellAddress) + { + gotoCell(aCellAddress); + dispatchCommand(mxComponent, u".uno:SortAscending"_ustr, {}); + } + + void sortDescendingForCell(std::u16string_view aCellAddress) + { + gotoCell(aCellAddress); + dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); + } + + void setCellBold(std::u16string_view aCellAddress) + { + gotoCell(aCellAddress); + dispatchCommand(mxComponent, u".uno:Bold"_ustr, {}); + } + + void undo() { dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); } + + void redo() { dispatchCommand(mxComponent, u".uno:Redo"_ustr, {}); } +}; + +/** Test class that contains methods commonly used for testing sync of sheet views. */ +class SyncTest : public SheetViewTest +{ +public: + void tearDown() override + { + moSheetView = std::nullopt; + moDefaultView = std::nullopt; + SheetViewTest::tearDown(); + } + +protected: + std::optional moSheetView; + std::optional moDefaultView; + ScTabViewShell* mpTabViewSheetView = nullptr; + ScTabViewShell* mpTabViewDefaultView = nullptr; + + void setupViews() + { + moSheetView.emplace(); + mpTabViewSheetView = moSheetView->getTabViewShell(); + + SfxLokHelper::createView(); + Scheduler::ProcessEventsToIdle(); + + moDefaultView.emplace(); + mpTabViewDefaultView = moDefaultView->getTabViewShell(); + + CPPUNIT_ASSERT(mpTabViewSheetView != mpTabViewDefaultView); + CPPUNIT_ASSERT(moSheetView->getViewID() != moDefaultView->getViewID()); + } + + void switchToSheetView() + { + SfxLokHelper::setView(moSheetView->getViewID()); + Scheduler::ProcessEventsToIdle(); + } + + void switchToDefaultView() + { + SfxLokHelper::setView(moDefaultView->getViewID()); + Scheduler::ProcessEventsToIdle(); + } + + ScDrawView* getDrawView() + { + ScTabViewShell* pTabViewShell = ScTabViewShell::GetActiveViewShell(); + CPPUNIT_ASSERT(pTabViewShell); + ScDrawView* pDrawView = pTabViewShell->GetScDrawView(); + CPPUNIT_ASSERT(pDrawView); + return pDrawView; + } + + /** Find first pivot table on the input tab. */ + static ScDPObject* findPivotTableOnTab(ScDocument& rDocument, SCTAB nTab) + { + ScDPCollection* pDPCollection = rDocument.GetDPCollection(); + for (size_t i = 0; i < pDPCollection->GetCount(); ++i) + { + ScDPObject& rDPObject = (*pDPCollection)[i]; + if (rDPObject.GetOutRange().aStart.Tab() == nTab) + return &rDPObject; + } + return nullptr; + } + + static size_t countPivotTablesOnTab(ScDocument& rDocument, SCTAB nTab) + { + size_t nCount = 0; + ScDPCollection* pDPCollection = rDocument.GetDPCollection(); + for (size_t i = 0; i < pDPCollection->GetCount(); ++i) + { + if ((*pDPCollection)[i].GetOutRange().aStart.Tab() == nTab) + ++nCount; + } + return nCount; + } + + static void setupPivotTableSourceData(ScDocument& rDocument) + { + rDocument.SetString(ScAddress(0, 0, 0), u"Category"_ustr); + rDocument.SetString(ScAddress(1, 0, 0), u"Value"_ustr); + rDocument.SetString(ScAddress(0, 1, 0), u"A"_ustr); + rDocument.SetString(ScAddress(0, 2, 0), u"A"_ustr); + rDocument.SetString(ScAddress(0, 3, 0), u"B"_ustr); + rDocument.SetValue(ScAddress(1, 1, 0), 10.0); + rDocument.SetValue(ScAddress(1, 2, 0), 20.0); + rDocument.SetValue(ScAddress(1, 3, 0), 30.0); + } + + static ScDPObject + createCategoryValueDPObject(ScDocument& rDocument, SCTAB nTab, ScRange aOutRange, + css::sheet::DataPilotFieldOrientation eCategoryOrientation) + { + ScDPObject aDPObject(&rDocument); + ScSheetSourceDesc aSheetDesc(&rDocument); + aSheetDesc.SetSourceRange(ScRange(0, 0, nTab, 1, 3, nTab)); + aDPObject.SetSheetDesc(aSheetDesc); + aDPObject.SetOutRange(aOutRange); + + ScDPSaveData aSaveData; + ScDPSaveDimension* pDim = aSaveData.GetNewDimensionByName(u"Category"_ustr); + pDim->SetOrientation(eCategoryOrientation); + pDim = aSaveData.GetNewDimensionByName(u"Value"_ustr); + pDim->SetOrientation(css::sheet::DataPilotFieldOrientation_DATA); + pDim->SetFunction(ScGeneralFunction::SUM); + aDPObject.SetSaveData(aSaveData); + + return aDPObject; + } + + void insertDrawObject(ScDrawLayer* pDrawLayer, const tools::Rectangle& rRectangle) + { + ScDrawView* pDrawView = getDrawView(); + rtl::Reference pObject = new SdrRectObj(*pDrawLayer, rRectangle); + pDrawView->InsertObjectSafe(pObject.get(), *pDrawView->GetSdrPageView()); + } + + void moveDrawObject(SdrObject* pObject, const tools::Rectangle& rNewPosition) + { + tools::Rectangle aOldPosition = pObject->GetLogicRect(); + Size aOffset(rNewPosition.Left() - aOldPosition.Left(), + rNewPosition.Top() - aOldPosition.Top()); + ScDrawView* pDrawView = getDrawView(); + pDrawView->UnmarkAllObj(); + pDrawView->MarkObj(pObject, pDrawView->GetSdrPageView()); + pDrawView->MoveMarkedObj(aOffset); + } + + void deleteDrawObject(SdrObject* pObject) + { + ScDrawView* pDrawView = getDrawView(); + pDrawView->UnmarkAllObj(); + pDrawView->MarkObj(pObject, pDrawView->GetSdrPageView()); + pDrawView->DeleteMarkedObj(); } }; @@ -71,38 +431,37 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSheetViewAutoFilter) Scheduler::ProcessEventsToIdle(); // Check AutoFilter values - CPPUNIT_ASSERT(checkValues(pTabView1, 0, 1, 4, { u"4", u"5", u"3", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), getValues(pTabView1, 0, 1, 4)); // Switch to view 2 SfxLokHelper::setView(aView2.getViewID()); Scheduler::ProcessEventsToIdle(); // Check auto-filter values - CPPUNIT_ASSERT(checkValues(pTabView2, 0, 1, 4, { u"4", u"5", u"3", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), getValues(pTabView2, 0, 1, 4)); // Check what sheet we currently have selected for view 1 & 2 CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView2->GetViewData().GetTabNumber()); // Create a new sheet view for view 2 - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); - Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); // Check what sheet we currently have selected for view 1 & 2 CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); - CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView2->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabView2->GetViewData().GetTabNumber()); // Sort AutoFilter descending - dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); + sortDescendingForCell(u"A1"); CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); - CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView2->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabView2->GetViewData().GetTabNumber()); // Check view 2 - sorted - CPPUNIT_ASSERT(checkValues(pTabView2, 0, 1, 4, { u"7", u"5", u"4", u"3" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), getValues(pTabView2, 0, 1, 4)); // Check view 1 - unsorted - CPPUNIT_ASSERT(checkValues(pTabView1, 0, 1, 4, { u"4", u"5", u"3", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), getValues(pTabView1, 0, 1, 4)); } CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncValuesBetweenMainSheetAndSheetView) @@ -147,9 +506,9 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncValuesBetweenMainSheetAndSheetView) // Create a sheet view in View2 SfxLokHelper::setView(aView2.getViewID()); Scheduler::ProcessEventsToIdle(); - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + createNewSheetViewInCurrentView(); - // Change content in View1 with default view -> default view ro sheet view sync + // Change content in View1 with default view -> default view to sheet view sync SfxLokHelper::setView(aView1.getViewID()); typeCharsInCell(std::string("XYZ"), aA1.Col(), aA1.Row(), pTabView1, pModelObj); typeCharsInCell(std::string("=UPPER(\"x\"&\"Y\"&\"z\""), aA2.Col(), aA2.Row(), pTabView1, @@ -214,28 +573,26 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetView) Scheduler::ProcessEventsToIdle(); // Create a new sheet view for view 1 - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); - Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); // Check AutoFilter values for each view - CPPUNIT_ASSERT(checkValues(pTabView1, 0, 1, 4, { u"4", u"5", u"3", u"7" })); - CPPUNIT_ASSERT(checkValues(pTabView2, 0, 1, 4, { u"4", u"5", u"3", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), getValues(pTabView1, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), getValues(pTabView2, 0, 1, 4)); // Switch to View2 SfxLokHelper::setView(aView2.getViewID()); Scheduler::ProcessEventsToIdle(); // Sort AutoFilter descending - dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); - Scheduler::ProcessEventsToIdle(); + sortDescendingForCell(u"A1"); // Check values are sorted for view 2 - CPPUNIT_ASSERT(checkValues(pTabView1, 0, 1, 4, { u"4", u"5", u"3", u"7" })); - CPPUNIT_ASSERT(checkValues(pTabView2, 0, 1, 4, { u"7", u"5", u"4", u"3" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), getValues(pTabView1, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), getValues(pTabView2, 0, 1, 4)); // Sheet view must be present auto pSheetViewManager = pDocument->GetSheetViewManager(0); - CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewManager->size()); // There should be 2 tables CPPUNIT_ASSERT_EQUAL(SCTAB(2), pDocument->GetTableCount()); @@ -245,12 +602,11 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetView) Scheduler::ProcessEventsToIdle(); // We remove the current sheet view - dispatchCommand(mxComponent, u".uno:RemoveSheetView"_ustr, {}); + removeSheetViewInCurrentView(); Scheduler::ProcessEventsToIdle(); - // Sheet view is retained, but null - CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewManager->getSheetViews().size()); - CPPUNIT_ASSERT(!pSheetViewManager->getSheetViews().at(0)); + // Sheet view was removed + CPPUNIT_ASSERT_EQUAL(size_t(0), pSheetViewManager->size()); // Only 1 table left CPPUNIT_ASSERT_EQUAL(SCTAB(1), pDocument->GetTableCount()); @@ -283,14 +639,12 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSheetViewOperationRestrictions_DefaultVi // Create a new sheet view for view 1 SfxLokHelper::setView(aView1.getViewID()); Scheduler::ProcessEventsToIdle(); - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); - Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); // Create a new sheet view for view 3 SfxLokHelper::setView(aView3.getViewID()); Scheduler::ProcessEventsToIdle(); - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); - Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); // Check AutoFilter values for each view CPPUNIT_ASSERT_EQUAL(u"4"_ustr, pTabView1->GetCurrentString(0, 1)); @@ -314,19 +668,10 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSheetViewOperationRestrictions_DefaultVi // Sheet view must be present auto pSheetViewManager = pDocument->GetSheetViewManager(SCTAB(0)); - CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewManager->size()); - auto pSheetView1 = pSheetViewManager->get(0); - CPPUNIT_ASSERT_EQUAL(true, pSheetView1->isSynced()); - auto pSheetView2 = pSheetViewManager->get(1); - CPPUNIT_ASSERT_EQUAL(true, pSheetView2->isSynced()); - - // Sort, which will unsync sheet views - pTabView2->SetCursor(0, 0); - dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); - - CPPUNIT_ASSERT_EQUAL(false, pSheetView1->isSynced()); - CPPUNIT_ASSERT_EQUAL(false, pSheetView2->isSynced()); + // Sort on default view + sortDescendingForCell(u"A1"); } CPPUNIT_TEST_FIXTURE(SheetViewTest, testSheetViewOperationRestrictions_SheetViewChanged) @@ -356,14 +701,12 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSheetViewOperationRestrictions_SheetView // Create a new sheet view for view 1 SfxLokHelper::setView(aView1.getViewID()); Scheduler::ProcessEventsToIdle(); - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); - Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); // Create a new sheet view for view 3 SfxLokHelper::setView(aView3.getViewID()); Scheduler::ProcessEventsToIdle(); - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); - Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); // Check AutoFilter values for each view CPPUNIT_ASSERT_EQUAL(u"4"_ustr, pTabView1->GetCurrentString(0, 1)); @@ -383,95 +726,12 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSheetViewOperationRestrictions_SheetView // Sheet view must be present auto pSheetViewManager = pDocument->GetSheetViewManager(SCTAB(0)); - CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewManager->size()); - auto pSheetView1 = pSheetViewManager->get(0); - CPPUNIT_ASSERT_EQUAL(true, pSheetView1->isSynced()); - - auto pSheetView2 = pSheetViewManager->get(1); - CPPUNIT_ASSERT_EQUAL(true, pSheetView2->isSynced()); - - // Sort, which will unsync sheet views + // Sort on sheet view 1 SfxLokHelper::setView(aView1.getViewID()); Scheduler::ProcessEventsToIdle(); - pTabView1->SetCursor(0, 0); - dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); - Scheduler::ProcessEventsToIdle(); - - CPPUNIT_ASSERT_EQUAL(false, pSheetView1->isSynced()); - CPPUNIT_ASSERT_EQUAL(true, pSheetView2->isSynced()); -} - -CPPUNIT_TEST_FIXTURE(SheetViewTest, testSheetViewManager) -{ - sc::SheetViewID nNonExistingID = 99; - - // Empty - sc::SheetViewManager maSheetViewManager; - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getNextSheetView(sc::DefaultSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getNextSheetView(0)); // First non existing - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getNextSheetView(1)); // Next non existing - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getNextSheetView(nNonExistingID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, - maSheetViewManager.getNextSheetView(sc::InvalidSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, maSheetViewManager.getNextSheetView(-99)); - - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getPreviousSheetView(sc::DefaultSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getPreviousSheetView(0)); // First non existing - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getPreviousSheetView(1)); // Next non existing - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getPreviousSheetView(nNonExistingID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, - maSheetViewManager.getPreviousSheetView(sc::InvalidSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, maSheetViewManager.getPreviousSheetView(-99)); - - // Add ID 1 - auto nID1 = maSheetViewManager.create(nullptr); - CPPUNIT_ASSERT(maSheetViewManager.get(nID1)); - - CPPUNIT_ASSERT_EQUAL(nID1, maSheetViewManager.getNextSheetView(sc::DefaultSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, maSheetViewManager.getNextSheetView(nID1)); - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getNextSheetView(nNonExistingID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, - maSheetViewManager.getNextSheetView(sc::InvalidSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, maSheetViewManager.getNextSheetView(-99)); - - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, maSheetViewManager.getPreviousSheetView(nID1)); - CPPUNIT_ASSERT_EQUAL(nID1, maSheetViewManager.getPreviousSheetView(sc::DefaultSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getPreviousSheetView(nNonExistingID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, - maSheetViewManager.getPreviousSheetView(sc::InvalidSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, maSheetViewManager.getPreviousSheetView(-99)); - - // Add ID 2 - auto nID2 = maSheetViewManager.create(nullptr); - CPPUNIT_ASSERT(maSheetViewManager.get(nID2)); - CPPUNIT_ASSERT_EQUAL(nID1, maSheetViewManager.getNextSheetView(sc::DefaultSheetViewID)); - CPPUNIT_ASSERT_EQUAL(nID2, maSheetViewManager.getNextSheetView(nID1)); - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, maSheetViewManager.getNextSheetView(nID2)); - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getNextSheetView(nNonExistingID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, - maSheetViewManager.getNextSheetView(sc::InvalidSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, maSheetViewManager.getNextSheetView(-99)); - - CPPUNIT_ASSERT_EQUAL(nID2, maSheetViewManager.getPreviousSheetView(sc::DefaultSheetViewID)); - CPPUNIT_ASSERT_EQUAL(nID1, maSheetViewManager.getPreviousSheetView(nID2)); - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, maSheetViewManager.getPreviousSheetView(nID1)); - CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, - maSheetViewManager.getPreviousSheetView(nNonExistingID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, - maSheetViewManager.getPreviousSheetView(sc::InvalidSheetViewID)); - CPPUNIT_ASSERT_EQUAL(sc::InvalidSheetViewID, maSheetViewManager.getPreviousSheetView(-99)); + sortDescendingForCell(u"A1"); } CPPUNIT_TEST_FIXTURE(SheetViewTest, testCheckIfSheetViewIsSavedInDocument_ODF) @@ -480,8 +740,7 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testCheckIfSheetViewIsSavedInDocument_ODF) ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); pModelObj->initializeForTiledRendering(uno::Sequence()); - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); - Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); save(TestFilter::ODS); @@ -496,8 +755,7 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testCheckIfSheetViewIsSavedInDocument_OOXML) ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); pModelObj->initializeForTiledRendering(uno::Sequence()); - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); - Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); save(TestFilter::XLSX); @@ -528,7 +786,7 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveTableWithSheetViews) { auto pSheetViewManager = rDocument.GetSheetViewManager(SCTAB(0)); CPPUNIT_ASSERT(pSheetViewManager); - CPPUNIT_ASSERT_EQUAL(size_t(0), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(0), pSheetViewManager->size()); // Check we have the correct table selected CPPUNIT_ASSERT_EQUAL(SCTAB(2), rDocument.GetTableCount()); @@ -539,14 +797,15 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveTableWithSheetViews) } // Create first sheet views - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + createNewSheetViewInCurrentView(); { auto pSheetViewManager = rDocument.GetSheetViewManager(SCTAB(0)); CPPUNIT_ASSERT(pSheetViewManager); - CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewManager->size()); - CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); + // View is now on the sheet view tab + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabView1->GetViewData().GetTabNumber()); auto pSheetView1 = pSheetViewManager->get(0); CPPUNIT_ASSERT_EQUAL(SCTAB(1), pSheetView1->getTableNumber()); @@ -557,10 +816,11 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveTableWithSheetViews) } // Create second sheet views - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + createNewSheetViewInCurrentView(); { - CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); + // View is now on the latest sheet view tab + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabView1->GetViewData().GetTabNumber()); CPPUNIT_ASSERT_EQUAL(SCTAB(4), rDocument.GetTableCount()); CPPUNIT_ASSERT_EQUAL(u"NewTab"_ustr, rDocument.GetAllTableNames()[0]); @@ -572,7 +832,7 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveTableWithSheetViews) auto pSheetViewManager = rDocument.GetSheetViewManager(SCTAB(0)); CPPUNIT_ASSERT(pSheetViewManager); - CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewManager->size()); auto pSheetView1 = pSheetViewManager->get(0); CPPUNIT_ASSERT_EQUAL(SCTAB(2), pSheetView1->getTableNumber()); @@ -595,6 +855,51 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveTableWithSheetViews) } } +CPPUNIT_TEST_FIXTURE(SheetViewTest, testNewSheetViewKeepsOthersUnchanged) +{ + // Regression: SC_TAB_INSERTED was broadcast twice in MakeNewSheetView, + // making every passive view shift its active tab twice and land on the + // wrong sheet. + + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument& rDocument = *pModelObj->GetDocument(); + + ScTestViewCallback aView1; + ScTabViewShell* pTabView1 = aView1.getTabViewShell(); + + // 4 sheets is the minimum that keeps a buggy double shift of 2 -> 4 + // from being clamped back to 3 by tableCount - 1. + insertSheet(u"Sheet2"_ustr, 2); + insertSheet(u"Sheet3"_ustr, 3); + insertSheet(u"Sheet4"_ustr, 4); + CPPUNIT_ASSERT_EQUAL(SCTAB(4), rDocument.GetTableCount()); + pTabView1->SetTabNo(0); + + // Setup View #2 on Sheet3. + SfxLokHelper::createView(); + Scheduler::ProcessEventsToIdle(); + ScTestViewCallback aView2; + ScTabViewShell* pTabView2 = aView2.getTabViewShell(); + SfxLokHelper::setView(aView2.getViewID()); + Scheduler::ProcessEventsToIdle(); + pTabView2->SetTabNo(2); + CPPUNIT_ASSERT_EQUAL(SCTAB(2), pTabView2->GetViewData().GetTabNumber()); + + // View #1 creates a new sheet view of Sheet1: one tab is inserted at + // index 1. + SfxLokHelper::setView(aView1.getViewID()); + Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(SCTAB(5), rDocument.GetTableCount()); + // View #1 lands on its new sheet view at tab 1 + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabView1->GetViewData().GetTabNumber()); + // View #2 must follow Sheet3 from tab 2 to tab 3. + CPPUNIT_ASSERT_EQUAL(SCTAB(3), pTabView2->GetViewData().GetTabNumber()); +} + CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetViewHolderTable) { // Delete the sheet view holder table directly @@ -610,18 +915,18 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetViewHolderTable) { auto pSheetViewManager = rDocument.GetSheetViewManager(SCTAB(0)); CPPUNIT_ASSERT(pSheetViewManager); - CPPUNIT_ASSERT_EQUAL(size_t(0), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(0), pSheetViewManager->size()); } // Create first sheet views - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + createNewSheetViewInCurrentView(); { auto pSheetViewManager = rDocument.GetSheetViewManager(SCTAB(0)); CPPUNIT_ASSERT(pSheetViewManager); - CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewManager->size()); - CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabView1->GetViewData().GetTabNumber()); auto pSheetView1 = pSheetViewManager->get(0); CPPUNIT_ASSERT_EQUAL(SCTAB(1), pSheetView1->getTableNumber()); @@ -631,10 +936,10 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetViewHolderTable) } // Create second sheet views - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + createNewSheetViewInCurrentView(); { - CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabView1->GetViewData().GetTabNumber()); CPPUNIT_ASSERT_EQUAL(SCTAB(3), rDocument.GetTableCount()); CPPUNIT_ASSERT_EQUAL(u"Hoja1"_ustr, rDocument.GetAllTableNames()[0]); @@ -645,7 +950,7 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetViewHolderTable) auto pSheetViewManager = rDocument.GetSheetViewManager(SCTAB(0)); CPPUNIT_ASSERT(pSheetViewManager); - CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewManager->size()); auto pSheetView1 = pSheetViewManager->get(0); CPPUNIT_ASSERT_EQUAL(SCTAB(2), pSheetView1->getTableNumber()); @@ -683,7 +988,7 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetViewHolderTable) auto pSheetViewManager = rDocument.GetSheetViewManager(SCTAB(0)); CPPUNIT_ASSERT(pSheetViewManager); - CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewManager->getSheetViews().size()); + CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewManager->size()); auto pSheetView1 = pSheetViewManager->get(0); CPPUNIT_ASSERT_EQUAL(SCTAB(1), pSheetView1->getTableNumber()); @@ -694,39 +999,6 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetViewHolderTable) } } -CPPUNIT_TEST_FIXTURE(SheetViewTest, testRenderStateInSheetView) -{ - // Check the View Render State is set correctly when in sheet view. - // When in sheet view, we expect the sheet view ID to be set in the state. - - ScModelObj* pModelObj = createDoc("empty.ods"); - - // View 1 - ScTestViewCallback aView1; - - // View 1 - default state - CPPUNIT_ASSERT_EQUAL("S;Default"_ostr, pModelObj->getViewRenderState()); - - // View 2 - SfxLokHelper::createView(); - ScTestViewCallback aView2; - - // View 2 - default state - CPPUNIT_ASSERT_EQUAL("S;Default"_ostr, pModelObj->getViewRenderState()); - - // Create a sheet view in View 2 - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); - - // View 2 - state includes view sheet ID - CPPUNIT_ASSERT_EQUAL("S;Default;VS:0"_ostr, pModelObj->getViewRenderState()); - - // Switch to View 1 - SfxLokHelper::setView(aView1.getViewID()); - - // View 1 - still default state - CPPUNIT_ASSERT_EQUAL("S;Default"_ostr, pModelObj->getViewRenderState()); -} - CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncAfterSorting_DefaultViewSort) { // Two related scenarios tested: @@ -762,9 +1034,9 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncAfterSorting_DefaultViewSort) CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewSheetView->GetViewData().GetTabNumber()); CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewDefaultView->GetViewData().GetTabNumber()); - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + createNewSheetViewInCurrentView(); - CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewSheetView->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabViewSheetView->GetViewData().GetTabNumber()); CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewDefaultView->GetViewData().GetTabNumber()); } @@ -773,37 +1045,45 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncAfterSorting_DefaultViewSort) SfxLokHelper::setView(aDefaultView.getViewID()); Scheduler::ProcessEventsToIdle(); - CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewSheetView->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabViewSheetView->GetViewData().GetTabNumber()); CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewDefaultView->GetViewData().GetTabNumber()); // Sort AutoFilter ascending - dispatchCommand(mxComponent, u".uno:SortAscending"_ustr, {}); + sortAscendingForCell(u"A1"); - CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewSheetView->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabViewSheetView->GetViewData().GetTabNumber()); CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewDefaultView->GetViewData().GetTabNumber()); // Check values - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"3", u"4", u"5", u"7" })); - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"4", u"5", u"3", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(pTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pTabViewSheetView, 0, 1, 4)); typeCharsInCell(std::string("9"), 0, 1, pTabViewDefaultView, pModelObj); // Check values - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"9", u"4", u"5", u"7" })); - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"4", u"5", u"9", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"9", u"4", u"5", u"7" }), + getValues(pTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"9", u"7" }), + getValues(pTabViewSheetView, 0, 1, 4)); // Sort AutoFilter AGAIN descending - dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); + sortDescendingForCell(u"A1"); // Check values - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"9", u"7", u"5", u"4" })); - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"4", u"5", u"9", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"9", u"7", u"5", u"4" }), + getValues(pTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"9", u"7" }), + getValues(pTabViewSheetView, 0, 1, 4)); typeCharsInCell(std::string("6"), 0, 3, pTabViewDefaultView, pModelObj); // Check values - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"9", u"7", u"6", u"4" })); - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"4", u"6", u"9", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"9", u"7", u"6", u"4" }), + getValues(pTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"6", u"9", u"7" }), + getValues(pTabViewSheetView, 0, 1, 4)); } } @@ -841,32 +1121,50 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncAfterSorting_SheetViewSort) Scheduler::ProcessEventsToIdle(); // New Sheet view - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + createNewSheetViewInCurrentView(); + + // Expect the data is same in both + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pTabViewDefaultView, 0, 1, 4)); // Sort AutoFilter - dispatchCommand(mxComponent, u".uno:SortAscending"_ustr, {}); + sortAscendingForCell(u"A1"); // Check values - Sheet View - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"3", u"4", u"5", u"7" })); - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"4", u"5", u"3", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(pTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pTabViewDefaultView, 0, 1, 4)); typeCharsInCell(std::string("9"), 0, 1, pTabViewSheetView, pModelObj); - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"9", u"4", u"5", u"7" })); - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"4", u"5", u"9", u"7" })); + // Sheet view is automatically sorted if it was sorted before. + // So it would be { u"9", u"4", u"5", u"7" } + // and then sorted to { u"4", u"5", u"7", u"9" } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"7", u"9" }), + getValues(pTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"9", u"7" }), + getValues(pTabViewDefaultView, 0, 1, 4)); // Scenario 2 // Sort AutoFilter - dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); + sortDescendingForCell(u"A1"); - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"9", u"7", u"5", u"4" })); - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"4", u"5", u"9", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"9", u"7", u"5", u"4" }), + getValues(pTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"9", u"7" }), + getValues(pTabViewDefaultView, 0, 1, 4)); typeCharsInCell(std::string("6"), 0, 3, pTabViewSheetView, pModelObj); - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"9", u"7", u"6", u"4" })); - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"4", u"6", u"9", u"7" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"6", u"9", u"7" }), + getValues(pTabViewDefaultView, 0, 1, 4)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"9", u"7", u"6", u"4" }), + getValues(pTabViewSheetView, 0, 1, 4)); } } @@ -894,33 +1192,4370 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncAfterSorting_SortInDefaultAndSheetVi SfxLokHelper::setView(aSheetView.getViewID()); Scheduler::ProcessEventsToIdle(); - dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + createNewSheetViewInCurrentView(); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pTabViewDefaultView, 0, 1, 4)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pTabViewSheetView, 0, 1, 4)); // Sort AutoFilter - dispatchCommand(mxComponent, u".uno:SortAscending"_ustr, {}); + sortAscendingForCell(u"A1"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pTabViewDefaultView, 0, 1, 4)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(pTabViewSheetView, 0, 1, 4)); } - // Switch to Sheet View and Create + // Switch to Default view and sort { SfxLokHelper::setView(aDefaultView.getViewID()); Scheduler::ProcessEventsToIdle(); // Sort AutoFilter - dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); + sortDescendingForCell(u"A1"); - // Check values - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"3", u"4", u"5", u"7" })); - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"7", u"5", u"4", u"3" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pTabViewDefaultView, 0, 1, 4)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(pTabViewSheetView, 0, 1, 4)); } + // Switch to Sheet view and set a value { SfxLokHelper::setView(aSheetView.getViewID()); Scheduler::ProcessEventsToIdle(); + // Change "4" to "44" typeCharsInCell(std::string("44"), 0, 2, pTabViewSheetView, pModelObj); - CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"3", u"44", u"5", u"7" })); - CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"7", u"5", u"44", u"3" })); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"44", u"3" }), + getValues(pTabViewDefaultView, 0, 1, 4)); + + // Result in { u"3", u"44", u"5", u"7" } but we resort the sheet view immediately + // so we get { u"3", u"5", u"7", u"44" }. + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"5", u"7", u"44" }), + getValues(pTabViewSheetView, 0, 1, 4)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSyncAfterSorting_SortInDefaultAndSheetView_Formulas) +{ + // Input is an test file that uses formulas instead of values. + // This test checks if the sorting of the document behaves the same + // for formulas as values. + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter_Formulas.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + + setupViews(); + + // Switch to Sheet View and Create + { + switchToSheetView(); + + createNewSheetViewInCurrentView(); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7", u"1", u"6" }), + getValues(mpTabViewDefaultView, 0, 1, 6)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7", u"1", u"6" }), + getValues(mpTabViewSheetView, 0, 1, 6)); + + // Sort AutoFilter + sortAscendingForCell(u"A1"); + + // No change to sorted values + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7", u"1", u"6" }), + getValues(mpTabViewDefaultView, 0, 1, 6)); + // Expect sorted values for the sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"1", u"3", u"4", u"5", u"6", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 6)); + } + + // Switch to Default view and sort + { + switchToDefaultView(); + + // Sort AutoFilter + sortDescendingForCell(u"A1"); + + // Expect sorted values for the default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3", u"1" }), + getValues(mpTabViewDefaultView, 0, 1, 6)); + + // Previously sorted values - no change + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"1", u"3", u"4", u"5", u"6", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 6)); + } + + // Switch to Sheet view and set a value + { + switchToSheetView(); + + // Change "4" to "44" + typeCharsInCell(std::string("=40+4"), 0, 3, mpTabViewSheetView, pModelObj); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"44", u"3", u"1" }), + getValues(mpTabViewDefaultView, 0, 1, 6)); + + // Result in { u"1", u"3", u"4", u"5", u"6", u"7" } but we resort the sheet view immediately + // so we get { u"1", u"3", u"5", u"6", u"7", u"44" }. + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"1", u"3", u"5", u"6", u"7", u"44" }), + getValues(mpTabViewSheetView, 0, 1, 6)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSyncAfterSorting_SortInDefaultView_Attributes) +{ + // Instead of the number, we set the attribute + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + // Create new sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Switch to Sheet view and set "bold" text attribute to all cells in the auto filter one by one + { + switchToSheetView(); + + // Current state default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Current state sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Current font weight state + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Set A4 in sheet view -> A5 in default view + setCellBold(u"A4"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"B", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Set A2 in sheet view -> A4 in default view + setCellBold(u"A2"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"N", u"B", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Set A3 in sheet view -> A3 in default view + setCellBold(u"A3"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"B", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Set A5 in sheet view -> A2 in default view + setCellBold(u"A5"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Set range A4:A5, which are A2, A5 in default view + setCellBold(u"A4:A5"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"B", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSyncAfterSorting_SortInDefaultAndSheetView_Attributes) +{ + // Instead of the number, we set the attribute + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Switch to Sheet view and set "bold" text attribute to all cells in the auto filter one by one + { + switchToSheetView(); + + // Current state default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Current state sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Current font weight state + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Set A5 in sheet view -> A2 in default view + setCellBold(u"A5"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Set A4 in sheet view -> A3 in default view + setCellBold(u"A4"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Set A3 in sheet view -> A4 in default view + setCellBold(u"A3"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"B", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Set A2 in sheet view -> A4 in default view + setCellBold(u"A2"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DefaultView_DeleteCellOperation) +{ + // Create two views, and leave the second one current. + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"", u"", u"", u"" }), getValues(pDocument, 0, 1, 4, 1)); + + // Switch to Sheet View and Create + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pDocument, 0, 1, 4, 1)); + + // Switch to Default View + { + switchToDefaultView(); + + gotoCell(u"A3"); + + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + } + + OUString aExpected = expectedValues({ u"4", u"", u"3", u"7" }); + CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 0)); + + OUString aExpectedSorted = expectedValues({ u"7", u"4", u"3", u"" }); + CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(pDocument, 0, 1, 4, 1)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_SheetView_DeleteCellOperation) +{ + // Create two views, and leave the second one current. + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"", u"", u"", u"" }), getValues(pDocument, 0, 1, 4, 1)); + + // Switch to Sheet View and Create + { + switchToSheetView(); + + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pDocument, 0, 1, 4, 1)); + + gotoCell(u"A4"); + + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + } + + OUString aExpected = expectedValues({ u"", u"5", u"3", u"7" }); + CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 0)); + + OUString aExpectedSorted = expectedValues({ u"7", u"5", u"3", u"" }); + CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(pDocument, 0, 1, 4, 1)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DefaultView_DeleteContentOperation) +{ + // Create two views, and leave the second one current. + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"", u"", u"", u"" }), getValues(pDocument, 0, 1, 4, 1)); + + // Switch to Sheet View and Create + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pDocument, 0, 1, 4, 1)); + + // Switch to Default View + { + switchToDefaultView(); + + gotoCell(u"A3:A4"); + + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + } + + OUString aExpected = expectedValues({ u"4", u"", u"", u"7" }); + CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 0)); + + OUString aExpectedSorted = expectedValues({ u"7", u"4", u"", u"" }); + CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(pDocument, 0, 1, 4, 1)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_SheetView_DeleteContentOperation) +{ + // Create two views, and leave the second one current. + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"", u"", u"", u"" }), getValues(pDocument, 0, 1, 4, 1)); + + // Switch to Sheet View and Create + { + switchToSheetView(); + + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pDocument, 0, 1, 4, 1)); + + gotoCell(u"A3:A4"); + + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + } + + OUString aExpected = expectedValues({ u"", u"", u"3", u"7" }); + CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 0)); + + OUString aExpectedSorted = expectedValues({ u"7", u"3", u"", u"" }); + CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(pDocument, 0, 1, 4, 1)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testCreateAndDeleteSheetView) +{ + // Test that creating a sheet view, deleting it, creating a new one again, + // works without an issue. + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + // Initial values + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + + // Create a sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + // Delete the sheet view + { + switchToSheetView(); + removeSheetViewInCurrentView(); + } + + // Create a new sheet view again + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + + typeCharsInCell(std::string("99"), 0, 1, mpTabViewSheetView, pModelObj); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"99", u"5", u"3", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSorting_NonAutoFilterRange) +{ + // When we sort outside of the auto-filtered range, we sync the changes + // to all views. When sorting auto-filtered range, then we sort only the + // current view and don't sync. + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter_Extended.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument& rDocument = *pModelObj->GetDocument(); + + setupViews(); + + // Check sorting when no sheet view was created yet + { + switchToDefaultView(); + + // Check we have no sheet view yet + auto pSheetViewManager = rDocument.GetSheetViewManager(SCTAB(0)); + CPPUNIT_ASSERT(pSheetViewManager); + CPPUNIT_ASSERT(pSheetViewManager->isEmpty()); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ccc", u"rrr", u"sss", u"aaa" }), + getValues(mpTabViewDefaultView, 1, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"44", u"22", u"11", u"33" }), + getValues(mpTabViewDefaultView, 4, 1, 4)); + + // Select and sort the range - no sheet views yet + sortDescendingForCell(u"E2:E5"); + + // Check - we expect to be sorted descending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"44", u"33", u"22", u"11" }), + getValues(mpTabViewDefaultView, 4, 1, 4)); + } + + // Check sheet view sorting + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + + // Check initial values of the E2:E5 range + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"44", u"33", u"22", u"11" }), + getValues(mpTabViewSheetView, 4, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"44", u"33", u"22", u"11" }), + getValues(mpTabViewDefaultView, 4, 1, 4)); + + // Sort the range ascending + sortAscendingForCell(u"E2:E5"); + + // Check - we expect both views to be sorted ascending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"11", u"22", u"33", u"44" }), + getValues(mpTabViewSheetView, 4, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"11", u"22", u"33", u"44" }), + getValues(mpTabViewDefaultView, 4, 1, 4)); + + // Check the auto-filtered values in column B + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ccc", u"rrr", u"sss", u"aaa" }), + getValues(mpTabViewSheetView, 1, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ccc", u"rrr", u"sss", u"aaa" }), + getValues(mpTabViewDefaultView, 1, 1, 4)); + + // Select the range of an auto-filtered range and sort ascending column B + sortAscendingForCell(u"B1"); + + // Check - only the sheet view should be sorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"aaa", u"ccc", u"rrr", u"sss" }), + getValues(mpTabViewSheetView, 1, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ccc", u"rrr", u"sss", u"aaa" }), + getValues(mpTabViewDefaultView, 1, 1, 4)); + } +} + +CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetViewAndSwitchTab) +{ + // Test that creating a sheet view, removing it, switching to another tab + // and switching back shows the correct data (not an empty sheet). + + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument& rDocument = *pModelObj->GetDocument(); + + ScTestViewCallback aView1; + ScTabViewShell* pTabView1 = aView1.getTabViewShell(); + + // Insert a second sheet + uno::Sequence aArgsInsert(comphelper::InitPropertySequence( + { { "Name", uno::Any(u"Sheet2"_ustr) }, { "Index", uno::Any(sal_Int16(2)) } })); + dispatchCommand(mxComponent, u".uno:Insert"_ustr, aArgsInsert); + + CPPUNIT_ASSERT_EQUAL(SCTAB(2), rDocument.GetTableCount()); + + // Go back to the first sheet + pTabView1->SetTabNo(0); + + // Put some data in the first sheet + rDocument.SetString(ScAddress(0, 0, 0), u"ABC"_ustr); + CPPUNIT_ASSERT_EQUAL(u"ABC"_ustr, rDocument.GetString(ScAddress(0, 0, 0))); + + // Create a sheet view on the first sheet + createNewSheetViewInCurrentView(); + + // Verify we are now on the sheet view tab + CPPUNIT_ASSERT(rDocument.GetTableSheetViewID(pTabView1->GetViewData().GetTabNumber()) + != sc::DefaultSheetViewID); + + // Remove the sheet view + removeSheetViewInCurrentView(); + + // Should be back on the default tab (first sheet) + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); + + // Switch to the second sheet + pTabView1->SetTabNo(1); + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabView1->GetViewData().GetTabNumber()); + + // Switch back to the first sheet + pTabView1->SetTabNo(0); + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); + + // Verify the data is still visible (not an empty sheet) + CPPUNIT_ASSERT_EQUAL(u"ABC"_ustr, rDocument.GetString(ScAddress(0, 0, 0))); +} + +CPPUNIT_TEST_FIXTURE(SheetViewTest, testNewViewOpensInDefaultView) +{ + // Test that opening a new view while on a sheet view tab opens the new + // view on the default tab, not on the sheet view tab. + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + + // Setup first view + ScTestViewCallback aView1; + ScTabViewShell* pTabView1 = aView1.getTabViewShell(); + + // Verify we start on tab 0 (default) + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); + + // Create a sheet view - view 1 should move to the sheet view tab + createNewSheetViewInCurrentView(); + + // Create a new view - simulates a new user or new window + SfxLokHelper::createView(); + Scheduler::ProcessEventsToIdle(); + + ScTestViewCallback aView2; + ScTabViewShell* pTabView2 = aView2.getTabViewShell(); + + CPPUNIT_ASSERT(pTabView1 != pTabView2); + + // View 1 should be open on sheet view tab + CPPUNIT_ASSERT_EQUAL(SCTAB(1), pTabView1->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT(pTabView1->GetViewData().GetSheetViewID() != sc::DefaultSheetViewID); + + // The view 2 should open on the default tab + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView2->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(sc::DefaultSheetViewID, pTabView2->GetViewData().GetSheetViewID()); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DefaultView_ClearItemsOperation) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Switch to Sheet View and Create, sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + // Default view: 4, 5, 3, 7 + // Sheet view: 7, 5, 4, 3 (sorted) + + // Set A2 and A3 bold in sheet view + { + switchToSheetView(); + setCellBold(u"A2"); + setCellBold(u"A3"); + } + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Switch to Default View and call ClearItems on A4:A5 + { + switchToDefaultView(); + + ScMarkData aMark(pDocument->GetSheetLimits()); + aMark.SelectTable(0, true); + aMark.SetMarkArea(ScRange(0, 3, 0, 0, 4, 0)); + sal_uInt16 aWhich[] = { ATTR_FONT_WEIGHT, 0 }; + pDocShell->GetDocFunc().ClearItems(aMark, aWhich, true); + } + + // Default view: A4 is N so no change, A5 should change from B -> N + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + // Sheet view: A4 -> A5 and A5 -> A2, so A2 should change from B -> N + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_SheetView_ClearItemsOperation) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Switch to Sheet View and Create, sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + // Default view: 4, 5, 3, 7 + // Sheet view: 7, 5, 4, 3 (sorted) + + // Set all cells bold from sheet view + { + switchToSheetView(); + setCellBold(u"A2:A5"); + } + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Call ClearItems on A3:A4 on sheet view + { + switchToSheetView(); + + ScMarkData aMark(pDocument->GetSheetLimits()); + aMark.SelectTable(1, true); + aMark.SetMarkArea(ScRange(0, 2, 1, 0, 3, 1)); + sal_uInt16 aWhich[] = { ATTR_FONT_WEIGHT, 0 }; + pDocShell->GetDocFunc().ClearItems(aMark, aWhich, true); + } + + // Sheet view: A3, A4 changed from B -> N + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"N", u"N", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Default view: A3 -> A3, A4 -> A2, so A2 and A3 from B -> N + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"B", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_AutoFormat_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Switch to sheet view and apply AutoFormat + { + switchToSheetView(); + + // Current state default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Current state sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Initial text weights + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Apply AutoFormat (format 0) to A2:A5 on default view (index 0) + pDocShell->GetDocFunc().AutoFormat(ScRange(0, 1, 0, 0, 4, 0), nullptr, 0, true); + + // Values should remain unchanged after AutoFormat + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // First row is defined as header row, so we can exploit that to test resorting. + // Default view: AutoFormat applies blue to first row, gray to others + //FIXME + //CPPUNIT_ASSERT_EQUAL(expectedValues({ u"000080", u"cccccc", u"cccccc", u"cccccc" }), + // getBackgroundColor(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ffffff", u"ffffff", u"ffffff", u"ffffff" }), + getBackgroundColor(pDocument, 0, 1, 4, 0)); + + // Sheet view: background colors synced and re-sorted + //FIXME + //CPPUNIT_ASSERT_EQUAL(expectedValues({ u"cccccc", u"cccccc", u"cccccc", u"000080" }), + // getBackgroundColor(pDocument, 0, 1, 4, 1)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ffffff", u"ffffff", u"ffffff", u"ffffff" }), + getBackgroundColor(pDocument, 0, 1, 4, 1)); + } + + // AutoFormat on the sheet view should be blocked - input intersects autofilter + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + bool bResult = pDocShell->GetDocFunc().AutoFormat( + ScRange(0, 1, nSheetViewTab, 0, 4, nSheetViewTab), nullptr, 1, true); + + // Returns false because the running is blocked + CPPUNIT_ASSERT(!bResult); + + // Background colors should remain unchanged + //FIXME + //CPPUNIT_ASSERT_EQUAL(expectedValues({ u"000080", u"cccccc", u"cccccc", u"cccccc" }), + // getBackgroundColor(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ffffff", u"ffffff", u"ffffff", u"ffffff" }), + getBackgroundColor(pDocument, 0, 1, 4, 0)); + + //FIXME + //CPPUNIT_ASSERT_EQUAL(expectedValues({ u"cccccc", u"cccccc", u"cccccc", u"000080" }), + // getBackgroundColor(pDocument, 0, 1, 4, nSheetViewTab)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ffffff", u"ffffff", u"ffffff", u"ffffff" }), + getBackgroundColor(pDocument, 0, 1, 4, nSheetViewTab)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_MultipleOps_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument* pDocument = pModelObj->GetDocument(); + + // Set up 2 views: for default view and for sheet view 1 + setupViews(); + + // Add another view for sheet view 2 + SfxLokHelper::createView(); + Scheduler::ProcessEventsToIdle(); + ScTestViewCallback aSheetView2; + int nSheetView2 = aSheetView2.getViewID(); + + // Set up data, which will be duplicated to default view and sheet views + // A1 = 1 - input cell + // B1 = =A1*10 - formula + // variable inputs: + // A3 = 2 + // A4 = 3 + // A5 = 4 + pDocument->SetValue(ScAddress(0, 0, 0), 1); + pDocument->SetString(ScAddress(1, 0, 0), u"=A1*10"_ustr); + pDocument->SetValue(ScAddress(0, 2, 0), 2); + pDocument->SetValue(ScAddress(0, 3, 0), 3); + pDocument->SetValue(ScAddress(0, 4, 0), 4); + + // Check value + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(1, 0, 0))); + + // Create sheet view 1 + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + // Create sheet view 2 + { + SfxLokHelper::setView(nSheetView2); + Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); + } + + // Perform Multiple Operations from sheet view 1 + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + ScTabOpParam aParam; + aParam.aRefFormulaCell = ScRefAddress(1, 0, nSheetViewTab); + aParam.aRefFormulaEnd = aParam.aRefFormulaCell; + aParam.aRefColCell = ScRefAddress(0, 0, nSheetViewTab); + aParam.meMode = ScTabOpParam::Column; + + // Apply Multiple Operations on A3:B5 — fills B3:B5 with 20, 30, 40 + pDocShell->GetDocFunc().TabOp(ScRange(0, 2, nSheetViewTab, 1, 4, nSheetViewTab), nullptr, + aParam, true, true); + + // Verify results in default view (index 0) + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + CPPUNIT_ASSERT_EQUAL(u"20"_ustr, pDocument->GetString(ScAddress(1, 2, nDefaultViewTab))); + CPPUNIT_ASSERT_EQUAL(u"30"_ustr, pDocument->GetString(ScAddress(1, 3, nDefaultViewTab))); + CPPUNIT_ASSERT_EQUAL(u"40"_ustr, pDocument->GetString(ScAddress(1, 4, nDefaultViewTab))); + + // Verify same results in sheet view 1 + CPPUNIT_ASSERT_EQUAL(u"20"_ustr, pDocument->GetString(ScAddress(1, 2, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(u"30"_ustr, pDocument->GetString(ScAddress(1, 3, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(u"40"_ustr, pDocument->GetString(ScAddress(1, 4, nSheetViewTab))); + + // Verify same results in sheet view 2 + SCTAB nSheetView2Tab = aSheetView2.getTabViewShell()->GetViewData().GetTabNumber(); + CPPUNIT_ASSERT_EQUAL(u"20"_ustr, pDocument->GetString(ScAddress(1, 2, nSheetView2Tab))); + CPPUNIT_ASSERT_EQUAL(u"30"_ustr, pDocument->GetString(ScAddress(1, 3, nSheetView2Tab))); + CPPUNIT_ASSERT_EQUAL(u"40"_ustr, pDocument->GetString(ScAddress(1, 4, nSheetView2Tab))); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_ReplaceNote_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Replace note from default view on C1 + { + switchToDefaultView(); + + OUString aAuthor(u"Test Author"_ustr); + OUString aDate(u"2026-03-08"_ustr); + pDocShell->GetDocFunc().ReplaceNote(ScAddress(2, 0, 0), u"Default Note"_ustr, &aAuthor, + &aDate, true); + + // Verify note on default view + ScPostIt* pNoteDefault = pDocument->GetNote(ScAddress(2, 0, 0)); + CPPUNIT_ASSERT(pNoteDefault); + CPPUNIT_ASSERT_EQUAL(u"Default Note"_ustr, pNoteDefault->GetText()); + + // Verify note synced to sheet view + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + ScPostIt* pNoteSheet = pDocument->GetNote(ScAddress(2, 0, nSheetViewTab)); + CPPUNIT_ASSERT(pNoteSheet); + CPPUNIT_ASSERT_EQUAL(u"Default Note"_ustr, pNoteSheet->GetText()); + } + + // Replace note from sheet view on A2 + // Sheet view ascending: A2=3, A3=4, A4=5, A5=7 + // Default view descending: A2=7, A3=5, A4=4, A5=3 + // A2 on sheet view (value 3) maps to A5 on default view (value 3) + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + OUString aAuthor(u"Sheet Author"_ustr); + OUString aDate(u"2026-03-08"_ustr); + pDocShell->GetDocFunc().ReplaceNote(ScAddress(0, 1, nSheetViewTab), u"Sheet Note"_ustr, + &aAuthor, &aDate, true); + + // Verify note on default view at A5 (value 3) + ScPostIt* pNoteDefault = pDocument->GetNote(ScAddress(0, 4, 0)); + CPPUNIT_ASSERT(pNoteDefault); + CPPUNIT_ASSERT_EQUAL(u"Sheet Note"_ustr, pNoteDefault->GetText()); + + // Verify note on sheet view at A2 (value 3) + ScPostIt* pNoteSheet = pDocument->GetNote(ScAddress(0, 1, nSheetViewTab)); + CPPUNIT_ASSERT(pNoteSheet); + CPPUNIT_ASSERT_EQUAL(u"Sheet Note"_ustr, pNoteSheet->GetText()); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_MoveBlock_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Put data in column C (outside autofilter range) on default view + pDocument->SetString(ScAddress(2, 0, 0), u"Hello"_ustr); + pDocument->SetValue(ScAddress(2, 1, 0), 10.0); + pDocument->SetValue(ScAddress(2, 2, 0), 20.0); + + // Move block from default view: C1:C3 -> D1:D3 (outside autofilter) + { + switchToDefaultView(); + + bool bMoved = pDocShell->GetDocFunc().MoveBlock( + ScRange(2, 0, 0, 2, 2, 0), ScAddress(3, 0, 0), true, true, false, true); + CPPUNIT_ASSERT(bMoved); + + // Verify on default view + CPPUNIT_ASSERT_EQUAL(OUString(), pDocument->GetString(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"Hello"_ustr, pDocument->GetString(ScAddress(3, 0, 0))); + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(3, 1, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDocument->GetValue(ScAddress(3, 2, 0))); + + // Verify synced on sheet view + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + CPPUNIT_ASSERT_EQUAL(OUString(), pDocument->GetString(ScAddress(2, 0, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(u"Hello"_ustr, pDocument->GetString(ScAddress(3, 0, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(3, 1, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(20.0, pDocument->GetValue(ScAddress(3, 2, nSheetViewTab))); + } + + // Move block from sheet view: D1:D3 -> E1:E3 (outside autofilter) + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + bool bMoved = pDocShell->GetDocFunc().MoveBlock( + ScRange(3, 0, nSheetViewTab, 3, 2, nSheetViewTab), ScAddress(4, 0, nSheetViewTab), true, + true, false, true); + CPPUNIT_ASSERT(bMoved); + + // Verify on default view + CPPUNIT_ASSERT_EQUAL(OUString(), pDocument->GetString(ScAddress(3, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"Hello"_ustr, pDocument->GetString(ScAddress(4, 0, 0))); + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(4, 1, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDocument->GetValue(ScAddress(4, 2, 0))); + + // Verify synced on sheet view + CPPUNIT_ASSERT_EQUAL(OUString(), pDocument->GetString(ScAddress(3, 0, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(u"Hello"_ustr, pDocument->GetString(ScAddress(4, 0, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(10.0, pDocument->GetValue(ScAddress(4, 1, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(20.0, pDocument->GetValue(ScAddress(4, 2, nSheetViewTab))); + } + + // Move block from default view inside autofilter: A2:A3 -> C2:C3 + { + switchToDefaultView(); + + bool bMoved = pDocShell->GetDocFunc().MoveBlock( + ScRange(0, 1, 0, 0, 2, 0), ScAddress(2, 1, 0), true, true, false, true); + CPPUNIT_ASSERT(bMoved); + + // Verify A2:A3 cleared and C2:C3 has values on default view + CPPUNIT_ASSERT_EQUAL(OUString(), pDocument->GetString(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(OUString(), pDocument->GetString(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(7.0, pDocument->GetValue(ScAddress(2, 1, 0))); + CPPUNIT_ASSERT_EQUAL(5.0, pDocument->GetValue(ScAddress(2, 2, 0))); + + // Verify autofilter column on both views + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"", u"", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"", u"" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } + + // Undo the move inside autofilter + { + switchToDefaultView(); + undo(); + + // Verify autofilter values restored + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } + + // Move block on the sheet view should be blocked as source intersects autofilter + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + // Try to move A2:A3 -> C2:C3 on sheet view tab + bool bResult = pDocShell->GetDocFunc().MoveBlock( + ScRange(0, 1, nSheetViewTab, 0, 2, nSheetViewTab), ScAddress(2, 1, nSheetViewTab), true, + true, false, true); + CPPUNIT_ASSERT(!bResult); + + // Values should remain unchanged + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_EnterMatrix_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Switch to sheet view and enter matrix formulas + { + switchToSheetView(); + + // Current state default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Current state sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Modify Sheet View A3 : 4 -> ={14} (matrix formula) + pDocShell->GetDocFunc().EnterMatrix(ScRange(0, 2, 1, 0, 2, 1), nullptr, nullptr, + u"={14}"_ustr, true, true, OUString(), + formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX); + + // Default view: translated A3 to A4 : 4 -> 14 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"14", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view: A3 : 4 -> 14, and resort + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"5", u"7", u"14" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Modify Default view A2 : 7 -> ={17} (matrix formula) + pDocShell->GetDocFunc().EnterMatrix(ScRange(0, 1, 0, 0, 1, 0), nullptr, nullptr, + u"={17}"_ustr, true, true, OUString(), + formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX); + + // Default view: A2 : 7 -> 17 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"17", u"5", u"14", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view: translated A2 to A4 : 7 -> 17, and resort + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"5", u"14", u"17" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_FillSimple_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Switch to sheet view and fill simple + { + switchToSheetView(); + + // Current state default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Current state sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // FillSimple A2:A3 on default view (index 0), FILL_TO_BOTTOM + // Copies A2 to A3 (value 7) + pDocShell->GetDocFunc().FillSimple(ScRange(0, 1, 0, 0, 2, 0), nullptr, FILL_TO_BOTTOM, + true); + + // Default view: A3 changed from 5 -> 7 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"7", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view: synced and re-sorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"7", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } + + // Try to FillSimple on the sheet view — should be blocked because it intersects autofilter + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + bool bResult = pDocShell->GetDocFunc().FillSimple( + ScRange(0, 1, nSheetViewTab, 0, 2, nSheetViewTab), nullptr, FILL_TO_BOTTOM, true); + CPPUNIT_ASSERT(!bResult); + + // Values should remain unchanged + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"7", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"7", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_FillSeries_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Switch to sheet view and fill series + { + switchToSheetView(); + + // Current state default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Current state sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // FillSeries A2:A5 on default view (index 0), FILL_TO_BOTTOM, FILL_LINEAR + // start=40, step=-10: fills 40, 30, 20, 10 + pDocShell->GetDocFunc().FillSeries(ScRange(0, 1, 0, 0, 4, 0), nullptr, FILL_TO_BOTTOM, + FILL_LINEAR, FILL_DAY, 40.0, -10.0, 0.0, true); + + // Default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"40", u"30", u"20", u"10" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view: synced and re-sorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"10", u"20", u"30", u"40" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } + + // Try to FillSeries on the sheet view — should be blocked because it intersects autofilter + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + bool bResult = pDocShell->GetDocFunc().FillSeries( + ScRange(0, 1, nSheetViewTab, 0, 4, nSheetViewTab), nullptr, FILL_TO_BOTTOM, FILL_LINEAR, + FILL_DAY, 100.0, 100.0, 0.0, true); + CPPUNIT_ASSERT(!bResult); + + // Values should remain unchanged + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"40", u"30", u"20", u"10" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"10", u"20", u"30", u"40" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_FillAuto_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + // Put data in column C (outside autofilter range) on the default view + rDocument.SetValue(ScAddress(2, 0, 0), 1.0); + rDocument.SetValue(ScAddress(2, 1, 0), 2.0); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // FillAuto on the default view inside autofilter + { + switchToDefaultView(); + + // Current state default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Current state sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // FillAuto source A2:A3 on default view (index 0), FILL_TO_BOTTOM, nCount=2 + // Source: 7, 5 (step -2), fills A4:A5 with 3, 1 + ScRange aFillRange(0, 1, 0, 0, 2, 0); + pDocShell->GetDocFunc().FillAuto(aFillRange, nullptr, FILL_TO_BOTTOM, FILL_AUTO, FILL_DAY, + 2, 1.0, 100.0, true, true); + + // Default view: 7, 5, 3, 1 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"3", u"1" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view: synced and re-sorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"1", u"3", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } + + // Try to FillAuto on the sheet view — should be blocked because it intersects autofilter + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + ScRange aFillRange(0, 1, nSheetViewTab, 0, 2, nSheetViewTab); + bool bResult = pDocShell->GetDocFunc().FillAuto( + aFillRange, nullptr, FILL_TO_BOTTOM, FILL_AUTO, FILL_DAY, 2, 1.0, 100.0, true, true); + CPPUNIT_ASSERT(!bResult); + + // Values should remain unchanged + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"3", u"1" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"1", u"3", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + } + + // FillAuto from sheet view outside autofilter (column C) should work + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + ScRange aFillRange(2, 0, nSheetViewTab, 2, 1, nSheetViewTab); + bool bResult = pDocShell->GetDocFunc().FillAuto( + aFillRange, nullptr, FILL_TO_BOTTOM, FILL_AUTO, FILL_DAY, 2, 1.0, 100.0, true, true); + CPPUNIT_ASSERT(bResult); + + // Verify the returned range is on the sheet view tab, + // because the caller uses it for MarkRange on the current view + CPPUNIT_ASSERT_EQUAL(nSheetViewTab, aFillRange.aStart.Tab()); + CPPUNIT_ASSERT_EQUAL(nSheetViewTab, aFillRange.aEnd.Tab()); + + // Verify fill result on default view: C1=1, C2=2, C3=3, C4=4 + CPPUNIT_ASSERT_EQUAL(3.0, rDocument.GetValue(ScAddress(2, 2, 0))); + CPPUNIT_ASSERT_EQUAL(4.0, rDocument.GetValue(ScAddress(2, 3, 0))); + + // Verify synced to sheet view + CPPUNIT_ASSERT_EQUAL(3.0, rDocument.GetValue(ScAddress(2, 2, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(4.0, rDocument.GetValue(ScAddress(2, 3, nSheetViewTab))); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_TransliterateText_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter_Extended.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Create new sheet view and sort ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Default view at Column B: aaa, rrr, ccc, sss + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"aaa", u"rrr", u"ccc", u"sss" }), + getValues(mpTabViewDefaultView, 1, 1, 4)); + // Sheet view at Column B: sss, ccc, rrr, aaa + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"sss", u"ccc", u"rrr", u"aaa" }), + getValues(mpTabViewSheetView, 1, 1, 4)); + + // Transliterate B2:B5 to uppercase from sheet view + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + ScMarkData aMark(pDocument->GetSheetLimits()); + aMark.SelectTable(nSheetViewTab, true); + aMark.SetMarkArea(ScRange(1, 1, nSheetViewTab, 1, 4, nSheetViewTab)); + pDocShell->GetDocFunc().TransliterateText(aMark, TransliterationFlags::LOWERCASE_UPPERCASE, + true); + } + + // Sheet view: text is uppercased, ascending order + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"SSS", u"CCC", u"RRR", u"AAA" }), + getValues(mpTabViewSheetView, 1, 1, 4)); + + // Default view: synced, descending order, uppercased + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"AAA", u"RRR", u"CCC", u"SSS" }), + getValues(mpTabViewDefaultView, 1, 1, 4)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_ConvertFormulaToValue_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + // Set up formulas + pDocument->SetString(ScAddress(0, 0, 0), u"=10+20"_ustr); + pDocument->SetString(ScAddress(0, 1, 0), u"=30+40"_ustr); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + // Verify formulas exist on both tabs + CPPUNIT_ASSERT(pDocument->GetFormulaCell(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT(pDocument->GetFormulaCell(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT(pDocument->GetFormulaCell(ScAddress(0, 0, nSheetViewTab))); + CPPUNIT_ASSERT(pDocument->GetFormulaCell(ScAddress(0, 1, nSheetViewTab))); + + // Convert formulas to values from sheet view + { + switchToSheetView(); + pDocShell->GetDocFunc().ConvertFormulaToValue( + ScRange(0, 0, nSheetViewTab, 0, 1, nSheetViewTab), false); + } + + // Sheet view: formula converted, values preserved + CPPUNIT_ASSERT(!pDocument->GetFormulaCell(ScAddress(0, 0, nSheetViewTab))); + CPPUNIT_ASSERT(!pDocument->GetFormulaCell(ScAddress(0, 1, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(0, 0, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(70.0, pDocument->GetValue(ScAddress(0, 1, nSheetViewTab))); + + // Default view: synced — formulas also converted + CPPUNIT_ASSERT(!pDocument->GetFormulaCell(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT(!pDocument->GetFormulaCell(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(70.0, pDocument->GetValue(ScAddress(0, 1, 0))); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_SetNoteText_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Default view descending: 7, 5, 4, 3 + // Sheet view ascending: 3, 4, 5, 7 + + // Set note on A2 in sheet view + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + pDocShell->GetDocFunc().SetNoteText(ScAddress(0, 1, nSheetViewTab), u"Hello Note"_ustr, + true); + } + + // Sheet view: note on A2 + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + ScPostIt* pNoteSheet = pDocument->GetNote(ScAddress(0, 1, nSheetViewTab)); + CPPUNIT_ASSERT(pNoteSheet); + CPPUNIT_ASSERT_EQUAL(u"Hello Note"_ustr, pNoteSheet->GetText()); + + // Default view: note synced to the cell A5 + ScPostIt* pNoteDefault = pDocument->GetNote(ScAddress(0, 4, 0)); + CPPUNIT_ASSERT(pNoteDefault); + CPPUNIT_ASSERT_EQUAL(u"Hello Note"_ustr, pNoteDefault->GetText()); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_ChangeIndent_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Switch to Sheet view and change indent on A2:A3 + // Sheet view ascending: 3, 4, 5, 7 + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + ScMarkData aMark(pDocument->GetSheetLimits()); + aMark.SelectTable(nSheetViewTab, true); + aMark.SetMarkArea(ScRange(0, 1, nSheetViewTab, 0, 2, nSheetViewTab)); + aMark.MarkToMulti(); + pDocShell->GetDocFunc().ChangeIndent(aMark, true, true); + } + + // Sheet view: A2,A3 indented, A4,A5 not + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(pDocument, 0, 1, 4, 1)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"Y", u"Y", u"N", u"N" }), + getIndent(pDocument, 0, 1, 4, 1)); + + // Default view: A4,A5 indented (A4 is A3, A5 is A2) + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"Y", u"Y" }), + getIndent(pDocument, 0, 1, 4, 0)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testUndo_DefaultView_DeleteContent) +{ + // Test undo of DeleteContents from the default view with a sheet view present. + // After undo, both views should be consistent. + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + // Switch to Sheet View and Create, sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + // Default view and sheet view state + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pDocument, 0, 1, 4, 1)); + + // Clear content in default view + { + switchToDefaultView(); + gotoCell(u"A4"); + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + } + + // State after delete + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"" }), + getValues(pDocument, 0, 1, 4, 1)); + + // Undo from default view + { + switchToDefaultView(); + undo(); + } + + // After undo: default should be restored + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + + // Sheet view should also be synced back + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pDocument, 0, 1, 4, 1)); + + // Redo from default view + { + switchToDefaultView(); + redo(); + } + + // State after delete + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"" }), + getValues(pDocument, 0, 1, 4, 1)); + + // Undo from default view + { + switchToDefaultView(); + undo(); + } + + // Default view and sheet view state + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pDocument, 0, 1, 4, 1)); + + // Clear content in sheet view + { + switchToSheetView(); + gotoCell(u"A4"); + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + } + + // State after delete + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + // Sheet view was resorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"3", u"" }), + getValues(pDocument, 0, 1, 4, 1)); + + // Undo from sheet view + { + switchToSheetView(); + undo(); + } + + // Default view and sheet view state + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(pDocument, 0, 1, 4, 1)); + + // Redo from sheet view + { + switchToSheetView(); + redo(); + } + + // State after delete + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"", u"5", u"3", u"7" }), + getValues(pDocument, 0, 1, 4, 0)); + // Sheet view was resorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"3", u"" }), + getValues(pDocument, 0, 1, 4, 1)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testUndo_DefaultView_ClearItems) +{ + // Test undo of ClearItems (bold removal) from the default view with a sheet view present. + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Switch to Sheet View and Create, sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + // Set A2 and A3 bold in sheet view (values 7 and 5) + { + switchToSheetView(); + setCellBold(u"A2"); + setCellBold(u"A3"); + } + + // Default: N, B, N, B (rows with 5 and 7 are bold) + // Sheet: B, B, N, N + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Clear bold on A4:A5 in default view (values 3 and 7) + { + switchToDefaultView(); + + ScMarkData aMark(pDocument->GetSheetLimits()); + aMark.SelectTable(0, true); + aMark.SetMarkArea(ScRange(0, 3, 0, 0, 4, 0)); + sal_uInt16 aWhich[] = { ATTR_FONT_WEIGHT, 0 }; + pDocShell->GetDocFunc().ClearItems(aMark, aWhich, true); + } + + // After clear: A5(7) was bold -> now N + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Undo from default view + { + switchToDefaultView(); + undo(); + } + + // After undo: default should be restored + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + + // Sheet view should also be synced back + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Redo from default view + { + switchToDefaultView(); + redo(); + } + + // After redo: same as after clear + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Undo from default view + { + switchToDefaultView(); + undo(); + } + + // Default view and sheet view state restored + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Clear bold on A2:A3 in sheet view + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + ScMarkData aMark(pDocument->GetSheetLimits()); + aMark.SelectTable(nSheetViewTab, true); + aMark.SetMarkArea(ScRange(0, 1, nSheetViewTab, 0, 2, nSheetViewTab)); + sal_uInt16 aWhich[] = { ATTR_FONT_WEIGHT, 0 }; + pDocShell->GetDocFunc().ClearItems(aMark, aWhich, true); + } + + // After clear from sheet view: all bold cleared + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Undo from sheet view + { + switchToSheetView(); + undo(); + } + + // Default view and sheet view state restored + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"B", u"N", u"B" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"B", u"B", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); + + // Redo from sheet view + { + switchToSheetView(); + redo(); + } + + // After redo: all bold cleared + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 0)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"N", u"N", u"N", u"N" }), + getTextWeight(pDocument, 0, 1, 4, 1)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testUndo_DefaultView_FillSeries) +{ + // Test undo of FillSeries from default view with a sheet view present. + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + + setupViews(); + + // Create new sheet view and sort autofilter ascending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortAscendingForCell(u"A1"); + } + + // Sort autofilter descending in default view + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Current statw default view and sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // FillSeries: start=40, step=-10 -> 40, 30, 20, 10 + { + switchToDefaultView(); + pDocShell->GetDocFunc().FillSeries(ScRange(0, 1, 0, 0, 4, 0), nullptr, FILL_TO_BOTTOM, + FILL_LINEAR, FILL_DAY, 40.0, -10.0, 0.0, true); + } + + // After fill: the default view should have the decreasing values + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"40", u"30", u"20", u"10" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + // Sheet view has ascending sorting + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"10", u"20", u"30", u"40" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Undo from default view + { + switchToDefaultView(); + undo(); + } + + // After undo: default and sheet view should be restored + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Redo from default view + { + switchToDefaultView(); + redo(); + } + + // Values are back + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"40", u"30", u"20", u"10" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"10", u"20", u"30", u"40" }), + getValues(mpTabViewSheetView, 0, 1, 4)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_MergeCells_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument* pDocument = pModelObj->GetDocument(); + + // Set up 3 views: default view, sheet view 1, sheet view 2 + setupViews(); + + SfxLokHelper::createView(); + Scheduler::ProcessEventsToIdle(); + ScTestViewCallback aView3; + int nView3ID = aView3.getViewID(); + + // Put data in cells that will be merged + pDocument->SetString(ScAddress(0, 0, 0), u"Hello"_ustr); + pDocument->SetValue(ScAddress(1, 0, 0), 42.0); + + // Create sheet view 1 + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + // Create sheet view 2 + { + SfxLokHelper::setView(nView3ID); + Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); + } + + // Merge cells A1:B2 from sheet view 1 + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + ScCellMergeOption aMergeOption(0, 0, 1, 1); + aMergeOption.maTabs.insert(nSheetViewTab); + + bool bMerged = pDocShell->GetDocFunc().MergeCells(aMergeOption, false, true, true); + CPPUNIT_ASSERT(bMerged); + + // Verify on default view: A1 should have the content, merge flag set + CPPUNIT_ASSERT_EQUAL(u"Hello"_ustr, pDocument->GetString(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT(pDocument->HasAttrib(0, 0, 0, 1, 1, 0, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)); + + // Verify on sheet view 1 + CPPUNIT_ASSERT_EQUAL(u"Hello"_ustr, pDocument->GetString(ScAddress(0, 0, nSheetViewTab))); + CPPUNIT_ASSERT(pDocument->HasAttrib(0, 0, nSheetViewTab, 1, 1, nSheetViewTab, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)); + + // Verify on sheet view 2 + SCTAB nSheetView2Tab = aView3.getTabViewShell()->GetViewData().GetTabNumber(); + CPPUNIT_ASSERT_EQUAL(u"Hello"_ustr, pDocument->GetString(ScAddress(0, 0, nSheetView2Tab))); + CPPUNIT_ASSERT(pDocument->HasAttrib(0, 0, nSheetView2Tab, 1, 1, nSheetView2Tab, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_InsertNameList_DefaultAndSheetView) +{ + // Insert name list inserts the list of the named ranges into the sheet. + // We should sync that to all sheet views + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument* pDocument = pModelObj->GetDocument(); + + // Set up 3 views: default view, sheet view 1, sheet view 2 + setupViews(); + + SfxLokHelper::createView(); + Scheduler::ProcessEventsToIdle(); + ScTestViewCallback aView3; + int nView3ID = aView3.getViewID(); + + // Add a named range so InsertNameList has something to insert + ScRangeName& rGlobalNames = pDocument->GetRangeName(); + ScRangeData* pRangeData = new ScRangeData(*pDocument, u"TestRange"_ustr, u"$A$10:$B$20"_ustr); + rGlobalNames.insert(std::unique_ptr(pRangeData)); + + // Create sheet view 1 + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + // Create sheet view 2 + { + SfxLokHelper::setView(nView3ID); + Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); + } + + // Insert name list from sheet view 1 at A1 + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + bool bInserted + = pDocShell->GetDocFunc().InsertNameList(ScAddress(0, 0, nSheetViewTab), true); + CPPUNIT_ASSERT(bInserted); + + // Verify on default view: A1 should have the range name + CPPUNIT_ASSERT_EQUAL(u"TestRange"_ustr, pDocument->GetString(ScAddress(0, 0, 0))); + + // Verify synced to sheet views + CPPUNIT_ASSERT_EQUAL(u"TestRange"_ustr, + pDocument->GetString(ScAddress(0, 0, nSheetViewTab))); + + SCTAB nSheetView2Tab = aView3.getTabViewShell()->GetViewData().GetTabNumber(); + CPPUNIT_ASSERT_EQUAL(u"TestRange"_ustr, + pDocument->GetString(ScAddress(0, 0, nSheetView2Tab))); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_SubTotals_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument* pDocument = pModelObj->GetDocument(); + + // Set up 3 views: default view, sheet view 1, sheet view 2 + setupViews(); + + SfxLokHelper::createView(); + Scheduler::ProcessEventsToIdle(); + ScTestViewCallback aView3; + int nView3ID = aView3.getViewID(); + + // Set up data with headers and values for subtotals + // Column A: Category, Column B: Values + pDocument->SetString(ScAddress(0, 0, 0), u"Category"_ustr); + pDocument->SetString(ScAddress(1, 0, 0), u"Value"_ustr); + pDocument->SetString(ScAddress(0, 1, 0), u"A"_ustr); + pDocument->SetString(ScAddress(0, 2, 0), u"A"_ustr); + pDocument->SetString(ScAddress(0, 3, 0), u"B"_ustr); + pDocument->SetValue(ScAddress(1, 1, 0), 10.0); + pDocument->SetValue(ScAddress(1, 2, 0), 20.0); + pDocument->SetValue(ScAddress(1, 3, 0), 30.0); + + // Create a DB area for the data range + ScDBData* pDBData = new ScDBData(u"TestDB"_ustr, 0, 0, 0, 1, 3); + pDocument->GetDBCollection()->getNamedDBs().insert(std::unique_ptr(pDBData)); + + // Create sheet view 1 + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + // Create sheet view 2 + { + SfxLokHelper::setView(nView3ID); + Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); + } + + // Run subtotals from sheet view 1 + { + switchToSheetView(); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + ScSubTotalParam aParam; + aParam.bReplace = false; + aParam.bDoSort = false; + aParam.nCol1 = 0; + aParam.nRow1 = 0; + aParam.nCol2 = 1; + aParam.nRow2 = 3; + aParam.aGroups[0].bActive = true; + aParam.aGroups[0].nField = 0; // group by column A + SCCOL nSubCols[] = { 1 }; // subtotal on column B + ScSubTotalFunc nFunctions[] = { SUBTOTAL_FUNC_SUM }; + aParam.SetSubTotals(0, nSubCols, nFunctions, 1); + + ScDBDocFunc aDBDocFunc(*pDocShell); + aDBDocFunc.DoSubTotals(nSheetViewTab, aParam, true, true); + + // After subtotals, new rows are inserted with subtotal results + // Row layout: Header(0), A 10(1), A 20(2), A Sum(3), B 30(4), B Sum(5), Grand Total(6) + + // Verify on default view + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(1, 3, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(1, 5, 0))); + CPPUNIT_ASSERT_EQUAL(60.0, pDocument->GetValue(ScAddress(1, 6, 0))); + + // Verify sync to sheet view 1 + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(1, 3, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(1, 5, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(60.0, pDocument->GetValue(ScAddress(1, 6, nSheetViewTab))); + + // Verify sync to sheet view 2 + SCTAB nSheetView2Tab = aView3.getTabViewShell()->GetViewData().GetTabNumber(); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(1, 3, nSheetView2Tab))); + CPPUNIT_ASSERT_EQUAL(30.0, pDocument->GetValue(ScAddress(1, 5, nSheetView2Tab))); + CPPUNIT_ASSERT_EQUAL(60.0, pDocument->GetValue(ScAddress(1, 6, nSheetView2Tab))); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DrawObject_DefaultAndSheetView) +{ + // Checks that draw objects are synchronized between the default view and sheet views. + // This checks inserting, moving and deleting draw objects. + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocument* pDocument = pModelObj->GetDocument(); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + switchToDefaultView(); + + ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); + CPPUNIT_ASSERT(pDrawLayer); + + SCTAB nDefaultViewTable = mpTabViewDefaultView->GetViewData().GetTabNumber(); + SCTAB nSheetViewTable = mpTabViewSheetView->GetViewData().GetTabNumber(); + + SdrPage* pDefaultViewPage = pDrawLayer->GetPage(sal_uInt16(nDefaultViewTable)); + SdrPage* pSheetViewPage = pDrawLayer->GetPage(sal_uInt16(nSheetViewTable)); + CPPUNIT_ASSERT(pDefaultViewPage); + CPPUNIT_ASSERT(pSheetViewPage); + + const tools::Rectangle aRectangle1(1000, 1000, 3000, 2000); + const tools::Rectangle aRectangle2(5000, 5000, 7000, 6000); + + // Initially no objects on either page + CPPUNIT_ASSERT_EQUAL(size_t(0), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(size_t(0), pSheetViewPage->GetObjCount()); + + // Insert shape on default view + { + switchToDefaultView(); + insertDrawObject(pDrawLayer, aRectangle1); + + // Default view page has 1 object at correct position + CPPUNIT_ASSERT_EQUAL(size_t(1), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1, pDefaultViewPage->GetObj(0)->GetLogicRect()); + + // Sheet view page should also have 1 object at same position after sync + CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1, pSheetViewPage->GetObj(0)->GetLogicRect()); + } + + // Insert shape on sheet view + { + switchToSheetView(); + insertDrawObject(pDrawLayer, aRectangle2); + + // Default view page has 2 objects at correct positions + CPPUNIT_ASSERT_EQUAL(size_t(2), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1, pDefaultViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2, pDefaultViewPage->GetObj(1)->GetLogicRect()); + + // Sheet view page should also have 2 objects at same positions + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1, pSheetViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2, pSheetViewPage->GetObj(1)->GetLogicRect()); + } + + // Undo the shape insertion from sheet view + { + switchToSheetView(); + undo(); + + // Back to 1 object on both pages, position preserved + CPPUNIT_ASSERT_EQUAL(size_t(1), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1, pDefaultViewPage->GetObj(0)->GetLogicRect()); + + CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1, pSheetViewPage->GetObj(0)->GetLogicRect()); + } + + // Redo the shape insertion + { + redo(); + + // Back to 2 objects on both pages, positions preserved + CPPUNIT_ASSERT_EQUAL(size_t(2), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1, pDefaultViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2, pDefaultViewPage->GetObj(1)->GetLogicRect()); + + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1, pSheetViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2, pSheetViewPage->GetObj(1)->GetLogicRect()); + } + + // Move the first object from the default view + const tools::Rectangle aRectangle1Moved(1500, 1300, 3500, 2300); + { + switchToDefaultView(); + moveDrawObject(pDefaultViewPage->GetObj(0), aRectangle1Moved); + + // Default view page: first object moved, second unchanged + CPPUNIT_ASSERT_EQUAL(size_t(2), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pDefaultViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2, pDefaultViewPage->GetObj(1)->GetLogicRect()); + + // Sheet view page: same positions after sync + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pSheetViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2, pSheetViewPage->GetObj(1)->GetLogicRect()); + } + + // Move the second object from the sheet view + const tools::Rectangle aRectangle2Moved(5500, 5300, 7500, 6300); + { + switchToSheetView(); + moveDrawObject(pDefaultViewPage->GetObj(1), aRectangle2Moved); + + // Default view page: both objects at moved positions + CPPUNIT_ASSERT_EQUAL(size_t(2), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pDefaultViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2Moved, pDefaultViewPage->GetObj(1)->GetLogicRect()); + + // Sheet view page: same position as in default view page + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pSheetViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2Moved, pSheetViewPage->GetObj(1)->GetLogicRect()); + } + + // Delete the second object from the default view + { + switchToDefaultView(); + deleteDrawObject(pDefaultViewPage->GetObj(1)); + + // 1 object remaining on both pages + CPPUNIT_ASSERT_EQUAL(size_t(1), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pDefaultViewPage->GetObj(0)->GetLogicRect()); + + CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pSheetViewPage->GetObj(0)->GetLogicRect()); + } + + // Undo the delete + { + undo(); + + // Both objects restored on both pages + CPPUNIT_ASSERT_EQUAL(size_t(2), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pDefaultViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2Moved, pDefaultViewPage->GetObj(1)->GetLogicRect()); + + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pSheetViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2Moved, pSheetViewPage->GetObj(1)->GetLogicRect()); + } + + // Delete the first object from the sheet view + { + switchToSheetView(); + deleteDrawObject(pDefaultViewPage->GetObj(0)); + + // 1 object remaining on both pages + CPPUNIT_ASSERT_EQUAL(size_t(1), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle2Moved, pDefaultViewPage->GetObj(0)->GetLogicRect()); + + CPPUNIT_ASSERT_EQUAL(size_t(1), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle2Moved, pSheetViewPage->GetObj(0)->GetLogicRect()); + } + + // Undo the delete from sheet view + { + undo(); + + // Both objects restored on both pages + CPPUNIT_ASSERT_EQUAL(size_t(2), pDefaultViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pDefaultViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2Moved, pDefaultViewPage->GetObj(1)->GetLogicRect()); + + CPPUNIT_ASSERT_EQUAL(size_t(2), pSheetViewPage->GetObjCount()); + CPPUNIT_ASSERT_EQUAL(aRectangle1Moved, pSheetViewPage->GetObj(0)->GetLogicRect()); + CPPUNIT_ASSERT_EQUAL(aRectangle2Moved, pSheetViewPage->GetObj(1)->GetLogicRect()); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_InsertSparklines_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + // Set up data for sparklines in A1:A3 + rDocument.SetValue(ScAddress(0, 0, 0), 1.0); + rDocument.SetValue(ScAddress(0, 1, 0), 5.0); + rDocument.SetValue(ScAddress(0, 2, 0), 3.0); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + // Insert sparkline from default view: data A1:A3, sparkline at B1 + { + switchToDefaultView(); + + auto pSparklineGroup = std::make_shared(); + pDocShell->GetDocFunc().InsertSparklines(ScRange(0, 0, 0, 0, 2, 0), + ScRange(1, 0, 0, 1, 0, 0), pSparklineGroup); + + // Verify on default view + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 0, 0))); + + // Verify synced to sheet view + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 0, nSheetViewTab))); + } + + // Insert sparkline from sheet view: data A1:A3, sparkline at B2 + { + switchToSheetView(); + + auto pSparklineGroup = std::make_shared(); + pDocShell->GetDocFunc().InsertSparklines(ScRange(0, 0, nSheetViewTab, 0, 2, nSheetViewTab), + ScRange(1, 1, nSheetViewTab, 1, 1, nSheetViewTab), + pSparklineGroup); + + // Verify on default view + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 1, 0))); + + // Verify synced to sheet view + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 1, nSheetViewTab))); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_ChangeSparkline_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + // Set up data for sparklines + rDocument.SetValue(ScAddress(0, 0, 0), 1.0); + rDocument.SetValue(ScAddress(0, 1, 0), 5.0); + rDocument.SetValue(ScAddress(0, 2, 0), 3.0); + rDocument.SetValue(ScAddress(2, 0, 0), 10.0); + rDocument.SetValue(ScAddress(2, 1, 0), 20.0); + rDocument.SetValue(ScAddress(2, 2, 0), 30.0); + + // Create a sparkline at B1 with data A1:A3 + auto pSparklineGroup = std::make_shared(); + rDocument.CreateSparkline(ScAddress(1, 0, 0), pSparklineGroup); + { + ScRangeList aDataRange; + aDataRange.push_back(ScRange(0, 0, 0, 0, 2, 0)); + auto pSparkline = rDocument.GetSparkline(ScAddress(1, 0, 0)); + pSparkline->setInputRange(aDataRange); + } + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + // Change sparkline data range from default view: A1:A3 -> C1:C3 + { + switchToDefaultView(); + + auto pSparkline = rDocument.GetSparkline(ScAddress(1, 0, 0)); + CPPUNIT_ASSERT(pSparkline); + + ScRangeList aNewDataRange; + aNewDataRange.push_back(ScRange(2, 0, 0, 2, 2, 0)); + pDocShell->GetDocFunc().ChangeSparkline(pSparkline, 0, aNewDataRange); + + // Verify input range changed on default view + ScRangeList aInputRange = pSparkline->getInputRange(); + CPPUNIT_ASSERT_EQUAL(size_t(1), aInputRange.size()); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), aInputRange[0].aStart.Col()); + + // Verify synced to sheet view + auto pSheetViewSparkline = rDocument.GetSparkline(ScAddress(1, 0, nSheetViewTab)); + CPPUNIT_ASSERT(pSheetViewSparkline); + ScRangeList aSheetViewInputRange = pSheetViewSparkline->getInputRange(); + CPPUNIT_ASSERT_EQUAL(size_t(1), aSheetViewInputRange.size()); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), aSheetViewInputRange[0].aStart.Col()); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DeleteSparkline_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + // Create sparklines at B1 and B2 + auto pSparklineGroup = std::make_shared(); + rDocument.CreateSparkline(ScAddress(1, 0, 0), pSparklineGroup); + rDocument.CreateSparkline(ScAddress(1, 1, 0), pSparklineGroup); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + // Verify sparklines exist on both views + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 0, 0))); + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 1, 0))); + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 0, nSheetViewTab))); + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 1, nSheetViewTab))); + + // Delete sparkline at B1 from default view + { + switchToDefaultView(); + + bool bResult = pDocShell->GetDocFunc().DeleteSparkline(ScAddress(1, 0, 0)); + CPPUNIT_ASSERT(bResult); + + // Verify deleted on default view + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 0, 0))); + + // Verify synced to sheet view + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 0, nSheetViewTab))); + } + + // Delete sparkline at B2 from sheet view + { + switchToSheetView(); + + bool bResult = pDocShell->GetDocFunc().DeleteSparkline(ScAddress(1, 1, nSheetViewTab)); + CPPUNIT_ASSERT(bResult); + + // Verify deleted on default view + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 1, 0))); + + // Verify synced to sheet view + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 1, nSheetViewTab))); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_GroupUngroupSparklines_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + // Create two sparklines in different groups at B1 and B2 + auto pGroup1 = std::make_shared(); + auto pGroup2 = std::make_shared(); + rDocument.CreateSparkline(ScAddress(1, 0, 0), pGroup1); + rDocument.CreateSparkline(ScAddress(1, 1, 0), pGroup2); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + // Verify sparklines are in different groups initially + { + auto pSparkline1 = rDocument.GetSparkline(ScAddress(1, 0, 0)); + auto pSparkline2 = rDocument.GetSparkline(ScAddress(1, 1, 0)); + CPPUNIT_ASSERT(pSparkline1->getSparklineGroup() != pSparkline2->getSparklineGroup()); + } + + // Group sparklines from default view: B1:B2 into pGroup1 + { + switchToDefaultView(); + + pDocShell->GetDocFunc().GroupSparklines(ScRange(1, 0, 0, 1, 1, 0), pGroup1); + + // Verify both sparklines are in the same group on default view + auto pSparkline1 = rDocument.GetSparkline(ScAddress(1, 0, 0)); + auto pSparkline2 = rDocument.GetSparkline(ScAddress(1, 1, 0)); + CPPUNIT_ASSERT_EQUAL(pSparkline1->getSparklineGroup(), pSparkline2->getSparklineGroup()); + + // Verify synced to sheet view + auto pSheetViewSparkline1 = rDocument.GetSparkline(ScAddress(1, 0, nSheetViewTab)); + auto pSheetViewSparkline2 = rDocument.GetSparkline(ScAddress(1, 1, nSheetViewTab)); + CPPUNIT_ASSERT_EQUAL(pSheetViewSparkline1->getSparklineGroup(), + pSheetViewSparkline2->getSparklineGroup()); + } + + // Ungroup sparklines from default view: B1:B2 + { + switchToDefaultView(); + + pDocShell->GetDocFunc().UngroupSparklines(ScRange(1, 0, 0, 1, 1, 0)); + + // Verify sparklines are in different groups on default view + auto pSparkline1 = rDocument.GetSparkline(ScAddress(1, 0, 0)); + auto pSparkline2 = rDocument.GetSparkline(ScAddress(1, 1, 0)); + CPPUNIT_ASSERT(pSparkline1->getSparklineGroup() != pSparkline2->getSparklineGroup()); + + // Verify synced to sheet view + auto pSheetViewSparkline1 = rDocument.GetSparkline(ScAddress(1, 0, nSheetViewTab)); + auto pSheetViewSparkline2 = rDocument.GetSparkline(ScAddress(1, 1, nSheetViewTab)); + CPPUNIT_ASSERT(pSheetViewSparkline1->getSparklineGroup() + != pSheetViewSparkline2->getSparklineGroup()); + } + + // Group sparklines from sheet view: B1:B2 into pGroup1 + { + switchToSheetView(); + + pDocShell->GetDocFunc().GroupSparklines(ScRange(1, 0, nSheetViewTab, 1, 1, nSheetViewTab), + pGroup1); + + // Verify both sparklines are in the same group on default view + auto pSparkline1 = rDocument.GetSparkline(ScAddress(1, 0, 0)); + auto pSparkline2 = rDocument.GetSparkline(ScAddress(1, 1, 0)); + CPPUNIT_ASSERT_EQUAL(pSparkline1->getSparklineGroup(), pSparkline2->getSparklineGroup()); + + // Verify synced to sheet view + auto pSheetViewSparkline1 = rDocument.GetSparkline(ScAddress(1, 0, nSheetViewTab)); + auto pSheetViewSparkline2 = rDocument.GetSparkline(ScAddress(1, 1, nSheetViewTab)); + CPPUNIT_ASSERT_EQUAL(pSheetViewSparkline1->getSparklineGroup(), + pSheetViewSparkline2->getSparklineGroup()); + } + + // Ungroup sparklines from sheet view: B1:B2 + { + switchToSheetView(); + + pDocShell->GetDocFunc().UngroupSparklines( + ScRange(1, 0, nSheetViewTab, 1, 1, nSheetViewTab)); + + // Verify sparklines are in different groups on default view + auto pSparkline1 = rDocument.GetSparkline(ScAddress(1, 0, 0)); + auto pSparkline2 = rDocument.GetSparkline(ScAddress(1, 1, 0)); + CPPUNIT_ASSERT(pSparkline1->getSparklineGroup() != pSparkline2->getSparklineGroup()); + + // Verify synced to sheet view + auto pSheetViewSparkline1 = rDocument.GetSparkline(ScAddress(1, 0, nSheetViewTab)); + auto pSheetViewSparkline2 = rDocument.GetSparkline(ScAddress(1, 1, nSheetViewTab)); + CPPUNIT_ASSERT(pSheetViewSparkline1->getSparklineGroup() + != pSheetViewSparkline2->getSparklineGroup()); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_ChangeSparklineGroupAttributes_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + // Create a sparkline group with Column type and a sparkline at B1 + auto pSparklineGroup = std::make_shared(); + pSparklineGroup->getAttributes().setType(sc::SparklineType::Column); + rDocument.CreateSparkline(ScAddress(1, 0, 0), pSparklineGroup); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + // Change sparkline group attributes from default view: Column -> Stacked + { + switchToDefaultView(); + + sc::SparklineAttributes aNewAttributes; + aNewAttributes.setType(sc::SparklineType::Stacked); + + pDocShell->GetDocFunc().ChangeSparklineGroupAttributes(pSparklineGroup, aNewAttributes); + + // Verify on default view + CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Stacked, + pSparklineGroup->getAttributes().getType()); + + // Verify synced to sheet view + auto pSheetViewSparkline = rDocument.GetSparkline(ScAddress(1, 0, nSheetViewTab)); + CPPUNIT_ASSERT(pSheetViewSparkline); + CPPUNIT_ASSERT_EQUAL(sc::SparklineType::Stacked, + pSheetViewSparkline->getSparklineGroup()->getAttributes().getType()); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DeleteSparklineGroup_DefaultAndSheetView) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + // Create two sparkline groups with sparklines + auto pGroup1 = std::make_shared(); + auto pGroup2 = std::make_shared(); + rDocument.CreateSparkline(ScAddress(1, 0, 0), pGroup1); + rDocument.CreateSparkline(ScAddress(1, 1, 0), pGroup1); + rDocument.CreateSparkline(ScAddress(1, 2, 0), pGroup2); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + + // Delete sparkline group 1 from default view + { + switchToDefaultView(); + + bool bResult = pDocShell->GetDocFunc().DeleteSparklineGroup(pGroup1, 0); + CPPUNIT_ASSERT(bResult); + + // Verify sparklines from group 1 are gone on default view + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 0, 0))); + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 1, 0))); + // Group 2 sparkline still exists + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 2, 0))); + + // Verify synced to sheet view + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 0, nSheetViewTab))); + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 1, nSheetViewTab))); + CPPUNIT_ASSERT(rDocument.HasSparkline(ScAddress(1, 2, nSheetViewTab))); + } + + // Delete sparkline group 2 from sheet view + { + switchToSheetView(); + + bool bResult = pDocShell->GetDocFunc().DeleteSparklineGroup(pGroup2, nSheetViewTab); + CPPUNIT_ASSERT(bResult); + + // Verify all sparklines are gone on default view + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 2, 0))); + + // Verify synced to sheet view + CPPUNIT_ASSERT(!rDocument.HasSparkline(ScAddress(1, 2, nSheetViewTab))); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_InsertCells_DefaultAndSheetView) +{ + // Test sync to sheet view when inserting rows + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + // Put data below autofilter range so we can verify the row insert syncs + rDocument.SetString(ScAddress(0, 6, 0), u"ABC"_ustr); + + setupViews(); + + // Create sheet view and sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Verify initial state: range A2:A5 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Insert row before row 7 in default view (outside autofilter range) + { + switchToDefaultView(); + + sc::InsertCellsOperation aOperation( + *pDocShell, ScRange(0, 6, nDefaultViewTab, rDocument.MaxCol(), 6, nDefaultViewTab), + nullptr, INS_INSROWS_BEFORE, true, true, false, 0); + CPPUNIT_ASSERT(aOperation.run()); + + // Autofilter data unchanged in both views + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // "ABC" shifted from A7 to A8, A7 is now empty - synced to both views + CPPUNIT_ASSERT_EQUAL(u""_ustr, rDocument.GetString(ScAddress(0, 6, nDefaultViewTab))); + CPPUNIT_ASSERT_EQUAL(u"ABC"_ustr, rDocument.GetString(ScAddress(0, 7, nDefaultViewTab))); + CPPUNIT_ASSERT_EQUAL(u""_ustr, rDocument.GetString(ScAddress(0, 6, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(u"ABC"_ustr, rDocument.GetString(ScAddress(0, 7, nSheetViewTab))); + } + + // Insert row in autofilter range from default view + { + switchToDefaultView(); + + sc::InsertCellsOperation aOperation( + *pDocShell, ScRange(0, 2, nDefaultViewTab, rDocument.MaxCol(), 2, nDefaultViewTab), + nullptr, INS_INSROWS_BEFORE, true, true, false, 0); + CPPUNIT_ASSERT(aOperation.run()); + + // Default view: inserted empty row into A3 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + // Sheet view re-sorted descending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3", u"" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Auto-filter range should have expanded to A1:A6 on both views + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 5, nDefaultViewTab), + getAutoFilterArea(rDocument, nDefaultViewTab)); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nSheetViewTab, 0, 5, nSheetViewTab), + getAutoFilterArea(rDocument, nSheetViewTab)); + } + + // Insert row on sheet view in autofilter range — should be blocked + { + switchToSheetView(); + + sc::InsertCellsOperation aOperation( + *pDocShell, ScRange(0, 2, nSheetViewTab, rDocument.MaxCol(), 2, nSheetViewTab), nullptr, + INS_INSROWS_BEFORE, true, true, false, 0); + CPPUNIT_ASSERT(!aOperation.run()); + + // Values should remain unchanged + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3", u"" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Auto-filter ranges should remain unchanged + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 5, nDefaultViewTab), + getAutoFilterArea(rDocument, nDefaultViewTab)); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nSheetViewTab, 0, 5, nSheetViewTab), + getAutoFilterArea(rDocument, nSheetViewTab)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_UndoInsertCells_SheetViewSortData) +{ + // Test that undoing insert rows restores sheet view sort data + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + setupViews(); + + // Create sheet view and sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Verify initial state + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Verify sheet view has sort data + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + CPPUNIT_ASSERT(pManager); + auto& rSheetView = *pManager->iterateValidSheetViews().begin(); + CPPUNIT_ASSERT(rSheetView.getSortOrder() != nullptr); + + // Insert row in auto-filter range from default view + { + switchToDefaultView(); + sc::InsertCellsOperation aOperation( + *pDocShell, ScRange(0, 2, nDefaultViewTab, rDocument.MaxCol(), 2, nDefaultViewTab), + nullptr, INS_INSROWS_BEFORE, true, true, false, 0); + CPPUNIT_ASSERT(aOperation.run()); + } + + // Verify expanded sort range + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3", u"" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Undo the insert + { + switchToDefaultView(); + undo(); + } + + // Verify data is back to original + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view sort data should be restored - sort range should be original 4 rows + CPPUNIT_ASSERT(rSheetView.getSortOrder() != nullptr); + CPPUNIT_ASSERT(rSheetView.getSortParam() != nullptr); + + // Trigger sync by editing on default view + { + switchToDefaultView(); + typeCharsInCell(std::string("44"), 0, 1, mpTabViewDefaultView, pModelObj); + } + + // Default view: A2=44 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"44", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view should sync correctly with original sort range (descending) + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"44", u"7", u"5", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_UndoOnSheetViewDoesNotSwitchTab) +{ + // Test that undoing a cell edit on a sheet view doesn't switch the + // view to the default view tab. + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + CPPUNIT_ASSERT(nSheetViewTab != 0); + + // Type a value on the sheet view + { + switchToSheetView(); + typeCharsInCell(std::string("XyZ"), 0, 1, mpTabViewSheetView, pModelObj); + } + + // Verify we're still on the sheet view tab + CPPUNIT_ASSERT_EQUAL(nSheetViewTab, mpTabViewSheetView->GetViewData().GetTabNumber()); + + // Undo from the sheet view + { + switchToSheetView(); + undo(); + } + + // The sheet view should still be on its original tab + CPPUNIT_ASSERT_EQUAL(nSheetViewTab, mpTabViewSheetView->GetViewData().GetTabNumber()); + + // Redo from the sheet view + { + switchToSheetView(); + redo(); + } + + // Still on the sheet view tab + CPPUNIT_ASSERT_EQUAL(nSheetViewTab, mpTabViewSheetView->GetViewData().GetTabNumber()); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_AutoFilterRangeExpansionFromDefaultView) +{ + // Test that expanding a range of auto-filter when typing into the cell + // directly below the auto-filter range works as expected on default view + // and is properly synced to sheet views. Also check undo and redo works as + // expected. + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + setupViews(); + + // Create sheet view and sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + // Sort ascending on default view + { + switchToDefaultView(); + sortAscendingForCell(u"A1"); + } + + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Initial state - default view ascending, sheet view descending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Verify auto-filter range is A1:A5 + ScDBData* pDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + CPPUNIT_ASSERT(pDBData); + ScRange aDBRange; + pDBData->GetArea(aDBRange); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 4, nDefaultViewTab), aDBRange); + + // Get objects for sort data checks + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + std::shared_ptr pSheetView = rDocument.GetSheetView(nSheetViewTab); + CPPUNIT_ASSERT(pSheetView); + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + CPPUNIT_ASSERT(pManager); + + // Initial sort data + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pSheetView->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pSheetView->getSortOrder()->maSortInfo.mnLastRow); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(0), pSheetView->getSortParam()->nRow1); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pSheetView->getSortParam()->nRow2); + CPPUNIT_ASSERT(pManager->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pManager->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pManager->getSortOrder()->maSortInfo.mnLastRow); + + // Type a value in A6 on default view (below auto-filter range) + { + switchToDefaultView(); + typeCharsInCell(std::string("6"), 0, 5, mpTabViewDefaultView, pModelObj); + } + + // DB range expanded to A1:A6 + pDBData->GetArea(aDBRange); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 5, nDefaultViewTab), aDBRange); + + // Default view - ascending sorted with new value + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7", u"6" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + + // Sheet view - descending sorted with new value + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Sort data after expansion + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pSheetView->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pSheetView->getSortOrder()->maSortInfo.mnLastRow); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(0), pSheetView->getSortParam()->nRow1); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pSheetView->getSortParam()->nRow2); + CPPUNIT_ASSERT(pManager->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pManager->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pManager->getSortOrder()->maSortInfo.mnLastRow); + + // Undo the cell edit + { + switchToDefaultView(); + undo(); + } + + // DB range contracted back to A1:A5 + pDBData->GetArea(aDBRange); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 4, nDefaultViewTab), aDBRange); + + // Default view - back to ascending sorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(u""_ustr, rDocument.GetString(ScAddress(0, 5, nDefaultViewTab))); + + // Sheet view - back to descending sorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Sort data after undo + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pSheetView->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pSheetView->getSortOrder()->maSortInfo.mnLastRow); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(0), pSheetView->getSortParam()->nRow1); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pSheetView->getSortParam()->nRow2); + CPPUNIT_ASSERT(pManager->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pManager->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pManager->getSortOrder()->maSortInfo.mnLastRow); + + // Redo the cell edit + { + switchToDefaultView(); + redo(); + } + + // DB range expanded to A1:A6 again + pDBData->GetArea(aDBRange); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 5, nDefaultViewTab), aDBRange); + + // Default view - ascending sorted with new value + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7", u"6" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + + // Sheet view - descending sorted with new value + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Sort data after redo + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pSheetView->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pSheetView->getSortOrder()->maSortInfo.mnLastRow); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(0), pSheetView->getSortParam()->nRow1); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pSheetView->getSortParam()->nRow2); + CPPUNIT_ASSERT(pManager->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pManager->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pManager->getSortOrder()->maSortInfo.mnLastRow); + + // Sort the default view descending - now covers all 5 rows + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Default view - descending sorted with all 5 values + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + + // Sheet view - still descending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Edit values one at a time on the default view + + // Edit A2 + { + switchToDefaultView(); + typeCharsInCell(std::string("77"), 0, 1, mpTabViewDefaultView, pModelObj); + } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Edit A3 + { + switchToDefaultView(); + typeCharsInCell(std::string("66"), 0, 2, mpTabViewDefaultView, pModelObj); + } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Edit A4 + { + switchToDefaultView(); + typeCharsInCell(std::string("55"), 0, 3, mpTabViewDefaultView, pModelObj); + } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Edit A5 + { + switchToDefaultView(); + typeCharsInCell(std::string("44"), 0, 4, mpTabViewDefaultView, pModelObj); + } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"44", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"44", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Edit A6 + { + switchToDefaultView(); + typeCharsInCell(std::string("33"), 0, 5, mpTabViewDefaultView, pModelObj); + } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"44", u"33" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"44", u"33" }), + getValues(mpTabViewSheetView, 0, 1, 5)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_AutoFilterRangeExpansionFromSheetView) +{ + // Test that expanding a range of auto-filter when typing into the cell + // directly below the auto-filter range works as expected on sheet view + // and is properly synced to the default view. Also check undo and redo + // works as expected. + // Run the same test with different ways to set the cell value to cover + // all the paths. + + using SetCellFunc = std::function; + struct TestCase + { + SetCellFunc maSetCell; + bool mbTextCell; // is the cell value text or number + }; + + auto aTestCases = std::to_array({ + // SetNormalStringOperation + { [this](ScDocShell&, ScDocument&, ScAddress const& rPos, ScTabViewShell* pTabView, + ScModelObj* pModel) { + typeCharsInCell(std::string("6"), rPos.Col(), rPos.Row(), pTabView, pModel); + }, + false }, + // SetValueOperation + { [](ScDocShell& rDocShell, ScDocument&, ScAddress const& rPos, ScTabViewShell*, + ScModelObj*) { rDocShell.GetDocFunc().SetValueCell(rPos, 6.0, true); }, + false }, + // SetFormulaOperation + { [](ScDocShell& rDocShell, ScDocument& rDocument, ScAddress const& rPos, ScTabViewShell*, + ScModelObj*) { + rDocShell.GetDocFunc().SetFormulaCell( + rPos, new ScFormulaCell(rDocument, rPos, u"=3+3"_ustr), true); + }, + false }, + // SetStringOperation + { [](ScDocShell& rDocShell, ScDocument&, ScAddress const& rPos, ScTabViewShell*, + ScModelObj*) { rDocShell.GetDocFunc().SetStringCell(rPos, u"6"_ustr, true); }, + true }, + // SetEditTextOperation + { [](ScDocShell& rDocShell, ScDocument& rDocument, ScAddress const& rPos, ScTabViewShell*, + ScModelObj*) { + ScFieldEditEngine& rEE = rDocument.GetEditEngine(); + rEE.SetTextCurrentDefaults(u"6"_ustr); + rDocShell.GetDocFunc().SetEditCell(rPos, rEE.CreateTextObject(), true); + }, + true }, + }); + + for (auto const& rTestCase : aTestCases) + { + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + setupViews(); + + // Create sheet view and sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + // Sort ascending on default view + { + switchToDefaultView(); + sortAscendingForCell(u"A1"); + } + + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Initial state - default view ascending, sheet view descending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Verify auto-filter range is A1:A5 + ScDBData* pDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + CPPUNIT_ASSERT(pDBData); + ScRange aDBRange; + pDBData->GetArea(aDBRange); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 4, nDefaultViewTab), aDBRange); + + // Get classes for sort data checks + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + std::shared_ptr pSheetView = rDocument.GetSheetView(nSheetViewTab); + CPPUNIT_ASSERT(pSheetView); + std::shared_ptr pManager + = rDocument.GetSheetViewManager(nDefaultViewTab); + CPPUNIT_ASSERT(pManager); + + // Initial sort data + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pSheetView->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pSheetView->getSortOrder()->maSortInfo.mnLastRow); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(0), pSheetView->getSortParam()->nRow1); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pSheetView->getSortParam()->nRow2); + CPPUNIT_ASSERT(pManager->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pManager->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pManager->getSortOrder()->maSortInfo.mnLastRow); + + // Set a value in A6 on sheet view (below auto-filter range) + { + switchToSheetView(); + ScAddress aCellPos(0, 5, nSheetViewTab); + rTestCase.maSetCell(*pDocShell, rDocument, aCellPos, mpTabViewSheetView, pModelObj); + } + + // DB range expanded to A1:A6 + pDBData->GetArea(aDBRange); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 5, nDefaultViewTab), aDBRange); + + // Default view - ascending sorted with new value + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7", u"6" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + + // Sheet view - descending sorted with new value + // Text cells sort before numbers in descending order + if (rTestCase.mbTextCell) + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"6", u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + else + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Sort data valid after expansion + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pSheetView->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pSheetView->getSortOrder()->maSortInfo.mnLastRow); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(0), pSheetView->getSortParam()->nRow1); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pSheetView->getSortParam()->nRow2); + CPPUNIT_ASSERT(pManager->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pManager->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pManager->getSortOrder()->maSortInfo.mnLastRow); + + // Undo the cell edit + { + switchToSheetView(); + undo(); + } + + // DB range contracted back to A1:A5 + pDBData->GetArea(aDBRange); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 4, nDefaultViewTab), aDBRange); + + // Default view - back to ascending sorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(u""_ustr, rDocument.GetString(ScAddress(0, 5, nDefaultViewTab))); + + // Sheet view - back to descending sorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Sort data preserved after undo + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pSheetView->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pSheetView->getSortOrder()->maSortInfo.mnLastRow); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(0), pSheetView->getSortParam()->nRow1); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pSheetView->getSortParam()->nRow2); + CPPUNIT_ASSERT(pManager->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pManager->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(4), pManager->getSortOrder()->maSortInfo.mnLastRow); + + // Redo the cell edit + { + switchToSheetView(); + redo(); + } + + // DB range expanded to A1:A6 again + pDBData->GetArea(aDBRange); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 5, nDefaultViewTab), aDBRange); + + // Default view - ascending sorted with new value + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7", u"6" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + + // Sheet view - descending sorted with new value + if (rTestCase.mbTextCell) + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"6", u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + else + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Sort data preserved after redo + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pSheetView->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pSheetView->getSortOrder()->maSortInfo.mnLastRow); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(0), pSheetView->getSortParam()->nRow1); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pSheetView->getSortParam()->nRow2); + CPPUNIT_ASSERT(pManager->getSortOrder() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCROW(1), pManager->getSortOrder()->maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(5), pManager->getSortOrder()->maSortInfo.mnLastRow); + + // Sort the default view descending - now covers all 5 rows + { + switchToDefaultView(); + sortDescendingForCell(u"A1"); + } + + // Default view - descending sorted with all 5 values + // After re-sorting, text "6" becomes a number via typeCharsInCell overwrite + if (rTestCase.mbTextCell) + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"6", u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + else + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + + // Sheet view - still descending + if (rTestCase.mbTextCell) + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"6", u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + else + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Edit values one at a time on the default view + + // Edit A2 + { + switchToDefaultView(); + typeCharsInCell(std::string("77"), 0, 1, mpTabViewDefaultView, pModelObj); + } + if (rTestCase.mbTextCell) + { + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"7", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + } + else + { + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"6", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + } + + // Edit A3 + { + switchToDefaultView(); + typeCharsInCell(std::string("66"), 0, 2, mpTabViewDefaultView, pModelObj); + } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"5", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Edit A4 + { + switchToDefaultView(); + typeCharsInCell(std::string("55"), 0, 3, mpTabViewDefaultView, pModelObj); + } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"4", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Edit A5 + { + switchToDefaultView(); + typeCharsInCell(std::string("44"), 0, 4, mpTabViewDefaultView, pModelObj); + } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"44", u"3" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"44", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + // Edit A6 + { + switchToDefaultView(); + typeCharsInCell(std::string("33"), 0, 5, mpTabViewDefaultView, pModelObj); + } + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"44", u"33" }), + getValues(mpTabViewDefaultView, 0, 1, 5)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"77", u"66", u"55", u"44", u"33" }), + getValues(mpTabViewSheetView, 0, 1, 5)); + + tearDown(); + setUp(); + + } // end for loop +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_UndoDeleteCells_SheetViewSortData) +{ + // Test that undoing delete rows restores sheet view sort data + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + setupViews(); + + // Create sheet view and sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Verify initial state + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + CPPUNIT_ASSERT(pManager); + auto& rSheetView = *pManager->iterateValidSheetViews().begin(); + CPPUNIT_ASSERT(rSheetView.getSortOrder() != nullptr); + + // Delete row in auto-filter range from default view (row 3) + { + switchToDefaultView(); + sc::DeleteCellsOperation aOperation( + *pDocShell, ScRange(0, 2, nDefaultViewTab, rDocument.MaxCol(), 2, nDefaultViewTab), + nullptr, DelCellCmd::Rows, true); + CPPUNIT_ASSERT(aOperation.run()); + } + + // Verify shrunk sort range + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 3)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 3)); + + // Undo the delete + { + switchToDefaultView(); + undo(); + } + + // Verify data is back to original + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view sort data should be restored + CPPUNIT_ASSERT(rSheetView.getSortOrder() != nullptr); + CPPUNIT_ASSERT(rSheetView.getSortParam() != nullptr); + + // Trigger sync by editing on default view + { + switchToDefaultView(); + typeCharsInCell(std::string("55"), 0, 2, mpTabViewDefaultView, pModelObj); + } + + // Default view: A3=55 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"55", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view should sync correctly with original sort range (descending) + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"55", u"7", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_InsertDeleteColumns_SheetViewSortData) +{ + // Test that inserting/deleting columns in the middle of the auto-filter + // adjusts sheet view sort ranges and that undo/redo restores them. + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter_Extended.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + setupViews(); + + // Create sheet view and sort descending on column A + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Verify initial state + // Column A: default unsorted, sheet view descending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + // Column B: follows the sort + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ccc", u"rrr", u"sss", u"aaa" }), + getValues(mpTabViewDefaultView, 1, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"aaa", u"rrr", u"ccc", u"sss" }), + getValues(mpTabViewSheetView, 1, 1, 4)); + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + std::shared_ptr pSheetView = rDocument.GetSheetView(nSheetViewTab); + CPPUNIT_ASSERT(pSheetView); + + // Verify initial sort ranges + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortOrder()->maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), pSheetView->getSortOrder()->maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortParam()->nCol1); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), pSheetView->getSortParam()->nCol2); + + // Insert a column before column B (in the middle of the auto-filter) + { + switchToDefaultView(); + sc::InsertCellsOperation aOperation( + *pDocShell, ScRange(1, 0, nDefaultViewTab, 1, rDocument.MaxRow(), nDefaultViewTab), + nullptr, INS_INSCOLS_BEFORE, true, true, false, 0); + CPPUNIT_ASSERT(aOperation.run()); + } + + // Column A unchanged, original B shifted to C + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ccc", u"rrr", u"sss", u"aaa" }), + getValues(mpTabViewDefaultView, 2, 1, 4)); + // Sheet view sorted - column C has the sorted B values + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"aaa", u"rrr", u"ccc", u"sss" }), + getValues(mpTabViewSheetView, 2, 1, 4)); + + // Sort ranges should have expanded from A-C to A-D + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortOrder()->maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(3), pSheetView->getSortOrder()->maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortParam()->nCol1); + CPPUNIT_ASSERT_EQUAL(SCCOL(3), pSheetView->getSortParam()->nCol2); + + // Undo the column insert + { + switchToDefaultView(); + undo(); + } + + // Data back in original columns + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ccc", u"rrr", u"sss", u"aaa" }), + getValues(mpTabViewDefaultView, 1, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"aaa", u"rrr", u"ccc", u"sss" }), + getValues(mpTabViewSheetView, 1, 1, 4)); + + // Sort ranges should be restored to A-C + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortOrder()->maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), pSheetView->getSortOrder()->maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortParam()->nCol1); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), pSheetView->getSortParam()->nCol2); + + // Redo the column insert + { + switchToDefaultView(); + redo(); + } + + // Data shifted again - original B now in C + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ccc", u"rrr", u"sss", u"aaa" }), + getValues(mpTabViewDefaultView, 2, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"aaa", u"rrr", u"ccc", u"sss" }), + getValues(mpTabViewSheetView, 2, 1, 4)); + + // Sort ranges should be A-D again + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortOrder()->maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(3), pSheetView->getSortOrder()->maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortParam()->nCol1); + CPPUNIT_ASSERT_EQUAL(SCCOL(3), pSheetView->getSortParam()->nCol2); + + // Undo again to get back to original state for the delete test + { + switchToDefaultView(); + undo(); + } + + // Delete column B from default view + { + switchToDefaultView(); + sc::DeleteCellsOperation aOperation( + *pDocShell, ScRange(1, 0, nDefaultViewTab, 1, rDocument.MaxRow(), nDefaultViewTab), + nullptr, DelCellCmd::Cols, true); + CPPUNIT_ASSERT(aOperation.run()); + } + + // Column B deleted - original C now in B + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Sort ranges should have shrunk from A-C to A-B + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortOrder()->maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), pSheetView->getSortOrder()->maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortParam()->nCol1); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), pSheetView->getSortParam()->nCol2); + + // Undo the column delete + { + switchToDefaultView(); + undo(); + } + + // Data restored + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"ccc", u"rrr", u"sss", u"aaa" }), + getValues(mpTabViewDefaultView, 1, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"aaa", u"rrr", u"ccc", u"sss" }), + getValues(mpTabViewSheetView, 1, 1, 4)); + + // Sort ranges should be restored to A-C + CPPUNIT_ASSERT(pSheetView->getSortOrder() != nullptr); + CPPUNIT_ASSERT(pSheetView->getSortParam() != nullptr); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortOrder()->maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), pSheetView->getSortOrder()->maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), pSheetView->getSortParam()->nCol1); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), pSheetView->getSortParam()->nCol2); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DeleteCells_DefaultAndSheetView) +{ + // Test sync to sheet view when deleting rows + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + // Put data below autofilter range so we can verify the row delete syncs + rDocument.SetString(ScAddress(0, 6, 0), u"ABC"_ustr); + + setupViews(); + + // Create sheet view and sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Verify initial state - autofilter range A1:A5, data A2:A5 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 4, nDefaultViewTab), + getAutoFilterArea(rDocument, nDefaultViewTab)); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nSheetViewTab, 0, 4, nSheetViewTab), + getAutoFilterArea(rDocument, nSheetViewTab)); + + // Delete row 7 from default view (outside autofilter range) + { + switchToDefaultView(); + + sc::DeleteCellsOperation aOperation( + *pDocShell, ScRange(0, 6, nDefaultViewTab, rDocument.MaxCol(), 6, nDefaultViewTab), + nullptr, DelCellCmd::Rows, true); + CPPUNIT_ASSERT(aOperation.run()); + + // Autofilter data unchanged in both views + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // "ABC" was in A7 - now deleted on both views + CPPUNIT_ASSERT_EQUAL(u""_ustr, rDocument.GetString(ScAddress(0, 6, nDefaultViewTab))); + CPPUNIT_ASSERT_EQUAL(u""_ustr, rDocument.GetString(ScAddress(0, 6, nSheetViewTab))); + + // Autofilter range unchanged on both views (delete was outside) + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 4, nDefaultViewTab), + getAutoFilterArea(rDocument, nDefaultViewTab)); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nSheetViewTab, 0, 4, nSheetViewTab), + getAutoFilterArea(rDocument, nSheetViewTab)); + } + + // Delete row in autofilter range from default view (delete row 3) + { + switchToDefaultView(); + + sc::DeleteCellsOperation aOperation( + *pDocShell, ScRange(0, 2, nDefaultViewTab, rDocument.MaxCol(), 2, nDefaultViewTab), + nullptr, DelCellCmd::Rows, true); + CPPUNIT_ASSERT(aOperation.run()); + + // Default view: row 3 deleted, range is now A2:A4 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 3)); + // Sheet view re-sorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 3)); + + // Autofilter range should have shrunk from A1:A5 to A1:A4 on both views + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 3, nDefaultViewTab), + getAutoFilterArea(rDocument, nDefaultViewTab)); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nSheetViewTab, 0, 3, nSheetViewTab), + getAutoFilterArea(rDocument, nSheetViewTab)); + } + + // Delete row on sheet view in autofilter range - should be blocked + { + switchToSheetView(); + + sc::DeleteCellsOperation aOperation( + *pDocShell, ScRange(0, 2, nSheetViewTab, rDocument.MaxCol(), 2, nSheetViewTab), nullptr, + DelCellCmd::Rows, true); + CPPUNIT_ASSERT(!aOperation.run()); + + // Values should remain unchanged + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 3)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 3)); + + // Autofilter ranges should remain unchanged + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nDefaultViewTab, 0, 3, nDefaultViewTab), + getAutoFilterArea(rDocument, nDefaultViewTab)); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, nSheetViewTab, 0, 3, nSheetViewTab), + getAutoFilterArea(rDocument, nSheetViewTab)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_UndoSortOnSheetView) +{ + // Test case: + // - Create sheet view + // - Sort descending + // - Sort ascending + // - Undo + // - Undo + // Verify SheetView has correct sort data on each undo step + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Verify initial unsorted state on both views + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Sort descending on sheet view + { + switchToSheetView(); + sortDescendingForCell(u"A1"); + } + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + CPPUNIT_ASSERT(pManager); + auto& rSheetView = *pManager->iterateValidSheetViews().begin(); + CPPUNIT_ASSERT(rSheetView.getSortOrder() != nullptr); + CPPUNIT_ASSERT(rSheetView.getSortParam() != nullptr); + + // Sort ascending on sheet view (second sort) + { + switchToSheetView(); + sortAscendingForCell(u"A1"); + } + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Undo ascending sort - should revert to descending + { + switchToSheetView(); + undo(); + } + + // After first undo, sheet view should show descending sort + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // SheetView sort data should reflect descending sort + CPPUNIT_ASSERT(rSheetView.getSortOrder() != nullptr); + CPPUNIT_ASSERT(rSheetView.getSortParam() != nullptr); + + // Undo descending sort - should revert to original unsorted + { + switchToSheetView(); + undo(); + } + + // After second undo, sheet view data should be unsorted + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // SheetView sort data should be fully reset + CPPUNIT_ASSERT(rSheetView.getSortOrder() == nullptr); + CPPUNIT_ASSERT(rSheetView.getSortParam() == nullptr); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_UndoSortOnDefaultView) +{ + // Test: + // - create sheet view with sort + // - sort default view + // - undo default view sort + // - edit on default view + // - verify sheet view sync + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + setupViews(); + + // Create sheet view and sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Initial state: default unsorted, sheet view descending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Sort ascending on default view + { + switchToDefaultView(); + sortAscendingForCell(u"A1"); + } + + // Default view now ascending, sheet view still descending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"3", u"4", u"5", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // SheetViewManager should have sort data from the default view sort + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + CPPUNIT_ASSERT(pManager); + CPPUNIT_ASSERT(pManager->getSortOrder() != nullptr); + + // Undo the default view sort + { + switchToDefaultView(); + undo(); + } + + // Default view should be back to original order + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Default view sort data should be restored (no sort) + CPPUNIT_ASSERT(pManager->getSortOrder() == nullptr); + + // Sheet view should still be descending + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Edit a cell on the default view to trigger sync - change A2 + { + switchToDefaultView(); + typeCharsInCell(std::string("44"), 0, 1, mpTabViewDefaultView, pModelObj); + } + + // Default view: A2=44 replaces 4 + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"44", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + + // Sheet view should be synced and still sorted descending with the new value + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"44", u"7", u"5", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_RemoveAutoFilter_DefaultAndSheetView) +{ + // Test that removing auto-filter from default view removes it from sheet view + // and resets the sort data in SheetView and SheetViewManager + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + + setupViews(); + + // Create sheet view and sort descending + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Verify initial state + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Verify auto-filter exists on both views + ScDBData* pDefaultDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + CPPUNIT_ASSERT(pDefaultDBData); + CPPUNIT_ASSERT(pDefaultDBData->HasAutoFilter()); + + ScDBData* pSheetViewDBData = rDocument.GetAnonymousDBData(nSheetViewTab); + CPPUNIT_ASSERT(pSheetViewDBData); + CPPUNIT_ASSERT(pSheetViewDBData->HasAutoFilter()); + + // Verify SheetView has sort data + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + CPPUNIT_ASSERT(pManager); + CPPUNIT_ASSERT(!pManager->isEmpty()); + + auto& rSheetView = *pManager->iterateValidSheetViews().begin(); + CPPUNIT_ASSERT(rSheetView.getSortOrder() != nullptr); + CPPUNIT_ASSERT(rSheetView.getSortParam() != nullptr); + + // Remove auto-filter from default view + { + switchToDefaultView(); + gotoCell(u"A1"); + mpTabViewDefaultView->ToggleAutoFilter(); + } + + // Verify auto-filter is removed from default view + pDefaultDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + CPPUNIT_ASSERT(!pDefaultDBData || !pDefaultDBData->HasAutoFilter()); + + // Verify auto-filter is removed from sheet view + pSheetViewDBData = rDocument.GetAnonymousDBData(nSheetViewTab); + CPPUNIT_ASSERT(!pSheetViewDBData || !pSheetViewDBData->HasAutoFilter()); + + // Verify data is same in both views (unsorted, since auto-filter is gone) + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Verify SheetView sort data is reset + CPPUNIT_ASSERT(rSheetView.getSortOrder() == nullptr); + CPPUNIT_ASSERT(rSheetView.getSortParam() == nullptr); + + // Undo removing auto-filter from default view + { + switchToDefaultView(); + undo(); + } + + // Verify auto-filter is back on both views + pDefaultDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + CPPUNIT_ASSERT(pDefaultDBData); + CPPUNIT_ASSERT(pDefaultDBData->HasAutoFilter()); + + pSheetViewDBData = rDocument.GetAnonymousDBData(nSheetViewTab); + CPPUNIT_ASSERT(pSheetViewDBData); + CPPUNIT_ASSERT(pSheetViewDBData->HasAutoFilter()); + + // Verify data is restored - both views show same data + // (sort data was reset, so sheet view is no longer sorted) + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // TODO: Sort data is not restored by undo - we expect it should be. + CPPUNIT_ASSERT(rSheetView.getSortOrder() == nullptr); + CPPUNIT_ASSERT(rSheetView.getSortParam() == nullptr); + + // Redo removing auto-filter + { + switchToDefaultView(); + redo(); + } + + // Verify auto-filter is removed again from both views + pDefaultDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + CPPUNIT_ASSERT(!pDefaultDBData || !pDefaultDBData->HasAutoFilter()); + + pSheetViewDBData = rDocument.GetAnonymousDBData(nSheetViewTab); + CPPUNIT_ASSERT(!pSheetViewDBData || !pSheetViewDBData->HasAutoFilter()); + + // Verify data is unsorted on both views + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewDefaultView, 0, 1, 4)); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 4)); + + // Verify SheetView sort data is reset again + CPPUNIT_ASSERT(rSheetView.getSortOrder() == nullptr); + CPPUNIT_ASSERT(rSheetView.getSortParam() == nullptr); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_PivotTable_DefaultAndSheetView) +{ + // Test sync to sheet view when creating and updating the pivot table + + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + setupPivotTableSourceData(rDocument); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Create pivot table from default view + { + switchToDefaultView(); + + ScDPObject aDPObject = createCategoryValueDPObject( + rDocument, nDefaultViewTab, ScRange(ScAddress(4, 0, nDefaultViewTab)), + css::sheet::DataPilotFieldOrientation_ROW); + + ScDBDocFunc aDBDocFunc(*pDocShell); + bool bResult = aDBDocFunc.CreatePivotTable(aDPObject, true, true); + CPPUNIT_ASSERT(bResult); + + // Verify pivot table output on default view - cell E1 should have content + CPPUNIT_ASSERT(!rDocument.GetString(ScAddress(4, 0, nDefaultViewTab)).isEmpty()); + + // Verify the pivot table output is synced to sheet view + CPPUNIT_ASSERT_EQUAL(rDocument.GetString(ScAddress(4, 0, nDefaultViewTab)), + rDocument.GetString(ScAddress(4, 0, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(rDocument.GetString(ScAddress(4, 1, nDefaultViewTab)), + rDocument.GetString(ScAddress(4, 1, nSheetViewTab))); + } + + // Update pivot table layout: change Category from ROW to COLUMN + { + switchToDefaultView(); + + ScDPObject* pDefaultDPObject = findPivotTableOnTab(rDocument, nDefaultViewTab); + CPPUNIT_ASSERT(pDefaultDPObject); + + // Change layout: move Category to COLUMN orientation + ScDPSaveData* pSaveData = pDefaultDPObject->GetSaveData(); + CPPUNIT_ASSERT(pSaveData); + ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(u"Category"_ustr); + CPPUNIT_ASSERT(pDim); + pDim->SetOrientation(css::sheet::DataPilotFieldOrientation_COLUMN); + + ScDBDocFunc aDBDocFunc(*pDocShell); + bool bResult = aDBDocFunc.UpdatePivotTable(*pDefaultDPObject, true, true); + CPPUNIT_ASSERT(bResult); + + // Verify the sheet view pivot table has the updated COLUMN layout + ScDPObject* pSheetViewDPObject = findPivotTableOnTab(rDocument, nSheetViewTab); + CPPUNIT_ASSERT(pSheetViewDPObject); + ScDPSaveDimension* pSheetViewDim + = pSheetViewDPObject->GetSaveData()->GetDimensionByName(u"Category"_ustr); + CPPUNIT_ASSERT_EQUAL(css::sheet::DataPilotFieldOrientation_COLUMN, + pSheetViewDim->GetOrientation()); + + // Verify both pivot tables have the same layout + CPPUNIT_ASSERT_EQUAL(*pDefaultDPObject->GetSaveData(), *pSheetViewDPObject->GetSaveData()); + } + + // Update pivot table layout from sheet view: change Category from COLUMN back to ROW + { + switchToSheetView(); + + ScDPObject* pSheetViewDPObject = findPivotTableOnTab(rDocument, nSheetViewTab); + CPPUNIT_ASSERT(pSheetViewDPObject); + + // Change layout: move Category back to ROW orientation + ScDPSaveData* pSaveData = pSheetViewDPObject->GetSaveData(); + CPPUNIT_ASSERT(pSaveData); + ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(u"Category"_ustr); + CPPUNIT_ASSERT(pDim); + pDim->SetOrientation(css::sheet::DataPilotFieldOrientation_ROW); + + ScDBDocFunc aDBDocFunc(*pDocShell); + bool bResult = aDBDocFunc.UpdatePivotTable(*pSheetViewDPObject, true, true); + CPPUNIT_ASSERT(bResult); + + // Get the pivot table object again, as it can be recreated when we sync. + pSheetViewDPObject = findPivotTableOnTab(rDocument, nSheetViewTab); + CPPUNIT_ASSERT(pSheetViewDPObject); + + // Verify the default view pivot table has the updated ROW layout + ScDPObject* pDefaultDPObject = findPivotTableOnTab(rDocument, nDefaultViewTab); + CPPUNIT_ASSERT(pDefaultDPObject); + ScDPSaveDimension* pDefaultDim + = pDefaultDPObject->GetSaveData()->GetDimensionByName(u"Category"_ustr); + CPPUNIT_ASSERT_EQUAL(css::sheet::DataPilotFieldOrientation_ROW, + pDefaultDim->GetOrientation()); + +#if !defined MACOSX && !defined _WIN32 + // Verify both pivot tables have the same layout + CPPUNIT_ASSERT_EQUAL(*pDefaultDPObject->GetSaveData(), *pSheetViewDPObject->GetSaveData()); +#endif + } + + // Create pivot table from sheet view + { + switchToSheetView(); + + ScDPObject aDPObject = createCategoryValueDPObject( + rDocument, nSheetViewTab, ScRange(ScAddress(7, 0, nSheetViewTab)), + css::sheet::DataPilotFieldOrientation_ROW); + + ScDBDocFunc aDBDocFunc(*pDocShell); + bool bResult = aDBDocFunc.CreatePivotTable(aDPObject, true, true); + CPPUNIT_ASSERT(bResult); + + // Verify pivot table created on default view - cell H1 should have content + CPPUNIT_ASSERT(!rDocument.GetString(ScAddress(7, 0, nDefaultViewTab)).isEmpty()); + + // Verify the pivot table output is synced to sheet view + CPPUNIT_ASSERT_EQUAL(rDocument.GetString(ScAddress(7, 0, nDefaultViewTab)), + rDocument.GetString(ScAddress(7, 0, nSheetViewTab))); + CPPUNIT_ASSERT_EQUAL(rDocument.GetString(ScAddress(7, 1, nDefaultViewTab)), + rDocument.GetString(ScAddress(7, 1, nSheetViewTab))); + } + + // Remove first pivot table from default view + { + switchToDefaultView(); + + ScDPObject* pDefaultDPObject = findPivotTableOnTab(rDocument, nDefaultViewTab); + CPPUNIT_ASSERT(pDefaultDPObject); + + ScDBDocFunc aDBDocFunc(*pDocShell); + bool bResult = aDBDocFunc.RemovePivotTable(*pDefaultDPObject, true, true); + CPPUNIT_ASSERT(bResult); + + CPPUNIT_ASSERT_EQUAL(size_t(1), countPivotTablesOnTab(rDocument, nDefaultViewTab)); + CPPUNIT_ASSERT_EQUAL(size_t(1), countPivotTablesOnTab(rDocument, nSheetViewTab)); + } + + // Remove second pivot table from sheet view + { + switchToSheetView(); + + ScDPObject* pSheetViewDPObject = findPivotTableOnTab(rDocument, nSheetViewTab); + CPPUNIT_ASSERT(pSheetViewDPObject); + + ScDBDocFunc aDBDocFunc(*pDocShell); + bool bResult = aDBDocFunc.RemovePivotTable(*pSheetViewDPObject, true, true); + CPPUNIT_ASSERT(bResult); + + CPPUNIT_ASSERT_EQUAL(size_t(0), countPivotTablesOnTab(rDocument, nDefaultViewTab)); + CPPUNIT_ASSERT_EQUAL(size_t(0), countPivotTablesOnTab(rDocument, nSheetViewTab)); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_ReplacePivotTable_DefaultAndSheetView) +{ + // Test sync to sheet view when replacing a pivot table via DataPilotUpdate + + ScModelObj* pModelObj = createDoc("empty.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + ScDocShell* pDocShell = dynamic_cast(pModelObj->GetEmbeddedObject()); + ScDocument& rDocument = pDocShell->GetDocument(); + setupPivotTableSourceData(rDocument); + + setupViews(); + + // Create sheet view + { + switchToSheetView(); + createNewSheetViewInCurrentView(); + } + + SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber(); + SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber(); + + // Create pivot table from default view + { + switchToDefaultView(); + + ScDPObject aDPObject = createCategoryValueDPObject( + rDocument, nDefaultViewTab, ScRange(ScAddress(4, 0, nDefaultViewTab)), + css::sheet::DataPilotFieldOrientation_ROW); + + ScDBDocFunc aDBDocFunc(*pDocShell); + bool bResult = aDBDocFunc.CreatePivotTable(aDPObject, true, true); + CPPUNIT_ASSERT(bResult); + } + + // Replace pivot table from default view: change Category from ROW to COLUMN + { + switchToDefaultView(); + + ScDPObject* pDPObject = findPivotTableOnTab(rDocument, nDefaultViewTab); + CPPUNIT_ASSERT(pDPObject); + + // Build a new DPObject with modified layout + ScDPObject aNewDPObject + = createCategoryValueDPObject(rDocument, nDefaultViewTab, pDPObject->GetOutRange(), + css::sheet::DataPilotFieldOrientation_COLUMN); + + sc::ReplacePivotTableOperation aOperation(*pDocShell, pDPObject, &aNewDPObject, true, true, + false); + CPPUNIT_ASSERT(aOperation.run()); + + // Verify the sheet view pivot table has the updated COLUMN layout + ScDPObject* pSheetViewDPObject = findPivotTableOnTab(rDocument, nSheetViewTab); + CPPUNIT_ASSERT(pSheetViewDPObject); + ScDPSaveDimension* pSheetViewDim + = pSheetViewDPObject->GetSaveData()->GetDimensionByName(u"Category"_ustr); + CPPUNIT_ASSERT_EQUAL(css::sheet::DataPilotFieldOrientation_COLUMN, + pSheetViewDim->GetOrientation()); + + // Verify both pivot tables have the same layout + CPPUNIT_ASSERT_EQUAL(*pDPObject->GetSaveData(), *pSheetViewDPObject->GetSaveData()); + } + + // Replace pivot table from sheet view: change Category from COLUMN back to ROW + { + switchToSheetView(); + + ScDPObject* pSheetViewDPObject = findPivotTableOnTab(rDocument, nSheetViewTab); + CPPUNIT_ASSERT(pSheetViewDPObject); + + // Build a new DPObject with modified layout + ScDPObject aNewDPObject = createCategoryValueDPObject( + rDocument, nSheetViewTab, pSheetViewDPObject->GetOutRange(), + css::sheet::DataPilotFieldOrientation_ROW); + + sc::ReplacePivotTableOperation aOperation(*pDocShell, pSheetViewDPObject, &aNewDPObject, + true, true, false); + CPPUNIT_ASSERT(aOperation.run()); + + // Get the pivot table object again, as it can be recreated when we sync. + pSheetViewDPObject = findPivotTableOnTab(rDocument, nSheetViewTab); + CPPUNIT_ASSERT(pSheetViewDPObject); + + // Verify the default view pivot table has the updated ROW layout + ScDPObject* pDefaultDPObject = findPivotTableOnTab(rDocument, nDefaultViewTab); + CPPUNIT_ASSERT(pDefaultDPObject); + ScDPSaveDimension* pDefaultDim + = pDefaultDPObject->GetSaveData()->GetDimensionByName(u"Category"_ustr); + CPPUNIT_ASSERT_EQUAL(css::sheet::DataPilotFieldOrientation_ROW, + pDefaultDim->GetOrientation()); + + // Verify both pivot tables have the same layout + CPPUNIT_ASSERT_EQUAL(*pDefaultDPObject->GetSaveData(), *pSheetViewDPObject->GetSaveData()); + } +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_OperationInvalidatesOtherView) +{ + // Sheet view sync mutates content on the sheet view tab, so the view sitting on + // that tab must receive a tile invalidation. The reverse must also hold for the + // default view tab. + + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence()); + + comphelper::LibreOfficeKit::setPartInInvalidation(true); + comphelper::ScopeGuard aPartInvalidationGuard( + []() { comphelper::LibreOfficeKit::setPartInInvalidation(false); }); + + setupViews(); + + switchToSheetView(); + createNewSheetViewInCurrentView(); + sortDescendingForCell(u"A1"); + + CPPUNIT_ASSERT_EQUAL(SCTAB(1), mpTabViewSheetView->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(0), mpTabViewDefaultView->GetViewData().GetTabNumber()); + + // Operation on the default view tab must invalidate the sheet view tab. + { + switchToDefaultView(); + Scheduler::ProcessEventsToIdle(); + + moSheetView->ClearAllInvalids(); + moDefaultView->ClearAllInvalids(); + + gotoCell(u"A3"); + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_MESSAGE("default view tab should be repainted", + moDefaultView->m_bInvalidateTiles); + CPPUNIT_ASSERT_MESSAGE("sheet view tab should be repainted", + moSheetView->m_bInvalidateTiles); + + auto const& rSheetViewParts = moSheetView->m_aInvalidationsParts; + CPPUNIT_ASSERT_MESSAGE("sheet view callback should receive an invalidation", + std::ranges::find(rSheetViewParts, 1) != rSheetViewParts.end()); + } + + // Operation on the sheet view tab must invalidate the default view tab. + { + switchToSheetView(); + Scheduler::ProcessEventsToIdle(); + + moSheetView->ClearAllInvalids(); + moDefaultView->ClearAllInvalids(); + + gotoCell(u"A1"); + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_MESSAGE("sheet view tab should be repainted", + moSheetView->m_bInvalidateTiles); + CPPUNIT_ASSERT_MESSAGE("default view tab should be repainted", + moDefaultView->m_bInvalidateTiles); + + auto const& rDefaultViewParts = moDefaultView->m_aInvalidationsParts; + CPPUNIT_ASSERT_MESSAGE("default view callback should receive an invalidation", + std::ranges::find(rDefaultViewParts, 0) != rDefaultViewParts.end()); } } diff --git a/sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Extended.ods b/sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Extended.ods new file mode 100644 index 000000000000..fd93d5d9e9cb Binary files /dev/null and b/sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Extended.ods differ diff --git a/sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Formulas.ods b/sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Formulas.ods new file mode 100644 index 000000000000..f36104bf3079 Binary files /dev/null and b/sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Formulas.ods differ diff --git a/sc/qa/unit/tiledrendering/data/bullet-image-link.fods b/sc/qa/unit/tiledrendering/data/bullet-image-link.fods new file mode 100644 index 000000000000..ee53f179a423 --- /dev/null +++ b/sc/qa/unit/tiledrendering/data/bullet-image-link.fods @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + Cell content. + + + + + + + + First bullet with remote image + + + Second bullet with remote image + + + + + + + + + diff --git a/sc/qa/unit/tiledrendering/data/decimal-separator.ods b/sc/qa/unit/tiledrendering/data/decimal-separator.ods deleted file mode 100644 index 6f4baedd63f1..000000000000 Binary files a/sc/qa/unit/tiledrendering/data/decimal-separator.ods and /dev/null differ diff --git a/sc/qa/unit/tiledrendering/data/form-image-link.fods b/sc/qa/unit/tiledrendering/data/form-image-link.fods new file mode 100644 index 000000000000..8b56bac2a5c7 --- /dev/null +++ b/sc/qa/unit/tiledrendering/data/form-image-link.fods @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + Sheet with form image button. + + + + + + + diff --git a/sc/qa/unit/tiledrendering/data/page-background-link.fods b/sc/qa/unit/tiledrendering/data/page-background-link.fods new file mode 100644 index 000000000000..3dbcd131526a --- /dev/null +++ b/sc/qa/unit/tiledrendering/data/page-background-link.fods @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + Sheet with remote page background image. + + + + + + diff --git a/sc/qa/unit/tiledrendering/data/shape-background-link.fods b/sc/qa/unit/tiledrendering/data/shape-background-link.fods new file mode 100644 index 000000000000..02873b127171 --- /dev/null +++ b/sc/qa/unit/tiledrendering/data/shape-background-link.fods @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + Sheet with shape using remote fill image. + + + + + Rectangle with remote fill. + + + + + + diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index f860c34078c5..a3070b5c5f77 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -166,7 +167,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testPartHash) CPPUNIT_ASSERT(!pModelObj->getPartHash(it).isEmpty()); } - // check part that it does not exists + // check part that it does not exist CPPUNIT_ASSERT(pModelObj->getPartHash(100).isEmpty()); } @@ -480,7 +481,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testTextEditViews) pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::DOWN); Scheduler::ProcessEventsToIdle(); - // check that text edit view in view #1 has not be killed + // check that text edit view in view #1 has not been killed CPPUNIT_ASSERT(lcl_hasEditView(*pViewData)); } @@ -520,7 +521,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testTextEditViewInvalidations) Scheduler::ProcessEventsToIdle(); // text edit a cell in view #1 inside the new tile and - // check that view #2 receive a tile invalidate message + // check that view #2 receives a tile invalidate message aView2.m_bInvalidateTiles = false; pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); @@ -1160,6 +1161,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testLanguageStatus) // view #1 SfxViewShell* pView1 = SfxViewShell::Current(); + pView1->SetLOKLocale(u"en-US"_ustr); // view #2 int nView1 = SfxLokHelper::getCurrentView(); @@ -1653,7 +1655,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testJumpToLastRowInvalidation) CPPUNIT_ASSERT_EQUAL(tools::Rectangle(0, 13005, 26775, 261375), aView1.m_aInvalidations[0]); } -// We need to ensure that views are not perterbed by rendering (!?) hmm ... +// We need to ensure that views are not perturbed by rendering (!?) hmm ... CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testRowColumnHeaders) { ScModelObj* pModelObj = createDoc("empty.ods"); @@ -3693,6 +3695,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testLOKLanguageStatus) } { + pView->SetLOKLocale(u"en-US"_ustr); uno::Sequence aArgs( comphelper::InitPropertySequence({ { "Language", uno::Any(u"Default_English (USA)"_ustr) }, })); @@ -3739,6 +3742,233 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testPrintRanges) CPPUNIT_ASSERT_EQUAL(u"{\"printranges\":[{\"sheet\":0,\"ranges\":[[2,6,2,6]]}]}"_ustr, printRanges); } +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testThreadedCommentInsertAndResolve) +{ + comphelper::LibreOfficeKit::setTiledAnnotations(false); + // Reset the static counter so the first note gets a predictable id. + ScPostIt::mnLastPostItId = 1; + + // A scope to destroy ScTestViewCallback objects before setTiledAnnotations(true) + { + ScModelObj* pModelObj = createDoc("small.ods"); + ScTestViewCallback aView1; + + SfxLokHelper::createView(); + pModelObj->initializeForTiledRendering({}); + ScTestViewCallback aView2; + + SfxLokHelper::setView(aView1.getViewID()); + + ScTabViewShell* pTabViewShell = aView1.getTabViewShell(); + CPPUNIT_ASSERT(pTabViewShell); + pTabViewShell->SetCursor(2, 3); + + // 1) Insert a threaded comment via .uno:InsertThreadedComment + uno::Sequence aArgs(comphelper::InitPropertySequence( + { + {"Text", uno::Any(u"Threaded comment text"_ustr)}, + {"Author", uno::Any(u"Kit Author"_ustr)}, + })); + dispatchCommand(mxComponent, u".uno:InsertThreadedComment"_ustr, aArgs); + + // Both views receive KIT_CALLBACK_COMMENT with action "Add" + CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView1.m_aCommentCallbackResult.get("action")); + CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView2.m_aCommentCallbackResult.get("action")); + CPPUNIT_ASSERT_EQUAL(std::string("1"), aView1.m_aCommentCallbackResult.get("id")); + + // The callback must carry threaded-comment-specific fields + CPPUNIT_ASSERT_EQUAL(std::string("Threaded comment text"), aView1.m_aCommentCallbackResult.get("text")); + CPPUNIT_ASSERT_EQUAL(std::string("Kit Author"), aView1.m_aCommentCallbackResult.get("author")); + CPPUNIT_ASSERT_EQUAL(std::string("true"), aView1.m_aCommentCallbackResult.get("threaded")); + CPPUNIT_ASSERT_EQUAL(std::string("false"), aView1.m_aCommentCallbackResult.get("resolved")); + CPPUNIT_ASSERT_EQUAL(std::string("2 3 2 3"), aView1.m_aCommentCallbackResult.get("cellRange")); + + std::string aCommentId = aView1.m_aCommentCallbackResult.get("id"); + + // 2) Verify getPostIts() includes threaded/resolved fields + { + tools::JsonWriter aJsonWriter; + pModelObj->getPostIts(aJsonWriter); + std::string aJson(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(aJson); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + + auto aComments = aTree.get_child("comments"); + CPPUNIT_ASSERT_EQUAL(size_t(1), aComments.size()); + const auto& rComment = aComments.begin()->second; + CPPUNIT_ASSERT_EQUAL(std::string("Threaded comment text"), rComment.get("text")); + CPPUNIT_ASSERT_EQUAL(std::string("true"), rComment.get("threaded")); + CPPUNIT_ASSERT_EQUAL(std::string("false"), rComment.get("resolved")); + } + + // 3) Resolve the threaded comment via .uno:ResolveComment + aArgs = comphelper::InitPropertySequence( + { + {"Id", uno::Any(OUString::createFromAscii(aCommentId))}, + }); + dispatchCommand(mxComponent, u".uno:ResolveComment"_ustr, aArgs); + + // Both views receive KIT_CALLBACK_COMMENT with action "Modify" + CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get("action")); + CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView2.m_aCommentCallbackResult.get("action")); + CPPUNIT_ASSERT_EQUAL(std::string("true"), aView1.m_aCommentCallbackResult.get("resolved")); + + // 4) Verify getPostIts() now shows resolved=true + { + tools::JsonWriter aJsonWriter; + pModelObj->getPostIts(aJsonWriter); + std::string aJson(aJsonWriter.finishAndGetAsOString()); + std::stringstream aStream(aJson); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + + const auto& rComment = aTree.get_child("comments").begin()->second; + CPPUNIT_ASSERT_EQUAL(std::string("true"), rComment.get("resolved")); + } + + // 5) Toggle resolve back (unresolve) + dispatchCommand(mxComponent, u".uno:ResolveComment"_ustr, aArgs); + + CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get("action")); + CPPUNIT_ASSERT_EQUAL(std::string("false"), aView1.m_aCommentCallbackResult.get("resolved")); + } + comphelper::LibreOfficeKit::setTiledAnnotations(true); +} + +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testThreadedCommentDocModifiedAndUndo) +{ + // Before the fix, .uno:InsertThreadedComment manipulated the note model + // directly and never set the document-modified flag or registered undo. + comphelper::LibreOfficeKit::setTiledAnnotations(false); + ScPostIt::mnLastPostItId = 1; + + { + ScModelObj* pModelObj = createDoc("small.ods"); + ScTestViewCallback aView; + ScDocShell* pDocSh = dynamic_cast(pModelObj->GetEmbeddedObject()); + CPPUNIT_ASSERT(pDocSh); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + + ScTabViewShell* pTabViewShell = dynamic_cast(SfxViewShell::Current()); + CPPUNIT_ASSERT(pTabViewShell); + pTabViewShell->SetCursor(2, 3); + + // Fresh document: not modified, no undo actions, no note at the target cell. + CPPUNIT_ASSERT(!pDocSh->IsModified()); + SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager(); + CPPUNIT_ASSERT(pUndoMgr); + CPPUNIT_ASSERT_EQUAL(size_t(0), pUndoMgr->GetUndoActionCount()); + const ScAddress aPos(2, 3, 0); + CPPUNIT_ASSERT(!pDoc->GetNote(aPos)); + + // 1) Insert a threaded comment via .uno:InsertThreadedComment. + uno::Sequence aArgs(comphelper::InitPropertySequence( + { + {"Text", uno::Any(u"Kit thread"_ustr)}, + {"Author", uno::Any(u"Kit Author"_ustr)}, + })); + aView.m_aStateChanges.clear(); + dispatchCommand(mxComponent, u".uno:InsertThreadedComment"_ustr, aArgs); + + CPPUNIT_ASSERT(pDocSh->IsModified()); + CPPUNIT_ASSERT_EQUAL(size_t(1), pUndoMgr->GetUndoActionCount()); + + // The note exists with threaded data attached. + const ScPostIt* pNote = pDoc->GetNote(aPos); + CPPUNIT_ASSERT(pNote); + const ScThreadedCommentData* pThreaded = pNote->GetThreadedCommentData(); + CPPUNIT_ASSERT(pThreaded); + CPPUNIT_ASSERT_EQUAL(u"Kit thread"_ustr, pThreaded->maRoot.maText); + + // The bindings timer broadcasts the deferred .uno:ModifiedStatus state change. + pTabViewShell->GetViewFrame().GetBindings().GetTimer().Invoke(); + pTabViewShell->GetViewFrame().GetBindings().GetTimer().Invoke(); + auto it = aView.m_aStateChanges.find(".uno:ModifiedStatus"); + CPPUNIT_ASSERT(it != aView.m_aStateChanges.end()); + CPPUNIT_ASSERT_EQUAL(std::string("true"), it->second.get("state")); + + // 2) Undo removes the note. + dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); + CPPUNIT_ASSERT(!pDoc->GetNote(aPos)); + CPPUNIT_ASSERT_EQUAL(size_t(0), pUndoMgr->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(size_t(1), pUndoMgr->GetRedoActionCount()); + + // 3) Redo brings the note back, including the threaded payload. The undo + // action stores a clone of ScThreadedCommentData (it lives outside + // ScNoteData), so the redo path must reattach it. + dispatchCommand(mxComponent, u".uno:Redo"_ustr, {}); + pNote = pDoc->GetNote(aPos); + CPPUNIT_ASSERT(pNote); + pThreaded = pNote->GetThreadedCommentData(); + CPPUNIT_ASSERT(pThreaded); + CPPUNIT_ASSERT_EQUAL(u"Kit thread"_ustr, pThreaded->maRoot.maText); + } + + comphelper::LibreOfficeKit::setTiledAnnotations(true); +} + +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testThreadedCommentDocModifiedAndUndo2) +{ + // Sub-case: when Online dispatches the command with no Author arg or with + // an Author arg that carries an empty string, the engine must fall back to + // SvtUserOptions().GetFullName() (which carries the WOPI UserFriendlyName + // in a Kit context) rather than landing on "Unknown Author". Before the + // fix the slot's pAuthorItem ternary checked "was the arg sent" rather + // than "is the value non-empty", so an empty Author short-circuited the + // user-options fallback. + + comphelper::LibreOfficeKit::setTiledAnnotations(false); + ScPostIt::mnLastPostItId = 1; + { + SvtUserOptions aUserOpt; + const OUString aSavedFirstName = aUserOpt.GetFirstName(); + const OUString aSavedLastName = aUserOpt.GetLastName(); + aUserOpt.SetToken(UserOptToken::FirstName, u"WOPI"_ustr); + aUserOpt.SetToken(UserOptToken::LastName, u"Friendly"_ustr); + + ScModelObj* pModelObj = createDoc("small.ods"); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + ScTabViewShell* pTabViewShell = dynamic_cast(SfxViewShell::Current()); + CPPUNIT_ASSERT(pTabViewShell); + + const ScAddress aPos(4, 5, 0); + pTabViewShell->SetCursor(aPos.Col(), aPos.Row()); + + // 1) No Author arg at all: pAuthorItem == nullptr in the slot. + uno::Sequence aArgsNoAuthor(comphelper::InitPropertySequence( + { + {"Text", uno::Any(u"no author arg"_ustr)}, + })); + dispatchCommand(mxComponent, u".uno:InsertThreadedComment"_ustr, aArgsNoAuthor); + const ScPostIt* pNote = pDoc->GetNote(aPos); + CPPUNIT_ASSERT(pNote); + CPPUNIT_ASSERT_EQUAL(u"WOPI Friendly"_ustr, pNote->GetAuthor()); + + // Roll back so the next dispatch operates on a fresh cell state. + dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); + CPPUNIT_ASSERT(!pDoc->GetNote(aPos)); + + // 2) Author arg present but empty: the regression case. + uno::Sequence aArgsEmptyAuthor(comphelper::InitPropertySequence( + { + {"Text", uno::Any(u"empty author arg"_ustr)}, + {"Author", uno::Any(u""_ustr)}, + })); + dispatchCommand(mxComponent, u".uno:InsertThreadedComment"_ustr, aArgsEmptyAuthor); + pNote = pDoc->GetNote(aPos); + CPPUNIT_ASSERT(pNote); + CPPUNIT_ASSERT_EQUAL(u"WOPI Friendly"_ustr, pNote->GetAuthor()); + + aUserOpt.SetToken(UserOptToken::FirstName, aSavedFirstName); + aUserOpt.SetToken(UserOptToken::LastName, aSavedLastName); + } + + comphelper::LibreOfficeKit::setTiledAnnotations(true); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/tiledrendering/tiledrendering2.cxx b/sc/qa/unit/tiledrendering/tiledrendering2.cxx index f2b51d2f42f4..8e9f7a39113f 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering2.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering2.cxx @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #include @@ -129,28 +131,6 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testLocaleFormulaSeparator) CPPUNIT_ASSERT_EQUAL(u"0"_ustr, pDoc->GetString(addr)); } -CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testDecimalSeparatorInfo) -{ - createDoc("decimal-separator.ods"); - - ScTestViewCallback aView1; - - // Go to cell A1. - uno::Sequence aPropertyValues - = { comphelper::makePropertyValue("ToPoint", OUString("$A$1")) }; - dispatchCommand(mxComponent, ".uno:GoToCell", aPropertyValues); - - // Cell A1 has language set to English. Decimal separator should be ".". - CPPUNIT_ASSERT_EQUAL(std::string("."), aView1.decimalSeparator); - - // Go to cell B1. - aPropertyValues = { comphelper::makePropertyValue("ToPoint", OUString("B$1")) }; - dispatchCommand(mxComponent, ".uno:GoToCell", aPropertyValues); - - // Cell B1 has language set to Turkish. Decimal separator should be ",". - CPPUNIT_ASSERT_EQUAL(std::string(","), aView1.decimalSeparator); -} - CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCool11739LocaleDialogFieldUnit) { createDoc("empty.ods"); @@ -280,6 +260,93 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testBreakPageView) CPPUNIT_ASSERT_EQUAL(Color(255, 255, 255), aColor); } +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testPageBackgroundRemoteNotFetched) +{ + // Page background image with a remote URL must not fetch + // the URL during paint when link updates are not allowed. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"page-background-link.fods", aParams); + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + CPPUNIT_ASSERT(pModelObj); + pModelObj->initializeForTiledRendering({}); + + ScopedVclPtrInstance pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetOutputSizePixel(Size(1024, 768)); + pModelObj->paintTile(*pDevice, 1024, 768, 0, 0, 15360, 7680); +} + +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testShapeBackgroundRemoteNotFetched) +{ + // Shape fill bitmap with a remote URL must not fetch + // the URL during paint when link updates are not allowed. + // The assert in createNewSdrFillGraphicAttribute will fire if + // a remote fetch is attempted. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"shape-background-link.fods", aParams); + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + CPPUNIT_ASSERT(pModelObj); + + // The shape's deferred remote fill bitmap is registered as an external + // link as the shape is imported, so it appears in Edit, Links to External + // Files and can be updated or broken. + const sfx2::LinkManager* pLinkMgr = pModelObj->GetDocument()->GetLinkManager(); + CPPUNIT_ASSERT(pLinkMgr); + CPPUNIT_ASSERT_MESSAGE("shape fill bitmap link should be registered", + !pLinkMgr->GetLinks().empty()); + + pModelObj->initializeForTiledRendering({}); + + ScopedVclPtrInstance pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetOutputSizePixel(Size(1024, 768)); + pModelObj->paintTile(*pDevice, 1024, 768, 0, 0, 15360, 7680); +} + +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testBulletImageRemoteNotFetched) +{ + // text:list-level-style-image with a remote URL must not fetch + // the URL during paint when link updates are not allowed. + // Currently the editeng rendering path silently skips unresolved + // GraphicExternalLink graphics. If someone adds fetching here, + // this test should catch it. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"bullet-image-link.fods", aParams); + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + CPPUNIT_ASSERT(pModelObj); + pModelObj->initializeForTiledRendering({}); + + ScopedVclPtrInstance pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetOutputSizePixel(Size(1024, 768)); + pModelObj->paintTile(*pDevice, 1024, 768, 0, 0, 15360, 7680); +} + +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testFormImageRemoteNotFetched) +{ + // Form image button with a remote ImageURL must not fetch the + // URL during import when link updates are not allowed. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"form-image-link.fods", aParams); + ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); + CPPUNIT_ASSERT(pModelObj); + pModelObj->initializeForTiledRendering({}); + + ScopedVclPtrInstance pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetOutputSizePixel(Size(1024, 768)); + // FIXME: it fails with void DeInitVCL(): Assertion `vcl::Window::IsLOKWindowsEmpty()' failed + // pModelObj->paintTile(*pDevice, 1024, 768, 0, 0, 15360, 7680); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/types/SortOrderReverserTest.cxx b/sc/qa/unit/types/SortOrderReverserTest.cxx index 913a8db21846..850e117849ae 100644 --- a/sc/qa/unit/types/SortOrderReverserTest.cxx +++ b/sc/qa/unit/types/SortOrderReverserTest.cxx @@ -23,34 +23,50 @@ CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testUnsort) // Unchanged order - output rows should be the same as input { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 1, 2, 3, 4 }, 5, 8); + aReverser.addOrderIndices({ 0, 0, 5, 8, { 1, 2, 3, 4 }, {} }); - CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(5)); - CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(6)); - CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(7)); - CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(8)); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(5, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(6, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(7, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(8, 0)); } // Reversed order - output rows should be in reverse order than input { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 4, 3, 2, 1 }, 5, 8); + aReverser.addOrderIndices({ 0, 0, 5, 8, { 4, 3, 2, 1 }, {} }); - CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(5)); - CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(6)); - CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(7)); - CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(8)); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(5, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(6, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(7, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(8, 0)); + + // Column outside sort area - no change + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(5, 1)); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(8, 1)); + + // Row outside sort area - no change + CPPUNIT_ASSERT_EQUAL(SCROW(4), aReverser.unsort(4, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(9), aReverser.unsort(9, 0)); } // Some random order - output rows should follow the order { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 3, 1, 4, 2 }, 5, 8); + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); - CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(5)); - CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(6)); - CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(7)); - CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(8)); + CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(5, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(6, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(7, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(8, 0)); + + // Column outside sort area - no change + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(5, 1)); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(8, 1)); + + // Row outside sort area - no change + CPPUNIT_ASSERT_EQUAL(SCROW(4), aReverser.unsort(4, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(9), aReverser.unsort(9, 0)); } } @@ -59,43 +75,348 @@ CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testCombiningSortOrder) sc::SortOrderReverser aReverser; // first sorting order - aReverser.addOrderIndices({ 3, 1, 4, 2 }, 5, 8); + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); // second sorting order - only reverses the order - aReverser.addOrderIndices({ 4, 3, 2, 1 }, 5, 8); + aReverser.addOrderIndices({ 0, 0, 5, 8, { 4, 3, 2, 1 }, {} }); // check - CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(5)); - CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(6)); - CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(7)); - CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(8)); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(5, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(6, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(7, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(8, 0)); // directly compare the order std::vector aExpectedOrder{ 2, 4, 1, 3 }; - CPPUNIT_ASSERT( - std::equal(aExpectedOrder.begin(), aExpectedOrder.end(), aReverser.maOrder.begin())); + CPPUNIT_ASSERT(std::equal(aExpectedOrder.begin(), aExpectedOrder.end(), + aReverser.maSortInfo.maOrder.begin())); } CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testResort) { { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 4, 3, 2, 1 }, 5, 8); + aReverser.addOrderIndices({ 0, 0, 5, 8, { 4, 3, 2, 1 }, {} }); - CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.resort(5)); - CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.resort(6)); - CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.resort(7)); - CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.resort(8)); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.resort(5, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.resort(6, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.resort(7, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.resort(8, 0)); } { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 3, 1, 4, 2 }, 5, 8); + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); - CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.resort(5)); - CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.resort(6)); - CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.resort(7)); - CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.resort(8)); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.resort(5, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.resort(6, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.resort(7, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.resort(8, 0)); + + // Column outside sort area - no change + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.resort(5, 1)); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.resort(8, 1)); + + // Row outside sort area - no change + CPPUNIT_ASSERT_EQUAL(SCROW(4), aReverser.resort(4, 0)); + CPPUNIT_ASSERT_EQUAL(SCROW(9), aReverser.resort(9, 0)); + } +} + +CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testInsertedRows) +{ + // Insert after sort range - no change + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.insertedRows(10, 2); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.maSortInfo.mnLastRow); + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); + // Order values unchanged + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[0]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[1]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(4), aReverser.maSortInfo.maOrder[2]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[3]); + } + + // Insert before sort range - shift the whole range + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.insertedRows(2, 3); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(11), aReverser.maSortInfo.mnLastRow); + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); + // Order values unchanged + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[0]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[1]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(4), aReverser.maSortInfo.maOrder[2]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[3]); + } + + // Insert at start of sort range - expand the range + { + sc::SortOrderReverser aReverser; + // Order {3, 1, 4, 2} + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + // Insert 1 row at row 5 + aReverser.insertedRows(5, 1); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.maSortInfo.mnFirstRow); // unchanged + CPPUNIT_ASSERT_EQUAL(SCROW(9), aReverser.maSortInfo.mnLastRow); // expanded by 1 + CPPUNIT_ASSERT_EQUAL(size_t(5), aReverser.maSortInfo.maOrder.size()); // 4 + 1 new + // Shift all >=1 by 1, append 1 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(4), aReverser.maSortInfo.maOrder[0]); // 3 -> 4 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[1]); // 1 -> 2 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(5), aReverser.maSortInfo.maOrder[2]); // 4 -> 5 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[3]); // 2 -> 3 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[4]); // new, 1 + } + + // Insert at end of sort range - expand the range + { + sc::SortOrderReverser aReverser; + // Order {3, 1, 4, 2} + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + // Insert 1 row at row 8 + aReverser.insertedRows(8, 1); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(9), aReverser.maSortInfo.mnLastRow); // expanded by 1 + CPPUNIT_ASSERT_EQUAL(size_t(5), aReverser.maSortInfo.maOrder.size()); // 4 + 1 new + // Shift all >=4 by 1, append 4 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[0]); // no change + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[1]); // no change + CPPUNIT_ASSERT_EQUAL(SCCOLROW(5), aReverser.maSortInfo.maOrder[2]); // 4 -> 5 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[3]); // no change + CPPUNIT_ASSERT_EQUAL(SCCOLROW(4), aReverser.maSortInfo.maOrder[4]); // new, 4 + } + + // Insert within sort range - expand and update order + { + sc::SortOrderReverser aReverser; + // Order {3, 1, 4, 2} + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + // Insert 2 rows at row 7 (offset 3 in 1-based = within range) + aReverser.insertedRows(7, 2); + + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(10), aReverser.maSortInfo.mnLastRow); // expanded by 2 + CPPUNIT_ASSERT_EQUAL(size_t(6), aReverser.maSortInfo.maOrder.size()); // 4 + 2 new + + // Shift all >=3 by 2, append 3 and 4 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(5), aReverser.maSortInfo.maOrder[0]); // 3 -> 5 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[1]); // no change + CPPUNIT_ASSERT_EQUAL(SCCOLROW(6), aReverser.maSortInfo.maOrder[2]); // 4 -> 6 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[3]); // no change + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[4]); // new, 3 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(4), aReverser.maSortInfo.maOrder[5]); // new, 4 + } +} + +CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testDeletedRows) +{ + // Delete after sort range - no change + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.deletedRows(10, 2); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.maSortInfo.mnLastRow); + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); + // Order values unchanged + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[0]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[1]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(4), aReverser.maSortInfo.maOrder[2]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[3]); + } + + // Delete before sort range - shift the whole range + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.deletedRows(2, 2); + CPPUNIT_ASSERT_EQUAL(SCROW(3), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.maSortInfo.mnLastRow); + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); + // Order values unchanged + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[0]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[1]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(4), aReverser.maSortInfo.maOrder[2]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[3]); + } + + // Delete overlaps start - truncate from top + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + // Delete rows 4-5: row 4 is before range, row 5 is first row in range + aReverser.deletedRows(4, 2); + CPPUNIT_ASSERT_EQUAL(SCROW(4), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.maSortInfo.mnLastRow); + CPPUNIT_ASSERT_EQUAL(size_t(3), aReverser.maSortInfo.maOrder.size()); + // Remove value 1, shift remaining by -1 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[0]); // 3 -> 2 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[1]); // 4 -> 3 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[2]); // 2 -> 1 + } + + // Delete entire sort range - clear everything + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.deletedRows(3, 8); + CPPUNIT_ASSERT_EQUAL(SCROW(0), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(0), aReverser.maSortInfo.mnLastRow); + CPPUNIT_ASSERT(aReverser.maSortInfo.maOrder.empty()); + } + + // Delete within sort range - shrink and update order + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + // Delete row 6 (offset 2 within range 5-8) + aReverser.deletedRows(6, 1); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.maSortInfo.mnLastRow); + CPPUNIT_ASSERT_EQUAL(size_t(3), aReverser.maSortInfo.maOrder.size()); + // Remove value 2 (offset 2), shift values >= 3 by -1 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[0]); // 3 -> 2 + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[1]); // unchanged + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[2]); // 4 -> 3 + } + + // Delete overlaps end - truncate from bottom + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + // Delete rows 7-10: rows 7-8 are within range, 9-10 are after + aReverser.deletedRows(7, 4); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.maSortInfo.mnLastRow); + CPPUNIT_ASSERT_EQUAL(size_t(2), aReverser.maSortInfo.maOrder.size()); + // Remove values 3 and 4 (offset 3, count 2) + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[0]); // unchanged + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[1]); // unchanged + } + + // Delete multiple rows within sort range - shrink and update order + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 0, 0, 5, 8, { 3, 1, 4, 2 }, {} }); + // Delete rows 6-7 (offsets 2-3 within range 5-8) + aReverser.deletedRows(6, 2); + CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.maSortInfo.mnFirstRow); + CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.maSortInfo.mnLastRow); + CPPUNIT_ASSERT_EQUAL(size_t(2), aReverser.maSortInfo.maOrder.size()); + // Remove values 2 and 3 (offset 2, count 2) + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[0]); // unchanged + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[1]); // 4 -> 2 + } +} + +CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testInsertedColumns) +{ + // Insert after column range - no change + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.insertedColumns(7, 2); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), aReverser.maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(5), aReverser.maSortInfo.mnLastColumn); + } + + // Insert before column range - shift the whole range + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.insertedColumns(1, 3); + CPPUNIT_ASSERT_EQUAL(SCCOL(5), aReverser.maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(8), aReverser.maSortInfo.mnLastColumn); + } + + // Insert within column range - expand end + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.insertedColumns(4, 2); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), aReverser.maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(7), aReverser.maSortInfo.mnLastColumn); + } + + // Order values unchanged in all cases (columns don't affect row order) + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.insertedColumns(1, 1); + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(3), aReverser.maSortInfo.maOrder[0]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(1), aReverser.maSortInfo.maOrder[1]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(4), aReverser.maSortInfo.maOrder[2]); + CPPUNIT_ASSERT_EQUAL(SCCOLROW(2), aReverser.maSortInfo.maOrder[3]); + } +} + +CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testDeletedColumns) +{ + // Delete after column range - no change + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.deletedColumns(7, 2); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), aReverser.maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(5), aReverser.maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); + } + + // Delete before column range - shift the whole range + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.deletedColumns(0, 2); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), aReverser.maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(3), aReverser.maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); + } + + // Delete entire column range - clear everything + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.deletedColumns(1, 6); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), aReverser.maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), aReverser.maSortInfo.mnLastColumn); + CPPUNIT_ASSERT(aReverser.maSortInfo.maOrder.empty()); + } + + // Delete overlaps start - shrink from left + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.deletedColumns(1, 2); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), aReverser.maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(4), aReverser.maSortInfo.mnLastColumn); + // Order unchanged (columns don't affect row order) + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); + } + + // Delete within column range - shrink + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.deletedColumns(3, 2); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), aReverser.maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(3), aReverser.maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); + } + + // Delete overlaps end - shrink from right + { + sc::SortOrderReverser aReverser; + aReverser.addOrderIndices({ 2, 5, 5, 8, { 3, 1, 4, 2 }, {} }); + aReverser.deletedColumns(4, 3); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), aReverser.maSortInfo.mnFirstColumn); + CPPUNIT_ASSERT_EQUAL(SCCOL(3), aReverser.maSortInfo.mnLastColumn); + CPPUNIT_ASSERT_EQUAL(size_t(4), aReverser.maSortInfo.maOrder.size()); } } diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 2f3a9ced13ef..87be0c5cd500 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -42,8 +43,10 @@ #include #include +#include #include #include +#include #include @@ -876,6 +879,28 @@ CPPUNIT_TEST_FIXTURE(Test, testDataEntries) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(Test, testTdf158326_GermanEszett) +{ + m_pDoc->InsertTab(0, u"Test"_ustr); + + m_pDoc->SetString(ScAddress(0, 0, 0), u"Strasse"_ustr); + m_pDoc->SetString(ScAddress(0, 1, 0), u"Straße"_ustr); + m_pDoc->SetString(ScAddress(0, 2, 0), u"STRASSE"_ustr); + + ScFilterEntries aFilterEntries; + m_pDoc->GetFilterEntriesArea(0, 0, 2, 0, /*bCaseSens*/ false, aFilterEntries); + + // Without the fix in place, this test would have failed with + // - Expected: 2 + // - Actual : 1 + // i.e. the German "ß" would have been folded to "ss" leaving just a single entry + CPPUNIT_ASSERT_EQUAL(size_t(2), aFilterEntries.size()); + CPPUNIT_ASSERT_EQUAL(u"Strasse"_ustr, aFilterEntries.maStrData[0].GetString()); + CPPUNIT_ASSERT_EQUAL(u"Straße"_ustr, aFilterEntries.maStrData[1].GetString()); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(Test, testSelectionFunction) { /** @@ -1560,7 +1585,7 @@ bool broadcasterShifted(const ScDocument& rDoc, const ScAddress& rFrom, const Sc return true; } -formula::FormulaToken* getSingleRefToken(ScDocument& rDoc, const ScAddress& rPos) +ScSingleRefToken* getSingleRefToken(ScDocument& rDoc, const ScAddress& rPos) { ScFormulaCell* pFC = rDoc.GetFormulaCell(rPos); if (!pFC) @@ -1583,16 +1608,16 @@ formula::FormulaToken* getSingleRefToken(ScDocument& rDoc, const ScAddress& rPos return nullptr; } - return pToken; + return static_cast(pToken); } bool checkRelativeRefToken(ScDocument& rDoc, const ScAddress& rPos, SCCOL nRelCol, SCROW nRelRow) { - formula::FormulaToken* pToken = getSingleRefToken(rDoc, rPos); + auto pToken = getSingleRefToken(rDoc, rPos); if (!pToken) return false; - ScSingleRefData& rRef = *pToken->GetSingleRef(); + ScSingleRefData& rRef = pToken->GetSingleRef(); if (!rRef.IsColRel() || rRef.Col() != nRelCol) { std::cerr << "Unexpected relative column address." << std::endl; @@ -1610,11 +1635,11 @@ bool checkRelativeRefToken(ScDocument& rDoc, const ScAddress& rPos, SCCOL nRelCo bool checkDeletedRefToken(ScDocument& rDoc, const ScAddress& rPos) { - formula::FormulaToken* pToken = getSingleRefToken(rDoc, rPos); + auto pToken = getSingleRefToken(rDoc, rPos); if (!pToken) return false; - ScSingleRefData& rRef = *pToken->GetSingleRef(); + ScSingleRefData& rRef = pToken->GetSingleRef(); if (!rRef.IsDeleted()) { std::cerr << "Deleted reference is expected, but it's still a valid reference." << std::endl; @@ -1969,13 +1994,12 @@ CPPUNIT_TEST_FIXTURE(Test, testNamedRange) CPPUNIT_ASSERT_MESSAGE("Failed to insert range names.", bSuccess); m_pDoc->SetRangeName(std::move(pNames)); - ScRangeName* pNewRanges = m_pDoc->GetRangeName(); - CPPUNIT_ASSERT(pNewRanges); + ScRangeName& rNewRanges = m_pDoc->GetRangeName(); // Make sure the index lookup does the right thing. for (const auto& rName : aNames) { - const ScRangeData* p = pNewRanges->findByIndex(rName.mnIndex); + const ScRangeData* p = rNewRanges.findByIndex(rName.mnIndex); CPPUNIT_ASSERT_MESSAGE("lookup of range name by index failed.", p); OUString aName = p->GetName(); CPPUNIT_ASSERT_MESSAGE("wrong range name is retrieved.", aName.equalsAscii(rName.mpName)); @@ -1989,12 +2013,12 @@ CPPUNIT_TEST_FIXTURE(Test, testNamedRange) ASSERT_DOUBLES_EQUAL_MESSAGE ("calculation failed", 1.0, result); // Test copy-ability of range names. - std::unique_ptr pCopiedRanges(new ScRangeName(*pNewRanges)); + std::unique_ptr pCopiedRanges(new ScRangeName(rNewRanges)); m_pDoc->SetRangeName(std::move(pCopiedRanges)); // Make sure the index lookup still works. for (const auto& rName : aNames) { - const ScRangeData* p = m_pDoc->GetRangeName()->findByIndex(rName.mnIndex); + const ScRangeData* p = m_pDoc->GetRangeName().findByIndex(rName.mnIndex); CPPUNIT_ASSERT_MESSAGE("lookup of range name by index failed with the copied instance.", p); OUString aName = p->GetName(); CPPUNIT_ASSERT_MESSAGE("wrong range name is retrieved with the copied instance.", aName.equalsAscii(rName.mpName)); @@ -2006,10 +2030,10 @@ CPPUNIT_TEST_FIXTURE(Test, testNamedRange) ScRangeData* pLocal3 = new ScRangeData( *m_pDoc, u"local3"_ustr, u"Sheet1.$A$1"_ustr); ScRangeData* pLocal4 = new ScRangeData( *m_pDoc, u"local4"_ustr, u"$A$1"_ustr); // implicit relative sheet reference std::unique_ptr pLocalRangeName1(new ScRangeName); - pLocalRangeName1->insert(pLocal1); - pLocalRangeName1->insert(pLocal2); - pLocalRangeName1->insert(pLocal3); - pLocalRangeName1->insert(pLocal4); + pLocalRangeName1->insert(std::unique_ptr(pLocal1)); + pLocalRangeName1->insert(std::unique_ptr(pLocal2)); + pLocalRangeName1->insert(std::unique_ptr(pLocal3)); + pLocalRangeName1->insert(std::unique_ptr(pLocal4)); m_pDoc->SetRangeName(0, std::move(pLocalRangeName1)); CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc->InsertTab (1, u"Sheet2"_ustr)); @@ -2029,6 +2053,43 @@ CPPUNIT_TEST_FIXTURE(Test, testNamedRange) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(Test, testNamedRangeRedefinedKeepsTheSameEntry) +{ + CPPUNIT_ASSERT(m_pDoc->InsertTab(0, u"Sheet1"_ustr)); + + ScRangeName& rNames = m_pDoc->GetRangeName(); + + // the xls import assigns the index itself before it hands the name over + std::unique_ptr pFirst( + new ScRangeData(*m_pDoc, u"MyRange"_ustr, u"$Sheet1.$A$1:$A$10"_ustr)); + pFirst->SetIndex(4); + ScRangeData* pInserted = rNames.insert(std::move(pFirst)); + CPPUNIT_ASSERT(pInserted); + + // a second definition of the same name arrives, under a different index + std::unique_ptr pSecond( + new ScRangeData(*m_pDoc, u"MyRange"_ustr, u"$Sheet1.$B$1:$B$20"_ustr)); + pSecond->SetIndex(7); + ScRangeData* pSurvivor = rNames.insert(std::move(pSecond)); + + // a pointer taken from the first insert still addresses the live entry + CPPUNIT_ASSERT_EQUAL(pInserted, pSurvivor); + CPPUNIT_ASSERT_EQUAL(size_t(1), rNames.size()); + + // and that entry holds the later definition + ScRange aRange; + CPPUNIT_ASSERT(pSurvivor->IsReference(aRange)); + CPPUNIT_ASSERT_EQUAL(ScRange(1, 0, 0, 1, 19, 0), aRange); + + // the later index reaches the entry, the earlier one reaches nothing + CPPUNIT_ASSERT_EQUAL(sal_uInt16(7), pSurvivor->GetIndex()); + CPPUNIT_ASSERT_EQUAL(pSurvivor, rNames.findByIndex(7)); + CPPUNIT_ASSERT(!rNames.findByIndex(4)); + + m_pDoc->SetRangeName(nullptr); + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(Test, testInsertNameList) { m_pDoc->InsertTab(0, u"Test"_ustr); @@ -2814,6 +2875,7 @@ CPPUNIT_TEST_FIXTURE(Test, testFunctionLists) "ISNONTEXT", "ISNUMBER", "ISODD", + "ISOMITTED", "ISREF", "ISTEXT", "N", @@ -2917,15 +2979,21 @@ CPPUNIT_TEST_FIXTURE(Test, testFunctionLists) }; const char* aArray[] = { + "BYCOL", + "BYROW", "FOURIER", "FREQUENCY", "GROWTH", "LINEST", "LOGEST", + "MAKEARRAY", + "MAP", "MDETERM", "MINVERSE", "MMULT", "MUNIT", + "REDUCE", + "SCAN", "SEQUENCE", "SUMPRODUCT", "SUMX2MY2", @@ -3111,6 +3179,7 @@ CPPUNIT_TEST_FIXTURE(Test, testFunctionLists) "HYPERLINK", "INDEX", "INDIRECT", + "LAMBDA", "LET", "LOOKUP", "MATCH", @@ -3138,6 +3207,7 @@ CPPUNIT_TEST_FIXTURE(Test, testFunctionLists) const char* aText[] = { "ARABIC", + "ARRAYTOTEXT", "ASC", "BAHTTEXT", "BASE", @@ -4218,8 +4288,8 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf98642) ScRangeData* pName2 = new ScRangeData( *m_pDoc, u"name2"_ustr, u"$Sheet1.$A$1"_ustr); std::unique_ptr pGlobalRangeName(new ScRangeName()); - pGlobalRangeName->insert(pName1); - pGlobalRangeName->insert(pName2); + pGlobalRangeName->insert(std::unique_ptr(pName1)); + pGlobalRangeName->insert(std::unique_ptr(pName2)); m_pDoc->SetRangeName(std::move(pGlobalRangeName)); m_pDoc->SetString(1, 0, 0, u"=name1"_ustr); @@ -4511,6 +4581,40 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf106137_UnicodeEscapeInReplacement) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(Test, testSearchCellsIgnoreDiacritics) +{ + m_pDoc->InsertTab(0, u"Test"_ustr); + + // The same two letters, written with a precomposed accented character and + // with a base letter followed by a combining mark. + m_pDoc->SetString(ScAddress(0,0,0), u"a\u00e1"_ustr); + m_pDoc->SetString(ScAddress(0,1,0), u"a\u0061\u0308"_ustr); + + SvxSearchItem aItem(SID_SEARCH_ITEM); + aItem.SetSearchString(u"aa"_ustr); + aItem.SetCommand(SvxSearchCmd::FIND_ALL); + aItem.SetTransliterationFlags(TransliterationFlags::IGNORE_DIACRITICS_CTL); + ScMarkData aMarkData(m_pDoc->GetSheetLimits()); + aMarkData.SelectOneTable(0); + SCCOL nCol = 0; + SCROW nRow = 0; + SCTAB nTab = 0; + ScRangeList aMatchedRanges; + OUString aUndoStr; + bool bMatchedRangesWereClamped = false; + bool bSuccess = m_pDoc->SearchAndReplace(aItem, nCol, nRow, nTab, aMarkData, aMatchedRanges, + aUndoStr, nullptr, bMatchedRangesWereClamped); + + // A search that ignores diacritics finds both spellings. Without the + // accompanying fix only the second cell was found, because the accent of + // the first one was still compared. + CPPUNIT_ASSERT(bSuccess); + CPPUNIT_ASSERT(aMatchedRanges.Contains(ScRange(ScAddress(0,0,0)))); + CPPUNIT_ASSERT(aMatchedRanges.Contains(ScRange(ScAddress(0,1,0)))); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(Test, testFormulaPosition) { m_pDoc->InsertTab(0, u"Test"_ustr); @@ -4551,7 +4655,7 @@ bool hasRange(const ScDocument* pDoc, const std::vector& rRefTokens, { case formula::svSingleRef: { - ScSingleRefData aData = *p->GetSingleRef(); + ScSingleRefData aData = static_cast(p.get())->GetSingleRef(); if (rRange.aStart != rRange.aEnd) break; @@ -4562,7 +4666,7 @@ bool hasRange(const ScDocument* pDoc, const std::vector& rRefTokens, break; case formula::svDoubleRef: { - ScComplexRefData aData = *p->GetDoubleRef(); + ScComplexRefData aData = static_cast(p.get())->GetDoubleRef(); ScRange aThis = aData.toAbs(*pDoc, rPos); if (aThis == rRange) return true; @@ -5169,6 +5273,111 @@ CPPUNIT_TEST_FIXTURE(Test, testNoteDefaultStyle) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(Test, testNoteThreadedCommentData) +{ + m_pDoc->InsertTab(0, u"PostIts"_ustr); + m_pDoc->InitDrawLayer(m_xDocShell.get()); + + ScAddress aPos(0, 0, 0); + ScPostIt* pNote = m_pDoc->GetOrCreateNote(aPos); + pNote->SetText(aPos, u"Hello"_ustr); + pNote->SetAuthor(u"Author"_ustr); + + // Initially not resolved (no threaded data). + CPPUNIT_ASSERT(!pNote->IsResolved()); + CPPUNIT_ASSERT(!pNote->GetThreadedCommentData()); + + // SetResolved creates threaded data on demand. + pNote->SetResolved(true); + CPPUNIT_ASSERT(pNote->IsResolved()); + CPPUNIT_ASSERT(pNote->GetThreadedCommentData()); + CPPUNIT_ASSERT(pNote->GetThreadedCommentData()->mbDone); + + // SetResolved(false) clears the flag but keeps the data. + pNote->SetResolved(false); + CPPUNIT_ASSERT(!pNote->IsResolved()); + CPPUNIT_ASSERT(pNote->GetThreadedCommentData()); + CPPUNIT_ASSERT(!pNote->GetThreadedCommentData()->mbDone); + + // Set full threaded comment data. + auto pData = std::make_unique(); + pData->maRoot.maGuid = u"{11111111-1111-1111-1111-111111111111}"_ustr; + pData->maRoot.maPersonId = u"{AAAA}"_ustr; + pData->maRoot.maDateTime = u"2026-04-07T12:00:00Z"_ustr; + pData->mbDone = true; + + ScThreadedCommentEntry aReply; + aReply.maGuid = u"{22222222-2222-2222-2222-222222222222}"_ustr; + aReply.maPersonId = u"{BBBB}"_ustr; + aReply.maText = u"Reply text"_ustr; + pData->maReplies.push_back(aReply); + + pNote->SetThreadedCommentData(std::move(pData)); + CPPUNIT_ASSERT(pNote->IsResolved()); + CPPUNIT_ASSERT_EQUAL(size_t(1), pNote->GetThreadedCommentData()->maReplies.size()); + CPPUNIT_ASSERT_EQUAL(u"Reply text"_ustr, pNote->GetThreadedCommentData()->maReplies[0].maText); + + // Clone preserves threaded data. + std::unique_ptr pClone = pNote->Clone(aPos, *m_pDoc, ScAddress(1, 0, 0), true); + CPPUNIT_ASSERT(pClone->IsResolved()); + CPPUNIT_ASSERT(pClone->GetThreadedCommentData()); + CPPUNIT_ASSERT_EQUAL(u"{11111111-1111-1111-1111-111111111111}"_ustr, + pClone->GetThreadedCommentData()->maRoot.maGuid); + CPPUNIT_ASSERT_EQUAL(size_t(1), pClone->GetThreadedCommentData()->maReplies.size()); + + // Clone without caption also preserves threaded data. + std::unique_ptr pClone2 = pNote->Clone(aPos, *m_pDoc, ScAddress(2, 0, 0), false); + CPPUNIT_ASSERT(pClone2->IsResolved()); + CPPUNIT_ASSERT_EQUAL(u"{11111111-1111-1111-1111-111111111111}"_ustr, + pClone2->GetThreadedCommentData()->maRoot.maGuid); + + // Remove threaded data. + pNote->SetThreadedCommentData(nullptr); + CPPUNIT_ASSERT(!pNote->IsResolved()); + CPPUNIT_ASSERT(!pNote->GetThreadedCommentData()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(Test, testNotePersonList) +{ + m_pDoc->InsertTab(0, u"PostIts"_ustr); + + // Initially empty. + CPPUNIT_ASSERT(m_pDoc->GetPersonList().empty()); + + ScPersonData aPerson1; + aPerson1.maId = u"{AAAA}"_ustr; + aPerson1.maDisplayName = u"Alice"_ustr; + m_pDoc->AddPerson(aPerson1); + CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc->GetPersonList().size()); + + // Duplicate by ID is ignored. + ScPersonData aPerson1Dup; + aPerson1Dup.maId = u"{AAAA}"_ustr; + aPerson1Dup.maDisplayName = u"Alice duplicate"_ustr; + m_pDoc->AddPerson(aPerson1Dup); + CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc->GetPersonList().size()); + CPPUNIT_ASSERT_EQUAL(u"Alice"_ustr, m_pDoc->GetPersonList()[0].maDisplayName); + + // Different ID is added. + ScPersonData aPerson2; + aPerson2.maId = u"{BBBB}"_ustr; + aPerson2.maDisplayName = u"Bob"_ustr; + m_pDoc->AddPerson(aPerson2); + CPPUNIT_ASSERT_EQUAL(size_t(2), m_pDoc->GetPersonList().size()); + + // Lookup by ID. + const ScPersonData* pFound = m_pDoc->GetPersonById(u"{BBBB}"_ustr); + CPPUNIT_ASSERT(pFound); + CPPUNIT_ASSERT_EQUAL(u"Bob"_ustr, pFound->maDisplayName); + + // Unknown ID returns nullptr. + CPPUNIT_ASSERT(!m_pDoc->GetPersonById(u"{CCCC}"_ustr)); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(Test, testNoteBasic) { m_pDoc->InsertTab(0, u"PostIts"_ustr); @@ -6241,6 +6450,29 @@ CPPUNIT_TEST_FIXTURE(Test, testFormulaToValue) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(Test, testFormulaToValueUninterpreted) +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + + m_pDoc->InsertTab(0, u"Test"_ustr); + + // Nothing reads the cell after entry, so its result is not computed yet + m_pDoc->SetString(ScAddress(0, 0, 0), u"=1+1"_ustr); + const ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFC); + CPPUNIT_ASSERT(pFC->GetDirty()); + + m_xDocShell->GetDocFunc().ConvertFormulaToValue(ScRange(ScAddress(0, 0, 0)), false); + + // Without the fix in place, this test would have failed with + // - Expected: 2 + // - Actual : 0 + CPPUNIT_ASSERT_EQUAL(CELLTYPE_VALUE, m_pDoc->GetCellType(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(Test, testFormulaToValue2) { sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); @@ -7270,6 +7502,550 @@ CPPUNIT_TEST_FIXTURE(Test, testDocumentModelAccessor_getDocumentCurrencies) CPPUNIT_ASSERT_EQUAL(u"€"_ustr, aCurrencyIDs[0].aSymbol); } +CPPUNIT_TEST_FIXTURE(Test, testOverwriteContent) +{ + m_pDoc->InsertTab(0, u"Tab0"_ustr); + m_pDoc->InsertTab(1, u"Tab1"_ustr); + m_pDoc->InsertTab(2, u"Tab2"_ustr); + m_pDoc->InsertTab(3, u"Tab3"_ustr); + + // For cross table formula checking (forward and backward) + m_pDoc->SetValue(ScAddress(0, 0, 0), 99.0); // Tab0.A1 + m_pDoc->SetValue(ScAddress(0, 0, 3), 66.0); // Tab3.A1 + + std::vector> aData = { + { u"Column 1"_ustr, u"Column 2"_ustr, u"Column 3"_ustr, }, + { u"7"_ustr, u"A"_ustr, u"=A2+5"_ustr }, + { u"=2+2"_ustr, u"C"_ustr, u"=Tab3.A1"_ustr }, // forward cross-tab reference + { u"=A3-2"_ustr, u"D"_ustr, u"=SUM(A2:A6)"_ustr }, + { u"3"_ustr, u"B"_ustr, u"=C3-60"_ustr }, + { u"5"_ustr, u"E"_ustr, u"=Tab0.A1"_ustr }, // backward cross-tab reference + }; + + for (size_t i = 0; i < aData.size(); ++i) + { + for (size_t j = 0; j < aData[0].size(); ++j) + { + if (!aData[i][j].isEmpty()) + { + m_pDoc->SetString(j, i, 1, aData[i][j]); + } + } + } + m_pDoc->CalcAll(); + + // Verify Tab1 values and formulas before overwrite + { + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 1))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 1))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 1))); // A3-2=2 + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 1))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 1))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 1))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 1))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 1))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc->GetValue(ScAddress(2, 1, 1))); // =A2+5=12 + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 1))); // =Tab3.A1 + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(2, 3, 1))); // =SUM(A2:A6) + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 1))); // =C3-60 + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 1))); // =Tab0.A1 + } + + // Tab2 should be empty + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(0, 1, 2))); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(1, 2, 2))); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(2, 3, 2))); + + // Overwrite Tab2 with Tab1 content + m_pDoc->OverwriteContent(1, 2); + + // Tab1 should be unchanged + { + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 1))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 1))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 1))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 1))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 1))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 1))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 1))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 1))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc->GetValue(ScAddress(2, 1, 1))); + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 1))); + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(2, 3, 1))); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 1))); + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 1))); + } + + // Tab2 values should match Tab1 and the formulas adjusted if needed + { + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 2))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 2))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 2))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 2))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 2))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 2))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 2))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 2))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc->GetValue(ScAddress(2, 1, 2))); + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 2))); + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(2, 3, 2))); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 2))); + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 2))); + } + + // Check Tab2 formulas were copied correctly + { + CPPUNIT_ASSERT_EQUAL(u"=2+2"_ustr, m_pDoc->GetFormula(0, 2, 2)); + CPPUNIT_ASSERT_EQUAL(u"=A3-2"_ustr, m_pDoc->GetFormula(0, 3, 2)); + CPPUNIT_ASSERT_EQUAL(u"=A2+5"_ustr, m_pDoc->GetFormula(2, 1, 2)); + CPPUNIT_ASSERT_EQUAL(u"='Tab3'.A1"_ustr, m_pDoc->GetFormula(2, 2, 2)); + CPPUNIT_ASSERT_EQUAL(u"=SUM(A2:A6)"_ustr, m_pDoc->GetFormula(2, 3, 2)); + CPPUNIT_ASSERT_EQUAL(u"=C3-60"_ustr, m_pDoc->GetFormula(2, 4, 2)); + CPPUNIT_ASSERT_EQUAL(u"=Tab0.A1"_ustr, m_pDoc->GetFormula(2, 5, 2)); + } + + // Change Tab1 and see if it affects Tab2 + m_pDoc->SetValue(ScAddress(0, 1, 1), 10.0); // 7 -> 10 + m_pDoc->CalcAll(); + + // Check Tab 1 + { + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 1, 1))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 1))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 1))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 1))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 1))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 1))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 1))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 1))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(15.0, m_pDoc->GetValue(ScAddress(2, 1, 1))); + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 1))); + CPPUNIT_ASSERT_EQUAL(24.0, m_pDoc->GetValue(ScAddress(2, 3, 1))); // =SUM(A2:A6)=10+4+2+3+5 + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 1))); + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 1))); + } + + // Check Tab 2 + { + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 2))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 2))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 2))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 2))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 2))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 2))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 2))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 2))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc->GetValue(ScAddress(2, 1, 2))); + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 2))); + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(2, 3, 2))); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 2))); + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 2))); + } + + // Overwrite Tab2 again with updated Tab1 + m_pDoc->OverwriteContent(1, 2); + + // Check Tab 2 + { + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 1, 2))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 2))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 2))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 2))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 2))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 2))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 2))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 2))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(15.0, m_pDoc->GetValue(ScAddress(2, 1, 2))); + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 2))); + CPPUNIT_ASSERT_EQUAL(24.0, m_pDoc->GetValue(ScAddress(2, 3, 2))); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 2))); + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 2))); + } + + // Check formulas are still the same + { + CPPUNIT_ASSERT_EQUAL(u"=2+2"_ustr, m_pDoc->GetFormula(0, 2, 2)); + CPPUNIT_ASSERT_EQUAL(u"=A3-2"_ustr, m_pDoc->GetFormula(0, 3, 2)); + CPPUNIT_ASSERT_EQUAL(u"=A2+5"_ustr, m_pDoc->GetFormula(2, 1, 2)); + CPPUNIT_ASSERT_EQUAL(u"='Tab3'.A1"_ustr, m_pDoc->GetFormula(2, 2, 2)); + CPPUNIT_ASSERT_EQUAL(u"=SUM(A2:A6)"_ustr, m_pDoc->GetFormula(2, 3, 2)); + CPPUNIT_ASSERT_EQUAL(u"=C3-60"_ustr, m_pDoc->GetFormula(2, 4, 2)); + CPPUNIT_ASSERT_EQUAL(u"=Tab0.A1"_ustr, m_pDoc->GetFormula(2, 5, 2)); + } + + m_pDoc->DeleteTab(3); + m_pDoc->DeleteTab(2); + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(Test, testAutoFilterFlagsAfterColumnInsertUndoRedo) +{ + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Set up data - A1:C3 + m_pDoc->SetString(0, 0, 0, u"Col1"_ustr); + m_pDoc->SetString(1, 0, 0, u"Col2"_ustr); + m_pDoc->SetString(2, 0, 0, u"Col3"_ustr); + m_pDoc->SetString(0, 1, 0, u"1"_ustr); + m_pDoc->SetString(1, 1, 0, u"A"_ustr); + m_pDoc->SetString(2, 1, 0, u"X"_ustr); + m_pDoc->SetString(0, 2, 0, u"2"_ustr); + m_pDoc->SetString(1, 2, 0, u"B"_ustr); + m_pDoc->SetString(2, 2, 0, u"Y"_ustr); + + // Set up auto-filter on A1:C3 + ScDBData* pDBData = new ScDBData(u"NONAME"_ustr, 0, 0, 0, 2, 2); + m_pDoc->SetAnonymousDBData(0, std::unique_ptr(pDBData)); + pDBData->SetAutoFilter(true); + m_pDoc->ApplyFlagsTab(0, 0, 2, 0, 0, ScMF::Auto); + + // Verify initial auto-filter flags on A1:C1 + CPPUNIT_ASSERT(m_pDoc->HasAutoFilter(0, 0, 0)); + CPPUNIT_ASSERT(m_pDoc->HasAutoFilter(1, 0, 0)); + CPPUNIT_ASSERT(m_pDoc->HasAutoFilter(2, 0, 0)); + + // Insert a column before B + ScRange aColumnRange(1, 0, 0, 1, m_pDoc->MaxRow(), 0); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + aMark.SetMarkArea(aColumnRange); + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + rFunc.InsertCells(aColumnRange, &aMark, INS_INSCOLS_BEFORE, true, true); + + // After insert: auto-filter range is expanded + // The DB data range should have expanded via reference tracking + pDBData = m_pDoc->GetAnonymousDBData(0); + CPPUNIT_ASSERT(pDBData); + + ScRange aArea; + pDBData->GetArea(aArea); + // Auto-filter range should now be A1:D3 (column B was inserted) + CPPUNIT_ASSERT_EQUAL(SCCOL(0), aArea.aStart.Col()); + CPPUNIT_ASSERT_EQUAL(SCCOL(3), aArea.aEnd.Col()); + + // Check ScMF::Auto flags (A1:D1) + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(0, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(1, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(2, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(3, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(4, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(5, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + + // Undo the column insert + m_pDoc->GetUndoManager()->Undo(); + + // Back to A:C + pDBData = m_pDoc->GetAnonymousDBData(0); + CPPUNIT_ASSERT(pDBData); + pDBData->GetArea(aArea); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), aArea.aStart.Col()); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), aArea.aEnd.Col()); + + // Check ScMF::Auto flags (A1:C1) + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(0, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(1, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(2, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(3, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(4, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + + // Redo the column insert + m_pDoc->GetUndoManager()->Redo(); + + // Back to A:D + pDBData = m_pDoc->GetAnonymousDBData(0); + CPPUNIT_ASSERT(pDBData); + pDBData->GetArea(aArea); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), aArea.aStart.Col()); + CPPUNIT_ASSERT_EQUAL(SCCOL(3), aArea.aEnd.Col()); + + // Check ScMF::Auto flags (A1:D1) + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(0, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(1, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(2, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(3, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(4, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(5, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(Test, testAutoFilterFlagsAfterColumnDeleteUndoRedo) +{ + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Set up data: header in row 0, data in rows 1-2, columns A-C + m_pDoc->SetString(0, 0, 0, u"Col1"_ustr); + m_pDoc->SetString(1, 0, 0, u"Col2"_ustr); + m_pDoc->SetString(2, 0, 0, u"Col3"_ustr); + m_pDoc->SetString(0, 1, 0, u"1"_ustr); + m_pDoc->SetString(1, 1, 0, u"A"_ustr); + m_pDoc->SetString(2, 1, 0, u"X"_ustr); + m_pDoc->SetString(0, 2, 0, u"2"_ustr); + m_pDoc->SetString(1, 2, 0, u"B"_ustr); + m_pDoc->SetString(2, 2, 0, u"Y"_ustr); + + // Set up auto-filter on A1:C3 + ScDBData* pDBData = new ScDBData(u"NONAME"_ustr, 0, 0, 0, 2, 2); + m_pDoc->SetAnonymousDBData(0, std::unique_ptr(pDBData)); + pDBData->SetAutoFilter(true); + m_pDoc->ApplyFlagsTab(0, 0, 2, 0, 0, ScMF::Auto); + + // Verify initial auto-filter flags on A1:C1 + CPPUNIT_ASSERT(m_pDoc->HasAutoFilter(0, 0, 0)); + CPPUNIT_ASSERT(m_pDoc->HasAutoFilter(1, 0, 0)); + CPPUNIT_ASSERT(m_pDoc->HasAutoFilter(2, 0, 0)); + + // Delete column B + ScRange aColRange(1, 0, 0, 1, m_pDoc->MaxRow(), 0); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + aMark.SetMarkArea(aColRange); + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + rFunc.DeleteCells(aColRange, &aMark, DelCellCmd::Cols, true); + + // Auto-filter range shrunk to A:B + pDBData = m_pDoc->GetAnonymousDBData(0); + CPPUNIT_ASSERT(pDBData); + ScRange aArea; + pDBData->GetArea(aArea); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), aArea.aStart.Col()); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), aArea.aEnd.Col()); + + // Check ScMF::Auto flags (A1:B1) + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(0, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(1, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(2, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(3, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + + // Undo the column delete - column B re-inserted + m_pDoc->GetUndoManager()->Undo(); + + // Back to A:C + pDBData = m_pDoc->GetAnonymousDBData(0); + CPPUNIT_ASSERT(pDBData); + pDBData->GetArea(aArea); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), aArea.aStart.Col()); + CPPUNIT_ASSERT_EQUAL(SCCOL(2), aArea.aEnd.Col()); + + // Check ScMF::Auto flags (A1:C1) + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(0, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(1, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(2, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(3, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(4, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + + // Redo the column delete + m_pDoc->GetUndoManager()->Redo(); + + // Back to A:B + pDBData = m_pDoc->GetAnonymousDBData(0); + CPPUNIT_ASSERT(pDBData); + pDBData->GetArea(aArea); + CPPUNIT_ASSERT_EQUAL(SCCOL(0), aArea.aStart.Col()); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), aArea.aEnd.Col()); + + // Check ScMF::Auto flags (A1:B1) + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(0, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(bool(m_pDoc->GetAttr(1, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(2, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(3, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + CPPUNIT_ASSERT(!bool(m_pDoc->GetAttr(4, 0, 0, ATTR_MERGE_FLAG).GetValue() & ScMF::Auto)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(Test, testCopyTabContent) +{ + m_pDoc->InsertTab(0, u"Tab0"_ustr); + m_pDoc->InsertTab(1, u"Tab1"_ustr); + m_pDoc->InsertTab(2, u"Tab2"_ustr); + m_pDoc->InsertTab(3, u"Tab3"_ustr); + + // For cross-sheet formula checking (forward and backward) + m_pDoc->SetValue(ScAddress(0, 0, 0), 99.0); // Tab0.A1 + m_pDoc->SetValue(ScAddress(0, 0, 3), 66.0); // Tab3.A1 + + std::vector> aData = { + { u"Column 1"_ustr, u"Column 2"_ustr, u"Column 3"_ustr }, + { u"7"_ustr, u"A"_ustr, u"=A2+5"_ustr }, + { u"=2+2"_ustr, u"C"_ustr, u"=Tab3.A1"_ustr }, // forward cross-tab reference + { u"=A3-2"_ustr, u"D"_ustr, u"=SUM(A2:A6)"_ustr }, + { u"3"_ustr, u"B"_ustr, u"=C3-60"_ustr }, + { u"5"_ustr, u"E"_ustr, u"=Tab0.A1"_ustr }, // backward cross-tab reference + }; + + for (size_t i = 0; i < aData.size(); ++i) + { + for (size_t j = 0; j < aData[0].size(); ++j) + { + if (!aData[i][j].isEmpty()) + { + m_pDoc->SetString(j, i, 1, aData[i][j]); + } + } + } + m_pDoc->CalcAll(); + + // Verify Tab1 values and formulas before copy + { + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 1))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 1))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 1))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 1))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 1))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 1))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 1))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 1))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc->GetValue(ScAddress(2, 1, 1))); // =A2+5=12 + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 1))); // =Tab3.A1 + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(2, 3, 1))); // =SUM(A2:A6) + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 1))); // =C3-60 + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 1))); // =Tab0.A1 + } + + // Copy Tab1 to index 2 - Tab1_2 + m_pDoc->CopyTab(1, 2); + CPPUNIT_ASSERT_EQUAL(static_cast(5), m_pDoc->GetTableCount()); + + // Tab3 value shifted from index 3 to index 4 + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(0, 0, 4))); + // Tab0 value stays at index 0 + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + + // Tab1 (tab index 1) should be unchanged + { + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 1))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 1))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 1))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 1))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 1))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 1))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 1))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 1))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc->GetValue(ScAddress(2, 1, 1))); + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 1))); + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(2, 3, 1))); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 1))); + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 1))); + } + + // The copy Tab1_2 (tab index 2) should have the same data as Tab1 + { + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 2))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 2))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 2))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 2))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 2))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 2))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 2))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 2))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc->GetValue(ScAddress(2, 1, 2))); + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 2))); + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(2, 3, 2))); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 2))); + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 2))); + } + + // Check the formulas in Tab1_2 + { + CPPUNIT_ASSERT_EQUAL(u"=2+2"_ustr, m_pDoc->GetFormula(0, 2, 2)); + CPPUNIT_ASSERT_EQUAL(u"=A3-2"_ustr, m_pDoc->GetFormula(0, 3, 2)); + CPPUNIT_ASSERT_EQUAL(u"=A2+5"_ustr, m_pDoc->GetFormula(2, 1, 2)); + CPPUNIT_ASSERT_EQUAL(u"='Tab3'.A1"_ustr, m_pDoc->GetFormula(2, 2, 2)); + CPPUNIT_ASSERT_EQUAL(u"=SUM(A2:A6)"_ustr, m_pDoc->GetFormula(2, 3, 2)); + CPPUNIT_ASSERT_EQUAL(u"=C3-60"_ustr, m_pDoc->GetFormula(2, 4, 2)); + CPPUNIT_ASSERT_EQUAL(u"=Tab0.A1"_ustr, m_pDoc->GetFormula(2, 5, 2)); + } + + // Change Tab1 and verify the copy is independent + m_pDoc->SetValue(ScAddress(0, 1, 1), 10.0); // 7 -> 10 + m_pDoc->CalcAll(); + + // Tab1 should be changed + { + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 1, 1))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 1))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 1))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 1))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 1))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 1))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 1))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 1))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 1))); + + CPPUNIT_ASSERT_EQUAL(15.0, m_pDoc->GetValue(ScAddress(2, 1, 1))); + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 1))); + CPPUNIT_ASSERT_EQUAL(24.0, m_pDoc->GetValue(ScAddress(2, 3, 1))); // =SUM(A2:A6)=10+4+2+3+5 + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 1))); + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 1))); + } + + // No change in Tab1_2 + { + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 1, 2))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 2, 2))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 3, 2))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 4, 2))); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, m_pDoc->GetString(ScAddress(1, 1, 2))); + CPPUNIT_ASSERT_EQUAL(u"C"_ustr, m_pDoc->GetString(ScAddress(1, 2, 2))); + CPPUNIT_ASSERT_EQUAL(u"D"_ustr, m_pDoc->GetString(ScAddress(1, 3, 2))); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, m_pDoc->GetString(ScAddress(1, 4, 2))); + CPPUNIT_ASSERT_EQUAL(u"E"_ustr, m_pDoc->GetString(ScAddress(1, 5, 2))); + + CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc->GetValue(ScAddress(2, 1, 2))); + CPPUNIT_ASSERT_EQUAL(66.0, m_pDoc->GetValue(ScAddress(2, 2, 2))); + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(2, 3, 2))); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 4, 2))); + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 5, 2))); + } + + m_pDoc->DeleteTab(4); + m_pDoc->DeleteTab(3); + m_pDoc->DeleteTab(2); + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/qa/unit/ucalc_copypaste.cxx b/sc/qa/unit/ucalc_copypaste.cxx index 4d2d194819fc..8907550e3900 100644 --- a/sc/qa/unit/ucalc_copypaste.cxx +++ b/sc/qa/unit/ucalc_copypaste.cxx @@ -10,6 +10,9 @@ #include "helper/debughelper.hxx" #include "helper/qahelper.hxx" +#include +#include + #include #include #include @@ -18,7 +21,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -26,6 +31,9 @@ #include #include #include +#include +#include +#include #include @@ -254,14 +262,14 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPaste) static constexpr OUString aGlobal2Symbol(u"$Sheet1.$A$1:$A$23"_ustr); ScRangeData* pGlobal2 = new ScRangeData(*m_pDoc, u"global2"_ustr, aGlobal2Symbol); std::unique_ptr pGlobalRangeName(new ScRangeName()); - pGlobalRangeName->insert(pGlobal); - pGlobalRangeName->insert(pGlobal2); + pGlobalRangeName->insert(std::unique_ptr(pGlobal)); + pGlobalRangeName->insert(std::unique_ptr(pGlobal2)); std::unique_ptr pLocalRangeName1(new ScRangeName()); - pLocalRangeName1->insert(pLocal1); - pLocalRangeName1->insert(pLocal2); - pLocalRangeName1->insert(pLocal3); - pLocalRangeName1->insert(pLocal4); - pLocalRangeName1->insert(pLocal5); + pLocalRangeName1->insert(std::unique_ptr(pLocal1)); + pLocalRangeName1->insert(std::unique_ptr(pLocal2)); + pLocalRangeName1->insert(std::unique_ptr(pLocal3)); + pLocalRangeName1->insert(std::unique_ptr(pLocal4)); + pLocalRangeName1->insert(std::unique_ptr(pLocal5)); m_pDoc->SetRangeName(std::move(pGlobalRangeName)); m_pDoc->SetRangeName(0, std::move(pLocalRangeName1)); @@ -394,7 +402,7 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPaste) m_pDoc->CopyFromClip(aRange, aMark, InsertDeleteFlags::ALL, nullptr, &aClipDoc2); // The global2 range must not have changed. - pGlobal2 = m_pDoc->GetRangeName()->findByUpperName(u"GLOBAL2"_ustr); + pGlobal2 = m_pDoc->GetRangeName().findByUpperName(u"GLOBAL2"_ustr); CPPUNIT_ASSERT_MESSAGE("GLOBAL2 name not found", pGlobal2); OUString aSymbol = pGlobal2->GetSymbol(); CPPUNIT_ASSERT_EQUAL_MESSAGE("GLOBAL2 named range changed", aGlobal2Symbol, aSymbol); @@ -403,6 +411,90 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPaste) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPasteKeepDestProtection) +{ + // tdf#123974, tdf#150910: an interactive paste changes a cell's content, + // not whether it is locked. Copying a protected cell onto a cell the user + // explicitly unprotected must leave it editable, and this must not depend + // on whether the source spans a single row (the replicated-single-row fast + // path) or several rows (the general path) - the two used to disagree. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Source column A: two protected cells carrying values. + m_pDoc->SetValue(0, 0, 0, 1.0); + m_pDoc->SetValue(0, 1, 0, 2.0); + m_pDoc->ApplyAttr(0, 0, 0, ScProtectionAttr(true)); + m_pDoc->ApplyAttr(0, 1, 0, ScProtectionAttr(true)); + + // Targets the user explicitly unprotected by direct formatting: C1 (a + // single-row target) and D1:D2 (a multi-row target). + m_pDoc->ApplyAttr(2, 0, 0, ScProtectionAttr(false)); + m_pDoc->ApplyAttr(3, 0, 0, ScProtectionAttr(false)); + m_pDoc->ApplyAttr(3, 1, 0, ScProtectionAttr(false)); + + auto paste = [this](const ScRange& rSrc, const ScRange& rDest, bool bPreserveProtection) { + ScDocument aClipDoc(SCDOCMODE_CLIP); + copyToClip(m_pDoc, rSrc, &aClipDoc); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SetMarkArea(rDest); + m_pDoc->CopyFromClip(rDest, aMark, InsertDeleteFlags::ALL, nullptr, &aClipDoc, true, false, + true, false, nullptr, bPreserveProtection); + }; + + // Single-row source exercises the replicated-single-row fast path. + paste(ScRange(0, 0, 0, 0, 0, 0), ScRange(2, 0, 0, 2, 0, 0), /*bPreserveProtection*/ true); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(2, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("single-row paste must keep the target unprotected", + !m_pDoc->GetAttr(2, 0, 0, ATTR_PROTECTION).GetProtection()); + + // Multi-row source exercises the general path. + paste(ScRange(0, 0, 0, 0, 1, 0), ScRange(3, 0, 0, 3, 1, 0), /*bPreserveProtection*/ true); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(3, 0, 0)); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(3, 1, 0)); + CPPUNIT_ASSERT_MESSAGE("multi-row paste must keep the target unprotected (row 1)", + !m_pDoc->GetAttr(3, 0, 0, ATTR_PROTECTION).GetProtection()); + CPPUNIT_ASSERT_MESSAGE("multi-row paste must keep the target unprotected (row 2)", + !m_pDoc->GetAttr(3, 1, 0, ATTR_PROTECTION).GetProtection()); + + // The whole protection item is preserved, not just its Protected bit: an + // unprotected source pasted onto a protected + hidden-formula target keeps + // the target's own settings. + m_pDoc->SetValue(0, 5, 0, 9.0); // A6, unprotected source + m_pDoc->ApplyAttr(0, 5, 0, ScProtectionAttr(false)); + m_pDoc->ApplyAttr(2, 5, 0, ScProtectionAttr(true, /*bHideFormula*/ true)); // C6 target + paste(ScRange(0, 5, 0, 0, 5, 0), ScRange(2, 5, 0, 2, 5, 0), /*bPreserveProtection*/ true); + const ScProtectionAttr& rC6 = m_pDoc->GetAttr(2, 5, 0, ATTR_PROTECTION); + CPPUNIT_ASSERT_MESSAGE("paste must keep the target protected", rC6.GetProtection()); + CPPUNIT_ASSERT_MESSAGE("paste must keep the target's hide-formula flag", rC6.GetHideFormula()); + + // Without the flag (the programmatic copyRange path) attributes are copied + // verbatim, so the source's protection is carried over as before. + m_pDoc->ApplyAttr(4, 5, 0, ScProtectionAttr(true)); // E6 target, protected + paste(ScRange(0, 5, 0, 0, 5, 0), ScRange(4, 5, 0, 4, 5, 0), /*bPreserveProtection*/ false); + CPPUNIT_ASSERT_MESSAGE("paste without the flag must copy the source's state", + !m_pDoc->GetAttr(4, 5, 0, ATTR_PROTECTION).GetProtection()); + + // Protection that comes from a cell style, not from direct formatting, is + // not preserved: only direct protection is. Give G6 an unprotected cell + // style (no direct protection) and paste the protected A1 onto it - it must + // end up protected, following the paste like any other styled attribute. + ScStyleSheet& rUnprotectedStyle = static_cast( + m_pDoc->GetStyleSheetPool()->Make(u"Unprotected"_ustr, SfxStyleFamily::Para)); + rUnprotectedStyle.GetItemSet().Put(ScProtectionAttr(false)); + m_pDoc->ApplyStyle(6, 5, 0, rUnprotectedStyle); // G6 + CPPUNIT_ASSERT_MESSAGE("precondition: the style leaves G6 unprotected", + !m_pDoc->GetAttr(6, 5, 0, ATTR_PROTECTION).GetProtection()); + CPPUNIT_ASSERT_MESSAGE( + "precondition: G6 has no direct protection", + SfxItemState::SET + != m_pDoc->GetPattern(6, 5, 0)->GetItemSet().GetItemState(ATTR_PROTECTION, false)); + paste(ScRange(0, 0, 0, 0, 0, 0), ScRange(6, 5, 0, 6, 5, 0), /*bPreserveProtection*/ true); + CPPUNIT_ASSERT_MESSAGE("style-based protection is not preserved; it follows the paste", + m_pDoc->GetAttr(6, 5, 0, ATTR_PROTECTION).GetProtection()); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPasteAsLink) { sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // Turn on auto calc. @@ -9030,7 +9122,7 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testTdf142065) printRange(&aClipDoc, aSrcRange, "clip doc (&aClipDoc)"); printFormula(&aClipDoc, 1, 0, nTab); - // To A3:A9 + // To A3:A8 ScRange aDestRange(0, 2, nTab, 0, 7, nTab); ScMarkData aDestMark(m_pDoc->GetSheetLimits()); @@ -9907,6 +9999,397 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPasteFormulas) CPPUNIT_ASSERT_EQUAL(u"=$Sheet2.K$1"_ustr, m_pDoc->GetFormula(10, 14, 0)); } +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyToClipCarriesNamedDBs) +{ + // A copy whose range intersects a named table must carry that table + // into the clipboard document, otherwise structured-reference tokens + // in the copied formulas have nothing to resolve against and any + // textual form of those formulas produces #REF!. + m_pDoc->InsertTab(0, u"Test"_ustr); + + // Named table area B3:E6 on sheet 0. + auto pTable = std::make_unique(u"MyTable"_ustr, 0, 1, 2, 4, 5, true, true); + ScDBData* pTableRaw = pTable.get(); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTable))); + + // A second named table on sheet 0 that the copy does not touch. + auto pOther = std::make_unique(u"AwayTable"_ustr, 0, 10, 20, 12, 25, true, true); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pOther))); + + // Copy a single row inside MyTable's body. + ScRange aClipRange(1, 3, 0, 4, 3, 0); // B4:E4 + ScClipParam aClipParam(aClipRange, false); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + aMark.SetMarkArea(aClipRange); + + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + + ScDBCollection::NamedDBs& rClipDBs = aClipDoc.GetDBCollection()->getNamedDBs(); + CPPUNIT_ASSERT_EQUAL(size_t(1), rClipDBs.size()); + const ScDBData* pClone = rClipDBs.findByUpperName(u"MYTABLE"_ustr); + CPPUNIT_ASSERT(pClone); + CPPUNIT_ASSERT_EQUAL(pTableRaw->GetIndex(), pClone->GetIndex()); + ScRange aCloneArea; + pClone->GetArea(aCloneArea); + CPPUNIT_ASSERT_EQUAL(ScRange(1, 2, 0, 4, 5, 0), aCloneArea); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipShiftsNamedDBs) +{ + // Pasting a fully-copied named table into a document that does not already + // own it must recreate the table anchored to the paste location, not at the + // source coordinates, and the column names the copy carried must survive + // the re-anchor so a structured reference still resolves against the + // pasted table instead of evaluating to #REF!. + m_pDoc->InsertTab(0, u"Src"_ustr); + + // Named table MyTable over A1:C3 on the source sheet, with some content so + // the paste carries cells. + auto pTable = std::make_unique(u"MyTable"_ustr, 0, 0, 0, 2, 2, true, true); + pTable->SetTableColumnNames(std::vector{ u"Name"_ustr, u"A"_ustr, u"B"_ustr }); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTable))); + m_pDoc->SetString(0, 0, 0, u"Name"_ustr); + m_pDoc->SetString(1, 0, 0, u"A"_ustr); + m_pDoc->SetString(2, 0, 0, u"B"_ustr); + m_pDoc->SetValue(2, 2, 0, 42.0); + + // Copy the whole table A1:C3. + ScRange aClipRange(0, 0, 0, 2, 2, 0); + ScClipParam aClipParam(aClipRange, false); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + aMark.SetMarkArea(aClipRange); + + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + + // Fresh destination document that has no MyTable of its own. + ScDocShellRef xDestDocSh = new ScDocShell; + xDestDocSh->DoLoad(new SfxMedium(u"file:///dbshift.fake"_ustr, StreamMode::STD_READWRITE)); + ScDocument& rDestDoc = xDestDocSh->GetDocument(); + rDestDoc.InsertTab(0, u"Dest"_ustr); + + // Paste with the top-left at C5: the block shifts by (+2 col, +4 row). + ScRange aDestRange(2, 4, 0, 4, 6, 0); // C5:E7 + ScMarkData aDestMark(rDestDoc.GetSheetLimits()); + aDestMark.SelectOneTable(0); + rDestDoc.CopyFromClip(aDestRange, aDestMark, InsertDeleteFlags::ALL, nullptr, &aClipDoc); + + // The destination now owns MyTable, anchored to the pasted location. + ScDBCollection* pDestDBs = rDestDoc.GetDBCollection(); + CPPUNIT_ASSERT(pDestDBs); + const ScDBData* pPasted = pDestDBs->getNamedDBs().findByUpperName(u"MYTABLE"_ustr); + CPPUNIT_ASSERT(pPasted); + ScRange aPastedArea; + pPasted->GetArea(aPastedArea); + CPPUNIT_ASSERT_EQUAL(ScRange(2, 4, 0, 4, 6, 0), aPastedArea); + + // The column names the copy carried survive the re-anchor, so a structured + // reference can still resolve a column by name against the pasted table. + CPPUNIT_ASSERT_EQUAL(size_t(3), pPasted->GetTableColumnNames().size()); + CPPUNIT_ASSERT_EQUAL(u"Name"_ustr, pPasted->GetTableColumnNames()[0]); + CPPUNIT_ASSERT_EQUAL(u"A"_ustr, pPasted->GetTableColumnNames()[1]); + CPPUNIT_ASSERT_EQUAL(u"B"_ustr, pPasted->GetTableColumnNames()[2]); + + // A structured reference resolves against the pasted table by column + // name and computes against the cells the copy carried. Without the + // names, this would fail to resolve and the cell would hold a #REF! + // error. + rDestDoc.SetString(0, 9, 0, u"=SUM(MyTable[B])"_ustr); // A10 + rDestDoc.CalcAll(); + ScFormulaCell* pFC = rDestDoc.GetFormulaCell(ScAddress(0, 9, 0)); + CPPUNIT_ASSERT(pFC); + CPPUNIT_ASSERT_EQUAL(int(FormulaError::NONE), int(pFC->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(42.0, rDestDoc.GetValue(0, 9, 0)); + + // The source table must be left untouched at its original coordinates. + const ScDBData* pSrc + = m_pDoc->GetDBCollection()->getNamedDBs().findByUpperName(u"MYTABLE"_ustr); + CPPUNIT_ASSERT(pSrc); + ScRange aSrcArea; + pSrc->GetArea(aSrcArea); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, 0, 2, 2, 0), aSrcArea); + + xDestDocSh->DoClose(); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testRefUndoRestoresEmptyDBCollection) +{ + // Pasting a named table into a document that had none adds a DB range; the + // paste's ScRefUndoData must be able to restore the empty pre-state on undo. + // That requires snapshotting even an empty collection - otherwise undo + // leaves the table orphaned. Regression guard for that orphaned table. + m_pDoc->InsertTab(0, u"Test"_ustr); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().empty()); + + // Snapshot the (empty) pre-state, exactly as the paste undo does up front - + // forcing the DB-range snapshot (see ScViewFunc::PasteFromClip). + ScRefUndoData aRefUndo(*m_pDoc, /*bForceDBSnapshot*/ true); + + // Simulate the paste adding a named table to the empty collection. + auto pTable = std::make_unique(u"MyTable"_ustr, 0, 0, 0, 2, 2, true, true); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTable))); + CPPUNIT_ASSERT(!m_pDoc->GetDBCollection()->getNamedDBs().empty()); + + // DeleteUnchanged must keep the snapshot (collection changed), and DoUndo + // must restore the empty collection. + aRefUndo.DeleteUnchanged(*m_pDoc); + aRefUndo.DoUndo(*m_pDoc, true); + + CPPUNIT_ASSERT_MESSAGE("undo must drop a table added over an empty DB collection", + m_pDoc->GetDBCollection()->getNamedDBs().empty()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipPartialTableNoPhantom) +{ + // A partial copy (one that does not cover the whole table) carrying a + // structured reference must NOT fabricate a table in the destination. + // CopyDBsFromClip only recreates a fully-covered table; for a partial copy + // adjustDBRange must leave the reference unresolved (#REF!) instead of + // cloning a misplaced, header-less table at the source coordinates. + m_pDoc->InsertTab(0, u"Src"_ustr); + + // Named table MyTable over A1:C4 (header + 3 data rows) with explicit column + // names so a structured reference compiles, and H1-column data so it computes. + auto pTable = std::make_unique(u"MyTable"_ustr, 0, 0, 0, 2, 3, true, true); + pTable->SetTableColumnNames(std::vector{ u"H1"_ustr, u"H2"_ustr, u"H3"_ustr }); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTable))); + m_pDoc->SetValue(0, 1, 0, 1.0); // A2 + m_pDoc->SetValue(0, 2, 0, 4.0); // A3 + m_pDoc->SetValue(0, 3, 0, 16.0); // A4 + m_pDoc->SetString(2, 1, 0, u"=SUM(MyTable[H1])"_ustr); // C2, a structured-ref formula + m_pDoc->CalcAll(); + // Confirm the structured reference actually compiled and resolved, so the + // test really exercises adjustDBRange rather than passing trivially. + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(2, 1, 0)); + + // Copy a partial block A2:C3 - it intersects MyTable but does not cover it. + ScRange aClipRange(0, 1, 0, 2, 2, 0); + ScClipParam aClipParam(aClipRange, false); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + aMark.SetMarkArea(aClipRange); + + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + // The table was carried into the clip (it intersects the copied range). + CPPUNIT_ASSERT(aClipDoc.GetDBCollection()->getNamedDBs().findByUpperName(u"MYTABLE"_ustr)); + + // Paste into a fresh document that has no MyTable, at a different position. + ScDocShellRef xDestDocSh = new ScDocShell; + xDestDocSh->DoLoad(new SfxMedium(u"file:///nophantom.fake"_ustr, StreamMode::STD_READWRITE)); + ScDocument& rDestDoc = xDestDocSh->GetDocument(); + rDestDoc.InsertTab(0, u"Dest"_ustr); + + ScRange aDestRange(5, 10, 0, 7, 11, 0); // F11:H12 + ScMarkData aDestMark(rDestDoc.GetSheetLimits()); + aDestMark.SelectOneTable(0); + rDestDoc.CopyFromClip(aDestRange, aDestMark, InsertDeleteFlags::ALL, nullptr, &aClipDoc); + + // No phantom table must have been registered in the destination. + ScDBCollection* pDestDBs = rDestDoc.GetDBCollection(); + CPPUNIT_ASSERT_MESSAGE("partial copy must not fabricate a table in the destination", + !pDestDBs || pDestDBs->getNamedDBs().empty()); + + xDestDocSh->DoClose(); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipCrossDocSameNameNoBind) +{ + // A full table copy pasted into a different document that already owns an + // unrelated table of the same name must not bind the pasted structured + // reference to that destination table. The name is document-global and + // cannot be recreated, so the reference is left unresolved (#REF!) instead + // of silently computing the wrong table's data. + m_pDoc->InsertTab(0, u"Src"_ustr); + + // Source MyTable A1:C4; a structured-ref formula in C2 reads its H1 + // column. + auto pTable = std::make_unique(u"MyTable"_ustr, 0, 0, 0, 2, 3, true, true); + pTable->SetTableColumnNames(std::vector{ u"H1"_ustr, u"H2"_ustr, u"H3"_ustr }); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTable))); + m_pDoc->SetValue(0, 1, 0, 1.0); // A2 + m_pDoc->SetValue(0, 2, 0, 4.0); // A3 + m_pDoc->SetValue(0, 3, 0, 16.0); // A4 + m_pDoc->SetString(2, 1, 0, u"=SUM(MyTable[H1])"_ustr); // C2 + m_pDoc->CalcAll(); + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(2, 1, 0)); + + // Copy the whole table A1:C4. + ScRange aClipRange(0, 0, 0, 2, 3, 0); + ScClipParam aClipParam(aClipRange, false); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + aMark.SetMarkArea(aClipRange); + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + + // Destination document with its OWN unrelated MyTable at F11:H14 + // carrying distinct H1 data. + ScDocShellRef xDestDocSh = new ScDocShell; + xDestDocSh->DoLoad( + new SfxMedium(u"file:///crossdocnameclash.fake"_ustr, StreamMode::STD_READWRITE)); + ScDocument& rDestDoc = xDestDocSh->GetDocument(); + rDestDoc.InsertTab(0, u"Dest"_ustr); + auto pDestTable = std::make_unique(u"MyTable"_ustr, 0, 5, 10, 7, 13, true, true); + pDestTable->SetTableColumnNames(std::vector{ u"H1"_ustr, u"H2"_ustr, u"H3"_ustr }); + CPPUNIT_ASSERT(rDestDoc.GetDBCollection()->getNamedDBs().insert(std::move(pDestTable))); + rDestDoc.SetValue(5, 11, 0, 100.0); // F12 + rDestDoc.SetValue(5, 12, 0, 200.0); // F13 + rDestDoc.SetValue(5, 13, 0, 400.0); // F14 + + // Paste the copied table at A1, clear of the destination's own table. + ScRange aDestRange(0, 0, 0, 2, 3, 0); + ScMarkData aDestMark(rDestDoc.GetSheetLimits()); + aDestMark.SelectOneTable(0); + rDestDoc.CopyFromClip(aDestRange, aDestMark, InsertDeleteFlags::ALL, nullptr, &aClipDoc); + rDestDoc.CalcAll(); + + // The pasted formula resolves to FormulaError::NoRef. + CPPUNIT_ASSERT_EQUAL(int(FormulaError::NoRef), int(rDestDoc.GetErrCode(ScAddress(2, 1, 0)))); + + // The source's H1 data landed in the destination at A2:A4. + CPPUNIT_ASSERT_EQUAL(1.0, rDestDoc.GetValue(0, 1, 0)); + CPPUNIT_ASSERT_EQUAL(4.0, rDestDoc.GetValue(0, 2, 0)); + CPPUNIT_ASSERT_EQUAL(16.0, rDestDoc.GetValue(0, 3, 0)); + + // The destination's own table stays at its original area with its data + // untouched by the paste. + const ScDBData* pDestOwn + = rDestDoc.GetDBCollection()->getNamedDBs().findByUpperName(u"MYTABLE"_ustr); + CPPUNIT_ASSERT(pDestOwn); + ScRange aDestOwnArea; + pDestOwn->GetArea(aDestOwnArea); + CPPUNIT_ASSERT_EQUAL(ScRange(5, 10, 0, 7, 13, 0), aDestOwnArea); + CPPUNIT_ASSERT_EQUAL(100.0, rDestDoc.GetValue(5, 11, 0)); + CPPUNIT_ASSERT_EQUAL(200.0, rDestDoc.GetValue(5, 12, 0)); + CPPUNIT_ASSERT_EQUAL(400.0, rDestDoc.GetValue(5, 13, 0)); + + xDestDocSh->DoClose(); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyToClipMultiRangeGapTable) +{ + // A non-contiguous copy must carry only the tables that lie inside a copied + // range, not one sitting in the gap between two ranges. The gap table is + // inside the bounding box of the selection but none of its cells are copied. + m_pDoc->InsertTab(0, u"Test"_ustr); + + // Column-direction multi-selection A1:B3 and E1:F3; the gap is columns C, D. + + // InRangeTable at A1:B3 lies inside the first range. The clip carries it. + auto pInRange = std::make_unique(u"InRangeTable"_ustr, 0, 0, 0, 1, 2, true, true); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pInRange))); + + // GapTable at C1:D3 lies in the gap. The clip leaves it out. + auto pGap = std::make_unique(u"GapTable"_ustr, 0, 2, 0, 3, 2, true, true); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pGap))); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + ScClipParam aClipParam; + aClipParam.meDirection = ScClipParam::Column; + aClipParam.maRanges.push_back(ScRange(0, 0, 0, 1, 2, 0)); // A1:B3 + aClipParam.maRanges.push_back(ScRange(4, 0, 0, 5, 2, 0)); // E1:F3 + + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + + ScDBCollection::NamedDBs& rClipDBs = aClipDoc.GetDBCollection()->getNamedDBs(); + CPPUNIT_ASSERT_MESSAGE("a table inside a copied range is carried", + rClipDBs.findByUpperName(u"INRANGETABLE"_ustr)); + CPPUNIT_ASSERT_MESSAGE("a table in the gap between copied ranges must not be carried", + !rClipDBs.findByUpperName(u"GAPTABLE"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyToClipMultiSheetForeignTable) +{ + // A grouped-sheet copy carries only the tables on the sheet whose cells are + // copied, not a same-area table living on another selected sheet. So the + // paste side never receives tables from several sheets that would all be + // placed onto a single destination sheet. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + m_pDoc->InsertTab(1, u"Sheet2"_ustr); + + auto pTab0 = std::make_unique(u"Table0"_ustr, 0, 0, 0, 1, 1, true, true); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTab0))); + auto pTab1 = std::make_unique(u"Table1"_ustr, 1, 0, 0, 1, 1, true, true); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTab1))); + + // Copy A1:B2 with both sheets grouped. The copied ranges live on sheet 0. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectTable(0, true); + aMark.SelectTable(1, true); + ScRange aClipRange(0, 0, 0, 1, 1, 0); // A1:B2 on sheet 0 + aMark.SetMarkArea(aClipRange); + ScClipParam aClipParam(aClipRange, false); + + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + + ScDBCollection::NamedDBs& rClipDBs = aClipDoc.GetDBCollection()->getNamedDBs(); + CPPUNIT_ASSERT_MESSAGE("the copied sheet's table is carried", + rClipDBs.findByUpperName(u"TABLE0"_ustr)); + CPPUNIT_ASSERT_MESSAGE("a table on another sheet is not carried", + !rClipDBs.findByUpperName(u"TABLE1"_ustr)); + + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyFromClipValuesOnlyNoTable) +{ + // Pasting only values of a copied table must not recreate the table in the + // destination. The table is recreated so structured-reference formulas can + // resolve against it. A values-only paste carries no such formula, so it + // should leave the destination without a table. + m_pDoc->InsertTab(0, u"Src"_ustr); + + auto pTable = std::make_unique(u"MyTable"_ustr, 0, 0, 0, 2, 2, true, true); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pTable))); + m_pDoc->SetString(0, 0, 0, u"Name"_ustr); + m_pDoc->SetValue(2, 2, 0, 42.0); + + // Copy the whole table A1:C3. + ScRange aClipRange(0, 0, 0, 2, 2, 0); + ScClipParam aClipParam(aClipRange, false); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + aMark.SetMarkArea(aClipRange); + ScDocument aClipDoc(SCDOCMODE_CLIP); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + + // Fresh destination document that has no MyTable of its own. + ScDocShellRef xDestDocSh = new ScDocShell; + xDestDocSh->DoLoad(new SfxMedium(u"file:///valuesonly.fake"_ustr, StreamMode::STD_READWRITE)); + ScDocument& rDestDoc = xDestDocSh->GetDocument(); + rDestDoc.InsertTab(0, u"Dest"_ustr); + + // Paste values only, no formulas. + ScRange aDestRange(0, 0, 0, 2, 2, 0); + ScMarkData aDestMark(rDestDoc.GetSheetLimits()); + aDestMark.SelectOneTable(0); + rDestDoc.CopyFromClip(aDestRange, aDestMark, InsertDeleteFlags::VALUE, nullptr, &aClipDoc); + + ScDBCollection* pDestDBs = rDestDoc.GetDBCollection(); + CPPUNIT_ASSERT_MESSAGE("a values-only paste must not recreate the table", + !pDestDBs || pDestDBs->getNamedDBs().empty()); + + xDestDocSh->DoClose(); + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPasteFormulasExternalDoc) { SfxMedium* pMedium = new SfxMedium(u"file:///source.fake"_ustr, StreamMode::STD_READWRITE); @@ -10576,6 +11059,43 @@ CPPUNIT_TEST_FIXTURE(TestCopyPaste, testCopyPasteMatrixFormula) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(TestCopyPaste, testExportTextLeadingEmptyCellsTdf109299) +{ + m_pDoc->InsertTab(0, u"Test"_ustr); + + // Set a value to A1; B1 intentionally left empty + m_pDoc->SetString(ScAddress(0, 0, 0), u"A1"_ustr); + + // Create range from A1 to B1 including the empty cell B1 + ScRange aRange(ScAddress(0, 0, 0), ScAddress(1, 0, 0)); + + // ShrinkToDataArea is true (default case): trailing empty cell B1 is shrunk away + { + ScImportExport aObj(*m_pDoc, aRange); + OUString aResult; + CPPUNIT_ASSERT(aObj.ExportString(aResult, SotClipboardFormatId::STRING)); + CPPUNIT_ASSERT_EQUAL(u"A1"_ustr, aResult); + } + + // ShrinkToDataArea is false: trailing empty cell B1 is kept + { + auto pChange = comphelper::ConfigurationChanges::create(); + officecfg::Office::Calc::ClipboardCellsExport::ShrinkToDataArea::set(false, pChange); + pChange->commit(); + + ScImportExport aObj(*m_pDoc, aRange); + OUString aResult; + CPPUNIT_ASSERT(aObj.ExportString(aResult, SotClipboardFormatId::STRING)); + CPPUNIT_ASSERT(aResult.startsWith("A1\t")); + + // Restore default value + officecfg::Office::Calc::ClipboardCellsExport::ShrinkToDataArea::set(true, pChange); + pChange->commit(); + } + + m_pDoc->DeleteTab(0); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index fc521cd966b3..e194b629f6a8 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -112,9 +112,8 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaCreateStringFromTokens) { false, "sheetx", "Test.J1" } }; - ScRangeName* pGlobalNames = m_pDoc->GetRangeName(); + ScRangeName& rGlobalNames = m_pDoc->GetRangeName(); ScRangeName* pSheetNames = m_pDoc->GetRangeName(0); - CPPUNIT_ASSERT_MESSAGE("Failed to obtain global named expression object.", pGlobalNames); CPPUNIT_ASSERT_MESSAGE("Failed to obtain sheet-local named expression object.", pSheetNames); for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i) @@ -125,12 +124,12 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaCreateStringFromTokens) if (aNames[i].bGlobal) { - bool bInserted = pGlobalNames->insert(pName); + bool bInserted = rGlobalNames.insert(std::unique_ptr(pName)); CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bInserted); } else { - bool bInserted = pSheetNames->insert(pName); + bool bInserted = pSheetNames->insert(std::unique_ptr(pName)); CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bInserted); } } @@ -259,7 +258,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaParseReference) m_pDoc->InsertTab(1, aTab1); // name with a single quote. m_pDoc->InsertTab(2, aTab2); // name with 2 single quotes. m_pDoc->InsertTab(3, aTab3); // name without single quotes. - m_pDoc->InsertTab(4, aTab4); // name that doesn't require to be quoted. + m_pDoc->InsertTab(4, aTab4); // name that doesn't require being quoted. OUString aTabName; m_pDoc->GetName(1, aTabName); @@ -1152,7 +1151,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaCompilerImplicitIntersection2Param) CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of token(first argument to SUMIF)", svDoubleRef, ppTokens[0]->GetType()); CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of token(third argument to SUMIF)", svDoubleRef, ppTokens[2]->GetType()); - ScComplexRefData aSumRangeData = *ppTokens[2]->GetDoubleRef(); + ScComplexRefData aSumRangeData = static_cast(ppTokens[2])->GetDoubleRef(); ScRange aSumRange = aSumRangeData.toAbs(*m_pDoc, rCase.aCellAddress); CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong sum-range in RPN array", rCase.aSumRange, aSumRange); @@ -1251,8 +1250,8 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaCompilerImplicitIntersection1ParamN CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of raw token(argument to COS)", svDoubleRef, ppRawTokens[nRawArgPos]->GetType()); CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of RPN token(argument to COS)", svDoubleRef, ppRPNTokens[0]->GetType()); - ScComplexRefData aArgRangeRaw = *ppRawTokens[nRawArgPos]->GetDoubleRef(); - ScComplexRefData aArgRangeRPN = *ppRPNTokens[0]->GetDoubleRef(); + ScComplexRefData aArgRangeRaw = static_cast(ppRawTokens[nRawArgPos])->GetDoubleRef(); + ScComplexRefData aArgRangeRPN = static_cast(ppRPNTokens[0])->GetDoubleRef(); bool bRawMatchRPNToken(aArgRangeRaw == aArgRangeRPN); CPPUNIT_ASSERT_MESSAGE("raw arg token and RPN arg token contents do not match", bRawMatchRPNToken); } @@ -1333,7 +1332,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaCompilerImplicitIntersection1ParamW CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of RPN token(argument to COS)", svSingleRef, ppRPNTokens[0]->GetType()); - ScSingleRefData aArgAddrRPN = *ppRPNTokens[0]->GetSingleRef(); + ScSingleRefData aArgAddrRPN = static_cast(ppRPNTokens[0])->GetSingleRef(); ScAddress aArgAddrActual = aArgAddrRPN.toAbs(*m_pDoc, rCase.aCellAddress); CPPUNIT_ASSERT_EQUAL_MESSAGE("Computed implicit intersection singleref is wrong", rCase.aArgAddr, aArgAddrActual); } @@ -1489,13 +1488,13 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaAnnotateTrimOnDoubleRefs) FormulaToken* pTok = pRPNArray[nIdx]; if (pTok && pTok->GetType() == svDoubleRef) { - ScRange aRange = pTok->GetDoubleRef()->toAbs(*m_pDoc, ScAddress(4, 0, 0)); + ScRange aRange = static_cast(pTok)->GetDoubleRef().toAbs(*m_pDoc, ScAddress(4, 0, 0)); if (aRange == rTestCase.aTrimmableRange) CPPUNIT_ASSERT_MESSAGE(aMsgStart + "Double ref is incorrectly flagged as not trimmable to data", - pTok->GetDoubleRef()->IsTrimToData()); + static_cast(pTok)->GetDoubleRef().IsTrimToData()); else CPPUNIT_ASSERT_MESSAGE(aMsgStart + "Double ref is incorrectly flagged as trimmable to data", - !pTok->GetDoubleRef()->IsTrimToData()); + !static_cast(pTok)->GetDoubleRef().IsTrimToData()); } } } @@ -2473,7 +2472,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateInsertColumns) CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(3,3,0))); // Check that the named reference points to the moved cell, now D2. - ScRangeData* pName = m_pDoc->GetRangeName()->findByUpperName(u"ROWRELATIVERANGE"_ustr); + ScRangeData* pName = m_pDoc->GetRangeName().findByUpperName(u"ROWRELATIVERANGE"_ustr); CPPUNIT_ASSERT(pName); OUString aSymbol = pName->GetSymbol(aNamePos, formula::FormulaGrammar::GRAM_ENGLISH); CPPUNIT_ASSERT_EQUAL(u"$Formula.$D2"_ustr, aSymbol); @@ -2484,7 +2483,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateInsertColumns) CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(4,1,0))); // Check that the named column reference points to the moved column, now D. - pName = m_pDoc->GetRangeName()->findByUpperName(u"ENTIRECOLUMN"_ustr); + pName = m_pDoc->GetRangeName().findByUpperName(u"ENTIRECOLUMN"_ustr); CPPUNIT_ASSERT(pName); aSymbol = pName->GetSymbol(aNamePos, formula::FormulaGrammar::GRAM_ENGLISH); CPPUNIT_ASSERT_EQUAL(u"$D:$D"_ustr, aSymbol); @@ -2496,7 +2495,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateInsertColumns) // Check that the named row reference still points to the same entire row // and does not have a #REF! error due to inserted columns. - pName = m_pDoc->GetRangeName()->findByUpperName(u"ENTIREROW"_ustr); + pName = m_pDoc->GetRangeName().findByUpperName(u"ENTIREROW"_ustr); CPPUNIT_ASSERT(pName); aSymbol = pName->GetSymbol(aNamePos, formula::FormulaGrammar::GRAM_ENGLISH); CPPUNIT_ASSERT_EQUAL(u"$2:$2"_ustr, aSymbol); @@ -3372,13 +3371,12 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateName) m_pDoc->SetValue(ScAddress(2,4,0), 4); // Add a named expression that references the immediate left cell. - ScRangeName* pGlobalNames = m_pDoc->GetRangeName(); - CPPUNIT_ASSERT_MESSAGE("Failed to obtain global named expression object.", pGlobalNames); + ScRangeName& rGlobalNames = m_pDoc->GetRangeName(); ScRangeData* pName = new ScRangeData( *m_pDoc, u"ToLeft"_ustr, u"RC[-1]"_ustr, ScAddress(2,1,0), ScRangeData::Type::Name, formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1); - bool bInserted = pGlobalNames->insert(pName); + bool bInserted = rGlobalNames.insert(std::unique_ptr(pName)); CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bInserted); // Insert formulas in D2:D5 using the named expression. @@ -3419,7 +3417,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateName) // Insert a new named expression that references these values as absolute range. pName = new ScRangeData( *m_pDoc, u"MyRange"_ustr, u"$B$10:$B$12"_ustr, ScAddress(0,0,0), ScRangeData::Type::Name, formula::FormulaGrammar::GRAM_NATIVE); - bInserted = pGlobalNames->insert(pName); + bInserted = rGlobalNames.insert(std::unique_ptr(pName)); CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bInserted); // Set formula at C8 that references this named expression. @@ -3430,7 +3428,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateName) m_pDoc->InsertCol(ScRange(1,9,0,2,11,0)); // This should shift the absolute range B10:B12 that MyRange references. - pName = pGlobalNames->findByUpperName(u"MYRANGE"_ustr); + pName = rGlobalNames.findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT_MESSAGE("Failed to find named expression 'MyRange' in the global scope.", pName); OUString aExpr = pName->GetSymbol(); CPPUNIT_ASSERT_EQUAL(u"$D$10:$D$12"_ustr, aExpr); @@ -3450,7 +3448,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateName) m_pDoc->GetName(1, aName); CPPUNIT_ASSERT_EQUAL(u"Formula"_ustr, aName); - pName = pGlobalNames->findByUpperName(u"MYRANGE"_ustr); + pName = rGlobalNames.findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT_MESSAGE("Failed to find named expression 'MyRange' in the global scope.", pName); m_pDoc->SetValue(ScAddress(3,9,1), 10); @@ -3463,7 +3461,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateName) m_pDoc->GetName(0, aName); CPPUNIT_ASSERT_EQUAL(u"Formula"_ustr, aName); - pName = pGlobalNames->findByUpperName(u"MYRANGE"_ustr); + pName = rGlobalNames.findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT_MESSAGE("Failed to find named expression 'MyRange' in the global scope.", pName); m_pDoc->SetValue(ScAddress(3,9,0), 11); @@ -3471,11 +3469,11 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateName) // Clear all and start over. clearRange(m_pDoc, ScRange(0,0,0,100,100,0)); - pGlobalNames->clear(); + rGlobalNames.clear(); pName = new ScRangeData( *m_pDoc, u"MyRange"_ustr, u"$B$1:$C$6"_ustr, ScAddress(0,0,0), ScRangeData::Type::Name, formula::FormulaGrammar::GRAM_NATIVE); - bInserted = pGlobalNames->insert(pName); + bInserted = rGlobalNames.insert(std::unique_ptr(pName)); CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bInserted); aExpr = pName->GetSymbol(); CPPUNIT_ASSERT_EQUAL(u"$B$1:$C$6"_ustr, aExpr); @@ -3509,7 +3507,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameMove) m_pDoc->SetString(ScAddress(0,9,0), u"=SUM(MyRange)"_ustr); CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(0,9,0))); - ScRangeData* pData = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + ScRangeData* pData = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pData); OUString aSymbol = pData->GetSymbol(m_pDoc->GetGrammar()); CPPUNIT_ASSERT_EQUAL(u"$Test.$B$2:$B$4"_ustr, aSymbol); @@ -3532,7 +3530,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameMove) // Undo and check. pUndoMgr->Undo(); - pData = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + pData = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pData); aSymbol = pData->GetSymbol(m_pDoc->GetGrammar()); CPPUNIT_ASSERT_EQUAL(u"$Test.$B$2:$B$4"_ustr, aSymbol); @@ -3541,7 +3539,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameMove) // Redo and check. pUndoMgr->Redo(); - pData = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + pData = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pData); aSymbol = pData->GetSymbol(m_pDoc->GetGrammar()); CPPUNIT_ASSERT_EQUAL(u"$Test.$D$3:$D$5"_ustr, aSymbol); @@ -3568,7 +3566,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameMove) // Clear and start over. clearSheet(m_pDoc, 0); - m_pDoc->GetRangeName()->clear(); + m_pDoc->GetRangeName().clear(); // Set value to B2. m_pDoc->SetValue(ScAddress(1,1,0), 2.0); @@ -3615,7 +3613,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameExpandRef) ScMarkData aMark(m_pDoc->GetSheetLimits()); aMark.SelectOneTable(0); rFunc.InsertCells(ScRange(0,3,0,m_pDoc->MaxCol(),3,0), &aMark, INS_INSROWS_BEFORE, false, true); - ScRangeData* pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + ScRangeData* pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); OUString aSymbol = pName->GetSymbol(m_pDoc->GetGrammar()); CPPUNIT_ASSERT_EQUAL(u"$A$1:$A$4"_ustr, aSymbol); @@ -3628,7 +3626,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameExpandRef) // Insert a new column at column 2, which should not expand the named // range as it is only one column wide. rFunc.InsertCells(ScRange(1,0,0,1,m_pDoc->MaxRow(),0), &aMark, INS_INSCOLS_BEFORE, false, true); - pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); aSymbol = pName->GetSymbol(m_pDoc->GetGrammar()); CPPUNIT_ASSERT_EQUAL(u"$A$1:$A$4"_ustr, aSymbol); @@ -3640,7 +3638,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameExpandRef) CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc->GetValue(ScAddress(0,6,0))); // Clear the document and start over. - m_pDoc->GetRangeName()->clear(); + m_pDoc->GetRangeName().clear(); clearSheet(m_pDoc, 0); // Set values to B4:B6. @@ -3658,14 +3656,14 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameExpandRef) // Insert rows over 3:5 which should expand the range by 3 rows. rFunc.InsertCells(ScRange(0,2,0,m_pDoc->MaxCol(),4,0), &aMark, INS_INSROWS_BEFORE, false, true); - pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); aSymbol = pName->GetSymbol(m_pDoc->GetGrammar()); CPPUNIT_ASSERT_EQUAL(u"$B$4:$B$9"_ustr, aSymbol); // Clear the document and start over. - m_pDoc->GetRangeName()->clear(); + m_pDoc->GetRangeName().clear(); clearSheet(m_pDoc, 0); // Set values to A1:A3. @@ -3730,7 +3728,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameExpandRef2) // Insert a new column at column 3, which should expand the named rFunc.InsertCells(ScRange(1,0,0,1,m_pDoc->MaxRow(),0), &aMark, INS_INSCOLS_BEFORE, false, true); - ScRangeData* pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + ScRangeData* pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); OUString aSymbol = pName->GetSymbol(m_pDoc->GetGrammar()); CPPUNIT_ASSERT_EQUAL(u"$A$1:$C$3"_ustr, aSymbol); @@ -3746,7 +3744,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameDeleteRow) bool bInserted = m_pDoc->InsertNewRangeName(u"MyRange"_ustr, ScAddress(0,0,0), u"$B$2:$B$4"_ustr); CPPUNIT_ASSERT(bInserted); - const ScRangeData* pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + const ScRangeData* pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); sc::TokenStringContext aCxt(*m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH); @@ -3758,7 +3756,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameDeleteRow) bInserted = m_pDoc->InsertNewRangeName(u"MyAddress"_ustr, ScAddress(0,0,0), u"$B$3"_ustr); CPPUNIT_ASSERT(bInserted); - const ScRangeData* pName2 = m_pDoc->GetRangeName()->findByUpperName(u"MYADDRESS"_ustr); + const ScRangeData* pName2 = m_pDoc->GetRangeName().findByUpperName(u"MYADDRESS"_ustr); CPPUNIT_ASSERT(pName2); sc::TokenStringContext aCxt2(*m_pDoc, formula::FormulaGrammar::GRAM_ENGLISH); @@ -3792,7 +3790,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameDeleteRow) pUndoMgr->Undo(); - pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); pCode = pName->GetCode(); @@ -3802,7 +3800,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameDeleteRow) // Undo again and check. pUndoMgr->Undo(); - pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); pCode = pName->GetCode(); @@ -3818,14 +3816,14 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameDeleteRow) // Undo and check. pUndoMgr->Undo(); - pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); pCode = pName->GetCode(); aExpr = pCode->CreateString(aCxt, ScAddress(0,0,0)); CPPUNIT_ASSERT_EQUAL(u"$B$2:$B$4"_ustr, aExpr); - pName2 = m_pDoc->GetRangeName()->findByUpperName(u"MYADDRESS"_ustr); + pName2 = m_pDoc->GetRangeName().findByUpperName(u"MYADDRESS"_ustr); CPPUNIT_ASSERT(pName2); pCode2 = pName2->GetCode(); @@ -3838,14 +3836,14 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameDeleteRow) aMark2.SelectOneTable(1); rFunc.DeleteCells(ScRange(0,2,1,m_pDoc->MaxCol(),2,1), &aMark2, DelCellCmd::CellsUp, true); - pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); pCode = pName->GetCode(); aExpr = pCode->CreateString(aCxt, ScAddress(0,0,0)); CPPUNIT_ASSERT_EQUAL(u"$B$2:$B$4"_ustr, aExpr); - pName2 = m_pDoc->GetRangeName()->findByUpperName(u"MYADDRESS"_ustr); + pName2 = m_pDoc->GetRangeName().findByUpperName(u"MYADDRESS"_ustr); CPPUNIT_ASSERT(pName2); pCode2 = pName2->GetCode(); @@ -3938,7 +3936,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameCopySheet) m_pDoc->InsertTab(0, u"Test2"_ustr); // Local name referencing sheet Test2. - bInserted = m_pDoc->GetRangeName(0)->insert( new ScRangeData( *m_pDoc, u"localname"_ustr, u"$Test2.$A$1"_ustr)); + bInserted = m_pDoc->GetRangeName(0)->insert( std::make_unique( *m_pDoc, u"localname"_ustr, u"$Test2.$A$1"_ustr)); CPPUNIT_ASSERT(bInserted); m_pDoc->SetString(ScAddress(0,0,0), u"=SHEET()"_ustr); m_pDoc->SetString(ScAddress(1,0,0), u"=localname"_ustr); @@ -4193,7 +4191,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaRefUpdateNameDelete) bool bInserted = m_pDoc->InsertNewRangeName(u"MyRange"_ustr, ScAddress(0,0,0), u"$Test.$B$1"_ustr); CPPUNIT_ASSERT(bInserted); - const ScRangeData* pName = m_pDoc->GetRangeName()->findByUpperName(u"MYRANGE"_ustr); + const ScRangeData* pName = m_pDoc->GetRangeName().findByUpperName(u"MYRANGE"_ustr); CPPUNIT_ASSERT(pName); m_pDoc->DeleteCol(1, 0, 3, 0, 0, 1); @@ -4770,13 +4768,12 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFuncSUBTOTAL) m_pDoc->SetValue(ScAddress(2, i, 0), i + 1); // Add a named expression for a function. - ScRangeName* pGlobalNames = m_pDoc->GetRangeName(); - CPPUNIT_ASSERT_MESSAGE("Failed to obtain global named expression object.", pGlobalNames); + ScRangeName& rGlobalNames = m_pDoc->GetRangeName(); ScRangeData* pName = new ScRangeData( *m_pDoc, u"MyRelative"_ustr, u"$C1:$C$1000"_ustr, ScAddress(2, 999, 0), ScRangeData::Type::Name, formula::FormulaGrammar::GRAM_NATIVE); - bool bInserted = pGlobalNames->insert(pName); + bool bInserted = rGlobalNames.insert(std::unique_ptr(pName)); CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bInserted); for (size_t i = 0; i < 1025; i++) @@ -4791,42 +4788,56 @@ CPPUNIT_TEST_FIXTURE(TestFormula, testFuncSUBTOTAL) CPPUNIT_ASSERT_EQUAL((1000.0 - (i - 999.0)), m_pDoc->GetValue(3, i, 0)); } - ScRange aTrimedRange(2, 999, 0, 2, 1024, 0); - ScRange aValidRange(2, 0, 0, 2, 999, 0); - for (size_t i = 0; i < 1025; i++) + m_pDoc->DeleteTab(0); +} + +// tdf#168013: SUBTOTAL over a big range must keep the stored reference intact. +CPPUNIT_TEST_FIXTURE(TestFormula, testFuncSUBTOTALReferenceNotMutated) +{ + m_pDoc->InsertTab(0, u"Formula"_ustr); + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on. + + // Values in B1:B4, and a SUBTOTAL over a deliberately oversized range in D1. + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); // B1 + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); // B2 + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); // B3 + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); // B4 + + const SCROW nFarRow = 99998; // 0-based -> row 99999 in the UI, "far far away" + m_pDoc->SetString(ScAddress(3, 0, 0), u"=SUBTOTAL(9;B1:B99999)"_ustr); // D1 + + // Result over the existing data. + CPPUNIT_ASSERT_EQUAL(100.0, m_pDoc->GetValue(3, 0, 0)); + + // The stored reference must still span the full, untrimmed range B1:B99999. + auto checkRefPreserved = [this]() { - ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(3, i, 0)); + ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(3, 0, 0)); ScTokenArray* pCode = pCell->GetCode(); sal_uInt16 nLen = pCode->GetCodeLen(); FormulaToken** pRPNArray = pCode->GetCode(); - OUString aCellName = pCell->aPos.GetColRowString(); - + bool bFoundDoubleRef = false; for (sal_uInt16 nIdx = 0; nIdx < nLen; ++nIdx) { FormulaToken* pTok = pRPNArray[nIdx]; if (pTok && pTok->GetType() == svDoubleRef) { - ScRange aRange = pTok->GetDoubleRef()->toAbs(*m_pDoc, ScAddress(3, i, 0)); - if (i < 999) - { - CPPUNIT_ASSERT_EQUAL_MESSAGE(OUString("Double ref is incorrectly trimmed in: " + aCellName).toUtf8().getStr(), - aRange, aTrimedRange); - // Without the trim it would failed with - // assertion failed - // - Expression: aRange == aTrimedRange - // - Double ref is incorrectly trimmed in : D1 - // ScRange aTrimmableRange(2, 999, 0, 0, 1048575, 0); - } - else - { - CPPUNIT_ASSERT_EQUAL_MESSAGE(OUString("Double ref is incorrectly trimmed in: " + aCellName).toUtf8().getStr(), - aRange, aValidRange); - } + bFoundDoubleRef = true; + ScRange aRange = static_cast(pTok)->GetDoubleRef().toAbs( + *m_pDoc, ScAddress(3, 0, 0)); + CPPUNIT_ASSERT_EQUAL(ScRange(1, 0, 0, 1, nFarRow, 0), aRange); } } - if (i >= 999) - aValidRange.aStart.IncRow(); - } + CPPUNIT_ASSERT(bFoundDoubleRef); + }; + checkRefPreserved(); + + // Add a new row of data below the previous last data row: because the reference + // was not shrunk, it must be included on recalc. + m_pDoc->SetValue(ScAddress(1, 4, 0), 50.0); // B5 + CPPUNIT_ASSERT_EQUAL(150.0, m_pDoc->GetValue(3, 0, 0)); + checkRefPreserved(); m_pDoc->DeleteTab(0); } diff --git a/sc/qa/unit/ucalc_formula2.cxx b/sc/qa/unit/ucalc_formula2.cxx index 0ec654aa9ac2..89ce0ebbdb3f 100644 --- a/sc/qa/unit/ucalc_formula2.cxx +++ b/sc/qa/unit/ucalc_formula2.cxx @@ -9,8 +9,11 @@ #include "helper/qahelper.hxx" #include +#include +#include #include #include +#include #include #include #include @@ -23,7 +26,11 @@ #include #include +#include +#include +#include +#include #include #include #include @@ -198,6 +205,180 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testFuncIF) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(TestFormula2, testConcatWithOmittedOptionalParameter) +{ + // Concatenating an omitted optional lambda parameter yields just the + // provided operand. The missing value stands in for an empty string + // rather than being read as a double. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetString(ScAddress(0, 0, 0), u"=LAMBDA(x; [y]; x & y)(\"a\")"_ustr); + CPPUNIT_ASSERT_EQUAL(u"a"_ustr, m_pDoc->GetString(ScAddress(0, 0, 0))); + + // A genuine boolean operand is still rendered as TRUE or FALSE. + m_pDoc->SetString(ScAddress(0, 1, 0), u"=TRUE() & \"x\""_ustr); + CPPUNIT_ASSERT_EQUAL(u"TRUEx"_ustr, m_pDoc->GetString(ScAddress(0, 1, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testLambdaReducingArgumentDoesNotSpill) +{ + // A lambda whose body aggregates a range argument reduces to a single value + // even when entered as a spill-capable dynamic-array formula, the way an + // imported one is. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 2.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 3.0); + + // A value just below the formula blocks a three-row spill, so a result that + // is wrongly sized to the three-row argument surfaces as a spill error. + m_pDoc->SetValue(ScAddress(2, 1, 0), 99.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // The trailing flag makes this a spill-capable dynamic-array master, the + // same kind an imported dynamic-array formula becomes. + m_pDoc->InsertMatrixFormula(2, 0, 2, 0, aMark, u"=LAMBDA(r; SUM(r))(A1:A3)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pRangeCell = m_pDoc->GetFormulaCell(ScAddress(2, 0, 0)); + CPPUNIT_ASSERT(pRangeCell); + + // The whole range reaches the body, which sums it to one value. + CPPUNIT_ASSERT_EQUAL_MESSAGE("the reduced lambda must not report a spill error", + sal_Int32(FormulaError::NONE), + sal_Int32(pRangeCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(2, 0, 0))); + + // The value below the formula is untouched, confirming nothing spilled over it. + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(2, 1, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testLambdaOptionalParameterFromOOXML) +{ + // The OOXML format declares an optional lambda parameter with the _xlop. + // prefix while the body still refers to it through _xlpm.. Both spellings + // name the same parameter, so the body sees it and ISOMITTED reports + // whether the caller left it out. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Called with no argument, so the optional parameter is left out. + m_pDoc->SetFormula(ScAddress(0, 0, 0), + u"=_xlfn.LAMBDA(_xlop.x, IF(_xlfn.ISOMITTED(_xlpm.x), 12, 5))()"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(12.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + + // Called with an argument, so the parameter is present. + m_pDoc->SetFormula(ScAddress(0, 1, 0), + u"=_xlfn.LAMBDA(_xlop.x, IF(_xlfn.ISOMITTED(_xlpm.x), 12, 5))(99)"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + + // Concatenating an omitted optional parameter yields just the other + // operand. The missing operand stands in for an empty string. + m_pDoc->SetFormula(ScAddress(0, 2, 0), + u"=_xlfn.LAMBDA(_xlpm.x, _xlop.y, _xlpm.x & _xlpm.y)(\"a\")"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(u"a"_ustr, m_pDoc->GetString(ScAddress(0, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testLambdaBuiltInValueFromOOXML) +{ + // OOXML passes a built-in function as a value with the _xleta. prefix. The + // lambda receives COUNT as a parameter and calls it on the array, so the + // result is the count of the elements. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetFormula( + ScAddress(0, 0, 0), + u"=_xlfn.LAMBDA(_xlpm.f, _xlpm.n, _xlpm.f(_xlpm.n))(_xleta.COUNT, {1,2,3,4})"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testMapPerElementErrorIsolation) +{ + // MAP gives one result per element, so an element whose lambda errors holds + // an error in that cell alone. The error must not carry over into the + // elements computed after it. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // The middle element divides by zero. Entered as an array formula across + // three cells, the elements before and after it still hold their own value. + m_pDoc->InsertMatrixFormula(0, 0, 2, 0, aMark, u"=MAP({1;0;2}; LAMBDA(x; 1 / x))"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"#DIV/0!"_ustr, m_pDoc->GetString(ScAddress(1, 0, 0))); + CPPUNIT_ASSERT_EQUAL(0.5, m_pDoc->GetValue(ScAddress(2, 0, 0))); + + // IFERROR replaces only the erroring element, so the sum drops just that one. + m_pDoc->InsertMatrixFormula(0, 2, 0, 2, aMark, + u"=SUM(IFERROR(MAP({1;0;2}; LAMBDA(x; 1 / x)); 0))"_ustr); + CPPUNIT_ASSERT_EQUAL(1.5, m_pDoc->GetValue(ScAddress(0, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testMapMismatchedArrayLengths) +{ + // MAP over two arrays of different lengths produces a result as long as the + // longer one, with the position the shorter array cannot reach left not + // available, rather than clipping the result to the shorter array. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // Read MAP's result matrix directly. Entered over a single cell it is + // neither spilled nor padded, so the matrix is exactly what MAP produced. + // Linear element access keeps the check independent of the result shape. + m_pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, + u"=MAP({1;2;3}; {1;2}; LAMBDA(a; b; a + b))"_ustr); + ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + const ScMatrix* pMat = pCell->GetMatrix(); + CPPUNIT_ASSERT(pMat); + + // Three elements, the length of the longer array, not two. + SCSIZE nCols = 0; + SCSIZE nRows = 0; + pMat->GetDimensions(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCSIZE(3), nCols * nRows); + + // The two matched elements add. The third has no second operand. + CPPUNIT_ASSERT_EQUAL(2.0, pMat->GetDouble(0)); + CPPUNIT_ASSERT_EQUAL(4.0, pMat->GetDouble(1)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NotAvailable), + sal_Int32(GetDoubleErrorValue(pMat->GetDouble(2)))); + + // The same result reduced to a scalar, as a second check: IFERROR turns the + // not-available element into a sentinel, so a three-element result sums + // higher than one clipped to two elements. + m_pDoc->InsertMatrixFormula( + 2, 0, 2, 0, aMark, u"=SUM(IFERROR(MAP({1;2;3}; {1;2}; LAMBDA(a; b; a + b)); 100))"_ustr); + CPPUNIT_ASSERT_EQUAL(106.0, m_pDoc->GetValue(ScAddress(2, 0, 0))); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(TestFormula2, testFuncCHOOSE) { sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on. @@ -1117,9 +1298,9 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testFunc_MATCH_INDIRECT) sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn on auto calculation. - ScRangeName* pGlobalNames = m_pDoc->GetRangeName(); + ScRangeName& rGlobalNames = m_pDoc->GetRangeName(); ScRangeData* pRangeData = new ScRangeData(*m_pDoc, u"RoleAssignment"_ustr, u"$D$4:$D$13"_ustr); - pGlobalNames->insert(pRangeData); + rGlobalNames.insert(std::unique_ptr(pRangeData)); // D6: data to match, in 3rd row of named range. m_pDoc->SetString(3, 5, 0, u"Test1"_ustr); @@ -1726,9 +1907,9 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testExternalRangeName) rExtDoc.InsertTab(0, u"Data1"_ustr); rExtDoc.SetValue(0, 0, 0, 123.456); - ScRangeName* pRangeName = rExtDoc.GetRangeName(); + ScRangeName& rRangeName = rExtDoc.GetRangeName(); ScRangeData* pRangeData = new ScRangeData(rExtDoc, u"ExternalName"_ustr, u"$Data1.$A$1"_ustr); - pRangeName->insert(pRangeData); + rRangeName.insert(std::unique_ptr(pRangeData)); m_pDoc->InsertTab(0, u"Test Sheet"_ustr); m_pDoc->SetString(0, 1, 0, u"='file:///extdata.fake'#ExternalName"_ustr); @@ -2011,6 +2192,69 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testExternalRefUnresolved) #endif } +CPPUNIT_TEST_FIXTURE(TestFormula2, testMatrixArithmeticMismatchedExtent) +{ + // Range arithmetic between operands of unequal non-broadcast + // lengths extends the result to the longer length and fills the + // slots past the shorter operand with #N/A. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Test"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 2.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 4.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 7.0); + m_pDoc->SetValue(ScAddress(0, 3, 0), 7.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(1, 0, 1, 3, aMark, u"=A1:A4 * {1|2|3}"_ustr); + + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(1, 0, 0))); + CPPUNIT_ASSERT_EQUAL(8.0, m_pDoc->GetValue(ScAddress(1, 1, 0))); + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(1, 2, 0))); + CPPUNIT_ASSERT_EQUAL(FormulaError::NotAvailable, m_pDoc->GetErrCode(ScAddress(1, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testMatrixConcatMismatchedExtent) +{ + // String concatenation of two two-dimensional ranges of unequal + // length extends the result to the longer range. Where the two + // ranges overlap the cells join together. The rows past the shorter + // operand have no partner to join and stay empty. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Test"_ustr); + + // First operand A1:B3, three rows by two columns. + m_pDoc->SetString(ScAddress(0, 0, 0), u"a"_ustr); + m_pDoc->SetString(ScAddress(1, 0, 0), u"b"_ustr); + m_pDoc->SetString(ScAddress(0, 1, 0), u"c"_ustr); + m_pDoc->SetString(ScAddress(1, 1, 0), u"d"_ustr); + m_pDoc->SetString(ScAddress(0, 2, 0), u"e"_ustr); + m_pDoc->SetString(ScAddress(1, 2, 0), u"f"_ustr); + + // Second operand D1:E2, two rows by two columns, one row shorter. + m_pDoc->SetString(ScAddress(3, 0, 0), u"1"_ustr); + m_pDoc->SetString(ScAddress(4, 0, 0), u"2"_ustr); + m_pDoc->SetString(ScAddress(3, 1, 0), u"3"_ustr); + m_pDoc->SetString(ScAddress(4, 1, 0), u"4"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(6, 0, 7, 2, aMark, u"=A1:B3&D1:E2"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"a1"_ustr, m_pDoc->GetString(ScAddress(6, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"b2"_ustr, m_pDoc->GetString(ScAddress(7, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"c3"_ustr, m_pDoc->GetString(ScAddress(6, 1, 0))); + CPPUNIT_ASSERT_EQUAL(u"d4"_ustr, m_pDoc->GetString(ScAddress(7, 1, 0))); + // The third row is past the second operand, so those cells stay empty. + CPPUNIT_ASSERT_EQUAL(OUString(), m_pDoc->GetString(ScAddress(6, 2, 0))); + CPPUNIT_ASSERT_EQUAL(OUString(), m_pDoc->GetString(ScAddress(7, 2, 0))); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(TestFormula2, testMatrixOp) { m_pDoc->InsertTab(0, u"Test"_ustr); @@ -2245,8 +2489,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testFuncTableRef) { // Insert named expressions. - ScRangeName* pGlobalNames = m_pDoc->GetRangeName(); - CPPUNIT_ASSERT_MESSAGE("Failed to obtain global named expression object.", pGlobalNames); + ScRangeName& rGlobalNames = m_pDoc->GetRangeName(); for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i) { @@ -2257,7 +2500,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testFuncTableRef) = new ScRangeData(*m_pDoc, OUString::createFromAscii(aNames[i].pName), OUString::createFromAscii(aNames[i].pExpr), ScAddress(2, 4, 0), ScRangeData::Type::Name, formula::FormulaGrammar::GRAM_NATIVE); - bool bInserted = pGlobalNames->insert(pName); + bool bInserted = rGlobalNames.insert(std::unique_ptr(pName)); CPPUNIT_ASSERT_MESSAGE(OString(OString::Concat("Failed to insert named expression ") + aNames[i].pName + ".") .getStr(), @@ -2423,8 +2666,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testFuncTableRef) { // Insert named expressions. - ScRangeName* pGlobalNames = m_pDoc->GetRangeName(); - CPPUNIT_ASSERT_MESSAGE("Failed to obtain global named expression object.", pGlobalNames); + ScRangeName& rGlobalNames = m_pDoc->GetRangeName(); for (size_t i = 0; i < SAL_N_ELEMENTS(aHlNames); ++i) { @@ -2435,7 +2677,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testFuncTableRef) = new ScRangeData(*m_pDoc, OUString::createFromAscii(aHlNames[i].pName), OUString::createFromAscii(aHlNames[i].pExpr), ScAddress(6, 12, 0), ScRangeData::Type::Name, formula::FormulaGrammar::GRAM_NATIVE); - bool bInserted = pGlobalNames->insert(pName); + bool bInserted = rGlobalNames.insert(std::unique_ptr(pName)); CPPUNIT_ASSERT_MESSAGE(OString(OString::Concat("Failed to insert named expression ") + aHlNames[i].pName + ".") .getStr(), @@ -3776,7 +4018,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testTdf100818) //Insert local range name ScRangeData* pLocal = new ScRangeData(*m_pDoc, u"local"_ustr, u"$Sheet1.$A$1"_ustr); std::unique_ptr pLocalRangeName(new ScRangeName); - pLocalRangeName->insert(pLocal); + pLocalRangeName->insert(std::unique_ptr(pLocal)); m_pDoc->SetRangeName(0, std::move(pLocalRangeName)); m_pDoc->SetValue(0, 0, 0, 1.0); @@ -3944,11 +4186,11 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testIntersectionOpExcel) { CPPUNIT_ASSERT(m_pDoc->InsertTab(0, u"Test"_ustr)); - ScRangeName* pGlobalNames = m_pDoc->GetRangeName(); + ScRangeName& rGlobalNames = m_pDoc->GetRangeName(); // Horizontal cell range covering C2. - pGlobalNames->insert(new ScRangeData(*m_pDoc, u"horz"_ustr, u"$B$2:$D$2"_ustr)); + rGlobalNames.insert(std::make_unique(*m_pDoc, u"horz"_ustr, u"$B$2:$D$2"_ustr)); // Vertical cell range covering C2. - pGlobalNames->insert(new ScRangeData(*m_pDoc, u"vert"_ustr, u"$C$1:$C$3"_ustr)); + rGlobalNames.insert(std::make_unique(*m_pDoc, u"vert"_ustr, u"$C$1:$C$3"_ustr)); // Data in C2. m_pDoc->SetValue(2, 1, 0, 1.0); @@ -4331,7 +4573,7 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testFuncRefListArraySUBTOTAL) // Matrix in F7:F9, individual STDEV of A2:A3, A3:A4 and A4:A5 m_pDoc->InsertMatrixFormula(5, 6, 5, 8, aMark, u"=SUBTOTAL(7;OFFSET(A1;ROW(1:3);0;2))"_ustr); aPos.Set(5, 6, 0); - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("SUBTOTAL STDEV for A2:A3 failed", 1.414214, + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("SUBTOTAL STDEV for A2:A3 failed", M_SQRT2, m_pDoc->GetValue(aPos), 1e-6); aPos.IncRow(); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("SUBTOTAL STDEV for A3:A4 failed", 2.828427, @@ -4759,6 +5001,2790 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testVertQueryEmptyCell) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillErrorBasic) +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // Put data in A2 that will block the spill range of a matrix formula. + m_pDoc->SetValue(ScAddress(0, 1, 0), 99.0); + + // Insert a matrix formula in A1:A3 with spill check enabled. + // A2 contains data, so this should produce a spill error on the origin cell A1. + m_pDoc->InsertMatrixFormula(0, 0, 0, 2, aMark, u"=LEN(B1:B3)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("A1 should contain a formula cell.", pFormulaCell != nullptr); + + // The origin cell should have the spill error. + CPPUNIT_ASSERT_EQUAL_MESSAGE("A1 should have a spill error.", sal_Int32(FormulaError::Spill), + sal_Int32(pFormulaCell->GetErrCode())); + + // Cell should display a spill error. + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(ScAddress(0, 0, 0))); + + // The master is collapsed to 1x1 in spill state so the blocker is preserved. + SCCOL nCols = -1; + SCROW nRows = -1; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nRows); + + // The blocking cell A2 should still contain its original value. + CPPUNIT_ASSERT_EQUAL(99.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + + // A3 should remain empty. + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 2, 0))); + + // Delete the blocker and the matrix should auto resolve and expand to 1x3. + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aBlockerMark(m_pDoc->GetSheetLimits()); + aBlockerMark.SelectOneTable(0); + aBlockerMark.SetMarkArea(ScRange(ScAddress(0, 1, 0))); + rFunc.DeleteContents(aBlockerMark, InsertDeleteFlags::CONTENTS, true, true); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(3), nRows); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillErrorNoBlockingData) +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // The target range A1:A3 is completely empty - no spill error should occur. + m_pDoc->InsertMatrixFormula(0, 0, 0, 2, aMark, u"=LEN(B1:B3)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("A1 should contain a formula cell.", pFormulaCell != nullptr); + + // No error - range was empty, so the matrix expanded normally. + CPPUNIT_ASSERT_EQUAL_MESSAGE("A1 should have no error.", sal_Int32(FormulaError::NONE), + sal_Int32(pFormulaCell->GetErrCode())); + + // Should be a 1x3 matrix. + SCCOL nCols = -1; + SCROW nRows = -1; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(3), nRows); + + // A2 and A3 should be matrix reference cells. + CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA, m_pDoc->GetCellType(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA, m_pDoc->GetCellType(ScAddress(0, 2, 0))); + + const ScFormulaCell* pRef = m_pDoc->GetFormulaCell(ScAddress(0, 1, 0)); + CPPUNIT_ASSERT_MESSAGE("A2 should contain a formula cell.", pRef != nullptr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("A2 should be a matrix reference cell.", ScMatrixMode::Reference, + pRef->GetMatrixFlag()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillErrorMultiColumn) +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // Place blocking data at B2 (inside a 2x2 matrix range A1:B2). + m_pDoc->SetString(ScAddress(1, 1, 0), u"blocker"_ustr); + + // Insert a 2x2 matrix formula in A1:B2 with spill check. + m_pDoc->InsertMatrixFormula(0, 0, 1, 1, aMark, u"=LEN(C1:D2)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("A1 should contain a formula cell.", pFormulaCell != nullptr); + + // Should be a spill error because B2 has data. + CPPUNIT_ASSERT_EQUAL_MESSAGE("A1 should have a spill error.", sal_Int32(FormulaError::Spill), + sal_Int32(pFormulaCell->GetErrCode())); + + // The blocking cell B2 should still contain its original string. + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(1, 1, 0))); + + // A2, B1 should remain empty - no reference cells created. + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillErrorDisabledByDefault) +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // Place data in A2 that would block a spill. + m_pDoc->SetValue(ScAddress(0, 1, 0), 42.0); + + // Insert a matrix formula without spill check. + // This should succeed and overwrite A2. + m_pDoc->InsertMatrixFormula(0, 0, 0, 2, aMark, u"=LEN(B1:B3)"_ustr); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("A1 should contain a formula cell.", pFormulaCell != nullptr); + + // No spill error - overwrites existing cells. + CPPUNIT_ASSERT_EQUAL_MESSAGE("A1 should have no error.", sal_Int32(FormulaError::NONE), + sal_Int32(pFormulaCell->GetErrCode())); + + // Should be a 1x3 matrix. + SCCOL nCols = -1; + SCROW nRows = -1; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(3), nRows); + + // A2 should now be a matrix reference cell - old value was overwritten. + CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA, m_pDoc->GetCellType(ScAddress(0, 1, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillErrorSingleCell) +{ + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // A single-cell matrix formula should never produce a spill error, + // because there's nothing to spill into. + m_pDoc->SetValue(ScAddress(0, 1, 0), 99.0); // A2 has data, but range is only A1. + m_pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, u"=SUM(B1:B3)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("A1 should contain a formula cell.", pFormulaCell != nullptr); + + // No spill error for a 1x1 matrix. + CPPUNIT_ASSERT_EQUAL_MESSAGE("Single-cell matrix should not produce a spill error.", + sal_Int32(FormulaError::NONE), + sal_Int32(pFormulaCell->GetErrCode())); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillErrorAutoExpand) +{ + // Test that auto-expanding array formulas produce a spill error + // when the target range has non-empty cells. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Source data in B1:B3. + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + + // Place a blocker in A2 + m_pDoc->SetString(ScAddress(0, 1, 0), u"blocker"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // Enter a formula via ScDocFunc::EnterMatrix simulating the auto-expand path + ScRange aRange(0, 0, 0, 0, 2, 0); // A1:A3 + ScDocFunc& rDocFunc = m_xDocShell->GetDocFunc(); + rDocFunc.EnterMatrix(aRange, &aMark, nullptr, u"=B1:B3"_ustr, true, false, OUString(), + formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("A1 should contain a formula cell.", pFormulaCell != nullptr); + + // Should be a spill error - blocker in A2. + CPPUNIT_ASSERT_EQUAL_MESSAGE("A1 should have a spill error.", sal_Int32(FormulaError::Spill), + sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(ScAddress(0, 0, 0))); + + // Blocker should still be there. + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 1, 0))); + + // A3 should remain empty. + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillErrorAutoExpandEmpty) +{ + // Test that auto-expanding array formulas succeed when the range is empty. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Source data in B1:B3. + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + + // A1:A3 is empty - auto-expand should work. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + ScRange aRange(0, 0, 0, 0, 2, 0); // A1:A3 + ScDocFunc& rDocFunc = m_xDocShell->GetDocFunc(); + rDocFunc.EnterMatrix(aRange, &aMark, nullptr, u"=B1:B3"_ustr, true, false, OUString(), + formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("A1 should contain a formula cell.", pFormulaCell != nullptr); + + // No spill error - range was empty. + CPPUNIT_ASSERT_EQUAL_MESSAGE("A1 should have no error.", sal_Int32(FormulaError::NONE), + sal_Int32(pFormulaCell->GetErrCode())); + + // The formula should have spilled into A2 and A3. + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + + // A2 should be a matrix reference cell. + const ScFormulaCell* pRef = m_pDoc->GetFormulaCell(ScAddress(0, 1, 0)); + CPPUNIT_ASSERT_MESSAGE("A2 should be a formula cell.", pRef != nullptr); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Reference, pRef->GetMatrixFlag()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillErrorOverwrites) +{ + // Test that no check for spill still overwrites + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + + // Place a blocker. + m_pDoc->SetString(ScAddress(0, 1, 0), u"blocker"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + ScRange aRange(0, 0, 0, 0, 2, 0); // A1:A3 + ScDocFunc& rDocFunc = m_xDocShell->GetDocFunc(); + // Static Ctrl+Shift+Enter master: bDynamicArrayMaster=false. + rDocFunc.EnterMatrix(aRange, &aMark, nullptr, u"=B1:B3"_ustr, true, false, OUString(), + formula::FormulaGrammar::GRAM_DEFAULT, false); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("A1 should contain a formula cell.", pFormulaCell != nullptr); + + // No spill error + CPPUNIT_ASSERT_EQUAL_MESSAGE("CSE should not produce a spill error.", + sal_Int32(FormulaError::NONE), + sal_Int32(pFormulaCell->GetErrCode())); + + // The blocker should have been overwritten. + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillMatrixResolveAfterBlockerDelete) +{ + // A dynamic array formula whose spill range is blocked shows #SPILL!. + // Deleting the blocker and running spill resolution expands the matrix + // to the full result. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Source data B1:B4 with 4 unique values. + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + // Place a blocker at A2. + m_pDoc->SetString(ScAddress(0, 1, 0), u"blocker"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, u"=UNIQUE(B1:B4)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster=*/true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + + // Clear the blocker and trigger spill resolution -> matrix should expand. + m_pDoc->SetString(ScAddress(0, 1, 0), u""_ustr); + m_xDocShell->ResolveSpilledOutputs(); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(4), nRows); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, m_pDoc->GetValue(ScAddress(0, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSequenceFormulaResolveAfterBlockerIsDeleted) +{ + // Insert a SEQUENCE formula that is blocked by a blocker cell, which causes + // a spill error, then remove the blocker and check the result was expanded. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // Blocker at A2 + rFunc.SetStringCell(ScAddress(0, 1, 0), u"blocker"_ustr, true); + + // SEQUENCE(4) entered, blocked by the blocker in A2 + rFunc.EnterMatrix(ScRange(0, 0, 0, 0, 3, 0), &aMark, nullptr, u"=SEQUENCE(4)"_ustr, true, false, + OUString(), formula::FormulaGrammar::GRAM_DEFAULT, true); + + // Spill error is expected + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + + // The master must be collapsed to 1x1 so the blocker is preserved. + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nRows); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 1, 0))); + + // Delete the blocker - matrix must expand. + ScMarkData aBlockerMark(m_pDoc->GetSheetLimits()); + aBlockerMark.SelectOneTable(0); + aBlockerMark.SetMarkArea(ScRange(ScAddress(0, 1, 0))); + rFunc.DeleteContents(aBlockerMark, InsertDeleteFlags::CONTENTS, true, true); + + // No error expected + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + + // Result size should be 1x4 + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(4), nRows); + + // Expected result for a sequence formula + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(0, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillMatrixCollapsesOnRefCellEdit) +{ + // Writing into a reference cell of an expanded matrix master collapses + // the matrix to #SPILL!. The user visible UI flow is "type into a cell + // covered by TRANSPOSE, SEQUENCE, ...". Both conventional matrix formulas + // and dynamic array formulas behave the same way. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Source data A1:A4 + m_pDoc->SetValue(ScAddress(0, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(0, 3, 0), 40.0); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // Add TRANSPOSE formula to C1 + rFunc.EnterMatrix(ScRange(2, 0, 0, 5, 0, 0), &aMark, nullptr, u"=TRANSPOSE(A1:A4)"_ustr, true, + false, OUString(), formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(2, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, m_pDoc->GetValue(ScAddress(5, 0, 0))); + + // User types into a reference cell. The master must collapse to #SPILL! + // and the typed value must remain. + rFunc.SetStringCell(ScAddress(4, 0, 0), u"blocker"_ustr, true); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nRows); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(4, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testWriteToMasterReplacesWholeMatrix) +{ + // Writing a value into the master cell of a multi-cell matrix replaces + // the whole matrix (master plus reference cells) with the new value. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(0, 3, 0), 40.0); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // Enter TRANSPOSE formula + rFunc.EnterMatrix(ScRange(2, 0, 0, 5, 0, 0), &aMark, nullptr, u"=TRANSPOSE(A1:A4)"_ustr, true, + false, OUString(), formula::FormulaGrammar::GRAM_DEFAULT, true); + + CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA, m_pDoc->GetCellType(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA, m_pDoc->GetCellType(ScAddress(5, 0, 0))); + + // User selects only the master cell and types "hello". + bool bDummy = false; + rFunc.SetNormalString(bDummy, ScAddress(2, 0, 0), u"hello"_ustr, /*bApi*/ true); + + // The whole matrix should be gone. The typed value sits at the master cell. + CPPUNIT_ASSERT_EQUAL(u"hello"_ustr, m_pDoc->GetString(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(3, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(4, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(5, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testDeleteMasterDeletesWholeMatrix) +{ + // Pressing Delete on the master cell of a multi-cell matrix deletes + // the whole matrix (master plus reference cells), not just the master. + // Without this, the matrix-fragment protection refuses the operation. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(0, 3, 0), 40.0); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // TRANSPOSE(A1:A4) at C1 expanded into 4x1. + rFunc.EnterMatrix(ScRange(2, 0, 0, 5, 0, 0), &aMark, nullptr, u"=TRANSPOSE(A1:A4)"_ustr, true, + false, OUString(), formula::FormulaGrammar::GRAM_DEFAULT, true); + + CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA, m_pDoc->GetCellType(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_FORMULA, m_pDoc->GetCellType(ScAddress(5, 0, 0))); + + // User selects the master cell (single cell) and presses Delete. + ScMarkData aMasterMark(m_pDoc->GetSheetLimits()); + aMasterMark.SelectOneTable(0); + aMasterMark.SetMarkArea(ScRange(ScAddress(2, 0, 0))); + rFunc.DeleteContents(aMasterMark, InsertDeleteFlags::CONTENTS, true, true); + + // Master and all reference cells must be empty. + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(3, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(4, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(5, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillMatrixUndoRedoRefCellBlocker) +{ + // Writing a blocker into a reference cell of an expanded matrix + // collapses the master to #SPILL!. Undoing that write must restore + // the reference cell and re-expand the matrix. The blocker no + // longer exists so the master should be back to its full result. + // Redo must re-blocker and re-collapse. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // UNIQUE(B1:B4) expanded into A1:A4. + rFunc.EnterMatrix(ScRange(0, 0, 0, 0, 3, 0), &aMark, nullptr, u"=UNIQUE(B1:B4)"_ustr, true, + false, OUString(), formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + + auto assertExpanded = [&](const char* label) { + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, sal_Int32(FormulaError::NONE), + sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, SCROW(4), nRows); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 40.0, m_pDoc->GetValue(ScAddress(0, 3, 0))); + }; + + assertExpanded("Initial state"); + + // Add a blocker into a reference cell. + bool bDummy = false; + rFunc.SetNormalString(bDummy, ScAddress(0, 3, 0), u"blocker"_ustr, /*bApi*/ true); + + // Master should collapse. + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 3, 0))); + + SfxUndoManager* pUndoManager = m_pDoc->GetUndoManager(); + CPPUNIT_ASSERT(pUndoManager); + + // Undo - matrix must be fully expanded again, blocker gone. + pUndoManager->Undo(); + assertExpanded("After Undo"); + + // Redo - blocker back, master collapsed. + pUndoManager->Redo(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillMatrixUndoOfDeleteRestoresTracking) +{ + // Deleting the master cell of an expanded matrix removes the whole + // matrix and untracks it. Undoing must restore the matrix and put it + // back in the expanded matrix tracking set, so a subsequent blocker + // write into one of the reference cells can collapse it to #SPILL!. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(0, 3, 0), 40.0); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // TRANSPOSE expanded into C1:F1. + rFunc.EnterMatrix(ScRange(2, 0, 0, 5, 0, 0), &aMark, nullptr, u"=TRANSPOSE(A1:A4)"_ustr, true, + false, OUString(), formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(2, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + + // Delete the master cell - whole matrix should vanish. + ScMarkData aMasterMark(m_pDoc->GetSheetLimits()); + aMasterMark.SelectOneTable(0); + aMasterMark.SetMarkArea(ScRange(ScAddress(2, 0, 0))); + rFunc.DeleteContents(aMasterMark, InsertDeleteFlags::CONTENTS, true, true); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(5, 0, 0))); + + // Undo - matrix back. + SfxUndoManager* pUndoManager = m_pDoc->GetUndoManager(); + CPPUNIT_ASSERT(pUndoManager); + pUndoManager->Undo(); + + pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(2, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, m_pDoc->GetValue(ScAddress(5, 0, 0))); + + // Drop a blocker into a reference cell - master must collapse. + bool bDummy = false; + rFunc.SetNormalString(bDummy, ScAddress(3, 0, 0), u"blocker"_ustr, /*bApi*/ true); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(3, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillMatrixContractionOnValueChange) +{ + // A dynamic array formula shrinks when its source data produces fewer + // values: the matrix contracts and the freed cells are cleared. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 3, aMark, u"=UNIQUE(B1:B4)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster=*/true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + + // Make B4 a duplicate of B1 -> UNIQUE returns only 3 values. + m_pDoc->SetValue(ScAddress(1, 3, 0), 10.0); + m_pDoc->CalcFormulaTree(); + + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(3), nRows); + + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + // A4 cell should be cleared. + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillMatrixAutoResolveOnValueChange) +{ + // Both directions of auto-spill via AutoCalc. A blocked matrix shows + // #SPILL!. Shrinking the result to fit auto-resolves it. Growing it + // back re-triggers #SPILL! and clears the materialised cells. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + // Blocker at A4 - inside the 4-row spill range. + m_pDoc->SetString(ScAddress(0, 3, 0), u"blocker"_ustr); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, u"=UNIQUE(B1:B4)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster=*/true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + + // Make B4 a duplicate - now UNIQUE returns 3 values, fitting in A1:A3. + // A4's "blocker" is outside the spill range, so the spill auto-resolves. + m_pDoc->SetValue(ScAddress(1, 3, 0), 10.0); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(3), nRows); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + + // Blocker must be preserved. + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 3, 0))); + + // Restore B4 to a unique value + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 2, 0))); + // Blocker must be preserved. + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillMatrixComplexScenario) +{ + // End-to-end check via ScDocFunc: covers spill, auto-resolve + // and re-collapse along the same code path a user edit goes + // through. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + rFunc.SetValueCell(ScAddress(1, 0, 0), 10.0, false); + rFunc.SetValueCell(ScAddress(1, 1, 0), 20.0, false); + rFunc.SetValueCell(ScAddress(1, 2, 0), 30.0, false); + rFunc.SetValueCell(ScAddress(1, 3, 0), 40.0, false); + + // Blocker at A4 - inside the 4-row spill range. + rFunc.SetStringCell(ScAddress(0, 3, 0), u"blocker"_ustr, true); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, u"=UNIQUE(B1:B4)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster=*/true); + + // We expect the spill error + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + + // Change B4 to the same value as preceding value, so UNIQUE shrinks to 3 rows + rFunc.SetValueCell(ScAddress(1, 3, 0), 10.0, false); + + // Spill auto resolves. A4's "blocker" is outside the new range. + pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 3, 0))); + + // Restore B4 to a unique value, so UNIQUE wants 4 rows again + rFunc.SetValueCell(ScAddress(1, 3, 0), 40.0, false); + + // A4's "blocker" now blocks, matrix must collapse to 1x1 with #SPILL! and + // A2 and A3 ref cells must be cleared. + pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 3, 0))); + + // Clear the blocker - formula should expand + rFunc.SetStringCell(ScAddress(0, 3, 0), u""_ustr, false); + + pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::NONE), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, m_pDoc->GetValue(ScAddress(0, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillMatrixUndoRedoBlockerDelete) +{ + // UNIQUE blocked by a cell shows #SPILL!. Removing the blocker via + // expands the matrix. Undo must restore the blocker and the #SPILL! + // state. Redo must clear the blocker and expand the matrix again. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Source data and blocker. + insertRangeData(m_pDoc, ScAddress(0, 0, 0), + { + { nullptr, "10" }, + { "blocker", "20" }, + { nullptr, "30" }, + { nullptr, "40" }, + }); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // UNIQUE matrix at A1. + rFunc.EnterMatrix(ScRange(ScAddress(0, 0, 0)), &aMark, nullptr, u"=UNIQUE(B1:B4)"_ustr, true, + false, OUString(), formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster*/ true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + + // Delete the blocker. + ScMarkData aBlockerMark(m_pDoc->GetSheetLimits()); + aBlockerMark.SelectOneTable(0); + aBlockerMark.SetMarkArea(ScRange(ScAddress(0, 1, 0))); + rFunc.DeleteContents(aBlockerMark, InsertDeleteFlags::CONTENTS, true, true); + + auto assertExpanded = [&](const char* label) { + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, sal_Int32(FormulaError::NONE), + sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, SCROW(4), nRows); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 40.0, m_pDoc->GetValue(ScAddress(0, 3, 0))); + }; + + assertExpanded("After Delete"); + + // Undo - blocker should be back, matrix should re-spill. + SfxUndoManager* pUndoManager = m_pDoc->GetUndoManager(); + CPPUNIT_ASSERT(pUndoManager); + pUndoManager->Undo(); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(FormulaError::Spill), sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(OUString(), m_pDoc->GetString(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(OUString(), m_pDoc->GetString(ScAddress(0, 3, 0))); + + // Redo - blocker cleared, matrix expanded again. + pUndoManager->Redo(); + + assertExpanded("After Redo"); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpillMatrixUndoRedoInputChange) +{ + // UNIQUE blocked by a cell shows #SPILL!. Changing the source data so + // the result no longer overflows the declared range resolves the + // spill. The matrix expands to fit. Undo of the source change must + // restore the spilled state and redo must resolve it again. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Source data and blocker. + insertRangeData(m_pDoc, ScAddress(0, 0, 0), + { + { nullptr, "10" }, + { nullptr, "20" }, + { nullptr, "30" }, + { "blocker", "40" }, + }); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // UNIQUE matrix at A1. + rFunc.EnterMatrix(ScRange(ScAddress(0, 0, 0)), &aMark, nullptr, u"=UNIQUE(B1:B4)"_ustr, true, + false, OUString(), formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster*/ true); + + ScFormulaCell* pFormulaCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFormulaCell); + + auto assertSpilled = [&](const char* label) { + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, sal_Int32(FormulaError::Spill), + sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, u"#SPILL!"_ustr, m_pDoc->GetString(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, OUString(), m_pDoc->GetString(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, OUString(), m_pDoc->GetString(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 3, 0))); + }; + + auto assertResolved = [&](const char* label) { + // UNIQUE collapsed to three values, fits in A1:A3, blocker at A4 + // is outside the matrix range and stays. + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, sal_Int32(FormulaError::NONE), + sal_Int32(pFormulaCell->GetErrCode())); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, SCROW(3), nRows); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, 30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL_MESSAGE(label, u"blocker"_ustr, m_pDoc->GetString(ScAddress(0, 3, 0))); + }; + + assertSpilled("Initial"); + + // Change value 40 to 10, which resolves the blockage as the data fits + // the available output range. + rFunc.SetValueCell(ScAddress(1, 3, 0), 10.0, /*bInteraction*/ false); + assertResolved("After value change"); + + SfxUndoManager* pUndoManager = m_pDoc->GetUndoManager(); + CPPUNIT_ASSERT(pUndoManager); + + pUndoManager->Undo(); + assertSpilled("After Undo"); + + pUndoManager->Redo(); + assertResolved("After Redo"); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testDynamicArrayFlagCopy) +{ + // The mbDynamicArrayFunction flag on FormulaTokenArray is set by the + // compiler when it sees UNIQUE, FILTER, SORT... (dynamic array formula). + // The flag must survive copy, move, clone operations otherwise a cloned + // formula silently loses its dynamic array behaviour. + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, u"=UNIQUE(B1:B2)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, true); + + const ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + const ScTokenArray* pCode = pCell->GetCode(); + CPPUNIT_ASSERT(pCode); + CPPUNIT_ASSERT_MESSAGE("dynamic array flag should be true for UNIQUE", + pCode->HasDynamicArrayFunction()); + + // Copy + ScTokenArray aCopy(*pCode); + CPPUNIT_ASSERT_MESSAGE("dynamic array flag should survive copy", + aCopy.HasDynamicArrayFunction()); + + // Move + ScTokenArray aSource(*pCode); + ScTokenArray aMoved(std::move(aSource)); + CPPUNIT_ASSERT_MESSAGE("dynamic array flag should survive move", + aMoved.HasDynamicArrayFunction()); + + // Clone + std::unique_ptr pClone = pCode->Clone(); + CPPUNIT_ASSERT_MESSAGE("dynamic array flag should survive Clone", + pClone->HasDynamicArrayFunction()); + + // CloneValue + ScTokenArray aCloneValue = pCode->CloneValue(); + CPPUNIT_ASSERT_MESSAGE("dynamic array flag should survive CloneValue", + aCloneValue.HasDynamicArrayFunction()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSingleValueOperator) +{ + // @ collapses an array operand or a bare range to a single slot. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // @SEQUENCE collapses the spilled array. The row below stays empty. + m_pDoc->SetFormula(ScAddress(0, 0, 0), u"=@SEQUENCE(4)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 1, 0))); + + // Bare-range @ picks the slot whose row matches the formula row, + // and pushes #VALUE! when no slot matches. + m_pDoc->SetValue(ScAddress(1, 1, 0), 7.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 9.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 11.0); + m_pDoc->SetFormula(ScAddress(3, 1, 0), u"=@B2:B4"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + m_pDoc->SetFormula(ScAddress(3, 2, 0), u"=@B2:B4"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + m_pDoc->SetFormula(ScAddress(3, 3, 0), u"=@B2:B4"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + m_pDoc->SetFormula(ScAddress(3, 4, 0), u"=@B2:B4"_ustr, formula::FormulaGrammar::GRAM_NATIVE); + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(3, 1, 0))); + CPPUNIT_ASSERT_EQUAL(9.0, m_pDoc->GetValue(ScAddress(3, 2, 0))); + CPPUNIT_ASSERT_EQUAL(11.0, m_pDoc->GetValue(ScAddress(3, 3, 0))); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 4, 0))); + + // @ on a computed expression returns the upper-left of the + // produced array, even when the formula sits in a row that does + // not overlap the source. + m_pDoc->SetFormula(ScAddress(0, 5, 0), u"=@(B2:B3+0)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 5, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 6, 0))); + + // Two @-collapsed sub-expressions joined by a binary operator stay + // scalar. Without the collapse on each side the addition would see + // two arrays and produce one too, leaving the row below populated. + m_pDoc->SetFormula(ScAddress(0, 8, 0), u"=@((B2:B3+0)) + @((B2:B3+0))"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + CPPUNIT_ASSERT_EQUAL(14.0, m_pDoc->GetValue(ScAddress(0, 8, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 9, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testDynamicArrayMasterSurvivesCellCopy) +{ + // A copy of a dynamic-array master is itself a dynamic-array master. + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetFormula(ScAddress(0, 0, 0), u"=SEQUENCE(4)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + + // A fresh formula cell is not a dynamic-array master by default. + CPPUNIT_ASSERT(!pCell->IsDynamicArrayMaster()); + + pCell->SetDynamicArrayMaster(true); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + + std::unique_ptr pClone(pCell->Clone()); + CPPUNIT_ASSERT(pClone); + CPPUNIT_ASSERT(pClone->IsDynamicArrayMaster()); + + pCell->SetDynamicArrayMaster(false); + std::unique_ptr pPlainClone(pCell->Clone()); + CPPUNIT_ASSERT(pPlainClone); + CPPUNIT_ASSERT(!pPlainClone->IsDynamicArrayMaster()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSingleValueDroppedOnOdfSave) +{ + // ODF has no place for the @ implicit-intersection operator. The + // formula compiler strips @ on save regardless of the ODF version. + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetFormula(ScAddress(0, 0, 0), u"=@TRANSPOSE(B1:B4)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(pCell->GetCode()); + + sc::CompileFormulaContext aContext(*m_pDoc, formula::FormulaGrammar::GRAM_ODFF); + aContext.setODFSavingVersion(SvtSaveOptions::ODFSVER_014_EXTENDED); + ScCompiler aCompiler(aContext, pCell->aPos, *pCell->GetCode()); + OUStringBuffer aBuffer; + aCompiler.CreateStringFromTokenArray(aBuffer); + CPPUNIT_ASSERT_EQUAL(u"TRANSPOSE([.B1:.B4])"_ustr, aBuffer.makeStringAndClear()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testDynamicArrayMasterGrowsOnRecalc) +{ + // A matrix master flagged dynamic grows its declared range on recalc + // to match the actual result, even when the top-level call is not in + // HasDynamicArrayFunction. TRANSPOSE is one such call. + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // 1x1 static master at A6 with =TRANSPOSE(B1:B4). The flag stays off so + // the cell does not auto-resize on the first interpret. The test then + // opts the cell into dynamic-array mode and verifies the resize. + m_pDoc->InsertMatrixFormula(0, 5, 0, 5, aMark, u"=TRANSPOSE(B1:B4)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT); + m_pDoc->CalcAll(); + + ScFormulaCell* pMaster = m_pDoc->GetFormulaCell(ScAddress(0, 5, 0)); + CPPUNIT_ASSERT(pMaster); + + // Without the flag the declared 1x1 range is honoured even though the + // result is wider. + SCCOL nDeclCols = 0; + SCROW nDeclRows = 0; + pMaster->GetMatColsRows(nDeclCols, nDeclRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nDeclCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nDeclRows); + + // Opt the cell into dynamic-array mode and recalc. The declared range + // should now grow to 4x1 and the spilled values should land in B6:D6. + pMaster->SetDynamicArrayMaster(true); + pMaster->SetDirty(); + m_pDoc->CalcAll(); + + pMaster->GetMatColsRows(nDeclCols, nDeclRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(4), nDeclCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nDeclRows); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 5, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(1, 5, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(2, 5, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, m_pDoc->GetValue(ScAddress(3, 5, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testDynamicArrayMasterFlagDrivesRangeReferenceResize) +{ + // A bare multi-cell range reference at the top grows the declared + // range on recalc when the cell carries the dynamic-array flag. + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // 1x1 static master at A6 with =B1:B4. The flag stays off so the cell + // does not auto-resize on the first interpret. The test then opts the + // cell into dynamic-array mode and verifies the resize. + m_pDoc->InsertMatrixFormula(0, 5, 0, 5, aMark, u"=B1:B4"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT); + m_pDoc->CalcAll(); + + ScFormulaCell* pMaster = m_pDoc->GetFormulaCell(ScAddress(0, 5, 0)); + CPPUNIT_ASSERT(pMaster); + + SCCOL nDeclCols = 0; + SCROW nDeclRows = 0; + pMaster->GetMatColsRows(nDeclCols, nDeclRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nDeclCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nDeclRows); + + pMaster->SetDynamicArrayMaster(true); + pMaster->SetDirty(); + m_pDoc->CalcAll(); + + pMaster->GetMatColsRows(nDeclCols, nDeclRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nDeclCols); + CPPUNIT_ASSERT_EQUAL(SCROW(4), nDeclRows); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 5, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0, 6, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(0, 7, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, m_pDoc->GetValue(ScAddress(0, 8, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testDynamicArrayResizeDuringCopyToClip) +{ + // A dynamic-array resize queued during CopyToClip must run after the clipboard clone is made. + + m_pDoc->SetAutoCalc(false); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + // 1x1 master whose actual result wants 1x4, so Interpret will queue an expand. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, u"=UNIQUE(B1:B4)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster=*/true); + + ScFormulaCell* pMaster = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pMaster); + CPPUNIT_ASSERT(pMaster->GetDirty()); + SCCOL nDeclCols = 0; + SCROW nDeclRows = 0; + pMaster->GetMatColsRows(nDeclCols, nDeclRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nDeclCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nDeclRows); + + // AutoCalc on so the handler's Interpret call actually runs. + m_pDoc->SetAutoCalc(true); + + ScDocument aClipDoc(SCDOCMODE_CLIP); + ScRange aRange(0, 0, 0, 0, 0, 0); + ScClipParam aClipParam(aRange, false); + m_pDoc->CopyToClip(aClipParam, &aClipDoc, &aMark, false, false); + + // Clipboard reflects the 1x1 visible at copy time, not the post-resize 1x4. + ScFormulaCell* pClipMaster = aClipDoc.GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pClipMaster); + SCCOL nClipCols = 0; + SCROW nClipRows = 0; + pClipMaster->GetMatColsRows(nClipCols, nClipRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nClipCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nClipRows); + + // The deferred expand should have run by now, so the source is 1x4. + pMaster->GetMatColsRows(nDeclCols, nDeclRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nDeclCols); + CPPUNIT_ASSERT_EQUAL(SCROW(4), nDeclRows); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(0, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, m_pDoc->GetValue(ScAddress(0, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testDynamicArrayResizeDuringCopyStaticToDocument) +{ + // A dynamic-array resize must not run mid-walk. The hand-rolled loop tracks rows itself and drifts. + + m_pDoc->SetAutoCalc(false); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + // 1x1 master whose actual result wants 1x4. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, u"=UNIQUE(B1:B4)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, true); + + // Static cell past the spill range. Iterator drift would misplace it. + m_pDoc->SetValue(ScAddress(0, 5, 0), 999.0); + + m_pDoc->SetAutoCalc(true); + + ScDocShellRef xDestSh + = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS + | SfxModelFlags::DISABLE_DOCUMENT_RECOVERY); + xDestSh->DoInitUnitTest(); + ScDocument* pDestDoc = &xDestSh->GetDocument(); + pDestDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->CopyStaticToDocument(ScRange(0, 0, 0, 0, 5, 0), 0, *pDestDoc); + + // A6 in src must reach A6 in dest, not a row the iterator drifted onto. + CPPUNIT_ASSERT_EQUAL(999.0, pDestDoc->GetValue(ScAddress(0, 5, 0))); + + pDestDoc->DeleteTab(0); + xDestSh->DoClose(); + xDestSh.clear(); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testDynamicArrayResizeDuringCopyUpdated) +{ + // CopyUpdated reuses CopyToClipHandler, so it shares the same mid-walk-resize hazard. + + m_pDoc->SetAutoCalc(false); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 0, aMark, u"=UNIQUE(B1:B4)"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, true); + + ScFormulaCell* pMaster = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pMaster); + CPPUNIT_ASSERT(pMaster->GetDirty()); + + m_pDoc->SetAutoCalc(true); + + // Position doc selects A1. Dest doc collects clones. + ScDocument aPosDoc(SCDOCMODE_UNDO); + aPosDoc.InitUndo(*m_pDoc, 0, 0, true, true); + aPosDoc.SetValue(ScAddress(0, 0, 0), 1.0); + + ScDocument aDestDoc(SCDOCMODE_UNDO); + aDestDoc.InitUndo(*m_pDoc, 0, 0, false, false); + aDestDoc.AddUndoTab(0, 0); + + m_pDoc->CopyUpdated(&aPosDoc, &aDestDoc); + + // Dest clone reflects the pre-resize 1x1, not the post-resize 1x4. + ScFormulaCell* pDestMaster = aDestDoc.GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pDestMaster); + SCCOL nClipCols = 0; + SCROW nClipRows = 0; + pDestMaster->GetMatColsRows(nClipCols, nClipRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nClipCols); + CPPUNIT_ASSERT_EQUAL(SCROW(1), nClipRows); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testEnterMatrixUndoRedoKeepsDynamicFlag) +{ + // Entering a dynamic-array master through EnterMatrix, undoing, + // and redoing must restore the dynamic-array flag on the redone + // cell. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + rFunc.EnterMatrix(ScRange(ScAddress(0, 0, 0)), &aMark, nullptr, u"=UNIQUE(B1:B4)"_ustr, true, + false, OUString(), formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster*/ true); + + ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + + SfxUndoManager* pUndoManager = m_pDoc->GetUndoManager(); + CPPUNIT_ASSERT(pUndoManager); + + pUndoManager->Undo(); + CPPUNIT_ASSERT(!m_pDoc->GetFormulaCell(ScAddress(0, 0, 0))); + + pUndoManager->Redo(); + + pCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testUnknownNameRoundTrip) +{ + // An unknown name evaluates to a name error and its text survives in the + // stored formula expression. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScAddress aPosition(0, 0, 0); + m_pDoc->SetString(aPosition, u"=ZZUNKNOWNZZ"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"#NAME?"_ustr, m_pDoc->GetString(aPosition)); + + // Casing of the round-tripped name is not guaranteed, so match without + // regard to case. + OUString aFormula = m_pDoc->GetFormula(0, 0, 0); + CPPUNIT_ASSERT(!aFormula.isEmpty()); + CPPUNIT_ASSERT_MESSAGE(aFormula.toUtf8().getStr(), + aFormula.equalsIgnoreAsciiCase(u"=ZZUNKNOWNZZ")); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testCopyCellDropsAutoDynamicEligibility) +{ + // A clone (paste, fill, transpose) drops the auto-promotion + // eligibility, even at a destination position that would + // otherwise promote. + + m_pDoc->SetAutoCalc(false); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(0, 3, 0), 40.0); + + ScAddress aSourcePos(2, 0, 0); + ScCompiler aComp(*m_pDoc, aSourcePos, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pCode = aComp.CompileString(u"=UNIQUE(A1:A4)"_ustr); + auto pSource = new ScFormulaCell(*m_pDoc, aSourcePos, std::move(pCode)); + pSource->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aSourcePos, pSource); + + ScAddress aCopyPos(3, 0, 0); + auto pCopy = new ScFormulaCell(*pSource, *m_pDoc, aCopyPos); + m_pDoc->SetFormulaCell(aCopyPos, pCopy); + + m_pDoc->SetAutoCalc(true); + m_pDoc->CalcAll(); + + CPPUNIT_ASSERT(pSource->IsDynamicArrayMaster()); + CPPUNIT_ASSERT(!pCopy->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::NONE, pCopy->GetMatrixFlag()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testFuncLetWithOdffParameters) +{ + // A LET whose bound parameters use the ODFF _xlpm. prefix evaluates to the + // right value. The prefix starts with an underscore, which keeps the name + // from looking like an ordinary name to the compiler, so the bound + // parameters have to be resolved even in that case. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScAddress aPosition(0, 0, 0); + m_pDoc->SetFormula(aPosition, + u"=COM.MICROSOFT.LET(" + "_xlpm.first;5;" + "_xlpm.second;SUM(_xlpm.first;5);" + "_xlpm.third;SUM(_xlpm.second;5);" + "SUM(_xlpm.second;_xlpm.third))"_ustr, + formula::FormulaGrammar::GRAM_ODFF); + + CPPUNIT_ASSERT_EQUAL(25.0, m_pDoc->GetValue(aPosition)); + CPPUNIT_ASSERT_EQUAL(u"25"_ustr, m_pDoc->GetString(aPosition)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testCallBuiltInThroughCallable) +{ + // A built-in function used as a value and then called gets routed through + // the call operator. It returns the same result as calling the built-in + // directly. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Parenthesizing SUM turns it into a callable, and the following argument + // list calls it. + ScAddress aPos(0, 0, 0); + m_pDoc->SetString(aPos, u"=(SUM)(1;2;3)"_ustr); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(aPos)); + + // Binding a built-in to a LET parameter and calling that parameter takes + // the same call path. + aPos.IncRow(); + m_pDoc->SetString(aPos, u"=LET(f;SUM;f(1;2;3))"_ustr); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(aPos)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testCallBuiltInZeroAndOneArg) +{ + // A built-in called through the call operator returns the same value with + // no arguments and with one argument as the built-in does on its own. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // PI takes no arguments, so the empty list calls it with nothing. + ScAddress aPos(0, 0, 0); + m_pDoc->SetString(aPos, u"=(PI)()"_ustr); + CPPUNIT_ASSERT_EQUAL(M_PI, m_pDoc->GetValue(aPos)); + + // ABS takes one argument. + aPos.IncRow(); + m_pDoc->SetString(aPos, u"=(ABS)(-5)"_ustr); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(aPos)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testCallBuiltInChosenByFunction) +{ + // A built-in picked by IF and then called through an open paren that + // follows the closing paren of IF returns the chosen built-in's value. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // A true condition makes IF yield SUM. + ScAddress aPos(0, 0, 0); + m_pDoc->SetString(aPos, u"=IF(TRUE();SUM;MAX)(1;2;3)"_ustr); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(aPos)); + + // A false condition makes IF yield MAX. + aPos.IncRow(); + m_pDoc->SetString(aPos, u"=IF(FALSE();SUM;MAX)(1;2;3)"_ustr); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(aPos)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testCallableCallAsCallableArgument) +{ + // A call through the call operator used as an argument to another such call + // evaluates inner first and feeds its value to the outer call. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScAddress aPos(0, 0, 0); + m_pDoc->SetString(aPos, u"=(SUM)((MAX)(1;2);3)"_ustr); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(aPos)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testCallableWhereNumberExpected) +{ + // A callable handed to an operator that expects a number resolves to an + // illegal parameter error. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScAddress aPos(0, 0, 0); + m_pDoc->SetString(aPos, u"=(SUM)+1"_ustr); + CPPUNIT_ASSERT_EQUAL(u"Err:504"_ustr, m_pDoc->GetString(aPos)); + + aPos.IncRow(); + m_pDoc->SetString(aPos, u"=SUM+1"_ustr); + CPPUNIT_ASSERT_EQUAL(u"Err:504"_ustr, m_pDoc->GetString(aPos)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testAtFormulaIgnoresDynamicArrayMasterFlag) +{ + // An @-prefixed formula opts out of dynamic-array spilling. + // SetDynamicArrayMaster ignores a request to enable the flag on + // such a cell, so an OOXML cm="1" arriving on an @-cell does not + // turn into a #SPILL! at interpret time. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 2.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 3.0); + + m_pDoc->SetFormula(ScAddress(1, 0, 0), u"=@(A1:A3+0)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(1, 0, 0)); + CPPUNIT_ASSERT(pCell); + + pCell->SetDynamicArrayMaster(true); + CPPUNIT_ASSERT(!pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testMatrixConcatRendersBooleansAsTrueFalse) +{ + // A boolean value pulled into a string context renders as the + // string "TRUE" or "FALSE", not "1" or "0". The plain non-matrix + // concatenation already does this; the matrix paths through + // ScMatrixImpl::GetString and ScMatrixImpl::MatConcat are the + // ones the fix in this commit covers. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Plain scalar concatenation. Already works, kept here so a + // regression in this baseline path shows up too. + m_pDoc->SetString(ScAddress(0, 0, 0), u"=TRUE&\"!\""_ustr); + m_pDoc->SetString(ScAddress(0, 1, 0), u"=FALSE&\"!\""_ustr); + CPPUNIT_ASSERT_EQUAL(u"TRUE!"_ustr, m_pDoc->GetString(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"FALSE!"_ustr, m_pDoc->GetString(ScAddress(0, 1, 0))); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + + // Matrix concatenated with a scalar string -> ScMatrixImpl::GetString. + m_pDoc->InsertMatrixFormula(1, 0, 1, 1, aMark, u"={TRUE|FALSE}&\"!\""_ustr); + CPPUNIT_ASSERT_EQUAL(u"TRUE!"_ustr, m_pDoc->GetString(ScAddress(1, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"FALSE!"_ustr, m_pDoc->GetString(ScAddress(1, 1, 0))); + + // Matrix concatenated with another matrix -> ScMatrixImpl::MatConcat. + m_pDoc->InsertMatrixFormula(2, 0, 2, 1, aMark, u"={TRUE|FALSE}&{\"a\"|\"b\"}"_ustr); + CPPUNIT_ASSERT_EQUAL(u"TRUEa"_ustr, m_pDoc->GetString(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"FALSEb"_ustr, m_pDoc->GetString(ScAddress(2, 1, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testAutoSpillFromChooseAndLetAndLambda) +{ + // A UI-typed CHOOSE or LET whose result is a multi-cell array + // auto-promotes the cell to a dynamic-array master and spills + // the result. CHOOSE inspects each alternative slice and reports + // array if any one of them produces an array. LET recurses into + // the body slice, but not the parameters. LAMBDA never outputs + // an array. + + m_pDoc->SetAutoCalc(false); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 2.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 3.0); + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + + // CHOOSE(1; A1; A2*5; SUM(B1:B3)) picks A1, which is a single + // value. The cell at D1 does not spill, because none of the + // alternatives produce an array. + ScAddress aChoosePos1(3, 0, 0); + ScCompiler aChooseComp1(*m_pDoc, aChoosePos1, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pChooseCode1 + = aChooseComp1.CompileString(u"=CHOOSE(1; A1; A2*5; SUM(B1:B3))"_ustr); + auto pChooseCell1 = new ScFormulaCell(*m_pDoc, aChoosePos1, std::move(pChooseCode1)); + pChooseCell1->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aChoosePos1, pChooseCell1); + + // CHOOSE(2; A1:A3; B1:B3) picks B1:B3, a 3x1 column array. The + // cell at E1 spills into E1:E3 with 10, 20 and 30. + ScAddress aChoosePos2(4, 0, 0); + ScCompiler aChooseComp2(*m_pDoc, aChoosePos2, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pChooseCode2 + = aChooseComp2.CompileString(u"=CHOOSE(2; A1:A3; B1:B3)"_ustr); + auto pChooseCell2 = new ScFormulaCell(*m_pDoc, aChoosePos2, std::move(pChooseCode2)); + pChooseCell2->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aChoosePos2, pChooseCell2); + + // LET(x; A1:A3; MAX(x)*2) binds x to A1:A3 and doubles its MAX. + // The cell at F1 does not spill, because the last subexpression + // is not an array formula. + ScAddress aLetPos1(5, 0, 0); + ScCompiler aLetComp1(*m_pDoc, aLetPos1, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pLetCode1 + = aLetComp1.CompileString(u"=LET(x; A1:A3; MAX(x)*2)"_ustr); + auto pLetCell1 = new ScFormulaCell(*m_pDoc, aLetPos1, std::move(pLetCode1)); + pLetCell1->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aLetPos1, pLetCell1); + + // LET(x; A3; SEQUENCE(x;1;1;1)*2) binds x to A3 and generates a + // sequence from it. The cell at G1 spills into G1:G3 with 2, 4 + // and 6, because the last subexpression uses SEQUENCE, which + // always returns an array. + ScAddress aLetPos2(6, 0, 0); + ScCompiler aLetComp2(*m_pDoc, aLetPos2, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pLetCode2 + = aLetComp2.CompileString(u"=LET(x; 3; SEQUENCE(x;1;1;1)*2)"_ustr); + auto pLetCell2 = new ScFormulaCell(*m_pDoc, aLetPos2, std::move(pLetCode2)); + pLetCell2->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aLetPos2, pLetCell2); + + // LAMBDA(x; MAP(A1:B3; LAMBDA(y; y+x)))(6) does not spill, + // because LAMBDA never returns an array, and a called LAMBDA + // cannot offer any guarantee one way or the other. + ScAddress aLambdaPos1(7, 0, 0); + ScCompiler aLambdaComp1(*m_pDoc, aLambdaPos1, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pLambdaCode1 + = aLambdaComp1.CompileString(u"=LAMBDA(x; MAP(A1:B3; LAMBDA(y; y+x)))(6)"_ustr); + auto pLambdaCell1 = new ScFormulaCell(*m_pDoc, aLambdaPos1, std::move(pLambdaCode1)); + pLambdaCell1->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aLambdaPos1, pLambdaCell1); + + // MAKEARRAY(3; 2; LAMBDA(r; c; r*(10*c-9))) generates a 3x2 + // array. The cell at I1 spills into I1:I3 with 1, 2 and 3, + // and J1:J3 with 10, 20 and 30. + ScAddress aLambdaPos2(8, 0, 0); + ScCompiler aLambdaComp2(*m_pDoc, aLambdaPos2, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pLambdaCode2 + = aLambdaComp2.CompileString(u"=MAKEARRAY(3; 2; LAMBDA(r; c; r*(15*c-10)))"_ustr); + auto pLambdaCell2 = new ScFormulaCell(*m_pDoc, aLambdaPos2, std::move(pLambdaCode2)); + pLambdaCell2->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aLambdaPos2, pLambdaCell2); + + m_pDoc->SetAutoCalc(true); + m_pDoc->CalcAll(); + + CPPUNIT_ASSERT_MESSAGE("CHOOSE with no array branches should not auto-spill", + !pChooseCell1->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(3, 0, 0))); + + CPPUNIT_ASSERT_MESSAGE("CHOOSE with a range branch should auto-spill", + pChooseCell2->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(4, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(4, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(4, 2, 0))); + + CPPUNIT_ASSERT_MESSAGE("LET binding a range should not auto-spill on its own", + !pLetCell1->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(5, 0, 0))); + + CPPUNIT_ASSERT_MESSAGE("LET generating an array should auto-spill", + pLetCell2->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(6, 0, 0))); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(6, 1, 0))); + CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(ScAddress(6, 2, 0))); + + CPPUNIT_ASSERT_MESSAGE("LAMBDA containing an array function should not auto-spill", + !pLambdaCell1->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(7, 0, 0))); + + CPPUNIT_ASSERT_MESSAGE("Array formula containing a LAMBDA should auto-spill", + pLambdaCell2->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(5.0, m_pDoc->GetValue(ScAddress(8, 0, 0))); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(8, 1, 0))); + CPPUNIT_ASSERT_EQUAL(15.0, m_pDoc->GetValue(ScAddress(8, 2, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(9, 0, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, m_pDoc->GetValue(ScAddress(9, 1, 0))); + CPPUNIT_ASSERT_EQUAL(60.0, m_pDoc->GetValue(ScAddress(9, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testDynamicArrayIsFormula) +{ + // ISFORMULA is true for the master of a dynamic-array spill and + // false for the cells it spilled into, even though the spilled + // data came from formulas. The same input entered as a classic + // array formula keeps every cell a formula. + m_pDoc->SetAutoCalc(false); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetString(ScAddress(1, 0, 0), u"=1+10"_ustr); + m_pDoc->SetString(ScAddress(1, 1, 0), u"=1+20"_ustr); + m_pDoc->SetString(ScAddress(1, 2, 0), u"=1+30"_ustr); + + // A1 spills =B1:B3 into A1:A3 as a dynamic-array master. + ScAddress aPos(0, 0, 0); + ScCompiler aComp(*m_pDoc, aPos, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pCode = aComp.CompileString(u"=B1:B3"_ustr); + auto pCell = new ScFormulaCell(*m_pDoc, aPos, std::move(pCode)); + pCell->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aPos, pCell); + m_pDoc->SetAutoCalc(true); + m_pDoc->CalcAll(); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + + // A source cell is a real formula, but the cells the master + // spilled into are not. + m_pDoc->SetString(ScAddress(6, 0, 0), u"=ISFORMULA(B1)"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(6, 0, 0))); + + m_pDoc->SetString(ScAddress(4, 0, 0), u"=ISFORMULA(A1)"_ustr); + m_pDoc->SetString(ScAddress(4, 1, 0), u"=ISFORMULA(A2)"_ustr); + m_pDoc->SetString(ScAddress(4, 2, 0), u"=ISFORMULA(A3)"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(4, 0, 0))); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(4, 1, 0))); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(4, 2, 0))); + + // The range form agrees cell by cell: ISFORMULA over A1:A3 gives + // true, false, false across H1:H3. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(7, 0, 7, 2, aMark, u"=ISFORMULA(A1:A3)"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(7, 0, 0))); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(7, 1, 0))); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(7, 2, 0))); + + // The same =B1:B3 entered as a classic array formula at D1:D3 + // keeps every cell a formula. + m_pDoc->InsertMatrixFormula(3, 0, 3, 2, aMark, u"=B1:B3"_ustr); + m_pDoc->SetString(ScAddress(5, 0, 0), u"=ISFORMULA(D1)"_ustr); + m_pDoc->SetString(ScAddress(5, 1, 0), u"=ISFORMULA(D2)"_ustr); + m_pDoc->SetString(ScAddress(5, 2, 0), u"=ISFORMULA(D3)"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(5, 0, 0))); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(5, 1, 0))); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(5, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testFuncARRAYTOTEXTBooleanLocale) +{ + // A boolean lists as TRUE or FALSE in the current locale, so under a + // German locale ARRAYTOTEXT writes WAHR and FALSCH. + SvtSysLocaleOptions aLocaleOptions; + const OUString aPreviousLocale = aLocaleOptions.GetLanguageTag().getBcp47(); + aLocaleOptions.SetLocaleConfigString(u"de-DE"_ustr); + aLocaleOptions.Commit(); + comphelper::ScopeGuard aLocaleGuard([&aLocaleOptions, &aPreviousLocale] { + aLocaleOptions.SetLocaleConfigString(aPreviousLocale); + aLocaleOptions.Commit(); + }); + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Two boolean source cells. + m_pDoc->SetString(ScAddress(0, 0, 0), u"=TRUE()"_ustr); + m_pDoc->SetString(ScAddress(0, 1, 0), u"=FALSE()"_ustr); + + // A single boolean lists in the locale's words. + m_pDoc->SetString(ScAddress(1, 0, 0), u"=ARRAYTOTEXT(A1)"_ustr); + m_pDoc->SetString(ScAddress(1, 1, 0), u"=ARRAYTOTEXT(A2)"_ustr); + CPPUNIT_ASSERT_EQUAL(u"WAHR"_ustr, m_pDoc->GetString(ScAddress(1, 0, 0))); + CPPUNIT_ASSERT_EQUAL(u"FALSCH"_ustr, m_pDoc->GetString(ScAddress(1, 1, 0))); + + // A range lists each boolean, joined in row order with ", ". + m_pDoc->SetString(ScAddress(1, 2, 0), u"=ARRAYTOTEXT(A1:A2)"_ustr); + CPPUNIT_ASSERT_EQUAL(u"WAHR, FALSCH"_ustr, m_pDoc->GetString(ScAddress(1, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testExternalNameAsArgumentHasNoParameters) +{ + // An add-in name that stands in an argument position rather than being + // called must compile with a parameter count of zero. When the count kept + // whatever value the previously built token had left behind, interpreting + // the formula tried to pop that many arguments off the stack and underflowed + // it. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // MONTHS is a date add-in function. Here it fills the lookup-array position + // of VLOOKUP, so it is a plain operand and not a call with its own + // arguments. + m_pDoc->SetFormula(ScAddress(0, 0, 0), u"=VLOOKUP(MONTH(D8)&\"/\"&YEAR(D8),MONTHS,2)"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + + const ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pCell); + const ScTokenArray* pCode = pCell->GetCode(); + CPPUNIT_ASSERT(pCode); + + const FormulaExternalToken* pExternal = nullptr; + FormulaToken** ppTokens = pCode->GetCode(); + for (sal_uInt16 nIdx = 0; nIdx < pCode->GetCodeLen(); ++nIdx) + { + FormulaToken* pToken = ppTokens[nIdx]; + if (pToken->GetOpCode() == ocExternal && pToken->GetType() == svExternal) + { + pExternal = static_cast(pToken); + break; + } + } + CPPUNIT_ASSERT_MESSAGE("the add-in name resolves to an external token", pExternal); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), static_cast(pExternal->GetByte())); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testUndoDeleteTabRestoresCrossSheetFormula) +{ + // cool#15924: deleting a sheet turns a formula on another sheet that + // refers to it into a #REF! error. Undoing the delete brought the + // deleted sheet back, but the #REF! error was left in place on the + // other sheet instead of the original formula. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on. + + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + m_pDoc->InsertTab(1, u"Sheet2"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 42.0); + m_pDoc->SetString(ScAddress(0, 0, 1), u"=Sheet1.A1"_ustr); + CPPUNIT_ASSERT_EQUAL(42.0, m_pDoc->GetValue(ScAddress(0, 0, 1))); + + ScDocFunc& rFunc = m_xDocShell->GetDocFunc(); + CPPUNIT_ASSERT(rFunc.DeleteTable(0, true)); + + // The formula is now on the remaining sheet's tab 0 and broken. + FormulaError nError = m_pDoc->GetErrCode(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT_MESSAGE("Formula should be a #REF! error after the referenced sheet is deleted.", + nError != FormulaError::NONE); + + SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager(); + CPPUNIT_ASSERT(pUndoMgr); + pUndoMgr->Undo(); + + // Without the fix, the formula stayed "=#REF!" and its value stayed an error. + CPPUNIT_ASSERT_EQUAL(u"=Sheet1.A1"_ustr, m_pDoc->GetFormula(0, 0, 1)); + CPPUNIT_ASSERT_EQUAL(42.0, m_pDoc->GetValue(ScAddress(0, 0, 1))); + + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + +namespace +{ +// Read a token array back as an OOXML formula string, the way an XLSX save does. +OUString printAsOoxml(ScDocument& rDocument, ScTokenArray& rCode, const ScAddress& rPosition) +{ + sc::CompileFormulaContext aContext(rDocument, formula::FormulaGrammar::GRAM_OOXML); + ScCompiler aCompiler(aContext, rPosition, rCode); + OUStringBuffer aBuffer; + aCompiler.CreateStringFromTokenArray(aBuffer); + return aBuffer.makeStringAndClear(); +} + +// Add a call whose function name is gone, the shape an xls with an unknown function +// leaves behind. +void addCallWithoutName(ScTokenArray& rCode) +{ + rCode.AddOpCode(ocNoName); + rCode.AddOpCode(ocOpen); + ScSingleRefData aReference; + aReference.InitAddress(ScAddress(0, 0, 0)); + rCode.AddSingleReference(aReference); + rCode.AddOpCode(ocClose); +} + +std::unique_ptr +compileInNativeGrammar(ScDocument& rDocument, const OUString& rFormula, const ScAddress& rPosition) +{ + ScCompiler aCompiler(rDocument, rPosition, formula::FormulaGrammar::GRAM_NATIVE, true, false); + std::unique_ptr pCode = aCompiler.CompileString(rFormula); + CPPUNIT_ASSERT(pCode); + return pCode; +} + +// Compile a formula in native grammar down to RPN and return the parse error. +// FormulaError::NONE means the whole formula parsed as one expression. +FormulaError parseErrorInNativeGrammar(ScDocument& rDocument, const OUString& rFormula) +{ + const ScAddress aPosition(1, 0, 0); + std::unique_ptr pCode = compileInNativeGrammar(rDocument, rFormula, aPosition); + ScCompiler aCompiler(rDocument, aPosition, *pCode, formula::FormulaGrammar::GRAM_NATIVE); + aCompiler.CompileTokenArray(); + return pCode->GetCodeError(); +} + +// Compile a formula in a grammar where a blank is the intersection operator and print it as +// OOXML. Calc A1 uses an exclamation mark for that operator instead. +OUString compileInXlA1SyntaxAndPrintAsOoxml(ScDocument& rDocument, const OUString& rFormula) +{ + const ScAddress aPosition(1, 0, 0); + ScCompiler aCompiler(rDocument, aPosition, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1, true, + false); + std::unique_ptr pCode = aCompiler.CompileString(rFormula); + CPPUNIT_ASSERT(pCode); + ScCompiler aRpnCompiler(rDocument, aPosition, *pCode, + formula::FormulaGrammar::GRAM_ENGLISH_XL_A1); + aRpnCompiler.CompileTokenArray(); + return printAsOoxml(rDocument, *pCode, aPosition); +} + +// Compile a formula in native grammar and print it as OOXML. +OUString compileAndPrintAsOoxml(ScDocument& rDocument, const OUString& rFormula) +{ + const ScAddress aPosition(1, 0, 0); + std::unique_ptr pCode = compileInNativeGrammar(rDocument, rFormula, aPosition); + return printAsOoxml(rDocument, *pCode, aPosition); +} + +// The same, with the @ marker an xls import adds put in first. +OUString resolveAndPrintAsOoxml(ScDocument& rDocument, const OUString& rFormula) +{ + const ScAddress aPosition(1, 0, 0); + std::unique_ptr pCode = compileInNativeGrammar(rDocument, rFormula, aPosition); + ScFormulaCell::ResolveImplicitIntersection(*pCode, rDocument, aPosition); + return printAsOoxml(rDocument, *pCode, aPosition); +} + +} // end anonymous namespace + +CPPUNIT_TEST_FIXTURE(TestFormula2, testCallWithoutNameSavesAsErrorInOoxml) +{ + // A call with no function name has no spelling in OOXML, so the whole formula + // saves as a plain error string. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScTokenArray aCode(*m_pDoc); + addCallWithoutName(aCode); + + CPPUNIT_ASSERT_EQUAL(u"#REF!"_ustr, printAsOoxml(*m_pDoc, aCode, ScAddress(1, 0, 0))); + + // The error stands for the whole formula, so an @ in front of the call goes + // with it. + ScTokenArray aMarkedCode(*m_pDoc); + aMarkedCode.AddOpCode(ocSingleValue); + addCallWithoutName(aMarkedCode); + + CPPUNIT_ASSERT_EQUAL(u"#REF!"_ustr, printAsOoxml(*m_pDoc, aMarkedCode, ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testImplicitIntersectionWrapsPrefixOperatorWithItsOperand) +{ + // The sign belongs inside the wrapper, however many signs there are and + // whatever they apply to. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(-A1:A3)"_ustr, + resolveAndPrintAsOoxml(*m_pDoc, u"-A1:A3"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(+A1:A3)"_ustr, + resolveAndPrintAsOoxml(*m_pDoc, u"+A1:A3"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(--A1:A3)"_ustr, + resolveAndPrintAsOoxml(*m_pDoc, u"--A1:A3"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(-TRANSPOSE(A1:A3))"_ustr, + resolveAndPrintAsOoxml(*m_pDoc, u"-TRANSPOSE(A1:A3)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(-(A1:A3))"_ustr, + resolveAndPrintAsOoxml(*m_pDoc, u"-(A1:A3)"_ustr)); + + // A sign parsed with the @ already in front of it gets the binary opcode rather + // than the negation one, and still belongs inside the wrapper. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(-A1:A3)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@-A1:A3"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(--A1:A3)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@--A1:A3"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(-SUM(A1:A3))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@-SUM(A1:A3)"_ustr)); + + // A sign between two @ markers applies to what the inner one produces, so it + // sits between the two wrappers. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(-_xlfn.SINGLE(A1:A3))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@-@A1:A3"_ustr)); + + // A sign in front of an @ the formula already carries applies to the value the + // @ produces, so it stays outside the wrapper. + CPPUNIT_ASSERT_EQUAL(u"-_xlfn.SINGLE(A1:A3)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"-@A1:A3"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testImplicitIntersectionTakesOperandWhole) +{ + // The wrapper encloses the whole operand, whatever form the operand takes. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + m_pDoc->GetRangeName().insert(std::make_unique( + *m_pDoc, u"myrange"_ustr, u"$Sheet1.$A$1:$A$3"_ustr, ScAddress(1, 0, 0))); + + // A name reaches the writer as its own token rather than as a push. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(myrange)"_ustr, + resolveAndPrintAsOoxml(*m_pDoc, u"myrange"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(-myrange)"_ustr, + resolveAndPrintAsOoxml(*m_pDoc, u"-myrange"_ustr)); + + // An inline matrix reaches the writer as one push, brackets and all. Its column + // separator is a comma, which does not turn a parenthesized matrix into a union + // list, so the group's own pair still serves as the wrapper's. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE({1,2})"_ustr, + resolveAndPrintAsOoxml(*m_pDoc, u"{1;2}"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE({1,2})"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@({1;2})"_ustr)); + + // Whitespace between the @ and its operand goes inside the wrapper. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE( A1:A3)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@ A1:A3"_ustr)); + + // An operand built with the range operator keeps all of itself inside. + CPPUNIT_ASSERT_EQUAL(u"A1:INDEX(B1:B10,5)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"A1:INDEX(B1:B10;5)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(A1:INDEX(B1:B10,5))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@A1:INDEX(B1:B10;5)"_ustr)); + // The @ the resolve step adds to such a formula wraps the same way. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(A1:INDEX(B1:B10,5))"_ustr, + resolveAndPrintAsOoxml(*m_pDoc, u"A1:INDEX(B1:B10;5)"_ustr)); + + // An arithmetic operator is above the @ in the grammar, so it ends the operand and the + // wrapper closes before it. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(A1:A3)+1"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@A1:A3+1"_ustr)); + + // Whitespace between a function name and its parenthesis is dropped on save, + // and the call stays inside the wrapper as if it had never been there. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(SUM(A1:A3))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@SUM (A1:A3)"_ustr)); + + // AND and OR carry operator opcodes although they are written as calls, so + // neither name ends the operand in front of it. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(AND(A1:A3))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@AND(A1:A3)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(OR(A1:A3))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@OR(A1:A3)"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testImplicitIntersectionMarkersWrapOneAnother) +{ + // Each @ takes a wrapper of its own around the one behind it. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScTokenArray aCode(*m_pDoc); + aCode.AddOpCode(ocSingleValue); + aCode.AddOpCode(ocSingleValue); + ScSingleRefData aReference; + aReference.InitAddress(ScAddress(0, 0, 0)); + aCode.AddSingleReference(aReference); + + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(_xlfn.SINGLE($A$1))"_ustr, + printAsOoxml(*m_pDoc, aCode, ScAddress(1, 0, 0))); + + // An @ on an argument inside a wrapped call takes a wrapper of its own too. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(SUM(_xlfn.SINGLE(A1:A3)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@SUM(@A1:A3)"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpilledRangeBindsTighterThanSignAndMarker) +{ + // The # postfix becomes _xlfn.ANCHORARRAY around the operand before it, and binds + // tighter than a sign or an @ in front of that operand. A document from another + // application has the same nesting, so these are the forms actually in use. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // On its own the wrapper encloses just the reference before the #. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.ANCHORARRAY(A1)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"A1#"_ustr)); + + // An already parenthesised operand keeps its parentheses inside the wrapper. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.ANCHORARRAY((A1))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"(A1)#"_ustr)); + + // The sign stays outside the wrapper. + CPPUNIT_ASSERT_EQUAL(u"-_xlfn.ANCHORARRAY(A1)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"-A1#"_ustr)); + + // A percent sign after the # ends up after both wrappers. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(_xlfn.ANCHORARRAY(A1))%"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@A1#%"_ustr)); + + // The @ wrapper goes around the # one, whatever form the operand takes. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(_xlfn.ANCHORARRAY(A1))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@A1#"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(_xlfn.ANCHORARRAY((A1:A3)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@(A1:A3)#"_ustr)); + + // Whitespace between the operand and the # stays with the operand. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(_xlfn.ANCHORARRAY(A1 ))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@A1 #"_ustr)); + + // Whitespace in front of an operand stays outside the wrappers around it. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE( _xlfn.ANCHORARRAY(A1))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@ A1#"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"SUM( _xlfn.SINGLE(_xlfn.ANCHORARRAY(A1)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"SUM( @A1#)"_ustr)); + + // Whitespace before the operator that ends the operand stays outside the wrapper as well, + // so the operand is still one parenthesised group and that pair serves as the call's. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(A1) + 1"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@(A1) + 1"_ustr)); + + // A # on an argument inside a wrapped call wraps just that argument. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(SUM(_xlfn.ANCHORARRAY(A1)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@SUM(A1#)"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testIntersectionNextToASpilledRangeSurvives) +{ + // A # on either operand leaves the intersection operator between them alone, because the + // spill range the # yields is a reference like any other operand. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"A1:A5 _xlfn.ANCHORARRAY(C1)"_ustr, + compileInXlA1SyntaxAndPrintAsOoxml(*m_pDoc, u"=A1:A5 C1#"_ustr)); + + // Same with the # on the operand before the blank. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.ANCHORARRAY(A1) C1"_ustr, + compileInXlA1SyntaxAndPrintAsOoxml(*m_pDoc, u"=A1# C1"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testPostfixOperatorWithoutAFactorIsNoFormula) +{ + // The # binds to the factor before it and a percent sign ends that factor, so a # or a + // union operator after one has nothing to bind to and the formula doesn't parse. OOXML + // has no spelling for either shape. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + CPPUNIT_ASSERT_EQUAL(FormulaError::OperatorExpected, + parseErrorInNativeGrammar(*m_pDoc, u"=A1%#"_ustr)); + CPPUNIT_ASSERT_EQUAL(FormulaError::OperatorExpected, + parseErrorInNativeGrammar(*m_pDoc, u"=A1%~B2%"_ustr)); + + // The same operators parse fine when there is a factor in front of them. + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, parseErrorInNativeGrammar(*m_pDoc, u"=A1#"_ustr)); + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, parseErrorInNativeGrammar(*m_pDoc, u"=A1#%"_ustr)); + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, parseErrorInNativeGrammar(*m_pDoc, u"=A1~B2%"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpilledRangeOperatorNextToAnExclamationMark) +{ + // A # before an exclamation mark lexes as the start of an error constant and swallows + // the mark, so the intersection operator is gone and the formula doesn't parse. + // Parentheses keep them apart, the only way to write such an intersection. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + const FormulaError eRunTogether = parseErrorInNativeGrammar(*m_pDoc, u"=A1#!C1"_ustr); + CPPUNIT_ASSERT_MESSAGE("=A1#!C1 should not read as a formula", + FormulaError::NONE != eRunTogether); + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, parseErrorInNativeGrammar(*m_pDoc, u"=(A1#)!C1"_ustr)); + + // An exclamation mark before the # is fine, nothing runs the two together in that order. + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, + parseErrorInNativeGrammar(*m_pDoc, u"=A1:C2!A1#"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testSpilledRangeDroppedWithNoFactorInFrontOfIt) +{ + // A percent sign ends the factor before it, so a # after one has nothing to enclose and + // is dropped. OOXML has no spelling for that shape either, and no parse produces one. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"A1%"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"A1%#"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(A1)%"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"@A1%#"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(-A1)%"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@-A1%#"_ustr)); + + // A union list that comes after an @ wrapper closed by the percent sign starts before + // that wrapper. + CPPUNIT_ASSERT_EQUAL(u"(_xlfn.SINGLE(-A1)%,B2)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@-A1%~B2"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testUnionSavesAsParenthesizedListInOoxml) +{ + // OOXML spells the union operator with the same comma that separates arguments, + // so a union expression takes parentheses of its own to stay one argument. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"(A1,B2)"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"A1~B2"_ustr)); + // One pair encloses the whole list, however many parts it has. + CPPUNIT_ASSERT_EQUAL(u"(A1,B2,C3)"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"A1~B2~C3"_ustr)); + + CPPUNIT_ASSERT_EQUAL(u"SUM((A1,B2))"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"SUM(A1~B2)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"INDEX((A1:B3,D1:E3),1,1,2)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"INDEX(A1:B3~D1:E3;1;1;2)"_ustr)); + // AND and OR open an argument list too, although their opcodes are operators. + CPPUNIT_ASSERT_EQUAL(u"AND((A1,B2))"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"AND(A1~B2)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"OR((A1,B2))"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"OR(A1~B2)"_ustr)); + + // A sign applies to the whole union, so the list's parentheses sit inside it. + CPPUNIT_ASSERT_EQUAL(u"-(A1,B2)"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"-A1~B2"_ustr)); + // The list ends where an operator of looser binding follows. + CPPUNIT_ASSERT_EQUAL(u"(1+(A1,B2))"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"(1+A1~B2)"_ustr)); + + // Not doubling the pair is what holds a formula's shape over round trips. + CPPUNIT_ASSERT_EQUAL(u"(A1,B2)"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"(A1~B2)"_ustr)); + // Whitespace in front of the list is not part of it, so the group's pair serves. + CPPUNIT_ASSERT_EQUAL(u"( A1,B2)"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"( A1~B2)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"SUM((A1,B2))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"SUM((A1~B2))"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testUnionStaysInsideImplicitIntersectionWrapper) +{ + // The union binds tighter than the @, so the parenthesized list sits inside the + // _xlfn.SINGLE wrapper and keeps the wrapper to one argument. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE((A1,B2))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@A1~B2"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE((A1,B2))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@(A1~B2)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"SUM(_xlfn.SINGLE((A1,B2)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"SUM(@A1~B2)"_ustr)); + + // With the @ inside the group, one pair of parentheses cannot serve both, so + // the list takes a pair of its own. + CPPUNIT_ASSERT_EQUAL(u"(_xlfn.SINGLE((A1,B2)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"(@A1~B2)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"SUM((_xlfn.SINGLE((A1,B2))))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"SUM((@A1~B2))"_ustr)); + + // That holds on either side of whitespace behind the group's parenthesis. + CPPUNIT_ASSERT_EQUAL(u"( _xlfn.SINGLE((A1,B2)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"( @A1~B2)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"(_xlfn.SINGLE( (A1,B2)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"(@ A1~B2)"_ustr)); + + // A # takes the list part before it, and an @ in front of that part wraps around the #. + CPPUNIT_ASSERT_EQUAL(u"(A1,_xlfn.SINGLE(_xlfn.ANCHORARRAY(B2)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"A1~@B2#"_ustr)); + + // An already parenthesised union list fills the wrapper on its own, for either operator. + // Both forms show up in documents from another application. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.ANCHORARRAY((A1,B2))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"(A1~B2)#"_ustr)); + + // A percent sign closes the wrapper before it, so the union list that opens after it + // starts at the wrapper and the scope's parentheses hold the list. + CPPUNIT_ASSERT_EQUAL(u"(_xlfn.SINGLE( A1)%,B2)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"(@ A1%~B2)"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testPostfixOperatorsBindWhereTheGrammarPutsThem) +{ + // The # takes the factor before it and nothing wider. The % is above every reference + // operator, so it takes the whole expression in front of it instead. A document from + // another application draws the same line. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // One part of a union list is a factor, so the # takes that part and the % the list. + CPPUNIT_ASSERT_EQUAL(u"(A1,_xlfn.ANCHORARRAY(B2))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"A1~B2#"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"(A1,B2)%"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"A1~B2%"_ustr)); + + // The first part of the list is a factor too, so a # there takes only that part and the + // list's own parentheses end up outside the wrapper. + CPPUNIT_ASSERT_EQUAL(u"(_xlfn.ANCHORARRAY(A1),B2)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"A1#~B2"_ustr)); + + // A range reference is a single factor and goes inside the wrapper as a whole. A range + // built with the range operator has a factor on either side, and the # takes only the + // one before it. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.ANCHORARRAY(A1:A3)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"A1:A3#"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"A1:_xlfn.ANCHORARRAY(INDEX(B1:B10,5))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"A1:INDEX(B1:B10;5)#"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.ANCHORARRAY(A1):C1"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"A1#:C1"_ustr)); + + // A percent sign is above the union operator, so the one after the list goes after the + // list's own parentheses, while the one on the first part stays where it is. + CPPUNIT_ASSERT_EQUAL(u"(A1%,B2)%"_ustr, compileAndPrintAsOoxml(*m_pDoc, u"A1%~B2%"_ustr)); + + // A prefix sign is above the # too, so it stays outside the wrapper. + CPPUNIT_ASSERT_EQUAL(u"(A1,-_xlfn.ANCHORARRAY(B2))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"A1~-B2#"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"SUM((A1,-_xlfn.ANCHORARRAY(B2)))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"SUM(A1~-B2#)"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testAnOperatorOnAUnionListHasNoValue) +{ + // A union list holds several ranges, so there is no single value for an operator to work + // on and the formula gives #VALUE!. The producing application does the same. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 100.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 400.0); + m_pDoc->SetValue(ScAddress(1, 0, 0), 200.0); + + m_pDoc->SetString(ScAddress(3, 0, 0), u"=(A1~B1)%"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 0, 0))); + + // A percent sign written on the last part of the list is the same, because it is above + // the union operator wherever it is put. + m_pDoc->SetString(ScAddress(3, 1, 0), u"=(A1~B1%)"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 1, 0))); + + // SUM takes the list as a whole, so the one that fails is the operator after it. + m_pDoc->SetString(ScAddress(3, 2, 0), u"=SUM((A1~B1)%)"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 2, 0))); + + // A list isn't a string either. + m_pDoc->SetString(ScAddress(3, 3, 0), u"=(A1~B1)&\"x\""_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 3, 0))); + + // On its own the list is still a reference list that SUM adds up, written either way. + m_pDoc->SetString(ScAddress(3, 5, 0), u"=SUM((A1~B1))"_ustr); + CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 5, 0))); + m_pDoc->SetString(ScAddress(3, 6, 0), u"=SUM((A1;B1))"_ustr); + CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 6, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testAValueAmongTheUnionListPartsHasNoValue) +{ + // A union joins references, so a part that turned its reference into a value leaves + // nothing to join and the list gives #VALUE!. The producing application agrees. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 100.0); + m_pDoc->SetValue(ScAddress(1, 0, 0), 200.0); + + // The percent sign sits on a reference, so the part joins and the calculation complains. + m_pDoc->SetFormula(ScAddress(3, 0, 0), u"=(A1, B1%)"_ustr, formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 0, 0))); + + // A chain of percent signs is the same. + m_pDoc->SetFormula(ScAddress(3, 1, 0), u"=(A1, B1%%)"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 1, 0))); + + // Same on a middle part, which no file has: the producing application allows a percent + // sign only on the last one. + m_pDoc->SetFormula(ScAddress(3, 5, 0), u"=(A1, B1%, A1)"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 5, 0))); + + // An arithmetic operator after the reference makes a value of it too. + m_pDoc->SetFormula(ScAddress(3, 2, 0), u"=(A1, B1+A1)"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 2, 0))); + + // Written out, the union joins anything beside it, so a plain number or string errors too. + m_pDoc->SetString(ScAddress(3, 3, 0), u"=(A1~5)"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 3, 0))); + m_pDoc->SetString(ScAddress(3, 4, 0), u"=(A1~\"x\")"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 4, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testAUnionListPartJoinsWhenItBeginsWithAReference) +{ + // The separator joins two parts into a union if the left returns a reference and the + // right starts with one, or with a function that returns one. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 100.0); + m_pDoc->SetValue(ScAddress(1, 0, 0), 200.0); + + // A nested list works on either side of the separator, and a cell in both counts twice. + m_pDoc->SetFormula(ScAddress(3, 0, 0), u"=SUM((A1, (A1,B1)))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(400.0, m_pDoc->GetValue(ScAddress(3, 0, 0))); + m_pDoc->SetFormula(ScAddress(3, 1, 0), u"=SUM(((A1,B1), B1))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(500.0, m_pDoc->GetValue(ScAddress(3, 1, 0))); + + // IF, CHOOSE and INDEX return a reference, so a part can start with any of them. + m_pDoc->SetFormula(ScAddress(3, 2, 0), u"=SUM((A1, IF(TRUE,B1)))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 2, 0))); + m_pDoc->SetFormula(ScAddress(3, 3, 0), u"=SUM((A1, CHOOSE(1,B1)))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 3, 0))); + m_pDoc->SetFormula(ScAddress(3, 4, 0), u"=SUM((B1, INDEX(A1:B1,1,1)))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 4, 0))); + + // In a longer list every separator joins in turn, onto the union built so far. + m_pDoc->SetFormula(ScAddress(3, 5, 0), u"=SUM((A1, B1, A1))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(400.0, m_pDoc->GetValue(ScAddress(3, 5, 0))); + + // IFS, SWITCH and XLOOKUP return a reference too. + m_pDoc->SetFormula(ScAddress(3, 11, 0), u"=SUM((A1, _xlfn.IFS(TRUE, B1)))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 11, 0))); + m_pDoc->SetFormula(ScAddress(3, 12, 0), u"=SUM((A1, _xlfn.SWITCH(1,1,B1)))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 12, 0))); + m_pDoc->SetFormula(ScAddress(3, 13, 0), u"=SUM((A1, _xlfn.XLOOKUP(200, B1:B1, B1:B1)))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 13, 0))); + + // An error constant part becomes the result of the union, wherever the blank around the + // separator is. + m_pDoc->SetFormula(ScAddress(3, 14, 0), u"=(A1, #REF!)"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(3, 14, 0))); + m_pDoc->SetFormula(ScAddress(3, 16, 0), u"=(A1 ,#REF!)"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(3, 16, 0))); + + // The same list read the way it arrives from a file: no leading equals sign, and the + // implicit intersections worked out during the parse. + { + ScCompiler aCompiler(*m_pDoc, ScAddress(3, 17, 0), formula::FormulaGrammar::GRAM_OOXML, + true, false); + std::unique_ptr pArray = aCompiler.CompileString(u"(A1 ,#REF!)"_ustr); + aCompiler.CompileTokenArray(); + m_pDoc->SetFormula(ScAddress(3, 17, 0), *pArray); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(3, 17, 0))); + } + + // An @ part sits on the reference after it, and a bare list has no value anyway. + m_pDoc->SetFormula(ScAddress(3, 15, 0), u"=(A1, _xlfn.SINGLE(B1))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(3, 15, 0))); + + // Shapes the producing application refuses, so no file has them. A part not starting + // with a reference stays out of the list, leaving two expressions that do not parse. + const std::vector aRefusedShapes = { + u"=(A1%, B1)"_ustr, u"=(A1, -B1)"_ustr, u"=(A1, 5)"_ustr, + u"=(A1, \"x\")"_ustr, u"=(A1, SUM(A1:B1))"_ustr, + }; + SCROW nRow = 6; + for (const OUString& rShape : aRefusedShapes) + { + m_pDoc->SetFormula(ScAddress(3, nRow, 0), rShape, formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL_MESSAGE(OUStringToOString(rShape, RTL_TEXTENCODING_UTF8).getStr(), + FormulaError::OperatorExpected, + m_pDoc->GetErrCode(ScAddress(3, nRow, 0))); + ++nRow; + } + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testAFunctionCallMayFollowTheRangeOperator) +{ + // A1:IF has letters that are also a valid column name, so the symbol lexes like a range + // but names none. The parenthesis after it makes it a range operator followed by a call, + // so the reference in front stands on its own and the call gives the other end of the + // range. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 100.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 40.0); + + m_pDoc->SetFormula(ScAddress(3, 0, 0), u"=SUM(A1:IF(TRUE,A2))"_ustr, + formula::FormulaGrammar::GRAM_OOXML); + CPPUNIT_ASSERT_EQUAL(140.0, m_pDoc->GetValue(ScAddress(3, 0, 0))); + + // The display grammar reads the symbol the same way. + m_pDoc->SetString(ScAddress(3, 1, 0), u"=SUM(A1:IF(TRUE();A2))"_ustr); + CPPUNIT_ASSERT_EQUAL(140.0, m_pDoc->GetValue(ScAddress(3, 1, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testAUnionListMeetsTheIntersectionOperator) +{ + // A parenthesised union list is a reference like any other, so the whitespace + // intersection operator takes it as the left operand. The whitespace is an operator only + // under the OOXML grammar, the way a formula arrives from a file, so compile it that way. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 100.0); + m_pDoc->SetValue(ScAddress(1, 0, 0), 200.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 40.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 300.0); + + auto setOoxmlFormula = [this](const ScAddress& rPosition, const OUString& rFormula) { + ScCompiler aCompiler(*m_pDoc, rPosition, formula::FormulaGrammar::GRAM_OOXML); + std::unique_ptr pArray = aCompiler.CompileString(rFormula); + aCompiler.CompileTokenArray(); + m_pDoc->SetFormula(rPosition, *pArray); + }; + + setOoxmlFormula(ScAddress(3, 0, 0), u"=SUM((A1:B1, A2:B2) A1:A2)"_ustr); + CPPUNIT_ASSERT_EQUAL(140.0, m_pDoc->GetValue(ScAddress(3, 0, 0))); + + // A parenthesised expression works on the right of the operator the same way. The blank + // before the parenthesis keeps it a group instead of a call. + setOoxmlFormula(ScAddress(3, 1, 0), u"=SUM(A1:B1 (A1:B1))"_ustr); + CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 1, 0))); + setOoxmlFormula(ScAddress(3, 2, 0), u"=SUM((A1:B1, A2:B2) (A1:B1, A2:B2))"_ustr); + CPPUNIT_ASSERT_EQUAL(640.0, m_pDoc->GetValue(ScAddress(3, 2, 0))); + + // A union list can be the right operand as well as the left one. + setOoxmlFormula(ScAddress(3, 4, 0), u"=SUM(A1:A2 (A1:B1, A2:B2))"_ustr); + CPPUNIT_ASSERT_EQUAL(140.0, m_pDoc->GetValue(ScAddress(3, 4, 0))); + + // Ranges that share no cell intersect to nothing, which is the #NULL! error. + setOoxmlFormula(ScAddress(3, 3, 0), u"=A1:B1 (A2:B2)"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoCode, m_pDoc->GetErrCode(ScAddress(3, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testUnionParenthesesEncloseExactlyTheirList) +{ + // The list's opening parenthesis moves the text behind it along, and a wrapper + // spliced afterwards still lands where its own operand begins. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScSingleRefData aFirst; + aFirst.InitAddress(ScAddress(0, 0, 0)); + ScSingleRefData aSecond; + aSecond.InitAddress(ScAddress(1, 1, 0)); + + // An @ behind the union operator, a shape no parse of a formula produces. + ScTokenArray aMarkerInList(*m_pDoc); + aMarkerInList.AddSingleReference(aFirst); + aMarkerInList.AddOpCode(ocUnion); + aMarkerInList.AddOpCode(ocSingleValue); + aMarkerInList.AddSingleReference(aSecond); + + CPPUNIT_ASSERT_EQUAL(u"($A$1,_xlfn.SINGLE($B$2))"_ustr, + printAsOoxml(*m_pDoc, aMarkerInList, ScAddress(1, 0, 0))); + + // Same for a percent sign before the union operator. The sign comes after the first part + // of the list, so the list still starts before that part. + ScTokenArray aPercentInList(*m_pDoc); + aPercentInList.AddSingleReference(aFirst); + aPercentInList.AddOpCode(ocPercentSign); + aPercentInList.AddOpCode(ocUnion); + aPercentInList.AddSingleReference(aSecond); + + CPPUNIT_ASSERT_EQUAL(u"($A$1%,$B$2)"_ustr, + printAsOoxml(*m_pDoc, aPercentInList, ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testWrappersDroppedFromTextThatDidNotParse) +{ + // Text that no parse could read cannot take parentheses, so every wrapper around + // it is left out, however many markers stand in front of it or follow it. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // A prefix sign is kept while the @ is left out. + ScTokenArray aSigned(*m_pDoc); + aSigned.AddOpCode(ocSingleValue); + aSigned.AddOpCode(ocAdd); + aSigned.AddBad(u"PW value"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"+PW value"_ustr, printAsOoxml(*m_pDoc, aSigned, ScAddress(1, 0, 0))); + + ScTokenArray aNestedMarkers(*m_pDoc); + aNestedMarkers.AddOpCode(ocSingleValue); + aNestedMarkers.AddOpCode(ocSingleValue); + aNestedMarkers.AddBad(u"PW value"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"PW value"_ustr, + printAsOoxml(*m_pDoc, aNestedMarkers, ScAddress(1, 0, 0))); + + ScTokenArray aSpilled(*m_pDoc); + aSpilled.AddOpCode(ocSingleValue); + aSpilled.AddBad(u"PW value"_ustr); + aSpilled.AddOpCode(ocSpill); + + CPPUNIT_ASSERT_EQUAL(u"PW value"_ustr, printAsOoxml(*m_pDoc, aSpilled, ScAddress(1, 0, 0))); + + // A union list that reaches such text goes without its parentheses too. + ScTokenArray aUnion(*m_pDoc); + ScSingleRefData aReference; + aReference.InitAddress(ScAddress(0, 0, 0)); + aUnion.AddSingleReference(aReference); + aUnion.AddOpCode(ocUnion); + aUnion.AddBad(u"PW value"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"$A$1,PW value"_ustr, printAsOoxml(*m_pDoc, aUnion, ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testImplicitIntersectionDroppedWhenItHasNoOperand) +{ + // An @ with nothing behind it to enclose is left out of the saved formula. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScTokenArray aMarkerOnly(*m_pDoc); + aMarkerOnly.AddOpCode(ocSingleValue); + + CPPUNIT_ASSERT_EQUAL(OUString(), printAsOoxml(*m_pDoc, aMarkerOnly, ScAddress(1, 0, 0))); + + // The same holds when the operand behind the @ is another @ with nothing of its + // own behind it. + ScTokenArray aMarkersOnly(*m_pDoc); + aMarkersOnly.AddOpCode(ocSingleValue); + aMarkersOnly.AddOpCode(ocSingleValue); + + CPPUNIT_ASSERT_EQUAL(OUString(), printAsOoxml(*m_pDoc, aMarkersOnly, ScAddress(1, 0, 0))); + + // A missing argument writes nothing, so it gives the wrapper nothing to enclose + // either. + ScTokenArray aMissingOperand(*m_pDoc); + aMissingOperand.AddOpCode(ocSingleValue); + aMissingOperand.AddOpCode(ocMissing); + + CPPUNIT_ASSERT_EQUAL(OUString(), printAsOoxml(*m_pDoc, aMissingOperand, ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testImplicitIntersectionWrapsWholeTableReference) +{ + // A structured table reference is more than one token, and the wrapper goes around + // all of them. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // A two-column table over A1:B4 whose header row names the columns. + std::unique_ptr pData(new ScDBData(u"table"_ustr, 0, 0, 0, 1, 3)); + CPPUNIT_ASSERT(m_pDoc->GetDBCollection()->getNamedDBs().insert(std::move(pData))); + m_pDoc->SetString(ScAddress(0, 0, 0), u"Header1"_ustr); + m_pDoc->SetString(ScAddress(1, 0, 0), u"Header2"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"table[[Header1]]"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"table[[Header1]]"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(table[[Header1]])"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@table[[Header1]]"_ustr)); + + // A reference of several bracketed items has a separator of its own inside, and + // still goes into the wrapper whole. + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(table[[#Data],[Header1]])"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@table[[#Data];[Header1]]"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testImplicitIntersectionKeepsOffsetParameterErrorRewrite) +{ + // An OFFSET call whose first argument is not a reference saves that argument as a + // reference error, with or without an @ in front of the call. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + CPPUNIT_ASSERT_EQUAL(u"OFFSET(#REF!,0,2)"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"OFFSET(\"x\";0;2)"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"_xlfn.SINGLE(OFFSET(#REF!,0,2))"_ustr, + compileAndPrintAsOoxml(*m_pDoc, u"@OFFSET(\"x\";0;2)"_ustr)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testLongImplicitIntersectionChainSavesCompletely) +{ + // A formula may carry as many @ markers as the token array holds, and the writer + // gets through all of them. + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + ScTokenArray aCode(*m_pDoc); + // 30000 pairs stay under the 65535 token limit while going deeper than any stack + // of nested calls can follow. + for (sal_Int32 nPair = 0; nPair < 30000; ++nPair) + { + aCode.AddOpCode(ocSingleValue); + aCode.AddOpCode(ocAdd); + } + ScSingleRefData aReference; + aReference.InitAddress(ScAddress(0, 0, 0)); + aCode.AddSingleReference(aReference); + + const OUString aFormula = printAsOoxml(*m_pDoc, aCode, ScAddress(1, 0, 0)); + CPPUNIT_ASSERT(!aFormula.isEmpty()); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestFormula2, testAReferenceListTakesAFunctionResult) +{ + // A reference list is built from the parts of a parenthesised expression, and a part can + // be the result of a function that returns a reference. INDEX is one of those, so SUM + // adds the cell it picked to the rest of the list. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 100.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 400.0); + m_pDoc->SetValue(ScAddress(1, 0, 0), 200.0); + + m_pDoc->SetString(ScAddress(3, 0, 0), u"=SUM((INDEX(A1:A2;2);B1))"_ustr); + CPPUNIT_ASSERT_EQUAL(600.0, m_pDoc->GetValue(ScAddress(3, 0, 0))); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/ucalc_nanpayload.cxx b/sc/qa/unit/ucalc_nanpayload.cxx index 34d09bc04f7e..6e5ac8368ea9 100644 --- a/sc/qa/unit/ucalc_nanpayload.cxx +++ b/sc/qa/unit/ucalc_nanpayload.cxx @@ -17,8 +17,8 @@ class TestNanPayload : public ScUcalcTestBase CPPUNIT_TEST_FIXTURE(TestNanPayload, testNanPayload) { #ifndef DISABLE_NAN_TESTS - // Some tests, such as testExternalRefFunctions, testFuncGCD, and testFuncGCD, evaluates - // spreadsheet functions' error code, which need NaN payload feature of the hardware + // Some tests, such as testExternalRefFunctions, testFuncGCD, evaluate + // spreadsheet functions' error codes, which need the NaN payload feature of the hardware NanPayloadTest nanTest; CPPUNIT_ASSERT_MESSAGE(nanTest.getMessage(), nanTest.getIfSupported()); #endif diff --git a/sc/qa/unit/ucalc_pivottable.cxx b/sc/qa/unit/ucalc_pivottable.cxx index 5ef9059d279f..55d673a0fff9 100644 --- a/sc/qa/unit/ucalc_pivottable.cxx +++ b/sc/qa/unit/ucalc_pivottable.cxx @@ -27,6 +27,7 @@ #include #include #include +#include template<> std::string CppUnit::assertion_traits::toString(ScDPItemData const &) { return "ScDPItemData"; } //TODO: combine with ScDPItemData::Dump? @@ -136,6 +137,14 @@ ScDPObject* createDPFromRange( return createDPFromSourceDesc(pDoc, aSheetDesc, aFields, nFieldCount, bFilterButton); } +template +ScDPObject* createDPFromRange( + ScDocument* pDoc, const ScRange& rRange, + const std::array& aFields, bool bFilterButton) +{ + return createDPFromRange(pDoc, rRange, aFields.data(), aFields.size(), bFilterButton); +} + ScRange refresh(ScDPObject* pDPObj) { bool bOverflow = false; @@ -190,6 +199,11 @@ class TestPivottable : public ScUcalcTestBase protected: template ScRange insertDPSourceData(ScDocument* pDoc, DPFieldDef const aFields[], size_t nFieldCount, const char* aData[][Size], size_t nDataCount); + + template + ScRange insertDPSourceData(ScDocument* pDoc, + const std::array& aFields, + const std::array, Rows>& aData); }; template @@ -226,6 +240,42 @@ ScRange TestPivottable::insertDPSourceData(ScDocument* pDoc, DPFieldDef const aF return aSrcRange; } +template +ScRange TestPivottable::insertDPSourceData(ScDocument* pDoc, + const std::array& aFields, + const std::array, Rows>& aData) +{ + // Insert field names in row 0. + for (size_t i = 0; i < FieldCount; ++i) + pDoc->SetString(static_cast(i), 0, 0, OUString(aFields[i].aName)); + + // Insert data into row 1 and downward. + for (size_t i = 0; i < Rows; ++i) + { + SCROW nRow = static_cast(i) + 1; + for (size_t j = 0; j < FieldCount; ++j) + { + SCCOL nCol = static_cast(j); + pDoc->SetString( + nCol, nRow, 0, OUString(aData[i][j], strlen(aData[i][j]), RTL_TEXTENCODING_UTF8)); + } + } + + SCROW nRow1 = 0, nRow2 = 0; + SCCOL nCol1 = 0, nCol2 = 0; + pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Data is expected to start from (col=0,row=0).", SCCOL(0), nCol1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Data is expected to start from (col=0,row=0).", SCROW(0), nRow1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected data range.", + static_cast(FieldCount - 1), nCol2); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected data range.", + static_cast(Rows), nRow2); + + ScRange aSrcRange(nCol1, nRow1, 0, nCol2, nRow2, 0); + printRange(pDoc, aSrcRange, "Data sheet content"); + return aSrcRange; +} + CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTable) { @@ -400,7 +450,7 @@ CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTable) size_t(0), pDPs->GetSheetCaches().size()); // Now, "refresh" the table. This should still return a reference to self - // even with the absence of data cache. + // even in the absence of a data cache. aRefs.clear(); pDPs->ReloadCache(pDPObj, aRefs); CPPUNIT_ASSERT_EQUAL_MESSAGE("It should return the same object as a reference.", @@ -742,11 +792,10 @@ CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTableNamedSource) // Name this range. OUString aRangeName(u"MyData"_ustr); - ScRangeName* pNames = m_pDoc->GetRangeName(); - CPPUNIT_ASSERT_MESSAGE("Failed to get global range name container.", pNames); + ScRangeName& rNames = m_pDoc->GetRangeName(); ScRangeData* pName = new ScRangeData( *m_pDoc, aRangeName, aRangeStr); - bool bSuccess = pNames->insert(pName); + bool bSuccess = rNames.insert(std::unique_ptr(pName)); CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bSuccess); ScSheetSourceDesc aSheetDesc(m_pDoc); @@ -809,7 +858,7 @@ CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTableNamedSource) CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.", size_t(0), pDPs->GetNameCaches().size()); - pNames->clear(); + rNames.clear(); m_pDoc->DeleteTab(1); m_pDoc->DeleteTab(0); } @@ -3087,6 +3136,395 @@ CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTableCalculatedField) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTableSpillError) +{ + // Test that a pivot table detects non-empty cells in the output range + // and writes #SPILL! into the origin cell. + + m_pDoc->InsertTab(0, u"Data"_ustr); + m_pDoc->InsertTab(1, u"Table"_ustr); + + static constexpr auto aFields = std::to_array({ + { u"Name", sheet::DataPilotFieldOrientation_ROW, ScGeneralFunction::NONE, false }, + { u"Group", sheet::DataPilotFieldOrientation_COLUMN, ScGeneralFunction::NONE, false }, + { u"Score", sheet::DataPilotFieldOrientation_DATA, ScGeneralFunction::NONE, false } + }); + + static constexpr auto aData = std::to_array>({ + { "Andy", "A", "30" }, + { "Bruce", "A", "20" }, + { "Charlie", "B", "45" }, + }); + + ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, aData); + SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row(); + SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col(); + + ScDPObject* pDPObject = createDPFromRange( + m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, false); + + ScDPCollection* pDPs = m_pDoc->GetDPCollection(); + pDPs->InsertNewTable(std::unique_ptr(pDPObject)); + pDPObject->SetName(pDPs->CreateNewName()); + + // Place blocking data in the output area on Sheet 2. + m_pDoc->SetString(ScAddress(2, 3, 1), u"blocker"_ustr); + + bool bOverflow = false; + ScRange aOutRange = pDPObject->GetNewOutputRange(bOverflow); + CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverflow); + + // Use spill-checking Output - should fail because of the blocker cell. + bool bSuccess = pDPObject->Output(aOutRange.aStart, true); + CPPUNIT_ASSERT_MESSAGE("Output should fail due to spill error.", !bSuccess); + CPPUNIT_ASSERT_MESSAGE("HasSpillError should be true.", pDPObject->HasSpillError()); + + // The origin cell should display #SPILL!. + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(aOutRange.aStart)); + + // The blocker cell should still contain its original value. + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(ScAddress(2, 3, 1))); + + pDPs->FreeTable(pDPObject); + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTableSpillResolution) +{ + // Test that clearing a blocking cell and calling ResolveSpilledOutputs() + // causes the spilled pivot table to write an output in the output range. + + m_pDoc->InsertTab(0, u"Data"_ustr); + m_pDoc->InsertTab(1, u"Table"_ustr); + + static constexpr auto aFields = std::to_array({ + { u"Name", sheet::DataPilotFieldOrientation_ROW, ScGeneralFunction::NONE, false }, + { u"Group", sheet::DataPilotFieldOrientation_COLUMN, ScGeneralFunction::NONE, false }, + { u"Score", sheet::DataPilotFieldOrientation_DATA, ScGeneralFunction::NONE, false } + }); + + static constexpr auto aData = std::to_array>({ + { "Andy", "A", "30" }, + { "Bruce", "A", "20" }, + { "Charlie", "B", "45" }, + }); + + ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, aData); + SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row(); + SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col(); + + ScDPObject* pDPObject = createDPFromRange( + m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, false); + + ScDPCollection* pDPs = m_pDoc->GetDPCollection(); + pDPs->InsertNewTable(std::unique_ptr(pDPObject)); + pDPObject->SetName(pDPs->CreateNewName()); + + // Place blocking data in the output area on Sheet 2. + ScAddress aBlocker(2, 3, 1); + m_pDoc->SetString(aBlocker, u"blocker"_ustr); + + bool bOverflow = false; + ScRange aOutRange = pDPObject->GetNewOutputRange(bOverflow); + CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverflow); + + // Output with spill check - should produce #SPILL!. + pDPObject->Output(aOutRange.aStart, true); + CPPUNIT_ASSERT_MESSAGE("Should be spilled.", pDPObject->HasSpillError()); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(aOutRange.aStart)); + + // Now clear the blocking cell. + m_pDoc->SetString(aBlocker, u""_ustr); + + // Call ResolveSpilledOutputs - should auto-output the pivot table. + m_xDocShell->ResolveSpilledOutputs(); + + // The spill should be resolved. + CPPUNIT_ASSERT(!pDPObject->HasSpillError()); + + // The origin cell should no longer show #SPILL! but actual pivot data. + OUString aOriginValue = m_pDoc->GetString(aOutRange.aStart); + CPPUNIT_ASSERT_MESSAGE("Origin cell should have pivot table content, not #SPILL!.", + aOriginValue != "#SPILL!"); + CPPUNIT_ASSERT_MESSAGE("Origin cell should not be empty.", !aOriginValue.isEmpty()); + + pDPs->FreeTable(pDPObject); + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTableSpillResolutionNotReady) +{ + // Test that ResolveSpilledOutputs() does NOT resolve a spill when + // the blocking cell is still present. + + m_pDoc->InsertTab(0, u"Data"_ustr); + m_pDoc->InsertTab(1, u"Table"_ustr); + + static constexpr auto aFields = std::to_array({ + { u"Name", sheet::DataPilotFieldOrientation_ROW, ScGeneralFunction::NONE, false }, + { u"Group", sheet::DataPilotFieldOrientation_COLUMN, ScGeneralFunction::NONE, false }, + { u"Score", sheet::DataPilotFieldOrientation_DATA, ScGeneralFunction::NONE, false } + }); + + static constexpr auto aData = std::to_array>({ + { "Andy", "A", "30" }, + { "Bruce", "A", "20" }, + { "Charlie", "B", "45" }, + }); + + ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, aData); + SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row(); + SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col(); + + ScDPObject* pDPObject = createDPFromRange( + m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, false); + + ScDPCollection* pDPs = m_pDoc->GetDPCollection(); + pDPs->InsertNewTable(std::unique_ptr(pDPObject)); + pDPObject->SetName(pDPs->CreateNewName()); + + // Place blocking data. + m_pDoc->SetString(ScAddress(2, 3, 1), u"blocker"_ustr); + + bool bOverflow = false; + ScRange aOutRange = pDPObject->GetNewOutputRange(bOverflow); + CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverflow); + + pDPObject->Output(aOutRange.aStart, true); + CPPUNIT_ASSERT_MESSAGE("Should be spilled.", pDPObject->HasSpillError()); + + // Call resolve without clearing the blocker. + m_xDocShell->ResolveSpilledOutputs(); + + CPPUNIT_ASSERT_MESSAGE("Spill should NOT be resolved (blocker still present).", + pDPObject->HasSpillError()); + + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(aOutRange.aStart)); + + pDPs->FreeTable(pDPObject); + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTableUndoRechecksSpill) +{ + // Test that undoing a pivot table change re-outputs the restored pivot table + // with a spill check. Place the blocker before creating the pivot table so + // undo/redo properly preserves it. + + m_pDoc->InsertTab(0, u"Data"_ustr); + m_pDoc->InsertTab(1, u"Table"_ustr); + + // Raw data + const std::vector> aData = { + { "Name", "Value" }, + { "Sun", "1" }, + { "Oracle", "2" }, + }; + + static constexpr auto aFields = std::to_array({ + { u"Name", sheet::DataPilotFieldOrientation_ROW, ScGeneralFunction::NONE, false }, + { u"Value", sheet::DataPilotFieldOrientation_DATA, ScGeneralFunction::SUM, false }, + }); + + ScAddress aPos(1, 1, 0); + ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData); + + // Place a blocker on Sheet 2 before creating the pivot table. + ScAddress aBlocker(1, 2, 1); + m_pDoc->SetString(aBlocker, u"blocker"_ustr); + + std::unique_ptr pDPObject(createDPFromRange( + m_pDoc, aDataRange, aFields, false)); + + // Create pivot table doc function. + ScDBDocFunc aFunction(*m_xDocShell); + bool bSuccess = aFunction.CreatePivotTable(*pDPObject, true, true); + CPPUNIT_ASSERT_MESSAGE("Failed to create pivot table.", bSuccess); + + ScDPCollection* pDPs = m_pDoc->GetDPCollection(); + CPPUNIT_ASSERT_EQUAL(size_t(1), pDPs->GetCount()); + ScDPObject* pDocDPObject = &(*pDPs)[0]; + + // The pivot table should be spilled because the blocker was present. + CPPUNIT_ASSERT_MESSAGE("Should be spilled.", pDocDPObject->HasSpillError()); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(pDocDPObject->GetOutRange().aStart)); + + // The blocker should still be there. + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(aBlocker)); + + // Undo the pivot table creation. + m_pDoc->GetUndoManager()->Undo(); + + // After undo, the pivot table is deleted. + CPPUNIT_ASSERT_EQUAL(size_t(0), pDPs->GetCount()); + // The blocker should be there. + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(aBlocker)); + + // Redo the creation: blocker is still present, should spill again. + m_pDoc->GetUndoManager()->Redo(); + CPPUNIT_ASSERT_EQUAL(size_t(1), pDPs->GetCount()); + pDocDPObject = &(*pDPs)[0]; + CPPUNIT_ASSERT_MESSAGE("Should be spilled after redo.", pDocDPObject->HasSpillError()); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(pDocDPObject->GetOutRange().aStart)); + CPPUNIT_ASSERT_EQUAL(u"blocker"_ustr, m_pDoc->GetString(aBlocker)); + + // Now clear the blocker and resolve. + m_pDoc->SetString(aBlocker, u""_ustr); + m_xDocShell->ResolveSpilledOutputs(); + + // The pivot table should now be rendered. + CPPUNIT_ASSERT_MESSAGE("Spill should be resolved.", !pDocDPObject->HasSpillError()); + OUString aOriginValue = m_pDoc->GetString(pDocDPObject->GetOutRange().aStart); + CPPUNIT_ASSERT_MESSAGE("Should have real content now.", aOriginValue != "#SPILL!"); + CPPUNIT_ASSERT_MESSAGE("Should not be empty.", !aOriginValue.isEmpty()); + + pDPs->FreeTable(pDocDPObject); + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTableSpillUndoRestore) +{ + // Test that resolving a spill pushes an undo action. + // Undoing that action should restore the #SPILL! state. + // Redoing should re-render the pivot table. + + m_pDoc->InsertTab(0, u"Data"_ustr); + m_pDoc->InsertTab(1, u"Table"_ustr); + + static constexpr auto aFields = std::to_array({ + { u"Name", sheet::DataPilotFieldOrientation_ROW, ScGeneralFunction::NONE, false }, + { u"Group", sheet::DataPilotFieldOrientation_COLUMN, ScGeneralFunction::NONE, false }, + { u"Score", sheet::DataPilotFieldOrientation_DATA, ScGeneralFunction::NONE, false } + }); + + static constexpr auto aData = std::to_array>({ + { "Andy", "A", "30" }, + { "Bruce", "A", "20" }, + { "Charlie", "B", "45" }, + }); + + ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, aData); + SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row(); + SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col(); + + ScDPObject* pDPObject = createDPFromRange( + m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, false); + + ScDPCollection* pDPs = m_pDoc->GetDPCollection(); + pDPs->InsertNewTable(std::unique_ptr(pDPObject)); + pDPObject->SetName(pDPs->CreateNewName()); + + // Place blocker and trigger spill. + ScAddress aBlocker(2, 3, 1); + m_pDoc->SetString(aBlocker, u"blocker"_ustr); + + bool bOverflow = false; + ScRange aOutRange = pDPObject->GetNewOutputRange(bOverflow); + CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverflow); + + pDPObject->Output(aOutRange.aStart, true); + CPPUNIT_ASSERT_MESSAGE("Should be spilled.", pDPObject->HasSpillError()); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(aOutRange.aStart)); + + // Clear the blocker and resolve the spill. + m_pDoc->SetString(aBlocker, u""_ustr); + m_xDocShell->ResolveSpilledOutputs(); + + // Spill should be resolved - pivot table rendered. + CPPUNIT_ASSERT_MESSAGE("Spill should be resolved.", !pDPObject->HasSpillError()); + ScRange aRenderedRange = pDPObject->GetOutRange(); + OUString aRenderedValue = m_pDoc->GetString(aRenderedRange.aStart); + CPPUNIT_ASSERT_MESSAGE("Should have pivot content.", !aRenderedValue.isEmpty()); + CPPUNIT_ASSERT_MESSAGE("Should not show #SPILL!.", aRenderedValue != "#SPILL!"); + + // Undo - should go back to #SPILL!. + m_pDoc->GetUndoManager()->Undo(); + CPPUNIT_ASSERT_MESSAGE("Should be spilled again after undo.", pDPObject->HasSpillError()); + CPPUNIT_ASSERT_EQUAL(u"#SPILL!"_ustr, m_pDoc->GetString(aOutRange.aStart)); + + // Redo - should render the pivot table again. + m_pDoc->GetUndoManager()->Redo(); + CPPUNIT_ASSERT_MESSAGE("Should be resolved after redo.", !pDPObject->HasSpillError()); + aRenderedValue = m_pDoc->GetString(pDPObject->GetOutRange().aStart); + CPPUNIT_ASSERT_MESSAGE("Should have pivot content after redo.", !aRenderedValue.isEmpty()); + CPPUNIT_ASSERT_MESSAGE("Should not show #SPILL! after redo.", aRenderedValue != "#SPILL!"); + + pDPs->FreeTable(pDPObject); + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestPivottable, testPivotTableValueNumberFormat) +{ + // The values of a pivot table are shown with the number format of the source data. + m_pDoc->InsertTab(0, u"Data"_ustr); + m_pDoc->InsertTab(1, u"Table"_ustr); + + static const DPFieldDef aFields[] + = { { u"Name", sheet::DataPilotFieldOrientation_ROW, ScGeneralFunction::NONE, false }, + { u"Group", sheet::DataPilotFieldOrientation_COLUMN, ScGeneralFunction::NONE, false }, + { u"Score", sheet::DataPilotFieldOrientation_DATA, ScGeneralFunction::NONE, false } }; + + const char* aData[][3] = { + { "Andy", "A", "30" }, + { "Bruce", "B", "20" }, + }; + + size_t nFieldCount = SAL_N_ELEMENTS(aFields); + size_t const nDataCount = SAL_N_ELEMENTS(aData); + ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount); + + // Three decimals tell the format apart from the General format of an untouched cell. + SvNumberFormatter* pFormatter = m_pDoc->GetFormatTable(); + sal_Int32 nCheckPos = 0; + SvNumFormatType nType = SvNumFormatType::ALL; + sal_uInt32 nSourceFormat = 0; + OUString aFormatCode = u"0.000"_ustr; + pFormatter->PutEntry(aFormatCode, nCheckPos, nType, nSourceFormat); + CPPUNIT_ASSERT(nSourceFormat != 0); + + SCCOL nScoreColumn = aSrcRange.aEnd.Col(); + for (SCROW nRow = aSrcRange.aStart.Row() + 1; nRow <= aSrcRange.aEnd.Row(); ++nRow) + m_pDoc->ApplyAttr(nScoreColumn, nRow, 0, SfxUInt32Item(ATTR_VALUE_FORMAT, nSourceFormat)); + + ScDPObject* pDPObject + = createDPFromRange(m_pDoc, aSrcRange, aFields, nFieldCount, /*bFilterButton*/ false); + ScDPCollection* pDPs = m_pDoc->GetDPCollection(); + pDPs->InsertNewTable(std::unique_ptr(pDPObject)); + pDPObject->SetName(pDPs->CreateNewName()); + + bool bOverflow = false; + ScRange aOutRange = pDPObject->GetNewOutputRange(bOverflow); + CPPUNIT_ASSERT(!bOverflow); + pDPObject->Output(aOutRange.aStart); + aOutRange = pDPObject->GetOutRange(); + + SCTAB nTab = aOutRange.aStart.Tab(); + // The first two rows hold the field name and the column field members, the first column holds + // the row field members. + SCCOL nDataColumn = aOutRange.aStart.Col() + 1; + SCROW nDataRow = aOutRange.aStart.Row() + 2; + SCCOL nGrandTotalColumn = aOutRange.aEnd.Col(); + SCROW nGrandTotalRow = aOutRange.aEnd.Row(); + + CPPUNIT_ASSERT_EQUAL(nSourceFormat, m_pDoc->GetNumberFormat(nDataColumn, nDataRow, nTab)); + CPPUNIT_ASSERT_EQUAL(u"30.000"_ustr, m_pDoc->GetString(nDataColumn, nDataRow, nTab)); + + // The grand totals are values of the same data field, so they share the format. + CPPUNIT_ASSERT_EQUAL(nSourceFormat, m_pDoc->GetNumberFormat(nGrandTotalColumn, nDataRow, nTab)); + CPPUNIT_ASSERT_EQUAL(nSourceFormat, m_pDoc->GetNumberFormat(nDataColumn, nGrandTotalRow, nTab)); + CPPUNIT_ASSERT_EQUAL(u"50.000"_ustr, + m_pDoc->GetString(nGrandTotalColumn, nGrandTotalRow, nTab)); + + pDPs->FreeTable(pDPObject); + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/ucalc_range.cxx b/sc/qa/unit/ucalc_range.cxx index e118a039f79e..53dbab9a798c 100644 --- a/sc/qa/unit/ucalc_range.cxx +++ b/sc/qa/unit/ucalc_range.cxx @@ -18,6 +18,8 @@ #include #include +#include + class ScRangeTest : public ScUcalcTestBase { }; @@ -71,6 +73,29 @@ CPPUNIT_TEST_FIXTURE(ScRangeTest, testTdf147451) CPPUNIT_ASSERT_MESSAGE("Should fail to parse.", !(nRes & ScRefFlags::VALID)); } +CPPUNIT_TEST_FIXTURE(ScRangeTest, testHashDistribution) +{ + // tdf#164843: ranges sharing an end corner but differing only in the start + // corner must spread across hash buckets. The broken hash put all of them in + // a single bucket (distinct buckets == 1); a good hash spreads ~1000 ranges + // across most of the 1024 buckets. + constexpr size_t nCount = 1000; + constexpr size_t nBuckets = 1024; + + std::unordered_set aAreaBuckets; + std::unordered_set aStartColBuckets; + for (size_t i = 0; i < nCount; ++i) + { + // varying start row, shared end row (near MAXROW) + const ScRange aRange(28, static_cast(2000 + i), 0, 28, 1048575, 0); + aAreaBuckets.insert(aRange.hashArea() % nBuckets); + aStartColBuckets.insert(aRange.hashStartColumn() % nBuckets); + } + + CPPUNIT_ASSERT_GREATER(nCount / 2, aAreaBuckets.size()); + CPPUNIT_ASSERT_GREATER(nCount / 2, aStartColBuckets.size()); +} + class ScRangeUpdaterTest : public CppUnit::TestFixture { public: diff --git a/sc/qa/unit/ucalc_sharedformula.cxx b/sc/qa/unit/ucalc_sharedformula.cxx index 37ea7d8ecb2c..ab2f92bbbd1a 100644 --- a/sc/qa/unit/ucalc_sharedformula.cxx +++ b/sc/qa/unit/ucalc_sharedformula.cxx @@ -1084,9 +1084,9 @@ CPPUNIT_TEST_FIXTURE(TestSharedFormula, testSharedFormulasDeleteColumns) CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pCode->GetLen()); const FormulaToken* pToken = pCode->GetArray()[0]; CPPUNIT_ASSERT_EQUAL(svSingleRef, pToken->GetType()); - const ScSingleRefData* pSRef = pToken->GetSingleRef(); - CPPUNIT_ASSERT(pSRef->IsColDeleted()); - CPPUNIT_ASSERT_EQUAL(static_cast(0), pSRef->toAbs(*m_pDoc, ScAddress(1,0,0)).Row()); + const ScSingleRefData& rSRef = static_cast(pToken)->GetSingleRef(); + CPPUNIT_ASSERT(rSRef.IsColDeleted()); + CPPUNIT_ASSERT_EQUAL(static_cast(0), rSRef.toAbs(*m_pDoc, ScAddress(1,0,0)).Row()); // The formula string should show #REF! in lieu of the column position (only for Calc A1 syntax). sc::CompileFormulaContext aCFCxt(*m_pDoc, FormulaGrammar::GRAM_ENGLISH); diff --git a/sc/qa/unit/ucalc_sort.cxx b/sc/qa/unit/ucalc_sort.cxx index 481e1c5971c7..4762df44bf1c 100644 --- a/sc/qa/unit/ucalc_sort.cxx +++ b/sc/qa/unit/ucalc_sort.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -176,7 +177,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortHorizontal) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); { @@ -244,7 +245,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortHorizontalWholeColumn) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Check the sort result. @@ -308,7 +309,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortSingleRow) aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; // Do the sorting. This should not crash. - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Another test case - single row horizontal sort with header column. @@ -331,7 +332,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortSingleRow) aSortData.nCol1 = 0; aSortData.nCol2 = 6; aSortData.bByRow = false; - bSorted = aFunc.Sort(0, aSortData, true, true, true); + bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Check the result. @@ -671,7 +672,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortWithCellFormats) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, false, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, false, true); CPPUNIT_ASSERT(bSorted); // Check the sort result. @@ -741,7 +742,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); double aSorted[] = { 0.0, 1.0, 4.0, 14.0, 29.0, 36.0, 78.0, 98.0, 99.0 }; @@ -819,7 +820,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate) // Turn off reference update on sort. SortTypeSetter::changeTo(false); - bSorted = aFunc.Sort(0, aSortData, true, true, true); + bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Check the sort result again. @@ -893,7 +894,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate2) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Check the sort result in column A. @@ -979,7 +980,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate3) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Check the sorted values. @@ -1112,7 +1113,7 @@ void TestSort::testSortRefUpdate4_Impl() m_pDoc->SetAnonymousDBData( 0, std::unique_ptr(new ScDBData( STR_DB_LOCAL_NONAME, aSortRange.aStart.Tab(), aSortData.nCol1, aSortData.nRow1, aSortData.nCol2, aSortData.nRow2))); - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Check the sorted values. @@ -1184,7 +1185,7 @@ void TestSort::testSortRefUpdate4_Impl() m_pDoc->SetAnonymousDBData( 0, std::unique_ptr(new ScDBData( STR_DB_LOCAL_NONAME, aSortRange.aStart.Tab(), aSortData.nCol1, aSortData.nRow1, aSortData.nCol2, aSortData.nRow2))); - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Check the sorted values. @@ -1286,7 +1287,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate5) aSortData.maKeyState[0].nField = 0; // Date aSortData.maKeyState[0].bAscending = true; // ascending aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Check the sorted values. @@ -1382,7 +1383,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate6) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); { @@ -1519,7 +1520,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortBroadcaster) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = false; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); { @@ -1617,7 +1618,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortBroadcaster) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = false; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); { @@ -1721,7 +1722,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortBroadcastBroadcaster) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = false; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); { @@ -1792,7 +1793,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortOutOfPlaceResult) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // Source data still intact. @@ -1869,7 +1870,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortPartialFormulaGroup) aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); m_pDoc->CalcAll(); // just in case... @@ -2262,7 +2263,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testLanguageDependentNaturalSort) // Actually sort ScDBDocFunc aFunc(*m_xDocShell); - bool bSorted = aFunc.Sort(0, aSortParam, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortParam, true, true, true); CPPUNIT_ASSERT(bSorted); // Verify sort result. Without fix the comma was treated as ordinary character and thus the order @@ -2329,7 +2330,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortEmbeddedNumberTypes) // Actually sort ScDBDocFunc aFunc(*m_xDocShell); - bool bSorted = aFunc.Sort(0, aSortParam, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortParam, true, true, true); CPPUNIT_ASSERT(bSorted); // Verify sort result: Item | K1.2 | K1.104 | K2.5 | K2.40 | K2.501 | K10 @@ -2344,7 +2345,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortEmbeddedNumberTypes) // Make sure that type ScSortNumberBehavior::DOUBLE works as well // It sorts according the values of the decimal numbers. aSortParam.eSortNumberBehavior = ScSortNumberBehavior::DOUBLE; - bSorted = aFunc.Sort(0, aSortParam, true, true, true); + bSorted = aFunc.SortTab(0, aSortParam, true, true, true); CPPUNIT_ASSERT(bSorted); const std::array aExpectedDbl @@ -2358,7 +2359,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortEmbeddedNumberTypes) // And same for type ScSortNumberBehavior::ALPHA_NUMERIC // It treats digits and decimal separator of the numbers as normal characters. aSortParam.eSortNumberBehavior = ScSortNumberBehavior::ALPHA_NUMERIC; - bSorted = aFunc.Sort(0, aSortParam, true, true, true); + bSorted = aFunc.SortTab(0, aSortParam, true, true, true); CPPUNIT_ASSERT(bSorted); const std::array aExpectedAlpha @@ -2418,7 +2419,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testShuffle) aSortData.meSortOrderType = SortOrderType::Random; ScDBDocFunc aFunc(*m_xDocShell); - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); // First check the header, which should be untouched @@ -2522,7 +2523,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testShuffleAndThenSort) aSortData.aDataAreaExtras.mbCellFormats = true; aSortData.meSortOrderType = SortOrderType::Random; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); } @@ -2541,7 +2542,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testShuffleAndThenSort) aSortData.maKeyState[0].bAscending = true; aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None; - bool bSorted = aFunc.Sort(0, aSortData, true, true, true); + bool bSorted = aFunc.SortTab(0, aSortData, true, true, true); CPPUNIT_ASSERT(bSorted); } @@ -2568,6 +2569,37 @@ CPPUNIT_TEST_FIXTURE(TestSort, testShuffleAndThenSort) m_pDoc->DeleteTab(0); } +// cool#16004: a first row that carries autofilter or pivot table button +// attributes is a header row, so sorting leaves it in place. +CPPUNIT_TEST_FIXTURE(TestSort, testColHeaderWithFilterButtons) +{ + m_pDoc->InsertTab(0, u"test"_ustr); + + // All cells numeric, so no row qualifies as a header by cell type alone. + const std::vector> aData = { + { "10", "20" }, + { "3", "1" }, + { "2", "5" }, + }; + insertRangeData(m_pDoc, ScAddress(0, 0, 0), aData); + + CPPUNIT_ASSERT(!m_pDoc->HasColHeader(0, 0, 1, 2, 0)); + + // Flag the first row the way an autofilter marks its header cells. + m_pDoc->ApplyFlagsTab(0, 0, 1, 0, 0, ScMF::Auto); + CPPUNIT_ASSERT(m_pDoc->HasColHeader(0, 0, 1, 2, 0)); + + m_pDoc->RemoveFlagsTab(0, 0, 1, 0, 0, ScMF::Auto); + CPPUNIT_ASSERT(!m_pDoc->HasColHeader(0, 0, 1, 2, 0)); + + // A single cell flagged the way a pivot table marks its field buttons + // is enough to make the whole first row a header. + m_pDoc->ApplyFlagsTab(1, 0, 1, 0, 0, ScMF::ButtonPopup); + CPPUNIT_ASSERT(m_pDoc->HasColHeader(0, 0, 1, 2, 0)); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/ucalc_spilled_range.cxx b/sc/qa/unit/ucalc_spilled_range.cxx new file mode 100644 index 000000000000..50974cfdb329 --- /dev/null +++ b/sc/qa/unit/ucalc_spilled_range.cxx @@ -0,0 +1,553 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 "helper/qahelper.hxx" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace formula; + +class TestSpilledRange : public ScUcalcTestBase +{ +}; + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperator) +{ + // The # postfix operator on the origin of a 1x4 matrix formula + // expands to the spill range, so SUM(A1#) totals all four values. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + m_pDoc->SetValue(ScAddress(1, 3, 0), 40.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 3, aMark, u"=B1:B4"_ustr); + + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pFC); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pFC->GetMatrixFlag()); + SCCOL nCols = 0; + SCROW nRows = 0; + pFC->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nCols); + CPPUNIT_ASSERT_EQUAL(static_cast(4), nRows); + + m_pDoc->SetString(ScAddress(2, 0, 0), u"=SUM(A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(100.0, m_pDoc->GetValue(ScAddress(2, 0, 0))); + + m_pDoc->SetString(ScAddress(2, 1, 0), u"=COUNT(A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(4.0, m_pDoc->GetValue(ScAddress(2, 1, 0))); + + CPPUNIT_ASSERT_EQUAL(u"=SUM(A1#)"_ustr, m_pDoc->GetFormula(2, 0, 0)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorOnNumberCell) +{ + // # on a plain value cell reports #REF!. The operator requires + // its operand to be the master cell of a dynamic-array formula. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 42.0); + m_pDoc->SetString(ScAddress(1, 0, 0), u"=A1#"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorOnStringCell) +{ + // # on a plain string cell reports #REF!. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetString(ScAddress(0, 0, 0), u"hello"_ustr); + m_pDoc->SetString(ScAddress(1, 0, 0), u"=A1#"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorOnNonMasterFormula) +{ + // # on a plain formula cell that is not a dynamic-array master + // falls back to that cell's value. Only a master triggers the + // spill expansion. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetString(ScAddress(0, 0, 0), u"=1+2"_ustr); + m_pDoc->SetString(ScAddress(1, 0, 0), u"=A1#"_ustr); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeNeedsOneCellToNameAMaster) +{ + // The # refers to the master cell before it, so an operand wider than one cell has no + // master and gives #REF!. A union list is used because a plain range before a # is + // reduced to the cell it lines up with during the parse and never arrives as a range. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(4, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(4, 1, 0), 20.0); + + // Master at A1 spills =E1:E2 into A1:A2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 1, aMark, u"=E1:E2"_ustr); + + m_pDoc->SetString(ScAddress(6, 0, 0), u"=(A1~E1)#"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(6, 0, 0))); + + // The list gets there the same way with the spill range as its second part. + m_pDoc->SetString(ScAddress(6, 1, 0), u"=(E1~A1)#"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(6, 1, 0))); + + // A matrix formula and a dynamic-array master parse without working out implicit + // intersections, so a range before the # arrives whole in those too. + m_pDoc->InsertMatrixFormula(6, 2, 6, 2, aMark, u"=(E1:E2)#"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(6, 2, 0))); + + // The range is one operand of the #, not a matrix walked cell by cell, so the master + // gives one error and spills nothing. The value below it would force #SPILL! if it did. + m_pDoc->SetValue(ScAddress(7, 1, 0), 5.0); + m_pDoc->InsertMatrixFormula(7, 0, 7, 0, aMark, u"=(E1:E2)#"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster=*/true); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(7, 0, 0))); + + m_pDoc->SetValue(ScAddress(8, 1, 0), 5.0); + m_pDoc->InsertMatrixFormula(8, 0, 8, 0, aMark, u"=E1:E2#"_ustr, nullptr, + formula::FormulaGrammar::GRAM_DEFAULT, + /*bDynamicArrayMaster=*/true); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(8, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorImplicitIntersection) +{ + // A # reference in a cell that does not promote to a dynamic-array + // master reduces by implicit intersection on the spill range. The + // cell takes the slot of the spill range aligned with the formula + // position, or #VALUE! when the formula sits outside the spill + // range. Cells set through SetString are not eligible for + // promotion, so they take this path. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + // Master at A1 spills =B1:B3 with 10, 20 and 30 into A1:A3. + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 2, aMark, u"=B1:B3"_ustr); + + // The reference cells E1..E3 sit in rows aligned with the spill + // range. Each picks the slot of A1# matching its own row. E4 + // sits one row past the spill range, so the cell reports + // #VALUE! through implicit intersection failure. + m_pDoc->SetString(ScAddress(4, 0, 0), u"=A1#"_ustr); + m_pDoc->SetString(ScAddress(4, 1, 0), u"=A1#"_ustr); + m_pDoc->SetString(ScAddress(4, 2, 0), u"=A1#"_ustr); + m_pDoc->SetString(ScAddress(4, 3, 0), u"=A1#"_ustr); + + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(4, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(4, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(4, 2, 0))); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(4, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorRespills) +{ + // A freshly typed =A1# intends an array result, so it promotes to + // a dynamic-array master and spills the referenced range again + // instead of collapsing to the row-aligned value. + m_pDoc->SetAutoCalc(false); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + + // Master at A1 spills =B1:B3 into A1:A3. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 2, aMark, u"=B1:B3"_ustr); + + // Enter =A1# at E1 the way the UI does: eligible for promotion. + ScAddress aRefPos(4, 0, 0); + ScCompiler aComp(*m_pDoc, aRefPos, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pCode = aComp.CompileString(u"=A1#"_ustr); + auto pRef = new ScFormulaCell(*m_pDoc, aRefPos, std::move(pCode)); + pRef->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aRefPos, pRef); + + m_pDoc->SetAutoCalc(true); + m_pDoc->CalcAll(); + + // E1 became a master covering three rows and spilled its values + // into E1:E3. + CPPUNIT_ASSERT(pRef->IsDynamicArrayMaster()); + SCCOL nCols = 0; + SCROW nRows = 0; + pRef->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nCols); + CPPUNIT_ASSERT_EQUAL(static_cast(3), nRows); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(4, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, m_pDoc->GetValue(ScAddress(4, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(4, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorIsRef) +{ + // A # spilled-range reference answers ISREF as a reference, even + // though it evaluates to a matrix. A plain computed matrix is not + // a reference. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + + // Master at A1 spills =B1:B2 into A1:A2. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 1, aMark, u"=B1:B2"_ustr); + + m_pDoc->SetString(ScAddress(4, 0, 0), u"=ISREF(A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(4, 0, 0))); + + // A matrix that carries no source range stays a non-reference. + m_pDoc->SetString(ScAddress(4, 1, 0), u"=ISREF(MUNIT(2))"_ustr); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(4, 1, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorIsFormula) +{ + // ISFORMULA over a # spilled-range reference reports per cell of the + // spill range, the same as over the plain range: the master is a + // formula, the cells it spilled into are not. + m_pDoc->SetAutoCalc(false); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetString(ScAddress(0, 0, 0), u"=1+10"_ustr); + m_pDoc->SetString(ScAddress(0, 1, 0), u"=1+20"_ustr); + m_pDoc->SetString(ScAddress(0, 2, 0), u"=1+30"_ustr); + + // B2 spills =A1:A3 into B2:B4 as a dynamic-array master. + ScAddress aPos(1, 1, 0); + ScCompiler aComp(*m_pDoc, aPos, m_pDoc->GetGrammar(), false, false); + std::unique_ptr pCode = aComp.CompileString(u"=A1:A3"_ustr); + auto pCell = new ScFormulaCell(*m_pDoc, aPos, std::move(pCode)); + pCell->SetAutoDynamicArrayEligible(true); + m_pDoc->SetFormulaCell(aPos, pCell); + m_pDoc->SetAutoCalc(true); + m_pDoc->CalcAll(); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + + // In an array context, ISFORMULA(B2#) gives one formula (the master) + // then two non-formula spilled cells, matching ISFORMULA(B2:B4). + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(3, 0, 3, 2, aMark, u"=ISFORMULA(B2#)"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(3, 0, 0))); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(3, 1, 0))); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(3, 2, 0))); + + // In a plain cell it reduces by implicit intersection to the + // row-aligned cell: the master row is a formula, a spilled row is + // not. + m_pDoc->SetString(ScAddress(5, 1, 0), u"=ISFORMULA(B2#)"_ustr); + m_pDoc->SetString(ScAddress(5, 2, 0), u"=ISFORMULA(B2#)"_ustr); + m_pDoc->CalcAll(); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(5, 1, 0))); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(5, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorInheritsFormat) +{ + // A # reference that collapses to a single value keeps the number + // format of the spill-range cell it resolves to, the same as a + // plain reference to that cell would. A fractional value also + // survives without being truncated to a whole number. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 43831.5); + m_pDoc->SetValue(ScAddress(1, 1, 0), 43832.5); + m_pDoc->SetValue(ScAddress(1, 2, 0), 43833.5); + + // Master at A1 spills =B1:B3 into A1:A3. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 2, aMark, u"=B1:B3"_ustr); + + // Give the spill cells a date format. + SvNumberFormatter* pFormatter = m_pDoc->GetFormatTable(); + sal_uInt32 nDateFormat = pFormatter->GetFormatIndex(NF_DATE_SYS_DDMMYYYY, LANGUAGE_ENGLISH_US); + ScPatternAttr aFormatAttr(m_pDoc->getCellAttributeHelper()); + aFormatAttr.ItemSetPut(SfxUInt32Item(ATTR_VALUE_FORMAT, nDateFormat)); + m_pDoc->ApplyPatternAreaTab(0, 0, 0, 2, 0, aFormatAttr); + + // E2 collapses A1# to the row-aligned slot, keeping its value and + // date format. + m_pDoc->SetString(ScAddress(4, 1, 0), u"=A1#"_ustr); + CPPUNIT_ASSERT_EQUAL(43832.5, m_pDoc->GetValue(ScAddress(4, 1, 0))); + CPPUNIT_ASSERT_EQUAL(SvNumFormatType::DATE, + pFormatter->GetType(m_pDoc->GetNumberFormat(4, 1, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorMultiColumn) +{ + // # on the origin of a 2x3 matrix expands to all six cells. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(2, 0, 0), 1.0); + m_pDoc->SetValue(ScAddress(3, 0, 0), 2.0); + m_pDoc->SetValue(ScAddress(2, 1, 0), 3.0); + m_pDoc->SetValue(ScAddress(3, 1, 0), 4.0); + m_pDoc->SetValue(ScAddress(2, 2, 0), 5.0); + m_pDoc->SetValue(ScAddress(3, 2, 0), 6.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 1, 2, aMark, u"=C1:D3"_ustr); + + m_pDoc->SetString(ScAddress(4, 0, 0), u"=SUM(A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(21.0, m_pDoc->GetValue(ScAddress(4, 0, 0))); + + m_pDoc->SetString(ScAddress(4, 1, 0), u"=ROWS(A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(ScAddress(4, 1, 0))); + + m_pDoc->SetString(ScAddress(4, 2, 0), u"=COLUMNS(A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(4, 2, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorOnNonMasterMatrixCell) +{ + // # on a non-master slot of a spilled matrix reports #REF!. Only + // the master cell of the dynamic-array formula is a valid operand + // for the spill expansion. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(1, 2, 0), 30.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 2, aMark, u"=B1:B3"_ustr); + + // A2 is a non-master slot of the A1:A3 spill range, so =A2# is + // an illegal reference. + m_pDoc->SetString(ScAddress(2, 0, 0), u"=A2#"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(2, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorEmptyCell) +{ + // # on an empty cell reports #REF!. An empty cell is not a + // dynamic-array master, so the operator has no spill range + // to expand. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetString(ScAddress(1, 0, 0), u"=A1#"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorInExpression) +{ + // # composes with arithmetic and aggregating functions. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(1, 0, 0), 5.0); + m_pDoc->SetValue(ScAddress(1, 1, 0), 15.0); + + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 1, aMark, u"=B1:B2"_ustr); + + m_pDoc->SetString(ScAddress(2, 0, 0), u"=SUM(A1#)+100"_ustr); + CPPUNIT_ASSERT_EQUAL(120.0, m_pDoc->GetValue(ScAddress(2, 0, 0))); + + CPPUNIT_ASSERT_EQUAL(u"=SUM(A1#)+100"_ustr, m_pDoc->GetFormula(2, 0, 0)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeKeepsItsPlaceThroughAnOperator) +{ + // An operator over a # spilled range gives one value per cell, so the result sits at + // that range. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(4, 0, 0), 100.0); + m_pDoc->SetValue(ScAddress(4, 1, 0), 200.0); + m_pDoc->SetValue(ScAddress(4, 2, 0), 400.0); + + // Master at A1 spills =E1:E3 into A1:A3. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 2, aMark, u"=E1:E3"_ustr); + + // Each cell takes the percent of the spilled value in its own row. + m_pDoc->SetString(ScAddress(6, 0, 0), u"=A1#%"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(6, 0, 0))); + m_pDoc->SetString(ScAddress(6, 1, 0), u"=A1#%"_ustr); + CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(ScAddress(6, 1, 0))); + + // One row past the spill range there is no value to line up with. + m_pDoc->SetString(ScAddress(6, 3, 0), u"=A1#%"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NoValue, m_pDoc->GetErrCode(ScAddress(6, 3, 0))); + + // SUM takes an array, so it gets all the percents, not just one. + m_pDoc->SetString(ScAddress(7, 0, 0), u"=SUM(A1#%)"_ustr); + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(7, 0, 0))); + + // An explicit @ takes the first percent, not the row's, as they are not the cells' own values. + m_pDoc->SetString(ScAddress(9, 1, 0), u"=@(A1#%)"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(9, 1, 0))); + + // The spill range references its cells. The percents are the operator's own values, so + // they sit at that range without referencing it. + m_pDoc->SetString(ScAddress(8, 0, 0), u"=ISREF(A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(8, 0, 0))); + m_pDoc->SetString(ScAddress(8, 1, 0), u"=ISREF(A1#%)"_ustr); + CPPUNIT_ASSERT_EQUAL(0.0, m_pDoc->GetValue(ScAddress(8, 1, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeAsReferenceOperatorOperand) +{ + // The reference operators take a # spilled range as the range it stands for. They pop it + // as a matrix that carries the range, and since they work on ranges they use the range + // and leave the values alone. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(4, 0, 0), 10.0); + m_pDoc->SetValue(ScAddress(4, 1, 0), 20.0); + m_pDoc->SetValue(ScAddress(4, 2, 0), 30.0); + + // Master at A1 spills =E1:E3 into A1:A3. + ScMarkData aMark(m_pDoc->GetSheetLimits()); + aMark.SelectOneTable(0); + m_pDoc->InsertMatrixFormula(0, 0, 0, 2, aMark, u"=E1:E3"_ustr); + + // B2 and C1 sit outside the spill range, so each operator's result is a distinct sum. + m_pDoc->SetValue(ScAddress(1, 1, 0), 7.0); + m_pDoc->SetValue(ScAddress(2, 0, 0), 5.0); + + // The intersection of A1:C2 with the spill range A1:A3 is A1:A2, whichever side the + // spill range is on. + m_pDoc->SetString(ScAddress(6, 0, 0), u"=SUM(A1:C2!A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(6, 0, 0))); + // The parentheses keep the # away from the intersection operator, because a # directly + // before an exclamation mark lexes as the start of an error constant. + m_pDoc->SetString(ScAddress(7, 0, 0), u"=SUM((A1#)!A1:C2)"_ustr); + CPPUNIT_ASSERT_EQUAL(30.0, m_pDoc->GetValue(ScAddress(7, 0, 0))); + + // The range operator spans the spill range and C1, which is A1:C3, so B2 comes in. + m_pDoc->SetString(ScAddress(6, 1, 0), u"=SUM(A1#:C1)"_ustr); + CPPUNIT_ASSERT_EQUAL(72.0, m_pDoc->GetValue(ScAddress(6, 1, 0))); + // The parentheses keep the left operand apart from the spill range, because C1:A1 on its + // own lexes as a single reference instead of two operands of the range operator. + m_pDoc->SetString(ScAddress(7, 1, 0), u"=SUM((C1):A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, m_pDoc->GetErrCode(ScAddress(7, 1, 0))); + CPPUNIT_ASSERT_EQUAL(72.0, m_pDoc->GetValue(ScAddress(7, 1, 0))); + + // The union operator keeps the parts apart, so B2 stays out. + m_pDoc->SetString(ScAddress(6, 2, 0), u"=SUM(A1#~C1)"_ustr); + CPPUNIT_ASSERT_EQUAL(65.0, m_pDoc->GetValue(ScAddress(6, 2, 0))); + m_pDoc->SetString(ScAddress(7, 2, 0), u"=SUM(C1~A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(65.0, m_pDoc->GetValue(ScAddress(7, 2, 0))); + + // With a third part the union operator extends a list it already built, which is a + // separate code path, so check that the spill range gets there too. + m_pDoc->SetString(ScAddress(6, 3, 0), u"=SUM(C1~B2~A1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(72.0, m_pDoc->GetValue(ScAddress(6, 3, 0))); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_TEST_FIXTURE(TestSpilledRange, testSpilledRangeOperatorFormulaStringRoundtrip) +{ + // The # operator round-trips through GetFormula across several + // common shapes: standalone, inside SUM/AVERAGE, and on both + // operands of a binary expression. + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetString(ScAddress(0, 0, 0), u"=A2#"_ustr); + CPPUNIT_ASSERT_EQUAL(u"=A2#"_ustr, m_pDoc->GetFormula(0, 0, 0)); + + m_pDoc->SetString(ScAddress(0, 1, 0), u"=SUM(B1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(u"=SUM(B1#)"_ustr, m_pDoc->GetFormula(0, 1, 0)); + + m_pDoc->SetString(ScAddress(0, 2, 0), u"=AVERAGE(C5#)"_ustr); + CPPUNIT_ASSERT_EQUAL(u"=AVERAGE(C5#)"_ustr, m_pDoc->GetFormula(0, 2, 0)); + + m_pDoc->SetString(ScAddress(0, 3, 0), u"=MAX(D1#)+MIN(D1#)"_ustr); + CPPUNIT_ASSERT_EQUAL(u"=MAX(D1#)+MIN(D1#)"_ustr, m_pDoc->GetFormula(0, 3, 0)); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/qa/unit/ucalc_tablestyles.cxx b/sc/qa/unit/ucalc_tablestyles.cxx new file mode 100644 index 000000000000..321a6329da29 --- /dev/null +++ b/sc/qa/unit/ucalc_tablestyles.cxx @@ -0,0 +1,830 @@ +/* -*- 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 "helper/qahelper.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +using namespace css; + +class TableStylesTest : public ScUcalcTestBase +{ +}; + +namespace +{ +// Theme A: distinct primary accent colors for easy verification +std::shared_ptr createTestThemeA() +{ + auto pColorSet = std::make_shared("ThemeA"); + pColorSet->add(model::ThemeColorType::Dark1, 0x000000); + pColorSet->add(model::ThemeColorType::Light1, 0xFFFFFF); + pColorSet->add(model::ThemeColorType::Dark2, 0x444444); + pColorSet->add(model::ThemeColorType::Light2, 0xEEEEEE); + pColorSet->add(model::ThemeColorType::Accent1, 0xFF0000); // red + pColorSet->add(model::ThemeColorType::Accent2, 0x00FF00); // green + pColorSet->add(model::ThemeColorType::Accent3, 0x0000FF); // blue + pColorSet->add(model::ThemeColorType::Accent4, 0xFFFF00); // yellow + pColorSet->add(model::ThemeColorType::Accent5, 0xFF00FF); // magenta + pColorSet->add(model::ThemeColorType::Accent6, 0x00FFFF); // cyan + pColorSet->add(model::ThemeColorType::Hyperlink, 0x0563C1); + pColorSet->add(model::ThemeColorType::FollowedHyperlink, 0x954F72); + return pColorSet; +} + +// Theme B: swapped accents for theme change verification +std::shared_ptr createTestThemeB() +{ + auto pColorSet = std::make_shared("ThemeB"); + pColorSet->add(model::ThemeColorType::Dark1, 0x000000); + pColorSet->add(model::ThemeColorType::Light1, 0xFFFFFF); + pColorSet->add(model::ThemeColorType::Dark2, 0x333333); + pColorSet->add(model::ThemeColorType::Light2, 0xDDDDDD); + pColorSet->add(model::ThemeColorType::Accent1, 0x0000FF); // blue (was red) + pColorSet->add(model::ThemeColorType::Accent2, 0xFF0000); // red (was green) + pColorSet->add(model::ThemeColorType::Accent3, 0x00FF00); // green (was blue) + pColorSet->add(model::ThemeColorType::Accent4, 0x00FFFF); // cyan (was yellow) + pColorSet->add(model::ThemeColorType::Accent5, 0xFFFF00); // yellow (was magenta) + pColorSet->add(model::ThemeColorType::Accent6, 0xFF00FF); // magenta (was cyan) + pColorSet->add(model::ThemeColorType::Hyperlink, 0x0563C1); + pColorSet->add(model::ThemeColorType::FollowedHyperlink, 0x954F72); + return pColorSet; +} + +// Set up the document theme with the given ColorSet on the draw layer +void applyThemeToDocument(ScDocument* pDoc, std::shared_ptr pColorSet) +{ + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + CPPUNIT_ASSERT(pDrawLayer); + auto const& pTheme = pDrawLayer->getTheme(); + CPPUNIT_ASSERT(pTheme); + pTheme->setColorSet(pColorSet); +} + +// Create a ScDBData with table style assigned, range A1:D10 with header and total rows +ScDBData* createTestDBData(ScDocument* pDoc, const OUString& rStyleName) +{ + // range: A1:D11 (row 0 = header, rows 1-9 = data, row 10 = total) + ScDBData* pDBData = new ScDBData(u"TestTable"_ustr, 0, 0, 0, 3, 10, true, true, true); + + ScTableStyleParam aStyleParam; + aStyleParam.maStyleID = rStyleName; + aStyleParam.mbRowStripes = true; + aStyleParam.mbColumnStripes = false; + aStyleParam.mbFirstColumn = false; + aStyleParam.mbLastColumn = false; + pDBData->SetTableStyleInfo(aStyleParam); + + bool bInserted + = pDoc->GetDBCollection()->getNamedDBs().insert(std::unique_ptr(pDBData)); + CPPUNIT_ASSERT(bInserted); + return pDBData; +} + +} // anonymous namespace + +// Test 1: Verify 60 default styles are generated with correct names +CPPUNIT_TEST_FIXTURE(TableStylesTest, testGenerateDefaultStyles) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + ScTableStyles* pStyles = m_pDoc->GetTableStyles(); + CPPUNIT_ASSERT(pStyles); + + // Verify some key style names from each category + CPPUNIT_ASSERT(pStyles->GetTableStyle(u"TableStyleLight1"_ustr)); + CPPUNIT_ASSERT(pStyles->GetTableStyle(u"TableStyleLight21"_ustr)); + CPPUNIT_ASSERT(pStyles->GetTableStyle(u"TableStyleMedium1"_ustr)); + CPPUNIT_ASSERT(pStyles->GetTableStyle(u"TableStyleMedium2"_ustr)); + CPPUNIT_ASSERT(pStyles->GetTableStyle(u"TableStyleMedium28"_ustr)); + CPPUNIT_ASSERT(pStyles->GetTableStyle(u"TableStyleDark1"_ustr)); + CPPUNIT_ASSERT(pStyles->GetTableStyle(u"TableStyleDark11"_ustr)); + + // Verify non-existent style returns null + CPPUNIT_ASSERT(!pStyles->GetTableStyle(u"NonExistentStyle"_ustr)); + + // All styles should be marked as OOXML defaults + const ScTableStyle* pStyle = pStyles->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + CPPUNIT_ASSERT(pStyle->IsOOXMLDefault()); + + m_pDoc->DeleteTab(0); +} + +// Test 2: Verify fill colors are correctly resolved from theme +CPPUNIT_TEST_FIXTURE(TableStylesTest, testTableStyleFillColors) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + ScDBData* pDBData = createTestDBData(m_pDoc, u"TableStyleMedium2"_ustr); + + const ScTableStyle* pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + + // Header row (row 0) should have a solid fill based on Accent1 (red = 0xFF0000) + const SvxBrushItem* pHeaderFill = pStyle->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pHeaderFill); + Color aHeaderColor = pHeaderFill->GetColor(); + // Header fill for Medium2 uses Accent1 (theme index 4) — should be red-based + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0xFF), aHeaderColor.GetRed()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0x00), aHeaderColor.GetGreen()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0x00), aHeaderColor.GetBlue()); + + // First row stripe (row 1, rowIndex 0) should have a tinted fill + const SvxBrushItem* pStripeFill = pStyle->GetFillItem(*pDBData, 0, 1, 0); + if (pStripeFill) + { + Color aStripeColor = pStripeFill->GetColor(); + // Tinted Accent1 — should still be reddish but lighter + CPPUNIT_ASSERT(aStripeColor.GetRed() > aStripeColor.GetGreen()); + CPPUNIT_ASSERT(aStripeColor.GetRed() > aStripeColor.GetBlue()); + } + + // Second row stripe (row 2, rowIndex 1) — Medium2 has no fill for second stripe + const SvxBrushItem* pStripe2Fill = pStyle->GetFillItem(*pDBData, 0, 2, 1); + // Either null or transparent/white + if (pStripe2Fill) + { + Color aStripe2Color = pStripe2Fill->GetColor(); + CPPUNIT_ASSERT(aStripe2Color == COL_WHITE || aStripe2Color == COL_TRANSPARENT); + } + + m_pDoc->DeleteTab(0); +} + +// Test 3: Verify border widths and styles +CPPUNIT_TEST_FIXTURE(TableStylesTest, testTableStyleBorders) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + ScDBData* pDBData = createTestDBData(m_pDoc, u"TableStyleMedium2"_ustr); + + const ScTableStyle* pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + + // Data cell (row 5, middle of table) — should have thin borders from WholeTable + std::unique_ptr pBoxItem = pStyle->GetBoxItem(*pDBData, 1, 5, 4); + CPPUNIT_ASSERT(pBoxItem); + + // Top and bottom borders should be thin (SvxBorderLineWidth::Thin = 15) + const editeng::SvxBorderLine* pTopLine = pBoxItem->GetLine(SvxBoxItemLine::TOP); + CPPUNIT_ASSERT(pTopLine); + CPPUNIT_ASSERT_EQUAL(tools::Long(15), pTopLine->GetWidth()); + + const editeng::SvxBorderLine* pBotLine = pBoxItem->GetLine(SvxBoxItemLine::BOTTOM); + CPPUNIT_ASSERT(pBotLine); + CPPUNIT_ASSERT_EQUAL(tools::Long(15), pBotLine->GetWidth()); + + // Border color should be Accent1-tinted (reddish) + CPPUNIT_ASSERT(pTopLine->GetColor().GetRed() > pTopLine->GetColor().GetGreen()); + + // Total row (row 10, rowIndex 9) — should have a DOUBLE top border + std::unique_ptr pTotalBox = pStyle->GetBoxItem(*pDBData, 1, 10, 9); + CPPUNIT_ASSERT(pTotalBox); + const editeng::SvxBorderLine* pTotalTop = pTotalBox->GetLine(SvxBoxItemLine::TOP); + CPPUNIT_ASSERT(pTotalTop); + CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE_THIN, pTotalTop->GetBorderLineStyle()); + + m_pDoc->DeleteTab(0); +} + +// Test 4: Verify font properties (bold, color) +CPPUNIT_TEST_FIXTURE(TableStylesTest, testTableStyleFonts) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + ScDBData* pDBData = createTestDBData(m_pDoc, u"TableStyleMedium2"_ustr); + + const ScTableStyle* pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + + // Header row should have bold white font + const SfxItemSet* pHeaderFont = pStyle->GetFontItemSet(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pHeaderFont); + + // Check bold + const SvxWeightItem* pWeight = pHeaderFont->GetItemIfSet(ATTR_FONT_WEIGHT, false); + CPPUNIT_ASSERT(pWeight); + CPPUNIT_ASSERT_EQUAL(WEIGHT_BOLD, pWeight->GetWeight()); + + // Check white font color + const SvxColorItem* pColorItem = pHeaderFont->GetItemIfSet(ATTR_FONT_COLOR, false); + CPPUNIT_ASSERT(pColorItem); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, pColorItem->GetValue()); + + // Total row should have bold font + const SfxItemSet* pTotalFont = pStyle->GetFontItemSet(*pDBData, 0, 10, 9); + CPPUNIT_ASSERT(pTotalFont); + const SvxWeightItem* pTotalWeight = pTotalFont->GetItemIfSet(ATTR_FONT_WEIGHT, false); + CPPUNIT_ASSERT(pTotalWeight); + CPPUNIT_ASSERT_EQUAL(WEIGHT_BOLD, pTotalWeight->GetWeight()); + + // Data row should have no font override + const SfxItemSet* pDataFont = pStyle->GetFontItemSet(*pDBData, 0, 5, 4); + // Either null or empty — data rows typically have no font styling + if (pDataFont) + { + const SvxWeightItem* pDataWeight = pDataFont->GetItemIfSet(ATTR_FONT_WEIGHT, false); + // If present, should not be bold + if (pDataWeight) + CPPUNIT_ASSERT(pDataWeight->GetWeight() != WEIGHT_BOLD); + } + + m_pDoc->DeleteTab(0); +} + +// Test 5: Verify styles regenerate with new theme colors +CPPUNIT_TEST_FIXTURE(TableStylesTest, testTableStyleThemeChange) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + // Start with Theme A (Accent1 = red) + auto pColorSetA = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSetA); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSetA); + + ScDBData* pDBData = createTestDBData(m_pDoc, u"TableStyleMedium2"_ustr); + + const ScTableStyle* pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + + // Verify header fill is red-based (Accent1 = 0xFF0000) + const SvxBrushItem* pFillA = pStyle->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFillA); + Color aColorA = pFillA->GetColor(); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0xFF), aColorA.GetRed()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0x00), aColorA.GetBlue()); + + // Apply Theme B (Accent1 = blue) via ThemeColorChanger + auto pColorSetB = createTestThemeB(); + sc::ThemeColorChanger aChanger(*m_xDocShell); + aChanger.apply(pColorSetB); + + // Re-fetch style pointer (regenerated) + pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + + // Verify header fill is now blue-based (Accent1 = 0x0000FF) + const SvxBrushItem* pFillB = pStyle->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFillB); + Color aColorB = pFillB->GetColor(); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0x00), aColorB.GetRed()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0xFF), aColorB.GetBlue()); + + // Border colors should also have changed + std::unique_ptr pBoxB = pStyle->GetBoxItem(*pDBData, 1, 5, 4); + CPPUNIT_ASSERT(pBoxB); + const editeng::SvxBorderLine* pLine = pBoxB->GetLine(SvxBoxItemLine::TOP); + CPPUNIT_ASSERT(pLine); + // Should be blue-based now + CPPUNIT_ASSERT(pLine->GetColor().GetBlue() > pLine->GetColor().GetRed()); + + m_pDoc->DeleteTab(0); +} + +// Test 6: Verify undo/redo restores correct table style colors +CPPUNIT_TEST_FIXTURE(TableStylesTest, testTableStyleThemeChangeUndoRedo) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + // Start with Theme A (Accent1 = red) + auto pColorSetA = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSetA); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSetA); + + ScDBData* pDBData = createTestDBData(m_pDoc, u"TableStyleMedium2"_ustr); + + // Verify initial state: red + const ScTableStyle* pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + const SvxBrushItem* pFill = pStyle->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFill); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0xFF), pFill->GetColor().GetRed()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0x00), pFill->GetColor().GetBlue()); + + // Apply Theme B (Accent1 = blue) + auto pColorSetB = createTestThemeB(); + sc::ThemeColorChanger aChanger(*m_xDocShell); + aChanger.apply(pColorSetB); + + // Verify: blue + pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + pFill = pStyle->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFill); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0x00), pFill->GetColor().GetRed()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0xFF), pFill->GetColor().GetBlue()); + + // Undo → should be red again + m_pDoc->GetUndoManager()->Undo(); + + pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + pFill = pStyle->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFill); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0xFF), pFill->GetColor().GetRed()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0x00), pFill->GetColor().GetBlue()); + + // Redo → should be blue again + m_pDoc->GetUndoManager()->Redo(); + + pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + pFill = pStyle->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFill); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0x00), pFill->GetColor().GetRed()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0xFF), pFill->GetColor().GetBlue()); + + m_pDoc->DeleteTab(0); +} + +// Test 7: Verify multiple style categories have correct structure +CPPUNIT_TEST_FIXTURE(TableStylesTest, testMultipleTableStyleCategories) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + // range: A1:D11 (row 0 = header, rows 1-9 = data, row 10 = total) + ScDBData* pDBData = new ScDBData(u"TestTable"_ustr, 0, 0, 0, 3, 10, true, true, true); + ScTableStyleParam aStyleParam; + aStyleParam.mbRowStripes = true; + aStyleParam.mbColumnStripes = false; + aStyleParam.mbFirstColumn = false; + aStyleParam.mbLastColumn = false; + + ScTableStyles* pStyles = m_pDoc->GetTableStyles(); + CPPUNIT_ASSERT(pStyles); + + // Test Light style: typically no header fill, thin borders + { + const ScTableStyle* pLight = pStyles->GetTableStyle(u"TableStyleLight1"_ustr); + CPPUNIT_ASSERT(pLight); + + aStyleParam.maStyleID = u"TableStyleLight1"_ustr; + pDBData->SetTableStyleInfo(aStyleParam); + + // Light1 header row — may or may not have a fill, but should have a font + const SfxItemSet* pHeaderFont = pLight->GetFontItemSet(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pHeaderFont); + const SvxWeightItem* pWeight = pHeaderFont->GetItemIfSet(ATTR_FONT_WEIGHT, false); + CPPUNIT_ASSERT(pWeight); + CPPUNIT_ASSERT_EQUAL(WEIGHT_BOLD, pWeight->GetWeight()); + } + + // Test Medium styles: various accent-based styles + { + const OUString aMediumStyles[] = { u"TableStyleMedium1"_ustr, u"TableStyleMedium2"_ustr, + u"TableStyleMedium15"_ustr, u"TableStyleMedium28"_ustr }; + + for (const auto& rName : aMediumStyles) + { + const ScTableStyle* pMedium = pStyles->GetTableStyle(rName); + CPPUNIT_ASSERT_MESSAGE(OString("Style not found: " + rName.toUtf8()).getStr(), + pMedium != nullptr); + + aStyleParam.maStyleID = rName; + pDBData->SetTableStyleInfo(aStyleParam); + + // Medium styles should have header fill + const SvxBrushItem* pFill = pMedium->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT_MESSAGE(OString("No header fill for: " + rName.toUtf8()).getStr(), + pFill != nullptr); + + // Medium styles should have borders on data cells + std::unique_ptr pBox = pMedium->GetBoxItem(*pDBData, 1, 5, 4); + CPPUNIT_ASSERT_MESSAGE(OString("No borders for: " + rName.toUtf8()).getStr(), + pBox != nullptr); + } + } + + // Test Dark styles: dark fill, white font + { + const ScTableStyle* pDark = pStyles->GetTableStyle(u"TableStyleDark1"_ustr); + CPPUNIT_ASSERT(pDark); + + aStyleParam.maStyleID = u"TableStyleDark1"_ustr; + pDBData->SetTableStyleInfo(aStyleParam); + + // Dark1 header should have a fill + const SvxBrushItem* pFill = pDark->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFill); + + // Dark1 header font should be bold and white + const SfxItemSet* pFont = pDark->GetFontItemSet(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFont); + const SvxWeightItem* pWeight = pFont->GetItemIfSet(ATTR_FONT_WEIGHT, false); + CPPUNIT_ASSERT(pWeight); + CPPUNIT_ASSERT_EQUAL(WEIGHT_BOLD, pWeight->GetWeight()); + const SvxColorItem* pColor = pFont->GetItemIfSet(ATTR_FONT_COLOR, false); + CPPUNIT_ASSERT(pColor); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, pColor->GetValue()); + } + + delete pDBData; + m_pDoc->DeleteTab(0); +} + +// Test 8: Verify changing table style on a database range +CPPUNIT_TEST_FIXTURE(TableStylesTest, testChangeTableStyle) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + // Create DB range with initial style + ScDBData* pDBData = new ScDBData(u"TestTable"_ustr, 0, 0, 0, 3, 10, true, true, true); + ScTableStyleParam aStyleParam; + aStyleParam.mbRowStripes = true; + aStyleParam.mbColumnStripes = false; + aStyleParam.mbFirstColumn = false; + aStyleParam.mbLastColumn = false; + aStyleParam.maStyleID = u"TableStyleLight1"_ustr; + pDBData->SetTableStyleInfo(aStyleParam); + + bool bInserted + = m_pDoc->GetDBCollection()->getNamedDBs().insert(std::unique_ptr(pDBData)); + CPPUNIT_ASSERT(bInserted); + + ScTableStyles* pStyles = m_pDoc->GetTableStyles(); + CPPUNIT_ASSERT(pStyles); + + // --- Style 1: TableStyleLight1 --- + { + const ScTableStyle* pStyle = pStyles->GetTableStyle(u"TableStyleLight1"_ustr); + CPPUNIT_ASSERT(pStyle); + + // Light1 header — should have bold font + const SfxItemSet* pFont = pStyle->GetFontItemSet(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFont); + + // Remember header fill for comparison + const SvxBrushItem* pFillLight = pStyle->GetFillItem(*pDBData, 0, 0, 0); + // Light styles may or may not have header fill — just record for later comparison + Color aLightHeaderColor = pFillLight ? pFillLight->GetColor() : COL_TRANSPARENT; + + // --- Switch to Style 2: TableStyleMedium2 --- + aStyleParam.maStyleID = u"TableStyleMedium2"_ustr; + pDBData->SetTableStyleInfo(aStyleParam); + + const ScTableStyle* pMedium = pStyles->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pMedium); + + // Medium2 header should have Accent1-based fill (red) + const SvxBrushItem* pFillMedium = pMedium->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFillMedium); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0xFF), pFillMedium->GetColor().GetRed()); + + // The fill should differ from Light1 + CPPUNIT_ASSERT(pFillMedium->GetColor() != aLightHeaderColor); + + // --- Switch to Style 3: TableStyleDark1 --- + aStyleParam.maStyleID = u"TableStyleDark1"_ustr; + pDBData->SetTableStyleInfo(aStyleParam); + + const ScTableStyle* pDark = pStyles->GetTableStyle(u"TableStyleDark1"_ustr); + CPPUNIT_ASSERT(pDark); + + // Dark1 should have white font on header + const SfxItemSet* pDarkFont = pDark->GetFontItemSet(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pDarkFont); + const SvxColorItem* pDarkColor = pDarkFont->GetItemIfSet(ATTR_FONT_COLOR, false); + CPPUNIT_ASSERT(pDarkColor); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, pDarkColor->GetValue()); + + // Dark1 header fill should differ from Medium2 + const SvxBrushItem* pFillDark = pDark->GetFillItem(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pFillDark); + CPPUNIT_ASSERT(pFillDark->GetColor() != pFillMedium->GetColor()); + + // --- Switch to Style 4: TableStyleLight8 (with column stripes) --- + aStyleParam.maStyleID = u"TableStyleLight8"_ustr; + aStyleParam.mbColumnStripes = true; + aStyleParam.mbRowStripes = false; + pDBData->SetTableStyleInfo(aStyleParam); + + const ScTableStyle* pLight8 = pStyles->GetTableStyle(u"TableStyleLight8"_ustr); + CPPUNIT_ASSERT(pLight8); + + // Should have valid font on header + const SfxItemSet* pLight8Font = pLight8->GetFontItemSet(*pDBData, 0, 0, 0); + CPPUNIT_ASSERT(pLight8Font); + + // --- Switch to no style (empty / "None") --- + aStyleParam.maStyleID = u""_ustr; + aStyleParam.mbColumnStripes = false; + aStyleParam.mbRowStripes = true; + pDBData->SetTableStyleInfo(aStyleParam); + + // With empty style ID, GetTableStyle returns null — no crash, no formatting + const ScTableStyle* pNone = pStyles->GetTableStyle(u""_ustr); + CPPUNIT_ASSERT(!pNone); + + // Also test "None" explicitly + aStyleParam.maStyleID = u"None"_ustr; + pDBData->SetTableStyleInfo(aStyleParam); + + const ScTableStyle* pNone2 = pStyles->GetTableStyle(u"None"_ustr); + // "None" is not a real style — should be null + CPPUNIT_ASSERT(!pNone2); + } + + m_pDoc->DeleteTab(0); +} + +// Test 9: Verify table style adapts to no header / no total row +CPPUNIT_TEST_FIXTURE(TableStylesTest, testTableStyleNoHeaderNoTotal) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + const ScTableStyle* pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + + // No header, no total: range A1:D10, bHasH=false, bTotals=false + ScDBData aDBNoHeaderNoTotal(u"NoHeaderNoTotal"_ustr, 0, 0, 0, 3, 9, true, false, false); + ScTableStyleParam aStyleParam; + aStyleParam.maStyleID = u"TableStyleMedium2"_ustr; + aStyleParam.mbRowStripes = true; + aStyleParam.mbColumnStripes = false; + aStyleParam.mbFirstColumn = false; + aStyleParam.mbLastColumn = false; + aDBNoHeaderNoTotal.SetTableStyleInfo(aStyleParam); + + // Row 0 should be data (first row stripe), NOT header + const SvxBrushItem* pFillRow0 = pStyle->GetFillItem(aDBNoHeaderNoTotal, 0, 0, 0); + // With header, row 0 would be solid Accent1 (0xFF0000). + // Without header, row 0 is first data row — should have first row stripe pattern + if (pFillRow0) + { + // Should NOT be pure Accent1 red (that's the header color) + CPPUNIT_ASSERT(pFillRow0->GetColor() != Color(0xFF0000)); + } + + // Compare: in a table WITH header, row 1 (first data row) should have the same + // fill as row 0 in a table WITHOUT header — both are first row stripe + ScDBData aDBWithHeader(u"WithHeader"_ustr, 0, 0, 0, 3, 10, true, true, false); + aDBWithHeader.SetTableStyleInfo(aStyleParam); + const SvxBrushItem* pFirstStripeWithHeader = pStyle->GetFillItem(aDBWithHeader, 0, 1, 0); + if (pFillRow0 && pFirstStripeWithHeader) + { + // Both should be the same first row stripe color + CPPUNIT_ASSERT_EQUAL(pFirstStripeWithHeader->GetColor(), pFillRow0->GetColor()); + } + + // No total row — last row (row 9) is just a data row, not a total row + // No DOUBLE_THIN border + std::unique_ptr pBoxLast = pStyle->GetBoxItem(aDBNoHeaderNoTotal, 1, 9, 9); + if (pBoxLast) + { + const editeng::SvxBorderLine* pTopLine = pBoxLast->GetLine(SvxBoxItemLine::TOP); + if (pTopLine) + CPPUNIT_ASSERT(pTopLine->GetBorderLineStyle() != SvxBorderLineStyle::DOUBLE_THIN); + } + + // No bold font on last row (total row would have bold) + const SfxItemSet* pLastRowFont = pStyle->GetFontItemSet(aDBNoHeaderNoTotal, 0, 9, 9); + if (pLastRowFont) + { + const SvxWeightItem* pWeight = pLastRowFont->GetItemIfSet(ATTR_FONT_WEIGHT, false); + if (pWeight) + CPPUNIT_ASSERT(pWeight->GetWeight() != WEIGHT_BOLD); + } + + // Last row should have normal stripe fill, same as other data rows + // Row 9 (rowIndex 9) with no header: even index = first stripe, odd = second + const SvxBrushItem* pLastRowFill = pStyle->GetFillItem(aDBNoHeaderNoTotal, 0, 9, 9); + // Compare with another data row at the same stripe position + const SvxBrushItem* pDataRowFill = pStyle->GetFillItem(aDBNoHeaderNoTotal, 0, 1, 1); + if (pLastRowFill && pDataRowFill) + { + // Same stripe position → same color + CPPUNIT_ASSERT_EQUAL(pDataRowFill->GetColor(), pLastRowFill->GetColor()); + } + + // With header, with total + ScDBData aDBWithBoth(u"WithBoth"_ustr, 0, 0, 0, 3, 10, true, true, true); + aDBWithBoth.SetTableStyleInfo(aStyleParam); + + // Row 0 should be header — solid Accent1 + const SvxBrushItem* pHeaderFill = pStyle->GetFillItem(aDBWithBoth, 0, 0, 0); + CPPUNIT_ASSERT(pHeaderFill); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(0xFF), pHeaderFill->GetColor().GetRed()); + + // Total row (row 10) should have DOUBLE_THIN top border + std::unique_ptr pTotalBox = pStyle->GetBoxItem(aDBWithBoth, 1, 10, 9); + CPPUNIT_ASSERT(pTotalBox); + const editeng::SvxBorderLine* pTotalTop = pTotalBox->GetLine(SvxBoxItemLine::TOP); + CPPUNIT_ASSERT(pTotalTop); + CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE_THIN, pTotalTop->GetBorderLineStyle()); + + m_pDoc->DeleteTab(0); +} + +// Test 10: Verify banded columns work correctly +CPPUNIT_TEST_FIXTURE(TableStylesTest, testTableStyleBandedColumns) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + // Use a style that supports column stripes (Light8 has column stripe patterns) + const ScTableStyle* pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleLight8"_ustr); + CPPUNIT_ASSERT(pStyle); + + ScDBData aDBData(u"BandedCols"_ustr, 0, 0, 0, 5, 10, true, true, false); + ScTableStyleParam aStyleParam; + aStyleParam.maStyleID = u"TableStyleLight8"_ustr; + aStyleParam.mbRowStripes = false; + aStyleParam.mbColumnStripes = true; + aStyleParam.mbFirstColumn = false; + aStyleParam.mbLastColumn = false; + aDBData.SetTableStyleInfo(aStyleParam); + + // With column stripes enabled, alternating columns should have different fills + // Data row (row 1, rowIndex 0): col 0 vs col 1 should differ + const SvxBrushItem* pFillCol0 = pStyle->GetFillItem(aDBData, 0, 1, 0); + const SvxBrushItem* pFillCol1 = pStyle->GetFillItem(aDBData, 1, 1, 0); + + // At least one should have a fill for column stripes to be visible + // The two columns should have different styling (one striped, one not) + if (pFillCol0 && pFillCol1) + { + // They should differ — that's what banded columns means + CPPUNIT_ASSERT(pFillCol0->GetColor() != pFillCol1->GetColor()); + } + + m_pDoc->DeleteTab(0); +} + +// Test 11: Verify first/last column special formatting +CPPUNIT_TEST_FIXTURE(TableStylesTest, testTableStyleFirstLastColumn) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + // Use a style that has first/last column patterns + const ScTableStyle* pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + + // Range A1:D11 with first and last column enabled + ScDBData aDBData(u"FirstLastCol"_ustr, 0, 0, 0, 3, 10, true, true, true); + ScTableStyleParam aStyleParam; + aStyleParam.maStyleID = u"TableStyleMedium2"_ustr; + aStyleParam.mbRowStripes = true; + aStyleParam.mbColumnStripes = false; + aStyleParam.mbFirstColumn = true; + aStyleParam.mbLastColumn = true; + aDBData.SetTableStyleInfo(aStyleParam); + + // First column (col 0) data row should have bold font + const SfxItemSet* pFirstColFont = pStyle->GetFontItemSet(aDBData, 0, 5, 4); + if (pFirstColFont) + { + const SvxWeightItem* pWeight = pFirstColFont->GetItemIfSet(ATTR_FONT_WEIGHT, false); + if (pWeight) + CPPUNIT_ASSERT_EQUAL(WEIGHT_BOLD, pWeight->GetWeight()); + } + + // Last column (col 3) data row should also have bold font + const SfxItemSet* pLastColFont = pStyle->GetFontItemSet(aDBData, 3, 5, 4); + if (pLastColFont) + { + const SvxWeightItem* pWeight = pLastColFont->GetItemIfSet(ATTR_FONT_WEIGHT, false); + if (pWeight) + CPPUNIT_ASSERT_EQUAL(WEIGHT_BOLD, pWeight->GetWeight()); + } + + // Middle column (col 1) should NOT have bold font from first/last column + const SfxItemSet* pMidColFont = pStyle->GetFontItemSet(aDBData, 1, 5, 4); + if (pMidColFont) + { + const SvxWeightItem* pWeight = pMidColFont->GetItemIfSet(ATTR_FONT_WEIGHT, false); + if (pWeight) + CPPUNIT_ASSERT(pWeight->GetWeight() != WEIGHT_BOLD); + } + + m_pDoc->DeleteTab(0); +} + +// Test 12: Verify tiny table (single data row) doesn't crash +CPPUNIT_TEST_FIXTURE(TableStylesTest, testTableStyleTinyTable) +{ + m_pDoc->InitDrawLayer(); + m_pDoc->InsertTab(0, u"Test"_ustr); + + auto pColorSet = createTestThemeA(); + applyThemeToDocument(m_pDoc, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(*m_pDoc, *pColorSet); + + const ScTableStyle* pStyle = m_pDoc->GetTableStyles()->GetTableStyle(u"TableStyleMedium2"_ustr); + CPPUNIT_ASSERT(pStyle); + + // Tiny table: A1:B2 — header row + 1 data row, no total + ScDBData aDB1(u"Tiny1"_ustr, 0, 0, 0, 1, 1, true, true, false); + ScTableStyleParam aStyleParam; + aStyleParam.maStyleID = u"TableStyleMedium2"_ustr; + aStyleParam.mbRowStripes = true; + aStyleParam.mbColumnStripes = false; + aStyleParam.mbFirstColumn = false; + aStyleParam.mbLastColumn = false; + aDB1.SetTableStyleInfo(aStyleParam); + + // Should not crash — header row 0 + const SvxBrushItem* pFill = pStyle->GetFillItem(aDB1, 0, 0, 0); + CPPUNIT_ASSERT(pFill); // header should still have fill + const SfxItemSet* pFont = pStyle->GetFontItemSet(aDB1, 0, 0, 0); + CPPUNIT_ASSERT(pFont); + std::unique_ptr pBox = pStyle->GetBoxItem(aDB1, 0, 0, 0); + // Border may or may not exist, just verify no crash + + // Data row 1 + pStyle->GetFillItem(aDB1, 0, 1, 0); + pStyle->GetFontItemSet(aDB1, 0, 1, 0); + pStyle->GetBoxItem(aDB1, 0, 1, 0); + + // Single cell table: A1:A1 — just header, no data + ScDBData aDB2(u"Tiny2"_ustr, 0, 0, 0, 0, 0, true, true, false); + aDB2.SetTableStyleInfo(aStyleParam); + + // Should not crash + pStyle->GetFillItem(aDB2, 0, 0, 0); + pStyle->GetFontItemSet(aDB2, 0, 0, 0); + pStyle->GetBoxItem(aDB2, 0, 0, 0); + + // Header + total, no data rows: A1:B2 with total + ScDBData aDB3(u"Tiny3"_ustr, 0, 0, 0, 1, 1, true, true, true); + aDB3.SetTableStyleInfo(aStyleParam); + + // Row 0 = header, row 1 = total — no data rows + pStyle->GetFillItem(aDB3, 0, 0, 0); + pStyle->GetFillItem(aDB3, 0, 1, 0); + pStyle->GetBoxItem(aDB3, 0, 0, 0); + pStyle->GetBoxItem(aDB3, 0, 1, 0); + + m_pDoc->DeleteTab(0); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/qa/unit/uicalc/data/tdf170494.ods b/sc/qa/unit/uicalc/data/tdf170494.ods new file mode 100644 index 000000000000..54de6d0525bc Binary files /dev/null and b/sc/qa/unit/uicalc/data/tdf170494.ods differ diff --git a/sc/qa/unit/uicalc/uicalc.cxx b/sc/qa/unit/uicalc/uicalc.cxx index eb5ac64baa3c..9751610d804b 100644 --- a/sc/qa/unit/uicalc/uicalc.cxx +++ b/sc/qa/unit/uicalc/uicalc.cxx @@ -64,7 +64,7 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf142854_GridVisibilityImportXlsxInHeadl { // To avoid regression, in headless mode leave the bug tdf126541 // It means Sheet based grid line visibility setting will overwrite the global setting. - // If there is only 1 sheet in the document, it will not result visible problems. + // If there is only 1 sheet in the document, it will not result in visible problems. createScDoc("tdf126541_GridOff.xlsx"); ScDocument* pDoc = getScDoc(); CPPUNIT_ASSERT(!pDoc->GetViewOptions().GetOption(sc::ViewOption::GRID)); @@ -720,6 +720,33 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf144308) xGlobalSheetSettings->setDoAutoComplete(bOldValue); } +CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf98913_auto_complete_multi_line_strings) +{ + createScDoc(); + ScDocument* pDoc = getScDoc(); + + // Insert text into cell A1 with embedded newline + pDoc->SetString(ScAddress(0, 0, 0), u"Hello\nWorld"_ustr); + + // Activate auto complete + css::uno::Reference xGlobalSheetSettings + = css::sheet::GlobalSheetSettings::create(::comphelper::getProcessComponentContext()); + const bool bOldValue = xGlobalSheetSettings->getDoAutoComplete(); + xGlobalSheetSettings->setDoAutoComplete(true); + + // Insert the prefix of the test string without the embedded newline + insertStringToCell(u"A2"_ustr, u"Hello"); + + // Without the fix in place, this test would have failed with + // - Expected: Hello\nWorld + // - Actual : Hello + // i.e. the multi-line string was not auto-completed + CPPUNIT_ASSERT_EQUAL(u"Hello\nWorld"_ustr, pDoc->GetString(ScAddress(0, 1, 0))); + + // Restore the previous auto complete value + xGlobalSheetSettings->setDoAutoComplete(bOldValue); +} + CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testPasteWithReturnKey) { createScDoc(); @@ -889,10 +916,50 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf124820) pPattern->fillFontOnly(aFont); // Without the fix in place, this test would have failed here - CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be striked out", STRIKEOUT_SINGLE, + CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be struck out", STRIKEOUT_SINGLE, aFont.GetStrikeout()); } +CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf170494_Validity_Cell_Function) +{ + createScDoc("tdf170494.ods"); + ScDocument* pDoc = getScDoc(); + + insertStringToCell(u"A4"_ustr, u"2"); + CPPUNIT_ASSERT_EQUAL(u"1"_ustr, pDoc->GetString(ScAddress(0, 3, 0))); + + insertStringToCell(u"A4"_ustr, u"3"); + + // Without the fix in place, this test would have failed with + // - Expected: 3 + // - Actual : 1 + CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pDoc->GetString(ScAddress(0, 3, 0))); + + insertStringToCell(u"A8"_ustr, u"2"); + CPPUNIT_ASSERT_EQUAL(u"1"_ustr, pDoc->GetString(ScAddress(0, 7, 0))); + + insertStringToCell(u"A8"_ustr, u"3"); + CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pDoc->GetString(ScAddress(0, 7, 0))); + + insertStringToCell(u"A12"_ustr, u"2"); + CPPUNIT_ASSERT_EQUAL(u"1"_ustr, pDoc->GetString(ScAddress(0, 11, 0))); + + insertStringToCell(u"A12"_ustr, u"3"); + CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pDoc->GetString(ScAddress(0, 11, 0))); + + insertStringToCell(u"A16"_ustr, u"2"); + CPPUNIT_ASSERT_EQUAL(u"1"_ustr, pDoc->GetString(ScAddress(0, 15, 0))); + + insertStringToCell(u"A16"_ustr, u"3"); + CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pDoc->GetString(ScAddress(0, 15, 0))); + + insertStringToCell(u"A20"_ustr, u"2"); + CPPUNIT_ASSERT_EQUAL(u"1"_ustr, pDoc->GetString(ScAddress(0, 19, 0))); + + insertStringToCell(u"A20"_ustr, u"3"); + CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pDoc->GetString(ScAddress(0, 19, 0))); +} + CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf132026) { createScDoc("tdf132026.ods"); @@ -1457,7 +1524,7 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf122232) createScDoc("tdf122232.ods"); ScDocShell* pDocSh = getScDocShell(); - //Start with from C6. Press tabulator to reach G6. + //Start from C6. Press tabulator to reach G6. checkCurrentCursorPosition(*pDocSh, u"C6"); ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); @@ -1643,7 +1710,25 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf151752) dispatchCommand(mxComponent, u".uno:Paste"_ustr, {}); CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(0, 0, 0)); - CPPUNIT_ASSERT_EQUAL(0.0, pDoc->GetValue(1, 0, 0)); + // tdf#152327 - paste operation was silently dropped because the current sheet was deselected + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(1, 0, 0)); +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf152327_enter_data_after_select_unprotected_cells) +{ + createScDoc(); + ScDocument* pDoc = getScDoc(); + + // Select unprotected cells does not select any cells since all cells are protected by default + dispatchCommand(mxComponent, u".uno:SelectUnprotectedCells"_ustr, {}); + + insertStringToCell(u"A1"_ustr, u"1"); + + // Without the fix in place, this test would have failed with + // - Expected: 1 + // - Actual : 0 + // i.e. the current tab was cleared and the cell value was silently dropped + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(0, 0, 0)); } CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf95306) @@ -1886,7 +1971,7 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf149502_HangOnDeletingSheet1) uno::Sequence aArgs( comphelper::InitPropertySequence({ { "Index", uno::Any(sal_uInt16(0)) } })); - // Before the fix in place, this test frozen here + // Before the fix in place, this test froze here dispatchCommand(mxComponent, u".uno:Remove"_ustr, aArgs); CPPUNIT_ASSERT_EQUAL(static_cast(3), pDoc->GetTableCount()); @@ -2551,7 +2636,8 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf159174) ScModelObj* pModelObj = comphelper::getFromUnoTunnel(mxComponent); uno::Reference xPage(pModelObj->getDrawPages()->getByIndex(0), uno::UNO_QUERY_THROW); - CPPUNIT_ASSERT_EQUAL(static_cast(0), xPage->getCount()); + // tdf#152327 - paste operation was silently dropped because the current sheet was deselected + CPPUNIT_ASSERT_EQUAL(static_cast(1), xPage->getCount()); } CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testKeyboardMergeRef) diff --git a/sc/qa/unit/uicalc/uicalc2.cxx b/sc/qa/unit/uicalc/uicalc2.cxx index 38c4e0b6657f..f21aa1e882c2 100644 --- a/sc/qa/unit/uicalc/uicalc2.cxx +++ b/sc/qa/unit/uicalc/uicalc2.cxx @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -32,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -1070,7 +1073,7 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testTdf118983) xGlobalSheetSettings->setExpandReferences(true); - const ScRangeData* pRD = pDoc->GetRangeName()->findByUpperName(u"TEST"_ustr); + const ScRangeData* pRD = pDoc->GetRangeName().findByUpperName(u"TEST"_ustr); CPPUNIT_ASSERT(pRD); CPPUNIT_ASSERT_EQUAL(u"$Test.$A$3:$D$7"_ustr, pRD->GetSymbol()); @@ -1182,27 +1185,38 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testTdf99386) CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testTdf149378) { + // An array-returning formula lands as a dynamic-array master with no + // {} wrapping in the formula text. + createScDoc(); ScDocument* pDoc = getScDoc(); - insertStringToCell(u"A1"_ustr, u"=MINVERSE(A1:C3)"); + auto checkDynamic = [pDoc](SCCOL nCol, SCROW nRow) { + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(nCol, nRow, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pCell->GetMatrixFlag()); + }; - // Without the fix in place, this test would have failed with - // - Expected: {=MINVERSE(A1:C3)} - // - Actual : =MINVERSE(A1:C3) - CPPUNIT_ASSERT_EQUAL(u"{=MINVERSE(A1:C3)}"_ustr, pDoc->GetFormula(0, 0, 0)); + insertStringToCell(u"A1"_ustr, u"=MINVERSE(A1:C3)"); + CPPUNIT_ASSERT_EQUAL(u"=MINVERSE(A1:C3)"_ustr, pDoc->GetFormula(0, 0, 0)); + checkDynamic(0, 0); insertStringToCell(u"B1"_ustr, u"={1;2}"); - CPPUNIT_ASSERT_EQUAL(u"{={1;2}}"_ustr, pDoc->GetFormula(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"={1;2}"_ustr, pDoc->GetFormula(1, 0, 0)); + checkDynamic(1, 0); insertStringToCell(u"C1"_ustr, u"={1;2}+3"); - CPPUNIT_ASSERT_EQUAL(u"{={1;2}+3}"_ustr, pDoc->GetFormula(2, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"={1;2}+3"_ustr, pDoc->GetFormula(2, 0, 0)); + checkDynamic(2, 0); insertStringToCell(u"D1"_ustr, u"={1;2}+{3;4}"); - CPPUNIT_ASSERT_EQUAL(u"{={1;2}+{3;4}}"_ustr, pDoc->GetFormula(3, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"={1;2}+{3;4}"_ustr, pDoc->GetFormula(3, 0, 0)); + checkDynamic(3, 0); insertStringToCell(u"E1"_ustr, u"={1;2}+A1"); - CPPUNIT_ASSERT_EQUAL(u"{={1;2}+A1}"_ustr, pDoc->GetFormula(4, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"={1;2}+A1"_ustr, pDoc->GetFormula(4, 0, 0)); + checkDynamic(4, 0); insertStringToCell(u"F1"_ustr, u"={1;2}+A1:A2"); CPPUNIT_ASSERT_EQUAL(u"={1;2}+A1:A2"_ustr, pDoc->GetFormula(5, 0, 0)); @@ -1214,7 +1228,215 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testTdf149378) CPPUNIT_ASSERT_EQUAL(u"=SUM({1;2})"_ustr, pDoc->GetFormula(7, 0, 0)); insertStringToCell(u"I1"_ustr, u"=ABS({-1;-2})"); - CPPUNIT_ASSERT_EQUAL(u"{=ABS({-1;-2})}"_ustr, pDoc->GetFormula(8, 0, 0)); + CPPUNIT_ASSERT_EQUAL(u"=ABS({-1;-2})"_ustr, pDoc->GetFormula(8, 0, 0)); + checkDynamic(8, 0); + + insertStringToCell(u"J1"_ustr, u"=A1:A2"); + CPPUNIT_ASSERT_EQUAL(u"=A1:A2"_ustr, pDoc->GetFormula(9, 0, 0)); + checkDynamic(9, 0); +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testBinaryRangeAdditionSpills) +{ + // Typing =A2:A5+B2:B5 without Ctrl+Shift+Enter should make the cell a + // dynamic-array master and spill the result into C1:C4. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + insertStringToCell(u"A2"_ustr, u"1"); + insertStringToCell(u"A3"_ustr, u"2"); + insertStringToCell(u"A4"_ustr, u"3"); + insertStringToCell(u"A5"_ustr, u"4"); + insertStringToCell(u"B2"_ustr, u"10"); + insertStringToCell(u"B3"_ustr, u"20"); + insertStringToCell(u"B4"_ustr, u"30"); + insertStringToCell(u"B5"_ustr, u"40"); + + insertStringToCell(u"C1"_ustr, u"=A2:A5+B2:B5"); + + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(2, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pCell->GetMatrixFlag()); + + SCCOL nCols = 0; + SCROW nRows = 0; + pCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(4), nRows); + + CPPUNIT_ASSERT_EQUAL(11.0, pDoc->GetValue(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(22.0, pDoc->GetValue(ScAddress(2, 1, 0))); + CPPUNIT_ASSERT_EQUAL(33.0, pDoc->GetValue(ScAddress(2, 2, 0))); + CPPUNIT_ASSERT_EQUAL(44.0, pDoc->GetValue(ScAddress(2, 3, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testChainedRangeAdditionSpills) +{ + // A chain of binary additions over the same multi-cell range spills, + // even when the cell sits inside the source row span. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + insertStringToCell(u"A1"_ustr, u"1"); + insertStringToCell(u"A2"_ustr, u"2"); + insertStringToCell(u"A3"_ustr, u"3"); + insertStringToCell(u"A4"_ustr, u"4"); + + insertStringToCell(u"D2"_ustr, u"=A1:A4 + A1:A4 + A1:A4 + A1:A4 + A1:A4"); + + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(3, 1, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pCell->GetMatrixFlag()); + + SCCOL nCols = 0; + SCROW nRows = 0; + pCell->GetMatColsRows(nCols, nRows); + CPPUNIT_ASSERT_EQUAL(SCCOL(1), nCols); + CPPUNIT_ASSERT_EQUAL(SCROW(4), nRows); + + CPPUNIT_ASSERT_EQUAL(5.0, pDoc->GetValue(ScAddress(3, 1, 0))); + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(3, 2, 0))); + CPPUNIT_ASSERT_EQUAL(15.0, pDoc->GetValue(ScAddress(3, 3, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDoc->GetValue(ScAddress(3, 4, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testIfWithRangeBranchesSpills) +{ + // An IF whose true and false branches are multi-cell ranges has + // an array-shaped result. The cell promotes to a dynamic-array + // master and spills the chosen branch. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + insertStringToCell(u"A1"_ustr, u"1"); + insertStringToCell(u"B1"_ustr, u"10"); + insertStringToCell(u"B2"_ustr, u"20"); + insertStringToCell(u"B3"_ustr, u"30"); + insertStringToCell(u"B4"_ustr, u"40"); + insertStringToCell(u"C1"_ustr, u"100"); + insertStringToCell(u"C2"_ustr, u"200"); + insertStringToCell(u"C3"_ustr, u"300"); + insertStringToCell(u"C4"_ustr, u"400"); + + insertStringToCell(u"D1"_ustr, u"=IF(A1>0,B1:B4,C1:C4)"); + + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(3, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pCell->GetMatrixFlag()); + + // A1 is 1 so the true branch wins. The B column spills into D1:D4. + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(3, 0, 0))); + CPPUNIT_ASSERT_EQUAL(20.0, pDoc->GetValue(ScAddress(3, 1, 0))); + CPPUNIT_ASSERT_EQUAL(30.0, pDoc->GetValue(ScAddress(3, 2, 0))); + CPPUNIT_ASSERT_EQUAL(40.0, pDoc->GetValue(ScAddress(3, 3, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testRangeTimesScalarSpills) +{ + // A binary op other than addition still triggers the array-intent + // walk. The cell sits at B2 inside the row span of A1:A4 so the + // compile-time implicit-intersection skip is exercised as well. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + insertStringToCell(u"A1"_ustr, u"1"); + insertStringToCell(u"A2"_ustr, u"2"); + insertStringToCell(u"A3"_ustr, u"3"); + insertStringToCell(u"A4"_ustr, u"4"); + + insertStringToCell(u"B2"_ustr, u"=A1:A4*2"); + + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(1, 1, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pCell->GetMatrixFlag()); + + CPPUNIT_ASSERT_EQUAL(2.0, pDoc->GetValue(ScAddress(1, 1, 0))); + CPPUNIT_ASSERT_EQUAL(4.0, pDoc->GetValue(ScAddress(1, 2, 0))); + CPPUNIT_ASSERT_EQUAL(6.0, pDoc->GetValue(ScAddress(1, 3, 0))); + CPPUNIT_ASSERT_EQUAL(8.0, pDoc->GetValue(ScAddress(1, 4, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testSumOfRangeStaysScalar) +{ + // A function that reduces an array to a scalar must not promote + // its cell, even when the argument is a multi-cell range. The walk + // pops the range push, recognises SUM as a non-array-returning + // function, and leaves a scalar on the stack. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + insertStringToCell(u"A1"_ustr, u"1"); + insertStringToCell(u"A2"_ustr, u"2"); + insertStringToCell(u"A3"_ustr, u"3"); + insertStringToCell(u"A4"_ustr, u"4"); + + insertStringToCell(u"B1"_ustr, u"=SUM(A1:A4)"); + + ScFormulaCell* pCell = pDoc->GetFormulaCell(ScAddress(1, 0, 0)); + CPPUNIT_ASSERT(pCell); + CPPUNIT_ASSERT(!pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::NONE, pCell->GetMatrixFlag()); + + CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(1, 0, 0))); +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testAtOperatorOnOperandsControlsSpill) +{ + // @ on every operand keeps the cell scalar. @ on only one still + // lets the other spill. + + createScDoc(); + ScDocument* pDoc = getScDoc(); + + insertStringToCell(u"A1"_ustr, u"1"); + insertStringToCell(u"A2"_ustr, u"2"); + insertStringToCell(u"A3"_ustr, u"3"); + insertStringToCell(u"A4"_ustr, u"4"); + insertStringToCell(u"B1"_ustr, u"10"); + insertStringToCell(u"B2"_ustr, u"20"); + insertStringToCell(u"B3"_ustr, u"30"); + insertStringToCell(u"B4"_ustr, u"40"); + + // @ on both operands keeps the result scalar. + insertStringToCell(u"C1"_ustr, u"=@A1:A4 + @B1:B4"); + ScFormulaCell* pBoth = pDoc->GetFormulaCell(ScAddress(2, 0, 0)); + CPPUNIT_ASSERT(pBoth); + CPPUNIT_ASSERT(!pBoth->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::NONE, pBoth->GetMatrixFlag()); + CPPUNIT_ASSERT_EQUAL(11.0, pDoc->GetValue(ScAddress(2, 0, 0))); + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, pDoc->GetCellType(ScAddress(2, 1, 0))); + + // @ on the first operand only. The second operand stays a range, + // so the binary + still produces an array result. + insertStringToCell(u"D1"_ustr, u"=@A1:A4 + B1:B4"); + ScFormulaCell* pFirst = pDoc->GetFormulaCell(ScAddress(3, 0, 0)); + CPPUNIT_ASSERT(pFirst); + CPPUNIT_ASSERT(pFirst->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pFirst->GetMatrixFlag()); + CPPUNIT_ASSERT_EQUAL(11.0, pDoc->GetValue(ScAddress(3, 0, 0))); + CPPUNIT_ASSERT_EQUAL(21.0, pDoc->GetValue(ScAddress(3, 1, 0))); + CPPUNIT_ASSERT_EQUAL(31.0, pDoc->GetValue(ScAddress(3, 2, 0))); + CPPUNIT_ASSERT_EQUAL(41.0, pDoc->GetValue(ScAddress(3, 3, 0))); + + // @ on the second operand only. Same outcome. + insertStringToCell(u"E1"_ustr, u"=A1:A4 + @B1:B4"); + ScFormulaCell* pSecond = pDoc->GetFormulaCell(ScAddress(4, 0, 0)); + CPPUNIT_ASSERT(pSecond); + CPPUNIT_ASSERT(pSecond->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(ScMatrixMode::Formula, pSecond->GetMatrixFlag()); + CPPUNIT_ASSERT_EQUAL(11.0, pDoc->GetValue(ScAddress(4, 0, 0))); + CPPUNIT_ASSERT_EQUAL(12.0, pDoc->GetValue(ScAddress(4, 1, 0))); + CPPUNIT_ASSERT_EQUAL(13.0, pDoc->GetValue(ScAddress(4, 2, 0))); + CPPUNIT_ASSERT_EQUAL(14.0, pDoc->GetValue(ScAddress(4, 3, 0))); } CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testTdf152014) @@ -1289,6 +1511,47 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testTdf126926) CPPUNIT_ASSERT(pDBs->empty()); } +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testCrossDocCutPasteTableUndoable) +{ + // Cutting a named table from one document and pasting it into another that + // has no database ranges adds a range to the destination. Undoing the paste + // must drop it again rather than leave it orphaned over the now-empty cells. + createScDoc(); + ScDocument* pDoc = getScDoc(); + + insertStringToCell(u"A1"_ustr, u"a"); + insertStringToCell(u"B1"_ustr, u"b"); + insertStringToCell(u"A2"_ustr, u"c"); + insertStringToCell(u"B2"_ustr, u"d"); + + // A named table over A1:B2. + ScDBData* pDBData = new ScDBData(u"MyTable"_ustr, 0, 0, 0, 1, 1, true, true); + CPPUNIT_ASSERT( + pDoc->GetDBCollection()->getNamedDBs().insert(std::unique_ptr(pDBData))); + + // Cut the whole table. + goToCell(u"A1:B2"_ustr); + dispatchCommand(mxComponent, u".uno:Cut"_ustr, {}); + + // A second, empty document that owns no database ranges. + mxComponent2 = loadFromDesktop(u"private:factory/scalc"_ustr); + ScModelObj* pModelObj2 = comphelper::getFromUnoTunnel(mxComponent2); + CPPUNIT_ASSERT(pModelObj2); + ScDocument* pDoc2 = pModelObj2->GetDocument(); + CPPUNIT_ASSERT(pDoc2->GetDBCollection()->getNamedDBs().empty()); + + // Pasting into the second document recreates MyTable there. + dispatchCommand(mxComponent2, u".uno:Paste"_ustr, {}); + CPPUNIT_ASSERT_MESSAGE( + "paste should have recreated the table in the destination", + pDoc2->GetDBCollection()->getNamedDBs().findByUpperName(u"MYTABLE"_ustr)); + + // Undo must drop the range the paste added. + dispatchCommand(mxComponent2, u".uno:Undo"_ustr, {}); + CPPUNIT_ASSERT_MESSAGE("undo of a cut-paste must drop the table it added", + pDoc2->GetDBCollection()->getNamedDBs().empty()); +} + CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testUnallocatedColumnsAttributes) { createScDoc(); @@ -2207,6 +2470,131 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testTdf166791_PasteArrayOriginCellRefShiftin pMod->SetInputOptions(aInputOption); } +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testTdf107994_MoveActiveCellToFreezePaneSplitterPos) +{ + createScDoc(); + ScDocShell* pDocSh = getScDocShell(); + + // Verify the default GoToStart behavior without frozen panes + goToCell(u"D5"_ustr); + dispatchCommand(mxComponent, u".uno:GoToStart"_ustr, {}); + checkCurrentCursorPosition(*pDocSh, u"A1"); + + // Freeze panes at C3 and verify that GoToStart moves to the freeze pane splitter position + goToCell(u"C3"_ustr); + dispatchCommand(mxComponent, u".uno:FreezePanes"_ustr, {}); + goToCell(u"D5"_ustr); + dispatchCommand(mxComponent, u".uno:GoToStart"_ustr, {}); + + // Without the fix in place, this test would have failed with + // - Expected: C3 + // - Actual : A1 + // i.e. the active cell was not moved to the freeze pane splitter position + checkCurrentCursorPosition(*pDocSh, u"C3"); + + // Unfreeze panes and verify the GoToStart default behaviour again + dispatchCommand(mxComponent, u".uno:FreezePanes"_ustr, {}); + dispatchCommand(mxComponent, u".uno:GoToStart"_ustr, {}); + checkCurrentCursorPosition(*pDocSh, u"A1"); +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testSpillMatrixContractionOnPaste) +{ + createScDoc(); + ScDocument* pDoc = getScDoc(); + + // B2:B15: four distinct values -> UNIQUE() fills the 4-row matrix below. + const double aB[] = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 4, 4, 4 }; + for (size_t i = 0; i < SAL_N_ELEMENTS(aB); ++i) + pDoc->SetValue(1, 1 + static_cast(i), 0, aB[i]); // B2..B15 + + // D2:D15: only two distinct values - the shifted reference lands here. + for (SCROW nR = 1; nR <= 14; ++nR) + pDoc->SetValue(3, nR, 0, nR <= 7 ? 7.0 : 8.0); // D2..D15 + + insertArrayToCell(u"E2:E5"_ustr, u"=UNIQUE(B$2:B$15)", /*bDynamicArrayMaster*/ true); + // Dynamic-array masters read back without the {} wrapping that + // static Ctrl+Shift+Enter masters use. + CPPUNIT_ASSERT_EQUAL(u"=UNIQUE(B$2:B$15)"_ustr, pDoc->GetFormula(4, 1, 0)); // E2 + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(ScAddress(4, 1, 0))); // E2 + CPPUNIT_ASSERT_EQUAL(4.0, pDoc->GetValue(ScAddress(4, 4, 0))); // E5 + + // Paste origin E2 to G2: the reference shifts B -> D, UNIQUE(D$2:D$15) has + // two results, so the 4-row matrix contracts to 2 rows. + goToCell(u"E2"_ustr); + dispatchCommand(mxComponent, u".uno:Copy"_ustr, {}); + goToCell(u"G2"_ustr); + dispatchCommand(mxComponent, u".uno:Paste"_ustr, {}); + + CPPUNIT_ASSERT_EQUAL(u"=UNIQUE(D$2:D$15)"_ustr, pDoc->GetFormula(6, 1, 0)); // G2 + CPPUNIT_ASSERT_EQUAL(7.0, pDoc->GetValue(ScAddress(6, 1, 0))); // G2 + CPPUNIT_ASSERT_EQUAL(8.0, pDoc->GetValue(ScAddress(6, 2, 0))); // G3 + // G4:G5 are outside the now 2-row matrix, so they are empty. + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, pDoc->GetCellType(ScAddress(6, 3, 0))); // G4 + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, pDoc->GetCellType(ScAddress(6, 4, 0))); // G5 +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testSpillMatrixContractionOnEdit) +{ + createScDoc(); + ScDocument* pDoc = getScDoc(); + + // B2:B15: four distinct values {1,2,3,4}; the only '3' sits in B11. + const double aB[] = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 4, 4, 4 }; + for (size_t i = 0; i < SAL_N_ELEMENTS(aB); ++i) + pDoc->SetValue(1, 1 + static_cast(i), 0, aB[i]); // B2..B15 + + insertArrayToCell(u"D2:D5"_ustr, u"=UNIQUE(B$2:B$15)", /*bDynamicArrayMaster*/ true); + CPPUNIT_ASSERT_EQUAL(u"=UNIQUE(B$2:B$15)"_ustr, pDoc->GetFormula(3, 1, 0)); // D2 + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(ScAddress(3, 1, 0))); // D2 + CPPUNIT_ASSERT_EQUAL(2.0, pDoc->GetValue(ScAddress(3, 2, 0))); // D3 + CPPUNIT_ASSERT_EQUAL(3.0, pDoc->GetValue(ScAddress(3, 3, 0))); // D4 + CPPUNIT_ASSERT_EQUAL(4.0, pDoc->GetValue(ScAddress(3, 4, 0))); // D5 + + // Type '2' over B11: UNIQUE now has {1,2,4}, so the matrix shrinks 4 -> 3. + insertStringToCell(u"B11"_ustr, u"2"); + + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(ScAddress(3, 1, 0))); // D2 + CPPUNIT_ASSERT_EQUAL(2.0, pDoc->GetValue(ScAddress(3, 2, 0))); // D3 + CPPUNIT_ASSERT_EQUAL(4.0, pDoc->GetValue(ScAddress(3, 3, 0))); // D4 + CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, pDoc->GetCellType(ScAddress(3, 4, 0))); // D5 cleared +} + +CPPUNIT_TEST_FIXTURE(ScUiCalcTest2, testSetHyperlinkKeepSelection) +{ + // Given a Calc doc with "foo" in cell A1 and the cell cursor on A1: + createScDoc(); + ScDocument* pDoc = getScDoc(); + pDoc->SetString(ScAddress(0, 0, 0), u"foo"_ustr); + goToCell(u"A1"_ustr); + + // When dispatching .uno:SetHyperlink with Hyperlink.Text differing from the cell content, + // but marked as a hint: + uno::Sequence aArgs = { + comphelper::makePropertyValue(u"Hyperlink.Text"_ustr, uno::Any(u"mytext"_ustr)), + comphelper::makePropertyValue(u"Hyperlink.TextIsHint"_ustr, uno::Any(true)), + comphelper::makePropertyValue(u"Hyperlink.URL"_ustr, + uno::Any(u"http://www.example.com"_ustr)), + }; + dispatchCommand(mxComponent, u".uno:SetHyperlink"_ustr, aArgs); + + // Commit the input mode that InsertURLField left the cell in. + ScModule::get()->InputEnterHandler(); + + // Then make sure the cell's existing content is preserved as the URL field's + // displayed text, not replaced by Hyperlink.Text: + const EditTextObject* pEditText = pDoc->GetEditText(ScAddress(0, 0, 0)); + CPPUNIT_ASSERT(pEditText); + const SvxFieldData* pField = pEditText->GetFieldData(0, 0, css::text::textfield::Type::URL); + auto pURLField = dynamic_cast(pField); + CPPUNIT_ASSERT(pURLField); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: foo + // - Actual : mytext + // i.e. the cell content was lost, the provided text hint was used. + CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, pURLField->GetRepresentation()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/res/xml/tablestyles.xml b/sc/res/xml/tablestyles.xml index e3926532180f..e359fc3c8db7 100644 --- a/sc/res/xml/tablestyles.xml +++ b/sc/res/xml/tablestyles.xml @@ -88,7 +88,7 @@ - + @@ -168,7 +168,7 @@ - + @@ -248,7 +248,7 @@ - + @@ -328,7 +328,7 @@ - + @@ -408,7 +408,7 @@ - + @@ -488,7 +488,7 @@ - + @@ -568,7 +568,7 @@ - + @@ -648,7 +648,7 @@ - + @@ -728,7 +728,7 @@ - + @@ -808,7 +808,7 @@ - + diff --git a/sc/sdi/app.sdi b/sc/sdi/app.sdi index cae5e5d95afa..9e36fa54e165 100644 --- a/sc/sdi/app.sdi +++ b/sc/sdi/app.sdi @@ -48,8 +48,6 @@ interface StarCalc ] SID_CHOOSE_DESIGN [ ExecMethod = Execute; ] - SID_EURO_CONVERTER [ ExecMethod = Execute; ] - SID_OPEN_XML_FILTERSETTINGS [ ExecMethod = Execute; ] diff --git a/sc/sdi/cellsh.sdi b/sc/sdi/cellsh.sdi index 0791b88617d2..8be4fbf526f9 100644 --- a/sc/sdi/cellsh.sdi +++ b/sc/sdi/cellsh.sdi @@ -246,6 +246,8 @@ interface CellSelection FID_SHOW_ALL_NOTES [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] FID_DELETE_ALL_NOTES [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] SID_DELETE_NOTE [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] + SID_INSERT_THREADED_COMMENT [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] + SID_RESOLVE_THREADED_COMMENT [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] SID_DEC_INDENT [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] SID_INC_INDENT [ ExecMethod = ExecuteEdit; StateMethod = GetState; ] SID_SELECT_UNPROTECTED_CELLS [ ExecMethod = ExecuteEdit;] diff --git a/sc/sdi/docsh.sdi b/sc/sdi/docsh.sdi index dd8bbfc7f361..6447e1cf5e9b 100644 --- a/sc/sdi/docsh.sdi +++ b/sc/sdi/docsh.sdi @@ -53,6 +53,7 @@ interface TableDocument SID_SBA_IMPORT [ ExecMethod = Execute; StateMethod = GetState; ] SID_SC_SETTEXT [ ExecMethod = Execute; StateMethod = GetState; ] SID_TABLES_COUNT [ StateMethod = GetState; ] + SID_TABLE_STYLES [ StateMethod = GetState; ] SID_ATTR_YEAR2000 [ StateMethod = GetState; ExecMethod = Execute; ] SID_CHART_SOURCE [ ExecMethod = Execute; ] SID_CHART_ADDSOURCE [ ExecMethod = Execute; ] diff --git a/sc/sdi/prevwsh.sdi b/sc/sdi/prevwsh.sdi index 58cba8eaf47a..3c237c3446cf 100644 --- a/sc/sdi/prevwsh.sdi +++ b/sc/sdi/prevwsh.sdi @@ -129,6 +129,11 @@ interface TablePrintPreview SID_PREVIEW_CLOSE [ ExecMethod = Execute; StateMethod = GetState; ] SID_CANCEL [ ExecMethod = Execute; StateMethod = GetState; ] + SID_TOGGLEPRINTGRID [ ExecMethod = Execute; StateMethod = GetState; ] + SID_TOGGLEPRINTCOLROWHEADER [ ExecMethod = Execute; StateMethod = GetState; ] + SID_TOGGLEPRINTCOMMENTS [ ExecMethod = Execute; StateMethod = GetState; ] + SID_TOGGLEPRINTZEROVALUES [ ExecMethod = Execute; StateMethod = GetState; ] + SID_SAVEDOC [ StateMethod = GetState; ] SID_SAVEASDOC [ StateMethod = GetState; ] SID_MAIL_SENDDOC [ StateMethod = GetState; ] diff --git a/sc/sdi/scalc.sdi b/sc/sdi/scalc.sdi index c91a51522d26..53fd8374050a 100644 --- a/sc/sdi/scalc.sdi +++ b/sc/sdi/scalc.sdi @@ -745,9 +745,9 @@ SfxVoidItem ConditionalFormatEasy SID_EASY_CONDITIONAL_FORMAT_DIALOG RecordAbsolute = FALSE, RecordPerSet; - AccelConfig = TRUE, - MenuConfig = TRUE, - ToolBoxConfig = TRUE, + AccelConfig = FALSE, + MenuConfig = FALSE, + ToolBoxConfig = FALSE, GroupId = SfxGroupId::Format; ] @@ -1643,26 +1643,6 @@ SfxVoidItem EditScenario SID_EDIT_SCENARIO GroupId = SfxGroupId::Intern; ] - -SfxVoidItem EuroConverter SID_EURO_CONVERTER -() -[ - AutoUpdate = FALSE, - FastCall = FALSE, - ReadOnlyDoc = FALSE, - Toggle = FALSE, - Container = FALSE, - RecordAbsolute = FALSE, - RecordPerSet; - Asynchron; - - AccelConfig = TRUE, - MenuConfig = TRUE, - ToolBoxConfig = TRUE, - GroupId = SfxGroupId::Format; -] - - SfxVoidItem FillDown FID_FILL_TO_BOTTOM () [ @@ -2511,7 +2491,7 @@ SfxVoidItem SearchResultsDialog SID_SEARCH_RESULTS_DIALOG (SfxBoolItem Visible SID_SEARCH_RESULTS_DIALOG) [ AutoUpdate = FALSE, - FastCall = FALSE, + FastCall = TRUE, ReadOnlyDoc = TRUE, Toggle = FALSE, Container = FALSE, @@ -3868,6 +3848,41 @@ SfxVoidItem DeleteNote SID_DELETE_NOTE ] +SfxVoidItem InsertThreadedComment SID_INSERT_THREADED_COMMENT +(SvxPostItAuthorItem Author SID_ATTR_POSTIT_AUTHOR, + SvxPostItTextItem Text SID_ATTR_POSTIT_TEXT) +[ + AutoUpdate = FALSE, + FastCall = TRUE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = TRUE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Edit; +] + +SfxVoidItem ResolveComment SID_RESOLVE_THREADED_COMMENT +(SvxPostItIdItem Id SID_ATTR_POSTIT_ID) +[ + AutoUpdate = FALSE, + FastCall = TRUE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = FALSE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Edit; +] + SfxStringItem NumberFormat SID_NUMBER_FORMAT [ @@ -6103,23 +6118,6 @@ SfxBoolItem ToggleFormula FID_TOGGLEFORMULA GroupId = SfxGroupId::View ] -SfxInt32Item CurrentSheetVIew FID_CURRENT_SHEET_VIEW -[ - AutoUpdate = FALSE, - FastCall = FALSE, - ReadOnlyDoc = TRUE, - Toggle = FALSE, - Container = FALSE, - RecordAbsolute = FALSE, - RecordPerSet; - - - AccelConfig = FALSE, - MenuConfig = FALSE, - ToolBoxConfig = TRUE, - GroupId = SfxGroupId::Format; -] - SfxBoolItem NewSheetView FID_NEW_SHEET_VIEW [ /* flags */ @@ -6156,47 +6154,12 @@ SfxBoolItem RemoveSheetView FID_REMOVE_SHEET_VIEW GroupId = SfxGroupId::View ] -SfxBoolItem SwitchToNextSheetView FID_SWITCH_TO_NEXT_SHEET_VIEW +SfxVoidItem SelectSheetView FID_SELECT_SHEET_VIEW +(SfxInt32Item SheetViewID FN_PARAM_1) [ /* flags */ AutoUpdate = FALSE, - FastCall = FALSE, - ReadOnlyDoc = TRUE, - Toggle = FALSE, - Container = FALSE, - RecordAbsolute = FALSE, - RecordPerSet; - - /* config */ - AccelConfig = TRUE, - MenuConfig = FALSE, - ToolBoxConfig = FALSE, - GroupId = SfxGroupId::View -] - -SfxBoolItem SwitchToPreviousSheetView FID_SWITCH_TO_PREVIOUS_SHEET_VIEW -[ - /* flags */ - AutoUpdate = FALSE, - FastCall = FALSE, - ReadOnlyDoc = TRUE, - Toggle = FALSE, - Container = FALSE, - RecordAbsolute = FALSE, - RecordPerSet; - - /* config */ - AccelConfig = TRUE, - MenuConfig = FALSE, - ToolBoxConfig = FALSE, - GroupId = SfxGroupId::View -] - -SfxBoolItem SelectSheetView FID_SELECT_SHEET_VIEW -[ - /* flags */ - AutoUpdate = FALSE, - FastCall = FALSE, + FastCall = TRUE, ReadOnlyDoc = TRUE, Toggle = FALSE, Container = FALSE, @@ -6493,6 +6456,24 @@ SfxBoolItem CellProtection SID_SCATTR_CELLPROTECTION GroupId = SfxGroupId::Format; ] +SfxStringItem TableStyles SID_TABLE_STYLES + +[ + AutoUpdate = FALSE, + FastCall = TRUE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = FALSE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Document; +] + + ScDatabaseSettingItem DatabaseSettings SID_DATABASE_SETTINGS [ @@ -6655,9 +6636,9 @@ SvxSizeItem CalcPageMargin SID_SC_ATTR_PAGE_MARGIN RecordAbsolute = FALSE, RecordPerSet; - AccelConfig = TRUE, - MenuConfig = TRUE, - ToolBoxConfig = TRUE, + AccelConfig = FALSE, + MenuConfig = FALSE, + ToolBoxConfig = FALSE, GroupId = SfxGroupId::Format; ] @@ -6675,9 +6656,9 @@ SvxSizeItem CalcPageSize SID_SC_ATTR_PAGE_SIZE RecordAbsolute = FALSE, RecordPerSet; - AccelConfig = TRUE, - MenuConfig = TRUE, - ToolBoxConfig = TRUE, + AccelConfig = FALSE, + MenuConfig = FALSE, + ToolBoxConfig = FALSE, GroupId = SfxGroupId::Format; ] @@ -7027,3 +7008,71 @@ SfxVoidItem CopyDelete SID_COPYDELETE ToolBoxConfig = TRUE, GroupId = SfxGroupId::Edit; ] + +SfxBoolItem TogglePrintGrid SID_TOGGLEPRINTGRID +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::View; +] + +SfxBoolItem TogglePrintColRowHeader SID_TOGGLEPRINTCOLROWHEADER +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::View; +] + +SfxBoolItem TogglePrintComments SID_TOGGLEPRINTCOMMENTS +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::View; +] + +SfxBoolItem TogglePrintZeroValues SID_TOGGLEPRINTZEROVALUES +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::View; +] diff --git a/sc/sdi/tabvwsh.sdi b/sc/sdi/tabvwsh.sdi index 8700efcd5b8b..c211e9300e43 100644 --- a/sc/sdi/tabvwsh.sdi +++ b/sc/sdi/tabvwsh.sdi @@ -209,11 +209,8 @@ interface TableEditView FID_TOGGLEFORMULA [ ExecMethod = Execute; StateMethod = GetState; ] FID_NEW_SHEET_VIEW [ ExecMethod = Execute; StateMethod = GetState; ] FID_REMOVE_SHEET_VIEW [ ExecMethod = Execute; StateMethod = GetState; ] - FID_SWITCH_TO_NEXT_SHEET_VIEW [ ExecMethod = Execute; StateMethod = GetState; ] - FID_SWITCH_TO_PREVIOUS_SHEET_VIEW [ ExecMethod = Execute; StateMethod = GetState; ] FID_EXIT_SHEET_VIEW [ ExecMethod = Execute; StateMethod = GetState; ] FID_SELECT_SHEET_VIEW [ ExecMethod = Execute; StateMethod = GetState; ] - FID_CURRENT_SHEET_VIEW [ ExecMethod = Execute; StateMethod = GetState; ] FID_NORMALVIEWMODE [ ExecMethod = Execute; StateMethod = GetState; ] FID_PAGEBREAKMODE [ ExecMethod = Execute; StateMethod = GetState; ] SID_REPAINT [ ExecMethod = Execute; StateMethod = GetState; ] diff --git a/sc/source/core/data/PivotTableFormatOutput.cxx b/sc/source/core/data/PivotTableFormatOutput.cxx index ac7215a2ec5b..fb6f554bcc3f 100644 --- a/sc/source/core/data/PivotTableFormatOutput.cxx +++ b/sc/source/core/data/PivotTableFormatOutput.cxx @@ -8,10 +8,12 @@ */ #include +#include #include #include #include +#include #include #include #include @@ -25,6 +27,7 @@ namespace class NameResolver { private: + ScDPObject& mrObject; ScDPCache const& mrCache; std::unordered_map> maNameCache; @@ -45,6 +48,17 @@ private: void fillNamesForDimension(std::vector& rNames, sal_Int32 nDimension) { + // Try to get member names in pivot field order first. + // This matches the order used by the pivot table output. + std::vector aMembers; + if (mrObject.GetMembers(nDimension, 0, aMembers) && !aMembers.empty()) + { + for (const auto& rMember : aMembers) + rNames.push_back(rMember.maName); + return; + } + + // Fallback to cache order if (mrCache.IsValidDimensionIndex(nDimension)) { fillNamesForItems(rNames, mrCache.GetDimMemberValues(nDimension), nDimension); @@ -60,8 +74,9 @@ private: } public: - NameResolver(ScDPCache const& rCache) - : mrCache(rCache) + NameResolver(ScDPObject& rObject, ScDPCache const& rCache) + : mrObject(rObject) + , mrCache(rCache) { } @@ -127,6 +142,8 @@ void fillOutputFieldFromSelection(FormatOutputField& rOutputField, Selection con rOutputField.aName = rNameResolver.getNameForIndex(rOutputField.nIndex, rOutputField.nDimension); } + rOutputField.bSelected = rSelection.bSelected; + rOutputField.bHasSubtotal = rSelection.bHasSubtotal; rOutputField.bSet = true; } @@ -179,7 +196,7 @@ void FormatOutput::prepare(SCTAB nTab, std::vector const& rCol ScDPFilteredCache const& rFilteredCache = pTableData->GetCacheTable(); ScDPCache const& rCache = rFilteredCache.getCache(); - NameResolver aNameResolver(rCache); + NameResolver aNameResolver(mrObject, rCache); // Initialize format output entries (FormatOutputEntry) and set the data already available from output fields // (rColumnFields and rRowFields) and the pivot table format list (PivotTableFormat). @@ -199,6 +216,9 @@ void FormatOutput::prepare(SCTAB nTab, std::vector const& rCol aEntry.pPattern = rFormat.pPattern; aEntry.onTab = nTab; aEntry.eType = rFormat.eType; + aEntry.bGrandRow = rFormat.bGrandRow; + aEntry.bGrandColumn = rFormat.bGrandColumn; + aEntry.oOffset = rFormat.oOffset; initFormatOutputField(nSelectionIndex, aEntry.aRowOutputFields, rRowFields, rFormat, aNameResolver); @@ -298,163 +318,442 @@ void FormatOutput::insertFieldMember(size_t nFieldIndex, ScDPOutLevelData const& } namespace { -void checkForMatchingLines(std::vector const& rLines, - std::vector const& rFormatOutputField, - FormatType eType, - std::vector>& rMatches, - std::vector>& rMaybeMatches) +/** Find lines matching the format's field criteria. + * + * For labels: unreferenced fields must have a member/continuation. + * For data: exact matches take priority over broad matches. Falls back to broad if no exact. + */ +void findMatchingLines(std::vector const& rLines, + std::vector const& rFormatOutputField, FormatType eType, + std::vector>& rMatches) { + std::vector> aBroadMatches; + for (LineData const& rLineData : rLines) { - size_t nMatch = 0; - size_t nMaybeMatch = 0; size_t nNoOfFields = rLineData.maFields.size(); - - for (size_t nIndex = 0; nIndex < nNoOfFields; nIndex++) + bool bAllMatch = true; + bool bHasWildcardMember = false; + bool bHasSubtotalMatch = false; + // Check dimension alignment and referenced fields. + // Track whether any referenced field matched as a subtotal. + for (size_t nIndex = 0; nIndex < nNoOfFields && bAllMatch; nIndex++) { FieldData const& rFieldData = rLineData.maFields[nIndex]; FormatOutputField const& rFormatEntry = rFormatOutputField[nIndex]; - bool bFieldMatch = false; - bool bFieldMaybeMatch = false; - tools::Long nDimension = rFieldData.mnDimension; - if (nDimension == rFormatEntry.nDimension) + if (rFieldData.mnDimension != rFormatEntry.nDimension) { - if (rFormatEntry.bSet) - { - if (rFormatEntry.bMatchesAll && !rFieldData.bSubtotal) - bFieldMatch = true; - else if (nDimension == constDataDimension - && rFieldData.nIndex == rFormatEntry.nIndex) - bFieldMatch = true; - else if (nDimension != constDataDimension - && rFieldData.aName == rFormatEntry.aName) - bFieldMatch = true; - } - else if (!rFormatEntry.bSet && eType == FormatType::Data && !rFieldData.bIsMember - && !rFieldData.bContinue) - { - bFieldMatch = true; - } - else - { - bFieldMaybeMatch = true; - } + bAllMatch = false; + break; } - if (!bFieldMatch && !bFieldMaybeMatch) - break; + if (!rFormatEntry.bSet) + continue; - if (bFieldMatch) - nMatch++; + bool bFieldMatch = false; - if (bFieldMaybeMatch) - nMaybeMatch++; + if (rFormatEntry.bHasSubtotal) + { + if (rFieldData.bSubtotal && rFieldData.aName == rFormatEntry.aName) + { + // Exact subtotal match + bFieldMatch = true; + bHasSubtotalMatch = true; + } + else if (!rFormatEntry.bSelected && !rFieldData.bSubtotal + && rFieldData.aName == rFormatEntry.aName) + { + // selected=0 + subtotal: also match data rows in scope. + // Two pass matching will handle the broad/exact distinction. + bFieldMatch = true; + } + } + else if (rFormatEntry.bMatchesAll && !rFieldData.bSubtotal) + bFieldMatch = true; + else if (rFormatEntry.nDimension == constDataDimension + && rFieldData.nIndex == rFormatEntry.nIndex) + bFieldMatch = true; + else if (rFormatEntry.nDimension != constDataDimension && !rFieldData.bSubtotal + && rFieldData.aName == rFormatEntry.aName) + bFieldMatch = true; + + if (!bFieldMatch) + bAllMatch = false; } - if (nMatch == nNoOfFields) + // Check unreferenced fields. + // On subtotal lines, unreferenced fields are empty. Allow them + // when a referenced field matched as a subtotal. + for (size_t nIndex = 0; nIndex < nNoOfFields && bAllMatch; nIndex++) { - rMatches.push_back(std::cref(rLineData)); + FormatOutputField const& rFormatEntry = rFormatOutputField[nIndex]; + if (rFormatEntry.bSet) + continue; + + FieldData const& rFieldData = rLineData.maFields[nIndex]; + + if (eType == FormatType::Label) + { + if (!bHasSubtotalMatch && !rFieldData.bIsMember && !rFieldData.bContinue) + bAllMatch = false; + } + else if (eType == FormatType::Data) + { + if (!bHasSubtotalMatch && (rFieldData.bIsMember || rFieldData.bContinue)) + bHasWildcardMember = true; + } } - else if (nMatch + nMaybeMatch == nNoOfFields) + + if (bAllMatch) { - rMaybeMatches.push_back(std::cref(rLineData)); + if (bHasWildcardMember) + aBroadMatches.push_back(std::cref(rLineData)); + else + rMatches.push_back(std::cref(rLineData)); } } + + // For data, use exact matching if available, otherwise fall back to broad + if (eType == FormatType::Data && rMatches.empty() && !aBroadMatches.empty()) + rMatches = std::move(aBroadMatches); } -/** Check the lines in matches and maybe matches and output */ -void evaluateMatches(ScDocument& rDocument, - std::vector> const& rMatches, - std::vector> const& rMaybeMatches, - std::vector& aRows, std::vector& aColumns, - FormatOutputEntry const& rOutputEntry, FormatResultDirection eResultDirection) +/** Find the index of the first referenced (set) field in the format output fields */ +size_t findMatchedFieldIndex(std::vector const& rOutputFields) { - // We expect that tab and pattern to be set or this method shouldn't be called at all - assert(rOutputEntry.onTab); - assert(rOutputEntry.pPattern); + for (size_t i = 0; i < rOutputFields.size(); i++) + { + if (rOutputFields[i].bSet) + return i; + } + return 0; +} - if (rMatches.empty() && rMaybeMatches.empty()) - return; +/** Apply matched lines — labels go directly to cells, data collects rows/columns */ +void applyMatchedLines(ScDocument& rDocument, + std::vector> const& rMatches, + std::vector& aRows, std::vector& aColumns, + FormatOutputEntry const& rEntry, + std::vector const& rOutputFields, + FormatResultDirection eResultDirection, SCCOL nTabStartColumn, + SCROW nColumnHeaderStartRow, SCCOL nDataStartColumn, SCROW nDataStartRow) +{ + assert(rEntry.onTab); + assert(rEntry.pPattern); - bool bMaybeExists = rMatches.empty(); + // For range offsets (e.g. "IV2:IV3"), track position within the matched + // group to filter which lines get formatted. + bool bHasRowRange = false; + SCROW nOffsetRowStart = 0; + SCROW nOffsetRowEnd = 0; + if (rEntry.oOffset && eResultDirection == FormatResultDirection::ROW) + { + nOffsetRowStart = rEntry.oOffset->aStart.Row(); + nOffsetRowEnd = rEntry.oOffset->aEnd.Row(); + if (nOffsetRowStart != nOffsetRowEnd) + bHasRowRange = true; + } - auto const& rLineDataVector = bMaybeExists ? rMaybeMatches : rMatches; - - for (LineData const& rLineData : rLineDataVector) + size_t nMatchIndex = 0; + for (LineData const& rLineData : rMatches) { - // Can't continue if we don't have complete row/column data if (!rLineData.oLine || !rLineData.oPosition) continue; - if (rOutputEntry.eType == FormatType::Label && !bMaybeExists) + if (rEntry.eType == FormatType::Label) { - // Primary axis is set to column (line) then row (position) + // Range offset: only format lines within the row/col range + if (bHasRowRange) + { + SCROW nIdx = static_cast(nMatchIndex); + if (nIdx < nOffsetRowStart || nIdx > nOffsetRowEnd) + { + nMatchIndex++; + continue; + } + } + SCCOLROW nColumn = *rLineData.oLine; SCCOLROW nRow = *rLineData.oPosition; - // In row orientation, the primary axis is row, then column, so we need to swap if (eResultDirection == FormatResultDirection::ROW) std::swap(nRow, nColumn); - // Set the pattern to the sheet - rDocument.ApplyPattern(nColumn, nRow, *rOutputEntry.onTab, *rOutputEntry.pPattern); + // Determine the target column/row for the label. + size_t nFieldIndex = findMatchedFieldIndex(rOutputFields); + + if (eResultDirection == FormatResultDirection::ROW) + { + SCCOL nLabelColumns = nDataStartColumn - nTabStartColumn; + if (rEntry.oOffset && !bHasRowRange) + { + SCCOL nOffsetColumn = rEntry.oOffset->aStart.Col(); + if (nOffsetColumn < nLabelColumns) + nColumn = nTabStartColumn + nOffsetColumn; + else + nColumn = nTabStartColumn + nFieldIndex; + } + else + { + nColumn = nTabStartColumn + nFieldIndex; + } + } + else if (eResultDirection == FormatResultDirection::COLUMN) + { + SCROW nHeaderRows = nDataStartRow - nColumnHeaderStartRow; + if (rEntry.oOffset) + { + SCROW nOffsetRow = rEntry.oOffset->aStart.Row(); + if (nOffsetRow < nHeaderRows) + nRow = nColumnHeaderStartRow + nOffsetRow; + else + nRow = nColumnHeaderStartRow + nFieldIndex; + } + else + { + nRow = nColumnHeaderStartRow + nFieldIndex; + } + } + + rDocument.ApplyPattern(nColumn, nRow, *rEntry.onTab, *rEntry.pPattern); } - else if (rOutputEntry.eType == FormatType::Data) + else if (rEntry.eType == FormatType::Data) { if (eResultDirection == FormatResultDirection::ROW) aRows.push_back(*rLineData.oLine); else if (eResultDirection == FormatResultDirection::COLUMN) aColumns.push_back(*rLineData.oLine); } + nMatchIndex++; + } +} + +/** Check if any output field in the vector has been set (has a reference). */ +bool hasSetFields(std::vector const& rFields) +{ + if (rFields.empty()) + return false; + return std::any_of(rFields.begin(), rFields.end(), + [](auto const& rField) { return rField.bSet; }); +} + +/** Iterate matched lines and call the applicator for each line position, but + * skip the grand total position. */ +template +void applyToMatchedLines(LinesT const& rMatchedLines, SCCOLROW nGrandTotalPositionToSkip, + std::function const& rApplicator) +{ + for (LineData const& rLine : rMatchedLines) + { + if (!rLine.oLine) + continue; + if (nGrandTotalPositionToSkip >= 0 && *rLine.oLine == nGrandTotalPositionToSkip) + continue; + rApplicator(*rLine.oLine); + } +} + +/** Apply a grand total data format along one axis. + * If there are references, then find specific lines, otherwise apply to all + * lines. Skips the grand total position to avoid setting the intersection + * cell. */ +void applyGrandTotalDataFormat(std::vector const& rLines, + std::vector const& rOutputFields, + SCCOLROW nGrandTotalPositionToSkip, + std::function const& rApplicator) +{ + if (hasSetFields(rOutputFields)) + { + // Use FormatType::None to collect all matching lines (both exact and broad) + // because grand totals need to apply to all matches, not just the narrower set + std::vector> aMatches; + findMatchingLines(rLines, rOutputFields, FormatType::None, aMatches); + applyToMatchedLines(aMatches, nGrandTotalPositionToSkip, rApplicator); + } + else + { + applyToMatchedLines(rLines, nGrandTotalPositionToSkip, rApplicator); } } } // end anonymous namespace +bool FormatOutput::tryHandleGrandTotals(ScDocument& rDocument, sc::FormatOutputEntry const& rEntry) +{ + if (rEntry.bGrandRow && rEntry.bGrandColumn && mnGrandTotalRow >= 0 && mnGrandTotalColumn >= 0) + { + rDocument.ApplyPattern(mnGrandTotalColumn, mnGrandTotalRow, *rEntry.onTab, + *rEntry.pPattern); + return true; + } + + if (rEntry.bGrandRow && mnGrandTotalRow >= 0) + { + if (rEntry.eType == FormatType::Data) + { + applyGrandTotalDataFormat(maColumnLines, rEntry.aColumnOutputFields, mnGrandTotalColumn, + [&](SCCOLROW nColumnPosition) { + rDocument.ApplyPattern(nColumnPosition, mnGrandTotalRow, + *rEntry.onTab, *rEntry.pPattern); + }); + } + else if (rEntry.eType == FormatType::Label) + { + if (rEntry.oOffset && mnTabStartColumn >= 0 && mnDataStartColumn > mnTabStartColumn) + { + // Offset column is relative to the label area + SCCOL nOffsetColumn = rEntry.oOffset->aStart.Col(); + SCCOL nLabelCount = mnDataStartColumn - mnTabStartColumn; + SCCOL nTargetColumn + = mnTabStartColumn + std::min(nOffsetColumn, SCCOL(nLabelCount - 1)); + rDocument.ApplyPattern(nTargetColumn, mnGrandTotalRow, *rEntry.onTab, + *rEntry.pPattern); + } + else if (mnTabStartColumn >= 0 && mnDataStartColumn > mnTabStartColumn) + { + // No offset: apply to all label columns + for (SCCOL nColumn = mnTabStartColumn; nColumn < mnDataStartColumn; ++nColumn) + { + rDocument.ApplyPattern(nColumn, mnGrandTotalRow, *rEntry.onTab, + *rEntry.pPattern); + } + } + } + return true; + } + + if (rEntry.bGrandColumn && mnGrandTotalColumn >= 0) + { + if (rEntry.eType == FormatType::Data) + { + applyGrandTotalDataFormat(maRowLines, rEntry.aRowOutputFields, mnGrandTotalRow, + [&](SCCOLROW nRowPosition) { + rDocument.ApplyPattern(mnGrandTotalColumn, nRowPosition, + *rEntry.onTab, *rEntry.pPattern); + }); + } + else if (rEntry.eType == FormatType::Label) + { + // Apply to the column header rows at the grand total column. + // Use the column lines' positions to find header row positions. + std::set aHeaderRows; + for (LineData const& rColLine : maColumnLines) + { + if (rColLine.oPosition) + aHeaderRows.insert(*rColLine.oPosition); + } + for (SCROW nRow : aHeaderRows) + { + rDocument.ApplyPattern(mnGrandTotalColumn, nRow, *rEntry.onTab, *rEntry.pPattern); + } + } + return true; + } + + return false; +} + void FormatOutput::apply(ScDocument& rDocument) { if (!mpFormats) return; - for (auto const& rOutputEntry : maFormatOutputEntries) + for (auto const& rEntry : maFormatOutputEntries) { - if (!rOutputEntry.onTab || !rOutputEntry.pPattern) + if (!rEntry.onTab || !rEntry.pPattern) + continue; + + // Handle grand total formats + if (tryHandleGrandTotals(rDocument, rEntry)) continue; std::vector aRows; std::vector aColumns; + bool bHasRowReferences = hasSetFields(rEntry.aRowOutputFields); + bool bHasColumnReferences = hasSetFields(rEntry.aColumnOutputFields); + + // For labels, only match the axis that has references to avoid + // wildcard matching applying labels to the wrong axis cells. + bool bMatchRows = (rEntry.eType != FormatType::Label) || bHasRowReferences; + bool bMatchColumns = (rEntry.eType != FormatType::Label) || bHasColumnReferences; + + // Column headers start after any field name rows at the top. + // With N column fields, headers occupy the N rows before the data start. + SCROW nColumnHeaderStartRow = mnDataStartRow; + if (!maColumnLines.empty() && !maColumnLines[0].maFields.empty()) + nColumnHeaderStartRow -= SCROW(maColumnLines[0].maFields.size()); + + if (bMatchRows) { - std::vector> rMatches; - std::vector> rMaybeMatches; + std::vector> aRowMatches; + findMatchingLines(maRowLines, rEntry.aRowOutputFields, rEntry.eType, aRowMatches); - checkForMatchingLines(maRowLines, rOutputEntry.aRowOutputFields, rOutputEntry.eType, - rMatches, rMaybeMatches); + // For data formats targeting subtotal intersections (all set fields + // on both axes have bHasSubtotal), single data row groups get the + // format applied to the data row too, not just the subtotal row. + if (rEntry.eType == FormatType::Data && !aRowMatches.empty()) + { + bool bAllRowSubtotal = std::all_of( + rEntry.aRowOutputFields.begin(), rEntry.aRowOutputFields.end(), + [](auto const& rField) { return !rField.bSet || rField.bHasSubtotal; }); - evaluateMatches(rDocument, rMatches, rMaybeMatches, aRows, aColumns, rOutputEntry, - FormatResultDirection::ROW); + bool bAllColumnSubtotal = std::all_of( + rEntry.aColumnOutputFields.begin(), rEntry.aColumnOutputFields.end(), + [](auto const& rField) { return !rField.bSet || rField.bHasSubtotal; }); + + if (bAllRowSubtotal && bAllColumnSubtotal) + { + // Find the index of each matched subtotal in the lines vector, + // then check if the preceding line is a single item group member. + std::vector> aExtraMatches; + for (LineData const& rMatch : aRowMatches) + { + for (size_t i = 1; i < maRowLines.size(); i++) + { + if (&maRowLines[i] != &rMatch) + continue; + + LineData const& rPrev = maRowLines[i - 1]; + size_t nFieldIndex = findMatchedFieldIndex(rEntry.aRowOutputFields); + if (nFieldIndex < rPrev.maFields.size() + && rPrev.maFields[nFieldIndex].bIsMember + && !rPrev.maFields[nFieldIndex].bSubtotal) + { + aExtraMatches.push_back(std::cref(rPrev)); + } + break; + } + } + for (auto const& rExtra : aExtraMatches) + aRowMatches.push_back(rExtra); + } + } + + applyMatchedLines(rDocument, aRowMatches, aRows, aColumns, rEntry, + rEntry.aRowOutputFields, FormatResultDirection::ROW, mnTabStartColumn, + nColumnHeaderStartRow, mnDataStartColumn, mnDataStartRow); } + if (bMatchColumns) { - std::vector> rMatches; - std::vector> rMaybeMatches; - - checkForMatchingLines(maColumnLines, rOutputEntry.aColumnOutputFields, - rOutputEntry.eType, rMatches, rMaybeMatches); - - evaluateMatches(rDocument, rMatches, rMaybeMatches, aRows, aColumns, rOutputEntry, - FormatResultDirection::COLUMN); + std::vector> aColumnMatches; + findMatchingLines(maColumnLines, rEntry.aColumnOutputFields, rEntry.eType, + aColumnMatches); + applyMatchedLines(rDocument, aColumnMatches, aRows, aColumns, rEntry, + rEntry.aColumnOutputFields, FormatResultDirection::COLUMN, + mnTabStartColumn, nColumnHeaderStartRow, mnDataStartColumn, + mnDataStartRow); } - if (!aColumns.empty() && !aRows.empty() && rOutputEntry.eType == FormatType::Data) + if (!aColumns.empty() && !aRows.empty() && rEntry.eType == FormatType::Data) { for (SCCOLROW nRow : aRows) { for (SCCOLROW nColumn : aColumns) { - rDocument.ApplyPattern(nColumn, nRow, *rOutputEntry.onTab, - *rOutputEntry.pPattern); + rDocument.ApplyPattern(nColumn, nRow, *rEntry.onTab, *rEntry.pPattern); } } } diff --git a/sc/source/core/data/SheetView.cxx b/sc/source/core/data/SheetView.cxx index 0a141b99258d..b11431186970 100644 --- a/sc/source/core/data/SheetView.cxx +++ b/sc/source/core/data/SheetView.cxx @@ -12,58 +12,263 @@ namespace sc { -void SortOrderReverser::addOrderIndices(std::vector const& rOrder, SCROW firstRow, - SCROW lastRow) +namespace { - mnFirstRow = firstRow; - mnLastRow = lastRow; +/** Merge sort order arrays, so the order is the same as it would be by doing multiple independent sort operation */ +std::vector mergeOrder(std::vector const& rExistingOrder, + std::vector const& rAddedOrder) +{ + size_t nOrderSize = rExistingOrder.size(); + assert(nOrderSize == rAddedOrder.size()); - if (maOrder.empty()) + std::vector aNewOrder(nOrderSize); + for (size_t nIndex = 0; nIndex < nOrderSize; ++nIndex) { - maOrder = rOrder; + size_t nSortedIndex = rAddedOrder[nIndex] - 1; + aNewOrder[nIndex] = rExistingOrder[nSortedIndex]; + } + return aNewOrder; +} + +/** Adjust order indices when rows are inserted within a sorted range. */ +void expandOrderIndices(std::vector& rOrder, SCROW nStartRow, SCROW nFirstRow, + SCROW nCount) +{ + SCCOLROW nOffset = nStartRow - nFirstRow + 1; // 1-based + for (auto& rValue : rOrder) + { + if (rValue >= nOffset) + rValue += nCount; + } + for (SCROW i = 0; i < nCount; ++i) + rOrder.push_back(nOffset + i); +} + +/** Remove order entries at 1-based nOffset for nCount positions, adjusting remaining values. */ +void removeOrderEntries(std::vector& rOrder, SCCOLROW nOffset, SCROW nCount) +{ + std::vector aNewOrder; + for (auto& rValue : rOrder) + { + if (rValue >= nOffset && rValue < nOffset + nCount) + continue; // deleted + if (rValue >= nOffset + nCount) + aNewOrder.push_back(rValue - nCount); + else + aNewOrder.push_back(rValue); + } + rOrder = std::move(aNewOrder); +} + +/** Adjust a row range and order indices for deleted rows. + * + * On entire range deletion the order is cleared. + */ +void deleteRowsFromOrderedRange(SCROW& nStart, SCROW& nEnd, std::vector& rOrder, + SCROW nDeleteStart, SCROW nDeleteCount) +{ + SCROW nDeleteEnd = nDeleteStart + nDeleteCount - 1; + + // After the range - nothing to do + if (nDeleteStart > nEnd) + return; + + // Before the range - shift + if (nDeleteEnd < nStart) + { + nStart -= nDeleteCount; + nEnd -= nDeleteCount; + return; + } + + // Entire range deleted + if (nDeleteStart <= nStart && nDeleteEnd >= nEnd) + { + rOrder.clear(); + return; + } + + // Partial overlap - compute overlap and update order + SCROW nOverlapStart = std::max(nDeleteStart, nStart); + SCROW nOverlapEnd = std::min(nDeleteEnd, nEnd); + SCROW nDeletedWithin = nOverlapEnd - nOverlapStart + 1; + SCCOLROW nOffset = nOverlapStart - nStart + 1; // + 1 because offset is 1-based + + removeOrderEntries(rOrder, nOffset, nDeletedWithin); + + if (nDeleteStart <= nStart) + { + SCROW nDeletedBefore = nStart - nDeleteStart; + nStart -= nDeletedBefore; + nEnd -= nDeleteCount; } else { - assert(maOrder.size() == rOrder.size()); - std::vector newOrder(maOrder.size()); - for (size_t nIndex = 0; nIndex < maOrder.size(); ++nIndex) - { - size_t nSortedIndex = rOrder[nIndex]; - newOrder[nIndex] = maOrder[nSortedIndex - 1]; - } - maOrder = std::move(newOrder); + nEnd -= nDeletedWithin; + } +} +/** Adjust a column range for inserted columns. */ +void adjustColumnRangeForInsert(SCCOL& nStart, SCCOL& nEnd, SCCOL nInsertStart, SCCOL nInsertCount) +{ + if (nInsertStart <= nStart) + { + nStart += nInsertCount; + nEnd += nInsertCount; + } + else if (nInsertStart <= nEnd) + { + nEnd += nInsertCount; } } -SCROW SortOrderReverser::unsort(SCROW nRow) const +/** Adjust a column range for deleted columns. + * + * On entire range deletion the order is cleared. + */ +void deleteColumnsFromOrderedRange(SCCOL& nStart, SCCOL& nEnd, std::vector& rOrder, + SCCOL nDeleteStart, SCCOL nDeleteCount) { - if (maOrder.empty()) + SCCOL nDeleteEnd = nDeleteStart + nDeleteCount - 1; + + // After the range - nothing to do + if (nDeleteStart > nEnd) + return; + + // Before the range - shift + if (nDeleteEnd < nStart) + { + nStart -= nDeleteCount; + nEnd -= nDeleteCount; + return; + } + + // Entire range deleted + if (nDeleteStart <= nStart && nDeleteEnd >= nEnd) + { + rOrder.clear(); + return; + } + + // Partial overlap + SCCOL nOverlapStart = std::max(nDeleteStart, nStart); + SCCOL nOverlapEnd = std::min(nDeleteEnd, nEnd); + SCCOL nDeletedWithin = nOverlapEnd - nOverlapStart + 1; + if (nDeleteStart <= nStart) + nStart = nDeleteStart; + nEnd -= nDeletedWithin; +} +} // end anonymous namespace + +void SortOrderReverser::addOrderIndices(SortOrderInfo const& rSortInfo) +{ + bool bKeyStatesEqual = std::equal(rSortInfo.maKeyStates.begin(), rSortInfo.maKeyStates.begin(), + maSortInfo.maKeyStates.begin()); + + if (bKeyStatesEqual && maSortInfo.mnFirstRow == rSortInfo.mnFirstRow + && maSortInfo.mnLastRow == rSortInfo.mnLastRow) + { + if (maSortInfo.maOrder.empty()) + { + // just set the order - no need to merge + maSortInfo.maOrder = rSortInfo.maOrder; + } + else + { + maSortInfo.maOrder = mergeOrder(maSortInfo.maOrder, rSortInfo.maOrder); + } + } + else + { + maSortInfo = rSortInfo; + } +} + +SCROW SortOrderReverser::unsort(SCROW nRow, SCCOL nColumn) const +{ + if (maSortInfo.maOrder.empty()) return nRow; - if (nRow >= mnFirstRow && nRow <= mnLastRow) + if (maSortInfo.mnFirstColumn >= 0 && maSortInfo.mnLastColumn >= 0 + && (nColumn < maSortInfo.mnFirstColumn || nColumn > maSortInfo.mnLastColumn)) + return nRow; + + if (nRow < maSortInfo.mnFirstRow || nRow > maSortInfo.mnLastRow) + return nRow; + + size_t index = nRow - maSortInfo.mnFirstRow; + auto nUnsortedRow = maSortInfo.mnFirstRow + maSortInfo.maOrder[index] - 1; + return nUnsortedRow; +} + +SCROW SortOrderReverser::resort(SCROW nRow, SCCOL nColumn) const +{ + if (maSortInfo.maOrder.empty()) + return nRow; + + if (maSortInfo.mnFirstColumn >= 0 && maSortInfo.mnLastColumn >= 0 + && (nColumn < maSortInfo.mnFirstColumn || nColumn > maSortInfo.mnLastColumn)) + return nRow; + + if (nRow < maSortInfo.mnFirstRow || nRow > maSortInfo.mnLastRow) + return nRow; + + SCCOLROW nOrderValue = nRow - maSortInfo.mnFirstRow + 1; + for (size_t nIndex = 0; nIndex < maSortInfo.maOrder.size(); ++nIndex) { - size_t index = nRow - mnFirstRow; - auto nUnsortedRow = mnFirstRow + maOrder[index] - 1; - return nUnsortedRow; + if (maSortInfo.maOrder[nIndex] == nOrderValue) + return maSortInfo.mnFirstRow + nIndex; } return nRow; } -SCROW SortOrderReverser::resort(SCROW nRow) const +void SortOrderReverser::insertedRows(SCROW nStartRow, SCROW nRowCount) { - if (maOrder.empty()) - return nRow; - - if (nRow >= mnFirstRow && nRow <= mnLastRow) + if (nStartRow > maSortInfo.mnLastRow + 1) { - SCCOLROW nOrderValue = nRow - mnFirstRow + 1; - for (size_t nIndex = 0; nIndex < maOrder.size(); ++nIndex) - { - if (maOrder[nIndex] == nOrderValue) - return mnFirstRow + nIndex; - } + // After the sort range - nothing to do. + } + else if (nStartRow < maSortInfo.mnFirstRow) + { + // Before the sort range - shift the whole range. + maSortInfo.mnFirstRow += nRowCount; + maSortInfo.mnLastRow += nRowCount; + } + else + { + // At start of or within the sort range - expand and update order. + expandOrderIndices(maSortInfo.maOrder, nStartRow, maSortInfo.mnFirstRow, nRowCount); + maSortInfo.mnLastRow += nRowCount; + } +} + +void SortOrderReverser::deletedRows(SCROW nStartRow, SCROW nRowCount) +{ + deleteRowsFromOrderedRange(maSortInfo.mnFirstRow, maSortInfo.mnLastRow, maSortInfo.maOrder, + nStartRow, nRowCount); + + // no order indices - range is empty now + if (maSortInfo.maOrder.empty()) + { + maSortInfo.mnFirstRow = 0; + maSortInfo.mnLastRow = 0; + } +} + +void SortOrderReverser::insertedColumns(SCCOL nStartColumn, SCCOL nColumnCount) +{ + adjustColumnRangeForInsert(maSortInfo.mnFirstColumn, maSortInfo.mnLastColumn, nStartColumn, + nColumnCount); +} + +void SortOrderReverser::deletedColumns(SCCOL nStartColumn, SCCOL nColumnCount) +{ + deleteColumnsFromOrderedRange(maSortInfo.mnFirstColumn, maSortInfo.mnLastColumn, + maSortInfo.maOrder, nStartColumn, nColumnCount); + if (maSortInfo.maOrder.empty()) + { + maSortInfo.mnFirstColumn = 0; + maSortInfo.mnLastColumn = 0; } - return nRow; } SheetView::SheetView(ScTable* pTable, OUString const& rName, SheetViewID nID) @@ -81,12 +286,331 @@ SCTAB SheetView::getTableNumber() const return mpTable->GetTab(); } -void SheetView::addOrderIndices(std::vector const& rOrder, SCROW firstRow, SCROW lastRow) +SheetViewSortData& SheetView::ensureSortData() { - if (!moSortOrder) - moSortOrder.emplace(); - moSortOrder->addOrderIndices(rOrder, firstRow, lastRow); -} + if (!mpSortData) + mpSortData = std::make_shared(); + return *mpSortData; } +SortOrderReverser const* SheetView::getSortOrder() const +{ + if (!mpSortData || mpSortData->maSortOrder.maSortInfo.maOrder.empty()) + return nullptr; + return &mpSortData->maSortOrder; +} + +void SheetView::resetSortOrder() +{ + if (mpSortData) + mpSortData->maSortOrder = SortOrderReverser(); +} + +void SheetView::addOrderIndices(SortOrderInfo const& rSortInfo) +{ + ensureSortData().maSortOrder.addOrderIndices(rSortInfo); +} + +void SheetView::mergeReorderParameters(ReorderParam const& rReorderParameters) +{ + auto& rParams = ensureSortData().maOriginalReorderParams; + if (!rParams.maOrderIndices.empty()) + { + rParams.maOrderIndices + = mergeOrder(rParams.maOrderIndices, rReorderParameters.maOrderIndices); + } + else + { + rParams = rReorderParameters; + } +} + +ReorderParam const* SheetView::getReorderParameters() const +{ + if (!mpSortData || mpSortData->maOriginalReorderParams.maOrderIndices.empty()) + return nullptr; + return &mpSortData->maOriginalReorderParams; +} + +SCROW SheetView::reverseSortingToDefaultView(SCROW nRow, SCCOL nColumn) const +{ + SCROW nUnsortedRow = nRow; + + // Unsort the sheet view's sort and bring it to the default view's order + // when the sheet view was created. + if (mpSortData) + { + nUnsortedRow = mpSortData->maSortOrder.unsort(nRow, nColumn); + } + + // Resort the default view's sort done since the sheet view creation. + SCROW nResortedRow = nUnsortedRow; + if (mpSortData && !mpSortData->maOriginalReorderParams.maOrderIndices.empty()) + { + ScRange const& rRange = mpSortData->maOriginalReorderParams.maSortRange; + + SortOrderReverser aReverser; + aReverser.addOrderIndices({ rRange.aStart.Col(), + rRange.aEnd.Col(), + rRange.aStart.Row(), + rRange.aEnd.Row(), + mpSortData->maOriginalReorderParams.maOrderIndices, + {} }); + + nResortedRow = aReverser.resort(nUnsortedRow, nColumn); + } + return nResortedRow; +} + +SCROW SheetView::reverseDefaultViewToSheetView(SCROW nRow, SCCOL nColumn) const +{ + SCROW nUnsortedRow = nRow; + + // Reverse the default view's sorting (default view -> unsorted) + if (mpSortData && !mpSortData->maOriginalReorderParams.maOrderIndices.empty()) + { + ScRange const& rRange = mpSortData->maOriginalReorderParams.maSortRange; + SortOrderReverser aReverser; + aReverser.addOrderIndices({ rRange.aStart.Col(), + rRange.aEnd.Col(), + rRange.aStart.Row(), + rRange.aEnd.Row(), + mpSortData->maOriginalReorderParams.maOrderIndices, + {} }); + nUnsortedRow = aReverser.unsort(nRow, nColumn); + } + + // Apply the sheet view's sort (unsorted -> sheet view) + SCROW nSheetViewRow = nUnsortedRow; + if (mpSortData) + { + nSheetViewRow = mpSortData->maSortOrder.resort(nUnsortedRow, nColumn); + } + return nSheetViewRow; +} + +void SheetView::adjustReorderParamsForInsertRows(SCROW nStartRow, SCROW nRowCount) +{ + if (!mpSortData || mpSortData->maOriginalReorderParams.maOrderIndices.empty()) + return; + + ScRange& rRange = mpSortData->maOriginalReorderParams.maSortRange; + if (nStartRow < rRange.aStart.Row()) + { + rRange.aStart.IncRow(nRowCount); + rRange.aEnd.IncRow(nRowCount); + } + else if (nStartRow <= rRange.aEnd.Row() + 1) + { + expandOrderIndices(mpSortData->maOriginalReorderParams.maOrderIndices, nStartRow, + rRange.aStart.Row(), nRowCount); + rRange.aEnd.IncRow(nRowCount); + } +} + +void SheetView::adjustSortParamForInsertRows(SCROW nStartRow, SCROW nRowCount) +{ + if (!mpSortData) + return; + + if (nStartRow < mpSortData->maSortParam.nRow1) + { + mpSortData->maSortParam.nRow1 += nRowCount; + mpSortData->maSortParam.nRow2 += nRowCount; + } + else if (nStartRow <= mpSortData->maSortParam.nRow2 + 1) + { + mpSortData->maSortParam.nRow2 += nRowCount; + } +} + +void SheetView::insertedRows(SCROW nStartRow, SCROW nRowCount) +{ + if (mpSortData) + mpSortData->maSortOrder.insertedRows(nStartRow, nRowCount); + + // Update the reorder params that track the default view's sort since sheet view creation + adjustReorderParamsForInsertRows(nStartRow, nRowCount); + + // Update the stored sort parameters (the range the sheet view was sorted on) + adjustSortParamForInsertRows(nStartRow, nRowCount); +} + +void SheetView::adjustReorderParamsForDeleteRows(SCROW nStartRow, SCROW nRowCount) +{ + if (!mpSortData || mpSortData->maOriginalReorderParams.maOrderIndices.empty()) + return; + + ScRange& rRange = mpSortData->maOriginalReorderParams.maSortRange; + SCROW nRangeStart = rRange.aStart.Row(); + SCROW nRangeEnd = rRange.aEnd.Row(); + deleteRowsFromOrderedRange(nRangeStart, nRangeEnd, + mpSortData->maOriginalReorderParams.maOrderIndices, nStartRow, + nRowCount); + if (mpSortData->maOriginalReorderParams.maOrderIndices.empty()) + { + mpSortData->maOriginalReorderParams = ReorderParam(); + } + else + { + rRange.aStart.SetRow(nRangeStart); + rRange.aEnd.SetRow(nRangeEnd); + } +} + +void SheetView::adjustSortParamForDeleteRows(SCROW nStartRow, SCROW nRowCount) +{ + if (!mpSortData) + return; + + std::vector aUnused; + deleteRowsFromOrderedRange(mpSortData->maSortParam.nRow1, mpSortData->maSortParam.nRow2, + aUnused, nStartRow, nRowCount); +} + +void SheetView::deletedRows(SCROW nStartRow, SCROW nRowCount) +{ + // Update the sheet view's own sort order + if (mpSortData) + mpSortData->maSortOrder.deletedRows(nStartRow, nRowCount); + + // Update the reorder params that track the default view's sort since sheet view creation + adjustReorderParamsForDeleteRows(nStartRow, nRowCount); + + // Update the stored sort parameters (the range the sheet view was sorted on) + adjustSortParamForDeleteRows(nStartRow, nRowCount); +} + +ScSortParam const* SheetView::getSortParam() const +{ + if (!mpSortData || !mpSortData->maSortParam.GetSortKeyCount() + || !mpSortData->maSortParam.maKeyState[0].bDoSort) + return nullptr; + return &mpSortData->maSortParam; +} + +void SheetView::setSortParam(ScSortParam const& rSortParam) +{ + ensureSortData().maSortParam = rSortParam; +} + +void SheetView::adjustReorderParamsForInsertColumns(SCCOL nStartColumn, SCCOL nColumnCount) +{ + if (!mpSortData || mpSortData->maOriginalReorderParams.maOrderIndices.empty()) + return; + + ScRange& rRange = mpSortData->maOriginalReorderParams.maSortRange; + SCCOL nColumnStart = rRange.aStart.Col(); + SCCOL nColumnEnd = rRange.aEnd.Col(); + adjustColumnRangeForInsert(nColumnStart, nColumnEnd, nStartColumn, nColumnCount); + rRange.aStart.SetCol(nColumnStart); + rRange.aEnd.SetCol(nColumnEnd); +} + +void SheetView::adjustSortParamForInsertColumns(SCCOL nStartColumn, SCCOL nColumnCount) +{ + if (!mpSortData) + return; + + adjustColumnRangeForInsert(mpSortData->maSortParam.nCol1, mpSortData->maSortParam.nCol2, + nStartColumn, nColumnCount); + + // We need to adjust key state - columns shift by one + for (auto& rKey : mpSortData->maSortParam.maKeyState) + { + if (rKey.bDoSort && rKey.nField >= nStartColumn) + rKey.nField += nColumnCount; + } +} + +void SheetView::insertedColumns(SCCOL nStartColumn, SCCOL nColumnCount) +{ + // Update the sheet view's own sort order + if (mpSortData) + mpSortData->maSortOrder.insertedColumns(nStartColumn, nColumnCount); + + // Update the reorder params that track the default view's sort since sheet view creation + adjustReorderParamsForInsertColumns(nStartColumn, nColumnCount); + + // Update the stored sort parameters (the range the sheet view was sorted on) + adjustSortParamForInsertColumns(nStartColumn, nColumnCount); +} + +void SheetView::adjustReorderParamsForDeleteColumns(SCCOL nStartColumn, SCCOL nColumnCount) +{ + if (!mpSortData || mpSortData->maOriginalReorderParams.maOrderIndices.empty()) + return; + + ScRange& rRange = mpSortData->maOriginalReorderParams.maSortRange; + SCCOL nStart = rRange.aStart.Col(); + SCCOL nEnd = rRange.aEnd.Col(); + deleteColumnsFromOrderedRange(nStart, nEnd, mpSortData->maOriginalReorderParams.maOrderIndices, + nStartColumn, nColumnCount); + if (mpSortData->maOriginalReorderParams.maOrderIndices.empty()) + { + mpSortData->maOriginalReorderParams = ReorderParam(); + } + else + { + rRange.aStart.SetCol(nStart); + rRange.aEnd.SetCol(nEnd); + } +} + +void SheetView::adjustSortParamForDeleteColumns(SCCOL nStartColumn, SCCOL nColumnCount) +{ + if (!mpSortData) + return; + + SCCOL nDeleteEnd = nStartColumn + nColumnCount - 1; + + std::vector aUnused; + deleteColumnsFromOrderedRange(mpSortData->maSortParam.nCol1, mpSortData->maSortParam.nCol2, + aUnused, nStartColumn, nColumnCount); + + // We need to adjust key state - columns shift by one + for (auto& rKey : mpSortData->maSortParam.maKeyState) + { + if (rKey.bDoSort && rKey.nField >= nStartColumn) + { + if (rKey.nField <= nDeleteEnd) + rKey.bDoSort = false; // sort key column was deleted + else + rKey.nField -= nColumnCount; + } + } +} + +void SheetView::deletedColumns(SCCOL nStartColumn, SCCOL nColumnCount) +{ + // Update the sheet view's own sort order + if (mpSortData) + mpSortData->maSortOrder.deletedColumns(nStartColumn, nColumnCount); + + // Update the reorder params that track the default view's sort since sheet view creation + adjustReorderParamsForDeleteColumns(nStartColumn, nColumnCount); + + // Update the stored sort parameters (the range the sheet view was sorted on) + adjustSortParamForDeleteColumns(nStartColumn, nColumnCount); +} + +void SheetView::resetSortData() { mpSortData.reset(); } + +std::shared_ptr SheetView::captureSortData() const +{ + if (!mpSortData) + return nullptr; + return std::make_shared(*mpSortData); +} + +void SheetView::restoreSortData(std::shared_ptr const& pData) +{ + if (pData) + mpSortData = std::make_shared(*pData); + else + mpSortData.reset(); +} + +} // end sc namespace + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/SheetViewManager.cxx b/sc/source/core/data/SheetViewManager.cxx index bbc5d63dd7ac..e31442c1aef6 100644 --- a/sc/source/core/data/SheetViewManager.cxx +++ b/sc/source/core/data/SheetViewManager.cxx @@ -11,6 +11,7 @@ #include #include #include +#include namespace sc { @@ -19,24 +20,32 @@ SheetViewManager::SheetViewManager() {} SheetViewID SheetViewManager::create(ScTable* pSheetViewTable) { SheetViewID nID(maViews.size()); - maViews.emplace_back(std::make_shared(pSheetViewTable, generateName(), nID)); + auto pView = std::make_shared(pSheetViewTable, generateName(), nID); + pView->SetGUID(comphelper::xml::generateGUIDString()); + pView->SetFilterGUID(comphelper::xml::generateGUIDString()); + maViews.emplace_back(std::move(pView)); + mnSheetViewCount++; return nID; } bool SheetViewManager::remove(SheetViewID nID) { - if (isValidSheetViewID(nID)) - { - // We only reset the value and not actually remove if from the vector, because the SheetViewID - // also represents the index in the vector. If we removed the value it would make all the - // following indices / SheetViewIDs returning the wrong SheetView. - maViews[nID].reset(); - return true; - } - return false; -} + if (!isValidSheetViewID(nID)) + return false; -void SheetViewManager::removeAll() { maViews.clear(); } + // It's probably a bug if we want to remove a non-existent sheet view. + SAL_WARN_IF(!maViews[nID], "sc", "Removing a non-existing sheet view."); + + if (!maViews[nID]) + return false; + + // We only reset the value and not actually remove if from the vector, because the SheetViewID + // also represents the index in the vector. If we removed the value it would make all the + // following indices / SheetViewIDs returning the wrong SheetView. + maViews[nID].reset(); + mnSheetViewCount--; + return true; +} std::shared_ptr SheetViewManager::get(SheetViewID nID) const { @@ -47,85 +56,6 @@ std::shared_ptr SheetViewManager::get(SheetViewID nID) const return std::shared_ptr(); } -/// Calculate the next existing sheet view to use. -SheetViewID SheetViewManager::getNextSheetView(SheetViewID nID) -{ - if (nID != DefaultSheetViewID && nID < 0) - return InvalidSheetViewID; - - if (maViews.empty()) - return DefaultSheetViewID; - - // Set to max, so we prevent the for loop to run - sal_Int32 startIndex = std::numeric_limits::max(); - - // Start with first index and search for the first sheet view in for loop. - if (nID == DefaultSheetViewID) - { - startIndex = 0; - } - // If we assume current ID is valid, so set the start to current + 1 to search - // for then next valid sheet view in the for loop. - else if (isValidSheetViewID(nID)) - { - startIndex = sal_Int32(nID) + 1; - } - - for (sal_Int32 nIndex = startIndex; nIndex < sal_Int32(maViews.size()); ++nIndex) - { - if (maViews[nIndex]) - return SheetViewID(nIndex); - } - - return DefaultSheetViewID; -} - -/// Calculate the previous existing sheet view to use. -SheetViewID SheetViewManager::getPreviousSheetView(SheetViewID nID) -{ - if (nID != DefaultSheetViewID && nID < 0) - return InvalidSheetViewID; - - if (maViews.empty()) - return DefaultSheetViewID; - - // Set to -1, so we prevent the for loop to run - sal_Int32 startIndex = -1; - - // Start with first index and search for the first sheet view in for loop. - if (nID == DefaultSheetViewID) - { - startIndex = sal_Int32(maViews.size()) - 1; - } - // If we assume current ID is valid, so set the start to current + 1 to search - // for then next valid sheet view in the for loop. - else if (isValidSheetViewID(nID)) - { - startIndex = sal_Int32(nID) - 1; - } - - for (sal_Int32 nIndex = startIndex; nIndex >= 0; --nIndex) - { - if (maViews[nIndex]) - return SheetViewID(nIndex); - } - - return DefaultSheetViewID; -} - -void SheetViewManager::unsyncAllSheetViews() -{ - for (auto const& pSheetView : maViews) - { - if (!pSheetView) - { - continue; - } - - pSheetView->unsync(); - } -} - OUString SheetViewManager::generateName() { maNameCounter++; @@ -135,13 +65,119 @@ OUString SheetViewManager::generateName() OUString SheetViewManager::defaultViewName() { return ScResId(STR_SHEET_VIEW_DEFAULT_VIEW_NAME); } -void SheetViewManager::addOrderIndices(std::vector const& rOrder, SCROW nFirstRow, - SCROW nLastRow) +DefaultViewSortData& SheetViewManager::ensureSortData() { - if (!moSortOrder) - moSortOrder.emplace(); - moSortOrder->addOrderIndices(rOrder, nFirstRow, nLastRow); -} + if (!mpSortData) + mpSortData = std::make_shared(); + return *mpSortData; } +SortOrderReverser const* SheetViewManager::getSortOrder() const +{ + if (!mpSortData || mpSortData->maSortOrder.maSortInfo.maOrder.empty()) + return nullptr; + return &mpSortData->maSortOrder; +} + +void SheetViewManager::addOrderIndices(SortOrderInfo const& rSortInfo) +{ + ensureSortData().maSortOrder.addOrderIndices(rSortInfo); +} + +void SheetViewManager::mergeReorderParameters(ReorderParam const& rReorderParameters) +{ + for (auto& rSheetView : iterateValidSheetViews()) + { + rSheetView.mergeReorderParameters(rReorderParameters); + } +} + +void SheetViewManager::insertedRows(SCROW nStartRow, SCROW nRowCount) +{ + if (mpSortData) + mpSortData->maSortOrder.insertedRows(nStartRow, nRowCount); + + for (auto& rSheetView : iterateValidSheetViews()) + { + rSheetView.insertedRows(nStartRow, nRowCount); + } +} + +void SheetViewManager::deletedRows(SCROW nStartRow, SCROW nRowCount) +{ + if (mpSortData) + mpSortData->maSortOrder.deletedRows(nStartRow, nRowCount); + + for (auto& rSheetView : iterateValidSheetViews()) + { + rSheetView.deletedRows(nStartRow, nRowCount); + } +} + +void SheetViewManager::insertedColumns(SCCOL nStartCol, SCCOL nColCount) +{ + if (mpSortData) + mpSortData->maSortOrder.insertedColumns(nStartCol, nColCount); + + for (auto& rSheetView : iterateValidSheetViews()) + { + rSheetView.insertedColumns(nStartCol, nColCount); + } +} + +void SheetViewManager::deletedColumns(SCCOL nStartCol, SCCOL nColCount) +{ + if (mpSortData) + mpSortData->maSortOrder.deletedColumns(nStartCol, nColCount); + + for (auto& rSheetView : iterateValidSheetViews()) + { + rSheetView.deletedColumns(nStartCol, nColCount); + } +} + +std::shared_ptr SheetViewManager::captureSortData() const +{ + auto pSortDataCopy = std::make_shared(); + if (mpSortData) + pSortDataCopy->maSortOrder = mpSortData->maSortOrder; + + // Capture each SheetView's full sort data + for (auto const& rSheetView : iterateValidSheetViews()) + { + pSortDataCopy->maSheetViewSortData.emplace_back(rSheetView.getID(), + rSheetView.captureSortData()); + } + return pSortDataCopy; +} + +void SheetViewManager::restoreSortData(std::shared_ptr const& pData) +{ + if (!pData) + { + mpSortData.reset(); + } + else + { + mpSortData = std::make_shared(); + mpSortData->maSortOrder = pData->maSortOrder; + } + + // Restore each SheetView's full sort data + if (!pData) + return; + + for (auto const & [ nID, pSortData ] : pData->maSheetViewSortData) + { + if (isValidSheetViewID(nID)) + { + auto pSheetView = get(nID); + if (pSheetView) + pSheetView->restoreSortData(pSortData); + } + } +} + +} // end sc + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/SolverSettings.cxx b/sc/source/core/data/SolverSettings.cxx index c7413bcb943e..eea32409b4aa 100644 --- a/sc/source/core/data/SolverSettings.cxx +++ b/sc/source/core/data/SolverSettings.cxx @@ -401,9 +401,9 @@ void SolverSettings::WriteConstraintPart(ConstraintPart ePart, tools::Long nInde return; OUString sRange = m_aConstraintParts[ePart] + OUString::number(nIndex); - ScRangeData* pNewEntry = new ScRangeData(m_rDoc, sRange, sValue); + std::unique_ptr pNewEntry(new ScRangeData(m_rDoc, sRange, sValue)); pNewEntry->AddType(ScRangeData::Type::Hidden); - m_pRangeName->insert(pNewEntry); + m_pRangeName->insert(std::move(pNewEntry)); } // Reads a single constraint part from its associated named range; returns false if the named @@ -438,6 +438,11 @@ void SolverSettings::ReadEngine() m_sLOEngineName = "com.sun.star.comp.Calc.CoinMPSolver"; } + // The Lpsolve solver has been removed. A document that still names it is + // solved by CoinMP, which handles the same linear models. + if (m_sLOEngineName == "com.sun.star.comp.Calc.LpsolveSolver") + m_sLOEngineName = u"com.sun.star.comp.Calc.CoinMPSolver"_ustr; + if (SolverNamesToExcelEngines.count(m_sLOEngineName)) { // Find equivalent MS engine code @@ -517,7 +522,7 @@ void SolverSettings::SaveSolverSettings() /* Reads the current value of the parameter in the named range into rValue * If the value does not exist, the rValue is left unchanged * This is private because it is only used during initialization - * Returns true if the value exits; returns false otherwise + * Returns true if the value exists; returns false otherwise */ bool SolverSettings::ReadParamValue(SolverParameter eParam, OUString& rValue, bool bRemoveQuotes) { @@ -616,9 +621,9 @@ void SolverSettings::WriteParamValue(SolverParameter eParam, OUString sValue, bo const auto iter = m_mNamedRanges.find(eParam); assert(iter != m_mNamedRanges.end()); OUString sRange = iter->second; - ScRangeData* pNewEntry = new ScRangeData(m_rDoc, sRange, sValue); + std::unique_ptr pNewEntry(new ScRangeData(m_rDoc, sRange, sValue)); pNewEntry->AddType(ScRangeData::Type::Hidden); - m_pRangeName->insert(pNewEntry); + m_pRangeName->insert(std::move(pNewEntry)); } // Writes a parameter value of type 'double' to the file as a named range @@ -633,9 +638,9 @@ void SolverSettings::WriteDoubleParamValue(SolverParameter eParam, std::u16strin OUString sLocalizedValue = rtl::math::doubleToUString( fValue, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, ScGlobal::getLocaleData().getNumDecimalSep()[0], true); - ScRangeData* pNewEntry = new ScRangeData(m_rDoc, sRange, sLocalizedValue); + std::unique_ptr pNewEntry(new ScRangeData(m_rDoc, sRange, sLocalizedValue)); pNewEntry->AddType(ScRangeData::Type::Hidden); - m_pRangeName->insert(pNewEntry); + m_pRangeName->insert(std::move(pNewEntry)); } void SolverSettings::GetEngineOptions(css::uno::Sequence& aOptions) @@ -752,7 +757,7 @@ void SolverSettings::DeleteAllNamedRanges() m_pRangeName->erase(*pItem); } -/* Sets all solver parameters to their default values and clear all constraints. +/* Sets all solver parameters to their default values and clears all constraints. * This method only resets the object properties, but does not save changes to the * document. To save changes, call SaveSolverSettings(). */ diff --git a/sc/source/core/data/TableContentCopier.cxx b/sc/source/core/data/TableContentCopier.cxx new file mode 100644 index 000000000000..6a4a35d74351 --- /dev/null +++ b/sc/source/core/data/TableContentCopier.cxx @@ -0,0 +1,105 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +sc::TableContentCopier::TableContentCopier(ScDocument& rDoc, SCTAB nSourceTabNo, SCTAB nTargetTabNo) + : mrDoc(rDoc) + , mnSourceTabNo(nSourceTabNo) + , mnTargetTabNo(nTargetTabNo) + , mpSourceTab(mrDoc.FetchTable(nSourceTabNo)) + , mpTargetTab(mrDoc.FetchTable(nTargetTabNo)) +{ +} + +void sc::TableContentCopier::performCopy(const ScMarkData* pOnlyMarked, ScCloneFlags nCloneFlags, + SCTAB nPreviousSourceTabNo) +{ + if (nPreviousSourceTabNo < 0) + nPreviousSourceTabNo = mnSourceTabNo; + + const bool bGlobalNamesToLocal = true; + const ScRangeName* pNames = mrDoc.GetRangeName(mnSourceTabNo); + if (pNames) + pNames->CopyUsedNames(mnSourceTabNo, nPreviousSourceTabNo, mnTargetTabNo, mrDoc, mrDoc, + bGlobalNamesToLocal); + mrDoc.GetRangeName().CopyUsedNames(-1, nPreviousSourceTabNo, mnTargetTabNo, mrDoc, mrDoc, + bGlobalNamesToLocal); + + sc::CopyToDocContext aCopyDocCxt(mrDoc); + if (mrDoc.pDBCollection) + mrDoc.pDBCollection->CopyToTable(mnSourceTabNo, mnTargetTabNo); + mpSourceTab->CopyToTable(aCopyDocCxt, 0, 0, mrDoc.MaxCol(), mrDoc.MaxRow(), + InsertDeleteFlags::ALL, (pOnlyMarked != nullptr), mpTargetTab, + pOnlyMarked, false /*bAsLink*/, true /*bColRowFlags*/, nCloneFlags, + false /*bCopyCaptions*/); + mpTargetTab->SetTabBgColor(mpSourceTab->GetTabBgColor()); + + SCTAB nDz = mnTargetTabNo - mnSourceTabNo; + sc::RefUpdateContext aRefContext(mrDoc); + aRefContext.meMode = URM_COPY; + aRefContext.maRange + = ScRange(0, 0, mnTargetTabNo, mrDoc.MaxCol(), mrDoc.MaxRow(), mnTargetTabNo); + aRefContext.mnTabDelta = nDz; + mpTargetTab->UpdateReference(aRefContext); + + sc::SetFormulaDirtyContext aFormulaDirtyCxt; + mrDoc.SetAllFormulasDirty(aFormulaDirtyCxt); + + if (mrDoc.mpDrawLayer) // Skip cloning Note caption object + // page is already created in ScTable ctor + mrDoc.mpDrawLayer->ScCopyPage(static_cast(mnSourceTabNo), + static_cast(mnTargetTabNo)); + + if (mrDoc.pDPCollection) + mrDoc.pDPCollection->CopyToTab(mnSourceTabNo, mnTargetTabNo); + + mpTargetTab->SetPageStyle(mpSourceTab->GetPageStyle()); + mpTargetTab->SetPendingRowHeights(mpSourceTab->IsPendingRowHeights()); + + // Copy the custom print range if it exists. + mpTargetTab->CopyPrintRange(*mpSourceTab); + + // Copy the RTL settings + mpTargetTab->SetLayoutRTL(mpSourceTab->IsLayoutRTL()); + mpTargetTab->SetLoadingRTL(mpSourceTab->IsLoadingRTL()); + + // Finally copy the note captions, which need + // 1. the updated source ScColumn::nTab members if the target tab is before the source tab + // 2. row heights and column widths of the destination + // 3. RTL settings of the destination + mpSourceTab->CopyCaptionsToTable(0, 0, mrDoc.MaxCol(), mrDoc.MaxRow(), mpTargetTab, + true /*bCloneCaption*/); +} + +void sc::TableContentCopier::updateReferencesAfterTabInsertion( + sc::RefUpdateInsertTabContext& rContext) +{ + mpTargetTab->UpdateInsertTabAbs(mnTargetTabNo); + mpTargetTab->AdjustRelativeTabRefs(mnSourceTabNo, mnTargetTabNo, sc::TargetTabState::Inserted); + mpSourceTab->UpdateInsertTab(rContext); + mpSourceTab->UpdateCompile(); +} + +sc::TableContentCopier::~TableContentCopier() +{ + // maybe already compiled in Clone, but used names need recompilation + mpTargetTab->UpdateCompile(true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/TableStyleGenerator.cxx b/sc/source/core/data/TableStyleGenerator.cxx new file mode 100644 index 000000000000..6472d7d197e8 --- /dev/null +++ b/sc/source/core/data/TableStyleGenerator.cxx @@ -0,0 +1,360 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "defaulttablestyles.inc" + +namespace +{ +// OOXML theme index to model::ThemeColorType mapping +// (from spnColorTokens in stylesbuffer.cxx:266-268) +// Index: 0=lt1, 1=dk1, 2=lt2, 3=dk2, 4-9=accent1-6, 10=hlink, 11=folHlink +constexpr model::ThemeColorType aOoxmlIndexToThemeType[] = { + model::ThemeColorType::Light1, // 0 + model::ThemeColorType::Dark1, // 1 + model::ThemeColorType::Light2, // 2 + model::ThemeColorType::Dark2, // 3 + model::ThemeColorType::Accent1, // 4 + model::ThemeColorType::Accent2, // 5 + model::ThemeColorType::Accent3, // 6 + model::ThemeColorType::Accent4, // 7 + model::ThemeColorType::Accent5, // 8 + model::ThemeColorType::Accent6, // 9 + model::ThemeColorType::Hyperlink, // 10 + model::ThemeColorType::FollowedHyperlink, // 11 +}; + +struct ResolvedColor +{ + ::Color maColor; + model::ComplexColor maComplexColor; +}; + +struct FontData +{ + bool bBold = false; + ::Color maColor; + model::ComplexColor maComplexColor; +}; + +/// Build a ComplexColor from OOXML theme index + tint and resolve it. +/// Tint conversion replicates addExcelTintTransformation() from oox/source/drawingml/color.cxx. +ResolvedColor resolveThemeColor(const model::ColorSet& rColorSet, const ThemeColor& rThemeColor) +{ + ResolvedColor aResult; + + assert(rThemeColor.nThemeId >= 0 + && rThemeColor.nThemeId < static_cast(std::size(aOoxmlIndexToThemeType))); + model::ThemeColorType eType = aOoxmlIndexToThemeType[rThemeColor.nThemeId]; + + // Build ComplexColor with transforms in 10'000 scale (ComplexColor convention), + // converting from OOXML 100'000 scale used by addExcelTintTransformation(). + model::ComplexColor aComplexColor; + aComplexColor.setThemeColor(eType); + + double fTint = rThemeColor.fTint; + if (fTint > 0.0) + { + sal_Int32 nValue = std::round(std::abs(fTint) * 10'000.0); + aComplexColor.addTransformation({ model::TransformationType::LumMod, 10'000 - nValue }); + aComplexColor.addTransformation({ model::TransformationType::LumOff, nValue }); + } + else if (fTint < 0.0) + { + sal_Int32 nValue = std::round(std::abs(fTint) * 10'000.0); + aComplexColor.addTransformation({ model::TransformationType::LumMod, 10'000 - nValue }); + } + + aResult.maComplexColor = aComplexColor; + aResult.maColor = rColorSet.resolveOOXMLColor(aComplexColor); + + return aResult; +} + +// Use the exact same path as the oox filter: create a BorderLine2 and call +// SvxBoxItem::LineToSvxLine(). This guarantees identical SvxBorderLine results. +void setBorderLine(editeng::SvxBorderLine& rLine, const ResolvedColor& rColor, + BorderElementStyle eStyle) +{ + css::table::BorderLine2 bl2; + bl2.Color = sal_Int32(rColor.maColor); + bl2.OuterLineWidth = 0; + bl2.InnerLineWidth = 0; + bl2.LineDistance = 0; + bl2.LineStyle = 0; // css::table::BorderLineStyle::SOLID + bl2.LineWidth = 0; + + switch (eStyle) + { + case BorderElementStyle::THIN: + bl2.OuterLineWidth = SvxBorderLineWidth::Thin; + break; + case BorderElementStyle::MEDIUM: + bl2.OuterLineWidth = SvxBorderLineWidth::Medium; + break; + case BorderElementStyle::THICK: + bl2.OuterLineWidth = SvxBorderLineWidth::Thick; + break; + case BorderElementStyle::DOUBLE: + bl2.OuterLineWidth = SvxBorderLineWidth::VeryThin; + bl2.LineDistance = SvxBorderLineWidth::Thin; + bl2.InnerLineWidth = SvxBorderLineWidth::VeryThin; + bl2.LineStyle = sal_Int16(css::table::BorderLineStyle::DOUBLE_THIN); + break; + } + + SvxBoxItem::LineToSvxLine(bl2, rLine, false); + rLine.setComplexColor(rColor.maComplexColor); +} + +std::vector resolveColors(const model::ColorSet& rColorSet) +{ + size_t nColors = std::size(aThemeColors); + std::vector aColors(nColors); + for (size_t i = 0; i < nColors; ++i) + aColors[i] = resolveThemeColor(rColorSet, aThemeColors[i]); + return aColors; +} + +std::vector buildFills(const std::vector& rColors) +{ + size_t nFills = std::size(aFills); + std::vector aFillItems; + aFillItems.reserve(nFills); + for (size_t i = 0; i < nFills; ++i) + { + aFillItems.emplace_back(ATTR_BACKGROUND); + const ::Fill& rFill = aFills[i]; + aFillItems[i].SetColor(rColors[rFill.nFgColorId].maColor); + aFillItems[i].setComplexColor(rColors[rFill.nFgColorId].maComplexColor); + } + return aFillItems; +} + +void buildBorders(const std::vector& rColors, std::vector& rBoxItems, + std::vector& rBoxInfoItems) +{ + size_t nBorders = std::size(aBorders); + rBoxItems.clear(); + rBoxItems.reserve(nBorders); + rBoxInfoItems.clear(); + rBoxInfoItems.reserve(nBorders); + for (size_t i = 0; i < nBorders; ++i) + { + rBoxItems.emplace_back(ATTR_BORDER); + rBoxInfoItems.emplace_back(ATTR_BORDER_INNER); + } + + for (size_t i = 0; i < nBorders; ++i) + { + const ::Border& rBorder = aBorders[i]; + editeng::SvxBorderLine aLine; + + if (rBorder.nTopId >= 0) + { + const BorderElement& rElem = aBorderElements[rBorder.nTopId]; + setBorderLine(aLine, rColors[rElem.nColorId], rElem.eBorderStyle); + rBoxItems[i].SetLine(&aLine, SvxBoxItemLine::TOP); + } + if (rBorder.nBottomId >= 0) + { + const BorderElement& rElem = aBorderElements[rBorder.nBottomId]; + setBorderLine(aLine, rColors[rElem.nColorId], rElem.eBorderStyle); + rBoxItems[i].SetLine(&aLine, SvxBoxItemLine::BOTTOM); + } + if (rBorder.nLeftId >= 0) + { + const BorderElement& rElem = aBorderElements[rBorder.nLeftId]; + setBorderLine(aLine, rColors[rElem.nColorId], rElem.eBorderStyle); + rBoxItems[i].SetLine(&aLine, SvxBoxItemLine::LEFT); + } + if (rBorder.nRightId >= 0) + { + const BorderElement& rElem = aBorderElements[rBorder.nRightId]; + setBorderLine(aLine, rColors[rElem.nColorId], rElem.eBorderStyle); + rBoxItems[i].SetLine(&aLine, SvxBoxItemLine::RIGHT); + } + if (rBorder.nVerticalId >= 0) + { + const BorderElement& rElem = aBorderElements[rBorder.nVerticalId]; + setBorderLine(aLine, rColors[rElem.nColorId], rElem.eBorderStyle); + rBoxInfoItems[i].SetLine(&aLine, SvxBoxInfoItemLine::VERT); + } + if (rBorder.nHorizontalId >= 0) + { + const BorderElement& rElem = aBorderElements[rBorder.nHorizontalId]; + setBorderLine(aLine, rColors[rElem.nColorId], rElem.eBorderStyle); + rBoxInfoItems[i].SetLine(&aLine, SvxBoxInfoItemLine::HORI); + } + } +} + +std::vector buildFonts(const std::vector& rColors) +{ + size_t nFonts = std::size(aFonts); + std::vector aFontData(nFonts); + for (size_t i = 0; i < nFonts; ++i) + { + const ::Font& rFont = aFonts[i]; + aFontData[i].bBold = rFont.bBold; + aFontData[i].maColor = rColors[rFont.nThemeColorId].maColor; + aFontData[i].maComplexColor = rColors[rFont.nThemeColorId].maComplexColor; + } + return aFontData; +} + +std::vector> +buildDxfPatterns(ScDocument& rDoc, const std::vector& rFillItems, + const std::vector& rBoxItems, + const std::vector& rBoxInfoItems, + const std::vector& rFontData) +{ + size_t nDxfs = std::size(aDxfs); + std::vector> aDxfPatterns(nDxfs); + for (size_t i = 0; i < nDxfs; ++i) + { + const ::Dxf& rDxf = aDxfs[i]; + auto pPattern = std::make_unique(rDoc.getCellAttributeHelper()); + SfxItemSet& rItemSet = pPattern->GetItemSetWritable(); + + if (rDxf.nFillId >= 0) + rItemSet.Put(rFillItems[rDxf.nFillId]); + + if (rDxf.nBorderId >= 0) + { + const SvxBoxItem& rBox = rBoxItems[rDxf.nBorderId]; + bool bHasOuter + = rBox.GetLine(SvxBoxItemLine::TOP) || rBox.GetLine(SvxBoxItemLine::BOTTOM) + || rBox.GetLine(SvxBoxItemLine::LEFT) || rBox.GetLine(SvxBoxItemLine::RIGHT); + + if (bHasOuter) + rItemSet.Put(rBox); + + const SvxBoxInfoItem& rInfo = rBoxInfoItems[rDxf.nBorderId]; + if (rInfo.GetVert() || rInfo.GetHori()) + { + rItemSet.Put(rInfo); + } + } + + if (rDxf.nFontId >= 0) + { + const FontData& rFontInfo = rFontData[rDxf.nFontId]; + if (rFontInfo.bBold) + { + SvxWeightItem aWeight(WEIGHT_BOLD, ATTR_FONT_WEIGHT); + rItemSet.Put(aWeight); + rItemSet.Put(SvxWeightItem(WEIGHT_BOLD, ATTR_CJK_FONT_WEIGHT)); + rItemSet.Put(SvxWeightItem(WEIGHT_BOLD, ATTR_CTL_FONT_WEIGHT)); + } + SvxColorItem aColorItem(rFontInfo.maColor, rFontInfo.maComplexColor, ATTR_FONT_COLOR); + rItemSet.Put(aColorItem); + } + + aDxfPatterns[i] = std::move(pPattern); + } + return aDxfPatterns; +} + +TranslateId getCategoryTranslateId(TableStyleCategory eCategory) +{ + switch (eCategory) + { + case TableStyleCategory::Light: + return STR_TABLE_STYLE_LIGHT; + case TableStyleCategory::Medium: + return STR_TABLE_STYLE_MEDIUM; + case TableStyleCategory::Dark: + return STR_TABLE_STYLE_DARK; + } + SAL_WARN("sc", "getCategoryTranslateId: unknown TableStyleCategory"); + return {}; +} + +void assembleTableStyles(ScTableStyles& rTableStyles, + const std::vector>& rDxfPatterns) +{ + size_t nTableStyles = std::size(aTableStyles); + for (size_t i = 0; i < nTableStyles; ++i) + { + const ::TableStyle& rStyleInfo = aTableStyles[i]; + OUString aUIName = ScResId(getCategoryTranslateId(rStyleInfo.eCategory)) + " " + + OUString::number(rStyleInfo.nNumber); + auto pStyle = std::make_unique(OUString::createFromAscii(rStyleInfo.pName), + std::optional(aUIName)); + pStyle->SetOOXMLDefault(true); + + for (size_t j = 0; j < rStyleInfo.nElements; ++j) + { + const ::TableStyleElement& rElem + = aTableStyleElements[rStyleInfo.pTableStyleElementIds[j]]; + if (rDxfPatterns[rElem.nDxfId]) + { + auto pPatternCopy = std::make_unique(*rDxfPatterns[rElem.nDxfId]); + pStyle->SetPattern(rElem.eElement, std::move(pPatternCopy)); + } + } + + rTableStyles.AddTableStyle(std::move(pStyle)); + } +} + +} // end anonymous namespace + +void ScTableStyleGenerator::generateDefaultStyles(ScDocument& rDoc, + const model::ColorSet& rColorSet) +{ + ScTableStyles* pTableStyles = rDoc.GetTableStyles(); + if (!pTableStyles) + return; + + pTableStyles->ClearOOXMLDefaultStyles(); + + // Step 1: Resolve all theme colors + std::vector aColors = resolveColors(rColorSet); + + // Step 2: Build fill items (SvxBrushItem) + std::vector aFillItems = buildFills(aColors); + + // Step 3: Build border items (SvxBoxItem + SvxBoxInfoItem) + std::vector aBoxItems; + std::vector aBoxInfoItems; + buildBorders(aColors, aBoxItems, aBoxInfoItems); + + // Step 4: Build font data (bold + color) + std::vector aFontData = buildFonts(aColors); + + // Step 5: Build DXF patterns (ScPatternAttr) + std::vector> aDxfPatterns + = buildDxfPatterns(rDoc, aFillItems, aBoxItems, aBoxInfoItems, aFontData); + + // Step 6: Assemble table styles + assembleTableStyles(*pTableStyles, aDxfPatterns); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx index 0fbccbda8f21..db79f3d67a06 100644 --- a/sc/source/core/data/attarray.cxx +++ b/sc/source/core/data/attarray.cxx @@ -413,7 +413,7 @@ void ScAttrArray::RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow, std::unique_ptr pOldData; if (pDataArray) - pOldData = aCell.getEditText()->Clone(); + pOldData = std::make_unique(*aCell.getEditText()); // Direct modification of cell content - something to watch out for if // we decide to share edit text instances in the future. @@ -421,7 +421,7 @@ void ScAttrArray::RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow, if (pDataArray) { - std::unique_ptr pNewData = aCell.getEditText()->Clone(); + auto pNewData = std::make_unique(*aCell.getEditText()); pDataArray->AddItem(nTab, nCol, nRow, std::move(pOldData), std::move(pNewData)); } } @@ -1168,7 +1168,7 @@ bool ScAttrArray::ApplyFrame( const SvxBoxItem& rBoxItem, SvxBoxItem aNewFrame( *pOldFrame ); bool bRTL=rDocument.IsLayoutRTL(nTab); - // fdo#37464 check if the sheet are RTL then replace right <=> left + // fdo#37464 check if the sheet is RTL then replace right <=> left if (bRTL) { if( bLeft && nDistRight==0) @@ -1717,7 +1717,7 @@ void ScAttrArray::ChangeIndent( SCROW nStartRow, SCROW nEndRow, bool bIncrement pItem->GetValue() != SvxCellHorJustify::Right ); sal_uInt16 nOldValue = rOldSet.Get( ATTR_INDENT ).GetValue(); sal_uInt16 nNewValue = nOldValue; - // To keep Increment indent from running outside the cell1659 + // To keep Increment indent from running outside the cell tools::Long nColWidth = static_cast( rDocument.GetColWidth(nCol == -1 ? rDocument.MaxCol() : nCol,nTab)); if ( bIncrement ) diff --git a/sc/source/core/data/attrib.cxx b/sc/source/core/data/attrib.cxx index e70ed96c19d4..8773d0804370 100644 --- a/sc/source/core/data/attrib.cxx +++ b/sc/source/core/data/attrib.cxx @@ -400,11 +400,11 @@ ScPageHFItem::ScPageHFItem( const ScPageHFItem& rItem ) : SfxPoolItem ( rItem ) { if ( rItem.pLeftArea ) - pLeftArea = rItem.pLeftArea->Clone(); + pLeftArea = std::make_unique(*rItem.pLeftArea); if ( rItem.pCenterArea ) - pCenterArea = rItem.pCenterArea->Clone(); + pCenterArea = std::make_unique(*rItem.pCenterArea); if ( rItem.pRightArea ) - pRightArea = rItem.pRightArea->Clone(); + pRightArea = std::make_unique(*rItem.pRightArea); } ScPageHFItem::~ScPageHFItem() @@ -436,28 +436,28 @@ bool ScPageHFItem::PutValue( const uno::Any& rVal, sal_uInt8 /* nMemberId */ ) const EditTextObject* pImpLeft = pImp->GetLeftEditObject(); pLeftArea.reset(); if (pImpLeft) - pLeftArea = pImpLeft->Clone(); + pLeftArea = std::make_unique(*pImpLeft); const EditTextObject* pImpCenter = pImp->GetCenterEditObject(); pCenterArea.reset(); if (pImpCenter) - pCenterArea = pImpCenter->Clone(); + pCenterArea = std::make_unique(*pImpCenter); const EditTextObject* pImpRight = pImp->GetRightEditObject(); pRightArea.reset(); if (pImpRight) - pRightArea = pImpRight->Clone(); + pRightArea = std::make_unique(*pImpRight); if ( !pLeftArea || !pCenterArea || !pRightArea ) { // no Text with Null are left ScEditEngineDefaulter aEngine( EditEngine::CreatePool().get(), true ); if (!pLeftArea) - pLeftArea = aEngine.CreateTextObject(); + pLeftArea = std::make_unique(aEngine.CreateTextObject()); if (!pCenterArea) - pCenterArea = aEngine.CreateTextObject(); + pCenterArea = std::make_unique(aEngine.CreateTextObject()); if (!pRightArea) - pRightArea = aEngine.CreateTextObject(); + pRightArea = std::make_unique(aEngine.CreateTextObject()); } bRet = true; @@ -491,17 +491,17 @@ ScPageHFItem* ScPageHFItem::Clone( SfxItemPool* ) const void ScPageHFItem::SetLeftArea( const EditTextObject& rNew ) { - pLeftArea = rNew.Clone(); + pLeftArea = std::make_unique(rNew); } void ScPageHFItem::SetCenterArea( const EditTextObject& rNew ) { - pCenterArea = rNew.Clone(); + pCenterArea = std::make_unique(rNew); } void ScPageHFItem::SetRightArea( const EditTextObject& rNew ) { - pRightArea = rNew.Clone(); + pRightArea = std::make_unique(rNew); } void ScPageHFItem::dumpAsXml(xmlTextWriterPtr pWriter) const { diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx index b637158f39da..849fbf6826b5 100644 --- a/sc/source/core/data/cellvalue.cxx +++ b/sc/source/core/data/cellvalue.cxx @@ -167,7 +167,7 @@ bool hasStringImpl( CellType eType, ScFormulaCell* pFormula ) case CELLTYPE_EDIT: return true; case CELLTYPE_FORMULA: - return !pFormula->IsValue(); + return pFormula->IsString(); default: return false; } @@ -240,7 +240,7 @@ ScCellValue::ScCellValue( const ScRefCellValue& rCell ) maData = *rCell.getSharedString(); break; case CELLTYPE_EDIT: - maData = rCell.getEditText()->Clone().release(); + maData = new EditTextObject(*rCell.getEditText()); break; case CELLTYPE_FORMULA: maData = rCell.getFormula()->Clone(); @@ -266,7 +266,7 @@ ScCellValue::ScCellValue( const ScCellValue& r ) maData = *r.getSharedString(); break; case CELLTYPE_EDIT: - maData = r.getEditText()->Clone().release(); + maData = new EditTextObject(*r.getEditText()); break; case CELLTYPE_FORMULA: maData = r.getFormula()->Clone(); @@ -342,7 +342,13 @@ void ScCellValue::set( const svl::SharedString& rStr ) void ScCellValue::set( const EditTextObject& rEditText ) { clear(); - maData = rEditText.Clone().release(); + maData = new EditTextObject(rEditText); +} + +void ScCellValue::set( EditTextObject&& rEditText ) +{ + clear(); + maData = new EditTextObject(std::move(rEditText)); } void ScCellValue::set( std::unique_ptr xEditText ) @@ -369,7 +375,7 @@ void ScCellValue::assign( const ScDocument& rDoc, const ScAddress& rPos ) maData = *aRefVal.getSharedString(); break; case CELLTYPE_EDIT: - maData = aRefVal.getEditText() ? aRefVal.getEditText()->Clone().release() : static_cast(nullptr); + maData = aRefVal.getEditText() ? new EditTextObject(*aRefVal.getEditText()) : static_cast(nullptr); break; case CELLTYPE_VALUE: maData = aRefVal.getDouble(); @@ -402,14 +408,14 @@ void ScCellValue::assign(const ScCellValue& rOther, ScDocument& rDestDoc, ScClon if (bNewControl) rEngine.SetControlWord(nControl | nSpellControl); rEngine.SetTextCurrentDefaults(*rOther.getEditText()); - maData = rEngine.CreateTextObject().release(); + maData = new EditTextObject(rEngine.CreateTextObject()); if (bNewControl) rEngine.SetControlWord(nControl); } else { rEngine.SetTextCurrentDefaults(*rOther.getEditText()); - maData = rEngine.CreateTextObject().release(); + maData = new EditTextObject(rEngine.CreateTextObject()); } } break; @@ -436,7 +442,7 @@ void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const } break; case CELLTYPE_EDIT: - rDoc.SetEditText(rPos, getEditText()->Clone()); + rDoc.SetEditText(rPos, std::make_unique(*getEditText())); break; case CELLTYPE_VALUE: rDoc.SetValue(rPos, getDouble()); diff --git a/sc/source/core/data/cellvalues.cxx b/sc/source/core/data/cellvalues.cxx index d23d7a9eccca..8853fd2c0ec8 100644 --- a/sc/source/core/data/cellvalues.cxx +++ b/sc/source/core/data/cellvalues.cxx @@ -213,7 +213,7 @@ void CellValues::copyCellsTo( ScColumn& rCol, SCROW nRow ) const for (; it != itEnd; ++it) { const EditTextObject* p = *it; - aVals.push_back(p->Clone().release()); + aVals.push_back(new EditTextObject(*p)); } itPos = rDest.set(itPos, nCurRow, aVals.begin(), aVals.end()); } @@ -295,10 +295,10 @@ struct TableValues::Impl CellValues* getCellValues( SCTAB nTab, SCCOL nCol ) { if (nTab < maRange.aStart.Tab() || maRange.aEnd.Tab() < nTab) - // sheet index out of bound. + // sheet index out of bounds. return nullptr; if (nCol < maRange.aStart.Col() || maRange.aEnd.Col() < nCol) - // column index out of bound. + // column index out of bounds. return nullptr; size_t nTabOffset = nTab - maRange.aStart.Tab(); if (nTabOffset >= m_Tables.size()) diff --git a/sc/source/core/data/clipcontext.cxx b/sc/source/core/data/clipcontext.cxx index d1a439ba9ffa..b54f7c69b7bf 100644 --- a/sc/source/core/data/clipcontext.cxx +++ b/sc/source/core/data/clipcontext.cxx @@ -299,9 +299,9 @@ void CopyFromClipContext::setSingleCell( const ScAddress& rSrcPos, const ScColum // Turn this into a string or edit cell. if (rSrcCell.getFormula()->IsMultilineResult()) { - std::unique_ptr pObj(mrDestDoc.CreateSharedStringTextObject( + EditTextObject aObj(mrDestDoc.CreateSharedStringTextObject( rSrcCell.getFormula()->GetString())); - rSrcCell.set(*pObj); + rSrcCell.set(std::move(aObj)); } else rSrcCell.set(rSrcCell.getFormula()->GetString()); diff --git a/sc/source/core/data/colorscale.cxx b/sc/source/core/data/colorscale.cxx index 1aee0abc3d61..6b6989577e0a 100644 --- a/sc/source/core/data/colorscale.cxx +++ b/sc/source/core/data/colorscale.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -56,8 +57,8 @@ void ScFormulaListener::startListening(const ScTokenArray* pArr, const ScRange& { case formula::svSingleRef: { - ScAddress aCell = t->GetSingleRef()->toAbs(mrDoc, rRange.aStart); - ScAddress aCell2 = t->GetSingleRef()->toAbs(mrDoc, rRange.aEnd); + ScAddress aCell = static_cast(t)->GetSingleRef().toAbs(mrDoc, rRange.aStart); + ScAddress aCell2 = static_cast(t)->GetSingleRef().toAbs(mrDoc, rRange.aEnd); ScRange aRange(aCell, aCell2); if (aRange.IsValid()) mrDoc.StartListeningArea(aRange, false, this); @@ -65,8 +66,8 @@ void ScFormulaListener::startListening(const ScTokenArray* pArr, const ScRange& break; case formula::svDoubleRef: { - const ScSingleRefData& rRef1 = *t->GetSingleRef(); - const ScSingleRefData& rRef2 = *t->GetSingleRef2(); + const ScSingleRefData& rRef1 = static_cast(t)->GetSingleRef(); + const ScSingleRefData& rRef2 = static_cast(t)->GetSingleRef2(); ScAddress aCell1 = rRef1.toAbs(mrDoc, rRange.aStart); ScAddress aCell2 = rRef2.toAbs(mrDoc, rRange.aStart); ScAddress aCell3 = rRef1.toAbs(mrDoc, rRange.aEnd); diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index ae6f285ca87c..8bcb8f94bc23 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -202,16 +203,15 @@ bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark, const ScRange ScAddress aCurOrigin = aOrigin; bool bOpen = false; - for (size_t i = 0, n = rRangeList.size(); i < n; ++i) + for (const ScRange &rRange : rRangeList) { - const ScRange& r = rRangeList[i]; - if (nTab < r.aStart.Tab() || r.aEnd.Tab() < nTab) + if (nTab < rRange.aStart.Tab() || rRange.aEnd.Tab() < nTab) continue; - if (nCol < r.aStart.Col() || r.aEnd.Col() < nCol) + if (nCol < rRange.aStart.Col() || rRange.aEnd.Col() < nCol) continue; - SCROW nTop = r.aStart.Row(), nBottom = r.aEnd.Row(); + SCROW nTop = rRange.aStart.Row(), nBottom = rRange.aEnd.Row(); SCROW nRow = nTop; std::pair aPos = maCells.position(nRow); sc::CellStoreType::const_iterator it = aPos.first; @@ -785,7 +785,7 @@ public: std::vector aCloned; aCloned.reserve(nDataSize); for (; it != itEnd; ++it) - aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()).release()); + aCloned.push_back(new EditTextObject(ScEditUtil::Clone(**it, mrDestCol.GetDoc()))); maDestPos.miCellPos = mrDestCol.GetCellStore().set( maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end()); @@ -878,6 +878,8 @@ void ScColumn::CopyToClip( rCxt.isKeepScenarioFlags() ? (ScMF::All & ~ScMF::Scenario) : ScMF::All ); { + // Defer dynamic-array resizes so an Interpret in the walk cannot mutate maCells under the iterator. + sc::MatrixResizeGuard aMatrixResizeGuard(GetDoc()); CopyToClipHandler aFunc(GetDoc(), *this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol)); sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2); } @@ -907,6 +909,8 @@ void ScColumn::CopyStaticToDocument( aDestPos.miCellPos = rDestCol.maCells.begin(); ScDocument& rDocument = GetDoc(); + // Defer dynamic-array resizes so the block layout does not shift while the loop is walking it. + sc::MatrixResizeGuard aMatrixResizeGuard(rDocument); std::pair aPos = maCells.position(nRow1); sc::CellStoreType::const_iterator it = aPos.first; size_t nOffset = aPos.second; @@ -1034,9 +1038,9 @@ void ScColumn::CopyCellToDocument( SCROW nSrcRow, SCROW nDestRow, ScColumn& rDes { EditTextObject* p = sc::edittext_block::at(*it->data, aPos.second); if (&rDocument == &rDestCol.GetDoc()) - rDestCol.maCells.set(nDestRow, p->Clone().release()); + rDestCol.maCells.set(nDestRow, new EditTextObject(*p)); else - rDestCol.maCells.set(nDestRow, ScEditUtil::Clone(*p, rDestCol.GetDoc()).release()); + rDestCol.maCells.set(nDestRow, new EditTextObject(ScEditUtil::Clone(*p, rDestCol.GetDoc()))); } break; case sc::element_type_formula: @@ -1336,7 +1340,7 @@ class CopyByCloneHandler EditEngine& rEngine = mrDestCol.GetDoc().GetEditEngine(); rEngine.SetText(aStr.getString()); maDestPos.miCellPos = - mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rEngine.CreateTextObject().release()); + mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, new EditTextObject(rEngine.CreateTextObject())); } else { @@ -1349,14 +1353,14 @@ class CopyByCloneHandler public: CopyByCloneHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, - InsertDeleteFlags nCopyFlags, svl::SharedStringPool* pSharedStringPool, bool bGlobalNamesToLocal) : + InsertDeleteFlags nCopyFlags, svl::SharedStringPool* pSharedStringPool, ScCloneFlags nCloneFlags) : mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos), mpSharedStringPool(pSharedStringPool), mnCopyFlags(nCopyFlags), meListenType(sc::SingleCellListening), - mnFormulaCellCloneFlags(bGlobalNamesToLocal ? ScCloneFlags::NamesToLocal : ScCloneFlags::Default) + mnFormulaCellCloneFlags(nCloneFlags) { if (mpDestPos) maDestPos = *mpDestPos; @@ -1479,7 +1483,7 @@ public: std::vector aCloned; aCloned.reserve(nDataSize); for (; it != itEnd; ++it) - aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()).release()); + aCloned.push_back(new EditTextObject(ScEditUtil::Clone(**it, mrDestCol.GetDoc()))); maDestPos.miCellPos = mrDestCol.GetCellStore().set( maDestPos.miCellPos, nRow, aCloned.begin(), aCloned.end()); @@ -1522,7 +1526,7 @@ public: void ScColumn::CopyToColumn( sc::CopyToDocContext& rCxt, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, ScColumn& rColumn, - const ScMarkData* pMarkData, bool bAsLink, bool bGlobalNamesToLocal) const + const ScMarkData* pMarkData, bool bAsLink, ScCloneFlags nCloneFlags) const { if (bMarked) { @@ -1579,7 +1583,7 @@ void ScColumn::CopyToColumn( (GetDoc().GetPool() != rColumn.GetDoc().GetPool()) ? &rColumn.GetDoc().GetSharedStringPool() : nullptr; CopyByCloneHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags, - pSharedStringPool, bGlobalNamesToLocal); + pSharedStringPool, nCloneFlags); aFunc.setStartListening(rCxt.isStartListening()); sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2); } @@ -1615,6 +1619,8 @@ void ScColumn::CopyUpdated( const ScColumn* pPosCol, ScColumn& rDestCol ) const sc::SingleColumnSpanSet::SpansType aRanges; aRangeSet.getSpans(aRanges); + // Defer dynamic-array resizes so an Interpret in the walk cannot mutate maCells under the iterator. + sc::MatrixResizeGuard aMatrixResizeGuard(GetDoc()); CopyToClipHandler aFunc(GetDoc(), *this, rDestCol, nullptr); sc::CellStoreType::const_iterator itPos = maCells.begin(); for (const auto& rRange : aRanges) @@ -2368,7 +2374,7 @@ bool ScColumn::UpdateReference( sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc rCxt.maRange.aStart.Col() <= nCol && nCol <= rCxt.maRange.aEnd.Col()); if (bThisColShifted) { - // Cells in this column is being shifted. Split formula grouping at + // Cells in this column are being shifted. Split formula grouping at // the top and bottom boundaries before they get shifted. // Also, for deleted rows split at the top of the deleted area to adapt // the affected group length. @@ -2628,6 +2634,22 @@ public: } }; +/** For adjusting relative tab references. */ +class RelativeTabRefUpdater +{ + SCTAB mnOldTab; + SCTAB mnNewTab; + sc::TargetTabState meMode; +public: + RelativeTabRefUpdater(SCTAB nOldTab, SCTAB nNewTab, sc::TargetTabState eMode) : + mnOldTab(nOldTab), mnNewTab(nNewTab), meMode(eMode) {} + + void operator() (size_t /*nRow*/, ScFormulaCell* pCell) + { + pCell->AdjustRelativeTabRefs(mnOldTab, mnNewTab, meMode); + } +}; + class UsedRangeNameFinder { sc::UpdatedRangeNames& mrIndexes; @@ -2827,7 +2849,7 @@ struct CalcAllHandler if (pCell->GetCode()->IsRecalcModeNormal()) nNewVal = pCell->GetValue(); else - nNewVal = nOldVal; // random(), jetzt() etc. + nNewVal = nOldVal; // random(), now() etc. assert(nOldVal == nNewVal); #endif @@ -2967,7 +2989,7 @@ public: bool operator() (size_t nRow, const ScFormulaCell* p) { // With a formula cell, it's considered an edit text cell when either - // the result is multi-line or it has more than one script types. + // the result is multi-line or it has more than one script type. SvtScriptType nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow, miCellPos); if (IsAmbiguousScriptNonZero(nScriptType)) return true; @@ -3058,6 +3080,12 @@ void ScColumn::UpdateInsertTabAbs(SCTAB nNewPos) CellStorageModified(); } +void ScColumn::AdjustRelativeTabRefs(SCTAB nOldTab, SCTAB nNewTab, sc::TargetTabState eMode) +{ + RelativeTabRefUpdater aFunc(nOldTab, nNewTab, eMode); + sc::ProcessFormula(maCells, aFunc); +} + void ScColumn::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo ) { nTab = nTabNo; diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 99313224e3ef..8357a0e2c44d 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,10 @@ tools::Long ScColumn::GetNeededSize( if (bInPrintTwips) assert(pDev->GetMapMode().GetMapUnit() == MapUnit::MapTwip); + const bool bOld = pDev->isSubpixelPositioning(); + comphelper::ScopeGuard aSubpixelGuard([bOld, pDev] { pDev->setSubpixelPositioning(bOld); }); + pDev->setSubpixelPositioning(true); // force same subPixel calculations as LayoutStrings + std::pair aPos = maCells.position(nRow); sc::CellStoreType::const_iterator it = aPos.first; if (it == maCells.end() || it->type == sc::element_type_empty) @@ -1244,7 +1249,7 @@ public: // Overwrite the existing object. delete pObj; - pObj = mpEngine->CreateTextObject().release(); + pObj = new EditTextObject(mpEngine->CreateTextObject()); } else // create String { @@ -2701,6 +2706,8 @@ public: void ScColumn::FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nRow2, svl::SharedStringPool* pPool ) const { + // Defer dynamic-array resizes so an Interpret in the walk cannot mutate maCells under the iterator. + sc::MatrixResizeGuard aMatrixResizeGuard(GetDoc()); FillMatrixHandler aFunc(rMat, nMatCol, nRow1, GetDoc(), pPool); sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2); } @@ -3552,29 +3559,6 @@ void ScColumn::EndListening( sc::EndListeningContext& rCxt, const ScAddress& rAd rCxt.addEmptyBroadcasterPosition(rAddress.Tab(), rAddress.Col(), rAddress.Row()); } -void ScColumn::StartListeningSingleRefFormulaCells( sc::StartListeningContext& rCxt, - const ScSingleRefData* pRef, - const ScAddress& rAddress, ScFormulaCell** pp, ScFormulaCell** ppEnd ) -{ - sc::ColumnBlockPosition* p = rCxt.getBlockPosition(rAddress.Tab(), rAddress.Col()); - if (!p) - return; - sc::BroadcasterStoreType::iterator& it = p->miBroadcasterPos; - ScAddress aPos(rAddress); - for (; pp != ppEnd; ++pp) - { - if (!aPos.IsValid()) - break; - - std::pair aBroadcasterPos = maBroadcasters.position(it, aPos.Row()); - it = aBroadcasterPos.first; // store the block position for next iteration. - startListening(maBroadcasters, it, aBroadcasterPos.second, aPos.Row(), **pp); - - if (pRef->IsRowRel()) - aPos.IncRow(); - } -} - namespace { class CompileDBFormulaHandler @@ -3696,18 +3680,12 @@ void ScColumn::UpdateSelectionFunction( return; // nothing to do, bail out // Exclude all hidden rows. + ScFlatBoolRowSegments::RangeIterator aItr(rHiddenRows); ScFlatBoolRowSegments::RangeData aRange; - SCROW nRow = 0; - while (nRow <= GetDoc().MaxRow()) + for (bool bFound = aItr.getFirst(aRange); bFound; bFound = aItr.getNext(aRange)) { - if (!rHiddenRows.getRangeData(nRow, aRange)) - break; - if (aRange.mbValue) - // Hidden range detected. - aSpanSet.set(nRow, aRange.mnRow2, false); - - nRow = aRange.mnRow2 + 1; + aSpanSet.set(aRange.mnRow1, aRange.mnRow2, false); } sc::SingleColumnSpanSet::SpansType aSpans; diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 4fb7786879fa..cb7fff54a38e 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -185,6 +186,7 @@ void ScColumn::InterpretDirtyCells( SCROW nRow1, SCROW nRow2 ) if (!GetDoc().ValidRow(nRow1) || !GetDoc().ValidRow(nRow2) || nRow1 > nRow2) return; + sc::MatrixResizeGuard aGuard(GetDoc()); DirtyCellInterpreter aFunc; sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc); } @@ -194,6 +196,7 @@ bool ScColumn::InterpretCellsIfNeeded( SCROW nRow1, SCROW nRow2 ) if (!GetDoc().ValidRow(nRow1) || !GetDoc().ValidRow(nRow2) || nRow1 > nRow2) return false; + sc::MatrixResizeGuard aGuard(GetDoc()); NeedsInterpretCellInterpreter aFunc; sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc); return aFunc.allInterpreted; @@ -1775,7 +1778,7 @@ public: void operator() (size_t nRow, const EditTextObject* p) { - miNewCellsPos = maNewCells.set(miNewCellsPos, nRow-mnRowOffset, p->Clone().release()); + miNewCellsPos = maNewCells.set(miNewCellsPos, nRow-mnRowOffset, new EditTextObject(*p)); } void operator() (size_t nRow, const ScFormulaCell* p) @@ -1891,7 +1894,7 @@ public: { EditTextObject* pObj = sc::edittext_block::at(*aPos.first->data, aPos.second); miNewCellsPos = maNewCells.set( - miNewCellsPos, nDestRow-mnRowOffset, pObj->Clone().release()); + miNewCellsPos, nDestRow-mnRowOffset, new EditTextObject(*pObj)); } break; case sc::element_type_formula: @@ -2355,6 +2358,11 @@ bool ScColumn::SetString( SCROW nRow, SCTAB nTabP, const OUString& rString, return bNumFmtSet; } +void ScColumn::SetEditText( SCROW nRow, EditTextObject aEditText ) +{ + SetEditText(nRow, std::make_unique(std::move(aEditText))); +} + void ScColumn::SetEditText( SCROW nRow, std::unique_ptr pEditText ) { if (!pEditText) @@ -2394,7 +2402,7 @@ void ScColumn::SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, cons { if (GetDoc().GetEditEnginePool() == rEditText.GetPool()) { - SetEditText(rBlockPos, nRow, rEditText.Clone()); + SetEditText(rBlockPos, nRow, std::make_unique(rEditText)); return; } @@ -2406,11 +2414,27 @@ void ScColumn::SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, cons SetEditText(rBlockPos, nRow, rEngine.CreateTextObject()); } +void ScColumn::SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, EditTextObject&& rEditText ) +{ + if (GetDoc().GetEditEnginePool() == rEditText.GetPool()) + { + SetEditText(rBlockPos, nRow, std::make_unique(std::move(rEditText))); + return; + } + + // rats, yet another "spool" + // Sadly there is no other way to change the Pool than to + // "spool" the Object through a corresponding Engine + EditEngine& rEngine = GetDoc().GetEditEngine(); + rEngine.SetText(std::move(rEditText)); + SetEditText(rBlockPos, nRow, rEngine.CreateTextObject()); +} + void ScColumn::SetEditText( SCROW nRow, const EditTextObject& rEditText, const SfxItemPool* pEditPool ) { if (pEditPool && GetDoc().GetEditEnginePool() == pEditPool) { - SetEditText(nRow, rEditText.Clone()); + SetEditText(nRow, std::make_unique(rEditText)); return; } @@ -2721,98 +2745,79 @@ void ScColumn::GetBackColorFilterEntries(SCROW nRow1, SCROW nRow2, ScFilterEntri if (!GetDoc().ValidRow(nRow1) || !GetDoc().ValidRow(nRow2)) return; - ScAddress aCell(GetCol(), 0, GetTab()); ScDocument& rDoc = GetDoc(); - ScConditionalFormatList* pCondFormList = rDoc.GetCondFormList(aCell.Tab()); - // cache the output of GetCondResult - const ScPatternAttr* pPrevPattern = nullptr; - ScRefCellValue aPrevCellValue; - Color aPrevPatternColor; + ScConditionalFormatList* pCondFormList = rDoc.GetCondFormList(GetTab()); + Color aPrevInsertColor; - ScConditionalFormat* pCondFormat = nullptr; - const ScCondFormatIndexes* pCondFormats = nullptr; - Color aBackgroundBrushColor; - SCROW nPatternStartRow = -1; - SCROW nPatternEndRow = -1; - while (nRow1 <= nRow2) + bool bFirstInsert = true; + + // Iterate by pattern run rather than row by row: every empty cell in the + // same pattern run resolves to the same background colour, so a single CF + // evaluation per run is enough. Same idiom as ScColumn::GetUnprotectedCells. + SCROW nRow = nRow1; + while (nRow <= nRow2) { - aCell.SetRow(nRow1); + SCROW nPatternStartRow = nRow; + SCROW nPatternEndRow = nRow2; + const ScPatternAttr* pPattern = + pAttrArray->GetPatternRange(nPatternStartRow, nPatternEndRow, nRow); + if (!pPattern) + { + nRow = nPatternEndRow + 1; + continue; + } Color aBackColor; bool bCondBackColor = false; - if (nRow1 <= nPatternEndRow) - ; // then the previous value of pPattern and pCondFormat and pCondFormats and aBackgroundBrushColor is still valid - else - { - if (const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(nPatternStartRow, nPatternEndRow, nRow1)) - { - pCondFormats = &pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData(); - sal_uInt32 nIndex = 0; - if(!pCondFormats->empty()) - nIndex = (*pCondFormats)[0]; - if (nIndex) - { - assert(pCondFormList); - pCondFormat = pCondFormList->GetFormat( nIndex ); - } - else - pCondFormat = nullptr; - aBackgroundBrushColor = pPattern->GetItem(ATTR_BACKGROUND).GetColor(); + const ScCondFormatIndexes& rCondFormats = + pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData(); - if (!pCondFormats->empty()) - { - // Speed up processing when dealing with runs of identical cells. This avoids - // an expensive GetCondResult call. - ScRefCellValue aCellValue = GetCellValue(nRow1); - if (pPrevPattern == pPattern && aCellValue == aPrevCellValue) - { - aBackColor = aPrevPatternColor; - bCondBackColor = true; - } - else - { - const SfxItemSet* pCondSet = rDoc.GetCondResult(GetCol(), nRow1, GetTab()); - const SvxBrushItem* pCondBrush = &pPattern->GetItem(ATTR_BACKGROUND, pCondSet); - aBackColor = pCondBrush->GetColor(); - bCondBackColor = true; - aPrevCellValue = aCellValue; - pPrevPattern = pPattern; - aPrevPatternColor = aBackColor; - } - } - } - } - - if (pCondFormat) + if (!rCondFormats.empty()) { - for (size_t nFormat = 0; nFormat < pCondFormat->size(); nFormat++) + // Evaluate CF once for this pattern run. + const SfxItemSet* pCondSet = rDoc.GetCondResult(GetCol(), nRow, GetTab()); + const SvxBrushItem* pCondBrush = &pPattern->GetItem(ATTR_BACKGROUND, pCondSet); + aBackColor = pCondBrush->GetColor(); + bCondBackColor = true; + + // ColorScale CF entries override the resolved background colour. + sal_uInt32 nIndex = rCondFormats[0]; + if (nIndex && pCondFormList) { - auto aEntry = pCondFormat->GetEntry(nFormat); - if (aEntry->GetType() == ScFormatEntry::Type::Colorscale) + if (ScConditionalFormat* pCondFormat = pCondFormList->GetFormat(nIndex)) { - const ScColorScaleFormat* pColFormat = static_cast(aEntry); - std::optional oColor = pColFormat->GetColor(aCell); - if (oColor) + ScAddress aCell(GetCol(), nRow, GetTab()); + for (size_t nFormat = 0; nFormat < pCondFormat->size(); ++nFormat) { - aBackColor = *oColor; - bCondBackColor = true; + const ScFormatEntry* pEntry = pCondFormat->GetEntry(nFormat); + if (pEntry->GetType() == ScFormatEntry::Type::Colorscale) + { + const ScColorScaleFormat* pColFormat = + static_cast(pEntry); + std::optional oColor = pColFormat->GetColor(aCell); + if (oColor) + { + aBackColor = *oColor; + bCondBackColor = true; + } + } } } } } if (!bCondBackColor) - { - aBackColor = aBackgroundBrushColor; - } + aBackColor = pPattern->GetItem(ATTR_BACKGROUND).GetColor(); - if (aPrevInsertColor != aBackColor) + if (bFirstInsert || aPrevInsertColor != aBackColor) { rFilterEntries.addBackgroundColor(aBackColor); aPrevInsertColor = aBackColor; + bFirstInsert = false; } - nRow1++; + + nRow = nPatternEndRow + 1; } } diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx index 999cd804c13f..fd754d4450d6 100644 --- a/sc/source/core/data/column4.cxx +++ b/sc/source/core/data/column4.cxx @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -311,7 +312,7 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, std::vector aStrs; aStrs.reserve(nDestSize); for (size_t i = 0; i < nDestSize; ++i) - aStrs.push_back(rSrcCell.getEditText()->Clone().release()); + aStrs.push_back(new EditTextObject(*rSrcCell.getEditText())); pBlockPos->miCellPos = maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end()); @@ -504,8 +505,8 @@ public: case sc::FormulaResultValue::String: if (aRes.mbMultiLine) { - std::unique_ptr pObj(mrDoc.CreateSharedStringTextObject(aRes.maString)); - maResValues.setValue(nRow, std::move(pObj)); + EditTextObject aObj(mrDoc.CreateSharedStringTextObject(aRes.maString)); + maResValues.setValue(nRow, std::make_unique(std::move(aObj))); } else { @@ -912,7 +913,7 @@ bool ScColumn::HasCellNote(SCROW nStartRow, SCROW nEndRow) const void ScColumn::GetUnprotectedCells( SCROW nStartRow, SCROW nEndRow, ScRangeList& rRangeList ) const { SCROW nTmpStartRow = nStartRow, nTmpEndRow = nEndRow; - const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(nTmpStartRow, nTmpEndRow, nStartRow); + const ScPatternAttr* pPattern = GetPatternRange(nTmpStartRow, nTmpEndRow, nStartRow); bool bProtection = pPattern->GetItem(ATTR_PROTECTION).GetProtection(); if (!bProtection) { @@ -926,7 +927,7 @@ void ScColumn::GetUnprotectedCells( SCROW nStartRow, SCROW nEndRow, ScRangeList& while (nEndRow > nTmpEndRow) { nStartRow = nTmpEndRow + 1; - pPattern = pAttrArray->GetPatternRange(nTmpStartRow, nTmpEndRow, nStartRow); + pPattern = GetPatternRange(nTmpStartRow, nTmpEndRow, nStartRow); bool bTmpProtection = pPattern->GetItem(ATTR_PROTECTION).GetProtection(); if (!bTmpProtection) { @@ -1495,7 +1496,7 @@ public: continue; } - // If This is the last group in the range, see if the group + // If this is the last group in the range, see if the group // extends beyond the range, in which case have the excess // formula cells stop listening. size_t nEndGroupPos = (pp - ppBeg) + pFC->GetSharedLength(); @@ -2001,6 +2002,10 @@ bool ScColumn::EnsureFormulaCellResults( SCROW nRow1, SCROW nRow2, bool bSkipRun if (!HasFormulaCell(nRow1, nRow2)) return false; + // Guard against mid-iteration cell-store mutations that would invalidate + // lcl_EvalDirty's iterator. Pending resizes are drained when the guard goes + // out of scope. + sc::MatrixResizeGuard aGuard(GetDoc()); bool bAnyDirty = false, bTmp = false; lcl_EvalDirty(maCells, nRow1, nRow2, GetDoc(), nullptr, false, bSkipRunning, bAnyDirty, bTmp, nullptr); return bAnyDirty; @@ -2011,6 +2016,7 @@ bool ScColumn::HandleRefArrayForParallelism( SCROW nRow1, SCROW nRow2, const ScF if (nRow1 > nRow2) return false; + sc::MatrixResizeGuard aGuard(GetDoc()); bool bAllowThreading = true, bTmp = false; lcl_EvalDirty(maCells, nRow1, nRow2, GetDoc(), mxGroup, true, false, bTmp, bAllowThreading, pDirtiedAddress); diff --git a/sc/source/core/data/columniterator.cxx b/sc/source/core/data/columniterator.cxx index cec8f7a2028e..434c8a5d592d 100644 --- a/sc/source/core/data/columniterator.cxx +++ b/sc/source/core/data/columniterator.cxx @@ -50,7 +50,7 @@ void ScColumnTextWidthIterator::next() { if (miBlockCur->type != sc::element_type_celltextattr) { - // We don't iterator over this block. + // We don't iterate over this block. mnCurPos += miBlockCur->size; continue; } diff --git a/sc/source/core/data/compressedarray.cxx b/sc/source/core/data/compressedarray.cxx index 793b43b43a3b..6c4275d4aeb7 100644 --- a/sc/source/core/data/compressedarray.cxx +++ b/sc/source/core/data/compressedarray.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include @@ -82,7 +84,7 @@ void ScCompressedArray::SetValue( A nStart, A nEnd, const D& rValue ) if (nLimit < nNeeded) nLimit = nNeeded; std::unique_ptr pNewData(new DataEntry[nLimit]); - memcpy( pNewData.get(), pData.get(), nCount*sizeof(DataEntry)); + std::copy_n( pData.get(), nCount, pNewData.get()); pData = std::move(pNewData); } diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx index 58f2b09030ee..9f5880dd51d0 100644 --- a/sc/source/core/data/conditio.cxx +++ b/sc/source/core/data/conditio.cxx @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -90,15 +91,18 @@ static bool lcl_HasRelRef( ScDocument& rDoc, const ScTokenArray* pFormula, sal_u { case svDoubleRef: { - ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(t)->GetDoubleRef().Ref2; if ( rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel() ) return true; - [[fallthrough]]; + ScSingleRefData& rRef1 = static_cast(t)->GetSingleRef(); + if ( rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel() ) + return true; } + break; case svSingleRef: { - ScSingleRefData& rRef1 = *t->GetSingleRef(); + ScSingleRefData& rRef1 = static_cast(t)->GetSingleRef(); if ( rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel() ) return true; } @@ -107,9 +111,12 @@ static bool lcl_HasRelRef( ScDocument& rDoc, const ScTokenArray* pFormula, sal_u case svIndex: { if( t->GetOpCode() == ocName ) // DB areas always absolute - if( ScRangeData* pRangeData = rDoc.FindRangeNameBySheetAndIndex( t->GetSheet(), t->GetIndex()) ) + { + auto pIndexToken = static_cast(t); + if( ScRangeData* pRangeData = rDoc.FindRangeNameBySheetAndIndex( pIndexToken->GetSheet(), pIndexToken->GetIndex()) ) if( (nRecursion < 42) && lcl_HasRelRef( rDoc, pRangeData->GetCode(), nRecursion + 1 ) ) return true; + } } break; @@ -331,13 +338,14 @@ void ScConditionEntry::SimplifyCompiledFormula( std::unique_ptr& r if ( pToken->GetType() == svDouble ) { - rVal = pToken->GetDouble(); + rVal = static_cast(pToken)->GetDouble(); rFormula.reset(); // Do not remember as formula } else if ( pToken->GetType() == svString ) { rIsStr = true; - rStrVal = pToken->GetString().getString(); + assert(dynamic_cast(pToken)); + rStrVal = static_cast(pToken)->GetString().getString(); rFormula.reset(); // Do not remember as formula } } @@ -450,9 +458,7 @@ void ScConditionEntry::SetCaseSensitive(bool bSet) void ScConditionEntry::CompileAll() { pFCell1.reset(); - xRelRefCells1.reset(); pFCell2.reset(); - xRelRefCells2.reset(); } void ScConditionEntry::CompileXML() @@ -547,11 +553,7 @@ void ScConditionEntry::UpdateReference( sc::RefUpdateContext& rCxt ) } if (aRes.mbReferenceModified || bChangedPos) - { - // is created again in IsValid - pFCell1.reset(); - xRelRefCells1.reset(); - } + pFCell1.reset(); // is created again in IsValid } if (pFormula2) @@ -570,11 +572,7 @@ void ScConditionEntry::UpdateReference( sc::RefUpdateContext& rCxt ) } if (aRes.mbReferenceModified || bChangedPos) - { - // is created again in IsValid - pFCell2.reset(); - xRelRefCells2.reset(); - } + pFCell2.reset(); // is created again in IsValid } StartListening(); @@ -586,14 +584,12 @@ void ScConditionEntry::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ) { pFormula1->AdjustReferenceOnInsertedTab(rCxt, aSrcPos); pFCell1.reset(); - xRelRefCells1.reset(); } if (pFormula2) { pFormula2->AdjustReferenceOnInsertedTab(rCxt, aSrcPos); pFCell2.reset(); - xRelRefCells2.reset(); } ScRangeUpdater::UpdateInsertTab(aSrcPos, rCxt); @@ -605,14 +601,12 @@ void ScConditionEntry::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) { pFormula1->AdjustReferenceOnDeletedTab(rCxt, aSrcPos); pFCell1.reset(); - xRelRefCells1.reset(); } if (pFormula2) { pFormula2->AdjustReferenceOnDeletedTab(rCxt, aSrcPos); pFCell2.reset(); - xRelRefCells2.reset(); } ScRangeUpdater::UpdateDeleteTab(aSrcPos, rCxt); @@ -629,7 +623,6 @@ void ScConditionEntry::UpdateMoveTab(sc::RefUpdateMoveTabContext& rCxt) if (aRes.mbValueChanged) aResFinal.mnTab = aRes.mnTab; pFCell1.reset(); - xRelRefCells1.reset(); } if (pFormula2) @@ -638,7 +631,6 @@ void ScConditionEntry::UpdateMoveTab(sc::RefUpdateMoveTabContext& rCxt) if (aRes.mbValueChanged) aResFinal.mnTab = aRes.mnTab; pFCell2.reset(); - xRelRefCells2.reset(); } if (aResFinal.mnTab != aSrcPos.Tab()) @@ -685,12 +677,6 @@ bool ScConditionEntry::IsEqual( const ScFormatEntry& rOther, bool bIgnoreSrcPos return true; } -//static -std::unique_ptr ScConditionEntry::makeRelRefCells() -{ - return std::make_unique(0x9fff); -} - void ScConditionEntry::Interpret( const ScAddress& rPos ) { // Create formula cells @@ -701,25 +687,16 @@ void ScConditionEntry::Interpret( const ScAddress& rPos ) // Evaluate formulas bool bDirty = false; // 1 and 2 separate? + std::optional oTemp; ScFormulaCell* pEff1 = pFCell1.get(); if ( bRelRef1 ) { - if (!xRelRefCells1) - xRelRefCells1 = makeRelRefCells(); - auto iFind = xRelRefCells1->find(rPos); - if (iFind != xRelRefCells1->end()) - pEff1 = iFind->second.get(); + if (pFormula1) + oTemp.emplace(mrDoc, rPos, *pFormula1); else - { - std::unique_ptr xCell; - if (pFormula1) - xCell = std::make_unique(mrDoc, rPos, *pFormula1); - else - xCell = std::make_unique(mrDoc, rPos); - xCell->SetFreeFlying(true); - xCell->StartListeningTo(mrDoc); - pEff1 = xRelRefCells1->insert(std::make_pair(rPos, std::move(xCell)))->second.get(); - } + oTemp.emplace(mrDoc, rPos); + pEff1 = &*oTemp; + pEff1->SetFreeFlying(true); } if ( pEff1 ) { @@ -742,26 +719,17 @@ void ScConditionEntry::Interpret( const ScAddress& rPos ) } } } + oTemp.reset(); ScFormulaCell* pEff2 = pFCell2.get(); //@ 1!=2 if ( bRelRef2 ) { - if (!xRelRefCells2) - xRelRefCells2 = makeRelRefCells(); - auto iFind = xRelRefCells2->find(rPos); - if (iFind != xRelRefCells2->end()) - pEff2 = iFind->second.get(); + if (pFormula2) + oTemp.emplace(mrDoc, rPos, *pFormula2); else - { - std::unique_ptr xCell; - if (pFormula2) - xCell = std::make_unique(mrDoc, rPos, *pFormula2); - else - xCell = std::make_unique(mrDoc, rPos); - xCell->SetFreeFlying(true); - xCell->StartListeningTo(mrDoc); - pEff2 = xRelRefCells2->insert(std::make_pair(rPos, std::move(xCell)))->second.get(); - } + oTemp.emplace(mrDoc, rPos); + pEff2 = &*oTemp; + pEff2->SetFreeFlying(true); } if ( pEff2 ) { @@ -783,6 +751,7 @@ void ScConditionEntry::Interpret( const ScAddress& rPos ) } } } + oTemp.reset(); // If IsRunning, the last values remain if (bDirty && !bFirstRun) @@ -1419,9 +1388,9 @@ ScAddress ScConditionEntry::GetValidSrcPos() const { for ( auto t: pFormula->References() ) { - ScSingleRefData& rRef1 = *t->GetSingleRef(); - ScAddress aAbs = rRef1.toAbs(mrDoc, aSrcPos); - if (!rRef1.IsTabDeleted()) + ScSingleRefData* pRef1 = ScRefTokenHelper::getSingleRef(t); + ScAddress aAbs = pRef1->toAbs(mrDoc, aSrcPos); + if (!pRef1->IsTabDeleted()) { if (aAbs.Tab() < nMinTab) nMinTab = aAbs.Tab(); @@ -1430,7 +1399,7 @@ ScAddress ScConditionEntry::GetValidSrcPos() const } if ( t->GetType() == svDoubleRef ) { - ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(t)->GetDoubleRef().Ref2; aAbs = rRef2.toAbs(mrDoc, aSrcPos); if (!rRef2.IsTabDeleted()) { @@ -1597,47 +1566,16 @@ ScFormatEntry* ScCondFormatEntry::Clone( ScDocument& rDoc ) const void ScConditionEntry::CalcAll() { - if (pFCell1 || pFCell2 || xRelRefCells1 || !xRelRefCells2) + if (pFCell1 || pFCell2) { if (pFCell1) pFCell1->SetDirty(); - if (xRelRefCells1) - { - for (auto& rEntry : *xRelRefCells1) - rEntry.second->SetDirty(); - } if (pFCell2) pFCell2->SetDirty(); - if (xRelRefCells2) - { - for (auto& rEntry : *xRelRefCells2) - rEntry.second->SetDirty(); - } pCondFormat->DoRepaint(); } } -OUString ScConditionEntry::getCacheName() const -{ - return "ScConditionEntry"; -} - -bool ScConditionEntry::dropCaches() -{ - xRelRefCells1.reset(); - xRelRefCells2.reset(); - return true; -} - -void ScConditionEntry::dumpState(rtl::OStringBuffer& rState) -{ - rState.append("\nScConditionEntry:"); - rState.append("\n\t rel ref cells1: "); - rState.append(xRelRefCells1 ? static_cast(xRelRefCells1->size()) : 0); - rState.append("\n\t rel ref cells2: "); - rState.append(xRelRefCells2 ? static_cast(xRelRefCells2->size()) : 0); -} - ScCondDateFormatEntry::ScCondDateFormatEntry( ScDocument& rDoc ) : ScFormatEntry( rDoc ) , meType(condformat::TODAY) diff --git a/sc/source/filter/oox/defaulttablestyles.inc b/sc/source/core/data/defaulttablestyles.inc similarity index 75% rename from sc/source/filter/oox/defaulttablestyles.inc rename to sc/source/core/data/defaulttablestyles.inc index 692472c0ef7d..2cf41369fbef 100644 --- a/sc/source/filter/oox/defaulttablestyles.inc +++ b/sc/source/core/data/defaulttablestyles.inc @@ -10,12 +10,12 @@ // WARNING: This file is automatically generated and should not be manually edited! -#include +#include constexpr ThemeColor aThemeColors[] = { { 0, -0.3499862666707358f }, { 0, -0.1499984740745262f }, { 0, 0.0f }, { 1, 0.0f }, { 1, 0.1499984740745262f }, { 1, 0.249977111117893f }, { 1, 0.4499954222235786f }, { 4, -0.499984740745262f }, { 4, -0.249977111117893f }, { 4, 0.0f }, { 4, 0.3999755851924192f }, { 4, 0.5999938962981048f }, { 4, 0.7999816888943144f }, { 5, -0.499984740745262f }, { 5, -0.249977111117893f }, { 5, 0.0f }, { 5, 0.3999755851924192f }, { 5, 0.5999938962981048f }, { 5, 0.7999816888943144f }, { 6, -0.499984740745262f }, { 6, -0.249977111117893f }, { 6, 0.0f }, { 6, 0.3999755851924192f }, { 6, 0.5999938962981048f }, { 6, 0.7999816888943144f }, { 7, -0.499984740745262f }, { 7, -0.249977111117893f }, { 7, 0.0f }, { 7, 0.3999755851924192f }, { 7, 0.5999938962981048f }, { 7, 0.7999816888943144f }, { 8, -0.499984740745262f }, { 8, -0.249977111117893f }, { 8, 0.0f }, { 8, 0.3999755851924192f }, { 8, 0.5999938962981048f }, { 8, 0.7999816888943144f }, { 9, -0.499984740745262f }, { 9, -0.249977111117893f }, { 9, 0.0f }, { 9, 0.3999755851924192f }, { 9, 0.5999938962981048f }, { 9, 0.7999816888943144f } }; -constexpr Fill aFills[] = { { 0, 0 }, { 1, 1 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 8, 8 }, { 9, 9 }, { 11, 11 }, { 12, 12 }, { 13, 13 }, { 14, 14 }, { 15, 15 }, { 17, 17 }, { 18, 18 }, { 19, 19 }, { 20, 20 }, { 21, 21 }, { 23, 23 }, { 24, 24 }, { 25, 25 }, { 26, 26 }, { 27, 27 }, { 29, 29 }, { 30, 30 }, { 31, 31 }, { 32, 32 }, { 33, 33 }, { 35, 35 }, { 36, 36 }, { 37, 37 }, { 38, 38 }, { 39, 39 }, { 41, 41 }, { 42, 42 } }; +constexpr Fill aFills[] = { { 0 }, { 1 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }, { 9 }, { 11 }, { 12 }, { 13 }, { 14 }, { 15 }, { 17 }, { 18 }, { 19 }, { 20 }, { 21 }, { 23 }, { 24 }, { 25 }, { 26 }, { 27 }, { 29 }, { 30 }, { 31 }, { 32 }, { 33 }, { 35 }, { 36 }, { 37 }, { 38 }, { 39 }, { 41 }, { 42 } }; constexpr Font aFonts[] = { { false, 2 }, { false, 3 }, { false, 8 }, { false, 14 }, { false, 20 }, { false, 26 }, { false, 32 }, { false, 38 }, { true, 2 }, { true, 3 }, { true, 8 }, { true, 14 }, { true, 20 }, { true, 26 }, { true, 32 }, { true, 38 } }; @@ -27,7 +27,7 @@ constexpr Dxf aDxfs[] = { { -1, 2, -1 }, { -1, 3, -1 }, { -1, 4, -1 }, { -1, 5, constexpr TableStyleElement aTableStyleElements[] = { { ScTableStyleElement::FirstColumnStripe, 0 }, { ScTableStyleElement::SecondColumnStripe, 0 }, { ScTableStyleElement::FirstColumnStripe, 1 }, { ScTableStyleElement::SecondColumnStripe, 1 }, { ScTableStyleElement::FirstColumnStripe, 2 }, { ScTableStyleElement::SecondColumnStripe, 2 }, { ScTableStyleElement::FirstColumnStripe, 3 }, { ScTableStyleElement::SecondColumnStripe, 3 }, { ScTableStyleElement::FirstColumnStripe, 4 }, { ScTableStyleElement::SecondColumnStripe, 4 }, { ScTableStyleElement::FirstColumnStripe, 5 }, { ScTableStyleElement::SecondColumnStripe, 5 }, { ScTableStyleElement::FirstColumnStripe, 6 }, { ScTableStyleElement::SecondColumnStripe, 6 }, { ScTableStyleElement::FirstRowStripe, 7 }, { ScTableStyleElement::SecondRowStripe, 7 }, { ScTableStyleElement::FirstRowStripe, 8 }, { ScTableStyleElement::SecondRowStripe, 8 }, { ScTableStyleElement::FirstRowStripe, 9 }, { ScTableStyleElement::SecondRowStripe, 9 }, { ScTableStyleElement::FirstRowStripe, 10 }, { ScTableStyleElement::SecondRowStripe, 10 }, { ScTableStyleElement::FirstRowStripe, 11 }, { ScTableStyleElement::SecondRowStripe, 11 }, { ScTableStyleElement::FirstRowStripe, 12 }, { ScTableStyleElement::SecondRowStripe, 12 }, { ScTableStyleElement::FirstRowStripe, 13 }, { ScTableStyleElement::SecondRowStripe, 13 }, { ScTableStyleElement::TotalRow, 14 }, { ScTableStyleElement::FirstColumnStripe, 15 }, { ScTableStyleElement::FirstRowStripe, 15 }, { ScTableStyleElement::WholeTable, 16 }, { ScTableStyleElement::FirstColumnStripe, 16 }, { ScTableStyleElement::FirstRowStripe, 16 }, { ScTableStyleElement::FirstColumnStripe, 17 }, { ScTableStyleElement::FirstRowStripe, 17 }, { ScTableStyleElement::FirstColumnStripe, 18 }, { ScTableStyleElement::FirstRowStripe, 18 }, { ScTableStyleElement::FirstColumnStripe, 19 }, { ScTableStyleElement::FirstRowStripe, 19 }, { ScTableStyleElement::WholeTable, 20 }, { ScTableStyleElement::FirstColumnStripe, 20 }, { ScTableStyleElement::FirstRowStripe, 20 }, { ScTableStyleElement::FirstColumnStripe, 21 }, { ScTableStyleElement::FirstRowStripe, 21 }, { ScTableStyleElement::FirstColumnStripe, 22 }, { ScTableStyleElement::FirstRowStripe, 22 }, { ScTableStyleElement::FirstColumnStripe, 23 }, { ScTableStyleElement::FirstRowStripe, 23 }, { ScTableStyleElement::FirstColumnStripe, 24 }, { ScTableStyleElement::FirstRowStripe, 24 }, { ScTableStyleElement::FirstColumnStripe, 25 }, { ScTableStyleElement::FirstRowStripe, 25 }, { ScTableStyleElement::WholeTable, 26 }, { ScTableStyleElement::FirstColumnStripe, 26 }, { ScTableStyleElement::FirstRowStripe, 26 }, { ScTableStyleElement::FirstColumnStripe, 27 }, { ScTableStyleElement::FirstRowStripe, 27 }, { ScTableStyleElement::FirstColumnStripe, 28 }, { ScTableStyleElement::FirstRowStripe, 28 }, { ScTableStyleElement::FirstColumnStripe, 29 }, { ScTableStyleElement::FirstRowStripe, 29 }, { ScTableStyleElement::FirstColumnStripe, 30 }, { ScTableStyleElement::FirstRowStripe, 30 }, { ScTableStyleElement::FirstColumnStripe, 31 }, { ScTableStyleElement::FirstRowStripe, 31 }, { ScTableStyleElement::WholeTable, 32 }, { ScTableStyleElement::FirstColumnStripe, 32 }, { ScTableStyleElement::FirstRowStripe, 32 }, { ScTableStyleElement::FirstColumnStripe, 33 }, { ScTableStyleElement::FirstRowStripe, 33 }, { ScTableStyleElement::FirstColumnStripe, 34 }, { ScTableStyleElement::FirstRowStripe, 34 }, { ScTableStyleElement::FirstColumnStripe, 35 }, { ScTableStyleElement::FirstRowStripe, 35 }, { ScTableStyleElement::HeaderRow, 36 }, { ScTableStyleElement::WholeTable, 37 }, { ScTableStyleElement::WholeTable, 38 }, { ScTableStyleElement::WholeTable, 39 }, { ScTableStyleElement::HeaderRow, 39 }, { ScTableStyleElement::WholeTable, 40 }, { ScTableStyleElement::WholeTable, 41 }, { ScTableStyleElement::HeaderRow, 41 }, { ScTableStyleElement::WholeTable, 42 }, { ScTableStyleElement::WholeTable, 43 }, { ScTableStyleElement::HeaderRow, 43 }, { ScTableStyleElement::WholeTable, 44 }, { ScTableStyleElement::WholeTable, 45 }, { ScTableStyleElement::WholeTable, 46 }, { ScTableStyleElement::WholeTable, 47 }, { ScTableStyleElement::WholeTable, 48 }, { ScTableStyleElement::WholeTable, 49 }, { ScTableStyleElement::WholeTable, 50 }, { ScTableStyleElement::WholeTable, 51 }, { ScTableStyleElement::WholeTable, 52 }, { ScTableStyleElement::WholeTable, 53 }, { ScTableStyleElement::WholeTable, 54 }, { ScTableStyleElement::WholeTable, 55 }, { ScTableStyleElement::WholeTable, 56 }, { ScTableStyleElement::WholeTable, 57 }, { ScTableStyleElement::WholeTable, 58 }, { ScTableStyleElement::WholeTable, 59 }, { ScTableStyleElement::WholeTable, 60 }, { ScTableStyleElement::WholeTable, 61 }, { ScTableStyleElement::WholeTable, 62 }, { ScTableStyleElement::WholeTable, 63 }, { ScTableStyleElement::WholeTable, 64 }, { ScTableStyleElement::WholeTable, 65 }, { ScTableStyleElement::WholeTable, 66 }, { ScTableStyleElement::WholeTable, 67 }, { ScTableStyleElement::WholeTable, 68 }, { ScTableStyleElement::WholeTable, 69 }, { ScTableStyleElement::WholeTable, 70 }, { ScTableStyleElement::WholeTable, 71 }, { ScTableStyleElement::WholeTable, 72 }, { ScTableStyleElement::WholeTable, 73 }, { ScTableStyleElement::WholeTable, 74 }, { ScTableStyleElement::WholeTable, 75 }, { ScTableStyleElement::WholeTable, 76 }, { ScTableStyleElement::WholeTable, 77 }, { ScTableStyleElement::WholeTable, 78 }, { ScTableStyleElement::WholeTable, 79 }, { ScTableStyleElement::WholeTable, 80 }, { ScTableStyleElement::WholeTable, 81 }, { ScTableStyleElement::WholeTable, 82 }, { ScTableStyleElement::WholeTable, 83 }, { ScTableStyleElement::WholeTable, 84 }, { ScTableStyleElement::WholeTable, 85 }, { ScTableStyleElement::WholeTable, 86 }, { ScTableStyleElement::WholeTable, 87 }, { ScTableStyleElement::LastColumn, 88 }, { ScTableStyleElement::FirstColumn, 88 }, { ScTableStyleElement::HeaderRow, 88 }, { ScTableStyleElement::HeaderRow, 89 }, { ScTableStyleElement::HeaderRow, 90 }, { ScTableStyleElement::HeaderRow, 91 }, { ScTableStyleElement::TotalRow, 92 }, { ScTableStyleElement::TotalRow, 93 }, { ScTableStyleElement::FirstColumn, 94 }, { ScTableStyleElement::LastColumn, 95 }, { ScTableStyleElement::TotalRow, 96 }, { ScTableStyleElement::FirstColumn, 97 }, { ScTableStyleElement::LastColumn, 98 }, { ScTableStyleElement::LastColumn, 99 }, { ScTableStyleElement::FirstColumn, 99 }, { ScTableStyleElement::HeaderRow, 99 }, { ScTableStyleElement::HeaderRow, 100 }, { ScTableStyleElement::HeaderRow, 101 }, { ScTableStyleElement::TotalRow, 102 }, { ScTableStyleElement::TotalRow, 103 }, { ScTableStyleElement::FirstColumn, 104 }, { ScTableStyleElement::LastColumn, 105 }, { ScTableStyleElement::LastColumn, 106 }, { ScTableStyleElement::FirstColumn, 106 }, { ScTableStyleElement::HeaderRow, 106 }, { ScTableStyleElement::HeaderRow, 107 }, { ScTableStyleElement::HeaderRow, 108 }, { ScTableStyleElement::TotalRow, 109 }, { ScTableStyleElement::TotalRow, 110 }, { ScTableStyleElement::FirstColumn, 111 }, { ScTableStyleElement::LastColumn, 112 }, { ScTableStyleElement::LastColumn, 113 }, { ScTableStyleElement::FirstColumn, 113 }, { ScTableStyleElement::HeaderRow, 113 }, { ScTableStyleElement::HeaderRow, 114 }, { ScTableStyleElement::HeaderRow, 115 }, { ScTableStyleElement::TotalRow, 116 }, { ScTableStyleElement::TotalRow, 117 }, { ScTableStyleElement::FirstColumn, 118 }, { ScTableStyleElement::LastColumn, 119 }, { ScTableStyleElement::LastColumn, 120 }, { ScTableStyleElement::FirstColumn, 120 }, { ScTableStyleElement::HeaderRow, 120 }, { ScTableStyleElement::HeaderRow, 121 }, { ScTableStyleElement::HeaderRow, 122 }, { ScTableStyleElement::TotalRow, 123 }, { ScTableStyleElement::TotalRow, 124 }, { ScTableStyleElement::FirstColumn, 125 }, { ScTableStyleElement::LastColumn, 126 }, { ScTableStyleElement::LastColumn, 127 }, { ScTableStyleElement::FirstColumn, 127 }, { ScTableStyleElement::HeaderRow, 127 }, { ScTableStyleElement::HeaderRow, 128 }, { ScTableStyleElement::HeaderRow, 129 }, { ScTableStyleElement::TotalRow, 130 }, { ScTableStyleElement::TotalRow, 131 }, { ScTableStyleElement::FirstColumn, 132 }, { ScTableStyleElement::LastColumn, 133 }, { ScTableStyleElement::LastColumn, 134 }, { ScTableStyleElement::FirstColumn, 134 }, { ScTableStyleElement::HeaderRow, 134 }, { ScTableStyleElement::HeaderRow, 135 }, { ScTableStyleElement::HeaderRow, 136 }, { ScTableStyleElement::TotalRow, 137 }, { ScTableStyleElement::LastColumn, 138 }, { ScTableStyleElement::FirstColumn, 138 }, { ScTableStyleElement::HeaderRow, 138 }, { ScTableStyleElement::HeaderRow, 139 }, { ScTableStyleElement::HeaderRow, 140 }, { ScTableStyleElement::HeaderRow, 141 }, { ScTableStyleElement::HeaderRow, 142 }, { ScTableStyleElement::HeaderRow, 143 }, { ScTableStyleElement::HeaderRow, 144 }, { ScTableStyleElement::HeaderRow, 145 }, { ScTableStyleElement::HeaderRow, 146 }, { ScTableStyleElement::TotalRow, 147 }, { ScTableStyleElement::TotalRow, 148 }, { ScTableStyleElement::TotalRow, 149 }, { ScTableStyleElement::TotalRow, 150 }, { ScTableStyleElement::TotalRow, 151 }, { ScTableStyleElement::TotalRow, 152 }, { ScTableStyleElement::TotalRow, 153 }, { ScTableStyleElement::TotalRow, 154 }, { ScTableStyleElement::TotalRow, 155 }, { ScTableStyleElement::TotalRow, 156 }, { ScTableStyleElement::TotalRow, 157 }, { ScTableStyleElement::TotalRow, 158 }, { ScTableStyleElement::TotalRow, 159 }, { ScTableStyleElement::TotalRow, 160 }, { ScTableStyleElement::TotalRow, 161 }, { ScTableStyleElement::LastColumn, 162 }, { ScTableStyleElement::FirstColumn, 162 }, { ScTableStyleElement::HeaderRow, 163 }, { ScTableStyleElement::TotalRow, 164 }, { ScTableStyleElement::LastColumn, 165 }, { ScTableStyleElement::FirstColumn, 165 }, { ScTableStyleElement::HeaderRow, 166 }, { ScTableStyleElement::TotalRow, 167 }, { ScTableStyleElement::LastColumn, 168 }, { ScTableStyleElement::FirstColumn, 168 }, { ScTableStyleElement::HeaderRow, 169 }, { ScTableStyleElement::TotalRow, 170 }, { ScTableStyleElement::LastColumn, 171 }, { ScTableStyleElement::FirstColumn, 171 }, { ScTableStyleElement::HeaderRow, 172 }, { ScTableStyleElement::TotalRow, 173 }, { ScTableStyleElement::LastColumn, 174 }, { ScTableStyleElement::FirstColumn, 174 }, { ScTableStyleElement::HeaderRow, 175 }, { ScTableStyleElement::TotalRow, 176 }, { ScTableStyleElement::LastColumn, 177 }, { ScTableStyleElement::FirstColumn, 177 }, { ScTableStyleElement::HeaderRow, 178 }, { ScTableStyleElement::TotalRow, 179 } }; -constexpr TableStyle aTableStyles[] = { { "TableStyleDark1", 7, { 76, 133, 137, 138, 139, 35, 34 } }, { "TableStyleDark10", 7, { 53, 82, 213, 195, 194, 52, 51 } }, { "TableStyleDark11", 7, { 66, 85, 213, 195, 194, 65, 64 } }, { "TableStyleDark2", 7, { 77, 133, 140, 141, 142, 37, 36 } }, { "TableStyleDark3", 7, { 78, 133, 149, 150, 151, 44, 43 } }, { "TableStyleDark4", 7, { 80, 133, 158, 159, 160, 50, 49 } }, { "TableStyleDark5", 7, { 81, 133, 167, 168, 169, 57, 56 } }, { "TableStyleDark6", 7, { 83, 133, 176, 177, 178, 63, 62 } }, { "TableStyleDark7", 7, { 84, 133, 185, 186, 187, 70, 69 } }, { "TableStyleDark8", 7, { 31, 75, 213, 195, 194, 30, 29 } }, { "TableStyleDark9", 7, { 40, 79, 213, 195, 194, 39, 38 } }, { "TableStyleLight1", 7, { 86, 197, 205, 195, 194, 33, 32 } }, { "TableStyleLight10", 9, { 93, 154, 215, 195, 194, 18, 19, 4, 5 } }, { "TableStyleLight11", 9, { 96, 163, 216, 195, 194, 20, 21, 6, 7 } }, { "TableStyleLight12", 9, { 99, 172, 217, 195, 194, 22, 23, 8, 9 } }, { "TableStyleLight13", 9, { 102, 181, 218, 195, 194, 24, 25, 10, 11 } }, { "TableStyleLight14", 9, { 105, 190, 219, 195, 194, 26, 27, 12, 13 } }, { "TableStyleLight15", 7, { 89, 198, 213, 195, 194, 33, 32 } }, { "TableStyleLight16", 7, { 91, 199, 214, 195, 194, 42, 41 } }, { "TableStyleLight17", 7, { 94, 200, 215, 195, 194, 48, 47 } }, { "TableStyleLight18", 7, { 97, 201, 216, 195, 194, 55, 54 } }, { "TableStyleLight19", 7, { 100, 202, 217, 195, 194, 61, 60 } }, { "TableStyleLight2", 7, { 124, 222, 223, 221, 220, 42, 41 } }, { "TableStyleLight20", 7, { 103, 203, 218, 195, 194, 68, 67 } }, { "TableStyleLight21", 7, { 106, 204, 219, 195, 194, 74, 73 } }, { "TableStyleLight3", 7, { 125, 226, 227, 225, 224, 48, 47 } }, { "TableStyleLight4", 7, { 126, 230, 231, 229, 228, 55, 54 } }, { "TableStyleLight5", 7, { 127, 234, 235, 233, 232, 61, 60 } }, { "TableStyleLight6", 7, { 128, 238, 239, 237, 236, 68, 67 } }, { "TableStyleLight7", 7, { 129, 242, 243, 241, 240, 74, 73 } }, { "TableStyleLight8", 9, { 87, 132, 213, 195, 194, 14, 15, 0, 1 } }, { "TableStyleLight9", 9, { 90, 145, 214, 195, 194, 16, 17, 2, 3 } }, { "TableStyleMedium1", 7, { 88, 132, 213, 195, 194, 33, 32 } }, { "TableStyleMedium10", 7, { 114, 156, 157, 153, 152, 46, 45 } }, { "TableStyleMedium11", 7, { 116, 165, 166, 162, 161, 52, 51 } }, { "TableStyleMedium12", 7, { 118, 174, 175, 171, 170, 59, 58 } }, { "TableStyleMedium13", 7, { 120, 183, 184, 180, 179, 65, 64 } }, { "TableStyleMedium14", 7, { 122, 192, 193, 189, 188, 72, 71 } }, { "TableStyleMedium15", 7, { 109, 134, 28, 131, 130, 33, 32 } }, { "TableStyleMedium16", 7, { 108, 146, 28, 144, 143, 33, 32 } }, { "TableStyleMedium17", 7, { 108, 155, 28, 153, 152, 33, 32 } }, { "TableStyleMedium18", 7, { 108, 164, 28, 162, 161, 33, 32 } }, { "TableStyleMedium19", 7, { 108, 173, 28, 171, 170, 33, 32 } }, { "TableStyleMedium2", 7, { 92, 145, 214, 195, 194, 42, 41 } }, { "TableStyleMedium20", 7, { 108, 182, 28, 180, 179, 33, 32 } }, { "TableStyleMedium21", 7, { 108, 191, 28, 189, 188, 33, 32 } }, { "TableStyleMedium22", 7, { 111, 196, 206, 195, 194, 30, 29 } }, { "TableStyleMedium23", 7, { 113, 196, 207, 195, 194, 39, 38 } }, { "TableStyleMedium24", 7, { 115, 196, 208, 195, 194, 46, 45 } }, { "TableStyleMedium25", 7, { 117, 196, 209, 195, 194, 52, 51 } }, { "TableStyleMedium26", 7, { 119, 196, 210, 195, 194, 59, 58 } }, { "TableStyleMedium27", 7, { 121, 196, 211, 195, 194, 65, 64 } }, { "TableStyleMedium28", 7, { 123, 196, 212, 195, 194, 72, 71 } }, { "TableStyleMedium3", 7, { 95, 154, 215, 195, 194, 48, 47 } }, { "TableStyleMedium4", 7, { 98, 163, 216, 195, 194, 55, 54 } }, { "TableStyleMedium5", 7, { 101, 172, 217, 195, 194, 61, 60 } }, { "TableStyleMedium6", 7, { 104, 181, 218, 195, 194, 68, 67 } }, { "TableStyleMedium7", 7, { 107, 190, 219, 195, 194, 74, 73 } }, { "TableStyleMedium8", 7, { 110, 135, 136, 131, 130, 30, 29 } }, { "TableStyleMedium9", 7, { 112, 147, 148, 144, 143, 39, 38 } } }; +constexpr TableStyle aTableStyles[] = { { "TableStyleDark1", TableStyleCategory::Dark, 1, 7, { 76, 133, 137, 138, 139, 35, 34 } }, { "TableStyleDark10", TableStyleCategory::Dark, 10, 7, { 53, 82, 213, 195, 194, 52, 51 } }, { "TableStyleDark11", TableStyleCategory::Dark, 11, 7, { 66, 85, 213, 195, 194, 65, 64 } }, { "TableStyleDark2", TableStyleCategory::Dark, 2, 7, { 77, 133, 140, 141, 142, 37, 36 } }, { "TableStyleDark3", TableStyleCategory::Dark, 3, 7, { 78, 133, 149, 150, 151, 44, 43 } }, { "TableStyleDark4", TableStyleCategory::Dark, 4, 7, { 80, 133, 158, 159, 160, 50, 49 } }, { "TableStyleDark5", TableStyleCategory::Dark, 5, 7, { 81, 133, 167, 168, 169, 57, 56 } }, { "TableStyleDark6", TableStyleCategory::Dark, 6, 7, { 83, 133, 176, 177, 178, 63, 62 } }, { "TableStyleDark7", TableStyleCategory::Dark, 7, 7, { 84, 133, 185, 186, 187, 70, 69 } }, { "TableStyleDark8", TableStyleCategory::Dark, 8, 7, { 31, 75, 213, 195, 194, 30, 29 } }, { "TableStyleDark9", TableStyleCategory::Dark, 9, 7, { 40, 79, 213, 195, 194, 39, 38 } }, { "TableStyleLight1", TableStyleCategory::Light, 1, 7, { 86, 197, 205, 195, 194, 33, 32 } }, { "TableStyleLight10", TableStyleCategory::Light, 10, 9, { 93, 154, 215, 195, 194, 18, 19, 4, 5 } }, { "TableStyleLight11", TableStyleCategory::Light, 11, 9, { 96, 163, 216, 195, 194, 20, 21, 6, 7 } }, { "TableStyleLight12", TableStyleCategory::Light, 12, 9, { 99, 172, 217, 195, 194, 22, 23, 8, 9 } }, { "TableStyleLight13", TableStyleCategory::Light, 13, 9, { 102, 181, 218, 195, 194, 24, 25, 10, 11 } }, { "TableStyleLight14", TableStyleCategory::Light, 14, 9, { 105, 190, 219, 195, 194, 26, 27, 12, 13 } }, { "TableStyleLight15", TableStyleCategory::Light, 15, 7, { 89, 198, 213, 195, 194, 33, 32 } }, { "TableStyleLight16", TableStyleCategory::Light, 16, 7, { 91, 199, 214, 195, 194, 42, 41 } }, { "TableStyleLight17", TableStyleCategory::Light, 17, 7, { 94, 200, 215, 195, 194, 48, 47 } }, { "TableStyleLight18", TableStyleCategory::Light, 18, 7, { 97, 201, 216, 195, 194, 55, 54 } }, { "TableStyleLight19", TableStyleCategory::Light, 19, 7, { 100, 202, 217, 195, 194, 61, 60 } }, { "TableStyleLight2", TableStyleCategory::Light, 2, 7, { 124, 222, 223, 221, 220, 42, 41 } }, { "TableStyleLight20", TableStyleCategory::Light, 20, 7, { 103, 203, 218, 195, 194, 68, 67 } }, { "TableStyleLight21", TableStyleCategory::Light, 21, 7, { 106, 204, 219, 195, 194, 74, 73 } }, { "TableStyleLight3", TableStyleCategory::Light, 3, 7, { 125, 226, 227, 225, 224, 48, 47 } }, { "TableStyleLight4", TableStyleCategory::Light, 4, 7, { 126, 230, 231, 229, 228, 55, 54 } }, { "TableStyleLight5", TableStyleCategory::Light, 5, 7, { 127, 234, 235, 233, 232, 61, 60 } }, { "TableStyleLight6", TableStyleCategory::Light, 6, 7, { 128, 238, 239, 237, 236, 68, 67 } }, { "TableStyleLight7", TableStyleCategory::Light, 7, 7, { 129, 242, 243, 241, 240, 74, 73 } }, { "TableStyleLight8", TableStyleCategory::Light, 8, 9, { 87, 132, 213, 195, 194, 14, 15, 0, 1 } }, { "TableStyleLight9", TableStyleCategory::Light, 9, 9, { 90, 145, 214, 195, 194, 16, 17, 2, 3 } }, { "TableStyleMedium1", TableStyleCategory::Medium, 1, 7, { 88, 132, 213, 195, 194, 33, 32 } }, { "TableStyleMedium10", TableStyleCategory::Medium, 10, 7, { 114, 156, 157, 153, 152, 46, 45 } }, { "TableStyleMedium11", TableStyleCategory::Medium, 11, 7, { 116, 165, 166, 162, 161, 52, 51 } }, { "TableStyleMedium12", TableStyleCategory::Medium, 12, 7, { 118, 174, 175, 171, 170, 59, 58 } }, { "TableStyleMedium13", TableStyleCategory::Medium, 13, 7, { 120, 183, 184, 180, 179, 65, 64 } }, { "TableStyleMedium14", TableStyleCategory::Medium, 14, 7, { 122, 192, 193, 189, 188, 72, 71 } }, { "TableStyleMedium15", TableStyleCategory::Medium, 15, 7, { 109, 134, 28, 131, 130, 33, 32 } }, { "TableStyleMedium16", TableStyleCategory::Medium, 16, 7, { 108, 146, 28, 144, 143, 33, 32 } }, { "TableStyleMedium17", TableStyleCategory::Medium, 17, 7, { 108, 155, 28, 153, 152, 33, 32 } }, { "TableStyleMedium18", TableStyleCategory::Medium, 18, 7, { 108, 164, 28, 162, 161, 33, 32 } }, { "TableStyleMedium19", TableStyleCategory::Medium, 19, 7, { 108, 173, 28, 171, 170, 33, 32 } }, { "TableStyleMedium2", TableStyleCategory::Medium, 2, 7, { 92, 145, 214, 195, 194, 42, 41 } }, { "TableStyleMedium20", TableStyleCategory::Medium, 20, 7, { 108, 182, 28, 180, 179, 33, 32 } }, { "TableStyleMedium21", TableStyleCategory::Medium, 21, 7, { 108, 191, 28, 189, 188, 33, 32 } }, { "TableStyleMedium22", TableStyleCategory::Medium, 22, 7, { 111, 196, 206, 195, 194, 30, 29 } }, { "TableStyleMedium23", TableStyleCategory::Medium, 23, 7, { 113, 196, 207, 195, 194, 39, 38 } }, { "TableStyleMedium24", TableStyleCategory::Medium, 24, 7, { 115, 196, 208, 195, 194, 46, 45 } }, { "TableStyleMedium25", TableStyleCategory::Medium, 25, 7, { 117, 196, 209, 195, 194, 52, 51 } }, { "TableStyleMedium26", TableStyleCategory::Medium, 26, 7, { 119, 196, 210, 195, 194, 59, 58 } }, { "TableStyleMedium27", TableStyleCategory::Medium, 27, 7, { 121, 196, 211, 195, 194, 65, 64 } }, { "TableStyleMedium28", TableStyleCategory::Medium, 28, 7, { 123, 196, 212, 195, 194, 72, 71 } }, { "TableStyleMedium3", TableStyleCategory::Medium, 3, 7, { 95, 154, 215, 195, 194, 48, 47 } }, { "TableStyleMedium4", TableStyleCategory::Medium, 4, 7, { 98, 163, 216, 195, 194, 55, 54 } }, { "TableStyleMedium5", TableStyleCategory::Medium, 5, 7, { 101, 172, 217, 195, 194, 61, 60 } }, { "TableStyleMedium6", TableStyleCategory::Medium, 6, 7, { 104, 181, 218, 195, 194, 68, 67 } }, { "TableStyleMedium7", TableStyleCategory::Medium, 7, 7, { 107, 190, 219, 195, 194, 74, 73 } }, { "TableStyleMedium8", TableStyleCategory::Medium, 8, 7, { 110, 135, 136, 131, 130, 30, 29 } }, { "TableStyleMedium9", TableStyleCategory::Medium, 9, 7, { 112, 147, 148, 144, 143, 39, 38 } } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx index 0a4207280ed1..af1617e27f21 100644 --- a/sc/source/core/data/dociter.cxx +++ b/sc/source/core/data/dociter.cxx @@ -107,6 +107,21 @@ ScValueIterator::ScValueIterator(ScInterpreterContext& rContext, const ScRange& if (!mrDoc.ValidRow(maEndPos.Row())) maEndPos.SetRow(mrDoc.MaxRow()); if (!ValidTab(maStartPos.Tab()) || maStartPos.Tab() > nDocMaxTab) maStartPos.SetTab(nDocMaxTab); if (!ValidTab(maEndPos.Tab()) || maEndPos.Tab() > nDocMaxTab) maEndPos.SetTab(nDocMaxTab); + + // tdf#164843/tdf#168013: When iterating for SubTotal/Aggregate, clamp the area to + // the actual data range. SubTotal and Aggregate ignore empty cells, so trimming + // empty cells from the iterated range never changes the result, but it avoids + // walking huge ranges (e.g. relative named ranges expanded to MAXROW). The stored + // formula reference is left untouched - only this local iteration range is trimmed. + if (mnSubTotalFlags != SubtotalFlags::NONE) + { + ScRange aDataRange(maStartPos, maEndPos); + if (mrDoc.GetDataAreaSubrange(aDataRange)) + { + maStartPos = aDataRange.aStart; + maEndPos = aDataRange.aEnd; + } + } } SCROW ScValueIterator::GetRow() const @@ -686,7 +701,7 @@ bool ScDBQueryDataIterator::DataAccessMatrix::isValidQuery(SCROW nRow, const ScM if (bDone) break; - // Unequality check using collator. + // Inequality check using collator. sal_Int32 nCompare = rCollator.compareString(aMatStr.getString(), aQueryStr.getString()); switch (rEntry.eOp) { @@ -868,6 +883,20 @@ void ScCellIterator::init() if (!ValidTab(maStartPos.Tab(), nDocMaxTab)) maStartPos.SetTab(nDocMaxTab); if (!ValidTab(maEndPos.Tab(), nDocMaxTab)) maEndPos.SetTab(nDocMaxTab); + // tdf#164843/tdf#168013: When iterating for SubTotal/Aggregate (e.g. COUNTA), clamp + // the area to the actual data range. These functions ignore empty cells, so trimming + // empty cells away never changes the result, but avoids walking huge ranges. Only the + // local iteration range is trimmed; the stored formula reference is left untouched. + if (mnSubTotalFlags != SubtotalFlags::NONE) + { + ScRange aDataRange(maStartPos, maEndPos); + if (mrDoc.GetDataAreaSubrange(aDataRange)) + { + maStartPos = aDataRange.aStart; + maEndPos = aDataRange.aEnd; + } + } + while (maEndPos.Tab() > 0 && !mrDoc.maTabs[maEndPos.Tab()]) maEndPos.IncTab(-1); // Only the tables in use @@ -944,7 +973,7 @@ bool ScCellIterator::getCurrent() } SCROW nLastRow; - // Skip all filtered or hidden rows, depending on mSubTotalFlags + // Skip all filtered or hidden rows, depending on mnSubTotalFlags if ( ( ( mnSubTotalFlags & SubtotalFlags::IgnoreFiltered ) && pCol->GetDoc().RowFiltered(maCurPos.Row(), maCurPos.Tab(), nullptr, &nLastRow) ) || ( ( mnSubTotalFlags & SubtotalFlags::IgnoreHidden ) && @@ -988,7 +1017,7 @@ ScCellValue ScCellIterator::getCellValue() const return ScCellValue(maCurCell.getSharedString()); break; case CELLTYPE_EDIT: - return ScCellValue(maCurCell.getEditText()->Clone()); + return ScCellValue(std::make_unique(*maCurCell.getEditText())); break; case CELLTYPE_VALUE: return ScCellValue(maCurCell.getDouble()); @@ -1405,7 +1434,12 @@ void ScHorizontalAttrIterator::InitForNextRow(bool bInitialization) pHorizEnd[nPos] = rDoc.MaxCol()+1; // only for assert() } else - nIndex = ++pIndices[nPos]; + { + // a column can be more than one run behind nRow, so re-search + // rather than stepping a single run + pArray.Search(nRow, nIndex, pIndices[nPos]); + pIndices[nPos] = nIndex; + } if ( !nIndex && !pArray.Count() ) { @@ -1490,10 +1524,9 @@ ScUsedAreaIterator::ScUsedAreaIterator( ScDocument& rDocument, SCTAB nTable, , nFoundStartCol( 0 ) , nFoundEndCol( 0 ) , nFoundRow( 0 ) - , pFoundPattern( nullptr ) { pCell = aCellIter.GetNext( nCellCol, nCellRow ); - pPattern = aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow ); + maPattern.setScPatternAttr(aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow )); } ScUsedAreaIterator::~ScUsedAreaIterator() @@ -1509,22 +1542,22 @@ bool ScUsedAreaIterator::GetNext() while (pCell && pCell->isEmpty()) pCell = aCellIter.GetNext( nCellCol, nCellRow ); - if ( pPattern && IsGreater( nNextCol, nNextRow, nAttrCol2, nAttrRow ) ) - pPattern = aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow ); + if ( maPattern && IsGreater( nNextCol, nNextRow, nAttrCol2, nAttrRow ) ) + maPattern.setScPatternAttr(aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow )); - if ( pPattern && nAttrRow == nNextRow && nAttrCol1 < nNextCol ) + if ( maPattern && nAttrRow == nNextRow && nAttrCol1 < nNextCol ) nAttrCol1 = nNextCol; // Find next area bool bFound = true; bool bUseCell = false; - if ( pCell && pPattern ) + if ( pCell && maPattern ) { if ( IsGreater( nCellCol, nCellRow, nAttrCol1, nAttrRow ) ) // Only attributes at the beginning? { maFoundCell.clear(); - pFoundPattern = pPattern; + maFoundPattern = maPattern; nFoundRow = nAttrRow; nFoundStartCol = nAttrCol1; if ( nCellRow == nAttrRow && nCellCol <= nAttrCol2 ) // Area also contains cell? @@ -1536,20 +1569,20 @@ bool ScUsedAreaIterator::GetNext() { bUseCell = true; if ( nAttrRow == nCellRow && nAttrCol1 == nCellCol ) // Attributes on the cell? - pFoundPattern = pPattern; + maFoundPattern = maPattern; else - pFoundPattern = nullptr; + maFoundPattern.setScPatternAttr(nullptr); } } else if ( pCell ) // Just a cell -> take over right away { - pFoundPattern = nullptr; + maFoundPattern.setScPatternAttr(nullptr); bUseCell = true; // Cell position } - else if ( pPattern ) // Just attributes -> take over right away + else if ( maPattern ) // Just attributes -> take over right away { maFoundCell.clear(); - pFoundPattern = pPattern; + maFoundPattern = maPattern; nFoundRow = nAttrRow; nFoundStartCol = nAttrCol1; nFoundEndCol = nAttrCol2; diff --git a/sc/source/core/data/docpool.cxx b/sc/source/core/data/docpool.cxx index ab96fa3c8c8e..597ef720ec9b 100644 --- a/sc/source/core/data/docpool.cxx +++ b/sc/source/core/data/docpool.cxx @@ -133,7 +133,7 @@ static ItemInfoPackage& getItemInfoPackageScDocument() { ATTR_ROTATE_MODE, new SvxRotateModeItem( SVX_ROTATE_MODE_BOTTOM, ATTR_ROTATE_MODE ), SID_ATTR_ALIGN_LOCKPOS, SFX_ITEMINFOFLAG_NONE }, { ATTR_VERTICAL_ASIAN, new SfxBoolItem( ATTR_VERTICAL_ASIAN ), SID_ATTR_ALIGN_ASIANVERTICAL, SFX_ITEMINFOFLAG_NONE }, - // The default for the ATTR_WRITINGDIR cell attribute must by SvxFrameDirection::Environment, + // The default for the ATTR_WRITINGDIR cell attribute must be SvxFrameDirection::Environment, // so that value is returned when asking for a default cell's attributes. // The value from the page style is set as DefaultHorizontalTextDirection for the EditEngine. { ATTR_WRITINGDIR, new SvxFrameDirectionItem( SvxFrameDirection::Environment, ATTR_WRITINGDIR ), SID_ATTR_FRAMEDIRECTION, SFX_ITEMINFOFLAG_NONE }, @@ -314,7 +314,7 @@ static bool lcl_HFPresentation sal_uInt16 nPropRightMargin = rLRItem.GetPropRight(); sal_uInt16 nLeftMargin, nRightMargin; tools::Long nTmp; - nTmp = rLRItem.ResolveLeft({}); + nTmp = rLRItem.ResolveLeft(); nLeftMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp); nTmp = rLRItem.ResolveRight({}); nRightMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp); @@ -336,7 +336,7 @@ static bool lcl_HFPresentation EditResId(RID_SVXITEMS_LRSPACE_RIGHT); if ( 100 != nPropRightMargin ) { - aText += unicode::formatPercent(nPropLeftMargin, + aText += unicode::formatPercent(nPropRightMargin, Application::GetSettings().GetUILanguageTag()); } else diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 4dbc848001b7..fbd1a36e7c58 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -19,9 +19,11 @@ #include #include +#include #include #include +#include #include #include #include @@ -39,6 +41,8 @@ #include #include #include +#include +#include #include #include @@ -123,7 +127,7 @@ CellAttributeHelper& ScDocument::getCellAttributeHelper() const assert(!IsClipOrUndo() && "CellAttributeHelper needs to be shared using SharePooledResources, not created (!)"); SfxItemPool* pPool(const_cast(this)->GetPool()); assert(nullptr != pPool && "No SfxItemPool for this ScDocument (!)"); - mpCellAttributeHelper.reset(new CellAttributeHelper(*pPool)); + mpCellAttributeHelper.reset(new CellAttributeHelper(*pPool, const_cast(this))); } return *mpCellAttributeHelper; @@ -145,7 +149,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, ScDocShell* pDocShell ) : pEOFormulaTree( nullptr ), pFormulaTrack( nullptr ), pEOFormulaTrack( nullptr ), - mpTableStyles(new ScTableStyles), + mpTableStyles(new ScTableStyles(GetViewBindings())), pPreviewCellStyle( nullptr ), maPreviewSelection(*mxSheetLimits), nUnoObjectId( 0 ), @@ -413,6 +417,8 @@ ScDocument::~ScDocument() Clear( true ); // true = from destructor (needed for SdrModel::ClearModel) + ::comphelper::disposeComponent(mxVbaEvents); + pValidationList.reset(); pRangeName.reset(); pDBCollection.reset(); @@ -538,15 +544,15 @@ ScNoteEditEngine& ScDocument::GetNoteEngine() return *mpNoteEngine; } -std::unique_ptr ScDocument::CreateSharedStringTextObject( const svl::SharedString& rSS ) +EditTextObject ScDocument::CreateSharedStringTextObject( const svl::SharedString& rSS ) { /* TODO: Add shared string support to the edit engine to make this process * simpler. */ ScFieldEditEngine& rEngine = GetEditEngine(); rEngine.SetTextCurrentDefaults( rSS.getString()); - std::unique_ptr pObj( rEngine.CreateTextObject()); - pObj->NormalizeString( GetSharedStringPool()); - return pObj; + EditTextObject aObj( rEngine.CreateTextObject()); + aObj.NormalizeString( GetSharedStringPool()); + return aObj; } void ScDocument::ResetClip( ScDocument* pSourceDoc, const ScMarkData* pMarks ) @@ -804,6 +810,8 @@ bool ScDocument::MoveTab( SCTAB nOldPos, SCTAB nNewPos, ScProgress* pProgress ) pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_REORDER, aSourceRange, 0,0,nDz ) ); + UpdateQueryTables(aCxt); + ScTableUniquePtr pSaveTab = std::move(maTabs[nOldPos]); maTabs.erase(maTabs.begin()+nOldPos); maTabs.insert(maTabs.begin()+nNewPos, std::move(pSaveTab)); @@ -828,6 +836,47 @@ bool ScDocument::MoveTab( SCTAB nOldPos, SCTAB nNewPos, ScProgress* pProgress ) return bValid; } +bool ScDocument::OverwriteContent(SCTAB nSourceTabNo, SCTAB nTargetTabNo) +{ + ScTable* pSourceTable = FetchTable(nSourceTabNo); + ScTable* pTargetTable = FetchTable(nTargetTabNo); + + if (pSourceTable && pTargetTable) + { + sc::AutoCalcSwitch aACSwitch(*this, false); + SetNoListening(true); + + // Clear content of the target sheet + pTargetTable->DeleteArea(0, 0, MaxCol(), MaxRow(), InsertDeleteFlags::ALL); + + // Clear drawing objects on the target sheet + if (mpDrawLayer) + { + if (SdrPage* pTargetPage = mpDrawLayer->GetPage(static_cast(nTargetTabNo))) + pTargetPage->ClearSdrObjList(); + } + + // Clear pivot tables on the target sheet + if (pDPCollection) + { + pDPCollection->DeleteByTab(nTargetTabNo); + } + + // Copy all content from source sheet to target sheet + { + sc::TableContentCopier aHandler(*this, nSourceTabNo, nTargetTabNo); + aHandler.performCopy(nullptr, ScCloneFlags::NamesToLocal | ScCloneFlags::AdjustCrossSheetRefs); + } + + SetNoListening(false); + sc::StartListeningContext aSLCxt(*this); + maTabs[nTargetTabNo]->StartListeners(aSLCxt, true); + return true; + } + return false; +} + + bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyMarked ) { if (SC_TAB_APPEND == nNewPos || nNewPos >= GetTableCount()) @@ -848,6 +897,10 @@ bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM else bValid = !GetTable( aName, nDummy ); + // Early return + if (!bValid) + return false; + sc::AutoCalcSwitch aACSwitch(*this, false); sc::RefUpdateInsertTabContext aCxt( *this, nNewPos, 1); @@ -905,6 +958,8 @@ bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM if (pValidationList) pValidationList->UpdateInsertTab(aCxt); + + UpdateQueryTables(aCxt); } else bValid = false; @@ -913,64 +968,19 @@ bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM if (bValid) { - SetNoListening( true ); // not yet at CopyToTable/Insert + SetNoListening(true); - const bool bGlobalNamesToLocal = true; - const SCTAB nRealOldPos = (nNewPos < nOldPos) ? nOldPos - 1 : nOldPos; - const ScRangeName* pNames = GetRangeName( nOldPos); - if (pNames) - pNames->CopyUsedNames( nOldPos, nRealOldPos, nNewPos, *this, *this, bGlobalNamesToLocal); - GetRangeName()->CopyUsedNames( -1, nRealOldPos, nNewPos, *this, *this, bGlobalNamesToLocal); + SCTAB nPreviousSourceTabNo = (nNewPos < nOldPos) ? nOldPos - 1 : nOldPos; + { + sc::TableContentCopier aHandler(*this, nOldPos, nNewPos); + aHandler.performCopy(pOnlyMarked, ScCloneFlags::NamesToLocal, nPreviousSourceTabNo); + aHandler.updateReferencesAfterTabInsertion(aCxt); + } - sc::CopyToDocContext aCopyDocCxt(*this); - pDBCollection->CopyToTable(nOldPos, nNewPos); - maTabs[nOldPos]->CopyToTable(aCopyDocCxt, 0, 0, MaxCol(), MaxRow(), InsertDeleteFlags::ALL, - (pOnlyMarked != nullptr), maTabs[nNewPos].get(), pOnlyMarked, - false /*bAsLink*/, true /*bColRowFlags*/, bGlobalNamesToLocal, false /*bCopyCaptions*/ ); - maTabs[nNewPos]->SetTabBgColor(maTabs[nOldPos]->GetTabBgColor()); - - SCTAB nDz = nNewPos - nOldPos; - sc::RefUpdateContext aRefCxt(*this); - aRefCxt.meMode = URM_COPY; - aRefCxt.maRange = ScRange(0, 0, nNewPos, MaxCol(), MaxRow(), nNewPos); - aRefCxt.mnTabDelta = nDz; - maTabs[nNewPos]->UpdateReference(aRefCxt); - - maTabs[nNewPos]->UpdateInsertTabAbs(nNewPos); // move all paragraphs up by one!! - maTabs[nOldPos]->UpdateInsertTab(aCxt); - - maTabs[nOldPos]->UpdateCompile(); - maTabs[nNewPos]->UpdateCompile( true ); // maybe already compiled in Clone, but used names need recompilation - SetNoListening( false ); + SetNoListening(false); sc::StartListeningContext aSLCxt(*this); maTabs[nOldPos]->StartListeners(aSLCxt, true); maTabs[nNewPos]->StartListeners(aSLCxt, true); - - sc::SetFormulaDirtyContext aFormulaDirtyCxt; - SetAllFormulasDirty(aFormulaDirtyCxt); - - if (mpDrawLayer) // Skip cloning Note caption object - // page is already created in ScTable ctor - mpDrawLayer->ScCopyPage( static_cast(nOldPos), static_cast(nNewPos) ); - - if (pDPCollection) - pDPCollection->CopyToTab(nOldPos, nNewPos); - - maTabs[nNewPos]->SetPageStyle( maTabs[nOldPos]->GetPageStyle() ); - maTabs[nNewPos]->SetPendingRowHeights( maTabs[nOldPos]->IsPendingRowHeights() ); - - // Copy the custom print range if exists. - maTabs[nNewPos]->CopyPrintRange(*maTabs[nOldPos]); - - // Copy the RTL settings - maTabs[nNewPos]->SetLayoutRTL(maTabs[nOldPos]->IsLayoutRTL()); - maTabs[nNewPos]->SetLoadingRTL(maTabs[nOldPos]->IsLoadingRTL()); - - // Finally copy the note captions, which need - // 1. the updated source ScColumn::nTab members if nNewPos <= nOldPos - // 2. row heights and column widths of the destination - // 3. RTL settings of the destination - maTabs[nOldPos]->CopyCaptionsToTable( 0, 0, MaxCol(), MaxRow(), maTabs[nNewPos].get(), true /*bCloneCaption*/); } return bValid; @@ -1041,12 +1051,12 @@ bool ScDocument::TransferTab( ScDocument& rSrcDoc, SCTAB nSrcPos, const ScRangeName* pNames = rSrcDoc.GetRangeName( nSrcPos); if (pNames) pNames->CopyUsedNames( nSrcPos, nSrcPos, nDestPos, rSrcDoc, *this, bGlobalNamesToLocal); - rSrcDoc.GetRangeName()->CopyUsedNames( -1, nSrcPos, nDestPos, rSrcDoc, *this, bGlobalNamesToLocal); + rSrcDoc.GetRangeName().CopyUsedNames( -1, nSrcPos, nDestPos, rSrcDoc, *this, bGlobalNamesToLocal); } rSrcDoc.maTabs[nSrcPos]->CopyToTable(aCxt, 0, 0, MaxCol(), MaxRow(), ( bResultsOnly ? InsertDeleteFlags::ALL & ~InsertDeleteFlags::FORMULA : InsertDeleteFlags::ALL), false, maTabs[nDestPos].get(), /*pMarkData*/nullptr, /*bAsLink*/false, /*bColRowFlags*/true, - /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true ); + ScCloneFlags::Default, /*bCopyCaptions*/true ); } } maTabs[nDestPos]->SetTabNo(nDestPos); diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index 16a2d32fbdde..8f28411e039e 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -181,11 +181,11 @@ ScRangeName* ScDocument::GetRangeName(SCTAB nTab) const return nullptr; } -ScRangeName* ScDocument::GetRangeName() const +ScRangeName& ScDocument::GetRangeName() const { if (!pRangeName) pRangeName.reset(new ScRangeName); - return pRangeName.get(); + return *pRangeName; } void ScDocument::SetRangeName(SCTAB nTab, std::unique_ptr pNew) @@ -205,7 +205,7 @@ bool ScDocument::IsAddressInRangeName( RangeNameScope eScope, const ScAddress& r ScRange aNameRange; if (eScope == RangeNameScope::GLOBAL) - pRangeNames= GetRangeName(); + pRangeNames= &GetRangeName(); else pRangeNames= GetRangeName(rAddress.Tab()); @@ -223,12 +223,10 @@ bool ScDocument::IsAddressInRangeName( RangeNameScope eScope, const ScAddress& r bool ScDocument::InsertNewRangeName( const OUString& rName, const ScAddress& rPos, const OUString& rExpr ) { - ScRangeName* pGlobalNames = GetRangeName(); - if (!pGlobalNames) - return false; + ScRangeName& rGlobalNames = GetRangeName(); - ScRangeData* pName = new ScRangeData(*this, rName, rExpr, rPos, ScRangeData::Type::Name, GetGrammar()); - return pGlobalNames->insert(pName); + std::unique_ptr pName(new ScRangeData(*this, rName, rExpr, rPos, ScRangeData::Type::Name, GetGrammar())); + return rGlobalNames.insert(std::move(pName)); } bool ScDocument::InsertNewRangeName( SCTAB nTab, const OUString& rName, const ScAddress& rPos, const OUString& rExpr ) @@ -237,8 +235,8 @@ bool ScDocument::InsertNewRangeName( SCTAB nTab, const OUString& rName, const Sc if (!pLocalNames) return false; - ScRangeData* pName = new ScRangeData(*this, rName, rExpr, rPos, ScRangeData::Type::Name, GetGrammar()); - return pLocalNames->insert(pName); + std::unique_ptr pName(new ScRangeData(*this, rName, rExpr, rPos, ScRangeData::Type::Name, GetGrammar())); + return pLocalNames->insert(std::move(pName)); } const ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, OUString& rName, bool* pSheetLocal ) const @@ -274,7 +272,7 @@ const ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, OUString& ScRangeData* ScDocument::FindRangeNameBySheetAndIndex( SCTAB nTab, sal_uInt16 nIndex ) const { - const ScRangeName* pRN = (nTab < 0 ? GetRangeName() : GetRangeName(nTab)); + const ScRangeName* pRN = (nTab < 0 ?& GetRangeName() : GetRangeName(nTab)); return (pRN ? pRN->findByIndex( nIndex) : nullptr); } @@ -612,25 +610,22 @@ bool ScDocument::LinkExternalTab( SCTAB& rTab, const OUString& aDocTab, OUString aOptions; // Filter options sal_uInt32 nLinkCnt = pExtDocOptions ? pExtDocOptions->GetDocSettings().mnLinkCnt : 0; ScDocumentLoader aLoader( aFileName, aFilterName, aOptions, nLinkCnt + 1 ); - if ( aLoader.IsError() ) + ScDocument* pSrcDoc = aLoader.IsError() ? nullptr : aLoader.GetDocument(); + + if (!InsertTab(SC_TAB_APPEND, aDocTab, true)) + { + OSL_FAIL("can't insert external document table"); return false; - ScDocument* pSrcDoc = aLoader.GetDocument(); + } + rTab = GetTableCount() - 1; // Copy table SCTAB nSrcTab; - if ( pSrcDoc->GetTable( aTabName, nSrcTab ) ) + if (pSrcDoc && pSrcDoc->GetTable(aTabName, nSrcTab)) { - if ( !InsertTab( SC_TAB_APPEND, aDocTab, true ) ) - { - OSL_FAIL("can't insert external document table"); - return false; - } - rTab = GetTableCount() - 1; // Don't insert anew, just the results TransferTab( *pSrcDoc, nSrcTab, rTab, false, true ); } - else - return false; sal_Int32 nRefreshDelay = 0; @@ -1252,78 +1247,38 @@ void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem, { if ( rSearchItem.GetRowDirection() ) { - if ( rSearchItem.GetPattern() ) - { + rRow = MaxRow(); + if (!bReplace || rSearchItem.GetPattern()) + rCol = MaxCol() + 1; + else // bReplace rCol = MaxCol(); - rRow = MaxRow()+1; - } - else if ( bReplace ) - { - rCol = MaxCol(); - rRow = MaxRow(); - } - else - { - rCol = MaxCol()+1; - rRow = MaxRow(); - } } else { - if ( rSearchItem.GetPattern() ) - { - rCol = MaxCol()+1; + rCol = MaxCol(); + if (!bReplace || rSearchItem.GetPattern()) + rRow = MaxRow() + 1; + else // bReplace rRow = MaxRow(); - } - else if ( bReplace ) - { - rCol = MaxCol(); - rRow = MaxRow(); - } - else - { - rCol = MaxCol(); - rRow = MaxRow()+1; - } } } else { if ( rSearchItem.GetRowDirection() ) { - if ( rSearchItem.GetPattern() ) - { - rCol = 0; - rRow = SCROW(-1); - } - else if ( bReplace ) - { - rCol = 0; - rRow = 0; - } - else - { + rRow = 0; + if (!bReplace || rSearchItem.GetPattern()) rCol = SCCOL(-1); - rRow = 0; - } + else // bReplace + rCol = 0; } else { - if ( rSearchItem.GetPattern() ) - { - rCol = SCCOL(-1); - rRow = 0; - } - else if ( bReplace ) - { - rCol = 0; - rRow = 0; - } - else - { - rCol = 0; + rCol = 0; + if (!bReplace || rSearchItem.GetPattern()) rRow = SCROW(-1); - } + else // bReplace + rRow = 0; } } } @@ -1594,13 +1549,8 @@ void ScDocument::GetFilterEntries( ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, ScDBDataPortion::AREA); //!?? if (!pDBData) return; - // Do not extend DBArea automatically in case of Table Styles with Total row - if ((!pDBData->HasTotals() || !pDBData->GetTableStyleInfo()) - && (pDBData->GetName() == STR_DB_LOCAL_NONAME)) - { - pDBData->ExtendBackColorArea(*this); - pDBData->ExtendDataArea(*this); - } + pDBData->ExtendDataArea(*this); + SCTAB nAreaTab; SCCOL nStartCol; SCROW nStartRow; diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx index fe97855bb176..b06846e5d623 100644 --- a/sc/source/core/data/documen4.cxx +++ b/sc/source/core/data/documen4.cxx @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -61,7 +62,7 @@ using namespace formula; Regula Falsi (aka false position) algorithm to find a root of f(x). The start value and the target value are to be given by the user in the goal seek dialog. The f(x) in this case is defined as the formula in the - formula cell minus target value. This function may also perform additional + formula cell minus the target value. This function may also perform additional search in the horizontal directions when the f(x) is discrete in order to ensure a non-zero slope necessary for deriving a subsequent x that is reasonably close to the root of interest. @@ -251,12 +252,87 @@ bool ScDocument::Solver(SCCOL nFCol, SCROW nFRow, SCTAB nFTab, return bRet; } +bool ScDocument::IsMatrixSpillBlocked(const ScRange& rRange, + SCCOL nDeclCols, SCROW nDeclRows) const +{ + const ScAddress& rOrigin = rRange.aStart; + for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol) + { + for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow) + { + if (nCol < rOrigin.Col() + nDeclCols && nRow < rOrigin.Row() + nDeclRows) + continue; // inside the already-declared sub-range + ScRefCellValue aCell(const_cast(*this), + ScAddress(nCol, nRow, rOrigin.Tab())); + // A reference cell already belongs to a matrix - it's never a + // foreign blocker. This also lets the spill check recover when + // Undo restores reference cells inside a now collapsed master, + // which should re-expand on the next reconciliation. + if (aCell.getType() == CELLTYPE_FORMULA + && aCell.getFormula()->GetMatrixFlag() == ScMatrixMode::Reference) + continue; + if (!aCell.isEmpty()) + return true; + } + } + return false; +} + +std::vector ScDocument::CollectExpandedDynamicArraysInRange( + const ScMarkData& rMark, const ScRange& rRange) const +{ + std::vector aResult; + if (maExpandedDynamicArrays.empty()) + return aResult; + for (const ScAddress& rPosition : maExpandedDynamicArrays) + { + if (!rMark.GetTableSelect(rPosition.Tab())) + continue; + if (rPosition.Col() < rRange.aStart.Col() || rPosition.Col() > rRange.aEnd.Col()) + continue; + if (rPosition.Row() < rRange.aStart.Row() || rPosition.Row() > rRange.aEnd.Row()) + continue; + aResult.push_back(rPosition); + } + return aResult; +} + +bool ScDocument::HasMatrixBlocker(const ScRange& rRange) const +{ + const ScAddress& rOrigin = rRange.aStart; + for (SCCOL nColumn = rRange.aStart.Col(); nColumn <= rRange.aEnd.Col(); ++nColumn) + { + for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow) + { + if (nColumn == rOrigin.Col() && nRow == rOrigin.Row()) + continue; + ScRefCellValue aCell(const_cast(*this), + ScAddress(nColumn, nRow, rOrigin.Tab())); + if (aCell.getType() == CELLTYPE_FORMULA + && aCell.getFormula()->GetMatrixFlag() == ScMatrixMode::Reference) + { + // Skip only this matrix's own reference cells. A reference + // cell belonging to a different matrix is a real blocker. + ScAddress aRefOrigin; + if (aCell.getFormula()->GetMatrixOrigin(*this, aRefOrigin) + && aRefOrigin == rOrigin) + continue; + return true; + } + if (!aCell.isEmpty()) + return true; + } + } + return false; +} + void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark, const OUString& rFormula, const ScTokenArray* pArr, - const formula::FormulaGrammar::Grammar eGram ) + const formula::FormulaGrammar::Grammar eGram, + bool bDynamicArrayMaster) { PutInOrder(nCol1, nCol2); PutInOrder(nRow1, nRow2); @@ -286,6 +362,8 @@ void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1, else pCell = new ScFormulaCell(*this, aPos, rFormula, eGram, ScMatrixMode::Formula); pCell->SetMatColsRows( nCol2 - nCol1 + 1, nRow2 - nRow1 + 1 ); + if (bDynamicArrayMaster) + pCell->SetDynamicArrayMaster(true); SCTAB nMax = GetTableCount(); for (const auto& rTab : rMark) { @@ -308,6 +386,35 @@ void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1, *pCell, *this, ScAddress(nCol1, nRow1, rTab), ScCloneFlags::StartListening)); } + // Check for spill on dynamic-array masters: if any non-origin cell in + // the declared range is non-empty, collapse the master to 1x1 with a + // re-evaluable #SPILL! error and don't create reference cells over the + // blocker. A later cell change operation can re-resolve through the + // runtime spill check and expand the matrix to the result dimensions. + // Static array masters (flag off) keep the user-chosen range as is + // and overwrite whatever sat there. + if (bDynamicArrayMaster && (nCol2 > nCol1 || nRow2 > nRow1)) + { + bool bSpillBlocked = false; + for (const SCTAB& nTab : rMark) + { + if (nTab >= nMax) + break; + if (!FetchTable(nTab)) + continue; + if (IsMatrixSpillBlocked(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab))) + { + bSpillBlocked = true; + break; + } + } + if (bSpillBlocked) + { + pCell->MarkAsSpilled(); + return; + } + } + ScSingleRefData aRefData; aRefData.InitFlags(); aRefData.SetRelCol(0); @@ -337,7 +444,7 @@ void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1, // Reference in each cell must point to the origin cell relative to the current cell. aRefData.SetRelRow(nRow1 - nRow); - *t->GetSingleRef() = aRefData; + static_cast(t)->GetSingleRef() = aRefData; // Token array must be cloned so that each formula cell receives its own copy. ScTokenArray aTokArr(aArr.CloneValue()); aPos = ScAddress(nCol, nRow, nTab); @@ -346,6 +453,176 @@ void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1, } } } + + // Track every multi cell matrix master, so spill resolution can find it + // again if a blocker is later placed inside its declared range. + for (const SCTAB& nTab : rMark) + { + if (nTab >= nMax) + break; + if (!FetchTable(nTab)) + continue; + MarkExpandedDynamicArray(ScAddress(nCol1, nRow1, nTab)); + } +} + +// Resize a dynamic-array matrix formula at rOrigin to nNewCols x nNewRows, +// adding or removing reference cells to match. +// Must not run while an iterator over the cell store is live (see sc::MatrixResizeGuard). +void ScDocument::ResizeMatrixFormula(const ScAddress& rOrigin, SCCOL nNewCols, SCROW nNewRows) +{ + ScFormulaCell* pOrigin = GetFormulaCell(rOrigin); + if (!pOrigin || pOrigin->GetMatrixFlag() != ScMatrixMode::Formula) + return; + if (nNewCols <= 0 || nNewRows <= 0) + return; + + SCCOL nOldCols = 0; + SCROW nOldRows = 0; + pOrigin->GetMatColsRows(nOldCols, nOldRows); + if (nNewCols == nOldCols && nNewRows == nOldRows) + return; // nothing to do + + // A caller may be iterating the cell store (reached here from a row-height + // or interpret walk via InterpretTail). Inserting or removing cells now + // would invalidate that iterator - queue the resize and run it once the + // guard is popped. + if (IsMatrixResizeGuarded()) + { + MarkPendingMatrixResize(rOrigin); + return; + } + + SCTAB nTab = rOrigin.Tab(); + SCCOL nOriginColumn = rOrigin.Col(); + SCROW nOriginRow = rOrigin.Row(); + + ScTable* pTab = FetchTable(nTab); + if (!pTab) + return; + + // Update the matrix dimensions on the origin cell. + pOrigin->SetMatColsRows(nNewCols, nNewRows); + + // Clear reference cells that now fall outside the new matrix area. + if (nNewCols < nOldCols || nNewRows < nOldRows) + { + SCCOL nOldEndColumn = nOriginColumn + nOldCols - 1; + SCROW nOldEndRow = nOriginRow + nOldRows - 1; + for (SCCOL nColumn = nOriginColumn; nColumn <= nOldEndColumn; ++nColumn) + { + for (SCROW nRow = nOriginRow; nRow <= nOldEndRow; ++nRow) + { + if (nColumn < nOriginColumn + nNewCols && nRow < nOriginRow + nNewRows) + continue; // still inside the new matrix area + DeleteAreaTab(nColumn, nRow, nColumn, nRow, nTab, InsertDeleteFlags::ALL); + } + } + } + + // Create reference cells for newly covered positions. + if (nNewCols > nOldCols || nNewRows > nOldRows) + { + SCCOL nNewEndColumn = nOriginColumn + nNewCols - 1; + SCROW nNewEndRow = nOriginRow + nNewRows - 1; + + ScSingleRefData aRefData; + aRefData.InitFlags(); + aRefData.SetRelCol(0); + aRefData.SetRelRow(0); + aRefData.SetRelTab(0); + + ScTokenArray aArr(*this); + auto* pToken = static_cast(aArr.AddMatrixSingleReference(aRefData)); + + for (SCCOL nColumn = nOriginColumn; nColumn <= nNewEndColumn; ++nColumn) + { + aRefData.SetRelCol(nOriginColumn - nColumn); + for (SCROW nRow = nOriginRow; nRow <= nNewEndRow; ++nRow) + { + // Skip the origin cell and positions already covered by the old matrix. + if (nColumn < nOriginColumn + nOldCols && nRow < nOriginRow + nOldRows) + continue; + aRefData.SetRelRow(nOriginRow - nRow); + pToken->GetSingleRef() = aRefData; + ScTokenArray aTokArr(aArr.CloneValue()); + ScAddress aPos(nColumn, nRow, nTab); + ScFormulaCell* pNewCell = new ScFormulaCell( + *this, aPos, aTokArr, formula::FormulaGrammar::GRAM_DEFAULT, + ScMatrixMode::Reference); + pTab->SetFormulaCell(nColumn, nRow, pNewCell); + } + } + } + + // Broadcast the affected area so listeners pick up the change and the + // grid repaints the previously occupied / newly occupied cells. + SCCOL nMaxColumn = std::max(nOldCols, nNewCols); + SCROW nMaxRow = std::max(nOldRows, nNewRows); + ScRange aAffected(nOriginColumn, nOriginRow, nTab, + nOriginColumn + nMaxColumn - 1, nOriginRow + nMaxRow - 1, nTab); + BroadcastCells(aAffected, SfxHintId::ScDataChanged); + + // Track expanded-vs-collapsed state so the spill state fix-up can find + // this matrix again if a blocker is later placed inside its range via + // a path that doesn't itself notify the master. + if (nNewCols > 1 || nNewRows > 1) + MarkExpandedDynamicArray(rOrigin); + else + UnmarkExpandedDynamicArray(rOrigin); + + ScDocShell* pDocShell = GetDocumentShell(); + if (pDocShell) + pDocShell->PostPaint(aAffected, PaintPartFlags::Grid); +} + +// Drain the queue of dynamic-array formulas marked for a deferred resize +// (expand, contract, or collapse-on-#SPILL!). +void ScDocument::ProcessPendingMatrixResizes() +{ + if (maPendingMatrixResizes.empty()) + return; + + // A caller is iterating the cell store. Deleting or inserting cells now + // would invalidate that iterator - defer until the guard is popped. + if (IsMatrixResizeGuarded()) + return; + + // Take a snapshot - ResizeMatrixFormula may broadcast and reenter. + std::unordered_set aPending; + aPending.swap(maPendingMatrixResizes); + + for (const ScAddress& rPos : aPending) + { + ScFormulaCell* pFormulaCell = GetFormulaCell(rPos); + if (!pFormulaCell || pFormulaCell->GetMatrixFlag() != ScMatrixMode::Formula) + continue; + + if (pFormulaCell->GetErrCode() == FormulaError::Spill) + { + // Collapse to 1x1: remove materialised reference cells, leaving + // only the origin to show #SPILL!. + ResizeMatrixFormula(rPos, SCCOL(1), SCROW(1)); + continue; + } + + SCCOL nDeclCols = 0; + SCROW nDeclRows = 0; + pFormulaCell->GetMatColsRows(nDeclCols, nDeclRows); + + const ScMatrix* pMatrix = pFormulaCell->GetMatrix(); + if (!pMatrix) + continue; + + SCSIZE nResCols = 0; + SCSIZE nResRows = 0; + pMatrix->GetDimensions(nResCols, nResRows); + + if (SCSIZE(nDeclCols) == nResCols && SCSIZE(nDeclRows) == nResRows) + continue; // already matches + + ResizeMatrixFormula(rPos, static_cast(nResCols), static_cast(nResRows)); + } } void ScDocument::InsertTableOp(const ScTabOpParam& rParam, // multiple (repeated?) operation @@ -454,15 +731,19 @@ bool setCacheTableReferenced(const ScDocument& rDoc, formula::FormulaToken& rTok switch (rToken.GetType()) { case svExternalSingleRef: + { + auto rESRToken = static_cast(rToken); return rRefMgr.setCacheTableReferenced( - rToken.GetIndex(), rToken.GetString().getString(), 1); + rESRToken.GetFileId(), rESRToken.GetTableName().getString(), 1); + } case svExternalDoubleRef: { - const ScComplexRefData& rRef = *rToken.GetDoubleRef(); + auto rEDRToken = static_cast(rToken); + const ScComplexRefData& rRef = rEDRToken.GetDoubleRef(); ScRange aAbs = rRef.toAbs(rDoc, rPos); size_t nSheets = aAbs.aEnd.Tab() - aAbs.aStart.Tab() + 1; return rRefMgr.setCacheTableReferenced( - rToken.GetIndex(), rToken.GetString().getString(), nSheets); + rEDRToken.GetFileId(), rEDRToken.GetTableName().getString(), nSheets); } case svExternalName: /* TODO: external names aren't supported yet, but would @@ -502,7 +783,7 @@ bool ScDocument::MarkUsedExternalReferences( const ScTokenArray& rArr, const ScA { // this is a named range. Check if the range contains an external // reference. - ScRangeData* pRangeData = GetRangeName()->findByIndex(t->GetIndex()); + ScRangeData* pRangeData = GetRangeName().findByIndex(static_cast(t)->GetIndex()); if (!pRangeData) continue; diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx index 6d9f29d83bee..f091bf6419a7 100644 --- a/sc/source/core/data/documen7.cxx +++ b/sc/source/core/data/documen7.cxx @@ -435,6 +435,9 @@ void ScDocument::CalcFormulaTree( bool bOnlyForced, bool bProgressBar, bool bSet bCalculatingFormulaTree = false; mpFormulaGroupCxt.reset(); + + // Process any dynamic-array expansions queued during interpretation. + ProcessPendingMatrixResizes(); } void ScDocument::ClearFormulaTree() @@ -577,6 +580,12 @@ void ScDocument::TrackFormulas( SfxHintId nHintId ) } } OSL_ENSURE( nFormulaTrackCount==0, "TrackFormulas: nFormulaTrackCount!=0" ); + + // Process any pending dynamic-array expansions queued. + // We're outside any active interpreter here, so creating reference cells + // is safe. + if (!IsInInterpreter()) + ProcessPendingMatrixResizes(); } void ScDocument::StartAllListeners() diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx index 783686165971..d77fbdf8d948 100644 --- a/sc/source/core/data/documen8.cxx +++ b/sc/source/core/data/documen8.cxx @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include @@ -1036,21 +1036,6 @@ bool ScDocument::SetDdeLinkResultMatrix( size_t nDdePos, const ScMatrixRef& pRes return false; } -bool ScDocument::HasAreaLinks() const -{ - const sfx2::LinkManager* pMgr = GetDocLinkManager().getExistingLinkManager(); - if (!pMgr) - return false; - - const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks(); - sal_uInt16 nCount = rLinks.size(); - for (sal_uInt16 i=0; i(rLinks[i].get())) - return true; - - return false; -} - void ScDocument::UpdateAreaLinks() { sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false); diff --git a/sc/source/core/data/documen9.cxx b/sc/source/core/data/documen9.cxx index 23a7baa90d9a..f767bc480d2d 100644 --- a/sc/source/core/data/documen9.cxx +++ b/sc/source/core/data/documen9.cxx @@ -51,6 +51,9 @@ #include #include #include +#include +#include +#include using namespace ::com::sun::star; @@ -128,8 +131,10 @@ void ScDocument::InitDrawLayer( ScDocShell* pDocShell ) aName = mpShell->GetTitle(); mpDrawLayer.reset(new ScDrawLayer( this, aName )); - sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc); - if (pMgr) + // Create the LinkManager up front (not gated on bAutoCalc) so the draw + // layer can register fill bitmap links as shapes are imported. Setting it + // also installs SdrModel's fill bitmap link tracker. + if (sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(true)) mpDrawLayer->SetLinkManager(pMgr); // set DrawingLayer's SfxItemPool at Calc's SfxItemPool as @@ -186,6 +191,18 @@ void ScDocument::InitDrawLayer( ScDocShell* pDocShell ) mpDrawLayer->SetForbiddenCharsTable( xForbiddenCharacters ); mpDrawLayer->SetCharCompressType( GetAsianCompression() ); mpDrawLayer->SetKernAsianPunctuation( GetAsianKerning() ); + + // Generate default table styles from the document's theme colors. + // The SdrModel constructor provides a default Theme("Office") with a ColorSet, + // so theme colors are always available at this point. + if (!mpTableStyles->HasTableStyle()) + { + if (auto pTheme = mpDrawLayer->getTheme()) + { + if (auto pColorSet = pTheme->getColorSet()) + ScTableStyleGenerator::generateDefaultStyles(*this, *pColorSet); + } + } } void ScDocument::UpdateDrawLanguages() @@ -241,6 +258,23 @@ IMPL_LINK( ScDocument, GetUserDefinedColor, sal_uInt16, nColorIndex, Color* ) return const_cast(&(xColorList->GetColor(nColorIndex)->GetColor())); } +IMPL_LINK(ScDocument, GetUserDefinedColorIndex, const Color&, rColor, sal_Int32) +{ + rtl::Reference xColorList; + if (mpDrawLayer) + xColorList = mpDrawLayer->GetColorList(); + else + { + ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); + if (!pColorList.is()) + pColorList = XColorList::CreateStdColorList(); + xColorList = pColorList; + } + + return xColorList->GetIndexOfColor(rColor); +} + + bool ScDocument::DrawGetPrintArea( ScRange& rRange, bool bSetHor, bool bSetVer ) const { return mpDrawLayer->GetPrintArea( rRange, bSetHor, bSetVer ); @@ -410,7 +444,7 @@ SdrObject* ScDocument::GetObjectAtPoint( SCTAB nTab, const Point& rPos ) if ( pObject->GetCurrentBoundRect().Contains(rPos) ) { // Intern is of no interest - // Only object form background layer, when no object form another layer is found + // Only object from background layer, when no object from another layer is found SdrLayerID nLayer = pObject->GetLayer(); if ( (nLayer != SC_LAYER_INTERN) && (nLayer != SC_LAYER_HIDDEN) ) { diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 6182aa081613..fca80ec24491 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -104,6 +104,8 @@ #include #include +#include + using ::editeng::SvxBorderLine; using namespace ::com::sun::star; @@ -557,6 +559,8 @@ bool ScDocument::InsertTab( pValidationList->UpdateInsertTab(aCxt); } + UpdateQueryTables(aCxt); + bValid = true; } else @@ -647,6 +651,8 @@ bool ScDocument::InsertTabs( SCTAB nPos, const std::vector& rNames, pValidationList->UpdateInsertTab(aCxt); } + UpdateQueryTables(aCxt); + bValid = true; } else @@ -732,23 +738,25 @@ bool ScDocument::DeleteTab( SCTAB nTab ) auto pManager = pTable->GetSheetViewManager(); if (pManager) { - for (auto const& pSheetView : pManager->getSheetViews()) + for (auto const& rSheetView : pManager->iterateValidSheetViews()) { // Set the table pointer to null as the table will be deleted - pSheetView->getTablePointer()->RemoveSheetViewTablePointer(); + rSheetView.getTablePointer()->RemoveSheetViewTablePointer(); } } } } - // tdf#149502 make sure ScTable destructor called after the erase is finished, when + // tdf#149502 make sure ScTable destructor is called after the erase is finished, when // maTabs[x].nTab==x is true again, as it should be always true. // In the end of maTabs.erase, maTabs indexes change, but nTab updated before erase. - // ~ScTable expect that maTabs[x].nTab==x so it shouldn't be called during erase. + // ~ScTable expects that maTabs[x].nTab==x so it shouldn't be called during erase. ScTableUniquePtr pErasedTab = std::move(maTabs[nTab]); maTabs.erase(maTabs.begin() + nTab); delete pErasedTab.release(); + UpdateQueryTables(aCxt); + // UpdateBroadcastAreas must be called between UpdateDeleteTab, // which ends listening, and StartAllListeners, to not modify // areas that are to be inserted by starting listeners. @@ -774,6 +782,7 @@ bool ScDocument::DeleteTab( SCTAB nTab ) SfxLokHelper::notifyDocumentSizeChangedAllViews(pModel); } + BroadcastRefError(aCxt.maRefErrors); bValid = true; } } @@ -839,6 +848,9 @@ bool ScDocument::DeleteTabs( SCTAB nTab, SCTAB nSheets ) pTab->UpdateDeleteTab(aCxt); maTabs.erase(maTabs.begin() + nTab, maTabs.begin() + nTab + nSheets); + + UpdateQueryTables(aCxt); + // UpdateBroadcastAreas must be called between UpdateDeleteTab, // which ends listening, and StartAllListeners, to not modify // areas that are to be inserted by starting listeners. @@ -864,12 +876,70 @@ bool ScDocument::DeleteTabs( SCTAB nTab, SCTAB nSheets ) SfxLokHelper::notifyDocumentSizeChangedAllViews(pModel); } + BroadcastRefError(aCxt.maRefErrors); bValid = true; } } return bValid; } +void ScDocument::UpdateQueryTables(const sc::RefUpdateInsertTabContext& rCxt) +{ + if (maSheetQueryTables.empty()) + return; + + std::map aNew; + for (auto& [nTab, rVec] : maSheetQueryTables) + { + if (nTab >= rCxt.mnInsertPos) + aNew[nTab + rCxt.mnSheets] = std::move(rVec); + else + aNew[nTab] = std::move(rVec); + } + maSheetQueryTables = std::move(aNew); +} + +void ScDocument::UpdateQueryTables(const sc::RefUpdateDeleteTabContext& rCxt) +{ + if (maSheetQueryTables.empty()) + return; + + std::map aNew; + for (auto& [nTab, rVec] : maSheetQueryTables) + { + if (nTab >= rCxt.mnDeletePos && nTab < rCxt.mnDeletePos + rCxt.mnSheets) + continue; // deleted sheet + if (nTab >= rCxt.mnDeletePos + rCxt.mnSheets) + aNew[nTab - rCxt.mnSheets] = std::move(rVec); + else + aNew[nTab] = std::move(rVec); + } + maSheetQueryTables = std::move(aNew); +} + +void ScDocument::UpdateQueryTables(const sc::RefUpdateMoveTabContext& rCxt) +{ + if (maSheetQueryTables.empty()) + return; + + SCTAB nLower = std::min(rCxt.mnOldPos, rCxt.mnNewPos); + SCTAB nUpper = std::max(rCxt.mnOldPos, rCxt.mnNewPos); + + std::map aNew; + for (auto& [nTab, rVec] : maSheetQueryTables) + { + if (nTab < nLower || nTab > nUpper) + aNew[nTab] = std::move(rVec); + else if (nTab == rCxt.mnOldPos) + aNew[rCxt.mnNewPos] = std::move(rVec); + else if (rCxt.mnOldPos < rCxt.mnNewPos) + aNew[nTab - 1] = std::move(rVec); + else + aNew[nTab + 1] = std::move(rVec); + } + maSheetQueryTables = std::move(aNew); +} + bool ScDocument::RenameTab( SCTAB nTab, const OUString& rName, bool bExternalDocument ) { bool bValid = false; @@ -1117,13 +1187,6 @@ void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, pTable->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown ); } -void ScDocument::GetBackColorArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, - SCCOL& rEndCol, SCROW& rEndRow ) const -{ - if (ValidTab(nTab) && nTab < static_cast (maTabs.size()) && maTabs[nTab]) - maTabs[nTab]->GetBackColorArea( rStartCol, rStartRow, rEndCol, rEndRow ); -} - bool ScDocument::GetDataAreaSubrange(ScRange& rRange) const { SCTAB nTab = rRange.aStart.Tab(); @@ -1502,6 +1565,8 @@ void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab, if (pChartListenerCollection) pChartListenerCollection->UpdateDirtyCharts(); + + BroadcastRefError(aCxt.maRefErrors); } void ScDocument::DeleteRow( const ScRange& rRange ) @@ -1718,6 +1783,8 @@ void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTA if (pChartListenerCollection) pChartListenerCollection->UpdateDirtyCharts(); + + BroadcastRefError(aCxt.maRefErrors); } void ScDocument::DeleteCol( const ScRange& rRange ) @@ -2172,7 +2239,7 @@ void ScDocument::CopyToDocument(const ScRange& rRange, pTab->CopyToTable( aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(), aNewRange.aEnd.Col(), aNewRange.aEnd.Row(), nFlags, bOnlyMarked, pDestTab, pMarks, false, bColRowFlags, - /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true); + ScCloneFlags::Default, /*bCopyCaptions*/true); } rDestDoc.StartAllListeners(aNewRange); @@ -2253,6 +2320,7 @@ void ScDocument::CopyToClip(const ScClipParam& rClipParam, sc::CopyToClipContext aCxt(*pClipDoc, bKeepScenarioFlags); CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks); + CopyDBsToClip(pClipDoc, rClipParam.maRanges, pMarks); // 1. Copy selected cells for (SCTAB i = 0; i < nEndTab; ++i) @@ -2379,12 +2447,12 @@ void ScDocument::TransposeClip(ScDocument* pTransClip, InsertDeleteFlags nFlags, if (pRangeName) { - pTransClip->GetRangeName()->clear(); + pTransClip->GetRangeName().clear(); for (const auto& rEntry : *pRangeName) { sal_uInt16 nIndex = rEntry.second->GetIndex(); - ScRangeData* pData = new ScRangeData(*rEntry.second); - if (pTransClip->pRangeName->insert(pData)) + ScRangeData* pData = pTransClip->pRangeName->insert(std::make_unique(*rEntry.second)); + if (pData) pData->SetIndex(nIndex); } } @@ -2477,10 +2545,10 @@ void ScDocument::TransposeClip(ScDocument* pTransClip, InsertDeleteFlags nFlags, namespace { -void copyUsedNamesToClip(ScRangeName* pClipRangeName, ScRangeName* pRangeName, +void copyUsedNamesToClip(ScRangeName& rClipRangeName, ScRangeName* pRangeName, const sc::UpdatedRangeNames::NameIndicesType& rUsedNames) { - pClipRangeName->clear(); + rClipRangeName.clear(); for (const auto& rEntry : *pRangeName) //TODO: also DB and Pivot regions!!! { sal_uInt16 nIndex = rEntry.second->GetIndex(); @@ -2488,8 +2556,8 @@ void copyUsedNamesToClip(ScRangeName* pClipRangeName, ScRangeName* pRangeName, if (!bInUse) continue; - ScRangeData* pData = new ScRangeData(*rEntry.second); - if (pClipRangeName->insert(pData)) + ScRangeData* pData = rClipRangeName.insert(std::make_unique(*rEntry.second)); + if (pData) pData->SetIndex(nIndex); } } @@ -2515,6 +2583,100 @@ void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClip copyUsedNamesToClip(pClipDoc->GetRangeName(), pRangeName.get(), aUsedGlobalNames); } +// Carry named database ranges that overlap the copied area into the +// clipboard document. Without this, structured-reference tokens in the +// copied formulas have no ScDBData to resolve against on the clip side, +// so any later stringification of those formulas writes #REF! in place +// of the column name. +void ScDocument::CopyDBsToClip(ScDocument* pClipDoc, const ScRangeList& rClipRanges, const ScMarkData* pMarks) +{ + if (!pDBCollection || pDBCollection->getNamedDBs().empty()) + return; + + ScDBCollection* pClipDBs = pClipDoc->GetDBCollection(); + if (!pClipDBs) + return; + ScDBCollection::NamedDBs& rDest = pClipDBs->getNamedDBs(); + + for (const auto& rxSrc : pDBCollection->getNamedDBs()) + { + ScRange aArea; + rxSrc->GetArea(aArea); + if (pMarks && !pMarks->GetTableSelect(aArea.aStart.Tab())) + continue; + // Carry only a table that overlaps a copied range. A table sitting in + // the gap of a non-contiguous selection falls inside the bounding box + // but in none of the copied ranges, and its cells are not copied. + if (!rClipRanges.Intersects(aArea)) + continue; + auto pClone = std::make_unique(*rxSrc); + rDest.insert(std::move(pClone)); + } +} + +// Counterpart of CopyDBsToClip on the paste side: recreate a fully-copied +// named table in the destination, anchored to the paste location rather than +// the source coordinates it was carried with - otherwise the table, with its +// autofilter and style, would sit over the wrong (usually empty) cells. +// A same-document paste keeps the existing table instead (reconstructing an +// independent copy with a fresh unique name is intentionally out of scope). +void ScDocument::CopyDBsFromClip(const ScRange& rDestRange, const ScRange& rClipRange, + const ScDocument* pClipDoc) +{ + if (!pClipDoc) + return; + const ScDBCollection* pClipDBs = pClipDoc->GetDBCollection(); + if (!pClipDBs || pClipDBs->getNamedDBs().empty()) + return; + + if (!pDBCollection) + SetDBCollection(std::unique_ptr(new ScDBCollection(*this))); + ScDBCollection::NamedDBs& rDest = pDBCollection->getNamedDBs(); + + // The whole copied block shifts uniformly from the clip origin to the + // paste origin; the table area moves by the same delta and onto the + // destination sheet. + const SCCOL nDx = rDestRange.aStart.Col() - rClipRange.aStart.Col(); + const SCROW nDy = rDestRange.aStart.Row() - rClipRange.aStart.Row(); + const SCTAB nDestTab = rDestRange.aStart.Tab(); + + for (const auto& rxClip : pClipDBs->getNamedDBs()) + { + // Only recreate a table the copy fully covered; a partial copy must + // not register a clipped or misplaced table. + ScRange aSrcArea; + rxClip->GetArea(aSrcArea); + if (!rClipRange.Contains(aSrcArea)) + continue; + + // Destination already owns a table of this name (same-document paste): + // leave it, and any references resolving to it, alone. + if (rDest.findByUpperName(rxClip->GetUpperName())) + continue; + + const SCCOL nNewCol1 = aSrcArea.aStart.Col() + nDx; + const SCROW nNewRow1 = aSrcArea.aStart.Row() + nDy; + const SCCOL nNewCol2 = aSrcArea.aEnd.Col() + nDx; + const SCROW nNewRow2 = aSrcArea.aEnd.Row() + nDy; + if (!ValidColRowTab(nNewCol1, nNewRow1, nDestTab) || !ValidColRowTab(nNewCol2, nNewRow2, nDestTab)) + continue; + + auto pClone = std::make_unique(*rxClip); + pClone->SetIndex(0); // let the destination assign a fresh, collision-free index + + // Changing the area resets the table column names, because the header + // range moves. Keep the names the clip carried so a structured + // reference still resolves a column by name. The block is a pure + // translation, so the names map to the same columns as before. + std::vector aColumnNames = pClone->GetTableColumnNames(); + pClone->MoveTo(nDestTab, nNewCol1, nNewRow1, nNewCol2, nNewRow2); + if (!aColumnNames.empty()) + pClone->SetTableColumnNames(std::move(aColumnNames)); + + rDest.insert(std::move(pClone)); + } +} + ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument& rDoc, const ScDocument& rSrcDoc) : mrDoc(rDoc) { @@ -2886,7 +3048,7 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark, InsertDeleteFlags nInsFlag, ScDocument* pRefUndoDoc, ScDocument* pClipDoc, bool bResetCut, bool bAsLink, bool bIncludeFiltered, bool bSkipEmptyCells, - const ScRangeList * pDestRanges ) + const ScRangeList * pDestRanges, bool bPreserveDestProtection ) { if (bIsClip) return; @@ -2967,10 +3129,60 @@ void ScDocument::CopyFromClip( pDestRanges = &aLocalRangeList; } + // Recreate named tables the copy fully covered at the paste location, so the + // structured-reference tokens resolved further down bind to a table placed + // at the paste position. Only a formula paste carries such tokens, so a + // values-only paste needs no table. Must run before the cells, and their + // formulas, are copied in. + if (nInsFlag & InsertDeleteFlags::FORMULA) + CopyDBsFromClip(rDestRange, aClipRange, pClipDoc); + bInsertingFromOtherDoc = true; // No Broadcast/Listener created at Insert sc::ColumnSpanSet aBroadcastSpans; + // An interactive paste treats a cell's own directly applied protection as + // a property of the cell, not of the pasted data: copying a protected cell + // onto a cell the user directly unprotected must leave it editable (and + // vice versa). Note the directly set protection over the destination now, + // and put it back once the pasted attributes have overwritten it below. + // Only direct formatting is handled here; protection that instead comes + // from a cell style (including a style that conditional formatting applies) + // is left to follow the usual paste. A moved cell (cut and paste) keeps its + // own protection, so it is excluded. + struct KeptProtection + { + SCTAB nTab; + SCCOL nCol; + SCROW nRow1; + SCROW nRow2; + ScProtectionAttr aProtection; + }; + std::vector aKeptProtection; + const bool bKeepDestProtection = bPreserveDestProtection + && (nInsFlag & InsertDeleteFlags::ATTRIB) + && !pClipDoc->GetClipParam().mbCutMode; + if (bKeepDestProtection) + { + for (const SCTAB nTab : rMark) + { + for (const ScRange& rRange : *pDestRanges) + { + ScDocAttrIterator aIter(*this, nTab, rRange.aStart.Col(), rRange.aStart.Row(), + rRange.aEnd.Col(), rRange.aEnd.Row()); + SCCOL nAttrCol; + SCROW nAttrRow1, nAttrRow2; + while (const ScPatternAttr* pPattern = aIter.GetNext(nAttrCol, nAttrRow1, nAttrRow2)) + { + if (const ScProtectionAttr* pProtect + = pPattern->GetItemSet().GetItemIfSet(ATTR_PROTECTION, false)) + aKeptProtection.push_back( + { nTab, nAttrCol, nAttrRow1, nAttrRow2, *pProtect }); + } + } + } + } + SCCOL nClipStartCol = aClipRange.aStart.Col(); SCROW nClipStartRow = aClipRange.aStart.Row(); SCROW nClipEndRow = aClipRange.aEnd.Row(); @@ -3079,6 +3291,15 @@ void ScDocument::CopyFromClip( bInsertingFromOtherDoc = false; + // Put back the destination's own direct protection that the paste above + // overwrote (see the note where aKeptProtection is filled). + for (const KeptProtection& rKept : aKeptProtection) + { + ScPatternAttr aPattern(getCellAttributeHelper()); + aPattern.ItemSetPut(rKept.aProtection); + ApplyPatternAreaTab(rKept.nCol, rKept.nRow1, rKept.nCol, rKept.nRow2, rKept.nTab, aPattern); + } + if (nInsFlag & InsertDeleteFlags::CONTENTS) { for (SCTAB nTab : rMark) @@ -3379,12 +3600,12 @@ void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark, maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow, InsertDeleteFlags::CONTENTS, false, pMixDoc->maTabs[i].get(), /*pMarkData*/nullptr, /*bAsLink*/false, /*bColRowFlags*/true, - /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true ); + ScCloneFlags::Default, /*bCopyCaptions*/true ); } maTabs[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags); pSourceTable->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow, nFlags, false, maTabs[i].get(), nullptr, bAsLink, - /*bColRowFlags*/true, /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true ); + /*bColRowFlags*/true, ScCloneFlags::Default, /*bCopyCaptions*/true ); if (bDoMix) maTabs[i]->MixData(aMixDocCxt, nStartCol,nStartRow, nEndCol,nEndRow, @@ -3444,14 +3665,14 @@ void ScDocument::FillTabMarked( SCTAB nSrcTab, const ScMarkData& rMark, sc::CopyToDocContext aMixCxt(*pMixDoc); maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow, InsertDeleteFlags::CONTENTS, true, pMixDoc->maTabs[i].get(), &rMark, - /*bAsLink*/false, /*bColRowFlags*/true, /*bGlobalNamesToLocal*/false, + /*bAsLink*/false, /*bColRowFlags*/true, ScCloneFlags::Default, /*bCopyCaptions*/true ); } maTabs[i]->DeleteSelection( nDelFlags, rMark ); pSourceTable->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow, nFlags, true, maTabs[i].get(), &rMark, bAsLink, - /*bColRowFlags*/true, /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true ); + /*bColRowFlags*/true, ScCloneFlags::Default, /*bCopyCaptions*/true ); if (bDoMix) maTabs[i]->MixMarked(aMixDocCxt, rMark, nFunction, bSkipEmpty, pMixDoc->maTabs[i].get()); @@ -3497,6 +3718,11 @@ bool ScDocument::SetString( return SetString(rPos.Col(), rPos.Row(), rPos.Tab(), rString, pParam); } +bool ScDocument::SetEditText( const ScAddress& rPos, EditTextObject aEditText ) +{ + return SetEditText(rPos, std::make_unique(std::move(aEditText))); +} + bool ScDocument::SetEditText( const ScAddress& rPos, std::unique_ptr pEditText ) { if (ScTable* pTable = FetchTable(rPos.Tab())) @@ -3516,7 +3742,7 @@ void ScDocument::SetEditText( const ScAddress& rPos, const OUString& rStr ) { ScFieldEditEngine& rEngine = GetEditEngine(); rEngine.SetTextCurrentDefaults(rStr); - pTable->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject()); + pTable->SetEditText(rPos.Col(), rPos.Row(), std::make_unique(rEngine.CreateTextObject())); } } @@ -3537,7 +3763,7 @@ void ScDocument::SetTextCell(const ScAddress& rPos, const OUString& rStr, { ScFieldEditEngine& rEngine = GetEditEngine(); rEngine.SetTextCurrentDefaults(rStr); - pTable->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject()); + pTable->SetEditText(rPos.Col(), rPos.Row(), std::make_unique(rEngine.CreateTextObject())); } else { @@ -6904,6 +7130,20 @@ bool ScDocument::ContainsNotesInRange( const ScRangeList& rRangeList ) const return false; } +void ScDocument::AddPerson(const ScPersonData& rPerson) +{ + if (std::none_of(maPersonList.begin(), maPersonList.end(), + [&rPerson](const auto& r) { return r.maId == rPerson.maId; })) + maPersonList.push_back(rPerson); +} + +const ScPersonData* ScDocument::GetPersonById(const OUString& rId) const +{ + auto it = std::find_if(maPersonList.begin(), maPersonList.end(), + [&rId](const auto& r) { return r.maId == rId; }); + return it != maPersonList.end() ? &*it : nullptr; +} + void ScDocument::SetAutoNameCache( std::unique_ptr pCache ) { pAutoNameCache = std::move(pCache); @@ -6946,4 +7186,14 @@ void ScDocument::MergeContextBackIntoNonThreadedContext(ScInterpreterContext& th threadedContext.MergeDefaultFormatKeys(*GetFormatTable()); } +void ScDocument::BroadcastRefError(const sc::RefErrorContext& rCtx) +{ + if (!rCtx.mbErrorCreated) + return; + + ScHint aHint(SfxHintId::ScRefErrorCreated, rCtx.maFormulaCell); + if (ScDocShell* pDocSh = GetDocumentShell()) + pDocSh->Broadcast(aHint); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx index e9edef8c98a6..b43bab38c6e1 100644 --- a/sc/source/core/data/document10.cxx +++ b/sc/source/core/data/document10.cxx @@ -24,12 +24,20 @@ #include #include #include +#include +#include +#include #include #include #include #include +#include +#include +#include +#include #include #include +#include // Add totally brand-new methods to this source file. @@ -111,7 +119,7 @@ bool ScDocument::CopyOneCellFromClip( ScAddress aTestPos = aSrcPos; aTestPos.SetCol(nCol); if (pClipDoc->IsMerged(aTestPos)) - // We don't handle merged source cell for this. + // We don't handle merged source cells for this. return false; } @@ -545,6 +553,10 @@ void ScDocument::SetNeedsListeningGroups( const std::vector& rPosArra namespace { +#if defined __GNUC__ && !defined __clang__ && (__GNUC__ == 16 || __GNUC__ == 17) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif class StartNeededListenersHandler { std::shared_ptr mpCxt; @@ -562,6 +574,9 @@ public: p->StartListeners(*mpCxt, false); } }; +#if defined __GNUC__ && !defined __clang__ && (__GNUC__ == 16 || __GNUC__ == 17) +#pragma GCC diagnostic pop +#endif } @@ -650,7 +665,8 @@ bool ScDocument::FindRangeNamesReferencingSheet( sc::UpdatedRangeNames& rIndexes { if (p->GetOpCode() == ocName) { - bRef |= FindRangeNamesReferencingSheet( rIndexes, p->GetSheet(), p->GetIndex(), + auto pIndexToken = static_cast(p); + bRef |= FindRangeNamesReferencingSheet( rIndexes, pIndexToken->GetSheet(), pIndexToken->GetIndex(), nGlobalRefTab, nLocalRefTab, nOldTokenTab, nOldTokenTabReplacement, bSameDoc, nRecursion+1); } } @@ -703,7 +719,7 @@ ScRangeData* copyRangeName( const ScRangeData* pOldRangeData, ScDocument& rNewDo ScAddress aRangePos( pOldRangeData->GetPos()); if (nNewSheet >= 0) aRangePos.SetTab( nNewSheet); - ScRangeData* pRangeData = new ScRangeData(*pOldRangeData, &rNewDoc, &aRangePos); + std::unique_ptr pRangeData(new ScRangeData(*pOldRangeData, &rNewDoc, &aRangePos)); pRangeData->SetIndex(0); // needed for insert to assign a new index ScTokenArray* pRangeNameToken = pRangeData->GetCode(); if (bSameDoc && nNewSheet >= 0) @@ -723,13 +739,10 @@ ScRangeData* copyRangeName( const ScRangeData* pOldRangeData, ScDocument& rNewDo pRangeNameToken->AdjustAbsoluteRefs(rOldDoc, rOldPos, rNewPos, true); } - bool bInserted; if (nNewSheet < 0) - bInserted = rNewDoc.GetRangeName()->insert(pRangeData); + return rNewDoc.GetRangeName().insert(std::move(pRangeData)); else - bInserted = rNewDoc.GetRangeName(nNewSheet)->insert(pRangeData); - - return bInserted ? pRangeData : nullptr; + return rNewDoc.GetRangeName(nNewSheet)->insert(std::move(pRangeData)); } struct SheetIndex @@ -757,10 +770,10 @@ ScRangeData* copyRangeNames( SheetIndexMap& rSheetIndexMap, std::vectorfindByIndex(nOldIndex); + pOldRangeData = GetRangeName().findByIndex(nOldIndex); if (!pOldRangeData) return false; // might be an error in the formula array aRangeName = pOldRangeData->GetUpperName(); @@ -879,9 +892,8 @@ bool ScDocument::CopyAdjustRangeName( SCTAB& rSheet, sal_uInt16& rIndex, ScRange if (!rpRangeData && !bGlobalNamesToLocal) { nNewSheet = -1; - pNewNames = rNewDoc.GetRangeName(); - if (pNewNames) - rpRangeData = pNewNames->findByUpperName(aRangeName); + pNewNames = &rNewDoc.GetRangeName(); + rpRangeData = pNewNames->findByUpperName(aRangeName); } // If no range name was found copy it. if (!rpRangeData) @@ -941,16 +953,17 @@ bool ScDocument::CopyAdjustRangeName( SCTAB& rSheet, sal_uInt16& rIndex, ScRange { if (p->GetOpCode() == ocName) { - auto it = aSheetIndexMap.find( SheetIndex( p->GetSheet(), p->GetIndex())); + auto pIndexToken = static_cast(p); + auto it = aSheetIndexMap.find( SheetIndex( pIndexToken->GetSheet(), pIndexToken->GetIndex())); if (it != aSheetIndexMap.end()) { - p->SetSheet( it->second.mnSheet); - p->SetIndex( it->second.mnIndex); + pIndexToken->SetSheet( it->second.mnSheet); + pIndexToken->SetIndex( it->second.mnIndex); } else if (!bSameDoc) { SAL_WARN("sc.core","adjustCopyRangeName - mapping to new name in other doc missing"); - p->SetIndex(0); // #NAME? error instead of arbitrary name. + pIndexToken->SetIndex(0); // #NAME? error instead of arbitrary name. } } } @@ -1004,15 +1017,6 @@ std::optional ScDocument::GetColumnIterator( SCTAB nTab, SCC return pTab->GetColumnIterator(nCol, nRow1, nRow2); } -void ScDocument::CreateColumnIfNotExists( SCTAB nTab, SCCOL nCol ) -{ - ScTable* pTab = FetchTable(nTab); - if (!pTab) - return; - - pTab->CreateColumnIfNotExists(nCol); -} - bool ScDocument::EnsureFormulaCellResults( const ScRange& rRange, bool bSkipRunning ) { bool bAnyDirty = false; @@ -1038,6 +1042,30 @@ sc::ExternalDataMapper& ScDocument::GetExternalDataMapper() return *mpDataMapper; } +bool ScDocument::HasDataProviderMappings() const +{ + return mpDataMapper && !mpDataMapper->getDataSources().empty(); +} + +bool ScDocument::HasExternalLinks() const +{ + if (ScExternalRefManager* pRefMgr = GetExternalRefManager(); pRefMgr && pRefMgr->hasExternalData()) + return true; + + // sheet links can exist independently from external formula references (#i100042#) + SCTAB nTabCount = GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; ++nTab) + if (IsLinked(nTab)) + return true; + + if (HasLinkFormulaNeedingCheck() || HasDataProviderMappings() + || GetDocLinkManager().hasUpdatableLinks()) + return true; + + const ScDrawLayer* pDrawLayer = GetDrawLayer(); + return pDrawLayer && hasDeferredFillBitmapLinks(pDrawLayer->GetItemPool()); +} + void ScDocument::StoreTabToCache(SCTAB nTab, SvStream& rStrm) const { const ScTable* pTab = FetchTable(nTab); @@ -1140,6 +1168,27 @@ bool ScDocument::IsSheetViewHolder(SCTAB nTab) const return false; } +SCTAB ScDocument::GetDefaultViewTableNumber(SCTAB nTab) const +{ + if (ScTable const* pTable = FetchTable(nTab)) + { + if (ScTable const* pDefaultTable = pTable->GetDefaultViewTable()) + return pDefaultTable->GetTab(); + } + return nTab; +} + +sc::SheetViewID ScDocument::GetTableSheetViewID(SCTAB nTab) const +{ + if (ScTable const* pTable = FetchTable(nTab)) + { + sc::SheetViewID nID = pTable->GetSheetViewID(); + if (nID != sc::InvalidSheetViewID) + return nID; + } + return sc::DefaultSheetViewID; +} + std::pair ScDocument::CreateNewSheetView(SCTAB nTab) { if (ScTable* pTable = FetchTable(nTab)) @@ -1159,15 +1208,6 @@ std::pair ScDocument::CreateNewSheetView(SCTAB nTab) return { sc::InvalidSheetViewID, -1 }; } -bool ScDocument::HasSheetViews(SCTAB nTab) const -{ - if (ScTable const* pTable = FetchTable(nTab)) - { - return !pTable->GetSheetViewManager()->isEmpty(); - } - return false; -} - std::shared_ptr ScDocument::GetSheetViewManager(SCTAB nTable) { if (ScTable* pTable = FetchTable(nTable)) @@ -1178,6 +1218,23 @@ std::shared_ptr ScDocument::GetSheetViewManager(SCTAB nTab return {}; } +std::shared_ptr ScDocument::GetSheetView(SCTAB nTab) +{ + ScTable* pTable = FetchTable(nTab); + if (!pTable || !pTable->IsSheetViewHolder()) + return {}; + + ScTable* pDefaultViewTable = pTable->GetDefaultViewTable(); + if (!pDefaultViewTable) + return {}; + + auto pManager = pDefaultViewTable->GetSheetViewManager(); + if (!pManager) + return {}; + + return pManager->get(pTable->GetSheetViewID()); +} + SCTAB ScDocument::GetSheetViewNumber(SCTAB nTab, sc::SheetViewID nID) { if (ScTable* pMainSheet = FetchTable(nTab)) @@ -1190,9 +1247,95 @@ SCTAB ScDocument::GetSheetViewNumber(SCTAB nTab, sc::SheetViewID nID) { return pView->getTablePointer()->GetTab(); } - assert(false && "a non valid sheet view is unexpected..."); } return -1; } +void ScDocument::SyncSheetViews(SCTAB nDefaultViewTable) +{ + std::shared_ptr pManager = GetSheetViewManager(nDefaultViewTable); + if (!pManager || pManager->isEmpty()) + return; + + // Get the anonymous DB data for the default view table + ScDBData* pDefaultViewDBData = GetAnonymousDBData(nDefaultViewTable); + + // Iterate all valid sheet views + for (auto& rSheetView : pManager->iterateValidSheetViews()) + { + SCTAB nSheetViewTab = rSheetView.getTableNumber(); + + // Sync the sheet view's anonymous DB data from the default view + if (pDefaultViewDBData) + { + ScDBData* pSheetViewDBData = GetAnonymousDBData(nSheetViewTab); + if (pSheetViewDBData) + { + ScRange aDefaultRange; + pDefaultViewDBData->GetArea(aDefaultRange); + aDefaultRange.SetTab(nSheetViewTab); + pSheetViewDBData->SetArea(aDefaultRange); + pSheetViewDBData->SetAutoFilter(pDefaultViewDBData->HasAutoFilter()); + + // If auto-filter was removed, reset sheet view sort data + if (!pDefaultViewDBData->HasAutoFilter()) + rSheetView.resetSortData(); + } + } + + // Get the current query (filter) state of the auto-filter + std::optional oQueryParam; + ScDBData* pNoNameData = GetAnonymousDBData(nSheetViewTab); + if (pNoNameData && pNoNameData->HasAutoFilter()) + { + if (pNoNameData->HasQueryParam()) + { + oQueryParam.emplace(); + pNoNameData->GetQueryParam(*oQueryParam); + } + } + + // Overwrite the content from the default view table + OverwriteContent(nDefaultViewTable, nSheetViewTab); + + // Revert the sorting of the default view table. + // It can happen that the default view was sorted after the sheet view + // was created. + if (auto const* pReorderParameters = rSheetView.getReorderParameters()) + { + sc::ReorderParam aReorderParameters(*pReorderParameters); + aReorderParameters.maSortRange.aStart.SetTab(nSheetViewTab); + aReorderParameters.maSortRange.aEnd.SetTab(nSheetViewTab); + aReorderParameters.reverse(); + Reorder(aReorderParameters); + } + + // Sort the sheet view if it was sorted before + if (auto const* pSortParam = rSheetView.getSortParam()) + { + ScSortParam aSortParam(*pSortParam); + + // Adjust the sort range to the actual data extent on the default view. + if (pDefaultViewDBData && pDefaultViewDBData->HasAutoFilter()) + { + ScRange aDBRange; + pDefaultViewDBData->GetArea(aDBRange); + SCCOL nColumn1 = aDBRange.aStart.Col(); + SCROW nRow1 = aDBRange.aStart.Row(); + SCCOL nColumn2 = aDBRange.aEnd.Col(); + SCROW nRow2 = aDBRange.aEnd.Row(); + GetDataArea(nDefaultViewTable, nColumn1, nRow1, nColumn2, nRow2, false, true); + aSortParam.nRow2 = nRow2; + aSortParam.nCol2 = nColumn2; + } + + rSheetView.resetSortOrder(); + Sort(nSheetViewTab, aSortParam, false, false, nullptr, nullptr); + } + // Apply the stored query state (if available) + if (oQueryParam) + Query(nSheetViewTab, *oQueryParam, false, false); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/documentimport.cxx b/sc/source/core/data/documentimport.cxx index b2e823c4a511..b18fbca857ed 100644 --- a/sc/source/core/data/documentimport.cxx +++ b/sc/source/core/data/documentimport.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,19 @@ struct TabAttr std::vector maCols; }; +// The cell store's set() destroys the cell it overwrites with no shared +// formula bookkeeping, so a group whose member dies that way is left with a +// stale length, or with a dead top cell that the next Interpret of a +// surviving member dereferences. Detach the doomed cell from its group first. +void unshareDoomedCell(sc::CellStoreType& rCells, const sc::CellStoreType::iterator& itHint, SCROW nRow) +{ + sc::CellStoreType::position_type aPos = rCells.position(itHint, nRow); + if (aPos.first->type != sc::element_type_formula) + return; + ScFormulaCell& rCell = *sc::formula_block::at(*aPos.first->data, aPos.second); + sc::SharedFormulaUtil::unshareFormulaCell(aPos, rCell); +} + } struct ScDocumentImportImpl @@ -398,7 +412,8 @@ void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCel } void ScDocumentImport::setMatrixCells( - const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram) + const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram, + bool bCheckForSpill) { const ScAddress& rBasePos = rRange.aStart; @@ -421,6 +436,7 @@ void ScDocumentImport::setMatrixCells( mpImpl->mrDoc.CheckLinkFormulaNeedingCheck( *pCell->GetCode()); + unshareDoomedCell(rCells, pBlockPos->miCellPos, rBasePos.Row()); pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rBasePos.Row(), pCell); @@ -428,6 +444,15 @@ void ScDocumentImport::setMatrixCells( pCell->SetMatColsRows( rRange.aEnd.Col()-rRange.aStart.Col()+1, rRange.aEnd.Row()-rRange.aStart.Row()+1); + // The file was saved with a #SPILL! error. Trust that and don't + // materialise reference cells over the matrix range. Any blocker + // cell still sitting in the range survives. + if (bCheckForSpill) + { + pCell->MarkAsSpilled(); + return; + } + // Set the reference cells. ScSingleRefData aRefData; aRefData.InitFlags(); @@ -446,9 +471,10 @@ void ScDocumentImport::setMatrixCells( aPos.SetRow(nRow); // Reference in each cell must point to the origin cell relative to the current cell. aRefData.SetAddress(mpImpl->mrDoc.GetSheetLimits(), rBasePos, aPos); - *t->GetSingleRef() = aRefData; + *ScRefTokenHelper::getSingleRef(t) = aRefData; ScTokenArray aTokArr(aArr.CloneValue()); pCell = new ScFormulaCell(mpImpl->mrDoc, aPos, aTokArr, eGram, ScMatrixMode::Reference); + unshareDoomedCell(rCells, pBlockPos->miCellPos, aPos.Row()); pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, aPos.Row(), pCell); } @@ -466,13 +492,19 @@ void ScDocumentImport::setMatrixCells( { aPos.SetRow(nRow); aRefData.SetAddress(mpImpl->mrDoc.GetSheetLimits(), rBasePos, aPos); - *t->GetSingleRef() = aRefData; + *ScRefTokenHelper::getSingleRef(t) = aRefData; ScTokenArray aTokArr(aArr.CloneValue()); pCell = new ScFormulaCell(mpImpl->mrDoc, aPos, aTokArr, eGram, ScMatrixMode::Reference); + unshareDoomedCell(rColCells, pBlockPos->miCellPos, aPos.Row()); pBlockPos->miCellPos = rColCells.set(pBlockPos->miCellPos, aPos.Row(), pCell); } } + + // Register the expanded matrix master so spill resolution finds it + // again if a blocker is later placed inside its declared range. + if (rRange.aEnd.Col() > rRange.aStart.Col() || rRange.aEnd.Row() > rRange.aStart.Row()) + mpImpl->mrDoc.MarkExpandedDynamicArray(rBasePos); } void ScDocumentImport::setTableOpCells(const ScRange& rRange, const ScTabOpParam& rParam) @@ -618,9 +650,8 @@ void ScDocumentImport::setRowsVisible(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd { if (!bVisible) { + // tdf#171228 - postpone page size/breaks updates to avoid calculations on every row getDoc().ShowRows(nRowStart, nRowEnd, nTab, false); - getDoc().SetDrawPageSize(nTab); - getDoc().UpdatePageBreaks( nTab ); } else { diff --git a/sc/source/core/data/dpdimsave.cxx b/sc/source/core/data/dpdimsave.cxx index 2661606fc51c..e8f77de0fd02 100644 --- a/sc/source/core/data/dpdimsave.cxx +++ b/sc/source/core/data/dpdimsave.cxx @@ -96,18 +96,39 @@ void ScDPSaveGroupItem::RemoveElementsFromGroups( ScDPSaveGroupDimension& rDimen rDimension.RemoveFromGroups( rElement ); } -void ScDPSaveGroupItem::ConvertElementsToItems(SvNumberFormatter* pFormatter) const +void ScDPSaveGroupItem::ConvertElementsToItems(SvNumberFormatter* pFormatter, + const ScDPCache::ScDPItemDataVec& rSourceItems) const { maItems.reserve(aElements.size()); for (const auto& rElement : aElements) { - sal_uInt32 nFormat = 0; - double fValue; ScDPItemData aData; - if (pFormatter->IsNumberFormat(rElement, nFormat, fValue)) - aData.SetValue(fValue); - else - aData.SetString(rElement); + bool bFound = false; + + // This avoids mismatches where e.g. string "02" in the source + // would be converted to numeric 2 by IsNumberFormat. + for (const ScDPItemData& rSrcItem : rSourceItems) + { + if (rSrcItem.GetType() == ScDPItemData::String) + { + if (rSrcItem.GetString().equalsIgnoreAsciiCase(rElement)) + { + aData = rSrcItem; + bFound = true; + break; + } + } + } + + if (!bFound) + { + sal_uInt32 nFormat = 0; + double fValue; + if (pFormatter->IsNumberFormat(rElement, nFormat, fValue)) + aData.SetValue(fValue); + else + aData.SetString(rElement); + } maItems.push_back(aData); } @@ -115,7 +136,19 @@ void ScDPSaveGroupItem::ConvertElementsToItems(SvNumberFormatter* pFormatter) co bool ScDPSaveGroupItem::HasInGroup(const ScDPItemData& rItem) const { - return std::find(maItems.begin(), maItems.end(), rItem) != maItems.end(); + if (std::find(maItems.begin(), maItems.end(), rItem) != maItems.end()) + return true; + + // Empty items are stored as String("") by ConvertElementsToItems + // Match them here so they are correctly mapped to a group + if (rItem.GetType() == ScDPItemData::Empty) + { + ScDPItemData aEmptyStr; + aEmptyStr.SetString(OUString()); + return std::find(maItems.begin(), maItems.end(), aEmptyStr) != maItems.end(); + } + + return false; } void ScDPSaveGroupItem::AddToData(ScDPGroupDimension& rDataDim) const @@ -379,13 +412,13 @@ void ScDPSaveGroupDimension::AddToCache(ScDPCache& rCache) const } rCache.ResetGroupItems(nDim, aDateInfo, 0); + const ScDPCache::ScDPItemDataVec& rItems = rCache.GetDimMemberValues(nSourceDim); for (const ScDPSaveGroupItem& rGI : aGroups) { - rGI.ConvertElementsToItems(pFormatter); + rGI.ConvertElementsToItems(pFormatter, rItems); rCache.SetGroupItem(nDim, ScDPItemData(rGI.GetGroupName())); } - const ScDPCache::ScDPItemDataVec& rItems = rCache.GetDimMemberValues(nSourceDim); for (const ScDPItemData& rItem : rItems) { if (!IsInGroup(rItem)) @@ -796,11 +829,6 @@ ScDPDimCalcSaveData::ScDPDimCalcSaveData() { } -bool ScDPDimCalcSaveData::operator==(const ScDPDimCalcSaveData&) const -{ - return false; -} - void ScDPDimCalcSaveData::WriteToCache(ScDPCache& rCache, const std::vector& rGroupFieldNames) const { diff --git a/sc/source/core/data/dpfilteredcache.cxx b/sc/source/core/data/dpfilteredcache.cxx index 50e087b4c0f1..e343b6dc8256 100644 --- a/sc/source/core/data/dpfilteredcache.cxx +++ b/sc/source/core/data/dpfilteredcache.cxx @@ -98,11 +98,6 @@ sal_Int32 ScDPFilteredCache::getCalculatedColumnCount() const return mrCache.GetCalculatedFieldCount(); } -void ScDPFilteredCache::addCalculatedField(const std::shared_ptr& pField) -{ - maCalcFields.emplace_back(pField); -} - bool ScDPFilteredCache::isCalculatedField(sal_Int32 nDim) const { return std::any_of(maCalcFields.begin(), maCalcFields.end(), @@ -110,16 +105,6 @@ bool ScDPFilteredCache::isCalculatedField(sal_Int32 nDim) const { return nDim == pCalcF->mnIndex; }); } -OUString ScDPFilteredCache::getCalculatedFieldName(sal_Int32 nDim) const -{ - for (const auto& pCalcField : maCalcFields) - { - if (pCalcField->mnIndex == nDim) - return pCalcField->maFieldName; - } - return OUString(); // Empty string -} - OUString ScDPFilteredCache::getCalculation(sal_Int32 nDim) const { for (const auto& pCalcField : maCalcFields) diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index badc5ff378be..ab2b0f16509e 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -79,7 +79,6 @@ #include #include #include -#include #include #include @@ -1021,19 +1020,44 @@ ScRange ScDPObject::GetNewOutputRange( bool& rOverflow ) } } -void ScDPObject::Output( const ScAddress& rPos ) +bool ScDPObject::Output(const ScAddress& rPos, bool bCheckForSpill) { - // clear old output area - mpDocument->DeleteAreaTab(maOutputRange.aStart.Col(), maOutputRange.aStart.Row(), - maOutputRange.aEnd.Col(), maOutputRange.aEnd.Row(), - maOutputRange.aStart.Tab(), InsertDeleteFlags::ALL ); - mpDocument->RemoveFlagsTab( maOutputRange.aStart.Col(), maOutputRange.aStart.Row(), - maOutputRange.aEnd.Col(), maOutputRange.aEnd.Row(), - maOutputRange.aStart.Tab(), ScMF::Auto ); - CreateOutput(); // create mxSource and mpOutput if not already done - mpOutput->SetPosition( rPos ); + mpOutput->SetPosition(rPos); + + if (bCheckForSpill) + { + // Pass the old output range so cells belonging to this pivot table + // are excluded from the non-empty check. + mpOutput->Output(maOutputRange, true); + if (mpOutput->HasSpillError()) + { + // Clear the old output area and write #SPILL! into the origin cell. + mpDocument->DeleteAreaTab( + maOutputRange.aStart.Col(), maOutputRange.aStart.Row(), + maOutputRange.aEnd.Col(), maOutputRange.aEnd.Row(), + maOutputRange.aStart.Tab(), InsertDeleteFlags::ALL); + mpDocument->RemoveFlagsTab( + maOutputRange.aStart.Col(), maOutputRange.aStart.Row(), + maOutputRange.aEnd.Col(), maOutputRange.aEnd.Row(), + maOutputRange.aStart.Tab(), ScMF::Auto); + mpDocument->SetError(rPos.Col(), rPos.Row(), rPos.Tab(), + FormulaError::Spill); + maOutputRange = ScRange(rPos); + mbSpillError = true; + return false; + } + mbSpillError = false; + } + + // Clear the old output area before rendering. + mpDocument->DeleteAreaTab(maOutputRange.aStart.Col(), maOutputRange.aStart.Row(), + maOutputRange.aEnd.Col(), maOutputRange.aEnd.Row(), + maOutputRange.aStart.Tab(), InsertDeleteFlags::ALL); + mpDocument->RemoveFlagsTab(maOutputRange.aStart.Col(), maOutputRange.aStart.Row(), + maOutputRange.aEnd.Col(), maOutputRange.aEnd.Row(), + maOutputRange.aStart.Tab(), ScMF::Auto); mpOutput->Output(); @@ -1042,6 +1066,12 @@ void ScDPObject::Output( const ScAddress& rPos ) const ScAddress& s = maOutputRange.aStart; const ScAddress& e = maOutputRange.aEnd; mpDocument->ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), ScMF::DpTable); + return true; +} + +bool ScDPObject::HasSpillError() const +{ + return mbSpillError; } ScRange ScDPObject::GetOutputRangeByType( sal_Int32 nType ) @@ -1181,6 +1211,11 @@ bool ScDPObject::GetMembers( sal_Int32 nDim, sal_Int32 nHier, std::vectorIsDateDimension(nDim); } void ScDPObject::FillLabelData(sal_Int32 nDim, ScDPLabelData& rLabels) @@ -3984,6 +4023,13 @@ OUString ScDPCollection::CreateNewName() const return OUString(); // should not happen } +void ScDPCollection::DeleteByTab(SCTAB nTab) +{ + std::erase_if(maTables, [nTab](const std::unique_ptr& rxTable) { + return rxTable->GetOutRange().aStart.Tab() == nTab; + }); +} + void ScDPCollection::FreeTable(const ScDPObject* pDPObject) { const ScRange& rOutRange = pDPObject->GetOutRange(); diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx index fd5d38189502..7f2d99feffcc 100644 --- a/sc/source/core/data/dpoutput.cxx +++ b/sc/source/core/data/dpoutput.cxx @@ -20,29 +20,25 @@ #include #include -#include -#include -#include -#include #include #include #include #include #include +#include #include #include #include #include #include -#include -#include #include #include #include #include #include #include +#include #include #include @@ -72,11 +68,6 @@ using namespace com::sun::star; -#define SC_DP_FRAME_INNER_BOLD 20 -#define SC_DP_FRAME_OUTER_BOLD 40 - -#define SC_DP_FRAME_COLOR Color(0,0,0) //( 0x20, 0x40, 0x68 ) - namespace { struct ScDPOutLevelDataComparator @@ -89,228 +80,9 @@ struct ScDPOutLevelDataComparator }; } // end anonymous namespace -class ScDPOutputImpl -{ - ScDocument* mpDoc; - sal_uInt16 mnTab; - std::vector< bool > mbNeedLineCols; - std::vector< SCCOL > mnCols; - - std::vector< bool > mbNeedLineRows; - std::vector< SCROW > mnRows; - - SCCOL mnTabStartCol; - SCROW mnTabStartRow; - - SCCOL mnDataStartCol; - SCROW mnDataStartRow; - SCCOL mnTabEndCol; - SCROW mnTabEndRow; - -public: - ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab, - SCCOL nTabStartCol, - SCROW nTabStartRow, - SCCOL nDataStartCol, - SCROW nDataStartRow, - SCCOL nTabEndCol, - SCROW nTabEndRow ); - bool AddRow( SCROW nRow ); - bool AddCol( SCCOL nCol ); - - void OutputDataArea(); - void OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori = false ); - -}; - -void ScDPOutputImpl::OutputDataArea() -{ - AddRow( mnDataStartRow ); - AddCol( mnDataStartCol ); - - mnCols.push_back( mnTabEndCol+1); //set last row bottom - mnRows.push_back( mnTabEndRow+1); //set last col bottom - - bool bAllRows = ( ( mnTabEndRow - mnDataStartRow + 2 ) == static_cast(mnRows.size()) ); - - std::sort( mnCols.begin(), mnCols.end()); - std::sort( mnRows.begin(), mnRows.end()); - - for( SCCOL nCol = 0; nCol < static_cast(mnCols.size())-1; nCol ++ ) - { - if ( !bAllRows ) - { - if ( nCol < static_cast(mnCols.size())-2) - { - for ( SCROW i = nCol%2; i < static_cast(mnRows.size())-2; i +=2 ) - OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 ); - if ( mnRows.size()>=2 ) - OutputBlockFrame( mnCols[nCol], mnRows[mnRows.size()-2], mnCols[nCol+1]-1, mnRows[mnRows.size()-1]-1 ); - } - else - { - for ( SCROW i = 0 ; i < static_cast(mnRows.size())-1; i++ ) - OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 ); - } - } - else - OutputBlockFrame( mnCols[nCol], mnRows.front(), mnCols[nCol+1]-1, mnRows.back()-1, bAllRows ); - } - //out put rows area outer framer - if ( mnTabStartCol != mnDataStartCol ) - { - if ( mnTabStartRow != mnDataStartRow ) - OutputBlockFrame( mnTabStartCol, mnTabStartRow, mnDataStartCol-1, mnDataStartRow-1 ); - OutputBlockFrame( mnTabStartCol, mnDataStartRow, mnDataStartCol-1, mnTabEndRow ); - } - //out put cols area outer framer - OutputBlockFrame( mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow-1 ); -} - -ScDPOutputImpl::ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab, - SCCOL nTabStartCol, - SCROW nTabStartRow, - SCCOL nDataStartCol, - SCROW nDataStartRow, - SCCOL nTabEndCol, - SCROW nTabEndRow ): - mpDoc( pDoc ), - mnTab( nTab ), - mnTabStartCol( nTabStartCol ), - mnTabStartRow( nTabStartRow ), - mnDataStartCol ( nDataStartCol ), - mnDataStartRow ( nDataStartRow ), - mnTabEndCol( nTabEndCol ), - mnTabEndRow( nTabEndRow ) -{ - mbNeedLineCols.resize( nTabEndCol-nDataStartCol+1, false ); - mbNeedLineRows.resize( nTabEndRow-nDataStartRow+1, false ); - -} - -bool ScDPOutputImpl::AddRow( SCROW nRow ) -{ - if ( !mbNeedLineRows[ nRow - mnDataStartRow ] ) - { - mbNeedLineRows[ nRow - mnDataStartRow ] = true; - mnRows.push_back( nRow ); - return true; - } - else - return false; -} - -bool ScDPOutputImpl::AddCol( SCCOL nCol ) -{ - - if ( !mbNeedLineCols[ nCol - mnDataStartCol ] ) - { - mbNeedLineCols[ nCol - mnDataStartCol ] = true; - mnCols.push_back( nCol ); - return true; - } - else - return false; -} - -void ScDPOutputImpl::OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori ) -{ - Color color = SC_DP_FRAME_COLOR; - ::editeng::SvxBorderLine aLine( &color, SC_DP_FRAME_INNER_BOLD ); - ::editeng::SvxBorderLine aOutLine( &color, SC_DP_FRAME_OUTER_BOLD ); - - SvxBoxItem aBox( ATTR_BORDER ); - - if ( nStartCol == mnTabStartCol ) - aBox.SetLine(&aOutLine, SvxBoxItemLine::LEFT); - else - aBox.SetLine(&aLine, SvxBoxItemLine::LEFT); - - if ( nStartRow == mnTabStartRow ) - aBox.SetLine(&aOutLine, SvxBoxItemLine::TOP); - else - aBox.SetLine(&aLine, SvxBoxItemLine::TOP); - - if ( nEndCol == mnTabEndCol ) //bottom row - aBox.SetLine(&aOutLine, SvxBoxItemLine::RIGHT); - else - aBox.SetLine(&aLine, SvxBoxItemLine::RIGHT); - - if ( nEndRow == mnTabEndRow ) //bottom - aBox.SetLine(&aOutLine, SvxBoxItemLine::BOTTOM); - else - aBox.SetLine(&aLine, SvxBoxItemLine::BOTTOM); - - SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER ); - aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::VERT,false ); - if ( bHori ) - { - aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI); - aBoxInfo.SetLine( &aLine, SvxBoxInfoItemLine::HORI ); - } - else - aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI,false ); - - aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::DISTANCE,false); - - mpDoc->ApplyFrameAreaTab(ScRange(nStartCol, nStartRow, mnTab, nEndCol, nEndRow , mnTab), aBox, aBoxInfo); - -} - namespace { -void lcl_SetStyleById(ScDocument* pDoc, SCTAB nTab, - SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - TranslateId pStrId) -{ - if ( nCol1 > nCol2 || nRow1 > nRow2 ) - { - OSL_FAIL("SetStyleById: invalid range"); - return; - } - - OUString aStyleName = ScResId(pStrId); - ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool(); - ScStyleSheet* pStyle = static_cast( pStlPool->Find( aStyleName, SfxStyleFamily::Para ) ); - if (!pStyle) - { - // create new style (was in ScPivot::SetStyle) - - pStyle = static_cast( &pStlPool->Make( aStyleName, SfxStyleFamily::Para, - SfxStyleSearchBits::UserDefined ) ); - pStyle->SetParent( ScResId(STR_STYLENAME_STANDARD) ); - SfxItemSet& rSet = pStyle->GetItemSet(); - if (pStrId == STR_PIVOT_STYLENAME_RESULT || pStrId == STR_PIVOT_STYLENAME_TITLE){ - rSet.Put( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) ); - rSet.Put( SvxWeightItem( WEIGHT_BOLD, ATTR_CJK_FONT_WEIGHT ) ); - rSet.Put( SvxWeightItem( WEIGHT_BOLD, ATTR_CTL_FONT_WEIGHT ) ); - } - if (pStrId == STR_PIVOT_STYLENAME_CATEGORY || pStrId == STR_PIVOT_STYLENAME_TITLE) - rSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Left, ATTR_HOR_JUSTIFY ) ); - } - - pDoc->ApplyStyleAreaTab( nCol1, nRow1, nCol2, nRow2, nTab, *pStyle ); -} - -void lcl_SetFrame( ScDocument* pDoc, SCTAB nTab, - SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - sal_uInt16 nWidth ) -{ - ::editeng::SvxBorderLine aLine(nullptr, nWidth, SvxBorderLineStyle::SOLID); - SvxBoxItem aBox( ATTR_BORDER ); - aBox.SetLine(&aLine, SvxBoxItemLine::LEFT); - aBox.SetLine(&aLine, SvxBoxItemLine::TOP); - aBox.SetLine(&aLine, SvxBoxItemLine::RIGHT); - aBox.SetLine(&aLine, SvxBoxItemLine::BOTTOM); - SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER ); - aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI,false); - aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::VERT,false); - aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::DISTANCE,false); - - pDoc->ApplyFrameAreaTab(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab), aBox, aBoxInfo); -} - void lcl_FillNumberFormats( std::unique_ptr& rFormats, sal_Int32& rCount, const uno::Reference& xLevRes, const uno::Reference& xDims ) @@ -482,6 +254,7 @@ ScDPOutput::ScDPOutput(ScDocument* pDocument, uno::Reference(*pDocument)) , mxSource(std::move(xSource)) , maStartPos(rPosition) , mnColFormatCount(0) @@ -771,23 +544,11 @@ void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab, if ( !(nFlags & sheet::MemberResultFlags::SUBTOTAL) ) return; - ScDPOutputImpl outputimp(mpDocument, nTab, - mnTabStartCol, mnTabStartRow, - mnDataStartCol, mnDataStartRow, mnTabEndCol, mnTabEndRow); - //TODO: limit frames to horizontal or vertical? + bool bGrandTotal = (nFlags & sheet::MemberResultFlags::GRANDTOTAL) != 0; if (bColHeader) - { - outputimp.OutputBlockFrame(nCol, mnMemberStartRow+static_cast(nLevel), nCol, mnDataStartRow - 1); - - lcl_SetStyleById(mpDocument, nTab, nCol, mnMemberStartRow + static_cast(nLevel), nCol, mnDataStartRow - 1, STR_PIVOT_STYLENAME_TITLE); - lcl_SetStyleById(mpDocument, nTab, nCol, mnDataStartRow, nCol, mnTabEndRow, STR_PIVOT_STYLENAME_RESULT ); - } + mpStyleOutput->addSubtotalColumn(nCol, mnMemberStartRow + SCROW(nLevel), bGrandTotal); else - { - outputimp.OutputBlockFrame(mnMemberStartCol + static_cast(nLevel), nRow, mnDataStartCol - 1, nRow); - lcl_SetStyleById(mpDocument, nTab, mnMemberStartCol + static_cast(nLevel), nRow, mnDataStartCol - 1, nRow, STR_PIVOT_STYLENAME_TITLE); - lcl_SetStyleById(mpDocument, nTab, mnDataStartCol, nRow, mnTabEndCol, nRow, STR_PIVOT_STYLENAME_RESULT); - } + mpStyleOutput->addSubtotalRow(nRow, mnMemberStartCol + SCCOL(nLevel), bGrandTotal); } void ScDPOutput::MultiFieldCell(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bRowField) @@ -807,7 +568,7 @@ void ScDPOutput::MultiFieldCell(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bRowFie nMergeFlag |= ScMF::ButtonPopup2; mpDocument->ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, nMergeFlag); - lcl_SetStyleById(mpDocument, nTab, nCol, nRow, nCol, nRow, STR_PIVOT_STYLENAME_FIELDNAME); + mpStyleOutput->addFieldCell(nCol, nRow, /*bFrame*/ false); } void ScDPOutput::FieldCell( @@ -820,9 +581,6 @@ void ScDPOutput::FieldCell( aParam.mbHandleApostrophe = false; mpDocument->SetString(nCol, nRow, nTab, rData.maCaption, &aParam); - if (bInTable) - lcl_SetFrame(mpDocument, nTab, nCol,nRow, nCol,nRow, 20); - // For field button drawing ScMF nMergeFlag = ScMF::NONE; if (rData.mbHasHiddenMember) @@ -842,7 +600,7 @@ void ScDPOutput::FieldCell( mpDocument->ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, nMergeFlag); } - lcl_SetStyleById(mpDocument, nTab, nCol,nRow, nCol,nRow, STR_PIVOT_STYLENAME_FIELDNAME); + mpStyleOutput->addFieldCell(nCol, nRow, bInTable); } static void lcl_DoFilterButton( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab ) @@ -994,11 +752,11 @@ void ScDPOutput::outputPageFields(SCTAB nTab) aParam.setTextInput(); mpDocument->SetString(nFieldCol, nHeaderRow, nTab, aPageValue, &aParam); - lcl_SetFrame(mpDocument, nTab, nFieldCol, nHeaderRow, nFieldCol, nHeaderRow, 20); + mpStyleOutput->addPageFieldValueCell(nFieldCol, nHeaderRow); } } -void ScDPOutput::outputColumnHeaders(SCTAB nTab, ScDPOutputImpl& rOutputImpl) +void ScDPOutput::outputColumnHeaders(SCTAB nTab) { size_t nNumColFields = mpColFields.size(); @@ -1037,27 +795,7 @@ void ScDPOutput::outputColumnHeaders(SCTAB nTab, ScDPOutputImpl& rOutputImpl) ++nEnd; SCCOL nEndColPos = mnDataStartCol + SCCOL(nEnd); //TODO: check for overflow - if (nField + 1 < mpColFields.size()) - { - if (nField + 2 == mpColFields.size()) - { - rOutputImpl.AddCol( nColPos ); - if (nColPos + 1 == nEndColPos) - rOutputImpl.OutputBlockFrame(nColPos, nRowPos, nEndColPos, nRowPos + 1, true); - } - else - rOutputImpl.OutputBlockFrame(nColPos, nRowPos, nEndColPos, nRowPos); - - lcl_SetStyleById(mpDocument, nTab, nColPos, nRowPos, nEndColPos, mnDataStartRow - 1, STR_PIVOT_STYLENAME_CATEGORY); - } - else - { - lcl_SetStyleById(mpDocument, nTab, nColPos, nRowPos, nColPos, mnDataStartRow - 1, STR_PIVOT_STYLENAME_CATEGORY); - } - } - else if (rMember.Flags & sheet::MemberResultFlags::SUBTOTAL) - { - rOutputImpl.AddCol(nColPos); + mpStyleOutput->addColumnMemberSpan(nField, nColPos, nEndColPos, nRowPos); } // Resolve formats @@ -1066,15 +804,11 @@ void ScDPOutput::outputColumnHeaders(SCTAB nTab, ScDPOutputImpl& rOutputImpl) // Apply the same number format as in data source. mpDocument->ApplyAttr(nColPos, nRowPos, nTab, SfxUInt32Item(ATTR_VALUE_FORMAT, mpColFields[nField].mnSrcNumFmt)); } - if (nField == 0 && mpColFields.size() == 1 && mnMemberStartRow > mnTabStartRow) - rOutputImpl.OutputBlockFrame(mnDataStartCol, mnTabStartRow, mnTabEndCol, nRowPos - 1); } } -void ScDPOutput::outputRowHeader(SCTAB nTab, ScDPOutputImpl& rOutputImpl) +void ScDPOutput::outputRowHeader(SCTAB nTab) { - std::vector vbSetBorder; - vbSetBorder.resize(mnTabEndRow - mnDataStartRow + 1, false); size_t nFieldColOffset = 0; size_t nFieldIndentLevel = 0; // To calculate indent level for fields packed in a column. size_t nNumRowFields = mpRowFields.size(); @@ -1103,31 +837,13 @@ void ScDPOutput::outputRowHeader(SCTAB nTab, ScDPOutputImpl& rOutputImpl) HeaderCell( nColPos, nRowPos, nTab, rData, false, nFieldColOffset ); if (bHasMember && !bSubtotal) { - if (nField + 1 < mpRowFields.size()) + tools::Long nEnd = nRow; + while (nEnd + 1 < nThisRowCount && (pMemberArray[nEnd + 1].Flags & sheet::MemberResultFlags::CONTINUE)) { - tools::Long nEnd = nRow; - while (nEnd + 1 < nThisRowCount && (pMemberArray[nEnd + 1].Flags & sheet::MemberResultFlags::CONTINUE)) - { - ++nEnd; - } - SCROW nEndRowPos = mnDataStartRow + SCROW(nEnd); //TODO: check for overflow - rOutputImpl.AddRow(nRowPos); - if (!vbSetBorder[nRow] ) - { - rOutputImpl.OutputBlockFrame(nColPos, nRowPos, mnTabEndCol, nEndRowPos); - vbSetBorder[nRow] = true; - } - rOutputImpl.OutputBlockFrame(nColPos, nRowPos, nColPos, nEndRowPos); - - if (nField == mpRowFields.size() - 2) - rOutputImpl.OutputBlockFrame(nColPos + 1, nRowPos, nColPos + 1, nEndRowPos); - - lcl_SetStyleById(mpDocument, nTab, nColPos, nRowPos, mnDataStartCol - 1, nEndRowPos, STR_PIVOT_STYLENAME_CATEGORY); - } - else - { - lcl_SetStyleById(mpDocument, nTab, nColPos, nRowPos, mnDataStartCol - 1, nRowPos, STR_PIVOT_STYLENAME_CATEGORY); + ++nEnd; } + SCROW nEndRowPos = mnDataStartRow + SCROW(nEnd); //TODO: check for overflow + mpStyleOutput->addRowMemberSpan(nField, nColPos, nRowPos, nEndRowPos); // Set flags for collapse/expand buttons and indent field header text { @@ -1136,18 +852,14 @@ void ScDPOutput::outputRowHeader(SCTAB nTab, ScDPOutputImpl& rOutputImpl) tools::Long nIndent = o3tl::convert(13 * (bLast ? nFieldIndentLevel : nMinIndentLevel + nFieldIndentLevel), o3tl::Length::px, o3tl::Length::twip); bool bHasContinue = !bLast && nRow + 1 < nThisRowCount && (pMemberArray[nRow + 1].Flags & sheet::MemberResultFlags::CONTINUE); if (nIndent) - mpDocument->ApplyAttr(nColPos, nRowPos, nTab, ScIndentItem(nIndent)); + mpStyleOutput->addIndent(nColPos, nRowPos, nIndent); if (mbExpandCollapse && !bLast) { - mpDocument->ApplyFlagsTab(nColPos, nRowPos, nColPos, nRowPos, nTab, + mpStyleOutput->addExpander(nColPos, nRowPos, bHasContinue ? ScMF::DpCollapse : ScMF::DpExpand); } } } - else if (bSubtotal) - { - rOutputImpl.AddRow(nRowPos); - } // Resolve formats maFormatOutput.insertFieldMember(nField, mpRowFields[nField], nRow, rMember, nColPos, nRowPos, sc::FormatResultDirection::ROW); @@ -1199,10 +911,45 @@ void ScDPOutput::Output() if (mbSizeOverflow || mbResultsError) // does output area exceed sheet limits? return; // nothing + // Collect the pivot table sections while the content is written, so all the visual + // formatting can be drawn in one pass at the end. + mpStyleOutput->clear(); + { + sc::pivot::Geometry aGeometry; + aGeometry.mnTab = nTab; + aGeometry.mnTabStartCol = mnTabStartCol; + aGeometry.mnTabStartRow = mnTabStartRow; + aGeometry.mnMemberStartCol = mnMemberStartCol; + aGeometry.mnMemberStartRow = mnMemberStartRow; + aGeometry.mnDataStartCol = mnDataStartCol; + aGeometry.mnDataStartRow = mnDataStartRow; + aGeometry.mnTabEndCol = mnTabEndCol; + aGeometry.mnTabEndRow = mnTabEndRow; + aGeometry.mnColumnFieldCount = mpColFields.size(); + aGeometry.mnRowFieldCount = mpRowFields.size(); + mpStyleOutput->setGeometry(aGeometry); + } + // Prepare format output bool bColumnFieldIsDataOnly = mnColCount == 1 && mnRowCount > 0 && mpColFields.empty(); maFormatOutput.prepare(nTab, mpColFields, mpRowFields, bColumnFieldIsDataOnly); + // Set grand total positions and data area for format output matching + { + bool bColumnGrand = false; + bool bRowGrand = false; + uno::Reference xSourcePropertySet(mxSource, uno::UNO_QUERY); + if (xSourcePropertySet.is()) + { + bColumnGrand = ScUnoHelpFunctions::GetBoolProperty(xSourcePropertySet, SC_UNO_DP_COLGRAND); + bRowGrand = ScUnoHelpFunctions::GetBoolProperty(xSourcePropertySet, SC_UNO_DP_ROWGRAND); + } + SCROW nGrandTotalRow = bRowGrand ? mnTabEndRow : -1; + SCCOL nGrandTotalColumn = bColumnGrand ? mnTabEndCol : -1; + maFormatOutput.setGrandTotalPositions(nGrandTotalRow, nGrandTotalColumn); + maFormatOutput.setDataArea(maStartPos.Col(), maStartPos.Row(), mnDataStartCol, mnDataStartRow, mnTabEndCol, mnTabEndRow); + } + // clear whole (new) output area // when modifying table, clear old area ! //TODO: include InsertDeleteFlags::OBJECTS ??? @@ -1222,18 +969,9 @@ void ScDPOutput::Output() } mpDocument->SetString(mnTabStartCol, mnTabStartRow, nTab, maDataDescription); - // set STR_PIVOT_STYLENAME_INNER for whole data area (subtotals are overwritten) + outputColumnHeaders(nTab); - if (mnDataStartRow > mnTabStartRow) - lcl_SetStyleById(mpDocument, nTab, mnTabStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow - 1, STR_PIVOT_STYLENAME_TOP); - lcl_SetStyleById(mpDocument, nTab, mnDataStartCol, mnDataStartRow, mnTabEndCol, mnTabEndRow, STR_PIVOT_STYLENAME_INNER); - - ScDPOutputImpl aOutputImpl(mpDocument, nTab, mnTabStartCol, mnTabStartRow, - mnDataStartCol, mnDataStartRow, mnTabEndCol, mnTabEndRow); - - outputColumnHeaders(nTab, aOutputImpl); - - outputRowHeader(nTab, aOutputImpl); + outputRowHeader(nTab); if (bColumnFieldIsDataOnly) { @@ -1249,7 +987,39 @@ void ScDPOutput::Output() outputDataResults(nTab); - aOutputImpl.OutputDataArea(); + mpStyleOutput->apply(); +} + +void ScDPOutput::Output(const ScRange& rOldRange, bool bCheckForSpill) +{ + mbSpillError = false; + + if (!bCheckForSpill) + { + Output(); + return; + } + + SCTAB nTab = maStartPos.Tab(); + + CalcSizes(); + + if (mbSizeOverflow || mbResultsError) + return; + + // Check if the new output range has non-empty cells outside the old pivot table area. + ScRange aNewRange(maStartPos.Col(), maStartPos.Row(), nTab, mnTabEndCol, mnTabEndRow, nTab); + ScCellIterator aIterator(*mpDocument, aNewRange); + for (bool bHasCell = aIterator.first(); bHasCell; bHasCell = aIterator.next()) + { + if (!aIterator.isEmpty() && !rOldRange.Contains(aIterator.GetPos())) + { + mbSpillError = true; + return; + } + } + + // No spill detected } ScRange ScDPOutput::GetOutputRange( sal_Int32 nRegionType ) diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx index f15abf4586c0..90e85bc11bd0 100644 --- a/sc/source/core/data/dpshttab.cxx +++ b/sc/source/core/data/dpshttab.cxx @@ -262,18 +262,15 @@ const ScRange& ScSheetSourceDesc::GetSourceRange() const { // Obtain the source range from the range name first. maSourceRange = ScRange(); - ScRangeName* pRangeName = mpDoc->GetRangeName(); + ScRangeName& rRangeName = mpDoc->GetRangeName(); do { - if (!pRangeName) - break; - OUString aUpper = ScGlobal::getCharClass().uppercase(maRangeName); - const ScRangeData* pData = pRangeName->findByUpperName(aUpper); + const ScRangeData* pData = rRangeName.findByUpperName(aUpper); if (!pData) break; - // range name found. Fow now, we only use the first token and + // range name found. For now, we only use the first token and // ignore the rest. ScRange aRange; if (!pData->IsReference(aRange)) diff --git a/sc/source/core/data/dptabres.cxx b/sc/source/core/data/dptabres.cxx index 1a33a9952efe..c6e81855f606 100644 --- a/sc/source/core/data/dptabres.cxx +++ b/sc/source/core/data/dptabres.cxx @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -78,21 +79,25 @@ const TranslateId aFuncStrIds[] = // matching enum ScSubTotalFunc {} // SUBTOTAL_FUNC_SELECTION_COUNT - not used for pivot table }; -bool lcl_SearchMember( const std::vector>& list, SCROW nOrder, SCROW& rIndex) +// binary search over the span returning the location found in rIndex. +// The comparison is between nOrder and the result of rGetter which must return a SCROW value. +template +bool lcl_SearchMemberCore(const std::span& list, SCROW nOrder, SCROW& rIndex, const F& rGetter) { bool bFound = false; SCROW nLo = 0; SCROW nHi = list.size() - 1; SCROW nIndex; + while (nLo <= nHi) { nIndex = (nLo + nHi) / 2; - if ( list[nIndex]->GetOrder() < nOrder ) + if (rGetter(list[nIndex]) < nOrder) nLo = nIndex + 1; else { nHi = nIndex - 1; - if ( list[nIndex]->GetOrder() == nOrder ) + if (rGetter(list[nIndex]) == nOrder) { bFound = true; nLo = nIndex; @@ -103,6 +108,18 @@ bool lcl_SearchMember( const std::vector>& lis return bFound; } +bool lcl_SearchMember(const std::vector>& list, SCROW nOrder, + SCROW& rIndex) +{ + return lcl_SearchMemberCore(std::span{ list }, nOrder, rIndex, + [](const auto& m) { return m->GetOrder(); }); +} + +bool lcl_SearchMember(const std::span& list, SCROW nOrder, SCROW& rIndex) +{ + return lcl_SearchMemberCore(list, nOrder, rIndex, [](const auto& m) { return m.GetOrder(); }); +} + class FilterStack { std::vector& mrFilters; @@ -230,7 +247,7 @@ bool ScDPRowMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) con const ScDPResultMember* pMember1 = rDimension.GetMember(nIndex1); const ScDPResultMember* pMember2 = rDimension.GetMember(nIndex2); -// make the hide item to the largest order. + // make hidden items have the largest order. if ( !pMember1->IsVisible() || !pMember2->IsVisible() ) return pMember1->IsVisible(); const ScDPDataMember* pDataMember1 = pMember1->GetDataRoot() ; @@ -267,7 +284,6 @@ void ScDPInitState::RemoveMember() } namespace { - #if DUMP_PIVOT_TABLE void dumpRow( const OUString& rType, const OUString& rName, const ScDPAggData* pAggData, @@ -757,7 +773,7 @@ static ScSubTotalFunc lcl_GetForceFunc( const ScDPLevel* pLevel, tools::Long nFu if ( nSequence && aSeq[0] != sheet::GeneralFunction2::AUTO ) { // For manual subtotals, "automatic" is added as first function. - // ScDPResultMember::GetSubTotalCount adds to the count, here NONE has to be + // ScDPResultMemberFull::GetSubTotalCount adds to the count, here NONE has to be // returned as the first function then. --nFuncNo; // keep NONE for first (check below), move the other entries @@ -988,7 +1004,74 @@ ResultMembers& ScDPResultData::GetDimResultMembers(tools::Long nDim, const ScDPD return *maDimMembers[nDim]; } -ScDPResultMember::ScDPResultMember( +ScDPResultMemberSlim::ScDPResultMemberSlim( + ScDPResultDimension* pRDimension, + const ScDPParentDimData& rParentDimData) : + mpOurDimension(pRDimension), + mpMemberDesc(rParentDimData.mpMemberDesc), + mnOrder(rParentDimData.mnOrder), + bmHasElements(false), + bmHasHiddenDetails(false), + bmInitialized(false), + bmPromoted(false) +{ +}; + +// Used for array new, items filled in shortly after +ScDPResultMemberSlim::ScDPResultMemberSlim() + : mpOurDimension(nullptr) + , mpMemberDesc(nullptr) + , mnOrder(std::numeric_limits::max()) + , // To stop false matches during init + bmHasElements(false) + , bmHasHiddenDetails(false) + , bmInitialized(false) + , bmPromoted(false){}; + +ScDPResultMember* ScDPResultMemberSlim::GetPromote() const +{ + return mpOurDimension->GetPromote(mnOrder); +} + +ScDPResultMember* ScDPResultMemberSlim::Promote(const char* sReason) +{ + // If we've already been promoted just retrieve it + if (bmPromoted) + return GetPromote(); + + SAL_INFO("sc.core", "ScDPResultMemberSlim::Promote for " << sReason << " on " << this); + ScDPResultMember* pNewMember = mpOurDimension->Promote(this, mnOrder); + + // Really do expect it to be promoted! + assert(pNewMember != this); + bmPromoted = true; + + return pNewMember; +} + +const ScDPDimension* ScDPResultMemberSlim::GetParentDim() const +{ + if (bmPromoted) + return GetPromote()->GetParentDim(); + // We don't store the Parent information, ask our dimension + return mpOurDimension->GetParentDimForResult(); +} + +const ScDPLevel* ScDPResultMemberSlim::GetParentLevel() const +{ + if (bmPromoted) + return GetPromote()->GetParentLevel(); + // We don't store the Parent information, ask our dimension + return mpOurDimension->GetParentLevelForResult(); +} + +const ScDPResultData* ScDPResultMemberSlim::GetResultData() const +{ + // pResultData is constant over the dimension, just ask it + return mpOurDimension->GetResultData(); +} + +ScDPResultMemberFull::ScDPResultMemberFull( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData ) : pResultData( pData ), aParentDimData( rParentDimData ), @@ -1002,7 +1085,7 @@ ScDPResultMember::ScDPResultMember( // pParentLevel/pMemberDesc is 0 for root members } -ScDPResultMember::ScDPResultMember( +ScDPResultMemberFull::ScDPResultMemberFull( const ScDPResultData* pData, bool bForceSub ) : pResultData( pData ), nMemberStep( 1 ), @@ -1013,7 +1096,7 @@ ScDPResultMember::ScDPResultMember( bAutoHidden( false ) { } -ScDPResultMember::~ScDPResultMember() +ScDPResultMemberFull::~ScDPResultMemberFull() { } @@ -1026,17 +1109,18 @@ OUString ScDPResultMember::GetName() const return ScResId(STR_PIVOT_TOTAL); // root member } -OUString ScDPResultMember::GetDisplayName( bool bLocaleIndependent ) const +OUString ScDPResultMember::GetDisplayName(bool bLocaleIndependent) const { const ScDPMember* pDPMember = GetDPMember(); if (!pDPMember) return OUString(); ScDPItemData aItem(pDPMember->FillItemData()); - if (aParentDimData.mpParentDim) + if (GetParentDim()) { - tools::Long nDim = aParentDimData.mpParentDim->GetDimension(); - return pResultData->GetSource().GetData()->GetFormattedString(nDim, aItem, bLocaleIndependent); + tools::Long nDim = GetParentDim()->GetDimension(); + return GetResultData()->GetSource().GetData()->GetFormattedString(nDim, aItem, + bLocaleIndependent); } return aItem.GetString(); @@ -1050,7 +1134,7 @@ ScDPItemData ScDPResultMember::FillItemData() const return ScDPItemData(ScResId(STR_PIVOT_TOTAL)); // root member } -bool ScDPResultMember::IsNamedItem( SCROW nIndex ) const +bool ScDPResultMember::IsNamedItem(SCROW nIndex) const { //TODO: store ScDPMember pointer instead of ScDPMember ??? const ScDPMember* pMemberDesc = GetDPMember(); @@ -1059,7 +1143,7 @@ bool ScDPResultMember::IsNamedItem( SCROW nIndex ) const return false; } -bool ScDPResultMember::IsValidEntry( const std::vector< SCROW >& aMembers ) const +bool ScDPResultMember::IsValidEntry(const std::vector& aMembers) const { if ( !IsValid() ) return false; @@ -1078,15 +1162,15 @@ bool ScDPResultMember::IsValidEntry( const std::vector< SCROW >& aMembers ) cons return true; } -void ScDPResultMember::InitFrom( const std::vector& ppDim, const std::vector& ppLev, - size_t nPos, ScDPInitState& rInitState , - bool bInitChild ) +void ScDPResultMember::InitFrom(const std::vector& ppDim, + const std::vector& ppLev, size_t nPos, + ScDPInitState& rInitState, bool bInitChild) { // with LateInit, initialize only those members that have data - if ( pResultData->IsLateInit() ) + if (GetResultData()->IsLateInit()) return; - bInitialized = true; + SetInitialized(); if (nPos >= ppDim.size()) return; @@ -1095,35 +1179,41 @@ void ScDPResultMember::InitFrom( const std::vector& ppDim, const if ( GetDPMember() && !GetDPMember()->getShowDetails() ) { // Show DataLayout dimension - nMemberStep = 1; + SetMemberStep(1); while ( nPos < ppDim.size() ) { if ( ppDim[nPos]->getIsDataLayoutDimension() ) { - if ( !pChildDimension ) - pChildDimension.reset( new ScDPResultDimension( pResultData ) ); - pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState , false ); + if (!GetChildDimension()) + ResetChildDimension(); + GetChildDimension()->InitFrom(ppDim, ppLev, nPos, rInitState, false); return; } else { //find next dim nPos ++; - nMemberStep ++; + SetMemberStep(GetMemberStep() + 1); } } - bHasHiddenDetails = true; // only if there is a next dimension + SetHasHiddenDetails(); // only if there is a next dimension return; } if ( bInitChild ) { - pChildDimension.reset( new ScDPResultDimension( pResultData ) ); - pChildDimension->InitFrom(ppDim, ppLev, nPos, rInitState); + ResetChildDimension(); + GetChildDimension()->InitFrom(ppDim, ppLev, nPos, rInitState); } } -void ScDPResultMember::LateInitFrom( - LateInitParams& rParams, const std::vector& pItemData, size_t nPos, ScDPInitState& rInitState) +void ScDPResultMemberFull::ResetChildDimension() +{ + pChildDimension.reset(new ScDPResultDimension(pResultData)); +} + +void ScDPResultMemberFull::LateInitFrom(LateInitParams& rParams, + const std::vector& pItemData, size_t nPos, + ScDPInitState& rInitState) { // without LateInit, everything has already been initialized if ( !pResultData->IsLateInit() ) @@ -1177,8 +1267,8 @@ void ScDPResultMember::LateInitFrom( bool ScDPResultMember::IsSubTotalInTitle(tools::Long nMeasure) const { bool bRet = false; - if ( pChildDimension && /*pParentLevel*/GetParentLevel() && - /*pParentLevel*/GetParentLevel()->IsOutlineLayout() && /*pParentLevel*/GetParentLevel()->IsSubtotalsAtTop() ) + if (GetChildDimension() && GetParentLevel() && GetParentLevel()->IsOutlineLayout() + && GetParentLevel()->IsSubtotalsAtTop()) { tools::Long nUserSubStart; tools::Long nSubTotals = GetSubTotalCount( &nUserSubStart ); @@ -1186,7 +1276,7 @@ bool ScDPResultMember::IsSubTotalInTitle(tools::Long nMeasure) const if ( nSubTotals ) { if ( nMeasure == SC_DPMEASURE_ALL ) - nSubTotals *= pResultData->GetMeasureCount(); // number of subtotals that will be inserted + nSubTotals *= GetResultData()->GetMeasureCount(); // number of subtotals that will be inserted // only a single subtotal row will be shown in the outline title row if ( nSubTotals == 1 ) @@ -1205,20 +1295,20 @@ tools::Long ScDPResultMember::GetSize(tools::Long nMeasure) const if ( pParentLevel && pParentLevel->IsAddEmpty() ) ++nExtraSpace; - if ( pChildDimension ) + if (GetChildDimension()) { // outline layout takes up an extra row for the title only if subtotals aren't shown in that row if ( pParentLevel && pParentLevel->IsOutlineLayout() && !IsSubTotalInTitle( nMeasure ) ) ++nExtraSpace; - tools::Long nSize = pChildDimension->GetSize(nMeasure); + tools::Long nSize = GetChildDimension()->GetSize(nMeasure); tools::Long nUserSubStart; tools::Long nUserSubCount = GetSubTotalCount( &nUserSubStart ); nUserSubCount -= nUserSubStart; // for output size, use visible count if ( nUserSubCount ) { if ( nMeasure == SC_DPMEASURE_ALL ) - nSize += pResultData->GetMeasureCount() * nUserSubCount; + nSize += GetResultData()->GetMeasureCount() * nUserSubCount; else nSize += nUserSubCount; } @@ -1227,7 +1317,7 @@ tools::Long ScDPResultMember::GetSize(tools::Long nMeasure) const else { if ( nMeasure == SC_DPMEASURE_ALL ) - return pResultData->GetMeasureCount() + nExtraSpace; + return GetResultData()->GetMeasureCount() + nExtraSpace; else return 1 + nExtraSpace; } @@ -1235,13 +1325,13 @@ tools::Long ScDPResultMember::GetSize(tools::Long nMeasure) const bool ScDPResultMember::IsVisible() const { - if (!bInitialized) + if (!IsInitialized()) return false; if (!IsValid()) return false; - if (bHasElements) + if (GetHasElements()) return true; // not initialized -> shouldn't be there at all @@ -1255,25 +1345,25 @@ bool ScDPResultMember::IsValid() const { // non-Valid members are left out of calculation - // was member set no invisible at the DataPilotSource? + // was member set to invisible at the DataPilotSource? const ScDPMember* pMemberDesc = GetDPMember(); if ( pMemberDesc && !pMemberDesc->isVisible() ) return false; - if ( bAutoHidden ) + if (IsAutoHidden()) return false; return true; } -tools::Long ScDPResultMember::GetSubTotalCount( tools::Long* pUserSubStart ) const +tools::Long ScDPResultMember::GetSubTotalCount(tools::Long* pUserSubStart) const { if ( pUserSubStart ) *pUserSubStart = 0; // default const ScDPLevel* pParentLevel = GetParentLevel(); - if ( bForceSubTotal ) // set if needed for root members + if (GetForceSubTotal()) // set if needed for root members return 1; // grand total is always "automatic" else if ( pParentLevel ) { @@ -1296,8 +1386,10 @@ tools::Long ScDPResultMember::GetSubTotalCount( tools::Long* pUserSubStart ) con return 0; } -void ScDPResultMember::ProcessData( const std::vector< SCROW >& aChildMembers, const ScDPResultDimension* pDataDim, - const std::vector< SCROW >& aDataMembers, const std::vector& aValues ) +void ScDPResultMemberFull::ProcessData(const std::vector& aChildMembers, + const ScDPResultDimension* pDataDim, + const std::vector& aDataMembers, + const std::vector& aValues) { SetHasElements(); @@ -1362,9 +1454,10 @@ static OUString lcl_parseSubtotalName(std::u16string_view rSubStr, std::u16strin return aNewStr.makeStringAndClear(); } -void ScDPResultMember::FillMemberResults( - uno::Sequence* pSequences, tools::Long& rPos, tools::Long nMeasure, bool bRoot, - const OUString* pMemberName, const OUString* pMemberCaption ) +void ScDPResultMember::FillMemberResults(uno::Sequence* pSequences, + tools::Long& rPos, tools::Long nMeasure, bool bRoot, + const OUString* pMemberName, + const OUString* pMemberCaption) { // IsVisible() test is in ScDPResultDimension::FillMemberResults // (not on data layout dimension) @@ -1387,10 +1480,11 @@ void ScDPResultMember::FillMemberResults( else { ScDPItemData aItemData(FillItemData()); - if (aParentDimData.mpParentDim) + if (GetParentDim()) { - tools::Long nDim = aParentDimData.mpParentDim->GetDimension(); - aName = pResultData->GetSource().GetData()->GetFormattedString(nDim, aItemData, false); + tools::Long nDim = GetParentDim()->GetDimension(); + aName = GetResultData()->GetSource().GetData()->GetFormattedString(nDim, aItemData, + false); } else { @@ -1398,7 +1492,8 @@ void ScDPResultMember::FillMemberResults( const ScDPMember* pMem = GetDPMember(); if (pMem) nDim = pMem->GetDim(); - aName = pResultData->GetSource().GetData()->GetFormattedString(nDim, aItemData, false); + aName = GetResultData()->GetSource().GetData()->GetFormattedString(nDim, aItemData, + false); } ScDPItemData::Type eType = aItemData.GetType(); @@ -1411,7 +1506,7 @@ void ScDPResultMember::FillMemberResults( } const ScDPDimension* pParentDim = GetParentDim(); - if ( bIsNumeric && pParentDim && pResultData->IsNumOrDateGroup( pParentDim->GetDimension() ) ) + if (bIsNumeric && pParentDim && GetResultData()->IsNumOrDateGroup(pParentDim->GetDimension())) { // Numeric group dimensions use numeric entries for proper sorting, // but the group titles must be output as text. @@ -1484,16 +1579,16 @@ void ScDPResultMember::FillMemberResults( // no extra row for the subtotals is needed bool bSubTotalInTitle = IsSubTotalInTitle( nMeasure ); - bool bHasChild = ( pChildDimension != nullptr ); + bool bHasChild = (GetChildDimension() != nullptr); if (bHasChild) { if ( bTitleLine ) // in tabular layout the title is on a separate row ++rPos; // -> fill child dimension one row below if (bRoot) // same sequence for root member - pChildDimension->FillMemberResults( pSequences, rPos, nMeasure ); + GetChildDimension()->FillMemberResults(pSequences, rPos, nMeasure); else - pChildDimension->FillMemberResults( pSequences + nMemberStep/*1*/, rPos, nMeasure ); + GetChildDimension()->FillMemberResults(pSequences + GetMemberStep(), rPos, nMeasure); if ( bTitleLine ) // title row is included in GetSize, so the following --rPos; // positions are calculated with the normal values @@ -1503,11 +1598,11 @@ void ScDPResultMember::FillMemberResults( tools::Long nUserSubStart; tools::Long nUserSubCount = GetSubTotalCount(&nUserSubStart); - if ( !nUserSubCount || !pChildDimension || bSubTotalInTitle ) + if (!nUserSubCount || !GetChildDimension() || bSubTotalInTitle) return; tools::Long nMemberMeasure = nMeasure; - tools::Long nSubSize = pResultData->GetCountForMeasure(nMeasure); + tools::Long nSubSize = GetResultData()->GetCountForMeasure(nMeasure); rPos -= nSubSize * (nUserSubCount - nUserSubStart); // GetSize includes space for SubTotal rPos -= nExtraSpace; // GetSize includes the empty line @@ -1524,7 +1619,9 @@ void ScDPResultMember::FillMemberResults( eForce = lcl_GetForceFunc( pParentLevel, nUserPos ); bool bTotalResult = false; - OUString aSubStr = aCaption + " " + pResultData->GetMeasureString(nMemberMeasure, false, eForce, bTotalResult); + OUString aSubStr + = aCaption + " " + + GetResultData()->GetMeasureString(nMemberMeasure, false, eForce, bTotalResult); if (bTotalResult) { @@ -1532,6 +1629,7 @@ void ScDPResultMember::FillMemberResults( { // single data field layout. const std::optional & pSubtotalName = pParentDim->GetSubtotalName(); + // coverity[var_deref_model : FALSE] - null_ref will not be derefed in this case if (pSubtotalName) aSubStr = lcl_parseSubtotalName(*pSubtotalName, aCaption); pArray[rPos].Flags &= ~sheet::MemberResultFlags::GRANDTOTAL; @@ -1539,7 +1637,7 @@ void ScDPResultMember::FillMemberResults( else { // root member - subtotal (grand total?) for multi-data field layout. - const std::optional & pGrandTotalName = pResultData->GetSource().GetGrandTotalName(); + const std::optional & pGrandTotalName = GetResultData()->GetSource().GetGrandTotalName(); if (pGrandTotalName) aSubStr = *pGrandTotalName; pArray[rPos].Flags |= sheet::MemberResultFlags::GRANDTOTAL; @@ -1562,7 +1660,7 @@ void ScDPResultMember::FillMemberResults( uno::Sequence* pLayoutSeq = pSequences; if (!bRoot) ++pLayoutSeq; - ScDPResultDimension* pLayoutDim = pChildDimension.get(); + ScDPResultDimension* pLayoutDim = GetChildDimension(); while ( pLayoutDim && !pLayoutDim->IsDataLayout() ) { pLayoutDim = pLayoutDim->GetFirstChildDimension(); @@ -1571,7 +1669,7 @@ void ScDPResultMember::FillMemberResults( if ( pLayoutDim ) { sheet::MemberResult* pLayoutArray = pLayoutSeq->getArray(); - pLayoutArray[rPos].Name = pResultData->GetMeasureDimensionName(nMemberMeasure); + pLayoutArray[rPos].Name = GetResultData()->GetMeasureDimensionName(nMemberMeasure); } } @@ -1582,10 +1680,10 @@ void ScDPResultMember::FillMemberResults( rPos += nExtraSpace; // add again (subtracted above) } -void ScDPResultMember::FillDataResults( - const ScDPResultMember* pRefMember, - ScDPResultFilterContext& rFilterCxt, uno::Sequence >& rSequence, - tools::Long nMeasure) const +void ScDPResultMember::FillDataResults(const ScDPResultMember* pRefMember, + ScDPResultFilterContext& rFilterCxt, + uno::Sequence>& rSequence, + tools::Long nMeasure) const { std::unique_ptr pFilterStack; const ScDPMember* pDPMember = GetDPMember(); @@ -1611,14 +1709,14 @@ void ScDPResultMember::FillDataResults( bool bSubTotalInTitle = IsSubTotalInTitle( nMeasure ); - bool bHasChild = ( pChildDimension != nullptr ); + bool bHasChild = (GetChildDimension() != nullptr); if (bHasChild) { if ( bTitleLine ) // in tabular layout the title is on a separate row ++rFilterCxt.mnRow; // -> fill child dimension one row below sal_Int32 nOldRow = rFilterCxt.mnRow; - pChildDimension->FillDataResults(pRefMember, rFilterCxt, rSequence, nMeasure); + GetChildDimension()->FillDataResults(pRefMember, rFilterCxt, rSequence, nMeasure); rFilterCxt.mnRow = nOldRow; // Revert to the original row before the call. rFilterCxt.mnRow += GetSize( nMeasure ); @@ -1641,7 +1739,7 @@ void ScDPResultMember::FillDataResults( } tools::Long nMemberMeasure = nMeasure; - tools::Long nSubSize = pResultData->GetCountForMeasure(nMeasure); + tools::Long nSubSize = GetResultData()->GetCountForMeasure(nMeasure); if (bHasChild) { rFilterCxt.mnRow -= nSubSize * ( nUserSubCount - nUserSubStart ); // GetSize includes space for SubTotal @@ -1655,7 +1753,7 @@ void ScDPResultMember::FillDataResults( rFilterCxt.mnRow = nStartRow; } - if ( pDataRoot ) + if (GetDataRoot()) { ScDPSubTotalState aSubState; // initial state @@ -1671,7 +1769,7 @@ void ScDPResultMember::FillDataResults( { if ( nMeasure == SC_DPMEASURE_ALL ) nMemberMeasure = nSubCount; - else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL ) + else if (GetResultData()->GetColStartMeasure() == SC_DPMEASURE_ALL) nMemberMeasure = SC_DPMEASURE_ALL; OSL_ENSURE( rFilterCxt.mnRow < rSequence.getLength(), "bumm" ); @@ -1679,7 +1777,8 @@ void ScDPResultMember::FillDataResults( if (pRefMember->IsVisible()) { uno::Sequence& rSubSeq = rSequence.getArray()[rFilterCxt.mnRow]; - pDataRoot->FillDataRow(pRefMember, rFilterCxt, rSubSeq, nMemberMeasure, bHasChild, aSubState); + GetDataRoot()->FillDataRow(pRefMember, rFilterCxt, rSubSeq, nMemberMeasure, + bHasChild, aSubState); } rFilterCxt.mnRow += 1; } @@ -1694,12 +1793,13 @@ void ScDPResultMember::FillDataResults( rFilterCxt.mnRow += nMoveSubTotal; } -void ScDPResultMember::UpdateDataResults( const ScDPResultMember* pRefMember, tools::Long nMeasure ) const +void ScDPResultMember::UpdateDataResults(const ScDPResultMember* pRefMember, + tools::Long nMeasure) const { // IsVisible() test is in ScDPResultDimension::FillDataResults // (not on data layout dimension) - bool bHasChild = ( pChildDimension != nullptr ); + bool bHasChild = (GetChildDimension() != nullptr); tools::Long nUserSubCount = GetSubTotalCount(); @@ -1711,9 +1811,9 @@ void ScDPResultMember::UpdateDataResults( const ScDPResultMember* pRefMember, to nUserSubCount = 1; tools::Long nMemberMeasure = nMeasure; - tools::Long nSubSize = pResultData->GetCountForMeasure(nMeasure); + tools::Long nSubSize = GetResultData()->GetCountForMeasure(nMeasure); - if (pDataRoot) + if (GetDataRoot()) { ScDPSubTotalState aSubState; // initial state @@ -1729,36 +1829,36 @@ void ScDPResultMember::UpdateDataResults( const ScDPResultMember* pRefMember, to { if (nMeasure == SC_DPMEASURE_ALL) nMemberMeasure = nSubCount; - else if (pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL) + else if (GetResultData()->GetColStartMeasure() == SC_DPMEASURE_ALL) nMemberMeasure = SC_DPMEASURE_ALL; - pDataRoot->UpdateDataRow(pRefMember, nMemberMeasure, bHasChild, aSubState); + GetDataRoot()->UpdateDataRow(pRefMember, nMemberMeasure, bHasChild, aSubState); } } } if (bHasChild) // child dimension must be processed last, so the column total is known { - pChildDimension->UpdateDataResults( pRefMember, nMeasure ); + GetChildDimension()->UpdateDataResults(pRefMember, nMeasure); } } -void ScDPResultMember::SortMembers( ScDPResultMember* pRefMember ) +void ScDPResultMember::SortMembers(ScDPResultMember* pRefMember) { - bool bHasChild = ( pChildDimension != nullptr ); + bool bHasChild = (GetChildDimension() != nullptr); if (bHasChild) - pChildDimension->SortMembers( pRefMember ); // sorting is done at the dimension + GetChildDimension()->SortMembers(pRefMember); // sorting is done at the dimension - if ( IsRoot() && pDataRoot ) + if (IsRoot() && GetDataRoot()) { // use the row root member to sort columns // sub total count is always 1 - pDataRoot->SortMembers( pRefMember ); + GetDataRoot()->SortMembers(pRefMember); } } -void ScDPResultMember::DoAutoShow( ScDPResultMember* pRefMember ) +void ScDPResultMemberFull::DoAutoShow(ScDPResultMember* pRefMember) { bool bHasChild = ( pChildDimension != nullptr ); if (bHasChild) @@ -1773,7 +1873,7 @@ void ScDPResultMember::DoAutoShow( ScDPResultMember* pRefMember ) } } -void ScDPResultMember::ResetResults() +void ScDPResultMemberFull::ResetResults() { if (pDataRoot) pDataRoot->ResetResults(); @@ -1782,15 +1882,16 @@ void ScDPResultMember::ResetResults() pChildDimension->ResetResults(); } -void ScDPResultMember::UpdateRunningTotals( ScDPResultMember* pRefMember, tools::Long nMeasure, - ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const +void ScDPResultMember::UpdateRunningTotals(ScDPResultMember* pRefMember, tools::Long nMeasure, + ScDPRunningTotalState& rRunning, + ScDPRowTotals& rTotals) const { // IsVisible() test is in ScDPResultDimension::FillDataResults // (not on data layout dimension) rTotals.SetInColRoot( IsRoot() ); - bool bHasChild = ( pChildDimension != nullptr ); + bool bHasChild = (GetChildDimension() != nullptr); tools::Long nUserSubCount = GetSubTotalCount(); //if ( nUserSubCount || !bHasChild ) @@ -1801,9 +1902,9 @@ void ScDPResultMember::UpdateRunningTotals( ScDPResultMember* pRefMember, tools: nUserSubCount = 1; tools::Long nMemberMeasure = nMeasure; - tools::Long nSubSize = pResultData->GetCountForMeasure(nMeasure); + tools::Long nSubSize = GetResultData()->GetCountForMeasure(nMeasure); - if ( pDataRoot ) + if (GetDataRoot()) { ScDPSubTotalState aSubState; // initial state @@ -1819,12 +1920,12 @@ void ScDPResultMember::UpdateRunningTotals( ScDPResultMember* pRefMember, tools: { if ( nMeasure == SC_DPMEASURE_ALL ) nMemberMeasure = nSubCount; - else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL ) + else if (GetResultData()->GetColStartMeasure() == SC_DPMEASURE_ALL) nMemberMeasure = SC_DPMEASURE_ALL; if (pRefMember->IsVisible()) - pDataRoot->UpdateRunningTotals( - pRefMember, nMemberMeasure, bHasChild, aSubState, rRunning, rTotals, *this); + GetDataRoot()->UpdateRunningTotals(pRefMember, nMemberMeasure, bHasChild, + aSubState, rRunning, rTotals, *this); } } } @@ -1832,14 +1933,36 @@ void ScDPResultMember::UpdateRunningTotals( ScDPResultMember* pRefMember, tools: if (bHasChild) // child dimension must be processed last, so the column total is known { - pChildDimension->UpdateRunningTotals( pRefMember, nMeasure, rRunning, rTotals ); + GetChildDimension()->UpdateRunningTotals(pRefMember, nMeasure, rRunning, rTotals); } } #if DUMP_PIVOT_TABLE -void ScDPResultMember::DumpState( const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos ) const +void ScDPResultMemberSlim::DumpState(const ScDPResultMember*, ScDocument* pDoc, ScAddress& rPos) const { - dumpRow(u"ScDPResultMember"_ustr, GetName(), nullptr, pDoc, rPos); + dumpRow(u"ScDPResultMemberSlim"_ustr, GetName(), nullptr, pDoc, rPos); + SCROW nStartRow = rPos.Row(); + + indent(pDoc, nStartRow, rPos); +} + +void ScDPResultMemberSlim::Dump(int nIndent) const +{ + std::string aIndent(nIndent*2, ' '); + std::cout << aIndent << "-- result member(Slim) '" << GetName() << "'" << std::endl; + std::cout << aIndent << " Order: " << mnOrder << " Flags: " + << (bmHasElements?"E":"") + << (bmHasHiddenDetails?"H":"") + << (bmInitialized?"I":"") + << (bmPromoted?"P":"") + << std::endl; +} +#endif + +#if DUMP_PIVOT_TABLE +void ScDPResultMemberFull::DumpState(const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos) const +{ + dumpRow(u"ScDPResultMemberFull"_ustr, GetName(), nullptr, pDoc, rPos); SCROW nStartRow = rPos.Row(); if (pDataRoot) @@ -1851,10 +1974,10 @@ void ScDPResultMember::DumpState( const ScDPResultMember* pRefMember, ScDocument indent(pDoc, nStartRow, rPos); } -void ScDPResultMember::Dump(int nIndent) const +void ScDPResultMemberFull::Dump(int nIndent) const { std::string aIndent(nIndent*2, ' '); - std::cout << aIndent << "-- result member '" << GetName() << "'" << std::endl; + std::cout << aIndent << "-- result member(Full) '" << GetName() << "'" << std::endl; std::cout << aIndent << " column totals" << std::endl; for (const ScDPAggData* p = pColTotal.get(); p; p = p->GetExistingChild()) @@ -1871,7 +1994,7 @@ void ScDPResultMember::Dump(int nIndent) const } #endif -ScDPAggData* ScDPResultMember::GetColTotal( tools::Long nMeasure ) +ScDPAggData* ScDPResultMemberFull::GetColTotal(tools::Long nMeasure) { if (!pColTotal) { @@ -1880,10 +2003,10 @@ ScDPAggData* ScDPResultMember::GetColTotal( tools::Long nMeasure ) return lcl_GetChildTotal(pColTotal.get(), nMeasure); } -void ScDPResultMember::FillVisibilityData(ScDPResultVisibilityData& rData) const +void ScDPResultMember::FillVisibilityData(ScDPResultVisibilityData& rData) { - if (pChildDimension) - pChildDimension->FillVisibilityData(rData); + if (GetChildDimension()) + GetChildDimension()->FillVisibilityData(rData); } ScDPDataMember::ScDPDataMember( const ScDPResultData* pData, const ScDPResultMember* pRes ) : @@ -1986,7 +2109,7 @@ void ScDPDataMember::ProcessData( const std::vector< SCROW >& aChildMembers, con if ( pResultData->IsLateInit() && !pChildDimension && pResultMember && pResultMember->GetChildDimension() ) { // if this DataMember doesn't have a child dimension because the ResultMember's - // child dimension wasn't there yet during this DataMembers's creation, + // child dimension wasn't there yet during this DataMember's creation, // create the child dimension now InitFrom( pResultMember->GetChildDimension() ); } @@ -2304,7 +2427,7 @@ void ScDPDataMember::UpdateDataRow( } } -void ScDPDataMember::SortMembers( ScDPResultMember* pRefMember ) +void ScDPDataMember::SortMembers(ScDPResultMember* pRefMember) { OSL_ENSURE( pRefMember == pResultMember || !pResultMember, "bla" ); @@ -2317,7 +2440,7 @@ void ScDPDataMember::SortMembers( ScDPResultMember* pRefMember ) } } -void ScDPDataMember::DoAutoShow( ScDPResultMember* pRefMember ) +void ScDPDataMember::DoAutoShow(ScDPResultMember* pRefMember) { OSL_ENSURE( pRefMember == pResultMember || !pResultMember, "bla" ); @@ -2735,7 +2858,7 @@ std::unique_ptr ScDPDataMember::ReplaceTokenMeasuresWithValues(con formula::FormulaTokenArrayPlainIterator aIterResult(*pNewArray); for (formula::FormulaToken* t = aIterResult.GetNextDPFieldNameRPN(); t; t = aIterResult.GetNextDPFieldNameRPN()) { - OUString aName = t->GetString().getString(); + OUString aName = static_cast(t)->GetString().getString(); tools::Long nMemberMeasure = FindMeasureIndex(pResultData->GetMeasureNames(), aName); if (nMemberMeasure >= 0) { @@ -2790,8 +2913,12 @@ std::unique_ptr ScDPDataMember::ReplaceTokenMeasuresWithValues(con // replace token with value if calculation was successful if (pAggData->IsCalculated()) { - formula::FormulaToken* pValToken = new formula::FormulaDoubleToken(pAggData->GetResult()); - pNewArray->ReplaceRPNToken(aIterResult.GetIndex() - 1, pValToken); + formula::FormulaToken* pNewToken; + if (pAggData->HasError()) + pNewToken = new formula::FormulaErrorToken(FormulaError::NoValue); + else + pNewToken = new formula::FormulaDoubleToken(pAggData->GetResult()); + pNewArray->ReplaceRPNToken(aIterResult.GetIndex() - 1, pNewToken); } } // remove from recursion stack after processing @@ -2909,60 +3036,81 @@ bool ScDPGroupCompare::TestIncluded( const ScDPMember& rMember ) return bInclude; } -ScDPResultDimension::ScDPResultDimension( const ScDPResultData* pData ) : - pResultData( pData ), - nSortMeasure( 0 ), - bIsDataLayout( false ), - bSortByData( false ), - bSortAscending( false ), - bAutoShow( false ), - bAutoTopItems( false ), - bInitialized( false ), - nAutoMeasure( 0 ), - nAutoCount( 0 ) +ScDPResultDimension::ScDPResultDimension(const ScDPResultData* pData) + : pResultData(pData) + , mpDimension(nullptr) + , mpLevel(nullptr) + , nSortMeasure(0) + , bIsDataLayout(false) + , bSortByData(false) + , bSortAscending(false) + , bAutoShow(false) + , bAutoTopItems(false) + , bInitialized(false) + , nAutoMeasure(0) + , nAutoCount(0) { } ScDPResultDimension::~ScDPResultDimension() { + if (mpaMemberSlimArray != nullptr) + { + // This is the raw array in the span under the unique_ptr + delete[] mpaMemberSlimArray->data(); + } } ScDPResultMember *ScDPResultDimension::FindMember( SCROW iData ) const { + SCROW nIndex; + + // If we have Slim's search them first + if (mpaMemberSlimArray != nullptr) + { + if (bIsDataLayout) + { + if (!mpaMemberSlimArray->empty()) + { + ScDPResultMemberSlim* pSlimMember = &(*mpaMemberSlimArray)[0]; + return pSlimMember; + } + } + else + { + if (lcl_SearchMember(*mpaMemberSlimArray, iData, nIndex)) + { + ScDPResultMemberSlim* pSlimMember = &(*mpaMemberSlimArray)[nIndex]; + if (pSlimMember->IsNamedItem(iData)) + return pSlimMember; + } + } + auto pResultIter = std::ranges::find_if( + *mpaMemberSlimArray, [iData](const auto& m) { return m.IsNamedItem(iData); }); + if (pResultIter != mpaMemberSlimArray->end()) + { + return &*pResultIter; + } + } + if( bIsDataLayout ) { SAL_WARN_IF(maMemberArray.empty(), "sc.core", "MemberArray is empty"); return !maMemberArray.empty() ? maMemberArray[0].get() : nullptr; } - MemberHash::const_iterator aRes = maMemberHash.find( iData ); - if( aRes != maMemberHash.end()) { - if ( aRes->second->IsNamedItem( iData ) ) - return aRes->second; - OSL_FAIL("problem! hash result is not the same as IsNamedItem"); + if (lcl_SearchMember(maMemberArray, iData, nIndex)) + { + ScDPResultMember* pResultMember = maMemberArray[nIndex].get(); + if (pResultMember->IsNamedItem(iData)) + return pResultMember; } - // Normal late allocation normally always finds it in the hash - if (!pResultData->IsLateInit()) + auto pResultIter = std::ranges::find_if( + maMemberArray, [iData](const auto& m) { return m->IsNamedItem(iData); }); + if (pResultIter != maMemberArray.end()) { - // For full (non-late) init, we don't use the hash since it's huge - // but we can normally use a binary search for efficiency - SCROW nIndex; - if (lcl_SearchMember(maMemberArray, iData, nIndex)) - { - // I *think* this is always true, but check for sanity - ScDPResultMember* pResultMember = maMemberArray[nIndex].get(); - if (pResultMember->IsNamedItem(iData)) - return pResultMember; - } - } - unsigned int i; - unsigned int nCount = maMemberArray.size(); - for( i = 0; i < nCount ; i++ ) - { - ScDPResultMember* pResultMember = maMemberArray[i].get(); - if ( pResultMember->IsNamedItem( iData ) ) - return pResultMember; + return pResultIter->get(); } return nullptr; } @@ -2986,6 +3134,10 @@ void ScDPResultDimension::InitFrom( return; } + // Stash for promotion + mpDimension = pThisDim; + mpLevel = pThisLevel; + bIsDataLayout = pThisDim->getIsDataLayoutDimension(); // member aDimensionName = pThisDim->getName(); // member @@ -3017,21 +3169,47 @@ void ScDPResultDimension::InitFrom( // Now, go through all members and initialize them. ScDPMembers* pMembers = pThisLevel->GetMembersObject(); tools::Long nMembCount = pMembers->getCount(); + + // Loop once to find out how much space we need + size_t nCount = 0; for ( tools::Long i=0; igetByIndex(nSorted); + if (aCompare.IsIncluded(*pMember)) + { + nCount++; + } + } + + auto aSlimRawArray = new ScDPResultMemberSlim[nCount]; + mpaMemberSlimArray.reset( + new std::span(&aSlimRawArray[0], &aSlimRawArray[nCount])); + + // Loop again to actually fill in the data + size_t nIndex = 0; + for (tools::Long i = 0; i < nMembCount; i++) + { + tools::Long nSorted = rGlobalOrder.empty() ? i : rGlobalOrder[i]; + ScDPMember* pMember = pMembers->getByIndex(nSorted); if ( aCompare.IsIncluded( *pMember ) ) { ScDPParentDimData aData( i, pThisDim, pThisLevel, pMember); - ScDPResultMember* pNew = AddMember( aData ); + ScDPResultMemberSlim* pNew = &(*mpaMemberSlimArray)[nIndex++]; + + // Fill in the array element by hand + pNew->mpOurDimension = this; + pNew->mpMemberDesc = pMember; + pNew->mnOrder = i; rInitState.AddMember(nDimSource, pNew->GetDataId()); pNew->InitFrom( ppDim, ppLev, nPos+1, rInitState, bInitChild ); rInitState.RemoveMember(); } } + assert(nIndex == nCount); bInitialized = true; } @@ -3052,6 +3230,10 @@ void ScDPResultDimension::LateInitFrom( if (!pThisDim || !pThisLevel) return; + // Stash for promotion + mpDimension = pThisDim; + mpLevel = pThisLevel; + tools::Long nDimSource = pThisDim->GetDimension(); //TODO: check GetSourceDim? bool bShowEmpty = pThisLevel->getShowEmpty(); @@ -3154,7 +3336,7 @@ void ScDPResultDimension::LateInitFrom( tools::Long ScDPResultDimension::GetSize(tools::Long nMeasure) const { - tools::Long nMemberCount = maMemberArray.size(); + tools::Long nMemberCount = GetMemberCount(); if (!nMemberCount) return 0; @@ -3164,13 +3346,13 @@ tools::Long ScDPResultDimension::GetSize(tools::Long nMeasure) const OSL_ENSURE(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1, "DataLayout dimension twice?"); // repeat first member... - nTotal = nMemberCount * maMemberArray[0]->GetSize(0); // all measures have equal size + nTotal = nMemberCount * GetMember(0)->GetSize(0); // all measures have equal size } else { // add all members for (tools::Long nMem=0; nMemGetSize(nMeasure); + nTotal += GetMember(nMem)->GetSize(nMeasure); } return nTotal; } @@ -3217,20 +3399,20 @@ void ScDPResultDimension::FillMemberResults( uno::Sequence* tools::Long nStart, tools::Long nMeasure ) { tools::Long nPos = nStart; - tools::Long nCount = maMemberArray.size(); + tools::Long nCount = GetMemberCount(); for (tools::Long i=0; iGetMeasureDimensionName( nSorted ); OUString aMbrCapt = pResultData->GetMeasureString( nSorted, false, SUBTOTAL_FUNC_NONE, bTotalResult ); - maMemberArray[0]->FillMemberResults( pSequences, nPos, nSorted, false, &aMbrName, &aMbrCapt ); + GetMember(0)->FillMemberResults(pSequences, nPos, nSorted, false, &aMbrName, &aMbrCapt); } else if ( pMember->IsVisible() ) { @@ -3248,7 +3430,7 @@ void ScDPResultDimension::FillDataResults( aFilterStack.pushDimName(GetName(), bIsDataLayout); tools::Long nMemberMeasure = nMeasure; - tools::Long nCount = maMemberArray.size(); + tools::Long nCount = GetMemberCount(); for (tools::Long i=0; iGetMeasureCount() == 1, "DataLayout dimension twice?"); - pMember = maMemberArray[0].get(); + pMember = GetMember(0); nMemberMeasure = nSorted; } else - pMember = maMemberArray[nSorted].get(); + pMember = GetMember(nSorted); if ( pMember->IsVisible() ) pMember->FillDataResults(pRefMember, rFilterCxt, rSequence, nMemberMeasure); } } -void ScDPResultDimension::UpdateDataResults( const ScDPResultMember* pRefMember, tools::Long nMeasure ) const +void ScDPResultDimension::UpdateDataResults(const ScDPResultMember* pRefMember, + tools::Long nMeasure) const { tools::Long nMemberMeasure = nMeasure; - tools::Long nCount = maMemberArray.size(); + tools::Long nCount = GetMemberCount(); for (tools::Long i=0; iGetMeasureCount() == 1, "DataLayout dimension twice?"); - pMember = maMemberArray[0].get(); + pMember = GetMember(0); nMemberMeasure = i; } else - pMember = maMemberArray[i].get(); + pMember = GetMember(i); if ( pMember->IsVisible() ) pMember->UpdateDataResults( pRefMember, nMemberMeasure ); } } -void ScDPResultDimension::SortMembers( ScDPResultMember* pRefMember ) +void ScDPResultDimension::SortMembers(ScDPResultMember* pRefMember) { - tools::Long nCount = maMemberArray.size(); + tools::Long nCount = GetMemberCount(); if ( bSortByData ) { @@ -3314,15 +3497,15 @@ void ScDPResultDimension::SortMembers( ScDPResultMember* pRefMember ) tools::Long nLoopCount = bIsDataLayout ? std::min(1, nCount) : nCount; for (tools::Long i=0; iIsVisible() ) pMember->SortMembers( pRefMember ); } } -void ScDPResultDimension::DoAutoShow( ScDPResultMember* pRefMember ) +void ScDPResultDimension::DoAutoShow(ScDPResultMember* pRefMember) { - tools::Long nCount = maMemberArray.size(); + tools::Long nCount = GetMemberCount(); // handle children first, before changing the visible state @@ -3330,7 +3513,7 @@ void ScDPResultDimension::DoAutoShow( ScDPResultMember* pRefMember ) tools::Long nLoopCount = bIsDataLayout ? 1 : nCount; for (tools::Long i=0; iIsVisible() ) pMember->DoAutoShow( pRefMember ); } @@ -3352,7 +3535,7 @@ void ScDPResultDimension::DoAutoShow( ScDPResultMember* pRefMember ) // look for equal values to the last included one tools::Long nIncluded = nAutoCount; - const ScDPResultMember* pMember1 = maMemberArray[aAutoOrder[nIncluded - 1]].get(); + const ScDPResultMember* pMember1 = GetMember(aAutoOrder[nIncluded - 1]); const ScDPDataMember* pDataMember1 = pMember1->IsVisible() ? pMember1->GetDataRoot() : nullptr; bool bContinue = true; while ( bContinue ) @@ -3360,7 +3543,7 @@ void ScDPResultDimension::DoAutoShow( ScDPResultMember* pRefMember ) bContinue = false; if ( nIncluded < nCount ) { - const ScDPResultMember* pMember2 = maMemberArray[aAutoOrder[nIncluded]].get(); + const ScDPResultMember* pMember2 = GetMember(aAutoOrder[nIncluded]); const ScDPDataMember* pDataMember2 = pMember2->IsVisible() ? pMember2->GetDataRoot() : nullptr; if ( lcl_IsEqual( pDataMember1, pDataMember2, nAutoMeasure ) ) @@ -3375,18 +3558,18 @@ void ScDPResultDimension::DoAutoShow( ScDPResultMember* pRefMember ) for (nPos = nIncluded; nPos < nCount; nPos++) { - ScDPResultMember* pMember = maMemberArray[aAutoOrder[nPos]].get(); + ScDPResultMember* pMember = GetMember(aAutoOrder[nPos]); pMember->SetAutoHidden(); } } void ScDPResultDimension::ResetResults() { - tools::Long nCount = maMemberArray.size(); + tools::Long nCount = GetMemberCount(); for (tools::Long i=0; iResetResults(); } } @@ -3396,12 +3579,13 @@ tools::Long ScDPResultDimension::GetSortedIndex( tools::Long nUnsorted ) const return aMemberOrder.empty() ? nUnsorted : aMemberOrder[nUnsorted]; } -void ScDPResultDimension::UpdateRunningTotals( ScDPResultMember* pRefMember, tools::Long nMeasure, - ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const +void ScDPResultDimension::UpdateRunningTotals(ScDPResultMember* pRefMember, tools::Long nMeasure, + ScDPRunningTotalState& rRunning, + ScDPRowTotals& rTotals) const { const ScDPResultMember* pMember; tools::Long nMemberMeasure = nMeasure; - tools::Long nCount = maMemberArray.size(); + tools::Long nCount = GetMemberCount(); for (tools::Long i=0; iGetMeasureCount() == 1, "DataLayout dimension twice?"); - pMember = maMemberArray[0].get(); + pMember = GetMember(0); nMemberMeasure = nSorted; } else - pMember = maMemberArray[nSorted].get(); + pMember = GetMember(nSorted); if ( pMember->IsVisible() ) { @@ -3439,7 +3623,7 @@ ScDPDataMember* ScDPResultDimension::GetRowReferenceMember( ScDPDataMember* pColMember = nullptr; bool bFirstExisting = ( pRelativePos == nullptr && pName == nullptr ); - tools::Long nMemberCount = maMemberArray.size(); + tools::Long nMemberCount = GetMemberCount(); tools::Long nMemberIndex = 0; // unsorted tools::Long nDirection = 1; // forward if no relative position is used if ( pRelativePos ) @@ -3453,14 +3637,14 @@ ScDPDataMember* ScDPResultDimension::GetRowReferenceMember( { // search for named member - const ScDPResultMember* pRowMember = maMemberArray[GetSortedIndex(nMemberIndex)].get(); + const ScDPResultMember* pRowMember = GetMember(GetSortedIndex(nMemberIndex)); //TODO: use ScDPItemData, as in ScDPDimension::IsValidPage? while ( pRowMember && pRowMember->GetName() != *pName ) { ++nMemberIndex; if ( nMemberIndex < nMemberCount ) - pRowMember = maMemberArray[GetSortedIndex(nMemberIndex)].get(); + pRowMember = GetMember(GetSortedIndex(nMemberIndex)); else pRowMember = nullptr; } @@ -3469,7 +3653,7 @@ ScDPDataMember* ScDPResultDimension::GetRowReferenceMember( bool bContinue = true; while ( bContinue && nMemberIndex >= 0 && nMemberIndex < nMemberCount ) { - const ScDPResultMember* pRowMember = maMemberArray[GetSortedIndex(nMemberIndex)].get(); + const ScDPResultMember* pRowMember = GetMember(GetSortedIndex(nMemberIndex)); // get child members by given indexes @@ -3671,34 +3855,47 @@ void ScDPResultDimension::Dump(int nIndent) const tools::Long ScDPResultDimension::GetMemberCount() const { + if (mpaMemberSlimArray != nullptr) + { + return mpaMemberSlimArray->size(); + } return maMemberArray.size(); } const ScDPResultMember* ScDPResultDimension::GetMember(tools::Long n) const { + if (mpaMemberSlimArray != nullptr) + { + return &(*mpaMemberSlimArray)[n]; + } return maMemberArray[n].get(); } ScDPResultMember* ScDPResultDimension::GetMember(tools::Long n) { + if (mpaMemberSlimArray != nullptr) + { + return &(*mpaMemberSlimArray)[n]; + } return maMemberArray[n].get(); } -ScDPResultDimension* ScDPResultDimension::GetFirstChildDimension() const +ScDPResultDimension* ScDPResultDimension::GetFirstChildDimension() { - if ( !maMemberArray.empty() ) - return maMemberArray[0]->GetChildDimension(); + if (GetMemberCount()) + return GetMember(0)->GetChildDimension(); else return nullptr; } -void ScDPResultDimension::FillVisibilityData(ScDPResultVisibilityData& rData) const +void ScDPResultDimension::FillVisibilityData(ScDPResultVisibilityData& rData) { if (IsDataLayout()) return; - for (const auto& rxMember : maMemberArray) + tools::Long nCount = GetMemberCount(); + for (tools::Long i = 0; i < nCount; i++) { - ScDPResultMember* pMember = rxMember.get(); + ScDPResultMember* pMember = GetMember(i); if (pMember->IsValid()) { ScDPItemData aItem(pMember->FillItemData()); @@ -3708,6 +3905,35 @@ void ScDPResultDimension::FillVisibilityData(ScDPResultVisibilityData& rData) co } } +// Called by an ScDPResultMemberSlim which has already been promoted +// but something calls one of its member functions +ScDPResultMember* ScDPResultDimension::GetPromote(SCROW nOrder) const +{ + // Find the existing slim entry + SCROW nIndex; + if (!lcl_SearchMember(maMemberArray, nOrder, nIndex)) + throw container::NoSuchElementException(); + + return maMemberArray[nIndex].get(); +} + +// Called by an ScDPResultMemberSlim when a member function needs +// to do something which Slim can't represent +ScDPResultMember* ScDPResultDimension::Promote(ScDPResultMemberSlim* pSlim, SCROW nOrder) +{ + ScDPParentDimData aParentData(nOrder, mpDimension, mpLevel, pSlim->mpMemberDesc); + ScDPResultMember* pFull = InsertMember(&aParentData); + + if (pSlim->bmHasElements) + pFull->SetHasElements(); + if (pSlim->bmHasHiddenDetails) + pFull->SetHasHiddenDetails(); + if (pSlim->bmInitialized) + pFull->SetInitialized(); + + return pFull; +} + ScDPDataDimension::ScDPDataDimension( const ScDPResultData* pData ) : pResultData( pData ), pResultDimension( nullptr ), @@ -4138,7 +4364,7 @@ size_t ScDPResultVisibilityData::MemberHash::operator() (const ScDPItemData& r) else return r.GetString().hashCode(); } -SCROW ScDPResultMember::GetDataId( ) const +SCROW ScDPResultMember::GetDataId() const { const ScDPMember* pMemberDesc = GetDPMember(); if (pMemberDesc) @@ -4148,12 +4374,9 @@ SCROW ScDPResultMember::GetDataId( ) const ScDPResultMember* ScDPResultDimension::AddMember(const ScDPParentDimData &aData ) { - ScDPResultMember* pMember = new ScDPResultMember( pResultData, aData ); - SCROW nDataIndex = pMember->GetDataId(); + ScDPResultMember* pMember = new ScDPResultMemberFull(pResultData, aData); maMemberArray.emplace_back( pMember ); - if (pResultData->IsLateInit()) - maMemberHash.emplace(nDataIndex, pMember); return pMember; } @@ -4162,12 +4385,9 @@ ScDPResultMember* ScDPResultDimension::InsertMember(const ScDPParentDimData *pMe SCROW nInsert = 0; if ( !lcl_SearchMember( maMemberArray, pMemberData->mnOrder , nInsert ) ) { - ScDPResultMember* pNew = new ScDPResultMember( pResultData, *pMemberData ); + ScDPResultMember* pNew = new ScDPResultMemberFull(pResultData, *pMemberData); maMemberArray.emplace( maMemberArray.begin()+nInsert, pNew ); - SCROW nDataIndex = pMemberData->mpMemberDesc->GetItemDataId(); - if (pResultData->IsLateInit()) - maMemberHash.emplace(nDataIndex, pNew); return pNew; } return maMemberArray[ nInsert ].get(); @@ -4260,25 +4480,25 @@ bool LateInitParams::IsEnd( size_t nPos ) const void ScDPResultDimension::CheckShowEmpty( bool bShow ) { - tools::Long nCount = maMemberArray.size(); + tools::Long nCount = GetMemberCount(); for (tools::Long i=0; iCheckShowEmpty(bShow); } } -void ScDPResultMember::CheckShowEmpty( bool bShow ) +void ScDPResultMember::CheckShowEmpty(bool bShow) { - if (bHasElements) + if (GetHasElements()) { ScDPResultDimension* pChildDim = GetChildDimension(); if (pChildDim) pChildDim->CheckShowEmpty(); } - else if (IsValid() && bInitialized) + else if (IsValid() && IsInitialized()) { bShow = bShow || (GetParentLevel() && GetParentLevel()->getShowEmpty()); if (bShow) diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx index d6f82409bf2f..268f038747f5 100644 --- a/sc/source/core/data/dptabsrc.cxx +++ b/sc/source/core/data/dptabsrc.cxx @@ -779,7 +779,7 @@ void ScDPSource::AddDataDimsToResultData(sheet::DataPilotFieldOrientation nDataO for (formula::FormulaToken* t = aIter.GetNextDPFieldNameRPN(); t; t = aIter.GetNextDPFieldNameRPN()) { - OUString aName = t->GetString().getString(); + OUString aName = static_cast(t)->GetString().getString(); SCCOL nDepIndex = rCache.GetDimensionIndex(aName); if (nDepIndex < 0) @@ -955,8 +955,8 @@ void ScDPSource::CreateRes_Impl() tools::Long nRowDimCount2 = maRowDims.size() - (nDataLayoutOrient == sheet::DataPilotFieldOrientation_ROW ? 1 : 0); bool bShowColGrand = mbColumnGrand && nColDimCount2 > 0; bool bShowRowGrand = mbRowGrand && nRowDimCount2 > 0; - mpColumnResultRoot.reset( new ScDPResultMember(mpResultData.get(), bShowColGrand) ); - mpRowResultRoot.reset( new ScDPResultMember(mpResultData.get(), bShowRowGrand) ); + mpColumnResultRoot.reset(new ScDPResultMemberFull(mpResultData.get(), bShowColGrand)); + mpRowResultRoot.reset(new ScDPResultMemberFull(mpResultData.get(), bShowRowGrand)); FillCalcInfo(false, aInfo, bHasAutoShow); tools::Long nColLevelCount = aInfo.aColLevels.size(); @@ -2670,6 +2670,10 @@ uno::Reference SAL_CALL ScDPMember::getPropertySetInfo( { SC_UNO_DP_POSITION, 0, cppu::UnoType::get(), 0, 0 }, { SC_UNO_DP_SHOWDETAILS, 0, cppu::UnoType::get(), 0, 0 }, { SC_UNO_DP_LAYOUTNAME, 0, cppu::UnoType::get(), 0, 0 }, + { SC_UNO_DP_MEMBER_VALUE, 0, cppu::UnoType::get(), + beans::PropertyAttribute::READONLY, 0 }, + { SC_UNO_DP_MEMBER_HAS_VALUE, 0, cppu::UnoType::get(), + beans::PropertyAttribute::READONLY, 0 }, }; static uno::Reference aRef = new SfxItemPropertySetInfo( aDPMemberMap_Impl ); @@ -2707,6 +2711,16 @@ uno::Any SAL_CALL ScDPMember::getPropertyValue( const OUString& aPropertyName ) aRet <<= nPosition; else if (aPropertyName == SC_UNO_DP_LAYOUTNAME) aRet <<= mpLayoutName ? *mpLayoutName : OUString(); + else if (aPropertyName == SC_UNO_DP_MEMBER_VALUE) + { + const ScDPItemData* pData = GetItemData(); + aRet <<= pData ? pData->GetValue() : 0.0; + } + else if (aPropertyName == SC_UNO_DP_MEMBER_HAS_VALUE) + { + const ScDPItemData* pData = GetItemData(); + aRet <<= pData && pData->IsValue(); + } else { OSL_FAIL("unknown property"); diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 454d39ee65f0..ec1bfd203cc8 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -48,7 +48,7 @@ #include #include -// Similar as in output.cxx +// Similar to output.cxx static void lcl_GetMergeRange( SCCOL nX, SCROW nY, SCSIZE nArrY, const ScDocument* pDoc, RowInfo* pRowInfo, @@ -108,7 +108,7 @@ static void lcl_GetMergeRange( SCCOL nX, SCROW nY, SCSIZE nArrY, !pDoc->RowHidden(rStartY, nTab, nullptr, &nLastRow) && pRowInfo[nArrY].nRowNo == rStartY) { - pMerge = &pRowInfo[nArrY].cellInfo(rStartX).pPatternAttr-> + pMerge = &pRowInfo[nArrY].cellInfo(rStartX).getPatternAttr()-> GetItem(ATTR_MERGE); } else @@ -381,7 +381,7 @@ void ScDocument::FillInfo( SCROW nYExtra = nRow2+1; initRowInfo(this, pRowInfo, rTabInfo.mnArrCapacity, fRowScale, nRow1, nTab, nYExtra, nArrRow, nRow2, aRowLookup); - nArrCount = nArrRow; // incl. Dummys + nArrCount = nArrRow; // incl. Dummies // Rotated text... @@ -525,33 +525,33 @@ void ScDocument::FillInfo( do { - const ScPatternAttr* pPattern = nullptr; + CellAttributeHolder aPatternHolder; if ( pThisAttrArr->Count() ) { nThisRow = pThisAttrArr->mvData[nIndex].nEndRow; // End of range - pPattern = pThisAttrArr->mvData[nIndex].getScPatternAttr(); + aPatternHolder.setScPatternAttr(pThisAttrArr->mvData[nIndex].getScPatternAttr()); } else { nThisRow = MaxRow(); - pPattern = &getCellAttributeHelper().getDefaultCellAttribute(); + aPatternHolder.setScPatternAttr(&getCellAttributeHelper().getDefaultCellAttribute()); } - const SvxBrushItem* pBackground = &pPattern->GetItem(ATTR_BACKGROUND); - const SvxBrushItem* pExplicitBackground = pPattern->GetItemSet().GetItemIfSet(ATTR_BACKGROUND); - const SvxBoxItem* pLinesAttr = &pPattern->GetItem(ATTR_BORDER); - const SvxBoxItem* pExplicitLinesAttr = pPattern->GetItemSet().GetItemIfSet(ATTR_BORDER); + const SvxBrushItem* pBackground = &aPatternHolder.getScPatternAttr()->GetItem(ATTR_BACKGROUND); + const SvxBrushItem* pExplicitBackground = aPatternHolder.getScPatternAttr()->GetItemSet().GetItemIfSet(ATTR_BACKGROUND); + const SvxBoxItem* pLinesAttr = &aPatternHolder.getScPatternAttr()->GetItem(ATTR_BORDER); + const SvxBoxItem* pExplicitLinesAttr = aPatternHolder.getScPatternAttr()->GetItemSet().GetItemIfSet(ATTR_BORDER); - const SvxLineItem* pTLBRLine = &pPattern->GetItem( ATTR_BORDER_TLBR ); - const SvxLineItem* pBLTRLine = &pPattern->GetItem( ATTR_BORDER_BLTR ); + const SvxLineItem* pTLBRLine = &aPatternHolder.getScPatternAttr()->GetItem( ATTR_BORDER_TLBR ); + const SvxLineItem* pBLTRLine = &aPatternHolder.getScPatternAttr()->GetItem( ATTR_BORDER_BLTR ); - const SvxShadowItem* pShadowAttr = &pPattern->GetItem(ATTR_SHADOW); + const SvxShadowItem* pShadowAttr = &aPatternHolder.getScPatternAttr()->GetItem(ATTR_SHADOW); if (!SfxPoolItem::areSame(pShadowAttr, pDefShadow)) bAnyShadow = true; - const ScMergeAttr* pMergeAttr = &pPattern->GetItem(ATTR_MERGE); + const ScMergeAttr* pMergeAttr = &aPatternHolder.getScPatternAttr()->GetItem(ATTR_MERGE); bool bMerged = !SfxPoolItem::areSame( pMergeAttr, pDefMerge ); - ScMF nOverlap = pPattern->GetItemSet(). + ScMF nOverlap = aPatternHolder.getScPatternAttr()->GetItemSet(). Get(ATTR_MERGE_FLAG).GetValue(); bool bHOverlapped(nOverlap & ScMF::Hor); bool bVOverlapped(nOverlap & ScMF::Ver); @@ -569,14 +569,14 @@ void ScDocument::FillInfo( bool bHidden, bHideFormula; if (bTabProtect) { - const ScProtectionAttr& rProtAttr = pPattern->GetItem(ATTR_PROTECTION); + const ScProtectionAttr& rProtAttr = aPatternHolder.getScPatternAttr()->GetItem(ATTR_PROTECTION); bHidden = rProtAttr.GetHideCell(); bHideFormula = rProtAttr.GetHideFormula(); } else bHidden = bHideFormula = false; - const ScCondFormatIndexes& rCondFormats = pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData(); + const ScCondFormatIndexes& rCondFormats = aPatternHolder.getScPatternAttr()->GetItem(ATTR_CONDITIONAL).GetCondFormatData(); bool bContainsCondFormat = !rCondFormats.empty(); do @@ -612,7 +612,7 @@ void ScDocument::FillInfo( { pInfo->maBackground = SfxPoolItemHolder(*pPool, pBackground); } - pInfo->pPatternAttr = pPattern; + pInfo->pPatternAttr = aPatternHolder; pInfo->bMerged = bMerged; pInfo->bHOverlapped = bHOverlapped; pInfo->bVOverlapped = bVOverlapped; @@ -737,7 +737,7 @@ void ScDocument::FillInfo( { if ( ScStyleSheet* pPreviewStyle = GetPreviewCellStyle( nCol, pRowInfo[nArrRow].nRowNo, nTab ) ) { - aAltPatterns.push_back( std::make_unique( *pInfo->pPatternAttr ) ); + aAltPatterns.push_back( std::make_unique( *pInfo->getPatternAttr() ) ); pModifiedPatt = aAltPatterns.back().get(); pModifiedPatt->SetStyleSheet( pPreviewStyle ); } diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 020315a20c85..9096748d4566 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -48,10 +49,13 @@ #include #include #include +#include #include #include #include +#include +#include #include #include #include @@ -427,7 +431,7 @@ bool lcl_isReference(const FormulaToken& rToken) rToken.GetType() == svDoubleRef; } -void adjustRangeName(formula::FormulaToken* pToken, ScDocument& rNewDoc, const ScDocument& rOldDoc, +void adjustRangeName(FormulaIndexToken* pToken, ScDocument& rNewDoc, const ScDocument& rOldDoc, const ScAddress& rNewPos, const ScAddress& rOldPos, bool bGlobalNamesToLocal) { ScRangeData* pRangeData = nullptr; @@ -453,8 +457,18 @@ void adjustDBRange(formula::FormulaToken* pToken, ScDocument& rNewDoc, const ScD ScDBCollection* pOldDBCollection = rOldDoc.GetDBCollection(); if (!pOldDBCollection) return;//strange error case, don't do anything + + auto eOpCode = pToken->GetOpCode(); + sal_uInt16 nIndex = 0; + if (eOpCode == ocDBArea) + nIndex = static_cast(pToken)->GetIndex(); + else if (eOpCode == ocTableRef) + nIndex = static_cast(pToken)->GetIndex(); + else + assert(false); + ScDBCollection::NamedDBs& aOldNamedDBs = pOldDBCollection->getNamedDBs(); - ScDBData* pDBData = aOldNamedDBs.findByIndex(pToken->GetIndex()); + ScDBData* pDBData = aOldNamedDBs.findByIndex(nIndex); if (!pDBData) return; //invalid index OUString aDBName = pDBData->GetUpperName(); @@ -470,11 +484,38 @@ void adjustDBRange(formula::FormulaToken* pToken, ScDocument& rNewDoc, const ScD ScDBData* pNewDBData = aNewNamedDBs.findByUpperName(aDBName); if (!pNewDBData) { + // No matching table in the destination. For a clipboard paste leave it + // unresolved (index 0 -> #REF!): a fully-covered table is already + // recreated at the paste position before the cells arrive, so a miss + // here means only part of the table was copied, and fabricating one + // would register a misplaced, header-less table. Like the OOXML format, + // a partial copy makes no table. For any other clone - undo/redo + // restore, transpose - keep materialising the table so the reference + // still resolves, as those paths always expected the table to exist. + // TODO: the OOXML format keeps the paste case working with a + // cross-document external table reference ('source.xlsx'#Table1[Col]). + // We have no external structured references yet, so the value becomes + // #REF! instead. + if (rOldDoc.IsClipboard()) + { + if (eOpCode == ocDBArea) + static_cast(pToken)->SetIndex(0); + else if (eOpCode == ocTableRef) + static_cast(pToken)->SetIndex(0); + else + assert(false); + return; + } pNewDBData = new ScDBData(*pDBData); bool ins = aNewNamedDBs.insert(std::unique_ptr(pNewDBData)); assert(ins); (void)ins; } - pToken->SetIndex(pNewDBData->GetIndex()); + if (eOpCode == ocDBArea) + static_cast(pToken)->SetIndex(pNewDBData->GetIndex()); + else if (eOpCode == ocTableRef) + static_cast(pToken)->SetIndex(pNewDBData->GetIndex()); + else + assert(false); } } @@ -797,6 +838,9 @@ ScFormulaCell::ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const mbIsExtRef(false), mbSeenInPath(false), mbFreeFlying(false), + mbDynamicArrayMaster(rCell.mbDynamicArrayMaster), + // A clone is not freshly typed, so the flag drops on copy. + mbAutoDynamicArrayEligible(false), cMatrixFlag ( rCell.cMatrixFlag ), nSeenInIteration(0), nFormatType( rCell.nFormatType ), @@ -835,7 +879,7 @@ ScFormulaCell::ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const { OpCode eOpCode = pToken->GetOpCode(); if (eOpCode == ocName) - adjustRangeName(pToken, rDoc, rCell.rDocument, aPos, rCell.aPos, bGlobalNamesToLocal); + adjustRangeName(static_cast(pToken), rDoc, rCell.rDocument, aPos, rCell.aPos, bGlobalNamesToLocal); else if (eOpCode == ocDBArea || eOpCode == ocTableRef) adjustDBRange(pToken, rDoc, rCell.rDocument); } @@ -848,6 +892,11 @@ ScFormulaCell::ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const } pCode->AdjustAbsoluteRefs( rCell.rDocument, rCell.aPos, aPos, bCopyBetweenDocs ); + + if ((nCloneFlags & ScCloneFlags::AdjustCrossSheetRefs) != ScCloneFlags::Default) + { + pCode->AdjustRelativeTabRefs(rCell.aPos.Tab(), aPos.Tab()); + } } if (!rDocument.IsClipOrUndo()) @@ -872,7 +921,21 @@ ScFormulaCell::ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const } else if ( t->GetType() == svIndex ) { - const ScRangeData* pRangeData = rDoc.FindRangeNameBySheetAndIndex( t->GetSheet(), t->GetIndex()); + sal_Int16 nSheet; + sal_uInt16 nIndex; + if (t->GetOpCode() == ocName || t->GetOpCode() == ocDBArea) + { + auto pIToken = static_cast(t); + nSheet = pIToken->GetSheet(); + nIndex = pIToken->GetIndex(); + } + else + { + auto pIToken = static_cast(t); + nSheet = -1; + nIndex = pIToken->GetIndex(); + } + const ScRangeData* pRangeData = rDoc.FindRangeNameBySheetAndIndex( nSheet, nIndex); if( pRangeData ) { if( pRangeData->HasReferences() ) @@ -966,7 +1029,7 @@ OUString ScFormulaCell::GetFormula( const FormulaGrammar::Grammar eGrammar, ScIn * GetEnglishFormula() omitted that test. * Can we live without in all cases? */ ScFormulaCell* pCell = nullptr; - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(rDocument, aPos); if (rDocument.ValidAddress(aAbs)) pCell = rDocument.GetFormulaCell(aAbs); @@ -993,7 +1056,9 @@ OUString ScFormulaCell::GetFormula( const FormulaGrammar::Grammar eGrammar, ScIn } buffer.insert( 0, '='); - if( cMatrixFlag != ScMatrixMode::NONE ) + // Dynamic-array masters read back as plain formulas in the formula + // bar. Static array masters still get the {} wrapping. + if (cMatrixFlag != ScMatrixMode::NONE && !mbDynamicArrayMaster) { buffer.insert( 0, '{'); buffer.append( '}'); @@ -1024,7 +1089,7 @@ OUString ScFormulaCell::GetFormula( sc::CompileFormulaContext& rCxt, ScInterpret * GetEnglishFormula() omitted that test. * Can we live without in all cases? */ ScFormulaCell* pCell = nullptr; - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(rDocument, aPos); if (rDocument.ValidAddress(aAbs)) pCell = rDocument.GetFormulaCell(aAbs); @@ -1051,7 +1116,9 @@ OUString ScFormulaCell::GetFormula( sc::CompileFormulaContext& rCxt, ScInterpret } aBuf.insert( 0, '='); - if( cMatrixFlag != ScMatrixMode::NONE ) + // Dynamic-array masters read back as plain formulas in the formula + // bar. Static array masters still get the {} wrapping. + if (cMatrixFlag != ScMatrixMode::NONE && !mbDynamicArrayMaster) { aBuf.insert( 0, '{'); aBuf.append( '}'); @@ -1066,7 +1133,7 @@ void ScFormulaCell::GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows ) if (pCode->GetCodeError() == FormulaError::NONE && aResult.GetType() == svMatrixCell) { - const ScMatrix* pMat = aResult.GetToken()->GetMatrix(); + const ScMatrix* pMat = static_cast(aResult.GetToken().get())->GetMatrix(); if (pMat) { pMat->GetDimensions( rCols, rRows ); @@ -1353,6 +1420,12 @@ void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rPr // (for external links warning, CompileXML is called at the end of loading XML file) rDocument.CheckLinkFormulaNeedingCheck(*pCode); + // Plain non-array cells whose RPN intends an array result get the @ + // implicit-intersection marker baked in here, so the round trip + // preserves their single-value intent without leaning on a runtime + // flag. + ResolveImplicitIntersection(); + //volatile cells must be added here for import if( !pCode->IsRecalcModeNormal() || pCode->IsRecalcModeForced()) { @@ -1427,7 +1500,7 @@ void ScFormulaCell::CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartL // for each F9 bDirty = true; } - // No SetDirty yet, as no all Listeners are known yet (only in SetDirtyAfterLoad) + // No SetDirty yet, as not all Listeners are known yet (only in SetDirtyAfterLoad) } bool ScFormulaCell::MarkUsedExternalReferences() @@ -1501,6 +1574,187 @@ private: } }; +// True when the RPN top is the @ implicit-intersection operator. +bool rpnTopIsImplicitIntersection(const ScTokenArray& rCode) +{ + const sal_uInt16 nRpnLength = rCode.GetCodeLen(); + if (nRpnLength == 0) + return false; + const formula::FormulaToken* pTop = rCode.GetCode()[nRpnLength - 1]; + return pTop && pTop->GetOpCode() == ocSingleValue; +} + +// Bottom-up RPN walk that decides whether the formula intends to produce +// an array. A push of a range or inline matrix is an array on the stack. +// Binary and unary operators preserve array-ness through any operand. A +// function known to return a matrix (UNIQUE, TRANSPOSE, MMULT ...) pushes +// an array, every other function reduces to a scalar. Returns false if +// the walk cannot decide: jump commands, arity mismatch, null tokens. +bool intendsArrayResultInRange(formula::FormulaToken* const* pRpn, + sal_uInt16 nStart, sal_uInt16 nEnd) +{ + std::vector aStackIsArray; + for (sal_uInt16 i = nStart; i < nEnd; ++i) + { + const formula::FormulaToken* p = pRpn[i]; + if (!p) + return false; + const OpCode eOp = p->GetOpCode(); + if (eOp == ocPush) + { + const formula::StackVar eType = p->GetType(); + aStackIsArray.push_back(eType == formula::svDoubleRef + || eType == formula::svExternalDoubleRef + || eType == formula::svMatrix); + continue; + } + // Jump commands expose their branches through a + // FormulaJumpToken. In most cases, branches + // k=1..nJumpCount-1 hold the result expressions: IF + // carries THEN and ELSE, CHOOSE carries the + // alternatives. The token is array-intent if any branch + // is. + if (eOp == ocIf || eOp == ocIfError || eOp == ocIfNA + || eOp == ocChoose) + { + if (aStackIsArray.empty()) + return false; + aStackIsArray.pop_back(); + const auto* pJumpTok = static_cast(p); + const short* pJump = pJumpTok->GetJump(); + const short nJumpCount = pJump[0]; + bool bAnyBranchArray = false; + for (short nBranch = 1; nBranch < nJumpCount && !bAnyBranchArray; ++nBranch) + { + const sal_uInt16 nBranchStart = pJump[nBranch] + 1; + const sal_uInt16 nBranchEnd = pJump[nBranch + 1]; + if (nBranchEnd <= nBranchStart || nBranchEnd > nEnd) + continue; + if (intendsArrayResultInRange(pRpn, nBranchStart, nBranchEnd)) + bAnyBranchArray = true; + } + aStackIsArray.push_back(bAnyBranchArray); + i = pJump[nJumpCount]; + continue; + } + // Whether LET intends an array depends (only) on the + // last subexpression. + // TODO: More sophisticated analysis is possible; the + // other subexpressions can be substituted into the + // last one, to determine the answer more conclusively. + // Is it worthwhile to do this analysis? + if (eOp == ocLet) + { + if (aStackIsArray.empty()) + return false; + aStackIsArray.pop_back(); + const auto* pJumpTok = static_cast(p); + const short* pJump = pJumpTok->GetJump(); + const short nJumpCount = pJump[0]; + short nBranch = nJumpCount - 1; + const sal_uInt16 nBranchStart = pJump[nBranch] + 1; + const sal_uInt16 nBranchEnd = pJump[nBranch + 1]; + if (nBranchEnd > nBranchStart && nBranchEnd <= nEnd) + aStackIsArray.push_back(intendsArrayResultInRange(pRpn, nBranchStart, nBranchEnd)); + else + aStackIsArray.push_back(false); + i = pJump[nJumpCount]; + continue; + } + // The output of a LAMBDA is always a callable (or an + // error), never an array. ocLambda also appears before + // the first subexpression, instead of after. + if (eOp == ocLambda) + { + const auto* pJumpTok = static_cast(p); + const short* pJump = pJumpTok->GetJump(); + const short nJumpCount = pJump[0]; + aStackIsArray.push_back(false); + i = pJump[nJumpCount]; + continue; + } + // Any other jump command stays an unknown shape. + if (formula::FormulaCompiler::IsOpCodeJumpCommand(eOp)) + return false; + const sal_uInt8 nParameters = p->GetParamCount(); + if (nParameters > aStackIsArray.size()) + return false; + bool bAnyArrayArgument = false; + for (sal_uInt8 j = 0; j < nParameters; ++j) + { + if (aStackIsArray.back()) + bAnyArrayArgument = true; + aStackIsArray.pop_back(); + } + bool bResultArray = false; + if (eOp == ocSingleValue) + // The @ implicit-intersection operator extracts the upper- + // left scalar from its operand. The result is scalar even + // when the operand was an array. + bResultArray = false; + else if (eOp == ocSpill) + // The # spilled-range operator expands its operand to the + // whole spill range. The result is an array whatever the + // operand shape was. + bResultArray = true; + else if (formula::FormulaCompiler::IsMatrixFunction(eOp) || p->IsInForceArray()) + bResultArray = true; + else if (eOp == ocRange || eOp == ocUnion || eOp == ocIntersect) + // The ODFF parser keeps A:B style range constructors as + // their own opcodes instead of folding them into a single + // svDoubleRef push. The result is always a multi-cell + // reference, so the array flag flows through. + bResultArray = true; + else if (isBinaryOperatorOpCode(eOp) && eOp != ocAnd && eOp != ocOr) + // ocAnd and ocOr share the binary-operator opcode range but + // reduce their arguments to a scalar boolean. Treat them as + // function-form reducers, not elementwise operators. + bResultArray = bAnyArrayArgument; + else if (isUnaryOperatorOpCode(eOp)) + bResultArray = bAnyArrayArgument; + aStackIsArray.push_back(bResultArray); + } + return !aStackIsArray.empty() && aStackIsArray.back(); +} + +bool rpnIntendsArrayResult(const ScTokenArray& rCode) +{ + const sal_uInt16 nRpnLength = rCode.GetCodeLen(); + if (nRpnLength == 0) + return false; + return intendsArrayResultInRange(rCode.GetCode(), 0, nRpnLength); +} + +// Prepend @ to a token array. The parse array gets it at index 0 (a +// prefix operator in the formula text). The RPN gets it at the end +// (where ocSingleValue belongs in postfix). +void prependImplicitIntersection(ScTokenArray& rCode) +{ + // A cloned or compiled array is already at its final size and cannot grow, so build fresh parse + // and RPN buffers with the extra token in place and install them directly: + formula::FormulaToken* pSingleValue = new formula::FormulaByteToken(ocSingleValue); + + // For the parse buffer, the new token is a prefix operator, so it is prepended at index 0: + const sal_uInt16 parseLength = rCode.GetLen(); + formula::FormulaToken** pParse = rCode.GetArray(); + std::vector newParse(parseLength + 1); + newParse[0] = pSingleValue; + for (sal_uInt16 i = 0; i < parseLength; ++i) + newParse[i + 1] = pParse[i]; + pSingleValue->IncRef(); + rCode.CreateNewCodeArrayFromData(newParse.data(), parseLength + 1); + + // For the RPN buffer, ocSingleValue belongs at the end in postfix order: + const sal_uInt16 nRpnLength = rCode.GetCodeLen(); + formula::FormulaToken** pRpn = rCode.GetCode(); + std::vector aNewRpn(nRpnLength + 1); + for (sal_uInt16 i = 0; i < nRpnLength; ++i) + aNewRpn[i] = pRpn[i]; + aNewRpn[nRpnLength] = pSingleValue; + pSingleValue->IncRef(); + rCode.CreateNewRPNArrayFromData(aNewRpn.data(), nRpnLength + 1); +} + } // namespace bool ScFormulaCell::Interpret(SCROW nStartOffset, SCROW nEndOffset) @@ -1667,7 +1921,7 @@ bool ScFormulaCell::Interpret(SCROW nStartOffset, SCROW nEndOffset) // Mark older cells dirty again, in case they converted // without accounting for all remaining cells in the circle // that weren't touched so far, e.g. conditional. Restore - // backupped result. + // backed-up result. sal_uInt16 nIteration = rRecursionHelper.GetIteration(); for (ScFormulaRecursionList::const_iterator aIter( aOldStart); aIter != @@ -1885,6 +2139,15 @@ bool ScFormulaCell::Interpret(SCROW nStartOffset, SCROW nEndOffset) aDC.storeResult( aResult.GetString()); #endif + // A lazy Interpret() may have queued a dynamic-array resize. The + // TrackFormulas and CalcFormulaTree hooks don't fire on this path, + // so drain the queue once the outermost interpret has unwound. + if (rDocument.HasPendingMatrixResizes() + && !rDocument.IsInInterpreter() && !rDocument.IsInDtorClear()) + { + rDocument.ProcessPendingMatrixResizes(); + } + return bGroupInterpreted; } @@ -1917,6 +2180,28 @@ void ScFormulaCell::InterpretTail( ScInterpreterContext& rContext, ScInterpretTa if( pCode->GetCodeLen() ) { + // A freshly UI-typed formula promotes to a dynamic-array master + // at interpret entry when the RPN says it intends to produce an + // array. Matrix mode has to be set before the interpreter runs + // so the array result is kept. Loaded and macro-created cells + // leave the flag false so legacy formulas keep their old + // result. An @ at the top suppresses promotion. Grouped cells + // stay single-cell so the group is not broken. + if (mbAutoDynamicArrayEligible + && cMatrixFlag == ScMatrixMode::NONE + && !pCode->IsHyperLink() + && !mxGroup) + { + if (!rpnTopIsImplicitIntersection(*pCode) + && rpnIntendsArrayResult(*pCode)) + { + cMatrixFlag = ScMatrixMode::Formula; + SetMatColsRows(1, 1); + mbDynamicArrayMaster = true; + } + mbAutoDynamicArrayEligible = false; + } + std::unique_ptr pScopedInterpreter; ScInterpreter* pInterpreter; if (rContext.pInterpreter) @@ -2254,8 +2539,96 @@ void ScFormulaCell::InterpretTail( ScInterpreterContext& rContext, ScInterpretTa { // If the formula wasn't entered as a matrix formula, live on with // the upper left corner and let reference counting delete the matrix. - if( cMatrixFlag != ScMatrixMode::Formula && !pCode->IsHyperLink() ) + if (cMatrixFlag != ScMatrixMode::Formula && !pCode->IsHyperLink()) + { aResult.SetToken( aResult.GetCellResultToken().get()); + } + else + { + // If the result is larger than the declared matrix, check the + // expansion area for blocking cells and report #SPILL! if any. + SCCOL nDeclCols = 0; + SCROW nDeclRows = 0; + GetMatColsRows(nDeclCols, nDeclRows); + SCSIZE nResCols = 0; + SCSIZE nResRows = 0; + aResult.GetMatrix()->GetDimensions(nResCols, nResRows); + bool bSpillBlocked = false; + // Auto resize fires for matrix formulas whose result wants + // more cells than declared, in two situations: + // - the cell is a dynamic-array master. + // - the cell is currently in spill state. Re-checking lets + // the matrix auto expand the next time the user clears + // the blocking cell. + // Static array masters where the user explicitly picked the + // range fall outside both - their declared dimensions are + // intentional. + const bool bShouldCheckSpill + = mbDynamicArrayMaster + || rDocument.IsFormulaSpilled(aPos); + if (bShouldCheckSpill && nDeclCols > 0 && nDeclRows > 0 + && (o3tl::make_unsigned(nDeclCols) < nResCols + || o3tl::make_unsigned(nDeclRows) < nResRows)) + { + SCCOL nSpillEndCol = aPos.Col() + static_cast(nResCols) - 1; + SCROW nSpillEndRow = aPos.Row() + static_cast(nResRows) - 1; + if (nSpillEndCol > rDocument.MaxCol() || nSpillEndRow > rDocument.MaxRow()) + { + bSpillBlocked = true; // spill would go out of bounds + } + else + { + bSpillBlocked = rDocument.IsMatrixSpillBlocked( + ScRange(aPos.Col(), aPos.Row(), aPos.Tab(), + nSpillEndCol, nSpillEndRow, aPos.Tab()), + nDeclCols, nDeclRows); + } + if (bSpillBlocked) + { + // Set only the result error, not a code error. Code + // errors are sticky and would prevent re-evaluation + // when the blocking cells are later cleared. + aResult.SetResultError(FormulaError::Spill); + bChanged = bContentChanged = true; + } + } + // Track spill state so cell-change operations can re-evaluate. + if (bSpillBlocked) + rDocument.MarkFormulaSpilled(aPos); + else + rDocument.UnmarkFormulaSpilled(aPos); + + // Collapse to 1x1 on spill so previously materialised reference + // cells are cleared, leaving only the origin to show #SPILL!. + // Deferred - deleting cells inline would invalidate the caller's + // cell-store iterator. + if (bSpillBlocked && (nDeclCols > 1 || nDeclRows > 1) + && !rDocument.IsThreadedGroupCalcInProgress()) + { + rDocument.MarkPendingMatrixResize(aPos); + } + + if (!bSpillBlocked && nDeclCols > 0 && nDeclRows > 0 + && bShouldCheckSpill + && !rDocument.IsThreadedGroupCalcInProgress()) + { + if (o3tl::make_unsigned(nDeclCols) > nResCols + || o3tl::make_unsigned(nDeclRows) > nResRows) + { + // Contract inline: removing cells can't recurse into + // Interpret. ResizeMatrixFormula itself defers while a + // cell-store iteration is live, so the call stays safe. + rDocument.ResizeMatrixFormula(aPos, SCCOL(nResCols), SCROW(nResRows)); + } + else if (o3tl::make_unsigned(nDeclCols) < nResCols + || o3tl::make_unsigned(nDeclRows) < nResRows) + { + // Expand is deferred: freshly created reference cells + // would otherwise recurse through Interpret. + rDocument.MarkPendingMatrixResize(aPos); + } + } + } } if ( aResult.IsValue() && !std::isfinite( aResult.GetDouble() ) ) { @@ -2392,6 +2765,52 @@ void ScFormulaCell::SetCompile( bool bVal ) bCompile = bVal; } +void ScFormulaCell::SetDynamicArrayMaster(bool bDynamic) +{ + // A formula with @ on top of its RPN opts out of dynamic-array + // spilling: the operator collapses any array operand to a single + // value, so there is nothing to spill. XLSX still emits the cm="1" + // marker on such cells, so reject the request rather than letting + // the spill check fire against a 1x1 declared matrix. + if (bDynamic && pCode && rpnTopIsImplicitIntersection(*pCode)) + return; + mbDynamicArrayMaster = bDynamic; + // A plain single-cell formula that opts into the dynamic-array flag + // becomes a 1x1 matrix master so the first interpret can expand it + // through the auto-resize gate. + if (bDynamic && cMatrixFlag == ScMatrixMode::NONE) + { + cMatrixFlag = ScMatrixMode::Formula; + SetMatColsRows(1, 1); + } +} + +void ScFormulaCell::ResolveImplicitIntersection(ScTokenArray& rCode, ScDocument& rDoc, + const ScAddress& rPos) +{ + if (rCode.IsHyperLink() || rCode.GetLen() == 0) + return; + if (rCode.GetCodeLen() == 0) + { + // Parse has tokens but RPN was not built yet. Build it so the + // walk has post-fix order to inspect. Keep multi-cell range + // tokens unfolded so the array-intent walk can see them. + ScCompiler aComp(rDoc, rPos, rCode, formula::FormulaGrammar::GRAM_DEFAULT, false, false); + aComp.CompileTokenArray(); + } + if (rpnTopIsImplicitIntersection(rCode)) + return; + if (rpnIntendsArrayResult(rCode)) + prependImplicitIntersection(rCode); +} + +void ScFormulaCell::ResolveImplicitIntersection() +{ + if (!pCode || cMatrixFlag != ScMatrixMode::NONE || mxGroup) + return; + ResolveImplicitIntersection(*pCode, rDocument, aPos); +} + void ScFormulaCell::SetMatColsRows( SCCOL nCols, SCROW nRows ) { ScMatrixFormulaCellToken* pMat = aResult.GetMatrixFormulaCellTokenNonConst(); @@ -2652,6 +3071,13 @@ void ScFormulaCell::SetResultError( FormulaError n ) aResult.SetResultError( n ); } +void ScFormulaCell::MarkAsSpilled() +{ + SetMatColsRows(1, 1); + SetResultError(FormulaError::Spill); + rDocument.MarkFormulaSpilled(aPos); +} + void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits ) { if ( (nBits & ScRecalcMode::EMask) != ScRecalcMode::NORMAL ) @@ -2741,7 +3167,7 @@ bool ScFormulaCell::IsHyperLinkCell() const return pCode && pCode->IsHyperLink(); } -std::unique_ptr ScFormulaCell::CreateURLObject() +EditTextObject ScFormulaCell::CreateURLObject() { OUString aCellText; OUString aURL; @@ -2789,6 +3215,18 @@ bool ScFormulaCell::IsValueNoError() const return aResult.IsValueNoError(); } +bool ScFormulaCell::IsString() +{ + MaybeInterpret(); + return aResult.IsString(); +} + +bool ScFormulaCell::IsCallable() +{ + MaybeInterpret(); + return aResult.IsCallable(); +} + double ScFormulaCell::GetValue() { MaybeInterpret(); @@ -2801,6 +3239,18 @@ const svl::SharedString & ScFormulaCell::GetString() return GetRawString(); } +formula::FormulaCallableRef ScFormulaCell::GetCallable() +{ + MaybeInterpret(); + return GetRawCallable(); +} + +formula::FormulaTokenRef ScFormulaCell::CloneResultToken() +{ + MaybeInterpret(); + return CloneRawResultToken(); +} + double ScFormulaCell::GetRawValue() const { if ((pCode->GetCodeError() == FormulaError::NONE) && @@ -2812,12 +3262,38 @@ double ScFormulaCell::GetRawValue() const const svl::SharedString & ScFormulaCell::GetRawString() const { if ((pCode->GetCodeError() == FormulaError::NONE) && - aResult.GetResultError() == FormulaError::NONE) + aResult.GetResultError() == FormulaError::NONE) return aResult.GetString(); return svl::SharedString::getEmptyString(); } +formula::FormulaCallableRef ScFormulaCell::GetRawCallable() const +{ + if ((pCode->GetCodeError() == FormulaError::NONE) && + aResult.GetResultError() == FormulaError::NONE) + return aResult.GetCallable(); + + return nullptr; +} + +formula::FormulaConstTokenRef ScFormulaCell::GetRawResultToken() const +{ + if ((pCode->GetCodeError() == FormulaError::NONE) && + aResult.GetResultError() == FormulaError::NONE) + return aResult.GetToken(); + + return nullptr; +} + +formula::FormulaTokenRef ScFormulaCell::CloneRawResultToken() const +{ + if (pCode->GetCodeError() != FormulaError::NONE) + return new formula::FormulaErrorToken(pCode->GetCodeError()); + else + return aResult.CloneToken(); +} + const ScMatrix* ScFormulaCell::GetMatrix() { if ( rDocument.GetAutoCalc() ) @@ -2843,7 +3319,7 @@ bool ScFormulaCell::GetMatrixOrigin( const ScDocument& rDoc, ScAddress& rPos ) c formula::FormulaToken* t = aIter.GetNextReferenceRPN(); if( t ) { - ScSingleRefData& rRef = *t->GetSingleRef(); + ScSingleRefData& rRef = static_cast(t)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(rDoc, aPos); if (rDoc.ValidAddress(aAbs)) { @@ -3098,11 +3574,13 @@ ScFormulaCell::RelNameRef ScFormulaCell::HasRelNameReference() const switch (t->GetType()) { case formula::svSingleRef: - if (t->GetSingleRef()->IsRelName() && eRelNameRef == RelNameRef::NONE) + if (static_cast(t)->GetSingleRef().IsRelName() && eRelNameRef == RelNameRef::NONE) eRelNameRef = RelNameRef::SINGLE; break; case formula::svDoubleRef: - if (t->GetDoubleRef()->Ref1.IsRelName() || t->GetDoubleRef()->Ref2.IsRelName()) + { + auto pDoubleRefToken = static_cast(t); + if (pDoubleRefToken->GetDoubleRef().Ref1.IsRelName() || pDoubleRefToken->GetDoubleRef().Ref2.IsRelName()) // May originate from individual cell names, in which case // it needs recompilation. return RelNameRef::DOUBLE; @@ -3110,6 +3588,7 @@ ScFormulaCell::RelNameRef ScFormulaCell::HasRelNameReference() const * extended? or too cumbersome? might narrow recompilation to * only needed cases. * */ + } break; default: ; // nothing @@ -3164,7 +3643,7 @@ bool checkCompileColRowName( ScRangePairList* pRowList = rDoc.GetRowNameRanges(); while ((t = aIter.GetNextColRowName()) != nullptr) { - ScSingleRefData& rRef = *t->GetSingleRef(); + ScSingleRefData& rRef = static_cast(t)->GetSingleRef(); if (rCxt.mnRowDelta > 0 && rRef.IsColRel()) { // ColName ScAddress aAdr = rRef.toAbs(rDoc, aPos); @@ -3209,7 +3688,7 @@ bool checkCompileColRowName( const formula::FormulaToken* t = aIter.GetNextColRowName(); for (; t; t = aIter.GetNextColRowName()) { - const ScSingleRefData& rRef = *t->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(t)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(rDoc, aPos); if (rDoc.ValidAddress(aAbs)) { @@ -3692,12 +4171,12 @@ void ScFormulaCell::UpdateInsertTabAbs(SCTAB nTable) formula::FormulaToken* p = aIter.GetNextReferenceRPN(); while (p) { - ScSingleRefData& rRef1 = *p->GetSingleRef(); - if (!rRef1.IsTabRel() && nTable <= rRef1.Tab()) - rRef1.IncTab(1); + ScSingleRefData* pRef1 = ScRefTokenHelper::getSingleRef(p); + if (!pRef1->IsTabRel() && nTable <= pRef1->Tab()) + pRef1->IncTab(1); if (p->GetType() == formula::svDoubleRef) { - ScSingleRefData& rRef2 = p->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(p)->GetDoubleRef().Ref2; if (!rRef2.IsTabRel() && nTable <= rRef2.Tab()) rRef2.IncTab(1); } @@ -3705,6 +4184,18 @@ void ScFormulaCell::UpdateInsertTabAbs(SCTAB nTable) } } +void ScFormulaCell::AdjustRelativeTabRefs(SCTAB nOldTab, SCTAB nNewTab, sc::TargetTabState eMode) +{ + if (rDocument.IsClipOrUndo()) + return; + + bool bAdjustCode = !mxGroup || mxGroup->mpTopCell == this; + if (!bAdjustCode) + return; + + pCode->AdjustRelativeTabRefs(nOldTab, nNewTab, eMode); +} + bool ScFormulaCell::TestTabRefAbs(SCTAB nTable) { if (rDocument.IsClipOrUndo()) @@ -3719,7 +4210,7 @@ bool ScFormulaCell::TestTabRefAbs(SCTAB nTable) formula::FormulaToken* p = aIter.GetNextReferenceRPN(); while (p) { - ScSingleRefData& rRef1 = *p->GetSingleRef(); + ScSingleRefData& rRef1 = *ScRefTokenHelper::getSingleRef(p); if (!rRef1.IsTabRel()) { if (nTable != rRef1.Tab()) @@ -3729,7 +4220,7 @@ bool ScFormulaCell::TestTabRefAbs(SCTAB nTable) } if (p->GetType() == formula::svDoubleRef) { - ScSingleRefData& rRef2 = p->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(p)->GetDoubleRef().Ref2; if (!rRef2.IsTabRel()) { if(nTable != rRef2.Tab()) @@ -3769,14 +4260,14 @@ void ScFormulaCell::TransposeReference() formula::FormulaToken* t; while ( ( t = aIter.GetNextReference() ) != nullptr ) { - ScSingleRefData& rRef1 = *t->GetSingleRef(); - if ( rRef1.IsColRel() && rRef1.IsRowRel() ) + ScSingleRefData* pRef1 = ScRefTokenHelper::getSingleRef(t); + if ( pRef1->IsColRel() && pRef1->IsRowRel() ) { bool bDouble = (t->GetType() == formula::svDoubleRef); - ScSingleRefData& rRef2 = (bDouble ? t->GetDoubleRef()->Ref2 : rRef1); + ScSingleRefData& rRef2 = (bDouble ? static_cast(t)->GetDoubleRef().Ref2 : *pRef1); if ( !bDouble || (rRef2.IsColRel() && rRef2.IsRowRel()) ) { - lcl_TransposeReference(rRef1); + lcl_TransposeReference(*pRef1); if ( bDouble ) lcl_TransposeReference(rRef2); @@ -3828,7 +4319,8 @@ void ScFormulaCell::UpdateTranspose( const ScRange& rSource, const ScAddress& rD { if( t->GetOpCode() == ocName ) { - const ScRangeData* pName = rDocument.FindRangeNameBySheetAndIndex( t->GetSheet(), t->GetIndex()); + auto pIndexToken = static_cast(t); + const ScRangeData* pName = rDocument.FindRangeNameBySheetAndIndex( pIndexToken->GetSheet(), pIndexToken->GetIndex()); if (pName && pName->IsModified()) bRefChanged = true; } @@ -3889,7 +4381,8 @@ void ScFormulaCell::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY { if( t->GetOpCode() == ocName ) { - const ScRangeData* pName = rDocument.FindRangeNameBySheetAndIndex( t->GetSheet(), t->GetIndex()); + auto pIndexToken = static_cast(t); + const ScRangeData* pName = rDocument.FindRangeNameBySheetAndIndex( pIndexToken->GetSheet(), pIndexToken->GetIndex()); if (pName && pName->IsModified()) bRefChanged = true; } @@ -3926,8 +4419,9 @@ static void lcl_FindRangeNamesInUse(sc::UpdatedRangeNames& rIndexes, const ScTok { if (p->GetOpCode() == ocName) { - sal_uInt16 nTokenIndex = p->GetIndex(); - SCTAB nTab = p->GetSheet(); + auto pIndexToken = static_cast(p); + sal_uInt16 nTokenIndex = pIndexToken->GetIndex(); + SCTAB nTab = pIndexToken->GetSheet(); rIndexes.setUpdatedName( nTab, nTokenIndex); if (nRecursion < 126) // whatever... 42*3 @@ -4101,8 +4595,8 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( const ScFormulaC case formula::svSingleRef: { // Single cell reference. - const ScSingleRefData& rRef = *pThisTok->GetSingleRef(); - if (rRef != *pOtherTok->GetSingleRef()) + const ScSingleRefData& rRef = static_cast(pThisTok)->GetSingleRef(); + if (rRef != static_cast(pOtherTok)->GetSingleRef()) return NotEqual; if (rRef.IsRowRel()) @@ -4112,12 +4606,12 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( const ScFormulaC case formula::svDoubleRef: { // Range reference. - const ScSingleRefData& rRef1 = *pThisTok->GetSingleRef(); - const ScSingleRefData& rRef2 = *pThisTok->GetSingleRef2(); - if (rRef1 != *pOtherTok->GetSingleRef()) + const ScSingleRefData& rRef1 = static_cast(pThisTok)->GetSingleRef(); + const ScSingleRefData& rRef2 = static_cast(pThisTok)->GetSingleRef2(); + if (rRef1 != static_cast(pOtherTok)->GetSingleRef()) return NotEqual; - if (rRef2 != *pOtherTok->GetSingleRef2()) + if (rRef2 != static_cast(pOtherTok)->GetSingleRef2()) return NotEqual; if (rRef1.IsRowRel()) @@ -4129,40 +4623,57 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( const ScFormulaC break; case formula::svDouble: { - if(!rtl::math::approxEqual(pThisTok->GetDouble(), pOtherTok->GetDouble())) + if(!rtl::math::approxEqual(static_cast(pThisTok)->GetDouble(), static_cast(pOtherTok)->GetDouble())) return NotEqual; } break; case formula::svString: { - if(pThisTok->GetString() != pOtherTok->GetString()) + assert(dynamic_cast(pThisTok)); + assert(dynamic_cast(pOtherTok)); + if(static_cast(pThisTok)->GetString() != static_cast(pOtherTok)->GetString()) return NotEqual; } break; case formula::svIndex: { - if(pThisTok->GetIndex() != pOtherTok->GetIndex() || pThisTok->GetSheet() != pOtherTok->GetSheet()) - return NotEqual; + if (pThisTok->GetOpCode() == ocName || pThisTok->GetOpCode() == ocDBArea) + { + auto lhs = static_cast(pThisTok); + auto rhs = static_cast(pOtherTok); + if(lhs->GetIndex() != rhs->GetIndex() || lhs->GetSheet() != rhs->GetSheet()) + return NotEqual; + } + else + { + assert(pThisTok->GetOpCode() == ocTableRef); + auto lhs = static_cast(pThisTok); + auto rhs = static_cast(pOtherTok); + if(lhs->GetIndex() != rhs->GetIndex()) + return NotEqual; + } } break; case formula::svByte: { - if(pThisTok->GetByte() != pOtherTok->GetByte()) + if(static_cast(pThisTok)->GetByte() != static_cast(pOtherTok)->GetByte()) return NotEqual; } break; case formula::svExternal: { - if (pThisTok->GetExternal() != pOtherTok->GetExternal()) + auto lhs = static_cast(pThisTok); + auto rhs = static_cast(pOtherTok); + if (lhs->GetExternal() != rhs->GetExternal()) return NotEqual; - - if (pThisTok->GetByte() != pOtherTok->GetByte()) + if (lhs->GetByte() != rhs->GetByte()) return NotEqual; } break; case formula::svError: { - if (pThisTok->GetError() != pOtherTok->GetError()) + if (static_cast(pThisTok)->GetError() + != static_cast(pOtherTok)->GetError()) return NotEqual; } break; @@ -4210,8 +4721,8 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( const ScFormulaC case formula::svSingleRef: { // Single cell reference. - const ScSingleRefData& rRef = *pThisTok->GetSingleRef(); - if (rRef != *pOtherTok->GetSingleRef()) + const ScSingleRefData& rRef = static_cast(pThisTok)->GetSingleRef(); + if (rRef != static_cast(pOtherTok)->GetSingleRef()) return NotEqual; if (rRef.IsRowRel()) @@ -4221,12 +4732,12 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( const ScFormulaC case formula::svDoubleRef: { // Range reference. - const ScSingleRefData& rRef1 = *pThisTok->GetSingleRef(); - const ScSingleRefData& rRef2 = *pThisTok->GetSingleRef2(); - if (rRef1 != *pOtherTok->GetSingleRef()) + const ScSingleRefData& rRef1 = static_cast(pThisTok)->GetSingleRef(); + const ScSingleRefData& rRef2 = static_cast(pThisTok)->GetSingleRef2(); + if (rRef1 != static_cast(pOtherTok)->GetSingleRef()) return NotEqual; - if (rRef2 != *pOtherTok->GetSingleRef2()) + if (rRef2 != static_cast(pOtherTok)->GetSingleRef2()) return NotEqual; if (rRef1.IsRowRel()) @@ -4240,19 +4751,26 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( const ScFormulaC // different OpCode values. case formula::svIndex: { - if (pThisTok->GetIndex() != pOtherTok->GetIndex()) - return NotEqual; switch (pThisTok->GetOpCode()) { case ocTableRef: + { + if (static_cast(pThisTok)->GetIndex() + != static_cast(pOtherTok)->GetIndex()) + return NotEqual; // nothing, sheet value assumed as -1, silence // ScTableRefToken::GetSheet() SAL_WARN about // unhandled ; break; + } default: // ocName, ocDBArea - if (pThisTok->GetSheet() != pOtherTok->GetSheet()) + { + auto lhs = static_cast(pThisTok); + auto rhs = static_cast(pOtherTok); + if (lhs->GetIndex() != rhs->GetIndex() || lhs->GetSheet() != rhs->GetSheet()) return NotEqual; + } } } break; @@ -4441,7 +4959,7 @@ struct ScDependantsCalculator // Because Lookup will extend the Result Vector under certain circumstances listed at: // https://wiki.documentfoundation.org/Documentation/Calc_Functions/LOOKUP // then if the Lookup has a Result Vector only accept the Lookup for parallelization - // of the Result Vector has the same dimensions as the Search Vector. + // if the Result Vector has the same dimensions as the Search Vector. bool LookupResultVectorMismatch(sal_Int32 nTokenIdx) { if (nTokenIdx >= 3) @@ -4464,8 +4982,8 @@ struct ScDependantsCalculator // Result vector. if (res->GetType() == svDoubleRef) { - ScComplexRefData aRef1 = *res->GetDoubleRef(); - ScComplexRefData aRef2 = *pRPNArray[nTokenIdx - 2]->GetDoubleRef(); + ScComplexRefData aRef1 = static_cast(res)->GetDoubleRef(); + ScComplexRefData aRef2 = static_cast(pRPNArray[nTokenIdx - 2])->GetDoubleRef(); ScRange resultRange = aRef1.toAbs(mrDoc, mrPos); ScRange sourceRange = aRef2.toAbs(mrDoc, mrPos); @@ -4503,7 +5021,7 @@ struct ScDependantsCalculator { // The dependency evaluator evaluates all arguments of IF/IFS/SWITCH irrespective // of the result of the condition expression. - // This is a perf problem if we *don't* intent on recalc'ing all dirty cells + // This is a perf problem if we *don't* intend on recalc'ing all dirty cells // in the document. So let's disable threading and stop dependency evaluation if // the call did not originate from ScDocShell::DoRecalc()/ScDocShell::DoHardRecalc() // for formulae with IF/IFS/SWITCH @@ -4527,11 +5045,22 @@ struct ScDependantsCalculator return false; } + if ((p->GetOpCode() == ocSumIf || p->GetOpCode() == ocAverageIf) && p->GetParamCount() >= 3) + { + // With a separate sum range these functions grow it to the criteria range's shape + // when it is smaller, and read cells beyond the sum range's own reference. Those + // extra cells are not named by any reference token, so examining the arguments alone + // does not capture the true range of dependencies. The two argument form sums the + // criteria range itself and stays a candidate for parallelizing. + SAL_WARN("sc.core.formulacell", "conditional sum range extension, dropping as candidate for parallelizing"); + return false; + } + switch (p->GetType()) { case svSingleRef: { - ScSingleRefData aRef = *p->GetSingleRef(); // =Sheet1!A1 + ScSingleRefData aRef = static_cast(p)->GetSingleRef(); // =Sheet1!A1 if( aRef.IsDeleted()) return false; ScAddress aRefPos = aRef.toAbs(mrDoc, mrPos); @@ -4567,7 +5096,7 @@ struct ScDependantsCalculator break; case svDoubleRef: { - ScComplexRefData aRef = *p->GetDoubleRef(); + ScComplexRefData aRef = static_cast(p)->GetDoubleRef(); if( aRef.IsDeleted()) return false; ScRange aAbs = aRef.toAbs(mrDoc, mrPos); @@ -5266,7 +5795,7 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup() { case svSingleRef: { - ScSingleRefData aRef = *p->GetSingleRef(); + ScSingleRefData aRef = static_cast(p)->GetSingleRef(); ScAddress aRefPos = aRef.toAbs(rDocument, aPos); formula::FormulaTokenRef pNewToken = rDocument.ResolveStaticReference(aRefPos); if (!pNewToken) @@ -5277,7 +5806,7 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup() break; case svDoubleRef: { - ScComplexRefData aRef = *p->GetDoubleRef(); + ScComplexRefData aRef = static_cast(p)->GetDoubleRef(); ScRange aRefRange = aRef.toAbs(rDocument, aPos); formula::FormulaTokenRef pNewToken = rDocument.ResolveStaticReference(aRefRange); if (!pNewToken) @@ -5332,8 +5861,8 @@ namespace { void startListeningArea( ScFormulaCell* pCell, ScDocument& rDoc, const ScAddress& rPos, const formula::FormulaToken& rToken) { - const ScSingleRefData& rRef1 = *rToken.GetSingleRef(); - const ScSingleRefData& rRef2 = *rToken.GetSingleRef2(); + const ScSingleRefData& rRef1 = static_cast(rToken).GetSingleRef(); + const ScSingleRefData& rRef2 = static_cast(rToken).GetSingleRef2(); ScAddress aCell1 = rRef1.toAbs(rDoc, rPos); ScAddress aCell2 = rRef2.toAbs(rDoc, rPos); if (!(aCell1.IsValid() && aCell2.IsValid())) @@ -5381,7 +5910,7 @@ void ScFormulaCell::StartListeningTo( ScDocument& rDoc ) { case svSingleRef: { - ScAddress aCell = t->GetSingleRef()->toAbs(rDocument, aPos); + ScAddress aCell = static_cast(t)->GetSingleRef().toAbs(rDocument, aPos); if (aCell.IsValid()) rDoc.StartListeningCell(aCell, this); } @@ -5424,7 +5953,7 @@ void ScFormulaCell::StartListeningTo( sc::StartListeningContext& rCxt ) { case svSingleRef: { - ScAddress aCell = t->GetSingleRef()->toAbs(rDocument, aPos); + ScAddress aCell = static_cast(t)->GetSingleRef().toAbs(rDocument, aPos); if (aCell.IsValid()) rDoc.StartListeningCell(rCxt, aCell, *this); } @@ -5444,8 +5973,8 @@ namespace { void endListeningArea( ScFormulaCell* pCell, ScDocument& rDoc, const ScAddress& rPos, const formula::FormulaToken& rToken) { - const ScSingleRefData& rRef1 = *rToken.GetSingleRef(); - const ScSingleRefData& rRef2 = *rToken.GetSingleRef2(); + const ScSingleRefData& rRef1 = static_cast(rToken).GetSingleRef(); + const ScSingleRefData& rRef2 = static_cast(rToken).GetSingleRef2(); ScAddress aCell1 = rRef1.toAbs(rDoc, rPos); ScAddress aCell2 = rRef2.toAbs(rDoc, rPos); if (!(aCell1.IsValid() && aCell2.IsValid())) @@ -5501,7 +6030,7 @@ void ScFormulaCell::EndListeningTo( ScDocument& rDoc, ScTokenArray* pArr, { case svSingleRef: { - ScAddress aCell = t->GetSingleRef()->toAbs(rDocument, aCellPos); + ScAddress aCell = static_cast(t)->GetSingleRef().toAbs(rDocument, aCellPos); if (aCell.IsValid()) rDoc.EndListeningCell(aCell, this); } @@ -5548,7 +6077,7 @@ void ScFormulaCell::EndListeningTo( sc::EndListeningContext& rCxt ) { case svSingleRef: { - ScAddress aCell = t->GetSingleRef()->toAbs(rDocument, aCellPos); + ScAddress aCell = static_cast(t)->GetSingleRef().toAbs(rDocument, aCellPos); if (aCell.IsValid()) rDoc.EndListeningCell(rCxt, aCell, *this); } diff --git a/sc/source/core/data/formulaiter.cxx b/sc/source/core/data/formulaiter.cxx index d7f183b2a0a2..4478ab30d8b2 100644 --- a/sc/source/core/data/formulaiter.cxx +++ b/sc/source/core/data/formulaiter.cxx @@ -23,6 +23,7 @@ #include #include #include +#include using namespace formula; @@ -35,13 +36,21 @@ ScDetectiveRefIter::ScDetectiveRefIter( const ScDocument& rDoc, ScFormulaCell* p static bool lcl_ScDetectiveRefIter_SkipRef( const ScDocument& rDoc, formula::FormulaToken* p, const ScAddress& rPos ) { - ScSingleRefData& rRef1 = *p->GetSingleRef(); - ScAddress aAbs1 = rRef1.toAbs(rDoc, rPos); + ScSingleRefData* pRef1 = ScRefTokenHelper::getSingleRef(p); + ScAddress aAbs1 = pRef1->toAbs(rDoc, rPos); if (!rDoc.ValidAddress(aAbs1)) return true; - if ( p->GetType() == svDoubleRef || p->GetType() == svExternalDoubleRef ) + + if ( p->GetType() == svDoubleRef ) { - ScSingleRefData& rRef2 = p->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(p)->GetDoubleRef().Ref2; + ScAddress aAbs2 = rRef2.toAbs(rDoc, rPos); + if (!rDoc.ValidAddress(aAbs2)) + return true; + } + else if ( p->GetType() == svExternalDoubleRef ) + { + ScSingleRefData& rRef2 = static_cast(p)->GetDoubleRef().Ref2; ScAddress aAbs2 = rRef2.toAbs(rDoc, rPos); if (!rDoc.ValidAddress(aAbs2)) return true; diff --git a/sc/source/core/data/funcdesc.cxx b/sc/source/core/data/funcdesc.cxx index e9e02c78f01c..b70895e28482 100644 --- a/sc/source/core/data/funcdesc.cxx +++ b/sc/source/core/data/funcdesc.cxx @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -43,9 +44,9 @@ namespace { struct ScFuncDescCore { /* - * An opcode from include/formula/compiler.hxx + * An opcode from include/formula/opcode.hxx */ - sal_uInt16 nOpCode; + OpCode nOpCode; /* * Pointer to list of strings */ @@ -181,10 +182,10 @@ OUString ScFuncDesc::GetParamList() const * parameters. For now parameters are always added, so no special * treatment of a trailing "; " necessary. */ aSig.append(maDefArgNames[nVarArgsStart] - + "1" + + (mxFuncName == "LAMBDA" ? "2" : (mxFuncName == "MAP" ? "3" : "1")) + sep + " " + maDefArgNames[nVarArgsStart] - + "2" + + (mxFuncName == "LAMBDA" ? "3" : (mxFuncName == "MAP" ? "4" : "2")) + sep + " ... "); } else @@ -390,424 +391,433 @@ ScFunctionList::ScFunctionList( bool bEnglishFunctionNames ) // which will concept check that the list is sorted on first use to ensure this holds static const ScFuncDescCore aDescs[] = { - { SC_OPCODE_IF, ENTRY(SC_OPCODE_IF_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_WENN, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_IF_ERROR, ENTRY(SC_OPCODE_IF_ERROR_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_IFERROR, 2, { 0, 0 }, 0 }, - { SC_OPCODE_IF_NA, ENTRY(SC_OPCODE_IF_NA_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_IFNA, 2, { 0, 0 }, 0 }, - { SC_OPCODE_CHOOSE, ENTRY(SC_OPCODE_CHOOSE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_WAHL, VAR_ARGS+1, { 0, 0 }, 31 }, - { SC_OPCODE_LET, ENTRY(SC_OPCODE_LET_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_LET_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 0 }, 0 }, - { SC_OPCODE_AND, ENTRY(SC_OPCODE_AND_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_UND, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_OR, ENTRY(SC_OPCODE_OR_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_ODER, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_PI, ENTRY(SC_OPCODE_PI_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_PI, 0, { }, 0 }, - { SC_OPCODE_RANDOM, ENTRY(SC_OPCODE_RANDOM_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ZUFALLSZAHL, 0, { }, 0 }, - { SC_OPCODE_TRUE, ENTRY(SC_OPCODE_TRUE_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_WAHR, 0, { }, 0 }, - { SC_OPCODE_FALSE, ENTRY(SC_OPCODE_FALSE_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_FALSCH, 0, { }, 0 }, - { SC_OPCODE_GET_ACT_DATE, ENTRY(SC_OPCODE_GET_ACT_DATE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_HEUTE, 0, { }, 0 }, - { SC_OPCODE_GET_ACT_TIME, ENTRY(SC_OPCODE_GET_ACT_TIME_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_JETZT, 0, { }, 0 }, - { SC_OPCODE_NO_VALUE, ENTRY(SC_OPCODE_NO_VALUE_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_NV, 0, { }, 0 }, - { SC_OPCODE_CURRENT, ENTRY(SC_OPCODE_CURRENT_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_AKTUELL, 0, { }, 0 }, - { SC_OPCODE_RANDOM_NV, ENTRY(SC_OPCODE_RANDOM_NV_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RAND_NV, 0, { }, 0 }, - { SC_OPCODE_DEG, ENTRY(SC_OPCODE_DEG_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_DEG, 1, { 0 }, 0 }, - { SC_OPCODE_RAD, ENTRY(SC_OPCODE_RAD_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RAD, 1, { 0 }, 0 }, - { SC_OPCODE_SIN, ENTRY(SC_OPCODE_SIN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SIN, 1, { 0 }, 0 }, - { SC_OPCODE_COS, ENTRY(SC_OPCODE_COS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COS, 1, { 0 }, 0 }, - { SC_OPCODE_TAN, ENTRY(SC_OPCODE_TAN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_TAN, 1, { 0 }, 0 }, - { SC_OPCODE_COT, ENTRY(SC_OPCODE_COT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COT, 1, { 0 }, 0 }, - { SC_OPCODE_ARC_SIN, ENTRY(SC_OPCODE_ARC_SIN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCSIN, 1, { 0 }, 0 }, - { SC_OPCODE_ARC_COS, ENTRY(SC_OPCODE_ARC_COS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCCOS, 1, { 0 }, 0 }, - { SC_OPCODE_ARC_TAN, ENTRY(SC_OPCODE_ARC_TAN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCTAN, 1, { 0 }, 0 }, - { SC_OPCODE_ARC_COT, ENTRY(SC_OPCODE_ARC_COT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCCOT, 1, { 0 }, 0 }, - { SC_OPCODE_SIN_HYP, ENTRY(SC_OPCODE_SIN_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SINHYP, 1, { 0 }, 0 }, - { SC_OPCODE_COS_HYP, ENTRY(SC_OPCODE_COS_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COSHYP, 1, { 0 }, 0 }, - { SC_OPCODE_TAN_HYP, ENTRY(SC_OPCODE_TAN_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_TANHYP, 1, { 0 }, 0 }, - { SC_OPCODE_COT_HYP, ENTRY(SC_OPCODE_COT_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COTHYP, 1, { 0 }, 0 }, - { SC_OPCODE_ARC_SIN_HYP, ENTRY(SC_OPCODE_ARC_SIN_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARSINHYP, 1, { 0 }, 0 }, - { SC_OPCODE_ARC_COS_HYP, ENTRY(SC_OPCODE_ARC_COS_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCOSHYP, 1, { 0 }, 0 }, - { SC_OPCODE_ARC_TAN_HYP, ENTRY(SC_OPCODE_ARC_TAN_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARTANHYP, 1, { 0 }, 0 }, - { SC_OPCODE_ARC_COT_HYP, ENTRY(SC_OPCODE_ARC_COT_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCOTHYP, 1, { 0 }, 0 }, - { SC_OPCODE_COSECANT, ENTRY(SC_OPCODE_COSECANT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COSECANT, 1, { 0 }, 0 }, - { SC_OPCODE_SECANT, ENTRY(SC_OPCODE_SECANT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SECANT, 1, { 0 }, 0 }, - { SC_OPCODE_COSECANT_HYP, ENTRY(SC_OPCODE_COSECANT_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COSECANTHYP, 1, { 0 }, 0 }, - { SC_OPCODE_SECANT_HYP, ENTRY(SC_OPCODE_SECANT_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SECANTHYP, 1, { 0 }, 0 }, - { SC_OPCODE_EXP, ENTRY(SC_OPCODE_EXP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_EXP, 1, { 0 }, 0 }, - { SC_OPCODE_LN, ENTRY(SC_OPCODE_LN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_LN, 1, { 0 }, 0 }, - { SC_OPCODE_SQRT, ENTRY(SC_OPCODE_SQRT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_WURZEL, 1, { 0 }, 0 }, - { SC_OPCODE_FACT, ENTRY(SC_OPCODE_FACT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_FAKULTAET, 1, { 0 }, 0 }, - { SC_OPCODE_GET_YEAR, ENTRY(SC_OPCODE_GET_YEAR_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_JAHR, 1, { 0 }, 0 }, - { SC_OPCODE_GET_MONTH, ENTRY(SC_OPCODE_GET_MONTH_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_MONAT, 1, { 0 }, 0 }, - { SC_OPCODE_GET_DAY, ENTRY(SC_OPCODE_GET_DAY_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_TAG, 1, { 0 }, 0 }, - { SC_OPCODE_GET_HOUR, ENTRY(SC_OPCODE_GET_HOUR_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_STUNDE, 1, { 0 }, 0 }, - { SC_OPCODE_GET_MIN, ENTRY(SC_OPCODE_GET_MIN_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_MINUTE, 1, { 0 }, 0 }, - { SC_OPCODE_GET_SEC, ENTRY(SC_OPCODE_GET_SEC_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_SEKUNDE, 1, { 0 }, 0 }, - { SC_OPCODE_PLUS_MINUS, ENTRY(SC_OPCODE_PLUS_MINUS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_VORZEICHEN, 1, { 0 }, 0 }, - { SC_OPCODE_ABS, ENTRY(SC_OPCODE_ABS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ABS, 1, { 0 }, 0 }, - { SC_OPCODE_INT, ENTRY(SC_OPCODE_INT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_GANZZAHL, 1, { 0 }, 0 }, - { SC_OPCODE_PHI, ENTRY(SC_OPCODE_PHI_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PHI, 1, { 0 }, 0 }, - { SC_OPCODE_GAUSS, ENTRY(SC_OPCODE_GAUSS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAUSS, 1, { 0 }, 0 }, - { SC_OPCODE_IS_EMPTY, ENTRY(SC_OPCODE_IS_EMPTY_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTLEER, 1, { 0 }, 0 }, - { SC_OPCODE_IS_STRING, ENTRY(SC_OPCODE_IS_STRING_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTTEXT, 1, { 0 }, 0 }, - { SC_OPCODE_IS_NON_STRING, ENTRY(SC_OPCODE_IS_NON_STRING_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTKTEXT, 1, { 0 }, 0 }, - { SC_OPCODE_IS_LOGICAL, ENTRY(SC_OPCODE_IS_LOGICAL_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTLOG, 1, { 0 }, 0 }, - { SC_OPCODE_TYPE, ENTRY(SC_OPCODE_TYPE_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_TYP, 1, { 0 }, 0 }, - { SC_OPCODE_IS_REF, ENTRY(SC_OPCODE_IS_REF_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTBEZUG, 1, { 0 }, 0 }, - { SC_OPCODE_IS_VALUE, ENTRY(SC_OPCODE_IS_VALUE_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTZAHL, 1, { 0 }, 0 }, - { SC_OPCODE_IS_FORMULA, ENTRY(SC_OPCODE_IS_FORMULA_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTFORMEL, 1, { 0 }, 0 }, - { SC_OPCODE_IS_NV, ENTRY(SC_OPCODE_IS_NV_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTNV, 1, { 0 }, 0 }, - { SC_OPCODE_IS_ERR, ENTRY(SC_OPCODE_IS_ERR_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTFEHL, 1, { 0 }, 0 }, - { SC_OPCODE_IS_ERROR, ENTRY(SC_OPCODE_IS_ERROR_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTFEHLER, 1, { 0 }, 0 }, - { SC_OPCODE_IS_EVEN, ENTRY(SC_OPCODE_IS_EVEN_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTGERADE, 1, { 0 }, 0 }, - { SC_OPCODE_IS_ODD, ENTRY(SC_OPCODE_IS_ODD_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTUNGERADE, 1, { 0 }, 0 }, - { SC_OPCODE_N, ENTRY(SC_OPCODE_N_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_N, 1, { 0 }, 0 }, - { SC_OPCODE_GET_DATE_VALUE, ENTRY(SC_OPCODE_GET_DATE_VALUE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_DATWERT, 1, { 0 }, 0 }, - { SC_OPCODE_GET_TIME_VALUE, ENTRY(SC_OPCODE_GET_TIME_VALUE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_ZEITWERT, 1, { 0 }, 0 }, - { SC_OPCODE_CODE, ENTRY(SC_OPCODE_CODE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_CODE, 1, { 0 }, 0 }, - { SC_OPCODE_TRIM, ENTRY(SC_OPCODE_TRIM_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_GLAETTEN, 1, { 0 }, 0 }, - { SC_OPCODE_UPPER, ENTRY(SC_OPCODE_UPPER_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_GROSS, 1, { 0 }, 0 }, - { SC_OPCODE_PROPER, ENTRY(SC_OPCODE_PROPER_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_GROSS2, 1, { 0 }, 0 }, - { SC_OPCODE_LOWER, ENTRY(SC_OPCODE_LOWER_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_KLEIN, 1, { 0 }, 0 }, - { SC_OPCODE_LEN, ENTRY(SC_OPCODE_LEN_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_LAENGE, 1, { 0 }, 0 }, - { SC_OPCODE_T, ENTRY(SC_OPCODE_T_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_T, 1, { 0 }, 0 }, - { SC_OPCODE_VALUE, ENTRY(SC_OPCODE_VALUE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_VALUE, 1, { 0 }, 0 }, - { SC_OPCODE_CLEAN, ENTRY(SC_OPCODE_CLEAN_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_SAEUBERN, 1, { 0 }, 0 }, - { SC_OPCODE_CHAR, ENTRY(SC_OPCODE_CHAR_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ZEICHEN, 1, { 0 }, 0 }, - { SC_OPCODE_LOG10, ENTRY(SC_OPCODE_LOG10_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_LOG10, 1, { 0 }, 0 }, - { SC_OPCODE_EVEN, ENTRY(SC_OPCODE_EVEN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_GERADE, 1, { 0 }, 0 }, - { SC_OPCODE_ODD, ENTRY(SC_OPCODE_ODD_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_UNGERADE, 1, { 0 }, 0 }, - { SC_OPCODE_STD_NORM_DIST, ENTRY(SC_OPCODE_STD_NORM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STANDNORMVERT, 1, { 0 }, 0 }, - { SC_OPCODE_FISHER, ENTRY(SC_OPCODE_FISHER_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FISHER, 1, { 0 }, 0 }, - { SC_OPCODE_FISHER_INV, ENTRY(SC_OPCODE_FISHER_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FISHERINV, 1, { 0 }, 0 }, - { SC_OPCODE_S_NORM_INV, ENTRY(SC_OPCODE_S_NORM_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STANDNORMINV, 1, { 0 }, 0 }, - { SC_OPCODE_GAMMA_LN, ENTRY(SC_OPCODE_GAMMA_LN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMALN, 1, { 0 }, 0 }, - { SC_OPCODE_ERROR_TYPE, ENTRY(SC_OPCODE_ERROR_TYPE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_FEHLERTYP, 1, { 0 }, 0 }, - { SC_OPCODE_FORMULA, ENTRY(SC_OPCODE_FORMULA_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_FORMEL, 1, { 0 }, 0 }, - { SC_OPCODE_ARABIC, ENTRY(SC_OPCODE_ARABIC_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ARABISCH, 1, { 0 }, 0 }, - { SC_OPCODE_INFO, ENTRY(SC_OPCODE_INFO_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_INFO, 1, { 0 }, 0 }, - { SC_OPCODE_BAHTTEXT, ENTRY(SC_OPCODE_BAHTTEXT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_BAHTTEXT, 1, { 0 }, 0 }, - { SC_OPCODE_JIS, ENTRY(SC_OPCODE_JIS_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_JIS, 1, { 0 }, 0 }, - { SC_OPCODE_ASC, ENTRY(SC_OPCODE_ASC_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ASC, 1, { 0 }, 0 }, - { SC_OPCODE_UNICODE, ENTRY(SC_OPCODE_UNICODE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_UNICODE, 1, { 0 }, 0 }, - { SC_OPCODE_UNICHAR, ENTRY(SC_OPCODE_UNICHAR_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_UNICHAR, 1, { 0 }, 0 }, - { SC_OPCODE_GAMMA, ENTRY(SC_OPCODE_GAMMA_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMA, 1, { 0 }, 0 }, - { SC_OPCODE_GAMMA_LN_MS, ENTRY(SC_OPCODE_GAMMA_LN_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMALN_MS, 1, { 0 }, 0 }, - { SC_OPCODE_ERF_MS, ENTRY(SC_OPCODE_ERF_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ERF_MS, 1, { 0 }, 0 }, - { SC_OPCODE_ERFC_MS, ENTRY(SC_OPCODE_ERFC_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ERFC_MS, 1, { 0 }, 0 }, - { SC_OPCODE_ERROR_TYPE_ODF, ENTRY(SC_OPCODE_ERROR_TYPE_ODF_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_ERROR_TYPE_ODF, 1, { 0 }, 0 }, - { SC_OPCODE_ENCODEURL, ENTRY(SC_OPCODE_ENCODEURL_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ENCODEURL, 1, { 0 }, 0 }, - { SC_OPCODE_ISOWEEKNUM, ENTRY(SC_OPCODE_ISOWEEKNUM_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_ISOWEEKNUM, 1, { 0 }, 0 }, - { SC_OPCODE_NOT, ENTRY(SC_OPCODE_NOT_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_NICHT, 1, { 0 }, 0 }, - { SC_OPCODE_ARC_TAN_2, ENTRY(SC_OPCODE_ARC_TAN_2_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCTAN2, 2, { 0, 0 }, 0 }, - { SC_OPCODE_CEIL, ENTRY(SC_OPCODE_CEIL_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_OBERGRENZE, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_FLOOR, ENTRY(SC_OPCODE_FLOOR_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_UNTERGRENZE, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_ROUND, ENTRY(SC_OPCODE_ROUND_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RUNDEN, 2, { 0, 1 }, 0 }, - { SC_OPCODE_ROUND_UP, ENTRY(SC_OPCODE_ROUND_UP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_AUFRUNDEN, 2, { 0, 1 }, 0 }, - { SC_OPCODE_ROUND_DOWN, ENTRY(SC_OPCODE_ROUND_DOWN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ABRUNDEN, 2, { 0, 1 }, 0 }, - { SC_OPCODE_TRUNC, ENTRY(SC_OPCODE_TRUNC_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_KUERZEN, 2, { 0, 0 }, 0 }, - { SC_OPCODE_LOG, ENTRY(SC_OPCODE_LOG_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_LOG, 2, { 0, 1 }, 0 }, - { SC_OPCODE_POWER, ENTRY(SC_OPCODE_POWER_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_POTENZ, 2, { 0, 0 }, 0 }, - { SC_OPCODE_GCD, ENTRY(SC_OPCODE_GCD_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_GGT, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_LCM, ENTRY(SC_OPCODE_LCM_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_KGV, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_MOD, ENTRY(SC_OPCODE_MOD_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_REST, 2, { 0, 0 }, 0 }, - { SC_OPCODE_SUM_PRODUCT, ENTRY(SC_OPCODE_SUM_PRODUCT_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_SUMMENPRODUKT, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_SUM_SQ, ENTRY(SC_OPCODE_SUM_SQ_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_QUADRATESUMME, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_SUM_X2MY2, ENTRY(SC_OPCODE_SUM_X2MY2_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_SUMMEX2MY2, 2, { 0, 0 }, 0 }, - { SC_OPCODE_SUM_X2DY2, ENTRY(SC_OPCODE_SUM_X2DY2_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_SUMMEX2PY2, 2, { 0, 0 }, 0 }, - { SC_OPCODE_SUM_XMY2, ENTRY(SC_OPCODE_SUM_XMY2_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_SUMMEXMY2, 2, { 0, 0 }, 0 }, - { SC_OPCODE_GET_DATE, ENTRY(SC_OPCODE_GET_DATE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_DATUM, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_GET_TIME, ENTRY(SC_OPCODE_GET_TIME_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_ZEIT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_GET_DIFF_DATE, ENTRY(SC_OPCODE_GET_DIFF_DATE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_TAGE, 2, { 0, 0 }, 0 }, - { SC_OPCODE_GET_DIFF_DATE_360, ENTRY(SC_OPCODE_GET_DIFF_DATE_360_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_TAGE360, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_MIN, ENTRY(SC_OPCODE_MIN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MIN, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_MAX, ENTRY(SC_OPCODE_MAX_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MAX, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_SUM, ENTRY(SC_OPCODE_SUM_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SUMME, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_PRODUCT, ENTRY(SC_OPCODE_PRODUCT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_PRODUKT, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_AVERAGE, ENTRY(SC_OPCODE_AVERAGE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MITTELWERT, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_COUNT, ENTRY(SC_OPCODE_COUNT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ANZAHL, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_COUNT_2, ENTRY(SC_OPCODE_COUNT_2_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ANZAHL2, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_NPV, ENTRY(SC_OPCODE_NPV_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_NBW, VAR_ARGS+1, { 0, 0 }, 0 }, - { SC_OPCODE_IRR, ENTRY(SC_OPCODE_IRR_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_IKV, 2, { 0, 1 }, 0 }, - { SC_OPCODE_VAR, ENTRY(SC_OPCODE_VAR_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIANZ, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_VAR_P, ENTRY(SC_OPCODE_VAR_P_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIANZEN, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_ST_DEV, ENTRY(SC_OPCODE_ST_DEV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STABW, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_ST_DEV_P, ENTRY(SC_OPCODE_ST_DEV_P_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STABWN, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_B, ENTRY(SC_OPCODE_B_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_B, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_NORM_DIST, ENTRY(SC_OPCODE_NORM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NORMVERT, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_EXP_DIST, ENTRY(SC_OPCODE_EXP_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_EXPONVERT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_BINOM_DIST, ENTRY(SC_OPCODE_BINOM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BINOMVERT, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_POISSON_DIST, ENTRY(SC_OPCODE_POISSON_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_POISSON, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_COMBIN, ENTRY(SC_OPCODE_COMBIN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_KOMBINATIONEN, 2, { 0, 0 }, 0 }, - { SC_OPCODE_COMBIN_A, ENTRY(SC_OPCODE_COMBIN_A_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_KOMBINATIONEN2, 2, { 0, 0 }, 0 }, - { SC_OPCODE_PERMUT, ENTRY(SC_OPCODE_PERMUT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIATIONEN, 2, { 0, 0 }, 0 }, - { SC_OPCODE_PERMUTATION_A, ENTRY(SC_OPCODE_PERMUTATION_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIATIONEN2, 2, { 0, 0 }, 0 }, - { SC_OPCODE_PV, ENTRY(SC_OPCODE_PV_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_BW, 5, { 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_SYD, ENTRY(SC_OPCODE_SYD_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_DIA, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_DDB, ENTRY(SC_OPCODE_DDB_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_GDA, 5, { 0, 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_DB, ENTRY(SC_OPCODE_DB_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_GDA2, 5, { 0, 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_VBD , ENTRY(SC_OPCODE_VBD_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_VDB, 7, { 0, 0, 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_PDURATION, ENTRY(SC_OPCODE_PDURATION_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_LAUFZEIT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_SLN, ENTRY(SC_OPCODE_SLN_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_LIA, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_PMT, ENTRY(SC_OPCODE_PMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_RMZ, 5, { 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_COLUMNS, ENTRY(SC_OPCODE_COLUMNS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SPALTEN, 1, { 0 }, 0 }, - { SC_OPCODE_ROWS, ENTRY(SC_OPCODE_ROWS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_ZEILEN, 1, { 0 }, 0 }, - { SC_OPCODE_COLUMN, ENTRY(SC_OPCODE_COLUMN_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SPALTE, 1, { 1 }, 0 }, - { SC_OPCODE_ROW, ENTRY(SC_OPCODE_ROW_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_ZEILE, 1, { 1 }, 0 }, - { SC_OPCODE_RRI, ENTRY(SC_OPCODE_RRI_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZGZ, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_FV, ENTRY(SC_OPCODE_FV_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZW, 5, { 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_NPER, ENTRY(SC_OPCODE_NPER_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZZR, 5, { 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_RATE, ENTRY(SC_OPCODE_RATE_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZINS, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_IPMT, ENTRY(SC_OPCODE_IPMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZINSZ, 6, { 0, 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_PPMT, ENTRY(SC_OPCODE_PPMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_KAPZ, 6, { 0, 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_CUM_IPMT, ENTRY(SC_OPCODE_CUM_IPMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_KUMZINSZ, 6, { 0, 0, 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_CUM_PRINC, ENTRY(SC_OPCODE_CUM_PRINC_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_KUMKAPITAL, 6, { 0, 0, 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_EFFECT, ENTRY(SC_OPCODE_EFFECT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_EFFEKTIV, 2, { 0, 0 }, 0 }, - { SC_OPCODE_NOMINAL, ENTRY(SC_OPCODE_NOMINAL_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_NOMINAL, 2, { 0, 0 }, 0 }, - { SC_OPCODE_SUB_TOTAL, ENTRY(SC_OPCODE_SUB_TOTAL_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_TEILERGEBNIS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_DB_SUM, ENTRY(SC_OPCODE_DB_SUM_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBSUMME, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_DB_COUNT, ENTRY(SC_OPCODE_DB_COUNT_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBANZAHL, 3, { 0, 1, 0 }, 0 }, - { SC_OPCODE_DB_COUNT_2, ENTRY(SC_OPCODE_DB_COUNT_2_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBANZAHL2, 3, { 0, 1, 0 }, 0 }, - { SC_OPCODE_DB_AVERAGE, ENTRY(SC_OPCODE_DB_AVERAGE_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBMITTELWERT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_DB_GET, ENTRY(SC_OPCODE_DB_GET_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBAUSZUG, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_DB_MAX, ENTRY(SC_OPCODE_DB_MAX_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBMAX, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_DB_MIN, ENTRY(SC_OPCODE_DB_MIN_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBMIN, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_DB_PRODUCT, ENTRY(SC_OPCODE_DB_PRODUCT_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBPRODUKT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_DB_STD_DEV, ENTRY(SC_OPCODE_DB_STD_DEV_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBSTDABW, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_DB_STD_DEV_P, ENTRY(SC_OPCODE_DB_STD_DEV_P_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBSTDABWN, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_DB_VAR, ENTRY(SC_OPCODE_DB_VAR_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBVARIANZ, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_DB_VAR_P, ENTRY(SC_OPCODE_DB_VAR_P_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBVARIANZEN, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_INDIRECT, ENTRY(SC_OPCODE_INDIRECT_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_INDIREKT, 2, { 0, 1 }, 0 }, - { SC_OPCODE_ADDRESS, ENTRY(SC_OPCODE_ADDRESS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_ADRESSE, 5, { 0, 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_MATCH, ENTRY(SC_OPCODE_MATCH_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VERGLEICH, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_COUNT_EMPTY_CELLS, ENTRY(SC_OPCODE_COUNT_EMPTY_CELLS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ANZAHLLEEREZELLEN, 1, { 0 }, 0 }, - { SC_OPCODE_COUNT_IF, ENTRY(SC_OPCODE_COUNT_IF_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ZAEHLENWENN, 2, { 0, 0 }, 0 }, - { SC_OPCODE_SUM_IF, ENTRY(SC_OPCODE_SUM_IF_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SUMMEWENN, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_LOOKUP, ENTRY(SC_OPCODE_LOOKUP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VERWEIS, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_V_LOOKUP, ENTRY(SC_OPCODE_V_LOOKUP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SVERWEIS, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_H_LOOKUP, ENTRY(SC_OPCODE_H_LOOKUP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_WVERWEIS, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_OFFSET, ENTRY(SC_OPCODE_OFFSET_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VERSCHIEBUNG, 5, { 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_INDEX, ENTRY(SC_OPCODE_INDEX_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_INDEX, 4, { 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_AREAS, ENTRY(SC_OPCODE_AREAS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_BEREICHE, 1, { 0 }, 0 }, - { SC_OPCODE_CURRENCY, ENTRY(SC_OPCODE_CURRENCY_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_DM, 2, { 0, 1 }, 0 }, - { SC_OPCODE_REPLACE, ENTRY(SC_OPCODE_REPLACE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ERSETZEN, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_FIXED, ENTRY(SC_OPCODE_FIXED_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_FEST, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_FIND, ENTRY(SC_OPCODE_FIND_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_FINDEN, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_EXACT, ENTRY(SC_OPCODE_EXACT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_IDENTISCH, 2, { 0, 0 }, 0 }, - { SC_OPCODE_LEFT, ENTRY(SC_OPCODE_LEFT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_LINKS, 2, { 0, 1 }, 0 }, - { SC_OPCODE_RIGHT, ENTRY(SC_OPCODE_RIGHT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_RECHTS, 2, { 0, 1 }, 0 }, - { SC_OPCODE_SEARCH, ENTRY(SC_OPCODE_SEARCH_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_SUCHEN, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_MID, ENTRY(SC_OPCODE_MID_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEIL, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_TEXT, ENTRY(SC_OPCODE_TEXT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXT, 2, { 0, 0 }, 0 }, - { SC_OPCODE_SUBSTITUTE, ENTRY(SC_OPCODE_SUBSTITUTE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_WECHSELN, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_REPT, ENTRY(SC_OPCODE_REPT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_WIEDERHOLEN, 2, { 0, 0 }, 0 }, - { SC_OPCODE_CONCAT, ENTRY(SC_OPCODE_CONCAT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_VERKETTEN, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_MAT_DET, ENTRY(SC_OPCODE_MAT_DET_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MDET, 1, { 0 }, 0 }, - { SC_OPCODE_MAT_INV, ENTRY(SC_OPCODE_MAT_INV_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MINV, 1, { 0 }, 0 }, - { SC_OPCODE_MAT_MULT, ENTRY(SC_OPCODE_MAT_MULT_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MMULT, 2, { 0, 0 }, 0 }, - { SC_OPCODE_MAT_TRANS, ENTRY(SC_OPCODE_MAT_TRANS_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MTRANS, 1, { 0 }, 0 }, - { SC_OPCODE_MATRIX_UNIT, ENTRY(SC_OPCODE_MATRIX_UNIT_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_EINHEITSMATRIX, 1, { 0 }, 0 }, - { SC_OPCODE_HYP_GEOM_DIST, ENTRY(SC_OPCODE_HYP_GEOM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_HYPGEOMVERT, 5, { 0, 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_LOG_NORM_DIST, ENTRY(SC_OPCODE_LOG_NORM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_LOGNORMVERT, 4, { 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_T_DIST, ENTRY(SC_OPCODE_T_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TVERT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_F_DIST, ENTRY(SC_OPCODE_F_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FVERT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CHI_DIST, ENTRY(SC_OPCODE_CHI_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHIVERT, 2, { 0, 0 }, 0 }, - { SC_OPCODE_WEIBULL, ENTRY(SC_OPCODE_WEIBULL_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_WEIBULL, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_NEG_BINOM_VERT, ENTRY(SC_OPCODE_NEG_BINOM_VERT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NEGBINOMVERT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CRIT_BINOM, ENTRY(SC_OPCODE_CRIT_BINOM_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KRITBINOM, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_KURT, ENTRY(SC_OPCODE_KURT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KURT, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_HAR_MEAN, ENTRY(SC_OPCODE_HAR_MEAN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_HARMITTEL, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_GEO_MEAN, ENTRY(SC_OPCODE_GEO_MEAN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GEOMITTEL, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_STANDARD, ENTRY(SC_OPCODE_STANDARD_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STANDARDISIERUNG, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_AVE_DEV, ENTRY(SC_OPCODE_AVE_DEV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MITTELABW, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_SKEW, ENTRY(SC_OPCODE_SKEW_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_SCHIEFE, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_DEV_SQ, ENTRY(SC_OPCODE_DEV_SQ_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_SUMQUADABW, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_MEDIAN, ENTRY(SC_OPCODE_MEDIAN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MEDIAN, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_MODAL_VALUE, ENTRY(SC_OPCODE_MODAL_VALUE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MODALWERT, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_Z_TEST, ENTRY(SC_OPCODE_Z_TEST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GTEST, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_T_TEST, ENTRY(SC_OPCODE_T_TEST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TTEST, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_RANK, ENTRY(SC_OPCODE_RANK_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_RANG, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_PERCENTILE, ENTRY(SC_OPCODE_PERCENTILE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUANTIL, 2, { 0, 0 }, 0 }, - { SC_OPCODE_PERCENT_RANK, ENTRY(SC_OPCODE_PERCENT_RANK_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUANTILSRANG, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_LARGE, ENTRY(SC_OPCODE_LARGE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KGROESSTE, 2, { 0, 0 }, 0 }, - { SC_OPCODE_SMALL, ENTRY(SC_OPCODE_SMALL_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KKLEINSTE, 2, { 0, 0 }, 0 }, - { SC_OPCODE_FREQUENCY, ENTRY(SC_OPCODE_FREQUENCY_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_HAEUFIGKEIT, 2, { 0, 0 }, 0 }, - { SC_OPCODE_QUARTILE, ENTRY(SC_OPCODE_QUARTILE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUARTILE, 2, { 0, 0 }, 0 }, - { SC_OPCODE_NORM_INV, ENTRY(SC_OPCODE_NORM_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NORMINV, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CONFIDENCE, ENTRY(SC_OPCODE_CONFIDENCE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KONFIDENZ, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_F_TEST, ENTRY(SC_OPCODE_F_TEST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FTEST, 2, { 0, 0 }, 0 }, - { SC_OPCODE_TRIM_MEAN, ENTRY(SC_OPCODE_TRIM_MEAN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GESTUTZTMITTEL, 2, { 0, 0 }, 0 }, - { SC_OPCODE_PROB, ENTRY(SC_OPCODE_PROB_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_WAHRSCHBEREICH, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_CORREL, ENTRY(SC_OPCODE_CORREL_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KORREL, 2, { 0, 0 }, 0 }, - { SC_OPCODE_COVAR, ENTRY(SC_OPCODE_COVAR_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KOVAR, 2, { 0, 0 }, 0 }, - { SC_OPCODE_PEARSON, ENTRY(SC_OPCODE_PEARSON_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PEARSON, 2, { 0, 0 }, 0 }, - { SC_OPCODE_RSQ, ENTRY(SC_OPCODE_RSQ_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BESTIMMTHEITSMASS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_STEYX, ENTRY(SC_OPCODE_STEYX_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STFEHLERYX, 2, { 0, 0 }, 0 }, - { SC_OPCODE_SLOPE, ENTRY(SC_OPCODE_SLOPE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STEIGUNG, 2, { 0, 0 }, 0 }, - { SC_OPCODE_INTERCEPT, ENTRY(SC_OPCODE_INTERCEPT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ACHSENABSCHNITT, 2, { 0, 0 }, 0 }, - { SC_OPCODE_TREND, ENTRY(SC_OPCODE_TREND_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_TREND, 4, { 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_GROWTH, ENTRY(SC_OPCODE_GROWTH_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_VARIATION, 4, { 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_LINEST, ENTRY(SC_OPCODE_LINEST_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_RGP, 4, { 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_LOGEST, ENTRY(SC_OPCODE_LOGEST_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_RKP, 4, { 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_FORECAST, ENTRY(SC_OPCODE_FORECAST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_SCHAETZER, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CHI_INV, ENTRY(SC_OPCODE_CHI_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHIINV, 2, { 0, 0 }, 0 }, - { SC_OPCODE_GAMMA_DIST, ENTRY(SC_OPCODE_GAMMA_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMAVERT, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_GAMMA_INV, ENTRY(SC_OPCODE_GAMMA_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMAINV, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_T_INV, ENTRY(SC_OPCODE_T_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TINV, 2, { 0, 0 }, 0 }, - { SC_OPCODE_F_INV, ENTRY(SC_OPCODE_F_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FINV, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CHI_TEST, ENTRY(SC_OPCODE_CHI_TEST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHITEST, 2, { 0, 0 }, 0 }, - { SC_OPCODE_LOG_INV, ENTRY(SC_OPCODE_LOG_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_LOGINV, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_BETA_DIST, ENTRY(SC_OPCODE_BETA_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BETAVERT, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_BETA_INV, ENTRY(SC_OPCODE_BETA_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BETAINV, 5, { 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_WEEK, ENTRY(SC_OPCODE_WEEK_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_KALENDERWOCHE, 2, { 0, 1 }, 0 }, - { SC_OPCODE_GET_DAY_OF_WEEK, ENTRY(SC_OPCODE_GET_DAY_OF_WEEK_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_WOCHENTAG, 2, { 0, 1 }, 0 }, - { SC_OPCODE_STYLE, ENTRY(SC_OPCODE_STYLE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VORLAGE, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_DDE, ENTRY(SC_OPCODE_DDE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_DDE, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_BASE, ENTRY(SC_OPCODE_BASE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_BASIS, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_SHEET, ENTRY(SC_OPCODE_SHEET_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TABELLE, 1, { 1 }, 0 }, - { SC_OPCODE_SHEETS, ENTRY(SC_OPCODE_SHEETS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TABELLEN, 1, { 1 }, 0 }, - { SC_OPCODE_MIN_A, ENTRY(SC_OPCODE_MIN_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MINA, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_MAX_A, ENTRY(SC_OPCODE_MAX_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MAXA, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_AVERAGE_A, ENTRY(SC_OPCODE_AVERAGE_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MITTELWERTA, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_ST_DEV_A, ENTRY(SC_OPCODE_ST_DEV_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STABWA, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_ST_DEV_P_A, ENTRY(SC_OPCODE_ST_DEV_P_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STABWNA, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_VAR_A, ENTRY(SC_OPCODE_VAR_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIANZA, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_VAR_P_A, ENTRY(SC_OPCODE_VAR_P_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIANZENA, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_EASTERSUNDAY, ENTRY(SC_OPCODE_EASTERSUNDAY_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_OSTERSONNTAG, 1, { 0 }, 0 }, - { SC_OPCODE_DECIMAL, ENTRY(SC_OPCODE_DECIMAL_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_DEZIMAL, 2, { 0, 0 }, 0 }, - { SC_OPCODE_CONVERT_OOO, ENTRY(SC_OPCODE_CONVERT_OOO_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_UMRECHNEN, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_ROMAN, ENTRY(SC_OPCODE_ROMAN_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ROEMISCH, 2, { 0, 1 }, 0 }, - { SC_OPCODE_MIRR, ENTRY(SC_OPCODE_MIRR_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_QIKV, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CELL, ENTRY(SC_OPCODE_CELL_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ZELLE, 2, { 0, 1 }, 0 }, - { SC_OPCODE_ISPMT, ENTRY(SC_OPCODE_ISPMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ISPMT, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_HYPERLINK, ENTRY(SC_OPCODE_HYPERLINK_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_HYPERLINK, 2, { 0, 1 }, 0 }, - { SC_OPCODE_X_LOOKUP, ENTRY(SC_OPCODE_X_LOOKUP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_XLOOKUP_MS, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_X_MATCH, ENTRY(SC_OPCODE_X_MATCH_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_XMATCH_MS, 4, { 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_GET_PIVOT_DATA, ENTRY(SC_OPCODE_GET_PIVOT_DATA_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_GETPIVOTDATA, VAR_ARGS+2, { 0, 0, 1 }, 0 }, - { SC_OPCODE_EUROCONVERT, ENTRY(SC_OPCODE_EUROCONVERT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_EUROCONVERT, 5, { 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_NUMBERVALUE, ENTRY(SC_OPCODE_NUMBERVALUE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_NUMBERVALUE, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_CHISQ_DIST, ENTRY(SC_OPCODE_CHISQ_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHISQDIST, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_CHISQ_INV, ENTRY(SC_OPCODE_CHISQ_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHISQINV, 2, { 0, 0 }, 0 }, - { SC_OPCODE_BITAND, ENTRY(SC_OPCODE_BITAND_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITAND, 2, { 0, 0 }, 0 }, - { SC_OPCODE_BITOR, ENTRY(SC_OPCODE_BITOR_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITOR, 2, { 0, 0 }, 0 }, - { SC_OPCODE_BITXOR, ENTRY(SC_OPCODE_BITXOR_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITXOR, 2, { 0, 0 }, 0 }, - { SC_OPCODE_BITRSHIFT, ENTRY(SC_OPCODE_BITRSHIFT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITRSHIFT, 2, { 0, 0 }, 0 }, - { SC_OPCODE_BITLSHIFT, ENTRY(SC_OPCODE_BITLSHIFT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITLSHIFT, 2, { 0, 0 }, 0 }, - { SC_OPCODE_GET_DATEDIF, ENTRY(SC_OPCODE_GET_DATEDIF_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_DATEDIF, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_XOR, ENTRY(SC_OPCODE_XOR_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_XOR, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_AVERAGE_IF, ENTRY(SC_OPCODE_AVERAGE_IF_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_AVERAGEIF, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_SUM_IFS, ENTRY(SC_OPCODE_SUM_IFS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SUMIFS, PAIRED_VAR_ARGS+1, { 0, 0, 0 }, 0 }, - { SC_OPCODE_AVERAGE_IFS, ENTRY(SC_OPCODE_AVERAGE_IFS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_AVERAGEIFS, PAIRED_VAR_ARGS+1, { 0, 0, 0 }, 0 }, - { SC_OPCODE_COUNT_IFS, ENTRY(SC_OPCODE_COUNT_IFS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_COUNTIFS, PAIRED_VAR_ARGS, { 0, 0 }, 0 }, - { SC_OPCODE_SKEWP, ENTRY(SC_OPCODE_SKEWP_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_SKEWP, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_LENB, ENTRY(SC_OPCODE_LENB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_LENB, 1, { 0 }, 0 }, - { SC_OPCODE_RIGHTB, ENTRY(SC_OPCODE_RIGHTB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_RIGHTB, 2, { 0, 1 }, 0 }, - { SC_OPCODE_LEFTB, ENTRY(SC_OPCODE_LEFTB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_LEFTB, 2, { 0, 1 }, 0 }, - { SC_OPCODE_MIDB, ENTRY(SC_OPCODE_MIDB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_MIDB, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_FILTERXML, ENTRY(SC_OPCODE_FILTERXML_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_FILTERXML, 2, { 0, 0 }, 0 }, - { SC_OPCODE_WEBSERVICE, ENTRY(SC_OPCODE_WEBSERVICE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_WEBSERVICE, 1, { 0, 0 }, 0 }, - { SC_OPCODE_COVARIANCE_S, ENTRY(SC_OPCODE_COVARIANCE_S_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_COVARIANCE_S, 2, { 0, 0 }, 0 }, - { SC_OPCODE_COVARIANCE_P, ENTRY(SC_OPCODE_COVARIANCE_P_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_COVARIANCE_P, 2, { 0, 0 }, 0 }, - { SC_OPCODE_ST_DEV_P_MS, ENTRY(SC_OPCODE_ST_DEV_P_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ST_DEV_P_MS, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_ST_DEV_S, ENTRY(SC_OPCODE_ST_DEV_S_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ST_DEV_S, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_VAR_P_MS, ENTRY(SC_OPCODE_VAR_P_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VAR_P_MS, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_VAR_S, ENTRY(SC_OPCODE_VAR_S_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VAR_S, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_BETA_DIST_MS, ENTRY(SC_OPCODE_BETA_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BETADIST_MS, 6, { 0, 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_BETA_INV_MS, ENTRY(SC_OPCODE_BETA_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BETAINV_MS, 5, { 0, 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_BINOM_DIST_MS, ENTRY(SC_OPCODE_BINOM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BINOM_DIST_MS, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_BINOM_INV, ENTRY(SC_OPCODE_BINOM_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BINOM_INV_MS, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CHI_DIST_MS, ENTRY(SC_OPCODE_CHI_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHIVERT_MS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_CHI_INV_MS, ENTRY(SC_OPCODE_CHI_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHIINV_MS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_CHI_TEST_MS, ENTRY(SC_OPCODE_CHI_TEST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHITEST_MS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_CHISQ_DIST_MS, ENTRY(SC_OPCODE_CHISQ_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHISQDIST_MS, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CHISQ_INV_MS, ENTRY(SC_OPCODE_CHISQ_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHISQINV_MS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_CONFIDENCE_N, ENTRY(SC_OPCODE_CONFIDENCE_N_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CONFIDENCE_N, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CONFIDENCE_T, ENTRY(SC_OPCODE_CONFIDENCE_T_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CONFIDENCE_T, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_F_DIST_LT, ENTRY(SC_OPCODE_F_DIST_LT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_DIST_LT, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_F_DIST_RT, ENTRY(SC_OPCODE_F_DIST_RT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_DIST_RT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_F_INV_LT, ENTRY(SC_OPCODE_F_INV_LT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_INV_LT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_F_INV_RT, ENTRY(SC_OPCODE_F_INV_RT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_INV_RT, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_F_TEST_MS, ENTRY(SC_OPCODE_F_TEST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_TEST_MS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_EXP_DIST_MS, ENTRY(SC_OPCODE_EXP_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_EXP_DIST_MS, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_HYP_GEOM_DIST_MS, ENTRY(SC_OPCODE_HYP_GEOM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_HYP_GEOM_DIST_MS, 5, { 0, 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_POISSON_DIST_MS, ENTRY(SC_OPCODE_POISSON_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_POISSON_DIST_MS, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_WEIBULL_MS, ENTRY(SC_OPCODE_WEIBULL_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_WEIBULL_DIST_MS, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_GAMMA_DIST_MS, ENTRY(SC_OPCODE_GAMMA_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMADIST_MS, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_GAMMA_INV_MS, ENTRY(SC_OPCODE_GAMMA_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMAINV_MS, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_LOG_NORM_DIST_MS, ENTRY(SC_OPCODE_LOG_NORM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_LOGNORMDIST_MS, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_LOG_INV_MS, ENTRY(SC_OPCODE_LOG_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_LOGINV, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_NORM_DIST_MS, ENTRY(SC_OPCODE_NORM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NORMDIST_MS, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_NORM_INV_MS, ENTRY(SC_OPCODE_NORM_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NORMINV_MS, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_STD_NORM_DIST_MS, ENTRY(SC_OPCODE_STD_NORM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STD_NORMDIST_MS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_S_NORM_INV_MS, ENTRY(SC_OPCODE_S_NORM_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STD_NORMINV_MS, 1, { 0 }, 0 }, - { SC_OPCODE_T_DIST_MS, ENTRY(SC_OPCODE_T_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TDIST_MS, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_T_DIST_RT, ENTRY(SC_OPCODE_T_DIST_RT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TDIST_RT, 2, { 0, 0 }, 0 }, - { SC_OPCODE_T_DIST_2T, ENTRY(SC_OPCODE_T_DIST_2T_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TDIST_2T, 2, { 0, 0 }, 0 }, - { SC_OPCODE_T_INV_2T, ENTRY(SC_OPCODE_T_INV_2T_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TINV_2T, 2, { 0, 0 }, 0 }, - { SC_OPCODE_T_INV_MS, ENTRY(SC_OPCODE_T_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TINV_MS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_T_TEST_MS, ENTRY(SC_OPCODE_T_TEST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TTEST_MS, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_PERCENTILE_INC, ENTRY(SC_OPCODE_PERCENTILE_INC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PERCENTILE_INC, 2, { 0, 0 }, 0 }, - { SC_OPCODE_PERCENT_RANK_INC, ENTRY(SC_OPCODE_PERCENT_RANK_INC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PERCENTRANK_INC, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_QUARTILE_INC, ENTRY(SC_OPCODE_QUARTILE_INC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUARTILE_INC, 2, { 0, 0 }, 0 }, - { SC_OPCODE_RANK_EQ, ENTRY(SC_OPCODE_RANK_EQ_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_RANK_EQ, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_PERCENTILE_EXC, ENTRY(SC_OPCODE_PERCENTILE_EXC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PERCENTILE_EXC, 2, { 0, 0 }, 0 }, - { SC_OPCODE_PERCENT_RANK_EXC, ENTRY(SC_OPCODE_PERCENT_RANK_EXC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PERCENTRANK_EXC, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_QUARTILE_EXC, ENTRY(SC_OPCODE_QUARTILE_EXC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUARTILE_EXC, 2, { 0, 0 }, 0 }, - { SC_OPCODE_RANK_AVG, ENTRY(SC_OPCODE_RANK_AVG_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_RANK_AVG, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_MODAL_VALUE_MS, ENTRY(SC_OPCODE_MODAL_VALUE_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MODAL_VALUE_MS, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_MODAL_VALUE_MULTI, ENTRY(SC_OPCODE_MODAL_VALUE_MULTI_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MODAL_VALUE_MULTI, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_NEG_BINOM_DIST_MS, ENTRY(SC_OPCODE_NEG_BINOM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NEGBINOMDIST_MS, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_Z_TEST_MS, ENTRY(SC_OPCODE_Z_TEST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_Z_TEST_MS, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_CEIL_MS, ENTRY(SC_OPCODE_CEIL_MS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_CEIL_MS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_CEIL_ISO, ENTRY(SC_OPCODE_CEIL_ISO_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_CEIL_ISO, 2, { 0, 1 }, 0 }, - { SC_OPCODE_FLOOR_MS, ENTRY(SC_OPCODE_FLOOR_MS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_FLOOR_MS, 2, { 0, 0 }, 0 }, - { SC_OPCODE_NETWORKDAYS_MS, ENTRY(SC_OPCODE_NETWORKDAYS_MS_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_NETWORKDAYS_MS, 4, { 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_WORKDAY_MS, ENTRY(SC_OPCODE_WORKDAY_MS_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_WORKDAY_MS, 4, { 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_AGGREGATE, ENTRY(SC_OPCODE_AGGREGATE_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_AGGREGATE, VAR_ARGS+3, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_COLOR, ENTRY(SC_OPCODE_COLOR_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COLOR, 4, { 0, 0, 0, 1 }, 0 }, - { SC_OPCODE_CEIL_MATH, ENTRY(SC_OPCODE_CEIL_MATH_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_CEIL_MATH, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_CEIL_PRECISE, ENTRY(SC_OPCODE_CEIL_PRECISE_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_CEIL_PRECISE, 2, { 0, 1 }, 0 }, - { SC_OPCODE_NETWORKDAYS, ENTRY(SC_OPCODE_NETWORKDAYS_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_NETWORKDAYS, 4, { 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_FLOOR_MATH, ENTRY(SC_OPCODE_FLOOR_MATH_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_FLOOR_MATH, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_FLOOR_PRECISE, ENTRY(SC_OPCODE_FLOOR_PRECISE_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_FLOOR_PRECISE, 2, { 0, 1 }, 0 }, - { SC_OPCODE_RAWSUBTRACT, ENTRY(SC_OPCODE_RAWSUBTRACT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RAWSUBTRACT, VAR_ARGS+2, { 0, 0, 1 }, 0 }, - { SC_OPCODE_WEEKNUM_OOO, ENTRY(SC_OPCODE_WEEKNUM_OOO_ARY), 2, ID_FUNCTION_GRP_DATETIME, HID_FUNC_WEEKNUM_OOO, 2, { 0, 0 }, 0 }, - { SC_OPCODE_FORECAST_ETS_ADD, ENTRY(SC_OPCODE_FORECAST_ETS_ADD_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_ADD, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_FORECAST_ETS_SEA, ENTRY(SC_OPCODE_FORECAST_ETS_SEA_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_SEA, 4, { 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_FORECAST_ETS_MUL, ENTRY(SC_OPCODE_FORECAST_ETS_MUL_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_MUL, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_FORECAST_ETS_PIA, ENTRY(SC_OPCODE_FORECAST_ETS_PIA_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_PIA, 7, { 0, 0, 0, 1, 1, 1, 1 }, 0 }, - { SC_OPCODE_FORECAST_ETS_PIM, ENTRY(SC_OPCODE_FORECAST_ETS_PIM_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_PIM, 7, { 0, 0, 0, 1, 1, 1, 1 }, 0 }, - { SC_OPCODE_FORECAST_ETS_STA, ENTRY(SC_OPCODE_FORECAST_ETS_STA_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_STA, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_FORECAST_ETS_STM, ENTRY(SC_OPCODE_FORECAST_ETS_STM_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_STM, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_FORECAST_LIN, ENTRY(SC_OPCODE_FORECAST_LIN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_LIN, 3, { 0, 0, 0 }, 0 }, - { SC_OPCODE_CONCAT_MS, ENTRY(SC_OPCODE_CONCAT_MS_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_CONCAT_MS, VAR_ARGS, { 0 }, 0 }, - { SC_OPCODE_TEXTJOIN_MS, ENTRY(SC_OPCODE_TEXTJOIN_MS_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXTJOIN_MS, VAR_ARGS + 2, { 0, 0, 0 }, 0 }, - { SC_OPCODE_IFS_MS, ENTRY(SC_OPCODE_IFS_MS_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_IFS_MS, PAIRED_VAR_ARGS, { 0, 0 }, 0 }, - { SC_OPCODE_SWITCH_MS, ENTRY(SC_OPCODE_SWITCH_MS_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_SWITCH_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 0 }, 0 }, - { SC_OPCODE_MINIFS_MS, ENTRY(SC_OPCODE_MINIFS_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MINIFS_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 0 }, 0 }, - { SC_OPCODE_MAXIFS_MS, ENTRY(SC_OPCODE_MAXIFS_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MAXIFS_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 0 }, 0 }, - { SC_OPCODE_ROUNDSIG, ENTRY(SC_OPCODE_ROUNDSIG_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ROUNDSIG, 2, { 0, 0 }, 0 }, - { SC_OPCODE_REPLACEB, ENTRY(SC_OPCODE_REPLACEB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_REPLACEB, 4, { 0, 0, 0, 0 }, 0 }, - { SC_OPCODE_FINDB, ENTRY(SC_OPCODE_FINDB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_FINDB, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_SEARCHB, ENTRY(SC_OPCODE_SEARCHB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_SEARCHB, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_REGEX, ENTRY(SC_OPCODE_REGEX_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_REGEX, 4, { 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_FOURIER, ENTRY(SC_OPCODE_FOURIER_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_FOURIER, 5, { 0, 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_RANDBETWEEN_NV, ENTRY(SC_OPCODE_RANDBETWEEN_NV_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RANDBETWEEN_NV, 2, { 0, 0 }, 0 }, - { SC_OPCODE_FILTER, ENTRY(SC_OPCODE_FILTER_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_FILTER_MS, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_SORT, ENTRY(SC_OPCODE_SORT_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SORT_MS, 4, { 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_SORTBY, ENTRY(SC_OPCODE_SORTBY_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SORTBY_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 1 }, 0 }, - { SC_OPCODE_MAT_SEQUENCE, ENTRY(SC_OPCODE_MAT_SEQUENCE_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MSEQUENCE_MS, 4, { 0, 1, 1, 1 }, 0 }, - { SC_OPCODE_RANDARRAY, ENTRY(SC_OPCODE_RANDARRAY_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RANDARRAY_MS, 5, { 1, 1, 1, 1, 1 }, 0 }, - { SC_OPCODE_CHOOSECOLS, ENTRY(SC_OPCODE_CHOOSECOLS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_CHOOSECOLS_MS, VAR_ARGS + 1, { 0, 0 }, 0 }, - { SC_OPCODE_CHOOSEROWS, ENTRY(SC_OPCODE_CHOOSEROWS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_CHOOSEROWS_MS, VAR_ARGS + 1, { 0, 0 }, 0 }, - { SC_OPCODE_DROP, ENTRY(SC_OPCODE_DROP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_DROP_MS, 3, { 0, 0, 1 }, 0 }, - { SC_OPCODE_EXPAND, ENTRY(SC_OPCODE_EXPAND_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_EXPAND_MS, 4, { 0, 0, 1, 1 }, 0 }, - { SC_OPCODE_HSTACK, ENTRY(SC_OPCODE_HSTACK_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_HSTACK_MS, VAR_ARGS + 1, { 0, 0 }, 0 }, - { SC_OPCODE_VSTACK, ENTRY(SC_OPCODE_VSTACK_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VSTACK_MS, VAR_ARGS + 1, { 0, 0 }, 0 }, - { SC_OPCODE_TAKE, ENTRY(SC_OPCODE_TAKE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TAKE_MS, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_TEXTAFTER, ENTRY(SC_OPCODE_TEXTAFTER_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXTAFTER_MS, 6, { 0, 1, 1, 1, 1, 1 }, 0 }, - { SC_OPCODE_TEXTBEFORE, ENTRY(SC_OPCODE_TEXTBEFORE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXTBEFORE_MS, 6, { 0, 1, 1, 1, 1, 1 }, 0 }, - { SC_OPCODE_TEXTSPLIT, ENTRY(SC_OPCODE_TEXTSPLIT_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TEXTSPLIT_MS, 6, { 0, 1, 1, 1, 1, 1 }, 0 }, - { SC_OPCODE_TOCOL, ENTRY(SC_OPCODE_TOCOL_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TOCOL_MS, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_TOROW, ENTRY(SC_OPCODE_TOROW_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TOROW_MS, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_UNIQUE, ENTRY(SC_OPCODE_UNIQUE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_UNIQUE_MS, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_WRAPCOLS, ENTRY(SC_OPCODE_WRAPCOLS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_WRAPCOLS_MS, 3, { 0, 1, 1 }, 0 }, - { SC_OPCODE_WRAPROWS, ENTRY(SC_OPCODE_WRAPROWS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_WRAPROWS_MS, 3, { 0, 1, 1 }, 0 }, + { ocIf, ENTRY(ocIF_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_WENN, 3, { 0, 1, 1 }, 0 }, + { ocIfError, ENTRY(ocIF_ERROR_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_IFERROR, 2, { 0, 0 }, 0 }, + { ocIfNA, ENTRY(ocIF_NA_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_IFNA, 2, { 0, 0 }, 0 }, + { ocChoose, ENTRY(ocCHOOSE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_WAHL, VAR_ARGS+1, { 0, 0 }, 31 }, + { ocLet, ENTRY(ocLET_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_LET_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 0 }, 0 }, + { ocLambda, ENTRY(ocLAMBDA_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_LAMBDA_MS, VAR_ARGS + 1, { 0 }, 0 }, + { ocAnd, ENTRY(ocAND_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_UND, VAR_ARGS, { 0 }, 0 }, + { ocOr, ENTRY(ocOR_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_ODER, VAR_ARGS, { 0 }, 0 }, + { ocPi, ENTRY(ocPI_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_PI, 0, { }, 0 }, + { ocRandom, ENTRY(ocRANDOM_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ZUFALLSZAHL, 0, { }, 0 }, + { ocTrue, ENTRY(ocTRUE_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_WAHR, 0, { }, 0 }, + { ocFalse, ENTRY(ocFALSE_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_FALSCH, 0, { }, 0 }, + { ocGetActDate, ENTRY(ocGET_ACT_DATE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_HEUTE, 0, { }, 0 }, + { ocGetActTime, ENTRY(ocGET_ACT_TIME_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_JETZT, 0, { }, 0 }, + { ocNotAvail, ENTRY(ocNO_VALUE_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_NV, 0, { }, 0 }, + { ocCurrent, ENTRY(ocCURRENT_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_AKTUELL, 0, { }, 0 }, + { ocRandomNV, ENTRY(ocRANDOM_NV_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RAND_NV, 0, { }, 0 }, + { ocDeg, ENTRY(ocDEG_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_DEG, 1, { 0 }, 0 }, + { ocRad, ENTRY(ocRAD_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RAD, 1, { 0 }, 0 }, + { ocSin, ENTRY(ocSIN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SIN, 1, { 0 }, 0 }, + { ocCos, ENTRY(ocCOS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COS, 1, { 0 }, 0 }, + { ocTan, ENTRY(ocTAN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_TAN, 1, { 0 }, 0 }, + { ocCot, ENTRY(ocCOT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COT, 1, { 0 }, 0 }, + { ocArcSin, ENTRY(ocARC_SIN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCSIN, 1, { 0 }, 0 }, + { ocArcCos, ENTRY(ocARC_COS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCCOS, 1, { 0 }, 0 }, + { ocArcTan, ENTRY(ocARC_TAN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCTAN, 1, { 0 }, 0 }, + { ocArcCot, ENTRY(ocARC_COT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCCOT, 1, { 0 }, 0 }, + { ocSinHyp, ENTRY(ocSIN_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SINHYP, 1, { 0 }, 0 }, + { ocCosHyp, ENTRY(ocCOS_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COSHYP, 1, { 0 }, 0 }, + { ocTanHyp, ENTRY(ocTAN_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_TANHYP, 1, { 0 }, 0 }, + { ocCotHyp, ENTRY(ocCOT_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COTHYP, 1, { 0 }, 0 }, + { ocArcSinHyp, ENTRY(ocARC_SIN_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARSINHYP, 1, { 0 }, 0 }, + { ocArcCosHyp, ENTRY(ocARC_COS_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCOSHYP, 1, { 0 }, 0 }, + { ocArcTanHyp, ENTRY(ocARC_TAN_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARTANHYP, 1, { 0 }, 0 }, + { ocArcCotHyp, ENTRY(ocARC_COT_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCOTHYP, 1, { 0 }, 0 }, + { ocCosecant, ENTRY(ocCOSECANT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COSECANT, 1, { 0 }, 0 }, + { ocSecant, ENTRY(ocSECANT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SECANT, 1, { 0 }, 0 }, + { ocCosecantHyp, ENTRY(ocCOSECANT_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COSECANTHYP, 1, { 0 }, 0 }, + { ocSecantHyp, ENTRY(ocSECANT_HYP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SECANTHYP, 1, { 0 }, 0 }, + { ocExp, ENTRY(ocEXP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_EXP, 1, { 0 }, 0 }, + { ocLn, ENTRY(ocLN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_LN, 1, { 0 }, 0 }, + { ocSqrt, ENTRY(ocSQRT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_WURZEL, 1, { 0 }, 0 }, + { ocFact, ENTRY(ocFACT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_FAKULTAET, 1, { 0 }, 0 }, + { ocGetYear, ENTRY(ocGET_YEAR_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_JAHR, 1, { 0 }, 0 }, + { ocGetMonth, ENTRY(ocGET_MONTH_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_MONAT, 1, { 0 }, 0 }, + { ocGetDay, ENTRY(ocGET_DAY_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_TAG, 1, { 0 }, 0 }, + { ocGetHour, ENTRY(ocGET_HOUR_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_STUNDE, 1, { 0 }, 0 }, + { ocGetMin, ENTRY(ocGET_MIN_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_MINUTE, 1, { 0 }, 0 }, + { ocGetSec, ENTRY(ocGET_SEC_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_SEKUNDE, 1, { 0 }, 0 }, + { ocPlusMinus, ENTRY(ocPLUS_MINUS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_VORZEICHEN, 1, { 0 }, 0 }, + { ocAbs, ENTRY(ocABS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ABS, 1, { 0 }, 0 }, + { ocInt, ENTRY(ocINT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_GANZZAHL, 1, { 0 }, 0 }, + { ocPhi, ENTRY(ocPHI_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PHI, 1, { 0 }, 0 }, + { ocGauss, ENTRY(ocGAUSS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAUSS, 1, { 0 }, 0 }, + { ocIsEmpty, ENTRY(ocIS_EMPTY_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTLEER, 1, { 0 }, 0 }, + { ocIsString, ENTRY(ocIS_STRING_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTTEXT, 1, { 0 }, 0 }, + { ocIsNonString, ENTRY(ocIS_NON_STRING_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTKTEXT, 1, { 0 }, 0 }, + { ocIsLogical, ENTRY(ocIS_LOGICAL_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTLOG, 1, { 0 }, 0 }, + { ocType, ENTRY(ocTYPE_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_TYP, 1, { 0 }, 0 }, + { ocIsRef, ENTRY(ocIS_REF_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTBEZUG, 1, { 0 }, 0 }, + { ocIsValue, ENTRY(ocIS_VALUE_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTZAHL, 1, { 0 }, 0 }, + { ocIsFormula, ENTRY(ocIS_FORMULA_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTFORMEL, 1, { 0 }, 0 }, + { ocIsNA, ENTRY(ocIS_NV_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTNV, 1, { 0 }, 0 }, + { ocIsErr, ENTRY(ocIS_ERR_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTFEHL, 1, { 0 }, 0 }, + { ocIsError, ENTRY(ocIS_ERROR_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTFEHLER, 1, { 0 }, 0 }, + { ocIsEven, ENTRY(ocIS_EVEN_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTGERADE, 1, { 0 }, 0 }, + { ocIsOdd, ENTRY(ocIS_ODD_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ISTUNGERADE, 1, { 0 }, 0 }, + { ocN, ENTRY(ocN_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_N, 1, { 0 }, 0 }, + { ocIsOmitted, ENTRY(ocIS_OMITTED_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_IS_OMITTED_MS, 1, { 0 }, 0 }, + { ocGetDateValue, ENTRY(ocGET_DATE_VALUE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_DATWERT, 1, { 0 }, 0 }, + { ocGetTimeValue, ENTRY(ocGET_TIME_VALUE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_ZEITWERT, 1, { 0 }, 0 }, + { ocCode, ENTRY(ocCODE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_CODE, 1, { 0 }, 0 }, + { ocTrim, ENTRY(ocTRIM_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_GLAETTEN, 1, { 0 }, 0 }, + { ocUpper, ENTRY(ocUPPER_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_GROSS, 1, { 0 }, 0 }, + { ocProper, ENTRY(ocPROPER_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_GROSS2, 1, { 0 }, 0 }, + { ocLower, ENTRY(ocLOWER_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_KLEIN, 1, { 0 }, 0 }, + { ocLen, ENTRY(ocLEN_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_LAENGE, 1, { 0 }, 0 }, + { ocT, ENTRY(ocT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_T, 1, { 0 }, 0 }, + { ocValue, ENTRY(ocVALUE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_VALUE, 1, { 0 }, 0 }, + { ocClean, ENTRY(ocCLEAN_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_SAEUBERN, 1, { 0 }, 0 }, + { ocChar, ENTRY(ocCHAR_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ZEICHEN, 1, { 0 }, 0 }, + { ocLog10, ENTRY(ocLOG10_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_LOG10, 1, { 0 }, 0 }, + { ocEven, ENTRY(ocEVEN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_GERADE, 1, { 0 }, 0 }, + { ocOdd, ENTRY(ocODD_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_UNGERADE, 1, { 0 }, 0 }, + { ocStdNormDist, ENTRY(ocSTD_NORM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STANDNORMVERT, 1, { 0 }, 0 }, + { ocFisher, ENTRY(ocFISHER_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FISHER, 1, { 0 }, 0 }, + { ocFisherInv, ENTRY(ocFISHER_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FISHERINV, 1, { 0 }, 0 }, + { ocSNormInv, ENTRY(ocS_NORM_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STANDNORMINV, 1, { 0 }, 0 }, + { ocGammaLn, ENTRY(ocGAMMA_LN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMALN, 1, { 0 }, 0 }, + { ocErrorType, ENTRY(ocERROR_TYPE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_FEHLERTYP, 1, { 0 }, 0 }, + { ocFormula, ENTRY(ocFORMULA_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_FORMEL, 1, { 0 }, 0 }, + { ocArabic, ENTRY(ocARABIC_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ARABISCH, 1, { 0 }, 0 }, + { ocInfo, ENTRY(ocINFO_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_INFO, 1, { 0 }, 0 }, + { ocBahtText, ENTRY(ocBAHTTEXT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_BAHTTEXT, 1, { 0 }, 0 }, + { ocJis, ENTRY(ocJIS_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_JIS, 1, { 0 }, 0 }, + { ocAsc, ENTRY(ocASC_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ASC, 1, { 0 }, 0 }, + { ocUnicode, ENTRY(ocUNICODE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_UNICODE, 1, { 0 }, 0 }, + { ocUnichar, ENTRY(ocUNICHAR_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_UNICHAR, 1, { 0 }, 0 }, + { ocGamma, ENTRY(ocGAMMA_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMA, 1, { 0 }, 0 }, + { ocGammaLn_MS, ENTRY(ocGAMMA_LN_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMALN_MS, 1, { 0 }, 0 }, + { ocErf_MS, ENTRY(ocERF_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ERF_MS, 1, { 0 }, 0 }, + { ocErfc_MS, ENTRY(ocERFC_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ERFC_MS, 1, { 0 }, 0 }, + { ocErrorType_ODF, ENTRY(ocERROR_TYPE_ODF_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_ERROR_TYPE_ODF, 1, { 0 }, 0 }, + { ocEncodeURL, ENTRY(ocENCODEURL_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ENCODEURL, 1, { 0 }, 0 }, + { ocIsoWeeknum, ENTRY(ocISOWEEKNUM_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_ISOWEEKNUM, 1, { 0 }, 0 }, + { ocNot, ENTRY(ocNOT_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_NICHT, 1, { 0 }, 0 }, + { ocArcTan2, ENTRY(ocARC_TAN_2_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCTAN2, 2, { 0, 0 }, 0 }, + { ocCeil, ENTRY(ocCEIL_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_OBERGRENZE, 3, { 0, 1, 1 }, 0 }, + { ocFloor, ENTRY(ocFLOOR_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_UNTERGRENZE, 3, { 0, 1, 1 }, 0 }, + { ocRound, ENTRY(ocROUND_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RUNDEN, 2, { 0, 1 }, 0 }, + { ocRoundUp, ENTRY(ocROUND_UP_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_AUFRUNDEN, 2, { 0, 1 }, 0 }, + { ocRoundDown, ENTRY(ocROUND_DOWN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ABRUNDEN, 2, { 0, 1 }, 0 }, + { ocTrunc, ENTRY(ocTRUNC_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_KUERZEN, 2, { 0, 0 }, 0 }, + { ocLog, ENTRY(ocLOG_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_LOG, 2, { 0, 1 }, 0 }, + { ocPower, ENTRY(ocPOWER_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_POTENZ, 2, { 0, 0 }, 0 }, + { ocGCD, ENTRY(ocGCD_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_GGT, VAR_ARGS, { 0 }, 0 }, + { ocLCM, ENTRY(ocLCM_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_KGV, VAR_ARGS, { 0 }, 0 }, + { ocMod, ENTRY(ocMOD_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_REST, 2, { 0, 0 }, 0 }, + { ocSumProduct, ENTRY(ocSUM_PRODUCT_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_SUMMENPRODUKT, VAR_ARGS, { 0 }, 0 }, + { ocSumSQ, ENTRY(ocSUM_SQ_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_QUADRATESUMME, VAR_ARGS, { 0 }, 0 }, + { ocSumX2MY2, ENTRY(ocSUM_X2MY2_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_SUMMEX2MY2, 2, { 0, 0 }, 0 }, + { ocSumX2DY2, ENTRY(ocSUM_X2DY2_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_SUMMEX2PY2, 2, { 0, 0 }, 0 }, + { ocSumXMY2, ENTRY(ocSUM_XMY2_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_SUMMEXMY2, 2, { 0, 0 }, 0 }, + { ocGetDate, ENTRY(ocGET_DATE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_DATUM, 3, { 0, 0, 0 }, 0 }, + { ocGetTime, ENTRY(ocGET_TIME_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_ZEIT, 3, { 0, 0, 0 }, 0 }, + { ocGetDiffDate, ENTRY(ocGET_DIFF_DATE_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_TAGE, 2, { 0, 0 }, 0 }, + { ocGetDiffDate360, ENTRY(ocGET_DIFF_DATE_360_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_TAGE360, 3, { 0, 0, 1 }, 0 }, + { ocMin, ENTRY(ocMIN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MIN, VAR_ARGS, { 0 }, 0 }, + { ocMax, ENTRY(ocMAX_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MAX, VAR_ARGS, { 0 }, 0 }, + { ocSum, ENTRY(ocSUM_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SUMME, VAR_ARGS, { 0 }, 0 }, + { ocProduct, ENTRY(ocPRODUCT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_PRODUKT, VAR_ARGS, { 0 }, 0 }, + { ocAverage, ENTRY(ocAVERAGE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MITTELWERT, VAR_ARGS, { 0 }, 0 }, + { ocCount, ENTRY(ocCOUNT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ANZAHL, VAR_ARGS, { 0 }, 0 }, + { ocCount2, ENTRY(ocCOUNT_2_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ANZAHL2, VAR_ARGS, { 0 }, 0 }, + { ocNPV, ENTRY(ocNPV_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_NBW, VAR_ARGS+1, { 0, 0 }, 0 }, + { ocIRR, ENTRY(ocIRR_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_IKV, 2, { 0, 1 }, 0 }, + { ocVar, ENTRY(ocVAR_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIANZ, VAR_ARGS, { 0 }, 0 }, + { ocVarP, ENTRY(ocVAR_P_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIANZEN, VAR_ARGS, { 0 }, 0 }, + { ocStDev, ENTRY(ocST_DEV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STABW, VAR_ARGS, { 0 }, 0 }, + { ocStDevP, ENTRY(ocST_DEV_P_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STABWN, VAR_ARGS, { 0 }, 0 }, + { ocB, ENTRY(ocB_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_B, 4, { 0, 0, 0, 1 }, 0 }, + { ocNormDist, ENTRY(ocNORM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NORMVERT, 4, { 0, 0, 0, 1 }, 0 }, + { ocExpDist, ENTRY(ocEXP_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_EXPONVERT, 3, { 0, 0, 0 }, 0 }, + { ocBinomDist, ENTRY(ocBINOM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BINOMVERT, 4, { 0, 0, 0, 0 }, 0 }, + { ocPoissonDist, ENTRY(ocPOISSON_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_POISSON, 3, { 0, 0, 1 }, 0 }, + { ocCombin, ENTRY(ocCOMBIN_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_KOMBINATIONEN, 2, { 0, 0 }, 0 }, + { ocCombinA, ENTRY(ocCOMBIN_A_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_KOMBINATIONEN2, 2, { 0, 0 }, 0 }, + { ocPermut, ENTRY(ocPERMUT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIATIONEN, 2, { 0, 0 }, 0 }, + { ocPermutationA, ENTRY(ocPERMUTATION_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIATIONEN2, 2, { 0, 0 }, 0 }, + { ocPV, ENTRY(ocPV_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_BW, 5, { 0, 0, 0, 1, 1 }, 0 }, + { ocSYD, ENTRY(ocSYD_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_DIA, 4, { 0, 0, 0, 0 }, 0 }, + { ocDDB, ENTRY(ocDDB_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_GDA, 5, { 0, 0, 0, 0, 1 }, 0 }, + { ocDB, ENTRY(ocDB_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_GDA2, 5, { 0, 0, 0, 0, 1 }, 0 }, + { ocVBD , ENTRY(ocVBD_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_VDB, 7, { 0, 0, 0, 0, 0, 1, 1 }, 0 }, + { ocPDuration, ENTRY(ocPDURATION_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_LAUFZEIT, 3, { 0, 0, 0 }, 0 }, + { ocSLN, ENTRY(ocSLN_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_LIA, 3, { 0, 0, 0 }, 0 }, + { ocPMT, ENTRY(ocPMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_RMZ, 5, { 0, 0, 0, 1, 1 }, 0 }, + { ocColumns, ENTRY(ocCOLUMNS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SPALTEN, 1, { 0 }, 0 }, + { ocRows, ENTRY(ocROWS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_ZEILEN, 1, { 0 }, 0 }, + { ocColumn, ENTRY(ocCOLUMN_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SPALTE, 1, { 1 }, 0 }, + { ocRow, ENTRY(ocROW_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_ZEILE, 1, { 1 }, 0 }, + { ocRRI, ENTRY(ocRRI_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZGZ, 3, { 0, 0, 0 }, 0 }, + { ocFV, ENTRY(ocFV_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZW, 5, { 0, 0, 0, 1, 1 }, 0 }, + { ocNper, ENTRY(ocNPER_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZZR, 5, { 0, 0, 0, 1, 1 }, 0 }, + { ocRate, ENTRY(ocRATE_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZINS, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, + { ocIpmt, ENTRY(ocIPMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ZINSZ, 6, { 0, 0, 0, 0, 1, 1 }, 0 }, + { ocPpmt, ENTRY(ocPPMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_KAPZ, 6, { 0, 0, 0, 0, 1, 1 }, 0 }, + { ocCumIpmt, ENTRY(ocCUM_IPMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_KUMZINSZ, 6, { 0, 0, 0, 0, 0, 0 }, 0 }, + { ocCumPrinc, ENTRY(ocCUM_PRINC_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_KUMKAPITAL, 6, { 0, 0, 0, 0, 0, 0 }, 0 }, + { ocEffect, ENTRY(ocEFFECT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_EFFEKTIV, 2, { 0, 0 }, 0 }, + { ocNominal, ENTRY(ocNOMINAL_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_NOMINAL, 2, { 0, 0 }, 0 }, + { ocSubTotal, ENTRY(ocSUB_TOTAL_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_TEILERGEBNIS, 2, { 0, 0 }, 0 }, + { ocDBSum, ENTRY(ocDB_SUM_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBSUMME, 3, { 0, 0, 0 }, 0 }, + { ocDBCount, ENTRY(ocDB_COUNT_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBANZAHL, 3, { 0, 1, 0 }, 0 }, + { ocDBCount2, ENTRY(ocDB_COUNT_2_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBANZAHL2, 3, { 0, 1, 0 }, 0 }, + { ocDBAverage, ENTRY(ocDB_AVERAGE_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBMITTELWERT, 3, { 0, 0, 0 }, 0 }, + { ocDBGet, ENTRY(ocDB_GET_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBAUSZUG, 3, { 0, 0, 0 }, 0 }, + { ocDBMax, ENTRY(ocDB_MAX_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBMAX, 3, { 0, 0, 0 }, 0 }, + { ocDBMin, ENTRY(ocDB_MIN_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBMIN, 3, { 0, 0, 0 }, 0 }, + { ocDBProduct, ENTRY(ocDB_PRODUCT_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBPRODUKT, 3, { 0, 0, 0 }, 0 }, + { ocDBStdDev, ENTRY(ocDB_STD_DEV_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBSTDABW, 3, { 0, 0, 0 }, 0 }, + { ocDBStdDevP, ENTRY(ocDB_STD_DEV_P_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBSTDABWN, 3, { 0, 0, 0 }, 0 }, + { ocDBVar, ENTRY(ocDB_VAR_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBVARIANZ, 3, { 0, 0, 0 }, 0 }, + { ocDBVarP, ENTRY(ocDB_VAR_P_ARY), 0, ID_FUNCTION_GRP_DATABASE, HID_FUNC_DBVARIANZEN, 3, { 0, 0, 0 }, 0 }, + { ocIndirect, ENTRY(ocINDIRECT_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_INDIREKT, 2, { 0, 1 }, 0 }, + { ocAddress, ENTRY(ocADDRESS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_ADRESSE, 5, { 0, 0, 1, 1, 1 }, 0 }, + { ocMatch, ENTRY(ocMATCH_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VERGLEICH, 3, { 0, 0, 1 }, 0 }, + { ocCountEmptyCells, ENTRY(ocCOUNT_EMPTY_CELLS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ANZAHLLEEREZELLEN, 1, { 0 }, 0 }, + { ocCountIf, ENTRY(ocCOUNT_IF_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ZAEHLENWENN, 2, { 0, 0 }, 0 }, + { ocSumIf, ENTRY(ocSUM_IF_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SUMMEWENN, 3, { 0, 0, 1 }, 0 }, + { ocLookup, ENTRY(ocLOOKUP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VERWEIS, 3, { 0, 0, 1 }, 0 }, + { ocVLookup, ENTRY(ocV_LOOKUP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SVERWEIS, 4, { 0, 0, 0, 1 }, 0 }, + { ocHLookup, ENTRY(ocH_LOOKUP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_WVERWEIS, 4, { 0, 0, 0, 1 }, 0 }, + { ocOffset, ENTRY(ocOFFSET_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VERSCHIEBUNG, 5, { 0, 0, 0, 1, 1 }, 0 }, + { ocIndex, ENTRY(ocINDEX_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_INDEX, 4, { 0, 1, 1, 1 }, 0 }, + { ocAreas, ENTRY(ocAREAS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_BEREICHE, 1, { 0 }, 0 }, + { ocCurrency, ENTRY(ocCURRENCY_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_DM, 2, { 0, 1 }, 0 }, + { ocReplace, ENTRY(ocREPLACE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ERSETZEN, 4, { 0, 0, 0, 0 }, 0 }, + { ocFixed, ENTRY(ocFIXED_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_FEST, 3, { 0, 1, 1 }, 0 }, + { ocFind, ENTRY(ocFIND_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_FINDEN, 3, { 0, 0, 1 }, 0 }, + { ocExact, ENTRY(ocEXACT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_IDENTISCH, 2, { 0, 0 }, 0 }, + { ocLeft, ENTRY(ocLEFT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_LINKS, 2, { 0, 1 }, 0 }, + { ocRight, ENTRY(ocRIGHT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_RECHTS, 2, { 0, 1 }, 0 }, + { ocSearch, ENTRY(ocSEARCH_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_SUCHEN, 3, { 0, 0, 1 }, 0 }, + { ocMid, ENTRY(ocMID_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEIL, 3, { 0, 0, 0 }, 0 }, + { ocText, ENTRY(ocTEXT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXT, 2, { 0, 0 }, 0 }, + { ocSubstitute, ENTRY(ocSUBSTITUTE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_WECHSELN, 4, { 0, 0, 0, 1 }, 0 }, + { ocRept, ENTRY(ocREPT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_WIEDERHOLEN, 2, { 0, 0 }, 0 }, + { ocConcat, ENTRY(ocCONCAT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_VERKETTEN, VAR_ARGS, { 0 }, 0 }, + { ocMatDet, ENTRY(ocMAT_DET_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MDET, 1, { 0 }, 0 }, + { ocMatInv, ENTRY(ocMAT_INV_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MINV, 1, { 0 }, 0 }, + { ocMatMult, ENTRY(ocMAT_MULT_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MMULT, 2, { 0, 0 }, 0 }, + { ocMatTrans, ENTRY(ocMAT_TRANS_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MTRANS, 1, { 0 }, 0 }, + { ocMatrixUnit, ENTRY(ocMATRIX_UNIT_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_EINHEITSMATRIX, 1, { 0 }, 0 }, + { ocHypGeomDist, ENTRY(ocHYP_GEOM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_HYPGEOMVERT, 5, { 0, 0, 0, 0, 1 }, 0 }, + { ocLogNormDist, ENTRY(ocLOG_NORM_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_LOGNORMVERT, 4, { 0, 1, 1, 1 }, 0 }, + { ocTDist, ENTRY(ocT_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TVERT, 3, { 0, 0, 0 }, 0 }, + { ocFDist, ENTRY(ocF_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FVERT, 3, { 0, 0, 0 }, 0 }, + { ocChiDist, ENTRY(ocCHI_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHIVERT, 2, { 0, 0 }, 0 }, + { ocWeibull, ENTRY(ocWEIBULL_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_WEIBULL, 4, { 0, 0, 0, 0 }, 0 }, + { ocNegBinomVert, ENTRY(ocNEG_BINOM_VERT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NEGBINOMVERT, 3, { 0, 0, 0 }, 0 }, + { ocCritBinom, ENTRY(ocCRIT_BINOM_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KRITBINOM, 3, { 0, 0, 0 }, 0 }, + { ocKurt, ENTRY(ocKURT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KURT, VAR_ARGS, { 0 }, 0 }, + { ocHarMean, ENTRY(ocHAR_MEAN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_HARMITTEL, VAR_ARGS, { 0 }, 0 }, + { ocGeoMean, ENTRY(ocGEO_MEAN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GEOMITTEL, VAR_ARGS, { 0 }, 0 }, + { ocStandard, ENTRY(ocSTANDARD_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STANDARDISIERUNG, 3, { 0, 0, 0 }, 0 }, + { ocAveDev, ENTRY(ocAVE_DEV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MITTELABW, VAR_ARGS, { 0 }, 0 }, + { ocSkew, ENTRY(ocSKEW_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_SCHIEFE, VAR_ARGS, { 0 }, 0 }, + { ocDevSq, ENTRY(ocDEV_SQ_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_SUMQUADABW, VAR_ARGS, { 0 }, 0 }, + { ocMedian, ENTRY(ocMEDIAN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MEDIAN, VAR_ARGS, { 0 }, 0 }, + { ocModalValue, ENTRY(ocMODAL_VALUE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MODALWERT, VAR_ARGS, { 0 }, 0 }, + { ocZTest, ENTRY(ocZ_TEST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GTEST, 3, { 0, 0, 1 }, 0 }, + { ocTTest, ENTRY(ocT_TEST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TTEST, 4, { 0, 0, 0, 0 }, 0 }, + { ocRank, ENTRY(ocRANK_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_RANG, 3, { 0, 0, 1 }, 0 }, + { ocPercentile, ENTRY(ocPERCENTILE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUANTIL, 2, { 0, 0 }, 0 }, + { ocPercentrank, ENTRY(ocPERCENT_RANK_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUANTILSRANG, 3, { 0, 0, 1 }, 0 }, + { ocLarge, ENTRY(ocLARGE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KGROESSTE, 2, { 0, 0 }, 0 }, + { ocSmall, ENTRY(ocSMALL_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KKLEINSTE, 2, { 0, 0 }, 0 }, + { ocFrequency, ENTRY(ocFREQUENCY_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_HAEUFIGKEIT, 2, { 0, 0 }, 0 }, + { ocQuartile, ENTRY(ocQUARTILE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUARTILE, 2, { 0, 0 }, 0 }, + { ocNormInv, ENTRY(ocNORM_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NORMINV, 3, { 0, 0, 0 }, 0 }, + { ocConfidence, ENTRY(ocCONFIDENCE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KONFIDENZ, 3, { 0, 0, 0 }, 0 }, + { ocFTest, ENTRY(ocF_TEST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FTEST, 2, { 0, 0 }, 0 }, + { ocTrimMean, ENTRY(ocTRIM_MEAN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GESTUTZTMITTEL, 2, { 0, 0 }, 0 }, + { ocProb, ENTRY(ocPROB_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_WAHRSCHBEREICH, 4, { 0, 0, 0, 1 }, 0 }, + { ocCorrel, ENTRY(ocCORREL_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KORREL, 2, { 0, 0 }, 0 }, + { ocCovar, ENTRY(ocCOVAR_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_KOVAR, 2, { 0, 0 }, 0 }, + { ocPearson, ENTRY(ocPEARSON_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PEARSON, 2, { 0, 0 }, 0 }, + { ocRSQ, ENTRY(ocRSQ_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BESTIMMTHEITSMASS, 2, { 0, 0 }, 0 }, + { ocSTEYX, ENTRY(ocSTEYX_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STFEHLERYX, 2, { 0, 0 }, 0 }, + { ocSlope, ENTRY(ocSLOPE_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STEIGUNG, 2, { 0, 0 }, 0 }, + { ocIntercept, ENTRY(ocINTERCEPT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ACHSENABSCHNITT, 2, { 0, 0 }, 0 }, + { ocTrend, ENTRY(ocTREND_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_TREND, 4, { 0, 1, 1, 1 }, 0 }, + { ocGrowth, ENTRY(ocGROWTH_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_VARIATION, 4, { 0, 1, 1, 1 }, 0 }, + { ocLinest, ENTRY(ocLINEST_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_RGP, 4, { 0, 1, 1, 1 }, 0 }, + { ocLogest, ENTRY(ocLOGEST_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_RKP, 4, { 0, 1, 1, 1 }, 0 }, + { ocForecast, ENTRY(ocFORECAST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_SCHAETZER, 3, { 0, 0, 0 }, 0 }, + { ocChiInv, ENTRY(ocCHI_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHIINV, 2, { 0, 0 }, 0 }, + { ocGammaDist, ENTRY(ocGAMMA_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMAVERT, 4, { 0, 0, 0, 1 }, 0 }, + { ocGammaInv, ENTRY(ocGAMMA_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMAINV, 3, { 0, 0, 0 }, 0 }, + { ocTInv, ENTRY(ocT_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TINV, 2, { 0, 0 }, 0 }, + { ocFInv, ENTRY(ocF_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FINV, 3, { 0, 0, 0 }, 0 }, + { ocChiTest, ENTRY(ocCHI_TEST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHITEST, 2, { 0, 0 }, 0 }, + { ocLogInv, ENTRY(ocLOG_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_LOGINV, 3, { 0, 1, 1 }, 0 }, + { ocBetaDist, ENTRY(ocBETA_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BETAVERT, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, + { ocBetaInv, ENTRY(ocBETA_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BETAINV, 5, { 0, 0, 0, 1, 1 }, 0 }, + { ocWeek, ENTRY(ocWEEK_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_KALENDERWOCHE, 2, { 0, 1 }, 0 }, + { ocGetDayOfWeek, ENTRY(ocGET_DAY_OF_WEEK_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_WOCHENTAG, 2, { 0, 1 }, 0 }, + { ocStyle, ENTRY(ocSTYLE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VORLAGE, 3, { 0, 1, 1 }, 0 }, + { ocDde, ENTRY(ocDDE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_DDE, 4, { 0, 0, 0, 1 }, 0 }, + { ocBase, ENTRY(ocBASE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_BASIS, 3, { 0, 0, 1 }, 0 }, + { ocSheet, ENTRY(ocSHEET_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TABELLE, 1, { 1 }, 0 }, + { ocSheets, ENTRY(ocSHEETS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TABELLEN, 1, { 1 }, 0 }, + { ocMinA, ENTRY(ocMIN_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MINA, VAR_ARGS, { 0 }, 0 }, + { ocMaxA, ENTRY(ocMAX_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MAXA, VAR_ARGS, { 0 }, 0 }, + { ocAverageA, ENTRY(ocAVERAGE_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MITTELWERTA, VAR_ARGS, { 0 }, 0 }, + { ocStDevA, ENTRY(ocST_DEV_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STABWA, VAR_ARGS, { 0 }, 0 }, + { ocStDevPA, ENTRY(ocST_DEV_P_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STABWNA, VAR_ARGS, { 0 }, 0 }, + { ocVarA, ENTRY(ocVAR_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIANZA, VAR_ARGS, { 0 }, 0 }, + { ocVarPA, ENTRY(ocVAR_P_A_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VARIANZENA, VAR_ARGS, { 0 }, 0 }, + { ocEasterSunday, ENTRY(ocEASTERSUNDAY_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_OSTERSONNTAG, 1, { 0 }, 0 }, + { ocDecimal, ENTRY(ocDECIMAL_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_DEZIMAL, 2, { 0, 0 }, 0 }, + { ocConvertOOo, ENTRY(ocCONVERT_OOO_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_UMRECHNEN, 3, { 0, 0, 0 }, 0 }, + { ocRoman, ENTRY(ocROMAN_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ROEMISCH, 2, { 0, 1 }, 0 }, + { ocMIRR, ENTRY(ocMIRR_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_QIKV, 3, { 0, 0, 0 }, 0 }, + { ocCell, ENTRY(ocCELL_ARY), 0, ID_FUNCTION_GRP_INFO, HID_FUNC_ZELLE, 2, { 0, 1 }, 0 }, + { ocISPMT, ENTRY(ocISPMT_ARY), 0, ID_FUNCTION_GRP_FINANCIAL, HID_FUNC_ISPMT, 4, { 0, 0, 0, 0 }, 0 }, + { ocHyperLink, ENTRY(ocHYPERLINK_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_HYPERLINK, 2, { 0, 1 }, 0 }, + { ocXLookup, ENTRY(ocX_LOOKUP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_XLOOKUP_MS, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, + { ocXMatch, ENTRY(ocX_MATCH_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_XMATCH_MS, 4, { 0, 0, 1, 1 }, 0 }, + { ocGetPivotData, ENTRY(ocGET_PIVOT_DATA_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_GETPIVOTDATA, VAR_ARGS+2, { 0, 0, 1 }, 0 }, + { ocEuroConvert, ENTRY(ocEUROCONVERT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_EUROCONVERT, 5, { 0, 0, 0, 1, 1 }, 0 }, + { ocNumberValue, ENTRY(ocNUMBERVALUE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_NUMBERVALUE, 3, { 0, 1, 1 }, 0 }, + { ocChiSqDist, ENTRY(ocCHISQ_DIST_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHISQDIST, 3, { 0, 0, 1 }, 0 }, + { ocChiSqInv, ENTRY(ocCHISQ_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHISQINV, 2, { 0, 0 }, 0 }, + { ocBitAnd, ENTRY(ocBITAND_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITAND, 2, { 0, 0 }, 0 }, + { ocBitOr, ENTRY(ocBITOR_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITOR, 2, { 0, 0 }, 0 }, + { ocBitXor, ENTRY(ocBITXOR_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITXOR, 2, { 0, 0 }, 0 }, + { ocBitRshift, ENTRY(ocBITRSHIFT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITRSHIFT, 2, { 0, 0 }, 0 }, + { ocBitLshift, ENTRY(ocBITLSHIFT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_BITLSHIFT, 2, { 0, 0 }, 0 }, + { ocGetDateDif, ENTRY(ocGET_DATEDIF_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_DATEDIF, 3, { 0, 0, 0 }, 0 }, + { ocXor, ENTRY(ocXOR_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_XOR, VAR_ARGS, { 0 }, 0 }, + { ocAverageIf, ENTRY(ocAVERAGE_IF_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_AVERAGEIF, 3, { 0, 0, 1 }, 0 }, + { ocSumIfs, ENTRY(ocSUM_IFS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_SUMIFS, PAIRED_VAR_ARGS+1, { 0, 0, 0 }, 0 }, + { ocAverageIfs, ENTRY(ocAVERAGE_IFS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_AVERAGEIFS, PAIRED_VAR_ARGS+1, { 0, 0, 0 }, 0 }, + { ocCountIfs, ENTRY(ocCOUNT_IFS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_COUNTIFS, PAIRED_VAR_ARGS, { 0, 0 }, 0 }, + { ocSkewp, ENTRY(ocSKEWP_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_SKEWP, VAR_ARGS, { 0 }, 0 }, + { ocLenB, ENTRY(ocLENB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_LENB, 1, { 0 }, 0 }, + { ocRightB, ENTRY(ocRIGHTB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_RIGHTB, 2, { 0, 1 }, 0 }, + { ocLeftB, ENTRY(ocLEFTB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_LEFTB, 2, { 0, 1 }, 0 }, + { ocMidB, ENTRY(ocMIDB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_MIDB, 3, { 0, 0, 0 }, 0 }, + { ocFilterXML, ENTRY(ocFILTERXML_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_FILTERXML, 2, { 0, 0 }, 0 }, + { ocWebservice, ENTRY(ocWEBSERVICE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_WEBSERVICE, 1, { 0, 0 }, 0 }, + { ocCovarianceS, ENTRY(ocCOVARIANCE_S_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_COVARIANCE_S, 2, { 0, 0 }, 0 }, + { ocCovarianceP, ENTRY(ocCOVARIANCE_P_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_COVARIANCE_P, 2, { 0, 0 }, 0 }, + { ocStDevP_MS, ENTRY(ocST_DEV_P_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ST_DEV_P_MS, VAR_ARGS, { 0 }, 0 }, + { ocStDevS, ENTRY(ocST_DEV_S_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_ST_DEV_S, VAR_ARGS, { 0 }, 0 }, + { ocVarP_MS, ENTRY(ocVAR_P_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VAR_P_MS, VAR_ARGS, { 0 }, 0 }, + { ocVarS, ENTRY(ocVAR_S_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_VAR_S, VAR_ARGS, { 0 }, 0 }, + { ocBetaDist_MS, ENTRY(ocBETA_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BETADIST_MS, 6, { 0, 0, 0, 0, 1, 1 }, 0 }, + { ocBetaInv_MS, ENTRY(ocBETA_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BETAINV_MS, 5, { 0, 0, 0, 1, 1 }, 0 }, + { ocBinomDist_MS, ENTRY(ocBINOM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BINOM_DIST_MS, 4, { 0, 0, 0, 0 }, 0 }, + { ocBinomInv, ENTRY(ocBINOM_INV_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_BINOM_INV_MS, 3, { 0, 0, 0 }, 0 }, + { ocChiDist_MS, ENTRY(ocCHI_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHIVERT_MS, 2, { 0, 0 }, 0 }, + { ocChiInv_MS, ENTRY(ocCHI_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHIINV_MS, 2, { 0, 0 }, 0 }, + { ocChiTest_MS, ENTRY(ocCHI_TEST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHITEST_MS, 2, { 0, 0 }, 0 }, + { ocChiSqDist_MS, ENTRY(ocCHISQ_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHISQDIST_MS, 3, { 0, 0, 0 }, 0 }, + { ocChiSqInv_MS, ENTRY(ocCHISQ_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CHISQINV_MS, 2, { 0, 0 }, 0 }, + { ocConfidence_N, ENTRY(ocCONFIDENCE_N_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CONFIDENCE_N, 3, { 0, 0, 0 }, 0 }, + { ocConfidence_T, ENTRY(ocCONFIDENCE_T_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_CONFIDENCE_T, 3, { 0, 0, 0 }, 0 }, + { ocFDist_LT, ENTRY(ocF_DIST_LT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_DIST_LT, 4, { 0, 0, 0, 1 }, 0 }, + { ocFDist_RT, ENTRY(ocF_DIST_RT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_DIST_RT, 3, { 0, 0, 0 }, 0 }, + { ocFInv_LT, ENTRY(ocF_INV_LT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_INV_LT, 3, { 0, 0, 0 }, 0 }, + { ocFInv_RT, ENTRY(ocF_INV_RT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_INV_RT, 3, { 0, 0, 0 }, 0 }, + { ocFTest_MS, ENTRY(ocF_TEST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_F_TEST_MS, 2, { 0, 0 }, 0 }, + { ocExpDist_MS, ENTRY(ocEXP_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_EXP_DIST_MS, 3, { 0, 0, 0 }, 0 }, + { ocHypGeomDist_MS, ENTRY(ocHYP_GEOM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_HYP_GEOM_DIST_MS, 5, { 0, 0, 0, 0, 0 }, 0 }, + { ocPoissonDist_MS, ENTRY(ocPOISSON_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_POISSON_DIST_MS, 3, { 0, 0, 0 }, 0 }, + { ocWeibull_MS, ENTRY(ocWEIBULL_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_WEIBULL_DIST_MS, 4, { 0, 0, 0, 0 }, 0 }, + { ocGammaDist_MS, ENTRY(ocGAMMA_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMADIST_MS, 4, { 0, 0, 0, 0 }, 0 }, + { ocGammaInv_MS, ENTRY(ocGAMMA_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_GAMMAINV_MS, 3, { 0, 0, 0 }, 0 }, + { ocLogNormDist_MS, ENTRY(ocLOG_NORM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_LOGNORMDIST_MS, 4, { 0, 0, 0, 0 }, 0 }, + { ocLogInv_MS, ENTRY(ocLOG_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_LOGINV, 3, { 0, 0, 0 }, 0 }, + { ocNormDist_MS, ENTRY(ocNORM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NORMDIST_MS, 4, { 0, 0, 0, 0 }, 0 }, + { ocNormInv_MS, ENTRY(ocNORM_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NORMINV_MS, 3, { 0, 0, 0 }, 0 }, + { ocStdNormDist_MS, ENTRY(ocSTD_NORM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STD_NORMDIST_MS, 2, { 0, 0 }, 0 }, + { ocSNormInv_MS, ENTRY(ocS_NORM_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_STD_NORMINV_MS, 1, { 0 }, 0 }, + { ocTDist_MS, ENTRY(ocT_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TDIST_MS, 3, { 0, 0, 0 }, 0 }, + { ocTDist_RT, ENTRY(ocT_DIST_RT_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TDIST_RT, 2, { 0, 0 }, 0 }, + { ocTDist_2T, ENTRY(ocT_DIST_2T_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TDIST_2T, 2, { 0, 0 }, 0 }, + { ocTInv_2T, ENTRY(ocT_INV_2T_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TINV_2T, 2, { 0, 0 }, 0 }, + { ocTInv_MS, ENTRY(ocT_INV_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TINV_MS, 2, { 0, 0 }, 0 }, + { ocTTest_MS, ENTRY(ocT_TEST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_TTEST_MS, 4, { 0, 0, 0, 0 }, 0 }, + { ocPercentile_Inc, ENTRY(ocPERCENTILE_INC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PERCENTILE_INC, 2, { 0, 0 }, 0 }, + { ocPercentrank_Inc, ENTRY(ocPERCENT_RANK_INC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PERCENTRANK_INC, 3, { 0, 0, 1 }, 0 }, + { ocQuartile_Inc, ENTRY(ocQUARTILE_INC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUARTILE_INC, 2, { 0, 0 }, 0 }, + { ocRank_Eq, ENTRY(ocRANK_EQ_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_RANK_EQ, 3, { 0, 0, 1 }, 0 }, + { ocPercentile_Exc, ENTRY(ocPERCENTILE_EXC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PERCENTILE_EXC, 2, { 0, 0 }, 0 }, + { ocPercentrank_Exc, ENTRY(ocPERCENT_RANK_EXC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_PERCENTRANK_EXC, 3, { 0, 0, 1 }, 0 }, + { ocQuartile_Exc, ENTRY(ocQUARTILE_EXC_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_QUARTILE_EXC, 2, { 0, 0 }, 0 }, + { ocRank_Avg, ENTRY(ocRANK_AVG_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_RANK_AVG, 3, { 0, 0, 1 }, 0 }, + { ocModalValue_MS, ENTRY(ocMODAL_VALUE_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MODAL_VALUE_MS, VAR_ARGS, { 0 }, 0 }, + { ocModalValue_Multi, ENTRY(ocMODAL_VALUE_MULTI_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MODAL_VALUE_MULTI, VAR_ARGS, { 0 }, 0 }, + { ocNegBinomDist_MS, ENTRY(ocNEG_BINOM_DIST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_NEGBINOMDIST_MS, 4, { 0, 0, 0, 0 }, 0 }, + { ocZTest_MS, ENTRY(ocZ_TEST_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_Z_TEST_MS, 3, { 0, 0, 1 }, 0 }, + { ocCeil_MS, ENTRY(ocCEIL_MS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_CEIL_MS, 2, { 0, 0 }, 0 }, + { ocCeil_ISO, ENTRY(ocCEIL_ISO_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_CEIL_ISO, 2, { 0, 1 }, 0 }, + { ocFloor_MS, ENTRY(ocFLOOR_MS_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_FLOOR_MS, 2, { 0, 0 }, 0 }, + { ocNetWorkdays_MS, ENTRY(ocNETWORKDAYS_MS_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_NETWORKDAYS_MS, 4, { 0, 0, 1, 1 }, 0 }, + { ocWorkday_MS, ENTRY(ocWORKDAY_MS_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_WORKDAY_MS, 4, { 0, 0, 1, 1 }, 0 }, + { ocAggregate, ENTRY(ocAGGREGATE_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_AGGREGATE, VAR_ARGS+3, { 0, 0, 0, 1 }, 0 }, + { ocColor, ENTRY(ocCOLOR_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_COLOR, 4, { 0, 0, 0, 1 }, 0 }, + { ocCeil_Math, ENTRY(ocCEIL_MATH_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_CEIL_MATH, 3, { 0, 1, 1 }, 0 }, + { ocCeil_Precise, ENTRY(ocCEIL_PRECISE_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_CEIL_PRECISE, 2, { 0, 1 }, 0 }, + { ocNetWorkdays, ENTRY(ocNETWORKDAYS_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_NETWORKDAYS, 4, { 0, 0, 1, 1 }, 0 }, + { ocFloor_Math, ENTRY(ocFLOOR_MATH_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_FLOOR_MATH, 3, { 0, 1, 1 }, 0 }, + { ocFloor_Precise, ENTRY(ocFLOOR_PRECISE_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_FLOOR_PRECISE, 2, { 0, 1 }, 0 }, + { ocRawSubtract, ENTRY(ocRAWSUBTRACT_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RAWSUBTRACT, VAR_ARGS+2, { 0, 0, 1 }, 0 }, + { ocWeeknumOOo, ENTRY(ocWEEKNUM_OOO_ARY), 2, ID_FUNCTION_GRP_DATETIME, HID_FUNC_WEEKNUM_OOO, 2, { 0, 0 }, 0 }, + { ocForecast_ETS_ADD, ENTRY(ocFORECAST_ETS_ADD_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_ADD, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, + { ocForecast_ETS_SEA, ENTRY(ocFORECAST_ETS_SEA_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_SEA, 4, { 0, 0, 1, 1 }, 0 }, + { ocForecast_ETS_MUL, ENTRY(ocFORECAST_ETS_MUL_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_MUL, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, + { ocForecast_ETS_PIA, ENTRY(ocFORECAST_ETS_PIA_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_PIA, 7, { 0, 0, 0, 1, 1, 1, 1 }, 0 }, + { ocForecast_ETS_PIM, ENTRY(ocFORECAST_ETS_PIM_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_PIM, 7, { 0, 0, 0, 1, 1, 1, 1 }, 0 }, + { ocForecast_ETS_STA, ENTRY(ocFORECAST_ETS_STA_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_STA, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, + { ocForecast_ETS_STM, ENTRY(ocFORECAST_ETS_STM_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_ETS_STM, 6, { 0, 0, 0, 1, 1, 1 }, 0 }, + { ocForecast_LIN, ENTRY(ocFORECAST_LIN_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_FORECAST_LIN, 3, { 0, 0, 0 }, 0 }, + { ocConcat_MS, ENTRY(ocCONCAT_MS_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_CONCAT_MS, VAR_ARGS, { 0 }, 0 }, + { ocTextJoin_MS, ENTRY(ocTEXTJOIN_MS_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXTJOIN_MS, VAR_ARGS + 2, { 0, 0, 0 }, 0 }, + { ocIfs_MS, ENTRY(ocIFS_MS_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_IFS_MS, PAIRED_VAR_ARGS, { 0, 0 }, 0 }, + { ocSwitch_MS, ENTRY(ocSWITCH_MS_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_SWITCH_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 0 }, 0 }, + { ocMinIfs_MS, ENTRY(ocMINIFS_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MINIFS_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 0 }, 0 }, + { ocMaxIfs_MS, ENTRY(ocMAXIFS_MS_ARY), 0, ID_FUNCTION_GRP_STATISTIC, HID_FUNC_MAXIFS_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 0 }, 0 }, + { ocRoundSig, ENTRY(ocROUNDSIG_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ROUNDSIG, 2, { 0, 0 }, 0 }, + { ocReplaceB, ENTRY(ocREPLACEB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_REPLACEB, 4, { 0, 0, 0, 0 }, 0 }, + { ocFindB, ENTRY(ocFINDB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_FINDB, 3, { 0, 0, 1 }, 0 }, + { ocSearchB, ENTRY(ocSEARCHB_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_SEARCHB, 3, { 0, 0, 1 }, 0 }, + { ocRegex, ENTRY(ocREGEX_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_REGEX, 4, { 0, 0, 1, 1 }, 0 }, + { ocFourier, ENTRY(ocFOURIER_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_FOURIER, 5, { 0, 0, 1, 1, 1 }, 0 }, + { ocRandbetweenNV, ENTRY(ocRANDBETWEEN_NV_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RANDBETWEEN_NV, 2, { 0, 0 }, 0 }, + { ocFilter, ENTRY(ocFILTER_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_FILTER_MS, 3, { 0, 0, 1 }, 0 }, + { ocSort, ENTRY(ocSORT_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SORT_MS, 4, { 0, 1, 1, 1 }, 0 }, + { ocSortBy, ENTRY(ocSORTBY_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SORTBY_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 1 }, 0 }, + { ocMatSequence, ENTRY(ocMAT_SEQUENCE_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MSEQUENCE_MS, 4, { 0, 1, 1, 1 }, 0 }, + { ocRandArray, ENTRY(ocRANDARRAY_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RANDARRAY_MS, 5, { 1, 1, 1, 1, 1 }, 0 }, + { ocChooseCols, ENTRY(ocCHOOSECOLS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_CHOOSECOLS_MS, VAR_ARGS + 1, { 0, 0 }, 0 }, + { ocChooseRows, ENTRY(ocCHOOSEROWS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_CHOOSEROWS_MS, VAR_ARGS + 1, { 0, 0 }, 0 }, + { ocDrop, ENTRY(ocDROP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_DROP_MS, 3, { 0, 0, 1 }, 0 }, + { ocExpand, ENTRY(ocEXPAND_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_EXPAND_MS, 4, { 0, 0, 1, 1 }, 0 }, + { ocHStack, ENTRY(ocHSTACK_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_HSTACK_MS, VAR_ARGS + 1, { 0, 0 }, 0 }, + { ocVStack, ENTRY(ocVSTACK_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VSTACK_MS, VAR_ARGS + 1, { 0, 0 }, 0 }, + { ocTake, ENTRY(ocTAKE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TAKE_MS, 3, { 0, 1, 1 }, 0 }, + { ocTextAfter, ENTRY(ocTEXTAFTER_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXTAFTER_MS, 6, { 0, 1, 1, 1, 1, 1 }, 0 }, + { ocTextBefore, ENTRY(ocTEXTBEFORE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXTBEFORE_MS, 6, { 0, 1, 1, 1, 1, 1 }, 0 }, + { ocTextSplit, ENTRY(ocTEXTSPLIT_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TEXTSPLIT_MS, 6, { 0, 1, 1, 1, 1, 1 }, 0 }, + { ocToCol, ENTRY(ocTOCOL_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TOCOL_MS, 3, { 0, 1, 1 }, 0 }, + { ocToRow, ENTRY(ocTOROW_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TOROW_MS, 3, { 0, 1, 1 }, 0 }, + { ocUnique, ENTRY(ocUNIQUE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_UNIQUE_MS, 3, { 0, 1, 1 }, 0 }, + { ocWrapCols, ENTRY(ocWRAPCOLS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_WRAPCOLS_MS, 3, { 0, 1, 1 }, 0 }, + { ocWrapRows, ENTRY(ocWRAPROWS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_WRAPROWS_MS, 3, { 0, 1, 1 }, 0 }, + { ocByCol, ENTRY(ocBYCOL_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_BYCOL_MS, 2, {0, 0}, 0 }, + { ocByRow, ENTRY(ocBYROW_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_BYROW_MS, 2, {0, 0}, 0 }, + { ocMakeArray, ENTRY(ocMAKEARRAY_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MAKEARRAY_MS, 3, { 0, 0, 0 }, 0 }, + { ocMap, ENTRY(ocMAP_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MAP_MS, VAR_ARGS + 2, { 0, 0 }, 0 }, + { ocReduce, ENTRY(ocREDUCE_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_REDUCE_MS, 3, { 1, 0, 0 }, 0 }, + { ocScan, ENTRY(ocSCAN_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_SCAN_MS, 3, { 1, 0, 0 }, 0 }, + { ocArrayToText, ENTRY(ocARRAYTOTEXT_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ARRAYTOTEXT_MS, 2, { 0, 1 }, 0 }, }; ScFuncDesc* pDesc = nullptr; @@ -818,8 +828,8 @@ ScFunctionList::ScFunctionList( bool bEnglishFunctionNames ) // otherwise the sub resources within the resource blocks and the // resource blocks themselves would had to be ordered according to // OpCodes, which is utopian... - ScFuncDescCore const * pDescsEnd = aDescs + std::size(aDescs); - for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i) + ScFuncDescCore const * pDescsEnd = aDescs + SAL_N_ELEMENTS(aDescs); + for (sal_uInt16 i = 0; i <= ocLastOpcodeId; ++i) { const ScFuncDescCore *pEntry = std::lower_bound(aDescs, pDescsEnd, i, [](const ScFuncDescCore &rItem, sal_uInt16 key) @@ -854,7 +864,7 @@ ScFunctionList::ScFunctionList( bool bEnglishFunctionNames ) // legacy binary AddIn functions - sal_uInt16 nNextId = SC_OPCODE_LAST_OPCODE_ID + 1; // FuncID for AddIn functions + sal_uInt16 nNextId = ocLastOpcodeId + 1; // FuncID for AddIn functions // Interpretation of AddIn list OUString aDefArgNameValue = u"value"_ustr; diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx index 4e3202900b3b..8e1393382022 100644 --- a/sc/source/core/data/global.cxx +++ b/sc/source/core/data/global.cxx @@ -278,6 +278,12 @@ ScUnoAddInCollection* ScGlobal::GetAddInCollection() return comphelper::doubleCheckedInit( pAddInCollection, []() { return new ScUnoAddInCollection(); }); } +bool ScGlobal::IsValidExternal(const OUString& rAddIn) +{ + return (ScGlobal::GetLegacyFuncCollection()->findByName(rAddIn) + || !ScGlobal::GetAddInCollection()->FindFunction(rAddIn, false).isEmpty()); +} + ScUserList& ScGlobal::GetUserList() { assert(!bThreadedGroupCalcInProgress); @@ -331,6 +337,8 @@ OUString ScGlobal::GetErrorString(FormulaError nErr) return ScCompiler::GetNativeSymbol(ocErrDivZero); case FormulaError::IllegalFPOperation: return ScCompiler::GetNativeSymbol(ocErrNum); + case FormulaError::Spill: + return ScCompiler::GetNativeSymbol(ocErrSpill); default: return ScResId(STR_ERROR_STR) + OUString::number( static_cast(nErr) ); } @@ -419,9 +427,15 @@ OUString ScGlobal::GetLongErrorString(FormulaError nErr) case FormulaError::LinkFormulaNeedingCheck: pErrNumber = STR_ERR_LONG_LINK_FORMULA_NEEDING_CHECK; break; + case FormulaError::Spill: + pErrNumber = STR_LONG_ERR_SPILL; + break; case FormulaError::NoValue: pErrNumber = STR_LONG_ERR_NO_VALUE; break; + case FormulaError::NotAFunction: + pErrNumber = STR_LONG_ERR_NOT_FUNC; + break; case FormulaError::NotAvailable: pErrNumber = STR_LONG_ERR_NV; break; @@ -442,6 +456,7 @@ bool ScGlobal::IsValidOOXMLError(FormulaError nErrNumber) case FormulaError::IllegalFPOperation: case FormulaError::NoRef: case FormulaError::NoValue: + case FormulaError::Spill: return true; default: return false; @@ -516,7 +531,7 @@ void ScGlobal::InitTextHeight(SfxItemPool& rPool) { // this gets handed over the m_pMessagePool in ScModule::ScModule, so // the previously used item ScPatternAttr is unchanged. This allows to - // just use an temporary incarnation of a CellAttributeHelper here + // just use a temporary incarnation of a CellAttributeHelper here const CellAttributeHelper aTempHelper(rPool); const ScPatternAttr& rDefaultCellAttribute(aTempHelper.getDefaultCellAttribute()); @@ -575,40 +590,40 @@ void ScGlobal::Clear() xDrawClipDocShellRef.clear(); } -rtl_TextEncoding ScGlobal::GetCharsetValue( std::u16string_view rCharSet ) +rtl_TextEncoding ScGlobal::GetEncodingValue( std::u16string_view rEncoding ) { // new TextEncoding values - if ( CharClass::isAsciiNumeric( rCharSet ) ) + if ( CharClass::isAsciiNumeric( rEncoding ) ) { - sal_Int32 nVal = o3tl::toInt32(rCharSet); + sal_Int32 nVal = o3tl::toInt32(rEncoding); if ( nVal == RTL_TEXTENCODING_DONTKNOW ) return osl_getThreadTextEncoding(); return static_cast(nVal); } // old CharSet values for compatibility - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"ANSI") ) return RTL_TEXTENCODING_MS_1252; - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"MAC") ) return RTL_TEXTENCODING_APPLE_ROMAN; - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"IBMPC") ) return RTL_TEXTENCODING_IBM_850; - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"IBMPC_437")) return RTL_TEXTENCODING_IBM_437; - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"IBMPC_850")) return RTL_TEXTENCODING_IBM_850; - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"IBMPC_860")) return RTL_TEXTENCODING_IBM_860; - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"IBMPC_861")) return RTL_TEXTENCODING_IBM_861; - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"IBMPC_863")) return RTL_TEXTENCODING_IBM_863; - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"IBMPC_865")) return RTL_TEXTENCODING_IBM_865; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"ANSI") ) return RTL_TEXTENCODING_MS_1252; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"MAC") ) return RTL_TEXTENCODING_APPLE_ROMAN; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"IBMPC") ) return RTL_TEXTENCODING_IBM_850; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"IBMPC_437")) return RTL_TEXTENCODING_IBM_437; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"IBMPC_850")) return RTL_TEXTENCODING_IBM_850; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"IBMPC_860")) return RTL_TEXTENCODING_IBM_860; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"IBMPC_861")) return RTL_TEXTENCODING_IBM_861; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"IBMPC_863")) return RTL_TEXTENCODING_IBM_863; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"IBMPC_865")) return RTL_TEXTENCODING_IBM_865; // Some wrong "help" on the net mentions UTF8 and even unoconv uses it, // which worked accidentally if the system encoding is UTF-8 anyway, so // support it ;) but only when reading. - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"UTF8")) return RTL_TEXTENCODING_UTF8; - else if (o3tl::equalsIgnoreAsciiCase(rCharSet, u"UTF-8")) return RTL_TEXTENCODING_UTF8; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"UTF8")) return RTL_TEXTENCODING_UTF8; + else if (o3tl::equalsIgnoreAsciiCase(rEncoding, u"UTF-8")) return RTL_TEXTENCODING_UTF8; else return osl_getThreadTextEncoding(); } -OUString ScGlobal::GetCharsetString( rtl_TextEncoding eVal ) +OUString ScGlobal::GetEncodingString( rtl_TextEncoding eVal ) { const char* pChar; switch ( eVal ) { - // old CharSet strings for compatibility + // old encoding strings for compatibility case RTL_TEXTENCODING_MS_1252: pChar = "ANSI"; break; case RTL_TEXTENCODING_APPLE_ROMAN: pChar = "MAC"; break; // IBMPC == IBMPC_850 diff --git a/sc/source/core/data/grouptokenconverter.cxx b/sc/source/core/data/grouptokenconverter.cxx index 18b2807515ee..789f5f81192c 100644 --- a/sc/source/core/data/grouptokenconverter.cxx +++ b/sc/source/core/data/grouptokenconverter.cxx @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -118,7 +119,7 @@ bool ScGroupTokenConverter::convert( const ScTokenArray& rCode, sc::FormulaLogge { case svSingleRef: { - ScSingleRefData aRef = *p->GetSingleRef(); + ScSingleRefData aRef = static_cast(p)->GetSingleRef(); if( aRef.IsDeleted()) return false; ScAddress aRefPos = aRef.toAbs(mrDoc, mrPos); @@ -130,7 +131,7 @@ bool ScGroupTokenConverter::convert( const ScTokenArray& rCode, sc::FormulaLogge // Trim data array length to actual data range. SCROW nTrimLen = trimLength(aRefPos.Tab(), aRefPos.Col(), aRefPos.Col(), aRefPos.Row(), nLen); // Fetch double array guarantees that the length of the - // returned array equals or greater than the requested + // returned array is equal to or greater than the requested // length. formula::VectorRefArray aArray; @@ -189,7 +190,7 @@ bool ScGroupTokenConverter::convert( const ScTokenArray& rCode, sc::FormulaLogge // Additionally some functions such as INDEX() and OFFSET() require a reference, // that is handled by denylisting those opcodes in ScTokenArray::CheckToken(). - ScComplexRefData aRef = *p->GetDoubleRef(); + ScComplexRefData aRef = static_cast(p)->GetDoubleRef(); if( aRef.IsDeleted()) return false; ScRange aAbs = aRef.toAbs(mrDoc, mrPos); @@ -257,7 +258,7 @@ bool ScGroupTokenConverter::convert( const ScTokenArray& rCode, sc::FormulaLogge aArrays.push_back(aArray); } - std::vector aArraysTmp = aArrays; + std::vector aArraysTmp = aArrays; formula::DoubleVectorRefToken aTok( std::move(aArraysTmp), nArrayLength, nRefRowSize, bAbsFirst, bAbsLast ); mrGroupTokens.AddToken(aTok); rScope.addRefMessage(mrPos, aAbs.aStart, nRequestedLength, aArrays); @@ -282,12 +283,9 @@ bool ScGroupTokenConverter::convert( const ScTokenArray& rCode, sc::FormulaLogge } // Named range. - ScRangeName* pNames = mrDoc.GetRangeName(); - if (!pNames) - // This should never fail. - return false; + ScRangeName& rNames = mrDoc.GetRangeName(); - ScRangeData* pRange = pNames->findByIndex(p->GetIndex()); + ScRangeData* pRange = rNames.findByIndex(static_cast(p)->GetIndex()); if (!pRange) // No named range exists by that index. return false; diff --git a/sc/source/core/data/markdata.cxx b/sc/source/core/data/markdata.cxx index 98a3aebe5c8b..13e12ace8c50 100644 --- a/sc/source/core/data/markdata.cxx +++ b/sc/source/core/data/markdata.cxx @@ -286,7 +286,7 @@ bool ScMarkData::IsCellMarked( SCCOL nCol, SCROW nRow, bool bNoSimple ) const bool ScMarkData::IsColumnMarked( SCCOL nCol ) const { - // bMarkIsNeg meanwhile also for columns heads + // bMarkIsNeg meanwhile also for column heads //TODO: GetMarkColumnRanges for completely marked column if ( bMarked && !bMarkIsNeg && @@ -318,13 +318,15 @@ bool ScMarkData::IsRowMarked( SCROW nRow ) const void ScMarkData::MarkFromRangeList( const ScRangeList& rList, bool bReset ) { + size_t nCount = rList.size(); if (bReset) { - maTabMarked.clear(); + // tdf#152327 - preserve current tab selection when replacement selection is empty + if (nCount > 0) + maTabMarked.clear(); ResetMark(); } - size_t nCount = rList.size(); if ( nCount == 1 && !bMarked && !bMultiMarked ) { const ScRange& rRange = rList[ 0 ]; diff --git a/sc/source/core/data/patattr.cxx b/sc/source/core/data/patattr.cxx index 4754dfa6c2d7..997a5ef02cb7 100644 --- a/sc/source/core/data/patattr.cxx +++ b/sc/source/core/data/patattr.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include #include #include #include @@ -66,8 +67,9 @@ #include #include -CellAttributeHelper::CellAttributeHelper(SfxItemPool& rSfxItemPool) +CellAttributeHelper::CellAttributeHelper(SfxItemPool& rSfxItemPool, ScDocument* pDocument) : mrSfxItemPool(rSfxItemPool) +, mpDocument(pDocument) , mpDefaultCellAttribute(nullptr) , maRegisteredCellAttributes() , mpLastHit(nullptr) @@ -407,6 +409,39 @@ ScPatternAttr::ScPatternAttr(CellAttributeHelper& rHelper, const SfxItemSet* pIt // SfxItemState::INVALID aka IsInvalidItem, this is a precious // value/information e.g. in ScDocument::CreateSelectionPattern maLocalSfxItemSet.Put(*pItemSet, false); + + // tdf#172647: store fonts by their typographic names + ScDocument* pConvDoc = rHelper.GetDocument(); + const TypedWhichId aFontIds[3] = { ATTR_FONT, ATTR_CJK_FONT, ATTR_CTL_FONT }; + const TypedWhichId aWeightIds[3] + = { ATTR_FONT_WEIGHT, ATTR_CJK_FONT_WEIGHT, ATTR_CTL_FONT_WEIGHT }; + const TypedWhichId aPostureIds[3] + = { ATTR_FONT_POSTURE, ATTR_CJK_FONT_POSTURE, ATTR_CTL_FONT_POSTURE }; + OutputDevice* pRefDev = nullptr; + for (int i = 0; pConvDoc && i < 3; ++i) + { + const SvxFontItem* pFont = maLocalSfxItemSet.GetItemIfSet(aFontIds[i], false); + if (!pFont) + continue; + if (!pRefDev) + { + pRefDev = pConvDoc->GetRefDevice(true); + if (!pRefDev) + break; + } + FontWeight eWeight = WEIGHT_DONTKNOW; + if (const SvxWeightItem* pWeight = maLocalSfxItemSet.GetItemIfSet(aWeightIds[i], false)) + eWeight = pWeight->GetWeight(); + FontItalic eItalic = ITALIC_DONTKNOW; + if (const SvxPostureItem* pPosture = maLocalSfxItemSet.GetItemIfSet(aPostureIds[i], false)) + eItalic = pPosture->GetPosture(); + + SvxFontItem aFont(*pFont); + aFont.makeTypographic(*pRefDev, eWeight, WIDTH_DONTKNOW, eItalic); + if (aFont.GetFamilyName() != pFont->GetFamilyName() + || aFont.GetStyleName() != pFont->GetStyleName()) + maLocalSfxItemSet.Put(aFont); + } } } @@ -467,6 +502,7 @@ bool ScPatternAttr::operator==(const ScPatternAttr& rCmp) const void ScPatternAttr::CalcHashCode() const { + assert(!ScGlobal::bThreadedGroupCalcInProgress); size_t nHash = 0; if (const OUString* pName = GetStyleName()) nHash = pName->hashCode(); @@ -1538,7 +1574,10 @@ CellAttributeHolder ScPatternAttr::MigrateToDocument( ScDocument* pDestDoc, ScDo bool ScPatternAttr::IsVisible() const { if (!mxVisible.has_value()) + { + assert(!ScGlobal::bThreadedGroupCalcInProgress); mxVisible = CalcVisible(); + } return *mxVisible; } @@ -1702,14 +1741,22 @@ bool ScPatternAttr::HasValidNumberFormat() const sal_uInt32 ScPatternAttr::GetNumberFormatKey() const { if (!mxNumberFormatKey.has_value()) + { + if (ScGlobal::bThreadedGroupCalcInProgress) + return getNumberFormatKey(GetItemSet()); mxNumberFormatKey = getNumberFormatKey(GetItemSet()); + } return *mxNumberFormatKey; } LanguageType ScPatternAttr::GetLanguageType() const { if (!mxLanguageType.has_value()) + { + if (ScGlobal::bThreadedGroupCalcInProgress) + return getLanguageType(GetItemSet()); mxLanguageType = getLanguageType(GetItemSet()); + } return *mxLanguageType; } diff --git a/sc/source/core/data/pivot/PivotTableResultTraverser.cxx b/sc/source/core/data/pivot/PivotTableResultTraverser.cxx index 90037e6684e3..308dc7e23455 100644 --- a/sc/source/core/data/pivot/PivotTableResultTraverser.cxx +++ b/sc/source/core/data/pivot/PivotTableResultTraverser.cxx @@ -31,24 +31,6 @@ using namespace css; namespace sc { -namespace pivot -{ -uno::Any getMemberForLevel(uno::Reference const& xLevel, OUString const& rName) -{ - uno::Reference xMembersSupplier(xLevel, uno::UNO_QUERY); - if (xMembersSupplier.is()) - { - uno::Reference xMembers = xMembersSupplier->getMembers(); - if (xMembers.is()) - { - if (xMembers->hasByName(rName)) - return xMembers->getByName(rName); - } - } - return uno::Any(); -} -} - // PivotTableResultTraverser void PivotTableResultTraverser::traverse() diff --git a/sc/source/core/data/pivot/StyleOutput.cxx b/sc/source/core/data/pivot/StyleOutput.cxx new file mode 100644 index 000000000000..0fabb08ad72c --- /dev/null +++ b/sc/source/core/data/pivot/StyleOutput.cxx @@ -0,0 +1,354 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * 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 + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace +{ +constexpr sal_uInt16 SC_DP_FRAME_WIDTH = SvxBorderLineWidth::Thin; + +constexpr Color SC_DP_FRAME_COLOR(0, 0, 0); + +void lcl_SetFrame(ScDocument& rDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, + sal_uInt16 nWidth) +{ + ::editeng::SvxBorderLine aLine(nullptr, nWidth, SvxBorderLineStyle::SOLID); + SvxBoxItem aBox(ATTR_BORDER); + aBox.SetLine(&aLine, SvxBoxItemLine::LEFT); + aBox.SetLine(&aLine, SvxBoxItemLine::TOP); + aBox.SetLine(&aLine, SvxBoxItemLine::RIGHT); + aBox.SetLine(&aLine, SvxBoxItemLine::BOTTOM); + SvxBoxInfoItem aBoxInfo(ATTR_BORDER_INNER); + aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI, false); + aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::VERT, false); + aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::DISTANCE, false); + + rDoc.ApplyFrameAreaTab(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab), aBox, aBoxInfo); +} + +void lcl_SetLeftAligned(ScDocument& rDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, + SCROW nRow2) +{ + ScPatternAttr aPattern(rDoc.getCellAttributeHelper()); + aPattern.ItemSetPut(SvxHorJustifyItem(SvxCellHorJustify::Left, ATTR_HOR_JUSTIFY)); + rDoc.ApplyPatternAreaTab(nCol1, nRow1, nCol2, nRow2, nTab, aPattern); +} + +void lcl_SetBold(ScDocument& rDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) +{ + ScPatternAttr aPattern(rDoc.getCellAttributeHelper()); + aPattern.ItemSetPut(SvxWeightItem(WEIGHT_BOLD, ATTR_FONT_WEIGHT)); + aPattern.ItemSetPut(SvxWeightItem(WEIGHT_BOLD, ATTR_CJK_FONT_WEIGHT)); + aPattern.ItemSetPut(SvxWeightItem(WEIGHT_BOLD, ATTR_CTL_FONT_WEIGHT)); + rDoc.ApplyPatternAreaTab(nCol1, nRow1, nCol2, nRow2, nTab, aPattern); +} + +/** Draws the block frames of the table: each block gets a thin box around it. The rows and + * columns where subtotal and member blocks begin are collected with AddRow and AddCol, and + * OutputDataArea then frames the blocks between them. */ +class BlockFrameOutput +{ + ScDocument& mrDocument; + SCTAB mnTab; + std::vector mbNeedLineCols; + std::vector mnCols; + + std::vector mbNeedLineRows; + std::vector mnRows; + + SCCOL mnTabStartCol; + SCROW mnTabStartRow; + + SCCOL mnDataStartCol; + SCROW mnDataStartRow; + SCCOL mnTabEndCol; + SCROW mnTabEndRow; + +public: + BlockFrameOutput(ScDocument& rDocument, sc::pivot::Geometry const& rGeometry) + : mrDocument(rDocument) + , mnTab(rGeometry.mnTab) + , mnTabStartCol(rGeometry.mnTabStartCol) + , mnTabStartRow(rGeometry.mnTabStartRow) + , mnDataStartCol(rGeometry.mnDataStartCol) + , mnDataStartRow(rGeometry.mnDataStartRow) + , mnTabEndCol(rGeometry.mnTabEndCol) + , mnTabEndRow(rGeometry.mnTabEndRow) + { + mbNeedLineCols.resize(mnTabEndCol - mnDataStartCol + 1, false); + mbNeedLineRows.resize(mnTabEndRow - mnDataStartRow + 1, false); + } + + void AddRow(SCROW nRow) + { + if (!mbNeedLineRows[nRow - mnDataStartRow]) + { + mbNeedLineRows[nRow - mnDataStartRow] = true; + mnRows.push_back(nRow); + } + } + + void AddCol(SCCOL nCol) + { + if (!mbNeedLineCols[nCol - mnDataStartCol]) + { + mbNeedLineCols[nCol - mnDataStartCol] = true; + mnCols.push_back(nCol); + } + } + + void OutputBlockFrame(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, + bool bHori = false) + { + Color color = SC_DP_FRAME_COLOR; + ::editeng::SvxBorderLine aLine(&color, SC_DP_FRAME_WIDTH); + + SvxBoxItem aBox(ATTR_BORDER); + aBox.SetLine(&aLine, SvxBoxItemLine::LEFT); + aBox.SetLine(&aLine, SvxBoxItemLine::TOP); + aBox.SetLine(&aLine, SvxBoxItemLine::RIGHT); + aBox.SetLine(&aLine, SvxBoxItemLine::BOTTOM); + + SvxBoxInfoItem aBoxInfo(ATTR_BORDER_INNER); + aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::VERT, false); + if (bHori) + { + aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI); + aBoxInfo.SetLine(&aLine, SvxBoxInfoItemLine::HORI); + } + else + aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI, false); + + aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::DISTANCE, false); + + mrDocument.ApplyFrameAreaTab(ScRange(nStartCol, nStartRow, mnTab, nEndCol, nEndRow, mnTab), + aBox, aBoxInfo); + } + + void OutputDataArea() + { + AddRow(mnDataStartRow); + AddCol(mnDataStartCol); + + mnCols.push_back(mnTabEndCol + 1); //set last col right + mnRows.push_back(mnTabEndRow + 1); //set last row bottom + + bool bAllRows = ((mnTabEndRow - mnDataStartRow + 2) == static_cast(mnRows.size())); + + std::sort(mnCols.begin(), mnCols.end()); + std::sort(mnRows.begin(), mnRows.end()); + + for (SCCOL nCol = 0; nCol < static_cast(mnCols.size()) - 1; nCol++) + { + if (!bAllRows) + { + if (nCol < static_cast(mnCols.size()) - 2) + { + for (SCROW i = nCol % 2; i < static_cast(mnRows.size()) - 2; i += 2) + OutputBlockFrame(mnCols[nCol], mnRows[i], mnCols[nCol + 1] - 1, + mnRows[i + 1] - 1); + if (mnRows.size() >= 2) + OutputBlockFrame(mnCols[nCol], mnRows[mnRows.size() - 2], + mnCols[nCol + 1] - 1, mnRows[mnRows.size() - 1] - 1); + } + else + { + for (SCROW i = 0; i < static_cast(mnRows.size()) - 1; i++) + OutputBlockFrame(mnCols[nCol], mnRows[i], mnCols[nCol + 1] - 1, + mnRows[i + 1] - 1); + } + } + else + OutputBlockFrame(mnCols[nCol], mnRows.front(), mnCols[nCol + 1] - 1, + mnRows.back() - 1, bAllRows); + } + //output rows area outer frame + if (mnTabStartCol != mnDataStartCol) + { + if (mnTabStartRow != mnDataStartRow) + OutputBlockFrame(mnTabStartCol, mnTabStartRow, mnDataStartCol - 1, + mnDataStartRow - 1); + OutputBlockFrame(mnTabStartCol, mnDataStartRow, mnDataStartCol - 1, mnTabEndRow); + } + //output cols area outer frame + OutputBlockFrame(mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow - 1); + } +}; + +} // end anonymous namespace + +namespace sc::pivot +{ +void StyleOutput::clear() +{ + maGeometry = Geometry(); + maFieldCells.clear(); + maPageFieldValueCells.clear(); + maColumnMemberSpans.clear(); + maRowMemberSpans.clear(); + maSubtotalColumns.clear(); + maSubtotalRows.clear(); + maIndentCells.clear(); + maExpanderCells.clear(); +} + +void StyleOutput::apply() +{ + SCTAB nTab = maGeometry.mnTab; + + // Field caption cells and page field value cells + for (FieldCell const& rCell : maFieldCells) + { + if (rCell.bFrame) + lcl_SetFrame(mrDocument, nTab, rCell.nCol, rCell.nRow, rCell.nCol, rCell.nRow, + SC_DP_FRAME_WIDTH); + } + for (PageFieldValueCell const& rCell : maPageFieldValueCells) + { + lcl_SetFrame(mrDocument, nTab, rCell.nCol, rCell.nRow, rCell.nCol, rCell.nRow, + SC_DP_FRAME_WIDTH); + } + + BlockFrameOutput aBlockFrames(mrDocument, maGeometry); + + // Column field members + for (ColumnMemberSpan const& rSpan : maColumnMemberSpans) + { + if (rSpan.nField + 1 < maGeometry.mnColumnFieldCount) + { + if (rSpan.nField + 2 == maGeometry.mnColumnFieldCount) + { + aBlockFrames.AddCol(rSpan.nStartCol); + if (rSpan.nStartCol + 1 == rSpan.nEndCol) + aBlockFrames.OutputBlockFrame(rSpan.nStartCol, rSpan.nRow, rSpan.nEndCol, + rSpan.nRow + 1, true); + } + else + { + aBlockFrames.OutputBlockFrame(rSpan.nStartCol, rSpan.nRow, rSpan.nEndCol, + rSpan.nRow); + } + lcl_SetLeftAligned(mrDocument, nTab, rSpan.nStartCol, rSpan.nRow, rSpan.nEndCol, + maGeometry.mnDataStartRow - 1); + } + else + { + lcl_SetLeftAligned(mrDocument, nTab, rSpan.nStartCol, rSpan.nRow, rSpan.nStartCol, + maGeometry.mnDataStartRow - 1); + } + } + + // A single column field shares its header row with the data description, so the frame around + // the description row spans the whole width of the data columns. + if (maGeometry.mnColumnFieldCount == 1 + && maGeometry.mnMemberStartRow > maGeometry.mnTabStartRow) + { + aBlockFrames.OutputBlockFrame(maGeometry.mnDataStartCol, maGeometry.mnTabStartRow, + maGeometry.mnTabEndCol, maGeometry.mnMemberStartRow - 1); + } + + // Subtotal and grand total columns. The label cells in the header area are bold and aligned + // to the left, the result cells below them are bold. + for (SubtotalColumn const& rColumn : maSubtotalColumns) + { + aBlockFrames.AddCol(rColumn.nCol); + aBlockFrames.OutputBlockFrame(rColumn.nCol, rColumn.nStartRow, rColumn.nCol, + maGeometry.mnDataStartRow - 1); + lcl_SetBold(mrDocument, nTab, rColumn.nCol, rColumn.nStartRow, rColumn.nCol, + maGeometry.mnDataStartRow - 1); + lcl_SetLeftAligned(mrDocument, nTab, rColumn.nCol, rColumn.nStartRow, rColumn.nCol, + maGeometry.mnDataStartRow - 1); + lcl_SetBold(mrDocument, nTab, rColumn.nCol, maGeometry.mnDataStartRow, rColumn.nCol, + maGeometry.mnTabEndRow); + } + + // Row field members. The first member that begins in a row also gets a frame around the whole + // width of the table for its row span. + std::vector aBorderSet(maGeometry.mnTabEndRow - maGeometry.mnDataStartRow + 1, false); + for (RowMemberSpan const& rSpan : maRowMemberSpans) + { + if (rSpan.nField + 1 < maGeometry.mnRowFieldCount) + { + aBlockFrames.AddRow(rSpan.nStartRow); + if (!aBorderSet[rSpan.nStartRow - maGeometry.mnDataStartRow]) + { + aBlockFrames.OutputBlockFrame(rSpan.nCol, rSpan.nStartRow, maGeometry.mnTabEndCol, + rSpan.nEndRow); + aBorderSet[rSpan.nStartRow - maGeometry.mnDataStartRow] = true; + } + aBlockFrames.OutputBlockFrame(rSpan.nCol, rSpan.nStartRow, rSpan.nCol, rSpan.nEndRow); + + if (rSpan.nField == maGeometry.mnRowFieldCount - 2) + aBlockFrames.OutputBlockFrame(rSpan.nCol + 1, rSpan.nStartRow, rSpan.nCol + 1, + rSpan.nEndRow); + + lcl_SetLeftAligned(mrDocument, nTab, rSpan.nCol, rSpan.nStartRow, + maGeometry.mnDataStartCol - 1, rSpan.nEndRow); + } + else + { + lcl_SetLeftAligned(mrDocument, nTab, rSpan.nCol, rSpan.nStartRow, + maGeometry.mnDataStartCol - 1, rSpan.nStartRow); + } + } + + // Subtotal and grand total rows. The label cells in the header area are bold and aligned to + // the left, the result cells to the right of them are bold. + for (SubtotalRow const& rRow : maSubtotalRows) + { + aBlockFrames.AddRow(rRow.nRow); + aBlockFrames.OutputBlockFrame(rRow.nStartCol, rRow.nRow, maGeometry.mnDataStartCol - 1, + rRow.nRow); + lcl_SetBold(mrDocument, nTab, rRow.nStartCol, rRow.nRow, maGeometry.mnDataStartCol - 1, + rRow.nRow); + lcl_SetLeftAligned(mrDocument, nTab, rRow.nStartCol, rRow.nRow, + maGeometry.mnDataStartCol - 1, rRow.nRow); + lcl_SetBold(mrDocument, nTab, maGeometry.mnDataStartCol, rRow.nRow, maGeometry.mnTabEndCol, + rRow.nRow); + } + + // Member indents and the expand and collapse buttons. The indent shows up because the member + // cells are aligned to the left, an indent has no effect in a centered cell. + for (Indent const& rIndent : maIndentCells) + mrDocument.ApplyAttr(rIndent.nCol, rIndent.nRow, nTab, ScIndentItem(rIndent.nIndent)); + + for (Expander const& rExpander : maExpanderCells) + { + mrDocument.ApplyFlagsTab(rExpander.nCol, rExpander.nRow, rExpander.nCol, rExpander.nRow, + nTab, rExpander.nFlags); + } + + aBlockFrames.OutputDataArea(); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/core/data/pivot2.cxx b/sc/source/core/data/pivot2.cxx index 3fc96837cd3c..e64a10127318 100644 --- a/sc/source/core/data/pivot2.cxx +++ b/sc/source/core/data/pivot2.cxx @@ -33,7 +33,9 @@ ScDPName::ScDPName(OUString aName, OUString aLayoutName, sal_uInt8 nDupCount) : ScDPLabelData::Member::Member() : mbVisible(true), - mbShowDetails(true) + mbShowDetails(true), + mfValue(0.0), + mbHasValue(false) {} OUString const & ScDPLabelData::Member::getDisplayName() const @@ -55,7 +57,8 @@ ScDPLabelData::ScDPLabelData() : mbIsValue(false), mbDataLayout(false), mbRepeatItemLabels(false), - mbCalculatedField(false) + mbCalculatedField(false), + mbIsDateDimension(false) {} OUString const & ScDPLabelData::getDisplayName() const diff --git a/sc/source/core/data/poolhelp.cxx b/sc/source/core/data/poolhelp.cxx index c58808f48de9..4be2e4f92c90 100644 --- a/sc/source/core/data/poolhelp.cxx +++ b/sc/source/core/data/poolhelp.cxx @@ -48,7 +48,7 @@ SfxItemPool* ScPoolHelper::GetEditEnginePool() const { mpEditEnginePool = EditEngine::CreatePool(); mpEditEnginePool->SetDefaultMetric( MapUnit::Map100thMM ); - } // ifg ( pEnginePool ) + } // if ( !mpEditEnginePool ) return mpEditEnginePool.get(); } SvNumberFormatter* ScPoolHelper::GetFormTable() const @@ -82,6 +82,7 @@ std::unique_ptr ScPoolHelper::CreateNumberFormatter() const } assert(mxStylePool->GetDocument()); p->SetColorLink( LINK(mxStylePool->GetDocument(), ScDocument, GetUserDefinedColor)); + p->SetColorIndexLink( LINK(mxStylePool->GetDocument(), ScDocument, GetUserDefinedColorIndex)); p->SetEvalDateFormat(NfEvalDateFormat::InternationalThenFormat); sal_uInt16 d,m; @@ -98,7 +99,10 @@ void ScPoolHelper::SourceDocumentGone() // reset all pointers to the source document mxStylePool->SetDocument( nullptr ); if ( pFormTable ) + { pFormTable->SetColorLink( Link() ); + pFormTable->SetColorIndexLink(Link()); + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/postit.cxx b/sc/source/core/data/postit.cxx index 817c33566ba3..74c2cf1cbc48 100644 --- a/sc/source/core/data/postit.cxx +++ b/sc/source/core/data/postit.cxx @@ -451,6 +451,8 @@ ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNo maNoteData( rNote.maNoteData ) { mnPostItId = nPostItId == 0 ? mnLastPostItId++ : nPostItId; + if (rNote.mpThreadedCommentData) + mpThreadedCommentData = std::make_unique(*rNote.mpThreadedCommentData); maNoteData.mxCaption.clear(); CreateCaption( rPos, rNote.maNoteData.mxCaption.get() ); } @@ -477,7 +479,16 @@ std::unique_ptr ScPostIt::Clone( const ScAddress& rOwnPos, ScDocument& bCloneCaption = false; CreateCaptionFromInitData( rOwnPos ); sal_uInt32 nPostItId = comphelper::LibreOfficeKit::isActive() ? 0 : mnPostItId; - return bCloneCaption ? std::make_unique( rDestDoc, rDestPos, *this, nPostItId ) : std::make_unique( rDestDoc, rDestPos, maNoteData, false, mnPostItId ); + std::unique_ptr pClone; + if (bCloneCaption) + pClone = std::make_unique(rDestDoc, rDestPos, *this, nPostItId); + else + { + pClone = std::make_unique(rDestDoc, rDestPos, maNoteData, false, mnPostItId); + if (mpThreadedCommentData) + pClone->mpThreadedCommentData = std::make_unique(*mpThreadedCommentData); + } + return pClone; } void ScPostIt::SetDate( const OUString& rDate ) @@ -490,6 +501,18 @@ void ScPostIt::SetAuthor( const OUString& rAuthor ) maNoteData.maAuthor = rAuthor; } +void ScPostIt::SetResolved(bool bResolved) +{ + if (!mpThreadedCommentData) + mpThreadedCommentData = std::make_unique(); + mpThreadedCommentData->mbDone = bResolved; +} + +void ScPostIt::SetThreadedCommentData(std::unique_ptr pData) +{ + mpThreadedCommentData = std::move(pData); +} + void ScPostIt::AutoStamp(bool bCreate) { if (bCreate) diff --git a/sc/source/core/data/queryiter.cxx b/sc/source/core/data/queryiter.cxx index 5c080dbc08c4..7fc93b6d0f87 100644 --- a/sc/source/core/data/queryiter.cxx +++ b/sc/source/core/data/queryiter.cxx @@ -52,7 +52,7 @@ ScQueryCellIteratorBase< accessType, queryType >::ScQueryCellIteratorBase(ScDocu , nSortedBinarySearch( nBinarySearchDisabled ) , bAdvanceQuery( false ) , bIgnoreMismatchOnLeadingStrings( false ) - , nSearchOpCode( SC_OPCODE_NONE ) + , nSearchOpCode( ocNone ) , nBestFitCol(SCCOL_MAX) , nBestFitRow(SCROW_MAX) { @@ -91,7 +91,7 @@ void ScQueryCellIteratorBase< accessType, queryType >::PerformQuery() ((maParam.bByRow && nRow == maParam.nRow1) || (!maParam.bByRow && nCol == maParam.nCol1)); bool bTestEqualCondition = false; - const bool bNewSearchFunction = nSearchOpCode == SC_OPCODE_X_LOOKUP || nSearchOpCode == SC_OPCODE_X_MATCH; + const bool bNewSearchFunction = nSearchOpCode == ocXLookup || nSearchOpCode == ocXMatch; ScQueryEvaluator queryEvaluator(rDoc, *rDoc.maTabs[nTab], maParam, &mrContext, (nTestEqualCondition ? &bTestEqualCondition : nullptr), bNewSearchFunction); if( queryType == ScQueryCellIteratorType::CountIf ) @@ -297,7 +297,7 @@ void ScQueryCellIteratorBase< accessType, queryType >::InitPos() { // This should be all in AccessBase::InitPos(), but that one can't call // BinarySearch(), so do it this way instead. - bool bNewSearchFunction = nSearchOpCode == SC_OPCODE_X_LOOKUP || nSearchOpCode == SC_OPCODE_X_MATCH; + bool bNewSearchFunction = nSearchOpCode == ocXLookup || nSearchOpCode == ocXMatch; AccessBase::InitPosStart(bNewSearchFunction, nSortedBinarySearch); ScQueryOp& op = maParam.GetEntry(0).eOp; SCCOLROW beforeColRow = -1; @@ -337,7 +337,7 @@ void ScQueryCellIteratorBase< accessType, queryType >::InitPos() if( BinarySearch( maParam.bByRow ? nCol : nRow) ) { lastColRow = maParam.bByRow ? nRow : nCol; - if (nSearchOpCode == SC_OPCODE_X_LOOKUP || nSearchOpCode == SC_OPCODE_X_MATCH) + if (nSearchOpCode == ocXLookup || nSearchOpCode == ocXMatch) { ScQueryOp saveOp = op; op = SC_LESS; @@ -346,7 +346,7 @@ void ScQueryCellIteratorBase< accessType, queryType >::InitPos() op = saveOp; } } - if ((nSearchOpCode == SC_OPCODE_X_LOOKUP || nSearchOpCode == SC_OPCODE_X_MATCH) && + if ((nSearchOpCode == ocXLookup || nSearchOpCode == ocXMatch) && (lastColRow == beforeColRow || beforeColRow == -1)) { beforeColRow = -1; @@ -881,7 +881,7 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo nFoundCol = rDoc.MaxCol()+1; nFoundRow = rDoc.MaxRow()+1; - if ((nSearchOpCode == SC_OPCODE_X_LOOKUP || nSearchOpCode == SC_OPCODE_X_MATCH) && + if ((nSearchOpCode == ocXLookup || nSearchOpCode == ocXMatch) && nSortedBinarySearch == nBinarySearchDisabled) SetStopOnMismatch( false ); // assume not sorted keys for XLookup/XMatch else @@ -897,7 +897,7 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo (maParam.GetEntry(0).eOp == SC_LESS_EQUAL || maParam.GetEntry(0).eOp == SC_GREATER_EQUAL); // assume not sorted properly if we are using XLookup/XMatch with forward or backward search - if (bBinary && (nSearchOpCode == SC_OPCODE_X_LOOKUP || nSearchOpCode == SC_OPCODE_X_MATCH) && + if (bBinary && (nSearchOpCode == ocXLookup || nSearchOpCode == ocXMatch) && nSortedBinarySearch == nBinarySearchDisabled) bBinary = false; @@ -991,8 +991,8 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo } } } - if (IsEqualConditionFulfilled() && (nSearchOpCode != SC_OPCODE_X_LOOKUP && - nSearchOpCode != SC_OPCODE_X_MATCH)) + if (IsEqualConditionFulfilled() && (nSearchOpCode != ocXLookup && + nSearchOpCode != ocXMatch)) { // Position on last equal entry, except for XLOOKUP, // which looking for the first equal entry @@ -1624,7 +1624,7 @@ static bool CanBeUsedForSorterCache(ScDocument& /*rDoc*/, const ScQueryParam& /* return false; if(rParam.mbRangeLookup) return false; - const bool bNewSearchFunction = nSearchOpCode == SC_OPCODE_X_LOOKUP || nSearchOpCode == SC_OPCODE_X_MATCH; + const bool bNewSearchFunction = nSearchOpCode == ocX_LOOKUP || nSearchOpCode == ocX_MATCH; if(rParam.GetEntry(0).GetQueryItem().meType == ScQueryEntry::ByString && !bNewSearchFunction && !ScQueryEvaluator::isMatchWholeCell(rDoc, rParam.GetEntry(0).eOp)) return false; // substring matching cannot be sorted @@ -1756,6 +1756,19 @@ sal_uInt64 ScCountIfCellIterator< accessType >::GetCount() { maParam.nCol1 = rDoc.ClampToAllocatedColumns(nTab, maParam.nCol1); maParam.nCol2 = rDoc.ClampToAllocatedColumns(nTab, maParam.nCol2); + + // Also trim rows to the actual data area. Empty cells outside the + // data bounding box cannot match a non-empty criterion (which the + // mbMatchEmpty guard above already confirms), so the result is + // unchanged. Mirrors the trim that COUNTIFS already performs in + // ScInterpreter::IterateParametersIfs. + ScRange aRange(maParam.nCol1, maParam.nRow1, nTab, + maParam.nCol2, maParam.nRow2, nTab); + if (rDoc.GetDataAreaSubrange(aRange)) + { + maParam.nRow1 = aRange.aStart.Row(); + maParam.nRow2 = aRange.aEnd.Row(); + } } nCol = maParam.nCol1; InitPos(); @@ -1786,7 +1799,7 @@ sal_uInt64 ScCountIfCellIterator< ScQueryCellIteratorAccess::SortedCache >::GetC nRow = maParam.nRow1; ScRange aSortedRangeRange( col, maParam.nRow1, nTab, col, maParam.nRow2, nTab); ScQueryOp& op = maParam.GetEntry(0).eOp; - bool bNewSearchFunction = nSearchOpCode == SC_OPCODE_X_LOOKUP || nSearchOpCode == SC_OPCODE_X_MATCH; + bool bNewSearchFunction = nSearchOpCode == ocXLookup || nSearchOpCode == ocXMatch; SetSortedRangeCache( rDoc.GetSortedRangeCache( aSortedRangeRange, maParam, &mrContext, bNewSearchFunction, nSearchOpCode )); if( op == SC_EQUAL ) { diff --git a/sc/source/core/data/segmenttree.cxx b/sc/source/core/data/segmenttree.cxx index e3962aa510fc..9bb121cb9e45 100644 --- a/sc/source/core/data/segmenttree.cxx +++ b/sc/source/core/data/segmenttree.cxx @@ -506,6 +506,35 @@ OString ScFlatBoolRowSegments::dumpAsString() return aOutput.makeStringAndClear(); } +ScFlatBoolColSegments::RangeIterator::RangeIterator(ScFlatBoolColSegments const & rSegs) : + mrSegs(rSegs) +{ +} + +bool ScFlatBoolColSegments::RangeIterator::getFirst(RangeData& rRange) +{ + ScFlatBoolSegmentsImpl::RangeData aData; + if (!mrSegs.mpImpl->getFirst(aData)) + return false; + + rRange.mnCol1 = static_cast(aData.mnPos1); + rRange.mnCol2 = static_cast(aData.mnPos2); + rRange.mbValue = static_cast(aData.mnValue); + return true; +} + +bool ScFlatBoolColSegments::RangeIterator::getNext(RangeData& rRange) +{ + ScFlatBoolSegmentsImpl::RangeData aData; + if (!mrSegs.mpImpl->getNext(aData)) + return false; + + rRange.mnCol1 = static_cast(aData.mnPos1); + rRange.mnCol2 = static_cast(aData.mnPos2); + rRange.mbValue = static_cast(aData.mnValue); + return true; +} + ScFlatBoolColSegments::ScFlatBoolColSegments(SCCOL nMaxCol) : mpImpl(new ScFlatBoolSegmentsImpl(nMaxCol)) { @@ -530,7 +559,7 @@ bool ScFlatBoolColSegments::setFalse(SCCOL nCol1, SCCOL nCol2) return mpImpl->setFalse(static_cast(nCol1), static_cast(nCol2)); } -bool ScFlatBoolColSegments::getRangeData(SCCOL nCol, RangeData& rData) +bool ScFlatBoolColSegments::getRangeData(SCCOL nCol, RangeData& rData) const { ScFlatBoolSegmentsImpl::RangeData aData; if (!mpImpl->getRangeData(static_cast(nCol), aData)) diff --git a/sc/source/core/data/stlpool.cxx b/sc/source/core/data/stlpool.cxx index a193bdbbd30c..08403971d71a 100644 --- a/sc/source/core/data/stlpool.cxx +++ b/sc/source/core/data/stlpool.cxx @@ -267,8 +267,7 @@ void ScStyleSheetPool::CreateStandardStyles() SfxItemSet* pHFSet = nullptr; ScEditEngineDefaulter aEdEngine( pDoc->GetEditEnginePool(), true ); aEdEngine.SetUpdateLayout( false ); - std::unique_ptr pEmptyTxtObj = aEdEngine.CreateTextObject(); - std::unique_ptr pTxtObj; + EditTextObject aEmptyTxtObj = aEdEngine.CreateTextObject(); ScPageHFItem aHeaderItem( ATTR_PAGE_HEADERRIGHT ); ScPageHFItem aFooterItem( ATTR_PAGE_FOOTERRIGHT ); ScStyleSheet* pSheet = nullptr; @@ -334,10 +333,10 @@ void ScStyleSheetPool::CreateStandardStyles() aEdEngine.SetTextCurrentDefaults(OUString()); aEdEngine.QuickInsertField( SvxFieldItem(SvxTableField(), EE_FEATURE_FIELD), ESelection() ); - pTxtObj = aEdEngine.CreateTextObject(); - aHeaderItem.SetLeftArea ( *pEmptyTxtObj ); - aHeaderItem.SetCenterArea( *pTxtObj ); - aHeaderItem.SetRightArea ( *pEmptyTxtObj ); + EditTextObject aTxtObj = aEdEngine.CreateTextObject(); + aHeaderItem.SetLeftArea ( aEmptyTxtObj ); + aHeaderItem.SetCenterArea( aTxtObj ); + aHeaderItem.SetRightArea ( aEmptyTxtObj ); pSet->Put( aHeaderItem ); // Footer: @@ -347,10 +346,9 @@ void ScStyleSheetPool::CreateStandardStyles() aEdEngine.SetTextCurrentDefaults( aStr ); nStrLen = aStr.getLength(); aEdEngine.QuickInsertField( SvxFieldItem(SvxPageField(), EE_FEATURE_FIELD), ESelection(0,nStrLen) ); - pTxtObj = aEdEngine.CreateTextObject(); - aFooterItem.SetLeftArea ( *pEmptyTxtObj ); - aFooterItem.SetCenterArea( *pTxtObj ); - aFooterItem.SetRightArea ( *pEmptyTxtObj ); + aFooterItem.SetLeftArea ( aEmptyTxtObj ); + aFooterItem.SetCenterArea( aEdEngine.CreateTextObject() ); + aFooterItem.SetRightArea ( aEmptyTxtObj ); pSet->Put( aFooterItem ); // 2. Report @@ -393,16 +391,14 @@ void ScStyleSheetPool::CreateStandardStyles() aEdEngine.SetTextCurrentDefaults( aStr ); aEdEngine.QuickInsertField( SvxFieldItem(SvxFileField(), EE_FEATURE_FIELD), ESelection(0,2) ); aEdEngine.QuickInsertField( SvxFieldItem(SvxTableField(), EE_FEATURE_FIELD), ESelection() ); - pTxtObj = aEdEngine.CreateTextObject(); - aHeaderItem.SetLeftArea( *pTxtObj ); - aHeaderItem.SetCenterArea( *pEmptyTxtObj ); + aHeaderItem.SetLeftArea( aEdEngine.CreateTextObject() ); + aHeaderItem.SetCenterArea( aEmptyTxtObj ); aStr = ", "; aEdEngine.SetTextCurrentDefaults( aStr ); aEdEngine.QuickInsertField( SvxFieldItem(SvxTimeField(), EE_FEATURE_FIELD), ESelection(0,2) ); aEdEngine.QuickInsertField( SvxFieldItem(SvxDateField(Date( Date::SYSTEM ),SvxDateType::Var), EE_FEATURE_FIELD), ESelection() ); - pTxtObj = aEdEngine.CreateTextObject(); - aHeaderItem.SetRightArea( *pTxtObj ); + aHeaderItem.SetRightArea( aEdEngine.CreateTextObject() ); pSet->Put( aHeaderItem ); // Footer: @@ -415,10 +411,9 @@ void ScStyleSheetPool::CreateStandardStyles() aEdEngine.SetTextCurrentDefaults( aStr ); aEdEngine.QuickInsertField( SvxFieldItem(SvxPagesField(), EE_FEATURE_FIELD), ESelection(0,nStrLen2) ); aEdEngine.QuickInsertField( SvxFieldItem(SvxPageField(), EE_FEATURE_FIELD), ESelection(0,nStrLen) ); - pTxtObj = aEdEngine.CreateTextObject(); - aFooterItem.SetLeftArea ( *pEmptyTxtObj ); - aFooterItem.SetCenterArea( *pTxtObj ); - aFooterItem.SetRightArea ( *pEmptyTxtObj ); + aFooterItem.SetLeftArea ( aEmptyTxtObj ); + aFooterItem.SetCenterArea( aEdEngine.CreateTextObject() ); + aFooterItem.SetRightArea ( aEmptyTxtObj ); pSet->Put( aFooterItem ); bHasStandardStyles = true; diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 1944b32aaaa4..84da9824b23e 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -505,7 +506,13 @@ bool ScTable::SetOptimalHeight( mpRowHeights->enableTreeSearch(false); - GetOptimalHeightsInColumn(rCxt, aCol, nStartRow, nEndRow, pProgress, nProgressStart); + { + // Deciding a cell's script type / edit status during the per-column + // walk forces formula results, which can resize a dynamic-array + // formula and delete cells from the store being walked over. + sc::MatrixResizeGuard aMatrixResizeGuard(rDocument); + GetOptimalHeightsInColumn(rCxt, aCol, nStartRow, nEndRow, pProgress, nProgressStart); + } SetRowHeightRangeFunc aFunc(this, rCxt.getPPTY()); bool bChanged = SetOptimalHeightsToRows(rCxt, aFunc, pRowFlags.get(), nStartRow, nEndRow, bApi); diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index a8e67a655f5a..ff03d95d8ad1 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -953,7 +954,7 @@ public: } SCCOL nTransCol = mnCol1 + nRow - mnTopRow - mnFilteredRows + mnRowDestOffset; - mrClipTab.SetEditText(nTransCol, mnTransRow, ScEditUtil::Clone(*p, mrClipTab.GetDoc())); + mrClipTab.SetEditText(nTransCol, mnTransRow, std::make_unique(ScEditUtil::Clone(*p, mrClipTab.GetDoc()))); } void operator() (size_t nRow, const ScFormulaCell* p) @@ -1336,7 +1337,7 @@ void ScTable::StartListeningFormulaCells( void ScTable::CopyToTable( sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData, - bool bAsLink, bool bColRowFlags, bool bGlobalNamesToLocal, bool bCopyCaptions ) + bool bAsLink, bool bColRowFlags, ScCloneFlags nCloneFlags, bool bCopyCaptions ) { if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2)) return; @@ -1376,7 +1377,7 @@ void ScTable::CopyToTable( pDestTab->CreateColumnIfNotExists(ClampToAllocatedColumns(nCol2)); // avoid repeated resizing for (SCCOL i = nCol1; i <= ClampToAllocatedColumns(nCol2); i++) aCol[i].CopyToColumn(rCxt, nRow1, nRow2, bToUndoDoc ? nFlags : nTempFlags, bMarked, - pDestTab->CreateColumnIfNotExists(i), pMarkData, bAsLink, bGlobalNamesToLocal); + pDestTab->CreateColumnIfNotExists(i), pMarkData, bAsLink, nCloneFlags); // tdf#154044: Restore from the default column data if (bFromUndoDoc && (nFlags & InsertDeleteFlags::ATTRIB) && nCol2 >= aCol.size()) { @@ -2229,6 +2230,11 @@ void ScTable::SetLoadingMedium(bool bLoading) void ScTable::CalcAll() { + // Interpreting a dynamic-array formula here can resize it, deleting or + // inserting reference cells in the columns this loop walks. Defer any + // such resize to the end of the whole-table walk so the cell store is + // not mutated underneath the iteration. + sc::MatrixResizeGuard aMatrixResizeGuard(rDocument); for (SCCOL i=0; i < aCol.size(); i++) aCol[i].CalcAll(); @@ -4488,17 +4494,57 @@ SCROW ScTable::GetRowForHeightPixels(SCROW nStartRow, tools::Long& rStartRowHeig tools::Long ScTable::GetColOffset( SCCOL nCol, bool bHiddenAsZero ) const { - tools::Long n = 0; - if ( mpColWidth ) + if ( !mpColWidth ) { - auto colWidthIt = mpColWidth->begin(); - for (SCCOL i = 0; i < nCol; (++i < nCol) ? ++colWidthIt : (void)false) - if (!( bHiddenAsZero && ColHidden(i) )) - n += *colWidthIt; + OSL_FAIL("GetColumnOffset: Data missing"); + return 0; + } + tools::Long n = 0; + if (bHiddenAsZero) + { + // Walk the two data structures in parallel, for performance. + size_t nColWidthIndex; + SCCOL nColWidthRangeEnd; + sal_uInt16 nColWidth = mpColWidth->GetValue(0, nColWidthIndex, nColWidthRangeEnd); + ScFlatBoolColSegments::RangeData aHiddenColsRange; + ScFlatBoolColSegments::RangeIterator aHiddenColsRangeItr(maFilterData.getHiddenCols()); + bool bHasHiddenColsRange = aHiddenColsRangeItr.getFirst(aHiddenColsRange); + for (SCCOL i = 0; i < nCol; ++i) + { + // Fetch the next width range if necessary. + if (i > nColWidthRangeEnd) + nColWidth = mpColWidth->GetNextValue(nColWidthIndex, nColWidthRangeEnd); + // Fetch the next hidden cols range if necessary. + if (bHasHiddenColsRange && i > aHiddenColsRange.mnCol2) + bHasHiddenColsRange = aHiddenColsRangeItr.getNext(aHiddenColsRange); + + if (!bHasHiddenColsRange) + { + // Zero width, because absence of data implies hidden, see FilterData::colHidden. + } + else if (i >= aHiddenColsRange.mnCol1 && i <= aHiddenColsRange.mnCol2) + { + // Inside a range for which we have "is-hidden" data + if (!aHiddenColsRange.mbValue) + n += nColWidth; + } + else + { + n += nColWidth; + } + } } else { - OSL_FAIL("GetColumnOffset: Data missing"); + size_t nColWidthIndex; + SCCOL nColWidthRangeEnd; + sal_uInt16 nColWidth = mpColWidth->GetValue(0, nColWidthIndex, nColWidthRangeEnd); + for (SCCOL i = 0; i < nCol; ++i) + { + if (i > nColWidthRangeEnd) + nColWidth = mpColWidth->GetNextValue(nColWidthIndex, nColWidthRangeEnd); + n += nColWidth; + } } return n; } diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index a98822369308..d6268aea107a 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -609,7 +610,7 @@ void fillSortedColumnArray( break; case CELLTYPE_EDIT: assert(rCell.mpAttr); - rCellStore.push_back(rCell.maCell.getEditText()->Clone().release()); + rCellStore.push_back(new EditTextObject(*rCell.maCell.getEditText())); break; case CELLTYPE_FORMULA: { @@ -1828,14 +1829,30 @@ void ScTable::Sort( bool bAutoFilter = GetDoc().HasAutoFilter(rSortParam.nCol1, nRow1, GetTab()); if (bAutoFilter) { - if (IsSheetViewHolder()) + sc::SortOrderInfo aSortOrderInfo; + + for (auto& rState : aSortParam.maKeyState) { - auto pSheetView = mpSheetViewFor->GetSheetViewManager()->get(mnSheetViewID); - pSheetView->addOrderIndices(pArray->GetOrderIndices(), nRow1, nLastRow); + if (rState.bDoSort) + aSortOrderInfo.maKeyStates.push_back(rState); } - else + + aSortOrderInfo.mnFirstColumn = rSortParam.nCol1; + aSortOrderInfo.mnLastColumn = rSortParam.nCol2; + aSortOrderInfo.mnFirstRow = nRow1; + aSortOrderInfo.mnLastRow = nLastRow; + aSortOrderInfo.maOrder = pArray->GetOrderIndices(); + + if (IsSheetViewHolder() && GetDefaultViewTable()) { - GetSheetViewManager()->addOrderIndices(pArray->GetOrderIndices(), nRow1, nLastRow); + auto pSheetView = GetDefaultViewTable()->GetSheetViewManager()->get(mnSheetViewID); + pSheetView->addOrderIndices(aSortOrderInfo); + pSheetView->setSortParam(aSortParam); + } + else if (GetSheetViewManager() && pUndo) + { + GetSheetViewManager()->addOrderIndices(aSortOrderInfo); + GetSheetViewManager()->mergeReorderParameters(*pUndo); } } } @@ -3035,6 +3052,13 @@ bool ScTable::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCR * evaluate it has header row, but that doesn't make much sense. */ return false; + // A first row holding autofilter or pivot table buttons is a header row, + // whatever cell types it holds. + for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++) + if (GetAttr(nCol, nStartRow, ATTR_MERGE_FLAG)->GetValue() + & (ScMF::Auto | ScMF::Button | ScMF::ButtonPopup | ScMF::ButtonPopup2)) + return true; + for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++) { CellType eType = GetCellType( nCol, nStartRow ); @@ -3107,13 +3131,25 @@ void ScTable::GetFilteredFilterEntries( if (nCol >= aCol.size()) return; - sc::ColumnBlockConstPosition aBlockPos; - aCol[nCol].InitBlockPosition(aBlockPos); - // remove the entry for this column from the query parameter ScQueryParam aParam( rParam ); aParam.RemoveEntryByField(nCol); + // Fast path: when no active filter constraints remain after removing this + // column's entry, every row is "valid" by definition. Skip the O(rows) + // per-row ValidQuery loop and use the block-scan path, which is + // O(non-empty cells) for the data plus O(pattern runs) for the empty tail. + // Makes opening the autofilter dropdown on a huge but mostly-empty DB + // range near-instant instead of evaluating CF for a million empty rows. + if (aParam.GetEntryCount() == 0 || !aParam.GetEntry(0).bDoQuery) + { + GetFilterEntries(nCol, nRow1, nRow2, rFilterEntries, bFiltering); + return; + } + + sc::ColumnBlockConstPosition aBlockPos; + aCol[nCol].InitBlockPosition(aBlockPos); + lcl_PrepareQuery(&rDocument, this, aParam, true); ScQueryEvaluator queryEvaluator(GetDoc(), *this, aParam); for ( SCROW j = nRow1; j <= nRow2; ++j ) diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx index b8c275597be0..ad4be97da919 100644 --- a/sc/source/core/data/table4.cxx +++ b/sc/source/core/data/table4.cxx @@ -1266,39 +1266,6 @@ void ScTable::FillSparkline(bool bVertical, SCCOLROW nFixed, } } -void ScTable::GetBackColorArea(SCCOL& rStartCol, SCROW& /*rStartRow*/, - SCCOL& rEndCol, SCROW& rEndRow ) const -{ - bool bExtend; - const SvxBrushItem* pDefBackground = &rDocument.GetPool()->GetUserOrPoolDefaultItem(ATTR_BACKGROUND); - - rStartCol = std::min(rStartCol, aCol.size() - 1); - rEndCol = std::min(rEndCol, aCol.size() - 1); - - do - { - bExtend = false; - - if (rEndRow < rDocument.MaxRow()) - { - for (SCCOL nCol = rStartCol; nCol <= rEndCol; ++nCol) - { - const ScPatternAttr* pPattern = GetColumnData(nCol).GetPattern(rEndRow + 1); - const SvxBrushItem* pBackground = &pPattern->GetItem(ATTR_BACKGROUND); - if (!pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData().empty() || - (pBackground->GetColor() != COL_TRANSPARENT && pBackground != pDefBackground)) - { - bExtend = true; - break; - } - } - - if (bExtend) - ++rEndRow; - } - } while (bExtend); -} - OUString ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY ) { OUString aValue; @@ -2789,6 +2756,12 @@ void ScTable::UpdateInsertTabAbs(SCTAB nTable) aCol[i].UpdateInsertTabAbs(nTable); } +void ScTable::AdjustRelativeTabRefs(SCTAB nOldTab, SCTAB nNewTab, sc::TargetTabState eMode) +{ + for (SCCOL i=0; i < aCol.size(); i++) + aCol[i].AdjustRelativeTabRefs(nOldTab, nNewTab, eMode); +} + bool ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, bool bInSel, const ScMarkData& rMark) const { diff --git a/sc/source/core/data/table6.cxx b/sc/source/core/data/table6.cxx index 89803bb125cb..9fbe4cbd2715 100644 --- a/sc/source/core/data/table6.cxx +++ b/sc/source/core/data/table6.cxx @@ -263,7 +263,7 @@ bool ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, sc::Colum { ScFieldEditEngine& rEngine = rDocument.GetEditEngine(); rEngine.SetTextCurrentDefaults(aString); - SetEditText(nCol, nRow, rEngine.CreateTextObject()); + SetEditText(nCol, nRow, std::make_unique(rEngine.CreateTextObject())); } else aCol[nCol].SetString(nRow, nTab, aString, rDocument.GetAddressConvention()); @@ -630,7 +630,7 @@ bool ScTable::SearchStyle(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rDocument.GetStyleSheetPool()->Find( rSearchItem.GetSearchString(), SfxStyleFamily::Para )); - SCCOL nCol = rCol; + SCCOL nCol = ClampToAllocatedColumns(rCol); SCROW nRow = rRow; bool bFound = false; @@ -639,7 +639,7 @@ bool ScTable::SearchStyle(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& bool bBack = rSearchItem.GetBackward(); short nAdd = bBack ? -1 : 1; - if (bRows) // by row + if (!bRows) // by column { if ( !IsColValid( nCol ) ) { @@ -663,7 +663,7 @@ bool ScTable::SearchStyle(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& } while ( !bFound && IsColValid( nCol ) ); } - else // by column + else // by row { SCCOL aColSize = aCol.size(); std::vector< SCROW > nNextRows ( aColSize ); @@ -777,18 +777,23 @@ bool ScTable::ReplaceAllStyle( ScDocument* pUndoDoc) { bool bRet = SearchAllStyle(rSearchItem, rMark, rMatchedRanges); + if (pUndoDoc && (bRet || rSearchItem.IsAllTables())) + { + rDocument.CopyToDocument(0, 0 ,nTab, rDocument.MaxCol(), rDocument.MaxRow(), nTab, + InsertDeleteFlags::ATTRIB, false, *pUndoDoc, &rMark); + } + if (bRet) { const ScStyleSheet* pReplaceStyle = static_cast( rDocument.GetStyleSheetPool()->Find( rSearchItem.GetReplaceString(), SfxStyleFamily::Para )); - if (pReplaceStyle) { - if (pUndoDoc) - rDocument.CopyToDocument(0, 0 ,nTab, rDocument.MaxCol(),rDocument.MaxRow(),nTab, - InsertDeleteFlags::ATTRIB, true, *pUndoDoc, &rMark); - ApplySelectionStyle( *pReplaceStyle, rMark ); + const ScRange aThisTab(0, 0, nTab, rDocument.MaxCol(), rDocument.MaxRow(), nTab); + const ScMarkData aThisMark(rDocument.GetSheetLimits(), + rMatchedRanges.GetIntersectedRange(aThisTab)); + ApplySelectionStyle(*pReplaceStyle, aThisMark); } else { @@ -837,12 +842,15 @@ bool ScTable::SearchAndReplace( aSearchOptions.Locale = ScGlobal::GetLocale(); // reflect UseAsianOptions flag in SearchOptions - // (use only ignore case and width if asian options are disabled). + // (use only ignore case and width if asian options are disabled, + // plus the two options that stand on their own in the dialog). // This is also done in SvxSearchDialog CommandHdl, but not in API object. if ( !rSearchItem.IsUseAsianOptions() ) aSearchOptions.transliterateFlags &= TransliterationFlags::IGNORE_CASE | - TransliterationFlags::IGNORE_WIDTH; + TransliterationFlags::IGNORE_WIDTH | + TransliterationFlags::IGNORE_DIACRITICS_CTL | + TransliterationFlags::IGNORE_KASHIDA_CTL; pSearchText.reset( new utl::TextSearch( aSearchOptions ) ); diff --git a/sc/source/core/data/tablestyle.cxx b/sc/source/core/data/tablestyle.cxx index 929c0a46001d..1c00f341fe7e 100644 --- a/sc/source/core/data/tablestyle.cxx +++ b/sc/source/core/data/tablestyle.cxx @@ -8,6 +8,15 @@ */ #include +#include +#include +#include +#include +#include +#include +#include +#include +#include ScTableStyle::ScTableStyle(const OUString& rName, const std::optional& rUIName) : mnFirstRowStripeSize(1) @@ -746,61 +755,6 @@ void ScTableStyle::SetPattern(ScTableStyleElement eTableStyleElement, } } -void ScTableStyle::SetTablePattern(std::unique_ptr pPattern) -{ - mpTablePattern = std::move(pPattern); -} - -void ScTableStyle::SetFirstColumnStripePattern(std::unique_ptr pPattern) -{ - mpFirstColumnStripePattern = std::move(pPattern); -} - -void ScTableStyle::SetSecondColumnStripePattern(std::unique_ptr pPattern) -{ - mpSecondColumnStripePattern = std::move(pPattern); -} - -void ScTableStyle::SetFirstRowStripePattern(std::unique_ptr pPattern) -{ - mpFirstRowStripePattern = std::move(pPattern); -} - -void ScTableStyle::SetSecondRowStripePattern(std::unique_ptr pPattern) -{ - mpSecondRowStripePattern = std::move(pPattern); -} - -void ScTableStyle::SetLastColumnPattern(std::unique_ptr pPattern) -{ - mpLastColumnPattern = std::move(pPattern); -} - -void ScTableStyle::SetFirstColumnPattern(std::unique_ptr pPattern) -{ - mpFirstColumnPattern = std::move(pPattern); -} - -void ScTableStyle::SetHeaderRowPattern(std::unique_ptr pPattern) -{ - mpHeaderRowPattern = std::move(pPattern); -} - -void ScTableStyle::SetTotalRowPattern(std::unique_ptr pPattern) -{ - mpTotalRowPattern = std::move(pPattern); -} - -void ScTableStyle::SetFirstHeaderCellPattern(std::unique_ptr pPattern) -{ - mpFirstHeaderCellPattern = std::move(pPattern); -} - -void ScTableStyle::SetLastHeaderCellPattern(std::unique_ptr pPattern) -{ - mpLastHeaderCellPattern = std::move(pPattern); -} - std::map ScTableStyle::GetSetPatterns() const { std::map aPatterns; @@ -863,22 +817,149 @@ std::map ScTableStyle::GetSetPatterns return aPatterns; } -sal_Int32 ScTableStyle::GetFirstRowStripeSize() const { return mnFirstRowStripeSize; } - -sal_Int32 ScTableStyle::GetSecondRowStripeSize() const { return mnSecondRowStripeSize; } - -sal_Int32 ScTableStyle::GetFirstColumnStripeSize() const { return mnFirstColStripeSize; } - -sal_Int32 ScTableStyle::GetSecondColumnStripeSize() const { return mnSecondColStripeSize; } - -ScTableStyles::ScTableStyles() {} +ScTableStyles::ScTableStyles(SfxBindings* pBindings) + : mpBindings(pBindings) +{ +} void ScTableStyles::AddTableStyle(std::unique_ptr pTableStyle) { + // TODO: insert() won't overwrite an existing entry with the same name. + // When we add UI support for creating custom table styles, we should + // either reject duplicates (with UI validation) or use insert_or_assign + // to replace the existing style. maTableStyles.insert({ pTableStyle->GetName(), std::move(pTableStyle) }); + if (mpBindings) + mpBindings->Invalidate(SID_TABLE_STYLES); } -void ScTableStyles::DeleteTableStyle(const OUString& rName) { maTableStyles.erase(rName); } +void ScTableStyles::ClearOOXMLDefaultStyles() +{ + std::erase_if(maTableStyles, + [](const auto& rEntry) { return rEntry.second->IsOOXMLDefault(); }); + if (mpBindings) + mpBindings->Invalidate(SID_TABLE_STYLES); +} + +namespace +{ +/// Update themed colors in a single pattern's items against a new ColorSet +void updatePatternThemedColors(ScPatternAttr& rPattern, const model::ColorSet& rColorSet) +{ + SfxItemSet& rItemSet = rPattern.GetItemSetWritable(); + + // Update background fill color + if (const SvxBrushItem* pBrush = rItemSet.GetItemIfSet(ATTR_BACKGROUND)) + { + const model::ComplexColor& rCC = pBrush->getComplexColor(); + if (rCC.getThemeColorType() != model::ThemeColorType::Unknown) + { + Color aNewColor = rColorSet.resolveOOXMLColor(rCC); + SvxBrushItem aNewBrush(aNewColor, ATTR_BACKGROUND); + aNewBrush.setComplexColor(rCC); + rItemSet.Put(aNewBrush); + } + } + + // Update font color + if (const SvxColorItem* pColorItem = rItemSet.GetItemIfSet(ATTR_FONT_COLOR)) + { + const model::ComplexColor& rCC = pColorItem->getComplexColor(); + if (rCC.getThemeColorType() != model::ThemeColorType::Unknown) + { + Color aNewColor = rColorSet.resolveOOXMLColor(rCC); + SvxColorItem aNewColorItem(aNewColor, rCC, ATTR_FONT_COLOR); + rItemSet.Put(aNewColorItem); + } + } + + // Update border line colors (outer borders) + if (const SvxBoxItem* pBox = rItemSet.GetItemIfSet(ATTR_BORDER)) + { + SvxBoxItem aNewBox(*pBox); + bool bChanged = false; + for (auto eLine : { SvxBoxItemLine::TOP, SvxBoxItemLine::BOTTOM, SvxBoxItemLine::LEFT, + SvxBoxItemLine::RIGHT }) + { + if (const editeng::SvxBorderLine* pLine = aNewBox.GetLine(eLine)) + { + const model::ComplexColor& rCC = pLine->getComplexColor(); + if (rCC.getThemeColorType() != model::ThemeColorType::Unknown) + { + Color aNewColor = rColorSet.resolveOOXMLColor(rCC); + editeng::SvxBorderLine aNewLine(*pLine); + aNewLine.SetColor(aNewColor); + aNewBox.SetLine(&aNewLine, eLine); + bChanged = true; + } + } + } + if (bChanged) + rItemSet.Put(aNewBox); + } + + // Update inner border line colors (vertical/horizontal) + if (const SvxBoxInfoItem* pBoxInfo = rItemSet.GetItemIfSet(ATTR_BORDER_INNER)) + { + SvxBoxInfoItem aNewBoxInfo(*pBoxInfo); + bool bChanged = false; + if (const editeng::SvxBorderLine* pLine = aNewBoxInfo.GetVert()) + { + const model::ComplexColor& rCC = pLine->getComplexColor(); + if (rCC.getThemeColorType() != model::ThemeColorType::Unknown) + { + Color aNewColor = rColorSet.resolveOOXMLColor(rCC); + editeng::SvxBorderLine aNewLine(*pLine); + aNewLine.SetColor(aNewColor); + aNewBoxInfo.SetLine(&aNewLine, SvxBoxInfoItemLine::VERT); + bChanged = true; + } + } + if (const editeng::SvxBorderLine* pLine = aNewBoxInfo.GetHori()) + { + const model::ComplexColor& rCC = pLine->getComplexColor(); + if (rCC.getThemeColorType() != model::ThemeColorType::Unknown) + { + Color aNewColor = rColorSet.resolveOOXMLColor(rCC); + editeng::SvxBorderLine aNewLine(*pLine); + aNewLine.SetColor(aNewColor); + aNewBoxInfo.SetLine(&aNewLine, SvxBoxInfoItemLine::HORI); + bChanged = true; + } + } + if (bChanged) + rItemSet.Put(aNewBoxInfo); + } +} + +} // anonymous namespace + +void ScTableStyle::UpdateThemedColors(const model::ColorSet& rColorSet) +{ + if (mbIsOOXMLDefault) + return; // defaults are fully regenerated, not updated in-place + + std::unique_ptr* aPatterns[] + = { &mpTablePattern, &mpFirstColumnStripePattern, &mpSecondColumnStripePattern, + &mpFirstRowStripePattern, &mpSecondRowStripePattern, &mpLastColumnPattern, + &mpFirstColumnPattern, &mpHeaderRowPattern, &mpTotalRowPattern, + &mpFirstHeaderCellPattern, &mpLastHeaderCellPattern }; + + for (auto* pPatternPtr : aPatterns) + { + if (*pPatternPtr) + updatePatternThemedColors(**pPatternPtr, rColorSet); + } +} + +void ScTableStyles::UpdateCustomStyleThemedColors(const model::ColorSet& rColorSet) +{ + for (auto & [ rName, pStyle ] : maTableStyles) + { + if (pStyle && !pStyle->IsOOXMLDefault()) + pStyle->UpdateThemedColors(rColorSet); + } +} const ScTableStyle* ScTableStyles::GetTableStyle(const OUString& rName) const { @@ -888,4 +969,61 @@ const ScTableStyle* ScTableStyles::GetTableStyle(const OUString& rName) const return maTableStyles.find(rName)->second.get(); } +namespace +{ +std::string_view tableStyleElementName(ScTableStyleElement eElement) +{ + switch (eElement) + { + case ScTableStyleElement::WholeTable: + return "WholeTable"; + case ScTableStyleElement::FirstColumnStripe: + return "FirstColumnStripe"; + case ScTableStyleElement::SecondColumnStripe: + return "SecondColumnStripe"; + case ScTableStyleElement::FirstRowStripe: + return "FirstRowStripe"; + case ScTableStyleElement::SecondRowStripe: + return "SecondRowStripe"; + case ScTableStyleElement::LastColumn: + return "LastColumn"; + case ScTableStyleElement::FirstColumn: + return "FirstColumn"; + case ScTableStyleElement::HeaderRow: + return "HeaderRow"; + case ScTableStyleElement::TotalRow: + return "TotalRow"; + case ScTableStyleElement::FirstHeaderCell: + return "FirstHeaderCell"; + case ScTableStyleElement::LastHeaderCell: + return "LastHeaderCell"; + } + return {}; +} +} + +void ScTableStyles::generateJSON(tools::JsonWriter& rWriter) const +{ + auto aStylesArray = rWriter.startArray("TableStyles"); + + for (auto const & [ rName, pStyle ] : maTableStyles) + { + auto aStyleStruct = rWriter.startStruct(); + rWriter.put("Name", pStyle->GetName().toUtf8()); + rWriter.put("UIName", pStyle->GetUIName().toUtf8()); + + auto aElementsArray = rWriter.startArray("Elements"); + for (auto const & [ eElement, pPattern ] : pStyle->GetSetPatterns()) + { + const SvxBrushItem* pBrush = pPattern->GetItemSet().GetItemIfSet(ATTR_BACKGROUND); + if (!pBrush) + continue; + + auto aElementStruct = rWriter.startStruct(); + rWriter.put("Type", tableStyleElementName(eElement)); + rWriter.put("FillColor", pBrush->GetColor().AsRGBHexString().toUtf8()); + } + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx index 1dbffe1cf94a..315970d6f419 100644 --- a/sc/source/core/data/validat.cxx +++ b/sc/source/core/data/validat.cxx @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -53,6 +52,7 @@ #include #include #include +#include #include #include @@ -419,7 +419,7 @@ void ScValidationData::DoError(weld::Window* pParent, const OUString& rInput, co } std::shared_ptr xBox(Application::CreateMessageDialog(pParent, eType, - eStyle, aMessage, SfxViewShell::Current())); + eStyle, aMessage)); xBox->set_title(aTitle); xBox->SetInstallLOKNotifierHdl(LINK(nullptr, ScValidationData, InstallLOKNotifierHdl)); @@ -787,7 +787,10 @@ rtl_uString* ScStringTokenIterator::Next() maCurString = svl::SharedString(); // start with invalid string. if (mbOk && pToken) - maCurString = pToken->GetString(); + { + assert(dynamic_cast(pToken)); + maCurString = static_cast(pToken)->GetString(); + } // string found but empty -> get next token; otherwise return it return (maCurString.isValid() && maCurString.isEmpty()) ? Next() : maCurString.getData(); @@ -802,6 +805,50 @@ sal_uInt32 lclGetCellFormat( const ScDocument& rDoc, const ScAddress& rPos ) return pPattern->GetNumberFormat( rDoc.GetFormatTable() ); } +/** Fills rRange with the cell area a structured table reference stands for. + Returns false when no area can be determined. */ +bool lclGetTableRefArea(const FormulaToken* pToken, const ScDocument& rDocument, + const ScAddress& rPos, ScRange& rRange) +{ + auto pTableRef = static_cast(pToken); + + // A compiled reference already holds the exact area it resolves to: the + // columns and data rows it selects, lined up with the interpreted values. + if (const FormulaToken* pArea = pTableRef->GetAreaRefRPN()) + { + switch (pArea->GetType()) + { + case svSingleRef: + rRange = ScRange( + static_cast(pArea)->GetSingleRef().toAbs(rDocument, rPos)); + return true; + case svDoubleRef: + rRange = static_cast(pArea)->GetDoubleRef().toAbs(rDocument, rPos); + return true; + default: + return false; + } + } + + // Not compiled yet, so fall back to the database range. + const ScDBData* pDBData + = rDocument.GetDBCollection()->getNamedDBs().findByIndex(pTableRef->GetIndex()); + if (!pDBData) + return false; + + pDBData->GetArea(rRange); + // Every selector but the whole table refers to the data part, so leave out + // the header and totals rows. + if (pTableRef->GetItem() != ScTableRefToken::ALL) + { + if (pDBData->HasHeader()) + rRange.aStart.IncRow(); + if (pDBData->HasTotals()) + rRange.aEnd.IncRow(-1); + } + return true; +} + } // namespace bool ScValidationData::HasSelectionList() const @@ -878,21 +925,41 @@ bool ScValidationData::GetSelectionFromFormula( if (t) { OpCode eOpCode = t->GetOpCode(); - if (eOpCode == ocDBArea || eOpCode == ocTableRef) + if (eOpCode == ocDBArea) { - if (const ScDBData* pDBData = rDocument.GetDBCollection()->getNamedDBs().findByIndex(t->GetIndex())) + auto pIndexToken = static_cast(t); + if (const ScDBData* pDBData = rDocument.GetDBCollection()->getNamedDBs().findByIndex(pIndexToken->GetIndex())) { pDBData->GetArea(aRange); bRef = true; } } + else if (eOpCode == ocTableRef) + { + if (lclGetTableRefArea(t, rDocument, rPos, aRange)) + bRef = true; + } else if (eOpCode == ocName) { - const ScRangeData* pName = rDocument.FindRangeNameBySheetAndIndex( t->GetSheet(), t->GetIndex()); + auto pIndexToken = static_cast(t); + const ScRangeData* pName = rDocument.FindRangeNameBySheetAndIndex( pIndexToken->GetSheet(), pIndexToken->GetIndex()); if (pName && pName->IsReference(aRange)) { bRef = true; } + else if (pName) + { + // The name wraps a table reference. A column-qualified one + // like MyTable[Column] is several tokens led by the table + // reference, so resolve the area from that leading token. + const ScTokenArray* pNameCode = pName->GetCode(); + const FormulaToken* pFirst = pNameCode ? pNameCode->FirstToken() : nullptr; + if (pFirst && pFirst->GetOpCode() == ocTableRef + && lclGetTableRefArea(pFirst, rDocument, rPos, aRange)) + { + bRef = true; + } + } } else if (t->GetType() != svIndex) { diff --git a/sc/source/core/inc/adiasync.hxx b/sc/source/core/inc/adiasync.hxx index b693f12a28b8..b1a647b7eddb 100644 --- a/sc/source/core/inc/adiasync.hxx +++ b/sc/source/core/inc/adiasync.hxx @@ -42,7 +42,7 @@ private: }; std::unique_ptr pDocs; // List of using documents LegacyFuncData* mpFuncData; // Pointer to data in collection - sal_uLong nHandle; // is casted from double to sal_uLong + sal_uLong nHandle; // is cast from double to sal_uLong ParamType meType; // result of type PTR_DOUBLE or PTR_STRING bool bValid; // is value valid? diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index 706bc766d810..7a81a6e84635 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -19,11 +19,16 @@ #pragma once +#include + #include #include #include +#include #include #include +#include +#include #include #include #include @@ -37,6 +42,7 @@ #include #include +#include #include #include #include @@ -65,7 +71,7 @@ struct VectorSearchArguments { // struct contains the contents of the function arguments // OpCode of struct owner - sal_uInt16 nSearchOpCode = SC_OPCODE_NONE; + sal_uInt16 nSearchOpCode = ocNone; // match mode (common, enum values are from XLOOKUP) // optional 5th argument to set match mode @@ -135,13 +141,13 @@ inline std::basic_ostream & operator <<(std::basic_ostream moMatrixOperandRange; + bool mbMatrixOperandRangeConflict = false; + const formula::FormulaToken* pCur; // current token const formula::FormulaToken* pStack[ MAXSTACK ]; // the current stack FormulaError nGlobalError; // global (local to this formula expression) error @@ -305,6 +320,7 @@ private: double GetCellValueOrZero( const ScAddress&, const ScRefCellValue& rCell ); double GetValueCellValue( const ScAddress&, double fOrig ); void GetCellString( svl::SharedString& rStr, const ScRefCellValue& rCell ); + formula::FormulaCallableRef GetCellCallable( const ScRefCellValue& rCell ); static FormulaError GetCellErrCode( const ScRefCellValue& rCell ); bool CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, @@ -379,7 +395,33 @@ private: void PushCellResultToken( bool bDisplayEmptyAsString, const ScAddress & rAddress, SvNumFormatType * pRetTypeExpr, sal_uInt32 * pRetIndexExpr, bool bFinalResult = false ); - formula::FormulaConstTokenRef PopToken(); + formula::FormulaConstTokenRef PopTokenImpl(); + template + ::boost::intrusive_ptr PopToken() + { + auto p = PopTokenImpl(); + assert(!p || dynamic_cast(p.get())); + return static_cast(p.get()); + } + /** Note the range a popped matrix operand sits at, so a result of the same shape can be + passed on as sitting there too. */ + void NoteMatrixOperandRange(const formula::FormulaToken* pToken); + + /** Pop the operand of a reference operator. + + A spilled range arrives as a matrix that carries the range it was read from. These + operators work on ranges, so such a matrix comes back as the matching double + reference. Everything else comes back unchanged. + */ + formula::FormulaConstTokenRef PopReferenceOperand(); + + /** Whether the top of the stack is a matrix whose values are still the cells' own. */ + bool IsTopMatrixReference() const + { + return sp > 0 && pStack[sp - 1]->GetType() == formula::svMatrix + && static_cast(pStack[sp - 1])->IsMatrixReference(); + } + void Pop(); void PopError(); double PopDouble(); @@ -455,6 +497,7 @@ private: void PushStringBuffer( const sal_Unicode* pString ); void PushString( const OUString& rStr ); void PushString( const svl::SharedString& rString ); + void PushCallable( formula::FormulaCallableRef pCallable ); void PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab); void PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2); @@ -501,6 +544,11 @@ private: /// returns TRUE if double (or error, check nGlobalError), else FALSE bool GetDoubleOrString( double& rValue, svl::SharedString& rString ); svl::SharedString GetString(); + // Pop a non-matrix operand as a string for the & concatenation + // operator. A boolean operand (a LOGICAL-typed double) formats + // as "TRUE" or "FALSE", everything else routes through + // GetString. + OUString PopOperandStringForConcat(); svl::SharedString GetStringFromMatrix(const ScMatrixRef& pMat); svl::SharedString GetStringFromDouble( const double fVal); // pop matrix and obtain one element, upper left or according to jump matrix @@ -512,15 +560,12 @@ private: ScMatrixRef GetMatrix(); ScMatrixRef GetMatrix( short & rParam, size_t & rInRefList ); sc::RangeMatrix GetRangeMatrix(); - - // Get tokens at specific parameters for LET (lambda) function - static void replaceNamesToResult( const std::unordered_map& rResultIndexes, - ScTokenArray& rTokens, short nStartPos, short nEndPos ); - ScTokenArray checkPushTokens( const ScTokenArray& rTokens, - short nStartPos, short nEndPos ); + formula::FormulaCallableRef GetCallable(); void ScTableOp(); // repeated operations + void DispatchOpCode(OpCode eOp); + // common helper functions void CurFmtToFuncFmt() @@ -603,7 +648,9 @@ private: void ScXor(); void ScNot(); void ScNeg(); + void ScSingleValue(); void ScPercentSign(); + void ScSpilledRange(); void ScIntersect(); void ScRangeFunc(); void ScUnionFunc(); @@ -652,6 +699,9 @@ private: void ScIsRef(); void ScIsValue(); void ScIsFormula(); + // Push a boolean matrix that reports, per cell of the range, whether + // ISFORMULA counts that cell as a formula. + void PushIsFormulaMatrix(const ScRange& rRange); void ScFormula(); void ScRoman(); void ScArabic(); @@ -733,6 +783,7 @@ private: void ScTextAfter(); void ScTextBefore(); void ScTextSplit(); + void ScArrayToText(); void ScToCol(); void ScToRow(); void ScUnique(); @@ -740,6 +791,9 @@ private: void ScSubTotal(); void ScWrapCols(); void ScWrapRows(); + void ScLambda(); + void ScIsOmitted(); + void ScCall(); private: void ScTextBeforeOrAfter(bool bBefore); @@ -748,6 +802,13 @@ private: void ScWrapColsOrRows(bool bCols); void ScTakeOrDrop(bool bTake); void ScHorizontalOrVerticalStack(bool bHorizontal); + void ScCall(formula::FormulaCallableRef pCallable, sal_uInt8 nArgCount); + void ScCall(formula::FormulaCallableRef pCallable, const std::vector& aArguments); + formula::FormulaTokenRef RefToAbs(formula::FormulaConstTokenRef pToken); +#if HAVE_FEATURE_SCRIPTING + bool BuildMacroArgs(const std::vector& rArgsIn, SbxArrayRef refArgsOut, bool bUseVBAObjects); + bool GetMacroArg(formula::FormulaConstTokenRef pArgIn, SbxVariable* pArgOut, bool bUseVBAObjects); +#endif public: // If upon call rMissingField==true then the database field parameter may be @@ -945,6 +1006,14 @@ public: void ScEMat(); void ScMatRef(); ScMatrixRef MatConcat(const ScMatrixRef& pMat1, const ScMatrixRef& pMat2); + void PutMatrixValue(formula::FormulaConstTokenRef pToken, ScMatrixRef xMatrix, SCSIZE nCol, SCSIZE nRow); + void PutCellIntoMatrix(const ScAddress& rAdr, const ScMatrixRef& xMatrix, SCSIZE nCol, SCSIZE nRow); + void ScByCol(); + void ScByRow(); + void ScMakeArray(); + void ScMap(); + void ScReduce(); + void ScScan(); void ScSumProduct(); void ScSumX2MY2(); void ScSumX2DY2(); @@ -1141,7 +1210,7 @@ public: FormulaError GetError() const { return nGlobalError; } formula::StackVar GetResultType() const { return xResult->GetType(); } const svl::SharedString & GetStringResult() const; - double GetNumResult() const { return xResult->GetDouble(); } + double GetNumResult() const { return static_cast(xResult.get())->GetDouble(); } const formula::FormulaConstTokenRef& GetResultToken() const { return xResult; } SvNumFormatType GetRetFormatType() const { return nRetFmtType; } sal_uLong GetRetFormatIndex() const { return nRetFmtIndex; } diff --git a/sc/source/core/inc/parclass.hxx b/sc/source/core/inc/parclass.hxx index 4b043fd7fef6..7dac43b059bd 100644 --- a/sc/source/core/inc/parclass.hxx +++ b/sc/source/core/inc/parclass.hxx @@ -39,6 +39,7 @@ namespace formula { class FormulaToken; + class FormulaExternalToken; } class ScParameterClassification @@ -63,7 +64,7 @@ public: static bool HasForceArray( OpCode eOp) { return 0 <= static_cast(eOp) && - eOp <= SC_OPCODE_LAST_OPCODE_ID && + eOp <= ocLastOpcodeId && pData[eOp].bHasForceArray; } @@ -98,7 +99,7 @@ private: // ocExternal AddIns static formula::ParamClass GetExternalParameterType( - const formula::FormulaToken* pToken, sal_uInt16 nParameter); + const formula::FormulaExternalToken* pToken, sal_uInt16 nParameter); #if DEBUG_SC_PARCLASSDOC // Generate documentation to stdout if environment variable @@ -125,7 +126,7 @@ private: of parameters is significant. */ static inline sal_uInt8 GetMinimumParameters( OpCode eOp) { - if ( eOp <= SC_OPCODE_LAST_OPCODE_ID ) + if ( eOp <= ocLAST_OPCODE_ID ) return pData[eOp].aData.nParam[0] == formula::ParamClass::Unknown ? 1 : pData[eOp].nMinParams; @@ -135,7 +136,7 @@ private: /** Whether last parameter types are repeated. */ static inline bool HasRepeatParameters( OpCode eOp) { - return eOp <= SC_OPCODE_LAST_OPCODE_ID + return eOp <= ocLAST_OPCODE_ID && pData[eOp].aData.nRepeatLast > 0; } #endif // DEBUG_SC_PARCLASSDOC diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx index 38b49abdeb76..686ccd52c2f9 100644 --- a/sc/source/core/opencl/formulagroupcl.cxx +++ b/sc/source/core/opencl/formulagroupcl.cxx @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -60,9 +61,6 @@ const char* const publicFunc = #include #include #include - -#include - #include using namespace formula; @@ -160,12 +158,12 @@ std::string DebugPeekData(const FormulaToken* ref, int doubleRefIndex = 0) else if (ref->GetType() == formula::svString) { outputstream buf; - buf << "String " << LimitedString( ref->GetString().getString()); + buf << "String " << LimitedString( static_cast(ref)->GetString().getString()); return buf.str(); } else if (ref->GetType() == formula::svDouble) { - return preciseFloat(ref->GetDouble()); + return preciseFloat(static_cast(ref)->GetDouble()); } else { @@ -734,7 +732,7 @@ public: if (GetFormulaToken()->GetType() != formula::svString) throw Unhandled(__FILE__, __LINE__); FormulaToken* Tok = GetFormulaToken(); - ss << GetStringId(Tok->GetString().getData()); + ss << GetStringId(static_cast(Tok)->GetString().getData()); return ss.str(); } virtual std::string GenIsString( bool = false ) const override @@ -752,7 +750,7 @@ public: { throw Unhandled(__FILE__, __LINE__); } - cl_double stringId = GetStringId(ref->GetString().getData()); + cl_double stringId = GetStringId(static_cast(ref)->GetString().getData()); // Pass the scalar result back to the rest of the formula kernel SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno @@ -2369,8 +2367,9 @@ DynamicKernelSoPArguments::DynamicKernelSoPArguments(const ScCalcConfig& config, CASE(ocZTest, std::make_shared()) #undef CASE case ocExternal: + case ocUDExternal: #define EXTCASE( name, createCode ) \ - else if (pChild->GetExternal() == name) \ + else if (static_cast(pChild)->GetExternal() == name) \ { \ mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], createCode, nResultSize)); \ } @@ -2421,7 +2420,7 @@ DynamicKernelSoPArguments::DynamicKernelSoPArguments(const ScCalcConfig& config, EXTCASE("com.sun.star.sheet.addin.Analysis.getYielddisc", std::make_shared()) EXTCASE("com.sun.star.sheet.addin.Analysis.getYieldmat", std::make_shared()) else - throw UnhandledToken(OUString("unhandled external " + pChild->GetExternal()).toUtf8().getStr(), __FILE__, __LINE__); + throw UnhandledToken(OUString("unhandled external " + static_cast(pChild)->GetExternal()).toUtf8().getStr(), __FILE__, __LINE__); break; #undef EXTCASE @@ -2555,12 +2554,11 @@ std::string const & DynamicKernel::GetMD5() { outputstream md5s; // Compute MD5SUM of kernel body to obtain the name - sal_uInt8 result[RTL_DIGEST_LENGTH_MD5]; - rtl_digest_MD5( - mFullProgramSrc.c_str(), - mFullProgramSrc.length(), result, - RTL_DIGEST_LENGTH_MD5); - for (sal_uInt8 i : result) + ::std::vector hash{ + ::comphelper::Hash::calculateHash(mFullProgramSrc.c_str(), + mFullProgramSrc.length(), ::comphelper::HashType::MD5)}; + + for (sal_uInt8 i : hash) { md5s << std::hex << static_cast(i); } diff --git a/sc/source/core/opencl/op_math.cxx b/sc/source/core/opencl/op_math.cxx index 75475bc5f054..e8c850efac8f 100644 --- a/sc/source/core/opencl/op_math.cxx +++ b/sc/source/core/opencl/op_math.cxx @@ -1001,7 +1001,7 @@ void OpCountIf::GenSlidingWindowFunction(outputstream &ss, else if(tmpCur->GetType() == formula::svDouble) { ss << " varb = "; - ss << tmpCur->GetDouble() << ";\n"; + ss << static_cast(tmpCur)->GetDouble() << ";\n"; } } else @@ -1099,7 +1099,7 @@ void OpSumIf::GenSlidingWindowFunction(outputstream &ss, else if(tmpCur->GetType() == formula::svDouble) { ss << " varb = "; - ss << tmpCur->GetDouble() << ";\n"; + ss << static_cast(tmpCur)->GetDouble() << ";\n"; } } else diff --git a/sc/source/core/opencl/opbase.cxx b/sc/source/core/opencl/opbase.cxx index 4ea248daaa3a..47d5135c74da 100644 --- a/sc/source/core/opencl/opbase.cxx +++ b/sc/source/core/opencl/opbase.cxx @@ -265,7 +265,7 @@ void SlidingFunctionBase::GenerateArg( const char* name, int arg, SubArguments& } else if(token->GetType() == formula::svDouble) { - ss << " double " << name << " = " << token->GetDouble() << ";\n"; + ss << " double " << name << " = " << static_cast(token)->GetDouble() << ";\n"; if( generateType == GenerateArgType ) ss << " bool " << name << "_is_string = " << vSubArguments[arg]->GenIsString() << ";\n"; @@ -379,7 +379,7 @@ void SlidingFunctionBase::GenerateRangeArgs( int firstArg, int lastArg, SubArgum else if(token->GetType() == formula::svDouble) { ss << " {\n"; - ss << " double arg = " << token->GetDouble() << ";\n"; + ss << " double arg = " << static_cast(token)->GetDouble() << ";\n"; ss << code; ss << " }\n"; } diff --git a/sc/source/core/opencl/opbase.hxx b/sc/source/core/opencl/opbase.hxx index bfdad82df998..aef448f53add 100644 --- a/sc/source/core/opencl/opbase.hxx +++ b/sc/source/core/opencl/opbase.hxx @@ -284,7 +284,7 @@ public: formula::FormulaToken* Tok = GetFormulaToken(); if (Tok->GetType() != formula::svDouble) throw Unhandled(__FILE__, __LINE__); - return Tok->GetDouble(); + return static_cast(Tok)->GetDouble(); } /// Create buffer and pass the buffer to a given kernel virtual size_t Marshal( cl_kernel k, int argno, int, cl_program ) override diff --git a/sc/source/core/tool/addincol.cxx b/sc/source/core/tool/addincol.cxx index c3b0181a76aa..c0f46e9de948 100644 --- a/sc/source/core/tool/addincol.cxx +++ b/sc/source/core/tool/addincol.cxx @@ -319,7 +319,7 @@ void ScUnoAddInCollection::Initialize() } // ReadConfiguration is called after looking at the AddIn implementations. - // Duplicated are skipped (by using the service information, they don't have to be updated again + // Duplicates are skipped (by using the service information, they don't have to be updated again // when argument information is needed). ReadConfiguration(); @@ -1046,8 +1046,8 @@ static void lcl_UpdateFunctionList( const ScFunctionList& rFunctionList, const S // as used in FillFunctionDescFromData const OUString& aCompare = (bEnglishFunctionNames ? rFuncData.GetUpperEnglish() : rFuncData.GetUpperLocal()); - sal_uLong nCount = rFunctionList.GetCount(); - for (sal_uLong nPos=0; nPosmxFuncName && *pDesc->mxFuncName == aCompare ) diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx index 157d68c5c094..8e30a93823f7 100644 --- a/sc/source/core/tool/address.cxx +++ b/sc/source/core/tool/address.cxx @@ -429,8 +429,9 @@ static const sal_Unicode * lcl_XL_ParseSheetRef( const sal_Unicode* start, TRUE in all other cases, also when there is no index sequence or the input name is not numeric. */ -static bool lcl_XL_getExternalDoc( const sal_Unicode** ppErrRet, OUString& rExternDocName, - const uno::Sequence* pExternalLinks ) +static bool lcl_XL_getExternalDoc(const sal_Unicode** ppErrRet, OUString& rExternDocName, + const uno::Sequence* pExternalLinks, + bool& bMissingPath) { // 1-based, sequence starts with an empty element. if (pExternalLinks && pExternalLinks->hasElements()) @@ -445,6 +446,7 @@ static bool lcl_XL_getExternalDoc( const sal_Unicode** ppErrRet, OUString& rExte switch (rInfo.Type) { case sheet::ExternalLinkType::DOCUMENT : + case sheet::ExternalLinkType::MISSINGDOCUMENT: { OUString aStr; if (!(rInfo.Data >>= aStr)) @@ -457,6 +459,8 @@ static bool lcl_XL_getExternalDoc( const sal_Unicode** ppErrRet, OUString& rExte return false; } rExternDocName = aStr; + if (rInfo.Type == sheet::ExternalLinkType::MISSINGDOCUMENT) + bMissingPath = true; } break; case sheet::ExternalLinkType::SELF : @@ -498,6 +502,7 @@ const sal_Unicode* ScRange::Parse_XL_Header( rExternDocName.clear(); const sal_Unicode* pMsoxlQuoteStop = nullptr; const sal_Unicode* pQuoted3DStop = nullptr; + bool bMissingPath = false; if (*p == '[') { ++p; @@ -523,10 +528,11 @@ const sal_Unicode* ScRange::Parse_XL_Header( ++p; const sal_Unicode* pErrRet = start; - if (!lcl_XL_getExternalDoc( &pErrRet, rExternDocName, pExternalLinks)) + if (!lcl_XL_getExternalDoc(&pErrRet, rExternDocName, pExternalLinks, bMissingPath)) return pErrRet; - rExternDocName = ScGlobal::GetAbsDocName(rExternDocName, rDoc.GetDocumentShell()); + if (!bMissingPath) + rExternDocName = ScGlobal::GetAbsDocName(rExternDocName, rDoc.GetDocumentShell()); } else if (*p == '\'') { @@ -594,7 +600,8 @@ const sal_Unicode* ScRange::Parse_XL_Header( if (nOpen == 0) { const sal_Unicode* pErrRet = start; - if (!lcl_XL_getExternalDoc( &pErrRet, rExternDocName, pExternalLinks)) + if (!lcl_XL_getExternalDoc(&pErrRet, rExternDocName, pExternalLinks, + bMissingPath)) return pErrRet; } } @@ -650,8 +657,11 @@ const sal_Unicode* ScRange::Parse_XL_Header( if (!rExternDocName.isEmpty()) { - ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager(); - pRefMgr->convertToAbsName(rExternDocName); + if (!bMissingPath) + { + ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager(); + pRefMgr->convertToAbsName(rExternDocName); + } } else { diff --git a/sc/source/core/tool/appoptio.cxx b/sc/source/core/tool/appoptio.cxx index 3825ccf8468b..6a5f170dd897 100644 --- a/sc/source/core/tool/appoptio.cxx +++ b/sc/source/core/tool/appoptio.cxx @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -62,11 +62,11 @@ void ScAppOptions::SetDefaults() bDetectiveAuto = true; pLRUList.reset( new sal_uInt16[5] ); // sensible initialization - pLRUList[0] = SC_OPCODE_SUM; - pLRUList[1] = SC_OPCODE_AVERAGE; - pLRUList[2] = SC_OPCODE_MIN; - pLRUList[3] = SC_OPCODE_MAX; - pLRUList[4] = SC_OPCODE_IF; + pLRUList[0] = ocSum; + pLRUList[1] = ocAverage; + pLRUList[2] = ocMin; + pLRUList[3] = ocMax; + pLRUList[4] = ocIf; nLRUFuncCount = 5; nTrackContentColor = COL_TRANSPARENT; diff --git a/sc/source/core/tool/callable.cxx b/sc/source/core/tool/callable.cxx new file mode 100644 index 000000000000..fabb939c705e --- /dev/null +++ b/sc/source/core/tool/callable.cxx @@ -0,0 +1,283 @@ +/* -*- 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 + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +ScMacroFunction::ScMacroFunction(const ScInterpreter& rInterpreter, const OUString& aMacro) + : formula::FormulaCallable() + , mnError(FormulaError::NONE) + , mpDocShell(rInterpreter.mrDoc.GetDocumentShell()) + , mpMethod(nullptr) + , mpModule(nullptr) + , mbInvalid(false) +{ +#if !HAVE_FEATURE_SCRIPTING + (void)rInterpreter; + (void)aMacro; + mbInvalid = true; // without DocShell no CallBasic +#else + SbxBase::ResetError(); + + if (!mpDocShell) + { + mbInvalid = true; // without DocShell no CallBasic + return; + } + + // The macro security prompt is not raised here. CallBasic checks it when + // the macro actually runs. + + // Find the Basic method by name, then keep the library and macro name + // strings that CallBasic needs to invoke it. + + StarBASIC* pRoot; + + try + { + pRoot = mpDocShell->GetBasic(); + } + catch (...) + { + pRoot = nullptr; + } + + SbxVariable* pVar = pRoot ? pRoot->Find(aMacro, SbxClassType::Method) : nullptr; + if (!pVar || pVar->GetType() == SbxVOID) + { + mbInvalid = true; + mnError = FormulaError::NoMacro; + return; + } + mpMethod = dynamic_cast(pVar); + if (!mpMethod) + { + mbInvalid = true; + mnError = FormulaError::NoMacro; + return; + } + mpModule = mpMethod->GetModule(); + if (!mpModule) + { + mbInvalid = true; + mnError = FormulaError::NoMacro; + return; + } + + bool bUseVBAObjects = mpModule->IsVBASupport(); + SbxObject* pObject = mpModule->GetParent(); + assert(pObject); + OSL_ENSURE(dynamic_cast(pObject) != nullptr, "No Basic found!"); + maMacroStr = pObject->GetName() + "." + mpModule->GetName() + "." + mpMethod->GetName(); + if (pRoot && bUseVBAObjects) + { + // just here to make sure the VBA objects are initialized when we run the macro during ODF import + pRoot->getVBAGlobals(); + } + if (pObject->GetParent()) + maBasicStr = pObject->GetParent()->GetName(); // document BASIC + else + maBasicStr = SfxGetpApp()->GetName(); // application BASIC +#endif +} + +/// clone a contiguous subset of the (RPN) tokens into a new array +static void lcl_CloneSubarray(const ScTokenArray& rTokensIn, short nStartPos, short nEndPos, + ScTokenArray& rTokensOut) +{ + const short nOffset = nStartPos + 1; + // An empty or inverted span has no body to clone, so return an empty output + // rather than computing a negative length. + if (nEndPos <= nOffset) + return; + + const short nLen = nEndPos - nOffset; + // Start every slot empty so a run that clones fewer tokens than nLen never + // hands an uninitialized pointer to the new array. + std::vector aResult(nLen, nullptr); + short nCount = 0; + formula::FormulaTokenArrayPlainIterator aIter(rTokensIn); + aIter.Jump(nOffset); + for (const formula::FormulaToken* pToken = aIter.NextRPN(); + aIter.GetIndex() <= nEndPos && pToken && nCount < nLen; pToken = aIter.NextRPN()) + { + formula::FormulaToken* pNewToken = pToken->Clone(); + pNewToken->IncRef(); + aResult[nCount++] = pNewToken; + auto pJumpToken = dynamic_cast(pNewToken); + if (pJumpToken) + { + // adjust jumps to match new locations + short* pJump = pJumpToken->GetJump(); + short nJumpCount = pJump[0]; + for (short nJump = 1; nJump <= nJumpCount; ++nJump) + pJump[nJump] -= nOffset; + } + } + // Hand over only the tokens actually cloned. + rTokensOut.CreateNewRPNArrayFromData(aResult.data(), nCount); +} + +/// find all the locations where the specified variable would have to be substituted +static std::forward_list lcl_FindReplacementPositions(std::u16string_view aStrName, + const ScTokenArray& rTokens, + short nEntryPoint) +{ + std::forward_list aPositions; + formula::FormulaTokenIterator aIter(rTokens); + std::queue aStartPoints; + aStartPoints.push(nEntryPoint); + + while (!aStartPoints.empty()) + { + { + short nStartPoint = aStartPoints.front(); + aStartPoints.pop(); + aIter.Jump(nStartPoint, SHRT_MAX, SHRT_MAX); + } + while (!aIter.IsEndOfPath()) + { + const formula::FormulaToken* pToken = aIter.Next(); + auto pStringNameToken = formula::GetStringNameToken(pToken); + if (pStringNameToken) + { + short nNextOp = aIter.GetPC() + 1; + if (!(nNextOp < rTokens.GetCodeLen() + && rTokens.GetCode()[nNextOp]->GetOpCode() == ocLet)) + { + if (pStringNameToken->GetString().getString().equalsIgnoreAsciiCase(aStrName)) + aPositions.push_front(aIter.GetPC()); + } + } + else + { + auto pJumpToken = dynamic_cast(pToken); + if (pJumpToken) + { + const short* pJump = pJumpToken->GetJump(); + short nJumpCount = pJump[0]; + switch (pJumpToken->GetOpCode()) + { + case ocLet: + { + aStartPoints.push(pJump[1]); + auto pSubToken + = formula::GetStringNameToken(rTokens.GetCode()[aIter.GetPC() - 1]); + if (!(pSubToken + && pSubToken->GetString().getString().equalsIgnoreAsciiCase( + aStrName))) + { + bool bFound = false; + for (short nJump = 2; nJump < nJumpCount - 1; nJump += 2) + { + aStartPoints.push(pJump[nJump + 1]); + pSubToken = formula::GetStringNameToken( + rTokens.GetCode()[pJump[nJump] + 1]); + if (pSubToken + && pSubToken->GetString().getString().equalsIgnoreAsciiCase( + aStrName)) + { + // this name shadows the one we're looking for, after this point + bFound = true; + break; + } + } + if (!bFound) + aStartPoints.push(pJump[nJumpCount - 1]); + } + } + break; + case ocLambda: + { + bool bFound = false; + for (short nJump = 1; nJump < nJumpCount - 1; ++nJump) + { + auto pSubToken = formula::GetStringNameToken( + rTokens.GetCode()[pJump[nJump] + 1]); + if (pSubToken + && pSubToken->GetString().getString().equalsIgnoreAsciiCase( + aStrName)) + { + // this name shadows the one we're looking for, in the body + bFound = true; + break; + } + } + if (!bFound) + aStartPoints.push(pJump[nJumpCount - 1]); + } + break; + default: // nothing else affects local variables + { + for (short nJump = 1; nJump < nJumpCount; ++nJump) + aStartPoints.push(pJump[nJump]); + } + break; + } + aIter.Jump(pJump[nJumpCount], SHRT_MAX, SHRT_MAX); + } // pJumpToken + } // !pStringNameToken + } // !aIter.IsEndOfPath() + } // !aStartPoints.empty() + + return aPositions; +} + +ScFormulaFunction::ScFormulaFunction(const ScInterpreter& rInterpreter, + const std::vector& rParams, short nRequiredParams, + const ScTokenArray& rTokens, short nBodyStart, short nBodyEnd) + : formula::FormulaCallable() + , mpDoc(&rInterpreter.mrDoc) + , maPos(rInterpreter.aPos) + , mpCell(rInterpreter.mrDoc.GetFormulaCell(rInterpreter.aPos)) + , mpContext(&rInterpreter.mrContext) + , maLambdaBody(rInterpreter.mrDoc) + , maReplacementPositions(rParams.size()) + , mnRequiredParams(nRequiredParams) +{ + lcl_CloneSubarray(rTokens, nBodyStart, nBodyEnd, maLambdaBody); + + // figure out right now where the names will need to be replaced, as an optimization + for (std::vector::size_type nParam = 0; nParam < rParams.size(); ++nParam) + maReplacementPositions[nParam] + = lcl_FindReplacementPositions(rParams[nParam], maLambdaBody, -1); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/tool/cellform.cxx b/sc/source/core/tool/cellform.cxx index c598d0dad509..dcb474bff05a 100644 --- a/sc/source/core/tool/cellform.cxx +++ b/sc/source/core/tool/cellform.cxx @@ -105,6 +105,13 @@ OUString ScCellFormat::GetString( const ScRefCellValue& rCell, sal_uInt32 nForma return str; } } + else if ( pFCell->IsCallable() ) + { + // TODO: Consider showing more information than just a bare lambda + // callables can't be represented visually, so we'll just use a placeholder + // U+03BB GREEK SMALL LETTER LAMBDA. + return u"\u03BB"_ustr; + } else { OUString str; diff --git a/sc/source/core/tool/chartarr.cxx b/sc/source/core/tool/chartarr.cxx index 1b475ff67777..4ecf3c7aa181 100644 --- a/sc/source/core/tool/chartarr.cxx +++ b/sc/source/core/tool/chartarr.cxx @@ -290,7 +290,7 @@ std::unique_ptr ScChartArray::CreateMemChartMulti() SCSIZE nCol = 0; SCSIZE nRow = 0; bool bCalcAsShown = rDocument.GetDocOptions().IsCalcAsShown(); - sal_uLong nIndex = 0; + sal_uInt64 nIndex = 0; if (bValidData) { for ( nCol = 0; nCol < nColCount; nCol++ ) diff --git a/sc/source/core/tool/chartlis.cxx b/sc/source/core/tool/chartlis.cxx index 91477b2407c7..c76602a73b22 100644 --- a/sc/source/core/tool/chartlis.cxx +++ b/sc/source/core/tool/chartlis.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include using namespace com::sun::star; @@ -211,7 +212,7 @@ public: bool bExternal = ScRefTokenHelper::isExternalRef(pToken); if (bExternal) { - sal_uInt16 nFileId = pToken->GetIndex(); + sal_uInt16 nFileId = static_cast(pToken.get())->GetFileId(); ScExternalRefManager* pRefMgr = mrDoc.GetExternalRefManager(); ScChartListener::ExternalRefListener* pExtRefListener = mrParent.GetExtRefListener(); if (mbStart) diff --git a/sc/source/core/tool/chgtrack.cxx b/sc/source/core/tool/chgtrack.cxx index ab18add226a2..e34c50bf7ac8 100644 --- a/sc/source/core/tool/chgtrack.cxx +++ b/sc/source/core/tool/chgtrack.cxx @@ -1800,7 +1800,7 @@ void ScChangeActionContent::PutValueToDoc( static void lcl_InvalidateReference( const ScDocument& rDoc, formula::FormulaToken& rTok, const ScBigAddress& rPos ) { - ScSingleRefData& rRef1 = *rTok.GetSingleRef(); + ScSingleRefData& rRef1 = static_cast(rTok).GetSingleRef(); if ( rPos.Col() < 0 || rDoc.MaxCol() < rPos.Col() ) { rRef1.SetColDeleted( true ); @@ -1816,7 +1816,7 @@ static void lcl_InvalidateReference( const ScDocument& rDoc, formula::FormulaTok if ( rTok.GetType() != formula::svDoubleRef ) return; - ScSingleRefData& rRef2 = rTok.GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(rTok).GetDoubleRef().Ref2; if ( rPos.Col() < 0 || rDoc.MaxCol() < rPos.Col() ) { rRef2.SetColDeleted( true ); @@ -2315,10 +2315,12 @@ void ScChangeTrack::MasterLinks( ScChangeAction* pAppend ) } } -void ScChangeTrack::AppendLoaded( std::unique_ptr pActionParam ) +bool ScChangeTrack::AppendLoaded( std::unique_ptr pActionParam ) { + auto [it, inserted] = aMap.insert(std::make_pair(pActionParam->GetActionNumber(), pActionParam.get())); + if (!inserted) + return false; ScChangeAction* pAppend = pActionParam.release(); - aMap.insert( ::std::make_pair( pAppend->GetActionNumber(), pAppend ) ); if ( !pLast ) pFirst = pLast = pAppend; else @@ -2328,6 +2330,7 @@ void ScChangeTrack::AppendLoaded( std::unique_ptr pActionParam ) pLast = pAppend; } MasterLinks( pAppend ); + return true; } void ScChangeTrack::Append( ScChangeAction* pAppend, sal_uLong nAction ) @@ -2698,12 +2701,12 @@ void ScChangeTrack::AppendContentRange( const ScRange& rRange, aPos.SetTab( nTab ); // AppendContent() is a no-op if both cells are empty. SCCOL lastCol = std::max( rRefDoc.ClampToAllocatedColumns( nTab, nCol2 ), - rRefDoc.ClampToAllocatedColumns( nTab, nCol2 )); + rDoc.ClampToAllocatedColumns( nTab, nCol2 )); for ( SCCOL nCol = nCol1; nCol <= lastCol; nCol++ ) { aPos.SetCol( nCol ); SCROW lastRow = std::max( rRefDoc.GetLastDataRow( nTab, nCol, nCol, nRow2 ), - rRefDoc.GetLastDataRow( nTab, nCol, nCol, nRow2 )); + rDoc.GetLastDataRow( nTab, nCol, nCol, nRow2 )); for ( SCROW nRow = nRow1; nRow <= lastRow; nRow++ ) { aPos.SetRow( nRow ); diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 5a758993234b..a26d0b7e48b9 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -77,6 +77,7 @@ #include #include #include +#include using namespace formula; using namespace ::com::sun::star; @@ -140,7 +141,8 @@ constexpr std::array makeCommonCharTable() a['='] = ScCharFlags::Char | ScCharFlags::Bool | ScCharFlags::WordSep | ScCharFlags::ValueSep; a['>'] = ScCharFlags::CharBool | ScCharFlags::Bool | ScCharFlags::WordSep | ScCharFlags::ValueSep; a['?'] = ScCharFlags::CharWord | ScCharFlags::Word | ScCharFlags::Name; - /* @ */ // FREE + // @ is the prefix operator that opts a formula out of auto-spill. + a['@'] = ScCharFlags::Char | ScCharFlags::WordSep | ScCharFlags::ValueSep; for (int i = 'A'; i <= 'Z'; i++) a[i] = ScCharFlags::CharWord | ScCharFlags::Word | ScCharFlags::CharIdent | ScCharFlags::Ident | ScCharFlags::CharName | ScCharFlags::Name; @@ -210,7 +212,8 @@ constexpr std::array makeCharTable_XL() a['='] |= ScCharFlags::Word; a['>'] |= ScCharFlags::Word; /* ? */ // question really is not permitted in sheet name - a['@'] |= ScCharFlags::Word; + // @ stays an operator in the XL grammar too. Sheet names that contain + // @ have to be quoted. a['['] = ScCharFlags::Word; a[']'] = ScCharFlags::Word; a['{'] |= ScCharFlags::Word; @@ -1039,12 +1042,17 @@ struct ConventionOOO_A1 : public Convention_A1 rBuffer.append('.'); } - if (!rRef.IsColRel()) - rBuffer.append('$'); - MakeColStr( rLimits, rBuffer, aAbsRef.Col()); - if (!rRef.IsRowRel()) - rBuffer.append('$'); - MakeRowStr( rLimits, rBuffer, aAbsRef.Row()); + if (!rRef.IsColRel() && !rRef.IsRowRel() && rRef.IsColDeleted() && rRef.IsRowDeleted()) + rBuffer.append("#REF!"); + else + { + if (!rRef.IsColRel()) + rBuffer.append('$'); + MakeColStr(rLimits, rBuffer, aAbsRef.Col()); + if (!rRef.IsRowRel()) + rBuffer.append('$'); + MakeRowStr(rLimits, rBuffer, aAbsRef.Row()); + } return true; } @@ -1368,12 +1376,17 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL static void makeSingleCellStr( const ScSheetLimits& rLimits, OUStringBuffer& rBuf, const ScSingleRefData& rRef, const ScAddress& rAbs ) { - if (!rRef.IsColRel()) - rBuf.append('$'); - MakeColStr(rLimits, rBuf, rAbs.Col()); - if (!rRef.IsRowRel()) - rBuf.append('$'); - MakeRowStr(rLimits, rBuf, rAbs.Row()); + if (!rRef.IsColRel() && !rRef.IsRowRel() && rRef.IsColDeleted() && rRef.IsRowDeleted()) + rBuf.append("#REF!"); + else + { + if (!rRef.IsColRel()) + rBuf.append('$'); + MakeColStr(rLimits, rBuf, rAbs.Col()); + if (!rRef.IsRowRel()) + rBuf.append('$'); + MakeRowStr(rLimits, rBuf, rAbs.Row()); + } } virtual void makeRefStr( @@ -1434,14 +1447,22 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL } } - makeSingleCellStr(rLimits, rBuf, aRef.Ref1, aAbs1); + OUStringBuffer aBuf; + + makeSingleCellStr(rLimits, aBuf, aRef.Ref1, aAbs1); if (!bSingleRef && (aAbs1.Row() != aAbs2.Row() || aRef.Ref1.IsRowRel() != aRef.Ref2.IsRowRel() || aAbs1.Col() != aAbs2.Col() || aRef.Ref1.IsColRel() != aRef.Ref2.IsColRel())) { - rBuf.append( ':' ); - makeSingleCellStr(rLimits, rBuf, aRef.Ref2, aAbs2); + aBuf.append( ':' ); + makeSingleCellStr(rLimits, aBuf, aRef.Ref2, aAbs2); } + + OUString sErrRef = "#REF!"; + if (aBuf.indexOf(sErrRef) == -1) + rBuf.append(aBuf); + else + rBuf.append(sErrRef); } virtual ParseResult parseAnyToken( const OUString& rFormula, @@ -1459,7 +1480,7 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL KParseTokens::ASC_UNDERSCORE | KParseTokens::ASC_DOLLAR; constexpr sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT; // '?' allowed in range names - static constexpr OUString aAddAllowed(u"?!"_ustr); + static constexpr OUString aAddAllowed(u"?!#"_ustr); return pCharClass->parseAnyToken( rFormula, nSrcPos, nStartFlags, aAddAllowed, (bGroupSeparator ? nContFlags | KParseTokens::GROUP_SEPARATOR_IN_NUMBER_3 : nContFlags), @@ -1514,12 +1535,20 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL ConventionXL::makeExternalTabNameRange(rBuffer, rTabName, rTabNames, aAbsRef); rBuffer.append('!'); - makeSingleCellStr(rLimits, rBuffer, rRef.Ref1, aAbsRef.aStart); + OUStringBuffer aBuf; + + makeSingleCellStr(rLimits, aBuf, rRef.Ref1, aAbsRef.aStart); if (aAbsRef.aStart != aAbsRef.aEnd) { - rBuffer.append(':'); - makeSingleCellStr(rLimits, rBuffer, rRef.Ref2, aAbsRef.aEnd); + aBuf.append(':'); + makeSingleCellStr(rLimits, aBuf, rRef.Ref2, aAbsRef.aEnd); } + + OUString sErrRef = "#REF!"; + if (aBuf.indexOf(sErrRef) == -1) + rBuffer.append(aBuf); + else + rBuffer.append(sErrRef); } }; @@ -1683,13 +1712,20 @@ struct ConventionXL_OOX : public ConventionXL_A1 rBuffer.append( aBuf); } rBuffer.append('!'); + aBuf.setLength(0); - makeSingleCellStr(rLimits, rBuffer, rRef.Ref1, aAbsRef.aStart); + makeSingleCellStr(rLimits, aBuf, rRef.Ref1, aAbsRef.aStart); if (aAbsRef.aStart != aAbsRef.aEnd) { - rBuffer.append(':'); - makeSingleCellStr(rLimits, rBuffer, rRef.Ref2, aAbsRef.aEnd); + aBuf.append(':'); + makeSingleCellStr(rLimits, aBuf, rRef.Ref2, aAbsRef.aEnd); } + + OUString sErrRef = "#REF!"; + if (aBuf.indexOf(sErrRef) == -1) + rBuffer.append(aBuf); + else + rBuffer.append(sErrRef); } static void makeExternalDocStr( OUStringBuffer& rBuffer, sal_uInt16 nFileId ) @@ -2072,9 +2108,10 @@ void ScCompiler::CheckTabQuotes( OUString& rString, sal_Int32 nContFlags = nStartFlags | KParseTokens::ANY_NUMBER; ParseResult aRes = ScGlobal::getCharClass().parsePredefinedToken( KParseType::IDENTNAME, rString, 0, nStartFlags, OUString(), nContFlags, OUString()); + bool bKeyWord = (rString == "FALSE" || rString == "TRUE"); bool bNeedsQuote = (!((aRes.TokenType & KParseType::IDENTNAME) && aRes.EndPos == rString.getLength()) - || lcl_TabContainsReference(rString)); + || lcl_TabContainsReference(rString) || bKeyWord); switch ( eConv ) { @@ -2193,8 +2230,8 @@ void ScCompiler::SetRefConvention( const ScCompiler::Convention *pConvP ) void ScCompiler::SetError(FormulaError nError) { - if( pArr->GetCodeError() == FormulaError::NONE) - pArr->SetCodeError( nError); + if( mpArr->GetCodeError() == FormulaError::NONE) + mpArr->SetCodeError( nError); } static sal_Unicode* lcl_UnicodeStrNCpy( sal_Unicode* pDst, const sal_Unicode* pSrc, sal_Int32 nMax ) @@ -2344,7 +2381,7 @@ Label_MaskStateMachine: case ssGetChar : { // Order is important! - if (eLastOp == ocTableRefOpen && c != '[' && c != '#' && c != ']') + if (meLastOp == ocTableRefOpen && c != '[' && c != '#' && c != ']') { *pSym++ = c; eState = ssGetTableRefColumn; @@ -2408,7 +2445,7 @@ Label_MaskStateMachine: // entirely, or can be ocTableRefOpen, of which the first // transforms an ocDBArea into an ocTableRef. if (c == '[' && FormulaGrammar::isExcelSyntax( meGrammar) - && eLastOp != ocDBArea && maTableRefs.empty()) + && meLastOp != ocDBArea && maTableRefs.empty()) { // [0]!Global_Range_Name, is a special case in OOXML // syntax, where the '0' is referencing to self and we @@ -3034,8 +3071,8 @@ Label_MaskStateMachine: *--pSym = 0; --nSrcPos; } - if ( bAutoCorrect ) - aCorrectedSymbol = OUString(cSymbol, pSym - cSymbol); + if ( mbAutoCorrect ) + maCorrectedSymbol = OUString(cSymbol, pSym - cSymbol); if (bAutoIntersection && vSpaces[nAutoIntersectionSpacesPos].nCount > 1) --vSpaces[nAutoIntersectionSpacesPos].nCount; // replace '!!' with only one space return vSpaces; @@ -3045,7 +3082,13 @@ Label_MaskStateMachine: bool ScCompiler::ParseOpCode( const OUString& rName, bool bInArray ) { - OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap().find( rName)); + OUString aName( rName ); + // A built-in function passed as a value, rather than called in place, is + // written with the _xleta. prefix in OOXML. Strip it so the plain function + // name resolves. + if (mxSymbols->isOOXML() && rName.startsWithIgnoreAsciiCase(u"_xleta.")) + aName = rName.copy(7); + OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap().find( aName)); bool bFound = (iLook != mxSymbols->getHashMap().end()); if (bFound) { @@ -3180,12 +3223,14 @@ bool ScCompiler::ParseOpCode( const OUString& rName, bool bInArray ) if (!bFound) { - OUString aIntName; + OUString aIntName, aFuncName = rName, sUDPrefix = mxSymbols->getSymbol(ocUDExternal); + if (aFuncName.matchIgnoreAsciiCase(sUDPrefix)) + aFuncName = aFuncName.copy(sUDPrefix.getLength()); + if (mxSymbols->hasExternals()) { // If symbols are set by filters get mapping to exact name. - ExternalHashMap::const_iterator iExt( - mxSymbols->getExternalHashMap().find( rName)); + ExternalHashMap::const_iterator iExt(mxSymbols->getExternalHashMap().find(aFuncName)); if (iExt != mxSymbols->getExternalHashMap().end()) { if (ScGlobal::GetAddInCollection()->GetFuncData( (*iExt).second)) @@ -3202,25 +3247,29 @@ bool ScCompiler::ParseOpCode( const OUString& rName, bool bInArray ) else // bLocalFirst=false for (English) upper full original name // (service.function) - aIntName = ScGlobal::GetAddInCollection()->FindFunction( - rName, !mxSymbols->isEnglish()); + aIntName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, + !mxSymbols->isEnglish()); } if (!aIntName.isEmpty()) { maRawToken.SetExternal( aIntName ); // international name bFound = true; } + else if (rName != aFuncName) + { + // User-defined function + maRawToken.SetExternal(aFuncName, ocUDExternal); + bFound = true; + } } if (!bFound) return false; OpCode eOp = maRawToken.GetOpCode(); if (eOp == ocSub || eOp == ocNegSub) { - bool bShouldBeNegSub = - (eLastOp == ocOpen || eLastOp == ocSep || eLastOp == ocNegSub || - (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_BIN_OP) || - eLastOp == ocArrayOpen || - eLastOp == ocArrayColSep || eLastOp == ocArrayRowSep); + bool bShouldBeNegSub = (meLastOp == ocOpen || meLastOp == ocSep || meLastOp == ocNegSub + || isBinaryOperatorOpCode(meLastOp) || meLastOp == ocArrayOpen + || meLastOp == ocArrayColSep || meLastOp == ocArrayRowSep); if (bShouldBeNegSub && eOp == ocSub) maRawToken.NewOpCode( ocNegSub ); //TODO: if ocNegSub had ForceArray we'd have to set it here @@ -3233,7 +3282,7 @@ bool ScCompiler::ParseOpCode( const OUString& rName, bool bInArray ) bool ScCompiler::ParseOpCode2( std::u16string_view rName ) { // If we have Pivot Table field names, means we are parsing a pivot table - // calculation field, which are not support any OpCode2 tokens, only there + // calculation field, which do not support any OpCode2 tokens, only their // own field names. if (!maPivotFieldNames.empty()) return false; @@ -3259,7 +3308,7 @@ static bool lcl_ParenthesisFollows( const sal_Unicode* p ) return *p == '('; } -bool ScCompiler::ParseValue( const OUString& rSym ) +bool ScCompiler::ParseValue(const OUString& rSym, bool bInArray) { const sal_Int32 nFormulaLanguage = FormulaGrammar::extractFormulaLanguage( GetGrammar()); if (nFormulaLanguage == css::sheet::FormulaLanguage::ODFF || nFormulaLanguage == css::sheet::FormulaLanguage::OOXML) @@ -3288,9 +3337,12 @@ bool ScCompiler::ParseValue( const OUString& rSym ) if (eOpFunc != ocNone) { maRawToken.SetOpCode(eOpFunc); - // add missing trailing parentheses - maPendingOpCodes.push(ocOpen); - maPendingOpCodes.push(ocClose); + if (!bInArray) + { + // add missing trailing parentheses + maPendingOpCodes.push(ocOpen); + maPendingOpCodes.push(ocClose); + } return true; } return false; @@ -3318,6 +3370,27 @@ bool ScCompiler::ParseValue( const OUString& rSym ) return true; } + // Compile bare TRUE / FALSE as the ocTrue / ocFalse function + // call so the interpreter pushes a typed double tagged LOGICAL. + // Inside an inline array, leave the bare opcode for MergeArray + // to consume as element_boolean. + OpCode eBooleanOp = ocNone; + if (rSym.equalsIgnoreAsciiCase("TRUE")) + eBooleanOp = ocTrue; + else if (rSym.equalsIgnoreAsciiCase("FALSE")) + eBooleanOp = ocFalse; + if (eBooleanOp != ocNone + && !lcl_ParenthesisFollows(aFormula.getStr() + nSrcPos)) + { + maRawToken.SetOpCode(eBooleanOp); + if (!bInArray) + { + maPendingOpCodes.push(ocOpen); + maPendingOpCodes.push(ocClose); + } + return true; + } + double fVal; sal_uInt32 nIndex = mxSymbols->isEnglishLocale() ? mrInterpreterContext.NFGetStandardIndex(LANGUAGE_ENGLISH_US) : 0; @@ -3347,7 +3420,7 @@ bool ScCompiler::ParseValue( const OUString& rSym ) return true; } -bool ScCompiler::ParseString() +bool ScCompiler::ParseLiteralString() { if ( cSymbol[0] != '"' ) return false; @@ -3504,8 +3577,10 @@ bool ScCompiler::ParseSingleReference( const OUString& rName, const OUString* pE { // Valid given tab and invalid col or row may indicate a sheet-local // named expression, bail out early and don't create a reference token. - if (!(nFlags & ScRefFlags::VALID) && mnCurrentSheetEndPos > 0 && - (nFlags & ScRefFlags::TAB_VALID) && (nFlags & ScRefFlags::TAB_3D)) + bool bErrRef = (rName.subView(mnCurrentSheetEndPos) == mxSymbols->getSymbol(ocErrRef)); + + if (!(nFlags & ScRefFlags::VALID) && mnCurrentSheetEndPos > 0 + && (nFlags & ScRefFlags::TAB_VALID) && (nFlags & ScRefFlags::TAB_3D) && !bErrRef) { if (aExtInfo.mbExternal) { @@ -3534,8 +3609,8 @@ bool ScCompiler::ParseSingleReference( const OUString& rName, const OUString* pE ScSingleRefData aRef; aRef.InitAddress( aAddr ); - aRef.SetColRel( (nFlags & ScRefFlags::COL_ABS) == ScRefFlags::ZERO ); - aRef.SetRowRel( (nFlags & ScRefFlags::ROW_ABS) == ScRefFlags::ZERO ); + aRef.SetColRel(((nFlags & ScRefFlags::COL_ABS) == ScRefFlags::ZERO) && !bErrRef); + aRef.SetRowRel(((nFlags & ScRefFlags::ROW_ABS) == ScRefFlags::ZERO) && !bErrRef); aRef.SetTabRel( (nFlags & ScRefFlags::TAB_ABS) == ScRefFlags::ZERO ); aRef.SetFlag3D( ( nFlags & ScRefFlags::TAB_3D ) != ScRefFlags::ZERO ); // the reference is really invalid @@ -3750,7 +3825,7 @@ bool ScCompiler::ParseMacro( const OUString& rName ) const ScRangeData* ScCompiler::GetRangeData( SCTAB& rSheet, const OUString& rUpperName ) const { - // try local names first + // try sheet names first rSheet = aPos.Tab(); const ScRangeName* pRangeName = rDoc.GetRangeName(rSheet); const ScRangeData* pData = nullptr; @@ -3758,9 +3833,8 @@ const ScRangeData* ScCompiler::GetRangeData( SCTAB& rSheet, const OUString& rUpp pData = pRangeName->findByUpperName(rUpperName); if (!pData) { - pRangeName = rDoc.GetRangeName(); - if (pRangeName) - pData = pRangeName->findByUpperName(rUpperName); + pRangeName = &rDoc.GetRangeName(); + pData = pRangeName->findByUpperName(rUpperName); if (pData) rSheet = -1; } @@ -3769,8 +3843,8 @@ const ScRangeData* ScCompiler::GetRangeData( SCTAB& rSheet, const OUString& rUpp bool ScCompiler::HasPossibleNamedRangeConflict( SCTAB nTab ) const { - const ScRangeName* pRangeName = rDoc.GetRangeName(); - if (pRangeName && pRangeName->hasPossibleAddressConflict()) + const ScRangeName* pRangeName = &rDoc.GetRangeName(); + if (pRangeName->hasPossibleAddressConflict()) return true; pRangeName = rDoc.GetRangeName(nTab); if (pRangeName && pRangeName->hasPossibleAddressConflict()) @@ -3782,7 +3856,7 @@ bool ScCompiler::ParseNamedRange( const OUString& rUpperName, bool onlyCheck ) { // ParseNamedRange is called only from NextNewToken, with an upper-case string // If we have Pivot Table field names, means we are parsing a pivot table - // calculation field, which are not support any name based tokens, only there + // calculation field, which do not support any name-based tokens, only their // own field names. if (!maPivotFieldNames.empty()) return false; @@ -3816,24 +3890,68 @@ bool ScCompiler::ParseNamedRange( const OUString& rUpperName, bool onlyCheck ) return false; } -bool ScCompiler::ParseLambdaFuncName( const OUString& aOrg ) +bool ScCompiler::ParseLocalName( const OUString& aOrg ) { - if (m_aLambda.bInLambdaFunction && !aOrg.isEmpty()) + if (!maBindings.empty() && !aOrg.isEmpty()) { OUString aName = aOrg; + // A required parameter carries the _xlpm. prefix and an optional one + // the _xlop. prefix. The body always uses the _xlpm. prefix. Strip + // either so the declaration and body share the bare name, and note if + // the parameter is optional. + bool bOptional = false; if (aOrg.startsWithIgnoreAsciiCase(u"_xlpm.")) aName = aName.copy(6); - - if (m_aLambda.nParaPos % 2 == 1 && m_aLambda.nParaCount > m_aLambda.nParaPos) - m_aLambda.aNameSet.insert(aName); - else + else if (aOrg.startsWithIgnoreAsciiCase(u"_xlop.")) { - // should already exist the name - if (m_aLambda.aNameSet.find(aName) == m_aLambda.aNameSet.end()) + aName = aName.copy(6); + bOptional = true; + } + + bool bSearch = true; + if (mIsInBinding) + { + switch (maBindings.front().eOpCode) + { + case ocLet: + bSearch = (maBindings.front().nParaPos % 2 == 0 || maBindings.front().nParaPos == maBindings.front().nParaCount); + break; + case ocLambda: + bSearch = (maBindings.front().nParaPos == maBindings.front().nParaCount); + break; + default: + SAL_WARN( "sc.core", "OpCode: " << +maBindings.front().eOpCode); + assert(!"ScCompiler::ParseLocalName: someone forgot to add an OpCode case"); + } + } + + // Match local names without regard to case, like other Calc names. The + // token keeps the original spelling, while the binding layers are keyed + // on the upper-cased form. + OUString aKey = aName.toAsciiUpperCase(); + + if (bSearch) + { + // the name should already exist in (at least) one of the layers + auto aEnd = maBindings.end(); + bool bFound = false; + for (auto aIter = maBindings.begin(); aIter != aEnd; ++aIter) + { + if ( aIter->aNameSet.find(aKey) != aIter->aNameSet.end() ) + { + bFound = true; + break; + } + } + if (!bFound) return false; } + else + maBindings.front().aNameSet.insert(aKey); + svl::SharedString aSS = rDoc.GetSharedStringPool().intern(aName); maRawToken.SetStringName(aSS.getData(), aSS.getDataIgnoreCase()); + mbOptionalLocalName = bOptional; return true; } return false; @@ -3850,7 +3968,7 @@ bool ScCompiler::ParseExternalNamedRange( const OUString& rSymbol, bool& rbInval rbInvalidExternalNameRange = false; // If we have Pivot Table field names, means we are parsing a pivot table - // calculation field, which are not support any name based tokens, only there + // calculation field, which do not support any name-based tokens, only their // own field names. if (!maPivotFieldNames.empty()) return false; @@ -3862,13 +3980,15 @@ bool ScCompiler::ParseExternalNamedRange( const OUString& rSymbol, bool& rbInval if (!pConv->parseExternalName( rSymbol, aFile, aName, rDoc, &maExternalLinks)) return false; + // Remove the user-defined flag + OUString sUDPrefix = mxSymbols->getSymbol(ocUDExternal); + if (aName.matchIgnoreAsciiCase(sUDPrefix)) + aName = aName.copy(sUDPrefix.getLength()); + if (aFile.getLength() > MAXSTRLEN || aName.getLength() > MAXSTRLEN) return false; ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager(); - OUString aTmp = aFile; - pRefMgr->convertToAbsName(aTmp); - aFile = aTmp; sal_uInt16 nFileId = pRefMgr->getExternalFileId(aFile); if (!pRefMgr->isValidRangeName(nFileId, aName)) { @@ -3878,7 +3998,7 @@ bool ScCompiler::ParseExternalNamedRange( const OUString& rSymbol, bool& rbInval } const OUString* pRealName = pRefMgr->getRealRangeName(nFileId, aName); - maRawToken.SetExternalName(nFileId, pRealName ? *pRealName : aTmp); + maRawToken.SetExternalName(nFileId, pRealName ? *pRealName : aFile); maExternalFiles.push_back(nFileId); return true; } @@ -3886,7 +4006,7 @@ bool ScCompiler::ParseExternalNamedRange( const OUString& rSymbol, bool& rbInval bool ScCompiler::ParseDBRange( const OUString& rName ) { // If we have Pivot Table field names, means we are parsing a pivot table - // calculation field, which are not support any name based tokens, only there + // calculation field, which do not support any name-based tokens, only their // own field names. if (!maPivotFieldNames.empty()) return false; @@ -3945,7 +4065,7 @@ bool ScCompiler::ParseDPFieldName( const OUString& rName ) bool ScCompiler::ParseColRowName( const OUString& rName ) { // If we have Pivot Table field names, means we are parsing a pivot table - // calculation field, which are not support any name based tokens, only there + // calculation field, which do not support any name-based tokens, only their // own field names. if (!maPivotFieldNames.empty()) return false; @@ -4203,20 +4323,6 @@ bool ScCompiler::ParseColRowName( const OUString& rName ) return false; } -bool ScCompiler::ParseBoolean( const OUString& rName ) -{ - OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap().find( rName ) ); - if( iLook != mxSymbols->getHashMap().end() && - ((*iLook).second == ocTrue || - (*iLook).second == ocFalse) ) - { - maRawToken.SetOpCode( (*iLook).second ); - return true; - } - else - return false; -} - bool ScCompiler::ParseErrorConstant( const OUString& rName ) { FormulaError nError = GetErrorConstant( rName); @@ -4386,13 +4492,13 @@ bool ScCompiler::ParseTableRefColumn( const OUString& rName ) void ScCompiler::SetAutoCorrection( bool bVal ) { assert(mbJumpCommandReorder); - bAutoCorrect = bVal; + mbAutoCorrect = bVal; mbStopOnError = !bVal; } void ScCompiler::AutoCorrectParsedSymbol() { - sal_Int32 nPos = aCorrectedSymbol.getLength(); + sal_Int32 nPos = maCorrectedSymbol.getLength(); if ( !nPos ) return; @@ -4400,52 +4506,52 @@ void ScCompiler::AutoCorrectParsedSymbol() const sal_Unicode cQuote = '\"'; const sal_Unicode cx = 'x'; const sal_Unicode cX = 'X'; - sal_Unicode c1 = aCorrectedSymbol[0]; - sal_Unicode c2 = aCorrectedSymbol[nPos]; - sal_Unicode c2p = nPos > 0 ? aCorrectedSymbol[nPos-1] : 0; + sal_Unicode c1 = maCorrectedSymbol[0]; + sal_Unicode c2 = maCorrectedSymbol[nPos]; + sal_Unicode c2p = nPos > 0 ? maCorrectedSymbol[nPos-1] : 0; if ( c1 == cQuote && c2 != cQuote ) { // "... // What's not a word doesn't belong to it. // Don't be pedantic: c < 128 should be sufficient here. - while ( nPos && ((aCorrectedSymbol[nPos] < 128) && - ((GetCharTableFlags(aCorrectedSymbol[nPos], aCorrectedSymbol[nPos-1]) & + while ( nPos && ((maCorrectedSymbol[nPos] < 128) && + ((GetCharTableFlags(maCorrectedSymbol[nPos], maCorrectedSymbol[nPos-1]) & (ScCharFlags::Word | ScCharFlags::CharDontCare)) == ScCharFlags::NONE)) ) nPos--; if ( nPos == MAXSTRLEN - 1 ) - aCorrectedSymbol = aCorrectedSymbol.replaceAt( nPos, 1, rtl::OUStringChar(cQuote) ); // '"' the MAXSTRLENth character + maCorrectedSymbol = maCorrectedSymbol.replaceAt( nPos, 1, rtl::OUStringChar(cQuote) ); // '"' the MAXSTRLENth character else - aCorrectedSymbol = aCorrectedSymbol.replaceAt( nPos + 1, 0, rtl::OUStringChar(cQuote) ); - bCorrected = true; + maCorrectedSymbol = maCorrectedSymbol.replaceAt( nPos + 1, 0, rtl::OUStringChar(cQuote) ); + mbCorrected = true; } else if ( c1 != cQuote && c2 == cQuote ) { // ..." - aCorrectedSymbol = OUStringChar(cQuote) + aCorrectedSymbol; - bCorrected = true; + maCorrectedSymbol = OUStringChar(cQuote) + maCorrectedSymbol; + mbCorrected = true; } else if ( nPos == 0 && (c1 == cx || c1 == cX) ) { // x => * - aCorrectedSymbol = mxSymbols->getSymbol(ocMul); - bCorrected = true; + maCorrectedSymbol = mxSymbols->getSymbol(ocMul); + mbCorrected = true; } else if ( (GetCharTableFlags( c1, 0 ) & ScCharFlags::CharValue) && (GetCharTableFlags( c2, c2p ) & ScCharFlags::CharValue) ) { - if ( aCorrectedSymbol.indexOf(cx) >= 0 ) // At least two tokens separated by cx + if ( maCorrectedSymbol.indexOf(cx) >= 0 ) // At least two tokens separated by cx { // x => * sal_Unicode c = mxSymbols->getSymbolChar(ocMul); - aCorrectedSymbol = aCorrectedSymbol.replaceAll(OUStringChar(cx), OUStringChar(c)); - bCorrected = true; + maCorrectedSymbol = maCorrectedSymbol.replaceAll(OUStringChar(cx), OUStringChar(c)); + mbCorrected = true; } - if ( aCorrectedSymbol.indexOf(cX) >= 0 ) // At least two tokens separated by cX + if ( maCorrectedSymbol.indexOf(cX) >= 0 ) // At least two tokens separated by cX { // X => * sal_Unicode c = mxSymbols->getSymbolChar(ocMul); - aCorrectedSymbol = aCorrectedSymbol.replaceAll(OUStringChar(cX), OUStringChar(c)); - bCorrected = true; + maCorrectedSymbol = maCorrectedSymbol.replaceAll(OUStringChar(cX), OUStringChar(c)); + mbCorrected = true; } } else { - OUString aSymbol( aCorrectedSymbol ); + OUString aSymbol( maCorrectedSymbol ); OUString aDoc; if ( aSymbol[0] == '\'' ) { @@ -4561,16 +4667,16 @@ void ScCompiler::AutoCorrectParsedSymbol() } if ( bChanged && bOk ) { - aCorrectedSymbol = aDoc; - aCorrectedSymbol += aTab[0]; - aCorrectedSymbol += aRef[0]; + maCorrectedSymbol = aDoc; + maCorrectedSymbol += aTab[0]; + maCorrectedSymbol += aRef[0]; if ( nRefs == 2 ) { - aCorrectedSymbol += ":"; - aCorrectedSymbol += aTab[1]; - aCorrectedSymbol += aRef[1]; + maCorrectedSymbol += ":"; + maCorrectedSymbol += aTab[1]; + maCorrectedSymbol += aRef[1]; } - bCorrected = true; + mbCorrected = true; } } } @@ -4593,7 +4699,7 @@ bool ScCompiler::ToUpperAsciiOrI18nIsAscii( OUString& rUpper, const OUString& rO } } -short ScCompiler::GetPossibleParaCount( std::u16string_view rLambdaFormula ) const +short ScCompiler::GetPossibleParaCount( std::u16string_view rBindingFormula ) const { sal_Unicode cSep = mxSymbols->getSymbolChar(ocSep); sal_Unicode cOpen = mxSymbols->getSymbolChar(ocOpen); @@ -4602,7 +4708,7 @@ short ScCompiler::GetPossibleParaCount( std::u16string_view rLambdaFormula ) con sal_Unicode cArrayClose = mxSymbols->getSymbolChar(ocArrayClose); short nBrackets = 0; - short nCount = std::count_if(rLambdaFormula.begin(), rLambdaFormula.end(), + short nCount = std::count_if(rBindingFormula.begin(), rBindingFormula.end(), [&](sal_Unicode c) { if (c == cOpen || c == cArrayOpen || c == '[') { nBrackets++; @@ -4632,7 +4738,6 @@ bool ScCompiler::NextNewToken( bool bInArray ) return true; } - bool bAllowBooleans = bInArray; const std::vector vSpaces = NextSymbol(bInArray); if (!cSymbol[0]) @@ -4641,7 +4746,7 @@ bool ScCompiler::NextNewToken( bool bInArray ) { // Nothing could be parsed, remainder as bad string. // NextSymbol() must had set an error for this. - assert( pArr->GetCodeError() != FormulaError::NONE); + assert( mpArr->GetCodeError() != FormulaError::NONE); const OUString aBad( aFormula.copy( nSrcPos)); svl::SharedString aSS = rDoc.GetSharedStringPool().intern( aBad); maRawToken.SetString( aSS.getData(), aSS.getDataIgnoreCase()); @@ -4673,7 +4778,7 @@ bool ScCompiler::NextNewToken( bool bInArray ) aToken.whitespace.nCount = static_cast( std::min(rSpace.nCount, 255) ); aToken.whitespace.cChar = rSpace.cChar; } - if (!static_cast(pArr)->AddRawToken( aToken )) + if (!static_cast(mpArr)->AddRawToken( aToken )) { SetError(FormulaError::CodeOverflow); return false; @@ -4696,8 +4801,19 @@ bool ScCompiler::NextNewToken( bool bInArray ) } if ( (cSymbol[0] == '#' || cSymbol[0] == '$') && cSymbol[1] == 0 && - !bAutoCorrect ) - { // special case to speed up broken [$]#REF documents + !mbAutoCorrect ) + { + // A bare # right after a reference or value is the spilled-range + // operator. It expands the preceding reference to the dynamic- + // array spill range whose origin lives at that cell. + if (cSymbol[0] == '#' && (meLastOp == ocColRowName || meLastOp == ocPush + || meLastOp == ocClose || meLastOp == ocMatRef + || meLastOp == ocPercentSign || meLastOp == ocSpill)) + { + maRawToken.SetOpCode(ocSpill); + return true; + } + // special case to speed up broken [$]#REF documents /* FIXME: ISERROR(#REF!) would be valid and true and the formula to * be processed as usual. That would need some special treatment, * also in NextSymbol() because of possible combinations of @@ -4705,56 +4821,50 @@ bool ScCompiler::NextNewToken( bool bInArray ) * handled by IsPredetectedReference(), this case here remains for * manual/API input. */ OUString aBad( aFormula.copy( nSrcPos-1 ) ); - const FormulaToken* pBadToken = pArr->AddBad(aBad); - eLastOp = pBadToken ? pBadToken->GetOpCode() : ocNone; + const FormulaToken* pBadToken = mpArr->AddBad(aBad); + meLastOp = pBadToken ? pBadToken->GetOpCode() : ocNone; return false; } - if( ParseString() ) + if( ParseLiteralString() ) return true; - bool bMayBeFuncName; + bool bMayBeName; + bool bParenFollows; bool bAsciiNonAlnum; // operators, separators, ... if ( cSymbol[0] < 128 ) { - bMayBeFuncName = rtl::isAsciiAlpha(cSymbol[0]) + bMayBeName = rtl::isAsciiAlpha(cSymbol[0]) || (cSymbol[0] == '_' && mxSymbols->isOOXML() && rtl::isAsciiAlpha(cSymbol[1])); - if (!bMayBeFuncName && (cSymbol[0] == '_' && cSymbol[1] == '_') && !comphelper::IsFuzzing()) + if (!bMayBeName && (cSymbol[0] == '_' && cSymbol[1] == '_') && !comphelper::IsFuzzing()) { - bMayBeFuncName = officecfg::Office::Common::Misc::ExperimentalMode::get(); + bMayBeName = officecfg::Office::Common::Misc::ExperimentalMode::get(); } - bAsciiNonAlnum = !bMayBeFuncName && !rtl::isAsciiDigit( cSymbol[0] ); + bAsciiNonAlnum = !bMayBeName && !rtl::isAsciiDigit( cSymbol[0] ); } else { OUString aTmpStr( cSymbol[0] ); - bMayBeFuncName = pCharClass->isLetter( aTmpStr, 0 ); + bMayBeName = pCharClass->isLetter( aTmpStr, 0 ); bAsciiNonAlnum = false; } + bParenFollows = lcl_ParenthesisFollows( aFormula.getStr() + nSrcPos ); + // Within a TableRef anything except an unescaped '[' or ']' is an item // or a column specifier, do not attempt to recognize any other single // operator there so even [,] or [+] for a single character column // specifier works. Note that space between two ocTableRefOpen is not // supported (Table[ [ColumnSpec]]), not only here. Note also that Table[] // without any item or column specifier is valid. - if (bAsciiNonAlnum && cSymbol[1] == 0 && (eLastOp != ocTableRefOpen || cSymbol[0] == '[' || cSymbol[0] == ']')) + if (bAsciiNonAlnum && cSymbol[1] == 0 && (meLastOp != ocTableRefOpen || cSymbol[0] == '[' || cSymbol[0] == ']')) { // Shortcut for operators and separators that need no further checks or upper. if (ParseOpCode( OUString( cSymbol), bInArray )) return true; } - if ( bMayBeFuncName ) - { - // a function name must be followed by a parenthesis - const sal_Unicode* p = aFormula.getStr() + nSrcPos; - while( *p == ' ' ) - p++; - bMayBeFuncName = ( *p == '(' ); - } - // Italian ARCTAN.2 resulted in #REF! => ParseOpcode() before // ParseReference(). @@ -4779,11 +4889,10 @@ Label_Rewind: mbRewind = false; aUpper.clear(); - bAsciiUpper = false; + bAsciiUpper = ToUpperAsciiOrI18nIsAscii( aUpper, aOrg); if (bAsciiNonAlnum) { - bAsciiUpper = ToUpperAsciiOrI18nIsAscii( aUpper, aOrg); if (cSymbol[0] == '#') { // Check for TableRef item specifiers first. @@ -4807,99 +4916,208 @@ Label_Rewind: return true; } - if (bMayBeFuncName) + // mbPreferLocalNames changes the priority of names detected by the compiler: + // 1. Locals in scope (bound with LET or LAMBDA) + // 2. Named ranges in scope + // 3. External names + // 4. DB ranges + // 5. Column and row names + // 6. Macros + // 7. Pivot Table DataPilot fields + // 8. Opcodes + // This priority is compatible with GSheets, but incompatible with Excel. + if (mbPreferLocalNames) { - if (aUpper.isEmpty()) - bAsciiUpper = ToUpperAsciiOrI18nIsAscii( aUpper, aOrg); - if (ParseOpCode( aUpper, bInArray )) - return true; - } - // Column 'DM' ("Deutsche Mark", German currency) couldn't be - // referred => ParseReference() before ParseValue(). - // Preserve case of file names in external references. - if (ParseReference( aOrg )) - { - if (mbRewind) // Range operator, but no direct reference. - continue; // do; up to range operator. - // If a syntactically correct reference was recognized but invalid - // e.g. because of non-existing sheet name => entire reference - // ocBad to preserve input instead of #REF!.A1 - if (!maRawToken.IsValidReference(rDoc)) + if (bMayBeName) { - aUpper = aOrg; // ensure for ocBad - break; // do; create ocBad token or set error. + if (ParseLocalName( aOrg )) + return true; + + if (ParseNamedRange( aUpper )) + return true; + + // Preserve case of file names in external references. + bool bInvalidExternalNameRange; + if (ParseExternalNamedRange( aOrg, bInvalidExternalNameRange )) + return true; + // Preserve case of file names in external references even when range + // is not valid and previous check failed tdf#89330 + if (bInvalidExternalNameRange) + { + // add ocBad but do not lowercase + svl::SharedString aSS = rDoc.GetSharedStringPool().intern(aOrg); + maRawToken.SetString(aSS.getData(), aSS.getDataIgnoreCase()); + maRawToken.NewOpCode( ocBad ); + return true; + } + + if (ParseDBRange( aUpper )) + return true; + + // If followed by '(' (with or without space inbetween) it can not be a + // column/row label. Prevent arbitrary content detection. + if (!bParenFollows && ParseColRowName( aUpper )) + return true; + + if (ParseMacro( aUpper )) + return true; + + if (ParseOpCode( aUpper, bInArray )) + return true; + + if (ParseOpCode2( aUpper )) + return true; } - return true; + + // A local name is in scope here, and its name can make bMayBeName false + // (for example, the "_xlpm." prefix in non-OOXML grammars), so resolve + // it unconditionally. In expression positions, ParseLocalName only + // matches names that are actually bound in the current scope. + if (ParseLocalName( aOrg )) + return true; + + // Parse Pivot Table DataPilot field names. A field name may be quoted + // (for example, 'Sales'), which makes bMayBeName false, so try this + // unconditionally after the name and opcode detection. + if (ParseDPFieldName(aUpper)) + return true; + } - - if (aUpper.isEmpty()) - bAsciiUpper = ToUpperAsciiOrI18nIsAscii( aUpper, aOrg); - - // ParseBoolean() before ParseValue() to catch inline bools without the kludge - // for inline arrays. - if (bAllowBooleans && ParseBoolean( aUpper )) - return true; - - if (ParseValue( aUpper )) - return true; - - // User defined names and such do need i18n upper also in ODF. - if (bAsciiUpper || mbCharClassesDiffer) + else { - // Use current system locale here because user defined symbols are - // more likely in that localized language than in the formula - // language. This in corner cases needs to continue to work for - // existing documents and environments. - // Do not change bAsciiUpper from here on for the lowercase() call - // below in the ocBad case to use the correct CharClass. - aUpper = ScGlobal::getCharClass().uppercase( aOrg ); - } - if (ParseNamedRange( aUpper )) - return true; + // OpCodes are detected first only if they are called immediately + if (bMayBeName && bParenFollows) + { + if (ParseOpCode( aUpper, bInArray )) + return true; + } - // Compiling a named expression during collecting them in import shall - // not match arbitrary names that otherwise if all named expressions - // were present would be recognized as named expression. Such name will - // flag an error below and will be recompiled in a second step later - // with ScRangeData::CompileUnresolvedXML() - if (meExtendedErrorDetection == EXTENDED_ERROR_DETECTION_NAME_NO_BREAK && rDoc.IsImportingXML()) - break; // while + // Column 'DM' ("Deutsche Mark", German currency) couldn't be + // referred => ParseReference() before ParseValue(). + // Preserve case of file names in external references. + if (ParseReference( aOrg )) + { + if (mbRewind) // Range operator, but no direct reference. + continue; // do; up to range operator. + // If a syntactically correct reference was recognized but invalid + // e.g. because of non-existing sheet name => entire reference + // ocBad to preserve input instead of #REF!.A1 + if (!maRawToken.IsValidReference(rDoc)) + { + // A parenthesis after such a symbol makes it a range operator plus + // a call, as in F25:IF(TRUE,F26) where IF also reads as a column. + // Cut at the operator, so the reference stands alone and the call + // follows. + if (bParenFollows && mnRangeOpPosInSymbol > 0) + { + sal_Int32 nLen = mnRangeOpPosInSymbol; + while (cSymbol[++nLen]) + ; + cSymbol[mnRangeOpPosInSymbol] = 0; + nSrcPos -= (nLen - mnRangeOpPosInSymbol); + mnRangeOpPosInSymbol = -1; + mbRewind = true; + continue; // do; up to range operator. + } + aUpper = aOrg; // ensure for ocBad + break; // do; create ocBad token or set error. + } + return true; + } - // Preserve case of file names in external references. - bool bInvalidExternalNameRange; - if (ParseExternalNamedRange( aOrg, bInvalidExternalNameRange )) - return true; - // Preserve case of file names in external references even when range - // is not valid and previous check failed tdf#89330 - if (bInvalidExternalNameRange) - { - // add ocBad but do not lowercase - svl::SharedString aSS = rDoc.GetSharedStringPool().intern(aOrg); - maRawToken.SetString(aSS.getData(), aSS.getDataIgnoreCase()); - maRawToken.NewOpCode( ocBad ); - return true; - } - if (ParseDBRange( aUpper )) - return true; - // If followed by '(' (with or without space inbetween) it can not be a - // column/row label. Prevent arbitrary content detection. - if (!bMayBeFuncName && ParseColRowName( aUpper )) - return true; - if (bMayBeFuncName && ParseMacro( aUpper )) - return true; - if (bMayBeFuncName && ParseOpCode2( aUpper )) - return true; + if (ParseValue(aUpper, bInArray)) + return true; - if (ParseLambdaFuncName( aOrg )) - return true; + // User defined names and such do need i18n upper also in ODF. + if (bAsciiUpper || mbCharClassesDiffer) + { + // Use current system locale here because user defined symbols are + // more likely in that localized language than in the formula + // language. This in corner cases needs to continue to work for + // existing documents and environments. + // Do not change bAsciiUpper from here on for the lowercase() call + // below in the ocBad case to use the correct CharClass. + aUpper = ScGlobal::getCharClass().uppercase( aOrg ); + } - // Parse Pivot Table DataPilot field names. - // This is only true if the compiler is created with the actual - // Pivot Table Fields name - if (ParseDPFieldName(aUpper)) - return true; + // A name that is followed by '(' and matches a Basic macro is a + // macro call. An XLSM can hold both a macro and a defined name for + // the same user-defined function, so in the call position the macro + // takes priority over a same-named defined name. A plain name + // reference still resolves as the named range. + if (bMayBeName && bParenFollows && ParseMacro(aUpper)) + return true; + + if (ParseNamedRange( aUpper )) + return true; + + // Compiling a named expression during collecting them in import shall + // not match arbitrary names that otherwise if all named expressions + // were present would be recognized as named expression. Such name will + // flag an error below and will be recompiled in a second step later + // with ScRangeData::CompileUnresolvedXML() + if (meExtendedErrorDetection == EXTENDED_ERROR_DETECTION_NAME_NO_BREAK && rDoc.IsImportingXML()) + break; // while + + // Preserve case of file names in external references. + bool bInvalidExternalNameRange; + if (ParseExternalNamedRange( aOrg, bInvalidExternalNameRange )) + return true; + // Preserve case of file names in external references even when range + // is not valid and previous check failed tdf#89330 + if (bInvalidExternalNameRange) + { + // add ocBad but do not lowercase + svl::SharedString aSS = rDoc.GetSharedStringPool().intern(aOrg); + maRawToken.SetString(aSS.getData(), aSS.getDataIgnoreCase()); + maRawToken.NewOpCode( ocBad ); + return true; + } + if (ParseDBRange( aUpper )) + return true; + // If followed by '(' (with or without space inbetween) it can not be a + // column/row label. Prevent arbitrary content detection. + if (!bParenFollows && ParseColRowName( aUpper )) + return true; + + if (bMayBeName) + { + if (ParseMacro( aUpper )) + return true; + + if (ParseLocalName( aOrg )) + return true; + + // A pivot field whose name matches a built-in function name + // (for example the field "B" and the function B) resolves to + // the field when it is not a direct call, so recognize a bare + // field name as a DataPilot field before opcode detection. + if (!bParenFollows && ParseDPFieldName(aUpper)) + return true; + + if (ParseOpCode( aUpper, bInArray )) + return true; + + if (ParseOpCode2( aUpper )) + return true; + } + + // A local name is in scope here, and its name can make bMayBeName false + // (for example, the "_xlpm." prefix in non-OOXML grammars), so resolve + // it unconditionally. In expression positions, ParseLocalName only + // matches names that are actually bound in the current scope. + if (ParseLocalName(aOrg)) + return true; + + // Parse Pivot Table DataPilot field names. A field name may be quoted + // (for example, 'Sales'), which makes bMayBeName false, so try this + // unconditionally after the name and opcode detection. + if (ParseDPFieldName(aUpper)) + return true; + + } // !mbPreferLocalNames } while (mbRewind); @@ -4930,7 +5148,7 @@ Label_Rewind: svl::SharedString aSS = rDoc.GetSharedStringPool().intern(aUpper); maRawToken.SetString(aSS.getData(), aSS.getDataIgnoreCase()); maRawToken.NewOpCode( ocBad ); - if ( bAutoCorrect ) + if ( mbAutoCorrect ) AutoCorrectParsedSymbol(); return true; } @@ -4939,14 +5157,14 @@ void ScCompiler::CreateStringFromXMLTokenArray( OUString& rFormula, OUString& rF { bool bExternal = GetGrammar() == FormulaGrammar::GRAM_EXTERNAL; sal_uInt16 nExpectedCount = bExternal ? 2 : 1; - OSL_ENSURE( pArr->GetLen() == nExpectedCount, "ScCompiler::CreateStringFromXMLTokenArray - wrong number of tokens" ); - if( pArr->GetLen() == nExpectedCount ) + OSL_ENSURE( mpArr->GetLen() == nExpectedCount, "ScCompiler::CreateStringFromXMLTokenArray - wrong number of tokens" ); + if( mpArr->GetLen() == nExpectedCount ) { - FormulaToken** ppTokens = pArr->GetArray(); + FormulaToken** ppTokens = mpArr->GetArray(); // string tokens expected, GetString() will assert if token type is wrong - rFormula = ppTokens[0]->GetString().getString(); + rFormula = static_cast(ppTokens[0])->GetString().getString(); if( bExternal ) - rFormulaNmsp = ppTokens[1]->GetString().getString(); + rFormulaNmsp = static_cast(ppTokens[1])->GetName().getString(); } } @@ -4975,31 +5193,31 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul SetGrammar( FormulaGrammar::GRAM_PODF ); ScTokenArray aArr(rDoc); - pArr = &aArr; - maArrIterator = FormulaTokenArrayPlainIterator(*pArr); + mpArr = &aArr; + maArrIterator = FormulaTokenArrayPlainIterator(*mpArr); aFormula = comphelper::string::strip(rFormula, ' '); nSrcPos = 0; - bCorrected = false; - if ( bAutoCorrect ) + mbCorrected = false; + if ( mbAutoCorrect ) { - aCorrectedFormula.clear(); - aCorrectedSymbol.clear(); + maCorrectedFormula.clear(); + maCorrectedSymbol.clear(); } sal_uInt8 nForced = 0; // ==formula forces recalc even if cell is not visible if( nSrcPos < aFormula.getLength() && aFormula[nSrcPos] == '=' ) { nSrcPos++; nForced++; - if ( bAutoCorrect ) - aCorrectedFormula += "="; + if ( mbAutoCorrect ) + maCorrectedFormula += "="; } if( nSrcPos < aFormula.getLength() && aFormula[nSrcPos] == '=' ) { nSrcPos++; nForced++; - if ( bAutoCorrect ) - aCorrectedFormula += "="; + if ( mbAutoCorrect ) + maCorrectedFormula += "="; } struct FunctionStack { @@ -5012,15 +5230,16 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul bool bUseFunctionStack = (bPODF || bOOXML); const size_t nAlloc = 512; FunctionStack aFuncs[ nAlloc ]; - FunctionStack* pFunctionStack = (bUseFunctionStack && o3tl::make_unsigned(rFormula.getLength()) > nAlloc ? - new FunctionStack[rFormula.getLength()] : &aFuncs[0]); + // A formula of length L composed entirely of open tokens needs L+1 slots, + FunctionStack* pFunctionStack = (bUseFunctionStack && o3tl::make_unsigned(rFormula.getLength()) >= nAlloc ? + new FunctionStack[rFormula.getLength() + 1] : &aFuncs[0]); pFunctionStack[0].eOp = ocNone; pFunctionStack[0].nSep = 0; size_t nFunction = 0; size_t nHighWatermark = 0; short nBrackets = 0; bool bInArray = false; - eLastOp = ocOpen; + meLastOp = ocOpen; while( NextNewToken( bInArray ) ) { const OpCode eOp = maRawToken.GetOpCode(); @@ -5031,19 +5250,55 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul { case ocOpen: { - if (eLastOp == ocLet) + if (meLastOp == ocLet || meLastOp == ocLambda) { - m_aLambda.bInLambdaFunction = true; - m_aLambda.nBracketPos = nBrackets; - m_aLambda.nParaPos++; - m_aLambda.nParaCount = GetPossibleParaCount(rFormula.subView(nSrcPos - 1)); + maBindings.push_front(BindingsLayer { + meLastOp, + nBrackets, + 1, + GetPossibleParaCount(rFormula.subView(nSrcPos - 1)), + std::unordered_set(), + }); + } + else if (meLastOp == ocPush + || meLastOp == ocStringName + || meLastOp == ocName + || meLastOp == ocClose + || meLastOp == ocMacro + || meLastOp == ocDBArea + || meLastOp == ocTableRefClose + || meLastOp == ocArrayClose + || meLastOp == ocTableRef ) + { + // Where the intersection operator is a blank, a blank before the + // parenthesis is that operator and opens a group, not an argument list. + const sal_uInt16 nArrayLength = mpArr->GetLen(); + const bool bIntersectingBlank + = (meLastOp == ocPush || meLastOp == ocClose) + && FormulaGrammar::isExcelSyntax( meGrammar) + && nArrayLength > 0 + && mpArr->TokenAt(nArrayLength - 1)->GetOpCode() == ocSpaces; + if (!bIntersectingBlank) + { + // We're trying to call a function, it seems. Inject ocCall so the + // compiler can see what's going on. + ScRawToken aToken; + aToken.SetOpCode( ocCall ); + FormulaToken* pNewToken = static_cast(mpArr)->Add( + aToken.CreateToken(rDoc.GetSheetLimits())); + if (!pNewToken) + { + SetError(FormulaError::CodeOverflow); + goto OutsideLoop; + } + } } ++nBrackets; if (bUseFunctionStack) { ++nFunction; - pFunctionStack[ nFunction ].eOp = eLastOp; + pFunctionStack[ nFunction ].eOp = meLastOp; pFunctionStack[ nFunction ].nSep = 0; nHighWatermark = nFunction; } @@ -5054,20 +5309,20 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul if( !nBrackets ) { SetError( FormulaError::PairExpected ); - if ( bAutoCorrect ) + if ( mbAutoCorrect ) { - bCorrected = true; - aCorrectedSymbol.clear(); + mbCorrected = true; + maCorrectedSymbol.clear(); } } else { nBrackets--; - if (m_aLambda.bInLambdaFunction && m_aLambda.nBracketPos == nBrackets) + if (!maBindings.empty() && maBindings.front().nBracketPos == nBrackets) { - m_aLambda.bInLambdaFunction = false; - m_aLambda.nBracketPos = nBrackets; + maBindings.pop_front(); } + mIsInBinding = (!maBindings.empty() && maBindings.front().nBracketPos + 1 == nBrackets); } if (bUseFunctionStack && nFunction) --nFunction; @@ -5078,8 +5333,8 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul if (bUseFunctionStack) ++pFunctionStack[ nFunction ].nSep; - if (m_aLambda.bInLambdaFunction && m_aLambda.nBracketPos + 1 == nBrackets) - m_aLambda.nParaPos++; + if (!maBindings.empty() && maBindings.front().nBracketPos + 1 == nBrackets) + maBindings.front().nParaPos++; } break; case ocArrayOpen: @@ -5107,10 +5362,10 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul else { SetError( FormulaError::PairExpected ); - if ( bAutoCorrect ) + if ( mbAutoCorrect ) { - bCorrected = true; - aCorrectedSymbol.clear(); + mbCorrected = true; + maCorrectedSymbol.clear(); } } if (bUseFunctionStack && nFunction) @@ -5119,20 +5374,32 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul break; case ocTableRefOpen: { - // Don't count following item separator as parameter separator. - if (bUseFunctionStack) + // If we're expecting a lambda parameter name, enclosing it in [] makes it optional. + if (!(mIsInBinding + && maBindings.front().eOpCode == ocLambda + && maBindings.front().nParaPos < maBindings.front().nParaCount)) { - ++nFunction; - pFunctionStack[ nFunction ].eOp = eOp; - pFunctionStack[ nFunction ].nSep = 0; - nHighWatermark = nFunction; + // Don't count following item separator as parameter separator. + if (bUseFunctionStack) + { + ++nFunction; + pFunctionStack[ nFunction ].eOp = eOp; + pFunctionStack[ nFunction ].nSep = 0; + nHighWatermark = nFunction; + } } } break; case ocTableRefClose: { - if (bUseFunctionStack && nFunction) - --nFunction; + // If we're expecting a lambda parameter name, enclosing it in [] makes it optional. + if (!(mIsInBinding + && maBindings.front().eOpCode == ocLambda + && maBindings.front().nParaPos < maBindings.front().nParaCount)) + { + if (bUseFunctionStack && nFunction) + --nFunction; + } } break; case ocColRowName: @@ -5144,12 +5411,12 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul default: break; } - if ((eLastOp != ocOpen || eOp != ocClose) && - (eLastOp == ocOpen || - eLastOp == ocSep || - eLastOp == ocArrayRowSep || - eLastOp == ocArrayColSep || - eLastOp == ocArrayOpen) && + if ((meLastOp != ocOpen || eOp != ocClose) && + (meLastOp == ocOpen || + meLastOp == ocSep || + meLastOp == ocArrayRowSep || + meLastOp == ocArrayColSep || + meLastOp == ocArrayOpen) && (eOp == ocSep || eOp == ocClose || eOp == ocArrayRowSep || @@ -5158,7 +5425,7 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul { // TODO: should we check for known functions with optional empty // args so the correction dialog can do better? - if ( !static_cast(pArr)->Add( new FormulaMissingToken ) ) + if ( !static_cast(mpArr)->Add( new FormulaMissingToken ) ) { SetError(FormulaError::CodeOverflow); break; } @@ -5172,8 +5439,8 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul pFunctionStack[ nFunc ].nSep == 0 && pFunctionStack[ nFunc ].eOp == ocWeek) // 2nd week start { - if ( !static_cast(pArr)->Add( new FormulaToken( svSep, ocSep)) || - !static_cast(pArr)->Add( new FormulaDoubleToken( 1.0))) + if ( !static_cast(mpArr)->Add( new FormulaToken( svSep, ocSep)) || + !static_cast(mpArr)->Add( new FormulaDoubleToken( 1.0))) { SetError(FormulaError::CodeOverflow); break; } @@ -5188,16 +5455,22 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul pFunctionStack[ nFunction ].eOp == ocAddress && pFunctionStack[ nFunction ].nSep == 3) { - if ( !static_cast(pArr)->Add( new FormulaToken( svSep, ocSep)) || - !static_cast(pArr)->Add( new FormulaDoubleToken( 1.0))) + if ( !static_cast(mpArr)->Add( new FormulaToken( svSep, ocSep)) || + !static_cast(mpArr)->Add( new FormulaDoubleToken( 1.0))) { SetError(FormulaError::CodeOverflow); break; } ++pFunctionStack[ nFunction ].nSep; } } - FormulaToken* pNewToken = static_cast(pArr)->Add( maRawToken.CreateToken(rDoc.GetSheetLimits())); - if (!pNewToken && eOp == ocArrayClose && pArr->OpCodeBefore( pArr->GetLen()) == ocArrayClose) + FormulaToken* pNewToken = static_cast(mpArr)->Add( maRawToken.CreateToken(rDoc.GetSheetLimits())); + // A lambda parameter written with the _xlop. prefix is optional. Its + // byte records that, keeping an optional parameter distinct from a + // required _xlpm. one. + if (pNewToken && mbOptionalLocalName && pNewToken->GetOpCode() == ocStringName) + static_cast(pNewToken)->SetByte(1); + mbOptionalLocalName = false; + if (!pNewToken && eOp == ocArrayClose && mpArr->OpCodeBefore( mpArr->GetLen()) == ocArrayClose) { // Nested inline array or non-value/non-string in array. The // original tokens are still in the ScTokenArray and not merged @@ -5209,60 +5482,67 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul SetError(FormulaError::CodeOverflow); break; } - else if (eLastOp == ocRange && pNewToken->GetOpCode() == ocPush && pNewToken->GetType() == svSingleRef) + else if (meLastOp == ocRange && pNewToken->GetOpCode() == ocPush && pNewToken->GetType() == svSingleRef) { - static_cast(pArr)->MergeRangeReference( aPos); + static_cast(mpArr)->MergeRangeReference( aPos); } - else if (eLastOp == ocDBArea && pNewToken->GetOpCode() == ocTableRefOpen) + else if (meLastOp == ocDBArea && pNewToken->GetOpCode() == ocTableRefOpen) { - sal_uInt16 nIdx = pArr->GetLen() - 1; - const FormulaToken* pPrev = pArr->PeekPrev( nIdx); + sal_uInt16 nIdx = mpArr->GetLen() - 1; + const FormulaToken* pPrev = mpArr->PeekPrev( nIdx); if (pPrev && pPrev->GetOpCode() == ocDBArea) { - ScTableRefToken* pTableRefToken = new ScTableRefToken( pPrev->GetIndex(), ScTableRefToken::TABLE); + ScTableRefToken* pTableRefToken = new ScTableRefToken( static_cast(pPrev)->GetIndex(), ScTableRefToken::TABLE); maTableRefs.emplace_back( pTableRefToken); // pPrev may be dead hereafter. - static_cast(pArr)->ReplaceToken( nIdx, pTableRefToken, + static_cast(mpArr)->ReplaceToken( nIdx, pTableRefToken, FormulaTokenArray::ReplaceMode::CODE_ONLY); } } - switch (eOp) + if (!(mIsInBinding + && maBindings.front().eOpCode == ocLambda + && maBindings.front().nParaPos < maBindings.front().nParaCount)) { - case ocTableRefOpen: - SAL_WARN_IF( maTableRefs.empty(), "sc.core", "ocTableRefOpen without TableRefEntry"); - if (maTableRefs.empty()) - SetError(FormulaError::Pair); - else - ++maTableRefs.back().mnLevel; - break; - case ocTableRefClose: - SAL_WARN_IF( maTableRefs.empty(), "sc.core", "ocTableRefClose without TableRefEntry"); - if (maTableRefs.empty()) - SetError(FormulaError::Pair); - else - { - if (--maTableRefs.back().mnLevel == 0) - maTableRefs.pop_back(); - } - break; - default: - break; + switch (eOp) + { + case ocTableRefOpen: + SAL_WARN_IF( maTableRefs.empty(), "sc.core", "ocTableRefOpen without TableRefEntry"); + if (maTableRefs.empty()) + SetError(FormulaError::Pair); + else + ++maTableRefs.back().mnLevel; + break; + case ocTableRefClose: + SAL_WARN_IF( maTableRefs.empty(), "sc.core", "ocTableRefClose without TableRefEntry"); + if (maTableRefs.empty()) + SetError(FormulaError::Pair); + else + { + if (--maTableRefs.back().mnLevel == 0) + maTableRefs.pop_back(); + } + break; + default: + break; + } } - eLastOp = maRawToken.GetOpCode(); - if ( bAutoCorrect ) - aCorrectedFormula += aCorrectedSymbol; + meLastOp = maRawToken.GetOpCode(); + if ( mbAutoCorrect ) + maCorrectedFormula += maCorrectedSymbol; + mIsInBinding = (!maBindings.empty() && maBindings.front().nBracketPos + 1 == nBrackets); } +OutsideLoop: if ( mbCloseBrackets ) { if( bInArray ) { FormulaByteToken aToken( ocArrayClose ); - if( !pArr->AddToken( aToken ) ) + if( !mpArr->AddToken( aToken ) ) { SetError(FormulaError::CodeOverflow); } - else if ( bAutoCorrect ) - aCorrectedFormula += mxSymbols->getSymbol(ocArrayClose); + else if ( mbAutoCorrect ) + maCorrectedFormula += mxSymbols->getSymbol(ocArrayClose); } if (nBrackets) @@ -5270,28 +5550,28 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul FormulaToken aToken( svSep, ocClose ); while( nBrackets-- ) { - if( !pArr->AddToken( aToken ) ) + if( !mpArr->AddToken( aToken ) ) { SetError(FormulaError::CodeOverflow); break; // while } - if ( bAutoCorrect ) - aCorrectedFormula += mxSymbols->getSymbol(ocClose); + if ( mbAutoCorrect ) + maCorrectedFormula += mxSymbols->getSymbol(ocClose); } } } if ( nForced >= 2 ) - pArr->SetRecalcModeForced(); + mpArr->SetRecalcModeForced(); if (pFunctionStack != &aFuncs[0]) delete [] pFunctionStack; - // remember pArr, in case a subsequent CompileTokenArray() is executed. + // remember mpArr, in case a subsequent CompileTokenArray() is executed. std::unique_ptr pNew(new ScTokenArray( std::move(aArr) )); pNew->GenHash(); - // coverity[escape : FALSE] - ownership of pNew is retained by caller, so pArr remains valid - pArr = pNew.get(); - maArrIterator = FormulaTokenArrayPlainIterator(*pArr); + // coverity[escape : FALSE] - ownership of pNew is retained by caller, so mpArr remains valid + mpArr = pNew.get(); + maArrIterator = FormulaTokenArrayPlainIterator(*mpArr); if (!maExternalFiles.empty()) { @@ -5319,11 +5599,11 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul ScTokenArray aTokenArray(rDoc); if( ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, aTokenSeq ) ) { - // remember pArr, in case a subsequent CompileTokenArray() is executed. + // remember mpArr, in case a subsequent CompileTokenArray() is executed. std::unique_ptr pNew(new ScTokenArray( std::move(aTokenArray) )); - // coverity[escape : FALSE] - ownership of pNew is retained by caller, so pArr remains valid - pArr = pNew.get(); - maArrIterator = FormulaTokenArrayPlainIterator(*pArr); + // coverity[escape : FALSE] - ownership of pNew is retained by caller, so mpArr remains valid + mpArr = pNew.get(); + maArrIterator = FormulaTokenArrayPlainIterator(*mpArr); return pNew; } } @@ -5334,7 +5614,7 @@ std::unique_ptr ScCompiler::CompileString( const OUString& rFormul return CompileString( rFormula ); } -ScRangeData* ScCompiler::GetRangeData( const FormulaToken& rToken ) const +ScRangeData* ScCompiler::GetRangeData( const FormulaIndexToken& rToken ) const { return rDoc.FindRangeNameBySheetAndIndex( rToken.GetSheet(), rToken.GetIndex()); } @@ -5342,7 +5622,10 @@ ScRangeData* ScCompiler::GetRangeData( const FormulaToken& rToken ) const bool ScCompiler::HandleStringName() { ScTokenArray* pNew = new ScTokenArray(rDoc); - pNew->AddStringName(mpToken->GetString()); + // The byte carries the optional marker set when an _xlop. lambda parameter + // was parsed, so the parameter name keeps that property in the code. + const bool bOptional = static_cast(mpToken.get())->GetByte() != 0; + pNew->AddStringName(static_cast(mpToken.get())->GetString(), bOptional); PushTokenArray(pNew, true); return GetToken(); } @@ -5350,7 +5633,7 @@ bool ScCompiler::HandleStringName() bool ScCompiler::HandleDPFieldName() { ScTokenArray* pNew = new ScTokenArray(rDoc); - pNew->AddDPFieldName(mpToken->GetString()); + pNew->AddDPFieldName(static_cast(mpToken.get())->GetString()); PushTokenArray(pNew, true); return GetToken(); } @@ -5358,7 +5641,7 @@ bool ScCompiler::HandleDPFieldName() bool ScCompiler::HandleRange() { ScTokenArray* pNew; - const ScRangeData* pRangeData = GetRangeData( *mpToken); + const ScRangeData* pRangeData = GetRangeData( static_cast(*mpToken)); if (pRangeData) { FormulaError nErr = pRangeData->GetErrCode(); @@ -5394,7 +5677,8 @@ bool ScCompiler::HandleRange() // shall still point to the same sheet as if used on the // original sheet, not shifted to the current position where // they are used. - SCTAB nSheetTab = mpToken->GetSheet(); + assert(dynamic_cast(mpToken.get())); + SCTAB nSheetTab = static_cast(mpToken.get())->GetSheet(); if (nSheetTab >= 0 && nSheetTab != aPos.Tab()) AdjustSheetLocalNameRelReferences( nSheetTab - aPos.Tab()); @@ -5433,17 +5717,18 @@ bool ScCompiler::HandleExternalReference(const FormulaToken& _aToken) break; case svExternalName: { + const auto & rExtToken = static_cast(_aToken); ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager(); - const OUString* pFile = pRefMgr->getExternalFileName(_aToken.GetIndex()); + const OUString* pFile = pRefMgr->getExternalFileName(rExtToken.GetFileId()); if (!pFile) { SetError(FormulaError::NoName); return true; } - OUString aName = _aToken.GetString().getString(); + OUString aName = rExtToken.GetName().getString(); ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getRangeNameTokens( - _aToken.GetIndex(), aName, &aPos); + rExtToken.GetFileId(), aName, &aPos); if (!xNew) { @@ -5470,14 +5755,14 @@ bool ScCompiler::HandleExternalReference(const FormulaToken& _aToken) void ScCompiler::AdjustSheetLocalNameRelReferences( SCTAB nDelta ) { - for ( auto t: pArr->References() ) + for ( auto t: mpArr->References() ) { - ScSingleRefData& rRef1 = *t->GetSingleRef(); - if (rRef1.IsTabRel()) - rRef1.IncTab( nDelta); + ScSingleRefData* pRef1 = ScRefTokenHelper::getSingleRef(t); + if (pRef1->IsTabRel()) + pRef1->IncTab( nDelta); if ( t->GetType() == svDoubleRef ) { - ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(t)->GetDoubleRef().Ref2; if (rRef2.IsTabRel()) rRef2.IncTab( nDelta); } @@ -5488,14 +5773,14 @@ void ScCompiler::AdjustSheetLocalNameRelReferences( SCTAB nDelta ) void ScCompiler::SetRelNameReference() { - for ( auto t: pArr->References() ) + for ( auto t: mpArr->References() ) { - ScSingleRefData& rRef1 = *t->GetSingleRef(); + ScSingleRefData& rRef1 = *ScRefTokenHelper::getSingleRef(t); if ( rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel() ) rRef1.SetRelName( true ); if ( t->GetType() == svDoubleRef ) { - ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(t)->GetDoubleRef().Ref2; if ( rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel() ) rRef2.SetRelName( true ); } @@ -5506,12 +5791,16 @@ void ScCompiler::SetRelNameReference() // don't call for other token arrays! void ScCompiler::MoveRelWrap() { - for ( auto t: pArr->References() ) + for ( auto t: mpArr->References() ) { - if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef ) - ScRefUpdate::MoveRelWrap( rDoc, aPos, rDoc.MaxCol(), rDoc.MaxRow(), SingleDoubleRefModifier( *t->GetSingleRef() ).Ref() ); + if ( t->GetType() == svSingleRef ) + ScRefUpdate::MoveRelWrap( rDoc, aPos, rDoc.MaxCol(), rDoc.MaxRow(), SingleDoubleRefModifier( static_cast(t)->GetSingleRef() ).Ref() ); + else if ( t->GetType() == svExternalSingleRef ) + ScRefUpdate::MoveRelWrap( rDoc, aPos, rDoc.MaxCol(), rDoc.MaxRow(), SingleDoubleRefModifier( static_cast(t)->GetSingleRef() ).Ref() ); + else if (t->GetType() == svDoubleRef) + ScRefUpdate::MoveRelWrap( rDoc, aPos, rDoc.MaxCol(), rDoc.MaxRow(), static_cast(t)->GetDoubleRef() ); else - ScRefUpdate::MoveRelWrap( rDoc, aPos, rDoc.MaxCol(), rDoc.MaxRow(), *t->GetDoubleRef() ); + ScRefUpdate::MoveRelWrap( rDoc, aPos, rDoc.MaxCol(), rDoc.MaxRow(), static_cast(t)->GetDoubleRef() ); } } @@ -5522,10 +5811,14 @@ void ScCompiler::MoveRelWrap( const ScTokenArray& rArr, const ScDocument& rDoc, { for ( auto t: rArr.References() ) { - if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef ) - ScRefUpdate::MoveRelWrap( rDoc, rPos, nMaxCol, nMaxRow, SingleDoubleRefModifier( *t->GetSingleRef() ).Ref() ); + if ( t->GetType() == svSingleRef ) + ScRefUpdate::MoveRelWrap( rDoc, rPos, nMaxCol, nMaxRow, SingleDoubleRefModifier( static_cast(t)->GetSingleRef() ).Ref() ); + else if ( t->GetType() == svExternalSingleRef ) + ScRefUpdate::MoveRelWrap( rDoc, rPos, nMaxCol, nMaxRow, SingleDoubleRefModifier( static_cast(t)->GetSingleRef() ).Ref() ); + else if ( t->GetType() == svDoubleRef ) + ScRefUpdate::MoveRelWrap( rDoc, rPos, nMaxCol, nMaxRow, static_cast(t)->GetDoubleRef() ); else - ScRefUpdate::MoveRelWrap( rDoc, rPos, nMaxCol, nMaxRow, *t->GetDoubleRef() ); + ScRefUpdate::MoveRelWrap( rDoc, rPos, nMaxCol, nMaxRow, static_cast(t)->GetDoubleRef() ); } } @@ -5576,12 +5869,20 @@ OUString ScCompiler::SanitizeDefinedName(const OUString& rStr, const ScDocument& OUString sName = aBuffer.makeStringAndClear(); + if (sName.isEmpty()) + bValidName = false; + // Name can't be a valid cell reference if ((ScAddress().Parse(sName, rDoc, ::formula::FormulaGrammar::CONV_XL_A1) != ScRefFlags::ZERO) || (ScRange().Parse(sName, rDoc, ::formula::FormulaGrammar::CONV_XL_R1C1) + != ScRefFlags::ZERO) + || (ScAddress().Parse(sName, rDoc, ::formula::FormulaGrammar::CONV_XL_R1C1) != ScRefFlags::ZERO)) bValidName = false; + if (sName.equalsIgnoreAsciiCase("true") || sName.equalsIgnoreAsciiCase("false")) + bValidName = false; + if (!bValidName || sName != rStr) { sName = bValidName ? sName : "_" + sName; @@ -5595,7 +5896,14 @@ OUString ScCompiler::SanitizeDefinedName(const OUString& rStr, const ScDocument& void ScCompiler::CreateStringFromExternal( OUStringBuffer& rBuffer, const FormulaToken* pTokenP ) const { const FormulaToken* t = pTokenP; - sal_uInt16 nFileId = t->GetIndex(); + sal_uInt16 nFileId; + switch (t->GetType()) + { + case svExternalName: nFileId = static_cast(t)->GetFileId(); break; + case svExternalSingleRef: nFileId = static_cast(t)->GetFileId(); break; + case svExternalDoubleRef: nFileId = static_cast(t)->GetFileId(); break; + default: assert(false); nFileId = 0; + } ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager(); sal_uInt16 nUsedFileId = pRefMgr->convertFileIdToUsedFileId(nFileId); const OUString* pFileName = pRefMgr->getExternalFileName(nFileId); @@ -5605,27 +5913,42 @@ void ScCompiler::CreateStringFromExternal( OUStringBuffer& rBuffer, const Formul switch (t->GetType()) { case svExternalName: - rBuffer.append( - pConv->makeExternalNameStr(nUsedFileId, *pFileName, t->GetString().getString())); + { + FormulaToken* p = maArrIterator.PeekNextNoSpaces(); + OUString sName = static_cast(t)->GetName().getString(); + // An external name used as a function is followed by an opening + // parenthesis, or by the call operator when the name is the callee + // of a first-class call. In both cases the OOXML form needs the + // user-defined function prefix. + if (p && (p->GetOpCode() == ocOpen || p->GetOpCode() == ocCall)) + { + OUString sUDPrefix = mxSymbols->getSymbol(ocUDExternal); + if (FormulaGrammar::isOOXML(meGrammar) && !sName.matchIgnoreAsciiCase(sUDPrefix)) + sName = sUDPrefix + sName; + } + + rBuffer.append(pConv->makeExternalNameStr(nUsedFileId, *pFileName, sName)); + } break; case svExternalSingleRef: pConv->makeExternalRefStr(rDoc.GetSheetLimits(), - rBuffer, GetPos(), nUsedFileId, *pFileName, t->GetString().getString(), - *t->GetSingleRef()); + rBuffer, GetPos(), nUsedFileId, *pFileName, static_cast(t)->GetTableName().getString(), + static_cast(t)->GetSingleRef()); break; case svExternalDoubleRef: { std::vector aTabNames; pRefMgr->getAllCachedTableNames(nFileId, aTabNames); + auto pEDRToken = static_cast(t); // No sheet names is a valid case if external sheets were not // cached in this document and external document is not reachable, // else not and worth to be investigated. SAL_WARN_IF( aTabNames.empty(), "sc.core", "wrecked cache of external document? '" << - *pFileName << "' '" << t->GetString().getString() << "'"); + *pFileName << "' '" << pEDRToken->GetTableName().getString() << "'"); pConv->makeExternalRefStr( - rDoc.GetSheetLimits(), rBuffer, GetPos(), nUsedFileId, *pFileName, aTabNames, t->GetString().getString(), - *t->GetDoubleRef()); + rDoc.GetSheetLimits(), rBuffer, GetPos(), nUsedFileId, *pFileName, aTabNames, pEDRToken->GetTableName().getString(), + pEDRToken->GetDoubleRef()); } break; default: @@ -5637,7 +5960,11 @@ void ScCompiler::CreateStringFromExternal( OUStringBuffer& rBuffer, const Formul void ScCompiler::CreateStringFromMatrix( OUStringBuffer& rBuffer, const FormulaToken* pTokenP ) const { - const ScMatrix* pMatrix = pTokenP->GetMatrix(); + const ScMatrix* pMatrix; + if (pTokenP->GetType() == svMatrixCell) + pMatrix = static_cast(pTokenP)->GetMatrix(); + else + pMatrix = static_cast(pTokenP)->GetMatrix(); SCSIZE nC, nMaxC, nR, nMaxR; pMatrix->GetDimensions( nMaxC, nMaxR); @@ -5710,7 +6037,7 @@ bool ScCompiler::GetRefColRowNames(const FormulaToken* pToken, ScComplexRefData& bool& bInList, FormulaError& nError, bool bLookUpColRowNames) const { - ScSingleRefData rSingleRef = *pToken->GetSingleRef(); + ScSingleRefData rSingleRef = static_cast(pToken)->GetSingleRef(); const ScAddress aAbs = rSingleRef.toAbs(rDoc, aPos); if (!rDoc.ValidAddress(aAbs)) @@ -5852,8 +6179,7 @@ bool ScCompiler::GetRefColRowNames(const FormulaToken* pToken, ScComplexRefData& if (eOp1 != ocColRowName && eOp1 != ocIntersect && eOp2 != ocColRowName && eOp2 != ocIntersect) { - if ((SC_OPCODE_START_BIN_OP <= eOp1 && eOp1 < SC_OPCODE_STOP_BIN_OP) - || (SC_OPCODE_START_BIN_OP <= eOp2 && eOp2 < SC_OPCODE_STOP_BIN_OP)) + if (isBinaryOperatorOpCode(eOp1) || isBinaryOperatorOpCode(eOp2)) bSingle = true; } if (bSingle) @@ -5925,7 +6251,7 @@ OUString ScCompiler::CreateStringFromLabel(const FormulaToken* _pTokenP) const { pConv->makeRefStr(rDoc.GetSheetLimits(), aBuffer, meGrammar, aPos, aErrRef, GetSetupTabNames(), aRef, (aRef.Ref1 == aRef.Ref2), - (pArr && pArr->IsFromRangeName())); + (mpArr && mpArr->IsFromRangeName())); return aBuffer.makeStringAndClear(); } @@ -5938,7 +6264,7 @@ void ScCompiler::CreateStringFromSingleRef( OUStringBuffer& rBuffer, const Formu const FormulaToken* p; OUString aErrRef = GetCurrentOpCodeMap()->getSymbol(ocErrRef); const OpCode eOp = _pTokenP->GetOpCode(); - const ScSingleRefData& rRef = *_pTokenP->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(_pTokenP)->GetSingleRef(); ScComplexRefData aRef; aRef.Ref1 = aRef.Ref2 = rRef; if ( eOp == ocColRowName ) @@ -5967,10 +6293,10 @@ void ScCompiler::CreateStringFromSingleRef( OUStringBuffer& rBuffer, const Formu { rBuffer.append(ScCompiler::GetNativeSymbol(ocErrName)); pConv->makeRefStr(rDoc.GetSheetLimits(), rBuffer, meGrammar, aPos, aErrRef, - GetSetupTabNames(), aRef, true, (pArr && pArr->IsFromRangeName())); + GetSetupTabNames(), aRef, true, (mpArr && mpArr->IsFromRangeName())); } } - else if (pArr && (p = maArrIterator.PeekPrevNoSpaces()) && p->GetOpCode() == ocTableRefOpen) + else if (mpArr && (p = maArrIterator.PeekPrevNoSpaces()) && p->GetOpCode() == ocTableRefOpen) { OUString aStr; ScAddress aAbs = rRef.toAbs(rDoc, aPos); @@ -5999,14 +6325,14 @@ void ScCompiler::CreateStringFromSingleRef( OUStringBuffer& rBuffer, const Formu } else pConv->makeRefStr(rDoc.GetSheetLimits(), rBuffer, meGrammar, aPos, aErrRef, - GetSetupTabNames(), aRef, true, (pArr && pArr->IsFromRangeName())); + GetSetupTabNames(), aRef, true, (mpArr && mpArr->IsFromRangeName())); } void ScCompiler::CreateStringFromDoubleRef( OUStringBuffer& rBuffer, const FormulaToken* _pTokenP ) const { OUString aErrRef = GetCurrentOpCodeMap()->getSymbol(ocErrRef); pConv->makeRefStr(rDoc.GetSheetLimits(), rBuffer, meGrammar, aPos, aErrRef, GetSetupTabNames(), - *_pTokenP->GetDoubleRef(), false, (pArr && pArr->IsFromRangeName())); + static_cast(_pTokenP)->GetDoubleRef(), false, (mpArr && mpArr->IsFromRangeName())); } void ScCompiler::CreateStringFromIndex( OUStringBuffer& rBuffer, const FormulaToken* _pTokenP ) const @@ -6017,10 +6343,10 @@ void ScCompiler::CreateStringFromIndex( OUStringBuffer& rBuffer, const FormulaTo { case ocName: { - const ScRangeData* pData = GetRangeData( *_pTokenP); + const ScRangeData* pData = GetRangeData( static_cast(*_pTokenP)); if (pData) { - SCTAB nTab = _pTokenP->GetSheet(); + SCTAB nTab = static_cast(_pTokenP)->GetSheet(); if (nTab >= 0 && (nTab != aPos.Tab() || mbRefConventionChartOOXML)) { // Sheet-local on other sheet. @@ -6046,7 +6372,7 @@ void ScCompiler::CreateStringFromIndex( OUStringBuffer& rBuffer, const FormulaTo break; case ocDBArea: { - const ScDBData* pDBData = rDoc.GetDBCollection()->getNamedDBs().findByIndex(_pTokenP->GetIndex()); + const ScDBData* pDBData = rDoc.GetDBCollection()->getNamedDBs().findByIndex(static_cast(_pTokenP)->GetIndex()); if (pDBData) aBuffer.append(pDBData->GetName()); } @@ -6075,7 +6401,7 @@ void ScCompiler::CreateStringFromIndex( OUStringBuffer& rBuffer, const FormulaTo CreateStringFromDoubleRef( aBuffer, pRef); break; case svError: - AppendErrorConstant( aBuffer, pRef->GetError()); + AppendErrorConstant( aBuffer, static_cast(pRef)->GetError()); break; default: AppendErrorConstant( aBuffer, FormulaError::NoCode); @@ -6085,7 +6411,7 @@ void ScCompiler::CreateStringFromIndex( OUStringBuffer& rBuffer, const FormulaTo } else { - const ScDBData* pDBData = rDoc.GetDBCollection()->getNamedDBs().findByIndex(_pTokenP->GetIndex()); + const ScDBData* pDBData = rDoc.GetDBCollection()->getNamedDBs().findByIndex(static_cast(_pTokenP)->GetIndex()); if (pDBData) aBuffer.append(pDBData->GetName()); } @@ -6102,7 +6428,7 @@ void ScCompiler::CreateStringFromIndex( OUStringBuffer& rBuffer, const FormulaTo void ScCompiler::CreateStringFromDPFieldName( OUStringBuffer& rBuffer, const FormulaToken* _pTokenP ) const { - OUString aFieldName = _pTokenP->GetString().getString(); + OUString aFieldName = static_cast(_pTokenP)->GetString().getString(); if (aFieldName.indexOf('\'') >= 0) aFieldName = aFieldName.replaceAll(u"'", u"''"); rBuffer.append("'" + aFieldName + "'"); @@ -6193,7 +6519,7 @@ bool ScCompiler::HandleColRowName() bool ScCompiler::HandleDbData() { - ScDBData* pDBData = rDoc.GetDBCollection()->getNamedDBs().findByIndex(mpToken->GetIndex()); + ScDBData* pDBData = rDoc.GetDBCollection()->getNamedDBs().findByIndex(static_cast(mpToken.get())->GetIndex()); if ( !pDBData ) SetError(FormulaError::NoName); else if (mbJumpCommandReorder) @@ -6381,8 +6707,8 @@ bool ScCompiler::HandleTableRef() if (eState == sOpen && p->GetType() == svSingleRef) { bColumnRange = true; - bCol1Rel = p->GetSingleRef()->IsColRel(); - bCol1RelName = p->GetSingleRef()->IsRelName(); + bCol1Rel = static_cast(p)->GetSingleRef().IsColRel(); + bCol1RelName = static_cast(p)->GetSingleRef().IsRelName(); eState = sLast; } else @@ -6420,7 +6746,7 @@ bool ScCompiler::HandleTableRef() { case svSingleRef: { - aColRange.aStart = aColRange.aEnd = mpToken->GetSingleRef()->toAbs(rDoc, aPos); + aColRange.aStart = aColRange.aEnd = static_cast(mpToken.get())->GetSingleRef().toAbs(rDoc, aPos); if ( GetTokenIfOpCode( ocTableRefClose) && (nLevel--) && GetTokenIfOpCode( ocRange) && GetTokenIfOpCode( ocTableRefOpen) && (++nLevel) && @@ -6430,10 +6756,10 @@ bool ScCompiler::HandleTableRef() aColRange = ScRange( ScAddress::INITIALIZE_INVALID); else { - aColRange.aEnd = mpToken->GetSingleRef()->toAbs(rDoc, aPos); + aColRange.aEnd = static_cast(mpToken.get())->GetSingleRef().toAbs(rDoc, aPos); aColRange.PutInOrder(); - bCol2Rel = mpToken->GetSingleRef()->IsColRel(); - bCol2RelName = mpToken->GetSingleRef()->IsRelName(); + bCol2Rel = static_cast(mpToken.get())->GetSingleRef().IsColRel(); + bCol2RelName = static_cast(mpToken.get())->GetSingleRef().IsRelName(); } } } @@ -6461,7 +6787,7 @@ bool ScCompiler::HandleTableRef() { aRefData.SetRowRel( true); if (!bCol1RelName) - bCol1RelName = pArr->IsFromRangeName(); + bCol1RelName = mpArr->IsFromRangeName(); } aRefData.SetRelName( bCol1RelName); aRefData.SetFlag3D( true); @@ -6489,7 +6815,7 @@ bool ScCompiler::HandleTableRef() aRefData.Ref1.SetRowRel( true); aRefData.Ref2.SetRowRel( true); if (!bRelName) - bRelName = pArr->IsFromRangeName(); + bRelName = mpArr->IsFromRangeName(); } aRefData.Ref1.SetRelName( bRelName); aRefData.Ref2.SetRelName( bRelName); @@ -6569,8 +6895,11 @@ void ScCompiler::HandleIIOpCode(FormulaToken* token, FormulaToken*** pppToken, s // return true if opcode is handled bool ScCompiler::HandleIIOpCodeInternal(FormulaToken* token, FormulaToken*** pppToken, sal_uInt8 nNumParams) { - if (nNumParams > 0 && *pppToken[0] == nullptr) - return false; // Bad expression (see the dummy creation in FormulaCompiler::CompileTokenArray()) + for (sal_uInt8 i = 0; i < nNumParams; ++i) + { + if (!pppToken[i] || !*pppToken[i]) + return false; // Bad expression (see the dummy creation in FormulaCompiler::CompileTokenArray()) + } const OpCode nOpCode = token->GetOpCode(); @@ -6596,22 +6925,22 @@ bool ScCompiler::HandleIIOpCodeInternal(FormulaToken* token, FormulaToken*** ppp if ( eSumRangeType != svSingleRef && eSumRangeType != svDoubleRef ) return false; - const ScComplexRefData& rBaseRange = *(*pppToken[0])->GetDoubleRef(); + const ScComplexRefData& rBaseRange = static_cast(*pppToken[0])->GetDoubleRef(); ScComplexRefData aSumRange; if (eSumRangeType == svSingleRef) { - aSumRange.Ref1 = *(*pppToken[2])->GetSingleRef(); + aSumRange.Ref1 = static_cast(*pppToken[2])->GetSingleRef(); aSumRange.Ref2 = aSumRange.Ref1; } else - aSumRange = *(*pppToken[2])->GetDoubleRef(); + aSumRange = static_cast(*pppToken[2])->GetDoubleRef(); CorrectSumRange(rBaseRange, aSumRange, pppToken[2]); // TODO mark parameters as handled return true; } - else if (nOpCode >= SC_OPCODE_START_1_PAR && nOpCode < SC_OPCODE_STOP_1_PAR) + else if (nOpCode >= ocStartOneParameter && nOpCode < ocStopOneParameter) { if (nNumParams != 1) return false; @@ -6627,9 +6956,8 @@ bool ScCompiler::HandleIIOpCodeInternal(FormulaToken* token, FormulaToken*** ppp mPendingImplicitIntersectionOptimizations.emplace_back( pppToken[0], token ); return true; } - else if ((nOpCode >= SC_OPCODE_START_BIN_OP && nOpCode < SC_OPCODE_STOP_BIN_OP - && nOpCode != ocAnd && nOpCode != ocOr) - || nOpCode == ocRound || nOpCode == ocRoundUp || nOpCode == ocRoundDown) + else if ((isBinaryOperatorOpCode(nOpCode) && nOpCode != ocAnd && nOpCode != ocOr) + || nOpCode == ocRound || nOpCode == ocRoundUp || nOpCode == ocRoundDown) { if (nNumParams != 2) return false; @@ -6646,8 +6974,7 @@ bool ScCompiler::HandleIIOpCodeInternal(FormulaToken* token, FormulaToken*** ppp mPendingImplicitIntersectionOptimizations.emplace_back( pppToken[1], token ); return true; } - else if ((nOpCode >= SC_OPCODE_START_UN_OP && nOpCode < SC_OPCODE_STOP_UN_OP) - || nOpCode == ocPercentSign) + else if (isUnaryOperatorOpCode(nOpCode) || nOpCode == ocPercentSign) { if (nNumParams != 1) return false; @@ -6713,7 +7040,7 @@ void ScCompiler::PostProcessCode() { if( *item.parameterLocation != item.parameter ) // the parameter has been changed somehow continue; - if( item.parameterLocation >= pCode ) // the location is not inside the code (pCode points after the end) + if( item.parameterLocation >= mpCode ) // the location is not inside the code (pCode points after the end) continue; // E.g. "SUMPRODUCT(I5:I6+1)" shouldn't do implicit intersection. if( item.operation->IsInForceArray()) @@ -6730,11 +7057,8 @@ void ScCompiler::AnnotateOperands() void ScCompiler::ReplaceDoubleRefII(FormulaToken** ppDoubleRefTok) { - const ScComplexRefData* pRange = (*ppDoubleRefTok)->GetDoubleRef(); - if (!pRange) - return; - - const ScComplexRefData& rRange = *pRange; + assert((*ppDoubleRefTok)->GetType() == svDoubleRef); + const ScComplexRefData& rRange = static_cast(*ppDoubleRefTok)->GetDoubleRef(); // Can't do optimization reliably in this case (when row references are absolute). // Example : =SIN(A$1:A$10) filled in a formula group starting at B5 and of length 100. @@ -6939,29 +7263,28 @@ void ScCompiler::CorrectSumRange(const ScComplexRefData& rBaseRange, pNewSumRangeTok->IncRef(); } -// If we are loading, we might be loading each sheet in a separate thread at the same time -// It is unsafe to use ShrinkToDataArea on a range that refers to a different sheet whose -// columns and rows are still being added to. Even if it is the same sheet, it probably -// doesn't make sense to ShrinkToDataArea during document load. -static bool IsSafeToShrinkToDataArea(const ScDocument& rDoc) -{ - const bool bIsLoading = !rDoc.GetDocumentShell() || rDoc.GetDocumentShell()->IsLoading(); - return !bIsLoading; -} - void ScCompiler::AnnotateTrimOnDoubleRefs() { - if (!pCode || !(*(pCode - 1))) + if (!mpCode || !(*(mpCode - 1))) return; // OpCode of the "root" operator (which is already in RPN array). - OpCode eOpCode = (*(pCode - 1))->GetOpCode(); + OpCode eOpCode = (*(mpCode - 1))->GetOpCode(); // Param number of the "root" operator (which is already in RPN array). - sal_uInt8 nRootParam = (*(pCode - 1))->GetByte(); + auto p = *(mpCode - 1); + sal_uInt8 nRootParam = 0; + if (p->GetType() == svExternal) + nRootParam = static_cast(p)->GetByte(); + else if (eOpCode == ocBad) + nRootParam = static_cast(p)->GetByte(); + else if (p->GetType() == svFAP) + nRootParam = static_cast(p)->GetByte(); + else if (p->GetType() == svByte) + nRootParam = static_cast(p)->GetByte(); // eOpCode can be some operator which does not change with operands with or contains zero values. if (eOpCode == ocSum) { - FormulaToken** ppTok = pCode - 2; // exclude the root operator. + FormulaToken** ppTok = mpCode - 2; // exclude the root operator. // The following loop runs till a "pattern" is found or there is a mismatch // and marks the push DoubleRef arguments as trimmable when there is a match. // The pattern is @@ -7013,7 +7336,7 @@ void ScCompiler::AnnotateTrimOnDoubleRefs() if (!pTok->IsInForceArray()) return; - const short nJumpCount = pTok->GetJump()[0]; + const short nJumpCount = static_cast(pTok)->GetJump()[0]; if (nJumpCount != 2) // Should have THEN but no ELSE. return; @@ -7027,9 +7350,9 @@ void ScCompiler::AnnotateTrimOnDoubleRefs() ((pRHS->GetType() == svSingleRef || pRHS->GetType() == svDouble) && pLHS->GetType() == svDoubleRef)) { if (pLHS->GetType() == svDoubleRef) - pLHS->GetDoubleRef()->SetTrimToData(true); + static_cast(pLHS)->GetDoubleRef().SetTrimToData(true); else - pRHS->GetDoubleRef()->SetTrimToData(true); + static_cast(pRHS)->GetDoubleRef().SetTrimToData(true); return; } } @@ -7042,7 +7365,7 @@ void ScCompiler::AnnotateTrimOnDoubleRefs() } else if (eOpCode == ocSumProduct) { - FormulaToken** ppTok = pCode - 2; // exclude the root operator. + FormulaToken** ppTok = mpCode - 2; // exclude the root operator. // The following loop runs till a "pattern" is found or there is a mismatch // and marks the push DoubleRef arguments as trimmable when there is a match. // The pattern is @@ -7083,8 +7406,8 @@ void ScCompiler::AnnotateTrimOnDoubleRefs() StackVar rhsType = pRHS->GetType(); if (lhsType == svDoubleRef && rhsType == svDoubleRef) { - pLHS->GetDoubleRef()->SetTrimToData(true); - pRHS->GetDoubleRef()->SetTrimToData(true); + static_cast(pLHS)->GetDoubleRef().SetTrimToData(true); + static_cast(pRHS)->GetDoubleRef().SetTrimToData(true); } } } @@ -7116,11 +7439,11 @@ void ScCompiler::AnnotateTrimOnDoubleRefs() StackVar rhsType = pRHS->GetType(); if (lhsType == svDoubleRef && (rhsType == svSingleRef || rhsType == svDoubleRef)) { - pLHS->GetDoubleRef()->SetTrimToData(true); + static_cast(pLHS)->GetDoubleRef().SetTrimToData(true); } if (rhsType == svDoubleRef && (lhsType == svSingleRef || lhsType == svDoubleRef)) { - pRHS->GetDoubleRef()->SetTrimToData(true); + static_cast(pRHS)->GetDoubleRef().SetTrimToData(true); } } } @@ -7144,7 +7467,7 @@ void ScCompiler::AnnotateTrimOnDoubleRefs() if (!pTok->IsInForceArray()) return; - const short nJumpCount = pTok->GetJump()[0]; + const short nJumpCount = static_cast(pTok)->GetJump()[0]; if (nJumpCount != 2) // Should have THEN but no ELSE. return; @@ -7158,11 +7481,11 @@ void ScCompiler::AnnotateTrimOnDoubleRefs() StackVar rhsType = pRHS->GetType(); if (lhsType == svDoubleRef && (rhsType == svSingleRef || rhsType == svDouble)) { - pLHS->GetDoubleRef()->SetTrimToData(true); + static_cast(pLHS)->GetDoubleRef().SetTrimToData(true); } if ((lhsType == svSingleRef || lhsType == svDouble) && rhsType == svDoubleRef) { - pRHS->GetDoubleRef()->SetTrimToData(true); + static_cast(pRHS)->GetDoubleRef().SetTrimToData(true); } return; } @@ -7175,35 +7498,22 @@ void ScCompiler::AnnotateTrimOnDoubleRefs() } else if (eOpCode == ocSubTotal) { - // tdf#164843: Double references from relative named ranges can point to large - // ranges (MAXCOL/MAXROW) and because of that some function evaluation - // like SubTotal can be extremely slow when we call ScTable::CompileHybridFormula - // with these large ranges. Since all the SubTotal functions ignore empty cells - // its worth to optimize and trim the double references in SubTotal functions. - FormulaToken** ppTok = pCode - 2; + // tdf#164843: SubTotal references can span very large ranges (whole + // columns, or relative named ranges resolving to MAXCOL/MAXROW), which + // makes evaluation slow. Since SubTotal ignores empty cells, any such + // range can safely be trimmed to the data area before iterating. + // tdf#168013: only flag the references for trimming - do NOT rewrite them + // with SetRange(). Mutating the stored reference permanently shrinks the + // formula (=SUBTOTAL(9;A1:A99999) -> =SUBTOTAL(9;A2:A5)) and drops rows + // added later. The trim instead happens at evaluation time in + // ScValueIterator/ScCellIterator (gated on mnSubTotalFlags); the flag is + // also honoured by the matrix path in CreateMatrixFromDoubleRef. + FormulaToken** ppTok = mpCode - 2; while (*ppTok) { FormulaToken* pTok = *ppTok; if (pTok->GetType() == svDoubleRef) - { - ScComplexRefData* pRefData = pTok->GetDoubleRef(); - // do no set pRefData->SetTrimToData(true); because we need to trim here if possible - ScRange rRange = pRefData->toAbs(rDoc, aPos); - SCCOL nTempStartCol = rRange.aStart.Col(); - SCROW nTempStartRow = rRange.aStart.Row(); - SCCOL nTempEndCol = rRange.aEnd.Col(); - SCROW nTempEndRow = rRange.aEnd.Row(); - if (IsSafeToShrinkToDataArea(rDoc)) - rDoc.ShrinkToDataArea(rRange.aStart.Tab(), nTempStartCol, nTempStartRow, nTempEndCol, nTempEndRow); - // check if range is still valid - if (nTempStartRow <= nTempEndRow && nTempStartCol <= nTempEndCol) - { - rRange.aStart.Set(nTempStartCol, nTempStartRow, rRange.aStart.Tab()); - rRange.aEnd.Set(nTempEndCol, nTempEndRow, rRange.aEnd.Tab()); - if (rRange.IsValid()) - pRefData->SetRange(rDoc.GetSheetLimits(), rRange, aPos); - } - } + static_cast(pTok)->GetDoubleRef().SetTrimToData(true); --ppTok; } } diff --git a/sc/source/core/tool/consoli.cxx b/sc/source/core/tool/consoli.cxx index 1e8b4af980f7..1b9b468f617a 100644 --- a/sc/source/core/tool/consoli.cxx +++ b/sc/source/core/tool/consoli.cxx @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -175,10 +176,9 @@ void ScConsData::AddFields( const ScDocument* pSrcDoc, SCTAB nTab, aTitle = pSrcDoc->GetString(nCol, nRow1, nTab); if (!aTitle.isEmpty()) { - bool bFound = false; - for (SCSIZE i=0; iGetString(nCol1, nRow, nTab); if (!aTitle.isEmpty()) { - bool bFound = false; - for (SCSIZE i=0; i(i); - bFound = true; - } - OSL_ENSURE(bFound, "column not found"); + auto it = std::find(maColHeaders.begin(), + maColHeaders.begin() + nColCount, aTitle); + if (it != maColHeaders.begin() + nColCount) + nPos = static_cast(std::distance(maColHeaders.begin(), it)); + OSL_ENSURE(it != maColHeaders.begin() + nColCount, "column not found"); } pDestCols[nCol-nStartCol] = nPos; } @@ -311,14 +307,11 @@ void ScConsData::AddData( ScDocument* pSrcDoc, SCTAB nTab, SCROW nPos = SC_CONS_NOTFOUND; if (!aTitle.isEmpty()) { - bool bFound = false; - for (SCSIZE i=0; i(i); - bFound = true; - } - OSL_ENSURE(bFound, "row not found"); + auto it = std::find(maRowHeaders.begin(), + maRowHeaders.begin() + nRowCount, aTitle); + if (it != maRowHeaders.begin() + nRowCount) + nPos = static_cast(std::distance(maRowHeaders.begin(), it)); + OSL_ENSURE(it != maRowHeaders.begin() + nRowCount, "row not found"); } pDestRows[nRow-nStartRow] = nPos; } diff --git a/sc/source/core/tool/dbdata.cxx b/sc/source/core/tool/dbdata.cxx index a922ad24b943..5937033d6fba 100644 --- a/sc/source/core/tool/dbdata.cxx +++ b/sc/source/core/tool/dbdata.cxx @@ -962,13 +962,20 @@ std::vector ScDBData::GetTotalRowAttributes(formula::Form while ((pCell = aIter.GetNext(nCol, nRow)) != nullptr) { TableColumnAttributes aNameAttr; - if (pCell->getType() != CELLTYPE_FORMULA) + aNameAttr.mbHasContent = true; + CellType eCellType = pCell->getType(); + if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) { + // A totals row label describes text content, so only cells that + // actually hold text qualify. A plain number in the totals row is + // exported as a number and carries no label, since declaring it as + // a label would leave the exported table column and its underlying + // cell disagreeing about the cell's type. OUString aStr = pCell->getString(rDoc); if (!aStr.isEmpty()) aNameAttr.maTotalsRowLabel = aStr; } - else + else if (eCellType == CELLTYPE_FORMULA) { if (ScFormulaCell* pFC = pCell->getFormula()) { @@ -1098,7 +1105,7 @@ OUString ScDBData::GetSimpleSubTotalFunction(const ScTokenArray* pTokens, SCCOL { if (nIdx == 2) // { ocPush, formula::svDouble } { - sal_Int32 nFunc = static_cast(t->GetDouble()); + sal_Int32 nFunc = static_cast(static_cast(t)->GetDouble()); if (nFunc > 100.) nFunc -= 100; @@ -1111,7 +1118,8 @@ OUString ScDBData::GetSimpleSubTotalFunction(const ScTokenArray* pTokens, SCCOL } else if (nIdx == 4) // { ocTableRef, formula::svIndex } { - sal_uInt16 nDbIndex = t->GetIndex(); + assert(eOpCode == ocTableRef); + sal_uInt16 nDbIndex = static_cast(t)->GetIndex(); if (GetIndex() != nDbIndex) { return u"custom"_ustr; @@ -1119,8 +1127,8 @@ OUString ScDBData::GetSimpleSubTotalFunction(const ScTokenArray* pTokens, SCCOL } else if (nIdx == 6) // { ocPush, formula::svSingleRef } { - const ScSingleRefData* pRef = t->GetSingleRef(); - if (!(pRef && pRef->Col() == nCol && pRef->Row() == nHeaderRow)) + const ScSingleRefData& rRef = static_cast(t)->GetSingleRef(); + if (!(rRef.Col() == nCol && rRef.Row() == nHeaderRow)) { return u"custom"_ustr; } @@ -1311,6 +1319,12 @@ bool ScDBData::UpdateReference(const ScDocument& rDoc, UpdateRefMode eUpdateRefM void ScDBData::ExtendDataArea(const ScDocument& rDoc) { + // Only the anonymous range follows its data block; a named DB range is a + // fixed, user-owned extent, and a Total Row fixes the bottom edge too — + // neither must be auto-extended (e.g. on filter). + if (HasTotals() || GetTableStyleInfo() || GetName() != STR_DB_LOCAL_NONAME) + return; + // Extend the DB area to include data rows immediately below. SCCOL nOldCol1 = nStartCol, nOldCol2 = nEndCol; SCROW nOldEndRow = nEndRow; @@ -1328,23 +1342,6 @@ void ScDBData::ExtendDataArea(const ScDocument& rDoc) } } -void ScDBData::ExtendBackColorArea(const ScDocument& rDoc) -{ - // Extend the DB area to include data rows immediately below. - SCCOL nOldCol1 = nStartCol, nOldCol2 = nEndCol; - SCROW nOldEndRow = nEndRow; - rDoc.GetBackColorArea(nTable, nStartCol, nStartRow, nEndCol, nEndRow); - - if (nOldEndRow < rDoc.MaxRow() && nEndRow < nOldEndRow) - nEndRow = nOldEndRow; - - if (nStartCol != nOldCol1 || nEndCol != nOldCol2) - { - SAL_WARN_IF( !maTableColumnNames.empty(), "sc.core", "ScDBData::ExtendBackColorArea - invalidating column names/offsets"); - InvalidateTableColumnNames( true); - } -} - void ScDBData::StartTableColumnNamesListener() { if (mpContainer && bHasHeader) @@ -1514,7 +1511,7 @@ void ScDBData::RefreshTableColumnNames( ScDocument* pDoc ) } // Never leave us with empty names, try to remember previous name that - // might had been used to compile formulas, but only if same number of + // might have been used to compile formulas, but only if same number of // columns and no duplicates. if (bHaveEmpty && aNewNames.size() == maTableColumnNames.size()) { @@ -1548,7 +1545,7 @@ void ScDBData::RefreshTableColumnNames( ScDocument* pDoc ) mbTableColumnNamesDirty = false; } -void ScDBData::RefreshTableColumnNames( ScDocument& rDoc, const ScRange& rRange ) +void ScDBData::RefreshTableColumnNames( ScDocument& rDoc, const ScRangeList& rRangeList ) { // Header-less tables get names generated, completely empty a full refresh. if (mbTableColumnNamesDirty && (!HasHeader() || maTableColumnNames.empty())) @@ -1558,8 +1555,7 @@ void ScDBData::RefreshTableColumnNames( ScDocument& rDoc, const ScRange& rRange } // Check if this is affected for the range requested. - ScRange aIntersection( GetHeaderArea().Intersection( rRange)); - if (!aIntersection.IsValid()) + if (!rRangeList.Intersects(GetHeaderArea())) return; // Always fully refresh, only one cell of a range was broadcasted per area @@ -1668,11 +1664,6 @@ const ScTableStyleParam* ScDBData::GetTableStyleInfo() const return mpTableStyles.get(); } -void ScDBData::RemoveTableStyleInfo() -{ - mpTableStyles.reset(); -} - ScSubTotalFunc ScDBData::GetSubTotalFuncFromString(std::u16string_view sFunction) { if (sFunction == u"sum") @@ -1712,11 +1703,11 @@ OUString ScDBData::GetStringFromSubTotalFunc(ScSubTotalFunc eFunc) else if (eFunc == SUBTOTAL_FUNC_CNT2) return u"count"_ustr; else if (eFunc == SUBTOTAL_FUNC_PROD) - return u"custom"_ustr; // ooxml not support in Total row + return u"custom"_ustr; // ooxml not supported in Total row else if (eFunc == SUBTOTAL_FUNC_AVE) return u"average"_ustr; else if (eFunc == SUBTOTAL_FUNC_MED) - return u"custom"_ustr; // ooxml not support in Total row + return u"custom"_ustr; // ooxml not supported in Total row else if (eFunc == SUBTOTAL_FUNC_MAX) return u"max"_ustr; else if (eFunc == SUBTOTAL_FUNC_MIN) @@ -1724,7 +1715,7 @@ OUString ScDBData::GetStringFromSubTotalFunc(ScSubTotalFunc eFunc) else if (eFunc == SUBTOTAL_FUNC_STD) return u"stdDev"_ustr; else if (eFunc == SUBTOTAL_FUNC_STDP) - return u"custom"_ustr; // ooxml not support in Total row + return u"custom"_ustr; // ooxml not supported in Total row else if (eFunc == SUBTOTAL_FUNC_VAR) return u"var"_ustr; else @@ -1938,7 +1929,7 @@ void ScDBCollection::NamedDBs::initInserted( ScDBData* p ) if (mrDoc.IsClipOrUndo()) return; - p->StartTableColumnNamesListener(); // needs the container be set already + p->StartTableColumnNamesListener(); // needs the container to be set already if (!p->AreTableColumnNamesDirty()) return; @@ -2309,14 +2300,12 @@ std::vector ScDBCollection::GetAllNamedDBsInArea(SCCOL nCol1, S void ScDBCollection::RefreshDirtyTableColumnNames() { - for (size_t i=0; i < maNamedDBs.maDirtyTableColumnNames.size(); ++i) + if (maNamedDBs.maDirtyTableColumnNames.empty()) + return; + for (auto const& it : maNamedDBs) { - const ScRange & rRange = maNamedDBs.maDirtyTableColumnNames[i]; - for (auto const& it : maNamedDBs) - { - if (it->AreTableColumnNamesDirty()) - it->RefreshTableColumnNames( maNamedDBs.mrDoc, rRange); - } + if (it->AreTableColumnNamesDirty()) + it->RefreshTableColumnNames( maNamedDBs.mrDoc, maNamedDBs.maDirtyTableColumnNames); } maNamedDBs.maDirtyTableColumnNames.RemoveAll(); } diff --git a/sc/source/core/tool/ddelink.cxx b/sc/source/core/tool/ddelink.cxx index dfa6b0e955b1..8a9ac579e6f8 100644 --- a/sc/source/core/tool/ddelink.cxx +++ b/sc/source/core/tool/ddelink.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include #include #include #include @@ -29,6 +30,7 @@ #include #include +#include #include #include #include @@ -123,6 +125,10 @@ void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const sfx2::SvBaseLink::UpdateResult ScDdeLink::DataChanged( const OUString& rMimeType, const css::uno::Any & rValue ) { + if (rDoc.GetDocumentShell() + && !rDoc.GetDocumentShell()->GetEmbeddedObjectContainer().getUserAllowsLinkUpdate()) + return SUCCESS; + // we only master strings... if ( SotClipboardFormatId::STRING != SotExchange::GetFormatIdFromMimeType( rMimeType )) return SUCCESS; diff --git a/sc/source/core/tool/editutil.cxx b/sc/source/core/tool/editutil.cxx index 433be6bb18be..a00a5f026964 100644 --- a/sc/source/core/tool/editutil.cxx +++ b/sc/source/core/tool/editutil.cxx @@ -136,7 +136,7 @@ OUString ScEditUtil::GetString( const EditTextObject& rEditText, const ScDocumen return GetMultilineString( rEE); } -std::unique_ptr ScEditUtil::CreateURLObjectFromURL( ScDocument& rDoc, const OUString& rURL, const OUString& rText ) +EditTextObject ScEditUtil::CreateURLObjectFromURL( ScDocument& rDoc, const OUString& rURL, const OUString& rText ) { SvxURLField aUrlField( rURL, rText, SvxURLFormat::AppDefault); EditEngine& rEE = rDoc.GetEditEngine(); @@ -180,10 +180,8 @@ void ScEditUtil::RemoveCharAttribs( EditTextObject& rEditText, const ScPatternAt } } -std::unique_ptr ScEditUtil::Clone( const EditTextObject& rObj, ScDocument& rDestDoc ) +EditTextObject ScEditUtil::Clone( const EditTextObject& rObj, ScDocument& rDestDoc ) { - std::unique_ptr pNew; - EditEngine& rEngine = rDestDoc.GetEditEngine(); if (rObj.HasOnlineSpellErrors()) { @@ -193,17 +191,16 @@ std::unique_ptr ScEditUtil::Clone( const EditTextObject& rObj, S if (bNewControl) rEngine.SetControlWord(nControl | nSpellControl); rEngine.SetText(rObj); - pNew = rEngine.CreateTextObject(); + EditTextObject aNew = rEngine.CreateTextObject(); if (bNewControl) rEngine.SetControlWord(nControl); + return aNew; } else { rEngine.SetText(rObj); - pNew = rEngine.CreateTextObject(); + return rEngine.CreateTextObject(); } - - return pNew; } OUString ScEditUtil::GetCellFieldValue( diff --git a/sc/source/core/tool/formulaopt.cxx b/sc/source/core/tool/formulaopt.cxx index 745428e36c12..28daf73dd76a 100644 --- a/sc/source/core/tool/formulaopt.cxx +++ b/sc/source/core/tool/formulaopt.cxx @@ -121,11 +121,6 @@ bool ScFormulaOptions::operator==( const ScFormulaOptions& rOpt ) const && meReCalcOptiRowHeights == rOpt.meReCalcOptiRowHeights; } -bool ScFormulaOptions::operator!=( const ScFormulaOptions& rOpt ) const -{ - return !(operator==(rOpt)); -} - ScTpFormulaItem::ScTpFormulaItem( ScFormulaOptions aOpt ) : SfxPoolItem ( SID_SCFORMULAOPTIONS ), theOptions (std::move( aOpt )) diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx index e326da7f2121..619d1265456b 100644 --- a/sc/source/core/tool/formularesult.cxx +++ b/sc/source/core/tool/formularesult.cxx @@ -102,7 +102,7 @@ void ScFormulaResult::ResolveToken( const formula::FormulaToken * p ) switch (p->GetType()) { case formula::svError: - mnError = p->GetError(); + mnError = static_cast(p)->GetError(); p->DecRef(); mbToken = false; // set in case mnError is 0 now, which shouldn't happen but ... @@ -121,7 +121,7 @@ void ScFormulaResult::ResolveToken( const formula::FormulaToken * p ) mbValueCached = true; break; case formula::svDouble: - mfValue = p->GetDouble(); + mfValue = static_cast(p)->GetDouble(); p->DecRef(); mbToken = false; meMultiline = MULTILINE_FALSE; @@ -347,6 +347,16 @@ bool ScFormulaResult::IsValueNoError() const } } +bool ScFormulaResult::IsString() const +{ + return isString(GetCellResultType()); +} + +bool ScFormulaResult::IsCallable() const +{ + return GetCellResultType() == formula::svCallable; +} + bool ScFormulaResult::IsMultiline() const { if (meMultiline == MULTILINE_UNKNOWN) @@ -380,12 +390,13 @@ bool ScFormulaResult::GetErrorOrDouble( FormulaError& rErr, double& rVal ) const if (GetType() == formula::svMatrixCell) { // don't need to test for mpToken here, GetType() already did it - rErr = static_cast(mpToken)-> - GetUpperLeftToken()->GetError(); + auto pMCRToken = static_cast(mpToken); + auto pFEToken = static_cast(pMCRToken->GetUpperLeftToken().get()); + rErr = pFEToken->GetError(); } else if (mpToken) { - rErr = mpToken->GetError(); + rErr = static_cast(mpToken)->GetError(); } } @@ -414,12 +425,13 @@ sc::FormulaResultValue ScFormulaResult::GetResult() const if (GetType() == formula::svMatrixCell) { // don't need to test for mpToken here, GetType() already did it - nErr = static_cast(mpToken)-> - GetUpperLeftToken()->GetError(); + auto pMCRToken = static_cast(mpToken); + auto pFEToken = static_cast(pMCRToken->GetUpperLeftToken().get()); + nErr = pFEToken->GetError(); } else if (mpToken) { - nErr = mpToken->GetError(); + nErr = static_cast(mpToken)->GetError(); } } @@ -448,11 +460,14 @@ FormulaError ScFormulaResult::GetResultError() const if (sv == formula::svError) { if (GetType() == formula::svMatrixCell) + { // don't need to test for mpToken here, GetType() already did it - return static_cast(mpToken)-> - GetUpperLeftToken()->GetError(); + auto pMCRToken = static_cast(mpToken); + auto pFEToken = static_cast(pMCRToken->GetUpperLeftToken().get()); + return pFEToken->GetError(); + } if (mpToken) - return mpToken->GetError(); + return static_cast(mpToken)->GetError(); } return FormulaError::NONE; } @@ -471,6 +486,16 @@ formula::FormulaConstTokenRef ScFormulaResult::GetToken() const return nullptr; } +formula::FormulaTokenRef ScFormulaResult::CloneToken() const +{ + if (mnError != FormulaError::NONE) + return new formula::FormulaErrorToken(mnError); + else if (mbToken) + return mpToken->Clone(); + else + return new formula::FormulaDoubleToken(mfValue); +} + formula::FormulaConstTokenRef ScFormulaResult::GetCellResultToken() const { if (GetType() == formula::svMatrixCell) @@ -492,13 +517,13 @@ double ScFormulaResult::GetDouble() const switch (mpToken->GetType()) { case formula::svHybridCell: - return mpToken->GetDouble(); + return static_cast(mpToken)->GetDouble(); case formula::svMatrixCell: { const ScMatrixCellResultToken* p = static_cast(mpToken); if (p->GetUpperLeftType() == formula::svDouble) - return p->GetUpperLeftToken()->GetDouble(); + return static_cast(p->GetUpperLeftToken().get())->GetDouble(); } break; default: @@ -521,14 +546,15 @@ const svl::SharedString & ScFormulaResult::GetString() const switch (mpToken->GetType()) { case formula::svString: + return static_cast(mpToken)->GetString(); case formula::svHybridCell: - return mpToken->GetString(); + return static_cast(mpToken)->GetString(); case formula::svMatrixCell: { const ScMatrixCellResultToken* p = static_cast(mpToken); if (p->GetUpperLeftType() == formula::svString) - return p->GetUpperLeftToken()->GetString(); + return static_cast(p->GetUpperLeftToken().get())->GetString(); } break; default: @@ -538,10 +564,33 @@ const svl::SharedString & ScFormulaResult::GetString() const return svl::SharedString::getEmptyString(); } +formula::FormulaCallableRef ScFormulaResult::GetCallable() const +{ + if (mbToken && mpToken) + { + switch (mpToken->GetType()) + { + case formula::svCallable: + return static_cast(mpToken)->GetCallable(); + case formula::svMatrixCell: + { + const ScMatrixCellResultToken* p = + static_cast(mpToken); + if (p->GetUpperLeftType() == formula::svCallable) + return static_cast(p->GetUpperLeftToken().get())->GetCallable(); + } + break; + default: + ; // nothing + } + } + return nullptr; +} + ScConstMatrixRef ScFormulaResult::GetMatrix() const { if (GetType() == formula::svMatrixCell) - return mpToken->GetMatrix(); + return static_cast(mpToken)->GetMatrix(); return nullptr; } @@ -641,8 +690,11 @@ void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRe const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const { - return (GetType() == formula::svMatrixCell ? - static_cast(mpToken) : nullptr); + // Inspect mpToken directly: GetType() would report svError when mnError is + // set, hiding the still-valid matrix token from callers that only need the + // declared dimensions. + return (mbToken && mpToken && mpToken->GetType() == formula::svMatrixCell + ? static_cast(mpToken) : nullptr); } ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellTokenNonConst() diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 708c80171215..7799f8c2de12 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include @@ -67,10 +69,23 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -78,6 +93,10 @@ #include #include #include +#include + +using namespace com::sun::star; +using namespace formula; const sal_uInt64 n2power48 = SAL_CONST_UINT64( 281474976710656); // 2^48 @@ -87,7 +106,7 @@ using namespace formula; void ScInterpreter::ScIfJump() { - const short* pJump = pCur->GetJump(); + const short* pJump = static_cast(pCur)->GetJump(); short nJumpCount = pJump[ 0 ]; MatrixJumpConditionToMatrix(); if ( GetStackType() != svMatrix ) @@ -195,7 +214,7 @@ static void lcl_storeJumpMatResult( void ScInterpreter::ScIfError( bool bNAonly ) { - const short* pJump = pCur->GetJump(); + const short* pJump = static_cast(pCur)->GetJump(); short nJumpCount = pJump[ 0 ]; if (!sp || nJumpCount != 2) { @@ -365,7 +384,7 @@ void ScInterpreter::ScChooseJump() // We have to set a jump, if there was none chosen because of an error set // it to endpoint. bool bHaveJump = false; - const short* pJump = pCur->GetJump(); + const short* pJump = static_cast(pCur)->GetJump(); short nJumpCount = pJump[ 0 ]; MatrixJumpConditionToMatrix(); switch ( GetStackType() ) @@ -491,7 +510,7 @@ static void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, SCSIZE nParmCols, SCSIZE bool ScInterpreter::JumpMatrix( short nStackLevel ) { - pJumpMatrix = pStack[sp-nStackLevel]->GetJumpMatrix(); + pJumpMatrix = static_cast(pStack[sp-nStackLevel])->GetJumpMatrix(); bool bHasResMat = pJumpMatrix->HasResultMatrix(); SCSIZE nC, nR; if ( nStackLevel == 2 ) @@ -585,7 +604,7 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) /* TODO: What about error handling and do we actually * need the result matrix above at all in this case? */ ScComplexRefData aRef; - aRef.Ref1 = aRef.Ref2 = *(xRef->GetSingleRef()); + aRef.Ref1 = aRef.Ref2 = static_cast(xRef.get())->GetSingleRef(); pJumpMatrix->GetRefList().push_back( aRef); } } @@ -607,8 +626,8 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) // Do not modify the original range because we use it // to adjust the size of the result matrix if necessary. ScAddress aAdr( aRange.aStart); - sal_uLong nCol = static_cast(aAdr.Col()) + nC; - sal_uLong nRow = static_cast(aAdr.Row()) + nR; + sal_uInt16 nCol = static_cast(aAdr.Col()) + nC; + sal_uInt32 nRow = static_cast(aAdr.Row()) + nR; if ((nCol > o3tl::make_unsigned(aRange.aEnd.Col()) && aRange.aEnd.Col() != aRange.aStart.Col()) || (nRow > o3tl::make_unsigned(aRange.aEnd.Row()) && @@ -666,7 +685,7 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) { /* TODO: What about error handling and do we actually * need the result matrix above at all in this case? */ - pJumpMatrix->GetRefList().push_back( *(xRef->GetDoubleRef())); + pJumpMatrix->GetRefList().push_back( static_cast(xRef.get())->GetDoubleRef() ); } } break; @@ -684,10 +703,10 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) switch (pToken->GetType()) { case svDouble: - pJumpMatrix->PutResultDouble( pToken->GetDouble(), nC, nR ); + pJumpMatrix->PutResultDouble( static_cast(pToken.get())->GetDouble(), nC, nR ); break; case svString: - pJumpMatrix->PutResultString( pToken->GetString(), nC, nR ); + pJumpMatrix->PutResultString( static_cast(pToken.get())->GetString(), nC, nR ); break; case svEmptyCell: pJumpMatrix->PutResultEmpty( nC, nR ); @@ -805,7 +824,7 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) !FormulaCompiler::IsOpCodeJumpCommand( pJumpMatrix->GetOpCode()) && aCode.PeekNextOperator()) { - FormulaTokenRef xRef = new ScRefListToken(true); + ::boost::intrusive_ptr xRef = new ScRefListToken(true); *(xRef->GetRefList()) = pJumpMatrix->GetRefList(); pJumpMatrix = nullptr; Pop(); @@ -1543,6 +1562,66 @@ void ScInterpreter::ScNeg() } } +void ScInterpreter::ScSingleValue() +{ + // The @ implicit-intersection operator collapses an operand to + // a single value. For a bare range, pick the slot row-aligned + // (or column-aligned) with the formula cell, and push #VALUE! + // when no slot matches. For a computed matrix, pick the + // upper-left value, whether or not it knows where its values sit. + nFuncFmtType = nCurFmtType; + StackVar eType = GetStackType(); + if (eType == svDoubleRef || IsTopMatrixReference()) + { + ScRange aRange; + if (eType == svDoubleRef) + { + PopDoubleRef(aRange); + } + else + { + const auto* pRangeToken = static_cast(pStack[sp - 1]); + const ScComplexRefData& rRef = pRangeToken->GetDoubleRef(); + aRange.aStart = rRef.Ref1.toAbs(mrDoc, aPos); + aRange.aEnd = rRef.Ref2.toAbs(mrDoc, aPos); + Pop(); + } + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } + ScAddress aAdr; + if (!DoubleRefToPosSingleRef(aRange, aAdr)) + { + // DoubleRefToPosSingleRef set FormulaError::NoValue. + PushError(nGlobalError); + return; + } + ScRefCellValue aCell(mrDoc, aAdr); + if (aCell.hasString()) + PushString(aCell.getString(mrDoc)); + else + PushDouble(GetCellValue(aAdr, aCell)); + return; + } + if (eType == svMatrix) + { + ScMatrixRef pMat = GetMatrix(); + if (!pMat) + { + PushIllegalParameter(); + return; + } + ScMatrixValue aVal = pMat->Get(0, 0); + if (aVal.nType == ScMatValType::String || aVal.nType == ScMatValType::Empty) + PushString(aVal.aStr); + else + PushDouble(aVal.fVal); + } + // Non-matrix, non-range operand passes through unchanged. +} + void ScInterpreter::ScPercentSign() { nFuncFmtType = SvNumFormatType::PERCENT; @@ -1557,6 +1636,89 @@ void ScInterpreter::ScPercentSign() cPar = nSavePar; } +void ScInterpreter::ScSpilledRange() +{ + // The # postfix operator expands a master cell's spill range + // into a matrix. A plain formula cell falls back to its scalar + // value. An empty cell, a number, a string, or a non-master + // spill slot yields #REF!, since none of them is a dynamic-array + // master. + // + // The operator refers to a single cell, so an operand wider than + // that has no master. A range, a reference list and a computed + // matrix all give #REF!. + const StackVar eOperandType = GetStackType(); + if (eOperandType != svSingleRef && eOperandType != svError) + { + Pop(); + PushError(FormulaError::NoRef); + return; + } + + ScAddress aAddress; + PopSingleRef(aAddress); + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } + + ScFormulaCell* pFormulaCell = mrDoc.GetFormulaCell(aAddress); + if (!pFormulaCell) + { + PushError(FormulaError::NoRef); + return; + } + if (pFormulaCell->GetMatrixFlag() == ScMatrixMode::Reference) + { + PushError(FormulaError::NoRef); + return; + } + if (pFormulaCell->GetMatrixFlag() != ScMatrixMode::Formula) + { + PushCellResultToken(false, aAddress, nullptr, nullptr); + return; + } + + // Force the master to interpret if it has not yet, so that its + // matrix result is materialized before we read it. + pFormulaCell->MaybeInterpret(); + + SCCOL nCols = 0; + SCROW nRows = 0; + pFormulaCell->GetMatColsRows(nCols, nRows); + if (nCols <= 1 && nRows <= 1) + { + PushCellResultToken(false, aAddress, nullptr, nullptr); + return; + } + + // Push the spill range as a matrix so binary operators and + // aggregating functions see all values. Pushing a double reference + // would let arithmetic operators fold it to a single value through + // implicit intersection. The source range travels with the matrix + // through ScMatrixRangeToken so a plain cell receiving the spill + // range as its final result can reduce it via implicit + // intersection at result-storage time. + ScMatrixRef pMatrix = CreateMatrixFromDoubleRef(nullptr, + aAddress.Col(), aAddress.Row(), aAddress.Tab(), + aAddress.Col() + nCols - 1, aAddress.Row() + nRows - 1, aAddress.Tab()); + if (pMatrix) + { + sc::RangeMatrix aRangeMat; + aRangeMat.mpMat = std::move(pMatrix); + aRangeMat.mnCol1 = aAddress.Col(); + aRangeMat.mnRow1 = aAddress.Row(); + aRangeMat.mnTab1 = aAddress.Tab(); + aRangeMat.mnCol2 = aAddress.Col() + nCols - 1; + aRangeMat.mnRow2 = aAddress.Row() + nRows - 1; + aRangeMat.mnTab2 = aAddress.Tab(); + PushMatrix(aRangeMat); + } + else + PushIllegalArgument(); +} + void ScInterpreter::ScNot() { nFuncFmtType = SvNumFormatType::LOGICAL; @@ -1696,7 +1858,7 @@ void ScInterpreter::ScRandomImpl( const std::functionGetJumpMatrix()->GetDimensions( nC, nR); + static_cast(pStack[sp-1])->GetJumpMatrix()->GetDimensions( nC, nR); nCols = std::max(0, static_cast(nC)); nRows = std::max(0, static_cast(nR)); } @@ -2527,7 +2689,7 @@ void ScInterpreter::ScCellExternal() SCCOL nCol; SCROW nRow; SCTAB nTab; - aRef.SetAbsTab(0); // external ref has a tab index of -1, which SingleRefToVars() don't like. + aRef.SetAbsTab(0); // external ref has a tab index of -1, which SingleRefToVars() doesn't like. SingleRefToVars(aRef, nCol, nRow, nTab); if (nGlobalError != FormulaError::NONE) { @@ -2601,13 +2763,13 @@ void ScInterpreter::ScCellExternal() switch (pToken->GetType()) { case svString: - PushString(pToken->GetString()); + PushString(static_cast(pToken.get())->GetString()); break; case svDouble: - PushString(OUString::number(pToken->GetDouble())); + PushString(OUString::number(static_cast(pToken.get())->GetDouble())); break; case svError: - PushString(ScGlobal::GetErrorString(pToken->GetError())); + PushString(ScGlobal::GetErrorString(static_cast(pToken.get())->GetError())); break; default: PushString(OUString()); @@ -2686,7 +2848,7 @@ void ScInterpreter::ScIsRef() break; case svRefList : { - FormulaConstTokenRef x = PopToken(); + auto x = PopToken(); if ( nGlobalError == FormulaError::NONE ) bRes = !x->GetRefList()->empty(); } @@ -2707,6 +2869,15 @@ void ScInterpreter::ScIsRef() bRes = true; } break; + case svMatrix: + { + // A spilled-range reference travels as a matrix that + // carries its source range. It answers as a reference, + // while a plain computed matrix does not. + bRes = IsTopMatrixReference(); + Pop(); + } + break; default: Pop(); } @@ -2785,12 +2956,96 @@ void ScInterpreter::ScIsValue() PushInt( int(bRes) ); } +namespace { + +// Whether ISFORMULA counts a cell as a formula. A dynamic-array +// spill cell is not a formula, only its master is. A classic array +// formula cell stays a formula. +bool lclReportsAsFormula(const ScDocument& rDocument, const ScAddress& rPosition) +{ + if (rDocument.GetCellType(rPosition) != CELLTYPE_FORMULA) + return false; + const ScFormulaCell* pCell = rDocument.GetFormulaCell(rPosition); + if (pCell && pCell->GetMatrixFlag() == ScMatrixMode::Reference) + { + ScAddress aOrigin; + if (pCell->GetMatrixOrigin(rDocument, aOrigin)) + { + const ScFormulaCell* pMaster = rDocument.GetFormulaCell(aOrigin); + if (pMaster && pMaster->IsDynamicArrayMaster()) + return false; + } + } + return true; +} + +} + +void ScInterpreter::PushIsFormulaMatrix(const ScRange& rRange) +{ + ScMatrixRef pResultMatrix = GetNewMat( + SCSIZE(rRange.aEnd.Col() - rRange.aStart.Col() + 1), + SCSIZE(rRange.aEnd.Row() - rRange.aStart.Row() + 1), true); + if (!pResultMatrix) + { + PushError( FormulaError::MatrixSize); + return; + } + + /* TODO: we really should have a gap-aware cell iterator. */ + SCSIZE i = 0, j = 0; + ScAddress aAddress( 0, 0, rRange.aStart.Tab()); + for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol) + { + aAddress.SetCol(nCol); + for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow) + { + aAddress.SetRow(nRow); + pResultMatrix->PutBoolean(lclReportsAsFormula(mrDoc, aAddress), i, j); + ++j; + } + ++i; + j = 0; + } + + PushMatrix( pResultMatrix); +} + void ScInterpreter::ScIsFormula() { nFuncFmtType = SvNumFormatType::LOGICAL; bool bRes = false; switch ( GetStackType() ) { + case svMatrix: + { + // A spilled-range reference carries its source range and + // reports ISFORMULA per cell of that range, the same as a + // plain range. A plain computed matrix is not a reference + // and reports false. + if (!IsTopMatrixReference()) + { + Pop(); + break; + } + const ScComplexRefData& rReference + = static_cast(pStack[sp - 1])->GetDoubleRef(); + ScRange aRange(rReference.Ref1.toAbs(mrDoc, aPos), rReference.Ref2.toAbs(mrDoc, aPos)); + Pop(); + if (IsInArrayContext()) + { + PushIsFormulaMatrix(aRange); + return; + } + ScAddress aAddress; + if (!DoubleRefToPosSingleRef(aRange, aAddress)) + { + PushError(nGlobalError); + return; + } + bRes = lclReportsAsFormula(mrDoc, aAddress); + } + break; case svDoubleRef : if (IsInArrayContext()) { @@ -2808,33 +3063,7 @@ void ScInterpreter::ScIsFormula() PushIllegalArgument(); return; } - - ScMatrixRef pResMat = GetNewMat( static_cast(nCol2 - nCol1 + 1), - static_cast(nRow2 - nRow1 + 1), true); - if (!pResMat) - { - PushError( FormulaError::MatrixSize); - return; - } - - /* TODO: we really should have a gap-aware cell iterator. */ - SCSIZE i=0, j=0; - ScAddress aAdr( 0, 0, nTab1); - for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) - { - aAdr.SetCol(nCol); - for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) - { - aAdr.SetRow(nRow); - ScRefCellValue aCell(mrDoc, aAdr); - pResMat->PutBoolean( (aCell.getType() == CELLTYPE_FORMULA), i,j); - ++j; - } - ++i; - j = 0; - } - - PushMatrix( pResMat); + PushIsFormulaMatrix(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2)); return; } [[fallthrough]]; @@ -2844,7 +3073,7 @@ void ScInterpreter::ScIsFormula() if ( !PopDoubleRefOrSingleRef( aAdr ) ) break; - bRes = (mrDoc.GetCellType(aAdr) == CELLTYPE_FORMULA); + bRes = lclReportsAsFormula(mrDoc, aAdr); } break; default: @@ -2958,7 +3187,7 @@ void ScInterpreter::ScIsNV() ScExternalRefCache::TokenRef pToken; PopExternalSingleRef(pToken); if (nGlobalError == FormulaError::NotAvailable || - (pToken && pToken->GetType() == svError && pToken->GetError() == FormulaError::NotAvailable)) + (pToken && pToken->GetType() == svError && static_cast(pToken.get())->GetError() == FormulaError::NotAvailable)) bRes = true; } break; @@ -3015,7 +3244,7 @@ void ScInterpreter::ScIsErr() ScExternalRefCache::TokenRef pToken; PopExternalSingleRef(pToken); if ((nGlobalError != FormulaError::NONE && nGlobalError != FormulaError::NotAvailable) || !pToken || - (pToken->GetType() == svError && pToken->GetError() != FormulaError::NotAvailable)) + (pToken->GetType() == svError && static_cast(pToken.get())->GetError() != FormulaError::NotAvailable)) bRes = true; } break; @@ -3162,7 +3391,7 @@ bool ScInterpreter::IsEven() PopExternalSingleRef(pToken); if (nGlobalError == FormulaError::NONE && pToken->GetType() == svDouble) { - fVal = pToken->GetDouble(); + fVal = static_cast(pToken.get())->GetDouble(); bRes = true; } } @@ -4950,7 +5179,7 @@ void ScInterpreter::ScMatch() return; VectorSearchArguments vsa; - vsa.nSearchOpCode = SC_OPCODE_MATCH; + vsa.nSearchOpCode = ocMatch; // get match mode double fType = ( nParamCount == 3 ? GetDouble() : 1.0 ); @@ -5066,12 +5295,16 @@ void ScInterpreter::ScMatch() if (pToken->GetType() == svDouble) { vsa.isStringSearch = false; - vsa.fSearchVal = pToken->GetDouble(); + vsa.fSearchVal = static_cast(pToken.get())->GetDouble(); + } + else if (pToken->GetType() == svString) + { + vsa.isStringSearch = true; + vsa.sSearchStr = static_cast(pToken.get())->GetString(); } else { vsa.isStringSearch = true; - vsa.sSearchStr = pToken->GetString(); } } break; @@ -5112,7 +5345,7 @@ void ScInterpreter::ScXMatch() return; VectorSearchArguments vsa; - vsa.nSearchOpCode = SC_OPCODE_X_MATCH; + vsa.nSearchOpCode = ocXMatch; // get search mode if (nParamCount == 4) @@ -5246,12 +5479,16 @@ void ScInterpreter::ScXMatch() if (pToken->GetType() == svDouble) { vsa.isStringSearch = false; - vsa.fSearchVal = pToken->GetDouble(); + vsa.fSearchVal = static_cast(pToken.get())->GetDouble(); + } + else if (pToken->GetType() == svString) + { + vsa.isStringSearch = true; + vsa.sSearchStr = static_cast(pToken.get())->GetString(); } else { vsa.isStringSearch = true; - vsa.sSearchStr = pToken->GetString(); } } break; @@ -5452,9 +5689,9 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) } if (pToken->GetType() == svDouble) - pSumExtraMatrix->PutDouble(pToken->GetDouble(), 0, 0); - else - pSumExtraMatrix->PutString(pToken->GetString(), 0, 0); + pSumExtraMatrix->PutDouble(static_cast(pToken.get())->GetDouble(), 0, 0); + else if (pToken->GetType() == svString) + pSumExtraMatrix->PutString(static_cast(pToken.get())->GetString(), 0, 0); } break; case svExternalDoubleRef: @@ -5525,11 +5762,11 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) { if (pToken->GetType() == svDouble) { - fVal = pToken->GetDouble(); + fVal = static_cast(pToken.get())->GetDouble(); bIsString = false; } - else - aString = pToken->GetString(); + else if (pToken->GetType() == svString) + aString = static_cast(pToken.get())->GetString(); } } break; @@ -6086,7 +6323,7 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf = bIsCountIfs ? pStack[sp - 1] : pStack[sp - nParamCount]; if (pMainRangeToken->GetType() == svDoubleRef && bHasDoubleRefCriteriaRanges) { - const ScComplexRefData* pRefData = pMainRangeToken->GetDoubleRef(); + const ScComplexRefData* pRefData = &static_cast(pMainRangeToken)->GetDoubleRef(); if (!pRefData->IsDeleted()) { DoubleRefToRange( *pRefData, aMainRange); @@ -6172,11 +6409,11 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf { if (pToken->GetType() == svDouble) { - fVal = pToken->GetDouble(); + fVal = static_cast(pToken.get())->GetDouble(); bIsString = false; } - else - aString = pToken->GetString(); + else if (pToken->GetType() == svString) + aString = static_cast(pToken.get())->GetString(); } } break; @@ -7782,7 +8019,7 @@ void ScInterpreter::CalculateLookup(bool bHLookup) else { ScAddress aResultPos( nCol1, nRow1, nTab1); - bFound = LookupQueryWithCache( aResultPos, aParam, refData, LookupSearchMode::Forward, SC_OPCODE_V_LOOKUP ); + bFound = LookupQueryWithCache( aResultPos, aParam, refData, LookupSearchMode::Forward, ocVLookup ); nRow = aResultPos.Row(); nCol = nSpIndex; } @@ -7875,7 +8112,7 @@ void ScInterpreter::ScXLookup() return; VectorSearchArguments vsa; - vsa.nSearchOpCode = SC_OPCODE_X_LOOKUP; + vsa.nSearchOpCode = ocXLookup; if ( nParamCount == 6 ) { @@ -7911,7 +8148,10 @@ void ScInterpreter::ScXLookup() if ( nParamCount >= 4 && GetStackType() != svEmptyCell ) { xNotFound = PopToken(); - nFirstMatchError = xNotFound->GetError(); + if (xNotFound->GetType() == svError) + nFirstMatchError = static_cast(xNotFound.get())->GetError(); + else + nFirstMatchError = FormulaError::NONE; nGlobalError = FormulaError::NONE; // propagate only for match or active result path } @@ -8085,12 +8325,16 @@ void ScInterpreter::ScXLookup() if (pToken->GetType() == svDouble) { vsa.isStringSearch = false; - vsa.fSearchVal = pToken->GetDouble(); + vsa.fSearchVal = static_cast(pToken.get())->GetDouble(); + } + else if (pToken->GetType() == svString) + { + vsa.isStringSearch = true; + vsa.sSearchStr = static_cast(pToken.get())->GetString(); } else { vsa.isStringSearch = true; - vsa.sSearchStr = pToken->GetString(); } } break; @@ -8415,6 +8659,11 @@ void ScInterpreter::ScSort() { bool bMissing = IsMissing(); ScMatrixRef pSortOrder = GetMatrix(); + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } if (!bMissing) { aSortOrderValues.clear(); @@ -8436,6 +8685,11 @@ void ScInterpreter::ScSort() { bool bMissing = IsMissing(); ScMatrixRef pSortIndex = GetMatrix(); + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } if (!bMissing) { aSortIndexValues.clear(); @@ -8837,6 +9091,12 @@ void ScInterpreter::ScTakeOrDrop(bool bTake) Pop(); } + if (!nArgCols.has_value() && !nArgRows.has_value()) + { + PushIllegalArgument(); + return; + } + // 1st argument: take unique search range ScMatrixRef pMatSource = nullptr; SCSIZE nsC = 0, nsR = 0; @@ -8893,6 +9153,11 @@ void ScInterpreter::ScTakeOrDrop(bool bTake) nMinCol = nArgCols.value(); } } + else if (!bTake) + { + PushIllegalArgument(); + return; + } } SCSIZE nMinRow = 0; @@ -8916,6 +9181,11 @@ void ScInterpreter::ScTakeOrDrop(bool bTake) nMinRow = nArgRows.value(); } } + else if (!bTake) + { + PushIllegalArgument(); + return; + } } for (SCSIZE col = nMinCol; col < nMaxCol; col++) @@ -9088,7 +9358,7 @@ void ScInterpreter::ScExpand() if (!MustHaveParamCount(nParamCount, 2, 4)) return; - // 4rd argument optional - pad_with + // 4th argument optional - pad_with std::optional bDouble; double fNumber(0.0); svl::SharedString aString; @@ -9326,7 +9596,7 @@ void ScInterpreter::ScTextBeforeOrAfter(bool bBefore) if (nParamCount == 6) aIfNotFound = GetString(); - // 5rd argument optional - match_end + // 5th argument optional - match_end bool bMatchEnd = false; if (nParamCount >= 5) { @@ -9338,7 +9608,7 @@ void ScInterpreter::ScTextBeforeOrAfter(bool bBefore) Pop(); } - // 4rd argument optional - match_mode + // 4th argument optional - match_mode bool bMatchMode = false; if (nParamCount >= 4) { @@ -9350,7 +9620,7 @@ void ScInterpreter::ScTextBeforeOrAfter(bool bBefore) Pop(); } - // 3nd argument optional - instance_num + // 3rd argument optional - instance_num sal_Int32 nInstanceNum(1); if (nParamCount >= 3) { @@ -9414,8 +9684,6 @@ void ScInterpreter::ScTextBeforeOrAfter(bool bBefore) } std::vector aDelimiterPositions; - if (bMatchEnd && !bBefore) - aDelimiterPositions.push_back(0); OUString sStr(sText.getString()); const sal_Int32 nLength (sStr.getLength()); @@ -9461,8 +9729,13 @@ void ScInterpreter::ScTextBeforeOrAfter(bool bBefore) nStart = nIndex + nDelLength; } - if (bMatchEnd && bBefore) - aDelimiterPositions.push_back(nLength); + if (bMatchEnd) + { + if (nInstanceNum < 0) + aDelimiterPositions.insert(aDelimiterPositions.begin(), 0); + else + aDelimiterPositions.push_back(nLength); + } sal_Int32 nSize(aDelimiterPositions.size()); if (nSize == 0 || std::abs(nInstanceNum) > nSize) @@ -9547,7 +9820,7 @@ void ScInterpreter::ScTextSplit() if (nParamCount == 6) aPadWith = GetString(); - // 5rd argument optional - match_mode + // 5th argument optional - match_mode bool bMatchMode = false; if (nParamCount >= 5) { @@ -9559,7 +9832,7 @@ void ScInterpreter::ScTextSplit() Pop(); } - // 4rd argument optional - ignore_empty + // 4th argument optional - ignore_empty bool bIgnoreEmpty = false; if (nParamCount >= 4) { @@ -9800,6 +10073,234 @@ void ScInterpreter::ScToRow() ScToColOrRow(/*bCol*/ false); } +void ScInterpreter::ScArrayToText() +{ + sal_uInt8 nParameterCount = GetByte(); + if (!MustHaveParamCount(nParameterCount, 1, 2)) + return; + + // 2nd argument optional - Format: 0 = concise (default), 1 = strict + sal_Int32 nFormat = 0; + if (nParameterCount == 2) + { + nFormat = GetInt32WithDefault(0); + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } + if (nFormat < 0 || nFormat > 1) + { + // Any format other than 0 or 1 is rejected with #VALUE!. + PushError(FormulaError::NoValue); + return; + } + } + const bool bStrict = (nFormat == 1); + + // The concise format joins all values with ", " in row order. The + // strict format writes an array constant: braces around the whole + // array, "," between columns, ";" between rows, and quoted text. + OUStringBuffer aResult; + + auto appendSeparator = [&aResult, bStrict](bool bNewRow) + { + if (bNewRow) + aResult.append(bStrict ? u";" : u", "); + else + aResult.append(bStrict ? u"," : u", "); + }; + auto appendText = [&aResult, bStrict](const OUString& rStr) + { + if (bStrict) + { + // Each double quote inside the text is doubled. + aResult.append('"'); + aResult.append(rStr.replaceAll(u"\"", u"\"\"")); + aResult.append('"'); + } + else + aResult.append(rStr); + }; + // Boolean values format through the LOGICAL key, so their text is + // TRUE or FALSE in the current locale. + const sal_uInt32 nLogicalKey = mrContext.NFGetStandardFormat( SvNumFormatType::LOGICAL, ScGlobal::eLnge); + auto appendLogical = [this, &aResult, nLogicalKey](double fValue) + { + OUString aString; + const Color* pColor = nullptr; + mrContext.NFGetOutputString(fValue, nLogicalKey, aString, &pColor); + aResult.append(aString); + }; + auto appendNumber = [this, &aResult](double fValue) + { + aResult.append(GetStringFromDouble(fValue).getString()); + }; + // An error value becomes its error text and the other elements are + // still written out. + auto appendError = [&aResult](FormulaError nError) + { + aResult.append(ScGlobal::GetErrorString(nError)); + }; + if (bStrict) + aResult.append('{'); + + switch (GetStackType()) + { + case svSingleRef: + case svDoubleRef: + { + // A referenced range reads directly from the document, cell by + // cell in row order, so that a number cell formatted as boolean + // still lists as TRUE or FALSE. + SCCOL nColumn1; + SCCOL nColumn2; + SCROW nRow1; + SCROW nRow2; + SCTAB nTable1; + SCTAB nTable2; + // A single-cell reference is a scalar argument, so an error in + // that one cell propagates as the result. In a multi-cell range + // an error cell instead lists as its error text. + const bool bScalarRef = (GetStackType() == svSingleRef); + if (bScalarRef) + { + ScAddress aAddress; + PopSingleRef(aAddress); + nColumn1 = nColumn2 = aAddress.Col(); + nRow1 = nRow2 = aAddress.Row(); + nTable1 = nTable2 = aAddress.Tab(); + } + else + { + PopDoubleRef(nColumn1, nRow1, nTable1, nColumn2, nRow2, nTable2); + } + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } + if (nTable1 != nTable2) + { + PushIllegalParameter(); + return; + } + + for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) + { + if (nRow > nRow1) + appendSeparator(/*bNewRow*/ true); + for (SCCOL nColumn = nColumn1; nColumn <= nColumn2; ++nColumn) + { + if (nColumn > nColumn1) + appendSeparator(/*bNewRow*/ false); + + ScAddress aAddress(nColumn, nRow, nTable1); + ScRefCellValue aCell(mrDoc, aAddress); + if (aCell.isEmpty()) + { + // An empty cell adds no text of its own; only the + // separators around it remain. + } + else if (aCell.hasError()) + { + const FormulaError nError = aCell.getFormula()->GetErrCode(); + if (bScalarRef) + { + PushError(nError); + return; + } + appendError(nError); + } + else if (aCell.hasNumeric()) + { + // A formula result carries its own format type, a + // value cell is formatted by its cell attribute. + SvNumFormatType eCellFormat; + if (aCell.getType() == CELLTYPE_FORMULA) + eCellFormat = aCell.getFormula()->GetFormatType(); + else + eCellFormat = mrContext.NFGetType(mrDoc.GetNumberFormat(mrContext, aAddress)); + if (eCellFormat == SvNumFormatType::LOGICAL) + appendLogical(aCell.getValue()); + else + appendNumber(aCell.getValue()); + } + else + { + svl::SharedString aSharedString; + GetCellString(aSharedString, aCell); + appendText(aSharedString.getString()); + } + } + } + break; + } + default: + { + // A scalar behaves like a 1 by 1 array, and a scalar error + // becomes an error element inside that array, so it is written + // out as text like any other element. + ScMatrixRef pMatrix = GetMatrix(); + if (!pMatrix) + { + PushIllegalParameter(); + return; + } + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } + + SCSIZE nColumns = 0; + SCSIZE nRows = 0; + pMatrix->GetDimensions(nColumns, nRows); + + for (SCSIZE nRow = 0; nRow < nRows; ++nRow) + { + if (nRow > 0) + appendSeparator(/*bNewRow*/ true); + for (SCSIZE nColumn = 0; nColumn < nColumns; ++nColumn) + { + if (nColumn > 0) + appendSeparator(/*bNewRow*/ false); + + const ScMatrixValue aValue = pMatrix->Get(nColumn, nRow); + switch (aValue.nType) + { + case ScMatValType::String: + appendText(aValue.aStr.getString()); + break; + case ScMatValType::Boolean: + appendLogical(aValue.fVal); + break; + case ScMatValType::Value: + { + const FormulaError nError = aValue.GetError(); + if (nError != FormulaError::NONE) + appendError(nError); + else + appendNumber(aValue.fVal); + break; + } + default: + // An empty element adds no text of its own; + // only the separators around it remain. + break; + } + } + } + break; + } + } + + if (bStrict) + aResult.append('}'); + + PushString(aResult.makeStringAndClear()); +} + void ScInterpreter::ScUnique() { sal_uInt8 nParamCount = GetByte(); @@ -9920,169 +10421,956 @@ void ScInterpreter::ScUnique() PushMatrix(pResMat); } -void ScInterpreter::replaceNamesToResult( const std::unordered_map& rResultIndexes, - ScTokenArray& rTokens, short nStartPos, short nEndPos ) +void ScInterpreter::ScLambda() { - formula::FormulaTokenArrayPlainIterator aIterResult(rTokens); - aIterResult.Jump(nStartPos + 1); - for (FormulaToken* t = aIterResult.GetNextStringNameRPN(); t; t = aIterResult.GetNextStringNameRPN()) - { - if (aIterResult.GetIndex() > nEndPos) - break; - auto iRes = rResultIndexes.find(t->GetString().getString()); - if (iRes != rResultIndexes.end()) - rTokens.ReplaceRPNToken(aIterResult.GetIndex() - 1, iRes->second->Clone()); - } -} - -ScTokenArray ScInterpreter::checkPushTokens(const ScTokenArray& rTokens, short nStartPos, short nEndPos) -{ - formula::FormulaTokenArrayPlainIterator aIterResult(rTokens); - aIterResult.Jump(nStartPos + 1); - ScTokenArray aTempTokens(mrDoc); - for (FormulaToken* t = aIterResult.NextRPN(); t; t = aIterResult.NextRPN()) - { - if (aIterResult.GetIndex() > nEndPos) - break; - - aTempTokens.AddToken(*t->Clone()); - } - return aTempTokens; -} - -void ScInterpreter::ScLet() -{ - const short* pJump = pCur->GetJump(); + const short* pJump = static_cast(pCur)->GetJump(); short nJumpCount = pJump[0]; - short nOrgJumpCount = nJumpCount; - if (nJumpCount < 3 || (nJumpCount % 2 != 1)) + // This corresponds to LAMBDA(), with no parameters + if (nJumpCount < 2) { PushError(FormulaError::ParameterExpected); - aCode.Jump(pJump[nOrgJumpCount], pJump[nOrgJumpCount]); + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); return; } - OUString aStrName; - std::unordered_map nResultIndexes; - formula::FormulaTokenArrayPlainIterator aIter(*pArr); - // clone tokens for replacing string name tokens - ScTokenArray aValueTokens = pArr->CloneValue(); + FormulaToken** pCode = pArr->GetCode(); + // One jump for each param, plus a jump for the body, and a jump after the LAMBDA + short nParams = nJumpCount - 2; + std::vector aParams(nParams); + short nFirstOptionalParam = nParams; - // name and function pairs parameter - while (nJumpCount > 1) + // Param names are found at pJump[1] + 1 to pJump[nJumpCount - 2] + 1 + for (short nParam = 0; nParam < nParams; ++nParam) { - if (nJumpCount == nOrgJumpCount) + if (const FormulaStringNameToken* pToken = GetStringNameToken(pCode[pJump[nParam + 1] + 1])) { - aStrName = GetString().getString(); - } - else if ((nOrgJumpCount - nJumpCount + 1) % 2 == 1) - { - aIter.Jump(pJump[static_cast(nOrgJumpCount - nJumpCount + 1)] - 1); - FormulaToken* t = aIter.NextRPN(); - aStrName = t->GetString().getString(); - } - else - { - PushError(FormulaError::ParameterExpected); - aCode.Jump(pJump[nOrgJumpCount], pJump[nOrgJumpCount]); - return; - } - nJumpCount--; - - // replace names with result tokens - replaceNamesToResult(nResultIndexes, aValueTokens, pJump[nOrgJumpCount - nJumpCount], pJump[nOrgJumpCount - nJumpCount + 1]); - - ScTokenArray aTempTokens = checkPushTokens(aValueTokens, pJump[nOrgJumpCount - nJumpCount], pJump[nOrgJumpCount - nJumpCount + 1]); - - // calculate the inner results unless we already have a push result token - if (aTempTokens.GetLen() == 0) - { - PushIllegalParameter(); - aCode.Jump(pJump[nOrgJumpCount], pJump[nOrgJumpCount]); - return; - } - else if (aTempTokens.GetLen() == 1 && aTempTokens.GetArray()[0]->GetOpCode() == ocPush) - { - if (!nResultIndexes.insert(std::make_pair(aStrName, aTempTokens.GetArray()[0]->Clone())).second) + if (pCode[pJump[nParam + 1] + 2]->GetType() == svSep) // must be followed by a separator { - PushIllegalParameter(); - aCode.Jump(pJump[nOrgJumpCount], pJump[nOrgJumpCount]); + aParams[nParam] = pToken->GetString().getString(); + // All optional parameters must appear at the end of the parameter list + if (nFirstOptionalParam < nParams) + { + // We've seen at least one optional param; all params after that point must + // be optional, as well. + if (!pToken->GetIsOptional()) + { + PushError(FormulaError::IllegalParameter); + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); + return; + } + } + else if (pToken->GetIsOptional()) + nFirstOptionalParam = nParam; + } + else + { + PushError(FormulaError::ParameterExpected); + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); return; } } else { - ScInterpreter aInt(mrDoc.GetFormulaCell(aPos), mrDoc, mrContext, aPos, aValueTokens); - aInt.aCode.Jump(pJump[nOrgJumpCount - nJumpCount], pJump[nOrgJumpCount - nJumpCount + 1], pJump[nOrgJumpCount - nJumpCount + 1]); - while (aInt.aCode.HasStacked()) - aInt.aCode.FrontPop(); - aInt.aCode.Lambda(true); + PushError(FormulaError::ParameterExpected); + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); + return; + } + } - sfx2::LinkManager aNewLinkMgr(mrDoc.GetDocumentShell()); - aInt.SetLinkManager(&aNewLinkMgr); + // Lambda-body is found between pJump[nJumpCount - 1] and pJump[nJumpCount] + FormulaCallableRef pFunc = new ScFormulaFunction(*this, aParams, nFirstOptionalParam, *pArr, + pJump[nJumpCount - 1], pJump[nJumpCount]); + PushCallable(pFunc); - formula::StackVar aIntType = aInt.Interpret(); + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); +} - if (aIntType == formula::svMatrixCell) +void ScInterpreter::ScIsOmitted() +{ + if ( ! MustHaveParamCount(GetByte(), 1) ) + return; + + auto pArg = PopToken(); + if (pArg->GetType() == svMissing) + PushInt(1); + else + PushInt(0); +} + +/// Calls a Callable with arguments on the stack +void ScInterpreter::ScCall( FormulaCallableRef rCallable, sal_uInt8 nArgCount ) +{ + OpCode eOpCode = rCallable->GetOpCode(); + if (eOpCode == ocLambda || eOpCode == ocMacro) + { + std::vector aArguments(nArgCount); + for( sal_uInt32 i = nArgCount; i > 0 ; i-- ) + aArguments[i - 1] = PopToken(); + + ScCall(rCallable, aArguments); + return; + } + else if (ocStartNoParameters <= eOpCode && eOpCode < ocStopNoParameters) + { + if (nArgCount != 0) + { + SetError( FormulaError::PairExpected ); + PushError( nGlobalError ); + return; + } + } + else if (ocStartOneParameter <= eOpCode && eOpCode < ocStopOneParameter) + { + if (nArgCount != 1) + { + SetError( FormulaError::PairExpected ); + PushError( nGlobalError ); + return; + } + } + else if ( eOpCode != ocExternal + && !(ocStartTwoParameters <= eOpCode && eOpCode < ocStopTwoParameters) ) + { + SAL_WARN("sc", "Unexpected OpCode in FormulaCallable: " << +eOpCode); + SetError( FormulaError::NotAFunction ); + PushError( nGlobalError ); + return; + } + // at this point we're dealing with a built-in function + // and the stack is set up with the relevant args + // we just need to dispatch the OpCode + auto pOldCur = pCur; + auto cOldPar = cPar; + FormulaTokenRef pTempToken = new FormulaByteToken(eOpCode, nArgCount); + pCur = pTempToken.get(); + cPar = nArgCount; + DispatchOpCode( eOpCode ); + pCur = pOldCur; + cPar = cOldPar; +} + +/// If pToken contains one or more relative references, they are converted to absolute references +/// Either way, a fresh token is returned, or nullptr if an error occurred +FormulaTokenRef ScInterpreter::RefToAbs(FormulaConstTokenRef pToken) +{ + switch (pToken->GetType()) + { + case svSingleRef: + { + auto pRefToken = static_cast(pToken.get()); + const ScSingleRefData& rRefData = pRefToken->GetSingleRef(); + if (rRefData.IsDeleted()) { - ScConstMatrixRef xMat(aInt.GetResultToken()->GetMatrix()); - if (!nResultIndexes.insert(std::make_pair(aStrName, new ScMatrixToken(xMat->Clone()))).second) + SetError(FormulaError::NoRef); + return nullptr; + } + + ScAddress aAbsAdr = rRefData.toAbs(mrDoc, aPos); + ScSingleRefData aAbsRefData; + aAbsRefData.InitAddress(aAbsAdr); + return new ScSingleRefToken(mrDoc.GetSheetLimits(), aAbsRefData); + } + case svExternalSingleRef: + { + auto pRefToken = static_cast(pToken.get()); + const ScSingleRefData& rRefData = pRefToken->GetSingleRef(); + if (rRefData.IsDeleted()) + { + SetError(FormulaError::NoRef); + return nullptr; + } + + ScAddress aAbsAdr = rRefData.toAbs(mrDoc, aPos); + ScSingleRefData aAbsRefData; + aAbsRefData.InitAddress(aAbsAdr); + return new ScExternalSingleRefToken(pRefToken->GetFileId(), pRefToken->GetTableName(), aAbsRefData); + } + case svDoubleRef: + { + auto pRefToken = static_cast(pToken.get()); + const ScComplexRefData& rRefData = pRefToken->GetDoubleRef(); + if (rRefData.IsDeleted()) + { + SetError(FormulaError::NoRef); + return nullptr; + } + + ScRange aAbsRange = rRefData.toAbs(mrDoc, aPos); + ScComplexRefData aAbsRefData; + aAbsRefData.InitRange(aAbsRange); + return new ScDoubleRefToken(mrDoc.GetSheetLimits(), aAbsRefData); + } + case svExternalDoubleRef: + { + auto pRefToken = static_cast(pToken.get()); + const ScComplexRefData& rRefData = pRefToken->GetDoubleRef(); + if (rRefData.IsDeleted()) + { + SetError(FormulaError::NoRef); + return nullptr; + } + + ScRange aAbsRange = rRefData.toAbs(mrDoc, aPos); + ScComplexRefData aAbsRefData; + aAbsRefData.InitRange(aAbsRange); + return new ScExternalDoubleRefToken(pRefToken->GetFileId(), pRefToken->GetTableName(), aAbsRefData); + } + case svRefList: + { + auto pRefListToken = static_cast(pToken->Clone()); + for (auto &rRefData : *pRefListToken->GetRefList()) + { + ScRange aAbsRange = rRefData.toAbs(mrDoc, aPos); + rRefData.SetRange(mrDoc.GetSheetLimits(), aAbsRange, aPos); + } + return pRefListToken; + } + default: + return pToken->Clone(); + } +} + +#if HAVE_FEATURE_SCRIPTING + +static uno::Any lcl_getSheetModule( const uno::Reference& xCellRange, const ScDocument* pDok ) +{ + uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW ); + OUString sCodeName; + xProps->getPropertyValue(u"CodeName"_ustr) >>= sCodeName; + // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible + // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there + // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at + // the document in the future could fix this, especially IF the switching of the vba mode takes care to + // create the special document module objects if they don't exist. + BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager(); + + uno::Reference< uno::XInterface > xIf; + if ( pBasMgr && !pBasMgr->GetName().isEmpty() ) + { + OUString sProj( u"Standard"_ustr ); + if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() ) + { + sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName(); + } + StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj ); + if ( pBasic ) + { + SbModule* pMod = pBasic->FindModule( sCodeName ); + if ( pMod ) + { + xIf = pMod->GetUnoModule(); + } + } + } + return uno::Any( xIf ); +} + +static bool lcl_setVBARange( const ScRange& aRange, const ScDocument& rDok, SbxVariable* pPar ) +{ + bool bOk = false; + try + { + uno::Reference< uno::XInterface > xVBARange; + uno::Reference xCellRange = ScCellRangeObj::CreateRangeFromDoc( rDok, aRange ); + uno::Sequence< uno::Any > aArgs{ lcl_getSheetModule( xCellRange, &rDok ), + uno::Any(xCellRange) }; + xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( rDok.GetDocumentShell(), "ooo.vba.excel.Range", aArgs ); + if ( xVBARange.is() ) + { + SbxObjectRef aObj = GetSbUnoObject( u"A-Range"_ustr, uno::Any( xVBARange ) ); + SetSbUnoObjectDfltPropName( aObj.get() ); + bOk = pPar->PutObject( aObj.get() ); + } + } + catch( uno::Exception& ) + { + } + return bOk; +} + +static bool lcl_isNumericResult( double& fVal, const SbxVariable* pVar ) +{ + switch (pVar->GetType()) + { + case SbxINTEGER: + case SbxLONG: + case SbxSINGLE: + case SbxDOUBLE: + case SbxCURRENCY: + case SbxDATE: + case SbxUSHORT: + case SbxULONG: + case SbxINT: + case SbxUINT: + case SbxSALINT64: + case SbxSALUINT64: + case SbxDECIMAL: + fVal = pVar->GetDouble(); + return true; + case SbxBOOL: + fVal = (pVar->GetBool() ? 1.0 : 0.0); + return true; + default: + ; // nothing + } + return false; +} + +bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos ) +{ + bool bOk = true; + ScRefCellValue aCell(mrDoc, rPos); + if (!aCell.isEmpty()) + { + FormulaError nErr; + double nVal; + switch (aCell.getType()) + { + case CELLTYPE_VALUE : + nVal = GetValueCellValue(rPos, aCell.getDouble()); + pVar->PutDouble( nVal ); + break; + case CELLTYPE_STRING : + case CELLTYPE_EDIT : + pVar->PutString(aCell.getString(mrDoc)); + break; + case CELLTYPE_FORMULA : + nErr = aCell.getFormula()->GetErrCode(); + if( nErr == FormulaError::NONE ) { - PushIllegalParameter(); - aCode.Jump(pJump[nOrgJumpCount], pJump[nOrgJumpCount]); + if (aCell.getFormula()->IsValue()) + { + nVal = aCell.getFormula()->GetValue(); + pVar->PutDouble( nVal ); + } + else if (aCell.getFormula()->IsCallable()) // TODO + { + SetError( FormulaError::IllegalParameter ); + bOk = false; + } + else + pVar->PutString(aCell.getFormula()->GetString().getString()); + } + else + { + SetError( nErr ); + bOk = false; + } + break; + default : + pVar->PutEmpty(); + } + } + else + pVar->PutEmpty(); + + return bOk; +} + +bool ScInterpreter::BuildMacroArgs( const std::vector& rArgsIn, SbxArrayRef refArgsOut, bool bUseVBAObjects ) +{ + sal_uInt32 nArgCount = rArgsIn.size(); + for( sal_uInt32 i = 0; i < nArgCount; i++ ) + { + formula::FormulaConstTokenRef pToken = rArgsIn[i]; + SbxVariable* pArg = refArgsOut->Get(i + 1); // refArgsOut is one-based + if (!GetMacroArg(pToken, pArg, bUseVBAObjects)) + return false; + } + return true; +} + +bool ScInterpreter::GetMacroArg( formula::FormulaConstTokenRef pArgIn, SbxVariable* pArgOut, bool bUseVBAObjects ) +{ + switch( pArgIn->GetType() ) + { + case svDouble: + { + auto pToken = static_cast(pArgIn.get()); + pArgOut->PutDouble( pToken->GetDouble() ); + } + break; + case svString: + { + auto pToken = static_cast(pArgIn.get()); + pArgOut->PutString( pToken->GetString().getString() ); + } + break; + case svMissing: + // tdf#102381 - add additional information about a missing parameter + SbxSetMissingParameter(*pArgOut); + break; + case svCallable: // TODO + { + //auto pToken = static_cast(pArgIn.get()); + SetError( FormulaError::IllegalParameter ); + return false; + } + case svExternalSingleRef: + { + auto pToken = static_cast(pArgIn.get()); + sal_uInt16 nFileId = pToken->GetFileId(); + OUString aTabName = pToken->GetTableName().getString(); + ScSingleRefData aRef = pToken->GetSingleRef(); + + ScExternalRefManager* pRefMgr = mrDoc.GetExternalRefManager(); + const OUString* pFile = pRefMgr->getExternalFileName(nFileId); + if (!pFile) + { + SetError(FormulaError::NoName); + return false; + } + + if (aRef.IsTabRel()) + { + OSL_FAIL("ScInterpreter:GetMacroArg: external single reference must have an absolute table reference!"); + SetError(FormulaError::NoRef); + return false; + } + + ScAddress aAddr = aRef.toAbs(mrDoc, aPos); + ScExternalRefCache::CellFormat aFmt; + ScExternalRefCache::TokenRef pRefToken = pRefMgr->getSingleRefToken( + nFileId, aTabName, aAddr, &aPos, nullptr, &aFmt); + + if (!pRefToken) + { + SetError(FormulaError::NoRef); + return false; + } + else + return GetMacroArg(pRefToken, pArgOut, bUseVBAObjects); + } + break; + case svSingleRef: + { + auto pToken = static_cast(pArgIn.get()); + ScAddress aAdr; + const ScSingleRefData& pRefData = pToken->GetSingleRef(); + if (pRefData.IsDeleted()) + { + SetError( FormulaError::NoRef); + return false; + } + + SCCOL nCol; + SCROW nRow; + SCTAB nTab; + SingleRefToVars( pRefData, nCol, nRow, nTab); + aAdr.Set( nCol, nRow, nTab ); + if (!mrDoc.m_TableOpList.empty()) + ReplaceCell( aAdr ); + + if ( bUseVBAObjects ) + { + ScRange aRange( aAdr ); + if ( ! lcl_setVBARange( aRange, mrDoc, pArgOut ) ) + return false; + } + else + { + if ( ! SetSbxVariable( pArgOut, aAdr ) ) + return false; + } + } + break; + case svDoubleRef: + { + auto pToken = static_cast(pArgIn.get()); + SCCOL nCol1; + SCROW nRow1; + SCTAB nTab1; + SCCOL nCol2; + SCROW nRow2; + SCTAB nTab2; + DoubleRefToVars( pToken, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); + if( nTab1 != nTab2 ) + { + SetError( FormulaError::IllegalParameter ); + return false; + } + else + { + if ( bUseVBAObjects ) + { + ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); + if ( ! lcl_setVBARange( aRange, mrDoc, pArgOut ) ) + return false; + } + else + { + SbxDimArrayRef refArray = new SbxDimArray; + refArray->AddDim(1, nRow2 - nRow1 + 1); + refArray->AddDim(1, nCol2 - nCol1 + 1); + ScAddress aAdr( nCol1, nRow1, nTab1 ); + for( SCROW nRow = nRow1; nRow <= nRow2; nRow++ ) + { + aAdr.SetRow( nRow ); + sal_Int32 nIdx[ 2 ]; + nIdx[ 0 ] = nRow-nRow1+1; + for( SCCOL nCol = nCol1; nCol <= nCol2; nCol++ ) + { + aAdr.SetCol( nCol ); + nIdx[ 1 ] = nCol-nCol1+1; + SbxVariable* p = refArray->Get(nIdx); + if ( ! SetSbxVariable( p, aAdr ) ) + return false; + } + } + pArgOut->PutObject( refArray.get() ); + } + } + } + break; + case svMatrix: + { + auto pToken = static_cast(pArgIn.get()); + // ScMatrix itself maintains an im/mutable flag that should + // be obeyed where necessary... so we can return ScMatrixRef + // here instead of ScConstMatrixRef. + ScMatrixRef pMat = const_cast(pToken)->GetMatrix(); + if ( !pMat ) + { + SetError( FormulaError::UnknownVariable); + return false; + } + pMat->SetErrorInterpreter( this); + if (nGlobalError != FormulaError::NONE) + { + SetError( FormulaError::IllegalParameter ); + return false; + } + SCSIZE nC, nR; + pMat->GetDimensions(nC, nR); + SbxDimArrayRef refArray = new SbxDimArray; + refArray->AddDim(1, static_cast(nR)); + refArray->AddDim(1, static_cast(nC)); + for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ ) + { + sal_Int32 nIdx[ 2 ]; + nIdx[ 0 ] = static_cast(nMatRow+1); + for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ ) + { + nIdx[ 1 ] = static_cast(nMatCol+1); + SbxVariable* p = refArray->Get(nIdx); + // TODO: account for callables + if (pMat->IsStringOrEmpty(nMatCol, nMatRow)) + p->PutString( pMat->GetString(nMatCol, nMatRow).getString() ); + else + p->PutDouble( pMat->GetDouble(nMatCol, nMatRow)); + } + } + pArgOut->PutObject( refArray.get() ); + } + break; + case svExternalDoubleRef: + { + auto pToken = static_cast(pArgIn.get()); + sal_uInt16 nFileId = pToken->GetFileId(); + OUString aTabName = pToken->GetTableName().getString(); + ScComplexRefData aData = pToken->GetDoubleRef(); + ScExternalRefCache::TokenArrayRef pArray; + + GetExternalDoubleRef(nFileId, aTabName, aData, pArray); + if (nGlobalError != FormulaError::NONE || !pArray) + return false; + + // For now, we only support single range data for external + // references, which means the array should only contain a + // single matrix token. + FormulaToken* pFirst = pArray->FirstToken(); + if (!pFirst || pFirst->GetType() != svMatrix) + { + SetError( FormulaError::IllegalParameter); + return false; + } + ScMatrixRef pMat = static_cast(pFirst)->GetMatrix(); + if (!pMat) + { + SetError( FormulaError::UnknownVariable); + return false; + } + SCSIZE nC, nR; + pMat->GetDimensions(nC, nR); + SbxDimArrayRef refArray = new SbxDimArray; + refArray->AddDim(1, static_cast(nR)); + refArray->AddDim(1, static_cast(nC)); + for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ ) + { + sal_Int32 nIdx[ 2 ]; + nIdx[ 0 ] = static_cast(nMatRow+1); + for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ ) + { + nIdx[ 1 ] = static_cast(nMatCol+1); + SbxVariable* pVar = refArray->Get(nIdx); + // TODO: account for callables + if (pMat->IsStringOrEmpty(nMatCol, nMatRow)) + pVar->PutString( pMat->GetString(nMatCol, nMatRow).getString() ); + else + pVar->PutDouble( pMat->GetDouble(nMatCol, nMatRow)); + } + } + pArgOut->PutObject( refArray.get() ); + } + break; + default: + SetError( FormulaError::IllegalParameter ); + return false; + } + return true; +} +#endif + +/// Replaces the tokens at the specified positions with references to pToken +static void lcl_ReplaceParam( ScTokenArray& rTokens, const std::forward_list& rPositions, FormulaTokenRef pToken ) +{ + std::for_each( rPositions.begin(), rPositions.end(), [&rTokens, pToken](short nPos) + { + rTokens.ReplaceRPNToken(nPos, pToken.get()); + } ); +} + +/// Calls a Callable with passed args +void ScInterpreter::ScCall( FormulaCallableRef pCallable, const std::vector& aArguments ) +{ + OpCode eOpCode = pCallable->GetOpCode(); + if (eOpCode == ocLambda) + { + // How deeply lambda bodies may nest before a call is refused. Each level + // runs in a fresh nested interpreter, so a lambda that ends up calling + // itself needs a bound. It matches the recursion limit used for ordinary + // formula cell evaluation. + const sal_Int32 MAX_CALLABLE_INTERPRET_LEVEL = 400; + + // Only ScFormulaFunction reports ocLambda, so cast directly instead of + // paying for a type check on every call. + assert(dynamic_cast(pCallable.get())); + auto pLambda = static_cast(pCallable.get()); + + // A lambda body runs in a fresh nested interpreter and does not pass + // through the per-cell recursion counter, so bound the nesting depth + // here. A formula that exceeds the limit yields an error. + ScDocument& rLambdaDoc = pLambda->GetDocument(); + if (rLambdaDoc.GetCallableInterpretLevel() >= MAX_CALLABLE_INTERPRET_LEVEL) + { + SetError(FormulaError::StackOverflow); + PushError(nGlobalError); + return; + } + + sal_Int32 nParamCount = pLambda->GetNumParams(); + sal_Int32 nRequiredParamCount = pLambda->GetNumRequiredParams(); + sal_Int32 nArgCount = aArguments.size(); + if (nArgCount > nParamCount || nArgCount < nRequiredParamCount) + { + // A call with the wrong number of arguments is a value error, + // matching the OOXML interpretation. + SetError(FormulaError::NoValue); + PushError(nGlobalError); + return; + } + + // clone tokens of lambda-body for replacing string name tokens with arguments + ScTokenArray aNewTokens = pLambda->GetLambdaBody().CloneValue(); + + for (sal_Int32 nParam = 0; nParam < nParamCount; ++nParam) + { + const std::forward_list& rPositions = pLambda->GetReplacementPositions(nParam); + + FormulaTokenRef pNewArg = nullptr; + if (nParam < nArgCount) + { + FormulaConstTokenRef pArgument = aArguments[nParam]; + pNewArg = RefToAbs(pArgument); + if (!pNewArg) + { + PushError(nGlobalError); return; } } else { - const FormulaConstTokenRef& xTok(aInt.GetResultToken()); - if (!nResultIndexes.insert(std::make_pair(aStrName, xTok->Clone())).second) - { - PushIllegalParameter(); - aCode.Jump(pJump[nOrgJumpCount], pJump[nOrgJumpCount]); - return; - } + // Ensure parameters that are optional and not provided are set to svMissing, + // so that ISOMITTED detects them properly. + pNewArg = new FormulaMissingToken(); } + + lcl_ReplaceParam(aNewTokens, rPositions, pNewArg); } - nJumpCount--; + + // calculate the final result, in the stored context + ScInterpreter aInt(pLambda->GetFormulaCell(), rLambdaDoc, pLambda->GetContext(), + pLambda->GetAddress(), aNewTokens); + aInt.aCode.Lambda(true); + + sfx2::LinkManager aNewLinkMgr(rLambdaDoc.GetDocumentShell()); + aInt.SetLinkManager(&aNewLinkMgr); + + rLambdaDoc.IncCallableInterpretLevel(); + formula::StackVar aResultType = aInt.Interpret(); + rLambdaDoc.DecCallableInterpretLevel(); + formula::FormulaConstTokenRef xLambdaResult( aInt.GetResultToken() ); + + if (aResultType == formula::svMatrixCell) + { + ScConstMatrixRef xMat(static_cast(xLambdaResult.get())->GetMatrix()); + PushTokenRef(new ScMatrixToken(xMat->Clone())); + } + else if (xLambdaResult) + PushTokenRef(xLambdaResult); + else if (nGlobalError != FormulaError::NONE) + PushError(nGlobalError); + else + PushNoValue(); } - - // last parameter: calculation - // replace names with result tokens - replaceNamesToResult(nResultIndexes, aValueTokens, pJump[nOrgJumpCount - nJumpCount], pJump[nOrgJumpCount - nJumpCount + 1]); - - // calculate the final result - ScInterpreter aInt(mrDoc.GetFormulaCell(aPos), mrDoc, mrContext, aPos, aValueTokens); - aInt.aCode.Jump(pJump[nOrgJumpCount - nJumpCount], pJump[nOrgJumpCount - nJumpCount + 1], pJump[nOrgJumpCount - nJumpCount + 1]); - while (aInt.aCode.HasStacked()) - aInt.aCode.FrontPop(); - aInt.aCode.Lambda(true); - - sfx2::LinkManager aNewLinkMgr(mrDoc.GetDocumentShell()); - aInt.SetLinkManager(&aNewLinkMgr); - formula::StackVar aIntType = aInt.Interpret(); - - if (aIntType == formula::svMatrixCell) + else if (eOpCode == ocMacro) { - ScConstMatrixRef xMat(aInt.GetResultToken()->GetMatrix()); - PushTokenRef(new ScMatrixToken(xMat->Clone())); +#if !HAVE_FEATURE_SCRIPTING + PushNoValue(); // without DocShell no CallBasic +#else + // Only ScMacroFunction reports ocMacro, so cast directly instead of + // paying for a type check on every call. + assert(dynamic_cast(pCallable.get())); + auto pMacro = static_cast(pCallable.get()); + + if (!pMacro->IsValid()) + { + FormulaError nError = pMacro->GetError(); + if (nError != FormulaError::NONE) + { + SetError(nError); + PushError(nGlobalError); + } + else + PushNoValue(); + return; + } + + bool bVolatileMacro = false; + bool bUseVBAObjects = pMacro->GetModule()->IsVBASupport(); + + SbxArrayRef refArgs = new SbxArray; + if( BuildMacroArgs(aArguments, refArgs, bUseVBAObjects) ) + { + ScDocShell* pDocSh = pMacro->GetDocumentShell(); + mrDoc.LockTable( aPos.Tab() ); + SbxVariableRef refRes = new SbxVariable; + mrDoc.IncMacroInterpretLevel(); + ErrCode eRet = pDocSh->CallBasic( pMacro->GetMacroStr(), pMacro->GetBasicStr(), refArgs.get(), refRes.get() ); + mrDoc.DecMacroInterpretLevel(); + mrDoc.UnlockTable( aPos.Tab() ); + + ScMacroManager* pMacroMgr = mrDoc.GetMacroManager(); + if (pMacroMgr) + { + bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMacro->GetMethod()->GetName() ); + pMacroMgr->AddDependentCell(pMacro->GetModule()->GetName(), pMyFormulaCell); + } + + double fVal; + SbxDataType eResType = refRes->GetType(); + if( SbxBase::GetError() ) + { + SetError( FormulaError::NoValue); + } + if ( eRet != ERRCODE_NONE ) + { + PushNoValue(); + } + else if (lcl_isNumericResult( fVal, refRes.get())) + { + switch (eResType) + { + case SbxDATE: + nFuncFmtType = SvNumFormatType::DATE; + break; + case SbxBOOL: + nFuncFmtType = SvNumFormatType::LOGICAL; + break; + // Do not add SbxCURRENCY, we don't know which currency. + default: + ; // nothing + } + PushDouble( fVal ); + } + else if ( eResType & SbxARRAY ) + { + SbxBase* pElemObj = refRes->GetObject(); + SbxDimArray* pDimArray = dynamic_cast(pElemObj); + sal_Int32 nDim = pDimArray ? pDimArray->GetDims() : 0; + if ( 1 <= nDim && nDim <= 2 ) + { + sal_Int32 nCs, nCe, nRs; + SCSIZE nC, nR; + SCCOL nColIdx; + SCROW nRowIdx; + if ( nDim == 1 ) + { // array( cols ) one line, several columns + pDimArray->GetDim(1, nCs, nCe); + nC = static_cast(nCe - nCs + 1); + nRs = 0; + nR = 1; + nColIdx = 0; + nRowIdx = 1; + } + else + { // array( rows, cols ) + sal_Int32 nRe; + pDimArray->GetDim(1, nRs, nRe); + nR = static_cast(nRe - nRs + 1); + pDimArray->GetDim(2, nCs, nCe); + nC = static_cast(nCe - nCs + 1); + nColIdx = 1; + nRowIdx = 0; + } + ScMatrixRef pMat = GetNewMat( nC, nR, /*bEmpty*/true); + if ( pMat ) + { + SbxVariable* pV; + for ( SCSIZE j=0; j < nR; j++ ) + { + sal_Int32 nIdx[ 2 ]; + // in one-dimensional array( cols ) nIdx[1] + // from SbxDimArray::Get is ignored + nIdx[ nRowIdx ] = nRs + static_cast(j); + for ( SCSIZE i=0; i < nC; i++ ) + { + nIdx[ nColIdx ] = nCs + static_cast(i); + pV = pDimArray->Get(nIdx); + // TODO: account for callables + if ( lcl_isNumericResult( fVal, pV) ) + pMat->PutDouble( fVal, i, j ); + else + pMat->PutString(mrStrPool.intern(pV->GetOUString()), i, j); + } + } + PushMatrix( pMat ); + } + else + PushIllegalArgument(); + } + else + PushNoValue(); + } + else + PushString( refRes->GetOUString() ); + } + else + PushError(nGlobalError); // the arguments could not be built + + // prevent cycles from leaking memory + refArgs->Clear(); + + if (bVolatileMacro && meVolatileType == NOT_VOLATILE) + meVolatileType = VOLATILE_MACRO; +#endif } else { - const formula::FormulaConstTokenRef& xLambdaResult(aInt.GetResultToken()); - if (xLambdaResult) + std::for_each( aArguments.begin(), aArguments.end(), [this](formula::FormulaConstTokenRef rToken) { - nGlobalError = xLambdaResult->GetError(); - if (nGlobalError == FormulaError::NONE) - PushTokenRef(xLambdaResult); - else - PushError(nGlobalError); + PushTokenRef(rToken); + } ); + ScCall( pCallable, aArguments.size() ); + } +} + +void ScInterpreter::ScCall() +{ + sal_uInt8 nArgCount = GetByte() - 1; + { + // the first argument to ocCall is the callable itself + // we want to move that to the top of the stack, which requires shifting the arguments above it + const FormulaToken** pSrc = &pStack[sp - nArgCount - 1]; + const FormulaToken* pTempToken = *pSrc; + const FormulaToken** pDst = pSrc++; + for (; pSrc < &pStack[sp]; pDst = pSrc++) *pDst = *pSrc; + *pDst = pTempToken; + } + FormulaCallableRef pCallable = GetCallable(); + + if (!pCallable || nGlobalError != FormulaError::NONE) + { + PushError( nGlobalError ); + return; + } + + ScCall(pCallable, nArgCount); +} + + +void ScInterpreter::ScLet() +{ + const short* pJump = static_cast(pCur)->GetJump(); + short nJumpCount = pJump[0]; + short nJump; + + // LET without bindings is not an error; the result is already on the stack, + // so we have nothing to do + if (nJumpCount == 1) + { + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); + return; + } + else if (nJumpCount < 3 || (nJumpCount % 2) != 1) + { + PushError(FormulaError::ParameterExpected); + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); + return; + } + else if (GetRawStackType() != svStringName) + { + PushError(FormulaError::ParameterExpected); + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); + return; + } + + std::vector aParams; + std::vector aArgs; + + // calculate the first subformula with no bindings + { + FormulaCallableRef pFunc = new ScFormulaFunction(*this, aParams, 0, *pArr, + pJump[1], pJump[2]); + ScCall(pFunc, aArgs); + + aArgs.push_back(PopToken()); + // the param name is on the stack + aParams.push_back(GetString().getString()); + } + + FormulaToken** pCode = pArr->GetCode(); + for (nJump = 3; nJump < nJumpCount; nJump += 2) + { + // calculate each subformula with the bindings created before it + FormulaCallableRef pFunc = new ScFormulaFunction(*this, aParams, aParams.size(), + *pArr, pJump[nJump], pJump[nJump + 1]); + ScCall(pFunc, aArgs); + + aArgs.push_back(PopToken()); + // the param name is one jump before the current one + const FormulaStringNameToken* pToken = GetStringNameToken(pCode[pJump[nJump - 1] + 1]); + if (pToken) + aParams.push_back(pToken->GetString().getString()); + else + { + PushError(FormulaError::ParameterExpected); + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); + return; } } - nJumpCount--; - aCode.Jump(pJump[nOrgJumpCount], pJump[nOrgJumpCount]); + // the last subformula isn't named + nJump--; + + // calculate the last subformula with all of the bindings in place + FormulaCallableRef pFunc = new ScFormulaFunction(*this, aParams, aParams.size(), + *pArr, pJump[nJump], pJump[nJump + 1]); + ScCall(pFunc, aArgs); + + aCode.Jump(pJump[nJumpCount], pJump[nJumpCount]); } void ScInterpreter::ScSubTotal() @@ -10767,9 +12055,12 @@ void ScInterpreter::ScIndirect() svl::SharedString sSharedRefStr = GetString(); const OUString & sRefStr = sSharedRefStr.getString(); - if (sRefStr.isEmpty()) + if (sRefStr.isEmpty() || sRefStr.indexOf(u'\0') >= 0) { // Bail out early for empty cells, rely on "we do have a string" below. + // Also reject strings with embedded NULs: the formula compiler's state + // machine cannot advance past a NUL and would otherwise leave input + // unconsumed without setting an error. PushError( FormulaError::NoRef); return; } @@ -11280,7 +12571,7 @@ void ScInterpreter::ScIndex() return; } if (GetStackType() == svRefList) - nAreaCount = (sp ? pStack[sp-1]->GetRefList()->size() : 0); + nAreaCount = (sp ? static_cast(pStack[sp-1])->GetRefList()->size() : 0); else nAreaCount = 1; // one reference or array or whatever if (nGlobalError != FormulaError::NONE || nAreaCount == 0 || o3tl::make_unsigned(nArea) > nAreaCount) @@ -11429,7 +12720,7 @@ void ScInterpreter::ScIndex() bool bRowArray = false; if (GetStackType() == svRefList) { - FormulaConstTokenRef xRef = PopToken(); + auto xRef = PopToken(); if (nGlobalError != FormulaError::NONE || !xRef) { PushError( FormulaError::NoRef); @@ -11516,20 +12807,20 @@ void ScInterpreter::ScAreas() case svSingleRef: { FormulaConstTokenRef xT = PopToken(); - ValidateRef( *xT->GetSingleRef()); + ValidateRef( static_cast(xT.get())->GetSingleRef()); ++nCount; } break; case svDoubleRef: { FormulaConstTokenRef xT = PopToken(); - ValidateRef( *xT->GetDoubleRef()); + ValidateRef( static_cast(xT.get())->GetDoubleRef()); ++nCount; } break; case svRefList: { - FormulaConstTokenRef xT = PopToken(); + auto xT = PopToken(); ValidateRef( *(xT->GetRefList())); nCount += xT->GetRefList()->size(); } @@ -12473,7 +13764,7 @@ FormulaError ScInterpreter::GetErrorType() { case svRefList : { - FormulaConstTokenRef x = PopToken(); + auto x = PopToken(); if (nGlobalError != FormulaError::NONE) nErr = nGlobalError; else @@ -12869,7 +14160,7 @@ bool ScInterpreter::SearchRangeForValue( VectorSearchArguments& vsa, ScQueryPara { rParam.bByRow = false; bool bBinarySearch = vsa.eSearchMode == LookupSearchMode::BinaryAscending || vsa.eSearchMode == LookupSearchMode::BinaryDescending; - if (bBinarySearch && (vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP || vsa.nSearchOpCode == SC_OPCODE_X_MATCH)) + if (bBinarySearch && (vsa.nSearchOpCode == ocXLookup || vsa.nSearchOpCode == ocXMatch)) { ScQueryCellIteratorSortedCache aCellIter(mrDoc, mrContext, rParam.nTab, rParam, false, false); // Advance Entry.nField in Iterator if column changed @@ -12954,7 +14245,7 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa ) case wildcard : case regex : // this mode can only used with XLOOKUP/XMATCH - if ( vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP || vsa.nSearchOpCode == SC_OPCODE_X_MATCH ) + if ( vsa.nSearchOpCode == ocXLookup || vsa.nSearchOpCode == ocXMatch ) { // Wildcard/Regex search mode with binary search is not allowed if (vsa.eSearchMode == LookupSearchMode::BinaryAscending || vsa.eSearchMode == LookupSearchMode::BinaryDescending) @@ -12989,15 +14280,15 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa ) ScQueryEntry::Item& rItem = rEntry.GetQueryItem(); // allow to match empty cells as result if we are looking for the next smaller // or larger values in case of the new lookup functions - if (rEntry.eOp != SC_EQUAL && (vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP || - vsa.nSearchOpCode == SC_OPCODE_X_MATCH)) + if (rEntry.eOp != SC_EQUAL && (vsa.nSearchOpCode == ocXLookup || + vsa.nSearchOpCode == ocXMatch)) rItem.mbMatchEmpty = true; if ( vsa.isStringSearch ) { rItem.meType = ScQueryEntry::ByString; rItem.maString = vsa.sSearchStr; - if ( vsa.nSearchOpCode == SC_OPCODE_MATCH ) + if ( vsa.nSearchOpCode == ocMatch ) { if ( mrDoc.IsInVBAMode() ) rParam.eSearchType = utl::SearchParam::SearchType::Wildcard; @@ -13005,8 +14296,8 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa ) rParam.eSearchType = DetectSearchType(rEntry.GetQueryItem().maString.getString(), mrDoc); } } - else if ( vsa.isEmptySearch && (vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP || - vsa.nSearchOpCode == SC_OPCODE_X_MATCH) ) + else if ( vsa.isEmptySearch && (vsa.nSearchOpCode == ocXLookup || + vsa.nSearchOpCode == ocXMatch) ) { rEntry.SetQueryByEmpty(); rItem.mbMatchEmpty = true; @@ -13034,12 +14325,12 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa ) // MATCH expects index starting with 1, XLOOKUP expects index starting with 0 if ( vsa.nHitIndex > 0 ) { - vsa.nIndex = ( vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP ? --vsa.nHitIndex : vsa.nHitIndex ); + vsa.nIndex = ( vsa.nSearchOpCode == ocXLookup ? --vsa.nHitIndex : vsa.nHitIndex ); return true; } else if ( vsa.nHitIndex == 0 && vsa.nBestFit != SCSIZE_MAX ) { - if ( vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP ) + if ( vsa.nSearchOpCode == ocXLookup ) { vsa.nIndex = vsa.nBestFit; if ( !vsa.pMatSrc ) @@ -13069,7 +14360,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter SCCOL nCol; SCROW nRow; bool bBinarySearch = nSearchMode == LookupSearchMode::BinaryAscending || nSearchMode == LookupSearchMode::BinaryDescending; - if ((bBinarySearch && (nOpCode == SC_OPCODE_X_LOOKUP || nOpCode == SC_OPCODE_X_MATCH)) || + if ((bBinarySearch && (nOpCode == ocXLookup || nOpCode == ocXMatch)) || ScQueryCellIteratorSortedCache::CanBeUsed(rDoc, rParam, rParam.nTab, cell, refData, rContext)) { ScQueryCellIteratorSortedCache aCellIter(rDoc, rContext, rParam.nTab, rParam, false, false); diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index ddef32baa82e..e9152442c3cc 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -850,7 +850,7 @@ void ScInterpreter::ScGetDateDif() // and months from the difference of dates. Birthday-like 23 years // and 10 months and 19 days. - // Algorithm's roll-over behavior extracted from Excel by try and + // Algorithm's roll-over behavior extracted from Excel by trial and // error... // If day1 <= day2 then simply day2 - day1. // If day1 > day2 then set month1 to month2-1 and year1 to @@ -1100,7 +1100,7 @@ void ScInterpreter::ScRoundSignificant() /** tdf69552 ODFF1.2 function CEILING and Excel function CEILING.MATH In essence, the difference between the two is that ODFF-CEILING needs to have arguments value and significance of the same sign and with - CEILING.MATH the sign of argument significance is irrevelevant. + CEILING.MATH the sign of argument significance is irrelevant. This is why ODFF-CEILING is exported to Excel as CEILING.MATH and CEILING.MATH is imported in Calc as CEILING.MATH */ @@ -1188,7 +1188,7 @@ void ScInterpreter::ScCeil_Precise() /** tdf69552 ODFF1.2 function FLOOR and Excel function FLOOR.MATH In essence, the difference between the two is that ODFF-FLOOR needs to have arguments value and significance of the same sign and with - FLOOR.MATH the sign of argument significance is irrevelevant. + FLOOR.MATH the sign of argument significance is irrelevant. This is why ODFF-FLOOR is exported to Excel as FLOOR.MATH and FLOOR.MATH is imported in Calc as FLOOR.MATH */ @@ -2059,7 +2059,7 @@ bool ScInterpreter::RateIteration( double fNper, double fPayment, double fPv, // See also #i15090# // Newton-Raphson method: x(i+1) = x(i) - f(x(i)) / f'(x(i)) // This solution handles integer and non-integer values of Nper different. - // If ODFF will constraint Nper to integer, the distinction of cases can be + // If ODFF will constrain Nper to integer, the distinction of cases can be // removed; only the integer-part is needed then. bool bValid = true, bFound = false; double fX, fXnew, fTerm, fTermDerivation; @@ -2408,8 +2408,8 @@ void ScInterpreter::ScMod() void ScInterpreter::ScIntersect() { - formula::FormulaConstTokenRef p2nd = PopToken(); - formula::FormulaConstTokenRef p1st = PopToken(); + formula::FormulaConstTokenRef p2nd = PopReferenceOperand(); + formula::FormulaConstTokenRef p1st = PopReferenceOperand(); if (nGlobalError != FormulaError::NONE || !p2nd || !p1st) { @@ -2437,20 +2437,20 @@ void ScInterpreter::ScIntersect() StackVar sv[2] = { sv1, sv2 }; // There may only be one reference; the other is necessarily a list // Ensure converted list proper destruction - std::unique_ptr p; + std::unique_ptr p; for (size_t i=0; i<2; ++i) { if (sv[i] == svSingleRef) { ScComplexRefData aRef; - aRef.Ref1 = aRef.Ref2 = *xt[i]->GetSingleRef(); + aRef.Ref1 = aRef.Ref2 = static_cast(xt[i])->GetSingleRef(); p.reset(new ScRefListToken); p->GetRefList()->push_back( aRef); xt[i] = p.get(); } else if (sv[i] == svDoubleRef) { - ScComplexRefData aRef = *xt[i]->GetDoubleRef(); + ScComplexRefData aRef = static_cast(xt[i])->GetDoubleRef(); p.reset(new ScRefListToken); p->GetRefList()->push_back( aRef); xt[i] = p.get(); @@ -2459,13 +2459,13 @@ void ScInterpreter::ScIntersect() x1 = xt[0]; x2 = xt[1]; - ScTokenRef xRes = new ScRefListToken; + ::boost::intrusive_ptr xRes = new ScRefListToken; ScRefList* pRefList = xRes->GetRefList(); - for (const auto& rRef1 : *x1->GetRefList()) + for (const auto& rRef1 : *static_cast(x1)->GetRefList()) { const ScAddress r11 = rRef1.Ref1.toAbs(mrDoc, aPos); const ScAddress r12 = rRef1.Ref2.toAbs(mrDoc, aPos); - for (const auto& rRef2 : *x2->GetRefList()) + for (const auto& rRef2 : *static_cast(x2)->GetRefList()) { const ScAddress r21 = rRef2.Ref1.toAbs(mrDoc, aPos); const ScAddress r22 = rRef2.Ref2.toAbs(mrDoc, aPos); @@ -2511,27 +2511,23 @@ void ScInterpreter::ScIntersect() switch (sv[i]) { case svSingleRef: + { + const ScAddress r = static_cast(pt[i])->GetSingleRef().toAbs(mrDoc, aPos); + nC1[i] = nC2[i] = r.Col(); + nR1[i] = nR2[i] = r.Row(); + nT1[i] = nT2[i] = r.Tab(); + } + break; case svDoubleRef: { - { - const ScAddress r = pt[i]->GetSingleRef()->toAbs(mrDoc, aPos); - nC1[i] = r.Col(); - nR1[i] = r.Row(); - nT1[i] = r.Tab(); - } - if (sv[i] == svDoubleRef) - { - const ScAddress r = pt[i]->GetSingleRef2()->toAbs(mrDoc, aPos); - nC2[i] = r.Col(); - nR2[i] = r.Row(); - nT2[i] = r.Tab(); - } - else - { - nC2[i] = nC1[i]; - nR2[i] = nR1[i]; - nT2[i] = nT1[i]; - } + const ScAddress r = static_cast(pt[i])->GetSingleRef().toAbs(mrDoc, aPos); + nC1[i] = r.Col(); + nR1[i] = r.Row(); + nT1[i] = r.Tab(); + const ScAddress r2 = static_cast(pt[i])->GetSingleRef2().toAbs(mrDoc, aPos); + nC2[i] = r2.Col(); + nR2[i] = r2.Row(); + nT2[i] = r2.Tab(); } break; default: @@ -2555,8 +2551,8 @@ void ScInterpreter::ScIntersect() void ScInterpreter::ScRangeFunc() { - formula::FormulaConstTokenRef x2 = PopToken(); - formula::FormulaConstTokenRef x1 = PopToken(); + formula::FormulaConstTokenRef x2 = PopReferenceOperand(); + formula::FormulaConstTokenRef x1 = PopReferenceOperand(); if (nGlobalError != FormulaError::NONE || !x2 || !x1) { @@ -2575,12 +2571,15 @@ void ScInterpreter::ScRangeFunc() void ScInterpreter::ScUnionFunc() { - formula::FormulaConstTokenRef p2nd = PopToken(); - formula::FormulaConstTokenRef p1st = PopToken(); + formula::FormulaConstTokenRef p2nd = PopReferenceOperand(); + formula::FormulaConstTokenRef p1st = PopReferenceOperand(); if (nGlobalError != FormulaError::NONE || !p2nd || !p1st) { - PushIllegalArgument(); + // An error in one of the parts, for example an error constant written into + // the list, becomes the result of the whole list. + PushError(nGlobalError != FormulaError::NONE ? nGlobalError + : FormulaError::IllegalArgument); return; } @@ -2589,23 +2588,25 @@ void ScInterpreter::ScUnionFunc() if ((sv1 != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList) || (sv2 != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList)) { - PushIllegalArgument(); + // A union joins references, so a value part like A1% leaves + // nothing to join and gives #VALUE!. + PushError( FormulaError::NoValue); return; } const formula::FormulaToken* x1 = p1st.get(); const formula::FormulaToken* x2 = p2nd.get(); - ScTokenRef xRes; + ::boost::intrusive_ptr xRes; // Append to an existing RefList if there is one. if (sv1 == svRefList) { - xRes = x1->Clone(); + xRes = static_cast(x1)->Clone(); sv1 = svUnknown; // mark as handled } else if (sv2 == svRefList) { - xRes = x2->Clone(); + xRes = static_cast(x2)->Clone(); sv2 = svUnknown; // mark as handled } else @@ -2622,16 +2623,16 @@ void ScInterpreter::ScUnionFunc() case svSingleRef: { ScComplexRefData aRef; - aRef.Ref1 = aRef.Ref2 = *pt[i]->GetSingleRef(); + aRef.Ref1 = aRef.Ref2 = static_cast(pt[i])->GetSingleRef(); pRes->push_back( aRef); } break; case svDoubleRef: - pRes->push_back( *pt[i]->GetDoubleRef()); + pRes->push_back( static_cast(pt[i])->GetDoubleRef()); break; case svRefList: { - const ScRefList* p = pt[i]->GetRefList(); + const ScRefList* p = static_cast(pt[i])->GetRefList(); for (const auto& rRef : *p) { pRes->push_back( rRef); @@ -2809,7 +2810,7 @@ void ScInterpreter::ScDde() //decision if (!mrDoc.HasLinkFormulaNeedingCheck()) { - //TODO: evaluate asynchron ??? + //TODO: evaluate asynchronously ??? pLink->TryUpdate(); // TryUpdate doesn't call Update multiple times } @@ -2922,7 +2923,7 @@ void ScInterpreter::ScBase() #if 0 // =BASIS(1e308;36) => GPF with // nDig = (size_t) ::rtl::math::approxFloor( fVal - fMult ); - // in spite off previous test if fVal >= fMult + // in spite of previous test if fVal >= fMult double fDebug1 = fVal - fMult; // fVal := 7,5975311883090e+290 // fMult := 7,5975311883090e+290 diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 42cce1c345f3..13aacb4d875f 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -68,6 +68,7 @@ #include #include #include +#include #include #include @@ -291,6 +292,50 @@ void ScInterpreter::GetCellString( svl::SharedString& rStr, const ScRefCellValue SetError(nErr); } +formula::FormulaCallableRef ScInterpreter::GetCellCallable( const ScRefCellValue& rCell ) +{ + formula::FormulaCallableRef pCallable = nullptr; + + CellType eType = rCell.getType(); + switch (eType) + { + case CELLTYPE_FORMULA: + { + ScFormulaCell* pFCell = rCell.getFormula(); + FormulaError nErr = pFCell->GetErrCode(); + if( nErr == FormulaError::NONE ) + { + if (pFCell->IsCallable()) + { + pCallable = pFCell->GetCallable(); + } + else + { + pCallable = nullptr; + SetError(FormulaError::NotAFunction); + } + } + else + { + pCallable = nullptr; + SetError(nErr); + } + } + break; + case CELLTYPE_VALUE: + case CELLTYPE_STRING: + case CELLTYPE_EDIT: + case CELLTYPE_NONE: + { + pCallable = nullptr; + SetError(FormulaError::NotAFunction); + } + break; + } + + return pCallable; +} + bool ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr) { @@ -643,7 +688,7 @@ void ScInterpreter::PushTempToken( FormulaToken* p ) { if (p->GetType() == svError) { - p->SetError( nGlobalError); + static_cast(p)->SetError( nGlobalError); PushTempTokenWithoutError( p); } else @@ -688,7 +733,7 @@ void ScInterpreter::PushTokenRef( const formula::FormulaConstTokenRef& x ) { if (nGlobalError != FormulaError::NONE) { - if (x->GetType() == svError && x->GetError() == nGlobalError) + if (x->GetType() == svError && static_cast(x.get())->GetError() == nGlobalError) PushTempTokenWithoutError( x.get()); else PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError)); @@ -733,7 +778,7 @@ void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString, if (pRetIndexExpr) *pRetIndexExpr = 0; } - else + else if (aCell.hasNumeric()) { double fVal = GetCellValue(rAddress, aCell); if (bFinalResult) @@ -751,6 +796,15 @@ void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString, if (pRetIndexExpr) *pRetIndexExpr = nCurFmtIndex; } + else + { + formula::FormulaCallableRef pCallable = GetCellCallable(aCell); + PushCallable(pCallable); + if (pRetTypeExpr) + *pRetTypeExpr = SvNumFormatType::UNDEFINED; + if (pRetIndexExpr) + *pRetIndexExpr = 0; + } } // Simply throw away TOS. @@ -771,20 +825,20 @@ void ScInterpreter::PopError() { sp--; if (pStack[sp]->GetType() == svError) - nGlobalError = pStack[sp]->GetError(); + nGlobalError = static_cast(pStack[sp])->GetError(); } else SetError(FormulaError::UnknownStackVariable); } -FormulaConstTokenRef ScInterpreter::PopToken() +FormulaConstTokenRef ScInterpreter::PopTokenImpl() { if (sp) { sp--; const FormulaToken* p = pStack[ sp ]; if (p->GetType() == svError) - nGlobalError = p->GetError(); + nGlobalError = static_cast(p)->GetError(); return p; } else @@ -792,6 +846,39 @@ FormulaConstTokenRef ScInterpreter::PopToken() return nullptr; } +void ScInterpreter::NoteMatrixOperandRange(const FormulaToken* pToken) +{ + if (!static_cast(pToken)->IsMatrixRangeToken()) + return; + const ScComplexRefData& rReference + = static_cast(pToken)->GetDoubleRef(); + // A relative part would have to be resolved against the position the range was read + // from, and we do not keep that, so only a fully absolute range says where the values + // sit. + if (rReference.Ref1.IsColRel() || rReference.Ref1.IsRowRel() + || rReference.Ref2.IsColRel() || rReference.Ref2.IsRowRel()) + { + return; + } + if (moMatrixOperandRange && *moMatrixOperandRange != rReference) + mbMatrixOperandRangeConflict = true; + moMatrixOperandRange = rReference; +} + +FormulaConstTokenRef ScInterpreter::PopReferenceOperand() +{ + FormulaConstTokenRef xToken = PopToken(); + if (!xToken || xToken->GetType() != svMatrix + || !static_cast(xToken.get())->IsMatrixReference()) + { + return xToken; + } + + const ScComplexRefData& rReference + = static_cast(xToken.get())->GetDoubleRef(); + return FormulaConstTokenRef(new ScDoubleRefToken(mrDoc.GetSheetLimits(), rReference)); +} + double ScInterpreter::PopDouble() { nCurFmtType = SvNumFormatType::NUMBER; @@ -803,14 +890,15 @@ double ScInterpreter::PopDouble() switch (p->GetType()) { case svError: - nGlobalError = p->GetError(); + nGlobalError = static_cast(p)->GetError(); break; case svDouble: { - SvNumFormatType nType = static_cast(p->GetDoubleType()); + auto pDToken = static_cast(p); + SvNumFormatType nType = static_cast(pDToken->GetDoubleType()); if (nType != SvNumFormatType::ALL && nType != SvNumFormatType::UNDEFINED) nCurFmtType = nType; - return p->GetDouble(); + return static_cast(p)->GetDouble(); } case svEmptyCell: case svMissing: @@ -835,12 +923,13 @@ const svl::SharedString & ScInterpreter::PopString() switch (p->GetType()) { case svError: - nGlobalError = p->GetError(); + nGlobalError = static_cast(p)->GetError(); break; case svString: + return static_cast(p)->GetString(); case svStringName: case svDPFieldName: - return p->GetString(); + return static_cast(p)->GetString(); case svEmptyCell: case svMissing: return svl::SharedString::getEmptyString(); @@ -929,12 +1018,12 @@ void ScInterpreter::PopSingleRef( ScAddress& rAdr ) switch (p->GetType()) { case svError: - nGlobalError = p->GetError(); + nGlobalError = static_cast(p)->GetError(); break; case svSingleRef: { - const ScSingleRefData* pRefData = p->GetSingleRef(); - if (pRefData->IsDeleted()) + const ScSingleRefData& rRefData = static_cast(p)->GetSingleRef(); + if (rRefData.IsDeleted()) { SetError( FormulaError::NoRef); break; @@ -943,7 +1032,7 @@ void ScInterpreter::PopSingleRef( ScAddress& rAdr ) SCCOL nCol; SCROW nRow; SCTAB nTab; - SingleRefToVars( *pRefData, nCol, nRow, nTab); + SingleRefToVars( rRefData, nCol, nRow, nTab); rAdr.Set( nCol, nRow, nTab ); if (!mrDoc.m_TableOpList.empty()) ReplaceCell( rAdr ); @@ -961,7 +1050,8 @@ void ScInterpreter::DoubleRefToVars( const formula::FormulaToken* p, SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1, SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2 ) { - const ScComplexRefData& rCRef = *p->GetDoubleRef(); + assert(p->GetType() == svDoubleRef); + const ScComplexRefData& rCRef = static_cast(p)->GetDoubleRef(); SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1); SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2); PutInOrder(rCol1, rCol2); @@ -1026,7 +1116,7 @@ void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1, switch (p->GetType()) { case svError: - nGlobalError = p->GetError(); + nGlobalError = static_cast(p)->GetError(); break; case svDoubleRef: DoubleRefToVars( p, rCol1, rRow1, rTab1, rCol2, rRow2, rTab2); @@ -1065,23 +1155,23 @@ void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRe switch (pToken->GetType()) { case svError: - nGlobalError = pToken->GetError(); + nGlobalError = static_cast(pToken)->GetError(); break; case svDoubleRef: { --sp; - const ScComplexRefData* pRefData = pToken->GetDoubleRef(); - if (pRefData->IsDeleted()) + const ScComplexRefData& rRefData = static_cast(pToken)->GetDoubleRef(); + if (rRefData.IsDeleted()) { SetError( FormulaError::NoRef); break; } - DoubleRefToRange( *pRefData, rRange); + DoubleRefToRange( rRefData, rRange); break; } case svRefList: { - const ScRefList* pList = pToken->GetRefList(); + const ScRefList* pList = static_cast(pToken)->GetRefList(); if (rRefInList < pList->size()) { DoubleRefToRange( (*pList)[rRefInList], rRange); @@ -1118,10 +1208,10 @@ void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp ) switch (p->GetType()) { case svError: - nGlobalError = p->GetError(); + nGlobalError = static_cast(p)->GetError(); break; case svDoubleRef: - DoubleRefToRange( *p->GetDoubleRef(), rRange, bDontCheckForTableOp); + DoubleRefToRange( static_cast(p)->GetDoubleRef(), rRange, bDontCheckForTableOp); break; default: SetError( FormulaError::IllegalParameter); @@ -1139,10 +1229,10 @@ const ScComplexRefData* ScInterpreter::GetStackDoubleRef(size_t rRefInList) switch (p->GetType()) { case svDoubleRef: - return p->GetDoubleRef(); + return &static_cast(p)->GetDoubleRef(); case svRefList: { - const ScRefList* pList = p->GetRefList(); + const ScRefList* pList = static_cast(p)->GetRefList(); if (rRefInList < pList->size()) return &(*pList)[rRefInList]; break; @@ -1168,7 +1258,7 @@ void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName if (eType == svError) { - nGlobalError = p->GetError(); + nGlobalError = static_cast(p)->GetError(); return; } @@ -1178,9 +1268,9 @@ void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName return; } - rFileId = p->GetIndex(); - rTabName = p->GetString().getString(); - rRef = *p->GetSingleRef(); + rFileId = static_cast(p)->GetFileId(); + rTabName = static_cast(p)->GetTableName().getString(); + rRef = static_cast(p)->GetSingleRef(); } void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt) @@ -1226,7 +1316,7 @@ void ScInterpreter::PopExternalSingleRef( } if (xNew->GetType() == svError) - SetError( xNew->GetError()); + SetError( static_cast(xNew.get())->GetError()); rToken = std::move(xNew); if (pFmt) @@ -1247,7 +1337,7 @@ void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName if (eType == svError) { - nGlobalError = p->GetError(); + nGlobalError = static_cast(p)->GetError(); return; } @@ -1257,9 +1347,9 @@ void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName return; } - rFileId = p->GetIndex(); - rTabName = p->GetString().getString(); - rRef = *p->GetDoubleRef(); + rFileId = static_cast(p)->GetFileId(); + rTabName = static_cast(p)->GetTableName().getString(); + rRef = static_cast(p)->GetDoubleRef(); } void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray) @@ -1291,7 +1381,7 @@ void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat) SetError( FormulaError::IllegalParameter); else { - rMat = p->GetMatrix(); + rMat = static_cast(p)->GetMatrix(); if (!rMat) SetError( FormulaError::UnknownVariable); } @@ -1336,7 +1426,7 @@ void ScInterpreter::GetExternalDoubleRef( assert(pToken); if (pToken->GetType() == svError) { - SetError( pToken->GetError()); + SetError( static_cast(pToken)->GetError()); return; } if (pToken->GetType() != svMatrix) @@ -1395,7 +1485,7 @@ void ScInterpreter::PopRefListPushMatrixOrRef() { if ( GetStackType() == svRefList ) { - FormulaConstTokenRef xTok = pStack[sp-1]; + ::boost::intrusive_ptr xTok = static_cast(pStack[sp-1]); const std::vector* pv = xTok->GetRefList(); if (pv) { @@ -1491,6 +1581,7 @@ bool ScInterpreter::ConvertMatrixParameters() case svDouble: case svString: case svStringName: + case svCallable: case svDPFieldName: case svSingleRef: case svExternalSingleRef: @@ -1504,7 +1595,7 @@ bool ScInterpreter::ConvertMatrixParameters() if ( ScParameterClassification::GetParameterType( pCur, nParams - i) == formula::ParamClass::Value ) { // only if single value expected - ScConstMatrixRef pMat = p->GetMatrix(); + ScConstMatrixRef pMat = static_cast(p)->GetMatrix(); if ( !pMat ) SetError( FormulaError::UnknownVariable); else @@ -1536,6 +1627,19 @@ bool ScInterpreter::ConvertMatrixParameters() SCROW nRow1, nRow2; SCTAB nTab1, nTab2; DoubleRefToVars( p, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); + // Trim full-column references to the data area to + // avoid creating huge matrices. Only shrink the end; + // the start is preserved for correct index semantics. + // Restrict to Value parameters to avoid changing the + // size of ForceArray/Array parameters used by paired- + // array functions like CORREL across different sheets. + if (eType == formula::ParamClass::Value && nTab1 == nTab2 + && (nRow2 == mrDoc.MaxRow() || nCol2 == mrDoc.MaxCol())) + { + SCCOL nTempCol = nCol1; + SCROW nTempRow = nRow1; + mrDoc.ShrinkToDataArea(nTab1, nTempCol, nTempRow, nCol2, nRow2); + } // Make sure the map exists, created if not. GetTokenMatrixMap(); ScMatrixRef pMat = CreateMatrixFromDoubleRef( p, @@ -1549,7 +1653,25 @@ bool ScInterpreter::ConvertMatrixParameters() if ( nJumpRows < o3tl::make_unsigned(nRow2 - nRow1 + 1) ) nJumpRows = static_cast(nRow2 - nRow1 + 1); } - formula::FormulaToken* pNew = new ScMatrixToken( std::move(pMat) ); + // For an @ operand, pair the matrix with + // the source range so the row-aligned slot + // can be picked. Other operators receive a + // plain ScMatrixToken. + formula::FormulaToken* pNew = nullptr; + if (pCur->GetOpCode() == ocSingleValue) + { + sc::RangeMatrix aRangeMatrix; + aRangeMatrix.mpMat = std::move(pMat); + aRangeMatrix.mnCol1 = nCol1; + aRangeMatrix.mnRow1 = nRow1; + aRangeMatrix.mnTab1 = nTab1; + aRangeMatrix.mnCol2 = nCol2; + aRangeMatrix.mnRow2 = nRow2; + aRangeMatrix.mnTab2 = nTab2; + pNew = new ScMatrixRangeToken(aRangeMatrix, true); + } + else + pNew = new ScMatrixToken( std::move(pMat) ); pNew->IncRef(); pStack[ sp - i ] = pNew; p->DecRef(); // p may be dead now! @@ -1562,9 +1684,10 @@ bool ScInterpreter::ConvertMatrixParameters() formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i); if (eType == formula::ParamClass::Value || eType == formula::ParamClass::Array) { - sal_uInt16 nFileId = p->GetIndex(); - OUString aTabName = p->GetString().getString(); - const ScComplexRefData& rRef = *p->GetDoubleRef(); + auto pEDRToken = static_cast(p); + sal_uInt16 nFileId = pEDRToken->GetFileId(); + OUString aTabName = pEDRToken->GetTableName().getString(); + const ScComplexRefData& rRef = pEDRToken->GetDoubleRef(); ScExternalRefCache::TokenArrayRef pArray; GetExternalDoubleRef(nFileId, aTabName, rRef, pArray); if (nGlobalError != FormulaError::NONE || !pArray) @@ -1573,7 +1696,8 @@ bool ScInterpreter::ConvertMatrixParameters() if (!pTemp) break; - ScMatrixRef pMat = pTemp->GetMatrix(); + assert(dynamic_cast(pTemp)); + ScMatrixRef pMat = static_cast(pTemp)->GetMatrix(); if (pMat) { if (eType == formula::ParamClass::Value) @@ -1666,16 +1790,19 @@ ScMatrixRef ScInterpreter::PopMatrix() switch (p->GetType()) { case svError: - nGlobalError = p->GetError(); + nGlobalError = static_cast(p)->GetError(); break; case svMatrix: { // ScMatrix itself maintains an im/mutable flag that should // be obeyed where necessary... so we can return ScMatrixRef // here instead of ScConstMatrixRef. - ScMatrix* pMat = const_cast(p)->GetMatrix(); + ScMatrix* pMat = static_cast(const_cast(p))->GetMatrix(); if ( pMat ) + { pMat->SetErrorInterpreter( this); + NoteMatrixOperandRange(p); + } else SetError( FormulaError::UnknownVariable); return pMat; @@ -1700,13 +1827,13 @@ sc::RangeMatrix ScInterpreter::PopRangeMatrix() { --sp; const FormulaToken* p = pStack[sp]; - aRet.mpMat = const_cast(p)->GetMatrix(); + aRet.mpMat = static_cast(const_cast(p))->GetMatrix(); if (aRet.mpMat) { aRet.mpMat->SetErrorInterpreter(this); - if (p->GetByte() == MATRIX_TOKEN_HAS_RANGE) + if (static_cast(p)->IsMatrixRangeToken()) { - const ScComplexRefData& rRef = *p->GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel()) { aRet.mnCol1 = rRef.Ref1.Col(); @@ -1852,6 +1979,12 @@ void ScInterpreter::PushString( const svl::SharedString& rString ) PushTempTokenWithoutError( new FormulaStringToken( rString ) ); } +void ScInterpreter::PushCallable( formula::FormulaCallableRef pCallable ) +{ + if (!IfErrorPushError()) + PushTempTokenWithoutError( new FormulaCallableToken( pCallable ) ); +} + void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab) { if (!IfErrorPushError()) @@ -1929,7 +2062,16 @@ void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat ) rMat.mpMat->SetErrorInterpreter(nullptr); nGlobalError = FormulaError::NONE; - PushTempTokenWithoutError(new ScMatrixRangeToken(rMat)); + PushTempTokenWithoutError(new ScMatrixRangeToken(rMat, true)); +} + +// Works on its operands one value at a time, so a same-shaped result holds one value per +// cell of the operand. Functions are out, they may move the values around. +static bool lclIsElementwiseOperator(OpCode eOp) +{ + if (eOp == ocAnd || eOp == ocOr) + return false; + return isBinaryOperatorOpCode(eOp) || isUnaryOperatorOpCode(eOp) || eOp == ocPercentSign; } void ScInterpreter::PushMatrix(const ScMatrixRef& pMat) @@ -1940,6 +2082,32 @@ void ScInterpreter::PushMatrix(const ScMatrixRef& pMat) // mean to inherit the error on all array elements in all following // operations. nGlobalError = FormulaError::NONE; + // A result shaped like the range an operand sat at sits there as well, one value per + // cell, so it keeps the range. The values are the operator's own now, so the range only + // says where they sit, not that they belong to those cells. + if (moMatrixOperandRange && !mbMatrixOperandRangeConflict && pCur + && lclIsElementwiseOperator(pCur->GetOpCode())) + { + const ScComplexRefData& rReference = *moMatrixOperandRange; + SCSIZE nCols = 0; + SCSIZE nRows = 0; + pMat->GetDimensions(nCols, nRows); + if (rReference.Ref1.Tab() == rReference.Ref2.Tab() + && static_cast(rReference.Ref2.Col() - rReference.Ref1.Col() + 1) == nCols + && static_cast(rReference.Ref2.Row() - rReference.Ref1.Row() + 1) == nRows) + { + sc::RangeMatrix aRangeMatrix; + aRangeMatrix.mpMat = pMat; + aRangeMatrix.mnCol1 = rReference.Ref1.Col(); + aRangeMatrix.mnRow1 = rReference.Ref1.Row(); + aRangeMatrix.mnTab1 = rReference.Ref1.Tab(); + aRangeMatrix.mnCol2 = rReference.Ref2.Col(); + aRangeMatrix.mnRow2 = rReference.Ref2.Row(); + aRangeMatrix.mnTab2 = rReference.Ref2.Tab(); + PushTempTokenWithoutError(new ScMatrixRangeToken(aRangeMatrix, false)); + return; + } + } PushTempTokenWithoutError( new ScMatrixToken( pMat ) ); } @@ -2161,6 +2329,12 @@ double ScInterpreter::GetDouble() nVal = 0.0; } break; + case svRefList: + // A list of ranges has no single value, which is what #VALUE! says. + PopError(); + SetError( FormulaError::NoValue); + nVal = 0.0; + break; case svExternalSingleRef: { ScExternalRefCache::TokenRef pToken; @@ -2171,10 +2345,12 @@ double ScInterpreter::GetDouble() break; } - if (pToken->GetType() == svDouble || pToken->GetType() == svEmptyCell) - nVal = pToken->GetDouble(); + if (pToken->GetType() == svDouble) + nVal = static_cast(pToken.get())->GetDouble(); + else if (pToken->GetType() == svEmptyCell) + nVal = 0.0; else - nVal = ConvertStringToValue( pToken->GetString().getString()); + nVal = ConvertStringToValue( static_cast(pToken.get())->GetString().getString()); } break; case svExternalDoubleRef: @@ -2205,6 +2381,24 @@ double ScInterpreter::GetDouble() Pop(); nVal = 0.0; break; + case svCallable: + { + formula::FormulaCallableRef pCallable = GetCallable(); + // GetCallable returns nullptr and sets an error for an operand that + // is not a usable callable, so the value stays zero in that case. + if (!pCallable) + nVal = 0.0; + else if (pCallable->GetOpCode() == ocTrue) + nVal = 1.0; + else if (pCallable->GetOpCode() == ocFalse) + nVal = 0.0; + else + { + SetError( FormulaError::IllegalParameter); + nVal = 0.0; + } + } + break; default: PopError(); SetError( FormulaError::IllegalParameter); @@ -2413,6 +2607,11 @@ svl::SharedString ScInterpreter::GetString() else return svl::SharedString::getEmptyString(); } + case svRefList: + // A list of ranges has no single value, same as when a number is asked for. + PopError(); + SetError( FormulaError::NoValue); + return svl::SharedString::getEmptyString(); case svExternalSingleRef: { ScExternalRefCache::TokenRef pToken; @@ -2422,10 +2621,13 @@ svl::SharedString ScInterpreter::GetString() if (pToken->GetType() == svDouble) { - return GetStringFromDouble( pToken->GetDouble() ); + return GetStringFromDouble( static_cast(pToken.get())->GetDouble() ); } - else // svString or svEmpty - return pToken->GetString(); + // svString or svEmpty + else if (pToken->GetType() == svString) + return static_cast(pToken.get())->GetString(); + else + return svl::SharedString::getEmptyString(); } case svExternalDoubleRef: { @@ -2537,6 +2739,81 @@ svl::SharedString ScInterpreter::GetStringFromDouble( double fVal ) return mrStrPool.intern(mrContext.NFGetInputLineString(fVal, nIndex)); } +formula::FormulaCallableRef ScInterpreter::GetCallable() +{ + switch (GetRawStackType()) + { + case svError: + { + PopError(); + return nullptr; + } + case svMissing: + case svEmptyCell: + case svDouble: + case svString: + case svStringName: + { + Pop(); + SetError( FormulaError::NotAFunction ); + return nullptr; + } + case svCallable: + return PopToken()->GetCallable(); + case svSingleRef: + { + ScAddress aAdr; + PopSingleRef( aAdr ); + if (nGlobalError == FormulaError::NONE) + { + ScRefCellValue aCell(mrDoc, aAdr); + return GetCellCallable(aCell); + } + else + return nullptr; + } + case svDoubleRef: + { // generate position dependent SingleRef + ScRange aRange; + PopDoubleRef( aRange ); + ScAddress aAdr; + if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr ) ) + { + ScRefCellValue aCell(mrDoc, aAdr); + return GetCellCallable(aCell); + } + else + return nullptr; + } + case svExternalSingleRef: + { + ScExternalRefCache::TokenRef pToken; + PopExternalSingleRef(pToken); + if (nGlobalError != FormulaError::NONE) + return nullptr; + + if (pToken->GetType() == svCallable) + { + return static_cast(pToken.get())->GetCallable(); + } + else + { + SetError( FormulaError::NotAFunction ); + return nullptr; + } + } + // TODO: a matrix or external double reference cannot yet produce a + // callable, so such an operand falls through to the illegal-argument + // case below. + default: + { + PopError(); + SetError( FormulaError::IllegalArgument); + return nullptr; + } + } +} + void ScInterpreter::ScDBGet() { bool bMissingField = false; @@ -2576,7 +2853,7 @@ void ScInterpreter::ScExternal() { sal_uInt8 nParamCount = GetByte(); OUString aUnoName; - OUString aFuncName( pCur->GetExternal().toAsciiUpperCase()); // programmatic name + OUString aFuncName( static_cast(pCur)->GetExternal().toAsciiUpperCase()); // programmatic name LegacyFuncData* pLegacyFuncData = ScGlobal::GetLegacyFuncCollection()->findByName(aFuncName); if (pLegacyFuncData) { @@ -3161,475 +3438,16 @@ void ScInterpreter::ScMissing() PushTempToken( new FormulaMissingToken ); } -#if HAVE_FEATURE_SCRIPTING - -static uno::Any lcl_getSheetModule( const uno::Reference& xCellRange, const ScDocument* pDok ) -{ - uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW ); - uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW ); - OUString sCodeName; - xProps->getPropertyValue(u"CodeName"_ustr) >>= sCodeName; - // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible - // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there - // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at - // the document in the future could fix this, especially IF the switching of the vba mode takes care to - // create the special document module objects if they don't exist. - BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager(); - - uno::Reference< uno::XInterface > xIf; - if ( pBasMgr && !pBasMgr->GetName().isEmpty() ) - { - OUString sProj( u"Standard"_ustr ); - if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() ) - { - sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName(); - } - StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj ); - if ( pBasic ) - { - SbModule* pMod = pBasic->FindModule( sCodeName ); - if ( pMod ) - { - xIf = pMod->GetUnoModule(); - } - } - } - return uno::Any( xIf ); -} - -static bool lcl_setVBARange( const ScRange& aRange, const ScDocument& rDok, SbxVariable* pPar ) -{ - bool bOk = false; - try - { - uno::Reference< uno::XInterface > xVBARange; - uno::Reference xCellRange = ScCellRangeObj::CreateRangeFromDoc( rDok, aRange ); - uno::Sequence< uno::Any > aArgs{ lcl_getSheetModule( xCellRange, &rDok ), - uno::Any(xCellRange) }; - xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( rDok.GetDocumentShell(), "ooo.vba.excel.Range", aArgs ); - if ( xVBARange.is() ) - { - SbxObjectRef aObj = GetSbUnoObject( u"A-Range"_ustr, uno::Any( xVBARange ) ); - SetSbUnoObjectDfltPropName( aObj.get() ); - bOk = pPar->PutObject( aObj.get() ); - } - } - catch( uno::Exception& ) - { - } - return bOk; -} - -static bool lcl_isNumericResult( double& fVal, const SbxVariable* pVar ) -{ - switch (pVar->GetType()) - { - case SbxINTEGER: - case SbxLONG: - case SbxSINGLE: - case SbxDOUBLE: - case SbxCURRENCY: - case SbxDATE: - case SbxUSHORT: - case SbxULONG: - case SbxINT: - case SbxUINT: - case SbxSALINT64: - case SbxSALUINT64: - case SbxDECIMAL: - fVal = pVar->GetDouble(); - return true; - case SbxBOOL: - fVal = (pVar->GetBool() ? 1.0 : 0.0); - return true; - default: - ; // nothing - } - return false; -} - -#endif - void ScInterpreter::ScMacro() { - #if !HAVE_FEATURE_SCRIPTING PushNoValue(); // without DocShell no CallBasic - return; #else - SbxBase::ResetError(); - - sal_uInt8 nParamCount = GetByte(); - OUString aMacro( pCur->GetExternal() ); - - ScDocShell* pDocSh = mrDoc.GetDocumentShell(); - if ( !pDocSh ) - { - PushNoValue(); // without DocShell no CallBasic - return; - } - - // no security queue beforehand (just CheckMacroWarn), moved to CallBasic - - // If the Dok was loaded during a Basic-Calls, - // is the Sbx-object created(?) -// pDocSh->GetSbxObject(); - - // search function with the name, - // then assemble SfxObjectShell::CallBasic from aBasicStr, aMacroStr - - StarBASIC* pRoot; - - try - { - pRoot = pDocSh->GetBasic(); - } - catch (...) - { - pRoot = nullptr; - } - - SbxVariable* pVar = pRoot ? pRoot->Find(aMacro, SbxClassType::Method) : nullptr; - if( !pVar || pVar->GetType() == SbxVOID ) - { - PushError( FormulaError::NoMacro ); - return; - } - SbMethod* pMethod = dynamic_cast(pVar); - if( !pMethod ) - { - PushError( FormulaError::NoMacro ); - return; - } - - bool bVolatileMacro = false; - - SbModule* pModule = pMethod->GetModule(); - bool bUseVBAObjects = pModule->IsVBASupport(); - SbxObject* pObject = pModule->GetParent(); - assert(pObject); - OSL_ENSURE(dynamic_cast(pObject) != nullptr, "No Basic found!"); - OUString aMacroStr = pObject->GetName() + "." + pModule->GetName() + "." + pMethod->GetName(); - OUString aBasicStr; - if (pRoot && bUseVBAObjects) - { - // just here to make sure the VBA objects when we run the macro during ODF import - pRoot->getVBAGlobals(); - } - if (pObject->GetParent()) - { - aBasicStr = pObject->GetParent()->GetName(); // document BASIC - } - else - { - aBasicStr = SfxGetpApp()->GetName(); // application BASIC - } - // assemble a parameter array - - SbxArrayRef refPar = new SbxArray; - bool bOk = true; - for( sal_uInt32 i = nParamCount; i && bOk ; i-- ) - { - SbxVariable* pPar = refPar->Get(i); - switch( GetStackType() ) - { - case svDouble: - pPar->PutDouble( GetDouble() ); - break; - case svString: - pPar->PutString( GetString().getString() ); - break; - case svExternalSingleRef: - { - ScExternalRefCache::TokenRef pToken; - PopExternalSingleRef(pToken); - if (nGlobalError != FormulaError::NONE) - bOk = false; - else - { - if ( pToken->GetType() == svString ) - pPar->PutString( pToken->GetString().getString() ); - else if ( pToken->GetType() == svDouble ) - pPar->PutDouble( pToken->GetDouble() ); - else - { - SetError( FormulaError::IllegalArgument ); - bOk = false; - } - } - } - break; - case svSingleRef: - { - ScAddress aAdr; - PopSingleRef( aAdr ); - if ( bUseVBAObjects ) - { - ScRange aRange( aAdr ); - bOk = lcl_setVBARange( aRange, mrDoc, pPar ); - } - else - { - bOk = SetSbxVariable( pPar, aAdr ); - } - } - break; - case svDoubleRef: - { - SCCOL nCol1; - SCROW nRow1; - SCTAB nTab1; - SCCOL nCol2; - SCROW nRow2; - SCTAB nTab2; - PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); - if( nTab1 != nTab2 ) - { - SetError( FormulaError::IllegalParameter ); - bOk = false; - } - else - { - if ( bUseVBAObjects ) - { - ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); - bOk = lcl_setVBARange( aRange, mrDoc, pPar ); - } - else - { - SbxDimArrayRef refArray = new SbxDimArray; - refArray->AddDim(1, nRow2 - nRow1 + 1); - refArray->AddDim(1, nCol2 - nCol1 + 1); - ScAddress aAdr( nCol1, nRow1, nTab1 ); - for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ ) - { - aAdr.SetRow( nRow ); - sal_Int32 nIdx[ 2 ]; - nIdx[ 0 ] = nRow-nRow1+1; - for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ ) - { - aAdr.SetCol( nCol ); - nIdx[ 1 ] = nCol-nCol1+1; - SbxVariable* p = refArray->Get(nIdx); - bOk = SetSbxVariable( p, aAdr ); - } - } - pPar->PutObject( refArray.get() ); - } - } - } - break; - case svExternalDoubleRef: - case svMatrix: - { - ScMatrixRef pMat = GetMatrix(); - SCSIZE nC, nR; - if (pMat && nGlobalError == FormulaError::NONE) - { - pMat->GetDimensions(nC, nR); - SbxDimArrayRef refArray = new SbxDimArray; - refArray->AddDim(1, static_cast(nR)); - refArray->AddDim(1, static_cast(nC)); - for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ ) - { - sal_Int32 nIdx[ 2 ]; - nIdx[ 0 ] = static_cast(nMatRow+1); - for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ ) - { - nIdx[ 1 ] = static_cast(nMatCol+1); - SbxVariable* p = refArray->Get(nIdx); - if (pMat->IsStringOrEmpty(nMatCol, nMatRow)) - { - p->PutString( pMat->GetString(nMatCol, nMatRow).getString() ); - } - else - { - p->PutDouble( pMat->GetDouble(nMatCol, nMatRow)); - } - } - } - pPar->PutObject( refArray.get() ); - } - else - { - SetError( FormulaError::IllegalParameter ); - } - } - break; - default: - SetError( FormulaError::IllegalParameter ); - bOk = false; - } - } - if( bOk ) - { - mrDoc.LockTable( aPos.Tab() ); - SbxVariableRef refRes = new SbxVariable; - mrDoc.IncMacroInterpretLevel(); - ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar.get(), refRes.get() ); - mrDoc.DecMacroInterpretLevel(); - mrDoc.UnlockTable( aPos.Tab() ); - - ScMacroManager* pMacroMgr = mrDoc.GetMacroManager(); - if (pMacroMgr) - { - bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() ); - pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell); - } - - double fVal; - SbxDataType eResType = refRes->GetType(); - if( SbxBase::GetError() ) - { - SetError( FormulaError::NoValue); - } - if ( eRet != ERRCODE_NONE ) - { - PushNoValue(); - } - else if (lcl_isNumericResult( fVal, refRes.get())) - { - switch (eResType) - { - case SbxDATE: - nFuncFmtType = SvNumFormatType::DATE; - break; - case SbxBOOL: - nFuncFmtType = SvNumFormatType::LOGICAL; - break; - // Do not add SbxCURRENCY, we don't know which currency. - default: - ; // nothing - } - PushDouble( fVal ); - } - else if ( eResType & SbxARRAY ) - { - SbxBase* pElemObj = refRes->GetObject(); - SbxDimArray* pDimArray = dynamic_cast(pElemObj); - sal_Int32 nDim = pDimArray ? pDimArray->GetDims() : 0; - if ( 1 <= nDim && nDim <= 2 ) - { - sal_Int32 nCs, nCe, nRs; - SCSIZE nC, nR; - SCCOL nColIdx; - SCROW nRowIdx; - if ( nDim == 1 ) - { // array( cols ) one line, several columns - pDimArray->GetDim(1, nCs, nCe); - nC = static_cast(nCe - nCs + 1); - nRs = 0; - nR = 1; - nColIdx = 0; - nRowIdx = 1; - } - else - { // array( rows, cols ) - sal_Int32 nRe; - pDimArray->GetDim(1, nRs, nRe); - nR = static_cast(nRe - nRs + 1); - pDimArray->GetDim(2, nCs, nCe); - nC = static_cast(nCe - nCs + 1); - nColIdx = 1; - nRowIdx = 0; - } - ScMatrixRef pMat = GetNewMat( nC, nR, /*bEmpty*/true); - if ( pMat ) - { - SbxVariable* pV; - for ( SCSIZE j=0; j < nR; j++ ) - { - sal_Int32 nIdx[ 2 ]; - // in one-dimensional array( cols ) nIdx[1] - // from SbxDimArray::Get is ignored - nIdx[ nRowIdx ] = nRs + static_cast(j); - for ( SCSIZE i=0; i < nC; i++ ) - { - nIdx[ nColIdx ] = nCs + static_cast(i); - pV = pDimArray->Get(nIdx); - if ( lcl_isNumericResult( fVal, pV) ) - { - pMat->PutDouble( fVal, i, j ); - } - else - { - pMat->PutString(mrStrPool.intern(pV->GetOUString()), i, j); - } - } - } - PushMatrix( pMat ); - } - else - { - PushIllegalArgument(); - } - } - else - { - PushNoValue(); - } - } - else - { - PushString( refRes->GetOUString() ); - } - } - - if (bVolatileMacro && meVolatileType == NOT_VOLATILE) - meVolatileType = VOLATILE_MACRO; + OUString aMacro( static_cast(pCur)->GetExternal() ); + PushCallable(new ScMacroFunction(*this, aMacro)); #endif } -#if HAVE_FEATURE_SCRIPTING - -bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos ) -{ - bool bOk = true; - ScRefCellValue aCell(mrDoc, rPos); - if (!aCell.isEmpty()) - { - FormulaError nErr; - double nVal; - switch (aCell.getType()) - { - case CELLTYPE_VALUE : - nVal = GetValueCellValue(rPos, aCell.getDouble()); - pVar->PutDouble( nVal ); - break; - case CELLTYPE_STRING : - case CELLTYPE_EDIT : - pVar->PutString(aCell.getString(mrDoc)); - break; - case CELLTYPE_FORMULA : - nErr = aCell.getFormula()->GetErrCode(); - if( nErr == FormulaError::NONE ) - { - if (aCell.getFormula()->IsValue()) - { - nVal = aCell.getFormula()->GetValue(); - pVar->PutDouble( nVal ); - } - else - pVar->PutString(aCell.getFormula()->GetString().getString()); - } - else - { - SetError( nErr ); - bOk = false; - } - break; - default : - pVar->PutEmpty(); - } - } - else - pVar->PutEmpty(); - - return bOk; -} - -#endif - void ScInterpreter::ScTableOp() { sal_uInt8 nParamCount = GetByte(); @@ -3722,7 +3540,7 @@ void ScInterpreter::ScTableOp() void ScInterpreter::ScDBArea() { - ScDBData* pDBData = mrDoc.GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex()); + ScDBData* pDBData = mrDoc.GetDBCollection()->getNamedDBs().findByIndex(static_cast(pCur)->GetIndex()); if (pDBData) { ScComplexRefData aRefData; @@ -3739,7 +3557,8 @@ void ScInterpreter::ScDBArea() void ScInterpreter::ScColRowNameAuto() { - ScComplexRefData aRefData( *pCur->GetDoubleRef() ); + assert(pCur->GetType() == svDoubleRef); + ScComplexRefData aRefData( static_cast(pCur)->GetDoubleRef() ); ScRange aAbs = aRefData.toAbs(mrDoc, aPos); if (!mrDoc.ValidRange(aAbs)) { @@ -3932,17 +3751,23 @@ void ScInterpreter::MergeCalcConfig() namespace { -double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos) +// Reduce a range-carrying matrix to the single value aligned with the +// formula position. On a hit rSrc receives the spill-range cell the +// value came from, so the caller can inherit its number format. On a +// miss the result is NaN and rSrc is left untouched. +double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos, ScAddress& rSrc) { if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2) { SCROW nOffset = rPos.Row() - rMat.mnRow1; + rSrc = ScAddress(rMat.mnCol1, rPos.Row(), rMat.mnTab1); return rMat.mpMat->GetDouble(0, nOffset); } if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2) { SCROW nOffset = rPos.Col() - rMat.mnCol1; + rSrc = ScAddress(rPos.Col(), rMat.mnRow1, rMat.mnTab1); return rMat.mpMat->GetDouble(nOffset, 0); } @@ -3984,6 +3809,480 @@ bool IsErrFunc(OpCode oc) } //namespace +void ScInterpreter::DispatchOpCode( OpCode eOp ) +{ + switch( eOp ) + { + case ocSep: + case ocClose: // pushed by the compiler + case ocMissing : ScMissing(); break; + case ocMacro : ScMacro(); break; + case ocDBArea : ScDBArea(); break; + case ocColRowNameAuto : ScColRowNameAuto(); break; + case ocIf : ScIfJump(); break; + case ocIfError : ScIfError( false ); break; + case ocIfNA : ScIfError( true ); break; + case ocChoose : ScChooseJump(); break; + case ocChooseCols : ScChooseCols(); break; + case ocChooseRows : ScChooseRows(); break; + case ocAdd : ScAdd(); break; + case ocSub : ScSub(); break; + case ocMul : ScMul(); break; + case ocDiv : ScDiv(); break; + case ocAmpersand : ScAmpersand(); break; + case ocPow : ScPow(); break; + case ocEqual : ScEqual(); break; + case ocNotEqual : ScNotEqual(); break; + case ocLess : ScLess(); break; + case ocGreater : ScGreater(); break; + case ocLessEqual : ScLessEqual(); break; + case ocGreaterEqual : ScGreaterEqual(); break; + case ocAnd : ScAnd(); break; + case ocOr : ScOr(); break; + case ocXor : ScXor(); break; + case ocIntersect : ScIntersect(); break; + case ocRange : ScRangeFunc(); break; + case ocUnion : ScUnionFunc(); break; + case ocCall : ScCall(); break; + case ocNot : ScNot(); break; + case ocNegSub : + case ocNeg : ScNeg(); break; + case ocSingleValue : ScSingleValue(); break; + case ocSpill : ScSpilledRange(); break; + case ocPercentSign : ScPercentSign(); break; + case ocPi : ScPi(); break; + case ocRandom : ScRandom(); break; + case ocRandArray : ScRandArray(); break; + case ocRandomNV : ScRandom(); break; + case ocRandbetweenNV : ScRandbetween(); break; + case ocFilter : ScFilter(); break; + case ocSort : ScSort(); break; + case ocSortBy : ScSortBy(); break; + case ocDrop : ScDrop(); break; + case ocExpand : ScExpand(); break; + case ocHStack : ScHStack(); break; + case ocVStack : ScVStack(); break; + case ocTake : ScTake(); break; + case ocTextAfter : ScTextAfter(); break; + case ocTextBefore : ScTextBefore(); break; + case ocTextSplit : ScTextSplit(); break; + case ocArrayToText : ScArrayToText(); break; + case ocToCol : ScToCol(); break; + case ocToRow : ScToRow(); break; + case ocUnique : ScUnique(); break; + case ocLet : ScLet(); break; + case ocWrapCols : ScWrapCols(); break; + case ocWrapRows : ScWrapRows(); break; + case ocLambda : ScLambda(); break; + case ocIsOmitted : ScIsOmitted(); break; + case ocTrue : ScTrue(); break; + case ocFalse : ScFalse(); break; + case ocGetActDate : ScGetActDate(); break; + case ocGetActTime : ScGetActTime(); break; + case ocNotAvail : PushError( FormulaError::NotAvailable); break; + case ocDeg : ScDeg(); break; + case ocRad : ScRad(); break; + case ocSin : ScSin(); break; + case ocCos : ScCos(); break; + case ocTan : ScTan(); break; + case ocCot : ScCot(); break; + case ocArcSin : ScArcSin(); break; + case ocArcCos : ScArcCos(); break; + case ocArcTan : ScArcTan(); break; + case ocArcCot : ScArcCot(); break; + case ocSinHyp : ScSinHyp(); break; + case ocCosHyp : ScCosHyp(); break; + case ocTanHyp : ScTanHyp(); break; + case ocCotHyp : ScCotHyp(); break; + case ocArcSinHyp : ScArcSinHyp(); break; + case ocArcCosHyp : ScArcCosHyp(); break; + case ocArcTanHyp : ScArcTanHyp(); break; + case ocArcCotHyp : ScArcCotHyp(); break; + case ocCosecant : ScCosecant(); break; + case ocSecant : ScSecant(); break; + case ocCosecantHyp : ScCosecantHyp(); break; + case ocSecantHyp : ScSecantHyp(); break; + case ocExp : ScExp(); break; + case ocLn : ScLn(); break; + case ocLog10 : ScLog10(); break; + case ocSqrt : ScSqrt(); break; + case ocFact : ScFact(); break; + case ocGetYear : ScGetYear(); break; + case ocGetMonth : ScGetMonth(); break; + case ocGetDay : ScGetDay(); break; + case ocGetDayOfWeek : ScGetDayOfWeek(); break; + case ocWeek : ScGetWeekOfYear(); break; + case ocIsoWeeknum : ScGetIsoWeekOfYear(); break; + case ocWeeknumOOo : ScWeeknumOOo(); break; + case ocEasterSunday : ScEasterSunday(); break; + case ocNetWorkdays : ScNetWorkdays( false); break; + case ocNetWorkdays_MS : ScNetWorkdays( true ); break; + case ocWorkday_MS : ScWorkday_MS(); break; + case ocGetHour : ScGetHour(); break; + case ocGetMin : ScGetMin(); break; + case ocGetSec : ScGetSec(); break; + case ocPlusMinus : ScPlusMinus(); break; + case ocAbs : ScAbs(); break; + case ocInt : ScInt(); break; + case ocEven : ScEven(); break; + case ocOdd : ScOdd(); break; + case ocPhi : ScPhi(); break; + case ocGauss : ScGauss(); break; + case ocStdNormDist : ScStdNormDist(); break; + case ocStdNormDist_MS : ScStdNormDist_MS(); break; + case ocFisher : ScFisher(); break; + case ocFisherInv : ScFisherInv(); break; + case ocIsEmpty : ScIsEmpty(); break; + case ocIsString : ScIsString(); break; + case ocIsNonString : ScIsNonString(); break; + case ocIsLogical : ScIsLogical(); break; + case ocType : ScType(); break; + case ocCell : ScCell(); break; + case ocIsRef : ScIsRef(); break; + case ocIsValue : ScIsValue(); break; + case ocIsFormula : ScIsFormula(); break; + case ocFormula : ScFormula(); break; + case ocIsNA : ScIsNV(); break; + case ocIsErr : ScIsErr(); break; + case ocIsError : ScIsError(); break; + case ocIsEven : ScIsEven(); break; + case ocIsOdd : ScIsOdd(); break; + case ocN : ScN(); break; + case ocGetDateValue : ScGetDateValue(); break; + case ocGetTimeValue : ScGetTimeValue(); break; + case ocCode : ScCode(); break; + case ocTrim : ScTrim(); break; + case ocUpper : ScUpper(); break; + case ocProper : ScProper(); break; + case ocLower : ScLower(); break; + case ocLen : ScLen(); break; + case ocT : ScT(); break; + case ocClean : ScClean(); break; + case ocValue : ScValue(); break; + case ocNumberValue : ScNumberValue(); break; + case ocChar : ScChar(); break; + case ocArcTan2 : ScArcTan2(); break; + case ocMod : ScMod(); break; + case ocPower : ScPower(); break; + case ocRound : ScRound(); break; + case ocRoundSig : ScRoundSignificant(); break; + case ocRoundUp : ScRoundUp(); break; + case ocTrunc : + case ocRoundDown : ScRoundDown(); break; + case ocCeil : ScCeil( true ); break; + case ocCeil_MS : ScCeil_MS(); break; + case ocCeil_Precise : + case ocCeil_ISO : ScCeil_Precise(); break; + case ocCeil_Math : ScCeil( false ); break; + case ocFloor : ScFloor( true ); break; + case ocFloor_MS : ScFloor_MS(); break; + case ocFloor_Precise : ScFloor_Precise(); break; + case ocFloor_Math : ScFloor( false ); break; + case ocSumProduct : ScSumProduct(); break; + case ocSumSQ : ScSumSQ(); break; + case ocSumX2MY2 : ScSumX2MY2(); break; + case ocSumX2DY2 : ScSumX2DY2(); break; + case ocSumXMY2 : ScSumXMY2(); break; + case ocRawSubtract : ScRawSubtract(); break; + case ocLog : ScLog(); break; + case ocGCD : ScGCD(); break; + case ocLCM : ScLCM(); break; + case ocGetDate : ScGetDate(); break; + case ocGetTime : ScGetTime(); break; + case ocGetDiffDate : ScGetDiffDate(); break; + case ocGetDiffDate360 : ScGetDiffDate360(); break; + case ocGetDateDif : ScGetDateDif(); break; + case ocMin : ScMin() ; break; + case ocMinA : ScMin( true ); break; + case ocMax : ScMax(); break; + case ocMaxA : ScMax( true ); break; + case ocSum : ScSum(); break; + case ocProduct : ScProduct(); break; + case ocNPV : ScNPV(); break; + case ocIRR : ScIRR(); break; + case ocMIRR : ScMIRR(); break; + case ocISPMT : ScISPMT(); break; + case ocAverage : ScAverage() ; break; + case ocAverageA : ScAverage( true ); break; + case ocCount : ScCount(); break; + case ocCount2 : ScCount2(); break; + case ocVar : + case ocVarS : ScVar(); break; + case ocVarA : ScVar( true ); break; + case ocVarP : + case ocVarP_MS : ScVarP(); break; + case ocVarPA : ScVarP( true ); break; + case ocStDev : + case ocStDevS : ScStDev(); break; + case ocStDevA : ScStDev( true ); break; + case ocStDevP : + case ocStDevP_MS : ScStDevP(); break; + case ocStDevPA : ScStDevP( true ); break; + case ocPV : ScPV(); break; + case ocSYD : ScSYD(); break; + case ocDDB : ScDDB(); break; + case ocDB : ScDB(); break; + case ocVBD : ScVDB(); break; + case ocPDuration : ScPDuration(); break; + case ocSLN : ScSLN(); break; + case ocPMT : ScPMT(); break; + case ocColumns : ScColumns(); break; + case ocRows : ScRows(); break; + case ocSheets : ScSheets(); break; + case ocColumn : ScColumn(); break; + case ocRow : ScRow(); break; + case ocSheet : ScSheet(); break; + case ocRRI : ScRRI(); break; + case ocFV : ScFV(); break; + case ocNper : ScNper(); break; + case ocRate : ScRate(); break; + case ocFilterXML : ScFilterXML(); break; + case ocWebservice : ScWebservice(); break; + case ocEncodeURL : ScEncodeURL(); break; + case ocColor : ScColor(); break; + case ocErf_MS : ScErf(); break; + case ocErfc_MS : ScErfc(); break; + case ocIpmt : ScIpmt(); break; + case ocPpmt : ScPpmt(); break; + case ocCumIpmt : ScCumIpmt(); break; + case ocCumPrinc : ScCumPrinc(); break; + case ocEffect : ScEffect(); break; + case ocNominal : ScNominal(); break; + case ocSubTotal : ScSubTotal(); break; + case ocAggregate : ScAggregate(); break; + case ocDBSum : ScDBSum(); break; + case ocDBCount : ScDBCount(); break; + case ocDBCount2 : ScDBCount2(); break; + case ocDBAverage : ScDBAverage(); break; + case ocDBGet : ScDBGet(); break; + case ocDBMax : ScDBMax(); break; + case ocDBMin : ScDBMin(); break; + case ocDBProduct : ScDBProduct(); break; + case ocDBStdDev : ScDBStdDev(); break; + case ocDBStdDevP : ScDBStdDevP(); break; + case ocDBVar : ScDBVar(); break; + case ocDBVarP : ScDBVarP(); break; + case ocIndirect : ScIndirect(); break; + case ocAddress : ScAddressFunc(); break; + case ocMatch : ScMatch(); break; + case ocXMatch : ScXMatch(); break; + case ocCountEmptyCells : ScCountEmptyCells(); break; + case ocCountIf : ScCountIf(); break; + case ocSumIf : ScSumIf(); break; + case ocAverageIf : ScAverageIf(); break; + case ocSumIfs : ScSumIfs(); break; + case ocAverageIfs : ScAverageIfs(); break; + case ocCountIfs : ScCountIfs(); break; + case ocLookup : ScLookup(); break; + case ocVLookup : ScVLookup(); break; + case ocXLookup : ScXLookup(); break; + case ocHLookup : ScHLookup(); break; + case ocIndex : ScIndex(); break; + case ocMultiArea : ScMultiArea(); break; + case ocOffset : ScOffset(); break; + case ocAreas : ScAreas(); break; + case ocCurrency : ScCurrency(); break; + case ocReplace : ScReplace(); break; + case ocFixed : ScFixed(); break; + case ocFind : ScFind(); break; + case ocExact : ScExact(); break; + case ocLeft : ScLeft(); break; + case ocRight : ScRight(); break; + case ocSearch : ScSearch(); break; + case ocMid : ScMid(); break; + case ocText : ScText(); break; + case ocSubstitute : ScSubstitute(); break; + case ocRegex : ScRegex(); break; + case ocRept : ScRept(); break; + case ocConcat : ScConcat(); break; + case ocConcat_MS : ScConcat_MS(); break; + case ocTextJoin_MS : ScTextJoin_MS(); break; + case ocIfs_MS : ScIfs_MS(); break; + case ocSwitch_MS : ScSwitch_MS(); break; + case ocMinIfs_MS : ScMinIfs_MS(); break; + case ocMaxIfs_MS : ScMaxIfs_MS(); break; + case ocMatValue : ScMatValue(); break; + case ocMatrixUnit : ScEMat(); break; + case ocMatDet : ScMatDet(); break; + case ocMatInv : ScMatInv(); break; + case ocMatMult : ScMatMult(); break; + case ocMatSequence : ScMatSequence(); break; + case ocMatTrans : ScMatTrans(); break; + case ocMatRef : ScMatRef(); break; + case ocByCol : ScByCol(); break; + case ocByRow : ScByRow(); break; + case ocMakeArray : ScMakeArray(); break; + case ocMap : ScMap(); break; + case ocReduce : ScReduce(); break; + case ocScan : ScScan(); break; + case ocB : ScB(); break; + case ocNormDist : ScNormDist( 3 ); break; + case ocNormDist_MS : ScNormDist( 4 ); break; + case ocExpDist : + case ocExpDist_MS : ScExpDist(); break; + case ocBinomDist : + case ocBinomDist_MS : ScBinomDist(); break; + case ocPoissonDist : ScPoissonDist( true ); break; + case ocPoissonDist_MS : ScPoissonDist( false ); break; + case ocCombin : ScCombin(); break; + case ocCombinA : ScCombinA(); break; + case ocPermut : ScPermut(); break; + case ocPermutationA : ScPermutationA(); break; + case ocHypGeomDist : ScHypGeomDist( 4 ); break; + case ocHypGeomDist_MS : ScHypGeomDist( 5 ); break; + case ocLogNormDist : ScLogNormDist( 1 ); break; + case ocLogNormDist_MS : ScLogNormDist( 4 ); break; + case ocTDist : ScTDist(); break; + case ocTDist_MS : ScTDist_MS(); break; + case ocTDist_RT : ScTDist_T( 1 ); break; + case ocTDist_2T : ScTDist_T( 2 ); break; + case ocFDist : + case ocFDist_RT : ScFDist(); break; + case ocFDist_LT : ScFDist_LT(); break; + case ocChiDist : ScChiDist( true ); break; + case ocChiDist_MS : ScChiDist( false ); break; + case ocChiSqDist : ScChiSqDist(); break; + case ocChiSqDist_MS : ScChiSqDist_MS(); break; + case ocStandard : ScStandard(); break; + case ocAveDev : ScAveDev(); break; + case ocDevSq : ScDevSq(); break; + case ocKurt : ScKurt(); break; + case ocSkew : ScSkew(); break; + case ocSkewp : ScSkewp(); break; + case ocModalValue : ScModalValue(); break; + case ocModalValue_MS : ScModalValue_MS( true ); break; + case ocModalValue_Multi : ScModalValue_MS( false ); break; + case ocMedian : ScMedian(); break; + case ocGeoMean : ScGeoMean(); break; + case ocHarMean : ScHarMean(); break; + case ocWeibull : + case ocWeibull_MS : ScWeibull(); break; + case ocBinomInv : + case ocCritBinom : ScCritBinom(); break; + case ocNegBinomVert : ScNegBinomDist(); break; + case ocNegBinomDist_MS : ScNegBinomDist_MS(); break; + case ocNoName : ScNoName(); break; + case ocBad : ScBadName(); break; + case ocZTest : + case ocZTest_MS : ScZTest(); break; + case ocTTest : + case ocTTest_MS : ScTTest(); break; + case ocFTest : + case ocFTest_MS : ScFTest(); break; + case ocRank : + case ocRank_Eq : ScRank( false ); break; + case ocRank_Avg : ScRank( true ); break; + case ocPercentile : + case ocPercentile_Inc : ScPercentile( true ); break; + case ocPercentile_Exc : ScPercentile( false ); break; + case ocPercentrank : + case ocPercentrank_Inc : ScPercentrank( true ); break; + case ocPercentrank_Exc : ScPercentrank( false ); break; + case ocLarge : ScLarge(); break; + case ocSmall : ScSmall(); break; + case ocFrequency : ScFrequency(); break; + case ocQuartile : + case ocQuartile_Inc : ScQuartile( true ); break; + case ocQuartile_Exc : ScQuartile( false ); break; + case ocNormInv : + case ocNormInv_MS : ScNormInv(); break; + case ocSNormInv : + case ocSNormInv_MS : ScSNormInv(); break; + case ocConfidence : + case ocConfidence_N : ScConfidence(); break; + case ocConfidence_T : ScConfidenceT(); break; + case ocTrimMean : ScTrimMean(); break; + case ocProb : ScProbability(); break; + case ocCorrel : ScCorrel(); break; + case ocCovar : + case ocCovarianceP : ScCovarianceP(); break; + case ocCovarianceS : ScCovarianceS(); break; + case ocPearson : ScPearson(); break; + case ocRSQ : ScRSQ(); break; + case ocSTEYX : ScSTEYX(); break; + case ocSlope : ScSlope(); break; + case ocIntercept : ScIntercept(); break; + case ocTrend : ScTrend(); break; + case ocGrowth : ScGrowth(); break; + case ocLinest : ScLinest(); break; + case ocLogest : ScLogest(); break; + case ocForecast_LIN : + case ocForecast : ScForecast(); break; + case ocForecast_ETS_ADD : ScForecast_Ets( etsAdd ); break; + case ocForecast_ETS_SEA : ScForecast_Ets( etsSeason ); break; + case ocForecast_ETS_MUL : ScForecast_Ets( etsMult ); break; + case ocForecast_ETS_PIA : ScForecast_Ets( etsPIAdd ); break; + case ocForecast_ETS_PIM : ScForecast_Ets( etsPIMult ); break; + case ocForecast_ETS_STA : ScForecast_Ets( etsStatAdd ); break; + case ocForecast_ETS_STM : ScForecast_Ets( etsStatMult ); break; + case ocGammaLn : + case ocGammaLn_MS : ScLogGamma(); break; + case ocGamma : ScGamma(); break; + case ocGammaDist : ScGammaDist( true ); break; + case ocGammaDist_MS : ScGammaDist( false ); break; + case ocGammaInv : + case ocGammaInv_MS : ScGammaInv(); break; + case ocChiTest : + case ocChiTest_MS : ScChiTest(); break; + case ocChiInv : + case ocChiInv_MS : ScChiInv(); break; + case ocChiSqInv : + case ocChiSqInv_MS : ScChiSqInv(); break; + case ocTInv : + case ocTInv_2T : ScTInv( 2 ); break; + case ocTInv_MS : ScTInv( 4 ); break; + case ocFInv : + case ocFInv_RT : ScFInv(); break; + case ocFInv_LT : ScFInv_LT(); break; + case ocLogInv : + case ocLogInv_MS : ScLogNormInv(); break; + case ocBetaDist : ScBetaDist(); break; + case ocBetaDist_MS : ScBetaDist_MS(); break; + case ocBetaInv : + case ocBetaInv_MS : ScBetaInv(); break; + case ocFourier : ScFourier(); break; + case ocExternal : + case ocUDExternal : ScExternal(); break; + case ocTableOp : ScTableOp(); break; + case ocStop : break; + case ocErrorType : ScErrorType(); break; + case ocErrorType_ODF : ScErrorType_ODF(); break; + case ocCurrent : ScCurrent(); break; + case ocStyle : ScStyle(); break; + case ocDde : ScDde(); break; + case ocBase : ScBase(); break; + case ocDecimal : ScDecimal(); break; + case ocConvertOOo : ScConvertOOo(); break; + case ocEuroConvert : ScEuroConvert(); break; + case ocRoman : ScRoman(); break; + case ocArabic : ScArabic(); break; + case ocInfo : ScInfo(); break; + case ocHyperLink : ScHyperLink(); break; + case ocBahtText : ScBahtText(); break; + case ocGetPivotData : ScGetPivotData(); break; + case ocJis : ScJis(); break; + case ocAsc : ScAsc(); break; + case ocLenB : ScLenB(); break; + case ocRightB : ScRightB(); break; + case ocLeftB : ScLeftB(); break; + case ocMidB : ScMidB(); break; + case ocReplaceB : ScReplaceB(); break; + case ocFindB : ScFindB(); break; + case ocSearchB : ScSearchB(); break; + case ocUnicode : ScUnicode(); break; + case ocUnichar : ScUnichar(); break; + case ocBitAnd : ScBitAnd(); break; + case ocBitOr : ScBitOr(); break; + case ocBitXor : ScBitXor(); break; + case ocBitRshift : ScBitRshift(); break; + case ocBitLshift : ScBitLshift(); break; + case ocTTT : ScTTT(); break; + case ocDebugVar : ScDebugVar(); break; + case ocNone : break; + default : PushError( FormulaError::UnknownOpCode); break; + } +} + StackVar ScInterpreter::Interpret() { SvNumFormatType nRetTypeExpr = SvNumFormatType::UNDEFINED; @@ -4018,7 +4317,9 @@ StackVar ScInterpreter::Interpret() if (!pCur || (nGlobalError != FormulaError::NONE && nErrorFunction > nErrorFunctionCount) ) break; eOp = pCur->GetOpCode(); - cPar = pCur->GetByte(); + cPar = pCur->GetParamCount(); + moMatrixOperandRange.reset(); + mbMatrixOperandRangeConflict = false; if ( eOp == ocPush ) { // RPN code push without error @@ -4092,463 +4393,9 @@ StackVar ScInterpreter::Interpret() } } - switch( eOp ) - { - case ocSep: - case ocClose: // pushed by the compiler - case ocMissing : ScMissing(); break; - case ocMacro : ScMacro(); break; - case ocDBArea : ScDBArea(); break; - case ocColRowNameAuto : ScColRowNameAuto(); break; - case ocIf : ScIfJump(); break; - case ocIfError : ScIfError( false ); break; - case ocIfNA : ScIfError( true ); break; - case ocChoose : ScChooseJump(); break; - case ocChooseCols : ScChooseCols(); break; - case ocChooseRows : ScChooseRows(); break; - case ocAdd : ScAdd(); break; - case ocSub : ScSub(); break; - case ocMul : ScMul(); break; - case ocDiv : ScDiv(); break; - case ocAmpersand : ScAmpersand(); break; - case ocPow : ScPow(); break; - case ocEqual : ScEqual(); break; - case ocNotEqual : ScNotEqual(); break; - case ocLess : ScLess(); break; - case ocGreater : ScGreater(); break; - case ocLessEqual : ScLessEqual(); break; - case ocGreaterEqual : ScGreaterEqual(); break; - case ocAnd : ScAnd(); break; - case ocOr : ScOr(); break; - case ocXor : ScXor(); break; - case ocIntersect : ScIntersect(); break; - case ocRange : ScRangeFunc(); break; - case ocUnion : ScUnionFunc(); break; - case ocNot : ScNot(); break; - case ocNegSub : - case ocNeg : ScNeg(); break; - case ocPercentSign : ScPercentSign(); break; - case ocPi : ScPi(); break; - case ocRandom : ScRandom(); break; - case ocRandArray : ScRandArray(); break; - case ocRandomNV : ScRandom(); break; - case ocRandbetweenNV : ScRandbetween(); break; - case ocFilter : ScFilter(); break; - case ocSort : ScSort(); break; - case ocSortBy : ScSortBy(); break; - case ocDrop : ScDrop(); break; - case ocExpand : ScExpand(); break; - case ocHStack : ScHStack(); break; - case ocVStack : ScVStack(); break; - case ocTake : ScTake(); break; - case ocTextAfter : ScTextAfter(); break; - case ocTextBefore : ScTextBefore(); break; - case ocTextSplit : ScTextSplit(); break; - case ocToCol : ScToCol(); break; - case ocToRow : ScToRow(); break; - case ocUnique : ScUnique(); break; - case ocLet : ScLet(); break; - case ocWrapCols : ScWrapCols(); break; - case ocWrapRows : ScWrapRows(); break; - case ocTrue : ScTrue(); break; - case ocFalse : ScFalse(); break; - case ocGetActDate : ScGetActDate(); break; - case ocGetActTime : ScGetActTime(); break; - case ocNotAvail : PushError( FormulaError::NotAvailable); break; - case ocDeg : ScDeg(); break; - case ocRad : ScRad(); break; - case ocSin : ScSin(); break; - case ocCos : ScCos(); break; - case ocTan : ScTan(); break; - case ocCot : ScCot(); break; - case ocArcSin : ScArcSin(); break; - case ocArcCos : ScArcCos(); break; - case ocArcTan : ScArcTan(); break; - case ocArcCot : ScArcCot(); break; - case ocSinHyp : ScSinHyp(); break; - case ocCosHyp : ScCosHyp(); break; - case ocTanHyp : ScTanHyp(); break; - case ocCotHyp : ScCotHyp(); break; - case ocArcSinHyp : ScArcSinHyp(); break; - case ocArcCosHyp : ScArcCosHyp(); break; - case ocArcTanHyp : ScArcTanHyp(); break; - case ocArcCotHyp : ScArcCotHyp(); break; - case ocCosecant : ScCosecant(); break; - case ocSecant : ScSecant(); break; - case ocCosecantHyp : ScCosecantHyp(); break; - case ocSecantHyp : ScSecantHyp(); break; - case ocExp : ScExp(); break; - case ocLn : ScLn(); break; - case ocLog10 : ScLog10(); break; - case ocSqrt : ScSqrt(); break; - case ocFact : ScFact(); break; - case ocGetYear : ScGetYear(); break; - case ocGetMonth : ScGetMonth(); break; - case ocGetDay : ScGetDay(); break; - case ocGetDayOfWeek : ScGetDayOfWeek(); break; - case ocWeek : ScGetWeekOfYear(); break; - case ocIsoWeeknum : ScGetIsoWeekOfYear(); break; - case ocWeeknumOOo : ScWeeknumOOo(); break; - case ocEasterSunday : ScEasterSunday(); break; - case ocNetWorkdays : ScNetWorkdays( false); break; - case ocNetWorkdays_MS : ScNetWorkdays( true ); break; - case ocWorkday_MS : ScWorkday_MS(); break; - case ocGetHour : ScGetHour(); break; - case ocGetMin : ScGetMin(); break; - case ocGetSec : ScGetSec(); break; - case ocPlusMinus : ScPlusMinus(); break; - case ocAbs : ScAbs(); break; - case ocInt : ScInt(); break; - case ocEven : ScEven(); break; - case ocOdd : ScOdd(); break; - case ocPhi : ScPhi(); break; - case ocGauss : ScGauss(); break; - case ocStdNormDist : ScStdNormDist(); break; - case ocStdNormDist_MS : ScStdNormDist_MS(); break; - case ocFisher : ScFisher(); break; - case ocFisherInv : ScFisherInv(); break; - case ocIsEmpty : ScIsEmpty(); break; - case ocIsString : ScIsString(); break; - case ocIsNonString : ScIsNonString(); break; - case ocIsLogical : ScIsLogical(); break; - case ocType : ScType(); break; - case ocCell : ScCell(); break; - case ocIsRef : ScIsRef(); break; - case ocIsValue : ScIsValue(); break; - case ocIsFormula : ScIsFormula(); break; - case ocFormula : ScFormula(); break; - case ocIsNA : ScIsNV(); break; - case ocIsErr : ScIsErr(); break; - case ocIsError : ScIsError(); break; - case ocIsEven : ScIsEven(); break; - case ocIsOdd : ScIsOdd(); break; - case ocN : ScN(); break; - case ocGetDateValue : ScGetDateValue(); break; - case ocGetTimeValue : ScGetTimeValue(); break; - case ocCode : ScCode(); break; - case ocTrim : ScTrim(); break; - case ocUpper : ScUpper(); break; - case ocProper : ScProper(); break; - case ocLower : ScLower(); break; - case ocLen : ScLen(); break; - case ocT : ScT(); break; - case ocClean : ScClean(); break; - case ocValue : ScValue(); break; - case ocNumberValue : ScNumberValue(); break; - case ocChar : ScChar(); break; - case ocArcTan2 : ScArcTan2(); break; - case ocMod : ScMod(); break; - case ocPower : ScPower(); break; - case ocRound : ScRound(); break; - case ocRoundSig : ScRoundSignificant(); break; - case ocRoundUp : ScRoundUp(); break; - case ocTrunc : - case ocRoundDown : ScRoundDown(); break; - case ocCeil : ScCeil( true ); break; - case ocCeil_MS : ScCeil_MS(); break; - case ocCeil_Precise : - case ocCeil_ISO : ScCeil_Precise(); break; - case ocCeil_Math : ScCeil( false ); break; - case ocFloor : ScFloor( true ); break; - case ocFloor_MS : ScFloor_MS(); break; - case ocFloor_Precise : ScFloor_Precise(); break; - case ocFloor_Math : ScFloor( false ); break; - case ocSumProduct : ScSumProduct(); break; - case ocSumSQ : ScSumSQ(); break; - case ocSumX2MY2 : ScSumX2MY2(); break; - case ocSumX2DY2 : ScSumX2DY2(); break; - case ocSumXMY2 : ScSumXMY2(); break; - case ocRawSubtract : ScRawSubtract(); break; - case ocLog : ScLog(); break; - case ocGCD : ScGCD(); break; - case ocLCM : ScLCM(); break; - case ocGetDate : ScGetDate(); break; - case ocGetTime : ScGetTime(); break; - case ocGetDiffDate : ScGetDiffDate(); break; - case ocGetDiffDate360 : ScGetDiffDate360(); break; - case ocGetDateDif : ScGetDateDif(); break; - case ocMin : ScMin() ; break; - case ocMinA : ScMin( true ); break; - case ocMax : ScMax(); break; - case ocMaxA : ScMax( true ); break; - case ocSum : ScSum(); break; - case ocProduct : ScProduct(); break; - case ocNPV : ScNPV(); break; - case ocIRR : ScIRR(); break; - case ocMIRR : ScMIRR(); break; - case ocISPMT : ScISPMT(); break; - case ocAverage : ScAverage() ; break; - case ocAverageA : ScAverage( true ); break; - case ocCount : ScCount(); break; - case ocCount2 : ScCount2(); break; - case ocVar : - case ocVarS : ScVar(); break; - case ocVarA : ScVar( true ); break; - case ocVarP : - case ocVarP_MS : ScVarP(); break; - case ocVarPA : ScVarP( true ); break; - case ocStDev : - case ocStDevS : ScStDev(); break; - case ocStDevA : ScStDev( true ); break; - case ocStDevP : - case ocStDevP_MS : ScStDevP(); break; - case ocStDevPA : ScStDevP( true ); break; - case ocPV : ScPV(); break; - case ocSYD : ScSYD(); break; - case ocDDB : ScDDB(); break; - case ocDB : ScDB(); break; - case ocVBD : ScVDB(); break; - case ocPDuration : ScPDuration(); break; - case ocSLN : ScSLN(); break; - case ocPMT : ScPMT(); break; - case ocColumns : ScColumns(); break; - case ocRows : ScRows(); break; - case ocSheets : ScSheets(); break; - case ocColumn : ScColumn(); break; - case ocRow : ScRow(); break; - case ocSheet : ScSheet(); break; - case ocRRI : ScRRI(); break; - case ocFV : ScFV(); break; - case ocNper : ScNper(); break; - case ocRate : ScRate(); break; - case ocFilterXML : ScFilterXML(); break; - case ocWebservice : ScWebservice(); break; - case ocEncodeURL : ScEncodeURL(); break; - case ocColor : ScColor(); break; - case ocErf_MS : ScErf(); break; - case ocErfc_MS : ScErfc(); break; - case ocIpmt : ScIpmt(); break; - case ocPpmt : ScPpmt(); break; - case ocCumIpmt : ScCumIpmt(); break; - case ocCumPrinc : ScCumPrinc(); break; - case ocEffect : ScEffect(); break; - case ocNominal : ScNominal(); break; - case ocSubTotal : ScSubTotal(); break; - case ocAggregate : ScAggregate(); break; - case ocDBSum : ScDBSum(); break; - case ocDBCount : ScDBCount(); break; - case ocDBCount2 : ScDBCount2(); break; - case ocDBAverage : ScDBAverage(); break; - case ocDBGet : ScDBGet(); break; - case ocDBMax : ScDBMax(); break; - case ocDBMin : ScDBMin(); break; - case ocDBProduct : ScDBProduct(); break; - case ocDBStdDev : ScDBStdDev(); break; - case ocDBStdDevP : ScDBStdDevP(); break; - case ocDBVar : ScDBVar(); break; - case ocDBVarP : ScDBVarP(); break; - case ocIndirect : ScIndirect(); break; - case ocAddress : ScAddressFunc(); break; - case ocMatch : ScMatch(); break; - case ocXMatch : ScXMatch(); break; - case ocCountEmptyCells : ScCountEmptyCells(); break; - case ocCountIf : ScCountIf(); break; - case ocSumIf : ScSumIf(); break; - case ocAverageIf : ScAverageIf(); break; - case ocSumIfs : ScSumIfs(); break; - case ocAverageIfs : ScAverageIfs(); break; - case ocCountIfs : ScCountIfs(); break; - case ocLookup : ScLookup(); break; - case ocVLookup : ScVLookup(); break; - case ocXLookup : ScXLookup(); break; - case ocHLookup : ScHLookup(); break; - case ocIndex : ScIndex(); break; - case ocMultiArea : ScMultiArea(); break; - case ocOffset : ScOffset(); break; - case ocAreas : ScAreas(); break; - case ocCurrency : ScCurrency(); break; - case ocReplace : ScReplace(); break; - case ocFixed : ScFixed(); break; - case ocFind : ScFind(); break; - case ocExact : ScExact(); break; - case ocLeft : ScLeft(); break; - case ocRight : ScRight(); break; - case ocSearch : ScSearch(); break; - case ocMid : ScMid(); break; - case ocText : ScText(); break; - case ocSubstitute : ScSubstitute(); break; - case ocRegex : ScRegex(); break; - case ocRept : ScRept(); break; - case ocConcat : ScConcat(); break; - case ocConcat_MS : ScConcat_MS(); break; - case ocTextJoin_MS : ScTextJoin_MS(); break; - case ocIfs_MS : ScIfs_MS(); break; - case ocSwitch_MS : ScSwitch_MS(); break; - case ocMinIfs_MS : ScMinIfs_MS(); break; - case ocMaxIfs_MS : ScMaxIfs_MS(); break; - case ocMatValue : ScMatValue(); break; - case ocMatrixUnit : ScEMat(); break; - case ocMatDet : ScMatDet(); break; - case ocMatInv : ScMatInv(); break; - case ocMatMult : ScMatMult(); break; - case ocMatSequence : ScMatSequence(); break; - case ocMatTrans : ScMatTrans(); break; - case ocMatRef : ScMatRef(); break; - case ocB : ScB(); break; - case ocNormDist : ScNormDist( 3 ); break; - case ocNormDist_MS : ScNormDist( 4 ); break; - case ocExpDist : - case ocExpDist_MS : ScExpDist(); break; - case ocBinomDist : - case ocBinomDist_MS : ScBinomDist(); break; - case ocPoissonDist : ScPoissonDist( true ); break; - case ocPoissonDist_MS : ScPoissonDist( false ); break; - case ocCombin : ScCombin(); break; - case ocCombinA : ScCombinA(); break; - case ocPermut : ScPermut(); break; - case ocPermutationA : ScPermutationA(); break; - case ocHypGeomDist : ScHypGeomDist( 4 ); break; - case ocHypGeomDist_MS : ScHypGeomDist( 5 ); break; - case ocLogNormDist : ScLogNormDist( 1 ); break; - case ocLogNormDist_MS : ScLogNormDist( 4 ); break; - case ocTDist : ScTDist(); break; - case ocTDist_MS : ScTDist_MS(); break; - case ocTDist_RT : ScTDist_T( 1 ); break; - case ocTDist_2T : ScTDist_T( 2 ); break; - case ocFDist : - case ocFDist_RT : ScFDist(); break; - case ocFDist_LT : ScFDist_LT(); break; - case ocChiDist : ScChiDist( true ); break; - case ocChiDist_MS : ScChiDist( false ); break; - case ocChiSqDist : ScChiSqDist(); break; - case ocChiSqDist_MS : ScChiSqDist_MS(); break; - case ocStandard : ScStandard(); break; - case ocAveDev : ScAveDev(); break; - case ocDevSq : ScDevSq(); break; - case ocKurt : ScKurt(); break; - case ocSkew : ScSkew(); break; - case ocSkewp : ScSkewp(); break; - case ocModalValue : ScModalValue(); break; - case ocModalValue_MS : ScModalValue_MS( true ); break; - case ocModalValue_Multi : ScModalValue_MS( false ); break; - case ocMedian : ScMedian(); break; - case ocGeoMean : ScGeoMean(); break; - case ocHarMean : ScHarMean(); break; - case ocWeibull : - case ocWeibull_MS : ScWeibull(); break; - case ocBinomInv : - case ocCritBinom : ScCritBinom(); break; - case ocNegBinomVert : ScNegBinomDist(); break; - case ocNegBinomDist_MS : ScNegBinomDist_MS(); break; - case ocNoName : ScNoName(); break; - case ocBad : ScBadName(); break; - case ocZTest : - case ocZTest_MS : ScZTest(); break; - case ocTTest : - case ocTTest_MS : ScTTest(); break; - case ocFTest : - case ocFTest_MS : ScFTest(); break; - case ocRank : - case ocRank_Eq : ScRank( false ); break; - case ocRank_Avg : ScRank( true ); break; - case ocPercentile : - case ocPercentile_Inc : ScPercentile( true ); break; - case ocPercentile_Exc : ScPercentile( false ); break; - case ocPercentrank : - case ocPercentrank_Inc : ScPercentrank( true ); break; - case ocPercentrank_Exc : ScPercentrank( false ); break; - case ocLarge : ScLarge(); break; - case ocSmall : ScSmall(); break; - case ocFrequency : ScFrequency(); break; - case ocQuartile : - case ocQuartile_Inc : ScQuartile( true ); break; - case ocQuartile_Exc : ScQuartile( false ); break; - case ocNormInv : - case ocNormInv_MS : ScNormInv(); break; - case ocSNormInv : - case ocSNormInv_MS : ScSNormInv(); break; - case ocConfidence : - case ocConfidence_N : ScConfidence(); break; - case ocConfidence_T : ScConfidenceT(); break; - case ocTrimMean : ScTrimMean(); break; - case ocProb : ScProbability(); break; - case ocCorrel : ScCorrel(); break; - case ocCovar : - case ocCovarianceP : ScCovarianceP(); break; - case ocCovarianceS : ScCovarianceS(); break; - case ocPearson : ScPearson(); break; - case ocRSQ : ScRSQ(); break; - case ocSTEYX : ScSTEYX(); break; - case ocSlope : ScSlope(); break; - case ocIntercept : ScIntercept(); break; - case ocTrend : ScTrend(); break; - case ocGrowth : ScGrowth(); break; - case ocLinest : ScLinest(); break; - case ocLogest : ScLogest(); break; - case ocForecast_LIN : - case ocForecast : ScForecast(); break; - case ocForecast_ETS_ADD : ScForecast_Ets( etsAdd ); break; - case ocForecast_ETS_SEA : ScForecast_Ets( etsSeason ); break; - case ocForecast_ETS_MUL : ScForecast_Ets( etsMult ); break; - case ocForecast_ETS_PIA : ScForecast_Ets( etsPIAdd ); break; - case ocForecast_ETS_PIM : ScForecast_Ets( etsPIMult ); break; - case ocForecast_ETS_STA : ScForecast_Ets( etsStatAdd ); break; - case ocForecast_ETS_STM : ScForecast_Ets( etsStatMult ); break; - case ocGammaLn : - case ocGammaLn_MS : ScLogGamma(); break; - case ocGamma : ScGamma(); break; - case ocGammaDist : ScGammaDist( true ); break; - case ocGammaDist_MS : ScGammaDist( false ); break; - case ocGammaInv : - case ocGammaInv_MS : ScGammaInv(); break; - case ocChiTest : - case ocChiTest_MS : ScChiTest(); break; - case ocChiInv : - case ocChiInv_MS : ScChiInv(); break; - case ocChiSqInv : - case ocChiSqInv_MS : ScChiSqInv(); break; - case ocTInv : - case ocTInv_2T : ScTInv( 2 ); break; - case ocTInv_MS : ScTInv( 4 ); break; - case ocFInv : - case ocFInv_RT : ScFInv(); break; - case ocFInv_LT : ScFInv_LT(); break; - case ocLogInv : - case ocLogInv_MS : ScLogNormInv(); break; - case ocBetaDist : ScBetaDist(); break; - case ocBetaDist_MS : ScBetaDist_MS(); break; - case ocBetaInv : - case ocBetaInv_MS : ScBetaInv(); break; - case ocFourier : ScFourier(); break; - case ocExternal : ScExternal(); break; - case ocTableOp : ScTableOp(); break; - case ocStop : break; - case ocErrorType : ScErrorType(); break; - case ocErrorType_ODF : ScErrorType_ODF(); break; - case ocCurrent : ScCurrent(); break; - case ocStyle : ScStyle(); break; - case ocDde : ScDde(); break; - case ocBase : ScBase(); break; - case ocDecimal : ScDecimal(); break; - case ocConvertOOo : ScConvertOOo(); break; - case ocEuroConvert : ScEuroConvert(); break; - case ocRoman : ScRoman(); break; - case ocArabic : ScArabic(); break; - case ocInfo : ScInfo(); break; - case ocHyperLink : ScHyperLink(); break; - case ocBahtText : ScBahtText(); break; - case ocGetPivotData : ScGetPivotData(); break; - case ocJis : ScJis(); break; - case ocAsc : ScAsc(); break; - case ocLenB : ScLenB(); break; - case ocRightB : ScRightB(); break; - case ocLeftB : ScLeftB(); break; - case ocMidB : ScMidB(); break; - case ocReplaceB : ScReplaceB(); break; - case ocFindB : ScFindB(); break; - case ocSearchB : ScSearchB(); break; - case ocUnicode : ScUnicode(); break; - case ocUnichar : ScUnichar(); break; - case ocBitAnd : ScBitAnd(); break; - case ocBitOr : ScBitOr(); break; - case ocBitXor : ScBitXor(); break; - case ocBitRshift : ScBitRshift(); break; - case ocBitLshift : ScBitLshift(); break; - case ocTTT : ScTTT(); break; - case ocDebugVar : ScDebugVar(); break; - case ocNone : nFuncFmtType = SvNumFormatType::UNDEFINED; break; - default : PushError( FormulaError::UnknownOpCode); break; - } + DispatchOpCode( eOp ); + if (eOp == ocNone) + nFuncFmtType = SvNumFormatType::UNDEFINED; if (FormulaCompiler::IsOpCodeVolatile(eOp)) meVolatileType = VOLATILE; @@ -4672,136 +4519,159 @@ StackVar ScInterpreter::Interpret() pCur = pStack[ sp-1 ]; if( pCur->GetOpCode() == ocPush ) { - // An svRefList can be resolved if it a) contains just one - // reference, or b) in array context contains an array of single - // cell references. - if (pCur->GetType() == svRefList) + if ( ! aCode.IsLambda() ) // leave everything alone inside a lambda { - PopRefListPushMatrixOrRef(); - pCur = pStack[ sp-1 ]; - } - switch( pCur->GetType() ) - { - case svEmptyCell: - ; // nothing - break; - case svError: - nGlobalError = pCur->GetError(); - break; - case svDouble : - { - // If typed, pop token to obtain type information and - // push a plain untyped double so the result token to - // be transferred to the formula cell result does not - // unnecessarily duplicate the information. - if (pCur->GetDoubleType() != 0) - { - double fVal = PopDouble(); - if (!bForcedResultType) - { - if (nCurFmtType != nFuncFmtType) - nRetIndexExpr = 0; // carry format index only for matching type - nRetTypeExpr = nFuncFmtType = nCurFmtType; - } - if (nRetTypeExpr == SvNumFormatType::DURATION) - { - // Round the duration in case a wall clock time - // display format is used instead of a duration - // format. To micro seconds which then catches - // the converted hh:mm:ss.9999997 cases. - if (fVal != 0.0) - { - fVal *= 86400.0; - fVal = rtl::math::round( fVal, 6); - fVal /= 86400.0; - } - } - PushTempToken( CreateFormulaDoubleToken( fVal)); - } - if ( nFuncFmtType == SvNumFormatType::UNDEFINED ) - { - nRetTypeExpr = SvNumFormatType::NUMBER; - nRetIndexExpr = 0; - } - } - break; - case svString : - nRetTypeExpr = SvNumFormatType::TEXT; - nRetIndexExpr = 0; - break; - case svSingleRef : + // An svRefList can be resolved if it a) contains just one + // reference, or b) in array context contains an array of single + // cell references. + if (pCur->GetType() == svRefList) { - ScAddress aAdr; - PopSingleRef( aAdr ); - if( nGlobalError == FormulaError::NONE) - PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true); + PopRefListPushMatrixOrRef(); + pCur = pStack[ sp-1 ]; } - break; - case svRefList : - PopError(); // maybe #REF! takes precedence over #VALUE! - PushError( FormulaError::NoValue); - break; - case svDoubleRef : + switch( pCur->GetType() ) { - if ( bMatrixFormula ) - { // create matrix for {=A1:A5} - PopDoubleRefPushMatrix(); - ScMatrixRef xMat = PopMatrix(); - QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr); - } - else + case svEmptyCell: + ; // nothing + break; + case svError: + nGlobalError = static_cast(pCur)->GetError(); + break; + case svDouble : + { + auto pDToken = static_cast(pCur); + // If typed, pop token to obtain type information and + // push a plain untyped double so the result token to + // be transferred to the formula cell result does not + // unnecessarily duplicate the information. + if (pDToken->GetDoubleType() != 0) + { + double fVal = PopDouble(); + if (!bForcedResultType) + { + if (nCurFmtType != nFuncFmtType) + nRetIndexExpr = 0; // carry format index only for matching type + nRetTypeExpr = nFuncFmtType = nCurFmtType; + } + if (nRetTypeExpr == SvNumFormatType::DURATION) + { + // Round the duration in case a wall clock time + // display format is used instead of a duration + // format. To micro seconds which then catches + // the converted hh:mm:ss.9999997 cases. + if (fVal != 0.0) + { + fVal *= 86400.0; + fVal = rtl::math::round( fVal, 6); + fVal /= 86400.0; + } + } + PushTempToken( CreateFormulaDoubleToken( fVal)); + } + if ( nFuncFmtType == SvNumFormatType::UNDEFINED ) + { + nRetTypeExpr = SvNumFormatType::NUMBER; + nRetIndexExpr = 0; + } + } + break; + case svString : + nRetTypeExpr = SvNumFormatType::TEXT; + nRetIndexExpr = 0; + break; + case svSingleRef : { - ScRange aRange; - PopDoubleRef( aRange ); ScAddress aAdr; - if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr)) + PopSingleRef( aAdr ); + if( nGlobalError == FormulaError::NONE) PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true); } - } - break; - case svExternalDoubleRef: - { - ScMatrixRef xMat; - PopExternalDoubleRef(xMat); - QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr); - } - break; - case svMatrix : - { - sc::RangeMatrix aMat = PopRangeMatrix(); - if (aMat.isRangeValid()) + break; + case svRefList : + PopError(); // maybe #REF! takes precedence over #VALUE! + PushError( FormulaError::NoValue); + break; + case svDoubleRef : { - // This matrix represents a range reference. Apply implicit intersection. - double fVal = applyImplicitIntersection(aMat, aPos); - if (std::isnan(fVal)) - PushNoValue(); + if ( bMatrixFormula ) + { // create matrix for {=A1:A5} + PopDoubleRefPushMatrix(); + ScMatrixRef xMat = PopMatrix(); + QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr); + } else - PushInt(fVal); + { + ScRange aRange; + PopDoubleRef( aRange ); + ScAddress aAdr; + if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr)) + PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true); + } } - else - // This is a normal matrix. - QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr); - } - break; - case svExternalSingleRef: - { - FormulaTokenRef xToken; - ScExternalRefCache::CellFormat aFmt; - PopExternalSingleRef(xToken, &aFmt); - if (nGlobalError != FormulaError::NONE) - break; - - PushTokenRef(xToken); - - if (aFmt.mbIsSet) + break; + case svExternalDoubleRef: { - nFuncFmtType = aFmt.mnType; - nFuncFmtIndex = aFmt.mnIndex; + ScMatrixRef xMat; + PopExternalDoubleRef(xMat); + QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr); } + break; + case svMatrix : + { + sc::RangeMatrix aMat = PopRangeMatrix(); + // A matrix that carries a source range reduces + // by implicit intersection when the cell + // expects a single value. A matrix-formula + // context (CSE array master) wants the full + // matrix and routes through QueryMatrixType so + // the master can hold and spill the range. + if (aMat.isRangeValid() && !bMatrixFormula) + { + // This matrix represents a range reference. Apply implicit intersection. + ScAddress aSrc; + double fVal = applyImplicitIntersection(aMat, aPos, aSrc); + if (std::isnan(fVal)) + PushNoValue(); + else + { + PushDouble(fVal); + // Keep the number format of the spill-range + // cell the value came from, so a spilled date + // or currency value still shows its formatting. + mrDoc.GetNumberFormatInfo(mrContext, nRetTypeExpr, nRetIndexExpr, aSrc); + } + } + else + // This is a normal matrix. + QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr); + } + break; + case svExternalSingleRef: + { + FormulaTokenRef xToken; + ScExternalRefCache::CellFormat aFmt; + PopExternalSingleRef(xToken, &aFmt); + if (nGlobalError != FormulaError::NONE) + break; + + PushTokenRef(xToken); + + if (aFmt.mbIsSet) + { + nFuncFmtType = aFmt.mnType; + nFuncFmtIndex = aFmt.mnIndex; + } + } + break; + case svCallable: + { + nRetTypeExpr = SvNumFormatType::UNDEFINED; + nRetIndexExpr = 0; + } + break; + default : + SetError( FormulaError::UnknownStackVariable); } - break; - default : - SetError( FormulaError::UnknownStackVariable); } } else @@ -4842,7 +4712,7 @@ StackVar ScInterpreter::Interpret() if (eType == svMatrix) // Results are immutable in case they would be reused as input for new // interpreters. - xResult->GetMatrix()->SetImmutable(); + static_cast(xResult.get())->GetMatrix()->SetImmutable(); return eType; } @@ -4853,7 +4723,7 @@ void ScInterpreter::AssertFormulaMatrix() const svl::SharedString & ScInterpreter::GetStringResult() const { - return xResult->GetString(); + return static_cast(xResult.get())->GetString(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx index 19a81324b1f0..a28b445aef1e 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -47,6 +47,29 @@ using namespace formula; namespace { +// True when the stack token is a double carrying a boolean value, tagged +// LOGICAL. A missing argument or an empty cell is reported as a double by the +// stack but is not a double token, so the token's own type is checked before +// the cast. +bool isLogicalDoubleToken(const FormulaToken* pToken) +{ + return pToken->GetType() == svDouble + && static_cast(pToken)->GetDoubleType() + == static_cast(SvNumFormatType::LOGICAL); +} + +// Format a value through the LOGICAL standard format so the string +// is "TRUE" for non-zero or "FALSE" for zero. +OUString formatLogical(ScInterpreterContext& rContext, double fVal) +{ + sal_uInt32 nKey = rContext.NFGetStandardFormat( + SvNumFormatType::LOGICAL, ScGlobal::eLnge); + OUString aStr; + const Color* pColor = nullptr; + rContext.NFGetOutputString(fVal, nKey, aStr, &pColor); + return aStr; +} + double MatrixAdd(const double& lhs, const double& rhs) { return ::rtl::math::approxAdd( lhs,rhs); @@ -311,8 +334,12 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken if (nTab1 == nTab2 && pToken) { - const ScComplexRefData& rCRef = *pToken->GetDoubleRef(); - if (rCRef.IsTrimToData()) + const ScComplexRefData* pCRef; + if (pToken->GetType() == svDoubleRef) + pCRef = &static_cast(pToken)->GetDoubleRef(); + else + pCRef = &static_cast(pToken)->GetDoubleRef(); + if (pCRef->IsTrimToData()) { // Clamp the size of the matrix area to rows which actually contain data. // For e.g. SUM(IF over an entire column, this can make a big difference, @@ -344,7 +371,7 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken * TODO: a matrix already stored in pTokenMatrixMap should be * read-only and have a copy-on-write mechanism. Previously all tokens * were modifiable so we're already better than before ... */ - return const_cast((*aIter).second.get())->GetMatrix(); + return static_cast(const_cast((*aIter).second.get()))->GetMatrix(); } ScMatrixRef pMat = GetNewMat( nMatCols, nMatRows, true); @@ -550,13 +577,13 @@ ScMatrixRef ScInterpreter::GetMatrix() switch (pToken->GetType()) { case svError: - pMat->PutError( pToken->GetError(), 0, 0); + pMat->PutError( static_cast(pToken.get())->GetError(), 0, 0); break; case svDouble: - pMat->PutDouble( pToken->GetDouble(), 0, 0); + pMat->PutDouble( static_cast(pToken.get())->GetDouble(), 0, 0); break; case svString: - pMat->PutString( pToken->GetString(), 0, 0); + pMat->PutString( static_cast(pToken.get())->GetString(), 0, 0); break; default: ; // nothing, empty element matrix @@ -858,7 +885,7 @@ static int lcl_LUP_decompose( ScMatrix* mA, const SCSIZE n, } /* Solve a LUP decomposed equation Ax=b. LU is a combined matrix of L and U - * triangulars and P the permutation vector as obtained from + * triangular matrices and P the permutation vector as obtained from * lcl_LUP_decompose(). B is the right-hand side input vector, X is used to * return the solution vector. */ @@ -1194,17 +1221,16 @@ void ScInterpreter::ScMatTrans() PushIllegalParameter(); } -/** Minimum extent of one result matrix dimension. - For a row or column vector to be replicated the larger matrix dimension is - returned, else the smaller dimension. - */ -static SCSIZE lcl_GetMinExtent( SCSIZE n1, SCSIZE n2 ) +// Pair non-broadcast operands to the larger extent so the longer +// side keeps its data. A single-cell side broadcasts to the other +// side's length. +static SCSIZE lcl_GetExtent( SCSIZE n1, SCSIZE n2 ) { if (n1 == 1) return n2; else if (n2 == 1) return n1; - else if (n1 < n2) + else if (n1 > n2) return n1; else return n2; @@ -1213,34 +1239,587 @@ static SCSIZE lcl_GetMinExtent( SCSIZE n1, SCSIZE n2 ) static ScMatrixRef lcl_MatrixCalculation( const ScMatrix& rMat1, const ScMatrix& rMat2, ScInterpreter* pInterpreter, const ScMatrix::CalculateOpFunction& Op) { - SCSIZE nC1, nC2, nMinC; - SCSIZE nR1, nR2, nMinR; + SCSIZE nC1, nC2, nExtentC; + SCSIZE nR1, nR2, nExtentR; rMat1.GetDimensions(nC1, nR1); rMat2.GetDimensions(nC2, nR2); - nMinC = lcl_GetMinExtent( nC1, nC2); - nMinR = lcl_GetMinExtent( nR1, nR2); - ScMatrixRef xResMat = pInterpreter->GetNewMat(nMinC, nMinR, /*bEmpty*/true); + nExtentC = lcl_GetExtent( nC1, nC2); + nExtentR = lcl_GetExtent( nR1, nR2); + ScMatrixRef xResMat = pInterpreter->GetNewMat(nExtentC, nExtentR, /*bEmpty*/true); if (xResMat) - xResMat->ExecuteBinaryOp(nMinC, nMinR, rMat1, rMat2, pInterpreter, Op); + xResMat->ExecuteBinaryOp(nExtentC, nExtentR, rMat1, rMat2, pInterpreter, Op); return xResMat; } ScMatrixRef ScInterpreter::MatConcat(const ScMatrixRef& pMat1, const ScMatrixRef& pMat2) { - SCSIZE nC1, nC2, nMinC; - SCSIZE nR1, nR2, nMinR; + SCSIZE nC1, nC2, nExtentC; + SCSIZE nR1, nR2, nExtentR; pMat1->GetDimensions(nC1, nR1); pMat2->GetDimensions(nC2, nR2); - nMinC = lcl_GetMinExtent( nC1, nC2); - nMinR = lcl_GetMinExtent( nR1, nR2); - ScMatrixRef xResMat = GetNewMat(nMinC, nMinR, /*bEmpty*/true); + nExtentC = lcl_GetExtent( nC1, nC2); + nExtentR = lcl_GetExtent( nR1, nR2); + ScMatrixRef xResMat = GetNewMat(nExtentC, nExtentR, /*bEmpty*/true); if (xResMat) { - xResMat->MatConcat(nMinC, nMinR, pMat1, pMat2, mrContext, mrDoc.GetSharedStringPool()); + xResMat->MatConcat(nExtentC, nExtentR, pMat1, pMat2, mrContext, mrDoc.GetSharedStringPool()); } return xResMat; } +void ScInterpreter::PutCellIntoMatrix(const ScAddress& rAdr, const ScMatrixRef& xMatrix, SCSIZE nCol, SCSIZE nRow) +{ + // A formula cell contributes its computed result; any other cell + // contributes its own value. An empty cell becomes an empty entry. + if (ScFormulaCell* pCell = mrDoc.GetFormulaCell(rAdr)) + { + PutMatrixValue(pCell->CloneResultToken(), xMatrix, nCol, nRow); + return; + } + ScRefCellValue aCell(mrDoc, rAdr); + if (aCell.isEmpty()) + xMatrix->PutEmpty(nCol, nRow); + else if (aCell.hasString()) + xMatrix->PutString(aCell.getSharedString(mrDoc, mrStrPool), nCol, nRow); + else + xMatrix->PutDouble(aCell.getValue(), nCol, nRow); +} + +void ScInterpreter::PutMatrixValue(FormulaConstTokenRef pToken, ScMatrixRef xMatrix, SCSIZE nCol, SCSIZE nRow) +{ + switch (pToken->GetType()) + { + case svSingleRef: + { + auto pTypedToken = static_cast(pToken.get()); + const ScSingleRefData& rRefData = pTypedToken->GetSingleRef(); + if (rRefData.IsDeleted()) + { + xMatrix->PutError(FormulaError::NoRef, nCol, nRow); + break; + } + + ScAddress aAdr = rRefData.toAbs(mrDoc, aPos); + if (!mrDoc.m_TableOpList.empty()) + ReplaceCell(aAdr); + + PutCellIntoMatrix(aAdr, xMatrix, nCol, nRow); + break; + } + case svDoubleRef: + { + auto pTypedToken = static_cast(pToken.get()); + const ScComplexRefData& rRefData = pTypedToken->GetDoubleRef(); + if (rRefData.IsDeleted()) + { + xMatrix->PutError(FormulaError::NoRef, nCol, nRow); + break; + } + + ScRange aRange = rRefData.toAbs(mrDoc, aPos); + if (aRange.aStart != aRange.aEnd) + { + xMatrix->PutError(FormulaError::IllegalArgument, nCol, nRow); + break; + } + + if (!mrDoc.m_TableOpList.empty()) + ReplaceCell(aRange.aStart); + + PutCellIntoMatrix(aRange.aStart, xMatrix, nCol, nRow); + break; + } + case svRefList: + { + auto pTypedToken = static_cast(pToken.get()); + const ScRefList* pRefList = pTypedToken->GetRefList(); + if (pRefList->size() > 1) + { + xMatrix->PutError(FormulaError::IllegalArgument, nCol, nRow); + break; + } + const ScComplexRefData& rRefData = (*pRefList)[0]; + if (rRefData.IsDeleted()) + { + xMatrix->PutError(FormulaError::NoRef, nCol, nRow); + break; + } + + ScRange aRange = rRefData.toAbs(mrDoc, aPos); + if (aRange.aStart != aRange.aEnd) + { + xMatrix->PutError(FormulaError::IllegalArgument, nCol, nRow); + break; + } + + if (!mrDoc.m_TableOpList.empty()) + ReplaceCell(aRange.aStart); + + PutCellIntoMatrix(aRange.aStart, xMatrix, nCol, nRow); + break; + } + case svDouble: + { + auto pTypedToken = static_cast(pToken.get()); + xMatrix->PutDouble(pTypedToken->GetDouble(), nCol, nRow); + break; + } + case svString: + { + auto pTypedToken = static_cast(pToken.get()); + xMatrix->PutString(pTypedToken->GetString(), nCol, nRow); + break; + } + case svEmptyCell: + case svMissing: + { + xMatrix->PutEmpty(nCol, nRow); + break; + } + case svError: + { + auto pTypedToken = static_cast(pToken.get()); + xMatrix->PutError(pTypedToken->GetError(), nCol, nRow); + break; + } + case svMatrix: + case svMatrixCell: + { + // Reduce a one by one matrix result to its single value. + const ScMatrix* xTokMatrix; + if (pToken->GetType() == svMatrix) + xTokMatrix = static_cast(pToken.get())->GetMatrix(); + else + xTokMatrix = static_cast(pToken.get())->GetMatrix(); + SCSIZE nCols = 0, nRows = 0; + if (xTokMatrix) + xTokMatrix->GetDimensions(nCols, nRows); + if (xTokMatrix && nCols == 1 && nRows == 1) + { + if (xTokMatrix->IsEmpty(0, 0)) + xMatrix->PutEmpty(nCol, nRow); + else if (xTokMatrix->IsValue(0, 0)) + { + FormulaError nError = xTokMatrix->GetError(0, 0); + if (nError == FormulaError::NONE) + xMatrix->PutDouble(xTokMatrix->GetDouble(0, 0), nCol, nRow); + else + xMatrix->PutError(nError, nCol, nRow); + } + else if (xTokMatrix->IsStringOrEmpty(0, 0)) + xMatrix->PutString(xTokMatrix->GetString(0, 0), nCol, nRow); + else // TODO: callable + xMatrix->PutError(FormulaError::IllegalArgument, nCol, nRow); + } + else + xMatrix->PutError(FormulaError::IllegalArgument, nCol, nRow); + break; + } + case svCallable: // TODO + default: + { + xMatrix->PutError(FormulaError::IllegalArgument, nCol, nRow); + break; + } + } +} + +void ScInterpreter::ScByCol() +{ + if ( ! MustHaveParamCount( GetByte(), 2 ) ) + return; + + formula::FormulaCallableRef pCallable = GetCallable(); + ScMatrixRef xMatrix = GetMatrix(); + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } + else if (!pCallable || !xMatrix) + { + PushIllegalArgument(); + return; + } + + SCSIZE nC, nR; + xMatrix->GetDimensions(nC, nR); + + ScMatrixRef xArgMat = GetNewMat(1, nR, /*bEmpty*/true); + ScMatrixRef xResMat = GetNewMat(nC, 1, /*bEmpty*/true); + if (!xArgMat || !xResMat) + { + PushError(FormulaError::MatrixSize); + return; + } + + std::vector aArgs(1); + aArgs[0] = new ScMatrixToken(xArgMat); + + // TODO: These loops are definitely candidates for multithreading + for (SCSIZE nCol = 0; nCol < nC; ++nCol) + { + for (SCSIZE nRow = 0; nRow < nR; ++nRow) + { + if (xMatrix->IsEmpty(nCol, nRow)) + xArgMat->PutEmpty(0, nRow); + else if (xMatrix->IsValue(nCol, nRow)) + { + FormulaError nError = xMatrix->GetError(nCol, nRow); + if (nError == FormulaError::NONE) + xArgMat->PutDouble(xMatrix->GetDouble(nCol, nRow), 0, nRow); + else + xArgMat->PutError(nError, 0, nRow); + } + else if (xMatrix->IsStringOrEmpty(nCol, nRow)) + xArgMat->PutString(xMatrix->GetString(nCol, nRow), 0, nRow); + else // TODO: callable + xArgMat->PutError(FormulaError::IllegalArgument, 0, nRow); + } + ScCall(pCallable, aArgs); + PutMatrixValue(PopToken(), xResMat, nCol, 0); + // The result of this column is stored, so clear any error it produced + // and let the next column compute from a clean state. + nGlobalError = FormulaError::NONE; + } + + PushMatrix(xResMat); +} + +void ScInterpreter::ScByRow() +{ + if ( ! MustHaveParamCount( GetByte(), 2 ) ) + return; + + formula::FormulaCallableRef pCallable = GetCallable(); + ScMatrixRef xMatrix = GetMatrix(); + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } + else if (!pCallable || !xMatrix) + { + PushIllegalArgument(); + return; + } + + SCSIZE nC, nR; + xMatrix->GetDimensions(nC, nR); + + ScMatrixRef xArgMat = GetNewMat(nC, 1, /*bEmpty*/true); + ScMatrixRef xResMat = GetNewMat(1, nR, /*bEmpty*/true); + if (!xArgMat || !xResMat) + { + PushError(FormulaError::MatrixSize); + return; + } + + std::vector aArgs(1); + aArgs[0] = new ScMatrixToken(xArgMat); + + // TODO: These loops are definitely candidates for multithreading + for (SCSIZE nRow = 0; nRow < nR; ++nRow) + { + for (SCSIZE nCol = 0; nCol < nC; ++nCol) + { + if (xMatrix->IsEmpty(nCol, nRow)) + xArgMat->PutEmpty(nCol, 0); + else if (xMatrix->IsValue(nCol, nRow)) + { + FormulaError nError = xMatrix->GetError(nCol, nRow); + if (nError == FormulaError::NONE) + xArgMat->PutDouble(xMatrix->GetDouble(nCol, nRow), nCol, 0); + else + xArgMat->PutError(nError, nCol, 0); + } + else if (xMatrix->IsStringOrEmpty(nCol, nRow)) + xArgMat->PutString(xMatrix->GetString(nCol, nRow), nCol, 0); + else // TODO: callable + xArgMat->PutError(FormulaError::IllegalArgument, nCol, 0); + } + ScCall(pCallable, aArgs); + PutMatrixValue(PopToken(), xResMat, 0, nRow); + // The result of this row is stored, so clear any error it produced and + // let the next row compute from a clean state. + nGlobalError = FormulaError::NONE; + } + + PushMatrix(xResMat); +} + +void ScInterpreter::ScMakeArray() +{ + if ( ! MustHaveParamCount( GetByte(), 3 ) ) + return; + + formula::FormulaCallableRef pCallable = GetCallable(); + SCSIZE nCols = static_cast(GetInt32()); + SCSIZE nRows = static_cast(GetInt32()); + + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } + else if (!pCallable) + { + PushIllegalArgument(); + return; + } + else if (nCols <= 0 || nRows <= 0) + { + // A non-positive number of rows or columns is a value error. + PushNoValue(); + return; + } + + if (nCols == 1 && nRows == 1) + { + formula::FormulaConstTokenRef pRow = new formula::FormulaDoubleToken(1); + formula::FormulaConstTokenRef pCol = new formula::FormulaDoubleToken(1); + std::vector aArguments(2); + aArguments[0] = pRow; + aArguments[1] = pCol; + ScCall(pCallable, aArguments); + return; + } + + ScMatrixRef xResMat = GetNewMat(nCols, nRows, /*bEmpty*/true); + if (!xResMat) + { + PushError(FormulaError::MatrixSize); + return; + } + + // TODO: These loops are definitely candidates for multithreading + for (SCSIZE nRow = 0; nRow < nRows; nRow++) + { + for (SCSIZE nCol = 0; nCol < nCols; nCol++) + { + formula::FormulaConstTokenRef pRowToken = new formula::FormulaDoubleToken(nRow + 1); + formula::FormulaConstTokenRef pColToken = new formula::FormulaDoubleToken(nCol + 1); + std::vector aArguments(2); + aArguments[0] = pRowToken; + aArguments[1] = pColToken; + ScCall(pCallable, aArguments); + PutMatrixValue(PopToken(), xResMat, nCol, nRow); + // The result of this cell is stored, so clear any error it produced + // and let the next cell compute from a clean state. + nGlobalError = FormulaError::NONE; + } + } + + PushMatrix(xResMat); +} + +void ScInterpreter::ScMap() +{ + sal_uInt8 nParamCount = GetByte(); + if ( ! MustHaveParamCountMin(nParamCount, 2) ) + return; + + sal_uInt8 nArgCount = nParamCount - 1; + formula::FormulaCallableRef pCallable = GetCallable(); + std::vector aMatrices(nArgCount); + SCSIZE nC = 0, nR = 0; + for (sal_Int32 i = static_cast(nArgCount) - 1; i >= 0; --i) + { + ScMatrixRef xMat = GetMatrix(); + if (xMat) + { + SCSIZE nCols, nRows; + xMat->GetDimensions(nCols, nRows); + // The result spans the largest argument array. A shorter array + // leaves its missing positions not available. + if (nCols > nC) + nC = nCols; + if (nRows > nR) + nR = nRows; + aMatrices[i] = xMat; + } + else + SetError(FormulaError::IllegalArgument); + } + if (nGlobalError != FormulaError::NONE) + { + PushError(nGlobalError); + return; + } + else if (!pCallable) + { + PushIllegalArgument(); + return; + } + + std::vector aArgs(nArgCount); + ScMatrixRef xResMat = GetNewMat(nC, nR, /*bEmpty*/true); + if (!xResMat) + { + PushError(FormulaError::MatrixSize); + return; + } + + for (SCSIZE nCol = 0; nCol < nC; ++nCol) + { + for (SCSIZE nRow = 0; nRow < nR; ++nRow) + { + bool bElementMissing = false; + for (sal_uInt8 nMat = 0; nMat < nArgCount; ++nMat) + { + SCSIZE nMatCols, nMatRows; + aMatrices[nMat]->GetDimensions(nMatCols, nMatRows); + if (nCol >= nMatCols || nRow >= nMatRows) + { + bElementMissing = true; + break; + } + if (aMatrices[nMat]->IsEmpty(nCol, nRow)) + aArgs[nMat] = new formula::FormulaMissingToken(); + else if (aMatrices[nMat]->IsValue(nCol, nRow)) + { + FormulaError nError = aMatrices[nMat]->GetError(nCol, nRow); + if (nError == FormulaError::NONE) + aArgs[nMat] = new formula::FormulaDoubleToken(aMatrices[nMat]->GetDouble(nCol, nRow)); + else + aArgs[nMat] = new formula::FormulaErrorToken(nError); + } + else if (aMatrices[nMat]->IsStringOrEmpty(nCol, nRow)) + aArgs[nMat] = new formula::FormulaStringToken(aMatrices[nMat]->GetString(nCol, nRow)); + else // TODO: callable + aArgs[nMat] = new formula::FormulaErrorToken(FormulaError::IllegalParameter); + } + // One of the arrays is shorter and has no element here, so there is + // nothing to map at this position. + if (bElementMissing) + { + xResMat->PutError(FormulaError::NotAvailable, nCol, nRow); + continue; + } + ScCall(pCallable, aArgs); + PutMatrixValue(PopToken(), xResMat, nCol, nRow); + // The result of this cell is stored, so clear any error it produced + // and let the next cell compute from a clean state. + nGlobalError = FormulaError::NONE; + } + } + + PushMatrix(xResMat); +} + +void ScInterpreter::ScReduce() +{ + sal_uInt8 nParamCount = GetByte(); + if ( ! MustHaveParamCount(nParamCount, 2, 3) ) + return; + + formula::FormulaCallableRef pCallable = GetCallable(); + ScMatrixRef xMatrix = GetMatrix(); + formula::FormulaConstTokenRef xInitValue = nullptr; + if (nParamCount == 3) + { + xInitValue = PopToken(); + if (xInitValue->GetType() == svMissing) + xInitValue = new formula::FormulaDoubleToken(0.0); + } + if (!pCallable || !xMatrix) + { + PushIllegalArgument(); + return; + } + + SCSIZE nC, nR; + xMatrix->GetDimensions(nC, nR); + std::vector aArgs(2); + aArgs[0] = xInitValue; + + for (SCSIZE nRow = 0; nRow < nR; ++nRow) + { + for (SCSIZE nCol = 0; nCol < nC; ++nCol) + { + if (xMatrix->IsEmpty(nCol, nRow)) + aArgs[1] = new formula::FormulaMissingToken(); + else if (xMatrix->IsValue(nCol, nRow)) + { + FormulaError nError = xMatrix->GetError(nCol, nRow); + if (nError == FormulaError::NONE) + aArgs[1] = new formula::FormulaDoubleToken(xMatrix->GetDouble(nCol, nRow)); + else + aArgs[1] = new formula::FormulaErrorToken(nError); + } + else if (xMatrix->IsStringOrEmpty(nCol, nRow)) + aArgs[1] = new formula::FormulaStringToken(xMatrix->GetString(nCol, nRow)); + else // TODO: callable + aArgs[1] = new formula::FormulaErrorToken(FormulaError::IllegalParameter); + + ScCall(pCallable, aArgs); + aArgs[0] = PopToken(); + } + } + + PushTokenRef(aArgs[0]); +} + +void ScInterpreter::ScScan() +{ + sal_uInt8 nParamCount = GetByte(); + if ( ! MustHaveParamCount(nParamCount, 2, 3) ) + return; + + formula::FormulaCallableRef pCallable = GetCallable(); + ScMatrixRef xMatrix = GetMatrix(); + formula::FormulaConstTokenRef xInitValue = nullptr; + if (nParamCount == 3) + { + xInitValue = PopToken(); + if (xInitValue->GetType() == svMissing) + xInitValue = new formula::FormulaDoubleToken(0.0); + } + if (!pCallable || !xMatrix) + { + PushIllegalArgument(); + return; + } + + SCSIZE nC, nR; + xMatrix->GetDimensions(nC, nR); + ScMatrixRef xResMat = GetNewMat(nC, nR, /*bEmpty*/true); + if (!xResMat) + { + PushError(FormulaError::MatrixSize); + return; + } + std::vector aArgs(2); + aArgs[0] = xInitValue; + + for (SCSIZE nRow = 0; nRow < nR; ++nRow) + { + for (SCSIZE nCol = 0; nCol < nC; ++nCol) + { + if (xMatrix->IsEmpty(nCol, nRow)) + aArgs[1] = new formula::FormulaMissingToken(); + else if (xMatrix->IsValue(nCol, nRow)) + { + FormulaError nError = xMatrix->GetError(nCol, nRow); + if (nError == FormulaError::NONE) + aArgs[1] = new formula::FormulaDoubleToken(xMatrix->GetDouble(nCol, nRow)); + else + aArgs[1] = new formula::FormulaErrorToken(nError); + } + else if (xMatrix->IsStringOrEmpty(nCol, nRow)) + aArgs[1] = new formula::FormulaStringToken(xMatrix->GetString(nCol, nRow)); + else // TODO: callable + aArgs[1] = new formula::FormulaErrorToken(FormulaError::IllegalParameter); + + ScCall(pCallable, aArgs); + aArgs[0] = PopToken(); + PutMatrixValue(aArgs[0], xResMat, nCol, nRow); + } + } + + PushMatrix(xResMat); +} + // for DATE, TIME, DATETIME, DURATION static void lcl_GetDiffDateTimeFmtType( SvNumFormatType& nFuncFmt, SvNumFormatType nFmt1, SvNumFormatType nFmt2 ) { @@ -1422,6 +2001,13 @@ void ScInterpreter::CalculateAddSub(bool _bSub) } } +OUString ScInterpreter::PopOperandStringForConcat() +{ + if (GetStackType() == svDouble && isLogicalDoubleToken(pStack[sp - 1])) + return formatLogical(mrContext, PopDouble()); + return GetString().getString(); +} + void ScInterpreter::ScAmpersand() { ScMatrixRef pMat1 = nullptr; @@ -1430,11 +2016,11 @@ void ScInterpreter::ScAmpersand() if ( GetStackType() == svMatrix ) pMat2 = GetMatrix(); else - sStr2 = GetString().getString(); + sStr2 = PopOperandStringForConcat(); if ( GetStackType() == svMatrix ) pMat1 = GetMatrix(); else - sStr1 = GetString().getString(); + sStr1 = PopOperandStringForConcat(); if (pMat1 && pMat2) { ScMatrixRef pResMat = MatConcat(pMat1, pMat2); @@ -2030,9 +2616,9 @@ double lcl_GetSign(double fValue) * For each NxK matrix A exists a decomposition A=Q*R with an orthogonal * NxN matrix Q and a NxK matrix R. * Q=H1*H2*...*Hk with Householder matrices H. Such a householder matrix can - * be build from a vector u by H=I-(2/u'u)*(u u'). This vectors u are returned + * be built from a vector u by H=I-(2/u'u)*(u u'). These vectors u are returned * in the columns of matrix A, overwriting the old content. - * The matrix R has a quadric upper part KxK with values in the upper right + * The matrix R has a quadratic upper part KxK with values in the upper right * triangle and zeros in all other elements. Here the diagonal elements of R * are stored in the vector R and the other upper right elements in the upper * right of the matrix A. @@ -2411,13 +2997,13 @@ void ScInterpreter::CalculateRGPRKP(bool _bRKP) return; bool bConstant, bStats; - // optional forth parameter + // optional fourth parameter if (nParamCount == 4) bStats = GetBool(); else bStats = false; - // The third parameter may not be missing in ODF, if the forth parameter + // The third parameter may not be missing in ODF, if the fourth parameter // is present. But Excel allows it with default true, we too. if (nParamCount >= 3) { @@ -2934,14 +3520,14 @@ void ScInterpreter::CalculateTrendGrowth(bool _bGrowth) if (!MustHaveParamCount( nParamCount, 1, 4 )) return; - // optional forth parameter + // optional fourth parameter bool bConstant; if (nParamCount == 4) bConstant = GetBool(); else bConstant = true; - // The third parameter may be missing in ODF, although the forth parameter + // The third parameter may be missing in ODF, although the fourth parameter // is present. Default values depend on data not yet read. ScMatrixRef pMatNewX; if (nParamCount >= 3) diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx index 6d9889841a97..dd7fb475f872 100644 --- a/sc/source/core/tool/interpr6.cxx +++ b/sc/source/core/tool/interpr6.cxx @@ -297,6 +297,49 @@ public: size_t getCount() const { return mnCount; } }; +class NonEmptyCellCounter +{ + size_t mnCount; +public: + NonEmptyCellCounter() : mnCount(0) {} + + void operator() (const sc::CellStoreType::value_type& rNode, size_t /*nOffset*/, size_t nDataSize) + { + if (rNode.type != sc::element_type_empty) + mnCount += nDataSize; + } + + size_t getCount() const { return mnCount; } +}; + +class FuncCountA : public sc::ColumnSpanSet::ColumnAction +{ + sc::ColumnBlockConstPosition maPos; + ScColumn* mpCol; + size_t mnCount; + +public: + FuncCountA() : mpCol(nullptr), mnCount(0) {} + + virtual void startColumn(ScColumn* pCol) override + { + mpCol = pCol; + mpCol->InitBlockPosition(maPos); + } + + virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal) override + { + if (!bVal) + return; + + NonEmptyCellCounter aFunc; + maPos.miCellPos = sc::ParseBlock(maPos.miCellPos, mpCol->GetCellStore(), aFunc, nRow1, nRow2); + mnCount += aFunc.getCount(); + }; + + size_t getCount() const { return mnCount; } +}; + class FuncCount : public sc::ColumnSpanSet::ColumnAction { const ScInterpreterContext& mrContext; @@ -570,7 +613,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero ) else if (eType == svDouble) { nCount++; - fVal = pToken->GetDouble(); + fVal = static_cast(pToken.get())->GetDouble(); if (aFmt.mbIsSet) { nFuncFmtType = aFmt.mnType; @@ -732,7 +775,17 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero ) if ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) break; } - if( eFunc == ifCOUNT2 ) + if( eFunc == ifCOUNT2 && mnSubTotalFlags == SubtotalFlags::NONE ) + { + sc::RangeColumnSpanSet aSet( aRange ); + FuncCountA aAction; + aSet.executeColumnAction( mrDoc, aAction ); + nCount += aAction.getCount(); + + if ( nGlobalError != FormulaError::NONE ) + nGlobalError = FormulaError::NONE; + } + else if( eFunc == ifCOUNT2 ) { ScCellIterator aIter( mrDoc, aRange, mnSubTotalFlags ); for (bool bHas = aIter.first(); bHas; bHas = aIter.next()) diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx index a2d34f327467..ce05b026384c 100644 --- a/sc/source/core/tool/interpr7.cxx +++ b/sc/source/core/tool/interpr7.cxx @@ -73,7 +73,7 @@ void ScInterpreter::ScFilterXML() } else if (GetStackType() == formula::svMatrix) { - const ScMatrix* pPathMatrix = pStack[sp-1]->GetMatrix(); + const ScMatrix* pPathMatrix = static_cast(pStack[sp-1])->GetMatrix(); if (!pPathMatrix) { PushIllegalParameter(); diff --git a/sc/source/core/tool/math.cxx b/sc/source/core/tool/math.cxx index e61d39386e98..e9add5d4a0e6 100644 --- a/sc/source/core/tool/math.cxx +++ b/sc/source/core/tool/math.cxx @@ -52,7 +52,7 @@ double power(const double& fVal1, const double& fVal2) { fPow = err_pow(fVal1, fVal2); } - // The pow() call must had been the most recent call to check errno or exception. + // The pow() call must have been the most recent call to check errno or exception. if ((((math_errhandling & MATH_ERRNO) != 0) && (errno == EDOM || errno == ERANGE)) // emscripten is currently broken by https://github.com/emscripten-core/emscripten/pull/11087 // While the removal is correct for C99, it's not for C++11 (see http://www.cplusplus.com/reference/cfenv/FE_INEXACT/) diff --git a/sc/source/core/tool/orcusxml.cxx b/sc/source/core/tool/orcusxml.cxx index b10f92f6e48b..6b693adc6c70 100644 --- a/sc/source/core/tool/orcusxml.cxx +++ b/sc/source/core/tool/orcusxml.cxx @@ -11,7 +11,7 @@ #include #include -#include +#include ScOrcusXMLTreeParam::EntryData::EntryData(EntryType eType) : mnNamespaceID(0) diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx index f56ce47e0439..03842d9c6843 100644 --- a/sc/source/core/tool/parclass.cxx +++ b/sc/source/core/tool/parclass.cxx @@ -59,7 +59,8 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocChoose, {{ Array, Reference }, 1, Value }}, { ocChooseCols, {{ ReferenceOrRefArray, ReferenceOrRefArray }, 1, ForceArrayReturn }}, { ocChooseRows, {{ ReferenceOrRefArray, ReferenceOrRefArray }, 1, ForceArrayReturn }}, - { ocLet, {{ Value, ReferenceOrRefArray, ReferenceOrRefArray, }, 2, ForceArrayReturn } }, + { ocLet, {{ Value, ReferenceOrRefArray, ReferenceOrRefArray }, 2, Value }}, + { ocLambda, {{ Value }, 1, Value }}, // Other specials. { ocArrayClose, {{ Bounds }, 0, Bounds }}, { ocArrayColSep, {{ Bounds }, 0, Bounds }}, @@ -106,11 +107,15 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocAmpersand, {{ Array, Array }, 0, Value }}, { ocAnd, {{ Reference }, 1, Value }}, { ocAreas, {{ Reference }, 0, Value }}, + { ocArrayToText, {{ ReferenceOrRefArray, Value }, 0, Value }}, { ocAveDev, {{ Reference }, 1, Value }}, { ocAverage, {{ ReferenceOrRefArray }, 1, Value }}, { ocAverageA, {{ ReferenceOrRefArray }, 1, Value }}, { ocAverageIf, {{ ReferenceOrRefArray, Value, Reference }, 0, Value }}, { ocAverageIfs, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value }, 2, Value }}, + { ocByCol, {{ ForceArray, Value }, 0, ForceArrayReturn }}, + { ocByRow, {{ ForceArray, Value }, 0, ForceArrayReturn }}, + { ocCall, {{ Value, ForceArray }, 1, Value }}, { ocCell, {{ Value, Reference }, 0, Value }}, { ocColumn, {{ Reference }, 0, Value }}, { ocColumns, {{ Reference }, 1, Value }}, @@ -172,6 +177,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocIntercept, {{ ForceArray, ForceArray }, 0, Value }}, { ocIntersect, {{ Reference, Reference }, 0, Reference }}, { ocIsFormula, {{ Reference }, 0, Value }}, + { ocIsOmitted, {{ Value }, 1, Value }}, { ocIsRef, {{ Reference }, 0, Value }}, { ocKurt, {{ Reference }, 1, Value }}, { ocLCM, {{ Reference }, 1, Value }}, @@ -182,6 +188,8 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocLogest, {{ ForceArray, ForceArray, Value, Value }, 0, Value }}, { ocLookup, {{ Value, ReferenceOrForceArray, ReferenceOrForceArray }, 0, Value }}, { ocMIRR, {{ Reference, Value, Value }, 0, Value }}, + { ocMakeArray, {{ Value, Value, Value }, 0, ForceArrayReturn }}, + { ocMap, {{ ForceArray, ReferenceOrRefArray }, 1, ForceArrayReturn }}, { ocMatDet, {{ ForceArray }, 0, Value }}, { ocMatInv, {{ ForceArray }, 0, Value }}, { ocMatMult, {{ ForceArray, ForceArray }, 0, Value }}, @@ -235,17 +243,23 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocRank, {{ Value, Reference, Value }, 0, Value }}, { ocRank_Avg, {{ Value, Reference, Value }, 0, Value }}, { ocRank_Eq, {{ Value, Reference, Value }, 0, Value }}, + { ocReduce, {{ Value, ForceArray, Value }, 0, Value }}, { ocRow, {{ Reference }, 0, Value }}, { ocRows, {{ Reference }, 1, Value }}, { ocSTEYX, {{ ForceArray, ForceArray }, 0, Value }}, + { ocScan, {{ Value, ForceArray, Value }, 0, ForceArrayReturn }}, { ocSheet, {{ Reference }, 0, Value }}, { ocSheets, {{ Reference }, 1, Value }}, + { ocSingleValue, {{ ForceArray }, 0, Value }}, { ocSkew, {{ Reference }, 1, Value }}, { ocSkewp, {{ Reference }, 1, Value }}, { ocSlope, {{ ForceArray, ForceArray }, 0, Value }}, { ocSmall, {{ Reference, Value }, 0, Value }}, { ocSort, {{ ReferenceOrRefArray, ForceArray, ForceArray, Value }, 0, ForceArrayReturn }}, { ocSortBy, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value, }, 2, ForceArrayReturn }}, + // The # refers to the master cell before it, so the operand is taken as one whole + // reference, in an array formula too. + { ocSpill, {{ Reference }, 0, Reference }}, { ocStDev, {{ Reference }, 1, Value }}, { ocStDevA, {{ Reference }, 1, Value }}, { ocStDevP, {{ Reference }, 1, Value }}, @@ -311,14 +325,14 @@ void ScParameterClassification::Init() { if ( pData ) return; - pData = new RunData[ SC_OPCODE_LAST_OPCODE_ID + 1 ]; - memset( pData, 0, sizeof(RunData) * (SC_OPCODE_LAST_OPCODE_ID + 1)); + pData = new RunData[ ocLastOpcodeId + 1 ]; + memset( pData, 0, sizeof(RunData) * (ocLastOpcodeId + 1)); // init from specified static data above for (const auto & i : pRawData) { const RawData* pRaw = &i; - if ( pRaw->eOp > SC_OPCODE_LAST_OPCODE_ID ) + if ( pRaw->eOp > ocLastOpcodeId ) { OSL_ENSURE( pRaw->eOp == ocNone, "RawData OpCode error"); } @@ -391,7 +405,8 @@ formula::ParamClass ScParameterClassification::GetParameterType( switch ( eOp ) { case ocExternal: - return GetExternalParameterType( pToken, nParameter); + case ocUDExternal: + return GetExternalParameterType( static_cast(pToken), nParameter); case ocMacro: return (nParameter == SAL_MAX_UINT16 ? Value : Reference); default: @@ -399,7 +414,7 @@ formula::ParamClass ScParameterClassification::GetParameterType( // added to avoid warnings } } - if ( 0 <= static_cast(eOp) && eOp <= SC_OPCODE_LAST_OPCODE_ID ) + if ( 0 <= static_cast(eOp) && eOp <= ocLastOpcodeId ) { sal_uInt8 nRepeat; formula::ParamClass eType; @@ -424,7 +439,7 @@ formula::ParamClass ScParameterClassification::GetParameterType( return Unknown; } -formula::ParamClass ScParameterClassification::GetExternalParameterType( const formula::FormulaToken* pToken, +formula::ParamClass ScParameterClassification::GetExternalParameterType( const FormulaExternalToken* pToken, sal_uInt16 nParameter) { formula::ParamClass eRet = Unknown; @@ -510,7 +525,7 @@ void ScParameterClassification::MergeArgumentsFromFunctionResource() for ( const ScFuncDesc* pDesc = pFuncList->First(); pDesc; pDesc = pFuncList->Next() ) { - if ( pDesc->nFIndex > SC_OPCODE_LAST_OPCODE_ID || + if ( pDesc->nFIndex > ocLAST_OPCODE_ID || pData[pDesc->nFIndex].aData.nParam[0] != Unknown ) continue; // not an internal opcode or already done @@ -580,7 +595,7 @@ void ScParameterClassification::GenerateDocumentation() // preset parameter count according to opcode value, with some // special handling bool bAddParentheses = true; - if ( eOp < SC_OPCODE_STOP_DIV ) + if ( eOp < ocSTOP_DIV ) { bAddParentheses = false; // will be overridden below if parameters switch ( eOp ) @@ -592,6 +607,7 @@ void ScParameterClassification::GenerateDocumentation() case ocIfError: case ocIfNA: case ocChoose: + case ocLambda: aToken.SetByte(2); break; case ocPercentSign: @@ -600,12 +616,12 @@ void ScParameterClassification::GenerateDocumentation() default:; } } - else if ( eOp < SC_OPCODE_STOP_ERRORS ) + else if ( eOp < ocSTOP_ERRORS ) { bAddParentheses = false; aToken.SetByte(0); } - else if ( eOp < SC_OPCODE_STOP_BIN_OP ) + else if ( eOp < ocSTOP_BIN_OP ) { switch ( eOp ) { @@ -617,11 +633,11 @@ void ScParameterClassification::GenerateDocumentation() aToken.SetByte(2); } } - else if ( eOp < SC_OPCODE_STOP_UN_OP ) + else if ( eOp < ocSTOP_UN_OP ) aToken.SetByte(1); - else if ( eOp < SC_OPCODE_STOP_NO_PAR ) + else if ( eOp < ocSTOP_NO_PAR ) aToken.SetByte(0); - else if ( eOp < SC_OPCODE_STOP_1_PAR ) + else if ( eOp < ocSTOP_1_PAR ) aToken.SetByte(1); else aToken.SetByte( nParams); diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx index a39dabdcf559..70d1471d5077 100644 --- a/sc/source/core/tool/queryentry.cxx +++ b/sc/source/core/tool/queryentry.cxx @@ -24,7 +24,7 @@ /* * dialog returns the special field values "empty"/"not empty" * as constants SC_EMPTYFIELDS and SC_NONEMPTYFIELDS respectively in nVal in - * conjunctions with the flag bQueryByString = FALSE. + * conjunction with the flag bQueryByString = FALSE. */ #define SC_EMPTYFIELDS (double(0x0042)) diff --git a/sc/source/core/tool/queryparam.cxx b/sc/source/core/tool/queryparam.cxx index aafe0d891951..33eb7f0324bd 100644 --- a/sc/source/core/tool/queryparam.cxx +++ b/sc/source/core/tool/queryparam.cxx @@ -32,8 +32,6 @@ namespace { -const size_t MAXQUERY = 8; - class FindByField { SCCOLROW mnField; diff --git a/sc/source/core/tool/rangelst.cxx b/sc/source/core/tool/rangelst.cxx index e96185da0ef4..553829061dbc 100644 --- a/sc/source/core/tool/rangelst.cxx +++ b/sc/source/core/tool/rangelst.cxx @@ -346,11 +346,6 @@ bool ScRangeList::operator==( const ScRangeList& r ) const return maRanges == r.maRanges; } -bool ScRangeList::operator!=( const ScRangeList& r ) const -{ - return !operator==( r ); -} - bool ScRangeList::UpdateReference( UpdateRefMode eUpdateRefMode, const ScDocument& rDoc, diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 4fc30e71d508..e9685ef11e28 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -137,6 +138,20 @@ ScRangeData::~ScRangeData() { } +ScRangeData& ScRangeData::operator=( ScRangeData&& rData ) +{ + aName = std::move(rData.aName); + aUpperName = std::move(rData.aUpperName); + maNewName = std::move(rData.maNewName); + pCode = std::move(rData.pCode); + aPos = rData.aPos; + eType = rData.eType; + eTempGrammar = rData.eTempGrammar; + nIndex = rData.nIndex; + bModified = rData.bModified; + return *this; +} + void ScRangeData::CompileRangeData( const OUString& rSymbol, bool bSetError ) { if (eTempGrammar == FormulaGrammar::GRAM_UNSPECIFIED) @@ -204,10 +219,10 @@ void ScRangeData::Dump() const void ScRangeData::GuessPosition() { - // set a position that allows "absoluting" of all relative references + // set a position that allows "absolutizing" of all relative references // in CalcAbsIfRel without errors - OSL_ENSURE(aPos == ScAddress(), "position will go lost now"); + OSL_ENSURE(aPos == ScAddress(), "position will get lost now"); SCCOL nMinCol = 0; SCROW nMinRow = 0; @@ -217,17 +232,17 @@ void ScRangeData::GuessPosition() formula::FormulaTokenArrayPlainIterator aIter(*pCode); while ( ( t = aIter.GetNextReference() ) != nullptr ) { - ScSingleRefData& rRef1 = *t->GetSingleRef(); - if ( rRef1.IsColRel() && rRef1.Col() < nMinCol ) - nMinCol = rRef1.Col(); - if ( rRef1.IsRowRel() && rRef1.Row() < nMinRow ) - nMinRow = rRef1.Row(); - if ( rRef1.IsTabRel() && rRef1.Tab() < nMinTab ) - nMinTab = rRef1.Tab(); + ScSingleRefData* pRef1 = ScRefTokenHelper::getSingleRef(t); + if ( pRef1->IsColRel() && pRef1->Col() < nMinCol ) + nMinCol = pRef1->Col(); + if ( pRef1->IsRowRel() && pRef1->Row() < nMinRow ) + nMinRow = pRef1->Row(); + if ( pRef1->IsTabRel() && pRef1->Tab() < nMinTab ) + nMinTab = pRef1->Tab(); if ( t->GetType() == svDoubleRef ) { - ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(t)->GetDoubleRef().Ref2; if ( rRef2.IsColRel() && rRef2.Col() < nMinCol ) nMinCol = rRef2.Col(); if ( rRef2.IsRowRel() && rRef2.Row() < nMinRow ) @@ -548,9 +563,9 @@ void ScRangeData::ValidateTabRefs() formula::FormulaTokenArrayPlainIterator aIter(*pCode); while ( ( t = aIter.GetNextReference() ) != nullptr ) { - ScSingleRefData& rRef1 = *t->GetSingleRef(); - ScAddress aAbs = rRef1.toAbs(rDoc, aPos); - if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() ) + ScSingleRefData* pRef1 = ScRefTokenHelper::getSingleRef(t); + ScAddress aAbs = pRef1->toAbs(rDoc, aPos); + if ( pRef1->IsTabRel() && !pRef1->IsTabDeleted() ) { if (aAbs.Tab() < nMinTab) nMinTab = aAbs.Tab(); @@ -559,7 +574,7 @@ void ScRangeData::ValidateTabRefs() } if ( t->GetType() == svDoubleRef ) { - ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(t)->GetDoubleRef().Ref2; aAbs = rRef2.toAbs(rDoc, aPos); if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() ) { @@ -589,7 +604,7 @@ void ScRangeData::ValidateTabRefs() { case svSingleRef: { - ScSingleRefData& rRef = *t->GetSingleRef(); + ScSingleRefData& rRef = static_cast(t)->GetSingleRef(); if (!rRef.IsTabDeleted()) { ScAddress aAbs = rRef.toAbs(rDoc, aOldPos); @@ -599,7 +614,7 @@ void ScRangeData::ValidateTabRefs() break; case svDoubleRef: { - ScComplexRefData& rRef = *t->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(t)->GetDoubleRef(); if (!rRef.Ref1.IsTabDeleted()) { ScAddress aAbs = rRef.Ref1.toAbs(rDoc, aOldPos); @@ -799,10 +814,10 @@ void ScRangeName::CopyUsedNames( const SCTAB nLocalTab, const SCTAB nOldTab, con } } -bool ScRangeName::insert( ScRangeData* p, bool bReuseFreeIndex ) +ScRangeData* ScRangeName::insert( std::unique_ptr p, bool bReuseFreeIndex ) { if (!p) - return false; + return nullptr; if (!p->GetIndex()) { @@ -828,19 +843,34 @@ bool ScRangeName::insert( ScRangeData* p, bool bReuseFreeIndex ) } OUString aName(p->GetUpperName()); - erase(aName); // ptr_map won't insert it if a duplicate name exists. - std::pair r = - m_Data.insert(std::make_pair(aName, std::unique_ptr(p))); - if (r.second) + ScRangeData* pRet; + DataType::iterator itrExisting = m_Data.find(aName); + if (itrExisting != m_Data.end()) { - // Data inserted. Store its index for mapping. - size_t nPos = p->GetIndex() - 1; - if (nPos >= maIndexToData.size()) - maIndexToData.resize(nPos+1, nullptr); - maIndexToData[nPos] = p; - mHasPossibleAddressConflictDirty = true; + // An entry with this name already exists. Move the values of p into + // it, so that pointers held to the existing entry stay valid. The + // move takes the index of p as well, so free the slot the existing + // entry holds before the move overwrites its index. + ScRangeData* pExisting = itrExisting->second.get(); + sal_uInt16 nOldIndex = pExisting->GetIndex(); + assert(0 < nOldIndex && nOldIndex <= maIndexToData.size() && maIndexToData[nOldIndex-1] == pExisting); + maIndexToData[nOldIndex-1] = nullptr; + *pExisting = std::move(*p); + pRet = pExisting; } - return r.second; + else + { + pRet = p.get(); + m_Data.insert(std::make_pair(aName, std::move(p))); + } + + // Store the index of the surviving entry for mapping. + size_t nPos = pRet->GetIndex() - 1; + if (nPos >= maIndexToData.size()) + maIndexToData.resize(nPos+1, nullptr); + maIndexToData[nPos] = pRet; + mHasPossibleAddressConflictDirty = true; + return pRet; } void ScRangeName::erase(const ScRangeData& r) diff --git a/sc/source/core/tool/rangeutl.cxx b/sc/source/core/tool/rangeutl.cxx index e7314645c2b6..27551d94eace 100644 --- a/sc/source/core/tool/rangeutl.cxx +++ b/sc/source/core/tool/rangeutl.cxx @@ -286,7 +286,7 @@ bool ScRangeUtil::MakeRangeFromName ( pData = pRangeNames->findByUpperName(aName); } if (!pData && eScope != RUTL_NAMES_LOCAL) - pData = rDoc.GetRangeName()->findByUpperName(aName); + pData = rDoc.GetRangeName().findByUpperName(aName); if (pData) { OUString aStrArea; @@ -964,11 +964,8 @@ ScRangeData* ScRangeStringConverter::GetRangeDataFromString( const OUString& rSt } if (!pData) { - ScRangeName* pGlobalRangeName = rDoc.GetRangeName(); - if (pGlobalRangeName) - { - pData = pGlobalRangeName->findByUpperName(aUpperName); - } + ScRangeName& rGlobalRangeName = rDoc.GetRangeName(); + pData = rGlobalRangeName.findByUpperName(aUpperName); } return pData; } @@ -992,15 +989,12 @@ bool ScArea::operator==( const ScArea& r ) const } ScAreaNameIterator::ScAreaNameIterator( const ScDocument& rDoc ) : - pRangeName(rDoc.GetRangeName()), + rRangeName(rDoc.GetRangeName()), pDBCollection(rDoc.GetDBCollection()), bFirstPass(true) { - if (pRangeName) - { - maRNPos = pRangeName->begin(); - maRNEnd = pRangeName->end(); - } + maRNPos = rRangeName.begin(); + maRNEnd = rRangeName.end(); } bool ScAreaNameIterator::Next( OUString& rName, ScRange& rRange ) @@ -1009,7 +1003,7 @@ bool ScAreaNameIterator::Next( OUString& rName, ScRange& rRange ) { if ( bFirstPass ) // first the area names { - if ( pRangeName && maRNPos != maRNEnd ) + if ( maRNPos != maRNEnd ) { const ScRangeData& rData = *maRNPos->second; ++maRNPos; diff --git a/sc/source/core/tool/refdata.cxx b/sc/source/core/tool/refdata.cxx index 3e1b9b1af8be..fcf256ea8aa1 100644 --- a/sc/source/core/tool/refdata.cxx +++ b/sc/source/core/tool/refdata.cxx @@ -354,11 +354,6 @@ bool ScSingleRefData::operator==( const ScSingleRefData& r ) const return mnFlagValue == r.mnFlagValue && mnCol == r.mnCol && mnRow == r.mnRow && mnTab == r.mnTab; } -bool ScSingleRefData::operator!=( const ScSingleRefData& r ) const -{ - return !operator==(r); -} - #if DEBUG_FORMULA_COMPILER void ScSingleRefData::Dump( int nIndent ) const { diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx index 03bf88f19df1..f332d3483471 100644 --- a/sc/source/core/tool/reftokenhelper.cxx +++ b/sc/source/core/tool/reftokenhelper.cxx @@ -74,7 +74,7 @@ void ScRefTokenHelper::compileRangeRepresentation( { case svSingleRef: { - const ScSingleRefData& rRef = *p->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); if (!rRef.Valid(rDoc)) bFailure = true; else if (bOnly3DRef && !rRef.IsFlag3D()) @@ -83,7 +83,7 @@ void ScRefTokenHelper::compileRangeRepresentation( break; case svDoubleRef: { - const ScComplexRefData& rRef = *p->GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); if (!rRef.Valid(rDoc)) bFailure = true; else if (bOnly3DRef && !rRef.Ref1.IsFlag3D()) @@ -92,25 +92,26 @@ void ScRefTokenHelper::compileRangeRepresentation( break; case svExternalSingleRef: { - if (!p->GetSingleRef()->ValidExternal(rDoc)) + if (!static_cast(p)->GetSingleRef().ValidExternal(rDoc)) bFailure = true; } break; case svExternalDoubleRef: { - if (!p->GetDoubleRef()->ValidExternal(rDoc)) + if (!static_cast(p)->GetDoubleRef().ValidExternal(rDoc)) bFailure = true; } break; case svString: - if (p->GetString().isEmpty()) + if (static_cast(p)->GetString().isEmpty()) bFailure = true; break; case svIndex: { if (p->GetOpCode() == ocName) { - ScRangeData* pNameRange = rDoc.FindRangeNameBySheetAndIndex(p->GetSheet(), p->GetIndex()); + auto pIndexToken = static_cast(p); + ScRangeData* pNameRange = rDoc.FindRangeNameBySheetAndIndex(pIndexToken->GetSheet(), pIndexToken->GetIndex()); if (!pNameRange->HasReferences()) bFailure = true; } @@ -132,29 +133,43 @@ bool ScRefTokenHelper::getRangeFromToken( const ScDocument* pDoc, ScRange& rRange, const ScTokenRef& pToken, const ScAddress& rPos, bool bExternal) { - StackVar eType = pToken->GetType(); switch (pToken->GetType()) { case svSingleRef: - case svExternalSingleRef: { - if ((eType == svExternalSingleRef && !bExternal) || - (eType == svSingleRef && bExternal)) + if (bExternal) return false; - const ScSingleRefData& rRefData = *pToken->GetSingleRef(); + const ScSingleRefData& rRefData = static_cast(pToken.get())->GetSingleRef(); + rRange.aStart = rRefData.toAbs(*pDoc, rPos); + rRange.aEnd = rRange.aStart; + return true; + } + case svExternalSingleRef: + { + if (!bExternal) + return false; + + const ScSingleRefData& rRefData = static_cast(pToken.get())->GetSingleRef(); rRange.aStart = rRefData.toAbs(*pDoc, rPos); rRange.aEnd = rRange.aStart; return true; } case svDoubleRef: - case svExternalDoubleRef: { - if ((eType == svExternalDoubleRef && !bExternal) || - (eType == svDoubleRef && bExternal)) + if (bExternal) return false; - const ScComplexRefData& rRefData = *pToken->GetDoubleRef(); + const ScComplexRefData& rRefData = static_cast(pToken.get())->GetDoubleRef(); + rRange = rRefData.toAbs(*pDoc, rPos); + return true; + } + case svExternalDoubleRef: + { + if (!bExternal) + return false; + + const ScComplexRefData& rRefData = static_cast(pToken.get())->GetDoubleRef(); rRange = rRefData.toAbs(*pDoc, rPos); return true; } @@ -162,7 +177,8 @@ bool ScRefTokenHelper::getRangeFromToken( { if (pToken->GetOpCode() == ocName) { - ScRangeData* pNameRange = pDoc->FindRangeNameBySheetAndIndex(pToken->GetSheet(), pToken->GetIndex()); + auto pIndexToken = static_cast(pToken.get()); + ScRangeData* pNameRange = pDoc->FindRangeNameBySheetAndIndex(pIndexToken->GetSheet(), pIndexToken->GetIndex()); if (pNameRange->IsReference(rRange, rPos)) return true; } @@ -249,7 +265,9 @@ bool ScRefTokenHelper::intersects( return false; bool bExternal = isExternalRef(pToken); - sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0; + sal_uInt16 nFileId = 0; + if (bExternal) + nFileId = static_cast(pToken.get())->GetFileId(); ScRange aRange; getRangeFromToken(pDoc, aRange, pToken, rPos, bExternal); @@ -265,9 +283,13 @@ bool ScRefTokenHelper::intersects( ScRange aRange2; getRangeFromToken(pDoc, aRange2, p, rPos, bExternal); - if (bExternal && nFileId != p->GetIndex()) - // different external file - continue; + if (bExternal) + { + sal_uInt16 nOtherFileId = static_cast(p.get())->GetFileId(); + if (nFileId != nOtherFileId) + // different external file + continue; + } if (aRange.Intersects(aRange2)) return true; @@ -331,8 +353,17 @@ private: // Get the information of the new token. bool bExternal = ScRefTokenHelper::isExternalRef(pToken); - sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0; - svl::SharedString aTabName = bExternal ? pToken->GetString() : svl::SharedString::getEmptyString(); + sal_uInt16 nFileId = bExternal ? static_cast(pToken.get())->GetFileId() : 0; + svl::SharedString aTabName; + if (bExternal) + { + if (pToken->GetType() == svExternalDoubleRef) + aTabName = static_cast(pToken.get())->GetTableName(); + else + aTabName = static_cast(pToken.get())->GetTableName(); + } + else + aTabName = svl::SharedString::getEmptyString(); bool bJoined = false; for (ScTokenRef& pOldToken : rTokens) @@ -348,11 +379,14 @@ private: if (bExternal) { - if (nFileId != pOldToken->GetIndex()) + if (nFileId != static_cast(pOldToken.get())->GetFileId()) // Different external files. continue; - if (aTabName != pOldToken->GetString()) + auto aNewTabName = pOldToken->GetType() == svExternalSingleRef + ? static_cast(pOldToken.get())->GetTableName() + : static_cast(pOldToken.get())->GetTableName(); + if (aTabName != aNewTabName) // Different table names. continue; } @@ -445,9 +479,17 @@ bool ScRefTokenHelper::getDoubleRefDataFromToken(ScComplexRefData& rData, const switch (pToken->GetType()) { case svSingleRef: + { + const ScSingleRefData& r = static_cast(pToken.get())->GetSingleRef(); + rData.Ref1 = r; + rData.Ref1.SetFlag3D(true); + rData.Ref2 = r; + rData.Ref2.SetFlag3D(false); // Don't display sheet name on second reference. + } + break; case svExternalSingleRef: { - const ScSingleRefData& r = *pToken->GetSingleRef(); + const ScSingleRefData& r = static_cast(pToken.get())->GetSingleRef(); rData.Ref1 = r; rData.Ref1.SetFlag3D(true); rData.Ref2 = r; @@ -455,8 +497,10 @@ bool ScRefTokenHelper::getDoubleRefDataFromToken(ScComplexRefData& rData, const } break; case svDoubleRef: + rData = static_cast(pToken.get())->GetDoubleRef(); + break; case svExternalDoubleRef: - rData = *pToken->GetDoubleRef(); + rData = static_cast(pToken.get())->GetDoubleRef(); break; default: // Not a reference token. Bail out. @@ -481,4 +525,18 @@ ScTokenRef ScRefTokenHelper::createRefToken(const ScDocument& rDoc, const ScRang return pRef; } +ScSingleRefData* ScRefTokenHelper::getSingleRef(formula::FormulaToken* t) +{ + if ( t->GetType() == svSingleRef ) + return &static_cast(t)->GetSingleRef(); + else if ( t->GetType() == svExternalSingleRef ) + return &static_cast(t)->GetSingleRef(); + else if ( t->GetType() == svDoubleRef ) + return &static_cast(t)->GetSingleRef(); + else if ( t->GetType() == svExternalDoubleRef ) + return &static_cast(t)->GetSingleRef(); + else + return nullptr; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index 63acabf4b646..5579efb3e61a 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -90,6 +90,18 @@ double convertStringToValue( ScInterpreter* pErrorInterpreter, const OUString& r return CreateDoubleError( FormulaError::NoValue); } +// Format a value through the LOGICAL key so the string form is +// "TRUE" for a non-zero value or "FALSE" for zero. +OUString formatLogical(ScInterpreterContext& rContext, double fValue) +{ + sal_uInt32 nKey = rContext.NFGetStandardFormat(SvNumFormatType::LOGICAL, + ScGlobal::eLnge); + OUString aString; + const Color* pColor = nullptr; + rContext.NFGetOutputString(fValue, nKey, aString, &pColor); + return aString; +} + struct ElemEqualZero { double operator() (double val) const @@ -612,14 +624,7 @@ void ScMatrixImpl::PutEmptyPath(SCSIZE nC, SCSIZE nR) if (ValidColRow( nC, nR)) { maMat.set_empty(nR, nC); -#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12 && __cplusplus == 202002L -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" -#endif maMatFlag.set(nR, nC, SC_MATFLAG_EMPTYPATH); -#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12 && __cplusplus == 202002L -#pragma GCC diagnostic pop -#endif } else { @@ -740,6 +745,7 @@ svl::SharedString ScMatrixImpl::GetString( ScInterpreterContext& rContext, SCSIZ } double fVal = 0.0; + SvNumFormatType eFormatType = SvNumFormatType::NUMBER; MatrixImplType::const_position_type aPos = maMat.position(nR, nC); switch (maMat.get_type(aPos)) { @@ -759,8 +765,13 @@ svl::SharedString ScMatrixImpl::GetString( ScInterpreterContext& rContext, SCSIZ rContext.NFGetOutputString( 0.0, nKey, aStr, &pColor); return svl::SharedString( aStr); // string not interned } - case mdds::mtm::element_numeric: case mdds::mtm::element_boolean: + // Format the cell through the LOGICAL key so the string + // form is "TRUE" or "FALSE". + fVal = maMat.get_numeric(aPos); + eFormatType = SvNumFormatType::LOGICAL; + break; + case mdds::mtm::element_numeric: fVal = maMat.get_numeric(aPos); break; default: @@ -774,6 +785,9 @@ svl::SharedString ScMatrixImpl::GetString( ScInterpreterContext& rContext, SCSIZ return svl::SharedString( ScGlobal::GetErrorString( nError)); // string not interned } + if (eFormatType == SvNumFormatType::LOGICAL) + return svl::SharedString(formatLogical(rContext, fVal)); // string not interned + sal_uInt32 nKey = rContext.NFGetStandardFormat( SvNumFormatType::NUMBER, ScGlobal::eLnge); return svl::SharedString(rContext.NFGetInputLineString( fVal, nKey )); // string not interned @@ -2828,8 +2842,9 @@ void ScMatrixImpl::MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef& std::function aBoolFunc = [&](size_t nRow, size_t nCol, bool nVal) { - OUString aStr = rContext.NFGetInputLineString( nVal ? 1.0 : 0.0, nKey); - aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] + aStr; + OUString aLogicalText = formatLogical(rContext, nVal ? 1.0 : 0.0); + size_t nIndex = get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset); + aString[nIndex] = aString[nIndex] + aLogicalText; }; std::function aStringFunc = @@ -2866,7 +2881,7 @@ void ScMatrixImpl::MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef& else xMat1->ExecuteOperation( std::pair(0, 0), - std::pair(nMaxRow - 1, nMaxCol - 1), + std::pair(std::min(nR1, nMaxRow) - 1, std::min(nC1, nMaxCol) - 1), std::move(aDoubleFunc), std::move(aBoolFunc), std::move(aStringFunc), std::move(aEmptyFunc)); std::vector aSharedString(nMaxCol*nMaxRow); @@ -2888,8 +2903,9 @@ void ScMatrixImpl::MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef& std::function aBoolFunc2 = [&](size_t nRow, size_t nCol, bool nVal) { - OUString aStr = rContext.NFGetInputLineString( nVal ? 1.0 : 0.0, nKey); - aSharedString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = rStringPool.intern(aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] + aStr); + OUString aLogicalText = formatLogical(rContext, nVal ? 1.0 : 0.0); + size_t nIndex = get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset); + aSharedString[nIndex] = rStringPool.intern(aString[nIndex] + aLogicalText); }; std::function aStringFunc2 = @@ -2929,7 +2945,7 @@ void ScMatrixImpl::MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef& else xMat2->ExecuteOperation( std::pair(0, 0), - std::pair(nMaxRow - 1, nMaxCol - 1), + std::pair(std::min(nR2, nMaxRow) - 1, std::min(nC2, nMaxCol) - 1), std::move(aDoubleFunc2), std::move(aBoolFunc2), std::move(aStringFunc2), std::move(aEmptyFunc2)); aString.clear(); @@ -3140,7 +3156,10 @@ void ScMatrixImpl::ExecuteBinaryOp(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatri } } else - aOutPos = maMat.set(aOutPos, CreateDoubleError(FormulaError::NoValue)); + // Out of bounds against the shorter operand. + // Mismatched-extent arithmetic fills these slots + // with #N/A so the longer side still has a result. + aOutPos = maMat.set(aOutPos, CreateDoubleError(FormulaError::NotAvailable)); aOutPos = MatrixImplType::next_position(aOutPos); } } diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx index 499264900861..53ff50f6232a 100644 --- a/sc/source/core/tool/sharedformula.cxx +++ b/sc/source/core/tool/sharedformula.cxx @@ -14,7 +14,7 @@ #include #include #include -#include +#include namespace sc { @@ -379,19 +379,25 @@ void SharedFormulaUtil::startListeningAsGroup( sc::StartListeningContext& rCxt, { case formula::svSingleRef: { - const ScSingleRefData* pRef = t->GetSingleRef(); - ScAddress aPos = pRef->toAbs(rDoc, rTopCell.aPos); + const ScSingleRefData& rRef = static_cast(t)->GetSingleRef(); + ScAddress aPos = rRef.toAbs(rDoc, rTopCell.aPos); ScFormulaCell** pp = ppSharedTop; ScFormulaCell** ppEnd = ppSharedTop + xGroup->mnLength; - if (aPos.IsValid()) - if (ScTable* pTable = rDoc.FetchTable(aPos.Tab())) - pTable->CreateColumnIfNotExists(aPos.Col()).StartListeningSingleRefFormulaCells(rCxt, pRef, aPos, pp, ppEnd); + for (; pp != ppEnd; ++pp) + { + if (!aPos.IsValid()) + break; + + rDoc.StartListeningCell(rCxt, aPos, **pp); + if (rRef.IsRowRel()) + aPos.IncRow(); + } } break; case formula::svDoubleRef: { - const ScSingleRefData& rRef1 = *t->GetSingleRef(); - const ScSingleRefData& rRef2 = *t->GetSingleRef2(); + const ScSingleRefData& rRef1 = static_cast(t)->GetSingleRef(); + const ScSingleRefData& rRef2 = static_cast(t)->GetSingleRef2(); ScAddress aPos1 = rRef1.toAbs(rDoc, rTopCell.aPos); ScAddress aPos2 = rRef2.toAbs(rDoc, rTopCell.aPos); diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index bad83b4ebb97..c14c757bfa15 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -158,10 +157,10 @@ namespace switch ((*pp)->GetType()) { case svSingleRef: - return (*pp)->GetSingleRef()->IsRelName(); + return static_cast(*pp)->GetSingleRef().IsRelName(); case svDoubleRef: { - const ScComplexRefData& rRef = *(*pp)->GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(*pp)->GetDoubleRef(); return rRef.Ref1.IsRelName() || rRef.Ref2.IsRelName(); } default: @@ -222,6 +221,7 @@ void ScRawToken::SetOpCode( OpCode e ) nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1; break; case ocLet: + case ocLambda: eType = svJump; nJump[ 0 ] = FORMULA_MAXPARAMS + 1; break; @@ -346,10 +346,13 @@ void ScRawToken::SetExternalName( sal_uInt16 nFileId, const OUString& rName ) maExternalName = rName; } -void ScRawToken::SetExternal( const OUString& rStr ) +void ScRawToken::SetExternal( const OUString& rStr, OpCode eCode ) { - eOp = ocExternal; + eOp = eCode; eType = svExternal; + // set later when a call's arguments are parsed + sbyte.cByte = 0; + sbyte.eInForceArray = ParamClass::Unknown; maExternalName = rStr; } @@ -456,20 +459,20 @@ bool checkTextEqual( const ScSheetLimits& rLimits, const FormulaToken& _rToken1, ScComplexRefData aTemp1; if ( _rToken1.GetType() == svSingleRef ) { - aTemp1.Ref1 = *_rToken1.GetSingleRef(); + aTemp1.Ref1 = static_cast(_rToken1).GetSingleRef(); aTemp1.Ref2 = aTemp1.Ref1; } else - aTemp1 = *_rToken1.GetDoubleRef(); + aTemp1 = static_cast(_rToken1).GetDoubleRef(); ScComplexRefData aTemp2; if ( _rToken2.GetType() == svSingleRef ) { - aTemp2.Ref1 = *_rToken2.GetSingleRef(); + aTemp2.Ref1 = static_cast(_rToken2).GetSingleRef(); aTemp2.Ref2 = aTemp2.Ref1; } else - aTemp2 = *_rToken2.GetDoubleRef(); + aTemp2 = static_cast(_rToken2).GetDoubleRef(); ScAddress aPos; ScRange aRange1 = aTemp1.toAbs(rLimits, aPos), aRange2 = aTemp2.toAbs(rLimits, aPos); @@ -555,16 +558,18 @@ FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, FormulaToken & rTo * merged here. For Xcl syntax already parse an external range * reference entirely, cumbersome. */ - const ScSingleRefData& rRef2 = *rTok2.GetSingleRef(); + const ScSingleRefData& rRef2 = static_cast(rTok2).GetSingleRef(); if (bExternal && rRef2.IsFlag3D()) return nullptr; ScComplexRefData aRef; - aRef.Ref1 = aRef.Ref2 = *rTok1.GetSingleRef(); + aRef.Ref1 = aRef.Ref2 = bExternal + ? static_cast(rTok1).GetSingleRef() + : static_cast(rTok1).GetSingleRef(); aRef.Ref2.SetFlag3D( false); aRef.Extend(rLimits, rRef2, rPos); if (bExternal) - xRes = new ScExternalDoubleRefToken( rTok1.GetIndex(), rTok1.GetString(), aRef); + xRes = new ScExternalDoubleRefToken( static_cast(rTok1).GetFileId(), static_cast(rTok1).GetTableName(), aRef); else xRes = new ScDoubleRefToken(rLimits, aRef); } @@ -583,9 +588,9 @@ FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, FormulaToken & rTo sv2 = svUnknown; // mark as handled } else if (sv1 == svRefList) - pRefList = rTok1.GetRefList(); + pRefList = static_cast(rTok1).GetRefList(); else if (sv2 == svRefList) - pRefList = rTok2.GetRefList(); + pRefList = static_cast(rTok2).GetRefList(); if (pRefList) { if (pRefList->empty()) @@ -598,20 +603,20 @@ FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, FormulaToken & rTo return nullptr; // shouldn't happen... StackVar sv[2] = { sv1, sv2 }; formula::FormulaToken* pt[2] = { &rTok1, &rTok2 }; - ScComplexRefData& rRef = *xRes->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(xRes.get())->GetDoubleRef(); for (size_t i=0; i<2; ++i) { switch (sv[i]) { case svSingleRef: - rRef.Extend(rLimits, *pt[i]->GetSingleRef(), rPos); + rRef.Extend(rLimits, static_cast(pt[i])->GetSingleRef(), rPos); break; case svDoubleRef: - rRef.Extend(rLimits, *pt[i]->GetDoubleRef(), rPos); + rRef.Extend(rLimits, static_cast(pt[i])->GetDoubleRef(), rPos); break; case svRefList: { - const ScRefList* p = pt[i]->GetRefList(); + const ScRefList* p = static_cast(pt[i])->GetRefList(); if (p->empty()) return nullptr; for (const auto& rRefData : *p) @@ -624,13 +629,13 @@ FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, FormulaToken & rTo if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D()) return nullptr; // no other sheets with external refs else - rRef.Extend(rLimits, *pt[i]->GetSingleRef(), rPos); + rRef.Extend(rLimits, static_cast(pt[i])->GetSingleRef(), rPos); break; case svExternalDoubleRef: if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D()) return nullptr; // no other sheets with external refs else - rRef.Extend(rLimits, *pt[i]->GetDoubleRef(), rPos); + rRef.Extend(rLimits, static_cast(pt[i])->GetDoubleRef(), rPos); break; default: ; // nothing, prevent compiler warning @@ -642,30 +647,24 @@ FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, FormulaToken & rTo // real implementations of virtual functions -const ScSingleRefData* ScSingleRefToken::GetSingleRef() const { return &aSingleRef; } -ScSingleRefData* ScSingleRefToken::GetSingleRef() { return &aSingleRef; } bool ScSingleRefToken::TextEqual( const FormulaToken& _rToken ) const { return FormulaToken::operator ==(_rToken) && checkTextEqual(mrSheetLimits, *this, _rToken); } bool ScSingleRefToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && aSingleRef == *r.GetSingleRef(); + return FormulaToken::operator==( r ) + && aSingleRef == static_cast(r).GetSingleRef(); } -const ScSingleRefData* ScDoubleRefToken::GetSingleRef() const { return &aDoubleRef.Ref1; } -ScSingleRefData* ScDoubleRefToken::GetSingleRef() { return &aDoubleRef.Ref1; } -const ScComplexRefData* ScDoubleRefToken::GetDoubleRef() const { return &aDoubleRef; } -ScComplexRefData* ScDoubleRefToken::GetDoubleRef() { return &aDoubleRef; } -const ScSingleRefData* ScDoubleRefToken::GetSingleRef2() const { return &aDoubleRef.Ref2; } -ScSingleRefData* ScDoubleRefToken::GetSingleRef2() { return &aDoubleRef.Ref2; } bool ScDoubleRefToken::TextEqual( const FormulaToken& _rToken ) const { return FormulaToken::operator ==(_rToken) && checkTextEqual(mrSheetLimits, *this, _rToken); } bool ScDoubleRefToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && aDoubleRef == *r.GetDoubleRef(); + return FormulaToken::operator==( r ) + && aDoubleRef == static_cast(r).GetDoubleRef(); } const ScRefList* ScRefListToken::GetRefList() const { return &aRefList; } @@ -673,10 +672,12 @@ const ScRefList* ScRefListToken::GetRefList() const { return &aRefList; bool ScRefListToken::IsArrayResult() const { return mbArrayResult; } bool ScRefListToken::operator==( const FormulaToken& r ) const { - if (!FormulaToken::operator==( r ) || &aRefList != r.GetRefList()) + if (!FormulaToken::operator==( r )) return false; - const ScRefListToken* p = dynamic_cast(&r); - return p && mbArrayResult == p->IsArrayResult(); + const ScRefListToken* p = static_cast(&r); + if (&aRefList != p->GetRefList()) + return false; + return mbArrayResult == p->IsArrayResult(); } ScMatrixToken::ScMatrixToken( ScMatrixRef p ) : @@ -688,55 +689,45 @@ const ScMatrix* ScMatrixToken::GetMatrix() const { return pMatrix.get(); ScMatrix* ScMatrixToken::GetMatrix() { return pMatrix.get(); } bool ScMatrixToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && pMatrix == r.GetMatrix(); + return FormulaToken::operator==( r ) + && pMatrix == static_cast(r).GetMatrix(); } -ScMatrixRangeToken::ScMatrixRangeToken( const sc::RangeMatrix& rMat ) : - FormulaToken(formula::svMatrix), mpMatrix(rMat.mpMat) +ScMatrixRangeToken::ScMatrixRangeToken(sc::RangeMatrix const& rMatrix, bool bReference) + : ScMatrixToken(rMatrix.mpMat) + , mbReference(bReference) { - maRef.InitRange(rMat.mnCol1, rMat.mnRow1, rMat.mnTab1, rMat.mnCol2, rMat.mnRow2, rMat.mnTab2); + maRef.InitRange(rMatrix.mnCol1, rMatrix.mnRow1, rMatrix.mnTab1, rMatrix.mnCol2, + rMatrix.mnRow2, rMatrix.mnTab2); } ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRangeToken& ) = default; -sal_uInt8 ScMatrixRangeToken::GetByte() const -{ - return MATRIX_TOKEN_HAS_RANGE; -} - -const ScMatrix* ScMatrixRangeToken::GetMatrix() const -{ - return mpMatrix.get(); -} - -ScMatrix* ScMatrixRangeToken::GetMatrix() -{ - return mpMatrix.get(); -} - -const ScComplexRefData* ScMatrixRangeToken::GetDoubleRef() const -{ - return &maRef; -} - -ScComplexRefData* ScMatrixRangeToken::GetDoubleRef() -{ - return &maRef; -} - -bool ScMatrixRangeToken::operator==( const FormulaToken& r ) const -{ - return FormulaToken::operator==(r) && mpMatrix == r.GetMatrix(); -} - FormulaToken* ScMatrixRangeToken::Clone() const { return new ScMatrixRangeToken(*this); } +ScExternalToken::ScExternalToken(formula::StackVar eTypeP, OpCode e, sal_uInt16 nFileId) : + FormulaToken(eTypeP, e), + mnFileId(nFileId) +{ +} + +ScExternalToken::~ScExternalToken() +{ +} + +bool ScExternalToken::operator ==( const FormulaToken& r ) const +{ + if (!FormulaToken::operator==(r)) + return false; + + return mnFileId == static_cast(r).mnFileId; +} + ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, svl::SharedString aTabName, const ScSingleRefData& r ) : - FormulaToken( svExternalSingleRef, ocPush), - mnFileId(nFileId), + ScExternalToken( svExternalSingleRef, ocPush, nFileId ), maTabName(std::move(aTabName)), maSingleRef(r) { @@ -746,43 +737,19 @@ ScExternalSingleRefToken::~ScExternalSingleRefToken() { } -sal_uInt16 ScExternalSingleRefToken::GetIndex() const -{ - return mnFileId; -} - -const svl::SharedString & ScExternalSingleRefToken::GetString() const -{ - return maTabName; -} - -const ScSingleRefData* ScExternalSingleRefToken::GetSingleRef() const -{ - return &maSingleRef; -} - -ScSingleRefData* ScExternalSingleRefToken::GetSingleRef() -{ - return &maSingleRef; -} - bool ScExternalSingleRefToken::operator ==( const FormulaToken& r ) const { - if (!FormulaToken::operator==(r)) + if (!ScExternalToken::operator==(r)) return false; - if (mnFileId != r.GetIndex()) + if (maTabName != static_cast(r).GetTableName()) return false; - if (maTabName != r.GetString()) - return false; - - return maSingleRef == *r.GetSingleRef(); + return maSingleRef == static_cast(r).GetSingleRef(); } ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, svl::SharedString aTabName, const ScComplexRefData& r ) : - FormulaToken( svExternalDoubleRef, ocPush), - mnFileId(nFileId), + ScExternalToken( svExternalDoubleRef, ocPush, nFileId), maTabName(std::move(aTabName)), maDoubleRef(r) { @@ -792,88 +759,33 @@ ScExternalDoubleRefToken::~ScExternalDoubleRefToken() { } -sal_uInt16 ScExternalDoubleRefToken::GetIndex() const -{ - return mnFileId; -} - -const svl::SharedString & ScExternalDoubleRefToken::GetString() const -{ - return maTabName; -} - -const ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef() const -{ - return &maDoubleRef.Ref1; -} - -ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef() -{ - return &maDoubleRef.Ref1; -} - -const ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef2() const -{ - return &maDoubleRef.Ref2; -} - -ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef2() -{ - return &maDoubleRef.Ref2; -} - -const ScComplexRefData* ScExternalDoubleRefToken::GetDoubleRef() const -{ - return &maDoubleRef; -} - -ScComplexRefData* ScExternalDoubleRefToken::GetDoubleRef() -{ - return &maDoubleRef; -} - bool ScExternalDoubleRefToken::operator ==( const FormulaToken& r ) const { - if (!FormulaToken::operator==(r)) + if (!ScExternalToken::operator==(r)) return false; - if (mnFileId != r.GetIndex()) + auto rhs = static_cast(r); + + if (maTabName != rhs.maTabName) return false; - if (maTabName != r.GetString()) - return false; - - return maDoubleRef == *r.GetDoubleRef(); + return maDoubleRef == rhs.GetDoubleRef(); } ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, svl::SharedString aName ) : - FormulaToken( svExternalName, ocPush), - mnFileId(nFileId), + ScExternalToken( svExternalName, ocPush, nFileId), maName(std::move(aName)) { } ScExternalNameToken::~ScExternalNameToken() {} -sal_uInt16 ScExternalNameToken::GetIndex() const -{ - return mnFileId; -} - -const svl::SharedString & ScExternalNameToken::GetString() const -{ - return maName; -} - bool ScExternalNameToken::operator==( const FormulaToken& r ) const { - if ( !FormulaToken::operator==(r) ) + if ( !ScExternalToken::operator==(r) ) return false; - if (mnFileId != r.GetIndex()) - return false; - - return maName == r.GetString(); + return maName == static_cast(r).maName; } ScTableRefToken::ScTableRefToken( sal_uInt16 nIndex, ScTableRefToken::Item eItem ) : @@ -903,15 +815,6 @@ void ScTableRefToken::SetIndex( sal_uInt16 n ) mnIndex = n; } -sal_Int16 ScTableRefToken::GetSheet() const -{ - // Code asking for this may have to be adapted as it might assume an - // svIndex token would always be ocName or ocDBArea. - SAL_WARN("sc.core","ScTableRefToken::GetSheet - maybe adapt caller to know about TableRef?"); - // Database range is always global. - return -1; -} - ScTableRefToken::Item ScTableRefToken::GetItem() const { return meItem; @@ -937,21 +840,19 @@ bool ScTableRefToken::operator==( const FormulaToken& r ) const if ( !FormulaToken::operator==(r) ) return false; - if (mnIndex != r.GetIndex()) + auto const & rhs = static_cast(r); + + if (mnIndex != rhs.GetIndex()) return false; - const ScTableRefToken* p = dynamic_cast(&r); - if (!p) + if (meItem != rhs.GetItem()) return false; - if (meItem != p->GetItem()) - return false; - - if (!mxAreaRefRPN && !p->mxAreaRefRPN) + if (!mxAreaRefRPN && !rhs.mxAreaRefRPN) ; // nothing - else if (!mxAreaRefRPN || !p->mxAreaRefRPN) + else if (!mxAreaRefRPN || !rhs.mxAreaRefRPN) return false; - else if (!(*mxAreaRefRPN == *(p->mxAreaRefRPN))) + else if (!(*mxAreaRefRPN == *(rhs.mxAreaRefRPN))) return false; return true; @@ -971,20 +872,14 @@ ScJumpMatrix* ScJumpMatrixToken::GetJumpMatrix() const bool ScJumpMatrixToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && mpJumpMatrix.get() == r.GetJumpMatrix(); + return FormulaToken::operator==( r ) + && mpJumpMatrix.get() == static_cast(r).GetJumpMatrix(); } ScJumpMatrixToken::~ScJumpMatrixToken() { } -double ScEmptyCellToken::GetDouble() const { return 0.0; } - -const svl::SharedString & ScEmptyCellToken::GetString() const -{ - return svl::SharedString::getEmptyString(); -} - bool ScEmptyCellToken::operator==( const FormulaToken& r ) const { return FormulaToken::operator==( r ) && @@ -997,22 +892,9 @@ ScMatrixCellResultToken::ScMatrixCellResultToken( ScConstMatrixRef pMat, const f ScMatrixCellResultToken::ScMatrixCellResultToken( const ScMatrixCellResultToken& ) = default; -double ScMatrixCellResultToken::GetDouble() const { return xUpperLeft->GetDouble(); } - ScMatrixCellResultToken::~ScMatrixCellResultToken() {} -const svl::SharedString & ScMatrixCellResultToken::GetString() const -{ - return xUpperLeft->GetString(); -} - const ScMatrix* ScMatrixCellResultToken::GetMatrix() const { return xMatrix.get(); } -// Non-const GetMatrix() is private and unused but must be implemented to -// satisfy vtable linkage. -ScMatrix* ScMatrixCellResultToken::GetMatrix() -{ - return const_cast(xMatrix.get()); -} bool ScMatrixCellResultToken::operator==( const FormulaToken& r ) const { @@ -1059,7 +941,13 @@ bool ScMatrixFormulaCellToken::operator==( const FormulaToken& r ) const void ScMatrixFormulaCellToken::CloneUpperLeftIfNecessary() { - if (xUpperLeft && xUpperLeft->GetType() == svDouble) + // Clone an svDouble because SetUpperLeftDouble changes it in place. Clone an + // uncounted token because storing it here would take no counted reference + // and leave the upper left dangling; this happens during threaded group + // calculation, when the group's pCode tokens are switched to + // RefCntPolicy::None. The clone is a normally reference-counted copy. + if (xUpperLeft && (xUpperLeft->GetType() == svDouble + || xUpperLeft->GetRefCntPolicy() == formula::RefCntPolicy::None)) xUpperLeft = xUpperLeft->Clone(); } @@ -1083,7 +971,7 @@ void ScMatrixFormulaCellToken::Assign( const formula::FormulaToken& r ) if (r.GetType() == svMatrix) { xUpperLeft = nullptr; - xMatrix = r.GetMatrix(); + xMatrix = static_cast(r).GetMatrix(); } else { @@ -1099,7 +987,7 @@ void ScMatrixFormulaCellToken::SetUpperLeftDouble( double f ) switch (GetUpperLeftType()) { case svDouble: - const_cast(xUpperLeft.get())->SetDouble(f); + static_cast(const_cast(xUpperLeft.get()))->SetDouble(f); break; case svString: xUpperLeft = new FormulaDoubleToken( f); @@ -1137,16 +1025,13 @@ ScHybridCellToken::ScHybridCellToken( double ScHybridCellToken::GetDouble() const { return mfDouble; } -const svl::SharedString & ScHybridCellToken::GetString() const -{ - return maString; -} - bool ScHybridCellToken::operator==( const FormulaToken& r ) const { - return FormulaToken::operator==( r ) && - mfDouble == r.GetDouble() && maString == r.GetString() && - maFormula == static_cast(r).GetFormula(); + if (!FormulaToken::operator==( r )) + return false; + auto const & rhs = static_cast(r); + return mfDouble == rhs.GetDouble() && maString == rhs.GetString() && + maFormula == rhs.GetFormula(); } bool ScTokenArray::AddFormulaToken( @@ -1327,6 +1212,7 @@ void ScTokenArray::CheckForThreading( const FormulaToken& r ) constinit #endif static const o3tl::sorted_vector aThreadedCalcDenyList({ + ocCall, ocIndirect, ocMacro, ocOffset, @@ -1350,9 +1236,11 @@ void ScTokenArray::CheckForThreading( const FormulaToken& r ) ocText, ocSheet, ocExternal, + ocUDExternal, ocDde, ocWebservice, - ocGetPivotData + ocGetPivotData, + ocSpill }); // Don't enable threading once we decided to disable it. @@ -1405,7 +1293,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r ) OpCode eOp = r.GetOpCode(); - if (SC_OPCODE_START_FUNCTION <= eOp && eOp < SC_OPCODE_STOP_FUNCTION) + if (ocStartFunction <= eOp && eOp < ocStopFunction) { if (ScInterpreter::GetGlobalConfig().mbOpenCLSubsetOnly && ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->end()) @@ -1638,6 +1526,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r ) // Depends on the reference state. meVectorState = FormulaVectorCheckReference; break; + case svCallable: case svError: case svEmptyCell: case svExternal: @@ -1664,7 +1553,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r ) ; } } - else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP) + else if (isBinaryOperatorOpCode(eOp) || isUnaryOperatorOpCode(eOp)) { if (ScInterpreter::GetGlobalConfig().mbOpenCLSubsetOnly && ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->end()) @@ -1714,6 +1603,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r ) // Known good, don't change state. case ocStop: case ocExternal: + case ocUDExternal: case ocOpen: case ocClose: case ocSep: @@ -1740,6 +1630,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r ) case ocIfNA: case ocChoose: case ocLet: + case ocLambda: // Jump commands are now supported. break; } @@ -1756,13 +1647,13 @@ bool ScTokenArray::ImplGetReference( ScRange& rRange, const ScAddress& rPos, boo { if ( pToken->GetType() == svSingleRef ) { - const ScSingleRefData& rRef = *static_cast(pToken)->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef(); rRange.aStart = rRange.aEnd = rRef.toAbs(*mxSheetLimits, rPos); bIs = !bValidOnly || mxSheetLimits->ValidAddress(rRange.aStart); } else if ( pToken->GetType() == svDoubleRef ) { - const ScComplexRefData& rCompl = *static_cast(pToken)->GetDoubleRef(); + const ScComplexRefData& rCompl = static_cast(pToken)->GetDoubleRef(); const ScSingleRefData& rRef1 = rCompl.Ref1; const ScSingleRefData& rRef2 = rCompl.Ref2; rRange.aStart = rRef1.toAbs(*mxSheetLimits, rPos); @@ -1813,33 +1704,33 @@ void ScTokenArray::GenHash() case svByte: { // Constant value. - sal_uInt8 nVal = p->GetByte(); + sal_uInt8 nVal = static_cast(p)->GetByte(); nHash += static_cast(nVal); } break; case svDouble: { // Constant value. - double fVal = p->GetDouble(); + double fVal = static_cast(p)->GetDouble(); nHash += std::hash()(fVal); } break; case svString: { // Constant string. - OUString aStr = p->GetString().getString(); + OUString aStr = static_cast(p)->GetString().getString(); nHash += aHasher(aStr); } break; case svSingleRef: { - size_t nVal = HashSingleRef(*p->GetSingleRef()); + size_t nVal = HashSingleRef(static_cast(p)->GetSingleRef()); nHash += nVal; } break; case svDoubleRef: { - const ScComplexRefData& rRef = *p->GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); size_t nVal1 = HashSingleRef(rRef.Ref1); size_t nVal2 = HashSingleRef(rRef.Ref2); nHash += nVal1; @@ -1893,17 +1784,29 @@ bool ScTokenArray::IsInvariant() const switch ((*p)->GetType()) { case svSingleRef: + { + const ScSingleRefData& rRef = static_cast(*p)->GetSingleRef(); + if (rRef.IsRowRel()) + return false; + } + break; case svExternalSingleRef: { - const ScSingleRefData& rRef = *(*p)->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(*p)->GetSingleRef(); if (rRef.IsRowRel()) return false; } break; case svDoubleRef: + { + const ScComplexRefData& rRef = static_cast(*p)->GetDoubleRef(); + if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel()) + return false; + } + break; case svExternalDoubleRef: { - const ScComplexRefData& rRef = *(*p)->GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(*p)->GetDoubleRef(); if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel()) return false; } @@ -2006,6 +1909,7 @@ std::unique_ptr ScTokenArray::Clone() const p->mbThreadingEnabled = mbThreadingEnabled; p->mbFromRangeName = mbFromRangeName; p->mbShareable = mbShareable; + p->mbDynamicArrayFunction = mbDynamicArrayFunction; FormulaToken** pp; if( nLen ) @@ -2018,11 +1922,15 @@ std::unique_ptr ScTokenArray::Clone() const *pp = (*pp)->Clone(); (*pp)->IncRef(); } + // pCode is sized to exactly nLen here, so the array is already at its minimum size; mark it + // so that a later Add() reallocates instead of writing past the end: + p->mbFinalized = true; } if( nRPN ) { - pp = p->pRPN = new FormulaToken*[ nRPN ]; - memcpy( pp, pRPN, nRPN * sizeof( formula::FormulaToken* ) ); + p->pRPN = std::make_unique(nRPN); + pp = p->pRPN.get(); + memcpy( pp, pRPN.get(), nRPN * sizeof( formula::FormulaToken* ) ); for( sal_uInt16 i = 0; i < nRPN; i++, pp++ ) { FormulaToken* t = *pp; @@ -2064,6 +1972,7 @@ ScTokenArray ScTokenArray::CloneValue() const aNew.mbThreadingEnabled = mbThreadingEnabled; aNew.mbFromRangeName = mbFromRangeName; aNew.mbShareable = mbShareable; + aNew.mbDynamicArrayFunction = mbDynamicArrayFunction; FormulaToken** pp; if( nLen ) @@ -2076,11 +1985,15 @@ ScTokenArray ScTokenArray::CloneValue() const *pp = (*pp)->Clone(); (*pp)->IncRef(); } + // pCode is sized to exactly nLen here, so the array is already at its minimum size; mark it + // so that a later Add() reallocates instead of writing past the end: + aNew.mbFinalized = true; } if( nRPN ) { - pp = aNew.pRPN = new FormulaToken*[ nRPN ]; - memcpy( pp, pRPN, nRPN * sizeof( formula::FormulaToken* ) ); + aNew.pRPN = std::make_unique(nRPN); + pp = aNew.pRPN.get(); + memcpy( pp, pRPN.get(), nRPN * sizeof( formula::FormulaToken* ) ); for( sal_uInt16 i = 0; i < nRPN; i++, pp++ ) { FormulaToken* t = *pp; @@ -2254,12 +2167,12 @@ FormulaToken* ScTokenArray::MergeArray( ) case ocPush : if ( t->GetType() == svDouble ) { - pArray->PutDouble( t->GetDouble() * nSign, nCol, nRow ); + pArray->PutDouble( static_cast(t)->GetDouble() * nSign, nCol, nRow ); nSign = 1; } else if ( t->GetType() == svString ) { - pArray->PutString(t->GetString(), nCol, nRow); + pArray->PutString(static_cast(t)->GetString(), nCol, nRow); } break; @@ -2443,7 +2356,7 @@ bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend, FormulaToken* t = pRPN[nRPN-1]; if ( t->GetType() == svByte ) { - sal_uInt8 nParamCount = t->GetByte(); + sal_uInt8 nParamCount = static_cast(t)->GetByte(); if ( nParamCount && nRPN > nParamCount ) { bool bRet = false; @@ -2455,7 +2368,7 @@ bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend, { case svSingleRef : { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rPos); switch ( eDir ) { @@ -2492,7 +2405,7 @@ bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend, break; case svDoubleRef : { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rPos); switch ( eDir ) { @@ -2570,14 +2483,17 @@ bool SkipReference(formula::FormulaToken* pToken, const ScAddress& rPos, const S { case svDoubleRef: { - ScSingleRefData& rRef = *pToken->GetSingleRef2(); + ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef2(); if (rRef.IsColRel() || rRef.IsRowRel()) return true; + ScSingleRefData& rRef1 = static_cast(pToken)->GetSingleRef(); + if (rRef1.IsColRel() || rRef1.IsRowRel()) + return true; } - [[fallthrough]]; + break; case svSingleRef: { - ScSingleRefData& rRef = *pToken->GetSingleRef(); + ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef(); if (rRef.IsColRel() || rRef.IsRowRel()) return true; } @@ -2622,7 +2538,7 @@ void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument& rOldDoc, ScDo if (SkipReference(pCode[j], rPos, rOldDoc, bRangeName, true)) continue; - ScComplexRefData& rRef = *pCode[j]->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(pCode[j])->GetDoubleRef(); ScSingleRefData& rRef2 = rRef.Ref2; ScSingleRefData& rRef1 = rRef.Ref1; @@ -2642,7 +2558,7 @@ void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument& rOldDoc, ScDo if (SkipReference(pCode[j], rPos, rOldDoc, bRangeName, true)) continue; - ScSingleRefData& rRef = *pCode[j]->GetSingleRef(); + ScSingleRefData& rRef = static_cast(pCode[j])->GetSingleRef(); if ( rRef.IsFlag3D() && !rRef.IsTabRel() ) { @@ -2666,7 +2582,7 @@ void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument& rOldDoc, ScDo void ScTokenArray::AdjustAbsoluteRefs( const ScDocument& rOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCheckCopyRange) { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN, true); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN, true); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -2684,7 +2600,7 @@ void ScTokenArray::AdjustAbsoluteRefs( const ScDocument& rOldDoc, const ScAddres if (!SkipReference(p, rOldPos, rOldDoc, false, bCheckCopyRange)) continue; - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScSingleRefData& rRef2 = rRef.Ref2; ScSingleRefData& rRef1 = rRef.Ref1; @@ -2697,7 +2613,7 @@ void ScTokenArray::AdjustAbsoluteRefs( const ScDocument& rOldDoc, const ScAddres if (!SkipReference(p, rOldPos, rOldDoc, false, bCheckCopyRange)) continue; - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); AdjustSingleRefData( rRef, rOldPos, rNewPos ); } @@ -2711,9 +2627,61 @@ void ScTokenArray::AdjustAbsoluteRefs( const ScDocument& rOldDoc, const ScAddres } } +namespace +{ + +void adjustRelativeTabRef(ScSingleRefData& rRef, SCTAB nOldTab, SCTAB nNewTab, bool bInsertedTab) +{ + if (!rRef.IsTabRel() || rRef.Tab() == 0) + return; + SCTAB nAbsTarget = nOldTab + rRef.Tab(); + if (bInsertedTab && nAbsTarget >= nNewTab) + nAbsTarget++; + SCTAB nNewOffset = nAbsTarget - nNewTab; + rRef.IncTab(nNewOffset - rRef.Tab()); +} + +} // anonymous namespace + +void ScTokenArray::AdjustRelativeTabRefs(SCTAB nOldTab, SCTAB nNewTab, sc::TargetTabState eMode) +{ + const bool bInsertedTab = (eMode == sc::TargetTabState::Inserted); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN, true); + for (size_t j=0; j<2; ++j) + { + FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; + FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop; + for (; pp != pEnd; ++pp) + { + FormulaToken* p = aPtrs.getHandledToken(j,pp); + if (!p) + continue; + + switch ( p->GetType() ) + { + case svDoubleRef: + { + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); + adjustRelativeTabRef(rRef.Ref1, nOldTab, nNewTab, bInsertedTab); + adjustRelativeTabRef(rRef.Ref2, nOldTab, nNewTab, bInsertedTab); + break; + } + case svSingleRef: + { + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); + adjustRelativeTabRef(rRef, nOldTab, nNewTab, bInsertedTab); + break; + } + default: + break; + } + } + } +} + void ScTokenArray::AdjustSheetLocalNameReferences( SCTAB nOldTab, SCTAB nNewTab ) { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN, false); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN, false); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -2728,7 +2696,7 @@ void ScTokenArray::AdjustSheetLocalNameReferences( SCTAB nOldTab, SCTAB nNewTab { case svDoubleRef : { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScSingleRefData& rRef2 = rRef.Ref2; ScSingleRefData& rRef1 = rRef.Ref1; @@ -2746,7 +2714,7 @@ void ScTokenArray::AdjustSheetLocalNameReferences( SCTAB nOldTab, SCTAB nNewTab break; case svSingleRef : { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); if (!rRef.IsTabRel() && rRef.Tab() == nOldTab) rRef.SetAbsTab( nNewTab); @@ -2761,7 +2729,7 @@ void ScTokenArray::AdjustSheetLocalNameReferences( SCTAB nOldTab, SCTAB nNewTab bool ScTokenArray::ReferencesSheet( SCTAB nTab, SCTAB nPosTab ) const { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN, false); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN, false); for (size_t j=0; j<2; ++j) { FormulaToken* const * pp = aPtrs.maPointerRange[j].mpStart; @@ -2776,7 +2744,7 @@ bool ScTokenArray::ReferencesSheet( SCTAB nTab, SCTAB nPosTab ) const { case svDoubleRef : { - const ScComplexRefData& rRef = *p->GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); const ScSingleRefData& rRef2 = rRef.Ref2; const ScSingleRefData& rRef1 = rRef.Ref1; @@ -2788,7 +2756,7 @@ bool ScTokenArray::ReferencesSheet( SCTAB nTab, SCTAB nPosTab ) const break; case svSingleRef : { - const ScSingleRefData& rRef = *p->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); if (rRef.IsTabRel()) { if (rRef.Tab() + nPosTab == nTab) @@ -3174,7 +3142,7 @@ bool expandRangeByEdge( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, co return false; } -bool isNameModified( const sc::UpdatedRangeNames& rUpdatedNames, SCTAB nOldTab, const formula::FormulaToken& rToken ) +bool isNameModified( const sc::UpdatedRangeNames& rUpdatedNames, SCTAB nOldTab, const FormulaIndexToken& rToken ) { SCTAB nTab = -1; if (rToken.GetSheet() >= 0) @@ -3186,8 +3154,17 @@ bool isNameModified( const sc::UpdatedRangeNames& rUpdatedNames, SCTAB nOldTab, bool isDBDataModified( const ScDocument& rDoc, const formula::FormulaToken& rToken ) { + auto nOpCode = rToken.GetOpCode(); + sal_uInt16 nIndex; + if (nOpCode == ocDBArea) + nIndex = static_cast(rToken).GetIndex(); + else + { + assert(nOpCode == ocTableRef); + nIndex = static_cast(rToken).GetIndex(); + } // Check if this DBData has been modified. - const ScDBData* pDBData = rDoc.GetDBCollection()->getNamedDBs().findByIndex( rToken.GetIndex()); + const ScDBData* pDBData = rDoc.GetDBCollection()->getNamedDBs().findByIndex( nIndex); if (!pDBData) return true; @@ -3196,6 +3173,23 @@ bool isDBDataModified( const ScDocument& rDoc, const formula::FormulaToken& rTok } +namespace { + +void lcl_accumulateRefError(sc::RefErrorContext& rCtx, const ScAddress& rFormulaPos, + bool bOldError, bool bNewError) +{ + if (bOldError || !bNewError) + return; + + if (!rCtx.mbErrorCreated) + { + rCtx.mbErrorCreated = true; + rCtx.maFormulaCell = rFormulaPos; + } +} + +} + sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos ) { ScRange aSelectedRange = getSelectedRange(rCxt); @@ -3212,7 +3206,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon } } - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -3227,14 +3221,16 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon { case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); if (rCxt.isDeleted() && aSelectedRange.Contains(aAbs)) { + bool bOldError = rRef.IsDeleted(); // This reference is in the deleted region. setRefDeleted(rRef, rCxt); aRes.mbValueChanged = true; + lcl_accumulateRefError(rCxt.maRefErrors, aNewPos, bOldError, rRef.IsDeleted()); break; } @@ -3263,20 +3259,24 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); if (rCxt.isDeleted()) { if (aSelectedRange.Contains(aAbs)) { + bool bOldError = rRef.Ref1.IsDeleted() || rRef.Ref2.IsDeleted(); // This reference is in the deleted region. setRefDeleted(rRef, rCxt); aRes.mbValueChanged = true; + bool bNewError = rRef.Ref1.IsDeleted() || rRef.Ref2.IsDeleted(); + lcl_accumulateRefError(rCxt.maRefErrors, aNewPos, bOldError, bNewError); break; } else if (aSelectedRange.Intersects(aAbs)) { + bool bOldError = rRef.Ref1.IsDeleted() || rRef.Ref2.IsDeleted(); const ShrinkResult eSR = shrinkRange(rCxt, aAbs, aSelectedRange, rRef); if (eSR == SHRUNK) { @@ -3284,6 +3284,11 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon rRef.SetRange(*mxSheetLimits, aAbs, aNewPos); aRes.mbValueChanged = true; aRes.mbReferenceModified = true; + // shrinkRange may have set the range invalid if it + // was fully covered in col+row but not in tab (3D + // refs, partial-tab delete). Treat that as #REF!. + bool bNewError = rRef.Ref1.IsDeleted() || rRef.Ref2.IsDeleted() || !aAbs.IsValid(); + lcl_accumulateRefError(rCxt.maRefErrors, aNewPos, bOldError, bNewError); break; } else if (eSR == STICKY) @@ -3376,7 +3381,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon { // For external reference, just reset the reference with // respect to the new cell position. - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); rRef.SetAddress(*mxSheetLimits, aAbs, aNewPos); } @@ -3384,7 +3389,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon case svExternalDoubleRef: { // Same as above. - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); rRef.SetRange(*mxSheetLimits, aAbs, aNewPos); } @@ -3401,14 +3406,15 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon { case ocName: { - SCTAB nOldTab = (*pp)->GetSheet(); - if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp)) + auto pIToken = static_cast(*pp); + SCTAB nOldTab = pIToken->GetSheet(); + if (isNameModified(rCxt.maUpdatedNames, nOldTab, *pIToken)) aRes.mbNameModified = true; if (rCxt.mnTabDelta && rCxt.maRange.aStart.Tab() <= nOldTab && nOldTab <= rCxt.maRange.aEnd.Tab()) { aRes.mbNameModified = true; - (*pp)->SetSheet( nOldTab + rCxt.mnTabDelta); + static_cast(*pp)->SetSheet( nOldTab + rCxt.mnTabDelta); } } break; @@ -3445,7 +3451,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove( assert(!"can't move"); } - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -3460,7 +3466,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove( { case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); // Do not update the reference in transposed case (cut paste transposed). @@ -3490,7 +3496,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove( break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); // Do not update the reference in transposed case (cut paste transposed). @@ -3546,14 +3552,14 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove( break; case svExternalSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); rRef.SetAddress(*mxSheetLimits, aAbs, rNewPos); } break; case svExternalDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); rRef.SetRange(*mxSheetLimits, aAbs, rNewPos); } @@ -3570,8 +3576,9 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove( { case ocName: { - SCTAB nOldTab = (*pp)->GetSheet(); - if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp)) + auto pIToken = static_cast(*pp); + SCTAB nOldTab = pIToken->GetSheet(); + if (isNameModified(rCxt.maUpdatedNames, nOldTab, *pIToken)) aRes.mbNameModified = true; } break; @@ -3593,7 +3600,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove( void ScTokenArray::MoveReferenceColReorder( const ScAddress& rPos, SCTAB nTab, SCROW nRow1, SCROW nRow2, const sc::ColRowReorderMapType& rColMap ) { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -3608,7 +3615,7 @@ void ScTokenArray::MoveReferenceColReorder( { case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rPos); if (aAbs.Tab() == nTab && nRow1 <= aAbs.Row() && aAbs.Row() <= nRow2) @@ -3627,7 +3634,7 @@ void ScTokenArray::MoveReferenceColReorder( break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rPos); if (aAbs.aStart.Tab() != aAbs.aEnd.Tab()) @@ -3662,7 +3669,7 @@ void ScTokenArray::MoveReferenceColReorder( void ScTokenArray::MoveReferenceRowReorder( const ScAddress& rPos, SCTAB nTab, SCCOL nCol1, SCCOL nCol2, const sc::ColRowReorderMapType& rRowMap ) { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -3677,7 +3684,7 @@ void ScTokenArray::MoveReferenceRowReorder( const ScAddress& rPos, SCTAB nTab, S { case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rPos); if (aAbs.Tab() == nTab && nCol1 <= aAbs.Col() && aAbs.Col() <= nCol2) @@ -3696,7 +3703,7 @@ void ScTokenArray::MoveReferenceRowReorder( const ScAddress& rPos, SCTAB nTab, S break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rPos); if (aAbs.aStart.Tab() != aAbs.aEnd.Tab()) @@ -3889,7 +3896,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInName( // Copying cells does not modify named expressions. return aRes; - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -3904,7 +3911,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInName( { case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); if (rCxt.mnRowDelta < 0) { // row(s) deleted. @@ -3970,7 +3977,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInName( break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(rCxt.mrDoc, rPos); if (aAbs.aStart.Tab() > rCxt.maRange.aEnd.Tab() || aAbs.aEnd.Tab() < rCxt.maRange.aStart.Tab()) @@ -4164,7 +4171,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdat sc::RefUpdateResult aRes; - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -4179,7 +4186,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdat { case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); if (rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel()) continue; @@ -4203,7 +4210,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdat break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); if (rRef.Ref1.IsColRel() || rRef.Ref1.IsRowRel() || rRef.Ref1.IsTabRel() || rRef.Ref2.IsColRel() || rRef.Ref2.IsRowRel() || rRef.Ref2.IsTabRel()) continue; @@ -4327,7 +4334,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnDeletedTab( const sc::RefUpda ScAddress aNewPos = rOldPos; ScRangeUpdater::UpdateDeleteTab( aNewPos, rCxt); - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -4342,15 +4349,24 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnDeletedTab( const sc::RefUpda { case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); + bool bOldError = rRef.IsTabDeleted(); + if (adjustSingleRefOnDeletedTab(*mxSheetLimits, rRef, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos)) aRes.mbReferenceModified = true; + + lcl_accumulateRefError(rCxt.maRefErrors, aNewPos, bOldError, rRef.IsTabDeleted()); } break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); + bool bOldError = rRef.Ref1.IsTabDeleted() || rRef.Ref2.IsTabDeleted(); + aRes.mbReferenceModified |= adjustDoubleRefOnDeleteTab(*mxSheetLimits, rRef, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos); + + bool bNewError = rRef.Ref1.IsTabDeleted() || rRef.Ref2.IsTabDeleted(); + lcl_accumulateRefError(rCxt.maRefErrors, aNewPos, bOldError, bNewError); } break; default: @@ -4365,17 +4381,18 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnDeletedTab( const sc::RefUpda { case ocName: { - SCTAB nOldTab = (*pp)->GetSheet(); - if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp)) + auto pIToken = static_cast(*pp); + SCTAB nOldTab = pIToken->GetSheet(); + if (isNameModified(rCxt.maUpdatedNames, nOldTab, *pIToken)) aRes.mbNameModified = true; if (rCxt.mnDeletePos <= nOldTab) { aRes.mbNameModified = true; if (rCxt.mnDeletePos + rCxt.mnSheets <= nOldTab) - (*pp)->SetSheet( nOldTab - rCxt.mnSheets); + static_cast(*pp)->SetSheet( nOldTab - rCxt.mnSheets); else // Would point to a deleted sheet. Invalidate. - (*pp)->SetSheet( SCTAB_MAX); + static_cast(*pp)->SetSheet( SCTAB_MAX); } } break; @@ -4400,7 +4417,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnInsertedTab( const sc::RefUpd if (rCxt.mnInsertPos <= rOldPos.Tab()) aNewPos.IncTab(rCxt.mnSheets); - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -4415,14 +4432,14 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnInsertedTab( const sc::RefUpd { case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); if (adjustSingleRefOnInsertedTab(*mxSheetLimits, rRef, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos)) aRes.mbReferenceModified = true; } break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); if (adjustSingleRefOnInsertedTab(*mxSheetLimits, rRef.Ref1, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos)) aRes.mbReferenceModified = true; if (adjustSingleRefOnInsertedTab(*mxSheetLimits, rRef.Ref2, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos)) @@ -4441,13 +4458,14 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnInsertedTab( const sc::RefUpd { case ocName: { - SCTAB nOldTab = (*pp)->GetSheet(); - if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp)) + auto pIToken = static_cast(*pp); + SCTAB nOldTab = pIToken->GetSheet(); + if (isNameModified(rCxt.maUpdatedNames, nOldTab, *pIToken)) aRes.mbNameModified = true; if (rCxt.mnInsertPos <= nOldTab) { aRes.mbNameModified = true; - (*pp)->SetSheet( nOldTab + rCxt.mnSheets); + pIToken->SetSheet( nOldTab + rCxt.mnSheets); } } break; @@ -4493,7 +4511,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( const sc::RefUpdate aRes.mnTab = aNewPos.Tab(); // this sets the new tab position used when deleting } - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -4508,7 +4526,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( const sc::RefUpdate { case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); if (adjustTabOnMove(aAbs, rCxt)) aRes.mbReferenceModified = true; @@ -4517,7 +4535,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( const sc::RefUpdate break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); if (adjustTabOnMove(aAbs.aStart, rCxt)) aRes.mbReferenceModified = true; @@ -4538,14 +4556,15 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( const sc::RefUpdate { case ocName: { - SCTAB nOldTab = (*pp)->GetSheet(); - if (isNameModified(rCxt.maUpdatedNames, nOldTab, **pp)) + auto pIToken = static_cast(*pp); + SCTAB nOldTab = pIToken->GetSheet(); + if (isNameModified(rCxt.maUpdatedNames, nOldTab, *pIToken)) aRes.mbNameModified = true; SCTAB nNewTab = rCxt.getNewTab( nOldTab); if (nNewTab != nOldTab) { aRes.mbNameModified = true; - (*pp)->SetSheet( nNewTab); + pIToken->SetSheet( nNewTab); } } break; @@ -4566,7 +4585,7 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( const sc::RefUpdate void ScTokenArray::AdjustReferenceOnMovedOrigin( const ScAddress& rOldPos, const ScAddress& rNewPos ) { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -4580,17 +4599,29 @@ void ScTokenArray::AdjustReferenceOnMovedOrigin( const ScAddress& rOldPos, const switch (p->GetType()) { case svSingleRef: + { + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); + ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); + rRef.SetAddress(*mxSheetLimits, aAbs, rNewPos); + } + break; case svExternalSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); rRef.SetAddress(*mxSheetLimits, aAbs, rNewPos); } break; case svDoubleRef: + { + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); + ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); + rRef.SetRange(*mxSheetLimits, aAbs, rNewPos); + } + break; case svExternalDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); rRef.SetRange(*mxSheetLimits, aAbs, rNewPos); } @@ -4604,7 +4635,7 @@ void ScTokenArray::AdjustReferenceOnMovedOrigin( const ScAddress& rOldPos, const void ScTokenArray::AdjustReferenceOnMovedOriginIfOtherSheet( const ScAddress& rOldPos, const ScAddress& rNewPos ) { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -4615,31 +4646,36 @@ void ScTokenArray::AdjustReferenceOnMovedOriginIfOtherSheet( const ScAddress& rO if (!p) continue; - bool bAdjust = false; switch (p->GetType()) { case svExternalSingleRef: - bAdjust = true; // always - [[fallthrough]]; + { + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); + ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); + rRef.SetAddress(*mxSheetLimits, aAbs, rNewPos); + } + break; case svSingleRef: { - ScSingleRefData& rRef = *p->GetSingleRef(); + ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); - if (!bAdjust) - bAdjust = (aAbs.Tab() != rOldPos.Tab()); + bool bAdjust = (aAbs.Tab() != rOldPos.Tab()); if (bAdjust) rRef.SetAddress(*mxSheetLimits, aAbs, rNewPos); } break; case svExternalDoubleRef: - bAdjust = true; // always - [[fallthrough]]; + { + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); + ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); + rRef.SetRange(*mxSheetLimits, aAbs, rNewPos); + } + break; case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rOldPos); - if (!bAdjust) - bAdjust = (rOldPos.Tab() < aAbs.aStart.Tab() || aAbs.aEnd.Tab() < rOldPos.Tab()); + bool bAdjust = (rOldPos.Tab() < aAbs.aStart.Tab() || aAbs.aEnd.Tab() < rOldPos.Tab()); if (bAdjust) rRef.SetRange(*mxSheetLimits, aAbs, rNewPos); } @@ -4653,7 +4689,7 @@ void ScTokenArray::AdjustReferenceOnMovedOriginIfOtherSheet( const ScAddress& rO void ScTokenArray::AdjustReferenceOnCopy( const ScAddress& rNewPos ) { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN, false); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN, false); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -4668,7 +4704,7 @@ void ScTokenArray::AdjustReferenceOnCopy( const ScAddress& rNewPos ) { case svDoubleRef: { - ScComplexRefData& rRef = *p->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); rRef.PutInOrder( rNewPos); } break; @@ -4707,14 +4743,14 @@ void ScTokenArray::ClearTabDeleted( const ScAddress& rPos, SCTAB nStartTab, SCTA case svSingleRef: { formula::FormulaToken* pToken = *p; - ScSingleRefData& rRef = *pToken->GetSingleRef(); + ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef(); clearTabDeletedFlag(*mxSheetLimits, rRef, rPos, nStartTab, nEndTab); } break; case svDoubleRef: { - formula::FormulaToken* pToken = *p; - ScComplexRefData& rRef = *pToken->GetDoubleRef(); + auto pToken = static_cast(*p); + ScComplexRefData& rRef = pToken->GetDoubleRef(); clearTabDeletedFlag(*mxSheetLimits, rRef.Ref1, rPos, nStartTab, nEndTab); clearTabDeletedFlag(*mxSheetLimits, rRef.Ref2, rPos, nStartTab, nEndTab); } @@ -4836,7 +4872,7 @@ void checkBounds( void ScTokenArray::CheckRelativeReferenceBounds( const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector& rBounds ) const { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -4851,12 +4887,12 @@ void ScTokenArray::CheckRelativeReferenceBounds( { case svSingleRef: { - checkBounds(rCxt, rPos, nGroupLen, *p->GetSingleRef(), rBounds); + checkBounds(rCxt, rPos, nGroupLen, static_cast(p)->GetSingleRef(), rBounds); } break; case svDoubleRef: { - const ScComplexRefData& rRef = *p->GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); checkBounds(rCxt, rPos, nGroupLen, rRef.Ref1, rBounds); checkBounds(rCxt, rPos, nGroupLen, rRef.Ref2, rBounds); } @@ -4871,7 +4907,7 @@ void ScTokenArray::CheckRelativeReferenceBounds( void ScTokenArray::CheckRelativeReferenceBounds( const ScAddress& rPos, SCROW nGroupLen, const ScRange& rRange, std::vector& rBounds ) const { - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken** pp = aPtrs.maPointerRange[j].mpStart; @@ -4886,13 +4922,13 @@ void ScTokenArray::CheckRelativeReferenceBounds( { case svSingleRef: { - const ScSingleRefData& rRef = *p->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef, rBounds, nullptr); } break; case svDoubleRef: { - const ScComplexRefData& rRef = *p->GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef.Ref1, rBounds, nullptr); checkBounds(*mxSheetLimits, rPos, nGroupLen, rRange, rRef.Ref2, rBounds, nullptr); } @@ -4908,7 +4944,7 @@ void ScTokenArray::CheckExpandReferenceBounds( const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector& rBounds ) const { const SCROW nInsRow = rCxt.maRange.aStart.Row(); - TokenPointers aPtrs( pCode.get(), nLen, pRPN, nRPN); + TokenPointers aPtrs( pCode.get(), nLen, pRPN.get(), nRPN); for (size_t j=0; j<2; ++j) { FormulaToken* const * pp = aPtrs.maPointerRange[j].mpStart; @@ -4923,7 +4959,7 @@ void ScTokenArray::CheckExpandReferenceBounds( { case svDoubleRef: { - const ScComplexRefData& rRef = *p->GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(p)->GetDoubleRef(); bool bStartRowRelative = rRef.Ref1.IsRowRel(); bool bEndRowRelative = rRef.Ref2.IsRowRel(); @@ -5035,8 +5071,7 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU { if (rToken.IsExternalRef()) { - size_t nFileId = rToken.GetIndex(); - OUString aTabName = rToken.GetString().getString(); + size_t nFileId = static_cast(rToken).GetFileId(); if (nFileId >= rCxt.maExternalFileNames.size()) // out of bound return; @@ -5046,11 +5081,17 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU switch (rToken.GetType()) { case svExternalName: + { + OUString aTabName = static_cast(rToken).GetName().getString(); rBuf.append(rCxt.mpRefConv->makeExternalNameStr(nFileId, aFileName, aTabName)); + } break; case svExternalSingleRef: + { + OUString aTabName = static_cast(rToken).GetTableName().getString(); rCxt.mpRefConv->makeExternalRefStr( - rLimits, rBuf, rPos, nFileId, aFileName, aTabName, *rToken.GetSingleRef()); + rLimits, rBuf, rPos, nFileId, aFileName, aTabName, static_cast(rToken).GetSingleRef()); + } break; case svExternalDoubleRef: { @@ -5060,9 +5101,10 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU if (it == rCxt.maExternalCachedTabNames.end()) return; + OUString aTabName = static_cast(rToken).GetTableName().getString(); rCxt.mpRefConv->makeExternalRefStr( rLimits, rBuf, rPos, nFileId, aFileName, it->second, aTabName, - *rToken.GetDoubleRef()); + static_cast(rToken).GetDoubleRef()); } break; default: @@ -5077,11 +5119,11 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU switch (rToken.GetType()) { case svDouble: - appendDouble(rCxt, rBuf, rToken.GetDouble()); + appendDouble(rCxt, rBuf, static_cast(rToken).GetDouble()); break; case svString: { - OUString aStr = rToken.GetString().getString(); + OUString aStr = static_cast(rToken).GetString().getString(); if (eOp == ocBad || eOp == ocStringXML || eOp == ocStringName || eOp == ocDPFieldName) { rBuf.append(aStr); @@ -5095,7 +5137,7 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU { if (rCxt.mpRefConv) { - const ScSingleRefData& rRef = *rToken.GetSingleRef(); + const ScSingleRefData& rRef = static_cast(rToken).GetSingleRef(); ScComplexRefData aRef; aRef.Ref1 = rRef; aRef.Ref2 = rRef; @@ -5110,7 +5152,7 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU { if (rCxt.mpRefConv) { - const ScComplexRefData& rRef = *rToken.GetDoubleRef(); + const ScComplexRefData& rRef = static_cast(rToken).GetDoubleRef(); rCxt.mpRefConv->makeRefStr(rLimits, rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, rRef, false, bFromRangeName); } @@ -5120,7 +5162,7 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU break; case svMatrix: { - const ScMatrix* pMat = rToken.GetMatrix(); + const ScMatrix* pMat = static_cast(rToken).GetMatrix(); if (!pMat) return; @@ -5173,12 +5215,13 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU { typedef sc::TokenStringContext::IndexNameMapType NameType; - sal_uInt16 nIndex = rToken.GetIndex(); switch (eOp) { case ocName: { - SCTAB nTab = rToken.GetSheet(); + const auto & rIndexToken = static_cast(rToken); + sal_uInt16 nIndex = rIndexToken.GetIndex(); + SCTAB nTab = rIndexToken.GetSheet(); if (nTab < 0) { // global named range @@ -5230,8 +5273,18 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU } break; case ocDBArea: + { + const auto & rIndexToken = static_cast(rToken); + sal_uInt16 nIndex = rIndexToken.GetIndex(); + NameType::const_iterator it = rCxt.maNamedDBs.find(nIndex); + if (it != rCxt.maNamedDBs.end()) + rBuf.append(it->second); + } + break; case ocTableRef: { + const auto & rTRToken = static_cast(rToken); + sal_uInt16 nIndex = rTRToken.GetIndex(); NameType::const_iterator it = rCxt.maNamedDBs.find(nIndex); if (it != rCxt.maNamedDBs.end()) rBuf.append(it->second); @@ -5245,7 +5298,7 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU case svExternal: { // mapped or translated name of AddIns - OUString aAddIn = rToken.GetExternal(); + OUString aAddIn = static_cast(rToken).GetExternal(); bool bMapped = rCxt.mxOpCodeMap->isPODF(); // ODF 1.1 directly uses programmatical name if (!bMapped && rCxt.mxOpCodeMap->hasExternals()) { @@ -5266,7 +5319,7 @@ void appendTokenByType( ScSheetLimits& rLimits, sc::TokenStringContext& rCxt, OU break; case svError: { - FormulaError nErr = rToken.GetError(); + FormulaError nErr = static_cast(rToken).GetError(); OpCode eOpErr; switch (nErr) { @@ -5329,7 +5382,7 @@ OUString ScTokenArray::CreateString( sc::TokenStringContext& rCxt, const ScAddre } else if (eOp == ocWhitespace) { - aBuf.append( pToken->GetChar()); + aBuf.append( static_cast(pToken)->GetChar()); continue; } @@ -5396,7 +5449,7 @@ void ScTokenArray::WrapReference( const ScAddress& rPos, SCCOL nMaxCol, SCROW nM case svSingleRef: { formula::FormulaToken* pToken = *p; - ScSingleRefData& rRef = *pToken->GetSingleRef(); + ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef(); ScAddress aAbs = rRef.toAbs(*mxSheetLimits, rPos); wrapAddress(aAbs, nMaxCol, nMaxRow); rRef.SetAddress(*mxSheetLimits, aAbs, rPos); @@ -5405,7 +5458,7 @@ void ScTokenArray::WrapReference( const ScAddress& rPos, SCCOL nMaxCol, SCROW nM case svDoubleRef: { formula::FormulaToken* pToken = *p; - ScComplexRefData& rRef = *pToken->GetDoubleRef(); + ScComplexRefData& rRef = static_cast(pToken)->GetDoubleRef(); ScRange aAbs = rRef.toAbs(*mxSheetLimits, rPos); // Entire columns/rows are sticky. if (!rRef.IsEntireCol(*mxSheetLimits) && !rRef.IsEntireRow(*mxSheetLimits)) @@ -5437,11 +5490,11 @@ sal_Int32 ScTokenArray::GetWeight() const { case svDoubleRef: { - const auto pComplexRef = (*pRPN[i]).GetDoubleRef(); + const auto rComplexRef = static_cast(*pRPN[i]).GetDoubleRef(); // Number of cells referenced divided by 10. - const double nRows = 1 + (pComplexRef->Ref2.Row() - pComplexRef->Ref1.Row()); - const double nCols = 1 + (pComplexRef->Ref2.Col() - pComplexRef->Ref1.Col()); + const double nRows = 1 + (rComplexRef.Ref2.Row() - rComplexRef.Ref1.Row()); + const double nCols = 1 + (rComplexRef.Ref2.Col() - rComplexRef.Ref1.Col()); const double nNumCellsTerm = nRows * nCols / 10.0; if (nNumCellsTerm + nResult < SAL_MAX_INT32) diff --git a/sc/source/core/tool/tokenstringcontext.cxx b/sc/source/core/tool/tokenstringcontext.cxx index 5a4430c155a3..926ead3cf689 100644 --- a/sc/source/core/tool/tokenstringcontext.cxx +++ b/sc/source/core/tool/tokenstringcontext.cxx @@ -54,10 +54,9 @@ TokenStringContext::TokenStringContext( const ScDocument& rDoc, formula::Formula } // Fetch all named range names. - const ScRangeName* pNames = rDoc.GetRangeName(); - if (pNames) - // global names - insertAllNames(maGlobalRangeNames, *pNames); + const ScRangeName& rNames = rDoc.GetRangeName(); + // global names + insertAllNames(maGlobalRangeNames, rNames); { ScRangeName::TabNameCopyMap aTabRangeNames; @@ -73,7 +72,7 @@ TokenStringContext::TokenStringContext( const ScDocument& rDoc, formula::Formula } } - // Fetch all named database ranges names. + // Fetch all named database range names. const ScDBCollection* pDBs = rDoc.GetDBCollection(); if (pDBs) { diff --git a/sc/source/core/tool/typedstrdata.cxx b/sc/source/core/tool/typedstrdata.cxx index 14ea33ab9221..dc7252908fb1 100644 --- a/sc/source/core/tool/typedstrdata.cxx +++ b/sc/source/core/tool/typedstrdata.cxx @@ -10,10 +10,22 @@ #include #include +#include #include #include #include +namespace +{ +// tdf#158326 - compare case-insensitively with simple case mapping. The previously used +// IGNORE_CASE transliteration folded the German "ß" to "ss", leading to a single entry. +sal_Int32 compareIgnoreCase(const OUString& rLeft, const OUString& rRight) +{ + const CharClass& rCharClass = ScGlobal::getCharClass(); + return rCharClass.uppercase(rLeft).compareTo(rCharClass.uppercase(rRight)); +} +} + bool ScTypedStrData::LessHiddenRows::operator() (const ScTypedStrData& left, const ScTypedStrData& right) const { return left.mbIsHiddenByFilter < right.mbIsHiddenByFilter; @@ -81,8 +93,8 @@ bool ScTypedStrData::LessCaseInsensitive::operator() (const ScTypedStrData& left if (left.mbIsDate != right.mbIsDate) return left.mbIsDate < right.mbIsDate; - sal_Int32 nEqual - = ScGlobal::GetTransliteration().compareString(left.maStrValue, right.maStrValue); + // tdf#158326 - compare case-insensitively with simple case mapping + sal_Int32 nEqual = compareIgnoreCase(left.maStrValue, right.maStrValue); if (!nEqual) return left.mbIsHiddenByFilter < right.mbIsHiddenByFilter; @@ -105,7 +117,7 @@ bool ScTypedStrData::LessSortCaseInsensitive::operator() (const ScTypedStrData& if (left.mbIsDate != right.mbIsDate) return left.mbIsDate < right.mbIsDate; - sal_Int32 nEqual = ScGlobal::GetCaseCollator().compareString(left.maStrValue, right.maStrValue); + sal_Int32 nEqual = ScGlobal::GetCollator().compareString(left.maStrValue, right.maStrValue); if (!nEqual) return left.mbIsHiddenByFilter < right.mbIsHiddenByFilter; @@ -138,7 +150,8 @@ bool ScTypedStrData::EqualCaseInsensitive::operator() (const ScTypedStrData& lef if (left.mbIsDate != right.mbIsDate ) return false; - return ScGlobal::GetTransliteration().isEqual(left.maStrValue, right.maStrValue); + // tdf#158326 - compare case-insensitively with simple case mapping + return compareIgnoreCase(left.maStrValue, right.maStrValue) == 0; } bool ScTypedStrData::operator< (const ScTypedStrData& r) const diff --git a/sc/source/core/tool/webservicelink.cxx b/sc/source/core/tool/webservicelink.cxx index c30f34300edf..cbb226e240a8 100644 --- a/sc/source/core/tool/webservicelink.cxx +++ b/sc/source/core/tool/webservicelink.cxx @@ -7,6 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #include @@ -36,10 +38,21 @@ ScWebServiceLink::~ScWebServiceLink() {} sfx2::SvBaseLink::UpdateResult ScWebServiceLink::DataChanged(const OUString&, const css::uno::Any&) { + if (pDoc && pDoc->GetDocumentShell() + && !pDoc->GetDocumentShell()->GetEmbeddedObjectContainer().getUserAllowsLinkUpdate()) + return SUCCESS; + aResult.clear(); bHasResult = false; INetURLObject aURLObject(aURL); + if (aURLObject.IsExoticProtocol()) + { + SAL_WARN("sc.ui", + "ScWebServiceLink::DataChanged: blocked exotic protocol: \"" << aURL << "\""); + return ERROR_GENERAL; + } + const OUString sHost = aURLObject.GetHost(); if (HostFilter::isForbidden(sHost)) { diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx index 21e537baa28f..3132d4b16de6 100644 --- a/sc/source/filter/excel/excdoc.cxx +++ b/sc/source/filter/excel/excdoc.cxx @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -606,7 +608,7 @@ void ExcTable::FillAsTableXml() // list of NOTE records, generated by the cell table // not in the worksheet file if( mxNoteList != nullptr && !mxNoteList->IsEmpty() ) - aRecList.AppendNewRecord( new XclExpComments( mnScTab, *mxNoteList ) ); + aRecList.AppendNewRecord( new XclExpComments( mnScTab, *mxNoteList, rDoc ) ); const ScTableProtection* pTabProtect = rDoc.GetTabProtection(mnScTab); if (pTabProtect && pTabProtect->isProtected()) @@ -637,16 +639,18 @@ void ExcTable::FillAsTableXml() aRecList.AppendRecord( xPageSett ); + std::unique_ptr pImgData(xPageSett->getGraphicExport()); // all MSODRAWING and OBJ stuff of this sheet goes here - aRecList.AppendRecord( GetObjectManager().ProcessDrawing( GetSdrPage( mnScTab ) ) ); - - XclExpImgData* pImgData = xPageSett->getGraphicExport(); - if (pImgData) - aRecList.AppendRecord(pImgData); + aRecList.AppendRecord( GetObjectManager().ProcessDrawing( GetSdrPage( mnScTab ), std::move(pImgData) ) ); // after and before aRecList.AppendRecord( GetTablesManager().GetTablesBySheet( mnScTab)); + aRecList.AppendNewRecord(new xcl::exp::NamedSheetViews(GetRoot(), mnScTab)); + + // queryTable parts (no wrapper element in sheet XML, only .rels entries) + aRecList.AppendRecord( GetQueryTablesManager().GetQueryTablesBySheet( mnScTab )); + aRecList.AppendRecord( xExtLst ); } @@ -742,6 +746,7 @@ void ExcDocument::ReadDoc() aHeader.FillAsHeaderXml(maBoundsheetList); GetXmlPivotTableManager().Initialize(); GetTablesManager().Initialize(); // Move outside conditions if we wanted to support BIFF. + GetQueryTablesManager().Initialize(); } SCTAB nScTab = 0, nScTabCount = GetTabInfo().GetScTabCount(); @@ -839,7 +844,7 @@ void ExcDocument::WriteXml( XclExpXmlStream& rStrm ) = sAlgorithm != "PBKDF2" && !sSalt.isEmpty() && !sHash.isEmpty() && !sUserName.isEmpty(); rStrm.exportDocumentProperties(xDocProps, pDocShell->IsSecurityOptOpenReadOnly() && !bHasPasswordHash && !bHasPasswordInfo); - rStrm.exportCustomFragments(); + rStrm.exportCustomFragments(rStrm.GetCurrentStream()); sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream(); rWorkbook->startElement( XML_workbook, @@ -912,6 +917,52 @@ void ExcDocument::WriteXml( XclExpXmlStream& rStrm ) // write the table maTableList.GetRecord( nTab )->WriteXml( rStrm ); } + + // xl/metadata.xml: emit the dynamic array property metadata block. + if (rStrm.HasDynamicArrayFormula()) + { + sax_fastparser::FSHelperPtr pMetadata = rStrm.CreateOutputStream( + u"xl/metadata.xml"_ustr, + u"metadata.xml", + rStrm.GetCurrentStream()->getOutputStream(), + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml", + oox::getRelationship(Relationship::SHEETMETADATA)); + + pMetadata->startElement(XML_metadata, + XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)), + FSNS(XML_xmlns, XML_xda), rStrm.getNamespaceURL(OOX_NS(xda))); + + pMetadata->startElement(XML_metadataTypes, XML_count, "1"); + pMetadata->singleElement(XML_metadataType, + XML_name, "XLDAPR", + XML_minSupportedVersion, "120000", + XML_copy, "1", XML_pasteAll, "1", XML_pasteValues, "1", + XML_merge, "1", XML_splitFirst, "1", XML_rowColShift, "1", + XML_clearFormats, "1", XML_clearComments, "1", + XML_assign, "1", XML_coerce, "1", XML_cellMeta, "1"); + pMetadata->endElement(XML_metadataTypes); + + pMetadata->startElement(XML_futureMetadata, + XML_name, "XLDAPR", XML_count, "1"); + pMetadata->startElement(XML_bk); + pMetadata->startElement(XML_extLst); + pMetadata->startElement(XML_ext, + XML_uri, "{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}"); + pMetadata->singleElement(FSNS(XML_xda, XML_dynamicArrayProperties), + XML_fDynamic, "1", XML_fCollapsed, "0"); + pMetadata->endElement(XML_ext); + pMetadata->endElement(XML_extLst); + pMetadata->endElement(XML_bk); + pMetadata->endElement(XML_futureMetadata); + + pMetadata->startElement(XML_cellMetadata, XML_count, "1"); + pMetadata->startElement(XML_bk); + pMetadata->singleElement(XML_rc, XML_t, "1", XML_v, "0"); + pMetadata->endElement(XML_bk); + pMetadata->endElement(XML_cellMetadata); + + pMetadata->endElement(XML_metadata); + } } if( m_xExpChangeTrack ) @@ -1358,6 +1409,31 @@ void ExcDocument::WriteXml( XclExpXmlStream& rStrm ) xExtLst->SaveXml(rStrm); } + // Write persons part for threaded comments. + const auto& rPersonList = rDoc.GetPersonList(); + if (!rPersonList.empty()) + { + sax_fastparser::FSHelperPtr pPersons = rStrm.CreateOutputStream( + u"xl/persons/person.xml"_ustr, u"persons/person.xml", + rStrm.GetCurrentStream()->getOutputStream(), "application/vnd.ms-excel.person+xml", + oox::getRelationship(Relationship::PERSON)); + rStrm.PushStream(pPersons); + + pPersons->startElement(XML_personList, XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xthreaded))); + + for (const auto& rPerson : rPersonList) + { + pPersons->singleElement( + XML_person, XML_displayName, rPerson.maDisplayName, XML_id, rPerson.maId, + XML_userId, sax_fastparser::UseIf(rPerson.maUserId, !rPerson.maUserId.isEmpty()), + XML_providerId, sax_fastparser::UseIf(rPerson.maProviderId, + !rPerson.maProviderId.isEmpty())); + } + + pPersons->endElement(XML_personList); + rStrm.PopStream(); + } + rWorkbook->endElement( XML_workbook ); rWorkbook.reset(); } @@ -1374,14 +1450,23 @@ void ExcDocument::addElemensToAttrList(const rtl::Reference>= aFastSeq) { for (const auto& rAttr : aFastSeq) - pAttrList->add(rAttr.Token, rAttr.Value); + { + // Decode OOXML _xHHHH_ escape sequences so the serializer + // re-encodes them correctly instead of double-escaping + // (e.g. _x0000_ -> _x005F_x0000_). + OUString aDecoded = oox::AttributeConversion::decodeXString(rAttr.Value); + pAttrList->add(rAttr.Token, aDecoded); + } } else if (a >>= aUnkSeq) { for (const auto& rAttr : aUnkSeq) + { + OUString aDecoded = oox::AttributeConversion::decodeXString(rAttr.Value); pAttrList->addUnknown(rAttr.NamespaceURL, OUStringToOString(rAttr.Name, RTL_TEXTENCODING_UTF8), - OUStringToOString(rAttr.Value, RTL_TEXTENCODING_UTF8)); + OUStringToOString(aDecoded, RTL_TEXTENCODING_UTF8)); + } } } } diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx index 742a94e4a5d9..6ab8327a39f2 100644 --- a/sc/source/filter/excel/excform.cxx +++ b/sc/source/filter/excel/excform.cxx @@ -119,7 +119,13 @@ void ImportExcel::Formula( if (pSharedCode) { ScFormulaCell* pCell; - pCell = new ScFormulaCell(rD, aScPos, pSharedCode->Clone()); + // XLS has no @ encoding. Bake an implicit @ into the + // RPN when the formula intends an array result so a + // TRANSPOSE-style call returns the upper-left value at + // the cell position. + std::unique_ptr pTokens = pSharedCode->Clone(); + ScFormulaCell::ResolveImplicitIntersection(*pTokens, rD, aScPos); + pCell = new ScFormulaCell(rD, aScPos, std::move(pTokens)); pCell->GetCode()->WrapReference(aScPos, EXC_MAXCOL8, EXC_MAXROW8); rDoc.getDoc().EnsureTable(aScPos.Tab()); rDoc.setFormulaCell(aScPos, pCell); @@ -147,6 +153,10 @@ void ImportExcel::Formula( if (pResult) { + // XLS has no @ encoding. Bake an implicit @ into the RPN when + // the formula intends an array result so a TRANSPOSE-style call + // returns the upper-left value at the cell position. + ScFormulaCell::ResolveImplicitIntersection(*pResult, rDoc.getDoc(), aScPos); pCell = new ScFormulaCell(rDoc.getDoc(), aScPos, std::move(pResult)); pCell->GetCode()->WrapReference(aScPos, EXC_MAXCOL8, EXC_MAXROW8); rDoc.getDoc().CheckLinkFormulaNeedingCheck( *pCell->GetCode()); @@ -531,8 +541,10 @@ ConvErr ExcelToSc::Convert( std::unique_ptr& pResult, XclImpStream else if (pName->GetScRangeData()) aStack << aPool.StoreName(nUINT16, pName->IsGlobal() ? -1 : pName->GetScTab()); - else + else if (ScGlobal::IsValidExternal(pName->GetXclName())) aStack << aPool.Store(ocExternal, pName->GetXclName()); + else + aStack << aPool.Store(ocUDExternal, pName->GetXclName()); } } break; @@ -1541,7 +1553,7 @@ void ExcelToSc::DoMulArgs( DefTokenId eId, sal_uInt8 nCnt ) if( nPass < nCnt ) nCnt = static_cast< sal_uInt8 >( nPass ); - if( nCnt > 0 && eId == ocExternal ) + if( nCnt > 0 && (eId == ocExternal || eId == ocUDExternal) ) { TokenId n = eParam[ nCnt - 1 ]; //##### ADJUST STUPIDITY FOR BASIC-FUNCS! @@ -1553,9 +1565,11 @@ void ExcelToSc::DoMulArgs( DefTokenId eId, sal_uInt8 nCnt ) aPool << n; } else - aPool << eId; + aPool << aPool.Store( eId, OUString() ); nCnt--; } + else if( eId == ocExternal || eId == ocUDExternal ) + aPool << aPool.Store( eId, OUString() ); else aPool << eId; diff --git a/sc/source/filter/excel/excform8.cxx b/sc/source/filter/excel/excform8.cxx index f09bf8557e4b..8d6343d29b47 100644 --- a/sc/source/filter/excel/excform8.cxx +++ b/sc/source/filter/excel/excform8.cxx @@ -40,34 +40,26 @@ namespace { * Extract a file path from OLE link path. An OLE link path is expected to * be in the following format: * - * Excel.Sheet.8 \3 [file path] + * Excel.Sheet.8 [file path] + * Excel.Sheet.12 [file path] */ bool extractFilePath(const OUString& rUrl, OUString& rPath) { - const char* prefix = "Excel.Sheet.8\3"; - size_t nPrefixLen = ::std::strlen(prefix); + OUString prefix1 = "Excel.Sheet.8", prefix2 = "Excel.Sheet.12"; + sal_Int32 nStart = -1; - sal_Int32 n = rUrl.getLength(); - if (n <= static_cast(nPrefixLen)) - // needs to have the specified prefix. + if (rUrl.startsWith(prefix1)) + nStart = prefix1.getLength(); + else if (rUrl.startsWith(prefix2)) + nStart = prefix2.getLength(); + + if (nStart < 0) return false; - OUStringBuffer aBuf; - const sal_Unicode* p = rUrl.getStr(); - for (size_t i = 0; i < o3tl::make_unsigned(n); ++i, ++p) - { - if (i < nPrefixLen) - { - sal_Unicode pc = static_cast(*prefix++); - if (pc != *p) - return false; + if (nStart < rUrl.getLength() && rUrl[nStart] == u'\3') + nStart++; - continue; - } - aBuf.append(*p); - } - - rPath = aBuf.makeStringAndClear(); + rPath = rUrl.copy(nStart); return true; } @@ -94,7 +86,11 @@ bool ExcelToSc8::GetExternalFileIdFromXti( sal_uInt16 nIxti, sal_uInt16& rFileId if (!pFileUrl || pFileUrl->isEmpty() || !GetDocShell()) return false; - OUString aFileUrl = ScGlobal::GetAbsDocName(*pFileUrl, GetDocShell()); + OUString aFileUrl; + if (rLinkMan.IsSupbookXlStartup(nIxti)) + aFileUrl = *pFileUrl; + else + aFileUrl = ScGlobal::GetAbsDocName(*pFileUrl, GetDocShell()); ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager(); rFileId = pRefMgr->getExternalFileId(aFileUrl); @@ -353,7 +349,7 @@ ConvErr ExcelToSc8::Convert( std::unique_ptr& rpTokArray, XclImpSt case 0x10: // RadicalLel 4 - err case 0x1D: // SxName 4 - val aIn.Ignore( 4 ); - aPool << ocBad; + aPool << ocErrName; aPool >> aStack; break; default: @@ -484,8 +480,10 @@ ConvErr ExcelToSc8::Convert( std::unique_ptr& rpTokArray, XclImpSt || pName->HasTokens()) // check forward declaration aStack << aPool.StoreName(nUINT16, pName->IsGlobal() ? -1 : pName->GetScTab()); - else + else if (ScGlobal::IsValidExternal(pName->GetXclName())) aStack << aPool.Store(ocExternal, pName->GetXclName()); + else + aStack << aPool.Store(ocUDExternal, pName->GetXclName()); } break; } @@ -669,8 +667,10 @@ ConvErr ExcelToSc8::Convert( std::unique_ptr& rpTokArray, XclImpSt aStack << aPool.StoreName( nNameIdx, pName->IsGlobal() ? -1 : pName->GetScTab()); else if (pName->IsMacro()) aStack << aPool.Store(ocMacro, pName->GetXclName()); - else + else if (ScGlobal::IsValidExternal(pName->GetXclName())) aStack << aPool.Store(ocExternal, pName->GetXclName()); + else + aStack << aPool.Store(ocUDExternal, pName->GetXclName()); } } else if( const XclImpExtName* pExtName = rLinkMan.GetExternName( nXtiIndex, nNameIdx ) ) @@ -746,7 +746,7 @@ ConvErr ExcelToSc8::Convert( std::unique_ptr& rpTokArray, XclImpSt } } else - aStack << aPool.Store(ocNoName, pExtName->GetName()); + aStack << aPool.Store(ocErrRef); } break; default: @@ -780,13 +780,16 @@ ConvErr ExcelToSc8::Convert( std::unique_ptr& rpTokArray, XclImpSt ExternalTabInfo aExtInfo; if (!Read3DTabReference(nIxti, nTabFirst, nTabLast, aExtInfo)) { - aPool << ocBad; - aPool >> aStack; - break; + aSRD.SetRelTab(0); + aSRD.SetFlag3D(false); + nTabFirst = nTabLast = 0; + aExtInfo.mbExternal = false; + } + else + { + aSRD.SetAbsTab(nTabFirst); + aSRD.SetFlag3D(true); } - - aSRD.SetAbsTab(nTabFirst); - aSRD.SetFlag3D(true); ExcRelToScRel8( nRw, nGrbitCol, aSRD, bRangeNameOrCond ); diff --git a/sc/source/filter/excel/excrecds.cxx b/sc/source/filter/excel/excrecds.cxx index b9a7c766681a..adbed9cd76eb 100644 --- a/sc/source/filter/excel/excrecds.cxx +++ b/sc/source/filter/excel/excrecds.cxx @@ -18,6 +18,7 @@ */ #include +#include #include #include @@ -893,23 +894,8 @@ void XclExpAutofilter::SaveXml( XclExpXmlStream& rStrm ) // CT_DateGroupItems for (const auto& rDateValue : maDateValues) { - OString aStr = OUStringToOString(rDateValue, RTL_TEXTENCODING_UTF8); - rtl::Reference pAttrList = sax_fastparser::FastSerializerHelper::createAttrList(); - sal_Int32 aDateGroup[3] = { XML_year, XML_month, XML_day }; - sal_Int32 idx = 0; - for (size_t i = 0; idx >= 0 && i < 3; i++) - { - OString kw = aStr.getToken(0, '-', idx); - kw = kw.trim(); - if (!kw.isEmpty()) - { - pAttrList->add(aDateGroup[i], kw); - } - } - // TODO: date filter can only handle YYYY-MM-DD date formats, so XML_dateTimeGrouping value - // will be "day" as default, until date filter cannot handle HH:MM:SS. - pAttrList->add(XML_dateTimeGrouping, "day"); - rWorksheet->singleElement(XML_dateGroupItem, pAttrList); + OString aDateString = OUStringToOString(rDateValue, RTL_TEXTENCODING_UTF8); + oox::xls::writeDateGroupItem(rWorksheet, XML_dateGroupItem, aDateString); } rWorksheet->endElement(XML_filters); } @@ -1011,6 +997,24 @@ ExcAutoFilterRecs::ExcAutoFilterRecs( const XclExpRoot& rRoot, SCTAB nTab, const { auto nFlag = rDoc.GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ).GetValue(); bool bIsButtonHidden = !( nFlag & ScMF::Auto ); + + // For merged cells, during import, we don't remove the dropdown button for merge master + // If the last cell in the merged cells has the flag `ScMF::Auto` then remove the + // dropdown button for merge master + if (!bIsButtonHidden) + { + const ScMergeAttr& rMerge + = rDoc.GetAttr(nCol, nRow, nTab, ATTR_MERGE); + SCCOL nColSpan = rMerge.GetColMerge(); + if (nColSpan > 1) + { + auto nLastColFlag + = rDoc.GetAttr(nCol + nColSpan - 1, nRow, nTab, ATTR_MERGE_FLAG).GetValue(); + if (nLastColFlag & ScMF::Auto) + bIsButtonHidden = true; + } + } + if ( bIsButtonHidden ) { // Create filter column with hiddenButton=1 attribute if it doesn't exist diff --git a/sc/source/filter/excel/export/ExportTools.cxx b/sc/source/filter/excel/export/ExportTools.cxx index dacd4e469a4a..5d0fca61ce0a 100644 --- a/sc/source/filter/excel/export/ExportTools.cxx +++ b/sc/source/filter/excel/export/ExportTools.cxx @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace oox::xls @@ -40,6 +41,44 @@ void writeComplexColor(const sax_fastparser::FSHelperPtr& pFS, sal_Int32 nElemen writeComplexColor(pFS, nElement, rComplexColor, rComplexColor.getFinalColor()); } } + +void writeDateGroupItem(const sax_fastparser::FSHelperPtr& pStream, sal_Int32 nElement, + std::string_view aDateString) +{ + rtl::Reference pAttrList + = sax_fastparser::FastSerializerHelper::createAttrList(); + + // Tokenize on '-' to extract year, month, day components. + // The date string may be partial: "YYYY", "YYYY-MM", or "YYYY-MM-DD". + static constexpr sal_Int32 aDateTokens[] = { XML_year, XML_month, XML_day }; + const char* pGrouping = "year"; + + size_t nStart = 0; + for (size_t i = 0; i < 3 && nStart < aDateString.size(); ++i) + { + size_t nSep = aDateString.find('-', nStart); + std::string_view aPart; + if (nSep != std::string_view::npos) + aPart = aDateString.substr(nStart, nSep - nStart); + else + aPart = aDateString.substr(nStart); + + if (!aPart.empty()) + pAttrList->add(aDateTokens[i], aPart); + + if (i == 1) + pGrouping = "month"; + else if (i == 2) + pGrouping = "day"; + + if (nSep == std::string_view::npos) + break; + nStart = nSep + 1; + } + + pAttrList->add(XML_dateTimeGrouping, pGrouping); + pStream->singleElement(nElement, pAttrList); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/export/NamedSheetViews.cxx b/sc/source/filter/excel/export/NamedSheetViews.cxx new file mode 100644 index 000000000000..c3369bbf79a5 --- /dev/null +++ b/sc/source/filter/excel/export/NamedSheetViews.cxx @@ -0,0 +1,357 @@ +/* -*- 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +using namespace oox; + +namespace +{ +/** Writes filter XML elements for query entries on a single column. */ +class ColumnFilterWriter +{ +public: + ColumnFilterWriter(const sax_fastparser::FSHelperPtr& pStream, + const std::vector& rEntries, const XclExpDxfs& rDxfs) + : mpStream(pStream) + , mrEntries(rEntries) + , mrDxfs(rDxfs) + { + } + + void write() + { + if (mrEntries.empty()) + return; + + const ScQueryEntry& rFirst = *mrEntries[0]; + + if (rFirst.eOp == SC_TOPVAL || rFirst.eOp == SC_BOTVAL || rFirst.eOp == SC_TOPPERC + || rFirst.eOp == SC_BOTPERC) + writeTop10(rFirst); + else if (rFirst.IsQueryByTextColor() || rFirst.IsQueryByBackgroundColor()) + writeColor(rFirst); + else if (rFirst.eOp == SC_EQUAL) + writeDiscrete(); + else + writeCustom(); + } + +private: + static const char* getOperator(ScQueryOp eOp) + { + switch (eOp) + { + case SC_EQUAL: + return "equal"; + case SC_LESS: + return "lessThan"; + case SC_GREATER: + return "greaterThan"; + case SC_LESS_EQUAL: + return "lessThanOrEqual"; + case SC_GREATER_EQUAL: + return "greaterThanOrEqual"; + case SC_NOT_EQUAL: + return "notEqual"; + default: + return nullptr; + } + } + + void writeTop10(const ScQueryEntry& rEntry) + { + const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems(); + if (rItems.empty()) + return; + + bool bTop = (rEntry.eOp == SC_TOPVAL || rEntry.eOp == SC_TOPPERC); + bool bPercent = (rEntry.eOp == SC_TOPPERC || rEntry.eOp == SC_BOTPERC); + mpStream->singleElement(FSNS(XML_x, XML_top10), XML_top, ToPsz(bTop), XML_percent, + ToPsz(bPercent), XML_val, + OString::number(sal_Int32(rItems[0].mfVal))); + } + + void writeColor(const ScQueryEntry& rEntry) + { + const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems(); + if (rItems.empty()) + return; + + bool bCellColor = rEntry.IsQueryByBackgroundColor(); + sal_Int32 nDxfId = mrDxfs.GetDxfByColor(rItems[0].maColor); + mpStream->singleElement(FSNS(XML_x, XML_colorFilter), XML_dxfId, OString::number(nDxfId), + XML_cellColor, OString::number(bCellColor ? 1 : 0)); + } + + void writeDiscrete() + { + const ScQueryEntry& rFirst = *mrEntries[0]; + + bool bHasBlank = false; + std::vector aValues; + std::vector aDateValues; + + for (const auto* pEntry : mrEntries) + { + const ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems(); + for (const auto& rItem : rItems) + { + if (rItem.maString.isEmpty()) + bHasBlank = true; + else if (rItem.meType == ScQueryEntry::ByDate) + aDateValues.push_back( + OUStringToOString(rItem.maString.getString(), RTL_TEXTENCODING_UTF8)); + else + aValues.push_back( + OUStringToOString(rItem.maString.getString(), RTL_TEXTENCODING_UTF8)); + } + } + + if (rFirst.IsQueryByEmpty()) + bHasBlank = true; + + if (bHasBlank) + mpStream->startElement(FSNS(XML_x, XML_filters), XML_blank, "1"); + else + mpStream->startElement(FSNS(XML_x, XML_filters)); + + for (const auto& rValue : aValues) + { + mpStream->singleElement(FSNS(XML_x, XML_filter), XML_val, rValue); + } + + for (const auto& rDateValue : aDateValues) + { + oox::xls::writeDateGroupItem(mpStream, FSNS(XML_x, XML_dateGroupItem), rDateValue); + } + + mpStream->endElement(FSNS(XML_x, XML_filters)); + } + + void writeCustom() + { + const char* pOperator = getOperator(mrEntries[0]->eOp); + if (!pOperator) + return; + + bool bAnd = (mrEntries.size() > 1 && mrEntries[1]->eConnect == SC_AND); + mpStream->startElement(FSNS(XML_x, XML_customFilters), XML_and, ToPsz(bAnd)); + + for (const auto* pEntry : mrEntries) + { + const char* pEntryOperator = getOperator(pEntry->eOp); + if (!pEntryOperator) + continue; + + const ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems(); + OString aValue; + if (!rItems.empty()) + aValue = OUStringToOString(rItems[0].maString.getString(), RTL_TEXTENCODING_UTF8); + + mpStream->singleElement(FSNS(XML_x, XML_customFilter), XML_operator, pEntryOperator, + XML_val, aValue); + } + + mpStream->endElement(FSNS(XML_x, XML_customFilters)); + } + + const sax_fastparser::FSHelperPtr& mpStream; + const std::vector& mrEntries; + const XclExpDxfs& mrDxfs; +}; + +} // anonymous namespace + +xcl::exp::NamedSheetViews::NamedSheetViews(const XclExpRoot& rRoot, SCTAB nTab) + : XclExpRoot(rRoot) + , mnTab(nTab) + , mbHasSheetViews(false) +{ + auto pManager = GetDoc().GetSheetViewManager(nTab); + if (pManager && !pManager->isEmpty()) + mbHasSheetViews = true; +} + +void xcl::exp::NamedSheetViews::saveColumnFilters(const sax_fastparser::FSHelperPtr& pStream, + const ScQueryParam& rQueryParam) +{ + // Group query entries by column + std::map> aColumnEntries; + bool bHasFilters = false; + + for (SCSIZE i = 0; i < rQueryParam.GetEntryCount(); ++i) + { + const ScQueryEntry& rEntry = rQueryParam.GetEntry(i); + if (!rEntry.bDoQuery) + break; + aColumnEntries[rEntry.nField].push_back(&rEntry); + bHasFilters = true; + } + + if (!bHasFilters) + return; + + for (const auto & [ nCol, rEntries ] : aColumnEntries) + { + pStream->startElement(XML_columnFilter, XML_colId, OString::number(nCol)); + pStream->startElement(XML_filter, XML_colId, OString::number(nCol)); + ColumnFilterWriter(pStream, rEntries, GetDxfs()).write(); + pStream->endElement(XML_filter); + pStream->endElement(XML_columnFilter); + } +} + +void xcl::exp::NamedSheetViews::saveSortRules(const sax_fastparser::FSHelperPtr& pStream, + const ScRange& rRange, SCTAB nViewTab, + const ScSortParam& rSortParam) +{ + bool bHasSort = false; + for (const auto& rKey : rSortParam.maKeyState) + { + if (rKey.bDoSort) + { + bHasSort = true; + break; + } + } + + if (!bHasSort) + return; + + pStream->startElement(XML_sortRules, XML_caseSensitive, ToPsz(rSortParam.bCaseSens)); + + for (const auto& rKey : rSortParam.maKeyState) + { + if (!rKey.bDoSort) + continue; + + OString aSortRuleGUID = comphelper::xml::generateGUIDString(); + + pStream->startElement(XML_sortRule, XML_colId, OString::number(rKey.nField), XML_id, + aSortRuleGUID); + + // Build the column range reference for sortCondition + ScRange aSortColRange; + aSortColRange.aStart.SetCol(SCCOL(rKey.nField)); + aSortColRange.aStart.SetRow(rRange.aStart.Row()); + aSortColRange.aStart.SetTab(nViewTab); + aSortColRange.aEnd.SetCol(SCCOL(rKey.nField)); + aSortColRange.aEnd.SetRow(rRange.aEnd.Row()); + aSortColRange.aEnd.SetTab(nViewTab); + + OString aSortReference = XclXmlUtils::ToOString(GetDoc(), aSortColRange); + + std::optional sDescending; + if (!rKey.bAscending) + sDescending = "1"; + + pStream->singleElement(XML_sortCondition, XML_ref, aSortReference, XML_descending, + sDescending); + + pStream->endElement(XML_sortRule); + } + + pStream->endElement(XML_sortRules); +} + +void xcl::exp::NamedSheetViews::saveSheetView(const sax_fastparser::FSHelperPtr& pStream, + const sc::SheetView& rSheetView) +{ + pStream->startElement(XML_namedSheetView, XML_name, rSheetView.GetName().toUtf8(), XML_id, + rSheetView.GetGUID()); + + // Get the view tab to access its filter/sort data + SCTAB nViewTab = rSheetView.getTableNumber(); + ScDBData* pDBData = GetDoc().GetAnonymousDBData(nViewTab); + + if (pDBData) + { + ScRange aRange; + pDBData->GetArea(aRange); + aRange.aStart.SetTab(nViewTab); + aRange.aEnd.SetTab(nViewTab); + + OString aRangeString = XclXmlUtils::ToOString(GetDoc(), aRange); + // tableId=0 marks the filter as bound to the worksheet auto-filter + // (anonymous DB range), not to a formal
      element. + // TODO: emit the real
      when sheet view filters get bound to + // a formal table. + pStream->startElement(XML_nsvFilter, XML_filterId, rSheetView.GetFilterGUID(), XML_ref, + aRangeString, XML_tableId, OString::number(0)); + + ScQueryParam aQueryParam; + pDBData->GetQueryParam(aQueryParam); + saveColumnFilters(pStream, aQueryParam); + + ScSortParam aSortParam; + pDBData->GetSortParam(aSortParam); + saveSortRules(pStream, aRange, nViewTab, aSortParam); + + pStream->endElement(XML_nsvFilter); + } + + pStream->endElement(XML_namedSheetView); +} + +void xcl::exp::NamedSheetViews::SaveXml(XclExpXmlStream& rStream) +{ + if (!mbHasSheetViews) + return; + + auto pManager = GetDoc().GetSheetViewManager(mnTab); + if (!pManager || pManager->isEmpty()) + return; + + // Create output stream for the namedSheetView part + sax_fastparser::FSHelperPtr pWorksheetStream = rStream.GetCurrentStream(); + + OUString sFullPath + = XclXmlUtils::GetStreamName("xl/namedSheetViews/", "namedSheetView", mnTab + 1); + OUString sRelPath + = XclXmlUtils::GetStreamName("../namedSheetViews/", "namedSheetView", mnTab + 1); + + sax_fastparser::FSHelperPtr pNamedSheetViewStream = rStream.CreateOutputStream( + sFullPath, sRelPath, pWorksheetStream->getOutputStream(), + "application/vnd.ms-excel.namedSheetViews+xml", + u"http://schemas.microsoft.com/office/2019/04/relationships/namedSheetView"_ustr); + + rStream.PushStream(pNamedSheetViewStream); + + pNamedSheetViewStream->startElement( + XML_namedSheetViews, XML_xmlns, rStream.getNamespaceURL(OOX_NS(xnsv)), + FSNS(XML_xmlns, XML_x), rStream.getNamespaceURL(OOX_NS(xls)), FSNS(XML_xmlns, XML_x14), + rStream.getNamespaceURL(OOX_NS(xls14Lst))); + + for (auto& rSheetView : pManager->iterateValidSheetViews()) + saveSheetView(pNamedSheetViewStream, rSheetView); + + pNamedSheetViewStream->endElement(XML_namedSheetViews); + + rStream.PopStream(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/impop.cxx b/sc/source/filter/excel/impop.cxx index b4f8b64e5374..7f1adbc269f4 100644 --- a/sc/source/filter/excel/impop.cxx +++ b/sc/source/filter/excel/impop.cxx @@ -72,7 +72,7 @@ using namespace ::com::sun::star; ImportTyp::ImportTyp(ScDocument& rDoc, rtl_TextEncoding eQ) - : eQuellChar(eQ) + : eSrcEncoding(eQ) , rD(rDoc) { @@ -849,6 +849,10 @@ void ImportExcel::Shrfmla() ScDocumentImport& rDoc = GetDocImport(); + // XLS has no @ encoding. Bake an implicit @ into the RPN when the + // formula intends an array result so a TRANSPOSE-style call returns + // the upper-left value at the cell position. + ScFormulaCell::ResolveImplicitIntersection(*pResult, rD, aPos); ScFormulaCell* pCell = new ScFormulaCell(rD, aPos, std::move(pResult)); pCell->GetCode()->WrapReference(aPos, EXC_MAXCOL8, EXC_MAXROW8); rDoc.getDoc().CheckLinkFormulaNeedingCheck( *pCell->GetCode()); diff --git a/sc/source/filter/excel/tokstack.cxx b/sc/source/filter/excel/tokstack.cxx index 3fd7a40bce0d..61281caccf83 100644 --- a/sc/source/filter/excel/tokstack.cxx +++ b/sc/source/filter/excel/tokstack.cxx @@ -596,6 +596,11 @@ const OUString* TokenPool::GetExternal( const TokenId& rId ) const if ( nExt < ppP_Ext.m_writemark && ppP_Ext[ nExt ] ) p = &ppP_Ext[ nExt ]->aText; } + else if (eType == T_ExtName) + { + if (nExt < maExtNames.size()) + p = &maExtNames[nExt].maName; + } } return p; diff --git a/sc/source/filter/excel/xechart.cxx b/sc/source/filter/excel/xechart.cxx index 2c93fcf2f02c..3e8259f22879 100644 --- a/sc/source/filter/excel/xechart.cxx +++ b/sc/source/filter/excel/xechart.cxx @@ -867,8 +867,11 @@ void lclAddDoubleRefData( OSL_ENSURE( (rToken.GetType() == ::formula::svDoubleRef) || (rToken.GetType() == ::formula::svExternalDoubleRef), "lclAddDoubleRefData - double reference token expected"); if( rToken.GetType() == ::formula::svExternalDoubleRef ) + { + auto rEDRToken = static_cast(rToken); orArray.AddExternalDoubleReference( - rToken.GetIndex(), rToken.GetString(), aComplexRef); + rEDRToken.GetFileId(), rEDRToken.GetTableName(), aComplexRef); + } else orArray.AddDoubleReference( aComplexRef ); } @@ -919,9 +922,13 @@ sal_uInt16 XclExpChSourceLink::ConvertDataSequence( Reference< XDataSequence > c case ::formula::svExternalDoubleRef: { // split 3-dimensional ranges into single sheets - const ScComplexRefData& rComplexRef = *pToken->GetDoubleRef(); - ScAddress aAbs1 = rComplexRef.Ref1.toAbs(GetRoot().GetDoc(), ScAddress()); - ScAddress aAbs2 = rComplexRef.Ref2.toAbs(GetRoot().GetDoc(), ScAddress()); + const ScComplexRefData* pComplexRef; + if (pToken->GetType() == ::formula::svDoubleRef) + pComplexRef = &static_cast(pToken)->GetDoubleRef(); + else + pComplexRef = &static_cast(pToken)->GetDoubleRef(); + ScAddress aAbs1 = pComplexRef->Ref1.toAbs(GetRoot().GetDoc(), ScAddress()); + ScAddress aAbs2 = pComplexRef->Ref2.toAbs(GetRoot().GetDoc(), ScAddress()); for (SCTAB nScTab = aAbs1.Tab(); nScTab <= aAbs2.Tab(); ++nScTab) { // split 2-dimensional ranges into single columns diff --git a/sc/source/filter/excel/xecontent.cxx b/sc/source/filter/excel/xecontent.cxx index 0404740d1b0c..4dfa51149b56 100644 --- a/sc/source/filter/excel/xecontent.cxx +++ b/sc/source/filter/excel/xecontent.cxx @@ -338,7 +338,7 @@ XclExpHyperlink::XclExpHyperlink( const XclExpRoot& rRoot, const SvxURLField& rU INetURLObject aUrlObj( rUrl ); const INetProtocol eProtocol = aUrlObj.GetProtocol(); bool bWithRepr = !rRepr.isEmpty(); - XclExpStream aXclStrm( *mxVarData, rRoot ); // using in raw write mode. + XclExpStream aXclStrm( *mxVarData, rRoot ); // used in raw write mode. // description if( bWithRepr ) @@ -736,7 +736,7 @@ XclExpCFImpl::XclExpCFImpl( const XclExpRoot& rRoot, const ScCondFormatEntry& rF XclExpFormulaCompiler& rFmlaComp = GetFormulaCompiler(); - // Explicity registers external references if the formula contains any + // Explicitly registers external references if the formula contains any std::unique_ptr< ScTokenArray > xScTokArr( mrFormatEntry.CreateFlatCopiedTokenArray( 0 ) ); mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_CONDFMT, *xScTokArr ); @@ -1068,14 +1068,17 @@ void XclExpCFImpl::SaveXml( XclExpXmlStream& rStrm ) { case formula::svDouble: { - aText = OString::number(pTokenArray->FirstToken()->GetDouble()); + auto pDoubleToken = static_cast(pTokenArray->FirstToken()); + aText = OString::number(pDoubleToken->GetDouble()); + break; + } + case formula::svString: + { + aText = static_cast(pTokenArray->FirstToken())->GetString().getString().toUtf8(); break; } default: - { - aText = pTokenArray->FirstToken()->GetString().getString().toUtf8(); break; - } } } } diff --git a/sc/source/filter/excel/xedbdata.cxx b/sc/source/filter/excel/xedbdata.cxx index 522b5ea19747..d85fa4009eff 100644 --- a/sc/source/filter/excel/xedbdata.cxx +++ b/sc/source/filter/excel/xedbdata.cxx @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -75,6 +77,15 @@ void XclExpTablesImpl8::SaveXml( XclExpXmlStream& rStrm ) pWorksheetStrm->startElement(XML_tableParts); for (auto const& it : maTables) { + const ScDBData& rData = *it.mpData; + ScRange aRange(ScAddress::UNINITIALIZED); + rData.GetArea(aRange); + // a valid table has to have at least 1 data row + // don't export if less than that, Excel won't accept it + const SCROW nMinHeight = (rData.HasHeader() ? 1 : 0) + (rData.HasTotals() ? 1 : 0) + 1; + if (aRange.aEnd.Row() - aRange.aStart.Row() + 1 < nMinHeight) + continue; + OUString aRelId; sax_fastparser::FSHelperPtr pTableStrm = rStrm.CreateOutputStream( XclXmlUtils::GetStreamName("xl/tables/", "table", it.mnTableId), @@ -192,14 +203,21 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, const Entry& rEntry ) const std::vector aTotalValues = rData.GetTotalRowAttributes(formula::FormulaGrammar::GRAM_OOXML); - // if the Total row have ever been showed it will be true - bool hasAnySetValue = rData.HasTotals() || std::any_of(aTotalValues.begin(), aTotalValues.end(), - [](const TableColumnAttributes& attr) - { - return attr.maTotalsRowLabel.has_value() - || attr.maTotalsFunction.has_value() - || attr.maCustomFunction.has_value(); - }); + // Excel does not accept a totals row on a table that has no header row. It also + // does not accept one where a column's totals row cell holds content that this + // class could not describe as a label or an aggregate function, since the + // exported cell value would then disagree with the table's declared totals row. + // A column whose totals row cell is simply empty does not have that problem, so + // a totals row with nothing but blank cells stays a valid, shown totals row. + bool bAnyColumnHasUndescribedContent = std::any_of( + aTotalValues.begin(), aTotalValues.end(), [](const TableColumnAttributes& attr) { + return attr.mbHasContent && !attr.maTotalsRowLabel.has_value() + && !attr.maTotalsFunction.has_value(); + }); + bool bExportTotals = rData.HasHeader() && rData.HasTotals() && !bAnyColumnHasUndescribedContent; + + // if the Total row has ever been shown it will be true + bool hasAnySetValue = bExportTotals; pTableStrm->startElement( XML_table, XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8(), @@ -209,7 +227,7 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, const Entry& rEntry ) XML_ref, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aRange), XML_tableType, tableType, XML_headerRowCount, ToPsz10(rData.HasHeader()), - XML_totalsRowCount, ToPsz10(rData.HasTotals()), + XML_totalsRowCount, ToPsz10(bExportTotals), XML_totalsRowShown, (hasAnySetValue ? nullptr : ToPsz10(false)) // we don't support that but // if there are totals or any total row attribute is set they are shown // OOXTODO: XML_comment, ..., @@ -246,7 +264,7 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, const Entry& rEntry ) const std::vector< TableColumnModel >& rTableColumnModel = rData.GetTableColumnModel(); if (!rColNames.empty()) { - // rColNames and aTotalValues size should always be equal + // rColNames and aTotalValues sizes should always be equal assert((rColNames.size() == aTotalValues.size()) && "XclExpTables::SaveTableXml - mismatch between column names and total values"); @@ -275,8 +293,8 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, const Entry& rEntry ) XML_id, OString::number(i+1), XML_uniqueName, uniqueName, XML_name, rColNames[i].toUtf8(), - XML_totalsRowLabel, (i < aTotalValues.size() ? aTotalValues[i].maTotalsRowLabel : std::nullopt), - XML_totalsRowFunction, (i < aTotalValues.size() ? aTotalValues[i].maTotalsFunction : std::nullopt) + XML_totalsRowLabel, (bExportTotals && i < aTotalValues.size() ? aTotalValues[i].maTotalsRowLabel : std::nullopt), + XML_totalsRowFunction, (bExportTotals && i < aTotalValues.size() ? aTotalValues[i].maTotalsFunction : std::nullopt) // OOXTODO: XML_dataCellStyle, ..., // OOXTODO: XML_dataDxfId, ..., // OOXTODO: XML_headerRowCellStyle, ..., @@ -303,7 +321,7 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, const Entry& rEntry ) pTableStrm->singleElement(XML_xmlColumnPr, pXmlColumnPrAttrList); } - if (i < aTotalValues.size() && aTotalValues[i].maTotalsFunction.has_value() + if (bExportTotals && i < aTotalValues.size() && aTotalValues[i].maTotalsFunction.has_value() && aTotalValues[i].maTotalsFunction.value() == u"custom"_ustr) { // write custom functions @@ -340,4 +358,132 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, const Entry& rEntry ) pTableStrm->endElement( XML_table); } + +// --- XclExpQueryTables --- + +XclExpQueryTables::Entry::Entry( std::shared_ptr pModel, sal_Int32 nId ) : + mpModel(std::move(pModel)), mnQueryTableId(nId) +{ +} + +XclExpQueryTables::XclExpQueryTables( const XclExpRoot& rRoot ) : + XclExpRoot(rRoot) +{ +} + +XclExpQueryTables::~XclExpQueryTables() +{ +} + +void XclExpQueryTables::AppendQueryTable( std::shared_ptr pModel, sal_Int32 nQueryTableId ) +{ + maQueryTables.emplace_back( std::move(pModel), nQueryTableId ); +} + +void XclExpQueryTables::SaveXml( XclExpXmlStream& rStrm ) +{ + sax_fastparser::FSHelperPtr& pWorksheetStrm = rStrm.GetCurrentStream(); + + for (const auto& rEntry : maQueryTables) + { + sax_fastparser::FSHelperPtr pQTStrm = rStrm.CreateOutputStream( + XclXmlUtils::GetStreamName("xl/queryTables/", "queryTable", rEntry.mnQueryTableId), + XclXmlUtils::GetStreamName("../queryTables/", "queryTable", rEntry.mnQueryTableId), + pWorksheetStrm->getOutputStream(), + CREATE_XL_CONTENT_TYPE("queryTable"), + CREATE_OFFICEDOC_RELATION_TYPE("queryTable")); + + rStrm.PushStream( pQTStrm ); + SaveQueryTableXml( rStrm, rEntry ); + rStrm.PopStream(); + } +} + +void XclExpQueryTables::SaveQueryTableXml( XclExpXmlStream& rStrm, const Entry& rEntry ) +{ + const oox::xls::QueryTableModel& rModel = *rEntry.mpModel; + sax_fastparser::FSHelperPtr& pStream = rStrm.GetCurrentStream(); + + const char* pGrowShrinkType = nullptr; + if (rModel.mnGrowShrinkType == XML_insertClear) + pGrowShrinkType = "insertClear"; + else if (rModel.mnGrowShrinkType == XML_overwriteClear) + pGrowShrinkType = "overwriteClear"; + // XML_insertDelete is the default, omit + + std::optional aAutoFormatId; + if (rModel.mnAutoFormatId != 0) + aAutoFormatId = OString::number(rModel.mnAutoFormatId); + + pStream->singleElement( XML_queryTable, + XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8(), + XML_name, rModel.maDefName.toUtf8(), + XML_connectionId, OString::number(rModel.mnConnId), + XML_autoFormatId, aAutoFormatId, + XML_growShrinkType, pGrowShrinkType, + XML_headers, rModel.mbHeaders ? nullptr : ToPsz10(false), + XML_rowNumbers, rModel.mbRowNumbers ? ToPsz10(true) : nullptr, + XML_disableRefresh, rModel.mbDisableRefresh ? ToPsz10(true) : nullptr, + XML_backgroundRefresh, rModel.mbBackground ? nullptr : ToPsz10(false), + XML_firstBackgroundRefresh, rModel.mbFirstBackground ? ToPsz10(true) : nullptr, + XML_refreshOnLoad, rModel.mbRefreshOnLoad ? ToPsz10(true) : nullptr, + XML_fillFormulas, rModel.mbFillFormulas ? ToPsz10(true) : nullptr, + XML_removeDataOnSave, rModel.mbRemoveDataOnSave ? ToPsz10(true) : nullptr, + XML_disableEdit, rModel.mbDisableEdit ? ToPsz10(true) : nullptr, + XML_preserveFormatting, rModel.mbPreserveFormat ? nullptr : ToPsz10(false), + XML_adjustColumnWidth, rModel.mbAdjustColWidth ? nullptr : ToPsz10(false), + XML_intermediate, rModel.mbIntermediate ? ToPsz10(true) : nullptr, + XML_applyNumberFormats, ToPsz10(rModel.mbApplyNumFmt), + XML_applyBorderFormats, ToPsz10(rModel.mbApplyBorder), + XML_applyFontFormats, ToPsz10(rModel.mbApplyFont), + XML_applyPatternFormats, ToPsz10(rModel.mbApplyFill), + XML_applyAlignmentFormats, ToPsz10(rModel.mbApplyAlignment), + XML_applyWidthHeightFormats, ToPsz10(rModel.mbApplyProtection)); +} + + +// --- XclExpQueryTablesManager --- + +XclExpQueryTablesManager::XclExpQueryTablesManager( const XclExpRoot& rRoot ) : + XclExpRoot( rRoot ) +{ +} + +XclExpQueryTablesManager::~XclExpQueryTablesManager() +{ +} + +void XclExpQueryTablesManager::Initialize() +{ + ScDocument& rDoc = GetDoc(); + if (!rDoc.hasAnyQueryTables()) + return; + + sal_Int32 nQueryTableId = 0; + SCTAB nScTabCount = GetTabInfo().GetScTabCount(); + + for (SCTAB nScTab = 0; nScTab < nScTabCount; ++nScTab) + { + if (!GetTabInfo().IsExportTab(nScTab)) + continue; + + const QueryTableModelVector* pModels = rDoc.getSheetQueryTables(nScTab); + if (!pModels || pModels->empty()) + continue; + + rtl::Reference< XclExpQueryTables > pNew = new XclExpQueryTables( GetRoot() ); + for (const auto& pModel : *pModels) + { + pNew->AppendQueryTable( pModel, ++nQueryTableId ); + } + maQueryTablesMap.insert( ::std::make_pair( nScTab, pNew ) ); + } +} + +rtl::Reference< XclExpQueryTables > XclExpQueryTablesManager::GetQueryTablesBySheet( SCTAB nTab ) +{ + QueryTablesMapType::iterator it = maQueryTablesMap.find(nTab); + return it == maQueryTablesMap.end() ? nullptr : it->second; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx index 08eceeccfea4..80dab2adb885 100644 --- a/sc/source/filter/excel/xeescher.cxx +++ b/sc/source/filter/excel/xeescher.cxx @@ -24,12 +24,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -147,6 +149,20 @@ tools::Long lcl_hmm2output(tools::Long value, bool bInEMU) return o3tl::convert(value, o3tl::Length::mm100, bInEMU ? o3tl::Length::emu : o3tl::Length::px); } +void lcl_SetFromToClamped( sal_Int32 nRow, sal_Int32 nCol, sal_Int32 nColOff, sal_Int32 nRowOff, + bool bInEMU, tools::Rectangle& aFrom ) +{ + if (nRow <= 0 || nCol <= 0) + { + SAL_WARN("sc.filter", "Clamping invalid row/column index to 0 while calculating from-to positions row=" << (nRow - 1) << " col=" << (nCol - 1)); + } + + sal_Int32 nNewCol = (nCol > 0) ? nCol - 1 : 0; + sal_Int32 nNewRow = (nRow > 0) ? nRow - 1 : 0; + aFrom = tools::Rectangle( nNewCol, lcl_hmm2output( nColOff, bInEMU ), + nNewRow, lcl_hmm2output( nRowOff, bInEMU ) ); +} + void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_Int32 nTab, tools::Rectangle &aFrom, tools::Rectangle &aTo, bool bInEMU = false ) { sal_Int32 nCol = 0, nRow = 0; @@ -170,8 +186,7 @@ void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_ } if( r.Left() > aRect.Left() && r.Top() > aRect.Top() ) { - aFrom = tools::Rectangle( nCol-1, lcl_hmm2output( nColOff, bInEMU ), - nRow-1, lcl_hmm2output( nRowOff, bInEMU ) ); + lcl_SetFromToClamped( nRow, nCol, nColOff, nRowOff, bInEMU, aFrom ); break; } } @@ -193,8 +208,7 @@ void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_ } if( r.Left() < aRect.Left() && r.Top() > aRect.Top() ) { - aFrom = tools::Rectangle( nCol-1, lcl_hmm2output( nColOff, bInEMU ), - nRow-1, lcl_hmm2output( nRowOff, bInEMU ) ); + lcl_SetFromToClamped( nRow, nCol, nColOff, nRowOff, bInEMU, aFrom ); break; } } @@ -235,6 +249,84 @@ void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_ } } +const char* lcl_GetVmlHorAlign(sal_uInt8 nHorAlign) +{ + switch (nHorAlign) + { + case EXC_OBJ_HOR_CENTER: + return "Center"; + case EXC_OBJ_HOR_RIGHT: + return "Right"; + default: + return "Left"; + } +} + +const char* lcl_GetVmlDivStyle(sal_uInt8 nHorAlign) +{ + switch (nHorAlign) + { + case EXC_OBJ_HOR_CENTER: + return "text-align:center"; + case EXC_OBJ_HOR_RIGHT: + return "text-align:right"; + default: + return "text-align:left"; + } +} + +const char* lcl_GetVmlVerAlign(sal_uInt8 nVerAlign) +{ + switch (nVerAlign) + { + case EXC_OBJ_VER_CENTER: + return "Center"; + case EXC_OBJ_VER_BOTTOM: + return "Bottom"; + default: + return "Top"; + } +} + +const char* lcl_GetDrawingHorAlign(sal_uInt8 nHorAlign) +{ + switch (nHorAlign) + { + case EXC_OBJ_HOR_CENTER: + return "ctr"; + case EXC_OBJ_HOR_RIGHT: + return "r"; + default: + return "l"; + } +} + +const char* lcl_GetDrawingVerAlign(sal_uInt8 nVerAlign) +{ + switch (nVerAlign) + { + case EXC_OBJ_VER_CENTER: + return "ctr"; + case EXC_OBJ_VER_BOTTOM: + return "b"; + default: + return "t"; + } +} + +const char* lcl_GetDrawingUnderline(FontLineStyle eUnderline) +{ + switch (eUnderline) + { + case LINESTYLE_NONE: + return "none"; + case LINESTYLE_DOUBLE: + return "dbl"; + default: + return "sng"; + } +} + } // namespace // Escher client anchor ======================================================= @@ -522,7 +614,7 @@ void XclExpControlHelper::WriteFormulaSubRec( XclExpStream& rStrm, sal_uInt16 nS rStrm.EndRecord(); } -//delete for exporting OCX +// Delete for exporting OCX //#if EXC_EXP_OCX_CTRL XclExpOcxControlObj::XclExpOcxControlObj( XclExpObjectManager& rObjMgr, Reference< XShape > const & xShape, @@ -557,7 +649,7 @@ XclExpOcxControlObj::XclExpOcxControlObj( XclExpObjectManager& rObjMgr, Referenc aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName ); // meta file - //TODO - needs check + // TODO - needs check Reference< XPropertySet > xShapePS( xShape, UNO_QUERY ); if( xShapePS.is() && aPropOpt.CreateGraphicProperties( xShapePS, u"MetaFile"_ustr, false ) ) { @@ -651,17 +743,35 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< mbScrollHor( false ), mbPrint( false ), mbVisible( false ), + mbStroked( false ), mnShapeId( 0 ), mrRoot(rRoot) { namespace FormCompType = css::form::FormComponentType; namespace AwtVisualEffect = css::awt::VisualEffect; namespace AwtScrollOrient = css::awt::ScrollBarOrientation; + namespace AwtTextAlign = css::awt::TextAlign; ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) ); if( !xShape.is() || !aCtrlProp.Is() ) return; + Reference xShapeProps(xShape, UNO_QUERY); + if (xShapeProps.is() + && xShapeProps->getPropertySetInfo()->hasPropertyByName(u"InteropGrabBag"_ustr)) + { + Sequence aGrabBag; + xShapeProps->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag; + for (auto& aProp : aGrabBag) + { + if (aProp.Name == "VMLStroked") + { + aProp.Value >>= mbStroked; + break; + } + } + } + mnHeight = xShape->getSize().Height; if( mnHeight <= 0 ) return; @@ -711,7 +821,7 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< if( aCtrlProp.GetProperty( msCtrlName, u"Name"_ustr ) && !msCtrlName.isEmpty() ) aPropOpt.AddOpt( ESCHER_Prop_wzName, msCtrlName ); - //Export description as alt text + // Export description as alt text if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) ) { OUString aAltTxt; @@ -744,18 +854,49 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< mrEscherEx.AddAtom( 0, ESCHER_ClientTextbox ); // TXO record mrEscherEx.UpdateDffFragmentEnd(); - sal_uInt16 nXclFont = EXC_FONT_APP; if( !msLabel.isEmpty() ) { - XclFontData aFontData; - GetFontPropSetHelper().ReadFontProperties( aFontData, aCtrlProp, EXC_FONTPROPSET_CONTROL ); - if( (!aFontData.maName.isEmpty() ) && (aFontData.mnHeight > 0) ) - nXclFont = GetFontBuffer().Insert( aFontData, EXC_COLOR_CTRLTEXT ); + GetFontPropSetHelper().ReadFontProperties(maFontData, aCtrlProp, + EXC_FONTPROPSET_CONTROL); + if ((!maFontData.maName.isEmpty()) && (maFontData.mnHeight > 0)) + mnXclFont = GetFontBuffer().Insert(maFontData, EXC_COLOR_CTRLTEXT); } - pTxo.reset( new XclTxo( msLabel, nXclFont ) ); - pTxo->SetHorAlign( (mnObjType == EXC_OBJTYPE_BUTTON) ? EXC_OBJ_HOR_CENTER : EXC_OBJ_HOR_LEFT ); - pTxo->SetVerAlign( EXC_OBJ_VER_CENTER ); + // The default for Align is centered on a button, left elsewhere; the default for + // VerticalAlign is center + if (sal_Int16 nApiHorAlign = 0; aCtrlProp.GetProperty(nApiHorAlign, u"Align"_ustr)) + { + switch (nApiHorAlign) + { + case AwtTextAlign::CENTER: + mnTextHAlign = EXC_OBJ_HOR_CENTER; + break; + case AwtTextAlign::RIGHT: + mnTextHAlign = EXC_OBJ_HOR_RIGHT; + break; + default: + mnTextHAlign = EXC_OBJ_HOR_LEFT; + } + } + if (css::style::VerticalAlignment eApiVerAlign{}; + aCtrlProp.GetProperty(eApiVerAlign, u"VerticalAlign"_ustr)) + { + switch (eApiVerAlign) + { + case css::style::VerticalAlignment_TOP: + mnTextVAlign = EXC_OBJ_VER_TOP; + break; + case css::style::VerticalAlignment_BOTTOM: + mnTextVAlign = EXC_OBJ_VER_BOTTOM; + break; + default: + mnTextVAlign = EXC_OBJ_VER_CENTER; + } + } + + pTxo.reset( new XclTxo( msLabel, mnXclFont ) ); + pTxo->SetHorAlign( mnTextHAlign ); + pTxo->SetVerAlign( mnTextVAlign ); } mrEscherEx.CloseContainer(); // ESCHER_SpContainer @@ -1107,13 +1248,21 @@ public: const OUString& sControlName, const OUString& sFmlaLink, OUString aLabel, OUString aMacroName, sal_Int16 nState); bool m_bLook3d = true; + bool m_bStroked = false; std::optional m_oBackgroundFill; + XclFontData m_aFontData; + sal_uInt16 m_nXclFont = EXC_FONT_APP; + sal_uInt8 m_nTextHAlign = EXC_OBJ_HOR_LEFT; + sal_uInt8 m_nTextVAlign = EXC_OBJ_VER_CENTER; protected: using VMLExport::StartShape; sal_Int32 StartShape() override; using VMLExport::EndShape; void EndShape(sal_Int32 nShapeElement) override; + +private: + void WriteLabel(); }; VmlFormControlExporter::VmlFormControlExporter(const sax_fastparser::FSHelperPtr& p, @@ -1149,19 +1298,64 @@ sal_Int32 VmlFormControlExporter::StartShape() else AddShapeAttribute(XML_filled, "f"); + if (!m_bStroked) + AddShapeAttribute(XML_stroked, "f"); + return VMLExport::StartShape(); } +void VmlFormControlExporter::WriteLabel() +{ + sax_fastparser::FSHelperPtr pVmlDrawing = GetFS(); + + pVmlDrawing->startElement(XML_div, XML_style, lcl_GetVmlDivStyle(m_nTextHAlign)); + + const Color& rColor = m_aFontData.maComplexColor.getFinalColor(); + // the VML size is in twips, which is what XclFontData::mnHeight already holds + pVmlDrawing->startElement( + XML_font, XML_face, + sax_fastparser::UseIf(m_aFontData.maName, !m_aFontData.maName.isEmpty()), XML_size, + sax_fastparser::UseIf(OUString::number(m_aFontData.mnHeight), m_aFontData.mnHeight != 0), + XML_color, rColor == COL_AUTO ? u"auto"_ustr : "#" + rColor.AsRGBHexString()); + + // Excel writes the effects here as well as into the DrawingML run properties + const bool bBold = m_aFontData.GetScWeight() > WEIGHT_NORMAL; + const FontLineStyle eUnderline = m_aFontData.GetScUnderline(); + if (bBold) + pVmlDrawing->startElement(XML_b); + if (m_aFontData.mbItalic) + pVmlDrawing->startElement(XML_i); + if (eUnderline != LINESTYLE_NONE) + { + // a bare cannot say "double", so Excel points at the workbook font record instead + const OString aFontClass = OString::Concat("font") + OString::number(m_nXclFont); + const bool bDouble = eUnderline == LINESTYLE_DOUBLE && m_nXclFont != EXC_FONT_APP; + pVmlDrawing->startElement(XML_u, XML_class, sax_fastparser::UseIf(aFontClass, bDouble)); + } + if (m_aFontData.mbStrikeout) + pVmlDrawing->startElement(XML_s); + + pVmlDrawing->writeEscaped(m_aLabel); + + if (m_aFontData.mbStrikeout) + pVmlDrawing->endElement(XML_s); + if (eUnderline != LINESTYLE_NONE) + pVmlDrawing->endElement(XML_u); + if (m_aFontData.mbItalic) + pVmlDrawing->endElement(XML_i); + if (bBold) + pVmlDrawing->endElement(XML_b); + pVmlDrawing->endElement(XML_font); + + pVmlDrawing->endElement(XML_div); +} + void VmlFormControlExporter::EndShape(sal_Int32 nShapeElement) { sax_fastparser::FSHelperPtr pVmlDrawing = GetFS(); pVmlDrawing->startElement(FSNS(XML_v, XML_textbox)); - pVmlDrawing->startElement(XML_div); - pVmlDrawing->startElement(XML_font); - pVmlDrawing->writeEscaped(m_aLabel); - pVmlDrawing->endElement(XML_font); - pVmlDrawing->endElement(XML_div); + WriteLabel(); pVmlDrawing->endElement(FSNS(XML_v, XML_textbox)); OString aObjectType; @@ -1195,12 +1389,17 @@ void VmlFormControlExporter::EndShape(sal_Int32 nShapeElement) if (!m_bLook3d) pVmlDrawing->singleElement(FSNS(XML_x, XML_NoThreeD)); - // XclExpOcxControlObj::WriteSubRecs() has the same fixed values. - if (m_nObjType == EXC_OBJTYPE_BUTTON) + // Excel leaves these out for Left and Top, which the import applies when they are missing + if (m_nTextHAlign != EXC_OBJ_HOR_LEFT) { - XclXmlUtils::WriteElement(pVmlDrawing, FSNS(XML_x, XML_TextHAlign), "Center"); + XclXmlUtils::WriteElement(pVmlDrawing, FSNS(XML_x, XML_TextHAlign), + lcl_GetVmlHorAlign(m_nTextHAlign)); + } + if (m_nTextVAlign != EXC_OBJ_VER_TOP) + { + XclXmlUtils::WriteElement(pVmlDrawing, FSNS(XML_x, XML_TextVAlign), + lcl_GetVmlVerAlign(m_nTextVAlign)); } - XclXmlUtils::WriteElement(pVmlDrawing, FSNS(XML_x, XML_TextVAlign), "Center"); if (!m_sFmlaLink.isEmpty()) XclXmlUtils::WriteElement(pVmlDrawing, FSNS(XML_x, XML_FmlaLink), m_sFmlaLink); @@ -1232,7 +1431,12 @@ void XclExpTbxControlObj::SaveVml(XclExpXmlStream& rStrm) aFormControlExporter.SetSkipwzName(true); // use XML_id for legacyid, not XML_ID aFormControlExporter.OverrideShapeIDGen(true, "_x0000_s"_ostr); aFormControlExporter.m_bLook3d = !mbFlatButton; + aFormControlExporter.m_bStroked = mbStroked; aFormControlExporter.m_oBackgroundFill = moBackgroundFill; + aFormControlExporter.m_aFontData = maFontData; + aFormControlExporter.m_nXclFont = mnXclFont; + aFormControlExporter.m_nTextHAlign = mnTextHAlign; + aFormControlExporter.m_nTextVAlign = mnTextVAlign; aFormControlExporter.AddSdrObject(*pObj, /*bIsFollowingTextFlow=*/false, /*eHOri=*/-1, /*eVOri=*/-1, /*eHRel=*/-1, /*eVRel=*/-1, /*pWrapAttrList=*/nullptr, /*bOOxmlExport=*/true, mnShapeId); @@ -1262,6 +1466,39 @@ void XclExpTbxControlObj::WriteAnchor(const sax_fastparser::FSHelperPtr& rTarget rTarget->endElement(bIsDrawing ? FSNS(XML_xdr, XML_to) : XML_to); } +void XclExpTbxControlObj::WriteLabelFont(const sax_fastparser::FSHelperPtr& rTarget) const +{ + // the VML can only say "double" through the font record mnXclFont names, so without one + // both halves say single rather than disagreeing + FontLineStyle eUnderline = maFontData.GetScUnderline(); + if (eUnderline == LINESTYLE_DOUBLE && mnXclFont == EXC_FONT_APP) + eUnderline = LINESTYLE_SINGLE; + + // a:rPr wants hundredths of a point, XclFontData::mnHeight is in twips + rTarget->startElementNS( + XML_a, XML_rPr, XML_sz, + sax_fastparser::UseIf(OString::number(maFontData.mnHeight * 5), maFontData.mnHeight != 0), + XML_b, ToPsz10(maFontData.GetScWeight() > WEIGHT_NORMAL), XML_i, + ToPsz10(maFontData.mbItalic), XML_u, lcl_GetDrawingUnderline(eUnderline), + XML_strike, maFontData.mbStrikeout ? "sngStrike" : "noStrike"); + + if (const Color& rColor = maFontData.maComplexColor.getFinalColor(); rColor != COL_AUTO) + { + rTarget->startElementNS(XML_a, XML_solidFill); + rTarget->singleElementNS(XML_a, XML_srgbClr, XML_val, + I32SHEX(sal_uInt32(rColor) & 0x00FFFFFF)); + rTarget->endElementNS(XML_a, XML_solidFill); + } + + if (!maFontData.maName.isEmpty()) + { + rTarget->singleElementNS(XML_a, XML_latin, XML_typeface, maFontData.maName); + rTarget->singleElementNS(XML_a, XML_cs, XML_typeface, maFontData.maName); + } + + rTarget->endElementNS(XML_a, XML_rPr); +} + // save into xl\drawings\drawing1.xml void XclExpTbxControlObj::SaveXml( XclExpXmlStream& rStrm ) { @@ -1282,11 +1519,26 @@ void XclExpTbxControlObj::SaveXml( XclExpXmlStream& rStrm ) // xdr:nvSpPr pDrawing->startElement(FSNS(XML_xdr, XML_nvSpPr)); { - pDrawing->singleElement(FSNS(XML_xdr, XML_cNvPr), - XML_id, OString::number(mnShapeId), - XML_name, msCtrlName, // control name - XML_descr, msLabel, // description as alt text - XML_hidden, mbVisible ? "0" : "1"); + // The form control's visible rendering comes from the VML + // companion shape in vmlDrawing1.vml; this DrawingML entry is + // an anchor/compatibility record, so it is always hidden and + // linked to the VML shape via compatExt/@spid. Without this, + // Excel renders both representations and the control appears + // doubled. + pDrawing->startElement(FSNS(XML_xdr, XML_cNvPr), XML_id, OString::number(mnShapeId), + XML_name, msCtrlName, // control name + XML_descr, msLabel, // description as alt text + XML_hidden, "1"); + pDrawing->startElement(FSNS(XML_a, XML_extLst)); + pDrawing->startElement(FSNS(XML_a, XML_ext), + XML_uri, "{63B3BB69-23CF-44E3-9099-C40C66FF867C}"); + pDrawing->setAllowXEscape(false); + pDrawing->singleElement(FSNS(XML_a14, XML_compatExt), + XML_spid, "_x0000_s" + OString::number(mnShapeId)); + pDrawing->setAllowXEscape(true); + pDrawing->endElement(FSNS(XML_a, XML_ext)); + pDrawing->endElement(FSNS(XML_a, XML_extLst)); + pDrawing->endElement(FSNS(XML_xdr, XML_cNvPr)); pDrawing->singleElement(FSNS(XML_xdr, XML_cNvSpPr)); } pDrawing->endElement(FSNS(XML_xdr, XML_nvSpPr)); @@ -1361,7 +1613,7 @@ void XclExpTbxControlObj::SaveXml( XclExpXmlStream& rStrm ) XML_rIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nRight)), nRight != DEFLRINS), XML_tIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nTop)), nTop != DEFTBINS), XML_bIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nBottom)), nBottom != DEFTBINS), - XML_anchor, "ctr"); + XML_anchor, lcl_GetDrawingVerAlign(mnTextVAlign)); { bool bTextAutoGrowHeight = false; @@ -1385,7 +1637,10 @@ void XclExpTbxControlObj::SaveXml( XclExpXmlStream& rStrm ) { pDrawing->startElementNS(XML_a, XML_p); + pDrawing->singleElementNS(XML_a, XML_pPr, XML_algn, + lcl_GetDrawingHorAlign(mnTextHAlign)); pDrawing->startElementNS(XML_a, XML_r); + WriteLabelFont(pDrawing); pDrawing->startElementNS(XML_a, XML_t); pDrawing->writeEscaped(msLabel); pDrawing->endElementNS(XML_a, XML_t); @@ -1432,13 +1687,6 @@ OUString XclExpTbxControlObj::SaveControlPropertiesXml(XclExpXmlStream& rStrm) c if (mnState == EXC_OBJ_CHECKBOX_CHECKED) pFormControl->write(" checked=\"Checked\""); - pFormControl->write(" autoLine=\"false\""); - - if (mbPrint) - pFormControl->write(" print=\"true\""); - else - pFormControl->write(" print=\"false\""); - if (mxCellLinkAddress.IsValid()) { OUString aCellLink = mxCellLinkAddress.Format(ScRefFlags::ADDR_ABS, @@ -1449,7 +1697,9 @@ OUString XclExpTbxControlObj::SaveControlPropertiesXml(XclExpXmlStream& rStrm) c pFormControl->write(" fmlaLink=\""); if (aCellLink.indexOf('!') < 0) { - pFormControl->write(GetTabInfo().GetScTabName(mxCellLinkAddress.Tab())); + OUString sTabName = GetTabInfo().GetScTabName(mxCellLinkAddress.Tab()); + ScCompiler::CheckTabQuotes(sTabName); + pFormControl->writeEscaped(sTabName); pFormControl->write("!"); } pFormControl->write(aCellLink); @@ -1644,7 +1894,7 @@ void XclExpChartObj::SaveXml( XclExpXmlStream& rStrm ) sal_Int32 nChartCount = rStrm.getNewChartUniqueId(); sal_Int32 nID = rStrm.GetUniqueId(); aChartExport.WriteChartObj( mxShape, nID, nChartCount ); - // TODO: get the correcto chart number + // TODO: get the correct chart number } pDrawing->singleElement( FSNS( XML_xdr, XML_clientData) @@ -1703,8 +1953,11 @@ XclExpNote::XclExpNote(const XclExpRoot& rRoot, const ScAddress& rScPos, if( SdrCaptionObj* pCaption = pScNote->GetOrCreateCaption( maScPos ) ) { lcl_GetFromTo( rRoot, pCaption->GetLogicRect(), maScPos.Tab(), maCommentFrom, maCommentTo ); - if( const OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() ) - mnObjId = rRoot.GetObjectManager().AddObj( std::make_unique( rRoot.GetObjectManager(), pCaption->GetLogicRect(), pOPO->GetTextObject(), pCaption, mbVisible, maScPos, maCommentFrom, maCommentTo ) ); + const OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject(); + const EditTextObject* pEditObj = pOPO ? &pOPO->GetTextObject() : nullptr; + mnObjId = rRoot.GetObjectManager().AddObj(std::make_unique( + rRoot.GetObjectManager(), pCaption->GetLogicRect(), pEditObj, pCaption, + mbVisible, maScPos, maCommentFrom, maCommentTo)); SfxItemSet aItemSet = pCaption->GetMergedItemSet(); meTVA = pCaption->GetTextVerticalAdjust(); @@ -1738,6 +1991,13 @@ XclExpNote::XclExpNote(const XclExpRoot& rRoot, const ScAddress& rScPos, if (const EditTextObject *pEditObj = pScNote->GetEditTextObject()) mpNoteContents = XclExpStringHelper::CreateString( rRoot, *pEditObj ); + + if (const ScThreadedCommentData* pThreadedData = pScNote->GetThreadedCommentData()) + { + maThreadedCommentGuid = pThreadedData->maRoot.maGuid; + // Legacy comment author must be tc={guid} for Excel to link it + maAuthor = XclExpString(u"tc=" + maThreadedCommentGuid, XclStrFlags::NONE, 54); + } } SetRecSize( 9 + maAuthor.GetSize() ); @@ -1816,10 +2076,10 @@ void XclExpNote::WriteXml( sal_Int32 nAuthorId, XclExpXmlStream& rStrm ) sax_fastparser::FSHelperPtr rComments = rStrm.GetCurrentStream(); rComments->startElement( XML_comment, - XML_ref, XclXmlUtils::ToOString(mrRoot.GetDoc(), ScRange(maScPos)), - XML_authorId, OString::number(nAuthorId) - // OOXTODO: XML_guid - ); + XML_ref, XclXmlUtils::ToOString(mrRoot.GetDoc(), ScRange(maScPos)), + XML_authorId, OString::number(nAuthorId), + XML_guid, sax_fastparser::UseIf(maThreadedCommentGuid, + !maThreadedCommentGuid.isEmpty())); rComments->startElement(XML_text); // OOXTODO: phoneticPr, rPh, r if( mpNoteContents ) @@ -1931,8 +2191,10 @@ void XclExpShapeObj::WriteSubRecs( XclExpStream& rStrm ) WriteMacroSubRec( rStrm ); } -XclExpComments::XclExpComments( SCTAB nTab, XclExpRecordList< XclExpNote >& rNotes ) - : mnTab( nTab ), mrNotes( rNotes ) +XclExpComments::XclExpComments(SCTAB nTab, XclExpRecordList& rNotes, ScDocument& rDoc) + : mnTab(nTab) + , mrNotes(rNotes) + , mrDoc(rDoc) { } @@ -1996,6 +2258,73 @@ void XclExpComments::SaveXml( XclExpXmlStream& rStrm ) rComments->endElement( XML_comments ); rStrm.PopStream(); + + SaveThreadedCommentsXml(rStrm); +} + +void XclExpComments::SaveThreadedCommentsXml(XclExpXmlStream& rStrm) +{ + // Collect notes with threaded comment data on this sheet. + std::vector aNotes; + mrDoc.GetAllNoteEntries(mnTab, aNotes); + + std::vector aThreaded; + for (const auto& rEntry : aNotes) + { + if (rEntry.mpNote->GetThreadedCommentData()) + aThreaded.push_back(&rEntry); + } + + if (aThreaded.empty()) + return; + + sax_fastparser::FSHelperPtr pStream = rStrm.CreateOutputStream( + XclXmlUtils::GetStreamName("xl/", "threadedComments/threadedComment", mnTab + 1), + XclXmlUtils::GetStreamName("../", "threadedComments/threadedComment", mnTab + 1), + rStrm.GetCurrentStream()->getOutputStream(), + "application/vnd.ms-excel.threadedcomments+xml", + oox::getRelationship(Relationship::THREADEDCOMMENT)); + rStrm.PushStream(pStream); + + pStream->startElement(XML_ThreadedComments, + XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xthreaded))); + + for (const auto* pEntry : aThreaded) + { + const ScThreadedCommentData* pData = pEntry->mpNote->GetThreadedCommentData(); + OString aRef = XclXmlUtils::ToOString(mrDoc, ScRange(pEntry->maPos)); + + // Root comment. + pStream->startElement(XML_threadedComment, + XML_ref, aRef, + XML_dT, sax_fastparser::UseIf(pData->maRoot.maDateTime, + !pData->maRoot.maDateTime.isEmpty()), + XML_personId, pData->maRoot.maPersonId, + XML_id, pData->maRoot.maGuid, + XML_done, sax_fastparser::UseIf("1", pData->mbDone)); + pStream->startElement(XML_text); + pStream->writeEscaped(pData->maRoot.maText); + pStream->endElement(XML_text); + pStream->endElement(XML_threadedComment); + + // Replies. + for (const auto& rReply : pData->maReplies) + { + pStream->startElement(XML_threadedComment, + XML_ref, aRef, + XML_dT, sax_fastparser::UseIf(rReply.maDateTime, !rReply.maDateTime.isEmpty()), + XML_personId, rReply.maPersonId, + XML_id, rReply.maGuid, + XML_parentId, pData->maRoot.maGuid); + pStream->startElement(XML_text); + pStream->writeEscaped(rReply.maText); + pStream->endElement(XML_text); + pStream->endElement(XML_threadedComment); + } + } + + pStream->endElement(XML_ThreadedComments); + rStrm.PopStream(); } // object manager ============================================================= @@ -2035,7 +2364,7 @@ void XclExpObjectManager::StartSheet() mxObjList = new XclExpObjList( GetRoot(), *mxEscherEx ); } -rtl::Reference< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const SdrPage* pSdrPage ) +rtl::Reference< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const SdrPage* pSdrPage, std::unique_ptr pImgData ) { if( pSdrPage ) mxEscherEx->AddSdrPage( *pSdrPage, GetOutput() != EXC_OUTPUT_BINARY ); @@ -2043,6 +2372,8 @@ rtl::Reference< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const Sd OSL_ENSURE( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" ); while( mxEscherEx->GetGroupLevel() ) mxEscherEx->LeaveGroup(); + if (pImgData) + mxObjList->SetImageData(std::move(pImgData)); mxObjList->EndSheet(); return mxObjList; } diff --git a/sc/source/filter/excel/xeextlst.cxx b/sc/source/filter/excel/xeextlst.cxx index c2b9e3469802..dca560d8ca6d 100644 --- a/sc/source/filter/excel/xeextlst.cxx +++ b/sc/source/filter/excel/xeextlst.cxx @@ -13,7 +13,9 @@ #include #include +#include #include +#include #include #include #include @@ -149,6 +151,10 @@ XclExpExtCF::XclExpExtCF( const XclExpRoot& rRoot, const ScCondFormatEntry& rFor XclExpRoot(rRoot), mrFormat(rFormat) { + // Explicitly register external references if the formula contains any + XclExpFormulaCompiler& rFmlaComp = GetFormulaCompiler(); + std::unique_ptr pTokenArray(mrFormat.CreateFlatCopiedTokenArray(0)); + rFmlaComp.CreateFormula(EXC_FMLATYPE_CONDFMT, *pTokenArray); } namespace { diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx index 91b7ec58fa89..0125484a91da 100644 --- a/sc/source/filter/excel/xeformula.cxx +++ b/sc/source/filter/excel/xeformula.cxx @@ -128,7 +128,6 @@ public: const XclFunctionInfo& rFuncInfo, XclExpExtFuncData aExtFuncData ); - const FormulaToken& GetScToken() const { return *mrTokData.mpScToken; } OpCode GetOpCode() const { return mrFuncInfo.meOpCode; } sal_uInt16 GetXclFuncIdx() const { return mrFuncInfo.mnXclFunc; } bool IsVolatile() const { return mrFuncInfo.IsVolatile(); } @@ -172,8 +171,9 @@ XclExpFuncData::XclExpFuncData( const XclExpScToken& rTokData, { OSL_ENSURE( mrTokData.mpScToken, "XclExpFuncData::XclExpFuncData - missing core token" ); // set name of an add-in function - if( (maExtFuncData.maFuncName.isEmpty()) && dynamic_cast< const FormulaExternalToken* >( mrTokData.mpScToken ) ) - maExtFuncData.Set( GetScToken().GetExternal(), true, false ); + if( maExtFuncData.maFuncName.isEmpty() ) + if( auto pFEToken = dynamic_cast< const FormulaExternalToken* >( mrTokData.mpScToken ) ) + maExtFuncData.Set( pFEToken->GetExternal(), true, false ); } const XclFuncParamInfo& XclExpFuncData::GetParamInfo() const @@ -844,9 +844,16 @@ bool XclExpFmlaCompImpl::GetNextToken( XclExpScToken& rTokData ) rTokData.mpScToken = GetNextRawToken(); rTokData.mnSpaces = 0; /* TODO: handle ocWhitespace characters? */ - while (rTokData.GetOpCode() == ocSpaces || rTokData.GetOpCode() == ocWhitespace) + // XLS predates the @ implicit-intersection operator. The BIFF token + // stream has no encoding for ocSingleValue, so drop it on the way out + // and let the operand flow through unchanged. XLS does not auto-spill + // anyway, so the saved formula evaluates to the same upper-left value + // it did before. + while (rTokData.GetOpCode() == ocSpaces || rTokData.GetOpCode() == ocWhitespace + || rTokData.GetOpCode() == ocSingleValue) { - rTokData.mnSpaces += rTokData.mpScToken->GetByte(); + if (rTokData.GetOpCode() != ocSingleValue) + rTokData.mnSpaces += static_cast(rTokData.mpScToken)->GetByte(); rTokData.mpScToken = GetNextRawToken(); } return rTokData.Is(); @@ -1226,7 +1233,7 @@ XclExpScToken XclExpFmlaCompImpl::Factor( XclExpScToken aTokData ) void XclExpFmlaCompImpl::ProcessDouble( const XclExpScToken& rTokData ) { - double fValue = rTokData.mpScToken->GetDouble(); + double fValue = static_cast(rTokData.mpScToken)->GetDouble(); double fInt; double fFrac = modf( fValue, &fInt ); if( (fFrac == 0.0) && (0.0 <= fInt) && (fInt <= 65535.0) ) @@ -1238,7 +1245,7 @@ void XclExpFmlaCompImpl::ProcessDouble( const XclExpScToken& rTokData ) void XclExpFmlaCompImpl::ProcessString( const XclExpScToken& rTokData ) { AppendOperandTokenId( EXC_TOKID_STR, rTokData.mnSpaces ); - Append( rTokData.mpScToken->GetString().getString() ); + Append( static_cast(rTokData.mpScToken)->GetString().getString() ); } void XclExpFmlaCompImpl::ProcessMissing( const XclExpScToken& rTokData ) @@ -1272,7 +1279,7 @@ bool lclGetTokenString( OUString& rString, const XclExpScToken& rTokData ) { bool bIsStr = (rTokData.GetType() == svString) && (rTokData.GetOpCode() == ocPush); if( bIsStr ) - rString = rTokData.mpScToken->GetString().getString(); + rString = static_cast(rTokData.mpScToken)->GetString().getString(); return bIsStr; } @@ -1312,14 +1319,14 @@ void XclExpFmlaCompImpl::ProcessExternal( const XclExpScToken& rTokData ) token is processed as external function call, otherwise as undefined name. */ const FormulaToken* pNextScToken = PeekNextRawToken(); if( !pNextScToken || (pNextScToken->GetOpCode() != ocOpen) ) - AppendMissingNameToken( rTokData.mpScToken->GetExternal(), rTokData.mnSpaces ); + AppendMissingNameToken( static_cast(rTokData.mpScToken)->GetExternal(), rTokData.mnSpaces ); else ProcessFunction( rTokData ); } void XclExpFmlaCompImpl::ProcessMatrix( const XclExpScToken& rTokData ) { - const ScMatrix* pMatrix = rTokData.mpScToken->GetMatrix(); + const ScMatrix* pMatrix = static_cast(rTokData.mpScToken)->GetMatrix(); if( pMatrix && mxData->mrCfg.mbAllowArrays ) { SCSIZE nScCols, nScRows; @@ -1395,7 +1402,7 @@ void XclExpFmlaCompImpl::ProcessFunction( const XclExpScToken& rTokData ) XclExpExtFuncData aExtFuncData; // no exportable function found - try to create an external macro call - if( !pFuncInfo && (eOpCode >= SC_OPCODE_START_NO_PAR) ) + if( !pFuncInfo && (eOpCode >= ocStartNoParameters) ) { const OUString& rFuncName = ScCompiler::GetNativeSymbol( eOpCode ); if( !rFuncName.isEmpty() ) @@ -1686,6 +1693,7 @@ void XclExpFmlaCompImpl::AppendDefaultParam( XclExpFuncData& rFuncData ) switch( rFuncData.GetOpCode() ) { case ocExternal: + case ocUDExternal: AppendAddInCallToken( rFuncData.GetExtFuncData() ); break; case ocEuroConvert: @@ -1763,6 +1771,7 @@ void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData ) break; case ocExternal: + case ocUDExternal: case ocMacro: // external or macro call without parameters needs the external name reference if( nParamCount == 0 ) @@ -1974,7 +1983,7 @@ void XclExpFmlaCompImpl::ProcessCellRef( const XclExpScToken& rTokData ) { // get the Excel address components, adjust internal data in aRefData bool bNatLangRef = (meBiff == EXC_BIFF8) && mxData->mpScBasePos && (rTokData.GetOpCode() == ocColRowName); - ScSingleRefData aRefData = *rTokData.mpScToken->GetSingleRef(); + ScSingleRefData aRefData = static_cast(rTokData.mpScToken)->GetSingleRef(); XclAddress aXclPos( ScAddress::UNINITIALIZED ); ConvertRefData( aRefData, aXclPos, bNatLangRef, false, false ); @@ -2031,7 +2040,7 @@ void XclExpFmlaCompImpl::ProcessCellRef( const XclExpScToken& rTokData ) void XclExpFmlaCompImpl::ProcessRangeRef( const XclExpScToken& rTokData ) { // get the Excel address components, adjust internal data in aRefData - ScComplexRefData aRefData = *rTokData.mpScToken->GetDoubleRef(); + ScComplexRefData aRefData = static_cast(rTokData.mpScToken)->GetDoubleRef(); XclRange aXclRange( ScAddress::UNINITIALIZED ); ConvertRefData( aRefData, aXclRange, false ); @@ -2077,15 +2086,20 @@ void XclExpFmlaCompImpl::ProcessExternalCellRef( const XclExpScToken& rTokData ) { if( mxData->mpLinkMgr ) { + auto pESRToken = static_cast(rTokData.mpScToken); // get the Excel address components, adjust internal data in aRefData - ScSingleRefData aRefData = *rTokData.mpScToken->GetSingleRef(); + ScSingleRefData aRefData = pESRToken->GetSingleRef(); XclAddress aXclPos( ScAddress::UNINITIALIZED ); ConvertRefData( aRefData, aXclPos, false, false, false ); - // store external cell contents in CRN records - sal_uInt16 nFileId = rTokData.mpScToken->GetIndex(); - OUString aTabName = rTokData.mpScToken->GetString().getString(); - if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos ) + // Store external cell contents in CRN records. A chart series is not + // a cell formula, but still needs its referenced external value + // cached here: it is the only thing that keeps the cache from + // exporting empty once nothing else in the sheet uses the same + // external range. + sal_uInt16 nFileId = pESRToken->GetFileId(); + OUString aTabName = pESRToken->GetTableName().getString(); + if( (mxData->mrCfg.mbFromCell || mxData->mrCfg.meType == EXC_FMLATYPE_CHART) && mxData->mpScBasePos ) mxData->mpLinkMgr->StoreCell(nFileId, aTabName, aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos)); // 1-based EXTERNSHEET index and 0-based Excel sheet indexes @@ -2113,15 +2127,17 @@ void XclExpFmlaCompImpl::ProcessExternalRangeRef( const XclExpScToken& rTokData { if( mxData->mpLinkMgr ) { + auto pEDRToken = static_cast(rTokData.mpScToken); // get the Excel address components, adjust internal data in aRefData - ScComplexRefData aRefData = *rTokData.mpScToken->GetDoubleRef(); + ScComplexRefData aRefData = pEDRToken->GetDoubleRef(); XclRange aXclRange( ScAddress::UNINITIALIZED ); ConvertRefData( aRefData, aXclRange, false ); - // store external cell contents in CRN records - sal_uInt16 nFileId = rTokData.mpScToken->GetIndex(); - OUString aTabName = rTokData.mpScToken->GetString().getString(); - if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos ) + // Store external cell contents in CRN records, for the same reason + // as in ProcessExternalCellRef above. + sal_uInt16 nFileId = pEDRToken->GetFileId(); + OUString aTabName = pEDRToken->GetTableName().getString(); + if( (mxData->mrCfg.mbFromCell || mxData->mrCfg.meType == EXC_FMLATYPE_CHART) && mxData->mpScBasePos ) mxData->mpLinkMgr->StoreCellRange(nFileId, aTabName, aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos)); // 1-based EXTERNSHEET index and 0-based Excel sheet indexes @@ -2149,11 +2165,12 @@ void XclExpFmlaCompImpl::ProcessExternalRangeRef( const XclExpScToken& rTokData void XclExpFmlaCompImpl::ProcessDefinedName( const XclExpScToken& rTokData ) { - sal_Int16 nSheet = rTokData.mpScToken->GetSheet(); + auto pIndexToken = static_cast(rTokData.mpScToken); + sal_Int16 nSheet = pIndexToken->GetSheet(); SCTAB nTab = (nSheet < 0 ? SCTAB_GLOBAL : nSheet); XclExpNameManager& rNameMgr = GetNameManager(); - sal_uInt16 nNameIdx = rNameMgr.InsertName(nTab, rTokData.mpScToken->GetIndex(), GetCurrScTab()); + sal_uInt16 nNameIdx = rNameMgr.InsertName(nTab, pIndexToken->GetIndex(), GetCurrScTab()); if( nNameIdx != 0 ) { // global names always with tName token, local names dependent on config @@ -2181,9 +2198,10 @@ void XclExpFmlaCompImpl::ProcessExternalName( const XclExpScToken& rTokData ) { if( mxData->mpLinkMgr ) { + auto pExtNameToken = static_cast(rTokData.mpScToken); ScExternalRefManager& rExtRefMgr = *GetDoc().GetExternalRefManager(); - sal_uInt16 nFileId = rTokData.mpScToken->GetIndex(); - OUString aName = rTokData.mpScToken->GetString().getString(); + sal_uInt16 nFileId = pExtNameToken->GetFileId(); + OUString aName = pExtNameToken->GetName().getString(); ScExternalRefCache::TokenArrayRef xArray = rExtRefMgr.getRangeNameTokens( nFileId, aName ); if( xArray ) { @@ -2199,16 +2217,17 @@ void XclExpFmlaCompImpl::ProcessExternalName( const XclExpScToken& rTokData ) { case svExternalSingleRef: { - ScSingleRefData aRefData = *pScToken->GetSingleRef(); + ScSingleRefData aRefData = static_cast(pScToken)->GetSingleRef(); mxData->mpLinkMgr->StoreCell( - nFileId, pScToken->GetString().getString(), aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos)); + nFileId, static_cast(pScToken)->GetTableName().getString(), aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos)); } break; case svExternalDoubleRef: { - ScComplexRefData aRefData = *pScToken->GetDoubleRef(); + auto pEDRToken = static_cast(pScToken); + ScComplexRefData aRefData = pEDRToken->GetDoubleRef(); mxData->mpLinkMgr->StoreCellRange( - nFileId, pScToken->GetString().getString(), aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos)); + nFileId, pEDRToken->GetTableName().getString(), aRefData.toAbs(GetRoot().GetDoc(), *mxData->mpScBasePos)); } break; default: diff --git a/sc/source/filter/excel/xehelper.cxx b/sc/source/filter/excel/xehelper.cxx index 71761b18264a..a0890d86c623 100644 --- a/sc/source/filter/excel/xehelper.cxx +++ b/sc/source/filter/excel/xehelper.cxx @@ -440,7 +440,7 @@ XclExpStringRef lclCreateFormattedString( // font buffer and helper item set for edit engine -> Calc item conversion XclExpFontBuffer& rFontBuffer = rRoot.GetFontBuffer(); - SfxItemSetFixed aItemSet( *rRoot.GetDoc().GetPool() ); + SfxItemSet aItemSet(SfxItemSet::makeFixedSfxItemSet( *rRoot.GetDoc().GetPool()) ); // script type handling Reference< XBreakIterator > xBreakIt = rRoot.GetDoc().GetBreakIterator(); @@ -700,7 +700,7 @@ void XclExpHFConverter::AppendPortion( const EditTextObject* pTextObj, sal_Unico OUString aText; sal_Int32 nHeight = 0; - SfxItemSetFixed aItemSet( *GetDoc().GetPool() ); + SfxItemSet aItemSet(SfxItemSet::makeFixedSfxItemSet( *GetDoc().GetPool() )); // edit engine bool bOldUpdateMode = mrEE.SetUpdateLayout( true ); @@ -765,7 +765,7 @@ void XclExpHFConverter::AppendPortion( const EditTextObject* pTextObj, sal_Unico (aNewData.mnWeight > EXC_FONTWGHT_NORMAL) ? WEIGHT_BOLD : WEIGHT_NORMAL, aNewData.mbItalic ? ITALIC_NORMAL : ITALIC_NONE ) ); aNewData.maStyle = pFontList->GetStyleName( aFontMetric ); - if( !aNewData.maStyle.isEmpty() ) + if( !aNewData.maStyle.isEmpty() && aNewData.maStyle != pFontList->GetNormalStr() ) aParaText.append("," + aNewData.maStyle); } aParaText.append("\""); diff --git a/sc/source/filter/excel/xelink.cxx b/sc/source/filter/excel/xelink.cxx index e47ab65f4c9e..60c8eae0f102 100644 --- a/sc/source/filter/excel/xelink.cxx +++ b/sc/source/filter/excel/xelink.cxx @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,8 @@ using ::com::sun::star::uno::Any; +constexpr int MAX_TAB_NAME_LENGTH = 31; + using namespace oox; // *** Helper classes *** @@ -363,6 +366,9 @@ private: XclSupbookType meType; /// Type of this SUPBOOK record. sal_uInt16 mnXclTabCount; /// Number of internal sheets. sal_uInt16 mnFileId; /// 1-based external reference file ID for OOXML + + bool mbPathMissing = false; /// true if external relation is xlPathMissing. + bool mbXlStartup = false; /// true if path is relative to XLSTART folder. }; // All SUPBOOKS in a document ================================================= @@ -514,8 +520,13 @@ public: /** Derived classes write the entire link table to the passed OOXML stream. */ virtual void SaveXml( XclExpXmlStream& rStrm ) = 0; + const std::unordered_map& GetTruncatedSheetMap(sal_uInt16 nFileId); + protected: explicit XclExpLinkManagerImpl( const XclExpRoot& rRoot ); + +private: + std::unordered_map> maTruncatedSheetMaps; }; namespace { @@ -960,7 +971,7 @@ void XclExpExtName::WriteAddData( XclExpStream& rStrm ) { case svExternalSingleRef: { - const ScSingleRefData& rRef = *p->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(p)->GetSingleRef(); if (rRef.IsTabRel()) break; @@ -971,7 +982,7 @@ void XclExpExtName::WriteAddData( XclExpStream& rStrm ) if (bColRel) nCol |= 0x4000; if (bRowRel) nCol |= 0x8000; - OUString aTabName = p->GetString().getString(); + OUString aTabName = static_cast(p)->GetTableName().getString(); sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName); // size is always 9 @@ -984,7 +995,8 @@ void XclExpExtName::WriteAddData( XclExpStream& rStrm ) } case svExternalDoubleRef: { - const ScComplexRefData& rRef = *p->GetDoubleRef(); + auto pEDRToken = static_cast(p); + const ScComplexRefData& rRef = pEDRToken->GetDoubleRef(); const ScSingleRefData& r1 = rRef.Ref1; const ScSingleRefData& r2 = rRef.Ref2; if (r1.IsTabRel() || r2.IsTabRel()) @@ -1006,7 +1018,7 @@ void XclExpExtName::WriteAddData( XclExpStream& rStrm ) if (bCol2Rel) nCol2 |= 0x4000; if (bRow2Rel) nCol2 |= 0x8000; - OUString aTabName = p->GetString().getString(); + OUString aTabName = pEDRToken->GetTableName().getString(); sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName); // size is always 13 (0x0D) @@ -1361,14 +1373,20 @@ bool XclExpXct::BuildCrnList( XclExpCrnList& rCrnRecs ) switch( xToken->GetType() ) { case svDouble: + { + double fVal = static_cast(xToken.get())->GetDouble(); bValid = (rFormatter.GetType( nScNumFmt ) == SvNumFormatType::LOGICAL) ? - rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) : - rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) ); + rCrnRecs.InsertValue( nScCol, nScRow, Any( fVal != 0 ) ) : + rCrnRecs.InsertValue( nScCol, nScRow, Any( fVal ) ); + } break; case svString: + { + auto pSToken = static_cast(xToken.get()); // do not save empty strings (empty cells) to cache - if( !xToken->GetString().isEmpty() ) - bValid = rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetString().getString() ) ); + if( !pSToken->GetString().isEmpty() ) + bValid = rCrnRecs.InsertValue( nScCol, nScRow, Any( pSToken->GetString().getString() ) ); + } break; default: break; @@ -1523,6 +1541,8 @@ XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl ) : ScExternalRefManager* pRefMgr = rRoot.GetDoc().GetExternalRefManager(); sal_uInt16 nFileId = pRefMgr->getExternalFileId( rUrl ); mnFileId = nFileId + 1; + mbPathMissing = pRefMgr->isPathMissing(nFileId); + mbXlStartup = pRefMgr->isXlStartup(nFileId); ScfStringVec aTabNames; pRefMgr->getAllCachedTableNames( nFileId, aTabNames ); size_t nTabIndex = 0; @@ -1661,20 +1681,29 @@ void XclExpSupbook::SaveXml( XclExpXmlStream& rStrm ) sax_fastparser::FSHelperPtr pExternalLink = rStrm.GetCurrentStream(); // Add relation for this stream, e.g. xl/externalLinks/_rels/externalLink1.xml.rels - sal_uInt16 nLevel = 0; - bool bRel = true; - - // BuildFileName delete ../ and convert them to nLevel - // but addrelation needs ../ instead of nLevel, so we have to convert it back - OUString sFile = XclExpHyperlink::BuildFileName(nLevel, bRel, maUrl, GetRoot(), true); - while (nLevel > 0) + OUString sFile = maUrl; + OUString sRelType; + if (mbPathMissing) + sRelType = oox::getRelationship(Relationship::MISSINGEXTERNALLINKPATH); + else if (mbXlStartup) + sRelType = oox::getRelationship(Relationship::XLSTARTUPEXTERNALLINKPATH); + else { - sFile = "../" + sFile; - --nLevel; + sal_uInt16 nLevel = 0; + bool bRel = true; + + // BuildFileName delete ../ and convert them to nLevel + // but addrelation needs ../ instead of nLevel, so we have to convert it back + sFile = XclExpHyperlink::BuildFileName(nLevel, bRel, maUrl, GetRoot(), true); + while (nLevel > 0) + { + sFile = "../" + sFile; + --nLevel; + } + sRelType = oox::getRelationship(Relationship::EXTERNALLINKPATH); } - OUString sId = rStrm.addRelation( pExternalLink->getOutputStream(), - oox::getRelationship(Relationship::EXTERNALLINKPATH), sFile, true ); + OUString sId = rStrm.addRelation(pExternalLink->getOutputStream(), sRelType, sFile, true); pExternalLink->startElement( XML_externalLink, XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8()); @@ -1688,11 +1717,22 @@ void XclExpSupbook::SaveXml( XclExpXmlStream& rStrm ) pExternalLink->startElement(XML_sheetNames); for (size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos) { - OString sSheetName = XclXmlUtils::ToOString(maXctList.GetRecord(nPos)->GetTabName()); + OUString sSheetName = XclXmlUtils::ToOUString(maXctList.GetRecord(nPos)->GetTabName()); // Sometimes `ReadUniString` could result in a garbage string // Guess whether the SheetName is valid by checking if it contains '?' - if (sSheetName.indexOf("?") != -1) - sSheetName = "Invalid_Sheet_Name_" + OString::number(sSheetName.getLength()); + if (sSheetName.indexOf(u'?') != -1) + { + sSheetName = u"Invalid_Sheet_Name_"_ustr + OUString::number(sSheetName.getLength()); + } + else + { + // mnFileId is 1-based; the link manager uses 0-based file IDs. + const auto& aTruncatedMap = GetGlobalLinkManager().GetTruncatedSheetMap(mnFileId - 1); + if (auto it = aTruncatedMap.find(sSheetName); it != aTruncatedMap.end()) + { + sSheetName = it->second; + } + } pExternalLink->singleElement(XML_sheetName, XML_val, sSheetName); } pExternalLink->endElement( XML_sheetNames); @@ -2189,6 +2229,52 @@ sal_uInt16 XclExpSupbookBuffer::Append( XclExpSupbookRef const & xSupbook ) // Export link manager ======================================================== +static std::unordered_map lcl_generate_truncated_sheet_map(const std::vector& rOriginalNames) +{ + std::unordered_map aTruncatedMap; + std::vector aNewTabNames; + aNewTabNames.reserve(rOriginalNames.size()); + + for (const auto& rOriginalName : rOriginalNames) + { + if (rOriginalName.getLength() > MAX_TAB_NAME_LENGTH) + { + OUString aNewName = XclExpXmlStream::GenerateUniqueTableName(rOriginalName, aNewTabNames, rOriginalNames); + if (!aNewName.isEmpty()) + { + aTruncatedMap[rOriginalName] = aNewName; + aNewTabNames.push_back(aNewName); + } + else + { + aNewTabNames.push_back(rOriginalName); + } + } + else + aNewTabNames.push_back(rOriginalName); + } + + return aTruncatedMap; +} + +const std::unordered_map& +XclExpLinkManagerImpl::GetTruncatedSheetMap(sal_uInt16 nFileId) +{ + auto [it, inserted] = maTruncatedSheetMaps.try_emplace(nFileId); + const bool bValidateTabNames = officecfg::Office::Calc::Filter::Export::MS_Excel::TruncateLongSheetNames::get(); + + if (inserted && bValidateTabNames) // don't populate the map if disable in config + { + std::vector aNames; + if (ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager()) + pRefMgr->getAllCachedTableNames(nFileId, aNames); + + it->second = lcl_generate_truncated_sheet_map(aNames); + } + + return it->second; +} + XclExpLinkManagerImpl::XclExpLinkManagerImpl( const XclExpRoot& rRoot ) : XclExpRoot( rRoot ) { @@ -2511,6 +2597,25 @@ void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm ) void XclExpLinkManagerImpl8::SaveXml( XclExpXmlStream& rStrm ) { + // Export external defined names used in drawing-shape macros + ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager(); + for (const auto& [nFileId, rNames] : pRefMgr->getDrawingMacros()) + { + const OUString* pUrl = pRefMgr->getExternalFileName(nFileId); + if (!pUrl || pUrl->isEmpty()) + continue; + // InsertExtName may push_back via getExternalFileId and pUrl then + // becomes invalidated, which is ok on first loop, but on the next + // it's a potential crash + const OUString aUrl = *pUrl; + for (const OUString& rName : rNames) + { + ScExternalRefCache::TokenArrayRef xEmpty + = std::make_shared(GetRoot().GetDoc()); + maSBBuffer.InsertExtName(aUrl, rName, xEmpty); + } + } + if (maSBBuffer.HasExternalReferences()) { sax_fastparser::FSHelperPtr pWorkbook = rStrm.GetCurrentStream(); @@ -2639,4 +2744,10 @@ void XclExpLinkManager::SaveXml( XclExpXmlStream& rStrm ) mxImpl->SaveXml( rStrm ); } +const std::unordered_map& +XclExpLinkManager::GetTruncatedSheetMap(sal_uInt16 nFileId) const +{ + return mxImpl->GetTruncatedSheetMap(nFileId); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/xename.cxx b/sc/source/filter/excel/xename.cxx index 6bd1ec43dbfe..ef08a6d7fcef 100644 --- a/sc/source/filter/excel/xename.cxx +++ b/sc/source/filter/excel/xename.cxx @@ -22,7 +22,9 @@ #include #include +#include #include +#include #include #include #include @@ -31,6 +33,7 @@ #include #include #include +#include #include #include @@ -41,6 +44,8 @@ using namespace ::oox; using namespace ::com::sun::star; +constexpr int MAX_TAB_NAME_LENGTH = 31; + // *** Helper classes *** namespace { @@ -347,7 +352,6 @@ void XclExpName::SaveXml( XclExpXmlStream& rStrm ) // (1 based) to get the sheetid as of the exported document's perspective. SCTAB nXlsxTab = mnXclTab - 1; OUString sName = ScCompiler::SanitizeDefinedName(maOrigName, GetDoc()); - // Regenerate symbol for external references if (ScTokenArray* pScTokArr = GetScTokenArray()) { @@ -365,12 +369,54 @@ void XclExpName::SaveXml( XclExpXmlStream& rStrm ) name should follow OOXML conventions */ if (!pNext || (pNext->GetOpCode() != ocOpen)) { - msSymbol = ScCompiler::SanitizeDefinedName(t->GetExternal(), GetDoc()); + msSymbol = ScCompiler::SanitizeDefinedName(static_cast(t)->GetExternal(), GetDoc()); break; } } else if (t->IsExternalRef()) { + // excel doesn't allow sheet names having length > 31 + do + { + if (t->IsExternalRef() && t->GetType() != formula::svExternalName) + { + formula::StackVar eType = t->GetType(); + OUString aSheetName; + if (eType == formula::svExternalSingleRef) + aSheetName = static_cast(t)->GetTableName().getString(); + else + aSheetName = static_cast(t)->GetTableName().getString(); + if (aSheetName.getLength() > MAX_TAB_NAME_LENGTH) + { + sal_uInt16 nFileId = static_cast(t)->GetFileId(); + const auto& aTruncatedMap + = GetRoot().GetGlobalLinkManager().GetTruncatedSheetMap(nFileId); + if (auto it = aTruncatedMap.find(aSheetName); it != aTruncatedMap.end()) + { + formula::FormulaToken* pNewToken = nullptr; + if (eType == formula::svExternalSingleRef) + { + auto pESRToken = static_cast(t); + pNewToken = new ScExternalSingleRefToken( + nFileId, svl::SharedString(it->second), + pESRToken->GetSingleRef()); + } + else if (eType == formula::svExternalDoubleRef) + { + auto pEDRToken = static_cast(t); + pNewToken = new ScExternalDoubleRefToken( + nFileId, svl::SharedString(it->second), + pEDRToken->GetDoubleRef()); + } + + if (pNewToken) + pScTokArr->ReplaceToken(aIter.GetIndex() - 1, pNewToken, + formula::FormulaTokenArray::CODE_ONLY); + } + } + } + t = aIter.Next(); + } while (t); msSymbol = XclXmlUtils::ToOUString(GetCompileFormulaContext(), GetPos(), pScTokArr); break; } @@ -424,13 +470,13 @@ static bool lcl_EnsureAbs3DToken( const SCTAB nTab, formula::FormulaToken* pTok, if ( !pTok || ( pTok->GetType() != formula::svSingleRef && pTok->GetType() != formula::svDoubleRef ) ) return bFixRequired; - ScSingleRefData* pRef1 = pTok->GetSingleRef(); + ScSingleRefData* pRef1 = ScRefTokenHelper::getSingleRef(pTok); if ( !pRef1 ) return bFixRequired; ScSingleRefData* pRef2 = nullptr; if ( pTok->GetType() == formula::svDoubleRef ) - pRef2 = pTok->GetSingleRef2(); + pRef2 = &static_cast(pTok)->GetSingleRef2(); if ( pRef1->IsTabRel() || !pRef1->IsFlag3D() ) { @@ -477,7 +523,7 @@ sal_uInt16 XclExpNameManagerImpl::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx, { sal_uInt16 nNameIdx = 0; const ScRangeData* pData = nullptr; - ScRangeName* pRN = (nTab == SCTAB_GLOBAL) ? GetDoc().GetRangeName() : GetDoc().GetRangeName(nTab); + ScRangeName* pRN = (nTab == SCTAB_GLOBAL) ? &GetDoc().GetRangeName() : GetDoc().GetRangeName(nTab); if (pRN) pData = pRN->findByIndex(nScNameIdx); @@ -635,17 +681,21 @@ sal_uInt16 XclExpNameManagerImpl::FindBuiltInNameIdx( OUString XclExpNameManagerImpl::GetUnusedName( const OUString& rName ) const { + const CharClass& rCharClass = ScGlobal::getCharClass(); OUString aNewName( rName ); sal_Int32 nAppIdx = 0; bool bExist = true; while( bExist ) { - // search the list of user-defined names + // search the list of user-defined names. Two names that differ + // only in letter case count as the same name, so compare the + // uppercase form of each pair. bExist = false; + OUString aUpperName( rCharClass.uppercase( aNewName ) ); for( size_t nPos = mnFirstUserIdx, nSize = maNameList.GetSize(); !bExist && (nPos < nSize); ++nPos ) { XclExpNameRef xName = maNameList.GetRecord( nPos ); - bExist = xName->GetOrigName() == aNewName; + bExist = rCharClass.uppercase( xName->GetOrigName() ) == aUpperName; // name exists -> create a new name "_" if( bExist ) aNewName = rName + "_" + OUString::number( ++nAppIdx ); @@ -695,7 +745,29 @@ sal_uInt16 XclExpNameManagerImpl::CreateName( SCTAB nTab, const ScRangeData& rRa if ( rRangeData.HasType( ScRangeData::Type::AbsPos ) || rRangeData.HasType( ScRangeData::Type::AbsArea ) ) { // Don't modify the actual document; use a temporary copy to create the export formulas. - lcl_EnsureAbs3DToken(nTab, pScTokArrCopy->FirstToken()); + + // Ensure 3D reference for global as well as local ranges + const SCTAB nLocalTab = (nTab == SCTAB_GLOBAL) ? rRangeData.GetPos().Tab() : nTab; + + // Ensure 3D reference for all the possible tokens + formula::FormulaToken** pFormulaArray = pScTokArrCopy->GetArray(); + const sal_uInt16 nLen = pScTokArrCopy->GetLen(); + for (sal_uInt16 i = 0; i < nLen; ++i) + { + formula::FormulaToken* pToken = pFormulaArray[i]; + // Skip references preceded by '!' (ocBad) - these are + // current-sheet references (e.g. !D3 in CELL("filename",!D3)) + // that will be wrongly converted. + if (pToken && pToken->GetOpCode() == ocBad + && static_cast(pToken)->GetString().getString() == "!") + { + // Skip the following reference token + if (i + 1 < nLen) + ++i; + continue; + } + lcl_EnsureAbs3DToken(nLocalTab, pToken); + } xTokArr = GetFormulaCompiler().CreateFormula(EXC_FMLATYPE_NAME, *pScTokArrCopy); if ( GetOutput() != EXC_OUTPUT_BINARY ) diff --git a/sc/source/filter/excel/xepage.cxx b/sc/source/filter/excel/xepage.cxx index dad649ab7256..f42f57c5db1f 100644 --- a/sc/source/filter/excel/xepage.cxx +++ b/sc/source/filter/excel/xepage.cxx @@ -251,7 +251,7 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) : maData.mbManualStart = maData.mnStartPage && (!nScTab || rDoc.NeedPageResetAfterTab( nScTab - 1 )); const SvxLRSpaceItem& rLRItem = rItemSet.Get( ATTR_LRSPACE ); - maData.mfLeftMargin = XclTools::GetInchFromTwips(rLRItem.ResolveLeft({})); + maData.mfLeftMargin = XclTools::GetInchFromTwips(rLRItem.ResolveLeft()); maData.mfRightMargin = XclTools::GetInchFromTwips(rLRItem.ResolveRight({})); const SvxULSpaceItem& rULItem = rItemSet.Get( ATTR_ULSPACE ); maData.mfTopMargin = XclTools::GetInchFromTwips( rULItem.GetUpper() ); diff --git a/sc/source/filter/excel/xepivotxml.cxx b/sc/source/filter/excel/xepivotxml.cxx index 31ea6aa56e19..fa29250aa42b 100644 --- a/sc/source/filter/excel/xepivotxml.cxx +++ b/sc/source/filter/excel/xepivotxml.cxx @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -145,13 +146,23 @@ XclExpXmlPivotCaches::XclExpXmlPivotCaches( const XclExpRoot& rRoot ) : void XclExpXmlPivotCaches::SaveXml( XclExpXmlStream& rStrm ) { sax_fastparser::FSHelperPtr& pWorkbookStrm = rStrm.GetCurrentStream(); - pWorkbookStrm->startElement(XML_pivotCaches); + bool bStartedPivotCaches = false; - for (size_t i = 0, n = maCaches.size(); i < n; ++i) + for (sal_Int32 nCacheId = 0; const auto& rEntry : maCaches) { - const Entry& rEntry = maCaches[i]; + const ScDPCache& rCache = *rEntry.mpCache; - sal_Int32 nCacheId = i + 1; + size_t nFieldCount = rCache.GetFieldCount() + rCache.GetGroupFieldCount(); + if (nFieldCount == 0) + continue; + + if (!bStartedPivotCaches) + { + bStartedPivotCaches = true; + pWorkbookStrm->startElement(XML_pivotCaches); + } + + ++nCacheId; OUString aRelId; sax_fastparser::FSHelperPtr pPCStrm = rStrm.CreateOutputStream( XclXmlUtils::GetStreamName("xl/pivotCache/", "pivotCacheDefinition", nCacheId), @@ -170,7 +181,8 @@ void XclExpXmlPivotCaches::SaveXml( XclExpXmlStream& rStrm ) rStrm.PopStream(); } - pWorkbookStrm->endElement(XML_pivotCaches); + if (bStartedPivotCaches) + pWorkbookStrm->endElement(XML_pivotCaches); } void XclExpXmlPivotCaches::SetCaches( std::vector&& rCaches ) @@ -299,12 +311,14 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr SvNumberFormatter& rFormatter = GetFormatter(); - // In Excel, DATE can't be later than 9999-12-31. + // In Excel, DATE can't be earlier than 1899-12-30 (serial 0) + // or later than 9999-12-31. // Number of days from 1900-01-01 to 9999-12-31 is 2958465. + constexpr double MIN_DATE = 0; constexpr double MAX_DATE = 2.958465e6; auto GetClampedDate = [&](double fVal, double fSub) { - if (fVal > MAX_DATE) + if (fVal < MIN_DATE || fVal > MAX_DATE) return GetExcelFormattedDate(fSub, rFormatter); else return GetExcelFormattedDate(fVal, rFormatter); @@ -378,7 +392,7 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr auto pGroupAttList = sax_fastparser::FastSerializerHelper::createAttrList(); pGroupAttList->add(XML_groupBy, sGroupBy); // Possible TODO: find out when to write autoStart attribute for years grouping - pGroupAttList->add(XML_startDate, GetClampedDate(pGI->mfStart, 0).toUtf8()); + pGroupAttList->add(XML_startDate, GetClampedDate(pGI->mfStart, MIN_DATE).toUtf8()); pGroupAttList->add(XML_endDate, GetClampedDate(pGI->mfEnd, MAX_DATE).toUtf8()); if (pGI->mfStep) pGroupAttList->add(XML_groupInterval, OString::number(pGI->mfStep)); @@ -409,6 +423,7 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr double fMin = std::numeric_limits::infinity(), fMax = -std::numeric_limits::infinity(); bool isValueInteger = true; bool isContainsDate = rCache.IsDateDimension(i); + bool hasInvalidDate = false; bool isLongText = false; for (const auto& rFieldItem : rFieldItems) { @@ -419,10 +434,14 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr aDPTypes.insert(eType); if (eType == ScDPItemData::Value) { - double fVal = rFieldItem.GetValue(); + // Rounds the value to 15 digits + double fVal = rtl::math::approxValue(rFieldItem.GetValue()); fMin = std::min(fMin, fVal); fMax = std::max(fMax, fVal); + if (isContainsDate && fVal > MAX_DATE) + hasInvalidDate = true; + // Check if all values are integers if (isValueInteger && (modf(fVal, &o3tl::temporary(double())) != 0.0)) { @@ -447,7 +466,7 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr const bool isContainsBlank = aDPTypes.count(ScDPItemData::Empty) > 0; const bool isContainsNumber = !isContainsDate && aDPTypesWithoutBlank.count(ScDPItemData::Value) > 0; - bool isContainsNonDate = !(isContainsDate && aDPTypesWithoutBlank.size() <= 1); + bool isContainsNonDate = !(isContainsDate && aDPTypesWithoutBlank.size() <= 1 && !hasInvalidDate); // XML_containsSemiMixedTypes possible values: // 1 - (Default) at least one text value, or can also contain a mix of other data types and blank values, @@ -472,7 +491,7 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr // XML_containsMixedType possible values: // 1 - field contains more than one data type // 0 - (Default) only one data type. The field can still contain blank values (that's why we are using aDPTypesWithoutBlank) - if (aDPTypesWithoutBlank.size() > 1) + if (aDPTypesWithoutBlank.size() > 1 || (isContainsDate && hasInvalidDate)) pAttList->add(XML_containsMixedTypes, ToPsz10(true)); // If field contain mixed types (Date and Numbers), MS Excel is saving only "minDate" and "maxDate" and not "minValue" and "maxValue" @@ -500,7 +519,7 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr if (isContainsDate) { - pAttList->add(XML_minDate, GetClampedDate(fMin, 0).toUtf8()); + pAttList->add(XML_minDate, GetClampedDate(fMin, MIN_DATE).toUtf8()); pAttList->add(XML_maxDate, GetClampedDate(fMax, MAX_DATE).toUtf8()); } @@ -529,7 +548,7 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr if (isContainsDate) { double fDate = rItem.GetValue(); - if (fDate > MAX_DATE) + if (fDate < MIN_DATE || fDate > MAX_DATE) pDefStrm->singleElement(XML_n, XML_v, OString::number(fDate)); else pDefStrm->singleElement( @@ -632,6 +651,16 @@ void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entr OUString aItemName = rCache.GetFormattedString(nBase, rItem, false); if (aItemToGroupIdx.find(aItemName) == aItemToGroupIdx.end()) { + // Dates are grouped by converting to double + if (rItem.GetType() == ScDPItemData::Value) + { + auto iter = aItemToGroupIdx.find(OUString::number(rItem.GetValue())); + if (iter != aItemToGroupIdx.end()) + { + aItemToGroupIdx[aItemName] = iter->second; + continue; + } + } sal_Int32 nGroupIdx = static_cast(aGroupItemNames.size()); aGroupItemNames.push_back(aItemName); aItemToGroupIdx[aItemName] = nGroupIdx; @@ -801,6 +830,16 @@ void XclExpXmlPivotTables::SaveXml( XclExpXmlStream& rStrm ) sal_Int32 nCacheId = rTable.mnCacheId; sal_Int32 nPivotId = rTable.mnPivotId; + const XclExpXmlPivotCaches::Entry* pCacheEntry = mrCaches.GetCache(nCacheId); + if (!pCacheEntry) + continue; + + const ScDPCache& rCache = *pCacheEntry->mpCache; + + size_t nFieldCount = rCache.GetFieldCount() + rCache.GetGroupFieldCount(); + if (nFieldCount == 0) + continue; + sax_fastparser::FSHelperPtr pPivotStrm = rStrm.CreateOutputStream( XclXmlUtils::GetStreamName("xl/pivotTables/", "pivotTable", nPivotId), XclXmlUtils::GetStreamName(nullptr, "../pivotTables/pivotTable", nPivotId), @@ -1028,45 +1067,45 @@ void writeRowColumnItems(sal_Int32 nItemElement, RowOrColumnMemberResultData& rM bIsGrandTotal = true; } + // Count how many leading fields repeat from the previous column item. + // These are omitted and their count is stored in the "r" attribute. + size_t nRepeat = 0; + for (OUString const& rFieldName : rMemberResultData.maFieldOrder) { - OUString const& rFieldName = rMemberResultData.maFieldOrder[0]; RowOrColumnItemsData const& rData = rItemMap[rFieldName]; - sal_Int32 nIndex = -1; - if (!rData.msName.isEmpty()) - nIndex = rMemberResultData.lookup(rFieldName, rData.msName); - if (bIsGrandTotal) - { - pStream->startElement(XML_i, XML_t, "grand"); - pStream->singleElement(XML_x); - } - else if (bIsSubtotal) - { - pStream->startElement(XML_i, XML_t, "default"); - - if (nIndex == 0) // 0 is the default - pStream->singleElement(XML_x); - else - pStream->singleElement(XML_x, XML_v, OString::number(nIndex)); - } - else if (rData.mbContinue) - { - pStream->startElement(XML_i, XML_r, "1"); - } - else if (nIndex >= 0) - { - pStream->startElement(XML_i); - if (nIndex == 0) // 0 is the default - pStream->singleElement(XML_x); - else - pStream->singleElement(XML_x, XML_v, OString::number(nIndex)); - } - else - { - pStream->startElement(XML_i); - } + if (!rData.mbContinue) + break; + nRepeat++; } - for (size_t i = 1; i < rMemberResultData.maFieldOrder.size(); i++) + // Write the start element with optional t and r attributes. + if (bIsGrandTotal) + { + if (nRepeat > 0) + pStream->startElement(XML_i, XML_t, "grand", + XML_r, OString::number(nRepeat)); + else + pStream->startElement(XML_i, XML_t, "grand"); + pStream->singleElement(XML_x); + } + else if (bIsSubtotal) + { + if (nRepeat > 0) + pStream->startElement(XML_i, XML_t, "default", + XML_r, OString::number(nRepeat)); + else + pStream->startElement(XML_i, XML_t, "default"); + } + else + { + if (nRepeat > 0) + pStream->startElement(XML_i, XML_r, OString::number(nRepeat)); + else + pStream->startElement(XML_i); + } + + // Write elements for all non-repeated fields that have a valid item index. + for (size_t i = nRepeat; i < rMemberResultData.maFieldOrder.size(); i++) { OUString const& rItemName = rMemberResultData.maFieldOrder[i]; RowOrColumnItemsData const& rData = rItemMap[rItemName]; @@ -1211,7 +1250,9 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP XML_outline, ToPsz10(!bTabularMode), XML_outlineData, ToPsz10(!bTabularMode), XML_compact, ToPsz10(bCompactMode), - XML_compactData, ToPsz10(bCompactMode)); + XML_compactData, ToPsz10(bCompactMode), + XML_rowGrandTotals, sax_fastparser::UseIf(ToPsz10(false), !rSaveData.GetRowGrand()), + XML_colGrandTotals, sax_fastparser::UseIf(ToPsz10(false), !rSaveData.GetColumnGrand())); // NB: Excel's range does not include page field area (if any). ScRange aOutRange = rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::TABLE); @@ -1619,7 +1660,7 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP } // - savePivotTableFormats(rStrm, rDPObj); + savePivotTableFormats(rStrm, rDPObj, nFieldCount); // Now add style info (use grab bag, or just a set which is default on Excel 2007 through 2016) auto const& rStyleInfo = rDPObj.getStyleInfo(); @@ -1652,7 +1693,8 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP pPivotStrm->endElement(XML_pivotTableDefinition); } -void XclExpXmlPivotTables::savePivotTableFormats(XclExpXmlStream& rStream, ScDPObject const& rDPObject) +void XclExpXmlPivotTables::savePivotTableFormats(XclExpXmlStream& rStream, + ScDPObject const& rDPObject, size_t nFieldCount) { sax_fastparser::FSHelperPtr& pPivotStream = rStream.GetCurrentStream(); @@ -1660,18 +1702,41 @@ void XclExpXmlPivotTables::savePivotTableFormats(XclExpXmlStream& rStream, ScDPO if (pSaveData && pSaveData->hasFormats()) { sc::PivotTableFormats const& rFormats = pSaveData->getFormats(); - if (rFormats.size() > 0) + + // Skip formats that reference fields outside cache range. + std::vector> aValidFormats; + for (auto const& rFormat : rFormats.getVector()) { - pPivotStream->startElement(XML_formats, XML_count, OString::number(rFormats.size())); + if (!rFormat.pPattern) + continue; - for (auto const& rFormat : rFormats.getVector()) + if (GetDxfs().GetDxfIdForPattern(rFormat.pPattern.get()) == -1) + continue; + + // Check that all field references are within range. + bool bValid = true; + for (sc::Selection const& rSelection : rFormat.getSelections()) { - if (!rFormat.pPattern) - continue; + if (rSelection.nField >= 0 && o3tl::make_unsigned(rSelection.nField) >= nFieldCount) + { + bValid = false; + break; + } + } + if (!bValid) + continue; + aValidFormats.push_back(std::cref(rFormat)); + } + + if (aValidFormats.size()) + { + pPivotStream->startElement(XML_formats, XML_count, + OString::number(aValidFormats.size())); + + for (sc::PivotTableFormat const& rFormat : aValidFormats) + { sal_Int32 nDxf = GetDxfs().GetDxfIdForPattern(rFormat.pPattern.get()); - if (nDxf == -1) - continue; pPivotStream->startElement(XML_format, XML_dxfId, OString::number(nDxf)); { @@ -1680,8 +1745,29 @@ void XclExpXmlPivotTables::savePivotTableFormats(XclExpXmlStream& rStream, ScDPO pAttributeList->add(XML_dataOnly, "0"); if (rFormat.bLabelOnly) // default is false pAttributeList->add(XML_labelOnly, "1"); + if (rFormat.bGrandRow) // default is false + pAttributeList->add(XML_grandRow, "1"); + if (rFormat.bGrandColumn) // default is false + pAttributeList->add(XML_grandCol, "1"); if (!rFormat.bOutline) // default is true pAttributeList->add(XML_outline, "0"); + if (rFormat.oOffset) + { + ScRange const& rOffset = *rFormat.oOffset; + ScRefFlags nFlags = ScRefFlags::COL_VALID | ScRefFlags::ROW_VALID; + OUString aStart = rOffset.aStart.Format( + nFlags, nullptr, formula::FormulaGrammar::CONV_XL_A1); + if (rOffset.aStart == rOffset.aEnd) + { + pAttributeList->add(XML_offset, aStart); + } + else + { + OUString aEnd = rOffset.aEnd.Format( + nFlags, nullptr, formula::FormulaGrammar::CONV_XL_A1); + pAttributeList->add(XML_offset, aStart + ":" + aEnd); + } + } if (rFormat.oFieldPosition) pAttributeList->add(XML_fieldPosition, OString::number(*rFormat.oFieldPosition)); pPivotStream->startElement(XML_pivotArea, pAttributeList); @@ -1694,9 +1780,11 @@ void XclExpXmlPivotTables::savePivotTableFormats(XclExpXmlStream& rStream, ScDPO { auto pRefAttributeList = sax_fastparser::FastSerializerHelper::createAttrList(); pRefAttributeList->add(XML_field, OString::number(sal_uInt32(rSelection.nField))); - pRefAttributeList->add(XML_count, "1"); + pRefAttributeList->add(XML_count, OString::number(rSelection.nIndices.size())); if (!rSelection.bSelected) // default is true pRefAttributeList->add(XML_selected, "0"); + if (rSelection.bHasSubtotal) + pRefAttributeList->add(XML_defaultSubtotal, "1"); pPivotStream->startElement(XML_reference, pRefAttributeList); } diff --git a/sc/source/filter/excel/xeroot.cxx b/sc/source/filter/excel/xeroot.cxx index 2aa51073ed90..d162b9e419f1 100644 --- a/sc/source/filter/excel/xeroot.cxx +++ b/sc/source/filter/excel/xeroot.cxx @@ -182,6 +182,12 @@ XclExpTablesManager& XclExpRoot::GetTablesManager() return *mrExpData.mxTablesMgr; } +XclExpQueryTablesManager& XclExpRoot::GetQueryTablesManager() +{ + assert(mrExpData.mxQueryTablesMgr); + return *mrExpData.mxQueryTablesMgr; +} + void XclExpRoot::InitializeConvert() { mrExpData.mxTabInfo = std::make_shared( GetRoot() ); @@ -221,6 +227,7 @@ void XclExpRoot::InitializeGlobals() { mrExpData.mxXmlPTableMgr = std::make_shared(GetRoot()); mrExpData.mxTablesMgr = std::make_shared(GetRoot()); + mrExpData.mxQueryTablesMgr = std::make_shared(GetRoot()); mrExpData.mxTableStyles = new XclExpXmlTableStyles( GetRoot() ); do diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx index 67e3caad51ef..17c8ed631752 100644 --- a/sc/source/filter/excel/xestream.cxx +++ b/sc/source/filter/excel/xestream.cxx @@ -68,6 +68,8 @@ #include #include #include +#include +#include #include #include @@ -89,6 +91,8 @@ using namespace ::com::sun::star::uno; using namespace ::formula; using namespace ::oox; +constexpr int MAX_TAB_NAME_LENGTH = 31; + XclExpStream::XclExpStream( SvStream& rOutStrm, const XclExpRoot& rRoot, sal_uInt16 nMaxRecSize ) : mrStrm( rOutStrm ), mrRoot( rRoot ), @@ -660,6 +664,10 @@ static const char* lcl_GetErrorString( FormulaError nScErrCode ) case EXC_ERR_REF: return "#REF!"; case EXC_ERR_NAME: return "#NAME?"; case EXC_ERR_NUM: return "#NUM!"; + // OOXML cell error strings (ST_CellType="e") have no #SPILL! literal. + // Use #VALUE! instead, which is accepted and is reclassified to #SPILL! + // on recalc and reload (same as MSO does). + case EXC_ERR_SPILL: return "#VALUE!"; case EXC_ERR_NA: default: return "#N/A"; } @@ -932,6 +940,8 @@ sax_fastparser::FSHelperPtr XclXmlUtils::WriteFontData( sax_fastparser::FSHelper XclExpXmlStream::XclExpXmlStream( const uno::Reference< XComponentContext >& rCC, bool bExportVBA, bool bExportTemplate ) : XmlFilterBase( rCC ), mpRoot( nullptr ), + mpShapeExport(), + maDiagramId(0), mbExportVBA(bExportVBA), mbExportTemplate(bExportTemplate) { @@ -1193,10 +1203,38 @@ OUString XclExpXmlStream::getImplementationName() return u"TODO"_ustr; } +OUString XclExpXmlStream::GenerateUniqueTableName(const std::u16string_view& rOriginalName, const std::vector& aNewTabNames, const std::vector& aOriginalTabNames) +{ + std::unordered_set aUsedNames; + aUsedNames.reserve(aNewTabNames.size() + aOriginalTabNames.size()); + aUsedNames.insert(aNewTabNames.begin(), aNewTabNames.end()); + aUsedNames.insert(aOriginalTabNames.begin(), aOriginalTabNames.end()); + + // let's try just truncate "" + OUString aNewName(rOriginalName.substr(0, MAX_TAB_NAME_LENGTH)); + if (aUsedNames.contains(aNewName)) + aNewName.clear(); + + // let's try "-XXX" template + int rangeStart = 1; + for (int digits = 1; digits < 10 && aNewName.isEmpty(); digits++) + { + const int rangeEnd = rangeStart * 10; + OUString aBaseName(rOriginalName.substr(0, MAX_TAB_NAME_LENGTH - 1 - digits)); + for (int i = rangeStart; i < rangeEnd && aNewName.isEmpty(); i++) + { + aNewName = aBaseName + u"-"_ustr + OUString::number(i); + if (aUsedNames.contains(aNewName)) + aNewName.clear(); + } + rangeStart = rangeEnd; + } + + return aNewName; +} + void XclExpXmlStream::validateTabNames(std::vector& aOriginalTabNames) { - const int MAX_TAB_NAME_LENGTH = 31; - ScDocShell* pShell = getDocShell(); ScDocument& rDoc = pShell->GetDocument(); @@ -1217,38 +1255,7 @@ void XclExpXmlStream::validateTabNames(std::vector& aOriginalTabNames) const OUString& rOriginalName = aOriginalTabNames[nTab]; if (rOriginalName.getLength() > MAX_TAB_NAME_LENGTH) { - OUString aNewName; - - // let's try just truncate "" - if (aNewName.isEmpty()) - { - aNewName = rOriginalName.copy(0, MAX_TAB_NAME_LENGTH); - if (aNewTabNames.end() != std::find(aNewTabNames.begin(), aNewTabNames.end(), aNewName) || - aOriginalTabNames.end() != std::find(aOriginalTabNames.begin(), aOriginalTabNames.end(), aNewName)) - { - // was found => let's use another tab name - aNewName.clear(); - } - } - - // let's try "-XXX" template - for (int digits=1; digits<10 && aNewName.isEmpty(); digits++) - { - const int rangeStart = pow(10, digits - 1); - const int rangeEnd = pow(10, digits); - - for (int i=rangeStart; i let's use another tab name - aNewName.clear(); - } - } - } - + OUString aNewName = GenerateUniqueTableName(rOriginalName, aNewTabNames, aOriginalTabNames); if (!aNewName.isEmpty()) { // new name was created => rename diff --git a/sc/source/filter/excel/xestyle.cxx b/sc/source/filter/excel/xestyle.cxx index 842d197d122d..782114d5b736 100644 --- a/sc/source/filter/excel/xestyle.cxx +++ b/sc/source/filter/excel/xestyle.cxx @@ -1715,7 +1715,13 @@ XclExpCellBorder::XclExpCellBorder() : mnRightColorId( XclExpPalette::GetColorIdFromIndex( mnRightColor ) ), mnTopColorId( XclExpPalette::GetColorIdFromIndex( mnTopColor ) ), mnBottomColorId( XclExpPalette::GetColorIdFromIndex( mnBottomColor ) ), - mnDiagColorId( XclExpPalette::GetColorIdFromIndex( mnDiagColor ) ) + mnDiagColorId( XclExpPalette::GetColorIdFromIndex( mnDiagColor ) ), + mnVertColorId( XclExpPalette::GetColorIdFromIndex( 0 ) ), + mnHorzColorId( XclExpPalette::GetColorIdFromIndex( 0 ) ), + mnVertColor( 0 ), + mnHorzColor( 0 ), + mnVertLine( EXC_LINE_NONE ), + mnHorzLine( EXC_LINE_NONE ) { } @@ -1756,6 +1762,13 @@ bool XclExpCellBorder::FillFromItemSet( bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER_TLBR, bStyle ) || ScfTools::CheckItem( rItemSet, ATTR_BORDER_BLTR, bStyle ); + // Inner borders (vertical/horizontal) + const SvxBoxInfoItem& rBoxInfoItem = rItemSet.Get( ATTR_BORDER_INNER ); + lclGetBorderLine( mnVertLine, mnVertColorId, maComplexColorVertical, rBoxInfoItem.GetVert(), rPalette, eBiff ); + lclGetBorderLine( mnHorzLine, mnHorzColorId, maComplexColorHorizontal, rBoxInfoItem.GetHori(), rPalette, eBiff ); + + bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER_INNER, bStyle ); + [[fallthrough]]; } @@ -1788,6 +1801,8 @@ void XclExpCellBorder::SetFinalColors( const XclExpPalette& rPalette ) mnTopColor = rPalette.GetColorIndex( mnTopColorId ); mnBottomColor = rPalette.GetColorIndex( mnBottomColorId ); mnDiagColor = rPalette.GetColorIndex( mnDiagColorId ); + mnVertColor = rPalette.GetColorIndex( mnVertColorId ); + mnHorzColor = rPalette.GetColorIndex( mnHorzColorId ); } void XclExpCellBorder::FillToXF5( sal_uInt32& rnBorder, sal_uInt32& rnArea ) const @@ -1854,12 +1869,16 @@ static const char* ToLineStyle( sal_uInt8 nLineStyle ) namespace { -void lcl_WriteBorder(XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLineStyle, const Color& rColor, model::ComplexColor const& rComplexColor) +void lcl_WriteBorder(XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLineStyle, const Color& rColor, model::ComplexColor const& rComplexColor, bool bWriteEmpty = true) { sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); if( nLineStyle == EXC_LINE_NONE ) { - rStyleSheet->singleElement(nElement); + // In a differential format (dxf) an empty side element (e.g. ) means + // "no border" and overrides the underlying table style, so omit it there and + // let the side be inherited. The cell border list still writes it. + if (bWriteEmpty) + rStyleSheet->singleElement(nElement); return; } else if (rColor == Color(0, 0, 0) && !rComplexColor.isValidThemeType()) @@ -1874,7 +1893,7 @@ void lcl_WriteBorder(XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLine } } // end anonymous namespace -void XclExpCellBorder::SaveXml(XclExpXmlStream& rStream) const +void XclExpCellBorder::SaveXml(XclExpXmlStream& rStream, bool bDxf) const { sax_fastparser::FSHelperPtr& rStyleSheet = rStream.GetCurrentStream(); @@ -1886,13 +1905,19 @@ void XclExpCellBorder::SaveXml(XclExpXmlStream& rStream) const // OOXTODO: XML_outline ); - lcl_WriteBorder(rStream, XML_left, mnLeftLine, rPalette.GetColor(mnLeftColor), maComplexColorLeft); - lcl_WriteBorder(rStream, XML_right, mnRightLine, rPalette.GetColor(mnRightColor), maComplexColorRight); - lcl_WriteBorder(rStream, XML_top, mnTopLine, rPalette.GetColor(mnTopColor), maComplexColorTop); - lcl_WriteBorder(rStream, XML_bottom, mnBottomLine, rPalette.GetColor(mnBottomColor), maComplexColorBottom); - lcl_WriteBorder(rStream, XML_diagonal, mnDiagLine, rPalette.GetColor(mnDiagColor), maComplexColorDiagonal); + lcl_WriteBorder(rStream, XML_left, mnLeftLine, rPalette.GetColor(mnLeftColor), maComplexColorLeft, !bDxf); + lcl_WriteBorder(rStream, XML_right, mnRightLine, rPalette.GetColor(mnRightColor), maComplexColorRight, !bDxf); + lcl_WriteBorder(rStream, XML_top, mnTopLine, rPalette.GetColor(mnTopColor), maComplexColorTop, !bDxf); + lcl_WriteBorder(rStream, XML_bottom, mnBottomLine, rPalette.GetColor(mnBottomColor), maComplexColorBottom, !bDxf); + lcl_WriteBorder(rStream, XML_diagonal, mnDiagLine, rPalette.GetColor(mnDiagColor), maComplexColorDiagonal, !bDxf); + + // Inner borders (vertical/horizontal). Only emitted when actually set, so + // ordinary cell borders keep their previous output. + if (mnVertLine != EXC_LINE_NONE) + lcl_WriteBorder(rStream, XML_vertical, mnVertLine, rPalette.GetColor(mnVertColor), maComplexColorVertical); + if (mnHorzLine != EXC_LINE_NONE) + lcl_WriteBorder(rStream, XML_horizontal, mnHorzLine, rPalette.GetColor(mnHorzColor), maComplexColorHorizontal); - // OOXTODO: XML_vertical, XML_horizontal rStyleSheet->endElement( XML_border ); } @@ -3329,7 +3354,7 @@ void XclExpDxf::SaveXml( XclExpXmlStream& rStrm ) if (mpAlign) mpAlign->SaveXml(rStrm); if (mpBorder) - mpBorder->SaveXml(rStrm); + mpBorder->SaveXml(rStrm, /*bDxf*/true); if (mpProt) mpProt->SaveXml(rStrm); if (mpCellArea) @@ -3351,7 +3376,7 @@ void XclExpDxf::SaveXmlExt( XclExpXmlStream& rStrm ) if (mpAlign) mpAlign->SaveXml(rStrm); if (mpBorder) - mpBorder->SaveXml(rStrm); + mpBorder->SaveXml(rStrm, /*bDxf*/true); if (mpProt) mpProt->SaveXml(rStrm); rStyleSheet->endElementNS( XML_x14, XML_dxf ); @@ -3395,9 +3420,9 @@ XclExpXmlTableStyles::XclExpXmlTableStyles( const XclExpRoot& rRoot): if (!pTableStyles) return; - for (auto itr = rDBs.begin(); itr != rDBs.end(); ++itr) + for (const auto& rDB : rDBs) { - const ScTableStyleParam* pParam = itr->get()->GetTableStyleInfo(); + const ScTableStyleParam* pParam = rDB->GetTableStyleInfo(); if (pParam && pTableStyles->GetTableStyle(pParam->maStyleID)) { aTableStyleNames.insert(pParam->maStyleID); diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index 984e63837f87..c272ef70a69e 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -168,7 +168,7 @@ XclExpArrayRef XclExpArrayBuffer::FindArray( const ScTokenArray& rScTokArr, cons // not a matrix reference token. return xRec; - const ScSingleRefData& rRef = *pToken->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef(); ScAddress aAbsPos = rRef.toAbs(GetRoot().GetDoc(), rBasePos); XclExpArrayMap::const_iterator it = maRecMap.find(aAbsPos); @@ -226,7 +226,7 @@ bool XclExpShrfmlaBuffer::IsValidTokenArray( const ScTokenArray& rArray ) const { case svSingleRef: { - const ScSingleRefData& rRefData = *p->GetSingleRef(); + const ScSingleRefData& rRefData = static_cast(p)->GetSingleRef(); if (!GetFormulaCompiler().IsRef2D(rRefData)) // Excel's shared formula cannot include 3D reference. return false; @@ -234,7 +234,7 @@ bool XclExpShrfmlaBuffer::IsValidTokenArray( const ScTokenArray& rArray ) const break; case svDoubleRef: { - const ScComplexRefData& rRefData = *p->GetDoubleRef(); + const ScComplexRefData& rRefData = static_cast(p)->GetDoubleRef(); if (!GetFormulaCompiler().IsRef2D(rRefData)) // Excel's shared formula cannot include 3D reference. return false; @@ -945,11 +945,20 @@ void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm ) OUString sValue; XclXmlUtils::GetFormulaTypeAndValue( mrScFmlaCell, sType, sValue ); sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); + + // Mark dynamic array masters with cm="1" so it is recognised as a + // dynamic array and reads the matching dynamicArrayProperties out of + // xl/metadata.xml. + const bool bDynamicArrayMaster = mrScFmlaCell.IsDynamicArrayMaster(); + if (bDynamicArrayMaster) + rStrm.NoteDynamicArrayFormula(); + rWorksheet->startElement( XML_c, XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), GetXclPos()).getStr(), XML_s, lcl_GetStyleId(rStrm, *this), - XML_t, sType - // OOXTODO: XML_cm, XML_vm, XML_ph + XML_t, sType, + XML_cm, bDynamicArrayMaster ? "1" : nullptr + // OOXTODO: XML_vm, XML_ph ); bool bWriteFormula = true; @@ -981,29 +990,34 @@ void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm ) OStringBuffer sFmlaCellRange; if (rStrm.GetRoot().GetDoc().ValidRange(aMatScRange)) { - // calculate the cell range. - sFmlaCellRange.append( XclXmlUtils::ToOString( - rStrm.GetRoot().GetStringBuf(), aMatScRange.aStart ) - + OString::Concat(":")); - sFmlaCellRange.append( XclXmlUtils::ToOString( - rStrm.GetRoot().GetStringBuf(), aMatScRange.aEnd )); + sFmlaCellRange.append(XclXmlUtils::ToOString( + rStrm.GetRoot().GetStringBuf(), aMatScRange.aStart)); + // 1x1 masters (the collapsed dynamic array spill state) + if (aMatScRange.aStart != aMatScRange.aEnd) + sFmlaCellRange.append(":" + + XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), + aMatScRange.aEnd)); } if ( aMatScRange.aStart.Col() == GetXclPos().mnCol && aMatScRange.aStart.Row() == static_cast(GetXclPos().mnRow)) { + // Dynamic array masters need aca="1" (always calc array) + // and ca="1" (calculate always). + const bool bAca = bDynamicArrayMaster + || (mxTokArr && mxTokArr->IsVolatile()) + || (mxAddRec && mxAddRec->IsVolatile()); rWorksheet->startElement( XML_f, - XML_aca, ToPsz( (mxTokArr && mxTokArr->IsVolatile()) || - (mxAddRec && mxAddRec->IsVolatile())), - XML_t, mxAddRec ? "array" : nullptr, - XML_ref, !sFmlaCellRange.isEmpty()? sFmlaCellRange.getStr() : nullptr + XML_aca, ToPsz(bAca), + XML_t, (bDynamicArrayMaster || mxAddRec) ? "array" : nullptr, + XML_ref, !sFmlaCellRange.isEmpty()? sFmlaCellRange.getStr() : nullptr, + XML_ca, bDynamicArrayMaster ? "1" : nullptr // OOXTODO: XML_dt2D, bool // OOXTODO: XML_dtr, bool // OOXTODO: XML_del1, bool // OOXTODO: XML_del2, bool // OOXTODO: XML_r1, ST_CellRef // OOXTODO: XML_r2, ST_CellRef - // OOXTODO: XML_ca, bool // OOXTODO: XML_si, uint // OOXTODO: XML_bx bool ); @@ -1016,6 +1030,18 @@ void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm ) if (bWriteFormula) { ScTokenArray aTokenArray(*mrScFmlaCell.GetCode()); + // OOXML expresses the @ of a plain =@ref# cell by leaving it out and keeping the + // cell a non-array formula. Write it the same way, so a reader that does not know + // the _xlfn.SINGLE call still gets the formula. + if (!bDynamicArrayMaster && mrScFmlaCell.GetMatrixFlag() == ScMatrixMode::NONE + && aTokenArray.GetLen() == 3 + && aTokenArray.TokenAt(0)->GetOpCode() == ocSingleValue + && aTokenArray.TokenAt(1)->GetType() == formula::svSingleRef + && aTokenArray.TokenAt(2)->GetOpCode() == ocSpill) + { + aTokenArray.RemoveToken(0, 1); + } + bool bValid = true; // Discard formulas containing macros in XLSX export. if (!rStrm.IsExportVBA()) @@ -1029,6 +1055,19 @@ void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm ) bValid = false; break; } + else if (t->GetOpCode() == ocUDExternal && t->GetType() == formula::svExternal) + { + OUString sUDName(static_cast(t)->GetExternal()); + OUString sSanitizedName = sUDName.replaceAll(" ", "_"); + if (sUDName != sSanitizedName) + { + sal_uInt16 nIndex = aIter.GetIndex(); + aTokenArray.ReplaceToken( + nIndex - 1, + new formula::FormulaExternalToken(ocUDExternal, sSanitizedName), + formula::FormulaTokenArray::CODE_ONLY); + } + } t = aIter.Next(); } } @@ -2334,7 +2373,7 @@ void XclExpRowBuffer::Finalize( XclExpDefaultRowData& rDefRowData, XclExpDefaultRowData aMaxDefData; size_t nMaxDefCount = 0; // only look for default format in existing rows, if there are more than unused - // if the row is hidden, then row xml must be created even if it not contain cells + // if the row is hidden, then row xml must be created even if it does not contain cells XclExpRow* pPrev = nullptr; std::vector< XclExpRow* > aRepeated; for (const auto& rEntry : maRowMap) @@ -2578,7 +2617,7 @@ XclExpCellTable::XclExpCellTable( const XclExpRoot& rRoot ) : if(nLastUsedScCol > nMaxScCol) nLastUsedScCol = nMaxScCol; - // check extra blank rows to avoid of losing their not default settings (workaround for tdf#41425) + // check extra blank rows to avoid losing their non-default settings (workaround for tdf#41425) nLastUsedScRow += 1000; if(nLastUsedScRow > nMaxScRow) diff --git a/sc/source/filter/excel/xichart.cxx b/sc/source/filter/excel/xichart.cxx index c97d1de3e1b5..4d6e7862da7c 100644 --- a/sc/source/filter/excel/xichart.cxx +++ b/sc/source/filter/excel/xichart.cxx @@ -801,9 +801,13 @@ sal_uInt16 XclImpChSourceLink::GetCellCount() const case ::formula::svExternalDoubleRef: { // cell range - const ScComplexRefData& rComplexRef = *pToken->GetDoubleRef(); - ScAddress aAbs1 = rComplexRef.Ref1.toAbs(GetRoot().GetDoc(), ScAddress()); - ScAddress aAbs2 = rComplexRef.Ref2.toAbs(GetRoot().GetDoc(), ScAddress()); + const ScComplexRefData* pComplexRef; + if( pToken->GetType() == ::formula::svDoubleRef ) + pComplexRef = &static_cast(pToken)->GetDoubleRef(); + else + pComplexRef = &static_cast(pToken)->GetDoubleRef(); + ScAddress aAbs1 = pComplexRef->Ref1.toAbs(GetRoot().GetDoc(), ScAddress()); + ScAddress aAbs2 = pComplexRef->Ref2.toAbs(GetRoot().GetDoc(), ScAddress()); sal_uInt32 nTabs = static_cast(aAbs2.Tab() - aAbs1.Tab() + 1); sal_uInt32 nCols = static_cast(aAbs2.Col() - aAbs1.Col() + 1); sal_uInt32 nRows = static_cast(aAbs2.Row() - aAbs1.Row() + 1); diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx index b7769c941108..dcbcedff281b 100644 --- a/sc/source/filter/excel/xicontent.cxx +++ b/sc/source/filter/excel/xicontent.cxx @@ -194,7 +194,7 @@ void lclInsertUrl( XclImpRoot& rRoot, const OUString& rUrl, SCCOL nScCol, SCROW } // The cell will own the text object instance. - rDoc.setEditCell(aScPos, rEE.CreateTextObject()); + rDoc.setEditCell(aScPos, std::make_unique(rEE.CreateTextObject())); } break; @@ -668,7 +668,7 @@ void XclImpCondFormat::ReadCF( XclImpStream& rStrm ) // If it's an external formula then skip the entry if (const formula::FormulaToken* pToken = pTokArr->FirstToken()) { - if (pToken->GetOpCode() == ocExternal) + if (pToken->GetOpCode() == ocExternal || pToken->GetOpCode() == ocUDExternal) return; } xTokArr1 = std::move( pTokArr ); @@ -688,7 +688,7 @@ void XclImpCondFormat::ReadCF( XclImpStream& rStrm ) // If it's an external formula then skip the entry if (const formula::FormulaToken* pToken = pTokArr->FirstToken()) { - if (pToken->GetOpCode() == ocExternal) + if (pToken->GetOpCode() == ocExternal || pToken->GetOpCode() == ocUDExternal) return; } xTokArr2 = std::move( pTokArr ); diff --git a/sc/source/filter/excel/xiescher.cxx b/sc/source/filter/excel/xiescher.cxx index 4e41746d233d..48b14a234fcb 100644 --- a/sc/source/filter/excel/xiescher.cxx +++ b/sc/source/filter/excel/xiescher.cxx @@ -1508,18 +1508,18 @@ void XclImpTextObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& { if( maTextData.mxString ) { + if (maTextData.mxString->GetText().getLength() > 1024 && comphelper::IsFuzzing()) + { + SAL_WARN("sc.filter", "truncating slow long text for fuzzing performance"); + maTextData.mxString->SetText(maTextData.mxString->GetText().copy(0, 1024)); + } + if( maTextData.mxString->IsRich() ) { - if (maTextData.mxString->GetText().getLength() > 1024 && comphelper::IsFuzzing()) - { - SAL_WARN("sc.filter", "truncating slow long rich text for fuzzing performance"); - maTextData.mxString->SetText(maTextData.mxString->GetText().copy(0, 1024)); - } - // rich text - std::unique_ptr< EditTextObject > xEditObj( + std::optional< EditTextObject > xEditObj( XclImpStringHelper::CreateTextObject( GetRoot(), *maTextData.mxString ) ); - OutlinerParaObject aOutlineObj(std::move(xEditObj)); + OutlinerParaObject aOutlineObj(std::move(*xEditObj)); aOutlineObj.SetOutlinerMode( OutlinerMode::TextObject ); pTextObj->NbcSetOutlinerParaObject( std::move(aOutlineObj) ); } diff --git a/sc/source/filter/excel/xihelper.cxx b/sc/source/filter/excel/xihelper.cxx index 40dd4ba5901c..74d95b2479af 100644 --- a/sc/source/filter/excel/xihelper.cxx +++ b/sc/source/filter/excel/xihelper.cxx @@ -146,10 +146,10 @@ void XclImpAddressConverter::ConvertRangeList( ScRangeList& rScRanges, namespace { -std::unique_ptr lclCreateTextObject( const XclImpRoot& rRoot, +std::optional lclCreateTextObject( const XclImpRoot& rRoot, const XclImpString& rString, XclFontItemType eType, sal_uInt16 nXFIndex ) { - std::unique_ptr pTextObj; + std::optional pTextObj; const XclImpXFBuffer& rXFBuffer = rRoot.GetXFBuffer(); const XclImpFont* pFirstFont = rXFBuffer.GetFont( nXFIndex ); @@ -213,7 +213,7 @@ std::unique_ptr lclCreateTextObject( const XclImpRoot& rRoot, // send items of last text portion to edit engine rEE.QuickSetAttribs( aItemSet, aSelection ); - pTextObj = rEE.CreateTextObject(); + pTextObj.emplace(rEE.CreateTextObject()); } return pTextObj; @@ -221,7 +221,7 @@ std::unique_ptr lclCreateTextObject( const XclImpRoot& rRoot, } // namespace -std::unique_ptr XclImpStringHelper::CreateTextObject( +std::optional XclImpStringHelper::CreateTextObject( const XclImpRoot& rRoot, const XclImpString& rString ) { return lclCreateTextObject( rRoot, rString, XclFontItemType::Editeng, 0 ); @@ -234,11 +234,11 @@ void XclImpStringHelper::SetToDocument( if (rString.GetText().isEmpty()) return; - ::std::unique_ptr< EditTextObject > pTextObj( lclCreateTextObject( rRoot, rString, XclFontItemType::Editeng, nXFIndex ) ); + ::std::optional< EditTextObject > pTextObj( lclCreateTextObject( rRoot, rString, XclFontItemType::Editeng, nXFIndex ) ); if (pTextObj) { - rDoc.setEditCell(rPos, std::move(pTextObj)); + rDoc.setEditCell(rPos, std::make_unique(std::move(*pTextObj))); } else { @@ -253,7 +253,7 @@ void XclImpStringHelper::SetToDocument( ScFieldEditEngine& rEngine = rDoc.getDoc().GetEditEngine(); rEngine.SetSingleLine(bSingleLine); rEngine.SetTextCurrentDefaults(aStr); - rDoc.setEditCell(rPos, rEngine.CreateTextObject()); + rDoc.setEditCell(rPos, std::make_unique(rEngine.CreateTextObject())); rEngine.SetSingleLine(false); } else @@ -576,7 +576,7 @@ void XclImpHFConverter::CreateCurrObject() { InsertText(); SetAttribs(); - GetCurrObj() = mrEE.CreateTextObject(); + GetCurrObj() = std::make_shared(mrEE.CreateTextObject()); } void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew ) @@ -610,9 +610,9 @@ void lclAppendUrlChar( OUString& rUrl, sal_Unicode cChar ) } // namespace -void XclImpUrlHelper::DecodeUrl( - OUString& rUrl, OUString& rTabName, bool& rbSameWb, - const XclImpRoot& rRoot, const OUString& rEncodedUrl ) +void XclImpUrlHelper::DecodeUrl(OUString& rUrl, OUString& rTabName, bool& rbSameWb, + const XclImpRoot& rRoot, const OUString& rEncodedUrl, + bool* pbXlStartup) { enum { @@ -626,6 +626,9 @@ void XclImpUrlHelper::DecodeUrl( bool bEncoded = true; rbSameWb = false; + if (pbXlStartup) + *pbXlStartup = false; + sal_Unicode cCurrDrive = 0; OUString aDosBase( INetURLObject( rRoot.GetBasePath() ).getFSysPath( FSysStyle::Dos ) ); if (!aDosBase.isEmpty() && aDosBase.match(":\\", 1)) @@ -716,6 +719,10 @@ void XclImpUrlHelper::DecodeUrl( } } break; + case EXC_URL_XLSTART: + if( pbXlStartup ) + *pbXlStartup = true; + break; case '[': eState = xlUrlFileName; break; @@ -754,12 +761,12 @@ void XclImpUrlHelper::DecodeUrl( } } -void XclImpUrlHelper::DecodeUrl( - OUString& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const OUString& rEncodedUrl ) +void XclImpUrlHelper::DecodeUrl(OUString& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, + const OUString& rEncodedUrl, bool* const pbXlStartup) { OUString aTabName; OUString aUrl; - DecodeUrl( aUrl, aTabName, rbSameWb, rRoot, rEncodedUrl ); + DecodeUrl( aUrl, aTabName, rbSameWb, rRoot, rEncodedUrl, pbXlStartup ); rUrl = aUrl; OSL_ENSURE( aTabName.isEmpty(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" ); } diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx index 0bae231e7741..27b7c8e9e092 100644 --- a/sc/source/filter/excel/xilink.cxx +++ b/sc/source/filter/excel/xilink.cxx @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include @@ -108,6 +110,9 @@ public: /** Returns the URL of the external document. */ const OUString& GetXclUrl() const { return maXclUrl; } + /** Returns true if the path is relative to the XLSTARTUP folder. */ + bool IsXlStartup() const { return mbXlStartup; } + /** Returns the external name specified by an index from the Excel document (one-based). */ const XclImpExtName* GetExternName( sal_uInt16 nXclIndex ) const; /** Tries to decode the URL to OLE or DDE link components. @@ -135,6 +140,8 @@ private: OUString maXclUrl; /// URL of the external document (Excel mode). XclSupbookType meType; /// Type of the supbook record. sal_uInt16 mnSBTab; /// Current Excel sheet index from SUPBOOK for XCT/CRN records. + + bool mbXlStartup = false; /// true if path is relative to XLSTART folder. }; // Import link manager ======================================================== @@ -193,6 +200,8 @@ public: the index. */ const OUString* GetSupbookUrl( sal_uInt16 nXtiIndex ) const; + bool IsSupbookXlStartup( sal_uInt16 nXtiIndex ) const; + OUString GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const; /** Tries to decode the URL of the specified XTI entry to OLE or DDE link components. @@ -492,9 +501,6 @@ bool XclImpExtName::CreateOleData(const ScDocument& rDoc, const OUString& rUrl, const ScMatrix& rCache = moMOper->GetCache(); SCSIZE nC, nR; rCache.GetDimensions(nC, nR); - if (!nC || !nR) - // cache matrix is empty. - return false; ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager(); sal_uInt16 nFileId = pRefMgr->getExternalFileId(rUrl); @@ -618,6 +624,36 @@ void XclImpSupbookTab::LoadCachedValues( const ScExternalRefCache::TableTypeRef& // External document (SUPBOOK) ================================================ +static OUString lcl_sanitize_table_name(const OUString& rName) +{ + const sal_Int32 nLen = rName.getLength(); + OUStringBuffer aNameBuffer; + aNameBuffer.ensureCapacity(nLen); + + for (sal_Int32 i = 0; i < nLen; ++i) + { + const sal_Unicode c = rName[i]; + switch (c) + { + case ':': + case '\\': + case '/': + case '?': + case '*': + case '[': + case ']': + break; + case '\'': + if (i == 0 || i == nLen - 1) // not allowed as first or last character + break; + [[fallthrough]]; + default: + aNameBuffer.append(c); + } + } + return aNameBuffer.makeStringAndClear(); +} + XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) : XclImpRoot( rStrm.GetRoot() ), meType( XclSupbookType::Unknown ), @@ -639,7 +675,7 @@ XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) : OUString aEncUrl( rStrm.ReadUniString() ); bool bSelf = false; - XclImpUrlHelper::DecodeUrl( maXclUrl, bSelf, GetRoot(), aEncUrl ); + XclImpUrlHelper::DecodeUrl( maXclUrl, bSelf, GetRoot(), aEncUrl, &mbXlStartup ); if( maXclUrl.equalsIgnoreAsciiCase( "\010EUROTOOL.XLA" ) ) { @@ -660,9 +696,14 @@ XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) : nSBTabCnt = nMaxRecords; } + const ScDefaultsOptions& rOpt = ScModule::get()->GetDefaultsOptions(); + const OUString aStrTable = rOpt.GetInitTabPrefix(); + for( sal_uInt16 nSBTab = 0; nSBTab < nSBTabCnt; ++nSBTab ) { - OUString aTabName( rStrm.ReadUniString() ); + OUString aTabName = lcl_sanitize_table_name( rStrm.ReadUniString() ); + if (aTabName.isEmpty()) + aTabName = aStrTable + OUString::number(static_cast(nSBTab)); maSupbTabList.push_back( std::make_unique( aTabName ) ); } } @@ -741,10 +782,17 @@ void XclImpSupbook::LoadCachedValues() if (meType != XclSupbookType::Extern || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0 || !GetDocShell()) return; - OUString aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) ); + OUString aUrl; + if (mbXlStartup) + aUrl = maXclUrl; + else + aUrl = ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()); ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager(); - sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl); + sal_uInt16 nFileId = pRefMgr->getExternalFileId(aUrl); + + if (mbXlStartup) + pRefMgr->setXlStartup(nFileId); for (auto& rxTab : maSupbTabList) { @@ -848,6 +896,12 @@ const OUString* XclImpLinkManagerImpl::GetSupbookUrl( sal_uInt16 nXtiIndex ) con return &p->GetXclUrl(); } +bool XclImpLinkManagerImpl::IsSupbookXlStartup( sal_uInt16 nXtiIndex ) const +{ + const XclImpSupbook* p = GetSupbook( nXtiIndex ); + return p && p->IsXlStartup(); +} + OUString XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const { const XclImpSupbook* p = GetSupbook(nXti); @@ -945,6 +999,11 @@ const OUString* XclImpLinkManager::GetSupbookUrl( sal_uInt16 nXtiIndex ) const return mxImpl->GetSupbookUrl(nXtiIndex); } +bool XclImpLinkManager::IsSupbookXlStartup( sal_uInt16 nXtiIndex ) const +{ + return mxImpl->IsSupbookXlStartup(nXtiIndex); +} + OUString XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const { return mxImpl->GetSupbookTabName(nXti, nXtiTab); diff --git a/sc/source/filter/excel/xiname.cxx b/sc/source/filter/excel/xiname.cxx index 2b3af1c74f5f..272982f73c3b 100644 --- a/sc/source/filter/excel/xiname.cxx +++ b/sc/source/filter/excel/xiname.cxx @@ -236,26 +236,20 @@ void XclImpName::ConvertTokens() void XclImpName::InsertName(const ScTokenArray* pArray) { // create the Calc name data - ScRangeData* pData = new ScRangeData(GetDoc(), maScName, *pArray, ScAddress(), meNameType); - pData->GuessPosition(); // calculate base position for relative refs - pData->SetIndex( mnNameIndex ); // used as unique identifier in formulas + std::unique_ptr pNewData(new ScRangeData(GetDoc(), maScName, *pArray, ScAddress(), meNameType)); + pNewData->GuessPosition(); // calculate base position for relative refs + pNewData->SetIndex( mnNameIndex ); // used as unique identifier in formulas + ScRangeData* pData = nullptr; if (mnXclTab == EXC_NAME_GLOBAL) { - if (!GetDoc().GetRangeName()->insert(pData)) - pData = nullptr; + pData = GetDoc().GetRangeName().insert(std::move(pNewData)); } else { ScRangeName* pLocalNames = GetDoc().GetRangeName(mnScTab); if (pLocalNames) { - if (!pLocalNames->insert(pData)) - pData = nullptr; - } - else - { - delete pData; - pData = nullptr; + pData = pLocalNames->insert(std::move(pNewData)); } if (GetBiff() == EXC_BIFF8 && pData) @@ -291,15 +285,8 @@ const XclImpName* XclImpNameManager::FindName( std::u16string_view rXclName, SCT { const XclImpName* pGlobalName = nullptr; // a found global name const XclImpName* pLocalName = nullptr; // a found local name - // If a duplicate name is seen by ScRangeName::insert then the existing - // name is erased and the new one inserted, so in the case of duplicates - // the last one seen is valid and the others invalid. So do this lookup in - // reverse in order to return the XclImpName* that references the valid - // entry (see tdf#44831 for the insert behavior and 'forum-mso-en4-30276.xls' - // for an example of this problem) - for (auto itName = maNameList.rbegin(); itName != maNameList.rend(); ++itName) + for( const auto& rxName : maNameList ) { - const auto& rxName = *itName; if( rxName->GetXclName() == rXclName ) { if( rxName->GetScTab() == nScTab ) diff --git a/sc/source/filter/excel/xipivot.cxx b/sc/source/filter/excel/xipivot.cxx index 78602724ce88..09127431ce1c 100644 --- a/sc/source/filter/excel/xipivot.cxx +++ b/sc/source/filter/excel/xipivot.cxx @@ -223,7 +223,8 @@ const XclImpPCItem* XclImpPCField::GetLimitItem( sal_uInt16 nItemIdx ) const void XclImpPCField::WriteFieldNameToSource( SCCOL nScCol, SCTAB nScTab ) { - OSL_ENSURE( HasOrigItems(), "XclImpPCField::WriteFieldNameToSource - only for standard fields" ); + OSL_ENSURE(HasOrigItems() || IsStandardField(), + "XclImpPCField::WriteFieldNameToSource - only for standard fields"); GetDocImport().setStringCell(ScAddress(nScCol, 0, nScTab), maFieldInfo.maName); mnSourceScCol = nScCol; } @@ -338,11 +339,17 @@ void XclImpPCField::ReadSxfield( XclImpStream& rStrm ) meFieldType = EXC_PCFIELD_STANDARD; OSL_ENSURE( meFieldType == EXC_PCFIELD_STANDARD, "XclImpPCField::ReadSxfield - invalid postponed field" ); } + else + { + if (!bCalced && !bChild && !bNum && (nGroupC == 0) && (nBaseC == 0) && (nOrigC == 0)) + meFieldType = EXC_PCFIELD_STANDARD; + } } void XclImpPCField::ReadItem( XclImpStream& rStrm ) { - OSL_ENSURE( HasInlineItems() || HasPostponedItems(), "XclImpPCField::ReadItem - field does not expect items" ); + OSL_ENSURE(HasInlineItems() || HasPostponedItems() || IsStandardField(), + "XclImpPCField::ReadItem - field does not expect items"); // read the item XclImpPCItemRef xItem = std::make_shared( rStrm ); @@ -356,7 +363,7 @@ void XclImpPCField::ReadItem( XclImpStream& rStrm ) else maOrigItems.push_back(std::move(xItem)); } - else if( HasInlineItems() || HasPostponedItems() ) + else if (HasInlineItems() || HasPostponedItems() || IsStandardField()) { maItems.push_back( xItem ); // visible item is original item in standard fields @@ -404,6 +411,20 @@ void XclImpPCField::ConvertGroupField( ScDPSaveData& rSaveData, const ScfStringV // private -------------------------------------------------------------------- +static OUString lcl_ItemToText( const XclImpPCItem& rItem, const XclImpRoot& rRoot ) +{ + const OUString& rText = rItem.ConvertToText(); + if( !rText.isEmpty() ) + return rText; + if( const double* pVal = rItem.GetDouble() ) + return OUString::number( *pVal ); + if( const DateTime* pDateTime = rItem.GetDateTime() ) + return OUString::number( rRoot.GetDoubleFromDateTime( *pDateTime ) ); + if( const sal_Int16* pVal = rItem.GetInteger() ) + return OUString::number( *pVal ); + return rText; +} + void XclImpPCField::ConvertStdGroupField( ScDPSaveData& rSaveData, const ScfStringVec& rVisNames ) const { const XclImpPCField* pBaseField = GetGroupBaseField(); @@ -419,7 +440,7 @@ void XclImpPCField::ConvertStdGroupField( ScDPSaveData& rSaveData, const ScfStri aGroupItems.reserve( maItems.size() ); // initialize with own item names for( const auto& rxItem : maItems ) - aGroupItems.emplace_back( rxItem->ConvertToText() ); + aGroupItems.emplace_back(lcl_ItemToText(*rxItem, *this)); // *** iterate over all base items, set their names at corresponding own items *** for( sal_uInt16 nItemIdx = 0, nItemCount = static_cast< sal_uInt16 >( maGroupOrder.size() ); nItemIdx < nItemCount; ++nItemIdx ) @@ -427,7 +448,7 @@ void XclImpPCField::ConvertStdGroupField( ScDPSaveData& rSaveData, const ScfStri if( const XclImpPCItem* pBaseItem = pBaseField->GetItem( nItemIdx ) ) if( const XclImpPCItem* pGroupItem = GetItem( maGroupOrder[ nItemIdx ] ) ) if( *pBaseItem != *pGroupItem ) - aGroupItems[ maGroupOrder[ nItemIdx ] ].AddElement( pBaseItem->ConvertToText() ); + aGroupItems[maGroupOrder[nItemIdx]].AddElement(lcl_ItemToText(*pBaseItem, *this)); // *** create the ScDPSaveGroupDimension object, fill with grouping info *** ScDPSaveGroupDimension aGroupDim( rBaseFieldName, GetFieldName( rVisNames ) ); @@ -707,6 +728,7 @@ void XclImpPivotCache::ReadPivotCacheStream( const XclImpStream& rStrm ) OUString aName = aDummyName.makeStringAndClear(); rDoc.CreateValidTabName( aName ); rDoc.RenameTab( nScTab, aName ); + rDoc.SetVisible( nScTab, false ); // set sheet index to source range maSrcRange.aStart.SetTab( nScTab ); maSrcRange.aEnd.SetTab( nScTab ); @@ -759,6 +781,12 @@ void XclImpPivotCache::ReadPivotCacheStream( const XclImpStream& rStrm ) if( bGenerateSource && (nFieldScCol <= rDoc.MaxCol()) ) xCurrField->WriteFieldNameToSource( nFieldScCol++, nScTab ); } + else if (xCurrField->IsStandardField()) + { + aOrigFields.push_back(xCurrField); + if (bGenerateSource && (nFieldScCol <= rDoc.MaxCol())) + xCurrField->WriteFieldNameToSource(nFieldScCol++, nScTab); + } // do not read items into invalid/postponed fields if( !xCurrField->HasInlineItems() ) xCurrField.reset(); diff --git a/sc/source/filter/excel/xistream.cxx b/sc/source/filter/excel/xistream.cxx index b691ff7a0e94..8ecc9eb95cec 100644 --- a/sc/source/filter/excel/xistream.cxx +++ b/sc/source/filter/excel/xistream.cxx @@ -894,6 +894,18 @@ OUString XclImpStream::ReadUniString( sal_uInt16 nChars, sal_uInt8 nFlags ) std::size_t nExtSize = ReadUniStringExtHeader( b16Bit, nFlags ); OUString aRet( ReadRawUniString( nChars, b16Bit ) ); Ignore( nExtSize ); + + OString aUtf8Check; + if (!aRet.convertToString( + &aUtf8Check, RTL_TEXTENCODING_UTF8, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)) + { + SAL_WARN("sc", "invalid utf8 string, doing best-effort fix"); + aRet.convertToString(&aUtf8Check, RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); + aRet = OStringToOUString(aUtf8Check, RTL_TEXTENCODING_UTF8); + } + return aRet; } @@ -953,6 +965,17 @@ OUString XclImpStream::ReadRawByteString( sal_uInt16 nChars ) sal_uInt16 nCharsRead = ReadRawData( pcBuffer.get(), nChars ); pcBuffer[ nCharsRead ] = '\0'; OUString aRet( pcBuffer.get(), strlen(pcBuffer.get()), mrRoot.GetTextEncoding() ); + + OString aUtf8Check; + if (!aRet.convertToString( + &aUtf8Check, RTL_TEXTENCODING_UTF8, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)) + { + SAL_WARN("sc", "invalid utf8 string, doing best-effort fix"); + aRet.convertToString(&aUtf8Check, RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); + aRet = OStringToOUString(aUtf8Check, RTL_TEXTENCODING_UTF8); + } return aRet; } diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx index 742557f0f822..b9d38106d3a5 100644 --- a/sc/source/filter/excel/xlformula.cxx +++ b/sc/source/filter/excel/xlformula.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -220,7 +221,8 @@ const XclFunctionInfo saFuncTable_2[] = { ocLenB, 211, 1, 1, V, { VR }, 0, nullptr }, { ocRoundUp, 212, 2, 2, V, { VR }, 0, nullptr }, { ocRoundDown, 213, 2, 2, V, { VR }, 0, nullptr }, - { ocExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_IMPORTONLY, nullptr } + { ocExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_IMPORTONLY, nullptr }, + { ocUDExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_IMPORTONLY, nullptr } }; /** Functions new in BIFF3. */ @@ -349,6 +351,7 @@ const XclFunctionInfo saFuncTable_5[] = { ocGetDiffDate360, 220, 2, 3, V, { VR }, 0, nullptr }, // BIFF3-4: 2, BIFF5: 2-3 { ocMacro, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, { ocExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, + { ocUDExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, nullptr }, { ocConcat, 336, 0, MX, V, { VR }, 0, nullptr }, { ocPower, 337, 2, 2, V, { VR }, 0, nullptr }, { ocRad, 342, 1, 1, V, { VR }, 0, nullptr }, @@ -610,7 +613,16 @@ const XclFunctionInfo saFuncTable_2021[] = EXC_FUNCENTRY_V_VR( ocMatSequence,1, 4, 0, "SEQUENCE" ), EXC_FUNCENTRY_V_VR( ocRandArray, 0, 5, 0, "RANDARRAY" ), EXC_FUNCENTRY_V_VR( ocUnique, 1, 3, 0, "UNIQUE" ), + EXC_FUNCENTRY_V_VR( ocArrayToText,1, 2, 0, "ARRAYTOTEXT" ), EXC_FUNCENTRY_V_VR( ocLet, 3, 3, 0, "LET"), + EXC_FUNCENTRY_V_VR( ocLambda, 1, MX, 0, "LAMBDA"), + EXC_FUNCENTRY_V_VR( ocIsOmitted, 1, 1, 0, "ISOMITTED"), + EXC_FUNCENTRY_V_VR( ocByCol, 2, 2, 0, "BYCOL"), + EXC_FUNCENTRY_V_VR( ocByRow, 2, 2, 0, "BYROW"), + EXC_FUNCENTRY_V_VR( ocMakeArray, 3, 3, 0, "MAKEARRAY"), + EXC_FUNCENTRY_V_VR( ocMap, 2, MX, 0, "MAP"), + EXC_FUNCENTRY_V_VR( ocReduce, 2, 3, 0, "REDUCE"), + EXC_FUNCENTRY_V_VR( ocScan, 2, 3, 0, "SCAN"), }; /** Functions new in Excel 2024. @@ -924,7 +936,7 @@ void XclTokenArrayIterator::SkipSpaces() bool XclTokenArrayHelper::GetTokenString( OUString& rString, const FormulaToken& rScToken ) { bool bIsStr = (rScToken.GetType() == svString) && (rScToken.GetOpCode() == ocPush); - if( bIsStr ) rString = rScToken.GetString().getString(); + if( bIsStr ) rString = static_cast(rScToken).GetString().getString(); return bIsStr; } @@ -994,7 +1006,7 @@ bool lclGetAddress( const ScDocument& rDoc, ScAddress& rAddress, const FormulaTo bool bIsSingleRef = (eOpCode == ocPush) && (rToken.GetType() == svSingleRef); if( bIsSingleRef ) { - const ScSingleRefData& rRef = *rToken.GetSingleRef(); + const ScSingleRefData& rRef = static_cast(rToken).GetSingleRef(); rAddress = rRef.toAbs(rDoc, rPos); bIsSingleRef = !rRef.IsDeleted(); } diff --git a/sc/source/filter/excel/xlroot.cxx b/sc/source/filter/excel/xlroot.cxx index 7dea69cc1384..a5068cf99e0b 100644 --- a/sc/source/filter/excel/xlroot.cxx +++ b/sc/source/filter/excel/xlroot.cxx @@ -309,7 +309,7 @@ ScStyleSheetPool& XclRoot::GetStyleSheetPool() const ScRangeName& XclRoot::GetNamedRanges() const { - return *GetDoc().GetRangeName(); + return GetDoc().GetRangeName(); } SdrPage* XclRoot::GetSdrPage( SCTAB nScTab ) const @@ -388,7 +388,7 @@ ScHeaderEditEngine& XclRoot::GetHFEditEngine() const // set Calc header/footer defaults SfxItemSet aEditSet( rEE.GetEmptyItemSet() ); - SfxItemSetFixed aItemSet( *GetDoc().GetPool() ); + SfxItemSet aItemSet(SfxItemSet::makeFixedSfxItemSet( *GetDoc().GetPool() )); ScPatternAttr::FillToEditItemSet( aEditSet, aItemSet ); // FillToEditItemSet() adjusts font height to 1/100th mm, we need twips aEditSet.Put( aItemSet.Get( ATTR_FONT_HEIGHT ).CloneSetWhich(EE_CHAR_FONTHEIGHT) ); diff --git a/sc/source/filter/excel/xlstyle.cxx b/sc/source/filter/excel/xlstyle.cxx index 65764f753a08..dddc9803536f 100644 --- a/sc/source/filter/excel/xlstyle.cxx +++ b/sc/source/filter/excel/xlstyle.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -98,14 +99,14 @@ XclDefaultPalette::XclDefaultPalette( const XclRoot& rRoot ) : // Don't use the system HelpBack and HelpText colours as it causes problems // with modern gnome. This is because mnNoteText and mnNoteBack are used // when colour indices ( instead of real colours ) are specified. - // Note: That this it is not an unusual scenario that we get the Note + // Note: it is not an unusual scenario that we get the Note // background specified as a real colour and the text specified as a // colour index. That means the text colour would be picked from // the system where the note background would be picked from a real colour. // Previously the note text colour was picked from the system tooltip // text colour, on modern gnome(e.g. 3) that tends to be 'white' with the // default theme. - // Using the Libreoffice defaults ( instead of system specific colours + // Using the LibreOffice defaults ( instead of system specific colours // ) lessens the chance of the one colour being an unsuitable combination // because by default the note text is black and the note background is // a light yellow colour ( very similar to Excel's normal defaults ) @@ -201,7 +202,19 @@ void XclFontData::Clear() void XclFontData::FillFromVclFont(const vcl::Font& rFont, model::ComplexColor const& rComplexColor) { - maName = XclTools::GetXclFontName( rFont.GetFamilyName() ); // substitute with MS fonts + // tdf#172647: recompose the legacy font name. + OUString aFontName(rFont.GetFamilyName()); + if (!rFont.GetStyleName().isEmpty()) + { + if (OutputDevice* pDev = Application::GetDefaultDevice()) + { + OUString aLegacyName; + if (pDev->GetLegacyFontName(aFontName, rFont.GetStyleName(), rFont.GetWeight(), + rFont.GetItalic(), aLegacyName)) + aFontName = aLegacyName; + } + } + maName = XclTools::GetXclFontName( aFontName ); // substitute with MS fonts maStyle.clear(); SetScUnderline( rFont.GetUnderline() ); mnEscapem = EXC_FONTESC_NONE; @@ -572,7 +585,7 @@ const char *const *const sppcPropNamesChCmplxNoName = sppcPropNamesChCmplx + 1; const char *const sppcPropNamesControl[] = { "FontName", "FontFamily", "FontCharset", "FontHeight", "FontSlant", - "FontWeight", "FontLineStyle", "FontStrikeout", "TextColor", nullptr + "FontWeight", "FontUnderline", "FontStrikeout", "TextColor", nullptr }; /** Inserts all passed API font settings into the font data object. */ diff --git a/sc/source/filter/excel/xltools.cxx b/sc/source/filter/excel/xltools.cxx index c6ecb31ed6d5..8f6e6aec4493 100644 --- a/sc/source/filter/excel/xltools.cxx +++ b/sc/source/filter/excel/xltools.cxx @@ -213,6 +213,7 @@ sal_uInt8 XclTools::GetXclErrorCode( FormulaError nScError ) case FormulaError::NoAddin: return EXC_ERR_NAME; case FormulaError::NoMacro: return EXC_ERR_NAME; case FormulaError::NotAvailable: return EXC_ERR_NA; + case FormulaError::Spill: return EXC_ERR_SPILL; default: break; } return EXC_ERR_NA; @@ -229,6 +230,7 @@ FormulaError XclTools::GetScErrorCode( sal_uInt8 nXclError ) case EXC_ERR_NAME: return FormulaError::NoName; case EXC_ERR_NUM: return FormulaError::IllegalFPOperation; case EXC_ERR_NA: return FormulaError::NotAvailable; + case EXC_ERR_SPILL: return FormulaError::Spill; default: OSL_FAIL( "XclTools::GetScErrorCode - unknown error code" ); } return FormulaError::NotAvailable; diff --git a/sc/source/filter/html/htmlexp.cxx b/sc/source/filter/html/htmlexp.cxx index 6287447c0e97..263823f0e3ec 100644 --- a/sc/source/filter/html/htmlexp.cxx +++ b/sc/source/filter/html/htmlexp.cxx @@ -790,7 +790,7 @@ void ScHTMLExport::WriteTables() "=\"" OOO_STRING_SVTOOLS_HTML_AL_left "\""); } - // ALIGN=LEFT allow text and graphics to flow around + // ALIGN=LEFT allows text and graphics to flow around // CELLSPACING aByteStrOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cellspacing "=\"" + @@ -1223,7 +1223,7 @@ void ScHTMLExport::WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SC //create the element holding the contents //this is a bit naive, since it doesn't separate - //lines into html breaklines yet + //lines into html line breaks yet TAG_ON(OOO_STRING_SVTOOLS_HTML_comment2); OUT_STR( pNote->GetText() ); TAG_OFF(OOO_STRING_SVTOOLS_HTML_comment2); @@ -1396,7 +1396,9 @@ bool ScHTMLExport::WriteFieldText( const EditTextObject* pData ) { bUrl = true; rStrm.WriteChar( '<' ).WriteOString( OOO_STRING_SVTOOLS_HTML_anchor ).WriteChar( ' ' ).WriteOString( OOO_STRING_SVTOOLS_HTML_O_href ).WriteOString( "=\"" ); - OUT_STR( pURLField->GetURL() ); + // tdf#44196 - keep relative paths on URL export + OUT_STR(URIHelper::simpleNormalizedMakeRelative(aBaseURL, + pURLField->GetURL())); rStrm.WriteOString( "\">" ); OUT_STR( pURLField->GetRepresentation() ); rStrm.WriteOString( "' ); diff --git a/sc/source/filter/html/htmlimp.cxx b/sc/source/filter/html/htmlimp.cxx index 8b5c88e2bfee..9bf3cbd578c9 100644 --- a/sc/source/filter/html/htmlimp.cxx +++ b/sc/source/filter/html/htmlimp.cxx @@ -72,7 +72,7 @@ ScHTMLImport::ScHTMLImport( ScDocument& rDoc, const OUString& rBaseURL, const Sc { const SfxItemSet& rSet = pStyleSheet->GetItemSet(); const SvxLRSpaceItem* pLRItem = &rSet.Get( ATTR_LRSPACE ); - tools::Long nLeftMargin = pLRItem->ResolveLeft({}); + tools::Long nLeftMargin = pLRItem->ResolveLeft(); tools::Long nRightMargin = pLRItem->ResolveRight({}); const SvxULSpaceItem* pULItem = &rSet.Get( ATTR_ULSPACE ); tools::Long nTopMargin = pULItem->GetUpper(); @@ -107,8 +107,7 @@ void ScHTMLImport::InsertRangeName( ScDocument& rDoc, const OUString& rName, con aRefData.Ref2.SetFlag3D( aRefData.Ref2.Tab() != aRefData.Ref1.Tab() ); ScTokenArray aTokArray(rDoc); aTokArray.AddDoubleReference( aRefData ); - ScRangeData* pRangeData = new ScRangeData( rDoc, rName, aTokArray ); - rDoc.GetRangeName()->insert( pRangeData ); + rDoc.GetRangeName().insert( std::make_unique( rDoc, rName, aTokArray ) ); } void ScHTMLImport::WriteToDocument( @@ -191,7 +190,7 @@ void ScHTMLImport::WriteToDocument( if (!pTable->GetTableCaption().isEmpty()) aName.append(" - " + pTable->GetTableCaption()); const OUString sName(aName.makeStringAndClear()); - if (!mrDoc.GetRangeName()->findByUpperName(ScGlobal::getCharClass().uppercase(sName))) + if (!mrDoc.GetRangeName().findByUpperName(ScGlobal::getCharClass().uppercase(sName))) InsertRangeName(mrDoc, sName, aNewRange); } } @@ -207,19 +206,19 @@ OUString ScHTMLImport::GetHTMLRangeNameList( const ScDocument& rDoc, std::u16str return OUString(); OUString aNewName; - ScRangeName* pRangeNames = rDoc.GetRangeName(); + ScRangeName& rRangeNames = rDoc.GetRangeName(); ScRangeList aRangeList; sal_Int32 nStringIx = 0; do { OUString aToken( o3tl::getToken(rOrigName, 0, ';', nStringIx ) ); - if( pRangeNames && ScfTools::IsHTMLTablesName( aToken ) ) + if( ScfTools::IsHTMLTablesName( aToken ) ) { // build list with all HTML tables sal_uLong nIndex = 1; for(;;) { aToken = ScfTools::GetNameFromHTMLIndex( nIndex++ ); - const ScRangeData* pRangeData = pRangeNames->findByUpperName(ScGlobal::getCharClass().uppercase(aToken)); + const ScRangeData* pRangeData = rRangeNames.findByUpperName(ScGlobal::getCharClass().uppercase(aToken)); if (!pRangeData) break; ScRange aRange; diff --git a/sc/source/filter/html/htmlpars.cxx b/sc/source/filter/html/htmlpars.cxx index b74f90f193cd..47cd951da694 100644 --- a/sc/source/filter/html/htmlpars.cxx +++ b/sc/source/filter/html/htmlpars.cxx @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -327,7 +328,8 @@ ScHTMLLayoutParser::ScHTMLLayoutParser( bFirstRow( true ), bTabInTabCell( false ), bInCell( false ), - bInTitle( false ) + bInTitle( false ), + bInImg( false ) { MakeColNoRef( xLocalColOffset.get(), 0, 0, 0, 0 ); MakeColNoRef( &maColOffset, 0, 0, 0, 0 ); @@ -1003,6 +1005,11 @@ IMPL_LINK( ScHTMLLayoutParser, HTMLImportHdl, HtmlImportInfo&, rInfo, void ) } while ( nTableLevel > 0 ) TableOff( &rInfo ); // close tables, if
      missing + if (bInImg) + { + CloseEntry( &rInfo ); + bInImg = false; + } break; case HtmlImportState::SetAttr: break; @@ -1223,7 +1230,7 @@ void ScHTMLLayoutParser::TableOn( HtmlImportInfo* pInfo ) NextRow( pInfo ); } else - { // It start's in this cell or next to each other + { // It starts in this cell or next to each other bTabInTabCell = false; nColCntStart = nColCnt; nColOffset = nTmpColOffset; @@ -1344,7 +1351,7 @@ void ScHTMLLayoutParser::TableOff( const HtmlImportInfo* pInfo ) { // Outer for ( SCROW j=0; j < nRowSpan; j++ ) { - sal_uLong nRowKey = nRow + j; + SCROW nRowKey = nRow + j; SCROW nR = (*pTab1)[ nRowKey ]; if ( !nR ) (*pTab1)[ nRowKey ] = nRowsPerRow1; @@ -1372,13 +1379,13 @@ void ScHTMLLayoutParser::TableOff( const HtmlImportInfo* pInfo ) if ( nRowsPerRow2 > 1 ) { // Inner if ( !pTab2 ) - { // nRowsPerRow2 could be've been incremented + { // nRowsPerRow2 could have been incremented pTab2 = new InnerMap; (*pTables)[ nTable ].reset(pTab2); } for ( SCROW j=0; j < nRows; j++ ) { - sal_uLong nRowKey = nRow + j; + SCROW nRowKey = nRow + j; (*pTab2)[ nRowKey ] = nRowsPerRow2; } } @@ -1436,6 +1443,7 @@ void ScHTMLLayoutParser::TableOff( const HtmlImportInfo* pInfo ) void ScHTMLLayoutParser::Image( HtmlImportInfo* pInfo ) { + bInImg = true; mxActEntry->maImageList.push_back(std::make_unique()); ScHTMLImage* pImage = mxActEntry->maImageList.back().get(); const HTMLOptions& rOptions = static_cast(pInfo->pParser)->GetOptions(); @@ -1498,8 +1506,21 @@ void ScHTMLLayoutParser::Image( HtmlImportInfo* pInfo ) sal_uInt16 nFormat; std::optional oGraphic(std::in_place); GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); - if ( ERRCODE_NONE != GraphicFilter::LoadGraphic( pImage->aURL, pImage->aFilterName, + INetURLObject aGraphicURL(pImage->aURL); + if (aGraphicURL.GetProtocol() == INetProtocol::Data) + { + std::unique_ptr const pStream(aGraphicURL.getData()); + if (!pStream) + return; // Bad luck - malformed data: URL + *oGraphic = rFilter.ImportUnloadedGraphic(*pStream); + pImage->aURL.clear(); + } + else if ( ERRCODE_NONE == GraphicFilter::LoadGraphic( pImage->aURL, pImage->aFilterName, *oGraphic, &rFilter, &nFormat ) ) + { + pImage->aFilterName = rFilter.GetImportFormatName( nFormat ); + } + else { return ; // Bad luck } @@ -1508,7 +1529,6 @@ void ScHTMLLayoutParser::Image( HtmlImportInfo* pInfo ) mxActEntry->bHasGraphic = true; mxActEntry->aAltText.clear(); } - pImage->aFilterName = rFilter.GetImportFormatName( nFormat ); pImage->oGraphic = std::move( oGraphic ); if ( !(pImage->aSize.Width() && pImage->aSize.Height()) ) { diff --git a/sc/source/filter/inc/NamedSheetViewFragment.hxx b/sc/source/filter/inc/NamedSheetViewFragment.hxx new file mode 100644 index 000000000000..4f4ca210132c --- /dev/null +++ b/sc/source/filter/inc/NamedSheetViewFragment.hxx @@ -0,0 +1,157 @@ +/* -*- 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/. + */ + +#pragma once + +#include "excelhandlers.hxx" +#include "autofilterbuffer.hxx" + +#include + +namespace oox::xls::nsv +{ +// Schema for NamedSheetViews : +// https://learn.microsoft.com/ga-ie/openspecs/office_standards/ms-xlsx/55396aef-0c07-4ffb-9ffb-e48b6d339abe + +struct FilterData +{ + sal_Int32 maColumnID; // required + std::shared_ptr mxSettings; +}; + +struct ColumnFilterData +{ + sal_Int32 maColumnID; // required + OUString maID; // GUID, optional + std::vector maFilters; // min 0, max unbounded +}; + +struct SortRuleData +{ + sal_Int32 maColumnID; // required + OUString maID; // GUID, optional + + // Part of (x14:CT_SortCondition) + bool mbDescending = false; // optional, default false + sal_Int32 maSortBy = XML_value; // optional, default "value" + OUString maRef; // required + + // customList, x:ST_Xstring, optional + // dxfId, x:ST_DxfId, optional + // iconSet, ST_IconSetType, optional, default "3Arrows" + // iconId, sal_uInt32, optional +}; + +struct SortRulesData +{ + bool mbCaseSensitive = false; // optional, default false + sal_Int32 mnMethod = XML_none; // optional, default none + std::vector maRules; // min 0, max 64 +}; + +struct NsvFilterData +{ + OUString maFilterID; // GUID, required + OUString maRef; // optional + std::optional maTableID; // optional + std::vector maColumnFilters; // min 0, max unbounded + std::optional maSortRules; // optional +}; + +struct NamedSheetViewData +{ + OUString maName; // required + OUString maID; // GUID, required + std::vector maNsvFilters; // min 0, max unbounded +}; + +/** Handles parsing of one element and sub-elements */ +class FilterContext final : public WorksheetContextBase +{ + FilterData& mrFilterData; + +public: + explicit FilterContext(WorksheetContextBase& rParent, FilterData& rFilterData); + +private: + virtual oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; +}; + +/** Handles parsing of one element and sub-elements */ +class ColumnFilterContext final : public WorksheetContextBase +{ + ColumnFilterData& mrColumnFilterData; + +public: + explicit ColumnFilterContext(WorksheetContextBase& rParent, + ColumnFilterData& rColumnFilterData); + +private: + virtual oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; +}; + +/** Handles parsing of one element and sub-elements */ +class SortRuleContext final : public WorksheetContextBase +{ + SortRuleData& mrSortRuleData; + +public: + explicit SortRuleContext(WorksheetContextBase& rParent, SortRuleData& rSortRuleData); + +private: + virtual oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; +}; + +/** Handles parsing of one element and sub-elements */ +class NsvFilterContext final : public WorksheetContextBase +{ + NsvFilterData& mrNsvFilterData; + +public: + explicit NsvFilterContext(WorksheetContextBase& rParent, NsvFilterData& rNsvFilterData); + +private: + virtual oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; +}; + +/** Handles parsing of one element and sub-elements */ +class NamedSheetViewContext final : public WorksheetContextBase +{ + NamedSheetViewData& mrNamedSheetViewData; + +public: + explicit NamedSheetViewContext(WorksheetFragmentBase& rParent, + NamedSheetViewData& rNamedSheetViewData); + +private: + virtual oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; +}; + +/** Handles parsing of named sheet view data contained in namedSheetView*.xml file */ +class NamedSheetViewFragment final : public WorksheetFragmentBase +{ + std::vector maNamedSheetViews; + +public: + explicit NamedSheetViewFragment(WorksheetHelper const& rHelper, OUString const& rFragmentPath); + +private: + virtual oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + AttributeList const& rAttribs) override; + virtual void finalizeImport() override; +}; + +} // namespace oox::xls::nsv + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/inc/NamedSheetViewImporter.hxx b/sc/source/filter/inc/NamedSheetViewImporter.hxx new file mode 100644 index 000000000000..f18306586171 --- /dev/null +++ b/sc/source/filter/inc/NamedSheetViewImporter.hxx @@ -0,0 +1,33 @@ +/* -*- 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/. + */ + +#pragma once + +#include "workbookhelper.hxx" +#include "NamedSheetViewFragment.hxx" + +#include + +namespace oox::xls::nsv +{ +/** Imports named sheet view data into the document model. */ +class NamedSheetViewImporter final : public WorkbookHelper +{ + std::vector maNamedSheetViews; + SCTAB mnTab; + +public: + explicit NamedSheetViewImporter(const WorkbookHelper& rHelper, SCTAB nTab); + void setNamedSheetViews(std::vector&& rData); + void finalizeImport(); +}; + +} // namespace oox::xls::nsv + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/inc/PivotTableFormat.hxx b/sc/source/filter/inc/PivotTableFormat.hxx index 544ee06cc2d0..189d0049a33f 100644 --- a/sc/source/filter/inc/PivotTableFormat.hxx +++ b/sc/source/filter/inc/PivotTableFormat.hxx @@ -51,7 +51,8 @@ private: bool mbOutline = true; std::optional moOffset = std::nullopt; bool mbCollapsedLevelsAreSubtotals = false; - // TODO Axis + // tdf#122473 - import alignment and axis-based pivot area formats + std::optional moAxis = std::nullopt; std::optional moFieldPosition = std::nullopt; std::vector> maReferences; diff --git a/sc/source/filter/inc/autofilterbuffer.hxx b/sc/source/filter/inc/autofilterbuffer.hxx index 09cadae26484..b75aef577a79 100644 --- a/sc/source/filter/inc/autofilterbuffer.hxx +++ b/sc/source/filter/inc/autofilterbuffer.hxx @@ -193,10 +193,14 @@ public: FilterSettingsBase& createFilterSettings() { mxSettings = std::make_shared( *this ); return *mxSettings; } + /** Sets column ID and filter settings from external data. */ + void setColumnData(sal_Int32 nColId, std::shared_ptr xSettings); + /** Returns converted UNO API filter settings representing all filter settings of this column. */ ApiFilterSettings finalizeImport(); bool isButtonHidden(); + sal_Int32 getColumnId() const { return mnColId; } private: std::shared_ptr< FilterSettingsBase > @@ -239,6 +243,9 @@ public: SortCondition& createSortCondition(); + /** Sets the filter range directly. */ + void setRange(const ScRange& rRange); + /** Applies the filter to the passed filter descriptor. */ void finalizeImport( const rtl::Reference& rxDatabaseRange, sal_Int16 nSheet ); diff --git a/sc/source/filter/inc/autofiltercontext.hxx b/sc/source/filter/inc/autofiltercontext.hxx index f6eadab801bc..5d68eb20cac1 100644 --- a/sc/source/filter/inc/autofiltercontext.hxx +++ b/sc/source/filter/inc/autofiltercontext.hxx @@ -63,7 +63,7 @@ private: class SortConditionContext final : public WorksheetContextBase { public: - explicit SortConditionContext( WorksheetContextBase& rFragment, SortCondition& rSortCondition ); + explicit SortConditionContext( WorksheetContextBase& rParent, SortCondition& rSortCondition ); private: virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) override; @@ -80,7 +80,7 @@ private: class SortStateContext final : public WorksheetContextBase { public: - explicit SortStateContext( WorksheetContextBase& rFragment, AutoFilter& rAutoFilter ); + explicit SortStateContext( WorksheetContextBase& rParent, AutoFilter& rAutoFilter ); private: virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) override; diff --git a/sc/source/filter/inc/biffhelper.hxx b/sc/source/filter/inc/biffhelper.hxx index c01d47e40e21..f5448d33d17c 100644 --- a/sc/source/filter/inc/biffhelper.hxx +++ b/sc/source/filter/inc/biffhelper.hxx @@ -566,6 +566,7 @@ const sal_uInt8 BIFF_ERR_REF = 0x17; const sal_uInt8 BIFF_ERR_NAME = 0x1D; const sal_uInt8 BIFF_ERR_NUM = 0x24; const sal_uInt8 BIFF_ERR_NA = 0x2A; +const sal_uInt8 BIFF_ERR_SPILL = 0x2B; const sal_uInt16 BIFF_BOF_BIFF2 = 0x0200; const sal_uInt16 BIFF_BOF_BIFF3 = 0x0300; diff --git a/sc/source/filter/inc/drawingbase.hxx b/sc/source/filter/inc/drawingbase.hxx index 576a3619db1e..4070a52a6325 100644 --- a/sc/source/filter/inc/drawingbase.hxx +++ b/sc/source/filter/inc/drawingbase.hxx @@ -105,6 +105,8 @@ public: /** Calculates the resulting shape anchor in 1/100 mm. */ css::awt::Rectangle calcAnchorRectHmm( const css::awt::Size& rPageSizeHmm ) const; AnchorType getEditAs() const { return meEditAs; } + + AnchorType getAnchorType() const { return meAnchorType; } private: /** Converts the passed anchor to an absolute position in EMUs. */ ::oox::drawingml::EmuPoint calcCellAnchorEmu( const CellAnchorModel& rModel ) const; diff --git a/sc/source/filter/inc/drawingfragment.hxx b/sc/source/filter/inc/drawingfragment.hxx index 64c7644e3ca3..6bff771b3850 100644 --- a/sc/source/filter/inc/drawingfragment.hxx +++ b/sc/source/filter/inc/drawingfragment.hxx @@ -149,9 +149,6 @@ public: explicit VmlDrawing( const WorksheetHelper& rHelper ); - /** Returns the drawing shape for a cell note at the specified position. */ - const ::oox::vml::ShapeBase* getNoteShape( const ScAddress& rPos ) const; - NoteShapesMap buildNoteShapesMap() const; /** Filters cell note shapes. */ diff --git a/sc/source/filter/inc/export/ExportTools.hxx b/sc/source/filter/inc/export/ExportTools.hxx index dc08c33846b1..66166593a4c4 100644 --- a/sc/source/filter/inc/export/ExportTools.hxx +++ b/sc/source/filter/inc/export/ExportTools.hxx @@ -12,12 +12,22 @@ #include #include +#include + namespace oox::xls { void writeComplexColor(const sax_fastparser::FSHelperPtr& pFS, sal_Int32 nElement, model::ComplexColor const& rComplexColor, Color const& rColor); void writeComplexColor(const sax_fastparser::FSHelperPtr& pFS, sal_Int32 nElement, model::ComplexColor const& rComplexColor); + +/** Writes an OOXML dateGroupItem element from a date string. + The date string may be partial: "YYYY", "YYYY-MM", or "YYYY-MM-DD". + The dateTimeGrouping attribute is determined by the number of date components. + nElement is the fully-qualified element token (e.g. XML_dateGroupItem or + FSNS(XML_x, XML_dateGroupItem) depending on the stream's namespace context). */ +void writeDateGroupItem(sax_fastparser::FSHelperPtr const& pStream, sal_Int32 nElement, + std::string_view aDateString); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/inc/export/NamedSheetViews.hxx b/sc/source/filter/inc/export/NamedSheetViews.hxx new file mode 100644 index 000000000000..797266399ba1 --- /dev/null +++ b/sc/source/filter/inc/export/NamedSheetViews.hxx @@ -0,0 +1,47 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include +#include +#include + +struct ScQueryParam; +struct ScSortParam; +namespace sc +{ +class SheetView; +} + +namespace xcl::exp +{ +/** Export of named sheet views for a single sheet. */ +class NamedSheetViews : public XclExpRecordBase, protected XclExpRoot +{ +public: + explicit NamedSheetViews(const XclExpRoot& rRoot, SCTAB nTab); + + virtual void SaveXml(XclExpXmlStream& rStream) override; + +private: + void saveSheetView(const sax_fastparser::FSHelperPtr& pStream, const sc::SheetView& rSheetView); + void saveColumnFilters(const sax_fastparser::FSHelperPtr& pStream, + const ScQueryParam& rQueryParam); + void saveSortRules(const sax_fastparser::FSHelperPtr& pStream, const ScRange& rRange, + SCTAB nViewTab, const ScSortParam& rSortParam); + + SCTAB mnTab; + bool mbHasSheetViews; +}; + +} // end namespace xcl::exp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/inc/externallinkbuffer.hxx b/sc/source/filter/inc/externallinkbuffer.hxx index 2f2727a7b673..24feff87c1eb 100644 --- a/sc/source/filter/inc/externallinkbuffer.hxx +++ b/sc/source/filter/inc/externallinkbuffer.hxx @@ -161,8 +161,9 @@ enum class ExternalLinkType Self, /// Link refers to the current workbook. Same, /// Link refers to the current sheet. External, /// Link refers to an external spreadsheet document. - // let's ignore xlStartup and xlAlternateStartup for now + // let's ignore xlAlternateStartup for now PathMissing, /// Just for round-tripping (FIXME: Functionality not actually implemented after all.) + XlStartup, /// Link refers to a document in the XLSTART folder. Library, /// Link refers to an external add-in. DDE, /// DDE link. OLE, /// OLE link. @@ -178,6 +179,7 @@ inline std::basic_ostream & operator <<( case ExternalLinkType::Self: return stream << "self"; case ExternalLinkType::Same: return stream << "same"; case ExternalLinkType::External: return stream << "external"; + case ExternalLinkType::XlStartup: return stream << "xlstartup"; case ExternalLinkType::PathMissing: return stream << "pathmissing"; case ExternalLinkType::Library: return stream << "library"; case ExternalLinkType::DDE: return stream << "dde"; diff --git a/sc/source/filter/inc/formulabuffer.hxx b/sc/source/filter/inc/formulabuffer.hxx index 11b088d6ac8f..abb21a9edc98 100644 --- a/sc/source/filter/inc/formulabuffer.hxx +++ b/sc/source/filter/inc/formulabuffer.hxx @@ -10,12 +10,34 @@ #pragma once #include "workbookhelper.hxx" +#include +#include +#include #include #include #include +class ScTokenArray; + namespace oox::xls { +// When one of the trigger opcodes is followed by ((...)) that +// spans the whole argument, drop the inner parenthesis pair: +// OPCODE((expr)) -> OPCODE(expr) +// An inner pair that does not span the whole argument, or +// parentheses that belong to a function call inside the +// argument, stay: +// OPCODE((A)+B) -> OPCODE((A)+B) +// OPCODE(FUNC(arg)) -> OPCODE(FUNC(arg)) +SAL_DLLPUBLIC_EXPORT void stripRedundantParentheses( + ScTokenArray& rArray, std::initializer_list aTriggerOpCodes); + +// _xlfn.ANCHORARRAY() is the OOXML spelling of the native +// postfix #. Both give the same RPN, but the parse array +// keeps the source order and would read back as #(), so +// rewrite each such span to #. +SAL_DLLPUBLIC_EXPORT void liftAnchorArrayToPostfix(ScTokenArray& rArray); + class FormulaBuffer final : public WorkbookHelper { public: @@ -42,24 +64,51 @@ public: OUString maCellValue; sal_Int32 mnSharedId; sal_Int32 mnValueType; + /// True when the XLSX cell carried cm="1", marking it as a dynamic-array + /// master. + bool mbDynamicArrayMaster = false; SharedFormulaDesc( const ScAddress& rAddr, sal_Int32 nSharedId, - OUString aCellValue, sal_Int32 nValueType ); + OUString aCellValue, sal_Int32 nValueType, + bool bDynamicArrayMaster = false ); }; struct TokenAddressItem { OUString maTokenStr; ScAddress maAddress; - TokenAddressItem( OUString aTokenStr, const ScAddress& rAddress ) : maTokenStr(std::move( aTokenStr )), maAddress( rAddress ) {} + /// True when the XLSX cell carried cm="1", marking it as a dynamic-array + /// master. + bool mbDynamicArrayMaster = false; + TokenAddressItem( OUString aTokenStr, const ScAddress& rAddress, + bool bDynamicArrayMaster = false ) + : maTokenStr(std::move( aTokenStr )) + , maAddress( rAddress ) + , mbDynamicArrayMaster(bDynamicArrayMaster) {} }; struct TokenRangeAddressItem { TokenAddressItem maTokenAndAddress; ScRange maRange; - TokenRangeAddressItem( TokenAddressItem aTokenAndAddress, const ScRange& rRange ) : maTokenAndAddress(std::move( aTokenAndAddress )), maRange( rRange ) {} + + /// File was saved with a #SPILL! error on the master cell. Triggers + /// blocker preservation so reference cells aren't materialised over + /// real user data sitting in the matrix range. + bool mbCachedSpill; + /// True when the XLSX cell carried cm="1", marking it as a dynamic-array + /// master. + bool mbDynamicArrayMaster = false; + + TokenRangeAddressItem(TokenAddressItem aTokenAndAddress, const ScRange& rRange, + bool bCachedSpill = false, + bool bDynamicArrayMaster = false) + : maTokenAndAddress(std::move(aTokenAndAddress)) + , maRange(rRange) + , mbCachedSpill(bCachedSpill) + , mbDynamicArrayMaster(bDynamicArrayMaster) + {} }; struct FormulaValue @@ -97,18 +146,22 @@ private: public: explicit FormulaBuffer( const WorkbookHelper& rHelper ); void finalizeImport(); - void setCellFormula( const ScAddress& rAddress, const OUString& ); + void setCellFormula( const ScAddress& rAddress, const OUString&, + bool bDynamicArrayMaster = false ); void setCellFormula( const ScAddress& rAddress, sal_Int32 nSharedId, - const OUString& rCellValue, sal_Int32 nValueType ); + const OUString& rCellValue, sal_Int32 nValueType, + bool bDynamicArrayMaster = false ); void setCellFormulaValue( const ScAddress& rAddress, const OUString& rValueStr, sal_Int32 nCellType ); - void setCellArrayFormula( const ScRange& rRangeAddress, - const ScAddress& rTokenAddress, - const OUString& ); + void setCellArrayFormula(const ScRange& rRangeAddress, + const ScAddress& rTokenAddress, + const OUString&, + bool bCachedSpill = false, + bool bDynamicArrayMaster = false); void createSharedFormulaMapEntry( const ScAddress& rAddress, sal_Int32 nSharedId, const OUString& rTokens ); @@ -119,6 +172,6 @@ public: void addDataTable(const ScRange& rRange) { maDataTables.push_back(rRange); } }; -} +} // namespace oox::xls /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/inc/formulaparser.hxx b/sc/source/filter/inc/formulaparser.hxx index d03dec52bbd9..c5eb1f41cc4c 100644 --- a/sc/source/filter/inc/formulaparser.hxx +++ b/sc/source/filter/inc/formulaparser.hxx @@ -129,6 +129,10 @@ public: /** Converts the passed formula to a macro name for a drawing shape. */ OUString importMacroName( std::u16string_view aFormulaString ); + /** Extracts the external link URL and defined-name of an external reference */ + bool importMacroExternalRef(std::u16string_view aFormulaString, OUString& rUrl, + OUString& rName); + private: ::std::unique_ptr< FormulaParserImpl > mxImpl; }; diff --git a/sc/source/filter/inc/htmlpars.hxx b/sc/source/filter/inc/htmlpars.hxx index ca6dcd7dff2e..0d8ae17aa339 100644 --- a/sc/source/filter/inc/htmlpars.hxx +++ b/sc/source/filter/inc/htmlpars.hxx @@ -103,7 +103,7 @@ struct ScHTMLTableStackEntry ScRangeListRef xLockedList; std::shared_ptr xCellEntry; std::shared_ptr xLocalColOffset; - sal_uLong nFirstTableCell; + size_t nFirstTableCell; SCROW nRowCnt; SCCOL nColCntStart; SCCOL nMaxCol; @@ -114,7 +114,7 @@ struct ScHTMLTableStackEntry bool bFirstRow; ScHTMLTableStackEntry( std::shared_ptr xE, ScRangeListRef xL, std::shared_ptr xTO, - sal_uLong nFTC, + size_t nFTC, SCROW nRow, SCCOL nStart, SCCOL nMax, sal_uInt16 nTab, sal_uInt16 nTW, sal_uInt16 nCO, sal_uInt16 nCOS, @@ -162,7 +162,7 @@ private: std::unique_ptr pTables; ScHTMLColOffset maColOffset; std::shared_ptr xLocalColOffset; // per table - sal_uLong nFirstTableCell; // per table + size_t nFirstTableCell; // per table short nTableLevel; sal_uInt16 nTable; sal_uInt16 nMaxTable; @@ -176,6 +176,7 @@ private: bool bTabInTabCell:1; bool bInCell:1; bool bInTitle:1; + bool bInImg:1; DECL_LINK( HTMLImportHdl, HtmlImportInfo&, void ); void NewActEntry( const ScEEParseEntry* ); diff --git a/sc/source/filter/inc/imp_op.hxx b/sc/source/filter/inc/imp_op.hxx index 398ae11827b0..ed2f3565d6be 100644 --- a/sc/source/filter/inc/imp_op.hxx +++ b/sc/source/filter/inc/imp_op.hxx @@ -42,7 +42,7 @@ struct XclAddress; class ImportTyp { protected: - rtl_TextEncoding eQuellChar; // source (Quelle) character set + rtl_TextEncoding eSrcEncoding; // source encoding ScDocument& rD; // document public: diff --git a/sc/source/filter/inc/lotattr.hxx b/sc/source/filter/inc/lotattr.hxx index 94c88b733b6e..89919339b15c 100644 --- a/sc/source/filter/inc/lotattr.hxx +++ b/sc/source/filter/inc/lotattr.hxx @@ -23,6 +23,7 @@ #include #include +#include class ScPatternAttr; class SvxColorItem; @@ -106,7 +107,7 @@ private: struct ENTRY { - const ScPatternAttr* pPattAttr; + CellAttributeHolder pPattAttr; SCROW nFirstRow; SCROW nLastRow; }; diff --git a/sc/source/filter/inc/patterncache.hxx b/sc/source/filter/inc/patterncache.hxx index 25013a930143..895d768402f8 100644 --- a/sc/source/filter/inc/patterncache.hxx +++ b/sc/source/filter/inc/patterncache.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include class ScPatternAttr; @@ -30,7 +31,7 @@ class ScPatternCache { sal_Int32 nXfId; sal_Int32 nNumFmtId; - ScPatternAttr* pPattern; + CellAttributeHolder pPattern; Entry(); }; diff --git a/sc/source/filter/inc/personsfragment.hxx b/sc/source/filter/inc/personsfragment.hxx new file mode 100644 index 000000000000..7268644a9548 --- /dev/null +++ b/sc/source/filter/inc/personsfragment.hxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include "excelhandlers.hxx" + +namespace oox::xls +{ +/** Fragment handler for the persons part (xl/persons/person.xml). + Imports person metadata for threaded comments ([MS-XLSX] section 2.1.19). */ +class PersonsFragment final : public WorkbookFragmentBase +{ +public: + explicit PersonsFragment(const WorkbookHelper& rHelper, const OUString& rFragmentPath); + +private: + virtual oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; +}; + +} // namespace oox::xls + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/filter/inc/querytablebuffer.hxx b/sc/source/filter/inc/querytablebuffer.hxx index 16410ec8cfea..a511a7e3b9f8 100644 --- a/sc/source/filter/inc/querytablebuffer.hxx +++ b/sc/source/filter/inc/querytablebuffer.hxx @@ -58,6 +58,9 @@ public: /** Inserts a web query into the sheet. */ void finalizeImport(); + /** Returns the query table model data. */ + const QueryTableModel& getModel() const { return maModel; } + private: QueryTableModel maModel; }; diff --git a/sc/source/filter/inc/richstring.hxx b/sc/source/filter/inc/richstring.hxx index 3969de6b7974..855b2363be8a 100644 --- a/sc/source/filter/inc/richstring.hxx +++ b/sc/source/filter/inc/richstring.hxx @@ -235,14 +235,12 @@ public: @param rxText The XText interface of the target object. */ void convert( const css::uno::Reference< css::text::XText >& rxText ); - std::unique_ptr convert( ScEditEngineDefaulter& rEE, const oox::xls::Font* pFont ); + EditTextObject convert( ScEditEngineDefaulter& rEE, const oox::xls::Font* pFont ); RichStringPortion& getPortion(sal_Int32 nPortionIdx) { return maTextPortions[nPortionIdx]; } void setAttributes(const AttributeList& rAttribs); - bool isPreserveSpace() const { return mbPreserveSpace; } - private: /** Creates, appends, and returns a new empty string portion. */ sal_Int32 createPortion(); diff --git a/sc/source/filter/inc/sheetdatacontext.hxx b/sc/source/filter/inc/sheetdatacontext.hxx index b413e3d921b1..1bababfcb344 100644 --- a/sc/source/filter/inc/sheetdatacontext.hxx +++ b/sc/source/filter/inc/sheetdatacontext.hxx @@ -114,6 +114,8 @@ private: BinAddress maCurrPos; /// Current cell position (BIFF12 only). bool mbHasFormula; /// True = current cell has formula data (OOXML only). bool mbValidRange; /// True = maFmlaData.maFormulaRef is valid (OOXML only). + bool mbCalcAlways; /// True = formula has ca="1" (often a matrix-reference placeholder). + bool mbCellMetadata = false; /// True = cell has cm="1" (dynamic array master). sal_Int32 mnRow; /// row index (0-based) sal_Int32 mnCol; /// column index (0-based) diff --git a/sc/source/filter/inc/stylesbuffer.hxx b/sc/source/filter/inc/stylesbuffer.hxx index eab4d05d138a..0e003fedfe6c 100644 --- a/sc/source/filter/inc/stylesbuffer.hxx +++ b/sc/source/filter/inc/stylesbuffer.hxx @@ -152,7 +152,7 @@ struct FontModel bool mbItalic; /// True = italic characters. bool mbStrikeout; /// True = Strike out characters. bool mbOutline; /// True = outlined characters. - bool mbShadow; /// True = shadowed chgaracters. + bool mbShadow; /// True = shadowed characters. explicit FontModel(); @@ -205,7 +205,7 @@ struct ApiFontData sal_Int16 mnEscapement; /// Escapement style. sal_Int8 mnEscapeHeight; /// Escapement font height. bool mbOutline; /// True = outlined characters. - bool mbShadow; /// True = shadowed chgaracters. + bool mbShadow; /// True = shadowed characters. explicit ApiFontData(); }; @@ -218,8 +218,6 @@ public: /** Sets font formatting attributes for the passed element. */ void importAttribs( sal_Int32 nElement, const AttributeList& rAttribs ); - /** Sets font formatting attributes for OOXML default table styles. */ - void setFontElements( const XlsColor& rColor, bool bWeight ); /** Imports the FONT record from the passed stream. */ void importFont( SequenceInputStream& rStrm ); @@ -341,6 +339,9 @@ private: ApiAlignmentData maApiData; /// Alignment data converted to API constants. }; +// tdf#122473 - import alignment and axis-based pivot area formats +typedef std::shared_ptr AlignmentRef; + /** Contains all XML cell protection attributes, e.g. from a protection element. */ struct ProtectionModel { @@ -474,9 +475,6 @@ public: /** Imports a border from a DXF record from the passed stream. */ void importDxfBorder( sal_Int32 nElement, SequenceInputStream& rStrm ); - // for OOXML default table styles - void setBorderElement(sal_Int32 nElement, const XlsColor& rColor, sal_Int32 nStyle); - /** Final processing after import of all style settings. */ void finalizeImport( bool bRTL ); @@ -588,9 +586,6 @@ public: /** Imports gradient stop settings from a DXF record. */ void importDxfStop( SequenceInputStream& rStrm ); - // for dealing with OOXML default table styles - void setFillColors(const XlsColor& rFgColor, const XlsColor& rBgColor); - /** Final processing after import of all style settings. */ void finalizeImport(); @@ -713,14 +708,11 @@ public: BorderRef const & createBorder( bool bAlwaysNew = true ); /** Creates a new empty fill object. */ FillRef const & createFill( bool bAlwaysNew = true ); + /** Creates a new empty alignment object. */ + AlignmentRef const& createAlignment(bool bAlwaysNew = true); /** Creates a new empty protection object. */ ProtectionRef const & createProtection( bool bAlwaysNew = true ); - // methods for OOXML default table style import - void setFill(const FillRef& xFill); - void setBorder(const BorderRef& xBorder); - void setFont(const FontRef& xFont); - /** Inserts a new number format code. */ void importNumFmt( const AttributeList& rAttribs ); @@ -869,12 +861,8 @@ public: explicit TableStyle( const WorkbookHelper& rHelper, bool bDefaultOOXMLStyle ); void setName(const OUString& rName); - void setUIName(const OUString& rName); void importTableStyleElement(const AttributeList& rAttribs); void finalizeImport(const DxfVector& mrDxfs); - - // for OOXML default table styles - void setTableStyleElement(ScTableStyleElement eTableStyleElement, sal_Int32 nDxfId); }; typedef std::shared_ptr< TableStyle > TableStyleRef; diff --git a/sc/source/filter/inc/tablecolumnsbuffer.hxx b/sc/source/filter/inc/tablecolumnsbuffer.hxx index 8abc3915afb6..4c8cbd2b86ce 100644 --- a/sc/source/filter/inc/tablecolumnsbuffer.hxx +++ b/sc/source/filter/inc/tablecolumnsbuffer.hxx @@ -81,7 +81,7 @@ public: TableColumn& createTableColumn(); /** Applies the columns to the passed database range. */ - bool finalizeImport( ScDBData* pDBData ); + bool finalizeImport( ScDBData* pDBData, bool bQueryTable ); private: typedef RefVector< TableColumn > TableColumnVector; @@ -99,7 +99,7 @@ public: TableColumns& createTableColumns(); /** Applies the table columns to the passed database range. */ - void finalizeImport( ScDBData* pDBData ); + void finalizeImport( ScDBData* pDBData, bool bQueryTable ); private: /** Returns the table columns object used. */ diff --git a/sc/source/filter/inc/threadedcommentsfragment.hxx b/sc/source/filter/inc/threadedcommentsfragment.hxx new file mode 100644 index 000000000000..dd2d74e570ba --- /dev/null +++ b/sc/source/filter/inc/threadedcommentsfragment.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include "excelhandlers.hxx" + +#include + +namespace oox::xls +{ +/** Intermediate model for a single threadedComment element during import. */ +struct ThreadedCommentImportEntry +{ + OUString maRef; /// Cell reference (e.g. "A2"). + OUString maId; /// Unique GUID. + OUString maPersonId; /// Person GUID. + OUString maDateTime; /// xsd:dateTime. + OUString maParentId; /// Parent GUID (empty = root). + bool mbDone = false; /// Resolved flag. + OUString maText; /// Plain text content. +}; + +/** Fragment handler for the threaded-comments part + (xl/threadedComments/threadedComment*.xml). + Imports threaded comment data and attaches it to existing ScPostIt notes + ([MS-XLSX] section 2.1.20). */ +class ThreadedCommentsFragment final : public WorksheetFragmentBase +{ +public: + explicit ThreadedCommentsFragment(const WorksheetHelper& rHelper, + const OUString& rFragmentPath); + +private: + virtual oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; + virtual void onCharacters(const OUString& rChars) override; + virtual void onEndElement() override; + + /** Attaches collected threaded comment data to existing ScPostIt notes. */ + void attachToNotes(); + + std::vector maEntries; + ThreadedCommentImportEntry* mpCurrentEntry = nullptr; +}; + +} // namespace oox::xls + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/filter/inc/tokstack.hxx b/sc/source/filter/inc/tokstack.hxx index 2e84fc068c31..9a8ac178231f 100644 --- a/sc/source/filter/inc/tokstack.hxx +++ b/sc/source/filter/inc/tokstack.hxx @@ -208,7 +208,6 @@ private: sal_uInt16 m_nRek; // recursion counter #endif - bool GrowTripel( sal_uInt16 nByMin ); bool GrowId(); bool GrowMatrix(); /** @return false means nElementCurrent range diff --git a/sc/source/filter/inc/worksheethelper.hxx b/sc/source/filter/inc/worksheethelper.hxx index 364522b5e056..67a1bc2c692e 100644 --- a/sc/source/filter/inc/worksheethelper.hxx +++ b/sc/source/filter/inc/worksheethelper.hxx @@ -38,6 +38,8 @@ namespace com::sun::star { namespace table { class XCellRange; } } +namespace oox::xls::nsv { struct NamedSheetViewData; } + namespace oox::xls { class AutoFilterBuffer; @@ -218,6 +220,9 @@ public: ExtLst& getExtLst() const; + /** Sets the named sheet views data for this sheet. */ + void setNamedSheetViews(std::vector&& rData); + /** Sets a column or row page break described in the passed struct. */ void setPageBreak( const PageBreakModel& rModel, bool bRowBreak ); /** Inserts the hyperlink URL into the spreadsheet. */ @@ -228,6 +233,8 @@ public: void setDrawingPath( const OUString& rDrawingPath ); /** Sets the path to the legacy VML drawing fragment of this sheet. */ void setVmlDrawingPath( const OUString& rVmlDrawingPath ); + /** Sets the path to the threaded comments fragment of this sheet. */ + void setThreadedCommentsPath( const OUString& rPath ); /** Extends the used area of this sheet by the passed cell position. */ void extendUsedArea( const ScAddress& rAddress ); @@ -274,13 +281,20 @@ public: /** Final import of drawing objects. Has to be called after all content has been imported */ void finalizeDrawingImport(); - void setCellFormula( const ScAddress& rTokenAddress, const OUString& ); + /** Finalizes the import of named sheet views, by creating the sheet views from the data. */ + void finalizeNamedSheetViews(); + + void setCellFormula( const ScAddress& rTokenAddress, const OUString&, + bool bDynamicArrayMaster = false ); void setCellFormula( const ScAddress& rAddr, sal_Int32 nSharedId, - const OUString& rCellValue, sal_Int32 nValueType ); + const OUString& rCellValue, sal_Int32 nValueType, + bool bDynamicArrayMaster = false ); - void setCellArrayFormula( const ScRange& rRangeAddress, const ScAddress& rTokenAddress, const OUString& rTokenStr ); + void setCellArrayFormula(const ScRange& rRangeAddress, const ScAddress& rTokenAddress, + const OUString& rTokenStr, bool bCachedSpill = false, + bool bDynamicArrayMaster = false); void createSharedFormulaMapEntry( const ScAddress& rAddress, diff --git a/sc/source/filter/inc/xcl97rec.hxx b/sc/source/filter/inc/xcl97rec.hxx index 27a7b4261af5..ff9f7c54bfee 100644 --- a/sc/source/filter/inc/xcl97rec.hxx +++ b/sc/source/filter/inc/xcl97rec.hxx @@ -27,6 +27,7 @@ #include #include +class XclExpImgData; class XclObj; class XclExpMsoDrawing; class SdrCaptionObj; @@ -44,6 +45,8 @@ public: virtual bool isExternalURL(const OUString& rURL) const override; + virtual sal_Int32 getExternalLinkIndex(const OUString& rUrl) const override; + private: ScDocument& mrDoc; }; @@ -75,7 +78,7 @@ public: iterator end () { return maObjs.end(); } XclExpMsoDrawing* GetMsodrawingPerSheet() { return pMsodrawingPerSheet.get(); } - + void SetImageData(std::unique_ptr pImgData); /// close groups and DgContainer opened in ctor void EndSheet(); @@ -88,6 +91,7 @@ private: XclEscherEx& mrEscherEx; std::unique_ptr pMsodrawingPerSheet; std::unique_ptr pSolverContainer; + std::unique_ptr m_pImgData; std::vector> maObjs; }; @@ -178,7 +182,7 @@ class XclObjComment : public XclObj public: XclObjComment( XclExpObjectManager& rObjMgr, - const tools::Rectangle& rRect, const EditTextObject& rEditObj, SdrCaptionObj* pCaption, bool bVisible, const ScAddress& rAddress, const tools::Rectangle &rFrom, const tools::Rectangle &To ); + const tools::Rectangle& rRect, const EditTextObject* pEditObj, SdrCaptionObj* pCaption, bool bVisible, const ScAddress& rAddress, const tools::Rectangle &rFrom, const tools::Rectangle &To ); virtual ~XclObjComment() override; /** c'tor process for formatted text objects above . @@ -259,8 +263,7 @@ protected: public: XclObjAny( XclExpObjectManager& rObjMgr, - const css::uno::Reference< css::drawing::XShape >& rShape, - ScDocument* pDoc); + const css::uno::Reference< css::drawing::XShape >& rShape, ScDocument* pDoc); virtual ~XclObjAny() override; const css::uno::Reference< css::drawing::XShape >& diff --git a/sc/source/filter/inc/xedbdata.hxx b/sc/source/filter/inc/xedbdata.hxx index a7fddfe04eaa..b72e20595af9 100644 --- a/sc/source/filter/inc/xedbdata.hxx +++ b/sc/source/filter/inc/xedbdata.hxx @@ -63,4 +63,44 @@ private: TablesMapType maTablesMap; }; +namespace oox::xls { struct QueryTableModel; } + +class XclExpQueryTables : public XclExpRecordBase, protected XclExpRoot +{ +public: + explicit XclExpQueryTables( const XclExpRoot& rRoot ); + virtual ~XclExpQueryTables() override; + + void AppendQueryTable( std::shared_ptr pModel, sal_Int32 nQueryTableId ); + + virtual void SaveXml( XclExpXmlStream& rStrm ) override; + +private: + struct Entry + { + std::shared_ptr mpModel; + sal_Int32 mnQueryTableId; + + Entry( std::shared_ptr pModel, sal_Int32 nId ); + }; + + std::vector maQueryTables; + + static void SaveQueryTableXml( XclExpXmlStream& rStrm, const Entry& rEntry ); +}; + +class XclExpQueryTablesManager : protected XclExpRoot +{ +public: + explicit XclExpQueryTablesManager( const XclExpRoot& rRoot ); + virtual ~XclExpQueryTablesManager() override; + + void Initialize(); + rtl::Reference< XclExpQueryTables > GetQueryTablesBySheet( SCTAB nTab ); + +private: + typedef ::std::map< SCTAB, rtl::Reference< XclExpQueryTables > > QueryTablesMapType; + QueryTablesMapType maQueryTablesMap; +}; + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/inc/xeescher.hxx b/sc/source/filter/inc/xeescher.hxx index e0753f333536..afe30fa45611 100644 --- a/sc/source/filter/inc/xeescher.hxx +++ b/sc/source/filter/inc/xeescher.hxx @@ -161,7 +161,7 @@ private: sal_uInt16 mnRecId; /// Record identifier for the IMGDATA record. }; -/** Helper class for form controls to manage spreadsheet links . */ +/** Helper class for form controls to manage spreadsheet links. */ class XclExpControlHelper : protected XclExpRoot { public: @@ -276,8 +276,10 @@ private: void WriteCellLinkSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId ); /** Writes the ftSbs sub structure containing scrollbar data. */ void WriteSbs( XclExpStream& rStrm ); - /** Writes an anchor, if empty calculates one form XShape */ + /** Writes an anchor, if empty calculates one from XShape */ void WriteAnchor( const sax_fastparser::FSHelperPtr& rTarget, bool bIsDrawing ) const; + /** Writes the label's run properties, the DrawingML half of the label font. */ + void WriteLabelFont(const sax_fastparser::FSHelperPtr& rTarget) const; private: const css::uno::Reference< css::drawing::XShape > mxShape; @@ -298,6 +300,7 @@ private: bool mbScrollHor; /// Scrollbar: true = horizontal. bool mbPrint; bool mbVisible; + bool mbStroked; OUString msCtrlName; OUString msLabel; sal_Int32 mnShapeId; @@ -305,6 +308,10 @@ private: tools::Rectangle maAreaTo; XclExpObjectManager& mrRoot; std::optional<::Color> moBackgroundFill; + XclFontData maFontData; /// Font of the control label. + sal_uInt16 mnXclFont = EXC_FONT_APP; /// Font record index of the control label. + sal_uInt8 mnTextHAlign = EXC_OBJ_HOR_LEFT; /// Horizontal alignment of the control label. + sal_uInt8 mnTextVAlign = EXC_OBJ_VER_CENTER; /// Vertical alignment of the control label. }; //#endif @@ -388,18 +395,22 @@ private: tools::Rectangle maCommentTo; /// To and To Offsets /// map authors to remove personal info std::unique_ptr mpAuthorIDs; + OUString maThreadedCommentGuid; /// Threaded comment GUID (for linking legacy comment) }; class XclExpComments : public XclExpRecord { public: - XclExpComments( SCTAB nTab, XclExpRecordList< XclExpNote >& rNotes ); + XclExpComments(SCTAB nTab, XclExpRecordList& rNotes, ScDocument& rDoc); virtual void SaveXml( XclExpXmlStream& rStrm ) override; private: + void SaveThreadedCommentsXml(XclExpXmlStream& rStrm); + SCTAB mnTab; XclExpRecordList< XclExpNote >& mrNotes; + ScDocument& mrDoc; }; // object manager ============================================================= @@ -411,7 +422,7 @@ public: virtual ~XclExpObjectManager() override; /** Creates a new DFF client anchor object. Caller takes ownership! May be - overwritten in derived classes. */ + overwritten in derived classes. */ virtual XclExpDffAnchorBase* CreateDffAnchor() const; /** Creates and returns the MSODRAWINGGROUP record containing global DFF @@ -423,7 +434,7 @@ public: /** Processes a drawing page and returns the record block containing all related records (MSODRAWING, OBJ, TXO, charts, etc.). */ - rtl::Reference< XclExpRecordBase > ProcessDrawing( const SdrPage* pSdrPage ); + rtl::Reference< XclExpRecordBase > ProcessDrawing( const SdrPage* pSdrPage, std::unique_ptr pImgData = nullptr); /** Processes a collection of UNO shapes and returns the record block containing all related records (MSODRAWING, OBJ, TXO, charts, etc.). */ rtl::Reference< XclExpRecordBase > ProcessDrawing( const css::uno::Reference< css::drawing::XShapes >& rxShapes ); diff --git a/sc/source/filter/inc/xelink.hxx b/sc/source/filter/inc/xelink.hxx index b975bc4d15dc..fb3f294b5b06 100644 --- a/sc/source/filter/inc/xelink.hxx +++ b/sc/source/filter/inc/xelink.hxx @@ -219,6 +219,8 @@ public: /** Writes the entire Link table to OOXML. */ virtual void SaveXml( XclExpXmlStream& rStrm ) override; + const std::unordered_map& GetTruncatedSheetMap(sal_uInt16 nFileId) const; + private: typedef std::shared_ptr< XclExpLinkManagerImpl > XclExpLinkMgrImplPtr; XclExpLinkMgrImplPtr mxImpl; diff --git a/sc/source/filter/inc/xepivotxml.hxx b/sc/source/filter/inc/xepivotxml.hxx index 5e02ba214b78..647f916804cd 100644 --- a/sc/source/filter/inc/xepivotxml.hxx +++ b/sc/source/filter/inc/xepivotxml.hxx @@ -66,7 +66,8 @@ public: private: void SavePivotTableXml(XclExpXmlStream& rStrm, const ScDPObject& rObj, sal_Int32 nCacheId); - void savePivotTableFormats(XclExpXmlStream& rStrm, ScDPObject const& rDPObject); + void savePivotTableFormats(XclExpXmlStream& rStrm, ScDPObject const& rDPObject, + size_t nFieldCount); }; class XclExpXmlPivotTableManager : protected XclExpRoot diff --git a/sc/source/filter/inc/xeroot.hxx b/sc/source/filter/inc/xeroot.hxx index c604e403a1aa..7dfe576936d5 100644 --- a/sc/source/filter/inc/xeroot.hxx +++ b/sc/source/filter/inc/xeroot.hxx @@ -54,6 +54,7 @@ class XclExpDxfs; class XclExpXmlTableStyles; class XclExpXmlPivotTableManager; class XclExpTablesManager; +class XclExpQueryTablesManager; namespace sc { class CompileFormulaContext; } /** Stores global buffers and data needed for Excel export filter. */ @@ -98,6 +99,7 @@ struct XclExpRootData : public XclRootData std::shared_ptr mxXmlPTableMgr; std::shared_ptr mxTablesMgr; + std::shared_ptr mxQueryTablesMgr; std::shared_ptr mpCompileFormulaCxt; ScCompiler::OpCodeMapPtr mxOpCodeMap; /// mapping between op-codes and names @@ -163,6 +165,7 @@ public: XclExpXmlPivotTableManager& GetXmlPivotTableManager(); XclExpTablesManager& GetTablesManager(); + XclExpQueryTablesManager& GetQueryTablesManager(); /** Is called when export filter starts to create the Excel document (all BIFF versions). */ void InitializeConvert(); diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx index cb2671b385a8..2da0692e9039 100644 --- a/sc/source/filter/inc/xestream.hxx +++ b/sc/source/filter/inc/xestream.hxx @@ -36,6 +36,7 @@ #include namespace com::sun::star::beans { struct NamedValue; } +namespace oox::drawingml { class ShapeExport; } /* ============================================================================ Output stream class for Excel export @@ -327,6 +328,13 @@ public: virtual oox::drawingml::table::TableStyleListPtr getTableStyles() override; virtual oox::drawingml::chart::ChartConverter* getChartConverter() override; + static OUString GenerateUniqueTableName(const std::u16string_view& rOriginalName, const std::vector& aNewTabNames, const std::vector& aOriginalTabNames); + sal_Int32 getAndIncrementDiagramId() { maDiagramId++; return maDiagramId; }; + + /// Set when a dynamic array master cell is emitted. + void NoteDynamicArrayFormula() { mbHasDynamicArrayFormula = true; } + bool HasDynamicArrayFormula() const { return mbHasDynamicArrayFormula; } + private: virtual ::oox::ole::VbaProject* implCreateVbaProject() const override; virtual OUString SAL_CALL getImplementationName() override; @@ -354,8 +362,12 @@ private: std::stack< sax_fastparser::FSHelperPtr > maStreams; XclExpXmlPathToStateMap maOpenedStreamMap; + std::unique_ptr mpShapeExport; + sal_Int32 maDiagramId; + bool mbExportVBA; bool mbExportTemplate; + bool mbHasDynamicArrayFormula = false; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/inc/xestyle.hxx b/sc/source/filter/inc/xestyle.hxx index a564b2006eb1..db87a8822e87 100644 --- a/sc/source/filter/inc/xestyle.hxx +++ b/sc/source/filter/inc/xestyle.hxx @@ -348,12 +348,21 @@ struct XclExpCellBorder : public XclCellBorder sal_uInt32 mnTopColorId; /// Color ID for top line. sal_uInt32 mnBottomColorId; /// Color ID for bottom line. sal_uInt32 mnDiagColorId; /// Color ID for diagonal line(s). + sal_uInt32 mnVertColorId; /// Color ID for inner vertical line. + sal_uInt32 mnHorzColorId; /// Color ID for inner horizontal line. model::ComplexColor maComplexColorLeft; model::ComplexColor maComplexColorRight; model::ComplexColor maComplexColorTop; model::ComplexColor maComplexColorBottom; model::ComplexColor maComplexColorDiagonal; + model::ComplexColor maComplexColorVertical; /// Complex color for inner vertical line. + model::ComplexColor maComplexColorHorizontal; /// Complex color for inner horizontal line. + + sal_uInt16 mnVertColor; /// Palette index for inner vertical line. + sal_uInt16 mnHorzColor; /// Palette index for inner horizontal line. + sal_uInt8 mnVertLine; /// Style of inner vertical line. + sal_uInt8 mnHorzLine; /// Style of inner horizontal line. explicit XclExpCellBorder(); @@ -373,7 +382,8 @@ struct XclExpCellBorder : public XclCellBorder /** Fills the data to the passed fields of a BIFF8 CF (conditional format) record. */ void FillToCF8( sal_uInt16& rnLine, sal_uInt32& rnColor ) const; - void SaveXml( XclExpXmlStream& rStrm ) const; + /// bDxf: omit unset border sides (dxf) instead of writing them as empty elements. + void SaveXml( XclExpXmlStream& rStrm, bool bDxf = false ) const; }; /** Extends the XclCellArea struct for export. diff --git a/sc/source/filter/inc/xichart.hxx b/sc/source/filter/inc/xichart.hxx index a4edbba1881d..8c4c853cd009 100644 --- a/sc/source/filter/inc/xichart.hxx +++ b/sc/source/filter/inc/xichart.hxx @@ -787,7 +787,7 @@ public: /** Sets a data point or series format (CHDATAFORMAT group) for this series. */ void SetDataFormat( const XclImpChDataFormatRef& xDataFmt ); - /** Sets a label text (CHTEXT group) attached to a series or data point. */ + /** Sets a label text (CHTEXT group) attached to a series or data point. */ void SetDataLabel(const XclImpChTextRef& xLabel); /** Adds error bar settings from the passed series to the own series. */ void AddChildSeries( const XclImpChSeries& rSeries ); @@ -1312,7 +1312,7 @@ public: XclImpChTypeGroupRef GetTypeGroup( sal_uInt16 nGroupIdx ) const; /** Returns the specified default text. */ const XclImpChText* GetDefaultText( XclChTextType eTextType ) const; - /** Returns true, if the plot area has benn moved and/or resized manually. */ + /** Returns true, if the plot area has been moved and/or resized manually. */ bool IsManualPlotArea() const; /** Returns the number of units on the progress bar needed for the chart. */ static std::size_t GetProgressSize() { return 2 * EXC_CHART_PROGRESS_SIZE; } diff --git a/sc/source/filter/inc/xihelper.hxx b/sc/source/filter/inc/xihelper.hxx index a359ed3bdd92..7f3c0e901790 100644 --- a/sc/source/filter/inc/xihelper.hxx +++ b/sc/source/filter/inc/xihelper.hxx @@ -120,7 +120,7 @@ public: XclImpStringHelper() = delete; /** Returns a new edit engine text object. @param nXFIndex Index to XF for first text portion (for escapement). */ - static std::unique_ptr CreateTextObject( + static std::optional CreateTextObject( const XclImpRoot& rRoot, const XclImpString& rString ); @@ -268,24 +268,27 @@ public: @param rUrl Returns the decoded file name incl. path. @param rTabName Returns the decoded sheet name. @param rbSameWb Returns true, if the URL is a reference to the own workbook. - @param rEncodedUrl An encoded URL from Excel. */ + @param rEncodedUrl An encoded URL from Excel. + @param pbXlStartup If non-null, returns true if the path is relative to XLSTART folder. */ static void DecodeUrl( OUString& rUrl, OUString& rTabName, bool& rbSameWb, const XclImpRoot& rRoot, - const OUString& rEncodedUrl ); + const OUString& rEncodedUrl, + bool* pbXlStartup = nullptr ); /** Decodes an encoded external document URL without sheet name. @param rUrl Returns the decoded file name incl. path. @param rbSameWb Returns true, if the URL is a reference to the own workbook. - @param rEncodedUrl An encoded URL from Excel. */ - + @param rEncodedUrl An encoded URL from Excel. + @param pbXlStartup If non-null, returns true if the path is relative to XLSTART folder. */ static void DecodeUrl( OUString& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, - const OUString& rEncodedUrl ); + const OUString& rEncodedUrl, + bool* pbXlStartup = nullptr ); /** Decodes the passed URL to OLE or DDE link components. @descr For DDE links: Decodes to application name and topic. diff --git a/sc/source/filter/inc/xilink.hxx b/sc/source/filter/inc/xilink.hxx index 686f928ff1c6..83eb38d9101f 100644 --- a/sc/source/filter/inc/xilink.hxx +++ b/sc/source/filter/inc/xilink.hxx @@ -210,6 +210,8 @@ public: const OUString* GetSupbookUrl( sal_uInt16 nXtiIndex ) const; + bool IsSupbookXlStartup( sal_uInt16 nXtiIndex ) const; + OUString GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const; /** Tries to decode the URL of the specified XTI entry to OLE or DDE link components. diff --git a/sc/source/filter/inc/xlconst.hxx b/sc/source/filter/inc/xlconst.hxx index e9d791d08e50..dadb1867f46e 100644 --- a/sc/source/filter/inc/xlconst.hxx +++ b/sc/source/filter/inc/xlconst.hxx @@ -95,6 +95,7 @@ const sal_Unicode EXC_URL_DRIVEROOT = '\x02'; /// Root directory of cu const sal_Unicode EXC_URL_SUBDIR = '\x03'; /// Directory name delimiter. const sal_Unicode EXC_URL_PARENTDIR = '\x04'; /// Parent directory. const sal_Unicode EXC_URL_RAW = '\x05'; /// Unencoded URL. +const sal_Unicode EXC_URL_XLSTART = '\x06'; /// XLSTART folder path. const sal_Unicode EXC_URL_SHEETNAME = '\x09'; /// Sheet name starts here (BIFF4). const sal_Unicode EXC_DDE_DELIM = '\x03'; /// DDE application-topic delimiter @@ -108,6 +109,7 @@ const sal_uInt8 EXC_ERR_REF = 0x17; const sal_uInt8 EXC_ERR_NAME = 0x1D; const sal_uInt8 EXC_ERR_NUM = 0x24; const sal_uInt8 EXC_ERR_NA = 0x2A; +const sal_uInt8 EXC_ERR_SPILL = 0x2B; // Cached values list (EXTERNNAME, ptgArray, ...) ----------------------------- diff --git a/sc/source/filter/inc/xlstyle.hxx b/sc/source/filter/inc/xlstyle.hxx index 2385b00136af..bcfd47ac13cb 100644 --- a/sc/source/filter/inc/xlstyle.hxx +++ b/sc/source/filter/inc/xlstyle.hxx @@ -572,7 +572,7 @@ public: /** Sets all "attribute used" flags to the passed state. */ void SetAllUsedFlags( bool bUsed ); - /** Returns true, if any "attribute used" flags are ste in this XF. */ + /** Returns true, if any "attribute used" flags are set in this XF. */ bool HasUsedFlags() const; /** Returns true, if this is a hard cell format. */ diff --git a/sc/source/filter/lotus/lotattr.cxx b/sc/source/filter/lotus/lotattr.cxx index 410cac7ba242..058023bb890a 100644 --- a/sc/source/filter/lotus/lotattr.cxx +++ b/sc/source/filter/lotus/lotattr.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include #include #include @@ -171,7 +172,7 @@ const SvxColorItem& LotAttrCache::GetColorItem( const sal_uInt8 nLotIndex ) cons const Color& LotAttrCache::GetColor( const sal_uInt8 nLotIndex ) const { // color <-> index fits background, but not for fonts (0 <-> 7)! - // *LotAttrCache::GetColor(): Index > 7, caller hast to check index!" + // *LotAttrCache::GetColor(): Index > 7, caller has to check index! assert( nLotIndex < 8 ); return pColTab[ nLotIndex ]; @@ -187,13 +188,13 @@ void LotAttrCol::SetAttr( const ScDocument* pDoc, const SCROW nRow, const ScPatt if(iterLast != aEntries.rend()) { - if( ( (*iterLast)->nLastRow == nRow - 1 ) && ScPatternAttr::areSame( &rAttr, (*iterLast)->pPattAttr ) ) + if( ( (*iterLast)->nLastRow == nRow - 1 ) && ScPatternAttr::areSame( &rAttr, (*iterLast)->pPattAttr.getScPatternAttr() ) ) (*iterLast)->nLastRow = nRow; else { ENTRY *pCurrent = new ENTRY; - pCurrent->pPattAttr = &rAttr; + pCurrent->pPattAttr.setScPatternAttr(&rAttr); pCurrent->nFirstRow = pCurrent->nLastRow = nRow; aEntries.push_back(std::unique_ptr(pCurrent)); @@ -202,7 +203,7 @@ void LotAttrCol::SetAttr( const ScDocument* pDoc, const SCROW nRow, const ScPatt else { // first entry ENTRY *pCurrent = new ENTRY; - pCurrent->pPattAttr = &rAttr; + pCurrent->pPattAttr.setScPatternAttr(&rAttr); pCurrent->nFirstRow = pCurrent->nLastRow = nRow; aEntries.push_back(std::unique_ptr(pCurrent)); @@ -216,7 +217,7 @@ void LotAttrCol::Apply(LotusContext& rContext, const SCCOL nColNum, const SCTAB for (const auto& rxEntry : aEntries) { rDoc.ApplyPatternAreaTab(nColNum, rxEntry->nFirstRow, nColNum, rxEntry->nLastRow, - nTabNum, *(rxEntry->pPattAttr)); + nTabNum, *(rxEntry->pPattAttr.getScPatternAttr())); } } @@ -228,13 +229,16 @@ LotAttrTable::LotAttrTable(LotusContext& rContext): void LotAttrTable::SetAttr( const LotusContext& rContext, const SCCOL nColFirst, const SCCOL nColLast, const SCROW nRow, const LotAttrWK3& rAttr ) { - // With the current implementation of MAXCOLCOUNT>=1024 and nColFirst and - // nColLast being calculated as sal_uInt8+sal_uInt8 there's no chance that - // they would be invalid. + // nColFirst and nColLast are derived from the imported file. Clamp the + // range to keep the pCols index valid. + if (nColFirst > rContext.rDoc.MaxCol()) + return; + const SCCOL nClampedLast = std::min(nColLast, rContext.rDoc.MaxCol()); + const ScPatternAttr &rPattAttr = aAttrCache.GetPattAttr( rAttr ); SCCOL nColCnt; - for( nColCnt = nColFirst ; nColCnt <= nColLast ; nColCnt++ ) + for( nColCnt = nColFirst ; nColCnt <= nClampedLast ; nColCnt++ ) pCols[ nColCnt ].SetAttr( &rContext.rDoc, nRow, rPattAttr ); } diff --git a/sc/source/filter/lotus/lotimpop.cxx b/sc/source/filter/lotus/lotimpop.cxx index 593c4068fdb2..2e527273d2f7 100644 --- a/sc/source/filter/lotus/lotimpop.cxx +++ b/sc/source/filter/lotus/lotimpop.cxx @@ -163,7 +163,7 @@ void ImportLotus::Userrange() char aBuffer[ 17 ]; aBuffer[pIn->ReadBytes(aBuffer, 16)] = 0; - OUString aName(aBuffer, strlen(aBuffer), eQuellChar); + OUString aName(aBuffer, strlen(aBuffer), eSrcEncoding); Read(aScRange); @@ -311,7 +311,7 @@ void ImportLotus::Formulacell( sal_uInt16 n ) void ImportLotus::Read( OUString &r ) { - ScfTools::AppendCString( *pIn, r, eQuellChar ); + ScfTools::AppendCString( *pIn, r, eSrcEncoding ); } void ImportLotus::RowPresentation( sal_uInt16 nRecLen ) @@ -437,6 +437,9 @@ void ImportLotus::Row_( const sal_uInt16 nRecLen ) while( nCntDwn ) { + if (nColCnt > rContext.rDoc.MaxCol()) + break; + Read( aAttr ); Read( nRepeats ); diff --git a/sc/source/filter/oox/NamedSheetViewFragment.cxx b/sc/source/filter/oox/NamedSheetViewFragment.cxx new file mode 100644 index 000000000000..c839f64bec27 --- /dev/null +++ b/sc/source/filter/oox/NamedSheetViewFragment.cxx @@ -0,0 +1,208 @@ +/* -*- 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 + +#include +#include +#include +#include + +namespace oox::xls::nsv +{ +using namespace ::oox::core; + +FilterContext::FilterContext(WorksheetContextBase& rParent, FilterData& rFilterData) + : WorksheetContextBase(rParent) + , mrFilterData(rFilterData) +{ +} + +ContextHandlerRef FilterContext::onCreateContext(sal_Int32 nElement, + const AttributeList& /*rAttribs*/) +{ + switch (nElement) + { + case XLS_TOKEN(filters): + { + mrFilterData.mxSettings = std::make_shared(*this); + return new FilterSettingsContext(*this, *mrFilterData.mxSettings); + } + case XLS_TOKEN(top10): + { + mrFilterData.mxSettings = std::make_shared(*this); + return new FilterSettingsContext(*this, *mrFilterData.mxSettings); + } + case XLS_TOKEN(customFilters): + { + mrFilterData.mxSettings = std::make_shared(*this); + return new FilterSettingsContext(*this, *mrFilterData.mxSettings); + } + case XLS_TOKEN(colorFilter): + { + mrFilterData.mxSettings = std::make_shared(*this); + return new FilterSettingsContext(*this, *mrFilterData.mxSettings); + } + } + + return nullptr; +} + +ColumnFilterContext::ColumnFilterContext(WorksheetContextBase& rParent, + ColumnFilterData& rColumnFilterData) + : WorksheetContextBase(rParent) + , mrColumnFilterData(rColumnFilterData) +{ +} + +ContextHandlerRef ColumnFilterContext::onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) +{ + switch (nElement) + { + case XNSV_TOKEN(filter): + { + auto& rFilter = mrColumnFilterData.maFilters.emplace_back(); + rFilter.maColumnID = rAttribs.getInteger(XML_colId, 0); + return new FilterContext(*this, rFilter); + } + } + + return nullptr; +} + +SortRuleContext::SortRuleContext(WorksheetContextBase& rParent, SortRuleData& rSortRuleData) + : WorksheetContextBase(rParent) + , mrSortRuleData(rSortRuleData) +{ +} + +ContextHandlerRef SortRuleContext::onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) +{ + switch (nElement) + { + case XNSV_TOKEN(sortCondition): + case XLS14_TOKEN(sortCondition): + mrSortRuleData.maRef = rAttribs.getString(XML_ref, {}); // required + mrSortRuleData.mbDescending = rAttribs.getBool(XML_descending, false); // optional + mrSortRuleData.maSortBy = rAttribs.getToken(XML_sortBy, XML_value); // optional + return this; + } + + return nullptr; +} + +NsvFilterContext::NsvFilterContext(WorksheetContextBase& rParent, NsvFilterData& rNsvFilterData) + : WorksheetContextBase(rParent) + , mrNsvFilterData(rNsvFilterData) +{ +} + +ContextHandlerRef NsvFilterContext::onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) +{ + switch (nElement) + { + case XNSV_TOKEN(columnFilter): + { + auto& rColumnFilter = mrNsvFilterData.maColumnFilters.emplace_back(); + rColumnFilter.maColumnID = rAttribs.getInteger(XML_colId, 0); // required + rColumnFilter.maID = rAttribs.getString(XML_id, {}); // optional + return new ColumnFilterContext(*this, rColumnFilter); + } + case XNSV_TOKEN(sortRules): + { + mrNsvFilterData.maSortRules.emplace(); + mrNsvFilterData.maSortRules->mnMethod = rAttribs.getToken(XML_sortMethod, XML_none); + mrNsvFilterData.maSortRules->mbCaseSensitive + = rAttribs.getBool(XML_caseSensitive, false); + return this; + } + case XNSV_TOKEN(sortRule): + { + if (mrNsvFilterData.maSortRules) + { + auto& rSortRules = *mrNsvFilterData.maSortRules; + + auto& rSortRule = rSortRules.maRules.emplace_back(); + SAL_WARN_IF(rSortRules.maRules.size() > 64, "sc", + "Max number of sort rules according to schema is 64!"); + rSortRule.maColumnID = rAttribs.getInteger(XML_colId, 0); // required + rSortRule.maID = rAttribs.getString(XML_id, {}); // optional + return new SortRuleContext(*this, rSortRule); + } + } + } + + return nullptr; +} + +NamedSheetViewContext::NamedSheetViewContext(WorksheetFragmentBase& rParent, + NamedSheetViewData& rNamedSheetViewData) + : WorksheetContextBase(rParent) + , mrNamedSheetViewData(rNamedSheetViewData) +{ +} + +ContextHandlerRef NamedSheetViewContext::onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) +{ + switch (nElement) + { + case XNSV_TOKEN(nsvFilter): + { + auto& rNsvFilter = mrNamedSheetViewData.maNsvFilters.emplace_back(); + rNsvFilter.maFilterID = rAttribs.getString(XML_filterId, {}); + rNsvFilter.maRef = rAttribs.getString(XML_ref, {}); + rNsvFilter.maTableID = rAttribs.getInteger(XML_tableId); + return new NsvFilterContext(*this, rNsvFilter); + } + default: + break; + } + + return nullptr; +} + +NamedSheetViewFragment::NamedSheetViewFragment(WorksheetHelper const& rHelper, + OUString const& rFragmentPath) + : WorksheetFragmentBase(rHelper, rFragmentPath) +{ +} + +ContextHandlerRef NamedSheetViewFragment::onCreateContext(sal_Int32 nElement, + AttributeList const& rAttribs) +{ + switch (nElement) + { + case XNSV_TOKEN(namedSheetViews): + { + return this; + } + case XNSV_TOKEN(namedSheetView): + { + auto& rData = maNamedSheetViews.emplace_back(); + rData.maName = rAttribs.getString(XML_name, {}); + rData.maID = rAttribs.getString(XML_id, {}); + return new NamedSheetViewContext(*this, rData); + } + } + return nullptr; +} + +void NamedSheetViewFragment::finalizeImport() +{ + if (!maNamedSheetViews.empty()) + setNamedSheetViews(std::move(maNamedSheetViews)); +} + +} // namespace oox::xls::nsv + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/oox/NamedSheetViewImporter.cxx b/sc/source/filter/oox/NamedSheetViewImporter.cxx new file mode 100644 index 000000000000..70e20114e7e0 --- /dev/null +++ b/sc/source/filter/oox/NamedSheetViewImporter.cxx @@ -0,0 +1,183 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace oox::xls::nsv +{ +using namespace ::com::sun::star; + +NamedSheetViewImporter::NamedSheetViewImporter(const WorkbookHelper& rHelper, SCTAB nTab) + : WorkbookHelper(rHelper) + , mnTab(nTab) +{ +} + +void NamedSheetViewImporter::setNamedSheetViews(std::vector&& rData) +{ + maNamedSheetViews = std::move(rData); +} + +void NamedSheetViewImporter::finalizeImport() +{ + if (maNamedSheetViews.empty()) + return; + + ScDocument& rDoc = getScDocument(); + + for (const auto& rViewData : maNamedSheetViews) + { + auto[nSheetViewID, nViewTab] = rDoc.CreateNewSheetView(mnTab); + if (nSheetViewID == sc::InvalidSheetViewID) + continue; + + // Set the imported name on the sheet view + auto pSheetViewManager = rDoc.GetSheetViewManager(mnTab); + if (!pSheetViewManager) + continue; + + auto pSheetView = pSheetViewManager->get(nSheetViewID); + if (pSheetView) + { + pSheetView->SetName(rViewData.maName); + pSheetView->SetGUID(rViewData.maID.toUtf8()); + if (!rViewData.maNsvFilters.empty()) + pSheetView->SetFilterGUID(rViewData.maNsvFilters.front().maFilterID.toUtf8()); + } + + // Apply filters and sort for each nsvFilter + for (const auto& rNsvFilter : rViewData.maNsvFilters) + { + // Parse the filter range reference + ScRange aFilterRange; + if (rNsvFilter.maRef.isEmpty()) + continue; + + if (!getAddressConverter().convertToCellRange(aFilterRange, rNsvFilter.maRef, nViewTab, + true, true)) + continue; + + // Adjust the range to the view tab + aFilterRange.aStart.SetTab(nViewTab); + aFilterRange.aEnd.SetTab(nViewTab); + + // Build an AutoFilter from the NSV column filter data and apply it + bool bHasColumnFilters + = std::any_of(rNsvFilter.maColumnFilters.begin(), rNsvFilter.maColumnFilters.end(), + [](const auto& rCF) { return !rCF.maFilters.empty(); }); + + if (bHasColumnFilters) + { + try + { + AutoFilter aAutoFilter(*this); + aAutoFilter.setRange(aFilterRange); + + for (const auto& rColFilter : rNsvFilter.maColumnFilters) + { + for (const auto& rFilter : rColFilter.maFilters) + { + if (rFilter.mxSettings) + { + FilterColumn& rFilterColumn = aAutoFilter.createFilterColumn(); + rFilterColumn.setColumnData(rFilter.maColumnID, rFilter.mxSettings); + } + } + } + + rtl::Reference xDatabaseRange + = createUnnamedDatabaseRangeObject(aFilterRange); + if (xDatabaseRange.is()) + { + xDatabaseRange->setPropertyValue(u"AutoFilter"_ustr, css::uno::Any(true)); + aAutoFilter.finalizeImport(xDatabaseRange, nViewTab); + + // Execute the filter query to actually hide rows + ScDBData* pDBData = rDoc.GetAnonymousDBData(nViewTab); + ScDocShell* pFilterDocShell = rDoc.GetDocumentShell(); + if (pDBData && pFilterDocShell) + { + ScQueryParam aQueryParam; + pDBData->GetQueryParam(aQueryParam); + ScDBDocFunc aDBDocFunc(*pFilterDocShell); + aDBDocFunc.Query(nViewTab, aQueryParam, nullptr, false, false); + } + } + } + catch (const css::uno::Exception&) + { + SAL_WARN("sc", "Failed to apply filter to named sheet view"); + } + } + + // Apply sort rules if present + if (rNsvFilter.maSortRules) + { + const auto& rSortRules = *rNsvFilter.maSortRules; + if (!rSortRules.maRules.empty()) + { + ScSortParam aParam; + aParam.nCol1 = aFilterRange.aStart.Col(); + aParam.nRow1 = aFilterRange.aStart.Row(); + aParam.nCol2 = aFilterRange.aEnd.Col(); + aParam.nRow2 = aFilterRange.aEnd.Row(); + aParam.bHasHeader = true; + aParam.bByRow = true; + aParam.bCaseSens = rSortRules.mbCaseSensitive; + + size_t nKeyIdx = 0; + for (const auto& rSortRule : rSortRules.maRules) + { + if (nKeyIdx >= aParam.GetSortKeyCount()) + aParam.maKeyState.resize(nKeyIdx + 1); + + // Parse the sort condition reference to get the column + ScRange aSortRange; + if (!rSortRule.maRef.isEmpty() + && getAddressConverter().convertToCellRange(aSortRange, rSortRule.maRef, + nViewTab, true, true)) + { + aParam.maKeyState[nKeyIdx].bDoSort = true; + aParam.maKeyState[nKeyIdx].bAscending = !rSortRule.mbDescending; + aParam.maKeyState[nKeyIdx].nField = aSortRange.aStart.Col(); + ++nKeyIdx; + } + } + + if (nKeyIdx > 0) + { + ScDocShell* pDocShell = rDoc.GetDocumentShell(); + if (pDocShell) + { + ScDBDocFunc aFunc(*pDocShell); + aFunc.SortTab(nViewTab, aParam, false, false, true); + } + } + } + } + } + } +} + +} // namespace oox::xls::nsv + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/oox/PivotTableFormat.cxx b/sc/source/filter/oox/PivotTableFormat.cxx index a4e7b0bcf30a..ee44ccc1f497 100644 --- a/sc/source/filter/oox/PivotTableFormat.cxx +++ b/sc/source/filter/oox/PivotTableFormat.cxx @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -72,6 +73,8 @@ void PivotTableFormat::importPivotArea(const oox::AttributeList& rAttribs) moOffset = rAttribs.getXString(XML_offset); mbCollapsedLevelsAreSubtotals = rAttribs.getBool(XML_collapsedLevelsAreSubtotals, false); moFieldPosition = rAttribs.getUnsigned(XML_fieldPosition); + // tdf#122473 - import alignment and axis-based pivot area formats + moAxis = rAttribs.getToken(XML_axis); } void PivotTableFormat::finalizeImport() @@ -91,8 +94,6 @@ void PivotTableFormat::finalizeImport() if (pSaveData->hasFormats()) aFormats = pSaveData->getFormats(); - // Resolve references - TODO - sc::PivotTableFormat aFormat; if (mbDataOnly) aFormat.eType = sc::FormatType::Data; @@ -102,19 +103,64 @@ void PivotTableFormat::finalizeImport() aFormat.bDataOnly = mbDataOnly; aFormat.bLabelOnly = mbLabelOnly; aFormat.bOutline = mbOutline; + aFormat.bGrandRow = mbGrandRow; + aFormat.bGrandColumn = mbGrandCol; aFormat.oFieldPosition = moFieldPosition; + if (moOffset) + { + // Resolve offset. Either it is a range or a single cell. + // Try as a range first + ScRange aRange; + ScRefFlags nFlags + = aRange.Parse(*moOffset, getScDocument(), formula::FormulaGrammar::CONV_XL_A1); + if (nFlags & ScRefFlags::COL_VALID) + { + aFormat.oOffset = aRange; + } + else + { + // Try as a single cell address + ScAddress aAddress; + nFlags + = aAddress.Parse(*moOffset, getScDocument(), formula::FormulaGrammar::CONV_XL_A1); + if (nFlags & ScRefFlags::COL_VALID) + aFormat.oOffset = ScRange(aAddress); + } + } aFormat.pPattern = std::move(pPattern); for (auto& rReference : maReferences) { if (rReference->mnField) { + sal_Int32 nDimension = sal_Int32(*rReference->mnField); + + bool bHasSubtotal = rReference->mbDefaultSubtotal || rReference->mbSumSubtotal + || rReference->mbCountASubtotal || rReference->mbAvgSubtotal + || rReference->mbMaxSubtotal || rReference->mbMinSubtotal + || rReference->mbProductSubtotal || rReference->mbCountSubtotal + || rReference->mbStdDevSubtotal || rReference->mbStdDevPSubtotal + || rReference->mbVarSubtotal || rReference->mbVarPSubtotal; + aFormat.aSelections.push_back( sc::Selection{ .bSelected = rReference->mbSelected, - .nField = sal_Int32(*rReference->mnField), - .nIndices = rReference->maFieldItemsIndices }); + .nField = nDimension, + .nIndices = rReference->maFieldItemsIndices, + .bHasSubtotal = bHasSubtotal }); } } + + // tdf#122473 - import alignment and axis-based pivot area formats + // There is no field or reference given. However, there exists an axis value. + // The format uses it to identify the label of the field data. Treat it as an + // explicit reference to the values field. + if (maReferences.empty() && mbLabelOnly && moAxis && *moAxis == XML_axisValues) + { + aFormat.aSelections.push_back(sc::Selection{ .bSelected = true, + .nField = sal_Int32(sc::constDataDimension), + .nIndices = {}, + .bHasSubtotal = false }); + } aFormats.add(aFormat); pSaveData->setFormats(aFormats); diff --git a/sc/source/filter/oox/autofilterbuffer.cxx b/sc/source/filter/oox/autofilterbuffer.cxx index ab9b5ebf4e4a..77b539d78247 100644 --- a/sc/source/filter/oox/autofilterbuffer.cxx +++ b/sc/source/filter/oox/autofilterbuffer.cxx @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -645,6 +646,12 @@ void FilterColumn::importFilterColumn( SequenceInputStream& rStrm ) mbShowButton = !getFlag( nFlags, BIFF12_FILTERCOLUMN_SHOWBUTTON ); } +void FilterColumn::setColumnData(sal_Int32 nColId, std::shared_ptr xSettings) +{ + mnColId = nColId; + mxSettings = std::move(xSettings); +} + ApiFilterSettings FilterColumn::finalizeImport() { ApiFilterSettings aSettings; @@ -707,6 +714,11 @@ void AutoFilter::importSortState( const AttributeList& rAttribs, sal_Int16 nShee AddressConverter::convertToCellRangeUnchecked(maSortRange, aRangeStr, nSheet, getScDocument()); } +void AutoFilter::setRange(const ScRange& rRange) +{ + maRange = rRange; +} + FilterColumn& AutoFilter::createFilterColumn() { FilterColumnVector::value_type xFilterColumn = std::make_shared( *this ); @@ -757,10 +769,15 @@ void AutoFilter::finalizeImport(const rtl::Reference& rxData '(A1 and B1) or (B2 and C1)'. */ bool bHasOrConnection = false; - SCCOL nCol = maRange.aStart.Col(); + SCCOL nStartCol = maRange.aStart.Col(); SCROW nRow = maRange.aStart.Row(); SCTAB nTab = maRange.aStart.Tab(); + std::set aHiddenButtonIds; + for (const auto& rxFilterColumn : maFilterColumns) + if (rxFilterColumn->isButtonHidden()) + aHiddenButtonIds.insert(rxFilterColumn->getColumnId()); + // process all filter column objects, exit when 'or' connection exists for( const auto& rxFilterColumn : maFilterColumns ) { @@ -770,10 +787,28 @@ void AutoFilter::finalizeImport(const rtl::Reference& rxData if (rxFilterColumn->isButtonHidden()) { + // In OOXML `colId` attribute is 0-based offset of autofilter range + SCCOL nCol = nStartCol + rxFilterColumn->getColumnId(); + + /* For merged cells except first cell all remaining cells will have the + "overlapped" property set to true. Autofilter dropdown button can only be + drawn on non-overlapped cells. + + So, here if a column belongs to a merged cells, and it's the merge master + we skip hiding the button. */ + + const ScMergeAttr& rMerge = rDoc.GetAttr(nCol, nRow, nTab, ATTR_MERGE); + SCCOL nColSpan = rMerge.GetColMerge(); + if (nColSpan > 1) + { + sal_Int32 nLastColId = rxFilterColumn->getColumnId() + nColSpan - 1; + if (aHiddenButtonIds.find(nLastColId) == aHiddenButtonIds.end()) + continue; + } + auto nFlag = rDoc.GetAttr(nCol, nRow, nTab, ATTR_MERGE_FLAG).GetValue(); rDoc.ApplyAttr(nCol, nRow, nTab, ScMergeFlagAttr(nFlag & ~ScMF::Auto)); } - nCol++; /* Check whether mode for regular expressions is compatible with the global mode in obNeedsRegExp. If either one is still in diff --git a/sc/source/filter/oox/biffhelper.cxx b/sc/source/filter/oox/biffhelper.cxx index 20a088fc73fc..360426b8a36c 100644 --- a/sc/source/filter/oox/biffhelper.cxx +++ b/sc/source/filter/oox/biffhelper.cxx @@ -21,6 +21,8 @@ #include #include +#include +#include #include @@ -89,6 +91,17 @@ const sal_Int32 BIFF_RK_VALUEMASK = 0xFFFFFFFC; // SequenceInputStream always supports getRemaining() nCharCount = ::std::min( nCharCount, static_cast< sal_Int32 >( rStrm.getRemaining() / 2 ) ); aString = rStrm.readUnicodeArray( nCharCount ); + + OString aUtf8Check; + if( !aString.convertToString( + &aUtf8Check, RTL_TEXTENCODING_UTF8, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR ) ) + { + SAL_WARN( "sc", "invalid utf8 string, doing best-effort fix" ); + aString.convertToString( &aUtf8Check, RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); + aString = OStringToOUString( aUtf8Check, RTL_TEXTENCODING_UTF8 ); + } } } return aString; diff --git a/sc/source/filter/oox/connectionsbuffer.cxx b/sc/source/filter/oox/connectionsbuffer.cxx index 2a18b1b08028..357c43765b9c 100644 --- a/sc/source/filter/oox/connectionsbuffer.cxx +++ b/sc/source/filter/oox/connectionsbuffer.cxx @@ -106,28 +106,28 @@ ConnectionModel::ConnectionModel() : WebPrModel& ConnectionModel::createWebPr() { - OSL_ENSURE( !mxWebPr, "ConnectionModel::createWebPr - multiple call" ); + OSL_ENSURE( !mxWebPr, "ConnectionModel::createWebPr - multiple calls" ); mxWebPr.reset( new WebPrModel ); return *mxWebPr; } TextPrModel& ConnectionModel::createTextPr() { - OSL_ENSURE(!mxTextPr, "ConnectionModel::createTextPr - multiple call"); + OSL_ENSURE(!mxTextPr, "ConnectionModel::createTextPr - multiple calls"); mxTextPr.reset(new TextPrModel); return *mxTextPr; } ParametersModel& ConnectionModel::createParameters() { - OSL_ENSURE(!mxParameters, "ConnectionModel::createParameters - multiple call"); + OSL_ENSURE(!mxParameters, "ConnectionModel::createParameters - multiple calls"); mxParameters.reset(new ParametersModel); return *mxParameters; } ExtensionListModel& ConnectionModel::createExtensionList() { - OSL_ENSURE(!mxExtensionList, "ConnectionModel::createExtensionList - multiple call"); + OSL_ENSURE(!mxExtensionList, "ConnectionModel::createExtensionList - multiple calls"); mxExtensionList.reset(new ExtensionListModel); return *mxExtensionList; } @@ -472,7 +472,7 @@ void ConnectionsBuffer::insertConnectionToMap( const ConnectionRef& rxConnection sal_Int32 nConnId = rxConnection->getConnectionId(); if( nConnId > 0 ) { - OSL_ENSURE( !maConnectionsById.has( nConnId ), "ConnectionsBuffer::insertConnectionToMap - multiple connection identifier" ); + OSL_ENSURE( !maConnectionsById.has( nConnId ), "ConnectionsBuffer::insertConnectionToMap - multiple connection identifiers" ); maConnectionsById[ nConnId ] = rxConnection; mnUnusedId = ::std::max< sal_Int32 >( mnUnusedId, nConnId + 1 ); } diff --git a/sc/source/filter/oox/defaulttablestyles.cxx b/sc/source/filter/oox/defaulttablestyles.cxx deleted file mode 100644 index 5f734e434610..000000000000 --- a/sc/source/filter/oox/defaulttablestyles.cxx +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include -#include - -#include "defaulttablestyles.inc" -#include - -DefaultOOXMLTableStyles::DefaultOOXMLTableStyles(const oox::xls::WorkbookHelper& rHelper) - : WorkbookHelper(rHelper) -{ - importColors(); - importFills(); - importBorders(); - importFonts(); - importDxfs(); -} - -void DefaultOOXMLTableStyles::importColors() -{ - size_t nColors = sizeof(aThemeColors) / sizeof(ThemeColor); - for (size_t i = 0; i < nColors; ++i) - { - oox::xls::XlsColor aColor; - aColor.setTheme(aThemeColors[i].nThemeId, aThemeColors[i].fTint); - maColors.push_back(std::move(aColor)); - } -} - -void DefaultOOXMLTableStyles::importFills() -{ - size_t nFills = sizeof(aFills) / sizeof(Fill); - for (size_t i = 0; i < nFills; ++i) - { - auto xFill = std::make_shared(*this, true); - xFill->setFillColors(maColors[aFills[i].nFgColorId], maColors[aFills[i].nBgColorId]); - maFills.push_back(std::move(xFill)); - } -} - -void DefaultOOXMLTableStyles::importBorderElement(oox::xls::BorderRef xBorder, - sal_Int32 nBorderElement, - sal_Int32 nBorderElementId) -{ - const BorderElement& rBorderElement = aBorderElements[nBorderElementId]; - if (rBorderElement.nColorId >= static_cast(maColors.size())) - return; - - sal_Int32 nBorderStyle; - switch (rBorderElement.eBorderStyle) - { - case BorderElementStyle::THIN: - nBorderStyle = oox::XML_thin; - break; - case BorderElementStyle::MEDIUM: - nBorderStyle = oox::XML_medium; - break; - case BorderElementStyle::THICK: - nBorderStyle = oox::XML_thick; - break; - case BorderElementStyle::DOUBLE: - nBorderStyle = oox::XML_double; - break; - default: - nBorderStyle = oox::XML_none; - } - - oox::xls::XlsColor& rColor = maColors[rBorderElement.nColorId]; - xBorder->setBorderElement(nBorderElement, rColor, nBorderStyle); -} - -void DefaultOOXMLTableStyles::importBorders() -{ - size_t nBorders = sizeof(aBorders) / sizeof(Border); - for (size_t i = 0; i < nBorders; ++i) - { - auto xBorder = std::make_shared(*this, true); - - const Border& rBorderInfo = aBorders[i]; - if (rBorderInfo.nTopId >= 0) - importBorderElement(xBorder, XLS_TOKEN(top), rBorderInfo.nTopId); - if (rBorderInfo.nBottomId >= 0) - importBorderElement(xBorder, XLS_TOKEN(bottom), rBorderInfo.nBottomId); - if (rBorderInfo.nLeftId >= 0) - importBorderElement(xBorder, XLS_TOKEN(left), rBorderInfo.nLeftId); - if (rBorderInfo.nRightId >= 0) - importBorderElement(xBorder, XLS_TOKEN(right), rBorderInfo.nRightId); - if (rBorderInfo.nVerticalId >= 0) - importBorderElement(xBorder, XLS_TOKEN(vertical), rBorderInfo.nVerticalId); - if (rBorderInfo.nHorizontalId >= 0) - importBorderElement(xBorder, XLS_TOKEN(horizontal), rBorderInfo.nHorizontalId); - - maBorders.push_back(std::move(xBorder)); - } -} - -void DefaultOOXMLTableStyles::importFonts() -{ - size_t nFonts = sizeof(aFonts) / sizeof(Font); - for (size_t i = 0; i < nFonts; ++i) - { - auto xFont = std::make_shared(*this, true); - - const Font& rFontInfo = aFonts[i]; - xFont->setFontElements(maColors[rFontInfo.nThemeColorId], rFontInfo.bBold); - - maFonts.push_back(std::move(xFont)); - } -} - -void DefaultOOXMLTableStyles::importDxfs() -{ - size_t nDxfs = sizeof(aDxfs) / sizeof(Dxf); - for (size_t i = 0; i < nDxfs; ++i) - { - auto xDxf = std::make_shared(*this); - auto aDxfInfo = aDxfs[i]; - - if (aDxfInfo.nFillId >= 0) - xDxf->setFill(maFills[aDxfInfo.nFillId]); - - if (aDxfInfo.nBorderId >= 0) - xDxf->setBorder(maBorders[aDxfInfo.nBorderId]); - - if (aDxfInfo.nFontId >= 0) - xDxf->setFont(maFonts[aDxfInfo.nFontId]); - - xDxf->finalizeImport(); - maDxfs.push_back(std::move(xDxf)); - } -} - -void DefaultOOXMLTableStyles::importTableStyle(const TableStyle& rTableStyleInfo) -{ - oox::xls::TableStyle aTableStyle(*this, true); - aTableStyle.setName(OUString::createFromAscii(rTableStyleInfo.pName)); - for (size_t i = 0; i < rTableStyleInfo.nElements; ++i) - { - const TableStyleElement& rTableStyleElement - = aTableStyleElements[rTableStyleInfo.pTableStyleElementIds[i]]; - aTableStyle.setTableStyleElement(rTableStyleElement.eElement, rTableStyleElement.nDxfId); - } - - aTableStyle.finalizeImport(maDxfs); -} - -void DefaultOOXMLTableStyles::importTableStyles() -{ - size_t nTableStyles = sizeof(aTableStyles) / sizeof(TableStyle); - for (size_t i = 0; i < nTableStyles; ++i) - { - importTableStyle(aTableStyles[i]); - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/filter/oox/defnamesbuffer.cxx b/sc/source/filter/oox/defnamesbuffer.cxx index 5d4e113601d7..5c8dec099cdd 100644 --- a/sc/source/filter/oox/defnamesbuffer.cxx +++ b/sc/source/filter/oox/defnamesbuffer.cxx @@ -56,6 +56,7 @@ const sal_uInt32 BIFF12_DEFNAME_MACRO = 0x00000008; const sal_uInt32 BIFF12_DEFNAME_BUILTIN = 0x00000020; constexpr OUString spcOoxPrefix(u"_xlnm."_ustr); +constexpr OUString spcDefNamePrefix(u"Excel_BuiltIn_"_ustr); const char* const sppcBaseNames[] = { @@ -88,7 +89,8 @@ OUString lclGetBaseName( sal_Unicode cBuiltinId ) OUString lclGetPrefixedName( sal_Unicode cBuiltinId ) { - return spcOoxPrefix + lclGetBaseName( cBuiltinId ); + // tdf#113596 - retrieve the same prefix as for the XLS import in XclTools::GetBuiltInDefName + return spcDefNamePrefix + lclGetBaseName(cBuiltinId); } /** returns the built-in name identifier from a prefixed built-in name, e.g. '_xlnm.Print_Area'. */ diff --git a/sc/source/filter/oox/drawingfragment.cxx b/sc/source/filter/oox/drawingfragment.cxx index ec75f6544a4c..b6b07ffb1e9a 100644 --- a/sc/source/filter/oox/drawingfragment.cxx +++ b/sc/source/filter/oox/drawingfragment.cxx @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include #include @@ -140,7 +142,20 @@ GroupShapeContext::GroupShapeContext( const FragmentHandler2& rParent, ShapePtr xShape = std::make_shared( rHelper, rAttribs, u"com.sun.star.drawing.CustomShape"_ustr ); if( pxShape ) *pxShape = xShape; - xShape->setMacro(rAttribs.getXString(XML_macro, OUString())); + OUString aMacro = rAttribs.getXString(XML_macro, OUString()); + if (!aMacro.isEmpty()) + { + xShape->setMacro(aMacro); + + OUString aExtUrl, aExtName; + if (rHelper.getFormulaParser().importMacroExternalRef(aMacro, aExtUrl, aExtName)) + { + xShape->setMacroExtUrl(aExtUrl); + ScExternalRefManager* pRefMgr = rHelper.getScDocument().GetExternalRefManager(); + sal_uInt16 nFileId = pRefMgr->getExternalFileId(aExtUrl); + pRefMgr->addDrawingMacros(nFileId, aExtName); + } + } xShape->setTextLinkAttr(rAttribs.getXString(XML_textlink, OUString())); xShape->setFLocksText(rAttribs.getBool(XML_fLocksText, true)); // default="true" xShape->setFPublished(rAttribs.getBool(XML_fPublished, false)); // default="false" @@ -265,12 +280,30 @@ void DrawingFragment::onEndElement() if( mxDrawPage.is() && mxShape && mxAnchor ) { EmuRectangle aShapeRectEmu = mxAnchor->calcAnchorRectEmu( getDrawPageSize() ); + + // In these two ranges of angles the anchor rectangle describes the bounding + // box of the rotated shape, so its width and height are exchanged + const sal_Int32 nRotation = mxShape->getRotation(); + const bool bQuarterTurn + = ((nRotation >= 45 * PER_DEGREE && nRotation < 135 * PER_DEGREE) + || (nRotation >= 225 * PER_DEGREE && nRotation < 315 * PER_DEGREE)); + + // For twoCellAnchor we should set the size and anchor based on the `editAs` attribute (ISO-IEC-29500-1 2016 [20.5.3.2]) + if (mxAnchor->getAnchorType() == ShapeAnchor::ANCHOR_TWOCELL + && (mxAnchor->getEditAs() == ShapeAnchor::ANCHOR_ONECELL + || mxAnchor->getEditAs() == ShapeAnchor::ANCHOR_ABSOLUTE)) + { + const css::awt::Size& rShapeSize = mxShape->getSize(); + if (rShapeSize.Width > 0 && rShapeSize.Height > 0) + { + aShapeRectEmu.Width = bQuarterTurn ? rShapeSize.Height : rShapeSize.Width; + aShapeRectEmu.Height = bQuarterTurn ? rShapeSize.Width : rShapeSize.Height; + } + } const bool bIsShapeVisible = mxAnchor->isAnchorValid(); if( (aShapeRectEmu.X >= 0) && (aShapeRectEmu.Y >= 0) && (aShapeRectEmu.Width >= 0) && (aShapeRectEmu.Height >= 0) ) { - const sal_Int32 aRotation = mxShape->getRotation(); - if ((aRotation >= 45 * PER_DEGREE && aRotation < 135 * PER_DEGREE) - || (aRotation >= 225 * PER_DEGREE && aRotation < 315 * PER_DEGREE)) + if (bQuarterTurn) { // When rotating any shape in MSO Excel within the range of degrees given above, // Excel changes the cells in which the shape is anchored. The new position of @@ -319,23 +352,39 @@ void DrawingFragment::onEndElement() // diagram shapes at all. Here the size has been determined from the anchor and // thus repeating the import of diagram.xml gives the diagram shapes. // - // I have checked that mpDiagramHelper at mxShape is *not* resetted here + // I have checked that mpDiagramHelper at mxShape is *not* reset here // which is crucial to keep that stuff working. Also added a isDiagram // method to avoid indirect test for Diagram using former getDiagramDoms() if (nullptr != mxShape->getDiagramHelper() && mxShape->getChildren().size() == 1 && mxShape->getExtDrawings().size() != 0) { + // this is a diagram with content and has external graphics, that + // means a GraphicalReplacement. Import & use that if it exists mxShape->getChildren()[0]->setSize(mxShape->getSize()); OUString sFragmentPath( getFragmentPathFromRelId(mxShape->getExtDrawings()[0])); - // Don't know why importFragment looses shape name and id. Rescue them. - OUString sBackupName(mxShape->getName()); - OUString sBackupId(mxShape->getId()); - getOoxFilter().importFragment(new oox::shape::ShapeDrawingFragmentHandler( - getOoxFilter(), sFragmentPath, mxShape)); + + // Don't know why importFragment loses shape name and id. Rescue them. + const OUString sBackupName(mxShape->getName()); + const OUString sBackupId(mxShape->getId()); + + // take care of possibility to ignore GraphicalReplacement + // to 'force' a ReLayout at import time + static bool bIgnoreExtDrawings(nullptr != std::getenv("DIAGRAM_IGNORE_EXTDRAWINGS")); + if (!bIgnoreExtDrawings) + { + getOoxFilter().importFragment(new oox::shape::ShapeDrawingFragmentHandler( + getOoxFilter(), sFragmentPath, mxShape)); + } + mxShape->setName(sBackupName); mxShape->setId(sBackupId); + + // need to rescue/set DomTrees of DomMapFlag::OOXDrawing + // and DomMapFlag::OOXDrawing(Image|Hlink)Rels to be able + // to export original if not changed + mxShape->keepDiagramDrawing(getOoxFilter(), sFragmentPath); } if (mxShape->getFontRefColorForNodes().isUsed()) @@ -384,33 +433,6 @@ void DrawingFragment::applyFontRefColor(const oox::drawingml::ShapePtr& pShape, // VML -namespace { - -class VmlFindNoteFunc -{ -public: - explicit VmlFindNoteFunc( const ScAddress& rPos ); - bool operator()( const ::oox::vml::ShapeBase& rShape ) const; - -private: - sal_Int32 mnCol; - sal_Int32 mnRow; -}; - -VmlFindNoteFunc::VmlFindNoteFunc( const ScAddress& rPos ) : - mnCol( rPos.Col() ), - mnRow( rPos.Row() ) -{ -} - -bool VmlFindNoteFunc::operator()( const ::oox::vml::ShapeBase& rShape ) const -{ - const ::oox::vml::ClientData* pClientData = rShape.getClientData(); - return pClientData && (pClientData->mnCol == mnCol) && (pClientData->mnRow == mnRow); -} - -} // namespace - VmlControlMacroAttacher::VmlControlMacroAttacher( const OUString& rMacroName, const Reference< XIndexContainer >& rxCtrlFormIC, sal_Int32 nCtrlIndex, sal_Int32 nCtrlType, sal_Int32 nDropStyle ) : VbaMacroAttacherBase( rMacroName ), @@ -485,11 +507,6 @@ VmlDrawing::VmlDrawing( const WorksheetHelper& rHelper ) : maListBoxFont.monSize = 160; } -const ::oox::vml::ShapeBase* VmlDrawing::getNoteShape( const ScAddress& rPos ) const -{ - return getShapes().findShape( VmlFindNoteFunc( rPos ) ); -} - VmlDrawing::NoteShapesMap VmlDrawing::buildNoteShapesMap() const { VmlDrawing::NoteShapesMap aMap; @@ -711,6 +728,25 @@ Reference< XShape > VmlDrawing::createAndInsertClientXShape( const ::oox::vml::S sal_Int32 nCtrlIndex = -1; Reference< XShape > xShape = createAndInsertXControlShape( aControl, rxShapes, aShapeRect, nCtrlIndex ); + if (xShape.is()) + { + Reference xShapeProps(xShape, UNO_QUERY); + if (xShapeProps.is() + && xShapeProps->getPropertySetInfo()->hasPropertyByName( + u"InteropGrabBag"_ustr)) + { + Sequence aGrabBag; + xShapeProps->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag; + sal_Int32 length = aGrabBag.getLength(); + aGrabBag.realloc(length + 1); + auto pGrabBag = aGrabBag.getArray(); + pGrabBag[length].Name = "VMLStroked"; + pGrabBag[length].Value + <<= rShape.getTypeModel().maStrokeModel.moStroked.value_or(true); + xShapeProps->setPropertyValue(u"InteropGrabBag"_ustr, Any(aGrabBag)); + } + } + // control shape macro if( xShape.is() && (nCtrlIndex >= 0) && !pClientData->maFmlaMacro.isEmpty() ) { @@ -868,9 +904,20 @@ void VmlDrawing::convertControlFontData( AxFontData& rAxFontData, sal_uInt32& rn setFlag( rAxFontData.mnFontEffects, AxFontFlags::Bold, rFontModel.mobBold.value_or( false ) ); setFlag( rAxFontData.mnFontEffects, AxFontFlags::Italic, rFontModel.mobItalic.value_or( false ) ); setFlag( rAxFontData.mnFontEffects, AxFontFlags::Strikeout, rFontModel.mobStrikeout.value_or( false ) ); - sal_Int32 nUnderline = rFontModel.monUnderline.value_or( XML_none ); - setFlag( rAxFontData.mnFontEffects, AxFontFlags::Underline, nUnderline != XML_none ); - rAxFontData.mbDblUnderline = nUnderline == XML_double; + setFlag( rAxFontData.mnFontEffects, AxFontFlags::Underline, rFontModel.mobUnderline.value_or( false ) ); + // A bare element cannot say "double", so Excel names the workbook font record that carries + // the style - the class is a reference, not a style of its own. + rAxFontData.mbDblUnderline = false; + if ((rAxFontData.mnFontEffects & AxFontFlags::Underline) && rFontModel.moUnderlineClass) + { + if (OUString aFontId; rFontModel.moUnderlineClass.value().startsWith(u"font", &aFontId)) + { + if (FontRef rxFont = getStyles().getFont(aFontId.toInt32())) + rAxFontData.mbDblUnderline + = (rxFont->getModel().mnUnderline == XML_double) + || (rxFont->getModel().mnUnderline == XML_doubleAccounting); + } + } // font color rnOleTextColor = convertControlTextColor( rFontModel.moColor.value_or( OUString() ) ); diff --git a/sc/source/filter/oox/externallinkbuffer.cxx b/sc/source/filter/oox/externallinkbuffer.cxx index a812a48cff5a..e3a73f3ae4b6 100644 --- a/sc/source/filter/oox/externallinkbuffer.cxx +++ b/sc/source/filter/oox/externallinkbuffer.cxx @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -88,9 +89,20 @@ void ExternalName::importDefinedName( const AttributeList& rAttribs ) maModel.maName = rAttribs.getXString( XML_name, OUString() ); OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importDefinedName - empty name" ); maModel.maFormula = rAttribs.getXString(XML_refersTo, OUString()); - OSL_ENSURE( !maModel.maFormula.isEmpty(), "ExternalName::importDefinedName - empty formula" ); // zero-based index into sheet list of externalBook maModel.mnSheet = rAttribs.getInteger( XML_sheetId, -1 ); + + ScExternalRefManager* pRefMgr = getScDocument().GetExternalRefManager(); + sal_uInt16 nFileId = pRefMgr->getExternalFileId(mrParentLink.getTargetUrl()); + + if (maModel.maFormula.isEmpty()) + { + // Store the name with an empty token array so it survives roundtrip + ScTokenArray aEmpty(getScDocument()); + pRefMgr->storeRangeNameTokens(nFileId, maModel.maName, aEmpty); + return; + } + // cache external defined names and formulas ScCompiler aComp(getScDocument(), ScAddress(0, 0, maModel.mnSheet), formula::FormulaGrammar::GRAM_OOXML); aComp.SetExternalLinks(getExternalLinks().getLinkInfos()); @@ -101,12 +113,7 @@ void ExternalName::importDefinedName( const AttributeList& rAttribs ) pArray->DelRPN(); pArray->SetCodeError(nErr); - if (pArray->HasReferences()) - { - ScExternalRefManager* pRefMgr = getScDocument().GetExternalRefManager(); - sal_uInt16 nFileId = pRefMgr->getExternalFileId(mrParentLink.getTargetUrl()); - pRefMgr->storeRangeNameTokens(nFileId, maModel.maName, *pArray); - } + pRefMgr->storeRangeNameTokens(nFileId, maModel.maName, *pArray); } void ExternalName::importDdeItem( const AttributeList& rAttribs ) @@ -413,6 +420,11 @@ ExternalLinkInfo ExternalLink::getLinkInfo() const aLinkInfo.Type = css::sheet::ExternalLinkType::DOCUMENT; aLinkInfo.Data <<= maTargetUrl; break; + case ExternalLinkType::PathMissing: + case ExternalLinkType::XlStartup: + aLinkInfo.Type = css::sheet::ExternalLinkType::MISSINGDOCUMENT; + aLinkInfo.Data <<= maTargetUrl; + break; case ExternalLinkType::Library: // parser will return library function names in OPCODE_BAD string tokens aLinkInfo.Type = css::sheet::ExternalLinkType::SPECIAL; @@ -445,13 +457,19 @@ FunctionLibraryType ExternalLink::getFuncLibraryType() const sal_Int32 ExternalLink::getDocumentLinkIndex() const { - OSL_ENSURE( meLinkType == ExternalLinkType::External, "ExternalLink::getDocumentLinkIndex - invalid link type" ); + OSL_ENSURE(meLinkType == ExternalLinkType::External + || meLinkType == ExternalLinkType::PathMissing + || meLinkType == ExternalLinkType::XlStartup, + "ExternalLink::getDocumentLinkIndex - invalid link type"); return mxDocLink.is() ? mxDocLink->getTokenIndex() : -1; } sal_Int32 ExternalLink::getSheetCacheIndex( sal_Int32 nTabId ) const { - OSL_ENSURE( meLinkType == ExternalLinkType::External, "ExternalLink::getSheetCacheIndex - invalid link type" ); + OSL_ENSURE(meLinkType == ExternalLinkType::External + || meLinkType == ExternalLinkType::PathMissing + || meLinkType == ExternalLinkType::XlStartup, + "ExternalLink::getSheetCacheIndex - invalid link type"); return ContainerHelper::getVectorElement( maSheetCaches, nTabId, -1 ); } @@ -483,6 +501,8 @@ void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId break; case ExternalLinkType::External: + case ExternalLinkType::PathMissing: + case ExternalLinkType::XlStartup: { sal_Int32 nDocLinkIdx = getDocumentLinkIndex(); // BIFF12: passed indexes point into sheet list of EXTSHEETLIST @@ -515,8 +535,14 @@ void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUStr } else if( rTargetType == CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlPathMissing" ) ) { + maTargetUrl = rTargetUrl; meLinkType = ExternalLinkType::PathMissing; } + else if( rTargetType == CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlStartup" ) ) + { + maTargetUrl = rTargetUrl; + meLinkType = ExternalLinkType::XlStartup; + } else if( rTargetType == CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlLibrary" ) ) { meLinkType = ExternalLinkType::Library; @@ -525,11 +551,17 @@ void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUStr SAL_WARN_IF( meLinkType == ExternalLinkType::Unknown, "sc.filter", "Empty target URL or unknown target type, URL='" << rTargetUrl << "', type='" << rTargetType << "'" ); // create the external document link API object that will contain the sheet caches - if( meLinkType == ExternalLinkType::External ) try + if (meLinkType == ExternalLinkType::External || meLinkType == ExternalLinkType::PathMissing + || meLinkType == ExternalLinkType::XlStartup) try { PropertySet aDocProps(( Reference< css::beans::XPropertySet >(getDocument()) )); Reference< XExternalDocLinks > xDocLinks( aDocProps.getAnyProperty( PROP_ExternalDocLinks ), UNO_QUERY_THROW ); - mxDocLink = xDocLinks->addDocLink( maTargetUrl ); + if (meLinkType == ExternalLinkType::PathMissing) + mxDocLink = xDocLinks->addSpecialDocLink(maTargetUrl, ExternalLinkRelType::PATH_MISSING); + else if (meLinkType == ExternalLinkType::XlStartup) + mxDocLink = xDocLinks->addSpecialDocLink(maTargetUrl, ExternalLinkRelType::XL_STARTUP); + else + mxDocLink = xDocLinks->addDocLink(maTargetUrl); } catch( Exception& ) { diff --git a/sc/source/filter/oox/externallinkfragment.cxx b/sc/source/filter/oox/externallinkfragment.cxx index 07fbece61698..ebe39ac51e30 100644 --- a/sc/source/filter/oox/externallinkfragment.cxx +++ b/sc/source/filter/oox/externallinkfragment.cxx @@ -196,7 +196,10 @@ ContextHandlerRef ExternalLinkFragment::onCreateContext( sal_Int32 nElement, con if( nElement == XLS_TOKEN( definedName ) ) mrExtLink.importDefinedName( rAttribs ); break; case XLS_TOKEN( sheetDataSet ): - if( (nElement == XLS_TOKEN( sheetData )) && (mrExtLink.getLinkType() == ExternalLinkType::External) ) + if ((nElement == XLS_TOKEN(sheetData)) + && (mrExtLink.getLinkType() == ExternalLinkType::External + || mrExtLink.getLinkType() == ExternalLinkType::PathMissing + || mrExtLink.getLinkType() == ExternalLinkType::XlStartup)) return createSheetDataContext( rAttribs.getInteger( XML_sheetId, -1 ) ); break; @@ -284,7 +287,9 @@ ContextHandlerRef ExternalLinkFragment::onCreateRecordContext( sal_Int32 nRecId, switch( nRecId ) { case BIFF12_ID_EXTSHEETDATA: - if( mrExtLink.getLinkType() == ExternalLinkType::External ) + if (mrExtLink.getLinkType() == ExternalLinkType::External + || mrExtLink.getLinkType() == ExternalLinkType::XlStartup + || mrExtLink.getLinkType() == ExternalLinkType::PathMissing) return createSheetDataContext( rStrm.readInt32() ); break; diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx index 60610682c6c7..35a558f74e73 100644 --- a/sc/source/filter/oox/formulabase.cxx +++ b/sc/source/filter/oox/formulabase.cxx @@ -884,7 +884,16 @@ const FunctionData saFuncTable2021[] = { "COM.MICROSOFT.SEQUENCE", "SEQUENCE", NOID, NOID, 1, 4, A, { VO }, FuncFlags::MACROCALL_NEW }, { "COM.MICROSOFT.RANDARRAY", "RANDARRAY", NOID, NOID, 0, 5, A, { VO }, FuncFlags::MACROCALL_NEW }, { "COM.MICROSOFT.UNIQUE", "UNIQUE", NOID, NOID, 1, 3, A, { VO }, FuncFlags::MACROCALL_NEW }, + { "COM.MICROSOFT.ARRAYTOTEXT", "ARRAYTOTEXT", NOID, NOID, 1, 2, V, { RO, VR }, FuncFlags::MACROCALL_NEW }, { "COM.MICROSOFT.LET", "LET", NOID, NOID, 3, MX, R, { VR, VR, VA }, FuncFlags::MACROCALL_NEW | FuncFlags::PARAMPAIRS }, + { "COM.MICROSOFT.LAMBDA", "LAMBDA", NOID, NOID, 1, MX, V, { VA }, FuncFlags::MACROCALL_NEW }, + { "COM.MICROSOFT.ISOMITTED", "ISOMITTED", NOID, NOID, 1, 1, V, { VV }, FuncFlags::MACROCALL_NEW }, + { "COM.MICROSOFT.BYCOL", "BYCOL", NOID, NOID, 2, 2, A, { VA, VV }, FuncFlags::MACROCALL_NEW | FuncFlags::VOLATILE }, + { "COM.MICROSOFT.BYROW", "BYROW", NOID, NOID, 2, 2, A, { VA, VV }, FuncFlags::MACROCALL_NEW | FuncFlags::VOLATILE }, + { "COM.MICROSOFT.MAKEARRAY", "MAKEARRAY", NOID, NOID, 3, 3, A, { VV, VV, VV }, FuncFlags::MACROCALL_NEW | FuncFlags::VOLATILE }, + { "COM.MICROSOFT.MAP", "MAP", NOID, NOID, 2, MX, A, { VA, VO }, FuncFlags::MACROCALL_NEW | FuncFlags::VOLATILE }, + { "COM.MICROSOFT.REDUCE", "REDUCE", NOID, NOID, 2, 3, V, { VV, VA, VV }, FuncFlags::MACROCALL_NEW | FuncFlags::VOLATILE }, + { "COM.MICROSOFT.SCAN", "SCAN", NOID, NOID, 2, 3, A, { VV, VA, VV }, FuncFlags::MACROCALL_NEW | FuncFlags::VOLATILE }, }; /** Functions new in Excel 2024. @@ -1200,6 +1209,7 @@ private: bool initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap& rFuncTokenMap ); bool initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, const ApiTokenMap& rExtFuncTokenMap, const FunctionInfoVector& rFuncInfos ); + bool initErrorOpCodes( const ApiTokenMap& rTokenMap ); }; OpCodeProviderImpl::OpCodeProviderImpl( const FunctionInfoVector& rFuncInfos, @@ -1269,7 +1279,10 @@ OpCodeProviderImpl::OpCodeProviderImpl( const FunctionInfoVector& rFuncInfos, // functions fillFuncTokenMaps( aTokenMap, aExtFuncTokenMap, aEntrySeq, xMapper ) && initFuncOpCodes( aTokenMap, aExtFuncTokenMap, rFuncInfos ) && - initOpCode( OPCODE_DDE, aTokenMap, "DDE", nullptr ); + initOpCode( OPCODE_DDE, aTokenMap, "DDE", nullptr ) && + // error constants + fillTokenMap( aTokenMap, aEntrySeq, xMapper, ERROR_CONSTANTS ) && + initErrorOpCodes( aTokenMap ); OSL_ENSURE( bIsValid, "OpCodeProviderImpl::OpCodeProviderImpl - opcodes not initialized" ); @@ -1449,6 +1462,18 @@ bool OpCodeProviderImpl::initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, c return bIsValid; } +bool OpCodeProviderImpl::initErrorOpCodes( const ApiTokenMap& rTokenMap ) +{ + for (const auto& [rName, rToken] : rTokenMap) + { + FormulaOpCodeMapEntry aEntry; + aEntry.Name = rName; + aEntry.Token = rToken; + maParserMap.push_back( aEntry ); + } + return true; +} + OpCodeProvider::OpCodeProvider( const Reference< XMultiServiceFactory >& rxModelFactory, bool bImportFilter ) : FunctionProvider( bImportFilter ), diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx index a781aaeb9ef6..88bb03e43aba 100644 --- a/sc/source/filter/oox/formulabuffer.cxx +++ b/sc/source/filter/oox/formulabuffer.cxx @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -24,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -33,6 +36,90 @@ using namespace ::com::sun::star::sheet; namespace oox::xls { +void stripRedundantParentheses(ScTokenArray& rArray, + std::initializer_list aTriggerOpCodes) +{ + sal_uInt16 nPosition = 0; + while (nPosition + 4 < rArray.GetLen()) + { + const OpCode eTrigger = rArray.TokenAt(nPosition)->GetOpCode(); + const bool bIsTrigger = std::find(aTriggerOpCodes.begin(), + aTriggerOpCodes.end(), + eTrigger) + != aTriggerOpCodes.end(); + if (!bIsTrigger + || rArray.TokenAt(nPosition + 1)->GetOpCode() != ocOpen + || rArray.TokenAt(nPosition + 2)->GetOpCode() != ocOpen) + { + ++nPosition; + continue; + } + // Strip only when the inner pair fully spans the wrapper's + // argument. + sal_uInt16 nDepth = 2; + for (sal_uInt16 nScan = nPosition + 3; nScan < rArray.GetLen(); ++nScan) + { + OpCode eOp = rArray.TokenAt(nScan)->GetOpCode(); + if (nDepth == 1) + { + if (eOp == ocClose) + { + rArray.RemoveToken(nScan - 1, 1); + rArray.RemoveToken(nPosition + 2, 1); + } + break; + } + if (eOp == ocOpen) + ++nDepth; + else if (eOp == ocClose) + --nDepth; + } + ++nPosition; + } +} + +// Rewrite each four-token span +// ocAnchorArray ocOpen ocClose +// to +// ocSpill +// so the parse array matches the native postfix form. Inverse of what the export does. +void liftAnchorArrayToPostfix(ScTokenArray& rArray) +{ + sal_uInt16 nPosition = 0; + while (nPosition + 1 < rArray.GetLen()) + { + if (rArray.TokenAt(nPosition)->GetOpCode() == ocAnchorArray + && rArray.TokenAt(nPosition + 1)->GetOpCode() == ocOpen) + { + // Find the parenthesis that closes the one right after the + // spill opcode, tracking nesting so a parenthesised operand + // such as ((A1)) is taken whole. + sal_uInt16 nClose = nPosition + 2; + sal_uInt16 nDepth = 1; + while (nClose < rArray.GetLen()) + { + const OpCode eInner = rArray.TokenAt(nClose)->GetOpCode(); + if (eInner == ocOpen) + ++nDepth; + else if (eInner == ocClose && --nDepth == 0) + break; + ++nClose; + } + if (nClose < rArray.GetLen()) + { + // Put the postfix operator behind the operand and drop the + // wrapper parentheses, keeping any inner ones. + rArray.ReplaceToken(nClose, new formula::FormulaByteToken(ocSpill), + formula::FormulaTokenArray::CODE_ONLY); + rArray.RemoveToken(nPosition + 1, 1); + rArray.RemoveToken(nPosition, 1); + continue; + } + } + ++nPosition; + } +} + namespace { /** @@ -120,6 +207,8 @@ void applySharedFormulas( std::unique_ptr pArray = aComp.CompileString(rTokenStr); if (pArray) { + stripRedundantParentheses(*pArray, {ocSingleValue}); + liftAnchorArrayToPostfix(*pArray); aComp.CompileTokenArray(); // Generate RPN tokens. aGroups.set(nId, std::move(pArray), aPos); } @@ -154,6 +243,9 @@ void applySharedFormulas( else pCell = new ScFormulaCell(rDoc.getDoc(), aPos, *pArray); + if (rDesc.mbDynamicArrayMaster) + pCell->SetDynamicArrayMaster(true); + rDoc.setFormulaCell(aPos, pCell); const bool bNeedNumberFormat = ((rDoc.getDoc().GetNumberFormat( aPos.Col(), aPos.Row(), aPos.Tab()) % SV_COUNTRY_LANGUAGE_OFFSET) == 0); @@ -263,6 +355,9 @@ void applyCellFormulas( else pCell = new ScFormulaCell(rDoc.getDoc(), aPos, p->mpCell->GetCode()->Clone()); + if (rItem.mbDynamicArrayMaster) + pCell->SetDynamicArrayMaster(true); + rDoc.setFormulaCell(aPos, pCell); if (rDoc.getDoc().GetNumberFormat(aPos.Col(), aPos.Row(), aPos.Tab()) % SV_COUNTRY_LANGUAGE_OFFSET == 0) pCell->SetNeedNumberFormat(true); @@ -279,9 +374,23 @@ void applyCellFormulas( if (!pCode) continue; + stripRedundantParentheses(*pCode, {ocSingleValue}); + liftAnchorArrayToPostfix(*pCode); aCompiler.CompileTokenArray(); // Generate RPN tokens. + // OOXML leaves the @ of a plain =@ref# cell out of the text, expressing it by + // keeping the cell a non-array formula, so put it back. Anything wider keeps its + // _xlfn.SINGLE, so only the bare shape qualifies: one reference and the operator, + // not even parentheses. A dynamic-array master spills instead, so it gets no @. + if (!rItem.mbDynamicArrayMaster && pCode->GetLen() == 2 + && pCode->TokenAt(0)->GetType() == formula::svSingleRef + && pCode->TokenAt(1)->GetOpCode() == ocSpill) + { + ScFormulaCell::ResolveImplicitIntersection(*pCode, rDoc.getDoc(), aPos); + } ScFormulaCell* pCell = new ScFormulaCell(rDoc.getDoc(), aPos, std::move(pCode)); + if (rItem.mbDynamicArrayMaster) + pCell->SetDynamicArrayMaster(true); rDoc.setFormulaCell(aPos, pCell); if (rDoc.getDoc().GetNumberFormat(aPos.Col(), aPos.Row(), aPos.Tab()) % SV_COUNTRY_LANGUAGE_OFFSET == 0) pCell->SetNeedNumberFormat(true); @@ -302,7 +411,38 @@ void applyArrayFormulas( aComp.SetExternalLinks(rExternalLinks); std::unique_ptr pArray(aComp.CompileString(rAddressItem.maTokenAndAddress.maTokenStr)); if (pArray) - rDoc.setMatrixCells(rAddressItem.maRange, *pArray, formula::FormulaGrammar::GRAM_OOXML); + { + stripRedundantParentheses(*pArray, {ocSingleValue}); + liftAnchorArrayToPostfix(*pArray); + + // A single-cell t="array" that starts with @ imports as + // a plain ScFormulaCell, not a CSE array. The @ collapses + // the operand to a scalar, so the cell reads back as + // =@(expr) instead of {=@(expr)}. + const sal_uInt16 nParseLength = pArray->GetLen(); + const formula::FormulaToken* pFirst = nParseLength ? pArray->GetArray()[0] : nullptr; + const bool bSingleCellRange + = rAddressItem.maRange.aStart == rAddressItem.maRange.aEnd; + if (bSingleCellRange && pFirst + && pFirst->GetOpCode() == ocSingleValue) + { + aComp.CompileTokenArray(); + ScFormulaCell* pCell = new ScFormulaCell(rDoc.getDoc(), aPos, + std::move(pArray)); + rDoc.setFormulaCell(aPos, pCell); + continue; + } + + rDoc.setMatrixCells(rAddressItem.maRange, *pArray, + formula::FormulaGrammar::GRAM_OOXML, + rAddressItem.mbCachedSpill); + if (rAddressItem.mbDynamicArrayMaster) + { + ScFormulaCell* pMaster = rDoc.getDoc().GetFormulaCell(aPos); + if (pMaster) + pMaster->SetDynamicArrayMaster(true); + } + } } } @@ -418,9 +558,14 @@ FormulaBuffer::SharedFormulaEntry::SharedFormulaEntry( maAddress(rAddr), maTokenStr(std::move(aTokenStr)), mnSharedId(nSharedId) {} FormulaBuffer::SharedFormulaDesc::SharedFormulaDesc( - const ScAddress& rAddr, sal_Int32 nSharedId, - OUString aCellValue, sal_Int32 nValueType ) : - maAddress(rAddr), maCellValue(std::move(aCellValue)), mnSharedId(nSharedId), mnValueType(nValueType) {} + const ScAddress& rAddr, sal_Int32 nSharedId, + OUString aCellValue, sal_Int32 nValueType, bool bDynamicArrayMaster) + : maAddress(rAddr) + , maCellValue(std::move(aCellValue)) + , mnSharedId(nSharedId) + , mnValueType(nValueType) + , mbDynamicArrayMaster(bDynamicArrayMaster) +{} FormulaBuffer::SheetItem::SheetItem() : mpCellFormulas(nullptr), @@ -509,25 +654,30 @@ void FormulaBuffer::createSharedFormulaMapEntry( rSharedFormulas.push_back( aEntry ); } -void FormulaBuffer::setCellFormula( const ScAddress& rAddress, const OUString& rTokenStr ) +void FormulaBuffer::setCellFormula(const ScAddress& rAddress, const OUString& rTokenStr, + bool bDynamicArrayMaster) { assert( rAddress.Tab() >= 0 && o3tl::make_unsigned(rAddress.Tab()) < maCellFormulas.size() ); - maCellFormulas[ rAddress.Tab() ].emplace_back( rTokenStr, rAddress ); + maCellFormulas[rAddress.Tab()].emplace_back(rTokenStr, rAddress, bDynamicArrayMaster); } void FormulaBuffer::setCellFormula( - const ScAddress& rAddress, sal_Int32 nSharedId, const OUString& rCellValue, sal_Int32 nValueType ) + const ScAddress& rAddress, sal_Int32 nSharedId, const OUString& rCellValue, sal_Int32 nValueType, + bool bDynamicArrayMaster) { assert( rAddress.Tab() >= 0 && o3tl::make_unsigned(rAddress.Tab()) < maSharedFormulaIds.size() ); - maSharedFormulaIds[rAddress.Tab()].emplace_back(rAddress, nSharedId, rCellValue, nValueType); + maSharedFormulaIds[rAddress.Tab()].emplace_back(rAddress, nSharedId, rCellValue, nValueType, + bDynamicArrayMaster); } -void FormulaBuffer::setCellArrayFormula( const ScRange& rRangeAddress, const ScAddress& rTokenAddress, const OUString& rTokenStr ) +void FormulaBuffer::setCellArrayFormula(const ScRange& rRangeAddress, const ScAddress& rTokenAddress, + const OUString& rTokenStr, bool bCachedSpill, + bool bDynamicArrayMaster) { TokenAddressItem tokenPair( rTokenStr, rTokenAddress ); assert( rRangeAddress.aStart.Tab() >= 0 && o3tl::make_unsigned(rRangeAddress.aStart.Tab()) < maCellArrayFormulas.size() ); - maCellArrayFormulas[ rRangeAddress.aStart.Tab() ].emplace_back( tokenPair, rRangeAddress ); + maCellArrayFormulas[rRangeAddress.aStart.Tab()].emplace_back(tokenPair, rRangeAddress, bCachedSpill, bDynamicArrayMaster); } void FormulaBuffer::setCellFormulaValue( diff --git a/sc/source/filter/oox/formulaparser.cxx b/sc/source/filter/oox/formulaparser.cxx index 398a18961715..40ab60613a0f 100644 --- a/sc/source/filter/oox/formulaparser.cxx +++ b/sc/source/filter/oox/formulaparser.cxx @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include namespace oox::xls { @@ -1458,7 +1458,7 @@ bool OoxFormulaParserImpl::importPivotToken( SequenceInputStream& rStrm ) } if( aFieldName.isEmpty() ) return pushBiffErrorOperand( BIFF_ERR_REF ); - return pushValueOperand( aFieldName, SC_OPCODE_DP_FIELD ); + return pushValueOperand( aFieldName, ocDPFieldName ); } bool OoxFormulaParserImpl::importTableToken( SequenceInputStream& rStrm ) @@ -1860,6 +1860,27 @@ OUString FormulaParser::importOleTargetLink( SequenceInputStream& rStrm ) return aTargetLink; } +bool FormulaParser::importMacroExternalRef(std::u16string_view aFormulaString, OUString& rUrl, + OUString& rName) +{ + sal_Int32 nRefId = -1; + OUString aRemainder; + if (lclExtractRefId(nRefId, aRemainder, aFormulaString) && aRemainder[0] == '!') + { + const ExternalLink* pExtLink = getExternalLinks().getExternalLink(nRefId, false).get(); + if (pExtLink) + { + rUrl = pExtLink->getTargetUrl(); + if (!rUrl.isEmpty()) + { + rName = aRemainder.copy(1); + return true; + } + } + } + return false; +} + OUString FormulaParser::importMacroName( std::u16string_view aFormulaString ) { /* Valid macros are either sheet macros or VBA macros. OOXML and all BIFF diff --git a/sc/source/filter/oox/ooxformulaparser.cxx b/sc/source/filter/oox/ooxformulaparser.cxx index bce44c008761..2ecb3333df20 100644 --- a/sc/source/filter/oox/ooxformulaparser.cxx +++ b/sc/source/filter/oox/ooxformulaparser.cxx @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -65,7 +66,7 @@ const FunctionInfo* OOXMLFormulaParserImpl::resolveBadFuncName( const OUString& call is assumed to be "'\Library\'!". */ - // the string has to start with an apostroph (followed by the library URL) + // the string has to start with an apostrophe (followed by the library URL) if( (rTokenData.getLength() >= 6) && (rTokenData[ 0 ] == '\'') ) { // library URL and function name are separated by an exclamation mark @@ -128,7 +129,7 @@ void SAL_CALL OOXMLFormulaParser::initialize( const Sequence< Any >& rArgs ) { OSL_ENSURE( rArgs.hasElements(), "OOXMLFormulaParser::initialize - missing arguments" ); if( !rArgs.hasElements() ) - throw RuntimeException(); + throw IllegalArgumentException("Initialization argument contains no elements.", static_cast(this), 0); mxComponent.set( rArgs[ 0 ], UNO_QUERY_THROW ); } @@ -157,7 +158,7 @@ OUString SAL_CALL OOXMLFormulaParser::printFormula( const Sequence< FormulaToken >& /*rTokens*/, const CellAddress& /*rReferencePos*/ ) { // not implemented - throw RuntimeException(); + throw RuntimeException("The method is not implemented.", static_cast(this)); } } // namespace oox::xls diff --git a/sc/source/filter/oox/patterncache.cxx b/sc/source/filter/oox/patterncache.cxx index 2431a36fed20..028d4c72321e 100644 --- a/sc/source/filter/oox/patterncache.cxx +++ b/sc/source/filter/oox/patterncache.cxx @@ -22,7 +22,6 @@ ScPatternCache::Entry::Entry() : nXfId(-1) , nNumFmtId(-1) - , pPattern(nullptr) { } @@ -36,7 +35,7 @@ ScPatternAttr* ScPatternCache::query(sal_Int32 nXfId, sal_Int32 nNumFmtId) const for (const auto& entry : maEntries) { if (entry.nXfId == nXfId && entry.nNumFmtId == nNumFmtId) - return entry.pPattern; + return const_cast(entry.pPattern.getScPatternAttr()); } return nullptr; @@ -48,5 +47,5 @@ void ScPatternCache::add(sal_Int32 nXfId, sal_Int32 nNumFmtId, ScPatternAttr* pP nNextPos = ((nNextPos + 1) % nPatternCacheSize); rEntry.nXfId = nXfId; rEntry.nNumFmtId = nNumFmtId; - rEntry.pPattern = pPattern; + rEntry.pPattern.setScPatternAttr(pPattern); } diff --git a/sc/source/filter/oox/personsfragment.cxx b/sc/source/filter/oox/personsfragment.cxx new file mode 100644 index 000000000000..953ee36c0dd2 --- /dev/null +++ b/sc/source/filter/oox/personsfragment.cxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 + +#include + +#include +#include +#include +#include + +namespace oox::xls +{ +PersonsFragment::PersonsFragment(const WorkbookHelper& rHelper, const OUString& rFragmentPath) + : WorkbookFragmentBase(rHelper, rFragmentPath) +{ +} + +core::ContextHandlerRef PersonsFragment::onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) +{ + switch (getCurrentElement()) + { + case core::XML_ROOT_CONTEXT: + if (nElement == XTHREADED_TOKEN(personList)) + return this; + break; + case XTHREADED_TOKEN(personList): + if (nElement == XTHREADED_TOKEN(person)) + { + ScPersonData aPerson; + aPerson.maDisplayName = rAttribs.getXString(XML_displayName, {}); + aPerson.maId = rAttribs.getXString(XML_id, {}); + aPerson.maUserId = rAttribs.getXString(XML_userId, {}); + aPerson.maProviderId = rAttribs.getXString(XML_providerId, {}); + if (!aPerson.maId.isEmpty()) + getScDocument().AddPerson(aPerson); + } + break; + } + return {}; +} + +} // namespace oox::xls + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/filter/oox/pivottablebuffer.cxx b/sc/source/filter/oox/pivottablebuffer.cxx index d66f6bb445e3..f7db92bf4e05 100644 --- a/sc/source/filter/oox/pivottablebuffer.cxx +++ b/sc/source/filter/oox/pivottablebuffer.cxx @@ -1246,9 +1246,10 @@ void PivotTable::importPTLocation( SequenceInputStream& rStrm, sal_Int16 nSheet { BinRange aBinRange; rStrm >> aBinRange; - maLocationModel.mnFirstHeaderRow = rStrm.readInt32(); - maLocationModel.mnFirstDataRow = rStrm.readInt32(); - maLocationModel.mnFirstDataCol = rStrm.readInt32(); + const BinAddress& aOrigin = aBinRange.maFirst; + maLocationModel.mnFirstHeaderRow = rStrm.readInt32() - aOrigin.mnRow; + maLocationModel.mnFirstDataRow = rStrm.readInt32() - aOrigin.mnRow; + maLocationModel.mnFirstDataCol = rStrm.readInt32() - aOrigin.mnCol; maLocationModel.mnRowPageCount = rStrm.readInt32(); maLocationModel.mnColPageCount = rStrm.readInt32(); AddressConverter::convertToCellRangeUnchecked( maLocationModel.maRange, aBinRange, nSheet ); diff --git a/sc/source/filter/oox/querytablebuffer.cxx b/sc/source/filter/oox/querytablebuffer.cxx index dc746a389eed..2557b1cf407f 100644 --- a/sc/source/filter/oox/querytablebuffer.cxx +++ b/sc/source/filter/oox/querytablebuffer.cxx @@ -34,6 +34,7 @@ #include #include #include +#include #include namespace oox::xls { @@ -279,6 +280,17 @@ QueryTable& QueryTableBuffer::createQueryTable() void QueryTableBuffer::finalizeImport() { maQueryTables.forEachMem( &QueryTable::finalizeImport ); + + // Persist QueryTableModel data on ScDocument for round-trip XLSX export + if (!maQueryTables.empty()) + { + QueryTableModelVector aModels; + aModels.reserve(maQueryTables.size()); + for (const auto& rxQueryTable : maQueryTables) + aModels.push_back( + std::make_shared(rxQueryTable->getModel())); + getScDocument().setSheetQueryTables(getSheetIndex(), std::move(aModels)); + } } } // namespace oox::xls diff --git a/sc/source/filter/oox/revisionfragment.cxx b/sc/source/filter/oox/revisionfragment.cxx index d8dc26c89505..f6e8b07e8d2b 100644 --- a/sc/source/filter/oox/revisionfragment.cxx +++ b/sc/source/filter/oox/revisionfragment.cxx @@ -142,13 +142,10 @@ protected: { // The value is a rich text string. ScDocument& rDoc = getScDocument(); - std::unique_ptr pTextObj = mxRichString->convert(rDoc.GetEditEngine(), nullptr); - if (pTextObj) - { - svl::SharedStringPool& rPool = rDoc.GetSharedStringPool(); - pTextObj->NormalizeString(rPool); - mrCellValue.set(std::move(pTextObj)); - } + EditTextObject aTextObj = mxRichString->convert(rDoc.GetEditEngine(), nullptr); + svl::SharedStringPool& rPool = rDoc.GetSharedStringPool(); + aTextObj.NormalizeString(rPool); + mrCellValue.set(std::move(aTextObj)); } } break; diff --git a/sc/source/filter/oox/richstring.cxx b/sc/source/filter/oox/richstring.cxx index 6f2a75b5f721..6a810974c8c8 100644 --- a/sc/source/filter/oox/richstring.cxx +++ b/sc/source/filter/oox/richstring.cxx @@ -405,7 +405,7 @@ OUString RichString::getStringContent() const return sString.makeStringAndClear(); } -std::unique_ptr RichString::convert( ScEditEngineDefaulter& rEE, const oox::xls::Font* pFirstPortionFont ) +EditTextObject RichString::convert( ScEditEngineDefaulter& rEE, const oox::xls::Font* pFirstPortionFont ) { ESelection aSelection; diff --git a/sc/source/filter/oox/sheetdatabuffer.cxx b/sc/source/filter/oox/sheetdatabuffer.cxx index 586e1030fb1c..c918f29b506c 100644 --- a/sc/source/filter/oox/sheetdatabuffer.cxx +++ b/sc/source/filter/oox/sheetdatabuffer.cxx @@ -354,7 +354,7 @@ void SheetDataBuffer::addColXfStyles() std::sort( s.begin(), s.end(), StyleRowRangeComp()); s.erase( std::unique( s.begin(), s.end(), [](const RowRangeStyle& lhs, const RowRangeStyle& rhs) - // Synthetize operator== from operator < . Do not create an actual operator== + // Synthesize operator== from operator < . Do not create an actual operator== // as operator< is somewhat specific (see StyleRowRangeComp). { return !StyleRowRangeComp()(lhs,rhs) && !StyleRowRangeComp()(rhs,lhs); } ), s.end()); @@ -761,7 +761,7 @@ void SheetDataBuffer::setCellFormat( const CellModel& rModel ) break; } else if (pLastRange->aStart.Row() > (rMergeRange.aEnd.Row() + 1)) - break; // Un-necessary to check with any other rows + break; // Unnecessary to check with any other rows } } // update merged ranges for 'center across selection' and 'fill' diff --git a/sc/source/filter/oox/sheetdatacontext.cxx b/sc/source/filter/oox/sheetdatacontext.cxx index 920f64dd6149..56f9d4dbb37d 100644 --- a/sc/source/filter/oox/sheetdatacontext.cxx +++ b/sc/source/filter/oox/sheetdatacontext.cxx @@ -63,6 +63,7 @@ SheetDataContext::SheetDataContext( WorksheetFragmentBase& rFragment ) : mnSheet( rFragment.getSheetIndex() ), mbHasFormula( false ), mbValidRange( false ), + mbCalcAlways( false ), mnRow( -1 ), mnCol( -1 ) { @@ -134,13 +135,24 @@ void SheetDataContext::onEndElement() // a) need to set format first // :/ case XML_normal: - setCellFormula( maCellData.maCellAddr, maFormulaStr ); - mrSheetData.setCellFormat( maCellData ); + // An empty without ca is a standalone broken formula and + // should be skipped to avoid creating a formula cell with no + // tokens. + // An empty with ca="1" is a matrix-reference placeholder + // for an array formula whose master is a different cell; the + // master will create the matrix cells via setMatrixCells. + if (!maFormulaStr.isEmpty() || mbCalcAlways) + { + setCellFormula(maCellData.maCellAddr, maFormulaStr, mbCellMetadata); + mrSheetData.setCellFormat(maCellData); - // If a number cell has some preloaded value, stick it into the buffer - // but do this only for real cell formulas (not array, shared etc.) - if (!maCellValue.isEmpty()) - setCellFormulaValue(maCellData.maCellAddr, maCellValue, maCellData.mnCellType); + // If a number cell has some preloaded value, stick it into the buffer + // but do this only for real cell formulas (not array, shared etc.) + if (!maCellValue.isEmpty()) + setCellFormulaValue(maCellData.maCellAddr, maCellValue, maCellData.mnCellType); + } + else + mbHasFormula = false; break; case XML_shared: @@ -149,7 +161,8 @@ void SheetDataContext::onEndElement() if( mbValidRange && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) ) createSharedFormulaMapEntry(maCellData.maCellAddr, maFmlaData.mnSharedId, maFormulaStr); - setCellFormula(maCellData.maCellAddr, maFmlaData.mnSharedId, maCellValue, maCellData.mnCellType); + setCellFormula(maCellData.maCellAddr, maFmlaData.mnSharedId, maCellValue, maCellData.mnCellType, + mbCellMetadata); mrSheetData.setCellFormat( maCellData ); } else @@ -159,7 +172,18 @@ void SheetDataContext::onEndElement() case XML_array: if( mbValidRange && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) ) { - setCellArrayFormula( maFmlaData.maFormulaRef, maCellData.maCellAddr, maFormulaStr ); + // A cached error on the array master signals that the file + // was saved while the dynamic array's spill range was blocked. + // The OOXML spec has no #SPILL! cell error literal, so write + // #VALUE! and reclassify via valueMetadata. + // Plumbing this through keeps the import path from writing + // reference cells over the blocker. + const bool bCachedSpill + = maCellData.mnCellType == XML_e + && mbCellMetadata + && maCellValue == u"#VALUE!"; + setCellArrayFormula(maFmlaData.maFormulaRef, maCellData.maCellAddr, maFormulaStr, + bCachedSpill, mbCellMetadata); } // set cell formatting, but do not set result as cell value mrSheetData.setBlankCell( maCellData ); @@ -346,6 +370,11 @@ bool SheetDataContext::importCell( const AttributeList& rAttribs ) maCellData.mnCellType = rAttribs.getToken( XML_t, XML_n ); maCellData.mnXfId = rAttribs.getInteger( XML_s, -1 ); maCellData.mbShowPhonetic = rAttribs.getBool( XML_ph, false ); + // cm attribute marks a dynamic array master cell that points at a + // cellMetadata block in xl/metadata.xml. The actual metadata index + // is irrelevant for us currently - we only need to know it's a dynamic + // array master. + mbCellMetadata = rAttribs.getInteger(XML_cm, 0) > 0; // reset cell value, formula settings, and inline string maCellValue.clear(); @@ -365,6 +394,7 @@ void SheetDataContext::importFormula( const AttributeList& rAttribs ) maFmlaData.mnFormulaType = rAttribs.getToken( XML_t, XML_normal ); maFmlaData.mnSharedId = rAttribs.getInteger( XML_si, -1 ); + mbCalcAlways = rAttribs.getBool( XML_ca, false ); if( maFmlaData.mnFormulaType == XML_dataTable ) { diff --git a/sc/source/filter/oox/stylesbuffer.cxx b/sc/source/filter/oox/stylesbuffer.cxx index 83a34f5dc41a..0eff19e12fa0 100644 --- a/sc/source/filter/oox/stylesbuffer.cxx +++ b/sc/source/filter/oox/stylesbuffer.cxx @@ -658,14 +658,6 @@ void Font::importAttribs( sal_Int32 nElement, const AttributeList& rAttribs ) } } -void Font::setFontElements(const XlsColor& rColor, bool bWeight) -{ - maModel.maColor = rColor; - maUsedFlags.mbColorUsed = true; - maModel.mbBold = bWeight; - maUsedFlags.mbWeightUsed = true; -} - void Font::importFont( SequenceInputStream& rStrm ) { SAL_WARN_IF( mbDxf, "sc", "Font::importFont - unexpected conditional formatting flag" ); @@ -1593,16 +1585,6 @@ void Border::importDxfBorder( sal_Int32 nElement, SequenceInputStream& rStrm ) } } -void Border::setBorderElement( sal_Int32 nElement, const XlsColor& rColor, sal_Int32 nStyle) -{ - if( BorderLineModel* pBorderLine = getBorderLine( nElement ) ) - { - pBorderLine->maColor = rColor; - pBorderLine->mnStyle = nStyle; - pBorderLine->mbUsed = true; - } -} - void Border::finalizeImport( bool bRTL ) { if (bRTL) @@ -1993,19 +1975,6 @@ void Fill::importDxfStop( SequenceInputStream& rStrm ) mxGradientModel->readGradientStop( rStrm, true ); } -void Fill::setFillColors(const XlsColor& rFgColor, const XlsColor& rBgColor) -{ - mxPatternModel = std::make_shared(true); - mxPatternModel->mnPattern = XML_solid; - mxPatternModel->mbPatternUsed = true; - - mxPatternModel->maPatternColor = rFgColor; - mxPatternModel->mbPattColorUsed = true; - - mxPatternModel->maFillColor = rBgColor; - mxPatternModel->mbFillColorUsed = true; -} - void Fill::finalizeImport() { const GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper(); @@ -2158,7 +2127,7 @@ void Xf::importXf( const AttributeList& rAttribs, bool bCellXf ) { maModel.mbCellXf = bCellXf; // tdf#70565 Set proper default value to "0" of xfId attribute - // When xfId is not exist during .xlsx import + // When xfId does not exist during .xlsx import // it must have values set to "0". // This doesn't impact spreadsheets created with MS Excel, // as xfId attribute is always created during export to .xlsx @@ -2484,6 +2453,14 @@ FillRef const & Dxf::createFill( bool bAlwaysNew ) return mxFill; } +// tdf#122473 - import alignment and axis-based pivot area formats +AlignmentRef const& Dxf::createAlignment(bool bAlwaysNew) +{ + if (bAlwaysNew || !mxAlignment) + mxAlignment = std::make_shared(*this); + return mxAlignment; +} + ProtectionRef const & Dxf::createProtection( bool bAlwaysNew ) { if ( bAlwaysNew || !mxProtection ) @@ -2491,21 +2468,6 @@ ProtectionRef const & Dxf::createProtection( bool bAlwaysNew ) return mxProtection; } -void Dxf::setFill(const FillRef& xFill) -{ - mxFill = xFill; -} - -void Dxf::setBorder(const BorderRef& xBorder) -{ - mxBorder = xBorder; -} - -void Dxf::setFont(const FontRef& xFont) -{ - mxFont = xFont; -} - void Dxf::importNumFmt( const AttributeList& rAttribs ) { // don't propagate number formats defined in Dxf entries @@ -2622,11 +2584,6 @@ void TableStyle::setName(const OUString& rName) maName = rName; } -void TableStyle::setUIName(const OUString& rName) -{ - maUIName = rName; -} - void TableStyle::importTableStyleElement(const AttributeList& rAttribs) { TableStyleElementInfo aInfo; @@ -2658,13 +2615,6 @@ void TableStyle::importTableStyleElement(const AttributeList& rAttribs) maTableStyleElements.insert({eElement, aInfo}); } -void TableStyle::setTableStyleElement(ScTableStyleElement eElement, sal_Int32 nDxfId) -{ - TableStyleElementInfo aInfo; - aInfo.mnDxfID = nDxfId; - maTableStyleElements.insert({eElement, aInfo}); -} - void TableStyle::finalizeImport(const DxfVector& rDxfs) { ::ScDocument& rDoc = getScDocument(); diff --git a/sc/source/filter/oox/stylesfragment.cxx b/sc/source/filter/oox/stylesfragment.cxx index c738016029c3..e4f04c7beedf 100644 --- a/sc/source/filter/oox/stylesfragment.cxx +++ b/sc/source/filter/oox/stylesfragment.cxx @@ -149,9 +149,8 @@ ContextHandlerRef DxfContext::onCreateContext( sal_Int32 nElement, const Attribu case XLS_TOKEN( fill ): return new FillContext( *this, mxDxf->createFill() ); case XLS_TOKEN( numFmt ): mxDxf->importNumFmt( rAttribs ); break; -#if 0 - case XLS_TOKEN( alignment ): mxDxf->importAlignment( rAttribs ); break; -#endif + // tdf#122473 - import alignment and axis-based pivot area formats + case XLS_TOKEN(alignment): mxDxf->createAlignment()->importAlignment(rAttribs); break; case XLS_TOKEN( protection ): mxDxf->createProtection()->importProtection( rAttribs ); break; } break; @@ -163,6 +162,8 @@ ContextHandlerRef DxfContext::onCreateContext( sal_Int32 nElement, const Attribu case XLS_TOKEN( border ): return new BorderContext( *this, mxDxf->createBorder() ); case XLS_TOKEN( fill ): return new FillContext( *this, mxDxf->createFill() ); case XLS_TOKEN( numFmt ): mxDxf->importNumFmt( rAttribs ); break; + // tdf#122473 - import alignment and axis-based pivot area formats + case XLS_TOKEN(alignment): mxDxf->createAlignment()->importAlignment(rAttribs); break; case XLS_TOKEN( protection ): mxDxf->createProtection()->importProtection( rAttribs ); break; } break; diff --git a/sc/source/filter/oox/tablebuffer.cxx b/sc/source/filter/oox/tablebuffer.cxx index cdbdf1da7fa1..c1c55a89c020 100644 --- a/sc/source/filter/oox/tablebuffer.cxx +++ b/sc/source/filter/oox/tablebuffer.cxx @@ -200,7 +200,8 @@ void Table::applyAutoFilters() void Table::applyTableColumns() { - maTableColumns.finalizeImport( findDatabaseRangeByIndex( mnTokenIndex )); + maTableColumns.finalizeImport(findDatabaseRangeByIndex(mnTokenIndex), + maModel.mnType == XML_queryTable); } TableBuffer::TableBuffer( const WorkbookHelper& rHelper ) : diff --git a/sc/source/filter/oox/tablecolumnsbuffer.cxx b/sc/source/filter/oox/tablecolumnsbuffer.cxx index c93f49e2b171..eb427e77b926 100644 --- a/sc/source/filter/oox/tablecolumnsbuffer.cxx +++ b/sc/source/filter/oox/tablecolumnsbuffer.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include XmlColumnPrModel::XmlColumnPrModel() : @@ -55,7 +56,7 @@ TableColumn::TableColumn( const WorkbookHelper& rHelper ) : void TableColumn::importTableColumn( const AttributeList& rAttribs ) { mnId = rAttribs.getInteger( XML_id, -1 ); - maName = rAttribs.getString( XML_name, OUString() ); + maName = rAttribs.getXString( XML_name, OUString() ); maModel.maUniqueName = rAttribs.getXString( XML_uniqueName, OUString() ); mnDataDxfId = rAttribs.getInteger( XML_dataDxfId, -1 ); if ( rAttribs.hasAttribute(XML_totalsRowLabel ) ) @@ -136,7 +137,7 @@ TableColumn& TableColumns::createTableColumn() #pragma GCC diagnostic pop #endif -bool TableColumns::finalizeImport( ScDBData* pDBData ) +bool TableColumns::finalizeImport( ScDBData* pDBData, bool bQueryTable ) { SAL_WARN_IF( static_cast(mnCount) != maTableColumnVector.size(), "sc.filter", "TableColumns::finalizeImport - count attribute doesn't match number of tableColumn elements"); @@ -167,6 +168,27 @@ bool TableColumns::finalizeImport( ScDBData* pDBData ) } pDBData->SetTableColumnNames( std::move(aNames) ); + // If table type is "queryTable" and `removeDataOnSave` attribute is set to true, + // Excel removes table data from sheet, including headers. + // We don't support Power Query connections, so fill table headers in the sheet with table data. + if (bQueryTable && pDBData->HasHeader()) + { + ScRange aRange; + pDBData->GetArea(aRange); + ScDocument& rDoc = getScDocument(); + const std::vector& rNames = pDBData->GetTableColumnNames(); + SCCOL nStartCol = aRange.aStart.Col(); + SCROW nRow = aRange.aStart.Row(); + SCTAB nTab = aRange.aStart.Tab(); + for (size_t j = 0; j < rNames.size(); ++j) + { + SCCOL nCol = nStartCol + static_cast(j); + OUString sHeader = rNames[j]; + if (!sHeader.isEmpty() && rDoc.GetString(nCol, nRow, nTab).isEmpty()) + rDoc.SetString(nCol, nRow, nTab, sHeader); + } + } + // Import subtotal parameters for columns if (hasAnySetValue) { @@ -194,11 +216,11 @@ TableColumns& TableColumnsBuffer::createTableColumns() return *xTableColumns; } -void TableColumnsBuffer::finalizeImport( ScDBData* pDBData ) +void TableColumnsBuffer::finalizeImport( ScDBData* pDBData, bool bQueryTable ) { TableColumns* pTableColumns = getActiveTableColumns(); if ( pTableColumns ) - pTableColumns->finalizeImport( pDBData ); + pTableColumns->finalizeImport( pDBData, bQueryTable ); } TableColumns* TableColumnsBuffer::getActiveTableColumns() diff --git a/sc/source/filter/oox/threadedcommentsfragment.cxx b/sc/source/filter/oox/threadedcommentsfragment.cxx new file mode 100644 index 000000000000..97a55de95105 --- /dev/null +++ b/sc/source/filter/oox/threadedcommentsfragment.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 + +#include + +#include +#include +#include +#include +#include + +#include + +namespace oox::xls +{ +ThreadedCommentsFragment::ThreadedCommentsFragment(const WorksheetHelper& rHelper, + const OUString& rFragmentPath) + : WorksheetFragmentBase(rHelper, rFragmentPath) +{ +} + +core::ContextHandlerRef ThreadedCommentsFragment::onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) +{ + switch (getCurrentElement()) + { + case core::XML_ROOT_CONTEXT: + if (nElement == XTHREADED_TOKEN(ThreadedComments)) + return this; + break; + case XTHREADED_TOKEN(ThreadedComments): + if (nElement == XTHREADED_TOKEN(threadedComment)) + { + mpCurrentEntry = &maEntries.emplace_back(); + mpCurrentEntry->maRef = rAttribs.getXString(XML_ref, {}); + mpCurrentEntry->maId = rAttribs.getXString(XML_id, {}); + mpCurrentEntry->maPersonId = rAttribs.getXString(XML_personId, {}); + mpCurrentEntry->maDateTime = rAttribs.getXString(XML_dT, {}); + mpCurrentEntry->maParentId = rAttribs.getXString(XML_parentId, {}); + mpCurrentEntry->mbDone = rAttribs.getBool(XML_done, false); + return this; + } + break; + case XTHREADED_TOKEN(threadedComment): + if (nElement == XTHREADED_TOKEN(text)) + return this; // collect text in onCharacters() + break; + } + return {}; +} + +void ThreadedCommentsFragment::onCharacters(const OUString& rChars) +{ + if (isCurrentElement(XTHREADED_TOKEN(text)) && mpCurrentEntry) + mpCurrentEntry->maText += rChars; +} + +void ThreadedCommentsFragment::onEndElement() +{ + if (isCurrentElement(XTHREADED_TOKEN(threadedComment))) + mpCurrentEntry = nullptr; + else if (isCurrentElement(XTHREADED_TOKEN(ThreadedComments))) + attachToNotes(); +} + +void ThreadedCommentsFragment::attachToNotes() +{ + ScDocument& rDoc = getScDocument(); + + // Separate root comments from replies. Excel uses flat threads: all replies + // reference the root comment's id in their parentId. Nested replies (where a + // reply references another reply) are not supported by Excel and are ignored here. + std::map aRootById; + std::map> aRepliesByParentId; + + for (auto& rEntry : maEntries) + { + if (rEntry.maParentId.isEmpty()) + aRootById[rEntry.maId] = &rEntry; + else + aRepliesByParentId[rEntry.maParentId].push_back(&rEntry); + } + + // For each root entry, find the matching ScPostIt and attach threaded data. + for (auto & [ rId, pRoot ] : aRootById) + { + // Convert cell reference to address. + ScRange aRange; + AddressConverter::convertToCellRangeUnchecked(aRange, pRoot->maRef, getSheetIndex(), rDoc); + ScPostIt* pNote = rDoc.GetNote(aRange.aStart); + if (!pNote) + continue; // Match Excel: threaded comment without a legacy comment is ignored + + auto pData = std::make_unique(); + pData->maRoot.maGuid = pRoot->maId; + pData->maRoot.maPersonId = pRoot->maPersonId; + pData->maRoot.maDateTime = pRoot->maDateTime; + pData->maRoot.maText = pRoot->maText; + pData->mbDone = pRoot->mbDone; + + // Attach replies. + auto itReplies = aRepliesByParentId.find(rId); + if (itReplies != aRepliesByParentId.end()) + { + for (const auto* pReply : itReplies->second) + { + ScThreadedCommentEntry aReplyEntry; + aReplyEntry.maGuid = pReply->maId; + aReplyEntry.maPersonId = pReply->maPersonId; + aReplyEntry.maDateTime = pReply->maDateTime; + aReplyEntry.maText = pReply->maText; + pData->maReplies.push_back(std::move(aReplyEntry)); + } + } + + // Replace the legacy placeholder author (tc={guid}) with the actual person name. + const ScPersonData* pPerson = rDoc.GetPersonById(pRoot->maPersonId); + if (pPerson) + pNote->SetAuthor(pPerson->maDisplayName); + + pNote->SetThreadedCommentData(std::move(pData)); + } +} + +} // namespace oox::xls + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/filter/oox/unitconverter.cxx b/sc/source/filter/oox/unitconverter.cxx index 3b5e7e30e118..6f435ab7f682 100644 --- a/sc/source/filter/oox/unitconverter.cxx +++ b/sc/source/filter/oox/unitconverter.cxx @@ -107,6 +107,7 @@ UnitConverter::UnitConverter( const WorkbookHelper& rHelper ) : addErrorCode( BIFF_ERR_NAME, u"#NAME?"_ustr ); addErrorCode( BIFF_ERR_NUM, u"#NUM!"_ustr ); addErrorCode( BIFF_ERR_NA, u"#N/A"_ustr ); + addErrorCode( BIFF_ERR_SPILL, u"#SPILL!"_ustr ); } void UnitConverter::finalizeImport() diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx index f42dc199353c..83aed2a89169 100644 --- a/sc/source/filter/oox/workbookfragment.cxx +++ b/sc/source/filter/oox/workbookfragment.cxx @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -58,14 +59,16 @@ #include #include #include -#include +#include +#include #include #include #include #include +#include #include -#include +#include #include #include @@ -338,7 +341,7 @@ void importSheetFragments( WorkbookFragment& rWorkbookHandler, SheetFragmentVect nSheetsLeft++; } -#if defined EMSCRIPTEN && !HAVE_EMSCRIPTEN_JSPI +#if defined __EMSCRIPTEN__ && !HAVE_EMSCRIPTEN_JSPI // Hack around Application::Yield() deliberately calling std::abort() in the standard (non-JSPI) // Emscripten case; so instead of yielding (which implicitly releases the SolarMutex), just // release the SolarMutex so that the WorkerThreads can proceed: @@ -347,7 +350,7 @@ void importSheetFragments( WorkbookFragment& rWorkbookHandler, SheetFragmentVect // coverity[loop_top] - this isn't an infinite loop where nSheetsLeft gets decremented by the above threads while( nSheetsLeft > 0 && !Application::IsQuit()) { - // This is a much more controlled re-enterancy hazard than + // This is a much more controlled re-entrancy hazard than // allowing a yield deeper inside the filter code for progress // bar updating. Application::Yield(); @@ -379,8 +382,10 @@ void WorkbookFragment::finalizeImport() importOoxFragment(new ThemeFragmentHandler(getFilter(), aThemeFragmentPath, rOoxTheme, *pTheme)); xGlobalSegment->setPosition( 0.25 ); - DefaultOOXMLTableStyles aTableStyles(*this); - aTableStyles.importTableStyles(); + // Generate default table styles from the ECMA-376 spec data, + // resolving theme-relative colors against the document's theme. + if (pTheme && pTheme->getColorSet()) + ScTableStyleGenerator::generateDefaultStyles(getScDocument(), *pTheme->getColorSet()); // read the styles substream (requires finalized theme buffer) OUString aStylesFragmentPath = getFragmentPathFromFirstTypeFromOfficeDoc( u"styles" ); @@ -395,6 +400,12 @@ void WorkbookFragment::finalizeImport() importOoxFragment(new SharedStringsFragment(*this, aSstFragmentPath.replaceFirst("sharedStrings","SharedStrings"))); xGlobalSegment->setPosition( 0.75 ); + // read the persons substream (for threaded comments) + OUString aPersonsFragmentPath = getFragmentPathFromFirstType( + u"http://schemas.microsoft.com/office/2017/10/relationships/person"); + if (!aPersonsFragmentPath.isEmpty()) + importOoxFragment(new PersonsFragment(*this, aPersonsFragmentPath)); + // read the connections substream OUString aConnFragmentPath = getFragmentPathFromFirstTypeFromOfficeDoc( u"connections" ); if( !aConnFragmentPath.isEmpty() ) @@ -476,7 +487,7 @@ void WorkbookFragment::finalizeImport() (pRelation->maType == CREATE_MSOFFICE_RELATION_TYPE( "xlIntlMacrosheet" )) ) eSheetType = WorksheetType::Macro; else if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "dialogsheet" ) || - pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE_STRICT(" dialogsheet" )) + pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE_STRICT("dialogsheet" )) eSheetType = WorksheetType::Dialog; OSL_ENSURE( eSheetType != WorksheetType::Empty, "WorkbookFragment::finalizeImport - unknown sheet type" ); if( eSheetType != WorksheetType::Empty ) @@ -568,6 +579,12 @@ void WorkbookFragment::finalizeImport() pHelper->finalizeDrawingImport(); } + // Create sheet view tabs as late as possible. + for (WorksheetHelper* pHelper : aHelpers) + { + pHelper->finalizeNamedSheetViews(); + } + for( auto& [rxSheetGlob, rxFragment] : aSheetFragments ) { // delete fragment object and WorkbookGlobals object, will free all allocated sheet buffers diff --git a/sc/source/filter/oox/workbookhelper.cxx b/sc/source/filter/oox/workbookhelper.cxx index 1b9e2ed4617a..fe0226d97124 100644 --- a/sc/source/filter/oox/workbookhelper.cxx +++ b/sc/source/filter/oox/workbookhelper.cxx @@ -159,7 +159,7 @@ public: Reference< XStyle > getStyleObject( const OUString& rStyleName, bool bPageStyle ) const; /** Creates and returns a defined name on-the-fly in the Calc document. */ WorkbookHelper::RangeDataRet createNamedRangeObject(OUString& orName, sal_Int32 nIndex, sal_Int32 nNameFlags); - /** Creates and returns a defined name on the-fly in the correct Calc sheet. */ + /** Creates and returns a defined name on-the-fly in the correct Calc sheet. */ WorkbookHelper::RangeDataRet createLocalNamedRangeObject(OUString& orName, sal_Int32 nIndex, sal_Int32 nNameFlags, sal_Int32 nTab); /** Creates and returns a database range on-the-fly in the Calc document. */ rtl::Reference createDatabaseRangeObject( OUString& orName, const ScRange& rRangeAddr ); @@ -369,9 +369,8 @@ Reference< XStyle > WorkbookGlobals::getStyleObject( const OUString& rStyleName, namespace { -WorkbookHelper::RangeDataRet lcl_addNewByName(ScDocument& rDoc, ScRangeName* pNames, const OUString& rName, sal_Int16 nIndex, sal_Int32 nUnoType) +WorkbookHelper::RangeDataRet lcl_addNewByName(ScDocument& rDoc, ScRangeName& rNames, const OUString& rName, sal_Int16 nIndex, sal_Int32 nUnoType) { - bool bDone = false; ScRangeData::Type nNewType = ScRangeData::Type::Name; if ( nUnoType & NamedRangeFlag::FILTER_CRITERIA ) nNewType |= ScRangeData::Type::Criteria; if ( nUnoType & NamedRangeFlag::PRINT_AREA ) nNewType |= ScRangeData::Type::PrintArea; @@ -379,7 +378,7 @@ WorkbookHelper::RangeDataRet lcl_addNewByName(ScDocument& rDoc, ScRangeName* pNa if ( nUnoType & NamedRangeFlag::ROW_HEADER ) nNewType |= ScRangeData::Type::RowHeader; if ( nUnoType & NamedRangeFlag::HIDDEN ) nNewType |= ScRangeData::Type::Hidden; ScTokenArray aTokenArray(rDoc); - ScRangeData* pNew = new ScRangeData(rDoc, rName, aTokenArray, ScAddress(), nNewType); + std::unique_ptr pNew(new ScRangeData(rDoc, rName, aTokenArray, ScAddress(), nNewType)); pNew->GuessPosition(); if ( nIndex ) pNew->SetIndex( nIndex ); @@ -387,23 +386,19 @@ WorkbookHelper::RangeDataRet lcl_addNewByName(ScDocument& rDoc, ScRangeName* pNa if (((nUnoType & NamedRangeFlag::HIDDEN) == NamedRangeFlag::HIDDEN) && ((nUnoType & NamedRangeFlag::FILTER_CRITERIA) == NamedRangeFlag::FILTER_CRITERIA)) { - return WorkbookHelper::RangeDataRet(pNew, true); + return WorkbookHelper::RangeDataRet(pNew.release(), true); } - if ( pNames->insert(pNew) ) - bDone = true; - if (!bDone) - { - delete pNew; + ScRangeData* pInserted = rNames.insert(std::move(pNew)); + if (!pInserted) throw RuntimeException(); - } - return WorkbookHelper::RangeDataRet(pNew, false); + return WorkbookHelper::RangeDataRet(pInserted, false); } -OUString findUnusedName( const ScRangeName* pRangeName, const OUString& rSuggestedName ) +OUString findUnusedName( const ScRangeName& rRangeName, const OUString& rSuggestedName ) { OUString aNewName = rSuggestedName; sal_Int32 nIndex = 0; - while(pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(aNewName))) + while(rRangeName.findByUpperName(ScGlobal::getCharClass().uppercase(aNewName))) aNewName = rSuggestedName + OUStringChar('_') + OUString::number( nIndex++ ); return aNewName; @@ -419,11 +414,11 @@ WorkbookHelper::RangeDataRet WorkbookGlobals::createNamedRangeObject( if( !orName.isEmpty() ) { ScDocument& rDoc = getScDocument(); - ScRangeName* pNames = rDoc.GetRangeName(); + ScRangeName& rNames = rDoc.GetRangeName(); // find an unused name - orName = findUnusedName( pNames, orName ); + orName = findUnusedName( rNames, orName ); // create the named range - aScRangeData = lcl_addNewByName(rDoc, pNames, orName, nIndex, nNameFlags); + aScRangeData = lcl_addNewByName(rDoc, rNames, orName, nIndex, nNameFlags); } return aScRangeData; } @@ -440,9 +435,9 @@ WorkbookHelper::RangeDataRet WorkbookGlobals::createLocalNamedRangeObject( if(!pNames) throw RuntimeException(u"invalid sheet index used"_ustr); // find an unused name - orName = findUnusedName( pNames, orName ); + orName = findUnusedName( *pNames, orName ); // create the named range - aScRangeData = lcl_addNewByName(rDoc, pNames, orName, nIndex, nNameFlags); + aScRangeData = lcl_addNewByName(rDoc, *pNames, orName, nIndex, nNameFlags); } return aScRangeData; } @@ -464,13 +459,8 @@ rtl::Reference WorkbookGlobals::createDatabaseRangeObject( O while (pNames && pNames->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(aNewName)) != nullptr ) aNewName = orName + OUStringChar('_') + OUString::number( nIndex++ ); orName = aNewName; - // create the database range - CellRangeAddress aApiRange( aDestRange.aStart.Tab(), aDestRange.aStart.Col(), aDestRange.aStart.Row(), - aDestRange.aEnd.Col(), aDestRange.aEnd.Row() ); ScDBDocFunc aFunc(*pDocSh); - ScRange aNameRange( static_cast(aApiRange.StartColumn), static_cast(aApiRange.StartRow), aApiRange.Sheet, - static_cast(aApiRange.EndColumn), static_cast(aApiRange.EndRow), aApiRange.Sheet ); - if(!( aFunc.AddDBRange( orName, aNameRange ) )) + if(!( aFunc.AddDBRange( orName, aDestRange ) )) throw RuntimeException(u"Could not add database range"_ustr); return new ScDatabaseRangeObj(pDocSh, orName); } diff --git a/sc/source/filter/oox/workbooksettings.cxx b/sc/source/filter/oox/workbooksettings.cxx index f84c613d55a8..6961cb61e431 100644 --- a/sc/source/filter/oox/workbooksettings.cxx +++ b/sc/source/filter/oox/workbooksettings.cxx @@ -80,7 +80,7 @@ WorkbookSettingsModel::WorkbookSettingsModel() : mnUpdateLinksMode( XML_userSet ), mnDefaultThemeVer( -1 ), mbDateMode1904( false ), - mbDateCompatibility ( false ), + mbDateCompatibility( false ), mbSaveExtLinkValues( true ) { } @@ -286,7 +286,7 @@ sal_Int16 WorkbookSettings::getApiShowObjectMode() const css::util::Date const & WorkbookSettings::getNullDate() const { - // Excel (inacurrately) treats Feb 29, 1900 as a valid date (for compatibility with Lotus). + // Excel (inaccurately) treats Feb 29, 1900 as a valid date (for compatibility with Lotus). // AFAICS, only Strict .xlsx treats that date as invalid // (regardless of whether dateCompatibility="0" or "1"). // Thus the only purpose of dateCompatibility="1" is to determine the oldest recognizable date diff --git a/sc/source/filter/oox/worksheetbuffer.cxx b/sc/source/filter/oox/worksheetbuffer.cxx index 241474359f44..1ebd8f6b2a64 100644 --- a/sc/source/filter/oox/worksheetbuffer.cxx +++ b/sc/source/filter/oox/worksheetbuffer.cxx @@ -23,14 +23,10 @@ #include -#include -#include -#include #include #include #include #include -#include #include #include #include @@ -38,14 +34,9 @@ #include #include #include -#include namespace oox::xls { -using namespace ::com::sun::star::container; -using namespace ::com::sun::star::sheet; -using namespace ::com::sun::star::uno; - SheetInfoModel::SheetInfoModel() : mnSheetId( -1 ), mnState( XML_visible ) @@ -187,40 +178,38 @@ WorksheetBuffer::SheetInfo::SheetInfo( const SheetInfoModel& rModel, sal_Int16 n WorksheetBuffer::IndexNamePair WorksheetBuffer::createSheet( const OUString& rPreferredName, sal_Int32 nSheetPos ) { - //FIXME: Rewrite this block using ScDocument[Import] instead of UNO - try + ScDocument& rDoc = getScDocument(); + sal_Int16 nCalcSheet = -1; + OUString aSheetName = rPreferredName.isEmpty() ? ScResId(STR_TABLE_DEF) : rPreferredName; + if( nSheetPos < rDoc.GetTableCount() ) { - Reference< XSpreadsheets > xSheets( getDocument()->getSheets(), UNO_SET_THROW ); - Reference< XIndexAccess > xSheetsIA( xSheets, UNO_QUERY_THROW ); - sal_Int16 nCalcSheet = -1; - OUString aSheetName = rPreferredName.isEmpty() ? ScResId(STR_TABLE_DEF) : rPreferredName; - if( nSheetPos < xSheetsIA->getCount() ) + nCalcSheet = static_cast< sal_Int16 >( nSheetPos ); + // existing sheet - try to rename + OUString aOldName; + if( rDoc.GetName(nCalcSheet, aOldName) && aOldName != aSheetName ) { - nCalcSheet = static_cast< sal_Int16 >( nSheetPos ); - // existing sheet - try to rename - Reference< XNamed > xSheetName( xSheetsIA->getByIndex( nSheetPos ), UNO_QUERY_THROW ); - if( xSheetName->getName() != aSheetName ) + rDoc.CreateValidTabName(aSheetName); + if(!rDoc.RenameTab(nCalcSheet, aSheetName)) { - aSheetName = ContainerHelper::getUnusedName( xSheets, aSheetName, ' ' ); - xSheetName->setName( aSheetName ); + OSL_FAIL( "WorksheetBuffer::createSheet - cannot rename worksheet" ); + return IndexNamePair(-1, OUString()); } } - else - { - nCalcSheet = static_cast< sal_Int16 >( xSheetsIA->getCount() ); - // new sheet - insert with unused name - aSheetName = ContainerHelper::getUnusedName( xSheets, aSheetName, ' ' ); - xSheets->insertNewByName( aSheetName, nCalcSheet ); - } - - // return final sheet index if sheet exists - return IndexNamePair( nCalcSheet, aSheetName ); } - catch (const Exception&) + else { - OSL_FAIL( "WorksheetBuffer::createSheet - cannot insert or rename worksheet" ); + nCalcSheet = static_cast< sal_Int16 >( rDoc.GetTableCount() ); + // new sheet - insert with unused name + rDoc.CreateValidTabName(aSheetName); + if(!rDoc.InsertTab(nCalcSheet, aSheetName)) + { + OSL_FAIL( "WorksheetBuffer::createSheet - cannot insert worksheet" ); + return IndexNamePair(-1, OUString()); + } } - return IndexNamePair( -1, OUString() ); + + // return final sheet index if sheet exists + return IndexNamePair( nCalcSheet, aSheetName ); } void WorksheetBuffer::insertSheet( const SheetInfoModel& rModel ) diff --git a/sc/source/filter/oox/worksheetfragment.cxx b/sc/source/filter/oox/worksheetfragment.cxx index 0b31247bfdae..96b120e6922f 100644 --- a/sc/source/filter/oox/worksheetfragment.cxx +++ b/sc/source/filter/oox/worksheetfragment.cxx @@ -43,6 +43,7 @@ #include #include #include +#include namespace oox::xls { @@ -347,6 +348,16 @@ WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUSt OUString aCommentsFragmentPath = getFragmentPathFromFirstTypeFromOfficeDoc( u"comments" ); if( !aCommentsFragmentPath.isEmpty() ) importOoxFragment( new CommentsFragment( *this, aCommentsFragmentPath ) ); + + OUString aNamedSheetViewPath = getFragmentPathFromFirstType(u"http://schemas.microsoft.com/office/2019/04/relationships/namedSheetView"); + if (!aNamedSheetViewPath.isEmpty()) + importOoxFragment(new oox::xls::nsv::NamedSheetViewFragment(*this, aNamedSheetViewPath)); + + // store threaded comments path for later (imported after comments are finalized) + OUString aThreadedCommentsPath = getFragmentPathFromFirstType( + u"http://schemas.microsoft.com/office/2017/10/relationships/threadedComment"); + if (!aThreadedCommentsPath.isEmpty()) + setThreadedCommentsPath(aThreadedCommentsPath); } ContextHandlerRef WorksheetFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) diff --git a/sc/source/filter/oox/worksheethelper.cxx b/sc/source/filter/oox/worksheethelper.cxx index 5734bfd8ea24..4d64e556ac33 100644 --- a/sc/source/filter/oox/worksheethelper.cxx +++ b/sc/source/filter/oox/worksheethelper.cxx @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ #include #include #include +#include #include #include @@ -270,6 +272,12 @@ public: /** returns the ExtLst entries that need to be filled */ ExtLst& getExtLst() { return maExtLst; } + /** Sets the named sheet views data for this sheet. */ + void setNamedSheetViews(std::vector&& rData) + { + maNamedSheetViewImporter.setNamedSheetViews(std::move(rData)); + } + /** Sets a column or row page break described in the passed struct. */ void setPageBreak( const PageBreakModel& rModel, bool bRowBreak ); /** Inserts the hyperlink URL into the spreadsheet. */ @@ -280,6 +288,8 @@ public: void setDrawingPath( const OUString& rDrawingPath ); /** Sets the path to the legacy VML drawing fragment of this sheet. */ void setVmlDrawingPath( const OUString& rVmlDrawingPath ); + /** Sets the path to the threaded comments fragment of this sheet. */ + void setThreadedCommentsPath( const OUString& rPath ); /** Extends the used area of this sheet by the passed cell position. */ void extendUsedArea( const ScAddress& rAddress ); @@ -316,6 +326,9 @@ public: void finalizeDrawingImport(); + /** Creates sheet views from imported named sheet view data and applies filters/sort. */ + void finalizeNamedSheetViews(); + /// Allow the threaded importer to override our progress bar impl. virtual ISegmentProgressBarRef getRowProgress() override { @@ -389,8 +402,10 @@ private: SheetViewSettings maSheetViewSett; /// View settings for this sheet. VmlDrawingPtr mxVmlDrawing; /// Collection of all VML shapes. ExtLst maExtLst; /// List of extended elements + nsv::NamedSheetViewImporter maNamedSheetViewImporter; /// Named sheet view importer. OUString maDrawingPath; /// Path to DrawingML fragment. OUString maVmlDrawingPath; /// Path to legacy VML drawing fragment. + OUString maThreadedCommentsPath; /// Path to threaded comments fragment. awt::Size maDrawPageSize; /// Current size of the drawing page in 1/100 mm. awt::Rectangle maShapeBoundingBox; /// Bounding box for all shapes from all drawings. ISegmentProgressBarRef mxProgressBar; /// Sheet progress bar. @@ -414,6 +429,7 @@ WorksheetGlobals::WorksheetGlobals( const WorkbookHelper& rHelper, ISegmentProgr maSheetSett( *this ), maPageSett( *this ), maSheetViewSett( *this ), + maNamedSheetViewImporter(*this, nSheet), mxProgressBar(std::move( xProgressBar )), mbFastRowProgress( false ), meSheetType( eSheetType ), @@ -683,6 +699,11 @@ void WorksheetGlobals::setVmlDrawingPath( const OUString& rVmlDrawingPath ) maVmlDrawingPath = rVmlDrawingPath; } +void WorksheetGlobals::setThreadedCommentsPath( const OUString& rPath ) +{ + maThreadedCommentsPath = rPath; +} + void WorksheetGlobals::extendUsedArea( const ScAddress& rAddress ) { maUsedArea.aStart.SetCol( ::std::min( maUsedArea.aStart.Col(), rAddress.Col() ) ); @@ -972,6 +993,11 @@ void WorksheetGlobals::finalizeWorksheetImport() lclUpdateProgressBar( mxFinalProgress, 1.0 ); } +void WorksheetGlobals::finalizeNamedSheetViews() +{ + maNamedSheetViewImporter.finalizeImport(); +} + void WorksheetGlobals::finalizeDrawingImport() { finalizeDrawings(); @@ -1048,7 +1074,7 @@ void WorksheetGlobals::insertHyperlink( const ScAddress& rAddress, const OUStrin SvxFieldItem aURLItem(aURLField, EE_FEATURE_FIELD); rEE.QuickInsertField(aURLItem, ESelection()); - rDoc.setEditCell(rAddress, rEE.CreateTextObject()); + rDoc.setEditCell(rAddress, std::make_unique(rEE.CreateTextObject())); } else { @@ -1350,6 +1376,10 @@ void WorksheetGlobals::finalizeDrawings() // comments (after callout shapes have been imported from VML/DFF) maComments.finalizeImport(); + // threaded comments (after ScPostIt objects have been created by maComments.finalizeImport) + if (!maThreadedCommentsPath.isEmpty()) + importOoxFragment(new ThreadedCommentsFragment(*this, maThreadedCommentsPath)); + /* Extend used area of the sheet by cells covered with drawing objects. Needed if the imported document is inserted as "OLE object from file" and thus does not provide an OLE size property by itself. */ @@ -1498,6 +1528,11 @@ ExtLst& WorksheetHelper::getExtLst() const return mrSheetGlob.getExtLst(); } +void WorksheetHelper::setNamedSheetViews(std::vector&& rData) +{ + mrSheetGlob.setNamedSheetViews(std::move(rData)); +} + void WorksheetHelper::setPageBreak( const PageBreakModel& rModel, bool bRowBreak ) { mrSheetGlob.setPageBreak( rModel, bRowBreak ); @@ -1523,6 +1558,11 @@ void WorksheetHelper::setVmlDrawingPath( const OUString& rVmlDrawingPath ) mrSheetGlob.setVmlDrawingPath( rVmlDrawingPath ); } +void WorksheetHelper::setThreadedCommentsPath( const OUString& rPath ) +{ + mrSheetGlob.setThreadedCommentsPath( rPath ); +} + void WorksheetHelper::extendUsedArea( const ScAddress& rAddress ) { mrSheetGlob.extendUsedArea( rAddress ); @@ -1571,7 +1611,7 @@ void WorksheetHelper::putRichString( const ScAddress& rAddress, RichString& rStr rEE.SetSingleLine(bSingleLine); // The cell will own the text object instance returned from convert(). - getDocImport().setEditCell(rAddress, rString.convert(rEE, pFirstPortionFont)); + getDocImport().setEditCell(rAddress, std::make_unique(rString.convert(rEE, pFirstPortionFont))); rEE.SetSingleLine(false); } @@ -1599,21 +1639,31 @@ void WorksheetHelper::finalizeDrawingImport() mrSheetGlob.finalizeDrawingImport(); } -void WorksheetHelper::setCellFormula( const ScAddress& rTokenAddress, const OUString& rTokenStr ) +void WorksheetHelper::finalizeNamedSheetViews() { - getFormulaBuffer().setCellFormula( rTokenAddress, rTokenStr ); + mrSheetGlob.finalizeNamedSheetViews(); +} + +void WorksheetHelper::setCellFormula(const ScAddress& rTokenAddress, const OUString& rTokenStr, + bool bDynamicArrayMaster) +{ + getFormulaBuffer().setCellFormula(rTokenAddress, rTokenStr, bDynamicArrayMaster); } void WorksheetHelper::setCellFormula( const ScAddress& rAddr, sal_Int32 nSharedId, - const OUString& rCellValue, sal_Int32 nValueType ) + const OUString& rCellValue, sal_Int32 nValueType, + bool bDynamicArrayMaster) { - getFormulaBuffer().setCellFormula(rAddr, nSharedId, rCellValue, nValueType); + getFormulaBuffer().setCellFormula(rAddr, nSharedId, rCellValue, nValueType, bDynamicArrayMaster); } -void WorksheetHelper::setCellArrayFormula( const ScRange& rRangeAddress, const ScAddress& rTokenAddress, const OUString& rTokenStr ) +void WorksheetHelper::setCellArrayFormula(const ScRange& rRangeAddress, const ScAddress& rTokenAddress, + const OUString& rTokenStr, bool bCachedSpill, + bool bDynamicArrayMaster) { - getFormulaBuffer().setCellArrayFormula( rRangeAddress, rTokenAddress, rTokenStr ); + getFormulaBuffer().setCellArrayFormula(rRangeAddress, rTokenAddress, rTokenStr, bCachedSpill, + bDynamicArrayMaster); } void WorksheetHelper::createSharedFormulaMapEntry( diff --git a/sc/source/filter/oox/worksheetsettings.cxx b/sc/source/filter/oox/worksheetsettings.cxx index ab079b2bface..d23c81f19ca3 100644 --- a/sc/source/filter/oox/worksheetsettings.cxx +++ b/sc/source/filter/oox/worksheetsettings.cxx @@ -286,7 +286,8 @@ void WorksheetSettings::finalizeImport() if( !maSheetSettings.maTabColor.isAuto() ) { ::Color nColor = maSheetSettings.maTabColor.getColor( getBaseFilter().getGraphicHelper() ); - xSheet->setPropertyValue( u"TabColor"_ustr, Any(nColor) ); + // tdf#122945 - set the color directly to avoid sheet protection preventing the import + getScDocument().SetTabBgColor(getSheetIndex(), nColor); } // Summary data below or above the contents diff --git a/sc/source/filter/orcus/interface.cxx b/sc/source/filter/orcus/interface.cxx index 9481226689ab..0c3f1a07c56f 100644 --- a/sc/source/filter/orcus/interface.cxx +++ b/sc/source/filter/orcus/interface.cxx @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -145,6 +146,51 @@ void ScOrcusNamedExpression::set_named_expression(std::string_view name, { maName = OUString(name.data(), name.size(), mrGlobalSettings.getTextEncoding()); maExpr = OUString(expression.data(), expression.size(), mrGlobalSettings.getTextEncoding()); + + formula::FormulaGrammar::AddressConvention eConv + = formula::FormulaGrammar::extractRefConvention(mrGlobalSettings.getCalcGrammar()); + + std::vector aTables = mrDoc.getDoc().GetAllTableNames(); + for (const auto& aTable : aTables) + { + OUString aReqTable = aTable; + ScCompiler::CheckTabQuotes(aReqTable, eConv); + + if (aReqTable.indexOf('\'') == -1) + continue; + + sal_Int32 nPos = 0; + while ((nPos = maExpr.indexOf(aTable, nPos)) != -1) + { + bool bQuoted = (nPos > 0 && maExpr[nPos - 1] == '\''); + bool bIsCompleteTableName = true; + sal_Int32 nLen = aTable.getLength(); + sal_Int32 nEndPos = nPos + nLen; + + if (nPos > 0) + { + sal_Unicode cPrevChar = maExpr[nPos - 1]; + bIsCompleteTableName &= !(rtl::isAsciiAlphanumeric(cPrevChar) || cPrevChar == '_' + || cPrevChar == '.'); + } + + if (nEndPos < maExpr.getLength()) + { + sal_Unicode cEndChar = maExpr[nEndPos]; + bIsCompleteTableName &= (cEndChar == '!' || cEndChar == ':'); + } + + if (!bQuoted && bIsCompleteTableName) + { + maExpr = maExpr.replaceAt(nPos, nLen, aReqTable); + nPos += aReqTable.getLength(); + } + else + { + nPos += nLen; + } + } + } } void ScOrcusNamedExpression::set_named_range(std::string_view /*name*/, std::string_view /*range*/) @@ -155,15 +201,15 @@ void ScOrcusNamedExpression::set_named_range(std::string_view /*name*/, std::str void ScOrcusNamedExpression::commit() { ScRangeName* pNames - = mnTab >= 0 ? mrDoc.getDoc().GetRangeName(mnTab) : mrDoc.getDoc().GetRangeName(); + = mnTab >= 0 ? mrDoc.getDoc().GetRangeName(mnTab) : &mrDoc.getDoc().GetRangeName(); if (!pNames) return; - ScRangeData* pRange - = new ScRangeData(mrDoc.getDoc(), maName, maExpr, maBasePos, ScRangeData::Type::Name, - mrGlobalSettings.getCalcGrammar()); + std::unique_ptr pRange(new ScRangeData(mrDoc.getDoc(), maName, maExpr, maBasePos, + ScRangeData::Type::Name, + mrGlobalSettings.getCalcGrammar())); - pNames->insert(pRange, false); + pNames->insert(std::move(pRange), false); reset(); // make sure to reset the state for the next run. } @@ -369,7 +415,8 @@ void ScOrcusFactory::finalize() maDoc.setStringCell(rToken.maPos, std::get<0>(s)); break; case 1: // std::unique_ptr - maDoc.setEditCell(rToken.maPos, std::get<1>(s)->Clone()); + maDoc.setEditCell(rToken.maPos, + std::make_unique(*std::get<1>(s))); break; } ++nCellCount; @@ -558,7 +605,7 @@ void ScOrcusFactory::pushMatrixFormulaToken(const ScAddress& rPos, const OUStrin void ScOrcusFactory::pushFormulaResult(const ScAddress& rPos, double fValue) { // Formula result is expected to be pushed immediately following the - // formula token it belongs. + // formula token it belongs to. if (maCellStoreTokens.empty()) return; @@ -584,7 +631,7 @@ void ScOrcusFactory::pushFormulaResult(const ScAddress& rPos, double fValue) void ScOrcusFactory::pushFormulaResult(const ScAddress& rPos, const OUString& rValue) { // Formula result is expected to be pushed immediately following the - // formula token it belongs. + // formula token it belongs to. if (maCellStoreTokens.empty()) return; @@ -1553,7 +1600,8 @@ size_t ScOrcusSharedStrings::commit_segments() for (const auto & [ rSel, rFormat ] : maFormatSegments) mrEditEngine.QuickSetAttribs(rFormat, rSel); - auto nPos = mrFactory.appendFormattedString(mrEditEngine.CreateTextObject()); + auto nPos = mrFactory.appendFormattedString( + std::make_unique(mrEditEngine.CreateTextObject())); mrEditEngine.Clear(); maFormatSegments.clear(); return nPos; diff --git a/sc/source/filter/orcus/xmlcontext.cxx b/sc/source/filter/orcus/xmlcontext.cxx index 916a94ab9bce..e055ab285938 100644 --- a/sc/source/filter/orcus/xmlcontext.cxx +++ b/sc/source/filter/orcus/xmlcontext.cxx @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include @@ -91,7 +91,7 @@ void populateTree(weld::TreeView& rTreeCtrl, orcus::xml_structure_tree::walker& if (bRepeat) { - // Recurring elements use different icon. + // Recurring elements use different icons. rTreeCtrl.set_image(*xEntry, rParam.maImgElementRepeat, -1); } diff --git a/sc/source/filter/rtf/eeimpars.cxx b/sc/source/filter/rtf/eeimpars.cxx index 0314bb8cf14a..981545445b17 100644 --- a/sc/source/filter/rtf/eeimpars.cxx +++ b/sc/source/filter/rtf/eeimpars.cxx @@ -143,7 +143,7 @@ void ScEEImport::WriteToDocument( bool bSizeColsRows, double nOutputFactor, SvNu // Automatic language option selected. Check for the global 'use US English' option. bNumbersEnglishUS = officecfg::Office::Common::Filter::HTML::Import::NumbersEnglishUS::get(); } - ScRangeName* pRangeNames = mrDoc.GetRangeName(); + ScRangeName& rRangeNames = mrDoc.GetRangeName(); for ( size_t i = 0, n = mpParser->ListSize(); i < n; ++i ) { pE = mpParser->ListEntry( i ); @@ -413,20 +413,20 @@ void ScEEImport::WriteToDocument( bool bSizeColsRows, double nOutputFactor, SvNu mrDoc.SetTextCell(ScAddress(nCol, nRow, nTab), aStr, &aParam); } } - else if (std::unique_ptr pTextObject = IsValidSel(*mpEngine, pE->aSel) ? mpEngine->CreateTextObject(pE->aSel) : nullptr) + else if (IsValidSel(*mpEngine, pE->aSel)) { + EditTextObject aTextObject = mpEngine->CreateTextObject(pE->aSel); // The cell will own the text object instance. - mrDoc.SetEditText(ScAddress(nCol,nRow,nTab), std::move(pTextObject)); + mrDoc.SetEditText(ScAddress(nCol,nRow,nTab), std::move(aTextObject)); } if ( !pE->maImageList.empty() ) bHasGraphics |= GraphicSize( nCol, nRow, pE ); if ( pE->pName ) { // Anchor Name => RangeName - if (!pRangeNames->findByUpperName(ScGlobal::getCharClass().uppercase(*pE->pName))) + if (!rRangeNames.findByUpperName(ScGlobal::getCharClass().uppercase(*pE->pName))) { - ScRangeData* pData = new ScRangeData( mrDoc, *pE->pName, - ScAddress( nCol, nRow, nTab ) ); - pRangeNames->insert( pData ); + rRangeNames.insert( std::make_unique( mrDoc, *pE->pName, + ScAddress( nCol, nRow, nTab ) ) ); } } } @@ -619,10 +619,13 @@ void ScEEImport::InsertGraphic( SCCOL nCol, SCROW nRow, SCTAB nTab, pPage->InsertObject( pObj.get() ); - // SetGraphicLink has to be used after inserting the object, - // otherwise an empty graphic is swapped in and the contact stuff crashes. - // See #i37444#. - pObj->SetGraphicLink( pI->aURL ); + if (!pI->aURL.isEmpty()) + { + // SetGraphicLink has to be used after inserting the object, + // otherwise an empty graphic is swapped in and the contact stuff crashes. + // See #i37444#. + pObj->SetGraphicLink( pI->aURL ); + } pObj->SetLogicRect( aRect ); // Only after InsertObject! } diff --git a/sc/source/filter/rtf/rtfexp.cxx b/sc/source/filter/rtf/rtfexp.cxx index 586d0ee35597..cace80fcdcc1 100644 --- a/sc/source/filter/rtf/rtfexp.cxx +++ b/sc/source/filter/rtf/rtfexp.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -260,6 +261,7 @@ void ScRTFExport::WriteCell( SCTAB nTab, SCROW nRow, SCCOL nCol ) bool bResetAttr(false); const SvxFontItem& rFontItem = pAttr->GetItem( ATTR_FONT ); + const SvxFontHeightItem& rFontHeightItem = pAttr->GetItem(ATTR_FONT_HEIGHT); const SvxHorJustifyItem& rHorJustifyItem = pAttr->GetItem( ATTR_HOR_JUSTIFY ); const SvxWeightItem& rWeightItem = pAttr->GetItem( ATTR_FONT_WEIGHT ); const SvxPostureItem& rPostureItem = pAttr->GetItem( ATTR_FONT_POSTURE ); @@ -268,6 +270,12 @@ void ScRTFExport::WriteCell( SCTAB nTab, SCROW nRow, SCCOL nCol ) m_aDocStrm.WriteOString( OOO_STRING_SVTOOLS_RTF_F ) .WriteOString( OString::number(AddFont(rFontItem)) ); + m_aDocStrm.WriteOString(OOO_STRING_SVTOOLS_RTF_FS); + sal_Int32 nHeight = rFontHeightItem.GetHeight(); + // Twips => HalfPoints + nHeight /= 10; + m_aDocStrm.WriteNumberAsString(nHeight); + const char* pChar; switch( rHorJustifyItem.GetValue() ) diff --git a/sc/source/filter/xcl97/XclExpChangeTrack.cxx b/sc/source/filter/xcl97/XclExpChangeTrack.cxx index 93cd21649c2f..36d3486e7765 100644 --- a/sc/source/filter/xcl97/XclExpChangeTrack.cxx +++ b/sc/source/filter/xcl97/XclExpChangeTrack.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include #include #include #include @@ -548,7 +549,7 @@ XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( const XclExpChTrTabIdBuffer& rCopy nLastId( rCopy.nLastId ) { pBuffer.reset( new sal_uInt16[ nBufSize ] ); - memcpy( pBuffer.get(), rCopy.pBuffer.get(), sizeof(sal_uInt16) * nBufSize ); + std::copy_n( rCopy.pBuffer.get(), nBufSize, pBuffer.get() ); pLast = pBuffer.get() + nBufSize - 1; } @@ -1506,6 +1507,9 @@ XclExpChangeTrack::XclExpChangeTrack( const XclExpRoot& rRoot ) : pScAction = pPrevAction; } + if (aActionStack.empty()) + return; + // build record list if (GetOutput() == EXC_OUTPUT_BINARY) { diff --git a/sc/source/filter/xcl97/xcl97esc.cxx b/sc/source/filter/xcl97/xcl97esc.cxx index 7db78d45bcd4..d6bc672a174a 100644 --- a/sc/source/filter/xcl97/xcl97esc.cxx +++ b/sc/source/filter/xcl97/xcl97esc.cxx @@ -196,7 +196,7 @@ EscherExHostAppData* XclEscherEx::StartShape( const Reference< XShape >& rxShape //added for exporting OCX control sal_Int16 nMsCtlType = 0; if ( !pObj ) - pCurrXclObj = new XclObjAny( mrObjMgr, rxShape, &GetDoc() ); // just what is it?!? + pCurrXclObj = new XclObjAny( mrObjMgr, rxShape, &GetDoc() );// just what is it?!? else { pCurrXclObj = nullptr; @@ -245,7 +245,7 @@ EscherExHostAppData* XclEscherEx::StartShape( const Reference< XShape >& rxShape else //TBX Form Control pCurrXclObj = CreateTBXCtrlObj( rxShape, pChildAnchor ).release(); if( !pCurrXclObj ) - pCurrXclObj = new XclObjAny( mrObjMgr, rxShape, &GetDoc() ); // just a metafile + pCurrXclObj = new XclObjAny( mrObjMgr, rxShape, &GetDoc() ); // just a metafile } else if( !ScDrawLayer::IsNoteCaption( pObj ) ) { diff --git a/sc/source/filter/xcl97/xcl97rec.cxx b/sc/source/filter/xcl97/xcl97rec.cxx index 577138edf905..f1febef44536 100644 --- a/sc/source/filter/xcl97/xcl97rec.cxx +++ b/sc/source/filter/xcl97/xcl97rec.cxx @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #include #include @@ -55,6 +57,7 @@ #include #include #include +#include #include #include @@ -131,6 +134,11 @@ std::unique_ptr XclExpObjList::pop_back () return ret; } +void XclExpObjList::SetImageData(std::unique_ptr pImgData) +{ + m_pImgData = std::move(pImgData); +} + void XclExpObjList::EndSheet() { // Is there still something in the stream? -> The solver container @@ -397,10 +405,16 @@ void XclExpObjList::SaveXml( XclExpXmlStream& rStrm ) pSolverContainer->SaveXml( rStrm ); if( maObjs.empty()) + { + if (m_pImgData) + m_pImgData->SaveXml(rStrm); return; + } SaveDrawingMLObjects( *this, rStrm ); SaveVmlObjects( *this, rStrm ); + if (m_pImgData) + m_pImgData->SaveXml(rStrm); SaveFormControlObjects( *this, rStrm ); } @@ -569,7 +583,7 @@ void setSuppressGetBitmapFromXclObjComment(SdrCaptionObj* pSdrCaptionObj, bool b } } -XclObjComment::XclObjComment( XclExpObjectManager& rObjMgr, const tools::Rectangle& rRect, const EditTextObject& rEditObj, SdrCaptionObj* pCaption, bool bVisible, const ScAddress& rAddress, const tools::Rectangle &rFrom, const tools::Rectangle &rTo ) : +XclObjComment::XclObjComment( XclExpObjectManager& rObjMgr, const tools::Rectangle& rRect, const EditTextObject* pEditObj, SdrCaptionObj* pCaption, bool bVisible, const ScAddress& rAddress, const tools::Rectangle &rFrom, const tools::Rectangle &rTo ) : XclObj( rObjMgr, EXC_OBJTYPE_NOTE, true ) , maScPos( rAddress ) , mpCaption( pCaption ) @@ -586,7 +600,10 @@ XclObjComment::XclObjComment( XclExpObjectManager& rObjMgr, const tools::Rectang ProcessEscherObj( rObjMgr.GetRoot(), rRect, pCaption, bVisible); // TXO - pTxo .reset(new XclTxo( rObjMgr.GetRoot(), rEditObj, pCaption )); + if (pEditObj) + pTxo.reset(new XclTxo( rObjMgr.GetRoot(), *pEditObj, pCaption )); + else + pTxo.reset(new XclTxo( OUString(), 0 )); } static void lcl_FillProps( EscherPropertyContainer& rPropOpt, SdrObject* pCaption, bool bVisible ) @@ -1305,6 +1322,20 @@ bool ScURLTransformer::isExternalURL(const OUString& rURL) const return !rURL.startsWith("#"); } +sal_Int32 ScURLTransformer::getExternalLinkIndex(const OUString& rUrl) const +{ + if (!rUrl.isEmpty()) + { + ScExternalRefManager* pRefMgr = mrDoc.GetExternalRefManager(); + if (pRefMgr) + { + sal_uInt16 nFileId = pRefMgr->getExternalFileId(rUrl); + return static_cast(pRefMgr->convertFileIdToUsedFileId(nFileId)) + 1; + } + } + return 0; +} + void XclObjAny::SaveXml( XclExpXmlStream& rStrm ) { // Return early if unknown/invalid shape; otherwise bogus drawing XML gets written @@ -1318,6 +1349,13 @@ void XclObjAny::SaveXml( XclExpXmlStream& rStrm ) SdrObject* pObject = SdrObject::getSdrObjectFromXShape(mxShape); if (pObject) { + if (pObject->GetObjIdentifier() == SdrObjKind::Graphic) + { + auto pGrafObj = dynamic_cast(pObject); + if (pGrafObj && pGrafObj->GetGraphic().GetType() == GraphicType::NONE) + return; + } + ScDocument& rDoc = rStrm.GetRoot().GetDoc(); ScDetectiveFunc aDetFunc(rDoc, mnScTab); ScAddress aPosition; @@ -1342,7 +1380,36 @@ void XclObjAny::SaveXml( XclExpXmlStream& rStrm ) if (xPropSet.is()) { WriteFromTo( rStrm, *this ); - aDML.WriteShape( mxShape ); + bool bWriteAsShape(true); + + if (pObject && pObject->isDiagram()) + { + bool bSaveAsDiagram(false); + const std::shared_ptr& rIDiagramHelper(pObject->getDiagramHelper()); + + if (rIDiagramHelper) + { + // check if all needed data exists to either write unchanged/untouched + // Diagram or with re-creation of some DataDoms + bSaveAsDiagram = rIDiagramHelper->checkMinimalDataDoms(); + } + + if (bSaveAsDiagram) + { + const sal_Int32 nDiagramId(rStrm.getAndIncrementDiagramId()); + const sal_Int32 nShapeId = aDML.GetNewShapeID(mxShape); + SAL_INFO("sc.eppt", "writing Diagram " + OUString::number(nDiagramId) + " with Shape Id " + OUString::number(nShapeId)); + pDrawing->startElementNS(XML_xdr, XML_graphicFrame); + aDML.WriteDiagram(mxShape, nDiagramId, nShapeId); + pDrawing->endElementNS(XML_xdr, XML_graphicFrame); + bWriteAsShape = false; + } + } + + if (bWriteAsShape) + { + aDML.WriteShape( mxShape ); + } } pDrawing->singleElement( FSNS( XML_xdr, XML_clientData) diff --git a/sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx b/sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx index 177332225cd3..84363af364cc 100644 --- a/sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx +++ b/sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx @@ -719,8 +719,10 @@ void ScXMLChangeTrackingImportHelper::CreateChangeTrack(ScDocument* pDoc) // old files didn't store nanoseconds, disable until encountered pTrack->SetTimeNanoSeconds( false ); - for (const auto & rAction : aActions) + auto aItr = aActions.begin(); + while (aItr != aActions.end()) { + const auto& rAction = *aItr; std::unique_ptr pAction; switch (rAction->nActionType) @@ -764,17 +766,20 @@ void ScXMLChangeTrackingImportHelper::CreateChangeTrack(ScDocument* pDoc) } } - if (pAction) - pTrack->AppendLoaded(std::move(pAction)); + // Malformed documents can repeat the same XML id across actions. If + // this happens drop entries whose action number is already in the track. + if (pAction && pTrack->AppendLoaded(std::move(pAction))) + ++aItr; else { - OSL_FAIL("no action"); + SAL_WARN("sc.filter", "Dropping malformed change track entry"); + aItr = aActions.erase(aItr); } } if (pTrack->GetLast()) pTrack->SetActionMax(pTrack->GetLast()->GetActionNumber()); - auto aItr = aActions.begin(); + aItr = aActions.begin(); while (aItr != aActions.end()) { SetDependencies(aItr->get(), *pDoc); diff --git a/sc/source/filter/xml/XMLStylesExportHelper.cxx b/sc/source/filter/xml/XMLStylesExportHelper.cxx index 12fafe861c7a..b2a4ac377a9a 100644 --- a/sc/source/filter/xml/XMLStylesExportHelper.cxx +++ b/sc/source/filter/xml/XMLStylesExportHelper.cxx @@ -705,49 +705,29 @@ bool ScFormatRangeStyles::AddStyleName(OUString const & rString, sal_Int32& rInd sal_Int32 ScFormatRangeStyles::GetIndexOfStyleName(std::u16string_view rString, std::u16string_view rPrefix, bool& bIsAutoStyle) { - sal_Int32 nPrefixLength(rPrefix.size()); - std::u16string_view sTemp(rString.substr(nPrefixLength)); - sal_Int32 nIndex(o3tl::toInt32(sTemp)); - if (nIndex > 0 && o3tl::make_unsigned(nIndex-1) < aAutoStyleNames.size() && aAutoStyleNames.at(nIndex - 1) == rString) + if (std::u16string_view rest; o3tl::starts_with(rString, rPrefix, &rest)) + { + sal_Int32 nIndex(o3tl::toInt32(rest)); + if (nIndex > 0 && o3tl::make_unsigned(nIndex - 1) < aStyleNames.size() && aStyleNames[nIndex - 1] == rString) + { + bIsAutoStyle = true; + return nIndex - 1; + } + } + + if (auto i = std::find(aStyleNames.begin(), aStyleNames.end(), rString); i != aStyleNames.end()) + { + bIsAutoStyle = false; + return std::distance(aStyleNames.begin(), i); + } + + if (auto i = std::find(aAutoStyleNames.begin(), aAutoStyleNames.end(), rString); i != aAutoStyleNames.end()) { bIsAutoStyle = true; - return nIndex - 1; - } - else - { - sal_Int32 i(0); - bool bFound(false); - while (!bFound && o3tl::make_unsigned(i) < aStyleNames.size()) - { - if (aStyleNames[i] == rString) - bFound = true; - else - ++i; - } - if (bFound) - { - bIsAutoStyle = false; - return i; - } - else - { - i = 0; - while (!bFound && o3tl::make_unsigned(i) < aAutoStyleNames.size()) - { - if (aAutoStyleNames[i] == rString) - bFound = true; - else - ++i; - } - if (bFound) - { - bIsAutoStyle = true; - return i; - } - else - return -1; - } + return std::distance(aAutoStyleNames.begin(), i); } + + return -1; } sal_Int32 ScFormatRangeStyles::GetStyleNameIndex(const sal_Int32 nTable, diff --git a/sc/source/filter/xml/XMLTableShapesContext.cxx b/sc/source/filter/xml/XMLTableShapesContext.cxx index 676bc560faa5..2c4ea541c5a5 100644 --- a/sc/source/filter/xml/XMLTableShapesContext.cxx +++ b/sc/source/filter/xml/XMLTableShapesContext.cxx @@ -26,7 +26,7 @@ using namespace com::sun::star; ScXMLTableShapesContext::ScXMLTableShapesContext( ScXMLImport& rImport ) : ScXMLImportContext( rImport ) { - // here are no attributes + // Here, there are no attributes } ScXMLTableShapesContext::~ScXMLTableShapesContext() diff --git a/sc/source/filter/xml/xmlannoi.cxx b/sc/source/filter/xml/xmlannoi.cxx index 15725b7e8b99..bdcd27a4dd3d 100644 --- a/sc/source/filter/xml/xmlannoi.cxx +++ b/sc/source/filter/xml/xmlannoi.cxx @@ -28,6 +28,113 @@ using namespace com::sun::star; using namespace xmloff::token; +namespace { + +/// Context handler for inside . +class ScXMLThreadedCommentReplyContext : public ScXMLImportContext +{ +public: + ScXMLThreadedCommentReplyContext(ScXMLImport& rImport, + const css::uno::Reference& xAttrList, + ScXMLAnnotationData& rData) + : ScXMLImportContext(rImport) + , mrData(rData) + { + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + switch (aIter.getToken()) + { + case XML_ELEMENT(LO_EXT, XML_ID): + maEntry.maGuid = aIter.toString(); + break; + case XML_ELEMENT(LO_EXT, XML_DATE_TIME): + maEntry.maDateTime = aIter.toString(); + break; + case XML_ELEMENT(LO_EXT, XML_PERSON_ID): + maEntry.maPersonId = aIter.toString(); + break; + } + } + } + + css::uno::Reference SAL_CALL createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference&) override + { + if (nElement == XML_ELEMENT(LO_EXT, XML_TEXT)) + return new ScXMLContentContext(GetScImport(), maTextBuffer); + return nullptr; + } + + void SAL_CALL endFastElement(sal_Int32) override + { + maEntry.maText = maTextBuffer.makeStringAndClear(); + if (mrData.mpThreadedCommentData) + mrData.mpThreadedCommentData->maReplies.push_back(std::move(maEntry)); + } + +private: + ScXMLAnnotationData& mrData; + ScThreadedCommentEntry maEntry; + OUStringBuffer maTextBuffer; +}; + +/// Context handler for inside . +class ScXMLThreadedCommentContext : public ScXMLImportContext +{ +public: + ScXMLThreadedCommentContext(ScXMLImport& rImport, + const css::uno::Reference& xAttrList, + ScXMLAnnotationData& rData) + : ScXMLImportContext(rImport) + , mrData(rData) + { + mrData.mpThreadedCommentData = std::make_unique(); + + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + switch (aIter.getToken()) + { + case XML_ELEMENT(LO_EXT, XML_ID): + mrData.mpThreadedCommentData->maRoot.maGuid = aIter.toString(); + break; + case XML_ELEMENT(LO_EXT, XML_DATE_TIME): + mrData.mpThreadedCommentData->maRoot.maDateTime = aIter.toString(); + break; + case XML_ELEMENT(LO_EXT, XML_RESOLVED): + mrData.mpThreadedCommentData->mbDone = IsXMLToken(aIter, XML_TRUE); + break; + case XML_ELEMENT(LO_EXT, XML_PERSON_ID): + mrData.mpThreadedCommentData->maRoot.maPersonId = aIter.toString(); + break; + } + } + } + + css::uno::Reference SAL_CALL createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference& xAttrList) override + { + if (nElement == XML_ELEMENT(LO_EXT, XML_TEXT)) + return new ScXMLContentContext(GetScImport(), maTextBuffer); + if (nElement == XML_ELEMENT(LO_EXT, XML_REPLY)) + return new ScXMLThreadedCommentReplyContext(GetScImport(), xAttrList, mrData); + return nullptr; + } + + void SAL_CALL endFastElement(sal_Int32) override + { + if (mrData.mpThreadedCommentData) + mrData.mpThreadedCommentData->maRoot.maText = maTextBuffer.makeStringAndClear(); + } + +private: + ScXMLAnnotationData& mrData; + OUStringBuffer maTextBuffer; +}; + +} // anonymous namespace + ScXMLAnnotationData::ScXMLAnnotationData() : mbUseShapePos( false ), mbShown( false ) @@ -114,6 +221,8 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > ScXMLAnnotationContext return new ScXMLContentContext(GetScImport(), maCreateDateBuffer); case XML_ELEMENT(META, XML_DATE_STRING): return new ScXMLContentContext(GetScImport(), maCreateDateStringBuffer); + case XML_ELEMENT(LO_EXT, XML_THREADED_COMMENT): + return new ScXMLThreadedCommentContext(GetScImport(), xAttrList, mrAnnotationData); } if( pShapeContext ) diff --git a/sc/source/filter/xml/xmlannoi.hxx b/sc/source/filter/xml/xmlannoi.hxx index 6f8c9dc492e7..b8230b9e3aa3 100644 --- a/sc/source/filter/xml/xmlannoi.hxx +++ b/sc/source/filter/xml/xmlannoi.hxx @@ -22,8 +22,10 @@ #include #include #include +#include #include "importcontext.hxx" +#include #include class ScXMLImport; @@ -58,6 +60,7 @@ struct ScXMLAnnotationData OUString maTextStyle; bool mbUseShapePos; bool mbShown; + std::unique_ptr mpThreadedCommentData; std::vector maContentStyles; explicit ScXMLAnnotationData(); diff --git a/sc/source/filter/xml/xmlbodyi.cxx b/sc/source/filter/xml/xmlbodyi.cxx index 2eec7feaab0f..daaedce41ecc 100644 --- a/sc/source/filter/xml/xmlbodyi.cxx +++ b/sc/source/filter/xml/xmlbodyi.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include "xmlbodyi.hxx" @@ -117,6 +118,42 @@ ScXMLBodyContext::~ScXMLBodyContext() { } +ScXMLPersonsContext::ScXMLPersonsContext(ScXMLImport& rImport) + : ScXMLImportContext(rImport) +{ +} + +uno::Reference SAL_CALL +ScXMLPersonsContext::createFastChildContext(sal_Int32 nElement, + const uno::Reference& xAttrList) +{ + if (nElement == XML_ELEMENT(LO_EXT, XML_PERSON)) + { + ScPersonData aPerson; + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + switch (aIter.getToken()) + { + case XML_ELEMENT(LO_EXT, XML_PERSON_ID): + aPerson.maId = aIter.toString(); + break; + case XML_ELEMENT(LO_EXT, XML_DISPLAY_NAME): + aPerson.maDisplayName = aIter.toString(); + break; + case XML_ELEMENT(LO_EXT, XML_USER_ID): + aPerson.maUserId = aIter.toString(); + break; + case XML_ELEMENT(LO_EXT, XML_PROVIDER_ID): + aPerson.maProviderId = aIter.toString(); + break; + } + } + if (ScDocument* pDoc = GetScImport().GetDocument()) + pDoc->AddPerson(aPerson); + } + return nullptr; +} + uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLBodyContext::createFastChildContext( sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList > & xAttrList ) @@ -166,6 +203,9 @@ uno::Reference< xml::sax::XFastContextHandler > SAL_CALL GetScImport(), std::make_shared(GetScImport()) ); break; + case XML_ELEMENT( LO_EXT, XML_PERSONS ): + pContext = new ScXMLPersonsContext(GetScImport()); + break; case XML_ELEMENT( TABLE, XML_DATABASE_RANGES ): pContext = new ScXMLDatabaseRangesContext ( GetScImport() ); break; diff --git a/sc/source/filter/xml/xmlbodyi.hxx b/sc/source/filter/xml/xmlbodyi.hxx index 6db678017088..1f257a91fb06 100644 --- a/sc/source/filter/xml/xmlbodyi.hxx +++ b/sc/source/filter/xml/xmlbodyi.hxx @@ -53,4 +53,14 @@ public: virtual void SAL_CALL characters(const OUString & aChars) override; }; +class ScXMLPersonsContext : public ScXMLImportContext +{ +public: + ScXMLPersonsContext(ScXMLImport& rImport); + + virtual css::uno::Reference SAL_CALL + createFastChildContext(sal_Int32 nElement, + const css::uno::Reference& xAttrList) override; +}; + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx index 5f68c14a2e39..76bea8d8e5a2 100644 --- a/sc/source/filter/xml/xmlcelli.cxx +++ b/sc/source/filter/xml/xmlcelli.cxx @@ -179,6 +179,10 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport, bIsMatrix = true; nMatrixRows = static_cast(it.toInt32()); break; + case XML_ELEMENT(LO_EXT, XML_SPILL): + case XML_ELEMENT(COL_EXT, XML_SPILL): + mbDynamicArraySpill = IsXMLToken(it, XML_TRUE); + break; case XML_ELEMENT( TABLE, XML_NUMBER_COLUMNS_REPEATED ): { if (ScDocument* pDoc = rImport.GetDocument()) @@ -954,6 +958,8 @@ void ScXMLTableRowCellContext::SetAnnotation(const ScAddress& rPos) pNote->SetDate( aDate ); } pNote->SetAuthor( mxAnnotationData->maAuthor ); + if (mxAnnotationData->mpThreadedCommentData) + pNote->SetThreadedCommentData(std::move(mxAnnotationData->mpThreadedCommentData)); } // register a shape that has been newly created in the ScNoteUtil functions @@ -1132,7 +1138,7 @@ void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos, // This edit engine uses the SfxItemPool instance returned // from pDoc->GetEditPool() to create the text object, which // is a prerequisite for using this constructor of ScEditCell. - rDoc.setEditCell(rCurrentPos, mpEditEngine->CreateTextObject()); + rDoc.setEditCell(rCurrentPos, std::make_unique(mpEditEngine->CreateTextObject())); } } else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() ) @@ -1421,9 +1427,28 @@ void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos ) } } - ScFormulaCell* pNewCell = new ScFormulaCell(*pDoc, rCellPos, std::move(pCode), eGrammar, ScMatrixMode::NONE); - SetFormulaCell(pNewCell); - rDocImport.setFormulaCell(rCellPos, pNewCell); + if (mbDynamicArraySpill) + { + // A non-array cell with loext:spill="true" was saved while in + // spill state. Re-instate as a 1x1 dynamic-array master and + // mark the position spilled so the next interpret re-checks + // the blockers and either expands the matrix or stays in + // #SPILL!. + ScFormulaCell* pNewCell = new ScFormulaCell(*pDoc, rCellPos, std::move(pCode), eGrammar, ScMatrixMode::NONE); + pNewCell->SetDynamicArrayMaster(true); + SetFormulaCell(pNewCell); + rDocImport.setFormulaCell(rCellPos, pNewCell); + pDoc->MarkFormulaSpilled(rCellPos); + } + else + { + // Plain non-array formula. The @ implicit-intersection + // decision is resolved once the XML placeholder has been + // compiled into native tokens. + ScFormulaCell* pNewCell = new ScFormulaCell(*pDoc, rCellPos, std::move(pCode), eGrammar, ScMatrixMode::NONE); + SetFormulaCell(pNewCell); + rDocImport.setFormulaCell(rCellPos, pNewCell); + } } void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos ) @@ -1440,13 +1465,20 @@ void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos ) { if (nMatrixCols > 0 && nMatrixRows > 0) { - //matrix cells are put in the document, but we must set the - //value/text of each matrix cell later + // Matrix cells are put in the document, but we must set the + // value/text of each matrix cell later. + // The file recorded the array's master cell with a #SPILL! + // error result. Transport that through so any blocker cell still + // sitting in the matrix range is preserved instead of being + // replaced by a reference cell. + const bool bCachedSpill = mbErrorValue + && GetScImport().GetFormulaErrorConstant(GetFirstParagraph()) + == FormulaError::Spill; rXMLImport.GetTables().AddMatrixRange( rCellPos.Col(), rCellPos.Row(), std::min(rCellPos.Col() + nMatrixCols - 1, pDoc->MaxCol()), std::min(rCellPos.Row() + nMatrixRows - 1, pDoc->MaxRow()), - maFormula->first, maFormula->second, eGrammar); + maFormula->first, maFormula->second, eGrammar, bCachedSpill); // Set the value/text of the top-left matrix position in its // cached result. For import, we only need to set the correct @@ -1454,6 +1486,13 @@ void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos ) ScFormulaCell* pFCell = pDoc->GetFormulaCell(rCellPos); if (pFCell) { + // loext:spill="true" promotes the matrix master to + // a dynamic-array master. Without the marker the + // cell stays a static Ctrl+Shift+Enter (CSE) + // master, so legacy files keep their iteration- + // and-pad behaviour. + if (mbDynamicArraySpill) + pFCell->SetDynamicArrayMaster(true); ScMatrixRef pMat(new ScMatrix(nMatrixCols, nMatrixRows)); if (bFormulaTextResult && maStringValue) { diff --git a/sc/source/filter/xml/xmlcelli.hxx b/sc/source/filter/xml/xmlcelli.hxx index 73d839e69244..ae3ba661b983 100644 --- a/sc/source/filter/xml/xmlcelli.hxx +++ b/sc/source/filter/xml/xmlcelli.hxx @@ -83,6 +83,7 @@ class ScXMLTableRowCellContext : public ScXMLImportContext sal_Int16 nCellType; bool bIsMerged; bool bIsMatrix; + bool mbDynamicArraySpill = false; bool bIsCovered; bool bIsEmpty; bool mbNewValueType; diff --git a/sc/source/filter/xml/xmlcondformat.cxx b/sc/source/filter/xml/xmlcondformat.cxx index 214c9c9334d1..4b232623344e 100644 --- a/sc/source/filter/xml/xmlcondformat.cxx +++ b/sc/source/filter/xml/xmlcondformat.cxx @@ -150,15 +150,18 @@ static bool HasRelRefIgnoringSheet0Relative( ScDocument* pDoc, const ScTokenArra { case formula::svDoubleRef: { - ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2; + ScSingleRefData& rRef2 = static_cast(t)->GetDoubleRef().Ref2; if ( rRef2.IsColRel() || rRef2.IsRowRel() || (rRef2.IsFlag3D() && rRef2.IsTabRel()) ) return true; - [[fallthrough]]; + ScSingleRefData& rRef1 = static_cast(t)->GetSingleRef(); + if ( rRef1.IsColRel() || rRef1.IsRowRel() || (rRef1.IsFlag3D() && rRef1.IsTabRel()) ) + return true; } + break; case formula::svSingleRef: { - ScSingleRefData& rRef1 = *t->GetSingleRef(); + ScSingleRefData& rRef1 = static_cast(t)->GetSingleRef(); if ( rRef1.IsColRel() || rRef1.IsRowRel() || (rRef1.IsFlag3D() && rRef1.IsTabRel()) ) return true; } @@ -167,9 +170,12 @@ static bool HasRelRefIgnoringSheet0Relative( ScDocument* pDoc, const ScTokenArra case formula::svIndex: { if( t->GetOpCode() == ocName ) // DB areas always absolute - if( ScRangeData* pRangeData = pDoc->FindRangeNameBySheetAndIndex( t->GetSheet(), t->GetIndex()) ) + { + auto pIndexToken = static_cast(t); + if( ScRangeData* pRangeData = pDoc->FindRangeNameBySheetAndIndex( pIndexToken->GetSheet(), pIndexToken->GetIndex()) ) if( (nRecursion < 42) && HasRelRefIgnoringSheet0Relative( pDoc, pRangeData->GetCode(), nRecursion + 1 ) ) return true; + } } break; @@ -210,7 +216,7 @@ static bool HasOneSingleFullyRelativeReference( const ScTokenArray* pTokens, ScS { case formula::svSingleRef: { - ScSingleRefData& rRef1 = *t->GetSingleRef(); + ScSingleRefData& rRef1 = static_cast(t)->GetSingleRef(); if ( rRef1.IsColRel() && rRef1.IsRowRel() && !rRef1.IsFlag3D() && rRef1.IsTabRel() ) { nCount++; diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index 30aa19714077..0f207b10a55d 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -1950,6 +1950,7 @@ void ScXMLExport::ExportContent_() } } WriteExternalRefCaches(*pDoc); + WritePersons(*pDoc); WriteNamedExpressions(*pDoc); WriteDataStream(*pDoc); aExportDatabaseRanges.WriteDatabaseRanges(*pDoc); @@ -3184,7 +3185,22 @@ void ScXMLExport::WriteCell(ScDocument& rDoc, const ScMyCell& aCell, sal_Int32 n AddAttribute(sAttrStyleName, pCellStyles->GetStyleNameByIndex(aCell.nStyleIndex, aCell.bIsAutoStyle)); if (aCell.nValidationIndex > -1) AddAttribute(XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION_NAME, pValidationsContainer->GetValidationName(aCell.nValidationIndex)); - const bool bIsFirstMatrixCell(aCell.bIsMatrixBase); + // A dynamic-array master in spill state has collapsed to 1x1. + // Write it as a plain non-array formula carrying loext:spill="true" + // so the next import re-instates it as a dynamic master and re- + // checks the blockers. Other matrix masters keep their declared + // size. + ScFormulaCell* pFormulaCell = nullptr; + if (aCell.nType == table::CellContentType_FORMULA + && aCell.maBaseCell.getType() == CELLTYPE_FORMULA) + { + pFormulaCell = aCell.maBaseCell.getFormula(); + } + const bool bDynamicSpilling + = pFormulaCell + && pFormulaCell->IsDynamicArrayMaster() + && pFormulaCell->GetErrCode() == FormulaError::Spill; + const bool bIsFirstMatrixCell(aCell.bIsMatrixBase && !bDynamicSpilling); if (bIsFirstMatrixCell) { SCCOL nColumns( aCell.aMatrixRange.aEnd.Col() - aCell.aMatrixRange.aStart.Col() + 1 ); @@ -3192,6 +3208,15 @@ void ScXMLExport::WriteCell(ScDocument& rDoc, const ScMyCell& aCell, sal_Int32 n AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_COLUMNS_SPANNED, OUString::number(nColumns)); AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_MATRIX_ROWS_SPANNED, OUString::number(nRows)); } + // loext:spill="true" marks a matrix master as dynamic. Plain ODF has no + // place to record the dynamic-vs-static distinction, so the attribute + // only lands in extended ODF. + if ((getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) + && pFormulaCell + && pFormulaCell->IsDynamicArrayMaster()) + { + AddAttribute(XML_NAMESPACE_LO_EXT, XML_SPILL, XML_TRUE); + } bool bIsEmpty(false); switch (aCell.nType) { @@ -3226,7 +3251,8 @@ void ScXMLExport::WriteCell(ScDocument& rDoc, const ScMyCell& aCell, sal_Int32 n if (aCell.maBaseCell.getType() == CELLTYPE_FORMULA) { const bool bIsMatrix(bIsFirstMatrixCell || aCell.bIsMatrixCovered); - ScFormulaCell* pFormulaCell = aCell.maBaseCell.getFormula(); + if (!pFormulaCell) + pFormulaCell = aCell.maBaseCell.getFormula(); if (!bIsMatrix || bIsFirstMatrixCell) { if (!mpCompileFormulaCxt) @@ -3239,14 +3265,19 @@ void ScXMLExport::WriteCell(ScDocument& rDoc, const ScMyCell& aCell, sal_Int32 n sal_uInt16 nNamespacePrefix = (mpCompileFormulaCxt->getGrammar() == formula::FormulaGrammar::GRAM_ODFF ? XML_NAMESPACE_OF : XML_NAMESPACE_OOOC); - if (!bIsMatrix) - { - AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula, false)); - } - else - { - AddAttribute(sAttrFormula, GetNamespaceMap().GetQNameByKey(nNamespacePrefix, aFormula.copy(1, aFormula.getLength()-2), false)); - } + // GetFormula wraps static array masters as + // {=FORMULA} but leaves dynamic-array masters as + // =FORMULA. Strip the {} wrapping only when it + // is actually present. + const bool bWrapped + = bIsMatrix && aFormula.startsWith("{") + && aFormula.endsWith("}"); + const OUString aText = bWrapped + ? aFormula.copy(1, aFormula.getLength() - 2) + : aFormula; + AddAttribute(sAttrFormula, + GetNamespaceMap().GetQNameByKey( + nNamespacePrefix, aText, false)); } if (pFormulaCell->GetErrCode() != FormulaError::NONE) { @@ -3656,8 +3687,22 @@ void ScXMLExport::WriteShapes(const ScDocument& rDoc, const ScMyCell& rMyCell) if (bNeedsRestoreSize) { - double fScaleWidthInvers = 1.0 / fScaleWidth; - double fScaleHeightInvers = 1.0 / fScaleHeight; + double fScaleWidthInvers; + if (fScaleWidth == 0.0) + { + SAL_WARN("sc", "WriteShapes: zero scale width, skipping inverse resize"); + fScaleWidthInvers = 1.0; + } + else + fScaleWidthInvers = 1.0 / fScaleWidth; + double fScaleHeightInvers; + if (fScaleHeight == 0.0) + { + SAL_WARN("sc", "WriteShapes: zero scale height, skipping inverse resize"); + fScaleHeightInvers = 1.0; + } + else + fScaleHeightInvers = 1.0 / fScaleHeight; pObj->NbcResize(aFullTopPoint, fScaleWidthInvers, fScaleHeightInvers); } if (bNeedsRestorePosition) @@ -3801,6 +3846,38 @@ void ScXMLExport::exportAnnotationMeta( const uno::Reference < drawing::XShape > false ); Characters(aDate); } + + if (!(getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)) + return; + + const ScThreadedCommentData* pData = pNote->GetThreadedCommentData(); + if (!pData) + return; + + AddAttribute(XML_NAMESPACE_LO_EXT, XML_ID, pData->maRoot.maGuid); + if (!pData->maRoot.maDateTime.isEmpty()) + AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_TIME, pData->maRoot.maDateTime); + if (pData->mbDone) + AddAttribute(XML_NAMESPACE_LO_EXT, XML_RESOLVED, XML_TRUE); + AddAttribute(XML_NAMESPACE_LO_EXT, XML_PERSON_ID, pData->maRoot.maPersonId); + { + SvXMLElementExport aThreadedComment(*this, XML_NAMESPACE_LO_EXT, + XML_THREADED_COMMENT, true, true); + { + SvXMLElementExport aText(*this, XML_NAMESPACE_LO_EXT, XML_TEXT, true, false); + Characters(pData->maRoot.maText); + } + for (const auto& rReply : pData->maReplies) + { + AddAttribute(XML_NAMESPACE_LO_EXT, XML_ID, rReply.maGuid); + if (!rReply.maDateTime.isEmpty()) + AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_TIME, rReply.maDateTime); + AddAttribute(XML_NAMESPACE_LO_EXT, XML_PERSON_ID, rReply.maPersonId); + SvXMLElementExport aReply(*this, XML_NAMESPACE_LO_EXT, XML_REPLY, true, true); + SvXMLElementExport aText(*this, XML_NAMESPACE_LO_EXT, XML_TEXT, true, false); + Characters(rReply.maText); + } + } } void ScXMLExport::WriteAnnotation(ScDocument& rDoc, const ScMyCell& rMyCell) @@ -4173,10 +4250,32 @@ void ScXMLExport::WriteLabelRanges(const ScDocument& rDoc, const uno::Reference< } } +void ScXMLExport::WritePersons(const ScDocument& rDoc) +{ + if (!(getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)) + return; + + const auto& rPersonList = rDoc.GetPersonList(); + if (rPersonList.empty()) + return; + + SvXMLElementExport aPersons(*this, XML_NAMESPACE_LO_EXT, XML_PERSONS, true, true); + for (const auto& rPerson : rPersonList) + { + AddAttribute(XML_NAMESPACE_LO_EXT, XML_PERSON_ID, rPerson.maId); + AddAttribute(XML_NAMESPACE_LO_EXT, XML_DISPLAY_NAME, rPerson.maDisplayName); + if (!rPerson.maUserId.isEmpty()) + AddAttribute(XML_NAMESPACE_LO_EXT, XML_USER_ID, rPerson.maUserId); + if (!rPerson.maProviderId.isEmpty()) + AddAttribute(XML_NAMESPACE_LO_EXT, XML_PROVIDER_ID, rPerson.maProviderId); + SvXMLElementExport aPerson(*this, XML_NAMESPACE_LO_EXT, XML_PERSON, true, true); + } +} + void ScXMLExport::WriteNamedExpressions(const ScDocument& rDoc) { - ScRangeName* pNamedRanges = rDoc.GetRangeName(); - WriteNamedRange(rDoc, pNamedRanges); + ScRangeName& rNamedRanges = rDoc.GetRangeName(); + WriteNamedRange(rDoc, &rNamedRanges); } void ScXMLExport::WriteExternalDataMapping(ScDocument& rDoc) @@ -5129,14 +5228,14 @@ void ScXMLExport::WriteExternalRefCaches(const ScDocument& rDoc) case svDouble: { AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT); - aStrVal = OUString::number(pToken->GetDouble()); + aStrVal = OUString::number(static_cast(pToken.get())->GetDouble()); AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, aStrVal); } break; case svString: { AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING); - aStrVal = pToken->GetString().getString(); + aStrVal = static_cast(pToken.get())->GetString().getString(); } break; default: diff --git a/sc/source/filter/xml/xmlexprt.hxx b/sc/source/filter/xml/xmlexprt.hxx index 3c75397135b7..da2c7d0d7c56 100644 --- a/sc/source/filter/xml/xmlexprt.hxx +++ b/sc/source/filter/xml/xmlexprt.hxx @@ -192,6 +192,7 @@ class ScXMLExport : public SvXMLExport void WriteScenario(const ScDocument& rDoc); // core implementation void WriteTheLabelRanges(const ScDocument& rDoc, const rtl::Reference& xSpreadDoc); void WriteLabelRanges(const ScDocument& rDoc, const css::uno::Reference< css::container::XIndexAccess >& xRangesIAccess, bool bColumn); + void WritePersons(const ScDocument& rDoc); void WriteNamedExpressions(const ScDocument& rDoc); void WriteExternalDataMapping(ScDocument& rDoc); void WriteExternalDataTransformations(const ScDocument& rDoc, const std::vector>& rDataTransformations); diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index f8355b1f4f86..56a33bf86840 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -1296,9 +1296,9 @@ public: if (!p.bIsExpression) ScXMLConverter::ConvertCellRangeAddress(aContent); - ScRangeData* pData = new ScRangeData( - mrDoc, p.sName, aContent, aPos, nNewType, p.eGrammar); - mrRangeName.insert(pData); + std::unique_ptr pData(new ScRangeData( + mrDoc, p.sName, aContent, aPos, nNewType, p.eGrammar)); + mrRangeName.insert(std::move(pData)); } } }; @@ -1314,9 +1314,9 @@ void ScXMLImport::SetNamedRanges() return; // Insert the namedRanges - ScRangeName* pRangeNames = mpDoc->GetRangeName(); + ScRangeName& rRangeNames = mpDoc->GetRangeName(); ::std::for_each(m_aMyNamedExpressions.begin(), m_aMyNamedExpressions.end(), - RangeNameInserter(*mpDoc, *pRangeNames, -1)); + RangeNameInserter(*mpDoc, rRangeNames, -1)); } void ScXMLImport::SetSheetNamedRanges() @@ -1407,6 +1407,14 @@ void SAL_CALL ScXMLImport::endDocument() mpDoc->GetExternalRefManager()->updateAbsAfterLoad(); } + // tdf#171228 - compute page size once per sheet after row visibility was applied + if (mpDoc) + { + const SCTAB nTabCount = mpDoc->GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; ++nTab) + mpDoc->SetDrawPageSize(nTab); + } + // If the stream contains cells outside of the current limits, the styles can't be re-created, // so stream copying is disabled then. if (mpDoc && GetModel().is() && !mpDoc->HasRangeOverflow()) @@ -1418,7 +1426,6 @@ void SAL_CALL ScXMLImport::endDocument() SCTAB nTabCount = mpDoc->GetTableCount(); for (SCTAB nTab=0; nTabSetDrawPageSize(nTab); if (!pSheetData->IsSheetBlocked( nTab )) mpDoc->SetStreamValid( nTab, true ); } @@ -1614,7 +1621,7 @@ void ScXMLImport::ExtractFormulaNamespaceGrammar( /* Check if a namespace URL could be resolved from the attribute value. Use that namespace only, if the Calc document knows an associated external formula parser. This prevents that the range operator in - conjunction with defined names is confused as namespaces prefix, e.g. + conjunction with defined names is confused as a namespace prefix, e.g. in the expression 'table:A1' where 'table' is a named reference. */ if( ((nNsId & XML_NAMESPACE_UNKNOWN_FLAG) != 0) && !rFormulaNmsp.isEmpty() && mpDoc->GetFormulaParserPool().hasFormulaParser( rFormulaNmsp ) ) @@ -1719,7 +1726,7 @@ extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportFODS(SvStream &rStream) //SetLoading hack because the document properties will be re-initted //by the xml filter and during the init, while it's considered uninitialized, //setting a property will inform the document it's modified, which attempts - //to update the properties, which throws cause the properties are uninitialized + //to update the properties, which throws because the properties are uninitialized xDocSh->SetLoading(SfxLoadedFlags::NONE); bool ret = xFilter->filter(aArgs); xDocSh->SetLoading(SfxLoadedFlags::ALL); @@ -1772,7 +1779,7 @@ extern "C" SAL_DLLPUBLIC_EXPORT bool TestFODSExportXLS(SvStream &rStream) //SetLoading hack because the document properties will be re-initted //by the xml filter and during the init, while it's considered uninitialized, //setting a property will inform the document it's modified, which attempts - //to update the properties, which throws cause the properties are uninitialized + //to update the properties, which throws because the properties are uninitialized xDocSh->SetLoading(SfxLoadedFlags::NONE); bool ret = xFilter->filter(aArgs); xDocSh->SetLoading(SfxLoadedFlags::ALL); @@ -1827,7 +1834,7 @@ extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportXLSX(SvStream &rStream) //SetLoading hack because the document properties will be re-initted //by the xml filter and during the init, while it's considered uninitialized, //setting a property will inform the document it's modified, which attempts - //to update the properties, which throws cause the properties are uninitialized + //to update the properties, which throws because the properties are uninitialized xDocSh->SetLoading(SfxLoadedFlags::NONE); bool ret = false; try diff --git a/sc/source/filter/xml/xmlmappingi.cxx b/sc/source/filter/xml/xmlmappingi.cxx index 5ce0967762ff..809a3cd72560 100644 --- a/sc/source/filter/xml/xmlmappingi.cxx +++ b/sc/source/filter/xml/xmlmappingi.cxx @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -102,6 +103,16 @@ ScXMLMappingContext::ScXMLMappingContext( ScXMLImport& rImport, if (!aProvider.isEmpty()) { + // Only build the data providers we support. The sql provider is left + // out: it was never finished and was dropped from the dialog in tdf#169079. + if (aProvider != "org.libreoffice.calc.csv" + && aProvider != "org.libreoffice.calc.html" + && aProvider != "org.libreoffice.calc.xml") + { + SAL_WARN("sc", "ignoring document data mapping for provider \"" << aProvider << "\""); + return; + } + ScDocument* pDoc = GetScImport().GetDocument(); auto& rDataMapper = pDoc->GetExternalDataMapper(); sc::ExternalDataSource aSource(aURL, aProvider, pDoc); @@ -111,16 +122,6 @@ ScXMLMappingContext::ScXMLMappingContext( ScXMLImport& rImport, } } -ScXMLMappingContext::~ScXMLMappingContext() -{ - ScDocument* pDoc = GetScImport().GetDocument(); - auto& rDataMapper = pDoc->GetExternalDataMapper(); - auto& rDataSources = rDataMapper.getDataSources(); - if(!rDataSources.empty()) - rDataSources.back().refresh(pDoc, true); - -} - uno::Reference SAL_CALL ScXMLMappingContext::createFastChildContext( sal_Int32 nElement, const uno::Reference& /*xAttrList*/) diff --git a/sc/source/filter/xml/xmlmappingi.hxx b/sc/source/filter/xml/xmlmappingi.hxx index cc38d40dbe93..98a74a7eff31 100644 --- a/sc/source/filter/xml/xmlmappingi.hxx +++ b/sc/source/filter/xml/xmlmappingi.hxx @@ -34,8 +34,6 @@ public: ScXMLMappingContext( ScXMLImport& rImport, const rtl::Reference& rAttrList ); - virtual ~ScXMLMappingContext() override; - virtual css::uno::Reference SAL_CALL createFastChildContext( sal_Int32 nElement, const css::uno::Reference& xAttrList) override; diff --git a/sc/source/filter/xml/xmlrowi.cxx b/sc/source/filter/xml/xmlrowi.cxx index a9c28a796e39..e65d99f77ccd 100644 --- a/sc/source/filter/xml/xmlrowi.cxx +++ b/sc/source/filter/xml/xmlrowi.cxx @@ -264,7 +264,8 @@ ScXMLTableRowsContext::ScXMLTableRowsContext( ScXMLImport& rImport, } else if (bGroup) { - nGroupStartRow = rImport.GetTables().GetCurrentRow(); + ScAddress aAddr = rImport.GetTables().GetCurrentCellPos(); + nGroupStartRow = aAddr.Row(); ++nGroupStartRow; if ( rAttrList.is() ) { diff --git a/sc/source/filter/xml/xmlsubti.cxx b/sc/source/filter/xml/xmlsubti.cxx index 89c2e8d9be17..284cb308f003 100644 --- a/sc/source/filter/xml/xmlsubti.cxx +++ b/sc/source/filter/xml/xmlsubti.cxx @@ -260,7 +260,8 @@ void ScMyTables::AddOLE(const uno::Reference & rShape, void ScMyTables::AddMatrixRange( const SCCOL nStartColumn, const SCROW nStartRow, const SCCOL nEndColumn, const SCROW nEndRow, - const OUString& rFormula, const OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar) + const OUString& rFormula, const OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar, + bool bCachedSpill) { OSL_ENSURE(nEndRow >= nStartRow, "wrong row order"); OSL_ENSURE(nEndColumn >= nStartColumn, "wrong column order"); @@ -269,13 +270,19 @@ void ScMyTables::AddMatrixRange( nEndColumn, nEndRow, maCurrentCellPos.Tab() ); - maMatrixRangeList.push_back(aScRange); + // When the saved file recorded #SPILL!, setMatrixCells will set the + // master's spill error and *not* materialise reference cells across the + // declared range - so cells inside the range need to be treated as + // regular non-matrix cells on import (they're either blockers or + // empty). + if (!bCachedSpill) + maMatrixRangeList.push_back(aScRange); ScDocumentImport& rDoc = rImport.GetDoc(); ScTokenArray aCode(rDoc.getDoc()); aCode.AssignXMLString( rFormula, ((eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) ? rFormulaNmsp : OUString())); - rDoc.setMatrixCells(aScRange, aCode, eGrammar); + rDoc.setMatrixCells(aScRange, aCode, eGrammar, bCachedSpill); rDoc.getDoc().IncXMLImportedFormulaCount( rFormula.getLength() ); } diff --git a/sc/source/filter/xml/xmlsubti.hxx b/sc/source/filter/xml/xmlsubti.hxx index b4c5ed051352..060a61fb9a7d 100644 --- a/sc/source/filter/xml/xmlsubti.hxx +++ b/sc/source/filter/xml/xmlsubti.hxx @@ -97,13 +97,14 @@ public: void AddOLE(const css::uno::Reference & rShape, const OUString &rRangeList); - void AddMatrixRange( const SCCOL nStartColumn, - const SCROW nStartRow, - const SCCOL nEndColumn, - const SCROW nEndRow, - const OUString& rFormula, - const OUString& rFormulaNmsp, - const formula::FormulaGrammar::Grammar ); + void AddMatrixRange(const SCCOL nStartColumn, + const SCROW nStartRow, + const SCCOL nEndColumn, + const SCROW nEndRow, + const OUString& rFormula, + const OUString& rFormulaNmsp, + const formula::FormulaGrammar::Grammar, + bool bCachedSpill = false); bool IsPartOfMatrix( const ScAddress& rScAddress) const; }; diff --git a/sc/source/solver/CoinMPModel.cxx b/sc/source/solver/CoinMPModel.cxx new file mode 100644 index 000000000000..f20ce4adb644 --- /dev/null +++ b/sc/source/solver/CoinMPModel.cxx @@ -0,0 +1,207 @@ +/* -*- 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 +#include + +#include "CoinMPModel.hxx" + +#include +#include + +using namespace com::sun::star; + +CoinMpSolveResult coinmpSolveLinearModel(const uno::Sequence& rVariables, + const uno::Sequence& rConstraints, + const table::CellAddress& rObjective, + const ScSolverCellHashMap& rCells, + const std::vector& rLowerBounds, + const std::vector& rUpperBounds, + const std::vector& rColumnType, bool bMaximize, + double fTimeoutSeconds) +{ + CoinMpSolveResult aResult; + + const size_t nVariables = rVariables.size(); + size_t nVar = 0; + + // objective: slope of each variable, plus the constant term at the origin + const std::vector& rObjectCoefficients = rCells.at(rObjective); + std::unique_ptr pObjectCoefficients(new double[nVariables]); + for (nVar = 0; nVar < nVariables; nVar++) + pObjectCoefficients[nVar] = rObjectCoefficients[nVar + 1]; + double fObjectConstant = rObjectCoefficients[0]; + + // rows: collect all coefficients row-wise first + size_t nRows = rConstraints.getLength(); + size_t nDenseSize = nVariables * nRows; + std::unique_ptr pDenseMatrix(new double[nDenseSize]); + for (size_t i = 0; i < nDenseSize; i++) + pDenseMatrix[i] = 0.0; + + std::unique_ptr pRHS(new double[nRows]); + std::unique_ptr pRowType(new char[nRows]); + for (size_t i = 0; i < nRows; i++) + { + pRHS[i] = 0.0; + pRowType[i] = 'N'; + } + + for (sal_Int32 nConstraintPosition = 0; nConstraintPosition < rConstraints.getLength(); + ++nConstraintPosition) + { + // integer and binary constraints are reflected in the column types + sheet::SolverConstraintOperator eOperator = rConstraints[nConstraintPosition].Operator; + if (eOperator == sheet::SolverConstraintOperator_LESS_EQUAL + || eOperator == sheet::SolverConstraintOperator_GREATER_EQUAL + || eOperator == sheet::SolverConstraintOperator_EQUAL) + { + double fDirectValue = 0.0; + bool bRightCell = false; + table::CellAddress aRightAddress; + const uno::Any& rRightAny = rConstraints[nConstraintPosition].Right; + if (rRightAny >>= aRightAddress) + bRightCell = true; + else + rRightAny >>= fDirectValue; + + table::CellAddress aLeftAddress = rConstraints[nConstraintPosition].Left; + + const std::vector& rLeftCoefficients = rCells.at(aLeftAddress); + double* pValues = &pDenseMatrix[nConstraintPosition * nVariables]; + for (nVar = 0; nVar < nVariables; nVar++) + pValues[nVar] = rLeftCoefficients[nVar + 1]; + + // if the left hand cell has a constant term, move it to the right + double fRightValue = -rLeftCoefficients[0]; + + if (bRightCell) + { + const std::vector& rRightCoefficients = rCells.at(aRightAddress); + for (nVar = 0; nVar < nVariables; nVar++) + pValues[nVar] -= rRightCoefficients[nVar + 1]; + + fRightValue += rRightCoefficients[0]; + } + else + fRightValue += fDirectValue; + + switch (eOperator) + { + case sheet::SolverConstraintOperator_LESS_EQUAL: + pRowType[nConstraintPosition] = 'L'; + break; + case sheet::SolverConstraintOperator_GREATER_EQUAL: + pRowType[nConstraintPosition] = 'G'; + break; + case sheet::SolverConstraintOperator_EQUAL: + pRowType[nConstraintPosition] = 'E'; + break; + default: + break; + } + pRHS[nConstraintPosition] = fRightValue; + } + } + + // turn the row-wise matrix into the column-wise form CoinMP wants + std::unique_ptr pMatrixBegin(new int[nVariables + 1]); + std::unique_ptr pMatrixCount(new int[nVariables]); + std::unique_ptr pMatrix(new double[nDenseSize]); + std::unique_ptr pMatrixIndex(new int[nDenseSize]); + int nMatrixPosition = 0; + for (nVar = 0; nVar < nVariables; nVar++) + { + int nBegin = nMatrixPosition; + for (size_t nRow = 0; nRow < nRows; nRow++) + { + double fCoefficient = pDenseMatrix[nRow * nVariables + nVar]; + if (fCoefficient != 0.0) + { + pMatrix[nMatrixPosition] = fCoefficient; + pMatrixIndex[nMatrixPosition] = nRow; + ++nMatrixPosition; + } + } + pMatrixBegin[nVar] = nBegin; + pMatrixCount[nVar] = nMatrixPosition - nBegin; + } + pMatrixBegin[nVariables] = nMatrixPosition; + pDenseMatrix.reset(); + + std::unique_ptr pLowerBounds(new double[nVariables]); + std::unique_ptr pUpperBounds(new double[nVariables]); + std::unique_ptr pColumnType(new char[nVariables]); + for (nVar = 0; nVar < nVariables; nVar++) + { + pLowerBounds[nVar] = rLowerBounds[nVar]; + pUpperBounds[nVar] = rUpperBounds[nVar]; + pColumnType[nVar] = rColumnType[nVar]; + } + + int nObjectSense = bMaximize ? SOLV_OBJSENS_MAX : SOLV_OBJSENS_MIN; + + HPROB hProblem = CoinCreateProblem(""); + int nResult = CoinLoadProblem(hProblem, nVariables, nRows, nMatrixPosition, 0, nObjectSense, + fObjectConstant, pObjectCoefficients.get(), pLowerBounds.get(), + pUpperBounds.get(), pRowType.get(), pRHS.get(), nullptr, + pMatrixBegin.get(), pMatrixCount.get(), pMatrixIndex.get(), + pMatrix.get(), nullptr, nullptr, nullptr); + if (nResult == SOLV_CALL_SUCCESS) + nResult = CoinLoadInteger(hProblem, pColumnType.get()); + + pColumnType.reset(); + pMatrixIndex.reset(); + pMatrix.reset(); + pMatrixCount.reset(); + pMatrixBegin.reset(); + pUpperBounds.reset(); + pLowerBounds.reset(); + pRowType.reset(); + pRHS.reset(); + pObjectCoefficients.reset(); + + CoinSetRealOption(hProblem, COIN_REAL_MAXSECONDS, fTimeoutSeconds); + CoinSetRealOption(hProblem, COIN_REAL_MIPMAXSEC, fTimeoutSeconds); + + if (nResult == SOLV_CALL_SUCCESS) + nResult = CoinCheckProblem(hProblem); + + if (nResult == SOLV_CALL_SUCCESS) + { + try + { + nResult = CoinOptimizeProblem(hProblem, 0); + } + catch (const CoinError& rError) + { + CoinUnloadProblem(hProblem); + throw std::runtime_error(rError.message()); + } + } + + aResult.bSuccess = (nResult == SOLV_CALL_SUCCESS); + if (aResult.bSuccess) + { + aResult.aSolution.resize(nVariables); + CoinGetSolutionValues(hProblem, aResult.aSolution.data(), nullptr, nullptr, nullptr); + aResult.fObjective = CoinGetObjectValue(hProblem); + } + else + { + aResult.nStatus = CoinGetSolutionStatus(hProblem); + } + + CoinUnloadProblem(hProblem); + + return aResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/solver/CoinMPModel.hxx b/sc/source/solver/CoinMPModel.hxx new file mode 100644 index 000000000000..09928268c767 --- /dev/null +++ b/sc/source/solver/CoinMPModel.hxx @@ -0,0 +1,46 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include +#include +#include + +#include "SolverComponent.hxx" + +#include + +// Result of solving one linear problem with CoinMP. +struct CoinMpSolveResult +{ + bool bSuccess = false; + // CoinGetSolutionStatus when the solve did not succeed: 1 infeasible, + // 2 unbounded, other values for the remaining cases. + int nStatus = 0; + std::vector aSolution; + double fObjective = 0.0; +}; + +// Build a linear problem from already sampled coefficients and solve it with +// CoinMP. For the objective and for each constraint cell, rCells holds a vector +// whose first entry is the value of an affine model of that cell at the origin +// (all variables zero) and whose remaining entries are the slope of each +// variable. The caller supplies the variable bounds and column types (which +// encode integer and binary variables), so the same routine serves both a +// one-shot linear solve and a linearized step of an outer nonlinear loop. +CoinMpSolveResult coinmpSolveLinearModel( + const css::uno::Sequence& rVariables, + const css::uno::Sequence& rConstraints, + const css::table::CellAddress& rObjective, const ScSolverCellHashMap& rCells, + const std::vector& rLowerBounds, const std::vector& rUpperBounds, + const std::vector& rColumnType, bool bMaximize, double fTimeoutSeconds); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/solver/CoinMPSolver.cxx b/sc/source/solver/CoinMPSolver.cxx new file mode 100644 index 000000000000..167a4a36e902 --- /dev/null +++ b/sc/source/solver/CoinMPSolver.cxx @@ -0,0 +1,201 @@ +/* -*- 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 "CoinMPModel.hxx" +#include "SolverComponent.hxx" +#include "strings.hrc" + +#include + +#include +#include + +#include +#include +#include +#include + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace com::sun::star; + +namespace { + +class CoinMPSolver : public SolverComponent +{ +public: + CoinMPSolver() {} + +private: + virtual void SAL_CALL solve() override; + virtual OUString SAL_CALL getImplementationName() override + { + return u"com.sun.star.comp.Calc.CoinMPSolver"_ustr; + } + virtual OUString SAL_CALL getComponentDescription() override + { + return ScResId( RID_COINMP_SOLVER_COMPONENT ); + } +}; + +} + +void SAL_CALL CoinMPSolver::solve() +{ + uno::Reference xModel( mxDoc, uno::UNO_QUERY_THROW ); + + maStatus.clear(); + mbSuccess = false; + + xModel->lockControllers(); + + // collect variables in vector (?) + + const auto & aVariableCells = maVariables; + size_t nVariables = aVariableCells.size(); + size_t nVar = 0; + + // collect all dependent cells + + ScSolverCellHashMap aCellsHash; + aCellsHash[maObjective].reserve( nVariables + 1 ); // objective function + + for (const auto& rConstr : maConstraints) + { + table::CellAddress aCellAddr = rConstr.Left; + aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: left hand side + + if ( rConstr.Right >>= aCellAddr ) + aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: right hand side + } + + // set all variables to zero + //! store old values? + //! use old values as initial values? + for ( const auto& rVarCell : aVariableCells ) + { + SetValue(rVarCell, 0.0); + } + + // read initial values from all dependent cells + for ( auto& rEntry : aCellsHash ) + { + double fValue = GetValue(rEntry.first); + rEntry.second.push_back( fValue ); // store as first element, as-is + } + + // loop through variables + for ( const auto& rVarCell : aVariableCells ) + { + SetValue(rVarCell, 1.0); // set to 1 to examine influence + + // read value change from all dependent cells + for ( auto& rEntry : aCellsHash ) + { + double fChanged = GetValue(rEntry.first); + double fInitial = rEntry.second.front(); + rEntry.second.push_back( fChanged - fInitial ); + } + + SetValue(rVarCell, 2.0); // minimal test for linearity + + for ( const auto& rEntry : aCellsHash ) + { + double fInitial = rEntry.second.front(); + double fCoeff = rEntry.second.back(); // last appended: coefficient for this variable + double fTwo = GetValue(rEntry.first); + + bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) || + rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff ); + // second comparison is needed in case fTwo is zero + if ( !bLinear ) + maStatus = ScResId( RID_ERROR_NONLINEAR ); + } + + SetValue(rVarCell, 0.0); // set back to zero for examining next variable + } + + xModel->unlockControllers(); + + if ( !maStatus.isEmpty() ) + return; + + // variable bounds and column types. The default range is unbounded unless + // non-negativity was requested. Integer and binary single-variable + // constraints refine these. + std::vector aLowerBounds(nVariables, mbNonNegative ? 0.0 : -DBL_MAX); + std::vector aUpperBounds(nVariables, DBL_MAX); + std::vector aColumnType(nVariables, mbInteger ? 'I' : 'C'); + + for (const auto& rConstr : maConstraints) + { + sheet::SolverConstraintOperator eOp = rConstr.Operator; + if ( eOp == sheet::SolverConstraintOperator_INTEGER || + eOp == sheet::SolverConstraintOperator_BINARY ) + { + table::CellAddress aLeftAddr = rConstr.Left; + for (nVar=0; nVar const &) +{ + return cppu::acquire(new CoinMPSolver()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/solver/DEAlgorithm.hxx b/sc/source/solver/DEAlgorithm.hxx new file mode 100644 index 000000000000..fc076eba54de --- /dev/null +++ b/sc/source/solver/DEAlgorithm.hxx @@ -0,0 +1,142 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include "Swarm.hxx" + +#include +#include +#include + +// Where a mutated value that lands outside a variable's bounds is sent. Clamp +// pins it to the nearest bound. Wrap folds it back into the range, keeping its +// offset from the lower bound. +enum class DifferentialBound +{ + Clamp, + Wrap +}; + +// The base the mutant is built around. RandomMember picks a random particle +// (classic differential evolution). GlobalBest uses the swarm's best +// position, which pulls trials toward the best. +enum class DifferentialBase +{ + RandomMember, + GlobalBest +}; + +// One differential evolution generation, a reusable engine any swarm-based +// solver can drive. Each call advances the bound swarm by one generation: for +// every particle it builds a trial by binomial crossover, where each chosen +// dimension takes base + weight * (first - second) kept inside the bounds, and +// keeps the trial only when it improves on the particle (greedy selection). +template class DEAlgorithm +{ + Swarm& mrSwarm; + double mfWeight; + double mfCrossover; + DifferentialBound meBound; + DifferentialBase meBase; + std::uniform_real_distribution<> maRandom01; + std::uniform_int_distribution<> maRandomParticle; + std::uniform_int_distribution<> maRandomDimension; + +public: + DEAlgorithm(Swarm& rSwarm, double fWeight, double fCrossover, + DifferentialBound eBound, DifferentialBase eBase) + : mrSwarm(rSwarm) + , mfWeight(fWeight) + , mfCrossover(fCrossover) + , meBound(eBound) + , meBase(eBase) + , maRandom01(0.0, 1.0) + , maRandomParticle(0, rSwarm.numParticles() > 0 ? int(rSwarm.numParticles() - 1) : 0) + , maRandomDimension(0, rSwarm.dimensionality() > 0 ? int(rSwarm.dimensionality() - 1) : 0) + { + } + + bool next() { return mrSwarm.advance(*this); } + + void step(Particle& rParticle, size_t nParticleIndex) + { + DataProvider& rDataProvider = mrSwarm.dataProvider(); + std::mt19937& rGenerator = mrSwarm.generator(); + std::vector& rParticles = mrSwarm.particles(); + + // The difference vector is taken from two distinct other particles. The + // mutant base is either a third random particle or the swarm's best. + size_t nFirst; + size_t nSecond; + const std::vector* pBase; + if (meBase == DifferentialBase::RandomMember) + { + size_t nBaseParticle; + do + { + nBaseParticle = maRandomParticle(rGenerator); + } while (nBaseParticle == nParticleIndex); + do + { + nFirst = maRandomParticle(rGenerator); + } while (nFirst == nParticleIndex || nFirst == nBaseParticle); + do + { + nSecond = maRandomParticle(rGenerator); + } while (nSecond == nParticleIndex || nSecond == nBaseParticle || nSecond == nFirst); + pBase = &rParticles[nBaseParticle].mPosition; + } + else + { + do + { + nFirst = maRandomParticle(rGenerator); + } while (nFirst == nParticleIndex); + do + { + nSecond = maRandomParticle(rGenerator); + } while (nSecond == nParticleIndex || nSecond == nFirst); + pBase = &mrSwarm.bestPosition(); + } + + const std::vector& rBase = *pBase; + const std::vector& rFirst = rParticles[nFirst].mPosition; + const std::vector& rSecond = rParticles[nSecond].mPosition; + + std::vector aTrial = rParticle.mPosition; + const size_t nDimensionality = rParticle.mPosition.size(); + const size_t nForced = maRandomDimension(rGenerator); + for (size_t nDimension = 0; nDimension < nDimensionality; ++nDimension) + { + if (nDimension == nForced || maRandom01(rGenerator) < mfCrossover) + { + double fMutant + = rBase[nDimension] + mfWeight * (rFirst[nDimension] - rSecond[nDimension]); + aTrial[nDimension] = meBound == DifferentialBound::Wrap + ? rDataProvider.boundVariable(nDimension, fMutant) + : rDataProvider.clampVariable(nDimension, fMutant); + } + } + + // Greedy selection: keep the trial only if it improves on the particle. + double fTrialFitness = rDataProvider.calculateFitness(aTrial); + if (fTrialFitness > rParticle.mCurrentFitness) + { + for (size_t nDimension = 0; nDimension < nDimensionality; ++nDimension) + rParticle.mVelocity[nDimension] + = aTrial[nDimension] - rParticle.mPosition[nDimension]; + rParticle.mPosition = std::move(aTrial); + rParticle.mCurrentFitness = fTrialFitness; + } + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/solver/DEPSOSolver.hxx b/sc/source/solver/DEPSOSolver.hxx new file mode 100644 index 000000000000..e63f1ecb345e --- /dev/null +++ b/sc/source/solver/DEPSOSolver.hxx @@ -0,0 +1,68 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include "Swarm.hxx" +#include "PSOAlgorithm.hxx" +#include "DEAlgorithm.hxx" + +#include + +// A hybrid of particle swarm optimization and differential evolution that +// alternates between the two from one generation to the next over a single +// swarm. An even generation runs one full particle swarm generation: inertia +// plus a pull toward each particle's own best and the swarm's best. An odd +// generation runs one full differential evolution generation whose mutant base +// is the swarm's best, kept only when it improves on the particle. Each +// generation costs one fitness evaluation per particle, the same as either +// method alone, so alternating combines the social convergence of particle +// swarm optimization with the selection pressure and diversity of differential +// evolution without doubling the cost. +// +// It owns no algorithm code of its own: it drives the PSOAlgorithm and +// DEAlgorithm engines, both bound to its swarm. +template class DEPSOSolver +{ + // differential evolution mutation weight and crossover rate + static constexpr double constDifferentialWeight = 0.6; + static constexpr double constCrossover = 0.9; + + Swarm maSwarm; + PSOAlgorithm maParticleSwarm; + DEAlgorithm maDifferential; + +public: + DEPSOSolver(DataProvider& rDataProvider, size_t nNumOfParticles) + : maSwarm(rDataProvider, nNumOfParticles) + , maParticleSwarm(maSwarm) + , maDifferential(maSwarm, constDifferentialWeight, constCrossover, DifferentialBound::Clamp, + DifferentialBase::GlobalBest) + { + } + + void initialize() { maSwarm.initialize(); } + void restart() { maSwarm.restart(); } + + bool next() + { + // Differential evolution needs a difference vector, so fall back to a + // particle swarm generation when there are too few particles. + bool bDifferential = maSwarm.numParticles() >= 3 && (maSwarm.getGeneration() % 2 == 1); + return bDifferential ? maDifferential.next() : maParticleSwarm.next(); + } + + std::vector const& getResult() const { return maSwarm.getResult(); } + int getGeneration() const { return maSwarm.getGeneration(); } + int getLastChange() const { return maSwarm.getLastChange(); } + double getBestFitness() const { return maSwarm.getBestFitness(); } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/solver/DifferentialEvolution.hxx b/sc/source/solver/DifferentialEvolution.hxx new file mode 100644 index 000000000000..4039350124a6 --- /dev/null +++ b/sc/source/solver/DifferentialEvolution.hxx @@ -0,0 +1,46 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include "Swarm.hxx" +#include "DEAlgorithm.hxx" + +#include + +// Standalone differential evolution solver: a swarm driven by the differential +// evolution engine every generation, mutating around a random member. +template class DifferentialEvolutionSolver +{ + static constexpr double constDifferentialWeight = 0.5; // [0, 2] + static constexpr double constCrossoverProbability = 0.9; // [0, 1] + + Swarm maSwarm; + DEAlgorithm maAlgorithm; + +public: + DifferentialEvolutionSolver(DataProvider& rDataProvider, size_t nNumOfParticles) + : maSwarm(rDataProvider, nNumOfParticles) + , maAlgorithm(maSwarm, constDifferentialWeight, constCrossoverProbability, + DifferentialBound::Wrap, DifferentialBase::RandomMember) + { + } + + void initialize() { maSwarm.initialize(); } + void restart() { maSwarm.restart(); } + bool next() { return maAlgorithm.next(); } + + std::vector const& getResult() const { return maSwarm.getResult(); } + int getGeneration() const { return maSwarm.getGeneration(); } + int getLastChange() const { return maSwarm.getLastChange(); } + double getBestFitness() const { return maSwarm.getBestFitness(); } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/solver/PSOAlgorithm.hxx b/sc/source/solver/PSOAlgorithm.hxx new file mode 100644 index 000000000000..321f4f6f0d09 --- /dev/null +++ b/sc/source/solver/PSOAlgorithm.hxx @@ -0,0 +1,75 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include "Swarm.hxx" + +#include +#include + +// One particle swarm generation, a reusable engine any swarm-based solver can +// drive. Each call advances the bound swarm by one generation: every particle's +// velocity is pulled by inertia toward its own best and the swarm's best, then +// its position steps and is clamped. +template class PSOAlgorithm +{ + // inertia + static constexpr double constWeight = 0.729; + // cognitive coefficient + static constexpr double constCognitive = 1.49445; + // social coefficient + static constexpr double constSocial = 1.49445; + + Swarm& mrSwarm; + std::uniform_real_distribution<> maRandom01; + +public: + explicit PSOAlgorithm(Swarm& rSwarm) + : mrSwarm(rSwarm) + , maRandom01(0.0, 1.0) + { + } + + bool next() { return mrSwarm.advance(*this); } + + // Advance one particle: pull its velocity by inertia toward its own best and + // the swarm's best, then step and clamp its position. The move depends only + // on the particle and the swarm's best, so the particle index is unused. + void step(Particle& rParticle, size_t /*nParticleIndex*/) + { + DataProvider& rDataProvider = mrSwarm.dataProvider(); + std::mt19937& rGenerator = mrSwarm.generator(); + const std::vector& rGlobalBest = mrSwarm.bestPosition(); + + double fRandom1 = maRandom01(rGenerator); + double fRandom2 = maRandom01(rGenerator); + + const size_t nDimensionality = rParticle.mPosition.size(); + for (size_t nDimension = 0; nDimension < nDimensionality; ++nDimension) + { + rParticle.mVelocity[nDimension] + = (constWeight * rParticle.mVelocity[nDimension]) + + (constCognitive * fRandom1 + * (rParticle.mBestPosition[nDimension] - rParticle.mPosition[nDimension])) + + (constSocial * fRandom2 + * (rGlobalBest[nDimension] - rParticle.mPosition[nDimension])); + + // The inertia weight below one keeps the velocity bounded on its + // own, so only the position is clamped, which holds the particle + // inside its bounds. + rParticle.mPosition[nDimension] = rDataProvider.clampVariable( + nDimension, rParticle.mPosition[nDimension] + rParticle.mVelocity[nDimension]); + } + rParticle.mCurrentFitness = rDataProvider.calculateFitness(rParticle.mPosition); + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/solver/ParticelSwarmOptimization.hxx b/sc/source/solver/ParticelSwarmOptimization.hxx new file mode 100644 index 000000000000..aa44dd24ad5a --- /dev/null +++ b/sc/source/solver/ParticelSwarmOptimization.hxx @@ -0,0 +1,42 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include "Swarm.hxx" +#include "PSOAlgorithm.hxx" + +#include + +// Standalone particle swarm solver: a swarm driven by the particle swarm engine +// every generation. +template class ParticleSwarmOptimizationSolver +{ + Swarm maSwarm; + PSOAlgorithm maAlgorithm; + +public: + ParticleSwarmOptimizationSolver(DataProvider& rDataProvider, size_t nNumOfParticles) + : maSwarm(rDataProvider, nNumOfParticles) + , maAlgorithm(maSwarm) + { + } + + void initialize() { maSwarm.initialize(); } + void restart() { maSwarm.restart(); } + bool next() { return maAlgorithm.next(); } + + std::vector const& getResult() const { return maSwarm.getResult(); } + int getGeneration() const { return maSwarm.getGeneration(); } + int getLastChange() const { return maSwarm.getLastChange(); } + double getBestFitness() const { return maSwarm.getBestFitness(); } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/solver/SlpSolver.cxx b/sc/source/solver/SlpSolver.cxx new file mode 100644 index 000000000000..ee0b2a1dcd0f --- /dev/null +++ b/sc/source/solver/SlpSolver.cxx @@ -0,0 +1,656 @@ +/* -*- 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 "CoinMPModel.hxx" +#include "SolverComponent.hxx" +#include "strings.hrc" + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +using namespace com::sun::star; + +namespace +{ +// Sequential Quadratic Programming (SQP) solver for smooth nonlinear models. +// CoinMP can only solve straight-line (linear) problems, so this solver reaches +// a nonlinear optimum by solving a sequence of small quadratic problems, each a +// local model of the real one around the latest point. The quadratic curvature +// lets it converge in far fewer steps than a purely linear model would. +// +// Starting from the current cell values, it repeats four steps until the point +// stops moving: +// +// 1. Sample an affine model of the objective and every constraint cell around +// the current point by nudging each variable a little (a finite difference). +// This gives the objective gradient and a linear approximation of every +// constraint. +// +// 2. Build a quadratic model of the objective: its gradient plus a curvature +// term held in a matrix that a damped BFGS (Broyden-Fletcher-Goldfarb-Shanno) +// update keeps positive definite as the gradient changes from step to step. +// +// 3. Minimize that quadratic over the linearized constraints, kept as hard +// constraints so every point stays feasible, inside a trust region. The +// quadratic subproblem is solved by Frank-Wolfe: each inner iteration +// minimizes a linear objective over the same feasible region with CoinMP and +// takes a line-search step towards the vertex it returns. +// +// 4. Score the trial point with a merit function, its objective plus a large +// penalty for any constraint violation, and keep it only if the merit beats +// the current point. Resize the trust region from how well the quadratic +// model predicted the real change, and refresh the curvature from the new +// gradient. +// +// The loop ends when the step becomes negligible, the trust region collapses, +// the iteration limit is reached, or the time budget runs out. Success is +// reported only when the final point actually satisfies the constraints. +// +// The pieces are standard. The sequential quadratic model, the damped BFGS +// curvature update, the trust region, and the penalty merit function are +// covered by Nocedal and Wright, Numerical Optimization, second edition +// (Springer, 2006). Frank-Wolfe, used for the inner subproblem, is from Frank +// and Wolfe, "An algorithm for quadratic programming", Naval Research Logistics +// Quarterly 3 (1956), 95-110. +class SLPSolver : public SolverComponent +{ +public: + SLPSolver() {} + +private: + virtual void SAL_CALL solve() override; + virtual OUString SAL_CALL getImplementationName() override + { + return u"com.sun.star.comp.Calc.SLPSolver"_ustr; + } + virtual OUString SAL_CALL getComponentDescription() override + { + return ScResId(RID_SLP_SOLVER_COMPONENT); + } + + void applyPoint(const std::vector& rPoint); + // Raw objective value at the current cell values. + double objectiveAt(); + // Total amount by which the current cell values break the constraints. + double violationAt(); + // Value to minimize: the objective for a minimize model, its negation for a + // maximize model. + double cost(double fObjective) const { return mbMaximize ? -fObjective : fObjective; } + // Merit score of a point: its cost plus fPenalty for each unit of constraint + // violation. Leaves the variable cells holding rPoint. + double meritAt(const std::vector& rPoint, double fPenalty); + + // Fill rLower and rUpper from the single-variable constant constraints and + // the non-negative option. + void deriveBounds(std::vector& rLower, std::vector& rUpper); + // A representative magnitude for each variable: the width of a finite range, + // otherwise the size of the starting value. + std::vector deriveScale(const std::vector& rLower, + const std::vector& rUpper, + const std::vector& rStart); + // The finite-difference step for each variable: a small fraction of its + // scale, with an absolute floor so a near-zero scale is still probed. + std::vector deriveStep(const std::vector& rScale); + // The starting BFGS curvature matrix, a diagonal that balances the variable + // scales so the quadratic term is comparable across variables. + std::vector initialCurvature(const std::vector& rScale); + + // Build an affine model of the objective and every constraint cell around + // rPoint. For each dependent cell the returned vector holds the model's value + // extrapolated to the origin (all variables zero) at index 0, and the slope + // along variable j from a finite difference of size rStep[j] at index j+1. + // Leaves the variable cells holding rPoint. + ScSolverCellHashMap sampleAffineModel(const std::vector& rPoint, + const std::vector& rStep); + + // The gradient of the cost with respect to each variable, read from the + // objective slopes in rCells. For a maximize model the sign is flipped so + // the gradient always points in the minimize direction. + std::vector costGradient(const ScSolverCellHashMap& rCells); + + // Find the step d that most improves the quadratic model of the objective + // without leaving the feasible region. The model is 0.5 d' B d + g' d, where + // g (rGradient) is the objective gradient at the current point and B (rB) is + // the BFGS curvature matrix, so the expression estimates how much the + // objective changes for a step d. The feasible region is the linearized + // constraints carried in rCells together with the trust-region box + // [rTrustLower, rTrustUpper], so the new point rX + d obeys the linearized + // constraints and stays inside the region where the model is trusted. + // + // The subproblem is solved by Frank-Wolfe (the conditional-gradient method), + // which only ever minimizes a linear objective over that region, so each + // inner step is a single CoinMP solve. An inner step takes the gradient of + // the quadratic model at the current d (which is B d + g), asks CoinMP for + // the feasible point that minimizes it (a vertex of the region), and moves d + // partway towards that vertex by an exact line search of the quadratic. Every + // vertex is feasible, so d stays feasible throughout, and the loop stops once + // moving towards the best vertex can no longer improve the model. + // + // Returns the step d (the new point is rX + d), or an empty vector if the + // linearized problem has no feasible point inside this trust region. + std::vector solveTrustRegionQp(const ScSolverCellHashMap& rCells, + const std::vector& rB, + const std::vector& rGradient, + const std::vector& rX, + const std::vector& rTrustLower, + const std::vector& rTrustUpper, + const std::vector& rColumnType, double fTimeout); + + // Write rPoint back as the solution when it satisfies the model, otherwise + // record an infeasible status. + void reportSolution(const std::vector& rPoint); +}; + +double dotProduct(const std::vector& rLeft, const std::vector& rRight) +{ + double fSum = 0.0; + for (size_t i = 0; i < rLeft.size(); ++i) + fSum += rLeft[i] * rRight[i]; + return fSum; +} + +// Dense row-major square matrix times a vector. +std::vector multiplyMatrixVector(const std::vector& rMatrix, + const std::vector& rVector) +{ + size_t nSize = rVector.size(); + std::vector aResult(nSize, 0.0); + for (size_t i = 0; i < nSize; ++i) + { + const double* pRow = &rMatrix[i * nSize]; + double fSum = 0.0; + for (size_t j = 0; j < nSize; ++j) + fSum += pRow[j] * rVector[j]; + aResult[i] = fSum; + } + return aResult; +} + +// Refresh the curvature matrix rB from one step of progress, so the next +// quadratic model bends the way the objective actually bent over that step. +// +// BFGS (Broyden, Fletcher, Goldfarb and Shanno) learns the curvature rather +// than computing it. The true second derivatives would cost many extra cell +// recalculations, so instead it watches how the gradient changed +// (rGradientChange) over how far the point moved (rPointChange). A gradient +// that swings sharply over a short move means high curvature there. Each such +// pair folds into rB with a small update, so rB grows more accurate the longer +// the solver runs, at no extra sampling cost. +// +// The plain update only keeps rB a true upward-curving bowl (positive definite, +// the shape a minimum sits in) when the point move and the gradient change +// point the same way. The damping, due to Powell, blends the gradient change +// towards the old curvature whenever they do not, so rB stays positive definite +// even on a bumpy nonlinear problem. +void updateCurvature(std::vector& rB, const std::vector& rPointChange, + const std::vector& rGradientChange) +{ + const size_t nVariables = rPointChange.size(); + std::vector aBs = multiplyMatrixVector(rB, rPointChange); + double fSBs = dotProduct(rPointChange, aBs); + double fSy = dotProduct(rPointChange, rGradientChange); + if (fSBs <= 0.0) + return; + + constexpr double fDampingThreshold = 0.2; + constexpr double fDampingScale = 0.8; + double fTheta = 1.0; + if (fSy < fDampingThreshold * fSBs) + fTheta = fDampingScale * fSBs / (fSBs - fSy); + std::vector aR(nVariables); + for (size_t j = 0; j < nVariables; ++j) + { + aR[j] = fTheta * rGradientChange[j] + (1.0 - fTheta) * aBs[j]; + } + double fSr = dotProduct(rPointChange, aR); + if (fSr > 1.0e-12) + { + for (size_t i = 0; i < nVariables; ++i) + { + for (size_t j = 0; j < nVariables; ++j) + { + rB[i * nVariables + j] += -aBs[i] * aBs[j] / fSBs + aR[i] * aR[j] / fSr; + } + } + } +} + +void SLPSolver::applyPoint(const std::vector& rPoint) +{ + for (size_t i = 0; i < maVariables.size(); ++i) + SetValue(maVariables[i], rPoint[i]); +} + +double SLPSolver::objectiveAt() { return GetValue(maObjective); } + +double SLPSolver::violationAt() +{ + double fTotal = 0.0; + for (const auto& rConstraint : maConstraints) + { + sheet::SolverConstraintOperator eOperator = rConstraint.Operator; + if (eOperator != sheet::SolverConstraintOperator_LESS_EQUAL + && eOperator != sheet::SolverConstraintOperator_GREATER_EQUAL + && eOperator != sheet::SolverConstraintOperator_EQUAL) + continue; + + double fLeft = GetValue(rConstraint.Left); + double fRight = 0.0; + table::CellAddress aRightAddress; + if (rConstraint.Right >>= aRightAddress) + fRight = GetValue(aRightAddress); + else if (!(rConstraint.Right >>= fRight)) + continue; + + double fExcess; + if (eOperator == sheet::SolverConstraintOperator_LESS_EQUAL) + fExcess = fLeft - fRight; // Feasible when not positive. + else if (eOperator == sheet::SolverConstraintOperator_GREATER_EQUAL) + fExcess = fRight - fLeft; + else + fExcess = std::abs(fLeft - fRight); // Equality: any difference is a violation. + + if (fExcess > 0.0) + fTotal += fExcess; + } + return fTotal; +} + +double SLPSolver::meritAt(const std::vector& rPoint, double fPenalty) +{ + applyPoint(rPoint); + return cost(objectiveAt()) + fPenalty * violationAt(); +} + +void SLPSolver::deriveBounds(std::vector& rLower, std::vector& rUpper) +{ + const size_t nVariables = maVariables.size(); + // Fold single-variable constant constraints into box bounds. They remain + // ordinary constraint rows too. + rLower.assign(nVariables, mbNonNegative ? 0.0 : -DBL_MAX); + rUpper.assign(nVariables, DBL_MAX); + + // A constant on the right and the variable on the left is a plain bound. It + // is still passed to the subproblem as an ordinary row as well. + for (const auto& rConstraint : maConstraints) + { + sheet::SolverConstraintOperator eOperator = rConstraint.Operator; + double fRhs = 0.0; + if (!(rConstraint.Right >>= fRhs)) + continue; + for (size_t j = 0; j < nVariables; ++j) + { + if (!AddressEqual(maVariables[j], rConstraint.Left)) + continue; + if (eOperator == sheet::SolverConstraintOperator_LESS_EQUAL && fRhs < rUpper[j]) + rUpper[j] = fRhs; + else if (eOperator == sheet::SolverConstraintOperator_GREATER_EQUAL && fRhs > rLower[j]) + rLower[j] = fRhs; + else if (eOperator == sheet::SolverConstraintOperator_EQUAL) + { + rLower[j] = fRhs; + rUpper[j] = fRhs; + } + } + } +} + +std::vector SLPSolver::deriveScale(const std::vector& rLower, + const std::vector& rUpper, + const std::vector& rStart) +{ + const size_t nVariables = maVariables.size(); + std::vector aScale(nVariables); + for (size_t j = 0; j < nVariables; ++j) + { + // The width of a finite range, otherwise the size of the starting value. + if (rLower[j] > -DBL_MAX && rUpper[j] < DBL_MAX && rUpper[j] > rLower[j]) + aScale[j] = rUpper[j] - rLower[j]; + else + aScale[j] = std::max(1.0, std::abs(rStart[j])); + } + return aScale; +} + +std::vector SLPSolver::deriveStep(const std::vector& rScale) +{ + const size_t nVariables = maVariables.size(); + constexpr double fRelativeStep = 1.0e-6; + constexpr double fStepFloor = 1.0e-7; + std::vector aStep(nVariables); + for (size_t j = 0; j < nVariables; ++j) + aStep[j] = std::max(fStepFloor, fRelativeStep * rScale[j]); + return aStep; +} + +std::vector SLPSolver::initialCurvature(const std::vector& rScale) +{ + const size_t nVariables = maVariables.size(); + std::vector aB(nVariables * nVariables, 0.0); + for (size_t j = 0; j < nVariables; ++j) + aB[j * nVariables + j] = 1.0 / (rScale[j] * rScale[j]); + return aB; +} + +std::vector +SLPSolver::solveTrustRegionQp(const ScSolverCellHashMap& rCells, const std::vector& rB, + const std::vector& rGradient, const std::vector& rX, + const std::vector& rTrustLower, + const std::vector& rTrustUpper, + const std::vector& rColumnType, double fTimeout) +{ + const size_t nVariables = rX.size(); + std::vector aD(nVariables, 0.0); // Step, starts at zero (the point rX). + + // The linearized constraints stay the same throughout. Only the objective + // row changes each iteration, so copy the cells once and rewrite that row in + // place. The map is never restructured here, so the reference stays valid. + ScSolverCellHashMap aLinearCells = rCells; + std::vector& rObjectCoefficients = aLinearCells[maObjective]; + + constexpr int nMaxFrankWolfe = 50; + constexpr double fGapTolerance = 1.0e-9; + constexpr double fGapFraction = 1.0e-3; + double fInitialGap = 0.0; + for (int nFrankWolfe = 0; nFrankWolfe < nMaxFrankWolfe; ++nFrankWolfe) + { + // Gradient of the quadratic model at the current step: B d + g. + std::vector aQuadraticGradient = multiplyMatrixVector(rB, aD); + for (size_t j = 0; j < nVariables; ++j) + aQuadraticGradient[j] += rGradient[j]; + + // Minimize that linear objective over the feasible region: put the + // quadratic-model gradient in as the objective coefficients. + rObjectCoefficients.assign(nVariables + 1, 0.0); + for (size_t j = 0; j < nVariables; ++j) + rObjectCoefficients[j + 1] = aQuadraticGradient[j]; + + CoinMpSolveResult aLinearResult = coinmpSolveLinearModel( + maVariables, maConstraints, maObjective, aLinearCells, rTrustLower, rTrustUpper, + rColumnType, /*bMaximize*/ false, fTimeout); + if (!aLinearResult.bSuccess) + return std::vector(); // Infeasible in this trust region. + + // Frank-Wolfe vertex as a step from rX, and the search direction. + std::vector aDirection(nVariables); + for (size_t j = 0; j < nVariables; ++j) + aDirection[j] = (aLinearResult.aSolution[j] - rX[j]) - aD[j]; + + // Duality gap: how much the linear model could still improve. + double fGap = -dotProduct(aQuadraticGradient, aDirection); + if (nFrankWolfe == 0) + fInitialGap = fGap; + // Stop once the subproblem is solved well enough: the gap has shrunk to + // a small fraction of its initial value, or below an absolute floor. + // Driving the gap all the way to zero is wasted work, because the outer + // trust-region loop re-samples and re-solves around the accepted step. + if (fGap < fGapTolerance || fGap < fGapFraction * fInitialGap) + break; + + // Exact line search of the quadratic along the Frank-Wolfe direction. + std::vector aBDirection = multiplyMatrixVector(rB, aDirection); + double fDenominator = dotProduct(aDirection, aBDirection); + double fGamma = fDenominator > 1.0e-12 ? std::clamp(fGap / fDenominator, 0.0, 1.0) : 1.0; + + for (size_t j = 0; j < nVariables; ++j) + aD[j] += fGamma * aDirection[j]; + } + return aD; +} + +ScSolverCellHashMap SLPSolver::sampleAffineModel(const std::vector& rPoint, + const std::vector& rStep) +{ + const size_t nVariables = maVariables.size(); + + // The dependent cells are the objective and each side of every constraint. + ScSolverCellHashMap aCells; + aCells[maObjective].reserve(nVariables + 1); + for (const auto& rConstraint : maConstraints) + { + aCells[rConstraint.Left].reserve(nVariables + 1); + table::CellAddress aRightAddress; + if (rConstraint.Right >>= aRightAddress) + aCells[aRightAddress].reserve(nVariables + 1); + } + + // Value of every dependent cell at the base point, stored at index 0 for now. + for (size_t j = 0; j < nVariables; ++j) + SetValue(maVariables[j], rPoint[j]); + for (auto& rEntry : aCells) + rEntry.second.push_back(GetValue(rEntry.first)); + + // Perturb one variable at a time to estimate the slope of every cell. + for (size_t j = 0; j < nVariables; ++j) + { + SetValue(maVariables[j], rPoint[j] + rStep[j]); + for (auto& rEntry : aCells) + { + double fBase = rEntry.second.front(); + double fPerturbed = GetValue(rEntry.first); + rEntry.second.push_back((fPerturbed - fBase) / rStep[j]); + } + SetValue(maVariables[j], rPoint[j]); + } + + // Turn the base value at index 0 into the model's value at the origin: + // f(0) = f(point) - sum_j (slope_j * point_j). + for (auto& rEntry : aCells) + { + double fAtOrigin = rEntry.second.front(); + for (size_t j = 0; j < nVariables; ++j) + fAtOrigin -= rEntry.second[j + 1] * rPoint[j]; + rEntry.second.front() = fAtOrigin; + } + + return aCells; +} + +std::vector SLPSolver::costGradient(const ScSolverCellHashMap& rCells) +{ + const size_t nVariables = maVariables.size(); + const std::vector& rObjectCoefficients = rCells.at(maObjective); + double fSign = mbMaximize ? -1.0 : 1.0; + std::vector aGradient(nVariables); + for (size_t j = 0; j < nVariables; ++j) + aGradient[j] = fSign * rObjectCoefficients[j + 1]; + return aGradient; +} + +void SLPSolver::reportSolution(const std::vector& rPoint) +{ + applyPoint(rPoint); + double fObjective = objectiveAt(); + double fViolation = violationAt(); + + // Report success only when the final point really satisfies the model. + // The tolerance scales with the objective magnitude. + constexpr double fFeasibilityTolerance = 1.0e-6; + bool bFeasible = fViolation <= fFeasibilityTolerance * (1.0 + std::abs(fObjective)); + mbSuccess = bFeasible; + if (bFeasible) + { + maSolution.realloc(maVariables.size()); + std::copy(rPoint.begin(), rPoint.end(), maSolution.getArray()); + mfResultValue = fObjective; + } + else + { + maStatus = ScResId(RID_ERROR_INFEASIBLE); + } +} + +void SAL_CALL SLPSolver::solve() +{ + uno::Reference xModel(mxDoc, uno::UNO_QUERY_THROW); + + maStatus.clear(); + mbSuccess = false; + + const size_t nVariables = maVariables.size(); + if (nVariables == 0) + return; + + xModel->lockControllers(); + comphelper::ScopeGuard aUnlockGuard([&xModel] { xModel->unlockControllers(); }); + + std::vector aLower; + std::vector aUpper; + deriveBounds(aLower, aUpper); + + // Starting point: the current cell values, clamped to the bounds. + std::vector aX(nVariables); + for (size_t j = 0; j < nVariables; ++j) + aX[j] = std::clamp(GetValue(maVariables[j]), aLower[j], aUpper[j]); + + std::vector aScale = deriveScale(aLower, aUpper, aX); + std::vector aStep = deriveStep(aScale); + + std::vector aColumnType(nVariables, mbInteger ? 'I' : 'C'); + + std::vector aB = initialCurvature(aScale); + + // SQP tuning parameters. The trust region is a fraction of each variable's + // scale: it grows by fTrustGrow when the quadratic model predicts a step well + // (ratio above fGoodRatio) and shrinks by fTrustShrink otherwise (ratio below + // fPoorRatio, an empty subproblem, or a rejected step). The loop stops once + // the relative step is below fStepTolerance or the radius below fTrustMin. + constexpr double fPenalty = 1.0e4; + constexpr double fInitialTrust = 0.3; + constexpr double fTrustMin = 1.0e-9; + constexpr double fTrustMax = 1.0; + constexpr double fTrustGrow = 2.0; + constexpr double fTrustShrink = 0.5; + constexpr double fGoodRatio = 0.75; + constexpr double fPoorRatio = 0.25; + constexpr double fStepTolerance = 1.0e-8; + constexpr double fMinPredictedReduction = 1.0e-12; + constexpr double fDefaultTimeout = 100.0; + // High safety limit only. The time budget and the convergence test below + // are what normally end the loop, so a large model is not cut off early. + constexpr sal_Int32 nMaxIterations = 100000; + + double fTrust = fInitialTrust; + double fMerit = meritAt(aX, fPenalty); + ScSolverCellHashMap aCells = sampleAffineModel(aX, aStep); + std::vector aGradient = costGradient(aCells); + + const double fTimeout = mnTimeout > 0 ? double(mnTimeout) : fDefaultTimeout; + auto aStart = std::chrono::steady_clock::now(); + + for (sal_Int32 nIteration = 0; nIteration < nMaxIterations; ++nIteration) + { + std::chrono::duration aElapsed = std::chrono::steady_clock::now() - aStart; + if (aElapsed.count() >= fTimeout) + break; + + // Trust-region bounds, kept inside the real variable bounds. + std::vector aTrustLower(nVariables); + std::vector aTrustUpper(nVariables); + for (size_t j = 0; j < nVariables; ++j) + { + aTrustLower[j] = std::max(aLower[j], aX[j] - fTrust * aScale[j]); + aTrustUpper[j] = std::min(aUpper[j], aX[j] + fTrust * aScale[j]); + if (aTrustUpper[j] < aTrustLower[j]) + aTrustUpper[j] = aTrustLower[j]; + } + + std::vector aDelta = solveTrustRegionQp(aCells, aB, aGradient, aX, aTrustLower, + aTrustUpper, aColumnType, fTimeout); + if (aDelta.empty()) + { + fTrust *= fTrustShrink; + if (fTrust < fTrustMin) + break; + continue; + } + + std::vector aTrial(nVariables); + for (size_t j = 0; j < nVariables; ++j) + aTrial[j] = aX[j] + aDelta[j]; + + double fMeritTrial = meritAt(aTrial, fPenalty); + + // Reduction the quadratic model predicted: -(g'd + 0.5 d'B d). + std::vector aBDelta = multiplyMatrixVector(aB, aDelta); + double fPredicted = -(dotProduct(aGradient, aDelta) + 0.5 * dotProduct(aDelta, aBDelta)); + double fActual = fMerit - fMeritTrial; + + double fStepRelative = 0.0; + for (size_t j = 0; j < nVariables; ++j) + fStepRelative = std::max(fStepRelative, std::abs(aDelta[j]) / aScale[j]); + + if (fActual > 0.0) + { + // Accept: sample at the new point and update the curvature. + ScSolverCellHashMap aCellsNew = sampleAffineModel(aTrial, aStep); + std::vector aNewGradient = costGradient(aCellsNew); + + std::vector aPointChange(nVariables); + std::vector aGradientChange(nVariables); + for (size_t j = 0; j < nVariables; ++j) + { + aPointChange[j] = aTrial[j] - aX[j]; + aGradientChange[j] = aNewGradient[j] - aGradient[j]; + } + updateCurvature(aB, aPointChange, aGradientChange); + + aX = std::move(aTrial); + aGradient = std::move(aNewGradient); + aCells = std::move(aCellsNew); + fMerit = fMeritTrial; + + double fRatio = fPredicted > fMinPredictedReduction ? fActual / fPredicted : 1.0; + if (fRatio > fGoodRatio) + fTrust = std::min(fTrustMax, fTrust * fTrustGrow); + else if (fRatio < fPoorRatio) + fTrust *= fTrustShrink; + } + else + { + // The trial did not improve the merit, so reject it and shrink the + // trust region. + fTrust *= fTrustShrink; + } + + if (fStepRelative < fStepTolerance && fActual <= 0.0) + break; + if (fTrust < fTrustMin) + break; + } + + reportSolution(aX); +} +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_Calc_SLPSolver_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence const&) +{ + return cppu::acquire(new SLPSolver()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/SolverComponent.cxx b/sc/source/solver/SolverComponent.cxx similarity index 80% rename from sccomp/source/solver/SolverComponent.cxx rename to sc/source/solver/SolverComponent.cxx index a06b65f4c46a..c7434e332ac9 100644 --- a/sccomp/source/solver/SolverComponent.cxx +++ b/sc/source/solver/SolverComponent.cxx @@ -18,7 +18,7 @@ */ #include "SolverComponent.hxx" -#include +#include "strings.hrc" #include #include @@ -26,11 +26,16 @@ #include #include +#include #include -using namespace com::sun::star; +#include +#include +#include +#include +using namespace com::sun::star; constexpr OUStringLiteral STR_NONNEGATIVE = u"NonNegative"; constexpr OUStringLiteral STR_INTEGER = u"Integer"; @@ -40,14 +45,6 @@ constexpr OUStringLiteral STR_LIMITBBDEPTH = u"LimitBBDepth"; constexpr OUStringLiteral STR_GEN_SENSITIVITY = u"GenSensitivityReport"; constexpr OUStringLiteral STR_SENSITIVITY_REPORT = u"SensitivityReport"; - -// Resources from tools are used for translated strings - -OUString SolverComponent::GetResourceString(TranslateId aId) -{ - return Translate::get(aId, Translate::Create("scc")); -} - size_t ScSolverCellHash::operator()( const css::table::CellAddress& rAddress ) const { return ( rAddress.Sheet << 24 ) | ( rAddress.Column << 16 ) | rAddress.Row; @@ -72,24 +69,21 @@ namespace }; } -uno::Reference SolverComponent::GetCell( const uno::Reference& xDoc, - const table::CellAddress& rPos ) +void SolverComponent::SetValue(const table::CellAddress& rPosition, double fValue) { - uno::Reference xSheets( xDoc->getSheets(), uno::UNO_QUERY ); - uno::Reference xSheet( xSheets->getByIndex( rPos.Sheet ), uno::UNO_QUERY ); - return xSheet->getCellByPosition( rPos.Column, rPos.Row ); + if (mpDocument) + mpDocument->SetValue(ScAddress(SCCOL(rPosition.Column), + SCROW(rPosition.Row), + SCTAB(rPosition.Sheet)), fValue); } -void SolverComponent::SetValue( const uno::Reference& xDoc, - const table::CellAddress& rPos, double fValue ) +double SolverComponent::GetValue(const table::CellAddress& rPosition) { - SolverComponent::GetCell( xDoc, rPos )->setValue( fValue ); -} - -double SolverComponent::GetValue( const uno::Reference& xDoc, - const table::CellAddress& rPos ) -{ - return SolverComponent::GetCell( xDoc, rPos )->getValue(); + if (!mpDocument) + return 0.0; + return mpDocument->GetValue(ScAddress(SCCOL(rPosition.Column), + SCROW(rPosition.Row), + SCTAB(rPosition.Sheet))); } SolverComponent::SolverComponent() : @@ -119,9 +113,6 @@ SolverComponent::~SolverComponent() { } -IMPLEMENT_FORWARD_XINTERFACE2( SolverComponent, SolverComponent_Base, comphelper::OPropertyContainer2 ) -IMPLEMENT_FORWARD_XTYPEPROVIDER2( SolverComponent, SolverComponent_Base, comphelper::OPropertyContainer2 ) - cppu::IPropertyArrayHelper* SolverComponent::createArrayHelper() const { uno::Sequence aProps; @@ -129,16 +120,6 @@ cppu::IPropertyArrayHelper* SolverComponent::createArrayHelper() const return new cppu::OPropertyArrayHelper( aProps ); } -cppu::IPropertyArrayHelper& SolverComponent::getInfoHelper() -{ - return *getArrayHelper(); -} - -uno::Reference SAL_CALL SolverComponent::getPropertySetInfo() -{ - return createPropertySetInfo( getInfoHelper() ); -} - // XSolverDescription OUString SAL_CALL SolverComponent::getStatusDescription() @@ -177,7 +158,7 @@ OUString SAL_CALL SolverComponent::getPropertyDescription( const OUString& rProp } OUString aRet; if (pResId) - aRet = SolverComponent::GetResourceString(pResId); + aRet = ScResId(pResId); return aRet; } @@ -191,6 +172,15 @@ uno::Reference SAL_CALL SolverComponent::getDocumen void SAL_CALL SolverComponent::setDocument( const uno::Reference& _document ) { mxDoc = _document; + mpDocument = nullptr; + if (ScModelObj* pModel = comphelper::getFromUnoTunnel(mxDoc)) + { + mpDocument = pModel->GetDocument(); + // The solver writes input cells and reads the recalculated objective and + // constraint cells, which needs automatic recalculation to be on. + if ( mpDocument ) + mpDocument->SetAutoCalc( true ); + } } table::CellAddress SAL_CALL SolverComponent::getObjective() diff --git a/sccomp/source/solver/SolverComponent.hxx b/sc/source/solver/SolverComponent.hxx similarity index 81% rename from sccomp/source/solver/SolverComponent.hxx rename to sc/source/solver/SolverComponent.hxx index 543eeedea282..929e949be447 100644 --- a/sccomp/source/solver/SolverComponent.hxx +++ b/sc/source/solver/SolverComponent.hxx @@ -24,16 +24,16 @@ #include #include #include -#include -#include -#include -#include + +#include #include #include namespace com::sun::star::table { class XCell; } +class ScDocument; + // hash map for the coefficients of a dependent cell (objective or constraint) // The size of each vector is the number of columns (variable cells) plus one, first entry is initial value. @@ -54,19 +54,20 @@ struct ScSolverCellEqual typedef std::unordered_map< css::table::CellAddress, std::vector, ScSolverCellHash, ScSolverCellEqual > ScSolverCellHashMap; -typedef comphelper::WeakImplHelper< - css::sheet::XSolver, - css::sheet::XSolverDescription, - css::lang::XServiceInfo > - SolverComponent_Base; - -class SolverComponent : public comphelper::OPropertyContainer2, - public comphelper::OPropertyArrayUsageHelper< SolverComponent >, - public SolverComponent_Base +class SolverComponent + : public comphelper::OPropertyContainerImplHelper< + comphelper::WeakImplHelper< + css::sheet::XSolver, + css::sheet::XSolverDescription, + css::lang::XServiceInfo>, + SolverComponent> { protected: // settings css::uno::Reference< css::sheet::XSpreadsheetDocument > mxDoc; + // The ScDocument behind mxDoc, recovered through the UNO tunnel. Null until + // setDocument runs. + ScDocument* mpDocument = nullptr; css::table::CellAddress maObjective; css::uno::Sequence< css::table::CellAddress > maVariables; css::uno::Sequence< css::sheet::SolverConstraint > maConstraints; @@ -96,26 +97,14 @@ protected: css::uno::Sequence m_aConstrDecrease; css::sheet::SensitivityReport m_aSensitivityReport; - static OUString GetResourceString(TranslateId aId); - static css::uno::Reference GetCell( - const css::uno::Reference& xDoc, - const css::table::CellAddress& rPos ); - static void SetValue( - const css::uno::Reference& xDoc, - const css::table::CellAddress& rPos, double fValue ); - static double GetValue( - const css::uno::Reference& xDoc, - const css::table::CellAddress& rPos ); + // Direct cell access through mpDocument. + void SetValue(const css::table::CellAddress& rPosition, double fValue); + double GetValue(const css::table::CellAddress& rPosition); public: SolverComponent(); virtual ~SolverComponent() override; - DECLARE_XINTERFACE() - DECLARE_XTYPEPROVIDER() - - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override; - virtual ::cppu::IPropertyArrayHelper& getInfoHelper() override; // from OPropertySetHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override; // from OPropertyArrayUsageHelper // XSolver diff --git a/sc/source/solver/Swarm.hxx b/sc/source/solver/Swarm.hxx new file mode 100644 index 000000000000..cd3ea01c3afa --- /dev/null +++ b/sc/source/solver/Swarm.hxx @@ -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/. + * + */ + +#pragma once + +#include +#include +#include +#include + +struct Particle +{ + Particle(size_t nDimensionality) + : mVelocity(nDimensionality) + , mPosition(nDimensionality) + , mCurrentFitness(std::numeric_limits::lowest()) + , mBestPosition(nDimensionality) + , mBestFitness(std::numeric_limits::lowest()) + { + } + + std::vector mVelocity; + + std::vector mPosition; + double mCurrentFitness; + + std::vector mBestPosition; + double mBestFitness; +}; + +// The shared state of a swarm search: the particles, the best position and +// fitness found so far, and the generation counters. It owns the random +// generator, builds and rebuilds the swarm, and folds each particle's fitness +// into the bests. A per-generation algorithm advances it through this shared +// scaffolding rather than each one repeating it. +template class Swarm +{ + static constexpr double constAcceptedPrecision = 0.000000001; + + DataProvider& mrDataProvider; + size_t mnNumOfParticles; + + std::random_device maRandomDevice; + std::mt19937 maGenerator; + size_t mnDimensionality; + + std::vector maParticles; + std::vector maBestPosition; + double mfBestFitness; + int mnGeneration; + int mnLastChange; + +public: + Swarm(DataProvider& rDataProvider, size_t nNumOfParticles) + : mrDataProvider(rDataProvider) + , mnNumOfParticles(nNumOfParticles) + , maGenerator(maRandomDevice()) + , mnDimensionality(mrDataProvider.getDimensionality()) + , maBestPosition(mnDimensionality) + , mfBestFitness(std::numeric_limits::lowest()) + , mnGeneration(0) + , mnLastChange(0) + { + } + + DataProvider& dataProvider() { return mrDataProvider; } + std::mt19937& generator() { return maGenerator; } + std::vector& particles() { return maParticles; } + const std::vector& bestPosition() const { return maBestPosition; } + size_t dimensionality() const { return mnDimensionality; } + size_t numParticles() const { return mnNumOfParticles; } + + std::vector const& getResult() const { return maBestPosition; } + int getGeneration() const { return mnGeneration; } + int getLastChange() const { return mnLastChange; } + double getBestFitness() const { return mfBestFitness; } + + void initialize() + { + mnGeneration = 0; + mnLastChange = 0; + mfBestFitness = std::numeric_limits::lowest(); + + maParticles.clear(); + maParticles.reserve(mnNumOfParticles); + for (size_t nParticleIndex = 0; nParticleIndex < mnNumOfParticles; ++nParticleIndex) + { + maParticles.emplace_back(mnDimensionality); + seedParticle(maParticles.back()); + + Particle& rParticle = maParticles.back(); + if (rParticle.mCurrentFitness > mfBestFitness) + { + mfBestFitness = rParticle.mCurrentFitness; + maBestPosition = rParticle.mPosition; + } + } + } + + // Rebuild the swarm from a fresh random spread to escape a local optimum it + // has collapsed into, seeding one particle at the best position found so far + // so it is not lost. The no-change counter is reset to give the search a + // fresh window to improve in. + void restart() + { + mnLastChange = mnGeneration; + + maParticles.clear(); + maParticles.reserve(mnNumOfParticles); + for (size_t nParticleIndex = 0; nParticleIndex < mnNumOfParticles; ++nParticleIndex) + { + maParticles.emplace_back(mnDimensionality); + seedParticle(maParticles.back()); + } + + if (!maBestPosition.empty() && !maParticles.empty()) + { + Particle& rFirst = maParticles.front(); + rFirst.mPosition = maBestPosition; + rFirst.mBestPosition = maBestPosition; + rFirst.mCurrentFitness = mfBestFitness; + rFirst.mBestFitness = mfBestFitness; + } + } + + // Advance the swarm by one generation: apply the algorithm's step to every + // particle, fold the result into the bests, and count the generation. The + // step leaves the particle at its new position and current fitness. Returns + // whether the global best improved. + template bool advance(Algorithm& rAlgorithm) + { + bool bBestChanged = false; + for (size_t nParticleIndex = 0; nParticleIndex < maParticles.size(); ++nParticleIndex) + { + rAlgorithm.step(maParticles[nParticleIndex], nParticleIndex); + if (registerParticle(maParticles[nParticleIndex])) + bBestChanged = true; + } + ++mnGeneration; + return bBestChanged; + } + +private: + // Fill a fresh particle with a random clamped position and its fitness. + void seedParticle(Particle& rParticle) + { + mrDataProvider.initializeVariables(rParticle.mPosition, maGenerator); + for (size_t nDimension = 0; nDimension < mnDimensionality; ++nDimension) + rParticle.mPosition[nDimension] + = mrDataProvider.clampVariable(nDimension, rParticle.mPosition[nDimension]); + + rParticle.mCurrentFitness = mrDataProvider.calculateFitness(rParticle.mPosition); + rParticle.mBestPosition = rParticle.mPosition; + rParticle.mBestFitness = rParticle.mCurrentFitness; + } + + // Fold a particle's current fitness into its personal best and the swarm's + // global best. Returns whether the global best moved by more than the + // accepted precision, recording the generation when it did. + bool registerParticle(Particle& rParticle) + { + bool bBestChanged = false; + + if (rParticle.mCurrentFitness > rParticle.mBestFitness) + { + rParticle.mBestFitness = rParticle.mCurrentFitness; + rParticle.mBestPosition = rParticle.mPosition; + } + + if (rParticle.mCurrentFitness > mfBestFitness) + { + if (std::abs(rParticle.mCurrentFitness - mfBestFitness) > constAcceptedPrecision) + { + bBestChanged = true; + mnLastChange = mnGeneration; + } + maBestPosition = rParticle.mPosition; + mfBestFitness = rParticle.mCurrentFitness; + } + return bBestChanged; + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/SwarmSolver.cxx b/sc/source/solver/SwarmSolver.cxx similarity index 50% rename from sccomp/source/solver/SwarmSolver.cxx rename to sc/source/solver/SwarmSolver.cxx index 2365bfe337e9..b41dec21d6d3 100644 --- a/sccomp/source/solver/SwarmSolver.cxx +++ b/sc/source/solver/SwarmSolver.cxx @@ -20,27 +20,37 @@ #include #include #include +#include #include #include #include -#include -#include -#include +#include +#include #include #include #include #include #include +#include + +#include #include +#include + +#include +#include +#include +#include #include "DifferentialEvolution.hxx" #include "ParticelSwarmOptimization.hxx" +#include "DEPSOSolver.hxx" -#include +#include "strings.hrc" namespace com::sun::star::uno { @@ -86,6 +96,31 @@ struct Bound } }; +// A cell position used as a cache key. +struct CellKey +{ + sal_Int32 nSheet; + sal_Int32 nColumn; + sal_Int32 nRow; + + bool operator==(const CellKey& rOther) const + { + return nSheet == rOther.nSheet && nColumn == rOther.nColumn && nRow == rOther.nRow; + } +}; + +struct CellKeyHash +{ + size_t operator()(const CellKey& rKey) const + { + size_t nSeed = 0; + o3tl::hash_combine(nSeed, rKey.nSheet); + o3tl::hash_combine(nSeed, rKey.nColumn); + o3tl::hash_combine(nSeed, rKey.nRow); + return nSeed; + } +}; + enum { PROP_NONNEGATIVE, @@ -96,17 +131,17 @@ enum } // end anonymous namespace -typedef comphelper::WeakImplHelper - SwarmSolver_Base; - namespace { -class SwarmSolver : public comphelper::OPropertyContainer2, - public comphelper::OPropertyArrayUsageHelper, - public SwarmSolver_Base +class SwarmSolver + : public comphelper::OPropertyContainerImplHelper< + comphelper::WeakImplHelper, + SwarmSolver> { private: uno::Reference mxDocument; + // The ScDocument implementation behind mxDocument + ScDocument* mpDocument = nullptr; table::CellAddress maObjective; uno::Sequence maVariables; uno::Sequence maConstraints; @@ -128,9 +163,21 @@ private: std::vector maBounds; std::vector maNonBoundedConstraints; -private: - static OUString getResourceString(TranslateId aId); + // The document's variable values at the start of a solve, clamped into the + // bounds. Empty until solve captures it. + std::vector maStartingValues; + // How many times variables have been initialized this solve. + size_t mnInitCount = 0; + // Number of population members seeded from maStartingValues. Set from the + // population size when a solve starts. + size_t mnSeedCount = 0; + // Resolved cells, keyed by sheet, column and row. The search reads and + // writes the same handful of cells many thousands of times, so resolving + // each one only once is a large saving. + std::unordered_map, CellKeyHash> maCellCache; + +private: uno::Reference getCell(const table::CellAddress& rPosition); void setValue(const table::CellAddress& rPosition, double fValue); double getValue(const table::CellAddress& rPosition); @@ -141,7 +188,7 @@ public: , mbNonNegative(false) , mbInteger(false) , mnTimeout(60000) - , mnAlgorithm(0) + , mnAlgorithm(2) , mbSuccess(false) , mfResultValue(0.0) { @@ -155,15 +202,6 @@ public: cppu::UnoType::get()); } - DECLARE_XINTERFACE() - DECLARE_XTYPEPROVIDER() - - virtual uno::Reference SAL_CALL getPropertySetInfo() override - { - return createPropertySetInfo(getInfoHelper()); - } - // OPropertySetHelper - virtual cppu::IPropertyArrayHelper& getInfoHelper() override { return *getArrayHelper(); } // OPropertyArrayUsageHelper virtual cppu::IPropertyArrayHelper* createArrayHelper() const override { @@ -181,6 +219,15 @@ public: setDocument(const uno::Reference& rDocument) override { mxDocument = rDocument; + mpDocument = nullptr; + if (ScModelObj* pModel = comphelper::getFromUnoTunnel(mxDocument)) + { + mpDocument = pModel->GetDocument(); + // The solver writes input cells and reads the recalculated objective + // and constraint cells, which needs automatic recalculation on. + if (mpDocument) + mpDocument->SetAutoCalc(true); + } } virtual table::CellAddress SAL_CALL getObjective() override { return maObjective; } @@ -221,7 +268,7 @@ public: // XSolverDescription virtual OUString SAL_CALL getComponentDescription() override { - return SwarmSolver::getResourceString(RID_SWARM_SOLVER_COMPONENT); + return ScResId(RID_SWARM_SOLVER_COMPONENT); } virtual OUString SAL_CALL getStatusDescription() override { return maStatus; } @@ -246,7 +293,7 @@ public: default: break; } - return SwarmSolver::getResourceString(pResId); + return pResId ? ScResId(pResId) : OUString(); } // XServiceInfo @@ -268,6 +315,10 @@ public: private: void applyVariables(std::vector const& rVariables); bool doesViolateConstraints(); + // Total amount by which the current cell values break the non-bounded + // constraints, summed over all of them. Zero when every constraint holds. + double constraintViolation(); + bool isSolutionFeasible(std::vector const& rSolution); public: double calculateFitness(std::vector const& rVariables); @@ -278,35 +329,46 @@ public: }; } -OUString SwarmSolver::getResourceString(TranslateId aId) -{ - if (!aId) - return OUString(); - - return Translate::get(aId, Translate::Create("scc")); -} - uno::Reference SwarmSolver::getCell(const table::CellAddress& rPosition) { + CellKey aKey{ rPosition.Sheet, rPosition.Column, rPosition.Row }; + auto aFound = maCellCache.find(aKey); + if (aFound != maCellCache.end()) + return aFound->second; + uno::Reference xSheets(mxDocument->getSheets(), uno::UNO_QUERY); uno::Reference xSheet(xSheets->getByIndex(rPosition.Sheet), uno::UNO_QUERY); - return xSheet->getCellByPosition(rPosition.Column, rPosition.Row); + uno::Reference xCell = xSheet->getCellByPosition(rPosition.Column, rPosition.Row); + maCellCache.emplace(aKey, xCell); + return xCell; +} + +// Build a document cell address from the API address, throwing if its sheet is +// outside the document. Access through the spreadsheet UNO objects used to throw +// on a missing sheet. Direct ScDocument access does not, so validate here to keep +// an invalid variable cell an error rather than a silently ignored write. +static ScAddress lcl_cellAddress(const ScDocument& rDocument, const table::CellAddress& rPosition) +{ + if (rPosition.Sheet < 0 || rPosition.Sheet >= rDocument.GetTableCount()) + throw uno::RuntimeException(u"solver: cell address is outside the document"_ustr); + return ScAddress(static_cast(rPosition.Column), static_cast(rPosition.Row), + static_cast(rPosition.Sheet)); } void SwarmSolver::setValue(const table::CellAddress& rPosition, double fValue) { - getCell(rPosition)->setValue(fValue); + if (mpDocument) + mpDocument->SetValue(lcl_cellAddress(*mpDocument, rPosition), fValue); } double SwarmSolver::getValue(const table::CellAddress& rPosition) { - return getCell(rPosition)->getValue(); + if (!mpDocument) + return 0.0; + return mpDocument->GetValue(lcl_cellAddress(*mpDocument, rPosition)); } -IMPLEMENT_FORWARD_XINTERFACE2(SwarmSolver, SwarmSolver_Base, comphelper::OPropertyContainer2) -IMPLEMENT_FORWARD_XTYPEPROVIDER2(SwarmSolver, SwarmSolver_Base, comphelper::OPropertyContainer2) - void SwarmSolver::applyVariables(std::vector const& rVariables) { for (sal_Int32 i = 0; i < maVariables.getLength(); ++i) @@ -319,35 +381,122 @@ double SwarmSolver::calculateFitness(std::vector const& rVariables) { applyVariables(rVariables); - if (doesViolateConstraints()) - return std::numeric_limits::lowest(); - double x = getValue(maObjective); + double fFitness = mbMaximize ? x : -x; - if (mbMaximize) - return x; - else - return -x; + // Graded penalty: an infeasible candidate is pushed down in proportion to + // how badly it breaks the constraints, so a point close to feasible scores + // higher than one far off and the search has a slope to follow toward the + // feasible region. The strict feasibility test still decides what is + // reported as a solution, so a point that only nearly satisfies the + // constraints is never returned as the answer. + double fViolation = constraintViolation(); + if (fViolation > 0.0) + fFitness -= 1.0e7 * fViolation; + + return fFitness; +} + +double SwarmSolver::constraintViolation() +{ + double fTotal = 0.0; + for (const sheet::SolverConstraint& rConstraint : maNonBoundedConstraints) + { + double fLeftValue = getValue(rConstraint.Left); + double fRightValue = 0.0; + + table::CellAddress aCellAddress; + + if (rConstraint.Right >>= aCellAddress) + fRightValue = getValue(aCellAddress); + else if (rConstraint.Right >>= fRightValue) + { + // The right hand side is a plain number. + } + else + { + // The right hand side is neither a cell nor a number, so this + // constraint cannot be evaluated. Skip it, matching the strict + // feasibility check. + continue; + } + + switch (rConstraint.Operator) + { + case sheet::SolverConstraintOperator_LESS_EQUAL: + if (fLeftValue > fRightValue) + fTotal += fLeftValue - fRightValue; + break; + case sheet::SolverConstraintOperator_GREATER_EQUAL: + if (fLeftValue < fRightValue) + fTotal += fRightValue - fLeftValue; + break; + case sheet::SolverConstraintOperator_EQUAL: + if (!rtl::math::approxEqual(fLeftValue, fRightValue)) + fTotal += std::abs(fLeftValue - fRightValue); + break; + default: + break; + } + } + return fTotal; } void SwarmSolver::initializeVariables(std::vector& rVariables, std::mt19937& rGenerator) { + size_t nVariables(maVariables.getLength()); + rVariables.resize(nVariables); + + size_t nIndex = mnInitCount++; + + // The first seeded individual is the document's starting values unchanged, a + // feasible-scale anchor. The next seeded ones keep that scale but spread out + // with jitter scaled to each value's magnitude, so the search has diversity + // near the guess. Everything past mnSeedCount is drawn at random across the + // bounds for global exploration. + if (!maStartingValues.empty() && nIndex < mnSeedCount) + { + if (nIndex == 0) + { + for (size_t i = 0; i < nVariables; ++i) + rVariables[i] = clampVariable(i, maStartingValues[i]); + return; + } + std::normal_distribution aJitter(0.0, 0.5); + for (size_t i = 0; i < nVariables; ++i) + { + double fBase = maStartingValues[i]; + double fScale = std::max(1.0, std::abs(fBase)); + rVariables[i] = clampVariable(i, fBase + fScale * aJitter(rGenerator)); + } + return; + } + int nTry = 1; bool bConstraintsOK = false; while (!bConstraintsOK && nTry < 10) { - size_t noVariables(maVariables.getLength()); - - rVariables.resize(noVariables); - - for (size_t i = 0; i < noVariables; ++i) + for (size_t i = 0; i < nVariables; ++i) { Bound const& rBound = maBounds[i]; - if (mbInteger) + if (rBound.lower >= rBound.upper) { - sal_Int64 intLower(rBound.lower); - sal_Int64 intUpper(rBound.upper); + // An empty or reversed range has nothing to draw from. The + // random distributions are undefined when the lower bound is + // not below the upper one, so take the lower bound directly. + rVariables[i] = rBound.lower; + } + else if (mbInteger) + { + // The default bounds sit around the float range, which a 64 bit + // integer cannot hold. Turning such a double into sal_Int64 is + // undefined, so clamp to a magnitude that converts safely first. + // 2^62 is a power of two well inside the range and exact in both + // types. + constexpr double fIntegerLimit = double(sal_Int64(1) << 62); + sal_Int64 intLower(std::clamp(rBound.lower, -fIntegerLimit, fIntegerLimit)); + sal_Int64 intUpper(std::clamp(rBound.upper, -fIntegerLimit, fIntegerLimit)); std::uniform_int_distribution random(intLower, intUpper); rVariables[i] = double(random(rGenerator)); } @@ -368,6 +517,12 @@ void SwarmSolver::initializeVariables(std::vector& rVariables, std::mt19 double SwarmSolver::clampVariable(size_t nVarIndex, double fValue) { Bound const& rBound = maBounds[nVarIndex]; + + // An empty or reversed range has no room to clamp into. std::clamp with a + // lower bound above the upper bound is undefined, so return the lower bound. + if (rBound.lower >= rBound.upper) + return mbInteger ? std::trunc(rBound.lower) : rBound.lower; + double fResult = std::clamp(fValue, rBound.lower, rBound.upper); if (mbInteger) @@ -379,14 +534,24 @@ double SwarmSolver::clampVariable(size_t nVarIndex, double fValue) double SwarmSolver::boundVariable(size_t nVarIndex, double fValue) { Bound const& rBound = maBounds[nVarIndex]; - // double fResult = std::max(std::min(fValue, rBound.upper), rBound.lower); + double fResult = fValue; - while (fResult < rBound.lower || fResult > rBound.upper) + double const fRange = rBound.upper - rBound.lower; + if (fRange <= 0.0) { - if (fResult < rBound.lower) - fResult = rBound.upper - (rBound.lower - fResult); - if (fResult > rBound.upper) - fResult = (fResult - rBound.upper) + rBound.lower; + // An empty range, where the lower and upper bound are equal, or a + // reversed range from contradictory constraints, holds a single + // value. Return the lower bound. + fResult = rBound.lower; + } + else if (fResult < rBound.lower || fResult > rBound.upper) + { + // Wrap an out of range value back into the range, keeping its offset + // from the lower bound. + double fOffset = std::fmod(fResult - rBound.lower, fRange); + if (fOffset < 0.0) + fOffset += fRange; + fResult = rBound.lower + fOffset; } if (mbInteger) @@ -416,7 +581,10 @@ bool SwarmSolver::doesViolateConstraints() } else { - return false; + // The right hand side is neither a cell nor a number, so this + // constraint cannot be evaluated. Skip it and carry on checking the + // rest of the constraints. + continue; } sheet::SolverConstraintOperator eOp = rConstraint.Operator; @@ -447,6 +615,25 @@ bool SwarmSolver::doesViolateConstraints() return false; } +bool SwarmSolver::isSolutionFeasible(std::vector const& rSolution) +{ + // The search must have produced a value for every variable. + if (sal_Int32(rSolution.size()) != maVariables.getLength()) + return false; + + // A value outside the variable's bound is not a valid solution. + for (size_t i = 0; i < rSolution.size(); ++i) + { + Bound const& rBound = maBounds[i]; + if (rSolution[i] < rBound.lower || rSolution[i] > rBound.upper) + return false; + } + + // Put the candidate into the document and check the remaining constraints. + applyVariables(rSolution); + return !doesViolateConstraints(); +} + namespace { template class SwarmRunner @@ -457,6 +644,11 @@ private: static constexpr size_t mnPopulationSize = 40; static constexpr int constNumberOfGenerationsWithoutChange = 50; + // How many fresh restarts to try after the search stalls before giving up. + // An easy model converges and then stops after these few extra tries, while + // a hard one keeps finding better points across restarts and runs on until + // the time budget is gone. + static constexpr int constMaxStallRestarts = 3; std::chrono::high_resolution_clock::time_point maStart; std::chrono::high_resolution_clock::time_point maEnd; @@ -480,15 +672,33 @@ public: maEnd = maStart = high_resolution_clock::now(); - int nLastChange = 0; + int nStallRestarts = 0; + double fBestSoFar = mrAlgorithm.getBestFitness(); - while ((mrAlgorithm.getGeneration() - nLastChange) < constNumberOfGenerationsWithoutChange - && duration_cast(maEnd - maStart).count() < mfTimeout) + while (duration_cast(maEnd - maStart).count() < mfTimeout) { - bool bChange = mrAlgorithm.next(); + mrAlgorithm.next(); - if (bChange) - nLastChange = mrAlgorithm.getGeneration(); + // Any real improvement in the best fitness earns back the full + // restart budget, so a search that keeps making progress is never + // cut off early. + double fBest = mrAlgorithm.getBestFitness(); + if (fBest > fBestSoFar) + { + fBestSoFar = fBest; + nStallRestarts = 0; + } + + if ((mrAlgorithm.getGeneration() - mrAlgorithm.getLastChange()) + >= constNumberOfGenerationsWithoutChange) + { + // The search has settled. Stop once a few fresh restarts have + // also failed to improve on the best point found. + if (nStallRestarts >= constMaxStallRestarts) + break; + nStallRestarts++; + mrAlgorithm.restart(); + } maEnd = high_resolution_clock::now(); } @@ -506,10 +716,19 @@ void SAL_CALL SwarmSolver::solve() if (!maVariables.getLength()) return; - maBounds.resize(maVariables.getLength()); + // Start each solve from fresh state. assign refills every bound with a + // default, and clearing drops the constraints from the previous run, which + // are only ever appended. + maBounds.assign(maVariables.getLength(), Bound()); + maNonBoundedConstraints.clear(); + maCellCache.clear(); xModel->lockControllers(); + // Unlock again on any exit from here on, including an exception thrown by + // one of the cell accesses below, so the document is always left usable. + comphelper::ScopeGuard aUnlockGuard([&xModel] { xModel->unlockControllers(); }); + if (mbNonNegative) { for (Bound& rBound : maBounds) @@ -555,29 +774,66 @@ void SAL_CALL SwarmSolver::solve() maNonBoundedConstraints.push_back(rConstraint); } + // Capture the document's current variable values, clamped into the bounds, + // as a starting guess to seed part of the initial population from. + maStartingValues.assign(maVariables.getLength(), 0.0); + for (sal_Int32 i = 0; i < maVariables.getLength(); ++i) + maStartingValues[i] = clampVariable(i, getValue(maVariables[i])); + mnInitCount = 0; + + // Scale the population with the number of variables. A fixed small + // population cannot keep enough diversity on a high-dimensional model, while + // the original sizes are kept for small models so their behaviour does not + // change. The cap keeps each generation's cost bounded. + const size_t nDimensions = maVariables.getLength(); + std::vector aSolution; if (mnAlgorithm == 0) { - DifferentialEvolutionAlgorithm aDE(*this, 50); - SwarmRunner> aEvolution(aDE); + size_t nPopulation = std::clamp(10 * nDimensions, 50, 300); + mnSeedCount = nPopulation / 2; + DifferentialEvolutionSolver aDE(*this, nPopulation); + SwarmRunner> aEvolution(aDE); aEvolution.setTimeout(mnTimeout); aSolution = aEvolution.solve(); } + else if (mnAlgorithm == 2) + { + size_t nPopulation = std::clamp(10 * nDimensions, 100, 300); + mnSeedCount = nPopulation / 2; + DEPSOSolver aDepso(*this, nPopulation); + SwarmRunner> aRunner(aDepso); + aRunner.setTimeout(mnTimeout); + aSolution = aRunner.solve(); + } else { - ParticleSwarmOptimizationAlgorithm aPSO(*this, 100); - SwarmRunner> aSwarmSolver(aPSO); + size_t nPopulation = std::clamp(10 * nDimensions, 100, 300); + mnSeedCount = nPopulation / 2; + ParticleSwarmOptimizationSolver aPSO(*this, nPopulation); + SwarmRunner> aSwarmSolver(aPSO); aSwarmSolver.setTimeout(mnTimeout); aSolution = aSwarmSolver.solve(); } - xModel->unlockControllers(); + // Only report success when the returned values actually satisfy the + // model. The search can run out of generations or time without ever + // reaching a feasible point. + bool bFeasible = isSolutionFeasible(aSolution); - mbSuccess = true; + mbSuccess = bFeasible; - maSolution.realloc(aSolution.size()); - std::copy(aSolution.begin(), aSolution.end(), maSolution.getArray()); + if (bFeasible) + { + maSolution.realloc(aSolution.size()); + std::copy(aSolution.begin(), aSolution.end(), maSolution.getArray()); + } + else + { + maSolution.realloc(0); + maStatus = ScResId(RID_ERROR_INFEASIBLE); + } } extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* diff --git a/sccomp/source/solver/solver.component b/sc/source/solver/solver.component similarity index 87% rename from sccomp/source/solver/solver.component rename to sc/source/solver/solver.component index 496be6628486..a9afee83a8ba 100644 --- a/sccomp/source/solver/solver.component +++ b/sc/source/solver/solver.component @@ -13,8 +13,8 @@ - + diff --git a/sccomp/source/solver/solver.component.coinmp b/sc/source/solver/solver.component.coinmp similarity index 89% rename from sccomp/source/solver/solver.component.coinmp rename to sc/source/solver/solver.component.coinmp index 1ced6f61be45..aa618cb24294 100644 --- a/sccomp/source/solver/solver.component.coinmp +++ b/sc/source/solver/solver.component.coinmp @@ -5,3 +5,4 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. com.sun.star.comp.Calc.CoinMPSolver +com.sun.star.comp.Calc.SLPSolver diff --git a/sccomp/inc/strings.hrc b/sc/source/solver/strings.hrc similarity index 95% rename from sccomp/inc/strings.hrc rename to sc/source/solver/strings.hrc index c7826cc228ac..4a0693531005 100644 --- a/sccomp/inc/strings.hrc +++ b/sc/source/solver/strings.hrc @@ -24,6 +24,7 @@ #define RID_SOLVER_COMPONENT NC_("RID_SOLVER_COMPONENT", "%PRODUCTNAME Linear Solver") #define RID_COINMP_SOLVER_COMPONENT NC_("RID_COINMP_SOLVER_COMPONENT", "%PRODUCTNAME CoinMP Linear Solver") #define RID_SWARM_SOLVER_COMPONENT NC_("RID_SWARM_SOLVER_COMPONENT", "%PRODUCTNAME Swarm Non-Linear Solver (experimental)") +#define RID_SLP_SOLVER_COMPONENT NC_("RID_SLP_SOLVER_COMPONENT", "Sequential Quadratic Solver (experimental)") #define RID_PROPERTY_NONNEGATIVE NC_("RID_PROPERTY_NONNEGATIVE", "Assume variables as non-negative") #define RID_PROPERTY_INTEGER NC_("RID_PROPERTY_INTEGER", "Assume variables as integer") #define RID_PROPERTY_TIMEOUT NC_("RID_PROPERTY_TIMEOUT", "Solving time limit (seconds)") diff --git a/sc/source/ui/Accessibility/AccessibleCell.cxx b/sc/source/ui/Accessibility/AccessibleCell.cxx index eb4d6caccaa0..e4163930aa55 100644 --- a/sc/source/ui/Accessibility/AccessibleCell.cxx +++ b/sc/source/ui/Accessibility/AccessibleCell.cxx @@ -50,29 +50,23 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; -rtl::Reference ScAccessibleCell::create( - const uno::Reference& rxParent, - ScTabViewShell* pViewShell, - const ScAddress& rCellAddress, - sal_Int64 nIndex, - ScSplitPos eSplitPos, - ScAccessibleDocument* pAccDoc) +rtl::Reference +ScAccessibleCell::create(const rtl::Reference& rpParent, + ScTabViewShell* pViewShell, const ScAddress& rCellAddress, + sal_Int64 nIndex, ScSplitPos eSplitPos, ScAccessibleDocument* pAccDoc) { - rtl::Reference x(new ScAccessibleCell( - rxParent, pViewShell, rCellAddress, nIndex, eSplitPos, pAccDoc)); + rtl::Reference x( + new ScAccessibleCell(rpParent, pViewShell, rCellAddress, nIndex, eSplitPos, pAccDoc)); x->Init(); return x; } -ScAccessibleCell::ScAccessibleCell( - const uno::Reference& rxParent, - ScTabViewShell* pViewShell, - const ScAddress& rCellAddress, - sal_Int64 nIndex, - ScSplitPos eSplitPos, - ScAccessibleDocument* pAccDoc) +ScAccessibleCell::ScAccessibleCell(const rtl::Reference& rpParent, + ScTabViewShell* pViewShell, const ScAddress& rCellAddress, + sal_Int64 nIndex, ScSplitPos eSplitPos, + ScAccessibleDocument* pAccDoc) : - ScAccessibleCellBase(rxParent, GetDocument(pViewShell), rCellAddress, nIndex), + ScAccessibleCellBase(rpParent, GetDocument(pViewShell), rCellAddress, nIndex), ::accessibility::AccessibleStaticTextBase(CreateEditSource(pViewShell, rCellAddress, eSplitPos)), mpViewShell(pViewShell), mpAccDoc(pAccDoc), @@ -330,7 +324,8 @@ bool ScAccessibleCell::IsSelected() { if (IsFormulaMode()) { - const ScAccessibleSpreadsheet *pSheet =static_cast(mxParent.get()); + const ScAccessibleSpreadsheet* pSheet + = static_cast(mpParent.get()); if (pSheet) { return pSheet->IsScAddrFormulaSel(maCellAddress); @@ -515,7 +510,7 @@ uno::Sequence< beans::PropertyValue > SAL_CALL ScAccessibleCell::getCharacterAtt bool ScAccessibleCell::IsFormulaMode() { - ScAccessibleSpreadsheet* pSheet = static_cast(mxParent.get()); + ScAccessibleSpreadsheet* pSheet = static_cast(mpParent.get()); if (pSheet) { return pSheet->IsFormulaMode(); diff --git a/sc/source/ui/Accessibility/AccessibleCellBase.cxx b/sc/source/ui/Accessibility/AccessibleCellBase.cxx index 588a7e0459d1..42aec4cfdaec 100644 --- a/sc/source/ui/Accessibility/AccessibleCellBase.cxx +++ b/sc/source/ui/Accessibility/AccessibleCellBase.cxx @@ -44,10 +44,10 @@ using namespace ::com::sun::star::accessibility; #define DEFAULT_LINE_WIDTH 2 -ScAccessibleCellBase::ScAccessibleCellBase(const uno::Reference& rxParent, +ScAccessibleCellBase::ScAccessibleCellBase(const rtl::Reference& rpParent, ScDocument* pDoc, const ScAddress& rCellAddress, sal_Int64 nIndex) - : ImplInheritanceHelper(rxParent, AccessibleRole::TABLE_CELL) + : ImplInheritanceHelper(rpParent, AccessibleRole::TABLE_CELL) , maCellAddress(rCellAddress) , mpDoc(pDoc) , mnIndex(nIndex) diff --git a/sc/source/ui/Accessibility/AccessibleContextBase.cxx b/sc/source/ui/Accessibility/AccessibleContextBase.cxx index 1459a5849ce4..8159640fa514 100644 --- a/sc/source/ui/Accessibility/AccessibleContextBase.cxx +++ b/sc/source/ui/Accessibility/AccessibleContextBase.cxx @@ -37,11 +37,9 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; ScAccessibleContextBase::ScAccessibleContextBase( - uno::Reference xParent, - const sal_Int16 aRole) - : - mxParent(std::move(xParent)), - maRole(aRole) + const rtl::Reference& rpParent, const sal_Int16 aRole) + : mpParent(rpParent) + , maRole(aRole) { } @@ -74,7 +72,7 @@ void SAL_CALL ScAccessibleContextBase::disposing() OAccessible::disposing(); - mxParent.clear(); + mpParent.clear(); } @@ -110,16 +108,11 @@ bool ScAccessibleContextBase::isShowing( ) SolarMutexGuard aGuard; ensureAlive(); bool bShowing(false); - if (mxParent.is()) + if (mpParent.is()) { - uno::Reference xParentComponent (mxParent->getAccessibleContext(), uno::UNO_QUERY); - if (xParentComponent.is()) - { - tools::Rectangle aParentBounds( - vcl::unohelper::ConvertToVCLRect(xParentComponent->getBounds())); - tools::Rectangle aBounds(vcl::unohelper::ConvertToVCLRect(getBounds())); - bShowing = aBounds.Overlaps(aParentBounds); - } + tools::Rectangle aParentBounds(vcl::unohelper::ConvertToVCLRect(mpParent->getBounds())); + tools::Rectangle aBounds(vcl::unohelper::ConvertToVCLRect(getBounds())); + bShowing = aBounds.Overlaps(aParentBounds); } return bShowing; } @@ -149,7 +142,7 @@ sal_Int32 SAL_CALL ScAccessibleContextBase::getBackground( ) uno::Reference SAL_CALL ScAccessibleContextBase::getAccessibleParent() { - return mxParent; + return mpParent; } sal_Int16 SAL_CALL @@ -211,18 +204,12 @@ sal_Int64 SAL_CALL ScAccessibleContextBase::getAccessibleStateSet() return 0; } -lang::Locale SAL_CALL - ScAccessibleContextBase::getLocale() +lang::Locale SAL_CALL ScAccessibleContextBase::getLocale() { SolarMutexGuard aGuard; ensureAlive(); - if (mxParent.is()) - { - uno::Reference xParentContext ( - mxParent->getAccessibleContext()); - if (xParentContext.is()) - return xParentContext->getLocale (); - } + if (mpParent.is()) + return mpParent->getLocale(); // No locale and no parent. Therefore throw exception to indicate this // cluelessness. diff --git a/sc/source/ui/Accessibility/AccessibleCsvControl.cxx b/sc/source/ui/Accessibility/AccessibleCsvControl.cxx index ff5a06d103eb..d0b08625704c 100644 --- a/sc/source/ui/Accessibility/AccessibleCsvControl.cxx +++ b/sc/source/ui/Accessibility/AccessibleCsvControl.cxx @@ -727,13 +727,13 @@ css::uno::Reference SAL_CALL ScAccessibleCsvRul // Grid ======================================================================= -/** Converts a grid columnm index to an API column index. */ +/** Converts a grid column index to an API column index. */ static sal_Int32 lcl_GetApiColumn( sal_uInt32 nGridColumn ) { return (nGridColumn != CSV_COLUMN_HEADER) ? static_cast< sal_Int32 >( nGridColumn + 1 ) : 0; } -/** Converts an API columnm index to a ScCsvGrid column index. */ +/** Converts an API column index to a ScCsvGrid column index. */ static sal_uInt32 lcl_GetGridColumn( sal_Int32 nApiColumn ) { return (nApiColumn > 0) ? static_cast< sal_uInt32 >( nApiColumn - 1 ) : CSV_COLUMN_HEADER; @@ -1379,7 +1379,7 @@ css::awt::Rectangle ScAccessibleCsvCell::implGetBounds() aClipRect.SetRight( rGrid.GetLastX() ); } if( mnLine != CSV_LINE_HEADER ) - aClipRect.SetTop( rGrid.GetHdrHeight() ); + aClipRect.SetTop( rGrid.GetHdrHeight() ); tools::Rectangle aRect( implGetRealPos(), implGetRealSize() ); aRect.Intersection( aClipRect ); diff --git a/sc/source/ui/Accessibility/AccessibleDocument.cxx b/sc/source/ui/Accessibility/AccessibleDocument.cxx index c7b98ae1a354..68fb30bad133 100644 --- a/sc/source/ui/Accessibility/AccessibleDocument.cxx +++ b/sc/source/ui/Accessibility/AccessibleDocument.cxx @@ -227,7 +227,7 @@ public: sal_Int32 GetCount() const; rtl::Reference<::accessibility::AccessibleShape> Get(const ScAccessibleShapeData* pData) const; rtl::Reference<::accessibility::AccessibleShape> Get(sal_Int32 nIndex) const; - uno::Reference< XAccessible > GetAt(const awt::Point& rPoint) const; + rtl::Reference<::accessibility::AccessibleShape> GetAt(const awt::Point& rPoint) const; // gets the index of the shape starting on 0 (without the index of the table) // returns the selected shape @@ -417,7 +417,7 @@ bool ScChildrenShapes::ReplaceChild (::accessibility::AccessibleShape* pCurrentC { // create the new child rtl::Reference< ::accessibility::AccessibleShape > pReplacement(::accessibility::ShapeTypeHandler::Instance().CreateAccessibleObject ( - ::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->getAccessibleParent(), this ), + ::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->implGetAccessibleParent(), this ), _rShapeTreeInfo )); @@ -541,9 +541,10 @@ rtl::Reference<::accessibility::AccessibleShape> ScChildrenShapes::Get(sal_Int32 return Get(maZOrderedShapes[nIndex]); } -uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) const +rtl::Reference<::accessibility::AccessibleShape> +ScChildrenShapes::GetAt(const awt::Point& rPoint) const { - uno::Reference xAccessible; + rtl::Reference<::accessibility::AccessibleShape> pAccessible; if(mpViewShell) { if (mbShapesNeedSorting) @@ -569,7 +570,7 @@ uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) -= vcl::unohelper::ConvertToVCLRect(pShape->pAccShape->getBounds()).TopLeft(); if (pShape->pAccShape->containsPoint(vcl::unohelper::ConvertToAWTPoint(aPoint))) { - xAccessible = pShape->pAccShape.get(); + pAccessible = pShape->pAccShape.get(); bFound = true; } } @@ -584,7 +585,7 @@ uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) --i; } } - return xAccessible; + return pAccessible; } bool ScChildrenShapes::IsSelected(sal_Int32 nIndex, @@ -1283,14 +1284,12 @@ void ScChildrenShapes::VisAreaChanged() const pAccShapeData->pAccShape->ViewForwarderChanged(); } -ScAccessibleDocument::ScAccessibleDocument( - const uno::Reference& rxParent, - ScTabViewShell* pViewShell, - ScSplitPos eSplitPos) - : ImplInheritanceHelper(rxParent), - mpViewShell(pViewShell), - meSplitPos(eSplitPos), - mbCompleteSheetSelected(false) +ScAccessibleDocument::ScAccessibleDocument(const rtl::Reference& rpParent, + ScTabViewShell* pViewShell, ScSplitPos eSplitPos) + : ImplInheritanceHelper(rpParent) + , mpViewShell(pViewShell) + , meSplitPos(eSplitPos) + , mbCompleteSheetSelected(false) { maVisArea = GetVisibleArea_Impl(); } @@ -1317,10 +1316,11 @@ void ScAccessibleDocument::PreInit() ScViewData& rViewData = mpViewShell->GetViewData(); if (rViewData.HasEditView(meSplitPos)) { - uno::Reference xAcc = new ScAccessibleEditObject(this, rViewData.GetEditView(meSplitPos), - mpViewShell->GetWindowByPos(meSplitPos), GetCurrentCellName(), GetCurrentCellDescription(), + rtl::Reference pAcc = new ScAccessibleEditObject( + this, rViewData.GetEditView(meSplitPos), mpViewShell->GetWindowByPos(meSplitPos), + GetCurrentCellName(), GetCurrentCellDescription(), ScAccessibleEditObject::CellInEditMode); - AddChild(xAcc, false); + AddChild(pAcc, false); } } @@ -1399,7 +1399,7 @@ void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) auto pFocusLostHint = static_cast(&rHint); if (pFocusLostHint->GetOldGridWin() == meSplitPos) { - if (mxTempAcc.is() && mpTempAccEdit) + if (mpTempAcc.is() && mpTempAccEdit) mpTempAccEdit->LostFocus(); else if (mpAccessibleSpreadsheet.is()) mpAccessibleSpreadsheet->LostFocus(); @@ -1427,7 +1427,7 @@ void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) } else { - if (mxTempAcc.is() && mpTempAccEdit) + if (mpTempAcc.is() && mpTempAccEdit) mpTempAccEdit->GotFocus(); else if (mpAccessibleSpreadsheet.is()) mpAccessibleSpreadsheet->GotFocus(); @@ -1471,7 +1471,7 @@ void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) mpViewShell->GetWindowByPos(meSplitPos), GetCurrentCellName(), ScResId(STR_ACC_EDITLINE_DESCR), ScAccessibleEditObject::CellInEditMode); - AddChild(uno::Reference(mpTempAccEdit), true); + AddChild(mpTempAccEdit, true); if (mpAccessibleSpreadsheet.is()) mpAccessibleSpreadsheet->LostFocus(); @@ -1484,13 +1484,13 @@ void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) } else if (rHint.GetId() == SfxHintId::ScAccLeaveEditMode) { - if (mxTempAcc.is()) + if (mpTempAcc.is()) { if (mpTempAccEdit) { mpTempAccEdit->LostFocus(); } - RemoveChild(mxTempAcc, true); + RemoveChild(mpTempAcc, true); if (mpTempAccEdit) { // tdf#125982 a11y use-after-free of editengine by @@ -1560,31 +1560,26 @@ void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& / uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint( const awt::Point& rPoint ) { - uno::Reference xAccessible; + rtl::Reference pAccessible; if (containsPoint(rPoint)) { SolarMutexGuard aGuard; ensureAlive(); if (mpChildrenShapes) - xAccessible = mpChildrenShapes->GetAt(rPoint); - if(!xAccessible.is()) + pAccessible = mpChildrenShapes->GetAt(rPoint); + if (!pAccessible.is()) { - if (mxTempAcc.is()) + if (mpTempAcc.is()) { - uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext()); - uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY); - if (xComp.is()) - { - tools::Rectangle aBound(vcl::unohelper::ConvertToVCLRect(xComp->getBounds())); - if (aBound.Contains(vcl::unohelper::ConvertToVCLPoint(rPoint))) - xAccessible = mxTempAcc; - } + tools::Rectangle aBound(vcl::unohelper::ConvertToVCLRect(mpTempAcc->getBounds())); + if (aBound.Contains(vcl::unohelper::ConvertToVCLPoint(rPoint))) + pAccessible = mpTempAcc; } - if (!xAccessible.is()) - xAccessible = GetAccessibleSpreadsheet(); + if (!pAccessible.is()) + pAccessible = GetAccessibleSpreadsheet(); } } - return xAccessible; + return pAccessible; } void SAL_CALL ScAccessibleDocument::grabFocus( ) @@ -1620,7 +1615,7 @@ sal_Int64 SAL_CALL if (mpChildrenShapes) nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table - if (mxTempAcc.is()) + if (mpTempAcc.is()) ++nCount; return nCount; @@ -1632,28 +1627,29 @@ uno::Reference SAL_CALL { SolarMutexGuard aGuard; ensureAlive(); - uno::Reference xAccessible; + rtl::Reference pAccessible; if (nIndex >= 0) { sal_Int64 nCount(1); if (mpChildrenShapes) { - xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range + // returns NULL if it is the table or out of range + pAccessible = mpChildrenShapes->Get(nIndex); nCount = mpChildrenShapes->GetCount(); //there is always a table } - if (!xAccessible.is()) + if (!pAccessible.is()) { if (nIndex < nCount) - xAccessible = GetAccessibleSpreadsheet(); - else if (nIndex == nCount && mxTempAcc.is()) - xAccessible = mxTempAcc; + pAccessible = GetAccessibleSpreadsheet(); + else if (nIndex == nCount && mpTempAcc.is()) + pAccessible = mpTempAcc; } } - if (!xAccessible.is()) + if (!pAccessible.is()) throw lang::IndexOutOfBoundsException(); - return xAccessible; + return pAccessible; } /// Return the set of current states. @@ -1728,13 +1724,14 @@ void SAL_CALL return; sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table - if (mxTempAcc.is()) + if (mpTempAcc.is()) ++nCount; if (nChildIndex < 0 || nChildIndex >= nCount) throw lang::IndexOutOfBoundsException(); - uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex); - if (xAccessible.is()) + rtl::Reference<::accessibility::AccessibleShape> pAccessible + = mpChildrenShapes->Get(nChildIndex); + if (pAccessible.is()) { bool bWasTableSelected(IsTableSelected()); mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high @@ -1757,20 +1754,21 @@ sal_Bool SAL_CALL if (mpChildrenShapes) { sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table - if (mxTempAcc.is()) + if (mpTempAcc.is()) ++nCount; if (nChildIndex < 0 || nChildIndex >= nCount) throw lang::IndexOutOfBoundsException(); - uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex); - if (xAccessible.is()) + rtl::Reference<::accessibility::AccessibleShape> pAccessible + = mpChildrenShapes->Get(nChildIndex); + if (pAccessible.is()) { uno::Reference xShape; bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is too high } else { - if (mxTempAcc.is() && nChildIndex == nCount) + if (mpTempAcc.is() && nChildIndex == nCount) bResult = true; else bResult = IsTableSelected(); @@ -1818,7 +1816,7 @@ sal_Int64 SAL_CALL if (IsTableSelected()) ++nCount; - if (mxTempAcc.is()) + if (mpTempAcc.is()) ++nCount; return nCount; @@ -1829,7 +1827,7 @@ uno::Reference SAL_CALL { SolarMutexGuard aGuard; ensureAlive(); - uno::Reference xAccessible; + rtl::Reference pAccessible; if (mpChildrenShapes) { sal_Int64 nCount(getSelectedAccessibleChildCount()); //all shapes and the table @@ -1839,16 +1837,18 @@ uno::Reference SAL_CALL bool bTabMarked(IsTableSelected()); if (mpChildrenShapes) - xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is too high - if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1) - xAccessible = mxTempAcc; + // throws no lang::IndexOutOfBoundsException if Index is too high + pAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); + if (mpTempAcc.is() && nSelectedChildIndex == nCount - 1) + pAccessible = mpTempAcc; else if (bTabMarked) - xAccessible = GetAccessibleSpreadsheet(); + pAccessible = GetAccessibleSpreadsheet(); } - OSL_ENSURE(xAccessible.is(), "here should always be an accessible object or an exception thrown"); + OSL_ENSURE(pAccessible.is(), + "here should always be an accessible object or an exception thrown"); - return xAccessible; + return pAccessible; } void SAL_CALL @@ -1861,15 +1861,16 @@ void SAL_CALL return; sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table - if (mxTempAcc.is()) + if (mpTempAcc.is()) ++nCount; if (nChildIndex < 0 || nChildIndex >= nCount) throw lang::IndexOutOfBoundsException(); bool bTabMarked(IsTableSelected()); - uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex); - if (xAccessible.is()) + rtl::Reference<::accessibility::AccessibleShape> pAccessible + = mpChildrenShapes->Get(nChildIndex); + if (pAccessible.is()) { mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high if (bTabMarked) @@ -1989,8 +1990,7 @@ SCTAB ScAccessibleDocument::getVisibleTable() const return nVisibleTable; } -uno::Reference < XAccessible > - ScAccessibleDocument::GetAccessibleSpreadsheet() +rtl::Reference ScAccessibleDocument::GetAccessibleSpreadsheet() { if (!mpAccessibleSpreadsheet.is() && mpViewShell) { @@ -2031,15 +2031,17 @@ bool ScAccessibleDocument::IsDefunc(sal_Int64 nParentStates) (nParentStates & AccessibleStateType::DEFUNC); } -void ScAccessibleDocument::AddChild(const uno::Reference& xAcc, bool bFireEvent) +void ScAccessibleDocument::AddChild(const rtl::Reference& pAcc, + bool bFireEvent) { - OSL_ENSURE(!mxTempAcc.is(), "this object should be removed before"); - if (xAcc.is()) + OSL_ENSURE(!mpTempAcc.is(), "this object should be removed before"); + if (pAcc.is()) { - mxTempAcc = xAcc; + mpTempAcc = pAcc; if( bFireEvent ) { - CommitChange(AccessibleEventId::CHILD, uno::Any(), uno::Any(mxTempAcc), + CommitChange(AccessibleEventId::CHILD, uno::Any(), + uno::Any(uno::Reference(mpTempAcc)), getAccessibleChildCount() - 1); } } @@ -2047,14 +2049,15 @@ void ScAccessibleDocument::AddChild(const uno::Reference& xAcc, boo void ScAccessibleDocument::RemoveChild(const uno::Reference& xAcc, bool bFireEvent) { - OSL_ENSURE(mxTempAcc.is(), "this object should be added before"); + OSL_ENSURE(mpTempAcc.is(), "this object should be added before"); if (!xAcc.is()) return; - OSL_ENSURE(xAcc.get() == mxTempAcc.get(), "only the same object should be removed"); + OSL_ENSURE(xAcc.get() == mpTempAcc.get(), "only the same object should be removed"); if( bFireEvent ) - CommitChange(AccessibleEventId::CHILD, uno::Any(mxTempAcc), uno::Any()); - mxTempAcc = nullptr; + CommitChange(AccessibleEventId::CHILD, uno::Any(uno::Reference(mpTempAcc)), + uno::Any()); + mpTempAcc = nullptr; } OUString ScAccessibleDocument::GetCurrentCellName() const diff --git a/sc/source/ui/Accessibility/AccessibleDocumentBase.cxx b/sc/source/ui/Accessibility/AccessibleDocumentBase.cxx index 5171805158b6..6bdb8fe10c26 100644 --- a/sc/source/ui/Accessibility/AccessibleDocumentBase.cxx +++ b/sc/source/ui/Accessibility/AccessibleDocumentBase.cxx @@ -24,8 +24,9 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; -ScAccessibleDocumentBase::ScAccessibleDocumentBase(const uno::Reference& rxParent) - : ScAccessibleContextBase(rxParent, AccessibleRole::DOCUMENT_SPREADSHEET) +ScAccessibleDocumentBase::ScAccessibleDocumentBase( + const rtl::Reference& rpParent) + : ScAccessibleContextBase(rpParent, AccessibleRole::DOCUMENT_SPREADSHEET) { } diff --git a/sc/source/ui/Accessibility/AccessibleDocumentPagePreview.cxx b/sc/source/ui/Accessibility/AccessibleDocumentPagePreview.cxx index c6962aba57b6..07418b106a4b 100644 --- a/sc/source/ui/Accessibility/AccessibleDocumentPagePreview.cxx +++ b/sc/source/ui/Accessibility/AccessibleDocumentPagePreview.cxx @@ -653,13 +653,15 @@ public: void Init(); sal_Int32 GetBackShapeCount() const; - uno::Reference GetBackShape(sal_Int32 nIndex) const; + rtl::Reference<::accessibility::AccessibleShape> GetBackShape(sal_Int32 nIndex) const; sal_Int32 GetForeShapeCount() const; - uno::Reference GetForeShape(sal_Int32 nIndex) const; + rtl::Reference<::accessibility::AccessibleShape> GetForeShape(sal_Int32 nIndex) const; sal_Int32 GetControlCount() const; - uno::Reference GetControl(sal_Int32 nIndex) const; - uno::Reference GetForegroundShapeAt(const awt::Point& rPoint) const; // inclusive controls - uno::Reference GetBackgroundShapeAt(const awt::Point& rPoint) const; + rtl::Reference<::accessibility::AccessibleShape> GetControl(sal_Int32 nIndex) const; + rtl::Reference<::accessibility::AccessibleShape> + GetForegroundShapeAt(const awt::Point& rPoint) const; // inclusive controls + rtl::Reference<::accessibility::AccessibleShape> + GetBackgroundShapeAt(const awt::Point& rPoint) const; void DataChanged(); void VisAreaChanged() const; @@ -810,23 +812,24 @@ sal_Int32 ScShapeChildren::GetBackShapeCount() const return nCount; } -uno::Reference ScShapeChildren::GetBackShape(sal_Int32 nIndex) const +rtl::Reference<::accessibility::AccessibleShape> +ScShapeChildren::GetBackShape(sal_Int32 nIndex) const { - uno::Reference xAccessible; + rtl::Reference<::accessibility::AccessibleShape> pAccessible; for (const auto& rShapeRange : maShapeRanges) { sal_Int32 nCount(rShapeRange.maBackShapes.size()); if(nIndex < nCount) - xAccessible = GetAccShape(rShapeRange.maBackShapes, nIndex); + pAccessible = GetAccShape(rShapeRange.maBackShapes, nIndex); nIndex -= nCount; - if (xAccessible.is()) + if (pAccessible.is()) break; } if (nIndex >= 0) throw lang::IndexOutOfBoundsException(); - return xAccessible; + return pAccessible; } sal_Int32 ScShapeChildren::GetForeShapeCount() const @@ -837,23 +840,24 @@ sal_Int32 ScShapeChildren::GetForeShapeCount() const return nCount; } -uno::Reference ScShapeChildren::GetForeShape(sal_Int32 nIndex) const +rtl::Reference<::accessibility::AccessibleShape> +ScShapeChildren::GetForeShape(sal_Int32 nIndex) const { - uno::Reference xAccessible; + rtl::Reference<::accessibility::AccessibleShape> pAccessible; for (const auto& rShapeRange : maShapeRanges) { sal_Int32 nCount(rShapeRange.maForeShapes.size()); if(nIndex < nCount) - xAccessible = GetAccShape(rShapeRange.maForeShapes, nIndex); + pAccessible = GetAccShape(rShapeRange.maForeShapes, nIndex); nIndex -= nCount; - if (xAccessible.is()) + if (pAccessible.is()) break; } if (nIndex >= 0) throw lang::IndexOutOfBoundsException(); - return xAccessible; + return pAccessible; } sal_Int32 ScShapeChildren::GetControlCount() const @@ -864,23 +868,23 @@ sal_Int32 ScShapeChildren::GetControlCount() const return nCount; } -uno::Reference ScShapeChildren::GetControl(sal_Int32 nIndex) const +rtl::Reference<::accessibility::AccessibleShape> ScShapeChildren::GetControl(sal_Int32 nIndex) const { - uno::Reference xAccessible; + rtl::Reference<::accessibility::AccessibleShape> pAccessible; for (const auto& rShapeRange : maShapeRanges) { sal_Int32 nCount(rShapeRange.maControls.size()); if(nIndex < nCount) - xAccessible = GetAccShape(rShapeRange.maControls, nIndex); + pAccessible = GetAccShape(rShapeRange.maControls, nIndex); nIndex -= nCount; - if (xAccessible.is()) + if (pAccessible.is()) break; } if (nIndex >= 0) throw lang::IndexOutOfBoundsException(); - return xAccessible; + return pAccessible; } namespace { @@ -903,43 +907,45 @@ struct ScShapePointFound } -uno::Reference ScShapeChildren::GetForegroundShapeAt(const awt::Point& rPoint) const //inclusive Controls +rtl::Reference<::accessibility::AccessibleShape> +ScShapeChildren::GetForegroundShapeAt(const awt::Point& rPoint) const //inclusive Controls { - uno::Reference xAcc; + rtl::Reference<::accessibility::AccessibleShape> pAcc; for(const auto& rShapeRange : maShapeRanges) { ScShapeChildVec::const_iterator aFindItr = std::find_if(rShapeRange.maForeShapes.begin(), rShapeRange.maForeShapes.end(), ScShapePointFound(rPoint)); if (aFindItr != rShapeRange.maForeShapes.end()) - xAcc = GetAccShape(*aFindItr); + pAcc = GetAccShape(*aFindItr); else { ScShapeChildVec::const_iterator aCtrlItr = std::find_if(rShapeRange.maControls.begin(), rShapeRange.maControls.end(), ScShapePointFound(rPoint)); if (aCtrlItr != rShapeRange.maControls.end()) - xAcc = GetAccShape(*aCtrlItr); + pAcc = GetAccShape(*aCtrlItr); } - if (xAcc.is()) + if (pAcc.is()) break; } - return xAcc; + return pAcc; } -uno::Reference ScShapeChildren::GetBackgroundShapeAt(const awt::Point& rPoint) const +rtl::Reference<::accessibility::AccessibleShape> +ScShapeChildren::GetBackgroundShapeAt(const awt::Point& rPoint) const { - uno::Reference xAcc; + rtl::Reference<::accessibility::AccessibleShape> pAcc; for(const auto& rShapeRange : maShapeRanges) { ScShapeChildVec::const_iterator aFindItr = std::find_if(rShapeRange.maBackShapes.begin(), rShapeRange.maBackShapes.end(), ScShapePointFound(rPoint)); if (aFindItr != rShapeRange.maBackShapes.end()) - xAcc = GetAccShape(*aFindItr); - if (xAcc.is()) + pAcc = GetAccShape(*aFindItr); + if (pAcc.is()) break; } - return xAcc; + return pAcc; } ::accessibility::AccessibleShape* ScShapeChildren::GetAccShape(const ScShapeChild& rShape) const @@ -1110,9 +1116,9 @@ ScPagePreviewCountData::ScPagePreviewCountData( const ScPreviewLocationData& rDa } ScAccessibleDocumentPagePreview::ScAccessibleDocumentPagePreview( - const uno::Reference& rxParent, ScPreviewShell* pViewShell ) : - ScAccessibleDocumentBase(rxParent), - mpViewShell(pViewShell) + const rtl::Reference& rpParent, ScPreviewShell* pViewShell) + : ScAccessibleDocumentBase(rpParent) + , mpViewShell(pViewShell) { if (pViewShell) pViewShell->AddAccessibilityObject(*this); diff --git a/sc/source/ui/Accessibility/AccessibleEditObject.cxx b/sc/source/ui/Accessibility/AccessibleEditObject.cxx index 1b3918563665..abae71616cc9 100644 --- a/sc/source/ui/Accessibility/AccessibleEditObject.cxx +++ b/sc/source/ui/Accessibility/AccessibleEditObject.cxx @@ -54,7 +54,7 @@ using ::com::sun::star::lang::IndexOutOfBoundsException; using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; -ScAccessibleEditObject::ScAccessibleEditObject(const rtl::Reference& rpParent, +ScAccessibleEditObject::ScAccessibleEditObject(const rtl::Reference& rpParent, EditView* pEditView, vcl::Window* pWin, const OUString& rName, const OUString& rDescription, EditObjectType eObjectType) @@ -80,11 +80,9 @@ ScAccessibleEditObject::ScAccessibleEditObject(EditObjectType eObjectType) { } -void ScAccessibleEditObject::InitAcc( - const rtl::Reference& rpParent, - EditView* pEditView, - const OUString& rName, - const OUString& rDescription) +void ScAccessibleEditObject::InitAcc(const rtl::Reference& rpParent, + EditView* pEditView, const OUString& rName, + const OUString& rDescription) { SetParent(rpParent); mpEditView = pEditView; @@ -92,14 +90,10 @@ void ScAccessibleEditObject::InitAcc( CreateTextHelper(); SetName(rName); SetDescription(rDescription); - if( meObjectType == CellInEditMode) + if (meObjectType == CellInEditMode && rpParent.is()) { - const ScAccessibleDocument* pAccDoc = static_cast(rpParent.get()); - if (pAccDoc) - { - m_pScDoc = pAccDoc->GetDocument(); - m_curCellAddress =pAccDoc->GetCurCellAddress(); - } + m_pScDoc = rpParent->GetDocument(); + m_curCellAddress = rpParent->GetCurCellAddress(); } } diff --git a/sc/source/ui/Accessibility/AccessiblePageHeader.cxx b/sc/source/ui/Accessibility/AccessiblePageHeader.cxx index d11b2a564a53..564bfeccefe1 100644 --- a/sc/source/ui/Accessibility/AccessiblePageHeader.cxx +++ b/sc/source/ui/Accessibility/AccessiblePageHeader.cxx @@ -47,14 +47,15 @@ using namespace ::com::sun::star::accessibility; const sal_uInt8 MAX_AREAS = 3; -ScAccessiblePageHeader::ScAccessiblePageHeader( const css::uno::Reference& rxParent, - ScPreviewShell* pViewShell, bool bHeader, sal_Int32 nIndex ) : -ScAccessibleContextBase( rxParent, bHeader ? AccessibleRole::HEADER : AccessibleRole::FOOTER ), - mpViewShell( pViewShell ), - mnIndex( nIndex ), - mbHeader( bHeader ), - maAreas(MAX_AREAS, rtl::Reference()), - mnChildCount(-1) +ScAccessiblePageHeader::ScAccessiblePageHeader( + const rtl::Reference& rpParent, ScPreviewShell* pViewShell, + bool bHeader, sal_Int32 nIndex) + : ScAccessibleContextBase(rpParent, bHeader ? AccessibleRole::HEADER : AccessibleRole::FOOTER) + , mpViewShell(pViewShell) + , mnIndex(nIndex) + , mbHeader(bHeader) + , maAreas(MAX_AREAS, rtl::Reference()) + , mnChildCount(-1) { if (mpViewShell) mpViewShell->AddAccessibilityObject(*this); diff --git a/sc/source/ui/Accessibility/AccessiblePageHeaderArea.cxx b/sc/source/ui/Accessibility/AccessiblePageHeaderArea.cxx index 961cd71e6136..5959d7b5a8cb 100644 --- a/sc/source/ui/Accessibility/AccessiblePageHeaderArea.cxx +++ b/sc/source/ui/Accessibility/AccessiblePageHeaderArea.cxx @@ -41,14 +41,12 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; ScAccessiblePageHeaderArea::ScAccessiblePageHeaderArea( - const uno::Reference& rxParent, - ScPreviewShell* pViewShell, - const EditTextObject* pEditObj, - SvxAdjust eAdjust) - : ScAccessibleContextBase(rxParent, AccessibleRole::TEXT), - mpEditObj(pEditObj->Clone()), - mpViewShell(pViewShell), - meAdjust(eAdjust) + const rtl::Reference& rpParent, ScPreviewShell* pViewShell, + const EditTextObject* pEditObj, SvxAdjust eAdjust) + : ScAccessibleContextBase(rpParent, AccessibleRole::TEXT) + , mpEditObj(std::make_unique(*pEditObj)) + , mpViewShell(pViewShell) + , meAdjust(eAdjust) { if (mpViewShell) mpViewShell->AddAccessibilityObject(*this); @@ -81,7 +79,7 @@ void SAL_CALL ScAccessiblePageHeaderArea::disposing() void ScAccessiblePageHeaderArea::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) { - // only notify if child exist, otherwise it is not necessary + // only notify if children exist, otherwise it is not necessary if (rHint.GetId() == SfxHintId::ScAccVisAreaChanged) { if (mpTextHelper) @@ -196,19 +194,14 @@ OUString ScAccessiblePageHeaderArea::createAccessibleName() AbsoluteScreenPixelRectangle ScAccessiblePageHeaderArea::GetBoundingBoxOnScreen() { AbsoluteScreenPixelRectangle aRect; - if (mxParent.is()) + if (mpParent.is()) { - uno::Reference xContext = mxParent->getAccessibleContext(); - uno::Reference xComp(xContext, uno::UNO_QUERY); - if (xComp.is()) - { - // has the same size and position on screen like the parent - aRect = AbsoluteScreenPixelRectangle( - AbsoluteScreenPixelPoint( - vcl::unohelper::ConvertToVCLPoint(xComp->getLocationOnScreen())), - AbsoluteScreenPixelSize( - vcl::unohelper::ConvertToVCLRect(xComp->getBounds()).GetSize())); - } + // has the same size and position on screen like the parent + aRect = AbsoluteScreenPixelRectangle( + AbsoluteScreenPixelPoint( + vcl::unohelper::ConvertToVCLPoint(mpParent->getLocationOnScreen())), + AbsoluteScreenPixelSize( + vcl::unohelper::ConvertToVCLRect(mpParent->getBounds()).GetSize())); } return aRect; } @@ -216,17 +209,12 @@ AbsoluteScreenPixelRectangle ScAccessiblePageHeaderArea::GetBoundingBoxOnScreen( tools::Rectangle ScAccessiblePageHeaderArea::GetBoundingBox() { tools::Rectangle aRect; - if (mxParent.is()) + if (mpParent.is()) { - uno::Reference xContext = mxParent->getAccessibleContext(); - uno::Reference xComp(xContext, uno::UNO_QUERY); - if (xComp.is()) - { // has the same size and position on screen like the parent and so the pos is (0, 0) tools::Rectangle aNewRect(Point(0, 0), - vcl::unohelper::ConvertToVCLRect(xComp->getBounds()).GetSize()); + vcl::unohelper::ConvertToVCLRect(mpParent->getBounds()).GetSize()); aRect = aNewRect; - } } return aRect; diff --git a/sc/source/ui/Accessibility/AccessiblePreviewHeaderCell.cxx b/sc/source/ui/Accessibility/AccessiblePreviewHeaderCell.cxx index fba7b33878a5..c19a1a68f50e 100644 --- a/sc/source/ui/Accessibility/AccessiblePreviewHeaderCell.cxx +++ b/sc/source/ui/Accessibility/AccessiblePreviewHeaderCell.cxx @@ -50,10 +50,9 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; ScAccessiblePreviewHeaderCell::ScAccessiblePreviewHeaderCell( - const css::uno::Reference& rxParent, - ScPreviewShell* pViewShell, const ScAddress& rCellPos, bool bIsColHdr, bool bIsRowHdr, - sal_Int32 nIndex) - : ImplInheritanceHelper(rxParent, AccessibleRole::TABLE_CELL) + const rtl::Reference& rpParent, ScPreviewShell* pViewShell, + const ScAddress& rCellPos, bool bIsColHdr, bool bIsRowHdr, sal_Int32 nIndex) + : ImplInheritanceHelper(rpParent, AccessibleRole::TABLE_CELL) , mpViewShell(pViewShell) , mnIndex(nIndex) , maCellPos(rCellPos) diff --git a/sc/source/ui/Accessibility/AccessiblePreviewTable.cxx b/sc/source/ui/Accessibility/AccessiblePreviewTable.cxx index 21b3e810dd4c..6fb3c9c02941 100644 --- a/sc/source/ui/Accessibility/AccessiblePreviewTable.cxx +++ b/sc/source/ui/Accessibility/AccessiblePreviewTable.cxx @@ -43,9 +43,9 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; ScAccessiblePreviewTable::ScAccessiblePreviewTable( - const css::uno::Reference& rxParent, - ScPreviewShell* pViewShell, sal_Int32 nIndex) - : ImplInheritanceHelper(rxParent, AccessibleRole::TABLE) + const rtl::Reference& rpParent, ScPreviewShell* pViewShell, + sal_Int32 nIndex) + : ImplInheritanceHelper(rpParent, AccessibleRole::TABLE) , mpViewShell(pViewShell) , mnIndex(nIndex) { diff --git a/sc/source/ui/Accessibility/AccessibleTableBase.cxx b/sc/source/ui/Accessibility/AccessibleTableBase.cxx index 1075d0fd17aa..590cd83e228a 100644 --- a/sc/source/ui/Accessibility/AccessibleTableBase.cxx +++ b/sc/source/ui/Accessibility/AccessibleTableBase.cxx @@ -34,9 +34,10 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; -ScAccessibleTableBase::ScAccessibleTableBase(const uno::Reference& rxParent, - ScDocument* pDoc, const ScRange& rRange) - : ImplInheritanceHelper(rxParent, AccessibleRole::TABLE) +ScAccessibleTableBase::ScAccessibleTableBase( + const rtl::Reference& rpParent, ScDocument* pDoc, + const ScRange& rRange) + : ImplInheritanceHelper(rpParent, AccessibleRole::TABLE) , maRange(rRange) , mpDoc(pDoc) { diff --git a/sc/source/ui/StatisticsDialogs/AnalysisOfVarianceDialog.cxx b/sc/source/ui/StatisticsDialogs/AnalysisOfVarianceDialog.cxx index acfab698b601..4dcf06473442 100644 --- a/sc/source/ui/StatisticsDialogs/AnalysisOfVarianceDialog.cxx +++ b/sc/source/ui/StatisticsDialogs/AnalysisOfVarianceDialog.cxx @@ -68,10 +68,11 @@ OUString lclCreateMultiParameterFormula( return aResult.makeStringAndClear(); } -void lclMakeSubRangesList(ScRangeList& rRangeList, const ScRange& rInputRange, ScStatisticsInputOutputDialog::GroupedBy aGroupedBy) +void lclMakeSubRangesList(ScRangeList& rRangeList, const ScRange& rInputRange, + ScStatisticsInputOutputDialog::GroupedBy eGroupedBy) { std::unique_ptr pIterator; - if (aGroupedBy == ScStatisticsInputOutputDialog::BY_COLUMN) + if (eGroupedBy == ScStatisticsInputOutputDialog::GroupedBy::ByColumn) pIterator.reset(new DataRangeByColumnIterator(rInputRange)); else pIterator.reset(new DataRangeByRowIterator(rInputRange)); @@ -164,7 +165,8 @@ void ScAnalysisOfVarianceDialog::RowColumn(ScRangeList& rRangeList, AddressWalke } else { - TranslateId pLabelId = (aGroupedBy == BY_COLUMN) ? STR_COLUMN_LABEL_TEMPLATE : STR_ROW_LABEL_TEMPLATE; + TranslateId pLabelId = (aGroupedBy == GroupedBy::ByColumn) ? STR_COLUMN_LABEL_TEMPLATE + : STR_ROW_LABEL_TEMPLATE; OUString aLabelTemplate(ScResId(pLabelId)); for (size_t i = 0; i < rRangeList.size(); i++) @@ -350,8 +352,8 @@ void ScAnalysisOfVarianceDialog::AnovaTwoFactor(AddressWalkerWriter& output, For ScRangeList aColumnRangeList; ScRangeList aRowRangeList; - lclMakeSubRangesList(aColumnRangeList, mInputRange, BY_COLUMN); - lclMakeSubRangesList(aRowRangeList, mInputRange, BY_ROW); + lclMakeSubRangesList(aColumnRangeList, mInputRange, GroupedBy::ByColumn); + lclMakeSubRangesList(aRowRangeList, mInputRange, GroupedBy::ByRow); // Write ColumnX values output.push(); @@ -360,7 +362,8 @@ void ScAnalysisOfVarianceDialog::AnovaTwoFactor(AddressWalkerWriter& output, For output.resetRow(); ScRange aResultRange; OUString sFormula = OUString::createFromAscii(lclBasicStatistics[i].aFormula); - RowColumn(aColumnRangeList, output, aTemplate, sFormula, BY_COLUMN, &aResultRange); + RowColumn(aColumnRangeList, output, aTemplate, sFormula, GroupedBy::ByColumn, + &aResultRange); if (lclBasicStatistics[i].aResultRangeName != nullptr) { OUString sResultRangeName = OUString::createFromAscii(lclBasicStatistics[i].aResultRangeName); @@ -377,7 +380,7 @@ void ScAnalysisOfVarianceDialog::AnovaTwoFactor(AddressWalkerWriter& output, For output.resetRow(); ScRange aResultRange; OUString sFormula = OUString::createFromAscii(lclBasicStatistics[i].aFormula); - RowColumn(aRowRangeList, output, aTemplate, sFormula, BY_ROW, &aResultRange); + RowColumn(aRowRangeList, output, aTemplate, sFormula, GroupedBy::ByRow, &aResultRange); if (lclBasicStatistics[i].aResultRangeName != nullptr) { diff --git a/sc/source/ui/StatisticsDialogs/DescriptiveStatisticsDialog.cxx b/sc/source/ui/StatisticsDialogs/DescriptiveStatisticsDialog.cxx index d82d7fa0e957..1566711297ba 100644 --- a/sc/source/ui/StatisticsDialogs/DescriptiveStatisticsDialog.cxx +++ b/sc/source/ui/StatisticsDialogs/DescriptiveStatisticsDialog.cxx @@ -75,7 +75,7 @@ ScRange ScDescriptiveStatisticsDialog::ApplyOutput(ScDocShell* pDocShell) FormulaTemplate aTemplate(&mDocument); std::unique_ptr pIterator; - if (mGroupedBy == BY_COLUMN) + if (mGroupedBy == GroupedBy::ByColumn) pIterator.reset(new DataRangeByColumnIterator(mInputRange)); else pIterator.reset(new DataRangeByRowIterator(mInputRange)); @@ -92,7 +92,7 @@ ScRange ScDescriptiveStatisticsDialog::ApplyOutput(ScDocShell* pDocShell) OUString aColRowLabel = mDocument.GetString(pIterator->get().aStart); if (aColRowLabel.isEmpty()) { - if (mGroupedBy == BY_COLUMN) + if (mGroupedBy == GroupedBy::ByColumn) aTemplate.setTemplate(ScResId(STR_COLUMN_LABEL_TEMPLATE)); else aTemplate.setTemplate(ScResId(STR_ROW_LABEL_TEMPLATE)); diff --git a/sc/source/ui/StatisticsDialogs/ExponentialSmoothingDialog.cxx b/sc/source/ui/StatisticsDialogs/ExponentialSmoothingDialog.cxx index d7fe7c872167..a25df2f41031 100644 --- a/sc/source/ui/StatisticsDialogs/ExponentialSmoothingDialog.cxx +++ b/sc/source/ui/StatisticsDialogs/ExponentialSmoothingDialog.cxx @@ -63,7 +63,7 @@ ScRange ScExponentialSmoothingDialog::ApplyOutput(ScDocShell* pDocShell) output.push(); std::unique_ptr pIterator; - if (mGroupedBy == BY_COLUMN) + if (mGroupedBy == GroupedBy::ByColumn) pIterator.reset(new DataRangeByColumnIterator(mInputRange)); else pIterator.reset(new DataRangeByRowIterator(mInputRange)); @@ -75,7 +75,7 @@ ScRange ScExponentialSmoothingDialog::ApplyOutput(ScDocShell* pDocShell) ScRange aCurrentRange = pIterator->get(); // Write column label - if (mGroupedBy == BY_COLUMN) + if (mGroupedBy == GroupedBy::ByColumn) aTemplate.setTemplate(ScResId(STR_COLUMN_LABEL_TEMPLATE)); else aTemplate.setTemplate(ScResId(STR_ROW_LABEL_TEMPLATE)); diff --git a/sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx b/sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx index c95f211ae7dc..4cd4162f40b7 100644 --- a/sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx +++ b/sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx @@ -114,7 +114,7 @@ bool ScFourierAnalysisDialog::InputRangesValid() mInputRange.PutInOrder(); - mbGroupedByColumn = mGroupedBy == BY_COLUMN; + mbGroupedByColumn = mGroupedBy == GroupedBy::ByColumn; mbWithLabels = mxWithLabelsCheckBox->get_active(); mbUse3DAddresses = mInputRange.aStart.Tab() != mOutputAddress.Tab(); diff --git a/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx b/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx index f2059ff822a8..c57e818cc745 100644 --- a/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx +++ b/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx @@ -63,9 +63,9 @@ ScRange ScMatrixComparisonGenerator::ApplyOutput(ScDocShell* pDocShell) SCTAB inTab = mInputRange.aStart.Tab(); - ScRangeList aRangeList = (mGroupedBy == BY_COLUMN) ? - MakeColumnRangeList(inTab, mInputRange.aStart, mInputRange.aEnd) : - MakeRowRangeList(inTab, mInputRange.aStart, mInputRange.aEnd); + ScRangeList aRangeList = (mGroupedBy == GroupedBy::ByColumn) + ? MakeColumnRangeList(inTab, mInputRange.aStart, mInputRange.aEnd) + : MakeRowRangeList(inTab, mInputRange.aStart, mInputRange.aEnd); // labels output.writeString(getLabel()); @@ -76,7 +76,7 @@ ScRange ScMatrixComparisonGenerator::ApplyOutput(ScDocShell* pDocShell) // write labels to columns for (size_t i = 0; i < aRangeList.size(); i++) { - if (mGroupedBy == BY_COLUMN) + if (mGroupedBy == GroupedBy::ByColumn) aTemplate.setTemplate(ScResId(STR_COLUMN_LABEL_TEMPLATE)); else aTemplate.setTemplate(ScResId(STR_ROW_LABEL_TEMPLATE)); @@ -91,7 +91,7 @@ ScRange ScMatrixComparisonGenerator::ApplyOutput(ScDocShell* pDocShell) output.nextRow(); for (size_t i = 0; i < aRangeList.size(); i++) { - if (mGroupedBy == BY_COLUMN) + if (mGroupedBy == GroupedBy::ByColumn) aTemplate.setTemplate(ScResId(STR_COLUMN_LABEL_TEMPLATE)); else aTemplate.setTemplate(ScResId(STR_ROW_LABEL_TEMPLATE)); diff --git a/sc/source/ui/StatisticsDialogs/MovingAverageDialog.cxx b/sc/source/ui/StatisticsDialogs/MovingAverageDialog.cxx index 4cbe9343e200..0334349c2cf8 100644 --- a/sc/source/ui/StatisticsDialogs/MovingAverageDialog.cxx +++ b/sc/source/ui/StatisticsDialogs/MovingAverageDialog.cxx @@ -52,7 +52,7 @@ ScRange ScMovingAverageDialog::ApplyOutput(ScDocShell* pDocShell) mDocument.GetDataAreaSubrange(mInputRange); std::unique_ptr pIterator; - if (mGroupedBy == BY_COLUMN) + if (mGroupedBy == GroupedBy::ByColumn) pIterator.reset(new DataRangeByColumnIterator(mInputRange)); else pIterator.reset(new DataRangeByRowIterator(mInputRange)); @@ -65,7 +65,7 @@ ScRange ScMovingAverageDialog::ApplyOutput(ScDocShell* pDocShell) output.resetRow(); // Write label - if (mGroupedBy == BY_COLUMN) + if (mGroupedBy == GroupedBy::ByColumn) aTemplate.setTemplate(ScResId(STR_COLUMN_LABEL_TEMPLATE)); else aTemplate.setTemplate(ScResId(STR_ROW_LABEL_TEMPLATE)); diff --git a/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx b/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx index 998a075e22ca..6a0444946a17 100644 --- a/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx +++ b/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx @@ -64,7 +64,7 @@ ScStatisticsInputOutputDialog::ScStatisticsInputOutputDialog( , mInputRange(ScAddress::INITIALIZE_INVALID) , mAddressDetails(mDocument.GetAddressConvention(), 0, 0) , mOutputAddress(ScAddress::INITIALIZE_INVALID) - , mGroupedBy(BY_COLUMN) + , mGroupedBy(GroupedBy::ByColumn) , mxButtonOk(m_xBuilder->weld_button(u"ok"_ustr)) , mxButtonCancel(m_xBuilder->weld_button(u"cancel"_ustr)) , mpActiveEdit(nullptr) @@ -220,9 +220,9 @@ IMPL_LINK_NOARG(ScStatisticsInputOutputDialog, LoseButtonFocusHandler, formula:: IMPL_LINK_NOARG( ScStatisticsInputOutputDialog, GroupByChanged, weld::Toggleable&, void ) { if (mxGroupByColumnsRadio->get_active()) - mGroupedBy = BY_COLUMN; + mGroupedBy = GroupedBy::ByColumn; else if (mxGroupByRowsRadio->get_active()) - mGroupedBy = BY_ROW; + mGroupedBy = GroupedBy::ByRow; ValidateDialogInput(); } diff --git a/sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx b/sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx index 4ed3cb2e0ecd..47764af60876 100644 --- a/sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx +++ b/sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx @@ -222,8 +222,8 @@ void AddressWalkerWriter::writeBoldString(const OUString& aString) aItemSet.Put(aWeight); aItemSet.Put(aJustify); rEngine.QuickSetAttribs(aItemSet, ESelection(0, 0, 0, aString.getLength()) ); - std::unique_ptr pEditText(rEngine.CreateTextObject()); - mpDocShell->GetDocFunc().SetEditCell(mCurrentAddress, *pEditText, true); + EditTextObject aEditText(rEngine.CreateTextObject()); + mpDocShell->GetDocFunc().SetEditCell(mCurrentAddress, aEditText, true); } void AddressWalkerWriter::writeValue(double aValue) diff --git a/sc/source/ui/app/client.cxx b/sc/source/ui/app/client.cxx index f3af0655f5db..ab7545610521 100644 --- a/sc/source/ui/app/client.cxx +++ b/sc/source/ui/app/client.cxx @@ -177,7 +177,7 @@ void ScClient::ViewChanged() if ( GetAspect() == embed::Aspects::MSOLE_ICON ) { // the iconified object seems not to need such a scaling handling - // since the replacement image and the size a completely controlled by the container + // since the replacement image and the size are completely controlled by the container // TODO/LATER: when the icon exchange is implemented the scaling handling might be required again here return; diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index a89c5b62832a..9899ca5d348e 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include @@ -150,13 +149,20 @@ ScTypedCaseStrSet::const_iterator findText( return rDataSet.end(); // no matching text found } +OUString lcl_RemoveLineEnd(const OUString& rStr) +{ + return convertLineEnd(rStr, LINEEND_LF).replace('\n', ' '); +} + OUString getExactMatch(const ScTypedCaseStrSet& rDataSet, const OUString& rString) { - auto it = std::find_if(rDataSet.begin(), rDataSet.end(), - [&rString](const ScTypedStrData& rData) { - return (rData.GetStringType() != ScTypedStrData::Value) - && ScGlobal::GetTransliteration().isEqual(rData.GetString(), rString); - }); + // tdf#98913 - compare strings without line ends + auto it + = std::find_if(rDataSet.begin(), rDataSet.end(), [&rString](const ScTypedStrData& rData) { + return (rData.GetStringType() != ScTypedStrData::Value) + && ScGlobal::GetTransliteration().isEqual(lcl_RemoveLineEnd(rData.GetString()), + rString); + }); if (it != rDataSet.end()) return it->GetString(); return rString; @@ -728,12 +734,6 @@ static void lcl_RemoveTabs(OUString& rStr) rStr = rStr.replace('\t', ' '); } -static void lcl_RemoveLineEnd(OUString& rStr) -{ - rStr = convertLineEnd(rStr, LINEEND_LF); - rStr = rStr.replace('\n', ' '); -} - static sal_Int32 lcl_MatchParenthesis( const OUString& rStr, sal_Int32 nPos ) { int nDir; @@ -859,8 +859,7 @@ ScInputHandler::ScInputHandler() eAttrAdjust( SvxCellHorJustify::Standard ), fScaleX( 1.0 ), fScaleY( 1.0 ), - pRefViewSh( nullptr ), - pLastPattern( nullptr ) + pRefViewSh( nullptr ) { // The InputHandler is constructed with the view, so SfxViewShell::Current // doesn't have the right view yet. pActiveViewSh is updated in NotifyChange. @@ -940,6 +939,21 @@ void ScInputHandler::ImplCreateEditEngine() mpEditEngine->SetControlWord( mpEditEngine->GetControlWord() | EEControlBits::AUTOCORRECT ); mpEditEngine->SetReplaceLeadingSingleQuotationMark( false ); mpEditEngine->SetModifyHdl( LINK( this, ScInputHandler, ModifyHdl ) ); + mpEditEngine->SetEndPasteOrDropHdl( LINK( this, ScInputHandler, EndPasteOrDropHdl ) ); +} + +IMPL_LINK_NOARG( ScInputHandler, EndPasteOrDropHdl, PasteOrDropInfos&, void ) +{ + // tdf#167545: clipboard / drag-and-drop data can carry paragraph-level + // attributes (notably SvxAdjustItem) that override the cell pattern's + // adjust in the in-edit EditEngine and shift the overlay paint outside + // the destination cell. Calc cells don't store paragraph attribs; + // EnterHandler strips them at commit. Do the same after every paste / + // drop so in-edit rendering matches the committed result: RemoveAdjust + // drops paragraph attribs (migrating differing char-level items down to + // characters), and UpdateAdjust re-applies the cell pattern's defaults. + RemoveAdjust(); + UpdateAdjust( 0 ); } void ScInputHandler::UpdateAutoCorrFlag() @@ -984,7 +998,7 @@ void ScInputHandler::UpdateSpellSettings( bool bFromStartTab ) else nCntrl &= ~EEControlBits::ONLINESPELLING; // No AutoCorrect for Symbol Font (EditEngine does no evaluate Default) - if ( pLastPattern && pLastPattern->IsSymbolFont() ) + if ( maLastPattern && maLastPattern.getScPatternAttr()->IsSymbolFont() ) nCntrl &= ~EEControlBits::AUTOCORRECT; else nCntrl |= EEControlBits::AUTOCORRECT; @@ -1004,7 +1018,7 @@ void ScInputHandler::UpdateSpellSettings( bool bFromStartTab ) mpEditEngine->SetSpeller( xXSpellChecker1 ); } - bool bHyphen = pLastPattern && pLastPattern->GetItem(ATTR_HYPHENATE).GetValue(); + bool bHyphen = maLastPattern && maLastPattern.getScPatternAttr()->GetItem(ATTR_HYPHENATE).GetValue(); if ( bHyphen ) { css::uno::Reference xXHyphenator( LinguMgr::GetHyphenator() ); mpEditEngine->SetHyphenator( xXHyphenator ); @@ -1277,7 +1291,7 @@ void ScInputHandler::ShowArgumentsTip( OUString& rSelText ) } const SfxViewShell* pViewShell = SfxViewShell::Current(); - if (comphelper::LibreOfficeKit::isActive() && pViewShell && pViewShell->isLOKDesktop()) + if (comphelper::LibreOfficeKit::isActive() && pViewShell) { tools::JsonWriter writer; writer.put("type", "formulausage"); @@ -1875,19 +1889,6 @@ void ScTabViewShell::LOKSendFormulabarUpdate(const EditView* pActiveView, sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter ); maSendFormulabarUpdate.m_separator = pFormatter->GetFormatDecimalSep(nFormat); } - - maSendFormulabarUpdate.Send(); -} - -void ScTabViewShell::SendFormulabarUpdate::Send() -{ - std::unique_ptr pData = std::make_unique(); - (*pData)["action_type"_ostr] = "setText"; - (*pData)["text"_ostr] = m_aText; - (*pData)["selection"_ostr] = m_aSelection; - (*pData)["separator"_ostr] = m_separator; - OUString sWindowId = OUString::number(m_nShellId) + "formulabar"; - jsdialog::SendAction(sWindowId, u"sc_input_window"_ustr, std::move(pData)); } // Calculate selection and display as tip help @@ -2159,7 +2160,7 @@ void ScInputHandler::UseColData() // When typing // Strings can contain line endings (e.g. due to dBase import), // which would result in multiple paragraphs here, which is not desirable. //! Then GetExactMatch doesn't work either - lcl_RemoveLineEnd( aNew ); + aNew = lcl_RemoveLineEnd( aNew ); // Keep paragraph, just append the rest //! Exact replacement in EnterHandler !!! @@ -2216,7 +2217,7 @@ void ScInputHandler::NextAutoEntry( bool bBack ) bInOwnChange = true; // disable ModifyHdl (reset below) mbPartialPrefix = false; - lcl_RemoveLineEnd( aNew ); + aNew = lcl_RemoveLineEnd( aNew ); OUString aIns = aNew.copy(aAutoSearch.getLength()); // when editing in input line, apply to both edit views @@ -2318,7 +2319,7 @@ void ScInputHandler::ViewShellGone(const ScTabViewShell* pViewSh) // Executed sy if ( pViewSh == pActiveViewSh ) { pLastState.reset(); - pLastPattern = nullptr; + maLastPattern.setScPatternAttr(nullptr); } ScModule* mod = ScModule::get(); @@ -2390,6 +2391,9 @@ void ScInputHandler::UpdateActiveView() // tdf#71409: Always create the edit engine instance for the input // window, in order to properly manage accessibility events. pTopView = pInputWin->GetEditView(); + // tdf#82599 - sync pTableView to keep insert/overwrite mode consistent + if (pTopView && pTableView) + pTableView->SetInsertMode(pTopView->IsInsertMode()); if (eMode != SC_INPUT_TOP) pTopView = nullptr; } @@ -2418,7 +2422,7 @@ EditView* ScInputHandler::GetActiveView() void ScInputHandler::ForgetLastPattern() { - pLastPattern = nullptr; + maLastPattern.setScPatternAttr(nullptr); if ( !pLastState && pActiveViewSh ) pActiveViewSh->UpdateInputHandler( true ); // Get status again else @@ -2486,9 +2490,9 @@ void ScInputHandler::UpdateAdjust( sal_Unicode cTyped ) } // Cells with an explicit RTL writing direction are always right adjusted - if (pLastPattern) + if (maLastPattern) { - SvxFrameDirection eDir = pLastPattern->GetItem(ATTR_WRITINGDIR).GetValue(); + SvxFrameDirection eDir = maLastPattern.getScPatternAttr()->GetItem(ATTR_WRITINGDIR).GetValue(); if (eDir == SvxFrameDirection::Horizontal_RL_TB) { eSvxAdjust = SvxAdjust::Right; @@ -2527,9 +2531,9 @@ void ScInputHandler::UpdateAdjust( sal_Unicode cTyped ) break; } - bool bAsianVertical = pLastPattern && - pLastPattern->GetItem( ATTR_STACKED ).GetValue() && - pLastPattern->GetItem( ATTR_VERTICAL_ASIAN ).GetValue(); + bool bAsianVertical = maLastPattern && + maLastPattern.getScPatternAttr()->GetItem( ATTR_STACKED ).GetValue() && + maLastPattern.getScPatternAttr()->GetItem( ATTR_VERTICAL_ASIAN ).GetValue(); if ( bAsianVertical ) { // Always edit at top of cell -> LEFT when editing vertically @@ -2607,9 +2611,17 @@ bool ScInputHandler::StartTable(sal_Unicode cTyped, bool bFromCommand, bool bInp aTester.TestSelectedBlock( rDoc, aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Col(), aCursorPos.Row(), rMark ); + // Single cell input on a matrix reference cell is allowed. Writing + // turns the reference cell into a blocker, the matrix master detects + // it via spill resolution and collapses to #SPILL!. The matrix + // protection only fires for multi cell or master cell edits. + const bool bAllowMatrixRef + = !rMark.IsMarked() && !rMark.IsMultiMarked() + && aTester.IsEditableOrMatrixCell(rDoc, aCursorPos); + bool bStartInputMode = !(pActiveViewSh->GetViewShell() && pActiveViewSh->GetViewShell()->IsLokReadOnlyView()); - if (!aTester.IsEditable()) + if (!aTester.IsEditable() && !bAllowMatrixRef) { bProtected = true; // We allow read-only input mode activation regardless @@ -2647,7 +2659,7 @@ bool ScInputHandler::StartTable(sal_Unicode cTyped, bool bFromCommand, bool bInp const ScPatternAttr* pPattern = rDoc.GetPattern( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab() ); - if (!ScPatternAttr::areSame(pPattern, pLastPattern)) + if (!ScPatternAttr::areSame(pPattern, maLastPattern.getScPatternAttr())) { // Percent format? const SfxItemSet& rAttrSet = pPattern->GetItemSet(); @@ -2680,7 +2692,7 @@ bool ScInputHandler::StartTable(sal_Unicode cTyped, bool bFromCommand, bool bInp pPattern->FillEditItemSet( pEditDefaults.get() ); mpEditEngine->SetDefaults( *pEditDefaults ); - pLastPattern = pPattern; + maLastPattern.setScPatternAttr(pPattern); bLastIsSymbol = pPattern->IsSymbolFont(); // Background color must be known for automatic font color. @@ -3321,7 +3333,7 @@ void ScInputHandler::EnterHandler( ScEnterMode nBlockMode, bool bBeforeSavingInL void ScInputHandler::EnterHandler2(ScEnterMode nBlockMode, bool bForget, OUString aString, const OUString& aPreAutoCorrectString) { - std::unique_ptr pObject; + std::optional oObject; std::unique_ptr pCellAttrs; bool bMatrix = (nBlockMode == ScEnterMode::MATRIX); SfxApplication* pSfxApp = SfxGetpApp(); @@ -3487,7 +3499,7 @@ void ScInputHandler::EnterHandler2(ScEnterMode nBlockMode, bool bForget, OUStrin if (bAttrib) { mpEditEngine->ClearSpellErrors(); - pObject = mpEditEngine->CreateTextObject(); + oObject.emplace(mpEditEngine->CreateTextObject()); } else if (ScModule::get()->GetAppOptions().GetAutoComplete()) // Adjust Upper/Lower case { @@ -3531,8 +3543,8 @@ void ScInputHandler::EnterHandler2(ScEnterMode nBlockMode, bool bForget, OUStrin StopInputWinEngine(true); // Text input (through number formats) or ApplySelectionPattern modify - // the cell's attributes, so pLastPattern is no longer valid - pLastPattern = nullptr; + // the cell's attributes, so the last pattern is no longer valid + maLastPattern.setScPatternAttr(nullptr); if (bOldMod && !bProtected && !bForget) { @@ -3589,14 +3601,14 @@ void ScInputHandler::EnterHandler2(ScEnterMode nBlockMode, bool bForget, OUStrin { ScInputStatusItem aItem(FID_INPUTLINE_STATUS, aCursorPos, aCursorPos, aCursorPos, - aPreAutoCorrectString, pObject.get()); + aPreAutoCorrectString, oObject ? &*oObject : nullptr); aArgs[0] = &aItem; rBindings.Execute(nId, aArgs); } ScInputStatusItem aItemCorrected(FID_INPUTLINE_STATUS, aCursorPos, aCursorPos, aCursorPos, - aString, pObject.get()); + aString, oObject ? &*oObject : nullptr); sc::MisspellRangeResult aMisspellRangeResult; if ( !aMisspellRanges.empty() ) @@ -4629,12 +4641,21 @@ IMPL_LINK_NOARG( ScInputHandler, DelayTimer, Timer*, void ) bInOwnChange = true; // disable ModifyHdl (reset below) pActiveViewSh = nullptr; - mpEditEngine->SetTextCurrentDefaults( OUString() ); - if ( pInputWin ) + // tdf#97354 - keep formula bar content visible while a ref dialog is open + if (!ScModule::get()->IsRefDialogOpen()) + { + mpEditEngine->SetTextCurrentDefaults(OUString()); + if (pInputWin) + { + pInputWin->SetPosString(OUString()); + pInputWin->SetTextString(OUString(), true); + } + } + if (pInputWin) { - pInputWin->SetPosString( OUString() ); - pInputWin->SetTextString(OUString(), true); pInputWin->Disable(); + // tdf#97354 - repaint to update the input line's disabled text color + pInputWin->TextInvalidate(); } bInOwnChange = false; @@ -4718,9 +4739,8 @@ bool ScInputHandler::GetTextAndFields( ScEditEngineDefaulter& rDestEngine ) if ( eFieldState == SfxItemState::INVALID || eFieldState == SfxItemState::SET ) { // Copy content - std::unique_ptr pObj = mpEditEngine->CreateTextObject(); - rDestEngine.SetTextCurrentDefaults(*pObj); - pObj.reset(); + EditTextObject aObj = mpEditEngine->CreateTextObject(); + rDestEngine.SetTextCurrentDefaults(aObj); sal_Int32 nParCnt = mpEditEngine->GetParagraphCount(); // Delete attributes @@ -4855,7 +4875,7 @@ ScInputHdlState::ScInputHdlState( const ScAddress& rCurPos, aStartPos ( rStartPos ), aEndPos ( rEndPos ), aString (std::move( _aString )), - pEditData ( pData ? pData->Clone() : nullptr ) + pEditData ( pData ? std::make_unique(*pData) : nullptr ) { } @@ -4887,7 +4907,7 @@ ScInputHdlState& ScInputHdlState::operator=( const ScInputHdlState& r ) aString = r.aString; pEditData.reset(); if (r.pEditData) - pEditData = r.pEditData->Clone(); + pEditData = std::make_unique(*r.pEditData); } return *this; } diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx index b0c7deb6f3d2..b08c545c7fda 100644 --- a/sc/source/ui/app/inputwin.cxx +++ b/sc/source/ui/app/inputwin.cxx @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -47,6 +48,7 @@ #include #include #include +#include #include #include @@ -121,13 +123,11 @@ enum ScNameInputType SFX_IMPL_CHILDWINDOW_WITHID(ScInputWindowWrapper,FID_INPUTLINE_STATUS) -ScInputWindowWrapper::ScInputWindowWrapper( vcl::Window* pParentP, - sal_uInt16 nId, - SfxBindings* pBindings, - SfxChildWinInfo* /* pInfo */ ) - : SfxChildWindow( pParentP, nId ) +ScInputWindowWrapper::ScInputWindowWrapper(vcl::Window* pParentP, sal_uInt16 nId, + SfxBindings& rBindings, SfxChildWinInfo&) + : SfxChildWindow(pParentP, nId) { - VclPtr pWin = VclPtr::Create( pParentP, pBindings ); + VclPtr pWin = VclPtr::Create(pParentP, &rBindings); SetWindow( pWin ); pWin->Show(); @@ -135,7 +135,7 @@ ScInputWindowWrapper::ScInputWindowWrapper( vcl::Window* pParentP, pWin->SetSizePixel( pWin->CalcWindowSizePixel() ); SetAlignment(SfxChildAlignment::LOWESTTOP); - pBindings->Invalidate( FID_TOGGLEINPUTLINE ); + rBindings.Invalidate(FID_TOGGLEINPUTLINE); } /** @@ -164,7 +164,7 @@ static ScTabViewShell* lcl_chooseRuntimeImpl( const SfxBindings* pBind ) ScInputWindow::ScInputWindow( vcl::Window* pParent, const SfxBindings* pBind ) : // With WB_CLIPCHILDREN otherwise we get flickering ToolBox ( pParent, WinBits(WB_CLIPCHILDREN | WB_BORDER | WB_NOSHADOW) ), - aWndPos ( VclPtr::Create( this, lcl_chooseRuntimeImpl(pBind)) ), + aWndPos(VclPtr::Create(this)), mxTextWindow ( VclPtr::Create( this, lcl_chooseRuntimeImpl(pBind)) ), pInputHdl ( nullptr ), mpViewShell ( nullptr ), @@ -195,10 +195,7 @@ ScInputWindow::ScInputWindow( vcl::Window* pParent, const SfxBindings* pBind ) : InsertItem (SID_INPUT_FUNCTION, Image(StockImage::Yes, RID_BMP_INPUT_FUNCTION), ToolBoxItemBits::NONE, 2); } - const bool bIsLOKMobilePhone = mpViewShell && mpViewShell->isLOKMobilePhone(); - // sigma and equal buttons - if (!bIsLOKMobilePhone) { InsertItem (SID_INPUT_SUM, Image(StockImage::Yes, RID_BMP_INPUT_SUM), ToolBoxItemBits::DROPDOWN, 3); InsertItem (SID_INPUT_EQUAL, Image(StockImage::Yes, RID_BMP_INPUT_EQUAL), ToolBoxItemBits::NONE, 4); @@ -223,7 +220,6 @@ ScInputWindow::ScInputWindow( vcl::Window* pParent, const SfxBindings* pBind ) : } // sigma and equal buttons - if (!bIsLOKMobilePhone) { SetHelpId (SID_INPUT_SUM, HID_INSWIN_SUM); SetHelpId (SID_INPUT_EQUAL, HID_INSWIN_FUNC); @@ -429,12 +425,6 @@ void ScInputWindow::StartFormula() if (comphelper::LibreOfficeKit::isActive()) { TextGrabFocus(); - if (pViewSh && !pViewSh->isLOKDesktop()) - { - nStartPara = nEndPara = pView->getEditEngine().GetParagraphCount() ? - (pView->getEditEngine().GetParagraphCount() - 1) : 0; - nStartPos = nEndPos = pView->getEditEngine().GetTextLen(nStartPara); - } } pView->SetSelection(ESelection(nStartPara, nStartPos, nEndPara, nEndPos)); pScMod->InputChanged(pView); @@ -452,7 +442,7 @@ void ScInputWindow::PixelInvalidate(const tools::Rectangle* pRectangle) if (pRectangle) { tools::Rectangle aRect(*pRectangle); - aRect.Move(-GetOutOffXPixel(), -GetOutOffYPixel()); + aRect.Move(-GetDeviceOriginX(), -GetDeviceOriginY()); Window::PixelInvalidate(&aRect); } else @@ -858,7 +848,7 @@ void ScInputWindow::AutoSum( bool& bRangeFinder, bool& bSubTotal, OpCode eCode ) } ScInputBarGroup::ScInputBarGroup(vcl::Window* pParent, ScTabViewShell* pViewSh) - : InterimItemWindow(pParent, u"modules/scalc/ui/inputbar.ui"_ustr, u"InputBar"_ustr, true, reinterpret_cast(pViewSh)) + : InterimItemWindow(pParent, u"modules/scalc/ui/inputbar.ui"_ustr, u"InputBar"_ustr, true) , mxBackground(m_xBuilder->weld_container(u"background"_ustr)) , mxTextWndGroup(new ScTextWndGroup(*this, pViewSh)) , mxButtonUp(m_xBuilder->weld_button(u"up"_ustr)) @@ -882,10 +872,7 @@ ScInputBarGroup::ScInputBarGroup(vcl::Window* pParent, ScTabViewShell* pViewSh) mxButtonUp->set_size_request(-1, nHeight); mxButtonDown->set_size_request(-1, nHeight); - // disable the multiline toggle on the mobile phones - const SfxViewShell* pViewShell = SfxViewShell::Current(); - if (!comphelper::LibreOfficeKit::isActive() || !(pViewShell && pViewShell->isLOKMobilePhone())) - mxButtonDown->show(); + mxButtonDown->show(); // tdf#154042 Use an initial height of one row so the Toolbar positions // this in the same place regardless of how many rows it eventually shows @@ -1327,6 +1314,23 @@ void ScTextWnd::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangl } } + if (m_xEditEngine) + { + // tdf#97354 - use disabled text color while a modeless ref dialog owns reference input + Color aTxtColor = ScModule::get()->IsRefDialogOpen() ? rStyleSettings.GetDisableColor() + : rStyleSettings.GetWindowTextColor(); + if (aTextFont.GetColor() != aTxtColor) + { + aTextFont.SetColor(aTxtColor); + SfxItemSet aColorSet(m_xEditEngine->GetEmptyItemSet()); + aColorSet.Put(SvxColorItem(aTxtColor, EE_CHAR_COLOR)); + const bool bPrevInputMode = bInputMode; + bInputMode = true; + m_xEditEngine->QuickSetAttribs(aColorSet, ESelection::All()); + bInputMode = bPrevInputMode; + } + } + if (comphelper::LibreOfficeKit::isActive() && m_xEditEngine) { // EditEngine/EditView works in twips logical coordinates, so set the device map-mode to twips before painting @@ -1676,6 +1680,10 @@ void ScTextWnd::UpdateFocus(const ErrorHdl& errorHdl) bool ScTextWnd::MouseButtonDown( const MouseEvent& rMEvt ) { + // tdf#97354 - prevent editable input line while a modeless ref dialog owns reference input + if (ScModule::get()->IsRefDialogOpen()) + return false; + // tdf#169351 If trying to set focus to the formula bar triggers an error // dialog, intercept the launch of that dialog to detect this case, and in // that case abandon the mouse handler. @@ -1850,20 +1858,13 @@ bool ScTextWnd::Command( const CommandEvent& rCEvt ) StartEditEngine(ScInputHandler::ErrorMessage); TextGrabFocus(); - // information about paragraph is in additional data - // information about position in a paragraph in a Mouse Pos - // see vcl/jsdialog/executor.cxx "textselection" event - const Point* pParaPoint = static_cast(rCEvt.GetEventData()); Point aSelectionStartEnd = rCEvt.GetMousePosPixel(); - sal_Int32 nParaStart, nParaEnd, nPosStart, nPosEnd; + sal_Int32 nPosStart, nPosEnd; + nPosStart = m_xEditView->GetPosNoField(0, aSelectionStartEnd.X()); + nPosEnd = m_xEditView->GetPosNoField(0, aSelectionStartEnd.Y()); - nParaStart = pParaPoint ? pParaPoint->X() : 0; - nParaEnd = pParaPoint ? pParaPoint->Y() : 0; - nPosStart = m_xEditView->GetPosNoField(nParaStart, aSelectionStartEnd.X()); - nPosEnd = m_xEditView->GetPosNoField(nParaEnd, aSelectionStartEnd.Y()); - - m_xEditView->SetSelection(ESelection(nParaStart, nPosStart, nParaEnd, nPosEnd)); + m_xEditView->SetSelection(ESelection(0, nPosStart, 0, nPosEnd)); pScMod->InputSelection(m_xEditView.get()); bConsumed = true; @@ -2274,9 +2275,8 @@ void ScTextWnd::TextGrabFocus() } // Position window -ScPosWnd::ScPosWnd(vcl::Window* pParent, ScTabViewShell* pViewShell) - : InterimItemWindow(pParent, u"modules/scalc/ui/posbox.ui"_ustr, u"PosBox"_ustr, true, - reinterpret_cast(pViewShell)) +ScPosWnd::ScPosWnd(vcl::Window* pParent) + : InterimItemWindow(pParent, u"modules/scalc/ui/posbox.ui"_ustr, u"PosBox"_ustr, true) , m_xWidget(m_xBuilder->weld_combo_box(u"pos_window"_ustr)) , m_nAsyncGetFocusId(nullptr) , nTipVisible(nullptr) @@ -2364,8 +2364,8 @@ void ScPosWnd::FillRangeNames(bool initialize) ScDocument& rDoc = pDocShell->GetDocument(); ScRange aDummy; - ScRangeName* pRangeNames = rDoc.GetRangeName(); - for (const auto& rEntry : *pRangeNames) + ScRangeName& rRangeNames = rDoc.GetRangeName(); + for (const auto& rEntry : rRangeNames) { if (rEntry.second->IsValidReference(aDummy)) aSet.insert(rEntry.second->GetName()); @@ -2637,16 +2637,16 @@ void ScPosWnd::DoEnter() } else if ( eType == SC_NAME_INPUT_DEFINE ) { - ScRangeName* pNames = rDoc.GetRangeName(); + ScRangeName& rNames = rDoc.GetRangeName(); ScRange aSelection; - if ( pNames && !pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aText)) && + if ( !rNames.findByUpperName(ScGlobal::getCharClass().uppercase(aText)) && (rViewData.GetSimpleArea( aSelection ) == SC_MARK_SIMPLE) ) { - ScRangeName aNewRanges( *pNames ); + ScRangeName aNewRanges( rNames ); ScAddress aCursor( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.CurrentTabForData() ); OUString aContent(aSelection.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention())); - ScRangeData* pNew = new ScRangeData( rDoc, aText, aContent, aCursor ); - if ( aNewRanges.insert(pNew) ) + std::unique_ptr pNew(new ScRangeData( rDoc, aText, aContent, aCursor )); + if ( aNewRanges.insert(std::move(pNew)) ) { pDocShell->GetDocFunc().ModifyRangeNames( aNewRanges ); pViewSh->UpdateInputHandler(true); diff --git a/sc/source/ui/app/scdll.cxx b/sc/source/ui/app/scdll.cxx index 5766417d13ad..6b6efcc44376 100644 --- a/sc/source/ui/app/scdll.cxx +++ b/sc/source/ui/app/scdll.cxx @@ -152,7 +152,7 @@ void ScDLL::Init() SvxClipBoardControl ::RegisterControl(SID_PASTE_UNFORMATTED, pMod ); svx::FormatPaintBrushToolBoxControl::RegisterControl(SID_FORMATPAINTBRUSH, pMod ); sc::ScNumberFormatControl ::RegisterControl(SID_NUMBER_TYPE_FORMAT, pMod ); - sc::SheetViewControl::RegisterControl(FID_CURRENT_SHEET_VIEW, pMod); + sc::SheetViewControl::RegisterControl(FID_SELECT_SHEET_VIEW, pMod); sc::TableStylesControl ::RegisterControl(SID_DATABASE_SETTINGS, pMod); SvxGrafModeToolBoxControl ::RegisterControl(SID_ATTR_GRAF_MODE, pMod); diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx index 28f53ab86cdb..90afa969fdbc 100644 --- a/sc/source/ui/app/scmod.cxx +++ b/sc/source/ui/app/scmod.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include #include #include #include @@ -46,6 +47,8 @@ #include #include #include +#include +#include #include #include @@ -157,7 +160,19 @@ ScModule::ScModule( SfxObjectFactory* pFact ) : ScModule::~ScModule() { - OSL_ENSURE( !m_pSelTransfer, "Selection Transfer object not deleted" ); + assert( !m_pSelTransfer && "Selection Transfer object not deleted" ); + + // Mostly here to prevent leaks during shutdown when running unit tests + // Need to clear this early in the shutdown process, because it might hold references + // to large complex things like ScDocument. + try { + css::uno::Reference xClipboard = + css::datatransfer::clipboard::SystemClipboard::create( + comphelper::getProcessComponentContext()); + xClipboard->setContents( nullptr, nullptr ); + } catch (css::uno::DeploymentException const&) { + // ignore, sometimes happens that UNO is already shutdown by now + } // InputHandler does not need to be deleted (there's none in the App anymore) @@ -355,9 +370,6 @@ void ScModule::Execute( SfxRequest& rReq ) case SID_CHOOSE_DESIGN: SfxApplication::CallAppBasic( u"Template.Samples.ShowStyles"_ustr ); break; - case SID_EURO_CONVERTER: - SfxApplication::CallAppBasic( u"Euro.ConvertRun.Main"_ustr ); - break; case SID_AUTOSPELL_CHECK: { bool bSet; @@ -375,7 +387,7 @@ void ScModule::Execute( SfxRequest& rReq ) bSet = !ScModule::GetAutoSpellProperty(); } - SfxItemSetFixed aSet( GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aSet.Put( SfxBoolItem( SID_AUTOSPELL_CHECK, bSet ) ); ModifyOptions( aSet ); rReq.Done(); diff --git a/sc/source/ui/app/uiitems.cxx b/sc/source/ui/app/uiitems.cxx index a547ae9b5b45..e2042e669c1c 100644 --- a/sc/source/ui/app/uiitems.cxx +++ b/sc/source/ui/app/uiitems.cxx @@ -38,7 +38,7 @@ ScInputStatusItem::ScInputStatusItem( aStartPos ( rStartPos ), aEndPos ( rEndPos ), aString (std::move( _aString )), - pEditData ( pData ? pData->Clone() : nullptr ) + pEditData ( pData ? std::make_unique(*pData) : nullptr ) { } @@ -48,7 +48,7 @@ ScInputStatusItem::ScInputStatusItem( const ScInputStatusItem& rItem ) : aStartPos ( rItem.aStartPos ), aEndPos ( rItem.aEndPos ), aString ( rItem.aString ), - pEditData ( rItem.pEditData ? rItem.pEditData->Clone() : nullptr ), + pEditData ( rItem.pEditData ? std::make_unique(*rItem.pEditData) : nullptr ), maMisspellRanges(rItem.maMisspellRanges) { } @@ -106,7 +106,7 @@ ScIndexHint::~ScIndexHint() } /** - * Create new EditView for Cursorposition + * Create new EditView for cursor position */ ScEditViewHint::ScEditViewHint( ScEditEngineDefaulter& rEngine, const ScAddress& rCurPos ) : SfxHint(SfxHintId::ScEditView), @@ -252,7 +252,7 @@ bool ScSubTotalItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /* nMemberUd */ } /** - * Transporter for the UserLIst dialog + * Transporter for the UserList dialog */ ScUserListItem::ScUserListItem( sal_uInt16 nWhichP ) : SfxPoolItem ( nWhichP ) diff --git a/sc/source/ui/attrdlg/attrdlg.cxx b/sc/source/ui/attrdlg/attrdlg.cxx index 41f9f72a77b4..0dd462e53677 100644 --- a/sc/source/ui/attrdlg/attrdlg.cxx +++ b/sc/source/ui/attrdlg/attrdlg.cxx @@ -40,34 +40,35 @@ ScAttrDlg::ScAttrDlg(weld::Window* pParent, const SfxItemSet* pCellAttrs) { SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); - OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_NUMBERFORMAT), "GetTabPageCreatorFunc fail!"); + assert(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_NUMBERFORMAT) && "GetTabPageCreatorFunc fail!"); AddTabPage(u"numbers"_ustr, TabResId(RID_TAB_NUMBERS.aLabel), pFact->GetTabPageCreatorFunc(RID_SVXPAGE_NUMBERFORMAT), RID_M + RID_TAB_NUMBERS.sIconName); - OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_CHAR_NAME), "GetTabPageCreatorFunc fail!"); + assert(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_CHAR_NAME) && "GetTabPageCreatorFunc fail!"); AddTabPage(u"font"_ustr, TabResId(RID_TAB_FONT.aLabel), pFact->GetTabPageCreatorFunc(RID_SVXPAGE_CHAR_NAME), RID_M + RID_TAB_FONT.sIconName); - OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_CHAR_EFFECTS), "GetTabPageCreatorFunc fail!"); + assert(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_CHAR_EFFECTS) && "GetTabPageCreatorFunc fail!"); AddTabPage(u"fonteffects"_ustr, TabResId(RID_TAB_FONTEFFECTS.aLabel), pFact->GetTabPageCreatorFunc(RID_SVXPAGE_CHAR_EFFECTS), RID_M + RID_TAB_FONTEFFECTS.sIconName); - OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_ALIGNMENT), "GetTabPageCreatorFunc fail!"); + assert(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_ALIGNMENT) && "GetTabPageCreatorFunc fail!"); AddTabPage(u"alignment"_ustr, TabResId(RID_TAB_ALIGNMENT.aLabel), pFact->GetTabPageCreatorFunc(RID_SVXPAGE_ALIGNMENT), RID_M + RID_TAB_ALIGNMENT.sIconName); if (SvtCJKOptions::IsAsianTypographyEnabled()) { - OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_PARA_ASIAN), "GetTabPageCreatorFunc fail!"); + assert(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_PARA_ASIAN) + && "GetTabPageCreatorFunc fail!"); AddTabPage(u"asiantypography"_ustr, TabResId(RID_TAB_ASIANTYPO.aLabel), pFact->GetTabPageCreatorFunc(RID_SVXPAGE_PARA_ASIAN), RID_M + RID_TAB_ASIANTYPO.sIconName); } - OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BORDER), "GetTabPageCreatorFunc fail!"); + assert(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BORDER) && "GetTabPageCreatorFunc fail!"); AddTabPage(u"borders"_ustr, TabResId(RID_TAB_BORDER.aLabel), pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BORDER), RID_M + RID_TAB_BORDER.sIconName); - OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BKG), "GetTabPageCreatorFunc fail!"); + assert(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BKG) && "GetTabPageCreatorFunc fail!"); AddTabPage(u"background"_ustr, TabResId(RID_TAB_BACKGROUND.aLabel), pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BKG), RID_M + RID_TAB_BACKGROUND.sIconName); AddTabPage(u"cellprotection"_ustr, TabResId(RID_TAB_PROTECTION.aLabel), diff --git a/sc/source/ui/attrdlg/scdlgfact.cxx b/sc/source/ui/attrdlg/scdlgfact.cxx index e5e9ba6aca25..70deffec5e9f 100644 --- a/sc/source/ui/attrdlg/scdlgfact.cxx +++ b/sc/source/ui/attrdlg/scdlgfact.cxx @@ -783,10 +783,9 @@ public: VclPtr ScAbstractDialogFactory_Impl::CreateScTabBgColorDlg( weld::Window* pParent, const OUString& rTitle, - const OUString& rTabBgColorNoColorText, const Color& rDefaultColor) { - return VclPtr::Create(pParent, rTitle, rTabBgColorNoColorText, rDefaultColor); + return VclPtr::Create(pParent, rTitle, rDefaultColor); } namespace diff --git a/sc/source/ui/attrdlg/scdlgfact.hxx b/sc/source/ui/attrdlg/scdlgfact.hxx index 42fc374ca852..4c1c64f0020d 100644 --- a/sc/source/ui/attrdlg/scdlgfact.hxx +++ b/sc/source/ui/attrdlg/scdlgfact.hxx @@ -145,7 +145,6 @@ public: virtual VclPtr CreateScTabBgColorDlg(weld::Window* pParent, const OUString& rTitle, //Dialog Title - const OUString& rTabBgColorNoColorText, //Label for no tab color const Color& rDefaultColor) override; //Currently selected Color virtual VclPtr CreateScImportOptionsDlg(weld::Window* pParent, bool bAscii, diff --git a/sc/source/ui/cctrl/SheetViewBox.cxx b/sc/source/ui/cctrl/SheetViewBox.cxx index f6b3da019b49..6d4d71e4aaa1 100644 --- a/sc/source/ui/cctrl/SheetViewBox.cxx +++ b/sc/source/ui/cctrl/SheetViewBox.cxx @@ -28,7 +28,7 @@ SheetViewBox::SheetViewBox(vcl::Window* pParent) : InterimItemWindow(pParent, u"modules/scalc/ui/sheetviewbox.ui"_ustr, u"SheetViewBox"_ustr, - true, reinterpret_cast(SfxViewShell::Current())) + true) , m_xWidget(m_xBuilder->weld_combo_box(u"sheetview_combobox"_ustr)) { m_xWidget->connect_changed(LINK(this, SheetViewBox, SelectHdl)); @@ -51,33 +51,24 @@ void SheetViewBox::GetFocus() InterimItemWindow::GetFocus(); } -void SheetViewBox::Update(sc::SheetViewID nSelectedID) +void SheetViewBox::Update(ScViewData& rViewData) { - ScViewData* pViewData = ScDocShell::GetViewData(); - if (!pViewData) - return; - m_xWidget->clear(); m_xWidget->freeze(); OUString sActiveID = OUString::number(sc::DefaultSheetViewID); m_xWidget->append(sActiveID, sc::SheetViewManager::defaultViewName()); - auto pSheetManager = pViewData->GetCurrentSheetViewManager(); + auto pSheetManager = rViewData.GetCurrentSheetViewManager(); if (pSheetManager) { - sc::SheetViewID nSheetViewID = 0; - for (auto const& pSheetView : pSheetManager->getSheetViews()) + for (auto const& rSheetView : pSheetManager->iterateValidSheetViews()) { - if (pSheetView) - { - OUString sID = OUString::number(nSheetViewID); - if (nSheetViewID == nSelectedID) - sActiveID = sID; - m_xWidget->append(sID, pSheetView->GetName()); - } - nSheetViewID++; + OUString sID = OUString::number(rSheetView.getID()); + if (rSheetView.getID() == rViewData.GetSheetViewID()) + sActiveID = sID; + m_xWidget->append(sID, rSheetView.GetName()); } } m_xWidget->thaw(); @@ -96,8 +87,8 @@ IMPL_STATIC_LINK(SheetViewBox, SelectHdl, weld::ComboBox&, rComboBox, void) return; const OUString sValue = rComboBox.get_active_id(); - SfxInt32Item aItem(FID_CURRENT_SHEET_VIEW, sValue.toInt32()); - pDispatcher->ExecuteList(FID_CURRENT_SHEET_VIEW, SfxCallMode::RECORD, { &aItem }); + SfxInt32Item aItem(FN_PARAM_1, sValue.toInt32()); + pDispatcher->ExecuteList(FID_SELECT_SHEET_VIEW, SfxCallMode::RECORD, { &aItem }); pViewFrame->GetWindow().GrabFocus(); } diff --git a/sc/source/ui/cctrl/SheetViewControl.cxx b/sc/source/ui/cctrl/SheetViewControl.cxx index cd0a8e5e92a8..ca367dd5ee8c 100644 --- a/sc/source/ui/cctrl/SheetViewControl.cxx +++ b/sc/source/ui/cctrl/SheetViewControl.cxx @@ -9,12 +9,15 @@ #include #include +#include #include #include +#include +#include using namespace sc; -SFX_IMPL_TOOLBOX_CONTROL(SheetViewControl, SfxInt32Item); +SFX_IMPL_TOOLBOX_CONTROL(SheetViewControl, SfxVoidItem); SheetViewControl::SheetViewControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx) : SfxToolBoxControl(nSlotId, nId, rTbx) @@ -23,13 +26,21 @@ SheetViewControl::SheetViewControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBo SheetViewControl::~SheetViewControl() {} -void SheetViewControl::StateChangedAtToolBoxControl(sal_uInt16, SfxItemState eState, +void SheetViewControl::StateChangedAtToolBoxControl(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState) { ToolBoxItemId nId = GetId(); ToolBox& rToolBox = GetToolBox(); SheetViewBox* pSheetViewBox = static_cast(rToolBox.GetItemWindow(nId)); + css::uno::Reference xFrame = getFrameInterface(); + SfxViewShell* pShell = SfxViewShell::Get(xFrame->getController()); + ScTabViewShell* pTabViewShell = dynamic_cast(pShell); + if (!pTabViewShell) + return; + + ScViewData& rViewData = pTabViewShell->GetViewData(); + if (SfxItemState::DISABLED == eState) pSheetViewBox->Disable(); else @@ -37,19 +48,9 @@ void SheetViewControl::StateChangedAtToolBoxControl(sal_uInt16, SfxItemState eSt rToolBox.EnableItem(nId, SfxItemState::DISABLED != eState); - switch (eState) - { - case SfxItemState::DEFAULT: - { - const auto* pItem = static_cast(pState); - sc::SheetViewID nValue = pItem->GetValue(); - pSheetViewBox->Update(nValue); - break; - } + pSheetViewBox->Update(rViewData); - default: - break; - } + SfxToolBoxControl::StateChangedAtToolBoxControl(nSID, eState, pState); } VclPtr SheetViewControl::CreateItemWindow(vcl::Window* pParent) diff --git a/sc/source/ui/cctrl/TableStylesBox.cxx b/sc/source/ui/cctrl/TableStylesBox.cxx index 78d69f8c457a..48cef4bd47c9 100644 --- a/sc/source/ui/cctrl/TableStylesBox.cxx +++ b/sc/source/ui/cctrl/TableStylesBox.cxx @@ -24,7 +24,7 @@ TableStylesBox::TableStylesBox(vcl::Window* pParent) : InterimItemWindow(pParent, u"modules/scalc/ui/tablestylesbox.ui"_ustr, u"TableStylesBox"_ustr, - true, reinterpret_cast(SfxViewShell::Current())) + true) , m_xChkHeaderRow(m_xBuilder->weld_check_button(u"chk_header_row2"_ustr)) , m_xChkTotalRow(m_xBuilder->weld_check_button(u"chk_total_row2"_ustr)) , m_xChkFilterButtons(m_xBuilder->weld_check_button(u"chk_filter_buttons2"_ustr)) @@ -44,7 +44,7 @@ TableStylesBox::TableStylesBox(vcl::Window* pParent) m_xCmbStyle->connect_changed(LINK(this, TableStylesBox, SelectHdl)); m_xCmbStyle->connect_key_press(LINK(this, TableStylesBox, KeyInputHdl)); - // to have enough space for the entries since we have two row of entries + // to have enough space for the entries since we have two rows of entries SetSizePixel(pParent->get_preferred_size() * 2); // TODO: no Table tab page for core } diff --git a/sc/source/ui/cctrl/cbnumberformat.cxx b/sc/source/ui/cctrl/cbnumberformat.cxx index ff64c2fd71e6..b9302f6bcfd0 100644 --- a/sc/source/ui/cctrl/cbnumberformat.cxx +++ b/sc/source/ui/cctrl/cbnumberformat.cxx @@ -29,8 +29,7 @@ #include ScNumberFormat::ScNumberFormat(vcl::Window* pParent) - : InterimItemWindow(pParent, u"modules/scalc/ui/numberbox.ui"_ustr, u"NumberBox"_ustr, true, - reinterpret_cast(SfxViewShell::Current())) + : InterimItemWindow(pParent, u"modules/scalc/ui/numberbox.ui"_ustr, u"NumberBox"_ustr, true) , m_xWidget(m_xBuilder->weld_combo_box(u"numbertype"_ustr)) { m_xWidget->append_text(ScResId(STR_GENERAL)); diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index 743676490c94..fda2a01505d3 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -18,6 +18,9 @@ */ #include + +#include + #include #include #include @@ -31,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -633,8 +637,8 @@ ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScViewData // popup isn't a true dialog mxButtonBox->sort_native_button_order(); - mxTreeChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); - mxListChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); + mxTreeChecks->enable_toggle_buttons(); + mxListChecks->enable_toggle_buttons(); mxBox->show(); if (mbIsMultiField) @@ -860,7 +864,7 @@ namespace /* * in case marked members are to be included, we include * them at the end because we can see in the functions which call - * this function that the marked members will be disabled anyways + * this function that the marked members will be disabled anyway * if lock is checked. */ if (!bIncludeMarkedMembers || (!rMembers[i].mbMarked && !rMembers[i].mbHiddenByOtherFilter)) @@ -922,30 +926,29 @@ void ScCheckListMenuControl::MarkCheckedMembers() } else { + // tdf#168193 - look up the row label instead of scanning all members + std::unordered_map aNameToMember; + aNameToMember.reserve(maMembers.size()); + for (size_t i = 0; i < maMembers.size(); ++i) + // duplicate names keep their first member since they all show up as a single entry + aNameToMember.emplace(maMembers[i].maName, i); + // go over the members visible in the popup, and remember which one is // checked, and which one is not by setting `mbMarked` to `true`; by default // `mbMarked` is `false`, we clear all the marks when lock is unchecked, see // at the end of this callback. - mpChecks->all_foreach([this](weld::TreeIter& rEntry){ - if (mpChecks->get_toggle(rEntry) == TRISTATE_TRUE) + mpChecks->all_foreach( + [this, &aNameToMember](weld::TreeIter& rEntry) { - for (auto& aMember : maMembers) + if (mpChecks->get_toggle(rEntry) == TRISTATE_TRUE) { - if (aMember.maName == mpChecks->get_text(rEntry)) - { - aMember.mbMarked = true; - /* - * if there are multiple entries with the same - * name in the range, they all show up as a single - * entry in the autofilter, so we can break - */ - break; - } + const auto aItr = aNameToMember.find(mpChecks->get_text(rEntry)); + if (aItr != aNameToMember.end()) + maMembers[aItr->second].mbMarked = true; } - } - return false; - }); + return false; + }); } } @@ -1010,7 +1013,7 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, ComboChangedHdl, weld::ComboBox&, void) mxFieldChangedAction->execute(); } -IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::Entry&, void) +IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::TextWidget&, void) { maSearchEditTimer.Start(); } @@ -1853,11 +1856,13 @@ ScListSubMenuControl::ScListSubMenuControl(weld::Widget* pParent, ScCheckListMen else { mxBackColorMenu->set_clicks_to_toggle(1); - mxBackColorMenu->enable_toggle_buttons(weld::ColumnToggleType::Radio); + mxBackColorMenu->enable_toggle_buttons(); + mxBackColorMenu->set_toggle_button_type(weld::ColumnToggleType::Radio); mxBackColorMenu->connect_selection_changed( LINK(this, ScListSubMenuControl, ColorSelChangedHdl)); mxTextColorMenu->set_clicks_to_toggle(1); - mxTextColorMenu->enable_toggle_buttons(weld::ColumnToggleType::Radio); + mxTextColorMenu->enable_toggle_buttons(); + mxTextColorMenu->set_toggle_button_type(weld::ColumnToggleType::Radio); mxTextColorMenu->connect_selection_changed( LINK(this, ScListSubMenuControl, ColorSelChangedHdl)); SetupMenu(*mxBackColorMenu); diff --git a/sc/source/ui/condformat/colorformat.cxx b/sc/source/ui/condformat/colorformat.cxx index 6768bd587b0d..bfa5e6479ea3 100644 --- a/sc/source/ui/condformat/colorformat.cxx +++ b/sc/source/ui/condformat/colorformat.cxx @@ -18,7 +18,6 @@ #include #include #include -#include namespace { diff --git a/sc/source/ui/condformat/condformatdlg.cxx b/sc/source/ui/condformat/condformatdlg.cxx index 81936bc8384e..d84153fe4138 100644 --- a/sc/source/ui/condformat/condformatdlg.cxx +++ b/sc/source/ui/condformat/condformatdlg.cxx @@ -420,17 +420,11 @@ IMPL_LINK( ScCondFormatList, EntrySelectHdl, ScCondFrmtEntry&, rEntry, void ) RecalcAll(); } -static bool isLOKMobilePhone() -{ - SfxViewShell* pCurrent = SfxViewShell::Current(); - return pCurrent && pCurrent->isLOKMobilePhone(); -} - ScCondFormatDlg::ScCondFormatDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, ScViewData& rViewData, const std::shared_ptr& rItem) : ScAnyRefDlgController(pB, pCW, pParent, - isLOKMobilePhone()?u"modules/scalc/ui/conditionalformatdialogmobile.ui"_ustr:u"modules/scalc/ui/conditionalformatdialog.ui"_ustr, + u"modules/scalc/ui/conditionalformatdialog.ui"_ustr, u"ConditionalFormatDialog"_ustr) , mrViewData(rViewData) // previous version based on SfxPoolItem used SfxPoolItem::Clone here, so make a copy diff --git a/sc/source/ui/condformat/condformatdlgentry.cxx b/sc/source/ui/condformat/condformatdlgentry.cxx index 4f4e39cc633c..904d1455ddbd 100644 --- a/sc/source/ui/condformat/condformatdlgentry.cxx +++ b/sc/source/ui/condformat/condformatdlgentry.cxx @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -44,15 +46,9 @@ // force them to take a 1/3 of the available space #define CommonWidgetWidth 10 -static bool isLOKMobilePhone() -{ - SfxViewShell* pCurrent = SfxViewShell::Current(); - return pCurrent && pCurrent->isLOKMobilePhone(); -} - ScCondFrmtEntry::ScCondFrmtEntry(ScCondFormatList* pParent, ScDocument& rDoc, const ScAddress& rPos) : mpParent(pParent) - , mxBuilder(Application::CreateBuilder(pParent->GetGrid(), isLOKMobilePhone()?u"modules/scalc/ui/conditionalentrymobile.ui"_ustr:u"modules/scalc/ui/conditionalentry.ui"_ustr)) + , mxBuilder(Application::CreateBuilder(pParent->GetGrid(), u"modules/scalc/ui/conditionalentry.ui"_ustr)) , mxBorder(mxBuilder->weld_widget(u"border"_ustr)) , mxGrid(mxBuilder->weld_container(u"grid"_ustr)) , mxFtCondNr(mxBuilder->weld_label(u"number"_ustr)) diff --git a/sc/source/ui/condformat/condformateasydlg.cxx b/sc/source/ui/condformat/condformateasydlg.cxx index 547dc8c5ed90..ad541ec8eedc 100644 --- a/sc/source/ui/condformat/condformateasydlg.cxx +++ b/sc/source/ui/condformat/condformateasydlg.cxx @@ -47,7 +47,7 @@ namespace sc { void ConditionalFormatEasyDialog::SetDescription(std::u16string_view rCondition) { - mxDescription->set_label(mxDescription->get_label().replaceAll("%1", rCondition)); + mxConditionFrame->set_label(mxConditionFrame->get_label().replaceAll("%1", rCondition)); } ConditionalFormatEasyDialog::ConditionalFormatEasyDialog(SfxBindings* pBindings, @@ -65,7 +65,7 @@ ConditionalFormatEasyDialog::ConditionalFormatEasyDialog(SfxBindings* pBindings, , mxRangeEntry(new formula::RefEdit(m_xBuilder->weld_entry(u"entryRange"_ustr))) , mxButtonRangeEdit(new formula::RefButton(m_xBuilder->weld_button(u"rbassign"_ustr))) , mxStyles(m_xBuilder->weld_combo_box(u"themeCombo"_ustr)) - , mxDescription(m_xBuilder->weld_label(u"description"_ustr)) + , mxConditionFrame(m_xBuilder->weld_frame(u"condition"_ustr)) , mxButtonOk(m_xBuilder->weld_button(u"ok"_ustr)) , mxButtonCancel(m_xBuilder->weld_button(u"cancel"_ustr)) { diff --git a/sc/source/ui/condformat/condformathelper.cxx b/sc/source/ui/condformat/condformathelper.cxx index 2bee433a7295..6acb98c532f0 100644 --- a/sc/source/ui/condformat/condformathelper.cxx +++ b/sc/source/ui/condformat/condformathelper.cxx @@ -192,7 +192,7 @@ OUString ScCondFormatHelper::GetExpression( ScCondFormatEntryType eType, sal_Int OUStringBuffer aBuffer(getTextForType(eType) + " "); if(eType == CONDITION) { - // workaround missing FORMULA option in the conditions case + // work around missing FORMULA option in the conditions case // FORMULA is handled later if(nIndex > 9) ++nIndex; diff --git a/sc/source/ui/condformat/condformatmgr.cxx b/sc/source/ui/condformat/condformatmgr.cxx index 9945d1b0ab76..2fd2f98f4584 100644 --- a/sc/source/ui/condformat/condformatmgr.cxx +++ b/sc/source/ui/condformat/condformatmgr.cxx @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sc/source/ui/dataprovider/csvdataprovider.cxx b/sc/source/ui/dataprovider/csvdataprovider.cxx index 9cac06a48f2a..a2b4e06f2c7a 100644 --- a/sc/source/ui/dataprovider/csvdataprovider.cxx +++ b/sc/source/ui/dataprovider/csvdataprovider.cxx @@ -83,21 +83,11 @@ CSVFetchThread::~CSVFetchThread() { } -bool CSVFetchThread::IsRequestedTerminate() -{ - return mbTerminate.load(); -} - void CSVFetchThread::RequestTerminate() { mbTerminate.store(true); } -void CSVFetchThread::EndThread() -{ - RequestTerminate(); -} - void CSVFetchThread::execute() { OStringBuffer aBuffer(64000); diff --git a/sc/source/ui/dataprovider/dataprovider.cxx b/sc/source/ui/dataprovider/dataprovider.cxx index 1a31a1afddaf..bea50ee0f817 100644 --- a/sc/source/ui/dataprovider/dataprovider.cxx +++ b/sc/source/ui/dataprovider/dataprovider.cxx @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "htmldataprovider.hxx" #include "xmldataprovider.hxx" @@ -24,6 +26,10 @@ #include #include #include +#include +#include +#include +#include #include using namespace com::sun::star; @@ -32,6 +38,19 @@ namespace sc { std::unique_ptr DataProvider::FetchStreamFromURL(const OUString& rURL, OStringBuffer& rBuffer) { + INetURLObject aURLObject(rURL); + if (aURLObject.IsExoticProtocol()) + { + SAL_WARN("sc.ui", "DataProvider::FetchStreamFromURL: blocked exotic protocol: \"" << rURL << "\""); + return nullptr; + } + + if (HostFilter::isForbidden(aURLObject.GetHost())) + { + SAL_WARN("sc.ui", "DataProvider::FetchStreamFromURL: blocked host: \"" << rURL << "\""); + return nullptr; + } + try { uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess = ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ); @@ -179,8 +198,46 @@ const std::vector>& ExternalDataSource:: return maDataTransformations; } -ExternalDataMapper::ExternalDataMapper(ScDocument& /*rDoc*/) - //mrDoc(rDoc) +namespace { + +// A data mapping fetches external data (CSV, HTML, XML) into a sheet. It is +// registered in the LinkManager so it passes through the same link update +// control as sheet links, area links, and external references. The link holds +// the index of its data source in the mapper. That index is stable because +// data sources are only ever appended, never removed. +class ScDataProviderLink final : public sfx2::SvBaseLink +{ + ScDocShell& mrDocShell; + size_t mnSourceIndex; + +public: + ScDataProviderLink(ScDocShell& rDocShell, size_t nSourceIndex) + : sfx2::SvBaseLink(SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SIMPLE_FILE) + , mrDocShell(rDocShell) + , mnSourceIndex(nSourceIndex) + { + } + + virtual sfx2::SvBaseLink::UpdateResult DataChanged(const OUString&, + const css::uno::Any&) override + { + if (!mrDocShell.GetEmbeddedObjectContainer().getUserAllowsLinkUpdate()) + return SUCCESS; + + ScDocument& rDoc = mrDocShell.GetDocument(); + std::vector& rSources + = rDoc.GetExternalDataMapper().getDataSources(); + if (mnSourceIndex < rSources.size()) + rSources[mnSourceIndex].refresh(&rDoc, true); + + return SUCCESS; + } +}; + +} + +ExternalDataMapper::ExternalDataMapper(ScDocument& rDoc) + : mrDoc(rDoc) { } @@ -191,6 +248,19 @@ ExternalDataMapper::~ExternalDataMapper() void ExternalDataMapper::insertDataSource(const sc::ExternalDataSource& rSource) { maDataSources.push_back(rSource); + + ScDocShell* pDocShell = mrDoc.GetDocumentShell(); + if (!pDocShell) + return; + + sfx2::LinkManager* pLinkManager = mrDoc.GetLinkManager(); + if (!pLinkManager) + return; + + ScDataProviderLink* pLink = new ScDataProviderLink(*pDocShell, maDataSources.size() - 1); + const OUString& rProvider = rSource.getProvider(); + pLinkManager->InsertFileLink(*pLink, sfx2::SvBaseLinkObjectType::ClientFile, + rSource.getURL(), &rProvider, nullptr); } const std::vector& ExternalDataMapper::getDataSources() const diff --git a/sc/source/ui/dataprovider/datatransformation.cxx b/sc/source/ui/dataprovider/datatransformation.cxx index decb4a7c9a9a..b2ddf191f8b6 100644 --- a/sc/source/ui/dataprovider/datatransformation.cxx +++ b/sc/source/ui/dataprovider/datatransformation.cxx @@ -1167,21 +1167,6 @@ TransformationType FindReplaceTransformation::getTransformationType() const return TransformationType::FINDREPLACE_TRANSFORMATION; } -SCCOL FindReplaceTransformation::getColumn() const -{ - return mnCol; -} - -const OUString& FindReplaceTransformation::getFindString() const -{ - return maFindString; -} - -const OUString& FindReplaceTransformation::getReplaceString() const -{ - return maReplaceString; -} - DeleteRowTransformation::DeleteRowTransformation(SCCOL nCol, OUString aFindString) : mnCol(nCol) , maFindString(std::move(aFindString)) @@ -1215,16 +1200,6 @@ TransformationType DeleteRowTransformation::getTransformationType() const return TransformationType::DELETEROW_TRANSFORMATION; } -SCCOL DeleteRowTransformation::getColumn() const -{ - return mnCol; -} - -const OUString& DeleteRowTransformation::getFindString() const -{ - return maFindString; -} - SwapRowsTransformation::SwapRowsTransformation(SCROW mRow, SCROW nRow) : mxRow(mRow) , nxRow(nRow) @@ -1261,16 +1236,6 @@ TransformationType SwapRowsTransformation::getTransformationType() const return TransformationType::SWAPROWS_TRANSFORMATION; } -SCROW SwapRowsTransformation::getFirstRow() const -{ - return mxRow; -} - -SCROW SwapRowsTransformation::getSecondRow() const -{ - return nxRow; -} - } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/dataprovider/htmldataprovider.hxx b/sc/source/ui/dataprovider/htmldataprovider.hxx index f978ebdd1519..cc54e045761e 100644 --- a/sc/source/ui/dataprovider/htmldataprovider.hxx +++ b/sc/source/ui/dataprovider/htmldataprovider.hxx @@ -29,7 +29,7 @@ public: virtual void Import() override; - virtual const OUString& GetURL() const override; + virtual const OUString& GetURL() const; void ImportFinished(); }; diff --git a/sc/source/ui/dataprovider/sqldataprovider.cxx b/sc/source/ui/dataprovider/sqldataprovider.cxx index e4610c6dcea1..ac61a8dc53f0 100644 --- a/sc/source/ui/dataprovider/sqldataprovider.cxx +++ b/sc/source/ui/dataprovider/sqldataprovider.cxx @@ -9,6 +9,8 @@ #include "sqldataprovider.hxx" #include +#include +#include #include #include #include @@ -16,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -63,6 +67,13 @@ void SQLFetchThread::execute() OUString aTable = maID.copy(0, nIndex); OUString aDatabase = maID.copy(nIndex + 1); + if (INetURLObject(aDatabase).IsExoticProtocol()) + { + SAL_WARN("sc.ui", + "SQLFetchThread::execute: blocked exotic protocol: \"" << aDatabase << "\""); + return; + } + try { uno::Reference xContext @@ -80,10 +91,13 @@ void SQLFetchThread::execute() uno::Reference xConnection = xSource->connectWithCompletion(xHandler); + const OUString aQuote = xConnection->getMetaData()->getIdentifierQuoteString(); + const OUString aQuotedTable = ::dbtools::quoteName(aQuote, aTable); + uno::Reference xStatement = xConnection->createStatement(); uno::Reference xResult - = xStatement->executeQuery("SELECT * FROM " + aTable); + = xStatement->executeQuery("SELECT * FROM " + aQuotedTable); if (xResult.is()) { diff --git a/sc/source/ui/dataprovider/sqldataprovider.hxx b/sc/source/ui/dataprovider/sqldataprovider.hxx index fbbca7601269..3e9a9e13fe35 100644 --- a/sc/source/ui/dataprovider/sqldataprovider.hxx +++ b/sc/source/ui/dataprovider/sqldataprovider.hxx @@ -29,7 +29,7 @@ public: virtual void Import() override; - virtual const OUString& GetURL() const override; + virtual const OUString& GetURL() const; void ImportFinished(); }; diff --git a/sc/source/ui/dataprovider/xmldataprovider.hxx b/sc/source/ui/dataprovider/xmldataprovider.hxx index 7be3f95c3769..807a9bb5542a 100644 --- a/sc/source/ui/dataprovider/xmldataprovider.hxx +++ b/sc/source/ui/dataprovider/xmldataprovider.hxx @@ -28,7 +28,7 @@ public: virtual void Import() override; - virtual const OUString& GetURL() const override; + virtual const OUString& GetURL() const; void ImportFinished(); }; diff --git a/sc/source/ui/dbgui/PivotCalcFieldDialog.cxx b/sc/source/ui/dbgui/PivotCalcFieldDialog.cxx index 5f43d92d4d82..fbe13ab1a47f 100644 --- a/sc/source/ui/dbgui/PivotCalcFieldDialog.cxx +++ b/sc/source/ui/dbgui/PivotCalcFieldDialog.cxx @@ -59,17 +59,6 @@ ScPivotCalcFieldDlg::ScPivotCalcFieldDlg(weld::Window* pParent, ScViewData& rDat , mxBtnInsert(m_xBuilder->weld_button(u"insertbtn"_ustr)) , mxBtnOK(m_xBuilder->weld_button(u"ok"_ustr)) , mxBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr)) -{ - Init(); -} - -ScPivotCalcFieldDlg::~ScPivotCalcFieldDlg() -{ - if (m_xInfoBox) - m_xInfoBox->response(RET_OK); -} - -void ScPivotCalcFieldDlg::Init() { // Buttons mxBtnCancel->connect_clicked(LINK(this, ScPivotCalcFieldDlg, CancelClicked)); @@ -94,6 +83,12 @@ void ScPivotCalcFieldDlg::Init() aStrModify = mxBtnMod->get_label(); } +ScPivotCalcFieldDlg::~ScPivotCalcFieldDlg() +{ + if (m_xInfoBox) + m_xInfoBox->response(RET_OK); +} + void ScPivotCalcFieldDlg::ErrorBox(const OUString& rString) { if (m_xInfoBox) @@ -593,7 +588,7 @@ IMPL_LINK_NOARG(ScPivotCalcFieldDlg, CalcFieldNameSelected, weld::ComboBox&, voi } } -IMPL_LINK_NOARG(ScPivotCalcFieldDlg, CalcEntryChanged, weld::TextView&, void) +IMPL_LINK_NOARG(ScPivotCalcFieldDlg, CalcEntryChanged, weld::TextWidget&, void) { OUString aName = mxCalcNames->get_active_text(); OUString aCalc = mxCalculation->get_text().trim(); diff --git a/sc/source/ui/dbgui/PivotLayoutDialog.cxx b/sc/source/ui/dbgui/PivotLayoutDialog.cxx index 14c882dad18e..0172f515d1ca 100644 --- a/sc/source/ui/dbgui/PivotLayoutDialog.cxx +++ b/sc/source/ui/dbgui/PivotLayoutDialog.cxx @@ -28,6 +28,7 @@ #include #include #include +#include using namespace css::uno; using namespace css::sheet; @@ -53,11 +54,9 @@ namespace ScRange lclGetRangeForNamedRange(OUString const & aName, const ScDocument& rDocument) { ScRange aInvalidRange(ScAddress::INITIALIZE_INVALID); - ScRangeName* pRangeName = rDocument.GetRangeName(); - if (pRangeName == nullptr) - return aInvalidRange; + ScRangeName& rRangeName = rDocument.GetRangeName(); - const ScRangeData* pData = pRangeName->findByUpperName(aName.toAsciiUpperCase()); + const ScRangeData* pData = rRangeName.findByUpperName(aName.toAsciiUpperCase()); if (pData == nullptr) return aInvalidRange; diff --git a/sc/source/ui/dbgui/PivotLayoutTreeList.cxx b/sc/source/ui/dbgui/PivotLayoutTreeList.cxx index fb8a3cc4fef2..1b1df1c3a9d6 100644 --- a/sc/source/ui/dbgui/PivotLayoutTreeList.cxx +++ b/sc/source/ui/dbgui/PivotLayoutTreeList.cxx @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/sc/source/ui/dbgui/PivotLayoutTreeListBase.cxx b/sc/source/ui/dbgui/PivotLayoutTreeListBase.cxx index f25b06a56d81..a9cf83ac2f94 100644 --- a/sc/source/ui/dbgui/PivotLayoutTreeListBase.cxx +++ b/sc/source/ui/dbgui/PivotLayoutTreeListBase.cxx @@ -12,6 +12,8 @@ #include #include +#include + ScPivotLayoutTreeListBase::ScPivotLayoutTreeListBase(std::unique_ptr xControl, SvPivotTreeListType eType) : mxControl(std::move(xControl)) , maDropTargetHelper(*this) diff --git a/sc/source/ui/dbgui/PivotLayoutTreeListData.cxx b/sc/source/ui/dbgui/PivotLayoutTreeListData.cxx index e085f9ade438..88057d488837 100644 --- a/sc/source/ui/dbgui/PivotLayoutTreeListData.cxx +++ b/sc/source/ui/dbgui/PivotLayoutTreeListData.cxx @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -90,7 +91,8 @@ IMPL_LINK(ScPivotLayoutTreeListData, DoubleClickHdl, const weld::TreeIter&, rIte mpFunctionDlg = pFactory->CreateScDPFunctionDlg(mxControl.get(), mpParent->GetLabelDataVector(), rCurrentLabelData, rCurrentFunctionData); - mpFunctionDlg->StartExecuteAsync([this, pCurrentItemValue, &rIter](int nResult) mutable { + std::shared_ptr pIter = mxControl->make_iterator(&rIter); + mpFunctionDlg->StartExecuteAsync([this, pCurrentItemValue, pIter](int nResult) mutable { if (nResult == RET_OK) { ScPivotFuncData& rFunctionData = pCurrentItemValue->maFunctionData; @@ -105,7 +107,7 @@ IMPL_LINK(ScPivotLayoutTreeListData, DoubleClickHdl, const weld::TreeIter&, rIte rLabelData.maName, rFunctionData.mnDupCount); - mxControl->set_text(rIter, sDataItemName); + mxControl->set_text(*pIter, sDataItemName); } mpFunctionDlg->disposeOnce(); diff --git a/sc/source/ui/dbgui/PivotLayoutTreeListLabel.cxx b/sc/source/ui/dbgui/PivotLayoutTreeListLabel.cxx index e4a2276dacee..b2ade1f5d2a8 100644 --- a/sc/source/ui/dbgui/PivotLayoutTreeListLabel.cxx +++ b/sc/source/ui/dbgui/PivotLayoutTreeListLabel.cxx @@ -13,9 +13,11 @@ #include #include -#include #include +#include +#include + ScPivotLayoutTreeListLabel::ScPivotLayoutTreeListLabel(std::unique_ptr xControl) : ScPivotLayoutTreeListBase(std::move(xControl), LABEL_LIST) , maDataItem(0) diff --git a/sc/source/ui/dbgui/asciiopt.cxx b/sc/source/ui/dbgui/asciiopt.cxx index 39d40d4531a8..af2d640f7f05 100644 --- a/sc/source/ui/dbgui/asciiopt.cxx +++ b/sc/source/ui/dbgui/asciiopt.cxx @@ -42,10 +42,11 @@ ScAsciiOptions::ScAsciiOptions() : bSaveAsShown(true), bSaveFormulas(false), bIncludeBOM(false), + nEndianness(SvStreamEndian::LITTLE), cTextSep ( cDefaultTextSep ), - eCharSet ( osl_getThreadTextEncoding() ), + eEncoding ( osl_getThreadTextEncoding() ), eLang ( LANGUAGE_SYSTEM ), - bCharSetSystem ( false ), + bEncodingSystem ( false ), nStartRow ( 1 ) { } @@ -121,18 +122,18 @@ void ScAsciiOptions::ReadFromString( std::u16string_view rString, SvStream* pStr if ( nPos >= 0 ) { const std::u16string_view aToken = o3tl::getToken(rString, 0, ',', nPos); - bool bDetectCharSet = aToken == pStrDet; - if ( bDetectCharSet && pStream4Detect ) + bool bDetectEncoding = aToken == pStrDet; + if ( bDetectEncoding && pStream4Detect ) { pStream4Detect->DetectEncoding(); - eCharSet = pStream4Detect->GetStreamEncoding(); + eEncoding = pStream4Detect->GetStreamEncoding(); } - else if (!bDetectCharSet) - eCharSet = ScGlobal::GetCharsetValue( aToken ); + else if (!bDetectEncoding) + eEncoding = ScGlobal::GetEncodingValue( aToken ); } if (bDetectSep && pStream4Detect) - SfxObjectShell::DetectCsvSeparators(*pStream4Detect, eCharSet, aFieldSeps, cTextSep); + SfxObjectShell::DetectCsvSeparators(*pStream4Detect, eEncoding, aFieldSeps, cTextSep); // Token 3: Number of start row. if ( nPos >= 0 ) @@ -226,6 +227,11 @@ void ScAsciiOptions::ReadFromString( std::u16string_view rString, SvStream* pStr else bDetectScientificNumber = true; // default of versions that didn't add the parameter + // Token 15: determine endianness + if (nPos >= 0) + { + nEndianness = static_cast(o3tl::toInt32(o3tl::getToken(rString, 0, ',', nPos))); + } } OUString ScAsciiOptions::WriteToString() const @@ -256,10 +262,10 @@ OUString ScAsciiOptions::WriteToString() const aOutStr.append("," + OUString::number(cTextSep) + ","); //Token 2: Text encoding. - if ( bCharSetSystem ) // force "SYSTEM" - aOutStr.append(ScGlobal::GetCharsetString( RTL_TEXTENCODING_DONTKNOW )); + if ( bEncodingSystem ) // force "SYSTEM" + aOutStr.append(ScGlobal::GetEncodingString( RTL_TEXTENCODING_DONTKNOW )); else - aOutStr.append(ScGlobal::GetCharsetString( eCharSet )); + aOutStr.append(ScGlobal::GetEncodingString( eEncoding )); //Token 3: Number of start row. aOutStr.append("," + OUString::number(nStartRow) + ","); @@ -298,7 +304,9 @@ OUString ScAsciiOptions::WriteToString() const // Token 13: include BOM OUString::boolean(bIncludeBOM) + "," + // Token 14: Detect scientific numbers. - OUString::boolean( bDetectScientificNumber ) + OUString::boolean( bDetectScientificNumber ) + "," + + // Token 15: Determine endianness + OUString::number( static_cast(nEndianness) ) ); return aOutStr.makeStringAndClear(); } diff --git a/sc/source/ui/dbgui/consdlg.cxx b/sc/source/ui/dbgui/consdlg.cxx index 1c21f1dff732..32e0059bc24b 100644 --- a/sc/source/ui/dbgui/consdlg.cxx +++ b/sc/source/ui/dbgui/consdlg.cxx @@ -35,8 +35,8 @@ #include #include #include +#include #include -#include namespace { @@ -173,9 +173,9 @@ void ScConsolidateDlg::Init() // Use the ScAreaData helper class to save those range names from the // RangeNames and database ranges that appear in the ListBoxes. - ScRangeName* pRangeNames = rDoc.GetRangeName(); + ScRangeName& rRangeNames = rDoc.GetRangeName(); ScDBCollection* pDbNames = rDoc.GetDBCollection(); - size_t nRangeCount = pRangeNames ? pRangeNames->size() : 0; + size_t nRangeCount = rRangeNames.size(); size_t nDbCount = pDbNames ? pDbNames->getNamedDBs().size() : 0; nAreaDataCount = nRangeCount+nDbCount; @@ -228,7 +228,7 @@ void ScConsolidateDlg::FillAreaLists() } // Handover of a range within a table that has been selected by the mouse. -// This range is then shown in the reference window as new selection. +// This range is then shown in the reference window as the new selection. void ScConsolidateDlg::SetReference( const ScRange& rRef, ScDocument& rDocP ) { diff --git a/sc/source/ui/dbgui/csvgrid.cxx b/sc/source/ui/dbgui/csvgrid.cxx index 406fd3430ac9..8d7ba178f8f7 100644 --- a/sc/source/ui/dbgui/csvgrid.cxx +++ b/sc/source/ui/dbgui/csvgrid.cxx @@ -106,11 +106,11 @@ void ScCsvGrid::SetDrawingArea(weld::DrawingArea* pDrawingArea) weld::SetPointFont(rRefDevice, maHeaderFont); maHeaderFont = rRefDevice.GetFont(); - // Because this is an always LeftToRight layout widget the initial size of - // this widget needs to be smaller than the size of the parent scrolling - // window (ScCsvTableBox ctor) because in RTL mode the alignment is against - // the right edge of the parent, and if larger than the scrolling window - // the left edge will be lost. If this widget is smaller than the scrolling + // Because this widget always uses a LeftToRight layout, its initial size + // needs to be smaller than the size of the parent scrolling window + // (ScCsvTableBox ctor) because in RTL mode the alignment is against the + // right edge of the parent, and if larger than the scrolling window the + // left edge will be lost. If this widget is smaller than the scrolling // window it is stretched to fit the parent and the problem doesn't arise. Size aInitialSize(10, 10); if (comphelper::LibreOfficeKit::isActive()) diff --git a/sc/source/ui/dbgui/dapidata.cxx b/sc/source/ui/dbgui/dapidata.cxx index cbe1b0d1291c..8322093ea8f9 100644 --- a/sc/source/ui/dbgui/dapidata.cxx +++ b/sc/source/ui/dbgui/dapidata.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/sc/source/ui/dbgui/dapitype.cxx b/sc/source/ui/dbgui/dapitype.cxx index ecabcf47704e..8829361c43ed 100644 --- a/sc/source/ui/dbgui/dapitype.cxx +++ b/sc/source/ui/dbgui/dapitype.cxx @@ -32,8 +32,8 @@ ScDataPilotSourceTypeDlg::ScDataPilotSourceTypeDlg(weld::Window* pParent, bool b , m_xBtnDatabase(m_xBuilder->weld_radio_button(u"database"_ustr)) , m_xBtnExternal(m_xBuilder->weld_radio_button(u"external"_ustr)) , m_xLbNamedRange(m_xBuilder->weld_combo_box(u"rangelb"_ustr)) - , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr)) // for LOK jsdialog - , m_xBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr)) // for LOK jsdialog + , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr)) + , m_xBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr)) { m_xBtnSelection->connect_toggled( LINK(this, ScDataPilotSourceTypeDlg, RadioClickHdl) ); m_xBtnNamedRange->connect_toggled( LINK(this, ScDataPilotSourceTypeDlg, RadioClickHdl) ); diff --git a/sc/source/ui/dbgui/dbnamdlg.cxx b/sc/source/ui/dbgui/dbnamdlg.cxx index 647d8907ff71..0a1ca7a24a03 100644 --- a/sc/source/ui/dbgui/dbnamdlg.cxx +++ b/sc/source/ui/dbgui/dbnamdlg.cxx @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -356,18 +355,10 @@ void ScDbNameDlg::UpdateDBData( const OUString& rStrName ) } m_xBtnAdd->set_label( aStrModify ); - if (pData && !pData->GetTableStyleInfo()) - { - m_xOptions->set_sensitive(true); - m_xBtnAdd->set_sensitive(true); - m_xBtnRemove->set_sensitive(true); - } - else - { - m_xBtnAdd->set_sensitive(false); - m_xBtnRemove->set_sensitive(false); - m_xOptions->set_sensitive(false); - } + + m_xOptions->set_sensitive(true); + m_xBtnAdd->set_sensitive(true); + m_xBtnRemove->set_sensitive(true); } bool ScDbNameDlg::IsRefInputMode() const @@ -602,12 +593,7 @@ IMPL_LINK_NOARG(ScDbNameDlg, NameModifyHdl, weld::ComboBox&, void) m_xBtnRemove->set_sensitive(false); } - const ScDBData* pData = aLocalDbCol.getNamedDBs().findByUpperName( - ScGlobal::getCharClass().uppercase(theName)); - if (pData && pData->GetTableStyleInfo()) - m_xAssignFrame->set_sensitive(false); - else - m_xAssignFrame->set_sensitive(true); + m_xAssignFrame->set_sensitive(true); //@BugID 54702 enable/disable in the base class only //SFX_APPWINDOW->set_sensitive(true); diff --git a/sc/source/ui/dbgui/dbtabledlg.cxx b/sc/source/ui/dbgui/dbtabledlg.cxx index c50656382f75..27d55886fd3d 100644 --- a/sc/source/ui/dbgui/dbtabledlg.cxx +++ b/sc/source/ui/dbgui/dbtabledlg.cxx @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/sc/source/ui/dbgui/dpgroupdlg.cxx b/sc/source/ui/dbgui/dpgroupdlg.cxx index 509b754ed8a7..d91e01520d5f 100644 --- a/sc/source/ui/dbgui/dpgroupdlg.cxx +++ b/sc/source/ui/dbgui/dpgroupdlg.cxx @@ -220,7 +220,7 @@ ScDPDateGroupDlg::ScDPDateGroupDlg(weld::Window* pParent, maStartHelper.SetValue( rInfo.mbAutoStart, rInfo.mfStart ); maEndHelper.SetValue( rInfo.mbAutoEnd, rInfo.mfEnd ); - mxLbUnits->enable_toggle_buttons(weld::ColumnToggleType::Check); + mxLbUnits->enable_toggle_buttons(); if( nDatePart == 0 ) nDatePart = css::sheet::DataPilotFieldGroupBy::MONTHS; diff --git a/sc/source/ui/dbgui/filtdlg.cxx b/sc/source/ui/dbgui/filtdlg.cxx index 20237d8ef68c..faa335ab2dfb 100644 --- a/sc/source/ui/dbgui/filtdlg.cxx +++ b/sc/source/ui/dbgui/filtdlg.cxx @@ -39,10 +39,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include @@ -167,6 +168,16 @@ ScopedVclPtr lcl_getColorImage(const Color &rColor) void ScFilterDlg::Init() { + m_xLbField1->append_text(u"0000000000"_ustr); + m_xLbField1->set_active(0); + auto nPrefWidth = m_xLbField1->get_preferred_size().Width(); + m_xLbField1->clear(); + + m_xLbField1->set_size_request(nPrefWidth, -1); + m_xLbField2->set_size_request(nPrefWidth, -1); + m_xLbField3->set_size_request(nPrefWidth, -1); + m_xLbField4->set_size_request(nPrefWidth, -1); + m_xBtnClear->connect_clicked ( LINK( this, ScFilterDlg, BtnClearHdl ) ); m_xBtnOk->connect_clicked ( LINK( this, ScFilterDlg, EndDlgHdl ) ); m_xBtnCancel->connect_clicked ( LINK( this, ScFilterDlg, EndDlgHdl ) ); @@ -182,16 +193,6 @@ void ScFilterDlg::Init() m_xLbConnect3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) ); m_xLbConnect4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) ); - m_xLbField1->append_text(u"0000000000"_ustr); - m_xLbField1->set_active(0); - auto nPrefWidth = m_xLbField1->get_preferred_size().Width(); - m_xLbField1->clear(); - - m_xLbField1->set_size_request(nPrefWidth, -1); - m_xLbField2->set_size_request(nPrefWidth, -1); - m_xLbField3->set_size_request(nPrefWidth, -1); - m_xLbField4->set_size_request(nPrefWidth, -1); - m_xLbCond1->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) ); m_xLbCond2->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) ); m_xLbCond3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) ); diff --git a/sc/source/ui/dbgui/imoptdlg.cxx b/sc/source/ui/dbgui/imoptdlg.cxx index 2777eb9e450b..1626b08ff850 100644 --- a/sc/source/ui/dbgui/imoptdlg.cxx +++ b/sc/source/ui/dbgui/imoptdlg.cxx @@ -39,7 +39,7 @@ ScImportOptions::ScImportOptions( std::u16string_view rStr ) bFixedWidth = false; nFieldSepCode = 0; nTextSepCode = 0; - eCharSet = RTL_TEXTENCODING_DONTKNOW; + eEncoding = RTL_TEXTENCODING_DONTKNOW; bSaveAsShown = true; // "true" if not in string (after CSV import) bQuoteAllText = false; bSaveNumberAsSuch = true; @@ -48,6 +48,7 @@ ScImportOptions::ScImportOptions( std::u16string_view rStr ) nSheetToExport = 0; bEvaluateFormulas = true; // true if not present at all, for compatibility bIncludeBOM = false; + nEndianness = SvStreamEndian::LITTLE; sal_Int32 nTokenCount = comphelper::string::getTokenCount(rStr, ','); if ( nTokenCount < 3 ) return; @@ -61,7 +62,7 @@ ScImportOptions::ScImportOptions( std::u16string_view rStr ) nFieldSepCode = ScAsciiOptions::GetWeightedFieldSep( aToken, true); nTextSepCode = static_cast(o3tl::toInt32(o3tl::getToken(rStr, 0, ',', nIdx))); aStrFont = o3tl::getToken(rStr, 0, ',', nIdx); - eCharSet = ScGlobal::GetCharsetValue(aStrFont); + eEncoding = ScGlobal::GetEncodingValue(aStrFont); if ( nTokenCount == 4 ) { @@ -97,6 +98,8 @@ ScImportOptions::ScImportOptions( std::u16string_view rStr ) bEvaluateFormulas = o3tl::getToken(rStr, 0, ',', nIdx) == u"true"; if (nTokenCount >= 14) bIncludeBOM = o3tl::getToken(rStr, 0, ',', nIdx) == u"true"; + if (nTokenCount >= 15) + nEndianness = static_cast(o3tl::toInt32(o3tl::getToken(rStr, 0, ',', nIdx))); } } @@ -125,16 +128,18 @@ OUString ScImportOptions::BuildString() const "," + OUString::boolean( bEvaluateFormulas ) + // same as "Evaluate formulas" in ScAsciiOptions "," + - OUString::boolean(bIncludeBOM) ; // same as "Include BOM" in ScAsciiOptions + OUString::boolean(bIncludeBOM) + // same as "Include BOM" in ScAsciiOptions + "," + + OUString::number( static_cast(nEndianness) ); // same as "Endianness" in ScAsciiOptions return aResult; } void ScImportOptions::SetTextEncoding( rtl_TextEncoding nEnc ) { - eCharSet = (nEnc == RTL_TEXTENCODING_DONTKNOW ? + eEncoding = (nEnc == RTL_TEXTENCODING_DONTKNOW ? osl_getThreadTextEncoding() : nEnc); - aStrFont = ScGlobal::GetCharsetString( nEnc ); + aStrFont = ScGlobal::GetEncodingString( nEnc ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/dbgui/pfiltdlg.cxx b/sc/source/ui/dbgui/pfiltdlg.cxx index 30d1d4f8ec9b..ce571371912a 100644 --- a/sc/source/ui/dbgui/pfiltdlg.cxx +++ b/sc/source/ui/dbgui/pfiltdlg.cxx @@ -37,6 +37,7 @@ #include #include #include +#include ScPivotFilterDlg::ScPivotFilterDlg(weld::Window* pParent, const SfxItemSet& rArgSet, ScViewData& rData, SCTAB nSourceTab ) @@ -478,8 +479,8 @@ IMPL_LINK( ScPivotFilterDlg, ValModifyHdl, weld::ComboBox&, rEd, void ) if ( &rEd == m_xEdVal2.get() ) pLb = m_xLbCond2.get(); else if ( &rEd == m_xEdVal3.get() ) pLb = m_xLbCond3.get(); - // if cond of the special values "empty"/"non-empty" was chosen only the - // =-operand makes sense: + // if the condition of the special values "empty"/"non-empty" was chosen, + // only the =-operand makes sense: if ( aStrEmpty == aStrVal || aStrNotEmpty == aStrVal ) { diff --git a/sc/source/ui/dbgui/pvfundlg.cxx b/sc/source/ui/dbgui/pvfundlg.cxx index fb1b7a67f6d2..044131e138e1 100644 --- a/sc/source/ui/dbgui/pvfundlg.cxx +++ b/sc/source/ui/dbgui/pvfundlg.cxx @@ -679,7 +679,7 @@ ScDPSubtotalOptDlg::ScDPSubtotalOptDlg(weld::Window* pParent, ScDPObject& rDPObj , mrDPObj(rDPObj) , maLabelData(rLabelData) { - m_xLbHide->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xLbHide->enable_toggle_buttons(); m_xLbSortBy->set_size_request(m_xLbSortBy->get_approximate_digit_width() * 18, -1); m_xLbHide->set_size_request(-1, m_xLbHide->get_height_rows(5)); diff --git a/sc/source/ui/dbgui/scendlg.cxx b/sc/source/ui/dbgui/scendlg.cxx index 30fe15922353..831e016e82bf 100644 --- a/sc/source/ui/dbgui/scendlg.cxx +++ b/sc/source/ui/dbgui/scendlg.cxx @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/sc/source/ui/dbgui/scuiasciiopt.cxx b/sc/source/ui/dbgui/scuiasciiopt.cxx index 088509e67146..6cb770426775 100644 --- a/sc/source/ui/dbgui/scuiasciiopt.cxx +++ b/sc/source/ui/dbgui/scuiasciiopt.cxx @@ -43,10 +43,13 @@ #include #include -#include #include -#include +#include +#include +#include #include +#include +#include #include //! TODO make dynamic @@ -257,12 +260,12 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD , mnStreamInitPos(mnStreamPos) , mnRowPosCount(0) , mcTextSep(ScAsciiOptions::cDefaultTextSep) - , meDetectedCharSet(RTL_TEXTENCODING_DONTKNOW) - , mbCharSetDetect(true) + , meDetectedEncoding(RTL_TEXTENCODING_DONTKNOW) + , mbEncodingDetect(true) , meCall(eCall) - , mxFtCharSet(m_xBuilder->weld_label(u"textcharset"_ustr)) - , mxLbCharSet(new SvxTextEncodingBox(m_xBuilder->weld_combo_box(u"charset"_ustr))) - , mxFtDetectedCharSet(m_xBuilder->weld_label(u"textdetectedcharset"_ustr)) + , mxFtEncoding(m_xBuilder->weld_label(u"textencoding"_ustr)) + , mxLbEncoding(new SvxTextEncodingBox(m_xBuilder->weld_combo_box(u"encoding"_ustr))) + , mxFtDetectedEncoding(m_xBuilder->weld_label(u"textdetectedencoding"_ustr)) , mxFtCustomLang(m_xBuilder->weld_label(u"textlanguage"_ustr)) , mxLbCustomLang(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"language"_ustr))) , mxFtRow(m_xBuilder->weld_label(u"textfromrow"_ustr)) @@ -371,16 +374,39 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD else mxRbDetectSep->set_active(true); - // Detect character set only once and then use it for "Detect" option. - mpDatStream->DetectEncoding(); - meDetectedCharSet = mpDatStream->GetStreamEncoding(); - if (meDetectedCharSet == RTL_TEXTENCODING_DONTKNOW) + // this can be called from different cases, at least these: + // 1) csv file opening + // sc/source/ui/unoobj/filtuno.cxx ScFilterOptionsObj::execute, part "!bExport && aFilterString == SC_TEXT_CSV_FILTER_NAME" + // (eg: tdf#171097). In this part, we added in the same commit pInStream->SetStreamEncoding(RTL_TEXTENCODING_DONTKNOW) + // since we can't presume about the encoding of a csv + // => we need to call DetectEncoding + // + // 2) copy paste of 2 CJK lines in Calc from another application + // sc/source/ui/view/viewfun5.cxx ScViewFunc::PasteDataFormatFormattedText, + // part "nFormatId == SotClipboardFormatId::STRING || nFormatId == SotClipboardFormatId::STRING_TSVC..." + // (eg: tdf#172587). In this part, we use ScImportStringStream which sets explicitly the encoding to RTL_TEXTENCODING_UNICODE + // => we don't need to call DetectEncoding + // + // 3) use of Text to Columns function (in Calc/Data) + // sc/source/ui/view/cellsh2.cxx ScCellShell::ExecuteDB, part SID_TEXT_TO_COLUMNS + // (eg: tdf#166299). In this part, we use a SvMemoryStream and we already set the encoding to RTL_TEXTENCODING_UNICODE + // => we don't need to call DetectEncoding + + // Retrieve encoding, first time from the stream + meDetectedEncoding = mpDatStream->GetStreamEncoding(); + if (meDetectedEncoding == RTL_TEXTENCODING_DONTKNOW) { - meDetectedCharSet = osl_getThreadTextEncoding(); - // Prefer UTF-8, as UTF-16 would have already been detected from the stream. - // This gives a better chance that the file is going to be opened correctly. - if ( meDetectedCharSet == RTL_TEXTENCODING_UNICODE && mpDatStream ) - meDetectedCharSet = RTL_TEXTENCODING_UTF8; + // the stream encoding was unknown, second chance + mpDatStream->DetectEncoding(); + meDetectedEncoding = mpDatStream->GetStreamEncoding(); + if (meDetectedEncoding == RTL_TEXTENCODING_DONTKNOW) + { + meDetectedEncoding = osl_getThreadTextEncoding(); + // Prefer UTF-8, as UTF-16 would have already been detected from the stream. + // This gives a better chance that the file is going to be opened correctly. + if ( meDetectedEncoding == RTL_TEXTENCODING_UNICODE && mpDatStream ) + meDetectedEncoding = RTL_TEXTENCODING_UTF8; + } } if (bIsTSV) @@ -416,12 +442,12 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD // *** text encoding ListBox *** // all encodings allowed, including Unicode, but subsets are excluded - mxLbCharSet->FillFromTextEncodingTable( true ); + mxLbEncoding->FillFromTextEncodingTable( true ); // Insert one "SYSTEM" entry for compatibility in AsciiOptions and system // independent document linkage. - mxLbCharSet->InsertTextEncoding( RTL_TEXTENCODING_DONTKNOW, ScResId( SCSTR_CHARSET_USER ) ); - // Insert one for detecting charset. - mxLbCharSet->InsertTextEncoding( RTL_TEXTENCODING_USER_DETECTED, "- " + ScResId( SCSTR_AUTOMATIC ) + " -" ); + mxLbEncoding->InsertTextEncoding( RTL_TEXTENCODING_DONTKNOW, ScResId( SCSTR_ENCODING_USER ) ); + // Insert one for detecting encoding. + mxLbEncoding->InsertTextEncoding( RTL_TEXTENCODING_USER_DETECTED, "- " + ScResId( SCSTR_AUTOMATIC ) + " -" ); // Clipboard is always Unicode, and TextToColumns doesn't use encoding. if (meCall != SC_IMPORTFILE) @@ -429,10 +455,10 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD else if (eEncoding == RTL_TEXTENCODING_DONTKNOW) eEncoding = RTL_TEXTENCODING_USER_DETECTED; - mxLbCharSet->SelectTextEncoding(eEncoding); + mxLbEncoding->SelectTextEncoding(eEncoding); - SetSelectedCharSet(); - mxLbCharSet->connect_changed( LINK( this, ScImportAsciiDlg, CharSetHdl ) ); + SetSelectedEncoding(); + mxLbEncoding->connect_changed( LINK( this, ScImportAsciiDlg, EncodingHdl ) ); mxLbCustomLang->SetLanguageList( SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, false, false); @@ -440,10 +466,18 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD mxLbCustomLang->set_active_id(static_cast(nLanguage)); // *** column type ListBox *** - OUString aColumnUser( ScResId( SCSTR_COLUMN_USER ) ); - for (sal_Int32 nIdx {0}; nIdx>=0; ) + static const std::array aColumnTypes = { + SCSTR_COLUMN_USER_STANDARD, + SCSTR_COLUMN_USER_TEXT, + SCSTR_COLUMN_USER_DATE_DMY, + SCSTR_COLUMN_USER_DATE_MDY, + SCSTR_COLUMN_USER_DATE_YMD, + SCSTR_COLUMN_USER_US_ENGLISH, + SCSTR_COLUMN_USER_SKIP, + }; + for (const auto& nId : aColumnTypes) { - mxLbType->append_text(aColumnUser.getToken(0, ';', nIdx)); + mxLbType->append_text(ScResId(nId)); } mxLbType->connect_changed( LINK( this, ScImportAsciiDlg, LbColTypeHdl ) ); @@ -468,7 +502,7 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD if (nFromRow != 1) { mxNfRow->set_value(nFromRow); - // tdf#163638 - show visual indicator for from rows + // tdf#163638 - show visual indicator for the "From Row" value mxTableBox->GetGrid().Execute(CSVCMD_SETFIRSTIMPORTLINE, nFromRow - 1); } mxNfRow->connect_value_changed(LINK(this, ScImportAsciiDlg, FirstRowHdl)); @@ -477,8 +511,8 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD { m_xBuilder->weld_frame(u"frame1"_ustr)->hide(); // the whole "Import" section - mxFtCharSet->set_sensitive(false); - mxLbCharSet->set_sensitive(false); + mxFtEncoding->set_sensitive(false); + mxLbEncoding->set_sensitive(false); mxFtCustomLang->set_sensitive(false); mxLbCustomLang->set_active_id(LANGUAGE_SYSTEM); mxLbCustomLang->set_sensitive(false); @@ -529,7 +563,7 @@ bool ScImportAsciiDlg::GetLine( sal_uLong nLine, OUString &rText, sal_Unicode& r if (!mpRowPosArray) mpRowPosArray.reset( new sal_uLong[ASCIIDLG_MAXROWS + 2] ); - if (!mnRowPosCount) // complete re-fresh + if (!mnRowPosCount) // complete refresh { memset( mpRowPosArray.get(), 0, sizeof(mpRowPosArray[0]) * (ASCIIDLG_MAXROWS+2)); @@ -570,10 +604,10 @@ bool ScImportAsciiDlg::GetLine( sal_uLong nLine, OUString &rText, sal_Unicode& r mnStreamPos = mpDatStream->Tell(); } - // If the file content isn't unicode, ReadUniStringLine + // If the file content isn't Unicode, ReadUniStringLine // may try to seek beyond the file's end and cause a CANTSEEK error // (depending on the stream type). The error code has to be cleared, - // or further read operations (including non-unicode) will fail. + // or further read operations (including non-Unicode) will fail. if ( mpDatStream->GetError() == ERRCODE_IO_CANTSEEK ) mpDatStream->ResetError(); @@ -584,8 +618,8 @@ bool ScImportAsciiDlg::GetLine( sal_uLong nLine, OUString &rText, sal_Unicode& r void ScImportAsciiDlg::GetOptions( ScAsciiOptions& rOpt ) { - rOpt.SetCharSet( meCharSet ); - rOpt.SetCharSetSystem( mbCharSetSystem ); + rOpt.SetEncoding( meEncoding ); + rOpt.SetEncodingSystem( mbEncodingSystem ); rOpt.SetLanguage(mxLbCustomLang->get_active_id()); rOpt.SetFixedLen( mxRbFixed->get_active() ); rOpt.SetStartRow( mxNfRow->get_value() ); @@ -623,7 +657,7 @@ void ScImportAsciiDlg::SaveParameters() mxCkbQuotedAsText->get_active(), mxCkbDetectNumber->get_active(), mxCkbDetectScientificNumber->get_active(), mxRbFixed->get_active() ? FIXED : (mxRbDetectSep->get_active() ? DETECT_SEPARATOR : SEPARATOR), mxNfRow->get_value(), - mxLbCharSet->GetSelectTextEncoding(), + mxLbEncoding->GetSelectTextEncoding(), static_cast(mxLbCustomLang->get_active_id()), mxCkbSkipEmptyCells->get_active(), mxCkbRemoveSpace->get_active(), mxCkbEvaluateFormulas->get_active()); @@ -673,26 +707,26 @@ void ScImportAsciiDlg::SetSeparators( sal_Unicode cSep ) } } -void ScImportAsciiDlg::SetSelectedCharSet() +void ScImportAsciiDlg::SetSelectedEncoding() { - rtl_TextEncoding eOldCharSet = meCharSet; - meCharSet = mxLbCharSet->GetSelectTextEncoding(); - mbCharSetDetect = (meCharSet == RTL_TEXTENCODING_USER_DETECTED); - mbCharSetSystem = (meCharSet == RTL_TEXTENCODING_DONTKNOW); - if (mbCharSetDetect) + rtl_TextEncoding eOldEncoding = meEncoding; + meEncoding = mxLbEncoding->GetSelectTextEncoding(); + mbEncodingDetect = (meEncoding == RTL_TEXTENCODING_USER_DETECTED); + mbEncodingSystem = (meEncoding == RTL_TEXTENCODING_DONTKNOW); + if (mbEncodingDetect) { - meCharSet = meDetectedCharSet; - mxFtDetectedCharSet->set_label(SvxTextEncodingTable::GetTextString(meCharSet)); + meEncoding = meDetectedEncoding; + mxFtDetectedEncoding->set_label(SvxTextEncodingTable::GetTextString(meEncoding)); } - else if( mbCharSetSystem ) + else if( mbEncodingSystem ) { - meCharSet = osl_getThreadTextEncoding(); - mxFtDetectedCharSet->set_label(SvxTextEncodingTable::GetTextString(meCharSet)); + meEncoding = osl_getThreadTextEncoding(); + mxFtDetectedEncoding->set_label(SvxTextEncodingTable::GetTextString(meEncoding)); } else - mxFtDetectedCharSet->set_label(SvxTextEncodingTable::GetTextString(meCharSet)); + mxFtDetectedEncoding->set_label(SvxTextEncodingTable::GetTextString(meEncoding)); - if (eOldCharSet != meCharSet) + if (eOldEncoding != meEncoding) DetectCsvSeparators(); RbSepFix(); @@ -765,7 +799,7 @@ void ScImportAsciiDlg::SetupSeparatorCtrls() void ScImportAsciiDlg::DetectCsvSeparators() { mpDatStream->Seek(mnStreamInitPos); - SfxObjectShell::DetectCsvSeparators(*mpDatStream, meCharSet, maDetectedFieldSeps, mcTextSep); + SfxObjectShell::DetectCsvSeparators(*mpDatStream, meEncoding, maDetectedFieldSeps, mcTextSep); mpDatStream->Seek(mnStreamPos); } @@ -773,7 +807,7 @@ void ScImportAsciiDlg::UpdateVertical() { mnRowPosCount = 0; if (mpDatStream) - mpDatStream->SetStreamEncoding(meCharSet); + mpDatStream->SetStreamEncoding(meEncoding); } void ScImportAsciiDlg::RbSepFix() @@ -810,7 +844,7 @@ IMPL_LINK( ScImportAsciiDlg, SeparatorComboBoxHdl, weld::ComboBox&, rCtrl, void SeparatorHdl(&rCtrl); } -IMPL_LINK( ScImportAsciiDlg, SeparatorEditHdl, weld::Entry&, rEdit, void ) +IMPL_LINK(ScImportAsciiDlg, SeparatorEditHdl, weld::TextWidget&, rEdit, void) { SeparatorHdl(&rEdit); } @@ -845,7 +879,7 @@ void ScImportAsciiDlg::SeparatorHdl(const weld::Widget* pCtrl) OUString aOldFldSeps( maFieldSeparators); sal_Unicode cOldSep = mcTextSep; mcTextSep = lcl_CharFromCombo( *mxCbTextSep, SCSTR_TEXTSEP ); - // Any separator changed may result in completely different lines due to + // Any separator change may result in completely different lines due to // embedded line breaks. if (cOldSep != mcTextSep) { @@ -867,15 +901,15 @@ void ScImportAsciiDlg::SeparatorHdl(const weld::Widget* pCtrl) mxTableBox->GetGrid().Execute( CSVCMD_NEWCELLTEXTS ); } -IMPL_LINK_NOARG(ScImportAsciiDlg, CharSetHdl, weld::ComboBox&, void) +IMPL_LINK_NOARG(ScImportAsciiDlg, EncodingHdl, weld::ComboBox&, void) { - if (mxLbCharSet->get_active() != -1) + if (mxLbEncoding->get_active() != -1) { weld::WaitObject aWaitObj(m_xDialog.get()); - rtl_TextEncoding eOldCharSet = meCharSet; - SetSelectedCharSet(); - // switching char-set invalidates 8bit -> String conversions - if (eOldCharSet != meCharSet) + rtl_TextEncoding eOldEncoding = meEncoding; + SetSelectedEncoding(); + // switching encoding invalidates 8bit -> String conversions + if (eOldEncoding != meEncoding) UpdateVertical(); mxTableBox->GetGrid().Execute( CSVCMD_NEWCELLTEXTS ); diff --git a/sc/source/ui/dbgui/scuiimoptdlg.cxx b/sc/source/ui/dbgui/scuiimoptdlg.cxx index eda9d2792082..80be3485565f 100644 --- a/sc/source/ui/dbgui/scuiimoptdlg.cxx +++ b/sc/source/ui/dbgui/scuiimoptdlg.cxx @@ -95,17 +95,17 @@ OUString ScDelimiterTable::GetDelimiter( sal_Unicode nCode ) const void ScImportOptionsDlg::FillFromTextEncodingTable(bool bExcludeImportSubsets, sal_uInt32 nExcludeInfoFlags) { if (m_bIsAsciiImport) - m_xLbCharset->FillFromTextEncodingTable(bExcludeImportSubsets, nExcludeInfoFlags); + m_xLbEncoding->FillFromTextEncodingTable(bExcludeImportSubsets, nExcludeInfoFlags); else - m_xTvCharset->FillFromTextEncodingTable(bExcludeImportSubsets, nExcludeInfoFlags); + m_xTvEncoding->FillFromTextEncodingTable(bExcludeImportSubsets, nExcludeInfoFlags); } void ScImportOptionsDlg::FillFromDbTextEncodingMap(bool bExcludeImportSubsets, sal_uInt32 nExcludeInfoFlags) { if (m_bIsAsciiImport) - m_xLbCharset->FillFromDbTextEncodingMap(bExcludeImportSubsets, nExcludeInfoFlags); + m_xLbEncoding->FillFromDbTextEncodingMap(bExcludeImportSubsets, nExcludeInfoFlags); else - m_xTvCharset->FillFromDbTextEncodingMap(bExcludeImportSubsets, nExcludeInfoFlags); + m_xTvEncoding->FillFromDbTextEncodingMap(bExcludeImportSubsets, nExcludeInfoFlags); } // ScImportOptionsDlg @@ -117,7 +117,7 @@ ScImportOptionsDlg::ScImportOptionsDlg(weld::Window* pParent, bool bAscii, : GenericDialogController(pParent, u"modules/scalc/ui/imoptdialog.ui"_ustr, u"ImOptDialog"_ustr) , m_bIsAsciiImport(bAscii) , m_xFieldFrame(m_xBuilder->weld_frame(u"fieldframe"_ustr)) - , m_xFtCharset(m_xBuilder->weld_label(u"charsetft"_ustr)) + , m_xFtEncoding(m_xBuilder->weld_label(u"encodingft"_ustr)) , m_xEncGrid(m_xBuilder->weld_widget(u"grid2"_ustr)) , m_xFtFieldSep(m_xBuilder->weld_label(u"fieldft"_ustr)) , m_xEdFieldSep(m_xBuilder->weld_combo_box(u"field"_ustr)) @@ -127,23 +127,23 @@ ScImportOptionsDlg::ScImportOptionsDlg(weld::Window* pParent, bool bAscii, , m_xCbFormulas(m_xBuilder->weld_check_button(u"formulas"_ustr)) , m_xCbQuoteAll(m_xBuilder->weld_check_button(u"quoteall"_ustr)) , m_xCbFixed(m_xBuilder->weld_check_button(u"fixedwidth"_ustr)) - , m_xLbCharset(new SvxTextEncodingBox(m_xBuilder->weld_combo_box(u"charsetdropdown"_ustr))) - , m_xTvCharset(new SvxTextEncodingTreeView(m_xBuilder->weld_tree_view(u"charsetlist"_ustr))) + , m_xLbEncoding(new SvxTextEncodingBox(m_xBuilder->weld_combo_box(u"encodingdropdown"_ustr))) + , m_xTvEncoding(new SvxTextEncodingTreeView(m_xBuilder->weld_tree_view(u"encodinglist"_ustr))) { if (bAscii) { m_xDialog->set_help_id(m_xDialog->get_help_id() + "?config=NonTextImport"); - m_xLbCharset->show(); - m_xTvCharset->hide(); - m_xFtCharset->set_mnemonic_widget(&m_xLbCharset->getComboBox()); + m_xLbEncoding->show(); + m_xTvEncoding->hide(); + m_xFtEncoding->set_mnemonic_widget(&m_xLbEncoding->getComboBox()); } else { - m_xTvCharset->set_size_request(-1, m_xTvCharset->get_height_rows(6)); + m_xTvEncoding->set_size_request(-1, m_xTvEncoding->get_height_rows(6)); m_xEncGrid->set_vexpand(true); - m_xLbCharset->hide(); - m_xTvCharset->show(); - m_xFtCharset->set_mnemonic_widget(&m_xTvCharset->getTreeView()); + m_xLbEncoding->hide(); + m_xTvEncoding->show(); + m_xFtEncoding->set_mnemonic_widget(&m_xTvEncoding->getTreeView()); } OUString sFieldSep(SCSTR_FIELDSEP); @@ -215,7 +215,7 @@ ScImportOptionsDlg::ScImportOptionsDlg(weld::Window* pParent, bool bAscii, if( bAscii ) { - sal_Int32 nCharSet = officecfg::Office::Calc::Dialogs::CSVExport::CharSet::get(); + sal_Int32 nEncoding = officecfg::Office::Calc::Dialogs::CSVExport::Encoding::get(); OUString strFieldSeparator = officecfg::Office::Calc::Dialogs::CSVExport::FieldSeparator::get(); OUString strTextSeparator = officecfg::Office::Calc::Dialogs::CSVExport::TextSeparator::get(); bool bSaveTrueCellContent = officecfg::Office::Calc::Dialogs::CSVExport::SaveTrueCellContent::get(); @@ -232,33 +232,33 @@ ScImportOptionsDlg::ScImportOptionsDlg(weld::Window* pParent, bool bAscii, m_xCbQuoteAll->show(); m_xCbQuoteAll->set_active( bQuoteAllTextCells ); m_xCbFormulas->show(); - // default option for "save formulas" no longer taken from view shell but from persisted dialog settings + // default option for "save formulas" is no longer taken from view shell but from persisted dialog settings m_xCbFormulas->set_active( bSaveCellFormulas ); - // if no charset, text separator or field separator exist, keep the values from dialog initialization + // if no encoding, text separator or field separator exist, keep the values from dialog initialization if (strFieldSeparator.getLength() > 0) m_xEdFieldSep->set_entry_text(strFieldSeparator); if (strTextSeparator.getLength() > 0) m_xEdTextSep->set_entry_text(strTextSeparator); - if (nCharSet < 0 || nCharSet == RTL_TEXTENCODING_DONTKNOW ) - m_xLbCharset->SelectTextEncoding(pOptions ? pOptions->eCharSet : osl_getThreadTextEncoding()); + if (nEncoding < 0 || nEncoding == RTL_TEXTENCODING_DONTKNOW ) + m_xLbEncoding->SelectTextEncoding(pOptions ? pOptions->eEncoding : osl_getThreadTextEncoding()); else - m_xLbCharset->SelectTextEncoding(nCharSet); + m_xLbEncoding->SelectTextEncoding(nEncoding); } else { - m_xFieldFrame->set_label(m_xFtCharset->get_label()); + m_xFieldFrame->set_label(m_xFtEncoding->get_label()); m_xFtFieldSep->hide(); m_xFtTextSep->hide(); - m_xFtCharset->hide(); + m_xFtEncoding->hide(); m_xEdFieldSep->hide(); m_xEdTextSep->hide(); m_xCbFixed->hide(); m_xCbShown->hide(); m_xCbQuoteAll->hide(); m_xCbFormulas->hide(); - m_xTvCharset->grab_focus(); - m_xTvCharset->connect_item_activated(LINK(this, ScImportOptionsDlg, DoubleClickHdl)); - m_xTvCharset->SelectTextEncoding(pOptions ? pOptions->eCharSet : osl_getThreadTextEncoding()); + m_xTvEncoding->grab_focus(); + m_xTvEncoding->connect_item_activated(LINK(this, ScImportOptionsDlg, DoubleClickHdl)); + m_xTvEncoding->SelectTextEncoding(pOptions ? pOptions->eEncoding : osl_getThreadTextEncoding()); } // optional title: @@ -279,7 +279,7 @@ ScImportOptionsDlg::~ScImportOptionsDlg() void ScImportOptionsDlg::GetImportOptions( ScImportOptions& rOptions ) const { - auto nEncoding = m_bIsAsciiImport ? m_xLbCharset->GetSelectTextEncoding() : m_xTvCharset->GetSelectTextEncoding(); + auto nEncoding = m_bIsAsciiImport ? m_xLbEncoding->GetSelectTextEncoding() : m_xTvEncoding->GetSelectTextEncoding(); rOptions.SetTextEncoding(nEncoding); if (m_xCbFixed->get_visible()) @@ -339,8 +339,8 @@ IMPL_LINK_NOARG(ScImportOptionsDlg, DoubleClickHdl, const weld::TreeIter&, bool) void ScImportOptionsDlg::SaveImportOptions() const { std::shared_ptr < comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create()); - auto nEncoding = m_bIsAsciiImport ? m_xLbCharset->GetSelectTextEncoding() : m_xTvCharset->GetSelectTextEncoding(); - officecfg::Office::Calc::Dialogs::CSVExport::CharSet::set(nEncoding, batch); + auto nEncoding = m_bIsAsciiImport ? m_xLbEncoding->GetSelectTextEncoding() : m_xTvEncoding->GetSelectTextEncoding(); + officecfg::Office::Calc::Dialogs::CSVExport::Encoding::set(nEncoding, batch); officecfg::Office::Calc::Dialogs::CSVExport::FieldSeparator::set(m_xEdFieldSep->get_active_text(), batch); officecfg::Office::Calc::Dialogs::CSVExport::TextSeparator::set(m_xEdTextSep->get_active_text(), batch); officecfg::Office::Calc::Dialogs::CSVExport::FixedWidth::set(m_xCbFixed->get_active(), batch); diff --git a/sc/source/ui/dbgui/sfiltdlg.cxx b/sc/source/ui/dbgui/sfiltdlg.cxx index 873b3eeb9544..e644bde3ae44 100644 --- a/sc/source/ui/dbgui/sfiltdlg.cxx +++ b/sc/source/ui/dbgui/sfiltdlg.cxx @@ -35,8 +35,8 @@ #include #include #include +#include #include -#include // DEFINE -------------------------------------------------------------------- @@ -51,18 +51,18 @@ namespace } } - -ScSpecialFilterDlg::ScSpecialFilterDlg( SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, - ScViewData& rData, const SfxItemSet& rArgSet ) - - : ScAnyRefDlgController(pB, pCW, pParent, u"modules/scalc/ui/advancedfilterdialog.ui"_ustr, u"AdvancedFilterDialog"_ustr) - , aStrUndefined ( ScResId(SCSTR_UNDEFINED) ) - , nWhichQuery ( rArgSet.GetPool()->GetWhichIDFromSlotID( SID_QUERY ) ) - , theQueryData ( static_cast( - rArgSet.Get( nWhichQuery )).GetQueryData() ) - , rViewData(rData) - , rDoc(rViewData.GetDocument()) - , bRefInputMode(false) +ScSpecialFilterDlg::ScSpecialFilterDlg(SfxBindings& rBindings, SfxChildWindow* pCW, + weld::Window* pParent, ScViewData& rData, + const SfxItemSet& rArgSet) + : ScAnyRefDlgController(&rBindings, pCW, pParent, + u"modules/scalc/ui/advancedfilterdialog.ui"_ustr, + u"AdvancedFilterDialog"_ustr) + , m_aStrUndefined(ScResId(SCSTR_UNDEFINED)) + , m_nWhichQuery(rArgSet.GetPool()->GetWhichIDFromSlotID(SID_QUERY)) + , m_theQueryData(static_cast(rArgSet.Get(m_nWhichQuery)).GetQueryData()) + , m_rViewData(rData) + , m_rDoc(m_rViewData.GetDocument()) + , m_bRefInputMode(false) , m_pRefInputEdit(nullptr) , m_xLbFilterArea(m_xBuilder->weld_combo_box(u"lbfilterarea"_ustr)) , m_xEdFilterArea(new formula::RefEdit(m_xBuilder->weld_entry(u"edfilterarea"_ustr))) @@ -106,9 +106,9 @@ ScSpecialFilterDlg::ScSpecialFilterDlg( SfxBindings* pB, SfxChildWindow* pCW, we ScSpecialFilterDlg::~ScSpecialFilterDlg() { - pOptionsMgr.reset(); + m_pOptionsMgr.reset(); - pOutItem.reset(); + m_pOutItem.reset(); } void ScSpecialFilterDlg::Init( const SfxItemSet& rArgSet ) @@ -120,13 +120,14 @@ void ScSpecialFilterDlg::Init( const SfxItemSet& rArgSet ) m_xEdFilterArea->SetText( OUString() ); // may be overwritten below - if(rDoc.GetChangeTrack()!=nullptr) m_xBtnCopyResult->set_sensitive(false); + if (m_rDoc.GetChangeTrack() != nullptr) + m_xBtnCopyResult->set_sensitive(false); - ScRangeName* pRangeNames = rDoc.GetRangeName(); + ScRangeName& rRangeNames = m_rDoc.GetRangeName(); m_xLbFilterArea->clear(); - m_xLbFilterArea->append_text(aStrUndefined); + m_xLbFilterArea->append_text(m_aStrUndefined); - for (const auto& rEntry : *pRangeNames) + for (const auto& rEntry : rRangeNames) { if (!rEntry.second->HasType(ScRangeData::Type::Criteria)) continue; @@ -138,12 +139,12 @@ void ScSpecialFilterDlg::Init( const SfxItemSet& rArgSet ) // is there a stored source range? ScRange aAdvSource; - const ScQueryItem& rQueryItem = static_cast( - rArgSet.Get( nWhichQuery )); + const ScQueryItem& rQueryItem = static_cast(rArgSet.Get(m_nWhichQuery)); if (rQueryItem.GetAdvancedQuerySource(aAdvSource)) { - OUString aRefStr(aAdvSource.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention())); + OUString aRefStr( + aAdvSource.Format(m_rDoc, ScRefFlags::RANGE_ABS_3D, m_rDoc.GetAddressConvention())); m_xEdFilterArea->SetRefString( aRefStr ); } @@ -151,21 +152,11 @@ void ScSpecialFilterDlg::Init( const SfxItemSet& rArgSet ) // let options be initialized: - pOptionsMgr.reset( new ScFilterOptionsMgr( - rViewData, - theQueryData, - m_xBtnCase.get(), - m_xBtnRegExp.get(), - m_xBtnHeader.get(), - m_xBtnUnique.get(), - m_xBtnCopyResult.get(), - m_xBtnDestPers.get(), - m_xLbCopyArea.get(), - m_xEdCopyArea.get(), - m_xRbCopyArea.get(), - m_xFtDbAreaLabel.get(), - m_xFtDbArea.get(), - aStrUndefined ) ); + m_pOptionsMgr.reset(new ScFilterOptionsMgr( + m_rViewData, m_theQueryData, m_xBtnCase.get(), m_xBtnRegExp.get(), m_xBtnHeader.get(), + m_xBtnUnique.get(), m_xBtnCopyResult.get(), m_xBtnDestPers.get(), m_xLbCopyArea.get(), + m_xEdCopyArea.get(), m_xRbCopyArea.get(), m_xFtDbAreaLabel.get(), m_xFtDbArea.get(), + m_aStrUndefined)); // special filter always needs column headers m_xBtnHeader->set_active(true); @@ -179,7 +170,7 @@ void ScSpecialFilterDlg::Init( const SfxItemSet& rArgSet ) void ScSpecialFilterDlg::Close() { - rViewData.GetDocShell()->CancelAutoDBRange(); + m_rViewData.GetDocShell()->CancelAutoDBRange(); DoClose( ScSpecialFilterDlgWrapper::GetChildWindowId() ); } @@ -189,7 +180,7 @@ void ScSpecialFilterDlg::Close() void ScSpecialFilterDlg::SetReference( const ScRange& rRef, ScDocument& rDocP ) { - if ( !(bRefInputMode && m_pRefInputEdit) ) // only possible if in the reference edit mode + if (!(m_bRefInputMode && m_pRefInputEdit)) // only possible if in the reference edit mode return; if ( rRef.aStart != rRef.aEnd ) @@ -208,7 +199,7 @@ void ScSpecialFilterDlg::SetReference( const ScRange& rRef, ScDocument& rDocP ) void ScSpecialFilterDlg::SetActive() { - if ( bRefInputMode ) + if (m_bRefInputMode) { if (m_pRefInputEdit == m_xEdCopyArea.get()) { @@ -230,15 +221,12 @@ void ScSpecialFilterDlg::SetActive() ScQueryItem* ScSpecialFilterDlg::GetOutputItem( const ScQueryParam& rParam, const ScRange& rSource ) { - pOutItem.reset(new ScQueryItem( nWhichQuery, &rParam )); - pOutItem->SetAdvancedQuerySource( &rSource ); - return pOutItem.get(); + m_pOutItem.reset(new ScQueryItem(m_nWhichQuery, &rParam)); + m_pOutItem->SetAdvancedQuerySource(&rSource); + return m_pOutItem.get(); } -bool ScSpecialFilterDlg::IsRefInputMode() const -{ - return bRefInputMode; -} +bool ScSpecialFilterDlg::IsRefInputMode() const { return m_bRefInputMode; } // Handler: @@ -248,12 +236,12 @@ IMPL_LINK(ScSpecialFilterDlg, EndDlgHdl, weld::Button&, rBtn, void) { OUString theCopyStr( m_xEdCopyArea->GetText() ); OUString theAreaStr( m_xEdFilterArea->GetText() ); - ScQueryParam theOutParam( theQueryData ); + ScQueryParam theOutParam(m_theQueryData); ScAddress theAdrCopy; bool bEditInputOk = true; bool bQueryOk = false; ScRange theFilterArea; - const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention(); + const formula::FormulaGrammar::AddressConvention eConv = m_rDoc.GetAddressConvention(); if ( m_xBtnCopyResult->get_active() ) { @@ -262,7 +250,7 @@ IMPL_LINK(ScSpecialFilterDlg, EndDlgHdl, weld::Button&, rBtn, void) if ( -1 != nColonPos ) theCopyStr = theCopyStr.copy( 0, nColonPos ); - ScRefFlags nResult = theAdrCopy.Parse( theCopyStr, rDoc, eConv ); + ScRefFlags nResult = theAdrCopy.Parse(theCopyStr, m_rDoc, eConv); if ( (nResult & ScRefFlags::VALID) == ScRefFlags::ZERO ) { @@ -277,7 +265,7 @@ IMPL_LINK(ScSpecialFilterDlg, EndDlgHdl, weld::Button&, rBtn, void) if ( bEditInputOk ) { - ScRefFlags nResult = ScRange().Parse( theAreaStr, rDoc, eConv ); + ScRefFlags nResult = ScRange().Parse(theAreaStr, m_rDoc, eConv); if ( (nResult & ScRefFlags::VALID) == ScRefFlags::ZERO ) { @@ -291,10 +279,10 @@ IMPL_LINK(ScSpecialFilterDlg, EndDlgHdl, weld::Button&, rBtn, void) { /* * All edit fields contain valid areas. Now try to create - * a ScQueryParam from the filter area: + * an ScQueryParam from the filter area: */ - ScRefFlags nResult = theFilterArea.Parse( theAreaStr, rDoc, eConv ); + ScRefFlags nResult = theFilterArea.Parse(theAreaStr, m_rDoc, eConv); if ( (nResult & ScRefFlags::VALID) == ScRefFlags::VALID ) { @@ -324,7 +312,7 @@ IMPL_LINK(ScSpecialFilterDlg, EndDlgHdl, weld::Button&, rBtn, void) theOutParam.bDuplicate = !m_xBtnUnique->get_active(); theOutParam.bDestPers = m_xBtnDestPers->get_active(); - bQueryOk = rDoc.CreateQueryParam(ScRange(rStart,rEnd), theOutParam); + bQueryOk = m_rDoc.CreateQueryParam(ScRange(rStart, rEnd), theOutParam); } } @@ -367,17 +355,17 @@ void ScSpecialFilterDlg::RefInputHdl() if( m_xEdCopyArea->GetWidget()->has_focus() || m_xRbCopyArea->GetWidget()->has_focus() ) { m_pRefInputEdit = m_xEdCopyArea.get(); - bRefInputMode = true; + m_bRefInputMode = true; } else if( m_xEdFilterArea->GetWidget()->has_focus() || m_xRbFilterArea->GetWidget()->has_focus() ) { m_pRefInputEdit = m_xEdFilterArea.get(); - bRefInputMode = true; + m_bRefInputMode = true; } - else if( bRefInputMode ) + else if (m_bRefInputMode) { m_pRefInputEdit = nullptr; - bRefInputMode = false; + m_bRefInputMode = false; } } @@ -401,7 +389,7 @@ IMPL_LINK( ScSpecialFilterDlg, FilterAreaModHdl, formula::RefEdit&, rEd, void ) return; OUString theCurAreaStr = rEd.GetText(); - ScRefFlags nResult = ScRange().Parse( theCurAreaStr, rDoc ); + ScRefFlags nResult = ScRange().Parse(theCurAreaStr, m_rDoc); if ( (nResult & ScRefFlags::VALID) == ScRefFlags::VALID ) { diff --git a/sc/source/ui/dbgui/sortdlg.cxx b/sc/source/ui/dbgui/sortdlg.cxx index 405b26e44e53..a2995dc7fe79 100644 --- a/sc/source/ui/dbgui/sortdlg.cxx +++ b/sc/source/ui/dbgui/sortdlg.cxx @@ -22,8 +22,8 @@ #include #include #include -#include +#include #include #include #include @@ -44,10 +44,9 @@ ScSortDlg::ScSortDlg(weld::Window* pParent, const SfxItemSet* pArgSet) ScSortDlg::~ScSortDlg() { - // tdf#153852 - Make of sort dialog resizable (and remember size) + // tdf#153852 - Make the sort dialog resizable (and remember size) SvtViewOptions aDlgOpt(EViewType::Dialog, u"SortDialog"_ustr); - OUString sWindowState = m_xDialog->get_window_state(vcl::WindowDataMask::PosSize); - aDlgOpt.SetWindowState(sWindowState); + aDlgOpt.SetWindowState(m_xDialog->get_window_state(vcl::WindowDataMask::PosSize)); } ScSortWarningDlg::ScSortWarningDlg(weld::Window* pParent, @@ -76,7 +75,7 @@ IMPL_LINK(ScSortWarningDlg, BtnHdl, weld::Button&, rBtn, void) { m_xDialog->response(BTN_EXTEND_RANGE); } - else if(&rBtn == m_xBtnCurSort.get()) + else if (&rBtn == m_xBtnCurSort.get()) { m_xDialog->response(BTN_CURRENT_SELECTION); } diff --git a/sc/source/ui/dbgui/tpsort.cxx b/sc/source/ui/dbgui/tpsort.cxx index a3a1e28087b5..cd68095ef1ee 100644 --- a/sc/source/ui/dbgui/tpsort.cxx +++ b/sc/source/ui/dbgui/tpsort.cxx @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,7 @@ using namespace com::sun::star; /* - * Since the settings on the second Tab Page (Options) effects + * Since the settings on the second Tab Page (Options) affect * the first Tab Page, there must be a way for it to communicate with the * other Page. * @@ -721,7 +720,7 @@ void ScTabPageSortOptions::ActivatePage( const SfxItemSet& rSet ) if (!pDlg) return; - //tdf#168905 If sort by row, then include affects boundary columns. + //tdf#168905 If sorting by row, the include option affects the boundary columns. if (aSortData.bByRow) { m_xBtnIncComments->set_label(aStrCommentsColLabel); diff --git a/sc/source/ui/dbgui/tpsubt.cxx b/sc/source/ui/dbgui/tpsubt.cxx index ca05772bcdad..70bc1fa5848c 100644 --- a/sc/source/ui/dbgui/tpsubt.cxx +++ b/sc/source/ui/dbgui/tpsubt.cxx @@ -52,14 +52,14 @@ ScTpSubTotalGroup::ScTpSubTotalGroup(weld::Container* pPage, weld::DialogControl , mxLbFunctions(m_xBuilder->weld_tree_view(u"functions"_ustr)) , mxLbSelectAllColumns(m_xBuilder->weld_check_button(u"select_all_columns_button"_ustr)) { - for (size_t i = 0; i < SAL_N_ELEMENTS(SCSTR_SUBTOTALS); ++i) - mxLbFunctions->append_text(ScResId(SCSTR_SUBTOTALS[i])); + for (const auto& rResId : SCSTR_SUBTOTALS) + mxLbFunctions->append_text(ScResId(rResId)); auto nHeight = mxLbColumns->get_height_rows(14); mxLbColumns->set_size_request(-1, nHeight); mxLbFunctions->set_size_request(-1, nHeight); - mxLbColumns->enable_toggle_buttons(weld::ColumnToggleType::Check); + mxLbColumns->enable_toggle_buttons(); Init(); diff --git a/sc/source/ui/dbgui/validate.cxx b/sc/source/ui/dbgui/validate.cxx index 590768f75518..0af029794a44 100644 --- a/sc/source/ui/dbgui/validate.cxx +++ b/sc/source/ui/dbgui/validate.cxx @@ -81,14 +81,6 @@ const WhichRangesContainer ScTPValidationValue::pValueRanges(svl::Items< FID_VALID_MODE, FID_VALID_ERRTEXT >); -static bool isLOKMobilePhone() -{ - if (!comphelper::LibreOfficeKit::isActive()) - return false; - SfxViewShell* pViewShell = SfxViewShell::Current(); - return pViewShell && pViewShell->isLOKMobilePhone(); -} - ScValidationDlg::ScValidationDlg(weld::Window* pParent, const SfxItemSet* pArgSet, ScTabViewShell *pTabViewSh) : ScValidationDlgBase(pParent, @@ -105,12 +97,6 @@ ScValidationDlg::ScValidationDlg(weld::Window* pParent, const SfxItemSet* pArgSe ScTPValidationHelp::Create, RID_L + RID_TAB_VALIDITY_INPUT.sIconName); AddTabPage(u"erroralert"_ustr, TabResId(RID_TAB_VALIDITY_ERROR.aLabel), ScTPValidationError::Create, RID_L + RID_TAB_VALIDITY_ERROR.sIconName); - - if (isLOKMobilePhone()) - { - m_xBuilder->weld_button(u"cancel"_ustr)->hide(); - m_xBuilder->weld_button(u"help"_ustr)->hide(); - } } void ScValidationDlg::EndDialog(int nResponse) diff --git a/sc/source/ui/dialogs/SelectSheetViewDialog.cxx b/sc/source/ui/dialogs/SelectSheetViewDialog.cxx index 074b957d8064..ae628501b932 100644 --- a/sc/source/ui/dialogs/SelectSheetViewDialog.cxx +++ b/sc/source/ui/dialogs/SelectSheetViewDialog.cxx @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -20,17 +19,17 @@ namespace sc { class SheetViewListEntry { - std::shared_ptr mpSheetView; + OUString maName; sc::SheetViewID mnSheetViewID = sc::InvalidSheetViewID; public: - SheetViewListEntry(std::shared_ptr const& pSheetView, sc::SheetViewID nSheetViewID) - : mpSheetView(pSheetView) + SheetViewListEntry(OUString const& rName, sc::SheetViewID nSheetViewID) + : maName(rName) , mnSheetViewID(nSheetViewID) { } - const OUString& getName() const { return mpSheetView->GetName(); } + const OUString& getName() const { return maName; } sc::SheetViewID getSheetViewID() const { return mnSheetViewID; } }; @@ -42,9 +41,6 @@ SelectSheetViewDialog::SelectSheetViewDialog(weld::Window* pParent, ScViewData& { m_xEntryTree->connect_selection_changed(LINK(this, SelectSheetViewDialog, NameModifyHdl)); - ScDocument& rDocument = mrViewData.GetDocument(); - - auto pSheetManager = rDocument.GetSheetViewManager(mrViewData.GetTabNumber()); m_xEntryTree->clear(); m_xEntryTree->freeze(); @@ -52,21 +48,15 @@ SelectSheetViewDialog::SelectSheetViewDialog(weld::Window* pParent, ScViewData& OUString sActiveID = u"-1"_ustr; m_xEntryTree->append(u"-1"_ustr, SheetViewManager::defaultViewName()); - if (pSheetManager) + if (auto pSheetManager = mrViewData.GetCurrentSheetViewManager()) { - sc::SheetViewID nSheetViewID = 0; - - for (auto const& pSheetView : pSheetManager->getSheetViews()) + for (auto const& rSheetView : pSheetManager->iterateValidSheetViews()) { - if (pSheetView) - { - auto& aEntry = m_aEntries.emplace_back(pSheetView, nSheetViewID); - OUString sID = OUString::number(m_aEntries.size() - 1); - if (nSheetViewID == mrViewData.GetSheetViewID()) - sActiveID = sID; - m_xEntryTree->append(sID, aEntry.getName()); - } - nSheetViewID++; + auto& aEntry = m_aEntries.emplace_back(rSheetView.GetName(), rSheetView.getID()); + OUString sID = OUString::number(m_aEntries.size() - 1); + if (rSheetView.getID() == mrViewData.GetSheetViewID()) + sActiveID = sID; + m_xEntryTree->append(sID, aEntry.getName()); } } diff --git a/sc/source/ui/dialogs/searchresults.cxx b/sc/source/ui/dialogs/searchresults.cxx index b11a9340298f..2c275457da10 100644 --- a/sc/source/ui/dialogs/searchresults.cxx +++ b/sc/source/ui/dialogs/searchresults.cxx @@ -41,7 +41,7 @@ SearchResultsDlg::SearchResultsDlg(SfxBindings* _pBindings, weld::Window* pParen }; mxList->set_column_fixed_widths(aWidths); mxList->connect_selection_changed(LINK(this, SearchResultsDlg, ListSelectHdl)); - mxList->connect_column_clicked(LINK(this, SearchResultsDlg, HeaderBarClick)); + mxList->connect_column_header_clicked(LINK(this, SearchResultsDlg, HeaderBarClick)); } SearchResultsDlg::~SearchResultsDlg() @@ -233,6 +233,10 @@ IMPL_LINK_NOARG(SearchResultsDlg, ListSelectHdl, weld::ItemView&, void) pScViewShell->SetCursor(aPos.Col(), aPos.Row()); pScViewShell->AlignToCursor(aPos.Col(), aPos.Row(), SC_FOLLOW_JUMP); } + + // unselect single entry to allow the user to re-select it + if (mxList->n_children() == 1) + mxList->unselect_all(); } IMPL_STATIC_LINK( SearchResultsDlg, OnShowToggled, weld::Toggleable&, rButton, void ) @@ -245,10 +249,10 @@ IMPL_STATIC_LINK( SearchResultsDlg, OnShowToggled, weld::Toggleable&, rButton, v } } -SearchResultsDlgWrapper::SearchResultsDlgWrapper( - vcl::Window* _pParent, sal_uInt16 nId, SfxBindings* pBindings, SfxChildWinInfo* /*pInfo*/) +SearchResultsDlgWrapper::SearchResultsDlgWrapper(vcl::Window* _pParent, sal_uInt16 nId, + SfxBindings& rBindings, SfxChildWinInfo& /*rInfo*/) : SfxChildWindow(_pParent, nId) - , m_xDialog(std::make_shared(pBindings, _pParent->GetFrameWeld())) + , m_xDialog(std::make_shared(&rBindings, _pParent->GetFrameWeld())) { SetController(m_xDialog); } diff --git a/sc/source/ui/docshell/SheetViewOperationsTester.cxx b/sc/source/ui/docshell/SheetViewOperationsTester.cxx index 6b5469159173..d0e1643f1f62 100644 --- a/sc/source/ui/docshell/SheetViewOperationsTester.cxx +++ b/sc/source/ui/docshell/SheetViewOperationsTester.cxx @@ -8,8 +8,8 @@ */ #include -#include -#include +#include +#include #include #include @@ -17,129 +17,23 @@ namespace sc { namespace { -/** Return operation as string. */ -constexpr std::string_view getOperationName(Operation eOperation) -{ - switch (eOperation) - { - case Operation::Unknown: - return "Unknown"; - case Operation::DeleteContent: - return "DeleteContent"; - case Operation::DeleteCell: - return "DeleteCell"; - case Operation::TransliterateText: - return "TransliterateText"; - case Operation::SetNormalString: - return "SetNormalString"; - case Operation::SetNoteText: - return "SetNoteText"; - case Operation::ReplaceNoteText: - return "ReplaceNoteText"; - case Operation::InsertColumnsBefore: - return "InsertColumnsBefore"; - case Operation::InsertColumnsAfter: - return "InsertColumnsAfter"; - case Operation::InsertRowsBefore: - return "InsertRowsBefore"; - case Operation::InsertRowsAfter: - return "InsertRowsAfter"; - case Operation::InsertCellsDown: - return "InsertCellsDown"; - case Operation::InsertCellsRight: - return "InsertCellsRight"; - case Operation::DeleteColumns: - return "DeleteColumns"; - case Operation::DeleteRows: - return "DeleteRows"; - case Operation::DeleteCellsLeft: - return "DeleteCellsLeft"; - case Operation::DeleteCellsUp: - return "DeleteCellsUp"; - case Operation::MoveBlock: - return "MoveBlock"; - case Operation::ClearItems: - return "ClearItems"; - case Operation::ChangeIndent: - return "ChangeIndent"; - case Operation::AutoFormat: - return "AutoFormat"; - case Operation::EnterMatrix: - return "EnterMatrix"; - case Operation::TabOperation: - return "TabOperation"; - case Operation::FillSimple: - return "FillSimple"; - case Operation::FillSeries: - return "FillSeries"; - case Operation::FillAuto: - return "FillAuto"; - case Operation::MergeCells: - return "MergeCells"; - case Operation::InsertNameList: - return "InsertNameList"; - case Operation::ConvertFormulaToValue: - return "ConvertFormulaToValue"; - case Operation::Sort: - return "Sort"; - case Operation::Query: - return "Query"; - case Operation::SubTotals: - return "SubTotals"; - case Operation::PivotTableUpdate: - return "PivotTableUpdate"; - case Operation::PivotTableRemove: - return "PivotTableRemove"; - case Operation::PivotTableCreate: - return "PivotTableCreate"; - case Operation::SparklineInsert: - return "SparklineInsert"; - case Operation::SparklineDelete: - return "SparklineDelete"; - case Operation::SparklineChange: - return "SparklineChange"; - case Operation::SparklineGroup: - return "SparklineGroup"; - case Operation::SparklineUngroup: - return "SparklineUngroup"; - case Operation::SparklineGroupDelete: - return "SparklineGroupDelete"; - case Operation::SparklineGroupChange: - return "SparklineGroupChange"; - case Operation::EnterData: - return "EnterData"; - } - return ""; -} - /** Supported operations by sheet view. */ -constexpr bool isSupported(Operation eOperation) +constexpr bool isSupported(OperationType eOperationType) { - return eOperation == Operation::EnterData || eOperation == Operation::SetNormalString - || eOperation == Operation::Sort; + return eOperationType == OperationType::EnterData + || eOperationType == OperationType::SetNormalString + || eOperationType == OperationType::Sort; } -/** Operations on default view that unsync all the sheet views. */ -constexpr bool doesUnsycAllSheetView(Operation eOperation) -{ - bool bOperationAllowed - = eOperation == Operation::EnterData || eOperation == Operation::SetNormalString; - - return !bOperationAllowed; -} - -/** Operations that unsync the current sheet view. */ -constexpr bool doesUnsycSheetView(Operation eOperation) { return eOperation == Operation::Sort; } - } // end anonymous namespace -bool SheetViewOperationsTester::check(Operation eOperation) const +bool SheetViewOperationsTester::check(OperationType eOperationType) const { if (!mpViewData) return true; auto& rDocument = mpViewData->GetDocument(); - SCTAB nTab = mpViewData->GetTabNumber(); + SCTAB nTab = mpViewData->GetDefaultViewTab(); // Never allow direct changes to the data holder sheet of the sheet view. if (rDocument.IsSheetViewHolder(nTab)) @@ -147,36 +41,18 @@ bool SheetViewOperationsTester::check(Operation eOperation) const sc::SheetViewID nSheetViewID = mpViewData->GetSheetViewID(); - std::shared_ptr pSheetViewManager = rDocument.GetSheetViewManager(nTab); - - if (nSheetViewID == sc::DefaultSheetViewID && doesUnsycAllSheetView(eOperation)) + if (nSheetViewID != sc::DefaultSheetViewID) { - // Only unsync if there are sheet views. - if (!pSheetViewManager->isEmpty()) - { - pSheetViewManager->unsyncAllSheetViews(); - SAL_INFO("sc.ui", "Operation '" << getOperationName(eOperation) - << "' unsynced all sheet views for TAB " << nTab); - } - } - else - { - bool bSupported = isSupported(eOperation); + bool bSupported = isSupported(eOperationType); SAL_INFO_IF(!bSupported, "sc.ui", - "Operation '" << getOperationName(eOperation) + "Operation '" << operationTypeString(eOperationType) << "' not supported on sheet view '" << nSheetViewID << "'"); - - if (bSupported && doesUnsycSheetView(eOperation)) - { - std::shared_ptr pSheetView = pSheetViewManager->get(nSheetViewID); - pSheetView->unsync(); - SAL_INFO("sc.ui", "Operation '" << getOperationName(eOperation) - << "' unsynced sheet view '" << nSheetViewID << "'"); - } return bSupported; } return true; } -} + +} // end sc namespace + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/docshell/arealink.cxx b/sc/source/ui/docshell/arealink.cxx index f4600287565e..b8bd66533b27 100644 --- a/sc/source/ui/docshell/arealink.cxx +++ b/sc/source/ui/docshell/arealink.cxx @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -185,13 +184,13 @@ bool ScAreaLink::FindExtRange( ScRange& rRange, const ScDocument& rSrcDoc, const { bool bFound = false; OUString aUpperName = ScGlobal::getCharClass().uppercase(rAreaName); - ScRangeName* pNames = rSrcDoc.GetRangeName(); - if (pNames) // named ranges - { - const ScRangeData* p = pNames->findByUpperName(aUpperName); - if (p && p->IsValidReference(rRange)) - bFound = true; - } + ScRangeName& rNames = rSrcDoc.GetRangeName(); + + // named ranges + const ScRangeData* p = rNames.findByUpperName(aUpperName); + if (p && p->IsValidReference(rRange)) + bFound = true; + if (!bFound) // database ranges { ScDBCollection* pDBColl = rSrcDoc.GetDBCollection(); @@ -249,7 +248,7 @@ bool ScAreaLink::Refresh( const OUString& rNewFile, const OUString& rNewFilter, SfxMedium* pMed = ScDocumentLoader::CreateMedium( aNewUrl, pFilter, aOptions); - // aRef->DoClose() will be closed explicitly, but it is still more safe to use SfxObjectShellLock here + // aRef->DoClose() will be closed explicitly, but it is still safer to use SfxObjectShellLock here rtl::Reference pSrcShell = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS); pSrcShell->DoLoad(pMed); diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index 90d20da0f41f..8e1c21b33751 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -59,17 +59,18 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include using namespace ::com::sun::star; -bool ScDBDocFunc::CheckSheetViewProtection(sc::Operation eOperation) -{ - sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData()); - return aSheetViewTester.check(eOperation); -} - bool ScDBDocFunc::AddDBTable(const OUString& rName, const ScRange& rRange, bool bHeader, bool bRecord, bool bApi, const OUString& rStyleName) { @@ -91,23 +92,71 @@ bool ScDBDocFunc::AddDBTable(const OUString& rName, const ScRange& rRange, bool if (bRecord) pUndoColl.reset(new ScDBCollection(*pDocColl)); - std::unique_ptr pNew(new ScDBData(rName, rRange.aStart.Tab(), rRange.aStart.Col(), - rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), - true, bHeader, false, u""_ustr, rStyleName)); - if (pNew) + // If a database range already covers exactly this area, reuse it and + // promote it into a table rather than layering a second, overlapping + // range on top. + ScDBData* pExisting = pDocColl->GetDBAtArea(rRange.aStart.Tab(), rRange.aStart.Col(), + rRange.aStart.Row(), rRange.aEnd.Col(), + rRange.aEnd.Row()); + + // The exact range is already a styled table; don't create a duplicate. + if (pExisting && pExisting->GetTableStyleInfo()) { - pNew->SetAutoFilter(true); + if (!bApi) + rDocShell.ErrorMessage(STR_TABLE_ERR_ADD); + return false; + } + + bool bReuseNamed + = pExisting + && pDocColl->getNamedDBs().findByPointer(pExisting) != pDocColl->getNamedDBs().end(); + bool bReuseAnon + = pExisting && !bReuseNamed && rDoc.GetAnonymousDBData(rRange.aStart.Tab()) == pExisting; + + ScTableStyleParam aStyleParam; + aStyleParam.maStyleID = rStyleName; + + bool bOk = true; + + if (bReuseNamed) + { + pExisting->SetHeader(bHeader); + pExisting->SetAutoFilter(true); + pExisting->SetTableStyleInfo(aStyleParam); rDoc.ApplyFlagsTab(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aStart.Row(), rRange.aStart.Tab(), ScMF::Auto); } + else + { + std::unique_ptr pNew; + if (bReuseAnon) + { + // Migrate the anonymous range into the named range + pNew.reset(new ScDBData(rName, *pExisting)); + pNew->SetHeader(bHeader); + pNew->SetTableStyleInfo(aStyleParam); + } + else + { + pNew.reset(new ScDBData(rName, rRange.aStart.Tab(), rRange.aStart.Col(), + rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), + true, bHeader, false, u""_ustr, rStyleName)); + } + pNew->SetAutoFilter(true); + rDoc.ApplyFlagsTab(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), + rRange.aStart.Row(), rRange.aStart.Tab(), ScMF::Auto); - bool bCompile = !rDoc.IsImportingXML(); - if (bCompile) - rDoc.PreprocessDBDataUpdate(); + if (bReuseAnon) + rDoc.SetAnonymousDBData(rRange.aStart.Tab(), nullptr); - bool bOk = pDocColl->getNamedDBs().insert(std::move(pNew)); - if (bCompile) - rDoc.CompileHybridFormula(); + bool bCompile = !rDoc.IsImportingXML(); + if (bCompile) + rDoc.PreprocessDBDataUpdate(); + + bOk = pDocColl->getNamedDBs().insert(std::move(pNew)); + if (bCompile) + rDoc.CompileHybridFormula(); + } if (!bOk && !bApi) { @@ -524,9 +573,9 @@ bool ScDBDocFunc::RepeatDB( const OUString& rDBName, bool bApi, bool bIsUnnamed, rDoc.CopyToDocument(0, 0, 0, rDoc.MaxCol(), rDoc.MaxRow(), nTabCount-1, InsertDeleteFlags::FORMULA, false, *pUndoDoc); // ranges of DB and other - ScRangeName* pDocRange = rDoc.GetRangeName(); - if (!pDocRange->empty()) - pUndoRange.reset(new ScRangeName( *pDocRange )); + ScRangeName& rDocRange = rDoc.GetRangeName(); + if (!rDocRange.empty()) + pUndoRange.reset(new ScRangeName( rDocRange )); ScDBCollection* pDocDB = rDoc.GetDBCollection(); if (!pDocDB->empty()) pUndoDB.reset(new ScDBCollection( *pDocDB )); @@ -543,7 +592,7 @@ bool ScDBDocFunc::RepeatDB( const OUString& rDBName, bool bApi, bool bIsUnnamed, if (bSort) { pDBData->GetSortParam( aSortParam ); // range may have changed - (void)Sort( nTab, aSortParam, false, false, bApi ); + (void)SortTab( nTab, aSortParam, false, false, bApi ); } if (bQuery) { @@ -609,757 +658,24 @@ bool ScDBDocFunc::RepeatDB( const OUString& rDBName, bool bApi, bool bIsUnnamed, return bDone; } -bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam, - bool bRecord, bool bPaint, bool bApi ) +bool ScDBDocFunc::SortTab(SCTAB nTab, const ScSortParam& rSortParam, bool bRecord, bool bPaint, bool bApi) { - ScDocShellModificator aModificator( rDocShell ); - - ScDocument& rDoc = rDocShell.GetDocument(); - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1, - rSortParam.nCol2, rSortParam.nRow2 ); - if (!pDBData) - { - OSL_FAIL( "Sort: no DBData" ); - return false; - } - - bool bCopy = !rSortParam.bInplace; - if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 && - rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab ) - bCopy = false; - - ScSortParam aLocalParam( rSortParam ); - if ( bCopy ) - { - // Copy the data range to the destination then move the sort range to it. - ScRange aSrcRange(rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab); - ScAddress aDestPos(rSortParam.nDestCol,rSortParam.nDestRow,rSortParam.nDestTab); - - ScDocFunc& rDocFunc = rDocShell.GetDocFunc(); - bool bRet = rDocFunc.MoveBlock(aSrcRange, aDestPos, false, bRecord, bPaint, bApi); - - if (!bRet) - return false; - - aLocalParam.MoveToDest(); - nTab = aLocalParam.nDestTab; - } - - // tdf#119804: If there is a header row/column, it won't be affected by - // sorting; so we can exclude it from the test. - SCROW nStartingRowToEdit = aLocalParam.nRow1; - SCCOL nStartingColToEdit = aLocalParam.nCol1; - if ( aLocalParam.bHasHeader ) - { - if ( aLocalParam.bByRow ) - nStartingRowToEdit++; - else - nStartingColToEdit++; - } - - if (!CheckSheetViewProtection(sc::Operation::Sort)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( - rDoc, nTab, nStartingColToEdit, nStartingRowToEdit, - aLocalParam.nCol2, aLocalParam.nRow2, true /*bNoMatrixAtAll*/); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - const ScInputOptions aInputOption = ScModule::get()->GetInputOptions(); - const bool bUpdateRefs = aInputOption.GetSortRefUpdate(); - - // Adjust aLocalParam cols/rows to used data area. Keep sticky top row or - // column (depending on direction) in any case, not just if it has headers, - // so empty leading cells will be sorted to the end. - // aLocalParam.nCol/Row will encompass data content only, extras in - // aLocalParam.aDataAreaExtras. - bool bShrunk = false; - aLocalParam.aDataAreaExtras.resetArea(); - rDoc.ShrinkToUsedDataArea(bShrunk, nTab, aLocalParam.nCol1, aLocalParam.nRow1, - aLocalParam.nCol2, aLocalParam.nRow2, false, aLocalParam.bByRow, - !aLocalParam.bByRow, - (aLocalParam.aDataAreaExtras.anyExtrasWanted() ? - &aLocalParam.aDataAreaExtras : nullptr)); - - SCROW nStartRow = aLocalParam.nRow1; - if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < aLocalParam.nRow2) - ++nStartRow; - - SCCOL nOverallCol1 = aLocalParam.nCol1; - SCROW nOverallRow1 = aLocalParam.nRow1; - SCCOL nOverallCol2 = aLocalParam.nCol2; - SCROW nOverallRow2 = aLocalParam.nRow2; - if (aLocalParam.aDataAreaExtras.anyExtrasWanted()) - { - // Trailing empty excess columns/rows are excluded from being sorted, - // they stick at the end. Clip them. - const ScDataAreaExtras::Clip eClip = (aLocalParam.bByRow ? - ScDataAreaExtras::Clip::Row : ScDataAreaExtras::Clip::Col); - aLocalParam.aDataAreaExtras.GetOverallRange( nOverallCol1, nOverallRow1, nOverallCol2, nOverallRow2, eClip); - // Make it permanent. - aLocalParam.aDataAreaExtras.SetOverallRange( nOverallCol1, nOverallRow1, nOverallCol2, nOverallRow2); - - if (bUpdateRefs) - { - // With update references the entire range needs to be handled as - // one entity for references pointing within to be moved along, - // even when there's no data content. For huge ranges we may be - // DOOMed then. - aLocalParam.nCol1 = nOverallCol1; - aLocalParam.nRow1 = nOverallRow1; - aLocalParam.nCol2 = nOverallCol2; - aLocalParam.nRow2 = nOverallRow2; - } - } - - if (aLocalParam.aDataAreaExtras.mbCellFormats - && rDoc.HasAttrib( nOverallCol1, nStartRow, nTab, nOverallCol2, nOverallRow2, nTab, - HasAttrFlags::Merged | HasAttrFlags::Overlapped)) - { - // Merge attributes would be mixed up during sorting. - if (!bApi) - rDocShell.ErrorMessage(STR_SORT_ERR_MERGED); - return false; - } - - // execute - - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - // Calculate the script types for all cells in the sort range beforehand. - // This will speed up the row height adjustment that takes place after the - // sort. - rDoc.UpdateScriptTypes( - ScAddress(aLocalParam.nCol1,nStartRow,nTab), - aLocalParam.nCol2-aLocalParam.nCol1+1, - aLocalParam.nRow2-nStartRow+1); - - // No point adjusting row heights after the sort when all rows have the same height. - bool bUniformRowHeight = rDoc.HasUniformRowHeight(nTab, nStartRow, nOverallRow2); - - bool bRepeatQuery = false; // repeat existing filter? - ScQueryParam aQueryParam; - pDBData->GetQueryParam( aQueryParam ); - if ( aQueryParam.GetEntry(0).bDoQuery ) - bRepeatQuery = true; - - sc::ReorderParam aUndoParam; - - // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set), - // but always call it for random shuffle which doesn't need sort keys - if (aLocalParam.meSortOrderType == SortOrderType::Random - || (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)) - { - ScProgress aProgress(&rDocShell, ScResId(STR_PROGRESS_SORTING), 0, true); - if (!bRepeatQuery) - bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, aLocalParam.nRow2, nTab); - rDoc.Sort(nTab, aLocalParam, bRepeatQuery, bUpdateRefs, &aProgress, &aUndoParam); - } - - if (bRecord) - { - // Set up an undo object. - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique(rDocShell, aUndoParam)); - } - - ScSortParam aSortParamData(rSortParam); - aSortParamData.meSortOrderType = SortOrderType::Ordered; - pDBData->SetSortParam(aSortParamData); - // Remember additional settings on anonymous database ranges. - if (pDBData == rDoc.GetAnonymousDBData( nTab) || rDoc.GetDBCollection()->getAnonDBs().has( pDBData)) - pDBData->UpdateFromSortParam(aSortParamData); - - if (SfxViewShell* pKitSomeViewForThisDoc = comphelper::LibreOfficeKit::isActive() ? - rDocShell.GetBestViewShell(false) : nullptr) - { - SfxViewShell* pViewShell = SfxViewShell::GetFirst(); - while (pViewShell) - { - ScTabViewShell* pTabViewShell = dynamic_cast(pViewShell); - if (pTabViewShell && pTabViewShell->GetDocId() == pKitSomeViewForThisDoc->GetDocId()) - { - if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nTab)) - pPosHelper->invalidateByIndex(nStartRow); - } - pViewShell = SfxViewShell::GetNext(*pViewShell); - } - - ScTabViewShell::notifyAllViewsSheetGeomInvalidation( - pKitSomeViewForThisDoc, false /* bColumns */, true /* bRows */, true /* bSizes*/, - true /* bHidden */, true /* bFiltered */, true /* bGroups */, nTab); - } - - if (nStartRow <= aLocalParam.nRow2) - { - ScRange aDirtyRange( - aLocalParam.nCol1, nStartRow, nTab, - aLocalParam.nCol2, aLocalParam.nRow2, nTab); - rDoc.SetDirty( aDirtyRange, true ); - } - - if (bPaint) - { - PaintPartFlags nPaint = PaintPartFlags::Grid; - SCCOL nStartX = nOverallCol1; - SCROW nStartY = nOverallRow1; - SCCOL nEndX = nOverallCol2; - SCROW nEndY = nOverallRow2; - if ( bRepeatQuery ) - { - nPaint |= PaintPartFlags::Left; - nStartX = 0; - nEndX = rDoc.MaxCol(); - } - rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint); - } - - if (!bUniformRowHeight && nStartRow <= nOverallRow2) - rDocShell.AdjustRowHeight(nStartRow, nOverallRow2, nTab); - - aModificator.SetDocumentModified(); - - return true; + sc::SortOperation aOperation(rDocShell, nTab, rSortParam, bRecord, bPaint, bApi); + return aOperation.run(); } bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam, const ScRange* pAdvSource, bool bRecord, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - ScDocument& rDoc = rDocShell.GetDocument(); - - ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); - if (pViewSh && ScTabViewShell::isAnyEditViewInRange(pViewSh, /*bColumns*/ false, rQueryParam.nRow1, rQueryParam.nRow2)) - { - return false; - } - - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rQueryParam.nCol1, rQueryParam.nRow1, - rQueryParam.nCol2, rQueryParam.nRow2 ); - if (!pDBData) - { - OSL_FAIL( "Query: no DBData" ); - return false; - } - - // Change from Inplace to non-Inplace, only then cancel Inplace: - // (only if "Persistent" is selected in the dialog) - - if ( !rQueryParam.bInplace && pDBData->HasQueryParam() && rQueryParam.bDestPers ) - { - ScQueryParam aOldQuery; - pDBData->GetQueryParam(aOldQuery); - if (aOldQuery.bInplace) - { - // cancel old filtering - - SCSIZE nEC = aOldQuery.GetEntryCount(); - for (SCSIZE i=0; iGetArea( aOldDest ); - aDestTotal=ScRange( rQueryParam.nDestCol, - rQueryParam.nDestRow, - nDestTab, - rQueryParam.nDestCol + rQueryParam.nCol2 - rQueryParam.nCol1, - rQueryParam.nDestRow + rQueryParam.nRow2 - rQueryParam.nRow1, - nDestTab ); - - bDoSize = pDestData->IsDoSize(); - // test if formulas need to be filled in (nFormulaCols): - if ( bDoSize && aOldDest.aEnd.Col() == aDestTotal.aEnd.Col() ) - { - SCCOL nTestCol = aOldDest.aEnd.Col() + 1; // next to the range - SCROW nTestRow = rQueryParam.nDestRow + - ( aLocalParam.bHasHeader ? 1 : 0 ); - while ( nTestCol <= rDoc.MaxCol() && - rDoc.GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA ) - { - ++nTestCol; - ++nFormulaCols; - } - } - - bKeepFmt = pDestData->IsKeepFmt(); - if ( bDoSize && !rDoc.CanFitBlock( aOldDest, aDestTotal ) ) - { - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); // cannot insert rows - return false; - } - } - } - - // execute - - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - bool bKeepSub = false; // repeat existing partial results? - bool bKeepTotals = false; - if (rQueryParam.GetEntry(0).bDoQuery) // not at cancellation - { - ScSubTotalParam aSubTotalParam; - pDBData->GetSubTotalParam( aSubTotalParam ); // partial results exist? - - if (aSubTotalParam.aGroups[0].bActive && !aSubTotalParam.bRemoveOnly) - bKeepSub = true; - - if (pDBData->HasTotals() && pDBData->GetTableStyleInfo()) - bKeepTotals = true; - } - - ScDocumentUniquePtr pUndoDoc; - std::unique_ptr pUndoDB; - const ScRange* pOld = nullptr; - - if ( bRecord ) - { - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - if (bCopy) - { - pUndoDoc->InitUndo( rDoc, nDestTab, nDestTab, false, true ); - rDoc.CopyToDocument(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, - aLocalParam.nCol2, aLocalParam.nRow2, nDestTab, - InsertDeleteFlags::ALL, false, *pUndoDoc); - // secure attributes in case they were copied along - - if (pDestData) - { - rDoc.CopyToDocument(aOldDest, InsertDeleteFlags::ALL, false, *pUndoDoc); - pOld = &aOldDest; - } - } - else - { - pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true ); - rDoc.CopyToDocument(0, rQueryParam.nRow1, nTab, rDoc.MaxCol(), rQueryParam.nRow2, nTab, - InsertDeleteFlags::NONE, false, *pUndoDoc); - } - - ScDBCollection* pDocDB = rDoc.GetDBCollection(); - if (!pDocDB->empty()) - pUndoDB.reset(new ScDBCollection( *pDocDB )); - - rDoc.BeginDrawUndo(); - } - - std::unique_ptr pAttribDoc; - ScRange aAttribRange; - if (pDestData) // delete destination range - { - if ( bKeepFmt ) - { - // smaller of the end columns, header+1 row - aAttribRange = aOldDest; - if ( aAttribRange.aEnd.Col() > aDestTotal.aEnd.Col() ) - aAttribRange.aEnd.SetCol( aDestTotal.aEnd.Col() ); - aAttribRange.aEnd.SetRow( aAttribRange.aStart.Row() + - ( aLocalParam.bHasHeader ? 1 : 0 ) ); - - // also for filled-in formulas - aAttribRange.aEnd.SetCol( aAttribRange.aEnd.Col() + nFormulaCols ); - - pAttribDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pAttribDoc->InitUndo( rDoc, nDestTab, nDestTab, false, true ); - rDoc.CopyToDocument(aAttribRange, InsertDeleteFlags::ATTRIB, false, *pAttribDoc); - } - - if ( bDoSize ) - rDoc.FitBlock( aOldDest, aDestTotal ); - else - rDoc.DeleteAreaTab(aOldDest, InsertDeleteFlags::ALL); // simply delete - } - - // execute filtering on the document - SCSIZE nCount = rDoc.Query( nTab, rQueryParam, bKeepSub, bKeepTotals ); - pDBData->CalcSaveFilteredCount( nCount ); - if (bCopy) - { - aLocalParam.nRow2 = aLocalParam.nRow1 + nCount; - if (!aLocalParam.bHasHeader && nCount > 0) - --aLocalParam.nRow2; - - if ( bDoSize ) - { - // adjust to the real result range - // (this here is always a reduction) - - ScRange aNewDest( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, - aLocalParam.nCol2, aLocalParam.nRow2, nDestTab ); - rDoc.FitBlock( aDestTotal, aNewDest, false ); // sal_False - don't delete - - if ( nFormulaCols > 0 ) - { - // fill in formulas - //! Undo (Query and Repeat) !!! - - ScRange aNewForm( aLocalParam.nCol2+1, aLocalParam.nRow1, nDestTab, - aLocalParam.nCol2+nFormulaCols, aLocalParam.nRow2, nDestTab ); - ScRange aOldForm = aNewForm; - aOldForm.aEnd.SetRow( aOldDest.aEnd.Row() ); - rDoc.FitBlock( aOldForm, aNewForm, false ); - - ScMarkData aMark(rDoc.GetSheetLimits()); - aMark.SelectOneTable(nDestTab); - SCROW nFStartY = aLocalParam.nRow1 + ( aLocalParam.bHasHeader ? 1 : 0 ); - - sal_uLong nProgCount = nFormulaCols; - nProgCount *= aLocalParam.nRow2 - nFStartY; - ScProgress aProgress( rDoc.GetDocumentShell(), - ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true ); - - rDoc.Fill( aLocalParam.nCol2+1, nFStartY, - aLocalParam.nCol2+nFormulaCols, nFStartY, &aProgress, aMark, - aLocalParam.nRow2 - nFStartY, - FILL_TO_BOTTOM, FILL_SIMPLE ); - } - } - - if ( pAttribDoc ) // copy back the memorized attributes - { - // Header - if (aLocalParam.bHasHeader) - { - ScRange aHdrRange = aAttribRange; - aHdrRange.aEnd.SetRow( aHdrRange.aStart.Row() ); - pAttribDoc->CopyToDocument(aHdrRange, InsertDeleteFlags::ATTRIB, false, rDoc); - } - - // Data - SCCOL nAttrEndCol = aAttribRange.aEnd.Col(); - SCROW nAttrRow = aAttribRange.aStart.Row() + ( aLocalParam.bHasHeader ? 1 : 0 ); - for (SCCOL nCol = aAttribRange.aStart.Col(); nCol<=nAttrEndCol; nCol++) - { - const ScPatternAttr* pSrcPattern = pAttribDoc->GetPattern( - nCol, nAttrRow, nDestTab ); - OSL_ENSURE(pSrcPattern,"Pattern is 0"); - if (pSrcPattern) - { - rDoc.ApplyPatternAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2, - nDestTab, *pSrcPattern ); - const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet(); - if (pStyle) - rDoc.ApplyStyleAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2, - nDestTab, *pStyle ); - } - } - } - } - - // saving: Inplace always, otherwise depending on setting - // old Inplace-Filter may have already been removed - - bool bSave = rQueryParam.bInplace || rQueryParam.bDestPers; - if (bSave) // memorize - { - pDBData->SetQueryParam( rQueryParam ); - pDBData->SetHeader( rQueryParam.bHasHeader ); //! ??? - pDBData->SetAdvancedQuerySource( pAdvSource ); // after SetQueryParam - } - - if (bCopy) // memorize new DB range - { - // Selection is done afterwards from outside (dbfunc). - // Currently through the DB area at the destination position, - // so a range must be created there in any case. - - ScDBData* pNewData; - if (pDestData) - pNewData = pDestData; // range exists -> adjust (always!) - else // create range - pNewData = rDocShell.GetDBData( - ScRange( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, - aLocalParam.nCol2, aLocalParam.nRow2, nDestTab ), - SC_DB_MAKE, ScGetDBSelection::ForceMark ); - - if (pNewData) - { - pNewData->SetArea( nDestTab, aLocalParam.nCol1, aLocalParam.nRow1, - aLocalParam.nCol2, aLocalParam.nRow2 ); - - // query parameter is no longer set at the destination, only leads to confusion - // and mistakes with the query parameter at the source range (#37187#) - } - else - { - OSL_FAIL("Target are not available"); - } - } - - if (!bCopy) - { - rDoc.InvalidatePageBreaks(nTab); - rDoc.UpdatePageBreaks( nTab ); - } - - // #i23299# Subtotal functions depend on cell's filtered states. - ScRange aDirtyRange(0 , aLocalParam.nRow1, nDestTab, rDoc.MaxCol(), aLocalParam.nRow2, nDestTab); - rDoc.SetSubTotalCellsDirty(aDirtyRange); - - if ( bRecord ) - { - // create undo action after executing, because of drawing layer undo - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, nTab, rQueryParam, std::move(pUndoDoc), std::move(pUndoDB), - pOld, bDoSize, pAdvSource ) ); - } - - if ( pViewSh ) - { - // could there be horizontal autofilter ? - // maybe it would be better to set bColumns to !rQueryParam.bByRow ? - // anyway at the beginning the value of bByRow is 'false' - // then after the first sort action it becomes 'true' - pViewSh->OnLOKShowHideColRow(/*bColumns*/ false, rQueryParam.nRow1 - 1); - } - - if (bCopy) - { - SCCOL nEndX = aLocalParam.nCol2; - SCROW nEndY = aLocalParam.nRow2; - if (pDestData) - { - if ( aOldDest.aEnd.Col() > nEndX ) - nEndX = aOldDest.aEnd.Col(); - if ( aOldDest.aEnd.Row() > nEndY ) - nEndY = aOldDest.aEnd.Row(); - } - if (bDoSize) - nEndY = rDoc.MaxRow(); - - // remove AutoFilter button flags - rDocShell.DBAreaDeleted(nDestTab, aLocalParam.nCol1, aLocalParam.nRow1, aLocalParam.nCol2); - - rDocShell.PostPaint( - ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, nEndX, nEndY, nDestTab), - PaintPartFlags::Grid); - } - else - rDocShell.PostPaint( - ScRange(0, rQueryParam.nRow1, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab), - PaintPartFlags::Grid | PaintPartFlags::Left); - aModificator.SetDocumentModified(); - - return true; + sc::QueryOperation aOperation(rDocShell, nTab, rQueryParam, pAdvSource, bRecord, bApi); + return aOperation.run(); } void ScDBDocFunc::DoSubTotals( SCTAB nTab, const ScSubTotalParam& rParam, bool bRecord, bool bApi ) { - //! use also for ScDBFunc::DoSubTotals ! - // then stays outside: - // - mark new range (from DBData) - // - SelectionChanged (?) - - bool bDo = !rParam.bRemoveOnly; // sal_False = only delete - - ScDocument& rDoc = rDocShell.GetDocument(); - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1, - rParam.nCol2, rParam.nRow2 ); - if (!pDBData) - { - OSL_FAIL( "SubTotals: no DBData" ); - return; - } - - if (!CheckSheetViewProtection(sc::Operation::SubTotals)) - return; - - ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(rDoc, nTab, 0, rParam.nRow1 + 1, rDoc.MaxCol(), rDoc.MaxRow()); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return; - } - - if (rDoc.HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab, - rParam.nCol2, rParam.nRow2, nTab, HasAttrFlags::Merged | HasAttrFlags::Overlapped )) - { - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); // don't insert into merged - return; - } - - bool bOk = true; - if (rParam.bReplace) - { - if (rDoc.TestRemoveSubTotals( nTab, rParam )) - { - std::unique_ptr xBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(), - VclMessageType::Question, - VclButtonsType::YesNo, ScResId(STR_MSSG_DOSUBTOTALS_1))); // "Delete Data?" - xBox->set_title(ScResId(STR_MSSG_DOSUBTOTALS_0)); // "StarCalc" - bOk = xBox->run() == RET_YES; - } - } - - if (!bOk) - return; - - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - ScDocShellModificator aModificator( rDocShell ); - - ScSubTotalParam aNewParam( rParam ); // end of range is being changed - ScDocumentUniquePtr pUndoDoc; - std::unique_ptr pUndoTab; - std::unique_ptr pUndoRange; - std::unique_ptr pUndoDB; - - if (bRecord) // secure old data - { - bool bOldFilter = bDo && rParam.bDoSort; - - SCTAB nTabCount = rDoc.GetTableCount(); - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab ); - if (pTable) - { - pUndoTab.reset(new ScOutlineTable( *pTable )); - - // column/row state - SCCOLROW nOutStartCol, nOutEndCol; - SCCOLROW nOutStartRow, nOutEndRow; - pTable->GetColArray().GetRange( nOutStartCol, nOutEndCol ); - pTable->GetRowArray().GetRange( nOutStartRow, nOutEndRow ); - - pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true ); - rDoc.CopyToDocument(static_cast(nOutStartCol), 0, nTab, static_cast(nOutEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); - rDoc.CopyToDocument(0, nOutStartRow, nTab, rDoc.MaxCol(), nOutEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); - } - else - pUndoDoc->InitUndo( rDoc, nTab, nTab, false, bOldFilter ); - - // secure data range - incl. filtering result - rDoc.CopyToDocument(0, rParam.nRow1+1,nTab, rDoc.MaxCol(),rParam.nRow2,nTab, - InsertDeleteFlags::ALL, false, *pUndoDoc); - - // all formulas because of references - rDoc.CopyToDocument(0, 0, 0, rDoc.MaxCol(),rDoc.MaxRow(),nTabCount-1, - InsertDeleteFlags::FORMULA, false, *pUndoDoc); - - // ranges of DB and other - ScRangeName* pDocRange = rDoc.GetRangeName(); - if (!pDocRange->empty()) - pUndoRange.reset(new ScRangeName( *pDocRange )); - ScDBCollection* pDocDB = rDoc.GetDBCollection(); - if (!pDocDB->empty()) - pUndoDB.reset(new ScDBCollection( *pDocDB )); - } - -// rDoc.SetOutlineTable( nTab, NULL ); - ScOutlineTable* pOut = rDoc.GetOutlineTable( nTab ); - if (pOut) - pOut->GetRowArray().RemoveAll(); // only delete row outlines - - if (rParam.bReplace) - rDoc.RemoveSubTotals( nTab, aNewParam ); - bool bSuccess = true; - if (bDo) - { - // sort - if ( rParam.bDoSort ) - { - pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 ); - - // set partial result field to before the sorting - // (Duplicates are omitted, so can be called again) - - ScSortParam aOldSort; - pDBData->GetSortParam( aOldSort ); - ScSortParam aSortParam( aNewParam, aOldSort ); - Sort( nTab, aSortParam, false, false, bApi ); - } - - bSuccess = rDoc.DoSubTotals( nTab, aNewParam ); - rDoc.SetDrawPageSize(nTab); - } - ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab, - aNewParam.nCol2, aNewParam.nRow2, nTab ); - rDoc.SetDirty( aDirtyRange, true ); - - if (bRecord) - { -// ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL; - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, nTab, - rParam, aNewParam.nRow2, - std::move(pUndoDoc), std::move(pUndoTab), // pUndoDBData, - std::move(pUndoRange), std::move(pUndoDB) ) ); - } - - if (!bSuccess) - { - // "Cannot insert rows" - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); - } - - // memorize - pDBData->SetSubTotalParam( aNewParam ); - pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 ); - rDoc.CompileDBFormula(); - - rDocShell.PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab), - PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top | PaintPartFlags::Size); - aModificator.SetDocumentModified(); + sc::SubTotalsOperation aOperation(rDocShell, nTab, rParam, bRecord, bApi); + aOperation.run(); } void ScDBDocFunc::DoTableSubTotals( SCTAB nTab, const ScDBData& rNewData, const ScSubTotalParam& rParam, @@ -1464,109 +780,6 @@ void ScDBDocFunc::DoTableSubTotals( SCTAB nTab, const ScDBData& rNewData, const aModificator.SetDocumentModified(); } -namespace { - -bool lcl_EmptyExcept( ScDocument& rDoc, const ScRange& rRange, const ScRange& rExcept ) -{ - ScCellIterator aIter( rDoc, rRange ); - for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next()) - { - if (!aIter.isEmpty()) // real content? - { - if (!rExcept.Contains(aIter.GetPos())) - return false; // cell found - } - } - - return true; // nothing found - empty -} - -bool isEditable(ScDocShell& rDocShell, const ScRangeList& rRanges, bool bApi, - sc::EditAction eAction = sc::EditAction::Unknown) -{ - ScDocument& rDoc = rDocShell.GetDocument(); - if (!rDocShell.IsEditable() || rDoc.GetChangeTrack()) - { - // not recorded -> disallow - if (!bApi) - rDocShell.ErrorMessage(STR_PROTECTIONERR); - - return false; - } - - for (size_t i = 0, n = rRanges.size(); i < n; ++i) - { - const ScRange & r = rRanges[i]; - ScEditableTester aTester = ScEditableTester::CreateAndTestRange(rDoc, r, eAction); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - - return false; - } - } - - return true; -} - -void createUndoDoc(ScDocumentUniquePtr& pUndoDoc, ScDocument& rDoc, const ScRange& rRange) -{ - SCTAB nTab = rRange.aStart.Tab(); - pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); - pUndoDoc->InitUndo(rDoc, nTab, nTab); - rDoc.CopyToDocument(rRange, InsertDeleteFlags::ALL, false, *pUndoDoc); -} - -bool checkNewOutputRange(ScDPObject& rDPObj, ScDocShell& rDocShell, ScRange& rNewOut, bool bApi, - sc::EditAction eAction = sc::EditAction::Unknown) -{ - ScDocument& rDoc = rDocShell.GetDocument(); - - bool bOverflow = false; - rNewOut = rDPObj.GetNewOutputRange(bOverflow); - - // Test for overlap with source data range. - // TODO: Check with other pivot tables as well. - const ScSheetSourceDesc* pSheetDesc = rDPObj.GetSheetDesc(); - if (pSheetDesc && pSheetDesc->GetSourceRange().Intersects(rNewOut)) - { - // New output range intersteps with the source data. Move it up to - // where the old range is and see if that works. - ScRange aOldRange = rDPObj.GetOutRange(); - SCROW nDiff = aOldRange.aStart.Row() - rNewOut.aStart.Row(); - rNewOut.aStart.SetRow(aOldRange.aStart.Row()); - rNewOut.aEnd.IncRow(nDiff); - if (!rDoc.ValidRow(rNewOut.aStart.Row()) || !rDoc.ValidRow(rNewOut.aEnd.Row())) - bOverflow = true; - } - - if (bOverflow) - { - if (!bApi) - rDocShell.ErrorMessage(STR_PIVOT_ERROR); - - return false; - } - - if (!rDoc.IsImportingXML()) - { - ScEditableTester aTester = ScEditableTester::CreateAndTestRange(rDoc, rNewOut, eAction); - if (!aTester.IsEditable()) - { - // destination area isn't editable - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - - return false; - } - } - - return true; -} - -} - bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj, bool bRecord, bool bApi, bool bAllowMove ) { @@ -1575,379 +788,43 @@ bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb if (!pNewObj) return false; - return CreatePivotTable(*pNewObj, bRecord, bApi); + sc::CreatePivotTableOperation aOperation(rDocShell, *pNewObj, bRecord, bApi); + return aOperation.run(); } if (!pNewObj) - return RemovePivotTable(*pOldObj, bRecord, bApi); + { + sc::RemovePivotTableOperation aOperation(rDocShell, *pOldObj, bRecord, bApi); + return aOperation.run(); + } if (pOldObj == pNewObj) - return UpdatePivotTable(*pOldObj, bRecord, bApi); - - OSL_ASSERT(pOldObj && pNewObj && pOldObj != pNewObj); - - ScDocShellModificator aModificator( rDocShell ); - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - ScRangeList aRanges; - aRanges.push_back(pOldObj->GetOutRange()); - aRanges.push_back(ScRange(pNewObj->GetOutRange().aStart)); // at least one cell in the output position must be editable. - - if (!CheckSheetViewProtection(sc::Operation::PivotTableUpdate)) - return false; - - if (!isEditable(rDocShell, aRanges, bApi)) - return false; - - ScDocumentUniquePtr pOldUndoDoc; - ScDocumentUniquePtr pNewUndoDoc; - - ScDPObject aUndoDPObj(*pOldObj); // for undo or revert on failure - - ScDocument& rDoc = rDocShell.GetDocument(); - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - if (bRecord) - createUndoDoc(pOldUndoDoc, rDoc, pOldObj->GetOutRange()); - - pNewObj->WriteSourceDataTo(*pOldObj); // copy source data - - ScDPSaveData* pData = pNewObj->GetSaveData(); - OSL_ENSURE( pData, "no SaveData from living DPObject" ); - if (pData) - pOldObj->SetSaveData(*pData); // copy SaveData - - pOldObj->SetAllowMove(bAllowMove); - pOldObj->ReloadGroupTableData(); - pOldObj->SyncAllDimensionMembers(); - pOldObj->InvalidateData(); // before getting the new output area - - // make sure the table has a name (not set by dialog) - if (pOldObj->GetName().isEmpty()) - pOldObj->SetName( rDoc.GetDPCollection()->CreateNewName() ); - - ScRange aNewOut; - if (!checkNewOutputRange(*pOldObj, rDocShell, aNewOut, bApi)) { - *pOldObj = aUndoDPObj; - return false; + sc::UpdatePivotTableOperation aOperation(rDocShell, *pOldObj, bRecord, bApi); + return aOperation.run(); } - // test if new output area is empty except for old area - if (!bApi) - { - // OutRange of pOldObj (pDestObj) is still old area - if (!lcl_EmptyExcept(rDoc, aNewOut, pOldObj->GetOutRange())) - { - std::unique_ptr xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(), - VclMessageType::Question, VclButtonsType::YesNo, - ScResId(STR_PIVOT_NOTEMPTY))); - xQueryBox->set_default_response(RET_YES); - if (xQueryBox->run() == RET_NO) - { - //! like above (not editable) - *pOldObj = aUndoDPObj; - return false; - } - } - } - - if (bRecord) - createUndoDoc(pNewUndoDoc, rDoc, aNewOut); - - pOldObj->Output(aNewOut.aStart); - rDocShell.PostPaintGridAll(); //! only necessary parts - - if (bRecord) - { - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( - rDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObj, pOldObj, bAllowMove)); - } - - // notify API objects - rDoc.BroadcastUno( ScDataPilotModifiedHint(pOldObj->GetName()) ); - aModificator.SetDocumentModified(); - - return true; + sc::ReplacePivotTableOperation aOperation(rDocShell, pOldObj, pNewObj, bRecord, bApi, + bAllowMove); + return aOperation.run(); } bool ScDBDocFunc::RemovePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi) { - ScDocShellModificator aModificator(rDocShell); - weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); - - if (!CheckSheetViewProtection(sc::Operation::PivotTableRemove)) - return false; - - if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi)) - return false; - - ScDocument& rDoc = rDocShell.GetDocument(); - - if (!bApi) - { - // If we come from GUI - ask to delete the associated pivot charts too... - std::vector aListOfObjects = - sctools::getAllPivotChartsConnectedTo(rDPObj.GetName(), rDocShell); - - ScDrawLayer* pModel = rDoc.GetDrawLayer(); - - if (pModel && !aListOfObjects.empty()) - { - std::unique_ptr xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(), - VclMessageType::Question, VclButtonsType::YesNo, - ScResId(STR_PIVOT_REMOVE_PIVOTCHART))); - xQueryBox->set_default_response(RET_YES); - if (xQueryBox->run() == RET_NO) - { - return false; - } - else - { - for (SdrOle2Obj* pChartObject : aListOfObjects) - { - rDoc.GetChartListenerCollection()->removeByName(pChartObject->GetName()); - pModel->AddUndo(std::make_unique(*pChartObject)); - pChartObject->getSdrPageFromSdrObject()->RemoveObject(pChartObject->GetOrdNum()); - } - } - } - } - - ScDocumentUniquePtr pOldUndoDoc; - std::unique_ptr pUndoDPObj; - - if (bRecord) - pUndoDPObj.reset(new ScDPObject(rDPObj)); // copy old settings for undo - - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - // delete table - - ScRange aRange = rDPObj.GetOutRange(); - SCTAB nTab = aRange.aStart.Tab(); - - if (bRecord) - createUndoDoc(pOldUndoDoc, rDoc, aRange); - - rDoc.DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(), - aRange.aEnd.Col(), aRange.aEnd.Row(), - nTab, InsertDeleteFlags::ALL ); - rDoc.RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(), - aRange.aEnd.Col(), aRange.aEnd.Row(), - nTab, ScMF::Auto ); - - rDoc.GetDPCollection()->FreeTable(&rDPObj); // object is deleted here - - rDocShell.PostPaintGridAll(); //! only necessary parts - rDocShell.PostPaint(aRange, PaintPartFlags::Grid); - - if (bRecord) - { - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( - rDocShell, std::move(pOldUndoDoc), nullptr, pUndoDPObj.get(), nullptr, false)); - - // pUndoDPObj is copied - } - - aModificator.SetDocumentModified(); - return true; + sc::RemovePivotTableOperation aOperation(rDocShell, rDPObj, bRecord, bApi); + return aOperation.run(); } bool ScDBDocFunc::CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi) { - ScDocShellModificator aModificator(rDocShell); - weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); - - if (!CheckSheetViewProtection(sc::Operation::PivotTableCreate)) - return false; - - // At least one cell in the output range should be editable. Check in advance. - ScDocument& rDoc = rDocShell.GetDocument(); - if (!rDoc.IsImportingXML() && !isEditable(rDocShell, ScRange(rDPObj.GetOutRange().aStart), bApi)) - return false; - - ScDocumentUniquePtr pNewUndoDoc; - - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - // output range must be set at pNewObj - std::unique_ptr pDestObj(new ScDPObject(rDPObj)); - - ScDPObject& rDestObj = *pDestObj; - - // #i94570# When changing the output position in the dialog, a new table is created - // with the settings from the old table, including the name. - // So we have to check for duplicate names here (before inserting). - if (rDoc.GetDPCollection()->GetByName(rDestObj.GetName())) - rDestObj.SetName(OUString()); // ignore the invalid name, create a new name below - - // Synchronize groups between linked tables - { - const ScDPDimensionSaveData* pGroups = nullptr; - bool bRefFound = rDoc.GetDPCollection()->GetReferenceGroups(rDestObj, &pGroups); - if (bRefFound) - { - ScDPSaveData* pSaveData = rDestObj.GetSaveData(); - if (pSaveData) - pSaveData->SetDimensionData(pGroups); - } - } - - rDoc.GetDPCollection()->InsertNewTable(std::move(pDestObj)); - - rDestObj.ReloadGroupTableData(); - rDestObj.SyncAllDimensionMembers(); - rDestObj.InvalidateData(); // before getting the new output area - - // make sure the table has a name (not set by dialog) - if (rDestObj.GetName().isEmpty()) - rDestObj.SetName(rDoc.GetDPCollection()->CreateNewName()); - - bool bOverflow = false; - ScRange aNewOut = rDestObj.GetNewOutputRange(bOverflow); - - if (bOverflow) - { - if (!bApi) - rDocShell.ErrorMessage(STR_PIVOT_ERROR); - - return false; - } - - if (!rDoc.IsImportingXML()) - { - ScEditableTester aTester = ScEditableTester::CreateAndTestRange(rDoc, aNewOut, sc::EditAction::Unknown); - if (!aTester.IsEditable()) - { - // destination area isn't editable - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - - return false; - } - } - - // test if new output area is empty except for old area - if (!bApi) - { - bool bEmpty = rDoc.IsBlockEmpty( - aNewOut.aStart.Col(), aNewOut.aStart.Row(), - aNewOut.aEnd.Col(), aNewOut.aEnd.Row(), aNewOut.aStart.Tab() ); - - if (!bEmpty) - { - std::unique_ptr xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(), - VclMessageType::Question, VclButtonsType::YesNo, - ScResId(STR_PIVOT_NOTEMPTY))); - xQueryBox->set_default_response(RET_YES); - if (xQueryBox->run() == RET_NO) - { - //! like above (not editable) - return false; - } - } - } - - if (bRecord) - createUndoDoc(pNewUndoDoc, rDoc, aNewOut); - - rDestObj.Output(aNewOut.aStart); - rDocShell.PostPaintGridAll(); //! only necessary parts - - if (bRecord) - { - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique(rDocShell, nullptr, std::move(pNewUndoDoc), nullptr, &rDestObj, false)); - } - - // notify API objects - rDoc.BroadcastUno(ScDataPilotModifiedHint(rDestObj.GetName())); - aModificator.SetDocumentModified(); - - return true; + sc::CreatePivotTableOperation aOperation(rDocShell, rDPObj, bRecord, bApi); + return aOperation.run(); } bool ScDBDocFunc::UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi) { - ScDocShellModificator aModificator( rDocShell ); - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - if (!CheckSheetViewProtection(sc::Operation::PivotTableUpdate)) - return false; - - if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi, sc::EditAction::UpdatePivotTable)) - return false; - - ScDocumentUniquePtr pOldUndoDoc; - ScDocumentUniquePtr pNewUndoDoc; - - ScDPObject aUndoDPObj(rDPObj); // For undo or revert on failure. - - ScDocument& rDoc = rDocShell.GetDocument(); - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - if (bRecord) - createUndoDoc(pOldUndoDoc, rDoc, rDPObj.GetOutRange()); - - rDPObj.SetAllowMove(false); - rDPObj.ReloadGroupTableData(); - if (!rDPObj.SyncAllDimensionMembers()) - return false; - - rDPObj.InvalidateData(); // before getting the new output area - - // make sure the table has a name (not set by dialog) - if (rDPObj.GetName().isEmpty()) - rDPObj.SetName( rDoc.GetDPCollection()->CreateNewName() ); - - ScRange aNewOut; - if (!checkNewOutputRange(rDPObj, rDocShell, aNewOut, bApi, sc::EditAction::UpdatePivotTable)) - { - rDPObj = aUndoDPObj; - return false; - } - - // test if new output area is empty except for old area - if (!bApi) - { - if (!lcl_EmptyExcept(rDoc, aNewOut, rDPObj.GetOutRange())) - { - std::unique_ptr xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(), - VclMessageType::Question, VclButtonsType::YesNo, - ScResId(STR_PIVOT_NOTEMPTY))); - xQueryBox->set_default_response(RET_YES); - if (xQueryBox->run() == RET_NO) - { - rDPObj = aUndoDPObj; - return false; - } - } - } - - if (bRecord) - createUndoDoc(pNewUndoDoc, rDoc, aNewOut); - - rDPObj.Output(aNewOut.aStart); - rDocShell.PostPaintGridAll(); //! only necessary parts - - if (bRecord) - { - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( - rDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObj, &rDPObj, false)); - } - - // notify API objects - rDoc.BroadcastUno( ScDataPilotModifiedHint(rDPObj.GetName()) ); - aModificator.SetDocumentModified(); - return true; + sc::UpdatePivotTableOperation aOperation(rDocShell, rDPObj, bRecord, bApi); + return aOperation.run(); } void ScDBDocFunc::RefreshPivotTables(const ScDPObject* pDPObj, bool bApi) diff --git a/sc/source/ui/docshell/dbdocimp.cxx b/sc/source/ui/docshell/dbdocimp.cxx index f1913bde37a0..9a810bef1f4f 100644 --- a/sc/source/ui/docshell/dbdocimp.cxx +++ b/sc/source/ui/docshell/dbdocimp.cxx @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index 923a10c70e50..d3d5892cb490 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -100,18 +100,45 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -119,14 +146,6 @@ using namespace com::sun::star; -#define AUTOFORMAT_WARN_SIZE 0x10ffffUL - -bool ScDocFunc::CheckSheetViewProtection(sc::Operation eOperation) -{ - sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData()); - return aSheetViewTester.check(eOperation); -} - void ScDocFunc::NotifyDrawUndo( std::unique_ptr pUndoAction) { // #i101118# if drawing layer collects the undo actions, add it there @@ -137,6 +156,21 @@ void ScDocFunc::NotifyDrawUndo( std::unique_ptr pUndoAction) rDocShell.GetUndoManager()->AddUndoAction( std::make_unique( std::move(pUndoAction), rDocShell ) ); rDocShell.SetDrawModified(); + // Sync sheet views for standalone drawing modifications. + // Draw operations always target the default view's page, so + // just sync the default view to the sheet views. + if (!pDrawLayer || !pDrawLayer->IsRecording()) + { + ScViewData* pViewData = ScDocShell::GetViewData(); + if (pViewData) + { + ScDocument& rDoc = rDocShell.GetDocument(); + SCTAB nCurrentTab = pViewData->GetTabNumber(); + SCTAB nDefaultTab = rDoc.GetDefaultViewTableNumber(nCurrentTab); + rDoc.SyncSheetViews(nDefaultTab); + } + } + // the affected sheet isn't known, so all stream positions are invalidated ScDocument& rDoc = rDocShell.GetDocument(); SCTAB nTabCount = rDoc.GetTableCount(); @@ -146,7 +180,7 @@ void ScDocFunc::NotifyDrawUndo( std::unique_ptr pUndoAction) // paint row above the range (because of lines after AdjustRowHeight) -static void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange ) +void ScDocFunc::PaintAbove(ScDocShell& rDocShell, const ScRange& rRange) { SCROW nRow = rRange.aStart.Row(); if ( nRow > 0 ) @@ -589,98 +623,10 @@ void ScDocFunc::DetectiveCollectAllSuccs(const ScRangeList& rSrcRanges, std::vec lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, false); } -bool ScDocFunc::DeleteContents( - const ScMarkData& rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi ) +bool ScDocFunc::DeleteContents(const ScMarkData& rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi) { - ScDocShellModificator aModificator( rDocShell ); - - if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) - { - OSL_FAIL("ScDocFunc::DeleteContents without markings"); - return false; - } - - ScDocument& rDoc = rDocShell.GetDocument(); - - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - if (!CheckSheetViewProtection(sc::Operation::DeleteContent)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, rMark); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - ScMarkData aMultiMark = rMark; - aMultiMark.SetMarking(false); // for MarkToMulti - - ScDocumentUniquePtr pUndoDoc; - bool bMulti = aMultiMark.IsMultiMarked(); - aMultiMark.MarkToMulti(); - const ScRange& aMarkRange = aMultiMark.GetMultiMarkArea(); - ScRange aExtendedRange(aMarkRange); - if ( rDoc.ExtendMerge( aExtendedRange, true ) ) - bMulti = false; - - // no objects on protected tabs - bool bObjects = (nFlags & InsertDeleteFlags::OBJECTS) && !sc::DocFuncUtil::hasProtectedTab(rDoc, rMark); - - sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted - if ( nFlags & InsertDeleteFlags::ATTRIB ) - rDocShell.UpdatePaintExt( nExtFlags, aMarkRange ); - - // order of operations: - // 1) BeginDrawUndo - // 2) Delete objects (DrawUndo will be filled) - // 3) Copy content for undo and set up undo actions - // 4) Delete content - - bool bDrawUndo = bObjects || (nFlags & InsertDeleteFlags::NOTE); - if (bRecord && bDrawUndo) - rDoc.BeginDrawUndo(); - - if (bObjects) - { - if (bMulti) - rDoc.DeleteObjectsInSelection( aMultiMark ); - else - rDoc.DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), - aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), - aMultiMark ); - } - - // To keep track of all non-empty cells within the deleted area. - std::shared_ptr pDataSpans; - - if ( bRecord ) - { - pUndoDoc = sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc, aMultiMark, aMarkRange, nFlags, bMulti); - pDataSpans = sc::DocFuncUtil::getNonEmptyCellSpans(rDoc, aMultiMark, aMarkRange); - } - - rDoc.DeleteSelection( nFlags, aMultiMark ); - - // add undo action after drawing undo is complete (objects and note captions) - if( bRecord ) - { - sc::DocFuncUtil::addDeleteContentsUndo( - rDocShell.GetUndoManager(), rDocShell, aMultiMark, aExtendedRange, - std::move(pUndoDoc), nFlags, pDataSpans, bMulti, bDrawUndo); - } - - if (!AdjustRowHeight( aExtendedRange, true, bApi )) - rDocShell.PostPaint( aExtendedRange, PaintPartFlags::Grid, nExtFlags ); - else if (nExtFlags & SC_PF_LINES) - lcl_PaintAbove( rDocShell, aExtendedRange ); // for lines above the range - - aModificator.SetDocumentModified(); - - return true; + sc::DeleteContentOperation aOperation(*this, rDocShell, rMark, nFlags, bRecord, bApi); + return aOperation.run(); } tools::Long ScDocShell::GetTwipWidthHint(const ScAddress& rPos) @@ -704,242 +650,30 @@ tools::Long ScDocShell::GetTwipWidthHint(const ScAddress& rPos) bool ScDocFunc::DeleteCell( const ScAddress& rPos, const ScMarkData& rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi ) { - ScDocShellModificator aModificator(rDocShell); - - ScDocument& rDoc = rDocShell.GetDocument(); - - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - if (!CheckSheetViewProtection(sc::Operation::DeleteCell)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(rDoc, rPos.Col(), rPos.Row(), rPos.Col(), rPos.Row(), rMark); - if (!aTester.IsEditable()) - { - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - // no objects on protected tabs - bool bObjects = (nFlags & InsertDeleteFlags::OBJECTS) && !sc::DocFuncUtil::hasProtectedTab(rDoc, rMark); - - sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted - if (nFlags & InsertDeleteFlags::ATTRIB) - rDocShell.UpdatePaintExt(nExtFlags, ScRange(rPos)); - - // order of operations: - // 1) BeginDrawUndo - // 2) delete objects (DrawUndo is filled) - // 3) copy contents for undo - // 4) delete contents - // 5) add undo-action - - bool bDrawUndo = bObjects || (nFlags & InsertDeleteFlags::NOTE); // needed for shown notes - if (bDrawUndo && bRecord) - rDoc.BeginDrawUndo(); - - if (bObjects) - rDoc.DeleteObjectsInArea(rPos.Col(), rPos.Row(), rPos.Col(), rPos.Row(), rMark); - - // To keep track of all non-empty cells within the deleted area. - std::shared_ptr pDataSpans; - - ScDocumentUniquePtr pUndoDoc; - if (bRecord) - { - pUndoDoc = sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc, rMark, ScRange(rPos), nFlags, false); - pDataSpans = sc::DocFuncUtil::getNonEmptyCellSpans(rDoc, rMark, ScRange(rPos)); - } - - tools::Long nBefore(rDocShell.GetTwipWidthHint(rPos)); - rDoc.DeleteArea(rPos.Col(), rPos.Row(), rPos.Col(), rPos.Row(), rMark, nFlags); - - if (bRecord) - { - sc::DocFuncUtil::addDeleteContentsUndo( - rDocShell.GetUndoManager(), rDocShell, rMark, ScRange(rPos), std::move(pUndoDoc), - nFlags, pDataSpans, false, bDrawUndo); - } - - if (!AdjustRowHeight(ScRange(rPos), true, bApi)) - rDocShell.PostPaint( - rPos.Col(), rPos.Row(), rPos.Tab(), rPos.Col(), rPos.Row(), rPos.Tab(), - PaintPartFlags::Grid, nExtFlags, nBefore); - - aModificator.SetDocumentModified(); - - return true; + sc::DeleteCellOperation aOperation(*this, rDocShell, rPos, rMark, nFlags, bRecord, bApi); + return aOperation.run(); } bool ScDocFunc::TransliterateText( const ScMarkData& rMark, TransliterationFlags nType, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - ScDocument& rDoc = rDocShell.GetDocument(); - bool bRecord = true; - if (!rDoc.IsUndoEnabled()) - bRecord = false; - - if (!CheckSheetViewProtection(sc::Operation::TransliterateText)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, rMark); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - ScMarkData aMultiMark = rMark; - aMultiMark.SetMarking(false); // for MarkToMulti - aMultiMark.MarkToMulti(); - const ScRange& aMarkRange = aMultiMark.GetMultiMarkArea(); - - if (bRecord) - { - SCTAB nStartTab = aMarkRange.aStart.Tab(); - SCTAB nTabCount = rDoc.GetTableCount(); - - ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nStartTab, nStartTab ); - for (const auto& rTab : rMark) - { - if (rTab >= nTabCount) - break; - - if (rTab != nStartTab) - pUndoDoc->AddUndoTab( rTab, rTab ); - } - - ScRange aCopyRange = aMarkRange; - aCopyRange.aStart.SetTab(0); - aCopyRange.aEnd.SetTab(nTabCount-1); - rDoc.CopyToDocument(aCopyRange, InsertDeleteFlags::CONTENTS, true, *pUndoDoc, &aMultiMark); - - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, aMultiMark, std::move(pUndoDoc), nType ) ); - } - - rDoc.TransliterateText( aMultiMark, nType ); - - if (!AdjustRowHeight( aMarkRange, true, true )) - rDocShell.PostPaint( aMarkRange, PaintPartFlags::Grid ); - - aModificator.SetDocumentModified(); - - return true; + sc::TransliterateTextOperation aOperation(*this, rDocShell, rMark, nType, bApi); + return aOperation.run(); } -bool ScDocFunc::SetNormalString( bool& o_rbNumFmtSet, const ScAddress& rPos, const OUString& rText, bool bApi ) +bool ScDocFunc::SetNormalString(bool& o_rbNumFmtSet, const ScAddress& rPos, const OUString& rText, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument& rDoc = rDocShell.GetDocument(); - - bool bUndo(rDoc.IsUndoEnabled()); - - if (!CheckSheetViewProtection(sc::Operation::SetNormalString)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(rDoc, rPos.Tab(), rPos.Col(), rPos.Row(), rPos.Col(), rPos.Row()); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - bool bEditDeleted = (rDoc.GetCellType(rPos) == CELLTYPE_EDIT); - ScUndoEnterData::ValuesType aOldValues; - - if (bUndo) - { - ScUndoEnterData::Value aOldValue; - - aOldValue.mnTab = rPos.Tab(); - aOldValue.maCell.assign(rDoc, rPos); - - const ScPatternAttr* pPattern = rDoc.GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() ); - if ( const SfxUInt32Item* pItem = pPattern->GetItemSet().GetItemIfSet( - ATTR_VALUE_FORMAT,false) ) - { - aOldValue.mbHasFormat = true; - aOldValue.mnFormat = pItem->GetValue(); - } - else - aOldValue.mbHasFormat = false; - - aOldValues.push_back(aOldValue); - } - - tools::Long nBefore(rDocShell.GetTwipWidthHint(rPos)); - o_rbNumFmtSet = rDoc.SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText ); - tools::Long nAfter(rDocShell.GetTwipWidthHint(rPos)); - - if (bUndo) - { - // because of ChangeTracking, UndoAction can be created only after SetString was called - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique(rDocShell, rPos, aOldValues, rText, nullptr)); - } - - if ( bEditDeleted || rDoc.HasAttrib( ScRange(rPos), HasAttrFlags::NeedHeight ) ) - AdjustRowHeight( ScRange(rPos), true, bApi ); - - rDocShell.PostPaintCell( rPos, std::max(nBefore, nAfter) ); - aModificator.SetDocumentModified(); - - // notify input handler here the same way as in PutCell - if (bApi) - NotifyInputHandler( rPos ); - - const SfxUInt32Item& rItem = rDoc.GetAttr(rPos, ATTR_VALIDDATA); - const ScValidationData* pData = rDoc.GetValidationEntry(rItem.GetValue()); - if (pData) - { - ScRefCellValue aCell(rDoc, rPos); - if (pData->IsDataValid(aCell, rPos)) - ScDetectiveFunc(rDoc, rPos.Tab()).DeleteCirclesAt(rPos.Col(), rPos.Row()); - } - - return true; + sc::SetNormalStringOperation aOperation(*this, rDocShell, rPos, rText, bApi); + bool bResult = aOperation.run(); + if (bResult) + o_rbNumFmtSet = aOperation.isNumberFormatSet(); + return bResult; } bool ScDocFunc::SetValueCell( const ScAddress& rPos, double fVal, bool bInteraction ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument& rDoc = rDocShell.GetDocument(); - bool bUndo = rDoc.IsUndoEnabled(); - - bool bHeight = rDoc.HasAttrib(ScRange(rPos), HasAttrFlags::NeedHeight); - - ScCellValue aOldVal; - if (bUndo) - aOldVal.assign(rDoc, rPos); - - rDoc.SetValue(rPos, fVal); - - if (bUndo) - { - SfxUndoManager* pUndoMgr = rDocShell.GetUndoManager(); - ScCellValue aNewVal; - aNewVal.assign(rDoc, rPos); - pUndoMgr->AddUndoAction(std::make_unique(rDocShell, rPos, aOldVal, aNewVal)); - } - - if (bHeight) - AdjustRowHeight(ScRange(rPos), true, !bInteraction); - - rDocShell.PostPaintCell( rPos ); - aModificator.SetDocumentModified(); - - // #103934#; notify editline and cell in edit mode - if (!bInteraction) - NotifyInputHandler( rPos ); - - return true; + sc::SetValueOperation aOperation(*this, rDocShell, rPos, fVal, !bInteraction); + return aOperation.run(); } void ScDocFunc::SetValueCells( const ScAddress& rPos, const std::vector& aVals, bool bInteraction ) @@ -978,74 +712,14 @@ void ScDocFunc::SetValueCells( const ScAddress& rPos, const std::vector& bool ScDocFunc::SetStringCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument& rDoc = rDocShell.GetDocument(); - bool bUndo = rDoc.IsUndoEnabled(); - - bool bHeight = rDoc.HasAttrib(ScRange(rPos), HasAttrFlags::NeedHeight); - - ScCellValue aOldVal; - if (bUndo) - aOldVal.assign(rDoc, rPos); - - ScSetStringParam aParam; - aParam.setTextInput(); - rDoc.SetString(rPos, rStr, &aParam); - - if (bUndo) - { - SfxUndoManager* pUndoMgr = rDocShell.GetUndoManager(); - ScCellValue aNewVal; - aNewVal.assign(rDoc, rPos); - pUndoMgr->AddUndoAction(std::make_unique(rDocShell, rPos, aOldVal, aNewVal)); - } - - if (bHeight) - AdjustRowHeight(ScRange(rPos), true, !bInteraction); - - rDocShell.PostPaintCell( rPos ); - aModificator.SetDocumentModified(); - - // #103934#; notify editline and cell in edit mode - if (!bInteraction) - NotifyInputHandler( rPos ); - - return true; + sc::SetStringOperation aOperation(*this, rDocShell, rPos, rStr, !bInteraction); + return aOperation.run(); } bool ScDocFunc::SetEditCell( const ScAddress& rPos, const EditTextObject& rStr, bool bInteraction ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument& rDoc = rDocShell.GetDocument(); - bool bUndo = rDoc.IsUndoEnabled(); - - bool bHeight = rDoc.HasAttrib(ScRange(rPos), HasAttrFlags::NeedHeight); - - ScCellValue aOldVal; - if (bUndo) - aOldVal.assign(rDoc, rPos); - - rDoc.SetEditText(rPos, rStr.Clone()); - - if (bUndo) - { - SfxUndoManager* pUndoMgr = rDocShell.GetUndoManager(); - ScCellValue aNewVal; - aNewVal.assign(rDoc, rPos); - pUndoMgr->AddUndoAction(std::make_unique(rDocShell, rPos, aOldVal, aNewVal)); - } - - if (bHeight) - AdjustRowHeight(ScRange(rPos), true, !bInteraction); - - rDocShell.PostPaintCell( rPos ); - aModificator.SetDocumentModified(); - - // #103934#; notify editline and cell in edit mode - if (!bInteraction) - NotifyInputHandler( rPos ); - - return true; + sc::SetEditTextOperation aOperation(*this, rDocShell, rPos, rStr, !bInteraction); + return aOperation.run(); } bool ScDocFunc::SetStringOrEditCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction ) @@ -1056,8 +730,8 @@ bool ScDocFunc::SetStringOrEditCell( const ScAddress& rPos, const OUString& rStr { ScFieldEditEngine& rEngine = rDoc.GetEditEngine(); rEngine.SetTextCurrentDefaults(rStr); - std::unique_ptr pEditText(rEngine.CreateTextObject()); - return SetEditCell(rPos, *pEditText, bInteraction); + EditTextObject aEditText(rEngine.CreateTextObject()); + return SetEditCell(rPos, aEditText, bInteraction); } else return SetStringCell(rPos, rStr, bInteraction); @@ -1065,51 +739,8 @@ bool ScDocFunc::SetStringOrEditCell( const ScAddress& rPos, const OUString& rStr bool ScDocFunc::SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell, bool bInteraction ) { - std::unique_ptr xCell(pCell); - - ScDocShellModificator aModificator( rDocShell ); - ScDocument& rDoc = rDocShell.GetDocument(); - bool bUndo = rDoc.IsUndoEnabled(); - - bool bHeight = rDoc.HasAttrib(ScRange(rPos), HasAttrFlags::NeedHeight); - - ScCellValue aOldVal; - if (bUndo) - aOldVal.assign(rDoc, rPos); - - pCell = rDoc.SetFormulaCell(rPos, xCell.release()); - - // For performance reasons API calls may disable calculation while - // operating and recalculate once when done. If through user interaction - // and AutoCalc is disabled, calculate the formula (without its - // dependencies) once so the result matches the current document's content. - if (bInteraction && !rDoc.GetAutoCalc() && pCell) - { - // calculate just the cell once and set Dirty again - pCell->Interpret(); - pCell->SetDirtyVar(); - rDoc.PutInFormulaTree( pCell); - } - - if (bUndo) - { - SfxUndoManager* pUndoMgr = rDocShell.GetUndoManager(); - ScCellValue aNewVal; - aNewVal.assign(rDoc, rPos); - pUndoMgr->AddUndoAction(std::make_unique(rDocShell, rPos, aOldVal, aNewVal)); - } - - if (bHeight) - AdjustRowHeight(ScRange(rPos), true, !bInteraction); - - rDocShell.PostPaintCell( rPos ); - aModificator.SetDocumentModified(); - - // #103934#; notify editline and cell in edit mode - if (!bInteraction) - NotifyInputHandler( rPos ); - - return true; + sc::SetFormulaOperation aOperation(*this, rDocShell, rPos, pCell, !bInteraction); + return aOperation.run(); } bool ScDocFunc::SetFormulaCells( const ScAddress& rPos, std::vector& rCells, bool bInteraction ) @@ -1238,8 +869,8 @@ void ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, } // A copy of pNewData will be stored in the cell. - std::unique_ptr pNewData(rEngine.CreateTextObject()); - bRet = SetEditCell(rPos, *pNewData, !bApi); + EditTextObject aNewData(rEngine.CreateTextObject()); + bRet = SetEditCell(rPos, aNewData, !bApi); // Set the paragraph attributes back to the EditEngine. for (const auto& rxItem : aRememberItems) @@ -1358,102 +989,20 @@ bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow ) void ScDocFunc::SetNoteText( const ScAddress& rPos, const OUString& rText, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - ScDocument& rDoc = rDocShell.GetDocument(); - - if (!CheckSheetViewProtection(sc::Operation::SetNoteText)) - return; - - ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(rDoc, rPos.Tab(), rPos.Col(), rPos.Row(), rPos.Col(), rPos.Row()); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return; - } - - OUString aNewText = convertLineEnd(rText, GetSystemLineEnd()); //! is this necessary ??? - - if( ScPostIt* pNote = (!aNewText.isEmpty()) ? rDoc.GetOrCreateNote( rPos ) : rDoc.GetNote(rPos) ) - pNote->SetText( rPos, aNewText ); - - //! Undo !!! - - rDoc.SetStreamValid(rPos.Tab(), false); - - rDocShell.PostPaintCell( rPos ); - aModificator.SetDocumentModified(); + sc::SetNoteTextOperation aOperation(rDocShell, rPos, rText, bApi); + aOperation.run(); } void ScDocFunc::ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, const OUString* pAuthor, const OUString* pDate, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument& rDoc = rDocShell.GetDocument(); + sc::ReplaceNoteTextOperation aOperation(rDocShell, rPos, rNoteText, pAuthor, pDate, bApi); + aOperation.run(); +} - if (!CheckSheetViewProtection(sc::Operation::ReplaceNoteText)) - return; - - ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(rDoc, rPos.Tab(), rPos.Col(), rPos.Row(), rPos.Col(), rPos.Row()); - if (aTester.IsEditable()) - { - ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); - SfxUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : nullptr; - - ScNoteData aOldData; - std::unique_ptr pOldNote = rDoc.ReleaseNote( rPos ); - sal_uInt32 nNoteId = 0; - if( pOldNote ) - { - nNoteId = pOldNote->GetId(); - // ensure existing caption object before draw undo tracking starts - pOldNote->GetOrCreateCaption( rPos ); - // rescue note data for undo - aOldData = pOldNote->GetNoteData(); - } - - // collect drawing undo actions for deleting/inserting caption objects - if( pUndoMgr ) - pDrawLayer->BeginCalcUndo(false); - - // delete the note (creates drawing undo action for the caption object) - bool hadOldNote(pOldNote); - pOldNote.reset(); - - // create new note (creates drawing undo action for the new caption object) - ScNoteData aNewData; - ScPostIt* pNewNote = nullptr; - if( (pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true, nNoteId )) ) - { - if( pAuthor ) pNewNote->SetAuthor( *pAuthor ); - if( pDate ) pNewNote->SetDate( *pDate ); - - // rescue note data for undo - aNewData = pNewNote->GetNoteData(); - } - - // create the undo action - if( pUndoMgr && (aOldData.mxCaption || aNewData.mxCaption) ) - pUndoMgr->AddUndoAction( std::make_unique( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) ); - - // repaint cell (to make note marker visible) - rDocShell.PostPaintCell( rPos ); - - rDoc.SetStreamValid(rPos.Tab(), false); - - aModificator.SetDocumentModified(); - - // Let our LOK clients know about the new/modified note - if (pNewNote) - { - ScDocShell::LOKCommentNotify(hadOldNote ? LOKCommentNotificationType::Modify : LOKCommentNotificationType::Add, - rDoc, rPos, pNewNote); - } - } - else if (!bApi) - { - rDocShell.ErrorMessage(aTester.GetMessageId()); - } +void ScDocFunc::InsertThreadedComment( const ScAddress& rPos, const OUString& rText, const OUString* pAuthor, bool bApi ) +{ + sc::InsertThreadedCommentOperation aOperation(rDocShell, rPos, rText, pAuthor, bApi); + aOperation.run(); } void ScDocFunc::ImportNote( const ScAddress& rPos, @@ -1475,74 +1024,10 @@ void ScDocFunc::ImportNote( const ScAddress& rPos, aModificator.SetDocumentModified(); } -bool ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern, - bool bApi ) +bool ScDocFunc::ApplyAttributes(const ScMarkData& rMark, const ScPatternAttr& rPattern, bool bApi ) { - ScDocument& rDoc = rDocShell.GetDocument(); - bool bRecord = true; - if ( !rDoc.IsUndoEnabled() ) - bRecord = false; - - bool bImportingXML = rDoc.IsImportingXML(); - bool bImportingXLSX = rDoc.IsImportingXLSX(); - // Cell formats can still be set if the range isn't editable only because of matrix formulas. - // #i62483# When loading XML, the check can be skipped altogether. - bool bOnlyNotBecauseOfMatrix; - if ( !bImportingXML && !rDoc.IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix ) - && !bOnlyNotBecauseOfMatrix ) - { - if (!bApi) - rDocShell.ErrorMessage(STR_PROTECTIONERR); - return false; - } - - ScDocShellModificator aModificator( rDocShell ); - - //! Border - - ScRange aMultiRange; - bool bMulti = rMark.IsMultiMarked(); - if ( bMulti ) - aMultiRange = rMark.GetMultiMarkArea(); - else - aMultiRange = rMark.GetMarkArea(); - - if ( bRecord ) - { - ScDocumentUniquePtr pUndoDoc( new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() ); - rDoc.CopyToDocument(aMultiRange, InsertDeleteFlags::ATTRIB, bMulti, *pUndoDoc, &rMark); - - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( - rDocShell, rMark, - aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(), - aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(), - std::move(pUndoDoc), bMulti, &rPattern ) ); - } - - // While loading XML it is not necessary to ask HasAttrib. It needs too much time. - sal_uInt16 nExtFlags = 0; - if ( !bImportingXML && !bImportingXLSX ) - rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content before the change - - bool bChanged = false; - rDoc.ApplySelectionPattern( rPattern, rMark, nullptr, &bChanged ); - - if(bChanged) - { - if ( !bImportingXML && !bImportingXLSX ) - rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content after the change - - if (!AdjustRowHeight( aMultiRange, true, bApi )) - rDocShell.PostPaint( aMultiRange, PaintPartFlags::Grid, nExtFlags ); - else if (nExtFlags & SC_PF_LINES) - lcl_PaintAbove( rDocShell, aMultiRange ); // because of lines above the range - - aModificator.SetDocumentModified(); - } - - return true; + sc::ApplyAttributesOperation aOperation(*this, rDocShell, rMark, rPattern, bApi); + return aOperation.run(); } bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const OUString& rStyleName, @@ -1615,1640 +1100,25 @@ bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const OUString& rStyleName, return true; } -namespace { - -/** - * Check if this insertion attempt would end up cutting one or more pivot - * tables in half, which is not desirable. - * - * @return true if this insertion can be done safely without shearing any - * existing pivot tables, false otherwise. - */ -bool canInsertCellsByPivot(const ScRange& rRange, const ScMarkData& rMarkData, InsCellCmd eCmd, const ScDocument& rDoc) -{ - if (!rDoc.HasPivotTable()) - // This document has no pivot tables. - return true; - - const ScDPCollection* pDPs = rDoc.GetDPCollection(); - - ScRange aRange(rRange); // local copy - switch (eCmd) - { - case INS_INSROWS_BEFORE: - { - aRange.aStart.SetCol(0); - aRange.aEnd.SetCol(rDoc.MaxCol()); - [[fallthrough]]; - } - case INS_CELLSDOWN: - { - auto bIntersects = std::ranges::any_of(rMarkData, [&pDPs, &aRange](const SCTAB& rTab) { - return pDPs->IntersectsTableByColumns(aRange.aStart.Col(), aRange.aEnd.Col(), aRange.aStart.Row(), rTab); }); - if (bIntersects) - // This column range cuts through at least one pivot table. Not good. - return false; - - // Start row must be either at the top or above any pivot tables. - if (aRange.aStart.Row() < 0) - // I don't know how to handle this case. - return false; - - if (aRange.aStart.Row() == 0) - // First row is always allowed. - return true; - - ScRange aTest(aRange); - aTest.aStart.IncRow(-1); // Test one row up. - aTest.aEnd.SetRow(aTest.aStart.Row()); - for (const auto& rTab : rMarkData) - { - aTest.aStart.SetTab(rTab); - aTest.aEnd.SetTab(rTab); - if (pDPs->HasTable(aTest)) - return false; - } - } - break; - case INS_INSCOLS_BEFORE: - { - aRange.aStart.SetRow(0); - aRange.aEnd.SetRow(rDoc.MaxRow()); - [[fallthrough]]; - } - case INS_CELLSRIGHT: - { - auto bIntersects = std::ranges::any_of(rMarkData, [&pDPs, &aRange](const SCTAB& rTab) { - return pDPs->IntersectsTableByRows(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Row(), rTab); }); - if (bIntersects) - // This column range cuts through at least one pivot table. Not good. - return false; - - // Start row must be either at the top or above any pivot tables. - if (aRange.aStart.Col() < 0) - // I don't know how to handle this case. - return false; - - if (aRange.aStart.Col() == 0) - // First row is always allowed. - return true; - - ScRange aTest(aRange); - aTest.aStart.IncCol(-1); // Test one column to the left. - aTest.aEnd.SetCol(aTest.aStart.Col()); - for (const auto& rTab : rMarkData) - { - aTest.aStart.SetTab(rTab); - aTest.aEnd.SetTab(rTab); - if (pDPs->HasTable(aTest)) - return false; - } - } - break; - default: - ; - } - return true; -} - -/** - * Check if this deletion attempt would end up cutting one or more pivot - * tables in half, which is not desirable. - * - * @return true if this deletion can be done safely without shearing any - * existing pivot tables, false otherwise. - */ -bool canDeleteCellsByPivot(const ScRange& rRange, const ScMarkData& rMarkData, DelCellCmd eCmd, const ScDocument& rDoc) -{ - if (!rDoc.HasPivotTable()) - // This document has no pivot tables. - return true; - - const ScDPCollection* pDPs = rDoc.GetDPCollection(); - - ScRange aRange(rRange); // local copy - - switch (eCmd) - { - case DelCellCmd::Rows: - { - aRange.aStart.SetCol(0); - aRange.aEnd.SetCol(rDoc.MaxCol()); - [[fallthrough]]; - } - case DelCellCmd::CellsUp: - { - auto bIntersects = std::ranges::any_of(rMarkData, [&pDPs, &aRange](const SCTAB& rTab) { - return pDPs->IntersectsTableByColumns(aRange.aStart.Col(), aRange.aEnd.Col(), aRange.aStart.Row(), rTab); }); - if (bIntersects) - // This column range cuts through at least one pivot table. Not good. - return false; - - ScRange aTest(aRange); - for (const auto& rTab : rMarkData) - { - aTest.aStart.SetTab(rTab); - aTest.aEnd.SetTab(rTab); - if (pDPs->HasTable(aTest)) - return false; - } - } - break; - case DelCellCmd::Cols: - { - aRange.aStart.SetRow(0); - aRange.aEnd.SetRow(rDoc.MaxRow()); - [[fallthrough]]; - } - case DelCellCmd::CellsLeft: - { - auto bIntersects = std::ranges::any_of(rMarkData, [&pDPs, &aRange](const SCTAB& rTab) { - return pDPs->IntersectsTableByRows(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Row(), rTab); }); - if (bIntersects) - // This column range cuts through at least one pivot table. Not good. - return false; - - ScRange aTest(aRange); - for (const auto& rTab : rMarkData) - { - aTest.aStart.SetTab(rTab); - aTest.aEnd.SetTab(rTab); - if (pDPs->HasTable(aTest)) - return false; - } - } - break; - default: - ; - } - return true; -} - -} - bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd, bool bRecord, bool bApi, bool bPartOfPaste, size_t nInsertCount ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument& rDoc = rDocShell.GetDocument(); - - if (rDocShell.GetDocument().GetChangeTrack() && - ((eCmd == INS_CELLSDOWN && (rRange.aStart.Col() != 0 || rRange.aEnd.Col() != rDoc.MaxCol())) || - (eCmd == INS_CELLSRIGHT && (rRange.aStart.Row() != 0 || rRange.aEnd.Row() != rDoc.MaxRow())))) - { - // We should not reach this via UI disabled slots. - assert(bApi); - SAL_WARN("sc.ui","ScDocFunc::InsertCells - no change-tracking of partial cell shift"); - return false; - } - - ScRange aTargetRange( rRange ); - - // If insertion is for full cols/rows and after the current - // selection, then shift the range accordingly - if ( eCmd == INS_INSROWS_AFTER ) - { - ScRange aErrorRange( ScAddress::UNINITIALIZED ); - if (!aTargetRange.Move(0, rRange.aEnd.Row() - rRange.aStart.Row() + 1, 0, aErrorRange, rDoc)) - { - return false; - } - } - if ( eCmd == INS_INSCOLS_AFTER ) - { - ScRange aErrorRange( ScAddress::UNINITIALIZED ); - if (!aTargetRange.Move(rRange.aEnd.Col() - rRange.aStart.Col() + 1, 0, 0, aErrorRange, rDoc)) - { - return false; - } - } - - SCCOL nStartCol = aTargetRange.aStart.Col(); - SCROW nStartRow = aTargetRange.aStart.Row(); - SCTAB nStartTab = aTargetRange.aStart.Tab(); - SCCOL nEndCol = aTargetRange.aEnd.Col() + nInsertCount; - SCROW nEndRow = aTargetRange.aEnd.Row() + nInsertCount; - SCTAB nEndTab = aTargetRange.aEnd.Tab(); - - if ( !rDoc.ValidRow(nStartRow) || !rDoc.ValidRow(nEndRow) ) - { - OSL_FAIL("invalid row in InsertCells"); - return false; - } - - SCTAB nTabCount = rDoc.GetTableCount(); - SCCOL nPaintStartCol = nStartCol; - SCROW nPaintStartRow = nStartRow; - SCCOL nPaintEndCol = nEndCol; - SCROW nPaintEndRow = nEndRow; - PaintPartFlags nPaintFlags = PaintPartFlags::Grid; - bool bSuccess; - - ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); //preserve current cursor position - SCCOL nCursorCol = 0; - SCROW nCursorRow = 0; - if( pViewSh ) - { - nCursorCol = pViewSh->GetViewData().GetCurX(); - nCursorRow = pViewSh->GetViewData().GetCurY(); - } - - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - ScMarkData aMark(rDoc.GetSheetLimits()); - if (pTabMark) - aMark = *pTabMark; - else - { - SCTAB nCount = 0; - for( SCTAB i=0; i= nTabCount) - break; - - for( SCTAB j = rTab+1; j pUndoData; - if ( bRecord ) - { - pRefUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pRefUndoDoc->InitUndo( rDoc, 0, nTabCount-1 ); - - // pRefUndoDoc is filled in InsertCol / InsertRow - - pUndoData.reset(new ScRefUndoData( rDoc )); - - rDoc.BeginDrawUndo(); - } - - // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction - // the patch comes from mloiseleur and maoyg - bool bInsertMerge = false; - std::vector qIncreaseRange; - OUString aUndo = ScResId( STR_UNDO_INSERTCELLS ); - if (bRecord) - { - ViewShellId nViewShellId(-1); - if (pViewSh) - nViewShellId = pViewSh->GetViewShellId(); - rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo, 0, nViewShellId ); - } - std::unique_ptr pUndoRemoveMerge; - - for (const SCTAB i : aMark) - { - if (i >= nTabCount) - break; - - if( rDoc.HasAttrib( nMergeTestStartCol, nMergeTestStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i, HasAttrFlags::Merged | HasAttrFlags::Overlapped ) ) - { - if (eCmd==INS_CELLSRIGHT) - bNeedRefresh = true; - - SCCOL nMergeStartCol = nMergeTestStartCol; - SCROW nMergeStartRow = nMergeTestStartRow; - SCCOL nMergeEndCol = nMergeTestEndCol; - SCROW nMergeEndRow = nMergeTestEndRow; - - rDoc.ExtendMerge( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i ); - rDoc.ExtendOverlapped( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i ); - - if(( eCmd == INS_CELLSDOWN && ( nMergeStartCol != nMergeTestStartCol || nMergeEndCol != nMergeTestEndCol )) || - (eCmd == INS_CELLSRIGHT && ( nMergeStartRow != nMergeTestStartRow || nMergeEndRow != nMergeTestEndRow )) ) - { - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); - rDocShell.GetUndoManager()->LeaveListAction(); - return false; - } - - SCCOL nTestCol = -1; - SCROW nTestRow1 = -1; - SCROW nTestRow2 = -1; - - ScDocAttrIterator aTestIter( rDoc, i, nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, nMergeTestEndRow ); - ScRange aExtendRange( nMergeTestStartCol, nMergeTestStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i ); - const ScPatternAttr* pPattern = nullptr; - while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != nullptr ) - { - const ScMergeAttr& rMergeFlag = pPattern->GetItem(ATTR_MERGE); - const ScMergeFlagAttr& rMergeFlagAttr = pPattern->GetItem(ATTR_MERGE_FLAG); - ScMF nNewFlags = rMergeFlagAttr.GetValue() & (ScMF::Hor | ScMF::Ver); - if (rMergeFlag.IsMerged() || nNewFlags == ScMF::Hor || nNewFlags == ScMF::Ver) - { - ScRange aRange( nTestCol, nTestRow1, i ); - rDoc.ExtendOverlapped(aRange); - rDoc.ExtendMerge(aRange, true); - - if( nTestRow1 < nTestRow2 && nNewFlags == ScMF::Hor ) - { - for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ ) - { - ScRange aTestRange( nTestCol, nTestRow, i ); - rDoc.ExtendOverlapped( aTestRange ); - rDoc.ExtendMerge( aTestRange, true); - ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i ); - if( !aExtendRange.Contains( aMergeRange ) ) - { - qIncreaseRange.push_back( aTestRange ); - bInsertMerge = true; - } - } - } - else - { - ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i ); - if( !aExtendRange.Contains( aMergeRange ) ) - { - qIncreaseRange.push_back( aRange ); - } - bInsertMerge = true; - } - } - } - - if( bInsertMerge ) - { - if( eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER || eCmd == INS_CELLSDOWN ) - { - nStartRow = aExtendMergeRange.aStart.Row(); - nEndRow = aExtendMergeRange.aEnd.Row(); - - if( eCmd == INS_CELLSDOWN ) - nEndCol = nMergeTestEndCol; - else - { - nStartCol = 0; - nEndCol = rDoc.MaxCol(); - } - } - else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSCOLS_AFTER ) - { - - nStartCol = aExtendMergeRange.aStart.Col(); - nEndCol = aExtendMergeRange.aEnd.Col(); - if( eCmd == INS_CELLSRIGHT ) - { - nEndRow = nMergeTestEndRow; - } - else - { - nStartRow = 0; - nEndRow = rDoc.MaxRow(); - } - } - - if( !qIncreaseRange.empty() ) - { - if (bRecord && !pUndoRemoveMerge) - { - ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, *aMark.begin(), *aMark.rbegin()); - pUndoRemoveMerge.reset( new ScUndoRemoveMerge( rDocShell, rRange, std::move(pUndoDoc) )); - } - - for( const ScRange& aRange : qIncreaseRange ) - { - if( rDoc.HasAttrib( aRange, HasAttrFlags::Overlapped | HasAttrFlags::Merged ) ) - { - UnmergeCells( aRange, bRecord, pUndoRemoveMerge.get() ); - } - } - } - } - else - { - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); - rDocShell.GetUndoManager()->LeaveListAction(); - return false; - } - } - } - - if (bRecord && pUndoRemoveMerge) - { - rDocShell.GetUndoManager()->AddUndoAction( std::move(pUndoRemoveMerge)); - } - - switch (eCmd) - { - case INS_CELLSDOWN: - bSuccess = rDoc.InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast(nEndRow-nStartRow+1), pRefUndoDoc.get(), &aFullMark ); - nPaintEndRow = rDoc.MaxRow(); - break; - case INS_INSROWS_BEFORE: - case INS_INSROWS_AFTER: - bSuccess = rDoc.InsertRow( 0, 0, rDoc.MaxCol(), MAXTAB, nStartRow, static_cast(nEndRow-nStartRow+1), pRefUndoDoc.get(), &aFullMark ); - nPaintStartCol = 0; - nPaintEndCol = rDoc.MaxCol(); - nPaintEndRow = rDoc.MaxRow(); - nPaintFlags |= PaintPartFlags::Left; - break; - case INS_CELLSRIGHT: - bSuccess = rDoc.InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast(nEndCol-nStartCol+1), pRefUndoDoc.get(), &aFullMark ); - nPaintEndCol = rDoc.MaxCol(); - break; - case INS_INSCOLS_BEFORE: - case INS_INSCOLS_AFTER: - bSuccess = rDoc.InsertCol( 0, 0, rDoc.MaxRow(), MAXTAB, nStartCol, static_cast(nEndCol-nStartCol+1), pRefUndoDoc.get(), &aFullMark ); - nPaintStartRow = 0; - nPaintEndRow = rDoc.MaxRow(); - nPaintEndCol = rDoc.MaxCol(); - nPaintFlags |= PaintPartFlags::Top; - break; - default: - OSL_FAIL("Wrong code at inserting"); - bSuccess = false; - break; - } - - if ( bSuccess ) - { - SCTAB nUndoPos = 0; - - if ( bRecord ) - { - std::unique_ptr pTabs(new SCTAB[nSelCount]); - std::unique_ptr pScenarios(new SCTAB[nSelCount]); - nUndoPos = 0; - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - SCTAB nCount = 0; - for( SCTAB j=rTab+1; jLeaveListAction(); - } - - rDocShell.GetUndoManager()->AddUndoAction( std::make_unique( - rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ), - nUndoPos, std::move(pTabs), std::move(pScenarios), eCmd, std::move(pRefUndoDoc), std::move(pUndoData), bPartOfPaste ) ); - } - - // #i8302 : we remerge growing ranges, with the new part inserted - - while( !qIncreaseRange.empty() ) - { - ScRange aRange = qIncreaseRange.back(); - if( !rDoc.HasAttrib( aRange, HasAttrFlags::Overlapped | HasAttrFlags::Merged ) ) - { - switch (eCmd) - { - case INS_CELLSDOWN: - case INS_INSROWS_BEFORE: - case INS_INSROWS_AFTER: - aRange.aEnd.IncRow(static_cast(nEndRow-nStartRow+1)); - break; - case INS_CELLSRIGHT: - case INS_INSCOLS_BEFORE: - case INS_INSCOLS_AFTER: - aRange.aEnd.IncCol(static_cast(nEndCol-nStartCol+1)); - break; - default: - break; - } - ScCellMergeOption aMergeOption( - aRange.aStart.Col(), aRange.aStart.Row(), - aRange.aEnd.Col(), aRange.aEnd.Row() ); - aMergeOption.maTabs.insert(aRange.aStart.Tab()); - MergeCells(aMergeOption, false, true, true); - } - qIncreaseRange.pop_back(); - } - - if( bInsertMerge ) - rDocShell.GetUndoManager()->LeaveListAction(); - - for (const SCTAB i : aMark) - { - if (i >= nTabCount) - break; - - rDoc.SetDrawPageSize(i); - - if (bNeedRefresh) - rDoc.ExtendMerge( nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, nMergeTestEndRow, i, true ); - else - rDoc.RefreshAutoFilter( nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, nMergeTestEndRow, i ); - - if ( eCmd == INS_INSROWS_BEFORE ||eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSROWS_AFTER ||eCmd == INS_INSCOLS_AFTER ) - rDoc.UpdatePageBreaks( i ); - - sal_uInt16 nExtFlags = 0; - rDocShell.UpdatePaintExt( nExtFlags, nPaintStartCol, nPaintStartRow, i, nPaintEndCol, nPaintEndRow, i ); - - SCTAB nScenarioCount = 0; - - for( SCTAB j = i+1; jMarkRange( aTargetRange, false ); - pViewSh->SetCursor( nCursorCol, nCursorRow ); - } - } - - rDocShell.GetUndoManager()->LeaveListAction(); - rDocShell.GetUndoManager()->RemoveLastUndoAction(); - - pRefUndoDoc.reset(); - if (!bApi) - rDocShell.ErrorMessage(STR_INSERT_FULL); // column/row full - } - - // The cursor position needs to be modified earlier than updating - // any enabled edit view which is triggered by SetDocumentModified below. - if (bSuccess) - { - bool bInsertCols = ( eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSCOLS_AFTER); - bool bInsertRows = ( eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER ); - - if (bInsertCols) - { - pViewSh->OnLOKInsertDeleteColumn(rRange.aStart.Col() - (eCmd == INS_INSCOLS_BEFORE ? 1: 0), 1); - } - - if (bInsertRows) - { - pViewSh->OnLOKInsertDeleteRow(rRange.aStart.Row() - (eCmd == INS_INSROWS_BEFORE ? 1: 0), 1); - } - } - - aModificator.SetDocumentModified(); - - SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); - return bSuccess; + sc::InsertCellsOperation aOperation(rDocShell, rRange, pTabMark, eCmd, bRecord, bApi, bPartOfPaste, nInsertCount); + return aOperation.run(); } bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument& rDoc = rDocShell.GetDocument(); - - if (rDocShell.GetDocument().GetChangeTrack() && - ((eCmd == DelCellCmd::CellsUp && (rRange.aStart.Col() != 0 || rRange.aEnd.Col() != rDoc.MaxCol())) || - (eCmd == DelCellCmd::CellsLeft && (rRange.aStart.Row() != 0 || rRange.aEnd.Row() != rDoc.MaxRow())))) - { - // We should not reach this via UI disabled slots. - assert(bApi); - SAL_WARN("sc.ui","ScDocFunc::DeleteCells - no change-tracking of partial cell shift"); - return false; - } - - SCCOL nStartCol = rRange.aStart.Col(); - SCROW nStartRow = rRange.aStart.Row(); - SCTAB nStartTab = rRange.aStart.Tab(); - SCCOL nEndCol = rRange.aEnd.Col(); - SCROW nEndRow = rRange.aEnd.Row(); - SCTAB nEndTab = rRange.aEnd.Tab(); - - if ( !rDoc.ValidRow(nStartRow) || !rDoc.ValidRow(nEndRow) ) - { - OSL_FAIL("invalid row in DeleteCells"); - return false; - } - - SCTAB nTabCount = rDoc.GetTableCount(); - SCCOL nPaintStartCol = nStartCol; - SCROW nPaintStartRow = nStartRow; - SCCOL nPaintEndCol = nEndCol; - SCROW nPaintEndRow = nEndRow; - PaintPartFlags nPaintFlags = PaintPartFlags::Grid; - - bool bRecord = true; - if (!rDoc.IsUndoEnabled()) - bRecord = false; - - ScMarkData aMark(rDoc.GetSheetLimits()); - if (pTabMark) - aMark = *pTabMark; - else - { - SCTAB nCount = 0; - for(SCTAB i=0; i= nTabCount) - break; - - for( SCTAB j = rTab+1; j qDecreaseRange; - bool bDeletingMerge = false; - OUString aUndo = ScResId( STR_UNDO_DELETECELLS ); - if (bRecord) - { - ViewShellId nViewShellId(-1); - if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell()) - nViewShellId = pViewSh->GetViewShellId(); - rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo, 0, nViewShellId ); - } - std::unique_ptr pUndoRemoveMerge; - - for (const SCTAB i : aMark) - { - if (i >= nTabCount) - break; - - if ( rDoc.HasAttrib( nUndoStartCol, nUndoStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i, HasAttrFlags::Merged | HasAttrFlags::Overlapped )) - { - SCCOL nMergeStartCol = nUndoStartCol; - SCROW nMergeStartRow = nUndoStartRow; - SCCOL nMergeEndCol = nMergeTestEndCol; - SCROW nMergeEndRow = nMergeTestEndRow; - - rDoc.ExtendMerge( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i ); - rDoc.ExtendOverlapped( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i ); - if( ( eCmd == DelCellCmd::CellsUp && ( nMergeStartCol != nUndoStartCol || nMergeEndCol != nMergeTestEndCol))|| - ( eCmd == DelCellCmd::CellsLeft && ( nMergeStartRow != nUndoStartRow || nMergeEndRow != nMergeTestEndRow))) - { - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0); - rDocShell.GetUndoManager()->LeaveListAction(); - return false; - } - - nExtendStartCol = nMergeStartCol; - nExtendStartRow = nMergeStartRow; - SCCOL nTestCol = -1; - SCROW nTestRow1 = -1; - SCROW nTestRow2 = -1; - - ScDocAttrIterator aTestIter( rDoc, i, nUndoStartCol, nUndoStartRow, nMergeTestEndCol, nMergeTestEndRow ); - ScRange aExtendRange( nUndoStartCol, nUndoStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i ); - const ScPatternAttr* pPattern = nullptr; - while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != nullptr ) - { - const ScMergeAttr& rMergeFlag = pPattern->GetItem(ATTR_MERGE); - const ScMergeFlagAttr& rMergeFlagAttr = pPattern->GetItem(ATTR_MERGE_FLAG); - ScMF nNewFlags = rMergeFlagAttr.GetValue() & (ScMF::Hor | ScMF::Ver); - if (rMergeFlag.IsMerged() || nNewFlags == ScMF::Hor || nNewFlags == ScMF::Ver) - { - ScRange aRange( nTestCol, nTestRow1, i ); - rDoc.ExtendOverlapped( aRange ); - rDoc.ExtendMerge( aRange, true ); - - if( nTestRow1 < nTestRow2 && nNewFlags == ScMF::Hor ) - { - for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ ) - { - ScRange aTestRange( nTestCol, nTestRow, i ); - rDoc.ExtendOverlapped( aTestRange ); - rDoc.ExtendMerge( aTestRange, true ); - ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i ); - if( !aExtendRange.Contains( aMergeRange ) ) - { - qDecreaseRange.push_back( aTestRange ); - bDeletingMerge = true; - } - } - } - else - { - ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i ); - if( !aExtendRange.Contains( aMergeRange ) ) - { - qDecreaseRange.push_back( aRange ); - } - bDeletingMerge = true; - } - } - } - - if( bDeletingMerge ) - { - - if( eCmd == DelCellCmd::Rows || eCmd == DelCellCmd::CellsUp ) - { - nStartRow = aExtendMergeRange.aStart.Row(); - nEndRow = aExtendMergeRange.aEnd.Row(); - bNeedRefresh = true; - - if( eCmd == DelCellCmd::CellsUp ) - { - nEndCol = aExtendMergeRange.aEnd.Col(); - } - else - { - nStartCol = 0; - nEndCol = rDoc.MaxCol(); - } - } - else if( eCmd == DelCellCmd::CellsLeft || eCmd == DelCellCmd::Cols ) - { - - nStartCol = aExtendMergeRange.aStart.Col(); - nEndCol = aExtendMergeRange.aEnd.Col(); - if( eCmd == DelCellCmd::CellsLeft ) - { - nEndRow = aExtendMergeRange.aEnd.Row(); - bNeedRefresh = true; - } - else - { - nStartRow = 0; - nEndRow = rDoc.MaxRow(); - } - } - - if( !qDecreaseRange.empty() ) - { - if (bRecord && !pUndoRemoveMerge) - { - ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, *aMark.begin(), *aMark.rbegin()); - pUndoRemoveMerge.reset( new ScUndoRemoveMerge( rDocShell, rRange, std::move(pUndoDoc) )); - } - - for( const ScRange& aRange : qDecreaseRange ) - { - if( rDoc.HasAttrib( aRange, HasAttrFlags::Overlapped | HasAttrFlags::Merged ) ) - { - UnmergeCells( aRange, bRecord, pUndoRemoveMerge.get() ); - } - } - } - } - else - { - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0); - rDocShell.GetUndoManager()->LeaveListAction(); - return false; - } - } - } - - if (bRecord && pUndoRemoveMerge) - { - rDocShell.GetUndoManager()->AddUndoAction( std::move(pUndoRemoveMerge)); - } - - // do it - - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); // important because of TrackFormulas in UpdateReference - - ScDocumentUniquePtr pUndoDoc; - std::unique_ptr pRefUndoDoc; - std::unique_ptr pUndoData; - if ( bRecord ) - { - // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position, - // so it's no longer necessary to copy more than the deleted range into pUndoDoc. - - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, 0, nTabCount-1, (eCmd==DelCellCmd::Cols), (eCmd==DelCellCmd::Rows) ); - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - SCTAB nScenarioCount = 0; - - for( SCTAB j = rTab+1; jInitUndo( rDoc, 0, nTabCount-1 ); - - pUndoData.reset(new ScRefUndoData( rDoc )); - - rDoc.BeginDrawUndo(); - } - - sal_uInt16 nExtFlags = 0; - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, rTab, nEndCol, nEndRow, rTab ); - } - - switch (eCmd) - { - case DelCellCmd::CellsUp: - case DelCellCmd::CellsLeft: - rDoc.DeleteObjectsInArea(nStartCol, nStartRow, nEndCol, nEndRow, aMark, true); - break; - case DelCellCmd::Rows: - rDoc.DeleteObjectsInArea(0, nStartRow, rDoc.MaxCol(), nEndRow, aMark, true); - break; - case DelCellCmd::Cols: - rDoc.DeleteObjectsInArea(nStartCol, 0, nEndCol, rDoc.MaxRow(), aMark, true); - break; - default: - break; - } - - - bool bUndoOutline = false; - switch (eCmd) - { - case DelCellCmd::CellsUp: - rDoc.DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast(nEndRow-nStartRow+1), pRefUndoDoc.get(), nullptr, &aFullMark ); - nPaintEndRow = rDoc.MaxRow(); - break; - case DelCellCmd::Rows: - rDoc.DeleteRow( 0, 0, rDoc.MaxCol(), MAXTAB, nStartRow, static_cast(nEndRow-nStartRow+1), pRefUndoDoc.get(), &bUndoOutline, &aFullMark ); - nPaintStartCol = 0; - nPaintEndCol = rDoc.MaxCol(); - nPaintEndRow = rDoc.MaxRow(); - nPaintFlags |= PaintPartFlags::Left; - break; - case DelCellCmd::CellsLeft: - rDoc.DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast(nEndCol-nStartCol+1), pRefUndoDoc.get(), nullptr, &aFullMark ); - nPaintEndCol = rDoc.MaxCol(); - break; - case DelCellCmd::Cols: - rDoc.DeleteCol( 0, 0, rDoc.MaxRow(), MAXTAB, nStartCol, static_cast(nEndCol-nStartCol+1), pRefUndoDoc.get(), &bUndoOutline, &aFullMark ); - nPaintStartRow = 0; - nPaintEndRow = rDoc.MaxRow(); - nPaintEndCol = rDoc.MaxCol(); - nPaintFlags |= PaintPartFlags::Top; - break; - default: - OSL_FAIL("Wrong code at deleting"); - break; - } - - //! Test if the size of outline has changed - - if ( bRecord ) - { - for (const auto& rTab : aFullMark) - { - if (rTab >= nTabCount) - break; - - pRefUndoDoc->DeleteAreaTab(nUndoStartCol,nUndoStartRow,nUndoEndCol,nUndoEndRow, rTab, InsertDeleteFlags::ALL); - } - - // for all sheets, so that formulas can be copied - pUndoDoc->AddUndoTab( 0, nTabCount-1 ); - - // copy with bColRowFlags=false (#54194#) - pRefUndoDoc->CopyToDocument(0,0,0,rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB,InsertDeleteFlags::FORMULA,false,*pUndoDoc,nullptr,false); - pRefUndoDoc.reset(); - - std::unique_ptr pTabs( new SCTAB[nSelCount]); - std::unique_ptr pScenarios( new SCTAB[nSelCount]); - SCTAB nUndoPos = 0; - - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - SCTAB nCount = 0; - for( SCTAB j=rTab+1; jLeaveListAction(); - } - - rDocShell.GetUndoManager()->AddUndoAction( std::make_unique( - rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ), - nUndoPos, std::move(pTabs), std::move(pScenarios), - eCmd, std::move(pUndoDoc), std::move(pUndoData) ) ); - } - - // #i8302 want to be able to insert into the middle of merged cells - // the patch comes from maoyg - - while( !qDecreaseRange.empty() ) - { - ScRange aRange = qDecreaseRange.back(); - - sal_Int32 nDecreaseRowCount = 0; - sal_Int32 nDecreaseColCount = 0; - if( eCmd == DelCellCmd::CellsUp || eCmd == DelCellCmd::Rows ) - { - if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() ) - nDecreaseRowCount = nEndRow-nStartRow+1; - else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() ) - nDecreaseRowCount = aRange.aEnd.Row()-nStartRow+1; - else if( nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() ) - nDecreaseRowCount = aRange.aEnd.Row()-nEndRow+1; - } - else if( eCmd == DelCellCmd::CellsLeft || eCmd == DelCellCmd::Cols ) - { - if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() ) - nDecreaseColCount = nEndCol-nStartCol+1; - else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() ) - nDecreaseColCount = aRange.aEnd.Col()-nStartCol+1; - else if( nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() ) - nDecreaseColCount = aRange.aEnd.Col()-nEndCol+1; - } - - switch (eCmd) - { - case DelCellCmd::CellsUp: - case DelCellCmd::Rows: - aRange.aEnd.SetRow(static_cast( aRange.aEnd.Row()-nDecreaseRowCount)); - break; - case DelCellCmd::CellsLeft: - case DelCellCmd::Cols: - aRange.aEnd.SetCol(static_cast( aRange.aEnd.Col()-nDecreaseColCount)); - break; - default: - break; - } - - if( !rDoc.HasAttrib( aRange, HasAttrFlags::Overlapped | HasAttrFlags::Merged ) ) - { - ScCellMergeOption aMergeOption(aRange); - MergeCells( aMergeOption, false, true, true ); - } - qDecreaseRange.pop_back(); - } - - if( bDeletingMerge ) - rDocShell.GetUndoManager()->LeaveListAction(); - - if ( eCmd==DelCellCmd::Cols || eCmd==DelCellCmd::CellsLeft ) - nMergeTestEndCol = rDoc.MaxCol(); - if ( eCmd==DelCellCmd::Rows || eCmd==DelCellCmd::CellsUp ) - nMergeTestEndRow = rDoc.MaxRow(); - if ( bNeedRefresh ) - { - // #i51445# old merge flag attributes must be deleted also for single cells, - // not only for whole columns/rows - - ScPatternAttr aPattern(rDoc.getCellAttributeHelper()); - aPattern.ItemSetPut(ScMergeFlagAttr()); - - rDoc.ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndCol, nMergeTestEndRow, aMark, aPattern ); - - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - SCTAB nScenarioCount = 0; - - for( SCTAB j = rTab+1; j= nTabCount) - break; - - rDoc.RefreshAutoFilter( nExtendStartCol, nExtendStartRow, nMergeTestEndCol, nMergeTestEndRow, rTab ); - } - - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - rDoc.SetDrawPageSize(rTab); - - if ( eCmd == DelCellCmd::Cols || eCmd == DelCellCmd::Rows ) - rDoc.UpdatePageBreaks( rTab ); - - rDocShell.UpdatePaintExt( nExtFlags, nPaintStartCol, nPaintStartRow, rTab, nPaintEndCol, nPaintEndRow, rTab ); - - SCTAB nScenarioCount = 0; - - for( SCTAB j = rTab+1; jOnLOKInsertDeleteColumn(rRange.aStart.Col(), -1 * (rRange.aEnd.Col() - rRange.aStart.Col() + 1)); - } - if (eCmd == DelCellCmd::Rows) - { - pViewSh->OnLOKInsertDeleteRow(rRange.aStart.Row(), -1 * (rRange.aEnd.Row() - rRange.aStart.Row() + 1)); - } - } - - aModificator.SetDocumentModified(); - - SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); - - return true; + sc::DeleteCellsOperation aOperation(rDocShell, rRange, pTabMark, eCmd, bApi); + return aOperation.run(); } bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos, bool bCut, bool bRecord, bool bPaint, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - SCCOL nStartCol = rSource.aStart.Col(); - SCROW nStartRow = rSource.aStart.Row(); - SCTAB nStartTab = rSource.aStart.Tab(); - SCCOL nEndCol = rSource.aEnd.Col(); - SCROW nEndRow = rSource.aEnd.Row(); - SCTAB nEndTab = rSource.aEnd.Tab(); - SCCOL nDestCol = rDestPos.Col(); - SCROW nDestRow = rDestPos.Row(); - SCTAB nDestTab = rDestPos.Tab(); - - ScDocument& rDoc = rDocShell.GetDocument(); - if ( !rDoc.ValidRow(nStartRow) || !rDoc.ValidRow(nEndRow) || !rDoc.ValidRow(nDestRow) ) - { - OSL_FAIL("invalid row in MoveBlock"); - return false; - } - - // adjust related scenarios too - but only when moved within one sheet - bool bScenariosAdded = false; - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - SCTAB nTabCount = rDoc.GetTableCount(); - if ( nDestTab == nStartTab && !rDoc.IsScenario(nEndTab) ) - while ( nEndTab+1 < nTabCount && rDoc.IsScenario(nEndTab+1) ) - { - ++nEndTab; - bScenariosAdded = true; - } - - SCTAB nSrcTabCount = nEndTab-nStartTab+1; - SCTAB nDestEndTab = nDestTab+nSrcTabCount-1; - SCTAB nTab; - - ScDocumentUniquePtr pClipDoc(new ScDocument(SCDOCMODE_CLIP)); - - ScMarkData aSourceMark(rDoc.GetSheetLimits()); - for (nTab=nStartTab; nTab<=nEndTab; nTab++) - aSourceMark.SelectTable( nTab, true ); // select source - aSourceMark.SetMarkArea( rSource ); - - ScDocShellRef aDragShellRef; - if ( rDoc.HasOLEObjectsInArea( rSource ) ) - { - aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately - aDragShellRef->DoInitNew(); - } - ScDrawLayer::SetGlobalDrawPersist( aDragShellRef.get() ); - - ScClipParam aClipParam(ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nStartTab), bCut); - rDoc.CopyToClip(aClipParam, pClipDoc.get(), &aSourceMark, bScenariosAdded, true); - - ScDrawLayer::SetGlobalDrawPersist(nullptr); - - SCCOL nOldEndCol = nEndCol; - SCROW nOldEndRow = nEndRow; - bool bClipOver = false; - for (nTab=nStartTab; nTab<=nEndTab; nTab++) - { - SCCOL nTmpEndCol = nOldEndCol; - SCROW nTmpEndRow = nOldEndRow; - if (rDoc.ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab )) - bClipOver = true; - if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol; - if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow; - } - - SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol ); - SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow ); - - SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol ); // extended in destination block - SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow ); - - bool bIncludeFiltered = bCut; - if ( !bIncludeFiltered ) - { - // adjust sizes to include only non-filtered rows - - SCCOL nClipX; - SCROW nClipY; - pClipDoc->GetClipArea( nClipX, nClipY, false ); - SCROW nUndoAdd = nUndoEndRow - nDestEndRow; - nDestEndRow = nDestRow + nClipY; - nUndoEndRow = nDestEndRow + nUndoAdd; - } - - if (!rDoc.ValidCol(nUndoEndCol) || !rDoc.ValidRow(nUndoEndRow)) - { - if (!bApi) - rDocShell.ErrorMessage(STR_PASTE_FULL); - return false; - } - - if (!CheckSheetViewProtection(sc::Operation::MoveBlock)) - return false; - - // Test for cell protection - - ScEditableTester aTester; - for (nTab=nDestTab; nTab<=nDestEndTab; nTab++) - aTester.TestBlock( rDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow ); - if (bCut) - for (nTab=nStartTab; nTab<=nEndTab; nTab++) - aTester.TestBlock( rDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow ); - - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - // Test for merged cells- when moving after delete - - if (bClipOver && !bCut) - if (rDoc.HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab, - HasAttrFlags::Merged | HasAttrFlags::Overlapped )) - { // "Merge of already merged cells not possible" - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0); - return false; - } - - // Are there borders in the cells? (for painting) - - sal_uInt16 nSourceExt = 0; - rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab ); - sal_uInt16 nDestExt = 0; - rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab ); - - // do it - - ScDocumentUniquePtr pUndoDoc; - - if (bRecord) - { - bool bWholeCols = ( nStartRow == 0 && nEndRow == rDoc.MaxRow() ); - bool bWholeRows = ( nStartCol == 0 && nEndCol == rDoc.MaxCol() ); - InsertDeleteFlags nUndoFlags = (InsertDeleteFlags::ALL & ~InsertDeleteFlags::OBJECTS) | InsertDeleteFlags::NOCAPTIONS; - - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nStartTab, nEndTab, bWholeCols, bWholeRows ); - - if (bCut) - { - rDoc.CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, - nUndoFlags, false, *pUndoDoc ); - } - - if ( nDestTab != nStartTab ) - pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows ); - rDoc.CopyToDocument( nDestCol, nDestRow, nDestTab, - nDestEndCol, nDestEndRow, nDestEndTab, - nUndoFlags, false, *pUndoDoc ); - rDoc.BeginDrawUndo(); - } - - bool bSourceHeight = false; // adjust heights? - if (bCut) - { - ScMarkData aDelMark(rDoc.GetSheetLimits()); // only for tables - for (nTab=nStartTab; nTab<=nEndTab; nTab++) - { - rDoc.DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, InsertDeleteFlags::ALL ); - aDelMark.SelectTable( nTab, true ); - } - rDoc.DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark ); - - // Test for merged cells - - if (bClipOver) - if (rDoc.HasAttrib( nDestCol,nDestRow,nDestTab, - nUndoEndCol,nUndoEndRow,nDestEndTab, - HasAttrFlags::Merged | HasAttrFlags::Overlapped )) - { - rDoc.CopyFromClip( rSource, aSourceMark, InsertDeleteFlags::ALL, nullptr, pClipDoc.get() ); - for (nTab=nStartTab; nTab<=nEndTab; nTab++) - { - SCCOL nTmpEndCol = nEndCol; - SCROW nTmpEndRow = nEndRow; - rDoc.ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, true ); - } - - // Report error only after restoring content - if (!bApi) // "Merge of already merged cells not possible" - rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0); - - return false; - } - - bSourceHeight = AdjustRowHeight( rSource, false, bApi ); - } - - ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab ); - - ScMarkData aDestMark(rDoc.GetSheetLimits()); - for (nTab=nDestTab; nTab<=nDestEndTab; nTab++) - aDestMark.SelectTable( nTab, true ); // select destination - aDestMark.SetMarkArea( aPasteDest ); - - /* Do not copy drawing objects here. While pasting, the - function ScDocument::UpdateReference() is called which calls - ScDrawLayer::MoveCells() which may move away inserted objects to wrong - positions (e.g. if source and destination range overlaps).*/ - - rDoc.CopyFromClip( - aPasteDest, aDestMark, InsertDeleteFlags::ALL & ~InsertDeleteFlags::OBJECTS, - pUndoDoc.get(), pClipDoc.get(), true, false, bIncludeFiltered); - - // skipped rows and merged cells don't mix - if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() ) - UnmergeCells( aPasteDest, false, nullptr ); - - bool bDestHeight = AdjustRowHeight( - ScRange( 0,nDestRow,nDestTab, rDoc.MaxCol(),nDestEndRow,nDestEndTab ), - false, bApi ); - - /* Paste drawing objects after adjusting formula references - and row heights. There are no cell notes or drawing objects, if the - clipdoc does not contain a drawing layer.*/ - if ( pClipDoc->GetDrawLayer() ) - rDoc.CopyFromClip( aPasteDest, aDestMark, InsertDeleteFlags::OBJECTS, - nullptr, pClipDoc.get(), true, false, bIncludeFiltered ); - - if (bRecord) - { - ScRange aUndoRange(nStartCol, nStartRow, nStartTab, nOldEndCol, nOldEndRow, nEndTab); - ScAddress aDestPos(nDestCol, nDestRow, nDestTab); - - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( - rDocShell, aUndoRange, aDestPos, bCut, std::move(pUndoDoc), bScenariosAdded)); - } - - SCCOL nDestPaintEndCol = nDestEndCol; - SCROW nDestPaintEndRow = nDestEndRow; - for (nTab=nDestTab; nTab<=nDestEndTab; nTab++) - { - SCCOL nTmpEndCol = nDestEndCol; - SCROW nTmpEndRow = nDestEndRow; - rDoc.ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, true ); - if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol; - if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow; - } - - if (bCut) - for (nTab=nStartTab; nTab<=nEndTab; nTab++) - rDoc.RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab ); - - if (bPaint) - { - // destination range: - - SCCOL nPaintStartX = nDestCol; - SCROW nPaintStartY = nDestRow; - SCCOL nPaintEndX = nDestPaintEndCol; - SCROW nPaintEndY = nDestPaintEndRow; - PaintPartFlags nFlags = PaintPartFlags::Grid; - - if ( nStartRow==0 && nEndRow==rDoc.MaxRow() ) // copy widths too? - { - nPaintEndX = rDoc.MaxCol(); - nPaintStartY = 0; - nPaintEndY = rDoc.MaxRow(); - nFlags |= PaintPartFlags::Top; - } - if ( bDestHeight || ( nStartCol == 0 && nEndCol == rDoc.MaxCol() ) ) - { - nPaintEndY = rDoc.MaxRow(); - nPaintStartX = 0; - nPaintEndX = rDoc.MaxCol(); - nFlags |= PaintPartFlags::Left; - } - if ( bScenariosAdded ) - { - nPaintStartX = 0; - nPaintStartY = 0; - nPaintEndX = rDoc.MaxCol(); - nPaintEndY = rDoc.MaxRow(); - } - - rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab, - nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt ); - - if ( bCut ) - { - // source range: - - nPaintStartX = nStartCol; - nPaintStartY = nStartRow; - nPaintEndX = nEndCol; - nPaintEndY = nEndRow; - nFlags = PaintPartFlags::Grid; - - if ( bSourceHeight ) - { - nPaintEndY = rDoc.MaxRow(); - nPaintStartX = 0; - nPaintEndX = rDoc.MaxCol(); - nFlags |= PaintPartFlags::Left; - } - if ( bScenariosAdded ) - { - nPaintStartX = 0; - nPaintStartY = 0; - nPaintEndX = rDoc.MaxCol(); - nPaintEndY = rDoc.MaxRow(); - } - - rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab, - nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt ); - } - } - - aModificator.SetDocumentModified(); - - SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); - - return true; + sc::MoveBlockOperation aOperation(rDocShell, rSource, rDestPos, bCut, bRecord, bPaint, bApi); + return aOperation.run(); } static uno::Reference< uno::XInterface > GetDocModuleObject( const SfxObjectShell& rDocSh, const OUString& sCodeName ) @@ -3397,6 +1267,14 @@ bool ScDocFunc::InsertTable( SCTAB nTab, const OUString& rName, bool bRecord, bo return bSuccess; } +std::pair ScDocFunc::InsertSheetView( SCTAB nTab, bool bRecord ) +{ + sc::InsertSheetViewOperation aOperation(rDocShell, nTab, bRecord); + if (!aOperation.run()) + return { sc::InvalidSheetViewID, -1 }; + return { aOperation.getSheetViewID(), aOperation.getSheetViewTab() }; +} + bool ScDocFunc::DeleteTable( SCTAB nTab, bool bRecord ) { weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); @@ -3421,6 +1299,18 @@ bool ScDocFunc::DeleteTable( SCTAB nTab, bool bRecord ) pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true ); // only nTab with Flags pUndoDoc->AddUndoTab( 0, nCount-1 ); // all sheets for references + // Deleting nTab rewrites any formula on another sheet that refers to + // it into a #REF! error. Snapshot those sheets' formulas too, so + // ScMoveUndo::UndoRef() has the original formula to put back on undo + // instead of leaving the error in place. + for (SCTAB nOtherTab = 0; nOtherTab < nCount; ++nOtherTab) + { + if (nOtherTab == nTab) + continue; + rDoc.CopyToDocument(0,0,nOtherTab, rDoc.MaxCol(),rDoc.MaxRow(),nOtherTab, + InsertDeleteFlags::FORMULA, false, *pUndoDoc ); + } + rDoc.CopyToDocument(0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, InsertDeleteFlags::ALL,false, *pUndoDoc ); OUString aOldName; rDoc.GetName( nTab, aOldName ); @@ -4170,607 +2060,46 @@ bool ScDocFunc::Unprotect( SCTAB nTab, std::u16string_view rPassword, bool bApi void ScDocFunc::ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - ScDocument& rDoc = rDocShell.GetDocument(); - bool bUndo (rDoc.IsUndoEnabled()); - - if (!CheckSheetViewProtection(sc::Operation::ClearItems)) - return; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, rMark); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return; - } - - // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached - // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems - // here. - - ScMarkData aMultiMark = rMark; - aMultiMark.SetMarking(false); // for MarkToMulti - aMultiMark.MarkToMulti(); - const ScRange& aMarkRange = aMultiMark.GetMultiMarkArea(); - - if (bUndo) - { - SCTAB nStartTab = aMarkRange.aStart.Tab(); - SCTAB nEndTab = aMarkRange.aEnd.Tab(); - - ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nStartTab, nEndTab ); - rDoc.CopyToDocument( aMarkRange, InsertDeleteFlags::ATTRIB, true, *pUndoDoc, &aMultiMark ); - - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, aMultiMark, std::move(pUndoDoc), pWhich ) ); - } - - rDoc.ClearSelectionItems( pWhich, aMultiMark ); - - rDocShell.PostPaint( aMarkRange, PaintPartFlags::Grid, SC_PF_LINES | SC_PF_TESTMERGE ); - aModificator.SetDocumentModified(); - - //! Bindings-Invalidate etc.? + sc::ClearItemsOperation aOperation(rDocShell, rMark, pWhich, bApi); + aOperation.run(); } bool ScDocFunc::ChangeIndent( const ScMarkData& rMark, bool bIncrement, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - ScDocument& rDoc = rDocShell.GetDocument(); - bool bUndo(rDoc.IsUndoEnabled()); - - if (!CheckSheetViewProtection(sc::Operation::ChangeIndent)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, rMark); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - const ScRange& aMarkRange = rMark.GetMultiMarkArea(); - - if (bUndo) - { - SCTAB nStartTab = aMarkRange.aStart.Tab(); - SCTAB nTabCount = rDoc.GetTableCount(); - - ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nStartTab, nStartTab ); - for (const auto& rTab : rMark) - { - if (rTab >= nTabCount) - break; - - if (rTab != nStartTab) - pUndoDoc->AddUndoTab( rTab, rTab ); - } - - ScRange aCopyRange = aMarkRange; - aCopyRange.aStart.SetTab(0); - aCopyRange.aEnd.SetTab(nTabCount-1); - rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ATTRIB, true, *pUndoDoc, &rMark ); - - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, rMark, std::move(pUndoDoc), bIncrement ) ); - } - - rDoc.ChangeSelectionIndent( bIncrement, rMark ); - - rDocShell.PostPaint( aMarkRange, PaintPartFlags::Grid, SC_PF_LINES | SC_PF_TESTMERGE ); - aModificator.SetDocumentModified(); - - SfxBindings* pBindings = rDocShell.GetViewBindings(); - if (pBindings) - { - pBindings->Invalidate( SID_ALIGNLEFT ); // ChangeIndent aligns left - pBindings->Invalidate( SID_ALIGNRIGHT ); - pBindings->Invalidate( SID_ALIGNBLOCK ); - pBindings->Invalidate( SID_ALIGNCENTERHOR ); - pBindings->Invalidate( SID_ATTR_LRSPACE ); - pBindings->Invalidate( SID_ATTR_PARA_ADJUST_LEFT ); - pBindings->Invalidate( SID_ATTR_PARA_ADJUST_RIGHT ); - pBindings->Invalidate( SID_ATTR_PARA_ADJUST_BLOCK ); - pBindings->Invalidate( SID_ATTR_PARA_ADJUST_CENTER); - pBindings->Invalidate( SID_ATTR_PARA_ADJUST_START ); - pBindings->Invalidate( SID_ATTR_PARA_ADJUST_END ); - // pseudo slots for Format menu - pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT ); - pBindings->Invalidate( SID_ALIGN_ANY_LEFT ); - pBindings->Invalidate( SID_ALIGN_ANY_HCENTER ); - pBindings->Invalidate( SID_ALIGN_ANY_RIGHT ); - pBindings->Invalidate( SID_ALIGN_ANY_START ); - pBindings->Invalidate( SID_ALIGN_ANY_END ); - pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED ); - } - - return true; + sc::ChangeIndentOperation aOperation(rDocShell, rMark, bIncrement, bApi); + return aOperation.run(); } bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark, sal_uInt16 nFormatNo, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - ScDocument& rDoc = rDocShell.GetDocument(); - SCCOL nStartCol = rRange.aStart.Col(); - SCROW nStartRow = rRange.aStart.Row(); - SCTAB nStartTab = rRange.aStart.Tab(); - SCCOL nEndCol = rRange.aEnd.Col(); - SCROW nEndRow = rRange.aEnd.Row(); - SCTAB nEndTab = rRange.aEnd.Tab(); - - bool bRecord = true; - if (!rDoc.IsUndoEnabled()) - bRecord = false; - ScMarkData aMark(rDoc.GetSheetLimits()); - if (pTabMark) - aMark = *pTabMark; - else - { - for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) - aMark.SelectTable( nTab, true ); - } - - ScAutoFormat* pAutoFormat = ScGlobal::GetOrCreateAutoFormat(); - - if (!CheckSheetViewProtection(sc::Operation::AutoFormat)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); - if ( nFormatNo < pAutoFormat->size() && aTester.IsEditable() ) - { - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - bool bSize = pAutoFormat->GetData(nFormatNo)->IsWidthHeight(); - if (sal_uInt64(nEndCol - nStartCol + 1) * sal_uInt64(nEndRow - nStartRow + 1) > AUTOFORMAT_WARN_SIZE) - { - std::unique_ptr xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(), - VclMessageType::Warning, VclButtonsType::YesNo, - ScResId(STR_AUTOFORMAT_WAIT_WARNING))); - xQueryBox->set_default_response(RET_NO); - if (xQueryBox->run() != RET_YES) - return false; - } - - SCTAB nTabCount = rDoc.GetTableCount(); - ScDocumentUniquePtr pUndoDoc; - if ( bRecord ) - { - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nStartTab, nStartTab, bSize, bSize ); - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - if (rTab != nStartTab) - pUndoDoc->AddUndoTab( rTab, rTab, bSize, bSize ); - } - - ScRange aCopyRange = rRange; - aCopyRange.aStart.SetTab(0); - aCopyRange.aStart.SetTab(nTabCount-1); - rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ATTRIB, false, *pUndoDoc, &aMark ); - if (bSize) - { - rDoc.CopyToDocument( nStartCol,0,0, nEndCol,rDoc.MaxRow(),nTabCount-1, - InsertDeleteFlags::NONE, false, *pUndoDoc, &aMark ); - rDoc.CopyToDocument( 0,nStartRow,0, rDoc.MaxCol(),nEndRow,nTabCount-1, - InsertDeleteFlags::NONE, false, *pUndoDoc, &aMark ); - } - rDoc.BeginDrawUndo(); - } - - rDoc.AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark ); - - if (bSize) - { - std::vector aCols(1, sc::ColRowSpan(nStartCol,nEndCol)); - std::vector aRows(1, sc::ColRowSpan(nStartRow,nEndRow)); - - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - SetWidthOrHeight(true, aCols, rTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, false, true); - SetWidthOrHeight(false, aRows, rTab, SC_SIZE_VISOPT, 0, false, false); - rDocShell.PostPaint( 0,0,rTab, rDoc.MaxCol(),rDoc.MaxRow(),rTab, - PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top ); - } - } - else - { - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - bool bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, rTab, - nEndCol, nEndRow, rTab), false, bApi ); - if (bAdj) - rDocShell.PostPaint( 0,nStartRow,rTab, rDoc.MaxCol(),rDoc.MaxRow(),rTab, - PaintPartFlags::Grid | PaintPartFlags::Left ); - else - rDocShell.PostPaint( nStartCol, nStartRow, rTab, - nEndCol, nEndRow, rTab, PaintPartFlags::Grid ); - } - } - - if ( bRecord ) // only now is Draw-Undo available - { - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, rRange, std::move(pUndoDoc), aMark, bSize, nFormatNo ) ); - } - - aModificator.SetDocumentModified(); - } - else if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - - return false; + sc::AutoFormatOperation aOperation(*this, rDocShell, rRange, pTabMark, nFormatNo, bApi); + return aOperation.run(); } bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark, const ScTokenArray* pTokenArray, const OUString& rString, bool bApi, bool bEnglish, - const OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) + const OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar, + bool bDynamicArrayMaster) { - if (ScViewData::SelectionFillDOOM( rRange )) - return false; - - ScDocShellModificator aModificator( rDocShell ); - - bool bSuccess = false; - ScDocument& rDoc = rDocShell.GetDocument(); - SCCOL nStartCol = rRange.aStart.Col(); - SCROW nStartRow = rRange.aStart.Row(); - SCTAB nStartTab = rRange.aStart.Tab(); - SCCOL nEndCol = rRange.aEnd.Col(); - SCROW nEndRow = rRange.aEnd.Row(); - SCTAB nEndTab = rRange.aEnd.Tab(); - - ScMarkData aMark(rDoc.GetSheetLimits()); - if (pTabMark) - aMark = *pTabMark; - else - { - for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) - aMark.SelectTable( nTab, true ); - } - - if (!CheckSheetViewProtection(sc::Operation::EnterMatrix)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); - if ( aTester.IsEditable() ) - { - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - ScDocumentUniquePtr pUndoDoc; - - const bool bUndo(rDoc.IsUndoEnabled()); - if (bUndo) - { - //! take selected sheets into account also when undoing - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nStartTab, nEndTab ); - rDoc.CopyToDocument( rRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, *pUndoDoc ); - } - - // use TokenArray if given, string (and flags) otherwise - if ( pTokenArray ) - { - rDoc.InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, - aMark, OUString(), pTokenArray, eGrammar); - } - else if ( rDoc.IsImportingXML() ) - { - ScTokenArray aCode(rDoc); - aCode.AssignXMLString( rString, - ((eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) ? rFormulaNmsp : OUString())); - rDoc.InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, - aMark, OUString(), &aCode, eGrammar); - rDoc.IncXMLImportedFormulaCount( rString.getLength() ); - } - else if (bEnglish) - { - ScCompiler aComp( rDoc, rRange.aStart, eGrammar); - std::unique_ptr pCode = aComp.CompileString( rString ); - rDoc.InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, - aMark, OUString(), pCode.get(), eGrammar); - } - else - rDoc.InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, - aMark, rString, nullptr, eGrammar); - - if (bUndo) - { - //! take selected sheets into account also when undoing - std::unique_ptr pUndoArray; - if (pTokenArray) - pUndoArray = pTokenArray->Clone(); - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, rRange, std::move(pUndoDoc), - rString, std::move(pUndoArray) ) ); - } - - // Err522 painting of DDE-Formulas will be intercepted during interpreting - rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PaintPartFlags::Grid ); - aModificator.SetDocumentModified(); - - bSuccess = true; - } - else if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - - return bSuccess; + sc::EnterMatrixOperation aOperation(rDocShell, rRange, pTabMark, pTokenArray, + rString, bApi, bEnglish, rFormulaNmsp, eGrammar, + bDynamicArrayMaster); + return aOperation.run(); } bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark, const ScTabOpParam& rParam, bool bRecord, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - bool bSuccess = false; - ScDocument& rDoc = rDocShell.GetDocument(); - SCCOL nStartCol = rRange.aStart.Col(); - SCROW nStartRow = rRange.aStart.Row(); - SCTAB nStartTab = rRange.aStart.Tab(); - SCCOL nEndCol = rRange.aEnd.Col(); - SCROW nEndRow = rRange.aEnd.Row(); - SCTAB nEndTab = rRange.aEnd.Tab(); - - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - ScMarkData aMark(rDoc.GetSheetLimits()); - if (pTabMark) - aMark = *pTabMark; - else - { - for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) - aMark.SelectTable( nTab, true ); - } - - if (!CheckSheetViewProtection(sc::Operation::TabOperation)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); - if ( aTester.IsEditable() ) - { - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - rDoc.SetDirty( rRange, false ); - if ( bRecord ) - { - //! take selected sheets into account also when undoing - ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nStartTab, nEndTab ); - rDoc.CopyToDocument( rRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, *pUndoDoc ); - - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, - nStartCol, nStartRow, nStartTab, - nEndCol, nEndRow, nEndTab, std::move(pUndoDoc), - rParam.aRefFormulaCell, - rParam.aRefFormulaEnd, - rParam.aRefRowCell, - rParam.aRefColCell, - rParam.meMode) ); - } - rDoc.InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark); - rDocShell.PostPaintGridAll(); - aModificator.SetDocumentModified(); - bSuccess = true; - } - else if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - - return bSuccess; -} - -static ScDirection DirFromFillDir( FillDir eDir ) -{ - if (eDir==FILL_TO_BOTTOM) - return DIR_BOTTOM; - else if (eDir==FILL_TO_RIGHT) - return DIR_RIGHT; - else if (eDir==FILL_TO_TOP) - return DIR_TOP; - else // if (eDir==FILL_TO_LEFT) - return DIR_LEFT; -} - -namespace { - -/** - * Expand the fill range as necessary, to allow copying of adjacent cell(s) - * even when those cells are not in the original range. - */ -void adjustFillRangeForAdjacentCopy(const ScDocument &rDoc, ScRange& rRange, FillDir eDir) -{ - switch (eDir) - { - case FILL_TO_BOTTOM: - { - if (rRange.aStart.Row() == 0) - return; - - if (rRange.aStart.Row() != rRange.aEnd.Row()) - return; - - // Include the above row. - ScAddress& s = rRange.aStart; - s.SetRow(s.Row()-1); - } - break; - case FILL_TO_TOP: - { - if (rRange.aStart.Row() == rDoc.MaxRow()) - return; - - if (rRange.aStart.Row() != rRange.aEnd.Row()) - return; - - // Include the row below. - ScAddress& e = rRange.aEnd; - e.SetRow(e.Row()+1); - } - break; - case FILL_TO_LEFT: - { - if (rRange.aStart.Col() == rDoc.MaxCol()) - return; - - if (rRange.aStart.Col() != rRange.aEnd.Col()) - return; - - // Include the column to the right. - ScAddress& e = rRange.aEnd; - e.SetCol(e.Col()+1); - } - break; - case FILL_TO_RIGHT: - { - if (rRange.aStart.Col() == 0) - return; - - if (rRange.aStart.Col() != rRange.aEnd.Col()) - return; - - // Include the column to the left. - ScAddress& s = rRange.aStart; - s.SetCol(s.Col()-1); - } - break; - default: - ; - } -} - + sc::MultipleOpsOperation aOperation(rDocShell, rRange, pTabMark, rParam, bRecord, bApi); + return aOperation.run(); } bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument& rDoc = rDocShell.GetDocument(); - - bool bSuccess = false; - ScRange aRange = rRange; - adjustFillRangeForAdjacentCopy(rDoc, aRange, eDir); - - SCCOL nStartCol = aRange.aStart.Col(); - SCROW nStartRow = aRange.aStart.Row(); - SCTAB nStartTab = aRange.aStart.Tab(); - SCCOL nEndCol = aRange.aEnd.Col(); - SCROW nEndRow = aRange.aEnd.Row(); - SCTAB nEndTab = aRange.aEnd.Tab(); - - bool bRecord = true; - if (!rDoc.IsUndoEnabled()) - bRecord = false; - - ScMarkData aMark(rDoc.GetSheetLimits()); - if (pTabMark) - aMark = *pTabMark; - else - { - for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) - aMark.SelectTable( nTab, true ); - } - - if (!CheckSheetViewProtection(sc::Operation::FillSimple)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); - if ( aTester.IsEditable() ) - { - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - ScRange aSourceArea = aRange; - ScRange aDestArea = aRange; - - SCCOLROW nCount = 0; - switch (eDir) - { - case FILL_TO_BOTTOM: - nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row(); - aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() ); - break; - case FILL_TO_RIGHT: - nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col(); - aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() ); - break; - case FILL_TO_TOP: - nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row(); - aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() ); - break; - case FILL_TO_LEFT: - nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col(); - aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() ); - break; - } - - ScDocumentUniquePtr pUndoDoc; - if ( bRecord ) - { - SCTAB nTabCount = rDoc.GetTableCount(); - SCTAB nDestStartTab = aDestArea.aStart.Tab(); - - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nDestStartTab, nDestStartTab ); - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - if (rTab != nDestStartTab) - pUndoDoc->AddUndoTab( rTab, rTab ); - } - - ScRange aCopyRange = aDestArea; - aCopyRange.aStart.SetTab(0); - aCopyRange.aEnd.SetTab(nTabCount-1); - rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::AUTOFILL, false, *pUndoDoc, &aMark ); - } - - sal_uLong nProgCount; - if (eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP) - nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1; - else - nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1; - nProgCount *= nCount; - ScProgress aProgress( rDoc.GetDocumentShell(), - ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true ); - - rDoc.Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), - aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), &aProgress, - aMark, nCount, eDir, FILL_SIMPLE ); - AdjustRowHeight(aRange, true, bApi); - - if ( bRecord ) // only now is Draw-Undo available - { - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, aDestArea, aSourceArea, std::move(pUndoDoc), aMark, - eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307) ); - } - - rDocShell.PostPaintGridAll(); - aModificator.SetDocumentModified(); - - bSuccess = true; - } - else if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - - return bSuccess; + sc::FillSimpleOperation aOperation(*this, rDocShell, rRange, pTabMark, eDir, bApi); + return aOperation.run(); } bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark, @@ -4778,137 +2107,9 @@ bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark, double fStart, double fStep, double fMax, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - bool bSuccess = false; - ScDocument& rDoc = rDocShell.GetDocument(); - SCCOL nStartCol = rRange.aStart.Col(); - SCROW nStartRow = rRange.aStart.Row(); - SCTAB nStartTab = rRange.aStart.Tab(); - SCCOL nEndCol = rRange.aEnd.Col(); - SCROW nEndRow = rRange.aEnd.Row(); - SCTAB nEndTab = rRange.aEnd.Tab(); - - bool bRecord = true; - if (!rDoc.IsUndoEnabled()) - bRecord = false; - - ScMarkData aMark(rDoc.GetSheetLimits()); - if (pTabMark) - aMark = *pTabMark; - else - { - for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) - aMark.SelectTable( nTab, true ); - } - - if (!CheckSheetViewProtection(sc::Operation::FillSeries)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); - if ( aTester.IsEditable() ) - { - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - ScRange aSourceArea = rRange; - ScRange aDestArea = rRange; - - SCSIZE nCount = rDoc.GetEmptyLinesInBlock( - aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(), - aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(), - DirFromFillDir(eDir) ); - - // keep at least one row/column as source range - SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ? - static_cast( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) : - static_cast( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 ); - if ( nCount >= nTotLines ) - { - assert(nTotLines > 0 && "coverity 2023.12.2"); - nCount = nTotLines - 1; - } - - switch (eDir) - { - case FILL_TO_BOTTOM: - aSourceArea.aEnd.SetRow( sal::static_int_cast( aSourceArea.aEnd.Row() - nCount ) ); - break; - case FILL_TO_RIGHT: - aSourceArea.aEnd.SetCol( sal::static_int_cast( aSourceArea.aEnd.Col() - nCount ) ); - break; - case FILL_TO_TOP: - aSourceArea.aStart.SetRow( sal::static_int_cast( aSourceArea.aStart.Row() + nCount ) ); - break; - case FILL_TO_LEFT: - aSourceArea.aStart.SetCol( sal::static_int_cast( aSourceArea.aStart.Col() + nCount ) ); - break; - } - - ScDocumentUniquePtr pUndoDoc; - if ( bRecord ) - { - SCTAB nTabCount = rDoc.GetTableCount(); - SCTAB nDestStartTab = aDestArea.aStart.Tab(); - - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nDestStartTab, nDestStartTab ); - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - if (rTab != nDestStartTab) - pUndoDoc->AddUndoTab( rTab, rTab ); - } - - rDoc.CopyToDocument( - aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, - aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1, - InsertDeleteFlags::AUTOFILL, false, *pUndoDoc, &aMark ); - } - - if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() && - aDestArea.aStart.Row() <= aDestArea.aEnd.Row()) - { - if ( fStart != MAXDOUBLE ) - { - SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col(); - SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row(); - SCTAB nTab = aDestArea.aStart.Tab(); - rDoc.SetValue( nValX, nValY, nTab, fStart ); - } - - sal_uLong nProgCount; - if (eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP) - nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1; - else - nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1; - nProgCount *= nCount; - ScProgress aProgress( rDoc.GetDocumentShell(), - ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true ); - - rDoc.Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), - aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), &aProgress, - aMark, nCount, eDir, eCmd, eDateCmd, fStep, fMax ); - AdjustRowHeight(rRange, true, bApi); - - rDocShell.PostPaintGridAll(); - aModificator.SetDocumentModified(); - } - - if ( bRecord ) // only now is Draw-Undo available - { - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, aDestArea, aSourceArea, std::move(pUndoDoc), aMark, - eDir, eCmd, eDateCmd, fStart, fStep, fMax) ); - } - - bSuccess = true; - } - else if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - - return bSuccess; + sc::FillSeriesOperation aOperation(*this, rDocShell, rRange, pTabMark, eDir, eCmd, eDateCmd, + fStart, fStep, fMax, bApi); + return aOperation.run(); } bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, @@ -4919,260 +2120,15 @@ bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, sal_uLong nCount, double fStep, double fMax, bool bRecord, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - ScDocument& rDoc = rDocShell.GetDocument(); - SCCOL nStartCol = rRange.aStart.Col(); - SCROW nStartRow = rRange.aStart.Row(); - SCTAB nStartTab = rRange.aStart.Tab(); - SCCOL nEndCol = rRange.aEnd.Col(); - SCROW nEndRow = rRange.aEnd.Row(); - SCTAB nEndTab = rRange.aEnd.Tab(); - - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - ScMarkData aMark(rDoc.GetSheetLimits()); - if (pTabMark) - aMark = *pTabMark; - else - { - for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) - aMark.SelectTable( nTab, true ); - } - - ScRange aSourceArea = rRange; - ScRange aDestArea = rRange; - - switch (eDir) - { - case FILL_TO_BOTTOM: - aDestArea.aEnd.SetRow( sal::static_int_cast( aSourceArea.aEnd.Row() + nCount ) ); - break; - case FILL_TO_TOP: - if (nCount > sal::static_int_cast( aSourceArea.aStart.Row() )) - { - OSL_FAIL("FillAuto: Row < 0"); - nCount = aSourceArea.aStart.Row(); - } - aDestArea.aStart.SetRow( sal::static_int_cast( aSourceArea.aStart.Row() - nCount ) ); - break; - case FILL_TO_RIGHT: - aDestArea.aEnd.SetCol( sal::static_int_cast( aSourceArea.aEnd.Col() + nCount ) ); - break; - case FILL_TO_LEFT: - if (nCount > sal::static_int_cast( aSourceArea.aStart.Col() )) - { - OSL_FAIL("FillAuto: Col < 0"); - nCount = aSourceArea.aStart.Col(); - } - aDestArea.aStart.SetCol( sal::static_int_cast( aSourceArea.aStart.Col() - nCount ) ); - break; - default: - OSL_FAIL("Wrong direction with FillAuto"); - break; - } - - if (!CheckSheetViewProtection(sc::Operation::FillAuto)) - return false; - - // Test for cell protection - //! Source range can be protected !!! - //! but can't contain matrix fragments !!! - - ScEditableTester aTester = ScEditableTester::CreateAndTestRange(rDoc, aDestArea, sc::EditAction::Unknown); - if ( !aTester.IsEditable() ) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - if ( rDoc.HasSelectedBlockMatrixFragment( nStartCol, nStartRow, - nEndCol, nEndRow, aMark ) ) - { - if (!bApi) - rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR); - return false; - } - - // FID_FILL_... slots should already had been disabled, check here for API - // calls, no message. - if (ScViewData::SelectionFillDOOM( aDestArea)) - return false; - - weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); - - ScDocumentUniquePtr pUndoDoc; - if ( bRecord ) - { - SCTAB nTabCount = rDoc.GetTableCount(); - SCTAB nDestStartTab = aDestArea.aStart.Tab(); - - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nDestStartTab, nDestStartTab ); - for (const auto& rTab : aMark) - { - if (rTab >= nTabCount) - break; - - if (rTab != nDestStartTab) - pUndoDoc->AddUndoTab( rTab, rTab ); - } - - // do not clone note captions in undo document - rDoc.CopyToDocument( - aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, - aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1, - InsertDeleteFlags::AUTOFILL, false, *pUndoDoc, &aMark ); - } - - sal_uLong nProgCount; - if (eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP) - nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1; - else - nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1; - nProgCount *= nCount; - ScProgress aProgress( rDoc.GetDocumentShell(), - ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true ); - - rDoc.Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), - aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), &aProgress, - aMark, nCount, eDir, eCmd, eDateCmd, fStep, fMax ); - - AdjustRowHeight(aDestArea, true, bApi); - - if ( bRecord ) // only now is Draw-Undo available - { - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, aDestArea, aSourceArea, std::move(pUndoDoc), aMark, - eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax) ); - } - - rDocShell.PostPaintGridAll(); - aModificator.SetDocumentModified(); - - rRange = aDestArea; // return destination range (for marking) - return true; + sc::FillAutoOperation aOperation(*this, rDocShell, rRange, pTabMark, eDir, eCmd, eDateCmd, + nCount, fStep, fMax, bRecord, bApi); + return aOperation.run(); } bool ScDocFunc::MergeCells( const ScCellMergeOption& rOption, bool bContents, bool bRecord, bool bApi, bool bEmptyMergedCells /*=false*/ ) { - ScDocShellModificator aModificator( rDocShell ); - - SCCOL nStartCol = rOption.mnStartCol; - SCROW nStartRow = rOption.mnStartRow; - SCCOL nEndCol = rOption.mnEndCol; - SCROW nEndRow = rOption.mnEndRow; - if ((nStartCol == nEndCol && nStartRow == nEndRow) || rOption.maTabs.empty()) - { - // Nothing to do. Bail out quickly - return true; - } - - ScDocument& rDoc = rDocShell.GetDocument(); - SCTAB nTab1 = *rOption.maTabs.begin(), nTab2 = *rOption.maTabs.rbegin(); - - if (bRecord && !rDoc.IsUndoEnabled()) - bRecord = false; - - if (!CheckSheetViewProtection(sc::Operation::MergeCells)) - return false; - - for (const auto& rTab : rOption.maTabs) - { - - ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(rDoc, rTab, nStartCol, nStartRow, nEndCol, nEndRow); - if (!aTester.IsEditable()) - { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return false; - } - - if ( rDoc.HasAttrib( nStartCol, nStartRow, rTab, nEndCol, nEndRow, rTab, - HasAttrFlags::Merged | HasAttrFlags::Overlapped ) ) - { - // "Merge of already merged cells not possible" - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0); - return false; - } - } - - ScDocumentUniquePtr pUndoDoc; - bool bNeedContentsUndo = false; - for (const SCTAB nTab : rOption.maTabs) - { - bool bIsBlockEmpty = ( nStartRow == nEndRow ) - ? rDoc.IsEmptyData( nStartCol+1,nStartRow, nEndCol,nEndRow, nTab ) - : rDoc.IsEmptyData( nStartCol,nStartRow+1, nStartCol,nEndRow, nTab ) && - rDoc.IsEmptyData( nStartCol+1,nStartRow, nEndCol,nEndRow, nTab ); - bool bNeedContents = bContents && !bIsBlockEmpty; - bool bNeedEmpty = bEmptyMergedCells && !bIsBlockEmpty && !bNeedContents; // if DoMergeContents then cells are emptied - - if (bRecord) - { - // test if the range contains other notes which also implies that we need an undo document - bool bHasNotes = rDoc.HasNote(nTab, nStartCol, nStartRow, nEndCol, nEndRow); - if (!pUndoDoc) - { - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo(rDoc, nTab1, nTab2); - } - // note captions are collected by drawing undo - rDoc.CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, - InsertDeleteFlags::ALL|InsertDeleteFlags::NOCAPTIONS, false, *pUndoDoc ); - if( bHasNotes ) - rDoc.BeginDrawUndo(); - } - - if (bNeedContents) - rDoc.DoMergeContents( nStartCol,nStartRow, nEndCol,nEndRow, nTab ); - else if ( bNeedEmpty ) - rDoc.DoEmptyBlock( nStartCol,nStartRow, nEndCol,nEndRow, nTab ); - rDoc.DoMerge( nStartCol,nStartRow, nEndCol,nEndRow, nTab ); - - if (rOption.mbCenter) - { - rDoc.ApplyAttr( nStartCol, nStartRow, nTab, SvxHorJustifyItem( SvxCellHorJustify::Center, ATTR_HOR_JUSTIFY ) ); - rDoc.ApplyAttr( nStartCol, nStartRow, nTab, SvxVerJustifyItem( SvxCellVerJustify::Center, ATTR_VER_JUSTIFY ) ); - } - - if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, rDoc.MaxCol(),nEndRow,nTab ), true, bApi ) ) - rDocShell.PostPaint( nStartCol, nStartRow, nTab, - nEndCol, nEndRow, nTab, PaintPartFlags::Grid ); - if (bNeedContents || rOption.mbCenter) - { - ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab); - rDoc.SetDirty(aRange, true); - } - - bool bDone = ScDetectiveFunc(rDoc, nTab).DeleteAll( ScDetectiveDelete::Circles ); - if(bDone) - DetectiveMarkInvalid(nTab); - - bNeedContentsUndo |= bNeedContents; - } - - if (pUndoDoc) - { - std::unique_ptr pDrawUndo = rDoc.GetDrawLayer() ? rDoc.GetDrawLayer()->GetCalcUndo() : nullptr; - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique(rDocShell, rOption, bNeedContentsUndo, std::move(pUndoDoc), std::move(pDrawUndo)) ); - } - - aModificator.SetDocumentModified(); - - SfxBindings* pBindings = rDocShell.GetViewBindings(); - if (pBindings) - { - pBindings->Invalidate( FID_MERGE_ON ); - pBindings->Invalidate( FID_MERGE_OFF ); - pBindings->Invalidate( FID_MERGE_TOGGLE ); - } - - return true; + sc::MergeCellsOperation aOperation(rDocShell, rOption, bContents, bRecord, bApi, bEmptyMergedCells); + return aOperation.run(); } bool ScDocFunc::UnmergeCells( const ScRange& rRange, bool bRecord, ScUndoRemoveMerge* pUndoRemoveMerge ) @@ -5282,7 +2238,7 @@ void ScDocFunc::SetNewRangeNames( std::unique_ptr pNewRanges, bool } else { - pOld = rDoc.GetRangeName(); + pOld = &rDoc.GetRangeName(); } std::unique_ptr pUndoRanges(new ScRangeName(*pOld)); std::unique_ptr pRedoRanges(new ScRangeName(*pNewRanges)); @@ -5388,9 +2344,9 @@ void ScDocFunc::CreateOneName( ScRangeName& rList, if (bInsert) { - ScRangeData* pData = new ScRangeData( rDoc, aName, aContent, - ScAddress( nPosX, nPosY, nTab)); - if (!rList.insert(pData)) + std::unique_ptr pData(new ScRangeData( rDoc, aName, aContent, + ScAddress( nPosX, nPosY, nTab))); + if (!rList.insert(std::move(pData))) { OSL_FAIL("nanu?"); } @@ -5427,7 +2383,7 @@ bool ScDocFunc::CreateNames( const ScRange& rRange, CreateNameFlags nFlags, bool if (aTab >=0) pNames = rDoc.GetRangeName(nTab); else - pNames = rDoc.GetRangeName(); + pNames = &rDoc.GetRangeName(); if (!pNames) return false; // shouldn't happen @@ -5488,114 +2444,8 @@ bool ScDocFunc::CreateNames( const ScRange& rRange, CreateNameFlags nFlags, bool bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, bool bApi ) { - ScDocShellModificator aModificator( rDocShell ); - - bool bDone = false; - ScDocument& rDoc = rDocShell.GetDocument(); - const bool bRecord = rDoc.IsUndoEnabled(); - SCTAB nTab = rStartPos.Tab(); - - //local names have higher priority than global names - ScRangeName* pLocalList = rDoc.GetRangeName(nTab); - sal_uInt16 nValidCount = 0; - for (const auto& rEntry : *pLocalList) - { - const ScRangeData& r = *rEntry.second; - if (!r.HasType(ScRangeData::Type::Database)) - ++nValidCount; - } - ScRangeName* pList = rDoc.GetRangeName(); - for (const auto& rEntry : *pList) - { - const ScRangeData& r = *rEntry.second; - if (!r.HasType(ScRangeData::Type::Database) && !pLocalList->findByUpperName(r.GetUpperName())) - ++nValidCount; - } - - if (nValidCount) - { - SCCOL nStartCol = rStartPos.Col(); - SCROW nStartRow = rStartPos.Row(); - SCCOL nEndCol = nStartCol + 1; - SCROW nEndRow = nStartRow + static_cast(nValidCount) - 1; - - if (!CheckSheetViewProtection(sc::Operation::InsertNameList)) - return false; - - ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(rDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow); - if (aTester.IsEditable()) - { - ScDocumentUniquePtr pUndoDoc; - - if (bRecord) - { - pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nTab, nTab ); - rDoc.CopyToDocument(nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, - InsertDeleteFlags::ALL, false, *pUndoDoc); - - rDoc.BeginDrawUndo(); // because of adjusting heights - } - - std::unique_ptr ppSortArray(new ScRangeData* [ nValidCount ]); - sal_uInt16 j = 0; - for (const auto& rEntry : *pLocalList) - { - ScRangeData& r = *rEntry.second; - if (!r.HasType(ScRangeData::Type::Database)) - ppSortArray[j++] = &r; - } - for (const auto& [rName, rxData] : *pList) - { - ScRangeData& r = *rxData; - if (!r.HasType(ScRangeData::Type::Database) && !pLocalList->findByUpperName(rName)) - ppSortArray[j++] = &r; - } - qsort( static_cast(ppSortArray.get()), nValidCount, sizeof(ScRangeData*), - &ScRangeData_QsortNameCompare ); - OUString aName; - OUStringBuffer aContent; - OUString aFormula; - SCROW nOutRow = nStartRow; - for (j=0; jGetName(aName); - // adjust relative references to the left column in Excel-compliant way: - pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab )); - aFormula = "=" + aContent; - ScSetStringParam aParam; - aParam.setTextInput(); - rDoc.SetString(ScAddress(nStartCol,nOutRow,nTab), aName, &aParam); - rDoc.SetString(ScAddress(nEndCol,nOutRow,nTab), aFormula, &aParam); - ++nOutRow; - } - - ppSortArray.reset(); - - if (bRecord) - { - ScDocumentUniquePtr pRedoDoc(new ScDocument( SCDOCMODE_UNDO )); - pRedoDoc->InitUndo( rDoc, nTab, nTab ); - rDoc.CopyToDocument(nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, - InsertDeleteFlags::ALL, false, *pRedoDoc); - - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique( rDocShell, - ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ), - std::move(pUndoDoc), std::move(pRedoDoc) ) ); - } - - if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,rDoc.MaxCol(),nEndRow,nTab), true, true)) - rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PaintPartFlags::Grid ); - - aModificator.SetDocumentModified(); - bDone = true; - } - else if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - } - return bDone; + sc::InsertNameListOperation aOperation(rDocShell, rStartPos, bApi); + return aOperation.run(); } void ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd ) @@ -5830,38 +2680,8 @@ void ScDocFunc::SetConditionalFormatList( ScConditionalFormatList* pList, SCTAB void ScDocFunc::ConvertFormulaToValue( const ScRange& rRange, bool bInteraction ) { - ScDocShellModificator aModificator(rDocShell); - ScDocument& rDoc = rDocShell.GetDocument(); - bool bRecord = true; - if (!rDoc.IsUndoEnabled()) - bRecord = false; - - if (!CheckSheetViewProtection(sc::Operation::ConvertFormulaToValue)) - return; - - ScEditableTester aTester = ScEditableTester::CreateAndTestRange(rDoc, rRange, sc::EditAction::Unknown); - if (!aTester.IsEditable()) - { - if (bInteraction) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return; - } - - sc::TableValues aUndoVals(rRange); - sc::TableValues* pUndoVals = bRecord ? &aUndoVals : nullptr; - - rDoc.ConvertFormulaToValue(rRange, pUndoVals); - - if (bRecord && pUndoVals) - { - rDocShell.GetUndoManager()->AddUndoAction( - std::make_unique(rDocShell, *pUndoVals)); - } - - rDocShell.PostPaint(rRange, PaintPartFlags::Grid); - rDocShell.PostDataChanged(); - rDoc.BroadcastCells(rRange, SfxHintId::ScDataChanged); - aModificator.SetDocumentModified(); + sc::ConvertFormulaToValueOperation aOperation(rDocShell, rRange, bInteraction); + aOperation.run(); } void ScDocFunc::EnterListAction(TranslateId pNameResId) @@ -5881,181 +2701,45 @@ void ScDocFunc::EndListAction() bool ScDocFunc::InsertSparklines(ScRange const& rDataRange, ScRange const& rSparklineRange, const std::shared_ptr& pSparklineGroup) { - if (!CheckSheetViewProtection(sc::Operation::SparklineInsert)) - return false; - - std::vector aSparklineDataVector; - - if (rSparklineRange.aStart.Col() == rSparklineRange.aEnd.Col()) - { - sal_Int32 nOutputRowSize = rSparklineRange.aEnd.Row() - rSparklineRange.aStart.Row(); - - auto eInputOrientation = sc::calculateOrientation(nOutputRowSize, rDataRange); - - if (eInputOrientation == sc::RangeOrientation::Unknown) - return false; - - sal_Int32 nIndex = 0; - - for (ScAddress aAddress = rSparklineRange.aStart; aAddress.Row() <= rSparklineRange.aEnd.Row(); - aAddress.IncRow()) - { - ScRange aInputRangeSlice = rDataRange; - if (eInputOrientation == sc::RangeOrientation::Row) - { - aInputRangeSlice.aStart.SetRow(rDataRange.aStart.Row() + nIndex); - aInputRangeSlice.aEnd.SetRow(rDataRange.aStart.Row() + nIndex); - } - else - { - aInputRangeSlice.aStart.SetCol(rDataRange.aStart.Col() + nIndex); - aInputRangeSlice.aEnd.SetCol(rDataRange.aStart.Col() + nIndex); - } - - aSparklineDataVector.emplace_back(aAddress, aInputRangeSlice); - - nIndex++; - } - } - else if (rSparklineRange.aStart.Row() == rSparklineRange.aEnd.Row()) - { - sal_Int32 nOutputColSize = rSparklineRange.aEnd.Col() - rSparklineRange.aStart.Col(); - - auto eInputOrientation = sc::calculateOrientation(nOutputColSize, rDataRange); - - if (eInputOrientation == sc::RangeOrientation::Unknown) - return false; - - sal_Int32 nIndex = 0; - - for (ScAddress aAddress = rSparklineRange.aStart; aAddress.Col() <= rSparklineRange.aEnd.Col(); - aAddress.IncCol()) - { - ScRange aInputRangeSlice = rDataRange; - if (eInputOrientation == sc::RangeOrientation::Row) - { - aInputRangeSlice.aStart.SetRow(rDataRange.aStart.Row() + nIndex); - aInputRangeSlice.aEnd.SetRow(rDataRange.aStart.Row() + nIndex); - } - else - { - aInputRangeSlice.aStart.SetCol(rDataRange.aStart.Col() + nIndex); - aInputRangeSlice.aEnd.SetCol(rDataRange.aStart.Col() + nIndex); - } - - aSparklineDataVector.emplace_back(aAddress, aInputRangeSlice); - - nIndex++; - } - } - - if (aSparklineDataVector.empty()) - return false; - - auto pUndoInsertSparkline = std::make_unique(rDocShell, aSparklineDataVector, pSparklineGroup); - // insert the sparkline by "redoing" - pUndoInsertSparkline->Redo(); - rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoInsertSparkline)); - - ScDocument& rDoc = rDocShell.GetDocument(); - if (rSparklineRange.aStart == rSparklineRange.aEnd - && rDoc.HasAttrib(rSparklineRange, HasAttrFlags::Merged)) - { - ScRange aExtendMergeRange(rSparklineRange); - rDoc.ExtendMerge(aExtendMergeRange); - rDocShell.PostPaint(aExtendMergeRange, PaintPartFlags::Grid); - } - - return true; + sc::InsertSparklinesOperation aOperation(rDocShell, rDataRange, rSparklineRange, pSparklineGroup); + return aOperation.run(); } bool ScDocFunc::DeleteSparkline(ScAddress const& rAddress) { - auto& rDocument = rDocShell.GetDocument(); - - if (!rDocument.HasSparkline(rAddress)) - return false; - - if (!CheckSheetViewProtection(sc::Operation::SparklineDelete)) - return false; - - - auto pUndoDeleteSparkline = std::make_unique(rDocShell, rAddress); - // delete sparkline by "redoing" - pUndoDeleteSparkline->Redo(); - rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoDeleteSparkline)); - - return true; + sc::DeleteSparklineOperation aOperation(rDocShell, rAddress); + return aOperation.run(); } bool ScDocFunc::DeleteSparklineGroup(std::shared_ptr const& pSparklineGroup, SCTAB nTab) { - if (!pSparklineGroup) - return false; - - auto& rDocument = rDocShell.GetDocument(); - - if (!rDocument.HasTable(nTab)) - return false; - - if (!CheckSheetViewProtection(sc::Operation::SparklineGroupDelete)) - return false; - - auto pUndo = std::make_unique(rDocShell, pSparklineGroup, nTab); - // delete sparkline group by "redoing" - pUndo->Redo(); - rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); - return true; + sc::DeleteSparklineGroupOperation aOperation(rDocShell, pSparklineGroup, nTab); + return aOperation.run(); } bool ScDocFunc::ChangeSparklineGroupAttributes(std::shared_ptr const& pExistingSparklineGroup, sc::SparklineAttributes const& rNewAttributes) { - if (!CheckSheetViewProtection(sc::Operation::SparklineGroupChange)) - return false; - - - auto pUndo = std::make_unique(rDocShell, pExistingSparklineGroup, rNewAttributes); - // change sparkline group attributes by "redoing" - pUndo->Redo(); - rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); - return true; + sc::ChangeSparklineGroupAttributesOperation aOperation(rDocShell, pExistingSparklineGroup, rNewAttributes); + return aOperation.run(); } bool ScDocFunc::GroupSparklines(ScRange const& rRange, std::shared_ptr const& rpGroup) { - if (!CheckSheetViewProtection(sc::Operation::SparklineGroup)) - return false; - - auto pUndo = std::make_unique(rDocShell, rRange, rpGroup); - // group sparklines by "redoing" - pUndo->Redo(); - rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); - return true; + sc::GroupSparklinesOperation aOperation(rDocShell, rRange, rpGroup); + return aOperation.run(); } bool ScDocFunc::UngroupSparklines(ScRange const& rRange) { - if (!CheckSheetViewProtection(sc::Operation::SparklineUngroup)) - return false; - - auto pUndo = std::make_unique(rDocShell, rRange); - // ungroup sparklines by "redoing" - pUndo->Redo(); - rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); - return true; + sc::UngroupSparklinesOperation aOperation(rDocShell, rRange); + return aOperation.run(); } bool ScDocFunc::ChangeSparkline(std::shared_ptr const& rpSparkline, SCTAB nTab, ScRangeList const& rDataRange) { - if (!CheckSheetViewProtection(sc::Operation::SparklineChange)) - return false; - - auto pUndo = std::make_unique(rDocShell, rpSparkline, nTab, rDataRange); - // change sparkline by "redoing" - pUndo->Redo(); - rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); - return true; + sc::ChangeSparklineOperation aOperation(rDocShell, rpSparkline, nTab, rDataRange); + return aOperation.run(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/docshell/docfuncutil.cxx b/sc/source/ui/docshell/docfuncutil.cxx index 37d20dbdea2e..dbe28e332e76 100644 --- a/sc/source/ui/docshell/docfuncutil.cxx +++ b/sc/source/ui/docshell/docfuncutil.cxx @@ -18,7 +18,10 @@ */ #include +#include #include +#include +#include #include #include #include @@ -29,6 +32,26 @@ namespace sc { +bool DocFuncUtil::demolishMatrixMaster(ScDocFunc& rDocFunc, const ScDocument& rDoc, + const ScAddress& rPos, bool bApi) +{ + const ScFormulaCell* pCell = rDoc.GetFormulaCell(rPos); + if (!pCell || pCell->GetMatrixFlag() != ScMatrixMode::Formula) + return false; + SCCOL nCols = 0; + SCROW nRows = 0; + pCell->GetMatColsRows(nCols, nRows); + if (nCols <= 1 && nRows <= 1) + return false; + + ScMarkData aMark(rDoc.GetSheetLimits()); + aMark.SelectOneTable(rPos.Tab()); + aMark.SetMarkArea(ScRange(rPos)); + rDocFunc.DeleteContents(aMark, InsertDeleteFlags::CONTENTS, + /*bRecord*/ true, bApi); + return true; +} + bool DocFuncUtil::hasProtectedTab( const ScDocument& rDoc, const ScMarkData& rMark ) { SCTAB nTabCount = rDoc.GetTableCount(); @@ -79,12 +102,14 @@ void DocFuncUtil::addDeleteContentsUndo( SfxUndoManager* pUndoMgr, ScDocShell& rDocSh, const ScMarkData& rMark, const ScRange& rRange, ScDocumentUniquePtr&& pUndoDoc, InsertDeleteFlags nFlags, const std::shared_ptr& pSpans, - bool bMulti, bool bDrawUndo ) + bool bMulti, bool bDrawUndo, + std::vector const& rRestoreExpandedMatrices) { std::unique_ptr pUndo( new ScUndoDeleteContents( rDocSh, rMark, rRange, std::move(pUndoDoc), bMulti, nFlags, bDrawUndo)); pUndo->SetDataSpans(pSpans); + pUndo->SetRestoreExpandedMatrices(rRestoreExpandedMatrices); pUndoMgr->AddUndoAction(std::move(pUndo)); } diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 9355c3156340..1eb2291515f7 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include @@ -786,7 +786,7 @@ void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint ) else { // switching to shared mode has failed, the document should be opened readonly - // TODO/LATER: And error message should be shown here probably + // TODO/LATER: An error message should be shown here probably SetReadOnlyUI(); } } @@ -1289,11 +1289,11 @@ bool ScDocShell::ConvertFrom( SfxMedium& rMedium ) { // default for lotus import (from API without options): // IBM_437 encoding - sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_437 ); + sItStr = ScGlobal::GetEncodingString( RTL_TEXTENCODING_IBM_437 ); } ErrCode eError = ScFormatFilter::Get().ScImportLotus123( rMedium, *m_pDocument, - ScGlobal::GetCharsetValue(sItStr)); + ScGlobal::GetEncodingValue(sItStr)); if (eError != ERRCODE_NONE) { if (!GetErrorIgnoreWarning()) @@ -1363,7 +1363,7 @@ bool ScDocShell::ConvertFrom( SfxMedium& rMedium ) // default for ascii import (from API without options): // UTF-8 encoding, comma, double quotes - aOptions.SetCharSet(RTL_TEXTENCODING_UTF8); + aOptions.SetEncoding(RTL_TEXTENCODING_UTF8); aOptions.SetFieldSeps( OUString(',') ); aOptions.SetTextSep( '"' ); } @@ -1380,7 +1380,15 @@ bool ScDocShell::ConvertFrom( SfxMedium& rMedium ) SvStream* pInStream = rMedium.GetInStream(); if (pInStream) { - pInStream->SetStreamEncoding( aOptions.GetCharSet() ); + pInStream->SetStreamEncoding( aOptions.GetEncoding() ); + // tdf#169591 in case of RTL_TEXTENCODING_UCS2, we need to know endianness too. + // For this, we'll have to call a second time DetectEncoding. + // An alternative would be to save the endianness in ScFilterOptionsObj::aFilterOptions + // but does it worth it? + if (pInStream->GetStreamEncoding() == RTL_TEXTENCODING_UCS2) + { + pInStream->DetectEncoding(); + } pInStream->Seek( 0 ); bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL(), SotClipboardFormatId::STRING ); eError = bRet ? ERRCODE_NONE : SCERR_IMPORT_CONNECT; @@ -1389,9 +1397,17 @@ bool ScDocShell::ConvertFrom( SfxMedium& rMedium ) m_pDocument->SetAllFormulasDirty(aCxt); // tdf#82254 - check whether to include a byte-order-mark in the output - if (const bool bIncludeBOM = aImpEx.GetIncludeBOM()) - { + const bool bIncludeBOM = aImpEx.GetIncludeBOM(); + if (bIncludeBOM) aOptions.SetIncludeBOM(bIncludeBOM); + // tdf#169591 - check whether to include endianness + const SvStreamEndian nEndianness = aImpEx.GetEndianness(); + if (nEndianness == SvStreamEndian::BIG) + aOptions.SetEndianness(nEndianness); + // if aOptions has been set at least with one parameter, + // remember it + if (bIncludeBOM || (nEndianness == SvStreamEndian::BIG)) + { rMedium.GetItemSet().Put( SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions.WriteToString())); } @@ -1452,12 +1468,12 @@ bool ScDocShell::ConvertFrom( SfxMedium& rMedium ) // default for dBase import (from API without options): // IBM_850 encoding - sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 ); + sItStr = ScGlobal::GetEncodingString( RTL_TEXTENCODING_IBM_850 ); } ScDocRowHeightUpdater::TabRanges aRecalcRanges(0, m_pDocument->MaxRow()); ErrCode eError = DBaseImport( rMedium.GetPhysicalName(), - ScGlobal::GetCharsetValue(sItStr), aColWidthParam, aRecalcRanges.maRanges ); + ScGlobal::GetEncodingValue(sItStr), aColWidthParam, aRecalcRanges.maRanges ); aRecalcRowRangesArray.push_back(std::move(aRecalcRanges)); if (eError != ERRCODE_NONE) @@ -1491,11 +1507,11 @@ bool ScDocShell::ConvertFrom( SfxMedium& rMedium ) // default for DIF import (from API without options): // ISO8859-1/MS_1252 encoding - sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 ); + sItStr = ScGlobal::GetEncodingString( RTL_TEXTENCODING_MS_1252 ); } eError = ScFormatFilter::Get().ScImportDif( *pStream, m_pDocument.get(), ScAddress(0,0,0), - ScGlobal::GetCharsetValue(sItStr)); + ScGlobal::GetEncodingValue(sItStr)); if (eError != ERRCODE_NONE) { if (!GetErrorIgnoreWarning()) @@ -2018,22 +2034,23 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, { sal_Unicode cDelim = rAsciiOpt.nFieldSepCode; sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode; - rtl_TextEncoding eCharSet = rAsciiOpt.eCharSet; + rtl_TextEncoding eEncoding = rAsciiOpt.eEncoding; bool bFixedWidth = rAsciiOpt.bFixedWidth; bool bSaveNumberAsSuch = rAsciiOpt.bSaveNumberAsSuch; bool bSaveAsShown = rAsciiOpt.bSaveAsShown; bool bShowFormulas = rAsciiOpt.bSaveFormulas; bool bIncludeBOM = rAsciiOpt.bIncludeBOM; + SvStreamEndian nEndianness = rAsciiOpt.nEndianness; - rtl_TextEncoding eOldCharSet = rStream.GetStreamEncoding(); - rStream.SetStreamEncoding( eCharSet ); + rtl_TextEncoding eOldEncoding = rStream.GetStreamEncoding(); + rStream.SetStreamEncoding( eEncoding ); SvStreamEndian nOldNumberFormatInt = rStream.GetEndian(); OString aStrDelimEncoded; // only used if not Unicode OUString aStrDelimDecoded; // only used if context encoding OString aDelimEncoded; OUString aDelimDecoded; bool bContextOrNotAsciiEncoding; - if ( eCharSet == RTL_TEXTENCODING_UNICODE ) + if ( eEncoding == RTL_TEXTENCODING_UNICODE ) { rStream.StartWritingUnicodeText(); bContextOrNotAsciiEncoding = false; @@ -2041,21 +2058,23 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, else { // tdf#82254 - check whether to include a byte-order-mark in the output - if (bIncludeBOM && eCharSet == RTL_TEXTENCODING_UTF8) + if (bIncludeBOM && eEncoding == RTL_TEXTENCODING_UTF8) rStream.WriteUChar(0xEF).WriteUChar(0xBB).WriteUChar(0xBF); - aStrDelimEncoded = OString(&cStrDelim, 1, eCharSet); - aDelimEncoded = OString(&cDelim, 1, eCharSet); + if (nEndianness == SvStreamEndian::BIG) + rStream.SetEndian(SvStreamEndian::BIG); + aStrDelimEncoded = OString(&cStrDelim, 1, eEncoding); + aDelimEncoded = OString(&cDelim, 1, eEncoding); rtl_TextEncodingInfo aInfo; aInfo.StructSize = sizeof(aInfo); - if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) ) + if ( rtl_getTextEncodingInfo( eEncoding, &aInfo ) ) { bContextOrNotAsciiEncoding = (((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) || ((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0)); if ( bContextOrNotAsciiEncoding ) { - aStrDelimDecoded = OStringToOUString(aStrDelimEncoded, eCharSet); - aDelimDecoded = OStringToOUString(aDelimEncoded, eCharSet); + aStrDelimDecoded = OStringToOUString(aStrDelimEncoded, eEncoding); + aDelimDecoded = OStringToOUString(aDelimEncoded, eEncoding); } } else @@ -2100,7 +2119,7 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, aString = "sep=" + OUStringChar(cDelim); if (cStrDelim != 0) rStream.WriteUniOrByteChar( '"'); - rStream.WriteUnicodeOrByteText(aString, eCharSet); + rStream.WriteUnicodeOrByteText(aString, eEncoding); if (cStrDelim != 0) rStream.WriteUniOrByteChar( '"'); endlub( rStream ); @@ -2304,7 +2323,7 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, { if ( cStrDelim != 0 ) //@ BugId 55355 { - if ( eCharSet == RTL_TEXTENCODING_UNICODE ) + if ( eEncoding == RTL_TEXTENCODING_UNICODE ) { bool bNeedQuotes = false; sal_Int32 nPos = getTextSepPos(aUniString, rAsciiOpt, cStrDelim, cDelim, bNeedQuotes); @@ -2317,7 +2336,7 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, if ( bNeedQuotes || bForceQuotes ) rStream.WriteUniOrByteChar( cStrDelim ); - rStream.WriteUnicodeOrByteText(aUniString, eCharSet); + rStream.WriteUnicodeOrByteText(aUniString, eEncoding); if ( bNeedQuotes || bForceQuotes ) rStream.WriteUniOrByteChar( cStrDelim ); } @@ -2340,9 +2359,9 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, if ( bContextOrNotAsciiEncoding ) { // to byte encoding - OString aStrEnc = OUStringToOString(aUniString, eCharSet); + OString aStrEnc = OUStringToOString(aUniString, eEncoding); // back to Unicode - OUString aStrDec = OStringToOUString(aStrEnc, eCharSet); + OUString aStrDec = OStringToOUString(aStrEnc, eEncoding); // search on re-decoded string bool bNeedQuotes = false; @@ -2356,13 +2375,13 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, // write byte re-encoded if ( bNeedQuotes || bForceQuotes ) rStream.WriteUniOrByteChar( cStrDelim ); - rStream.WriteUnicodeOrByteText( aStrDec, eCharSet ); + rStream.WriteUnicodeOrByteText( aStrDec, eEncoding ); if ( bNeedQuotes || bForceQuotes ) rStream.WriteUniOrByteChar( cStrDelim ); } else { - OString aStrEnc = OUStringToOString(aUniString, eCharSet); + OString aStrEnc = OUStringToOString(aUniString, eEncoding); // search on encoded string bool bNeedQuotes = false; @@ -2430,7 +2449,7 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, endlub( rStream ); } - rStream.SetStreamEncoding( eOldCharSet ); + rStream.SetStreamEncoding( eOldEncoding ); rStream.SetEndian( nOldNumberFormatInt ); } @@ -2638,18 +2657,18 @@ bool ScDocShell::ConvertTo( SfxMedium &rMed ) } else if (aFltName == SC_DBASE_FILTER_NAME) { - OUString sCharSet; + OUString sEncoding; if ( const SfxStringItem* pOptionsItem = rMed.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) { - sCharSet = pOptionsItem->GetValue(); + sEncoding = pOptionsItem->GetValue(); } - if (sCharSet.isEmpty()) + if (sEncoding.isEmpty()) { // default for dBase export (from API without options): // IBM_850 encoding - sCharSet = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 ); + sEncoding = ScGlobal::GetEncodingString( RTL_TEXTENCODING_IBM_850 ); } weld::WaitObject aWait( GetActiveDialogParent() ); @@ -2658,7 +2677,7 @@ bool ScDocShell::ConvertTo( SfxMedium &rMed ) bool bHasMemo = false; ErrCodeMsg eError = DBaseExport( - rMed.GetPhysicalName(), ScGlobal::GetCharsetValue(sCharSet), bHasMemo); + rMed.GetPhysicalName(), ScGlobal::GetEncodingValue(sEncoding), bHasMemo); INetURLObject aTmpFile( rMed.GetPhysicalName(), INetProtocol::File ); if ( bHasMemo ) @@ -2721,12 +2740,12 @@ bool ScDocShell::ConvertTo( SfxMedium &rMed ) // default for DIF export (from API without options): // ISO8859-1/MS_1252 encoding - sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 ); + sItStr = ScGlobal::GetEncodingString( RTL_TEXTENCODING_MS_1252 ); } weld::WaitObject aWait( GetActiveDialogParent() ); ScFormatFilter::Get().ScExportDif( *pStream, *m_pDocument, ScAddress(0,0,0), - ScGlobal::GetCharsetValue(sItStr) ); + ScGlobal::GetEncodingValue(sItStr) ); bRet = true; if (m_pDocument->GetTableCount() > 1) @@ -2915,8 +2934,6 @@ ScDocShell::ScDocShell( const SfxModelFlags i_nSfxCreationFlags, const std::shar m_aDdeTextFmt(u"TEXT"_ustr), m_nPrtToScreenFactor( 1.0 ), m_pImpl ( new DocShell_Impl ), - m_bHeaderOn ( true ), - m_bFooterOn ( true ), m_bIsEmpty ( true ), m_bIsInUndo ( false ), m_bDocumentModifiedPending( false ), diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx index 4d250793cb26..b831ff7b98e5 100644 --- a/sc/source/ui/docshell/docsh3.cxx +++ b/sc/source/ui/docshell/docsh3.cxx @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -670,7 +669,7 @@ void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, weld::Wind OUString aDate = ScGlobal::getLocaleData().getDate( aDT ) + " " + ScGlobal::getLocaleData().getTime( aDT, false ); - SfxItemSetFixed aSet( GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aSet.Put( SvxPostItTextItem ( aComment, SID_ATTR_POSTIT_TEXT ) ); aSet.Put( SvxPostItAuthorItem( aAuthor, SID_ATTR_POSTIT_AUTHOR ) ); diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx index b3db4c8b19e8..38e638d19a3c 100644 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -24,12 +24,10 @@ #include #include #include -#include +#include #include #include #include -#include -#include #include #include #include @@ -39,10 +37,9 @@ #include #include #include -#include #include #include -#include +#include #include #include #include @@ -97,6 +94,8 @@ #include #include #include +#include +#include #include #include #include @@ -109,6 +108,7 @@ #include #include #include +#include #include #include #include @@ -212,9 +212,18 @@ void ScDocShell::ReloadAllLinks() } m_pDocument->UpdateAreaLinks(); + + // Draw-layer fill bitmap host links are registered when SID_UPDATETABLINKS + // runs at load, so they are not re-scanned here, only updated. + if (sfx2::LinkManager* pLinkMgr = m_pDocument->GetDocLinkManager().getLinkManager(false)) + { + registerDeferredFormImageLinks(GetDeferredFormControlImages(), *pLinkMgr); + ClearDeferredFormControlImages(); + pLinkMgr->UpdateAllLinks(false, u""_ustr); + } } -IMPL_LINK( ScDocShell, ReloadAllLinksHdl, weld::Button&, rButton, void ) +void ScDocShell::PerformLinkUpdate() { ScDocument& rDoc = GetDocument(); if (rDoc.HasLinkFormulaNeedingCheck() && rDoc.GetDocLinkManager().hasExternalRefLinks()) @@ -222,7 +231,7 @@ IMPL_LINK( ScDocShell, ReloadAllLinksHdl, weld::Button&, rButton, void ) // If we have WEBSERVICE/Dde link and other external links in the document, it might indicate some // exfiltration attempt, add *another* warning about this on top of the "Security Warning" // shown in the infobar before they got here. - std::unique_ptr xQueryBox(Application::CreateMessageDialog(&rButton, + std::unique_ptr xQueryBox(Application::CreateMessageDialog(GetActiveDialogParent(), VclMessageType::Warning, VclButtonsType::YesNo, ScResId(STR_TRUST_DOCUMENT_WARNING))); xQueryBox->set_secondary_text(ScResId(STR_WEBSERVICE_WITH_LINKS_WARNING)); @@ -232,21 +241,15 @@ IMPL_LINK( ScDocShell, ReloadAllLinksHdl, weld::Button&, rButton, void ) } ReloadAllLinks(); +} - ScTabViewShell* pViewSh = GetBestViewShell(); - SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr; - if (pViewFrame) - pViewFrame->RemoveInfoBar(u"enablecontent"); - SAL_WARN_IF(!pViewFrame, "sc", "expected there to be a ViewFrame"); +bool ScDocShell::HasExternalLinks() const +{ + return GetDocument().HasExternalLinks() || !GetDeferredFormControlImages().empty(); } namespace { -class LinkHelp -{ -public: - DECL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, void); -}; void lcl_setLOKLocale(const ScTabViewShell& rViewShell, const LanguageType eLang) { @@ -258,12 +261,6 @@ void lcl_setLOKLocale(const ScTabViewShell& rViewShell, const LanguageType eLang } // end anonymous namespace -IMPL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, rBtn, void) -{ - if (Help* pHelp = Application::GetHelp()) - pHelp->Start(HID_UPDATE_LINK_WARNING, &rBtn); -} - void ScDocShell::SetLanguage(LanguageType eLatin, LanguageType eCjk, LanguageType eCtl) { if (comphelper::LibreOfficeKit::isActive()) @@ -493,6 +490,15 @@ void ScDocShell::Execute( SfxRequest& rReq ) break; case SID_UPDATETABLINKS: { + // Draw-layer fill bitmap links are registered as the shapes are + // imported, via the draw model's link tracker. Form control + // images are collected during import and registered here. + if (sfx2::LinkManager* pLinkMgr = m_pDocument->GetDocLinkManager().getLinkManager(false)) + { + registerDeferredFormImageLinks(GetDeferredFormControlImages(), *pLinkMgr); + ClearDeferredFormControlImages(); + } + ScLkUpdMode nSet = GetLinkUpdateModeState(); if (nSet == LM_ALWAYS) @@ -503,35 +509,12 @@ void ScDocShell::Execute( SfxRequest& rReq ) else if (nSet == LM_NEVER) { getEmbeddedObjectContainer().setUserAllowsLinkUpdate(false); + CheckPendingLinkUpdateInfobar(); rReq.Ignore(); } else if (nSet == LM_ON_DEMAND) { - ScTabViewShell* pViewSh = GetBestViewShell(); - SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr; - if (pViewFrame) - { - pViewFrame->RemoveInfoBar(u"enablecontent"); - auto pInfoBar = pViewFrame->AppendInfoBar(u"enablecontent"_ustr, SfxResId(RID_SECURITY_WARNING_TITLE), - ScResId(STR_RELOAD_TABLES), InfobarType::WARNING); - if (pInfoBar) - { - weld::Button& rHelpBtn = pInfoBar->addButton(); - rHelpBtn.set_label(GetStandardText(StandardButtonType::Help).replaceFirst("~", "")); - rHelpBtn.connect_clicked(LINK(nullptr, LinkHelp, DispatchHelpLinksHdl)); - weld::Button& rBtn = pInfoBar->addButton(); - rBtn.set_label(ScResId(STR_ENABLE_CONTENT)); - rBtn.set_tooltip_text(ScResId(STR_ENABLE_CONTENT_TOOLTIP)); - rBtn.connect_clicked(LINK(this, ScDocShell, ReloadAllLinksHdl)); - - // when active content is disabled the "Allow updating" button has no functionality. - if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get()) - { - rBtn.set_tooltip_text(ScResId(STR_ENABLE_CONTENT_TOOLTIP_DISABLED)); - rBtn.set_sensitive(false); - } - } - } + ShowLinkUpdateInfobar(); rReq.Done(); } } @@ -582,7 +565,7 @@ void ScDocShell::Execute( SfxRequest& rReq ) if ( bContinue ) // error at import -> abort { - // internal operations, if some where saved + // internal operations, if some were saved if ( rDBData.HasQueryParam() || rDBData.HasSortParam() || rDBData.HasSubTotalParam() ) @@ -2208,8 +2191,8 @@ void ScDocShell::ExecutePageStyle( const SfxViewShell& rCaller, auto xRequest = std::make_shared(rReq); rReq.Ignore(); // the 'old' request is not relevant any more pDlg->StartExecuteAsync([this, pDlg, xRequest=std::move(xRequest), pStyleSheet, - xOldData=std::move(xOldData), aOldName, &rStyleSet, - nCurTab, &rCaller, bUndo](sal_Int32 nResult) { + xOldData=std::move(xOldData), aOldName, + &rCaller, bUndo](sal_Int32 nResult) { if ( nResult == RET_OK ) { const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); @@ -2231,8 +2214,6 @@ void ScDocShell::ExecutePageStyle( const SfxViewShell& rCaller, if ( pOutSet ) m_pDocument->ModifyStyleSheet( *pStyleSheet, *pOutSet ); - // memorizing for GetState(): - GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, m_bHeaderOn, m_bFooterOn ); rCaller.GetViewFrame().GetBindings().Invalidate( SID_HFEDIT ); ScStyleSaveData aNewData; @@ -2289,75 +2270,23 @@ void ScDocShell::ExecutePageStyle( const SfxViewShell& rCaller, { case SvxPageUsage::Left: case SvxPageUsage::Right: - { - if ( m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT; - else if ( SvxPageUsage::Right == eUsage ) - { - if ( !m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER; - else if ( m_bHeaderOn && !m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_RIGHTHEADER; - } - else - { - // #69193a# respect "shared" setting - if ( !m_bHeaderOn && m_bFooterOn ) - nResId = bShareFooter ? - RID_SCDLG_HFEDIT_RIGHTFOOTER : - RID_SCDLG_HFEDIT_LEFTFOOTER; - else if ( m_bHeaderOn && !m_bFooterOn ) - nResId = bShareHeader ? - RID_SCDLG_HFEDIT_RIGHTHEADER : - RID_SCDLG_HFEDIT_LEFTHEADER; - } - } - break; + nResId = RID_SCDLG_HFEDIT; + break; case SvxPageUsage::Mirror: case SvxPageUsage::All: default: { if ( !bShareHeader && !bShareFooter ) - { - if ( m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_ALL; - else if ( !m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_FOOTER; - else if ( m_bHeaderOn && !m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_HEADER; - } + nResId = RID_SCDLG_HFEDIT_ALL; else if ( bShareHeader && bShareFooter ) - { - if ( m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT; - else - { - if ( !m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER; - else if ( m_bHeaderOn && !m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_RIGHTHEADER; - } - } + nResId = RID_SCDLG_HFEDIT; else if ( !bShareHeader && bShareFooter ) - { - if ( m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_SFTR; - else if ( !m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER; - else if ( m_bHeaderOn && !m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_HEADER; - } + nResId = RID_SCDLG_HFEDIT_SFTR; else if ( bShareHeader && !bShareFooter ) - { - if ( m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_SHDR; - else if ( !m_bHeaderOn && m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_FOOTER; - else if ( m_bHeaderOn && !m_bFooterOn ) - nResId = RID_SCDLG_HFEDIT_RIGHTHEADER; - } + nResId = RID_SCDLG_HFEDIT_SHDR; } + break; } ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); @@ -2404,25 +2333,6 @@ void ScDocShell::GetStatePageStyle( SfxItemSet& rSet, case SID_STATUS_PAGESTYLE: rSet.Put( SfxStringItem( nWhich, m_pDocument->GetPageStyle( nCurTab ) ) ); break; - - case SID_HFEDIT: - { - OUString aStr = m_pDocument->GetPageStyle( nCurTab ); - ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool(); - SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStr, SfxStyleFamily::Page ); - - OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" ); - - if ( pStyleSheet ) - { - SfxItemSet& rStyleSet = pStyleSheet->GetItemSet(); - GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, m_bHeaderOn, m_bFooterOn ); - - if ( !m_bHeaderOn && !m_bFooterOn ) - rSet.DisableItem( nWhich ); - } - } - break; } nWhich = aIter.NextWhich(); @@ -2487,6 +2397,20 @@ void ScDocShell::GetState( SfxItemSet &rSet ) rSet.Put( SfxInt16Item( nWhich, m_pDocument->GetTableCount() ) ); break; + case SID_TABLE_STYLES: + { + ScTableStyles* pStyles = m_pDocument->GetTableStyles(); + if (pStyles) + { + tools::JsonWriter aTree; + pStyles->generateJSON(aTree); + OString aStr = aTree.finishAndGetAsOString(); + rSet.Put( + SfxStringItem( nWhich, OStringToOUString( aStr, RTL_TEXTENCODING_UTF8 ) ) ); + } + } + break; + case SID_ATTR_YEAR2000 : rSet.Put( SfxUInt16Item( nWhich, m_pDocument->GetDocOptions().GetYear2000() ) ); @@ -2851,42 +2775,6 @@ void ScDocShell::SnapVisArea( tools::Rectangle& rRect ) const ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle } -void ScDocShell::GetPageOnFromPageStyleSet( const SfxItemSet* pStyleSet, - SCTAB nCurTab, - bool& rbHeader, - bool& rbFooter ) -{ - if ( !pStyleSet ) - { - ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool(); - SfxStyleSheetBase* pStyleSheet = pStylePool-> - Find( m_pDocument->GetPageStyle( nCurTab ), - SfxStyleFamily::Page ); - - OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" ); - - if ( pStyleSheet ) - pStyleSet = &pStyleSheet->GetItemSet(); - else - rbHeader = rbFooter = false; - } - - OSL_ENSURE( pStyleSet, "PageStyle-Set not found! :-(" ); - if (!pStyleSet) - return; - - const SvxSetItem* pSetItem = nullptr; - const SfxItemSet* pSet = nullptr; - - pSetItem = &pStyleSet->Get( ATTR_PAGE_HEADERSET ); - pSet = &pSetItem->GetItemSet(); - rbHeader = pSet->Get(ATTR_PAGE_ON).GetValue(); - - pSetItem = &pStyleSet->Get( ATTR_PAGE_FOOTERSET ); - pSet = &pSetItem->GetItemSet(); - rbFooter = pSet->Get(ATTR_PAGE_ON).GetValue(); -} - #if defined(_WIN32) bool ScDocShell::DdeGetData( const OUString& rItem, const OUString& rMimeType, @@ -2988,17 +2876,14 @@ bool ScDocShell::DdeSetData( const OUString& rItem, // named range? OUString aPos = rItem; - ScRangeName* pRange = m_pDocument->GetRangeName(); - if( pRange ) + ScRangeName& rRange = m_pDocument->GetRangeName(); + const ScRangeData* pData = rRange.findByUpperName(ScGlobal::getCharClass().uppercase(aPos)); + if (pData) { - const ScRangeData* pData = pRange->findByUpperName(ScGlobal::getCharClass().uppercase(aPos)); - if (pData) - { - if( pData->HasType( ScRangeData::Type::RefArea ) - || pData->HasType( ScRangeData::Type::AbsArea ) - || pData->HasType( ScRangeData::Type::AbsPos ) ) - aPos = pData->GetSymbol(); // continue with the name's contents - } + if( pData->HasType( ScRangeData::Type::RefArea ) + || pData->HasType( ScRangeData::Type::AbsArea ) + || pData->HasType( ScRangeData::Type::AbsPos ) ) + aPos = pData->GetSymbol(); // continue with the name's contents } // Address in DDE function must be always parsed as CONV_OOO so that it @@ -3040,7 +2925,14 @@ void ScDocShell::LOKCommentNotify(LOKCommentNotificationType nType, const ScDocu { aAnnotation.put("author", pNote->GetAuthor()); aAnnotation.put("dateTime", pNote->GetDate()); - aAnnotation.put("text", pNote->GetText()); + if (const auto* pData = pNote->GetThreadedCommentData()) + { + aAnnotation.put("text", pData->maRoot.maText); + aAnnotation.put("threaded", "true"); + aAnnotation.put("resolved", pNote->IsResolved() ? "true" : "false"); + } + else + aAnnotation.put("text", pNote->GetText()); // Calculating the cell cursor position ScViewData* pViewData = GetViewData(); diff --git a/sc/source/ui/docshell/docsh5.cxx b/sc/source/ui/docshell/docsh5.cxx index 023d2d4e271e..5d912c423a33 100644 --- a/sc/source/ui/docshell/docsh5.cxx +++ b/sc/source/ui/docshell/docsh5.cxx @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,6 +42,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -492,6 +495,141 @@ void ScDocShell::RefreshPivotTables( const ScRange& rSource ) } } +// Re-check outputs that were previously blocked by #SPILL! (array formula +// cells and pivot tables). Called after cell-change operations that might +// have freed blocking cells. +void ScDocShell::ResolveSpilledOutputs() +{ + bool bAnyResolved = false; + + // Array formula cells currently in #SPILL! state: re-interpretation will + // clear the error if the blocker is gone and then expand to result dimensions. + const std::unordered_set aSpilledCells = m_pDocument->GetSpilledFormulaCells(); + for (const ScAddress& rPosition : aSpilledCells) + { + ScFormulaCell* pFormulaCell = m_pDocument->GetFormulaCell(rPosition); + if (pFormulaCell && pFormulaCell->GetErrCode() == FormulaError::Spill) + { + pFormulaCell->SetDirty(); + pFormulaCell->Interpret(); + if (pFormulaCell->GetErrCode() != FormulaError::Spill) + { + bAnyResolved = true; + // Expand the matrix to the result dimensions. + const ScMatrix* pMatrix = pFormulaCell->GetMatrix(); + if (pMatrix) + { + SCSIZE nResCols = 0; + SCSIZE nResRows = 0; + pMatrix->GetDimensions(nResCols, nResRows); + m_pDocument->ResizeMatrixFormula(rPosition, + SCCOL(nResCols), + SCROW(nResRows)); + } + } + } + } + + // Inverse direction: previously expanded dynamic array masters whose + // declared range now contains a foreign cell. The matrix master doesn't + // listen to its declared range, so we explicitly check. When a blocker + // is found, collapse the matrix back to 1x1 (preserving the blocker) and + // re-interpret. + const std::unordered_set aExpandedMatrices = m_pDocument->GetExpandedDynamicArrays(); + for (const ScAddress& rPosition : aExpandedMatrices) + { + ScFormulaCell* pFormulaCell = m_pDocument->GetFormulaCell(rPosition); + if (!pFormulaCell || pFormulaCell->GetMatrixFlag() != ScMatrixMode::Formula) + { + m_pDocument->UnmarkExpandedDynamicArray(rPosition); + continue; + } + SCCOL nDeclCols = 0; + SCROW nDeclRows = 0; + pFormulaCell->GetMatColsRows(nDeclCols, nDeclRows); + if (nDeclCols <= 1 && nDeclRows <= 1) + { + m_pDocument->UnmarkExpandedDynamicArray(rPosition); + continue; + } + ScRange aRange(rPosition.Col(), rPosition.Row(), rPosition.Tab(), + rPosition.Col() + nDeclCols - 1, rPosition.Row() + nDeclRows - 1, + rPosition.Tab()); + if (!m_pDocument->HasMatrixBlocker(aRange)) + continue; + + // Collapse: drop our own reference cells from the declared range. + // Then SetMatColsRows on the master and re-interpret - the runtime + // spill check now sees res > declared and sets #SPILL!. + for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol) + { + for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow) + { + if (nCol == rPosition.Col() && nRow == rPosition.Row()) + continue; + ScRefCellValue aCell(*m_pDocument, ScAddress(nCol, nRow, rPosition.Tab())); + if (aCell.getType() == CELLTYPE_FORMULA + && aCell.getFormula()->GetMatrixFlag() == ScMatrixMode::Reference) + { + m_pDocument->DeleteAreaTab(nCol, nRow, nCol, nRow, rPosition.Tab(), + InsertDeleteFlags::ALL); + } + } + } + pFormulaCell->SetMatColsRows(1, 1); + m_pDocument->UnmarkExpandedDynamicArray(rPosition); + // Conventional matrix formulas don't normally opt into the runtime + // spill check. Pre-marking the cell flips that bit so the next + // interpret recognises this as a spill-blocked master. + m_pDocument->MarkFormulaSpilled(rPosition); + pFormulaCell->SetDirty(); + pFormulaCell->Interpret(); + bAnyResolved = true; + } + + // Re-check spilled pivot tables. + ScDPCollection* pCollection = m_pDocument->GetDPCollection(); + if (pCollection) + { + bool bUndoEnabled = m_pDocument->IsUndoEnabled(); + bool bEnteredList = false; + size_t nCount = pCollection->GetCount(); + for (size_t i = 0; i < nCount; ++i) + { + ScDPObject& rDPObject = (*pCollection)[i]; + if (!rDPObject.HasSpillError()) + continue; + + // Try to re-output with spill check. If the blocking cells have been + // cleared, Output() will succeed and the pivot table will be rendered. + ScAddress aPosition = rDPObject.GetOutRange().aStart; + rDPObject.InvalidateData(); + if (rDPObject.Output(aPosition, true)) + { + bAnyResolved = true; + + if (bUndoEnabled) + { + if (!bEnteredList) + { + GetUndoManager()->EnterListAction(u""_ustr, u""_ustr, 0, ViewShellId(-1)); + bEnteredList = true; + } + GetUndoManager()->AddUndoAction( + std::make_unique( + *this, rDPObject.GetName(), rDPObject.GetOutRange())); + } + } + } + + if (bEnteredList) + GetUndoManager()->LeaveAndMergeListAction(); + } + + if (bAnyResolved) + PostPaintGridAll(); +} + static OUString lcl_GetAreaName( ScDocument* pDoc, const ScArea* pArea ) { ScDBData* pData = pDoc->GetDBAtArea( pArea->nTab, pArea->nColStart, pArea->nRowStart, diff --git a/sc/source/ui/docshell/docsh6.cxx b/sc/source/ui/docshell/docsh6.cxx index 75fefbd2c0ce..7ff1b05cf06e 100644 --- a/sc/source/ui/docshell/docsh6.cxx +++ b/sc/source/ui/docshell/docsh6.cxx @@ -38,7 +38,6 @@ #include #include -#include #include #include @@ -506,7 +505,7 @@ void ScDocShell::CheckConfigOptions() { std::shared_ptr xInfoBox(Application::CreateMessageDialog(pViewShell->GetFrameWeld(), VclMessageType::Info, VclButtonsType::Ok, - ScResId(STR_OPTIONS_WARN_SEPARATORS), pViewShell)); + ScResId(STR_OPTIONS_WARN_SEPARATORS))); xInfoBox->runAsync(xInfoBox, [] (int) {}); } diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx b/sc/source/ui/docshell/documentlinkmgr.cxx index 453066c3a84f..a0f928df66f9 100644 --- a/sc/source/ui/docshell/documentlinkmgr.cxx +++ b/sc/source/ui/docshell/documentlinkmgr.cxx @@ -32,7 +32,6 @@ #include #include #include -#include #include @@ -126,16 +125,6 @@ bool DocumentLinkManager::idleCheckLinks() } bool DocumentLinkManager::hasDdeLinks() const -{ - return hasDdeOrOleOrWebServiceLinks(true, false, false); -} - -bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks() const -{ - return hasDdeOrOleOrWebServiceLinks(true, true, true); -} - -bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, bool bWebService) const { sfx2::LinkManager* pMgr = mpImpl->mpLinkManager; if (!pMgr) @@ -143,19 +132,20 @@ bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, boo const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks(); for (const auto & rLink : rLinks) - { - sfx2::SvBaseLink* pBase = rLink.get(); - if (bDde && dynamic_cast(pBase)) + if (dynamic_cast(rLink.get())) return true; - if (bOle && (dynamic_cast(pBase) || dynamic_cast(pBase))) - return true; - if (bWebService && dynamic_cast(pBase)) - return true; - } return false; } +bool DocumentLinkManager::hasUpdatableLinks() const +{ + // Every link in the document's LinkManager can be updated from an external + // source, so a non-empty link list means the document has updatable links. + sfx2::LinkManager* pMgr = mpImpl->mpLinkManager; + return pMgr && !pMgr->GetLinks().empty(); +} + bool DocumentLinkManager::hasExternalRefLinks() const { sfx2::LinkManager* pMgr = mpImpl->mpLinkManager; diff --git a/sc/source/ui/docshell/editable.cxx b/sc/source/ui/docshell/editable.cxx index c10d0e0d4e21..cf76019420d3 100644 --- a/sc/source/ui/docshell/editable.cxx +++ b/sc/source/ui/docshell/editable.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include ScEditableTester::ScEditableTester() = default; @@ -180,4 +181,18 @@ TranslateId ScEditableTester::GetMessageId() const return STR_PROTECTIONERR; } +bool ScEditableTester::IsEditableOrMatrixCell(const ScDocument& rDoc, + const ScAddress& rPos) const +{ + if (mbIsEditable) + return true; + if (!mbOnlyMatrix) + return false; + const ScFormulaCell* pCell = rDoc.GetFormulaCell(rPos); + if (!pCell) + return false; + const ScMatrixMode eFlag = pCell->GetMatrixFlag(); + return eFlag == ScMatrixMode::Reference || eFlag == ScMatrixMode::Formula; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index 7ae2d9c43b2a..be7581902af7 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -178,7 +177,7 @@ public: if (pCell->IsValue()) { - // Turn this into value cell. + // Turn this into a value cell. mpDoc->SetValue(aPos, pCell->GetValue()); } else @@ -210,7 +209,7 @@ bool hasRefsToSrcDoc(ScRangeData& rData, sal_uInt16 nFileId) if (!p->IsExternalRef()) continue; - if (p->GetIndex() == nFileId) + if (static_cast(p)->GetFileId() == nFileId) return true; } return false; @@ -695,10 +694,10 @@ ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData( switch (pToken->GetType()) { case svDouble: - xMat->PutDouble(pToken->GetDouble(), nC, nR); + xMat->PutDouble(static_cast(pToken.get())->GetDouble(), nC, nR); break; case svString: - xMat->PutString(pToken->GetString(), nC, nR); + xMat->PutString(static_cast(pToken.get())->GetString(), nC, nR); break; default: ; @@ -1790,24 +1789,24 @@ void ScExternalRefManager::storeRangeNameTokens(sal_uInt16 nFileId, const OUStri { case svSingleRef: { - const ScSingleRefData& rRef = *pToken->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef(); OUString aTabName; if (SCTAB nCacheId = rRef.Tab(); nCacheId >= 0) aTabName = maRefCache.getTableName(nFileId, nCacheId); ScExternalSingleRefToken aNewToken(nFileId, svl::SharedString(aTabName), // string not interned - *pToken->GetSingleRef()); + static_cast(pToken)->GetSingleRef()); pNewArray->AddToken(aNewToken); bTokenAdded = true; } break; case svDoubleRef: { - const ScSingleRefData& rRef = *pToken->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef(); OUString aTabName; if (SCTAB nCacheId = rRef.Tab(); nCacheId >= 0) aTabName = maRefCache.getTableName(nFileId, nCacheId); ScExternalDoubleRefToken aNewToken(nFileId, svl::SharedString(aTabName), // string not interned - *pToken->GetDoubleRef()); + static_cast(pToken)->GetDoubleRef()); pNewArray->AddToken(aNewToken); bTokenAdded = true; } @@ -2134,9 +2133,9 @@ namespace { bool hasRangeName(const ScDocument& rDoc, const OUString& rName) { - ScRangeName* pExtNames = rDoc.GetRangeName(); + ScRangeName& rExtNames = rDoc.GetRangeName(); OUString aUpperName = ScGlobal::getCharClass().uppercase(rName); - const ScRangeData* pRangeData = pExtNames->findByUpperName(aUpperName); + const ScRangeData* pRangeData = rExtNames.findByUpperName(aUpperName); return pRangeData != nullptr; } @@ -2355,9 +2354,9 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokensFromSr ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokensFromSrcDoc( sal_uInt16 nFileId, const ScDocument& rSrcDoc, OUString& rName) { - ScRangeName* pExtNames = rSrcDoc.GetRangeName(); + ScRangeName& rExtNames = rSrcDoc.GetRangeName(); OUString aUpperName = ScGlobal::getCharClass().uppercase(rName); - const ScRangeData* pRangeData = pExtNames->findByUpperName(aUpperName); + const ScRangeData* pRangeData = rExtNames.findByUpperName(aUpperName); if (!pRangeData) return ScExternalRefCache::TokenArrayRef(); @@ -2377,22 +2376,22 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokensFromSr { case svSingleRef: { - const ScSingleRefData& rRef = *pToken->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef(); OUString aTabName; rSrcDoc.GetName(rRef.Tab(), aTabName); ScExternalSingleRefToken aNewToken(nFileId, svl::SharedString( aTabName), // string not interned - *pToken->GetSingleRef()); + static_cast(pToken)->GetSingleRef()); pNew->AddToken(aNewToken); bTokenAdded = true; } break; case svDoubleRef: { - const ScSingleRefData& rRef = *pToken->GetSingleRef(); + const ScSingleRefData& rRef = static_cast(pToken)->GetSingleRef(); OUString aTabName; rSrcDoc.GetName(rRef.Tab(), aTabName); ScExternalDoubleRefToken aNewToken(nFileId, svl::SharedString( aTabName), // string not interned - *pToken->GetDoubleRef()); + static_cast(pToken)->GetDoubleRef()); pNew->AddToken(aNewToken); bTokenAdded = true; } @@ -2544,7 +2543,8 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, OUSt ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false); std::shared_ptr pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter); - if (pFileData->maRelativeName.isEmpty()) + if (pFileData->maRelativeName.isEmpty() && !pFileData->mbPathMissing + && !pFileData->mbXlStartup) { // Generate a relative file path. INetURLObject aBaseURL(getOwnDocumentName()); @@ -2724,7 +2724,7 @@ void ScExternalRefManager::addFilesToLinkManager() void ScExternalRefManager::SrcFileData::maybeCreateRealFileName(std::u16string_view rOwnDocName) { - if (maRelativeName.isEmpty()) + if (mbPathMissing || mbXlStartup || maRelativeName.isEmpty()) // No relative path given. Nothing to do. return; @@ -2826,6 +2826,18 @@ sal_uInt16 ScExternalRefManager::convertFileIdToUsedFileId(sal_uInt16 nFileId) return maConvertFileIdToUsedFileId[nFileId]; } +void ScExternalRefManager::addDrawingMacros(sal_uInt16 nFileId, const OUString& rName) +{ + if (rName.isEmpty()) + return; + maDrawingMacros[nFileId].insert(rName); +} + +const std::map>& ScExternalRefManager::getDrawingMacros() const +{ + return maDrawingMacros; +} + void ScExternalRefManager::setSkipUnusedFileIds(std::vector& rExternFileIds) { mbSkipUnusedFileIds = true; @@ -3055,14 +3067,13 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId) // Remove all named ranges that reference this document. // Global named ranges. - ScRangeName* pRanges = mrDoc.GetRangeName(); - if (pRanges) - removeRangeNamesBySrcDoc(*pRanges, nFileId); + ScRangeName& rRanges = mrDoc.GetRangeName(); + removeRangeNamesBySrcDoc(rRanges, nFileId); // Sheet-local named ranges. for (SCTAB i = 0, n = mrDoc.GetTableCount(); i < n; ++i) { - pRanges = mrDoc.GetRangeName(i); + ScRangeName* pRanges = mrDoc.GetRangeName(i); if (pRanges) removeRangeNamesBySrcDoc(*pRanges, nFileId); } @@ -3109,6 +3120,34 @@ void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const OUString& rFi maSrcFiles[nFileId].maFilterOptions = rOptions; } +bool ScExternalRefManager::isPathMissing(sal_uInt16 nFileId) +{ + if (nFileId >= maSrcFiles.size()) + return true; + return maSrcFiles[nFileId].mbPathMissing; +} + +void ScExternalRefManager::setPathMissing(sal_uInt16 nFileId) +{ + if (nFileId >= maSrcFiles.size()) + return; + maSrcFiles[nFileId].mbPathMissing = true; +} + +bool ScExternalRefManager::isXlStartup(sal_uInt16 nFileId) +{ + if (nFileId >= maSrcFiles.size()) + return true; + return maSrcFiles[nFileId].mbXlStartup; +} + +void ScExternalRefManager::setXlStartup(sal_uInt16 nFileId) +{ + if (nFileId >= maSrcFiles.size()) + return; + maSrcFiles[nFileId].mbXlStartup = true; +} + void ScExternalRefManager::clear() { for (auto& rEntry : maLinkListeners) @@ -3135,6 +3174,9 @@ void ScExternalRefManager::resetSrcFileData(const OUString& rBaseFileUrl) { for (auto& rSrcFile : maSrcFiles) { + if (rSrcFile.mbPathMissing || rSrcFile.mbXlStartup) + continue; + // Re-generate relative file name from the absolute file name. OUString aAbsName = rSrcFile.maRealFileName; if (aAbsName.isEmpty()) diff --git a/sc/source/ui/docshell/impex.cxx b/sc/source/ui/docshell/impex.cxx index 6a42e856d4a9..f736420209ce 100644 --- a/sc/source/ui/docshell/impex.cxx +++ b/sc/source/ui/docshell/impex.cxx @@ -59,16 +59,18 @@ #include #include #include +#include #include #include #include -#include #include #include #include #include #include +#include + #include #include @@ -109,13 +111,14 @@ ScImportExport::ScImportExport( ScDocument& r ) bFormulas( false ), bIncludeFiltered( true ), bAll( true ), bSingle( true ), bUndo( false ), bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ), - mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ), mbIncludeBOM(false) + mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ), mbIncludeBOM(false), + mnEndianness(SvStreamEndian::LITTLE) { pUndoDoc = nullptr; pExtOptions = nullptr; } -// Insert am current cell without range(es) +// Insert at current cell without range(es) ScImportExport::ScImportExport( ScDocument& r, const ScAddress& rPt ) : pDocSh( r.GetDocumentShell() ), rDoc( r ), aRange( rPt ), @@ -124,7 +127,8 @@ ScImportExport::ScImportExport( ScDocument& r, const ScAddress& rPt ) bFormulas( false ), bIncludeFiltered( true ), bAll( false ), bSingle( true ), bUndo( pDocSh != nullptr ), bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ), - mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ), mbIncludeBOM(false) + mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ), mbIncludeBOM(false), + mnEndianness(SvStreamEndian::LITTLE) { pUndoDoc = nullptr; pExtOptions = nullptr; @@ -140,7 +144,8 @@ ScImportExport::ScImportExport( ScDocument& r, const ScRange& rRange ) bFormulas( false ), bIncludeFiltered( true ), bAll( false ), bSingle( false ), bUndo( pDocSh != nullptr ), bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ), - mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ), mbIncludeBOM(false) + mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ), mbIncludeBOM(false), + mnEndianness(SvStreamEndian::LITTLE) { pUndoDoc = nullptr; pExtOptions = nullptr; @@ -157,7 +162,8 @@ ScImportExport::ScImportExport( ScDocument& r, const OUString& rPos ) bFormulas( false ), bIncludeFiltered( true ), bAll( false ), bSingle( true ), bUndo( pDocSh != nullptr ), bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ), - mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ), mbIncludeBOM(false) + mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ), mbIncludeBOM(false), + mnEndianness(SvStreamEndian::LITTLE) { pUndoDoc = nullptr; pExtOptions = nullptr; @@ -165,21 +171,20 @@ ScImportExport::ScImportExport( ScDocument& r, const OUString& rPos ) SCTAB nTab = ScDocShell::GetCurTab(); aRange.aStart.SetTab( nTab ); OUString aPos( rPos ); + // Named range? - ScRangeName* pRange = rDoc.GetRangeName(); - if (pRange) + ScRangeName& rRange = rDoc.GetRangeName(); + const ScRangeData* pData = rRange.findByUpperName(ScGlobal::getCharClass().uppercase(aPos)); + if (pData) { - const ScRangeData* pData = pRange->findByUpperName(ScGlobal::getCharClass().uppercase(aPos)); - if (pData) + if( pData->HasType( ScRangeData::Type::RefArea ) + || pData->HasType( ScRangeData::Type::AbsArea ) + || pData->HasType( ScRangeData::Type::AbsPos ) ) { - if( pData->HasType( ScRangeData::Type::RefArea ) - || pData->HasType( ScRangeData::Type::AbsArea ) - || pData->HasType( ScRangeData::Type::AbsPos ) ) - { - aPos = pData->GetSymbol(); - } + aPos = pData->GetSymbol(); } } + formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention(); // Range? if (aRange.Parse(aPos, rDoc, eConv) & ScRefFlags::VALID) @@ -223,7 +228,8 @@ bool ScImportExport::IsFormatSupported( SotClipboardFormatId nFormat ) || nFormat == SotClipboardFormatId::LINK || nFormat == SotClipboardFormatId::HTML || nFormat == SotClipboardFormatId::HTML_SIMPLE - || nFormat == SotClipboardFormatId::DIF; + || nFormat == SotClipboardFormatId::DIF + || nFormat == SotClipboardFormatId::MARKDOWN; } // Prepare for Undo @@ -421,6 +427,34 @@ bool ScImportExport::ImportStream( SvStream& rStrm, const OUString& rBaseURL, So if ( pHTML && HTML2Doc( *pHTML, rBaseURL ) ) return true; } + if( nFmt == SotClipboardFormatId::MARKDOWN ) { + sal_uInt64 nSize = rStrm.remainingSize(); + if (nSize == 0) + return false; + + std::vector aBuf(nSize); + rStrm.ReadBytes(aBuf.data(), nSize); + OString aMdContent(aBuf.data(), nSize); + + auto outputCallback = [](const MD_CHAR* pText, MD_SIZE nLen, void* pUserData) { + static_cast(pUserData)->append(std::string_view(pText, nLen)); + }; + + OStringBuffer aHtml(""); + int nRet = md_html(aMdContent.getStr(), aMdContent.getLength(), + outputCallback, &aHtml, + MD_DIALECT_GITHUB, 0); + if (nRet != 0) + return false; + aHtml.append(""); + + OString aHtmlStr = aHtml.makeStringAndClear(); + SvMemoryStream aHtmlStream( + const_cast(aHtmlStr.getStr()), aHtmlStr.getLength(), + StreamMode::READ); + if (HTML2Doc(aHtmlStream, rBaseURL)) + return true; + } return false; } @@ -1035,7 +1069,7 @@ static bool lcl_PutString( { ScFieldEditEngine& rEngine = rDoc.GetEditEngine(); rEngine.SetTextCurrentDefaults(rStr); - rDocImport.setEditCell(ScAddress(nCol, nRow, nTab), rEngine.CreateTextObject()); + rDocImport.setEditCell(ScAddress(nCol, nRow, nTab), std::make_unique(rEngine.CreateTextObject())); return true; } else @@ -1446,7 +1480,7 @@ static bool lcl_PutString( ScFieldEditEngine& rEngine = rDoc.GetEditEngine(); rEngine.SetTextCurrentDefaults(rStr); if ( bUseDocImport ) - rDocImport.setEditCell(ScAddress(nCol, nRow, nTab), rEngine.CreateTextObject()); + rDocImport.setEditCell(ScAddress(nCol, nRow, nTab), std::make_unique(rEngine.CreateTextObject())); else rDoc.SetEditText( ScAddress( nCol, nRow, nTab ), rEngine.CreateTextObject() ); } @@ -1918,7 +1952,9 @@ bool ScImportExport::Doc2Text( SvStream& rStrm ) SCROW nEndRow = aRange.aEnd.Row(); SCTAB nEndTab = aRange.aEnd.Tab(); - if (!rDoc.GetClipParam().isMultiRange() && nStartTab == nEndTab) + // tdf#109299 - shrink to data area on entire document export or expert configuration + if ((bAll || officecfg::Office::Calc::ClipboardCellsExport::ShrinkToDataArea::get()) + && !rDoc.GetClipParam().isMultiRange() && nStartTab == nEndTab) if (!rDoc.ShrinkToDataArea( nStartTab, nStartCol, nStartRow, nEndCol, nEndRow )) return false; diff --git a/sc/source/ui/docshell/olinefun.cxx b/sc/source/ui/docshell/olinefun.cxx index 650e8007e7d0..d85883ad4201 100644 --- a/sc/source/ui/docshell/olinefun.cxx +++ b/sc/source/ui/docshell/olinefun.cxx @@ -328,7 +328,7 @@ bool ScOutlineDocFunc::SelectLevel( SCTAB nTab, bool bColumns, sal_uInt16 nLevel rArray.GetRange( nStart, nEnd ); // TODO undo can mess things up when another view is editing a cell in the range of group entry - // this is a temporarily workaround + // this is a temporary workaround if (!comphelper::LibreOfficeKit::isActive() && bRecord ) { std::unique_ptr pUndoTab(new ScOutlineTable( *pTable )); @@ -449,7 +449,7 @@ bool ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, bool bRecord ) SCCOLROW i; // TODO undo can mess things up when another view is editing a cell in the range of group entry - // this is a temporarily workaround + // this is a temporary workaround if ( !comphelper::LibreOfficeKit::isActive() && bRecord ) { std::unique_ptr pUndoTab(new ScOutlineTable( *pTable )); @@ -575,7 +575,7 @@ bool ScOutlineDocFunc::HideMarkedOutlines( const ScRange& rRange, bool bRecord ) rRowArray.ExtendBlock( nRowLevel, nEffStartRow, nEffEndRow ); // TODO undo can mess things up when another view is editing a cell in the range of group entry - // this is a temporarily workaround + // this is a temporary workaround if ( !comphelper::LibreOfficeKit::isActive() && bRecord ) { std::unique_ptr pUndoTab(new ScOutlineTable( *pTable )); @@ -649,7 +649,7 @@ void ScOutlineDocFunc::ShowOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel SCCOLROW nEnd = pEntry->GetEnd(); // TODO undo can mess things up when another view is editing a cell in the range of group entry - // this is a temporarily workaround + // this is a temporary workaround if ( !comphelper::LibreOfficeKit::isActive() && bRecord ) { ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); @@ -743,7 +743,7 @@ bool ScOutlineDocFunc::HideOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel return false; // TODO undo can mess things up when another view is editing a cell in the range of group entry - // this is a temporarily workaround + // this is a temporary workaround if ( !comphelper::LibreOfficeKit::isActive() && bRecord ) { ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); diff --git a/sc/source/ui/docshell/pagedata.cxx b/sc/source/ui/docshell/pagedata.cxx index 4ab70ed9fea7..f109b9d9ddc0 100644 --- a/sc/source/ui/docshell/pagedata.cxx +++ b/sc/source/ui/docshell/pagedata.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include #include #include @@ -36,13 +37,13 @@ ScPrintRangeData::~ScPrintRangeData() void ScPrintRangeData::SetPagesX( size_t nCount, const SCCOL* pData ) { mvPageEndX.resize( nCount ); - memcpy( mvPageEndX.data(), pData, nCount * sizeof(SCCOL) ); + std::copy_n( pData, nCount, mvPageEndX.data() ); } void ScPrintRangeData::SetPagesY( size_t nCount, const SCROW* pData ) { mvPageEndY.resize(nCount); - memcpy( mvPageEndY.data(), pData, nCount * sizeof(SCROW) ); + std::copy_n( pData, nCount, mvPageEndY.data() ); } ScPageBreakData::ScPageBreakData(size_t nMax) diff --git a/sc/source/ui/docshell/servobj.cxx b/sc/source/ui/docshell/servobj.cxx index 78b83a00179a..30ca7c0ddff0 100644 --- a/sc/source/ui/docshell/servobj.cxx +++ b/sc/source/ui/docshell/servobj.cxx @@ -37,15 +37,12 @@ static bool lcl_FillRangeFromName( ScRange& rRange, ScDocShell* pDocSh, const OU if (pDocSh) { ScDocument& rDoc = pDocSh->GetDocument(); - ScRangeName* pNames = rDoc.GetRangeName(); - if (pNames) + ScRangeName& rNames = rDoc.GetRangeName(); + const ScRangeData* pData = rNames.findByUpperName(ScGlobal::getCharClass().uppercase(rName)); + if (pData) { - const ScRangeData* pData = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(rName)); - if (pData) - { - if ( pData->IsValidReference( rRange ) ) - return true; - } + if ( pData->IsValidReference( rRange ) ) + return true; } } return false; @@ -213,7 +210,7 @@ void ScServerObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) // don't access DocShell anymore for EndListening etc. } } - else if (dynamic_cast( &rBC) != nullptr) + else if (dynamic_cast(&rBC) != nullptr) { if ( !aItemStr.isEmpty() && rHint.GetId() == SfxHintId::ScAreasChanged ) { diff --git a/sc/source/ui/docshell/tablink.cxx b/sc/source/ui/docshell/tablink.cxx index 9d11e6b3576d..974df919da7a 100644 --- a/sc/source/ui/docshell/tablink.cxx +++ b/sc/source/ui/docshell/tablink.cxx @@ -31,11 +31,12 @@ #include #include #include -#include +#include #include #include #include #include +#include #include #include @@ -140,6 +141,9 @@ bool ScTableLink::Refresh(const OUString& rNewFile, const OUString& rNewFilter, if (rNewFile.isEmpty() || rNewFilter.isEmpty()) return false; + if (!m_rDocSh.GetEmbeddedObjectContainer().getUserAllowsLinkUpdate()) + return false; + OUString aNewUrl = ScGlobal::GetAbsDocName(rNewFile, &m_rDocSh); bool bNewUrlName = aFileName != aNewUrl; diff --git a/sc/source/ui/drawfunc/drawsh.cxx b/sc/source/ui/drawfunc/drawsh.cxx index b5e2163ae59a..ca6e45470276 100644 --- a/sc/source/ui/drawfunc/drawsh.cxx +++ b/sc/source/ui/drawfunc/drawsh.cxx @@ -62,6 +62,7 @@ #include #include #include +#include using namespace css; diff --git a/sc/source/ui/drawfunc/drawsh5.cxx b/sc/source/ui/drawfunc/drawsh5.cxx index 548eb396ef50..7672ffb7254d 100644 --- a/sc/source/ui/drawfunc/drawsh5.cxx +++ b/sc/source/ui/drawfunc/drawsh5.cxx @@ -490,7 +490,7 @@ void ScDrawShell::ExecDrawFunc( SfxRequest& rReq ) const SfxBoolItem* pItem = rReq.GetArg(SID_ENABLE_HYPHENATION); if( pItem ) { - SfxItemSetFixed aSet( GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet( GetPool() )); bool bValue = pItem->GetValue(); aSet.Put( SfxBoolItem( EE_PARA_HYPHENATE, bValue ) ); pView->SetAttributes( aSet ); diff --git a/sc/source/ui/drawfunc/drtxtob.cxx b/sc/source/ui/drawfunc/drtxtob.cxx index eaf9ef2adb5b..41e73d62575d 100644 --- a/sc/source/ui/drawfunc/drtxtob.cxx +++ b/sc/source/ui/drawfunc/drtxtob.cxx @@ -66,6 +66,7 @@ #include #include #include +#include #include #include @@ -822,10 +823,9 @@ void ScDrawTextObjectBar::ExecuteAttr( SfxRequest &rReq ) if ( pOutView ) pOutView->DrawText_ToEditView( tools::Rectangle() ); - SfxItemSetFixed aEmptyAttr( *aEditAttr.GetPool() ); - SfxItemSetFixed aSizeAttr(*aEditAttr.GetPool()); - + SfxItemSet aEmptyAttr(SfxItemSet::makeFixedSfxItemSet( *aEditAttr.GetPool() )); + SfxItemSet aSizeAttr(SfxItemSet::makeFixedSfxItemSet( *aEditAttr.GetPool() )); aSizeAttr.Put(pView->GetAttrFromMarked(true)); pView->SetAttributes( aEmptyAttr, true ); @@ -987,7 +987,7 @@ void ScDrawTextObjectBar::ExecuteAttr( SfxRequest &rReq ) sal_uInt16 nId = SID_ATTR_PARA_LRSPACE; const SvxLRSpaceItem& rItem = static_cast( pArgs->Get( nId )); - SfxItemSetFixed aAttr( GetPool() ); + SfxItemSet aAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); nId = EE_PARA_LRSPACE; SvxLRSpaceItem aLRSpaceItem(rItem.GetLeft(), rItem.GetRight(), rItem.GetTextFirstLineOffset(), nId); @@ -998,7 +998,7 @@ void ScDrawTextObjectBar::ExecuteAttr( SfxRequest &rReq ) { SvxLineSpacingItem aLineSpaceItem = static_cast(pArgs->Get( GetPool().GetWhichIDFromSlotID(nSlot))); - SfxItemSetFixed aAttr( GetPool() ); + SfxItemSet aAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aAttr.Put( aLineSpaceItem ); pView->SetAttributes( aAttr ); } @@ -1006,7 +1006,7 @@ void ScDrawTextObjectBar::ExecuteAttr( SfxRequest &rReq ) { SvxULSpaceItem aULSpaceItem = static_cast(pArgs->Get( GetPool().GetWhichIDFromSlotID(nSlot))); - SfxItemSetFixed aAttr( GetPool() ); + SfxItemSet aAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aULSpaceItem.SetWhich(EE_PARA_ULSPACE); aAttr.Put( aULSpaceItem ); pView->SetAttributes( aAttr ); diff --git a/sc/source/ui/drawfunc/drtxtob2.cxx b/sc/source/ui/drawfunc/drtxtob2.cxx index 37629721cff4..3df3921a0cb7 100644 --- a/sc/source/ui/drawfunc/drtxtob2.cxx +++ b/sc/source/ui/drawfunc/drtxtob2.cxx @@ -82,7 +82,7 @@ void ScDrawTextObjectBar::ExecuteGlobal( SfxRequest &rReq ) case SID_TEXTDIRECTION_LEFT_TO_RIGHT: case SID_TEXTDIRECTION_TOP_TO_BOTTOM: { - SfxItemSetFixed aAttr(pView->GetModel().GetItemPool()); + SfxItemSet aAttr(SfxItemSet::makeFixedSfxItemSet(pView->GetModel().GetItemPool())); aAttr.Put( SvxWritingModeItem( nSlot == SID_TEXTDIRECTION_LEFT_TO_RIGHT ? css::text::WritingMode_LR_TB : css::text::WritingMode_TB_RL, @@ -98,7 +98,7 @@ void ScDrawTextObjectBar::ExecuteGlobal( SfxRequest &rReq ) const SfxBoolItem* pItem = rReq.GetArg(SID_ENABLE_HYPHENATION); if( pItem ) { - SfxItemSetFixed aSet( GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet( GetPool() )); bool bValue = pItem->GetValue(); aSet.Put( SfxBoolItem( EE_PARA_HYPHENATE, bValue ) ); pView->SetAttributes( aSet ); @@ -153,8 +153,8 @@ void ScDrawTextObjectBar::ExecuteExtra( SfxRequest &rReq ) case SID_ATTR_PARA_LEFT_TO_RIGHT: case SID_ATTR_PARA_RIGHT_TO_LEFT: { - SfxItemSetFixed aAttr(pView->GetModel().GetItemPool()); + SfxItemSet aAttr(SfxItemSet::makeFixedSfxItemSet< EE_PARA_WRITINGDIR, EE_PARA_WRITINGDIR, + EE_PARA_JUST, EE_PARA_JUST>(pView->GetModel().GetItemPool())); bool bLeft = ( nSlot == SID_ATTR_PARA_LEFT_TO_RIGHT ); aAttr.Put( SvxFrameDirectionItem( bLeft ? SvxFrameDirection::Horizontal_LR_TB : SvxFrameDirection::Horizontal_RL_TB, diff --git a/sc/source/ui/drawfunc/fuconcustomshape.cxx b/sc/source/ui/drawfunc/fuconcustomshape.cxx index 19fb390f4710..c72accf9429d 100644 --- a/sc/source/ui/drawfunc/fuconcustomshape.cxx +++ b/sc/source/ui/drawfunc/fuconcustomshape.cxx @@ -152,7 +152,7 @@ void FuConstCustomShape::SetAttributes( SdrObject* pObj ) if( pSourceObj ) { const SfxItemSet& rSource = pSourceObj->GetMergedItemSet(); - SfxItemSetFixed< + SfxItemSet aDest(SfxItemSet::makeFixedSfxItemSet< // Ranges from SdrAttrObj: SDRATTR_START, SDRATTR_SHADOW_LAST, SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST, @@ -163,8 +163,8 @@ void FuConstCustomShape::SetAttributes( SdrObject* pObj ) SDRATTR_GRAF_FIRST, SDRATTR_CUSTOMSHAPE_LAST, // Range from SdrTextObj: - EE_ITEMS_START, EE_ITEMS_END> aDest( - pObj->getSdrModelFromSdrObject().GetItemPool()); + EE_ITEMS_START, EE_ITEMS_END> ( + pObj->getSdrModelFromSdrObject().GetItemPool())); aDest.Set( rSource ); pObj->SetMergedItemSet( aDest ); Degree100 nAngle = pSourceObj->GetRotateAngle(); diff --git a/sc/source/ui/drawfunc/fudraw.cxx b/sc/source/ui/drawfunc/fudraw.cxx index c9c57512b7e5..49fa6c8a4b60 100644 --- a/sc/source/ui/drawfunc/fudraw.cxx +++ b/sc/source/ui/drawfunc/fudraw.cxx @@ -271,15 +271,6 @@ bool FuDraw::KeyInput(const KeyEvent& rKEvt) if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() ) { SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); - bool isMobilePhone = comphelper::LibreOfficeKit::isActive() && rViewShell.isLOKMobilePhone(); - // Double tapping on charts on phone may result in activating the edit mode which is not wanted. - // It happens due to the delay of selection message of the object from kit to javascript - // in that case F2 is sent instead of double click - if (isMobilePhone && ScDocument::IsChart(pObj)) - { - rViewShell.ActivateObject(static_cast(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY); - break; - } if ( lcl_KeyEditMode( pObj, rViewShell, nullptr ) ) // start text edit for suitable object bReturn = true; } diff --git a/sc/source/ui/drawfunc/fuins1.cxx b/sc/source/ui/drawfunc/fuins1.cxx index 8c85d707fb63..ac5d8770959d 100644 --- a/sc/source/ui/drawfunc/fuins1.cxx +++ b/sc/source/ui/drawfunc/fuins1.cxx @@ -34,9 +34,10 @@ #include #include #include +#include #include #include -#include +#include #include #include #include @@ -111,7 +112,7 @@ void ScLimitSizeOnDrawPage( Size& rSize, Point& rPos, const Size& rPage ) static void lcl_InsertGraphic( const Graphic& rGraphic, const OUString& rFileName, bool bAsLink, bool bApi, ScTabViewShell& rViewSh, const vcl::Window* pWindow, SdrView* pView, - ScAnchorType aAnchorType = SCA_CELL ) + ScAnchorType aAnchorType = SCA_CELL, bool bMultiInsert = false ) { Graphic& rGraphic1 = const_cast(rGraphic); GraphicNativeMetadata aMetadata; @@ -132,7 +133,7 @@ static void lcl_InsertGraphic( const Graphic& rGraphic, if(pDrawView) { const SdrMarkList& rMarkList = pDrawView->GetMarkedObjectList(); - if (1 == rMarkList.GetMarkCount()) + if (1 == rMarkList.GetMarkCount() && !bMultiInsert) { SdrObject* pPickObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); @@ -260,6 +261,11 @@ static void lcl_InsertMedia( const OUString& rMediaURL, bool bApi, tools::Rectangle(aInsertPos, aSize)); pObj->setURL( realURL, u""_ustr/*TODO?*/ ); + + // The user picked this media file, so its external reference is allowed without asking again. + if (bLink) + pObj->setLinkAllowed(true); + pView->InsertObjectAtView( pObj.get(), *pPV, bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE ); } #endif @@ -306,6 +312,7 @@ FuInsertGraphic::FuInsertGraphic( ScTabViewShell& rViewSh, SvxOpenGraphicDialog aDlg(ScResId(STR_INSERTGRAPHIC), pWin ? pWin->GetFrameWeld() : nullptr, ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR); + aDlg.setMultiSelect(true); Reference xCtrlAcc = aDlg.GetFilePickerControlAccess(); sal_Int16 nSelect = 0; Sequence aListBoxEntries { @@ -335,16 +342,19 @@ FuInsertGraphic::FuInsertGraphic( ScTabViewShell& rViewSh, ErrCode nError = aDlg.GetGraphic(aGraphic); if( nError == ERRCODE_NONE ) { - OUString aFileName = aDlg.GetPath(); + Sequence < OUString > aFileNames = aDlg.GetSelectedFiles(); const OUString& aFilterName = aDlg.GetDetectedFilter(); bool bAsLink = aDlg.IsAsLink(); // really store as link only? if( bAsLink && officecfg::Office::Common::Misc::ShowLinkWarningDialog::get() ) { - SvxLinkWarningDialog aWarnDlg(pWin ? pWin->GetFrameWeld() : nullptr, aFileName); - if (aWarnDlg.run() != RET_OK) - bAsLink = false; // don't store as link + for (const auto& aFileName : aFileNames) + { + SvxLinkWarningDialog aWarnDlg(pWin ? pWin->GetFrameWeld() : nullptr, aFileName); + if (aWarnDlg.run() != RET_OK) + bAsLink = false; // don't store as link + } } // Anchor to cell or to page? @@ -364,18 +374,30 @@ FuInsertGraphic::FuInsertGraphic( ScTabViewShell& rViewSh, else aAnchorType = SCA_DONTKNOW; - lcl_InsertGraphic( aGraphic, aFileName, bAsLink, false, rViewSh, pWindow, pView, aAnchorType ); - // append items for recording - rReq.AppendItem( SfxStringItem( SID_INSERT_GRAPHIC, aFileName ) ); + SfxStringListItem aItem(SID_INSERT_GRAPHIC); + aItem.SetStringList(aFileNames); + rReq.AppendItem(aItem); rReq.AppendItem( SfxStringItem( FN_PARAM_FILTER, aFilterName ) ); rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) ); + for (const auto& aFileName : aFileNames) + { + nError = GraphicFilter::LoadGraphic(aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter()); + // format not equal to current filter (with autodetection) + if (nError == ERRCODE_GRFILTER_FORMATERROR) + nError = GraphicFilter::LoadGraphic(aFileName, OUString(), aGraphic, &GraphicFilter::GetGraphicFilter()); + if (nError == ERRCODE_NONE) + lcl_InsertGraphic( aGraphic, aFileName, bAsLink, false, rViewSh, pWindow, pView, aAnchorType, aFileNames.getLength() > 1); + else + SAL_WARN("sc", "Failed to load graphic: " << aFileName); + } rReq.Done(); } else { // error is handled in SvxOpenGraphicDialog::GetGraphic } + aDlg.setMultiSelect(false); } } } diff --git a/sc/source/ui/drawfunc/fuins2.cxx b/sc/source/ui/drawfunc/fuins2.cxx index d8921bdc4d90..f5aebe659a49 100644 --- a/sc/source/ui/drawfunc/fuins2.cxx +++ b/sc/source/ui/drawfunc/fuins2.cxx @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include @@ -627,7 +627,7 @@ FuInsertChart::FuInsertChart(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawV if( xChartModel.is() ) xChartModel->unlockControllers(); } - else if (!rViewSh.isLOKMobilePhone()) + else { //the controller will be unlocked by the dialog when the dialog is told to do so diff --git a/sc/source/ui/drawfunc/futext.cxx b/sc/source/ui/drawfunc/futext.cxx index 1792346a4403..1f18d7dc0661 100644 --- a/sc/source/ui/drawfunc/futext.cxx +++ b/sc/source/ui/drawfunc/futext.cxx @@ -401,7 +401,7 @@ bool FuText::MouseButtonUp(const MouseEvent& rMEvt) SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); // set needed attributes for scrolling - SfxItemSetFixed aItemSet( rDrDoc.GetItemPool()); + SfxItemSet aItemSet(SfxItemSet::makeFixedSfxItemSet( rDrDoc.GetItemPool())); aItemSet.Put( makeSdrTextAutoGrowWidthItem( false ) ); aItemSet.Put( makeSdrTextAutoGrowHeightItem( false ) ); @@ -666,7 +666,7 @@ rtl::Reference FuText::CreateDefaultObject(const sal_uInt16 nID, cons if(bMarquee) { - SfxItemSetFixed aSet(rDrDoc.GetItemPool()); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet(rDrDoc.GetItemPool())); aSet.Put( makeSdrTextAutoGrowWidthItem( false ) ); aSet.Put( makeSdrTextAutoGrowHeightItem( false ) ); diff --git a/sc/source/ui/formdlg/dwfunctr.cxx b/sc/source/ui/formdlg/dwfunctr.cxx index 19532e942fba..8b2edc540e92 100644 --- a/sc/source/ui/formdlg/dwfunctr.cxx +++ b/sc/source/ui/formdlg/dwfunctr.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -450,7 +451,7 @@ void ScFunctionWin::DoEnter(bool bDoubleOrEnter) #* #************************************************************************/ -IMPL_LINK_NOARG(ScFunctionWin, ModifyHdl, weld::Entry&, void) +IMPL_LINK_NOARG(ScFunctionWin, ModifyHdl, weld::TextWidget&, void) { if (xCatBox->get_active() == LRU_CATEGORY || xCatBox->get_active() == FAVOURITES_CATEGORY) { diff --git a/sc/source/ui/formdlg/formula.cxx b/sc/source/ui/formdlg/formula.cxx index b810953c9a1b..6f4ff735fb2f 100644 --- a/sc/source/ui/formdlg/formula.cxx +++ b/sc/source/ui/formdlg/formula.cxx @@ -59,7 +59,7 @@ using namespace com::sun::star; ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, const ScViewData& rViewData, const formula::IFunctionManager* _pFunctionMgr) - : formula::FormulaDlg(pB, pCW, pParent, _pFunctionMgr, this) + : formula::FormulaDlg(pB, pCW, pParent, _pFunctionMgr, *this) , m_aHelper(this, pB, m_xDialog.get()) , m_pViewShell( nullptr ) { diff --git a/sc/source/ui/inc/AccessibleCell.hxx b/sc/source/ui/inc/AccessibleCell.hxx index 410de8bb7969..72252b90fb61 100644 --- a/sc/source/ui/inc/AccessibleCell.hxx +++ b/sc/source/ui/inc/AccessibleCell.hxx @@ -42,22 +42,15 @@ class ScAccessibleCell final : public ScAccessibleCellBase, public accessibility::AccessibleStaticTextBase { public: - static rtl::Reference create( - const css::uno::Reference& rxParent, - ScTabViewShell* pViewShell, - const ScAddress& rCellAddress, - sal_Int64 nIndex, - ScSplitPos eSplitPos, - ScAccessibleDocument* pAccDoc); + static rtl::Reference + create(const rtl::Reference& rpParent, ScTabViewShell* pViewShell, + const ScAddress& rCellAddress, sal_Int64 nIndex, ScSplitPos eSplitPos, + ScAccessibleDocument* pAccDoc); private: - ScAccessibleCell( - const css::uno::Reference& rxParent, - ScTabViewShell* pViewShell, - const ScAddress& rCellAddress, - sal_Int64 nIndex, - ScSplitPos eSplitPos, - ScAccessibleDocument* pAccDoc); + ScAccessibleCell(const rtl::Reference& rpParent, + ScTabViewShell* pViewShell, const ScAddress& rCellAddress, sal_Int64 nIndex, + ScSplitPos eSplitPos, ScAccessibleDocument* pAccDoc); using ScAccessibleCellBase::disposing; virtual void SAL_CALL disposing() override; diff --git a/sc/source/ui/inc/AccessibleCellBase.hxx b/sc/source/ui/inc/AccessibleCellBase.hxx index 8f641f879bce..9e288e342c6b 100644 --- a/sc/source/ui/inc/AccessibleCellBase.hxx +++ b/sc/source/ui/inc/AccessibleCellBase.hxx @@ -28,11 +28,9 @@ class ScAccessibleCellBase css::accessibility::XAccessibleValue> { public: - ScAccessibleCellBase( - const css::uno::Reference& rxParent, - ScDocument* pDoc, - const ScAddress& rCellAddress, - sal_Int64 nIndex); + ScAccessibleCellBase(const rtl::Reference& rpParent, ScDocument* pDoc, + const ScAddress& rCellAddress, sal_Int64 nIndex); + protected: virtual ~ScAccessibleCellBase() override; public: diff --git a/sc/source/ui/inc/AccessibleContextBase.hxx b/sc/source/ui/inc/AccessibleContextBase.hxx index 149e7e0af7d5..9f76bdc60519 100644 --- a/sc/source/ui/inc/AccessibleContextBase.hxx +++ b/sc/source/ui/inc/AccessibleContextBase.hxx @@ -38,9 +38,8 @@ class ScAccessibleContextBase : public comphelper::OAccessible, public SfxListen { public: - ScAccessibleContextBase( - css::uno::Reference xParent, - const sal_Int16 aRole); + ScAccessibleContextBase(const rtl::Reference& rpParent, + const sal_Int16 aRole); virtual void Init(); virtual void SAL_CALL disposing() override; @@ -136,7 +135,7 @@ public: /// Use this method to set initial Description without notification void SetDescription(const OUString& rDesc) { msDescription = rDesc; } - void SetParent(const css::uno::Reference& rParent) { mxParent = rParent; } + void SetParent(const rtl::Reference& rpParent) { mpParent = rpParent; } protected: /// Calls all FocusListener to tell they that the focus is gained. @@ -148,7 +147,7 @@ protected: bool IsDefunc() const { return rBHelper.bDisposed; } /// Reference to the parent object. - css::uno::Reference mxParent; + rtl::Reference mpParent; private: /** Description of this object. This is not a constant because it can diff --git a/sc/source/ui/inc/AccessibleDocument.hxx b/sc/source/ui/inc/AccessibleDocument.hxx index c95257070ea1..0beb28a05d2f 100644 --- a/sc/source/ui/inc/AccessibleDocument.hxx +++ b/sc/source/ui/inc/AccessibleDocument.hxx @@ -44,10 +44,8 @@ class ScAccessibleDocument final public accessibility::IAccessibleViewForwarder { public: - ScAccessibleDocument( - const css::uno::Reference& rxParent, - ScTabViewShell* pViewShell, - ScSplitPos eSplitPos); + ScAccessibleDocument(const rtl::Reference& rpParent, + ScTabViewShell* pViewShell, ScSplitPos eSplitPos); void PreInit(); @@ -160,8 +158,7 @@ public: rtl::Reference GetRelationSet(const ScAddress* pAddress) const; - css::uno::Reference< css::accessibility::XAccessible > - GetAccessibleSpreadsheet(); + rtl::Reference GetAccessibleSpreadsheet(); protected: virtual std::unordered_map implGetExtendedAttributes() override; @@ -186,7 +183,7 @@ private: rtl::Reference mpAccessibleSpreadsheet; std::unique_ptr mpChildrenShapes; rtl::Reference mpTempAccEdit; - css::uno::Reference mxTempAcc; + rtl::Reference mpTempAcc; tools::Rectangle maVisArea; bool mbCompleteSheetSelected; @@ -200,7 +197,7 @@ private: bool IsDefunc(sal_Int64 nParentStates); - void AddChild(const css::uno::Reference& xAcc, bool bFireEvent); + void AddChild(const rtl::Reference& pAcc, bool bFireEvent); void RemoveChild(const css::uno::Reference& xAcc, bool bFireEvent); OUString GetCurrentCellName() const; diff --git a/sc/source/ui/inc/AccessibleDocumentBase.hxx b/sc/source/ui/inc/AccessibleDocumentBase.hxx index 0a8d98509ade..f1d944728af4 100644 --- a/sc/source/ui/inc/AccessibleDocumentBase.hxx +++ b/sc/source/ui/inc/AccessibleDocumentBase.hxx @@ -24,7 +24,7 @@ class ScAccessibleDocumentBase : public ScAccessibleContextBase { public: - ScAccessibleDocumentBase(const css::uno::Reference& rxParent); + ScAccessibleDocumentBase(const rtl::Reference& rpParent); protected: virtual ~ScAccessibleDocumentBase() override; diff --git a/sc/source/ui/inc/AccessibleDocumentPagePreview.hxx b/sc/source/ui/inc/AccessibleDocumentPagePreview.hxx index f180713c8d85..2050971ced24 100644 --- a/sc/source/ui/inc/AccessibleDocumentPagePreview.hxx +++ b/sc/source/ui/inc/AccessibleDocumentPagePreview.hxx @@ -35,9 +35,9 @@ class ScAccessibleDocumentPagePreview final : public ScAccessibleDocumentBase { public: - ScAccessibleDocumentPagePreview( - const css::uno::Reference& rxParent, - ScPreviewShell* pViewShell ); + ScAccessibleDocumentPagePreview(const rtl::Reference& rpParent, + ScPreviewShell* pViewShell); + protected: virtual ~ScAccessibleDocumentPagePreview() override; diff --git a/sc/source/ui/inc/AccessibleEditObject.hxx b/sc/source/ui/inc/AccessibleEditObject.hxx index d5577adbb991..1425dccf9eb7 100644 --- a/sc/source/ui/inc/AccessibleEditObject.hxx +++ b/sc/source/ui/inc/AccessibleEditObject.hxx @@ -20,6 +20,7 @@ #pragma once #include "AccessibleContextBase.hxx" +#include "AccessibleDocument.hxx" #include #include @@ -53,13 +54,12 @@ public: }; ScAccessibleEditObject( - const rtl::Reference& rpParent, + const rtl::Reference& rpParent, EditView* pEditView, vcl::Window* pWin, const OUString& rName, const OUString& rDescription, EditObjectType eObjectType); - void InitAcc( - const rtl::Reference& rpParent, - EditView* pEditView, const OUString& rName, const OUString& rDescription); + void InitAcc(const rtl::Reference& rpParent, EditView* pEditView, + const OUString& rName, const OUString& rDescription); protected: virtual ~ScAccessibleEditObject() override; diff --git a/sc/source/ui/inc/AccessiblePageHeader.hxx b/sc/source/ui/inc/AccessiblePageHeader.hxx index f99fa1210463..885e0a2922c2 100644 --- a/sc/source/ui/inc/AccessiblePageHeader.hxx +++ b/sc/source/ui/inc/AccessiblePageHeader.hxx @@ -30,8 +30,8 @@ class ScAccessiblePageHeaderArea; class ScAccessiblePageHeader final : public ScAccessibleContextBase { public: - ScAccessiblePageHeader( const css::uno::Reference& rxParent, - ScPreviewShell* pViewShell, bool bHeader, sal_Int32 nIndex ); + ScAccessiblePageHeader(const rtl::Reference& rpParent, + ScPreviewShell* pViewShell, bool bHeader, sal_Int32 nIndex); protected: virtual ~ScAccessiblePageHeader() override; diff --git a/sc/source/ui/inc/AccessiblePageHeaderArea.hxx b/sc/source/ui/inc/AccessiblePageHeaderArea.hxx index 3cb2b35402ef..caaf0e86ef61 100644 --- a/sc/source/ui/inc/AccessiblePageHeaderArea.hxx +++ b/sc/source/ui/inc/AccessiblePageHeaderArea.hxx @@ -33,11 +33,10 @@ class ScAccessiblePageHeaderArea final : public ScAccessibleContextBase { public: - ScAccessiblePageHeaderArea( - const css::uno::Reference& rxParent, - ScPreviewShell* pViewShell, - const EditTextObject* pEditObj, - SvxAdjust eAdjust); + ScAccessiblePageHeaderArea(const rtl::Reference& rpParent, + ScPreviewShell* pViewShell, const EditTextObject* pEditObj, + SvxAdjust eAdjust); + protected: virtual ~ScAccessiblePageHeaderArea() override; public: diff --git a/sc/source/ui/inc/AccessiblePreviewHeaderCell.hxx b/sc/source/ui/inc/AccessiblePreviewHeaderCell.hxx index 46cb8d530357..8e94127bd1e0 100644 --- a/sc/source/ui/inc/AccessiblePreviewHeaderCell.hxx +++ b/sc/source/ui/inc/AccessiblePreviewHeaderCell.hxx @@ -35,10 +35,9 @@ class ScAccessiblePreviewHeaderCell final css::accessibility::XAccessibleValue> { public: - ScAccessiblePreviewHeaderCell( const css::uno::Reference& rxParent, - ScPreviewShell* pViewShell, - const ScAddress& rCellPos, bool bIsColHdr, bool bIsRowHdr, - sal_Int32 nIndex ); + ScAccessiblePreviewHeaderCell(const rtl::Reference& rpParent, + ScPreviewShell* pViewShell, const ScAddress& rCellPos, + bool bIsColHdr, bool bIsRowHdr, sal_Int32 nIndex); protected: virtual ~ScAccessiblePreviewHeaderCell() override; diff --git a/sc/source/ui/inc/AccessiblePreviewTable.hxx b/sc/source/ui/inc/AccessiblePreviewTable.hxx index 3cb5eb3c5e72..d4ab223a7f81 100644 --- a/sc/source/ui/inc/AccessiblePreviewTable.hxx +++ b/sc/source/ui/inc/AccessiblePreviewTable.hxx @@ -30,8 +30,8 @@ class ScAccessiblePreviewTable css::accessibility::XAccessibleTable> { public: - ScAccessiblePreviewTable( const css::uno::Reference& rxParent, - ScPreviewShell* pViewShell, sal_Int32 nIndex ); + ScAccessiblePreviewTable(const rtl::Reference& rpParent, + ScPreviewShell* pViewShell, sal_Int32 nIndex); protected: virtual ~ScAccessiblePreviewTable() override; diff --git a/sc/source/ui/inc/AccessibleTableBase.hxx b/sc/source/ui/inc/AccessibleTableBase.hxx index 96196718ded0..0def2aa68e80 100644 --- a/sc/source/ui/inc/AccessibleTableBase.hxx +++ b/sc/source/ui/inc/AccessibleTableBase.hxx @@ -32,10 +32,9 @@ class ScAccessibleTableBase css::accessibility::XAccessibleTable, css::accessibility::XAccessibleSelection> { public: - ScAccessibleTableBase( - const css::uno::Reference& rxParent, - ScDocument* pDoc, - const ScRange& rRange); + ScAccessibleTableBase(const rtl::Reference& rpParent, ScDocument* pDoc, + const ScRange& rRange); + protected: virtual ~ScAccessibleTableBase() override; public: diff --git a/sc/source/ui/inc/AnalysisOfVarianceDialog.hxx b/sc/source/ui/inc/AnalysisOfVarianceDialog.hxx index b3a132df4946..44d019c67cfd 100644 --- a/sc/source/ui/inc/AnalysisOfVarianceDialog.hxx +++ b/sc/source/ui/inc/AnalysisOfVarianceDialog.hxx @@ -15,6 +15,7 @@ #include "StatisticsInputOutputDialog.hxx" +#include #include class FormulaTemplate; @@ -40,8 +41,8 @@ private: std::unique_ptr mxRowsPerSampleField; static void RowColumn(ScRangeList& rRangeList, AddressWalkerWriter& aOutput, - FormulaTemplate& aTemplate, const OUString& sFormula, - GroupedBy aGroupedBy, ScRange* pResultRange); + FormulaTemplate& aTemplate, const OUString& sFormula, + GroupedBy eGroupedBy, ScRange* pResultRange); void AnovaSingleFactor(AddressWalkerWriter& output, FormulaTemplate& aTemplate); void AnovaTwoFactor(AddressWalkerWriter& output, FormulaTemplate& aTemplate); diff --git a/sc/source/ui/inc/ChildWindowWrapper.hxx b/sc/source/ui/inc/ChildWindowWrapper.hxx index 926e456c87ce..334289f1511b 100644 --- a/sc/source/ui/inc/ChildWindowWrapper.hxx +++ b/sc/source/ui/inc/ChildWindowWrapper.hxx @@ -21,27 +21,27 @@ template class ChildControllerWrapper : public SfxChildWindow { public: - ChildControllerWrapper(vcl::Window* pParentP, sal_uInt16 nId, - SfxBindings* pBindings, SfxChildWinInfo* pInfo) + ChildControllerWrapper(vcl::Window* pParentP, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo) : SfxChildWindow(pParentP, nId) { - ScTabViewShell* pViewShell = getTabViewShell( pBindings ); + ScTabViewShell* pViewShell = getTabViewShell(rBindings); if (!pViewShell) pViewShell = dynamic_cast< ScTabViewShell *>( SfxViewShell::Current() ); OSL_ENSURE(pViewShell, "Missing view shell!"); if (pViewShell) - SetController(pViewShell->CreateRefDialogController(pBindings, this, pInfo, pParentP->GetFrameWeld(), WindowID)); + SetController(pViewShell->CreateRefDialogController( + rBindings, this, rInfo, pParentP->GetFrameWeld(), WindowID)); if (pViewShell && !GetController()) pViewShell->GetViewFrame().SetChildWindow( nId, false ); } - static std::unique_ptr CreateImpl( - vcl::Window *pParent, sal_uInt16 nId, - SfxBindings *pBindings, SfxChildWinInfo* pInfo ) + static std::unique_ptr + CreateImpl(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, SfxChildWinInfo& rInfo) { - return std::make_unique(pParent, nId, pBindings, pInfo); + return std::make_unique(pParent, nId, rBindings, rInfo); } static void RegisterChildWindow ( @@ -61,11 +61,9 @@ public: } private: - static ScTabViewShell* getTabViewShell( const SfxBindings *pBindings ) + static ScTabViewShell* getTabViewShell(const SfxBindings& rBindings) { - if( !pBindings ) - return nullptr; - SfxDispatcher* pDispacher = pBindings ->GetDispatcher(); + SfxDispatcher* pDispacher = rBindings.GetDispatcher(); if( !pDispacher ) return nullptr; SfxViewFrame* pFrame = pDispacher->GetFrame(); diff --git a/sc/source/ui/inc/FilterListBox.hxx b/sc/source/ui/inc/FilterListBox.hxx index bf6630c3db5a..c4a6e23dd6d8 100644 --- a/sc/source/ui/inc/FilterListBox.hxx +++ b/sc/source/ui/inc/FilterListBox.hxx @@ -25,7 +25,7 @@ #include #include #include -#include +#include class ScGridWindow; struct ImplSVEvent; diff --git a/sc/source/ui/inc/FourierAnalysisDialog.hxx b/sc/source/ui/inc/FourierAnalysisDialog.hxx index c54540bb3321..4a9e556b3078 100644 --- a/sc/source/ui/inc/FourierAnalysisDialog.hxx +++ b/sc/source/ui/inc/FourierAnalysisDialog.hxx @@ -12,6 +12,8 @@ #include "StatisticsInputOutputDialog.hxx" +#include +#include #include class ScFourierAnalysisDialog : public ScStatisticsInputOutputDialog diff --git a/sc/source/ui/inc/MovingAverageDialog.hxx b/sc/source/ui/inc/MovingAverageDialog.hxx index 7d91a6d01a48..132ed0d2a225 100644 --- a/sc/source/ui/inc/MovingAverageDialog.hxx +++ b/sc/source/ui/inc/MovingAverageDialog.hxx @@ -15,6 +15,7 @@ #include "StatisticsInputOutputDialog.hxx" +#include #include class ScMovingAverageDialog : public ScStatisticsInputOutputDialog diff --git a/sc/source/ui/inc/PivotCalcFieldDialog.hxx b/sc/source/ui/inc/PivotCalcFieldDialog.hxx index 31cfa5b5958d..1feb009c168b 100644 --- a/sc/source/ui/inc/PivotCalcFieldDialog.hxx +++ b/sc/source/ui/inc/PivotCalcFieldDialog.hxx @@ -19,11 +19,12 @@ #pragma once -#include -#include +#include #include +#include #include #include +#include #include "viewdata.hxx" #include @@ -66,7 +67,6 @@ private: ScPivotParam maPivotParameters; std::vector maDeletedFieldNames; - void Init(); void ErrorBox(const OUString& rString); bool IsExistingField(std::u16string_view rName) const; std::shared_ptr ValidateFormula(const OUString& rFormula, @@ -89,7 +89,7 @@ private: DECL_LINK(DoubleClickHdl, const weld::TreeIter&, bool); DECL_LINK(FieldListSelected, weld::ItemView&, void); DECL_LINK(CalcFieldNameSelected, weld::ComboBox&, void); - DECL_LINK(CalcEntryChanged, weld::TextView&, void); + DECL_LINK(CalcEntryChanged, weld::TextWidget&, void); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/PivotLayoutDialog.hxx b/sc/source/ui/inc/PivotLayoutDialog.hxx index dacd0a755053..ac45d0df2e3b 100644 --- a/sc/source/ui/inc/PivotLayoutDialog.hxx +++ b/sc/source/ui/inc/PivotLayoutDialog.hxx @@ -19,6 +19,10 @@ #include "PivotLayoutTreeListLabel.hxx" #include +#include +#include +#include +#include class ScItemValue final { diff --git a/sc/source/ui/inc/PivotLayoutTreeListBase.hxx b/sc/source/ui/inc/PivotLayoutTreeListBase.hxx index 98673c180651..510119f1fe8b 100644 --- a/sc/source/ui/inc/PivotLayoutTreeListBase.hxx +++ b/sc/source/ui/inc/PivotLayoutTreeListBase.hxx @@ -12,7 +12,7 @@ #include #include -#include + #include class ScPivotLayoutDialog; diff --git a/sc/source/ui/inc/RandomNumberGeneratorDialog.hxx b/sc/source/ui/inc/RandomNumberGeneratorDialog.hxx index a0c9da561ce0..205742bc4f28 100644 --- a/sc/source/ui/inc/RandomNumberGeneratorDialog.hxx +++ b/sc/source/ui/inc/RandomNumberGeneratorDialog.hxx @@ -12,6 +12,9 @@ #include +#include +#include +#include #include #include diff --git a/sc/source/ui/inc/RegressionDialog.hxx b/sc/source/ui/inc/RegressionDialog.hxx index 691ce0f5bc8c..c7dc5fdd1eb7 100644 --- a/sc/source/ui/inc/RegressionDialog.hxx +++ b/sc/source/ui/inc/RegressionDialog.hxx @@ -13,6 +13,9 @@ #include "StatisticsTwoVariableDialog.hxx" #include "TableFillingAndNavigationTools.hxx" +#include +#include +#include #include class ScRegressionDialog : public ScStatisticsTwoVariableDialog diff --git a/sc/source/ui/inc/SamplingDialog.hxx b/sc/source/ui/inc/SamplingDialog.hxx index 9bf693acf7ec..c4cb888941c1 100644 --- a/sc/source/ui/inc/SamplingDialog.hxx +++ b/sc/source/ui/inc/SamplingDialog.hxx @@ -14,6 +14,10 @@ #include "anyrefdg.hxx" #include "viewdata.hxx" +#include +#include +#include +#include #include class ScSamplingDialog : public ScAnyRefDlgController diff --git a/sc/source/ui/inc/SheetViewBox.hxx b/sc/source/ui/inc/SheetViewBox.hxx index 80303c518247..f86723de1138 100644 --- a/sc/source/ui/inc/SheetViewBox.hxx +++ b/sc/source/ui/inc/SheetViewBox.hxx @@ -13,6 +13,8 @@ #include #include +class ScViewData; + /** Box / container for the combobox for showing / selecting the sheet view */ class SheetViewBox final : public InterimItemWindow { @@ -23,9 +25,7 @@ public: virtual void GetFocus() override; - void Update(sc::SheetViewID nID); - - weld::ComboBox* getWidget() { return m_xWidget.get(); } + void Update(ScViewData& rViewData); private: std::unique_ptr m_xWidget; diff --git a/sc/source/ui/inc/SheetViewOperationsTester.hxx b/sc/source/ui/inc/SheetViewOperationsTester.hxx index 21a1ac00ac34..8afa812bd63c 100644 --- a/sc/source/ui/inc/SheetViewOperationsTester.hxx +++ b/sc/source/ui/inc/SheetViewOperationsTester.hxx @@ -7,66 +7,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include - #pragma once class ScViewData; namespace sc { -/** Operations that can be performed on a sheet. */ -enum class Operation -{ - Unknown, - DeleteContent, - DeleteCell, - TransliterateText, - SetNormalString, - SetNoteText, - ReplaceNoteText, - InsertColumnsBefore, - InsertColumnsAfter, - InsertRowsBefore, - InsertRowsAfter, - InsertCellsDown, - InsertCellsRight, - DeleteColumns, - DeleteRows, - DeleteCellsLeft, - DeleteCellsUp, - MoveBlock, - ClearItems, - ChangeIndent, - AutoFormat, - EnterMatrix, - TabOperation, - FillSimple, - FillSeries, - FillAuto, - MergeCells, - InsertNameList, - ConvertFormulaToValue, - Sort, - Query, - SubTotals, - PivotTableUpdate, - PivotTableRemove, - PivotTableCreate, - SparklineInsert, - SparklineDelete, - SparklineChange, - SparklineGroup, - SparklineUngroup, - SparklineGroupDelete, - SparklineGroupChange, - EnterData, -}; +enum class OperationType; -/** Tester for operations on sheet views and default views - * - * Tests if an operation can be performed in a sheet view or the operation on the default view unsyncs the sheet view(s). - */ +/** Tester for operations on sheet views and default views */ class SheetViewOperationsTester { ScViewData* mpViewData; @@ -77,7 +26,7 @@ public: { } - bool check(Operation eOperation) const; + bool check(OperationType eOperationType) const; }; } diff --git a/sc/source/ui/inc/SparklineDataRangeDialog.hxx b/sc/source/ui/inc/SparklineDataRangeDialog.hxx index 99a9ba4ac3f5..c96b7b3e5946 100644 --- a/sc/source/ui/inc/SparklineDataRangeDialog.hxx +++ b/sc/source/ui/inc/SparklineDataRangeDialog.hxx @@ -49,7 +49,6 @@ private: void setupValues(); void perform(); - bool checkValidInputOutput(); public: SparklineDataRangeDialog(SfxBindings* pBindings, SfxChildWindow* pChildWindow, diff --git a/sc/source/ui/inc/SparklineDialog.hxx b/sc/source/ui/inc/SparklineDialog.hxx index df2a48bf60e9..2401da999341 100644 --- a/sc/source/ui/inc/SparklineDialog.hxx +++ b/sc/source/ui/inc/SparklineDialog.hxx @@ -16,8 +16,11 @@ #include #include +#include +#include #include #include +#include #include class ColorListBox; diff --git a/sc/source/ui/inc/StatisticsInputOutputDialog.hxx b/sc/source/ui/inc/StatisticsInputOutputDialog.hxx index e831772c8451..f66ecae9b0e2 100644 --- a/sc/source/ui/inc/StatisticsInputOutputDialog.hxx +++ b/sc/source/ui/inc/StatisticsInputOutputDialog.hxx @@ -14,12 +14,16 @@ #include "anyrefdg.hxx" #include "viewdata.hxx" +#include +#include + class ScStatisticsInputOutputDialog : public ScAnyRefDlgController { public: - enum GroupedBy { - BY_COLUMN, - BY_ROW + enum class GroupedBy + { + ByColumn, + ByRow }; ScStatisticsInputOutputDialog( diff --git a/sc/source/ui/inc/StatisticsTwoVariableDialog.hxx b/sc/source/ui/inc/StatisticsTwoVariableDialog.hxx index f848f8ccc3b1..e89935c00957 100644 --- a/sc/source/ui/inc/StatisticsTwoVariableDialog.hxx +++ b/sc/source/ui/inc/StatisticsTwoVariableDialog.hxx @@ -14,6 +14,9 @@ #include "anyrefdg.hxx" #include "viewdata.hxx" +#include +#include + class ScStatisticsTwoVariableDialog : public ScAnyRefDlgController { public: diff --git a/sc/source/ui/inc/TableStylesBox.hxx b/sc/source/ui/inc/TableStylesBox.hxx index 4a7cfacf47c0..66c5f04a8b08 100644 --- a/sc/source/ui/inc/TableStylesBox.hxx +++ b/sc/source/ui/inc/TableStylesBox.hxx @@ -10,6 +10,7 @@ #pragma once #include +#include #include #include @@ -23,8 +24,6 @@ public: void Update(const ScDatabaseSettingItem* pItem); - weld::ComboBox* getWidget() { return m_xCmbStyle.get(); } - private: std::unique_ptr m_xChkHeaderRow; std::unique_ptr m_xChkTotalRow; diff --git a/sc/source/ui/inc/ThemeColorChanger.hxx b/sc/source/ui/inc/ThemeColorChanger.hxx index f85401385888..57ca91cdb83c 100644 --- a/sc/source/ui/inc/ThemeColorChanger.hxx +++ b/sc/source/ui/inc/ThemeColorChanger.hxx @@ -24,7 +24,7 @@ public: ThemeColorChanger(ScDocShell& rDocShell); virtual ~ThemeColorChanger() override; - void doApply(std::shared_ptr const& pColorSet) override; + void apply(std::shared_ptr const& pColorSet) override; }; } // end sc namespace diff --git a/sc/source/ui/inc/acredlin.hxx b/sc/source/ui/inc/acredlin.hxx index e7e6c95b1479..8d3cd4f418a4 100644 --- a/sc/source/ui/inc/acredlin.hxx +++ b/sc/source/ui/inc/acredlin.hxx @@ -156,7 +156,7 @@ public: void ReInit(ScViewData& rViewData); - void Initialize (SfxChildWinInfo* pInfo); + void Initialize(SfxChildWinInfo& rInfo); virtual void FillInfo(SfxChildWinInfo&) const override; }; diff --git a/sc/source/ui/inc/asciiopt.hxx b/sc/source/ui/inc/asciiopt.hxx index af97d4b0f2ba..f081dbad2e8a 100644 --- a/sc/source/ui/inc/asciiopt.hxx +++ b/sc/source/ui/inc/asciiopt.hxx @@ -21,6 +21,7 @@ #include #include +#include #include "csvcontrol.hxx" @@ -39,10 +40,11 @@ private: bool bSaveAsShown; bool bSaveFormulas; bool bIncludeBOM; + SvStreamEndian nEndianness; sal_Unicode cTextSep; - rtl_TextEncoding eCharSet; + rtl_TextEncoding eEncoding; LanguageType eLang; - bool bCharSetSystem; + bool bEncodingSystem; sal_Int32 nStartRow; std::vector mvColStart; std::vector mvColFormat; @@ -55,7 +57,7 @@ public: void ReadFromString( std::u16string_view rString, SvStream* pStream4Detect = nullptr ); OUString WriteToString() const; - rtl_TextEncoding GetCharSet() const { return eCharSet; } + rtl_TextEncoding GetEncoding() const { return eEncoding; } const OUString& GetFieldSeps() const { return aFieldSeps; } bool IsMergeSeps() const { return bMergeFieldSeps; } bool IsRemoveSpace() const { return bRemoveSpace; } @@ -65,6 +67,7 @@ public: bool IsEvaluateFormulas() const { return bEvaluateFormulas; } bool IsSkipEmptyCells() const { return bSkipEmptyCells; } bool GetIncludeBOM() const { return bIncludeBOM; } + SvStreamEndian GetEndianness() const { return nEndianness; } sal_Unicode GetTextSep() const { return cTextSep; } bool IsFixedLen() const { return bFixedLen; } sal_uInt16 GetInfoCount() const { return mvColStart.size(); } @@ -73,8 +76,8 @@ public: sal_Int32 GetStartRow() const { return nStartRow; } LanguageType GetLanguage() const { return eLang; } - void SetCharSet( rtl_TextEncoding eNew ) { eCharSet = eNew; } - void SetCharSetSystem( bool bSet ) { bCharSetSystem = bSet; } + void SetEncoding( rtl_TextEncoding eNew ) { eEncoding = eNew; } + void SetEncodingSystem( bool bSet ) { bEncodingSystem = bSet; } void SetFixedLen( bool bSet ) { bFixedLen = bSet; } void SetFieldSeps( const OUString& rStr ) { aFieldSeps = rStr; } void SetMergeSeps( bool bSet ) { bMergeFieldSeps = bSet; } @@ -85,6 +88,7 @@ public: void SetEvaluateFormulas(bool bSet) { bEvaluateFormulas = bSet; } void SetSkipEmptyCells(bool bSet) { bSkipEmptyCells = bSet; } void SetIncludeBOM(bool bVal) { bIncludeBOM = bVal; } + void SetEndianness(SvStreamEndian nSet) { nEndianness = nSet; } void SetTextSep( sal_Unicode c ) { cTextSep = c; } void SetStartRow( sal_Int32 nRow) { nStartRow= nRow; } void SetLanguage(LanguageType e) { eLang = e; } diff --git a/sc/source/ui/inc/attrdlg.hxx b/sc/source/ui/inc/attrdlg.hxx index 1f4268481f35..ccc846123dee 100644 --- a/sc/source/ui/inc/attrdlg.hxx +++ b/sc/source/ui/inc/attrdlg.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include namespace weld { diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx index 5acb7f1c6890..47aabd3e4581 100644 --- a/sc/source/ui/inc/checklistmenu.hxx +++ b/sc/source/ui/inc/checklistmenu.hxx @@ -11,11 +11,14 @@ #include #include +#include #include +#include +#include #include #include +#include #include -#include #include #include @@ -271,7 +274,7 @@ private: DECL_LINK(SearchEditTimeoutHdl, Timer*, void); DECL_LINK(ComboChangedHdl, weld::ComboBox&, void); - DECL_LINK(EdModifyHdl, weld::Entry&, void); + DECL_LINK(EdModifyHdl, weld::TextWidget&, void); DECL_LINK(EdActivateHdl, weld::Entry&, bool); DECL_LINK(RowActivatedHdl, const weld::TreeIter&, bool); diff --git a/sc/source/ui/inc/colorformat.hxx b/sc/source/ui/inc/colorformat.hxx index 2d8a81342ae8..0e60cb7b8e43 100644 --- a/sc/source/ui/inc/colorformat.hxx +++ b/sc/source/ui/inc/colorformat.hxx @@ -9,10 +9,12 @@ #pragma once +#include +#include #include #include #include -#include +#include #include #include diff --git a/sc/source/ui/inc/condformatdlg.hxx b/sc/source/ui/inc/condformatdlg.hxx index c376d9f2ef95..5fee50a35fcd 100644 --- a/sc/source/ui/inc/condformatdlg.hxx +++ b/sc/source/ui/inc/condformatdlg.hxx @@ -15,6 +15,9 @@ #include "anyrefdg.hxx" +#include +#include +#include #include #include diff --git a/sc/source/ui/inc/condformatdlgentry.hxx b/sc/source/ui/inc/condformatdlgentry.hxx index 74df21669355..877b485dc997 100644 --- a/sc/source/ui/inc/condformatdlgentry.hxx +++ b/sc/source/ui/inc/condformatdlgentry.hxx @@ -12,9 +12,12 @@ #include #include #include +#include #include +#include #include -#include +#include +#include #include #include diff --git a/sc/source/ui/inc/condformateasydlg.hxx b/sc/source/ui/inc/condformateasydlg.hxx index 347486b9cb20..8956f42e6a1e 100644 --- a/sc/source/ui/inc/condformateasydlg.hxx +++ b/sc/source/ui/inc/condformateasydlg.hxx @@ -11,8 +11,11 @@ #include "anyrefdg.hxx" #include +#include #include +#include #include +#include #include class ScViewData; @@ -47,7 +50,7 @@ private: std::unique_ptr mxRangeEntry; std::unique_ptr mxButtonRangeEdit; std::unique_ptr mxStyles; - std::unique_ptr mxDescription; + std::unique_ptr mxConditionFrame; std::unique_ptr mxButtonOk; std::unique_ptr mxButtonCancel; }; diff --git a/sc/source/ui/inc/condformatmgr.hxx b/sc/source/ui/inc/condformatmgr.hxx index e761e1a81ff0..fa2a35f3bcd2 100644 --- a/sc/source/ui/inc/condformatmgr.hxx +++ b/sc/source/ui/inc/condformatmgr.hxx @@ -9,9 +9,10 @@ #pragma once +#include #include #include -#include +#include class ScDocument; class ScConditionalFormat; diff --git a/sc/source/ui/inc/conflictsdlg.hxx b/sc/source/ui/inc/conflictsdlg.hxx index 3f3cdf6a1375..813932c2df7e 100644 --- a/sc/source/ui/inc/conflictsdlg.hxx +++ b/sc/source/ui/inc/conflictsdlg.hxx @@ -21,6 +21,7 @@ #include #include +#include #include #include "docsh.hxx" diff --git a/sc/source/ui/inc/consdlg.hxx b/sc/source/ui/inc/consdlg.hxx index b2a46ccd6725..e4d3c41e5dd4 100644 --- a/sc/source/ui/inc/consdlg.hxx +++ b/sc/source/ui/inc/consdlg.hxx @@ -22,6 +22,8 @@ #include #include "anyrefdg.hxx" +#include + class ScViewData; class ScDocument; class ScAreaData; diff --git a/sc/source/ui/inc/content.hxx b/sc/source/ui/inc/content.hxx index 9ce132b2752c..4bba9b558012 100644 --- a/sc/source/ui/inc/content.hxx +++ b/sc/source/ui/inc/content.hxx @@ -20,7 +20,6 @@ #pragma once #include -#include #include #include #include diff --git a/sc/source/ui/inc/corodlg.hxx b/sc/source/ui/inc/corodlg.hxx index fa16f379ed49..e7b5a7ba1ee6 100644 --- a/sc/source/ui/inc/corodlg.hxx +++ b/sc/source/ui/inc/corodlg.hxx @@ -20,8 +20,9 @@ #pragma once #include +#include #include -#include +#include class ScColRowLabelDlg : public weld::GenericDialogController { diff --git a/sc/source/ui/inc/crdlg.hxx b/sc/source/ui/inc/crdlg.hxx index 73087391b6d4..f80a15110091 100644 --- a/sc/source/ui/inc/crdlg.hxx +++ b/sc/source/ui/inc/crdlg.hxx @@ -19,8 +19,11 @@ #pragma once +#include #include -#include +#include +#include +#include class ScColOrRowDlg : public weld::GenericDialogController { diff --git a/sc/source/ui/inc/crnrdlg.hxx b/sc/source/ui/inc/crnrdlg.hxx index 51672b432ab1..0e52c2aa0512 100644 --- a/sc/source/ui/inc/crnrdlg.hxx +++ b/sc/source/ui/inc/crnrdlg.hxx @@ -22,6 +22,9 @@ #include "anyrefdg.hxx" #include +#include +#include + #include class ScViewData; diff --git a/sc/source/ui/inc/csvtablebox.hxx b/sc/source/ui/inc/csvtablebox.hxx index 3d546952b74e..65fcf9cf5be4 100644 --- a/sc/source/ui/inc/csvtablebox.hxx +++ b/sc/source/ui/inc/csvtablebox.hxx @@ -23,7 +23,7 @@ #include #include #include -#include + #include #include "csvcontrol.hxx" #include "csvruler.hxx" diff --git a/sc/source/ui/inc/dapidata.hxx b/sc/source/ui/inc/dapidata.hxx index 844a900491aa..e87316ac0f74 100644 --- a/sc/source/ui/inc/dapidata.hxx +++ b/sc/source/ui/inc/dapidata.hxx @@ -21,7 +21,7 @@ #include #include -#include +#include struct ScImportSourceDesc; diff --git a/sc/source/ui/inc/dapitype.hxx b/sc/source/ui/inc/dapitype.hxx index 7a08bc64dbbd..70a0572470c3 100644 --- a/sc/source/ui/inc/dapitype.hxx +++ b/sc/source/ui/inc/dapitype.hxx @@ -19,10 +19,12 @@ #pragma once +#include #include #include #include -#include +#include +#include class ScDataPilotSourceTypeDlg : public weld::GenericDialogController { diff --git a/sc/source/ui/inc/datafdlg.hxx b/sc/source/ui/inc/datafdlg.hxx index b6b74829127b..c2e8d16bb674 100644 --- a/sc/source/ui/inc/datafdlg.hxx +++ b/sc/source/ui/inc/datafdlg.hxx @@ -9,10 +9,13 @@ #pragma once +#include #include #include +#include +#include #include -#include + #include #include "viewfunc.hxx" @@ -67,7 +70,7 @@ private: DECL_LINK(Impl_CloseHdl, weld::Button&, void); DECL_LINK(Impl_ScrollHdl, weld::ScrolledWindow&, void); - DECL_LINK(Impl_DataModifyHdl, weld::Entry&, void); + DECL_LINK(Impl_DataModifyHdl, weld::TextWidget&, void); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/dataprovider.hxx b/sc/source/ui/inc/dataprovider.hxx index 210db57d934f..6dd294761b0b 100644 --- a/sc/source/ui/inc/dataprovider.hxx +++ b/sc/source/ui/inc/dataprovider.hxx @@ -56,9 +56,6 @@ public: virtual ~CSVFetchThread() override; void RequestTerminate(); - bool IsRequestedTerminate(); - void Terminate(); - void EndThread(); bool IsParseError() const { return mbIsParseError; } const std::exception_ptr & GetLastException() const { return mpLastException; } @@ -85,8 +82,6 @@ public: virtual void Import() = 0; - virtual const OUString& GetURL() const = 0; - static std::unique_ptr FetchStreamFromURL(const OUString&, OStringBuffer& rBuffer); void setDeterministic(); @@ -106,7 +101,7 @@ public: virtual void Import() override; - const OUString& GetURL() const override; + const OUString& GetURL() const; void ImportFinished(); }; diff --git a/sc/source/ui/inc/dataproviderdlg.hxx b/sc/source/ui/inc/dataproviderdlg.hxx index 0e06e253c1cb..18ff958ec7b3 100644 --- a/sc/source/ui/inc/dataproviderdlg.hxx +++ b/sc/source/ui/inc/dataproviderdlg.hxx @@ -15,11 +15,13 @@ #include #include +#include #include +#include #include #include #include -#include + #include "datatableview.hxx" #include @@ -60,16 +62,14 @@ private: ScDBData* pDBData; ScDBCollection* mpDestDBCollection; - DECL_LINK(StartMenuHdl, const OString&, void); - DECL_LINK(ColumnMenuHdl, const weld::ComboBox&, void); DECL_LINK(ScrollToEnd, Timer*, void); DECL_LINK(ApplyQuitHdl, weld::Button&, void); DECL_LINK(CancelQuitHdl, weld::Button&, void); DECL_LINK(TransformationListHdl, weld::Button&, void); DECL_LINK(ProviderSelectHdl, weld::ComboBox&, void); DECL_LINK(TransformationSelectHdl, weld::ComboBox&, void); - DECL_LINK(IDEditHdl, weld::Entry&, void); - DECL_LINK(URLEditHdl, weld::Entry&, void); + DECL_LINK(IDEditHdl, weld::TextWidget&, void); + DECL_LINK(URLEditHdl, weld::TextWidget&, void); DECL_LINK(ApplyBtnHdl, weld::Button&, void); DECL_LINK(BrowseBtnHdl, weld::Button&, void); @@ -78,9 +78,6 @@ public: const ScDocument* pDocument); virtual ~ScDataProviderDlg() override; - void applyAndQuit(); - void cancelAndQuit(); - void deleteColumn(); void splitColumn(); void mergeColumns(); diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx index f3144570e9eb..bee921b3c6ab 100644 --- a/sc/source/ui/inc/datastreamdlg.hxx +++ b/sc/source/ui/inc/datastreamdlg.hxx @@ -11,10 +11,14 @@ #include +#include +#include #include #include #include -#include +#include +#include +#include class ScDocShell; class SvtURLBox; @@ -45,7 +49,7 @@ class DataStreamDlg : public weld::GenericDialogController std::unique_ptr m_xVclFrameMove; DECL_LINK(UpdateClickHdl, weld::Toggleable&, void); - DECL_LINK(UpdateHdl, weld::Entry&, void); + DECL_LINK(UpdateHdl, weld::TextWidget&, void); DECL_LINK(UpdateComboBoxHdl, weld::ComboBox&, void); DECL_LINK(BrowseHdl, weld::Button&, void); diff --git a/sc/source/ui/inc/datatableview.hxx b/sc/source/ui/inc/datatableview.hxx index 2635c7952a9e..d4d8293c7d68 100644 --- a/sc/source/ui/inc/datatableview.hxx +++ b/sc/source/ui/inc/datatableview.hxx @@ -105,7 +105,6 @@ public: virtual Size GetOptimalSize() const override; void getColRange(SCCOL& rStartCol, SCCOL& rEndCol) const; - void getRowRange(SCROW& rStartRow, SCROW& rEndRow) const; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/datatransformation.hxx b/sc/source/ui/inc/datatransformation.hxx index 038c11fb03b5..0818526bcafc 100644 --- a/sc/source/ui/inc/datatransformation.hxx +++ b/sc/source/ui/inc/datatransformation.hxx @@ -195,9 +195,6 @@ class FindReplaceTransformation : public DataTransformation FindReplaceTransformation(SCCOL nCol, OUString aFindString, OUString aReplaceString); virtual void Transform(ScDocument& rDoc) const override; virtual TransformationType getTransformationType() const override; - SCCOL getColumn() const; - const OUString & getFindString() const; - const OUString & getReplaceString() const; }; class DeleteRowTransformation : public DataTransformation @@ -209,8 +206,6 @@ class DeleteRowTransformation : public DataTransformation DeleteRowTransformation(SCCOL nCol, OUString aFindString); virtual void Transform(ScDocument& rDoc) const override; virtual TransformationType getTransformationType() const override; - SCCOL getColumn() const; - const OUString & getFindString() const; }; class SwapRowsTransformation : public DataTransformation @@ -221,8 +216,6 @@ class SwapRowsTransformation : public DataTransformation SwapRowsTransformation(SCROW mRow, SCROW nRow); virtual void Transform(ScDocument& rDoc) const override; virtual TransformationType getTransformationType() const override; - SCROW getFirstRow() const; - SCROW getSecondRow() const; }; } diff --git a/sc/source/ui/inc/dbdocfun.hxx b/sc/source/ui/inc/dbdocfun.hxx index 80a833bc2ddc..51d889211283 100644 --- a/sc/source/ui/inc/dbdocfun.hxx +++ b/sc/source/ui/inc/dbdocfun.hxx @@ -41,16 +41,16 @@ namespace svx { } namespace sc { - enum class Operation; + enum class OperationType; } class ScDBDocFunc { friend class ScDBFunc; +friend class SortOperation; private: ScDocShell& rDocShell; - static bool CheckSheetViewProtection(sc::Operation eOperation); public: ScDBDocFunc( ScDocShell& rDocSh ): rDocShell(rDocSh) {} @@ -65,14 +65,12 @@ public: static void ShowInBeamer( const ScImportParam& rParam, const SfxViewFrame* pFrame ); - SC_DLLPUBLIC bool Sort( - SCTAB nTab, const ScSortParam& rSortParam, bool bRecord, bool bPaint, bool bApi ); + SC_DLLPUBLIC bool SortTab(SCTAB nTab, const ScSortParam& rSortParam, bool bRecord, bool bPaint, bool bApi); SC_DLLPUBLIC bool Query( SCTAB nTab, const ScQueryParam& rQueryParam, const ScRange* pAdvSource, bool bRecord, bool bApi ); - void DoSubTotals( SCTAB nTab, const ScSubTotalParam& rParam, - bool bRecord, bool bApi ); + SC_DLLPUBLIC void DoSubTotals(SCTAB nTab, const ScSubTotalParam& rParam, bool bRecord, bool bApi); void DoTableSubTotals( SCTAB nTab, const ScDBData& rNewData, const ScSubTotalParam& rParam, bool bRecord, bool bApi ); @@ -93,9 +91,9 @@ public: bool DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj, bool bRecord, bool bApi, bool bAllowMove = false ); - bool RemovePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi); - bool CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi); - bool UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi); + SC_DLLPUBLIC bool RemovePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi); + SC_DLLPUBLIC bool CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi); + SC_DLLPUBLIC bool UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi); /** * Reload the referenced pivot cache, and refresh all pivot tables that diff --git a/sc/source/ui/inc/dbfunc.hxx b/sc/source/ui/inc/dbfunc.hxx index 6965b5980683..4ba94c964fa4 100644 --- a/sc/source/ui/inc/dbfunc.hxx +++ b/sc/source/ui/inc/dbfunc.hxx @@ -61,7 +61,7 @@ public: void DeleteCalcTable(); - void ToggleAutoFilter(); + SC_DLLPUBLIC void ToggleAutoFilter(); void HideAutoFilter(); void ClearAutoFilter(); diff --git a/sc/source/ui/inc/dbnamdlg.hxx b/sc/source/ui/inc/dbnamdlg.hxx index ab1438f5b614..e58baa0a6faa 100644 --- a/sc/source/ui/inc/dbnamdlg.hxx +++ b/sc/source/ui/inc/dbnamdlg.hxx @@ -19,6 +19,11 @@ #pragma once +#include +#include +#include +#include + #include #include "anyrefdg.hxx" #include diff --git a/sc/source/ui/inc/dbtabledlg.hxx b/sc/source/ui/inc/dbtabledlg.hxx index c3a8cc5f191b..f85fb5d334cb 100644 --- a/sc/source/ui/inc/dbtabledlg.hxx +++ b/sc/source/ui/inc/dbtabledlg.hxx @@ -23,6 +23,9 @@ #include "anyrefdg.hxx" #include +#include +#include + class ScViewData; class ScDocument; diff --git a/sc/source/ui/inc/delcldlg.hxx b/sc/source/ui/inc/delcldlg.hxx index f7547cf74bee..b592401e8529 100644 --- a/sc/source/ui/inc/delcldlg.hxx +++ b/sc/source/ui/inc/delcldlg.hxx @@ -20,7 +20,8 @@ #pragma once #include -#include +#include +#include #include diff --git a/sc/source/ui/inc/delcodlg.hxx b/sc/source/ui/inc/delcodlg.hxx index 46805a45cb20..2c262e272c57 100644 --- a/sc/source/ui/inc/delcodlg.hxx +++ b/sc/source/ui/inc/delcodlg.hxx @@ -19,8 +19,10 @@ #pragma once +#include #include -#include +#include + #include class ScDeleteContentsDlg : public weld::GenericDialogController diff --git a/sc/source/ui/inc/dialogs/SelectSheetViewDialog.hxx b/sc/source/ui/inc/dialogs/SelectSheetViewDialog.hxx index e108e1259435..89a2d880f7cb 100644 --- a/sc/source/ui/inc/dialogs/SelectSheetViewDialog.hxx +++ b/sc/source/ui/inc/dialogs/SelectSheetViewDialog.hxx @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include class ScViewData; diff --git a/sc/source/ui/inc/docfunc.hxx b/sc/source/ui/inc/docfunc.hxx index e308884c9b97..31d5fad77be3 100644 --- a/sc/source/ui/inc/docfunc.hxx +++ b/sc/source/ui/inc/docfunc.hxx @@ -24,8 +24,10 @@ #include #include #include +#include #include +#include #include #include @@ -58,7 +60,7 @@ namespace sc class SparklineAttributes; class SparklineGroup; class Sparkline; - enum class Operation; + enum class OperationType; } namespace tools { @@ -68,20 +70,20 @@ namespace tools class ScDocFunc { ScDocShell& rDocShell; - static bool CheckSheetViewProtection(sc::Operation eOperation); protected: - bool AdjustRowHeight( const ScRange& rRange, bool bPaint, bool bApi ); void CreateOneName( ScRangeName& rList, SCCOL nPosX, SCROW nPosY, SCTAB nTab, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, bool& rCancel, bool bApi ); - void NotifyInputHandler( const ScAddress& rPos ); ScDocFunc( ScDocShell& rDocSh ): rDocShell(rDocSh) {} public: virtual ~ScDocFunc() {} + bool AdjustRowHeight( const ScRange& rRange, bool bPaint, bool bApi ); + void NotifyInputHandler( const ScAddress& rPos ); + void NotifyDrawUndo(std::unique_ptr); // for grouping multiple operations into one with a new name @@ -105,14 +107,14 @@ public: bool DeleteCell( const ScAddress& rPos, const ScMarkData& rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi ); - bool TransliterateText( const ScMarkData& rMark, TransliterationFlags nType, + SC_DLLPUBLIC bool TransliterateText( const ScMarkData& rMark, TransliterationFlags nType, bool bApi ); bool SetNormalString( bool& o_rbNumFmtSet, const ScAddress& rPos, const OUString& rText, bool bApi ); - bool SetValueCell( const ScAddress& rPos, double fVal, bool bInteraction ); + SC_DLLPUBLIC bool SetValueCell( const ScAddress& rPos, double fVal, bool bInteraction ); void SetValueCells( const ScAddress& rPos, const std::vector& aVals, bool bInteraction ); - bool SetStringCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction ); - bool SetEditCell( const ScAddress& rPos, const EditTextObject& rStr, bool bInteraction ); + SC_DLLPUBLIC bool SetStringCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction ); + SC_DLLPUBLIC bool SetEditCell( const ScAddress& rPos, const EditTextObject& rStr, bool bInteraction ); bool SetStringOrEditCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction ); @@ -120,7 +122,7 @@ public: * Below two methods take ownership of the formula cell instance(s). The caller * must not delete it after passing it to this call. */ - bool SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell, bool bInteraction ); + SC_DLLPUBLIC bool SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell, bool bInteraction ); bool SetFormulaCells( const ScAddress& rPos, std::vector& rCells, bool bInteraction ); void PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, bool bApi ); bool SetCellText( @@ -129,8 +131,9 @@ public: SC_DLLPUBLIC bool ShowNote( const ScAddress& rPos, bool bShow ); - void SetNoteText( const ScAddress& rPos, const OUString& rNoteText, bool bApi ); - void ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, const OUString* pAuthor, const OUString* pDate, bool bApi ); + SC_DLLPUBLIC void SetNoteText( const ScAddress& rPos, const OUString& rNoteText, bool bApi ); + SC_DLLPUBLIC void ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, const OUString* pAuthor, const OUString* pDate, bool bApi ); + SC_DLLPUBLIC void InsertThreadedComment( const ScAddress& rPos, const OUString& rText, const OUString* pAuthor, bool bApi ); SC_DLLPUBLIC void ImportNote( const ScAddress& rPos, std::unique_ptr xGenerator, const tools::Rectangle& rCaptionRect, bool bShown ); @@ -146,10 +149,11 @@ public: bool DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd, bool bApi ); - bool MoveBlock( const ScRange& rSource, const ScAddress& rDestPos, + SC_DLLPUBLIC bool MoveBlock( const ScRange& rSource, const ScAddress& rDestPos, bool bCut, bool bRecord, bool bPaint, bool bApi ); SC_DLLPUBLIC bool InsertTable( SCTAB nTab, const OUString& rName, bool bRecord, bool bApi ); + std::pair InsertSheetView( SCTAB nTab, bool bRecord ); SC_DLLPUBLIC bool RenameTable( SCTAB nTab, const OUString& rName, bool bRecord, bool bApi ); bool DeleteTable( SCTAB nTab, bool bRecord ); @@ -174,9 +178,9 @@ public: bool Protect( SCTAB nTab, const OUString& rPassword ); bool Unprotect( SCTAB nTab, std::u16string_view rPassword, bool bApi ); - void ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, bool bApi ); - bool ChangeIndent( const ScMarkData& rMark, bool bIncrement, bool bApi ); - bool AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark, + SC_DLLPUBLIC void ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, bool bApi ); + SC_DLLPUBLIC bool ChangeIndent( const ScMarkData& rMark, bool bIncrement, bool bApi ); + SC_DLLPUBLIC bool AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark, sal_uInt16 nFormatNo, bool bApi ); SC_DLLPUBLIC bool @@ -184,14 +188,15 @@ public: const ScTokenArray* pTokenArray, const OUString& rString, bool bApi, bool bEnglish, const OUString& rFormulaNmsp, - const formula::FormulaGrammar::Grammar ); + const formula::FormulaGrammar::Grammar, + bool bDynamicArrayMaster = false); - bool TabOp( const ScRange& rRange, const ScMarkData* pTabMark, + SC_DLLPUBLIC bool TabOp( const ScRange& rRange, const ScMarkData* pTabMark, const ScTabOpParam& rParam, bool bRecord, bool bApi ); - bool FillSimple( const ScRange& rRange, const ScMarkData* pTabMark, + SC_DLLPUBLIC bool FillSimple( const ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, bool bApi ); - bool FillSeries( const ScRange& rRange, const ScMarkData* pTabMark, + SC_DLLPUBLIC bool FillSeries( const ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, double fStart, double fStep, double fMax, bool bApi ); @@ -224,7 +229,7 @@ public: void ModifyAllRangeNames(const std::map& rRangeMap); bool CreateNames( const ScRange& rRange, CreateNameFlags nFlags, bool bApi, SCTAB nTab = -1 ); // -1 for global range names - bool InsertNameList( const ScAddress& rStartPos, bool bApi ); + SC_DLLPUBLIC bool InsertNameList(const ScAddress& rStartPos, bool bApi); void InsertAreaLink( const OUString& rFile, const OUString& rFilter, const OUString& rOptions, const OUString& rSource, @@ -245,7 +250,7 @@ public: */ void SetConditionalFormatList( ScConditionalFormatList* pList, SCTAB nTab ); - void ConvertFormulaToValue( const ScRange& rRange, bool bInteraction ); + SC_DLLPUBLIC void ConvertFormulaToValue( const ScRange& rRange, bool bInteraction ); SC_DLLPUBLIC bool InsertSparklines(ScRange const& rDataRange, ScRange const& rSparklineRange, const std::shared_ptr& pSparklineGroup); @@ -258,6 +263,8 @@ public: SC_DLLPUBLIC bool UngroupSparklines(ScRange const& rRange); SC_DLLPUBLIC bool ChangeSparkline(std::shared_ptr const& rpSparkline, SCTAB nTab, ScRangeList const& rDataRange); + static void PaintAbove(ScDocShell& rDocShell, const ScRange& rRange); + private: void ProtectDocument(const ScDocProtection& rProtect); }; diff --git a/sc/source/ui/inc/docfuncutil.hxx b/sc/source/ui/inc/docfuncutil.hxx index 5a5ea1a22cd0..77cbc651b651 100644 --- a/sc/source/ui/inc/docfuncutil.hxx +++ b/sc/source/ui/inc/docfuncutil.hxx @@ -11,6 +11,8 @@ #include +class ScAddress; +class ScDocFunc; class ScMarkData; class ScRange; enum class InsertDeleteFlags : sal_Int32; @@ -23,6 +25,14 @@ public: static bool hasProtectedTab( const ScDocument& rDoc, const ScMarkData& rMark ); + /// If the cell at rPosition is the master of a multi-cell matrix formula, + /// delete the master cell so the whole matrix (master plus reference cells) + // is removed. + /// Returns true if a demolition happened. Used before single-cell + /// writes so the new value doesn't leave reference cells orphaned. + static bool demolishMatrixMaster( + ScDocFunc& rDocFunc, const ScDocument& rDoc, const ScAddress& rPosition, bool bApi); + static ScDocumentUniquePtr createDeleteContentsUndoDoc( ScDocument& rDoc, const ScMarkData& rMark, const ScRange& rRange, InsertDeleteFlags nFlags, bool bOnlyMarked ); @@ -31,7 +41,8 @@ public: SfxUndoManager* pUndoMgr, ScDocShell& rDocSh, const ScMarkData& rMark, const ScRange& rRange, ScDocumentUniquePtr&& pUndoDoc, InsertDeleteFlags nFlags, const std::shared_ptr& pSpans, - bool bMulti, bool bDrawUndo ); + bool bMulti, bool bDrawUndo, + std::vector const& rRestoreExpandedMatrices); static std::shared_ptr getNonEmptyCellSpans( const ScDocument& rDoc, const ScMarkData& rMark, const ScRange& rRange ); diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index ea8f5a0d8a6f..786e1442a6c7 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -86,8 +86,6 @@ class SAL_DLLPUBLIC_RTTI ScDocShell final: public SfxObjectShell, public SfxList std::unique_ptr m_pImpl; std::unique_ptr m_pDocFunc; - bool m_bHeaderOn; - bool m_bFooterOn; bool m_bIsInplace:1; // Is set by the View bool m_bIsEmpty:1; bool m_bIsInUndo:1; @@ -161,7 +159,7 @@ class SAL_DLLPUBLIC_RTTI ScDocShell final: public SfxObjectShell, public SfxList public: SFX_DECL_INTERFACE(SCID_DOC_SHELL) - SC_DLLPUBLIC static SfxObjectFactory& Factory(); \ + SC_DLLPUBLIC static SfxObjectFactory& Factory(); virtual SfxObjectFactory& GetFactory() const override { return Factory(); } private: @@ -276,6 +274,7 @@ public: void UpdatePendingRowHeights( SCTAB nUpdateTab, bool bBefore = false ); void RefreshPivotTables( const ScRange& rSource ); + SC_DLLPUBLIC void ResolveSpilledOutputs(); void DoConsolidate( const ScConsolidateParam& rParam, bool bRecord = true ); void UseScenario( SCTAB nTab, const OUString& rName, bool bRecord = true ); SCTAB MakeScenario(SCTAB nTab, const OUString& rName, const OUString& rComment, @@ -303,6 +302,10 @@ public: virtual void ReconnectDdeLink(SfxObjectShell& rServer) override; void UpdateLinks() override; + void PerformLinkUpdate() override; + /** The document's HasExternalLinks together with the deferred form-control + images the shell keeps itself. */ + bool HasExternalLinks() const; SC_DLLPUBLIC void SetInitialLinkUpdate( const SfxMedium* pMedium ); void AllowLinkUpdate(); SC_DLLPUBLIC void ReloadAllLinks(); @@ -351,7 +354,6 @@ public: void UnlockDocument(); DECL_LINK( DialogClosedHdl, sfx2::FileDialogHelper*, void ); - DECL_LINK( ReloadAllLinksHdl, weld::Button&, void ); virtual SfxStyleSheetBasePool* GetStyleSheetPool() override; @@ -364,10 +366,6 @@ public: void CalcOutputFactor(); double GetOutputFactor() const { return m_nPrtToScreenFactor;} - void GetPageOnFromPageStyleSet( const SfxItemSet* pStyleSet, - SCTAB nCurTab, - bool& rbHeader, - bool& rbFooter ); #if defined(_WIN32) virtual bool DdeGetData( const OUString& rItem, const OUString& rMimeType, diff --git a/sc/source/ui/inc/dpgroupdlg.hxx b/sc/source/ui/inc/dpgroupdlg.hxx index cc19d34e2f06..95ed4a8002af 100644 --- a/sc/source/ui/inc/dpgroupdlg.hxx +++ b/sc/source/ui/inc/dpgroupdlg.hxx @@ -20,10 +20,13 @@ #pragma once #include +#include #include +#include #include #include -#include +#include + #include class ScDoubleField; diff --git a/sc/source/ui/inc/drawview.hxx b/sc/source/ui/inc/drawview.hxx index fd15876dfe45..579e715b9252 100644 --- a/sc/source/ui/inc/drawview.hxx +++ b/sc/source/ui/inc/drawview.hxx @@ -19,6 +19,7 @@ #pragma once +#include #include #include @@ -29,7 +30,7 @@ class ScDocument; class ScViewData; class ScDrawObjData; -class ScDrawView final : public FmFormView +class SAL_DLLPUBLIC_RTTI ScDrawView final : public FmFormView { ScViewData& rViewData; VclPtr pDev; //! needed ? @@ -115,7 +116,7 @@ public: bool HasMarkedControl() const; bool HasMarkedInternal() const; - bool InsertObjectSafe(SdrObject* pObj, SdrPageView& rPV); + SC_DLLPUBLIC bool InsertObjectSafe(SdrObject* pObj, SdrPageView& rPV); /** Returns the selected object, if it is the caption object of a cell note. @param ppCaptData (out-param) If not null, returns the pointer to the caption object data. */ diff --git a/sc/source/ui/inc/duplicaterecordsdlg.hxx b/sc/source/ui/inc/duplicaterecordsdlg.hxx index 5be00cbf8580..c0ecacc91d5a 100644 --- a/sc/source/ui/inc/duplicaterecordsdlg.hxx +++ b/sc/source/ui/inc/duplicaterecordsdlg.hxx @@ -20,9 +20,12 @@ #pragma once #include "viewdata.hxx" + +#include +#include #include +#include #include -#include using namespace css; diff --git a/sc/source/ui/inc/dwfunctr.hxx b/sc/source/ui/inc/dwfunctr.hxx index 7e1f056c644d..d0787e2e31f8 100644 --- a/sc/source/ui/inc/dwfunctr.hxx +++ b/sc/source/ui/inc/dwfunctr.hxx @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -84,7 +86,7 @@ private: DECL_LINK( SetSimilarityToggleHdl, weld::Toggleable&, void ); DECL_LINK( SelComboHdl, weld::ComboBox&, void ); DECL_LINK(SelTreeHdl, weld::ItemView&, void); - DECL_LINK( ModifyHdl, weld::Entry&, void ); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); DECL_LINK( KeyInputHdl, const KeyEvent&, bool); public: diff --git a/sc/source/ui/inc/editable.hxx b/sc/source/ui/inc/editable.hxx index 5128fb47301d..c08b76a4cf6a 100644 --- a/sc/source/ui/inc/editable.hxx +++ b/sc/source/ui/inc/editable.hxx @@ -88,6 +88,10 @@ public: bool IsEditable() const { return mbIsEditable; } bool IsFormatEditable() const { return mbIsEditable || mbOnlyMatrix; } + /// True when the only obstacle is a matrix at the given single cell + /// position and that cell is part of a matrix. Direct single cell + /// input is allowed for both matrix masters and matrix reference cells. + bool IsEditableOrMatrixCell(const ScDocument& rDoc, const ScAddress& rPos) const; TranslateId GetMessageId() const; }; diff --git a/sc/source/ui/inc/filldlg.hxx b/sc/source/ui/inc/filldlg.hxx index c150f3c54e88..fc160c9f546b 100644 --- a/sc/source/ui/inc/filldlg.hxx +++ b/sc/source/ui/inc/filldlg.hxx @@ -19,9 +19,13 @@ #pragma once +#include #include #include -#include +#include +#include +#include + #include class ScDocument; diff --git a/sc/source/ui/inc/filtdlg.hxx b/sc/source/ui/inc/filtdlg.hxx index 66a226c5ff62..fb078ceb685a 100644 --- a/sc/source/ui/inc/filtdlg.hxx +++ b/sc/source/ui/inc/filtdlg.hxx @@ -25,6 +25,12 @@ #include #include +#include +#include +#include +#include +#include + #include #include #include @@ -177,7 +183,7 @@ private: class ScSpecialFilterDlg : public ScAnyRefDlgController { public: - ScSpecialFilterDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, + ScSpecialFilterDlg(SfxBindings& rBindings, SfxChildWindow* pCW, weld::Window* pParent, ScViewData& rData, const SfxItemSet& rArgSet); virtual ~ScSpecialFilterDlg() override; @@ -189,17 +195,17 @@ public: virtual void Close() override; private: - const OUString aStrUndefined; + const OUString m_aStrUndefined; - std::unique_ptr pOptionsMgr; + std::unique_ptr m_pOptionsMgr; - const sal_uInt16 nWhichQuery; - const ScQueryParam theQueryData; - std::unique_ptr pOutItem; - ScViewData& rViewData; - ScDocument& rDoc; + const sal_uInt16 m_nWhichQuery; + const ScQueryParam m_theQueryData; + std::unique_ptr m_pOutItem; + ScViewData& m_rViewData; + ScDocument& m_rDoc; - bool bRefInputMode; + bool m_bRefInputMode; formula::RefEdit* m_pRefInputEdit; diff --git a/sc/source/ui/inc/foptmgr.hxx b/sc/source/ui/inc/foptmgr.hxx index c5e108eb9828..3eea33060c3c 100644 --- a/sc/source/ui/inc/foptmgr.hxx +++ b/sc/source/ui/inc/foptmgr.hxx @@ -19,8 +19,9 @@ #pragma once +#include #include -#include +#include namespace formula { diff --git a/sc/source/ui/inc/gototabdlg.hxx b/sc/source/ui/inc/gototabdlg.hxx index c03485c38ffd..7c878b204b73 100644 --- a/sc/source/ui/inc/gototabdlg.hxx +++ b/sc/source/ui/inc/gototabdlg.hxx @@ -12,8 +12,9 @@ #include #include +#include #include -#include +#include class ScGoToTabDlg : public weld::GenericDialogController { @@ -26,7 +27,7 @@ private: std::unique_ptr m_xLb; DECL_LINK(DblClkHdl, const weld::TreeIter&, bool); - DECL_LINK(FindNameHdl, weld::Entry&, void); + DECL_LINK(FindNameHdl, weld::TextWidget&, void); public: ScGoToTabDlg(weld::Window* pParent); diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx index 76d4e7ae813d..371973ec5c5a 100644 --- a/sc/source/ui/inc/gridwin.hxx +++ b/sc/source/ui/inc/gridwin.hxx @@ -214,7 +214,8 @@ class SAL_DLLPUBLIC_RTTI ScGridWindow : public vcl::DocWindow, public DropTarget ScAddress aAutoMarkPos; ScAddress aListValPos; - Point aDrawSelectionPos; + // The position of the mouse when the left button was pressed + Point aDrawMouseDownPos; tools::Rectangle aInvertRect; diff --git a/sc/source/ui/inc/groupdlg.hxx b/sc/source/ui/inc/groupdlg.hxx index 5e974e998877..18ba90d8b47e 100644 --- a/sc/source/ui/inc/groupdlg.hxx +++ b/sc/source/ui/inc/groupdlg.hxx @@ -20,7 +20,8 @@ #pragma once #include -#include +#include +#include class ScGroupDlg : public weld::GenericDialogController { diff --git a/sc/source/ui/inc/hdrcont.hxx b/sc/source/ui/inc/hdrcont.hxx index 06b7f67678b8..5fed6c190a8e 100644 --- a/sc/source/ui/inc/hdrcont.hxx +++ b/sc/source/ui/inc/hdrcont.hxx @@ -46,6 +46,8 @@ private: tools::Long nWidth; tools::Long nSmallWidth; + tools::Long nMedWidth; + tools::Long nLargeWidth; tools::Long nBigWidth; SCCOLROW nSize; @@ -126,6 +128,8 @@ public: tools::Long GetWidth() const { return nWidth; } tools::Long GetSmallWidth() const { return nSmallWidth; } + tools::Long GetMedWidth() const { return nMedWidth; } + tools::Long GetLargeWidth() const { return nLargeWidth; } tools::Long GetBigWidth() const { return nBigWidth; } void SetWidth( tools::Long nNew ); void GetMarkRange(SCCOLROW& rStart, SCCOLROW& rEnd) const; diff --git a/sc/source/ui/inc/highred.hxx b/sc/source/ui/inc/highred.hxx index cfb706a8ec1d..4396f90aef85 100644 --- a/sc/source/ui/inc/highred.hxx +++ b/sc/source/ui/inc/highred.hxx @@ -21,9 +21,11 @@ #include "anyrefdg.hxx" -#include #include +#include +#include + class ScViewData; class ScDocument; diff --git a/sc/source/ui/inc/imoptdlg.hxx b/sc/source/ui/inc/imoptdlg.hxx index 91bd9e460ae0..cca5e0c008aa 100644 --- a/sc/source/ui/inc/imoptdlg.hxx +++ b/sc/source/ui/inc/imoptdlg.hxx @@ -22,6 +22,7 @@ #include #include #include +#include class SC_DLLPUBLIC ScImportOptions { @@ -32,7 +33,8 @@ public: : nFieldSepCode(nFieldSep), nTextSepCode(nTextSep), bFixedWidth(false), bSaveAsShown(false), bQuoteAllText(false), bSaveNumberAsSuch(true), bSaveFormulas(false), bRemoveSpace(false), - bEvaluateFormulas(true), bIncludeBOM(false), nSheetToExport(0) + bEvaluateFormulas(true), bIncludeBOM(false), nEndianness(SvStreamEndian::LITTLE), + nSheetToExport(0) { SetTextEncoding( nEnc ); } ScImportOptions& operator=( const ScImportOptions& rCpy ) = default; @@ -44,7 +46,7 @@ public: sal_Unicode nFieldSepCode; sal_Unicode nTextSepCode; OUString aStrFont; - rtl_TextEncoding eCharSet; + rtl_TextEncoding eEncoding; bool bFixedWidth; bool bSaveAsShown; bool bQuoteAllText; @@ -53,6 +55,7 @@ public: bool bRemoveSpace; bool bEvaluateFormulas; bool bIncludeBOM; + SvStreamEndian nEndianness; // "0" for 'current sheet', "-1" for all sheets (each to a separate file), // or 1-based specific sheet number (to a separate file). sal_Int32 nSheetToExport; diff --git a/sc/source/ui/inc/impex.hxx b/sc/source/ui/inc/impex.hxx index ecc984f00c2e..20535b1df93f 100644 --- a/sc/source/ui/inc/impex.hxx +++ b/sc/source/ui/inc/impex.hxx @@ -72,6 +72,7 @@ class SAL_DLLPUBLIC_RTTI ScImportExport // In this case we cannot use the insert optimization, but we // do not need to broadcast after the import. bool mbIncludeBOM; // Whether to include a byte-order-mark in the output. + SvStreamEndian mnEndianness; // Whether it's BIG or LITTLE endian ScExportTextOptions mExportTextOptions; std::unique_ptr pExtOptions; // extended options @@ -156,6 +157,7 @@ public: void SetExportTextOptions( const ScExportTextOptions& options ) { mExportTextOptions = options; } bool GetIncludeBOM() const { return mbIncludeBOM; } + SvStreamEndian GetEndianness() const { return mnEndianness; } }; // Helper class for importing clipboard strings as streams. diff --git a/sc/source/ui/inc/inputhdl.hxx b/sc/source/ui/inc/inputhdl.hxx index f70b053cbe01..e30f2c683f64 100644 --- a/sc/source/ui/inc/inputhdl.hxx +++ b/sc/source/ui/inc/inputhdl.hxx @@ -30,6 +30,7 @@ #include #include #include "viewdata.hxx" +#include #include #include @@ -40,6 +41,7 @@ class ScTabViewShell; class ScInputWindow; class ScPatternAttr; class ScEditEngineDefaulter; +struct PasteOrDropInfos; class EditView; class EditTextObject; class ScInputHdlState; @@ -86,7 +88,7 @@ private: sal_Unicode nCellPercentFormatDecSep; // 0:= no percent format, else which decimal separator - sal_uInt16 nAutoPar; // autom.parentheses than can be overwritten + sal_uInt16 nAutoPar; // automatic parentheses that can be overwritten ScAddress aCursorPos; ScInputMode eMode; @@ -118,7 +120,7 @@ private: ScTabViewShell* pRefViewSh; ScTabViewShell* pActiveViewSh; - const ScPatternAttr* pLastPattern; + CellAttributeHolder maLastPattern; std::unique_ptr pEditDefaults; @@ -176,6 +178,7 @@ private: DECL_LINK( ModifyHdl, LinkParamNone*, void ); DECL_LINK( ShowHideTipVisibleParentListener, VclWindowEvent&, void ); DECL_LINK( ShowHideTipVisibleSecParentListener, VclWindowEvent&, void ); + DECL_LINK( EndPasteOrDropHdl, PasteOrDropInfos&, void ); public: ScInputHandler(const ScInputHandler&) = delete; diff --git a/sc/source/ui/inc/inputwin.hxx b/sc/source/ui/inc/inputwin.hxx index 81428454752c..b9d4a77cc8c1 100644 --- a/sc/source/ui/inc/inputwin.hxx +++ b/sc/source/ui/inc/inputwin.hxx @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -173,7 +175,7 @@ private: std::set aRangeNames; public: - ScPosWnd(vcl::Window* pParent, ScTabViewShell* pViewSh); + ScPosWnd(vcl::Window* pParent); virtual ~ScPosWnd() override; virtual void dispose() override; @@ -360,10 +362,8 @@ private: class ScInputWindowWrapper : public SfxChildWindow { public: - ScInputWindowWrapper( vcl::Window* pParent, - sal_uInt16 nId, - SfxBindings* pBindings, - SfxChildWinInfo* pInfo ); + ScInputWindowWrapper(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); SFX_DECL_CHILDWINDOW_WITHID(ScInputWindowWrapper); }; diff --git a/sc/source/ui/inc/inscldlg.hxx b/sc/source/ui/inc/inscldlg.hxx index 3868af9e698c..9a7407e6306a 100644 --- a/sc/source/ui/inc/inscldlg.hxx +++ b/sc/source/ui/inc/inscldlg.hxx @@ -20,8 +20,8 @@ #pragma once #include +#include #include -#include #include #include "viewdata.hxx" diff --git a/sc/source/ui/inc/inscodlg.hxx b/sc/source/ui/inc/inscodlg.hxx index e8c06417b9f6..bfe9800166e7 100644 --- a/sc/source/ui/inc/inscodlg.hxx +++ b/sc/source/ui/inc/inscodlg.hxx @@ -19,8 +19,12 @@ #pragma once +#include +#include #include -#include +#include +#include + #include #include "scui_def.hxx" diff --git a/sc/source/ui/inc/instbdlg.hxx b/sc/source/ui/inc/instbdlg.hxx index 1f1414703791..5976ff796559 100644 --- a/sc/source/ui/inc/instbdlg.hxx +++ b/sc/source/ui/inc/instbdlg.hxx @@ -21,11 +21,15 @@ #include #include +#include +#include #include #include +#include +#include #include #include -#include + #include class ScViewData; diff --git a/sc/source/ui/inc/lbseldlg.hxx b/sc/source/ui/inc/lbseldlg.hxx index d16035006f8e..a66084ad79a1 100644 --- a/sc/source/ui/inc/lbseldlg.hxx +++ b/sc/source/ui/inc/lbseldlg.hxx @@ -21,7 +21,7 @@ #include #include -#include +#include class ScSelEntryDlg : public weld::GenericDialogController { diff --git a/sc/source/ui/inc/linkarea.hxx b/sc/source/ui/inc/linkarea.hxx index 1fe8bda26642..4070312d5f70 100644 --- a/sc/source/ui/inc/linkarea.hxx +++ b/sc/source/ui/inc/linkarea.hxx @@ -20,10 +20,12 @@ #pragma once #include +#include +#include #include +#include #include #include -#include namespace sfx2 { class DocumentInserter; } namespace sfx2 { class FileDialogHelper; } diff --git a/sc/source/ui/inc/mergecellsdialog.hxx b/sc/source/ui/inc/mergecellsdialog.hxx index aaf636a9fbba..38717a423dbb 100644 --- a/sc/source/ui/inc/mergecellsdialog.hxx +++ b/sc/source/ui/inc/mergecellsdialog.hxx @@ -11,7 +11,8 @@ #pragma once #include -#include +#include +#include enum ScMergeCellsOption { diff --git a/sc/source/ui/inc/mtrindlg.hxx b/sc/source/ui/inc/mtrindlg.hxx index 559e138d4a7b..7d846c4a5f89 100644 --- a/sc/source/ui/inc/mtrindlg.hxx +++ b/sc/source/ui/inc/mtrindlg.hxx @@ -19,9 +19,10 @@ #pragma once +#include #include #include -#include +#include class ScMetricInputDlg : public weld::GenericDialogController { diff --git a/sc/source/ui/inc/mvtabdlg.hxx b/sc/source/ui/inc/mvtabdlg.hxx index 5529a1fda3c4..bfcd5ec4bfd4 100644 --- a/sc/source/ui/inc/mvtabdlg.hxx +++ b/sc/source/ui/inc/mvtabdlg.hxx @@ -20,11 +20,15 @@ #pragma once #include + +#include #include #include #include +#include +#include #include -#include +#include class ScDocument; @@ -82,7 +86,7 @@ private: DECL_LINK(OkHdl, weld::Button&, void); DECL_LINK(SelHdl, weld::ComboBox&, void); DECL_LINK(CheckBtnHdl, weld::Toggleable&, void); - DECL_LINK(CheckNameHdl, weld::Entry&, void); + DECL_LINK(CheckNameHdl, weld::TextWidget&, void); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/namecrea.hxx b/sc/source/ui/inc/namecrea.hxx index 5a00897040f8..bba3e55c2558 100644 --- a/sc/source/ui/inc/namecrea.hxx +++ b/sc/source/ui/inc/namecrea.hxx @@ -19,8 +19,10 @@ #pragma once +#include #include -#include +#include + #include "scui_def.hxx" class ScNameCreateDlg final : public weld::GenericDialogController diff --git a/sc/source/ui/inc/namedefdlg.hxx b/sc/source/ui/inc/namedefdlg.hxx index 71867f283e9b..4adeafe5bdd8 100644 --- a/sc/source/ui/inc/namedefdlg.hxx +++ b/sc/source/ui/inc/namedefdlg.hxx @@ -11,7 +11,11 @@ #include "anyrefdg.hxx" +#include +#include #include +#include +#include #include @@ -67,7 +71,7 @@ private: DECL_LINK(CancelBtnHdl, weld::Button&, void); DECL_LINK(AddBtnHdl, weld::Button&, void); - DECL_LINK(NameModifyHdl, weld::Entry&, void); + DECL_LINK(NameModifyHdl, weld::TextWidget&, void); DECL_LINK(AssignGetFocusHdl, formula::RefEdit&, void); DECL_LINK(EdModifyCheckBoxHdl, weld::Toggleable&, void); DECL_LINK(RefEdModifyHdl, formula::RefEdit&, void); diff --git a/sc/source/ui/inc/namedlg.hxx b/sc/source/ui/inc/namedlg.hxx index d6544f6e2c6c..2e97a8d2dfa7 100644 --- a/sc/source/ui/inc/namedlg.hxx +++ b/sc/source/ui/inc/namedlg.hxx @@ -22,6 +22,11 @@ #include "anyrefdg.hxx" #include "namemgrtable.hxx" +#include +#include +#include +#include + #include #include @@ -96,7 +101,7 @@ private: DECL_LINK(CancelBtnHdl, weld::Button&, void); DECL_LINK(AddBtnHdl, weld::Button&, void); DECL_LINK(RemoveBtnHdl, weld::Button&, void); - DECL_LINK(EdModifyHdl, weld::Entry&, void); + DECL_LINK(EdModifyHdl, weld::TextWidget&, void); DECL_LINK(RefEdModifyHdl, formula::RefEdit&, void); DECL_LINK(EdModifyCheckBoxHdl, weld::Toggleable&, void); DECL_LINK(AssignGetFocusHdl, formula::RefEdit&, void); diff --git a/sc/source/ui/inc/namemgrtable.hxx b/sc/source/ui/inc/namemgrtable.hxx index cc256b862a24..d830223b554f 100644 --- a/sc/source/ui/inc/namemgrtable.hxx +++ b/sc/source/ui/inc/namemgrtable.hxx @@ -10,7 +10,6 @@ #pragma once #include -#include #include diff --git a/sc/source/ui/inc/namepast.hxx b/sc/source/ui/inc/namepast.hxx index 66c77c5ef465..dd17e697a0dc 100644 --- a/sc/source/ui/inc/namepast.hxx +++ b/sc/source/ui/inc/namepast.hxx @@ -19,8 +19,10 @@ #pragma once +#include #include -#include +#include + #include "namemgrtable.hxx" #include #include diff --git a/sc/source/ui/inc/navipi.hxx b/sc/source/ui/inc/navipi.hxx index 54862f488019..36cb28f8d052 100644 --- a/sc/source/ui/inc/navipi.hxx +++ b/sc/source/ui/inc/navipi.hxx @@ -96,7 +96,7 @@ friend class ScTabViewShell; private: static constexpr int CTRL_ITEMS = 4; - SfxBindings& rBindings; // must be first member + SfxBindings& m_rBindings; // must be first member std::unique_ptr m_xEdCol; std::unique_ptr m_xEdRow; @@ -110,20 +110,20 @@ private: VclPtr m_xNavigatorDlg; - Size aExpandedSize; - Idle aContentIdle; + Size m_aExpandedSize; + Idle m_aContentIdle; - OUString aStrActive; - OUString aStrNotActive; - OUString aStrActiveWin; + OUString m_aStrActive; + OUString m_aStrNotActive; + OUString m_aStrActiveWin; std::optional moMarkArea; - NavListMode eListMode; - sal_uInt16 nDropMode; - SCCOL nCurCol; - SCROW nCurRow; - SCTAB nCurTab; + NavListMode m_eListMode; + sal_uInt16 m_nDropMode; + SCCOL m_nCurCol; + SCROW m_nCurRow; + SCTAB m_nCurTab; std::array,CTRL_ITEMS> mvBoundItems; @@ -165,7 +165,7 @@ private: void ShowScenarios(); void SetDropMode(sal_uInt16 nNew); - sal_uInt16 GetDropMode() const { return nDropMode; } + sal_uInt16 GetDropMode() const { return m_nDropMode; } void MarkDataArea (); void UnmarkDataArea (); @@ -177,7 +177,7 @@ private: static void ReleaseFocus(); public: - ScNavigatorDlg(SfxBindings* pB, weld::Widget* pParent, SfxNavigator* pNavigatorDlg); + ScNavigatorDlg(SfxBindings& rBindings, weld::Widget* pParent, SfxNavigator* pNavigatorDlg); virtual weld::Window* GetFrameWeld() const override; virtual ~ScNavigatorDlg() override; @@ -188,8 +188,8 @@ public: class ScNavigatorWrapper final : public SfxNavigatorWrapper { public: - ScNavigatorWrapper(vcl::Window *pParent, sal_uInt16 nId, - SfxBindings* pBindings, SfxChildWinInfo* pInfo); + ScNavigatorWrapper(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); SFX_DECL_CHILDWINDOW(ScNavigatorWrapper); }; @@ -199,8 +199,8 @@ class ScNavigatorWin : public SfxNavigator private: std::unique_ptr m_xNavigator; public: - ScNavigatorWin(SfxBindings* _pBindings, SfxChildWindow* pMgr, - vcl::Window* pParent, SfxChildWinInfo* pInfo); + ScNavigatorWin(SfxBindings& rBindings, SfxChildWindow* pMgr, vcl::Window* pParent, + SfxChildWinInfo& rInfo); virtual void StateChanged(StateChangedType nStateChange) override; virtual void dispose() override { diff --git a/sc/source/ui/inc/operation/ApplyAttributesOperation.hxx b/sc/source/ui/inc/operation/ApplyAttributesOperation.hxx new file mode 100644 index 000000000000..fccbe59707b1 --- /dev/null +++ b/sc/source/ui/inc/operation/ApplyAttributesOperation.hxx @@ -0,0 +1,80 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include +#include + +class ScDocShell; +class ScMarkData; +class ScPatternAttr; +class ScDocFunc; + +namespace sc +{ +/** Operation which applies input attributes to marked cells or range. */ +class ApplyAttributesOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScMarkData const& mrMark; + ScPatternAttr const& mrPattern; + + bool runImplementation() override; + +public: + ApplyAttributesOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScMarkData& rMark, + const ScPatternAttr& rPattern, bool bApi); +}; + +/** Operation which applies input attributes to marked cells or range and remembers changed ranges. */ +class ApplyAttributesWithChangedRangeOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScMarkData const& mrMark; + ScPatternAttr const& mrPattern; + bool mbMultiMarked = false; + sal_uInt16 mnExtFlags; + ScRangeList maChangeRanges; + + bool runImplementation() override; + +public: + ApplyAttributesWithChangedRangeOperation(ScDocShell& rDocShell, const ScMarkData& rMark, + bool bMultiMarked, const ScPatternAttr& rPattern, + sal_uInt16 nExtFlags, bool bApi); + ScRangeList const& getChangedRangeList() { return maChangeRanges; } +}; + +/** Operation which applies input attributes to content to a cell. */ +class ApplyAttributesToCellOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScAddress const& mrPosition; + ScPatternAttr const& mrPattern; + sal_uInt16 mnExtFlags; + ScRangeList maChangeRanges; + + bool runImplementation() override; + +public: + ApplyAttributesToCellOperation(ScDocShell& rDocShell, ScAddress const& rPosition, + const ScPatternAttr& rPattern, sal_uInt16 nExtFlags, bool bApi); + ScRangeList const& getChangedRangeList() { return maChangeRanges; } +}; + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/AutoFormatOperation.hxx b/sc/source/ui/inc/operation/AutoFormatOperation.hxx new file mode 100644 index 000000000000..34cc0cfaf17f --- /dev/null +++ b/sc/source/ui/inc/operation/AutoFormatOperation.hxx @@ -0,0 +1,41 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocFunc; +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which applies an autoformat table style to a selected range. */ +class AutoFormatOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScRange maRange; + ScMarkData const* mpTabMark; + sal_uInt16 mnFormatNo; + + bool canRunTheOperation() const override; + bool runImplementation() override; + +public: + AutoFormatOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScRange& rRange, + const ScMarkData* pTabMark, sal_uInt16 nFormatNo, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/ChangeIndentOperation.hxx b/sc/source/ui/inc/operation/ChangeIndentOperation.hxx new file mode 100644 index 000000000000..8defae709dd4 --- /dev/null +++ b/sc/source/ui/inc/operation/ChangeIndentOperation.hxx @@ -0,0 +1,35 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" + +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which changes the indent of marked cells. */ +class ChangeIndentOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScMarkData const& mrMark; + bool mbIncrement; + + bool runImplementation() override; + +public: + ChangeIndentOperation(ScDocShell& rDocShell, const ScMarkData& rMark, bool bIncrement, + bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/ChangeSparklineGroupAttributesOperation.hxx b/sc/source/ui/inc/operation/ChangeSparklineGroupAttributesOperation.hxx new file mode 100644 index 000000000000..cff876705a77 --- /dev/null +++ b/sc/source/ui/inc/operation/ChangeSparklineGroupAttributesOperation.hxx @@ -0,0 +1,39 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; + +namespace sc +{ +class SparklineGroup; + +/** Changes the sparkline's group attributes to the input one. */ +class ChangeSparklineGroupAttributesOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + std::shared_ptr mpExistingSparklineGroup; + SparklineAttributes maNewAttributes; + + bool runImplementation() override; + +public: + ChangeSparklineGroupAttributesOperation( + ScDocShell& rDocShell, std::shared_ptr const& pExistingSparklineGroup, + SparklineAttributes const& rNewAttributes); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/ChangeSparklineOperation.hxx b/sc/source/ui/inc/operation/ChangeSparklineOperation.hxx new file mode 100644 index 000000000000..460eae9587a3 --- /dev/null +++ b/sc/source/ui/inc/operation/ChangeSparklineOperation.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include +#include + +class ScDocShell; + +namespace sc +{ +class Sparkline; + +/** Changes the sparkline's input data range. */ +class ChangeSparklineOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + std::shared_ptr mpSparkline; + SCTAB mnTab; + ScRangeList maDataRange; + + bool runImplementation() override; + +public: + ChangeSparklineOperation(ScDocShell& rDocShell, std::shared_ptr const& rpSparkline, + SCTAB nTab, ScRangeList const& rDataRange); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/ClearItemsOperation.hxx b/sc/source/ui/inc/operation/ClearItemsOperation.hxx new file mode 100644 index 000000000000..c872ff221803 --- /dev/null +++ b/sc/source/ui/inc/operation/ClearItemsOperation.hxx @@ -0,0 +1,36 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which clears specific items from one or multiple marked cells. */ +class ClearItemsOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScMarkData const& mrMark; + const sal_uInt16* mpWhich; + + bool runImplementation() override; + +public: + ClearItemsOperation(ScDocShell& rDocShell, const ScMarkData& rMark, const sal_uInt16* pWhich, + bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/ConvertFormulaToValueOperation.hxx b/sc/source/ui/inc/operation/ConvertFormulaToValueOperation.hxx new file mode 100644 index 000000000000..465ef567d76f --- /dev/null +++ b/sc/source/ui/inc/operation/ConvertFormulaToValueOperation.hxx @@ -0,0 +1,33 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +class ScDocShell; + +namespace sc +{ +/** Operation which converts formula cells to their computed values. */ +class ConvertFormulaToValueOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScRange maRange; + + bool runImplementation() override; + +public: + ConvertFormulaToValueOperation(ScDocShell& rDocShell, const ScRange& rRange, bool bInteraction); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/CreatePivotTableOperation.hxx b/sc/source/ui/inc/operation/CreatePivotTableOperation.hxx new file mode 100644 index 000000000000..3d909e235c1e --- /dev/null +++ b/sc/source/ui/inc/operation/CreatePivotTableOperation.hxx @@ -0,0 +1,32 @@ +/* -*- 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/. + */ + +#pragma once + +#include "PivotTableOperation.hxx" + +class ScDPObject; + +namespace sc +{ +/** Creates a pivot table from the input object. */ +class CreatePivotTableOperation : public PivotTableOperation +{ +private: + ScDPObject const& mrDPObject; + + bool runImplementation() override; + +public: + CreatePivotTableOperation(ScDocShell& rDocShell, ScDPObject const& rDPObject, bool bRecord, + bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/DeleteCellOperation.hxx b/sc/source/ui/inc/operation/DeleteCellOperation.hxx new file mode 100644 index 000000000000..b7a7899fc99f --- /dev/null +++ b/sc/source/ui/inc/operation/DeleteCellOperation.hxx @@ -0,0 +1,42 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +class ScDocShell; +class ScMarkData; +class ScDocFunc; +class ScAddress; +enum class InsertDeleteFlags : sal_Int32; + +namespace sc +{ +/** Operation which deletes content of one cells. */ +class DeleteCellOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScAddress const& mrPosition; + ScMarkData const& mrMark; + InsertDeleteFlags mnFlags; + + bool runImplementation() override; + +public: + DeleteCellOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScAddress& rPos, + const ScMarkData& rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi); +}; + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/DeleteCellsOperation.hxx b/sc/source/ui/inc/operation/DeleteCellsOperation.hxx new file mode 100644 index 000000000000..5ae9ca28a308 --- /dev/null +++ b/sc/source/ui/inc/operation/DeleteCellsOperation.hxx @@ -0,0 +1,42 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which deletes cells, rows, or columns. */ +class SC_DLLPUBLIC DeleteCellsOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScRange maRange; + ScMarkData const* mpTabMark; + DelCellCmd meCmd; + + bool canRunTheOperation() const override; + bool runImplementation() override; + + static OperationType toOperationType(DelCellCmd eCmd); + +public: + DeleteCellsOperation(ScDocShell& rDocShell, ScRange const& rRange, ScMarkData const* pTabMark, + DelCellCmd eCmd, bool bApi); +}; + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/DeleteContentOperation.hxx b/sc/source/ui/inc/operation/DeleteContentOperation.hxx new file mode 100644 index 000000000000..fb245363f0dc --- /dev/null +++ b/sc/source/ui/inc/operation/DeleteContentOperation.hxx @@ -0,0 +1,39 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +class ScDocShell; +class ScMarkData; +class ScDocFunc; +enum class InsertDeleteFlags : sal_Int32; + +namespace sc +{ +/** Operation which deletes content of one or multiple marked cells. */ +class DeleteContentOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScMarkData const& mrMark; + InsertDeleteFlags mnFlags; + + bool runImplementation() override; + +public: + DeleteContentOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScMarkData& rMark, + InsertDeleteFlags nFlags, bool bRecord, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/DeleteSparklineGroupOperation.hxx b/sc/source/ui/inc/operation/DeleteSparklineGroupOperation.hxx new file mode 100644 index 000000000000..066261f1600b --- /dev/null +++ b/sc/source/ui/inc/operation/DeleteSparklineGroupOperation.hxx @@ -0,0 +1,39 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; + +namespace sc +{ +class SparklineGroup; + +/** Deletes the whole sparkline group. */ +class DeleteSparklineGroupOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + std::shared_ptr mpSparklineGroup; + SCTAB mnTab; + + bool runImplementation() override; + +public: + DeleteSparklineGroupOperation(ScDocShell& rDocShell, + std::shared_ptr const& pSparklineGroup, + SCTAB nTab); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/DeleteSparklineOperation.hxx b/sc/source/ui/inc/operation/DeleteSparklineOperation.hxx new file mode 100644 index 000000000000..52135958ba3b --- /dev/null +++ b/sc/source/ui/inc/operation/DeleteSparklineOperation.hxx @@ -0,0 +1,33 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +class ScDocShell; + +namespace sc +{ +/** Deletes one sparkline */ +class DeleteSparklineOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScAddress maAddress; + + bool runImplementation() override; + +public: + DeleteSparklineOperation(ScDocShell& rDocShell, ScAddress const& rAddress); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/EnterMatrixOperation.hxx b/sc/source/ui/inc/operation/EnterMatrixOperation.hxx new file mode 100644 index 000000000000..fb2eac7594fc --- /dev/null +++ b/sc/source/ui/inc/operation/EnterMatrixOperation.hxx @@ -0,0 +1,47 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScMarkData; +class ScTokenArray; + +namespace sc +{ +/** Operation which enters an array (matrix/CSE) formula into a range. */ +class EnterMatrixOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScRange maRange; + ScMarkData const* mpTabMark; + ScTokenArray const* mpTokenArray; + OUString maString; + bool mbEnglish; + OUString maFormulaNmsp; + formula::FormulaGrammar::Grammar meGrammar; + bool mbDynamicArrayMaster; + + bool runImplementation() override; + +public: + EnterMatrixOperation(ScDocShell& rDocShell, const ScRange& rRange, const ScMarkData* pTabMark, + const ScTokenArray* pTokenArray, const OUString& rString, bool bApi, + bool bEnglish, const OUString& rFormulaNmsp, + formula::FormulaGrammar::Grammar eGrammar, + bool bDynamicArrayMaster = false); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/FillAutoOperation.hxx b/sc/source/ui/inc/operation/FillAutoOperation.hxx new file mode 100644 index 000000000000..9d26e23b4870 --- /dev/null +++ b/sc/source/ui/inc/operation/FillAutoOperation.hxx @@ -0,0 +1,48 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include +#include + +class ScDocFunc; +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which performs smart autofill, extending a detected pattern into adjacent cells. */ +class FillAutoOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScRange& mrRange; + ScMarkData const* mpTabMark; + FillDir meDir; + FillCmd meCmd; + FillDateCmd meDateCmd; + sal_uLong mnCount; + double mfStep; + double mfMax; + + bool canRunTheOperation() const override; + bool runImplementation() override; + +public: + FillAutoOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, ScRange& rRange, + const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, + sal_uLong nCount, double fStep, double fMax, bool bRecord, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/FillSeriesOperation.hxx b/sc/source/ui/inc/operation/FillSeriesOperation.hxx new file mode 100644 index 000000000000..8e52c41da54e --- /dev/null +++ b/sc/source/ui/inc/operation/FillSeriesOperation.hxx @@ -0,0 +1,47 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocFunc; +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which fills a range with a numeric or date series. */ +class FillSeriesOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScRange maRange; + ScMarkData const* mpTabMark; + FillDir meDir; + FillCmd meCmd; + FillDateCmd meDateCmd; + double mfStart; + double mfStep; + double mfMax; + + bool canRunTheOperation() const override; + bool runImplementation() override; + +public: + FillSeriesOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScRange& rRange, + const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, + FillDateCmd eDateCmd, double fStart, double fStep, double fMax, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/FillSimpleOperation.hxx b/sc/source/ui/inc/operation/FillSimpleOperation.hxx new file mode 100644 index 000000000000..11b216945707 --- /dev/null +++ b/sc/source/ui/inc/operation/FillSimpleOperation.hxx @@ -0,0 +1,41 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocFunc; +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which fills cells by copying data from an adjacent source row or column. */ +class FillSimpleOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScRange maRange; + ScMarkData const* mpTabMark; + FillDir meDir; + + bool canRunTheOperation() const override; + bool runImplementation() override; + +public: + FillSimpleOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScRange& rRange, + const ScMarkData* pTabMark, FillDir eDir, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/GroupSparklinesOperation.hxx b/sc/source/ui/inc/operation/GroupSparklinesOperation.hxx new file mode 100644 index 000000000000..505f300c9d72 --- /dev/null +++ b/sc/source/ui/inc/operation/GroupSparklinesOperation.hxx @@ -0,0 +1,38 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; + +namespace sc +{ +class SparklineGroup; + +/** Groups the sparklines in the input range together. */ +class GroupSparklinesOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScRange maRange; + std::shared_ptr mpGroup; + + bool runImplementation() override; + +public: + GroupSparklinesOperation(ScDocShell& rDocShell, ScRange const& rRange, + std::shared_ptr const& rpGroup); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/InsertCellsOperation.hxx b/sc/source/ui/inc/operation/InsertCellsOperation.hxx new file mode 100644 index 000000000000..4c942ace4913 --- /dev/null +++ b/sc/source/ui/inc/operation/InsertCellsOperation.hxx @@ -0,0 +1,45 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which inserts cells, rows, or columns. */ +class SC_DLLPUBLIC InsertCellsOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScRange maRange; + ScMarkData const* mpTabMark; + InsCellCmd meCmd; + bool mbPartOfPaste; + size_t mnInsertCount; + + bool canRunTheOperation() const override; + bool runImplementation() override; + + static OperationType toOperationType(InsCellCmd eCmd); + +public: + InsertCellsOperation(ScDocShell& rDocShell, ScRange const& rRange, ScMarkData const* pTabMark, + InsCellCmd eCmd, bool bRecord, bool bApi, bool bPartOfPaste, + size_t nInsertCount); +}; + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/InsertNameListOperation.hxx b/sc/source/ui/inc/operation/InsertNameListOperation.hxx new file mode 100644 index 000000000000..0e67d26dee1b --- /dev/null +++ b/sc/source/ui/inc/operation/InsertNameListOperation.hxx @@ -0,0 +1,33 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +class ScDocShell; + +namespace sc +{ +/** Inserts a list of defined named ranges into the spreadsheet at the given position. */ +class InsertNameListOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScAddress maStartPos; + + bool runImplementation() override; + +public: + InsertNameListOperation(ScDocShell& rDocShell, const ScAddress& rStartPos, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/InsertSheetViewOperation.hxx b/sc/source/ui/inc/operation/InsertSheetViewOperation.hxx new file mode 100644 index 000000000000..f7143f6dd5e6 --- /dev/null +++ b/sc/source/ui/inc/operation/InsertSheetViewOperation.hxx @@ -0,0 +1,39 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; + +namespace sc +{ +/** Operation which inserts a new sheet view for a given tab. */ +class InsertSheetViewOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + SCTAB mnTab; + SheetViewID mnSheetViewID = InvalidSheetViewID; + SCTAB mnSheetViewTab = -1; + + bool runImplementation() override; + +public: + InsertSheetViewOperation(ScDocShell& rDocShell, SCTAB nTab, bool bRecord); + + SheetViewID getSheetViewID() const { return mnSheetViewID; } + SCTAB getSheetViewTab() const { return mnSheetViewTab; } +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/InsertSparklinesOperation.hxx b/sc/source/ui/inc/operation/InsertSparklinesOperation.hxx new file mode 100644 index 000000000000..0e897d2f7a43 --- /dev/null +++ b/sc/source/ui/inc/operation/InsertSparklinesOperation.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; + +namespace sc +{ +class SparklineGroup; + +/** Inserts new sparklines at the input range, and add them into the input group. */ +class InsertSparklinesOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScRange maDataRange; + ScRange maSparklineRange; + std::shared_ptr mpSparklineGroup; + + bool runImplementation() override; + +public: + InsertSparklinesOperation(ScDocShell& rDocShell, ScRange const& rDataRange, + ScRange const& rSparklineRange, + std::shared_ptr const& pSparklineGroup); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/InsertThreadedCommentOperation.hxx b/sc/source/ui/inc/operation/InsertThreadedCommentOperation.hxx new file mode 100644 index 000000000000..347d8926799d --- /dev/null +++ b/sc/source/ui/inc/operation/InsertThreadedCommentOperation.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +#include + +class ScDocShell; + +namespace sc +{ +/** Inserts a threaded comment at the input address, registering an undo action + and setting the document-modified flag. */ +class InsertThreadedCommentOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScAddress maPos; + OUString maText; + std::optional moAuthor; + + bool runImplementation() override; + +public: + InsertThreadedCommentOperation(ScDocShell& rDocShell, const ScAddress& rPos, + const OUString& rText, const OUString* pAuthor, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/ui/inc/operation/MergeCellsOperation.hxx b/sc/source/ui/inc/operation/MergeCellsOperation.hxx new file mode 100644 index 000000000000..fbaeeb0ea2e0 --- /dev/null +++ b/sc/source/ui/inc/operation/MergeCellsOperation.hxx @@ -0,0 +1,36 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +class ScDocShell; + +namespace sc +{ +/** Merges a range of cells into one. */ +class MergeCellsOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScCellMergeOption maOption; + bool mbContents; + bool mbEmptyMergedCells; + + bool runImplementation() override; + +public: + MergeCellsOperation(ScDocShell& rDocShell, const ScCellMergeOption& rOption, bool bContents, + bool bRecord, bool bApi, bool bEmptyMergedCells = false); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/MoveBlockOperation.hxx b/sc/source/ui/inc/operation/MoveBlockOperation.hxx new file mode 100644 index 000000000000..7c5551acb6f9 --- /dev/null +++ b/sc/source/ui/inc/operation/MoveBlockOperation.hxx @@ -0,0 +1,38 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +class ScDocShell; + +namespace sc +{ +/** Moves or copies a block of cells from a source range to a destination position. */ +class MoveBlockOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScRange maSource; + ScAddress maDestPos; + bool mbCut; + bool mbPaint; + + bool canRunTheOperation() const override; + bool runImplementation() override; + +public: + MoveBlockOperation(ScDocShell& rDocShell, const ScRange& rSource, const ScAddress& rDestPos, + bool bCut, bool bRecord, bool bPaint, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/MultipleOpsOperation.hxx b/sc/source/ui/inc/operation/MultipleOpsOperation.hxx new file mode 100644 index 000000000000..0b878987c88d --- /dev/null +++ b/sc/source/ui/inc/operation/MultipleOpsOperation.hxx @@ -0,0 +1,39 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which fills a range with formulas substituting varying input values (Multiple Operations). */ +class MultipleOpsOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScRange maRange; + ScMarkData const* mpTabMark; + ScTabOpParam maParam; + + ScRefAddress convertRefAddress(ScRefAddress const& rRefAddress); + bool runImplementation() override; + +public: + MultipleOpsOperation(ScDocShell& rDocShell, const ScRange& rRange, const ScMarkData* pTabMark, + const ScTabOpParam& rParam, bool bRecord, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/Operation.hxx b/sc/source/ui/inc/operation/Operation.hxx new file mode 100644 index 000000000000..51c851b764d2 --- /dev/null +++ b/sc/source/ui/inc/operation/Operation.hxx @@ -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/. + */ + +#pragma once + +#include +#include +#include + +class ScMarkData; +class ScAddress; +class ScRange; +class ScRangeList; +class ScViewData; +class ScPatternAttr; + +namespace sc +{ +class UndoSheetViewSortData; +/** Operation is one atomic coarse change to the document model that can be run from UI or API + * + * An operation is a minimal change that is undoable and redoable. + * It should provide and handle: + * - document modification flag + * - undo/redo if enabled + * - sheet protections + * - sheet view sync and if it can be performed + * - API / UI code paths + * - invalidation + * - logging + * - other common tasks + * + * Each operation should have an OperationType. + */ +class Operation +{ +protected: + OperationType meType = OperationType::Unknown; + bool mbApi : 1 = false; + bool mbRecord : 1 = false; + ScViewData* mpViewData; + + bool checkSheetViewProtection(); + + /** Convert a tab from a sheet view to the tab in the default view. */ + SCTAB convertTab(SCTAB nTab); + + /** Convert address from a sheet view to the address in default view, take sorting into account. */ + ScAddress convertAddress(ScAddress const& rAddress); + + /** Convert a range from a sheet view to the range in default view, take sorting into account. */ + ScRange convertRange(ScRange const& rRange); + + /** Convert a range list from a sheet view to the range list in default view, take sorting into account. */ + ScRangeList convertRangeList(ScRangeList const& rRangeList); + + /** Convert a mark from a sheet view to the mark in default view, take sorting into account. */ + ScMarkData convertMark(ScMarkData const& rMarkData); + + /** Synchronizes the sheet views and the default view */ + void syncSheetViews(UndoSheetViewSortData* pUndoSortData = nullptr); + + /** Propagates a single cell change to all sheet views. + * This uses a fast-path to sync by setting the values directly to the default view and all + * sheet views, but can fall back to the slow sync in certain situations.*/ + void syncCellToSheetViews(const ScAddress& rDefaultViewAddress, + UndoSheetViewSortData* pUndoSortData = nullptr); + + /** Propagates a single-cell pattern change to all sheet views. */ + void syncCellPatternToSheetViews(const ScAddress& rDefaultViewAddress, + const ScPatternAttr& rPattern); + + /** Propagates a multi-range pattern change to all sheet views. */ + void syncMarkPatternToSheetViews(const ScMarkData& rDefaultViewMark, + const ScPatternAttr& rPattern); + + /** Check if a range is on a sheet view tab and intersects with any autofilter */ + bool isInputOnSheetViewAutoFilter(ScRange const& rRange) const; + + /** Check if we can run the operation or not */ + virtual bool canRunTheOperation() const { return true; } + + /** Operation implementation */ + virtual bool runImplementation() = 0; + +public: + Operation(OperationType eType, bool bRecord, bool bApi); + + /** Run the operation */ + SC_DLLPUBLIC bool run(); +}; + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/OperationType.hxx b/sc/source/ui/inc/operation/OperationType.hxx new file mode 100644 index 000000000000..70fd0d4c2f21 --- /dev/null +++ b/sc/source/ui/inc/operation/OperationType.hxx @@ -0,0 +1,77 @@ +/* -*- 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 + +#pragma once + +namespace sc +{ +/** Operations that can be performed on a sheet. */ +enum class OperationType +{ + Unknown, + ApplyAttributes, + ApplyAttributesWithChangedRange, + ApplyAttributesToCell, + DeleteContent, + DeleteCell, + TransliterateText, + SetNormalString, + SetValue, + SetString, + SetTextEdit, + SetFormula, + SetNoteText, + ReplaceNoteText, + InsertThreadedComment, + InsertColumnsBefore, + InsertColumnsAfter, + InsertRowsBefore, + InsertRowsAfter, + InsertCellsDown, + InsertCellsRight, + DeleteColumns, + DeleteRows, + DeleteCellsLeft, + DeleteCellsUp, + MoveBlock, + ClearItems, + ChangeIndent, + AutoFormat, + EnterMatrix, + MultipleOps, + FillSimple, + FillSeries, + FillAuto, + MergeCells, + InsertNameList, + ConvertFormulaToValue, + Sort, + Query, + SubTotals, + PivotTableUpdate, + PivotTableReplace, + PivotTableRemove, + PivotTableCreate, + SparklineInsert, + SparklineDelete, + SparklineChange, + SparklineGroup, + SparklineUngroup, + SparklineGroupDelete, + SparklineGroupChange, + EnterData, + InsertSheetView, +}; + +std::string_view operationTypeString(OperationType eType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/PivotTableOperation.hxx b/sc/source/ui/inc/operation/PivotTableOperation.hxx new file mode 100644 index 000000000000..e9f9921159dc --- /dev/null +++ b/sc/source/ui/inc/operation/PivotTableOperation.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" + +class ScDocShell; +class ScDPObject; + +namespace sc +{ +/** Base class for pivot table operations, providing common members and utilities. */ +class PivotTableOperation : public Operation +{ +protected: + ScDocShell& mrDocShell; + + /** Convert the output and source ranges of a DPObject from sheet view to default view. + * + * If the input DP object is not on sheet view, do nothing. + */ + void convertDPObjectRanges(ScDPObject& rDPObject); + + /** Find the DPObject on the default view tab that corresponds to the given + * DPObject, which is on a sheet view tab. + */ + ScDPObject* findDefaultViewDPObject(ScDPObject const& rDPObject); + + PivotTableOperation(OperationType eType, ScDocShell& rDocShell, bool bRecord, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/PivotTableOperationCommon.hxx b/sc/source/ui/inc/operation/PivotTableOperationCommon.hxx new file mode 100644 index 000000000000..557615076c1f --- /dev/null +++ b/sc/source/ui/inc/operation/PivotTableOperationCommon.hxx @@ -0,0 +1,108 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sc::pivot +{ +/** Can the input range be edited. */ +inline bool isEditable(ScDocShell& rDocShell, const ScRangeList& rRanges, bool bApi, + sc::EditAction eAction = sc::EditAction::Unknown) +{ + ScDocument& rDoc = rDocShell.GetDocument(); + if (!rDocShell.IsEditable() || rDoc.GetChangeTrack()) + { + if (!bApi) + rDocShell.ErrorMessage(STR_PROTECTIONERR); + return false; + } + + for (size_t i = 0, n = rRanges.size(); i < n; ++i) + { + const ScRange& r = rRanges[i]; + ScEditableTester aTester = ScEditableTester::CreateAndTestRange(rDoc, r, eAction); + if (!aTester.IsEditable()) + { + if (!bApi) + rDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + } + + return true; +} + +/** Create undo and copy the data to the undo document. */ +inline void createUndoDoc(ScDocumentUniquePtr& pUndoDoc, ScDocument& rDocument, + const ScRange& rRange) +{ + SCTAB nTab = rRange.aStart.Tab(); + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDocument, nTab, nTab); + rDocument.CopyToDocument(rRange, InsertDeleteFlags::ALL, false, *pUndoDoc); +} + +inline bool checkNewOutputRange(ScDPObject& rDPObj, ScDocShell& rDocShell, ScRange& rNewOut, + bool bApi, sc::EditAction eAction = sc::EditAction::Unknown) +{ + ScDocument& rDoc = rDocShell.GetDocument(); + + bool bOverflow = false; + rNewOut = rDPObj.GetNewOutputRange(bOverflow); + + // Test for overlap with source data range. + // TODO: Check with other pivot tables as well. + const ScSheetSourceDesc* pSheetDesc = rDPObj.GetSheetDesc(); + if (pSheetDesc && pSheetDesc->GetSourceRange().Intersects(rNewOut)) + { + // New output range intersteps with the source data. Move it up to + // where the old range is and see if that works. + ScRange aOldRange = rDPObj.GetOutRange(); + SCROW nDiff = aOldRange.aStart.Row() - rNewOut.aStart.Row(); + rNewOut.aStart.SetRow(aOldRange.aStart.Row()); + rNewOut.aEnd.IncRow(nDiff); + if (!rDoc.ValidRow(rNewOut.aStart.Row()) || !rDoc.ValidRow(rNewOut.aEnd.Row())) + bOverflow = true; + } + + if (bOverflow) + { + if (!bApi) + rDocShell.ErrorMessage(STR_PIVOT_ERROR); + + return false; + } + + if (!rDoc.IsImportingXML()) + { + ScEditableTester aTester = ScEditableTester::CreateAndTestRange(rDoc, rNewOut, eAction); + if (!aTester.IsEditable()) + { + // destination area isn't editable + if (!bApi) + rDocShell.ErrorMessage(aTester.GetMessageId()); + + return false; + } + } + + return true; +} +} // end sc::pivot namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/QueryOperation.hxx b/sc/source/ui/inc/operation/QueryOperation.hxx new file mode 100644 index 000000000000..86027716cfa7 --- /dev/null +++ b/sc/source/ui/inc/operation/QueryOperation.hxx @@ -0,0 +1,39 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +struct ScQueryParam; +class ScRange; + +namespace sc +{ +/** Operation which filters/queries cells in a sheet. */ +class QueryOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + SCTAB mnTab; + ScQueryParam const& mrQueryParam; + ScRange const* mpAdvSource; + + bool runImplementation() override; + +public: + QueryOperation(ScDocShell& rDocShell, SCTAB nTab, ScQueryParam const& rQueryParam, + ScRange const* pAdvSource, bool bRecord, bool bApi); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/RemovePivotTableOperation.hxx b/sc/source/ui/inc/operation/RemovePivotTableOperation.hxx new file mode 100644 index 000000000000..24460c2a9d94 --- /dev/null +++ b/sc/source/ui/inc/operation/RemovePivotTableOperation.hxx @@ -0,0 +1,32 @@ +/* -*- 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/. + */ + +#pragma once + +#include "PivotTableOperation.hxx" + +class ScDPObject; + +namespace sc +{ +/** Removes the pivot table identified by the input object. */ +class RemovePivotTableOperation : public PivotTableOperation +{ +private: + ScDPObject const& mrDPObject; + + bool runImplementation() override; + +public: + RemovePivotTableOperation(ScDocShell& rDocShell, ScDPObject const& rDPObject, bool bRecord, + bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/ReplaceNoteTextOperation.hxx b/sc/source/ui/inc/operation/ReplaceNoteTextOperation.hxx new file mode 100644 index 000000000000..adaba733d195 --- /dev/null +++ b/sc/source/ui/inc/operation/ReplaceNoteTextOperation.hxx @@ -0,0 +1,41 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +#include + +class ScDocShell; + +namespace sc +{ +/** Sets or replaces the content of the note at the input address. */ +class ReplaceNoteTextOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScAddress maPos; + OUString maText; + std::optional moAuthor; + std::optional moDate; + + bool runImplementation() override; + +public: + ReplaceNoteTextOperation(ScDocShell& rDocShell, const ScAddress& rPos, + const OUString& rNoteText, const OUString* pAuthor, + const OUString* pDate, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/ReplacePivotTableOperation.hxx b/sc/source/ui/inc/operation/ReplacePivotTableOperation.hxx new file mode 100644 index 000000000000..25af6deb5dac --- /dev/null +++ b/sc/source/ui/inc/operation/ReplacePivotTableOperation.hxx @@ -0,0 +1,35 @@ +/* -*- 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/. + */ + +#pragma once + +#include "PivotTableOperation.hxx" + +class ScDPObject; + +namespace sc +{ +/** Replaces a pivot table's layout with settings from a different DPObject. */ +class SC_DLLPUBLIC ReplacePivotTableOperation : public PivotTableOperation +{ +private: + ScDPObject* mpDPObject; + ScDPObject const* mpNewDPObject; + bool mbAllowMove; + + bool runImplementation() override; + +public: + ReplacePivotTableOperation(ScDocShell& rDocShell, ScDPObject* pDPObject, + ScDPObject const* pNewDPObject, bool bRecord, bool bApi, + bool bAllowMove); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/SetEditTextOperation.hxx b/sc/source/ui/inc/operation/SetEditTextOperation.hxx new file mode 100644 index 000000000000..558771184af5 --- /dev/null +++ b/sc/source/ui/inc/operation/SetEditTextOperation.hxx @@ -0,0 +1,41 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScAddress; +class ScDocFunc; +class EditTextObject; + +namespace sc +{ +/** Operation which sets a text object to a cell. */ +class SetEditTextOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScAddress const& mrPosition; + EditTextObject const& mrEditObject; + + bool runImplementation() override; + +public: + SetEditTextOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScAddress& rPosition, + const EditTextObject& rEditObject, bool bApi); +}; + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/SetFormulaOperation.hxx b/sc/source/ui/inc/operation/SetFormulaOperation.hxx new file mode 100644 index 000000000000..06921b7bea63 --- /dev/null +++ b/sc/source/ui/inc/operation/SetFormulaOperation.hxx @@ -0,0 +1,41 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScAddress; +class ScDocFunc; +class ScFormulaCell; + +namespace sc +{ +/** Operation which sets a formula to a cell. */ +class SetFormulaOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScAddress const& mrPosition; + ScFormulaCell* mpFormulaCell; + + bool runImplementation() override; + +public: + SetFormulaOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScAddress& rPosition, + ScFormulaCell* pFormulaCell, bool bApi); +}; + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/SetNormalStringOperation.hxx b/sc/source/ui/inc/operation/SetNormalStringOperation.hxx new file mode 100644 index 000000000000..18dbb7aa2a15 --- /dev/null +++ b/sc/source/ui/inc/operation/SetNormalStringOperation.hxx @@ -0,0 +1,41 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScAddress; +class ScDocFunc; + +namespace sc +{ +/** Operation which sets string content to a cell. */ +class SetNormalStringOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScAddress const& mrPosition; + OUString const& mrText; + bool mbIsNumberFormatSet = false; + + bool runImplementation() override; + +public: + SetNormalStringOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScAddress& rPosition, + const OUString& rText, bool bApi); + bool isNumberFormatSet() { return mbIsNumberFormatSet; } +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/SetNoteTextOperation.hxx b/sc/source/ui/inc/operation/SetNoteTextOperation.hxx new file mode 100644 index 000000000000..79a02ec5b382 --- /dev/null +++ b/sc/source/ui/inc/operation/SetNoteTextOperation.hxx @@ -0,0 +1,36 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; + +namespace sc +{ +/** Operation which sets a note text at a given cell address. */ +class SetNoteTextOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScAddress maPos; + OUString maText; + + bool runImplementation() override; + +public: + SetNoteTextOperation(ScDocShell& rDocShell, const ScAddress& rPos, const OUString& rText, + bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/SetStringOperation.hxx b/sc/source/ui/inc/operation/SetStringOperation.hxx new file mode 100644 index 000000000000..651d60140cff --- /dev/null +++ b/sc/source/ui/inc/operation/SetStringOperation.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScAddress; +class ScDocFunc; + +namespace sc +{ +/** Operation which sets a string to a cell. */ +class SetStringOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScAddress const& mrPosition; + OUString const& mrString; + + bool runImplementation() override; + +public: + SetStringOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScAddress& rPosition, + OUString const& rString, bool bApi); +}; + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/SetValueOperation.hxx b/sc/source/ui/inc/operation/SetValueOperation.hxx new file mode 100644 index 000000000000..319cf2f4850f --- /dev/null +++ b/sc/source/ui/inc/operation/SetValueOperation.hxx @@ -0,0 +1,39 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScAddress; +class ScDocFunc; + +namespace sc +{ +/** Operation which sets a floating point value to a cell. */ +class SetValueOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScAddress const& mrPosition; + double mfValue; + + bool runImplementation() override; + +public: + SetValueOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScAddress& rPosition, + double fValue, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/SortOperation.hxx b/sc/source/ui/inc/operation/SortOperation.hxx new file mode 100644 index 000000000000..a26360254273 --- /dev/null +++ b/sc/source/ui/inc/operation/SortOperation.hxx @@ -0,0 +1,41 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; +class ScMarkData; +class ScDocFunc; +struct ScSortParam; +enum class InsertDeleteFlags : sal_Int32; + +namespace sc +{ +/** Operation which sorts cells in a sheet. */ +class SortOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + SCTAB mnTab; + ScSortParam const& mrSortParam; + bool mbPaint; + + bool runImplementation() override; + +public: + SortOperation(ScDocShell& rDocShell, SCTAB nTab, ScSortParam const& rSortParam, bool bRecord, + bool bPaint, bool bApi); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/SubTotalsOperation.hxx b/sc/source/ui/inc/operation/SubTotalsOperation.hxx new file mode 100644 index 000000000000..fdcd6fa0e9a9 --- /dev/null +++ b/sc/source/ui/inc/operation/SubTotalsOperation.hxx @@ -0,0 +1,36 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include +#include + +class ScDocShell; + +namespace sc +{ +/** Inserts subtotal rows into a data range, allows grouping by a column and calculating aggregate functions. */ +class SubTotalsOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + SCTAB mnTab; + ScSubTotalParam maParam; + + bool runImplementation() override; + +public: + SubTotalsOperation(ScDocShell& rDocShell, SCTAB nTab, const ScSubTotalParam& rParam, + bool bRecord, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/TransliterateTextOperation.hxx b/sc/source/ui/inc/operation/TransliterateTextOperation.hxx new file mode 100644 index 000000000000..6af618f32504 --- /dev/null +++ b/sc/source/ui/inc/operation/TransliterateTextOperation.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +enum class TransliterationFlags; + +class ScDocFunc; +class ScDocShell; +class ScMarkData; + +namespace sc +{ +/** Operation which transliterates text in marked cells. */ +class TransliterateTextOperation : public Operation +{ +private: + ScDocFunc& mrDocFunc; + ScDocShell& mrDocShell; + ScMarkData const& mrMark; + TransliterationFlags mnType; + + bool runImplementation() override; + +public: + TransliterateTextOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, const ScMarkData& rMark, + TransliterationFlags nType, bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/UngroupSparklinesOperation.hxx b/sc/source/ui/inc/operation/UngroupSparklinesOperation.hxx new file mode 100644 index 000000000000..f0fd93c0a1a0 --- /dev/null +++ b/sc/source/ui/inc/operation/UngroupSparklinesOperation.hxx @@ -0,0 +1,33 @@ +/* -*- 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/. + */ + +#pragma once + +#include "Operation.hxx" +#include + +class ScDocShell; + +namespace sc +{ +/** Ungroup all the sparklines in the input range and create a new group for each sparkline. */ +class UngroupSparklinesOperation : public Operation +{ +private: + ScDocShell& mrDocShell; + ScRange maRange; + + bool runImplementation() override; + +public: + UngroupSparklinesOperation(ScDocShell& rDocShell, ScRange const& rRange); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/operation/UpdatePivotTableOperation.hxx b/sc/source/ui/inc/operation/UpdatePivotTableOperation.hxx new file mode 100644 index 000000000000..b2f2b021c117 --- /dev/null +++ b/sc/source/ui/inc/operation/UpdatePivotTableOperation.hxx @@ -0,0 +1,32 @@ +/* -*- 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/. + */ + +#pragma once + +#include "PivotTableOperation.hxx" + +class ScDPObject; + +namespace sc +{ +/** Updates the pivot table identified by the input object. */ +class UpdatePivotTableOperation : public PivotTableOperation +{ +private: + ScDPObject& mrDPObject; + + bool runImplementation() override; + +public: + UpdatePivotTableOperation(ScDocShell& rDocShell, ScDPObject& rDPObject, bool bRecord, + bool bApi); +}; +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/optsolver.hxx b/sc/source/ui/inc/optsolver.hxx index a2318bd3e70f..02a4eb2fe48c 100644 --- a/sc/source/ui/inc/optsolver.hxx +++ b/sc/source/ui/inc/optsolver.hxx @@ -25,8 +25,11 @@ #include #include #include +#include #include #include +#include +#include #include #include diff --git a/sc/source/ui/inc/pfiltdlg.hxx b/sc/source/ui/inc/pfiltdlg.hxx index 2aa8b94fc882..c460896161a7 100644 --- a/sc/source/ui/inc/pfiltdlg.hxx +++ b/sc/source/ui/inc/pfiltdlg.hxx @@ -19,9 +19,12 @@ #pragma once +#include #include #include -#include +#include +#include + #include #include #include diff --git a/sc/source/ui/inc/protectiondlg.hxx b/sc/source/ui/inc/protectiondlg.hxx index 150d3d1c69d3..db87b3a7adeb 100644 --- a/sc/source/ui/inc/protectiondlg.hxx +++ b/sc/source/ui/inc/protectiondlg.hxx @@ -19,10 +19,15 @@ #pragma once +#include +#include +#include #include #include +#include +#include #include -#include +#include class ScTableProtection; @@ -72,7 +77,7 @@ private: DECL_LINK(OKHdl, weld::Button&, void); DECL_LINK(CheckBoxHdl, weld::Toggleable&, void); - DECL_LINK(PasswordModifyHdl, weld::Entry&, void); + DECL_LINK(PasswordModifyHdl, weld::TextWidget&, void); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/pvfundlg.hxx b/sc/source/ui/inc/pvfundlg.hxx index 6e8ee51b65d9..4f5067ce60c0 100644 --- a/sc/source/ui/inc/pvfundlg.hxx +++ b/sc/source/ui/inc/pvfundlg.hxx @@ -22,11 +22,17 @@ #include #include +#include +#include #include +#include #include +#include +#include #include #include -#include +#include + #include #include diff --git a/sc/source/ui/inc/reffact.hxx b/sc/source/ui/inc/reffact.hxx index f4d4a88df469..5a0190eaf0f1 100644 --- a/sc/source/ui/inc/reffact.hxx +++ b/sc/source/ui/inc/reffact.hxx @@ -28,7 +28,7 @@ class Class : public SfxChildWindow \ { \ public: \ - Class( vcl::Window*, sal_uInt16, SfxBindings*, SfxChildWinInfo* ); \ + Class(vcl::Window*, sal_uInt16, SfxBindings&, SfxChildWinInfo&); \ SFX_DECL_CHILDWINDOW_WITHID(Class); \ }; @@ -178,10 +178,7 @@ private: class ScAcceptChgDlgWrapper : public SfxChildWindow { public: - ScAcceptChgDlgWrapper( vcl::Window*, - sal_uInt16, - SfxBindings*, - SfxChildWinInfo* ); + ScAcceptChgDlgWrapper(vcl::Window*, sal_uInt16, SfxBindings&, SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID(Class); @@ -191,10 +188,7 @@ public: class ScSimpleRefDlgWrapper: public SfxChildWindow { public: - ScSimpleRefDlgWrapper(vcl::Window*, - sal_uInt16, - SfxBindings*, - SfxChildWinInfo*); + ScSimpleRefDlgWrapper(vcl::Window*, sal_uInt16, SfxBindings&, SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID(Class); @@ -213,7 +207,7 @@ class ScValidityRefChildWin : public SfxChildWindow bool m_bVisibleLock:1; bool m_bFreeWindowLock:1; public: - ScValidityRefChildWin( vcl::Window*, sal_uInt16, const SfxBindings*, SfxChildWinInfo* ); + ScValidityRefChildWin(vcl::Window*, sal_uInt16, const SfxBindings&, SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID(ScValidityRefChildWin); virtual ~ScValidityRefChildWin() override; bool LockVisible( bool bLock ){ bool bVis = m_bVisibleLock; m_bVisibleLock = bLock; return bVis; } diff --git a/sc/source/ui/inc/refundo.hxx b/sc/source/ui/inc/refundo.hxx index 9b6787222768..195a2cf714a7 100644 --- a/sc/source/ui/inc/refundo.hxx +++ b/sc/source/ui/inc/refundo.hxx @@ -45,7 +45,7 @@ private: std::unique_ptr pUnoRefs; public: - ScRefUndoData(ScDocument& rDoc ); + ScRefUndoData(ScDocument& rDoc, bool bForceDBSnapshot = false); ~ScRefUndoData(); void DeleteUnchanged(ScDocument& rDoc); diff --git a/sc/source/ui/inc/retypepassdlg.hxx b/sc/source/ui/inc/retypepassdlg.hxx index df20680c40f0..4f4016517671 100644 --- a/sc/source/ui/inc/retypepassdlg.hxx +++ b/sc/source/ui/inc/retypepassdlg.hxx @@ -20,10 +20,15 @@ #pragma once #include +#include +#include +#include #include #include +#include +#include #include -#include + #include #include @@ -126,7 +131,7 @@ private: DECL_LINK(OKHdl, weld::Button&, void); DECL_LINK(RadioBtnHdl, weld::Toggleable&, void); DECL_LINK(CheckBoxHdl, weld::Toggleable&, void); - DECL_LINK(PasswordModifyHdl, weld::Entry&, void); + DECL_LINK(PasswordModifyHdl, weld::TextWidget&, void); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/scendlg.hxx b/sc/source/ui/inc/scendlg.hxx index 485ce1aee757..7a04bc724a78 100644 --- a/sc/source/ui/inc/scendlg.hxx +++ b/sc/source/ui/inc/scendlg.hxx @@ -19,10 +19,13 @@ #pragma once +#include +#include #include #include +#include #include -#include +#include enum class ScScenarioFlags; diff --git a/sc/source/ui/inc/scuiasciiopt.hxx b/sc/source/ui/inc/scuiasciiopt.hxx index dd5ff16d53e7..22830d1d72e7 100644 --- a/sc/source/ui/inc/scuiasciiopt.hxx +++ b/sc/source/ui/inc/scuiasciiopt.hxx @@ -22,10 +22,13 @@ #include #include #include +#include #include #include +#include +#include #include -#include +#include #include "asciiopt.hxx" @@ -46,15 +49,15 @@ class ScImportAsciiDlg : public weld::GenericDialogController OUString maDetectedFieldSeps; // detected field seps sal_Unicode mcTextSep; - rtl_TextEncoding meCharSet; /// Selected char set. - rtl_TextEncoding meDetectedCharSet; /// This is computed only once at initialization, so store it. - bool mbCharSetSystem; /// Is System char set selected? - bool mbCharSetDetect; /// Should we autodetect character set ? + rtl_TextEncoding meEncoding; /// Selected encoding. + rtl_TextEncoding meDetectedEncoding; /// This is computed only once at initialization, so store it. + bool mbEncodingSystem; /// Is System encoding selected? + bool mbEncodingDetect; /// Should we autodetect encoding? ScImportAsciiCall meCall; /// How the dialog is called (see asciiopt.hxx) - std::unique_ptr mxFtCharSet; - std::unique_ptr mxLbCharSet; - std::unique_ptr mxFtDetectedCharSet; + std::unique_ptr mxFtEncoding; + std::unique_ptr mxLbEncoding; + std::unique_ptr mxFtDetectedEncoding; std::unique_ptr mxFtCustomLang; std::unique_ptr mxLbCustomLang; @@ -99,8 +102,8 @@ public: void SaveParameters(); private: - /** Sets the selected char set data to meCharSet and mbCharSetSystem. */ - void SetSelectedCharSet(); + /** Sets the selected char set data to meEncoding and mbEncodingSystem. */ + void SetSelectedEncoding(); /** Set separators in ui from maFieldSeparators or an optionally defined separator. */ void SetSeparators( sal_Unicode cSep ); @@ -117,10 +120,10 @@ private: inline bool Seek( sal_uLong nPos ); // synced to and from mnStreamPos void RbSepFix(); - DECL_LINK( CharSetHdl, weld::ComboBox&, void ); + DECL_LINK( EncodingHdl, weld::ComboBox&, void ); DECL_LINK( FirstRowHdl, weld::SpinButton&, void ); DECL_LINK( RbSepFixHdl, weld::Toggleable&, void ); - DECL_LINK( SeparatorEditHdl, weld::Entry&, void ); + DECL_LINK(SeparatorEditHdl, weld::TextWidget&, void); DECL_LINK( SeparatorClickHdl, weld::Toggleable&, void ); DECL_LINK( OtherOptionsClickHdl, weld::Toggleable&, void ); DECL_LINK( SeparatorComboBoxHdl, weld::ComboBox&, void ); diff --git a/sc/source/ui/inc/scuiimoptdlg.hxx b/sc/source/ui/inc/scuiimoptdlg.hxx index d38ed7f6c468..38135ccef150 100644 --- a/sc/source/ui/inc/scuiimoptdlg.hxx +++ b/sc/source/ui/inc/scuiimoptdlg.hxx @@ -19,10 +19,13 @@ #pragma once +#include #include #include +#include +#include #include -#include +#include class ScDelimiterTable; class ScImportOptions; @@ -52,7 +55,7 @@ private: bool m_bIsAsciiImport; std::unique_ptr m_xFieldFrame; - std::unique_ptr m_xFtCharset; + std::unique_ptr m_xFtEncoding; std::unique_ptr m_xEncGrid; std::unique_ptr m_xFtFieldSep; std::unique_ptr m_xEdFieldSep; @@ -62,8 +65,8 @@ private: std::unique_ptr m_xCbFormulas; std::unique_ptr m_xCbQuoteAll; std::unique_ptr m_xCbFixed; - std::unique_ptr m_xLbCharset; - std::unique_ptr m_xTvCharset; + std::unique_ptr m_xLbEncoding; + std::unique_ptr m_xTvEncoding; private: sal_uInt16 GetCodeFromCombo( const weld::ComboBox& rEd ) const; diff --git a/sc/source/ui/inc/scuitphfedit.hxx b/sc/source/ui/inc/scuitphfedit.hxx index 50f4d5c87152..cf9c7b039ac0 100644 --- a/sc/source/ui/inc/scuitphfedit.hxx +++ b/sc/source/ui/inc/scuitphfedit.hxx @@ -24,10 +24,14 @@ #include #include +#include +#include #include +#include +#include #include +#include #include -#include enum ScHFEntryId { @@ -84,6 +88,7 @@ private: std::unique_ptr m_xBtnBold; std::unique_ptr m_xBtnItalic; std::unique_ptr m_xBtnUnderline; + std::unique_ptr m_xEnableHF; std::unique_ptr m_xFtConfidential; std::unique_ptr m_xFtPage; @@ -109,7 +114,7 @@ private: std::unique_ptr m_xWndCenterWnd; std::unique_ptr m_xWndRightWnd; - ScEditWindow * m_pEditFocus; ///one of m_pWndLeft, m_pWndCenter, m_pWndRight + ScEditWindow * m_pEditFocus; /// one of m_xWndLeft, m_xWndCenter, m_xWndRight DECL_LINK( ObjectSelectHdl, ScEditWindow&, void ); @@ -130,6 +135,7 @@ private: DECL_LINK( ClickHdl, weld::Button&, void ); DECL_LINK( ToggleHdl, weld::Toggleable&, void ); DECL_LINK( MenuHdl, const OUString&, void ); + DECL_LINK( ToggleEnableHdl, weld::Toggleable&, void ); }; class ScFirstHeaderEditPage : public ScHFEditPage diff --git a/sc/source/ui/inc/searchresults.hxx b/sc/source/ui/inc/searchresults.hxx index 672a58c56c28..e31f3be180b9 100644 --- a/sc/source/ui/inc/searchresults.hxx +++ b/sc/source/ui/inc/searchresults.hxx @@ -9,8 +9,10 @@ #pragma once +#include +#include #include -#include +#include #include #include @@ -47,8 +49,8 @@ class SearchResultsDlgWrapper : public SfxChildWindow { std::shared_ptr m_xDialog; public: - SearchResultsDlgWrapper( - vcl::Window* _pParent, sal_uInt16 nId, SfxBindings* pBindings, SfxChildWinInfo* pInfo ); + SearchResultsDlgWrapper(vcl::Window* _pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); virtual ~SearchResultsDlgWrapper() override; diff --git a/sc/source/ui/inc/select.hxx b/sc/source/ui/inc/select.hxx index 0e996042cb0d..a97aec64488d 100644 --- a/sc/source/ui/inc/select.hxx +++ b/sc/source/ui/inc/select.hxx @@ -69,7 +69,6 @@ public: virtual void DeselectAll() override; bool SetCursorAtCell( SCCOL nPosX, SCROW nPosY, bool bScroll ); - bool CheckRefBounds(SCCOL nPosX, SCROW nPosY); }; class ScHeaderFunctionSet : public FunctionSet // Column / row headers diff --git a/sc/source/ui/inc/sharedocdlg.hxx b/sc/source/ui/inc/sharedocdlg.hxx index 56b6fedec201..f22a44d6eaa7 100644 --- a/sc/source/ui/inc/sharedocdlg.hxx +++ b/sc/source/ui/inc/sharedocdlg.hxx @@ -19,9 +19,11 @@ #pragma once +#include #include +#include #include -#include +#include class ScViewData; class ScDocShell; diff --git a/sc/source/ui/inc/shtabdlg.hxx b/sc/source/ui/inc/shtabdlg.hxx index c4aa39076ca3..9a026c691131 100644 --- a/sc/source/ui/inc/shtabdlg.hxx +++ b/sc/source/ui/inc/shtabdlg.hxx @@ -20,8 +20,9 @@ #pragma once #include +#include #include -#include +#include class ScShowTabDlg : public weld::GenericDialogController { diff --git a/sc/source/ui/inc/simpref.hxx b/sc/source/ui/inc/simpref.hxx index 3e96ef0285c9..4ffebb227f73 100644 --- a/sc/source/ui/inc/simpref.hxx +++ b/sc/source/ui/inc/simpref.hxx @@ -21,6 +21,8 @@ #include "anyrefdg.hxx" +#include + class ScSimpleRefDlg: public ScAnyRefDlgController { private: @@ -42,8 +44,6 @@ private: std::unique_ptr m_xBtnOk; std::unique_ptr m_xBtnCancel; - void Init(); - DECL_LINK( CancelBtnHdl, weld::Button&, void ); DECL_LINK( OkBtnHdl, weld::Button&, void ); @@ -52,7 +52,7 @@ protected: virtual void RefInputDone( bool bForced = false ) override; public: - ScSimpleRefDlg( SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent); + ScSimpleRefDlg(SfxBindings& rBindings, SfxChildWindow* pCW, weld::Window* pParent); virtual ~ScSimpleRefDlg() override; virtual void SetReference( const ScRange& rRef, ScDocument& rDoc ) override; diff --git a/sc/source/ui/inc/solveroptions.hxx b/sc/source/ui/inc/solveroptions.hxx index 31c03ff1825c..234d29a1f0d2 100644 --- a/sc/source/ui/inc/solveroptions.hxx +++ b/sc/source/ui/inc/solveroptions.hxx @@ -20,12 +20,15 @@ #pragma once #include +#include #include #include #include +#include #include #include -#include +#include + #include namespace com::sun::star { diff --git a/sc/source/ui/inc/sortdlg.hxx b/sc/source/ui/inc/sortdlg.hxx index 2bcd32f9d8f7..9f6fcb862f5a 100644 --- a/sc/source/ui/inc/sortdlg.hxx +++ b/sc/source/ui/inc/sortdlg.hxx @@ -21,7 +21,8 @@ #include #include -#include +#include +#include class ScSortDlg : public SfxTabDialogController { diff --git a/sc/source/ui/inc/sortkeydlg.hxx b/sc/source/ui/inc/sortkeydlg.hxx index 8b6d600891be..83fc7050599a 100644 --- a/sc/source/ui/inc/sortkeydlg.hxx +++ b/sc/source/ui/inc/sortkeydlg.hxx @@ -12,9 +12,12 @@ #include #include +#include #include #include -#include +#include +#include +#include struct ScSortKeyItem { diff --git a/sc/source/ui/inc/spelldialog.hxx b/sc/source/ui/inc/spelldialog.hxx index 4da4777036f6..5803782bc640 100644 --- a/sc/source/ui/inc/spelldialog.hxx +++ b/sc/source/ui/inc/spelldialog.hxx @@ -40,8 +40,8 @@ class ScSpellDialogChildWindow : public svx::SpellDialogChildWindow public: SFX_DECL_CHILDWINDOW_WITHID( ScSpellDialogChildWindow ); - explicit ScSpellDialogChildWindow( vcl::Window* pParent, sal_uInt16 nId, - SfxBindings* pBindings, SfxChildWinInfo* pInfo ); + explicit ScSpellDialogChildWindow(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); virtual ~ScSpellDialogChildWindow() override; /** This method makes the one from the base class public so that diff --git a/sc/source/ui/inc/strindlg.hxx b/sc/source/ui/inc/strindlg.hxx index 0ac0900531cc..03d495b28ae3 100644 --- a/sc/source/ui/inc/strindlg.hxx +++ b/sc/source/ui/inc/strindlg.hxx @@ -21,7 +21,8 @@ #include #include -#include +#include +#include class ScStringInputDlg : public weld::GenericDialogController { diff --git a/sc/source/ui/inc/subtdlg.hxx b/sc/source/ui/inc/subtdlg.hxx index b0c97b09e173..bbacd4066fde 100644 --- a/sc/source/ui/inc/subtdlg.hxx +++ b/sc/source/ui/inc/subtdlg.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include class ScSubTotalDlg : public SfxTabDialogController { diff --git a/sc/source/ui/inc/tabbgcolordlg.hxx b/sc/source/ui/inc/tabbgcolordlg.hxx index a4632bb00806..56376dac3f84 100644 --- a/sc/source/ui/inc/tabbgcolordlg.hxx +++ b/sc/source/ui/inc/tabbgcolordlg.hxx @@ -19,52 +19,25 @@ #pragma once -#include #include -#include -#include +#include class ScTabBgColorDlg : public weld::GenericDialogController { public: ScTabBgColorDlg(weld::Window* pParent, const OUString& rTitle, - const OUString& rTabBgColorNoColorText, const Color& rDefaultColor); virtual ~ScTabBgColorDlg() override; Color GetSelectedColor() const; - class ScTabBgColorValueSet : public SvxColorValueSet - { - public: - ScTabBgColorValueSet(std::unique_ptr pWindow); - virtual ~ScTabBgColorValueSet() override; - - void SetDialog(ScTabBgColorDlg* pTabBgColorDlg) - { - m_pTabBgColorDlg = pTabBgColorDlg; - } - - virtual bool KeyInput( const KeyEvent& rKEvt ) override; - private: - ScTabBgColorDlg* m_pTabBgColorDlg; - }; - private: - PaletteManager m_aPaletteManager; - Color m_aTabBgColor; + Color m_aTabBgColor; + std::unique_ptr m_xColorContainer; + std::unique_ptr m_xColorListBox; - std::unique_ptr m_xSelectPalette; - std::unique_ptr m_xTabBgColorSet; - std::unique_ptr m_xTabBgColorSetWin; - std::unique_ptr m_xBtnOk; - - void FillPaletteLB(); - - DECL_LINK(SelectPaletteLBHdl, weld::ComboBox&, void); - DECL_LINK(TabBgColorDblClickHdl_Impl, ValueSet*, void); - DECL_LINK(TabBgColorOKHdl_Impl, weld::Button&, void); + DECL_LINK(ColorSelectedHdl, ColorListBox&, void); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/tabpages.hxx b/sc/source/ui/inc/tabpages.hxx index f7f70673a047..53c950076b39 100644 --- a/sc/source/ui/inc/tabpages.hxx +++ b/sc/source/ui/inc/tabpages.hxx @@ -20,6 +20,8 @@ #pragma once #include +#include +#include class ScTabPageProtection : public SfxTabPage { diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx index 57eaade2927b..c1fe4e40495c 100644 --- a/sc/source/ui/inc/tabvwsh.hxx +++ b/sc/source/ui/inc/tabvwsh.hxx @@ -117,8 +117,6 @@ private: : m_nShellId(0) { } - - void Send(); }; SendFormulabarUpdate maSendFormulabarUpdate; @@ -190,8 +188,6 @@ private: sal_uInt16 nCurRefDlgId; - bool bIsTabChangeInProgress; - std::unique_ptr pAccessibilityBroadcaster; // ugly hack for Add button in ScNameDlg @@ -207,6 +203,12 @@ private: // Chart insert wizard's mark to make sure it undoes the correct thing in LOK case UndoStackMark m_InsertWizardUndoMark = MARK_INVALID; + /// Cell to navigate to when the user clicks "Go to First Error" on the + /// #REF! warning infobar. Set each time the infobar is (re-)shown. + ScAddress m_aRefErrorCell; + + void ShowRefErrorInfoBar(const ScAddress& rFormulaCell); + private: void Construct( TriState nForceDesignMode ); @@ -224,6 +226,7 @@ private: DECL_LINK( SimpleRefChange, const OUString&, void ); DECL_LINK( FormControlActivated, LinkParamNone*, void ); DECL_LINK( DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, void ); + DECL_LINK( GoToRefErrorHdl, weld::Button&, void ); protected: virtual void Activate(bool bMDI) override; @@ -241,7 +244,7 @@ protected: virtual void QueryObjAreaPixel( tools::Rectangle& rRect ) const override; virtual OUString GetSelectionText( bool bWholeWord = false, bool bOnlyASample = false ) override; - virtual bool HasSelection( bool bText = true ) const override; + virtual bool HasSelection(bool bMustHaveText) const override; virtual void WriteUserData(OUString &, bool bBrowse = false) override; virtual void ReadUserData(const OUString &, bool bBrowse = false) override; @@ -294,9 +297,6 @@ public: void SetActive(); - void SetTabChangeInProgress(bool bState) { bIsTabChangeInProgress = bState; } - bool IsTabChangeInProgress() { return bIsTabChangeInProgress; } - ::editeng::SvxBorderLine* GetDefaultFrameLine() const { return pCurFrameLine.get(); } void SetDefaultFrameLine(const ::editeng::SvxBorderLine* pLine ); @@ -392,9 +392,9 @@ public: SAL_RET_MAYBENULL SC_DLLPUBLIC static ScTabViewShell* GetActiveViewShell(); - std::shared_ptr CreateRefDialogController(SfxBindings* pB, SfxChildWindow* pCW, - SfxChildWinInfo* pInfo, - weld::Window* pParent, sal_uInt16 nSlotId); + std::shared_ptr + CreateRefDialogController(SfxBindings& rBindings, SfxChildWindow* pCW, SfxChildWinInfo& rInfo, + weld::Window* pParent, sal_uInt16 nSlotId); void UpdateOleZoom(); diff --git a/sc/source/ui/inc/tbzoomsliderctrl.hxx b/sc/source/ui/inc/tbzoomsliderctrl.hxx index aa72239b8930..2c17b32479d6 100644 --- a/sc/source/ui/inc/tbzoomsliderctrl.hxx +++ b/sc/source/ui/inc/tbzoomsliderctrl.hxx @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include #include diff --git a/sc/source/ui/inc/textimportoptions.hxx b/sc/source/ui/inc/textimportoptions.hxx index 621ed8fd87f2..74ebe5877f9a 100644 --- a/sc/source/ui/inc/textimportoptions.hxx +++ b/sc/source/ui/inc/textimportoptions.hxx @@ -19,8 +19,11 @@ #pragma once +#include +#include #include -#include +#include +#include #include class SvxLanguageBox; diff --git a/sc/source/ui/inc/tpcalc.hxx b/sc/source/ui/inc/tpcalc.hxx index 4073bf26ed37..b6c950d33c91 100644 --- a/sc/source/ui/inc/tpcalc.hxx +++ b/sc/source/ui/inc/tpcalc.hxx @@ -20,6 +20,9 @@ #pragma once #include +#include +#include +#include #include #include "editfield.hxx" #include diff --git a/sc/source/ui/inc/tpcompatibility.hxx b/sc/source/ui/inc/tpcompatibility.hxx index 0ef36ce7abc9..e41dded44e1b 100644 --- a/sc/source/ui/inc/tpcompatibility.hxx +++ b/sc/source/ui/inc/tpcompatibility.hxx @@ -10,6 +10,7 @@ #pragma once #include +#include #include class ScTpCompatOptions : public SfxTabPage diff --git a/sc/source/ui/inc/tpdefaults.hxx b/sc/source/ui/inc/tpdefaults.hxx index e660851770a7..e86b3570db75 100644 --- a/sc/source/ui/inc/tpdefaults.hxx +++ b/sc/source/ui/inc/tpdefaults.hxx @@ -10,6 +10,7 @@ #pragma once #include +#include #include #include @@ -31,8 +32,8 @@ private: void CheckPrefix(); void OnFocusPrefixInput(); - DECL_LINK( NumModifiedHdl, weld::Entry&, void ); - DECL_LINK( PrefixModifiedHdl, weld::Entry&, void ); + DECL_LINK(NumModifiedHdl, weld::TextWidget&, void); + DECL_LINK(PrefixModifiedHdl, weld::TextWidget&, void); DECL_LINK( PrefixEditOnFocusHdl, weld::Widget&, void ); private: diff --git a/sc/source/ui/inc/tpformula.hxx b/sc/source/ui/inc/tpformula.hxx index 567b2cd7f654..51447fb8b870 100644 --- a/sc/source/ui/inc/tpformula.hxx +++ b/sc/source/ui/inc/tpformula.hxx @@ -20,8 +20,11 @@ #pragma once #include +#include +#include #include #include +#include #include #include @@ -43,7 +46,7 @@ public: private: void ResetSeparators(); - void OnFocusSeparatorInput(weld::Entry* pEdit); + void OnFocusSeparatorInput(weld::TextWidget* pEdit); void UpdateCustomCalcRadioButtons(bool bDefault); void LaunchCustomCalcSettings(); @@ -54,7 +57,7 @@ private: DECL_LINK(SepInsertTextHdl, OUString&, bool); DECL_LINK(ColSepInsertTextHdl, OUString&, bool); DECL_LINK(RowSepInsertTextHdl, OUString&, bool); - DECL_LINK(SepModifyHdl, weld::Entry&, void); + DECL_LINK(SepModifyHdl, weld::TextWidget&, void); DECL_LINK(SepEditOnFocusHdl, weld::Widget&, void); private: diff --git a/sc/source/ui/inc/tphfedit.hxx b/sc/source/ui/inc/tphfedit.hxx index c65049b7e9cc..de6ac2ff68b4 100644 --- a/sc/source/ui/inc/tphfedit.hxx +++ b/sc/source/ui/inc/tphfedit.hxx @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -48,7 +49,7 @@ public: void SetFont( const ScPatternAttr& rPattern ); void SetText( const EditTextObject& rTextObject ); - std::unique_ptr CreateTextObject(); + EditTextObject CreateTextObject(); void SetCharAttributes(); void InsertField( const SvxFieldItem& rFld ); diff --git a/sc/source/ui/inc/tpprint.hxx b/sc/source/ui/inc/tpprint.hxx index 5cb33891b835..e032c7a0097f 100644 --- a/sc/source/ui/inc/tpprint.hxx +++ b/sc/source/ui/inc/tpprint.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include class ScTpPrintOptions : public SfxTabPage { diff --git a/sc/source/ui/inc/tpsort.hxx b/sc/source/ui/inc/tpsort.hxx index bda4107e1624..5217dd32f898 100644 --- a/sc/source/ui/inc/tpsort.hxx +++ b/sc/source/ui/inc/tpsort.hxx @@ -26,7 +26,12 @@ #include #include #include +#include +#include +#include #include +#include +#include #include #include "sortkeydlg.hxx" diff --git a/sc/source/ui/inc/tpstat.hxx b/sc/source/ui/inc/tpstat.hxx index bb57d7212747..ec00674cda77 100644 --- a/sc/source/ui/inc/tpstat.hxx +++ b/sc/source/ui/inc/tpstat.hxx @@ -20,6 +20,8 @@ #pragma once #include +#include +#include class ScDocStatPage: public SfxTabPage { diff --git a/sc/source/ui/inc/tpsubt.hxx b/sc/source/ui/inc/tpsubt.hxx index 3ec5d36ccc13..8d70b49a2359 100644 --- a/sc/source/ui/inc/tpsubt.hxx +++ b/sc/source/ui/inc/tpsubt.hxx @@ -20,7 +20,10 @@ #pragma once #include +#include #include +#include +#include #include #include diff --git a/sc/source/ui/inc/tptable.hxx b/sc/source/ui/inc/tptable.hxx index 79066c3474e5..3e1dd99835b7 100644 --- a/sc/source/ui/inc/tptable.hxx +++ b/sc/source/ui/inc/tptable.hxx @@ -20,7 +20,10 @@ #pragma once #include +#include #include +#include +#include #include #include diff --git a/sc/source/ui/inc/tpusrlst.hxx b/sc/source/ui/inc/tpusrlst.hxx index 9bef12e0c7a1..25a1e0ea8802 100644 --- a/sc/source/ui/inc/tpusrlst.hxx +++ b/sc/source/ui/inc/tpusrlst.hxx @@ -20,8 +20,11 @@ #pragma once #include +#include #include +#include #include +#include class ScUserList; class ScDocument; @@ -38,8 +41,8 @@ public: virtual OUString GetAllStrings() override; - virtual bool FillItemSet ( SfxItemSet* rCoreAttrs ) override; - virtual void Reset ( const SfxItemSet* rCoreAttrs ) override; + virtual bool FillItemSet(SfxItemSet* pCoreAttrs) override; + virtual void Reset(const SfxItemSet* pCoreAttrs) override; virtual DeactivateRC DeactivatePage ( SfxItemSet* pSet ) override; private: @@ -56,38 +59,35 @@ private: std::unique_ptr mxBtnRemove; std::unique_ptr mxBtnCopy; - const OUString aStrQueryRemove; - const OUString aStrCopyList; - const OUString aStrCopyFrom; - const OUString aStrCopyErr; + const OUString m_aStrQueryRemove; + const OUString m_aStrCopyFrom; + const OUString m_aStrCopyErr; - const sal_uInt16 nWhichUserLists; - std::unique_ptr pUserLists; + const sal_uInt16 m_nWhichUserLists; + std::unique_ptr m_pUserLists; - ScDocument* pDoc; - ScViewData* pViewData; - OUString aStrSelectedArea; + ScDocument* m_pDoc; + ScViewData* m_pViewData; + OUString m_aStrSelectedArea; - bool bModifyMode; - bool bCancelMode; - bool bCopyDone; - sal_Int32 nCancelPos; + bool m_bModifyMode; + bool m_bCancelMode; + bool m_bCopyDone; + sal_Int32 m_nCancelPos; - void Init (); size_t UpdateUserListBox (); void UpdateEntries ( size_t nList ); - static void MakeListStr ( OUString& rListStr ); - void AddNewList ( const OUString& rEntriesStr ); + static OUString MakeListStr(std::u16string_view sListStr); + void AddNewList(std::u16string_view sEntriesStr); void RemoveList ( size_t nList ); - void ModifyList ( size_t nSelList, - const OUString& rEntriesStr ); + void ModifyList(size_t nSelList, std::u16string_view sEntriesStr); void CopyListFromArea ( const ScRefAddress& rStartPos, const ScRefAddress& rEndPos ); // Handler: DECL_LINK(LbSelectHdl, weld::ItemView&, void); DECL_LINK( BtnClickHdl, weld::Button&, void ); - DECL_LINK( EdEntriesModHdl, weld::TextView&, void); + DECL_LINK(EdEntriesModHdl, weld::TextWidget&, void); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/tpview.hxx b/sc/source/ui/inc/tpview.hxx index a75d4131b74a..60e8b76a0d2e 100644 --- a/sc/source/ui/inc/tpview.hxx +++ b/sc/source/ui/inc/tpview.hxx @@ -21,8 +21,10 @@ #include #include +#include #include #include +#include class ScViewOptions; diff --git a/sc/source/ui/inc/undo/UndoInsertSheetView.hxx b/sc/source/ui/inc/undo/UndoInsertSheetView.hxx new file mode 100644 index 000000000000..6b582cdefaa5 --- /dev/null +++ b/sc/source/ui/inc/undo/UndoInsertSheetView.hxx @@ -0,0 +1,44 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include +#include +#include + +class SdrUndoAction; + +namespace sc +{ +/** Undo action for inserting a sheet view. */ +class UndoInsertSheetView : public ScSimpleUndo +{ +private: + std::unique_ptr mpDrawUndo; + SCTAB mnTab; // the default/source tab + SCTAB mnSheetViewTab; // the sheet view tab + SheetViewID mnSheetViewID; + +public: + UndoInsertSheetView(ScDocShell& rDocShell, SCTAB nTab, SCTAB nSheetViewTab, + SheetViewID nSheetViewID); + virtual ~UndoInsertSheetView() override; + + void Undo() override; + void Redo() override; + void Repeat(SfxRepeatTarget& rTarget) override; + bool CanRepeat(SfxRepeatTarget& rTarget) const override; + OUString GetComment() const override; +}; + +} // namespace sc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/undo/UndoSheetViewSortData.hxx b/sc/source/ui/inc/undo/UndoSheetViewSortData.hxx new file mode 100644 index 000000000000..e434e73d997a --- /dev/null +++ b/sc/source/ui/inc/undo/UndoSheetViewSortData.hxx @@ -0,0 +1,64 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include +#include + +class ScDocShell; + +namespace sc +{ +/** Mixin for undo/redo of sheet view sort data and auto-filter DB range. + * + * Captures before/after state of SheetView and SheetViewManager sort data, + * and restores them on undo/redo. Used by any undo action that modifies + * sort data (sorting, insert/delete cells, auto-filter expansion,...) + */ +class UndoSheetViewSortData +{ + SCTAB mnDefaultViewTab = -1; + + // For operations on a sheet view tab + SheetViewID mnSheetViewID = -1; + std::shared_ptr mpSheetViewSortDataBefore; + std::shared_ptr mpSheetViewSortDataAfter; + + // For operations on a default view tab + std::shared_ptr mpDefaultViewSortDataBefore; + std::shared_ptr mpDefaultViewSortDataAfter; + + // Auto-filter DB range before/after + std::optional moAutoFilterRangeBefore; + std::optional moAutoFilterRangeAfter; + +public: + /** Set context for operations on a sheet view tab. */ + void setSheetViewContext(SCTAB nDefaultViewTab, SheetViewID nSheetViewID, + std::shared_ptr pBefore, + std::shared_ptr pAfter); + + /** Set context for operations on a default view tab. */ + void setDefaultViewContext(SCTAB nDefaultViewTab, std::shared_ptr pBefore, + std::shared_ptr pAfter); + + /** Set auto-filter DB range before/after for undo/redo. */ + void setAutoFilterRange(ScRange const& rBefore, ScRange const& rAfter); + + /** Restore sort data for undo (before state) or redo (after state). */ + void restore(ScDocShell& rDocShell, bool bUndo) const; + + /** True if any sort data was captured. */ + bool hasData() const { return mnDefaultViewTab >= 0; } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/undo/UndoSpillPivotTable.hxx b/sc/source/ui/inc/undo/UndoSpillPivotTable.hxx new file mode 100644 index 000000000000..3d30f60f7fb8 --- /dev/null +++ b/sc/source/ui/inc/undo/UndoSpillPivotTable.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include + +namespace sc +{ +/** Undo action for a pivot table spill resolution. When a spilled pivot table + is rendered (because blocking cells were cleared), this undo action can + restore the #SPILL! state. Redo re-renders the pivot table. */ +class UndoSpillPivotTable : public ScSimpleUndo +{ +public: + UndoSpillPivotTable(ScDocShell& rDocShell, const OUString& rDPName, + const ScRange& rOutputRange); + + void Undo() override; + void Redo() override; + void Repeat(SfxRepeatTarget& rTarget) override; + bool CanRepeat(SfxRepeatTarget& rTarget) const override; + + OUString GetComment() const override; + +private: + OUString maDPName; + ScRange maOutputRange; // output range when rendered (non-spill state) +}; + +} // namespace sc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/undo/UndoUngroupSparklines.hxx b/sc/source/ui/inc/undo/UndoUngroupSparklines.hxx index 7c836ac2d1ce..3c2a89208ee2 100644 --- a/sc/source/ui/inc/undo/UndoUngroupSparklines.hxx +++ b/sc/source/ui/inc/undo/UndoUngroupSparklines.hxx @@ -16,7 +16,7 @@ namespace sc { -/** Previous sparkline group data, which is restored at undo ungroupping */ +/** Previous sparkline group data, which is restored at undo ungrouping */ struct SparklineUndoData { SparklineUndoData(ScAddress const& rAddress, ScRangeList aDataRangeList, diff --git a/sc/source/ui/inc/undobase.hxx b/sc/source/ui/inc/undobase.hxx index 08c76bfb27cb..5798f8d2f5f8 100644 --- a/sc/source/ui/inc/undobase.hxx +++ b/sc/source/ui/inc/undobase.hxx @@ -61,6 +61,8 @@ protected: void BeginRedo(); void EndRedo(); + void SyncSheetViews(); + void BroadcastChanges( const ScRange& rRange ); /** diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx index fa1c703b107b..d4f85cf3275f 100644 --- a/sc/source/ui/inc/undoblk.hxx +++ b/sc/source/ui/inc/undoblk.hxx @@ -26,6 +26,7 @@ #include #include +#include "undo/UndoSheetViewSortData.hxx" #include class ScDocShell; @@ -34,7 +35,7 @@ class SvxSearchItem; class SdrUndoAction; class ScEditDataArray; -class ScUndoInsertCells: public ScMoveUndo +class ScUndoInsertCells: public ScMoveUndo, public sc::UndoSheetViewSortData { public: ScUndoInsertCells( ScDocShell& rNewDocShell, @@ -70,7 +71,7 @@ private: void SetChangeTrack(); }; -class ScUndoDeleteCells: public ScMoveUndo +class ScUndoDeleteCells: public ScMoveUndo, public sc::UndoSheetViewSortData { public: ScUndoDeleteCells( ScDocShell& rNewDocShell, @@ -264,8 +265,15 @@ public: void SetDataSpans( const std::shared_ptr& pSpans ); + /// Positions of multi cell matrix masters that fell inside the deleted + /// range. The delete drops them from the expanded matrix tracking set, + /// Undo restores their cells but the tracking has to be re-added + /// explicitly. + void SetRestoreExpandedMatrices(std::vector const& rPositions); + private: std::shared_ptr mpDataSpans; // Spans of non-empty cells. + std::vector maRestoreExpandedMatrices; ScRange aRange; ScMarkData aMarkData; @@ -736,7 +744,8 @@ public: const ScRange& rArea, ScDocumentUniquePtr pNewUndoDoc, OUString aForm, - std::unique_ptr pTokenArray = nullptr ); + std::unique_ptr pTokenArray = nullptr, + bool bDynamicArrayMaster = false); virtual ~ScUndoEnterMatrix() override; virtual void Undo() override; @@ -753,6 +762,7 @@ private: std::unique_ptr pTokenArray; sal_uLong nStartChangeAction; sal_uLong nEndChangeAction; + bool mbDynamicArrayMaster; void SetChangeTrack(); }; diff --git a/sc/source/ui/inc/undocell.hxx b/sc/source/ui/inc/undocell.hxx index a2ef46402aac..92f355544deb 100644 --- a/sc/source/ui/inc/undocell.hxx +++ b/sc/source/ui/inc/undocell.hxx @@ -25,6 +25,7 @@ #include #include #include +#include "undo/UndoSheetViewSortData.hxx" #include @@ -66,7 +67,7 @@ private: void DoChange( const CellAttributeHolder& rWhichPattern, const std::unique_ptr& pEditData ) const; }; -class ScUndoEnterData: public ScSimpleUndo +class ScUndoEnterData: public ScSimpleUndo, public sc::UndoSheetViewSortData { public: @@ -134,7 +135,7 @@ private: void SetChangeTrack(); }; -class ScUndoSetCell : public ScSimpleUndo +class ScUndoSetCell : public ScSimpleUndo, public sc::UndoSheetViewSortData { public: ScUndoSetCell( ScDocShell& rDocSh, const ScAddress& rPos, ScCellValue aOldVal, ScCellValue aNewVal ); @@ -251,13 +252,18 @@ public: bool bInsert, std::unique_ptr pDrawUndo ); - /** Constructs an undo action for replacing a cell note with another. */ + /** Constructs an undo action for replacing a cell note with another. The + threaded-comment payload lives on ScPostIt outside ScNoteData, so callers + rescuing a threaded note pass clones for either or both sides; classic + notes leave the defaults. */ ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos, ScNoteData aOldData, ScNoteData aNewData, - std::unique_ptr pDrawUndo ); + std::unique_ptr pDrawUndo, + std::unique_ptr pOldThreadedData = nullptr, + std::unique_ptr pNewThreadedData = nullptr ); virtual ~ScUndoReplaceNote() override; @@ -271,13 +277,15 @@ public: virtual std::optional getAffectedRange() const override { return ScRange(maPos); } private: - void DoInsertNote( const ScNoteData& rNoteData ); + void DoInsertNote( const ScNoteData& rNoteData, const ScThreadedCommentData* pThreadedData ); void DoRemoveNote( const ScNoteData& rNoteData ); private: ScAddress maPos; ScNoteData maOldData; ScNoteData maNewData; + std::unique_ptr mpOldThreadedData; + std::unique_ptr mpNewThreadedData; std::unique_ptr mpDrawUndo; }; diff --git a/sc/source/ui/inc/undodraw.hxx b/sc/source/ui/inc/undodraw.hxx index 00069c7139ee..3fe33f6a1309 100644 --- a/sc/source/ui/inc/undodraw.hxx +++ b/sc/source/ui/inc/undodraw.hxx @@ -31,6 +31,7 @@ class ScUndoDraw: public SfxUndoAction ViewShellId mnViewShellId; void UpdateSubShell(); + void SyncSheetViews(); public: ScUndoDraw( std::unique_ptr pUndo, ScDocShell& rDocSh ); diff --git a/sc/source/ui/inc/undosort.hxx b/sc/source/ui/inc/undosort.hxx index ad0671b08d64..6ee827132aa7 100644 --- a/sc/source/ui/inc/undosort.hxx +++ b/sc/source/ui/inc/undosort.hxx @@ -11,10 +11,11 @@ #include "undobase.hxx" #include +#include "undo/UndoSheetViewSortData.hxx" namespace sc { -class UndoSort : public ScSimpleUndo +class UndoSort : public ScSimpleUndo, public UndoSheetViewSortData { ReorderParam maParam; diff --git a/sc/source/ui/inc/validate.hxx b/sc/source/ui/inc/validate.hxx index 53bac5d5a2cd..c9af6bf2f312 100644 --- a/sc/source/ui/inc/validate.hxx +++ b/sc/source/ui/inc/validate.hxx @@ -20,9 +20,14 @@ #pragma once #include +#include +#include #include +#include #include #include +#include +#include #include #include "anyrefdg.hxx" diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx index effa2ec1b1e5..aa3f755297c7 100644 --- a/sc/source/ui/inc/viewdata.hxx +++ b/sc/source/ui/inc/viewdata.hxx @@ -146,7 +146,6 @@ public: void invalidateByPosition(tools::Long nPos); const value_type& getNearestByIndex(index_type nIndex) const; const value_type& getNearestByPosition(tools::Long nPos) const; - tools::Long getPosition(index_type nIndex) const; tools::Long computePosition(index_type nIndex, const std::function& getSizePx); }; @@ -243,11 +242,10 @@ private: SCCOL nMaxTiledCol; SCROW nMaxTiledRow; + SCTAB nLastSheetViewTab; // last active sheet view bool bShowGrid; // per sheet show grid lines option. bool mbOldCursorValid; // "virtual" Cursor position when combined - sc::SheetViewID mnSheetViewID = sc::DefaultSheetViewID; - ScViewDataTable(const ScDocument& rDoc); void WriteUserDataSequence( @@ -419,15 +417,18 @@ public: void SetSheetViewID(sc::SheetViewID nID); - sc::SheetViewID GetSheetViewID() const - { - return pThisTab->mnSheetViewID; - } + SC_DLLPUBLIC sc::SheetViewID GetSheetViewID() const; sc::SheetViewID GetSheetViewIDForSheet(SCTAB nTab) const; std::shared_ptr GetCurrentSheetViewManager() const; + /** Returns the default view tab for the sheet view */ + SCTAB GetDefaultViewTab() const; + + SCTAB GetLastSheetViewTab(SCTAB nDefaultTab) const; + void ClearLastSheetViewTab(SCTAB nDefaultTab); + SCCOL MaxCol() const { return mrDoc.MaxCol(); } SCROW MaxRow() const { return mrDoc.MaxRow(); } ScSplitPos GetActivePart() const { return pThisTab->eWhichActive; } @@ -439,8 +440,6 @@ public: SCROW GetCurYForTab( SCTAB nTabIndex ) const; SCCOL GetOldCurX() const; SCROW GetOldCurY() const; - tools::Long GetLOKDocWidthPixel() const { return pThisTab->aWidthHelper.getPosition(pThisTab->nMaxTiledCol); } - tools::Long GetLOKDocHeightPixel() const { return pThisTab->aHeightHelper.getPosition(pThisTab->nMaxTiledRow); } ScPositionHelper& GetLOKWidthHelper() { return pThisTab->aWidthHelper; } ScPositionHelper& GetLOKHeightHelper() { return pThisTab->aHeightHelper; } @@ -595,7 +594,6 @@ public: const ScViewOptions& GetOptions() const { return maOptions; } SC_DLLPUBLIC void SetOptions( const ScViewOptions& rOpt ); - bool IsGridMode () const { return maOptions.GetOption(sc::ViewOption::GRID); } bool IsSyntaxMode () const { return maOptions.GetOption(sc::ViewOption::SYNTAX); } void SetSyntaxMode ( bool bNewMode ) { maOptions.SetOption(sc::ViewOption::SYNTAX, bNewMode); } bool IsHeaderMode () const { return maOptions.GetOption(sc::ViewOption::HEADER); } diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx index b53284aba332..834b0c116f6c 100644 --- a/sc/source/ui/inc/viewfunc.hxx +++ b/sc/source/ui/inc/viewfunc.hxx @@ -53,7 +53,7 @@ namespace com::sun::star::embed { class XEmbeddedObject; } namespace sc { struct ColRowSpan; - enum class Operation; + enum class OperationType; } namespace com::sun::star::datatransfer { class XTransferable; } @@ -67,24 +67,13 @@ struct ScDataFormFragment ScDataFormFragment(weld::Grid* pGrid, int nLine); }; -namespace sc -{ - -/** Direction of searching for the sheet view to switch to relative to the current sheet view. */ -enum class SwitchSheetViewDirection -{ - Next, - Previous -}; - -} - class ScViewFunc : public ScTabView { private: - ScAddress aFormatSource; // for automatic extension of formatting - ScRange aFormatArea; - bool bFormatValid; + ScAddress maFormatSource; // for automatic extension of formatting + ScRange maFormatArea; + bool mbFormatValid; + bool mbMultiInsert; public: ScViewFunc( vcl::Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ); @@ -105,10 +94,10 @@ public: bool AutoSum( const ScRange& rRange, bool bSubTotal, bool bSetCursor, bool bContinue, const OpCode eCode ); OUString GetAutoSumFormula( const ScRangeList& rRangeList, bool bSubTotal, const ScAddress& rAddr, const OpCode eCode ); - SC_DLLPUBLIC void EnterDataToCurrentCell(const OUString& rString, const EditTextObject* pData = nullptr, bool bMatrixExpand = false); + SC_DLLPUBLIC void EnterDataToCurrentCell(const OUString& rString, const EditTextObject* pData = nullptr, bool bAutoDynamicArray = false); SC_DLLPUBLIC void EnterData(SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString& rString, - const EditTextObject* pData = nullptr, bool bMatrixExpand = false); + const EditTextObject* pData = nullptr, bool bAutoDynamicArray = false); void EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextObject& rData, bool bTestSimple = false ); void EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue ); @@ -162,6 +151,9 @@ public: SCCOL nPosX, SCROW nPosY, const Point* pLogicPos, bool bLink = false, bool bAllowDialogs = false, bool useSavedPrefs = false ); + bool isMultiInsert() { return mbMultiInsert; } + void SetMultiInsertState( bool bMultiInsert ) { mbMultiInsert = bMultiInsert; } + bool PasteFile( const Point&, const OUString&, bool bLink ); bool PasteObject( const Point&, const css::uno::Reference < css::embed::XEmbeddedObject >&, const Size*, const Graphic* = nullptr, const OUString& = OUString(), sal_Int64 nAspect = css::embed::Aspects::MSOLE_CONTENT ); bool PasteBitmap( const Point&, const Bitmap& ); @@ -369,7 +361,6 @@ public: // SheetView methods void MakeNewSheetView(); void RemoveCurrentSheetView(); - void SwitchSheetView(sc::SwitchSheetViewDirection eDirection); void ExitSheetView(); // Switch to default view void SelectSheetView(sc::SheetViewID nSelectSheetViewID); @@ -417,7 +408,7 @@ private: void CopyAutoSpellData( FillDir eDir, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount ); - bool CheckSheetViewProtection(sc::Operation eOperation); + bool CheckSheetViewProtection(sc::OperationType eOperationType); void PasteFromExcelClip(ScDocument& rClipDoc, SCTAB nSrcTab, SCCOL nPosX, SCROW nPosY, const Point* pLogicPos, bool bAllowDialogs); diff --git a/sc/source/ui/inc/warnbox.hxx b/sc/source/ui/inc/warnbox.hxx index 8d1bcc26b53a..33d9f5881187 100644 --- a/sc/source/ui/inc/warnbox.hxx +++ b/sc/source/ui/inc/warnbox.hxx @@ -19,8 +19,9 @@ #pragma once +#include #include -#include +#include /** Warning box for "Replace cell contents?". With warning image and "Do not show again" checkbox. */ diff --git a/sc/source/ui/inc/xmlsourcedlg.hxx b/sc/source/ui/inc/xmlsourcedlg.hxx index b9fa64ebd977..46ec731ac6d3 100644 --- a/sc/source/ui/inc/xmlsourcedlg.hxx +++ b/sc/source/ui/inc/xmlsourcedlg.hxx @@ -12,6 +12,9 @@ #include "anyrefdg.hxx" #include +#include +#include +#include #include #include diff --git a/sc/source/ui/miscdlgs/acredlin.cxx b/sc/source/ui/miscdlgs/acredlin.cxx index 663899094ed7..586ebdfd7433 100644 --- a/sc/source/ui/miscdlgs/acredlin.cxx +++ b/sc/source/ui/miscdlgs/acredlin.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -1660,13 +1661,13 @@ namespace } } -void ScAcceptChgDlg::Initialize(SfxChildWinInfo* pInfo) +void ScAcceptChgDlg::Initialize(SfxChildWinInfo& rInfo) { OUString aStr; - if (pInfo && !pInfo->aExtraString.isEmpty()) - aStr = lcl_StripAcceptChgDat(pInfo->aExtraString); + if (!rInfo.aExtraString.isEmpty()) + aStr = lcl_StripAcceptChgDat(rInfo.aExtraString); - SfxModelessDialogController::Initialize(pInfo); + SfxModelessDialogController::Initialize(rInfo); if (aStr.isEmpty()) return; diff --git a/sc/source/ui/miscdlgs/anyrefdg.cxx b/sc/source/ui/miscdlgs/anyrefdg.cxx index 3783cfcb1535..6dd4d08a29bd 100644 --- a/sc/source/ui/miscdlgs/anyrefdg.cxx +++ b/sc/source/ui/miscdlgs/anyrefdg.cxx @@ -215,12 +215,12 @@ void ScFormulaReferenceHelper::ShowFormulaReference(const OUString& rStr) ScRange aRange; if(bDoubleRef) { - ScComplexRefData aRef( *pToken->GetDoubleRef() ); + ScComplexRefData aRef( static_cast(pToken)->GetDoubleRef() ); aRange = aRef.toAbs(rDoc, aPos); } else { - ScSingleRefData aRef( *pToken->GetSingleRef() ); + ScSingleRefData aRef( static_cast(pToken)->GetSingleRef() ); aRange.aStart = aRef.toAbs(rDoc, aPos); aRange.aEnd = aRange.aStart; } @@ -425,7 +425,7 @@ void ScFormulaReferenceHelper::DoClose( sal_uInt16 nId ) SfxViewFrame* pViewFrm = SfxViewFrame::Current(); if ( pViewFrm && pViewFrm->HasChildWindow(FID_INPUTLINE_STATUS) ) { - // The input row is disabled with ToolBox::Disable disabled, thus it must be + // The input row is disabled with ToolBox::Disable, thus it must be // reenabled with ToolBox::Enable (before the AppWindow is enabled) // for the buttons to be drawn as enabled. SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_INPUTLINE_STATUS); @@ -433,6 +433,8 @@ void ScFormulaReferenceHelper::DoClose( sal_uInt16 nId ) { ScInputWindow* pWin = static_cast(pChild->GetWindow()); pWin->Enable(); + // tdf#97354 - repaint to update the input line's disabled text color + pWin->TextInvalidate(); } } @@ -733,7 +735,7 @@ void ScRefHandler::AddRefEntry() bool ScRefHandler::IsTableLocked() const { - // the default is that the sheet can be switched during while the reference is edited + // the default is that the sheet can be switched while the reference is edited return false; } diff --git a/sc/source/ui/miscdlgs/conflictsdlg.cxx b/sc/source/ui/miscdlgs/conflictsdlg.cxx index 6e40c01066a9..979cdefd91cc 100644 --- a/sc/source/ui/miscdlgs/conflictsdlg.cxx +++ b/sc/source/ui/miscdlgs/conflictsdlg.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include diff --git a/sc/source/ui/miscdlgs/crnrdlg.cxx b/sc/source/ui/miscdlgs/crnrdlg.cxx index 6d22b259e550..c6dcfd3ed519 100644 --- a/sc/source/ui/miscdlgs/crnrdlg.cxx +++ b/sc/source/ui/miscdlgs/crnrdlg.cxx @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/sc/source/ui/miscdlgs/datafdlg.cxx b/sc/source/ui/miscdlgs/datafdlg.cxx index 88c8eecd239f..33d2b55bd170 100644 --- a/sc/source/ui/miscdlgs/datafdlg.cxx +++ b/sc/source/ui/miscdlgs/datafdlg.cxx @@ -92,7 +92,7 @@ ScDataFormDlg::ScDataFormDlg(weld::Window* pParent, ScTabViewShell& rTabViewShel } } - //skip leading hide column + //skip leading hidden column for (int i=1;i<=MAX_DATAFORM_COLS;i++) { int nColWidth = m_rDoc.GetColWidth(m_nStartCol, m_nTab); @@ -139,7 +139,7 @@ ScDataFormDlg::ScDataFormDlg(weld::Window* pParent, ScTabViewShell& rTabViewShel m_aColLength = m_nEndCol - m_nStartCol + 1; - //new the controls + //the new controls m_aEntries.reserve(m_aColLength); sal_Int32 nGridRow = 0; @@ -219,7 +219,7 @@ void ScDataFormDlg::FillCtrls() m_xSlider->vadjustment_set_value(m_nCurrentRow - m_nStartRow - 1); } -IMPL_LINK( ScDataFormDlg, Impl_DataModifyHdl, weld::Entry&, rEdit, void) +IMPL_LINK(ScDataFormDlg, Impl_DataModifyHdl, weld::TextWidget&, rEdit, void) { if (rEdit.get_value_changed_from_saved()) m_xBtnRestore->set_sensitive(true); diff --git a/sc/source/ui/miscdlgs/dataproviderdlg.cxx b/sc/source/ui/miscdlgs/dataproviderdlg.cxx index 68ad4e27c890..075e834ac759 100644 --- a/sc/source/ui/miscdlgs/dataproviderdlg.cxx +++ b/sc/source/ui/miscdlgs/dataproviderdlg.cxx @@ -885,15 +885,9 @@ IMPL_LINK_NOARG(ScDataProviderDlg, ProviderSelectHdl, weld::ComboBox&, void) isValid(); } -IMPL_LINK_NOARG(ScDataProviderDlg, IDEditHdl, weld::Entry&, void) -{ - isValid(); -} +IMPL_LINK_NOARG(ScDataProviderDlg, IDEditHdl, weld::TextWidget&, void) { isValid(); } -IMPL_LINK_NOARG(ScDataProviderDlg, URLEditHdl, weld::Entry&, void) -{ - isValid(); -} +IMPL_LINK_NOARG(ScDataProviderDlg, URLEditHdl, weld::TextWidget&, void) { isValid(); } IMPL_LINK_NOARG(ScDataProviderDlg, ApplyBtnHdl, weld::Button&, void) { diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx index 84980468c4ce..83caeade762f 100644 --- a/sc/source/ui/miscdlgs/datastreamdlg.cxx +++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx @@ -66,7 +66,7 @@ IMPL_LINK_NOARG(DataStreamDlg, UpdateClickHdl, weld::Toggleable&, void) { Update IMPL_LINK_NOARG(DataStreamDlg, UpdateComboBoxHdl, weld::ComboBox&, void) { UpdateEnable(); } -IMPL_LINK_NOARG(DataStreamDlg, UpdateHdl, weld::Entry&, void) { UpdateEnable(); } +IMPL_LINK_NOARG(DataStreamDlg, UpdateHdl, weld::TextWidget&, void) { UpdateEnable(); } void DataStreamDlg::UpdateEnable() { diff --git a/sc/source/ui/miscdlgs/datatableview.cxx b/sc/source/ui/miscdlgs/datatableview.cxx index e6f7373e0491..08380c6025fb 100644 --- a/sc/source/ui/miscdlgs/datatableview.cxx +++ b/sc/source/ui/miscdlgs/datatableview.cxx @@ -292,15 +292,6 @@ void ScDataTableView::getColRange(SCCOL& rStartCol, SCCOL& rEndCol) const rEndCol = static_cast(aEnd); } -void ScDataTableView::getRowRange(SCROW& rStartCol, SCROW& rEndCol) const -{ - SCCOLROW aStart = 0; - SCCOLROW aEnd = 0; - mpRowView->GetMarkRange(aStart, aEnd); - rStartCol = static_cast(aStart); - rEndCol = static_cast(aEnd); -} - IMPL_LINK_NOARG(ScDataTableView, VertScrollHdl, weld::Scrollbar&, void) { mnFirstVisibleRow = mpVScroll->GetThumbPos(); diff --git a/sc/source/ui/miscdlgs/duplicaterecordsdlg.cxx b/sc/source/ui/miscdlgs/duplicaterecordsdlg.cxx index e9ec2a43774b..5bdee364c97f 100644 --- a/sc/source/ui/miscdlgs/duplicaterecordsdlg.cxx +++ b/sc/source/ui/miscdlgs/duplicaterecordsdlg.cxx @@ -46,7 +46,7 @@ ScDuplicateRecordsDlg::ScDuplicateRecordsDlg(weld::Window* pParent, , mrRange(rRange) , mrViewData(rViewData) { - m_xCheckList->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xCheckList->enable_toggle_buttons(); m_xCheckList->connect_toggled(LINK(this, ScDuplicateRecordsDlg, RecordsChkHdl)); Init(); } diff --git a/sc/source/ui/miscdlgs/filldlg.cxx b/sc/source/ui/miscdlgs/filldlg.cxx index 9ed00b056c0b..d14b60d65a5d 100644 --- a/sc/source/ui/miscdlgs/filldlg.cxx +++ b/sc/source/ui/miscdlgs/filldlg.cxx @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/sc/source/ui/miscdlgs/gototabdlg.cxx b/sc/source/ui/miscdlgs/gototabdlg.cxx index 51dd1089ac43..da4c04f15e2b 100644 --- a/sc/source/ui/miscdlgs/gototabdlg.cxx +++ b/sc/source/ui/miscdlgs/gototabdlg.cxx @@ -59,7 +59,7 @@ IMPL_LINK_NOARG(ScGoToTabDlg, DblClkHdl, const weld::TreeIter&, bool) return true; } -IMPL_LINK_NOARG(ScGoToTabDlg, FindNameHdl, weld::Entry&, void) +IMPL_LINK_NOARG(ScGoToTabDlg, FindNameHdl, weld::TextWidget&, void) { const OUString aMask = m_xEnNameMask->get_text(); m_xLb->clear(); diff --git a/sc/source/ui/miscdlgs/inscldlg.cxx b/sc/source/ui/miscdlgs/inscldlg.cxx index ed9a55abeea6..49f7d289af05 100644 --- a/sc/source/ui/miscdlgs/inscldlg.cxx +++ b/sc/source/ui/miscdlgs/inscldlg.cxx @@ -25,6 +25,7 @@ #include #include +#include static sal_uInt8 nInsItemChecked = 0; diff --git a/sc/source/ui/miscdlgs/instbdlg.cxx b/sc/source/ui/miscdlgs/instbdlg.cxx index 688387a94052..a20824b2455c 100644 --- a/sc/source/ui/miscdlgs/instbdlg.cxx +++ b/sc/source/ui/miscdlgs/instbdlg.cxx @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include diff --git a/sc/source/ui/miscdlgs/linkarea.cxx b/sc/source/ui/miscdlgs/linkarea.cxx index 9cbeb89bbba4..3214548dec27 100644 --- a/sc/source/ui/miscdlgs/linkarea.cxx +++ b/sc/source/ui/miscdlgs/linkarea.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -247,10 +248,10 @@ void ScLinkedAreaDlg::UpdateSourceRanges() } // tdf#142600 - list tables in order of their appearance in the document's source - const ScRangeName* pRangeName = m_pSourceShell->GetDocument().GetRangeName(); - for (size_t i = 1; i <= pRangeName->index_size(); i++) + const ScRangeName& rRangeName = m_pSourceShell->GetDocument().GetRangeName(); + for (size_t i = 1; i <= rRangeName.index_size(); i++) { - if (const ScRangeData* pRangeData = pRangeName->findByIndex(i)) + if (const ScRangeData* pRangeData = rRangeName.findByIndex(i)) { m_xLbRanges->append_text(pRangeData->GetName()); } diff --git a/sc/source/ui/miscdlgs/mtrindlg.cxx b/sc/source/ui/miscdlgs/mtrindlg.cxx index 93a29f206b84..48c666b5bd38 100644 --- a/sc/source/ui/miscdlgs/mtrindlg.cxx +++ b/sc/source/ui/miscdlgs/mtrindlg.cxx @@ -46,7 +46,7 @@ ScMetricInputDlg::ScMetricInputDlg( weld::Window* pParent, sal_Int64 nMin(0), nMax(0); m_xEdValue->get_range(nMin, nMax, FieldUnit::TWIP); - + m_xEdValue->select_region(0,-1); auto nIncrement = m_xEdValue->normalize(1); m_xEdValue->set_increments(nIncrement / 10, nIncrement, FieldUnit::NONE); m_xEdValue->set_value(m_xEdValue->normalize(nDefault), FieldUnit::TWIP); diff --git a/sc/source/ui/miscdlgs/mvtabdlg.cxx b/sc/source/ui/miscdlgs/mvtabdlg.cxx index a84d26a25434..05351dae5b8e 100644 --- a/sc/source/ui/miscdlgs/mvtabdlg.cxx +++ b/sc/source/ui/miscdlgs/mvtabdlg.cxx @@ -29,6 +29,7 @@ #include #include +#include ScMoveTableDlg::ScMoveTableDlg(weld::Window* pParent, OUString aDefault) : GenericDialogController(pParent, u"modules/scalc/ui/movecopysheet.ui"_ustr, @@ -326,7 +327,7 @@ IMPL_LINK_NOARG(ScMoveTableDlg, SelHdl, weld::ComboBox&, void) ResetRenameInput(); } -IMPL_LINK_NOARG(ScMoveTableDlg, CheckNameHdl, weld::Entry&, void) +IMPL_LINK_NOARG(ScMoveTableDlg, CheckNameHdl, weld::TextWidget&, void) { mbEverEdited = true; CheckNewTabName(); diff --git a/sc/source/ui/miscdlgs/onlyactivesheetsaveddlg.cxx b/sc/source/ui/miscdlgs/onlyactivesheetsaveddlg.cxx deleted file mode 100644 index 26bcde863f08..000000000000 --- a/sc/source/ui/miscdlgs/onlyactivesheetsaveddlg.cxx +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- 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 -#include -#include - -#include -#include -#include - -ScOnlyActiveSheetSavedDlg::ScOnlyActiveSheetSavedDlg(weld::Window* pParent) - : GenericDialogController(pParent, u"modules/scalc/ui/onlyactivesheetsaveddialog.ui"_ustr, - u"OnlyActiveSheetSavedDialog"_ustr) - , m_xWarningOnBox(m_xBuilder->weld_check_button("cbShow")) -{ - m_xDialog->set_default_response(RET_YES); -} - -short ScOnlyActiveSheetSavedDlg::run() -{ - short nRet = RET_YES; - ScModule* pScMod = ScModule::get(); - assert(pScMod); - if (pScMod->GetInputOptions().GetWarnActiveSheet()) - { - m_xDialog->run(); - if (!m_xWarningOnBox->get_active()) - { - ScInputOptions aInputOpt(pScMod->GetInputOptions()); - aInputOpt.SetWarnActiveSheet(false); - pScMod->SetInputOptions(aInputOpt); - } - } - return nRet; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/miscdlgs/optsolver.cxx b/sc/source/ui/miscdlgs/optsolver.cxx index 9be202288ee5..d499332eaf2e 100644 --- a/sc/source/ui/miscdlgs/optsolver.cxx +++ b/sc/source/ui/miscdlgs/optsolver.cxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/sc/source/ui/miscdlgs/protectiondlg.cxx b/sc/source/ui/miscdlgs/protectiondlg.cxx index a606ce46a839..ce8043778c59 100644 --- a/sc/source/ui/miscdlgs/protectiondlg.cxx +++ b/sc/source/ui/miscdlgs/protectiondlg.cxx @@ -70,7 +70,7 @@ ScTableProtectionDlg::ScTableProtectionDlg(weld::Window* pParent) m_aAutoFilter = m_xAutoFilter->get_label(); m_aPivot = m_xPivot->get_label(); - m_xOptionsListBox->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xOptionsListBox->enable_toggle_buttons(); Init(); } @@ -110,7 +110,7 @@ void ScTableProtectionDlg::Init() m_xBtnOk->connect_clicked(LINK(this, ScTableProtectionDlg, OKHdl)); - Link aLink = LINK(this, ScTableProtectionDlg, PasswordModifyHdl); + Link aLink = LINK(this, ScTableProtectionDlg, PasswordModifyHdl); m_xPassword1Edit->connect_changed(aLink); m_xPassword2Edit->connect_changed(aLink); @@ -157,7 +157,7 @@ IMPL_LINK_NOARG(ScTableProtectionDlg, OKHdl, weld::Button&, void) m_xDialog->response(RET_OK); } -IMPL_LINK(ScTableProtectionDlg, PasswordModifyHdl, weld::Entry&, rEntry, void) +IMPL_LINK(ScTableProtectionDlg, PasswordModifyHdl, weld::TextWidget&, rEntry, void) { OUString aPass1 = m_xPassword1Edit->get_text(); if (&rEntry == m_xPassword1Edit.get()) diff --git a/sc/source/ui/miscdlgs/redcom.cxx b/sc/source/ui/miscdlgs/redcom.cxx index ef04bd57e1ff..d1d4f829ea94 100644 --- a/sc/source/ui/miscdlgs/redcom.cxx +++ b/sc/source/ui/miscdlgs/redcom.cxx @@ -18,6 +18,7 @@ */ #include +#include #include #include diff --git a/sc/source/ui/miscdlgs/retypepassdlg.cxx b/sc/source/ui/miscdlgs/retypepassdlg.cxx index 6860589e072a..6ae097cf696f 100644 --- a/sc/source/ui/miscdlgs/retypepassdlg.cxx +++ b/sc/source/ui/miscdlgs/retypepassdlg.cxx @@ -294,7 +294,7 @@ void ScRetypePassInputDlg::Init() m_xBtnRetypePassword->connect_toggled(LINK(this, ScRetypePassInputDlg, RadioBtnHdl)); m_xBtnRemovePassword->connect_toggled(LINK(this, ScRetypePassInputDlg, RadioBtnHdl)); m_xBtnMatchOldPass->connect_toggled(LINK(this, ScRetypePassInputDlg, CheckBoxHdl)); - Link aLink2 = LINK(this, ScRetypePassInputDlg, PasswordModifyHdl); + Link aLink2 = LINK(this, ScRetypePassInputDlg, PasswordModifyHdl); m_xPassword1Edit->connect_changed(aLink2); m_xPassword2Edit->connect_changed(aLink2); @@ -361,7 +361,7 @@ IMPL_LINK_NOARG(ScRetypePassInputDlg, CheckBoxHdl, weld::Toggleable&, void) CheckPasswordInput(); } -IMPL_LINK_NOARG(ScRetypePassInputDlg, PasswordModifyHdl, weld::Entry&, void) +IMPL_LINK_NOARG(ScRetypePassInputDlg, PasswordModifyHdl, weld::TextWidget&, void) { CheckPasswordInput(); } diff --git a/sc/source/ui/miscdlgs/simpref.cxx b/sc/source/ui/miscdlgs/simpref.cxx index b4f0ac3b8b5e..d013a58a5d28 100644 --- a/sc/source/ui/miscdlgs/simpref.cxx +++ b/sc/source/ui/miscdlgs/simpref.cxx @@ -21,8 +21,9 @@ #include #include -ScSimpleRefDlg::ScSimpleRefDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent) - : ScAnyRefDlgController(pB, pCW, pParent, u"modules/scalc/ui/simplerefdialog.ui"_ustr, u"SimpleRefDialog"_ustr) +ScSimpleRefDlg::ScSimpleRefDlg(SfxBindings& rBindings, SfxChildWindow* pCW, weld::Window* pParent) + : ScAnyRefDlgController(&rBindings, pCW, pParent, u"modules/scalc/ui/simplerefdialog.ui"_ustr, + u"SimpleRefDialog"_ustr) , bAutoReOpen(true) , bCloseOnButtonUp(false) , bSingleCell(false) @@ -36,8 +37,9 @@ ScSimpleRefDlg::ScSimpleRefDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Windo m_xEdAssign->SetReferences(this, m_xFtAssign.get()); m_xRbAssign->SetReferences(this, m_xEdAssign.get()); - // in order to keep the Strings with the FixedTexts in the resource: - Init(); + m_xBtnOk->connect_clicked(LINK(this, ScSimpleRefDlg, OkBtnHdl)); + m_xBtnCancel->connect_clicked(LINK(this, ScSimpleRefDlg, CancelBtnHdl)); + bCloseFlag = false; SetDispatcherLock( true ); // activate modal mode } @@ -57,13 +59,6 @@ void ScSimpleRefDlg::SetRefString(const OUString &rStr) m_xEdAssign->SetText(rStr); } -void ScSimpleRefDlg::Init() -{ - m_xBtnOk->connect_clicked( LINK( this, ScSimpleRefDlg, OkBtnHdl ) ); - m_xBtnCancel->connect_clicked( LINK( this, ScSimpleRefDlg, CancelBtnHdl ) ); - bCloseFlag=false; -} - // Set the reference to a cell range selected with the mouse. This is then // shown as the new selection in the reference field. void ScSimpleRefDlg::SetReference( const ScRange& rRef, ScDocument& rDocP ) diff --git a/sc/source/ui/miscdlgs/solveroptions.cxx b/sc/source/ui/miscdlgs/solveroptions.cxx index 620be14fcc67..b75ffb2fd2b7 100644 --- a/sc/source/ui/miscdlgs/solveroptions.cxx +++ b/sc/source/ui/miscdlgs/solveroptions.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -74,7 +75,7 @@ ScSolverOptionsDialog::ScSolverOptionsDialog(weld::Window* pParent, m_xLbSettings->set_size_request(m_xLbSettings->get_approximate_digit_width() * 32, m_xLbSettings->get_height_rows(12)); - m_xLbSettings->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xLbSettings->enable_toggle_buttons(); m_xLbEngine->connect_changed( LINK( this, ScSolverOptionsDialog, EngineSelectHdl ) ); diff --git a/sc/source/ui/miscdlgs/solvrdlg.cxx b/sc/source/ui/miscdlgs/solvrdlg.cxx index 64df741fefb4..eea70b17a17d 100644 --- a/sc/source/ui/miscdlgs/solvrdlg.cxx +++ b/sc/source/ui/miscdlgs/solvrdlg.cxx @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -178,9 +177,8 @@ void ScSolverDlg::RaiseError( ScSolverErr eError ) break; } - m_xMessageBox.reset(Application::CreateMessageDialog(m_xDialog.get(), - VclMessageType::Warning, VclButtonsType::Ok, - sMessage)); + m_xMessageBox = Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, + VclButtonsType::Ok, sMessage); m_xMessageBox->runAsync(m_xMessageBox, [this](sal_Int32 /*nResult*/) { m_xEdTargetVal->grab_focus(); m_xMessageBox.reset(); diff --git a/sc/source/ui/miscdlgs/tabbgcolordlg.cxx b/sc/source/ui/miscdlgs/tabbgcolordlg.cxx index 55bc7f81aee1..58b7c0737c86 100644 --- a/sc/source/ui/miscdlgs/tabbgcolordlg.cxx +++ b/sc/source/ui/miscdlgs/tabbgcolordlg.cxx @@ -21,43 +21,30 @@ #include -#include -#include +#include #include -#include #include -#include - ScTabBgColorDlg::ScTabBgColorDlg(weld::Window* pParent, const OUString& rTitle, - const OUString& rTabBgColorNoColorText, const Color& rDefaultColor) - : GenericDialogController(pParent, u"modules/scalc/ui/tabcolordialog.ui"_ustr, u"TabColorDialog"_ustr) + const Color& rDefaultColor) + : GenericDialogController(pParent, u"modules/scalc/ui/tabcolordialog.ui"_ustr, + u"TabColorDialog"_ustr) , m_aTabBgColor(rDefaultColor) - , m_xSelectPalette(m_xBuilder->weld_combo_box(u"paletteselector"_ustr)) - , m_xTabBgColorSet(new ScTabBgColorValueSet(m_xBuilder->weld_scrolled_window(u"colorsetwin"_ustr, true))) - , m_xTabBgColorSetWin(new weld::CustomWeld(*m_xBuilder, u"colorset"_ustr, *m_xTabBgColorSet)) - , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr)) + , m_xColorContainer(m_xBuilder->weld_container(u"colorcontainer"_ustr)) + , m_xColorListBox(new ColorListBox(m_xBuilder->weld_menu_button(u"colorlistbox"_ustr), + [pParent] { return pParent; })) { - m_xTabBgColorSet->SetDialog(this); - m_xTabBgColorSet->SetColCount(SvxColorValueSet::getColumnCount()); - m_xDialog->set_title(rTitle); + m_xColorListBox->SetSlotId(0, /*bShowNoneButton=*/true); - const WinBits nBits(m_xTabBgColorSet->GetStyle() | WB_NAMEFIELD | WB_ITEMBORDER | WB_NONEFIELD | WB_3DLOOK | WB_NO_DIRECTSELECT); - m_xTabBgColorSet->SetStyle(nBits); - m_xTabBgColorSet->SetText(rTabBgColorNoColorText); + // tdf#163838 - select the current tab color when reopening the dialog + if (rDefaultColor != COL_AUTO) + m_xColorListBox->SelectEntry(rDefaultColor); - const sal_uInt32 nColCount = SvxColorValueSet::getColumnCount(); - const sal_uInt32 nRowCount(10); - const sal_uInt32 nLength = SvxColorValueSet::getEntryEdgeLength(); - Size aSize(m_xTabBgColorSet->CalcWindowSizePixel(Size(nLength, nLength), nColCount, nRowCount)); - m_xTabBgColorSetWin->set_size_request(aSize.Width() + 8, aSize.Height() + 8); + m_xColorListBox->SetSelectHdl(LINK(this, ScTabBgColorDlg, ColorSelectedHdl)); - FillPaletteLB(); - - m_xSelectPalette->connect_changed(LINK(this, ScTabBgColorDlg, SelectPaletteLBHdl)); - m_xTabBgColorSet->SetDoubleClickHdl(LINK(this, ScTabBgColorDlg, TabBgColorDblClickHdl_Impl)); - m_xBtnOk->connect_clicked(LINK(this, ScTabBgColorDlg, TabBgColorOKHdl_Impl)); + // tdf#163785 - embed the color picker content inline without any popup + m_xColorListBox->EmbedColorWindowContent(m_xColorContainer.get()); } ScTabBgColorDlg::~ScTabBgColorDlg() @@ -69,76 +56,11 @@ Color ScTabBgColorDlg::GetSelectedColor() const return m_aTabBgColor; } -void ScTabBgColorDlg::FillPaletteLB() +IMPL_LINK_NOARG(ScTabBgColorDlg, ColorSelectedHdl, ColorListBox&, void) { - m_xSelectPalette->clear(); - std::vector aPaletteList = m_aPaletteManager.GetPaletteList(); - for (auto const& palette : aPaletteList) - { - m_xSelectPalette->append_text(palette); - } - OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() ); - m_xSelectPalette->set_active_text(aPaletteName); - if (m_xSelectPalette->get_active() != -1) - { - SelectPaletteLBHdl(*m_xSelectPalette); - } -} - -IMPL_LINK_NOARG(ScTabBgColorDlg, SelectPaletteLBHdl, weld::ComboBox&, void) -{ - m_xTabBgColorSet->Clear(); - sal_Int32 nPos = m_xSelectPalette->get_active(); - m_aPaletteManager.SetPalette( nPos ); - m_aPaletteManager.ReloadColorSet(*m_xTabBgColorSet); - m_xTabBgColorSet->Resize(); - m_xTabBgColorSet->SelectItem(0); -} - -// Handler, called when color selection is changed -IMPL_LINK_NOARG(ScTabBgColorDlg, TabBgColorDblClickHdl_Impl, ValueSet*, void) -{ - sal_uInt16 nItemId = m_xTabBgColorSet->GetSelectedItemId(); - Color aColor = nItemId ? ( m_xTabBgColorSet->GetItemColor( nItemId ) ) : COL_AUTO; - m_aTabBgColor = aColor; + Color aColor = m_xColorListBox->GetSelectEntryColor(); + m_aTabBgColor = aColor == COL_NONE_COLOR ? COL_AUTO : aColor; m_xDialog->response(RET_OK); } -// Handler, called when the OK button is pushed -IMPL_LINK_NOARG(ScTabBgColorDlg, TabBgColorOKHdl_Impl, weld::Button&, void) -{ - sal_uInt16 nItemId = m_xTabBgColorSet->GetSelectedItemId(); - Color aColor = nItemId ? ( m_xTabBgColorSet->GetItemColor( nItemId ) ) : COL_AUTO; - m_aTabBgColor = aColor; - m_xDialog->response(RET_OK); -} - -ScTabBgColorDlg::ScTabBgColorValueSet::ScTabBgColorValueSet(std::unique_ptr pWindow) - : SvxColorValueSet(std::move(pWindow)) - , m_pTabBgColorDlg(nullptr) -{ -} - -ScTabBgColorDlg::ScTabBgColorValueSet::~ScTabBgColorValueSet() -{ -} - -bool ScTabBgColorDlg::ScTabBgColorValueSet::KeyInput( const KeyEvent& rKEvt ) -{ - switch ( rKEvt.GetKeyCode().GetCode() ) - { - case KEY_SPACE: - case KEY_RETURN: - { - sal_uInt16 nItemId = GetSelectedItemId(); - const Color aColor = nItemId ? ( GetItemColor( nItemId ) ) : COL_AUTO; - m_pTabBgColorDlg->m_aTabBgColor = aColor; - m_pTabBgColorDlg->response(RET_OK); - return true; - } - break; - } - return SvxColorValueSet::KeyInput(rKEvt); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/miscdlgs/tabopdlg.cxx b/sc/source/ui/miscdlgs/tabopdlg.cxx index 8cdc2457b0df..f56b487fddc2 100644 --- a/sc/source/ui/miscdlgs/tabopdlg.cxx +++ b/sc/source/ui/miscdlgs/tabopdlg.cxx @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/sc/source/ui/miscdlgs/textdlgs.cxx b/sc/source/ui/miscdlgs/textdlgs.cxx index d0cf689abb8a..3d95e5513909 100644 --- a/sc/source/ui/miscdlgs/textdlgs.cxx +++ b/sc/source/ui/miscdlgs/textdlgs.cxx @@ -31,6 +31,7 @@ #include #include +#include ScCharDlg::ScCharDlg(weld::Window* pParent, const SfxItemSet* pAttr, const SfxObjectShell* pDocShell, bool bDrawText) : SfxTabDialogController(pParent, u"modules/scalc/ui/chardialog.ui"_ustr, u"CharDialog"_ustr, pAttr) diff --git a/sc/source/ui/namedlg/namedefdlg.cxx b/sc/source/ui/namedlg/namedefdlg.cxx index 09ed2ebf5304..250a1aa7f830 100644 --- a/sc/source/ui/namedlg/namedefdlg.cxx +++ b/sc/source/ui/namedlg/namedefdlg.cxx @@ -237,11 +237,11 @@ void ScNameDefDlg::AddPushed() { ScRangeData::Type nType = ScRangeData::Type::Name; - ScRangeData* pNewEntry = new ScRangeData( mrDoc, + std::unique_ptr pNewEntry(new ScRangeData( mrDoc, aName, aExpression, maCursorPos, - nType ); + nType )); if ( m_xBtnRowHeader->get_active() ) nType |= ScRangeData::Type::RowHeader; if ( m_xBtnColHeader->get_active() ) nType |= ScRangeData::Type::ColHeader; @@ -253,8 +253,7 @@ void ScNameDefDlg::AddPushed() // aExpression valid? if ( FormulaError::NONE == pNewEntry->GetErrCode() ) { - if ( !pRangeName->insert( pNewEntry, false /*bReuseFreeIndex*/ ) ) - pNewEntry = nullptr; + ScRangeData* pInserted = pRangeName->insert( std::move(pNewEntry), false /*bReuseFreeIndex*/ ); if (mbUndo) { @@ -265,10 +264,10 @@ void ScNameDefDlg::AddPushed() if (!mrDoc.GetTable(aScope, nTab)) nTab = -1; - assert( pNewEntry); // undo of no insertion smells fishy - if (pNewEntry) + assert( pInserted); // undo of no insertion smells fishy + if (pInserted) mpDocShell->GetUndoManager()->AddUndoAction( - std::make_unique( *mpDocShell, pNewEntry, nTab) ); + std::make_unique( *mpDocShell, pInserted, nTab) ); // set table stream invalid, otherwise RangeName won't be saved if no other // call invalidates the stream @@ -288,7 +287,6 @@ void ScNameDefDlg::AddPushed() } else { - delete pNewEntry; m_xEdRange->GrabFocus(); m_xEdRange->SelectAll(); } @@ -343,13 +341,10 @@ IMPL_LINK_NOARG(ScNameDefDlg, CancelBtnHdl, weld::Button&, void) IMPL_LINK_NOARG(ScNameDefDlg, AddBtnHdl, weld::Button&, void) { AddPushed(); -}; - -IMPL_LINK_NOARG(ScNameDefDlg, NameModifyHdl, weld::Entry&, void) -{ - IsNameValid(); } +IMPL_LINK_NOARG(ScNameDefDlg, NameModifyHdl, weld::TextWidget&, void) { IsNameValid(); } + IMPL_LINK_NOARG(ScNameDefDlg, AssignGetFocusHdl, formula::RefEdit&, void) { IsNameValid(); diff --git a/sc/source/ui/namedlg/namedlg.cxx b/sc/source/ui/namedlg/namedlg.cxx index b7326b9c41e3..3ca93c655c19 100644 --- a/sc/source/ui/namedlg/namedlg.cxx +++ b/sc/source/ui/namedlg/namedlg.cxx @@ -214,10 +214,10 @@ void ScNameDlg::SetActive() void ScNameDlg::UpdateChecks(const ScRangeData* pData) { // remove handlers, we only want the handlers to process - // user input and not when we are syncing the controls with our internal - // model ( also UpdateChecks is called already from some other event + // user input and not when we are syncing the controls with our internal + // model (also UpdateChecks is called already from some other event // handlers, triggering handlers while already processing a handler can - // ( and does in this case ) corrupt the internal data + // (and does in this case) corrupt the internal data) m_xBtnCriteria->connect_toggled( Link() ); m_xBtnPrintArea->connect_toggled( Link() ); @@ -419,10 +419,10 @@ void ScNameDlg::NameModified() if ( m_xBtnPrintArea->get_active() ) nType |= ScRangeData::Type::PrintArea; if ( m_xBtnCriteria->get_active() ) nType |= ScRangeData::Type::Criteria; - ScRangeData* pNewEntry = new ScRangeData( mrDoc, aNewName, aExpr, - maCursorPos, nType); + std::unique_ptr pNewEntry(new ScRangeData( mrDoc, aNewName, aExpr, + maCursorPos, nType)); pNewEntry->SetIndex( nIndex); - pNewRangeName->insert(pNewEntry, false /*bReuseFreeIndex*/); + pNewRangeName->insert(std::move(pNewEntry), false /*bReuseFreeIndex*/); aLine.aName = aNewName; aLine.aExpression = aExpr; aLine.aScope = aNewScope; @@ -511,10 +511,7 @@ IMPL_LINK_NOARG(ScNameDlg, EdModifyCheckBoxHdl, weld::Toggleable&, void) NameModified(); } -IMPL_LINK_NOARG(ScNameDlg, EdModifyHdl, weld::Entry&, void) -{ - NameModified(); -} +IMPL_LINK_NOARG(ScNameDlg, EdModifyHdl, weld::TextWidget&, void) { NameModified(); } IMPL_LINK_NOARG(ScNameDlg, RefEdModifyHdl, formula::RefEdit&, void) { diff --git a/sc/source/ui/namedlg/namemgrtable.cxx b/sc/source/ui/namedlg/namemgrtable.cxx index bb5ee6e5ebf9..e42bfd2e8b0a 100644 --- a/sc/source/ui/namedlg/namemgrtable.cxx +++ b/sc/source/ui/namedlg/namemgrtable.cxx @@ -19,7 +19,6 @@ #include #include -#include #include void ScRangeManagerTable::GetCurrentLine(ScRangeNameLine& rLine) @@ -133,7 +132,7 @@ void ScRangeManagerTable::addEntry(const ScRangeNameLine& rLine, bool bSetCurEnt m_xTreeView->set_text(nRow, rLine.aName, 0); m_xTreeView->set_text(nRow, rLine.aExpression, 1); m_xTreeView->set_text(nRow, rLine.aScope, 2); - // just unique to track which one has been cached by maCalculatedFormulaEntries + // just used to track which one has been cached by maCalculatedFormulaEntries m_xTreeView->set_id(nRow, OUString::number(m_nId++)); if (bSetCurEntry) m_xTreeView->set_cursor(nRow); diff --git a/sc/source/ui/navipi/content.cxx b/sc/source/ui/navipi/content.cxx index 43545022bc59..39e584d06b81 100644 --- a/sc/source/ui/navipi/content.cxx +++ b/sc/source/ui/navipi/content.cxx @@ -390,7 +390,7 @@ void ScContentTree::ActivateSelectedEntry() if (ScPostIt* pNote = pSrcDoc ? pSrcDoc->GetNote(aPos.Col(), aPos.Row(), aPos.Tab()) : nullptr) { bool bVisible = pNote->IsCaptionShown(); - // Effectivelly set the visibility of the comment + // Effectively set the visibility of the comment GetManualOrCurrent()->GetDocFunc().ShowNote(aPos, !bVisible); // Put the note in edit mode ScTabViewShell* pScTabViewShell = ScNavigatorDlg::GetTabViewShell(); @@ -601,9 +601,9 @@ IMPL_LINK(ScContentTree, CommandHdl, const CommandEvent&, rCEvt, bool) OUString aName = pSh->GetTitle(); OUString aEntry = aName; if ( pSh == pCurrentSh ) - aEntry += pParentWindow->aStrActive; + aEntry += pParentWindow->m_aStrActive; else - aEntry += pParentWindow->aStrNotActive; + aEntry += pParentWindow->m_aStrNotActive; ++i; sId = "document" + OUString::number(i); xDocMenu->append_radio(sId, aEntry); @@ -615,7 +615,7 @@ IMPL_LINK(ScContentTree, CommandHdl, const CommandEvent&, rCEvt, bool) // "active window" ++i; sId = "document" + OUString::number(i); - xDocMenu->append_radio(sId, pParentWindow->aStrActiveWin); + xDocMenu->append_radio(sId, pParentWindow->m_aStrActiveWin); if (aManualDoc.isEmpty()) sActive = sId; xDocMenu->set_active(sActive, true); @@ -790,8 +790,8 @@ void ScContentTree::GetAreaNames() ScRange aDummy; std::set aSet; - ScRangeName* pRangeNames = pDoc->GetRangeName(); - for (const auto& rEntry : *pRangeNames) + ScRangeName& rRangeNames = pDoc->GetRangeName(); + for (const auto& rEntry : rRangeNames) { if (rEntry.second->IsValidReference(aDummy)) aSet.insert(rEntry.second->GetName()); @@ -1108,13 +1108,10 @@ static bool lcl_GetRange( const ScDocument& rDoc, ScContentId nType, const OUStr if ( nType == ScContentId::RANGENAME ) { - ScRangeName* pList = rDoc.GetRangeName(); - if (pList) - { - const ScRangeData* p = pList->findByUpperName(ScGlobal::getCharClass().uppercase(rName)); - if (p && p->IsValidReference(rRange)) - bFound = true; - } + ScRangeName& rList = rDoc.GetRangeName(); + const ScRangeData* p = rList.findByUpperName(ScGlobal::getCharClass().uppercase(rName)); + if (p && p->IsValidReference(rRange)) + bFound = true; } else if ( nType == ScContentId::DBAREA ) { @@ -1457,7 +1454,7 @@ void ScContentTree::SetManualDoc(const OUString& rName) void ScContentTree::SelectDoc(const OUString& rName) // rName like shown in Menu/Listbox { - if ( rName == pParentWindow->aStrActiveWin ) + if (rName == pParentWindow->m_aStrActiveWin) { ResetManualDoc(); return; @@ -1467,11 +1464,11 @@ void ScContentTree::SelectDoc(const OUString& rName) // rName like shown in OUString aRealName = rName; sal_Int32 nLen = rName.getLength(); - sal_Int32 nActiveStart = nLen - pParentWindow->aStrActive.getLength(); - if ( rName.subView( nActiveStart ) == pParentWindow->aStrActive ) + sal_Int32 nActiveStart = nLen - pParentWindow->m_aStrActive.getLength(); + if (rName.subView(nActiveStart) == pParentWindow->m_aStrActive) aRealName = rName.copy( 0, nActiveStart ); - sal_Int32 nNotActiveStart = nLen - pParentWindow->aStrNotActive.getLength(); - if ( rName.subView( nNotActiveStart ) == pParentWindow->aStrNotActive ) + sal_Int32 nNotActiveStart = nLen - pParentWindow->m_aStrNotActive.getLength(); + if (rName.subView(nNotActiveStart) == pParentWindow->m_aStrNotActive) aRealName = rName.copy( 0, nNotActiveStart ); bool bLoaded = false; diff --git a/sc/source/ui/navipi/navipi.cxx b/sc/source/ui/navipi/navipi.cxx index 33265211aea9..9a5480406f17 100644 --- a/sc/source/ui/navipi/navipi.cxx +++ b/sc/source/ui/navipi/navipi.cxx @@ -40,8 +40,7 @@ #include #include #include - -#include +#include #include @@ -173,7 +172,7 @@ IMPL_LINK(ScNavigatorDlg, ToolBoxSelectHdl, const OUString&, rSelId, void) // Switch the mode? if (rSelId == "contents" || rSelId == "scenarios") { - NavListMode eOldMode = eListMode; + NavListMode eOldMode = m_eListMode; NavListMode eNewMode; if (rSelId == "scenarios") @@ -247,7 +246,7 @@ IMPL_LINK(ScNavigatorDlg, MenuSelectHdl, const OUString&, rIdent, void) void ScNavigatorDlg::UpdateButtons() { - NavListMode eMode = eListMode; + NavListMode eMode = m_eListMode; m_xTbxCmd2->set_item_active(u"scenarios"_ustr, eMode == NAV_LMODE_SCENARIOS); m_xTbxCmd1->set_item_active(u"contents"_ustr, eMode != NAV_LMODE_NONE); @@ -265,7 +264,7 @@ void ScNavigatorDlg::UpdateButtons() } OUString sImageId; - switch (nDropMode) + switch (m_nDropMode) { case SC_DROPMODE_URL: sImageId = RID_BMP_DROP_URL; @@ -287,43 +286,37 @@ ScNavigatorSettings::ScNavigatorSettings() maExpandedVec.fill(false); } -ScNavigatorWin::ScNavigatorWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr, - vcl::Window* _pParent, SfxChildWinInfo* pInfo) - : SfxNavigator(_pBindings, _pMgr, _pParent, pInfo) +ScNavigatorWin::ScNavigatorWin(SfxBindings& rBindings, SfxChildWindow* _pMgr, vcl::Window* _pParent, + SfxChildWinInfo& rInfo) + : SfxNavigator(rBindings, _pMgr, _pParent, rInfo) { - m_xNavigator = std::make_unique(_pBindings, m_xContainer.get(), this); + m_xNavigator = std::make_unique(rBindings, m_xContainer.get(), this); SetMinOutputSizePixel(GetOptimalSize()); } -ScNavigatorDlg::ScNavigatorDlg(SfxBindings* pB, weld::Widget* pParent, SfxNavigator* pNavigatorDlg) +ScNavigatorDlg::ScNavigatorDlg(SfxBindings& rBindings, weld::Widget* pParent, + SfxNavigator* pNavigatorDlg) : PanelLayout(pParent, u"NavigatorPanel"_ustr, u"modules/scalc/ui/navigatorpanel.ui"_ustr) - , rBindings(*pB) + , m_rBindings(rBindings) , m_xEdCol(m_xBuilder->weld_spin_button(u"column"_ustr)) , m_xEdRow(m_xBuilder->weld_spin_button(u"row"_ustr)) , m_xTbxCmd1(m_xBuilder->weld_toolbar(u"toolbox1"_ustr)) , m_xTbxCmd2(m_xBuilder->weld_toolbar(u"toolbox2"_ustr)) , m_xLbEntries(new ScContentTree(m_xBuilder->weld_tree_view(u"contentbox"_ustr), this)) , m_xScenarioBox(m_xBuilder->weld_widget(u"scenariobox"_ustr)) - , m_xWndScenarios(new ScScenarioWindow(*m_xBuilder, - ScResId(SCSTR_QHLP_SCEN_LISTBOX), ScResId(SCSTR_QHLP_SCEN_COMMENT))) + , m_xWndScenarios(new ScScenarioWindow(*m_xBuilder, ScResId(SCSTR_QHLP_SCEN_LISTBOX), + ScResId(SCSTR_QHLP_SCEN_COMMENT))) , m_xLbDocuments(m_xBuilder->weld_combo_box(u"documents"_ustr)) , m_xDragModeMenu(m_xBuilder->weld_menu(u"dragmodemenu"_ustr)) , m_xNavigatorDlg(pNavigatorDlg) - , aContentIdle("ScNavigatorDlg aContentIdle") - , aStrActiveWin(ScResId(SCSTR_ACTIVEWIN)) - , eListMode(NAV_LMODE_NONE) - , nDropMode(SC_DROPMODE_URL) - , nCurCol(0) - , nCurRow(0) - , nCurTab(0) + , m_aContentIdle("ScNavigatorDlg aContentIdle") + , m_aStrActiveWin(ScResId(SCSTR_ACTIVEWIN)) + , m_eListMode(NAV_LMODE_NONE) + , m_nDropMode(SC_DROPMODE_URL) + , m_nCurCol(0) + , m_nCurRow(0) + , m_nCurTab(0) { - - if (comphelper::LibreOfficeKit::isActive()) - { - sal_uInt64 nShellId = reinterpret_cast(SfxViewShell::Current()); - jsdialog::SendNavigatorForView(nShellId); - } - UpdateInitShow(); UpdateSheetLimits(); @@ -343,24 +336,24 @@ ScNavigatorDlg::ScNavigatorDlg(SfxBindings* pB, weld::Widget* pParent, SfxNaviga m_xTbxCmd2->connect_menu_toggled(LINK(this, ScNavigatorDlg, ToolBoxDropdownClickHdl)); ScNavipiCfg& rCfg = ScModule::get()->GetNavipiCfg(); - nDropMode = rCfg.GetDragMode(); + m_nDropMode = rCfg.GetDragMode(); m_xLbDocuments->set_size_request(42, -1); // set a nominal width so it takes width of surroundings m_xLbDocuments->connect_changed(LINK(this, ScNavigatorDlg, DocumentSelectHdl)); - aStrActive = " (" + ScResId(SCSTR_ACTIVE) + ")"; // " (active)" - aStrNotActive = " (" + ScResId(SCSTR_NOTACTIVE) + ")"; // " (not active)" + m_aStrActive = " (" + ScResId(SCSTR_ACTIVE) + ")"; // " (active)" + m_aStrNotActive = " (" + ScResId(SCSTR_NOTACTIVE) + ")"; // " (not active)" - rBindings.ENTERREGISTRATIONS(); + m_rBindings.ENTERREGISTRATIONS(); - mvBoundItems[0].reset(new ScNavigatorControllerItem(SID_CURRENTCELL,*this,rBindings)); - mvBoundItems[1].reset(new ScNavigatorControllerItem(SID_CURRENTTAB,*this,rBindings)); - mvBoundItems[2].reset(new ScNavigatorControllerItem(SID_CURRENTDOC,*this,rBindings)); - mvBoundItems[3].reset(new ScNavigatorControllerItem(SID_SELECT_SCENARIO,*this,rBindings)); + mvBoundItems[0].reset(new ScNavigatorControllerItem(SID_CURRENTCELL, *this, m_rBindings)); + mvBoundItems[1].reset(new ScNavigatorControllerItem(SID_CURRENTTAB, *this, m_rBindings)); + mvBoundItems[2].reset(new ScNavigatorControllerItem(SID_CURRENTDOC, *this, m_rBindings)); + mvBoundItems[3].reset(new ScNavigatorControllerItem(SID_SELECT_SCENARIO, *this, m_rBindings)); - rBindings.LEAVEREGISTRATIONS(); + m_rBindings.LEAVEREGISTRATIONS(); StartListening( *(SfxGetpApp()) ); - StartListening( rBindings ); + StartListening(m_rBindings); // was a category chosen as root? ScContentId nLastRoot = rCfg.GetRootType(); @@ -377,8 +370,8 @@ ScNavigatorDlg::ScNavigatorDlg(SfxBindings* pB, weld::Widget* pParent, SfxNaviga m_xLbEntries->hide(); m_xScenarioBox->hide(); - aContentIdle.SetInvokeHandler( LINK( this, ScNavigatorDlg, TimeHdl ) ); - aContentIdle.SetPriority( TaskPriority::LOWEST ); + m_aContentIdle.SetInvokeHandler(LINK(this, ScNavigatorDlg, TimeHdl)); + m_aContentIdle.SetPriority(TaskPriority::LOWEST); m_xLbEntries->SetNavigatorDlgFlag(true); @@ -432,14 +425,14 @@ void ScNavigatorWin::StateChanged(StateChangedType nStateChange) ScNavigatorDlg::~ScNavigatorDlg() { - aContentIdle.Stop(); + m_aContentIdle.Stop(); for (auto & p : mvBoundItems) p.reset(); moMarkArea.reset(); EndListening( *(SfxGetpApp()) ); - EndListening( rBindings ); + EndListening(m_rBindings); m_xEdCol.reset(); m_xEdRow.reset(); @@ -483,7 +476,7 @@ void ScNavigatorDlg::Notify( SfxBroadcaster&, const SfxHint& rHint ) { m_xLbEntries->ActiveDocChanged(); } - else if (NAV_LMODE_NONE == eListMode) + else if (NAV_LMODE_NONE == m_eListMode) { // Table not any more } @@ -507,7 +500,7 @@ void ScNavigatorDlg::Notify( SfxBroadcaster&, const SfxHint& rHint ) m_xLbEntries->Refresh( ScContentId::GRAPHIC ); m_xLbEntries->Refresh( ScContentId::OLEOBJECT ); m_xLbEntries->Refresh( ScContentId::DRAWING ); - aContentIdle.Start(); // Do not search notes immediately + m_aContentIdle.Start(); // Do not search notes immediately break; case SfxHintId::ScAreaLinksChanged: @@ -522,7 +515,7 @@ void ScNavigatorDlg::Notify( SfxBroadcaster&, const SfxHint& rHint ) case SfxHintId::ScDataChanged: case SfxHintId::ScAnyDataChanged: - aContentIdle.Start(); // Do not search notes immediately + m_aContentIdle.Start(); // Do not search notes immediately break; case SfxHintId::ScSelectionChanged: UpdateSelection(); @@ -536,7 +529,7 @@ void ScNavigatorDlg::Notify( SfxBroadcaster&, const SfxHint& rHint ) IMPL_LINK( ScNavigatorDlg, TimeHdl, Timer*, pIdle, void ) { - if ( pIdle != &aContentIdle ) + if (pIdle != &m_aContentIdle) return; m_xLbEntries->Refresh( ScContentId::NOTE ); @@ -544,15 +537,15 @@ IMPL_LINK( ScNavigatorDlg, TimeHdl, Timer*, pIdle, void ) void ScNavigatorDlg::SetDropMode(sal_uInt16 nNew) { - nDropMode = nNew; + m_nDropMode = nNew; UpdateButtons(); ScNavipiCfg& rCfg = ScModule::get()->GetNavipiCfg(); - rCfg.SetDragMode(nDropMode); + rCfg.SetDragMode(m_nDropMode); } void ScNavigatorDlg::SetCurrentCell( SCCOL nColNo, SCROW nRowNo ) { - if ((nColNo+1 == nCurCol) && (nRowNo+1 == nCurRow)) + if ((nColNo + 1 == m_nCurCol) && (nRowNo + 1 == m_nCurRow)) return; // SID_CURRENTCELL == Item #0 clear cache, so it's possible @@ -569,9 +562,8 @@ void ScNavigatorDlg::SetCurrentCell( SCCOL nColNo, SCROW nRowNo ) SfxStringItem aPosItem( SID_CURRENTCELL, aAddr ); SfxBoolItem aUnmarkItem( FN_PARAM_1, bUnmark ); // cancel selection - rBindings.GetDispatcher()->ExecuteList(SID_CURRENTCELL, - SfxCallMode::SYNCHRON | SfxCallMode::RECORD, - { &aPosItem, &aUnmarkItem }); + m_rBindings.GetDispatcher()->ExecuteList( + SID_CURRENTCELL, SfxCallMode::SYNCHRON | SfxCallMode::RECORD, { &aPosItem, &aUnmarkItem }); } void ScNavigatorDlg::SetCurrentCellStr( const OUString& rName ) @@ -579,20 +571,18 @@ void ScNavigatorDlg::SetCurrentCellStr( const OUString& rName ) mvBoundItems[0]->ClearCache(); SfxStringItem aNameItem( SID_CURRENTCELL, rName ); - rBindings.GetDispatcher()->ExecuteList(SID_CURRENTCELL, - SfxCallMode::SYNCHRON | SfxCallMode::RECORD, - { &aNameItem }); + m_rBindings.GetDispatcher()->ExecuteList( + SID_CURRENTCELL, SfxCallMode::SYNCHRON | SfxCallMode::RECORD, { &aNameItem }); } void ScNavigatorDlg::SetCurrentTable( SCTAB nTabNo ) { - if ( nTabNo != nCurTab ) + if (nTabNo != m_nCurTab) { // Table for basic is base-1 SfxUInt16Item aTabItem( SID_CURRENTTAB, static_cast(nTabNo) + 1 ); - rBindings.GetDispatcher()->ExecuteList(SID_CURRENTTAB, - SfxCallMode::SYNCHRON | SfxCallMode::RECORD, - { &aTabItem }); + m_rBindings.GetDispatcher()->ExecuteList( + SID_CURRENTTAB, SfxCallMode::SYNCHRON | SfxCallMode::RECORD, { &aTabItem }); } } @@ -636,17 +626,15 @@ void ScNavigatorDlg::SetCurrentTableStr( std::u16string_view rName ) void ScNavigatorDlg::SetCurrentObject( const OUString& rName ) { SfxStringItem aNameItem( SID_CURRENTOBJECT, rName ); - rBindings.GetDispatcher()->ExecuteList( SID_CURRENTOBJECT, - SfxCallMode::SYNCHRON | SfxCallMode::RECORD, - { &aNameItem }); + m_rBindings.GetDispatcher()->ExecuteList( + SID_CURRENTOBJECT, SfxCallMode::SYNCHRON | SfxCallMode::RECORD, { &aNameItem }); } void ScNavigatorDlg::SetCurrentDoc( const OUString& rDocName ) // activate { SfxStringItem aDocItem( SID_CURRENTDOC, rDocName ); - rBindings.GetDispatcher()->ExecuteList( SID_CURRENTDOC, - SfxCallMode::SYNCHRON | SfxCallMode::RECORD, - { &aDocItem }); + m_rBindings.GetDispatcher()->ExecuteList( + SID_CURRENTDOC, SfxCallMode::SYNCHRON | SfxCallMode::RECORD, { &aDocItem }); } void ScNavigatorDlg::UpdateSelection() @@ -700,34 +688,34 @@ ScViewData* ScNavigatorDlg::GetViewData() void ScNavigatorDlg::UpdateColumn( const SCCOL* pCol ) { if ( pCol ) - nCurCol = *pCol; + m_nCurCol = *pCol; else if ( ScViewData* pData = GetViewData() ) - nCurCol = pData->GetCurX() + 1; + m_nCurCol = pData->GetCurX() + 1; - m_xEdCol->set_value(nCurCol); + m_xEdCol->set_value(m_nCurCol); } void ScNavigatorDlg::UpdateRow( const SCROW* pRow ) { if ( pRow ) - nCurRow = *pRow; + m_nCurRow = *pRow; else if ( ScViewData* pData = GetViewData() ) - nCurRow = pData->GetCurY() + 1; + m_nCurRow = pData->GetCurY() + 1; - m_xEdRow->set_value(nCurRow); + m_xEdRow->set_value(m_nCurRow); } void ScNavigatorDlg::UpdateTable( const SCTAB* pTab ) { if ( pTab ) - nCurTab = *pTab; + m_nCurTab = *pTab; else if ( ScViewData* pData = GetViewData() ) - nCurTab = pData->CurrentTabForData(); + m_nCurTab = pData->CurrentTabForData(); } void ScNavigatorDlg::UpdateAll() { - switch (eListMode) + switch (m_eListMode) { case NAV_LMODE_AREAS: m_xLbEntries->Refresh(); @@ -741,22 +729,19 @@ void ScNavigatorDlg::UpdateAll() ContentUpdated(); // not again } -void ScNavigatorDlg::ContentUpdated() -{ - aContentIdle.Stop(); -} +void ScNavigatorDlg::ContentUpdated() { m_aContentIdle.Stop(); } void ScNavigatorDlg::SetListMode(NavListMode eMode) { - if (eMode != eListMode) + if (eMode != m_eListMode) { - bool bForceParentResize = ParentIsFloatingWindow(m_xNavigatorDlg) && - (eMode == NAV_LMODE_NONE || eListMode == NAV_LMODE_NONE); + bool bForceParentResize = ParentIsFloatingWindow(m_xNavigatorDlg) + && (eMode == NAV_LMODE_NONE || m_eListMode == NAV_LMODE_NONE); SfxNavigator* pNav = bForceParentResize ? m_xNavigatorDlg.get() : nullptr; if (pNav && eMode == NAV_LMODE_NONE) //save last normal size on minimizing - aExpandedSize = pNav->GetSizePixel(); + m_aExpandedSize = pNav->GetSizePixel(); - eListMode = eMode; + m_eListMode = eMode; switch (eMode) { @@ -785,7 +770,8 @@ void ScNavigatorDlg::SetListMode(NavListMode eMode) pNav->InvalidateChildSizeCache(); Size aOptimalSize(pNav->GetOptimalSize()); Size aNewSize(pNav->GetOutputSizePixel()); - aNewSize.setHeight( eMode == NAV_LMODE_NONE ? aOptimalSize.Height() : aExpandedSize.Height() ); + aNewSize.setHeight(eMode == NAV_LMODE_NONE ? aOptimalSize.Height() + : m_aExpandedSize.Height()); pNav->SetMinOutputSizePixel(aOptimalSize); pNav->SetOutputSizePixel(aNewSize); } @@ -812,8 +798,8 @@ void ScNavigatorDlg::ShowList(bool bShow) void ScNavigatorDlg::ShowScenarios() { - rBindings.Invalidate( SID_SELECT_SCENARIO ); - rBindings.Update( SID_SELECT_SCENARIO ); + m_rBindings.Invalidate(SID_SELECT_SCENARIO); + m_rBindings.Update(SID_SELECT_SCENARIO); m_xScenarioBox->show(); m_xLbDocuments->show(); @@ -837,9 +823,9 @@ void ScNavigatorDlg::GetDocNames( const OUString* pManualSel ) OUString aName = pSh->GetTitle(); OUString aEntry = aName; if (pSh == pCurrentSh) - aEntry += aStrActive; + aEntry += m_aStrActive; else - aEntry += aStrNotActive; + aEntry += m_aStrNotActive; m_xLbDocuments->append_text(aEntry); if ( pManualSel ? ( aName == *pManualSel ) @@ -850,7 +836,7 @@ void ScNavigatorDlg::GetDocNames( const OUString* pManualSel ) pSh = SfxObjectShell::GetNext( *pSh ); } - m_xLbDocuments->append_text(aStrActiveWin); + m_xLbDocuments->append_text(m_aStrActiveWin); m_xLbDocuments->thaw(); @@ -923,11 +909,11 @@ void ScNavigatorDlg::EndOfDataArea() SFX_IMPL_DOCKINGWINDOW(ScNavigatorWrapper, SID_NAVIGATOR); -ScNavigatorWrapper::ScNavigatorWrapper(vcl::Window *_pParent, sal_uInt16 nId, - SfxBindings* pBindings, SfxChildWinInfo* pInfo) +ScNavigatorWrapper::ScNavigatorWrapper(vcl::Window* _pParent, sal_uInt16 nId, + SfxBindings& rBindings, SfxChildWinInfo& rInfo) : SfxNavigatorWrapper(_pParent, nId) { - SetWindow(VclPtr::Create(pBindings, this, _pParent, pInfo)); + SetWindow(VclPtr::Create(rBindings, this, _pParent, rInfo)); Initialize(); } diff --git a/sc/source/ui/navipi/scenwnd.cxx b/sc/source/ui/navipi/scenwnd.cxx index 3b6267009820..5421a8407d04 100644 --- a/sc/source/ui/navipi/scenwnd.cxx +++ b/sc/source/ui/navipi/scenwnd.cxx @@ -29,7 +29,7 @@ #include #include #include -#include + #include #include #include diff --git a/sc/source/ui/operation/ApplyAttributesOperation.cxx b/sc/source/ui/operation/ApplyAttributesOperation.cxx new file mode 100644 index 000000000000..481a3edf1faa --- /dev/null +++ b/sc/source/ui/operation/ApplyAttributesOperation.cxx @@ -0,0 +1,262 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +ApplyAttributesOperation::ApplyAttributesOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScMarkData& rMark, + const ScPatternAttr& rPattern, bool bApi) + : Operation(OperationType::ApplyAttributes, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrMark(rMark) + , mrPattern(rPattern) +{ +} + +bool ApplyAttributesOperation::runImplementation() +{ + ScDocument& rDoc = mrDocShell.GetDocument(); + bool bRecord = true; + if (!rDoc.IsUndoEnabled()) + bRecord = false; + + ScMarkData aMark = convertMark(mrMark); + + bool bImportingXML = rDoc.IsImportingXML(); + bool bImportingXLSX = rDoc.IsImportingXLSX(); + // Cell formats can still be set if the range isn't editable only because of matrix formulas. + // #i62483# When loading XML, the check can be skipped altogether. + bool bOnlyNotBecauseOfMatrix; + if (!bImportingXML && !rDoc.IsSelectionEditable(aMark, &bOnlyNotBecauseOfMatrix) + && !bOnlyNotBecauseOfMatrix) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_PROTECTIONERR); + return false; + } + + ScDocShellModificator aModificator(mrDocShell); + + //! Border + + ScRange aMultiRange; + bool bMulti = aMark.IsMultiMarked(); + if (bMulti) + aMultiRange = aMark.GetMultiMarkArea(); + else + aMultiRange = aMark.GetMarkArea(); + + if (bRecord) + { + ScDocumentUniquePtr pUndoDoc(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab()); + rDoc.CopyToDocument(aMultiRange, InsertDeleteFlags::ATTRIB, bMulti, *pUndoDoc, &aMark); + + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aMark, aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), + aMultiRange.aStart.Tab(), aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), + aMultiRange.aEnd.Tab(), std::move(pUndoDoc), bMulti, &mrPattern)); + } + + // While loading XML it is not necessary to ask HasAttrib. It needs too much time. + sal_uInt16 nExtFlags = 0; + if (!bImportingXML && !bImportingXLSX) + mrDocShell.UpdatePaintExt(nExtFlags, aMultiRange); // content before the change + + bool bChanged = false; + rDoc.ApplySelectionPattern(mrPattern, aMark, nullptr, &bChanged); + + if (bChanged) + { + if (!bImportingXML && !bImportingXLSX) + mrDocShell.UpdatePaintExt(nExtFlags, aMultiRange); // content after the change + + if (!mrDocFunc.AdjustRowHeight(aMultiRange, true, mbApi)) + mrDocShell.PostPaint(aMultiRange, PaintPartFlags::Grid, nExtFlags); + else if (nExtFlags & SC_PF_LINES) + ScDocFunc::PaintAbove(mrDocShell, aMultiRange); // because of lines above the range + + syncMarkPatternToSheetViews(aMark, mrPattern); + aModificator.SetDocumentModified(); + } + + return true; +} + +ApplyAttributesWithChangedRangeOperation::ApplyAttributesWithChangedRangeOperation( + ScDocShell& rDocShell, const ScMarkData& rMark, bool bMultiMarked, + const ScPatternAttr& rPattern, sal_uInt16 nExtFlags, bool bApi) + : Operation(OperationType::ApplyAttributesWithChangedRange, true, bApi) + , mrDocShell(rDocShell) + , mrMark(rMark) + , mrPattern(rPattern) + , mbMultiMarked(bMultiMarked) + , mnExtFlags(nExtFlags) +{ +} + +bool ApplyAttributesWithChangedRangeOperation::runImplementation() +{ + ScDocument& rDoc = mrDocShell.GetDocument(); + + ScViewData* pViewData = ScDocShell::GetViewData(); + if (!pViewData) + return false; + + bool bRecord = mbRecord; + if (!rDoc.IsUndoEnabled()) + bRecord = false; + + ScMarkData aMark = convertMark(mrMark); + + ScDocShellModificator aModificator(mrDocShell); + + const ScRange& aMarkRange = aMark.GetMultiMarkArea(); + SCTAB nTabCount = rDoc.GetTableCount(); + for (const auto& rTab : aMark) + { + ScRange aChangeRange(aMarkRange); + aChangeRange.aStart.SetTab(rTab); + aChangeRange.aEnd.SetTab(rTab); + maChangeRanges.push_back(aChangeRange); + } + + SCCOL nStartCol = aMarkRange.aStart.Col(); + SCROW nStartRow = aMarkRange.aStart.Row(); + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCCOL nEndCol = aMarkRange.aEnd.Col(); + SCROW nEndRow = aMarkRange.aEnd.Row(); + SCTAB nEndTab = aMarkRange.aEnd.Tab(); + + ScEditDataArray* pEditDataArray = nullptr; + if (bRecord) + { + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount - 1); + + ScDocumentUniquePtr pUndoDoc(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nStartTab, nStartTab); + for (const auto& rTab : aMark) + if (rTab != nStartTab) + pUndoDoc->AddUndoTab(rTab, rTab); + rDoc.CopyToDocument(aCopyRange, InsertDeleteFlags::ATTRIB, mbMultiMarked, *pUndoDoc, + &aMark); + + aMark.MarkToMulti(); + + ScUndoSelectionAttr* pUndoAttr = new ScUndoSelectionAttr( + mrDocShell, aMark, nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, + std::move(pUndoDoc), mbMultiMarked, &mrPattern); + mrDocShell.GetUndoManager()->AddUndoAction(std::unique_ptr(pUndoAttr)); + pEditDataArray = pUndoAttr->GetDataArray(); + } + + rDoc.ApplySelectionPattern(mrPattern, aMark, pEditDataArray); + + syncMarkPatternToSheetViews(aMark, mrPattern); + + mrDocShell.PostPaint(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, + PaintPartFlags::Grid, mnExtFlags | SC_PF_TESTMERGE); + mrDocShell.UpdateOle(*pViewData); + + aModificator.SetDocumentModified(); + + return true; +} + +ApplyAttributesToCellOperation::ApplyAttributesToCellOperation(ScDocShell& rDocShell, + ScAddress const& rPosition, + const ScPatternAttr& rPattern, + sal_uInt16 nExtFlags, bool bApi) + : Operation(OperationType::ApplyAttributesToCell, true, bApi) + , mrDocShell(rDocShell) + , mrPosition(rPosition) + , mrPattern(rPattern) + , mnExtFlags(nExtFlags) +{ +} +bool ApplyAttributesToCellOperation::runImplementation() +{ + ScDocument& rDoc = mrDocShell.GetDocument(); + + ScViewData* pViewData = ScDocShell::GetViewData(); + if (!pViewData) + return false; + + bool bRecord = mbRecord; + if (!rDoc.IsUndoEnabled()) + bRecord = false; + + ScAddress aPosition = convertAddress(mrPosition); + + ScDocShellModificator aModificator(mrDocShell); + + SCCOL nCol = aPosition.Col(); + SCROW nRow = aPosition.Row(); + SCTAB nTab = aPosition.Tab(); + + std::unique_ptr pOldEditData; + std::unique_ptr pNewEditData; + + ScRefCellValue aCell(rDoc, aPosition); + if (aCell.getType() == CELLTYPE_EDIT) + { + const EditTextObject* pEditObj = aCell.getEditText(); + pOldEditData = std::make_unique(*pEditObj); + rDoc.RemoveEditTextCharAttribs(aPosition, mrPattern); + pEditObj = rDoc.GetEditText(aPosition); + pNewEditData = std::make_unique(*pEditObj); + } + + maChangeRanges.push_back(ScRange(aPosition)); + std::optional pOldPat(*rDoc.GetPattern(nCol, nRow, nTab)); + + rDoc.ApplyPattern(nCol, nRow, nTab, mrPattern); + + const ScPatternAttr* pNewPat = rDoc.GetPattern(nCol, nRow, nTab); + + if (bRecord) + { + std::unique_ptr pUndo( + new ScUndoCursorAttr(mrDocShell, nCol, nRow, nTab, &*pOldPat, pNewPat, &mrPattern)); + pUndo->SetEditData(std::move(pOldEditData), std::move(pNewEditData)); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); + } + pOldPat.reset(); // is copied in undo (Pool) + + syncCellPatternToSheetViews(aPosition, mrPattern); + + mrDocShell.PostPaint(nCol, nRow, nTab, nCol, nRow, nTab, PaintPartFlags::Grid, + mnExtFlags | SC_PF_TESTMERGE); + mrDocShell.UpdateOle(*pViewData); + aModificator.SetDocumentModified(); + + return true; +} + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/AutoFormatOperation.cxx b/sc/source/ui/operation/AutoFormatOperation.cxx new file mode 100644 index 000000000000..b0a94e730a06 --- /dev/null +++ b/sc/source/ui/operation/AutoFormatOperation.cxx @@ -0,0 +1,182 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define AUTOFORMAT_WARN_SIZE 0x10ffffUL + +namespace sc +{ +AutoFormatOperation::AutoFormatOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScRange& rRange, const ScMarkData* pTabMark, + sal_uInt16 nFormatNo, bool bApi) + : Operation(OperationType::AutoFormat, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , maRange(rRange) + , mpTabMark(pTabMark) + , mnFormatNo(nFormatNo) +{ +} + +bool AutoFormatOperation::canRunTheOperation() const +{ + return !isInputOnSheetViewAutoFilter(maRange); +} + +bool AutoFormatOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + + ScRange aRange = convertRange(maRange); + SCCOL nStartCol = aRange.aStart.Col(); + SCROW nStartRow = aRange.aStart.Row(); + SCTAB nStartTab = aRange.aStart.Tab(); + SCCOL nEndCol = aRange.aEnd.Col(); + SCROW nEndRow = aRange.aEnd.Row(); + SCTAB nEndTab = aRange.aEnd.Tab(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScMarkData aMark(rDoc.GetSheetLimits()); + if (mpTabMark) + aMark = *mpTabMark; + else + { + for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++) + aMark.SelectTable(nTab, true); + } + + ScAutoFormat* pAutoFormat = ScGlobal::GetOrCreateAutoFormat(); + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock( + rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); + if (mnFormatNo < pAutoFormat->size() && aTester.IsEditable()) + { + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + bool bSize = pAutoFormat->GetData(mnFormatNo)->IsWidthHeight(); + if (sal_uInt64(nEndCol - nStartCol + 1) * sal_uInt64(nEndRow - nStartRow + 1) + > AUTOFORMAT_WARN_SIZE) + { + std::unique_ptr xQueryBox(Application::CreateMessageDialog( + ScDocShell::GetActiveDialogParent(), VclMessageType::Warning, VclButtonsType::YesNo, + ScResId(STR_AUTOFORMAT_WAIT_WARNING))); + xQueryBox->set_default_response(RET_NO); + if (xQueryBox->run() != RET_YES) + return false; + } + + SCTAB nTabCount = rDoc.GetTableCount(); + ScDocumentUniquePtr pUndoDoc; + if (mbRecord) + { + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nStartTab, nStartTab, bSize, bSize); + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + if (rTab != nStartTab) + pUndoDoc->AddUndoTab(rTab, rTab, bSize, bSize); + } + + ScRange aCopyRange = aRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aStart.SetTab(nTabCount - 1); + rDoc.CopyToDocument(aCopyRange, InsertDeleteFlags::ATTRIB, false, *pUndoDoc, &aMark); + if (bSize) + { + rDoc.CopyToDocument(nStartCol, 0, 0, nEndCol, rDoc.MaxRow(), nTabCount - 1, + InsertDeleteFlags::NONE, false, *pUndoDoc, &aMark); + rDoc.CopyToDocument(0, nStartRow, 0, rDoc.MaxCol(), nEndRow, nTabCount - 1, + InsertDeleteFlags::NONE, false, *pUndoDoc, &aMark); + } + rDoc.BeginDrawUndo(); + } + + rDoc.AutoFormat(nStartCol, nStartRow, nEndCol, nEndRow, mnFormatNo, aMark); + + if (bSize) + { + std::vector aCols(1, sc::ColRowSpan(nStartCol, nEndCol)); + std::vector aRows(1, sc::ColRowSpan(nStartRow, nEndRow)); + + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + mrDocFunc.SetWidthOrHeight(true, aCols, rTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, + false, true); + mrDocFunc.SetWidthOrHeight(false, aRows, rTab, SC_SIZE_VISOPT, 0, false, false); + mrDocShell.PostPaint(0, 0, rTab, rDoc.MaxCol(), rDoc.MaxRow(), rTab, + PaintPartFlags::Grid | PaintPartFlags::Left + | PaintPartFlags::Top); + } + } + else + { + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + bool bAdj = mrDocFunc.AdjustRowHeight( + ScRange(nStartCol, nStartRow, rTab, nEndCol, nEndRow, rTab), false, mbApi); + if (bAdj) + mrDocShell.PostPaint(0, nStartRow, rTab, rDoc.MaxCol(), rDoc.MaxRow(), rTab, + PaintPartFlags::Grid | PaintPartFlags::Left); + else + mrDocShell.PostPaint(nStartCol, nStartRow, rTab, nEndCol, nEndRow, rTab, + PaintPartFlags::Grid); + } + } + + if (mbRecord) // only now is Draw-Undo available + { + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aRange, std::move(pUndoDoc), aMark, bSize, mnFormatNo)); + } + + syncSheetViews(); + + aModificator.SetDocumentModified(); + return true; + } + else if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + + return false; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/ChangeIndentOperation.cxx b/sc/source/ui/operation/ChangeIndentOperation.cxx new file mode 100644 index 000000000000..27048c2ee862 --- /dev/null +++ b/sc/source/ui/operation/ChangeIndentOperation.cxx @@ -0,0 +1,110 @@ +/* -*- 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 + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace sc +{ +ChangeIndentOperation::ChangeIndentOperation(ScDocShell& rDocShell, const ScMarkData& rMark, + bool bIncrement, bool bApi) + : Operation(OperationType::ChangeIndent, false, bApi) + , mrDocShell(rDocShell) + , mrMark(rMark) + , mbIncrement(bIncrement) +{ +} + +bool ChangeIndentOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + bool bUndo(rDoc.IsUndoEnabled()); + + ScMarkData aMark = convertMark(mrMark); + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, aMark); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + const ScRange& aMarkRange = aMark.GetMultiMarkArea(); + + if (bUndo) + { + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCTAB nTabCount = rDoc.GetTableCount(); + + ScDocumentUniquePtr pUndoDoc(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nStartTab, nStartTab); + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + if (rTab != nStartTab) + pUndoDoc->AddUndoTab(rTab, rTab); + } + + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount - 1); + rDoc.CopyToDocument(aCopyRange, InsertDeleteFlags::ATTRIB, true, *pUndoDoc, &aMark); + + mrDocShell.GetUndoManager()->AddUndoAction( + std::make_unique(mrDocShell, aMark, std::move(pUndoDoc), mbIncrement)); + } + + rDoc.ChangeSelectionIndent(mbIncrement, aMark); + + syncSheetViews(); + + mrDocShell.PostPaint(aMarkRange, PaintPartFlags::Grid, SC_PF_LINES | SC_PF_TESTMERGE); + aModificator.SetDocumentModified(); + + SfxBindings* pBindings = mrDocShell.GetViewBindings(); + if (pBindings) + { + pBindings->Invalidate(SID_ALIGNLEFT); + pBindings->Invalidate(SID_ALIGNRIGHT); + pBindings->Invalidate(SID_ALIGNBLOCK); + pBindings->Invalidate(SID_ALIGNCENTERHOR); + pBindings->Invalidate(SID_ATTR_LRSPACE); + pBindings->Invalidate(SID_ATTR_PARA_ADJUST_LEFT); + pBindings->Invalidate(SID_ATTR_PARA_ADJUST_RIGHT); + pBindings->Invalidate(SID_ATTR_PARA_ADJUST_BLOCK); + pBindings->Invalidate(SID_ATTR_PARA_ADJUST_CENTER); + // pseudo slots for Format menu + pBindings->Invalidate(SID_ALIGN_ANY_HDEFAULT); + pBindings->Invalidate(SID_ALIGN_ANY_LEFT); + pBindings->Invalidate(SID_ALIGN_ANY_HCENTER); + pBindings->Invalidate(SID_ALIGN_ANY_RIGHT); + pBindings->Invalidate(SID_ALIGN_ANY_JUSTIFIED); + } + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/ChangeSparklineGroupAttributesOperation.cxx b/sc/source/ui/operation/ChangeSparklineGroupAttributesOperation.cxx new file mode 100644 index 000000000000..592cbcb2d61a --- /dev/null +++ b/sc/source/ui/operation/ChangeSparklineGroupAttributesOperation.cxx @@ -0,0 +1,42 @@ +/* -*- 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 + +#include +#include +#include + +namespace sc +{ +ChangeSparklineGroupAttributesOperation::ChangeSparklineGroupAttributesOperation( + ScDocShell& rDocShell, std::shared_ptr const& pExistingSparklineGroup, + SparklineAttributes const& rNewAttributes) + : Operation(OperationType::SparklineGroupChange, false, false) + , mrDocShell(rDocShell) + , mpExistingSparklineGroup(pExistingSparklineGroup) + , maNewAttributes(rNewAttributes) +{ +} + +bool ChangeSparklineGroupAttributesOperation::runImplementation() +{ + auto pUndo = std::make_unique(mrDocShell, mpExistingSparklineGroup, + maNewAttributes); + // change sparkline group attributes by "redoing" + pUndo->Redo(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); + + syncSheetViews(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/ChangeSparklineOperation.cxx b/sc/source/ui/operation/ChangeSparklineOperation.cxx new file mode 100644 index 000000000000..59013386a2eb --- /dev/null +++ b/sc/source/ui/operation/ChangeSparklineOperation.cxx @@ -0,0 +1,45 @@ +/* -*- 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 + +#include +#include +#include + +namespace sc +{ +ChangeSparklineOperation::ChangeSparklineOperation(ScDocShell& rDocShell, + std::shared_ptr const& rpSparkline, + SCTAB nTab, ScRangeList const& rDataRange) + : Operation(OperationType::SparklineChange, false, false) + , mrDocShell(rDocShell) + , mpSparkline(rpSparkline) + , mnTab(nTab) + , maDataRange(rDataRange) +{ +} + +bool ChangeSparklineOperation::runImplementation() +{ + SCTAB nTab = convertTab(mnTab); + ScRangeList aDataRange = convertRangeList(maDataRange); + + auto pUndo = std::make_unique(mrDocShell, mpSparkline, nTab, aDataRange); + // change sparkline by "redoing" + pUndo->Redo(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); + + syncSheetViews(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/ClearItemsOperation.cxx b/sc/source/ui/operation/ClearItemsOperation.cxx new file mode 100644 index 000000000000..e161b901ec11 --- /dev/null +++ b/sc/source/ui/operation/ClearItemsOperation.cxx @@ -0,0 +1,78 @@ +/* -*- 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 + +#include +#include +#include +#include + +#include + +namespace sc +{ +ClearItemsOperation::ClearItemsOperation(ScDocShell& rDocShell, const ScMarkData& rMark, + const sal_uInt16* pWhich, bool bApi) + : Operation(OperationType::ClearItems, false, bApi) + , mrDocShell(rDocShell) + , mrMark(rMark) + , mpWhich(pWhich) +{ +} + +bool ClearItemsOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + bool bUndo(rDoc.IsUndoEnabled()); + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, mrMark); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached + // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems + // here. + + ScMarkData aMultiMark = convertMark(mrMark); + aMultiMark.SetMarking(false); // for MarkToMulti + aMultiMark.MarkToMulti(); + const ScRange& aMarkRange = aMultiMark.GetMultiMarkArea(); + + if (bUndo) + { + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCTAB nEndTab = aMarkRange.aEnd.Tab(); + + ScDocumentUniquePtr pUndoDoc(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nStartTab, nEndTab); + rDoc.CopyToDocument(aMarkRange, InsertDeleteFlags::ATTRIB, true, *pUndoDoc, &aMultiMark); + + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aMultiMark, std::move(pUndoDoc), mpWhich)); + } + + rDoc.ClearSelectionItems(mpWhich, aMultiMark); + + syncSheetViews(); + + mrDocShell.PostPaint(aMarkRange, PaintPartFlags::Grid, SC_PF_LINES | SC_PF_TESTMERGE); + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/ConvertFormulaToValueOperation.cxx b/sc/source/ui/operation/ConvertFormulaToValueOperation.cxx new file mode 100644 index 000000000000..62cd5b935c2e --- /dev/null +++ b/sc/source/ui/operation/ConvertFormulaToValueOperation.cxx @@ -0,0 +1,72 @@ +/* -*- 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 + +#include +#include +#include +#include + +namespace sc +{ +ConvertFormulaToValueOperation::ConvertFormulaToValueOperation(ScDocShell& rDocShell, + const ScRange& rRange, + bool bInteraction) + : Operation(OperationType::ConvertFormulaToValue, true, !bInteraction) + , mrDocShell(rDocShell) + , maRange(rRange) +{ +} + +bool ConvertFormulaToValueOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScRange aRange = convertRange(maRange); + + ScEditableTester aTester + = ScEditableTester::CreateAndTestRange(rDoc, aRange, sc::EditAction::Unknown); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + sc::TableValues aUndoVals(aRange); + sc::TableValues* pUndoVals = mbRecord ? &aUndoVals : nullptr; + + // A formula that nothing has read since its last change has no result to convert yet + rDoc.InterpretCellsIfNeeded(ScRangeList(aRange)); + + rDoc.ConvertFormulaToValue(aRange, pUndoVals); + + if (mbRecord && pUndoVals) + { + mrDocShell.GetUndoManager()->AddUndoAction( + std::make_unique(mrDocShell, *pUndoVals)); + } + + syncSheetViews(); + + mrDocShell.PostPaint(aRange, PaintPartFlags::Grid); + mrDocShell.PostDataChanged(); + rDoc.BroadcastCells(aRange, SfxHintId::ScDataChanged); + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/CreatePivotTableOperation.cxx b/sc/source/ui/operation/CreatePivotTableOperation.cxx new file mode 100644 index 000000000000..35d05ba2c6b6 --- /dev/null +++ b/sc/source/ui/operation/CreatePivotTableOperation.cxx @@ -0,0 +1,138 @@ +/* -*- 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 +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace sc +{ +CreatePivotTableOperation::CreatePivotTableOperation(ScDocShell& rDocShell, + ScDPObject const& rDPObject, bool bRecord, + bool bApi) + : PivotTableOperation(OperationType::PivotTableCreate, rDocShell, bRecord, bApi) + , mrDPObject(rDPObject) +{ +} + +bool CreatePivotTableOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + // At least one cell in the output range should be editable. Check in advance. + ScDocument& rDoc = mrDocShell.GetDocument(); + auto aOutputStartRange = convertRange(ScRange(mrDPObject.GetOutRange().aStart)); + if (!rDoc.IsImportingXML() && !sc::pivot::isEditable(mrDocShell, aOutputStartRange, mbApi)) + { + return false; + } + + ScDocumentUniquePtr pNewUndoDoc; + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + // output range must be set at pNewObject + std::unique_ptr pDestObject(new ScDPObject(mrDPObject)); + + ScDPObject& rDestObject = *pDestObject; + + // Convert ranges from sheet view to default view + convertDPObjectRanges(rDestObject); + + // #i94570# When changing the output position in the dialog, a new table is created + // with the settings from the old table, including the name. + // So we have to check for duplicate names here (before inserting). + if (rDoc.GetDPCollection()->GetByName(rDestObject.GetName())) + rDestObject.SetName(OUString()); // ignore the invalid name, create a new name below + + // Synchronize groups between linked tables + { + const ScDPDimensionSaveData* pGroups = nullptr; + bool bRefFound = rDoc.GetDPCollection()->GetReferenceGroups(rDestObject, &pGroups); + if (bRefFound) + { + ScDPSaveData* pSaveData = rDestObject.GetSaveData(); + if (pSaveData) + pSaveData->SetDimensionData(pGroups); + } + } + + rDoc.GetDPCollection()->InsertNewTable(std::move(pDestObject)); + + rDestObject.ReloadGroupTableData(); + rDestObject.SyncAllDimensionMembers(); + rDestObject.InvalidateData(); // before getting the new output area + + // make sure the table has a name (not set by dialog) + if (rDestObject.GetName().isEmpty()) + rDestObject.SetName(rDoc.GetDPCollection()->CreateNewName()); + + bool bOverflow = false; + ScRange aNewOut = rDestObject.GetNewOutputRange(bOverflow); + + if (bOverflow) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_PIVOT_ERROR); + + return false; + } + + if (!rDoc.IsImportingXML()) + { + ScEditableTester aTester + = ScEditableTester::CreateAndTestRange(rDoc, aNewOut, sc::EditAction::Unknown); + if (!aTester.IsEditable()) + { + // destination area isn't editable + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + + return false; + } + } + + if (mbRecord) + sc::pivot::createUndoDoc(pNewUndoDoc, rDoc, aNewOut); + + // Use spill checking output if the destination range has non-empty cells, + // write #SPILL! into the origin cell instead of overwriting. + // Skip the spill check during XML import + rDestObject.Output(aNewOut.aStart, !rDoc.IsImportingXML()); + mrDocShell.PostPaintGridAll(); + + if (mbRecord) + { + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, nullptr, std::move(pNewUndoDoc), nullptr, &rDestObject, false)); + } + + syncSheetViews(); + + // notify API objects + rDoc.BroadcastUno(ScDataPilotModifiedHint(rDestObject.GetName())); + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/DataPilotUpdateOperation.cxx b/sc/source/ui/operation/DataPilotUpdateOperation.cxx new file mode 100644 index 000000000000..dcd79b68a832 --- /dev/null +++ b/sc/source/ui/operation/DataPilotUpdateOperation.cxx @@ -0,0 +1,157 @@ +/* -*- 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace sc +{ +DataPilotUpdateOperation::DataPilotUpdateOperation(ScDocShell& rDocShell, ScDPObject* pOldObj, + ScDPObject const* pNewObj, bool bRecord, + bool bApi, bool bAllowMove) + : Operation(OperationType::PivotTableUpdate, bRecord, bApi) + , mrDocShell(rDocShell) + , mpOldObj(pOldObj) + , mpNewObj(pNewObj) + , mbAllowMove(bAllowMove) +{ +} + +bool DataPilotUpdateOperation::runImplementation() +{ + // Delegate certain to sub-operations. Probably we need to find a better way how to do this. + + if (!mpOldObj) + { + if (!mpNewObj) + return false; + + CreatePivotTableOperation aOperation(mrDocShell, *mpNewObj, mbRecord, mbApi); + return aOperation.run(); + } + + if (!mpNewObj) + { + RemovePivotTableOperation aOperation(mrDocShell, *mpOldObj, mbRecord, mbApi); + return aOperation.run(); + } + + if (mpOldObj == mpNewObj) + { + UpdatePivotTableOperation aOperation(mrDocShell, *mpOldObj, mbRecord, mbApi); + return aOperation.run(); + } + + OSL_ASSERT(mpOldObj && mpNewObj && mpOldObj != mpNewObj); + + ScDocShellModificator aModificator(mrDocShell); + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + ScRangeList aRanges; + aRanges.push_back(mpOldObj->GetOutRange()); + aRanges.push_back( + ScRange(mpNewObj->GetOutRange() + .aStart)); // at least one cell in the output position must be editable. + + if (!checkSheetViewProtection()) + return false; + + if (!sc::pivot::isEditable(mrDocShell, aRanges, mbApi)) + return false; + + ScDocumentUniquePtr pOldUndoDoc; + ScDocumentUniquePtr pNewUndoDoc; + + ScDPObject aUndoDPObj(*mpOldObj); // for undo or revert on failure + + ScDocument& rDoc = mrDocShell.GetDocument(); + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + if (mbRecord) + sc::pivot::createUndoDoc(pOldUndoDoc, rDoc, mpOldObj->GetOutRange()); + + mpNewObj->WriteSourceDataTo(*mpOldObj); // copy source data + + ScDPSaveData* pData = mpNewObj->GetSaveData(); + OSL_ENSURE(pData, "no SaveData from living DPObject"); + if (pData) + mpOldObj->SetSaveData(*pData); // copy SaveData + + mpOldObj->SetAllowMove(mbAllowMove); + mpOldObj->ReloadGroupTableData(); + mpOldObj->SyncAllDimensionMembers(); + mpOldObj->InvalidateData(); // before getting the new output area + + // make sure the table has a name (not set by dialog) + if (mpOldObj->GetName().isEmpty()) + mpOldObj->SetName(rDoc.GetDPCollection()->CreateNewName()); + + ScRange aNewOut; + if (!sc::pivot::checkNewOutputRange(*mpOldObj, mrDocShell, aNewOut, mbApi)) + { + *mpOldObj = aUndoDPObj; + return false; + } + + // test if new output area is empty except for old area + if (!mbApi) + { + // OutRange of mpOldObj (pDestObj) is still old area + if (!sc::pivot::lcl_EmptyExcept(rDoc, aNewOut, mpOldObj->GetOutRange())) + { + std::unique_ptr xQueryBox(Application::CreateMessageDialog( + ScDocShell::GetActiveDialogParent(), VclMessageType::Question, + VclButtonsType::YesNo, ScResId(STR_PIVOT_NOTEMPTY))); + xQueryBox->set_default_response(RET_YES); + if (xQueryBox->run() == RET_NO) + { + //! like above (not editable) + *mpOldObj = aUndoDPObj; + return false; + } + } + } + + if (mbRecord) + sc::pivot::createUndoDoc(pNewUndoDoc, rDoc, aNewOut); + + mpOldObj->Output(aNewOut.aStart); + mrDocShell.PostPaintGridAll(); //! only necessary parts + + if (mbRecord) + { + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObj, mpOldObj, + mbAllowMove)); + } + + // notify API objects + rDoc.BroadcastUno(ScDataPilotModifiedHint(mpOldObj->GetName())); + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/DeleteCellOperation.cxx b/sc/source/ui/operation/DeleteCellOperation.cxx new file mode 100644 index 000000000000..dcb6ead32634 --- /dev/null +++ b/sc/source/ui/operation/DeleteCellOperation.cxx @@ -0,0 +1,118 @@ +/* -*- 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 + +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +DeleteCellOperation::DeleteCellOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + ScAddress const& rPosition, const ScMarkData& rMark, + InsertDeleteFlags nFlags, bool bRecord, bool bApi) + : Operation(OperationType::DeleteCell, bRecord, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrPosition(rPosition) + , mrMark(rMark) + , mnFlags(nFlags) +{ +} + +bool DeleteCellOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + // Convert taking sheet view sorting into account + ScAddress aPosition = convertAddress(mrPosition); + ScMarkData aMarkData = convertMark(mrMark); + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock( + rDoc, aPosition.Col(), aPosition.Row(), aPosition.Col(), aPosition.Row(), aMarkData); + if (!aTester.IsEditable()) + { + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + // no objects on protected tabs + bool bObjects = (mnFlags & InsertDeleteFlags::OBJECTS) + && !sc::DocFuncUtil::hasProtectedTab(rDoc, aMarkData); + + sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted + if (mnFlags & InsertDeleteFlags::ATTRIB) + mrDocShell.UpdatePaintExt(nExtFlags, ScRange(aPosition)); + + // order of operations: + // 1) BeginDrawUndo + // 2) delete objects (DrawUndo is filled) + // 3) copy contents for undo + // 4) delete contents + // 5) add undo-action + + bool bDrawUndo = bObjects || (mnFlags & InsertDeleteFlags::NOTE); // needed for shown notes + if (bDrawUndo && mbRecord) + rDoc.BeginDrawUndo(); + + if (bObjects) + rDoc.DeleteObjectsInArea(aPosition.Col(), aPosition.Row(), aPosition.Col(), aPosition.Row(), + aMarkData); + + // To keep track of all non-empty cells within the deleted area. + std::shared_ptr pDataSpans; + + ScDocumentUniquePtr pUndoDoc; + std::vector aRestoreExpandedMatrices; + if (mbRecord) + { + pUndoDoc = sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc, aMarkData, ScRange(aPosition), + mnFlags, false); + pDataSpans = sc::DocFuncUtil::getNonEmptyCellSpans(rDoc, aMarkData, ScRange(aPosition)); + aRestoreExpandedMatrices + = rDoc.CollectExpandedDynamicArraysInRange(aMarkData, ScRange(aPosition)); + } + + tools::Long nBefore(mrDocShell.GetTwipWidthHint(aPosition)); + rDoc.DeleteArea(aPosition.Col(), aPosition.Row(), aPosition.Col(), aPosition.Row(), aMarkData, + mnFlags); + + if (mbRecord) + { + sc::DocFuncUtil::addDeleteContentsUndo( + mrDocShell.GetUndoManager(), mrDocShell, aMarkData, ScRange(aPosition), + std::move(pUndoDoc), mnFlags, pDataSpans, false, bDrawUndo, aRestoreExpandedMatrices); + } + + if (!mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi)) + mrDocShell.PostPaint(aPosition.Col(), aPosition.Row(), aPosition.Tab(), aPosition.Col(), + aPosition.Row(), aPosition.Tab(), PaintPartFlags::Grid, nExtFlags, + nBefore); + + syncSheetViews(); + + aModificator.SetDocumentModified(); + + mrDocShell.ResolveSpilledOutputs(); + + return true; +} +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/DeleteCellsOperation.cxx b/sc/source/ui/operation/DeleteCellsOperation.cxx new file mode 100644 index 000000000000..98b1e6834595 --- /dev/null +++ b/sc/source/ui/operation/DeleteCellsOperation.cxx @@ -0,0 +1,808 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace +{ +/** + * Check if this deletion attempt would end up cutting one or more pivot + * tables in half, which is not desirable. + * + * @return true if this deletion can be done safely without shearing any + * existing pivot tables, false otherwise. + */ +bool canDeleteCellsByPivot(const ScRange& rRange, const ScMarkData& rMarkData, DelCellCmd eCmd, + const ScDocument& rDoc) +{ + if (!rDoc.HasPivotTable()) + // This document has no pivot tables. + return true; + + const ScDPCollection* pDPs = rDoc.GetDPCollection(); + + ScRange aRange(rRange); // local copy + + switch (eCmd) + { + case DelCellCmd::Rows: + { + aRange.aStart.SetCol(0); + aRange.aEnd.SetCol(rDoc.MaxCol()); + [[fallthrough]]; + } + case DelCellCmd::CellsUp: + { + auto bIntersects = std::ranges::any_of(rMarkData, [&pDPs, &aRange](const SCTAB& rTab) { + return pDPs->IntersectsTableByColumns(aRange.aStart.Col(), aRange.aEnd.Col(), + aRange.aStart.Row(), rTab); + }); + if (bIntersects) + // This column range cuts through at least one pivot table. Not good. + return false; + + ScRange aTest(aRange); + for (const auto& rTab : rMarkData) + { + aTest.aStart.SetTab(rTab); + aTest.aEnd.SetTab(rTab); + if (pDPs->HasTable(aTest)) + return false; + } + } + break; + case DelCellCmd::Cols: + { + aRange.aStart.SetRow(0); + aRange.aEnd.SetRow(rDoc.MaxRow()); + [[fallthrough]]; + } + case DelCellCmd::CellsLeft: + { + auto bIntersects = std::ranges::any_of(rMarkData, [&pDPs, &aRange](const SCTAB& rTab) { + return pDPs->IntersectsTableByRows(aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Row(), rTab); + }); + if (bIntersects) + // This column range cuts through at least one pivot table. Not good. + return false; + + ScRange aTest(aRange); + for (const auto& rTab : rMarkData) + { + aTest.aStart.SetTab(rTab); + aTest.aEnd.SetTab(rTab); + if (pDPs->HasTable(aTest)) + return false; + } + } + break; + default:; + } + return true; +} + +} // anonymous namespace + +namespace sc +{ +DeleteCellsOperation::DeleteCellsOperation(ScDocShell& rDocShell, ScRange const& rRange, + ScMarkData const* pTabMark, DelCellCmd eCmd, bool bApi) + : Operation(toOperationType(eCmd), true, bApi) + , mrDocShell(rDocShell) + , maRange(rRange) + , mpTabMark(pTabMark) + , meCmd(eCmd) +{ +} + +OperationType DeleteCellsOperation::toOperationType(DelCellCmd eCmd) +{ + switch (eCmd) + { + case DelCellCmd::Cols: + return OperationType::DeleteColumns; + case DelCellCmd::Rows: + return OperationType::DeleteRows; + case DelCellCmd::CellsLeft: + return OperationType::DeleteCellsLeft; + case DelCellCmd::CellsUp: + return OperationType::DeleteCellsUp; + default: + return OperationType::Unknown; + } +} + +bool DeleteCellsOperation::canRunTheOperation() const +{ + return !isInputOnSheetViewAutoFilter(maRange); +} + +bool DeleteCellsOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + + if (rDoc.GetChangeTrack() + && ((meCmd == DelCellCmd::CellsUp + && (maRange.aStart.Col() != 0 || maRange.aEnd.Col() != rDoc.MaxCol())) + || (meCmd == DelCellCmd::CellsLeft + && (maRange.aStart.Row() != 0 || maRange.aEnd.Row() != rDoc.MaxRow())))) + { + // We should not reach this via UI disabled slots. + assert(mbApi); + SAL_WARN("sc.ui", "ScDocFunc::DeleteCells - no change-tracking of partial cell shift"); + return false; + } + + SCCOL nStartCol = maRange.aStart.Col(); + SCROW nStartRow = maRange.aStart.Row(); + SCTAB nStartTab = maRange.aStart.Tab(); + SCCOL nEndCol = maRange.aEnd.Col(); + SCROW nEndRow = maRange.aEnd.Row(); + SCTAB nEndTab = maRange.aEnd.Tab(); + + if (!rDoc.ValidRow(nStartRow) || !rDoc.ValidRow(nEndRow)) + { + OSL_FAIL("invalid row in DeleteCells"); + return false; + } + + SCTAB nTabCount = rDoc.GetTableCount(); + SCCOL nPaintStartCol = nStartCol; + SCROW nPaintStartRow = nStartRow; + SCCOL nPaintEndCol = nEndCol; + SCROW nPaintEndRow = nEndRow; + PaintPartFlags nPaintFlags = PaintPartFlags::Grid; + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScMarkData aMark(rDoc.GetSheetLimits()); + if (mpTabMark) + aMark = *mpTabMark; + else + { + SCTAB nCount = 0; + for (SCTAB i = 0; i < nTabCount; i++) + { + if (!rDoc.IsScenario(i)) + { + nCount++; + if (nCount == nEndTab + 1) + { + aMark.SelectTable(i, true); + break; + } + } + } + } + + ScMarkData aFullMark(aMark); // including scenario sheets + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + for (SCTAB j = rTab + 1; j < nTabCount && rDoc.IsScenario(j); j++) + aFullMark.SelectTable(j, true); + } + + SCTAB nSelCount = aMark.GetSelectCount(); + + SCCOL nUndoStartCol = nStartCol; + SCROW nUndoStartRow = nStartRow; + SCCOL nUndoEndCol = nEndCol; + SCROW nUndoEndRow = nEndRow; + + ScRange aExtendMergeRange(maRange); + + if (maRange.aStart == maRange.aEnd && rDoc.HasAttrib(maRange, HasAttrFlags::Merged)) + { + rDoc.ExtendMerge(aExtendMergeRange); + rDoc.ExtendOverlapped(aExtendMergeRange); + nUndoEndCol = aExtendMergeRange.aEnd.Col(); + nUndoEndRow = aExtendMergeRange.aEnd.Row(); + nPaintEndCol = nUndoEndCol; + nPaintEndRow = nUndoEndRow; + } + + if (meCmd == DelCellCmd::Rows) + { + nUndoStartCol = 0; + nUndoEndCol = rDoc.MaxCol(); + } + if (meCmd == DelCellCmd::Cols) + { + nUndoStartRow = 0; + nUndoEndRow = rDoc.MaxRow(); + } + // Test for cell protection + + SCCOL nEditTestEndX = nUndoEndCol; + if (meCmd == DelCellCmd::Cols || meCmd == DelCellCmd::CellsLeft) + nEditTestEndX = rDoc.MaxCol(); + SCROW nEditTestEndY = nUndoEndRow; + if (meCmd == DelCellCmd::Rows || meCmd == DelCellCmd::CellsUp) + nEditTestEndY = rDoc.MaxRow(); + + ScEditableTester aTester; + switch (meCmd) + { + case DelCellCmd::Cols: + aTester = ScEditableTester::CreateAndTestBlockForAction( + rDoc, sc::EditAction::DeleteColumns, nUndoStartCol, 0, nUndoEndCol, rDoc.MaxRow(), + aMark); + break; + case DelCellCmd::Rows: + aTester = ScEditableTester::CreateAndTestBlockForAction( + rDoc, sc::EditAction::DeleteRows, 0, nUndoStartRow, rDoc.MaxCol(), nUndoEndRow, + aMark); + break; + default: + aTester = ScEditableTester::CreateAndTestSelectedBlock( + rDoc, nUndoStartCol, nUndoStartRow, nEditTestEndX, nEditTestEndY, aMark); + } + + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + if (!canDeleteCellsByPivot(maRange, aMark, meCmd, rDoc)) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE); + return false; + } + // Test for merged cells + + SCCOL nMergeTestEndCol = (meCmd == DelCellCmd::CellsLeft) ? rDoc.MaxCol() : nUndoEndCol; + SCROW nMergeTestEndRow = (meCmd == DelCellCmd::CellsUp) ? rDoc.MaxRow() : nUndoEndRow; + SCCOL nExtendStartCol = nUndoStartCol; + SCROW nExtendStartRow = nUndoStartRow; + bool bNeedRefresh = false; + + //Issue 8302 want to be able to insert into the middle of merged cells + //the patch comes from maoyg + ::std::vector qDecreaseRange; + bool bDeletingMerge = false; + OUString aUndo = ScResId(STR_UNDO_DELETECELLS); + if (mbRecord) + { + ViewShellId nViewShellId(-1); + if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell()) + nViewShellId = pViewSh->GetViewShellId(); + mrDocShell.GetUndoManager()->EnterListAction(aUndo, aUndo, 0, nViewShellId); + } + std::unique_ptr pUndoRemoveMerge; + + for (const SCTAB i : aMark) + { + if (i >= nTabCount) + break; + + if (rDoc.HasAttrib(nUndoStartCol, nUndoStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)) + { + SCCOL nMergeStartCol = nUndoStartCol; + SCROW nMergeStartRow = nUndoStartRow; + SCCOL nMergeEndCol = nMergeTestEndCol; + SCROW nMergeEndRow = nMergeTestEndRow; + + rDoc.ExtendMerge(nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i); + rDoc.ExtendOverlapped(nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i); + if ((meCmd == DelCellCmd::CellsUp + && (nMergeStartCol != nUndoStartCol || nMergeEndCol != nMergeTestEndCol)) + || (meCmd == DelCellCmd::CellsLeft + && (nMergeStartRow != nUndoStartRow || nMergeEndRow != nMergeTestEndRow))) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0); + mrDocShell.GetUndoManager()->LeaveListAction(); + return false; + } + + nExtendStartCol = nMergeStartCol; + nExtendStartRow = nMergeStartRow; + SCCOL nTestCol = -1; + SCROW nTestRow1 = -1; + SCROW nTestRow2 = -1; + + ScDocAttrIterator aTestIter(rDoc, i, nUndoStartCol, nUndoStartRow, nMergeTestEndCol, + nMergeTestEndRow); + ScRange aExtendRange(nUndoStartCol, nUndoStartRow, i, nMergeTestEndCol, + nMergeTestEndRow, i); + const ScPatternAttr* pPattern = nullptr; + while ((pPattern = aTestIter.GetNext(nTestCol, nTestRow1, nTestRow2)) != nullptr) + { + const ScMergeAttr& rMergeFlag = pPattern->GetItem(ATTR_MERGE); + const ScMergeFlagAttr& rMergeFlagAttr = pPattern->GetItem(ATTR_MERGE_FLAG); + ScMF nNewFlags = rMergeFlagAttr.GetValue() & (ScMF::Hor | ScMF::Ver); + if (rMergeFlag.IsMerged() || nNewFlags == ScMF::Hor || nNewFlags == ScMF::Ver) + { + ScRange aRange(nTestCol, nTestRow1, i); + rDoc.ExtendOverlapped(aRange); + rDoc.ExtendMerge(aRange, true); + + if (nTestRow1 < nTestRow2 && nNewFlags == ScMF::Hor) + { + for (SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++) + { + ScRange aTestRange(nTestCol, nTestRow, i); + rDoc.ExtendOverlapped(aTestRange); + rDoc.ExtendMerge(aTestRange, true); + ScRange aMergeRange(aTestRange.aStart.Col(), aTestRange.aStart.Row(), + i); + if (!aExtendRange.Contains(aMergeRange)) + { + qDecreaseRange.push_back(aTestRange); + bDeletingMerge = true; + } + } + } + else + { + ScRange aMergeRange(aRange.aStart.Col(), aRange.aStart.Row(), i); + if (!aExtendRange.Contains(aMergeRange)) + { + qDecreaseRange.push_back(aRange); + } + bDeletingMerge = true; + } + } + } + + if (bDeletingMerge) + { + if (meCmd == DelCellCmd::Rows || meCmd == DelCellCmd::CellsUp) + { + nStartRow = aExtendMergeRange.aStart.Row(); + nEndRow = aExtendMergeRange.aEnd.Row(); + bNeedRefresh = true; + + if (meCmd == DelCellCmd::CellsUp) + { + nEndCol = aExtendMergeRange.aEnd.Col(); + } + else + { + nStartCol = 0; + nEndCol = rDoc.MaxCol(); + } + } + else if (meCmd == DelCellCmd::CellsLeft || meCmd == DelCellCmd::Cols) + { + nStartCol = aExtendMergeRange.aStart.Col(); + nEndCol = aExtendMergeRange.aEnd.Col(); + if (meCmd == DelCellCmd::CellsLeft) + { + nEndRow = aExtendMergeRange.aEnd.Row(); + bNeedRefresh = true; + } + else + { + nStartRow = 0; + nEndRow = rDoc.MaxRow(); + } + } + + if (!qDecreaseRange.empty()) + { + if (mbRecord && !pUndoRemoveMerge) + { + ScDocumentUniquePtr pUndoDoc(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, *aMark.begin(), *aMark.rbegin()); + pUndoRemoveMerge.reset( + new ScUndoRemoveMerge(mrDocShell, maRange, std::move(pUndoDoc))); + } + + for (const ScRange& aRange : qDecreaseRange) + { + if (rDoc.HasAttrib(aRange, HasAttrFlags::Overlapped | HasAttrFlags::Merged)) + { + mrDocShell.GetDocFunc().UnmergeCells(aRange, mbRecord, + pUndoRemoveMerge.get()); + } + } + } + } + else + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0); + mrDocShell.GetUndoManager()->LeaveListAction(); + return false; + } + } + } + + if (mbRecord && pUndoRemoveMerge) + { + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoRemoveMerge)); + } + + // do it + + weld::WaitObject aWait( + ScDocShell:: + GetActiveDialogParent()); // important because of TrackFormulas in UpdateReference + + ScUndoDeleteCells* pUndoDeleteCells = nullptr; + ScDocumentUniquePtr pUndoDoc; + std::unique_ptr pRefUndoDoc; + std::unique_ptr pUndoData; + if (mbRecord) + { + // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old + // position, so it's no longer necessary to copy more than the deleted range into pUndoDoc. + + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, 0, nTabCount - 1, (meCmd == DelCellCmd::Cols), + (meCmd == DelCellCmd::Rows)); + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + SCTAB nScenarioCount = 0; + + for (SCTAB j = rTab + 1; j < nTabCount && rDoc.IsScenario(j); j++) + nScenarioCount++; + + rDoc.CopyToDocument( + nUndoStartCol, nUndoStartRow, rTab, nUndoEndCol, nUndoEndRow, rTab + nScenarioCount, + InsertDeleteFlags::ALL | InsertDeleteFlags::NOCAPTIONS, false, *pUndoDoc); + } + + pRefUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pRefUndoDoc->InitUndo(rDoc, 0, nTabCount - 1); + + pUndoData.reset(new ScRefUndoData(rDoc)); + + rDoc.BeginDrawUndo(); + } + + sal_uInt16 nExtFlags = 0; + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + mrDocShell.UpdatePaintExt(nExtFlags, nStartCol, nStartRow, rTab, nEndCol, nEndRow, rTab); + } + + switch (meCmd) + { + case DelCellCmd::CellsUp: + case DelCellCmd::CellsLeft: + rDoc.DeleteObjectsInArea(nStartCol, nStartRow, nEndCol, nEndRow, aMark, true); + break; + case DelCellCmd::Rows: + rDoc.DeleteObjectsInArea(0, nStartRow, rDoc.MaxCol(), nEndRow, aMark, true); + break; + case DelCellCmd::Cols: + rDoc.DeleteObjectsInArea(nStartCol, 0, nEndCol, rDoc.MaxRow(), aMark, true); + break; + default: + break; + } + + bool bUndoOutline = false; + switch (meCmd) + { + case DelCellCmd::CellsUp: + rDoc.DeleteRow(nStartCol, 0, nEndCol, MAXTAB, nStartRow, + static_cast(nEndRow - nStartRow + 1), pRefUndoDoc.get(), nullptr, + &aFullMark); + nPaintEndRow = rDoc.MaxRow(); + break; + case DelCellCmd::Rows: + rDoc.DeleteRow(0, 0, rDoc.MaxCol(), MAXTAB, nStartRow, + static_cast(nEndRow - nStartRow + 1), pRefUndoDoc.get(), + &bUndoOutline, &aFullMark); + nPaintStartCol = 0; + nPaintEndCol = rDoc.MaxCol(); + nPaintEndRow = rDoc.MaxRow(); + nPaintFlags |= PaintPartFlags::Left; + break; + case DelCellCmd::CellsLeft: + rDoc.DeleteCol(nStartRow, 0, nEndRow, MAXTAB, nStartCol, + static_cast(nEndCol - nStartCol + 1), pRefUndoDoc.get(), nullptr, + &aFullMark); + nPaintEndCol = rDoc.MaxCol(); + break; + case DelCellCmd::Cols: + rDoc.DeleteCol(0, 0, rDoc.MaxRow(), MAXTAB, nStartCol, + static_cast(nEndCol - nStartCol + 1), pRefUndoDoc.get(), + &bUndoOutline, &aFullMark); + nPaintStartRow = 0; + nPaintEndRow = rDoc.MaxRow(); + nPaintEndCol = rDoc.MaxCol(); + nPaintFlags |= PaintPartFlags::Top; + break; + default: + OSL_FAIL("Wrong code at deleting"); + break; + } + + //! Test if the size of outline has changed + + if (mbRecord) + { + for (const auto& rTab : aFullMark) + { + if (rTab >= nTabCount) + break; + + pRefUndoDoc->DeleteAreaTab(nUndoStartCol, nUndoStartRow, nUndoEndCol, nUndoEndRow, rTab, + InsertDeleteFlags::ALL); + } + + // for all sheets, so that formulas can be copied + pUndoDoc->AddUndoTab(0, nTabCount - 1); + + // copy with bColRowFlags=false (#54194#) + pRefUndoDoc->CopyToDocument(0, 0, 0, rDoc.MaxCol(), rDoc.MaxRow(), MAXTAB, + InsertDeleteFlags::FORMULA, false, *pUndoDoc, nullptr, false); + pRefUndoDoc.reset(); + + std::unique_ptr pTabs(new SCTAB[nSelCount]); + std::unique_ptr pScenarios(new SCTAB[nSelCount]); + SCTAB nUndoPos = 0; + + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + SCTAB nCount = 0; + for (SCTAB j = rTab + 1; j < nTabCount && rDoc.IsScenario(j); j++) + nCount++; + + pScenarios[nUndoPos] = nCount; + pTabs[nUndoPos] = rTab; + nUndoPos++; + } + + if (!bDeletingMerge) + { + mrDocShell.GetUndoManager()->LeaveListAction(); + } + + auto pUndoAction = std::make_unique( + mrDocShell, ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab), + nUndoPos, std::move(pTabs), std::move(pScenarios), meCmd, std::move(pUndoDoc), + std::move(pUndoData)); + pUndoDeleteCells = pUndoAction.get(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoAction)); + } + + // #i8302 want to be able to insert into the middle of merged cells + // the patch comes from maoyg + + while (!qDecreaseRange.empty()) + { + ScRange aRange = qDecreaseRange.back(); + + sal_Int32 nDecreaseRowCount = 0; + sal_Int32 nDecreaseColCount = 0; + if (meCmd == DelCellCmd::CellsUp || meCmd == DelCellCmd::Rows) + { + if (nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() + && nEndRow >= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row()) + nDecreaseRowCount = nEndRow - nStartRow + 1; + else if (nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() + && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row()) + nDecreaseRowCount = aRange.aEnd.Row() - nStartRow + 1; + else if (nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() + && nEndRow >= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row()) + nDecreaseRowCount = aRange.aEnd.Row() - nEndRow + 1; + } + else if (meCmd == DelCellCmd::CellsLeft || meCmd == DelCellCmd::Cols) + { + if (nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() + && nEndCol >= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col()) + nDecreaseColCount = nEndCol - nStartCol + 1; + else if (nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() + && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col()) + nDecreaseColCount = aRange.aEnd.Col() - nStartCol + 1; + else if (nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() + && nEndCol >= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col()) + nDecreaseColCount = aRange.aEnd.Col() - nEndCol + 1; + } + + switch (meCmd) + { + case DelCellCmd::CellsUp: + case DelCellCmd::Rows: + aRange.aEnd.SetRow(static_cast(aRange.aEnd.Row() - nDecreaseRowCount)); + break; + case DelCellCmd::CellsLeft: + case DelCellCmd::Cols: + aRange.aEnd.SetCol(static_cast(aRange.aEnd.Col() - nDecreaseColCount)); + break; + default: + break; + } + + if (!rDoc.HasAttrib(aRange, HasAttrFlags::Overlapped | HasAttrFlags::Merged)) + { + ScCellMergeOption aMergeOption(aRange); + mrDocShell.GetDocFunc().MergeCells(aMergeOption, false, true, true); + } + qDecreaseRange.pop_back(); + } + + if (bDeletingMerge) + mrDocShell.GetUndoManager()->LeaveListAction(); + + if (meCmd == DelCellCmd::Cols || meCmd == DelCellCmd::CellsLeft) + nMergeTestEndCol = rDoc.MaxCol(); + if (meCmd == DelCellCmd::Rows || meCmd == DelCellCmd::CellsUp) + nMergeTestEndRow = rDoc.MaxRow(); + if (bNeedRefresh) + { + // #i51445# old merge flag attributes must be deleted also for single cells, + // not only for whole columns/rows + + ScPatternAttr aPattern(rDoc.getCellAttributeHelper()); + aPattern.GetItemSetWritable().Put(ScMergeFlagAttr()); + + rDoc.ApplyPatternArea(nExtendStartCol, nExtendStartRow, nMergeTestEndCol, nMergeTestEndRow, + aMark, aPattern); + + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + SCTAB nScenarioCount = 0; + + for (SCTAB j = rTab + 1; j < nTabCount && rDoc.IsScenario(j); j++) + nScenarioCount++; + + ScRange aMergedRange(nExtendStartCol, nExtendStartRow, rTab, nMergeTestEndCol, + nMergeTestEndRow, rTab + nScenarioCount); + rDoc.ExtendMerge(aMergedRange, true); + } + } + + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + rDoc.RefreshAutoFilter(nExtendStartCol, nExtendStartRow, nMergeTestEndCol, nMergeTestEndRow, + rTab); + } + + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + rDoc.SetDrawPageSize(rTab); + + if (meCmd == DelCellCmd::Cols || meCmd == DelCellCmd::Rows) + rDoc.UpdatePageBreaks(rTab); + + mrDocShell.UpdatePaintExt(nExtFlags, nPaintStartCol, nPaintStartRow, rTab, nPaintEndCol, + nPaintEndRow, rTab); + + SCTAB nScenarioCount = 0; + + for (SCTAB j = rTab + 1; j < nTabCount && rDoc.IsScenario(j); j++) + nScenarioCount++; + + // delete entire rows: do not adjust + if (meCmd == DelCellCmd::Rows + || !mrDocShell.GetDocFunc().AdjustRowHeight(ScRange(0, nPaintStartRow, rTab, + rDoc.MaxCol(), nPaintEndRow, + rTab + nScenarioCount), + true, mbApi)) + mrDocShell.PostPaint(nPaintStartCol, nPaintStartRow, rTab, nPaintEndCol, nPaintEndRow, + rTab + nScenarioCount, nPaintFlags, nExtFlags); + else + { + // paint only what is not done by AdjustRowHeight + if (nExtFlags & SC_PF_LINES) + ScDocFunc::PaintAbove(mrDocShell, + ScRange(nPaintStartCol, nPaintStartRow, rTab, nPaintEndCol, + nPaintEndRow, rTab + nScenarioCount)); + if (nPaintFlags & PaintPartFlags::Top) + mrDocShell.PostPaint(nPaintStartCol, nPaintStartRow, rTab, nPaintEndCol, + nPaintEndRow, rTab + nScenarioCount, PaintPartFlags::Top); + } + } + + // The cursor position needs to be modified earlier than updating + // any enabled edit view which is triggered by SetDocumentModified below. + ScTabViewShell* pViewSh = mrDocShell.GetBestViewShell(); + if (pViewSh) + { + bool bDeleteCols = (meCmd == DelCellCmd::Cols); + bool bDeleteRows = (meCmd == DelCellCmd::Rows); + + if (bDeleteCols) + { + pViewSh->OnLOKInsertDeleteColumn(maRange.aStart.Col(), + -1 * (maRange.aEnd.Col() - maRange.aStart.Col() + 1)); + } + if (bDeleteRows) + { + pViewSh->OnLOKInsertDeleteRow(maRange.aStart.Row(), + -1 * (maRange.aEnd.Row() - maRange.aStart.Row() + 1)); + } + + // Update sheet view sort ranges to account for deleted rows/columns + if (bDeleteRows || bDeleteCols) + { + SCTAB nDefaultViewTab = rDoc.GetDefaultViewTableNumber(nStartTab); + std::shared_ptr pManager + = rDoc.GetSheetViewManager(nDefaultViewTab); + if (pManager) + { + auto pSortDataBefore = pManager->captureSortData(); + + if (bDeleteRows) + pManager->deletedRows(nStartRow, nEndRow - nStartRow + 1); + if (bDeleteCols) + pManager->deletedColumns(nStartCol, nEndCol - nStartCol + 1); + + auto pSortDataAfter = pManager->captureSortData(); + + if (mbRecord && pUndoDeleteCells) + { + pUndoDeleteCells->setDefaultViewContext( + nDefaultViewTab, std::move(pSortDataBefore), std::move(pSortDataAfter)); + } + } + } + + syncSheetViews(pUndoDeleteCells); + } + + aModificator.SetDocumentModified(); + + SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreaLinksChanged)); + + mrDocShell.ResolveSpilledOutputs(); + + return true; +} + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/DeleteContentOperation.cxx b/sc/source/ui/operation/DeleteContentOperation.cxx new file mode 100644 index 000000000000..d5a19b63643b --- /dev/null +++ b/sc/source/ui/operation/DeleteContentOperation.cxx @@ -0,0 +1,166 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +namespace +{ +// If the selection is a single cell that is the master of a multi-cell +// matrix formula, expand the mark to cover the whole matrix range. Deleting +// just the master would leave the reference cells orphaned, so this lets +// the user delete the matrix by hitting Delete on the master cell. +void expandSingleMasterToFullMatrix(ScMarkData& rMark, const ScDocument& rDoc) +{ + if (!rMark.IsMarked() || rMark.IsMultiMarked()) + return; + const ScRange aRange = rMark.GetMarkArea(); + if (aRange.aStart != aRange.aEnd) + return; + const ScFormulaCell* pCell = rDoc.GetFormulaCell(aRange.aStart); + if (!pCell || pCell->GetMatrixFlag() != ScMatrixMode::Formula) + return; + SCCOL nCols = 0; + SCROW nRows = 0; + pCell->GetMatColsRows(nCols, nRows); + if (nCols <= 1 && nRows <= 1) + return; + ScRange aFull(aRange.aStart); + aFull.aEnd.IncCol(nCols - 1); + aFull.aEnd.IncRow(nRows - 1); + rMark.SetMarkArea(aFull); +} +} + +DeleteContentOperation::DeleteContentOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScMarkData& rMark, InsertDeleteFlags nFlags, + bool bRecord, bool bApi) + : Operation(OperationType::DeleteContent, bRecord, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrMark(rMark) + , mnFlags(nFlags) +{ +} + +bool DeleteContentOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + if (!mrMark.IsMarked() && !mrMark.IsMultiMarked()) + { + SAL_WARN("sc", "Operation DeleteContents without markings."); + return false; + } + + ScDocument& rDoc = mrDocShell.GetDocument(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScMarkData aWorkMark(mrMark); + expandSingleMasterToFullMatrix(aWorkMark, rDoc); + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, aWorkMark); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + ScMarkData aMultiMark = convertMark(aWorkMark); + aMultiMark.SetMarking(false); // for MarkToMulti + + ScDocumentUniquePtr pUndoDoc; + bool bMulti = aMultiMark.IsMultiMarked(); + aMultiMark.MarkToMulti(); + const ScRange& aMarkRange = aMultiMark.GetMultiMarkArea(); + ScRange aExtendedRange(aMarkRange); + if (rDoc.ExtendMerge(aExtendedRange, true)) + bMulti = false; + + // no objects on protected tabs + bool bObjects = (mnFlags & InsertDeleteFlags::OBJECTS) + && !sc::DocFuncUtil::hasProtectedTab(rDoc, aWorkMark); + + sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted + if (mnFlags & InsertDeleteFlags::ATTRIB) + mrDocShell.UpdatePaintExt(nExtFlags, aMarkRange); + + // order of operations: + // 1) BeginDrawUndo + // 2) Delete objects (DrawUndo will be filled) + // 3) Copy content for undo and set up undo actions + // 4) Delete content + + bool bDrawUndo = bObjects || (mnFlags & InsertDeleteFlags::NOTE); + if (mbRecord && bDrawUndo) + rDoc.BeginDrawUndo(); + + if (bObjects) + { + if (bMulti) + rDoc.DeleteObjectsInSelection(aMultiMark); + else + rDoc.DeleteObjectsInArea(aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), + aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMultiMark); + } + + // To keep track of all non-empty cells within the deleted area. + std::shared_ptr pDataSpans; + + // Capture every multi-cell matrix master inside the delete range so + // undo can re-register them in the expanded-matrix tracking set after + // restoring their cells. + std::vector aRestoreExpandedMatrices; + if (mbRecord) + { + pUndoDoc = sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc, aMultiMark, aMarkRange, + mnFlags, bMulti); + pDataSpans = sc::DocFuncUtil::getNonEmptyCellSpans(rDoc, aMultiMark, aMarkRange); + aRestoreExpandedMatrices = rDoc.CollectExpandedDynamicArraysInRange(aMultiMark, aMarkRange); + } + + rDoc.DeleteSelection(mnFlags, aMultiMark); + + // add undo action after drawing undo is complete (objects and note captions) + if (mbRecord) + { + sc::DocFuncUtil::addDeleteContentsUndo( + mrDocShell.GetUndoManager(), mrDocShell, aMultiMark, aExtendedRange, + std::move(pUndoDoc), mnFlags, pDataSpans, bMulti, bDrawUndo, aRestoreExpandedMatrices); + } + + syncSheetViews(); + + if (!mrDocFunc.AdjustRowHeight(aExtendedRange, true, mbApi)) + mrDocShell.PostPaint(aExtendedRange, PaintPartFlags::Grid, nExtFlags); + else if (nExtFlags & SC_PF_LINES) + ScDocFunc::PaintAbove(mrDocShell, aExtendedRange); // for lines above the range + + aModificator.SetDocumentModified(); + + mrDocShell.ResolveSpilledOutputs(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/DeleteSparklineGroupOperation.cxx b/sc/source/ui/operation/DeleteSparklineGroupOperation.cxx new file mode 100644 index 000000000000..2408e9ccb4fc --- /dev/null +++ b/sc/source/ui/operation/DeleteSparklineGroupOperation.cxx @@ -0,0 +1,50 @@ +/* -*- 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 + +#include +#include +#include + +namespace sc +{ +DeleteSparklineGroupOperation::DeleteSparklineGroupOperation( + ScDocShell& rDocShell, std::shared_ptr const& pSparklineGroup, SCTAB nTab) + : Operation(OperationType::SparklineGroupDelete, false, false) + , mrDocShell(rDocShell) + , mpSparklineGroup(pSparklineGroup) + , mnTab(nTab) +{ +} + +bool DeleteSparklineGroupOperation::runImplementation() +{ + if (!mpSparklineGroup) + return false; + + SCTAB nTab = convertTab(mnTab); + + auto& rDocument = mrDocShell.GetDocument(); + + if (!rDocument.HasTable(nTab)) + return false; + + auto pUndo = std::make_unique(mrDocShell, mpSparklineGroup, nTab); + // delete sparkline group by "redoing" + pUndo->Redo(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); + + syncSheetViews(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/DeleteSparklineOperation.cxx b/sc/source/ui/operation/DeleteSparklineOperation.cxx new file mode 100644 index 000000000000..37947dfbfd2f --- /dev/null +++ b/sc/source/ui/operation/DeleteSparklineOperation.cxx @@ -0,0 +1,44 @@ +/* -*- 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 + +#include +#include + +namespace sc +{ +DeleteSparklineOperation::DeleteSparklineOperation(ScDocShell& rDocShell, ScAddress const& rAddress) + : Operation(OperationType::SparklineDelete, false, false) + , mrDocShell(rDocShell) + , maAddress(rAddress) +{ +} + +bool DeleteSparklineOperation::runImplementation() +{ + ScAddress aAddress = convertAddress(maAddress); + + auto& rDocument = mrDocShell.GetDocument(); + + if (!rDocument.HasSparkline(aAddress)) + return false; + + auto pUndoDeleteSparkline = std::make_unique(mrDocShell, aAddress); + // delete sparkline by "redoing" + pUndoDeleteSparkline->Redo(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoDeleteSparkline)); + + syncSheetViews(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/EnterMatrixOperation.cxx b/sc/source/ui/operation/EnterMatrixOperation.cxx new file mode 100644 index 000000000000..2ab39e3dace1 --- /dev/null +++ b/sc/source/ui/operation/EnterMatrixOperation.cxx @@ -0,0 +1,148 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace sc +{ +EnterMatrixOperation::EnterMatrixOperation(ScDocShell& rDocShell, const ScRange& rRange, + const ScMarkData* pTabMark, + const ScTokenArray* pTokenArray, const OUString& rString, + bool bApi, bool bEnglish, const OUString& rFormulaNmsp, + formula::FormulaGrammar::Grammar eGrammar, + bool bDynamicArrayMaster) + : Operation(OperationType::EnterMatrix, true, bApi) + , mrDocShell(rDocShell) + , maRange(rRange) + , mpTabMark(pTabMark) + , mpTokenArray(pTokenArray) + , maString(rString) + , mbEnglish(bEnglish) + , maFormulaNmsp(rFormulaNmsp) + , meGrammar(eGrammar) + , mbDynamicArrayMaster(bDynamicArrayMaster) +{ +} + +bool EnterMatrixOperation::runImplementation() +{ + if (ScViewData::SelectionFillDOOM(maRange)) + return false; + + ScDocShellModificator aModificator(mrDocShell); + + bool bSuccess = false; + ScDocument& rDoc = mrDocShell.GetDocument(); + + ScRange aRange = convertRange(maRange); + + SCCOL nStartCol = aRange.aStart.Col(); + SCROW nStartRow = aRange.aStart.Row(); + SCTAB nStartTab = aRange.aStart.Tab(); + SCCOL nEndCol = aRange.aEnd.Col(); + SCROW nEndRow = aRange.aEnd.Row(); + SCTAB nEndTab = aRange.aEnd.Tab(); + + ScMarkData aMark(rDoc.GetSheetLimits()); + if (mpTabMark) + aMark = *mpTabMark; + else + { + for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++) + aMark.SelectTable(nTab, true); + } + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock( + rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); + if (aTester.IsEditable()) + { + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + ScDocumentUniquePtr pUndoDoc; + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + if (mbRecord) + { + //! take selected sheets into account also when undoing + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nStartTab, nEndTab); + rDoc.CopyToDocument(aRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, + *pUndoDoc); + } + + // use TokenArray if given, string (and flags) otherwise + if (mpTokenArray) + { + rDoc.InsertMatrixFormula(nStartCol, nStartRow, nEndCol, nEndRow, aMark, OUString(), + mpTokenArray, meGrammar, mbDynamicArrayMaster); + } + else if (rDoc.IsImportingXML()) + { + ScTokenArray aCode(rDoc); + aCode.AssignXMLString(maString, ((meGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) + ? maFormulaNmsp + : OUString())); + rDoc.InsertMatrixFormula(nStartCol, nStartRow, nEndCol, nEndRow, aMark, OUString(), + &aCode, meGrammar); + rDoc.IncXMLImportedFormulaCount(maString.getLength()); + } + else if (mbEnglish) + { + ScCompiler aComp(rDoc, aRange.aStart, meGrammar); + std::unique_ptr pCode = aComp.CompileString(maString); + rDoc.InsertMatrixFormula(nStartCol, nStartRow, nEndCol, nEndRow, aMark, OUString(), + pCode.get(), meGrammar, mbDynamicArrayMaster); + } + else + rDoc.InsertMatrixFormula(nStartCol, nStartRow, nEndCol, nEndRow, aMark, maString, + nullptr, meGrammar, mbDynamicArrayMaster); + + if (mbRecord) + { + //! take selected sheets into account also when undoing + std::unique_ptr pUndoArray; + if (mpTokenArray) + pUndoArray = mpTokenArray->Clone(); + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aRange, std::move(pUndoDoc), maString, std::move(pUndoArray), + mbDynamicArrayMaster)); + } + + syncSheetViews(); + + // Err522 painting of DDE-Formulas will be intercepted during interpreting + mrDocShell.PostPaint(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, + PaintPartFlags::Grid); + aModificator.SetDocumentModified(); + + bSuccess = true; + } + else if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + + return bSuccess; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/FillAutoOperation.cxx b/sc/source/ui/operation/FillAutoOperation.cxx new file mode 100644 index 000000000000..0f78e36d3db5 --- /dev/null +++ b/sc/source/ui/operation/FillAutoOperation.cxx @@ -0,0 +1,198 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace sc +{ +FillAutoOperation::FillAutoOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, ScRange& rRange, + const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, + FillDateCmd eDateCmd, sal_uLong nCount, double fStep, + double fMax, bool bRecord, bool bApi) + : Operation(OperationType::FillAuto, bRecord, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrRange(rRange) + , mpTabMark(pTabMark) + , meDir(eDir) + , meCmd(eCmd) + , meDateCmd(eDateCmd) + , mnCount(nCount) + , mfStep(fStep) + , mfMax(fMax) +{ +} + +bool FillAutoOperation::canRunTheOperation() const +{ + return !isInputOnSheetViewAutoFilter(mrRange); +} + +bool FillAutoOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + + SCTAB nOriginalTab = mrRange.aStart.Tab(); + ScRange aRange = convertRange(mrRange); + SCCOL nStartCol = aRange.aStart.Col(); + SCROW nStartRow = aRange.aStart.Row(); + SCTAB nStartTab = aRange.aStart.Tab(); + SCCOL nEndCol = aRange.aEnd.Col(); + SCROW nEndRow = aRange.aEnd.Row(); + SCTAB nEndTab = aRange.aEnd.Tab(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScMarkData aMark(rDoc.GetSheetLimits()); + if (mpTabMark) + aMark = *mpTabMark; + else + { + for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++) + aMark.SelectTable(nTab, true); + } + + ScRange aSourceArea = aRange; + ScRange aDestArea = aRange; + + switch (meDir) + { + case FILL_TO_BOTTOM: + aDestArea.aEnd.SetRow(sal::static_int_cast(aSourceArea.aEnd.Row() + mnCount)); + break; + case FILL_TO_TOP: + if (mnCount > sal::static_int_cast(aSourceArea.aStart.Row())) + { + OSL_FAIL("FillAuto: Row < 0"); + mnCount = aSourceArea.aStart.Row(); + } + aDestArea.aStart.SetRow( + sal::static_int_cast(aSourceArea.aStart.Row() - mnCount)); + break; + case FILL_TO_RIGHT: + aDestArea.aEnd.SetCol(sal::static_int_cast(aSourceArea.aEnd.Col() + mnCount)); + break; + case FILL_TO_LEFT: + if (mnCount > sal::static_int_cast(aSourceArea.aStart.Col())) + { + OSL_FAIL("FillAuto: Col < 0"); + mnCount = aSourceArea.aStart.Col(); + } + aDestArea.aStart.SetCol( + sal::static_int_cast(aSourceArea.aStart.Col() - mnCount)); + break; + default: + OSL_FAIL("Wrong direction with FillAuto"); + break; + } + + // Test for cell protection + //! Source range can be protected !!! + //! but can't contain matrix fragments !!! + + ScEditableTester aTester + = ScEditableTester::CreateAndTestRange(rDoc, aDestArea, sc::EditAction::Unknown); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + if (rDoc.HasSelectedBlockMatrixFragment(nStartCol, nStartRow, nEndCol, nEndRow, aMark)) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR); + return false; + } + + // FID_FILL_... slots should already have been disabled, check here for API + // calls, no message. + if (ScViewData::SelectionFillDOOM(aDestArea)) + return false; + + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + ScDocumentUniquePtr pUndoDoc; + if (mbRecord) + { + SCTAB nTabCount = rDoc.GetTableCount(); + SCTAB nDestStartTab = aDestArea.aStart.Tab(); + + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nDestStartTab, nDestStartTab); + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + if (rTab != nDestStartTab) + pUndoDoc->AddUndoTab(rTab, rTab); + } + + // do not clone note captions in undo document + rDoc.CopyToDocument(aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, aDestArea.aEnd.Col(), + aDestArea.aEnd.Row(), nTabCount - 1, InsertDeleteFlags::AUTOFILL, false, + *pUndoDoc, &aMark); + } + + sal_uLong nProgCount; + if (meDir == FILL_TO_BOTTOM || meDir == FILL_TO_TOP) + nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1; + else + nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1; + nProgCount *= mnCount; + ScProgress aProgress(rDoc.GetDocumentShell(), ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, + true); + + rDoc.Fill(aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aEnd.Col(), + aSourceArea.aEnd.Row(), &aProgress, aMark, mnCount, meDir, meCmd, meDateCmd, mfStep, + mfMax); + + mrDocFunc.AdjustRowHeight(aDestArea, true, mbApi); + + syncSheetViews(); + + if (mbRecord) // only now is Draw-Undo available + { + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aDestArea, aSourceArea, std::move(pUndoDoc), aMark, meDir, meCmd, meDateCmd, + MAXDOUBLE, mfStep, mfMax)); + } + + mrDocShell.PostPaintGridAll(); + aModificator.SetDocumentModified(); + + aDestArea.aStart.SetTab(nOriginalTab); + aDestArea.aEnd.SetTab(nOriginalTab); + mrRange = aDestArea; // return destination range (for marking) + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/FillSeriesOperation.cxx b/sc/source/ui/operation/FillSeriesOperation.cxx new file mode 100644 index 000000000000..5ff5d2fad611 --- /dev/null +++ b/sc/source/ui/operation/FillSeriesOperation.cxx @@ -0,0 +1,210 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace +{ +ScDirection DirFromFillDir(FillDir eDir) +{ + if (eDir == FILL_TO_BOTTOM) + return DIR_BOTTOM; + else if (eDir == FILL_TO_RIGHT) + return DIR_RIGHT; + else if (eDir == FILL_TO_TOP) + return DIR_TOP; + else // if (eDir==FILL_TO_LEFT) + return DIR_LEFT; +} +} + +namespace sc +{ +FillSeriesOperation::FillSeriesOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScRange& rRange, const ScMarkData* pTabMark, + FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, + double fStart, double fStep, double fMax, bool bApi) + : Operation(OperationType::FillSeries, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , maRange(rRange) + , mpTabMark(pTabMark) + , meDir(eDir) + , meCmd(eCmd) + , meDateCmd(eDateCmd) + , mfStart(fStart) + , mfStep(fStep) + , mfMax(fMax) +{ +} + +bool FillSeriesOperation::canRunTheOperation() const +{ + return !isInputOnSheetViewAutoFilter(maRange); +} + +bool FillSeriesOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + bool bSuccess = false; + ScDocument& rDoc = mrDocShell.GetDocument(); + + ScRange aRange = convertRange(maRange); + SCCOL nStartCol = aRange.aStart.Col(); + SCROW nStartRow = aRange.aStart.Row(); + SCTAB nStartTab = aRange.aStart.Tab(); + SCCOL nEndCol = aRange.aEnd.Col(); + SCROW nEndRow = aRange.aEnd.Row(); + SCTAB nEndTab = aRange.aEnd.Tab(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScMarkData aMark(rDoc.GetSheetLimits()); + if (mpTabMark) + aMark = *mpTabMark; + else + { + for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++) + aMark.SelectTable(nTab, true); + } + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock( + rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); + if (aTester.IsEditable()) + { + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + ScRange aSourceArea = aRange; + ScRange aDestArea = aRange; + + SCSIZE nCount = rDoc.GetEmptyLinesInBlock( + aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(), + aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(), + DirFromFillDir(meDir)); + + // keep at least one row/column as source range + SCSIZE nTotLines + = (meDir == FILL_TO_BOTTOM || meDir == FILL_TO_TOP) + ? static_cast(aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1) + : static_cast(aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1); + if (nCount >= nTotLines) + { + assert(nTotLines > 0 && "coverity 2023.12.2"); + nCount = nTotLines - 1; + } + + switch (meDir) + { + case FILL_TO_BOTTOM: + aSourceArea.aEnd.SetRow( + sal::static_int_cast(aSourceArea.aEnd.Row() - nCount)); + break; + case FILL_TO_RIGHT: + aSourceArea.aEnd.SetCol( + sal::static_int_cast(aSourceArea.aEnd.Col() - nCount)); + break; + case FILL_TO_TOP: + aSourceArea.aStart.SetRow( + sal::static_int_cast(aSourceArea.aStart.Row() + nCount)); + break; + case FILL_TO_LEFT: + aSourceArea.aStart.SetCol( + sal::static_int_cast(aSourceArea.aStart.Col() + nCount)); + break; + } + + ScDocumentUniquePtr pUndoDoc; + if (mbRecord) + { + SCTAB nTabCount = rDoc.GetTableCount(); + SCTAB nDestStartTab = aDestArea.aStart.Tab(); + + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nDestStartTab, nDestStartTab); + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + if (rTab != nDestStartTab) + pUndoDoc->AddUndoTab(rTab, rTab); + } + + rDoc.CopyToDocument(aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, + aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount - 1, + InsertDeleteFlags::AUTOFILL, false, *pUndoDoc, &aMark); + } + + if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() + && aDestArea.aStart.Row() <= aDestArea.aEnd.Row()) + { + if (mfStart != MAXDOUBLE) + { + SCCOL nValX + = (meDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col(); + SCROW nValY + = (meDir == FILL_TO_TOP) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row(); + SCTAB nTab = aDestArea.aStart.Tab(); + rDoc.SetValue(nValX, nValY, nTab, mfStart); + } + + sal_uLong nProgCount; + if (meDir == FILL_TO_BOTTOM || meDir == FILL_TO_TOP) + nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1; + else + nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1; + nProgCount *= nCount; + ScProgress aProgress(rDoc.GetDocumentShell(), ScResId(STR_FILL_SERIES_PROGRESS), + nProgCount, true); + + rDoc.Fill(aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aEnd.Col(), + aSourceArea.aEnd.Row(), &aProgress, aMark, nCount, meDir, meCmd, meDateCmd, + mfStep, mfMax); + mrDocFunc.AdjustRowHeight(aRange, true, mbApi); + + syncSheetViews(); + + mrDocShell.PostPaintGridAll(); + aModificator.SetDocumentModified(); + } + + if (mbRecord) // only now is Draw-Undo available + { + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aDestArea, aSourceArea, std::move(pUndoDoc), aMark, meDir, meCmd, + meDateCmd, mfStart, mfStep, mfMax)); + } + + bSuccess = true; + } + else if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + + return bSuccess; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/FillSimpleOperation.cxx b/sc/source/ui/operation/FillSimpleOperation.cxx new file mode 100644 index 000000000000..be048d10c24b --- /dev/null +++ b/sc/source/ui/operation/FillSimpleOperation.cxx @@ -0,0 +1,223 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace +{ +void adjustFillRangeForAdjacentCopy(const ScDocument& rDoc, ScRange& rRange, FillDir eDir) +{ + switch (eDir) + { + case FILL_TO_BOTTOM: + { + if (rRange.aStart.Row() == 0) + return; + + if (rRange.aStart.Row() != rRange.aEnd.Row()) + return; + + // Include the above row. + ScAddress& s = rRange.aStart; + s.SetRow(s.Row() - 1); + } + break; + case FILL_TO_TOP: + { + if (rRange.aStart.Row() == rDoc.MaxRow()) + return; + + if (rRange.aStart.Row() != rRange.aEnd.Row()) + return; + + // Include the row below. + ScAddress& e = rRange.aEnd; + e.SetRow(e.Row() + 1); + } + break; + case FILL_TO_LEFT: + { + if (rRange.aStart.Col() == rDoc.MaxCol()) + return; + + if (rRange.aStart.Col() != rRange.aEnd.Col()) + return; + + // Include the column to the right. + ScAddress& e = rRange.aEnd; + e.SetCol(e.Col() + 1); + } + break; + case FILL_TO_RIGHT: + { + if (rRange.aStart.Col() == 0) + return; + + if (rRange.aStart.Col() != rRange.aEnd.Col()) + return; + + // Include the column to the left. + ScAddress& s = rRange.aStart; + s.SetCol(s.Col() - 1); + } + break; + default:; + } +} +} + +namespace sc +{ +FillSimpleOperation::FillSimpleOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScRange& rRange, const ScMarkData* pTabMark, + FillDir eDir, bool bApi) + : Operation(OperationType::FillSimple, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , maRange(rRange) + , mpTabMark(pTabMark) + , meDir(eDir) +{ +} + +bool FillSimpleOperation::canRunTheOperation() const +{ + return !isInputOnSheetViewAutoFilter(maRange); +} + +bool FillSimpleOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + + bool bSuccess = false; + ScRange aRange = convertRange(maRange); + adjustFillRangeForAdjacentCopy(rDoc, aRange, meDir); + + SCCOL nStartCol = aRange.aStart.Col(); + SCROW nStartRow = aRange.aStart.Row(); + SCTAB nStartTab = aRange.aStart.Tab(); + SCCOL nEndCol = aRange.aEnd.Col(); + SCROW nEndRow = aRange.aEnd.Row(); + SCTAB nEndTab = aRange.aEnd.Tab(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScMarkData aMark(rDoc.GetSheetLimits()); + if (mpTabMark) + aMark = *mpTabMark; + else + { + for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++) + aMark.SelectTable(nTab, true); + } + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock( + rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); + if (aTester.IsEditable()) + { + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + ScRange aSourceArea = aRange; + ScRange aDestArea = aRange; + + SCCOLROW nCount = 0; + switch (meDir) + { + case FILL_TO_BOTTOM: + nCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row(); + aSourceArea.aEnd.SetRow(aSourceArea.aStart.Row()); + break; + case FILL_TO_RIGHT: + nCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col(); + aSourceArea.aEnd.SetCol(aSourceArea.aStart.Col()); + break; + case FILL_TO_TOP: + nCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row(); + aSourceArea.aStart.SetRow(aSourceArea.aEnd.Row()); + break; + case FILL_TO_LEFT: + nCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col(); + aSourceArea.aStart.SetCol(aSourceArea.aEnd.Col()); + break; + } + + ScDocumentUniquePtr pUndoDoc; + if (mbRecord) + { + SCTAB nTabCount = rDoc.GetTableCount(); + SCTAB nDestStartTab = aDestArea.aStart.Tab(); + + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nDestStartTab, nDestStartTab); + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + if (rTab != nDestStartTab) + pUndoDoc->AddUndoTab(rTab, rTab); + } + + ScRange aCopyRange = aDestArea; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount - 1); + rDoc.CopyToDocument(aCopyRange, InsertDeleteFlags::AUTOFILL, false, *pUndoDoc, &aMark); + } + + sal_uLong nProgCount; + if (meDir == FILL_TO_BOTTOM || meDir == FILL_TO_TOP) + nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1; + else + nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1; + nProgCount *= nCount; + ScProgress aProgress(rDoc.GetDocumentShell(), ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, + true); + + rDoc.Fill(aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aEnd.Col(), + aSourceArea.aEnd.Row(), &aProgress, aMark, nCount, meDir, FILL_SIMPLE); + mrDocFunc.AdjustRowHeight(aRange, true, mbApi); + + if (mbRecord) // only now is Draw-Undo available + { + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aDestArea, aSourceArea, std::move(pUndoDoc), aMark, meDir, FILL_SIMPLE, + FILL_DAY, MAXDOUBLE, 1.0, 1e307)); + } + + syncSheetViews(); + + mrDocShell.PostPaintGridAll(); + aModificator.SetDocumentModified(); + + bSuccess = true; + } + else if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + + return bSuccess; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/GroupSparklinesOperation.cxx b/sc/source/ui/operation/GroupSparklinesOperation.cxx new file mode 100644 index 000000000000..b389b6f8cdd6 --- /dev/null +++ b/sc/source/ui/operation/GroupSparklinesOperation.cxx @@ -0,0 +1,42 @@ +/* -*- 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 + +#include +#include +#include + +namespace sc +{ +GroupSparklinesOperation::GroupSparklinesOperation(ScDocShell& rDocShell, ScRange const& rRange, + std::shared_ptr const& rpGroup) + : Operation(OperationType::SparklineGroup, false, false) + , mrDocShell(rDocShell) + , maRange(rRange) + , mpGroup(rpGroup) +{ +} + +bool GroupSparklinesOperation::runImplementation() +{ + ScRange aRange = convertRange(maRange); + + auto pUndo = std::make_unique(mrDocShell, aRange, mpGroup); + // group sparklines by "redoing" + pUndo->Redo(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); + + syncSheetViews(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/InsertCellsOperation.cxx b/sc/source/ui/operation/InsertCellsOperation.cxx new file mode 100644 index 000000000000..66a74cc7998a --- /dev/null +++ b/sc/source/ui/operation/InsertCellsOperation.cxx @@ -0,0 +1,806 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace +{ +/** + * Check if this insertion attempt would end up cutting one or more pivot + * tables in half, which is not desirable. + * + * @return true if this insertion can be done safely without shearing any + * existing pivot tables, false otherwise. + */ +bool canInsertCellsByPivot(const ScRange& rRange, const ScMarkData& rMarkData, InsCellCmd eCmd, + const ScDocument& rDoc) +{ + if (!rDoc.HasPivotTable()) + // This document has no pivot tables. + return true; + + const ScDPCollection* pDPs = rDoc.GetDPCollection(); + + ScRange aRange(rRange); // local copy + switch (eCmd) + { + case INS_INSROWS_BEFORE: + { + aRange.aStart.SetCol(0); + aRange.aEnd.SetCol(rDoc.MaxCol()); + [[fallthrough]]; + } + case INS_CELLSDOWN: + { + auto bIntersects = std::ranges::any_of(rMarkData, [&pDPs, &aRange](const SCTAB& rTab) { + return pDPs->IntersectsTableByColumns(aRange.aStart.Col(), aRange.aEnd.Col(), + aRange.aStart.Row(), rTab); + }); + if (bIntersects) + // This column range cuts through at least one pivot table. Not good. + return false; + + // Start row must be either at the top or above any pivot tables. + if (aRange.aStart.Row() < 0) + // I don't know how to handle this case. + return false; + + if (aRange.aStart.Row() == 0) + // First row is always allowed. + return true; + + ScRange aTest(aRange); + aTest.aStart.IncRow(-1); // Test one row up. + aTest.aEnd.SetRow(aTest.aStart.Row()); + for (const auto& rTab : rMarkData) + { + aTest.aStart.SetTab(rTab); + aTest.aEnd.SetTab(rTab); + if (pDPs->HasTable(aTest)) + return false; + } + } + break; + case INS_INSCOLS_BEFORE: + { + aRange.aStart.SetRow(0); + aRange.aEnd.SetRow(rDoc.MaxRow()); + [[fallthrough]]; + } + case INS_CELLSRIGHT: + { + auto bIntersects = std::ranges::any_of(rMarkData, [&pDPs, &aRange](const SCTAB& rTab) { + return pDPs->IntersectsTableByRows(aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Row(), rTab); + }); + if (bIntersects) + // This column range cuts through at least one pivot table. Not good. + return false; + + // Start row must be either at the top or above any pivot tables. + if (aRange.aStart.Col() < 0) + // I don't know how to handle this case. + return false; + + if (aRange.aStart.Col() == 0) + // First row is always allowed. + return true; + + ScRange aTest(aRange); + aTest.aStart.IncCol(-1); // Test one column to the left. + aTest.aEnd.SetCol(aTest.aStart.Col()); + for (const auto& rTab : rMarkData) + { + aTest.aStart.SetTab(rTab); + aTest.aEnd.SetTab(rTab); + if (pDPs->HasTable(aTest)) + return false; + } + } + break; + default:; + } + return true; +} + +} // anonymous namespace + +namespace sc +{ +InsertCellsOperation::InsertCellsOperation(ScDocShell& rDocShell, ScRange const& rRange, + ScMarkData const* pTabMark, InsCellCmd eCmd, + bool bRecord, bool bApi, bool bPartOfPaste, + size_t nInsertCount) + : Operation(toOperationType(eCmd), bRecord, bApi) + , mrDocShell(rDocShell) + , maRange(rRange) + , mpTabMark(pTabMark) + , meCmd(eCmd) + , mbPartOfPaste(bPartOfPaste) + , mnInsertCount(nInsertCount) +{ +} + +OperationType InsertCellsOperation::toOperationType(InsCellCmd eCmd) +{ + switch (eCmd) + { + case INS_INSCOLS_BEFORE: + return OperationType::InsertColumnsBefore; + case INS_INSCOLS_AFTER: + return OperationType::InsertColumnsAfter; + case INS_INSROWS_BEFORE: + return OperationType::InsertRowsBefore; + case INS_INSROWS_AFTER: + return OperationType::InsertRowsAfter; + case INS_CELLSDOWN: + return OperationType::InsertCellsDown; + case INS_CELLSRIGHT: + return OperationType::InsertCellsRight; + default: + return OperationType::Unknown; + } +} + +bool InsertCellsOperation::canRunTheOperation() const +{ + return !isInputOnSheetViewAutoFilter(maRange); +} + +bool InsertCellsOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + + if (mrDocShell.GetDocument().GetChangeTrack() + && ((meCmd == INS_CELLSDOWN + && (maRange.aStart.Col() != 0 || maRange.aEnd.Col() != rDoc.MaxCol())) + || (meCmd == INS_CELLSRIGHT + && (maRange.aStart.Row() != 0 || maRange.aEnd.Row() != rDoc.MaxRow())))) + { + // We should not reach this via UI disabled slots. + assert(mbApi); + SAL_WARN("sc.ui", "ScDocFunc::InsertCells - no change-tracking of partial cell shift"); + return false; + } + + ScRange aTargetRange(maRange); + + // If insertion is for full cols/rows and after the current + // selection, then shift the range accordingly + if (meCmd == INS_INSROWS_AFTER) + { + ScRange aErrorRange(ScAddress::UNINITIALIZED); + if (!aTargetRange.Move(0, maRange.aEnd.Row() - maRange.aStart.Row() + 1, 0, aErrorRange, + rDoc)) + { + return false; + } + } + if (meCmd == INS_INSCOLS_AFTER) + { + ScRange aErrorRange(ScAddress::UNINITIALIZED); + if (!aTargetRange.Move(maRange.aEnd.Col() - maRange.aStart.Col() + 1, 0, 0, aErrorRange, + rDoc)) + { + return false; + } + } + + SCCOL nStartCol = aTargetRange.aStart.Col(); + SCROW nStartRow = aTargetRange.aStart.Row(); + SCTAB nStartTab = aTargetRange.aStart.Tab(); + SCCOL nEndCol = aTargetRange.aEnd.Col() + mnInsertCount; + SCROW nEndRow = aTargetRange.aEnd.Row() + mnInsertCount; + SCTAB nEndTab = aTargetRange.aEnd.Tab(); + + if (!rDoc.ValidRow(nStartRow) || !rDoc.ValidRow(nEndRow)) + { + OSL_FAIL("invalid row in InsertCells"); + return false; + } + + SCTAB nTabCount = rDoc.GetTableCount(); + SCCOL nPaintStartCol = nStartCol; + SCROW nPaintStartRow = nStartRow; + SCCOL nPaintEndCol = nEndCol; + SCROW nPaintEndRow = nEndRow; + PaintPartFlags nPaintFlags = PaintPartFlags::Grid; + bool bSuccess; + + ScTabViewShell* pViewSh = mrDocShell.GetBestViewShell(); //preserve current cursor position + SCCOL nCursorCol = 0; + SCROW nCursorRow = 0; + if (pViewSh) + { + nCursorCol = pViewSh->GetViewData().GetCurX(); + nCursorRow = pViewSh->GetViewData().GetCurY(); + } + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScMarkData aMark(rDoc.GetSheetLimits()); + if (mpTabMark) + aMark = *mpTabMark; + else + { + SCTAB nCount = 0; + for (SCTAB i = 0; i < nTabCount; i++) + { + if (!rDoc.IsScenario(i)) + { + nCount++; + if (nCount == nEndTab + 1) + { + aMark.SelectTable(i, true); + break; + } + } + } + } + + ScMarkData aFullMark(aMark); // including scenario sheets + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + for (SCTAB j = rTab + 1; j < nTabCount && rDoc.IsScenario(j); j++) + aFullMark.SelectTable(j, true); + } + + SCTAB nSelCount = aMark.GetSelectCount(); + + // Adjust also related scenarios + + SCCOL nMergeTestStartCol = nStartCol; + SCROW nMergeTestStartRow = nStartRow; + SCCOL nMergeTestEndCol = nEndCol; + SCROW nMergeTestEndRow = nEndRow; + + ScRange aExtendMergeRange(aTargetRange); + + if (aTargetRange.aStart == aTargetRange.aEnd + && rDoc.HasAttrib(aTargetRange, HasAttrFlags::Merged)) + { + rDoc.ExtendMerge(aExtendMergeRange); + rDoc.ExtendOverlapped(aExtendMergeRange); + nMergeTestEndCol = aExtendMergeRange.aEnd.Col(); + nMergeTestEndRow = aExtendMergeRange.aEnd.Row(); + nPaintEndCol = nMergeTestEndCol; + nPaintEndRow = nMergeTestEndRow; + } + + if (meCmd == INS_INSROWS_BEFORE || meCmd == INS_INSROWS_AFTER) + { + nMergeTestStartCol = 0; + nMergeTestEndCol = rDoc.MaxCol(); + } + if (meCmd == INS_INSCOLS_BEFORE || meCmd == INS_INSCOLS_AFTER) + { + nMergeTestStartRow = 0; + nMergeTestEndRow = rDoc.MaxRow(); + } + if (meCmd == INS_CELLSDOWN) + nMergeTestEndRow = rDoc.MaxRow(); + if (meCmd == INS_CELLSRIGHT) + nMergeTestEndCol = rDoc.MaxCol(); + + bool bNeedRefresh = false; + + SCCOL nEditTestEndCol = (meCmd == INS_INSCOLS_BEFORE || meCmd == INS_INSCOLS_AFTER) + ? rDoc.MaxCol() + : nMergeTestEndCol; + SCROW nEditTestEndRow = (meCmd == INS_INSROWS_BEFORE || meCmd == INS_INSROWS_AFTER) + ? rDoc.MaxRow() + : nMergeTestEndRow; + + ScEditableTester aTester; + switch (meCmd) + { + case INS_INSCOLS_BEFORE: + aTester = ScEditableTester::CreateAndTestBlockForAction( + rDoc, sc::EditAction::InsertColumnsBefore, nMergeTestStartCol, 0, nMergeTestEndCol, + rDoc.MaxRow(), aMark); + break; + case INS_INSCOLS_AFTER: + aTester = ScEditableTester::CreateAndTestBlockForAction( + rDoc, sc::EditAction::InsertColumnsAfter, nMergeTestStartCol, 0, nMergeTestEndCol, + rDoc.MaxRow(), aMark); + break; + case INS_INSROWS_BEFORE: + aTester = ScEditableTester::CreateAndTestBlockForAction( + rDoc, sc::EditAction::InsertRowsBefore, 0, nMergeTestStartRow, rDoc.MaxCol(), + nMergeTestEndRow, aMark); + break; + case INS_INSROWS_AFTER: + aTester = ScEditableTester::CreateAndTestBlockForAction( + rDoc, sc::EditAction::InsertRowsAfter, 0, nMergeTestStartRow, rDoc.MaxCol(), + nMergeTestEndRow, aMark); + break; + default: + aTester = ScEditableTester::CreateAndTestSelectedBlock( + rDoc, nMergeTestStartCol, nMergeTestStartRow, nEditTestEndCol, nEditTestEndRow, + aMark); + break; + } + + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + // Check if this insertion is allowed with respect to pivot table. + if (!canInsertCellsByPivot(aTargetRange, aMark, meCmd, rDoc)) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE); + return false; + } + + weld::WaitObject aWait( + ScDocShell::GetActiveDialogParent()); // important due to TrackFormulas at UpdateReference + + ScUndoInsertCells* pUndoInsertCells = nullptr; + ScDocumentUniquePtr pRefUndoDoc; + std::unique_ptr pUndoData; + if (mbRecord) + { + pRefUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pRefUndoDoc->InitUndo(rDoc, 0, nTabCount - 1); + + // pRefUndoDoc is filled in InsertCol / InsertRow + + pUndoData.reset(new ScRefUndoData(rDoc)); + + rDoc.BeginDrawUndo(); + } + + // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction + // the patch comes from mloiseleur and maoyg + bool bInsertMerge = false; + std::vector qIncreaseRange; + OUString aUndo = ScResId(STR_UNDO_INSERTCELLS); + if (mbRecord) + { + ViewShellId nViewShellId(-1); + if (pViewSh) + nViewShellId = pViewSh->GetViewShellId(); + mrDocShell.GetUndoManager()->EnterListAction(aUndo, aUndo, 0, nViewShellId); + } + std::unique_ptr pUndoRemoveMerge; + + for (const SCTAB i : aMark) + { + if (i >= nTabCount) + break; + + if (rDoc.HasAttrib(nMergeTestStartCol, nMergeTestStartRow, i, nMergeTestEndCol, + nMergeTestEndRow, i, HasAttrFlags::Merged | HasAttrFlags::Overlapped)) + { + if (meCmd == INS_CELLSRIGHT) + bNeedRefresh = true; + + SCCOL nMergeStartCol = nMergeTestStartCol; + SCROW nMergeStartRow = nMergeTestStartRow; + SCCOL nMergeEndCol = nMergeTestEndCol; + SCROW nMergeEndRow = nMergeTestEndRow; + + rDoc.ExtendMerge(nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i); + rDoc.ExtendOverlapped(nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i); + + if ((meCmd == INS_CELLSDOWN + && (nMergeStartCol != nMergeTestStartCol || nMergeEndCol != nMergeTestEndCol)) + || (meCmd == INS_CELLSRIGHT + && (nMergeStartRow != nMergeTestStartRow || nMergeEndRow != nMergeTestEndRow))) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); + mrDocShell.GetUndoManager()->LeaveListAction(); + return false; + } + + SCCOL nTestCol = -1; + SCROW nTestRow1 = -1; + SCROW nTestRow2 = -1; + + ScDocAttrIterator aTestIter(rDoc, i, nMergeTestStartCol, nMergeTestStartRow, + nMergeTestEndCol, nMergeTestEndRow); + ScRange aExtendRange(nMergeTestStartCol, nMergeTestStartRow, i, nMergeTestEndCol, + nMergeTestEndRow, i); + const ScPatternAttr* pPattern = nullptr; + while ((pPattern = aTestIter.GetNext(nTestCol, nTestRow1, nTestRow2)) != nullptr) + { + const ScMergeAttr& rMergeFlag = pPattern->GetItem(ATTR_MERGE); + const ScMergeFlagAttr& rMergeFlagAttr = pPattern->GetItem(ATTR_MERGE_FLAG); + ScMF nNewFlags = rMergeFlagAttr.GetValue() & (ScMF::Hor | ScMF::Ver); + if (rMergeFlag.IsMerged() || nNewFlags == ScMF::Hor || nNewFlags == ScMF::Ver) + { + ScRange aRange(nTestCol, nTestRow1, i); + rDoc.ExtendOverlapped(aRange); + rDoc.ExtendMerge(aRange, true); + + if (nTestRow1 < nTestRow2 && nNewFlags == ScMF::Hor) + { + for (SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++) + { + ScRange aTestRange(nTestCol, nTestRow, i); + rDoc.ExtendOverlapped(aTestRange); + rDoc.ExtendMerge(aTestRange, true); + ScRange aMergeRange(aTestRange.aStart.Col(), aTestRange.aStart.Row(), + i); + if (!aExtendRange.Contains(aMergeRange)) + { + qIncreaseRange.push_back(aTestRange); + bInsertMerge = true; + } + } + } + else + { + ScRange aMergeRange(aRange.aStart.Col(), aRange.aStart.Row(), i); + if (!aExtendRange.Contains(aMergeRange)) + { + qIncreaseRange.push_back(aRange); + } + bInsertMerge = true; + } + } + } + + if (bInsertMerge) + { + if (meCmd == INS_INSROWS_BEFORE || meCmd == INS_INSROWS_AFTER + || meCmd == INS_CELLSDOWN) + { + nStartRow = aExtendMergeRange.aStart.Row(); + nEndRow = aExtendMergeRange.aEnd.Row(); + + if (meCmd == INS_CELLSDOWN) + nEndCol = nMergeTestEndCol; + else + { + nStartCol = 0; + nEndCol = rDoc.MaxCol(); + } + } + else if (meCmd == INS_CELLSRIGHT || meCmd == INS_INSCOLS_BEFORE + || meCmd == INS_INSCOLS_AFTER) + { + nStartCol = aExtendMergeRange.aStart.Col(); + nEndCol = aExtendMergeRange.aEnd.Col(); + if (meCmd == INS_CELLSRIGHT) + { + nEndRow = nMergeTestEndRow; + } + else + { + nStartRow = 0; + nEndRow = rDoc.MaxRow(); + } + } + + if (!qIncreaseRange.empty()) + { + if (mbRecord && !pUndoRemoveMerge) + { + ScDocumentUniquePtr pUndoDoc(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, *aMark.begin(), *aMark.rbegin()); + pUndoRemoveMerge.reset( + new ScUndoRemoveMerge(mrDocShell, maRange, std::move(pUndoDoc))); + } + + for (const ScRange& aRange : qIncreaseRange) + { + if (rDoc.HasAttrib(aRange, HasAttrFlags::Overlapped | HasAttrFlags::Merged)) + { + mrDocShell.GetDocFunc().UnmergeCells(aRange, mbRecord, + pUndoRemoveMerge.get()); + } + } + } + } + else + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); + mrDocShell.GetUndoManager()->LeaveListAction(); + return false; + } + } + } + + if (mbRecord && pUndoRemoveMerge) + { + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoRemoveMerge)); + } + + switch (meCmd) + { + case INS_CELLSDOWN: + bSuccess = rDoc.InsertRow(nStartCol, 0, nEndCol, MAXTAB, nStartRow, + static_cast(nEndRow - nStartRow + 1), + pRefUndoDoc.get(), &aFullMark); + nPaintEndRow = rDoc.MaxRow(); + break; + case INS_INSROWS_BEFORE: + case INS_INSROWS_AFTER: + bSuccess = rDoc.InsertRow(0, 0, rDoc.MaxCol(), MAXTAB, nStartRow, + static_cast(nEndRow - nStartRow + 1), + pRefUndoDoc.get(), &aFullMark); + nPaintStartCol = 0; + nPaintEndCol = rDoc.MaxCol(); + nPaintEndRow = rDoc.MaxRow(); + nPaintFlags |= PaintPartFlags::Left; + break; + case INS_CELLSRIGHT: + bSuccess = rDoc.InsertCol(nStartRow, 0, nEndRow, MAXTAB, nStartCol, + static_cast(nEndCol - nStartCol + 1), + pRefUndoDoc.get(), &aFullMark); + nPaintEndCol = rDoc.MaxCol(); + break; + case INS_INSCOLS_BEFORE: + case INS_INSCOLS_AFTER: + bSuccess = rDoc.InsertCol(0, 0, rDoc.MaxRow(), MAXTAB, nStartCol, + static_cast(nEndCol - nStartCol + 1), + pRefUndoDoc.get(), &aFullMark); + nPaintStartRow = 0; + nPaintEndRow = rDoc.MaxRow(); + nPaintEndCol = rDoc.MaxCol(); + nPaintFlags |= PaintPartFlags::Top; + break; + default: + OSL_FAIL("Wrong code at inserting"); + bSuccess = false; + break; + } + + if (bSuccess) + { + SCTAB nUndoPos = 0; + + if (mbRecord) + { + std::unique_ptr pTabs(new SCTAB[nSelCount]); + std::unique_ptr pScenarios(new SCTAB[nSelCount]); + nUndoPos = 0; + for (const auto& rTab : aMark) + { + if (rTab >= nTabCount) + break; + + SCTAB nCount = 0; + for (SCTAB j = rTab + 1; j < nTabCount && rDoc.IsScenario(j); j++) + nCount++; + + pScenarios[nUndoPos] = nCount; + pTabs[nUndoPos] = rTab; + nUndoPos++; + } + + if (!bInsertMerge) + { + mrDocShell.GetUndoManager()->LeaveListAction(); + } + + auto pUndoAction = std::make_unique( + mrDocShell, ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab), + nUndoPos, std::move(pTabs), std::move(pScenarios), meCmd, std::move(pRefUndoDoc), + std::move(pUndoData), mbPartOfPaste); + pUndoInsertCells = pUndoAction.get(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoAction)); + } + + // #i8302 : we remerge growing ranges, with the new part inserted + + while (!qIncreaseRange.empty()) + { + ScRange aRange = qIncreaseRange.back(); + if (!rDoc.HasAttrib(aRange, HasAttrFlags::Overlapped | HasAttrFlags::Merged)) + { + switch (meCmd) + { + case INS_CELLSDOWN: + case INS_INSROWS_BEFORE: + case INS_INSROWS_AFTER: + aRange.aEnd.IncRow(static_cast(nEndRow - nStartRow + 1)); + break; + case INS_CELLSRIGHT: + case INS_INSCOLS_BEFORE: + case INS_INSCOLS_AFTER: + aRange.aEnd.IncCol(static_cast(nEndCol - nStartCol + 1)); + break; + default: + break; + } + ScCellMergeOption aMergeOption(aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row()); + aMergeOption.maTabs.insert(aRange.aStart.Tab()); + mrDocShell.GetDocFunc().MergeCells(aMergeOption, false, true, true); + } + qIncreaseRange.pop_back(); + } + + if (bInsertMerge) + mrDocShell.GetUndoManager()->LeaveListAction(); + + for (const SCTAB i : aMark) + { + if (i >= nTabCount) + break; + + rDoc.SetDrawPageSize(i); + + if (bNeedRefresh) + rDoc.ExtendMerge(nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, + nMergeTestEndRow, i, true); + else + rDoc.RefreshAutoFilter(nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, + nMergeTestEndRow, i); + + if (meCmd == INS_INSROWS_BEFORE || meCmd == INS_INSCOLS_BEFORE + || meCmd == INS_INSROWS_AFTER || meCmd == INS_INSCOLS_AFTER) + rDoc.UpdatePageBreaks(i); + + sal_uInt16 nExtFlags = 0; + mrDocShell.UpdatePaintExt(nExtFlags, nPaintStartCol, nPaintStartRow, i, nPaintEndCol, + nPaintEndRow, i); + + SCTAB nScenarioCount = 0; + + for (SCTAB j = i + 1; j < nTabCount && rDoc.IsScenario(j); j++) + nScenarioCount++; + + bool bAdjusted; + switch (meCmd) + { + case INS_INSROWS_BEFORE: + case INS_INSROWS_AFTER: + bAdjusted = mrDocShell.GetDocFunc().AdjustRowHeight( + ScRange(0, nStartRow, i, rDoc.MaxCol(), nEndRow, i + nScenarioCount), true, + mbApi); + break; + case INS_INSCOLS_BEFORE: + case INS_INSCOLS_AFTER: + case INS_CELLSRIGHT: + // A horizontal insert, a whole column or cells shifted right, only adds empty + // cells and shifts existing cells sideways, leaving their content and column + // widths unchanged, so no row's optimal height can change. Nothing to + // recompute. + bAdjusted = false; + break; + default: + bAdjusted = mrDocShell.GetDocFunc().AdjustRowHeight( + ScRange(0, nPaintStartRow, i, rDoc.MaxCol(), nPaintEndRow, + i + nScenarioCount), + true, mbApi); + break; + } + if (bAdjusted) + { + // paint only what is not done by AdjustRowHeight + if (nPaintFlags & PaintPartFlags::Top) + mrDocShell.PostPaint(nPaintStartCol, nPaintStartRow, i, nPaintEndCol, + nPaintEndRow, i + nScenarioCount, PaintPartFlags::Top); + } + else + mrDocShell.PostPaint(nPaintStartCol, nPaintStartRow, i, nPaintEndCol, nPaintEndRow, + i + nScenarioCount, nPaintFlags, nExtFlags); + } + } + else + { + if (bInsertMerge) + { + while (!qIncreaseRange.empty()) + { + ScRange aRange = qIncreaseRange.back(); + ScCellMergeOption aMergeOption(aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row()); + mrDocShell.GetDocFunc().MergeCells(aMergeOption, false, true, true); + qIncreaseRange.pop_back(); + } + + if (pViewSh) + { + pViewSh->MarkRange(aTargetRange, false); + pViewSh->SetCursor(nCursorCol, nCursorRow); + } + } + + mrDocShell.GetUndoManager()->LeaveListAction(); + mrDocShell.GetUndoManager()->RemoveLastUndoAction(); + + pRefUndoDoc.reset(); + if (!mbApi) + mrDocShell.ErrorMessage(STR_INSERT_FULL); // column/row full + } + + // The cursor position needs to be modified earlier than updating + // any enabled edit view which is triggered by SetDocumentModified below. + if (bSuccess) + { + bool bInsertCols = (meCmd == INS_INSCOLS_BEFORE || meCmd == INS_INSCOLS_AFTER); + bool bInsertRows = (meCmd == INS_INSROWS_BEFORE || meCmd == INS_INSROWS_AFTER); + + if (bInsertCols) + { + pViewSh->OnLOKInsertDeleteColumn( + maRange.aStart.Col() - (meCmd == INS_INSCOLS_BEFORE ? 1 : 0), 1); + } + + if (bInsertRows) + { + pViewSh->OnLOKInsertDeleteRow( + maRange.aStart.Row() - (meCmd == INS_INSROWS_BEFORE ? 1 : 0), 1); + } + + // Update sheet view sort ranges to account for inserted rows/columns + if (bInsertRows || bInsertCols) + { + SCTAB nDefaultViewTab = rDoc.GetDefaultViewTableNumber(nStartTab); + std::shared_ptr pManager + = rDoc.GetSheetViewManager(nDefaultViewTab); + if (pManager) + { + auto pSortDataBefore = pManager->captureSortData(); + + if (bInsertRows) + pManager->insertedRows(nStartRow, nEndRow - nStartRow + 1); + if (bInsertCols) + pManager->insertedColumns(nStartCol, nEndCol - nStartCol + 1); + + auto pSortDataAfter = pManager->captureSortData(); + + if (mbRecord && pUndoInsertCells) + { + pUndoInsertCells->setDefaultViewContext( + nDefaultViewTab, std::move(pSortDataBefore), std::move(pSortDataAfter)); + } + } + } + + syncSheetViews(pUndoInsertCells); + } + + aModificator.SetDocumentModified(); + + SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreaLinksChanged)); + return bSuccess; +} + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/InsertNameListOperation.cxx b/sc/source/ui/operation/InsertNameListOperation.cxx new file mode 100644 index 000000000000..e57f9e4020f5 --- /dev/null +++ b/sc/source/ui/operation/InsertNameListOperation.cxx @@ -0,0 +1,149 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +InsertNameListOperation::InsertNameListOperation(ScDocShell& rDocShell, const ScAddress& rStartPos, + bool bApi) + : Operation(OperationType::InsertNameList, false, bApi) + , mrDocShell(rDocShell) + , maStartPos(rStartPos) +{ +} + +bool InsertNameListOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScAddress aStartPos = convertAddress(maStartPos); + + bool bDone = false; + ScDocument& rDoc = mrDocShell.GetDocument(); + const bool bRecord = rDoc.IsUndoEnabled(); + SCTAB nTab = aStartPos.Tab(); + + // local names have higher priority than global names + ScRangeName* pLocalList = rDoc.GetRangeName(nTab); + sal_uInt16 nValidCount = 0; + for (const auto& rEntry : *pLocalList) + { + const ScRangeData& r = *rEntry.second; + if (!r.HasType(ScRangeData::Type::Database)) + ++nValidCount; + } + ScRangeName& rList = rDoc.GetRangeName(); + for (const auto& rEntry : rList) + { + const ScRangeData& r = *rEntry.second; + if (!r.HasType(ScRangeData::Type::Database) + && !pLocalList->findByUpperName(r.GetUpperName())) + ++nValidCount; + } + + if (nValidCount) + { + SCCOL nStartCol = aStartPos.Col(); + SCROW nStartRow = aStartPos.Row(); + SCCOL nEndCol = nStartCol + 1; + SCROW nEndRow = nStartRow + static_cast(nValidCount) - 1; + + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow); + if (aTester.IsEditable()) + { + ScDocumentUniquePtr pUndoDoc; + + if (bRecord) + { + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nTab, nTab); + rDoc.CopyToDocument(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, + InsertDeleteFlags::ALL, false, *pUndoDoc); + + rDoc.BeginDrawUndo(); // because of adjusting heights + } + + std::unique_ptr ppSortArray(new ScRangeData*[nValidCount]); + sal_uInt16 j = 0; + for (const auto& rEntry : *pLocalList) + { + ScRangeData& r = *rEntry.second; + if (!r.HasType(ScRangeData::Type::Database)) + ppSortArray[j++] = &r; + } + for (const auto & [ rName, rxData ] : rList) + { + ScRangeData& r = *rxData; + if (!r.HasType(ScRangeData::Type::Database) && !pLocalList->findByUpperName(rName)) + ppSortArray[j++] = &r; + } + qsort(static_cast(ppSortArray.get()), nValidCount, sizeof(ScRangeData*), + &ScRangeData_QsortNameCompare); + OUString aName; + OUStringBuffer aContent; + OUString aFormula; + SCROW nOutRow = nStartRow; + for (j = 0; j < nValidCount; j++) + { + ScRangeData* pData = ppSortArray[j]; + pData->GetName(aName); + // adjust relative references to the left column in Excel-compliant way: + pData->UpdateSymbol(aContent, ScAddress(nStartCol, nOutRow, nTab)); + aFormula = "=" + aContent; + ScSetStringParam aParam; + aParam.setTextInput(); + rDoc.SetString(ScAddress(nStartCol, nOutRow, nTab), aName, &aParam); + rDoc.SetString(ScAddress(nEndCol, nOutRow, nTab), aFormula, &aParam); + ++nOutRow; + } + + ppSortArray.reset(); + + if (bRecord) + { + ScDocumentUniquePtr pRedoDoc(new ScDocument(SCDOCMODE_UNDO)); + pRedoDoc->InitUndo(rDoc, nTab, nTab); + rDoc.CopyToDocument(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, + InsertDeleteFlags::ALL, false, *pRedoDoc); + + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, ScRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab), + std::move(pUndoDoc), std::move(pRedoDoc))); + } + + if (!mrDocShell.GetDocFunc().AdjustRowHeight( + ScRange(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab), true, true)) + mrDocShell.PostPaint(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, + PaintPartFlags::Grid); + + syncSheetViews(); + + aModificator.SetDocumentModified(); + bDone = true; + } + else if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + } + return bDone; +} +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/InsertSheetViewOperation.cxx b/sc/source/ui/operation/InsertSheetViewOperation.cxx new file mode 100644 index 000000000000..cf74fc3f78f9 --- /dev/null +++ b/sc/source/ui/operation/InsertSheetViewOperation.cxx @@ -0,0 +1,66 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace sc +{ +InsertSheetViewOperation::InsertSheetViewOperation(ScDocShell& rDocShell, SCTAB nTab, bool bRecord) + : Operation(OperationType::InsertSheetView, bRecord, false) + , mrDocShell(rDocShell) + , mnTab(nTab) +{ +} + +bool InsertSheetViewOperation::runImplementation() +{ + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + DrawUndoGuard aDrawUndoGuard(rDoc, mbRecord); + + auto[nSheetViewID, nSheetViewTab] = rDoc.CreateNewSheetView(mnTab); + if (nSheetViewID == InvalidSheetViewID) + return false; + + mnSheetViewID = nSheetViewID; + mnSheetViewTab = nSheetViewTab; + + if (mbRecord) + mrDocShell.GetUndoManager()->AddUndoAction( + std::make_unique(mrDocShell, mnTab, nSheetViewTab, nSheetViewID)); + + mrDocShell.Broadcast(ScTablesHint(SC_TAB_INSERTED, nSheetViewTab)); + mrDocShell.PostPaintExtras(); + aModificator.SetDocumentModified(); + SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScTablesChanged)); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/InsertSparklinesOperation.cxx b/sc/source/ui/operation/InsertSparklinesOperation.cxx new file mode 100644 index 000000000000..d9a875ab076d --- /dev/null +++ b/sc/source/ui/operation/InsertSparklinesOperation.cxx @@ -0,0 +1,115 @@ +/* -*- 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 + +#include +#include +#include +#include + +namespace sc +{ +InsertSparklinesOperation::InsertSparklinesOperation( + ScDocShell& rDocShell, ScRange const& rDataRange, ScRange const& rSparklineRange, + std::shared_ptr const& pSparklineGroup) + : Operation(OperationType::SparklineInsert, false, false) + , mrDocShell(rDocShell) + , maDataRange(rDataRange) + , maSparklineRange(rSparklineRange) + , mpSparklineGroup(pSparklineGroup) +{ +} + +bool InsertSparklinesOperation::runImplementation() +{ + ScRange aDataRange = convertRange(maDataRange); + ScRange aSparklineRange = convertRange(maSparklineRange); + + std::vector aSparklineDataVector; + + if (aSparklineRange.aStart.Col() == aSparklineRange.aEnd.Col()) + { + sal_Int32 nOutputRowSize = aSparklineRange.aEnd.Row() - aSparklineRange.aStart.Row(); + + auto eInputOrientation = calculateOrientation(nOutputRowSize, aDataRange); + + if (eInputOrientation == RangeOrientation::Unknown) + return false; + + sal_Int32 nIndex = 0; + + for (ScAddress aAddress = aSparklineRange.aStart; + aAddress.Row() <= aSparklineRange.aEnd.Row(); aAddress.IncRow()) + { + ScRange aInputRangeSlice = aDataRange; + if (eInputOrientation == RangeOrientation::Row) + { + aInputRangeSlice.aStart.SetRow(aDataRange.aStart.Row() + nIndex); + aInputRangeSlice.aEnd.SetRow(aDataRange.aStart.Row() + nIndex); + } + else + { + aInputRangeSlice.aStart.SetCol(aDataRange.aStart.Col() + nIndex); + aInputRangeSlice.aEnd.SetCol(aDataRange.aStart.Col() + nIndex); + } + + aSparklineDataVector.emplace_back(aAddress, aInputRangeSlice); + + nIndex++; + } + } + else if (aSparklineRange.aStart.Row() == aSparklineRange.aEnd.Row()) + { + sal_Int32 nOutputColSize = aSparklineRange.aEnd.Col() - aSparklineRange.aStart.Col(); + + auto eInputOrientation = calculateOrientation(nOutputColSize, aDataRange); + + if (eInputOrientation == RangeOrientation::Unknown) + return false; + + sal_Int32 nIndex = 0; + + for (ScAddress aAddress = aSparklineRange.aStart; + aAddress.Col() <= aSparklineRange.aEnd.Col(); aAddress.IncCol()) + { + ScRange aInputRangeSlice = aDataRange; + if (eInputOrientation == RangeOrientation::Row) + { + aInputRangeSlice.aStart.SetRow(aDataRange.aStart.Row() + nIndex); + aInputRangeSlice.aEnd.SetRow(aDataRange.aStart.Row() + nIndex); + } + else + { + aInputRangeSlice.aStart.SetCol(aDataRange.aStart.Col() + nIndex); + aInputRangeSlice.aEnd.SetCol(aDataRange.aStart.Col() + nIndex); + } + + aSparklineDataVector.emplace_back(aAddress, aInputRangeSlice); + + nIndex++; + } + } + + if (aSparklineDataVector.empty()) + return false; + + auto pUndoInsertSparkline + = std::make_unique(mrDocShell, aSparklineDataVector, mpSparklineGroup); + // insert the sparkline by "redoing" + pUndoInsertSparkline->Redo(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoInsertSparkline)); + + syncSheetViews(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/InsertThreadedCommentOperation.cxx b/sc/source/ui/operation/InsertThreadedCommentOperation.cxx new file mode 100644 index 000000000000..d3b30834b832 --- /dev/null +++ b/sc/source/ui/operation/InsertThreadedCommentOperation.cxx @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sc +{ +InsertThreadedCommentOperation::InsertThreadedCommentOperation(ScDocShell& rDocShell, + const ScAddress& rPos, + const OUString& rText, + const OUString* pAuthor, bool bApi) + : Operation(OperationType::InsertThreadedComment, false, bApi) + , mrDocShell(rDocShell) + , maPos(rPos) + , maText(rText) + , moAuthor(pAuthor ? std::optional(*pAuthor) : std::nullopt) +{ +} + +bool InsertThreadedCommentOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + + ScAddress aPos = convertAddress(maPos); + + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, aPos.Tab(), aPos.Col(), aPos.Row(), aPos.Col(), aPos.Row()); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); + SfxUndoManager* pUndoMgr + = (pDrawLayer && rDoc.IsUndoEnabled()) ? mrDocShell.GetUndoManager() : nullptr; + + // Rescue the existing note (if any) for undo. Threaded data lives on ScPostIt + // outside ScNoteData, so capture it separately. + ScNoteData aOldData; + std::unique_ptr pOldThreadedData; + std::unique_ptr pOldNote = rDoc.ReleaseNote(aPos); + sal_uInt32 nNoteId = 0; + if (pOldNote) + { + nNoteId = pOldNote->GetId(); + // ensure existing caption object before draw undo tracking starts + pOldNote->GetOrCreateCaption(aPos); + aOldData = pOldNote->GetNoteData(); + if (const ScThreadedCommentData* pOldThreaded = pOldNote->GetThreadedCommentData()) + pOldThreadedData = std::make_unique(*pOldThreaded); + } + + if (pUndoMgr) + pDrawLayer->BeginCalcUndo(false); + + // delete the old note (creates drawing undo action for the caption object) + bool hadOldNote(pOldNote); + pOldNote.reset(); + + // create new note (creates drawing undo action for the new caption object) + ScNoteData aNewData; + std::unique_ptr pNewThreadedData; + ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString(rDoc, aPos, maText, false, true, nNoteId); + if (pNewNote) + { + OUString aAuthor = moAuthor.value_or(OUString()); + if (aAuthor.isEmpty()) + aAuthor = SvtUserOptions().GetFullName(); + if (aAuthor.isEmpty()) + aAuthor = ScResId(STR_CHG_UNKNOWN_AUTHOR); + + // Resolve the person entry; create one with a stable UUIDv5 derived from + // the author name so the same user gets the same person-id across documents. + OUString aPersonId; + for (const auto& rPerson : rDoc.GetPersonList()) + { + if (rPerson.maDisplayName == aAuthor) + { + aPersonId = rPerson.maId; + break; + } + } + if (aPersonId.isEmpty()) + { + // Namespace string is wire-stable; changing it remaps every existing + // document's person-ids and breaks author matching on reopen. + OString aInput = "LibreOffice:ThreadedCommentPerson:" + + OUStringToOString(aAuthor, RTL_TEXTENCODING_UTF8); + ::std::vector aDigest{ ::comphelper::Hash::calculateHash( + aInput.getStr(), aInput.getLength(), ::comphelper::HashType::SHA1) }; + aDigest[6] = (aDigest[6] & 0x0F) | 0x50; // version 5 + aDigest[8] = (aDigest[8] & 0x3F) | 0x80; // variant RFC 4122 + tools::Guid aPersonGuid(aDigest.data()); + + ScPersonData aPerson; + aPerson.maId = aPersonGuid.getOUString(); + aPerson.maDisplayName = aAuthor; + aPerson.maUserId = aAuthor; + aPerson.maProviderId = u"None"_ustr; + aPersonId = aPerson.maId; + rDoc.AddPerson(aPerson); + } + + auto pThreaded = std::make_unique(); + pThreaded->maRoot.maGuid = tools::Guid(tools::Guid::Generate).getOUString(); + pThreaded->maRoot.maDateTime = utl::toISO8601(DateTime(DateTime::SYSTEM).GetUNODateTime()); + pThreaded->maRoot.maPersonId = aPersonId; + pThreaded->maRoot.maText = maText; + + pNewNote->SetAuthor(aAuthor); + pNewNote->SetThreadedCommentData(std::move(pThreaded)); + + aNewData = pNewNote->GetNoteData(); + if (const ScThreadedCommentData* pNewThreaded = pNewNote->GetThreadedCommentData()) + pNewThreadedData = std::make_unique(*pNewThreaded); + } + + if (pUndoMgr && (aOldData.mxCaption || aNewData.mxCaption)) + pUndoMgr->AddUndoAction(std::make_unique( + mrDocShell, aPos, std::move(aOldData), std::move(aNewData), pDrawLayer->GetCalcUndo(), + std::move(pOldThreadedData), std::move(pNewThreadedData))); + + mrDocShell.PostPaintCell(aPos); + + rDoc.SetStreamValid(aPos.Tab(), false); + + syncSheetViews(); + + aModificator.SetDocumentModified(); + + if (pNewNote) + { + ScDocShell::LOKCommentNotify(hadOldNote ? LOKCommentNotificationType::Modify + : LOKCommentNotificationType::Add, + rDoc, aPos, pNewNote); + } + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/ui/operation/MergeCellsOperation.cxx b/sc/source/ui/operation/MergeCellsOperation.cxx new file mode 100644 index 000000000000..fa6b010a877f --- /dev/null +++ b/sc/source/ui/operation/MergeCellsOperation.cxx @@ -0,0 +1,176 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace sc +{ +MergeCellsOperation::MergeCellsOperation(ScDocShell& rDocShell, const ScCellMergeOption& rOption, + bool bContents, bool bRecord, bool bApi, + bool bEmptyMergedCells) + : Operation(OperationType::MergeCells, bRecord, bApi) + , mrDocShell(rDocShell) + , maOption(rOption) + , mbContents(bContents) + , mbEmptyMergedCells(bEmptyMergedCells) +{ +} + +bool MergeCellsOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScCellMergeOption aOption(maOption); + { + std::set aConvertedTabs; + for (SCTAB nTab : aOption.maTabs) + { + ScAddress aConverted = convertAddress(ScAddress(0, 0, nTab)); + aConvertedTabs.insert(aConverted.Tab()); + } + aOption.maTabs = std::move(aConvertedTabs); + } + + SCCOL nStartCol = aOption.mnStartCol; + SCROW nStartRow = aOption.mnStartRow; + SCCOL nEndCol = aOption.mnEndCol; + SCROW nEndRow = aOption.mnEndRow; + if ((nStartCol == nEndCol && nStartRow == nEndRow) || aOption.maTabs.empty()) + { + // Nothing to do. Bail out quickly + return true; + } + + ScDocument& rDoc = mrDocShell.GetDocument(); + SCTAB nTab1 = *aOption.maTabs.begin(), nTab2 = *aOption.maTabs.rbegin(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + for (const auto& rTab : aOption.maTabs) + { + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, rTab, nStartCol, nStartRow, nEndCol, nEndRow); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + if (rDoc.HasAttrib(nStartCol, nStartRow, rTab, nEndCol, nEndRow, rTab, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)) + { + // "Merge of already merged cells not possible" + if (!mbApi) + mrDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0); + return false; + } + } + + ScDocumentUniquePtr pUndoDoc; + bool bNeedContentsUndo = false; + for (const SCTAB nTab : aOption.maTabs) + { + bool bIsBlockEmpty + = (nStartRow == nEndRow) + ? rDoc.IsEmptyData(nStartCol + 1, nStartRow, nEndCol, nEndRow, nTab) + : rDoc.IsEmptyData(nStartCol, nStartRow + 1, nStartCol, nEndRow, nTab) + && rDoc.IsEmptyData(nStartCol + 1, nStartRow, nEndCol, nEndRow, nTab); + bool bNeedContents = mbContents && !bIsBlockEmpty; + bool bNeedEmpty = mbEmptyMergedCells && !bIsBlockEmpty + && !bNeedContents; // if DoMergeContents then cells are emptied + + if (mbRecord) + { + // test if the range contains other notes which also implies that we need an undo document + bool bHasNotes = rDoc.HasNote(nTab, nStartCol, nStartRow, nEndCol, nEndRow); + if (!pUndoDoc) + { + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nTab1, nTab2); + } + // note captions are collected by drawing undo + rDoc.CopyToDocument(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, + InsertDeleteFlags::ALL | InsertDeleteFlags::NOCAPTIONS, false, + *pUndoDoc); + if (bHasNotes) + rDoc.BeginDrawUndo(); + } + + if (bNeedContents) + rDoc.DoMergeContents(nStartCol, nStartRow, nEndCol, nEndRow, nTab); + else if (bNeedEmpty) + rDoc.DoEmptyBlock(nStartCol, nStartRow, nEndCol, nEndRow, nTab); + rDoc.DoMerge(nStartCol, nStartRow, nEndCol, nEndRow, nTab); + + if (aOption.mbCenter) + { + rDoc.ApplyAttr(nStartCol, nStartRow, nTab, + SvxHorJustifyItem(SvxCellHorJustify::Center, ATTR_HOR_JUSTIFY)); + rDoc.ApplyAttr(nStartCol, nStartRow, nTab, + SvxVerJustifyItem(SvxCellVerJustify::Center, ATTR_VER_JUSTIFY)); + } + + if (!mrDocShell.GetDocFunc().AdjustRowHeight( + ScRange(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab), true, mbApi)) + mrDocShell.PostPaint(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, + PaintPartFlags::Grid); + if (bNeedContents || aOption.mbCenter) + { + ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab); + rDoc.SetDirty(aRange, true); + } + + bool bDone = ScDetectiveFunc(rDoc, nTab).DeleteAll(ScDetectiveDelete::Circles); + if (bDone) + mrDocShell.GetDocFunc().DetectiveMarkInvalid(nTab); + + bNeedContentsUndo |= bNeedContents; + } + + if (pUndoDoc) + { + std::unique_ptr pDrawUndo + = rDoc.GetDrawLayer() ? rDoc.GetDrawLayer()->GetCalcUndo() : nullptr; + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aOption, bNeedContentsUndo, std::move(pUndoDoc), std::move(pDrawUndo))); + } + + syncSheetViews(); + + aModificator.SetDocumentModified(); + + SfxBindings* pBindings = mrDocShell.GetViewBindings(); + if (pBindings) + { + pBindings->Invalidate(FID_MERGE_ON); + pBindings->Invalidate(FID_MERGE_OFF); + pBindings->Invalidate(FID_MERGE_TOGGLE); + } + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/MoveBlockOperation.cxx b/sc/source/ui/operation/MoveBlockOperation.cxx new file mode 100644 index 000000000000..a2c76634dccc --- /dev/null +++ b/sc/source/ui/operation/MoveBlockOperation.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/. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sc +{ +MoveBlockOperation::MoveBlockOperation(ScDocShell& rDocShell, const ScRange& rSource, + const ScAddress& rDestPos, bool bCut, bool bRecord, + bool bPaint, bool bApi) + : Operation(OperationType::MoveBlock, bRecord, bApi) + , mrDocShell(rDocShell) + , maSource(rSource) + , maDestPos(rDestPos) + , mbCut(bCut) + , mbPaint(bPaint) +{ +} + +bool MoveBlockOperation::canRunTheOperation() const +{ + return !isInputOnSheetViewAutoFilter(maSource) + && !isInputOnSheetViewAutoFilter(ScRange(maDestPos)); +} + +bool MoveBlockOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScRange aSource = convertRange(maSource); + ScAddress aDestPos = convertAddress(maDestPos); + + SCCOL nStartCol = aSource.aStart.Col(); + SCROW nStartRow = aSource.aStart.Row(); + SCTAB nStartTab = aSource.aStart.Tab(); + SCCOL nEndCol = aSource.aEnd.Col(); + SCROW nEndRow = aSource.aEnd.Row(); + SCTAB nEndTab = aSource.aEnd.Tab(); + SCCOL nDestCol = aDestPos.Col(); + SCROW nDestRow = aDestPos.Row(); + SCTAB nDestTab = aDestPos.Tab(); + + ScDocument& rDoc = mrDocShell.GetDocument(); + if (!rDoc.ValidRow(nStartRow) || !rDoc.ValidRow(nEndRow) || !rDoc.ValidRow(nDestRow)) + { + OSL_FAIL("invalid row in MoveBlock"); + return false; + } + + // adjust related scenarios too - but only when moved within one sheet + bool bScenariosAdded = false; + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + SCTAB nTabCount = rDoc.GetTableCount(); + if (nDestTab == nStartTab && !rDoc.IsScenario(nEndTab)) + while (nEndTab + 1 < nTabCount && rDoc.IsScenario(nEndTab + 1)) + { + ++nEndTab; + bScenariosAdded = true; + } + + SCTAB nSrcTabCount = nEndTab - nStartTab + 1; + SCTAB nDestEndTab = nDestTab + nSrcTabCount - 1; + SCTAB nTab; + + ScDocumentUniquePtr pClipDoc(new ScDocument(SCDOCMODE_CLIP)); + + ScMarkData aSourceMark(rDoc.GetSheetLimits()); + for (nTab = nStartTab; nTab <= nEndTab; nTab++) + aSourceMark.SelectTable(nTab, true); // select source + aSourceMark.SetMarkArea(aSource); + + ScDocShellRef aDragShellRef; + if (rDoc.HasOLEObjectsInArea(aSource)) + { + aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately + aDragShellRef->DoInitNew(); + } + ScDrawLayer::SetGlobalDrawPersist(aDragShellRef.get()); + + ScClipParam aClipParam(ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nStartTab), + mbCut); + rDoc.CopyToClip(aClipParam, pClipDoc.get(), &aSourceMark, bScenariosAdded, true); + + ScDrawLayer::SetGlobalDrawPersist(nullptr); + + SCCOL nOldEndCol = nEndCol; + SCROW nOldEndRow = nEndRow; + bool bClipOver = false; + for (nTab = nStartTab; nTab <= nEndTab; nTab++) + { + SCCOL nTmpEndCol = nOldEndCol; + SCROW nTmpEndRow = nOldEndRow; + if (rDoc.ExtendMerge(nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab)) + bClipOver = true; + if (nTmpEndCol > nEndCol) + nEndCol = nTmpEndCol; + if (nTmpEndRow > nEndRow) + nEndRow = nTmpEndRow; + } + + SCCOL nDestEndCol = nDestCol + (nOldEndCol - nStartCol); + SCROW nDestEndRow = nDestRow + (nOldEndRow - nStartRow); + + SCCOL nUndoEndCol = nDestCol + (nEndCol - nStartCol); // extended in destination block + SCROW nUndoEndRow = nDestRow + (nEndRow - nStartRow); + + bool bIncludeFiltered = mbCut; + if (!bIncludeFiltered) + { + // adjust sizes to include only non-filtered rows + + SCCOL nClipX; + SCROW nClipY; + pClipDoc->GetClipArea(nClipX, nClipY, false); + SCROW nUndoAdd = nUndoEndRow - nDestEndRow; + nDestEndRow = nDestRow + nClipY; + nUndoEndRow = nDestEndRow + nUndoAdd; + } + + if (!rDoc.ValidCol(nUndoEndCol) || !rDoc.ValidRow(nUndoEndRow)) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_PASTE_FULL); + return false; + } + + // Test for cell protection + + ScEditableTester aTester; + for (nTab = nDestTab; nTab <= nDestEndTab; nTab++) + aTester.TestBlock(rDoc, nTab, nDestCol, nDestRow, nUndoEndCol, nUndoEndRow); + if (mbCut) + for (nTab = nStartTab; nTab <= nEndTab; nTab++) + aTester.TestBlock(rDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow); + + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + // Test for merged cells- when moving after delete + + if (bClipOver && !mbCut) + if (rDoc.HasAttrib(nDestCol, nDestRow, nDestTab, nUndoEndCol, nUndoEndRow, nDestEndTab, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)) + { // "Merge of already merged cells not possible" + if (!mbApi) + mrDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0); + return false; + } + + // Are there borders in the cells? (for painting) + + sal_uInt16 nSourceExt = 0; + mrDocShell.UpdatePaintExt(nSourceExt, nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, + nEndTab); + sal_uInt16 nDestExt = 0; + mrDocShell.UpdatePaintExt(nDestExt, nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, + nDestEndTab); + + // do it + + ScDocumentUniquePtr pUndoDoc; + + if (mbRecord) + { + bool bWholeCols = (nStartRow == 0 && nEndRow == rDoc.MaxRow()); + bool bWholeRows = (nStartCol == 0 && nEndCol == rDoc.MaxCol()); + InsertDeleteFlags nUndoFlags = (InsertDeleteFlags::ALL & ~InsertDeleteFlags::OBJECTS) + | InsertDeleteFlags::NOCAPTIONS; + + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nStartTab, nEndTab, bWholeCols, bWholeRows); + + if (mbCut) + { + rDoc.CopyToDocument(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, + nUndoFlags, false, *pUndoDoc); + } + + if (nDestTab != nStartTab) + pUndoDoc->AddUndoTab(nDestTab, nDestEndTab, bWholeCols, bWholeRows); + rDoc.CopyToDocument(nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab, + nUndoFlags, false, *pUndoDoc); + rDoc.BeginDrawUndo(); + } + + bool bSourceHeight = false; // adjust heights? + if (mbCut) + { + ScMarkData aDelMark(rDoc.GetSheetLimits()); // only for tables + for (nTab = nStartTab; nTab <= nEndTab; nTab++) + { + rDoc.DeleteAreaTab(nStartCol, nStartRow, nOldEndCol, nOldEndRow, nTab, + InsertDeleteFlags::ALL); + aDelMark.SelectTable(nTab, true); + } + rDoc.DeleteObjectsInArea(nStartCol, nStartRow, nOldEndCol, nOldEndRow, aDelMark); + + // Test for merged cells + + if (bClipOver) + if (rDoc.HasAttrib(nDestCol, nDestRow, nDestTab, nUndoEndCol, nUndoEndRow, nDestEndTab, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)) + { + rDoc.CopyFromClip(aSource, aSourceMark, InsertDeleteFlags::ALL, nullptr, + pClipDoc.get()); + for (nTab = nStartTab; nTab <= nEndTab; nTab++) + { + SCCOL nTmpEndCol = nEndCol; + SCROW nTmpEndRow = nEndRow; + rDoc.ExtendMerge(nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, true); + } + + // Report error only after restoring content + if (!mbApi) // "Merge of already merged cells not possible" + mrDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0); + + return false; + } + + bSourceHeight = mrDocShell.GetDocFunc().AdjustRowHeight(aSource, false, mbApi); + } + + ScRange aPasteDest(nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab); + + ScMarkData aDestMark(rDoc.GetSheetLimits()); + for (nTab = nDestTab; nTab <= nDestEndTab; nTab++) + aDestMark.SelectTable(nTab, true); // select destination + aDestMark.SetMarkArea(aPasteDest); + + /* Do not copy drawing objects here. While pasting, the + function ScDocument::UpdateReference() is called which calls + ScDrawLayer::MoveCells() which may move away inserted objects to wrong + positions (e.g. if source and destination range overlaps).*/ + + rDoc.CopyFromClip(aPasteDest, aDestMark, InsertDeleteFlags::ALL & ~InsertDeleteFlags::OBJECTS, + pUndoDoc.get(), pClipDoc.get(), true, false, bIncludeFiltered); + + // skipped rows and merged cells don't mix + if (!bIncludeFiltered && pClipDoc->HasClipFilteredRows()) + mrDocShell.GetDocFunc().UnmergeCells(aPasteDest, false, nullptr); + + bool bDestHeight = mrDocShell.GetDocFunc().AdjustRowHeight( + ScRange(0, nDestRow, nDestTab, rDoc.MaxCol(), nDestEndRow, nDestEndTab), false, mbApi); + + /* Paste drawing objects after adjusting formula references + and row heights. There are no cell notes or drawing objects, if the + clipdoc does not contain a drawing layer.*/ + if (pClipDoc->GetDrawLayer()) + rDoc.CopyFromClip(aPasteDest, aDestMark, InsertDeleteFlags::OBJECTS, nullptr, + pClipDoc.get(), true, false, bIncludeFiltered); + + if (mbRecord) + { + ScRange aUndoRange(nStartCol, nStartRow, nStartTab, nOldEndCol, nOldEndRow, nEndTab); + ScAddress aDestPosUndo(nDestCol, nDestRow, nDestTab); + + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aUndoRange, aDestPosUndo, mbCut, std::move(pUndoDoc), bScenariosAdded)); + } + + SCCOL nDestPaintEndCol = nDestEndCol; + SCROW nDestPaintEndRow = nDestEndRow; + for (nTab = nDestTab; nTab <= nDestEndTab; nTab++) + { + SCCOL nTmpEndCol = nDestEndCol; + SCROW nTmpEndRow = nDestEndRow; + rDoc.ExtendMerge(nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, true); + if (nTmpEndCol > nDestPaintEndCol) + nDestPaintEndCol = nTmpEndCol; + if (nTmpEndRow > nDestPaintEndRow) + nDestPaintEndRow = nTmpEndRow; + } + + if (mbCut) + for (nTab = nStartTab; nTab <= nEndTab; nTab++) + rDoc.RefreshAutoFilter(nStartCol, nStartRow, nEndCol, nEndRow, nTab); + + if (mbPaint) + { + // destination range: + + SCCOL nPaintStartX = nDestCol; + SCROW nPaintStartY = nDestRow; + SCCOL nPaintEndX = nDestPaintEndCol; + SCROW nPaintEndY = nDestPaintEndRow; + PaintPartFlags nFlags = PaintPartFlags::Grid; + + if (nStartRow == 0 && nEndRow == rDoc.MaxRow()) // copy widths too? + { + nPaintEndX = rDoc.MaxCol(); + nPaintStartY = 0; + nPaintEndY = rDoc.MaxRow(); + nFlags |= PaintPartFlags::Top; + } + if (bDestHeight || (nStartCol == 0 && nEndCol == rDoc.MaxCol())) + { + nPaintEndY = rDoc.MaxRow(); + nPaintStartX = 0; + nPaintEndX = rDoc.MaxCol(); + nFlags |= PaintPartFlags::Left; + } + if (bScenariosAdded) + { + nPaintStartX = 0; + nPaintStartY = 0; + nPaintEndX = rDoc.MaxCol(); + nPaintEndY = rDoc.MaxRow(); + } + + mrDocShell.PostPaint(nPaintStartX, nPaintStartY, nDestTab, nPaintEndX, nPaintEndY, + nDestEndTab, nFlags, nSourceExt | nDestExt); + + if (mbCut) + { + // source range: + + nPaintStartX = nStartCol; + nPaintStartY = nStartRow; + nPaintEndX = nEndCol; + nPaintEndY = nEndRow; + nFlags = PaintPartFlags::Grid; + + if (bSourceHeight) + { + nPaintEndY = rDoc.MaxRow(); + nPaintStartX = 0; + nPaintEndX = rDoc.MaxCol(); + nFlags |= PaintPartFlags::Left; + } + if (bScenariosAdded) + { + nPaintStartX = 0; + nPaintStartY = 0; + nPaintEndX = rDoc.MaxCol(); + nPaintEndY = rDoc.MaxRow(); + } + + mrDocShell.PostPaint(nPaintStartX, nPaintStartY, nStartTab, nPaintEndX, nPaintEndY, + nEndTab, nFlags, nSourceExt); + } + } + + syncSheetViews(); + + aModificator.SetDocumentModified(); + + SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreaLinksChanged)); + + mrDocShell.ResolveSpilledOutputs(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/MultipleOpsOperation.cxx b/sc/source/ui/operation/MultipleOpsOperation.cxx new file mode 100644 index 000000000000..36720c94b89a --- /dev/null +++ b/sc/source/ui/operation/MultipleOpsOperation.cxx @@ -0,0 +1,110 @@ +/* -*- 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 + +#include +#include +#include +#include + +#include +#include + +#include + +namespace sc +{ +MultipleOpsOperation::MultipleOpsOperation(ScDocShell& rDocShell, const ScRange& rRange, + const ScMarkData* pTabMark, const ScTabOpParam& rParam, + bool bRecord, bool bApi) + : Operation(OperationType::MultipleOps, bRecord, bApi) + , mrDocShell(rDocShell) + , maRange(rRange) + , mpTabMark(pTabMark) + , maParam(rParam) +{ +} + +ScRefAddress MultipleOpsOperation::convertRefAddress(ScRefAddress const& rRefAddress) +{ + ScAddress aConverted = convertAddress(rRefAddress.GetAddress()); + ScRefAddress aResult; + aResult.Set(aConverted, rRefAddress.IsRelCol(), rRefAddress.IsRelRow(), rRefAddress.IsRelTab()); + return aResult; +} + +bool MultipleOpsOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScRange aRange = convertRange(maRange); + ScTabOpParam aParam; + aParam.aRefFormulaCell = convertRefAddress(maParam.aRefFormulaCell); + aParam.aRefFormulaEnd = convertRefAddress(maParam.aRefFormulaEnd); + aParam.aRefRowCell = convertRefAddress(maParam.aRefRowCell); + aParam.aRefColCell = convertRefAddress(maParam.aRefColCell); + aParam.meMode = maParam.meMode; + + bool bSuccess = false; + ScDocument& rDoc = mrDocShell.GetDocument(); + SCCOL nStartCol = aRange.aStart.Col(); + SCROW nStartRow = aRange.aStart.Row(); + SCTAB nStartTab = aRange.aStart.Tab(); + SCCOL nEndCol = aRange.aEnd.Col(); + SCROW nEndRow = aRange.aEnd.Row(); + SCTAB nEndTab = aRange.aEnd.Tab(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScMarkData aMark(rDoc.GetSheetLimits()); + if (mpTabMark) + aMark = convertMark(*mpTabMark); + else + { + for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++) + aMark.SelectTable(nTab, true); + } + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock( + rDoc, nStartCol, nStartRow, nEndCol, nEndRow, aMark); + if (aTester.IsEditable()) + { + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + rDoc.SetDirty(aRange, false); + if (mbRecord) + { + //! take selected sheets into account also when undoing + ScDocumentUniquePtr pUndoDoc(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nStartTab, nEndTab); + rDoc.CopyToDocument(aRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, + *pUndoDoc); + + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, + std::move(pUndoDoc), aParam.aRefFormulaCell, aParam.aRefFormulaEnd, + aParam.aRefRowCell, aParam.aRefColCell, aParam.meMode)); + } + + rDoc.InsertTableOp(aParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark); + + syncSheetViews(); + mrDocShell.PostPaintGridAll(); + aModificator.SetDocumentModified(); + bSuccess = true; + } + else if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + + return bSuccess; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/Operation.cxx b/sc/source/ui/operation/Operation.cxx new file mode 100644 index 000000000000..fe6f9a6936a2 --- /dev/null +++ b/sc/source/ui/operation/Operation.cxx @@ -0,0 +1,584 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sc +{ +namespace +{ +std::shared_ptr getCurrentSheetView(ScViewData* pViewData) +{ + if (!pViewData) + return nullptr; + + sc::SheetViewID nID = pViewData->GetSheetViewID(); + if (nID == sc::DefaultSheetViewID) + return nullptr; + + std::shared_ptr pSheetViewManager + = pViewData->GetCurrentSheetViewManager(); + if (!pSheetViewManager) + return nullptr; + + return pSheetViewManager->get(nID); +} +} + +Operation::Operation(OperationType eType, bool bRecord, bool bApi) + : meType(eType) + , mbApi(bApi) + , mbRecord(bRecord) + , mpViewData(ScDocShell::GetViewData()) +{ +} + +SCTAB Operation::convertTab(SCTAB nTab) +{ + std::shared_ptr pSheetView = getCurrentSheetView(mpViewData); + if (!pSheetView) + return nTab; + + SCTAB nSheetViewTab = mpViewData->GetTabNumber(); + if (nTab != nSheetViewTab) + return nTab; + + return mpViewData->GetDefaultViewTab(); +} + +ScAddress Operation::convertAddress(ScAddress const& rAddress) +{ + SCTAB nConvertedTab = convertTab(rAddress.Tab()); + + // Tab was not converted, so no need to convert the address + if (nConvertedTab == rAddress.Tab()) + return rAddress; + + ScAddress aAddress(rAddress.Col(), rAddress.Row(), nConvertedTab); + + std::shared_ptr pSheetView = getCurrentSheetView(mpViewData); + + SCCOL nColumn = aAddress.Col(); + SCROW nRow = aAddress.Row(); + + SCROW nReversedRow = pSheetView->reverseSortingToDefaultView(nRow, nColumn); + + // Check if there was a change + if (nReversedRow == nRow) + return aAddress; + + return ScAddress(nColumn, nReversedRow, nConvertedTab); +} + +ScRange Operation::convertRange(ScRange const& rRange) +{ + return ScRange(convertAddress(rRange.aStart), convertAddress(rRange.aEnd)); +} + +ScRangeList Operation::convertRangeList(ScRangeList const& rRangeList) +{ + ScRangeList aConverted; + for (size_t i = 0; i < rRangeList.size(); ++i) + aConverted.push_back(convertRange(rRangeList[i])); + return aConverted; +} + +ScMarkData Operation::convertMark(ScMarkData const& rMarkData) +{ + ScViewData* pViewData = mpViewData; + + std::shared_ptr pSheetView = getCurrentSheetView(pViewData); + + // We get a valid pSheetView if we currently are in a sheet view, otherwise we don't need to convert + if (!pSheetView) + return rMarkData; + + SCTAB nSheetViewTab = pViewData->GetTabNumber(); + SCTAB nDefaultViewTab = pViewData->GetDefaultViewTab(); + + ScMarkData aNewMark(rMarkData); + aNewMark.MarkToMulti(); + bool bChanged = false; + + // Adjust tab to default view in ranges + if (nSheetViewTab == aNewMark.GetArea().aStart.Tab() + && nSheetViewTab == aNewMark.GetArea().aEnd.Tab()) + { + aNewMark.SetAreaTab(nDefaultViewTab); + bChanged = true; + } + + // If sheet view tab is selected, deselect and select default view tab instead + if (aNewMark.GetTableSelect(nSheetViewTab)) + { + aNewMark.SelectTable(nSheetViewTab, false); + aNewMark.SelectTable(nDefaultViewTab, true); + bChanged = true; + } + + // Take sorting into account when we convert to default view + if (aNewMark.GetTableSelect(nDefaultViewTab)) + { + SortOrderReverser const* pSortOrder = pSheetView->getSortOrder(); + ReorderParam const* pReorderParams = pSheetView->getReorderParameters(); + if (pSortOrder || pReorderParams) + { + std::vector> aMarkedCells; + + SCROW nRowStart = -1; + SCROW nRowEnd = -1; + SCCOL nColumnStart = -1; + SCCOL nColumnEnd = -1; + + if (pSortOrder) + { + SortOrderInfo const& rSortInfo = pSortOrder->maSortInfo; + nRowStart = rSortInfo.mnFirstRow; + nRowEnd = rSortInfo.mnLastRow; + nColumnStart = rSortInfo.mnFirstColumn; + nColumnEnd = rSortInfo.mnLastColumn; + } + else + { + ScRange const& rSortRange = pReorderParams->maSortRange; + nRowStart = rSortRange.aStart.Row(); + nRowEnd = rSortRange.aEnd.Row(); + nColumnStart = rSortRange.aStart.Col(); + nColumnEnd = rSortRange.aEnd.Col(); + } + + for (SCROW nRow = nRowStart; nRow <= nRowEnd; ++nRow) + { + for (SCCOL nColumn = nColumnStart; nColumn <= nColumnEnd; ++nColumn) + { + if (aNewMark.IsCellMarked(nColumn, nRow)) + { + // unmark the cell here, but remember which cell it was + ScRange aRange(nColumn, nRow, nDefaultViewTab, nColumn, nRow, + nDefaultViewTab); + aNewMark.SetMultiMarkArea(aRange, false); + aMarkedCells.emplace_back(nColumn, nRow); + } + } + } + for (auto & [ nColumn, nRow ] : aMarkedCells) + { + // reverse the row and mark the cell again + SCROW nReversedRow = pSheetView->reverseSortingToDefaultView(nRow, nColumn); + ScRange aRange(nColumn, nReversedRow, nDefaultViewTab, nColumn, nReversedRow, + nDefaultViewTab); + aNewMark.SetMultiMarkArea(aRange, true); + bChanged = true; + } + } + } + + if (!bChanged) + return rMarkData; + + if (bChanged && !aNewMark.HasAnyMultiMarks()) + aNewMark.ResetMark(); + + aNewMark.MarkToSimple(); + + return aNewMark; +} + +void Operation::syncSheetViews(UndoSheetViewSortData* pUndoSortData) +{ + if (!mpViewData) + return; + + auto& rDocument = mpViewData->GetDocument(); + SCTAB nDefaultViewTab = mpViewData->GetDefaultViewTab(); + + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + + // Capture sort data before adjustments + std::shared_ptr pSortDataBefore; + if (pManager) + pSortDataBefore = pManager->captureSortData(); + + // Adjust auto-filter DB range to match actual data extent + ScRange aAutoFilterRangeBefore; + bool bAutoFilterRangeChanged = false; + if (pManager && !pManager->isEmpty()) + { + ScDBData* pDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + if (pDBData && pDBData->HasAutoFilter()) + { + pDBData->GetArea(aAutoFilterRangeBefore); + SCCOL nColumn1 = aAutoFilterRangeBefore.aStart.Col(); + SCROW nRow1 = aAutoFilterRangeBefore.aStart.Row(); + SCCOL nColumn2 = aAutoFilterRangeBefore.aEnd.Col(); + SCROW nRow2 = aAutoFilterRangeBefore.aEnd.Row(); + rDocument.GetDataArea(nDefaultViewTab, nColumn1, nRow1, nColumn2, nRow2, false, true); + + if (nRow2 > aAutoFilterRangeBefore.aEnd.Row()) + { + pManager->insertedRows(aAutoFilterRangeBefore.aEnd.Row() + 1, + nRow2 - aAutoFilterRangeBefore.aEnd.Row()); + } + else if (nRow2 < aAutoFilterRangeBefore.aEnd.Row()) + { + pManager->deletedRows(nRow2 + 1, aAutoFilterRangeBefore.aEnd.Row() - nRow2); + } + + if (nRow2 != aAutoFilterRangeBefore.aEnd.Row() + || nColumn2 != aAutoFilterRangeBefore.aEnd.Col()) + { + pDBData->SetArea(nDefaultViewTab, aAutoFilterRangeBefore.aStart.Col(), + aAutoFilterRangeBefore.aStart.Row(), nColumn2, nRow2); + bAutoFilterRangeChanged = true; + } + } + } + + rDocument.SyncSheetViews(nDefaultViewTab); + + // Invalidate every sheet view tab whose content was just rewritten. + // SyncSheetViews re-applies the stored sort and query/filter on the sheet + // view tab, which can change row visibility. Therefore we need to apply + // Left, Top and Size paint part flags. + if (pManager) + { + if (ScDocShell* pDocShell = mpViewData->GetDocShell()) + { + for (auto const& rSheetView : pManager->iterateValidSheetViews()) + { + SCTAB nSheetViewTab = rSheetView.getTableNumber(); + pDocShell->PostPaint(0, 0, nSheetViewTab, rDocument.MaxCol(), rDocument.MaxRow(), + nSheetViewTab, + PaintPartFlags::Grid | PaintPartFlags::Left + | PaintPartFlags::Top | PaintPartFlags::Size); + } + } + } + + // Attach sort data and auto-filter range to the undo action + if (pManager && pUndoSortData) + { + auto pSortDataAfter = pManager->captureSortData(); + // Only set if not already set by the operation itself + if (!pUndoSortData->hasData()) + { + pUndoSortData->setDefaultViewContext(nDefaultViewTab, std::move(pSortDataBefore), + std::move(pSortDataAfter)); + } + if (bAutoFilterRangeChanged) + { + ScRange aAutoFilterRangeAfter; + ScDBData* pDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + if (pDBData) + pDBData->GetArea(aAutoFilterRangeAfter); + pUndoSortData->setAutoFilterRange(aAutoFilterRangeBefore, aAutoFilterRangeAfter); + } + } +} + +void Operation::syncCellToSheetViews(const ScAddress& rDefaultViewAddress, + UndoSheetViewSortData* pUndoSortData) +{ + if (!mpViewData) + return; + + auto& rDocument = mpViewData->GetDocument(); + SCTAB nDefaultViewTab = mpViewData->GetDefaultViewTab(); + + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + if (!pManager || pManager->isEmpty()) + return; + + // Check if the cell could expand the auto-filter range. If so, fall back + // to the full sync, which can handle the complexities of that. + ScDBData* pDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + if (pDBData && pDBData->HasAutoFilter()) + { + ScRange aDBRange; + pDBData->GetArea(aDBRange); + SCROW nCellRow = rDefaultViewAddress.Row(); + SCCOL nCellCol = rDefaultViewAddress.Col(); + if (nCellRow > aDBRange.aEnd.Row() && nCellCol >= aDBRange.aStart.Col() + && nCellCol <= aDBRange.aEnd.Col()) + { + // Cell is below the auto-filter range in a relevant column + // so we need full sync. + syncSheetViews(pUndoSortData); + return; + } + } + + // Read the cell value from the default view + ScCellValue aCellValue; + aCellValue.assign(rDocument, rDefaultViewAddress); + + SCCOL nColumn = rDefaultViewAddress.Col(); + SCROW nDefaultRow = rDefaultViewAddress.Row(); + + ScDBData* pDefaultViewDBData = rDocument.GetAnonymousDBData(nDefaultViewTab); + ScDocShell* pDocShell = mpViewData->GetDocShell(); + + for (auto& rSheetView : pManager->iterateValidSheetViews()) + { + SCTAB nSheetViewTab = rSheetView.getTableNumber(); + + // Set the cell value at the mapped position in the sheet view. + SCROW nSheetViewRow = rSheetView.reverseDefaultViewToSheetView(nDefaultRow, nColumn); + ScAddress aSheetViewAddress(nColumn, nSheetViewRow, nSheetViewTab); + aCellValue.commit(rDocument, aSheetViewAddress); + + // If the sheet view has an active sort, re-sort to maintain correct order. + ScSortParam const* pSortParam = rSheetView.getSortParam(); + if (pSortParam) + { + ScSortParam aSortParam(*pSortParam); + if (pDefaultViewDBData && pDefaultViewDBData->HasAutoFilter()) + { + ScRange aDBRange; + pDefaultViewDBData->GetArea(aDBRange); + SCCOL nColumn1 = aDBRange.aStart.Col(); + SCROW nRow1 = aDBRange.aStart.Row(); + SCCOL nColumn2 = aDBRange.aEnd.Col(); + SCROW nRow2 = aDBRange.aEnd.Row(); + rDocument.GetDataArea(nDefaultViewTab, nColumn1, nRow1, nColumn2, nRow2, false, + true); + aSortParam.nRow2 = nRow2; + aSortParam.nCol2 = nColumn2; + } + // Don't call resetSortOrder() here - we can just let it merge the existing + // sort indices with the new ones and the result will be correct. + rDocument.Sort(nSheetViewTab, aSortParam, false, false, nullptr, nullptr); + + // Re-sort can shuffle every row in the sort range. Repaint all. + if (pDocShell) + { + pDocShell->PostPaint(aSortParam.nCol1, aSortParam.nRow1, nSheetViewTab, + aSortParam.nCol2, aSortParam.nRow2, nSheetViewTab, + PaintPartFlags::Grid); + } + } + else if (pDocShell) + { + pDocShell->PostPaintCell(aSheetViewAddress); + } + } +} + +void Operation::syncCellPatternToSheetViews(const ScAddress& rDefaultViewAddress, + const ScPatternAttr& rPattern) +{ + if (!mpViewData) + return; + + auto& rDocument = mpViewData->GetDocument(); + SCTAB nDefaultViewTab = mpViewData->GetDefaultViewTab(); + + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + if (!pManager || pManager->isEmpty()) + return; + + SCCOL nColumn = rDefaultViewAddress.Col(); + SCROW nDefaultRow = rDefaultViewAddress.Row(); + + ScDocShell* pDocShell = mpViewData->GetDocShell(); + + for (auto& rSheetView : pManager->iterateValidSheetViews()) + { + SCTAB nSheetViewTab = rSheetView.getTableNumber(); + SCROW nSheetViewRow = rSheetView.reverseDefaultViewToSheetView(nDefaultRow, nColumn); + ScAddress aSheetViewAddress(nColumn, nSheetViewRow, nSheetViewTab); + + ScRefCellValue aCell(rDocument, aSheetViewAddress); + if (aCell.getType() == CELLTYPE_EDIT) + rDocument.RemoveEditTextCharAttribs(aSheetViewAddress, rPattern); + + rDocument.ApplyPattern(nColumn, nSheetViewRow, nSheetViewTab, rPattern); + + if (pDocShell) + { + // The pattern may have changed a border (drawn on the gap between + // two cells, so the neighbour must repaint too -> SC_PF_LINES) and + // may have been applied to a merged cell (the whole merge needs + // refresh, not just our rect -> SC_PF_TESTMERGE). + pDocShell->PostPaint(nColumn, nSheetViewRow, nSheetViewTab, nColumn, nSheetViewRow, + nSheetViewTab, PaintPartFlags::Grid, + SC_PF_LINES | SC_PF_TESTMERGE); + } + } +} + +void Operation::syncMarkPatternToSheetViews(const ScMarkData& rDefaultViewMark, + const ScPatternAttr& rPattern) +{ + if (!mpViewData) + return; + + auto& rDocument = mpViewData->GetDocument(); + SCTAB nDefaultViewTab = mpViewData->GetDefaultViewTab(); + + std::shared_ptr pManager = rDocument.GetSheetViewManager(nDefaultViewTab); + if (!pManager || pManager->isEmpty()) + return; + + for (auto& rSheetView : pManager->iterateValidSheetViews()) + { + SCTAB nSheetViewTab = rSheetView.getTableNumber(); + + // Rebuild the mark in this sheet view's coordinate space. + ScMarkData aSheetViewMark(rDefaultViewMark); + aSheetViewMark.MarkToMulti(); + + // Swap tab selection and area tab: default view to sheet view. + if (aSheetViewMark.GetTableSelect(nDefaultViewTab)) + { + aSheetViewMark.SelectTable(nDefaultViewTab, false); + aSheetViewMark.SelectTable(nSheetViewTab, true); + } + ScRange aArea = aSheetViewMark.GetMultiMarkArea(); + if (aArea.aStart.Tab() == nDefaultViewTab && aArea.aEnd.Tab() == nDefaultViewTab) + aSheetViewMark.SetAreaTab(nSheetViewTab); + + // Re-map marked rows through the sheet view's sort permutation. + SortOrderReverser const* pSortOrder = rSheetView.getSortOrder(); + ReorderParam const* pReorderParams = rSheetView.getReorderParameters(); + if ((pSortOrder || pReorderParams) && aSheetViewMark.GetTableSelect(nSheetViewTab)) + { + SCROW nRowStart = -1; + SCROW nRowEnd = -1; + SCCOL nColumnStart = -1; + SCCOL nColumnEnd = -1; + + if (pSortOrder) + { + SortOrderInfo const& rSortInfo = pSortOrder->maSortInfo; + nRowStart = rSortInfo.mnFirstRow; + nRowEnd = rSortInfo.mnLastRow; + nColumnStart = rSortInfo.mnFirstColumn; + nColumnEnd = rSortInfo.mnLastColumn; + } + else + { + ScRange const& rSortRange = pReorderParams->maSortRange; + nRowStart = rSortRange.aStart.Row(); + nRowEnd = rSortRange.aEnd.Row(); + nColumnStart = rSortRange.aStart.Col(); + nColumnEnd = rSortRange.aEnd.Col(); + } + + std::vector> aMarkedCells; + for (SCROW nRow = nRowStart; nRow <= nRowEnd; ++nRow) + { + for (SCCOL nColumn = nColumnStart; nColumn <= nColumnEnd; ++nColumn) + { + if (aSheetViewMark.IsCellMarked(nColumn, nRow)) + { + ScRange aCellRange(nColumn, nRow, nSheetViewTab, nColumn, nRow, + nSheetViewTab); + aSheetViewMark.SetMultiMarkArea(aCellRange, false); + aMarkedCells.emplace_back(nColumn, nRow); + } + } + } + for (auto & [ nColumn, nRow ] : aMarkedCells) + { + SCROW nMappedRow = rSheetView.reverseDefaultViewToSheetView(nRow, nColumn); + ScRange aCellRange(nColumn, nMappedRow, nSheetViewTab, nColumn, nMappedRow, + nSheetViewTab); + aSheetViewMark.SetMultiMarkArea(aCellRange, true); + } + } + + if (!aSheetViewMark.HasAnyMultiMarks()) + aSheetViewMark.ResetMark(); + aSheetViewMark.MarkToSimple(); + + rDocument.ApplySelectionPattern(rPattern, aSheetViewMark, nullptr); + + if (ScDocShell* pDocShell = mpViewData->GetDocShell()) + { + ScRange const& rPaintRange = aSheetViewMark.GetArea(); + // The pattern may have changed a border (drawn on the gap between + // two cells, so neighbours must repaint too -> SC_PF_LINES) and + // may have been applied to merged cells (the whole merge needs + // refresh, not just our rect -> SC_PF_TESTMERGE). + pDocShell->PostPaint(rPaintRange.aStart.Col(), rPaintRange.aStart.Row(), nSheetViewTab, + rPaintRange.aEnd.Col(), rPaintRange.aEnd.Row(), nSheetViewTab, + PaintPartFlags::Grid, SC_PF_LINES | SC_PF_TESTMERGE); + } + } +} + +bool Operation::isInputOnSheetViewAutoFilter(ScRange const& rRange) const +{ + if (!mpViewData) + return false; + + ScDocument& rDoc = mpViewData->GetDocument(); + + // Only relevant if the range is on a sheet view tab + if (!rDoc.IsSheetViewHolder(rRange.aStart.Tab())) + return false; + + ScDBCollection* pDBCollection = rDoc.GetDBCollection(); + if (!pDBCollection) + return false; + + SCTAB nTab = rRange.aStart.Tab(); + for (ScDBData* pDBData : pDBCollection->GetAllDBsFromTab(nTab)) + { + if (!pDBData->HasAutoFilter()) + continue; + + ScRange aDBRange; + pDBData->GetArea(aDBRange); + if (rRange.Intersects(aDBRange)) + return true; + } + return false; +} + +bool Operation::checkSheetViewProtection() +{ + sc::SheetViewOperationsTester aSheetViewTester(mpViewData); + return aSheetViewTester.check(meType); +} + +bool Operation::run() +{ + SAL_INFO("sc.op", "Running operation '" << operationTypeString(meType) << "'."); + bool bResult = false; + if (canRunTheOperation()) + { + bResult = runImplementation(); + SAL_INFO("sc.op", "Operation '" << operationTypeString(meType) + << (bResult ? "' succeeded." : "' failed.")); + } + else + { + SAL_INFO("sc.op", "Operation '" << operationTypeString(meType) + << "' can not be run using this input data."); + } + return bResult; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/OperationType.cxx b/sc/source/ui/operation/OperationType.cxx new file mode 100644 index 000000000000..41c4775d579a --- /dev/null +++ b/sc/source/ui/operation/OperationType.cxx @@ -0,0 +1,131 @@ +/* -*- 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 + +namespace sc +{ +/** Return operation type as string. */ +std::string_view operationTypeString(OperationType eOperation) +{ + switch (eOperation) + { + case OperationType::Unknown: + return "Unknown"; + case OperationType::ApplyAttributes: + return "ApplyAttributes"; + case OperationType::ApplyAttributesWithChangedRange: + return "ApplyAttributesWithChangedRange"; + case OperationType::ApplyAttributesToCell: + return "ApplyAttributesToCell"; + case OperationType::DeleteContent: + return "DeleteContent"; + case OperationType::DeleteCell: + return "DeleteCell"; + case OperationType::TransliterateText: + return "TransliterateText"; + case OperationType::SetNormalString: + return "SetNormalString"; + case OperationType::SetValue: + return "SetValue"; + case OperationType::SetString: + return "SetString"; + case OperationType::SetTextEdit: + return "SetTextEdit"; + case OperationType::SetFormula: + return "SetFormula"; + case OperationType::SetNoteText: + return "SetNoteText"; + case OperationType::ReplaceNoteText: + return "ReplaceNoteText"; + case OperationType::InsertThreadedComment: + return "InsertThreadedComment"; + case OperationType::InsertColumnsBefore: + return "InsertColumnsBefore"; + case OperationType::InsertColumnsAfter: + return "InsertColumnsAfter"; + case OperationType::InsertRowsBefore: + return "InsertRowsBefore"; + case OperationType::InsertRowsAfter: + return "InsertRowsAfter"; + case OperationType::InsertCellsDown: + return "InsertCellsDown"; + case OperationType::InsertCellsRight: + return "InsertCellsRight"; + case OperationType::DeleteColumns: + return "DeleteColumns"; + case OperationType::DeleteRows: + return "DeleteRows"; + case OperationType::DeleteCellsLeft: + return "DeleteCellsLeft"; + case OperationType::DeleteCellsUp: + return "DeleteCellsUp"; + case OperationType::MoveBlock: + return "MoveBlock"; + case OperationType::ClearItems: + return "ClearItems"; + case OperationType::ChangeIndent: + return "ChangeIndent"; + case OperationType::AutoFormat: + return "AutoFormat"; + case OperationType::EnterMatrix: + return "EnterMatrix"; + case OperationType::MultipleOps: + return "MultipleOps"; + case OperationType::FillSimple: + return "FillSimple"; + case OperationType::FillSeries: + return "FillSeries"; + case OperationType::FillAuto: + return "FillAuto"; + case OperationType::MergeCells: + return "MergeCells"; + case OperationType::InsertNameList: + return "InsertNameList"; + case OperationType::ConvertFormulaToValue: + return "ConvertFormulaToValue"; + case OperationType::Sort: + return "Sort"; + case OperationType::Query: + return "Query"; + case OperationType::SubTotals: + return "SubTotals"; + case OperationType::PivotTableUpdate: + return "PivotTableUpdate"; + case OperationType::PivotTableReplace: + return "PivotTableReplace"; + case OperationType::PivotTableRemove: + return "PivotTableRemove"; + case OperationType::PivotTableCreate: + return "PivotTableCreate"; + case OperationType::SparklineInsert: + return "SparklineInsert"; + case OperationType::SparklineDelete: + return "SparklineDelete"; + case OperationType::SparklineChange: + return "SparklineChange"; + case OperationType::SparklineGroup: + return "SparklineGroup"; + case OperationType::SparklineUngroup: + return "SparklineUngroup"; + case OperationType::SparklineGroupDelete: + return "SparklineGroupDelete"; + case OperationType::SparklineGroupChange: + return "SparklineGroupChange"; + case OperationType::EnterData: + return "EnterData"; + case OperationType::InsertSheetView: + return "InsertSheetView"; + } + return ""; +} + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/PivotTableOperation.cxx b/sc/source/ui/operation/PivotTableOperation.cxx new file mode 100644 index 000000000000..6542bf388b31 --- /dev/null +++ b/sc/source/ui/operation/PivotTableOperation.cxx @@ -0,0 +1,58 @@ +/* -*- 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 + +#include +#include +#include + +namespace sc +{ +PivotTableOperation::PivotTableOperation(OperationType eType, ScDocShell& rDocShell, bool bRecord, + bool bApi) + : Operation(eType, bRecord, bApi) + , mrDocShell(rDocShell) +{ +} + +void PivotTableOperation::convertDPObjectRanges(ScDPObject& rDPObject) +{ + rDPObject.SetOutRange(convertRange(rDPObject.GetOutRange())); + + const ScSheetSourceDesc* pSheetDesc = rDPObject.GetSheetDesc(); + if (pSheetDesc && !pSheetDesc->HasRangeName()) + { + ScSheetSourceDesc aDesc(*pSheetDesc); + aDesc.SetSourceRange(convertRange(aDesc.GetSourceRange())); + rDPObject.SetSheetDesc(aDesc); + } +} + +ScDPObject* PivotTableOperation::findDefaultViewDPObject(ScDPObject const& rSheetViewObject) +{ + SCTAB nSheetViewTab = rSheetViewObject.GetOutRange().aStart.Tab(); + SCTAB nDefaultTab = convertTab(nSheetViewTab); + if (nSheetViewTab == nDefaultTab) + return const_cast(&rSheetViewObject); + ScDPCollection& rDPs = *mrDocShell.GetDocument().GetDPCollection(); + for (size_t i = 0; i < rDPs.GetCount(); ++i) + { + auto& rDPObject = rDPs[i]; + if (rDPObject.GetName() == rSheetViewObject.GetName() + && rDPObject.GetOutRange().aStart.Tab() == nDefaultTab) + { + return &rDPObject; + } + } + return nullptr; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/QueryOperation.cxx b/sc/source/ui/operation/QueryOperation.cxx new file mode 100644 index 000000000000..dddc32eb1e1e --- /dev/null +++ b/sc/source/ui/operation/QueryOperation.cxx @@ -0,0 +1,408 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace sc +{ +QueryOperation::QueryOperation(ScDocShell& rDocShell, SCTAB nTab, ScQueryParam const& rQueryParam, + ScRange const* pAdvSource, bool bRecord, bool bApi) + : Operation(OperationType::Query, bRecord, bApi) + , mrDocShell(rDocShell) + , mnTab(nTab) + , mrQueryParam(rQueryParam) + , mpAdvSource(pAdvSource) +{ +} + +bool QueryOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + + ScTabViewShell* pViewSh = mrDocShell.GetBestViewShell(); + if (pViewSh + && ScTabViewShell::isAnyEditViewInRange(pViewSh, /*bColumns*/ false, mrQueryParam.nRow1, + mrQueryParam.nRow2)) + { + return false; + } + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScDBData* pDBData = rDoc.GetDBAtArea(mnTab, mrQueryParam.nCol1, mrQueryParam.nRow1, + mrQueryParam.nCol2, mrQueryParam.nRow2); + if (!pDBData) + { + OSL_FAIL("Query: no DBData"); + return false; + } + + // Change from Inplace to non-Inplace, only then cancel Inplace: + // (only if "Persistent" is selected in the dialog) + + if (!mrQueryParam.bInplace && pDBData->HasQueryParam() && mrQueryParam.bDestPers) + { + ScQueryParam aOldQuery; + pDBData->GetQueryParam(aOldQuery); + if (aOldQuery.bInplace) + { + // cancel old filtering + + SCSIZE nEC = aOldQuery.GetEntryCount(); + for (SCSIZE i = 0; i < nEC; i++) + aOldQuery.GetEntry(i).bDoQuery = false; + aOldQuery.bDuplicate = true; + QueryOperation aOperation(mrDocShell, mnTab, aOldQuery, nullptr, mbRecord, mbApi); + aOperation.run(); + } + } + + ScQueryParam aLocalParam(mrQueryParam); // for Paint / destination range + bool bCopy = !mrQueryParam.bInplace; // copied in Table::Query + ScDBData* pDestData = nullptr; // range to be copied to + bool bDoSize = false; // adjust destination size (insert/delete) + SCCOL nFormulaCols = 0; // only at bDoSize + bool bKeepFmt = false; + ScRange aOldDest; + ScRange aDestTotal; + if (bCopy && mrQueryParam.nDestCol == mrQueryParam.nCol1 + && mrQueryParam.nDestRow == mrQueryParam.nRow1 && mrQueryParam.nDestTab == mnTab) + bCopy = false; + SCTAB nDestTab = mnTab; + if (bCopy) + { + aLocalParam.MoveToDest(); + nDestTab = mrQueryParam.nDestTab; + if (!rDoc.ValidColRow(aLocalParam.nCol2, aLocalParam.nRow2)) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_PASTE_FULL); + return false; + } + + if (!checkSheetViewProtection()) + return false; + + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, nDestTab, aLocalParam.nCol1, aLocalParam.nRow1, aLocalParam.nCol2, + aLocalParam.nRow2); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + pDestData = rDoc.GetDBAtCursor(mrQueryParam.nDestCol, mrQueryParam.nDestRow, + mrQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT); + if (pDestData) + { + pDestData->GetArea(aOldDest); + aDestTotal = ScRange(mrQueryParam.nDestCol, mrQueryParam.nDestRow, nDestTab, + mrQueryParam.nDestCol + mrQueryParam.nCol2 - mrQueryParam.nCol1, + mrQueryParam.nDestRow + mrQueryParam.nRow2 - mrQueryParam.nRow1, + nDestTab); + + bDoSize = pDestData->IsDoSize(); + // test if formulas need to be filled in (nFormulaCols): + if (bDoSize && aOldDest.aEnd.Col() == aDestTotal.aEnd.Col()) + { + SCCOL nTestCol = aOldDest.aEnd.Col() + 1; // next to the range + SCROW nTestRow = mrQueryParam.nDestRow + (aLocalParam.bHasHeader ? 1 : 0); + while (nTestCol <= rDoc.MaxCol() + && rDoc.GetCellType(ScAddress(nTestCol, nTestRow, mnTab)) + == CELLTYPE_FORMULA) + { + ++nTestCol; + ++nFormulaCols; + } + } + + bKeepFmt = pDestData->IsKeepFmt(); + if (bDoSize && !rDoc.CanFitBlock(aOldDest, aDestTotal)) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); // cannot insert rows + return false; + } + } + } + + // execute + + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + bool bKeepSub = false; // repeat existing partial results? + bool bKeepTotals = false; + if (mrQueryParam.GetEntry(0).bDoQuery) // not at cancellation + { + ScSubTotalParam aSubTotalParam; + pDBData->GetSubTotalParam(aSubTotalParam); // partial results exist? + + if (aSubTotalParam.aGroups[0].bActive && !aSubTotalParam.bRemoveOnly) + bKeepSub = true; + + if (pDBData->HasTotals() && pDBData->GetTableStyleInfo()) + bKeepTotals = true; + } + + ScDocumentUniquePtr pUndoDoc; + std::unique_ptr pUndoDB; + const ScRange* pOld = nullptr; + + if (mbRecord) + { + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + if (bCopy) + { + pUndoDoc->InitUndo(rDoc, nDestTab, nDestTab, false, true); + rDoc.CopyToDocument(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, aLocalParam.nCol2, + aLocalParam.nRow2, nDestTab, InsertDeleteFlags::ALL, false, + *pUndoDoc); + // secure attributes in case they were copied along + + if (pDestData) + { + rDoc.CopyToDocument(aOldDest, InsertDeleteFlags::ALL, false, *pUndoDoc); + pOld = &aOldDest; + } + } + else + { + pUndoDoc->InitUndo(rDoc, mnTab, mnTab, false, true); + rDoc.CopyToDocument(0, mrQueryParam.nRow1, mnTab, rDoc.MaxCol(), mrQueryParam.nRow2, + mnTab, InsertDeleteFlags::NONE, false, *pUndoDoc); + } + + ScDBCollection* pDocDB = rDoc.GetDBCollection(); + if (!pDocDB->empty()) + pUndoDB.reset(new ScDBCollection(*pDocDB)); + + rDoc.BeginDrawUndo(); + } + + std::unique_ptr pAttribDoc; + ScRange aAttribRange; + if (pDestData) // delete destination range + { + if (bKeepFmt) + { + // smaller of the end columns, header+1 row + aAttribRange = aOldDest; + if (aAttribRange.aEnd.Col() > aDestTotal.aEnd.Col()) + aAttribRange.aEnd.SetCol(aDestTotal.aEnd.Col()); + aAttribRange.aEnd.SetRow(aAttribRange.aStart.Row() + (aLocalParam.bHasHeader ? 1 : 0)); + + // also for filled-in formulas + aAttribRange.aEnd.SetCol(aAttribRange.aEnd.Col() + nFormulaCols); + + pAttribDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pAttribDoc->InitUndo(rDoc, nDestTab, nDestTab, false, true); + rDoc.CopyToDocument(aAttribRange, InsertDeleteFlags::ATTRIB, false, *pAttribDoc); + } + + if (bDoSize) + rDoc.FitBlock(aOldDest, aDestTotal); + else + rDoc.DeleteAreaTab(aOldDest, InsertDeleteFlags::ALL); // simply delete + } + + // execute filtering on the document + SCSIZE nCount = rDoc.Query(mnTab, mrQueryParam, bKeepSub, bKeepTotals); + pDBData->CalcSaveFilteredCount(nCount); + if (bCopy) + { + aLocalParam.nRow2 = aLocalParam.nRow1 + nCount; + if (!aLocalParam.bHasHeader && nCount > 0) + --aLocalParam.nRow2; + + if (bDoSize) + { + // adjust to the real result range + // (this here is always a reduction) + + ScRange aNewDest(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, aLocalParam.nCol2, + aLocalParam.nRow2, nDestTab); + rDoc.FitBlock(aDestTotal, aNewDest, false); // sal_False - don't delete + + if (nFormulaCols > 0) + { + // fill in formulas + //! Undo (Query and Repeat) !!! + + ScRange aNewForm(aLocalParam.nCol2 + 1, aLocalParam.nRow1, nDestTab, + aLocalParam.nCol2 + nFormulaCols, aLocalParam.nRow2, nDestTab); + ScRange aOldForm = aNewForm; + aOldForm.aEnd.SetRow(aOldDest.aEnd.Row()); + rDoc.FitBlock(aOldForm, aNewForm, false); + + ScMarkData aMark(rDoc.GetSheetLimits()); + aMark.SelectOneTable(nDestTab); + SCROW nFStartY = aLocalParam.nRow1 + (aLocalParam.bHasHeader ? 1 : 0); + + sal_uLong nProgCount = nFormulaCols; + nProgCount *= aLocalParam.nRow2 - nFStartY; + ScProgress aProgress(rDoc.GetDocumentShell(), ScResId(STR_FILL_SERIES_PROGRESS), + nProgCount, true); + + rDoc.Fill(aLocalParam.nCol2 + 1, nFStartY, aLocalParam.nCol2 + nFormulaCols, + nFStartY, &aProgress, aMark, aLocalParam.nRow2 - nFStartY, FILL_TO_BOTTOM, + FILL_SIMPLE); + } + } + + if (pAttribDoc) // copy back the memorized attributes + { + // Header + if (aLocalParam.bHasHeader) + { + ScRange aHdrRange = aAttribRange; + aHdrRange.aEnd.SetRow(aHdrRange.aStart.Row()); + pAttribDoc->CopyToDocument(aHdrRange, InsertDeleteFlags::ATTRIB, false, rDoc); + } + + // Data + SCCOL nAttrEndCol = aAttribRange.aEnd.Col(); + SCROW nAttrRow = aAttribRange.aStart.Row() + (aLocalParam.bHasHeader ? 1 : 0); + for (SCCOL nCol = aAttribRange.aStart.Col(); nCol <= nAttrEndCol; nCol++) + { + const ScPatternAttr* pSrcPattern = pAttribDoc->GetPattern(nCol, nAttrRow, nDestTab); + OSL_ENSURE(pSrcPattern, "Pattern is 0"); + if (pSrcPattern) + { + rDoc.ApplyPatternAreaTab(nCol, nAttrRow, nCol, aLocalParam.nRow2, nDestTab, + *pSrcPattern); + const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet(); + if (pStyle) + rDoc.ApplyStyleAreaTab(nCol, nAttrRow, nCol, aLocalParam.nRow2, nDestTab, + *pStyle); + } + } + } + } + + // saving: Inplace always, otherwise depending on setting + // old Inplace-Filter may have already been removed + + bool bSave = mrQueryParam.bInplace || mrQueryParam.bDestPers; + if (bSave) // memorize + { + pDBData->SetQueryParam(mrQueryParam); + pDBData->SetHeader(mrQueryParam.bHasHeader); //! ??? + pDBData->SetAdvancedQuerySource(mpAdvSource); // after SetQueryParam + } + + if (bCopy) // memorize new DB range + { + // Selection is done afterwards from outside (dbfunc). + // Currently through the DB area at the destination position, + // so a range must be created there in any case. + + ScDBData* pNewData; + if (pDestData) + pNewData = pDestData; // range exists -> adjust (always!) + else // create range + pNewData = mrDocShell.GetDBData(ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, + aLocalParam.nCol2, aLocalParam.nRow2, nDestTab), + SC_DB_MAKE, ScGetDBSelection::ForceMark); + + if (pNewData) + { + pNewData->SetArea(nDestTab, aLocalParam.nCol1, aLocalParam.nRow1, aLocalParam.nCol2, + aLocalParam.nRow2); + + // query parameter is no longer set at the destination, only leads to confusion + // and mistakes with the query parameter at the source range (#37187#) + } + else + { + OSL_FAIL("Target are not available"); + } + } + + if (!bCopy) + { + rDoc.InvalidatePageBreaks(mnTab); + rDoc.UpdatePageBreaks(mnTab); + } + + // #i23299# Subtotal functions depend on cell's filtered states. + ScRange aDirtyRange(0, aLocalParam.nRow1, nDestTab, rDoc.MaxCol(), aLocalParam.nRow2, nDestTab); + rDoc.SetSubTotalCellsDirty(aDirtyRange); + + if (mbRecord) + { + // create undo action after executing, because of drawing layer undo + mrDocShell.GetUndoManager()->AddUndoAction( + std::make_unique(mrDocShell, mnTab, mrQueryParam, std::move(pUndoDoc), + std::move(pUndoDB), pOld, bDoSize, mpAdvSource)); + } + + if (pViewSh) + { + // could there be horizontal autofilter ? + // maybe it would be better to set bColumns to !rQueryParam.bByRow ? + // anyway at the beginning the value of bByRow is 'false' + // then after the first sort action it becomes 'true' + pViewSh->OnLOKShowHideColRow(/*bColumns*/ false, mrQueryParam.nRow1 - 1); + } + + if (bCopy) + { + SCCOL nEndX = aLocalParam.nCol2; + SCROW nEndY = aLocalParam.nRow2; + if (pDestData) + { + if (aOldDest.aEnd.Col() > nEndX) + nEndX = aOldDest.aEnd.Col(); + if (aOldDest.aEnd.Row() > nEndY) + nEndY = aOldDest.aEnd.Row(); + } + if (bDoSize) + nEndY = rDoc.MaxRow(); + + // remove AutoFilter button flags + mrDocShell.DBAreaDeleted(nDestTab, aLocalParam.nCol1, aLocalParam.nRow1, aLocalParam.nCol2); + + mrDocShell.PostPaint( + ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, nEndX, nEndY, nDestTab), + PaintPartFlags::Grid); + } + else + mrDocShell.PostPaint( + ScRange(0, mrQueryParam.nRow1, mnTab, rDoc.MaxCol(), rDoc.MaxRow(), mnTab), + PaintPartFlags::Grid | PaintPartFlags::Left); + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/RemovePivotTableOperation.cxx b/sc/source/ui/operation/RemovePivotTableOperation.cxx new file mode 100644 index 000000000000..c8bd2e979e4b --- /dev/null +++ b/sc/source/ui/operation/RemovePivotTableOperation.cxx @@ -0,0 +1,124 @@ +/* -*- 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace sc +{ +RemovePivotTableOperation::RemovePivotTableOperation(ScDocShell& rDocShell, + ScDPObject const& rDPObject, bool bRecord, + bool bApi) + : PivotTableOperation(OperationType::PivotTableRemove, rDocShell, bRecord, bApi) + , mrDPObject(rDPObject) +{ +} + +bool RemovePivotTableOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + ScDPObject* pDPObject = findDefaultViewDPObject(mrDPObject); + if (!pDPObject) + return false; + + if (!sc::pivot::isEditable(mrDocShell, pDPObject->GetOutRange(), mbApi)) + return false; + + ScDocument& rDoc = mrDocShell.GetDocument(); + + if (!mbApi) + { + // If we come from GUI - ask to delete the associated pivot charts too... + std::vector aListOfObjects + = sctools::getAllPivotChartsConnectedTo(pDPObject->GetName(), mrDocShell); + + ScDrawLayer* pModel = rDoc.GetDrawLayer(); + + if (pModel && !aListOfObjects.empty()) + { + std::unique_ptr xQueryBox(Application::CreateMessageDialog( + ScDocShell::GetActiveDialogParent(), VclMessageType::Question, + VclButtonsType::YesNo, ScResId(STR_PIVOT_REMOVE_PIVOTCHART))); + xQueryBox->set_default_response(RET_YES); + if (xQueryBox->run() == RET_NO) + { + return false; + } + else + { + for (SdrOle2Obj* pChartObject : aListOfObjects) + { + rDoc.GetChartListenerCollection()->removeByName(pChartObject->GetName()); + pModel->AddUndo(std::make_unique(*pChartObject)); + pChartObject->getSdrPageFromSdrObject()->RemoveObject( + pChartObject->GetOrdNum()); + } + } + } + } + + ScDocumentUniquePtr pOldUndoDoc; + std::unique_ptr pUndoDPObject; + + if (mbRecord) + pUndoDPObject.reset(new ScDPObject(*pDPObject)); // copy old settings for undo + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + // delete table + + ScRange aRange = pDPObject->GetOutRange(); + SCTAB nTab = aRange.aStart.Tab(); + + if (mbRecord) + sc::pivot::createUndoDoc(pOldUndoDoc, rDoc, aRange); + + rDoc.DeleteAreaTab(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), + aRange.aEnd.Row(), nTab, InsertDeleteFlags::ALL); + rDoc.RemoveFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), + aRange.aEnd.Row(), nTab, ScMF::Auto); + + rDoc.GetDPCollection()->FreeTable(pDPObject); // object is deleted here + + mrDocShell.PostPaintGridAll(); //! only necessary parts + mrDocShell.PostPaint(aRange, PaintPartFlags::Grid); + + if (mbRecord) + { + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, std::move(pOldUndoDoc), nullptr, pUndoDPObject.get(), nullptr, false)); + + // pUndoDPObject is copied + } + + syncSheetViews(); + + aModificator.SetDocumentModified(); + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/ReplaceNoteTextOperation.cxx b/sc/source/ui/operation/ReplaceNoteTextOperation.cxx new file mode 100644 index 000000000000..47079606a84f --- /dev/null +++ b/sc/source/ui/operation/ReplaceNoteTextOperation.cxx @@ -0,0 +1,117 @@ +/* -*- 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 + +#include + +#include +#include +#include +#include +#include + +namespace sc +{ +ReplaceNoteTextOperation::ReplaceNoteTextOperation(ScDocShell& rDocShell, const ScAddress& rPos, + const OUString& rNoteText, + const OUString* pAuthor, const OUString* pDate, + bool bApi) + : Operation(OperationType::ReplaceNoteText, false, bApi) + , mrDocShell(rDocShell) + , maPos(rPos) + , maText(rNoteText) + , moAuthor(pAuthor ? std::optional(*pAuthor) : std::nullopt) + , moDate(pDate ? std::optional(*pDate) : std::nullopt) +{ +} + +bool ReplaceNoteTextOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + + ScAddress aPos = convertAddress(maPos); + + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, aPos.Tab(), aPos.Col(), aPos.Row(), aPos.Col(), aPos.Row()); + if (aTester.IsEditable()) + { + ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); + SfxUndoManager* pUndoMgr + = (pDrawLayer && rDoc.IsUndoEnabled()) ? mrDocShell.GetUndoManager() : nullptr; + + ScNoteData aOldData; + std::unique_ptr pOldNote = rDoc.ReleaseNote(aPos); + sal_uInt32 nNoteId = 0; + if (pOldNote) + { + nNoteId = pOldNote->GetId(); + // ensure existing caption object before draw undo tracking starts + pOldNote->GetOrCreateCaption(aPos); + // rescue note data for undo + aOldData = pOldNote->GetNoteData(); + } + + // collect drawing undo actions for deleting/inserting caption objects + if (pUndoMgr) + pDrawLayer->BeginCalcUndo(false); + + // delete the note (creates drawing undo action for the caption object) + bool hadOldNote(pOldNote); + pOldNote.reset(); + + // create new note (creates drawing undo action for the new caption object) + ScNoteData aNewData; + ScPostIt* pNewNote = nullptr; + if ((pNewNote = ScNoteUtil::CreateNoteFromString(rDoc, aPos, maText, false, true, nNoteId))) + { + if (moAuthor) + pNewNote->SetAuthor(*moAuthor); + if (moDate) + pNewNote->SetDate(*moDate); + + // rescue note data for undo + aNewData = pNewNote->GetNoteData(); + } + + // create the undo action + if (pUndoMgr && (aOldData.mxCaption || aNewData.mxCaption)) + pUndoMgr->AddUndoAction(std::make_unique( + mrDocShell, aPos, aOldData, aNewData, pDrawLayer->GetCalcUndo())); + + // repaint cell (to make note marker visible) + mrDocShell.PostPaintCell(aPos); + + rDoc.SetStreamValid(aPos.Tab(), false); + + syncSheetViews(); + + aModificator.SetDocumentModified(); + + // Let our LOK clients know about the new/modified note + if (pNewNote) + { + ScDocShell::LOKCommentNotify(hadOldNote ? LOKCommentNotificationType::Modify + : LOKCommentNotificationType::Add, + rDoc, aPos, pNewNote); + } + + return true; + } + else if (!mbApi) + { + mrDocShell.ErrorMessage(aTester.GetMessageId()); + } + + return false; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/ReplacePivotTableOperation.cxx b/sc/source/ui/operation/ReplacePivotTableOperation.cxx new file mode 100644 index 000000000000..050d995c74ca --- /dev/null +++ b/sc/source/ui/operation/ReplacePivotTableOperation.cxx @@ -0,0 +1,121 @@ +/* -*- 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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace sc +{ +ReplacePivotTableOperation::ReplacePivotTableOperation(ScDocShell& rDocShell, ScDPObject* pDPObject, + ScDPObject const* pNewDPObject, bool bRecord, + bool bApi, bool bAllowMove) + : PivotTableOperation(OperationType::PivotTableReplace, rDocShell, bRecord, bApi) + , mpDPObject(pDPObject) + , mpNewDPObject(pNewDPObject) + , mbAllowMove(bAllowMove) +{ +} + +bool ReplacePivotTableOperation::runImplementation() +{ + assert(mpDPObject); + assert(mpNewDPObject); + assert(mpDPObject != mpNewDPObject); + + ScDocShellModificator aModificator(mrDocShell); + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + // Resolve to the default view's DPObject when called from a sheet view + ScDPObject* pDPObject = findDefaultViewDPObject(*mpDPObject); + if (!pDPObject) + pDPObject = mpDPObject; + + ScRangeList aRanges; + aRanges.push_back(pDPObject->GetOutRange()); + aRanges.push_back(ScRange( + convertAddress(mpNewDPObject->GetOutRange() + .aStart))); // at least one cell in the output position must be editable. + + if (!sc::pivot::isEditable(mrDocShell, aRanges, mbApi)) + return false; + + ScDocumentUniquePtr pOldUndoDoc; + ScDocumentUniquePtr pNewUndoDoc; + + ScDPObject aUndoDPObject(*pDPObject); // for undo or revert on failure + + ScDocument& rDoc = mrDocShell.GetDocument(); + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + if (mbRecord) + sc::pivot::createUndoDoc(pOldUndoDoc, rDoc, pDPObject->GetOutRange()); + + mpNewDPObject->WriteSourceDataTo(*pDPObject); // copy source data + + ScDPSaveData* pData = mpNewDPObject->GetSaveData(); + OSL_ENSURE(pData, "no SaveData from living DPObject"); + if (pData) + pDPObject->SetSaveData(*pData); // copy SaveData + + pDPObject->SetAllowMove(mbAllowMove); + pDPObject->ReloadGroupTableData(); + pDPObject->SyncAllDimensionMembers(); + pDPObject->InvalidateData(); // before getting the new output area + + // make sure the table has a name (not set by dialog) + if (pDPObject->GetName().isEmpty()) + pDPObject->SetName(rDoc.GetDPCollection()->CreateNewName()); + + ScRange aNewOut; + if (!sc::pivot::checkNewOutputRange(*pDPObject, mrDocShell, aNewOut, mbApi)) + { + *pDPObject = aUndoDPObject; + return false; + } + + if (mbRecord) + sc::pivot::createUndoDoc(pNewUndoDoc, rDoc, aNewOut); + + // Use spill checking output if the destination range has non-empty cells, + // write #SPILL! into the origin cell instead of overwriting. + // Skip the spill check during XML import + pDPObject->Output(aNewOut.aStart, !rDoc.IsImportingXML()); + mrDocShell.PostPaintGridAll(); + + if (mbRecord) + { + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObject, pDPObject, + mbAllowMove)); + } + + syncSheetViews(); + + // notify API objects + rDoc.BroadcastUno(ScDataPilotModifiedHint(pDPObject->GetName())); + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SetEditTextOperation.cxx b/sc/source/ui/operation/SetEditTextOperation.cxx new file mode 100644 index 000000000000..a2acf25985e0 --- /dev/null +++ b/sc/source/ui/operation/SetEditTextOperation.cxx @@ -0,0 +1,82 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +SetEditTextOperation::SetEditTextOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScAddress& rPosition, + const EditTextObject& rEditObject, bool bApi) + : Operation(OperationType::SetTextEdit, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrPosition(rPosition) + , mrEditObject(rEditObject) +{ +} + +bool SetEditTextOperation::runImplementation() +{ + ScAddress aPosition = convertAddress(mrPosition); + + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + bool bUndo = rDoc.IsUndoEnabled(); + + bool bHeight = rDoc.HasAttrib(ScRange(aPosition), HasAttrFlags::NeedHeight); + + ScCellValue aOldVal; + if (bUndo) + aOldVal.assign(rDoc, aPosition); + + rDoc.SetEditText(aPosition, std::make_unique(mrEditObject)); + + ScUndoSetCell* pUndoSetCell = nullptr; + if (bUndo) + { + SfxUndoManager* pUndoMgr = mrDocShell.GetUndoManager(); + ScCellValue aNewVal; + aNewVal.assign(rDoc, aPosition); + auto pUndoAction = std::make_unique(mrDocShell, aPosition, aOldVal, aNewVal); + pUndoSetCell = pUndoAction.get(); + pUndoMgr->AddUndoAction(std::move(pUndoAction)); + } + + syncCellToSheetViews(aPosition, pUndoSetCell); + + if (bHeight) + mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi); + + mrDocShell.PostPaintCell(aPosition); + aModificator.SetDocumentModified(); + + // #103934#; notify editline and cell in edit mode + if (mbApi) + mrDocFunc.NotifyInputHandler(aPosition); + + mrDocShell.ResolveSpilledOutputs(); + + return true; +} + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SetFormulaOperation.cxx b/sc/source/ui/operation/SetFormulaOperation.cxx new file mode 100644 index 000000000000..6cb4c2bf39fb --- /dev/null +++ b/sc/source/ui/operation/SetFormulaOperation.cxx @@ -0,0 +1,98 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +SetFormulaOperation::SetFormulaOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScAddress& rPosition, ScFormulaCell* pFormulaCell, + bool bApi) + : Operation(OperationType::SetFormula, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrPosition(rPosition) + , mpFormulaCell(pFormulaCell) +{ +} + +bool SetFormulaOperation::runImplementation() +{ + ScAddress aPosition = convertAddress(mrPosition); + + ScFormulaCell* pCell(mpFormulaCell); + std::unique_ptr xCell(mpFormulaCell); + + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + bool bUndo = rDoc.IsUndoEnabled(); + + bool bHeight = rDoc.HasAttrib(ScRange(aPosition), HasAttrFlags::NeedHeight); + + ScCellValue aOldVal; + if (bUndo) + aOldVal.assign(rDoc, aPosition); + + pCell = rDoc.SetFormulaCell(aPosition, xCell.release()); + + // For performance reasons API calls may disable calculation while + // operating and recalculate once when done. If through user interaction + // and AutoCalc is disabled, calculate the formula (without its + // dependencies) once so the result matches the current document's content. + if (!mbApi && !rDoc.GetAutoCalc() && pCell) + { + // calculate just the cell once and set Dirty again + pCell->Interpret(); + pCell->SetDirtyVar(); + rDoc.PutInFormulaTree(pCell); + } + + ScUndoSetCell* pUndoSetCell = nullptr; + if (bUndo) + { + SfxUndoManager* pUndoMgr = mrDocShell.GetUndoManager(); + ScCellValue aNewVal; + aNewVal.assign(rDoc, aPosition); + auto pUndoAction = std::make_unique(mrDocShell, aPosition, aOldVal, aNewVal); + pUndoSetCell = pUndoAction.get(); + pUndoMgr->AddUndoAction(std::move(pUndoAction)); + } + + syncCellToSheetViews(aPosition, pUndoSetCell); + + if (bHeight) + mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi); + + mrDocShell.PostPaintCell(aPosition); + aModificator.SetDocumentModified(); + + // #103934#; notify editline and cell in edit mode + if (mbApi) + mrDocFunc.NotifyInputHandler(aPosition); + + mrDocShell.ResolveSpilledOutputs(); + + return true; +} + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SetNormalStringOperation.cxx b/sc/source/ui/operation/SetNormalStringOperation.cxx new file mode 100644 index 000000000000..28e7e093e96d --- /dev/null +++ b/sc/source/ui/operation/SetNormalStringOperation.cxx @@ -0,0 +1,124 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +SetNormalStringOperation::SetNormalStringOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScAddress& rPosition, + const OUString& rText, bool bApi) + : Operation(OperationType::SetNormalString, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrPosition(rPosition) + , mrText(rText) +{ +} + +bool SetNormalStringOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + + bool bUndo(rDoc.IsUndoEnabled()); + + ScAddress aPosition = convertAddress(mrPosition); + + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, aPosition.Tab(), aPosition.Col(), aPosition.Row(), aPosition.Col(), aPosition.Row()); + if (!aTester.IsEditableOrMatrixCell(rDoc, aPosition)) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + // If the target is a multi-cell matrix master, tear the whole matrix + // down before the write so the new value doesn't leave reference cells + // orphaned. + DocFuncUtil::demolishMatrixMaster(mrDocFunc, rDoc, aPosition, mbApi); + + bool bEditDeleted = (rDoc.GetCellType(aPosition) == CELLTYPE_EDIT); + ScUndoEnterData::ValuesType aOldValues; + + if (bUndo) + { + ScUndoEnterData::Value aOldValue; + + aOldValue.mnTab = aPosition.Tab(); + aOldValue.maCell.assign(rDoc, aPosition); + + const ScPatternAttr* pPattern + = rDoc.GetPattern(aPosition.Col(), aPosition.Row(), aPosition.Tab()); + if (const SfxUInt32Item* pItem + = pPattern->GetItemSet().GetItemIfSet(ATTR_VALUE_FORMAT, false)) + { + aOldValue.mbHasFormat = true; + aOldValue.mnFormat = pItem->GetValue(); + } + else + aOldValue.mbHasFormat = false; + + aOldValues.push_back(aOldValue); + } + + tools::Long nBefore(mrDocShell.GetTwipWidthHint(aPosition)); + mbIsNumberFormatSet = rDoc.SetString(aPosition.Col(), aPosition.Row(), aPosition.Tab(), mrText); + tools::Long nAfter(mrDocShell.GetTwipWidthHint(aPosition)); + + ScUndoEnterData* pUndoEnterData = nullptr; + if (bUndo) + { + // because of ChangeTracking, UndoAction can be created only after SetString was called + auto pUndoAction + = std::make_unique(mrDocShell, aPosition, aOldValues, mrText, nullptr); + pUndoEnterData = pUndoAction.get(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoAction)); + } + + if (bEditDeleted || rDoc.HasAttrib(ScRange(aPosition), HasAttrFlags::NeedHeight)) + mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi); + + syncCellToSheetViews(aPosition, pUndoEnterData); + + mrDocShell.PostPaintCell(aPosition, std::max(nBefore, nAfter)); + aModificator.SetDocumentModified(); + + // notify input handler here the same way as in PutCell + if (mbApi) + mrDocFunc.NotifyInputHandler(aPosition); + + const SfxUInt32Item& rItem = rDoc.GetAttr(aPosition, ATTR_VALIDDATA); + const ScValidationData* pData = rDoc.GetValidationEntry(rItem.GetValue()); + if (pData) + { + ScRefCellValue aCell(rDoc, aPosition); + if (pData->IsDataValid(aCell, aPosition)) + ScDetectiveFunc(rDoc, aPosition.Tab()) + .DeleteCirclesAt(aPosition.Col(), aPosition.Row()); + } + + mrDocShell.ResolveSpilledOutputs(); + + return true; +} +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SetNoteTextOperation.cxx b/sc/source/ui/operation/SetNoteTextOperation.cxx new file mode 100644 index 000000000000..c251afb38743 --- /dev/null +++ b/sc/source/ui/operation/SetNoteTextOperation.cxx @@ -0,0 +1,65 @@ +/* -*- 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 + +#include +#include +#include + +#include +#include + +namespace sc +{ +SetNoteTextOperation::SetNoteTextOperation(ScDocShell& rDocShell, const ScAddress& rPos, + const OUString& rText, bool bApi) + : Operation(OperationType::SetNoteText, false, bApi) + , mrDocShell(rDocShell) + , maPos(rPos) + , maText(rText) +{ +} + +bool SetNoteTextOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + + ScAddress aPos = convertAddress(maPos); + + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, aPos.Tab(), aPos.Col(), aPos.Row(), aPos.Col(), aPos.Row()); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + OUString aNewText = convertLineEnd(maText, GetSystemLineEnd()); //! is this necessary ??? + + if (ScPostIt* pNote = (!aNewText.isEmpty()) ? rDoc.GetOrCreateNote(aPos) : rDoc.GetNote(aPos)) + pNote->SetText(aPos, aNewText); + + //! Undo !!! + + rDoc.SetStreamValid(aPos.Tab(), false); + + syncSheetViews(); + + mrDocShell.PostPaintCell(aPos); + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SetStringOperation.cxx b/sc/source/ui/operation/SetStringOperation.cxx new file mode 100644 index 000000000000..0d4fdfdf2551 --- /dev/null +++ b/sc/source/ui/operation/SetStringOperation.cxx @@ -0,0 +1,83 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +SetStringOperation::SetStringOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScAddress& rPosition, OUString const& rString, + bool bApi) + : Operation(OperationType::SetString, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrPosition(rPosition) + , mrString(rString) +{ +} + +bool SetStringOperation::runImplementation() +{ + ScAddress aPosition = convertAddress(mrPosition); + + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + bool bUndo = rDoc.IsUndoEnabled(); + + bool bHeight = rDoc.HasAttrib(ScRange(aPosition), HasAttrFlags::NeedHeight); + + ScCellValue aOldVal; + if (bUndo) + aOldVal.assign(rDoc, aPosition); + + ScSetStringParam aParam; + aParam.setTextInput(); + rDoc.SetString(aPosition, mrString, &aParam); + + ScUndoSetCell* pUndoSetCell = nullptr; + if (bUndo) + { + SfxUndoManager* pUndoMgr = mrDocShell.GetUndoManager(); + ScCellValue aNewVal; + aNewVal.assign(rDoc, aPosition); + auto pUndoAction = std::make_unique(mrDocShell, aPosition, aOldVal, aNewVal); + pUndoSetCell = pUndoAction.get(); + pUndoMgr->AddUndoAction(std::move(pUndoAction)); + } + + syncCellToSheetViews(aPosition, pUndoSetCell); + + if (bHeight) + mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi); + + mrDocShell.PostPaintCell(aPosition); + aModificator.SetDocumentModified(); + + // #103934#; notify editline and cell in edit mode + if (mbApi) + mrDocFunc.NotifyInputHandler(aPosition); + + mrDocShell.ResolveSpilledOutputs(); + + return true; +} +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SetValueOperation.cxx b/sc/source/ui/operation/SetValueOperation.cxx new file mode 100644 index 000000000000..0c73954c4361 --- /dev/null +++ b/sc/source/ui/operation/SetValueOperation.cxx @@ -0,0 +1,78 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +SetValueOperation::SetValueOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScAddress& rPosition, double fValue, bool bApi) + : Operation(OperationType::SetValue, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrPosition(rPosition) + , mfValue(fValue) +{ +} + +bool SetValueOperation::runImplementation() +{ + ScAddress aPosition = convertAddress(mrPosition); + + ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); + bool bUndo = rDoc.IsUndoEnabled(); + bool bHeight = rDoc.HasAttrib(ScRange(aPosition), HasAttrFlags::NeedHeight); + + ScCellValue aOldVal; + if (bUndo) + aOldVal.assign(rDoc, aPosition); + + rDoc.SetValue(aPosition, mfValue); + + ScUndoSetCell* pUndoSetCell = nullptr; + if (bUndo) + { + SfxUndoManager* pUndoMgr = mrDocShell.GetUndoManager(); + ScCellValue aNewVal; + aNewVal.assign(rDoc, aPosition); + auto pUndoAction = std::make_unique(mrDocShell, aPosition, aOldVal, aNewVal); + pUndoSetCell = pUndoAction.get(); + pUndoMgr->AddUndoAction(std::move(pUndoAction)); + } + + syncCellToSheetViews(aPosition, pUndoSetCell); + + if (bHeight) + mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi); + + mrDocShell.PostPaintCell(aPosition); + aModificator.SetDocumentModified(); + + // #103934#; notify editline and cell in edit mode + if (mbApi) + mrDocFunc.NotifyInputHandler(aPosition); + + mrDocShell.ResolveSpilledOutputs(); + + return true; +} +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SortOperation.cxx b/sc/source/ui/operation/SortOperation.cxx new file mode 100644 index 000000000000..a8574dc34a08 --- /dev/null +++ b/sc/source/ui/operation/SortOperation.cxx @@ -0,0 +1,333 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +SortOperation::SortOperation(ScDocShell& rDocShell, SCTAB nTab, const ScSortParam& rSortParam, + bool bRecord, bool bPaint, bool bApi) + : Operation(OperationType::Sort, bRecord, bApi) + , mrDocShell(rDocShell) + , mnTab(nTab) + , mrSortParam(rSortParam) + , mbPaint(bPaint) +{ +} + +bool SortOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScDBData* pDBData = rDoc.GetDBAtArea(mnTab, mrSortParam.nCol1, mrSortParam.nRow1, + mrSortParam.nCol2, mrSortParam.nRow2); + if (!pDBData) + { + SAL_WARN("sc", "Sort: no DBData"); + return false; + } + + ScSortParam aLocalParam(mrSortParam); + + // If we are in a sheet view and aren't sorting auto-filtered cell range, we need + // to sync the sorted cells. If this is the case then we need to convert the tab + // from the sheet view tab to the default view tab. + if (mpViewData && rDoc.IsSheetViewHolder(mnTab) && !pDBData->HasAutoFilter()) + { + SCTAB nSheetViewTab = mnTab; + mnTab = rDoc.GetDefaultViewTableNumber(nSheetViewTab); + + if (aLocalParam.nSourceTab == nSheetViewTab) + aLocalParam.nSourceTab = mnTab; + + if (aLocalParam.nDestTab == nSheetViewTab) + aLocalParam.nDestTab = mnTab; + } + + bool bCopy = !mrSortParam.bInplace; + if (bCopy && mrSortParam.nDestCol == mrSortParam.nCol1 + && mrSortParam.nDestRow == mrSortParam.nRow1 && mrSortParam.nDestTab == mnTab) + bCopy = false; + + if (bCopy) + { + // Copy the data range to the destination then move the sort range to it. + ScRange aSrcRange(mrSortParam.nCol1, mrSortParam.nRow1, mnTab, mrSortParam.nCol2, + mrSortParam.nRow2, mnTab); + ScAddress aDestPos(mrSortParam.nDestCol, mrSortParam.nDestRow, mrSortParam.nDestTab); + + ScDocFunc& rDocFunc = mrDocShell.GetDocFunc(); + bool bRet = rDocFunc.MoveBlock(aSrcRange, aDestPos, false, mbRecord, mbPaint, mbApi); + + if (!bRet) + return false; + + aLocalParam.MoveToDest(); + mnTab = aLocalParam.nDestTab; + } + + // tdf#119804: If there is a header row/column, it won't be affected by + // sorting; so we can exclude it from the test. + SCROW nStartingRowToEdit = aLocalParam.nRow1; + SCCOL nStartingColToEdit = aLocalParam.nCol1; + if (aLocalParam.bHasHeader) + { + if (aLocalParam.bByRow) + nStartingRowToEdit++; + else + nStartingColToEdit++; + } + + if (!checkSheetViewProtection()) + return false; + + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, mnTab, nStartingColToEdit, nStartingRowToEdit, aLocalParam.nCol2, aLocalParam.nRow2, + true /*bNoMatrixAtAll*/); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + const ScInputOptions aInputOption = ScModule::get()->GetInputOptions(); + const bool bUpdateRefs = aInputOption.GetSortRefUpdate(); + + // Adjust aLocalParam cols/rows to used data area. Keep sticky top row or + // column (depending on direction) in any case, not just if it has headers, + // so empty leading cells will be sorted to the end. + // aLocalParam.nCol/Row will encompass data content only, extras in + // aLocalParam.aDataAreaExtras. + bool bShrunk = false; + aLocalParam.aDataAreaExtras.resetArea(); + rDoc.ShrinkToUsedDataArea( + bShrunk, mnTab, aLocalParam.nCol1, aLocalParam.nRow1, aLocalParam.nCol2, aLocalParam.nRow2, + false, aLocalParam.bByRow, !aLocalParam.bByRow, + (aLocalParam.aDataAreaExtras.anyExtrasWanted() ? &aLocalParam.aDataAreaExtras : nullptr)); + + SCROW nStartRow = aLocalParam.nRow1; + if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < aLocalParam.nRow2) + ++nStartRow; + + SCCOL nOverallCol1 = aLocalParam.nCol1; + SCROW nOverallRow1 = aLocalParam.nRow1; + SCCOL nOverallCol2 = aLocalParam.nCol2; + SCROW nOverallRow2 = aLocalParam.nRow2; + if (aLocalParam.aDataAreaExtras.anyExtrasWanted()) + { + // Trailing empty excess columns/rows are excluded from being sorted, + // they stick at the end. Clip them. + const ScDataAreaExtras::Clip eClip + = (aLocalParam.bByRow ? ScDataAreaExtras::Clip::Row : ScDataAreaExtras::Clip::Col); + aLocalParam.aDataAreaExtras.GetOverallRange(nOverallCol1, nOverallRow1, nOverallCol2, + nOverallRow2, eClip); + // Make it permanent. + aLocalParam.aDataAreaExtras.SetOverallRange(nOverallCol1, nOverallRow1, nOverallCol2, + nOverallRow2); + + if (bUpdateRefs) + { + // With update references the entire range needs to be handled as + // one entity for references pointing within to be moved along, + // even when there's no data content. For huge ranges we may be + // DOOMed then. + aLocalParam.nCol1 = nOverallCol1; + aLocalParam.nRow1 = nOverallRow1; + aLocalParam.nCol2 = nOverallCol2; + aLocalParam.nRow2 = nOverallRow2; + } + } + + if (aLocalParam.aDataAreaExtras.mbCellFormats + && rDoc.HasAttrib(nOverallCol1, nStartRow, mnTab, nOverallCol2, nOverallRow2, mnTab, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)) + { + // Merge attributes would be mixed up during sorting. + if (!mbApi) + mrDocShell.ErrorMessage(STR_SORT_ERR_MERGED); + return false; + } + + // execute + + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + // Calculate the script types for all cells in the sort range beforehand. + // This will speed up the row height adjustment that takes place after the + // sort. + rDoc.UpdateScriptTypes(ScAddress(aLocalParam.nCol1, nStartRow, mnTab), + aLocalParam.nCol2 - aLocalParam.nCol1 + 1, + aLocalParam.nRow2 - nStartRow + 1); + + // No point adjusting row heights after the sort when all rows have the same height. + bool bUniformRowHeight = rDoc.HasUniformRowHeight(mnTab, nStartRow, nOverallRow2); + + bool bRepeatQuery = false; // repeat existing filter? + ScQueryParam aQueryParam; + pDBData->GetQueryParam(aQueryParam); + if (aQueryParam.GetEntry(0).bDoQuery) + bRepeatQuery = true; + + sc::ReorderParam aUndoParam; + + // Capture sheet view sort data before the sort (for undo) + std::shared_ptr pSheetView; + std::shared_ptr pSortDataBefore; + std::shared_ptr pDefaultViewSortDataBefore; + bool bDefaultViewSort = false; + SCTAB nDefaultViewTab = -1; + + if (mbRecord) + { + pSheetView = rDoc.GetSheetView(mnTab); + if (pSheetView) + { + // Sorting on a sheet view tab + pSortDataBefore = pSheetView->captureSortData(); + } + else + { + // Sorting on a default view tab - capture manager sort data + std::shared_ptr pManager = rDoc.GetSheetViewManager(mnTab); + if (pManager && !pManager->isEmpty()) + { + nDefaultViewTab = mnTab; + bDefaultViewSort = true; + pDefaultViewSortDataBefore = pManager->captureSortData(); + } + } + } + + // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set), + // but always call it for random shuffle which doesn't need sort keys + if (aLocalParam.meSortOrderType == SortOrderType::Random + || (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)) + { + ScProgress aProgress(&mrDocShell, ScResId(STR_PROGRESS_SORTING), 0, true); + if (!bRepeatQuery) + bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, aLocalParam.nRow2, mnTab); + rDoc.Sort(mnTab, aLocalParam, bRepeatQuery, bUpdateRefs, &aProgress, &aUndoParam); + } + + if (mbRecord) + { + auto pUndoSort = std::make_unique(mrDocShell, aUndoParam); + + // Capture sheet view sort data after the sort and attach to undo + if (pSheetView) + { + auto pSortDataAfter = pSheetView->captureSortData(); + pUndoSort->setSheetViewContext(rDoc.GetDefaultViewTableNumber(mnTab), + pSheetView->getID(), std::move(pSortDataBefore), + std::move(pSortDataAfter)); + } + else if (bDefaultViewSort) + { + std::shared_ptr pDefaultViewSortDataAfter; + std::shared_ptr pManager + = rDoc.GetSheetViewManager(nDefaultViewTab); + if (pManager) + pDefaultViewSortDataAfter = pManager->captureSortData(); + pUndoSort->setDefaultViewContext(nDefaultViewTab, std::move(pDefaultViewSortDataBefore), + std::move(pDefaultViewSortDataAfter)); + } + + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoSort)); + } + + pDBData->SetSortParam(mrSortParam); + // Remember additional settings on anonymous database ranges. + if (pDBData == rDoc.GetAnonymousDBData(mnTab) + || rDoc.GetDBCollection()->getAnonDBs().has(pDBData)) + pDBData->UpdateFromSortParam(mrSortParam); + + if (SfxViewShell* pKitSomeViewForThisDoc + = comphelper::LibreOfficeKit::isActive() ? mrDocShell.GetBestViewShell(false) : nullptr) + { + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while (pViewShell) + { + ScTabViewShell* pTabViewShell = dynamic_cast(pViewShell); + if (pTabViewShell && pTabViewShell->GetDocId() == pKitSomeViewForThisDoc->GetDocId()) + { + if (ScPositionHelper* pPosHelper + = pTabViewShell->GetViewData().GetLOKHeightHelper(mnTab)) + pPosHelper->invalidateByIndex(nStartRow); + } + pViewShell = SfxViewShell::GetNext(*pViewShell); + } + + ScTabViewShell::notifyAllViewsSheetGeomInvalidation( + pKitSomeViewForThisDoc, false /* bColumns */, true /* bRows */, true /* bSizes*/, + true /* bHidden */, true /* bFiltered */, true /* bGroups */, mnTab); + } + + if (nStartRow <= aLocalParam.nRow2) + { + ScRange aDirtyRange(aLocalParam.nCol1, nStartRow, mnTab, aLocalParam.nCol2, + aLocalParam.nRow2, mnTab); + rDoc.SetDirty(aDirtyRange, true); + } + + if (mbPaint) + { + PaintPartFlags nPaint = PaintPartFlags::Grid; + SCCOL nStartX = nOverallCol1; + SCROW nStartY = nOverallRow1; + SCCOL nEndX = nOverallCol2; + SCROW nEndY = nOverallRow2; + if (bRepeatQuery) + { + nPaint |= PaintPartFlags::Left; + nStartX = 0; + nEndX = rDoc.MaxCol(); + } + mrDocShell.PostPaint(ScRange(nStartX, nStartY, mnTab, nEndX, nEndY, mnTab), nPaint); + } + + if (!bUniformRowHeight && nStartRow <= nOverallRow2) + mrDocShell.AdjustRowHeight(nStartRow, nOverallRow2, mnTab); + + // Perform syncing, but only if we don't sort the auto-filtered cell range + if (!pDBData->HasAutoFilter()) + syncSheetViews(); + + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SubTotalsOperation.cxx b/sc/source/ui/operation/SubTotalsOperation.cxx new file mode 100644 index 000000000000..7bcb7c9cf98b --- /dev/null +++ b/sc/source/ui/operation/SubTotalsOperation.cxx @@ -0,0 +1,216 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sc +{ +SubTotalsOperation::SubTotalsOperation(ScDocShell& rDocShell, SCTAB nTab, + const ScSubTotalParam& rParam, bool bRecord, bool bApi) + : Operation(OperationType::SubTotals, bRecord, bApi) + , mrDocShell(rDocShell) + , mnTab(nTab) + , maParam(rParam) +{ +} + +bool SubTotalsOperation::runImplementation() +{ + //! use also for ScDBFunc::DoSubTotals ! + // then stays outside: + // - mark new range (from DBData) + // - SelectionChanged (?) + + SCTAB nTab = convertTab(mnTab); + + bool bDo = !maParam.bRemoveOnly; // false = only delete + + ScDocument& rDoc = mrDocShell.GetDocument(); + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + ScDBData* pDBData + = rDoc.GetDBAtArea(nTab, maParam.nCol1, maParam.nRow1, maParam.nCol2, maParam.nRow2); + if (!pDBData) + { + OSL_FAIL("SubTotals: no DBData"); + return false; + } + + ScEditableTester aTester = ScEditableTester::CreateAndTestBlock( + rDoc, nTab, 0, maParam.nRow1 + 1, rDoc.MaxCol(), rDoc.MaxRow()); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + if (rDoc.HasAttrib(maParam.nCol1, maParam.nRow1 + 1, nTab, maParam.nCol2, maParam.nRow2, nTab, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)) + { + if (!mbApi) + mrDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); // don't insert into merged + return false; + } + + bool bOk = true; + if (maParam.bReplace) + { + if (rDoc.TestRemoveSubTotals(nTab, maParam)) + { + std::unique_ptr xBox(Application::CreateMessageDialog( + ScDocShell::GetActiveDialogParent(), VclMessageType::Question, + VclButtonsType::YesNo, ScResId(STR_MSSG_DOSUBTOTALS_1))); // "Delete Data?" + xBox->set_title(ScResId(STR_MSSG_DOSUBTOTALS_0)); // "StarCalc" + bOk = xBox->run() == RET_YES; + } + } + + if (!bOk) + return false; + + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + ScDocShellModificator aModificator(mrDocShell); + + ScSubTotalParam aNewParam(maParam); // end of range is being changed + ScDocumentUniquePtr pUndoDoc; + std::unique_ptr pUndoTab; + std::unique_ptr pUndoRange; + std::unique_ptr pUndoDB; + + if (mbRecord) // secure old data + { + bool bOldFilter = bDo && maParam.bDoSort; + + SCTAB nTabCount = rDoc.GetTableCount(); + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + ScOutlineTable* pTable = rDoc.GetOutlineTable(nTab); + if (pTable) + { + pUndoTab.reset(new ScOutlineTable(*pTable)); + + // column/row state + SCCOLROW nOutStartCol, nOutEndCol; + SCCOLROW nOutStartRow, nOutEndRow; + pTable->GetColArray().GetRange(nOutStartCol, nOutEndCol); + pTable->GetRowArray().GetRange(nOutStartRow, nOutEndRow); + + pUndoDoc->InitUndo(rDoc, nTab, nTab, true, true); + rDoc.CopyToDocument(static_cast(nOutStartCol), 0, nTab, + static_cast(nOutEndCol), rDoc.MaxRow(), nTab, + InsertDeleteFlags::NONE, false, *pUndoDoc); + rDoc.CopyToDocument(0, nOutStartRow, nTab, rDoc.MaxCol(), nOutEndRow, nTab, + InsertDeleteFlags::NONE, false, *pUndoDoc); + } + else + pUndoDoc->InitUndo(rDoc, nTab, nTab, false, bOldFilter); + + // secure data range - incl. filtering result + rDoc.CopyToDocument(0, maParam.nRow1 + 1, nTab, rDoc.MaxCol(), maParam.nRow2, nTab, + InsertDeleteFlags::ALL, false, *pUndoDoc); + + // all formulas because of references + rDoc.CopyToDocument(0, 0, 0, rDoc.MaxCol(), rDoc.MaxRow(), nTabCount - 1, + InsertDeleteFlags::FORMULA, false, *pUndoDoc); + + // ranges of DB and other + ScRangeName& rDocRange = rDoc.GetRangeName(); + if (!rDocRange.empty()) + pUndoRange.reset(new ScRangeName(rDocRange)); + ScDBCollection* pDocDB = rDoc.GetDBCollection(); + if (!pDocDB->empty()) + pUndoDB.reset(new ScDBCollection(*pDocDB)); + } + + // rDoc.SetOutlineTable( nTab, NULL ); + ScOutlineTable* pOut = rDoc.GetOutlineTable(nTab); + if (pOut) + pOut->GetRowArray().RemoveAll(); // only delete row outlines + + if (maParam.bReplace) + rDoc.RemoveSubTotals(nTab, aNewParam); + bool bSuccess = true; + if (bDo) + { + // sort + if (maParam.bDoSort) + { + pDBData->SetArea(nTab, aNewParam.nCol1, aNewParam.nRow1, aNewParam.nCol2, + aNewParam.nRow2); + + // set partial result field to before the sorting + // (Duplicates are omitted, so can be called again) + + ScSortParam aOldSort; + pDBData->GetSortParam(aOldSort); + ScSortParam aSortParam(aNewParam, aOldSort); + ScDBDocFunc aDBDocFunc(mrDocShell); + aDBDocFunc.SortTab(nTab, aSortParam, false, false, mbApi); + } + + bSuccess = rDoc.DoSubTotals(nTab, aNewParam); + rDoc.SetDrawPageSize(nTab); + } + ScRange aDirtyRange(aNewParam.nCol1, aNewParam.nRow1, nTab, aNewParam.nCol2, aNewParam.nRow2, + nTab); + rDoc.SetDirty(aDirtyRange, true); + + if (mbRecord) + { + // ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL; + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, nTab, maParam, aNewParam.nRow2, std::move(pUndoDoc), + std::move(pUndoTab), // pUndoDBData, + std::move(pUndoRange), std::move(pUndoDB))); + } + + if (!bSuccess) + { + // "Cannot insert rows" + if (!mbApi) + mrDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); + } + + // memorize + pDBData->SetSubTotalParam(aNewParam); + pDBData->SetArea(nTab, aNewParam.nCol1, aNewParam.nRow1, aNewParam.nCol2, aNewParam.nRow2); + rDoc.CompileDBFormula(); + + mrDocShell.PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab), + PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top + | PaintPartFlags::Size); + + syncSheetViews(); + + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/TransliterateTextOperation.cxx b/sc/source/ui/operation/TransliterateTextOperation.cxx new file mode 100644 index 000000000000..56e5480fd696 --- /dev/null +++ b/sc/source/ui/operation/TransliterateTextOperation.cxx @@ -0,0 +1,93 @@ +/* -*- 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 + +#include +#include +#include +#include +#include + +#include + +namespace sc +{ +TransliterateTextOperation::TransliterateTextOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, + const ScMarkData& rMark, + TransliterationFlags nType, bool bApi) + : Operation(OperationType::TransliterateText, true, bApi) + , mrDocFunc(rDocFunc) + , mrDocShell(rDocShell) + , mrMark(rMark) + , mnType(nType) +{ +} + +bool TransliterateTextOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + + ScDocument& rDoc = mrDocShell.GetDocument(); + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + ScMarkData aMultiMark = convertMark(mrMark); + aMultiMark.SetMarking(false); // for MarkToMulti + aMultiMark.MarkToMulti(); + const ScRange& aMarkRange = aMultiMark.GetMultiMarkArea(); + + ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, aMultiMark); + if (!aTester.IsEditable()) + { + if (!mbApi) + mrDocShell.ErrorMessage(aTester.GetMessageId()); + return false; + } + + if (mbRecord) + { + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCTAB nTabCount = rDoc.GetTableCount(); + + ScDocumentUniquePtr pUndoDoc(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDoc, nStartTab, nStartTab); + for (const auto& rTab : mrMark) + { + if (rTab >= nTabCount) + break; + + if (rTab != nStartTab) + pUndoDoc->AddUndoTab(rTab, rTab); + } + + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount - 1); + rDoc.CopyToDocument(aCopyRange, InsertDeleteFlags::CONTENTS, true, *pUndoDoc, &aMultiMark); + + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, aMultiMark, std::move(pUndoDoc), mnType)); + } + + rDoc.TransliterateText(aMultiMark, mnType); + + syncSheetViews(); + + if (!mrDocFunc.AdjustRowHeight(aMarkRange, true, true)) + mrDocShell.PostPaint(aMarkRange, PaintPartFlags::Grid); + + aModificator.SetDocumentModified(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/UngroupSparklinesOperation.cxx b/sc/source/ui/operation/UngroupSparklinesOperation.cxx new file mode 100644 index 000000000000..7ddaf12872d2 --- /dev/null +++ b/sc/source/ui/operation/UngroupSparklinesOperation.cxx @@ -0,0 +1,39 @@ +/* -*- 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 + +#include +#include + +namespace sc +{ +UngroupSparklinesOperation::UngroupSparklinesOperation(ScDocShell& rDocShell, ScRange const& rRange) + : Operation(OperationType::SparklineUngroup, false, false) + , mrDocShell(rDocShell) + , maRange(rRange) +{ +} + +bool UngroupSparklinesOperation::runImplementation() +{ + ScRange aRange = convertRange(maRange); + + auto pUndo = std::make_unique(mrDocShell, aRange); + // ungroup sparklines by "redoing" + pUndo->Redo(); + mrDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); + + syncSheetViews(); + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/UpdatePivotTableOperation.cxx b/sc/source/ui/operation/UpdatePivotTableOperation.cxx new file mode 100644 index 000000000000..a18bf44b0fb2 --- /dev/null +++ b/sc/source/ui/operation/UpdatePivotTableOperation.cxx @@ -0,0 +1,107 @@ +/* -*- 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 +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace sc +{ +UpdatePivotTableOperation::UpdatePivotTableOperation(ScDocShell& rDocShell, ScDPObject& rDPObject, + bool bRecord, bool bApi) + : PivotTableOperation(OperationType::PivotTableUpdate, rDocShell, bRecord, bApi) + , mrDPObject(rDPObject) +{ +} + +bool UpdatePivotTableOperation::runImplementation() +{ + ScDocShellModificator aModificator(mrDocShell); + weld::WaitObject aWait(ScDocShell::GetActiveDialogParent()); + + ScDocument& rDoc = mrDocShell.GetDocument(); + + // Use default view's DPObject when called from a sheet view + ScDPObject* pDPObject = findDefaultViewDPObject(mrDPObject); + if (!pDPObject) + pDPObject = &mrDPObject; + + // Apply the SaveData from the input DPObject (which may have layout changes) + if (pDPObject != &mrDPObject && mrDPObject.GetSaveData()) + pDPObject->SetSaveData(*mrDPObject.GetSaveData()); + + if (!sc::pivot::isEditable(mrDocShell, pDPObject->GetOutRange(), mbApi, + sc::EditAction::UpdatePivotTable)) + return false; + + ScDocumentUniquePtr pOldUndoDoc; + ScDocumentUniquePtr pNewUndoDoc; + + ScDPObject aUndoDPObject(*pDPObject); // For undo or revert on failure. + + if (mbRecord && !rDoc.IsUndoEnabled()) + mbRecord = false; + + if (mbRecord) + sc::pivot::createUndoDoc(pOldUndoDoc, rDoc, pDPObject->GetOutRange()); + + pDPObject->SetAllowMove(false); + pDPObject->ReloadGroupTableData(); + if (!pDPObject->SyncAllDimensionMembers()) + return false; + + pDPObject->InvalidateData(); // before getting the new output area + + // make sure the table has a name (not set by dialog) + if (pDPObject->GetName().isEmpty()) + pDPObject->SetName(rDoc.GetDPCollection()->CreateNewName()); + + ScRange aNewOut; + if (!sc::pivot::checkNewOutputRange(*pDPObject, mrDocShell, aNewOut, mbApi, + sc::EditAction::UpdatePivotTable)) + { + *pDPObject = aUndoDPObject; + return false; + } + + if (mbRecord) + sc::pivot::createUndoDoc(pNewUndoDoc, rDoc, aNewOut); + + // Use spill checking output if the destination range has non-empty cells, + // write #SPILL! into the origin cell instead of overwriting. + // Skip the spill check during XML import + pDPObject->Output(aNewOut.aStart, !rDoc.IsImportingXML()); + mrDocShell.PostPaintGridAll(); + + if (mbRecord) + { + mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique( + mrDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObject, pDPObject, + false)); + } + + syncSheetViews(); + + // notify API objects + rDoc.BroadcastUno(ScDataPilotModifiedHint(pDPObject->GetName())); + aModificator.SetDocumentModified(); + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/optdlg/calcoptionsdlg.hxx b/sc/source/ui/optdlg/calcoptionsdlg.hxx index 82cf95bb9aa3..4a32e4806ac8 100644 --- a/sc/source/ui/optdlg/calcoptionsdlg.hxx +++ b/sc/source/ui/optdlg/calcoptionsdlg.hxx @@ -9,9 +9,11 @@ #pragma once +#include #include #include -#include +#include + #include class ScCalcOptionsDialog : public weld::GenericDialogController diff --git a/sc/source/ui/optdlg/opredlin.cxx b/sc/source/ui/optdlg/opredlin.cxx index 04e1baed370d..66575e25c3c1 100644 --- a/sc/source/ui/optdlg/opredlin.cxx +++ b/sc/source/ui/optdlg/opredlin.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff --git a/sc/source/ui/optdlg/tpcalc.cxx b/sc/source/ui/optdlg/tpcalc.cxx index 80f5c674363b..731c7a4e8fc6 100644 --- a/sc/source/ui/optdlg/tpcalc.cxx +++ b/sc/source/ui/optdlg/tpcalc.cxx @@ -21,7 +21,6 @@ #include #include -#include #include #include diff --git a/sc/source/ui/optdlg/tpcompatibility.cxx b/sc/source/ui/optdlg/tpcompatibility.cxx index 5ba87d8ee8dd..53e5b18fc057 100644 --- a/sc/source/ui/optdlg/tpcompatibility.cxx +++ b/sc/source/ui/optdlg/tpcompatibility.cxx @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/sc/source/ui/optdlg/tpdefaults.cxx b/sc/source/ui/optdlg/tpdefaults.cxx index a2dff21e6be3..5aced25ff812 100644 --- a/sc/source/ui/optdlg/tpdefaults.cxx +++ b/sc/source/ui/optdlg/tpdefaults.cxx @@ -17,6 +17,7 @@ #include #include #include +#include ScTpDefaultsOptions::ScTpDefaultsOptions(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rCoreSet) : SfxTabPage(pPage, pController, u"modules/scalc/ui/optdefaultpage.ui"_ustr, u"OptDefaultPage"_ustr, &rCoreSet) @@ -153,15 +154,9 @@ void ScTpDefaultsOptions::OnFocusPrefixInput() maOldPrefixValue = m_xEdSheetPrefix->get_text(); } -IMPL_LINK_NOARG(ScTpDefaultsOptions, NumModifiedHdl, weld::Entry&, void) -{ - CheckNumSheets(); -} +IMPL_LINK_NOARG(ScTpDefaultsOptions, NumModifiedHdl, weld::TextWidget&, void) { CheckNumSheets(); } -IMPL_LINK_NOARG(ScTpDefaultsOptions, PrefixModifiedHdl, weld::Entry&, void) -{ - CheckPrefix(); -} +IMPL_LINK_NOARG(ScTpDefaultsOptions, PrefixModifiedHdl, weld::TextWidget&, void) { CheckPrefix(); } IMPL_LINK_NOARG(ScTpDefaultsOptions, PrefixEditOnFocusHdl, weld::Widget&, void) { diff --git a/sc/source/ui/optdlg/tpformula.cxx b/sc/source/ui/optdlg/tpformula.cxx index 6cd9719c3fd6..80560d29df2f 100644 --- a/sc/source/ui/optdlg/tpformula.cxx +++ b/sc/source/ui/optdlg/tpformula.cxx @@ -32,6 +32,7 @@ #include #include #include +#include ScTpFormulaOptions::ScTpFormulaOptions(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) : SfxTabPage(pPage, pController, u"modules/scalc/ui/optformula.ui"_ustr, u"OptFormula"_ustr, &rCoreAttrs) @@ -65,7 +66,7 @@ ScTpFormulaOptions::ScTpFormulaOptions(weld::Container* pPage, weld::DialogContr mxEdSepArrayCol->connect_insert_text(LINK( this, ScTpFormulaOptions, ColSepInsertTextHdl )); mxEdSepArrayRow->connect_insert_text(LINK( this, ScTpFormulaOptions, RowSepInsertTextHdl )); - Link aLink = LINK( this, ScTpFormulaOptions, SepModifyHdl ); + Link aLink = LINK(this, ScTpFormulaOptions, SepModifyHdl); mxEdSepFuncArg->connect_changed(aLink); mxEdSepArrayCol->connect_changed(aLink); mxEdSepArrayRow->connect_changed(aLink); @@ -95,7 +96,7 @@ void ScTpFormulaOptions::ResetSeparators() mxEdSepArrayRow->set_text(aArrayRow); } -void ScTpFormulaOptions::OnFocusSeparatorInput(weld::Entry* pEdit) +void ScTpFormulaOptions::OnFocusSeparatorInput(weld::TextWidget* pEdit) { if (!pEdit) return; @@ -246,7 +247,7 @@ IMPL_LINK(ScTpFormulaOptions, ColSepInsertTextHdl, OUString&, rTest, bool) return true; } -IMPL_LINK( ScTpFormulaOptions, SepModifyHdl, weld::Entry&, rEdit, void ) +IMPL_LINK(ScTpFormulaOptions, SepModifyHdl, weld::TextWidget&, rEdit, void) { OnFocusSeparatorInput(&rEdit); } diff --git a/sc/source/ui/optdlg/tpprint.cxx b/sc/source/ui/optdlg/tpprint.cxx index 244784302025..814dff2c7813 100644 --- a/sc/source/ui/optdlg/tpprint.cxx +++ b/sc/source/ui/optdlg/tpprint.cxx @@ -27,6 +27,7 @@ #include #include #include +#include ScTpPrintOptions::ScTpPrintOptions( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs ) diff --git a/sc/source/ui/optdlg/tpusrlst.cxx b/sc/source/ui/optdlg/tpusrlst.cxx index 74264aea30a8..ead3f6bc953e 100644 --- a/sc/source/ui/optdlg/tpusrlst.cxx +++ b/sc/source/ui/optdlg/tpusrlst.cxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -46,7 +45,7 @@ const sal_Unicode cDelimiter = ','; -// Benutzerdefinierte Listen: +// User-defined lists ScTpUserLists::ScTpUserLists( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs ) @@ -64,29 +63,19 @@ ScTpUserLists::ScTpUserLists( weld::Container* pPage, weld::DialogController* pC , mxBtnModify(m_xBuilder->weld_button(u"modify"_ustr)) , mxBtnRemove(m_xBuilder->weld_button(u"delete"_ustr)) , mxBtnCopy(m_xBuilder->weld_button(u"copy"_ustr)) - , aStrQueryRemove ( ScResId( STR_QUERYREMOVE ) ) - , aStrCopyList ( ScResId( STR_COPYLIST ) ) - , aStrCopyFrom ( ScResId( STR_COPYFROM ) ) - , aStrCopyErr ( ScResId( STR_COPYERR ) ) - , nWhichUserLists ( GetWhich( SID_SCUSERLISTS ) ) - , pDoc ( nullptr ) - , pViewData ( nullptr ) - , bModifyMode ( false ) - , bCancelMode ( false ) - , bCopyDone ( false ) - , nCancelPos ( 0 ) + , m_aStrQueryRemove(ScResId(STR_QUERYREMOVE)) + , m_aStrCopyFrom(ScResId(STR_COPYFROM)) + , m_aStrCopyErr(ScResId(STR_COPYERR)) + , m_nWhichUserLists(GetWhich(SID_SCUSERLISTS)) + , m_pDoc(nullptr) + , m_pViewData(nullptr) + , m_bModifyMode(false) + , m_bCancelMode(false) + , m_bCopyDone(false) + , m_nCancelPos(0) { SetExchangeSupport(); - Init(); - Reset(&rCoreAttrs); -} -ScTpUserLists::~ScTpUserLists() -{ -} - -void ScTpUserLists::Init() -{ SfxViewShell* pSh = SfxViewShell::Current(); ScTabViewShell* pViewSh = dynamic_cast( pSh ); @@ -107,18 +96,17 @@ void ScTpUserLists::Init() SCCOL nEndCol = 0; SCROW nEndRow = 0; - pViewData = &pViewSh->GetViewData(); - pDoc = &pViewData->GetDocument(); + m_pViewData = &pViewSh->GetViewData(); + m_pDoc = &m_pViewData->GetDocument(); - pViewData->GetSimpleArea( nStartCol, nStartRow, nStartTab, - nEndCol, nEndRow, nEndTab ); + m_pViewData->GetSimpleArea(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); PutInOrder( nStartCol, nEndCol ); PutInOrder( nStartRow, nEndRow ); PutInOrder( nStartTab, nEndTab ); - aStrSelectedArea = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab - ).Format(*pDoc, ScRefFlags::RANGE_ABS_3D); + m_aStrSelectedArea = ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab) + .Format(*m_pDoc, ScRefFlags::RANGE_ABS_3D); mxBtnCopy->connect_clicked ( LINK( this, ScTpUserLists, BtnClickHdl ) ); mxBtnCopy->set_sensitive(true); @@ -130,6 +118,11 @@ void ScTpUserLists::Init() mxEdCopyFrom->set_sensitive(false); } + Reset(&rCoreAttrs); +} + +ScTpUserLists::~ScTpUserLists() +{ } std::unique_ptr ScTpUserLists::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) @@ -137,20 +130,20 @@ std::unique_ptr ScTpUserLists::Create( weld::Container* pPage, weld: return std::make_unique(pPage, pController, *rAttrSet); } -void ScTpUserLists::Reset( const SfxItemSet* rCoreAttrs ) +void ScTpUserLists::Reset(const SfxItemSet* pCoreAttrs) { - const ScUserListItem& rUserListItem = static_cast( - rCoreAttrs->Get( nWhichUserLists )); + const ScUserListItem& rUserListItem + = static_cast(pCoreAttrs->Get(m_nWhichUserLists)); const ScUserList* pCoreList = rUserListItem.GetUserList(); OSL_ENSURE( pCoreList, "UserList not found :-/" ); if ( pCoreList ) { - if ( !pUserLists ) - pUserLists.reset( new ScUserList( *pCoreList ) ); + if (!m_pUserLists) + m_pUserLists.reset(new ScUserList(*pCoreList)); else - *pUserLists = *pCoreList; + *m_pUserLists = *pCoreList; if ( UpdateUserListBox() > 0 ) { @@ -158,10 +151,10 @@ void ScTpUserLists::Reset( const SfxItemSet* rCoreAttrs ) UpdateEntries( 0 ); } } - else if ( !pUserLists ) - pUserLists.reset( new ScUserList ); + else if (!m_pUserLists) + m_pUserLists.reset(new ScUserList); - mxEdCopyFrom->set_text( aStrSelectedArea ); + mxEdCopyFrom->set_text(m_aStrSelectedArea); if ( mxLbLists->n_children() == 0 || officecfg::Office::Calc::SortList::List::isReadOnly() ) { @@ -180,7 +173,7 @@ void ScTpUserLists::Reset( const SfxItemSet* rCoreAttrs ) mxBtnAdd->set_sensitive(false); mxBtnModify->set_sensitive(false); - if ( !bCopyDone && pViewData ) + if (!m_bCopyDone && m_pViewData) { mxFtCopyFrom->set_sensitive(true); mxEdCopyFrom->set_sensitive(true); @@ -210,40 +203,40 @@ OUString ScTpUserLists::GetAllStrings() return sAllStrings.toString().replaceAll("_", ""); } -bool ScTpUserLists::FillItemSet( SfxItemSet* rCoreAttrs ) +bool ScTpUserLists::FillItemSet(SfxItemSet* pCoreAttrs) { // Changes aren't saved? // -> simulate click of Add-Button - if ( bModifyMode || bCancelMode ) + if (m_bModifyMode || m_bCancelMode) BtnClickHdl(*mxBtnAdd); - const ScUserListItem& rUserListItem = static_cast( - GetItemSet().Get( nWhichUserLists )); + const ScUserListItem& rUserListItem + = static_cast(GetItemSet().Get(m_nWhichUserLists)); ScUserList* pCoreList = rUserListItem.GetUserList(); bool bDataModified = false; - if ( (pUserLists == nullptr) && (pCoreList == nullptr) ) + if ((m_pUserLists == nullptr) && (pCoreList == nullptr)) { bDataModified = false; } - else if ( pUserLists != nullptr ) + else if (m_pUserLists != nullptr) { if ( pCoreList != nullptr ) - bDataModified = (*pUserLists != *pCoreList); + bDataModified = (*m_pUserLists != *pCoreList); else bDataModified = true; } if ( bDataModified ) { - ScUserListItem aULItem( nWhichUserLists ); + ScUserListItem aULItem(m_nWhichUserLists); - if ( pUserLists ) - aULItem.SetUserList( *pUserLists ); + if (m_pUserLists) + aULItem.SetUserList(*m_pUserLists); - rCoreAttrs->Put( aULItem ); + pCoreAttrs->Put(aULItem); } return bDataModified; @@ -261,16 +254,15 @@ size_t ScTpUserLists::UpdateUserListBox() { mxLbLists->clear(); - if ( !pUserLists ) return 0; - - size_t nCount = pUserLists->size(); - OUString aEntry; + if (!m_pUserLists) + return 0; + size_t nCount = m_pUserLists->size(); for ( size_t i=0; iappend_text( aEntry ); + const OUString sEntry = (*m_pUserLists)[i].GetString(); + OSL_ENSURE(!sEntry.isEmpty(), "Empty UserList-entry :-/"); + mxLbLists->append_text(sEntry); } return nCount; @@ -278,11 +270,12 @@ size_t ScTpUserLists::UpdateUserListBox() void ScTpUserLists::UpdateEntries( size_t nList ) { - if ( !pUserLists ) return; + if (!m_pUserLists) + return; - if ( nList < pUserLists->size() ) + if (nList < m_pUserLists->size()) { - const ScUserListData& rList = (*pUserLists)[nList]; + const ScUserListData& rList = (*m_pUserLists)[nList]; std::size_t nSubCount = rList.GetSubCount(); OUStringBuffer aEntryListStr; @@ -301,58 +294,56 @@ void ScTpUserLists::UpdateEntries( size_t nList ) } } -void ScTpUserLists::MakeListStr( OUString& rListStr ) +OUString ScTpUserLists::MakeListStr(std::u16string_view sListStr) { - if (rListStr.isEmpty()) - return; + if (sListStr.empty()) + return OUString(); OUStringBuffer aStr; for(sal_Int32 nIdx=0; nIdx>=0;) { - aStr.append(comphelper::string::strip(o3tl::getToken(rListStr, 0, LF, nIdx), ' ')); + aStr.append(comphelper::string::strip(o3tl::getToken(sListStr, 0, LF, nIdx), ' ')); aStr.append(cDelimiter); } aStr.strip(cDelimiter); sal_Int32 nLen = aStr.getLength(); - rListStr.clear(); + OUString sResult; // delete all duplicates of cDelimiter sal_Int32 c = 0; while ( c < nLen ) { - rListStr += OUStringChar(aStr[c]); + sResult += OUStringChar(aStr[c]); ++c; if ((c < nLen) && (aStr[c] == cDelimiter)) { - rListStr += OUStringChar(aStr[c]); + sResult += OUStringChar(aStr[c]); while ((c < nLen) && (aStr[c] == cDelimiter)) ++c; } } + return sResult; } -void ScTpUserLists::AddNewList( const OUString& rEntriesStr ) +void ScTpUserLists::AddNewList(std::u16string_view sEntriesStr) { - OUString theEntriesStr( rEntriesStr ); + if (!m_pUserLists) + m_pUserLists.reset(new ScUserList); - if ( !pUserLists ) - pUserLists.reset( new ScUserList ); - - MakeListStr( theEntriesStr ); - - pUserLists->emplace_back(theEntriesStr); + m_pUserLists->emplace_back(MakeListStr(sEntriesStr)); } void ScTpUserLists::CopyListFromArea( const ScRefAddress& rStartPos, const ScRefAddress& rEndPos ) { - if ( bCopyDone ) return; + if (m_bCopyDone) + return; SCTAB nTab = rStartPos.Tab(); SCCOL nStartCol = rStartPos.Col(); @@ -363,7 +354,7 @@ void ScTpUserLists::CopyListFromArea( const ScRefAddress& rStartPos, if ( (nStartCol != nEndCol) && (nStartRow != nEndRow) ) { - ScColOrRowDlg aDialog(GetFrameWeld(), aStrCopyList, aStrCopyFrom); + ScColOrRowDlg aDialog(GetFrameWeld(), ScResId(STR_COPYLIST), m_aStrCopyFrom); nCellDir = aDialog.run(); } else if ( nStartCol != nEndCol ) @@ -382,9 +373,9 @@ void ScTpUserLists::CopyListFromArea( const ScRefAddress& rStartPos, OUStringBuffer aStrList; for ( SCROW row=nStartRow; row<=nEndRow; row++ ) { - if ( pDoc->HasStringData( col, row, nTab ) ) + if (m_pDoc->HasStringData(col, row, nTab)) { - OUString aStrField = pDoc->GetString(col, row, nTab); + OUString aStrField = m_pDoc->GetString(col, row, nTab); if ( !aStrField.isEmpty() ) { @@ -405,9 +396,9 @@ void ScTpUserLists::CopyListFromArea( const ScRefAddress& rStartPos, OUStringBuffer aStrList; for ( SCCOL col=nStartCol; col<=nEndCol; col++ ) { - if ( pDoc->HasStringData( col, row, nTab ) ) + if (m_pDoc->HasStringData(col, row, nTab)) { - OUString aStrField = pDoc->GetString(col, row, nTab); + OUString aStrField = m_pDoc->GetString(col, row, nTab); if ( !aStrField.isEmpty() ) { @@ -424,33 +415,27 @@ void ScTpUserLists::CopyListFromArea( const ScRefAddress& rStartPos, if ( bValueIgnored ) { - std::unique_ptr xInfoBox(Application::CreateMessageDialog(GetFrameWeld(), - VclMessageType::Info, VclButtonsType::Ok, - aStrCopyErr)); + std::unique_ptr xInfoBox(Application::CreateMessageDialog( + GetFrameWeld(), VclMessageType::Info, VclButtonsType::Ok, m_aStrCopyErr)); xInfoBox->run(); } } - bCopyDone = true; - + m_bCopyDone = true; } -void ScTpUserLists::ModifyList( size_t nSelList, - const OUString& rEntriesStr ) +void ScTpUserLists::ModifyList(size_t nSelList, std::u16string_view sEntriesStr) { - if ( !pUserLists ) return; + if (!m_pUserLists) + return; - OUString theEntriesStr( rEntriesStr ); - - MakeListStr( theEntriesStr ); - - (*pUserLists)[nSelList].SetString( theEntriesStr ); + (*m_pUserLists)[nSelList].SetString(MakeListStr(sEntriesStr)); } void ScTpUserLists::RemoveList( size_t nList ) { - if (pUserLists && nList < pUserLists->size()) - pUserLists->EraseData(nList); + if (m_pUserLists && nList < m_pUserLists->size()) + m_pUserLists->EraseData(nList); } // Handler: @@ -480,11 +465,9 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) { if (&rBtn == mxBtnNew.get() || &rBtn == mxBtnDiscard.get()) { - if ( !bCancelMode ) + if (!m_bCancelMode) { - nCancelPos = ( mxLbLists->n_children() > 0 ) - ? mxLbLists->get_selected_index() - : 0; + m_nCancelPos = (mxLbLists->n_children() > 0) ? mxLbLists->get_selected_index() : 0; mxLbLists->unselect_all(); mxFtLists->set_sensitive(false); mxLbLists->set_sensitive(false); @@ -504,13 +487,13 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) } mxBtnNew->hide(); mxBtnDiscard->show(); - bCancelMode = true; + m_bCancelMode = true; } else // if ( bCancelMode ) { if ( mxLbLists->n_children() > 0 ) { - mxLbLists->select( nCancelPos ); + mxLbLists->select(m_nCancelPos); LbSelectHdl( *mxLbLists ); mxFtLists->set_sensitive(true); mxLbLists->set_sensitive(true); @@ -525,7 +508,7 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) mxBtnAdd->set_sensitive(false); mxBtnModify->set_sensitive(false); - if ( pViewData && !bCopyDone ) + if (m_pViewData && !m_bCopyDone) { mxBtnCopy->set_sensitive(true); mxFtCopyFrom->set_sensitive(true); @@ -533,15 +516,15 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) } mxBtnNew->show(); mxBtnDiscard->hide(); - bCancelMode = false; - bModifyMode = false; + m_bCancelMode = false; + m_bModifyMode = false; } } else if (&rBtn == mxBtnAdd.get() || &rBtn == mxBtnModify.get()) { OUString theEntriesStr( mxEdEntries->get_text() ); - if ( !bModifyMode ) + if (!m_bModifyMode) { if ( !theEntriesStr.isEmpty() ) { @@ -556,7 +539,7 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) { if ( mxLbLists->n_children() > 0 ) { - mxLbLists->select( nCancelPos ); + mxLbLists->select(m_nCancelPos); LbSelectHdl( *mxLbLists ); mxLbLists->set_sensitive(true); mxLbLists->set_sensitive(true); @@ -568,7 +551,7 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) mxBtnRemove->set_sensitive(true); mxBtnNew->show(); mxBtnDiscard->hide(); - bCancelMode = false; + m_bCancelMode = false; } else // if ( bModifyMode ) { @@ -590,18 +573,18 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) mxBtnNew->show(); mxBtnDiscard->hide(); - bCancelMode = false; + m_bCancelMode = false; mxBtnAdd->show(); mxBtnModify->show(); mxBtnAdd->set_sensitive(false); mxBtnModify->set_sensitive(false); - bModifyMode = false; + m_bModifyMode = false; mxBtnRemove->set_sensitive(true); mxFtLists->set_sensitive(true); mxLbLists->set_sensitive(true); } - if ( pViewData && !bCopyDone ) + if (m_pViewData && !m_bCopyDone) { mxBtnCopy->set_sensitive(true); mxFtCopyFrom->set_sensitive(true); @@ -613,9 +596,9 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) if ( mxLbLists->n_children() > 0 ) { sal_Int32 nRemovePos = mxLbLists->get_selected_index(); - OUString aMsg = o3tl::getToken(aStrQueryRemove, 0, '#' ) - + mxLbLists->get_text( nRemovePos ) - + o3tl::getToken(aStrQueryRemove, 1, '#' ); + OUString aMsg = o3tl::getToken(m_aStrQueryRemove, 0, '#') + + mxLbLists->get_text(nRemovePos) + + o3tl::getToken(m_aStrQueryRemove, 1, '#'); std::unique_ptr xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo, @@ -646,7 +629,7 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) } } - if ( pViewData && !bCopyDone && !mxBtnCopy->get_sensitive() ) + if (m_pViewData && !m_bCopyDone && !mxBtnCopy->get_sensitive()) { mxBtnCopy->set_sensitive(true); mxFtCopyFrom->set_sensitive(true); @@ -654,9 +637,9 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) } } } - else if ( pViewData && (&rBtn == mxBtnCopy.get()) ) + else if (m_pViewData && (&rBtn == mxBtnCopy.get())) { - if ( bCopyDone ) + if (m_bCopyDone) return; ScRefAddress theStartPos; @@ -666,21 +649,14 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) if ( !theAreaStr.isEmpty() ) { - bAreaOk = ScRangeUtil::IsAbsArea( theAreaStr, - *pDoc, - pViewData->CurrentTabForData(), - &theAreaStr, - &theStartPos, - &theEndPos, - pDoc->GetAddressConvention() ); + bAreaOk = ScRangeUtil::IsAbsArea(theAreaStr, *m_pDoc, m_pViewData->CurrentTabForData(), + &theAreaStr, &theStartPos, &theEndPos, + m_pDoc->GetAddressConvention()); if ( !bAreaOk ) { - bAreaOk = ScRangeUtil::IsAbsPos( theAreaStr, - *pDoc, - pViewData->CurrentTabForData(), - &theAreaStr, - &theStartPos, - pDoc->GetAddressConvention() ); + bAreaOk = ScRangeUtil::IsAbsPos(theAreaStr, *m_pDoc, + m_pViewData->CurrentTabForData(), &theAreaStr, + &theStartPos, m_pDoc->GetAddressConvention()); theEndPos = theStartPos; } } @@ -709,11 +685,8 @@ IMPL_LINK( ScTpUserLists, BtnClickHdl, weld::Button&, rBtn, void ) } } -IMPL_LINK( ScTpUserLists, EdEntriesModHdl, weld::TextView&, rEd, void ) +IMPL_LINK_NOARG(ScTpUserLists, EdEntriesModHdl, weld::TextWidget&, void) { - if ( &rEd != mxEdEntries.get() ) - return; - if ( mxBtnCopy->get_sensitive() ) { mxBtnCopy->set_sensitive(false); @@ -723,16 +696,16 @@ IMPL_LINK( ScTpUserLists, EdEntriesModHdl, weld::TextView&, rEd, void ) if ( !mxEdEntries->get_text().isEmpty() ) { - if ( !bCancelMode && !bModifyMode ) + if (!m_bCancelMode && !m_bModifyMode) { mxBtnNew->hide(); mxBtnDiscard->show(); - bCancelMode = true; + m_bCancelMode = true; mxBtnAdd->hide(); mxBtnAdd->set_sensitive(true); mxBtnModify->show(); mxBtnModify->set_sensitive(true); - bModifyMode = true; + m_bModifyMode = true; mxBtnRemove->set_sensitive(false); mxFtLists->set_sensitive(false); mxLbLists->set_sensitive(false); diff --git a/sc/source/ui/optdlg/tpview.cxx b/sc/source/ui/optdlg/tpview.cxx index 42055ec91434..496e5fd42c94 100644 --- a/sc/source/ui/optdlg/tpview.cxx +++ b/sc/source/ui/optdlg/tpview.cxx @@ -34,6 +34,7 @@ #include #include #include +#include ScTpContentOptions::ScTpContentOptions(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rArgSet) : SfxTabPage(pPage, pController, u"modules/scalc/ui/tpviewpage.ui"_ustr, u"TpViewPage"_ustr, &rArgSet) diff --git a/sc/source/ui/pagedlg/areasdlg.cxx b/sc/source/ui/pagedlg/areasdlg.cxx index 74b74a25679c..1584dc0c5ea8 100644 --- a/sc/source/ui/pagedlg/areasdlg.cxx +++ b/sc/source/ui/pagedlg/areasdlg.cxx @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -145,7 +144,7 @@ void ScPrintAreasDlg::Close() bool ScPrintAreasDlg::IsTableLocked() const { - // Printing areas are per table, therefore it makes no sense, + // Printing areas are per table, therefore it makes no sense // to switch the table during input return true; @@ -390,13 +389,13 @@ void ScPrintAreasDlg::Impl_FillLists() // Get ranges and remember in ListBoxen - ScRangeName* pRangeNames = rDoc.GetRangeName(); + ScRangeName& rRangeNames = rDoc.GetRangeName(); - if (!pRangeNames || pRangeNames->empty()) + if (rRangeNames.empty()) // No range names to process. return; - for (const auto& rEntry : *pRangeNames) + for (const auto& rEntry : rRangeNames) { if (!rEntry.second->HasType(ScRangeData::Type::AbsArea ) && !rEntry.second->HasType(ScRangeData::Type::RefArea) diff --git a/sc/source/ui/pagedlg/scuitphfedit.cxx b/sc/source/ui/pagedlg/scuitphfedit.cxx index b01b2cdc3837..103fa489b460 100644 --- a/sc/source/ui/pagedlg/scuitphfedit.cxx +++ b/sc/source/ui/pagedlg/scuitphfedit.cxx @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include @@ -67,6 +69,7 @@ ScHFEditPage::ScHFEditPage(weld::Container* pPage, weld::DialogController* pCont , m_xBtnBold(m_xBuilder->weld_toggle_button(u"buttonBTN_BOLD"_ustr)) , m_xBtnItalic(m_xBuilder->weld_toggle_button(u"buttonBTN_ITALIC"_ustr)) , m_xBtnUnderline(m_xBuilder->weld_toggle_button(u"buttonBTN_UNDERLINE"_ustr)) + , m_xEnableHF(m_xBuilder->weld_check_button(u"checkBTN_ENABLE_HF"_ustr)) , m_xFtConfidential(m_xBuilder->weld_label(u"labelSTR_HF_CONFIDENTIAL"_ustr)) , m_xFtPage(m_xBuilder->weld_label(u"labelSTR_PAGE"_ustr)) , m_xFtOfQuestion(m_xBuilder->weld_label(u"labelSTR_HF_OF_QUESTION"_ustr)) @@ -160,8 +163,8 @@ ScHFEditPage::ScHFEditPage(weld::Container* pPage, weld::DialogController* pCont m_xLbFontFamily->append_text(rFontMetric.GetFamilyName()); } - const SvxFontItem *pFontItem = m_pEditFocus->GetEditView()->GetAttribs().GetItemIfSet( EE_CHAR_FONTINFO ); - m_xLbFontFamily->set_active_text(pFontItem->GetFamilyName()); + if (const SvxFontItem *pFontItem = m_pEditFocus->GetEditView()->GetAttribs().GetItemIfSet( EE_CHAR_FONTINFO )) + m_xLbFontFamily->set_active_text(pFontItem->GetFamilyName()); sal_uInt16 nFontHeight; for (nFontHeight = 6; nFontHeight <= 16; ++nFontHeight) @@ -175,8 +178,20 @@ ScHFEditPage::ScHFEditPage(weld::Container* pPage, weld::DialogController* pCont for (nFontHeight = 80; nFontHeight <= 96; nFontHeight += 8) m_xLbFontHeight->append_text( OUString::number(nFontHeight) ); - const SvxFontHeightItem *pFontHeightItem = m_pEditFocus->GetEditView()->GetAttribs().GetItemIfSet( EE_CHAR_FONTHEIGHT ); - m_xLbFontHeight->set_active_text( OUString::number(pFontHeightItem->GetHeight() / 20) ); + if (const SvxFontHeightItem *pFontHeightItem = m_pEditFocus->GetEditView()->GetAttribs().GetItemIfSet( EE_CHAR_FONTHEIGHT )) + m_xLbFontHeight->set_active_text( OUString::number(pFontHeightItem->GetHeight() / 20) ); + + bool bHeader = (nWhich == SID_SCATTR_PAGE_HEADERFIRST || + nWhich == SID_SCATTR_PAGE_HEADERRIGHT || + nWhich == SID_SCATTR_PAGE_HEADERLEFT); + + const bool bOn = rCoreAttrs.Get( bHeader ? ATTR_PAGE_HEADERSET : ATTR_PAGE_FOOTERSET ).GetItemSet().Get( ATTR_PAGE_ON ).GetValue(); + + m_xEnableHF->set_label( ScResId( bHeader ? STR_HF_ENABLE_HEADER : STR_HF_ENABLE_FOOTER ) ); + m_xEnableHF->set_active( bOn ); + m_xEnableHF->connect_toggled( LINK( this, ScHFEditPage, ToggleEnableHdl ) ); + + ToggleEnableHdl( *m_xEnableHF ); } IMPL_LINK_NOARG( ScHFEditPage, ObjectSelectHdl, ScEditWindow&, void ) @@ -214,16 +229,38 @@ void ScHFEditPage::Reset( const SfxItemSet* rCoreSet ) bool ScHFEditPage::FillItemSet( SfxItemSet* rCoreSet ) { ScPageHFItem aItem( nWhich ); - std::unique_ptr pLeft = m_xWndLeft->CreateTextObject(); - std::unique_ptr pCenter = m_xWndCenter->CreateTextObject(); - std::unique_ptr pRight = m_xWndRight->CreateTextObject(); + EditTextObject aLeft = m_xWndLeft->CreateTextObject(); + EditTextObject aCenter = m_xWndCenter->CreateTextObject(); + EditTextObject aRight = m_xWndRight->CreateTextObject(); - aItem.SetLeftArea ( *pLeft ); - aItem.SetCenterArea( *pCenter ); - aItem.SetRightArea ( *pRight ); + aItem.SetLeftArea ( aLeft ); + aItem.SetCenterArea( aCenter ); + aItem.SetRightArea ( aRight ); rCoreSet->Put( aItem ); + bool bHeader = (nWhich == SID_SCATTR_PAGE_HEADERFIRST || + nWhich == SID_SCATTR_PAGE_HEADERRIGHT || + nWhich == SID_SCATTR_PAGE_HEADERLEFT); + + bool bIsOn = m_xEnableHF->get_active(); + sal_uInt16 nSetId = bHeader ? ATTR_PAGE_HEADERSET : ATTR_PAGE_FOOTERSET; + + const SfxPoolItem* pItem = nullptr; + std::unique_ptr pNewItem; + + if ( rCoreSet->GetItemState( nSetId, false, &pItem ) == SfxItemState::SET ) + pNewItem.reset( static_cast( pItem->Clone() ) ); + else + pNewItem.reset( static_cast( GetItemSet().Get( nSetId ).Clone() ) ); + + bool bOldOn = pNewItem->GetItemSet().Get( ATTR_PAGE_ON ).GetValue(); + if ( bIsOn != bOldOn ) + { + pNewItem->GetItemSet().Put( SfxBoolItem( ATTR_PAGE_ON, bIsOn ) ); + rCoreSet->Put( *pNewItem ); + } + return true; } @@ -235,7 +272,7 @@ void ScHFEditPage::InitPreDefinedList() std::optional pFldColour; std::optional pFldLineStyle; - // Get the all field values at the outset. + // Get all the field values at the outset. OUString aPageFieldValue(m_xWndLeft->GetEditEngine()->CalcFieldValue(SvxFieldItem(SvxPageField(), EE_FEATURE_FIELD), 0,0, pTxtColour, pFldColour, pFldLineStyle)); OUString aSheetFieldValue(m_xWndLeft->GetEditEngine()->CalcFieldValue(SvxFieldItem(SvxTableField(), EE_FEATURE_FIELD), 0,0, pTxtColour, pFldColour, pFldLineStyle)); OUString aFileFieldValue(m_xWndLeft->GetEditEngine()->CalcFieldValue(SvxFieldItem(SvxFileField(), EE_FEATURE_FIELD), 0,0, pTxtColour, pFldColour, pFldLineStyle)); @@ -304,17 +341,13 @@ void ScHFEditPage::SetSelectDefinedList() // default to customized ScHFEntryId eSelectEntry = eEntryCount; - std::unique_ptr< EditTextObject > pLeftObj; - std::unique_ptr< EditTextObject > pCenterObj; - std::unique_ptr< EditTextObject > pRightObj; - OUString aLeftEntry; OUString aCenterEntry; OUString aRightEntry; - pLeftObj = m_xWndLeft->GetEditEngine()->CreateTextObject(); - pCenterObj = m_xWndCenter->GetEditEngine()->CreateTextObject(); - pRightObj = m_xWndRight->GetEditEngine()->CreateTextObject(); + EditTextObject aLeftObj = m_xWndLeft->GetEditEngine()->CreateTextObject(); + EditTextObject aCenterObj = m_xWndCenter->GetEditEngine()->CreateTextObject(); + EditTextObject aRightObj = m_xWndRight->GetEditEngine()->CreateTextObject(); bool bFound = false; @@ -325,9 +358,9 @@ void ScHFEditPage::SetSelectDefinedList() { case eNoneEntry: { - aLeftEntry = pLeftObj->GetText(0); - aCenterEntry = pCenterObj->GetText(0); - aRightEntry = pRightObj->GetText(0); + aLeftEntry = aLeftObj.GetText(0); + aCenterEntry = aCenterObj.GetText(0); + aRightEntry = aRightObj.GetText(0); if(aLeftEntry.isEmpty() && aCenterEntry.isEmpty() && aRightEntry.isEmpty()) { @@ -339,11 +372,11 @@ void ScHFEditPage::SetSelectDefinedList() case ePageEntry: { - aLeftEntry = pLeftObj->GetText(0); - aRightEntry = pRightObj->GetText(0); + aLeftEntry = aLeftObj.GetText(0); + aRightEntry = aRightObj.GetText(0); if(aLeftEntry.isEmpty() && aRightEntry.isEmpty()) { - if(IsPageEntry(m_xWndCenter->GetEditEngine(), pCenterObj.get())) + if(IsPageEntry(m_xWndCenter->GetEditEngine(), &aCenterObj)) { eSelectEntry = ePageEntry; bFound = true; @@ -360,13 +393,13 @@ void ScHFEditPage::SetSelectDefinedList() case eSheetEntry: { - aLeftEntry = pLeftObj->GetText(0); - aRightEntry = pRightObj->GetText(0); + aLeftEntry = aLeftObj.GetText(0); + aRightEntry = aRightObj.GetText(0); if(aLeftEntry.isEmpty() && aRightEntry.isEmpty()) { - if(pCenterObj->IsFieldObject()) + if(aCenterObj.IsFieldObject()) { - const SvxFieldItem* pFieldItem = pCenterObj->GetField(); + const SvxFieldItem* pFieldItem = aCenterObj.GetField(); if(pFieldItem) { const SvxFieldData* pField = pFieldItem->GetField(); @@ -383,7 +416,7 @@ void ScHFEditPage::SetSelectDefinedList() case eConfidentialEntry: { - if(IsDateEntry(pCenterObj.get()) && IsPageEntry(m_xWndRight->GetEditEngine(), pRightObj.get())) + if(IsDateEntry(&aCenterObj) && IsPageEntry(m_xWndRight->GetEditEngine(), &aRightObj)) { OUString aConfidentialEntry(aUserOpt.GetCompany() + " " + m_xFtConfidential->get_label()); if(aConfidentialEntry == m_xWndLeft->GetEditEngine()->GetText(0)) @@ -403,9 +436,9 @@ void ScHFEditPage::SetSelectDefinedList() case eExtFileNameEntry: { - aLeftEntry = pLeftObj->GetText(0); - aRightEntry = pRightObj->GetText(0); - if(IsExtFileNameEntry(pCenterObj.get()) && aLeftEntry.isEmpty() + aLeftEntry = aLeftObj.GetText(0); + aRightEntry = aRightObj.GetText(0); + if(IsExtFileNameEntry(&aCenterObj) && aLeftEntry.isEmpty() && aRightEntry.isEmpty()) { eSelectEntry = eExtFileNameEntry; @@ -428,9 +461,9 @@ void ScHFEditPage::SetSelectDefinedList() case ePageExtFileNameEntry: { - aLeftEntry = pLeftObj->GetText(0); - if(IsPageEntry(m_xWndCenter->GetEditEngine(), pCenterObj.get()) && - IsExtFileNameEntry(pRightObj.get()) && aLeftEntry.isEmpty()) + aLeftEntry = aLeftObj.GetText(0); + if(IsPageEntry(m_xWndCenter->GetEditEngine(), &aCenterObj) && + IsExtFileNameEntry(&aRightObj) && aLeftEntry.isEmpty()) { eSelectEntry = ePageExtFileNameEntry; bFound = true; @@ -440,7 +473,7 @@ void ScHFEditPage::SetSelectDefinedList() case eUserNameEntry: { - if(IsDateEntry(pRightObj.get()) && IsPageEntry(m_xWndCenter->GetEditEngine(), pCenterObj.get())) + if(IsDateEntry(&aRightObj) && IsPageEntry(m_xWndCenter->GetEditEngine(), &aCenterObj)) { OUString aUserNameEntry(aUserOpt.GetFirstName() + " " + aUserOpt.GetLastName()); @@ -455,7 +488,7 @@ void ScHFEditPage::SetSelectDefinedList() case eCreatedByEntry: { - if(IsDateEntry(pCenterObj.get()) && IsPageEntry(m_xWndRight->GetEditEngine(), pRightObj.get())) + if(IsDateEntry(&aCenterObj) && IsPageEntry(m_xWndRight->GetEditEngine(), &aRightObj)) { OUString aCreatedByEntry(m_xFtCreatedBy->get_label() + " " + aUserOpt.GetFirstName() + " " + aUserOpt.GetLastName()); @@ -501,10 +534,10 @@ bool ScHFEditPage::IsPageEntry(EditEngine*pEngine, const EditTextObject* pTextOb { aSel.start.nIndex = aSel.end.nIndex; aSel.end.nIndex++; - std::unique_ptr< EditTextObject > pPageObj = pEngine->CreateTextObject(aSel); - if(pPageObj && pPageObj->IsFieldObject() ) + EditTextObject aPageObj = pEngine->CreateTextObject(aSel); + if(aPageObj.IsFieldObject() ) { - const SvxFieldItem* pFieldItem = pPageObj->GetField(); + const SvxFieldItem* pFieldItem = aPageObj.GetField(); if(pFieldItem) { const SvxFieldData* pField = pFieldItem->GetField(); @@ -558,7 +591,6 @@ bool ScHFEditPage::IsExtFileNameEntry(const EditTextObject* pTextObj) void ScHFEditPage::ProcessDefinedListSel(ScHFEntryId eSel, bool bTravelling) { SvtUserOptions aUserOpt; - std::unique_ptr< EditTextObject > pTextObj; switch(eSel) { @@ -593,8 +625,7 @@ void ScHFEditPage::ProcessDefinedListSel(ScHFEntryId eSel, bool bTravelling) m_xWndCenter->GetEditEngine()->QuickInsertText(aPageOfEntry,ESelection(aSel.end)); aSel.end.nIndex += aPageOfEntry.getLength(); m_xWndCenter->GetEditEngine()->QuickInsertField(SvxFieldItem(SvxPagesField(), EE_FEATURE_FIELD), ESelection(aSel.end)); - pTextObj = m_xWndCenter->GetEditEngine()->CreateTextObject(); - m_xWndCenter->SetText(*pTextObj); + m_xWndCenter->SetText(m_xWndCenter->GetEditEngine()->CreateTextObject()); if(!bTravelling) m_xWndCenter->GrabFocus(); } @@ -633,8 +664,7 @@ void ScHFEditPage::ProcessDefinedListSel(ScHFEntryId eSel, bool bTravelling) aSel.start.nIndex = aSel.end.nIndex; aSel.end.nIndex += aPageEntry.getLength(); m_xWndCenter->GetEditEngine()->QuickInsertField(SvxFieldItem(SvxPageField(), EE_FEATURE_FIELD), ESelection(aSel.end)); - pTextObj = m_xWndCenter->GetEditEngine()->CreateTextObject(); - m_xWndCenter->SetText(*pTextObj); + m_xWndCenter->SetText(m_xWndCenter->GetEditEngine()->CreateTextObject()); if(!bTravelling) m_xWndCenter->GrabFocus(); } @@ -662,8 +692,7 @@ void ScHFEditPage::ProcessDefinedListSel(ScHFEntryId eSel, bool bTravelling) m_xWndCenter->GetEditEngine()->QuickInsertText(aCommaSpace,ESelection(aSel.end)); aSel.end.nIndex += aCommaSpace.getLength(); m_xWndCenter->GetEditEngine()->QuickInsertField( SvxFieldItem(SvxTableField(), EE_FEATURE_FIELD), ESelection(aSel.end)); - pTextObj = m_xWndCenter->GetEditEngine()->CreateTextObject(); - m_xWndCenter->SetText(*pTextObj); + m_xWndCenter->SetText(m_xWndCenter->GetEditEngine()->CreateTextObject()); if(!bTravelling) m_xWndCenter->GrabFocus(); } @@ -682,8 +711,7 @@ void ScHFEditPage::ProcessDefinedListSel(ScHFEntryId eSel, bool bTravelling) m_xWndCenter->GetEditEngine()->QuickInsertText(aCommaSpace,ESelection(aSel.end)); aSel.end.nIndex += aCommaSpace.getLength(); m_xWndCenter->GetEditEngine()->QuickInsertField( SvxFieldItem(SvxFileField(), EE_FEATURE_FIELD), ESelection(aSel.end)); - pTextObj = m_xWndCenter->GetEditEngine()->CreateTextObject(); - m_xWndCenter->SetText(*pTextObj); + m_xWndCenter->SetText(m_xWndCenter->GetEditEngine()->CreateTextObject()); if(!bTravelling) m_xWndCenter->GrabFocus(); } @@ -750,17 +778,17 @@ void ScHFEditPage::UpdateFontAttributes() { const SfxItemSet aSet = m_pEditFocus->GetEditView()->GetAttribs(); - const SvxFontItem* pFontItem = aSet.GetItemIfSet( EE_CHAR_FONTINFO ); - const SvxFontHeightItem* pFontHeightItem = aSet.GetItemIfSet( EE_CHAR_FONTHEIGHT ); - const SvxWeightItem* pWeightItem = aSet.GetItemIfSet( EE_CHAR_WEIGHT ); - const SvxUnderlineItem* pUnderlineItem = aSet.GetItemIfSet( EE_CHAR_UNDERLINE ); - const SvxPostureItem* pItalicItem = aSet.GetItemIfSet( EE_CHAR_ITALIC ); + if (const SvxFontItem* pFontItem = aSet.GetItemIfSet( EE_CHAR_FONTINFO )) + m_xLbFontFamily->set_active_text(pFontItem->GetFamilyName()); + if (const SvxFontHeightItem* pFontHeightItem = aSet.GetItemIfSet( EE_CHAR_FONTHEIGHT )) + m_xLbFontHeight->set_active_text(OUString::number(pFontHeightItem->GetHeight() / 20)); + if (const SvxWeightItem* pWeightItem = aSet.GetItemIfSet( EE_CHAR_WEIGHT )) + m_xBtnBold->set_active(pWeightItem->GetValue() == WEIGHT_BOLD); + if (const SvxUnderlineItem* pUnderlineItem = aSet.GetItemIfSet( EE_CHAR_UNDERLINE )) + m_xBtnUnderline->set_active(pUnderlineItem->GetValue() != LINESTYLE_NONE); + if (const SvxPostureItem* pItalicItem = aSet.GetItemIfSet( EE_CHAR_ITALIC )) + m_xBtnItalic->set_active(pItalicItem->GetValue() == ITALIC_NORMAL); - m_xLbFontFamily->set_active_text(pFontItem->GetFamilyName()); - m_xLbFontHeight->set_active_text(OUString::number(pFontHeightItem->GetHeight() / 20)); - if (pWeightItem) m_xBtnBold->set_active(pWeightItem->GetValue() == WEIGHT_BOLD); - if (pItalicItem) m_xBtnItalic->set_active(pItalicItem->GetValue() == ITALIC_NORMAL); - if (pUnderlineItem) m_xBtnUnderline->set_active(pUnderlineItem->GetValue() != LINESTYLE_NONE); } // Handler: @@ -818,6 +846,32 @@ IMPL_LINK_NOARG( ScHFEditPage, FontFamilyListHdl, weld::ComboBox&, void) m_pEditFocus->GrabFocus(); } +IMPL_LINK_NOARG( ScHFEditPage, ToggleEnableHdl, weld::Toggleable&, void ) +{ + bool bActive = m_xEnableHF->get_active(); + + m_xLbDefined->set_sensitive( bActive ); + m_xLbFontFamily->set_sensitive( bActive ); + m_xLbFontHeight->set_sensitive( bActive ); + m_xBtnBold->set_sensitive( bActive ); + m_xBtnItalic->set_sensitive( bActive ); + m_xBtnUnderline->set_sensitive( bActive ); + + m_xBtnText->set_sensitive( bActive ); + m_xBtnFile->set_sensitive( bActive ); + m_xBtnTable->set_sensitive( bActive ); + m_xBtnPage->set_sensitive( bActive ); + m_xBtnLastPage->set_sensitive( bActive ); + m_xBtnDate->set_sensitive( bActive ); + m_xBtnTime->set_sensitive( bActive ); + + m_xWndLeftWnd->set_sensitive( bActive ); + m_xWndCenterWnd->set_sensitive( bActive ); + m_xWndRightWnd->set_sensitive( bActive ); + m_xLeft->set_sensitive( bActive ); + m_xRight->set_sensitive( bActive ); +} + IMPL_LINK( ScHFEditPage, ClickHdl, weld::Button&, rBtn, void ) { if (!m_pEditFocus) diff --git a/sc/source/ui/pagedlg/tphfedit.cxx b/sc/source/ui/pagedlg/tphfedit.cxx index f69c790c19ff..b86f937ffafd 100644 --- a/sc/source/ui/pagedlg/tphfedit.cxx +++ b/sc/source/ui/pagedlg/tphfedit.cxx @@ -129,7 +129,7 @@ void ScEditWindow::SetNumType(SvxNumType eNumType) pEditEngine->UpdateFields(); } -std::unique_ptr ScEditWindow::CreateTextObject() +EditTextObject ScEditWindow::CreateTextObject() { // reset paragraph attributes // (GetAttribs at creation of format dialog always returns the set items) diff --git a/sc/source/ui/sidebar/AlignmentPropertyPanel.hxx b/sc/source/ui/sidebar/AlignmentPropertyPanel.hxx index 666c2fa82967..bffe325a6e4b 100644 --- a/sc/source/ui/sidebar/AlignmentPropertyPanel.hxx +++ b/sc/source/ui/sidebar/AlignmentPropertyPanel.hxx @@ -23,7 +23,10 @@ #include #include #include +#include +#include #include +#include #include namespace sc::sidebar { diff --git a/sc/source/ui/sidebar/DatabasePropertyPanel.hxx b/sc/source/ui/sidebar/DatabasePropertyPanel.hxx index a732119360db..cac9f7f6c8db 100644 --- a/sc/source/ui/sidebar/DatabasePropertyPanel.hxx +++ b/sc/source/ui/sidebar/DatabasePropertyPanel.hxx @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace sc::sidebar diff --git a/sc/source/ui/sidebar/NumberFormatPropertyPanel.hxx b/sc/source/ui/sidebar/NumberFormatPropertyPanel.hxx index b9abfab7ed29..1b972d8c8c77 100644 --- a/sc/source/ui/sidebar/NumberFormatPropertyPanel.hxx +++ b/sc/source/ui/sidebar/NumberFormatPropertyPanel.hxx @@ -23,7 +23,9 @@ #include #include #include +#include #include +#include #include #include diff --git a/sc/source/ui/sidebar/ScPanelFactory.cxx b/sc/source/ui/sidebar/ScPanelFactory.cxx index 8982eaffe7e6..05399d560a6d 100644 --- a/sc/source/ui/sidebar/ScPanelFactory.cxx +++ b/sc/source/ui/sidebar/ScPanelFactory.cxx @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include @@ -87,7 +87,7 @@ Reference SAL_CALL ScPanelFactory::createUIElement ( xPanel = NumberFormatPropertyPanel::Create( pParent, xFrame, pBindings ); else if (rsResourceURL.endsWith("/NavigatorPanel")) { - xPanel = std::make_unique(pBindings, pParent, nullptr); + xPanel = std::make_unique(*pBindings, pParent, nullptr); nMinimumSize = 0; } else if (rsResourceURL.endsWith("/FunctionsPanel")) diff --git a/sc/source/ui/styleui/styledlg.cxx b/sc/source/ui/styleui/styledlg.cxx index bccc706c5374..f56ebc40a365 100644 --- a/sc/source/ui/styleui/styledlg.cxx +++ b/sc/source/ui/styleui/styledlg.cxx @@ -20,6 +20,7 @@ #undef SC_DLLIMPLEMENTATION #include +#include #include #include #include @@ -37,7 +38,6 @@ #include #include #include -#include #include @@ -135,7 +135,9 @@ void ScStyleDlg::PageCreated(const OUString& rPageId, SfxTabPage& rTabPage) assert(pInfoItem && "FontListItem not found!"); - aSet.Put (SvxFontListItem(pInfoItem->GetFontList(), SID_ATTR_CHAR_FONTLIST)); + aSet.Put(SvxFontListItem(pInfoItem->GetFontList(), SID_ATTR_CHAR_FONTLIST)); + if (rTabPage.GetItemSet().GetParent()) + aSet.Put(SfxUInt32Item(SID_FLAG_TYPE, SVX_RELATIVE_MODE)); rTabPage.PageCreated(aSet); } else if (rPageId == "background") diff --git a/sc/source/ui/theme/ThemeColorChanger.cxx b/sc/source/ui/theme/ThemeColorChanger.cxx index 983cfa77adf4..d6884735e9fb 100644 --- a/sc/source/ui/theme/ThemeColorChanger.cxx +++ b/sc/source/ui/theme/ThemeColorChanger.cxx @@ -12,6 +12,8 @@ #include +#include +#include #include #include #include @@ -58,6 +60,8 @@ bool changeBorderLine(editeng::SvxBorderLine* pBorderLine, model::ColorSet const if (rComplexColor.isValidThemeType()) { Color aColor = rColorSet.resolveColor(rComplexColor); + if (aColor == pBorderLine->GetColor()) + return false; pBorderLine->SetColor(aColor); return true; } @@ -75,11 +79,13 @@ bool changeCellItems(SfxItemSet& rItemSet, model::ColorSet const& rColorSet) if (rComplexColor.isValidThemeType()) { Color aColor = rColorSet.resolveColor(rComplexColor); - - SvxColorItem aColorItem(*pColorItem); - aColorItem.setColor(aColor); - rItemSet.Put(aColorItem); - bChanged = true; + if (aColor != pColorItem->getColor()) + { + SvxColorItem aColorItem(*pColorItem); + aColorItem.setColor(aColor); + rItemSet.Put(aColorItem); + bChanged = true; + } } } if (rItemSet.HasItem(ATTR_BACKGROUND, &pItem)) @@ -89,11 +95,13 @@ bool changeCellItems(SfxItemSet& rItemSet, model::ColorSet const& rColorSet) if (rComplexColor.isValidThemeType()) { Color aColor = rColorSet.resolveColor(rComplexColor); - - SvxBrushItem aNewBrushItem(*pBrushItem); - aNewBrushItem.SetColor(aColor); - rItemSet.Put(aNewBrushItem); - bChanged = true; + if (aColor != pBrushItem->GetColor()) + { + SvxBrushItem aNewBrushItem(*pBrushItem); + aNewBrushItem.SetColor(aColor); + rItemSet.Put(aNewBrushItem); + bChanged = true; + } } } if (rItemSet.HasItem(ATTR_BORDER, &pItem)) @@ -310,7 +318,7 @@ void changeThemeColorInTheDocModel(ScDocShell& rDocShell, } // end anonymous ns -void ThemeColorChanger::doApply(std::shared_ptr const& pColorSet) +void ThemeColorChanger::apply(std::shared_ptr const& pColorSet) { // Can't change to an empty color set if (!pColorSet) @@ -343,6 +351,9 @@ void ThemeColorChanger::doApply(std::shared_ptr const& pColorSe changeSparklines(m_rDocShell, *pColorSet); changeThemeColorInTheDocModel(m_rDocShell, pColorSet); + ScTableStyleGenerator::generateDefaultStyles(rDocument, *pColorSet); + if (ScTableStyles* pStyles = rDocument.GetTableStyles()) + pStyles->UpdateCustomStyleThemedColors(*pColorSet); m_rDocShell.Broadcast(SfxHint(SfxHintId::ThemeColorsChanged)); if (bUndo) diff --git a/sc/source/ui/undo/UndoDeleteSparkline.cxx b/sc/source/ui/undo/UndoDeleteSparkline.cxx index 2744a439eb4b..1d02da0c6028 100644 --- a/sc/source/ui/undo/UndoDeleteSparkline.cxx +++ b/sc/source/ui/undo/UndoDeleteSparkline.cxx @@ -56,7 +56,7 @@ void UndoDeleteSparkline::Redo() } else { - SAL_WARN("sc", "Can't delete a sparkline that donesn't exist."); + SAL_WARN("sc", "Can't delete a sparkline that doesn't exist."); } rDocShell.PostPaintCell(maSparklinePosition); diff --git a/sc/source/ui/undo/UndoInsertSheetView.cxx b/sc/source/ui/undo/UndoInsertSheetView.cxx new file mode 100644 index 000000000000..5fedcc5e1195 --- /dev/null +++ b/sc/source/ui/undo/UndoInsertSheetView.cxx @@ -0,0 +1,84 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#include + +namespace sc +{ +UndoInsertSheetView::UndoInsertSheetView(ScDocShell& rNewDocShell, SCTAB nTab, SCTAB nSheetViewTab, + SheetViewID nSheetViewID) + : ScSimpleUndo(rNewDocShell) + , mnTab(nTab) + , mnSheetViewTab(nSheetViewTab) + , mnSheetViewID(nSheetViewID) +{ + mpDrawUndo = GetSdrUndoAction(&rNewDocShell.GetDocument()); +} + +UndoInsertSheetView::~UndoInsertSheetView() = default; + +OUString UndoInsertSheetView::GetComment() const { return ScResId(STR_UNDO_INSERT_SHEET_VIEW); } + +void UndoInsertSheetView::Undo() +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (!pViewShell) + return; + + // Switch back to the default tab first + pViewShell->SetTabNo(mnTab); + + rDocShell.SetInUndo(true); + bDrawIsInUndo = true; + pViewShell->DeleteTable(mnSheetViewTab, false); + bDrawIsInUndo = false; + rDocShell.SetInUndo(false); + + DoSdrUndoAction(mpDrawUndo.get(), &rDocShell.GetDocument()); + + rDocShell.Broadcast(SfxHint(SfxHintId::ScForceSetTab)); +} + +void UndoInsertSheetView::Redo() +{ + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (!pViewShell) + return; + + RedoSdrUndoAction(mpDrawUndo.get()); + + rDocShell.SetInUndo(true); + bDrawIsInUndo = true; + + ScDocument& rDoc = rDocShell.GetDocument(); + auto[nNewID, nNewTab] = rDoc.CreateNewSheetView(mnTab); + if (nNewID != InvalidSheetViewID) + { + mnSheetViewID = nNewID; + mnSheetViewTab = nNewTab; + pViewShell->SetTabNo(mnSheetViewTab); + } + + bDrawIsInUndo = false; + rDocShell.SetInUndo(false); +} + +void UndoInsertSheetView::Repeat(SfxRepeatTarget& /*rTarget*/) {} + +bool UndoInsertSheetView::CanRepeat(SfxRepeatTarget& /*rTarget*/) const { return false; } + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/UndoSheetViewSortData.cxx b/sc/source/ui/undo/UndoSheetViewSortData.cxx new file mode 100644 index 000000000000..e1cc36066f1d --- /dev/null +++ b/sc/source/ui/undo/UndoSheetViewSortData.cxx @@ -0,0 +1,86 @@ +/* -*- 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 +#include +#include +#include + +namespace sc +{ +void UndoSheetViewSortData::setSheetViewContext(SCTAB nDefaultViewTab, SheetViewID nSheetViewID, + std::shared_ptr pBefore, + std::shared_ptr pAfter) +{ + mnDefaultViewTab = nDefaultViewTab; + mnSheetViewID = nSheetViewID; + mpSheetViewSortDataBefore = std::move(pBefore); + mpSheetViewSortDataAfter = std::move(pAfter); +} + +void UndoSheetViewSortData::setDefaultViewContext(SCTAB nDefaultViewTab, + std::shared_ptr pBefore, + std::shared_ptr pAfter) +{ + mnDefaultViewTab = nDefaultViewTab; + mpDefaultViewSortDataBefore = std::move(pBefore); + mpDefaultViewSortDataAfter = std::move(pAfter); +} + +void UndoSheetViewSortData::setAutoFilterRange(ScRange const& rBefore, ScRange const& rAfter) +{ + moAutoFilterRangeBefore = rBefore; + moAutoFilterRangeAfter = rAfter; +} + +void UndoSheetViewSortData::restore(ScDocShell& rDocShell, bool bUndo) const +{ + if (mnDefaultViewTab < 0) + return; + + ScDocument& rDocument = rDocShell.GetDocument(); + + // Restore sheet view sort data + if (mnSheetViewID >= 0) + { + std::shared_ptr pManager + = rDocument.GetSheetViewManager(mnDefaultViewTab); + if (pManager) + { + std::shared_ptr pSheetView = pManager->get(mnSheetViewID); + if (pSheetView) + pSheetView->restoreSortData(bUndo ? mpSheetViewSortDataBefore + : mpSheetViewSortDataAfter); + } + } + + // Restore manager (default view) sort data + if (mpDefaultViewSortDataBefore || mpDefaultViewSortDataAfter) + { + std::shared_ptr pManager + = rDocument.GetSheetViewManager(mnDefaultViewTab); + if (pManager) + pManager->restoreSortData(bUndo ? mpDefaultViewSortDataBefore + : mpDefaultViewSortDataAfter); + } + + // Restore auto-filter DB range + if (moAutoFilterRangeBefore || moAutoFilterRangeAfter) + { + ScDBData* pDBData = rDocument.GetAnonymousDBData(mnDefaultViewTab); + if (pDBData) + { + ScRange const& rRange = bUndo ? *moAutoFilterRangeBefore : *moAutoFilterRangeAfter; + pDBData->SetArea(rRange); + } + } +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/UndoSpillPivotTable.cxx b/sc/source/ui/undo/UndoSpillPivotTable.cxx new file mode 100644 index 000000000000..16a8fd9d02ed --- /dev/null +++ b/sc/source/ui/undo/UndoSpillPivotTable.cxx @@ -0,0 +1,81 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#include + +namespace sc +{ +UndoSpillPivotTable::UndoSpillPivotTable(ScDocShell& rNewDocShell, const OUString& rDPName, + const ScRange& rOutputRange) + : ScSimpleUndo(rNewDocShell) + , maDPName(rDPName) + , maOutputRange(rOutputRange) +{ +} + +OUString UndoSpillPivotTable::GetComment() const { return ScResId(STR_UNDO_PIVOT_MODIFY); } + +void UndoSpillPivotTable::Undo() +{ + // Undo: go from rendered pivot table back to #SPILL! state. + BeginUndo(); + + ScDocument& rDocument = rDocShell.GetDocument(); + ScDPObject* pDPObject = rDocument.GetDPCollection()->GetByName(maDPName); + if (pDPObject) + { + // Clear the rendered output. + rDocument.DeleteAreaTab(maOutputRange, InsertDeleteFlags::ALL); + rDocument.RemoveFlagsTab(maOutputRange.aStart.Col(), maOutputRange.aStart.Row(), + maOutputRange.aEnd.Col(), maOutputRange.aEnd.Row(), + maOutputRange.aStart.Tab(), ScMF::Auto); + + // Write #SPILL! into the origin cell. + ScAddress aOrigin = maOutputRange.aStart; + rDocument.SetError(aOrigin.Col(), aOrigin.Row(), aOrigin.Tab(), FormulaError::Spill); + pDPObject->SetOutRange(ScRange(aOrigin)); + pDPObject->SetSpillError(true); + + rDocShell.PostPaint(maOutputRange, PaintPartFlags::Grid); + } + + EndUndo(); +} + +void UndoSpillPivotTable::Redo() +{ + // Redo: resolve the spill and render the pivot table. + BeginRedo(); + + ScDocument& rDocument = rDocShell.GetDocument(); + ScDPObject* pDPObject = rDocument.GetDPCollection()->GetByName(maDPName); + if (pDPObject) + { + ScAddress aOrigin = pDPObject->GetOutRange().aStart; + pDPObject->InvalidateData(); + pDPObject->Output(aOrigin, true); + rDocShell.PostPaintGridAll(); + } + + EndRedo(); +} + +void UndoSpillPivotTable::Repeat(SfxRepeatTarget& /*rTarget*/) {} + +bool UndoSpillPivotTable::CanRepeat(SfxRepeatTarget& /*rTarget*/) const { return false; } + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/UndoThemeChange.cxx b/sc/source/ui/undo/UndoThemeChange.cxx index 3e5d2246d21f..a196cd673926 100644 --- a/sc/source/ui/undo/UndoThemeChange.cxx +++ b/sc/source/ui/undo/UndoThemeChange.cxx @@ -9,8 +9,11 @@ #include #include +#include #include #include +#include +#include namespace sc { @@ -47,6 +50,9 @@ void UndoThemeChange::Undo() auto pTheme = getTheme(rDocShell); pTheme->setColorSet(mpOldColorSet); + ScTableStyleGenerator::generateDefaultStyles(rDocShell.GetDocument(), *mpOldColorSet); + if (ScTableStyles* pStyles = rDocShell.GetDocument().GetTableStyles()) + pStyles->UpdateCustomStyleThemedColors(*mpOldColorSet); EndUndo(); } @@ -57,6 +63,9 @@ void UndoThemeChange::Redo() auto pTheme = getTheme(rDocShell); pTheme->setColorSet(mpNewColorSet); + ScTableStyleGenerator::generateDefaultStyles(rDocShell.GetDocument(), *mpNewColorSet); + if (ScTableStyles* pStyles = rDocShell.GetDocument().GetTableStyles()) + pStyles->UpdateCustomStyleThemedColors(*mpNewColorSet); EndRedo(); } diff --git a/sc/source/ui/undo/refundo.cxx b/sc/source/ui/undo/refundo.cxx index 356d69167a84..125924bd3860 100644 --- a/sc/source/ui/undo/refundo.cxx +++ b/sc/source/ui/undo/refundo.cxx @@ -30,16 +30,20 @@ #include #include -ScRefUndoData::ScRefUndoData( ScDocument& rDoc ) : +ScRefUndoData::ScRefUndoData( ScDocument& rDoc, bool bForceDBSnapshot ) : pPrintRanges(rDoc.CreatePrintRangeSaver()) { + // An empty database-range collection is normally skipped (nothing to + // restore). A caller that may add a range to an empty collection during a + // paste passes bForceDBSnapshot so the empty pre-state stays restorable. + // DeleteUnchanged() drops it again if the operation changed nothing. const ScDBCollection* pOldDBColl = rDoc.GetDBCollection(); - if (pOldDBColl && !pOldDBColl->empty()) + if (pOldDBColl && (bForceDBSnapshot || !pOldDBColl->empty())) pDBCollection.reset(new ScDBCollection(*pOldDBColl)); - const ScRangeName* pOldRanges = rDoc.GetRangeName(); - if (pOldRanges && !pOldRanges->empty()) - pRangeName.reset(new ScRangeName(*pOldRanges)); + const ScRangeName& rOldRanges = rDoc.GetRangeName(); + if (!rOldRanges.empty()) + pRangeName.reset(new ScRangeName(rOldRanges)); // when handling Pivot solely keep the range? @@ -81,8 +85,8 @@ void ScRefUndoData::DeleteUnchanged( ScDocument& rDoc ) } if (pRangeName) { - ScRangeName* pNewRanges = rDoc.GetRangeName(); - if ( pNewRanges && *pRangeName == *pNewRanges ) + ScRangeName& rNewRanges = rDoc.GetRangeName(); + if ( *pRangeName == rNewRanges ) pRangeName.reset(); } diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx index 40c74c61d51c..be4b1f8e796b 100644 --- a/sc/source/ui/undo/undobase.cxx +++ b/sc/source/ui/undo/undobase.cxx @@ -124,6 +124,9 @@ namespace void ScSimpleUndo::EndUndo() { + // After undo we need to restore the sheet views as well. + SyncSheetViews(); + { // rhbz#1352881 Temporarily turn off undo generation during // SetDocumentModified @@ -156,6 +159,9 @@ void ScSimpleUndo::EndRedo() if (pDetectiveUndo) pDetectiveUndo->Redo(); + // After redo we need to restore the sheet views as well. + SyncSheetViews(); + { // rhbz#1352881 Temporarily turn off undo generation during // SetDocumentModified @@ -174,6 +180,17 @@ void ScSimpleUndo::EndRedo() rDocShell.SetInUndo( false ); } +void ScSimpleUndo::SyncSheetViews() +{ + ScViewData* pViewData = ScDocShell::GetViewData(); + if (!pViewData) + return; + + ScDocument& rDocument = rDocShell.GetDocument(); + SCTAB nDefaultViewTable = rDocument.GetDefaultViewTableNumber(pViewData->GetTabNumber()); + rDocument.SyncSheetViews(nDefaultViewTable); +} + void ScSimpleUndo::BroadcastChanges( const ScRange& rRange ) { ScDocument& rDoc = rDocShell.GetDocument(); @@ -235,7 +252,7 @@ void ScSimpleUndo::ShowTable( const ScRange& rRange ) { SCTAB nStart = rRange.aStart.Tab(); SCTAB nEnd = rRange.aEnd.Tab(); - SCTAB nTab = pViewShell->GetViewData().CurrentTabForData(); + SCTAB nTab = pViewShell->GetViewData().GetTabNumber(); if ( nTab < nStart || nTab > nEnd ) // if not in range: pViewShell->SetTabNo( nStart ); // at beginning of the range } @@ -346,7 +363,7 @@ void ScBlockUndo::ShowBlock() ShowTable( aBlockRange ); // with multiple sheets in range each of them is good pViewShell->MoveCursorAbs( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(), SC_FOLLOW_JUMP, false, false ); - SCTAB nTab = pViewShell->GetViewData().CurrentTabForData(); + SCTAB nTab = pViewShell->GetViewData().GetTabNumber(); ScRange aRange = aBlockRange; aRange.aStart.SetTab( nTab ); aRange.aEnd.SetTab( nTab ); @@ -406,7 +423,7 @@ void ScMultiBlockUndo::ShowBlock() ShowTable(aRange); pViewShell->MoveCursorAbs( aRange.aStart.Col(), aRange.aStart.Row(), SC_FOLLOW_JUMP, false, false); - SCTAB nTab = pViewShell->GetViewData().CurrentTabForData(); + SCTAB nTab = pViewShell->GetViewData().GetTabNumber(); aRange.aStart.SetTab(nTab); aRange.aEnd.SetTab(nTab); pViewShell->MarkRange(aRange, false); diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx index 0e382bb7d0ed..59ab2e542fd0 100644 --- a/sc/source/ui/undo/undoblk.cxx +++ b/sc/source/ui/undo/undoblk.cxx @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -63,6 +65,22 @@ /*C*/ // ScArea //? // check later +namespace +{ +/** Refresh the header row to update ScMF::Auto flags. */ +void refreshAutoFilterForColumnChange(ScDocument& rDocument, SCTAB nTab) +{ + ScDBData* pDBData = rDocument.GetAnonymousDBData(nTab); + if (!pDBData || !pDBData->HasAutoFilter()) + return; + + ScRange aRange; + pDBData->GetArea(aRange); + // Scan the full header row as stale flags may be outside the range. + rDocument.RefreshAutoFilter(0, aRange.aStart.Row(), rDocument.MaxCol(), aRange.aStart.Row(), nTab); +} +} // end anonymous namespace + ScUndoInsertCells::ScUndoInsertCells( ScDocShell& rNewDocShell, const ScRange& rRange, SCTAB nNewCount, std::unique_ptr pNewTabs, std::unique_ptr pNewScenarios, @@ -115,7 +133,7 @@ bool ScUndoInsertCells::Merge( SfxUndoAction* pNextAction ) // Store paste action if this is part of paste with inserting cells. // A list action isn't used because Repeat wouldn't work (insert wrong cells). - // Pass ownership of the wrapped SfxUndoAction* to pPasteUndO + // Pass ownership of the wrapped SfxUndoAction* to pPasteUndo pPasteUndo = pWrapper->ReleaseWrappedUndo(); return true; } @@ -188,6 +206,8 @@ void ScUndoInsertCells::DoChange( const bool bUndo ) rDoc.InsertCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i], aEffRange.aStart.Col(), static_cast(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1)); + refreshAutoFilterForColumnChange(rDoc, pTabs[i]); + if (pViewShell) { const tools::Long nSign = bUndo ? -1 : 1; @@ -299,6 +319,9 @@ void ScUndoInsertCells::Undo() weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); // important due to TrackFormulas in UpdateReference BeginUndo(); DoChange( true ); + + sc::UndoSheetViewSortData::restore(rDocShell, true); + EndUndo(); ScDocument& rDoc = rDocShell.GetDocument(); @@ -311,6 +334,9 @@ void ScUndoInsertCells::Redo() weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); // important due to TrackFormulas in UpdateReference BeginRedo(); DoChange( false ); + + sc::UndoSheetViewSortData::restore(rDocShell, false); + EndRedo(); if ( pPasteUndo ) @@ -455,6 +481,13 @@ void ScUndoDeleteCells::DoChange( const bool bUndo ) InsertDeleteFlags::ALL | InsertDeleteFlags::NOCAPTIONS, false, rDoc); } + // Refresh after all cell operations are done. + if (eCmd == DelCellCmd::Cols || eCmd == DelCellCmd::CellsLeft) + { + for (i = 0; i < nCount; i++) + refreshAutoFilterForColumnChange(rDoc, pTabs[i]); + } + ScRange aWorkRange( aEffRange ); if ( eCmd == DelCellCmd::CellsLeft ) // only "shift left" requires refresh of the moved area aWorkRange.aEnd.SetCol(rDoc.MaxCol()); @@ -568,6 +601,9 @@ void ScUndoDeleteCells::Undo() weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); // important because of TrackFormulas in UpdateReference BeginUndo(); DoChange( true ); + + sc::UndoSheetViewSortData::restore(rDocShell, true); + EndUndo(); ScDocument& rDoc = rDocShell.GetDocument(); @@ -604,6 +640,9 @@ void ScUndoDeleteCells::Redo() weld::WaitObject aWait( ScDocShell::GetActiveDialogParent() ); // important because of TrackFormulas in UpdateReference BeginRedo(); DoChange( false); + + sc::UndoSheetViewSortData::restore(rDocShell, false); + EndRedo(); ScDocument& rDoc = rDocShell.GetDocument(); @@ -1396,15 +1435,14 @@ void ScUndoDragDrop::Undo() aCxt.mnTabDelta = nTabDelta; // Global range names. - ScRangeName* pName = rDoc.GetRangeName(); - if (pName) - pName->UpdateReference(aCxt); + ScRangeName& rName = rDoc.GetRangeName(); + rName.UpdateReference(aCxt); SCTAB nTabCount = rDoc.GetTableCount(); for (SCTAB nTab = 0; nTab < nTabCount; ++nTab) { // Sheet-local range names. - pName = rDoc.GetRangeName(nTab); + ScRangeName* pName = rDoc.GetRangeName(nTab); if (pName) pName->UpdateReference(aCxt, nTab); } @@ -1980,11 +2018,13 @@ bool ScUndoSelectionStyle::CanRepeat(SfxRepeatTarget& rTarget) const ScUndoEnterMatrix::ScUndoEnterMatrix( ScDocShell& rNewDocShell, const ScRange& rArea, ScDocumentUniquePtr pNewUndoDoc, OUString aForm, - std::unique_ptr pArray ) : + std::unique_ptr pArray, + bool bDynamicArrayMaster) : ScBlockUndo( rNewDocShell, rArea, SC_UNDO_SIMPLE ), pUndoDoc( std::move(pNewUndoDoc) ), aFormula(std::move( aForm )), - pTokenArray(std::move( pArray )) + pTokenArray(std::move(pArray)), + mbDynamicArrayMaster(bDynamicArrayMaster) { SetChangeTrack(); } @@ -2042,7 +2082,9 @@ void ScUndoEnterMatrix::Redo() rDoc.InsertMatrixFormula( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(), aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), - aDestMark, aFormula, pTokenArray.get() ); + aDestMark, aFormula, pTokenArray.get(), + formula::FormulaGrammar::GRAM_DEFAULT, + mbDynamicArrayMaster); SetChangeTrack(); diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx index 2dc2448528ea..8b2ffbcc7909 100644 --- a/sc/source/ui/undo/undoblk3.cxx +++ b/sc/source/ui/undo/undoblk3.cxx @@ -93,6 +93,11 @@ void ScUndoDeleteContents::SetDataSpans( const std::shared_ptr& p mpDataSpans = pSpans; } +void ScUndoDeleteContents::SetRestoreExpandedMatrices(std::vector const& rPositions) +{ + maRestoreExpandedMatrices = rPositions; +} + void ScUndoDeleteContents::SetChangeTrack() { ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack(); @@ -132,6 +137,11 @@ void ScUndoDeleteContents::DoChange( const bool bUndo ) pUndoDoc->CopyToDocument(aCopyRange, nUndoFlags, bMulti, rDoc, &aMarkData); + // Restore the document-level matrix tracking. Re-add any multi-cell + // matrix masters captured before the delete. + for (const ScAddress& rPosition : maRestoreExpandedMatrices) + rDoc.MarkExpandedDynamicArray(rPosition); + DoSdrUndoAction( pDrawUndo.get(), &rDoc ); ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack(); @@ -180,6 +190,11 @@ void ScUndoDeleteContents::Undo() DoChange( true ); EndUndo(); + // Need to replay spill resolution so an undo that restored a blocker + // re-spills the affected dynamic array master, and an undo that cleared + // a blocker expands it. + rDocShell.ResolveSpilledOutputs(); + HelperNotifyChanges::NotifyIfChangesListeners(rDocShell, aRange, u"undo"_ustr); } @@ -189,6 +204,8 @@ void ScUndoDeleteContents::Redo() DoChange( false ); EndRedo(); + rDocShell.ResolveSpilledOutputs(); + HelperNotifyChanges::NotifyIfChangesListeners(rDocShell, aRange, u"redo"_ustr); } diff --git a/sc/source/ui/undo/undocell.cxx b/sc/source/ui/undo/undocell.cxx index a17110edcdcb..91d63dcad362 100644 --- a/sc/source/ui/undo/undocell.cxx +++ b/sc/source/ui/undo/undocell.cxx @@ -199,7 +199,11 @@ void ScUndoEnterData::DoChange() const pViewShell, false /* bColumns */, true /* bRows */, true /* bSizes*/, false /* bHidden */, false /* bFiltered */, false /* bGroups */, maPos.Tab()); } - pViewShell->SetTabNo(maPos.Tab()); + // Don't switch tabs if the current view is a sheet view. + SCTAB nCurrentTab = pViewShell->GetViewData().GetTabNumber(); + ScDocument& rDocument = rDocShell.GetDocument(); + if (rDocument.GetDefaultViewTableNumber(nCurrentTab) != maPos.Tab()) + pViewShell->SetTabNo(maPos.Tab()); pViewShell->MoveCursorAbs(maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false); } @@ -258,7 +262,17 @@ void ScUndoEnterData::Undo() if ( pChangeTrack && mnEndChangeAction >= sal::static_int_cast(nCount) ) pChangeTrack->Undo( mnEndChangeAction - nCount + 1, mnEndChangeAction ); + sc::UndoSheetViewSortData::restore(rDocShell, true); + rDoc.SyncSheetViews(maPos.Tab()); + DoChange(); + + // Forward path ran spill resolution at the end of the write operation. + // Replay it so a dynamic array master that collapsed, because the user + // typed a blocker into one of its reference cells, re-expands now that + // the blocker is gone (and vice-versa). + rDocShell.ResolveSpilledOutputs(); + EndUndo(); HelperNotifyChanges::NotifyIfChangesListeners(rDocShell, maPos, maOldValues, u"undo"_ustr); @@ -287,7 +301,13 @@ void ScUndoEnterData::Redo() SetChangeTrack(); + sc::UndoSheetViewSortData::restore(rDocShell, false); + rDoc.SyncSheetViews(maPos.Tab()); + DoChange(); + + rDocShell.ResolveSpilledOutputs(); + EndRedo(); HelperNotifyChanges::NotifyIfChangesListeners(rDocShell, maPos, maOldValues, u"redo"_ustr); @@ -403,6 +423,12 @@ void ScUndoSetCell::Undo() if (pChangeTrack) pChangeTrack->Undo(mnEndChangeAction, mnEndChangeAction); + sc::UndoSheetViewSortData::restore(rDocShell, true); + + // Replay the resolution so dynamic array masters that should re-spill + // or re-expand after the value change are reconciled. + rDocShell.ResolveSpilledOutputs(); + EndUndo(); } @@ -413,6 +439,11 @@ void ScUndoSetCell::Redo() MoveCursorToCell(); rDocShell.PostPaintCell(maPos); SetChangeTrack(); + + sc::UndoSheetViewSortData::restore(rDocShell, false); + + rDocShell.ResolveSpilledOutputs(); + EndRedo(); } @@ -471,7 +502,7 @@ void ScUndoSetCell::SetValue( const ScCellValue& rVal ) } break; case CELLTYPE_EDIT: - rDoc.SetEditText(maPos, rVal.getEditText()->Clone()); + rDoc.SetEditText(maPos, std::make_unique(*rVal.getEditText())); break; case CELLTYPE_FORMULA: rDoc.SetFormulaCell(maPos, rVal.getFormula()->Clone()); @@ -486,7 +517,11 @@ void ScUndoSetCell::MoveCursorToCell() ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); if ( pViewShell ) { - pViewShell->SetTabNo( maPos.Tab() ); + // Don't switch tabs if the current view is a sheet view for the target tab. + SCTAB nCurrentTab = pViewShell->GetViewData().GetTabNumber(); + ScDocument& rDocument = rDocShell.GetDocument(); + if (rDocument.GetDefaultViewTableNumber(nCurrentTab) != maPos.Tab()) + pViewShell->SetTabNo(maPos.Tab()); pViewShell->MoveCursorAbs( maPos.Col(), maPos.Row(), SC_FOLLOW_JUMP, false, false ); } } @@ -741,11 +776,15 @@ ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocSh, const ScAddress& rPos, } ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocSh, const ScAddress& rPos, - ScNoteData aOldData, ScNoteData aNewData, std::unique_ptr pDrawUndo ) : + ScNoteData aOldData, ScNoteData aNewData, std::unique_ptr pDrawUndo, + std::unique_ptr pOldThreadedData, + std::unique_ptr pNewThreadedData ) : ScSimpleUndo( rDocSh ), maPos( rPos ), maOldData(std::move( aOldData )), maNewData(std::move( aNewData )), + mpOldThreadedData( std::move(pOldThreadedData) ), + mpNewThreadedData( std::move(pNewThreadedData) ), mpDrawUndo( std::move(pDrawUndo) ) { OSL_ENSURE( maOldData.mxCaption || maNewData.mxCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" ); @@ -765,7 +804,7 @@ void ScUndoReplaceNote::Undo() Undo remove -> insert old note. Undo replace -> remove new note, insert old note. */ DoRemoveNote( maNewData ); - DoInsertNote( maOldData ); + DoInsertNote( maOldData, mpOldThreadedData.get() ); rDocShell.PostPaintCell( maPos ); EndUndo(); } @@ -778,7 +817,7 @@ void ScUndoReplaceNote::Redo() Redo remove -> remove old note. Redo replace -> remove old note, insert new note. */ DoRemoveNote( maOldData ); - DoInsertNote( maNewData ); + DoInsertNote( maNewData, mpNewThreadedData.get() ); rDocShell.PostPaintCell( maPos ); EndRedo(); } @@ -798,7 +837,7 @@ OUString ScUndoReplaceNote::GetComment() const (maOldData.mxCaption ? STR_UNDO_EDITNOTE : STR_UNDO_INSERTNOTE) : STR_UNDO_DELETENOTE ); } -void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData ) +void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData, const ScThreadedCommentData* pThreadedData ) { if( rNoteData.mxCaption ) { @@ -806,6 +845,10 @@ void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData ) OSL_ENSURE( !rDoc.GetNote(maPos), "ScUndoReplaceNote::DoInsertNote - unexpected cell note" ); ScPostIt* pNote = new ScPostIt( rDoc, maPos, rNoteData, false ); rDoc.SetNote( maPos, std::unique_ptr(pNote) ); + // Threaded-comment data lives on ScPostIt outside ScNoteData, so the new + // post-it carries none yet; reattach a fresh clone (undo/redo may fire again). + if (pThreadedData) + pNote->SetThreadedCommentData(std::make_unique(*pThreadedData)); ScDocShell::LOKCommentNotify(LOKCommentNotificationType::Add, rDoc, maPos, pNote); } } diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx index bd283fe8a000..43c2491f2a94 100644 --- a/sc/source/ui/undo/undodat.cxx +++ b/sc/source/ui/undo/undodat.cxx @@ -1740,6 +1740,7 @@ void ScUndoDataPilot::Undo() } // update objects in collection + ScDPObject* pRestoredObject = nullptr; if (xNewDPObject) { // find updated object @@ -1754,6 +1755,7 @@ void ScUndoDataPilot::Undo() { // restore old settings *pDocObj = *xOldDPObject; + pRestoredObject = pDocObj; } else { @@ -1766,6 +1768,18 @@ void ScUndoDataPilot::Undo() { // re-insert deleted object rDoc.GetDPCollection()->InsertNewTable(std::make_unique(*xOldDPObject)); + aOldRange = xOldDPObject->GetOutRange(); + pRestoredObject = rDoc.GetDPAtCursor( + aOldRange.aStart.Col(), aOldRange.aStart.Row(), aOldRange.aStart.Tab()); + } + + // Re-output the restored pivot table with spill checking. + // The old output area may now contain blocking cells that weren't there before. + if (pRestoredObject) + { + ScAddress aOutputPosition = pRestoredObject->GetOutRange().aStart; + pRestoredObject->InvalidateData(); + pRestoredObject->Output(aOutputPosition, true); } if (xNewUndoDoc) diff --git a/sc/source/ui/undo/undodraw.cxx b/sc/source/ui/undo/undodraw.cxx index 155ddcbd8ee9..39524a271724 100644 --- a/sc/source/ui/undo/undodraw.cxx +++ b/sc/source/ui/undo/undodraw.cxx @@ -19,7 +19,9 @@ #include #include +#include #include +#include ScUndoDraw::ScUndoDraw( std::unique_ptr pUndo, ScDocShell& rDocSh ) : @@ -70,12 +72,26 @@ void ScUndoDraw::UpdateSubShell() pViewShell->UpdateDrawShell(); } +void ScUndoDraw::SyncSheetViews() +{ + ScViewData* pViewData = ScDocShell::GetViewData(); + if (!pViewData) + return; + + // Draw undo/redo always operates on the default view's page, so just sync. + ScDocument& rDocument = rDocShell.GetDocument(); + SCTAB nCurrentTab = pViewData->GetTabNumber(); + SCTAB nDefaultTab = rDocument.GetDefaultViewTableNumber(nCurrentTab); + rDocument.SyncSheetViews(nDefaultTab); +} + void ScUndoDraw::Undo() { if (pDrawUndo) { pDrawUndo->Undo(); rDocShell.SetDrawModified(); + SyncSheetViews(); UpdateSubShell(); } } @@ -86,6 +102,7 @@ void ScUndoDraw::Redo() { pDrawUndo->Redo(); rDocShell.SetDrawModified(); + SyncSheetViews(); UpdateSubShell(); } } diff --git a/sc/source/ui/undo/undorangename.cxx b/sc/source/ui/undo/undorangename.cxx index 08aae2bbd2ab..8a1eb01c9cf9 100644 --- a/sc/source/ui/undo/undorangename.cxx +++ b/sc/source/ui/undo/undorangename.cxx @@ -90,7 +90,7 @@ void ScUndoAddRangeData::Undo() ScRangeName* pRangeName = nullptr; if (mnTab == -1) { - pRangeName = rDoc.GetRangeName(); + pRangeName = &rDoc.GetRangeName(); } else { @@ -107,13 +107,13 @@ void ScUndoAddRangeData::Redo() ScRangeName* pRangeName = nullptr; if (mnTab == -1) { - pRangeName = rDoc.GetRangeName(); + pRangeName = &rDoc.GetRangeName(); } else { pRangeName = rDoc.GetRangeName( mnTab ); } - pRangeName->insert(new ScRangeData(*mpRangeData)); + pRangeName->insert(std::make_unique(*mpRangeData)); SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) ); } diff --git a/sc/source/ui/undo/undosort.cxx b/sc/source/ui/undo/undosort.cxx index 15f4eabffbfc..322b11700ba2 100644 --- a/sc/source/ui/undo/undosort.cxx +++ b/sc/source/ui/undo/undosort.cxx @@ -46,6 +46,8 @@ void UndoSort::Execute( bool bUndo ) aParam.reverse(); rDoc.Reorder(aParam); + UndoSheetViewSortData::restore(rDocShell, bUndo); + ScRange aOverallRange( maParam.maSortRange); if (maParam.maDataAreaExtras.anyExtrasWanted()) { diff --git a/sc/source/ui/undo/undotab.cxx b/sc/source/ui/undo/undotab.cxx index c8d3db940599..ab2bb578f997 100644 --- a/sc/source/ui/undo/undotab.cxx +++ b/sc/source/ui/undo/undotab.cxx @@ -504,7 +504,7 @@ void ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget) if (auto pViewTarget = dynamic_cast( &rTarget)) { ScTabViewShell& rViewShell = pViewTarget->GetViewShell(); - rViewShell.DeleteTable( rViewShell.GetViewData().CurrentTabForData() ); + rViewShell.DeleteTable( rViewShell.GetViewData().GetTabNumber() ); } } diff --git a/sc/source/ui/undo/undoutil.cxx b/sc/source/ui/undo/undoutil.cxx index f935054cbe0c..089c3250c39e 100644 --- a/sc/source/ui/undo/undoutil.cxx +++ b/sc/source/ui/undo/undoutil.cxx @@ -39,7 +39,7 @@ void ScUndoUtil::MarkSimpleBlock( const ScDocShell& rDocShell, if (!pViewShell) return; - SCTAB nViewTab = pViewShell->GetViewData().CurrentTabForData(); + SCTAB nViewTab = pViewShell->GetViewData().GetTabNumber(); if ( nViewTab < nStartZ || nViewTab > nEndZ ) pViewShell->SetTabNo( nStartZ ); diff --git a/sc/source/ui/unoobj/celllistsource.cxx b/sc/source/ui/unoobj/celllistsource.cxx index 19a1a94822bb..a2b8ed65460a 100644 --- a/sc/source/ui/unoobj/celllistsource.cxx +++ b/sc/source/ui/unoobj/celllistsource.cxx @@ -73,10 +73,6 @@ namespace calc } } - IMPLEMENT_FORWARD_XINTERFACE2( OCellListSource, OCellListSource_Base, OCellListSource_PBase ) - - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCellListSource, OCellListSource_Base, OCellListSource_PBase ) - void OCellListSource::disposing(std::unique_lock& rGuard) { Reference xBroadcaster( m_xRange, UNO_QUERY ); @@ -88,21 +84,11 @@ namespace calc EventObject aDisposeEvent( *this ); m_aListEntryListeners.disposeAndClear( rGuard, aDisposeEvent ); - WeakComponentImplHelperBase::disposing(rGuard); + disposePropertySetListeners(rGuard); // TODO: clean up here whatever you need to clean up (e.g. revoking listeners etc.) } - Reference< XPropertySetInfo > SAL_CALL OCellListSource::getPropertySetInfo( ) - { - return createPropertySetInfo( getInfoHelper() ) ; - } - - ::cppu::IPropertyArrayHelper& OCellListSource::getInfoHelper() - { - return *OCellListSource_PABase::getArrayHelper(); - } - ::cppu::IPropertyArrayHelper* OCellListSource::createArrayHelper( ) const { Sequence< Property > aProps; diff --git a/sc/source/ui/unoobj/celllistsource.hxx b/sc/source/ui/unoobj/celllistsource.hxx index 96eb5caa500a..6c83c7e636dc 100644 --- a/sc/source/ui/unoobj/celllistsource.hxx +++ b/sc/source/ui/unoobj/celllistsource.hxx @@ -20,40 +20,29 @@ #pragma once #include -#include -#include -#include -#include -#include #include #include #include #include +#include +#include + namespace com::sun::star::sheet { class XSpreadsheetDocument; } namespace com::sun::star::table { class XCellRange; } namespace calc { + using OCellListSource_Base = comphelper::OPropertyContainerImplHelper< + comphelper::WeakComponentImplHelper< + css::form::binding::XListEntryTypedSource, + css::util::XModifyListener, + css::lang::XServiceInfo, + css::lang::XInitialization>, + class OCellListSource>; - //= OCellListSource - - class OCellListSource; - // the base for our interfaces - typedef ::comphelper::WeakComponentImplHelper < css::form::binding::XListEntryTypedSource - , css::util::XModifyListener - , css::lang::XServiceInfo - , css::lang::XInitialization - > OCellListSource_Base; - // the base for the property handling - typedef ::comphelper::OPropertyContainer2 OCellListSource_PBase; - // the second base for property handling - typedef ::comphelper::OPropertyArrayUsageHelper< OCellListSource > - OCellListSource_PABase; - - class OCellListSource :public OCellListSource_Base // order matters! before OCellListSource_PBase, so rBHelper gets initialized - ,public OCellListSource_PBase - ,public OCellListSource_PABase + class OCellListSource final + : public OCellListSource_Base { private: css::uno::Reference< css::sheet::XSpreadsheetDocument > @@ -69,18 +58,9 @@ namespace calc const css::uno::Reference< css::sheet::XSpreadsheetDocument >& _rxDocument ); - using OCellListSource_PBase::getFastPropertyValue; - protected: virtual ~OCellListSource( ) override; - protected: - // XInterface - DECLARE_XINTERFACE() - - // XTypeProvider - DECLARE_XTYPEPROVIDER() - // XListEntrySource virtual sal_Int32 SAL_CALL getListEntryCount( ) override; virtual OUString SAL_CALL getListEntry( sal_Int32 Position ) override; @@ -99,14 +79,11 @@ namespace calc virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; - // XPropertySet - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; - - // OPropertySetHelper - virtual ::cppu::IPropertyArrayHelper& getInfoHelper() override; + // OPropertyImplHelper + using OCellListSource_Base::getFastPropertyValue; virtual void getFastPropertyValue( std::unique_lock& rGuard, css::uno::Any& _rValue, sal_Int32 _nHandle ) const override; - // ::comphelper::OPropertyArrayUsageHelper + // OPropertyArrayUsageHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; // XModifyListener diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index e70cf51591a6..f5e83309aee9 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -3271,8 +3271,6 @@ void SAL_CALL ScCellRangesBase::addModifyListener(const uno::ReferenceGetDocument(); for ( size_t i = 0, nCount = aRanges.size(); i < nCount; i++) rDoc.StartListeningArea( aRanges[ i ], false, pValueListener.get() ); - - acquire(); // don't lose this object (one ref for all listeners) } } @@ -3297,8 +3295,6 @@ void SAL_CALL ScCellRangesBase::removeModifyListener( const uno::ReferenceEndListeningAll(); - - release(); // release the ref for the listeners } break; @@ -5287,7 +5283,7 @@ void SAL_CALL ScCellRangeObj::sort( const uno::Sequence& a pDocSh->GetDBData( aRange, SC_DB_MAKE, ScGetDBSelection::ForceMark ); // if needed create area ScDBDocFunc aFunc(*pDocSh); // area must be created - (void)aFunc.Sort( nTab, aParam, true, true, true ); + (void)aFunc.SortTab(nTab, aParam, true, true, true); } // XFilterable diff --git a/sc/source/ui/unoobj/cellvaluebinding.cxx b/sc/source/ui/unoobj/cellvaluebinding.cxx index 21844d268365..13e9b20480a2 100644 --- a/sc/source/ui/unoobj/cellvaluebinding.cxx +++ b/sc/source/ui/unoobj/cellvaluebinding.cxx @@ -36,6 +36,7 @@ #include #include #include +#include namespace calc { @@ -80,10 +81,6 @@ namespace calc } } - IMPLEMENT_FORWARD_XINTERFACE2( OCellValueBinding, OCellValueBinding_Base, OCellValueBinding_PBase ) - - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCellValueBinding, OCellValueBinding_Base, OCellValueBinding_PBase ) - void OCellValueBinding::disposing( std::unique_lock& rGuard ) { Reference xBroadcaster( m_xCell, UNO_QUERY ); @@ -92,22 +89,12 @@ namespace calc xBroadcaster->removeModifyListener( this ); } - WeakComponentImplHelperBase::disposing(rGuard); + disposePropertySetListeners(rGuard); // TODO: clean up here whatever you need to clean up (e.g. deregister as XEventListener // for the cell) } - Reference< XPropertySetInfo > SAL_CALL OCellValueBinding::getPropertySetInfo( ) - { - return createPropertySetInfo( getInfoHelper() ) ; - } - - ::cppu::IPropertyArrayHelper& OCellValueBinding::getInfoHelper() - { - return *OCellValueBinding_PABase::getArrayHelper(); - } - ::cppu::IPropertyArrayHelper* OCellValueBinding::createArrayHelper( ) const { Sequence< Property > aProps; @@ -175,11 +162,7 @@ namespace calc { // look up in our sequence const Sequence< Type > aSupportedTypes( getSupportedValueTypes(rGuard) ); - for ( auto const & i : aSupportedTypes ) - if ( aType == i ) - return true; - - return false; + return std::ranges::find(aSupportedTypes, aType) != aSupportedTypes.end(); } Any SAL_CALL OCellValueBinding::getValue( const Type& aType ) diff --git a/sc/source/ui/unoobj/cellvaluebinding.hxx b/sc/source/ui/unoobj/cellvaluebinding.hxx index 8c77523f4ab0..84fa1b683185 100644 --- a/sc/source/ui/unoobj/cellvaluebinding.hxx +++ b/sc/source/ui/unoobj/cellvaluebinding.hxx @@ -20,14 +20,12 @@ #pragma once #include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include + +#include +#include namespace com::sun::star::table { class XCell; } namespace com::sun::star::sheet { class XSpreadsheetDocument; } @@ -35,27 +33,17 @@ namespace com::sun::star::text { class XTextRange; } namespace calc { + using OCellValueBinding_Base = comphelper::OPropertyContainerImplHelper< + comphelper::WeakComponentImplHelper< + css::form::binding::XValueBinding, + css::lang::XServiceInfo, + css::util::XModifyBroadcaster, + css::util::XModifyListener, + css::lang::XInitialization>, + class OCellValueBinding>; - //= OCellValueBinding - - class OCellValueBinding; - // the base for our interfaces - typedef ::comphelper::WeakComponentImplHelper < css::form::binding::XValueBinding - , css::lang::XServiceInfo - , css::util::XModifyBroadcaster - , css::util::XModifyListener - , css::lang::XInitialization - > OCellValueBinding_Base; - // the base for the property handling - typedef ::comphelper::OPropertyContainer2 OCellValueBinding_PBase; - // the second base for property handling - typedef ::comphelper::OPropertyArrayUsageHelper< OCellValueBinding > - OCellValueBinding_PABase; - - class OCellValueBinding : - public OCellValueBinding_Base // order matters! before OCellValueBinding_PBase, so rBHelper gets initialized - ,public OCellValueBinding_PBase - ,public OCellValueBinding_PABase + class OCellValueBinding final + : public OCellValueBinding_Base { private: css::uno::Reference< css::sheet::XSpreadsheetDocument > @@ -75,18 +63,9 @@ namespace calc bool _bListPos ); - using OCellValueBinding_PBase::getFastPropertyValue; - protected: virtual ~OCellValueBinding( ) override; - protected: - // XInterface - DECLARE_XINTERFACE() - - // XTypeProvider - DECLARE_XTYPEPROVIDER() - // XValueBinding virtual css::uno::Sequence< css::uno::Type > SAL_CALL getSupportedValueTypes( ) override; virtual sal_Bool SAL_CALL supportsType( const css::uno::Type& aType ) override; @@ -101,11 +80,8 @@ namespace calc virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; - // XPropertySet - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; - - // OPropertySetHelper - virtual ::cppu::IPropertyArrayHelper& getInfoHelper() override; + // OPropertyImplHelper + using OCellValueBinding_Base::getFastPropertyValue; virtual void getFastPropertyValue( std::unique_lock& rGuard, css::uno::Any& _rValue, sal_Int32 _nHandle ) const override; // ::comphelper::OPropertyArrayUsageHelper @@ -136,9 +112,6 @@ namespace calc void setBooleanFormat(); - private: - OCellValueBinding( const OCellValueBinding& ) = delete; - OCellValueBinding& operator=( const OCellValueBinding& ) = delete; }; } // namespace calc diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx index 42c6eaef4451..18b01ea126fc 100644 --- a/sc/source/ui/unoobj/chart2uno.cxx +++ b/sc/source/ui/unoobj/chart2uno.cxx @@ -338,7 +338,7 @@ Chart2PositionMap::Chart2PositionMap(SCCOL nAllColCount, SCROW nAllRowCount, if (nHeaderColCount && !bFoundValuesInCol && bFoundAnythingInCol && nCol == nHeaderColCount) { - // There is no values in row, but some data. And this column is next to header + // There are no values in row, but some data. And this column is next to header // So let's put it to header nHeaderColCount++; } @@ -725,10 +725,15 @@ void Chart2Positioner::createPositionMap() for (const ScTokenRef& pToken : mrRefTokens) { bool bExternal = ScRefTokenHelper::isExternalRef(pToken); - sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0; + sal_uInt16 nFileId = bExternal ? static_cast(pToken.get())->GetFileId() : 0; svl::SharedString aTabName = svl::SharedString::getEmptyString(); if (bExternal) - aTabName = pToken->GetString(); + { + if (pToken->GetType() == svExternalSingleRef) + aTabName = static_cast(pToken.get())->GetTableName(); + else + aTabName = static_cast(pToken.get())->GetTableName(); + } ScComplexRefData aData; if( !ScRefTokenHelper::getDoubleRefDataFromToken(aData, pToken) ) @@ -884,7 +889,8 @@ public: // Check there is a valid reference in named range if (!bValidToken && rToken->GetType() == svIndex && rToken->GetOpCode() == ocName) { - ScRangeData* pNameRange = mpDoc->FindRangeNameBySheetAndIndex(rToken->GetSheet(), rToken->GetIndex()); + auto pIndexToken = static_cast(rToken.get()); + ScRangeData* pNameRange = mpDoc->FindRangeNameBySheetAndIndex(pIndexToken->GetSheet(), pIndexToken->GetIndex()); if (pNameRange->HasReferences()) { const ScTokenRef aTempToken = pNameRange->GetCode()->FirstToken(); @@ -924,8 +930,12 @@ private: if (!bIsRefToken) return false; bool bExternal = ScRefTokenHelper::isExternalRef(pToken); - sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0; - const svl::SharedString aTabName = bExternal ? pToken->GetString() : svl::SharedString::getEmptyString(); + sal_uInt16 nFileId = bExternal ? static_cast(pToken.get())->GetFileId() : 0; + svl::SharedString aTabName; + if (!bExternal) + aTabName = svl::SharedString::getEmptyString(); + else + aTabName = static_cast(pToken.get())->GetTableName(); // In saving to XML, we don't prepend address with '$'. setRelative(aData.Ref1); @@ -1093,7 +1103,7 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, std::vectorGetSingleRef(); + const ScSingleRefData& rData = static_cast(pToken.get())->GetSingleRef(); nMinCol = rData.Col(); nMinRow = rData.Row(); nMaxCol = rData.Col(); @@ -1103,7 +1113,7 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, std::vectorGetDoubleRef(); + const ScComplexRefData& rData = static_cast(pToken.get())->GetDoubleRef(); nMinCol = std::min(rData.Ref1.Col(), rData.Ref2.Col()); nMinRow = std::min(rData.Ref1.Row(), rData.Ref2.Row()); nMaxCol = std::max(rData.Ref1.Col(), rData.Ref2.Col()); @@ -1113,27 +1123,29 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, std::vectorGetSingleRef(); + auto pESRToken = static_cast(pToken.get()); + const ScSingleRefData& rData = pESRToken->GetSingleRef(); nMinCol = rData.Col(); nMinRow = rData.Row(); nMaxCol = rData.Col(); nMaxRow = rData.Row(); nTab = rData.Tab(); - nFileId = pToken->GetIndex(); - aExtTabName = pToken->GetString(); + nFileId = pESRToken->GetFileId(); + aExtTabName = pESRToken->GetTableName(); bExternal = true; } break; case svExternalDoubleRef: { - const ScComplexRefData& rData = *pToken->GetDoubleRef(); + auto pEDRToken = static_cast(pToken.get()); + const ScComplexRefData& rData = pEDRToken->GetDoubleRef(); nMinCol = std::min(rData.Ref1.Col(), rData.Ref2.Col()); nMinRow = std::min(rData.Ref1.Row(), rData.Ref2.Row()); nMaxCol = std::max(rData.Ref1.Col(), rData.Ref2.Col()); nMaxRow = std::max(rData.Ref1.Row(), rData.Ref2.Row()); nTab = rData.Ref1.Tab(); - nFileId = pToken->GetIndex(); - aExtTabName = pToken->GetString(); + nFileId = pEDRToken->GetFileId(); + aExtTabName = pEDRToken->GetTableName(); bExternal = true; } break; @@ -1151,7 +1163,7 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, std::vectorGetSingleRef(); + const ScSingleRefData& rData = static_cast(pToken.get())->GetSingleRef(); nMinCol = std::min(nMinCol, rData.Col()); nMinRow = std::min(nMinRow, rData.Row()); @@ -1163,7 +1175,7 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, std::vectorGetDoubleRef(); + const ScComplexRefData& rData = static_cast(pToken.get())->GetDoubleRef(); nMinCol = std::min(nMinCol, rData.Ref1.Col()); nMinCol = std::min(nMinCol, rData.Ref2.Col()); @@ -1181,13 +1193,15 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, std::vector(pToken.get()); + if (!bExternal) return false; - if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString()) + if (nFileId != pESRToken->GetFileId() || aExtTabName != pESRToken->GetTableName()) return false; - const ScSingleRefData& rData = *pToken->GetSingleRef(); + const ScSingleRefData& rData = pESRToken->GetSingleRef(); nMinCol = std::min(nMinCol, rData.Col()); nMinRow = std::min(nMinRow, rData.Row()); @@ -1197,13 +1211,15 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, std::vector(pToken.get()); + if (!bExternal) return false; - if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString()) + if (nFileId != pEDRToken->GetFileId() || aExtTabName != pEDRToken->GetTableName()) return false; - const ScComplexRefData& rData = *pToken->GetDoubleRef(); + const ScComplexRefData& rData = pEDRToken->GetDoubleRef(); nMinCol = std::min(nMinCol, rData.Ref1.Col()); nMinCol = std::min(nMinCol, rData.Ref2.Col()); @@ -1243,27 +1259,35 @@ bool lcl_addUpperLeftCornerIfMissing(const ScDocument* pDoc, std::vectorGetSingleRef(); - if (rData.Col() == nMinCol && rData.Row() == nMinRow) + const ScSingleRefData* pData; + if (rxToken->GetType() == svSingleRef) + pData = &static_cast(rxToken.get())->GetSingleRef(); + else + pData = &static_cast(rxToken.get())->GetSingleRef(); + if (pData->Col() == nMinCol && pData->Row() == nMinRow) // The corner cell is contained. return false; - if (rData.Col() == nMinCol+nCornerColumnCount && rData.Row() == nMinRow) + if (pData->Col() == nMinCol+nCornerColumnCount && pData->Row() == nMinRow) bRight = true; - if (rData.Col() == nMinCol && rData.Row() == nMinRow+nCornerRowCount) + if (pData->Col() == nMinCol && pData->Row() == nMinRow+nCornerRowCount) bBottom = true; - if (rData.Col() == nMinCol+nCornerColumnCount && rData.Row() == nMinRow+nCornerRowCount) + if (pData->Col() == nMinCol+nCornerColumnCount && pData->Row() == nMinRow+nCornerRowCount) bDiagonal = true; } break; case svDoubleRef: case svExternalDoubleRef: { - const ScComplexRefData& rData = *rxToken->GetDoubleRef(); - const ScSingleRefData& r1 = rData.Ref1; - const ScSingleRefData& r2 = rData.Ref2; + const ScComplexRefData* pData; + if (rxToken->GetType() == svDoubleRef) + pData = &static_cast(rxToken.get())->GetDoubleRef(); + else + pData = &static_cast(rxToken.get())->GetDoubleRef(); + const ScSingleRefData& r1 = pData->Ref1; + const ScSingleRefData& r2 = pData->Ref2; if (r1.Col() <= nMinCol && nMinCol <= r2.Col() && r1.Row() <= nMinRow && nMinRow <= r2.Row()) // The corner cell is contained. @@ -1353,7 +1377,7 @@ public: if (rRef->GetType() != svDoubleRef) return; - ScComplexRefData& rData = *rRef->GetDoubleRef(); + ScComplexRefData& rData = static_cast(rRef.get())->GetDoubleRef(); ScSingleRefData& s = rData.Ref1; ScSingleRefData& e = rData.Ref2; @@ -1463,7 +1487,7 @@ ScChart2DataProvider::createDataSource( if (rxToken->GetType() != svDoubleRef) continue; - ScComplexRefData& rData = *rxToken->GetDoubleRef(); + ScComplexRefData& rData = static_cast(rxToken.get())->GetDoubleRef(); ScSingleRefData& s = rData.Ref1; ScSingleRefData& e = rData.Ref2; @@ -1588,8 +1612,7 @@ public: if (!ScRefTokenHelper::isRef(pToken)) return; - const ScSingleRefData& r = *pToken->GetSingleRef(); - mpTabNumVector->push_back(r.Tab()); + mpTabNumVector->push_back(ScRefTokenHelper::getSingleRef(pToken.get())->Tab()); } void getVector(std::vector& rVector) @@ -1651,19 +1674,23 @@ void RangeAnalyzer::initRangeAnalyzer( const ScDocument* pDoc, const std::vector StackVar eVar = aRefToken->GetType(); if (eVar == svDoubleRef || eVar == svExternalDoubleRef) { - const ScComplexRefData& r = *aRefToken->GetDoubleRef(); - if (r.Ref1.Tab() == r.Ref2.Tab()) + const ScComplexRefData* pRef; + if (eVar == svDoubleRef) + pRef = &static_cast(aRefToken.get())->GetDoubleRef(); + else + pRef = &static_cast(aRefToken.get())->GetDoubleRef(); + if (pRef->Ref1.Tab() == pRef->Ref2.Tab()) { - mnColumnCount = std::max(mnColumnCount, static_cast(abs(r.Ref2.Col() - r.Ref1.Col())+1)); - mnRowCount = std::max(mnRowCount, static_cast(abs(r.Ref2.Row() - r.Ref1.Row())+1)); + mnColumnCount = std::max(mnColumnCount, static_cast(abs(pRef->Ref2.Col() - pRef->Ref1.Col())+1)); + mnRowCount = std::max(mnRowCount, static_cast(abs(pRef->Ref2.Row() - pRef->Ref1.Row())+1)); if( mnStartColumn == -1 ) { - mnStartColumn = r.Ref1.Col(); - mnStartRow = r.Ref1.Row(); + mnStartColumn = pRef->Ref1.Col(); + mnStartRow = pRef->Ref1.Row(); } else { - if (mnStartColumn != r.Ref1.Col() && mnStartRow != r.Ref1.Row()) + if (mnStartColumn != pRef->Ref1.Col() && mnStartRow != pRef->Ref1.Row()) mbAmbiguous=true; } } @@ -1672,23 +1699,28 @@ void RangeAnalyzer::initRangeAnalyzer( const ScDocument* pDoc, const std::vector } else if (eVar == svSingleRef || eVar == svExternalSingleRef) { - const ScSingleRefData& r = *aRefToken->GetSingleRef(); + const ScSingleRefData* p; + if (eVar == svSingleRef) + p = &static_cast(aRefToken.get())->GetSingleRef(); + else + p = &static_cast(aRefToken.get())->GetSingleRef(); mnColumnCount = std::max( mnColumnCount, 1); mnRowCount = std::max( mnRowCount, 1); if( mnStartColumn == -1 ) { - mnStartColumn = r.Col(); - mnStartRow = r.Row(); + mnStartColumn = p->Col(); + mnStartRow = p->Row(); } else { - if (mnStartColumn != r.Col() && mnStartRow != r.Row()) + if (mnStartColumn != p->Col() && mnStartRow != p->Row()) mbAmbiguous=true; } } else if (eVar == svIndex && aRefToken->GetOpCode() == ocName) { - ScRangeData* pNameRange = pDoc->FindRangeNameBySheetAndIndex(aRefToken->GetSheet(), aRefToken->GetIndex()); + auto pIndexToken = static_cast(aRefToken.get()); + ScRangeData* pNameRange = pDoc->FindRangeNameBySheetAndIndex(pIndexToken->GetSheet(), pIndexToken->GetIndex()); ScRange aRange; if (pNameRange->IsReference(aRange)) { @@ -1815,7 +1847,8 @@ uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArgum { if (rxToken->GetType() == svIndex && rxToken->GetOpCode() == ocName) { - ScRangeData* pNameRange = m_pDocument->FindRangeNameBySheetAndIndex(rxToken->GetSheet(), rxToken->GetIndex()); + auto pIndexToken = static_cast(rxToken.get()); + ScRangeData* pNameRange = m_pDocument->FindRangeNameBySheetAndIndex(pIndexToken->GetSheet(), pIndexToken->GetIndex()); if (pNameRange->HasReferences()) { const ScTokenRef aTempToken = pNameRange->GetCode()->FirstToken(); @@ -1845,7 +1878,8 @@ uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArgum { if (rxToken->GetType() == svIndex && rxToken->GetOpCode() == ocName) { - ScRangeData* pNameRange = m_pDocument->FindRangeNameBySheetAndIndex(rxToken->GetSheet(), rxToken->GetIndex()); + auto pIndexToken = static_cast(rxToken.get()); + ScRangeData* pNameRange = m_pDocument->FindRangeNameBySheetAndIndex(pIndexToken->GetSheet(), pIndexToken->GetIndex()); if (pNameRange->HasReferences()) { const ScTokenRef aTempToken = pNameRange->GetCode()->FirstToken(); @@ -2113,12 +2147,12 @@ sal_Bool SAL_CALL ScChart2DataProvider::createDataSequenceByFormulaTokensPossibl break; case ocOpen: if (p != pFirst) - // open paran is allowed only as the first token. + // open parent is allowed only as the first token. return false; break; case ocClose: if (p != pLast) - // close paren is allowed only as the last token. + // close parent is allowed only as the last token. return false; break; default: @@ -2172,12 +2206,12 @@ ScChart2DataProvider::createDataSequenceByFormulaTokens( break; case ocOpen: if (p != pFirst) - // open paran is allowed only as the first token. + // open parent is allowed only as the first token. throw lang::IllegalArgumentException(); break; case ocClose: if (p != pLast) - // close paren is allowed only as the last token. + // close parent is allowed only as the last token. throw lang::IllegalArgumentException(); break; default: @@ -2410,6 +2444,7 @@ ScChart2DataSequence::ScChart2DataSequence( ScDocument* pDoc, bool bIncludeHiddenCells ) : m_xDataArray(new std::vector) , m_bIncludeHiddenCells( bIncludeHiddenCells) + , m_eDimType(DataSourceType::UNKNOWN) , m_nObjectId( 0 ) , m_pDocument( pDoc) , m_aTokens(std::move(rTokens)) @@ -2426,7 +2461,7 @@ ScChart2DataSequence::ScChart2DataSequence( ScDocument* pDoc, m_pDocument->AddUnoObject( *this); m_nObjectId = m_pDocument->GetNewUnoId(); } - // FIXME: real implementation of identifier and it's mapping to ranges. + // FIXME: real implementation of identifier and its mapping to ranges. // Reuse ScChartListener? // BM: don't use names of named ranges but the UI range strings @@ -2445,6 +2480,9 @@ ScChart2DataSequence::ScChart2DataSequence(ScDocument* pDoc, const ScChart2DataS , m_aHiddenValues(r.m_aHiddenValues) , m_aRole(r.m_aRole) , m_bIncludeHiddenCells( r.m_bIncludeHiddenCells) + , m_eDimType( r.m_eDimType) + , m_sFormula( r.m_sFormula) + , m_sNFormula( r.m_sNFormula) , m_nObjectId( 0 ) , m_pDocument( pDoc) , m_aPropSet(lcl_GetDataSequencePropertyMap()) @@ -2672,8 +2710,12 @@ sal_Int32 ScChart2DataSequence::FillCacheFromExternalRef(const ScTokenRef& pToke if (!ScRefTokenHelper::getRangeFromToken(m_pDocument, aRange, pToken, ScAddress(), true)) return 0; - sal_uInt16 nFileId = pToken->GetIndex(); - OUString aTabName = pToken->GetString().getString(); + sal_uInt16 nFileId = static_cast(pToken.get())->GetFileId(); + OUString aTabName; + if (pToken->GetType() == svExternalDoubleRef) + aTabName = static_cast(pToken.get())->GetTableName().getString(); + else + aTabName = static_cast(pToken.get())->GetTableName().getString(); ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, aTabName, aRange, nullptr); if (!pArray) // no external data exists for this range. @@ -2701,7 +2743,7 @@ sal_Int32 ScChart2DataSequence::FillCacheFromExternalRef(const ScTokenRef& pToke continue; } - const ScMatrix* pMat = p->GetMatrix(); + const ScMatrix* pMat = static_cast(p)->GetMatrix(); SCSIZE nCSize, nRSize; pMat->GetDimensions(nCSize, nRSize); for (SCSIZE nC = 0; nC < nCSize; ++nC) @@ -3049,7 +3091,7 @@ uno::Sequence< OUString > SAL_CALL ScChart2DataSequence::getTextualData() { if( m_aTokens.front()->GetType() == svString ) { - aSeq = uno::Sequence { m_aTokens.front()->GetString().getString() }; + aSeq = uno::Sequence { static_cast(m_aTokens.front().get())->GetString().getString() }; } } @@ -3284,8 +3326,6 @@ void SAL_CALL ScChart2DataSequence::addModifyListener( const uno::Reference< uti pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get()); } } - - acquire(); // don't lose this object (one ref for all listeners) } void SAL_CALL ScChart2DataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) @@ -3317,8 +3357,6 @@ void SAL_CALL ScChart2DataSequence::removeModifyListener( const uno::Reference< if (pCLC) pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); } - - release(); // release the ref for the listeners } break; @@ -3359,6 +3397,24 @@ void SAL_CALL ScChart2DataSequence::setPropertyValue( rValue>>= bTimeBased; mbTimeBased = bTimeBased; } + else if( rPropertyName == "ChartExDimType" ) + { + sal_Int32 nDimType; + if (rValue >>= nDimType) + m_eDimType = static_cast(nDimType); + else + throw lang::IllegalArgumentException(); + } + else if( rPropertyName == "ChartExFormula" ) + { + if ( !(rValue >>= m_sFormula)) + throw lang::IllegalArgumentException(); + } + else if( rPropertyName == "ChartExNFormula" ) + { + if ( !(rValue >>= m_sNFormula)) + throw lang::IllegalArgumentException(); + } else throw beans::UnknownPropertyException(rPropertyName); // TODO: support optional properties @@ -3394,6 +3450,12 @@ uno::Any SAL_CALL ScChart2DataSequence::getPropertyValue(const OUString& rProper } aRet <<= bHasStringLabel; } + else if ( rPropertyName == "ChartExDimType" ) + aRet <<= static_cast(m_eDimType); + else if ( rPropertyName == "ChartExFormula" ) + aRet <<= m_sFormula; + else if ( rPropertyName == "ChartExNFormula" ) + aRet <<= m_sNFormula; else throw beans::UnknownPropertyException(rPropertyName); // TODO: support optional properties @@ -3454,7 +3516,7 @@ sal_Bool ScChart2DataSequence::switchToNext(sal_Bool bWrap) if (rxToken->GetType() != svDoubleRef) continue; - ScComplexRefData& rData = *rxToken->GetDoubleRef(); + ScComplexRefData& rData = static_cast(rxToken.get())->GetDoubleRef(); ScSingleRefData& s = rData.Ref1; ScSingleRefData& e = rData.Ref2; @@ -3487,7 +3549,7 @@ sal_Bool ScChart2DataSequence::setToPointInTime(sal_Int32 nPoint) if (rxToken->GetType() != svDoubleRef) continue; - ScComplexRefData& rData = *rxToken->GetDoubleRef(); + ScComplexRefData& rData = static_cast(rxToken.get())->GetDoubleRef(); ScSingleRefData& s = rData.Ref1; ScSingleRefData& e = rData.Ref2; diff --git a/sc/source/ui/unoobj/chartuno.cxx b/sc/source/ui/unoobj/chartuno.cxx index d1eae3b117ee..9598b955175c 100644 --- a/sc/source/ui/unoobj/chartuno.cxx +++ b/sc/source/ui/unoobj/chartuno.cxx @@ -510,13 +510,6 @@ void ScChartObj::Update_Impl( const ScRangeListRef& rRanges, bool bColHeaders, b } } -// ::comphelper::OPropertySetHelper - -::cppu::IPropertyArrayHelper& ScChartObj::getInfoHelper() -{ - return *ScChartObj_PABase::getArrayHelper(); -} - void ScChartObj::setFastPropertyValue_NoBroadcast( std::unique_lock& /*rGuard*/, sal_Int32 nHandle, const uno::Any& rValue ) { switch ( nHandle ) @@ -598,14 +591,6 @@ void ScChartObj::getFastPropertyValue( std::unique_lock& /*rGuard*/, return new ::cppu::OPropertyArrayHelper( aProps ); } -// XInterface - -IMPLEMENT_FORWARD_XINTERFACE2( ScChartObj, ScChartObj_Base, ScChartObj_PBase ) - -// XTypeProvider - -IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScChartObj, ScChartObj_Base, ScChartObj_PBase ) - // XTableChart sal_Bool SAL_CALL ScChartObj::getHasColumnHeaders() @@ -727,11 +712,4 @@ void SAL_CALL ScChartObj::setName( const OUString& /* aName */ ) throw uno::RuntimeException(); // name cannot be changed } -// XPropertySet - -uno::Reference< beans::XPropertySetInfo > ScChartObj::getPropertySetInfo() -{ - return createPropertySetInfo( getInfoHelper() ) ; -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/unoobj/condformatuno.cxx b/sc/source/ui/unoobj/condformatuno.cxx index 54b83c4cf527..d481db9b588f 100644 --- a/sc/source/ui/unoobj/condformatuno.cxx +++ b/sc/source/ui/unoobj/condformatuno.cxx @@ -318,6 +318,8 @@ ScCondFormatsObj::ScCondFormatsObj(ScDocShell* pDocShell, SCTAB nTab): ScCondFormatsObj::~ScCondFormatsObj() { + SolarMutexGuard aGuard; + if (mpDocShell) mpDocShell->GetDocument().RemoveUnoObject(*this); } @@ -357,7 +359,11 @@ sal_Int32 ScCondFormatsObj::createByRange(const uno::Reference< sheet::XSheetCel auto pNewFormat = std::make_unique(0, mpDocShell->GetDocument()); pNewFormat->SetRange(aCoreRange); - return mpDocShell->GetDocument().AddCondFormat(std::move(pNewFormat), nTab); + ScDocument& rDoc = mpDocShell->GetDocument(); + sal_Int32 nIndex = rDoc.AddCondFormat(std::move(pNewFormat), nTab); + rDoc.AddCondFormatData(aCoreRange, nTab, nIndex); + + return nIndex; } void ScCondFormatsObj::removeByID(const sal_Int32 nID) @@ -463,6 +469,21 @@ ScDocShell* ScCondFormatObj::getDocShell() return mpDocShell; } +namespace +{ +ScColorScaleFormat* createColorScaleFormat(ScDocument& rDoc, size_t nEntries) +{ + ScColorScaleFormat* pNewEntry = new ScColorScaleFormat(rDoc); + + for (size_t i = 0; i < nEntries; ++i) + pNewEntry->AddEntry(new ScColorScaleEntry); + + pNewEntry->EnsureSize(); + + return pNewEntry; +} +} + void ScCondFormatObj::createEntry(const sal_Int32 nType, const sal_Int32 nPos) { SolarMutexGuard aGuard; @@ -479,8 +500,13 @@ void ScCondFormatObj::createEntry(const sal_Int32 nType, const sal_Int32 nPos) rDoc, pFormat->GetRange().GetTopLeftCorner(), u""_ustr); break; case sheet::ConditionEntryType::COLORSCALE: - pNewEntry = new ScColorScaleFormat(rDoc); - static_cast(pNewEntry)->EnsureSize(); + pNewEntry = createColorScaleFormat(rDoc, 0); + break; + case sheet::ConditionEntryType::COLORSCALE2: + pNewEntry = createColorScaleFormat(rDoc, 2); + break; + case sheet::ConditionEntryType::COLORSCALE3: + pNewEntry = createColorScaleFormat(rDoc, 3); break; case sheet::ConditionEntryType::DATABAR: pNewEntry = new ScDataBarFormat(rDoc); @@ -849,7 +875,15 @@ ScColorScaleFormat* ScColorScaleFormatObj::getCoreObject() sal_Int32 ScColorScaleFormatObj::getType() { - return sheet::ConditionEntryType::COLORSCALE; + switch (getCoreObject()->size()) + { + case 2: + return sheet::ConditionEntryType::COLORSCALE2; + case 3: + return sheet::ConditionEntryType::COLORSCALE3; + default: + return sheet::ConditionEntryType::COLORSCALE; + } } uno::Reference SAL_CALL ScColorScaleFormatObj::getPropertySetInfo() diff --git a/sc/source/ui/unoobj/confuno.cxx b/sc/source/ui/unoobj/confuno.cxx index 284ed81208d1..a9b7e3f49423 100644 --- a/sc/source/ui/unoobj/confuno.cxx +++ b/sc/source/ui/unoobj/confuno.cxx @@ -245,11 +245,11 @@ void SAL_CALL ScDocumentConfiguration::setPropertyValue( { SvMemoryStream aStream (aSequence.getArray(), nSize, StreamMode::READ ); aStream.Seek ( STREAM_SEEK_TO_BEGIN ); - auto pSet = std::make_unique(SfxItemSet::makeFixedSfxItemSet >( *rDoc.GetPool()); + SID_SCPRINTOPTIONS, SID_SCPRINTOPTIONS>( *rDoc.GetPool())); SfxPrinter* pPrinter = pDocShell->GetPrinter(); bool bPreferPrinterPapersize = false; @@ -565,7 +565,7 @@ uno::Any SAL_CALL ScDocumentConfiguration::getPropertyValue( const OUString& aPr else if ( aPropertyName == SC_UNO_MODIFYPASSWORDINFO ) aRet <<= pDocShell->GetModifyPasswordInfo(); else if (aPropertyName == SC_UNO_MODIFYPASSWORDHASH) - aRet <<= pDocShell->GetModifyPasswordHash(); + aRet <<= static_cast(pDocShell->GetModifyPasswordHash()); else if (aPropertyName == SC_UNO_EMBED_FONTS) aRet <<= rDoc.IsEmbedFonts(); else if (aPropertyName == SC_UNO_EMBED_ONLY_USED_FONTS) diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index 83b1cd89a72c..ea572a82ebef 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -55,6 +55,8 @@ #include #include #include +#include +#include #include #include #include @@ -528,10 +530,6 @@ static OString getTabViewRenderState(const ScTabViewShell& rTabViewShell) OString aThemeName = OUStringToOString(rViewRenderingOptions.GetColorSchemeName(), RTL_TEXTENCODING_UTF8); aState.append(aThemeName); - sc::SheetViewID nSheetViewID = rTabViewShell.GetViewData().GetSheetViewID(); - if (nSheetViewID >= 0) - aState.append(";VS:" + OString::number(nSheetViewID)); - return aState.makeStringAndClear(); } @@ -602,7 +600,7 @@ void ScModelObj::paintTile( VirtualDevice& rDevice, // Fetch the document size and the tiled rendering area together, // because the tiled rendering area is not cheap to compute, and we want - // to pass it down to ScGridWindow::PaintFile to avoid computing twice. + // to pass it down to ScGridWindow::PaintTile to avoid computing twice. SCCOL nTiledRenderingAreaEndCol = 0; SCROW nTiledRenderingAreaEndRow = 0; Size aDocSize = getDocumentSize(nTiledRenderingAreaEndCol, nTiledRenderingAreaEndRow); @@ -659,17 +657,6 @@ OUString ScModelObj::getPartInfo( int nPart ) ScDocument& rDocument = pViewData->GetDocument(); const bool bIsVisible = rDocument.IsVisible(nPart); const bool bIsProtected = rDocument.IsTabProtected(nPart); - const sc::SheetViewID nSheetViewID = pViewData->GetSheetViewIDForSheet(nPart); - - bool nSheetViewSynced = true; - - if (auto pSheetViewManager = rDocument.GetSheetViewManager(nPart)) - { - if (auto pSheetView = pSheetViewManager->get(nSheetViewID)) - { - nSheetViewSynced = pSheetView->isSynced(); - } - } //FIXME: Implement IsSelected(). const bool bIsSelected = false; //pViewData->GetDocument()->IsSelected(nPart); @@ -679,17 +666,26 @@ OUString ScModelObj::getPartInfo( int nPart ) jsonWriter.put("visible", static_cast(bIsVisible)); jsonWriter.put("rtllayout", static_cast(bIsRTLLayout)); jsonWriter.put("protected", static_cast(bIsProtected)); - jsonWriter.put("sheetviewid", int32_t(nSheetViewID)); - jsonWriter.put("sheetviewsynced", uint32_t(nSheetViewSynced)); jsonWriter.put("selected", static_cast(bIsSelected)); + const sc::SheetViewID nSheetViewID = pViewData->GetSheetViewIDForSheet(nPart); + if (nSheetViewID != sc::DefaultSheetViewID) + { + jsonWriter.put("sheetviewid", int32_t(nSheetViewID)); + + SCTAB nDefaultViewTableNumber = rDocument.GetDefaultViewTableNumber(nPart); + sal_Int64 nDefaultViewHashCode = 0; + if (rDocument.GetHashCode(nDefaultViewTableNumber, nDefaultViewHashCode)) + jsonWriter.put("defaultviewhash", int64_t(nDefaultViewHashCode)); + } + OUString tabName; pViewData->GetDocument().GetName(nPart, tabName); jsonWriter.put("name", tabName); - sal_Int64 hashCode; - pViewData->GetDocument().GetHashCode(nPart, hashCode); - jsonWriter.put("hash", hashCode); + sal_Int64 hashCode = 0; + if (pViewData->GetDocument().GetHashCode(nPart, hashCode)) + jsonWriter.put("hash", hashCode); Size lastColRow = getDataArea(nPart); jsonWriter.put("lastcolumn", lastColRow.getWidth()); @@ -866,8 +862,8 @@ void ScModelObj::postMouseEvent(int nType, int nX, int nY, int nCount, int nButt pGridWindow->GrabFocus(); // Calc operates in pixels... - const Point aPosition(nX * pViewData->GetPPTX() + pGridWindow->GetOutOffXPixel(), - nY * pViewData->GetPPTY() + pGridWindow->GetOutOffYPixel()); + const Point aPosition(nX * pViewData->GetPPTX() + pGridWindow->GetDeviceOriginX(), + nY * pViewData->GetPPTY() + pGridWindow->GetDeviceOriginY()); VclEventId aEvent = VclEventId::NONE; MouseEvent aData(aPosition, nCount, MouseEventModifiers::SIMPLECLICK, nButtons, nModifier); @@ -1284,7 +1280,14 @@ void ScModelObj::getPostIts(tools::JsonWriter& rJsonWriter) rJsonWriter.put("tab", aNote.maPos.Tab()); rJsonWriter.put("author", aNote.mpNote->GetAuthor()); rJsonWriter.put("dateTime", aNote.mpNote->GetDate()); - rJsonWriter.put("text", aNote.mpNote->GetText()); + if (const auto* pData = aNote.mpNote->GetThreadedCommentData()) + { + rJsonWriter.put("text", pData->maRoot.maText); + rJsonWriter.put("threaded", "true"); + rJsonWriter.put("resolved", aNote.mpNote->IsResolved() ? "true" : "false"); + } + else + rJsonWriter.put("text", aNote.mpNote->GetText()); // Calculating the cell cursor position if (ScViewData* pViewData = ScDocShell::GetViewData()) @@ -1552,7 +1555,7 @@ void ScModelObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) else if ( nId == SfxHintId::DataChanged ) { // cached data for rendering become invalid when contents change - // (if a broadcast is added to SetDrawModified, is has to be tested here, too) + // (if a broadcast is added to SetDrawModified, it has to be tested here, too) pPrintFuncCache.reset(); m_pPrintState.reset(); @@ -1905,6 +1908,19 @@ bool ScModelObj::FillRenderMarkData( const uno::Any& aSelection, return bDone; } +// The visible sheets of the document, in sheet order. +static std::vector lcl_GetVisibleTabs(const ScDocument& rDoc) +{ + std::vector aTabs; + SCTAB nTabCount = rDoc.GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; ++nTab) + { + if (rDoc.IsVisible(nTab)) + aTabs.push_back(nTab); + } + return aTabs; +} + sal_Int32 SAL_CALL ScModelObj::getRendererCount(const uno::Any& aSelection, const uno::Sequence& rOptions) { @@ -1971,7 +1987,7 @@ sal_Int32 SAL_CALL ScModelObj::getRendererCount(const uno::Any& aSelection, if (bSinglePageSheets) { - return pDocShell->GetDocument().GetTableCount(); + return static_cast(lcl_GetVisibleTabs(pDocShell->GetDocument()).size()); } bool bIsPrintEvenPages = (nEOContent != 1 && nContent == 0) || nContent != 0; @@ -2050,8 +2066,12 @@ uno::Sequence SAL_CALL ScModelObj::getRenderer( sal_Int32 } } + std::vector aSinglePageTabs; if (bSinglePageSheets) - nTotalPages = pDocShell->GetDocument().GetTableCount(); + { + aSinglePageTabs = lcl_GetVisibleTabs(pDocShell->GetDocument()); + nTotalPages = aSinglePageTabs.size(); + } sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages ); @@ -2099,7 +2119,11 @@ uno::Sequence SAL_CALL ScModelObj::getRenderer( sal_Int32 SCTAB nTab; if (bSinglePageSheets) - nTab = nSelRenderer; + { + if (nSelRenderer < 0 || o3tl::make_unsigned(nSelRenderer) >= aSinglePageTabs.size()) + throw lang::IllegalArgumentException(); + nTab = aSinglePageTabs[nSelRenderer]; + } else if ( !maValidPages.empty() ) nTab = pPrintFuncCache->GetTabForPage( maValidPages.at( nRenderer )-1 ); else @@ -2378,8 +2402,12 @@ static void lcl_PDFExportBookmarkHelper(OutputDevice* pDev, ScDocument& rDoc, // to get the target rectangle in pixels. assert(aLocationPixel.GetWidth() != 0 && aLocationPixel.GetHeight() != 0); - double fScaleX = double(aLocationPixel.GetWidth()) / aLocationMM.GetWidth(); - double fScaleY = double(aLocationPixel.GetHeight()) / aLocationMM.GetHeight(); + double fScaleX(0.0); + if (aLocationMM.GetWidth()) + fScaleX = double(aLocationPixel.GetWidth()) / aLocationMM.GetWidth(); + double fScaleY(0.0); + if (aLocationMM.GetHeight()) + fScaleY = double(aLocationPixel.GetHeight()) / aLocationMM.GetHeight(); tools::Long nX1 = aLocationPixel.Left() @@ -2483,7 +2511,7 @@ static void lcl_PDFExportMediaShapeScreen(const OutputDevice* pDev, const std::u SfxStyleSheetBase* pStyleSheet = pStylePool->Find(rDoc.GetPageStyle(nTab), SfxStyleFamily::Page); SfxItemSet* pItemSet = &pStyleSheet->GetItemSet(); - tools::Long nLeftMargin(pItemSet->Get(ATTR_LRSPACE).ResolveLeft({})); + tools::Long nLeftMargin(pItemSet->Get(ATTR_LRSPACE).ResolveLeft()); nLeftMargin = o3tl::convert(nLeftMargin, o3tl::Length::twip, o3tl::Length::mm100); tools::Long nTopMargin(pItemSet->Get(ATTR_ULSPACE).GetUpper()); @@ -2637,8 +2665,12 @@ void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelec } } + std::vector aSinglePageTabs; if (bSinglePageSheets) - nTotalPages = pDocShell->GetDocument().GetTableCount(); + { + aSinglePageTabs = lcl_GetVisibleTabs(pDocShell->GetDocument()); + nTotalPages = aSinglePageTabs.size(); + } // if no pages counted then user must be trying to print sheet/selection without any content (i.e empty) if (nTotalPages == 0) @@ -2662,7 +2694,13 @@ void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelec ScDocument& rDoc = pDocShell->GetDocument(); SCTAB nTab; - if (!maValidPages.empty()) + if (bSinglePageSheets) + { + if (nSelRenderer < 0 || o3tl::make_unsigned(nSelRenderer) >= aSinglePageTabs.size()) + throw lang::IllegalArgumentException(); + nTab = aSinglePageTabs[nSelRenderer]; + } + else if (!maValidPages.empty()) nTab = pPrintFuncCache->GetTabForPage(maValidPages.at(nRenderer) - 1); else nTab = pPrintFuncCache->GetTabForPage(nRenderer); @@ -2678,13 +2716,13 @@ void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelec { SCCOL nStartCol; SCROW nStartRow; - rDoc.GetDataStart( nSelRenderer, nStartCol, nStartRow ); + rDoc.GetDataStart(nTab, nStartCol, nStartRow); SCCOL nEndCol; SCROW nEndRow; - rDoc.GetPrintArea( nSelRenderer, nEndCol, nEndRow ); + rDoc.GetPrintArea(nTab, nEndCol, nEndRow); - aRange.aStart = ScAddress(nStartCol, nStartRow, nSelRenderer); - aRange.aEnd = ScAddress(nEndCol, nEndRow, nSelRenderer); + aRange.aStart = ScAddress(nStartCol, nStartRow, nTab); + aRange.aEnd = ScAddress(nEndCol, nEndRow, nTab); tools::Rectangle aMMRect( pDocShell->GetDocument().GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(), @@ -2692,9 +2730,9 @@ void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelec //Set visible tab SCTAB nVisTab = rDoc.GetVisibleTab(); - if (nVisTab != nSelRenderer) + if (nVisTab != nTab) { - nVisTab = nSelRenderer; + nVisTab = nTab; rDoc.SetVisibleTab(nVisTab); } @@ -4435,7 +4473,7 @@ sal_Int32 ScTableSheetsObj::importSheet( ScModelObj* pObj = comphelper::getFromUnoTunnel(xDocSrc); ScDocShell* pDocShellSrc = static_cast(pObj->GetEmbeddedObject()); - // SourceSheet Position and does srcName exists ? + // SourceSheet Position and does srcName exist ? SCTAB nIndexSrc; if ( !pDocShellSrc->GetDocument().GetTable( srcName, nIndexSrc ) ) throw lang::IllegalArgumentException(); diff --git a/sc/source/ui/unoobj/fielduno.cxx b/sc/source/ui/unoobj/fielduno.cxx index 0adbee4fee03..a0f22e41911e 100644 --- a/sc/source/ui/unoobj/fielduno.cxx +++ b/sc/source/ui/unoobj/fielduno.cxx @@ -192,8 +192,8 @@ ScUnoEditEngine::ScUnoEditEngine(ScEditEngineDefaulter* pSource) , nFieldPos(0) , nFieldIndex(0) { - std::unique_ptr pData = pSource->CreateTextObject(); - SetTextCurrentDefaults( *pData ); + EditTextObject aData = pSource->CreateTextObject(); + SetTextCurrentDefaults( aData ); } OUString ScUnoEditEngine::CalcFieldValue( const SvxFieldItem& rField, diff --git a/sc/source/ui/unoobj/filtuno.cxx b/sc/source/ui/unoobj/filtuno.cxx index 841c328592b3..1763dfb72640 100644 --- a/sc/source/ui/unoobj/filtuno.cxx +++ b/sc/source/ui/unoobj/filtuno.cxx @@ -61,30 +61,30 @@ constexpr OUStringLiteral SC_UNONAME_FILTERNAME = u"FilterName"; constexpr OUString SC_UNONAME_FILTEROPTIONS = u"FilterOptions"_ustr; constexpr OUStringLiteral SC_UNONAME_INPUTSTREAM = u"InputStream"; -constexpr OUString DBF_CHAR_SET = u"CharSet"_ustr; +constexpr OUString DBF_ENCODING = u"Encoding"_ustr; constexpr OUString DBF_SEP_PATH_IMPORT = u"Office.Calc/Dialogs/DBFImport"_ustr; constexpr OUString DBF_SEP_PATH_EXPORT = u"Office.Calc/Dialogs/DBFExport"_ustr; namespace { - enum class charsetSource + enum class encodingSource { - charset_from_file, - charset_from_user_setting, - charset_default + encoding_from_file, + encoding_from_user_setting, + encoding_default }; - charsetSource load_CharSet(rtl_TextEncoding &nCharSet, bool bExport, SvStream* dbf_Stream) + encodingSource load_Encoding(rtl_TextEncoding &nEncoding, bool bExport, SvStream* dbf_Stream) { - if (dbf_Stream && dbfReadCharset(nCharSet, dbf_Stream)) + if (dbf_Stream && dbfReadEncoding(nEncoding, dbf_Stream)) { - return charsetSource::charset_from_file; + return encodingSource::encoding_from_file; } Sequence aValues; const Any *pProperties; - Sequence aNames { DBF_CHAR_SET }; + Sequence aNames { DBF_ENCODING }; ScLinkConfigItem aItem( bExport ? DBF_SEP_PATH_EXPORT : DBF_SEP_PATH_IMPORT ); aValues = aItem.GetProperties( aNames ); @@ -96,30 +96,30 @@ namespace pProperties[0] >>= nChar; if( nChar >= 0) { - nCharSet = static_cast(nChar); - return charsetSource::charset_from_user_setting; + nEncoding = static_cast(nChar); + return encodingSource::encoding_from_user_setting; } } // Default choice - nCharSet = RTL_TEXTENCODING_IBM_850; - return charsetSource::charset_default; + nEncoding = RTL_TEXTENCODING_IBM_850; + return encodingSource::encoding_default; } - void save_CharSet( rtl_TextEncoding nCharSet, bool bExport ) + void save_Encoding( rtl_TextEncoding nEncoding, bool bExport ) { Sequence aValues; Any *pProperties; - Sequence aNames { DBF_CHAR_SET }; + Sequence aNames { DBF_ENCODING }; ScLinkConfigItem aItem( bExport ? DBF_SEP_PATH_EXPORT : DBF_SEP_PATH_IMPORT ); aValues = aItem.GetProperties( aNames ); pProperties = aValues.getArray(); - pProperties[0] <<= static_cast(nCharSet); + pProperties[0] <<= static_cast(nEncoding); aItem.PutProperties(aNames, aValues); } -} +} // namespace ScFilterOptionsObj::ScFilterOptionsObj() : bExport( false ) @@ -186,26 +186,31 @@ sal_Int16 SAL_CALL ScFilterOptionsObj::execute() INetURLObject aURL( aFileName ); // tdf#132421 - don't URL encode filename for the import ASCII dialog title OUString aPrivDatName(aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset)); - std::unique_ptr pInStream; - if ( xInputStream.is() ) - pInStream = utl::UcbStreamHelper::CreateStream( xInputStream ); - - ScopedVclPtr pDlg(pFact->CreateScImportAsciiDlg(Application::GetFrameWeld(xDialogParent), aPrivDatName, - pInStream.get(), SC_IMPORTFILE)); - - bool bShow; - // The "ShowFilterDialog" flag is passed from SfxApplication::OpenDocExec_Impl - if (!(css::uno::getCurrentContext()->getValueByName(u"ShowFilterDialog"_ustr) >>= bShow)) - bShow = utl::isShowFilterOptionsDialog(aFilterString); - const bool bOk = !bShow || pDlg->Execute() == RET_OK; - - if (bOk) + std::unique_ptr pInStream(utl::UcbStreamHelper::CreateStream( xInputStream )); + if ( pInStream ) { - ScAsciiOptions aOptions; - pDlg->GetOptions( aOptions ); - pDlg->SaveParameters(); - aFilterOptions = aOptions.WriteToString(); - nRet = ui::dialogs::ExecutableDialogResults::OK; + // by default, we don't know what's the encoding of the csv file + // see sc/source/ui/dbgui/scuiasciiopt.cxx, ScImportAsciiDlg ctr + // there's an explanation of the different cases + pInStream->SetStreamEncoding(RTL_TEXTENCODING_DONTKNOW); + + ScopedVclPtr pDlg(pFact->CreateScImportAsciiDlg(Application::GetFrameWeld(xDialogParent), aPrivDatName, + pInStream.get(), SC_IMPORTFILE)); + + bool bShow; + // The "ShowFilterDialog" flag is passed from SfxApplication::OpenDocExec_Impl + if (!(css::uno::getCurrentContext()->getValueByName(u"ShowFilterDialog"_ustr) >>= bShow)) + bShow = utl::isShowFilterOptionsDialog(aFilterString); + const bool bOk = !bShow || pDlg->Execute() == RET_OK; + + if (bOk) + { + ScAsciiOptions aOptions; + pDlg->GetOptions( aOptions ); + pDlg->SaveParameters(); + aFilterOptions = aOptions.WriteToString(); + nRet = ui::dialogs::ExecutableDialogResults::OK; + } } } else if (aFilterString == SC_HTML_WEBQ_FILTER_NAME || aFilterString == SC_HTML_FILTER_NAME) @@ -288,13 +293,13 @@ sal_Int16 SAL_CALL ScFilterOptionsObj::execute() std::unique_ptr pInStream; if ( xInputStream.is() ) pInStream = utl::UcbStreamHelper::CreateStream( xInputStream ); - switch(load_CharSet( eEncoding, bExport, pInStream.get())) + switch(load_Encoding( eEncoding, bExport, pInStream.get())) { - case charsetSource::charset_from_file: + case encodingSource::encoding_from_file: skipDialog = true; break; - case charsetSource::charset_from_user_setting: - case charsetSource::charset_default: + case encodingSource::encoding_from_user_setting: + case encodingSource::encoding_default: break; } bDBEnc = true; @@ -338,7 +343,7 @@ sal_Int16 SAL_CALL ScFilterOptionsObj::execute() { pDlg->SaveImportOptions(); pDlg->GetImportOptions( aOptions ); - save_CharSet( aOptions.eCharSet, bExport ); + save_Encoding( aOptions.eEncoding, bExport ); nRet = ui::dialogs::ExecutableDialogResults::OK; } } diff --git a/sc/source/ui/unoobj/linkuno.cxx b/sc/source/ui/unoobj/linkuno.cxx index 80b8e6ee0329..4921570aefc8 100644 --- a/sc/source/ui/unoobj/linkuno.cxx +++ b/sc/source/ui/unoobj/linkuno.cxx @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -1421,13 +1422,13 @@ Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRo { case svDouble: { - double fVal = pToken->GetDouble(); + double fVal = static_cast(pToken)->GetDouble(); aValue <<= fVal; } break; case svString: { - OUString aVal = pToken->GetString().getString(); + OUString aVal = static_cast(pToken)->GetString().getString(); aValue <<= aVal; } break; @@ -1611,6 +1612,22 @@ uno::Reference< sheet::XExternalDocLink > SAL_CALL ScExternalDocLinksObj::addDoc return aDocLink; } +uno::Reference + SAL_CALL ScExternalDocLinksObj::addSpecialDocLink(const OUString& aDocName, sal_Int16 nLinkType) +{ + SolarMutexGuard aGuard; + sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocName); + + if (nLinkType == sheet::ExternalLinkRelType::XL_STARTUP) + mpRefMgr->setXlStartup(nFileId); + else if (nLinkType == sheet::ExternalLinkRelType::PATH_MISSING) + mpRefMgr->setPathMissing(nFileId); + + uno::Reference aDocLink( + new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId)); + return aDocLink; +} + Any SAL_CALL ScExternalDocLinksObj::getByName(const OUString &aName) { SolarMutexGuard aGuard; diff --git a/sc/source/ui/unoobj/miscuno.cxx b/sc/source/ui/unoobj/miscuno.cxx index c0eba32bcd21..fa5f9cf91e28 100644 --- a/sc/source/ui/unoobj/miscuno.cxx +++ b/sc/source/ui/unoobj/miscuno.cxx @@ -88,6 +88,24 @@ sal_Int32 ScUnoHelpFunctions::GetLongProperty( const uno::Reference& xProp, + const OUString& rName, double fDefault) +{ + double fRet = fDefault; + if (xProp.is()) + { + try + { + xProp->getPropertyValue(rName) >>= fRet; + } + catch (uno::Exception&) + { + // keep default + } + } + return fRet; +} + sal_Int32 ScUnoHelpFunctions::GetEnumPropertyImpl( const uno::Reference& xProp, const OUString& rName, sal_Int32 nDefault ) { diff --git a/sc/source/ui/unoobj/nameuno.cxx b/sc/source/ui/unoobj/nameuno.cxx index 388c07e96120..14aac447a0ab 100644 --- a/sc/source/ui/unoobj/nameuno.cxx +++ b/sc/source/ui/unoobj/nameuno.cxx @@ -120,7 +120,7 @@ ScRangeData* ScNamedRangeObj::GetRangeData_Impl() if (nTab >= 0) pNames = pDocShell->GetDocument().GetRangeName(nTab); else - pNames = pDocShell->GetDocument().GetRangeName(); + pNames = &pDocShell->GetDocument().GetRangeName(); if (pNames) { pRet = pNames->findByUpperName(ScGlobal::getCharClass().uppercase(aName)); @@ -145,7 +145,7 @@ SCTAB ScNamedRangeObj::GetTab_Impl() return nTab; } else - return -1;//global range name + return -1; // global range name } // sheet::XNamedRange @@ -163,7 +163,7 @@ void ScNamedRangeObj::Modify_Impl( const OUString* pNewName, const ScTokenArray* if (nTab >= 0) pNames = rDoc.GetRangeName(nTab); else - pNames = rDoc.GetRangeName(); + pNames = &rDoc.GetRangeName(); if (!pNames) return; @@ -190,25 +190,21 @@ void ScNamedRangeObj::Modify_Impl( const OUString* pNewName, const ScTokenArray* if (pNewType) nType = *pNewType; - ScRangeData* pNew = nullptr; + std::unique_ptr pNew; if (pNewTokens) - pNew = new ScRangeData( rDoc, aInsName, *pNewTokens, aPos, nType ); + pNew.reset(new ScRangeData( rDoc, aInsName, *pNewTokens, aPos, nType )); else - pNew = new ScRangeData( rDoc, aInsName, aContent, aPos, nType, eGrammar ); + pNew.reset(new ScRangeData( rDoc, aInsName, aContent, aPos, nType, eGrammar )); pNew->SetIndex( pOld->GetIndex() ); pNewRanges->erase(*pOld); - if (pNewRanges->insert(pNew)) + if (pNewRanges->insert(std::move(pNew))) { pDocShell->GetDocFunc().SetNewRangeNames(std::move(pNewRanges), mxParent->IsModifyAndBroadcast(), nTab); aName = aInsName; //! broadcast? } - else - { - pNew = nullptr; //! uno::Exception/Error or something - } } OUString SAL_CALL ScNamedRangeObj::getName() @@ -487,17 +483,13 @@ void SAL_CALL ScNamedRangesObj::addNewByName( const OUString& aName, { std::unique_ptr pNewRanges(new ScRangeName( *pNames )); // GRAM_API for API compatibility. - ScRangeData* pNew = new ScRangeData( rDoc, aName, aContent, - aPos, nNewType,formula::FormulaGrammar::GRAM_API ); - if ( pNewRanges->insert(pNew) ) + std::unique_ptr pNew(new ScRangeData( rDoc, aName, aContent, + aPos, nNewType,formula::FormulaGrammar::GRAM_API )); + if ( pNewRanges->insert(std::move(pNew)) ) { pDocShell->GetDocFunc().SetNewRangeNames(std::move(pNewRanges), mbModifyAndBroadcast, GetTab_Impl()); bDone = true; } - else - { - pNew = nullptr; - } } } } @@ -785,12 +777,10 @@ rtl::Reference ScGlobalNamedRangesObj::GetObjectByIndex_Impl(sa if (!pDocShell) return nullptr; - ScRangeName* pNames = pDocShell->GetDocument().GetRangeName(); - if (!pNames) - return nullptr; + ScRangeName& rNames = pDocShell->GetDocument().GetRangeName(); sal_uInt16 nPos = 0; - for (const auto& rName : *pNames) + for (const auto& rName : rNames) { if (lcl_UserVisibleName(*rName.second)) { @@ -811,7 +801,7 @@ rtl::Reference ScGlobalNamedRangesObj::GetObjectByName_Impl(con ScRangeName* ScGlobalNamedRangesObj::GetRangeName_Impl() { - return pDocShell->GetDocument().GetRangeName(); + return &pDocShell->GetDocument().GetRangeName(); } SCTAB ScGlobalNamedRangesObj::GetTab_Impl() diff --git a/sc/source/ui/unoobj/scdetect.cxx b/sc/source/ui/unoobj/scdetect.cxx index c52427b013ad..e729c5a53f30 100644 --- a/sc/source/ui/unoobj/scdetect.cxx +++ b/sc/source/ui/unoobj/scdetect.cxx @@ -121,7 +121,7 @@ bool detectThisFormat(SvStream& rStr, const sal_uInt16* pSearch) else if( nMuster & M_ALT(0) ) { // alternative Bytes sal_uInt8 nCntAlt = static_cast(nMuster); - bSync = false; // first unsynchron + bSync = false; // first unsynchronized while( nCntAlt > 0 ) { pSearch++; diff --git a/sc/source/ui/unoobj/targuno.cxx b/sc/source/ui/unoobj/targuno.cxx index f5b8ddffa3c1..9b6d3531abf0 100644 --- a/sc/source/ui/unoobj/targuno.cxx +++ b/sc/source/ui/unoobj/targuno.cxx @@ -40,6 +40,8 @@ #include #include +#include + using namespace ::com::sun::star; const TranslateId aTypeResIds[SC_LINKTARGETTYPE_COUNT] = @@ -114,10 +116,7 @@ uno::Sequence SAL_CALL ScLinkTargetTypesObj::getElementNames() sal_Bool SAL_CALL ScLinkTargetTypesObj::hasByName(const OUString& aName) { - for (const auto & i : aNames) - if ( i == aName ) - return true; - return false; + return std::ranges::find(aNames, aName) != std::end(aNames); } // container::XElementAccess diff --git a/sc/source/ui/unoobj/textuno.cxx b/sc/source/ui/unoobj/textuno.cxx index e80d6ed1ec3b..884990dce6ea 100644 --- a/sc/source/ui/unoobj/textuno.cxx +++ b/sc/source/ui/unoobj/textuno.cxx @@ -144,7 +144,7 @@ void ScHeaderFooterContentObj::Init( const EditTextObject* pLeft, ScHeaderFooterTextData::ScHeaderFooterTextData( unotools::WeakReference xContent, ScHeaderFooterPart nP, const EditTextObject* pTextObj) : - mpTextObj(pTextObj ? pTextObj->Clone() : nullptr), + mpTextObj(pTextObj ? std::make_unique(*pTextObj) : nullptr), xContentObj(std::move( xContent )), nPart( nP ), bDataValid(false) @@ -184,7 +184,7 @@ SvxTextForwarder* ScHeaderFooterTextData::GetTextForwarder() // no access to ScDocument, use temporary default CellAttributeHelper // was: "use global pool from module" which is usually ScMessagePool // and gets set in ScTabViewObj::SelectionChanged() by - // ScFormatShell::ScFormatShell which calls + // ScFormatShell::ScFormatShell which calls // SetPool( &pTabViewShell->GetPool() ); pTmp.reset(new CellAttributeHelper(ScModule::get()->GetPool())); pCellAttributeDefault = &pTmp->getDefaultCellAttribute(); @@ -221,13 +221,13 @@ void ScHeaderFooterTextData::UpdateData() { if (pEditEngine) { - mpTextObj = pEditEngine->CreateTextObject(); + mpTextObj = std::make_unique(pEditEngine->CreateTextObject()); } } void ScHeaderFooterTextData::UpdateData(EditEngine& rEditEngine) { - mpTextObj = rEditEngine.CreateTextObject(); + mpTextObj = std::make_unique(rEditEngine.CreateTextObject()); bDataValid = false; } @@ -485,7 +485,7 @@ uno::Reference SAL_CALL ScHeaderFooterTextObj::ge uno::Reference SAL_CALL ScHeaderFooterTextObj::getTextFieldMasters() { - // this does not exists in Calc (?) + // this does not exist in Calc (?) return nullptr; } @@ -720,7 +720,7 @@ void ScEditEngineTextObj::SetText( const EditTextObject& rTextObject ) SetSelection( aSel ); } -std::unique_ptr ScEditEngineTextObj::CreateTextObject() +EditTextObject ScEditEngineTextObj::CreateTextObject() { return GetEditEngine()->CreateTextObject(); } diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx index b8e4e133a113..1ba729af97c7 100644 --- a/sc/source/ui/unoobj/tokenuno.cxx +++ b/sc/source/ui/unoobj/tokenuno.cxx @@ -402,16 +402,17 @@ void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc, case svByte: // Only the count of spaces is stored as "long". Parameter count is ignored. if ( eOpCode == ocSpaces ) - rAPI.Data <<= static_cast(rToken.GetByte()); + rAPI.Data <<= static_cast(static_cast(rToken).GetByte()); else if (eOpCode == ocWhitespace) { + auto const & rSToken = static_cast(rToken); // Convention is one character repeated. - if (rToken.GetByte() == 1) - rAPI.Data <<= OUString( rToken.GetChar()); + if (rSToken.GetByte() == 1) + rAPI.Data <<= OUString( rSToken.GetChar()); else { - OUStringBuffer aBuf( rToken.GetByte()); - comphelper::string::padToLength( aBuf, rToken.GetByte(), rToken.GetChar()); + OUStringBuffer aBuf(rSToken.GetByte()); + comphelper::string::padToLength( aBuf, rSToken.GetByte(), rSToken.GetChar()); rAPI.Data <<= aBuf.makeStringAndClear(); } } @@ -419,36 +420,36 @@ void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc, rAPI.Data.clear(); // no data break; case formula::svDouble: - rAPI.Data <<= rToken.GetDouble(); + rAPI.Data <<= static_cast(rToken).GetDouble(); break; case formula::svString: - rAPI.Data <<= rToken.GetString().getString(); + rAPI.Data <<= static_cast(rToken).GetString().getString(); break; case svExternal: // Function name is stored as string. // Byte (parameter count) is ignored. - rAPI.Data <<= rToken.GetExternal(); + rAPI.Data <<= static_cast(rToken).GetExternal(); break; case svSingleRef: { sheet::SingleReference aSingleRef; - lcl_SingleRefToApi( aSingleRef, *rToken.GetSingleRef() ); + lcl_SingleRefToApi( aSingleRef, static_cast(rToken).GetSingleRef() ); rAPI.Data <<= aSingleRef; } break; case formula::svDoubleRef: { sheet::ComplexReference aCompRef; - lcl_SingleRefToApi( aCompRef.Reference1, *rToken.GetSingleRef() ); - lcl_SingleRefToApi( aCompRef.Reference2, *rToken.GetSingleRef2() ); + lcl_SingleRefToApi( aCompRef.Reference1, static_cast(rToken).GetSingleRef() ); + lcl_SingleRefToApi( aCompRef.Reference2, static_cast(rToken).GetSingleRef2() ); rAPI.Data <<= aCompRef; } break; case svIndex: { - const ScTableRefToken* pTR; - if (rToken.GetOpCode() == ocTableRef && (pTR = dynamic_cast(&rToken))) + if (rToken.GetOpCode() == ocTableRef) { + const ScTableRefToken* pTR = static_cast(&rToken); sheet::TableRefToken aTableRefToken; aTableRefToken.Index = static_cast( pTR->GetIndex()); aTableRefToken.Item = static_cast( pTR->GetItem()); @@ -461,12 +462,12 @@ void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc, switch (pRef->GetType()) { case svSingleRef: - lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, *pRef->GetSingleRef()); + lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, static_cast(pRef)->GetSingleRef()); aTableRefToken.Reference.Reference2 = aTableRefToken.Reference.Reference1; break; case svDoubleRef: - lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, *pRef->GetSingleRef()); - lcl_SingleRefToApi( aTableRefToken.Reference.Reference2, *pRef->GetSingleRef2()); + lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, static_cast(pRef)->GetSingleRef()); + lcl_SingleRefToApi( aTableRefToken.Reference.Reference2, static_cast(pRef)->GetSingleRef2()); break; default: ; // nothing @@ -476,27 +477,29 @@ void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc, } else { + auto const & rIndexToken = static_cast(rToken); sheet::NameToken aNameToken; - aNameToken.Index = static_cast( rToken.GetIndex() ); - aNameToken.Sheet = rToken.GetSheet(); + aNameToken.Index = static_cast( rIndexToken.GetIndex() ); + aNameToken.Sheet = rIndexToken.GetSheet(); rAPI.Data <<= aNameToken; } } break; case svMatrix: - if (!ScRangeToSequence::FillMixedArray( rAPI.Data, rToken.GetMatrix(), true)) + if (!ScRangeToSequence::FillMixedArray( rAPI.Data, static_cast(rToken).GetMatrix(), true)) rAPI.Data.clear(); break; case svExternalSingleRef: { + const auto & rESRToken = static_cast(rToken); sheet::SingleReference aSingleRef; - lcl_ExternalRefToApi( aSingleRef, *rToken.GetSingleRef() ); + lcl_ExternalRefToApi( aSingleRef, rESRToken.GetSingleRef() ); size_t nCacheId; rDoc.GetExternalRefManager()->getCacheTable( - rToken.GetIndex(), rToken.GetString().getString(), false, &nCacheId); + rESRToken.GetFileId(), rESRToken.GetTableName().getString(), false, &nCacheId); aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId ); sheet::ExternalReference aExtRef; - aExtRef.Index = rToken.GetIndex(); + aExtRef.Index = rESRToken.GetFileId(); aExtRef.Reference <<= aSingleRef; rAPI.Data <<= aExtRef; eOpCode = ocPush; @@ -504,19 +507,20 @@ void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc, break; case svExternalDoubleRef: { + const auto & rEDRToken = static_cast(rToken); sheet::ComplexReference aComplRef; - lcl_ExternalRefToApi( aComplRef.Reference1, *rToken.GetSingleRef() ); - lcl_ExternalRefToApi( aComplRef.Reference2, *rToken.GetSingleRef2() ); + lcl_ExternalRefToApi( aComplRef.Reference1, rEDRToken.GetSingleRef() ); + lcl_ExternalRefToApi( aComplRef.Reference2, rEDRToken.GetSingleRef2() ); size_t nCacheId; rDoc.GetExternalRefManager()->getCacheTable( - rToken.GetIndex(), rToken.GetString().getString(), false, &nCacheId); + rEDRToken.GetFileId(), rEDRToken.GetTableName().getString(), false, &nCacheId); aComplRef.Reference1.Sheet = static_cast< sal_Int32 >( nCacheId ); // NOTE: This assumes that cached sheets are in consecutive order! aComplRef.Reference2.Sheet = aComplRef.Reference1.Sheet + - (rToken.GetSingleRef2()->Tab() - rToken.GetSingleRef()->Tab()); + (rEDRToken.GetSingleRef2().Tab() - rEDRToken.GetSingleRef().Tab()); sheet::ExternalReference aExtRef; - aExtRef.Index = rToken.GetIndex(); + aExtRef.Index = rEDRToken.GetFileId(); aExtRef.Reference <<= aComplRef; rAPI.Data <<= aExtRef; eOpCode = ocPush; @@ -524,9 +528,10 @@ void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc, break; case svExternalName: { + auto const & rExtNameToken = static_cast(rToken); sheet::ExternalReference aExtRef; - aExtRef.Index = rToken.GetIndex(); - aExtRef.Reference <<= rToken.GetString().getString(); + aExtRef.Index = rExtNameToken.GetFileId(); + aExtRef.Reference <<= rExtNameToken.GetName().getString(); rAPI.Data <<= aExtRef; eOpCode = ocPush; } @@ -534,8 +539,35 @@ void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc, default: SAL_WARN("sc", "ScTokenConversion::ConvertToTokenSequence: unhandled token type " << StackVarEnumToString(rToken.GetType())); [[fallthrough]]; + case svError: + switch (static_cast(rToken).GetError()) + { + case FormulaError::NoCode: + eOpCode = ocErrNull; + break; + case FormulaError::DivisionByZero: + eOpCode = ocErrDivZero; + break; + case FormulaError::NoValue: + eOpCode = ocErrValue; + break; + case FormulaError::NoRef: + eOpCode = ocErrRef; + break; + case FormulaError::NoName: + eOpCode = ocErrName; + break; + case FormulaError::IllegalFPOperation: + eOpCode = ocErrNum; + break; + case FormulaError::NotAvailable: + eOpCode = ocErrNA; + break; + default: + break; + } + [[fallthrough]]; case svJump: // occurs with ocIf, ocChoose - case svError: // seems to be fairly common, and probably not exceptional and not worth a warning? case svMissing: // occurs with ocMissing case svSep: // occurs with ocSep, ocOpen, ocClose, ocArray* rAPI.Data.clear(); // no data diff --git a/sc/source/ui/unoobj/viewuno.cxx b/sc/source/ui/unoobj/viewuno.cxx index 94c8de4458eb..424881622cfb 100644 --- a/sc/source/ui/unoobj/viewuno.cxx +++ b/sc/source/ui/unoobj/viewuno.cxx @@ -270,7 +270,7 @@ table::CellRangeAddress SAL_CALL ScViewPaneBase::getVisibleRange() SCROW nVisY = rViewData.VisibleCellsY( eWhichV ); if (!nVisX) nVisX = 1; // there has to be something in the range if (!nVisY) nVisY = 1; - aAdr.Sheet = rViewData.CurrentTabForData(); + aAdr.Sheet = rViewData.GetTabNumber(); aAdr.StartColumn = rViewData.GetPosX( eWhichH ); aAdr.StartRow = rViewData.GetPosY( eWhichV ); aAdr.EndColumn = aAdr.StartColumn + nVisX - 1; @@ -397,7 +397,7 @@ awt::Rectangle ScViewPaneBase::GetVisArea() const SC_SPLIT_TOP : SC_SPLIT_BOTTOM; ScAddress aCell(pViewShell->GetViewData().GetPosX(eWhichH), pViewShell->GetViewData().GetPosY(eWhichV), - pViewShell->GetViewData().CurrentTabForData()); + pViewShell->GetViewData().GetTabNumber()); tools::Rectangle aCellRect( rDoc.GetMMRect( aCell.Col(), aCell.Row(), aCell.Col(), aCell.Row(), aCell.Tab() ) ); Size aVisSize( pWindow->PixelToLogic( pWindow->GetSizePixel(), pWindow->GetDrawMapMode( true ) ) ); Point aVisPos( aCellRect.TopLeft() ); @@ -456,7 +456,7 @@ ScTabViewObj::ScTabViewObj( ScTabViewShell* pViewSh ) : mbLeftMousePressed(false) { if (pViewSh) - nPreviousTab = pViewSh->GetViewData().CurrentTabForData(); + nPreviousTab = pViewSh->GetViewData().GetTabNumber(); } ScTabViewObj::~ScTabViewObj() @@ -557,7 +557,7 @@ void ScTabViewObj::SheetChanged( bool bSameTabButMoved ) sheet::ActivationEvent aEvent; uno::Reference< sheet::XSpreadsheetView > xView(this); aEvent.Source.set(xView, uno::UNO_QUERY); - aEvent.ActiveSheet = new ScTableSheetObj(pDocSh, rViewData.CurrentTabForData()); + aEvent.ActiveSheet = new ScTableSheetObj(pDocSh, rViewData.GetTabNumber()); // Listener's handler may remove it from the listeners list for (size_t i = aActivationListeners.size(); i > 0; --i) { @@ -574,7 +574,7 @@ void ScTabViewObj::SheetChanged( bool bSameTabButMoved ) /* Handle sheet events, but do not trigger event handlers, if the old active sheet gets re-activated after inserting/deleting/moving a sheet. */ - SCTAB nNewTab = rViewData.CurrentTabForData(); + SCTAB nNewTab = rViewData.GetTabNumber(); if ( !bSameTabButMoved && (nNewTab != nPreviousTab) ) { lcl_CallActivate( pDocSh, nPreviousTab, ScSheetEventId::UNFOCUS ); @@ -677,7 +677,7 @@ sal_Bool SAL_CALL ScTabViewObj::select( const uno::Any& aSelection ) pDrawView->ScEndTextEdit(); pDrawView->UnmarkAll(); } - else //#102232#; if there is no DrawView remove range selection + else //#102232#; if there is no DrawView remove range selection pViewSh->Unmark(); bRet = true; } @@ -736,7 +736,7 @@ sal_Bool SAL_CALL ScTabViewObj::select( const uno::Any& aSelection ) // multiselection const ScRange & rFirst = rRanges[ 0 ]; - if ( !lcl_TabInRanges( rViewData.CurrentTabForData(), rRanges ) ) + if ( !lcl_TabInRanges( rViewData.GetTabNumber(), rRanges ) ) pViewSh->SetTabNo( rFirst.aStart.Tab() ); pViewSh->DoneBlockMode(); pViewSh->InitOwnBlockMode( rFirst ); /* TODO: or even the overall range? */ @@ -1093,7 +1093,7 @@ rtl::Reference ScTabViewObj::getActiveScSheet() if (pViewSh) { ScViewData& rViewData = pViewSh->GetViewData(); - SCTAB nTab = rViewData.CurrentTabForData(); + SCTAB nTab = rViewData.GetTabNumber(); return new ScTableSheetObj( rViewData.GetDocShell(), nTab ); } return nullptr; @@ -1133,7 +1133,7 @@ uno::Reference< uno::XInterface > ScTabViewObj::GetClickedObject(const Point& rP SCROW nY; ScViewData& rData = GetViewShell()->GetViewData(); ScSplitPos eSplitMode = rData.GetActivePart(); - SCTAB nTab(rData.CurrentTabForData()); + SCTAB nTab(rData.GetTabNumber()); rData.GetPosFromPixel( rPoint.X(), rPoint.Y(), eSplitMode, nX, nY); ScAddress aCellPos (nX, nY, nTab); @@ -1159,7 +1159,10 @@ uno::Reference< uno::XInterface > ScTabViewObj::GetClickedObject(const Point& rP for (const rtl::Reference& pObj : *pDrawPage) { - if (SdrObjectPrimitiveHit(*pObj, aPos, {fHitLog, fHitLog}, *pDrawView->GetSdrPageView(), nullptr, false)) + // tdf#120295 - restrict primitive hit to visible layers + if (SdrObjectPrimitiveHit( + *pObj, aPos, { fHitLog, fHitLog }, *pDrawView->GetSdrPageView(), + &pDrawView->GetSdrPageView()->GetVisibleLayers(), false)) { xTarget.set(pObj->getUnoShape(), uno::UNO_QUERY); break; @@ -1179,7 +1182,7 @@ bool ScTabViewObj::IsMouseListening() const // also include sheet events, because MousePressed must be called for them ScViewData& rViewData = GetViewShell()->GetViewData(); ScDocument& rDoc = rViewData.GetDocument(); - SCTAB nTab = rViewData.CurrentTabForData(); + SCTAB nTab = rViewData.GetTabNumber(); return rDoc.HasSheetEventScript( nTab, ScSheetEventId::RIGHTCLICK, true ) || rDoc.HasSheetEventScript( nTab, ScSheetEventId::DOUBLECLICK, true ) || @@ -1232,7 +1235,7 @@ bool ScTabViewObj::MousePressed( const awt::MouseEvent& e ) ScViewData& rViewData = pViewSh->GetViewData(); ScDocShell* pDocSh = rViewData.GetDocShell(); ScDocument& rDoc = pDocSh->GetDocument(); - SCTAB nTab = rViewData.CurrentTabForData(); + SCTAB nTab = rViewData.GetTabNumber(); const ScSheetEvents* pEvents = rDoc.GetSheetEvents(nTab); if (pEvents) { @@ -1707,7 +1710,7 @@ void ScTabViewObj::SelectionChanged() ScViewData& rViewData = pViewSh->GetViewData(); ScDocShell* pDocSh = rViewData.GetDocShell(); ScDocument& rDoc = pDocSh->GetDocument(); - SCTAB nTab = rViewData.CurrentTabForData(); + SCTAB nTab = rViewData.GetTabNumber(); const ScSheetEvents* pEvents = rDoc.GetSheetEvents(nTab); if (pEvents) { @@ -1869,7 +1872,7 @@ void SAL_CALL ScTabViewObj::setPropertyValue( // Options are set on the view and document (for new views), // so that they remain during saving. - //! In the app (module) we need an extra options to tune that + //! In the app (module) we need extra options to tune that //! (for new documents) if ( aNewOpt == rOldOpt ) @@ -2203,7 +2206,7 @@ uno::Sequence ScTabViewObj::getSelectedSheets() if (pExtOpt && pExtOpt->IsChanged()) { pViewSh->GetViewData().ReadExtOptions(*pExtOpt); // Excel view settings - pViewSh->SetTabNo(pViewSh->GetViewData().CurrentTabForData(), true); + pViewSh->SetTabNo(pViewSh->GetViewData().GetTabNumber(), true); pExtOpt->SetChanged(false); } diff --git a/sc/source/ui/vba/vbaapplication.cxx b/sc/source/ui/vba/vbaapplication.cxx index 03955113b200..2b4d4866a50e 100644 --- a/sc/source/ui/vba/vbaapplication.cxx +++ b/sc/source/ui/vba/vbaapplication.cxx @@ -782,7 +782,7 @@ ScVbaApplication::setCursor( sal_Int32 _cursor ) case excel::XlMousePointer::xlIBeam: { PointerStyle nPointer( static_cast< PointerStyle >( _cursor ) ); - //It will set the edit window, toobar and statusbar's mouse pointer. + //It will set the edit window, toolbar and statusbar's mouse pointer. setCursorHelper( xModel, nPointer, true ); break; } @@ -886,7 +886,7 @@ ScVbaApplication::getDisplayScrollBars() void SAL_CALL ScVbaApplication::setDisplayScrollBars( sal_Bool bSet ) { - // use uno here as it does all he repainting etc. magic + // use uno here as it does all the repainting etc. magic uno::Reference< sheet::XSpreadsheetView > xView( getCurrentDocument()->getCurrentController(), uno::UNO_QUERY_THROW ); uno::Reference< beans::XPropertySet > xProps( xView, uno::UNO_QUERY ); xProps->setPropertyValue(u"HasVerticalScrollBar"_ustr, uno::Any( bSet ) ); diff --git a/sc/source/ui/vba/vbaeventshelper.cxx b/sc/source/ui/vba/vbaeventshelper.cxx index 09c956fb9372..08283a647a3d 100644 --- a/sc/source/ui/vba/vbaeventshelper.cxx +++ b/sc/source/ui/vba/vbaeventshelper.cxx @@ -478,38 +478,40 @@ void ScVbaEventListener::postWindowResizeEvent( vcl::Window* pWindow ) IMPL_LINK( ScVbaEventListener, processWindowResizeEvent, void*, p, void ) { vcl::Window* pWindow = static_cast(p); - ::osl::MutexGuard aGuard( maMutex ); - - /* Check that the passed window is still alive (it must be registered in - maControllers). While closing a document, postWindowResizeEvent() may - be called on the last window which posts a user event via - Application::PostUserEvent to call this event handler. VCL will trigger - the handler some time later. Sometimes, the window gets deleted before. - This is handled via the disposing() function which removes the window - pointer from the member maControllers. Thus, checking whether - maControllers contains pWindow ensures that the window is still alive. */ - if( !mbDisposed && pWindow && !pWindow->isDisposed() && (maControllers.count(pWindow) > 0) ) { - // do not fire event unless all mouse buttons have been released - vcl::Window::PointerState aPointerState = pWindow->GetPointerState(); - if( (aPointerState.mnState & (MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT)) == 0 ) + ::osl::MutexGuard aGuard( maMutex ); + + /* Check that the passed window is still alive (it must be registered in + maControllers). While closing a document, postWindowResizeEvent() may + be called on the last window which posts a user event via + Application::PostUserEvent to call this event handler. VCL will trigger + the handler some time later. Sometimes, the window gets deleted before. + This is handled via the disposing() function which removes the window + pointer from the member maControllers. Thus, checking whether + maControllers contains pWindow ensures that the window is still alive. */ + if( !mbDisposed && pWindow && !pWindow->isDisposed() && (maControllers.count(pWindow) > 0) ) { - uno::Reference< frame::XController > xController = getControllerForWindow( pWindow ); - if( xController.is() ) + // do not fire event unless all mouse buttons have been released + vcl::Window::PointerState aPointerState = pWindow->GetPointerState(); + if( (aPointerState.mnState & (MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT)) == 0 ) { - uno::Sequence< uno::Any > aArgs{ uno::Any(xController) }; - // #163419# do not throw exceptions into application core - mrVbaEvents.processVbaEventNoThrow( WORKBOOK_WINDOWRESIZE, aArgs ); + uno::Reference< frame::XController > xController = getControllerForWindow( pWindow ); + if( xController.is() ) + { + uno::Sequence< uno::Any > aArgs{ uno::Any(xController) }; + // #163419# do not throw exceptions into application core + mrVbaEvents.processVbaEventNoThrow( WORKBOOK_WINDOWRESIZE, aArgs ); + } } } - } - { - // note: there may be multiple processWindowResizeEvent outstanding - // for pWindow, so it may have been added to m_PostedWindows multiple - // times - so this must delete exactly one of these elements! - auto const iter(m_PostedWindows.find(pWindow)); - assert(iter != m_PostedWindows.end()); - m_PostedWindows.erase(iter); + { + // note: there may be multiple processWindowResizeEvent outstanding + // for pWindow, so it may have been added to m_PostedWindows multiple + // times - so this must delete exactly one of these elements! + auto const iter(m_PostedWindows.find(pWindow)); + assert(iter != m_PostedWindows.end()); + m_PostedWindows.erase(iter); + } } release(); } diff --git a/sc/source/ui/vba/vbafiledialog.cxx b/sc/source/ui/vba/vbafiledialog.cxx index 9bef15a2609e..208bacba91ff 100644 --- a/sc/source/ui/vba/vbafiledialog.cxx +++ b/sc/source/ui/vba/vbafiledialog.cxx @@ -52,7 +52,7 @@ void ScVbaFileDialog::setInitialFileName( const css::uno::Any& rName ) sal_Int32 eSuccess = osl::FileBase::getFileURLFromSystemPath( sDefaultPath, sDefaultURL ) ; if( eSuccess == osl::FileBase::RC::E_INVAL ) - m_sInitialFileName = sDefaultPath; // the user may gave it in URL form + m_sInitialFileName = sDefaultPath; // the user may have given it in URL form else m_sInitialFileName = sDefaultURL; } diff --git a/sc/source/ui/vba/vbainterior.cxx b/sc/source/ui/vba/vbainterior.cxx index b83b80097c4c..f70f20214d4d 100644 --- a/sc/source/ui/vba/vbainterior.cxx +++ b/sc/source/ui/vba/vbainterior.cxx @@ -141,7 +141,7 @@ ScVbaInterior::setColorIndex( const css::uno::Any& _colorindex ) sal_Int32 nIndex = 0; _colorindex >>= nIndex; - // hackly for excel::XlColorIndex::xlColorIndexNone + // hacky for excel::XlColorIndex::xlColorIndexNone if( nIndex == excel::XlColorIndex::xlColorIndexNone ) { m_xProps->setPropertyValue( BACKCOLOR, uno::Any( sal_Int32( -1 ) ) ); @@ -161,8 +161,8 @@ ScVbaInterior::GetIndexColor( sal_Int32 nColorIndex ) // #FIXME xlColorIndexAutomatic & xlColorIndexNone are not really // handled properly here if ( !nIndex || ( nIndex == excel::XlColorIndex::xlColorIndexAutomatic ) || ( nIndex == excel::XlColorIndex::xlColorIndexNone ) ) - nIndex = 2; // default is white ( this maybe will probably break, e.g. we may at some stage need to know what this interior is, a cell or something else and then pick a default colour based on that ) - --nIndex; // OOo indices are zero bases + nIndex = 2; // default is white ( this will probably break, e.g. we may at some stage need to know what this interior is, a cell or something else and then pick a default colour based on that ) + --nIndex; // OOo indices are zero based uno::Reference< container::XIndexAccess > xIndex = getPalette(); return xIndex->getByIndex( nIndex ); } @@ -190,7 +190,7 @@ uno::Any SAL_CALL ScVbaInterior::getColorIndex() { sal_Int32 nColor = 0; - // hackly for excel::XlColorIndex::xlColorIndexNone + // hacky for excel::XlColorIndex::xlColorIndexNone uno::Any aColor = m_xProps->getPropertyValue( BACKCOLOR ); if( ( aColor >>= nColor ) && ( nColor == -1 ) ) { @@ -280,7 +280,7 @@ ScVbaInterior::SetUserDefinedAttributes( const OUString& sName, const uno::Any& m_xProps->setPropertyValue(u"UserDefinedAttributes"_ustr, uno::Any( xNameContainer ) ); } } -// OOo do not support below API +// OOo does not support below API uno::Any SAL_CALL ScVbaInterior::getPattern() { diff --git a/sc/source/ui/vba/vbamenubars.cxx b/sc/source/ui/vba/vbamenubars.cxx index a6df4695497f..671c239db2b1 100644 --- a/sc/source/ui/vba/vbamenubars.cxx +++ b/sc/source/ui/vba/vbamenubars.cxx @@ -34,7 +34,7 @@ public: } virtual uno::Any SAL_CALL nextElement() override { - // FIXME: should be add menubar + // FIXME: should add menubar if( !hasMoreElements() ) throw container::NoSuchElementException(); @@ -71,7 +71,7 @@ ScVbaMenuBars::createEnumeration() uno::Any ScVbaMenuBars::createCollectionObject( const uno::Any& aSource ) { - // make no sense + // makes no sense return aSource; } diff --git a/sc/source/ui/vba/vbamenuitems.cxx b/sc/source/ui/vba/vbamenuitems.cxx index 37dcc4b25eb3..1a68f000a5fb 100644 --- a/sc/source/ui/vba/vbamenuitems.cxx +++ b/sc/source/ui/vba/vbamenuitems.cxx @@ -37,7 +37,7 @@ public: } virtual uno::Any SAL_CALL nextElement() override { - // FIXME: should be add menu + // FIXME: should add menu if( !hasMoreElements() ) throw container::NoSuchElementException(); @@ -81,7 +81,7 @@ ScVbaMenuItems::createEnumeration() uno::Any ScVbaMenuItems::createCollectionObject( const uno::Any& aSource ) { - // make no sense + // makes no sense return aSource; } diff --git a/sc/source/ui/vba/vbamenus.cxx b/sc/source/ui/vba/vbamenus.cxx index d4be37a782d1..5215b9c72ef5 100644 --- a/sc/source/ui/vba/vbamenus.cxx +++ b/sc/source/ui/vba/vbamenus.cxx @@ -36,7 +36,7 @@ public: } virtual uno::Any SAL_CALL nextElement() override { - // FIXME: should be add menu + // FIXME: should add menu if( !hasMoreElements() ) throw container::NoSuchElementException(); @@ -75,7 +75,7 @@ ScVbaMenus::createEnumeration() uno::Any ScVbaMenus::createCollectionObject( const uno::Any& aSource ) { - // make no sense + // makes no sense return aSource; } diff --git a/sc/source/ui/vba/vbapalette.cxx b/sc/source/ui/vba/vbapalette.cxx index 67a444cba0ec..4dc71736184f 100644 --- a/sc/source/ui/vba/vbapalette.cxx +++ b/sc/source/ui/vba/vbapalette.cxx @@ -34,7 +34,7 @@ using namespace ::ooo::vba; /** Standard EGA colors, bright. */ #define EXC_PALETTE_EGA_COLORS_LIGHT \ Color(0x000000), Color(0xFFFFFF), Color(0xFF0000), Color(0x00FF00), Color(0x0000FF), Color(0xFFFF00), Color(0xFF00FF), Color(0x00FFFF) -/** Standard EGA colors), dark. */ +/** Standard EGA colors (dark). */ #define EXC_PALETTE_EGA_COLORS_DARK \ Color(0x800000), Color(0x008000), Color(0x000080), Color(0x808000), Color(0x800080), Color(0x008080), Color(0xC0C0C0), Color(0x808080) diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx index df14c07e7bc2..77ccc0129e87 100644 --- a/sc/source/ui/vba/vbarange.cxx +++ b/sc/source/ui/vba/vbarange.cxx @@ -4858,8 +4858,8 @@ namespace { /// @throws uno::RuntimeException sal_Unicode lclGetPrefixChar( const uno::Reference< table::XCell >& rxCell ) { - /* TODO/FIXME: We need an apostroph-prefix property at the cell to - implement this correctly. For now, return an apostroph for every text + /* TODO/FIXME: We need an apostrophe-prefix property at the cell to + implement this correctly. For now, return an apostrophe for every text cell. TODO/FIXME: When Application.TransitionNavigKeys is supported and true, @@ -4925,17 +4925,17 @@ uno::Any lclGetPrefixVariant( sal_Unicode cPrefixChar ) uno::Any SAL_CALL ScVbaRange::getPrefixCharacter() { /* (1) If Application.TransitionNavigKeys is false, this function returns - an apostroph character if the text cell begins with an apostroph + an apostrophe character if the text cell begins with an apostrophe character (formula return values are not taken into account); otherwise an empty string. (2) If Application.TransitionNavigKeys is true, this function returns - an apostroph character, if the cell is left-aligned; a double-quote + an apostrophe character, if the cell is left-aligned; a double-quote character, if the cell is right-aligned; a circumflex character, if the cell is centered; a backslash character, if the cell is set to filled; or an empty string, if nothing of the above. - If a range or a list of ranges contains texts with leading apostroph + If a range or a list of ranges contains texts with leading apostrophe character as well as other cells, this function returns an empty string. */ diff --git a/sc/source/ui/vba/vbaworksheet.cxx b/sc/source/ui/vba/vbaworksheet.cxx index a7667bfb1243..3338b760b8c8 100644 --- a/sc/source/ui/vba/vbaworksheet.cxx +++ b/sc/source/ui/vba/vbaworksheet.cxx @@ -672,7 +672,7 @@ ScVbaWorksheet::getSheetRange() return uno::Reference< excel::XRange >( new ScVbaRange( this, mxContext, xRange ) ); } -// These are hacks - we prolly (somehow) need to inherit +// These are hacks - we probably (somehow) need to inherit // the vbarange functionality here ... uno::Reference< excel::XRange > ScVbaWorksheet::Cells( const ::uno::Any &nRow, const ::uno::Any &nCol ) diff --git a/sc/source/ui/vba/vbawsfunction.cxx b/sc/source/ui/vba/vbawsfunction.cxx index 96d71e06b108..23f789b72825 100644 --- a/sc/source/ui/vba/vbawsfunction.cxx +++ b/sc/source/ui/vba/vbawsfunction.cxx @@ -135,7 +135,7 @@ ScVbaWSFunction::invoke(const OUString& FunctionName, const uno::Sequence< uno:: uno::Any aRet; bool bAsArray = true; - // special handing for some functions that don't work correctly in FunctionAccess + // special handling for some functions that don't work correctly in FunctionAccess formula::FormulaCompiler aCompiler; OpCode eOpCode = aCompiler.GetEnglishOpCode( FunctionName.toAsciiUpperCase() ); switch( eOpCode ) @@ -212,7 +212,7 @@ ScVbaWSFunction::invoke(const OUString& FunctionName, const uno::Sequence< uno:: } #if 0 - // MATCH function should alwayse return a double value, but currently if the first argument is XCellRange, MATCH function returns an array instead of a double value. Don't know why? + // MATCH function should always return a double value, but currently if the first argument is XCellRange, MATCH function returns an array instead of a double value. Don't know why? // To fix this issue in safe, current solution is to convert this array to a double value just for MATCH function. OUString aUpper( FunctionName.toAsciiUpperCase() ); ScCompiler aCompiler( NULL, ScAddress() ); @@ -251,7 +251,7 @@ ScVbaWSFunction::hasMethod(const OUString& Name) bool bIsFound = false; try { - // the function name contained in the com.sun.star.sheet.FunctionDescription service is alwayse localized. + // the function name contained in the com.sun.star.sheet.FunctionDescription service is always localized. // but the function name used in WorksheetFunction is a programmatic name (seems English). // So m_xNameAccess->hasByName( Name ) may fail to find name when a function name has a localized name. if( ScCompiler::IsEnglishSymbol( Name ) ) diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx index facd3315d8e2..88024c1bc4cf 100644 --- a/sc/source/ui/view/cellsh.cxx +++ b/sc/source/ui/view/cellsh.cxx @@ -496,6 +496,7 @@ void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFormatItem& rFormats lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BIFF_12 ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BIFF_8 ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BIFF_5 ); + lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::MARKDOWN ); } if ( !lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::EMBED_SOURCE_OLE ) ) @@ -530,7 +531,8 @@ static bool lcl_IsCellPastePossible( const TransferableDataHelper& rData ) rData.HasFormat( SotClipboardFormatId::LINK ) || rData.HasFormat( SotClipboardFormatId::HTML ) || rData.HasFormat( SotClipboardFormatId::HTML_SIMPLE ) || - rData.HasFormat( SotClipboardFormatId::DIF ) ) + rData.HasFormat( SotClipboardFormatId::DIF ) || + rData.HasFormat( SotClipboardFormatId::MARKDOWN ) ) { bPossible = true; } diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx index 58d5381708de..e74daa03b4c9 100644 --- a/sc/source/ui/view/cellsh1.cxx +++ b/sc/source/ui/view/cellsh1.cxx @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -55,6 +57,9 @@ #include #include #include +#include +#include +#include #include #include @@ -99,6 +104,7 @@ #include #include #include +#include #include #include @@ -2552,7 +2558,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) { std::shared_ptr xQueryBox(Application::CreateMessageDialog(pTabViewShell->GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo, - ScResId(STR_EDIT_EXISTING_COND_FORMATS), pTabViewShell)); + ScResId(STR_EDIT_EXISTING_COND_FORMATS))); xQueryBox->set_default_response(RET_YES); xQueryBox->runAsync(xQueryBox, [this, nIndex, nSlot, aPos, pTabViewShell] (int nResult) { sal_uInt32 nNewIndex = nIndex; @@ -2914,6 +2920,58 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) } break; + case SID_INSERT_THREADED_COMMENT: + { + // Currently only supported via Online; text must be provided. + // TODO: if desktop editing support is added in the future, this handler + // will need to handle the empty-text case and let the user edit in place. + const SvxPostItTextItem* pTextItem = nullptr; + const SvxPostItAuthorItem* pAuthorItem = nullptr; + if (pReqArgs) + { + pTextItem = pReqArgs->GetItemIfSet(SID_ATTR_POSTIT_TEXT); + pAuthorItem = pReqArgs->GetItemIfSet(SID_ATTR_POSTIT_AUTHOR); + } + if (pTextItem) + { + ScViewData& rData = GetViewData(); + OUString aAuthor = pAuthorItem ? pAuthorItem->GetValue() : OUString(); + rData.GetDocShell()->GetDocFunc().InsertThreadedComment( + rData.GetCurPos(), pTextItem->GetValue(), + pAuthorItem ? &aAuthor : nullptr, true); + } + rReq.Done(); + } + break; + + case SID_RESOLVE_THREADED_COMMENT: + { + const SvxPostItIdItem* pIdItem; + if (pReqArgs && (pIdItem = pReqArgs->GetItemIfSet(SID_ATTR_POSTIT_ID))) + { + sal_uInt32 nId = pIdItem->GetValue().toUInt32(); + ScDocument& rDoc = GetViewData().GetDocument(); + std::vector aNotes; + rDoc.GetAllNoteEntries(aNotes); + for (const auto& rEntry : aNotes) + { + if (rEntry.mpNote->GetId() == nId) + { + ScPostIt* pNote = rDoc.GetNote(rEntry.maPos); + if (!pNote || !pNote->GetThreadedCommentData()) + break; // not a threaded comment + pNote->SetResolved(!pNote->IsResolved()); + ScDocShell::LOKCommentNotify( + LOKCommentNotificationType::Modify, + rDoc, rEntry.maPos, pNote); + break; + } + } + } + rReq.Done(); + } + break; + case FID_DELETE_ALL_NOTES: { ScViewData& rData = GetViewData(); @@ -3014,7 +3072,20 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) const OUString& rTarget = pHyper->GetTargetFrame(); sal_uInt16 nType = static_cast(pHyper->GetInsertMode()); - pTabViewShell->InsertURL( rName, rURL, rTarget, nType ); + // When the provided text is just a hint, prefer the cell's existing content + // over it; if both are missing, use the URL. + ScViewData& rData = GetViewData(); + OUString aCellText = rData.GetDocument().GetString( + rData.GetCurX(), rData.GetCurY(), rData.GetTabNumber()); + OUString sLinkText; + if (pHyper->GetTextIsHint() && !aCellText.isEmpty()) + sLinkText = aCellText; + else if (!rName.isEmpty()) + sLinkText = rName; + else + sLinkText = rURL; + + pTabViewShell->InsertURL( sLinkText, rURL, rTarget, nType ); rReq.Done(); } else @@ -3613,13 +3684,10 @@ void ScCellShell::ExecuteDataPilotDialog() pTabViewShell->GetFrameWeld(), bEnableExt)); // Populate named ranges (if any). - ScRangeName* pRangeName = rDoc.GetRangeName(); - if (pRangeName) - { - ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end(); - for (; itr != itrEnd; ++itr) - pTypeDlg->AppendNamedRange(itr->second->GetName()); - } + ScRangeName& rRangeName = rDoc.GetRangeName(); + ScRangeName::const_iterator itr = rRangeName.begin(), itrEnd = rRangeName.end(); + for (; itr != itrEnd; ++itr) + pTypeDlg->AppendNamedRange(itr->second->GetName()); pTypeDlg->StartExecuteAsync([this, pTypeDlg, pTabViewShell, pScMod, pFact, &rDoc, &rMark, aDestPos](int nResult) mutable { diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx index 17e4449f72f9..72e308e8760b 100644 --- a/sc/source/ui/view/cellsh2.cxx +++ b/sc/source/ui/view/cellsh2.cxx @@ -555,7 +555,7 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq ) if( lcl_GetSortParam( rData, aSortParam ) ) { ScDocument& rDoc = GetViewData().GetDocument(); - SfxItemSetFixed aArgSet( GetPool() ); + SfxItemSet aArgSet(SfxItemSet::makeFixedSfxItemSet( GetPool() )); pDBData->GetSortParam( aSortParam ); bool bHasHeader = rDoc.HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, rData.CurrentTabForData() ); diff --git a/sc/source/ui/view/cellsh3.cxx b/sc/source/ui/view/cellsh3.cxx index bd1339f696af..7e3703d2448d 100644 --- a/sc/source/ui/view/cellsh3.cxx +++ b/sc/source/ui/view/cellsh3.cxx @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -58,103 +57,6 @@ using sc::TwipsToEvenHMM; -namespace -{ -/// Rid ourselves of unwanted " quoted json characters. -OString escapeJSON(const OUString &aStr) -{ - OUString aEscaped = aStr; - aEscaped = aEscaped.replaceAll("\n", " "); - aEscaped = aEscaped.replaceAll("\"", "'"); - return OUStringToOString(aEscaped, RTL_TEXTENCODING_UTF8); -} - -void lcl_lokGetWholeFunctionList() -{ - const SfxViewShell* pViewShell = SfxViewShell::Current(); - if (!(comphelper::LibreOfficeKit::isActive() - && pViewShell && pViewShell->isLOKMobilePhone())) - return; - - const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); - sal_uInt32 nListCount = pFuncList->GetCount(); - std::set aFuncNameOrderedSet; - for(sal_uInt32 i = 0; i < nListCount; ++i) - { - const ScFuncDesc* pDesc = pFuncList->GetFunction( i ); - if ( pDesc->mxFuncName ) - { - aFuncNameOrderedSet.insert(*pDesc->mxFuncName); - } - } - ScFunctionMgr* pFuncManager = ScGlobal::GetStarCalcFunctionMgr(); - if (!(pFuncManager && aFuncNameOrderedSet.size())) - return; - - OStringBuffer aPayload( - "{ \"wholeList\": true, " - "\"categories\": [ "); - - formula::FormulaHelper aHelper(pFuncManager); - sal_uInt32 nCategoryCount = pFuncManager->getCount(); - for (sal_uInt32 i = 0; i < nCategoryCount; ++i) - { - OUString sCategoryName = ScFunctionMgr::GetCategoryName(i); - aPayload.append("{" - "\"name\": \"" - + escapeJSON(sCategoryName) - + "\"}, "); - } - sal_Int32 nLen = aPayload.getLength(); - aPayload[nLen - 2] = ' '; - aPayload[nLen - 1] = ']'; - aPayload.append(", "); - - OUString aDescFuncNameStr; - aPayload.append("\"functions\": [ "); - sal_uInt32 nCurIndex = 0; - for (const OUString& aFuncNameStr : aFuncNameOrderedSet) - { - aDescFuncNameStr = aFuncNameStr + "()"; - sal_Int32 nNextFStart = 0; - const formula::IFunctionDescription* ppFDesc; - ::std::vector< OUString > aArgs; - OUString eqPlusFuncName = "=" + aDescFuncNameStr; - if ( aHelper.GetNextFunc( eqPlusFuncName, false, nNextFStart, nullptr, &ppFDesc, &aArgs ) ) - { - if ( ppFDesc && !ppFDesc->getFunctionName().isEmpty() ) - { - if (ppFDesc->getCategory()) - { - aPayload.append("{" - "\"index\": " - + OString::number(static_cast(nCurIndex)) - + ", " - "\"category\": " - + OString::number(static_cast(ppFDesc->getCategory()->getNumber())) - + ", " - "\"signature\": \"" - + escapeJSON(ppFDesc->getSignature()) - + "\", " - "\"description\": \"" - + escapeJSON(ppFDesc->getDescription()) - + "\"}, "); - } - } - } - ++nCurIndex; - } - nLen = aPayload.getLength(); - aPayload[nLen - 2] = ' '; - aPayload[nLen - 1] = ']'; - aPayload.append(" }"); - - OString s = aPayload.makeStringAndClear(); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CALC_FUNCTION_LIST, s); -} - -} // end namespace - void ScCellShell::Execute( SfxRequest& rReq ) { ScTabViewShell* pTabViewShell = GetViewData().GetViewShell(); @@ -290,7 +192,7 @@ void ScCellShell::Execute( SfxRequest& rReq ) ScInputHandler* pInputHandler = pScMod->GetInputHdl(pTabViewShell); if (bCommit) { - pTabViewShell->EnterDataToCurrentCell(aInputString, nullptr, true /*bMatrixExpand*/); + pTabViewShell->EnterDataToCurrentCell(aInputString, nullptr, true /*bAutoDynamicArray*/); } else if (pInputHandler) { @@ -356,10 +258,20 @@ void ScCellShell::Execute( SfxRequest& rReq ) { pTabViewShell->EnterBlock( aString, pData ); } + else if (nSlot == FID_INPUTLINE_MATRIX + && !aString.isEmpty() + && (aString[0] == '=' || aString[0] == '+' || aString[0] == '-')) + { + // Ctrl+Shift+Enter authored a classic static array + // formula. Route to EnterMatrix so the cell becomes + // a static array master. + ScDocument& rDoc = GetViewData().GetDocument(); + pTabViewShell->EnterMatrix(aString, rDoc.GetGrammar()); + } else if ( !aString.isEmpty() && ( aString[0] == '=' || aString[0] == '+' || aString[0] == '-' ) ) { pTabViewShell->EnterData( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), - aString, pData, true /*bMatrixExpand*/); + aString, pData, true /*bAutoDynamicArray*/); } else { @@ -389,7 +301,7 @@ void ScCellShell::Execute( SfxRequest& rReq ) aCursorPos.Row(), aCursorPos.Tab(), aString, nullptr, - true /*bMatrixExpand*/); + true /*bAutoDynamicArray*/); rReq.Done(); } } @@ -417,23 +329,11 @@ void ScCellShell::Execute( SfxRequest& rReq ) case SID_OPENDLG_FUNCTION: { - const SfxViewShell* pViewShell = SfxViewShell::Current(); - if (comphelper::LibreOfficeKit::isActive() - && pViewShell && pViewShell->isLOKMobilePhone()) - { - // not set the dialog id in the mobile case or we would - // not be able to get cell address pasted in the edit view - // by just tapping on them - lcl_lokGetWholeFunctionList(); - } - else - { - sal_uInt16 nId = SID_OPENDLG_FUNCTION; - SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame(); - SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId ); - bool bVis = comphelper::LibreOfficeKit::isActive() || pWnd == nullptr; - pScMod->SetRefDialog( nId, bVis ); - } + sal_uInt16 nId = SID_OPENDLG_FUNCTION; + SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId ); + bool bVis = comphelper::LibreOfficeKit::isActive() || pWnd == nullptr; + pScMod->SetRefDialog( nId, bVis ); rReq.Ignore(); } break; diff --git a/sc/source/ui/view/cliputil.cxx b/sc/source/ui/view/cliputil.cxx index 930fb70fd771..59c14fbb7865 100644 --- a/sc/source/ui/view/cliputil.cxx +++ b/sc/source/ui/view/cliputil.cxx @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -134,6 +135,7 @@ void ScClipUtil::PasteFromClipboard( ScViewData& rViewData, ScTabViewShell* pTab { ScRange maDestRange; // destination range for the full matrix const ScTokenArray* mpCode; // token array from the origin formula cell + bool mbDynamicArrayMaster; // source was a dynamic-array master }; std::vector aOriginInfos; aOriginInfos.reserve(rClipParam.maOriginMatrixRanges.size()); @@ -153,11 +155,15 @@ void ScClipUtil::PasteFromClipboard( ScViewData& rViewData, ScTabViewShell* pTab // to EnterMatrix ensures relative references are correctly // shifted to the destination position. const ScTokenArray* pCode = nullptr; + bool bDynamic = false; ScFormulaCell* pFC = pClipDoc->GetFormulaCell(rMat.aStart); if (pFC) + { pCode = pFC->GetCode(); + bDynamic = pFC->IsDynamicArrayMaster(); + } - aOriginInfos.push_back({ aDestMatRange, pCode }); + aOriginInfos.push_back({ aDestMatRange, pCode, bDynamic }); } // Pre-check: detect existing matrices at the destination. @@ -313,7 +319,8 @@ void ScClipUtil::PasteFromClipboard( ScViewData& rViewData, ScTabViewShell* pTab pDocSh->GetDocFunc().EnterMatrix( rDest, &aMark, rInfo.mpCode, OUString(), true /*bApi*/, false /*bEnglish*/, - OUString(), eGram); + OUString(), eGram, + rInfo.mbDynamicArrayMaster); } pUndoMgr->LeaveListAction(); diff --git a/sc/source/ui/view/dbfunc.cxx b/sc/source/ui/view/dbfunc.cxx index 3317075096ad..050e4a914bba 100644 --- a/sc/source/ui/view/dbfunc.cxx +++ b/sc/source/ui/view/dbfunc.cxx @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -216,7 +215,7 @@ void ScDBFunc::Sort( const ScSortParam& rSortParam, bool bRecord, bool bPaint ) ScDocShell* pDocSh = GetViewData().GetDocShell(); SCTAB nTab = GetViewData().CurrentTabForData(); ScDBDocFunc aDBDocFunc( *pDocSh ); - bool bSuccess = aDBDocFunc.Sort( nTab, rSortParam, bRecord, bPaint, false ); + bool bSuccess = aDBDocFunc.SortTab(nTab, rSortParam, bRecord, bPaint, false); if ( bSuccess && !rSortParam.bInplace ) { // mark target @@ -279,7 +278,7 @@ void ScDBFunc::ToggleAutoFilter() ScViewData& rViewData = GetViewData(); ScDocShell* pDocSh = rViewData.GetDocShell(); - ScQueryParam aParam; + auto xParam = std::make_shared(); ScDocument& rDoc = rViewData.GetDocument(); ScDBData* pDBData = GetDBData(false, SC_DB_AUTOFILTER, ScGetDBSelection::RowDown); @@ -287,10 +286,10 @@ void ScDBFunc::ToggleAutoFilter() return; pDBData->SetByRow( true ); //! undo, retrieve beforehand ?? - pDBData->GetQueryParam( aParam ); + pDBData->GetQueryParam( *xParam ); SCCOL nCol; - SCROW nRow = aParam.nRow1; + SCROW nRow = xParam->nRow1; SCTAB nTab = rViewData.CurrentTabForData(); ScMF nFlag; bool bHasAuto = true; @@ -298,7 +297,7 @@ void ScDBFunc::ToggleAutoFilter() //! instead retrieve from DB-range? - for (nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAuto; nCol++) + for (nCol=xParam->nCol1; nCol<=xParam->nCol2 && bHasAuto; nCol++) { nFlag = rDoc.GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ).GetValue(); @@ -310,11 +309,11 @@ void ScDBFunc::ToggleAutoFilter() { // hide filter buttons - for (nCol=aParam.nCol1; nCol<=aParam.nCol2; nCol++) + for (nCol=xParam->nCol1; nCol<=xParam->nCol2; nCol++) { nFlag = rDoc.GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ).GetValue(); rDoc.ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr( nFlag & ~ScMF::Auto ) ); - aParam.RemoveAllEntriesByField(nCol); + xParam->RemoveAllEntriesByField(nCol); } // use a list action for the AutoFilter buttons (ScUndoAutoFilter) and the filter operation @@ -329,17 +328,20 @@ void ScDBFunc::ToggleAutoFilter() pDBData->SetAutoFilter(false); - aParam.bDuplicate = true; - Query( aParam, nullptr, true ); + xParam->bDuplicate = true; + Query( *xParam, nullptr, true ); pDocSh->GetUndoManager()->LeaveListAction(); + // Sync sheet views — auto-filter removal needs to propagate + rDoc.SyncSheetViews(nTab); + ScDBFunc::ModifiedAutoFilter(*pDocSh); } else // show filter buttons { - if ( !rDoc.IsBlockEmpty( aParam.nCol1, aParam.nRow1, - aParam.nCol2, aParam.nRow2, nTab ) ) + if ( !rDoc.IsBlockEmpty( xParam->nCol1, xParam->nRow1, + xParam->nCol2, xParam->nRow2, nTab ) ) { if (!bHeader) { @@ -351,17 +353,17 @@ void ScDBFunc::ToggleAutoFilter() xBox->set_title(ScResId(STR_MSSG_DOSUBTOTALS_0)); // "StarCalc" xBox->set_default_response(RET_YES); xBox->SetInstallLOKNotifierHdl(LINK(this, ScDBFunc, InstallLOKNotifierHdl)); - xBox->runAsync(xBox, [pDocSh, &rViewData, pDBData, nRow, nTab, aParam] (sal_Int32 nResult) { + xBox->runAsync(xBox, [pDocSh, &rViewData, pDBData, nRow, nTab, xParam=std::move(xParam)] (sal_Int32 nResult) { if (nResult == RET_YES) { pDBData->SetHeader( true ); //! Undo ?? } - ApplyAutoFilter(*pDocSh, rViewData, pDBData, nRow, nTab, aParam); + ApplyAutoFilter(*pDocSh, rViewData, pDBData, nRow, nTab, *xParam); }); } else - ApplyAutoFilter(*pDocSh, rViewData, pDBData, nRow, nTab, aParam); + ApplyAutoFilter(*pDocSh, rViewData, pDBData, nRow, nTab, *xParam); } else { diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index ceba2d6c0b75..4b454155c600 100644 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -520,9 +520,9 @@ void ScDBFunc::DoSubTotals( const ScSubTotalParam& rParam, bool bRecord, InsertDeleteFlags::FORMULA, false, *pUndoDoc ); // database and other ranges - ScRangeName* pDocRange = rDoc.GetRangeName(); - if (!pDocRange->empty()) - pUndoRange.reset(new ScRangeName( *pDocRange )); + ScRangeName& rDocRange = rDoc.GetRangeName(); + if (!rDocRange.empty()) + pUndoRange.reset(new ScRangeName( rDocRange )); ScDBCollection* pDocDB = rDoc.GetDBCollection(); if (!pDocDB->empty()) pUndoDB.reset(new ScDBCollection( *pDocDB )); @@ -2312,9 +2312,9 @@ void ScDBFunc::RepeatDB( bool bRecord ) rDoc.CopyToDocument( 0,0,0, rDoc.MaxCol(),rDoc.MaxRow(),nTabCount-1, InsertDeleteFlags::FORMULA, false, *pUndoDoc ); // data base and other ranges - ScRangeName* pDocRange = rDoc.GetRangeName(); - if (!pDocRange->empty()) - pUndoRange.reset(new ScRangeName( *pDocRange )); + ScRangeName& rDocRange = rDoc.GetRangeName(); + if (!rDocRange.empty()) + pUndoRange.reset(new ScRangeName( rDocRange )); ScDBCollection* pDocDB = rDoc.GetDBCollection(); if (!pDocDB->empty()) pUndoDB.reset(new ScDBCollection( *pDocDB )); @@ -2345,7 +2345,7 @@ void ScDBFunc::RepeatDB( bool bRecord ) else Query( aQueryParam, nullptr, false ); - // if not inplace the sheet may have changed + // if not in-place the sheet may have changed if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab ) SetTabNo( nTab ); } @@ -2391,7 +2391,7 @@ void ScDBFunc::RepeatDB( bool bRecord ) ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab), PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top | PaintPartFlags::Size); } - else // "no not execute any operations" + else // "do not execute any operations" ErrorMessage(STR_MSSG_REPEATDB_0); } @@ -2400,7 +2400,7 @@ void ScDBFunc::OnLOKShowHideColRow(bool bColumns, SCCOLROW nStart) if (!comphelper::LibreOfficeKit::isActive()) return; - SCTAB nCurrentTabIndex = GetViewData().CurrentTabForData(); + SCTAB nCurrentTabIndex = GetViewData().GetTabNumber(); SfxViewShell* pThisViewShell = GetViewData().GetViewShell(); SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell) diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx index 732fa16026b5..036b952971cc 100644 --- a/sc/source/ui/view/drawview.cxx +++ b/sc/source/ui/view/drawview.cxx @@ -80,7 +80,10 @@ void ScDrawView::Construct() SetHitTolerancePixel( 2 ); SCTAB nViewTab = rViewData.CurrentTabForData(); - ShowSdrPage(GetModel().GetPage(nViewTab)); + // For sheet view tabs, use the default view's draw page so that + // all draw operations and undo actions reference the default view's page. + SCTAB nDrawTab = rDoc.GetDefaultViewTableNumber(nViewTab); + ShowSdrPage(GetModel().GetPage(nDrawTab)); bool bEx = rViewData.GetViewShell()->IsDrawSelMode(); bool bProt = rDoc.IsTabProtected( nViewTab ) || @@ -1094,7 +1097,8 @@ SdrObject* ScDrawView::ApplyGraphicToObject( ReplaceObjectAtView(&rHitObject, *GetSdrPageView(), pNewGrafObj.get()); // set in all cases - the Clone() will have copied an existing link (!) - pNewGrafObj->SetGraphicLink( rFile ); + if (!rFile.isEmpty()) + pNewGrafObj->SetGraphicLink(rFile); EndUndo(); return pNewGrafObj.get(); @@ -1103,7 +1107,7 @@ SdrObject* ScDrawView::ApplyGraphicToObject( { AddUndo(std::make_unique(rHitObject)); - SfxItemSetFixed aSet(GetModel().GetItemPool()); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet(GetModel().GetItemPool())); aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP)); aSet.Put(XFillBitmapItem(OUString(), rGraphic)); diff --git a/sc/source/ui/view/formatsh.cxx b/sc/source/ui/view/formatsh.cxx index 1810bfd0fee3..a35e1fe3053b 100644 --- a/sc/source/ui/view/formatsh.cxx +++ b/sc/source/ui/view/formatsh.cxx @@ -493,7 +493,7 @@ void ScFormatShell::ExecuteNumFormat( SfxRequest& rReq ) const SfxItemSet& rOldSet = pTabViewShell->GetSelectionPattern()->GetItemSet(); SfxItemPool* pDocPool = GetViewData().GetDocument().GetPool(); - SfxItemSetFixed aNewSet( *pDocPool ); + SfxItemSet aNewSet(SfxItemSet::makeFixedSfxItemSet( *pDocPool )); aNewSet.Put( *pItem ); pTabViewShell->ApplyAttributes( aNewSet, rOldSet ); } @@ -1093,10 +1093,14 @@ void ScFormatShell::ExecuteAttr( SfxRequest& rReq ) { // Update default line ::editeng::SvxBorderLine aLine; - const ::editeng::SvxBorderLine* pLine = pNewAttrs->Get(SID_FRAME_LINESTYLE).GetLine(); + const ::editeng::SvxBorderLine* pLine = nullptr; + const SfxPoolItem* pLineStyleItem = nullptr; + if (pNewAttrs->HasItem(SID_FRAME_LINESTYLE, &pLineStyleItem)) + pLine = static_cast(pLineStyleItem)->GetLine(); const SfxPoolItem *pItem1, *pItem2, *pItem3; - if (pNewAttrs->HasItem(FN_PARAM_1, &pItem1) && + if (pLine && + pNewAttrs->HasItem(FN_PARAM_1, &pItem1) && pNewAttrs->HasItem(FN_PARAM_2, &pItem2) && pNewAttrs->HasItem(FN_PARAM_3, &pItem3)) { @@ -1166,8 +1170,8 @@ void ScFormatShell::ExecuteAttr( SfxRequest& rReq ) { ::editeng::SvxBorderLine* pDefLine = pTabViewShell->GetDefaultFrameLine(); const ScPatternAttr* pOldAttrs = pTabViewShell->GetSelectionPattern(); - SfxItemSetFixed aOldSet( *rDoc.GetPool() ); - SfxItemSetFixed aNewSet( *rDoc.GetPool() ); + SfxItemSet aOldSet(SfxItemSet::makeFixedSfxItemSet( *rDoc.GetPool() )); + SfxItemSet aNewSet(SfxItemSet::makeFixedSfxItemSet( *rDoc.GetPool() )); const SfxPoolItem& rBorderAttr = pOldAttrs->GetItemSet().Get(ATTR_BORDER); // Evaluate border items from controller: diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 9c3ea627e357..0e54fa6d1a99 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -259,7 +259,8 @@ IMPL_LINK(ScFilterListBox, SelectHdl, const weld::TreeIter&, rIter, bool) if (!bInit && !bCancelled && !nAsyncSelectHdl) { nSel = xTreeView->get_iter_index_in_parent(rIter); - assert(nSel >= 0 && "Invalid index for activated row"); + assert(xTreeView->get_iter_index_in_parent(rIter) >= 0 + && "Invalid index for activated row"); // #i81298# launch async so the box isn't deleted from modifications within FilterSelect nAsyncSelectHdl = Application::PostUserEvent(LINK(this, ScFilterListBox, AsyncSelectHdl)); } @@ -391,7 +392,7 @@ ScGridWindow::ScGridWindow( vcl::Window* pParent, ScViewData& rData, ScSplitPos aComboButton( GetOutDev() ), aCurMousePos( 0,0 ), nPaintCount( 0 ), - aDrawSelectionPos( 0,0 ), + aDrawMouseDownPos( 0,0 ), aRFSelectedCorned( NONE ), maShowPageBreaksTimer("ScGridWindow maShowPageBreaksTimer"), bEEMouse( false ), @@ -1845,21 +1846,6 @@ bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, bool bAction ) void ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt ) { - if (SfxLokHelper::getDeviceFormFactor() == LOKDeviceFormFactor::MOBILE) - { - ScViewFunc* pView = mrViewData.GetView(); - ScTabViewShell* pViewShell = mrViewData.GetViewShell(); - bool bRefMode = pViewShell && pViewShell->IsRefInputMode(); - - Point aPos(rMEvt.GetPosPixel()); - SCCOL nPosX; - SCROW nPosY; - mrViewData.GetPosFromPixel(aPos.X(), aPos.Y(), eWhich, nPosX, nPosY); - - if (bRefMode && pView->GetFunctionSet().CheckRefBounds(nPosX, nPosY)) - return; - } - nNestedButtonState = ScNestedButtonState::Down; MouseEventState aState; @@ -1979,7 +1965,7 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventSta pSelEng->SetVisibleArea( tools::Rectangle(Point(), GetOutputSizePixel()) ); } - if (bEditMode && (mrViewData.GetRefTabNo() == mrViewData.CurrentTabForData())) + if (bEditMode && (mrViewData.GetRefTabNo() == mrViewData.GetTabNumber())) { Point aPos = rMEvt.GetPosPixel(); SCCOL nPosX; @@ -2041,6 +2027,7 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventSta RfCorner rCorner = NONE; bool bFound = HitRangeFinder(rMEvt.GetPosPixel(), rCorner, &nRFIndex, &nRFAddX, &nRFAddY); + bRFSize = (rCorner != NONE); aRFSelectedCorned = rCorner; if (bFound) @@ -2746,24 +2733,7 @@ void ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt ) ScGlobal::OpenURL(aUrl, aTarget, isTiledRendering); return; } - // On a mobile device view there is no ctrl+click and for hyperlink popup - // the cell coordinates must be sent along with click position for elegance - ScTabViewShell* pViewShell = mrViewData.GetViewShell(); - if (isTiledRendering && pViewShell && - (pViewShell->isLOKMobilePhone() || pViewShell->isLOKTablet())) - { - aPos = rMEvt.GetPosPixel(); - mrViewData.GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); - OString aCursor - = pViewShell->GetViewData().describeCellCursorAt(nUrlCellX, nPosY); - double fPPTX = pViewShell->GetViewData().GetPPTX(); - int mouseX = aPos.X() / fPPTX; - int mouseY = aPos.Y() / fPPTX; - OString aMsg(aUrl.toUtf8() + " coordinates: " + aCursor + ", " - + OString::number(mouseX) + ", " + OString::number(mouseY)); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED, aMsg); - } else - ScGlobal::OpenURL(aUrl, aTarget); + ScGlobal::OpenURL(aUrl, aTarget); } else { @@ -2993,7 +2963,7 @@ void ScGridWindow::MouseMove( const MouseEvent& rMEvt ) bool bEditMode = mrViewData.HasEditView(eWhich); //! Test if refMode dragging !!! - if ( bEditMode && (mrViewData.GetRefTabNo() == mrViewData.CurrentTabForData()) ) + if ( bEditMode && (mrViewData.GetRefTabNo() == mrViewData.GetTabNumber()) ) { Point aPos = rMEvt.GetPosPixel(); SCCOL nPosX; @@ -4101,7 +4071,7 @@ void ScGridWindow::DropScroll( const Point& rMousePos ) static bool lcl_TestScenarioRedliningDrop( const ScDocument* pDoc, const ScRange& aDragRange) { - // Test, if a scenario is affected by a drop when turing on RedLining, + // Test, if a scenario is affected by a drop when turning on RedLining, bool bReturn = false; SCTAB nTab = aDragRange.aStart.Tab(); SCTAB nTabCount = pDoc->GetTableCount(); @@ -5970,7 +5940,7 @@ bool extractURLInfo( const SvxFieldItem* pFieldItem, OUString* pName, OUString* static void lcl_SetEngineTextKeepingDefaults(const std::shared_ptr& pEngine, ScDocument& rDoc, ScRefCellValue& rCell, const OUString& rURL) { - std::unique_ptr pTextObj; + std::optional oTextObj; if (rCell.getType() == CELLTYPE_EDIT) { if (rCell.getEditText()) @@ -5981,7 +5951,7 @@ static void lcl_SetEngineTextKeepingDefaults(const std::shared_ptrCreateURLObject(); + oTextObj.emplace(rCell.getFormula()->CreateURLObject()); else { OUString aRepres = rURL; @@ -5992,11 +5962,11 @@ static void lcl_SetEngineTextKeepingDefaults(const std::shared_ptrGetString().getString(); - pTextObj = ScEditUtil::CreateURLObjectFromURL(rDoc, rURL, aRepres); + oTextObj.emplace(ScEditUtil::CreateURLObjectFromURL(rDoc, rURL, aRepres)); } - if (pTextObj) - pEngine->SetTextCurrentDefaults(*pTextObj); + if (oTextObj) + pEngine->SetTextCurrentDefaults(*oTextObj); } } diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx index e7be8abde6e1..2e4706c63c28 100644 --- a/sc/source/ui/view/gridwin2.cxx +++ b/sc/source/ui/view/gridwin2.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -135,7 +136,12 @@ bool ScGridWindow::DoAutoFilterButton( SCCOL nCol, SCROW nRow, const MouseEvent& if (aRect.Contains(rMEvt.GetPosPixel())) { if ( DoPageFieldSelection( nCol, nRow ) ) + { + // tdf#148660 - reset filter button to its default state + mpFilterButton.reset(); return true; + } + bool bFilterActive = IsAutoFilterActive(nCol, nRow, nTab); mpFilterButton->setHasHiddenMember(bFilterActive); @@ -147,6 +153,8 @@ bool ScGridWindow::DoAutoFilterButton( SCCOL nCol, SCROW nRow, const MouseEvent& return true; } + // tdf#148660 - reset filter button to its default state + mpFilterButton.reset(); return false; } @@ -650,8 +658,11 @@ void ScGridWindow::DPPopulateFieldMembers(const ScDPLabelData& rLabelData) if (aName.isEmpty()) // Use special string for an empty name. mpDPFieldPopup->addMember(ScResId(STR_EMPTYDATA), 0.0, rMem.mbVisible, false); + else if (rLabelData.mbIsDateDimension && rMem.mbHasValue) + // tdf#132518 - group pivot date field values in dropdown filter + mpDPFieldPopup->addDateMember(aName, rMem.mfValue, rMem.mbVisible, false); else - mpDPFieldPopup->addMember(rMem.getDisplayName(), 0.0, rMem.mbVisible, false); + mpDPFieldPopup->addMember(aName, 0.0, rMem.mbVisible, false); } } @@ -731,8 +742,9 @@ void ScGridWindow::DPLaunchFieldPopupMenu(const Point& rScrPos, const Size& rScr mpDPFieldPopup.reset(); weld::Window* pPopupParent = GetFrameWeld(); + // tdf#132518 - group pivot date field values in dropdown filter mpDPFieldPopup.reset(new ScCheckListMenuControl(pPopupParent, mrViewData, - false, -1)); + pDPData->maLabels.mbIsDateDimension, -1)); DPSetupFieldPopup(std::move(pDPData), bDimOrientNotPage, pDPObj); @@ -943,7 +955,7 @@ sal_uInt16 ScGridWindow::HitPageBreak( const Point& rMouse, ScRange* pSource, Point aTL = mrViewData.GetScrPos( nPosX, nPosY, eWhich ); Point aBR = mrViewData.GetScrPos( nPosX+1, nPosY+1, eWhich ); - // Horizontal more tolerances as for vertical, because there is more space + // Horizontal more tolerance than for vertical, because there is more space if ( nMouseX <= aTL.X() + 4 ) { bHori = true; diff --git a/sc/source/ui/view/gridwin3.cxx b/sc/source/ui/view/gridwin3.cxx index 08d96f470357..5645f5a47ae8 100644 --- a/sc/source/ui/view/gridwin3.cxx +++ b/sc/source/ui/view/gridwin3.cxx @@ -53,14 +53,13 @@ static bool lcl_HasSelectionChanged(const SdrMarkList & rBeforeList, const SdrMa return false; } -static bool lcl_PosUnchanged(const tools::Rectangle& rSelectionRect, const Point& rDrawSelectionPos) -{ - return rDrawSelectionPos.X() == rSelectionRect.Left() && - rDrawSelectionPos.Y() == rSelectionRect.Top(); -} - bool ScGridWindow::DrawMouseButtonDown(const MouseEvent& rMEvt) { + // Keep track of the mouse position when the left button was pressed so we can detect if it was + // moved on mouse up + if (rMEvt.IsLeft()) + aDrawMouseDownPos = rMEvt.GetPosPixel(); + bool bRet = false; FuPoor* pDraw = mrViewData.GetView()->GetDrawFuncPtr(); if (pDraw) @@ -75,14 +74,6 @@ bool ScGridWindow::DrawMouseButtonDown(const MouseEvent& rMEvt) pDraw->SetWindow( this ); Point aLogicPos = PixelToLogic(rMEvt.GetPosPixel()); - SdrMarkList aPreMarkList = pDrView->GetMarkedObjectList(); - if(!aPreMarkList.GetMarkCount()) - aDrawSelectionPos = Point(0,0); - else - { - tools::Rectangle aRect = pDrView->GetAllMarkedRect(); - aDrawSelectionPos = Point(aRect.Left(), aRect.Top()); - } if ( pDraw->IsDetectiveHit( aLogicPos ) ) { @@ -91,6 +82,7 @@ bool ScGridWindow::DrawMouseButtonDown(const MouseEvent& rMEvt) } else { + SdrMarkList aPreMarkList = pDrView->GetMarkedObjectList(); bRet = pDraw->MouseButtonDown( rMEvt ); if (bRet) { @@ -113,6 +105,18 @@ bool ScGridWindow::DrawMouseButtonDown(const MouseEvent& rMEvt) return bRet; } +namespace +{ +bool lcl_MouseUnmoved(ScDrawView* pDrView, const MouseEvent& rMEvt, const Point& aDownPos) +{ + sal_Int32 nThreshold = pDrView->GetDragThresholdPixels(); + const Point& aMousePos = rMEvt.GetPosPixel(); + + return std::abs(aMousePos.getX() - aDownPos.getX()) < nThreshold && + std::abs(aMousePos.getY() - aDownPos.getY()) < nThreshold; +} +} + bool ScGridWindow::DrawMouseButtonUp(const MouseEvent& rMEvt) { ScViewFunc* pView = mrViewData.GetView(); @@ -148,7 +152,7 @@ bool ScGridWindow::DrawMouseButtonUp(const MouseEvent& rMEvt) && ScModule::get()->GetAppOptions().IsClickChangeRotation() && !pDraw->HasSelectionChanged() && dynamic_cast(pDraw) - && lcl_PosUnchanged(pDrView->GetAllMarkedRect(), aDrawSelectionPos)) + && lcl_MouseUnmoved(pDrView, rMEvt, aDrawMouseDownPos)) { mrViewData.GetView()->SwitchRotateMode(); } @@ -390,7 +394,7 @@ void ScGridWindow::UpdateStatusPosSize() if (!pPV) return; // shouldn't be called in that case either - SfxItemSetFixed aSet(mrViewData.GetViewShell()->GetPool()); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet(mrViewData.GetViewShell()->GetPool())); // Fill items for position and size: // show action rectangle during action, diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index 26b8fc1c8616..70caf85056b7 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -679,7 +679,8 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI && comphelper::LibreOfficeKit::isCompatFlagSet( comphelper::LibreOfficeKit::Compat::scNoGridBackground); - SCTAB nTab = aOutputData.mnTab; + SCTAB nViewTab = aOutputData.mnTab; // the actual view tab (may be sheet view tab) + SCTAB nTab = rDoc.GetDefaultViewTableNumber(nViewTab); // default/logical tab for structural lookups SCCOL nX1 = aOutputData.mnX1; SCROW nY1 = aOutputData.mnY1; SCCOL nX2 = aOutputData.mnX2; @@ -722,7 +723,7 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI EditView* pEditView = nullptr; bool bEditMode = mrViewData.HasEditView(eWhich); - if ( bEditMode && mrViewData.GetRefTabNo() == nTab ) + if ( bEditMode && mrViewData.GetRefTabNo() == nViewTab ) { SCCOL nEditCol; SCROW nEditRow; @@ -804,7 +805,7 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI aDrawingRectLogic = PixelToLogic(aDrawingRectPixel, aDrawMode); } - bool bInPlaceEditing = bEditMode && (mrViewData.GetRefTabNo() == mrViewData.CurrentTabForData()); + bool bInPlaceEditing = bEditMode && (mrViewData.GetRefTabNo() == nViewTab); vcl::Cursor* pInPlaceCrsr = nullptr; bool bInPlaceVisCursor = false; if (bInPlaceEditing) @@ -1132,7 +1133,7 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI if (!(bOtherEditMode && ( nCol2 >= nX1 && nCol1 <= nX2 && nRow2 >= nY1 && nRow1 <= nY2 ) - && rOtherViewData.GetRefTabNo() == nTab)) + && rOtherViewData.GetRefTabNo() == nViewTab)) continue; // only views where in place editing is occurring need to be rendered EditView* pOtherEditView = rOtherViewData.GetEditView(eOtherWhich); diff --git a/sc/source/ui/view/hdrcont.cxx b/sc/source/ui/view/hdrcont.cxx index 47506cfa2a8d..3748bf71c0fe 100644 --- a/sc/source/ui/view/hdrcont.cxx +++ b/sc/source/ui/view/hdrcont.cxx @@ -102,12 +102,15 @@ ScHeaderControl::ScHeaderControl( vcl::Window* pParent, SelectionEngine* pSelect Size aSize = LogicToPixel( Size( GetTextWidth(u"8888"_ustr), GetTextHeight() ) ); - aSize.AdjustWidth(4 ); // place for highlight border + aSize.AdjustWidth(8); // place for highlight border aSize.AdjustHeight(3 ); SetSizePixel( aSize ); nWidth = nSmallWidth = aSize.Width(); - nBigWidth = LogicToPixel( Size( GetTextWidth(u"8888888"_ustr), 0 ) ).Width() + 5; + // tdf#148507 - pre-calculate individual column widths + nMedWidth = LogicToPixel( Size( GetTextWidth(u"88888"_ustr), 0 ) ).Width() + 8; + nLargeWidth = LogicToPixel( Size( GetTextWidth(u"888888"_ustr), 0 ) ).Width() + 8; + nBigWidth = LogicToPixel( Size( GetTextWidth(u"8888888"_ustr), 0 ) ).Width() + 8; aShowHelpTimer.SetInvokeHandler(LINK(this, ScHeaderControl, ShowDragHelpHdl)); aShowHelpTimer.SetTimeout(GetSettings().GetMouseSettings().GetDoubleClickTime()); @@ -341,12 +344,12 @@ void ScHeaderControl::Paint( vcl::RenderContext& rRenderContext, const tools::Re sc::SheetViewID nSheetViewID = rViewData.GetSheetViewID(); if (nSheetViewID >= 0) { - auto pSheetManager = rViewData.GetDocument().GetSheetViewManager(rViewData.GetTabNumber()); - auto pSheetView = pSheetManager->get(nSheetViewID); - if (pSheetView->isSynced()) + SCTAB nDefaultTab = rViewData.GetDefaultViewTab(); + auto pSheetManager = rViewData.GetDocument().GetSheetViewManager(nDefaultTab); + if (pSheetManager) + { aFaceColor.Merge(COL_LIGHTBLUE, 220); - else - aFaceColor.Merge(COL_LIGHTRED, 220); + } } } if (bDark) diff --git a/sc/source/ui/view/notemark.cxx b/sc/source/ui/view/notemark.cxx index f25e5bd70611..b341553481d9 100644 --- a/sc/source/ui/view/notemark.cxx +++ b/sc/source/ui/view/notemark.cxx @@ -112,9 +112,9 @@ const drawinglayer::primitive2d::Primitive2DContainer& ScNoteOverlay::getOrCreat tools::Rectangle ScNoteOverlay::calculateVisibleRectangle() { - // to not change anything for now in positioning/object - // creation sticked together from previous versions. This - // can (should) be converted to transformation stuff + // For now, don’t change anything in the positioning/object creation + // that was kept from previous versions... + // This can (should) be converted to transformation stuff // later. In principle it calculates the size of the // merged WindowSpace (all SplitWindows) and transforms // that range to logical coordinates in one of the @@ -352,7 +352,7 @@ ScNoteOverlay::~ScNoteOverlay() // destruct temporary SdrObject. It *needs* to be kept alive // during visualization due to it being used for decompose - // of the TextPrimitive. That is an old compromize in the + // of the TextPrimitive. That is an old compromise in the // primitives: the text primitive is not self-contained in // the sense that it needs the SdrTextObj for decompose. // Would be hard to correct, but would be good for the future diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx index 15b273d7a7df..baea15c1b914 100644 --- a/sc/source/ui/view/output.cxx +++ b/sc/source/ui/view/output.cxx @@ -64,6 +64,7 @@ #include #include +#include #include #include @@ -682,7 +683,7 @@ void ScOutputData::SetCellRotations() for (SCCOL nX=0; nX<=nRotMax; nX++) { ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nX); - const ScPatternAttr* pPattern = pInfo->pPatternAttr; + const ScPatternAttr* pPattern = pInfo->getPatternAttr(); const SfxItemSet* pCondSet = pInfo->pConditionSet; if ( !pPattern && !mpDoc->ColHidden(nX, mnTab) ) @@ -806,8 +807,8 @@ static bool lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther, { for ( nX=mnX1; nX<=mnX2; nX++ ) { - const ScPatternAttr* pPat1 = rFirst.cellInfo(nX).pPatternAttr; - const ScPatternAttr* pPat2 = rOther.cellInfo(nX).pPatternAttr; + const ScPatternAttr* pPat1 = rFirst.cellInfo(nX).getPatternAttr(); + const ScPatternAttr* pPat2 = rOther.cellInfo(nX).getPatternAttr(); if ( !pPat1 || !pPat2 || !SfxPoolItem::areSame(pPat1->GetItem(ATTR_PROTECTION), pPat2->GetItem(ATTR_PROTECTION) ) ) return false; @@ -1076,7 +1077,9 @@ void ScOutputData::DrawBackground(vcl::RenderContext& rRenderContext) // See more about bWorksInPixels in ScOutputData::DrawGrid bool bWorksInPixels = (meType == OUTTYPE_WINDOW); - const tools::Long nOneX = bWorksInPixels ? 1 : nOneXLogic; + // tdf#135891 - avoid visible gaps for metafile and window output as in ScOutputData::DrawGrid + const tools::Long nOneX = (bWorksInPixels || mbMetaFile) ? 1 : nOneXLogic; + const tools::Long nOneY = (bWorksInPixels || mbMetaFile) ? 1 : nOneYLogic; const tools::Long nLayoutSign = mbLayoutRTL ? -1 : 1; const tools::Long nSignedOneX = nOneX * nLayoutSign; @@ -1127,8 +1130,8 @@ void ScOutputData::DrawBackground(vcl::RenderContext& rRenderContext) if ( mbLayoutRTL ) nPosX += mnMirrorW - nOneX; - // tdf#135891 - adjust the x position to ensure the correct starting point - if (!bWorksInPixels) + // tdf#135891 - adjust the x position for printer output + if (!bWorksInPixels && !mbMetaFile) nPosX -= nLayoutSign + 1; aRect = tools::Rectangle(nPosX, nPosY - 1, nPosX, nPosY - 1 + nRowHeight); @@ -1155,7 +1158,7 @@ void ScOutputData::DrawBackground(vcl::RenderContext& rRenderContext) if (pInfo->bMerged && pInfo->pPatternAttr) { const ScMergeAttr* pMerge = - &pInfo->pPatternAttr->GetItem(ATTR_MERGE); + &pInfo->getPatternAttr()->GetItem(ATTR_MERGE); nMergedCols = std::max(1, pMerge->GetColMerge()); } @@ -1177,7 +1180,7 @@ void ScOutputData::DrawBackground(vcl::RenderContext& rRenderContext) } else if (bShowProt) // show cell protection in syntax mode { - const ScPatternAttr* pP = pInfo->pPatternAttr; + const ScPatternAttr* pP = pInfo->getPatternAttr(); if (pP) { const ScProtectionAttr& rProt = pP->GetItem(ATTR_PROTECTION); @@ -1211,11 +1214,14 @@ void ScOutputData::DrawBackground(vcl::RenderContext& rRenderContext) if (bWorksInPixels) nPosXLogic = rRenderContext.PixelToLogic(Point(nPosX, 0)).X(); - drawCells(rRenderContext, pColor, pBackground, pOldColor, pOldBackground, aRect, nPosXLogic, nLayoutSign, nOneXLogic, nOneYLogic, pDataBarInfo, pOldDataBarInfo, pIconSetInfo, pOldIconSetInfo, mpDoc->GetIconSetBitmapMap()); + // tdf#135891 - use adjusted nOneX/nOneY to avoid white gaps between colored cells + drawCells(rRenderContext, pColor, pBackground, pOldColor, pOldBackground, aRect, + nPosXLogic, nLayoutSign, nOneX, nOneY, pDataBarInfo, pOldDataBarInfo, + pIconSetInfo, pOldIconSetInfo, mpDoc->GetIconSetBitmapMap()); nPosX = nNewPosX; - // tdf#135891 - adjust the x position to ensure the correct starting point - if (!bWorksInPixels && nX == mnX1) + // tdf#135891 - adjust the x position for printer output + if (!bWorksInPixels && !mbMetaFile && nX == mnX1) nPosX += nSignedOneX + 1; } @@ -1223,7 +1229,10 @@ void ScOutputData::DrawBackground(vcl::RenderContext& rRenderContext) if (bWorksInPixels) nPosXLogic = rRenderContext.PixelToLogic(Point(nPosX, 0)).X(); - drawCells(rRenderContext, std::optional(), nullptr, pOldColor, pOldBackground, aRect, nPosXLogic, nLayoutSign, nOneXLogic, nOneYLogic, nullptr, pOldDataBarInfo, nullptr, pOldIconSetInfo, mpDoc->GetIconSetBitmapMap()); + // tdf#135891 - use adjusted nOneX/nOneY to avoid white gaps between colored cells + drawCells(rRenderContext, std::optional(), nullptr, pOldColor, + pOldBackground, aRect, nPosXLogic, nLayoutSign, nOneX, nOneY, nullptr, + pOldDataBarInfo, nullptr, pOldIconSetInfo, mpDoc->GetIconSetBitmapMap()); nArrY += nSkip; @@ -1543,6 +1552,13 @@ void ScOutputData::DrawFrame(vcl::RenderContext& rRenderContext) // *** draw the array *** + if (nColCount < 3 || nRowCount < 3) + { + SAL_WARN("sc.ui", "DrawFrame: unexpected array size:" + " nColCount=" << nColCount << " nRowCount=" << nRowCount); + return; + } + size_t nFirstCol = 1; size_t nFirstRow = 1; size_t nLastCol = nColCount - 2; @@ -1585,7 +1601,7 @@ void ScOutputData::DrawRotatedFrame(vcl::RenderContext& rRenderContext) if (mpRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && mpRowInfo[nRotY].nRotMaxCol > nRotMax) nRotMax = mpRowInfo[nRotY].nRotMaxCol; - const ScPatternAttr* pPattern; + CellAttributeHolder aPatternHolder; const SfxItemSet* pCondSet; const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); @@ -1636,21 +1652,21 @@ void ScOutputData::DrawRotatedFrame(vcl::RenderContext& rRenderContext) if ( pInfo->nRotateDir > ScRotateDir::Standard && !pInfo->bHOverlapped && !pInfo->bVOverlapped ) { - pPattern = pInfo->pPatternAttr; + aPatternHolder.setScPatternAttr(pInfo->getPatternAttr()); pCondSet = pInfo->pConditionSet; - if (!pPattern) + if (!aPatternHolder) { - pPattern = mpDoc->GetPattern( nX, nY, mnTab ); - pInfo->pPatternAttr = pPattern; + aPatternHolder.setScPatternAttr(mpDoc->GetPattern( nX, nY, mnTab )); + pInfo->pPatternAttr = aPatternHolder; pCondSet = mpDoc->GetCondResult( nX, nY, mnTab ); pInfo->pConditionSet = pCondSet; } //! LastPattern etc. - Degree100 nAttrRotate = pPattern->GetRotateVal( pCondSet ); + Degree100 nAttrRotate = aPatternHolder.getScPatternAttr()->GetRotateVal( pCondSet ); SvxRotateMode eRotMode = - pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet).GetValue(); + aPatternHolder.getScPatternAttr()->GetItem(ATTR_ROTATE_MODE, pCondSet).GetValue(); if (nAttrRotate) { @@ -1714,7 +1730,7 @@ void ScOutputData::DrawRotatedFrame(vcl::RenderContext& rRenderContext) const SvxBrushItem* pBackground(static_cast(pInfo->maBackground.getItem())); if (!pBackground) - pBackground = &pPattern->GetItem(ATTR_BACKGROUND, pCondSet); + pBackground = &aPatternHolder.getScPatternAttr()->GetItem(ATTR_BACKGROUND, pCondSet); if (bCellContrast) { // high contrast for cell borders and backgrounds -> empty background @@ -1940,6 +1956,8 @@ void ScOutputData::FindChanged() if (bAnyDirty || bAnyChanged) { + sc::MatrixResizeGuard aGuard(*mpDoc); + if (bAnyDirty) mpDoc->EnsureFormulaCellResults(ScRange(nCol1, nRow1, mnTab, nCol2, nRow2, mnTab), true); @@ -2807,7 +2825,7 @@ void ScOutputData::DrawClipMarks() SCCOL nOverX = nX; SCROW nOverY = nY; const ScMergeAttr* pMerge = - &pInfo->pPatternAttr->GetItem(ATTR_MERGE); + &pInfo->getPatternAttr()->GetItem(ATTR_MERGE); SCCOL nCountX = pMerge->GetColMerge(); for (SCCOL i=1; iGetColWidth(nOverX+i,mnTab) * mnPPTX; diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index ef16cb3ac2a6..c3f717c88cd2 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -891,7 +891,7 @@ static void lcl_DoHyperlinkResult( const OutputDevice* pDev, const tools::Rectan if ( !aURL.isEmpty() && pPDFData ) { vcl::PDFExtOutDevBookmarkEntry aBookmark; - aBookmark.nLinkId = pPDFData->CreateLink(rRect, u""_ustr); + aBookmark.nLinkId = pPDFData->CreateLink(rRect, aCellText.isEmpty() ? aURL : aCellText); aBookmark.aBookmark = aURL; std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks(); rBookmarks.push_back( aBookmark ); @@ -1442,7 +1442,7 @@ bool beginsWithRTLCharacter(const OUString& rStr) right alignment is returned. */ static SvxCellHorJustify getAlignmentFromContext( SvxCellHorJustify eInHorJust, - bool bCellIsValue, const OUString& rText, + bool bCellIsValue, bool bCellIsCallable, const OUString& rText, const ScPatternAttr& rPattern, const SfxItemSet* pCondSet, const ScDocument* pDoc, SCTAB mnTab, const bool bNumberFormatIsText ) { @@ -1461,6 +1461,8 @@ static SvxCellHorJustify getAlignmentFromContext( SvxCellHorJustify eInHorJust, } else if (bCellIsValue) //If language is not RTL eHorJustContext = bNumberFormatIsText ? SvxCellHorJustify::Left : SvxCellHorJustify::Right; + else if (bCellIsCallable) + eHorJustContext = SvxCellHorJustify::Center; else bUseWritingDirection = true; } @@ -1601,6 +1603,7 @@ void ScOutputData::LayoutStringsImpl(bool const bPixelToLogic, RowInfo* const pT const SfxItemSet* pCondSet = nullptr; const SfxItemSet* pTableSet = nullptr; bool bCellIsValue = false; + bool bCellIsCallable = false; tools::Long nNeededWidth = 0; OutputAreaParam aAreaParam; bool bMergeEmpty = false; @@ -1721,7 +1724,7 @@ void ScOutputData::LayoutStringsImpl(bool const bPixelToLogic, RowInfo* const pT if ( nCellY == nY && nCellX >= mnX1 && nCellX <= mnX2 ) { ScCellInfo& rCellInfo = pThisRowInfo->cellInfo(nCellX); - pPattern = rCellInfo.pPatternAttr; + pPattern = rCellInfo.getPatternAttr(); pCondSet = rCellInfo.pConditionSet; pTableSet = rCellInfo.pTableFormatSet; @@ -1818,11 +1821,12 @@ void ScOutputData::LayoutStringsImpl(bool const bPixelToLogic, RowInfo* const pT { ScFormulaCell* pFCell = aCell.getFormula(); bCellIsValue = pFCell->IsRunning() || pFCell->IsValue(); + bCellIsCallable = pFCell->IsCallable(); } const bool bNumberFormatIsText = lcl_isNumberFormatText( mpDoc, nCellX, nCellY, mnTab ); - eOutHorJust = getAlignmentFromContext( aVars.GetHorJust(), bCellIsValue, aVars.GetString(), - *pPattern, pCondSet, mpDoc, mnTab, bNumberFormatIsText ); + eOutHorJust = getAlignmentFromContext( aVars.GetHorJust(), bCellIsValue, bCellIsCallable, + aVars.GetString(), *pPattern, pCondSet, mpDoc, mnTab, bNumberFormatIsText ); bool bBreak = ( aVars.GetLineBreak() || aVars.GetHorJust() == SvxCellHorJustify::Block ); // #i111387# #o11817313# tdf#121040 disable automatic line breaks for all number formats @@ -1895,17 +1899,33 @@ void ScOutputData::LayoutStringsImpl(bool const bPixelToLogic, RowInfo* const pT if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip ) { tools::Long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin; - tools::Long nRepeatSize = aVars.GetTextSize().Width(); // without margin + double fRepeatSize = aVars.GetTextSize().Width(); // without margin + const OUString& aCellStr = aVars.GetString(); + + // Measuring a string containing a single copy of a short repeat string is inaccurate. + // To increase accuracy, start with a representative sample of the repeated sequence. + constexpr sal_Int32 nSampleSize = 20; + const size_t nLen = aCellStr.getLength(); + if (nLen && nLen < nSampleSize) + { + OUStringBuffer aFill(aCellStr); + aFill.ensureCapacity(nSampleSize); + while (aFill.getLength() < nSampleSize) + aFill.append(aCellStr); + fRepeatSize + = aVars.GetFmtTextWidth(aFill.copy(0, nSampleSize).makeStringAndClear()); + fRepeatSize = fRepeatSize * nLen / nSampleSize; + } + // When formatting for the printer, the text sizes don't always add up. // Round down (too few repetitions) rather than exceeding the cell size then: if ( pFmtDevice != mpRefDevice ) - ++nRepeatSize; - if ( nRepeatSize > 0 ) + ++fRepeatSize; + if (fRepeatSize > 0) { - tools::Long nRepeatCount = nAvailable / nRepeatSize; + const tools::Long nRepeatCount = nAvailable / fRepeatSize; if ( nRepeatCount > 1 ) { - OUString aCellStr = aVars.GetString(); OUStringBuffer aRepeated(aCellStr); for ( tools::Long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ ) aRepeated.append(aCellStr); @@ -4601,7 +4621,7 @@ void ScOutputData::DrawEdit(bool bPixelToLogic) !mpDoc->ColHidden(nCellX, mnTab) ) { ScCellInfo& rCellInfo = pThisRowInfo->cellInfo(nCellX); - pPattern = rCellInfo.pPatternAttr; + pPattern = rCellInfo.getPatternAttr(); pCondSet = rCellInfo.pConditionSet; pTableSet = rCellInfo.pTableFormatSet; aCell = rCellInfo.maCell; @@ -4636,7 +4656,8 @@ void ScOutputData::DrawEdit(bool bPixelToLogic) DrawEditParam aParam(pPattern, pCondSet, pTableSet, lcl_SafeIsValue(aCell)); const bool bNumberFormatIsText = lcl_isNumberFormatText( mpDoc, nCellX, nCellY, mnTab ); aParam.meHorJustContext = getAlignmentFromContext( aParam.meHorJustAttr, - aParam.mbCellIsValue, aStr, *pPattern, pCondSet, mpDoc, mnTab, bNumberFormatIsText); + aParam.mbCellIsValue, false, aStr, *pPattern, pCondSet, mpDoc, mnTab, + bNumberFormatIsText); aParam.meHorJustResult = (aParam.meHorJustAttr == SvxCellHorJustify::Block) ? SvxCellHorJustify::Block : aParam.meHorJustContext; aParam.mbPixelToLogic = bPixelToLogic; @@ -4762,7 +4783,7 @@ void ScOutputData::DrawRotated(bool bPixelToLogic) //! rest from merged cells further up do not work! bool bFromDoc = false; - pPattern = pInfo->pPatternAttr; + pPattern = pInfo->getPatternAttr(); pCondSet = pInfo->pConditionSet; if (!pPattern) { @@ -4951,7 +4972,7 @@ void ScOutputData::DrawRotated(bool bPixelToLogic) // tdf#143377 new strategy: instead of using zero for nSin, which // would be the *correct* value, continue with the corrected maximum // allowed value which is then *not* zero. This is similar to - // the behaviour before where (just due to numerical unprecisions) + // the behaviour before where (just due to numerical imprecisions) // nSin was also not zero (pure coincidence), but very close to it. // I checked and tried to make safe all places below that use // nSin and divide by it, but there is too much going on and that @@ -4970,7 +4991,7 @@ void ScOutputData::DrawRotated(bool bPixelToLogic) { //! the correct paper size for break depends on the number //! of rows, as long as the rows can not be outputted individually - //! offsetted -> therefore unlimited, so no wrapping. + //! offset -> therefore unlimited, so no wrapping. //! With offset rows the following would be correct: aPaperSize.setWidth( static_cast(nOutHeight / fabs(nSin)) ); } diff --git a/sc/source/ui/view/pivotsh.cxx b/sc/source/ui/view/pivotsh.cxx index 06e844cee276..ad64552e7c69 100644 --- a/sc/source/ui/view/pivotsh.cxx +++ b/sc/source/ui/view/pivotsh.cxx @@ -111,7 +111,7 @@ void ScPivotShell::Execute( const SfxRequest& rReq ) } ScViewData& rViewData = pViewShell->GetViewData(); - SfxItemSetFixed aArgSet( pViewShell->GetPool() ); + SfxItemSet aArgSet(SfxItemSet::makeFixedSfxItemSet( pViewShell->GetPool() )); aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA, &aQueryParam ) ); ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); diff --git a/sc/source/ui/view/preview.cxx b/sc/source/ui/view/preview.cxx index c3a2938cd907..df84d38eab7e 100644 --- a/sc/source/ui/view/preview.cxx +++ b/sc/source/ui/view/preview.cxx @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include @@ -911,6 +913,10 @@ void ScPreview::StaticInvalidate() rBindings.Invalidate(SID_ZOOM_OUT); rBindings.Invalidate(SID_PREVIEW_SCALINGFACTOR); rBindings.Invalidate(SID_ATTR_ZOOMSLIDER); + rBindings.Invalidate(SID_TOGGLEPRINTGRID); + rBindings.Invalidate(SID_TOGGLEPRINTCOLROWHEADER); + rBindings.Invalidate(SID_TOGGLEPRINTCOMMENTS); + rBindings.Invalidate(SID_TOGGLEPRINTZEROVALUES); } IMPL_STATIC_LINK_NOARG( ScPreview, InvalidateHdl, void*, void ) @@ -1079,7 +1085,7 @@ void ScPreview::MouseButtonUp( const MouseEvent& rMEvt ) } else if (bRightRulerChange && (o3tl::convert(aButtonUpPt.X(), o3tl::Length::mm100, o3tl::Length::twip) - < aLRItem.ResolveLeft({}) + < aLRItem.ResolveLeft() - o3tl::convert(aOffset.X(), o3tl::Length::mm100, o3tl::Length::twip))) { diff --git a/sc/source/ui/view/prevwsh.cxx b/sc/source/ui/view/prevwsh.cxx index 1af4c22399bc..5eb25ba65650 100644 --- a/sc/source/ui/view/prevwsh.cxx +++ b/sc/source/ui/view/prevwsh.cxx @@ -750,6 +750,43 @@ void ScPreviewShell::Execute( SfxRequest& rReq ) ScViewUtil::SetFullScreen( *this, false ); break; + case SID_TOGGLEPRINTGRID: + case SID_TOGGLEPRINTCOLROWHEADER: + case SID_TOGGLEPRINTCOMMENTS: + case SID_TOGGLEPRINTZEROVALUES: + { + OUString sStyle = pDocShell->GetDocument().GetPageStyle(pPreview->GetTab()); + ScStyleSheetPool* pStylePool = pDocShell->GetDocument().GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find(sStyle, SfxStyleFamily::Page); + OSL_ENSURE(pStyleSheet, "PageStyle not found! :-/"); + + SfxItemSet& rItemSet = pStyleSheet->GetItemSet(); + bool bOn; + switch (nSlot) + { + case SID_TOGGLEPRINTGRID: + bOn = rItemSet.Get(ATTR_PAGE_GRID).GetValue(); + rItemSet.Put(SfxBoolItem(ATTR_PAGE_GRID, !bOn)); + break; + case SID_TOGGLEPRINTCOLROWHEADER: + bOn = rItemSet.Get(ATTR_PAGE_HEADERS).GetValue(); + rItemSet.Put(SfxBoolItem(ATTR_PAGE_HEADERS, !bOn)); + break; + case SID_TOGGLEPRINTCOMMENTS: + bOn = rItemSet.Get(ATTR_PAGE_NOTES).GetValue(); + rItemSet.Put(SfxBoolItem(ATTR_PAGE_NOTES, !bOn)); + break; + case SID_TOGGLEPRINTZEROVALUES: + bOn = rItemSet.Get(ATTR_PAGE_NULLVALS).GetValue(); + rItemSet.Put(SfxBoolItem(ATTR_PAGE_NULLVALS, !bOn)); + break; + } + rReq.Done(); + GetViewFrame().GetBindings().Invalidate(nSlot); + pPreview->Invalidate(); + } + break; + default: break; } @@ -856,6 +893,42 @@ void ScPreviewShell::GetState( SfxItemSet& rSet ) if( pDocShell->IsReadOnly() ) rSet.DisableItem( nWhich ); break; + + case SID_TOGGLEPRINTGRID: + case SID_TOGGLEPRINTCOLROWHEADER: + case SID_TOGGLEPRINTCOMMENTS: + case SID_TOGGLEPRINTZEROVALUES: + { + if (pDocShell->IsReadOnly()) + rSet.DisableItem(nWhich); + else + { + OUString sStyle = pDocShell->GetDocument().GetPageStyle(pPreview->GetTab()); + ScStyleSheetPool* pStylePool = pDocShell->GetDocument().GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find(sStyle, SfxStyleFamily::Page); + OSL_ENSURE(pStyleSheet, "PageStyle not found! :-/"); + const SfxItemSet& rItemSet = pStyleSheet->GetItemSet(); + + bool bOn = false; + switch (nWhich) + { + case SID_TOGGLEPRINTGRID: + bOn = rItemSet.Get(ATTR_PAGE_GRID).GetValue(); + break; + case SID_TOGGLEPRINTCOLROWHEADER: + bOn = rItemSet.Get(ATTR_PAGE_HEADERS).GetValue(); + break; + case SID_TOGGLEPRINTCOMMENTS: + bOn = rItemSet.Get(ATTR_PAGE_NOTES).GetValue(); + break; + case SID_TOGGLEPRINTZEROVALUES: + bOn = rItemSet.Get(ATTR_PAGE_NULLVALS).GetValue(); + break; + } + rSet.Put(SfxBoolItem(nWhich, bOn)); + } + } + break; } nWhich = aIter.NextWhich(); diff --git a/sc/source/ui/view/printfun.cxx b/sc/source/ui/view/printfun.cxx index 426cdba011a8..1a4499a8a561 100644 --- a/sc/source/ui/view/printfun.cxx +++ b/sc/source/ui/view/printfun.cxx @@ -417,7 +417,7 @@ static void lcl_HidePrint( const ScTableInfo& rTabInfo, SCCOL nX1, SCCOL nX2 ) ScCellInfo& rCellInfo = pThisRowInfo->cellInfo(nX); ScBasicCellInfo& rBasicCellInfo = pThisRowInfo->basicCellInfo(nX); if (!rBasicCellInfo.bEmptyCellText) - if (rCellInfo.pPatternAttr-> + if (rCellInfo.getPatternAttr()-> GetItem(ATTR_PROTECTION, rCellInfo.pConditionSet).GetHidePrint()) { rCellInfo.maCell.clear(); @@ -539,9 +539,7 @@ void ScPrintFunc::DrawToDev(ScDocument& rDoc, OutputDevice* pDev, double /* nPri // If no lines, still leave space for grid lines // (would be elseways cut away) - // tdf#135891 - adjust the x position to ensure the correct starting point - const Size aOnePixel = pDev->PixelToLogic(Size(1, 1)); - nScrX += aOnePixel.Width(); + nScrX += 1; nScrY += 1; ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, &rDoc, nTab, @@ -668,7 +666,7 @@ static void lcl_FillHFParam( ScPrintHFParam& rParam, const SfxItemSet* pHFSet ) rParam.nHeight = pHFSet->Get(ATTR_PAGE_SIZE).GetSize().Height(); const SvxLRSpaceItem* pHFLR = &pHFSet->Get(ATTR_LRSPACE); tools::Long nTmp; - nTmp = pHFLR->ResolveLeft({}); + nTmp = pHFLR->ResolveLeft(); rParam.nLeft = nTmp < 0 ? 0 : sal_uInt16(nTmp); nTmp = pHFLR->ResolveRight({}); rParam.nRight = nTmp < 0 ? 0 : sal_uInt16(nTmp); @@ -716,7 +714,7 @@ bool ScPrintFunc::AdjustPrintArea( bool bNew ) bool bForcedChangeRow = false; // #i53558# Crop entire column of old row limit to real print area with - // some fuzzyness. + // some fuzziness. if (!bChangeRow && nStartRow == 0) { SCROW nPAEndRow; @@ -859,7 +857,7 @@ void ScPrintFunc::InitParam( const ScPrintOptions* pOptions ) // TabPage "Page" const SvxLRSpaceItem* pLRItem = &pParamSet->Get( ATTR_LRSPACE ); tools::Long nTmp; - nTmp = pLRItem->ResolveLeft({}); + nTmp = pLRItem->ResolveLeft(); nLeftMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp); nTmp = pLRItem->ResolveRight({}); nRightMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp); @@ -1018,6 +1016,11 @@ void ScPrintFunc::InitParam( const ScPrintOptions* pOptions ) aAreaParam.aPrintArea.aStart.SetTab(nPrintTab); aAreaParam.aPrintArea.aEnd.SetTab(nPrintTab); } + else if (!rDoc.IsVisible(nPrintTab)) + { + aAreaParam.bPrintArea = true; + bPrintCurrentTable = false; + } else if (bHasPrintRange) { if ( pPrintArea ) // at least one set? @@ -1030,24 +1033,14 @@ void ScPrintFunc::InitParam( const ScPrintOptions* pOptions ) } else { - // do not print hidden sheets with "Print entire sheet" flag - bPrintCurrentTable = rDoc.IsPrintEntireSheet( nPrintTab ) && rDoc.IsVisible( nPrintTab ); + bPrintCurrentTable = rDoc.IsPrintEntireSheet(nPrintTab); aAreaParam.bPrintArea = !bPrintCurrentTable; // otherwise the table is always counted } } else { - // don't print hidden tables if there's no print range defined there - if ( rDoc.IsVisible( nPrintTab ) ) - { - aAreaParam.bPrintArea = false; - bPrintCurrentTable = true; - } - else - { - aAreaParam.bPrintArea = true; // otherwise the table is always counted - bPrintCurrentTable = false; - } + aAreaParam.bPrintArea = false; + bPrintCurrentTable = true; } if ( oRepeatCol ) diff --git a/sc/source/ui/view/reffact.cxx b/sc/source/ui/view/reffact.cxx index 9136d93b218c..5f8bb5b9fa2a 100644 --- a/sc/source/ui/view/reffact.cxx +++ b/sc/source/ui/view/reffact.cxx @@ -61,33 +61,31 @@ SfxChildWinInfo ScValidityRefChildWin::GetInfo() const namespace { - ScTabViewShell* lcl_GetTabViewShell( const SfxBindings* pBindings ); +ScTabViewShell* lcl_GetTabViewShell(const SfxBindings& rBindings); } -#define IMPL_CONTROLLER_CHILD_CTOR(Class,sid) \ - Class::Class( vcl::Window* pParentP, \ - sal_uInt16 nId, \ - SfxBindings* p, \ - SfxChildWinInfo* pInfo ) \ - : SfxChildWindow(pParentP, nId) \ - { \ - /************************************************************************************/\ - /* When a new document is creating, the SfxViewFrame may be ready, */\ - /* But the ScTabViewShell may have not been activated yet. In this */\ - /* situation, SfxViewShell::Current() does not get the correct shell, */\ - /* and we should lcl_GetTabViewShell( p ) instead of SfxViewShell::Current() */\ - /************************************************************************************/\ - ScTabViewShell* pViewShell = lcl_GetTabViewShell( p ); \ - if (!pViewShell) \ - pViewShell = dynamic_cast( SfxViewShell::Current() ); \ - OSL_ENSURE( pViewShell, "missing view shell :-(" ); \ - SetController( pViewShell ? \ - pViewShell->CreateRefDialogController( p, this, pInfo, pParentP->GetFrameWeld(), sid ) : nullptr ); \ - if (pViewShell && !GetController()) \ - pViewShell->GetViewFrame().SetChildWindow( nId, false ); \ +#define IMPL_CONTROLLER_CHILD_CTOR(Class, sid) \ + Class::Class(vcl::Window* pParentP, sal_uInt16 nId, SfxBindings& rBindings, \ + SfxChildWinInfo& rInfo) \ + : SfxChildWindow(pParentP, nId) \ + { \ + /************************************************************************************/ \ + /* When a new document is creating, the SfxViewFrame may be ready, */ \ + /* But the ScTabViewShell may have not been activated yet. In this */ \ + /* situation, SfxViewShell::Current() does not get the correct shell, */ \ + /* and we should lcl_GetTabViewShell(rBindings) instead of SfxViewShell::Current() */ \ + /************************************************************************************/ \ + ScTabViewShell* pViewShell = lcl_GetTabViewShell(rBindings); \ + if (!pViewShell) \ + pViewShell = dynamic_cast(SfxViewShell::Current()); \ + OSL_ENSURE(pViewShell, "missing view shell :-("); \ + SetController(pViewShell ? pViewShell->CreateRefDialogController( \ + rBindings, this, rInfo, pParentP->GetFrameWeld(), sid) \ + : nullptr); \ + if (pViewShell && !GetController()) \ + pViewShell->GetViewFrame().SetChildWindow(nId, false); \ } - IMPL_CONTROLLER_CHILD_CTOR( ScNameDlgWrapper, FID_DEFINE_NAME ) IMPL_CONTROLLER_CHILD_CTOR( ScNameDefDlgWrapper, FID_ADD_NAME ) @@ -127,15 +125,13 @@ static tools::Long nScSimpleRefX; static tools::Long nScSimpleRefY; static bool bAutoReOpen = true; -ScSimpleRefDlgWrapper::ScSimpleRefDlgWrapper( vcl::Window* pParentP, - sal_uInt16 nId, - SfxBindings* p, - SfxChildWinInfo* pInfo ) - : SfxChildWindow(pParentP, nId) +ScSimpleRefDlgWrapper::ScSimpleRefDlgWrapper(vcl::Window* pParentP, sal_uInt16 nId, + SfxBindings& rBindings, SfxChildWinInfo& rInfo) + : SfxChildWindow(pParentP, nId) { ScTabViewShell* pViewShell = nullptr; - SfxDispatcher* pDisp = p->GetDispatcher(); + SfxDispatcher* pDisp = rBindings.GetDispatcher(); if ( pDisp ) { SfxViewFrame* pViewFrm = pDisp->GetFrame(); @@ -145,17 +141,18 @@ ScSimpleRefDlgWrapper::ScSimpleRefDlgWrapper( vcl::Window* pParentP, OSL_ENSURE( pViewShell, "missing view shell :-(" ); - if(pInfo!=nullptr && bScSimpleRefFlag) + if (bScSimpleRefFlag) { - pInfo->aPos.setX(nScSimpleRefX ); - pInfo->aPos.setY(nScSimpleRefY ); - pInfo->aSize.setHeight(nScSimpleRefHeight ); - pInfo->aSize.setWidth(nScSimpleRefWidth ); + rInfo.aPos.setX(nScSimpleRefX); + rInfo.aPos.setY(nScSimpleRefY); + rInfo.aSize.setHeight(nScSimpleRefHeight); + rInfo.aSize.setWidth(nScSimpleRefWidth); } SetController(nullptr); if (bAutoReOpen && pViewShell) - SetController(pViewShell->CreateRefDialogController(p, this, pInfo, pParentP->GetFrameWeld(), WID_SIMPLE_REF)); + SetController(pViewShell->CreateRefDialogController( + rBindings, this, rInfo, pParentP->GetFrameWeld(), WID_SIMPLE_REF)); if (!GetController()) { @@ -216,21 +213,20 @@ void ScSimpleRefDlgWrapper::StartRefInput() // ScAcceptChgDlgWrapper //FIXME: should be moved into ViewShell -ScAcceptChgDlgWrapper::ScAcceptChgDlgWrapper(vcl::Window* pParentP, - sal_uInt16 nId, - SfxBindings* pBindings, - SfxChildWinInfo* pInfo ) : - SfxChildWindow( pParentP, nId ) +ScAcceptChgDlgWrapper::ScAcceptChgDlgWrapper(vcl::Window* pParentP, sal_uInt16 nId, + SfxBindings& rBindings, SfxChildWinInfo& rInfo) + : SfxChildWindow(pParentP, nId) { ScTabViewShell* pViewShell = dynamic_cast( SfxViewShell::Current() ); OSL_ENSURE( pViewShell, "missing view shell :-(" ); if (pViewShell) { - auto xDlg = std::make_shared(pBindings, this, pParentP->GetFrameWeld(), pViewShell->GetViewData()); + auto xDlg = std::make_shared(&rBindings, this, pParentP->GetFrameWeld(), + pViewShell->GetViewData()); SetController(xDlg); - pInfo->nFlags = SfxChildWindowFlags::NEVERHIDE; - xDlg->Initialize( pInfo ); + rInfo.nFlags = SfxChildWindowFlags::NEVERHIDE; + xDlg->Initialize(rInfo); } else SetController( nullptr ); @@ -256,25 +252,23 @@ IMPL_CONTROLLER_CHILD_CTOR(ScHighlightChgDlgWrapper, FID_CHG_SHOW) namespace { - ScTabViewShell * lcl_GetTabViewShell( const SfxBindings *pBindings ) - { - if( pBindings ) - if( SfxDispatcher* pDisp = pBindings ->GetDispatcher() ) - if( SfxViewFrame *pFrm = pDisp->GetFrame() ) - if( SfxViewShell* pViewSh = pFrm->GetViewShell() ) - return dynamic_cast( pViewSh ); +ScTabViewShell* lcl_GetTabViewShell(const SfxBindings& rBindings) +{ + if (SfxDispatcher* pDisp = rBindings.GetDispatcher()) + if (SfxViewFrame* pFrm = pDisp->GetFrame()) + if (SfxViewShell* pViewSh = pFrm->GetViewShell()) + return dynamic_cast(pViewSh); - return nullptr; - } + return nullptr; +} } -ScValidityRefChildWin::ScValidityRefChildWin(vcl::Window* pParentP, - sal_uInt16 nId, - const SfxBindings* p, - SAL_UNUSED_PARAMETER SfxChildWinInfo* /*pInfo*/ ) - : SfxChildWindow(pParentP, nId) - , m_bVisibleLock(false) - , m_bFreeWindowLock(false) +ScValidityRefChildWin::ScValidityRefChildWin(vcl::Window* pParentP, sal_uInt16 nId, + const SfxBindings& rBindings, + SAL_UNUSED_PARAMETER SfxChildWinInfo& /*rInfo*/) + : SfxChildWindow(pParentP, nId) + , m_bVisibleLock(false) + , m_bFreeWindowLock(false) { SetWantsFocus( false ); std::shared_ptr xDlg(ScValidationDlg::Find1AliveObject(pParentP->GetFrameWeld())); @@ -283,7 +277,7 @@ ScValidityRefChildWin::ScValidityRefChildWin(vcl::Window* pParentP, if (xDlg) pViewShell = static_cast(xDlg.get())->GetTabViewShell(); else - pViewShell = lcl_GetTabViewShell( p ); + pViewShell = lcl_GetTabViewShell(rBindings); if (!pViewShell) pViewShell = dynamic_cast( SfxViewShell::Current() ); OSL_ENSURE( pViewShell, "missing view shell :-(" ); diff --git a/sc/source/ui/view/select.cxx b/sc/source/ui/view/select.cxx index b90a9d330469..470ad1b528fe 100644 --- a/sc/source/ui/view/select.cxx +++ b/sc/source/ui/view/select.cxx @@ -425,17 +425,6 @@ void ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool /* bDon SetCursorAtCell( nPosX, nPosY, bScroll ); } -bool ScViewFunctionSet::CheckRefBounds(SCCOL nPosX, SCROW nPosY) -{ - SCCOL startX = m_rViewData.GetRefStartX(); - SCROW startY = m_rViewData.GetRefStartY(); - - SCCOL endX = m_rViewData.GetRefEndX(); - SCROW endY = m_rViewData.GetRefEndY(); - - return nPosX >= startX && nPosX <= endX && nPosY >= startY && nPosY <= endY; -} - bool ScViewFunctionSet::SetCursorAtCell( SCCOL nPosX, SCROW nPosY, bool bScroll ) { ScTabView* pView = m_rViewData.GetView(); @@ -486,7 +475,7 @@ bool ScViewFunctionSet::SetCursorAtCell( SCCOL nPosX, SCROW nPosY, bool bScroll if (bRefMode) { // if no input is possible from this doc, don't move the reference cursor around - if ( !ScModule::get()->IsModalMode(m_rViewData.GetSfxDocShell()) && (!CheckRefBounds(nPosX, nPosY) || SfxLokHelper::getDeviceFormFactor() != LOKDeviceFormFactor::MOBILE)) + if ( !ScModule::get()->IsModalMode(m_rViewData.GetSfxDocShell())) { if (!m_bAnchor) { @@ -494,8 +483,7 @@ bool ScViewFunctionSet::SetCursorAtCell( SCCOL nPosX, SCROW nPosY, bool bScroll pView->InitRefMode( nPosX, nPosY, m_rViewData.CurrentTabForData(), SC_REFTYPE_REF ); } - if(SfxLokHelper::getDeviceFormFactor() != LOKDeviceFormFactor::MOBILE) - pView->UpdateRef( nPosX, nPosY, m_rViewData.CurrentTabForData() ); + pView->UpdateRef( nPosX, nPosY, m_rViewData.CurrentTabForData() ); pView->SelectionChanged(); } diff --git a/sc/source/ui/view/spelldialog.cxx b/sc/source/ui/view/spelldialog.cxx index 71ab6f50883a..c85311fe3549 100644 --- a/sc/source/ui/view/spelldialog.cxx +++ b/sc/source/ui/view/spelldialog.cxx @@ -39,15 +39,16 @@ SFX_IMPL_CHILDWINDOW_WITHID( ScSpellDialogChildWindow, SID_SPELL_DIALOG ) -ScSpellDialogChildWindow::ScSpellDialogChildWindow( vcl::Window* pParentP, sal_uInt16 nId, - SfxBindings* pBindings, SAL_UNUSED_PARAMETER SfxChildWinInfo* /*pInfo*/ ) : - svx::SpellDialogChildWindow( pParentP, nId, pBindings ), - mpViewShell( nullptr ), - mpViewData( nullptr ), - mpDocShell( nullptr ), - mpDoc( nullptr ), - mbNeedNextObj( false ), - mbOldIdleEnabled(true) +ScSpellDialogChildWindow::ScSpellDialogChildWindow(vcl::Window* pParentP, sal_uInt16 nId, + SfxBindings& rBindings, + SAL_UNUSED_PARAMETER SfxChildWinInfo& /*rInfo*/) + : svx::SpellDialogChildWindow(pParentP, nId, &rBindings) + , mpViewShell(nullptr) + , mpViewData(nullptr) + , mpDocShell(nullptr) + , mpDoc(nullptr) + , mbNeedNextObj(false) + , mbOldIdleEnabled(true) { Init(); } diff --git a/sc/source/ui/view/spelleng.cxx b/sc/source/ui/view/spelleng.cxx index 99aa1e903deb..368178b9c7d1 100644 --- a/sc/source/ui/view/spelleng.cxx +++ b/sc/source/ui/view/spelleng.cxx @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -126,8 +126,8 @@ bool ScConversionEngineBase::FindNextConversionCell() if (!bSimpleString || eCellType == CELLTYPE_EDIT) { - std::unique_ptr pEditObj(CreateTextObject()); - mrDoc.SetEditText(aPos, *pEditObj, GetItemPool()); + EditTextObject aEditObj(CreateTextObject()); + mrDoc.SetEditText(aPos, aEditObj, GetItemPool()); } else { diff --git a/sc/source/ui/view/tabcont.cxx b/sc/source/ui/view/tabcont.cxx index c200f43959cf..2eb334b89fc1 100644 --- a/sc/source/ui/view/tabcont.cxx +++ b/sc/source/ui/view/tabcont.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -77,7 +78,10 @@ ScTabControl::ScTabControl( vcl::Window* pParent, ScViewData& rData ) } } - SetCurPageId( static_cast(rViewData.GetTabNumber()) + 1 ); + SCTAB nCurTab = rViewData.GetTabNumber(); + if (!rDoc.IsVisible(nCurTab)) + nCurTab = rViewData.GetDefaultViewTab(); + SetCurPageId(sal_uInt16(nCurTab) + 1); SetSizePixel( Size(SC_TABBAR_DEFWIDTH, 0) ); @@ -98,9 +102,10 @@ IMPL_LINK(ScTabControl, ShowPageList, const CommandEvent &, rEvent, void) std::unique_ptr xBuilder(Application::CreateBuilder(pPopupParent, u"modules/scalc/ui/pagelistmenu.ui"_ustr)); std::unique_ptr xPopup(xBuilder->weld_menu(u"menu"_ustr)); - sal_uInt16 nCurPageId = GetCurPageId(); - ScDocument& rDoc = rViewData.GetDocument(); + SCTAB nDefaultOfView = rViewData.GetDefaultViewTab(); + sal_uInt16 nCurPageId = sal_uInt16(nDefaultOfView) + 1; + SCTAB nCount = rDoc.GetTableCount(); for (SCTAB i=0; i(i)+1, rMark.GetTableSelect(i) ); - SetCurPageId( static_cast(rViewData.GetTabNumber()) + 1 ); + SCTAB nLockedCurTab = rViewData.GetTabNumber(); + if (!rDoc.IsVisible(nLockedCurTab)) + nLockedCurTab = rViewData.GetDefaultViewTab(); + SetCurPageId(sal_uInt16(nLockedCurTab) + 1); return; } @@ -274,8 +282,17 @@ void ScTabControl::Select() if (!nCurId) return; // for Excel import it can happen that everything is hidden sal_uInt16 nPage = nCurId - 1; + // If user clicked a default tab that has a last-active sheet view, restore it + { + SCTAB nClickedTab = SCTAB(nPage); + SCTAB nLastViewTab = rViewData.GetLastSheetViewTab(nClickedTab); + if (nLastViewTab != nClickedTab && !rDoc.IsVisible(nLastViewTab)) + nPage = sal_uInt16(nLastViewTab); + } + // OLE-inplace deactivate - if ( nPage != static_cast(rViewData.GetTabNumber()) ) + SCTAB nDefaultSheet = rDoc.GetDefaultViewTableNumber(SCTAB(nPage)); + if (nDefaultSheet != rViewData.GetDefaultViewTab()) rViewData.GetView()->DrawMarkListHasChanged(); // InputEnterHandler onlw when not reference input @@ -396,7 +413,11 @@ void ScTabControl::UpdateStatus() } } } - SetCurPageId( static_cast(rViewData.GetTabNumber()) + 1 ); + SCTAB nCurrentTab = rViewData.GetTabNumber(); + // If on a hidden sheet view tab, show the default tab as current selected one in the tab bar + if (!rDoc.IsVisible(nCurrentTab)) + nCurrentTab = rViewData.GetDefaultViewTab(); + SetCurPageId(sal_uInt16(nCurrentTab) + 1); if (bActive) { diff --git a/sc/source/ui/view/tabsplit.cxx b/sc/source/ui/view/tabsplit.cxx index bd140ede83dc..14118c26392a 100644 --- a/sc/source/ui/view/tabsplit.cxx +++ b/sc/source/ui/view/tabsplit.cxx @@ -75,7 +75,7 @@ void ScTabSplitter::Paint( vcl::RenderContext& rRenderContext, const tools::Rect const tools::Long xc = rRect.Right() + rRect.Left(); const tools::Long h4 = rRect.GetHeight() / 4; // First xc fraction is truncated, second one is rounded. This will draw a centered line - // in handlers with odd width and a centered rectangle in those with even width. + // in handles with odd width and a centered rectangle in those with even width. rRenderContext.DrawRect(tools::Rectangle(Point(xc / 2, rRect.Top() + h4), Point((xc + 1) / 2, rRect.Bottom() - h4))); break; @@ -106,7 +106,7 @@ void ScTabSplitter::Paint( vcl::RenderContext& rRenderContext, const tools::Rect const tools::Long yc = rRect.Top() + rRect.Bottom(); const tools::Long w4 = rRect.GetWidth() / 4; // First yc fraction is truncated, second one is rounded. This will draw a centered line - // in handlers with odd height and a centered rectangle in those with even height. + // in handles with odd height and a centered rectangle in those with even height. GetOutDev()->DrawRect(tools::Rectangle(Point(rRect.Left() + w4, yc / 2), Point(rRect.Right() - w4, (yc + 1) / 2))); break; diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx index 946709e96d77..0cd831d1dc64 100644 --- a/sc/source/ui/view/tabview.cxx +++ b/sc/source/ui/view/tabview.cxx @@ -139,6 +139,8 @@ void ScCornerButton::MouseButtonDown( const MouseEvent& rMEvt ) { ScTabViewShell* pViewSh = rViewData.GetViewShell(); pViewSh->SetActive(); // Appear and SetViewFrame + // tdf#84694 - deselect draw objects before selecting the entire sheet + pViewSh->DrawDeselectAll(); pViewSh->ActiveGrabFocus(); bool bControl = rMEvt.IsMod1(); @@ -1588,15 +1590,14 @@ void ScTabView::UpdateHeaderWidth( const ScVSplitPos* pWhich, const SCROW* pPosY } } - tools::Long nSmall = pRowBar[SC_SPLIT_BOTTOM]->GetSmallWidth(); - tools::Long nBig = pRowBar[SC_SPLIT_BOTTOM]->GetBigWidth(); - tools::Long nDiff = nBig - nSmall; - - if (nEndPos>10000) - nEndPos = 10000; - else if (nEndPos<1) // avoid extra step at 0 (when only one row is visible) - nEndPos = 1; - tools::Long nWidth = nBig - ( 10000 - nEndPos ) * nDiff / 10000; + // tdf#148507 - update row header width only on digit changes + tools::Long nWidth = pRowBar[SC_SPLIT_BOTTOM]->GetSmallWidth(); + if (nEndPos >= 999999) + nWidth = pRowBar[SC_SPLIT_BOTTOM]->GetBigWidth(); + else if (nEndPos >= 99999) + nWidth = pRowBar[SC_SPLIT_BOTTOM]->GetLargeWidth(); + else if (nEndPos >= 9999) + nWidth = pRowBar[SC_SPLIT_BOTTOM]->GetMedWidth(); if (nWidth == pRowBar[SC_SPLIT_BOTTOM]->GetWidth() || bInUpdateHeader) return; diff --git a/sc/source/ui/view/tabview2.cxx b/sc/source/ui/view/tabview2.cxx index eaedba7e2b72..f637aaa930a0 100644 --- a/sc/source/ui/view/tabview2.cxx +++ b/sc/source/ui/view/tabview2.cxx @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -1661,9 +1661,8 @@ void ScTabView::ErrorMessage(TranslateId pGlobStrId) } } - m_xMessageBox.reset(Application::CreateMessageDialog(pParent, - VclMessageType::Info, VclButtonsType::Ok, - ScResId(pGlobStrId))); + m_xMessageBox = Application::CreateMessageDialog(pParent, VclMessageType::Info, + VclButtonsType::Ok, ScResId(pGlobStrId)); if (comphelper::LibreOfficeKit::isActive()) m_xMessageBox->SetInstallLOKNotifierHdl(LINK(this, ScTabView, InstallLOKNotifierHdl)); diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx index c64b381d1421..3f4661b0af58 100644 --- a/sc/source/ui/view/tabview3.cxx +++ b/sc/source/ui/view/tabview3.cxx @@ -1404,13 +1404,15 @@ void ScTabView::MoveCursorEnd( SCCOL nMovX, SCROW nMovY, ScFollowMode eMode, boo if ( nMovX > 0 || nMovY > 0 ) rDoc.GetPrintArea( nTab, nUsedX, nUsedY ); // get end - if (nMovX<0) - nNewX=0; + if (nMovX < 0) + // tdf#107994 - move to the freeze pane splitter position + nNewX = aViewData.GetHSplitMode() == SC_SPLIT_FIX ? aViewData.GetFixPosX() : 0; else if (nMovX>0) nNewX=nUsedX; // last used range if (nMovY<0) - nNewY=0; + // tdf#107994 - move to the freeze pane splitter position + nNewY = aViewData.GetVSplitMode() == SC_SPLIT_FIX ? aViewData.GetFixPosY() : 0; else if (nMovY>0) nNewY=nUsedY; @@ -1899,9 +1901,6 @@ void ScTabView::SelectTabPage( const sal_uInt16 nTab ) void ScTabView::SetTabNo( SCTAB nTab, bool bNew, bool bExtendSelection, bool bSameTabButMoved ) { - ScTabViewShell* pViewShell = aViewData.GetViewShell(); - pViewShell->SetTabChangeInProgress(true); - if ( !ValidTab(nTab) ) { OSL_FAIL("SetTabNo: invalid sheet"); @@ -1937,7 +1936,9 @@ void ScTabView::SetTabNo( SCTAB nTab, bool bNew, bool bExtendSelection, bool bSa SCTAB nTabCount = rDoc.GetTableCount(); SCTAB nOldPos = nTab; - while (!rDoc.IsVisible(nTab)) // search for next visible + + // Search for next visible + while (!rDoc.IsVisible(nTab) && !rDoc.IsSheetViewHolder(nTab)) { bool bUp = (nTab>=nOldPos); if (bUp) @@ -1992,7 +1993,7 @@ void ScTabView::SetTabNo( SCTAB nTab, bool bNew, bool bExtendSelection, bool bSa bool bAllSelected = true; for (SCTAB nSelTab = 0; nSelTab < nTabCount; ++nSelTab) { - if (!rDoc.IsVisible(nSelTab) || rMark.GetTableSelect(nSelTab)) + if ((!rDoc.IsVisible(nSelTab) && !rDoc.IsSheetViewHolder(nSelTab)) || rMark.GetTableSelect(nSelTab)) { if (nTab == nSelTab) // This tab is already in selection. Keep the current @@ -2103,6 +2104,7 @@ void ScTabView::SetTabNo( SCTAB nTab, bool bNew, bool bExtendSelection, bool bSa // disable invalidations for kit during tab switching { + ScTabViewShell* pViewShell = aViewData.GetViewShell(); SfxLokCallbackInterface* pCallback = pViewShell->getLibreOfficeKitViewCallback(); pViewShell->setLibreOfficeKitViewCallback(nullptr); comphelper::ScopeGuard aOutputGuard( @@ -2128,7 +2130,7 @@ void ScTabView::SetTabNo( SCTAB nTab, bool bNew, bool bExtendSelection, bool bSa rBindings.Invalidate( SID_STYLE_FAMILY4 ); // Designer rBindings.Invalidate( SID_TABLES_COUNT ); - rBindings.Invalidate(FID_CURRENT_SHEET_VIEW); + rBindings.Invalidate(FID_SELECT_SHEET_VIEW); if (pScMod->IsRefDialogOpen()) { @@ -2147,7 +2149,6 @@ void ScTabView::SetTabNo( SCTAB nTab, bool bNew, bool bExtendSelection, bool bSa } OnLibreOfficeKitTabChanged(); - pViewShell->SetTabChangeInProgress(false); } void ScTabView::AddWindowToForeignEditView(SfxViewShell* pViewShell, ScSplitPos eWhich) @@ -2166,11 +2167,11 @@ void ScTabView::OnLibreOfficeKitTabChanged() return; ScTabViewShell* pThisViewShell = aViewData.GetViewShell(); - SCTAB nThisTabNo = pThisViewShell->GetViewData().CurrentTabForData(); + SCTAB nThisTabNo = pThisViewShell->GetViewData().GetTabNumber(); auto lTabSwitch = [pThisViewShell, nThisTabNo] (ScTabViewShell* pOtherViewShell) { ScViewData& rOtherViewData = pOtherViewShell->GetViewData(); - SCTAB nOtherTabNo = rOtherViewData.CurrentTabForData(); + SCTAB nOtherTabNo = rOtherViewData.GetTabNumber(); if (nThisTabNo == nOtherTabNo) { for (int i = 0; i < 4; ++i) @@ -3608,12 +3609,9 @@ void ScTabView::CheckNeedsRepaint() bool ScTabView::NeedsRepaint() { - for (VclPtr & pWin : pGridWin) - { - if (pWin && pWin->IsVisible() && pWin->NeedsRepaint()) - return true; - } - return false; + return std::any_of(pGridWin.begin(), pGridWin.end(), [](const VclPtr& pWin) { + return pWin && pWin->IsVisible() && pWin->NeedsRepaint(); + }); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/tabview5.cxx b/sc/source/ui/view/tabview5.cxx index e55726913378..167d83f4a238 100644 --- a/sc/source/ui/view/tabview5.cxx +++ b/sc/source/ui/view/tabview5.cxx @@ -297,8 +297,11 @@ void ScTabView::ImplTabChanged(bool bSameTabButMoved) DrawDeselectAll(); // end also text edit mode SCTAB nTab = aViewData.CurrentTabForData(); + // For sheet view tabs, show the default view's draw page so that + // all draw operations target the default view's page. + SCTAB nDrawTab = aViewData.GetDocument().GetDefaultViewTableNumber(nTab); pDrawView->HideSdrPage(); - pDrawView->ShowSdrPage(pDrawView->GetModel().GetPage(nTab)); + pDrawView->ShowSdrPage(pDrawView->GetModel().GetPage(nDrawTab)); UpdateLayerLocks(); diff --git a/sc/source/ui/view/tabvwsh3.cxx b/sc/source/ui/view/tabvwsh3.cxx index ef488e2d911a..826a32f6491c 100644 --- a/sc/source/ui/view/tabvwsh3.cxx +++ b/sc/source/ui/view/tabvwsh3.cxx @@ -258,7 +258,7 @@ void ScTabViewShell::ExecProtectTable( SfxRequest& rReq ) ScModule* pScMod = ScModule::get(); const SfxItemSet* pReqArgs = rReq.GetArgs(); ScDocument& rDoc = GetViewData().GetDocument(); - SCTAB nTab = GetViewData().CurrentTabForData(); + SCTAB nTab = GetViewData().GetTabNumber(); bool bOldProtection = rDoc.IsTabProtected(nTab); if( pReqArgs ) @@ -686,8 +686,13 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) if ( rDoc.GetTable( aAddress, nNameTab ) ) { bFound = true; - if ( nNameTab != nTab ) - SetTabNo( nNameTab ); + if (nNameTab != nTab) + { + if (!rDoc.IsVisible(nNameTab)) + ErrorMessage(STR_ERR_HIDDEN_SHEET); + else + SetTabNo(nNameTab); + } } } @@ -1064,36 +1069,13 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) case FID_REMOVE_SHEET_VIEW: RemoveCurrentSheetView(); break; - case FID_SWITCH_TO_NEXT_SHEET_VIEW: - SwitchSheetView(sc::SwitchSheetViewDirection::Next); - break; - case FID_SWITCH_TO_PREVIOUS_SHEET_VIEW: - SwitchSheetView(sc::SwitchSheetViewDirection::Previous); - break; case FID_EXIT_SHEET_VIEW: ExitSheetView(); break; case FID_SELECT_SHEET_VIEW: - { - ScViewData& rViewData = GetViewData(); - auto pDialog = std::make_shared(GetFrameWeld(), rViewData); - weld::DialogController::runAsync(pDialog, [this, pDialog](sal_uInt32 nResult) { - if (RET_OK != nResult) - return; - - sc::SheetViewID nID = pDialog->getSelectedSheetViewID(); - if (nID != sc::InvalidSheetViewID) - { - SelectSheetView(nID); - } - }); - rReq.Done(); - } - break; - case FID_CURRENT_SHEET_VIEW: { const SfxPoolItem* pItem = nullptr; - if (pReqArgs != nullptr && pReqArgs->HasItem(FID_CURRENT_SHEET_VIEW, &pItem)) + if (pReqArgs != nullptr && pReqArgs->HasItem(FN_PARAM_1, &pItem)) { const sal_Int32 nValue = static_cast(pItem)->GetValue(); sc::SheetViewID nID(nValue); @@ -1102,6 +1084,21 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) SelectSheetView(nID); } } + else + { + ScViewData& rViewData = GetViewData(); + auto pDialog = std::make_shared(GetFrameWeld(), rViewData); + weld::DialogController::runAsync(pDialog, [this, pDialog](sal_uInt32 nResult) { + if (RET_OK != nResult) + return; + + sc::SheetViewID nID = pDialog->getSelectedSheetViewID(); + if (nID != sc::InvalidSheetViewID) + { + SelectSheetView(nID); + } + }); + } rReq.Done(); } break; @@ -1126,7 +1123,7 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) } else { - SfxItemSetFixed aSet( GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet( GetPool() )); SvxZoomItem aZoomItem( eOldZoomType, nOldZoom, SID_ATTR_ZOOM ); ScopedVclPtr pDlg; ScMarkData& rMark = GetViewData().GetMarkData(); @@ -1374,7 +1371,7 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) else { ScViewData& rViewData = GetViewData(); - SCTAB nThisTab = rViewData.CurrentTabForData(); + SCTAB nThisTab = rViewData.GetTabNumber(); bool bChangedX = false, bChangedY = false; if (rViewData.GetLOKSheetFreezeIndex(true) > 0 || rViewData.GetLOKSheetFreezeIndex(false) > 0 ) // remove freeze @@ -1396,7 +1393,7 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) // Invalidate the slot for all views on the same tab of the document. SfxLokHelper::forEachOtherView(this, [nThisTab](ScTabViewShell* pOther) { ScViewData& rOtherViewData = pOther->GetViewData(); - if (rOtherViewData.CurrentTabForData() != nThisTab) + if (rOtherViewData.GetTabNumber() != nThisTab) return; SfxBindings& rOtherBind = rOtherViewData.GetBindings(); @@ -1426,7 +1423,7 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) if (comphelper::LibreOfficeKit::isActive()) { ScViewData& rViewData = GetViewData(); - SCTAB nThisTab = rViewData.CurrentTabForData(); + SCTAB nThisTab = rViewData.GetTabNumber(); bool bChanged = rViewData.SetLOKSheetFreezeIndex(nFreezeIndex, bIsCol); rReq.Done(); if (bChanged) @@ -1436,7 +1433,7 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) // Invalidate the slot for all views on the same tab of the document. SfxLokHelper::forEachOtherView(this, [nSlot, nThisTab](ScTabViewShell* pOther) { ScViewData& rOtherViewData = pOther->GetViewData(); - if (rOtherViewData.CurrentTabForData() != nThisTab) + if (rOtherViewData.GetTabNumber() != nThisTab) return; SfxBindings& rOtherBind = rOtherViewData.GetBindings(); diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx index 9342e17a3b2e..04f8cc346f60 100644 --- a/sc/source/ui/view/tabvwsh4.cxx +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -76,9 +76,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -91,6 +91,8 @@ #include #include #include +#include +#include using namespace com::sun::star; using namespace sfx2::sidebar; @@ -1292,7 +1294,7 @@ bool ScTabViewShell::TabKeyInput(const KeyEvent& rKEvt) HideNoteOverlay(); // note marker // don't do extra HideCursor/ShowCursor calls if EnterHandler will switch to a different sheet - bool bOnRefSheet = ( GetViewData().GetRefTabNo() == GetViewData().CurrentTabForData() ); + bool bOnRefSheet = ( GetViewData().GetRefTabNo() == GetViewData().GetTabNumber() ); bool bHideCursor = ( ( nCode == KEY_RETURN && bInPlace ) || nCode == KEY_TAB ) && bOnRefSheet; if (bHideCursor) @@ -1676,23 +1678,7 @@ void ScTabViewShell::Construct( TriState nForceDesignMode ) if ( pDocSh->GetCreateMode() != SfxObjectCreateMode::INTERNAL && pDocSh->IsUpdateEnabled() ) // #105575#; update only in the first creation of the ViewShell { - // Check if there are any external data. - bool bLink = rDoc.GetExternalRefManager()->hasExternalData(); - if (!bLink) - { - // #i100042# sheet links can still exist independently from external formula references - SCTAB nTabCount = rDoc.GetTableCount(); - for (SCTAB i=0; iHasExternalLinks()) { if ( !pFirst ) pFirst = &GetViewFrame(); @@ -2193,7 +2179,6 @@ ScTabViewShell::ScTabViewShell( SfxViewFrame& rViewFrame, bInDispose(false), bMoveKeepEdit(false), nCurRefDlgId(0), - bIsTabChangeInProgress(false), mbInSwitch(false), m_pDragData(new ScDragData), m_pScCondFormatDlgData() @@ -2294,11 +2279,13 @@ ScTabViewShell::ScTabViewShell( SfxViewFrame& rViewFrame, if (pViewShell2 && pViewShell2 == this) { ScTabViewShell* pTabViewShell = dynamic_cast(pViewShell); - assert(pTabViewShell); - ScInputHandler* pInputHdl = pTabViewShell->GetInputHandler(); - if (pInputHdl && pInputHdl->IsFormulaMode()) + if (pTabViewShell) { - pInputHdl->SetMode(SC_INPUT_NONE); + ScInputHandler* pInputHdl = pTabViewShell->GetInputHandler(); + if (pInputHdl && pInputHdl->IsFormulaMode()) + { + pInputHdl->SetMode(SC_INPUT_NONE); + } } } @@ -2376,7 +2363,7 @@ void ScTabViewShell::FillFieldData( ScHeaderFieldData& rData ) { ScDocShell* pDocShell = GetViewData().GetDocShell(); ScDocument& rDoc = pDocShell->GetDocument(); - SCTAB nTab = GetViewData().CurrentTabForData(); + SCTAB nTab = GetViewData().GetTabNumber(); OUString aTmp; rDoc.GetName(nTab, aTmp); rData.aTabName = aTmp; diff --git a/sc/source/ui/view/tabvwsh5.cxx b/sc/source/ui/view/tabvwsh5.cxx index 4799465aa4b9..163120f5374c 100644 --- a/sc/source/ui/view/tabvwsh5.cxx +++ b/sc/source/ui/view/tabvwsh5.cxx @@ -38,6 +38,11 @@ #include #include #include +#include +#include +#include +#include +#include void ScTabViewShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) { @@ -213,6 +218,12 @@ void ScTabViewShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) default: break; } } + else if (rHint.GetId() == SfxHintId::ScRefErrorCreated) + { + assert(dynamic_cast(&rHint)); + const ScHint& rScHint = static_cast(rHint); + ShowRefErrorInfoBar(rScHint.GetStartAddress()); + } else // without parameter { const SfxHintId nSlot = rHint.GetId(); @@ -397,4 +408,48 @@ void ScTabViewShell::UpdateNumberFormatter( rInfoItem.GetNumberFormatter()->DeleteEntry( key ); } +void ScTabViewShell::ShowRefErrorInfoBar(const ScAddress& rFormulaCell) +{ + // Note: in Online, desktop-style infobars are not forwarded to + // the browser client. A future COOL implementation could hook into + // SfxHintId::ScRefErrorCreated at the kit protocol layer and surface this + // as a suggestion popup instead. The ScHint already carries the formula + // cell address, so all the data needed is available in the hint. + if (!officecfg::Office::Calc::Input::WarnOnDeleteCellReferences::get()) + return; + + // Remember the target so the "Go to First Error" button handler can + // navigate to it. Overwritten each time the infobar is (re-)shown, so + // the button always points at the most recent delete operation's first + // error. + m_aRefErrorCell = rFormulaCell; + + auto pInfoBar = GetViewFrame().AppendInfoBar( + u"ref_logic_error"_ustr, + ScResId(STR_REF_ERROR_TITLE), + ScResId(STR_REF_ERROR_MSG), + InfobarType::WARNING, + true); + + // AppendInfoBar returns nullptr if an infobar with this ID already + // exists. In that case the existing infobar still has its button, so we + // just keep it — m_aRefErrorCell update above is enough. + if (pInfoBar) + { + weld::Button& rBtn = pInfoBar->addButton(); + rBtn.set_label(ScResId(STR_REF_ERROR_GOTO)); + rBtn.connect_clicked(LINK(this, ScTabViewShell, GoToRefErrorHdl)); + } +} + +IMPL_LINK_NOARG(ScTabViewShell, GoToRefErrorHdl, weld::Button&, void) +{ + if (!m_aRefErrorCell.IsValid()) + return; + + SetTabNo(m_aRefErrorCell.Tab()); + AlignToCursor(m_aRefErrorCell.Col(), m_aRefErrorCell.Row(), SC_FOLLOW_JUMP); + SetCursor(m_aRefErrorCell.Col(), m_aRefErrorCell.Row()); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/tabvwsh8.cxx b/sc/source/ui/view/tabvwsh8.cxx index 17fb1dd8e145..880e5378fc22 100644 --- a/sc/source/ui/view/tabvwsh8.cxx +++ b/sc/source/ui/view/tabvwsh8.cxx @@ -36,13 +36,19 @@ void ScTabViewShell::SetDefaultFrameLine( const ::editeng::SvxBorderLine* pLine bool ScTabViewShell::HasSelection( bool bText ) const { - bool bHas = false; ScViewData& rData = const_cast(GetViewData()); + ScMarkData& rMark = rData.GetMarkData(); + if (rMark.IsMultiMarked() && rMark.IsMarkNegative()) + rMark.MarkToMulti(); // update the mark - is it really still marked? + + if (!rMark.IsMarked() && !rMark.IsMultiMarked()) + return false; + + bool bHas = false; if ( bText ) { // Content contained: Count2 >= 1 ScDocument& rDoc = rData.GetDocument(); - ScMarkData& rMark = rData.GetMarkData(); ScAddress aCursor( rData.GetCurX(), rData.GetCurY(), rData.CurrentTabForData() ); double fVal = 0.0; if ( rDoc.GetSelectionFunction( SUBTOTAL_FUNC_CNT2, aCursor, rMark, fVal ) ) diff --git a/sc/source/ui/view/tabvwsha.cxx b/sc/source/ui/view/tabvwsha.cxx index e43ea1fbcb85..cafd1fb62d4a 100644 --- a/sc/source/ui/view/tabvwsha.cxx +++ b/sc/source/ui/view/tabvwsha.cxx @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -128,7 +129,7 @@ bool ScTabViewShell::GetFunction( OUString& rFuncStr, FormulaError nErrCode ) SCROW nPosY = rViewData.GetCurY(); SCTAB nTab = rViewData.CurrentTabForData(); - OUString aStr = ScResId(pGlobStrId) + ": "; + OUString aStr = OUString::number(eFunc) + ":" + ScResId(pGlobStrId) + ": "; ScAddress aCursor( nPosX, nPosY, nTab ); double nVal; @@ -273,7 +274,7 @@ void ScTabViewShell::GetState( SfxItemSet& rSet ) case SID_CURRENTTAB: // Table for Basic is 1-based - rSet.Put( SfxUInt16Item( nWhich, static_cast(GetViewData().CurrentTabForData()) + 1 ) ); + rSet.Put( SfxUInt16Item( nWhich, static_cast(GetViewData().GetTabNumber()) + 1 ) ); break; case SID_CURRENTDOC: @@ -399,8 +400,6 @@ void ScTabViewShell::GetState( SfxItemSet& rSet ) case FID_NEW_SHEET_VIEW: case FID_REMOVE_SHEET_VIEW: - case FID_SWITCH_TO_NEXT_SHEET_VIEW: - case FID_SWITCH_TO_PREVIOUS_SHEET_VIEW: case FID_SELECT_SHEET_VIEW: case FID_EXIT_SHEET_VIEW: { @@ -414,11 +413,6 @@ void ScTabViewShell::GetState( SfxItemSet& rSet ) } } break; - case FID_CURRENT_SHEET_VIEW: - { - rSet.Put(SfxInt32Item(FID_CURRENT_SHEET_VIEW, GetViewData().GetSheetViewID())); - } - break; case FID_NORMALVIEWMODE: case FID_PAGEBREAKMODE: // always handle both slots - they exclude each other @@ -505,7 +499,7 @@ void ScTabViewShell::GetState( SfxItemSet& rSet ) Point aPos; bool bIsCol = (nWhich == SID_WINDOW_FIX_COL); aPos.setX(rViewData.GetLOKSheetFreezeIndex(bIsCol)); - aPos.setY(rViewData.CurrentTabForData()); + aPos.setY(rViewData.GetTabNumber()); rSet.Put(SfxPointItem(nWhich, aPos)); } break; diff --git a/sc/source/ui/view/tabvwshb.cxx b/sc/source/ui/view/tabvwshb.cxx index 6039bcdadf3a..a39b3b1b058a 100644 --- a/sc/source/ui/view/tabvwshb.cxx +++ b/sc/source/ui/view/tabvwshb.cxx @@ -828,6 +828,13 @@ void ScTabViewShell::ExecuteUndo(SfxRequest& rReq) else pUndoManager->RedoWithContext(aUndoRedoContext); } + if ( bIsUndo ) + { + // Dismiss the #REF! warning infobar if the user + // undoes. Redo re-runs the delete, which naturally + // re-broadcasts via Delete{Row,Col,Tab,Tabs}(). + GetViewFrame().RemoveInfoBar(u"ref_logic_error"); + } } catch ( const uno::Exception& ) { diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx index 73b95a26b0ba..5f166a9cd78c 100644 --- a/sc/source/ui/view/tabvwshc.cxx +++ b/sc/source/ui/view/tabvwshc.cxx @@ -116,10 +116,10 @@ void ScTabViewShell::SwitchBetweenRefDialogs(SfxModelessDialogController* pDialo } } -std::shared_ptr ScTabViewShell::CreateRefDialogController( - SfxBindings* pB, SfxChildWindow* pCW, - SfxChildWinInfo* pInfo, - weld::Window* pParent, sal_uInt16 nSlotId) +std::shared_ptr +ScTabViewShell::CreateRefDialogController(SfxBindings& rBindings, SfxChildWindow* pCW, + SfxChildWinInfo& rInfo, weld::Window* pParent, + sal_uInt16 nSlotId) { // only open dialog when called through ScModule::SetRefDialog, // so that it does not re appear for instance after a crash (#42341#). @@ -149,43 +149,50 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont switch( nSlotId ) { case SID_CORRELATION_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult + = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_SAMPLING_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_DESCRIPTIVE_STATISTICS_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, + GetViewData()); break; case SID_ANALYSIS_OF_VARIANCE_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, + GetViewData()); break; case SID_COVARIANCE_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_EXPONENTIAL_SMOOTHING_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, + GetViewData()); break; case SID_MOVING_AVERAGE_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult + = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_REGRESSION_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_FTEST_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_TTEST_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_ZTEST_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_CHI_SQUARE_TEST_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult + = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_FOURIER_ANALYSIS_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, + GetViewData()); break; case WID_SIMPLE_REF: { @@ -193,24 +200,25 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont ScViewData& rViewData = GetViewData(); rViewData.SetRefTabNo( rViewData.CurrentTabForData() ); - xResult = std::make_shared(pB, pCW, pParent); + xResult = std::make_shared(rBindings, pCW, pParent); break; } case FID_DEFINE_NAME: { if (!mbInSwitch) { - xResult = std::make_shared(pB, pCW, pParent, GetViewData(), - ScAddress( GetViewData().GetCurX(), - GetViewData().GetCurY(), - GetViewData().CurrentTabForData() ) ); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData(), + ScAddress(GetViewData().GetCurX(), + GetViewData().GetCurY(), + GetViewData().CurrentTabForData())); } else { - xResult = std::make_shared( pB, pCW, pParent, GetViewData(), - ScAddress( GetViewData().GetCurX(), - GetViewData().GetCurY(), - GetViewData().CurrentTabForData() ), &m_RangeMap); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData(), + ScAddress(GetViewData().GetCurX(), + GetViewData().GetCurY(), + GetViewData().CurrentTabForData()), + &m_RangeMap); static_cast(xResult.get())->SetEntry(maName, maScope); mbInSwitch = false; } @@ -222,10 +230,11 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont { std::map aRangeMap; rDoc.GetRangeNameMap(aRangeMap); - xResult = std::make_shared(pB, pCW, pParent, GetViewData(), std::move(aRangeMap), - ScAddress(GetViewData().GetCurX(), - GetViewData().GetCurY(), - GetViewData().CurrentTabForData()), true); + xResult = std::make_shared( + &rBindings, pCW, pParent, GetViewData(), std::move(aRangeMap), + ScAddress(GetViewData().GetCurX(), GetViewData().GetCurY(), + GetViewData().CurrentTabForData()), + true); } else { @@ -234,31 +243,35 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont { aRangeMap.insert(std::pair(itr.first, &itr.second)); } - xResult = std::make_shared(pB, pCW, pParent, GetViewData(), std::move(aRangeMap), - ScAddress(GetViewData().GetCurX(), - GetViewData().GetCurY(), - GetViewData().CurrentTabForData()), false); + xResult = std::make_shared( + &rBindings, pCW, pParent, GetViewData(), std::move(aRangeMap), + ScAddress(GetViewData().GetCurX(), GetViewData().GetCurY(), + GetViewData().CurrentTabForData()), + false); } break; } case SID_RANDOM_NUMBER_GENERATOR_DIALOG: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, + GetViewData()); break; case SID_SPARKLINE_DIALOG: { - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult + = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; } case SID_SPARKLINE_DATA_RANGE_DIALOG: { - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, + GetViewData()); break; } case SID_DEFINE_DBNAME: { // when called for an existing range, then mark GetDBData( true, SC_DB_OLD ); - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; } case SID_INSERT_CALCTABLE: @@ -268,14 +281,15 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) MarkDataArea( false ); - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; } case SID_OPENDLG_EDIT_PRINTAREA: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_DEFINE_COLROWNAMERANGES: - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult + = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; case SID_OPENDLG_SOLVE: { @@ -283,7 +297,8 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont ScAddress aCurPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.CurrentTabForData()); - xResult = std::make_shared(pB, pCW, pParent, &rViewData.GetDocument(), aCurPos); + xResult = std::make_shared(&rBindings, pCW, pParent, + &rViewData.GetDocument(), aCurPos); break; } case SID_OPENDLG_TABOP: @@ -293,13 +308,14 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont rViewData.GetCurY(), rViewData.CurrentTabForData()); - xResult = std::make_shared(pB, pCW, pParent, &rViewData.GetDocument(), aCurPos); + xResult = std::make_shared(&rBindings, pCW, pParent, + &rViewData.GetDocument(), aCurPos); break; } case SID_OPENDLG_CONSOLIDATE: { - SfxItemSetFixed aArgSet( GetPool() ); + SfxItemSet aArgSet(SfxItemSet::makeFixedSfxItemSet ( GetPool() )); const ScConsolidateParam* pDlgData = rDoc.GetConsolidateDlgData(); @@ -329,12 +345,13 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont { aArgSet.Put( ScConsolidateItem( SCITEM_CONSOLIDATEDATA, pDlgData ) ); } - xResult = std::make_shared(pB, pCW, pParent, aArgSet); + xResult = std::make_shared(&rBindings, pCW, pParent, aArgSet); break; } case SID_EASY_CONDITIONAL_FORMAT_DIALOG: { - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, + GetViewData()); break; } case SID_FILTER: @@ -342,10 +359,9 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont if (ScDBData* pDBData = GetDBData(false, SC_DB_MAKE, ScGetDBSelection::RowDown)) { ScQueryParam aQueryParam; - SfxItemSetFixed aArgSet( GetPool() ); + SfxItemSet aArgSet(SfxItemSet::makeFixedSfxItemSet( GetPool() )); pDBData->ExtendDataArea(rDoc); - pDBData->ExtendBackColorArea(rDoc); pDBData->GetQueryParam( aQueryParam ); ScRange aArea; @@ -357,7 +373,8 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont // mark current sheet (due to RefInput in dialog) GetViewData().SetRefTabNo( GetViewData().CurrentTabForData() ); - xResult = std::make_shared(pB, pCW, pParent, GetViewData(), aArgSet); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData(), + aArgSet); } break; } @@ -366,8 +383,8 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont if (ScDBData* pDBData = GetDBData(false, SC_DB_MAKE, ScGetDBSelection::RowDown)) { ScQueryParam aQueryParam; - SfxItemSetFixed aArgSet( GetPool() ); + SfxItemSet aArgSet(SfxItemSet::makeFixedSfxItemSet ( GetPool() )); pDBData->ExtendDataArea(rDoc); pDBData->GetQueryParam( aQueryParam ); @@ -386,7 +403,8 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont // mark current sheet (due to RefInput in dialog) GetViewData().SetRefTabNo( GetViewData().CurrentTabForData() ); - xResult = std::make_shared(pB, pCW, pParent, GetViewData(), aArgSet); + xResult = std::make_shared(rBindings, pCW, pParent, + GetViewData(), aArgSet); } break; } @@ -394,18 +412,19 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont { ScViewData& rViewData = GetViewData(); ScAddress aCurPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.CurrentTabForData()); - xResult = std::make_shared(pB, pCW, pParent, rViewData.GetDocShell(), aCurPos); + xResult = std::make_shared(&rBindings, pCW, pParent, + rViewData.GetDocShell(), aCurPos); break; } case FID_CHG_SHOW: { // dialog checks, what is in the cell - xResult = std::make_shared(pB, pCW, pParent, GetViewData()); + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData()); break; } case SID_MANAGE_XML_SOURCE: { - xResult = std::make_shared(pB, pCW, pParent, rDoc); + xResult = std::make_shared(&rBindings, pCW, pParent, rDoc); break; } case SID_OPENDLG_PIVOTTABLE: @@ -418,18 +437,17 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont ScViewData& rViewData = GetViewData(); rViewData.SetRefTabNo( rViewData.CurrentTabForData() ); ScDPObject* pObj = rDoc.GetDPAtCursor(rViewData.GetCurX(), rViewData.GetCurY(), rViewData.CurrentTabForData()); - xResult = std::make_shared(pB, pCW, pParent, rViewData, pDialogDPObject.get(), pObj == nullptr); + xResult = std::make_shared( + &rBindings, pCW, pParent, rViewData, pDialogDPObject.get(), pObj == nullptr); } break; } case SID_OPENDLG_FUNCTION: { - if (!isLOKMobilePhone()) - { - // dialog checks, what is in the cell - xResult = std::make_shared(pB, pCW, pParent, GetViewData(), ScGlobal::GetStarCalcFunctionMgr()); - } + // dialog checks, what is in the cell + xResult = std::make_shared(&rBindings, pCW, pParent, GetViewData(), + ScGlobal::GetStarCalcFunctionMgr()); break; } case WID_CONDFRMT_REF: @@ -442,7 +460,8 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont ScViewData& rViewData = GetViewData(); rViewData.SetRefTabNo( rViewData.CurrentTabForData() ); - xResult = std::make_shared(pB, pCW, pParent, rViewData, rDlgData); + xResult = std::make_shared(&rBindings, pCW, pParent, rViewData, + rDlgData); // Remove the DialogData stored by Conditional Format Manager Dialog. setScCondFormatDlgData(nullptr); @@ -454,8 +473,8 @@ std::shared_ptr ScTabViewShell::CreateRefDialogCont if (xResult) { - pInfo->nFlags = SfxChildWindowFlags::NEVERHIDE; - xResult->Initialize(pInfo); + rInfo.nFlags = SfxChildWindowFlags::NEVERHIDE; + xResult->Initialize(rInfo); } return xResult; } @@ -481,14 +500,6 @@ void ScTabViewShell::afterCallbackRegistered() pInputWindow->NotifyLOKClient(); } } - - SfxObjectShell* pDocShell = GetObjectShell(); - if (pDocShell && !IsTabChangeInProgress()) - { - std::shared_ptr pThemeColors = pDocShell->GetThemeColors(); - std::set aDocumentColors = pDocShell->GetDocColors(); - svx::theme::notifyLOK(pThemeColors, aDocumentColors); - } } void ScTabViewShell::NotifyCursor(SfxViewShell* pOtherShell) const diff --git a/sc/source/ui/view/tabvwshe.cxx b/sc/source/ui/view/tabvwshe.cxx index 36b6141ee6bc..a33b1591ea7a 100644 --- a/sc/source/ui/view/tabvwshe.cxx +++ b/sc/source/ui/view/tabvwshe.cxx @@ -232,6 +232,14 @@ void ScTabViewShell::ExecSearch( SfxRequest& rReq ) sal_uInt16 nSlot = rReq.GetSlot(); const SfxPoolItem* pItem; + // auto-accept any in-process input - which could otherwise end up on a different 'found' sheet + if (nSlot != SID_SEARCH_ITEM && ScGlobal::GetSearchItem().IsAllTables()) + { + ScModule* pScMod = ScModule::get(); + if (!pScMod->IsFormulaMode()) + pScMod->InputEnterHandler(); + } + switch ( nSlot ) { case FID_SEARCH_NOW: diff --git a/sc/source/ui/view/tabvwshf.cxx b/sc/source/ui/view/tabvwshf.cxx index 761f28e7e09c..d5808897527c 100644 --- a/sc/source/ui/view/tabvwshf.cxx +++ b/sc/source/ui/view/tabvwshf.cxx @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -64,8 +63,9 @@ void ScTabViewShell::ExecuteTable( SfxRequest& rReq ) ScViewData& rViewData = GetViewData(); ScDocument& rDoc = rViewData.GetDocument(); - SCTAB nCurrentTab = rViewData.CurrentTabForData(); - SCTAB nTabCount = rDoc.GetTableCount(); + SCTAB nCurrentTab = rViewData.GetTabNumber(); + + SCTAB nTabCount = rDoc.GetTableCount(); sal_uInt16 nSlot = rReq.GetSlot(); const SfxItemSet* pReqArgs = rReq.GetArgs(); @@ -120,7 +120,7 @@ void ScTabViewShell::ExecuteTable( SfxRequest& rReq ) if (it == rMark.GetSelectedTabs().end()) { // No it doesn't, so we won't shift the selected tab. Let's remember its position. - nActiveTab = GetViewData().CurrentTabForData(); + nActiveTab = GetViewData().GetTabNumber(); } rMark.SelectOneTable(nTabNumber); } @@ -212,7 +212,7 @@ void ScTabViewShell::ExecuteTable( SfxRequest& rReq ) case FID_TAB_DUPLICATE: { // Get info about current document and selected tab - SCTAB nTab = rViewData.CurrentTabForData(); + SCTAB nTab = rViewData.GetTabNumber(); OUString aDocName = GetViewData().GetDocShell()->GetTitle(SFX_TITLE_FULLNAME); sal_uInt16 nDoc = 0; @@ -393,7 +393,7 @@ void ScTabViewShell::ExecuteTable( SfxRequest& rReq ) { ScDocShell* pDocSh = rViewData.GetDocShell(); ScDocFunc &rFunc = pDocSh->GetDocFunc(); - bool bSet = !rDoc.IsLayoutRTL( nCurrentTab ); + bool bSet = !rDoc.IsLayoutRTL(nCurrentTab); const ScMarkData& rMark = rViewData.GetMarkData(); if ( rMark.GetSelectCount() != 0 ) @@ -410,7 +410,7 @@ void ScTabViewShell::ExecuteTable( SfxRequest& rReq ) pUndoManager->LeaveListAction(); } else - rFunc.SetLayoutRTL( nCurrentTab, bSet ); + rFunc.SetLayoutRTL(nCurrentTab, bSet); } break; @@ -469,7 +469,7 @@ void ScTabViewShell::GetStateTable( SfxItemSet& rSet ) ScDocument& rDoc = rViewData.GetDocument(); ScDocShell* pDocShell = rViewData.GetDocShell(); ScMarkData& rMark = GetViewData().GetMarkData(); - SCTAB nTab = rViewData.CurrentTabForData(); + SCTAB nTab = rViewData.GetTabNumber(); SCTAB nTabCount = rDoc.GetTableCount(); SCTAB nTabSelCount = rMark.GetSelectCount(); @@ -609,7 +609,7 @@ void ScTabViewShell::ExecuteMoveTable( SfxRequest& rReq ) bool bDoIt = false; sal_uInt16 nDoc = 0; - SCTAB nTab = rViewData.CurrentTabForData(); + SCTAB nTab = rViewData.GetTabNumber(); SCTAB nContextMenuTab = -1; bool bFromContextMenu = false; bool bFromMoveOrCopySheetDialog = false; // FN_PARAM_6 @@ -782,7 +782,7 @@ void ScTabViewShell::ExecuteMoveTable( SfxRequest& rReq ) else { OUString aDefaultName; - rDoc.GetName( rViewData.CurrentTabForData(), aDefaultName ); + rDoc.GetName( rViewData.GetTabNumber(), aDefaultName ); ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); @@ -834,7 +834,7 @@ void ScTabViewShell::ExecuteInsertTable(SfxRequest& rReq) ScDocument& rDoc = rViewData.GetDocument(); const SfxItemSet* pReqArgs = rReq.GetArgs(); sal_uInt16 nSlot = rReq.GetSlot(); - SCTAB nCurrentTab = rViewData.CurrentTabForData(); + SCTAB nCurrentTab = rViewData.GetTabNumber(); SCTAB nTabCount = rDoc.GetTableCount(); ScMarkData& rMark = rViewData.GetMarkData(); SCTAB nTabSelCount = rMark.GetSelectCount(); @@ -894,7 +894,7 @@ void ScTabViewShell::DoInsertTableFromDialog(SfxRequest& rReq, const VclPtrGetInputString(); @@ -1198,10 +1198,10 @@ void ScTabViewShell::ExecuteSetTableBackgroundCol(SfxRequest& rReq) const SfxItemSet* pReqArgs = rReq.GetArgs(); if ( nSlot == FID_TAB_MENU_SET_TAB_BG_COLOR ) nSlot = FID_TAB_SET_TAB_BG_COLOR; - SCTAB nTabNr = rViewData.CurrentTabForData(); + SCTAB nTabNr = rViewData.GetTabNumber(); ScMarkData& rMark = rViewData.GetMarkData(); SCTAB nTabSelCount = rMark.GetSelectCount(); - SCTAB nCurrentTab = rViewData.CurrentTabForData(); + SCTAB nCurrentTab = rViewData.GetTabNumber(); if ( !rDoc.IsDocEditable() ) return; @@ -1249,7 +1249,6 @@ void ScTabViewShell::ExecuteSetTableBackgroundCol(SfxRequest& rReq) VclPtr pDlg(pFact->CreateScTabBgColorDlg( GetFrameWeld(), ScResId(SCSTR_SET_TAB_BG_COLOR), - ScResId(SCSTR_NO_TAB_BG_COLOR), aTabBgColor)); auto xRequest = std::make_shared(rReq); @@ -1283,7 +1282,7 @@ bool ScTabViewShell::DoTableBackgroundDialog(sal_Int32 nResult, const VclPtrGetSelectedColor(); diff --git a/sc/source/ui/view/tabvwshh.cxx b/sc/source/ui/view/tabvwshh.cxx index 12503cb908bc..f7532e6f0016 100644 --- a/sc/source/ui/view/tabvwshh.cxx +++ b/sc/source/ui/view/tabvwshh.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -33,11 +34,12 @@ #include #include +#include #include +#include #include #include #include -#include #include @@ -263,8 +265,13 @@ bool ScTabViewShell::ExecuteRetypePassDlg(ScPasswordHash eDesiredHash) void ScTabViewShell::ExecuteOnlyActiveSheetSavedDlg() { - ScOnlyActiveSheetSavedDlg aDlg(GetFrameWeld()); - aDlg.run(); + QueryDialog aQueryDialog( + GetFrameWeld(), ScResId(STR_WARN_ONLYACTIVESHEET_TITLE), + ScResId(STR_WARN_ONLYACTIVESHEET_TEXT), ScResId(STR_WARN_ONLYACTIVESHEET_QUEST), true); + aQueryDialog.SetNoLabel(u""_ustr); //empty to hide the button + aQueryDialog.SetYesLabel(ScResId(STR_WARN_ONLYACTIVESHEET_BUTTON)); + aQueryDialog.SetTypeWarn(); + aQueryDialog.run(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index 8f745ef38ba3..e1e78cd88a8a 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -250,13 +250,6 @@ ScPositionHelper::getNearestByPosition(tools::Long nPos) const } } -tools::Long ScPositionHelper::getPosition(index_type nIndex) const -{ - auto it = mData.find(std::make_pair(nIndex, 0)); - if (it == mData.end()) return -1; - return it->second; -} - tools::Long ScPositionHelper::computePosition(index_type nIndex, const std::function& getSizePx) { assert(MAX_INDEX > 0); @@ -518,6 +511,7 @@ ScViewDataTable::ScViewDataTable(const ScDocument& rDoc) : aHeightHelper(rDoc, false), nMaxTiledCol( 20 ), nMaxTiledRow( 50 ), + nLastSheetViewTab(sc::DefaultSheetViewID), bShowGrid( true ), mbOldCursorValid( false ) { @@ -2519,6 +2513,18 @@ void ScViewData::SetTabNo( SCTAB nNewTab ) return; } + // Remember the current sheet view tab on the default sheet's per-tab data + if (ValidTab(mnTabNumber)) + { + SCTAB nDefaultOfOld = mrDoc.GetDefaultViewTableNumber(mnTabNumber); + if (nDefaultOfOld != mnTabNumber + && nDefaultOfOld < SCTAB(maTabData.size()) + && maTabData[nDefaultOfOld]) + { + maTabData[nDefaultOfOld]->nLastSheetViewTab = mnTabNumber; + } + } + mnTabNumber = nNewTab; CreateTabData(mnTabNumber); pThisTab = maTabData[mnTabNumber].get(); @@ -3501,11 +3507,14 @@ void ScViewData::WriteUserData(OUString& rData) else rData += "0"; - rData += ";" + OUString::number(CurrentTabForData()) + ";" + TAG_TABBARWIDTH + OUString::number( pView->GetTabBarWidth() ); + rData += ";" + OUString::number(GetTabNumber()) + ";" + TAG_TABBARWIDTH + OUString::number( pView->GetTabBarWidth() ); SCTAB nTabCount = mrDoc.GetTableCount(); for (SCTAB i=0; i(maTabData.size()) && maTabData[i]) { @@ -3646,7 +3655,7 @@ void ScViewData::WriteExtOptions( ScExtDocOptions& rDocOpt ) const ScExtDocSettings& rDocSett = rDocOpt.GetDocSettings(); // displayed sheet - rDocSett.mnDisplTab = CurrentTabForData(); + rDocSett.mnDisplTab = GetTabNumber(); // width of the tabbar, relative to frame window width rDocSett.mfTabBarWidth = pView->GetPendingRelTabBarWidth(); @@ -3945,9 +3954,9 @@ void ScViewData::WriteUserDataSequence(uno::Sequence & rSe pSettings[SC_TABLE_VIEWSETTINGS].Value <<= xNameContainer; OUString sName; - GetDocument().GetName(CurrentTabForData(), sName); + GetDocument().GetName(GetTabNumber(), sName); // tdf#150317 - sync visible tab (later used for, e.g., thumbnail generation) - GetDocument().SetVisibleTab(CurrentTabForData()); + GetDocument().SetVisibleTab(GetTabNumber()); pSettings[SC_ACTIVE_TABLE].Name = SC_ACTIVETABLE; pSettings[SC_ACTIVE_TABLE].Value <<= sName; pSettings[SC_HORIZONTAL_SCROLL_BAR_WIDTH].Name = SC_HORIZONTALSCROLLBARWIDTH; @@ -4065,7 +4074,10 @@ void ScViewData::ReadUserDataSequence(const uno::Sequence { SCTAB nTab(0); if (GetDocument().GetTable(sTabName, nTab)) - mnTabNumber = nTab; + { + // When opening a new window we shouldn't see a sheet view + mnTabNumber = GetDocument().GetDefaultViewTableNumber(nTab); + } } } else if (sName == SC_HORIZONTALSCROLLBARWIDTH) @@ -4597,41 +4609,68 @@ void ScViewData::OverrideWithLOKFreeze(ScSplitMode& eExHSplitMode, ScSplitMode& SCTAB ScViewData::CurrentTabForData() const { - if (!pThisTab) - return GetTabNumber(); - auto nSheetViewID = GetSheetViewID(); - if (nSheetViewID != sc::DefaultSheetViewID) - { - SCTAB nTab = mrDoc.GetSheetViewNumber(GetTabNumber(), nSheetViewID); - if (ValidTab(nTab)) - return nTab; - SAL_WARN("sc.ui","ScViewData::CurrentTabForData - invalid tab: " << nTab); - } return GetTabNumber(); } +sc::SheetViewID ScViewData::GetSheetViewID() const +{ + return mrDoc.GetTableSheetViewID(GetTabNumber()); +} + void ScViewData::SetSheetViewID(sc::SheetViewID nID) { - pThisTab->mnSheetViewID = nID; - - CalcPPT(); - RecalcPixPos(); + if (nID != sc::DefaultSheetViewID) + { + // Get the default tab (in case we're currently on a sheet view tab) + SCTAB nDefaultTab = GetDefaultViewTab(); + SCTAB nSheetViewTab = mrDoc.GetSheetViewNumber(nDefaultTab, nID); + if (ValidTab(nSheetViewTab)) + SetTabNo(nSheetViewTab); + } + else + { + // Returning to default view — switch back to the default tab + SCTAB nDefaultTab = GetDefaultViewTab(); + if (nDefaultTab != GetTabNumber()) + SetTabNo(nDefaultTab); + } } sc::SheetViewID ScViewData::GetSheetViewIDForSheet(SCTAB nTab) const { - if (!IsValidTabNumber(nTab)) - return sc::InvalidSheetViewID; - - if (!maTabData[nTab]) - return sc::InvalidSheetViewID; - - return maTabData[nTab]->mnSheetViewID; + return mrDoc.GetTableSheetViewID(nTab); } std::shared_ptr ScViewData::GetCurrentSheetViewManager() const { - return GetDocument().GetSheetViewManager(GetTabNumber()); + return GetDocument().GetSheetViewManager(GetDefaultViewTab()); +} + +SCTAB ScViewData::GetDefaultViewTab() const +{ + return mrDoc.GetDefaultViewTableNumber(GetTabNumber()); +} + +SCTAB ScViewData::GetLastSheetViewTab(SCTAB nDefaultTab) const +{ + if (nDefaultTab >= 0 + && nDefaultTab < static_cast(maTabData.size()) + && maTabData[nDefaultTab] + && maTabData[nDefaultTab]->nLastSheetViewTab != sc::DefaultSheetViewID) + { + return maTabData[nDefaultTab]->nLastSheetViewTab; + } + return nDefaultTab; +} + +void ScViewData::ClearLastSheetViewTab(SCTAB nDefaultTab) +{ + if (nDefaultTab >= 0 + && nDefaultTab < static_cast(maTabData.size()) + && maTabData[nDefaultTab]) + { + maTabData[nDefaultTab]->nLastSheetViewTab = sc::DefaultSheetViewID; + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx index 9abc52bcb8f3..cc8392dd4797 100644 --- a/sc/source/ui/view/viewfun2.cxx +++ b/sc/source/ui/view/viewfun2.cxx @@ -2,7 +2,7 @@ /* * This file is part of the LibreOffice project. * - * This Source eCode Form is subject to the terms of the Mozilla Public + * 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/. * @@ -19,6 +19,8 @@ #include +#include + #include #include #include @@ -40,7 +42,7 @@ #include #include #include -#include +#include #include #include @@ -2021,11 +2023,7 @@ bool ScViewFunc::SearchAndReplace( const SvxSearchItem* pSearchItem, DoneBlockMode(true); // don't delete mark InitOwnBlockMode( ScRange( nCol, nRow, nStartTab, nCol, nRow, nEndTab)); - // If search starts at the beginning don't ask again whether it shall start at the beginning bool bFirst = true; - if ( nCol == 0 && nRow == 0 && nTab == nStartTab && !pSearchItem->GetBackward() ) - bFirst = false; - bool bFound = false; while (true) { @@ -2553,11 +2551,11 @@ bool ScViewFunc::DeleteTables(const std::vector& rTabs, bool bRecord) { if (isFirstTab) { - pUndoDoc->InitUndo( rDoc, nTab,nTab, true,true ); // incl. column/fow flags + pUndoDoc->InitUndo( rDoc, nTab,nTab, true,true ); // incl. column/row flags isFirstTab = false; } else - pUndoDoc->AddUndoTab( nTab,nTab, true,true ); // incl. column/fow flags + pUndoDoc->AddUndoTab( nTab,nTab, true,true ); // incl. column/row flags rDoc.CopyToDocument(0,0,nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab, InsertDeleteFlags::ALL,false, *pUndoDoc ); rDoc.GetName( nTab, aOldName ); @@ -2596,6 +2594,18 @@ bool ScViewFunc::DeleteTables(const std::vector& rTabs, bool bRecord) pUndoDoc->AddUndoTab( 0, nCount-1 ); // all Tabs for references + // Deleting these tabs rewrites any formula on another sheet that + // refers to one of them into a #REF! error. Snapshot that sheet's + // formulas too, so ScMoveUndo::UndoRef() has the original formula to + // put back on undo instead of leaving the error in place. + for (SCTAB nOtherTab = 0; nOtherTab < nCount; ++nOtherTab) + { + if (std::find(rTabs.begin(), rTabs.end(), nOtherTab) != rTabs.end()) + continue; + rDoc.CopyToDocument(0,0,nOtherTab, rDoc.MaxCol(),rDoc.MaxRow(),nOtherTab, + InsertDeleteFlags::FORMULA, false, *pUndoDoc ); + } + rDoc.BeginDrawUndo(); // DeleteTab creates a SdrUndoDelPage pUndoData.reset(new ScRefUndoData( rDoc )); @@ -2617,9 +2627,9 @@ bool ScViewFunc::DeleteTables(const std::vector& rTabs, bool bRecord) if (auto pManager = rDoc.GetSheetViewManager(nTab)) { - for (auto const& pSheetView : pManager->getSheetViews()) + for (auto const& rSheetView : pManager->iterateValidSheetViews()) { - aSheetViewHolderTablesToDelete.push_back(pSheetView->getTablePointer()); + aSheetViewHolderTablesToDelete.push_back(rSheetView.getTablePointer()); } } @@ -3415,8 +3425,8 @@ void ScViewFunc::SetSelectionFrameLines( const SvxBorderLine* pLine, // none of the lines don't care? if( (eItemState != SfxItemState::INVALID) && (eTLBRState != SfxItemState::INVALID) && (eBLTRState != SfxItemState::INVALID) ) { - SfxItemSetFixed aOldSet( *rDoc.GetPool() ); - SfxItemSetFixed aNewSet( *rDoc.GetPool() ); + SfxItemSet aOldSet(SfxItemSet::makeFixedSfxItemSet( *rDoc.GetPool() )); + SfxItemSet aNewSet(SfxItemSet::makeFixedSfxItemSet( *rDoc.GetPool() )); SvxBorderLine aLine; diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx index 319bd53c1f63..c33e57befaa5 100644 --- a/sc/source/ui/view/viewfun3.cxx +++ b/sc/source/ui/view/viewfun3.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -112,10 +113,9 @@ MatrixOverlapInfo lcl_DetectMatrixOverlap(ScDocument& rDoc, const ScRange& rRang }; auto isInsideKnownMatrix = [&aAllMatrices](const ScAddress& rPos) { - for (const auto& rMat : aAllMatrices) - if (rMat.Contains(rPos)) - return true; - return false; + return std::any_of(aAllMatrices.begin(), aAllMatrices.end(), [&rPos](const auto& rMat) { + return rMat.Contains(rPos); + }); }; // Single pass: scan the original selection for matrix cells. @@ -257,6 +257,8 @@ void ScViewFunc::CutToClip() CellContentChanged(); + pDocSh->ResolveSpilledOutputs(); + OUString aStartAddress = aRange.aStart.GetColRowString(); OUString aEndAddress = aRange.aEnd.GetColRowString(); @@ -938,7 +940,7 @@ bool ScViewFunc::PasteFromSystem( SotClipboardFormatId nFormatId, bool bApi, boo pTabViewShell->OnLOKSetWidthOrHeight(rViewData.GetCurY(), false); ScTabViewShell::notifyAllViewsSheetGeomInvalidation(pTabViewShell, true /* bColumns */, true /* bRows */, - true /* bSizes */, false /* bHidden */, false /* bFiltered */, false /* bGroups */, rViewData.CurrentTabForData()); + true /* bSizes */, false /* bHidden */, false /* bFiltered */, false /* bGroups */, rViewData.GetTabNumber()); } } return bRet; @@ -1442,12 +1444,25 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, rDoc.CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1, nUndoFlags, false, *pUndoDoc ); + // A clip document carrying named tables can add a database range to + // this document during paste. Force the DB-range snapshot so that + // addition is undoable even when this document had no ranges yet - + // the general path skips an empty collection. The cut path always + // builds ScRefUndoData, and the flag extends its snapshot to the + // empty pre-state. + const bool bForceDBSnapshot = pClipDoc->GetDBCollection() + && !pClipDoc->GetDBCollection()->getNamedDBs().empty(); + if ( bCutMode ) { pRefUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); pRefUndoDoc->InitUndo( rDoc, 0, nTabCount-1 ); - pUndoData.reset(new ScRefUndoData( rDoc )); + pUndoData.reset(new ScRefUndoData( rDoc, bForceDBSnapshot )); + } + else if (bForceDBSnapshot) + { + pUndoData.reset(new ScRefUndoData( rDoc, true )); } } @@ -1497,9 +1512,13 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, if (!bAsLink) { // copy normally (original range) + // keep the destination cells' own directly applied protection - an + // interactive paste changes their content, not whether the user has + // directly locked them (tdf#123974) rDoc.CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc.get(), pClipDoc, true, false, bIncludeFiltered, - bSkipEmptyCells, (bMarkIsFiltered ? &aRangeList : nullptr) ); + bSkipEmptyCells, (bMarkIsFiltered ? &aRangeList : nullptr), + /*bPreserveDestProtection*/true ); // adapt refs manually in case of transpose if ( bTranspose && bCutMode && (nFlags & InsertDeleteFlags::CONTENTS) ) @@ -2027,6 +2046,8 @@ void ScViewFunc::PostPasteFromClip(const ScRangeList& rPasteRanges, const ScMark HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, u"paste"_ustr); else if (pModelObj) HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, u"data-area-invalidate"_ustr); + + pDocSh->ResolveSpilledOutputs(); } // D R A G A N D D R O P @@ -2233,42 +2254,38 @@ void ScViewFunc::DataFormPutData( SCROW nCurrentRow , void ScViewFunc::SheetViewChanged() { - ScViewData& rViewData = GetViewData(); - ScDocShell* pDocSh = rViewData.GetDocShell(); - ScDocument& rDocument = rViewData.GetDocument(); - pDocSh->PostPaint(0, 0, 0, rDocument.MaxCol(), rDocument.MaxRow(), MAXTAB, PaintPartFlags::All); - - if (ScTabViewShell* pViewShell = GetViewData().GetViewShell()) + // Invalidate the sheet view selector for all views connected to this document + ScTabViewShell* pThisViewShell = GetViewData().GetViewShell(); + if (pThisViewShell) { - ScModelObj* pModel = comphelper::getFromUnoTunnel(pViewShell->GetCurrentDocument()); - SfxLokHelper::notifyViewRenderState(pViewShell, pModel); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_HEADER, "all"_ostr); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY, "all"_ostr); + ViewShellDocId nDocID = pThisViewShell->GetDocId(); + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while (pViewShell) + { + ScTabViewShell* pTabViewShell = dynamic_cast(pViewShell); + if (pTabViewShell && pTabViewShell->GetDocId() == nDocID) + { + SfxBindings& rBindings = pTabViewShell->GetViewFrame().GetBindings(); + rBindings.Invalidate(FID_SELECT_SHEET_VIEW); + } + pViewShell = SfxViewShell::GetNext(*pViewShell); + } } - SfxBindings& rBindings = rViewData.GetBindings(); - rBindings.Invalidate(FID_CURRENT_SHEET_VIEW); } void ScViewFunc::MakeNewSheetView() { - SCTAB nTab = GetViewData().GetTabNumber(); - ScDocument& rDocument = GetViewData().GetDocument(); - - auto[nSheetViewID, nSheetViewTab] = rDocument.CreateNewSheetView(nTab); + // Convert to default view, if we are in sheet view. + SCTAB nTab = GetViewData().GetDefaultViewTab(); + auto [nSheetViewID, nSheetViewTab] = GetViewData().GetDocShell()->GetDocFunc().InsertSheetView(nTab, true); if (nSheetViewID == sc::InvalidSheetViewID) { SAL_WARN("sc", "Sheet view couldn't be created"); return; } - GetViewData().SetSheetViewID(nSheetViewID); - - GetViewData().GetDocShell()->Broadcast(ScTablesHint(SC_TAB_INSERTED, nSheetViewTab)); - SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScTablesChanged)); - - // Need to make sure we return to the main sheet, to make sure we are not at a different location after inserting - SetTabNo(nTab); + SetTabNo(nSheetViewTab); SheetViewChanged(); } @@ -2280,37 +2297,26 @@ void ScViewFunc::RemoveCurrentSheetView() return; ScDocument& rDocument = GetViewData().GetDocument(); - SCTAB nTab = GetViewData().GetTabNumber(); - if (rDocument.IsSheetViewHolder(nTab)) - return; + SCTAB nDefaultTab = GetViewData().GetDefaultViewTab(); - auto pSheetManager = rDocument.GetSheetViewManager(nTab); + auto pSheetManager = rDocument.GetSheetViewManager(nDefaultTab); if (!pSheetManager) return; - GetViewData().SetSheetViewID(sc::DefaultSheetViewID); + SCTAB nSheetViewTab = rDocument.GetSheetViewNumber(nDefaultTab, nSheetViewID); - SCTAB nSheetViewTab = rDocument.GetSheetViewNumber(nTab, nSheetViewID); - pSheetManager->remove(nSheetViewID); + // Switch back to the default tab before deleting + SetTabNo(nDefaultTab); + // Last sheet view tab is the deleted one, so reset + GetViewData().ClearLastSheetViewTab(nDefaultTab); + + // DeleteTable also removes the sheet view from the manager GetViewData().GetDocFunc().DeleteTable(nSheetViewTab, true); SheetViewChanged(); } -void ScViewFunc::SwitchSheetView(sc::SwitchSheetViewDirection eDirection) -{ - ScDocument& rDocument = GetViewData().GetDocument(); - SCTAB nTab = GetViewData().GetTabNumber(); - auto pSheetManager = rDocument.GetSheetViewManager(nTab); - sc::SheetViewID nSheetViewID = GetViewData().GetSheetViewID(); - - sc::SheetViewID nSwitchSheetViewID = eDirection == sc::SwitchSheetViewDirection::Next - ? pSheetManager->getNextSheetView(nSheetViewID) - : pSheetManager->getPreviousSheetView(nSheetViewID); - SelectSheetView(nSwitchSheetViewID); -} - void ScViewFunc::ExitSheetView() { SelectSheetView(sc::DefaultSheetViewID); @@ -2318,17 +2324,22 @@ void ScViewFunc::ExitSheetView() void ScViewFunc::SelectSheetView(sc::SheetViewID nSelectSheetViewID) { - SCTAB nTab = GetViewData().GetTabNumber(); - - if (GetViewData().GetDocument().IsSheetViewHolder(nTab)) + if (nSelectSheetViewID == GetViewData().GetSheetViewID()) return; - sc::SheetViewID nSheetViewID = GetViewData().GetSheetViewID(); - if (nSheetViewID == nSelectSheetViewID) - return; - - GetViewData().SetSheetViewID(nSelectSheetViewID); + ScDocument& rDocument = GetViewData().GetDocument(); + SCTAB nDefaultTab = GetViewData().GetDefaultViewTab(); + if (nSelectSheetViewID == sc::DefaultSheetViewID) + { + SetTabNo(nDefaultTab); + } + else + { + SCTAB nSheetViewTab = rDocument.GetSheetViewNumber(nDefaultTab, nSelectSheetViewID); + if (ValidTab(nSheetViewTab)) + SetTabNo(nSheetViewTab); + } SheetViewChanged(); } diff --git a/sc/source/ui/view/viewfun4.cxx b/sc/source/ui/view/viewfun4.cxx index b7008d6b756e..9cce9a688bea 100644 --- a/sc/source/ui/view/viewfun4.cxx +++ b/sc/source/ui/view/viewfun4.cxx @@ -44,7 +44,6 @@ #include #include #include -#include #include #include @@ -129,8 +128,8 @@ void ScViewFunc::PasteRTF( SCCOL nStartCol, SCROW nStartRow, rDoc.EnableUndo( false ); for( sal_Int32 n = 0; n < nParCnt; n++ ) { - std::unique_ptr pObject(pEngine->CreateTextObject(n)); - EnterData(nStartCol, nRow, nTab, *pObject, true); + EditTextObject aObject(pEngine->CreateTextObject(n)); + EnterData(nStartCol, nRow, nTab, aObject, true); if( ++nRow > rDoc.MaxRow() ) break; } @@ -407,10 +406,9 @@ void ScViewFunc::DoThesaurus() if (aOldText.getType() == CELLTYPE_EDIT) { // The cell will own the text object instance. - std::unique_ptr pText = pThesaurusEngine->CreateTextObject(); - auto tmp = pText.get(); - if (rDoc.SetEditText(ScAddress(nCol,nRow,nTab), std::move(pText))) - aNewText.set(*tmp); + EditTextObject* pText = new EditTextObject(pThesaurusEngine->CreateTextObject()); + if (rDoc.SetEditText(ScAddress(nCol,nRow,nTab), std::unique_ptr(pText))) + aNewText.set(*pText); } else { @@ -745,8 +743,8 @@ void ScViewFunc::InsertBookmark( const OUString& rDescription, const OUString& r aField.SetTargetFrame(*pTarget); aEngine.QuickInsertField( SvxFieldItem( aField, EE_FEATURE_FIELD ), aInsSel ); - std::unique_ptr pData(aEngine.CreateTextObject()); - EnterData(nPosX, nPosY, nTab, *pData); + EditTextObject aData(aEngine.CreateTextObject()); + EnterData(nPosX, nPosY, nTab, aData); } bool ScViewFunc::HasBookmarkAtCursor( SvxHyperlinkItem* pContent ) diff --git a/sc/source/ui/view/viewfun5.cxx b/sc/source/ui/view/viewfun5.cxx index 5a401d20e9ba..d5801f37df21 100644 --- a/sc/source/ui/view/viewfun5.cxx +++ b/sc/source/ui/view/viewfun5.cxx @@ -26,17 +26,12 @@ #include #include -#include -#include -#include -#include #include #include #include #include #include #include -#include #include #include #include @@ -51,14 +46,12 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -77,9 +70,11 @@ #include #include #include +#include #include #include #include +#include #include using namespace com::sun::star; @@ -394,6 +389,7 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId, if ( aDataHelper.GetFileList( nFormatId, aFileList ) ) { sal_uLong nCount = aFileList.Count(); + SetMultiInsertState(nCount > 1); for( sal_uLong i = 0; i < nCount ; i++ ) { OUString aFile = aFileList.GetFile( i ); @@ -697,89 +693,6 @@ bool ScViewFunc::PasteDataFormatSource( SotClipboardFormatId nFormatId, return bRet; } -static bool lcl_convert_markdown_to_csv(OUString& rData) -{ - - auto enter_block_callbck = [](MD_BLOCKTYPE, void*, void*) -> int { - return 0; - }; - - auto leave_block_callbck = [](MD_BLOCKTYPE type, void*, void* userdata) -> int { - - OUString& rStr = *static_cast(userdata); - switch(type) - { - case MD_BLOCK_DOC: - case MD_BLOCK_QUOTE: - case MD_BLOCK_UL: - case MD_BLOCK_OL: - case MD_BLOCK_LI: - case MD_BLOCK_HR: - case MD_BLOCK_H: - case MD_BLOCK_CODE: - case MD_BLOCK_HTML: - case MD_BLOCK_P: - case MD_BLOCK_TABLE: - case MD_BLOCK_THEAD: - case MD_BLOCK_TBODY: - break; - case MD_BLOCK_TR: - { - rStr += u"\n"_ustr; - break; - } - case MD_BLOCK_TH: - case MD_BLOCK_TD: - { - rStr += u","_ustr; - break; - } - } - - return 0; - }; - - auto enter_span_callbck = [](MD_SPANTYPE, void*, void*) -> int { - return 0; - }; - - auto leave_span_callbck = [](MD_SPANTYPE, void*, void*) -> int { - return 0; - }; - - auto text_callbck = [](MD_TEXTTYPE, const MD_CHAR* text, MD_SIZE size, void* userdata) -> int { - - OUString& rStr = *static_cast(userdata); - - OUString aText = OStringToOUString({text, size}, RTL_TEXTENCODING_UTF8); - rStr += aText; - - return 0; - }; - - MD_PARSER parser = {0, - MD_FLAG_TABLES, - enter_block_callbck, - leave_block_callbck, - enter_span_callbck, - leave_span_callbck, - text_callbck, - nullptr, - nullptr}; - - - OUString aConvertedData; - OString rawData = OUStringToOString(rData, RTL_TEXTENCODING_UTF8); - - int ret = md_parse(rawData.getStr(), rawData.getLength(), &parser, static_cast(&aConvertedData)); - - if(ret != 0) - return false; - - rData = aConvertedData; - return true; -} - bool ScViewFunc::PasteDataFormatFormattedText( SotClipboardFormatId nFormatId, const uno::Reference& rxTransferable, SCCOL nPosX, SCROW nPosY, bool bAllowDialogs, @@ -798,6 +711,16 @@ bool ScViewFunc::PasteDataFormatFormattedText( SotClipboardFormatId nFormatId, auto pObj = std::make_shared(GetViewData().GetDocument(), aCellPos); pObj->SetOverwriting( true ); + // tdf#119088 - show overwrite warning for system-clipboard text paste + if (bAllowDialogs && !ScModule::get()->IsInExecuteDrop() + && ScModule::get()->GetInputOptions().GetReplaceCellsWarn() + && !rDoc.IsBlockEmpty(nPosX, nPosY, nPosX, nPosY, aCellPos.Tab())) + { + ScReplaceWarnBox aBox(GetViewData().GetDialogParent()); + if (aBox.run() != RET_YES) + return false; + } + auto pStrBuffer = std::make_shared(); if (std::unique_ptr xStream = rDataHelper.GetSotStorageStream( nFormatId ) ) { @@ -850,42 +773,12 @@ bool ScViewFunc::PasteDataFormatFormattedText( SotClipboardFormatId nFormatId, && rDataHelper.GetString( nFormatId, *pStrBuffer )) { // Do CSV dialog if more than one line. But not if invoked from Automation. - const SfxViewShell* pViewShell = SfxViewShell::Current(); sal_Int32 nDelim = pStrBuffer->indexOf('\n'); - if (!(pViewShell && pViewShell->isLOKMobilePhone()) && !comphelper::Automation::AutomationInvokedZone::isActive() + if (!comphelper::Automation::AutomationInvokedZone::isActive() && nDelim >= 0 && nDelim != pStrBuffer->getLength () - 1) { vcl::Window* pParent = GetActiveWin(); - OUString aSelection; - std::vector aFormats; - aFormats.push_back(SvtResId(STR_FORMAT_STRING)); - - if(comphelper::IsMarkdownData(*pStrBuffer)) //markdown - { - aFormats.push_back(SvtResId(STR_FORMAT_ID_MARKDOWN)); - } - - if(aFormats.size() > 1) - { - GenericDropDownFieldDialog aDialog(pParent->GetFrameWeld(), - SvxResId(RID_SVXSTR_PASTE_AS_DIALOG_TITLE), - aFormats); - short nRet = aDialog.run(); - if( nRet == RET_OK) - { - aSelection = aDialog.GetSelectedItem(); - } - else if(nRet == RET_CANCEL) - return false; - } - - if(aSelection == SvtResId(STR_FORMAT_ID_MARKDOWN)) - { - if(!lcl_convert_markdown_to_csv(*pStrBuffer)) - return false; - } - auto pStrm = std::make_shared(*pStrBuffer); ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); diff --git a/sc/source/ui/view/viewfun6.cxx b/sc/source/ui/view/viewfun6.cxx index 69d1c5524623..2df22465afec 100644 --- a/sc/source/ui/view/viewfun6.cxx +++ b/sc/source/ui/view/viewfun6.cxx @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -192,14 +193,15 @@ void ScViewFunc::DetectiveMarkPred() // This is external. Open the external document if available, and // jump to the destination. - sal_uInt16 nFileId = p->GetIndex(); + auto pExtToken = static_cast(p.get()); + sal_uInt16 nFileId = pExtToken->GetFileId(); ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager(); const OUString* pPath = pRefMgr->getExternalFileName(nFileId); ScRange aRange; if (pPath && ScRefTokenHelper::getRangeFromToken(&rDoc, aRange, p, aCurPos, true)) { - OUString aTabName = p->GetString().getString(); + OUString aTabName = static_cast(p.get())->GetTableName().getString(); OUString aRangeStr(aRange.Format(rDoc, ScRefFlags::VALID)); OUString sUrl = *pPath + diff --git a/sc/source/ui/view/viewfun7.cxx b/sc/source/ui/view/viewfun7.cxx index eaefa3b80228..772167807a45 100644 --- a/sc/source/ui/view/viewfun7.cxx +++ b/sc/source/ui/view/viewfun7.cxx @@ -396,7 +396,7 @@ bool ScViewFunc::PasteGraphic( const Point& rPos, const Graphic& rGraphic, if (pPageView) { SdrObject* pPickObj = pScDrawView->PickObj(rPos, pScDrawView->getHitTolLog(), pPageView); - if (pPickObj) + if (pPickObj && !isMultiInsert()) { const OUString aBeginUndo(ScResId(STR_UNDO_DRAGDROP)); SdrObject* pResult = pScDrawView->ApplyGraphicToObject( diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index 8fc783e31749..aaec58f88fdc 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -81,6 +82,7 @@ #include #include #include +#include #include @@ -129,7 +131,8 @@ static void lcl_PostRepaintSparkLine(sc::SparklineList* pSparklineList, const Sc ScViewFunc::ScViewFunc( vcl::Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) : ScTabView( pParent, rDocSh, pViewShell ), - bFormatValid( false ) + mbFormatValid( false ), + mbMultiInsert( false ) { } @@ -137,7 +140,7 @@ ScViewFunc::~ScViewFunc() { } -bool ScViewFunc::CheckSheetViewProtection(sc::Operation eOperation) +bool ScViewFunc::CheckSheetViewProtection(sc::OperationType eOperation) { sc::SheetViewOperationsTester aSheetViewTester(&GetViewData()); return aSheetViewTester.check(eOperation); @@ -165,7 +168,7 @@ struct FormulaProcessingContext SCROW nRow; SCTAB nTab; - bool bMatrixExpand; + bool bAutoDynamicArray; bool bNumFmtChanged; bool bRecord; @@ -213,12 +216,12 @@ void ScViewFunc::StartFormatArea() if (bOk) { - bFormatValid = true; - aFormatSource = aMarkRange.aStart; - aFormatArea = ScRange( aFormatSource ); + mbFormatValid = true; + maFormatSource = aMarkRange.aStart; + maFormatArea = ScRange( maFormatSource ); } else - bFormatValid = false; // discard old range + mbFormatValid = false; // discard old range } bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, bool bAttrChanged ) @@ -238,39 +241,39 @@ bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, bool bAttrC //! Test if cell empty ??? bool bFound = false; - ScRange aNewRange = aFormatArea; - if ( bFormatValid && nTab == aFormatSource.Tab() ) + ScRange aNewRange = maFormatArea; + if ( mbFormatValid && nTab == maFormatSource.Tab() ) { - if ( nRow >= aFormatArea.aStart.Row() && nRow <= aFormatArea.aEnd.Row() ) + if ( nRow >= maFormatArea.aStart.Row() && nRow <= maFormatArea.aEnd.Row() ) { // within range? - if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() ) + if ( nCol >= maFormatArea.aStart.Col() && nCol <= maFormatArea.aEnd.Col() ) { bFound = true; // do not change range } // left ? - if ( nCol+1 == aFormatArea.aStart.Col() ) + if ( nCol+1 == maFormatArea.aStart.Col() ) { bFound = true; aNewRange.aStart.SetCol( nCol ); } // right ? - if ( nCol == aFormatArea.aEnd.Col()+1 ) + if ( nCol == maFormatArea.aEnd.Col()+1 ) { bFound = true; aNewRange.aEnd.SetCol( nCol ); } } - if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() ) + if ( nCol >= maFormatArea.aStart.Col() && nCol <= maFormatArea.aEnd.Col() ) { // top ? - if ( nRow+1 == aFormatArea.aStart.Row() ) + if ( nRow+1 == maFormatArea.aStart.Row() ) { bFound = true; aNewRange.aStart.SetRow( nRow ); } // bottom ? - if ( nRow == aFormatArea.aEnd.Row()+1 ) + if ( nRow == maFormatArea.aEnd.Row()+1 ) { bFound = true; aNewRange.aEnd.SetRow( nRow ); @@ -279,9 +282,9 @@ bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, bool bAttrC } if (bFound) - aFormatArea = aNewRange; // extend + maFormatArea = aNewRange; // extend else - bFormatValid = false; // outside of range -> break + mbFormatValid = false; // outside of range -> break return bFound; } @@ -293,7 +296,7 @@ void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab, ScDocument& rDoc = pDocSh->GetDocument(); const ScPatternAttr* pSource = rDoc.GetPattern( - aFormatSource.Col(), aFormatSource.Row(), nTab ); + maFormatSource.Col(), maFormatSource.Row(), nTab ); if ( !pSource->GetItem(ATTR_MERGE).IsMerged() ) { ScRange aRange( nCol, nRow, nTab, nCol, nRow, nTab ); @@ -312,7 +315,7 @@ void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab, } if ( bAttrChanged ) // value entered with number format? - aFormatSource.Set( nCol, nRow, nTab ); // then set a new source + maFormatSource.Set( nCol, nRow, nTab ); // then set a new source } // additional routines @@ -528,28 +531,6 @@ void finalizeFormulaProcessing(const std::shared_ptr& pScMod->SetAppOptions(aAppOpt); } - if (context->bMatrixExpand) - { - // If the outer function/operator returns an array/matrix then - // enter a matrix formula. ScViewFunc::EnterMatrix() takes care - // of selection/mark of the result dimensions or preselected - // mark. If the user wanted less or a single cell then should - // mark such prior to entering the formula. - const formula::FormulaToken* pToken = context->pArr->LastRPNToken(); - if (pToken && (formula::FormulaCompiler::IsMatrixFunction( pToken->GetOpCode()) - || pToken->IsInForceArray())) - { - // Discard this (still empty here) Undo action, - // EnterMatrix() will create its own. - if (context->bRecord) - context->GetDocFunc().EndListAction(); - - // Use corrected formula string. - context->rViewFunc.EnterMatrix( context->aFormula, context->GetDoc().GetGrammar()); - - return; - } - } } ScFormulaCell aCell(context->GetDoc(), *context->aPos, std::move(*context->pArr), formula::FormulaGrammar::GRAM_DEFAULT, ScMatrixMode::NONE); @@ -577,6 +558,12 @@ void finalizeFormulaProcessing(const std::shared_ptr& else { ScFormulaCell* pCell = new ScFormulaCell( aCell, context->GetDoc(), *(context->aPos) ); + // Mark a freshly typed formula as eligible for auto-promotion + // to a dynamic-array master. The setter runs on the document- + // owned cell after the clone, since the copy constructor + // clears the bit. + if (context->bAutoDynamicArray) + pCell->SetAutoDynamicArrayEligible(true); if ( nError != FormulaError::NONE ) { pCell->GetCode()->DelRPN(); @@ -663,13 +650,13 @@ void runAutoCorrectQueryAsync(const std::shared_ptr& c } // end anonymous namespace -void ScViewFunc::EnterDataToCurrentCell(const OUString& rString, const EditTextObject* pData, bool bMatrixExpand) +void ScViewFunc::EnterDataToCurrentCell(const OUString& rString, const EditTextObject* pData, bool bAutoDynamicArray) { SCCOL nCol = GetViewData().GetCurX(); SCROW nRow = GetViewData().GetCurY(); SCTAB nTab = GetViewData().CurrentTabForData(); - EnterData(nCol, nRow, nTab, rString, pData, bMatrixExpand); + EnterData(nCol, nRow, nTab, rString, pData, bAutoDynamicArray); } namespace @@ -715,14 +702,19 @@ bool checkFormula(const ScDocument& rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, co void applyFormulaToCell(ScViewFunc& rViewFunc, SCCOL nCol, SCROW nRow, SCTAB nTab, OUString const& rString, const EditTextObject* pData, const std::shared_ptr& rModificator, - ScMarkData const& rMark, bool bMatrixExpand, bool bRecord, bool& rbNumFmtChanged) + ScMarkData const& rMark, bool bAutoDynamicArray, bool bRecord, bool& rbNumFmtChanged) { ScDocument& rDoc = rViewFunc.GetViewData().GetDocument(); // formula, compile with autoCorrection auto xPosPtr = std::make_shared(nCol, nRow, nTab); - auto xCompPtr = std::make_shared(rDoc, *xPosPtr, rDoc.GetGrammar(), true, false); - std::unique_ptr xTextObject(pData ? pData->Clone() : nullptr); + // Skip the compile-time implicit-intersection optimization for UI-typed + // formulas so range tokens survive as svDoubleRef in the RPN and the + // multi-cell intent is visible at interpret time. A formula that stays + // a plain single-cell cell still gets implicit intersection applied at + // runtime. + auto xCompPtr = std::make_shared(rDoc, *xPosPtr, rDoc.GetGrammar(), !bAutoDynamicArray, false); + std::unique_ptr xTextObject(pData ? std::make_unique(*pData) : nullptr); //2do: enable/disable autoCorrection via calcoptions xCompPtr->SetAutoCorrection( true ); @@ -737,7 +729,7 @@ void applyFormulaToCell(ScViewFunc& rViewFunc, SCCOL nCol, SCROW nRow, SCTAB nTa std::move(xPosPtr), std::move(xCompPtr), rModificator, nullptr, nullptr, std::move(xTextObject), rMark, rViewFunc, OUString(), aFormula, rString, nCol, - nRow, nTab, bMatrixExpand, rbNumFmtChanged, + nRow, nTab, bAutoDynamicArray, rbNumFmtChanged, bRecord }; @@ -781,7 +773,7 @@ void applyText(ScViewFunc& rViewFunc, SCCOL nCol, SCROW nRow, SCTAB nTab, OUStri void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString& rString, const EditTextObject* pData, - bool bMatrixExpand ) + bool bAutoDynamicArray ) { ScDocument& rDoc = GetViewData().GetDocument(); ScMarkData aMark(GetViewData().GetMarkData()); @@ -790,11 +782,11 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, ScDocFunc &rFunc = GetViewData().GetDocFunc(); std::shared_ptr xModificator = std::make_shared(*GetViewData().GetDocShell()); - if (!CheckSheetViewProtection(sc::Operation::EnterData)) + if (!CheckSheetViewProtection(sc::OperationType::EnterData)) return; ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(rDoc, nCol, nRow, nCol, nRow, aMark); - if (!aTester.IsEditable()) + if (!aTester.IsEditableOrMatrixCell(rDoc, ScAddress(nCol, nRow, nTab))) { ErrorMessage(aTester.GetMessageId()); PaintArea(nCol, nRow, nCol, nRow); // possibly the edit-engine is still painted there @@ -804,85 +796,24 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, if ( bRecord ) rFunc.EnterListAction( STR_UNDO_ENTERDATA ); + // If the user is typing into a multi-cell matrix master, tear the + // matrix down first so the new value doesn't leave reference cells + // orphaned. Both undos roll back together because of the list action. + sc::DocFuncUtil::demolishMatrixMaster(rFunc, rDoc, ScAddress(nCol, nRow, nTab), + /*bApi*/ false); + bool bFormula = checkFormula(rDoc, nCol, nRow, nTab, rString); bool bNumFmtChanged = false; if (bFormula) { - SCTAB nSelectedTab = aMark.GetFirstSelected(); - - applyFormulaToCell(*this, nCol, nRow, nTab, rString, pData, xModificator, aMark, bMatrixExpand, bRecord, bNumFmtChanged); - - if (rDoc.IsSheetViewHolder(nSelectedTab)) - return; - - auto pManager = rDoc.GetSheetViewManager(nSelectedTab); - - for (auto const& pSheetView : pManager->getSheetViews()) - { - if (!pSheetView) - continue; - - SCTAB nSheetViewTab = pSheetView->getTableNumber(); - - ScMarkData aSheetViewMark(rDoc.GetSheetLimits()); - aSheetViewMark.SelectTable(nSheetViewTab, false); - ScRange aSheetViewRange(aMark.GetMarkArea()); - aSheetViewRange.aStart.SetTab(nSheetViewTab); - aSheetViewRange.aEnd.SetTab(nSheetViewTab); - aSheetViewMark.SetMarkArea(aSheetViewRange); - - applyFormulaToCell(*this, nCol, nRow, nSheetViewTab, rString, pData, xModificator, aSheetViewMark, bMatrixExpand, bRecord, bNumFmtChanged); - } + applyFormulaToCell(*this, nCol, nRow, nTab, rString, pData, xModificator, aMark, bAutoDynamicArray, bRecord, bNumFmtChanged); } else { - sc::SheetViewID nSheetViewID = GetViewData().GetSheetViewID(); for (const auto& rTab : aMark) { - if (rDoc.IsSheetViewHolder(rTab)) - continue; - - auto pManager = rDoc.GetSheetViewManager(rTab); - - for (auto const& pSheetView : pManager->getSheetViews()) - { - if (!pSheetView) - continue; - - SCTAB nSheetViewTab = pSheetView->getTableNumber(); - - if (GetViewData().GetSheetViewID() == sc::DefaultSheetViewID) - { - SCROW nUnsortedRow = nRow; - if (pManager->getSortOrder()) - nUnsortedRow = pManager->getSortOrder()->unsort(nUnsortedRow); - applyText(*this, nCol, nUnsortedRow, nSheetViewTab, rString, bNumFmtChanged); - } - else if (GetViewData().GetSheetViewID() == pSheetView->getID()) - { - applyText(*this, nCol, nRow, nSheetViewTab, rString, bNumFmtChanged); - } - else - { - // TODO - we need to update other sheet views as well, test case needed - } - } - - { - SCROW nUnsortedRow = nRow; - - if (nSheetViewID != sc::DefaultSheetViewID) - { - auto pSheetView = pManager->get(nSheetViewID); - - if (pSheetView->getSortOrder()) - nUnsortedRow = pSheetView->getSortOrder()->unsort(nUnsortedRow); - if (pManager->getSortOrder()) - nUnsortedRow = pManager->getSortOrder()->resort(nUnsortedRow); - } - applyText(*this, nCol, nUnsortedRow, rTab, rString, bNumFmtChanged); - } + applyText(*this, nCol, nRow, rTab, rString, bNumFmtChanged); } performAutoFormatAndUpdate(rString, aMark, nCol, nRow, nTab, bNumFmtChanged, bRecord, xModificator, *this); @@ -902,10 +833,19 @@ void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& r bool bUndo(rDoc.IsUndoEnabled()); ScDocShellModificator aModificator( *pDocSh ); + const ScAddress aPos( nCol, nRow, nTab ); ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(rDoc, nTab, nCol, nRow, nCol, nRow); - if (aTester.IsEditable()) + if (aTester.IsEditableOrMatrixCell(rDoc, aPos)) { - ScAddress aPos( nCol, nRow, nTab ); + ScDocFunc& rFunc = pDocSh->GetDocFunc(); + if (bUndo) + rFunc.EnterListAction(STR_UNDO_ENTERDATA); + + // If the user is replacing a multi-cell matrix master, tear the + // whole matrix down first so the new value doesn't leave reference + // cells orphaned. Both undos roll back together. + sc::DocFuncUtil::demolishMatrixMaster(rFunc, rDoc, aPos, /*bApi*/ false); + ScCellValue aUndoCell; if (bUndo) aUndoCell.assign(rDoc, aPos); @@ -917,6 +857,7 @@ void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& r { pDocSh->GetUndoManager()->AddUndoAction( std::make_unique(*pDocSh, aPos, aUndoCell, rValue)); + rFunc.EndListAction(); } pDocSh->PostPaintCell( aPos ); @@ -937,11 +878,11 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, ScDocShellModificator aModificator( *pDocSh ); - if (!CheckSheetViewProtection(sc::Operation::EnterData)) + if (!CheckSheetViewProtection(sc::OperationType::EnterData)) return; ScEditableTester aTester = ScEditableTester::CreateAndTestBlock(rDoc, nTab, nCol, nRow, nCol, nRow); - if (aTester.IsEditable()) + if (aTester.IsEditableOrMatrixCell(rDoc, ScAddress(nCol, nRow, nTab))) { // test for attribute @@ -997,7 +938,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, aOldValues.push_back(aOldValue); } - pUndoData = rData.Clone(); + pUndoData = std::make_unique(rData); } // enter data @@ -1010,10 +951,23 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, if (bCommon) AdjustRowHeight(nRow,nRow,true); - EnterData( nCol, nRow, nTab, aString, nullptr, true /*bMatrixExpand*/); + EnterData( nCol, nRow, nTab, aString, nullptr, true /*bAutoDynamicArray*/); } else { + ScDocFunc& rFunc = pDocSh->GetDocFunc(); + if (bRecord) + rFunc.EnterListAction(STR_UNDO_ENTERDATA); + + // If the user is replacing a multi-cell matrix master, tear the + // whole matrix down first so the new value doesn't leave + // reference cells orphaned. + for (const auto& rTab : rMark) + { + sc::DocFuncUtil::demolishMatrixMaster( + rFunc, rDoc, ScAddress(nCol, nRow, rTab), /*bApi*/ false); + } + for (const auto& rTab : rMark) { ScAddress aPos(nCol, nRow, rTab); @@ -1024,6 +978,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, { // because of ChangeTrack current first pDocSh->GetUndoManager()->AddUndoAction( std::make_unique(*pDocSh, ScAddress(nCol,nRow,nTab), aOldValues, aString, std::move(pUndoData))); + rFunc.EndListAction(); } HideAllCursors(); @@ -1070,7 +1025,8 @@ void ScViewFunc::EnterMatrix( const OUString& rString, ::formula::FormulaGrammar const SCCOL nCol = rData.GetCurX(); const SCROW nRow = rData.GetCurY(); const ScMarkData& rMark = rData.GetMarkData(); - if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) + bool bAutoExpand = !rMark.IsMarked() && !rMark.IsMultiMarked(); + if (bAutoExpand) { // nothing marked -> temporarily calculate block // with size of result formula to get the size @@ -1097,8 +1053,11 @@ void ScViewFunc::EnterMatrix( const OUString& rString, ::formula::FormulaGrammar if (rData.GetSimpleArea(aRange) == SC_MARK_SIMPLE) { ScDocShell* pDocSh = rData.GetDocShell(); + // Ctrl+Shift+Enter always produces a static CSE master, whether the + // user selected the range or Calc auto-expanded it from a single + // cell. The dynamic-array flag stays off. bool bSuccess = pDocSh->GetDocFunc().EnterMatrix( - aRange, &rMark, nullptr, rString, false, false, OUString(), eGram ); + aRange, &rMark, nullptr, rString, false, false, OUString(), eGram, false); if (bSuccess) pDocSh->UpdateOle(GetViewData()); else @@ -1164,7 +1123,27 @@ const ScPatternAttr* ScViewFunc::GetSelectionPattern(bool bExcludeFiltered) // copy sheet selection aMark.SetMarkArea( ScRange( nCol, nRow, nTab ) ); - const ScPatternAttr* pAttr = rDoc.GetSelectionPattern( aMark ); + + // We want to get the state of the sheet view, so we need to convert what is marked + if (GetViewData().GetSheetViewID() != sc::DefaultSheetViewID) + { + SCTAB nDefaultViewTab = GetViewData().GetTabNumber(); + SCTAB nSheetViewTab = GetViewData().CurrentTabForData(); + + if (nDefaultViewTab == aMark.GetArea().aStart.Tab() + && nDefaultViewTab == aMark.GetArea().aEnd.Tab()) + { + aMark.SetAreaTab(nSheetViewTab); + } + + if (aMark.GetTableSelect(nDefaultViewTab)) + { + aMark.SelectTable(nDefaultViewTab, false); + aMark.SelectTable(nSheetViewTab, true); + } + } + + const ScPatternAttr* pAttr = rDoc.GetSelectionPattern(aMark); return pAttr; } } @@ -1469,9 +1448,15 @@ void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr, bool bCursor ScMarkData aFuncMark( rViewData.GetMarkData() ); // local copy for UnmarkFiltered ScViewUtil::UnmarkFiltered( aFuncMark, rDoc ); - bool bRecord = true; - if (!rDoc.IsUndoEnabled()) - bRecord = false; + bool bMultiMarked = aFuncMark.IsMultiMarked(); + aFuncMark.MarkToMulti(); + ScAddress aPosition(rViewData.GetCurX(), rViewData.GetCurY(), rViewData.CurrentTabForData()); + bool bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1); + if (bOnlyTab) + { + aFuncMark.SetMarkArea(ScRange(aPosition)); + aFuncMark.MarkToMulti(); + } // State from old ItemSet doesn't matter for paint flags, as any change will be // from SfxItemState::SET in the new ItemSet (default is ignored in ApplyPattern). @@ -1488,114 +1473,24 @@ void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr, bool bCursor if ( bSetAlign ) nExtFlags |= SC_PF_WHOLEROWS; - ScDocShellModificator aModificator( *pDocSh ); - - bool bMulti = aFuncMark.IsMultiMarked(); - aFuncMark.MarkToMulti(); - bool bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1); - if (bOnlyTab) - { - SCCOL nCol = rViewData.GetCurX(); - SCROW nRow = rViewData.GetCurY(); - SCTAB nTab = rViewData.CurrentTabForData(); - aFuncMark.SetMarkArea(ScRange(nCol,nRow,nTab)); - aFuncMark.MarkToMulti(); - } - ScRangeList aChangeRanges; - + bool bResult = false; if (aFuncMark.IsMultiMarked() && !bCursorOnly) { - const ScRange& aMarkRange = aFuncMark.GetMultiMarkArea(); - SCTAB nTabCount = rDoc.GetTableCount(); - for (const auto& rTab : aFuncMark) - { - ScRange aChangeRange( aMarkRange ); - aChangeRange.aStart.SetTab( rTab ); - aChangeRange.aEnd.SetTab( rTab ); - aChangeRanges.push_back( aChangeRange ); - } - - SCCOL nStartCol = aMarkRange.aStart.Col(); - SCROW nStartRow = aMarkRange.aStart.Row(); - SCTAB nStartTab = aMarkRange.aStart.Tab(); - SCCOL nEndCol = aMarkRange.aEnd.Col(); - SCROW nEndRow = aMarkRange.aEnd.Row(); - SCTAB nEndTab = aMarkRange.aEnd.Tab(); - - ScEditDataArray* pEditDataArray = nullptr; - if (bRecord) - { - ScRange aCopyRange = aMarkRange; - aCopyRange.aStart.SetTab(0); - aCopyRange.aEnd.SetTab(nTabCount-1); - - ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); - pUndoDoc->InitUndo( rDoc, nStartTab, nStartTab ); - for (const auto& rTab : aFuncMark) - if (rTab != nStartTab) - pUndoDoc->AddUndoTab( rTab, rTab ); - rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ATTRIB, bMulti, *pUndoDoc, &aFuncMark ); - - aFuncMark.MarkToMulti(); - - ScUndoSelectionAttr* pUndoAttr = new ScUndoSelectionAttr( - *pDocSh, aFuncMark, nStartCol, nStartRow, nStartTab, - nEndCol, nEndRow, nEndTab, std::move(pUndoDoc), bMulti, &rAttr ); - pDocSh->GetUndoManager()->AddUndoAction(std::unique_ptr(pUndoAttr)); - pEditDataArray = pUndoAttr->GetDataArray(); - } - - rDoc.ApplySelectionPattern( rAttr, aFuncMark, pEditDataArray ); - - pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, - nEndCol, nEndRow, nEndTab, - PaintPartFlags::Grid, nExtFlags | SC_PF_TESTMERGE ); - pDocSh->UpdateOle(GetViewData()); - aModificator.SetDocumentModified(); - CellContentChanged(); + sc::ApplyAttributesWithChangedRangeOperation aOperation(*pDocSh, aFuncMark, bMultiMarked, rAttr, nExtFlags, false); + bResult = aOperation.run(); + aChangeRanges = aOperation.getChangedRangeList(); } - else // single cell - simpler undo + else { - SCCOL nCol = rViewData.GetCurX(); - SCROW nRow = rViewData.GetCurY(); - SCTAB nTab = rViewData.CurrentTabForData(); - - std::unique_ptr pOldEditData; - std::unique_ptr pNewEditData; - ScAddress aPos(nCol, nRow, nTab); - ScRefCellValue aCell(rDoc, aPos); - if (aCell.getType() == CELLTYPE_EDIT) - { - const EditTextObject* pEditObj = aCell.getEditText(); - pOldEditData = pEditObj->Clone(); - rDoc.RemoveEditTextCharAttribs(aPos, rAttr); - pEditObj = rDoc.GetEditText(aPos); - pNewEditData = pEditObj->Clone(); - } - - aChangeRanges.push_back(ScRange(aPos)); - std::optional pOldPat(*rDoc.GetPattern( nCol, nRow, nTab )); - - rDoc.ApplyPattern( nCol, nRow, nTab, rAttr ); - - const ScPatternAttr* pNewPat = rDoc.GetPattern( nCol, nRow, nTab ); - - if (bRecord) - { - std::unique_ptr pUndo(new ScUndoCursorAttr( - *pDocSh, nCol, nRow, nTab, &*pOldPat, pNewPat, &rAttr )); - pUndo->SetEditData(std::move(pOldEditData), std::move(pNewEditData)); - pDocSh->GetUndoManager()->AddUndoAction(std::move(pUndo)); - } - pOldPat.reset(); // is copied in undo (Pool) - - pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PaintPartFlags::Grid, nExtFlags | SC_PF_TESTMERGE ); - pDocSh->UpdateOle(GetViewData()); - aModificator.SetDocumentModified(); - CellContentChanged(); + sc::ApplyAttributesToCellOperation aOperation(*pDocSh, aPosition, rAttr, nExtFlags, false); + bResult = aOperation.run(); + aChangeRanges = aOperation.getChangedRangeList(); } + if (bResult) + CellContentChanged(); + ScModelObj* pModelObj = pDocSh->GetModel(); if (HelperNotifyChanges::getMustPropagateChangesModel(pModelObj)) @@ -1821,7 +1716,7 @@ void ScViewFunc::OnLOKInsertDeleteColumn(SCCOL nStartCol, tools::Long nOffset) if (!comphelper::LibreOfficeKit::isActive() || nOffset == 0) return; - SCTAB nCurrentTabIndex = GetViewData().CurrentTabForData(); + SCTAB nCurrentTabIndex = GetViewData().GetTabNumber(); SfxViewShell* pCurrentViewShell = GetViewData().GetViewShell(); SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell) @@ -1884,7 +1779,7 @@ void ScViewFunc::OnLOKInsertDeleteRow(SCROW nStartRow, tools::Long nOffset) if (!comphelper::LibreOfficeKit::isActive() || nOffset == 0) return; - SCTAB nCurrentTabIndex = GetViewData().CurrentTabForData(); + SCTAB nCurrentTabIndex = GetViewData().GetTabNumber(); SfxViewShell* pCurrentViewShell = GetViewData().GetViewShell(); SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell) @@ -2350,7 +2245,7 @@ void ScViewFunc::DeleteContents( InsertDeleteFlags nFlags ) { aMarkRange.aStart.SetCol(GetViewData().GetCurX()); aMarkRange.aStart.SetRow(GetViewData().GetCurY()); - aMarkRange.aStart.SetTab(GetViewData().CurrentTabForData()); + aMarkRange.aStart.SetTab(GetViewData().GetTabNumber()); aMarkRange.aEnd = aMarkRange.aStart; if ( rDoc.HasAttrib( aMarkRange, HasAttrFlags::Merged ) ) { @@ -2398,7 +2293,7 @@ void ScViewFunc::DeleteContents( InsertDeleteFlags nFlags ) if ( nFlags & InsertDeleteFlags::ATTRIB ) { if ( nFlags & InsertDeleteFlags::CONTENTS ) - bFormatValid = false; + mbFormatValid = false; else StartFormatArea(); // delete attribute is also attribute-change } @@ -3241,7 +3136,7 @@ bool ScViewFunc::InsertName( const OUString& rName, const OUString& rSymbol, ScDocShell* pDocSh = GetViewData().GetDocShell(); ScDocument& rDoc = pDocSh->GetDocument(); SCTAB nTab = GetViewData().CurrentTabForData(); - ScRangeName* pList = rDoc.GetRangeName(); + ScRangeName& rList = rDoc.GetRangeName(); ScRangeData::Type nType = ScRangeData::Type::Name; auto pNewEntry = std::make_unique( @@ -3265,15 +3160,14 @@ bool ScViewFunc::InsertName( const OUString& rName, const OUString& rSymbol, rDoc.PreprocessRangeNameUpdate(); // input available yet? Then remove beforehand (=change) - ScRangeData* pData = pList->findByUpperName(ScGlobal::getCharClass().uppercase(rName)); + ScRangeData* pData = rList.findByUpperName(ScGlobal::getCharClass().uppercase(rName)); if (pData) { // take old Index pNewEntry->SetIndex(pData->GetIndex()); - pList->erase(*pData); + rList.erase(*pData); } - // don't delete, insert took ownership, even on failure! - if ( pList->insert( pNewEntry.release() ) ) + if ( rList.insert( std::move(pNewEntry) ) ) bOk = true; rDoc.CompileHybridFormula(); diff --git a/sc/uiconfig/scalc/menubar/menubar.xml b/sc/uiconfig/scalc/menubar/menubar.xml index fe3c46feb4ae..b2aaba4e574b 100644 --- a/sc/uiconfig/scalc/menubar/menubar.xml +++ b/sc/uiconfig/scalc/menubar/menubar.xml @@ -22,11 +22,11 @@ - - + + - + @@ -34,14 +34,14 @@ - - + + - + @@ -50,8 +50,8 @@ - - + + @@ -63,11 +63,11 @@ - + - + @@ -75,63 +75,63 @@ - + - + - + - + - - - + + + - + - + - - + + - - + + - - + + - - - - - - - + + + + + + + - + - - + + - + - - + + @@ -147,8 +147,8 @@ - - + + @@ -156,51 +156,51 @@ - + - - - + + + - - - - - + + + + + - - + + - - + + - - - - - - + + + + + + - + - - - + + + - - - + + + - + @@ -209,31 +209,31 @@ - - - - + + + + - - + + - + - + - + - + - + - + @@ -245,24 +245,24 @@ - - - - - - - + + + + + + + - + - + - + - + @@ -277,47 +277,47 @@ - - - + + + - - - + + + - + - - - - - - + + + + + + - - + + - - - - - - + + + + + + - + - - + + - - + + - - + + @@ -325,7 +325,7 @@ - + @@ -356,7 +356,7 @@ - + @@ -368,68 +368,68 @@ - + - - - - - - - + + + + + + + - + - + - + - - - - + + + + - - - - + + + + - + - - - + + + - - + + - - - + + + - + - - - + + + - - - + + + @@ -438,79 +438,79 @@ - + - - - - + + + + - + - - + + - - - - + + + + - - + + - + - - + + - + - - - - + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - + + - + @@ -518,57 +518,57 @@ - - + + - + - - + + - + - + - + - - - - - - - + + + + + + + - + - + - - + + - + - - - - - + + + + + @@ -576,13 +576,13 @@ - - + + - - - + + + @@ -591,158 +591,158 @@ - + - - - - + + + + - + - - + + - - - + + + - + - - - + + + - + - - - - + + + + - + - + - + - - + + - + - - + + - - - - + + + + - - + + - - + + - - + + - + - + - + - + - - + + - + - + - + - - - + + + - - + + - - - + + + - - + + - - - + + + - + - - + + - - + + - - - + + + - - + + - - - + + + - + - + - - - - + + + + - + - + - + @@ -750,28 +750,27 @@ - + - + - - + - + - + diff --git a/sc/uiconfig/scalc/popupmenu/celledit.xml b/sc/uiconfig/scalc/popupmenu/celledit.xml index 36aad7336769..b3375a2f714e 100644 --- a/sc/uiconfig/scalc/popupmenu/celledit.xml +++ b/sc/uiconfig/scalc/popupmenu/celledit.xml @@ -11,6 +11,7 @@ + diff --git a/sc/uiconfig/scalc/popupmenu/formulabar.xml b/sc/uiconfig/scalc/popupmenu/formulabar.xml index ce6abf1d393d..40d53bf49d0c 100644 --- a/sc/uiconfig/scalc/popupmenu/formulabar.xml +++ b/sc/uiconfig/scalc/popupmenu/formulabar.xml @@ -11,7 +11,7 @@ - + diff --git a/sc/uiconfig/scalc/toolbar/previewbar.xml b/sc/uiconfig/scalc/toolbar/previewbar.xml index f8da09167073..ded831b6d0a0 100644 --- a/sc/uiconfig/scalc/toolbar/previewbar.xml +++ b/sc/uiconfig/scalc/toolbar/previewbar.xml @@ -35,5 +35,5 @@ - + diff --git a/sc/uiconfig/scalc/toolbar/toolbar.xml b/sc/uiconfig/scalc/toolbar/toolbar.xml index d2d1708b28cc..c24862a03dd2 100644 --- a/sc/uiconfig/scalc/toolbar/toolbar.xml +++ b/sc/uiconfig/scalc/toolbar/toolbar.xml @@ -30,7 +30,6 @@ - diff --git a/sc/uiconfig/scalc/ui/advancedfilterdialog.ui b/sc/uiconfig/scalc/ui/advancedfilterdialog.ui index 2f7f65abbffe..28a57894a10c 100644 --- a/sc/uiconfig/scalc/ui/advancedfilterdialog.ui +++ b/sc/uiconfig/scalc/ui/advancedfilterdialog.ui @@ -1,19 +1,19 @@ - + - False - 6 + False + 6 Advanced Filter False - 0 - 0 - dialog + 0 + 0 + dialog True - False + False True True vertical @@ -21,17 +21,17 @@ True - False + False True - end + end _OK True - True - True - True - True + True + True + True + True True @@ -49,9 +49,9 @@ _Cancel True - True - True - True + True + True + True True @@ -69,9 +69,9 @@ _Help True - True - True - True + True + True + True True @@ -85,32 +85,32 @@ False True - end + end 1 True - False + False True - 0 - none + 0 + none - + True - False - True - True - 12 + False 12 6 + True + True + 12 True - True - True + True + True @@ -121,14 +121,14 @@ - 2 - 0 + 2 + 0 True - False + False Select the named range, or enter the cell range that contains the filter criteria that you want to use. @@ -136,27 +136,28 @@ - 0 - 0 + 0 + 0 True - True + True True - True - 30 + True + 30 True + Read Filter Criteria From Select the named range, or enter the cell range that contains the filter criteria that you want to use. - 1 - 0 + 1 + 0 @@ -164,10 +165,10 @@ True - False + False Read _Filter Criteria From - True - lbfilterarea + True + lbfilterarea @@ -183,37 +184,37 @@ True - True + True True - True + True - + True - False + False 12 - 6 + 6 True True - 6 + 6 - + True - False + False True True - 6 - 12 + 6 + 12 _Case sensitive True - True - False + True + False True - True - True + True + True Distinguishes between uppercase and lowercase letters when filtering the data. @@ -221,19 +222,19 @@ - 0 - 0 + 0 + 0 Range c_ontains column labels True - True - False + True + False True - True - True + True + True Includes the column labels in the first row of a cell range. @@ -241,19 +242,19 @@ - 0 - 1 + 0 + 1 Regular _expressions True - True - False + True + False True - True - True + True + True Allows you to use regular expressions in the filter definition. @@ -261,19 +262,19 @@ - 1 - 0 + 1 + 0 _No duplications True - True - False + True + False True - True - True + True + True Excludes duplicate rows in the list of filtered data. @@ -281,19 +282,19 @@ - 1 - 1 + 1 + 1 Co_py results to: True - True - False + True + False True - True - True + True + True @@ -305,19 +306,19 @@ - 0 - 2 + 0 + 2 _Keep filter criteria True - True - False + True + False True - True - True + True + True Select the Copy results to check box, and then specify the destination range where you want to display the filtered data. If this box is checked, the destination range remains linked to the source range. You must have defined the source range under Data - Define range as a database range. @@ -325,28 +326,28 @@ - 1 - 2 + 1 + 2 - 0 - 0 + 0 + 0 - + True - False + False 12 True - 12 + 12 True - False + False @@ -358,21 +359,21 @@ - 0 - 0 + 0 + 0 True - True - 1 + True + 1 True - 30 + 30 + True - True Copy results to: @@ -381,15 +382,15 @@ - 1 - 0 + 1 + 0 True - True - True + True + True @@ -400,51 +401,51 @@ - 2 - 0 + 2 + 0 - 0 - 1 + 0 + 1 - + False - False - 12 + False + 12 False - False + False Data range: 0 - 0 - 0 + 0 + 0 False - False + False True dummy 0 - 1 - 0 + 1 + 0 - 0 - 2 + 0 + 2 @@ -452,9 +453,9 @@ True - False + False Op_tions - True + True @@ -476,9 +477,6 @@ cancel help - - - Defines an advanced filter. diff --git a/sc/uiconfig/scalc/ui/allheaderfooterdialog.ui b/sc/uiconfig/scalc/ui/allheaderfooterdialog.ui index bd4cbc25c5a4..1ab5df37452d 100644 --- a/sc/uiconfig/scalc/ui/allheaderfooterdialog.ui +++ b/sc/uiconfig/scalc/ui/allheaderfooterdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/analysisofvariancedialog.ui b/sc/uiconfig/scalc/ui/analysisofvariancedialog.ui index 90c0cd757390..d0baf1c7852b 100644 --- a/sc/uiconfig/scalc/ui/analysisofvariancedialog.ui +++ b/sc/uiconfig/scalc/ui/analysisofvariancedialog.ui @@ -1,39 +1,39 @@ - + 0.01 - 0.99 + 0.98999999999999999 0.05 - 0.01 - 0.05 + 0.01 + 0.05 - False - 6 + False + 6 Analysis of Variance (ANOVA) False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -46,9 +46,9 @@ _Cancel True - True - True - True + True + True + True True @@ -61,8 +61,8 @@ _Help True - True - True + True + True True @@ -76,105 +76,105 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 True - False + False Input range: - True - input-range-edit + True + input-range-edit 0 - 0 - 0 - - - - - True - False - Results to: - True - output-range-edit - 0 - - - 0 - 1 + 0 + 0 True - True + True center True - True + True + 30 True - 30 - 1 - 0 - - - - - True - True - center - True - True - True - 30 - - - 1 - 1 + 1 + 0 True - True - True + True + True - 2 - 0 + 2 + 0 + + + + + True + False + Results to: + True + output-range-edit + 0 + + + 0 + 1 + + + + + True + True + center + True + True + 30 + True + + + 1 + 1 True - True - True + True + True - 2 - 1 + 2 + 1 @@ -182,7 +182,7 @@ True - False + False Data @@ -199,48 +199,48 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 Single factor True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 Two factor True - True - False - True - True + True + False + True + True radio-single-factor - 1 - 0 + 1 + 0 @@ -248,7 +248,7 @@ True - False + False Type @@ -265,48 +265,48 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 Columns True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 Rows True - True - False - True - True + True + False + True + True groupedby-columns-radio - 1 - 0 + 1 + 0 @@ -314,7 +314,7 @@ True - False + False Grouped by @@ -331,76 +331,76 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 True - False + False Alpha: - True - alpha-spin + True + alpha-spin 0 - 0 - 0 + 0 + 0 True - True - True + True + True 0.05 + True alpha-adjustment 2 - True 0.05 - 1 - 0 + 1 + 0 True - False + False Rows per sample: - True - rows-per-sample-spin + True + rows-per-sample-spin 0 - 0 - 1 + 0 + 1 True - True - True + True + True 1 True 1 - 1 - 1 + 1 + 1 @@ -408,7 +408,7 @@ True - False + False Parameters @@ -429,9 +429,6 @@ cancel help - - - Produces the analysis of variance (ANOVA) of a given data set diff --git a/sc/uiconfig/scalc/ui/cellprotectionpage.ui b/sc/uiconfig/scalc/ui/cellprotectionpage.ui index 9bc1e47335e4..78bd59d0089b 100644 --- a/sc/uiconfig/scalc/ui/cellprotectionpage.ui +++ b/sc/uiconfig/scalc/ui/cellprotectionpage.ui @@ -1,84 +1,41 @@ - + - + True - False - 6 - 12 - 6 + False + 6 + 12 + 6 True - False + False GDK_EXPOSURE_MASK True - 0 - none + 0 + none - + True - False - True - 6 - 12 + False 12 6 - - - _Protected - True - True - False - 12 - True - True - True - True - - - Prevents the selected cells from being modified. - - - - - 0 - 1 - - - - - Hide _formula - True - True - False - 12 - True - True - True - - - Hides formulas in the selected cells. - - - - - 0 - 2 - - + True + 6 + 12 Hide _all True - True - False - True + True + False + True True - True + True Hides formulas and contents of the selected cells. @@ -86,29 +43,72 @@ - 0 - 0 + 0 + 0 + + + + + _Protected + True + True + False + 12 + True + True + True + True + + + Prevents the selected cells from being modified. + + + + + 0 + 1 + + + + + Hide _formula + True + True + False + 12 + True + True + True + + + Hides formulas in the selected cells. + + + + + 0 + 2 True - False + False end True Cell protection is only effective after the current sheet has been protected. Select 'Protect Sheet' from the 'Tools' menu. True - 52 + 52 0 - + - 1 - 0 + 1 + 0 3 @@ -117,7 +117,7 @@ Select 'Protect Sheet' from the 'Tools' menu. True - False + False Protection @@ -126,35 +126,35 @@ Select 'Protect Sheet' from the 'Tools' menu. - 0 - 0 + 0 + 0 True - False + False start True - 0 - none + 0 + none - + True - False - 12 + False 12 6 + 12 Hide _when printing True - True - False - True + True + False + True True - True + True Keeps the selected cells from being printed. @@ -162,27 +162,27 @@ Select 'Protect Sheet' from the 'Tools' menu. - 0 - 0 + 0 + 0 True - False + False end True The cells selected will be omitted when printing. True - 52 + 52 0 - + - 1 - 0 + 1 + 0 @@ -190,7 +190,7 @@ Select 'Protect Sheet' from the 'Tools' menu. True - False + False Print @@ -199,8 +199,8 @@ Select 'Protect Sheet' from the 'Tools' menu. - 0 - 1 + 0 + 1 diff --git a/sc/uiconfig/scalc/ui/chardialog.ui b/sc/uiconfig/scalc/ui/chardialog.ui index 8942216719cc..9eb08a4d1505 100644 --- a/sc/uiconfig/scalc/ui/chardialog.ui +++ b/sc/uiconfig/scalc/ui/chardialog.ui @@ -103,7 +103,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/chisquaretestdialog.ui b/sc/uiconfig/scalc/ui/chisquaretestdialog.ui index 52de4446c826..76c9586ccf13 100644 --- a/sc/uiconfig/scalc/ui/chisquaretestdialog.ui +++ b/sc/uiconfig/scalc/ui/chisquaretestdialog.ui @@ -1,32 +1,32 @@ - + - False - 6 + False + 6 Chi Square Test False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -39,9 +39,9 @@ _Cancel True - True - True - True + True + True + True True @@ -54,8 +54,8 @@ _Help True - True - True + True + True True @@ -69,105 +69,105 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 6 6 6 - 6 + 6 + 12 True - False + False Input range: - True - input-range-edit + True + input-range-edit 0 - 0 - 0 + 0 + 0 True - True + True center True - True + True + 30 True - 30 - 1 - 0 + 1 + 0 True - True - True + True + True - 2 - 0 + 2 + 0 True - False + False Results to: - True - output-range-edit + True + output-range-edit 0 - 0 - 1 + 0 + 1 True - True + True center True - True + True + 30 True - 30 - 1 - 1 + 1 + 1 True - True - True + True + True - 2 - 1 + 2 + 1 @@ -175,7 +175,7 @@ True - False + False Data @@ -192,48 +192,48 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 6 6 6 - 6 + 6 + 12 _Columns True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 _Rows True - True - False - True - True + True + False + True + True groupedby-columns-radio - 1 - 0 + 1 + 0 @@ -241,7 +241,7 @@ True - False + False Grouped by @@ -262,9 +262,6 @@ cancel help - - - Calculates the Chi-square test of a data sample. diff --git a/sc/uiconfig/scalc/ui/colorrowdialog.ui b/sc/uiconfig/scalc/ui/colorrowdialog.ui index c07d801f923c..ee51b8102cb8 100644 --- a/sc/uiconfig/scalc/ui/colorrowdialog.ui +++ b/sc/uiconfig/scalc/ui/colorrowdialog.ui @@ -1,33 +1,33 @@ - + - False - 6 + False + 6 Copy List False True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -40,8 +40,8 @@ _Cancel True - True - True + True + True True @@ -54,8 +54,8 @@ _Help True - True - True + True + True True @@ -63,40 +63,40 @@ True 2 True - True + True False True - end + end 0 True - False - 0 - none + False + 0 + none True - False - vertical - 6 + False 12 6 + vertical + 6 _Columns True - True - False - True + True + False + True True - True + True Select the Columns option to summarize the contents of the selected columns in a list. @@ -113,10 +113,10 @@ _Rows True - True - False - True - True + True + False + True + True columns @@ -135,7 +135,7 @@ True - False + False List From @@ -156,9 +156,6 @@ cancel help - - - Allows you to copy marked cells to a sort list. diff --git a/sc/uiconfig/scalc/ui/conditionaleasydialog.ui b/sc/uiconfig/scalc/ui/conditionaleasydialog.ui index 55cb0275c713..ecfcaac4c8ae 100644 --- a/sc/uiconfig/scalc/ui/conditionaleasydialog.ui +++ b/sc/uiconfig/scalc/ui/conditionaleasydialog.ui @@ -86,7 +86,7 @@ vertical 24 - + True False 0 diff --git a/sc/uiconfig/scalc/ui/consolidatedialog.ui b/sc/uiconfig/scalc/ui/consolidatedialog.ui index a7e3aca168e0..166d106c397a 100644 --- a/sc/uiconfig/scalc/ui/consolidatedialog.ui +++ b/sc/uiconfig/scalc/ui/consolidatedialog.ui @@ -1,5 +1,5 @@ - + @@ -11,32 +11,32 @@ - False - 6 + False + 6 Consolidate False - 0 - 0 - dialog + 0 + 0 + dialog - False + False True vertical 12 - False + False True - end + end _OK True - True - True - True - True + True + True + True + True True @@ -54,9 +54,9 @@ _Cancel True - True - True - True + True + True + True True @@ -74,9 +74,9 @@ _Help True - True - True - True + True + True + True True @@ -90,52 +90,52 @@ False True - end + end 0 - + True - False + False True True - 6 + 6 True - False + False True _Function: - True - func + True + func 0 - 0 - 0 + 0 + 0 True - False + False True _Consolidation ranges: - True - consareas + True + consareas 0 - 0 - 2 + 0 + 2 True - False + False True Sum @@ -157,29 +157,29 @@ - 0 - 1 + 0 + 1 True - True + True True True - in + in - -1 + -1 True - True - True + True + True True True liststore1 - False - 0 - False + False + 0 + False @@ -203,8 +203,8 @@ - 0 - 3 + 0 + 3 @@ -215,23 +215,23 @@ - + True - False - 6 + False + 6 - + True - False + False True True - 12 + 12 True - False + False True @@ -240,17 +240,17 @@ - 0 - 0 + 0 + 0 True - True + True True - True - 50 + True + 50 True @@ -259,15 +259,15 @@ - 1 - 0 + 1 + 0 True - True - True + True + True @@ -278,28 +278,28 @@ - 2 - 0 + 2 + 0 - 0 - 1 + 0 + 1 - + True - False + False True True - 12 + 12 True - False + False True @@ -308,17 +308,17 @@ - 0 - 0 + 0 + 0 True - True + True True - True - 50 + True + 50 True @@ -327,15 +327,15 @@ - 1 - 0 + 1 + 0 True - True - True + True + True @@ -346,30 +346,30 @@ - 2 - 0 + 2 + 0 - 0 - 3 + 0 + 3 True - False + False True 12 - center + center _Add True - True - True - True + True + True + True True @@ -387,9 +387,9 @@ _Delete True - True - True - True + True + True + True True @@ -405,36 +405,36 @@ - 0 - 4 + 0 + 4 True - False + False _Source data ranges: - True - lbdataarea + True + lbdataarea 0 - 0 - 0 + 0 + 0 True - False + False Copy results _to: - True - lbdestarea + True + lbdestarea 0 - 0 - 2 + 0 + 2 @@ -447,45 +447,45 @@ True - True + True True True - True + True True - False - 6 + False + 6 True True 12 True - False + False True True - 0 - none + 0 + none - + True - False - True - True - 6 + False 12 6 + True + True + 6 _Row labels True - True - False + True + False True - True - True + True + True Uses the row labels to arrange the consolidated data. @@ -493,19 +493,19 @@ - 0 - 0 + 0 + 0 C_olumn labels True - True - False + True + False True - True - True + True + True Uses the column labels to arrange the consolidated data. @@ -513,8 +513,8 @@ - 0 - 1 + 0 + 1 @@ -522,7 +522,7 @@ True - False + False Consolidate by @@ -539,25 +539,24 @@ True - False + False True True - 0 - none + 0 + none _Link to source data - start - True - True True - True - False - True - True - True + True + False + start 12 6 + True + True + True + True Links the data in the consolidation range to the source data, and automatically updates the results of the consolidation when the source data is changed. @@ -568,7 +567,7 @@ True - False + False Options @@ -587,7 +586,7 @@ True - False + False Options @@ -610,9 +609,6 @@ cancel help - - - Combines data from one or more independent cell ranges and calculates a new range using the function that you specify. diff --git a/sc/uiconfig/scalc/ui/correlationdialog.ui b/sc/uiconfig/scalc/ui/correlationdialog.ui index 97fc967e6624..db899009b016 100644 --- a/sc/uiconfig/scalc/ui/correlationdialog.ui +++ b/sc/uiconfig/scalc/ui/correlationdialog.ui @@ -1,32 +1,32 @@ - + - False - 6 + False + 6 Correlation False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -39,9 +39,9 @@ _Cancel True - True - True - True + True + True + True True @@ -54,8 +54,8 @@ _Help True - True - True + True + True True @@ -69,104 +69,104 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 - 6 6 + 6 + 6 + 12 True - False + False Input range: - True - input-range-edit + True + input-range-edit 0 - 0 - 0 - - - - - True - False - Results to: - True - output-range-edit - 0 - - - 0 - 1 + 0 + 0 True - True + True center True - True + True + 30 True - 30 - 1 - 0 - - - - - True - True - center - True - True - True - 30 - - - 1 - 1 + 1 + 0 True - True - True + True + True - 2 - 0 + 2 + 0 + + + + + True + False + Results to: + True + output-range-edit + 0 + + + 0 + 1 + + + + + True + True + center + True + True + 30 + True + + + 1 + 1 True - True - True + True + True - 2 - 1 + 2 + 1 @@ -174,7 +174,7 @@ True - False + False Data @@ -191,48 +191,47 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 - 6 - 6 12 + 6 + 6 + 12 Columns True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 Rows True - True - False - True - True + True + False + True + True groupedby-columns-radio - 1 - 0 + 1 + 0 @@ -240,7 +239,7 @@ True - False + False Grouped by @@ -261,9 +260,6 @@ cancel help - - - Calculates the correlation of two sets of numeric data. diff --git a/sc/uiconfig/scalc/ui/covariancedialog.ui b/sc/uiconfig/scalc/ui/covariancedialog.ui index 2d81a744bd49..febc84adbc77 100644 --- a/sc/uiconfig/scalc/ui/covariancedialog.ui +++ b/sc/uiconfig/scalc/ui/covariancedialog.ui @@ -1,32 +1,32 @@ - + - False - 6 + False + 6 Covariance False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -39,9 +39,9 @@ _Cancel True - True - True - True + True + True + True True @@ -54,8 +54,8 @@ _Help True - True - True + True + True True @@ -69,104 +69,104 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 6 6 + 6 + 12 True - False + False Input range: - True - input-range-edit + True + input-range-edit 0 - 0 - 0 + 0 + 0 True - True + True center True - True + True + 30 True - 30 - 1 - 0 + 1 + 0 True - True - True + True + True - 2 - 0 + 2 + 0 True - False + False Results to: - True - output-range-edit + True + output-range-edit 0 - 0 - 1 + 0 + 1 True - True + True center True - True + True + 30 True - 30 - 1 - 1 + 1 + 1 True - True - True + True + True - 2 - 1 + 2 + 1 @@ -174,7 +174,7 @@ True - False + False Data @@ -191,48 +191,48 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 Columns True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 Rows True - True - False - True - True + True + False + True + True groupedby-columns-radio - 1 - 0 + 1 + 0 @@ -240,7 +240,7 @@ True - False + False Grouped by @@ -261,9 +261,6 @@ cancel help - - - Calculates the covariance of two sets of numeric data. diff --git a/sc/uiconfig/scalc/ui/createnamesdialog.ui b/sc/uiconfig/scalc/ui/createnamesdialog.ui index 387c251ce8c7..37024512ac11 100644 --- a/sc/uiconfig/scalc/ui/createnamesdialog.ui +++ b/sc/uiconfig/scalc/ui/createnamesdialog.ui @@ -1,33 +1,33 @@ - + - False - 6 + False + 6 Create Names False True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -40,8 +40,8 @@ _Cancel True - True - True + True + True True @@ -54,8 +54,8 @@ _Help True - True - True + True + True 6 True @@ -70,32 +70,32 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none True - False - vertical - 6 + False 12 6 + vertical + 6 _Top row True - True - False - True - True + True + False + True + True Creates the range names from the header row of the selected range. @@ -112,10 +112,10 @@ _Left column True - True - False - True - True + True + False + True + True Creates the range names from the entries in the first column of the selected sheet range. @@ -132,10 +132,10 @@ _Bottom row True - True - False - True - True + True + False + True + True Creates the range names from the entries in the last row of the selected sheet range. @@ -152,10 +152,10 @@ _Right column True - True - False - True - True + True + False + True + True Creates the range names from the entries in the last column of the selected sheet range. @@ -173,7 +173,7 @@ True - False + False Create Names From 0.5 @@ -195,9 +195,6 @@ cancel help - - - Allows you to automatically name multiple cell ranges. diff --git a/sc/uiconfig/scalc/ui/datafielddialog.ui b/sc/uiconfig/scalc/ui/datafielddialog.ui index 8b40cafa9bd8..d665d7d00313 100644 --- a/sc/uiconfig/scalc/ui/datafielddialog.ui +++ b/sc/uiconfig/scalc/ui/datafielddialog.ui @@ -1,5 +1,5 @@ - + @@ -11,30 +11,30 @@ - False - 6 + False + 6 Data Field False - dialog + dialog - False + False True True vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -47,9 +47,9 @@ _Cancel True - True - True - True + True + True + True True @@ -62,8 +62,8 @@ _Help True - True - True + True + True True @@ -77,54 +77,54 @@ False True - end + end 0 - + True - False + False True True - 12 + 12 True - False + False True True - 0 - none + 0 + none True - False - True - True - 6 + False 12 6 + True + True + 6 True - True + True True True - in + in True - True - True + True + True True True liststore2 - False - 1 - False + False + 1 + False @@ -149,8 +149,8 @@ - 0 - 0 + 0 + 0 @@ -158,7 +158,7 @@ True - False + False Function @@ -167,18 +167,18 @@ - 0 - 0 + 0 + 0 Show it_ems without data True - True - False - True - True + True + False + True + True Includes empty columns and rows in the results table. @@ -186,109 +186,109 @@ - 0 - 1 + 0 + 1 - + True - False - 12 + False + 12 True - False + False Name: 0 - 0 - 0 + 0 + 0 True - False + False 0 - 1 - 0 + 1 + 0 - 0 - 2 + 0 + 2 True - True - True + True + True - + - True True - False - 6 - 12 + False 12 6 + True + 6 + 12 True - False + False _Type: - True - type + True + type end 0 - 0 - 0 + 0 + 0 True - False + False _Base field: - True - basefield + True + basefield end 0 - 0 - 1 + 0 + 1 True - False + False Ba_se item: - True - baseitem + True + baseitem end 0 - 0 - 2 + 0 + 2 True - False + False Normal Difference from @@ -302,19 +302,19 @@ - Select the type of calculating of the displayed value for the data field. + Select the type of calculation for the displayed value for the data field. - 1 - 0 + 1 + 0 True - False + False Select the field from which the respective value is taken as base for the calculation. @@ -322,14 +322,14 @@ - 1 - 1 + 1 + 1 True - False + False - previous item - - next item - @@ -341,8 +341,8 @@ - 1 - 2 + 1 + 2 @@ -350,7 +350,7 @@ True - False + False Displayed Value @@ -361,8 +361,8 @@ - 0 - 3 + 0 + 3 @@ -379,8 +379,5 @@ cancel help - - - diff --git a/sc/uiconfig/scalc/ui/datafieldoptionsdialog.ui b/sc/uiconfig/scalc/ui/datafieldoptionsdialog.ui index 91618a2e2ff8..f61acb40098b 100644 --- a/sc/uiconfig/scalc/ui/datafieldoptionsdialog.ui +++ b/sc/uiconfig/scalc/ui/datafieldoptionsdialog.ui @@ -1,13 +1,13 @@ - + 1 999 1 - 1 - 10 + 1 + 10 @@ -24,31 +24,31 @@ - False - 6 + False + 6 Data Field Options False True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -61,8 +61,8 @@ _Cancel True - True - True + True + True True @@ -75,8 +75,8 @@ _Help True - True - True + True + True True @@ -90,99 +90,39 @@ False True - end + end 0 - + True - False + False True True - 12 + 12 True - False + False True - 0 - none + 0 + none - + True - False - True - 6 - 12 + False 12 6 - - - _Ascending - True - True - False - True - True - True - - - Sorts the values from the lowest value to the highest value. If the selected field is the field for which the dialog was opened, the items are sorted by name. If a data field was selected, the items are sorted by the resultant value of the selected data field. - - - - - 1 - 0 - - - - - _Descending - True - True - False - True - True - ascending - - - Sorts the values descending from the highest value to the lowest value. If the selected field is the field for which the dialog was opened, the items are sorted by name. If a data field was selected, the items are sorted by the resultant value of the selected data field. - - - - - 1 - 1 - - - - - _Manual - True - True - False - True - True - ascending - - - Sorts values alphabetically. - - - - - 1 - 2 - - + True + 6 + 12 True - False + False center True @@ -193,11 +133,71 @@ - 0 - 0 + 0 + 0 2 + + + _Ascending + True + True + False + True + True + True + + + Sorts the values from the lowest value to the highest value. If the selected field is the field for which the dialog was opened, the items are sorted by name. If a data field was selected, the items are sorted by the resultant value of the selected data field. + + + + + 1 + 0 + + + + + _Descending + True + True + False + True + True + ascending + + + Sorts the values descending from the highest value to the lowest value. If the selected field is the field for which the dialog was opened, the items are sorted by name. If a data field was selected, the items are sorted by the resultant value of the selected data field. + + + + + 1 + 1 + + + + + _Manual + True + True + False + True + True + ascending + + + Sorts values alphabetically. + + + + + 1 + 2 + + @@ -206,7 +206,7 @@ True - False + False Sort by @@ -215,78 +215,43 @@ - 0 - 0 + 0 + 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 6 - - - _Repeat item labels - True - True - False - True - True - - - 0 - 2 - 2 - - - - - _Empty line after each item - True - True - False - True - True - - - Adds an empty row after the data for each item in the pivot table. - - - - - 0 - 1 - 2 - - + 6 + 12 True - False + False _Layout: - True - layout + True + layout 0 - 0 - 0 + 0 + 0 True - False + False True Tabular layout @@ -301,8 +266,43 @@ - 1 - 0 + 1 + 0 + + + + + _Empty line after each item + True + True + False + True + True + + + Adds an empty row after the data for each item in the pivot table. + + + + + 0 + 1 + 2 + + + + + _Repeat item labels + True + True + False + True + True + + + 0 + 2 + 2 @@ -310,7 +310,7 @@ True - False + False Display Options @@ -319,33 +319,33 @@ - 0 - 1 + 0 + 1 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 6 + 6 + 12 _Show: True - True - False - True - True + True + False + True + True @@ -356,67 +356,25 @@ - 0 - 0 + 0 + 0 - - True - False - _From: - True - from - 0 - - - 0 - 1 - - - - - True - False - _Using field: - True - using - 0 - - - 0 - 2 - - - - + True - False - 12 - - - True - False - items - True - layout - 0 - - - 1 - 0 - - + False + 12 True - True + True + True adjustment1 - True Enter the maximum number of items that you want to show automatically. @@ -424,20 +382,48 @@ - 0 - 0 + 0 + 0 + + + + + True + False + items + True + layout + 0 + + + 1 + 0 - 1 - 0 + 1 + 0 + + + + + True + False + _From: + True + from + 0 + + + 0 + 1 True - False + False Top Bottom @@ -449,14 +435,28 @@ - 1 - 1 + 1 + 1 + + + + + True + False + _Using field: + True + using + 0 + + + 0 + 2 True - False + False Select the data field that you want to sort the data by. @@ -464,8 +464,8 @@ - 1 - 2 + 1 + 2 @@ -473,7 +473,7 @@ True - False + False Show Automatically @@ -482,38 +482,38 @@ - 0 - 2 + 0 + 2 True - False + False True True - 0 - none + 0 + none True - True - True - True - in + True 12 6 + True + True + in True - True - True + True + True True True liststore2 - False - 1 - False + False + 1 + False @@ -529,12 +529,6 @@ 0 - - - - - True - 6 @@ -555,7 +549,7 @@ True - False + False Hide Items @@ -564,20 +558,34 @@ - 0 - 3 + 0 + 3 - + True - False - 12 + False + 12 + + + True + False + Hierarch_y: + True + hierarchy + 0 + + + 0 + 0 + + True - False + False Select the hierarchy that you want to use. The pivot table must be based on an external source data that contains data hierarchies. @@ -585,28 +593,14 @@ - 1 - 0 - - - - - True - False - Hierarch_y: - True - hierarchy - 0 - - - 0 - 0 + 1 + 0 - 0 - 4 + 0 + 4 @@ -623,9 +617,6 @@ cancel help - - - diff --git a/sc/uiconfig/scalc/ui/definedatabaserangedialog.ui b/sc/uiconfig/scalc/ui/definedatabaserangedialog.ui index af54e0d1072f..56398661499b 100644 --- a/sc/uiconfig/scalc/ui/definedatabaserangedialog.ui +++ b/sc/uiconfig/scalc/ui/definedatabaserangedialog.ui @@ -173,6 +173,7 @@ True + Name Enter a name for the database range that you want to define, or select an existing name from the list. diff --git a/sc/uiconfig/scalc/ui/descriptivestatisticsdialog.ui b/sc/uiconfig/scalc/ui/descriptivestatisticsdialog.ui index 0f802faa1db4..482024ff0849 100644 --- a/sc/uiconfig/scalc/ui/descriptivestatisticsdialog.ui +++ b/sc/uiconfig/scalc/ui/descriptivestatisticsdialog.ui @@ -1,32 +1,32 @@ - + - False - 6 + False + 6 Descriptive Statistics False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -39,9 +39,9 @@ _Cancel True - True - True - True + True + True + True True @@ -54,8 +54,8 @@ _Help True - True - True + True + True True @@ -69,105 +69,105 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 True - False + False Input range: - True - input-range-edit + True + input-range-edit 0 - 0 - 0 + 0 + 0 True - True + True center True - True + True + 30 True - 30 - 1 - 0 + 1 + 0 True - True - True + True + True - 2 - 0 + 2 + 0 True - False + False Results to: - True - output-range-edit + True + output-range-edit 0 - 0 - 1 + 0 + 1 True - True + True center True - True + True + 30 True - 30 - 1 - 1 + 1 + 1 True - True - True + True + True - 2 - 1 + 2 + 1 @@ -175,7 +175,7 @@ True - False + False Data @@ -192,48 +192,48 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 _Columns True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 _Rows True - True - False - True - True + True + False + True + True groupedby-columns-radio - 1 - 0 + 1 + 0 @@ -241,7 +241,7 @@ True - False + False Grouped by @@ -262,9 +262,6 @@ cancel help - - - Fill a table in the spreadsheet with the main statistical properties of the data set. diff --git a/sc/uiconfig/scalc/ui/drawtemplatedialog.ui b/sc/uiconfig/scalc/ui/drawtemplatedialog.ui index e06041312832..b60d33c25ecf 100644 --- a/sc/uiconfig/scalc/ui/drawtemplatedialog.ui +++ b/sc/uiconfig/scalc/ui/drawtemplatedialog.ui @@ -108,7 +108,6 @@ True left True - left False @@ -119,7 +118,7 @@ - reset + reset standard ok cancel diff --git a/sc/uiconfig/scalc/ui/duplicaterecordsdlg.ui b/sc/uiconfig/scalc/ui/duplicaterecordsdlg.ui index a5ebde45f059..8b37f4962ec7 100644 --- a/sc/uiconfig/scalc/ui/duplicaterecordsdlg.ui +++ b/sc/uiconfig/scalc/ui/duplicaterecordsdlg.ui @@ -168,13 +168,6 @@ 0 - - - - - True - 6 - Row/Column diff --git a/sc/uiconfig/scalc/ui/erroralerttabpage.ui b/sc/uiconfig/scalc/ui/erroralerttabpage.ui index 8915b71da84d..514b974564f4 100644 --- a/sc/uiconfig/scalc/ui/erroralerttabpage.ui +++ b/sc/uiconfig/scalc/ui/erroralerttabpage.ui @@ -57,6 +57,47 @@ 0 + + + True + False + True + + Stop + Warning + Information + Macro + Reject silently + + + + Select the action that you want to occur when invalid data is entered in a cell. + + + + + 1 + 0 + + + + + _Browse... + True + True + True + True + + + Opens the Macro dialog where you can select the macro that is executed when invalid data is entered in a cell. The macro is executed after the error message is displayed. + + + + + 2 + 0 + + True @@ -72,31 +113,6 @@ 1 - - - True - True - True - in - - - True - True - True - - - Enter the message that you want to display when invalid data is entered in a cell. - - - - - - - 1 - 2 - 2 - - True @@ -126,44 +142,29 @@ - - _Browse... + True True - True - True - - - Opens the Macro dialog where you can select the macro that is executed when invalid data is entered in a cell. The macro is executed after the error message is displayed. - - - - - 2 - 0 - - - - - True - False - True - - Stop - Warning - Information - Macro - Reject silently - - - - Select the action that you want to occur when invalid data is entered in a cell. + True + in + + + True + True + True + False + + + Enter the message that you want to display when invalid data is entered in a cell. + + 1 - 0 + 2 + 2 diff --git a/sc/uiconfig/scalc/ui/exponentialsmoothingdialog.ui b/sc/uiconfig/scalc/ui/exponentialsmoothingdialog.ui index acef132f4444..f1da8d46eaa4 100644 --- a/sc/uiconfig/scalc/ui/exponentialsmoothingdialog.ui +++ b/sc/uiconfig/scalc/ui/exponentialsmoothingdialog.ui @@ -1,38 +1,38 @@ - + 1 - 0.2 - 0.05 - 0.1 + 0.20 + 0.05 + 0.10 - False - 6 + False + 6 Exponential Smoothing False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -45,9 +45,9 @@ _Cancel True - True - True - True + True + True + True True @@ -60,8 +60,8 @@ _Help True - True - True + True + True True @@ -75,105 +75,105 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 True - False + False Input range: - True - input-range-edit + True + input-range-edit 0 - 0 - 0 + 0 + 0 True - True + True center True - True + True + 30 True - 30 - 1 - 0 + 1 + 0 True - True - True + True + True - 2 - 0 + 2 + 0 True - False + False Results to: - True - output-range-edit + True + output-range-edit 0 - 0 - 1 + 0 + 1 True - True + True center True - True + True + 30 True - 30 - 1 - 1 + 1 + 1 True - True - True + True + True - 2 - 1 + 2 + 1 @@ -181,7 +181,7 @@ True - False + False Data @@ -198,48 +198,48 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 Columns True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 Rows True - True - False - True - True + True + False + True + True groupedby-columns-radio - 1 - 0 + 1 + 0 @@ -247,7 +247,7 @@ True - False + False Grouped by @@ -264,48 +264,48 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 True - False + False Smoothing factor: - True - smoothing-factor-spin + True + smoothing-factor-spin 0 - 0 - 0 + 0 + 0 True - True - True + True + True 0.20 + True smoothing-factor-adjustment 2 - True 0.20000000298023224 - 1 - 0 + 1 + 0 @@ -313,7 +313,7 @@ True - False + False Parameters @@ -334,9 +334,6 @@ cancel help - - - Results in a smoothed data series diff --git a/sc/uiconfig/scalc/ui/externaldata.ui b/sc/uiconfig/scalc/ui/externaldata.ui index 4a116c2e6450..63320db88200 100644 --- a/sc/uiconfig/scalc/ui/externaldata.ui +++ b/sc/uiconfig/scalc/ui/externaldata.ui @@ -1,13 +1,13 @@ - + 1 99999 60 - 1 - 10 + 1 + 10 @@ -18,30 +18,30 @@ - False - 6 + False + 6 External Data True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -54,8 +54,8 @@ _Cancel True - True - True + True + True True @@ -68,8 +68,8 @@ _Help True - True - True + True + True True @@ -83,14 +83,14 @@ False True - end + end 0 True - False + False True True vertical @@ -98,37 +98,37 @@ True - False + False True - 0 - none + 0 + none True - False + False + 12 + 6 True vertical 6 - 12 - 6 True - False + False True 12 True - False - Enter the URL of the source document in the local file system or Internet here. - True + False + Enter the URL of the source document in the local file system or Internet here. + True True - True + True + True True - True @@ -147,9 +147,9 @@ _Browse... True - True - True - True + True + True + True Open a file dialog to locate the file containing the data you want to insert. @@ -174,9 +174,9 @@ True - False + False URL of _External Data Source - True + True @@ -192,38 +192,38 @@ True - False + False True True - 0 - none + 0 + none True - False + False + 12 + 6 True True vertical 6 - 12 - 6 True - True + True True True - in + in True - True + True True liststore1 - False - False - 0 - False + False + False + 0 + False @@ -254,16 +254,16 @@ True - False + False 12 _Update every: True - True - False - True - True + True + False + True + True @@ -282,18 +282,18 @@ True - False + False 6 True - True - True + True + True + True adjustment1 - True Enter the number of seconds to wait before the external data are reloaded into the current document. @@ -309,9 +309,9 @@ True - False + False _seconds - True + True False @@ -338,9 +338,9 @@ True - False + False _Available Tables/Ranges - True + True 0.5 @@ -368,9 +368,6 @@ cancel help - - - Inserts data from an HTML, Calc, CSV or Excel file into the current sheet as a link. The data must be located within a named range. diff --git a/sc/uiconfig/scalc/ui/filldlg.ui b/sc/uiconfig/scalc/ui/filldlg.ui index d4b06fd1be0d..9bbba2d7b5b7 100644 --- a/sc/uiconfig/scalc/ui/filldlg.ui +++ b/sc/uiconfig/scalc/ui/filldlg.ui @@ -1,32 +1,32 @@ - + - False - 6 + False + 6 Fill Series True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -39,8 +39,8 @@ _Cancel True - True - True + True + True True @@ -53,8 +53,8 @@ _Help True - True - True + True + True True @@ -68,42 +68,42 @@ False True - end + end 0 - + True - False - 12 - 12 + False + 12 + 12 True - False + False True - 0 - none + 0 + none True - False + False + 12 + 6 True vertical 6 - 12 - 6 _Down True - True - False - True + True + False + True True - True + True Creates a downward series in the selected cell range for the column using the defined increment to the end value. @@ -120,10 +120,10 @@ _Right True - True - False - True - True + True + False + True + True down @@ -141,10 +141,10 @@ _Up True - True - False - True - True + True + False + True + True down @@ -162,10 +162,10 @@ _Left True - True - False - True - True + True + False + True + True down @@ -184,7 +184,7 @@ True - False + False True Direction @@ -194,35 +194,35 @@ - 0 - 0 + 0 + 0 True - False + False True - 0 - none + 0 + none True - False + False + 12 + 6 True vertical 6 - 12 - 6 Li_near True - True - False - True + True + False + True True - True + True Creates a linear number series using the defined increment and end value. @@ -239,10 +239,10 @@ _Growth True - True - False - True - True + True + False + True + True linear @@ -260,10 +260,10 @@ Da_te True - True - False - True - True + True + False + True + True linear @@ -281,10 +281,10 @@ _AutoFill True - True - False - True - True + True + False + True + True linear @@ -303,7 +303,7 @@ True - False + False True Series Type @@ -313,35 +313,35 @@ - 1 - 0 + 1 + 0 True - False + False True - 0 - none + 0 + none True - False + False + 12 + 6 True vertical 6 - 12 - 6 Da_y True - True - False - True + True + False + True True - True + True Use the Date series type and this option to create a series using all seven days of the week. Unit of Increment is day. @@ -358,10 +358,10 @@ _Weekday True - True - False - True - True + True + False + True + True day @@ -379,10 +379,10 @@ _Month True - True - False - True - True + True + False + True + True day @@ -400,10 +400,10 @@ Y_ear True - True - False - True - True + True + False + True + True day @@ -422,7 +422,7 @@ True - False + False True Time Unit @@ -432,64 +432,64 @@ - 2 - 0 + 2 + 0 - + True - False - 6 - 12 + False + 6 + 12 True - False + False _Start value: - True - startValue + True + startValue 0 - 0 - 0 + 0 + 0 True - False + False End _value: - True - endValue + True + endValue 0 - 0 - 1 + 0 + 1 True - False + False In_crement: - True - increment + True + increment 0 - 0 - 2 + 0 + 2 True - True - True + True + True True @@ -498,15 +498,15 @@ - 1 - 0 + 1 + 0 True - True - True + True + True True @@ -515,15 +515,15 @@ - 1 - 1 + 1 + 1 True - True - True + True + True True @@ -532,14 +532,14 @@ - 1 - 2 + 1 + 2 - 0 - 1 + 0 + 1 2 @@ -560,9 +560,6 @@ cancel help - - - Automatically generate series with the options in this dialog. Determine direction, increment, time unit and series type. diff --git a/sc/uiconfig/scalc/ui/footerdialog.ui b/sc/uiconfig/scalc/ui/footerdialog.ui index dc4dace4dc04..a085ad7f0bee 100644 --- a/sc/uiconfig/scalc/ui/footerdialog.ui +++ b/sc/uiconfig/scalc/ui/footerdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/formatcellsdialog.ui b/sc/uiconfig/scalc/ui/formatcellsdialog.ui index 82ea6c0029a9..623cb3fed5ad 100644 --- a/sc/uiconfig/scalc/ui/formatcellsdialog.ui +++ b/sc/uiconfig/scalc/ui/formatcellsdialog.ui @@ -104,7 +104,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/formulacalculationoptions.ui b/sc/uiconfig/scalc/ui/formulacalculationoptions.ui index 100acd89b14b..1361caa91dde 100644 --- a/sc/uiconfig/scalc/ui/formulacalculationoptions.ui +++ b/sc/uiconfig/scalc/ui/formulacalculationoptions.ui @@ -1,31 +1,31 @@ - + - False + False True - 6 + 6 Detailed Calculation Settings True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _Help True - True - True + True + True True @@ -39,10 +39,10 @@ _OK True - True - True - True - True + True + True + True + True True @@ -55,8 +55,8 @@ _Cancel True - True - True + True + True True @@ -69,71 +69,87 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 6 + 6 + 12 True - False + False Conversion from text to number: - True - comboConversion + True + comboConversion 0 - 0 - 0 + 0 + 0 + + + + + True + False + + Generate #VALUE! error + Treat as zero + Convert only if unambiguous + Convert also locale dependent + + + + 1 + 0 Treat _empty string as zero True - True - False - True - True + True + False + True + True - 0 - 1 + 0 + 1 2 True - False + False Reference syntax for string reference: - True - comboSyntaxRef + True + comboSyntaxRef - 0 - 2 + 0 + 2 True - False + False Use formula syntax Calc A1 @@ -143,38 +159,22 @@ - 1 - 2 - - - - - True - False - - Generate #VALUE! error - Treat as zero - Convert only if unambiguous - Convert also locale dependent - - - - 1 - 0 + 1 + 2 Apply those settings to current document only True - True - False - True - True + True + False + True + True - 0 - 3 + 0 + 3 2 @@ -183,7 +183,7 @@ True - False + False Contents to Numbers @@ -204,9 +204,6 @@ ok cancel - - - Sets the rules for conversion from strings values to numeric values, string values to cell references, and strings values to date and time values. This affects built-in functions such as INDIRECT that takes a reference as a string value or date and time functions that takes arguments as string values in local or ISO 8601 formats. diff --git a/sc/uiconfig/scalc/ui/goalseekdlg.ui b/sc/uiconfig/scalc/ui/goalseekdlg.ui index 12456f09a8d0..d4cc7b439aca 100644 --- a/sc/uiconfig/scalc/ui/goalseekdlg.ui +++ b/sc/uiconfig/scalc/ui/goalseekdlg.ui @@ -1,29 +1,29 @@ - + - False - 6 + False + 6 Goal Seek - -1 - -1 - dialog + -1 + -1 + dialog - False + False vertical 12 - False - end + False + end _Cancel True - True - True + True + True True @@ -41,10 +41,10 @@ _OK True - True - True - True - True + True + True + True + True True @@ -62,8 +62,8 @@ _Help True - True - True + True + True True @@ -77,73 +77,47 @@ False True - end + end 0 True - False + False True - 0 - none + 0 + none - + True - False - True - 6 - 12 + False 12 6 + True + 6 + 12 True - False + False _Formula cell: - True - formulaedit + True + formulaedit - 0 - 0 - - - - - True - False - Target _value: - True - target - - - 0 - 1 - - - - - True - False - Variable _cell: - True - varedit - - - 0 - 2 + 0 + 0 True - True + True center True - True + True True @@ -152,17 +126,46 @@ - 1 - 0 + 1 + 0 + + + + + True + False + False + + + Click the Shrink icon to reduce the dialog to the size of the input field. It is then easier to mark the required reference in the sheet. The icons then automatically convert to the Maximize icon. Click it to restore the dialog to its original size. + + + + + 2 + 0 + + + + + True + False + Target _value: + True + target + + + 0 + 1 True - True + True center True - True + True True @@ -171,17 +174,30 @@ - 1 - 1 + 1 + 1 + + + + + True + False + Variable _cell: + True + varedit + + + 0 + 2 True - True + True center True - True + True True @@ -190,31 +206,15 @@ - 1 - 2 - - - - - True - False - False - - - Click the Shrink icon to reduce the dialog to the size of the input field. It is then easier to mark the required reference in the sheet. The icons then automatically convert to the Maximize icon. Click it to restore the dialog to its original size. - - - - - 2 - 0 + 1 + 2 True - False - False + False + False Click the Shrink icon to reduce the dialog to the size of the input field. It is then easier to mark the required reference in the sheet. The icons then automatically convert to the Maximize icon. Click it to restore the dialog to its original size. @@ -222,8 +222,8 @@ - 2 - 2 + 2 + 2 @@ -234,7 +234,7 @@ True - False + False Default Settings @@ -255,9 +255,6 @@ ok help - - - Opens a dialog where you can solve an equation with a variable. diff --git a/sc/uiconfig/scalc/ui/gotosheetdialog.ui b/sc/uiconfig/scalc/ui/gotosheetdialog.ui index c8c605eed0c6..923743250a66 100644 --- a/sc/uiconfig/scalc/ui/gotosheetdialog.ui +++ b/sc/uiconfig/scalc/ui/gotosheetdialog.ui @@ -97,6 +97,7 @@ True + Sheet Name Type some letters of sheet name to find it. diff --git a/sc/uiconfig/scalc/ui/groupbydate.ui b/sc/uiconfig/scalc/ui/groupbydate.ui index a73cbf06235f..a98d2c8d68d9 100644 --- a/sc/uiconfig/scalc/ui/groupbydate.ui +++ b/sc/uiconfig/scalc/ui/groupbydate.ui @@ -385,12 +385,6 @@ 0 - - - - - True - 6 diff --git a/sc/uiconfig/scalc/ui/headerdialog.ui b/sc/uiconfig/scalc/ui/headerdialog.ui index 950c8246424a..0b140c011fa6 100644 --- a/sc/uiconfig/scalc/ui/headerdialog.ui +++ b/sc/uiconfig/scalc/ui/headerdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/headerfootercontent.ui b/sc/uiconfig/scalc/ui/headerfootercontent.ui index 61d86b01440f..f73127301021 100644 --- a/sc/uiconfig/scalc/ui/headerfootercontent.ui +++ b/sc/uiconfig/scalc/ui/headerfootercontent.ui @@ -87,12 +87,26 @@ vertical 6 - + True False 12 6 + + + Enable + True + True + False + start + True + + + 0 + 0 + + True @@ -104,7 +118,7 @@ - 1 + 2 0 @@ -117,7 +131,7 @@ 0 - 0 + 1 0 @@ -159,6 +173,7 @@ True + True False @@ -183,12 +198,13 @@ True + True digits - Selects the font height. + Selects the font height. diff --git a/sc/uiconfig/scalc/ui/headerfooterdialog.ui b/sc/uiconfig/scalc/ui/headerfooterdialog.ui index 3900de52d0ec..8c85a8aa28e6 100644 --- a/sc/uiconfig/scalc/ui/headerfooterdialog.ui +++ b/sc/uiconfig/scalc/ui/headerfooterdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/imoptdialog.ui b/sc/uiconfig/scalc/ui/imoptdialog.ui index 9d08268a2562..91c4989c1bd2 100644 --- a/sc/uiconfig/scalc/ui/imoptdialog.ui +++ b/sc/uiconfig/scalc/ui/imoptdialog.ui @@ -99,10 +99,10 @@ 6 12 - + True False - _Character set: + _Encoding: True 0 @@ -118,13 +118,13 @@ False True - + False True True - - Specifies the character set for text export. + + Specifies the encoding for text export. @@ -142,7 +142,7 @@ never in - + True True True @@ -168,8 +168,8 @@ - - Select the character set from the options used for import/export. + + Select the encoding from the options used for import/export. diff --git a/sc/uiconfig/scalc/ui/insertname.ui b/sc/uiconfig/scalc/ui/insertname.ui index 5afaa0d0b2ca..ce125e733d46 100644 --- a/sc/uiconfig/scalc/ui/insertname.ui +++ b/sc/uiconfig/scalc/ui/insertname.ui @@ -1,5 +1,5 @@ - + @@ -15,28 +15,28 @@ - False - 6 + False + 6 Paste Names True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _Help True - True - True + True + True True @@ -50,9 +50,9 @@ _Paste All True - True - True - True + True + True + True Inserts a list of all named areas and the corresponding cell references at the current cursor position. @@ -69,11 +69,11 @@ _Paste True - True - True - True - True - True + True + True + True + True + True Inserts the selected named area and the corresponding cell reference at the current cursor position. @@ -83,7 +83,7 @@ False True - end + end 2 @@ -91,14 +91,14 @@ _Close True - True - True + True + True True False True - end + end 3 @@ -106,27 +106,27 @@ False True - end + end 0 True - True + True True True - in + in True - True - True + True + True True True liststore3 - 0 - False + 0 + False @@ -191,9 +191,6 @@ paste close - - - Inserts a defined named cell range at the current cursor's position. diff --git a/sc/uiconfig/scalc/ui/leftfooterdialog.ui b/sc/uiconfig/scalc/ui/leftfooterdialog.ui index 4a8fdcc2ea37..869cc663a7de 100644 --- a/sc/uiconfig/scalc/ui/leftfooterdialog.ui +++ b/sc/uiconfig/scalc/ui/leftfooterdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/leftheaderdialog.ui b/sc/uiconfig/scalc/ui/leftheaderdialog.ui index bc650d82fbb4..5be948f273d5 100644 --- a/sc/uiconfig/scalc/ui/leftheaderdialog.ui +++ b/sc/uiconfig/scalc/ui/leftheaderdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/managenamesdialog.ui b/sc/uiconfig/scalc/ui/managenamesdialog.ui index 1321417c25a9..0f341f72eb4f 100644 --- a/sc/uiconfig/scalc/ui/managenamesdialog.ui +++ b/sc/uiconfig/scalc/ui/managenamesdialog.ui @@ -526,7 +526,4 @@ - - column - diff --git a/sc/uiconfig/scalc/ui/movingaveragedialog.ui b/sc/uiconfig/scalc/ui/movingaveragedialog.ui index b7ed2f3810d8..29ddd0b2df9b 100644 --- a/sc/uiconfig/scalc/ui/movingaveragedialog.ui +++ b/sc/uiconfig/scalc/ui/movingaveragedialog.ui @@ -1,39 +1,39 @@ - + 2 10000 2 - 1 - 1 + 1 + 1 - False - 6 + False + 6 Moving Average False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -46,9 +46,9 @@ _Cancel True - True - True - True + True + True + True True @@ -61,8 +61,8 @@ _Help True - True - True + True + True True @@ -76,119 +76,119 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 6 6 6 - 6 + 6 + 12 True - False + False Input range: - True - input-range-edit + True + input-range-edit 0 - 0 - 0 + 0 + 0 True - True + True center True - True + True + 30 True - 30 - 1 - 0 + 1 + 0 True - True - True + True + True - 2 - 0 + 2 + 0 True - False + False Results to: - True - output-range-edit + True + output-range-edit 0 - 0 - 1 + 0 + 1 True - True + True center True - True + True + 30 True - 30 - 1 - 1 + 1 + 1 True - True - True + True + True - 2 - 1 + 2 + 1 Trim input range to actual data content True - True - False + True + False True - True + True - 0 - 2 + 0 + 2 2 @@ -200,7 +200,7 @@ True - False + False Data @@ -217,48 +217,48 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 6 6 6 - 6 + 6 + 12 Columns True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 Rows True - True - False - True - True + True + False + True + True groupedby-columns-radio - 1 - 0 + 1 + 0 @@ -266,7 +266,7 @@ True - False + False Grouped by @@ -283,46 +283,46 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 6 6 6 - 6 + 6 + 12 True - False + False Interval: - True + True 0 - 0 - 0 + 0 + 0 True - True - True + True + True 2 - interval-adjustment True + interval-adjustment 2 - 1 - 0 + 1 + 0 @@ -330,7 +330,7 @@ True - False + False Parameters @@ -351,9 +351,6 @@ cancel help - - - Calculates the moving average of a time series diff --git a/sc/uiconfig/scalc/ui/namerangesdialog.ui b/sc/uiconfig/scalc/ui/namerangesdialog.ui index 7ea8e175c780..ce85c9094ba3 100644 --- a/sc/uiconfig/scalc/ui/namerangesdialog.ui +++ b/sc/uiconfig/scalc/ui/namerangesdialog.ui @@ -1,5 +1,5 @@ - + @@ -11,32 +11,32 @@ - False - 6 + False + 6 Define Label Range False - 0 - 0 - dialog + 0 + 0 + dialog - False + False True True vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -54,9 +54,9 @@ _Cancel True - True - True - True + True + True + True True @@ -74,9 +74,9 @@ _Help True - True - True - True + True + True + True True @@ -90,41 +90,41 @@ False True - end + end 0 True - False + False True True - 0 - none + 0 + none - + True - False - True - True - 6 + False 12 6 + True + True + 6 - + True - False + False True - 12 + 12 True - True + True True - True + True True @@ -133,15 +133,15 @@ - 0 - 0 + 0 + 0 True - True - True + True + True @@ -152,33 +152,33 @@ - 1 - 0 + 1 + 0 - 0 - 1 + 0 + 1 - + True - False + False True - 12 + 12 Contains _column labels True - True - False + True + False True - True + True True - True + True Includes column labels in the current label range. @@ -186,19 +186,19 @@ - 0 - 0 + 0 + 0 Contains _row labels True - True - False + True + False True - True - True + True + True colhead @@ -207,43 +207,43 @@ - 1 - 0 + 1 + 0 - 0 - 2 + 0 + 2 True - False + False For _data range - True - edassign2 + True + edassign2 0 - 0 - 3 + 0 + 3 - + True - False + False True - 12 + 12 True - True + True True - True + True True @@ -252,15 +252,15 @@ - 0 - 0 + 0 + 0 True - True - True + True + True @@ -271,29 +271,29 @@ - 1 - 0 + 1 + 0 - 0 - 4 + 0 + 4 True - False + False True 12 - center + center _Add True - True - True + True + True True @@ -311,8 +311,8 @@ _Delete True - True - True + True + True True @@ -328,28 +328,28 @@ - 0 - 5 + 0 + 5 True - True + True True True - in + in True - True - True + True + True True True liststore1 - False - 0 - False + False + 0 + False @@ -374,8 +374,8 @@ - 0 - 0 + 0 + 0 @@ -383,7 +383,7 @@ True - False + False Range @@ -404,9 +404,6 @@ cancel help - - - Opens a dialog in which you can define a label range. diff --git a/sc/uiconfig/scalc/ui/notebookbar.ui b/sc/uiconfig/scalc/ui/notebookbar.ui index 3bb1883c7227..57aec5fd2db0 100644 --- a/sc/uiconfig/scalc/ui/notebookbar.ui +++ b/sc/uiconfig/scalc/ui/notebookbar.ui @@ -5,2211 +5,2196 @@ True - False + False True - False - AddonCommand + False + AddonCommand True - False + False True - False - .uno:ExtensionManager + False + .uno:ExtensionManager True - False + False True - False - .uno:DataSort + False + .uno:DataSort True - False - .uno:SortAscending + False + .uno:SortAscending True - False - .uno:SortDescending + False + .uno:SortDescending True - False + False True - False - .uno:DataFilterAutoFilter + False + .uno:DataFilterAutoFilter True - False - .uno:DataFilterStandardFilter + False + .uno:DataFilterStandardFilter True - False - .uno:DataFilterSpecialFilter + False + .uno:DataFilterSpecialFilter True - False - .uno:DataFilterRemoveFilter + False + .uno:DataFilterRemoveFilter True - False - .uno:DataFilterHideAutoFilter + False + .uno:DataFilterHideAutoFilter True - False + False True - False - .uno:DefineDBName + False + .uno:DefineDBName True - False - .uno:SelectDB + False + .uno:SelectDB True - False - .uno:DataAreaRefresh + False + .uno:DataAreaRefresh True - False + False True - False - .uno:InsertPivotTableNBLabel + False + .uno:InsertPivotTableNBLabel True - False - .uno:InsertCalculationNBLabel + False + .uno:InsertCalculationNBLabel True - False - .uno:RecalcPivotTable + False + .uno:RecalcPivotTable True - False - .uno:DeletePivotTable + False + .uno:DeletePivotTable True - False + False True - False - .uno:DataTableMenu + False + .uno:DataTableMenu True - False + False True - False - .uno:FormatSparklineMenu + False + .uno:FormatSparklineMenu True - False + False True - False - .uno:Calculate + False + .uno:Calculate True - False + False True - False - .uno:Validation + False + .uno:Validation True - False - .uno:DataSubTotals + False + .uno:DataSubTotals True - False - .uno:DataForm + False + .uno:DataForm True - False - .uno:DataStreams + False + .uno:DataStreams True - False + False True - False - .uno:TableOperationDialog + False + .uno:TableOperationDialog True - False - .uno:TextToColumns + False + .uno:TextToColumns True - False - .uno:DataConsolidate + False + .uno:DataConsolidate True - False + False True - False - .uno:Group + False + .uno:Group True - False - .uno:Ungroup + False + .uno:Ungroup True - False - .uno:AutoOutline + False + .uno:AutoOutline True - False - .uno:ClearOutline + False + .uno:ClearOutline True - False - .uno:HideDetail + False + .uno:HideDetail True - False - .uno:ShowDetail + False + .uno:ShowDetail True - False + False True - False - .uno:StatisticsMenu + False + .uno:StatisticsMenu True - False + False True - False - .uno:ToggleObjectBezierMode + False + .uno:ToggleObjectBezierMode True - False + False True - False - .uno:ExtrusionTiltDown + False + .uno:ExtrusionTiltDown True - False - .uno:ExtrusionTiltUp + False + .uno:ExtrusionTiltUp True - False - .uno:ExtrusionTiltLeft + False + .uno:ExtrusionTiltLeft True - False - .uno:ExtrusionTiltRight + False + .uno:ExtrusionTiltRight True - False + False True - False - .uno:RenameObject + False + .uno:RenameObject True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - .uno:InsertCurrentDate + False + .uno:InsertCurrentDate True - False - .uno:InsertCurrentTime + False + .uno:InsertCurrentTime True - False + False True - False - .uno:InsertFieldDateVariable + False + .uno:InsertFieldDateVariable True - False - .uno:InsertFieldSheet + False + .uno:InsertFieldSheet True - False - .uno:InsertFieldDocTitle + False + .uno:InsertFieldDocTitle True - False + False True - False - .uno:AddDirect + False + .uno:AddDirect True - False - .uno:RecentFileList + False + .uno:RecentFileList True - False - .uno:CloseDoc + False + .uno:CloseDoc True - False + False True - False - .uno:Save + False + .uno:Save True - False - .uno:SaveAs + False + .uno:SaveAs True - False - .uno:SaveAsRemote + False + .uno:SaveAsRemote True - False - .uno:SaveACopy + False + .uno:SaveACopy True - False + False True - False - .uno:Reload + False + .uno:Reload True - False + False True - False - .uno:ExportTo + False + .uno:ExportTo True - False - .uno:ExportToPDF + False + .uno:ExportToPDF True - False + False True - False - .uno:SendMail + False + .uno:SendMail True - False - .uno:SendMailDocAsPDF + False + .uno:SendMailDocAsPDF True - False - .uno:SendViaBluetooth + False + .uno:SendViaBluetooth True - False + False True - False - .uno:PrintPreview + False + .uno:PrintPreview True - False - .uno:Print + False + .uno:Print - False - False - .uno:PrintDefault + False + .uno:PrintDefault True - False - .uno:PrinterSetup + False + .uno:PrinterSetup True - False + False True - False - .uno:Signature + False + .uno:Signature True - False - .uno:SignPDF + False + .uno:SignPDF True - False - .uno:SetDocumentProperties + False + .uno:SetDocumentProperties True - False + False True - False - .uno:Quit + False + .uno:Quit True - False + False True - False - .uno:Label + False + .uno:Label True - False - .uno:Edit + False + .uno:Edit True - False - .uno:CheckBox + False + .uno:CheckBox True - False - .uno:RadioButton + False + .uno:RadioButton True - False - .uno:ListBox + False + .uno:ListBox True - False - .uno:ComboBox + False + .uno:ComboBox True - False + False True - False - .uno:Pushbutton + False + .uno:Pushbutton True - False - .uno:Imagebutton + False + .uno:Imagebutton True - False + False True - False - .uno:FormattedField + False + .uno:FormattedField True - False + False True - False - .uno:DateField + False + .uno:DateField True - False - .uno:TimeField + False + .uno:TimeField True - False - .uno:NumericField + False + .uno:NumericField True - False - .uno:CurrencyField + False + .uno:CurrencyField True - False - .uno:PatternField + False + .uno:PatternField True - False + False True - False - .uno:ImageControl + False + .uno:ImageControl True - False - .uno:FileControl + False + .uno:FileControl True - False + False True - False - .uno:Grid + False + .uno:Grid True - False - .uno:NavigationBar + False + .uno:NavigationBar True - False + False True - False - .uno:HelpIndex + False + .uno:HelpIndex True - False - .uno:ExtendedHelp + False + .uno:ExtendedHelp True - False - .uno:Documentation + False + .uno:Documentation True - False + False True - False - .uno:QuestionAnswers - - - - - True - False - .uno:SendFeedback + False + .uno:QuestionAnswers True - False + False True - False - .uno:SafeMode + False + .uno:SafeMode True - False - .uno:GetInvolved + False + .uno:GetInvolved True - False + False True - False - .uno:Donation + False + .uno:Donation True - False + False True - False - .uno:ShowLicense + False + .uno:ShowLicense True - False + False True - False - .uno:About + False + .uno:About True - False + False True - False - .uno:Shadowed + False + .uno:Shadowed True - False - .uno:OutlineFont + False + .uno:OutlineFont True - False - .uno:Overline + False + .uno:Overline True - False + False True - False - .uno:ChangeCaseToUpper + False + .uno:ChangeCaseToUpper True - False - .uno:ChangeCaseToLower + False + .uno:ChangeCaseToLower True - False - .uno:ChangeCaseRotateCase + False + .uno:ChangeCaseRotateCase True - False + False True - False - .uno:ChangeCaseToSentenceCase + False + .uno:ChangeCaseToSentenceCase True - False - .uno:ChangeCaseToTitleCase + False + .uno:ChangeCaseToTitleCase True - False - .uno:ChangeCaseToToggleCase + False + .uno:ChangeCaseToToggleCase True - False + False True - False - .uno:ParaLeftToRight + False + .uno:ParaLeftToRight True - False - .uno:ParaRightToLeft + False + .uno:ParaRightToLeft True - False + False True - False - .uno:InsertNonBreakingSpace + False + .uno:InsertNonBreakingSpace True - False - .uno:InsertHardHyphen + False + .uno:InsertHardHyphen True - False - .uno:InsertSoftHyphen + False + .uno:InsertSoftHyphen True - False - .uno:InsertZWSP + False + .uno:InsertZWSP True - False - .uno:InsertWJ + False + .uno:InsertWJ True - False - .uno:InsertLRM + False + .uno:InsertLRM True - False - .uno:InsertRLM + False + .uno:InsertRLM True - False + False True - False - .uno:SelectAll + False + .uno:SelectAll True - False - .uno:SelectRow + False + .uno:SelectRow True - False - .uno:SelectColumn + False + .uno:SelectColumn True - False - .uno:SelectData + False + .uno:SelectData True - False + False True - False - vnd.sun.star.findbar:FocusToFindbar + False + vnd.sun.star.findbar:FocusToFindbar True - False - .uno:SearchDialog + False + .uno:SearchDialog True - False + False True - False - .uno:Crop + False + .uno:Crop True - False - .uno:ExternalEdit + False + .uno:ExternalEdit True - False - .uno:ChangePicture + False + .uno:ChangePicture True - False - .uno:CompressGraphic + False + .uno:CompressGraphic True - False - .uno:SaveGraphic + False + .uno:SaveGraphic True - False + False True - False - .uno:OriginalSize + False + .uno:OriginalSize True - False - .uno:FitCellSize + False + .uno:FitCellSize True - False - .uno:TransformDialog + False + .uno:TransformDialog True - False - .uno:ImageMapDialog + False + .uno:ImageMapDialog True - False + False True - False - .uno:RenameObject + False + .uno:RenameObject True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - .uno:EditHyperlink + False + .uno:EditHyperlink True - False - .uno:RemoveHyperlink + False + .uno:RemoveHyperlink True - False - .uno:OpenHyperlinkOnCursor + False + .uno:OpenHyperlinkOnCursor True - False - .uno:AssignMacro + False + .uno:AssignMacro True - False + False True - False - .uno:FunctionDialog + False + .uno:FunctionDialog True - False - .uno:InsertName + False + .uno:InsertName True - False + False True - False - .uno:Gallery + False + .uno:Gallery True - False - .uno:TwainSelect + False + .uno:TwainSelect True - False - .uno:InsertAVMedia + False + .uno:InsertAVMedia True - False + False True - False - .uno:InsertQrCode + False + .uno:InsertQrCode True - False - .uno:InsertObject + False + .uno:InsertObject True - False - .uno:InsertSheetFromFile + False + .uno:InsertSheetFromFile True - False + False True - False - .uno:DrawText + False + .uno:DrawText True - False - .uno:VerticalText + False + .uno:VerticalText True - False - .uno:FontworkGalleryFloater + False + .uno:FontworkGalleryFloater True - False + False True - False - .uno:HyperlinkDialog + False + .uno:HyperlinkDialog True - False - .uno:AddName + False + .uno:AddName True - False - .uno:DefineName + False + .uno:DefineName True - False + False True - False - .uno:InsertCurrentDate + False + .uno:InsertCurrentDate True - False - .uno:InsertCurrentTime + False + .uno:InsertCurrentTime True - False - .uno:RandomNumberGeneratorDialog + False + .uno:RandomNumberGeneratorDialog True - False - .uno:EditHeaderAndFooter + False + .uno:EditHeaderAndFooter True - False + False True - False - .uno:AVMediaPlayer + False + .uno:AVMediaPlayer True - False + False True - False - .uno:RenameObject + False + .uno:RenameObject True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - .uno:EditHyperlink + False + .uno:EditHyperlink True - False - .uno:RemoveHyperlink + False + .uno:RemoveHyperlink True - False - .uno:OpenHyperlinkOnCursor + False + .uno:OpenHyperlinkOnCursor True - False - .uno:AssignMacro + False + .uno:AssignMacro True - False + False True - False - .uno:InsertCell + False + .uno:InsertCell True - False - .uno:DeleteCell + False + .uno:DeleteCell True - False + False True - False - .uno:PrintRangesMenu + False + .uno:PrintRangesMenu True - False + False True - False - .uno:InsertRowBreak + False + .uno:InsertRowBreak True - False - .uno:DeleteRowbreak + False + .uno:DeleteRowbreak True - False - .uno:InsertColumnBreak + False + .uno:InsertColumnBreak True - False - .uno:DeleteColumnbreak + False + .uno:DeleteColumnbreak True - False + False True - False - .uno:PageFormatDialog + False + .uno:RenameTable True - False + False True - False - .uno:PreviousPage + False + .uno:PreviousPage True - False - .uno:NextPage + False + .uno:NextPage True - False + False True - False - .uno:PageFormatDialog + False + .uno:PageFormatDialog True - False + False True - False - .uno:Print + False + .uno:Print True - False - .uno:ClosePreview + False + .uno:ClosePreview True - False + False True - False - .uno:SpellDialog + False + .uno:SpellDialog True - False - .uno:SpellOnline + False + .uno:SpellOnline True - False - .uno:ThesaurusDialog + False + .uno:ThesaurusDialog True - False + False True - False - .uno:SetLanguageAllTextMenu + False + .uno:SetLanguageAllTextMenu True - False + False True - False - .uno:Hyphenate + False + .uno:Hyphenate True - False - .uno:ChineseConversion + False + .uno:ChineseConversion True - False - .uno:HangulHanjaConversion + False + .uno:HangulHanjaConversion True - False - .uno:MoreDictionaries + False + .uno:MoreDictionaries True - False + False True - False - .uno:TraceChangeMode + False + .uno:TraceChangeMode True - False - .uno:AcceptChanges + False + .uno:AcceptChanges True - False + False True - False - .uno:InsertAnnotation + False + .uno:InsertAnnotation True - False - .uno:ShowAllNotes + False + .uno:ShowAllNotes True - False - .uno:HideAllNotes + False + .uno:HideAllNotes True - False + False True - False - .uno:Protect + False + .uno:Protect True - False - .uno:CompareDocuments + False + .uno:CompareDocuments True - False - .uno:MergeDocuments + False + .uno:MergeDocuments True - False + False True - False - .uno:SamplingDialog + False + .uno:SamplingDialog True - False - .uno:DescriptiveStatisticsDialog + False + .uno:DescriptiveStatisticsDialog True - False - .uno:AnalysisOfVarianceDialog + False + .uno:AnalysisOfVarianceDialog True - False - .uno:CorrelationDialog + False + .uno:CorrelationDialog True - False - .uno:CovarianceDialog + False + .uno:CovarianceDialog True - False - .uno:ExponentialSmoothingDialog + False + .uno:ExponentialSmoothingDialog True - False - .uno:MovingAverageDialog + False + .uno:MovingAverageDialog True - False - .uno:RegressionDialog + False + .uno:RegressionDialog True - False - .uno:TTestDialog + False + .uno:TTestDialog True - False - .uno:FTestDialog + False + .uno:FTestDialog True - False - .uno:ZTestDialog + False + .uno:ZTestDialog True - False - .uno:ChiSquareTestDialog + False + .uno:ChiSquareTestDialog True - False - .uno:FourierAnalysisDialog + False + .uno:FourierAnalysisDialog True - False + False True - False - .uno:MacroRecorder + False + .uno:MacroRecorder True - False - .uno:RunMacro + False + .uno:RunMacro True - False - .uno:BasicIDEAppear + False + .uno:BasicIDEAppear True - False - .uno:MacroOrganizer?TabId:short=1 + False + .uno:MacroOrganizer?TabId:short=1 True - False - .uno:ScriptOrganizer + False + .uno:ScriptOrganizer True - False - .uno:MacroSignature + False + .uno:MacroSignature True - False - .uno:DevelopmentToolsDockingWindow + False + .uno:DevelopmentToolsDockingWindow True - False + False True - False - .uno:GoalSeekDialog + False + .uno:GoalSeekDialog True - False - .uno:SolverDialog + False + .uno:SolverDialog True - False + False True - False - .uno:ShowPrecedents + False + .uno:ShowPrecedents True - False - .uno:ShowDependents + False + .uno:ShowDependents True - False + False True - False - .uno:ClearArrows + False + .uno:ClearArrows True - False - .uno:ClearArrowPrecedents + False + .uno:ClearArrowPrecedents True - False - .uno:ClearArrowDependents + False + .uno:ClearArrowDependents True - False + False True - False - .uno:ShowErrors + False + .uno:ShowErrors True - False - .uno:RefreshArrows + False + .uno:RefreshArrows True - False + False True - False - .uno:AuditingFillMode + False + .uno:AuditingFillMode True - False - .uno:AutoRefreshArrows + False + .uno:AutoRefreshArrows True - False - .uno:ShowInvalid + False + .uno:ShowInvalid True - False + False True - False - .uno:ViewDataSourceBrowser + False + .uno:ViewDataSourceBrowser True - False + False True - False - .uno:OpenXMLFilterSettings + False + .uno:OpenXMLFilterSettings True - False + False True - False - .uno:PagebreakMode + False + .uno:PagebreakMode True - False - .uno:NormalViewMode + False + .uno:NormalViewMode True - False + False True - False - .uno:FreezePanes + False + .uno:FreezePanes True - False - .uno:SplitWindow + False + .uno:SplitWindow True - False + False True - False - .uno:Menubar + False + .uno:Menubar True - False - .uno:Sidebar + False + .uno:Sidebar True - False - .uno:StatusBarVisible + False + .uno:StatusBarVisible True - False + False True - False - .uno:InputLineVisible + False + .uno:InputLineVisible True - False - .uno:ViewRowColumnHeaders + False + .uno:ViewRowColumnHeaders True - False - .uno:ToggleSheetGrid + False + .uno:ToggleSheetGrid True - False + False True - False - .uno:ViewValueHighlighting + False + .uno:ViewValueHighlighting True - False - .uno:ToggleFormula + False + .uno:ToggleFormula True - False - .uno:ShowGraphics + False + .uno:ShowGraphics True - False + False True - False - .uno:ZoomPage + False + .uno:ZoomPage True - False - .uno:ZoomPageWidth + False + .uno:ZoomPageWidth True - False - .uno:FullScreen + False + .uno:FullScreen - - True - False - cmd/lc_statisticsmenu.png - - - True - False - cmd/lc_changebezier.png - - - True - False - cmd/lc_insertfieldctrl.png - - + True - False + False True - False + False + 6 + 6 + 6 + 6 vertical True - True + True True True - + True - False + False - + True - False + False center - True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + True center True - both - False + both + False 3 - + True - .uno:AddDirect + .uno:AddDirect False @@ -2218,11 +2203,72 @@ - False - True - 0 + 0 + 0 + 2 + + + True + True + both + False + 3 + center + True + + + True + .uno:NewDoc + True + + + False + True + + + + + 1 + 0 + 2 + + + + + True + False + New + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -2231,75 +2277,177 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + Document + + + + + + + + + + 0 + 2 + 4 + + + + + True + True center - vertical + True + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:NewDoc - True - - - False - True - - + .uno:Open + True False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:SaveAsTemplate - True - - - False - True - - - - - False - True - 1 + True - False - True - 1 + 0 + 0 + 2 - + + + True + True + center + True + both + False + 3 + + + True + .uno:Save + True + + + False + True + + + + + 1 + 0 + 2 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:ExportTo + True + + + False + True + + + + + 2 + 0 + 2 + + + + + True + True + both-horiz + False + + + True + .uno:ExportDirectToPDF + True + + + False + True + + + + + 3 + 0 + + + + + True + False + vertical + + + 4 + 0 + 3 + + + + + True + True + both-horiz + False + + + True + .uno:SendMail + True + + + False + True + + + + + 3 + 1 + + + + + False @@ -2308,40 +2456,49 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + Print + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + True center True - both - False + both + False 3 - + True - .uno:Open - True + .uno:Print + True False @@ -2350,11 +2507,72 @@ - False - True - 1 + 0 + 0 + 2 + + + True + True + both-horiz + False + + + True + .uno:PrintDefault + True + + + False + True + + + + + 1 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:PrintPreview + True + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -2363,40 +2581,49 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + Properties + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + True center True - both - False + both + False 3 - + True - .uno:Save - True + .uno:SetDocumentProperties + True False @@ -2405,11 +2632,72 @@ - False - True - 1 + 0 + 0 + 2 + + + True + True + both-horiz + False + + + True + .uno:Signature + True + + + False + True + + + + + 1 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:SignPDF + True + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -2417,402 +2705,6 @@ 3 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ExportTo - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ExportDirectToPDF - True - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:SendMail - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Print - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:PrintDefault - True - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:PrintPreview - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SetDocumentProperties - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:Signature - True - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:SignPDF - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - True @@ -2823,30 +2715,30 @@ True - False + False end center True True - False + False center True vertical True - True + True end True - icons - False + icons + False 1 - + True - .uno:CloseDoc + .uno:CloseDoc False @@ -2863,16 +2755,16 @@ True - True + True end True - icons - False + icons + False 1 - + True - .uno:HelpIndex + .uno:HelpIndex False @@ -2896,22 +2788,22 @@ True - False + False center True vertical - _File + _File True - True - False - False + True + False + False end center True none - True + True False @@ -2921,16 +2813,16 @@ - _Help + _Help True - True - False - False + True + False + False end center True none - True + True False @@ -2949,70 +2841,75 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - True - False - ~File - True + False + ~File + True - False + False - + True - False + False 6 - + True - False + False center - True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Clipboard + + + + + + + 0 + 2 + 2 + + + + + True + True center True - both - False + both + False 3 - + True - .uno:Paste + .uno:Paste False @@ -3021,73 +2918,70 @@ - False - True - 0 + 0 + 0 + 2 - + True - False - center - vertical + True + both-horiz + False - + True - True - both-horiz - False - - - True - .uno:Cut - - - False - True - - + .uno:Cut False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Copy - - - False - True - - - - - False - True - 1 + True - False - True - 1 + 1 + 0 - + + + True + True + both-horiz + False + + + True + .uno:Copy + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -3096,997 +2990,46 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Font + + + + - False - True - 5 - 0 + 0 + 2 + 5 - + True - False - center - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:FormatPaintbrush - - - False - True - - - - - False - True - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:ResetAttributes - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False + True center True + both-horiz + False - + True - False - center - vertical - - - True - False - True - - - True - True - center - True - - - True - True - .uno:CharFontName - - - True - True - - - - - True - True - 0 - - - - - True - True - center - 5 - 5 - - - True - .uno:FontHeight - - - True - True - - - - - False - True - 1 - - - - - True - True - center - icons - False - - - True - .uno:Grow - - - False - True - - - - - True - .uno:Shrink - - - False - True - - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - True - center - icons - False - - - True - .uno:Bold - - - False - True - - - - - True - .uno:Italic - - - False - True - - - - - True - .uno:Underline - - - False - True - - - - - True - .uno:Strikeout - - - False - True - - - - - False - True - 0 - - - - - True - False - end - 5 - 5 - True - vertical - - - False - True - 1 - - - - - True - True - center - icons - False - - - True - .uno:SubScript - - - False - True - - - - - True - .uno:SuperScript - - - False - True - - - - - False - True - 2 - - - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 3 - - - - - True - True - center - icons - False - - - True - start - .uno:SetBorderStyle - - - True - True - - - - - True - .uno:BackgroundColor - True - - - False - True - - - - - True - .uno:Color - - - False - False - - - - - False - True - 4 - - - - - False - True - 2 - - - - - False - True - 1 - - - - - False - True - 2 - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - False - center - True - - - True - True - center - icons - False - - - True - .uno:AlignTop - - - False - True - - - - - True - .uno:AlignVCenter - - - False - True - - - - - True - .uno:AlignBottom - - - False - True - - - - - False - True - 0 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - True - center - icons - False - - - True - .uno:AlignLeft - - - False - True - - - - - True - .uno:AlignHorizontalCenter - - - False - True - - - - - True - .uno:AlignRight - - - False - True - - - - - False - True - 0 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - True - True - center - icons - False - - - True - .uno:Spacing - True - - - False - True - - - - - True - True - .uno:IncrementIndent - True - - - False - True - - - - - True - True - .uno:DecrementIndent - True - - - False - True - - - - - False - .uno:ParaLeftToRight - True - - - False - True - - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - True - center - icons - False - - - True - .uno:AlignBlock - - - False - True - - - - - False - True - 0 - - - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - True - True - center - icons - False - - - True - .uno:WrapText - - - False - True - - - - - False - .uno:ParaRightToLeft - True - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - False - True - - - True - True - center - True - icons - False - - - True - .uno:NumberFormatType - - - True - True - - - - - True - True - 0 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - True - center - icons - False - - - True - .uno:NumberFormatCurrency - - - False - False - - - - - True - center - True - .uno:NumberFormatPercent - - - False - False - - - - - True - center - True - .uno:NumberFormatDecimal - - - False - False - - - - - False - True - 0 - - - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - True - True - center - icons - False - - - True - .uno:NumberFormatIncDecimals - - - False - True - - - - - True - .uno:NumberFormatDecDecimals - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ToggleMergeCells + .uno:FormatPaintbrush False @@ -4095,175 +3038,167 @@ - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - icons - False - - - True - .uno:InsertRowsBefore - - - False - True - - - - - True - .uno:DeleteRows - - - False - True - - - - - True - .uno:RowOperations - - - False - True - - - - - False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:InsertColumnsBefore - - - False - True - - - - - True - .uno:DeleteColumns - - - False - True - - - - - True - .uno:ColumnOperations - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - 5 - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 0 + 0 - + True - True + True center True - both - False - 3 + both-horiz + False - + True - .uno:ConditionalFormatMenu + .uno:ResetAttributes + + + False + True + + + + + 0 + 1 + + + + + True + True + center + True + + + True + True + .uno:CharFontName + + + True + True + + + + + 1 + 0 + 2 + + + + + True + True + center + icons + False + + + True + .uno:Bold + + + False + True + + + + + True + .uno:Italic + + + False + True + + + + + True + .uno:Underline + + + False + True + + + + + True + .uno:Strikeout + + + False + True + + + + + 1 + 1 + + + + + True + True + center + 5 + 5 + + + True + .uno:FontHeight + + + True + True + + + + + 3 + 0 + + + + + True + True + center + icons + False + + + True + start + .uno:SetBorderStyle + + + True + True + + + + + True + .uno:BackgroundColor + True + + + False + True + + + + + True + .uno:Color False @@ -4272,262 +3207,32 @@ - False - True - 1 + 3 + 1 + 2 - - - - False - True - 8 - - - - - True - False - center - True - + True - False + True center - vertical + icons + False - + True - False - center - True - - - True - True - icons - False - - - True - center - True - .uno:StyleApply - - - True - True - - - - - True - True - 1 - - + .uno:SubScript False - True - 0 + True - + True - False - center - True - - - True - True - icons - False - - - True - .uno:StyleApply?Style:string=Default&FamilyName:string=CellStyles - cmd/sc_defaultcharstyle.png - - - False - True - - - - - False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:StyleApply?Style:string=Heading 1&FamilyName:string=CellStyles - cmd/sc_heading1parastyle.png - - - False - True - - - - - True - .uno:StyleApply?Style:string=Heading 2&FamilyName:string=CellStyles - cmd/sc_heading2parastyle.png - - - False - True - - - - - False - True - 4 - - - - - True - False - end - 5 - 5 - True - vertical - - - True - True - 5 - 5 - - - - - True - True - icons - False - - - True - .uno:StyleApply?Style:string=Good&FamilyName:string=CellStyles - cmd/sc_goodcellstyle.png - - - False - False - - - - - True - .uno:StyleApply?Style:string=Neutral&FamilyName:string=CellStyles - cmd/sc_neutralcellstyle.png - - - False - False - - - - - True - .uno:StyleApply?Style:string=Bad&FamilyName:string=CellStyles - cmd/sc_badcellstyle.png - - - False - False - - - - - False - True - 6 - - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SearchDialog + .uno:SuperScript False @@ -4536,96 +3241,663 @@ - False - True - 1 + 2 + 1 - - - - False - True - 10 - - - - - True - False - center - True - + True - False + True center - vertical + icons + False - + True - True - both-horiz - False - - - True - center - .uno:DataSort - - - False - True - - + .uno:Grow False - True - 0 + True - + True - True - both-horiz - False - - - True - center - .uno:DataFilterAutoFilter - - - False - True - - + .uno:Shrink False - True - 1 + True - False - True - 2 + 4 + 0 - + + + True + False + vertical + + + 5 + 0 + 3 + + + + + False True - 11 + 1 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + end + True + Alignment + + + + + + + 0 + 2 + 3 + + + + + True + True + center + icons + False + + + True + .uno:AlignTop + + + False + True + + + + + True + .uno:AlignVCenter + + + False + True + + + + + True + .uno:AlignBottom + + + False + True + + + + + 0 + 0 + + + + + True + True + center + icons + False + + + True + .uno:AlignLeft + + + False + True + + + + + True + .uno:AlignHorizontalCenter + + + False + True + + + + + True + .uno:AlignRight + + + False + True + + + + + 0 + 1 + + + + + True + True + center + icons + False + + + True + .uno:Spacing + True + + + False + True + + + + + True + True + .uno:IncrementIndent + True + + + False + True + + + + + True + True + .uno:DecrementIndent + True + + + False + True + + + + + .uno:ParaLeftToRight + True + + + False + True + + + + + 1 + 0 + 2 + + + + + True + True + center + icons + False + + + True + .uno:AlignBlock + + + False + True + + + + + 1 + 1 + + + + + True + True + center + icons + False + + + True + .uno:WrapText + + + False + True + + + + + .uno:ParaRightToLeft + True + + + False + True + + + + + 2 + 1 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + + + + False + True + 2 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + end + True + Number + + + + + + + 0 + 2 + 3 + + + + + True + True + center + 3 + True + icons + False + + + True + .uno:NumberFormatType + + + True + True + + + + + 1 + 0 + 2 + + + + + True + True + center + icons + False + + + True + .uno:NumberFormatCurrency + + + False + False + + + + + True + center + True + .uno:NumberFormatPercent + + + False + False + + + + + True + center + True + .uno:NumberFormatDecimal + + + False + False + + + + + 1 + 1 + + + + + True + True + center + icons + False + + + True + .uno:NumberFormatIncDecimals + + + False + True + + + + + True + .uno:NumberFormatDecDecimals + + + False + True + + + + + 2 + 1 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:ConditionalFormatMenu + + + False + False + + + + + 0 + 0 + 2 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + + + + False + True + 3 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + end + True + Cells + + + + + + + 0 + 2 + 2 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:ToggleMergeCells + + + False + True + + + + + 0 + 0 + 2 + + + + + True + True + center + True + icons + False + + + True + .uno:InsertRowsBefore + + + False + True + + + + + True + .uno:DeleteRows + + + False + True + + + + + True + .uno:RowOperations + + + False + True + + + + + 1 + 0 + + + + + True + True + center + True + icons + False + + + True + .uno:InsertColumnsBefore + + + False + True + + + + + True + .uno:DeleteColumns + + + False + True + + + + + True + .uno:ColumnOperations + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + + + + False + True + 4 @@ -4638,29 +3910,29 @@ True - False + False end center True True - False + False center True vertical - _Home + _Home True - True - False - False + True + False + False end center True none - True + True False @@ -4671,16 +3943,16 @@ True - True + True center True - icons - False + icons + False 1 - + True - .uno:SearchDialog + .uno:SearchDialog False @@ -4688,10 +3960,10 @@ - + True center - .uno:SortAscending + .uno:SortAscending False @@ -4699,10 +3971,10 @@ - + True center - .uno:DataFilterAutoFilter + .uno:DataFilterAutoFilter False @@ -4727,25 +3999,8 @@ False False - end - 1 - - - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 + end + 7 @@ -4756,9 +4011,9 @@ True - False - ~Home - True + False + ~Home + True + + + True + False + both-horiz + False + + + True + .uno:DefineName + + + False + True + + + + + 0 + 1 + + + + + False @@ -4897,39 +4254,58 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + Text + + + + + + + - False - True - 5 - 0 + 0 + 2 + 3 - + True - True + True center True - both - False + both + False 3 - + True - .uno:InsertObjectChart + .uno:DrawText + + + False + True + + + + + True + .uno:VerticalText False @@ -4938,11 +4314,119 @@ - False - True - 1 + 0 + 0 + 2 + + + True + True + center + True + both-horiz + False + + + True + .uno:CharmapControl + + + False + True + + + + + 1 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:HyperlinkDialog + + + False + True + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:InsertCurrentDate + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:InsertCurrentTime + True + + + False + True + + + + + 2 + 1 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + False @@ -4951,73 +4435,168 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + Objects + + + + + + + + + + 0 + 2 + 3 + + + + + True + True center - vertical + True + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:FunctionBox - - - False - True - - + .uno:InsertObjectChart False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:InsertObject - - - False - True - - - - - False - True - 1 + True - False - True - 2 + 0 + 0 + 2 - + + + True + True + both-horiz + False + + + True + .uno:InsertObject + + + False + True + + + + + 2 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:InsertGraphic + + + False + True + + + + + 1 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:Gallery + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:InsertObjectStarMath + + + False + True + + + + + 2 + 1 + + + + + False @@ -5026,39 +4605,145 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + Shapes + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True - center - True - both - False - 3 + True - + True - .uno:InsertGraphic + .uno:BasicShapes + + + True + True + + + + + True + .uno:SymbolShapes + + + True + True + + + + + True + .uno:ArrowShapes + + + True + True + + + + + 1 + 0 + + + + + True + True + + + True + .uno:StarShapes + + + True + True + + + + + True + .uno:CalloutShapes + + + True + True + + + + + True + .uno:FlowChartShapes + + + True + True + + + + + 1 + 1 + + + + + True + True + icons + False + + + True + .uno:Line + + + True + True + + + + + True + .uno:ConnectorToolbox + + + False + True + + + + + True + .uno:ArrowsToolbox False @@ -5067,11 +4752,77 @@ - False - True - 1 + 0 + 0 + + + True + True + icons + False + + + True + .uno:BasicShapes.rectangle + + + True + True + + + + + True + .uno:BasicShapes.ellipse + + + True + True + + + + + True + .uno:DrawCaption + + + True + True + + + + + True + .uno:LineToolbox + + + False + True + + + + + 0 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -5079,680 +4830,6 @@ 4 - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:Gallery - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:InsertAVMedia - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:HyperlinkDialog - - - False - True - - - - - False - True - 1 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:AddName - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:DefineName - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - Fiel_d - 70 - True - True - True - .uno:FieldMenu - paragraphstylei - none - True - top - True - - - False - True - 1 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:DrawText - - - False - True - - - - - True - .uno:VerticalText - - - False - True - - - - - False - True - 1 - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - icons - False - - - True - .uno:Line - - - True - True - - - - - True - .uno:ConnectorToolbox - - - False - True - - - - - True - .uno:ArrowsToolbox - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:BasicShapes.rectangle - - - True - True - - - - - True - .uno:BasicShapes.ellipse - - - True - True - - - - - True - .uno:DrawCaption - - - True - True - - - - - True - .uno:LineToolbox - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - - - True - .uno:BasicShapes - - - True - True - - - - - True - .uno:SymbolShapes - - - True - True - - - - - True - .uno:ArrowShapes - - - True - True - - - - - False - True - 0 - - - - - True - True - - - True - .uno:StarShapes - - - True - True - - - - - True - .uno:CalloutShapes - - - True - True - - - - - True - .uno:FlowChartShapes - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:CharmapControl - - - False - True - - - - - False - True - 1 - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - both - False - 3 - - - True - .uno:InsertObjectStarMath - - - False - True - - - - - False - True - 0 - - - - - False - True - 1 - - - - - - False - True - 13 - - True @@ -5763,29 +4840,29 @@ True - False + False end center True True - False + False center True vertical - _Insert + _Insert True - True - False - False + True + False + False end center True none - True + True False @@ -5796,16 +4873,16 @@ True - True + True end True - icons - False + icons + False 1 - + True - .uno:DataDataPilotRun + .uno:DataDataPilotRun False @@ -5813,10 +4890,10 @@ - + True center - .uno:InsertDraw + .uno:InsertDraw False @@ -5824,9 +4901,9 @@ - + True - .uno:FunctionBox + .uno:FunctionBox False @@ -5851,27 +4928,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 2 @@ -5880,46 +4940,81 @@ True - False - ~Insert - True + False + ~Insert + True 2 - False + False - + True - False + False center True - + True - False + False center - True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Page + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + True center True - both - False + both + False 3 - + True - .uno:PageFormatDialog + .uno:PageFormatDialog False @@ -5928,11 +5023,66 @@ - False - True - 0 + 0 + 0 + 2 + + + True + True + center + True + both + False + 3 + + + True + .uno:EditHeaderAndFooter + + + False + True + + + + + 1 + 0 + 2 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:AutoFormat + + + False + True + + + + + 2 + 0 + 2 + + + + + False @@ -5941,156 +5091,62 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - True - center - True - both - False - 3 - - - True - .uno:EditHeaderAndFooter - - - False - True - - + False + Print Area + + + + + + + - False - True - 1 + 0 + 2 + 2 - - - False - True - 1 - - - - - True - False - center - True - + True - False - center - vertical - - - True - True - both-horiz - False - - - True - start - .uno:NormalViewMode - - - True - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:PagebreakMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - 5 - 5 + False vertical - False - True - 5 - 0 + 2 + 0 + 3 - + True - True + True center True - both - False + both + False 3 - + True center True - .uno:DefinePrintArea + .uno:DefinePrintArea True @@ -6099,11 +5155,477 @@ - False - True - 1 + 0 + 0 + 2 + + + True + True + center + True + both-horiz + False + + + True + center + True + .uno:EditPrintArea + + + True + True + + + + + 1 + 0 + + + + + True + True + center + True + icons + False + + + True + center + True + .uno:AddPrintArea + + + True + True + + + + + True + center + True + .uno:DeletePrintArea + + + True + True + + + + + 1 + 1 + + + + + + + + False + True + 1 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + Sheet + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:Insert + + + False + True + + + + + 0 + 0 + 2 + + + + + True + True + both-horiz + False + + + True + start + .uno:RowOperations + + + True + True + + + + + 1 + 0 + + + + + True + True + both-horiz + False + + + True + start + .uno:ColumnOperations + + + True + True + + + + + 1 + 1 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:SheetRightToLeft + + + False + True + + + + + 2 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:ChooseDesign + + + False + True + + + + + 2 + 1 + + + + + + + + False + True + 2 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + Objects + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + vertical + + + 4 + 0 + 3 + + + + + True + True + icons + False + + + True + .uno:BringToFront + + + False + True + + + + + 2 + 0 + + + + + True + True + icons + False + + + True + .uno:SendToBack + + + False + True + + + + + 2 + 1 + + + + + True + True + both-horiz + False + + + True + .uno:ObjectForwardOne + + + False + True + + + + + 3 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:ObjectBackOne + + + False + True + + + + + 3 + 1 + + + + + True + True + both-horiz + False + + + True + .uno:SelectObject + + + False + True + + + + + 0 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:ToggleObjectRotateMode + + + False + True + + + + + 1 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:FormatGroup + + + False + True + + + + + 0 + 1 + + + + + True + True + both-horiz + False + + + True + start + .uno:ObjectAlign + + + True + True + + + + + 1 + 1 + + + + + False @@ -6111,825 +5633,6 @@ 3 - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - center - True - .uno:EditPrintArea - - - True - True - - - - - False - False - 0 - - - - - True - True - center - True - icons - False - - - True - center - True - .uno:AddPrintArea - - - True - True - - - - - True - center - True - .uno:DeletePrintArea - - - True - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Insert - - - False - True - - - - - False - True - 1 - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - start - .uno:RowOperations - - - True - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - start - .uno:ColumnOperations - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:RenameTable - - - False - True - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:Show - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Hide - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:AutoFormat - - - False - True - - - - - False - True - 1 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ChooseDesign - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:TableEvents - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:SelectObject - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:FormatGroup - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - start - .uno:ObjectAlign - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 13 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ObjectForwardOne - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectBackOne - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 14 - - True @@ -6940,29 +5643,29 @@ True - False + False end center True True - False + False center True vertical - _Layout + _Layout True - True - False - False + True + False + False end center True none - True + True False @@ -6973,16 +5676,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 - + True - .uno:PageFormatDialog + .uno:PageFormatDialog False @@ -7007,27 +5710,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 3 @@ -7036,45 +5722,80 @@ True - False - ~Layout - True + False + ~Layout + True 3 - False + False - + True - False + False 6 - + True - False + False center - True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Data Sources + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + vertical + + + 4 + 0 + 3 + + + + + True + True center True - both - False + both + False 3 - + True - .uno:InsertExternalDataSource + .uno:InsertExternalDataSource False @@ -7083,11 +5804,114 @@ - False - True - 1 + 0 + 0 + 2 + + + True + True + center + True + both + False + 3 + + + True + .uno:DataStreams + + + False + True + + + + + 1 + 0 + 2 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:ManageXMLSource + + + False + True + + + + + 2 + 0 + 2 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:DataProvider + + + False + True + + + + + 3 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:DataProviderRefresh + + + False + True + + + + + 3 + 1 + + + + + False @@ -7096,24 +5920,62 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - True + False + vertical + + + 3 + 0 + 3 + + + + + True + False + end + True + Sort + + + + + + + + + + 0 + 2 + 3 + + + + + True + True center True - both - False + both + False 3 - + True - .uno:DataStreams + .uno:DataSort False @@ -7122,11 +5984,88 @@ - False - True - 2 + 0 + 0 + 2 + + + True + True + center + True + icons + False + + + True + .uno:SortAscending + + + False + True + + + + + 1 + 0 + + + + + True + True + center + True + icons + False + + + True + .uno:SortDescending + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:Shuffle + + + False + True + + + + + 2 + 0 + 2 + + + + + False @@ -7135,37 +6074,148 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - True + False + vertical + + + 2 + 0 + 3 + + + + + True + False + end + True + Filter + + + + + + + + + + 0 + 2 + 2 + + + + + True + True center True - both - False - 3 + both-horiz + False - + True - .uno:ManageXMLSource + .uno:DataFilterAutoFilter - False + True True - False - True - 2 + 0 + 0 + + + True + True + center + True + both-horiz + False + + + True + .uno:DataFilterHideAutoFilter + + + True + True + + + + + 0 + 1 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:DataFilterStandardFilter + + + True + True + + + + + 1 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:DataFilterSpecialFilter + + + True + True + + + + + 1 + 1 + + + + + False @@ -7174,78 +6224,146 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + vertical + + + 2 + 0 + 3 + + + + + True + False + end + True + Examination + + + + + + + + + + 0 + 2 + 2 + + + + + True + True center True - vertical + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:DataProvider - - - False - True - - + .uno:DataConsolidate False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DataProviderRefresh - - - False - True - - - - - False - False - 1 + True - False - True - 3 + 1 + 0 - + + + True + True + center + True + both-horiz + False + + + True + .uno:Validation + + + False + True + + + + + 1 + 1 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:TextToColumns + + + False + True + + + + + 0 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:HandleDuplicateRecords + + + False + True + + + + + 0 + 1 + + + + + False @@ -7254,82 +6372,174 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 + False vertical - False - True - 5 - 0 + 3 + 0 + 3 - + True - False - vertical + False + end + True + Subtotal + + + + + + + + + + 0 + 2 + 3 + + + + + True + True + center + True + both + False + 3 - + True - True - both-horiz - - - True - .uno:Calculate - - - False - True - - + .uno:DataSubTotals False - True - 0 - - - - - True - True - both-horiz - - - True - .uno:HandleDuplicateRecords - - - False - True - - - - - False - True - 1 + True - False - True - 1 + 0 + 0 + 2 + + + True + True + center + True + both-horiz + False + + + True + .uno:Group + + + False + True + + + + + 1 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:Ungroup + + + False + True + + + + + 1 + 1 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:HideDetail + + + False + True + + + + + 2 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:ShowDetail + + + False + True + + + + + 2 + 1 + + + + + False @@ -7337,1041 +6547,6 @@ 4 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:DataDataPilotRun - - - False - True - - - - - False - True - 1 - - - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:RecalcPivotTable - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DeletePivotTable - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:DataSort - - - False - True - - - - - False - True - 1 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - icons - False - - - True - .uno:SortAscending - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:SortDescending - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:DataFilterAutoFilter - - - True - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DataFilterSpecialFilter - - - True - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:DataFilterStandardFilter - - - True - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DataFilterHideAutoFilter - - - True - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:DataSubTotals - - - False - True - - - - - False - True - 1 - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:Group - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:Ungroup - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:HideDetail - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:ShowDetail - - - False - True - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:DefineDBName - - - False - True - - - - - False - True - 1 - - - - - False - True - 13 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:SelectDB - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DataAreaRefresh - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 14 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:AddName - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DefineName - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 14 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:TextToColumns - - - False - True - - - - - False - True - 1 - - - - - False - True - 15 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:DataConsolidate - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:Validation - - - False - True - - - - - False - False - 1 - - - - - False - True - 1 - - - - - - False - True - 16 - - - - - True - False - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - _Statistics - 80 - True - True - True - .uno:StatisticsMenu - StatisticsImg - none - True - top - True - - - False - True - 2 - - - - - - False - True - 17 - - True @@ -8382,29 +6557,29 @@ True - False + False end center True True - False + False center True vertical - _Data + _Data True - True - False - False + True + False + False end center True none - True + True False @@ -8415,16 +6590,16 @@ True - True + True center True - icons - False + icons + False 1 - + True - .uno:SearchDialog + .uno:SearchDialog False @@ -8432,10 +6607,10 @@ - + True center - .uno:SortAscending + .uno:SortAscending False @@ -8443,10 +6618,10 @@ - + True center - .uno:DataFilterAutoFilter + .uno:DataFilterAutoFilter False @@ -8471,83 +6646,94 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 4 + 5 True - False - ~Data - True + False + ~Data + True 4 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + vertical + + + 3 + 0 + 3 + + + + + True + False + end + True + Goal Seeker + + + + + + + + + + 0 + 2 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:SpellDialog - - - False - True - - - - - True - .uno:ThesaurusDialog + .uno:GoalSeekDialog False @@ -8556,11 +6742,84 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + center + True + both + False + 3 + + + True + .uno:SolverDialog + + + False + True + + + + + 1 + 0 + 2 + + + + + True + False + both-horiz + False + + + True + .uno:ShowInvalid + + + False + True + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ShowErrors + + + False + True + + + + + 2 + 0 + + + + + False @@ -8569,74 +6828,166 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + vertical + + + 3 + 0 + 3 + + + + + True + False + end + True + Detective + + + + + + + + + + 0 + 2 + 3 + + + + + True + False center True - vertical + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:SpellOnline - - - True - True - - + .uno:AuditingFillMode False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Hyphenate - - - True - True - - - - - False - True - 1 + True - False - True - 2 + 0 + 0 + 2 - + + + True + False + both-horiz + False + + + True + .uno:ShowPrecedents + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ShowDependents + + + False + True + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ClearArrowPrecedents + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ClearArrowDependents + + + False + True + + + + + 2 + 1 + + + + + False @@ -8645,49 +6996,105 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 + False vertical - False - True - 5 - 0 + 2 + 0 + 3 - + True - True + False + end + True + Statistics + + + + + + + + + + 0 + 2 + 2 + + + + + True + False center True - both - False - 3 + both-horiz + False - + True - .uno:InsertAnnotation + .uno:ChiSquareTestDialog - True + False True - + True - .uno:EditAnnotation + .uno:FTestDialog + True + + + False + True + + + + + True + .uno:TTestDialog + True + + + False + True + + + + + True + .uno:ZTestDialog + True + + + False + True + + + + + True + .uno:AnalysisOfVarianceDialog + True False @@ -8696,11 +7103,532 @@ - False - True - 1 + 1 + 0 + + + True + False + center + True + both + False + 3 + + + True + .uno:DescriptiveStatisticsDialog + + + False + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:RegressionDialog + True + + + False + True + + + + + True + .uno:FourierAnalysisDialog + True + + + False + True + + + + + True + .uno:CorrelationDialog + True + + + False + True + + + + + True + .uno:CovarianceDialog + + + False + True + + + + + 1 + 1 + + + + + + + + False + True + 2 + + + + + True + True + 0 + + + + + 5 + + + + + True + False + ~Functions + + + 5 + False + + + + + True + False + + + True + False + center + + + + True + False + 6 + 3 + 6 + 6 + 3 + 3 + + + True + False + Spelling + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:SpellDialog + + + False + True + + + + + True + .uno:ThesaurusDialog + + + False + True + + + + + 0 + 0 + 2 + + + + + True + True + both-horiz + False + + + True + .uno:SpellOnline + + + True + True + + + + + 1 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:Hyphenate + + + True + True + + + + + 1 + 1 + + + + + + + + False + True + 0 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + Comments + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:InsertAnnotation + + + True + True + + + + + True + .uno:EditAnnotation + + + False + True + + + + + 0 + 0 + 2 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:ShowAllNotes + + + False + True + + + + + 1 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:DeleteAllNotes + + + False + True + + + + + 2 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:HideAllNotes + + + False + True + + + + + 1 + 1 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:DeleteNote + + + False + True + + + + + 2 + 1 + + + + + + + + False + True + 1 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + Track Changes + + + + + + + + + + 0 + 2 + + + + + True + False + vertical + + + 1 + 0 + 3 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:TraceChangeMode + + + False + True + + + + + True + .uno:AcceptChanges + True + + + False + True + + + + + 0 + 0 + 2 + + + + + False @@ -8709,78 +7637,190 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center - True + False + Document + + + + + + + + + + 0 + 2 + 4 + + + + + True + False vertical + + + 4 + 0 + 3 + + + + + True + False + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:ShowAllNotes - - - False - True - - + .uno:ToolProtectionDocument False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:HideAllNotes - - - False - True - - - - - False - False - 1 + True - False - True - 2 + 1 + 0 - + + + True + False + both-horiz + False + + + True + .uno:ShareDocument + + + False + True + + + + + 1 + 1 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:Protect + + + False + True + + + + + 0 + 0 + 2 + + + + + True + True + both-horiz + False + + + True + .uno:CompareDocuments + + + False + True + + + + + 3 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:MergeDocuments + + + False + True + + + + + 3 + 1 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:RedactDoc + + + False + True + + + + + 2 + 0 + 2 + + + + + False @@ -8788,499 +7828,6 @@ 3 - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:DeleteAllNotes - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DeleteNote - - - False - True - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:TraceChangeMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 5 - - - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:AcceptChanges - - - False - True - - - - - False - True - 1 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Protect - - - False - True - - - - - False - True - 1 - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ToolProtectionDocument - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ShareDocument - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:CompareDocuments - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:MergeDocuments - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:RedactDoc - - - False - True - - - - - False - True - 1 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:EditDoc - - - False - True - - - - - False - True - 1 - - - - - - False - True - 11 - - True @@ -9291,29 +7838,29 @@ True - False + False end center True True - False + False center True vertical - _Review + _Review True - True - False - False + True + False + False end center True none - True + True False @@ -9324,17 +7871,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 - + True center - .uno:AcceptChanges + .uno:AcceptChanges True @@ -9359,73 +7906,102 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 5 + 6 True - False - ~Review - True + False + ~Review + True - 5 - False + 6 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Freeze + + + + + + + + + + 0 + 2 + + + + + True + False + vertical + + + 1 + 0 + 3 + + + + + True + True center True - both - False + both + False 3 - + True - .uno:NormalViewMode + .uno:FreezePanes + + + False + True + + + + + True + .uno:SplitWindow + True False @@ -9434,11 +8010,14 @@ - False - True - 0 + 0 + 0 + 2 + + + False @@ -9447,24 +8026,60 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Zoom + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + True center True - both - False + both + False 3 - + True - .uno:PagebreakMode + .uno:ZoomOptimal False @@ -9473,11 +8088,84 @@ - False - True - 1 + 0 + 0 + 2 + + + True + True + both-horiz + False + + + True + .uno:Zoom100Percent + + + False + True + + + + + 1 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:ZoomPage + + + False + True + + + + + 1 + 1 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:FullScreen + + + False + True + + + + + 2 + 0 + 2 + + + + + False @@ -9486,24 +8174,59 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - True + False + Options + + + + + + + + + + 0 + 2 + 6 + + + + + True + False + vertical + + + 6 + 0 + 3 + + + + + True + True center True - both - False - 3 + both-horiz + False - + True - .uno:PrintPreview + .uno:Sidebar False @@ -9512,14 +8235,245 @@ - False - True - 2 + 1 + 0 - + + + True + True + center + True + both-horiz + False + + + True + .uno:ViewRowColumnHeaders + + + False + False + + + + + 2 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:ToggleSheetGrid + + + False + False + + + + + 2 + 1 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:Menubar + + + False + True + + + + + 3 + 0 + + + + + True + True + center + True + both-horiz + False + + + True + .uno:InputLineVisible + + + False + True + + + + + 3 + 1 + + + + + True + True + both-horiz + False + + + True + .uno:ViewValueHighlighting + + + False + True + + + + + 4 + 0 + + + + + True + True + both-horiz + False + + + True + .uno:ToggleFormula + + + False + True + + + + + 4 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ViewColumnRowHighlighting + + + False + True + + + + + 5 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ViewHiddenColRow + + + False + True + + + + + 5 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:FunctionBox + + + False + True + + + + + 1 + 1 + + + + + True + True + center + True + both + False + 3 + + + True + .uno:ChangeTheme + + + False + True + + + + + 0 + 0 + 2 + + + + + False @@ -9527,709 +8481,6 @@ 2 - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ViewValueHighlighting - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ToggleFormula - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - False - .uno:ChangeTheme - - - False - True - - - - - False - True - 1 - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ZoomOptimal - - - False - True - - - - - False - True - 1 - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:Zoom100Percent - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ZoomPage - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:FullScreen - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ZoomPageWidth - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:FreezePanes - - - False - True - - - - - False - True - 1 - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - center - True - both - False - 3 - - - True - .uno:SplitWindow - - - True - True - - - - - False - False - 0 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Sidebar - - - False - True - - - - - False - True - 1 - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:ViewRowColumnHeaders - - - False - False - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:ToggleSheetGrid - - - False - False - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:Menubar - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:InputLineVisible - - - False - True - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:NewWindow - - - True - True - - - - - False - True - 1 - - - - - - False - True - 12 - - True @@ -10240,29 +8491,29 @@ True - False + False end center True True - False + False center True vertical - _View + _View True - True - False - False + True + False + False end center True none - True + True False @@ -10273,17 +8524,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 - + True center - .uno:Zoom + .uno:Zoom False @@ -10308,75 +8559,160 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 6 + 7 True - False - ~View - True + False + ~View + True - 6 - False + 7 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True - center + False + end True - both - False - 3 + Image + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 + vertical + + + 3 + 0 + 3 + + + + + True + False + icons + False - + + True + .uno:CompressGraphic + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:Crop + + + False + True + + + + + 2 + 0 + + + + + True + False + icons + False + + True center True - .uno:AssignMacro + .uno:ToggleObjectRotateMode + + + False + False + + + + + True + .uno:FlipVertical + + + False + False + + + + + True + .uno:FlipHorizontal False @@ -10385,11 +8721,42 @@ - False - True - 0 + 1 + 1 + 2 + + + True + True + center + True + both + False + 3 + + + True + center + True + .uno:AssignMacro + + + False + False + + + + + 0 + 0 + 2 + + + + + False @@ -10398,127 +8765,198 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end True + Fill & Border + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + text + False - + True - False - - - True - True - icons - False - - - True - .uno:CompressGraphic - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Crop - - - False - True - - - - - False - True - 1 - - + .uno:FormatArea False - True - 0 - - - - - True - True - icons - False - - - True - center - True - .uno:ToggleObjectRotateMode - - - False - False - - - - - True - .uno:FlipVertical - - - False - False - - - - - True - .uno:FlipHorizontal - - - False - False - - - - - False - True - 1 + False - False - True - 1 + 0 + 1 + + + True + False + both-horiz + False + + + True + .uno:FillStyle + + + False + True + + + + + 1 + 1 + 2 + + + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + False @@ -10527,84 +8965,255 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Positioning + + + + + + + - False - True - 5 - 0 + 0 + 2 + 4 - + True - False + False + end + 5 + 5 vertical + + + 4 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - text - False - - - True - .uno:FormatLine - - - True - True - - + center + True + .uno:AnchorMenu False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 + False - False - True - 1 + 0 + 0 + 2 + + + True + True + icons + False + + + True + .uno:ObjectAlignLeft + + + False + True + + + + + True + .uno:AlignCenter + + + False + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + 1 + 0 + + + + + True + True + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + 1 + 1 + + + + + True + False + icons + False + + + True + .uno:BringToFront + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectForwardOne + + + False + True + + + + + 3 + 0 + + + + + True + False + icons + False + + + True + .uno:SendToBack + + + False + True + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectBackOne + + + False + True + + + + + 3 + 1 + + + + + False @@ -10613,125 +9222,221 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Modify + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + end + 5 + 5 vertical + + + 4 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - + center + True + .uno:GraphicFilterToolbox False - True - 0 - - - - - True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - - - - True - True - 1 + False - False - True - 2 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + center + 5 + .uno:GrafLuminance + + + False + False + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + center + 5 + .uno:GrafContrast + + + False + False + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + center + .uno:GrafTransparence + + + False + False + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + center + .uno:GrafGamma + + + False + False + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:GrafMode + + + False + True + + + + + 3 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ColorSettings + + + False + True + + + + + 3 + 1 + + + + + False @@ -10739,692 +9444,6 @@ 3 - - - True - False - center - True - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - center - True - .uno:AnchorMenu - - - False - False - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - 5 - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectForwardOne - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectBackOne - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - both - False - - - True - .uno:GraphicFilterToolbox - - - False - False - - - - - False - True - 1 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - center - .uno:GrafLuminance - - - False - False - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - center - 5 - .uno:GrafContrast - - - False - False - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 5 - 9 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - center - .uno:GrafTransparence - - - False - False - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - center - 5 - .uno:GrafGamma - - - False - False - - - - - False - True - 1 - - - - - False - True - 0 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - False - both-horiz - False - - - True - .uno:GrafMode - - - False - True - - - - - False - True - 0 - - - - - True - False - both-horiz - False - - - True - .uno:ColorSettings - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 11 - - True @@ -11435,28 +9454,28 @@ True - False + False end center True True - False + False center True vertical - Ima_ge + Ima_ge True - True - False - False + True + False + False end center none - True + True False @@ -11467,18 +9486,18 @@ True - True + True end True - icons - False + icons + False 1 - + True center True - .uno:SaveGraphic + .uno:SaveGraphic False @@ -11486,11 +9505,11 @@ - + True center True - .uno:FormatArea + .uno:FormatArea True @@ -11498,11 +9517,11 @@ - + True center True - .uno:FormatLine + .uno:FormatLine True @@ -11510,11 +9529,11 @@ - + True center True - .uno:TransformDialog + .uno:TransformDialog True @@ -11539,78 +9558,119 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 7 + 8 True - False - Ima~ge - True + False + Ima~ge + True - 7 - False + 8 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True - center + False + end True - both - False - 3 + Drawing Object + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False + icons + False - + True center True - .uno:AssignMacro + .uno:ToggleObjectRotateMode + + + False + False + + + + + True + .uno:FlipVertical + + + False + False + + + + + True + .uno:FlipHorizontal False @@ -11619,94 +9679,63 @@ - False - True - 0 + 1 + 1 - + True - False - center - vertical + False + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:ToggleObjectBezierMode - - - False - True - - + .uno:ToggleObjectBezierMode False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - True - .uno:FlipVertical - - - False - True - - - - - True - .uno:FlipHorizontal - - - False - True - - - - - False - True - 1 + True - False - True - 1 + 1 + 0 + + + True + True + center + True + both + False + 3 + + + True + center + True + .uno:AssignMacro + + + False + False + + + + + 0 + 0 + 2 + + + + + False @@ -11715,328 +9744,62 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - vertical - - - True - True - text - False - - - True - .uno:FormatLine - - - True - True - - - - - False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - vertical - - - True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - - - - True - True - 1 - - - - - False - True - 2 - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center + False + end True - both - False - 3 + Fill & Border + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 + vertical + + + 3 + 0 + 3 + + + + + True + False + text + False - + True - center - True - .uno:AnchorMenu + .uno:FormatArea False @@ -12045,14 +9808,652 @@ - False - True - 1 + 0 + 1 - + + + True + False + both-horiz + False + + + True + .uno:FillStyle + + + False + True + + + + + 1 + 1 + 2 + + + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + + + + False + True + 1 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + end + True + Positioning + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + end + 5 + 5 + vertical + + + 4 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + center + True + .uno:AnchorMenu + + + False + False + + + + + 0 + 0 + 2 + + + + + True + False + icons + False + + + True + .uno:ObjectAlignLeft + + + False + True + + + + + True + .uno:AlignCenter + + + False + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + 1 + 1 + + + + + True + False + icons + False + + + True + .uno:BringToFront + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectForwardOne + + + False + True + + + + + 3 + 0 + + + + + True + False + icons + False + + + True + .uno:SendToBack + + + False + True + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectBackOne + + + False + True + + + + + 3 + 1 + + + + + + + + False + True + 2 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + end + True + Grouping + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:FormatGroup + + + True + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:EnterGroup + + + True + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:LeaveGroup + + + True + True + + + + + 1 + 1 + + + + + + + + False + True + 3 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + end + True + 3D + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + False + both-horiz + False + + + True + .uno:ExtrusionToggle + + + True + True + + + + + 0 + 0 + + + + + True + False + icons + False + + + True + .uno:ExtrusionDepthFloater + + + True + True + + + + + True + .uno:ExtrusionDirectionFloater + + + True + True + + + + + True + .uno:Extrusion3DColor + + + False + False + + + + + True + .uno:ExtrusionSurfaceFloater + + + False + False + + + + + 0 + 1 + + + + + False @@ -12060,674 +10461,6 @@ 4 - - - True - False - center - True - - - True - False - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectForwardOne - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectBackOne - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:FormatGroup - - - True - True - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:EnterGroup - - - True - True - - - - - False - True - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:LeaveGroup - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ExtrusionToggle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:ExtrusionDepthFloater - - - True - True - - - - - True - .uno:ExtrusionDirectionFloater - - - True - True - - - - - True - .uno:Extrusion3DColor - - - False - False - - - - - True - .uno:ExtrusionSurfaceFloater - - - False - False - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:FontworkGalleryFloater - - - True - True - - - - - False - True - 1 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - icons - False - - - True - .uno:FontworkShapeType - - - True - True - - - - - True - .uno:FontworkSameLetterHeights - - - True - True - - - - - False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:FontworkAlignmentFloater - - - True - True - - - - - True - .uno:FontworkCharacterSpacingFloater - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 11 - - True @@ -12738,29 +10471,29 @@ True - False + False end center True True - False + False center True vertical - _Draw + _Draw True - True - False - False + True + False + False end center True none - True + True False @@ -12771,17 +10504,17 @@ True - True + True end True - icons - False + icons + False 1 - + True center - .uno:FormatArea + .uno:FormatArea False @@ -12789,10 +10522,10 @@ - + True center - .uno:FormatLine + .uno:FormatLine False @@ -12800,10 +10533,10 @@ - + True center - .uno:TransformDialog + .uno:TransformDialog False @@ -12828,38 +10561,21 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 8 + 9 True - False - ~Draw - True + False + ~Draw + True - 8 - False + 9 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True - center + False + end True - both - False - 3 + Object + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False + icons + False - + True center True - .uno:AssignMacro + .uno:ToggleObjectRotateMode + + + False + False + + + + + True + .uno:FlipVertical + + + False + False + + + + + True + .uno:FlipHorizontal False @@ -12911,94 +10685,65 @@ - False - True - 0 + 1 + 1 - + True - False + False center - vertical + True + both + False + 3 - + True - True center True - both-horiz - False - - - True - .uno:OriginalSize - - - False - True - - + .uno:AssignMacro False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - True - .uno:FlipVertical - - - False - True - - - - - True - .uno:FlipHorizontal - - - False - True - - - - - False - True - 1 + False - False - True - 2 + 0 + 0 + 2 + + + True + True + center + True + both-horiz + False + + + True + .uno:OriginalSize + + + False + True + + + + + 1 + 0 + + + + + False @@ -13007,84 +10752,198 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Fill & Border + + + + + + + - False - True - 5 - 0 + 0 + 2 + 3 - + True - False + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + text + False - + True - True - text - False - - - True - .uno:FormatLine - - - True - True - - + .uno:FormatArea False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 + False - False - True - 1 + 0 + 1 + + + True + False + both-horiz + False + + + True + .uno:FillStyle + + + False + True + + + + + 1 + 1 + 2 + + + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + False @@ -13093,125 +10952,255 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Positioning + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + end + 5 + 5 vertical + + + 4 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - + center + True + .uno:AnchorMenu False - True - 0 - - - - - True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - - - - True - True - 1 + False - False - True - 2 + 0 + 0 + 2 + + + True + False + icons + False + + + True + .uno:ObjectAlignLeft + + + False + True + + + + + True + .uno:AlignCenter + + + False + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + 1 + 1 + + + + + True + False + icons + False + + + True + .uno:BringToFront + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectForwardOne + + + False + True + + + + + 3 + 0 + + + + + True + False + icons + False + + + True + .uno:SendToBack + + + False + True + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectBackOne + + + False + True + + + + + 3 + 1 + + + + + False @@ -13219,371 +11208,6 @@ 2 - - - True - False - center - True - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - Convert - 70 - True - True - True - .uno:ChangeBezier - changebezierImg - none - True - top - True - - - False - True - 1 - - - - - True - False - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectForwardOne - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectBackOne - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 5 - - True @@ -13594,29 +11218,29 @@ True - False + False end center True True - False + False center True vertical - _Object + _Object True - True - False - False + True + False + False end center True none - True + True False @@ -13627,17 +11251,17 @@ True - True + True end True - icons - False + icons + False 1 - + True center - .uno:FormatArea + .uno:FormatArea False @@ -13645,10 +11269,10 @@ - + True center - .uno:FormatLine + .uno:FormatLine False @@ -13656,10 +11280,10 @@ - + True center - .uno:TransformDialog + .uno:TransformDialog False @@ -13684,79 +11308,102 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 9 + 10 True - False - ~Object - True + False + ~Object + True - 9 - False + 10 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Media + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + True center True - both - False + both + False 3 - + True center True - .uno:AssignMacro + .uno:AssignMacro True @@ -13765,70 +11412,14 @@ - False - True - 1 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:AVMediaPlayer - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 + 0 + 0 + 2 + + + False @@ -13837,41 +11428,239 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Positioning + + + + + + + - False - True - 5 - 0 + 0 + 2 + 4 - + True - True + False + end + 5 + 5 + vertical + + + 4 + 0 + 3 + + + + + True + False + icons + False + + + True + .uno:ObjectAlignLeft + + + False + True + + + + + True + .uno:AlignCenter + + + False + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + 1 + 1 + + + + + True + False + icons + False + + + True + .uno:BringToFront + + + False + True + + + + + 2 + 0 + + + + + True + False + icons + False + + + True + .uno:SendToBack + + + False + True + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectForwardOne + + + False + True + + + + + 3 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectBackOne + + + False + True + + + + + 3 + 1 + + + + + True + True center True - both - False + both + False 3 - + True center True - .uno:AnchorMenu + .uno:AnchorMenu False @@ -13880,14 +11669,14 @@ - False - True - 1 + 0 + 0 + 2 - + + + False @@ -13896,359 +11685,103 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Media Player + + + + + + + - False - True - 5 - 0 + 0 + 2 - + True - False + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + 200 + True + False + False - + True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - + .uno:AVMediaToolBox False - True - 0 + True - False - True - 1 + 0 + 0 - + + + True + False + both-horiz + False + + + True + .uno:AVMediaPlayer + + + False + True + + + + + 0 + 1 + + + + + False True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectForwardOne - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectBackOne - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - vertical - - - 148 - True - True - False - - - True - .uno:AVMediaToolBox - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:AVMediaPlayer - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 6 + 2 @@ -14261,27 +11794,27 @@ True - False + False end center True True - False + False center True vertical - _Media + _Media True - True - False - False + True + False + False end none - True + True False @@ -14292,17 +11825,17 @@ True - True + True end True - icons - False + icons + False 1 - + True center - .uno:FormatArea + .uno:FormatArea False @@ -14310,10 +11843,10 @@ - + True center - .uno:FormatLine + .uno:FormatLine False @@ -14321,10 +11854,10 @@ - + True center - .uno:TransformDialog + .uno:TransformDialog False @@ -14349,76 +11882,100 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 10 + 11 True - False - ~Media - True + False + ~Media + True - 10 - False + 11 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Page + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + True center True - both - False + both + False 3 - + True - .uno:PageFormatDialog + .uno:PageFormatDialog False @@ -14427,270 +11984,267 @@ - False - False - 0 + 0 + 0 + 2 - + True - False - center - True - vertical + True + both-horiz + False - + True - True - both-horiz - False - - - True - .uno:Margins - - - False - True - - + .uno:Margins False - False - 0 - - - - - True - True - both-horiz - False - - - True - .uno:EditHeaderAndFooter - - - False - True - - - - - False - False - 1 + True - False - True - 1 + 1 + 0 - + True - False - 5 - 5 - vertical + True + both-horiz + False + + + True + .uno:EditHeaderAndFooter + + + False + True + + - False - True - 5 - 2 + 1 + 1 - + + + False - False + True 0 - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end True - vertical - - - True - True - icons - False - - - True - .uno:FirstPage - - - False - True - - - - - True - .uno:PreviousPage - - - False - True - - - - - True - .uno:NextPage - - - False - True - - - - - True - .uno:LastPage - - - False - True - - - - - False - False - 0 - - - - - True - False - center - True - - - True - True - icons - False - - - True - .uno:ZoomMinus - - - False - True - - - - - False - False - 0 - - - - - True - True - icons - False - - - True - .uno:ZoomPlus - - - False - True - - - - - False - False - end - 1 - - - - - False - True - 2 - - + Zoom + + + + + + + - False - True - 0 + 0 + 2 - + True - False - 5 - 5 + False + end + 5 + 5 vertical - False - True - 5 - 3 + 1 + 0 + 3 + + + True + False + icons + False + + + True + .uno:ZoomMinus + + + False + True + + + + + True + .uno:ZoomPlus + + + False + True + + + + + 0 + 1 + + + + + True + False + + + True + .uno:FirstPage + True + + + False + True + + + + + True + .uno:PreviousPage + True + + + False + True + + + + + True + .uno:NextPage + True + + + False + True + + + + + True + .uno:LastPage + True + + + False + True + + + + + 0 + 0 + + + + + False - False + True 1 - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Print + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 + vertical + + + 3 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:Print + .uno:Print False @@ -14699,25 +12253,23 @@ - False - False - 5 - 0 + 0 + 0 + 2 - + True - True + False center True - both - False - 3 + both-horiz + False - + True - .uno:ClosePreview + .uno:TogglePrintGrid False @@ -14726,18 +12278,174 @@ - False - False - 1 + 1 + 0 + + + True + False + center + True + both-horiz + False + + + True + .uno:TogglePrintColRowHeader + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:TogglePrintComments + + + False + True + + + + + 2 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:TogglePrintZeroValues + + + False + True + + + + + 2 + 1 + + + + + False - False + True 2 + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:ClosePreview + + + False + True + + + + + 0 + 0 + 2 + + + + + True + False + end + True + + + + + + + + + + + 0 + 2 + + + + + + + + False + True + 3 + + True @@ -14748,28 +12456,28 @@ True - False + False end center True True - False + False center True vertical - _Print + _Print True - True - False - False + True + False + False end True none - True + True False @@ -14780,16 +12488,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 - + True - .uno:FullScreen + .uno:FullScreen True @@ -14814,76 +12522,100 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 11 + 12 True - False - ~Print - True + False + ~Print + True - 11 - False + 12 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Mode + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:SwitchControlDesignMode + .uno:SwitchControlDesignMode False @@ -14892,11 +12624,62 @@ - False - True - 0 + 0 + 0 + 2 + + + True + False + center + True + both-horiz + False + + + True + .uno:UseWizards + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:GroupBox + + + False + True + + + + + 1 + 1 + + + + + False @@ -14905,78 +12688,187 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end True + Properties + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:UseWizards - - - False - True - - + .uno:FormProperties False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:GroupBox - - - False - True - - - - - False - False - 1 + True - False - True - 1 + 0 + 0 - + + + True + False + both-horiz + False + + + True + .uno:ShowFmExplorer + + + False + True + + + + + 0 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:TabDialog + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:OpenReadOnly + + + False + True + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ControlProperties + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:AutoControlFocus + + + False + True + + + + + 2 + 1 + + + + + False @@ -14985,86 +12877,307 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center + False + end True + Controls + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + icons + False - + True - True - both-horiz - False - - - True - .uno:FormProperties - - - False - True - - + .uno:Label False - True - 0 + True - + True - True - both-horiz - False - - - True - .uno:ShowFmExplorer - - - False - True - - + .uno:Edit False - True - 1 + True + + + + + True + .uno:CheckBox + + + False + True - False - True - 1 + 0 + 0 + + + True + False + icons + False + + + True + .uno:RadioButton + + + False + True + + + + + True + .uno:ListBox + + + False + True + + + + + True + .uno:ComboBox + + + False + True + + + + + 0 + 1 + + + + + True + False + icons + False + + + True + .uno:NumericField + + + False + True + + + + + True + .uno:CurrencyField + + + False + True + + + + + True + .uno:PatternField + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:FormattedField + + + False + True + + + + + True + .uno:DateField + + + False + True + + + + + True + .uno:TimeField + + + False + True + + + + + 1 + 1 + + + + + True + False + icons + False + + + True + .uno:Pushbutton + + + False + True + + + + + True + .uno:Imagebutton + + + False + True + + + + + True + .uno:ImageControl + + + False + True + + + + + 2 + 0 + + + + + True + False + icons + False + + + True + .uno:FileControl + + + False + True + + + + + True + .uno:NavigationBar + + + False + True + + + + + True + .uno:Grid + + + False + True + + + + + 2 + 1 + + + + + False @@ -15072,563 +13185,6 @@ 2 - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:TabDialog - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:OpenReadOnly - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ControlProperties - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:AutoControlFocus - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Label - - - False - True - - - - - True - .uno:Edit - - - False - True - - - - - True - .uno:CheckBox - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:RadioButton - - - False - True - - - - - True - .uno:ListBox - - - False - True - - - - - True - .uno:ComboBox - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:NumericField - - - False - True - - - - - True - .uno:CurrencyField - - - False - True - - - - - True - .uno:PatternField - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FormattedField - - - False - True - - - - - True - .uno:DateField - - - False - True - - - - - True - .uno:TimeField - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Pushbutton - - - False - True - - - - - True - .uno:Imagebutton - - - False - True - - - - - True - .uno:ImageControl - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FileControl - - - False - True - - - - - True - .uno:NavigationBar - - - False - True - - - - - True - .uno:Grid - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - True @@ -15639,29 +13195,29 @@ True - False + False end center True True - False + False center True vertical - Fo_rm + Fo_rm True - True - False - False + True + False + False end center True none - True + True False @@ -15672,16 +13228,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 - + True - .uno:FormProperties + .uno:FormProperties False @@ -15706,61 +13262,44 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 12 + 13 True - False - Fo~rm - True + False + Fo~rm + True - 12 - False + 13 + False - + True - False + False - + True - False + False center True True - False + False center True @@ -15780,29 +13319,29 @@ True - False + False end center True True - False + False center True vertical - E_xtension + E_xtension True - True - False - False + True + False + False end center True none - True + True False @@ -15813,11 +13352,11 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 @@ -15837,24 +13376,24 @@ False False - end + end 1 True - False + False end - 5 - 5 + 5 + 5 vertical False True 5 - end + end 2 @@ -15866,44 +13405,85 @@ True - False - E~xtension - True + False + E~xtension + True 14 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Macro + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:RunMacro + .uno:RunMacro False @@ -15912,11 +13492,57 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:BasicIDEAppear + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + + + True + .uno:MacroDialog + + + False + True + + + + + 1 + 1 + + + + + False @@ -15925,115 +13551,65 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center + False + end True - vertical - - - True - True - both-horiz - False - - - True - .uno:BasicIDEAppear - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:MacroDialog - - - False - True - - - - - False - True - 1 - - + AutoCorrection + + + + + + + - False - True - 2 - - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 0 + 1 + 1 - + True - True + False + end + 5 + 5 + vertical + + + 1 + 0 + 2 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:AuditingFillMode + .uno:AutoCorrectDlg False @@ -16042,995 +13618,18 @@ - False - True - 1 + 0 + 0 + + + False True - 2 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ShowPrecedents - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ShowDependents - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ClearArrowPrecedents - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ClearArrowDependents - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:GoalSeekDialog - - - False - True - - - - - False - True - 1 - - - - - False - True - 5 - - - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:SolverDialog - - - False - True - - - - - False - True - 2 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ShowErrors - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ShowInvalid - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SwitchControlDesignMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:UseWizards - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:GroupBox - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Label - - - False - True - - - - - True - .uno:Edit - - - False - True - - - - - True - .uno:CheckBox - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:RadioButton - - - False - True - - - - - True - .uno:ListBox - - - False - True - - - - - True - .uno:ComboBox - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:NumericField - - - False - True - - - - - True - .uno:CurrencyField - - - False - True - - - - - True - .uno:PatternField - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FormattedField - - - False - True - - - - - True - .uno:DateField - - - False - True - - - - - True - .uno:TimeField - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Pushbutton - - - False - True - - - - - True - .uno:Imagebutton - - - False - True - - - - - True - .uno:ImageControl - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FileControl - - - False - True - - - - - True - .uno:NavigationBar - - - False - True - - - - - True - .uno:Grid - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:FormProperties - - - False - True - - - - - True - .uno:TabDialog - - - False - True - - - - - True - .uno:ControlProperties - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:ShowFmExplorer - - - False - True - - - - - True - .uno:OpenReadOnly - - - False - True - - - - - True - .uno:AutoControlFocus - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 13 + 0 @@ -17043,29 +13642,29 @@ True - False + False end center True True - False + False center True vertical - _Tools + _Tools True - True - False - False + True + False + False end center True none - True + True False @@ -17076,16 +13675,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 - + True - .uno:OptionsTreeDialog + .uno:OptionsTreeDialog False @@ -17110,42 +13709,25 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 13 + 15 True - False - ~Tools - True + False + ~Tools + True - 13 - False + 15 + False @@ -17157,35 +13739,9 @@ - 0 - 0 + 0 + 0 - - vertical - True - - - - - - - - - - - - vertical - True - - - - - - - - - - diff --git a/sc/uiconfig/scalc/ui/notebookbar_compact.ui b/sc/uiconfig/scalc/ui/notebookbar_compact.ui index 1311c069784d..2f8870b0d685 100644 --- a/sc/uiconfig/scalc/ui/notebookbar_compact.ui +++ b/sc/uiconfig/scalc/ui/notebookbar_compact.ui @@ -1049,13 +1049,6 @@ .uno:QuestionAnswers - - - True - False - .uno:SendFeedback - - True @@ -4737,7 +4730,8 @@ - False + False + False center True @@ -7410,9 +7404,9 @@ both-horiz False - + True - .uno:SpellingAndGrammarDialog + .uno:SpellDialog False diff --git a/sc/uiconfig/scalc/ui/notebookbar_groupedbar_compact.ui b/sc/uiconfig/scalc/ui/notebookbar_groupedbar_compact.ui index 4ef813e77cb9..cb01b04f8a1a 100644 --- a/sc/uiconfig/scalc/ui/notebookbar_groupedbar_compact.ui +++ b/sc/uiconfig/scalc/ui/notebookbar_groupedbar_compact.ui @@ -3008,10 +3008,10 @@ True False - + True False - .uno:SpellingAndGrammarDialog + .uno:SpellDialog @@ -4533,9 +4533,9 @@ icons False - + True - .uno:SpellingAndGrammarDialog + .uno:SpellDialog False diff --git a/sc/uiconfig/scalc/ui/notebookbar_groupedbar_full.ui b/sc/uiconfig/scalc/ui/notebookbar_groupedbar_full.ui index 2b2b85d452b4..676574354e17 100644 --- a/sc/uiconfig/scalc/ui/notebookbar_groupedbar_full.ui +++ b/sc/uiconfig/scalc/ui/notebookbar_groupedbar_full.ui @@ -1764,13 +1764,6 @@ .uno:QuestionAnswers - - - True - False - .uno:SendFeedback - - True @@ -1976,10 +1969,10 @@ True False - + True False - .uno:SpellingAndGrammarDialog + .uno:SpellDialog @@ -5198,9 +5191,9 @@ - + True - .uno:SpellingAndGrammarDialog + .uno:SpellDialog False @@ -6425,9 +6418,9 @@ both-horiz False - + True - .uno:SpellingAndGrammarDialog + .uno:SpellDialog False diff --git a/sc/uiconfig/scalc/ui/notebookbar_online.ui b/sc/uiconfig/scalc/ui/notebookbar_online.ui deleted file mode 100644 index 2a538a2fead7..000000000000 --- a/sc/uiconfig/scalc/ui/notebookbar_online.ui +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - True - False - - - True - False - vertical - - - True - True - True - - - True - True - .uno:CharFontName - - - True - True - - - - - True - True - 0 - - - - - True - True - 5 - - - True - .uno:FontHeight - - - True - True - - - - - False - True - 1 - - - - - True - True - icons - False - - - True - .uno:NumberFormatType - - - True - True - - - - - 0 - 0 - - - True - - - True - .uno:NumberFormatCurrency - - - True - True - - - - - False - True - 2 - - - - - True - True - center - True - icons - False - - - True - .uno:CurrentSheetView - - - True - True - - - - - True - True - 3 - - - - - True - True - center - True - both - False - - - True - .uno:DatabaseSettings - - - True - True - - - - - True - True - 3 - - - - - 0 - 0 - - - - diff --git a/sc/uiconfig/scalc/ui/onlyactivesheetsaveddialog.ui b/sc/uiconfig/scalc/ui/onlyactivesheetsaveddialog.ui deleted file mode 100644 index 7167588ae610..000000000000 --- a/sc/uiconfig/scalc/ui/onlyactivesheetsaveddialog.ui +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - False - 12 - False - True - dialog - - - False - vertical - 2 - - - False - True - end - - - _Show this message again - True - True - False - True - True - True - - - True - True - 0 - True - - - - - _OK - True - True - True - True - True - - - False - True - 1 - - - - - False - False - 0 - - - - - - True - False - - - True - False - 12 - Warning - - - - - - - static - - - - - 1 - 0 - - - - - True - False - - - 1 - 1 - - - - - True - False - True - Only the active sheet was saved. - - - static - - - - - 1 - 2 - - - - - True - False - center - center - 12 - help/warning_large.png - - - Warning image - - - - - 0 - 0 - 3 - - - - - True - True - 1 - - - - - - btnOk - - - diff --git a/sc/uiconfig/scalc/ui/optcalculatepage.ui b/sc/uiconfig/scalc/ui/optcalculatepage.ui index dcf3650de8dd..3e60d8ffea8a 100644 --- a/sc/uiconfig/scalc/ui/optcalculatepage.ui +++ b/sc/uiconfig/scalc/ui/optcalculatepage.ui @@ -14,7 +14,7 @@ 1 10 - + True False @@ -24,39 +24,41 @@ 12 24 - + True False 0 none - - + + True False 12 6 - True - 6 - 12 - - Enable multi-threaded calculation + + Enable w_ildcards in formulas True True False - Enable multi-threaded calculation of formula-groups + Enable wildcards for interoperability with Microsoft Excel True + True True + + + Specifies that wildcards are enabled when searching and also for character string comparisons. + + 1 0 - 2 - + False True center @@ -65,22 +67,49 @@ 0 - 0 + 1 - - Allow use of OpenCL + + Enable r_egular expressions in formulas True True False + True True + formulawildcards + + + Specifies that regular expressions instead of simple wildcards are enabled when searching and also for character string comparisons. + + 1 1 + + + No wildcards or regular expressions in formulas + True + True + False + True + True + formulawildcards + + + Specifies that only literal strings are used when searching and also for character string comparisons. + + + + + 1 + 2 + + @@ -90,10 +119,10 @@ - + True False - CPU Threading Settings + Formulas Wildcards @@ -102,8 +131,120 @@ 0 - 3 - 2 + 0 + + + + + True + False + 0 + none + + + + True + False + 12 + 6 + + + 1899-12-30 (defa_ult) + True + True + False + Value 0 corresponds to 1899-12-30 + True + True + True + + + Sets 1899-12-30 as day zero. + + + + + 1 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + 1900-01-01 (Star_Calc 1.0) + True + True + False + Value 0 corresponds to 1900-01-01 + True + True + datestd + + + Sets 1900-01-01 as day zero. Use this setting for StarCalc 1.0 spreadsheets containing date entries. + + + + + 1 + 1 + + + + + _1904-01-01 + True + True + False + 0 corresponds to 1904-01-01 + True + True + datestd + + + Sets 1904-01-01 as day zero. Use this setting for spreadsheets that are imported in a foreign format. + + + + + 1 + 2 + + + + + + + + + + + + + True + False + Date + + + + + + + + 1 + 0 @@ -120,6 +261,19 @@ 12 6 True + + + False + True + center + center + res/lock.png + + + 0 + 0 + + Case se_nsitive @@ -140,6 +294,19 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + _Precision as shown @@ -159,6 +326,19 @@ 1 + + + False + True + center + center + res/lock.png + + + 0 + 2 + + Search criteria = and <> must apply to _whole cells @@ -179,6 +359,19 @@ 2 + + + False + True + center + center + res/lock.png + + + 0 + 3 + + _Automatically find column and row labels @@ -198,6 +391,19 @@ 3 + + + False + True + center + center + res/lock.png + + + 0 + 4 + + _Limit decimals for general number format @@ -217,6 +423,19 @@ 4 + + + False + True + center + center + res/lock.png + + + 0 + 5 + + True @@ -262,84 +481,6 @@ 5 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 3 - - - - - False - True - center - center - res/lock.png - - - 0 - 4 - - - - - False - True - center - center - res/lock.png - - - 0 - 5 - - @@ -425,6 +566,19 @@ 18 3 6 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + True @@ -439,20 +593,6 @@ 0 - - - True - False - _Minimum change: - True - minchange - 0 - - - 1 - 1 - - True @@ -471,6 +611,33 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + True + False + _Minimum change: + True + minchange + 0 + + + 1 + 1 + + True @@ -489,32 +656,6 @@ 1 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - False @@ -535,238 +676,93 @@ + + 1 + 1 + + + + + True + False + 0 + none + + + + True + False + 12 + 6 + True + 6 + 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + Enable multi-threaded calculation + True + True + False + Enable multi-threaded calculation of formula-groups + True + True + + + 1 + 0 + 2 + + + + + Allow use of OpenCL + True + True + False + True + + + 1 + 1 + + + + + + + + + + + + + True + False + CPU Threading Settings + + + + + + 0 2 2 - - - True - False - 0 - none - - - - True - False - 12 - 6 - - - 1899-12-30 (defa_ult) - True - True - False - Value 0 corresponds to 1899-12-30 - True - True - True - - - Sets 1899-12-30 as day zero. - - - - - 1 - 0 - - - - - 1900-01-01 (Star_Calc 1.0) - True - True - False - Value 0 corresponds to 1900-01-01 - True - True - datestd - - - Sets 1900-01-01 as day zero. Use this setting for StarCalc 1.0 spreadsheets containing date entries. - - - - - 1 - 1 - - - - - _1904-01-01 - True - True - False - 0 corresponds to 1904-01-01 - True - True - datestd - - - Sets 1904-01-01 as day zero. Use this setting for spreadsheets that are imported in a foreign format. - - - - - 1 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - - - - - - - - - True - False - Date - - - - - - - - 1 - 0 - - - - - True - False - 0 - none - - - - True - False - 12 - 6 - - - Enable w_ildcards in formulas - True - True - False - Enable wildcards for interoperability with Microsoft Excel - True - True - True - - - Specifies that wildcards are enabled when searching and also for character string comparisons. - - - - - 1 - 0 - - - - - Enable r_egular expressions in formulas - True - True - False - True - True - formulawildcards - - - Specifies that regular expressions instead of simple wildcards are enabled when searching and also for character string comparisons. - - - - - 1 - 1 - - - - - No wildcards or regular expressions in formulas - True - True - False - True - True - formulawildcards - - - Specifies that only literal strings are used when searching and also for character string comparisons. - - - - - 1 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - - - - - - - - - True - False - Formulas Wildcards - - - - - - - - 0 - 0 - - - - - diff --git a/sc/uiconfig/scalc/ui/optchangespage.ui b/sc/uiconfig/scalc/ui/optchangespage.ui index 69df07673ddb..14690ae2092b 100644 --- a/sc/uiconfig/scalc/ui/optchangespage.ui +++ b/sc/uiconfig/scalc/ui/optchangespage.ui @@ -25,6 +25,19 @@ True 6 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + True @@ -39,48 +52,6 @@ 0 - - - True - False - _Deletions: - True - deletions - 0 - - - 1 - 1 - - - - - True - False - _Insertions: - True - insertions - 0 - - - 1 - 2 - - - - - True - False - _Moved entries: - True - entries - 0 - - - 1 - 3 - - True @@ -104,6 +75,33 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + True + False + _Deletions: + True + deletions + 0 + + + 1 + 1 + + True @@ -128,26 +126,30 @@ - - True + False - False - True - 0 - True - - - - - - - Specifies the color to highlight moved cell contents. - - + True + center + center + res/lock.png - 2 - 3 + 0 + 2 + + + + + True + False + _Insertions: + True + insertions + 0 + + + 1 + 2 @@ -173,45 +175,6 @@ 2 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - False @@ -225,6 +188,43 @@ 3 + + + True + False + _Moved entries: + True + entries + 0 + + + 1 + 3 + + + + + True + False + False + True + 0 + True + + + + + + + Specifies the color to highlight moved cell contents. + + + + + 2 + 3 + + diff --git a/sc/uiconfig/scalc/ui/optdefaultpage.ui b/sc/uiconfig/scalc/ui/optdefaultpage.ui index 9f971d2af8bb..23be61274497 100644 --- a/sc/uiconfig/scalc/ui/optdefaultpage.ui +++ b/sc/uiconfig/scalc/ui/optdefaultpage.ui @@ -29,6 +29,19 @@ 6 6 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + True @@ -43,6 +56,33 @@ 0 + + + True + True + start + True + True + adjustment1 + + + 2 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 1 + + True @@ -71,17 +111,16 @@ - - True - True - start - True - True - adjustment1 + + False + True + center + center + res/lock.png - 2 - 0 + 0 + 2 @@ -99,45 +138,6 @@ 2 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - diff --git a/sc/uiconfig/scalc/ui/optformula.ui b/sc/uiconfig/scalc/ui/optformula.ui index 4b4592d77f21..8b1b7b14a05d 100644 --- a/sc/uiconfig/scalc/ui/optformula.ui +++ b/sc/uiconfig/scalc/ui/optformula.ui @@ -23,20 +23,6 @@ 12 6 6 - - - Use English function names - True - True - False - True - True - - - 0 - 1 - - @@ -44,17 +30,6 @@ False True 12 - - - True - False - True - - - 1 - 0 - - True @@ -68,12 +43,37 @@ 0 + + + True + False + True + + + 1 + 0 + + 0 0 + + + Use English function names + True + True + False + True + True + + + 0 + 1 + + @@ -93,27 +93,29 @@ - + True False + True 0 none - - + + True False 12 6 + True 6 12 - + True False - Excel 2007 and newer: + _Function: True - ooxmlrecalc + function 0 @@ -122,29 +124,14 @@ - + True - False - ODF spreadsheet (not saved by %PRODUCTNAME): - True - odfrecalc - 0 - - - 0 - 1 - - - - - True - False - True - - Always recalculate - Never recalculate - Prompt user - + True + 1 + True + 5 + 1 + True 1 @@ -152,15 +139,28 @@ - + True False - True - - Always recalculate - Never recalculate - Prompt user - + Array co_lumn: + True + arraycolumn + 0 + + + 0 + 1 + + + + + True + True + 1 + True + 5 + 1 + True 1 @@ -168,12 +168,12 @@ - + True False - Optimal row height: + Array _row: True - odfrecalc + arrayrow 0 @@ -182,33 +182,47 @@ - + True - False - True - - Always recalculate - Never recalculate - Prompt user - - - - Define either we want to calculate the optimal row heights or we do not want at load time. - - + True + 1 + True + 5 + 1 + True 1 2 + + + Rese_t Separators Settings + True + True + True + end + True + + + 2 + 2 + + + + + + + + - + True False - Recalculation on File Load + Separators @@ -217,7 +231,7 @@ 0 - 3 + 1 @@ -310,29 +324,27 @@ - + True False - True 0 none - - + + True False 12 6 - True 6 12 - + True False - _Function: + Excel 2007 and newer: True - function + ooxmlrecalc 0 @@ -341,42 +353,15 @@ - + True False - Array co_lumn: - True - arraycolumn - 0 - - - 0 - 1 - - - - - True - False - Array _row: - True - arrayrow - 0 - - - 0 - 2 - - - - - True - True - 1 - True - 5 - 1 - True + True + + Always recalculate + Never recalculate + Prompt user + 1 @@ -384,14 +369,29 @@ - + True - True - 1 - True - 5 - 1 - True + False + ODF spreadsheet (not saved by %PRODUCTNAME): + True + odfrecalc + 0 + + + 0 + 1 + + + + + True + False + True + + Always recalculate + Never recalculate + Prompt user + 1 @@ -399,47 +399,47 @@ - + True - True - 1 - True - 5 - 1 - True + False + Optimal row height: + True + odfrecalc + 0 + + + 0 + 2 + + + + + True + False + True + + Always recalculate + Never recalculate + Prompt user + + + + Define either we want to calculate the optimal row heights or we do not want at load time. + + 1 2 - - - Rese_t Separators Settings - True - True - True - end - True - - - 2 - 2 - - - - - - - - - + True False - Separators + Recalculation on File Load @@ -448,7 +448,7 @@ 0 - 1 + 3 diff --git a/sc/uiconfig/scalc/ui/optsortlists.ui b/sc/uiconfig/scalc/ui/optsortlists.ui index 9b40cf403d96..bd8a48c2b0ab 100644 --- a/sc/uiconfig/scalc/ui/optsortlists.ui +++ b/sc/uiconfig/scalc/ui/optsortlists.ui @@ -1,5 +1,5 @@ - + @@ -26,70 +26,6 @@ True 12 12 - - - _Copy - True - True - True - True - - - Copies the contents of the cells in the Copy list from box. If you select a reference to related rows and columns, the Copy List dialog appears after clicking the button. You can use this dialog to define if the reference is converted to sort lists by row or by column. - - - - - 1 - 1 - - - - - True - False - True - 12 - - - True - False - Copy list _from: - True - copyfrom - - - False - True - 0 - - - - - True - True - center - True - True - True - - - Defines the spreadsheet and the cells to copy, in order to include them in the Lists box. The currently selected range in the spreadsheet is the default. - - - - - True - True - 1 - - - - - 0 - 1 - - @@ -182,6 +118,7 @@ True True True + False Displays the content of the currently selected list. This content can be edited. @@ -299,6 +236,70 @@ 0 + + + True + False + True + 12 + + + True + False + Copy list _from: + True + copyfrom + + + False + True + 0 + + + + + True + True + center + True + True + True + + + Defines the spreadsheet and the cells to copy, in order to include them in the Lists box. The currently selected range in the spreadsheet is the default. + + + + + True + True + 1 + + + + + 0 + 1 + + + + + _Copy + True + True + True + True + + + Copies the contents of the cells in the Copy list from box. If you select a reference to related rows and columns, the Copy List dialog appears after clicking the button. You can use this dialog to define if the reference is converted to sort lists by row or by column. + + + + + 1 + 1 + + False diff --git a/sc/uiconfig/scalc/ui/pagetemplatedialog.ui b/sc/uiconfig/scalc/ui/pagetemplatedialog.ui index e14866b40d9e..c4d7b23135f1 100644 --- a/sc/uiconfig/scalc/ui/pagetemplatedialog.ui +++ b/sc/uiconfig/scalc/ui/pagetemplatedialog.ui @@ -108,7 +108,6 @@ True True left - left True @@ -120,7 +119,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/paradialog.ui b/sc/uiconfig/scalc/ui/paradialog.ui index a3f45042335c..8710a2ef3f1d 100644 --- a/sc/uiconfig/scalc/ui/paradialog.ui +++ b/sc/uiconfig/scalc/ui/paradialog.ui @@ -103,7 +103,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/paratemplatedialog.ui b/sc/uiconfig/scalc/ui/paratemplatedialog.ui index 92a2017ec116..76c654b4067f 100644 --- a/sc/uiconfig/scalc/ui/paratemplatedialog.ui +++ b/sc/uiconfig/scalc/ui/paratemplatedialog.ui @@ -108,7 +108,6 @@ True left True - left False @@ -119,7 +118,7 @@ - reset + reset standard ok cancel diff --git a/sc/uiconfig/scalc/ui/pivotcalcfielddialog.ui b/sc/uiconfig/scalc/ui/pivotcalcfielddialog.ui index 59964b153e2d..f588ec546df5 100644 --- a/sc/uiconfig/scalc/ui/pivotcalcfielddialog.ui +++ b/sc/uiconfig/scalc/ui/pivotcalcfielddialog.ui @@ -176,6 +176,7 @@ True + True False diff --git a/sc/uiconfig/scalc/ui/pivotfielddialog.ui b/sc/uiconfig/scalc/ui/pivotfielddialog.ui index 375d18272542..b3fa2e10060b 100644 --- a/sc/uiconfig/scalc/ui/pivotfielddialog.ui +++ b/sc/uiconfig/scalc/ui/pivotfielddialog.ui @@ -1,5 +1,5 @@ - + @@ -11,31 +11,31 @@ - False - 6 + False + 6 Data Field True - 0 - 0 - dialog + 0 + 0 + dialog - False + False True True vertical 12 - False - end + False + end _Options... True - True - True - True + True + True + True Opens the Data Field Options dialog. The Options button is visible for filters and column or row fields only. @@ -52,10 +52,10 @@ _OK True - True - True - True - True + True + True + True + True True @@ -68,9 +68,9 @@ _Cancel True - True - True - True + True + True + True True @@ -83,8 +83,8 @@ _Help True - True - True + True + True True @@ -98,99 +98,99 @@ False True - end + end 0 - + True - False + False True True - 12 + 12 True - False + False True True - 0 - none + 0 + none - + True - False - True - True - 6 + False 12 6 + True + True + 6 _None True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 _Automatic True - True - False - True - True + True + False + True + True none - 0 - 1 + 0 + 1 _User-defined True - True - False - True - True + True + False + True + True none - 0 - 2 + 0 + 2 True - True + True True True - in + in True - True - True + True + True True True liststore2 - False - 1 - False + False + 1 + False @@ -215,8 +215,8 @@ - 0 - 3 + 0 + 3 @@ -224,7 +224,7 @@ True - False + False Subtotals @@ -233,18 +233,18 @@ - 0 - 0 + 0 + 0 Show it_ems without data True - True - False - True - True + True + False + True + True Includes empty columns and rows in the results table. @@ -252,43 +252,43 @@ - 0 - 1 + 0 + 1 - + True - False - 12 + False + 12 True - False + False Name: 0 - 0 - 0 + 0 + 0 True - False + False 0 - 1 - 0 + 1 + 0 - 0 - 2 + 0 + 2 @@ -305,8 +305,5 @@ cancel help - - - diff --git a/sc/uiconfig/scalc/ui/printareasdialog.ui b/sc/uiconfig/scalc/ui/printareasdialog.ui index 3f1ba9b629df..cb5638be3071 100644 --- a/sc/uiconfig/scalc/ui/printareasdialog.ui +++ b/sc/uiconfig/scalc/ui/printareasdialog.ui @@ -1,32 +1,32 @@ - + - False - 6 + False + 6 Edit Print Ranges False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -44,8 +44,8 @@ _Cancel True - True - True + True + True True @@ -63,8 +63,8 @@ _Help True - True - True + True + True True @@ -78,76 +78,38 @@ False True - end + end 0 True - False + False True vertical 12 True - False + False True - 0 - none + 0 + none - + True - False - True - 6 - 12 + False 12 6 - - - True - False - False - - - - - - Click the Shrink icon to reduce the dialog to the size of the input field. It is then easier to mark the required reference in the sheet. The icons then automatically convert to the Maximize icon. Click it to restore the dialog to its original size. - - - - - 2 - 0 - - - - - True - True - True - True - 50 - True - - - Allows you to modify a defined print range. - - - - - 1 - 0 - - + True + 6 + 12 True - False + False - none - - entire sheet - @@ -161,8 +123,46 @@ - 0 - 0 + 0 + 0 + + + + + True + True + True + True + 50 + True + + + Allows you to modify a defined print range. + + + + + 1 + 0 + + + + + True + False + False + + + + + + Click the Shrink icon to reduce the dialog to the size of the input field. It is then easier to mark the required reference in the sheet. The icons then automatically convert to the Maximize icon. Click it to restore the dialog to its original size. + + + + + 2 + 0 @@ -170,7 +170,7 @@ True - False + False Print Range @@ -187,62 +187,24 @@ True - False + False True - 0 - none + 0 + none - + True - False - True - 6 - 12 + False 12 6 - - - True - True - True - True - 50 - True - - - Choose one or more rows to print on every page. In the right text box enter the row reference, for example, "1" or "$1" or "$2:$3". - - - - - 1 - 0 - - - - - True - False - False - - - - - - Click the Shrink icon to reduce the dialog to the size of the input field. It is then easier to mark the required reference in the sheet. The icons then automatically convert to the Maximize icon. Click it to restore the dialog to its original size. - - - - - 2 - 0 - - + True + 6 + 12 True - False + False - none - - user defined - @@ -254,8 +216,46 @@ - 0 - 0 + 0 + 0 + + + + + True + True + True + True + 50 + True + + + Choose one or more rows to print on every page. In the right text box enter the row reference, for example, "1" or "$1" or "$2:$3". + + + + + 1 + 0 + + + + + True + False + False + + + + + + Click the Shrink icon to reduce the dialog to the size of the input field. It is then easier to mark the required reference in the sheet. The icons then automatically convert to the Maximize icon. Click it to restore the dialog to its original size. + + + + + 2 + 0 @@ -263,7 +263,7 @@ True - False + False Rows to Repeat @@ -280,62 +280,24 @@ True - False + False True - 0 - none + 0 + none - + True - False - True - 6 - 12 + False 12 6 - - - True - True - True - True - 50 - True - - - Choose one or more columns to print on every page. In the right text box enter the column reference, for example, "A" or "AB" or "$C:$E". - - - - - 1 - 0 - - - - - True - False - False - - - - - - Click the Shrink icon to reduce the dialog to the size of the input field. It is then easier to mark the required reference in the sheet. The icons then automatically convert to the Maximize icon. Click it to restore the dialog to its original size. - - - - - 2 - 0 - - + True + 6 + 12 True - False + False - none - - user defined - @@ -347,8 +309,46 @@ - 0 - 0 + 0 + 0 + + + + + True + True + True + True + 50 + True + + + Choose one or more columns to print on every page. In the right text box enter the column reference, for example, "A" or "AB" or "$C:$E". + + + + + 1 + 0 + + + + + True + False + False + + + + + + Click the Shrink icon to reduce the dialog to the size of the input field. It is then easier to mark the required reference in the sheet. The icons then automatically convert to the Maximize icon. Click it to restore the dialog to its original size. + + + + + 2 + 0 @@ -356,7 +356,7 @@ True - False + False Columns to Repeat @@ -384,9 +384,6 @@ cancel help - - - Opens a dialog where you can specify the print range. diff --git a/sc/uiconfig/scalc/ui/protectsheetdlg.ui b/sc/uiconfig/scalc/ui/protectsheetdlg.ui index 756f65df8a06..b799a040c1dd 100644 --- a/sc/uiconfig/scalc/ui/protectsheetdlg.ui +++ b/sc/uiconfig/scalc/ui/protectsheetdlg.ui @@ -1,5 +1,5 @@ - + @@ -192,6 +192,7 @@ False + Password Level Bar Measure of password strength @@ -276,12 +277,6 @@ 0 - - - - - True - 6 diff --git a/sc/uiconfig/scalc/ui/randomnumbergenerator.ui b/sc/uiconfig/scalc/ui/randomnumbergenerator.ui index 576ce9ed84e3..eb6c773f9702 100644 --- a/sc/uiconfig/scalc/ui/randomnumbergenerator.ui +++ b/sc/uiconfig/scalc/ui/randomnumbergenerator.ui @@ -1,54 +1,54 @@ - + 10000000000 - 1 - 10 + 1 + 10 1 255 1 - 1 - 10 + 1 + 10 100 1 - 1 - 10 + 1 + 10 100 - 1 - 10 + 1 + 10 - False - 6 + False + 6 Random Number Generator False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _Apply True - True - True - True + True + True + True True @@ -61,10 +61,10 @@ _OK True - True - True - True - True + True + True + True + True True @@ -77,9 +77,9 @@ _Close True - True - True - True + True + True + True True @@ -92,8 +92,8 @@ _Help True - True - True + True + True True @@ -107,32 +107,32 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none True - False - 12 + False 12 + 12 6 6 - 12 + 12 True - False + False Cell range: - True - cell-range-edit + True + cell-range-edit 0 @@ -144,11 +144,11 @@ True - True + True center True - True - 30 + True + 30 True @@ -165,8 +165,8 @@ True - True - True + True + True False @@ -179,7 +179,7 @@ True - False + False Data @@ -196,38 +196,38 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 True - False + False Distribution: - True - distribution-combo + True + distribution-combo 0 - 0 - 0 + 0 + 0 True - False + False True 0 @@ -249,71 +249,71 @@ - 1 - 0 + 1 + 0 True - False + False True ... - True - parameter1-spin + True + parameter1-spin 0 - 0 - 1 + 0 + 1 True - False + False True ... - True - parameter2-spin + True + parameter2-spin 0 - 0 - 2 + 0 + 2 True - True + True True - True + True 0.0000 - parameter2-adjustment True + parameter2-adjustment 4 - 1 - 1 + 1 + 1 True - True + True True - True + True 1,0000 + True parameter1-adjustment 4 - True 1 - 1 - 2 + 1 + 2 @@ -321,7 +321,7 @@ True - False + False Random Number Generator @@ -338,28 +338,28 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 Enable custom seed True - True - False - True - True + True + False + True + True Set the initial value of the random number generator to a known value Seed. @@ -367,34 +367,34 @@ - 0 - 0 + 0 + 0 2 True - False + False 12 Seed: - True - seed-spin + True + seed-spin 0 - 0 - 1 + 0 + 1 True - True + True True - True - adjustment1 + True True + adjustment1 Value set to initiate the random number generator algorithm. It is used to initialize (seed) the random number generator in order to reproduce the same sequence of pseudorandom numbers. Specify a positive integer number (1, 2, ...) to produce a specific sequence, or leave the field blank if you don't need this particular feature. @@ -402,18 +402,18 @@ - 1 - 1 + 1 + 1 Enable rounding True - True - False - True - True + True + False + True + True Round the number to a given number of Decimal Places. @@ -421,37 +421,37 @@ - 0 - 2 + 0 + 2 2 True - False - True + False 12 + True Decimal places: - True - decimal-places-spin + True + decimal-places-spin 0 - 0 - 3 + 0 + 3 True - True + True True - True + True 1 + True decimal-places-adjustment 1 - True Number of decimal places of the numbers generated. @@ -459,8 +459,8 @@ - 1 - 3 + 1 + 3 @@ -468,7 +468,7 @@ True - False + False Options @@ -490,9 +490,6 @@ close help - - - Populate a cell range with automatically generated pseudo random numbers with the selected distribution function and its parameters. diff --git a/sc/uiconfig/scalc/ui/regressiondialog.ui b/sc/uiconfig/scalc/ui/regressiondialog.ui index ea9469335733..da7615a10ba7 100644 --- a/sc/uiconfig/scalc/ui/regressiondialog.ui +++ b/sc/uiconfig/scalc/ui/regressiondialog.ui @@ -460,25 +460,6 @@ 0 - - - Calculate residuals - True - True - False - True - True - - - The residuals give information on how far the actual data points deviate from the predicted data points, based on the regression model. - - - - - 0 - 1 - - True @@ -503,6 +484,25 @@ 0 + + + Calculate residuals + True + True + False + True + True + + + The residuals give information on how far the actual data points deviate from the predicted data points, based on the regression model. + + + + + 0 + 1 + + Force intercept to be zero diff --git a/sc/uiconfig/scalc/ui/rightfooterdialog.ui b/sc/uiconfig/scalc/ui/rightfooterdialog.ui index f3d85ef848d2..1c7cfd1e2b03 100644 --- a/sc/uiconfig/scalc/ui/rightfooterdialog.ui +++ b/sc/uiconfig/scalc/ui/rightfooterdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/rightheaderdialog.ui b/sc/uiconfig/scalc/ui/rightheaderdialog.ui index 70a0a25ec49a..494df3d980b7 100644 --- a/sc/uiconfig/scalc/ui/rightheaderdialog.ui +++ b/sc/uiconfig/scalc/ui/rightheaderdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/samplingdialog.ui b/sc/uiconfig/scalc/ui/samplingdialog.ui index a6a11e30777f..766e1c0be766 100644 --- a/sc/uiconfig/scalc/ui/samplingdialog.ui +++ b/sc/uiconfig/scalc/ui/samplingdialog.ui @@ -1,44 +1,44 @@ - + 1 100 1 - 1 - 10 + 1 + 10 100 - 1 - 10 + 1 + 10 - False - 6 + False + 6 Sampling False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -51,9 +51,9 @@ _Cancel True - True - True - True + True + True + True True @@ -66,8 +66,8 @@ _Help True - True - True + True + True True @@ -81,105 +81,105 @@ False True - end + end 0 True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 True - False + False Input range: - True - input-range-edit + True + input-range-edit 0 - 0 - 0 + 0 + 0 True - True + True center True - True + True + 30 True - 30 - 1 - 0 + 1 + 0 True - True - True + True + True - 2 - 0 + 2 + 0 True - False + False Results to: - True - output-range-edit + True + output-range-edit 0 - 0 - 1 + 0 + 1 True - True + True center True - True + True + 30 True - 30 - 1 - 1 + 1 + 1 True - True - True + True + True - 2 - 1 + 2 + 1 @@ -187,7 +187,7 @@ True - False + False Data @@ -204,129 +204,81 @@ True - False - 0 - none + False + 0 + none - + True - False - 6 - 12 + False 12 + 12 6 6 - 12 + 6 + 12 - + + Random True - True - True - True - 1 - sample-size-adjustment - True - 1 + True + False + True + True + True - 1 - 1 + 0 + 0 + 2 True - False + False 12 True Sample size: - True + True center - sample-size-spin + sample-size-spin 0 - 0 - 1 + 0 + 1 - - Random + True - True - False - True - True - True - - - 0 - 0 - 2 - - - - - Periodic - True - True - False - True - True - random-method-radio - - - 0 - 4 - 2 - - - - - True - True + True True - True + True 1 - period-adjustment True + sample-size-adjustment 1 - 1 - 5 - - - - - True - False - 12 - True - Period: - True - period-spin - 0 - - - 0 - 5 + 1 + 1 With replacement True - True - False - True - True + True + False + True + True - 0 - 2 + 0 + 2 2 @@ -334,23 +286,71 @@ Keep order True - True - False - True - True + True + False + True + True - 0 - 3 + 0 + 3 2 + + + Periodic + True + True + False + True + True + random-method-radio + + + 0 + 4 + 2 + + + + + True + False + 12 + True + Period: + True + period-spin + 0 + + + 0 + 5 + + + + + True + True + True + True + 1 + True + period-adjustment + 1 + + + 1 + 5 + + True - False + False Sampling Method @@ -371,9 +371,6 @@ cancel help - - - Create a table with data sampled from another table. diff --git a/sc/uiconfig/scalc/ui/scgeneralpage.ui b/sc/uiconfig/scalc/ui/scgeneralpage.ui index 99a3f9705c2b..453d98263289 100644 --- a/sc/uiconfig/scalc/ui/scgeneralpage.ui +++ b/sc/uiconfig/scalc/ui/scgeneralpage.ui @@ -30,6 +30,19 @@ 6 3 6 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + True @@ -44,6 +57,34 @@ 0 + + + True + False + + + Defines the unit of measure in spreadsheets. + + + + + 2 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 1 + + True @@ -76,47 +117,6 @@ 1 - - - True - False - - - Defines the unit of measure in spreadsheets. - - - - - 2 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - @@ -147,6 +147,19 @@ True False + + + False + True + center + center + res/lock.png + + + 0 + 0 + + True @@ -209,19 +222,6 @@ 0 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - @@ -272,63 +272,30 @@ 3 6 - - Press Enter to switch to _edit mode - True - True - False - True - True - - - Allows you to immediately edit the selected cell after pressing the Enter key. - - + + False + True + center + center + res/lock.png - 1 - 1 - 2 + 0 + 0 - - Expand _formatting + + Press Enter to _move selection True True False True True - - - Specifies whether to automatically apply the formatting attributes of the selected cell to the empty adjacent cells. - - 1 - 3 - 2 - - - - - Expand _references when new columns/rows are inserted - True - True - False - True - True - - - Specifies whether to expand references when inserting columns or rows adjacent to the reference range. This is only possible if the reference range, where the column or row is inserted, originally spanned at least two cells in the desired direction. - - - - - 1 - 4 - 2 + 0 @@ -355,57 +322,49 @@ - - Press Enter to _move selection - True - True - False - True - True + + False + True + center + center + res/lock.png - 1 - 0 + 0 + 1 - - Position cell reference with selection + + Press Enter to switch to _edit mode True True False True True - - With the option set, expanding a selection (with Ctrl + Shift + Down/Up) jumps to the end of the range in the column that was added as last to the initial selection. When the option is not set, expanding a selection (with Ctrl + Shift + Down/Up) jumps to the end of the range in the column where selecting the cell range was started. The same of course applies when extending a selection on rows, with Ctrl + Shift + Left/Right. + + Allows you to immediately edit the selected cell after pressing the Enter key. 1 - 8 + 1 2 - - Show overwrite _warning when pasting data - True - True - False - True - True - - - Specifies that, when you paste cells from the clipboard to a cell range that is not empty, a warning appears. - - + + False + True + center + center + res/lock.png - 1 - 7 - 2 + 0 + 2 @@ -428,6 +387,112 @@ 2 + + + False + True + center + center + res/lock.png + + + 0 + 3 + + + + + Expand _formatting + True + True + False + True + True + + + Specifies whether to automatically apply the formatting attributes of the selected cell to the empty adjacent cells. + + + + + 1 + 3 + 2 + + + + + False + True + center + center + res/lock.png + + + 0 + 4 + + + + + Expand _references when new columns/rows are inserted + True + True + False + True + True + + + Specifies whether to expand references when inserting columns or rows adjacent to the reference range. This is only possible if the reference range, where the column or row is inserted, originally spanned at least two cells in the desired direction. + + + + + 1 + 4 + 2 + + + + + False + True + center + center + res/lock.png + + + 0 + 5 + + + + + Update references when sorting range of cells + True + True + False + True + + + 1 + 5 + 2 + + + + + False + True + center + center + res/lock.png + + + 0 + 6 + + Highlight sele_ction in column/row headers @@ -448,111 +513,6 @@ 2 - - - Update references when sorting range of cells - True - True - False - True - - - 1 - 5 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 3 - - - - - False - True - center - center - res/lock.png - - - 0 - 4 - - - - - False - True - center - center - res/lock.png - - - 0 - 5 - - - - - False - True - center - center - res/lock.png - - - 0 - 6 - - False @@ -566,6 +526,26 @@ 7 + + + Show overwrite _warning when pasting data + True + True + False + True + True + + + Specifies that, when you paste cells from the clipboard to a cell range that is not empty, a warning appears. + + + + + 1 + 7 + 2 + + False @@ -579,6 +559,26 @@ 8 + + + Position cell reference with selection + True + True + False + True + True + + + With the option set, expanding a selection (with Ctrl + Shift + Down/Up) jumps to the end of the range in the column that was added as last to the initial selection. When the option is not set, expanding a selection (with Ctrl + Shift + Down/Up) jumps to the end of the range in the column where selecting the cell range was started. The same of course applies when extending a selection on rows, with Ctrl + Shift + Left/Right. + + + + + 1 + 8 + 2 + + False diff --git a/sc/uiconfig/scalc/ui/sharedfirstfooterdialog.ui b/sc/uiconfig/scalc/ui/sharedfirstfooterdialog.ui index 4767b14eb44d..6705cca963c3 100644 --- a/sc/uiconfig/scalc/ui/sharedfirstfooterdialog.ui +++ b/sc/uiconfig/scalc/ui/sharedfirstfooterdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/sharedfirstheaderdialog.ui b/sc/uiconfig/scalc/ui/sharedfirstheaderdialog.ui index 4acb9575381d..ef8d1d20a85c 100644 --- a/sc/uiconfig/scalc/ui/sharedfirstheaderdialog.ui +++ b/sc/uiconfig/scalc/ui/sharedfirstheaderdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/sharedfooterdialog.ui b/sc/uiconfig/scalc/ui/sharedfooterdialog.ui index 633069a00a4a..b161cfc0ea48 100644 --- a/sc/uiconfig/scalc/ui/sharedfooterdialog.ui +++ b/sc/uiconfig/scalc/ui/sharedfooterdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/sharedheaderdialog.ui b/sc/uiconfig/scalc/ui/sharedheaderdialog.ui index ee097ddcb2a0..bb329719c241 100644 --- a/sc/uiconfig/scalc/ui/sharedheaderdialog.ui +++ b/sc/uiconfig/scalc/ui/sharedheaderdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/sharedleftfooterdialog.ui b/sc/uiconfig/scalc/ui/sharedleftfooterdialog.ui index 8cfe27cf9e2b..cca7dbe7e8c2 100644 --- a/sc/uiconfig/scalc/ui/sharedleftfooterdialog.ui +++ b/sc/uiconfig/scalc/ui/sharedleftfooterdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/sharedleftheaderdialog.ui b/sc/uiconfig/scalc/ui/sharedleftheaderdialog.ui index 004a15f7b673..bf60cb04ac0a 100644 --- a/sc/uiconfig/scalc/ui/sharedleftheaderdialog.ui +++ b/sc/uiconfig/scalc/ui/sharedleftheaderdialog.ui @@ -107,7 +107,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/sheetprintpage.ui b/sc/uiconfig/scalc/ui/sheetprintpage.ui index d5988d03b103..910c464859f9 100644 --- a/sc/uiconfig/scalc/ui/sheetprintpage.ui +++ b/sc/uiconfig/scalc/ui/sheetprintpage.ui @@ -441,6 +441,26 @@ 0 + + + True + False + + Reduce/enlarge printout + Shrink print range(s) to width/height + Shrink print range(s) on number of pages + + + + Select a scaling mode from the list box. Appropriate controls will be shown below the list box. + + + + + 1 + 0 + + True @@ -518,23 +538,6 @@ 0 - - - _Height in pages: - True - True - False - True - True - - - - - - 0 - 1 - - True @@ -556,6 +559,23 @@ 0 + + + _Height in pages: + True + True + False + True + True + + + + + + 0 + 1 + + True @@ -636,26 +656,6 @@ 1 - - - True - False - - Reduce/enlarge printout - Shrink print range(s) to width/height - Shrink print range(s) on number of pages - - - - Select a scaling mode from the list box. Appropriate controls will be shown below the list box. - - - - - 1 - 0 - - diff --git a/sc/uiconfig/scalc/ui/sidebarnumberformat.ui b/sc/uiconfig/scalc/ui/sidebarnumberformat.ui index 8e41dac91e3f..31e01b614971 100644 --- a/sc/uiconfig/scalc/ui/sidebarnumberformat.ui +++ b/sc/uiconfig/scalc/ui/sidebarnumberformat.ui @@ -22,7 +22,7 @@ True False - + True False @@ -30,6 +30,46 @@ 6 3 6 + + + True + False + _Category + True + numberformatcombobox + 0 + + + 0 + 0 + 2 + + + + + True + False + Select a category of contents. + center + True + + General + Number + Percent + Currency + Date + Time + Scientific + Fraction + Boolean Value + Text + + + + 0 + 1 + + True @@ -68,39 +108,9 @@ - - 0 - 0 - - - - - True - False - Select a category of contents. - center - True - - General - Number - Percent - Currency - Date - Time - Scientific - Fraction - Boolean Value - Text - - - - Category - - - 1 - 0 + 1 @@ -141,7 +151,7 @@ 0 - 1 + 2 @@ -191,7 +201,7 @@ 1 - 1 + 2 @@ -205,7 +215,7 @@ 0 - 2 + 3 @@ -224,7 +234,7 @@ 1 - 2 + 3 @@ -240,7 +250,7 @@ 0 - 3 + 4 2 @@ -257,7 +267,7 @@ 0 - 4 + 5 2 @@ -273,7 +283,7 @@ 0 - 5 + 6 2 @@ -288,7 +298,6 @@ - diff --git a/sc/uiconfig/scalc/ui/simplerefdialog.ui b/sc/uiconfig/scalc/ui/simplerefdialog.ui index 3def53be8a62..2ff846e28b72 100644 --- a/sc/uiconfig/scalc/ui/simplerefdialog.ui +++ b/sc/uiconfig/scalc/ui/simplerefdialog.ui @@ -1,32 +1,32 @@ - + - False - 6 + False + 6 Set range False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -39,8 +39,8 @@ _Cancel True - True - True + True + True True @@ -53,8 +53,8 @@ _Help True - True - True + True + True True @@ -68,56 +68,56 @@ False True - end + end 2 - + True - False + False True - 6 - 12 - True + 6 + 12 + True True - False + False Area: - True - assign + True + assign 0 - 0 - 0 + 0 + 0 True - True + True True - True + True + 50 True - 50 - 1 - 0 + 1 + 0 True - True - True + True + True - 2 - 0 + 2 + 0 @@ -134,9 +134,6 @@ cancel help - - - Filters the list of changes according to the range of cells that you specify. To select a range of cells in your sheet, click the Set Reference button (...). diff --git a/sc/uiconfig/scalc/ui/solverdlg.ui b/sc/uiconfig/scalc/ui/solverdlg.ui index cbd073dd6aee..0b0c5e50c67a 100644 --- a/sc/uiconfig/scalc/ui/solverdlg.ui +++ b/sc/uiconfig/scalc/ui/solverdlg.ui @@ -1,5 +1,5 @@ - + @@ -127,6 +127,7 @@ False _Target cell True + targetedit 0 @@ -134,129 +135,6 @@ 0 - - - True - False - Optimize result to - True - 0 - 0 - - - - - - - - 0 - 1 - 3 - - - - - True - False - _By changing cells - True - 0 - - - 0 - 4 - - - - - Minim_um - True - True - False - True - True - max - - - - - - Enter the cell range that can be changed. - - - - - 1 - 2 - - - - - _Maximum - True - True - False - True - True - True - - - - - - Enter the cell range that can be changed. - - - - - 1 - 1 - - - - - True - False - True - 6 - - - True - True - True - True - 32 - True - - - Enter the cell range that can be changed. - - - - - False - True - 0 - - - - - True - True - True - - - False - True - 1 - - - - - 1 - 4 - - True @@ -300,6 +178,72 @@ 0 + + + True + False + Optimize result to + True + 0 + 0 + + + + + + + + 0 + 1 + 3 + + + + + _Maximum + True + True + False + True + True + True + + + + + + Enter the cell range that can be changed. + + + + + 1 + 1 + + + + + Minim_um + True + True + False + True + True + max + + + + + + Enter the cell range that can be changed. + + + + + 1 + 2 + + True @@ -380,6 +324,64 @@ 3 + + + True + False + _By changing cells + True + changeedit + 0 + + + 0 + 4 + + + + + True + False + True + 6 + + + True + True + True + True + 32 + True + + + Enter the cell range that can be changed. + + + + + False + True + 0 + + + + + True + True + True + + + False + True + 1 + + + + + 1 + 4 + + False @@ -431,8 +433,7 @@ True False - _Cell reference - True + Cell reference 0 @@ -445,8 +446,7 @@ True False - _Operator - True + Operator 0 @@ -459,8 +459,7 @@ True False 6 - V_alue - True + Value 0 @@ -488,63 +487,6 @@ 1 - - - True - True - True - True - 20 - True - - - Cell reference - - - - - 0 - 2 - - - - - True - True - True - True - 20 - True - - - Cell reference - - - - - 0 - 3 - - - - - True - True - True - True - 20 - True - - - Cell reference - - - - - 0 - 4 - - True @@ -556,39 +498,6 @@ 1 - - - True - True - True - - - 1 - 2 - - - - - True - True - True - - - 1 - 3 - - - - - True - True - True - - - 1 - 4 - - True @@ -611,6 +520,79 @@ 1 + + + True + True + 6 + True + True + 15 + True + + + Value + + + + + 3 + 1 + + + + + True + True + True + + + 4 + 1 + + + + + True + True + True + Remove + + + 5 + 1 + + + + + True + True + True + True + 20 + True + + + Cell reference + + + + + 0 + 2 + + + + + True + True + True + + + 1 + 2 + + True @@ -633,6 +615,79 @@ 2 + + + True + True + 6 + True + True + 15 + True + + + Value + + + + + 3 + 2 + + + + + True + True + True + + + 4 + 2 + + + + + True + True + True + Remove + + + 5 + 2 + + + + + True + True + True + True + 20 + True + + + Cell reference + + + + + 0 + 3 + + + + + True + True + True + + + 1 + 3 + + True @@ -655,6 +710,79 @@ 3 + + + True + True + 6 + True + True + 15 + True + + + Value + + + + + 3 + 3 + + + + + True + True + True + + + 4 + 3 + + + + + True + True + True + Remove + + + 5 + 3 + + + + + True + True + True + True + 20 + True + + + Cell reference + + + + + 0 + 4 + + + + + True + True + True + + + 1 + 4 + + True @@ -677,66 +805,6 @@ 4 - - - True - True - 6 - True - True - 15 - True - - - Value - - - - - 3 - 1 - - - - - True - True - 6 - True - True - 15 - True - - - Value - - - - - 3 - 2 - - - - - True - True - 6 - True - True - 15 - True - - - Value - - - - - 3 - 3 - - True @@ -757,39 +825,6 @@ 4 - - - True - True - True - - - 4 - 1 - - - - - True - True - True - - - 4 - 2 - - - - - True - True - True - - - 4 - 3 - - True @@ -801,42 +836,6 @@ 4 - - - True - True - True - Remove - - - 5 - 2 - - - - - True - True - True - Remove - - - 5 - 1 - - - - - True - True - True - Remove - - - 5 - 3 - - True diff --git a/sc/uiconfig/scalc/ui/solveroptionsdialog.ui b/sc/uiconfig/scalc/ui/solveroptionsdialog.ui index d3d801ca23c9..1fcc3e4a7d00 100644 --- a/sc/uiconfig/scalc/ui/solveroptionsdialog.ui +++ b/sc/uiconfig/scalc/ui/solveroptionsdialog.ui @@ -1,5 +1,5 @@ - + @@ -17,28 +17,28 @@ - False - 6 + False + 6 Options False - dialog + dialog - False + False vertical 12 - False - end + False + end _OK True - True - True - True - True + True + True + True + True True @@ -51,8 +51,8 @@ _Cancel True - True - True + True + True True @@ -65,8 +65,8 @@ _Help True - True - True + True + True True @@ -80,42 +80,42 @@ False True - end + end 2 - + True - False + False True True - 12 + 12 - + True - False - 12 + False + 12 True - False + False Solver engine: - True - engine + True + engine 0 - 0 - 0 + 0 + 0 True - False + False Select a solver engine. The listbox is disabled if only one solver engine is installed. @@ -123,57 +123,57 @@ - 1 - 0 + 1 + 0 - 0 - 0 + 0 + 0 - + True - False + False True True - 6 + 6 True - False + False Settings: - True - settings + True + settings 0 - 0 - 0 + 0 + 0 True - True + True True True - in + in - -1 + -1 True - True - True + True + True True True liststore1 - False - 1 - False + False + 1 + False @@ -189,11 +189,6 @@ 0 - - - - - 6 @@ -206,8 +201,8 @@ - 0 - 1 + 0 + 1 @@ -215,10 +210,10 @@ Edit... True False - True - True + True + True start - True + True If the current entry in the Settings listbox allows you to edit a value, you can click the Edit button. A dialog opens where you can change the value. @@ -226,14 +221,14 @@ - 0 - 2 + 0 + 2 - 0 - 1 + 0 + 1 @@ -250,8 +245,5 @@ cancel help - - - diff --git a/sc/uiconfig/scalc/ui/sortdialog.ui b/sc/uiconfig/scalc/ui/sortdialog.ui index 1d0504f745fc..2c56d60ad9b4 100644 --- a/sc/uiconfig/scalc/ui/sortdialog.ui +++ b/sc/uiconfig/scalc/ui/sortdialog.ui @@ -106,7 +106,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/sortoptionspage.ui b/sc/uiconfig/scalc/ui/sortoptionspage.ui index 0ffa7e52b6c9..30fba5ab8ae2 100644 --- a/sc/uiconfig/scalc/ui/sortoptionspage.ui +++ b/sc/uiconfig/scalc/ui/sortoptionspage.ui @@ -101,6 +101,7 @@ 20 True True + True Example: A1.14, A1.2, A2.5, A10 (with dot as separator). The locale determines which character is used as the decimal separator. @@ -328,6 +329,7 @@ True + True False diff --git a/sc/uiconfig/scalc/ui/sparklinedatarangedialog.ui b/sc/uiconfig/scalc/ui/sparklinedatarangedialog.ui index 6149db846b2f..e0d3312b5c31 100644 --- a/sc/uiconfig/scalc/ui/sparklinedatarangedialog.ui +++ b/sc/uiconfig/scalc/ui/sparklinedatarangedialog.ui @@ -34,7 +34,7 @@ - _Close + _Cancel True True True diff --git a/sc/uiconfig/scalc/ui/sparklinedialog.ui b/sc/uiconfig/scalc/ui/sparklinedialog.ui index 0b958fcae179..79875cf977d8 100644 --- a/sc/uiconfig/scalc/ui/sparklinedialog.ui +++ b/sc/uiconfig/scalc/ui/sparklinedialog.ui @@ -50,7 +50,7 @@ - _Close + _Cancel True True True @@ -112,21 +112,19 @@ 6 6 - + True - True - True + False + Input range: + True + 0 - + + - - - Shrink - - - 2 + 0 0 @@ -154,21 +152,38 @@ - + True True True - + - - Shrink + + Shrink 2 + 0 + + + + + True + False + Output range: + True + 0 + + + + + + + 0 1 @@ -196,36 +211,21 @@ - + True - False - Input range: - True - 0 + True + True - - + + + + Shrink + + - 0 - 0 - - - - - True - False - Output range: - True - 0 - - - - - - - 0 + 2 1 @@ -248,6 +248,189 @@ 2 + + + True + False + start + True + 0 + none + + + + True + False + start + 12 + 6 + 3 + 6 + + + True + False + Type: + True + cbType + 0 + + + 0 + 0 + + + + + True + False + start + + Line + Column + Stacked + + + + Select the sparkline type in the drop-down list. Choices are: Line - draws a line between data values. Column - draws a bar for each data value. Stacked - also known as win/loss: displays equally sized bars indicating positive and negative values. + + + + + 1 + 0 + + + + + True + False + Line thickness: + True + seLineWidth + 0 + + + 0 + 1 + + + + + True + True + True + 1,00 + True + adjustment-line-width + 0.25 + 2 + True + True + 1 + + + Enter the line thickness number manually or use the spin button. + + + + + 1 + 1 + + + + + True + False + Display empty cells as: + True + cbEmptyCells + 0 + + + 0 + 2 + + + + + True + False + + Gap + Zero + Span + + + + Display empty cells as: Gap - the missing data is not displayed. The line type discontinues in the gap and the column is not displayed. Zero - the missing data is displayed as value zero. Span - for line type only, draws a continuous line connecting the previous value to the next value. + + + + + 1 + 2 + + + + + Display hidden + True + True + False + True + True + + + Check to show all columns or stacks in the range even when the data is in hidden cells. If unchecked, the hidden data is ignored. + + + + + 0 + 3 + 2 + + + + + Right-to-left + True + True + False + True + True + + + Check to have the sparklines show the data in reverse order. + + + + + 0 + 4 + 2 + + + + + + + True + False + Properties + + + + + + + + 0 + 1 + + True @@ -611,189 +794,6 @@ 1 - - - True - False - start - True - 0 - none - - - - True - False - start - 12 - 6 - 3 - 6 - - - True - False - Line thickness: - True - seLineWidth - 0 - - - 0 - 1 - - - - - True - True - True - 1,00 - True - adjustment-line-width - 0.25 - 2 - True - True - 1 - - - Enter the line thickness number manually or use the spin button. - - - - - 1 - 1 - - - - - True - False - Display empty cells as: - True - cbEmptyCells - 0 - - - 0 - 2 - - - - - True - False - - Gap - Zero - Span - - - - Display empty cells as: Gap - the missing data is not displayed. The line type discontinues in the gap and the column is not displayed. Zero - the missing data is displayed as value zero. Span - for line type only, draws a continuous line connecting the previous value to the next value. - - - - - 1 - 2 - - - - - Display hidden - True - True - False - True - True - - - Check to show all columns or stacks in the range even when the data is in hidden cells. If unchecked, the hidden data is ignored. - - - - - 0 - 3 - 2 - - - - - Right-to-left - True - True - False - True - True - - - Check to have the sparklines show the data in reverse order. - - - - - 0 - 4 - 2 - - - - - True - False - start - - Line - Column - Stacked - - - - Select the sparkline type in the drop-down list. Choices are: Line - draws a line between data values. Column - draws a bar for each data value. Stacked - also known as win/loss: displays equally sized bars indicating positive and negative values. - - - - - 1 - 0 - - - - - True - False - Type: - True - cbType - 0 - - - 0 - 0 - - - - - - - True - False - Properties - - - - - - - - 0 - 1 - - True @@ -809,6 +809,42 @@ 6 3 6 + + + Display X axis + True + True + False + start + True + True + + + Check to show the X axis for sparklines. + + + + + 0 + 0 + 3 + + + + + True + False + start + Vertical minimum: + True + cbMinAxisType + 0 + + + 0 + 1 + + True @@ -849,6 +885,21 @@ 1 + + + True + False + start + Vertical maximum: + True + cbMaxAxisType + 0 + + + 0 + 2 + + True @@ -889,57 +940,6 @@ 2 - - - True - False - start - Vertical maximum: - True - cbMaxAxisType - 0 - - - 0 - 2 - - - - - True - False - start - Vertical minimum: - True - cbMinAxisType - 0 - - - 0 - 1 - - - - - Display X axis - True - True - False - start - True - True - - - Check to show the X axis for sparklines. - - - - - 0 - 0 - 3 - - diff --git a/sc/uiconfig/scalc/ui/standardfilterdialog.ui b/sc/uiconfig/scalc/ui/standardfilterdialog.ui index b67a1609ae2b..65f9d375755e 100644 --- a/sc/uiconfig/scalc/ui/standardfilterdialog.ui +++ b/sc/uiconfig/scalc/ui/standardfilterdialog.ui @@ -1,5 +1,5 @@ - + @@ -209,90 +209,6 @@ 3 6 12 - - - True - False - - AND - OR - - - - - - - Operator 1 - For the following arguments, you can choose between the logical operators AND / OR. - - - - - 0 - 1 - - - - - True - False - - AND - OR - - - - - - - Operator 2 - For the following arguments, you can choose between the logical operators AND / OR. - - - - - 0 - 2 - - - - - True - False - - AND - OR - - - - Operator 3 - - - - - 0 - 3 - - - - - True - False - - AND - OR - - - - Operator 4 - - - - - 0 - 4 - - True @@ -337,6 +253,29 @@ 0 + + + True + False + + AND + OR + + + + + + + Operator 1 + For the following arguments, you can choose between the logical operators AND / OR. + + + + + 0 + 1 + + True @@ -356,59 +295,6 @@ 1 - - - True - False - - - - - - Field Name 2 - Specifies the field names from the current table to set them in the argument. - - - - - 1 - 2 - - - - - True - False - - - - - - Field Name 3 - Specifies the field names from the current table to set them in the argument. - - - - - 1 - 3 - - - - - True - False - - - Field Name 4 - - - - - 1 - 4 - - True @@ -448,6 +334,137 @@ 1 + + + + True + False + + + True + False + True + True + + + True + True + True + + + + + + + + Value 1 + Specifies a value to filter the field. + + + + + 0 + 0 + + + + + True + False + True + liststore1 + 0 + 1 + + + + 0 + + + + + + 3 + + + + + + + + Color + Specifies a color to filter the field. + + + + + 1 + 0 + + + + + 3 + 1 + + + + + True + True + True + Remove + 8 + image1 + True + + + 4 + 1 + + + + + True + False + + AND + OR + + + + + + + Operator 2 + For the following arguments, you can choose between the logical operators AND / OR. + + + + + 0 + 2 + + + + + True + False + + + + + + Field Name 2 + Specifies the field names from the current table to set them in the argument. + + + + + 1 + 2 + + True @@ -487,6 +504,133 @@ 2 + + + + True + False + + + True + False + True + True + + + True + True + True + + + + + + + + Value 1 + Specifies a value to filter the field. + + + + + 0 + 0 + + + + + True + False + True + liststore2 + 0 + 1 + + + + 1 + + + + + + 3 + + + + + + + + Color + Specifies a color to filter the field. + + + + + 1 + 0 + + + + + 3 + 2 + + + + + True + True + True + Remove + 8 + image2 + True + + + 4 + 2 + + + + + True + False + + AND + OR + + + + Operator 3 + + + + + 0 + 3 + + + + + True + False + + + + + + Field Name 3 + Specifies the field names from the current table to set them in the argument. + + + + + 1 + 3 + + True @@ -526,237 +670,6 @@ 3 - - - True - False - - = - < - > - <= - >= - <> - Largest - Smallest - Largest % - Smallest % - Contains - Does not contain - Begins with - Does not begin with - Ends with - Does not end with - Font color - Background color - - - - Condition 4 - - - - - 2 - 4 - - - - - True - True - True - Remove - 8 - image1 - True - - - 4 - 1 - - - - - True - True - True - Remove - 8 - image2 - True - - - 4 - 2 - - - - - True - True - True - Remove - 8 - image3 - True - - - 4 - 3 - - - - - True - True - True - Remove - 8 - image4 - True - - - 4 - 4 - - - - - - True - False - - - True - False - True - True - - - True - True - True - - - - - - - - Value 1 - Specifies a value to filter the field. - - - - - 0 - 0 - - - - - True - False - True - liststore2 - 0 - 1 - - - - 1 - - - - - - 3 - - - - - - - - 1 - 0 - - - - - 3 - 2 - - - - - - True - False - - - True - False - True - True - - - True - True - True - - - - - - - - Value 1 - Specifies a value to filter the field. - - - - - 0 - 0 - - - - - True - False - True - liststore1 - 0 - 1 - - - - 0 - - - - - - 3 - - - - - - - - 1 - 0 - - - - - 3 - 1 - - @@ -796,8 +709,8 @@ False True liststore3 - 0 - 1 + 0 + 1 @@ -813,6 +726,12 @@ + + + Color + Specifies a color to filter the field. + + 1 @@ -825,6 +744,90 @@ 3 + + + True + True + True + Remove + 8 + image3 + True + + + 4 + 3 + + + + + True + False + + AND + OR + + + + Operator 4 + + + + + 0 + 4 + + + + + True + False + + + Field Name 4 + + + + + 1 + 4 + + + + + True + False + + = + < + > + <= + >= + <> + Largest + Smallest + Largest % + Smallest % + Contains + Does not contain + Begins with + Does not begin with + Ends with + Does not end with + Font color + Background color + + + + Condition 4 + + + + + 2 + 4 + + @@ -864,8 +867,8 @@ False True liststore4 - 0 - 1 + 0 + 1 @@ -881,6 +884,12 @@ + + + Color + Specifies a color to filter the field. + + 1 @@ -893,6 +902,21 @@ 4 + + + True + True + True + Remove + 8 + image4 + True + + + 4 + 4 + + @@ -969,26 +993,6 @@ 0 - - - Range c_ontains column labels - True - True - False - True - True - True - - - Includes the column labels in the first row of a cell range. - - - - - 0 - 1 - - Regular _expressions @@ -1009,6 +1013,26 @@ 0 + + + Range c_ontains column labels + True + True + False + True + True + True + + + Includes the column labels in the first row of a cell range. + + + + + 0 + 1 + + _No duplications diff --git a/sc/uiconfig/scalc/ui/subtotalgrppage.ui b/sc/uiconfig/scalc/ui/subtotalgrppage.ui index c200e84d6505..0571e7939fa6 100644 --- a/sc/uiconfig/scalc/ui/subtotalgrppage.ui +++ b/sc/uiconfig/scalc/ui/subtotalgrppage.ui @@ -160,11 +160,6 @@ 0 - - - - - 6 diff --git a/sc/uiconfig/scalc/ui/tabcolordialog.ui b/sc/uiconfig/scalc/ui/tabcolordialog.ui index d5b39a79539e..00d1f1e76cb2 100644 --- a/sc/uiconfig/scalc/ui/tabcolordialog.ui +++ b/sc/uiconfig/scalc/ui/tabcolordialog.ui @@ -5,6 +5,7 @@ False 6 + False True 0 0 @@ -19,8 +20,8 @@ False end - - _OK + + _Close True True True @@ -34,20 +35,6 @@ 0 - - - _Cancel - True - True - True - True - - - False - True - 1 - - False @@ -60,26 +47,23 @@ True False - 3 + vertical + 0 - - True - False - center - Palette: - True - paletteselector - 0 - 0 + + False + True + True + False - True + False 0 - + True False @@ -91,47 +75,15 @@ - False + True True 0 - - - True - True - True - True - never - never - in - - - True - False - - - True - True - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK - True - True - - - - - - - False - True - 1 - - - ok - cancel + close diff --git a/sc/uiconfig/scalc/ui/textimportcsv.ui b/sc/uiconfig/scalc/ui/textimportcsv.ui index 80f3998fa8b4..9a1e8c6a7a07 100644 --- a/sc/uiconfig/scalc/ui/textimportcsv.ui +++ b/sc/uiconfig/scalc/ui/textimportcsv.ui @@ -113,12 +113,12 @@ 6 12 - + True False - Ch_aracter set: + E_ncoding: True - charset + encoding 0 @@ -155,12 +155,12 @@ - + True False - - Specifies the character set to be used in the imported file. + + Specifies the encoding to be used in the imported file. @@ -170,11 +170,11 @@ - + True False start - + 1 diff --git a/sc/uiconfig/scalc/ui/tpviewpage.ui b/sc/uiconfig/scalc/ui/tpviewpage.ui index 88ef021f4d3b..5667238e1e3c 100644 --- a/sc/uiconfig/scalc/ui/tpviewpage.ui +++ b/sc/uiconfig/scalc/ui/tpviewpage.ui @@ -26,6 +26,19 @@ False 12 6 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + _Formulas @@ -45,6 +58,19 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + Zero val_ues @@ -64,6 +90,19 @@ 1 + + + False + True + center + center + res/lock.png + + + 0 + 2 + + _Comment indicator @@ -83,6 +122,50 @@ 2 + + + False + True + center + center + res/lock.png + + + 0 + 3 + + + + + Comment authorship + True + True + False + True + + + Specifies whether the author of the comment is displayed above the comment. + + + + + 1 + 3 + + + + + False + True + center + center + res/lock.png + + + 0 + 4 + + _Formula indicator and hint @@ -102,6 +185,19 @@ 4 + + + False + True + center + center + res/lock.png + + + 0 + 5 + + Value h_ighlighting @@ -122,26 +218,39 @@ - - _Show references in color + + False + True + center + center + res/lock.png + + + 0 + 6 + + + + + Column/Row highlighting True True False True True - - Specifies that each reference is highlighted in color in the formula. The cell range is also enclosed by a colored border as soon as the cell containing the reference is selected for editing. + + Mark the Column/row highlighting box to show row/column highlighting for the row and column of the active cell. 1 - 9 + 6 - + False True center @@ -150,46 +259,26 @@ 0 - 0 + 7 - - False - True - center - center - res/lock.png + + Highlight cell in edit mode + True + True + False + True + True + + + Mark this box to show highlighted background when the cell is in edit mode. + + - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 4 + 1 + 7 @@ -205,19 +294,6 @@ 8 - - - False - True - center - center - res/lock.png - - - 0 - 5 - - _Anchor @@ -251,98 +327,22 @@ - - Column/Row highlighting + + _Show references in color True True False True True - - Mark the Column/row highlighting box to show row/column highlighting for the row and column of the active cell. + + Specifies that each reference is highlighted in color in the formula. The cell range is also enclosed by a colored border as soon as the cell containing the reference is selected for editing. 1 - 6 - - - - - False - True - center - center - res/lock.png - - - 0 - 6 - - - - - Highlight cell in edit mode - True - True - False - True - True - - - Mark this box to show highlighted background when the cell is in edit mode. - - - - - 1 - 7 - - - - - False - True - center - center - res/lock.png - - - 0 - 7 - - - - - Comment authorship - True - True - False - True - - - Specifies whether the author of the comment is displayed above the comment. - - - - - 1 - 3 - - - - - False - True - center - center - res/lock.png - - - 0 - 3 + 9 @@ -363,293 +363,6 @@ 0 - - - True - False - 0 - none - - - - True - False - 12 - 6 - - - Colu_mn/row headers - True - True - False - True - True - - - Specifies whether to display row and column headers. - - - - - 1 - 0 - - - - - Hori_zontal scroll bar - True - True - False - True - True - - - Specifies whether to display a horizontal scrollbar at the bottom of the document window. - - - - - 1 - 1 - - - - - _Vertical scroll bar - True - True - False - True - True - - - Specifies whether to display a vertical scrollbar at the right of the document window. - - - - - 1 - 2 - - - - - Sh_eet tabs - True - True - False - True - True - - - Specifies whether to display the sheet tabs at the bottom of the spreadsheet document. - - - - - 1 - 3 - - - - - _Outline symbols - True - True - False - True - True - - - If you have defined an outline, the Outline symbols option specifies whether to view the outline symbols at the border of the sheet. - - - - - 1 - 4 - - - - - Summary o_n search - True - True - False - True - True - True - - - If this box is checked, a Search Results window appears when you choose Find All in the Find Box, which summarizes the search results. - - - - - 1 - 5 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 3 - - - - - False - True - center - center - res/lock.png - - - 0 - 4 - - - - - False - True - center - center - res/lock.png - - - 0 - 5 - - - - - - - True - False - Window - - - - - - - - 0 - 1 - - - - - True - False - 0 - none - - - - True - False - 12 - 6 - - - S_ynchronize sheets - True - True - False - True - True - - - If checked, all sheets are shown with the same zoom factor. If not checked, each sheet can have its own zoom factor. - - - - - 1 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - - - True - False - Zoom - - - - - - - - 0 - 2 - - True @@ -666,43 +379,16 @@ 3 6 - - _Page breaks - True - True - False - True - True - - - Specifies whether to view the page breaks within a defined print area. - - + + False + True + center + center + res/lock.png - 1 - 2 - 3 - - - - - Helplines _while moving - True - True - False - True - True - - - Specifies whether to view guides when moving drawings, frames, graphics and other objects. - - - - - 1 - 3 - 3 + 0 + 0 @@ -745,6 +431,19 @@ 2 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + True @@ -801,32 +500,6 @@ 1 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - False @@ -840,6 +513,26 @@ 2 + + + _Page breaks + True + True + False + True + True + + + Specifies whether to view the page breaks within a defined print area. + + + + + 1 + 2 + 3 + + False @@ -853,6 +546,26 @@ 3 + + + Helplines _while moving + True + True + False + True + True + + + Specifies whether to view guides when moving drawings, frames, graphics and other objects. + + + + + 1 + 3 + 3 + + @@ -871,6 +584,231 @@ 0 + + + True + False + 0 + none + + + + True + False + 12 + 6 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + Colu_mn/row headers + True + True + False + True + True + + + Specifies whether to display row and column headers. + + + + + 1 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + Hori_zontal scroll bar + True + True + False + True + True + + + Specifies whether to display a horizontal scrollbar at the bottom of the document window. + + + + + 1 + 1 + + + + + False + True + center + center + res/lock.png + + + 0 + 2 + + + + + _Vertical scroll bar + True + True + False + True + True + + + Specifies whether to display a vertical scrollbar at the right of the document window. + + + + + 1 + 2 + + + + + False + True + center + center + res/lock.png + + + 0 + 3 + + + + + Sh_eet tabs + True + True + False + True + True + + + Specifies whether to display the sheet tabs at the bottom of the spreadsheet document. + + + + + 1 + 3 + + + + + False + True + center + center + res/lock.png + + + 0 + 4 + + + + + + _Outline symbols + True + True + False + True + True + + + If you have defined an outline, the Outline symbols option specifies whether to view the outline symbols at the border of the sheet. + + + + + 1 + 4 + + + + + False + True + center + center + res/lock.png + + + 0 + 5 + + + + + Summary o_n search + True + True + False + True + True + True + + + If this box is checked, a Search Results window appears when you choose Find All in the Find Box, which summarizes the search results. + + + + + 1 + 5 + + + + + + + True + False + Window + + + + + + + + 0 + 1 + + True @@ -886,6 +824,19 @@ 6 3 3 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + True @@ -905,44 +856,6 @@ 0 - - - True - False - Char_ts: - True - diagram - 0 - - - Defines if charts in your document are shown or hidden. - - - - - 1 - 1 - - - - - True - False - _Drawing objects: - True - draw - 0 - - - Defines if drawing objects in your document are shown or hidden. - - - - - 1 - 2 - - True @@ -962,6 +875,38 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + True + False + Char_ts: + True + diagram + 0 + + + Defines if charts in your document are shown or hidden. + + + + + 1 + 1 + + True @@ -981,6 +926,38 @@ 1 + + + False + True + center + center + res/lock.png + + + 0 + 2 + + + + + True + False + _Drawing objects: + True + draw + 0 + + + Defines if drawing objects in your document are shown or hidden. + + + + + 1 + 2 + + True @@ -1000,45 +977,6 @@ 2 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - @@ -1057,6 +995,69 @@ 1 + + + True + False + 0 + none + + + + True + False + 12 + 6 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + S_ynchronize sheets + True + True + False + True + True + + + If checked, all sheets are shown with the same zoom factor. If not checked, each sheet can have its own zoom factor. + + + + + 1 + 0 + + + + + + + True + False + Zoom + + + + + + + + 0 + 2 + + diff --git a/sc/uiconfig/scalc/ui/validationcriteriapage.ui b/sc/uiconfig/scalc/ui/validationcriteriapage.ui index 61a7bcf68534..cbc92f3dcfe8 100644 --- a/sc/uiconfig/scalc/ui/validationcriteriapage.ui +++ b/sc/uiconfig/scalc/ui/validationcriteriapage.ui @@ -25,20 +25,6 @@ 0 - - - False - True - _Data: - True - data - 0 - - - 0 - 5 - - True @@ -65,6 +51,98 @@ 0 + + + Allow _empty cells + True + True + False + True + True + + + In conjunction with Tools - Detective - Mark invalid Data, this defines that blank cells are shown as invalid data (disabled) or not (enabled). + + + + + 1 + 1 + + + + + Case _sensitive + True + True + False + True + True + + + In conjunction with Tools - Detective - Mark invalid Data, this defines that blank cells are shown as invalid data (disabled) or not (enabled). + + + + + 1 + 2 + + + + + Show selection _list + True + True + False + True + True + + + Shows a list of all valid strings or values to select from. + + + + + 1 + 3 + + + + + Sor_t entries ascending + True + True + False + 12 + True + True + True + + + Sorts the selection list in ascending order and filters duplicates from the list. If not checked, the order from the data source is taken. + + + + + 1 + 4 + + + + + False + True + _Data: + True + data + 0 + + + 0 + 5 + + False @@ -186,79 +264,6 @@ 6 - - - False - True - Ma_ximum: - True - max - 0 - - - 0 - 8 - - - - - Allow _empty cells - True - True - False - True - True - - - In conjunction with Tools - Detective - Mark invalid Data, this defines that blank cells are shown as invalid data (disabled) or not (enabled). - - - - - 1 - 1 - - - - - Show selection _list - True - True - False - True - True - - - Shows a list of all valid strings or values to select from. - - - - - 1 - 3 - - - - - Sor_t entries ascending - True - True - False - 12 - True - True - True - - - Sorts the selection list in ascending order and filters duplicates from the list. If not checked, the order from the data source is taken. - - - - - 1 - 4 - - False @@ -277,6 +282,20 @@ 7 + + + False + True + Ma_ximum: + True + max + 0 + + + 0 + 8 + + True @@ -295,25 +314,6 @@ 8 - - - Case _sensitive - True - True - False - True - True - - - In conjunction with Tools - Detective - Mark invalid Data, this defines that blank cells are shown as invalid data (disabled) or not (enabled). - - - - - 1 - 2 - - diff --git a/sc/uiconfig/scalc/ui/validationdialog.ui b/sc/uiconfig/scalc/ui/validationdialog.ui index 0ba2c165f3a7..07de439e49bd 100644 --- a/sc/uiconfig/scalc/ui/validationdialog.ui +++ b/sc/uiconfig/scalc/ui/validationdialog.ui @@ -133,7 +133,7 @@ - reset + reset ok cancel help diff --git a/sc/uiconfig/scalc/ui/validationhelptabpage.ui b/sc/uiconfig/scalc/ui/validationhelptabpage.ui index 8fb8d022d9bf..9bca76b62b3f 100644 --- a/sc/uiconfig/scalc/ui/validationhelptabpage.ui +++ b/sc/uiconfig/scalc/ui/validationhelptabpage.ui @@ -111,6 +111,7 @@ True True True + False Enter the message that you want to display when the cell or cell range is selected. diff --git a/sc/uiconfig/scalc/ui/xmlsourcedialog.ui b/sc/uiconfig/scalc/ui/xmlsourcedialog.ui index 918f541e5c98..e49e65b3d073 100644 --- a/sc/uiconfig/scalc/ui/xmlsourcedialog.ui +++ b/sc/uiconfig/scalc/ui/xmlsourcedialog.ui @@ -1,11 +1,11 @@ - + True - False - sc/res/file.png + False + sc/res/file.png @@ -18,31 +18,31 @@ - False - 6 + False + 6 XML Source False - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end _Import True - True - True - True - True - True + True + True + True + True + True False @@ -54,8 +54,8 @@ _Cancel True - True - True + True + True True @@ -68,8 +68,8 @@ _Help True - True - True + True + True True @@ -83,52 +83,52 @@ False True - end + end 2 True - False - 0 - none + False + 0 + none - + True - False - True - 6 - 12 - True + False 12 6 + True + 6 + 12 + True True - True - True - Browse to set source file. + True + True + Browse to set source file. image1 True - 0 - 0 + 0 + 0 True - False + False True - not set - 0 - 1 - 0 + 1 + 0 @@ -136,7 +136,7 @@ True - False + False Source File @@ -153,92 +153,92 @@ True - False + False True True - 0 - none + 0 + none - + True - False - True - 6 - 12 - True + False 12 6 + True + 6 + 12 + True - + True - False + False start - 6 - 12 + 6 + 12 True - False + False Mapped cell: - True + True 0 - 0 - 0 + 0 + 0 2 True - True - True + True + True + 20 True - 20 - 0 - 1 + 0 + 1 True - True - True + True + True - 1 - 1 + 1 + 1 - 1 - 0 + 1 + 0 True - True + True True True - in + in - -1 + -1 True - True - True + True + True True True liststore1 - False - 1 + False + 1 @@ -263,8 +263,8 @@ - 0 - 0 + 0 + 0 @@ -272,7 +272,7 @@ True - False + False Map to Document @@ -293,9 +293,6 @@ cancel help - - - Import XML data in a spreadsheet. diff --git a/sc/workben/generate_ooxml_tablestyle_info.py b/sc/workben/generate_ooxml_tablestyle_info.py index 2ef75611db2e..6385c0daa3a5 100644 --- a/sc/workben/generate_ooxml_tablestyle_info.py +++ b/sc/workben/generate_ooxml_tablestyle_info.py @@ -1,3 +1,5 @@ +import re + import click import xml.etree.ElementTree as ET from dataclasses import dataclass @@ -19,7 +21,6 @@ class Font: @dataclass(frozen=True, order=True) class Fill: fgColor: ThemeColor - bgColor: ThemeColor class BorderStyle(Enum): @@ -167,10 +168,8 @@ def parse_fill(fill) -> Fill: assert patternFill is not None fgColor = patternFill.find("fgColor") assert fgColor is not None - bgColor = patternFill.find("bgColor") - assert bgColor is not None - return Fill(parse_color(fgColor), parse_color(bgColor)) + return Fill(parse_color(fgColor)) def parse_font(font) -> Font: @@ -306,6 +305,9 @@ def parse_table_style(style) -> TableStyle: elif table_style_name == "TableStyleDark4 ": # Trim unintended trailing space table_style_name = "TableStyleDark4" + elif table_style_name == "TableStyleLight14 ": + # Trim unintended trailing space + table_style_name = "TableStyleLight14" return TableStyle(table_style_name, [parse_table_style_element(element, style_defs) for element in list(tableStyle)]) @@ -346,7 +348,7 @@ header = """ // WARNING: This file is automatically generated and should not be manually edited! -#include +#include """ @@ -359,7 +361,6 @@ def dump_colors(dxfs: set[Dxf]) -> tuple[str, dict[ThemeColor, int]]: # first collect all ThemeColor objects for dxf in dxfs: if dxf.fill is not None: - colors.add(dxf.fill.bgColor) colors.add(dxf.fill.fgColor) if dxf.font is not None: colors.add(dxf.font.color) @@ -394,8 +395,7 @@ def dump_fills(dxfs: set[Dxf], color_map: dict[ThemeColor, int]) -> tuple[str, d for fill in sorted(fills): fill_map[fill] = currentId fg_color_id = color_map[fill.fgColor] - bg_color_id = color_map[fill.bgColor] - fillOutputs.append(f"{{ {fg_color_id}, {bg_color_id} }}") + fillOutputs.append(f"{{ {fg_color_id} }}") currentId += 1 fillOutputStr = ", ".join(fillOutputs) @@ -564,14 +564,19 @@ def dump_table_styles(table_styles: list[TableStyle], output_path: str): for table_style in sorted(table_styles): table_style_element_ids = ", ".join([f"{table_style_element_map[element]}" for element in table_style.elements]) table_style_element_str = f"{{ {table_style_element_ids} }}" - output.append(f"{{ \"{table_style.name}\", {len(table_style.elements)}, {table_style_element_str} }}") + # Extract category and number from the style name (e.g. "TableStyleLight1" -> Light, 1) + m = re.match(r"^TableStyle(Light|Medium|Dark)(\d+)\s*$", table_style.name) + assert m, f"Unexpected table style name: {table_style.name}" + category = f"TableStyleCategory::{m.group(1)}" + number = m.group(2) + output.append(f"{{ \"{table_style.name}\", {category}, {number}, {len(table_style.elements)}, {table_style_element_str} }}") output_str = ", ".join(output) table_style_str = f"constexpr TableStyle aTableStyles[] = {{ {output_str} }};\n" content.append(table_style_str) content.append(footer) - with open(output_path, "w") as f: + with open(output_path, "w", newline="\n") as f: f.write("\n".join(content)) diff --git a/scaddins/source/analysis/analysishelper.cxx b/scaddins/source/analysis/analysishelper.cxx index 8a36d99a0f7e..e6c5a7256a56 100644 --- a/scaddins/source/analysis/analysishelper.cxx +++ b/scaddins/source/analysis/analysishelper.cxx @@ -2054,7 +2054,7 @@ ConvertDataList::ConvertDataList() // LENGTH: 1 Meter is... NEWDP( "m", 1.0000000000000000E00, CDC_Length ); // Meter - NEWD( "mi", 6.2137119223733397E-04, CDC_Length ); // Britsh Mile 6,21371192237333969617434184363e-4 + NEWD( "mi", 6.2137119223733397E-04, CDC_Length ); // British Mile 6,21371192237333969617434184363e-4 NEWD( "Nmi", 5.3995680345572354E-04, CDC_Length ); // Nautical Mile 5,39956803455723542116630669546e-4 NEWD( "in", 3.9370078740157480E01, CDC_Length ); // Inch 39,37007874015748031496062992126 NEWD( "ft", 3.2808398950131234E00, CDC_Length ); // Foot 3,2808398950131233595800524934383 @@ -2145,7 +2145,7 @@ ConvertDataList::ConvertDataList() NEWDP( "L", 1.0000000000000000E00, CDC_Volume ); // Liter also NEWDP( "lt", 1.0000000000000000E00, CDC_Volume ); // Liter also NEWDP( "m3", 1.0000000000000000E-03, CDC_Volume ); // *** Cubic Meter - NEWD( "mi3", 2.3991275857892772E-13, CDC_Volume ); // *** Cubic Britsh Mile + NEWD( "mi3", 2.3991275857892772E-13, CDC_Volume ); // *** Cubic British Mile NEWD( "Nmi3", 1.5742621468581148E-13, CDC_Volume ); // *** Cubic Nautical Mile NEWD( "in3", 6.1023744094732284E01, CDC_Volume ); // *** Cubic Inch NEWD( "ft3", 3.5314666721488590E-02, CDC_Volume ); // *** Cubic Foot @@ -2171,7 +2171,7 @@ ConvertDataList::ConvertDataList() // 1 Square Meter is... NEWDP( "m2", 1.0000000000000000E00, CDC_Area ); // *** Square Meter - NEWD( "mi2", 3.8610215854244585E-07, CDC_Area ); // *** Square Britsh Mile + NEWD( "mi2", 3.8610215854244585E-07, CDC_Area ); // *** Square British Mile NEWD( "Nmi2", 2.9155334959812286E-07, CDC_Area ); // *** Square Nautical Mile NEWD( "in2", 1.5500031000062000E03, CDC_Area ); // *** Square Inch NEWD( "ft2", 1.0763910416709722E01, CDC_Area ); // *** Square Foot @@ -2193,7 +2193,7 @@ ConvertDataList::ConvertDataList() NEWDP( "m/sec", 1.0000000000000000E00, CDC_Speed ); // *** Meters per Second also NEWDP( "m/h", 3.6000000000000000E03, CDC_Speed ); // *** Meters per Hour NEWDP( "m/hr", 3.6000000000000000E03, CDC_Speed ); // *** Meters per Hour also - NEWD( "mph", 2.2369362920544023E00, CDC_Speed ); // *** Britsh Miles per Hour + NEWD( "mph", 2.2369362920544023E00, CDC_Speed ); // *** British Miles per Hour NEWD( "kn", 1.9438444924406048E00, CDC_Speed ); // *** Knot = Nautical Miles per Hour NEWD( "admkn", 1.9438446603753486E00, CDC_Speed ); // *** Admiralty Knot NEWD( "ludicrous speed", 2.0494886343432328E-14, CDC_Speed ); // *** diff --git a/sccomp/CppunitTest_sccomp_solver.mk b/sccomp/CppunitTest_sccomp_solver.mk deleted file mode 100644 index 818b27e5a0a6..000000000000 --- a/sccomp/CppunitTest_sccomp_solver.mk +++ /dev/null @@ -1,43 +0,0 @@ -# -*- 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,sccomp_solver)) - -$(eval $(call gb_CppunitTest_add_exception_objects,sccomp_solver,\ - sccomp/qa/unit/solver \ -)) - -$(eval $(call gb_CppunitTest_add_defs,sccomp_solver,\ - $(if $(ENABLE_COINMP), -DENABLE_COINMP) \ - $(if $(ENABLE_LPSOLVE), -DENABLE_LPSOLVE) \ -)) - -$(eval $(call gb_CppunitTest_use_libraries,sccomp_solver,\ - cppu \ - sal \ - test \ - unotest \ -)) - -$(eval $(call gb_CppunitTest_set_include,sccomp_solver,\ - -I$(SRCDIR)/sc/inc \ - $$(INCLUDE) \ -)) - - -$(eval $(call gb_CppunitTest_use_sdk_api,sccomp_solver)) - -$(eval $(call gb_CppunitTest_use_ure,sccomp_solver)) -$(eval $(call gb_CppunitTest_use_vcl,sccomp_solver)) - -$(eval $(call gb_CppunitTest_use_rdb,sccomp_solver,services)) - -$(eval $(call gb_CppunitTest_use_configuration,sccomp_solver)) - -# vim: set noet sw=4 ts=4: diff --git a/sccomp/IwyuFilter_sccomp.yaml b/sccomp/IwyuFilter_sccomp.yaml deleted file mode 100644 index be2dc6eb42cf..000000000000 --- a/sccomp/IwyuFilter_sccomp.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -assumeFilename: sccomp/source/solver/SolverComponent.cxx -excludelist: - sccomp/source/solver/SolverComponent.hxx: - # Base class needs full type - - com/sun/star/sheet/XSolver.hpp - - com/sun/star/sheet/XSolverDescription.hpp - - com/sun/star/lang/XServiceInfo.hpp - sccomp/source/solver/SolverComponent.cxx: - # Actually used - - com/sun/star/sheet/XSpreadsheetDocument.hpp diff --git a/sccomp/Module_sccomp.mk b/sccomp/Module_sccomp.mk deleted file mode 100644 index e211ee26f958..000000000000 --- a/sccomp/Module_sccomp.mk +++ /dev/null @@ -1,35 +0,0 @@ -# -*- 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/. -# -# 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 . -# - -$(eval $(call gb_Module_Module,sccomp)) - -$(eval $(call gb_Module_add_targets,sccomp,\ - Library_solver \ -)) - -$(eval $(call gb_Module_add_l10n_targets,sccomp,\ - AllLangMoTarget_scc \ -)) - -$(eval $(call gb_Module_add_check_targets,sccomp,\ - CppunitTest_sccomp_solver \ - $(if $(and $(filter INTEL,$(CPUNAME)),$(filter -fsanitize=%,$(gb_CXX))),,$(if $(filter SCRIPTING,$(BUILD_TYPE)),CppunitTest_sccomp_swarmsolvertest)) \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/sccomp/README.md b/sccomp/README.md deleted file mode 100644 index 7927fcda415d..000000000000 --- a/sccomp/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Linear Solver for LibreOffice Calc - -The (linear) solver for LibreOffice Calc. diff --git a/sccomp/qa/unit/SwarmSolverTest.cxx b/sccomp/qa/unit/SwarmSolverTest.cxx deleted file mode 100644 index f1104fa081a8..000000000000 --- a/sccomp/qa/unit/SwarmSolverTest.cxx +++ /dev/null @@ -1,325 +0,0 @@ -/* -*- 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 - -#include -#include -#include -#include - -#include - -using namespace css; - -namespace -{ -class SwarmSolverTest : public UnoApiTest -{ - void testUnconstrained(); - void testVariableBounded(); - void testVariableConstrained(); - void testTwoVariables(); - void testMultipleVariables(); - -public: - SwarmSolverTest() - : UnoApiTest(u"sccomp/qa/unit/data"_ustr) - { - } - - CPPUNIT_TEST_SUITE(SwarmSolverTest); - CPPUNIT_TEST(testUnconstrained); - CPPUNIT_TEST(testVariableBounded); - CPPUNIT_TEST(testVariableConstrained); - CPPUNIT_TEST(testMultipleVariables); - CPPUNIT_TEST(testTwoVariables); - CPPUNIT_TEST_SUITE_END(); -}; - -void SwarmSolverTest::testUnconstrained() -{ - loadFromFile(u"Simple.ods"); - - uno::Reference xDocument(mxComponent, uno::UNO_QUERY_THROW); - uno::Reference xIndex(xDocument->getSheets(), uno::UNO_QUERY_THROW); - uno::Reference xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW); - - uno::Reference xSolver; - - xSolver.set(m_xContext->getServiceManager()->createInstanceWithContext( - u"com.sun.star.comp.Calc.SwarmSolver"_ustr, m_xContext), - uno::UNO_QUERY_THROW); - - table::CellAddress aObjective(0, 1, 1); - - // "changing cells" - unknown variables - uno::Sequence aVariables{ { 0, 1, 0 } }; - - // constraints - uno::Sequence aConstraints; - - // initialize solver - xSolver->setDocument(xDocument); - xSolver->setObjective(aObjective); - xSolver->setVariables(aVariables); - xSolver->setConstraints(aConstraints); - xSolver->setMaximize(false); - - // test results - xSolver->solve(); - CPPUNIT_ASSERT(xSolver->getSuccess()); - uno::Sequence aSolution = xSolver->getSolution(); - - CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); - // It happens that the unconstrained test does not find a solution in the - // timeframe or number of generations it has available as the search space is - // too big and the values might not converge to solution. So for now just run - // the test so we know for sure the algorithm is guaranteed to finish - // and doesn't cause any seg faults. - //CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[0], .9); -} - -void SwarmSolverTest::testVariableBounded() -{ - loadFromFile(u"Simple.ods"); - - uno::Reference xDocument(mxComponent, uno::UNO_QUERY_THROW); - uno::Reference xIndex(xDocument->getSheets(), uno::UNO_QUERY_THROW); - uno::Reference xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW); - - uno::Reference xSolver; - - xSolver.set(m_xContext->getServiceManager()->createInstanceWithContext( - u"com.sun.star.comp.Calc.SwarmSolver"_ustr, m_xContext), - uno::UNO_QUERY_THROW); - - table::CellAddress aObjective(0, 1, 1); - - // "changing cells" - unknown variables - uno::Sequence aVariables{ { 0, 1, 0 } }; - - // constraints - uno::Sequence aConstraints{ - { /* [0] Left */ table::CellAddress(0, 1, 0), - /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, - /* Right */ uno::Any(100.0) }, - { /* [1] Left */ table::CellAddress(0, 1, 0), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(-100.0) } - }; - - // initialize solver - xSolver->setDocument(xDocument); - xSolver->setObjective(aObjective); - xSolver->setVariables(aVariables); - xSolver->setConstraints(aConstraints); - xSolver->setMaximize(false); - - // test results - xSolver->solve(); - CPPUNIT_ASSERT(xSolver->getSuccess()); - uno::Sequence aSolution = xSolver->getSolution(); - - CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); - CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[0], 1E-5); -} - -void SwarmSolverTest::testVariableConstrained() -{ - loadFromFile(u"Simple.ods"); - - uno::Reference xDocument(mxComponent, uno::UNO_QUERY_THROW); - uno::Reference xIndex(xDocument->getSheets(), uno::UNO_QUERY_THROW); - uno::Reference xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW); - - uno::Reference xSolver; - - xSolver.set(m_xContext->getServiceManager()->createInstanceWithContext( - u"com.sun.star.comp.Calc.SwarmSolver"_ustr, m_xContext), - uno::UNO_QUERY_THROW); - - table::CellAddress aObjective(0, 1, 1); - - // "changing cells" - unknown variables - uno::Sequence aVariables{ { 0, 1, 0 } }; - - // constraints - uno::Sequence aConstraints{ - { /* [0] Left */ table::CellAddress(0, 1, 0), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(-50000.0) }, - { /* [1] Left */ table::CellAddress(0, 1, 0), - /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, - /* Right */ uno::Any(0.0) }, - { /* [2] Left */ table::CellAddress(0, 1, 1), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(10.0) } - }; - - // initialize solver - xSolver->setDocument(xDocument); - xSolver->setObjective(aObjective); - xSolver->setVariables(aVariables); - xSolver->setConstraints(aConstraints); - xSolver->setMaximize(false); - - // test results - xSolver->solve(); - CPPUNIT_ASSERT(xSolver->getSuccess()); - uno::Sequence aSolution = xSolver->getSolution(); - - CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); - CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.741657, aSolution[0], 1E-5); -} - -void SwarmSolverTest::testTwoVariables() -{ - loadFromFile(u"TwoVariables.ods"); - - uno::Reference xDocument(mxComponent, uno::UNO_QUERY_THROW); - uno::Reference xIndex(xDocument->getSheets(), uno::UNO_QUERY_THROW); - uno::Reference xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW); - - uno::Reference xSolver; - - xSolver.set(m_xContext->getServiceManager()->createInstanceWithContext( - u"com.sun.star.comp.Calc.SwarmSolver"_ustr, m_xContext), - uno::UNO_QUERY_THROW); - - table::CellAddress aObjective(0, 1, 5); - - // "changing cells" - unknown variables - uno::Sequence aVariables{ { 0, 1, 2 }, { 0, 1, 3 } }; - - // constraints - uno::Sequence aConstraints{ - { /* [0] Left */ table::CellAddress(0, 1, 2), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(-100.0) }, - { /* [1] Left */ table::CellAddress(0, 1, 3), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(-100.0) }, - { /* [2] Left */ table::CellAddress(0, 1, 2), - /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, - /* Right */ uno::Any(100.0) }, - { /* [3] Left */ table::CellAddress(0, 1, 3), - /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, - /* Right */ uno::Any(100.0) } - }; - - // initialize solver - xSolver->setDocument(xDocument); - xSolver->setObjective(aObjective); - xSolver->setVariables(aVariables); - xSolver->setConstraints(aConstraints); - xSolver->setMaximize(true); - - // test results - xSolver->solve(); - CPPUNIT_ASSERT(xSolver->getSuccess()); - uno::Sequence aSolution = xSolver->getSolution(); - - CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); - CPPUNIT_ASSERT_DOUBLES_EQUAL(0.666667, aSolution[0], 1E-5); - CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.666667, aSolution[1], 1E-5); -} - -void SwarmSolverTest::testMultipleVariables() -{ - loadFromFile(u"MultiVariable.ods"); - - uno::Reference xDocument(mxComponent, uno::UNO_QUERY_THROW); - uno::Reference xIndex(xDocument->getSheets(), uno::UNO_QUERY_THROW); - uno::Reference xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW); - - uno::Reference xSolver; - - xSolver.set(m_xContext->getServiceManager()->createInstanceWithContext( - u"com.sun.star.comp.Calc.SwarmSolver"_ustr, m_xContext), - uno::UNO_QUERY_THROW); - - uno::Reference xPropSet(xSolver, uno::UNO_QUERY_THROW); - xPropSet->setPropertyValue(u"Integer"_ustr, uno::Any(true)); - - table::CellAddress aObjective(0, 5, 7); - - // "changing cells" - unknown variables - uno::Sequence aVariables{ - { 0, 6, 1 }, { 0, 6, 2 }, { 0, 6, 3 }, { 0, 6, 4 } - }; - - // constraints - uno::Sequence aConstraints{ - { /* [ 0] Left */ table::CellAddress(0, 1, 5), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(table::CellAddress(0, 1, 6)) }, - { /* [ 1] Left */ table::CellAddress(0, 2, 5), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(table::CellAddress(0, 2, 6)) }, - { /* [ 2] Left */ table::CellAddress(0, 3, 5), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(table::CellAddress(0, 3, 6)) }, - { /* [ 3] Left */ table::CellAddress(0, 4, 5), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(table::CellAddress(0, 4, 6)) }, - { /* [ 4] Left */ table::CellAddress(0, 6, 1), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(0.0) }, - { /* [ 5] Left */ table::CellAddress(0, 6, 2), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(0.0) }, - { /* [ 6] Left */ table::CellAddress(0, 6, 3), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(0.0) }, - { /* [ 7] Left */ table::CellAddress(0, 6, 4), - /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL, - /* Right */ uno::Any(0.0) }, - { /* [ 8] Left */ table::CellAddress(0, 6, 1), - /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, - /* Right */ uno::Any(10000.0) }, - { /* [ 9] Left */ table::CellAddress(0, 6, 2), - /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, - /* Right */ uno::Any(10000.0) }, - { /* [10] Left */ table::CellAddress(0, 6, 3), - /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, - /* Right */ uno::Any(10000.0) }, - { /* [11] Left */ table::CellAddress(0, 6, 4), - /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, - /* Right */ uno::Any(10000.0) } - }; - - // initialize solver - xSolver->setDocument(xDocument); - xSolver->setObjective(aObjective); - xSolver->setVariables(aVariables); - xSolver->setConstraints(aConstraints); - xSolver->setMaximize(false); - - // test results - xSolver->solve(); - CPPUNIT_ASSERT(xSolver->getSuccess()); - uno::Sequence aSolution = xSolver->getSolution(); - - CPPUNIT_ASSERT_EQUAL(aVariables.getLength(), aSolution.getLength()); -#if 0 - // Disable for now, needs algorithm stability improvements - CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution[0], 1E-5); - CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[1], 1E-5); - CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aSolution[2], 1E-5); - CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution[3], 1E-5); -#endif -} - -CPPUNIT_TEST_SUITE_REGISTRATION(SwarmSolverTest); -} - -CPPUNIT_PLUGIN_IMPLEMENT(); - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/qa/unit/solver.cxx b/sccomp/qa/unit/solver.cxx deleted file mode 100644 index 536df7425bb9..000000000000 --- a/sccomp/qa/unit/solver.cxx +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- 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 - -#include -#include -#include -#include - -using namespace css; - -namespace { - -class LpSolverTest: public test::BootstrapFixture -{ - uno::Reference m_xDocument; - -#ifdef ENABLE_LPSOLVE - void testLpSolver(); -#endif -#ifdef ENABLE_COINMP - void testCoinMPSolver(); -#endif - -#if defined(ENABLE_LPSOLVE) || defined(ENABLE_COINMP) - void testSolver(OUString const & rName); -#endif - -public: - virtual void setUp() override; - virtual void tearDown() override; - - CPPUNIT_TEST_SUITE(LpSolverTest); -#ifdef ENABLE_LPSOLVE - CPPUNIT_TEST(testLpSolver); -#endif -#ifdef ENABLE_COINMP - CPPUNIT_TEST(testCoinMPSolver); -#endif - CPPUNIT_TEST_SUITE_END(); -}; - -void LpSolverTest::setUp() -{ - test::BootstrapFixture::setUp(); - uno::Reference xComponentLoader = frame::Desktop::create(m_xContext); - uno::Reference xComponent(xComponentLoader->loadComponentFromURL( - u"private:factory/scalc"_ustr, u"_blank"_ustr, 0, - uno::Sequence < css::beans::PropertyValue >())); - m_xDocument.set(xComponent, uno::UNO_QUERY_THROW); -} - -void LpSolverTest::tearDown() -{ - uno::Reference(m_xDocument, uno::UNO_QUERY_THROW)->dispose(); - m_xDocument.clear(); - test::BootstrapFixture::tearDown(); -} - -#ifdef ENABLE_LPSOLVE -void LpSolverTest::testLpSolver() -{ - testSolver(u"com.sun.star.comp.Calc.LpsolveSolver"_ustr); -} -#endif - -#ifdef ENABLE_COINMP -void LpSolverTest::testCoinMPSolver() -{ - testSolver(u"com.sun.star.comp.Calc.CoinMPSolver"_ustr); -} -#endif - -#if defined(ENABLE_LPSOLVE) || defined(ENABLE_COINMP) -void LpSolverTest::testSolver(OUString const & rName) -{ - uno::Reference xSolver(m_xContext->getServiceManager()-> - createInstanceWithContext(rName, m_xContext), uno::UNO_QUERY_THROW); - - table::CellAddress aObjective(0, 0, 0); - - // "changing cells" - unknown variables - uno::Sequence aVariables { {0, 0, 0 } }; - - // constraints - uno::Sequence aConstraints{ - { /* Left */ table::CellAddress(0, 0, 0), - /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL, - /* Right */ uno::Any(5.0) } - }; - - // initialize solver - xSolver->setDocument( m_xDocument ); - xSolver->setObjective( aObjective ); - xSolver->setVariables( aVariables ); - xSolver->setConstraints( aConstraints ); - xSolver->setMaximize( true ); - - // test results - xSolver->solve(); - CPPUNIT_ASSERT(xSolver->getSuccess()); - uno::Sequence aSolution = xSolver->getSolution(); - CPPUNIT_ASSERT_EQUAL(aSolution.getLength(), aVariables.getLength()); - CPPUNIT_ASSERT_EQUAL(5.0, aSolution[0]); - - uno::Reference xDesc(xSolver, uno::UNO_QUERY_THROW); - const OString sMessage("Empty description for " + OUStringToOString(rName, RTL_TEXTENCODING_UTF8)); - CPPUNIT_ASSERT_MESSAGE(sMessage.getStr(), !xDesc->getComponentDescription().isEmpty()); -} -#endif - -CPPUNIT_TEST_SUITE_REGISTRATION(LpSolverTest); - -} - -CPPUNIT_PLUGIN_IMPLEMENT(); - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/CoinMPSolver.cxx b/sccomp/source/solver/CoinMPSolver.cxx deleted file mode 100644 index 53a787e4721c..000000000000 --- a/sccomp/source/solver/CoinMPSolver.cxx +++ /dev/null @@ -1,365 +0,0 @@ -/* -*- 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 -#include - -#include "SolverComponent.hxx" -#include - -#include -#include - -#include -#include -#include -#include - -namespace com::sun::star::uno { class XComponentContext; } - -using namespace com::sun::star; - -namespace { - -class CoinMPSolver : public SolverComponent -{ -public: - CoinMPSolver() {} - -private: - virtual void SAL_CALL solve() override; - virtual OUString SAL_CALL getImplementationName() override - { - return u"com.sun.star.comp.Calc.CoinMPSolver"_ustr; - } - virtual OUString SAL_CALL getComponentDescription() override - { - return SolverComponent::GetResourceString( RID_COINMP_SOLVER_COMPONENT ); - } -}; - -} - -void SAL_CALL CoinMPSolver::solve() -{ - uno::Reference xModel( mxDoc, uno::UNO_QUERY_THROW ); - - maStatus.clear(); - mbSuccess = false; - - xModel->lockControllers(); - - // collect variables in vector (?) - - const auto & aVariableCells = maVariables; - size_t nVariables = aVariableCells.size(); - size_t nVar = 0; - - // collect all dependent cells - - ScSolverCellHashMap aCellsHash; - aCellsHash[maObjective].reserve( nVariables + 1 ); // objective function - - for (const auto& rConstr : maConstraints) - { - table::CellAddress aCellAddr = rConstr.Left; - aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: left hand side - - if ( rConstr.Right >>= aCellAddr ) - aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: right hand side - } - - // set all variables to zero - //! store old values? - //! use old values as initial values? - for ( const auto& rVarCell : aVariableCells ) - { - SolverComponent::SetValue( mxDoc, rVarCell, 0.0 ); - } - - // read initial values from all dependent cells - for ( auto& rEntry : aCellsHash ) - { - double fValue = SolverComponent::GetValue( mxDoc, rEntry.first ); - rEntry.second.push_back( fValue ); // store as first element, as-is - } - - // loop through variables - for ( const auto& rVarCell : aVariableCells ) - { - SolverComponent::SetValue( mxDoc, rVarCell, 1.0 ); // set to 1 to examine influence - - // read value change from all dependent cells - for ( auto& rEntry : aCellsHash ) - { - double fChanged = SolverComponent::GetValue( mxDoc, rEntry.first ); - double fInitial = rEntry.second.front(); - rEntry.second.push_back( fChanged - fInitial ); - } - - SolverComponent::SetValue( mxDoc, rVarCell, 2.0 ); // minimal test for linearity - - for ( const auto& rEntry : aCellsHash ) - { - double fInitial = rEntry.second.front(); - double fCoeff = rEntry.second.back(); // last appended: coefficient for this variable - double fTwo = SolverComponent::GetValue( mxDoc, rEntry.first ); - - bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) || - rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff ); - // second comparison is needed in case fTwo is zero - if ( !bLinear ) - maStatus = SolverComponent::GetResourceString( RID_ERROR_NONLINEAR ); - } - - SolverComponent::SetValue( mxDoc, rVarCell, 0.0 ); // set back to zero for examining next variable - } - - xModel->unlockControllers(); - - if ( !maStatus.isEmpty() ) - return; - - // - // build parameter arrays for CoinMP - // - - // set objective function - - const std::vector& rObjCoeff = aCellsHash[maObjective]; - std::unique_ptr pObjectCoeffs(new double[nVariables]); - for (nVar=0; nVar pCompMatrix(new double[nCompSize]); // first collect all coefficients, row-wise - for (size_t i=0; i pRHS(new double[nRows]); - std::unique_ptr pRowType(new char[nRows]); - for (size_t i=0; i>= aRightAddr ) - bRightCell = true; // cell specified as right-hand side - else - rRightAny >>= fDirectValue; // constant value - - table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left; - - const std::vector& rLeftCoeff = aCellsHash[aLeftAddr]; - double* pValues = &pCompMatrix[nConstrPos * nVariables]; - for (nVar=0; nVar& rRightCoeff = aCellsHash[aRightAddr]; - // modify pValues with rhs coefficients - for (nVar=0; nVar pMatrixBegin(new int[nVariables+1]); - std::unique_ptr pMatrixCount(new int[nVariables]); - std::unique_ptr pMatrix(new double[nCompSize]); // not always completely used - std::unique_ptr pMatrixIndex(new int[nCompSize]); - int nMatrixPos = 0; - for (nVar=0; nVar pLowerBounds(new double[nVariables]); - std::unique_ptr pUpperBounds(new double[nVariables]); - for (nVar=0; nVar pColType(new char[nVariables]); - for (nVar=0; nVar const &) -{ - return cppu::acquire(new CoinMPSolver()); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/DifferentialEvolution.hxx b/sccomp/source/solver/DifferentialEvolution.hxx deleted file mode 100644 index 37f4c35064ab..000000000000 --- a/sccomp/source/solver/DifferentialEvolution.hxx +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- 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/. - * - */ - -#pragma once - -#include -#include -#include - -struct Individual -{ - std::vector mVariables; -}; - -template class DifferentialEvolutionAlgorithm -{ - static constexpr double mnDifferentialWeight = 0.5; // [0, 2] - static constexpr double mnCrossoverProbability = 0.9; // [0, 1] - - static constexpr double constAcceptedPrecision = 0.000000001; - - DataProvider& mrDataProvider; - - size_t mnPopulationSize; - std::vector maPopulation; - - std::random_device maRandomDevice; - std::mt19937 maGenerator; - size_t mnDimensionality; - - std::uniform_int_distribution<> maRandomPopulation; - std::uniform_int_distribution<> maRandomDimensionality; - std::uniform_real_distribution<> maRandom01; - - Individual maBestCandidate; - double mfBestFitness; - int mnGeneration; - int mnLastChange; - -public: - DifferentialEvolutionAlgorithm(DataProvider& rDataProvider, size_t nPopulationSize) - : mrDataProvider(rDataProvider) - , mnPopulationSize(nPopulationSize) - , maGenerator(maRandomDevice()) - , mnDimensionality(mrDataProvider.getDimensionality()) - , maRandomPopulation(0, mnPopulationSize - 1) - , maRandomDimensionality(0, mnDimensionality - 1) - , maRandom01(0.0, 1.0) - , mfBestFitness(std::numeric_limits::lowest()) - , mnGeneration(0) - , mnLastChange(0) - { - } - - std::vector const& getResult() { return maBestCandidate.mVariables; } - - int getGeneration() { return mnGeneration; } - - int getLastChange() { return mnLastChange; } - - void initialize() - { - mnGeneration = 0; - mnLastChange = 0; - maPopulation.clear(); - maBestCandidate.mVariables.clear(); - - // Initialize population with individuals that have been initialized with uniform random - // noise - // uniform noise means random value inside your search space - maPopulation.reserve(mnPopulationSize); - for (size_t i = 0; i < mnPopulationSize; ++i) - { - maPopulation.emplace_back(); - Individual& rIndividual = maPopulation.back(); - mrDataProvider.initializeVariables(rIndividual.mVariables, maGenerator); - } - } - - // Calculate one generation - bool next() - { - bool bBestChanged = false; - - for (size_t agentIndex = 0; agentIndex < mnPopulationSize; ++agentIndex) - { - // calculate new candidate solution - - // pick random point from population - size_t x = agentIndex; // randomPopulation(generator); - size_t a, b, c; - - // create a copy of chosen random agent in population - Individual& rOriginal = maPopulation[x]; - Individual aCandidate(rOriginal); - - // pick three different random points from population - do - { - a = maRandomPopulation(maGenerator); - } while (a == x); - - do - { - b = maRandomPopulation(maGenerator); - } while (b == x || b == a); - - do - { - c = maRandomPopulation(maGenerator); - - } while (c == x || c == a || c == b); - - size_t randomIndex = maRandomDimensionality(maGenerator); - - for (size_t index = 0; index < mnDimensionality; ++index) - { - double randomCrossoverProbability = maRandom01(maGenerator); - if (index == randomIndex || randomCrossoverProbability < mnCrossoverProbability) - { - double fVarA = maPopulation[a].mVariables[index]; - double fVarB = maPopulation[b].mVariables[index]; - double fVarC = maPopulation[c].mVariables[index]; - - double fNewValue = fVarA + mnDifferentialWeight * (fVarB - fVarC); - fNewValue = mrDataProvider.boundVariable(index, fNewValue); - aCandidate.mVariables[index] = fNewValue; - } - } - - double fCandidateFitness = mrDataProvider.calculateFitness(aCandidate.mVariables); - - // see if is better than original, if so replace - if (fCandidateFitness > mrDataProvider.calculateFitness(rOriginal.mVariables)) - { - maPopulation[x] = std::move(aCandidate); - - if (fCandidateFitness > mfBestFitness) - { - if (std::abs(fCandidateFitness - mfBestFitness) > constAcceptedPrecision) - { - bBestChanged = true; - mnLastChange = mnGeneration; - } - mfBestFitness = fCandidateFitness; - maBestCandidate = maPopulation[x]; - } - } - } - mnGeneration++; - return bBestChanged; - } -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/LpsolveSolver.cxx b/sccomp/source/solver/LpsolveSolver.cxx deleted file mode 100644 index cda134a3d383..000000000000 --- a/sccomp/source/solver/LpsolveSolver.cxx +++ /dev/null @@ -1,452 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - * 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 -#include - -#undef LANGUAGE_NONE -#if defined _WIN32 -#define WINAPI __stdcall -#endif -#define LoadInverseLib FALSE -#define LoadLanguageLib FALSE -#ifdef SYSTEM_LPSOLVE -#include -#else -#include -#endif -#undef LANGUAGE_NONE - -#include "SolverComponent.hxx" -#include - -#include -#include -#include -#include -#include -#include - -namespace com::sun::star::uno { class XComponentContext; } - -using namespace com::sun::star; - -namespace { - -class LpsolveSolver : public SolverComponent -{ -public: - LpsolveSolver() {} - -private: - virtual void SAL_CALL solve() override; - virtual OUString SAL_CALL getImplementationName() override - { - return u"com.sun.star.comp.Calc.LpsolveSolver"_ustr; - } - virtual OUString SAL_CALL getComponentDescription() override - { - return SolverComponent::GetResourceString( RID_SOLVER_COMPONENT ); - } -}; - -} - -void SAL_CALL LpsolveSolver::solve() -{ - uno::Reference xModel( mxDoc, uno::UNO_QUERY_THROW ); - - maStatus.clear(); - mbSuccess = false; - - if ( mnEpsilonLevel < EPS_TIGHT || mnEpsilonLevel > EPS_BAGGY ) - { - maStatus = SolverComponent::GetResourceString( RID_ERROR_EPSILONLEVEL ); - return; - } - - xModel->lockControllers(); - - // collect variables in vector (?) - - const auto & aVariableCells = maVariables; - size_t nVariables = aVariableCells.size(); - size_t nVar = 0; - - // Store all RHS values - sal_uInt32 nConstraints = maConstraints.size(); - m_aConstrRHS.realloc(nConstraints); - - // collect all dependent cells - - ScSolverCellHashMap aCellsHash; - aCellsHash[maObjective].reserve( nVariables + 1 ); // objective function - - for (const auto& rConstr : maConstraints) - { - table::CellAddress aCellAddr = rConstr.Left; - aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: left hand side - - if ( rConstr.Right >>= aCellAddr ) - aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: right hand side - } - - // set all variables to zero - //! store old values? - //! use old values as initial values? - for ( const auto& rVarCell : aVariableCells ) - { - SolverComponent::SetValue( mxDoc, rVarCell, 0.0 ); - } - - // read initial values from all dependent cells - for ( auto& rEntry : aCellsHash ) - { - double fValue = SolverComponent::GetValue( mxDoc, rEntry.first ); - rEntry.second.push_back( fValue ); // store as first element, as-is - } - - // loop through variables - for ( const auto& rVarCell : aVariableCells ) - { - SolverComponent::SetValue( mxDoc, rVarCell, 1.0 ); // set to 1 to examine influence - - // read value change from all dependent cells - for ( auto& rEntry : aCellsHash ) - { - double fChanged = SolverComponent::GetValue( mxDoc, rEntry.first ); - double fInitial = rEntry.second.front(); - rEntry.second.push_back( fChanged - fInitial ); - } - - SolverComponent::SetValue( mxDoc, rVarCell, 2.0 ); // minimal test for linearity - - for ( const auto& rEntry : aCellsHash ) - { - double fInitial = rEntry.second.front(); - double fCoeff = rEntry.second.back(); // last appended: coefficient for this variable - double fTwo = SolverComponent::GetValue( mxDoc, rEntry.first ); - - bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) || - rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff ); - // second comparison is needed in case fTwo is zero - if ( !bLinear ) - maStatus = SolverComponent::GetResourceString( RID_ERROR_NONLINEAR ); - } - - SolverComponent::SetValue( mxDoc, rVarCell, 0.0 ); // set back to zero for examining next variable - } - - xModel->unlockControllers(); - - if ( !maStatus.isEmpty() ) - return; - - - // build lp_solve model - - - lprec* lp = make_lp( 0, nVariables ); - if ( !lp ) - return; - - set_outputfile( lp, const_cast( "" ) ); // no output - - // set objective function - - const std::vector& rObjCoeff = aCellsHash[maObjective]; - std::unique_ptr pObjVal(new REAL[nVariables+1]); - pObjVal[0] = 0.0; // ignored - for (nVar=0; nVar>= aRightAddr ) - bRightCell = true; // cell specified as right-hand side - else - rRightAny >>= fDirectValue; // constant value - - table::CellAddress aLeftAddr = rConstr.Left; - - const std::vector& rLeftCoeff = aCellsHash[aLeftAddr]; - std::unique_ptr pValues(new REAL[nVariables+1] ); - pValues[0] = 0.0; // ignored? - for (nVar=0; nVar& rRightCoeff = aCellsHash[aRightAddr]; - // modify pValues with rhs coefficients - for (nVar=0; nVar(is_infinite(lp, pObjFrom[i]))) - pObjDecrease[i] = get_infinite(lp); - else - pObjDecrease[i] = rObjCoeff[i + 1] - pObjFrom[i]; - - // Allowed increase - if (static_cast(is_infinite(lp, pObjTill[i]))) - pObjIncrease[i] = get_infinite(lp); - else - pObjIncrease[i] = pObjTill[i] - rObjCoeff[i + 1]; - } - - // Save objective coefficients for the sensitivity report - double* pObjCoefficients(new double[nVariables]); - for (size_t i = 0; i < nVariables; i++) - pObjCoefficients[i] = rObjCoeff[i + 1]; - m_aObjCoefficients.realloc(nVariables); - std::copy_n(pObjCoefficients, nVariables, m_aObjCoefficients.getArray()); - - // The reduced costs are in pConstrDual after the constraints - double* pObjRedCost(new double[nVariables]); - for (size_t i = 0; i < nVariables; i++) - pObjRedCost[i] = pConstrDual[nConstraints + i]; - m_aObjRedCost.realloc(nVariables); - std::copy_n(pObjRedCost, nVariables, m_aObjRedCost.getArray()); - - // Final value of constraints - get_ptr_constraints(lp, &pConstrValue); - m_aConstrValue.realloc(nConstraints); - std::copy_n(pConstrValue, nConstraints, m_aConstrValue.getArray()); - - // The RHS contains information for each constraint - m_aConstrDual.realloc(nConstraints); - m_aConstrDecrease.realloc(nConstraints); - m_aConstrIncrease.realloc(nConstraints); - std::copy_n(pConstrDual, nConstraints, m_aConstrDual.getArray()); - double* pConstrDecrease = m_aConstrDecrease.getArray(); - double* pConstrIncrease = m_aConstrIncrease.getArray(); - - for (sal_uInt32 i = 0; i < nConstraints; i++) - { - // Allowed decrease - pConstrDecrease[i] = m_aConstrRHS[i] - pConstrFrom[i]; - if (static_cast(is_infinite(lp, pConstrFrom[i])) - && maConstraints[i].Operator == sheet::SolverConstraintOperator_LESS_EQUAL) - pConstrDecrease[i] = m_aConstrRHS[i] - m_aConstrValue[i]; - - // Allowed increase - pConstrIncrease[i] = pConstrTill[i] - m_aConstrRHS[i]; - if (static_cast(is_infinite(lp, pConstrTill[i])) - && maConstraints[i].Operator == sheet::SolverConstraintOperator_GREATER_EQUAL) - pConstrIncrease[i] = m_aConstrValue[i] - m_aConstrRHS[i]; - } - - // Set all values of the SensitivityReport object - m_aSensitivityReport.ObjCoefficients = m_aObjCoefficients; - m_aSensitivityReport.ObjReducedCosts = m_aObjRedCost; - m_aSensitivityReport.ObjAllowableDecreases = m_aObjDecrease; - m_aSensitivityReport.ObjAllowableIncreases = m_aObjIncrease; - m_aSensitivityReport.ConstrValues = m_aConstrValue; - m_aSensitivityReport.ConstrRHS = m_aConstrRHS; - m_aSensitivityReport.ConstrShadowPrices = m_aConstrDual; - m_aSensitivityReport.ConstrAllowableDecreases = m_aConstrDecrease; - m_aSensitivityReport.ConstrAllowableIncreases = m_aConstrIncrease; - } - } - } - else if ( nResult == INFEASIBLE ) - maStatus = SolverComponent::GetResourceString( RID_ERROR_INFEASIBLE ); - else if ( nResult == UNBOUNDED ) - maStatus = SolverComponent::GetResourceString( RID_ERROR_UNBOUNDED ); - else if ( nResult == TIMEOUT || nResult == SUBOPTIMAL ) - maStatus = SolverComponent::GetResourceString( RID_ERROR_TIMEOUT ); - // SUBOPTIMAL is assumed to be caused by a timeout, and reported as an error - - delete_lp( lp ); -} - -extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * -com_sun_star_comp_Calc_LpsolveSolver_get_implementation( - css::uno::XComponentContext *, - css::uno::Sequence const &) -{ - return cppu::acquire(new LpsolveSolver()); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/ParticelSwarmOptimization.hxx b/sccomp/source/solver/ParticelSwarmOptimization.hxx deleted file mode 100644 index ad1103309341..000000000000 --- a/sccomp/source/solver/ParticelSwarmOptimization.hxx +++ /dev/null @@ -1,177 +0,0 @@ -/* -*- 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/. - * - */ - -#pragma once - -#include -#include -#include - -struct Particle -{ - Particle(size_t nDimensionality) - : mVelocity(nDimensionality) - , mPosition(nDimensionality) - , mCurrentFitness(std::numeric_limits::lowest()) - , mBestPosition(nDimensionality) - , mBestFitness(std::numeric_limits::lowest()) - { - } - - std::vector mVelocity; - - std::vector mPosition; - double mCurrentFitness; - - std::vector mBestPosition; - double mBestFitness; -}; - -template class ParticleSwarmOptimizationAlgorithm -{ -private: - // inertia - static constexpr double constWeight = 0.729; - // cognitive coefficient - static constexpr double c1 = 1.49445; - // social coefficient - static constexpr double c2 = 1.49445; - - static constexpr double constAcceptedPrecision = 0.000000001; - - DataProvider& mrDataProvider; - - size_t mnNumOfParticles; - - std::vector maSwarm; - - std::random_device maRandomDevice; - std::mt19937 maGenerator; - size_t mnDimensionality; - - std::uniform_real_distribution<> maRandom01; - - std::vector maBestPosition; - double mfBestFitness; - int mnGeneration; - int mnLastChange; - -public: - ParticleSwarmOptimizationAlgorithm(DataProvider& rDataProvider, size_t nNumOfParticles) - : mrDataProvider(rDataProvider) - , mnNumOfParticles(nNumOfParticles) - , maGenerator(maRandomDevice()) - , mnDimensionality(mrDataProvider.getDimensionality()) - , maRandom01(0.0, 1.0) - , maBestPosition(mnDimensionality) - , mfBestFitness(std::numeric_limits::lowest()) - , mnGeneration(0) - , mnLastChange(0) - { - } - - std::vector const& getResult() { return maBestPosition; } - - int getGeneration() { return mnGeneration; } - - int getLastChange() { return mnLastChange; } - - void initialize() - { - mnGeneration = 0; - mnLastChange = 0; - maSwarm.clear(); - - mfBestFitness = std::numeric_limits::lowest(); - - maSwarm.reserve(mnNumOfParticles); - for (size_t i = 0; i < mnNumOfParticles; i++) - { - maSwarm.emplace_back(mnDimensionality); - Particle& rParticle = maSwarm.back(); - - mrDataProvider.initializeVariables(rParticle.mPosition, maGenerator); - mrDataProvider.initializeVariables(rParticle.mVelocity, maGenerator); - - for (size_t k = 0; k < mnDimensionality; k++) - { - rParticle.mPosition[k] = mrDataProvider.clampVariable(k, rParticle.mPosition[k]); - } - - rParticle.mCurrentFitness = mrDataProvider.calculateFitness(rParticle.mPosition); - - for (size_t k = 0; k < mnDimensionality; k++) - { - rParticle.mPosition[k] = mrDataProvider.clampVariable(k, rParticle.mPosition[k]); - } - - rParticle.mBestPosition.insert(rParticle.mBestPosition.begin(), - rParticle.mPosition.begin(), rParticle.mPosition.end()); - rParticle.mBestFitness = rParticle.mCurrentFitness; - - if (rParticle.mCurrentFitness > mfBestFitness) - { - mfBestFitness = rParticle.mCurrentFitness; - maBestPosition.insert(maBestPosition.begin(), rParticle.mPosition.begin(), - rParticle.mPosition.end()); - } - } - } - - bool next() - { - bool bBestChanged = false; - - for (Particle& rParticle : maSwarm) - { - double fRandom1 = maRandom01(maGenerator); - double fRandom2 = maRandom01(maGenerator); - - for (size_t k = 0; k < mnDimensionality; k++) - { - rParticle.mVelocity[k] - = (constWeight * rParticle.mVelocity[k]) - + (c1 * fRandom1 * (rParticle.mBestPosition[k] - rParticle.mPosition[k])) - + (c2 * fRandom2 * (maBestPosition[k] - rParticle.mPosition[k])); - - mrDataProvider.clampVariable(k, rParticle.mVelocity[k]); - - rParticle.mPosition[k] += rParticle.mVelocity[k]; - rParticle.mPosition[k] = mrDataProvider.clampVariable(k, rParticle.mPosition[k]); - } - - rParticle.mCurrentFitness = mrDataProvider.calculateFitness(rParticle.mPosition); - - if (rParticle.mCurrentFitness > rParticle.mBestFitness) - { - rParticle.mBestFitness = rParticle.mCurrentFitness; - rParticle.mBestPosition.insert(rParticle.mBestPosition.begin(), - rParticle.mPosition.begin(), - rParticle.mPosition.end()); - } - - if (rParticle.mCurrentFitness > mfBestFitness) - { - if (std::abs(rParticle.mCurrentFitness - mfBestFitness) > constAcceptedPrecision) - { - bBestChanged = true; - mnLastChange = mnGeneration; - } - maBestPosition.insert(maBestPosition.begin(), rParticle.mPosition.begin(), - rParticle.mPosition.end()); - mfBestFitness = rParticle.mCurrentFitness; - } - } - mnGeneration++; - return bBestChanged; - } -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng index 139947b98310..710efd324ce9 100644 --- a/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng +++ b/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng @@ -969,6 +969,40 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1224,6 +1258,9 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + @@ -2121,8 +2158,70 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2205,6 +2304,14 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + + + + @@ -2354,6 +2461,31 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + + + + + + + + + + + + + + + + + + + + @@ -2780,6 +2912,17 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + loext:histogram + loext:correlation-circle + + + + + @@ -3116,6 +3259,15 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + + + + + @@ -3659,6 +3811,50 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + + 0 + 1 + 2 + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4042,6 +4238,16 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + + + + + + @@ -4126,6 +4332,15 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + + + + + @@ -4234,6 +4449,7 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + @@ -4288,4 +4504,35 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/schema/mathml2/presentation/layout.xsd b/schema/mathml2/presentation/layout.xsd index 80b005efd7e9..ff081e53273b 100644 --- a/schema/mathml2/presentation/layout.xsd +++ b/schema/mathml2/presentation/layout.xsd @@ -86,7 +86,7 @@ value="(\+|-)?([0-9]+|[0-9]*\.[0-9]+)(((%?) *(width|lspace|height|depth))|(em|ex - + diff --git a/scp2/InstallModule_calc.mk b/scp2/InstallModule_calc.mk index 0484fac3174e..f9bbce84e2ac 100644 --- a/scp2/InstallModule_calc.mk +++ b/scp2/InstallModule_calc.mk @@ -18,7 +18,7 @@ $(eval $(call gb_InstallModule_define_if_set,scp2/calc,\ ENABLE_MACOSX_SANDBOX \ )) -ifneq (,$(ENABLE_COINMP)$(ENABLE_LPSOLVE)) +ifneq (,$(ENABLE_COINMP)) $(eval $(call gb_InstallModule_add_defs,scp2/calc,\ -DWITH_LPSOLVER \ )) diff --git a/scp2/inc/macros.inc b/scp2/inc/macros.inc index d3e136f58cf3..5c1723c6aa62 100644 --- a/scp2/inc/macros.inc +++ b/scp2/inc/macros.inc @@ -423,26 +423,6 @@ End #define SCP2_URE_DL_DIR GID_DIR_URE_LIB -#if defined WNT -#define SCP2_URE_DL_NORMAL(n) n ".dll" -#define SCP2_URE_DL_VER(n, v) n v ".dll" -#define SCP2_URE_DL_UNO_VER(n, v) n v ".dll" -#define SCP2_URE_DL_UNO_COMID_VER(n, v) n v STRING(COMID) ".dll" -#else -#define SCP2_URE_DL_NORMAL(n) "lib" n STRING(UNXSUFFIX) -#define SCP2_URE_DL_VER(n, v) "lib" n STRING(UNXSUFFIX) "." v -#define SCP2_URE_DL_UNO_VER(n, v) "libuno_" n STRING(UNXSUFFIX) "." v -#define SCP2_URE_DL_UNO_NORMAL(n) "libuno_" n STRING(UNXSUFFIX) -#define SCP2_URE_DL_UNO_COMID_VER(n, v) \ - "libuno_" n STRING(COMID) STRING(UNXSUFFIX) "." v -#define SCP2_URE_DL_UNO_COMID_NORMAL(n) \ - "libuno_" n STRING(COMID) STRING(UNXSUFFIX) -#endif -#if defined MACOSX -#define SCP2_URE_JDL_NORMAL(n) "lib" n ".jnilib" -#else -#define SCP2_URE_JDL_NORMAL(n) SCP2_URE_DL_NORMAL(n) -#endif #if defined MACOSX #define FILELIST_DIR PREDEFINED_PROGDIR diff --git a/scp2/source/calc/module_calc.scp b/scp2/source/calc/module_calc.scp index dd31007bb5ca..7adc68575d3d 100644 --- a/scp2/source/calc/module_calc.scp +++ b/scp2/source/calc/module_calc.scp @@ -36,8 +36,7 @@ Module gid_Module_Prg_Calc_Bin Default = YES; Styles = (HIDDEN_ROOT); Files = (auto_calc_ALL, - gid_File_Share_Registry_Calc_Xcd, - gid_File_Lib_Lpsolve); + gid_File_Share_Registry_Calc_Xcd); End Module gid_Module_Prg_Calc_Addins diff --git a/scp2/source/draw/registryitem_draw.scp b/scp2/source/draw/registryitem_draw.scp index e1781c58cf24..d381e8c6960c 100644 --- a/scp2/source/draw/registryitem_draw.scp +++ b/scp2/source/draw/registryitem_draw.scp @@ -1079,6 +1079,7 @@ CONDITIONAL_REGISTER_DOC_EXTENSION( Gif, gid_Module_Prg_Draw_Other_Reg, gif, G CONDITIONAL_REGISTER_DOC_EXTENSION( Jpg, gid_Module_Prg_Draw_Other_Reg, jpg, JPG, JOINT_PHOTOGRAPHIC_EXPERTS_GROUP, 5, sdraw.exe, open, Draw ) CONDITIONAL_REGISTER_DOC_EXTENSION( Jpeg, gid_Module_Prg_Draw_Other_Reg, jpeg, JPEG, JOINT_PHOTOGRAPHIC_EXPERTS_GROUP, 5, sdraw.exe, open, Draw ) CONDITIONAL_REGISTER_DOC_EXTENSION( Jpe, gid_Module_Prg_Draw_Other_Reg, jpe, JPE, JOINT_PHOTOGRAPHIC_EXPERTS_GROUP, 5, sdraw.exe, open, Draw ) +CONDITIONAL_REGISTER_DOC_EXTENSION( Jxl, gid_Module_Prg_Draw_Other_Reg, jxl, JXL, JPEG_XL, 5, sdraw.exe, open, Draw ) CONDITIONAL_REGISTER_DOC_EXTENSION( Pbm, gid_Module_Prg_Draw_Other_Reg, pbm, PBM, PORTABLE_BITMAP_FORMAT, 5, sdraw.exe, open, Draw ) CONDITIONAL_REGISTER_DOC_EXTENSION( Pcx, gid_Module_Prg_Draw_Other_Reg, pcx, PCX, PERSONAL_COMPUTER_EXCHANGE, 5, sdraw.exe, open, Draw ) CONDITIONAL_REGISTER_DOC_EXTENSION( Pgm, gid_Module_Prg_Draw_Other_Reg, pgm, PGM, PORTABLE_GRAYMAP_FORMAT, 5, sdraw.exe, open, Draw ) diff --git a/scp2/source/ooo/file_ooo.scp b/scp2/source/ooo/file_ooo.scp index 39581867d7dc..412cc886dce6 100644 --- a/scp2/source/ooo/file_ooo.scp +++ b/scp2/source/ooo/file_ooo.scp @@ -185,7 +185,6 @@ MO_FILELIST_ALL_LANG(rpt) MO_FILELIST_ALL_LANG(sb) MO_FILELIST_ALL_LANG(sc) MO_FILELIST_ALL_LANG(sca) -MO_FILELIST_ALL_LANG(scc) MO_FILELIST_ALL_LANG(sd) MO_FILELIST_ALL_LANG(sfx) MO_FILELIST_ALL_LANG(sm) diff --git a/scp2/source/ooo/folderitem_ooo.ulf b/scp2/source/ooo/folderitem_ooo.ulf index 22f8a37f7981..bc3f5f19cccf 100644 --- a/scp2/source/ooo/folderitem_ooo.ulf +++ b/scp2/source/ooo/folderitem_ooo.ulf @@ -23,7 +23,7 @@ en-US = "From Template" en-US = "Open Document" [STR_FI_NAME_SAFEMODE] -en-US = "%PRODUCTNAME (Safe Mode)" +en-US = "%PRODUCTNAME (Troubleshoot Mode)" [STR_FI_TOOLTIP_SOFFICE] en-US = "LibreOffice, the office productivity suite provided by The Document Foundation. See https://www.documentfoundation.org" diff --git a/scripting/CppunitTest_scripting_beanshell.mk b/scripting/CppunitTest_scripting_beanshell.mk new file mode 100644 index 000000000000..43e6f5ea4b90 --- /dev/null +++ b/scripting/CppunitTest_scripting_beanshell.mk @@ -0,0 +1,50 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,scripting_beanshell)) + +$(eval $(call gb_CppunitTest_add_exception_objects,scripting_beanshell, \ + scripting/qa/cppunit/beanshell/beanshelltest \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,scripting_beanshell, \ + cppu \ + cppuhelper \ + jvmfwk \ + sal \ + subsequenttest \ + test \ + unotest \ + utl \ + tl \ +)) + +$(eval $(call gb_CppunitTest_use_externals,scripting_beanshell,\ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_api,scripting_beanshell,\ + udkapi \ + offapi \ +)) + +$(eval $(call gb_CppunitTest_use_jars,scripting_beanshell, \ + ScriptProviderForBeanShell \ +)) + +$(eval $(call gb_CppunitTest_use_ure,scripting_beanshell)) +$(eval $(call gb_CppunitTest_use_vcl,scripting_beanshell)) +$(eval $(call gb_CppunitTest_use_rdbs,scripting_beanshell, \ + services \ + scriptproviderforbeanshell \ +)) +$(eval $(call gb_CppunitTest_use_configuration,scripting_beanshell)) + +# vim: set noet sw=4 ts=4: diff --git a/scripting/CppunitTest_scripting_jsprov.mk b/scripting/CppunitTest_scripting_jsprov.mk new file mode 100644 index 000000000000..bf968ae35e37 --- /dev/null +++ b/scripting/CppunitTest_scripting_jsprov.mk @@ -0,0 +1,42 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,scripting_jsprov)) + +$(eval $(call gb_CppunitTest_add_exception_objects,scripting_jsprov, \ + scripting/qa/cppunit/jsprov/jsprovtest \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,scripting_jsprov, \ + cppu \ + cppuhelper \ + sal \ + subsequenttest \ + test \ + unotest \ + utl \ + tl \ +)) + +$(eval $(call gb_CppunitTest_use_externals,scripting_jsprov,\ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_api,scripting_jsprov,\ + udkapi \ + offapi \ +)) + +$(eval $(call gb_CppunitTest_use_ure,scripting_jsprov)) +$(eval $(call gb_CppunitTest_use_vcl,scripting_jsprov)) +$(eval $(call gb_CppunitTest_use_rdb,scripting_jsprov,services)) +$(eval $(call gb_CppunitTest_use_configuration,scripting_jsprov)) + +# vim: set noet sw=4 ts=4: diff --git a/scripting/CppunitTest_scripting_pythonscript.mk b/scripting/CppunitTest_scripting_pythonscript.mk new file mode 100644 index 000000000000..f87d2d70e14a --- /dev/null +++ b/scripting/CppunitTest_scripting_pythonscript.mk @@ -0,0 +1,52 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,scripting_pythonscript)) + +$(eval $(call gb_CppunitTest_add_exception_objects,scripting_pythonscript, \ + scripting/qa/cppunit/pythonscript/PythonScriptTest \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,scripting_pythonscript, \ + cppu \ + cppuhelper \ + pythonloader \ + pyuno \ + sal \ + subsequenttest \ + test \ + unotest \ + utl \ + tl \ +)) + +$(eval $(call gb_CppunitTest_use_externals,scripting_pythonscript,\ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_api,scripting_pythonscript,\ + udkapi \ + offapi \ +)) + +$(eval $(call gb_CppunitTest_use_packages,scripting_pythonscript,scripting_scriptproviderforpython)) +$(call gb_CppunitTest_get_target,scripting_pythonscript): \ + UNO_SERVICES += $(SRCDIR)/scripting/source/pyprov/scriptproviderforpython.rdb + +$(eval $(call gb_CppunitTest_use_components,scripting_pythonscript,\ + pyuno/source/loader/pythonloader \ +)) + +$(eval $(call gb_CppunitTest_use_ure,scripting_pythonscript)) +$(eval $(call gb_CppunitTest_use_vcl,scripting_pythonscript)) +$(eval $(call gb_CppunitTest_use_rdb,scripting_pythonscript,services)) +$(eval $(call gb_CppunitTest_use_configuration,scripting_pythonscript)) + +# vim: set noet sw=4 ts=4: diff --git a/scripting/CppunitTest_scripting_scripthandler.mk b/scripting/CppunitTest_scripting_scripthandler.mk new file mode 100644 index 000000000000..b1fcf4ea2b63 --- /dev/null +++ b/scripting/CppunitTest_scripting_scripthandler.mk @@ -0,0 +1,43 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,scripting_scripthandler)) + +$(eval $(call gb_CppunitTest_add_exception_objects,scripting_scripthandler, \ + scripting/qa/cppunit/scripthandler/ScriptHandlerTest \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,scripting_scripthandler, \ + cppu \ + cppuhelper \ + sal \ + subsequenttest \ + test \ + unotest \ + utl \ + tl \ + vcl \ +)) + +$(eval $(call gb_CppunitTest_use_externals,scripting_scripthandler,\ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_api,scripting_scripthandler,\ + udkapi \ + offapi \ +)) + +$(eval $(call gb_CppunitTest_use_ure,scripting_scripthandler)) +$(eval $(call gb_CppunitTest_use_vcl,scripting_scripthandler)) +$(eval $(call gb_CppunitTest_use_rdb,scripting_scripthandler,services)) +$(eval $(call gb_CppunitTest_use_configuration,scripting_scripthandler)) + +# vim: set noet sw=4 ts=4: diff --git a/scripting/Library_jsprov.mk b/scripting/Library_jsprov.mk new file mode 100644 index 000000000000..6a49315972c2 --- /dev/null +++ b/scripting/Library_jsprov.mk @@ -0,0 +1,34 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Library_Library,jsprov)) + +$(eval $(call gb_Library_set_componentfile,jsprov,scripting/source/jsprov/jsprov,services)) + +$(eval $(call gb_Library_use_sdk_api,jsprov)) + +$(eval $(call gb_Library_set_include,jsprov,\ + $$(INCLUDE) \ + -I$(SRCDIR)/scripting/source/inc \ +)) + +$(eval $(call gb_Library_use_libraries,jsprov,\ + comphelper \ + cppu \ + cppuhelper \ + jsuno \ + sal \ + singleprov \ +)) + +$(eval $(call gb_Library_add_exception_objects,jsprov,\ + scripting/source/jsprov/loader \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/scripting/Library_singleprov.mk b/scripting/Library_singleprov.mk new file mode 100644 index 000000000000..6b0c96a26865 --- /dev/null +++ b/scripting/Library_singleprov.mk @@ -0,0 +1,41 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Library_Library,singleprov)) + +$(eval $(call gb_Library_use_sdk_api,singleprov)) + +$(eval $(call gb_Library_set_include,singleprov,\ + $$(INCLUDE) \ + -I$(SRCDIR)/scripting/source/inc \ +)) + +$(eval $(call gb_Library_use_libraries,singleprov,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ +)) + +$(eval $(call gb_Library_add_exception_objects,singleprov,\ + scripting/source/singleprov/externaledit \ + scripting/source/singleprov/provcontext \ + scripting/source/singleprov/scriptdir \ + scripting/source/singleprov/scriptfile \ + scripting/source/singleprov/scriptmacro \ + scripting/source/singleprov/scriptprovider \ +)) + + +$(eval $(call gb_Library_use_system_win32_libs,singleprov,\ + shell32 \ + shlwapi \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/scripting/Module_scripting.mk b/scripting/Module_scripting.mk index 1d974e8e7c26..082948a5b182 100644 --- a/scripting/Module_scripting.mk +++ b/scripting/Module_scripting.mk @@ -37,14 +37,27 @@ $(eval $(call gb_Module_add_targets,scripting,\ Package_ScriptsPython \ Pyuno_mailmerge \ ) \ + $(if $(ENABLE_QUICKJS),Library_jsprov) \ Library_basprov \ Library_dlgprov \ Library_protocolhandler \ + Library_singleprov \ Library_scriptframe \ Library_stringresource \ Library_vbaevents \ )) +$(eval $(call gb_Module_add_check_targets,scripting,\ + $(if $(ENABLE_QUICKJS),CppunitTest_scripting_jsprov) \ + $(if $(ENABLE_SCRIPTING_BEANSHELL),CppunitTest_scripting_beanshell) \ + $(if $(DISABLE_PYTHON),,CppunitTest_scripting_pythonscript) \ + CppunitTest_scripting_scripthandler \ +)) + +$(eval $(call gb_Module_add_subsequentcheck_targets,scripting,\ + PythonTest_scripting_provider \ +)) + endif # vim: set noet sw=4 ts=4: diff --git a/external/more_fonts/UnpackedTarball_lumanosimo.mk b/scripting/PythonTest_scripting_provider.mk similarity index 52% rename from external/more_fonts/UnpackedTarball_lumanosimo.mk rename to scripting/PythonTest_scripting_provider.mk index 350d7ed6cda7..e231c53a87b2 100644 --- a/external/more_fonts/UnpackedTarball_lumanosimo.mk +++ b/scripting/PythonTest_scripting_provider.mk @@ -1,4 +1,4 @@ -# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- # # This file is part of the LibreOffice project. # @@ -7,8 +7,10 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # -$(eval $(call gb_UnpackedTarball_UnpackedTarball,font_lumanosimo)) +$(eval $(call gb_PythonTest_PythonTest,scripting_provider)) -$(eval $(call gb_UnpackedTarball_set_tarball,font_lumanosimo,$(FONT_LUMANOSIMO_TARBALL),0)) +$(eval $(call gb_PythonTest_add_modules,scripting_provider,$(SRCDIR)/scripting/qa/pytests,\ + provider_expandall \ +)) # vim: set noet sw=4 ts=4: diff --git a/scripting/README.md b/scripting/README.md index 0560a73b9786..988d1484c3ac 100644 --- a/scripting/README.md +++ b/scripting/README.md @@ -27,6 +27,11 @@ browsing and executing scripts. C++ for a `ProtocolHandler` implementation that handles `vnd.sun.star.script` URIs and dispatches them for execution to the Scripting Framework. +- `source/singleprov` + +A base helper class for C++ implementations of LanguageScriptProviders +that store a single macro in a source file. + - `source/basprov` C++ implementation of the `LanguageScriptProvider` UNO service for Basic @@ -36,6 +41,10 @@ C++ implementation of the `LanguageScriptProvider` UNO service for Basic C++ implementation of the `DialogProvider` UNO service used for loading UNO dialogs from various languages +- `source/jsprov` + +C++ implementation of the `LanguageScriptProvider` UNO service for JavaScript using QuickJS. + - `source/pyprov` `LanguageScriptProvider` for Python diff --git a/scripting/examples/python/TableSample.py b/scripting/examples/python/TableSample.py index 0920bf8ad021..cbb3c43c87ba 100644 --- a/scripting/examples/python/TableSample.py +++ b/scripting/examples/python/TableSample.py @@ -116,7 +116,7 @@ def createTable(): 0) textInTextFrame.insertString( cursorInTextFrame, - "\nWith this second line the height of the rame raises.", + "\nWith this second line the height of the frame raises.", 0) text.insertControlCharacter(cursor, PARAGRAPH_BREAK, 0) diff --git a/scripting/java/com/sun/star/script/framework/browse/ParcelBrowseNode.java b/scripting/java/com/sun/star/script/framework/browse/ParcelBrowseNode.java index cdb8715a5cbe..4f2de6ed060d 100644 --- a/scripting/java/com/sun/star/script/framework/browse/ParcelBrowseNode.java +++ b/scripting/java/com/sun/star/script/framework/browse/ParcelBrowseNode.java @@ -21,11 +21,13 @@ package com.sun.star.script.framework.browse; import com.sun.star.beans.XIntrospectionAccess; import com.sun.star.lang.XMultiComponentFactory; -import com.sun.star.lib.uno.helper.PropertySet; +import com.sun.star.lib.uno.helper.ComponentBase; -import com.sun.star.script.XInvocation; import com.sun.star.script.browse.BrowseNodeTypes; import com.sun.star.script.browse.XBrowseNode; +import com.sun.star.script.browse.XCreatableBrowseNode; +import com.sun.star.script.browse.XDeletableBrowseNode; +import com.sun.star.script.browse.XRenamableBrowseNode; import com.sun.star.script.framework.container.Parcel; import com.sun.star.script.framework.container.ParcelContainer; import com.sun.star.script.framework.container.ScriptEntry; @@ -46,18 +48,16 @@ import java.util.Collection; import javax.swing.JOptionPane; -public class ParcelBrowseNode extends PropertySet implements - XBrowseNode, XInvocation { +public class ParcelBrowseNode extends ComponentBase implements + XBrowseNode, XCreatableBrowseNode, XDeletableBrowseNode, XRenamableBrowseNode { private final ScriptProvider provider; private Collection browsenodes; private final ParcelContainer container; private Parcel parcel; - // these four are properties, they are accessed via reflection - public boolean deletable = true; - public boolean editable = false; - public boolean creatable = false; - public boolean renamable = true; + private boolean deletable = true; + private boolean creatable = false; + private boolean renamable = true; public ParcelBrowseNode(ScriptProvider provider, ParcelContainer container, String parcelName) throws @@ -69,10 +69,6 @@ public class ParcelBrowseNode extends PropertySet implements this.parcel = (Parcel)this.container.getByName(parcelName); - registerProperty("Deletable", new Type(boolean.class), (short)0, "deletable"); - registerProperty("Editable", new Type(boolean.class), (short)0, "editable"); - registerProperty("Creatable", new Type(boolean.class), (short)0, "creatable"); - registerProperty("Renamable", new Type(boolean.class), (short)0, "renamable"); if (provider.hasScriptEditor()) { this.creatable = true; @@ -91,7 +87,6 @@ public class ParcelBrowseNode extends PropertySet implements container.isUnoPkg() ) ) { deletable = false; - editable = false; creatable = false; renamable = false; } @@ -147,163 +142,89 @@ public class ParcelBrowseNode extends PropertySet implements return getName(); } - // implementation of XInvocation interface - public XIntrospectionAccess getIntrospection() { + @Override + public boolean isCreatableNode() { + return creatable; + } + + @Override + public boolean isDeletableNode() { + return deletable; + } + + @Override + public boolean isRenamableNode() { + return renamable; + } + + @Override + public ScriptBrowseNode createNode(String newName) { + if (newName == null || newName.length() == 0) + return null; + + try { + String source = provider.getScriptEditor().getTemplate(); + + String languageName = + newName + "." + provider.getScriptEditor().getExtension(); + + String language = container.getLanguage(); + + ScriptEntry entry = new ScriptEntry(language, languageName); + + Parcel parcel = (Parcel)container.getByName(getName()); + ScriptMetaData data = new ScriptMetaData(parcel, entry, source); + parcel.insertByName(languageName, data); + + ScriptBrowseNode sbn = + new ScriptBrowseNode(provider, parcel, languageName); + + if (browsenodes == null) { + LogUtils.DEBUG("browsenodes null!!"); + browsenodes = new ArrayList(4); + } + + browsenodes.add(sbn); + return sbn; + } catch (Exception e) { + LogUtils.DEBUG("ParcelBrowseNode[create] failed with: " + e); + LogUtils.DEBUG(LogUtils.getTrace(e)); + } return null; } - public Object invoke(String aFunctionName, Object[] aParams, - short[][] aOutParamIndex, Object[][] aOutParam) throws - com.sun.star.lang.IllegalArgumentException, - com.sun.star.script.CannotConvertException, - com.sun.star.reflection.InvocationTargetException { + @Override + public boolean deleteNode() { + try { + if (container.deleteParcel(getName())) + return true; + } catch (Exception e) { + } + return false; + } - LogUtils.DEBUG("ParcelBrowseNode invoke for " + aFunctionName); + @Override + public ParcelBrowseNode renameNode(String newName) { + try { + container.renameParcel(getName(), newName); + Parcel p = (Parcel)container.getByName(newName); - // Initialise the out parameters - not used but prevents error in - // UNO bridge - aOutParamIndex[0] = new short[0]; - aOutParam[0] = new Object[0]; - - Any result = new Any(new Type(Boolean.class), Boolean.TRUE); - - if (aFunctionName.equals("Creatable")) { - try { - String newName; - - if (aParams == null || aParams.length < 1 - || !AnyConverter.isString(aParams[0])) { - - String prompt = "Enter name for new Script"; - String title = "Create Script"; - - // try to get a DialogFactory instance, if it fails - // just use a Swing JOptionPane to prompt for the name - try { - DialogFactory dialogFactory = DialogFactory.getDialogFactory(); - newName = dialogFactory.showInputDialog(title, prompt); - } catch (Exception e) { - - newName = JOptionPane.showInputDialog(null, prompt, title, - JOptionPane.QUESTION_MESSAGE); - - } - } else { - newName = AnyConverter.toString(aParams[0]); - } - - if (newName == null || newName.length() == 0) { - result = new Any(new Type(Boolean.class), Boolean.FALSE); - } else { - String source = provider.getScriptEditor().getTemplate(); - - String languageName = - newName + "." + provider.getScriptEditor().getExtension(); - - String language = container.getLanguage(); - - ScriptEntry entry = new ScriptEntry(language, languageName); - - Parcel parcel = (Parcel)container.getByName(getName()); - ScriptMetaData data = new ScriptMetaData(parcel, entry, source); - parcel.insertByName(languageName, data); - - ScriptBrowseNode sbn = - new ScriptBrowseNode(provider, parcel, languageName); - - if (browsenodes == null) { - LogUtils.DEBUG("browsenodes null!!"); - browsenodes = new ArrayList(4); - } - - browsenodes.add(sbn); - result = new Any(new Type(XBrowseNode.class), sbn); - } - } catch (Exception e) { - LogUtils.DEBUG("ParcelBrowseNode[create] failed with: " + e); - LogUtils.DEBUG(LogUtils.getTrace(e)); - result = new Any(new Type(Boolean.class), Boolean.FALSE); + if (browsenodes == null) { + getChildNodes(); } - } else if (aFunctionName.equals("Deletable")) { - try { - if (container.deleteParcel(getName())) { - result = new Any(new Type(Boolean.class), Boolean.TRUE); - } else { - result = new Any(new Type(Boolean.class), Boolean.FALSE); - } - } catch (Exception e) { - result = new Any(new Type(Boolean.class), Boolean.FALSE); - } - } else if (aFunctionName.equals("Renamable")) { - - String newName = null; - - try { - - if (aParams == null || aParams.length < 1 || - !AnyConverter.isString(aParams[0])) { - String prompt = "Enter new name for Library"; - String title = "Rename Library"; - - // try to get a DialogFactory instance, if it fails - // just use a Swing JOptionPane to prompt for the name - try { - DialogFactory dialogFactory = DialogFactory.getDialogFactory(); - newName = dialogFactory.showInputDialog(title, prompt); - } catch (Exception e) { - - newName = JOptionPane.showInputDialog(null, prompt, title, - JOptionPane.QUESTION_MESSAGE); - - } - } else { - newName = AnyConverter.toString(aParams[0]); - } - - container.renameParcel(getName(), newName); - Parcel p = (Parcel)container.getByName(newName); - - if (browsenodes == null) { - getChildNodes(); - } + if (browsenodes != null) { ScriptBrowseNode[] childNodes = browsenodes.toArray(new ScriptBrowseNode[browsenodes.size()]); for (int index = 0; index < childNodes.length; index++) { childNodes[ index ].updateURI(p); } - - result = new Any(new Type(XBrowseNode.class), this); - } catch (Exception e) { - result = new Any(new Type(Boolean.class), Boolean.FALSE); } + + return this; + } catch (Exception e) { + return null; } - - else { - throw new com.sun.star.lang.IllegalArgumentException( - "Function " + aFunctionName + " not supported."); - } - - return result; - } - - public void setValue(String aPropertyName, Object aValue) throws - com.sun.star.beans.UnknownPropertyException, - com.sun.star.script.CannotConvertException, - com.sun.star.reflection.InvocationTargetException { - } - - public Object getValue(String aPropertyName) throws - com.sun.star.beans.UnknownPropertyException { - return null; - } - - public boolean hasMethod(String aName) { - return false; - } - - public boolean hasProperty(String aName) { - return false; } } diff --git a/scripting/java/com/sun/star/script/framework/browse/PkgProviderBrowseNode.java b/scripting/java/com/sun/star/script/framework/browse/PkgProviderBrowseNode.java index 6cdfd2a774d3..5c9e738fcbc8 100644 --- a/scripting/java/com/sun/star/script/framework/browse/PkgProviderBrowseNode.java +++ b/scripting/java/com/sun/star/script/framework/browse/PkgProviderBrowseNode.java @@ -37,8 +37,6 @@ public class PkgProviderBrowseNode extends ProviderBrowseNode { container.getParcelContainerDir()); LogUtils.DEBUG("*** PkgProviderBrowseNode ctor, container has num parcels = " + container.getElementNames().length); - deletable = false; - editable = false; creatable = false; } diff --git a/scripting/java/com/sun/star/script/framework/browse/ProviderBrowseNode.java b/scripting/java/com/sun/star/script/framework/browse/ProviderBrowseNode.java index 91c2566be5ae..972fdc525f59 100644 --- a/scripting/java/com/sun/star/script/framework/browse/ProviderBrowseNode.java +++ b/scripting/java/com/sun/star/script/framework/browse/ProviderBrowseNode.java @@ -22,11 +22,11 @@ import com.sun.star.beans.XIntrospectionAccess; import com.sun.star.lang.XMultiComponentFactory; -import com.sun.star.lib.uno.helper.PropertySet; +import com.sun.star.lib.uno.helper.ComponentBase; -import com.sun.star.script.XInvocation; import com.sun.star.script.browse.BrowseNodeTypes; import com.sun.star.script.browse.XBrowseNode; +import com.sun.star.script.browse.XCreatableBrowseNode; import com.sun.star.script.framework.container.ParcelContainer; import com.sun.star.script.framework.log.LogUtils; import com.sun.star.script.framework.provider.ScriptProvider; @@ -44,18 +44,15 @@ import java.util.Collection; import javax.swing.JOptionPane; -public class ProviderBrowseNode extends PropertySet implements - XBrowseNode, XInvocation { +public class ProviderBrowseNode extends ComponentBase implements + XBrowseNode, XCreatableBrowseNode { private final ScriptProvider provider; private Collection browsenodes; private final String name; protected ParcelContainer container; private final XComponentContext m_xCtx; - // these are properties, they are accessed by reflection - public boolean deletable = true; - public boolean creatable = true; - public boolean editable = false; + protected boolean creatable = true; public ProviderBrowseNode(ScriptProvider provider, ParcelContainer container, XComponentContext xCtx) { @@ -66,9 +63,6 @@ public class ProviderBrowseNode extends PropertySet implements this.provider = provider; this.m_xCtx = xCtx; - registerProperty("Deletable", new Type(boolean.class), (short)0, "deletable"); - registerProperty("Creatable", new Type(boolean.class), (short)0, "creatable"); - registerProperty("Editable", new Type(boolean.class), (short)0, "editable"); XMultiComponentFactory xFac = m_xCtx.getServiceManager(); try { @@ -78,7 +72,6 @@ public class ProviderBrowseNode extends PropertySet implements xCtx)); if ( container.isUnoPkg() || xSFA.isReadOnly( container.getParcelContainerDir() ) ) { - deletable = false; creatable = false; } } @@ -165,100 +158,36 @@ public class ProviderBrowseNode extends PropertySet implements return getName(); } - // implementation of XInvocation interface - public XIntrospectionAccess getIntrospection() { - return null; + @Override + public boolean isCreatableNode() { + return creatable; } - public Object invoke(String aFunctionName, Object[] aParams, - short[][] aOutParamIndex, Object[][] aOutParam) throws - com.sun.star.lang.IllegalArgumentException, - com.sun.star.script.CannotConvertException, - com.sun.star.reflection.InvocationTargetException { + @Override + public ParcelBrowseNode createNode(String name) { + try { + if (name == null || name.length() == 0) + return null; - // Initialise the out parameters - not used but prevents error in - // UNO bridge - aOutParamIndex[0] = new short[0]; - aOutParam[0] = new Object[0]; + Object newParcel = container.createParcel(name); + LogUtils.DEBUG("Parcel created " + name + " " + newParcel); - Any result = new Any(new Type(Boolean.class), Boolean.TRUE); + if (newParcel == null) + return null; - if (aFunctionName.equals("Creatable")) { - try { - String name; + ParcelBrowseNode parcel = new ParcelBrowseNode(provider, container, name); + LogUtils.DEBUG("created parcel node "); - if (aParams == null || aParams.length < 1 || - !AnyConverter.isString(aParams[0])) { - - String prompt = "Enter name for new Parcel"; - String title = "Create Parcel"; - - // try to get a DialogFactory instance, if it fails - // just use a Swing JOptionPane to prompt for the name - try { - DialogFactory dialogFactory = DialogFactory.getDialogFactory(); - name = dialogFactory.showInputDialog(title, prompt); - } catch (Exception e) { - - name = JOptionPane.showInputDialog(null, prompt, title, - JOptionPane.QUESTION_MESSAGE); - - } - } else { - name = AnyConverter.toString(aParams[0]); - } - - if (name == null || name.length() == 0) { - result = new Any(new Type(Boolean.class), Boolean.FALSE); - } else { - - Object newParcel = container.createParcel(name); - LogUtils.DEBUG("Parcel created " + name + " " + newParcel); - - if (newParcel == null) { - result = new Any(new Type(Boolean.class), Boolean.FALSE); - } else { - ParcelBrowseNode parcel = new ParcelBrowseNode(provider, container, name); - LogUtils.DEBUG("created parcel node "); - - if (browsenodes == null) { - browsenodes = new ArrayList(5); - } - - browsenodes.add(parcel); - result = new Any(new Type(XBrowseNode.class), parcel); - } - } - } catch (Exception e) { - LogUtils.DEBUG("ProviderBrowseNode[create] failed with: " + e); - LogUtils.DEBUG(LogUtils.getTrace(e)); - result = new Any(new Type(Boolean.class), Boolean.FALSE); + if (browsenodes == null) { + browsenodes = new ArrayList(5); } - } else { - throw new com.sun.star.lang.IllegalArgumentException( - "Function " + aFunctionName + " not supported."); + + browsenodes.add(parcel); + return parcel; + } catch (Exception e) { + LogUtils.DEBUG("ProviderBrowseNode[create] failed with: " + e); + LogUtils.DEBUG(LogUtils.getTrace(e)); + return null; } - - return result; - } - - public void setValue(String aPropertyName, Object aValue) throws - com.sun.star.beans.UnknownPropertyException, - com.sun.star.script.CannotConvertException, - com.sun.star.reflection.InvocationTargetException { - } - - public Object getValue(String aPropertyName) throws - com.sun.star.beans.UnknownPropertyException { - - return null; - } - - public boolean hasMethod(String aName) { - return false; - } - - public boolean hasProperty(String aName) { - return false; } } diff --git a/scripting/java/com/sun/star/script/framework/browse/ScriptBrowseNode.java b/scripting/java/com/sun/star/script/framework/browse/ScriptBrowseNode.java index 5f91b1a78699..72acf2b2d428 100644 --- a/scripting/java/com/sun/star/script/framework/browse/ScriptBrowseNode.java +++ b/scripting/java/com/sun/star/script/framework/browse/ScriptBrowseNode.java @@ -19,20 +19,15 @@ package com.sun.star.script.framework.browse; import com.sun.star.beans.XIntrospectionAccess; -import com.sun.star.container.ElementExistException; -import com.sun.star.container.NoSuchElementException; - -import com.sun.star.lang.NoSupportException; -import com.sun.star.lang.WrappedTargetException; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.lib.uno.helper.PropertySet; -import com.sun.star.reflection.InvocationTargetException; - -import com.sun.star.script.XInvocation; import com.sun.star.script.browse.BrowseNodeTypes; import com.sun.star.script.browse.XBrowseNode; +import com.sun.star.script.browse.XDeletableBrowseNode; +import com.sun.star.script.browse.XEditableBrowseNode; +import com.sun.star.script.browse.XRenamableBrowseNode; import com.sun.star.script.framework.container.Parcel; import com.sun.star.script.framework.container.ScriptEntry; import com.sun.star.script.framework.container.ScriptMetaData; @@ -44,12 +39,13 @@ import com.sun.star.ucb.XSimpleFileAccess; import com.sun.star.uno.Any; import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.DeploymentException; import com.sun.star.uno.Type; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; public class ScriptBrowseNode extends PropertySet implements - XBrowseNode, XInvocation { + XBrowseNode, XDeletableBrowseNode, XEditableBrowseNode, XRenamableBrowseNode { private final ScriptProvider provider; @@ -59,9 +55,10 @@ public class ScriptBrowseNode extends PropertySet implements // these are properties, accessed by reflection public String uri; public String description; - public boolean editable; - public boolean deletable = false; - public boolean renamable = false; + + private boolean editable = false; + private boolean deletable = false; + private boolean renamable = false; public ScriptBrowseNode(ScriptProvider provider, Parcel parent, String name) { @@ -111,9 +108,6 @@ public class ScriptBrowseNode extends PropertySet implements } - registerProperty("Deletable", new Type(boolean.class), (short)0, "deletable"); - registerProperty("Editable", new Type(boolean.class), (short)0, "editable"); - registerProperty("Renamable", new Type(boolean.class), (short)0, "renamable"); registerProperty("URI", new Type(String.class), (short)0, "uri"); registerProperty("Description", new Type(String.class), (short)0, "description"); @@ -154,147 +148,88 @@ public class ScriptBrowseNode extends PropertySet implements } } - // implementation of XInvocation interface - public XIntrospectionAccess getIntrospection() { - return null; + @Override + public boolean isDeletableNode() { + return deletable; } - public Object invoke(String aFunctionName, Object[] aParams, - short[][] aOutParamIndex, Object[][] aOutParam) throws - com.sun.star.lang.IllegalArgumentException, - com.sun.star.script.CannotConvertException, - com.sun.star.reflection.InvocationTargetException { + @Override + public boolean isEditableNode() { + return editable; + } - // Initialise the out parameters - not used but prevents error in - // UNO bridge - aOutParamIndex[0] = new short[0]; - aOutParam[0] = new Object[0]; + @Override + public boolean isRenamableNode() { + return renamable; + } - Any result = new Any(new Type(Boolean.class), Boolean.TRUE); - - if (aFunctionName.equals("Editable")) { - if (!editable) { - - NoSupportException nse = - new NoSupportException(aFunctionName + " is not editable "); - - throw new InvocationTargetException( - "Scripting framework error editing script", null, nse); - - } - - XScriptContext ctxt = provider.getScriptingContext(); - ScriptMetaData data = null; - - try { - data = parent.getByName(name); - } catch (NoSuchElementException nse) { - throw new com.sun.star.lang.IllegalArgumentException(nse, - name + " does not exist or can't be found "); - } catch (com.sun.star.lang.WrappedTargetException wte) { - // rethrow - throw new InvocationTargetException( - "Scripting framework editing script ", null, wte.TargetException); - } - - provider.getScriptEditor().edit(ctxt, data); - } else if (aFunctionName.equals("Deletable")) { - if (!deletable) { - - NoSupportException nse = new NoSupportException( - aFunctionName + " is not supported for this node"); - - throw new InvocationTargetException( - "Scripting framework error deleting script", null, nse); - } - - try { - parent.removeByName(name); - result = new Any(new Type(Boolean.class), Boolean.TRUE); - } catch (NoSuchElementException nse) { - throw new com.sun.star.lang.IllegalArgumentException(nse, - name + " does not exist or can't be found "); - } catch (WrappedTargetException wte) { - // rethrow - throw new InvocationTargetException( - "Scripting framework deleting script ", null, wte.TargetException); - } - - } else if (aFunctionName.equals("Renamable")) { - result = new Any(new Type(XBrowseNode.class), new XBrowseNode[0]); - - if (!renamable) { - - NoSupportException nse = new NoSupportException( - aFunctionName + " is not supported for this node"); - - throw new InvocationTargetException( - "Scripting framework error renaming script", null, nse); - } - - try { - String newName = AnyConverter.toString(aParams[0]); - ScriptMetaData oldData = parent.getByName(name); - oldData.loadSource(); - String oldSource = oldData.getSource(); - - LogUtils.DEBUG("Create renamed script"); - - String languageName = - newName + "." + provider.getScriptEditor().getExtension(); - - String language = provider.getName(); - - ScriptEntry entry = new ScriptEntry(language, languageName); - - ScriptMetaData data = - new ScriptMetaData(parent, entry, oldSource); - - parent.insertByName(languageName, data); - - LogUtils.DEBUG("Now remove old script"); - parent.removeByName(name); - - uri = data.getShortFormScriptURL(); - name = languageName; - result = new Any(new Type(XBrowseNode.class), this); - } catch (NoSuchElementException nse) { - throw new com.sun.star.lang.IllegalArgumentException(nse, - name + " does not exist or can't be found "); - } catch (ElementExistException eee) { - // rethrow - throw new InvocationTargetException( - "Scripting framework error renaming script ", null, eee); - } catch (WrappedTargetException wte) { - // rethrow - throw new InvocationTargetException( - "Scripting framework rename script ", null, wte.TargetException); - } - } else { - throw new com.sun.star.lang.IllegalArgumentException( - "Function " + aFunctionName + " not supported."); + @Override + public boolean editNode() { + if (!editable) { + throw new DeploymentException("Called editable on non-editable node"); } - return result; + XScriptContext ctxt = provider.getScriptingContext(); + ScriptMetaData data = null; + + try { + data = parent.getByName(name); + } catch (Exception e) { + return false; + } + + provider.getScriptEditor().edit(ctxt, data); + + return true; } - public void setValue(String aPropertyName, Object aValue) throws - com.sun.star.beans.UnknownPropertyException, - com.sun.star.script.CannotConvertException, - com.sun.star.reflection.InvocationTargetException { + @Override + public boolean deleteNode() { + if (!deletable) { + throw new DeploymentException("Called delete on non-deletable node"); + } + + try { + parent.removeByName(name); + return true; + } catch (Exception e) { + return false; + } } - public Object getValue(String aPropertyName) throws - com.sun.star.beans.UnknownPropertyException { + @Override + public ScriptBrowseNode renameNode(String newName) { + if (!renamable) { + throw new DeploymentException("Called rename on non-renamable node"); + } - return null; - } + try { + ScriptMetaData oldData = parent.getByName(name); + oldData.loadSource(); + String oldSource = oldData.getSource(); - public boolean hasMethod(String aName) { - return false; - } + LogUtils.DEBUG("Create renamed script"); - public boolean hasProperty(String aName) { - return false; + String languageName = + newName + "." + provider.getScriptEditor().getExtension(); + + String language = provider.getName(); + + ScriptEntry entry = new ScriptEntry(language, languageName); + + ScriptMetaData data = + new ScriptMetaData(parent, entry, oldSource); + + parent.insertByName(languageName, data); + + LogUtils.DEBUG("Now remove old script"); + parent.removeByName(name); + + uri = data.getShortFormScriptURL(); + name = languageName; + return this; + } catch (Exception e) { + return null; + } } } diff --git a/scripting/java/com/sun/star/script/framework/provider/ScriptProvider.java b/scripting/java/com/sun/star/script/framework/provider/ScriptProvider.java index e48bc48fbb45..97ea3d0788ed 100644 --- a/scripting/java/com/sun/star/script/framework/provider/ScriptProvider.java +++ b/scripting/java/com/sun/star/script/framework/provider/ScriptProvider.java @@ -38,9 +38,12 @@ import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.lang.XServiceInfo; import com.sun.star.lang.XTypeProvider; -import com.sun.star.script.XInvocation; import com.sun.star.script.browse.BrowseNodeTypes; import com.sun.star.script.browse.XBrowseNode; +import com.sun.star.script.browse.XCreatableBrowseNode; +import com.sun.star.script.browse.XDeletableBrowseNode; +import com.sun.star.script.browse.XEditableBrowseNode; +import com.sun.star.script.browse.XRenamableBrowseNode; import com.sun.star.script.framework.browse.DialogFactory; import com.sun.star.script.framework.browse.ProviderBrowseNode; import com.sun.star.script.framework.container.ParcelContainer; @@ -74,8 +77,9 @@ import com.sun.star.uno.XComponentContext; import com.sun.star.util.XMacroExpander; public abstract class ScriptProvider implements - XScriptProvider, XBrowseNode, XPropertySet, XInvocation, XInitialization, - XTypeProvider, XServiceInfo, XNameContainer { + XScriptProvider, XBrowseNode, XCreatableBrowseNode, XDeletableBrowseNode, + XEditableBrowseNode, XRenamableBrowseNode, XPropertySet, XInitialization, XTypeProvider, + XServiceInfo, XNameContainer { private final String[] __serviceNames = { "com.sun.star.script.provider.ScriptProviderFor", @@ -94,10 +98,13 @@ public abstract class ScriptProvider implements // proxies to helper objects which implement interfaces private XPropertySet m_xPropertySetProxy; - private XInvocation m_xInvocationProxy; // TODO should this be implemented in this class private XBrowseNode m_xBrowseNodeProxy; + private XCreatableBrowseNode m_xCreatableBrowseNodeProxy; + private XDeletableBrowseNode m_xDeletableBrowseNodeProxy; + private XEditableBrowseNode m_xEditableBrowseNodeProxy; + private XRenamableBrowseNode m_xRenamableBrowseNodeProxy; private XScriptContext m_xScriptContext; public ScriptProvider(XComponentContext ctx, String language) { @@ -243,9 +250,15 @@ public abstract class ScriptProvider implements // delegation???? m_xBrowseNodeProxy = new ProviderBrowseNode(this, m_container, m_xContext); + m_xCreatableBrowseNodeProxy = + UnoRuntime.queryInterface(XCreatableBrowseNode.class, m_xBrowseNodeProxy); + m_xDeletableBrowseNodeProxy = + UnoRuntime.queryInterface(XDeletableBrowseNode.class, m_xBrowseNodeProxy); + m_xEditableBrowseNodeProxy = + UnoRuntime.queryInterface(XEditableBrowseNode.class, m_xBrowseNodeProxy); + m_xRenamableBrowseNodeProxy = + UnoRuntime.queryInterface(XRenamableBrowseNode.class, m_xBrowseNodeProxy); - m_xInvocationProxy = - UnoRuntime.queryInterface(XInvocation.class, m_xBrowseNodeProxy); m_xPropertySetProxy = UnoRuntime.queryInterface(XPropertySet.class, m_xBrowseNodeProxy); } else { @@ -264,15 +277,18 @@ public abstract class ScriptProvider implements * @return The types value */ public com.sun.star.uno.Type[] getTypes() { - Type[] retValue = new Type[ 8 ]; + Type[] retValue = new Type[ 11 ]; retValue[ 0 ] = new Type(XScriptProvider.class); retValue[ 1 ] = new Type(XBrowseNode.class); retValue[ 2 ] = new Type(XInitialization.class); retValue[ 3 ] = new Type(XTypeProvider.class); retValue[ 4 ] = new Type(XServiceInfo.class); retValue[ 5 ] = new Type(XPropertySet.class); - retValue[ 6 ] = new Type(XInvocation.class); - retValue[ 7 ] = new Type(com.sun.star.container.XNameContainer.class); + retValue[ 6 ] = new Type(XCreatableBrowseNode.class); + retValue[ 7 ] = new Type(XDeletableBrowseNode.class); + retValue[ 8 ] = new Type(XEditableBrowseNode.class); + retValue[ 9 ] = new Type(XRenamableBrowseNode.class); + retValue[ 10 ] = new Type(com.sun.star.container.XNameContainer.class); return retValue; } @@ -415,44 +431,80 @@ public abstract class ScriptProvider implements return getName(); } - // implementation of XInvocation interface - public XIntrospectionAccess getIntrospection() { - return m_xInvocationProxy.getIntrospection(); + @Override + public boolean isCreatableNode() + { + if (m_xCreatableBrowseNodeProxy != null) + return m_xCreatableBrowseNodeProxy.isCreatableNode(); + else + return false; } - public Object invoke(String aFunctionName, Object[] aParams, - short[][] aOutParamIndex, Object[][] aOutParam) throws - com.sun.star.lang.IllegalArgumentException, - com.sun.star.script.CannotConvertException, - com.sun.star.reflection.InvocationTargetException { - - return m_xInvocationProxy.invoke( - aFunctionName, aParams, aOutParamIndex, aOutParam); + @Override + public XBrowseNode createNode(String newName) + { + if (m_xCreatableBrowseNodeProxy != null) + return m_xCreatableBrowseNodeProxy.createNode(newName); + else + return null; } - public void setValue(String aPropertyName, Object aValue) throws - com.sun.star.beans.UnknownPropertyException, - com.sun.star.script.CannotConvertException, - com.sun.star.reflection.InvocationTargetException { - - m_xInvocationProxy.setValue(aPropertyName, aValue); + @Override + public boolean isDeletableNode() + { + if (m_xDeletableBrowseNodeProxy != null) + return m_xDeletableBrowseNodeProxy.isDeletableNode(); + else + return false; } - public Object getValue(String aPropertyName) throws - com.sun.star.beans.UnknownPropertyException { - return m_xInvocationProxy.getValue(aPropertyName); + @Override + public boolean deleteNode() + { + if (m_xDeletableBrowseNodeProxy != null) + return m_xDeletableBrowseNodeProxy.deleteNode(); + else + return false; } - public boolean hasMethod(String aName) { - return m_xInvocationProxy.hasMethod(aName); + @Override + public boolean isEditableNode() + { + if (m_xEditableBrowseNodeProxy != null) + return m_xEditableBrowseNodeProxy.isEditableNode(); + else + return false; } - public boolean hasProperty(String aName) { - return m_xInvocationProxy.hasProperty(aName); + @Override + public boolean editNode() + { + if (m_xEditableBrowseNodeProxy != null) + return m_xEditableBrowseNodeProxy.editNode(); + else + return false; + } + + @Override + public boolean isRenamableNode() + { + if (m_xRenamableBrowseNodeProxy != null) + return m_xRenamableBrowseNodeProxy.isRenamableNode(); + else + return false; + } + + @Override + public XBrowseNode renameNode(String newName) + { + if (m_xRenamableBrowseNodeProxy != null) + return m_xRenamableBrowseNodeProxy.renameNode(newName); + else + return null; } public XPropertySetInfo getPropertySetInfo() { - return m_xPropertySetProxy.getPropertySetInfo(); + return m_xPropertySetProxy == null ? null : m_xPropertySetProxy.getPropertySetInfo(); } public void setPropertyValue(String aPropertyName, Object aValue) throws @@ -461,14 +513,18 @@ public abstract class ScriptProvider implements com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException { - m_xPropertySetProxy.setPropertyValue(aPropertyName, aValue); + if (m_xPropertySetProxy != null) + m_xPropertySetProxy.setPropertyValue(aPropertyName, aValue); } public Object getPropertyValue(String PropertyName) throws com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException { - return m_xPropertySetProxy.getPropertyValue(PropertyName); + if (m_xPropertySetProxy == null) + return null; + else + return m_xPropertySetProxy.getPropertyValue(PropertyName); } public void addPropertyChangeListener(String aPropertyName, @@ -476,7 +532,8 @@ public abstract class ScriptProvider implements com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException { - m_xPropertySetProxy.addPropertyChangeListener(aPropertyName, xListener); + if (m_xPropertySetProxy != null) + m_xPropertySetProxy.addPropertyChangeListener(aPropertyName, xListener); } public void removePropertyChangeListener( @@ -484,8 +541,8 @@ public abstract class ScriptProvider implements com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException { - m_xPropertySetProxy.removePropertyChangeListener( - aPropertyName, aListener); + if (m_xPropertySetProxy != null) + m_xPropertySetProxy.removePropertyChangeListener(aPropertyName, aListener); } public void addVetoableChangeListener( @@ -493,7 +550,8 @@ public abstract class ScriptProvider implements com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException { - m_xPropertySetProxy.addVetoableChangeListener(PropertyName, aListener); + if (m_xPropertySetProxy != null) + m_xPropertySetProxy.addVetoableChangeListener(PropertyName, aListener); } public void removeVetoableChangeListener(String PropertyName, @@ -501,9 +559,8 @@ public abstract class ScriptProvider implements com.sun.star.beans.UnknownPropertyException, com.sun.star.lang.WrappedTargetException { - m_xPropertySetProxy.removeVetoableChangeListener( - PropertyName, aListener); - + if (m_xPropertySetProxy != null) + m_xPropertySetProxy.removeVetoableChangeListener(PropertyName, aListener); } public java.lang.Object getByName(String aName) throws com.sun.star.container.NoSuchElementException, diff --git a/scripting/qa/cppunit/beanshell/beanshelltest.cxx b/scripting/qa/cppunit/beanshell/beanshelltest.cxx new file mode 100644 index 000000000000..6643bf0350a8 --- /dev/null +++ b/scripting/qa/cppunit/beanshell/beanshelltest.cxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +namespace +{ +class BeanShellTest : public UnoApiTest +{ +public: + BeanShellTest() + : UnoApiTest(u"/scripting/qa/extras"_ustr) + { + } + + void setUp() override; + +private: + void testRenameEmptyLibrary(); + void testRenameNonEmptyLibrary(); + + CPPUNIT_TEST_SUITE(BeanShellTest); + CPPUNIT_TEST(testRenameEmptyLibrary); + CPPUNIT_TEST(testRenameNonEmptyLibrary); + CPPUNIT_TEST_SUITE_END(); +}; + +void BeanShellTest::setUp() +{ + UnoApiTest::setUp(); + + // The ExpandContentProvider is needed for ScriptURIHelper to work + css::uno::Reference xUcb + = css::ucb::UniversalContentBroker::create(m_xContext); + css::uno::Reference xExpandProvider( + m_xSFactory->createInstance(u"com.sun.star.ucb.ExpandContentProvider"_ustr), + css::uno::UNO_QUERY_THROW); + xUcb->registerContentProvider(xExpandProvider, u"vnd.sun.star.expand"_ustr, true); +} + +void createChild(css::uno::Reference& xNode, + const OUString& sName) +{ + css::uno::Reference xCreatable( + xNode, css::uno::UNO_QUERY_THROW); + css::uno::Reference xResult = xCreatable->createNode(sName); + CPPUNIT_ASSERT(xResult.is()); +} + +void renameLibrary(css::uno::Reference& xNode, + const OUString& sName) +{ + css::uno::Reference xRenamable( + xNode, css::uno::UNO_QUERY_THROW); + css::uno::Reference xResult = xRenamable->renameNode(sName); + + CPPUNIT_ASSERT_EQUAL(xResult, xNode); +} + +css::uno::Reference +findChild(const css::uno::Reference& xParent, + std::u16string_view sName) +{ + for (const auto& xChild : xParent->getChildNodes()) + { + if (xChild->getName() == sName) + return xChild; + } + + OString sError + = OUStringToOString(Concat2View(u"Couldn’t find "_ustr + sName), RTL_TEXTENCODING_UTF8); + CPPUNIT_FAIL(sError.getStr()); +} + +void BeanShellTest::testRenameEmptyLibrary() +{ + css::uno::Sequence aArgs = { css::uno::Any(u"user"_ustr) }; + + css::uno::Reference xRoot( + m_xFactory->createInstanceWithArgumentsAndContext( + u"com.sun.star.script.provider.ScriptProviderForBeanShell"_ustr, aArgs, m_xContext), + css::uno::UNO_QUERY_THROW); + + // Create an empty library + createChild(xRoot, "EmptyLibrary"); + + // Make sure the library we just created exists in the hierarchy + css::uno::Reference xEmptyLibrary + = findChild(xRoot, u"EmptyLibrary"); + + // Try renaming it + renameLibrary(xEmptyLibrary, "RenamedEmptyLibrary"); + + // Make sure it now exists in the hierarchy with the new name + findChild(xRoot, u"RenamedEmptyLibrary"); +} + +void BeanShellTest::testRenameNonEmptyLibrary() +{ + css::uno::Sequence aArgs = { css::uno::Any(u"user"_ustr) }; + + css::uno::Reference xRoot( + m_xFactory->createInstanceWithArgumentsAndContext( + u"com.sun.star.script.provider.ScriptProviderForBeanShell"_ustr, aArgs, m_xContext), + css::uno::UNO_QUERY_THROW); + + // Create an empty library + createChild(xRoot, "NonEmptyLibrary"); + + // Make sure the library we just created exists in the hierarchy + css::uno::Reference xNewLibrary + = findChild(xRoot, u"NonEmptyLibrary"); + + // Create a script within the new library + createChild(xNewLibrary, "SomeScript"); + + // Try renaming the library + renameLibrary(xNewLibrary, "RenamedNonEmptyLibrary"); + + // Make sure it now exists in the hierarchy with the new name + css::uno::Reference xNewNode + = findChild(xRoot, u"RenamedNonEmptyLibrary"); + + // Make sure it still has the child + css::uno::Sequence> xChildren + = xNewNode->getChildNodes(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xChildren.getLength()); + CPPUNIT_ASSERT_EQUAL(u"SomeScript.bsh"_ustr, xChildren[0]->getName()); + + // Make sure the child has an updated URI + css::uno::Reference xChildProps(xChildren[0], + css::uno::UNO_QUERY_THROW); + OUString sUri; + CPPUNIT_ASSERT(xChildProps->getPropertyValue("URI") >>= sUri); + CPPUNIT_ASSERT(sUri.indexOf("RenamedNonEmptyLibrary") != -1); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(BeanShellTest); + +} // namespace +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/qa/cppunit/jsprov/jsprovtest.cxx b/scripting/qa/cppunit/jsprov/jsprovtest.cxx new file mode 100644 index 000000000000..c223f75941ba --- /dev/null +++ b/scripting/qa/cppunit/jsprov/jsprovtest.cxx @@ -0,0 +1,456 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +class JsProvTest : public UnoApiTest +{ +public: + JsProvTest() + : UnoApiTest(u"/scripting/qa/extras"_ustr) + { + } + + void setUp() override; + void tearDown() override; + +private: + css::uno::Reference m_xFileAccess; + css::uno::Reference m_xUriHelper; + css::uno::Reference m_xScriptProvider; + + css::uno::Reference createScriptProvider(); + void createDummyMacro(const OUString& sDirectoryUri); + + void testEditableCreatable(); + void testCreate(); + void testRun(); + void testUnrelatedFile(); + void testFolder(); + void testCopyable(); + + CPPUNIT_TEST_SUITE(JsProvTest); + CPPUNIT_TEST(testEditableCreatable); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testRun); + CPPUNIT_TEST(testUnrelatedFile); + CPPUNIT_TEST(testFolder); + CPPUNIT_TEST(testCopyable); + CPPUNIT_TEST_SUITE_END(); +}; + +void JsProvTest::setUp() +{ + UnoApiTest::setUp(); + + m_xFileAccess = css::ucb::SimpleFileAccess::create(m_xContext); + + // The ExpandContentProvider is needed for ScriptURIHelper to work + css::uno::Reference xUcb + = css::ucb::UniversalContentBroker::create(m_xContext); + css::uno::Reference xExpandProvider( + m_xSFactory->createInstance(u"com.sun.star.ucb.ExpandContentProvider"_ustr), + css::uno::UNO_QUERY_THROW); + xUcb->registerContentProvider(xExpandProvider, u"vnd.sun.star.expand"_ustr, true); + + m_xUriHelper = css::script::provider::ScriptURIHelper::create(getComponentContext(), + u"JavaScript"_ustr, u"user"_ustr); + + m_xScriptProvider = createScriptProvider(); +} + +void JsProvTest::tearDown() +{ + m_xScriptProvider.clear(); + + // Delete the JavaScript scripting directory so that each test can have a clean slate + if (m_xFileAccess->isFolder(m_xUriHelper->getRootStorageURI())) + m_xFileAccess->kill(m_xUriHelper->getRootStorageURI()); + + m_xFileAccess.clear(); + m_xUriHelper.clear(); + + UnoApiTest::tearDown(); +} + +css::uno::Reference JsProvTest::createScriptProvider() +{ + // Create the script provider by searching for a factory with the right implementation in case + // there are multiple JavaScript providers + css::uno::Reference xEnumAccess( + m_xFactory, css::uno::UNO_QUERY_THROW); + css::uno::Reference xEnum = xEnumAccess->createContentEnumeration( + "com.sun.star.script.provider.ScriptProviderForJavaScript"); + + while (xEnum->hasMoreElements()) + { + css::uno::Reference xFactory(xEnum->nextElement(), + css::uno::UNO_QUERY_THROW); + css::uno::Reference xServiceInfo(xFactory, + css::uno::UNO_QUERY_THROW); + + if (xServiceInfo->getImplementationName() + != "com.sun.star.singleprov.ScriptProviderForJavaScript") + continue; + + css::uno::Sequence aArgs(1); + aArgs.getArray()[0] <<= u"user"_ustr; + + css::uno::Reference xProvider( + xFactory->createInstanceWithArgumentsAndContext(aArgs, m_xContext), + css::uno::UNO_QUERY_THROW); + + return xProvider; + } + + CPPUNIT_FAIL("Couldn’t find com.sun.star.singleprov.ScriptProviderForJavaScript " + "implementation"); +} + +bool isEditable(const css::uno::Reference& xNode) +{ + css::uno::Reference xEditable(xNode, + css::uno::UNO_QUERY); + + return xEditable.is() && xEditable->isEditableNode(); +} + +bool isCreatable(const css::uno::Reference& xNode) +{ + css::uno::Reference xCreatable(xNode, + css::uno::UNO_QUERY); + + return xCreatable.is() && xCreatable->isCreatableNode(); +} + +void JsProvTest::testEditableCreatable() +{ + // Create a dummy macro in the script directory + createDummyMacro(m_xUriHelper->getRootStorageURI() + "/MyScript.js"); + + // The root node should be creatable but not editable + css::uno::Reference xRootNode(m_xScriptProvider, + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(isCreatable(xRootNode)); + CPPUNIT_ASSERT(!isEditable(xRootNode)); + + css::uno::Reference xBrowseNode(m_xScriptProvider, + css::uno::UNO_QUERY_THROW); + + // The root node should be a container + CPPUNIT_ASSERT_EQUAL(css::script::browse::BrowseNodeTypes::CONTAINER, xBrowseNode->getType()); + + CPPUNIT_ASSERT_EQUAL(u"JavaScript"_ustr, xBrowseNode->getName()); + + // The root node should have exactly one child which is the script we created above + CPPUNIT_ASSERT(xBrowseNode->hasChildNodes()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xBrowseNode->getChildNodes().getLength()); + + xBrowseNode = xBrowseNode->getChildNodes()[0]; + + // The next level down should be a container node to represent the module + CPPUNIT_ASSERT_EQUAL(css::script::browse::BrowseNodeTypes::CONTAINER, xBrowseNode->getType()); + + CPPUNIT_ASSERT_EQUAL(u"MyScript"_ustr, xBrowseNode->getName()); + + // The module should be editable but not creatable + CPPUNIT_ASSERT(!isCreatable(xBrowseNode)); + CPPUNIT_ASSERT(isEditable(xBrowseNode)); + + // The module should have exactly one child to represent the macro + CPPUNIT_ASSERT(xBrowseNode->hasChildNodes()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xBrowseNode->getChildNodes().getLength()); + + xBrowseNode = xBrowseNode->getChildNodes()[0]; + + // Finally we should be on a node representing the actual macro + CPPUNIT_ASSERT_EQUAL(css::script::browse::BrowseNodeTypes::SCRIPT, xBrowseNode->getType()); + + CPPUNIT_ASSERT_EQUAL(u"MyScript"_ustr, xBrowseNode->getName()); + + // The macro should be editable but not creatable + CPPUNIT_ASSERT(!isCreatable(xBrowseNode)); + CPPUNIT_ASSERT(isEditable(xBrowseNode)); + + // The macro should have no children + CPPUNIT_ASSERT(!xBrowseNode->hasChildNodes()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xBrowseNode->getChildNodes().getLength()); + + // Test the macro’s URL + css::uno::Reference xPropertySet(xBrowseNode, + css::uno::UNO_QUERY_THROW); + OUString sMacroUri; + bool bConvertResult = xPropertySet->getPropertyValue("URI") >>= sMacroUri; + CPPUNIT_ASSERT(bConvertResult); + CPPUNIT_ASSERT_EQUAL(u"vnd.sun.star.script:MyScript.js?language=JavaScript&location=user"_ustr, + sMacroUri); +} + +void JsProvTest::testCreate() +{ + css::uno::Reference xBrowseNode(m_xScriptProvider, + css::uno::UNO_QUERY_THROW); + // The root node should start by having no children + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xBrowseNode->getChildNodes().getLength()); + + // The root node should be creatable + CPPUNIT_ASSERT(isCreatable(xBrowseNode)); + + // Invoke the create method + css::uno::Reference xCreatable( + xBrowseNode, css::uno::UNO_QUERY_THROW); + xCreatable->createNode(u"My Script"_ustr); + + // That should have created the file + CPPUNIT_ASSERT(m_xFileAccess->exists(m_xUriHelper->getRootStorageURI() + "/My Script.js")); + + // The file should now appear as a child of the root node + CPPUNIT_ASSERT(xBrowseNode->hasChildNodes()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xBrowseNode->getChildNodes().getLength()); + + CPPUNIT_ASSERT_EQUAL(u"My Script"_ustr, xBrowseNode->getChildNodes()[0]->getName()); +} + +void JsProvTest::createDummyMacro(const OUString& sDirectoryUri) +{ + // Create a dummy macro in the given directory + css::uno::Reference xOutput + = m_xFileAccess->openFileWrite(sDirectoryUri); + + // Make the script insert some text in all of the writer documents + static constexpr OString sSource + = "let context = uno.componentContext;\n" + "let desktop = uno.idl.com.sun.star.frame.theDesktop(context);\n" + "let enumeration = desktop.getComponents().createEnumeration();\n" + "while (enumeration.hasMoreElements())\n" + "{\n" + " let model = enumeration.nextElement();\n" + " model.getText().getEnd().setString(\"jsprovtest\");\n" + "}\n"_ostr; + + css::uno::Sequence aSource(reinterpret_cast(sSource.getStr()), + sSource.getLength()); + xOutput->writeBytes(aSource); + + xOutput->closeOutput(); +} + +void JsProvTest::testRun() +{ + createDummyMacro(m_xUriHelper->getRootStorageURI() + "/MyScript.js"); + + // Get the macro as a property set + css::uno::Reference xBrowseNode(m_xScriptProvider, + css::uno::UNO_QUERY_THROW); + css::uno::Reference xPropertySet( + xBrowseNode->getChildNodes()[0]->getChildNodes()[0], css::uno::UNO_QUERY_THROW); + + // Get the XScript + OUString sScriptUri; + bool bConvertResult = xPropertySet->getPropertyValue("URI") >>= sScriptUri; + CPPUNIT_ASSERT(bConvertResult); + css::uno::Reference xScript + = m_xScriptProvider->getScript(sScriptUri); + CPPUNIT_ASSERT(xScript.is()); + + // Create a document to run the script on + loadFromURL(u"private:factory/swriter"_ustr); + + // Execute it + css::uno::Sequence aScriptParams; + css::uno::Sequence aOutParamIndex; + css::uno::Sequence aOutParam; + xScript->invoke(aScriptParams, aOutParamIndex, aOutParam); + + // Check that the text was inserted into our test document + css::uno::Reference xTextDocument(mxComponent, + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(u"jsprovtest"_ustr, xTextDocument->getText()->getString()); +} + +void JsProvTest::testUnrelatedFile() +{ + // Create a file with a name that shouldn’t be picked up by the JavaScript provider + OUString sFileUri = m_xUriHelper->getRootStorageURI() + "/MyScript.py"; + m_xFileAccess->openFileWrite(sFileUri); + CPPUNIT_ASSERT(m_xFileAccess->exists(sFileUri)); + + css::uno::Reference xBrowseNode(m_xScriptProvider, + css::uno::UNO_QUERY_THROW); + + // The root node should have no children + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xBrowseNode->getChildNodes().getLength()); +} + +void JsProvTest::testFolder() +{ + // Create a file that is nested in subfolders + m_xFileAccess->openFileWrite(m_xUriHelper->getRootStorageURI() + + "/very/nested/file/MyScript.js"); + + css::uno::Reference xBrowseNode(m_xScriptProvider, + css::uno::UNO_QUERY_THROW); + + std::array aParts = { u"very"_ustr, u"nested"_ustr, u"file"_ustr }; + + for (const auto& sPart : aParts) + { + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xBrowseNode->getChildNodes().getLength()); + + xBrowseNode = xBrowseNode->getChildNodes()[0]; + + CPPUNIT_ASSERT_EQUAL(css::script::browse::BrowseNodeTypes::CONTAINER, + xBrowseNode->getType()); + CPPUNIT_ASSERT_EQUAL(sPart, xBrowseNode->getName()); + + // Folders should be creatable but not editable + CPPUNIT_ASSERT(isCreatable(xBrowseNode)); + CPPUNIT_ASSERT(!isEditable(xBrowseNode)); + } + + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xBrowseNode->getChildNodes().getLength()); + xBrowseNode = xBrowseNode->getChildNodes()[0]; + CPPUNIT_ASSERT_EQUAL(u"MyScript"_ustr, xBrowseNode->getName()); +} + +bool isCopyableNode(const css::uno::Reference& xNode) +{ + css::uno::Reference xCopyable(xNode, + css::uno::UNO_QUERY); + + return xCopyable.is() && xCopyable->isCopyableNode(); +} + +void JsProvTest::testCopyable() +{ + // Create a dummy macro in a subfolder of the script directory + m_xFileAccess->createFolder(m_xUriHelper->getRootStorageURI() + "/SrcDir"); + createDummyMacro(m_xUriHelper->getRootStorageURI() + "/SrcDir/MyScript.js"); + + css::uno::Reference xRootNode(m_xScriptProvider, + css::uno::UNO_QUERY_THROW); + + // The root node shouldn’t be copyable + CPPUNIT_ASSERT(!isCopyableNode(xRootNode)); + + css::uno::Reference xLibrary = xRootNode->getChildNodes()[0]; + CPPUNIT_ASSERT_EQUAL(u"SrcDir"_ustr, xLibrary->getName()); + + // The library shouldn’t be copyable + CPPUNIT_ASSERT(!isCopyableNode(xLibrary)); + + css::uno::Reference xFile = xLibrary->getChildNodes()[0]; + CPPUNIT_ASSERT_EQUAL(u"MyScript"_ustr, xFile->getName()); + + // File nodes are copyable + CPPUNIT_ASSERT(isCopyableNode(xFile)); + + css::uno::Reference xMacro = xFile->getChildNodes()[0]; + CPPUNIT_ASSERT_EQUAL(u"MyScript"_ustr, xMacro->getName()); + + // Macro nodes are not copyable + CPPUNIT_ASSERT(!isCopyableNode(xMacro)); + + css::uno::Reference xCopyable( + xFile, css::uno::UNO_QUERY_THROW); + + // We can copy to the root level of the JavaScript hierarchy + CPPUNIT_ASSERT(xCopyable->nodeCanBeCopiedTo(xRootNode)); + // We can’t copy to the same directory that the file is already in + CPPUNIT_ASSERT(!xCopyable->nodeCanBeCopiedTo(xLibrary)); + // We can’t copy to a file + CPPUNIT_ASSERT(!xCopyable->nodeCanBeCopiedTo(xFile)); + // or a macro + CPPUNIT_ASSERT(!xCopyable->nodeCanBeCopiedTo(xMacro)); + + // We shouldn’t be able to copy to any other language providers + css::uno::Reference xMasterProviderFactory + = css::script::provider::theMasterScriptProviderFactory::get(m_xContext); + css::uno::Reference xMasterProvider( + xMasterProviderFactory->createScriptProvider(css::uno::Any(u"user"_ustr)), + css::uno::UNO_QUERY_THROW); + for (const auto& xChild : xMasterProvider->getChildNodes()) + { + if (xChild->getName() == u"JavaScript"_ustr) + continue; + CPPUNIT_ASSERT(!xCopyable->nodeCanBeCopiedTo(xChild)); + } + + // Make a new library that we can copy to + m_xFileAccess->createFolder(m_xUriHelper->getRootStorageURI() + "/DestDir"); + css::uno::Reference xOtherLibrary; + for (const auto& xChild : xRootNode->getChildNodes()) + { + if (xChild->getName() == u"DestDir"_ustr) + { + xOtherLibrary = xChild; + break; + } + } + CPPUNIT_ASSERT(xOtherLibrary.is()); + + // We should be able to copy into the new library + CPPUNIT_ASSERT(xCopyable->nodeCanBeCopiedTo(xOtherLibrary)); + css::uno::Reference xCopiedNode + = xCopyable->copyNode(xOtherLibrary); + + CPPUNIT_ASSERT_EQUAL(u"MyScript"_ustr, xCopiedNode->getName()); + + css::uno::Reference xCopiedMacro + = xCopiedNode->getChildNodes()[0]; + CPPUNIT_ASSERT_EQUAL(u"MyScript"_ustr, xCopiedMacro->getName()); + + // Get the URI of the copied macro + css::uno::Reference xPropertySet(xCopiedMacro, + css::uno::UNO_QUERY_THROW); + css::uno::Any xURI = xPropertySet->getPropertyValue(u"URI"_ustr); + OUString sURI; + CPPUNIT_ASSERT(xURI >>= sURI); + + // The URI should contain the new library name + CPPUNIT_ASSERT(sURI.indexOf(":DestDir|") != -1); + + // Create a document to run the script on + loadFromURL(u"private:factory/swriter"_ustr); + + // Execute it + css::uno::Sequence aScriptParams; + css::uno::Sequence aOutParamIndex; + css::uno::Sequence aOutParam; + m_xScriptProvider->getScript(sURI)->invoke(aScriptParams, aOutParamIndex, aOutParam); + + // Check that the text was inserted into our test document + css::uno::Reference xTextDocument(mxComponent, + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(u"jsprovtest"_ustr, xTextDocument->getText()->getString()); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(JsProvTest); + +} // namespace +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/qa/cppunit/pythonscript/PythonScriptTest.cxx b/scripting/qa/cppunit/pythonscript/PythonScriptTest.cxx new file mode 100644 index 000000000000..1de73580596d --- /dev/null +++ b/scripting/qa/cppunit/pythonscript/PythonScriptTest.cxx @@ -0,0 +1,201 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +class PythonScriptTest : public UnoApiTest +{ +public: + PythonScriptTest() + : UnoApiTest(u"/scripting/qa/extras"_ustr) + { + } + + void setUp() override; + void tearDown() override; + +private: + css::uno::Reference m_xFileAccess; + css::uno::Reference m_xUriHelper; + css::uno::Reference m_xScriptProvider; + + void createDummyMacro(); + + void testCopyable(); + + CPPUNIT_TEST_SUITE(PythonScriptTest); + CPPUNIT_TEST(testCopyable); + CPPUNIT_TEST_SUITE_END(); +}; + +void PythonScriptTest::setUp() +{ + UnoApiTest::setUp(); + + m_xFileAccess = css::ucb::SimpleFileAccess::create(m_xContext); + + // The ExpandContentProvider is needed for ScriptURIHelper to work + css::uno::Reference xUcb + = css::ucb::UniversalContentBroker::create(m_xContext); + css::uno::Reference xExpandProvider( + m_xSFactory->createInstance(u"com.sun.star.ucb.ExpandContentProvider"_ustr), + css::uno::UNO_QUERY_THROW); + xUcb->registerContentProvider(xExpandProvider, u"vnd.sun.star.expand"_ustr, true); + + m_xUriHelper = css::script::provider::ScriptURIHelper::create(getComponentContext(), + u"Python"_ustr, u"user"_ustr); + + css::uno::Sequence aArgs(1); + aArgs.getArray()[0] <<= u"user"_ustr; + + m_xScriptProvider.set( + m_xFactory->createInstanceWithArgumentsAndContext( + "com.sun.star.script.provider.ScriptProviderForPython", aArgs, m_xContext), + css::uno::UNO_QUERY_THROW); +} + +void PythonScriptTest::tearDown() +{ + m_xScriptProvider.clear(); + + // Delete the Python scripting directory so that each test can have a clean slate + if (m_xFileAccess->isFolder(m_xUriHelper->getRootStorageURI())) + m_xFileAccess->kill(m_xUriHelper->getRootStorageURI()); + + m_xFileAccess.clear(); + m_xUriHelper.clear(); + + UnoApiTest::tearDown(); +} + +void PythonScriptTest::createDummyMacro() +{ + // Create a dummy macro in the script directory + css::uno::Reference xOutput = m_xFileAccess->openFileWrite( + m_xUriHelper->getRootStorageURI() + "/MyLibrary/MyScript.py"); + css::uno::Reference xTextOutput + = css::io::TextOutputStream::create(m_xContext); + xTextOutput->setEncoding(u"UTF-8"_ustr); + + css::uno::Reference xActiveDataSource(xTextOutput, + css::uno::UNO_QUERY_THROW); + xActiveDataSource->setOutputStream(xOutput); + + xTextOutput->writeString(u"def MyMacro():\n pass\n"_ustr); + xTextOutput->closeOutput(); +} + +bool isCopyableNode(const css::uno::Reference& xNode) +{ + css::uno::Reference xCopyable(xNode, + css::uno::UNO_QUERY); + + return xCopyable.is() && xCopyable->isCopyableNode(); +} + +void PythonScriptTest::testCopyable() +{ + createDummyMacro(); + + css::uno::Reference xRootNode(m_xScriptProvider, + css::uno::UNO_QUERY_THROW); + + // The root node shouldn’t be copyable + CPPUNIT_ASSERT(!isCopyableNode(xRootNode)); + + css::uno::Reference xLibrary = xRootNode->getChildNodes()[0]; + CPPUNIT_ASSERT_EQUAL(u"MyLibrary"_ustr, xLibrary->getName()); + + // The library shouldn’t be copyable + CPPUNIT_ASSERT(!isCopyableNode(xLibrary)); + + css::uno::Reference xFile = xLibrary->getChildNodes()[0]; + CPPUNIT_ASSERT_EQUAL(u"MyScript"_ustr, xFile->getName()); + + // File nodes are copyable + CPPUNIT_ASSERT(isCopyableNode(xFile)); + + css::uno::Reference xMacro = xFile->getChildNodes()[0]; + CPPUNIT_ASSERT_EQUAL(u"MyMacro"_ustr, xMacro->getName()); + + // Macro nodes are not copyable + CPPUNIT_ASSERT(!isCopyableNode(xMacro)); + + css::uno::Reference xCopyable( + xFile, css::uno::UNO_QUERY_THROW); + + // We can copy to the root level of the Python hierarchy + CPPUNIT_ASSERT(xCopyable->nodeCanBeCopiedTo(xRootNode)); + // We can’t copy to the same directory that the file is already in + CPPUNIT_ASSERT(!xCopyable->nodeCanBeCopiedTo(xLibrary)); + // We can’t copy to a file + CPPUNIT_ASSERT(!xCopyable->nodeCanBeCopiedTo(xFile)); + // or a macro + CPPUNIT_ASSERT(!xCopyable->nodeCanBeCopiedTo(xMacro)); + + // Make a new library that we can copy to + m_xFileAccess->createFolder(m_xUriHelper->getRootStorageURI() + "/MyOtherLibrary"); + css::uno::Reference xOtherLibrary; + for (const auto& xChild : xRootNode->getChildNodes()) + { + if (xChild->getName() == u"MyOtherLibrary"_ustr) + { + xOtherLibrary = xChild; + break; + } + } + CPPUNIT_ASSERT(xOtherLibrary.is()); + + // We should be able to copy into the new library + CPPUNIT_ASSERT(xCopyable->nodeCanBeCopiedTo(xOtherLibrary)); + css::uno::Reference xCopiedNode + = xCopyable->copyNode(xOtherLibrary); + + CPPUNIT_ASSERT_EQUAL(u"MyScript"_ustr, xCopiedNode->getName()); + + css::uno::Reference xCopiedMacro + = xCopiedNode->getChildNodes()[0]; + CPPUNIT_ASSERT_EQUAL(u"MyMacro"_ustr, xCopiedMacro->getName()); + + // Get the URI of the copied macro + css::uno::Reference xPropertySet(xCopiedMacro, + css::uno::UNO_QUERY_THROW); + css::uno::Any xURI = xPropertySet->getPropertyValue(u"URI"_ustr); + OUString sURI; + CPPUNIT_ASSERT(xURI >>= sURI); + + // The URI should contain the new library name + CPPUNIT_ASSERT(sURI.indexOf(":MyOtherLibrary|") != -1); + + // Check that we can load the script. This should also end up checking that the contents of the + // file contains the macro. + CPPUNIT_ASSERT(m_xScriptProvider->getScript(sURI).is()); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(PythonScriptTest); + +} // namespace +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/qa/cppunit/scripthandler/ScriptHandlerTest.cxx b/scripting/qa/cppunit/scripthandler/ScriptHandlerTest.cxx new file mode 100644 index 000000000000..4a4d900645fa --- /dev/null +++ b/scripting/qa/cppunit/scripthandler/ScriptHandlerTest.cxx @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +constexpr OUString DUMMY_PROVIDER_SERVICE + = u"com.sun.star.script.provider.ScriptProviderForDummy"_ustr; +constexpr OUString LANGUAGE_PROVIDER_SERVICE + = u"com.sun.star.script.provider.LanguageScriptProvider"_ustr; +constexpr OUString SCRIPT_URL + = u"vnd.sun.star.script:Whatever?language=Dummy&location=document"_ustr; + +// A Dummy script provider so that we can execute our own function instead of running a script +class DummyProvider + : public cppu::WeakImplHelper +{ +public: + // XScriptProvider + css::uno::Reference + SAL_CALL getScript(const OUString& sScriptURI) override; + + // XScript + css::uno::Any SAL_CALL invoke(const css::uno::Sequence& aParams, + css::uno::Sequence& aOutParamIndex, + css::uno::Sequence& aOutParam) override; + + // XServiceInfo + OUString SAL_CALL getImplementationName() override; + sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override; + css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + + // XSingleComponentFactory + css::uno::Reference SAL_CALL createInstanceWithContext( + const css::uno::Reference& xContext) override; + css::uno::Reference SAL_CALL createInstanceWithArgumentsAndContext( + const css::uno::Sequence& rArguments, + const css::uno::Reference& xContext) override; + + bool m_bInvoked = false; +}; + +css::uno::Reference + SAL_CALL DummyProvider::getScript(const OUString&) +{ + return this; +} + +css::uno::Any SAL_CALL DummyProvider::invoke(const css::uno::Sequence& aParams, + css::uno::Sequence&, + css::uno::Sequence&) +{ + CPPUNIT_ASSERT_GREATEREQUAL(sal_Int32(6), aParams.getLength()); + + // First argument should be the URL + OUString sUrl; + CPPUNIT_ASSERT(aParams[0] >>= sUrl); + CPPUNIT_ASSERT_EQUAL(SCRIPT_URL, sUrl); + + // Second argument should be an XInteractionHandler + css::uno::Reference xInteractionHandler; + CPPUNIT_ASSERT(aParams[1] >>= xInteractionHandler); + + // Third argument is the OpenNewView value + bool bOpenNewView = true; + CPPUNIT_ASSERT(aParams[2] >>= bOpenNewView); + CPPUNIT_ASSERT(!bOpenNewView); + + // Fourth argument is the frame name + OUString sFrameName; + CPPUNIT_ASSERT(aParams[3] >>= sFrameName); + CPPUNIT_ASSERT_EQUAL(u"_self"_ustr, sFrameName); + + // Fifth argument is the macro execution mode + sal_Int16 nMacroExecutionMode = 0; + CPPUNIT_ASSERT(aParams[4] >>= nMacroExecutionMode); + CPPUNIT_ASSERT_EQUAL(css::document::MacroExecMode::USE_CONFIG, nMacroExecutionMode); + + // Sixth argument is the update doc mode + sal_Int16 nUpdateDocMode = 0; + CPPUNIT_ASSERT(aParams[5] >>= nUpdateDocMode); + CPPUNIT_ASSERT_EQUAL(css::document::UpdateDocMode::ACCORDING_TO_CONFIG, nUpdateDocMode); + + m_bInvoked = true; + + return css::uno::Any(); +} + +OUString SAL_CALL DummyProvider::getImplementationName() +{ + return u"com.sun.star.test.ScriptProviderForDummy"_ustr; +} + +sal_Bool SAL_CALL DummyProvider::supportsService(const OUString& sServiceName) +{ + return sServiceName == DUMMY_PROVIDER_SERVICE || sServiceName == LANGUAGE_PROVIDER_SERVICE; +} + +css::uno::Sequence SAL_CALL DummyProvider::getSupportedServiceNames() +{ + return css::uno::Sequence{ DUMMY_PROVIDER_SERVICE, LANGUAGE_PROVIDER_SERVICE }; +} + +css::uno::Reference SAL_CALL +DummyProvider::createInstanceWithContext(const css::uno::Reference&) +{ + return static_cast(this); +} + +css::uno::Reference + SAL_CALL DummyProvider::createInstanceWithArgumentsAndContext( + const css::uno::Sequence&, + const css::uno::Reference&) +{ + return static_cast(this); +} + +class ScriptHandlerTest : public UnoApiTest +{ +public: + ScriptHandlerTest() + : UnoApiTest(u"/scripting/qa/extras"_ustr) + { + } + +private: + void testDispatchArguments(); + + CPPUNIT_TEST_SUITE(ScriptHandlerTest); + CPPUNIT_TEST(testDispatchArguments); + CPPUNIT_TEST_SUITE_END(); +}; + +void ScriptHandlerTest::testDispatchArguments() +{ + // Tests that the first argument to a macro when invoked via a dispatch URL is the URL itself. + // See tdf#173160. + rtl::Reference xDummyProvider = new DummyProvider; + + // Temporarily register our dummy provider with the service manager so that the master script + // provider can find it + css::uno::Reference xServiceSet(m_xFactory, css::uno::UNO_QUERY_THROW); + css::uno::Reference xService(xDummyProvider); + xServiceSet->insert(css::uno::Any(xService)); + comphelper::ScopeGuard g( + [&xServiceSet, &xService] { xServiceSet->remove(css::uno::Any(xService)); }); + + css::uno::Sequence aPropertyValues = { + comphelper::makePropertyValue(u"FileName"_ustr, SCRIPT_URL), + comphelper::makePropertyValue(u"InteractionHandler"_ustr, + css::uno::Reference()), + comphelper::makePropertyValue(u"OpenNewView"_ustr, false), + comphelper::makePropertyValue(u"FrameName"_ustr, u"_self"_ustr), + comphelper::makePropertyValue(u"MacroExecutionMode"_ustr, + css::document::MacroExecMode::USE_CONFIG), + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + css::document::UpdateDocMode::ACCORDING_TO_CONFIG), + comphelper::makePropertyValue(u"SynchronMode"_ustr, false), + }; + + loadFromURL(u"private:factory/swriter"_ustr); + + // Dispatch the .uno:Open command. We can’t use XDispatchHelper for this because it will set + // SynchronMode to true and there isn’t a synchronous handler for it. + + css::uno::Reference xModel(mxComponent, css::uno::UNO_QUERY_THROW); + css::uno::Reference xDispatchProvider( + xModel->getCurrentController(), css::uno::UNO_QUERY_THROW); + + css::uno::Reference xParser + = css::util::URLTransformer::create(m_xContext); + css::util::URL aURL; + aURL.Complete = ".uno:Open"; + xParser->parseStrict(aURL); + + css::uno::Reference xDispatch + = xDispatchProvider->queryDispatch(aURL, OUString(), 0); + CPPUNIT_ASSERT(xDispatch.is()); + + xDispatch->dispatch(aURL, aPropertyValues); + + Scheduler::ProcessEventsToIdle(); + + // Make sure the script was actually invoked + CPPUNIT_ASSERT(xDummyProvider->m_bInvoked); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(ScriptHandlerTest); + +} // namespace + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/qa/pytests/provider_expandall.py b/scripting/qa/pytests/provider_expandall.py new file mode 100644 index 000000000000..9baa1625d0cd --- /dev/null +++ b/scripting/qa/pytests/provider_expandall.py @@ -0,0 +1,102 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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 unittest + +from org.libreoffice.unotest import pyuno +from com.sun.star.script.provider import theMasterScriptProviderFactory, ScriptURIHelper +from com.sun.star.ucb import UniversalContentBroker +from com.sun.star.uri import UriReferenceFactory +from com.sun.star.container import NoSuchElementException +import uno + +import contextlib +import os +import tempfile + + +testEnvironmentInitialized = False + + +def get_user_script_directory(context, language): + uriHelper = ScriptURIHelper.create(context, language, "user") + uri = uriHelper.getRootStorageURI() + return uno.fileUrlToSystemPath(uri) + + +class ProviderExpandAllTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.context = pyuno.getComponentContext() + global testEnvironmentInitialized + if not testEnvironmentInitialized: + pyuno.private_initTestEnvironment() + testEnvironmentInitialized = True + + # The ExpandContentProvider is needed for ScriptURIHelper to work + xUcb = UniversalContentBroker.create(cls.context) + xExpandProvider = cls.context.getServiceManager().createInstance( + "com.sun.star.ucb.ExpandContentProvider") + xUcb.registerContentProvider(xExpandProvider, "vnd.sun.star.expand", True) + + # Tries retrieving all nodes from the master script provider to make sure all of the providers + # are accessible from Python. See tdf#172532 + def test_expand_all(self): + # Disable the Java-based JavaScript provider so that we can be sure the QuickJS-based one + # will be used. Otherwise a random one will end up getting chosen and if it happens to be + # the Java one then the test will fail. The Java code is shared with the BeanShell provider + # so that will already be tested that way. + try: + self.context.getServiceManager().remove( + "com.sun.star.script.framework.provider.javascript.ScriptProviderForJavaScript$" + "ScriptProviderForJavaScript_2") + except NoSuchElementException: + pass + + with contextlib.ExitStack() as stack: + # If the QuickJS-based script provider is available then create a dummy JavaScript macro + # to make sure the provider is triggered. + if ("com.sun.star.script.provider.ScriptProviderForJavaScript" + in self.context.getServiceManager().getAvailableServiceNames()): + have_js_provider = True + js_path = get_user_script_directory(self.context, "JavaScript") + os.makedirs(js_path, exist_ok=True) + js_dir = stack.enter_context(tempfile.TemporaryDirectory(dir=js_path)) + with open(os.path.join(js_dir, "dummy_js_script.js"), 'w'): + pass + else: + have_js_provider = False + + xMasterProviderFactory = theMasterScriptProviderFactory.get(self.context) + + found_js_script = False + + for provider_context in ['user', 'share']: + xMasterProvider = xMasterProviderFactory.createScriptProvider(provider_context) + + stack = [xMasterProvider] + + while True: + try: + node = stack.pop() + except IndexError: + break + + if node.getName() == "dummy_js_script": + found_js_script = True + + # Add all of the children to the stack + if node.hasChildNodes(): + stack.extend(node.getChildNodes()) + + if have_js_provider: + self.assertTrue(found_js_script) + + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/scripting/source/basprov/basmethnode.cxx b/scripting/source/basprov/basmethnode.cxx index d0e1d8d93c54..30e90c699ae9 100644 --- a/scripting/source/basprov/basmethnode.cxx +++ b/scripting/source/basprov/basmethnode.cxx @@ -42,10 +42,8 @@ using namespace ::com::sun::star::script; using namespace ::sf_misc; #define BASPROV_PROPERTY_ID_URI 1 -#define BASPROV_PROPERTY_ID_EDITABLE 2 constexpr OUStringLiteral BASPROV_PROPERTY_URI = u"URI"; -constexpr OUString BASPROV_PROPERTY_EDITABLE = u"Editable"_ustr; #define BASPROV_DEFAULT_ATTRIBS() PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT | PropertyAttribute::READONLY @@ -64,7 +62,6 @@ namespace basprov ,m_sScriptingContext(std::move( sScriptingContext )) ,m_pMethod( pMethod ) ,m_bIsAppScript( isAppScript ) - ,m_bEditable( true ) { if ( m_pMethod ) { @@ -90,7 +87,6 @@ namespace basprov } registerProperty( BASPROV_PROPERTY_URI, BASPROV_PROPERTY_ID_URI, BASPROV_DEFAULT_ATTRIBS(), &m_sURI, cppu::UnoType::get() ); - registerProperty( BASPROV_PROPERTY_EDITABLE, BASPROV_PROPERTY_ID_EDITABLE, BASPROV_DEFAULT_ATTRIBS(), &m_bEditable, cppu::UnoType::get() ); } @@ -99,18 +95,6 @@ namespace basprov } - // XInterface - - - IMPLEMENT_FORWARD_XINTERFACE2( BasicMethodNodeImpl, BasicMethodNodeImpl_BASE, comphelper::OPropertyContainer2 ) - - - // XTypeProvider - - - IMPLEMENT_FORWARD_XTYPEPROVIDER2( BasicMethodNodeImpl, BasicMethodNodeImpl_BASE, comphelper::OPropertyContainer2 ) - - // XBrowseNode @@ -144,15 +128,6 @@ namespace basprov } - // OPropertySetHelper - - - ::cppu::IPropertyArrayHelper& BasicMethodNodeImpl::getInfoHelper( ) - { - return *getArrayHelper(); - } - - // OPropertyArrayUsageHelper @@ -164,35 +139,11 @@ namespace basprov } - // XPropertySet + sal_Bool BasicMethodNodeImpl::isEditableNode( ) { return true; } - Reference< XPropertySetInfo > BasicMethodNodeImpl::getPropertySetInfo( ) + sal_Bool BasicMethodNodeImpl::editNode( ) { - Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); - return xInfo; - } - - - // XInvocation - - - Reference< XIntrospectionAccess > BasicMethodNodeImpl::getIntrospection( ) - { - return Reference< XIntrospectionAccess >(); - } - - - Any BasicMethodNodeImpl::invoke( const OUString& aFunctionName, const Sequence< Any >&, - Sequence< sal_Int16 >&, Sequence< Any >& ) - { - if ( aFunctionName != BASPROV_PROPERTY_EDITABLE ) - { - throw IllegalArgumentException( - u"BasicMethodNodeImpl::invoke: function name not supported!"_ustr, - Reference< XInterface >(), 1 ); - } - OUString sDocURL, sLibName, sModName; sal_uInt16 nLine1 = 0; @@ -251,37 +202,7 @@ namespace basprov } - return Any(); - } - - - void BasicMethodNodeImpl::setValue( const OUString&, const Any& ) - { - throw UnknownPropertyException( - u"BasicMethodNodeImpl::setValue: property name is unknown!"_ustr ); - } - - - Any BasicMethodNodeImpl::getValue( const OUString& ) - { - throw UnknownPropertyException( - u"BasicMethodNodeImpl::getValue: property name is unknown!"_ustr ); - } - - - sal_Bool BasicMethodNodeImpl::hasMethod( const OUString& aName ) - { - bool bReturn = false; - if ( aName == BASPROV_PROPERTY_EDITABLE ) - bReturn = true; - - return bReturn; - } - - - sal_Bool BasicMethodNodeImpl::hasProperty( const OUString& ) - { - return false; + return true; } diff --git a/scripting/source/basprov/basmethnode.hxx b/scripting/source/basprov/basmethnode.hxx index d50bb663cefa..065e68125c42 100644 --- a/scripting/source/basprov/basmethnode.hxx +++ b/scripting/source/basprov/basmethnode.hxx @@ -19,16 +19,11 @@ #pragma once -#include -#include #include +#include #include -#include -#include -#include -#include -#include +#include class SbMethod; @@ -36,16 +31,12 @@ class SbMethod; namespace basprov { - - - - typedef ::comphelper::WeakImplHelper< - css::script::browse::XBrowseNode, - css::script::XInvocation > BasicMethodNodeImpl_BASE; - - class BasicMethodNodeImpl : public BasicMethodNodeImpl_BASE, - public ::comphelper::OPropertyContainer2, - public ::comphelper::OPropertyArrayUsageHelper< BasicMethodNodeImpl > + class BasicMethodNodeImpl final + : public comphelper::OPropertyContainerImplHelper< + comphelper::WeakImplHelper< + css::script::browse::XBrowseNode, + css::script::browse::XEditableBrowseNode>, + BasicMethodNodeImpl> { private: css::uno::Reference< css::uno::XComponentContext > m_xContext; @@ -55,12 +46,8 @@ namespace basprov // properties OUString m_sURI; - bool m_bEditable; protected: - // OPropertySetHelper - virtual ::cppu::IPropertyArrayHelper& getInfoHelper( ) override; - // OPropertyArrayUsageHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; @@ -70,32 +57,15 @@ namespace basprov SbMethod* pMethod, bool isAppScript ); virtual ~BasicMethodNodeImpl() override; - // XInterface - DECLARE_XINTERFACE() - - // XTypeProvider - DECLARE_XTYPEPROVIDER() - // XBrowseNode virtual OUString SAL_CALL getName( ) override; virtual css::uno::Sequence< css::uno::Reference< css::script::browse::XBrowseNode > > SAL_CALL getChildNodes( ) override; virtual sal_Bool SAL_CALL hasChildNodes( ) override; virtual sal_Int16 SAL_CALL getType( ) override; - // XPropertySet - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; - - // XInvocation - virtual css::uno::Reference< css::beans::XIntrospectionAccess > SAL_CALL getIntrospection( ) override; - virtual css::uno::Any SAL_CALL invoke( - const OUString& aFunctionName, - const css::uno::Sequence< css::uno::Any >& aParams, - css::uno::Sequence< sal_Int16 >& aOutParamIndex, - css::uno::Sequence< css::uno::Any >& aOutParam ) override; - virtual void SAL_CALL setValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; - virtual css::uno::Any SAL_CALL getValue( const OUString& aPropertyName ) override; - virtual sal_Bool SAL_CALL hasMethod( const OUString& aName ) override; - virtual sal_Bool SAL_CALL hasProperty( const OUString& aName ) override; + // XEditableBrowseNode + virtual sal_Bool SAL_CALL isEditableNode( ) override; + virtual sal_Bool SAL_CALL editNode( ) override; }; diff --git a/scripting/source/basprov/basscript.cxx b/scripting/source/basprov/basscript.cxx index 5f124d1c3d80..bd6924cb7f5f 100644 --- a/scripting/source/basprov/basscript.cxx +++ b/scripting/source/basprov/basscript.cxx @@ -115,27 +115,6 @@ constexpr OUString BASSCRIPT_PROPERTY_CALLER = u"Caller"_ustr; } - // XInterface - - - IMPLEMENT_FORWARD_XINTERFACE2( BasicScriptImpl, BasicScriptImpl_BASE, comphelper::OPropertyContainer2 ) - - - // XTypeProvider - - - IMPLEMENT_FORWARD_XTYPEPROVIDER2( BasicScriptImpl, BasicScriptImpl_BASE, comphelper::OPropertyContainer2 ) - - - // OPropertySetHelper - - - ::cppu::IPropertyArrayHelper& BasicScriptImpl::getInfoHelper( ) - { - return *getArrayHelper(); - } - - // OPropertyArrayUsageHelper @@ -147,16 +126,6 @@ constexpr OUString BASSCRIPT_PROPERTY_CALLER = u"Caller"_ustr; } - // XPropertySet - - - Reference< XPropertySetInfo > BasicScriptImpl::getPropertySetInfo( ) - { - Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); - return xInfo; - } - - // XScript @@ -310,6 +279,10 @@ constexpr OUString BASSCRIPT_PROPERTY_CALLER = u"Caller"_ustr; // reset parameters m_xMethod->SetParameters( nullptr ); + + // prevent cycles from leaking memory + if (xSbxParams) + xSbxParams->Clear(); } return aReturn; diff --git a/scripting/source/basprov/basscript.hxx b/scripting/source/basprov/basscript.hxx index 2adcd9c8b311..51fd94040a1d 100644 --- a/scripting/source/basprov/basscript.hxx +++ b/scripting/source/basprov/basscript.hxx @@ -21,11 +21,9 @@ #include #include -#include -#include -#include -#include + #include +#include #include class BasicManager; @@ -34,16 +32,11 @@ class BasicManager; namespace basprov { - - - - typedef ::comphelper::WeakImplHelper< - css::script::provider::XScript > BasicScriptImpl_BASE; - - - class BasicScriptImpl : public BasicScriptImpl_BASE, public SfxListener, - public ::comphelper::OPropertyContainer2, - public ::comphelper::OPropertyArrayUsageHelper< BasicScriptImpl > + class BasicScriptImpl final + : public comphelper::OPropertyContainerImplHelper< + comphelper::WeakImplHelper, + BasicScriptImpl>, + public SfxListener { private: SbMethodRef m_xMethod; @@ -56,9 +49,6 @@ namespace basprov // as it's not unusual to do that in corba ) css::uno::Sequence< css::uno::Any > m_caller; protected: - // OPropertySetHelper - virtual ::cppu::IPropertyArrayHelper& getInfoHelper( ) override; - // OPropertyArrayUsageHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; @@ -75,20 +65,11 @@ namespace basprov ); virtual ~BasicScriptImpl() override; - // XInterface - DECLARE_XINTERFACE() - - // XTypeProvider - DECLARE_XTYPEPROVIDER() - // XScript virtual css::uno::Any SAL_CALL invoke( const css::uno::Sequence< css::uno::Any >& aParams, css::uno::Sequence< sal_Int16 >& aOutParamIndex, css::uno::Sequence< css::uno::Any >& aOutParam ) override; - // XPropertySet - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; - // SfxListener virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; }; diff --git a/scripting/source/dlgprov/dlgevtatt.cxx b/scripting/source/dlgprov/dlgevtatt.cxx index 5379cc1c2034..3b151eaed222 100644 --- a/scripting/source/dlgprov/dlgevtatt.cxx +++ b/scripting/source/dlgprov/dlgevtatt.cxx @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/scripting/source/inc/singleprov/directorynode.hxx b/scripting/source/inc/singleprov/directorynode.hxx new file mode 100644 index 000000000000..5df7bdf1280d --- /dev/null +++ b/scripting/source/inc/singleprov/directorynode.hxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include + +namespace singleprovider +{ +class SingleScriptFactory; + +class SAL_LOPLUGIN_ANNOTATE("crosscast") DirectoryNode +{ +public: + virtual std::shared_ptr getScriptFactory() const = 0; + virtual std::optional getDirectoryUri() const = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/inc/singleprov/scriptprovider.hxx b/scripting/source/inc/singleprov/scriptprovider.hxx new file mode 100644 index 000000000000..cc1b43e0c1c9 --- /dev/null +++ b/scripting/source/inc/singleprov/scriptprovider.hxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace singleprovider +{ +class ProviderContext; +class ScriptBrowser; +class SingleScriptFactory; + +class ScriptProvider + : public cppu::WeakImplHelper, + public DirectoryNode +{ +public: + // XInitialization + void SAL_CALL initialize(const css::uno::Sequence& aArguments) override; + + // XServiceInfo + OUString SAL_CALL getImplementationName() override; + sal_Bool SAL_CALL supportsService(OUString const& serviceName) override; + css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + + // XBrowseNode + OUString SAL_CALL getName() override; + css::uno::Sequence> + SAL_CALL getChildNodes() override; + sal_Bool SAL_CALL hasChildNodes() override; + sal_Int16 SAL_CALL getType() override; + + // XCreatableBrowseNode + sal_Bool SAL_CALL isCreatableNode() override; + css::uno::Reference + SAL_CALL createNode(const OUString& sName) override; + + // XEditableBrowseNode + sal_Bool SAL_CALL isEditableNode() override; + sal_Bool SAL_CALL editNode() override; + + // XScriptProvider + css::uno::Reference + SAL_CALL getScript(const OUString& sScriptUri) override; + + // XPropertySet + css::uno::Reference SAL_CALL getPropertySetInfo() override; + void SAL_CALL setPropertyValue(const OUString& aPropertyName, + const css::uno::Any& aValue) override; + css::uno::Any SAL_CALL getPropertyValue(const OUString& sPropertyName) override; + void SAL_CALL addPropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& xListener) override; + void SAL_CALL removePropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& aListener) override; + void SAL_CALL addVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + void SAL_CALL removeVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + + // DirectoryNode + std::shared_ptr getScriptFactory() const override; + std::optional getDirectoryUri() const override; + + static SAL_DLLPUBLIC_EXPORT OUString + getImplementationNameStatic(std::u16string_view sLanguageName); + static SAL_DLLPUBLIC_EXPORT css::uno::Sequence + getSupportedServiceNamesStatic(std::u16string_view sLanguageName); + static SAL_DLLPUBLIC_EXPORT css::uno::Reference + create(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory); + +private: + ScriptProvider(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory); + + void setLocation(const OUString& sLocation); + + std::shared_ptr m_pProviderContext; + css::uno::Reference m_xRootBrowser; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/inc/singleprov/singlescriptfactory.hxx b/scripting/source/inc/singleprov/singlescriptfactory.hxx new file mode 100644 index 000000000000..dca2754daa86 --- /dev/null +++ b/scripting/source/inc/singleprov/singlescriptfactory.hxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +namespace com::sun::star::script::provider +{ +class XScript; +} + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +namespace singleprovider +{ +// Abstract class to provide callbacks into the real script provider. The provider should be able to +// just provide an implementation of the class and pass it to singleprov::ScriptBrowser. +class SingleScriptFactory +{ +public: + virtual OUString getLanguageName() const = 0; + // Gets the extensions (including the ‘.’) for files that this factory is interested in + virtual OUString getExtension() const = 0; + // Given the source code, returns the XScript for the macro contained within + virtual css::uno::Reference + getScript(css::uno::Reference xContext, const OUString& sName, + std::string_view sSource) const = 0; + // Given the basename of an executable, returns whether it looks like it might be an interpreter + // for the given language. This is used on Windows to try to avoid invoking a default app that + // is actually just going to run the script instead of editing it. + virtual bool appMightExecute(const OUString& sAppName) const; + // Get a string that will be inserted into a new source file as an example when the create + // button is pressed. + virtual OUString getExampleMacro() const { return OUString(); } + + virtual ~SingleScriptFactory() = default; +}; + +inline bool SingleScriptFactory::appMightExecute(const OUString&) const { return false; } +} diff --git a/scripting/source/inc/util/ScriptContext.hxx b/scripting/source/inc/util/ScriptContext.hxx new file mode 100644 index 000000000000..799f596173be --- /dev/null +++ b/scripting/source/inc/util/ScriptContext.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +namespace sf_misc +{ +class ScriptContext : public cppu::WeakImplHelper +{ +public: + explicit ScriptContext( + const css::uno::Reference& xContext, + const css::uno::Reference& xDocument + = css::uno::Reference(), + const css::uno::Reference& xInvocation + = css::uno::Reference()) + : m_xContext(xContext) + , m_xDocument(xDocument) + , m_xInvocation(xInvocation) + { + assert(m_xContext.is()); + } + + // XScriptContext + css::uno::Reference SAL_CALL getDocument() override + { + if (m_xDocument.is()) + return m_xDocument; + else + { + css::uno::Reference xDocument(getDesktop()->getCurrentComponent(), + css::uno::UNO_QUERY); + return xDocument; + } + } + + css::uno::Reference + SAL_CALL getInvocationContext() override + { + return m_xInvocation; + } + + css::uno::Reference SAL_CALL getDesktop() override + { + return css::frame::theDesktop::get(m_xContext); + } + + css::uno::Reference SAL_CALL getComponentContext() override + { + return m_xContext; + } + +private: + css::uno::Reference m_xContext; + css::uno::Reference m_xDocument; + css::uno::Reference m_xInvocation; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/jsprov/jsprov.component b/scripting/source/jsprov/jsprov.component new file mode 100644 index 000000000000..893b5cf55e31 --- /dev/null +++ b/scripting/source/jsprov/jsprov.component @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/scripting/source/jsprov/loader.cxx b/scripting/source/jsprov/loader.cxx new file mode 100644 index 000000000000..0336ec91307f --- /dev/null +++ b/scripting/source/jsprov/loader.cxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include + +#include +#include +#include + +namespace +{ +class ScriptWrapper : public cppu::WeakImplHelper +{ +public: + ScriptWrapper(const css::uno::Reference& xContext, + const OUString& sScript) + : m_xScriptContext(new sf_misc::ScriptContext(xContext)) + , m_sScript(sScript) + { + } + + // XScript + css::uno::Any SAL_CALL invoke(const css::uno::Sequence& aParams, + css::uno::Sequence& aOutParamIndex, + css::uno::Sequence& aOutParam) override; + +private: + css::uno::Reference m_xScriptContext; + OUString m_sScript; +}; + +class JsProvScriptFactory : public singleprovider::SingleScriptFactory +{ + OUString getLanguageName() const override; + OUString getExtension() const override; + css::uno::Reference + getScript(css::uno::Reference xContext, const OUString& sName, + std::string_view sSource) const override; + bool appMightExecute(const OUString& sAppName) const override; + OUString getExampleMacro() const override; +}; + +OUString JsProvScriptFactory::getLanguageName() const { return "JavaScript"; } + +OUString JsProvScriptFactory::getExtension() const { return ".js"; } + +css::uno::Reference +JsProvScriptFactory::getScript(css::uno::Reference xContext, + const OUString&, std::string_view sSource) const +{ + return new ScriptWrapper(xContext, OStringToOUString(sSource, RTL_TEXTENCODING_UTF8)); +} + +bool JsProvScriptFactory::appMightExecute(const OUString& sAppName) const +{ + return sAppName.startsWithIgnoreAsciiCase("js.") || sAppName.startsWithIgnoreAsciiCase("node."); +} + +OUString JsProvScriptFactory::getExampleMacro() const +{ + return u"let text = XSCRIPTCONTEXT.getDocument().getText();\n" + "\n" + "text.getEnd().setString(\"Hello, world!\");\n"_ustr; +} + +css::uno::Any SAL_CALL ScriptWrapper::invoke(const css::uno::Sequence&, + css::uno::Sequence&, + css::uno::Sequence&) +{ + std::pair> aGlobalVariables[] = { + { "XSCRIPTCONTEXT", m_xScriptContext }, + }; + + jsuno::execute(m_sScript, aGlobalVariables); + + return css::uno::Any(); +} +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +scripting_JavaScriptProviderImpl_get_implementation(css::uno::XComponentContext* pContext, + css::uno::Sequence const&) +{ + css::uno::Reference xProvider + = singleprovider::ScriptProvider::create(pContext, std::make_shared()); + xProvider->acquire(); + return xProvider.get(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/protocolhandler/scripthandler.cxx b/scripting/source/protocolhandler/scripthandler.cxx index becf01a89ca6..78f271a2cc2a 100644 --- a/scripting/source/protocolhandler/scripthandler.cxx +++ b/scripting/source/protocolhandler/scripthandler.cxx @@ -84,6 +84,71 @@ void SAL_CALL ScriptProtocolHandler::initialize( m_bInitialised = true; } +namespace +{ +Sequence lcl_filterAndOrderScriptArgs(const Sequence& rArgs) +{ + // Copy the Sequence to a local array so we can modify the order + Sequence aArgs = rArgs; + sal_Int32 nSize = aArgs.getLength(); + PropertyValue* pArgs = aArgs.getArray(); + + // For some reason the script gets passed only the values from the PropertyValue array and not + // the names so the only way for it to distinguish them is by the order. That means this order + // is set in stone. See tdf#173160. + static const std::array aPropertyOrder = { + u"URL"_ustr, u"InteractionHandler"_ustr, u"OpenNewView"_ustr, + u"FrameName"_ustr, u"MacroExecutionMode"_ustr, u"UpdateDocMode"_ustr, + }; + sal_Int32 nUsedArgs = 0; + + // Reorder the property values according to the preset order + for (const auto& sPropertyName : aPropertyOrder) + { + for (sal_Int32 i = nUsedArgs; i < nSize; ++i) + { + if (sPropertyName == pArgs[i].Name) + { + // Swap this property with the one in the place we want it to be + if (i != nUsedArgs) + std::swap(pArgs[i], pArgs[nUsedArgs]); + ++nUsedArgs; + break; + } + } + } + + // Sometimes we get a propertyval with name = "Referer" or "SynchronMode". These are not actual + // arguments to be passed to script, but flags describing the call, so ignore. Who thought that + // passing such "meta-arguments" mixed in with real arguments was a good idea? + while (nUsedArgs < nSize) + { + if (pArgs[nUsedArgs].Name == "Referer" || pArgs[nUsedArgs].Name == "SynchronMode") + { + // Move the last argument over the place of this one and then decrease the number of + // arguments that we’ll use so that the moved one will get ignored + if (nUsedArgs + 1 < nSize) + pArgs[nUsedArgs] = std::move(pArgs[nSize - 1]); + --nSize; + } + else + { + // Otherwise keep the argument + ++nUsedArgs; + } + } + + Sequence aValues(nUsedArgs); + Any* pValues = aValues.getArray(); + + // Move only the values into the final array + for (sal_Int32 i = 0; i < nUsedArgs; ++i) + pValues[i] = std::move(pArgs[i].Value); + + return aValues; +} +} // namespace + Reference< XDispatch > SAL_CALL ScriptProtocolHandler::queryDispatch( const URL& aURL, const OUString&, sal_Int32 ) { @@ -178,29 +243,10 @@ void SAL_CALL ScriptProtocolHandler::dispatchWithNotification( "ScriptProtocolHandler::dispatchWithNotification: validate xFunc - unable to obtain XScript interface" ); - Sequence< Any > inArgs; + Sequence< Any > inArgs = lcl_filterAndOrderScriptArgs(lArgs); Sequence< Any > outArgs; Sequence< sal_Int16 > outIndex; - if ( lArgs.hasElements() ) - { - int argCount = 0; - for ( const auto& rArg : lArgs ) - { - // Sometimes we get a propertyval with name = "Referer" or "SynchronMode". These - // are not actual arguments to be passed to script, but flags describing the - // call, so ignore. Who thought that passing such "meta-arguments" mixed in with - // real arguments was a good idea? - if ( (rArg.Name != "Referer" && - rArg.Name != "SynchronMode") || - rArg.Name.isEmpty() ) //TODO:??? - { - inArgs.realloc( ++argCount ); - inArgs.getArray()[ argCount - 1 ] = rArg.Value; - } - } - } - // attempt to protect the document against the script tampering with its Undo Context std::unique_ptr< ::framework::DocumentUndoGuard > pUndoGuard; if ( bIsDocumentScript ) diff --git a/scripting/source/provider/BrowseNodeFactoryImpl.cxx b/scripting/source/provider/BrowseNodeFactoryImpl.cxx index 5a975722f17e..2dfbf8e02488 100644 --- a/scripting/source/provider/BrowseNodeFactoryImpl.cxx +++ b/scripting/source/provider/BrowseNodeFactoryImpl.cxx @@ -320,157 +320,6 @@ typedef ::std::vector< Reference< browse::XBrowseNode > > vXBrowseNodes; namespace { -struct alphaSortForBNodes -{ - bool operator()( const Reference< browse::XBrowseNode >& a, const Reference< browse::XBrowseNode >& b ) - { - return a->getName().compareTo( b->getName() ) < 0; - } -}; - -} - -typedef ::cppu::WeakImplHelper< browse::XBrowseNode > t_BrowseNodeBase; - -namespace { - -class DefaultBrowseNode : - public t_BrowseNodeBase -{ - -private: - Reference< browse::XBrowseNode > m_xWrappedBrowseNode; - Reference< lang::XTypeProvider > m_xWrappedTypeProv; - Reference< XAggregation > m_xAggProxy; - Reference< XComponentContext > m_xCtx; - -public: - DefaultBrowseNode( const Reference< XComponentContext >& xCtx, const Reference< browse::XBrowseNode>& xNode ) : m_xWrappedBrowseNode( xNode ), m_xWrappedTypeProv( xNode, UNO_QUERY ), m_xCtx( xCtx ) - { - OSL_ENSURE( m_xWrappedBrowseNode.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" ); - OSL_ENSURE( m_xWrappedTypeProv.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" ); - OSL_ENSURE( m_xCtx.is(), "DefaultBrowseNode::DefaultBrowseNode(): No ComponentContext" ); - // Use proxy factory service to create aggregatable proxy. - try - { - Reference< reflection::XProxyFactory > xProxyFac = - reflection::ProxyFactory::create( m_xCtx ); - m_xAggProxy = xProxyFac->createProxy( m_xWrappedBrowseNode ); - } - catch( uno::Exception& ) - { - TOOLS_WARN_EXCEPTION( "scripting", "DefaultBrowseNode::DefaultBrowseNode" ); - } - OSL_ENSURE( m_xAggProxy.is(), - "DefaultBrowseNode::DefaultBrowseNode: Wrapped BrowseNode cannot be aggregated!" ); - - if ( !m_xAggProxy.is() ) - return; - - osl_atomic_increment( &m_refCount ); - - /* i35609 - Fix crash on Solaris. The setDelegator call needs - to be in its own block to ensure that all temporary Reference - instances that are acquired during the call are released - before m_refCount is decremented again */ - { - m_xAggProxy->setDelegator( - getXWeak() ); - } - - osl_atomic_decrement( &m_refCount ); - } - - virtual ~DefaultBrowseNode() override - { - if ( m_xAggProxy.is() ) - { - m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() ); - } - } - - virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL - getChildNodes() override - { - if ( hasChildNodes() ) - { - vXBrowseNodes aVNodes; - const Sequence < Reference< browse::XBrowseNode > > nodes = - m_xWrappedBrowseNode->getChildNodes(); - for ( const Reference< browse::XBrowseNode >& xBrowseNode : nodes ) - { - OSL_ENSURE( xBrowseNode.is(), "DefaultBrowseNode::getChildNodes(): Invalid BrowseNode" ); - if( xBrowseNode.is() ) - aVNodes.push_back( new DefaultBrowseNode( m_xCtx, xBrowseNode ) ); - } - - ::std::sort( aVNodes.begin(), aVNodes.end(), alphaSortForBNodes() ); - Sequence < Reference< browse::XBrowseNode > > children( aVNodes.size() ); - auto childrenRange = asNonConstRange(children); - sal_Int32 i = 0; - for ( const auto& rxNode : aVNodes ) - { - childrenRange[ i ].set( rxNode ); - i++; - } - return children; - } - else - { - // no nodes - - Sequence < Reference< browse::XBrowseNode > > none; - return none; - } - } - - virtual sal_Int16 SAL_CALL getType() override - { - return m_xWrappedBrowseNode->getType(); - } - - virtual OUString - SAL_CALL getName() override - { - return m_xWrappedBrowseNode->getName(); - } - - virtual sal_Bool SAL_CALL - hasChildNodes() override - { - return m_xWrappedBrowseNode->hasChildNodes(); - } - - // XInterface - virtual Any SAL_CALL queryInterface( const Type& aType ) override - { - Any aRet = t_BrowseNodeBase::queryInterface( aType ); - if ( aRet.hasValue() ) - { - return aRet; - } - if ( m_xAggProxy.is() ) - { - return m_xAggProxy->queryAggregation( aType ); - } - else - { - return Any(); - } - } - - // XTypeProvider (implemented by base, but needs to be overridden for - // delegating to aggregate) - virtual Sequence< Type > SAL_CALL getTypes() override - { - return m_xWrappedTypeProv->getTypes(); - } - virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override - { - return css::uno::Sequence(); - } -}; - class DefaultRootBrowseNode : public ::cppu::WeakImplHelper< browse::XBrowseNode > { @@ -487,7 +336,7 @@ public: for (Reference< browse::XBrowseNode > & xNode : nodes) { - m_vNodes.push_back( new DefaultBrowseNode( xCtx, xNode ) ); + m_vNodes.emplace_back(xNode); } m_Name = "Root"; } diff --git a/scripting/source/provider/MasterScriptProvider.cxx b/scripting/source/provider/MasterScriptProvider.cxx index f033a9dbe317..f87373153f0c 100644 --- a/scripting/source/provider/MasterScriptProvider.cxx +++ b/scripting/source/provider/MasterScriptProvider.cxx @@ -255,7 +255,7 @@ MasterScriptProvider::getScript( const OUString& scriptURI ) OUString language = sfUri->getParameter( langKey ); OUString location = sfUri->getParameter( locKey ); - // if script us located in uno pkg + // if script is located in uno pkg sal_Int32 index = -1; OUString pkgTag(u":uno_packages"_ustr); // for languages other than basic, scripts located in uno packages @@ -279,7 +279,7 @@ MasterScriptProvider::getScript( const OUString& scriptURI ) Reference< provider::XScript > xScript; // If the script location is in the same location context as this - // MSP then delete to the language provider controlled by this MSP + // MSP then delegate to the language provider controlled by this MSP // ** Special case is BASIC, all calls to getScript will be handled // by the language script provider in the current location context // even if it's different @@ -509,7 +509,7 @@ MasterScriptProvider::insertByName( const OUString& aName, const Any& aElement ) Reference < XInterface > (), 1 ); } // TODO for library package parse the language, for the moment will try - // to get each provider to process the new Package, the first one the succeeds + // to get each provider to process the new Package, the first one that succeeds // will terminate processing const bool bSuccess = FindProviderAndApply( *providerCache(), [&aName, &aElement](Reference& xCont) { diff --git a/scripting/source/provider/MasterScriptProvider.hxx b/scripting/source/provider/MasterScriptProvider.hxx index 0e6c40f5f0a6..93442c2381af 100644 --- a/scripting/source/provider/MasterScriptProvider.hxx +++ b/scripting/source/provider/MasterScriptProvider.hxx @@ -117,7 +117,7 @@ private: // in case of createInstanceWithArgumentsXXX() called m_bIsValid is set to reset // and then set to true when initialisation is complete bool m_bIsValid; - // m_bInitialised ensure initialisation only takes place once. + // m_bInitialised ensures initialisation only takes place once. bool m_bInitialised; bool m_bIsPkgMSP; css::uno::Reference< css::script::provider::XScriptProvider > m_xMSPPkg; diff --git a/scripting/source/provider/URIHelper.cxx b/scripting/source/provider/URIHelper.cxx index f1ed31f47f02..90971103323c 100644 --- a/scripting/source/provider/URIHelper.cxx +++ b/scripting/source/provider/URIHelper.cxx @@ -145,8 +145,7 @@ ScriptingFrameworkURIHelper::initBaseURI() m_xSimpleFileAccess->getFolderContents( uri, true ); auto pChild = std::find_if(children.begin(), children.end(), [&test](const OUString& child) { - sal_Int32 idx = child.lastIndexOf(test); - return idx != -1 && (idx + test.getLength()) == child.getLength(); + return child.endsWith(test); }); if (pChild != children.end()) { diff --git a/scripting/source/pyprov/msgbox.py b/scripting/source/pyprov/msgbox.py index 5e9436fff82b..4ddcfda51bc1 100644 --- a/scripting/source/pyprov/msgbox.py +++ b/scripting/source/pyprov/msgbox.py @@ -39,7 +39,7 @@ class MsgBox(unohelper.Base): self.ButtonSize = 50 self.boxSize = 200 self.lineHeight = 10 - self.fromBroxSize = False + self.fromBoxSize = False self.numberOfLines = -1 self.Buttons = [] @@ -62,7 +62,7 @@ class MsgBox(unohelper.Base): numberOfButtons = len(self.Buttons) self.ButtonSpace = self.ButtonSize/2 - if self.fromBroxSize: + if self.fromBoxSize: # button size is calculated from boxsize size = (2 * self.boxSize) / (3 * numberOfButtons + 1) self.ButtonSize = size @@ -180,12 +180,12 @@ class MsgBox(unohelper.Base): def renderFromBoxSize(self, size = 150): self.boxSize = size - self.fromBroxSize = True + self.fromBoxSize = True return def renderFromButtonSize(self, size = 50): self.ButtonSize = size - self.fromBroxSize = False + self.fromBoxSize = False return class ButtonListener(unohelper.Base, XActionListener): @@ -220,14 +220,14 @@ if __name__ == '__main__': myBox.addButton("No") myBox.addButton("May be") myBox.renderFromBoxSize(150) - myBox.numberOflines = 2 + myBox.numberOfLines = 2 print(myBox.show("A very long message A very long message A very long message A very long message A very long message A very long message A very long message A very long message A very long message A very long message " + chr(10)+chr(10)+"Do you agree ?",0,"Dialog title")) myBox = MsgBox(ctx) myBox.addButton("oK") myBox.renderFromButtonSize() - myBox.numberOflines = 2 + myBox.numberOfLines = 2 print(myBox.show("A small message",0,"Dialog title")) diff --git a/scripting/source/pyprov/pythonscript.py b/scripting/source/pyprov/pythonscript.py index 7eceaf908cbd..f86d87ac7ac7 100644 --- a/scripting/source/pyprov/pythonscript.py +++ b/scripting/source/pyprov/pythonscript.py @@ -39,11 +39,11 @@ from com.sun.star.beans import XPropertySet, Property from com.sun.star.container import XNameContainer from com.sun.star.xml.sax import XDocumentHandler, InputSource from com.sun.star.uno import Exception as UnoException -from com.sun.star.script import XInvocation from com.sun.star.awt import XActionListener from com.sun.star.script.provider import XScriptProvider, XScript, ScriptFrameworkErrorException -from com.sun.star.script.browse import XBrowseNode +from com.sun.star.script.browse import XBrowseNode, XCreatableBrowseNode, XCopyableBrowseNode +from com.sun.star.script.browse import XEditableBrowseNode from com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER from com.sun.star.system import SystemShellExecuteFlags @@ -199,13 +199,13 @@ def windowsDefaultAppMightExecute(): # First get the length of the string if assocQueryString(flags, assocStr, ".py", None, None, ctypes.byref(length)) != 1: # S_FALSE - log.debug("AsscQueryStringW failed") + log.debug("AssocQueryStringW failed") return True exeBuf = ctypes.create_unicode_buffer(length.value) if assocQueryString(flags, assocStr, ".py", None, exeBuf, ctypes.byref(length)) != 0: # S_OK - log.debug("AsscQueryStringW failed") + log.debug("AssocQueryStringW failed") return True if length.value < 2: @@ -585,7 +585,7 @@ def isScript(candidate): # ------------------------------------------------------- # A mixin class for nodes that have a uri property so that an editor can be used on it -class EditableNode(XInvocation, XActionListener): +class EditableNode(XActionListener, XEditableBrowseNode): def _edit_with_dialog(self): servicename = "com.sun.star.awt.DialogProvider" ctx = self.provCtx.scriptContext.getComponentContext() @@ -606,14 +606,13 @@ class EditableNode(XInvocation, XActionListener): self.editor.execute() - def invoke(self, name, params, outparamindex, outparams): - if name == "Editable": - if ENABLE_EDIT_DIALOG: - self._edit_with_dialog() - else: - openExternalEditor(self.provCtx.scriptContext.getComponentContext(), self.uri) + def editNode(self): + if ENABLE_EDIT_DIALOG: + self._edit_with_dialog() + else: + openExternalEditor(self.provCtx.scriptContext.getComponentContext(), self.uri) - return None + return True def setValue(self, name, value): return None @@ -630,7 +629,7 @@ class EditableNode(XInvocation, XActionListener): def getIntrospection(self): return None - def isEditable(self): + def isEditableNode(self): if self.provCtx.sfa.isReadOnly(self.uri): return False if urllib.parse.urlsplit(self.uri).scheme != 'file': @@ -700,8 +699,6 @@ class ScriptBrowseNode(unohelper.Base, XBrowseNode, XPropertySet, EditableNode): ret = self.provCtx.uriHelper.getScriptURI( self.provCtx.getPersistentUrlFromStorageUrl(self.uri + "$" + self.funcName) ) - elif name == "Editable": - ret = self.isEditable() log.debug("ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret)) except Exception: @@ -719,7 +716,7 @@ class ScriptBrowseNode(unohelper.Base, XBrowseNode, XPropertySet, EditableNode): # ------------------------------------------------------- -class FileBrowseNode(unohelper.Base, XBrowseNode, EditableNode, XPropertySet): +class FileBrowseNode(unohelper.Base, XBrowseNode, XCopyableBrowseNode, EditableNode): def __init__(self, provCtx, uri, name): self.provCtx = provCtx self.uri = uri @@ -754,24 +751,38 @@ class FileBrowseNode(unohelper.Base, XBrowseNode, EditableNode, XPropertySet): def getType(self): return CONTAINER - def getPropertyValue(self, name): - ret = None - if name == "Editable": - ret = self.isEditable() + def isCopyableNode(self): + return True - log.debug("FileBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret)) + def getCopyDestinationUrl(self, xDest): + if isinstance(xDest, PythonScriptProvider): + xDest = xDest.dirBrowseNode + if not isinstance(xDest, DirBrowseNode): + return None - return ret + # Don’t allow copying into the same directory + if xDest.rootUrl == self.uri[0:self.uri.rfind('/')]: + return None - def setPropertyValue(self, name, value): - log.debug("FileBrowseNode.setPropertyValue called " + name + "=" + str(value)) + return xDest.rootUrl - def getPropertySetInfo(self): - log.debug("FileBrowseNode.getPropertySetInfo called ") - return None + def nodeCanBeCopiedTo(self, parentNode): + return self.getCopyDestinationUrl(parentNode) != None + + def copyNode(self, parentNode): + dest_dir_url = self.getCopyDestinationUrl(parentNode) + if dest_dir_url is None: + raise IllegalArgumentException("Invalid parent node passed to copyNode", self, 0) + + self.provCtx.sfa.createFolder(dest_dir_url) + + target_url = f"{dest_dir_url}/{self.uri[self.uri.rfind('/') + 1:]}" + self.provCtx.sfa.copy(self.uri, target_url) + + return FileBrowseNode(self.provCtx, target_url, self.name) -class DirBrowseNode(unohelper.Base, XBrowseNode, XPropertySet, XInvocation): +class DirBrowseNode(unohelper.Base, XBrowseNode, XCreatableBrowseNode): def __init__(self, provCtx, name, rootUrl): self.provCtx = provCtx self.name = name @@ -810,66 +821,30 @@ class DirBrowseNode(unohelper.Base, XBrowseNode, XPropertySet, XInvocation): log.debug("DirBrowseNode getScript " + uri + " invoked") raise IllegalArgumentException("DirBrowseNode couldn't instantiate script " + uri, self, 0) - def getPropertyValue(self, name): - ret = None - try: - if name == "Creatable": - ret = urllib.parse.urlsplit(self.rootUrl).scheme == 'file' + def isCreatableNode(self): + return urllib.parse.urlsplit(self.rootUrl).scheme == 'file' - log.debug(f"DirBrowseNode.getPropertyValue called for {name} returning {str(ret)}") - except Exception: - log.error(f"DirBrowseNode.getPropertyValue error {lastException2String()}") + def createNode(self, scriptName): + uri = f"{self.rootUrl}/{scriptName}.py" + + # Create the file with an example macro + try: + filePath = uno.fileUrlToSystemPath(uri) + + os.makedirs(os.path.dirname(filePath), exist_ok=True) + + with open(filePath, "x", encoding="utf-8") as f: + f.write(EXAMPLE_MACRO) + + except OSError as e: + log.error(f"DirBrowseNode Creatable error {e}") raise - return ret + except Exception: + log.error(f"DirBrowseNode Creatable error {lastException2String()}") + raise - def setPropertyValue(self, name, value): - log.debug(f"DirBrowseNode.setPropertyValue called {name}={str(value)}") - - def getPropertySetInfo(self): - log.debug("DirBrowseNode.getPropertySetInfo called ") - return None - - def invoke(self, name, params, outparamindex, outparams): - if name == "Creatable": - scriptName = params[0] - uri = f"{self.rootUrl}/{scriptName}.py" - - # Create the file with an example macro - try: - filePath = uno.fileUrlToSystemPath(uri) - - os.makedirs(os.path.dirname(filePath), exist_ok=True) - - with open(filePath, "x", encoding="utf-8") as f: - f.write(EXAMPLE_MACRO) - - except OSError as e: - log.error(f"DirBrowseNode Creatable error {e}") - raise - - except Exception: - log.error(f"DirBrowseNode Creatable error {lastException2String()}") - raise - - return (FileBrowseNode(self.provCtx, uri, scriptName), [], []) - - return None - - def setValue(self, name, value): - return None - - def getValue(self, name): - return None - - def hasMethod(self, name): - return False - - def hasProperty(self, name): - return False - - def getIntrospection(self): - return None + return FileBrowseNode(self.provCtx, uri, scriptName) class ManifestHandler(XDocumentHandler, unohelper.Base): @@ -960,7 +935,7 @@ class DummyProgressHandler(unohelper.Base, XProgressHandler): log.debug("pythonscript: DummyProgressHandler.update " + str(status)) def pop(self, event): - log.debug("pythonscript: DummyProgressHandler.push " + str(event)) + log.debug("pythonscript: DummyProgressHandler.pop " + str(event)) class CommandEnvironment(unohelper.Base, XCommandEnvironment): @@ -1120,7 +1095,7 @@ class PythonScript(unohelper.Base, XScript): e.Message = e.Message + " (" + complete + ")" raise except Exception: - # General python exception are converted to uno RuntimeException + # General python exceptions are converted to uno RuntimeException text = lastException2String() complete = ( "Error during invoking function " @@ -1150,7 +1125,7 @@ def expandUri(uri): # -------------------------------------------------------------- class PythonScriptProvider(unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer, - XPropertySet, XInvocation): + XPropertySet, XCreatableBrowseNode, XEditableBrowseNode): def __init__(self, ctx, *args): if log.isDebugLevel(): mystr = "" @@ -1237,25 +1212,29 @@ class PythonScriptProvider(unohelper.Base, XBrowseNode, XScriptProvider, XNameCo if hasattr(self.dirBrowseNode, "getPropertySetInfo"): return self.dirBrowseNode.getPropertySetInfo() - def invoke(self, name, params, outparamindex, outparams): - if hasattr(self.dirBrowseNode, "invoke"): - return self.dirBrowseNode.invoke(name, params, outparamindex, outparams) + def isEditableNode(self): + if hasattr(self.dirBrowseNode, "isEditableNode"): + return self.dirBrowseNode.isEditableNode() + else: + return False - def getValue(self, name): - if hasattr(self.dirBrowseNode, "getValue"): - return self.dirBrowseNode.getValue(name) + def editNode(self): + if hasattr(self.dirBrowseNode, "editNode"): + return self.dirBrowseNode.editNode() + else: + return False - def hasMethod(self, name): - if hasattr(self.dirBrowseNode, "hasMethod"): - return self.dirBrowseNode.hasMethod(name) + def isCreatableNode(self): + if hasattr(self.dirBrowseNode, "isCreatableNode"): + return self.dirBrowseNode.isCreatableNode() + else: + return False - def hasProperty(self, name): - if hasattr(self.dirBrowseNode, "hasProperty"): - return self.dirBrowseNode.hasProperty(name) - - def getIntrospection(self): - if hasattr(self.dirBrowseNode, "getIntrospection"): - return self.dirBrowseNode.getIntrospection() + def createNode(self, name): + if hasattr(self.dirBrowseNode, "createNode"): + return self.dirBrowseNode.createNode(name) + else: + return None # retrieve function args in parenthesis def getFunctionArguments(self, func_signature): @@ -1339,7 +1318,7 @@ class PythonScriptProvider(unohelper.Base, XBrowseNode, XScriptProvider, XNameCo self.provCtx.removePackageByUrl(uri) else: log.debug("removeByName unknown uri " + str(name) + ", ignoring") - raise NoSuchElementException(uri + "is not in package", self) + raise NoSuchElementException(uri + " is not in package", self) log.debug("removeByName called" + str(uri) + " successful") def insertByName(self, name, value): diff --git a/scripting/source/singleprov/externaledit.cxx b/scripting/source/singleprov/externaledit.cxx new file mode 100644 index 000000000000..dc488c5243e8 --- /dev/null +++ b/scripting/source/singleprov/externaledit.cxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "externaledit.hxx" + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#endif + +#include "provcontext.hxx" + +namespace singleprovider +{ +#ifdef _WIN32 +namespace +{ +bool windowsDefaultAppMightExecute(const std::shared_ptr& pProviderContext) +{ + ASSOCF nFlags = 0; + ASSOCSTR nAssocStr = ASSOCSTR_EXECUTABLE; + DWORD nLength = 0; + + // Include a '\0' to make the string null terminated + OUString sExtension + = pProviderContext->m_pSingleScriptFactory->getExtension() + OUStringChar(u'\0'); + LPCWSTR pExtension = reinterpret_cast(sExtension.getStr()); + + // First get the length of the string + if (AssocQueryStringW(nFlags, nAssocStr, pExtension, nullptr, nullptr, &nLength) != S_FALSE) + return true; + + std::vector aExeBuf(nLength); + + if (AssocQueryStringW(nFlags, nAssocStr, pExtension, nullptr, aExeBuf.data(), &nLength) != S_OK) + return true; + + OUString sExe(reinterpret_cast(aExeBuf.data())); + + sal_Int32 lastSlash = sExe.lastIndexOf(u'\\'); + + if (lastSlash != -1) + sExe = sExe.copy(lastSlash + 1); + + return pProviderContext->m_pSingleScriptFactory->appMightExecute(sExe); +} +} +#endif + +void externalEdit(const std::shared_ptr& pProviderContext, const OUString& sUrl) +{ + css::uno::Reference xSystemShellExecute + = css::system::SystemShellExecute::create(pProviderContext->m_xContext); + +#ifdef _WIN32 + + OUString sPath; + + if (osl::FileBase::getSystemPathFromFileURL(sUrl, sPath) != osl::FileBase::E_None) + return; + + // If it looks like the default windows app might be a Python interpreter then open the file in + // Notepad instead + if (windowsDefaultAppMightExecute(pProviderContext)) + { + xSystemShellExecute->execute("notepad", "\"" + sPath + "\"", + css::system::SystemShellExecuteFlags::DEFAULTS); + } + else + { + OUString sPathWithNull = sPath + OUStringChar(u'\0'); + LPCWSTR pPathWithNull = reinterpret_cast(sPathWithNull.getStr()); + ShellExecuteW(nullptr, L"open", pPathWithNull, nullptr, nullptr, SW_SHOWNORMAL); + } + +#else + + xSystemShellExecute->execute(sUrl, "", css::system::SystemShellExecuteFlags::URIS_ONLY); + +#endif +} + +bool isEditable(const std::shared_ptr& pProviderContext, const OUString& sUrl) +{ + if (pProviderContext->m_xFileAccess->isReadOnly(sUrl)) + return false; + + OUString sPath; + + if (osl::FileBase::getSystemPathFromFileURL(sUrl, sPath) != osl::FileBase::E_None) + return false; + + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/externaledit.hxx b/scripting/source/singleprov/externaledit.hxx new file mode 100644 index 000000000000..015d4a3680d0 --- /dev/null +++ b/scripting/source/singleprov/externaledit.hxx @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace singleprovider +{ +class ProviderContext; + +void externalEdit(const std::shared_ptr& pProviderContext, const OUString& sUrl); + +bool isEditable(const std::shared_ptr& pProviderContext, const OUString& sUrl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/provcontext.cxx b/scripting/source/singleprov/provcontext.cxx new file mode 100644 index 000000000000..ac750804c3d0 --- /dev/null +++ b/scripting/source/singleprov/provcontext.cxx @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "provcontext.hxx" + +#include + +namespace singleprovider +{ +ProviderContext::ProviderContext(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory) + : m_xContext(xContext) + , m_pSingleScriptFactory(pSingleScriptFactory) + , m_xFileAccess(css::ucb::SimpleFileAccess::create(xContext)) +{ +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/provcontext.hxx b/scripting/source/singleprov/provcontext.hxx new file mode 100644 index 000000000000..14d7c7e19e01 --- /dev/null +++ b/scripting/source/singleprov/provcontext.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace com::sun::star::script::provider +{ +class XScriptURIHelper; +} + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +namespace com::sun::star::ucb +{ +class XSimpleFileAccess3; +} + +namespace singleprovider +{ +class SingleScriptFactory; + +class ProviderContext +{ +public: + ProviderContext(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory); + + css::uno::Reference m_xContext; + std::shared_ptr m_pSingleScriptFactory; + css::uno::Reference m_xUriHelper; + css::uno::Reference m_xFileAccess; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptdir.cxx b/scripting/source/singleprov/scriptdir.cxx new file mode 100644 index 000000000000..f0c0dff9e526 --- /dev/null +++ b/scripting/source/singleprov/scriptdir.cxx @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "scriptdir.hxx" + +#include +#include +#include +#include +#include + +#include + +#include "provcontext.hxx" +#include "scriptfile.hxx" + +namespace singleprovider +{ +ScriptDir::ScriptDir(const std::shared_ptr& pProviderContext) + : m_pProviderContext(pProviderContext) + , m_sName(pProviderContext->m_pSingleScriptFactory->getLanguageName()) + , m_sBaseUri(pProviderContext->m_xUriHelper->getRootStorageURI()) +{ +} + +ScriptDir::ScriptDir(const std::shared_ptr& pProviderContext, + const OUString& sName, const OUString& sBaseUri) + : m_pProviderContext(pProviderContext) + , m_sName(sName) + , m_sBaseUri(sBaseUri) +{ +} + +OUString SAL_CALL ScriptDir::getName() { return m_sName; } + +css::uno::Sequence> + SAL_CALL ScriptDir::getChildNodes() +{ + const css::uno::Reference& xFileAccess + = m_pProviderContext->m_xFileAccess; + + try + { + css::uno::Sequence aChildren = xFileAccess->getFolderContents(m_sBaseUri, true); + + std::vector> aNodes; + aNodes.reserve(aChildren.getLength()); + + OUString sExtension = m_pProviderContext->m_pSingleScriptFactory->getExtension(); + + for (int i = 0, nCount = aChildren.getLength(); i < nCount; ++i) + { + if (xFileAccess->isFolder(aChildren[i])) + { + OUString sName = nameFromUrl(aChildren[i]); + + aNodes.emplace_back(new ScriptDir(m_pProviderContext, sName, aChildren[i])); + } + else if (aChildren[i].endsWith(sExtension)) + { + OUString sName = nameFromUrl(aChildren[i]); + + aNodes.emplace_back(new ScriptFile(m_pProviderContext, sName, aChildren[i])); + } + } + + css::uno::Sequence> aNodesSequence( + aNodes.size()); + css::uno::Reference* pNodesSequence + = aNodesSequence.getArray(); + + for (int i = 0, nCount = aNodes.size(); i < nCount; ++i) + pNodesSequence[i] = std::move(aNodes[i]); + + return aNodesSequence; + } + catch (const css::uno::RuntimeException&) + { + throw; + } + catch (const css::uno::Exception&) + { + return css::uno::Sequence>(); + } +} + +sal_Bool SAL_CALL ScriptDir::hasChildNodes() { return true; } + +sal_Int16 SAL_CALL ScriptDir::getType() { return css::script::browse::BrowseNodeTypes::CONTAINER; } + +sal_Bool SAL_CALL ScriptDir::isCreatableNode() { return true; } + +OUString ScriptDir::nameFromUrl(const OUString& sUrl) +{ + sal_Int32 nSlashPos = sUrl.lastIndexOf('/'); + sal_Int32 nStart = nSlashPos == -1 ? 0 : nSlashPos + 1; + + sal_Int32 nCount = sUrl.getLength() - nStart; + + OUString sExtension = m_pProviderContext->m_pSingleScriptFactory->getExtension(); + + if (sUrl.endsWith(sExtension)) + nCount -= sExtension.getLength(); + + return rtl::Uri::decode(sUrl.copy(nStart, nCount), rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8); +} + +css::uno::Reference + SAL_CALL ScriptDir::createNode(const OUString& sMacroName) +{ + OUString sEncodedFilename = rtl::Uri::encode(sMacroName, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8); + OUString sUrl = m_sBaseUri + OUStringChar(u'/') + sEncodedFilename + + m_pProviderContext->m_pSingleScriptFactory->getExtension(); + + css::uno::Reference xOutput + = m_pProviderContext->m_xFileAccess->openFileWrite(sUrl); + + OUString sSourceCode = m_pProviderContext->m_pSingleScriptFactory->getExampleMacro(); + OString sSourceCodeUtf8 = OUStringToOString(sSourceCode, RTL_TEXTENCODING_UTF8); + css::uno::Sequence sSourceCodeSequence( + reinterpret_cast(sSourceCodeUtf8.getStr()), sSourceCodeUtf8.getLength()); + + xOutput->writeBytes(sSourceCodeSequence); + + xOutput->closeOutput(); + + return new ScriptFile(m_pProviderContext, sMacroName, sUrl); +} + +std::shared_ptr ScriptDir::getScriptFactory() const +{ + return m_pProviderContext->m_pSingleScriptFactory; +} + +std::optional ScriptDir::getDirectoryUri() const +{ + return std::make_optional(m_sBaseUri); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptdir.hxx b/scripting/source/singleprov/scriptdir.hxx new file mode 100644 index 000000000000..0a7cea44a77b --- /dev/null +++ b/scripting/source/singleprov/scriptdir.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include +#include +#include + +namespace singleprovider +{ +class ProviderContext; + +class ScriptDir : public cppu::WeakImplHelper, + public DirectoryNode +{ +public: + ScriptDir(const std::shared_ptr& pProviderContext); + ScriptDir(const std::shared_ptr& pProviderContext, const OUString& sName, + const OUString& sBaseUri); + + // XBrowseNode + OUString SAL_CALL getName() override; + css::uno::Sequence> + SAL_CALL getChildNodes() override; + sal_Bool SAL_CALL hasChildNodes() override; + sal_Int16 SAL_CALL getType() override; + + // XCreatableBrowseNode + sal_Bool SAL_CALL isCreatableNode() override; + css::uno::Reference + SAL_CALL createNode(const OUString& sName) override; + + // DirectoryNode + std::shared_ptr getScriptFactory() const override; + std::optional getDirectoryUri() const override; + +private: + OUString nameFromUrl(const OUString& sUrl); + + std::shared_ptr m_pProviderContext; + + OUString m_sName; + OUString m_sBaseUri; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptfile.cxx b/scripting/source/singleprov/scriptfile.cxx new file mode 100644 index 000000000000..42ec06978740 --- /dev/null +++ b/scripting/source/singleprov/scriptfile.cxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "scriptfile.hxx" + +#include +#include + +#include +#include + +#include "externaledit.hxx" +#include "provcontext.hxx" +#include "scriptmacro.hxx" + +namespace singleprovider +{ +ScriptFile::ScriptFile(const std::shared_ptr& pProviderContext, + const OUString& sName, const OUString& sBaseUri) + : m_pProviderContext(pProviderContext) + , m_sName(sName) + , m_sBaseUri(sBaseUri) +{ +} + +OUString SAL_CALL ScriptFile::getName() { return m_sName; } + +css::uno::Sequence> + SAL_CALL ScriptFile::getChildNodes() +{ + // Each file is treated as a container with a single macro inside it + css::uno::Sequence> aChild(1); + + aChild.getArray()[0].set(new ScriptMacro(m_pProviderContext, m_sName, m_sBaseUri)); + + return aChild; +} + +sal_Bool SAL_CALL ScriptFile::hasChildNodes() { return true; } + +sal_Int16 SAL_CALL ScriptFile::getType() { return css::script::browse::BrowseNodeTypes::CONTAINER; } + +sal_Bool SAL_CALL ScriptFile::isCopyableNode() { return true; } + +std::optional ScriptFile::getCopyDestinationUri( + const css::uno::Reference& xDest) const +{ + const DirectoryNode* pDirectoryNode = dynamic_cast(xDest.get()); + + if (!pDirectoryNode) + return std::nullopt; + + // Don’t allow copying into providers for other languages + if (pDirectoryNode->getScriptFactory()->getLanguageName() + != m_pProviderContext->m_pSingleScriptFactory->getLanguageName()) + { + return std::nullopt; + } + + std::optional sDirectoryUri = pDirectoryNode->getDirectoryUri(); + + // Don’t allow copying into the same directory + if (sDirectoryUri) + { + sal_Int32 nDirEnd = m_sBaseUri.lastIndexOf(u'/'); + + if (sDirectoryUri.value() == (nDirEnd == -1 ? m_sBaseUri : m_sBaseUri.copy(0, nDirEnd))) + return std::nullopt; + } + + return sDirectoryUri; +} + +sal_Bool SAL_CALL ScriptFile::nodeCanBeCopiedTo( + const css::uno::Reference& xParentNode) +{ + return getCopyDestinationUri(xParentNode).has_value(); +} + +css::uno::Reference SAL_CALL +ScriptFile::copyNode(const css::uno::Reference& xParentNode) +{ + std::optional sDirectoryUri = getCopyDestinationUri(xParentNode); + + if (!sDirectoryUri) + { + throw css::lang::IllegalArgumentException(u"Invalid parent node passed to copyNode"_ustr, + getXWeak(), 0); + } + + const css::uno::Reference& xFileAccess + = m_pProviderContext->m_xFileAccess; + + xFileAccess->createFolder(sDirectoryUri.value()); + + std::u16string_view sBaseName = m_sBaseUri.subView(m_sBaseUri.lastIndexOf(u'/') + 1); + OUString sTargetUri = sDirectoryUri.value() + OUStringChar('/') + sBaseName; + + xFileAccess->copy(m_sBaseUri, sTargetUri); + + return new ScriptFile(m_pProviderContext, m_sName, sTargetUri); +} + +sal_Bool SAL_CALL ScriptFile::isEditableNode() +{ + return isEditable(m_pProviderContext, m_sBaseUri); +} + +sal_Bool SAL_CALL ScriptFile::editNode() +{ + externalEdit(m_pProviderContext, m_sBaseUri); + return true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptfile.hxx b/scripting/source/singleprov/scriptfile.hxx new file mode 100644 index 000000000000..6a280dc587a9 --- /dev/null +++ b/scripting/source/singleprov/scriptfile.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace singleprovider +{ +class ProviderContext; + +class ScriptFile : public cppu::WeakImplHelper +{ +public: + ScriptFile(const std::shared_ptr& pProviderContext, const OUString& sName, + const OUString& sBaseUri); + + // XBrowseNode + OUString SAL_CALL getName() override; + css::uno::Sequence> + SAL_CALL getChildNodes() override; + sal_Bool SAL_CALL hasChildNodes() override; + sal_Int16 SAL_CALL getType() override; + + // XCopyableBrowseNode + sal_Bool SAL_CALL isCopyableNode() override; + sal_Bool SAL_CALL nodeCanBeCopiedTo( + const css::uno::Reference& xParentNode) override; + css::uno::Reference SAL_CALL + copyNode(const css::uno::Reference& xParentNode) override; + + // XEditableBrowseNode + sal_Bool SAL_CALL isEditableNode() override; + sal_Bool SAL_CALL editNode() override; + +private: + std::shared_ptr m_pProviderContext; + + OUString m_sName; + OUString m_sBaseUri; + + std::optional + getCopyDestinationUri(const css::uno::Reference& xDest) const; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptmacro.cxx b/scripting/source/singleprov/scriptmacro.cxx new file mode 100644 index 000000000000..06a2c74f9033 --- /dev/null +++ b/scripting/source/singleprov/scriptmacro.cxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "scriptmacro.hxx" + +#include +#include +#include + +#include "externaledit.hxx" +#include "provcontext.hxx" + +namespace singleprovider +{ +ScriptMacro::ScriptMacro(const std::shared_ptr& pProviderContext, + const OUString& sName, const OUString& sBaseUri) + : m_pProviderContext(pProviderContext) + , m_sName(sName) + , m_sBaseUri(sBaseUri) +{ +} + +OUString SAL_CALL ScriptMacro::getName() { return m_sName; } + +css::uno::Sequence> + SAL_CALL ScriptMacro::getChildNodes() +{ + return css::uno::Sequence>(); +} + +sal_Bool SAL_CALL ScriptMacro::hasChildNodes() { return false; } + +sal_Int16 SAL_CALL ScriptMacro::getType() { return css::script::browse::BrowseNodeTypes::SCRIPT; } + +sal_Bool SAL_CALL ScriptMacro::isEditableNode() +{ + return isEditable(m_pProviderContext, m_sBaseUri); +} + +sal_Bool SAL_CALL ScriptMacro::editNode() +{ + externalEdit(m_pProviderContext, m_sBaseUri); + return true; +} + +css::uno::Reference SAL_CALL ScriptMacro::getPropertySetInfo() +{ + return this; +} + +void SAL_CALL ScriptMacro::setPropertyValue(const OUString&, const css::uno::Any&) {} + +css::uno::Any SAL_CALL ScriptMacro::getPropertyValue(const OUString& sPropertyName) +{ + css::uno::Any xRet; + + if (sPropertyName == "URI") + xRet <<= m_pProviderContext->m_xUriHelper->getScriptURI(m_sBaseUri); + else + { + throw css::beans::UnknownPropertyException("Tried to get unknown property " + + sPropertyName); + } + + return xRet; +} + +void SAL_CALL ScriptMacro::addPropertyChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptMacro::removePropertyChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptMacro::addVetoableChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptMacro::removeVetoableChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +css::uno::Sequence SAL_CALL ScriptMacro::getProperties() +{ + css::uno::Sequence aProperties(1); + aProperties.getArray()[0] = getUriProperty(); + return aProperties; +} + +css::beans::Property SAL_CALL ScriptMacro::getPropertyByName(const OUString& sName) +{ + if (sName == "URI") + return getUriProperty(); + else + throw css::beans::UnknownPropertyException("Tried to retrieve unknown property " + sName); +} + +sal_Bool SAL_CALL ScriptMacro::hasPropertyByName(const OUString& sName) { return sName == "URI"; } + +css::beans::Property ScriptMacro::getUriProperty() +{ + return css::beans::Property("URI", 0, cppu::UnoType::get(), 0); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptmacro.hxx b/scripting/source/singleprov/scriptmacro.hxx new file mode 100644 index 000000000000..6ed6c1b39ee4 --- /dev/null +++ b/scripting/source/singleprov/scriptmacro.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace singleprovider +{ +class ProviderContext; + +class ScriptMacro + : public cppu::WeakImplHelper +{ +public: + ScriptMacro(const std::shared_ptr& pProviderContext, const OUString& sName, + const OUString& sUri); + + // XBrowseNode + OUString SAL_CALL getName() override; + css::uno::Sequence> + SAL_CALL getChildNodes() override; + sal_Bool SAL_CALL hasChildNodes() override; + sal_Int16 SAL_CALL getType() override; + + // XEditableBrowseNode + sal_Bool SAL_CALL isEditableNode() override; + sal_Bool SAL_CALL editNode() override; + + // XPropertySet + css::uno::Reference SAL_CALL getPropertySetInfo() override; + void SAL_CALL setPropertyValue(const OUString& aPropertyName, + const css::uno::Any& aValue) override; + css::uno::Any SAL_CALL getPropertyValue(const OUString& sPropertyName) override; + void SAL_CALL addPropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& xListener) override; + void SAL_CALL removePropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& aListener) override; + void SAL_CALL addVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + void SAL_CALL removeVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + + // XPropertySetInfo + css::uno::Sequence SAL_CALL getProperties() override; + css::beans::Property SAL_CALL getPropertyByName(const OUString& sName) override; + sal_Bool SAL_CALL hasPropertyByName(const OUString& sName) override; + +private: + static css::beans::Property getUriProperty(); + + std::shared_ptr m_pProviderContext; + + OUString m_sName; + OUString m_sBaseUri; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptprovider.cxx b/scripting/source/singleprov/scriptprovider.cxx new file mode 100644 index 000000000000..1cae3d373f34 --- /dev/null +++ b/scripting/source/singleprov/scriptprovider.cxx @@ -0,0 +1,271 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "provcontext.hxx" +#include "scriptdir.hxx" + +namespace singleprovider +{ +ScriptProvider::ScriptProvider(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory) + : m_pProviderContext(std::make_shared(xContext, pSingleScriptFactory)) +{ +} + +void SAL_CALL ScriptProvider::initialize(const css::uno::Sequence& aArguments) +{ + if (aArguments.getLength() > 0) + { + OUString sLocation; + if (aArguments[0] >>= sLocation) + setLocation(sLocation); + } +} + +void ScriptProvider::setLocation(const OUString& sLocation) +{ + OUString sLanguageName = m_pProviderContext->m_pSingleScriptFactory->getLanguageName(); + + m_pProviderContext->m_xUriHelper = css::script::provider::ScriptURIHelper::create( + m_pProviderContext->m_xContext, sLanguageName, sLocation); + m_xRootBrowser + = css::uno::Reference(new ScriptDir(m_pProviderContext)); +} + +OUString SAL_CALL ScriptProvider::getName() +{ + return m_pProviderContext->m_pSingleScriptFactory->getLanguageName(); +} + +css::uno::Sequence> + SAL_CALL ScriptProvider::getChildNodes() +{ + if (m_xRootBrowser.is()) + return m_xRootBrowser->getChildNodes(); + else + return css::uno::Sequence>(); +} + +sal_Bool SAL_CALL ScriptProvider::hasChildNodes() +{ + return m_xRootBrowser.is() && m_xRootBrowser->hasChildNodes(); +} + +sal_Int16 SAL_CALL ScriptProvider::getType() +{ + return m_xRootBrowser.is() ? m_xRootBrowser->getType() : 0; +} + +css::uno::Reference + SAL_CALL ScriptProvider::getScript(const OUString& sScriptUri) +{ + OUString sStorageUri = m_pProviderContext->m_xUriHelper->getStorageURI(sScriptUri); + + sal_Int32 nSlashPos = sStorageUri.lastIndexOf('/'); + OUString sName = sStorageUri.copy(nSlashPos == -1 ? 0 : nSlashPos + 1); + + try + { + std::vector aSource; + constexpr sal_Int32 nBufSize = 1024; + css::uno::Sequence aBuf(nBufSize); + + css::uno::Reference xIn + = m_pProviderContext->m_xFileAccess->openFileRead(sStorageUri); + + while (true) + { + sal_Int32 nBytesRead = xIn->readBytes(aBuf, aBuf.getLength()); + const char* pBuf = reinterpret_cast(aBuf.getConstArray()); + aSource.insert(aSource.end(), pBuf, pBuf + nBytesRead); + + if (nBytesRead < nBufSize) + break; + } + + return m_pProviderContext->m_pSingleScriptFactory->getScript( + m_pProviderContext->m_xContext, sName, + std::string_view(aSource.begin(), aSource.end())); + } + catch (const css::uno::Exception& e) + { + throw css::script::provider::ScriptFrameworkErrorException( + e.Message, static_cast(this), sName, + m_pProviderContext->m_pSingleScriptFactory->getLanguageName(), + css::script::provider::ScriptFrameworkErrorType::UNKNOWN); + } +} + +css::uno::Reference SAL_CALL ScriptProvider::getPropertySetInfo() +{ + css::uno::Reference xPropertySetInfo; + + css::uno::Reference xPropertySet(m_xRootBrowser, css::uno::UNO_QUERY); + + if (xPropertySet.is()) + xPropertySetInfo = xPropertySet->getPropertySetInfo(); + + return xPropertySetInfo; +} + +void SAL_CALL ScriptProvider::setPropertyValue(const OUString&, const css::uno::Any&) {} + +css::uno::Any SAL_CALL ScriptProvider::getPropertyValue(const OUString& sPropertyName) +{ + css::uno::Any xRet; + + css::uno::Reference xPropertySet(m_xRootBrowser, css::uno::UNO_QUERY); + + if (xPropertySet.is()) + xRet = xPropertySet->getPropertyValue(sPropertyName); + + return xRet; +} + +void SAL_CALL ScriptProvider::addPropertyChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptProvider::removePropertyChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptProvider::addVetoableChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptProvider::removeVetoableChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +sal_Bool SAL_CALL ScriptProvider::isCreatableNode() +{ + css::uno::Reference xCreatable(m_xRootBrowser, + css::uno::UNO_QUERY); + + if (xCreatable.is()) + return xCreatable->isCreatableNode(); + else + return false; +} + +css::uno::Reference + SAL_CALL ScriptProvider::createNode(const OUString& sName) +{ + css::uno::Reference xCreatable(m_xRootBrowser, + css::uno::UNO_QUERY); + + if (xCreatable.is()) + return xCreatable->createNode(sName); + else + return css::uno::Reference(); +} + +sal_Bool SAL_CALL ScriptProvider::isEditableNode() +{ + css::uno::Reference xEditable(m_xRootBrowser, + css::uno::UNO_QUERY); + + if (xEditable.is()) + return xEditable->isEditableNode(); + else + return false; +} + +sal_Bool SAL_CALL ScriptProvider::editNode() +{ + css::uno::Reference xEditable(m_xRootBrowser, + css::uno::UNO_QUERY); + + if (xEditable.is()) + return xEditable->editNode(); + else + return false; +} + +std::shared_ptr ScriptProvider::getScriptFactory() const +{ + return m_pProviderContext->m_pSingleScriptFactory; +} + +std::optional ScriptProvider::getDirectoryUri() const +{ + if (const DirectoryNode* pDirectoryNode + = dynamic_cast(m_xRootBrowser.get())) + return pDirectoryNode->getDirectoryUri(); + else + return std::nullopt; +} + +OUString SAL_CALL ScriptProvider::getImplementationName() +{ + return getImplementationNameStatic( + m_pProviderContext->m_pSingleScriptFactory->getLanguageName()); +} + +sal_Bool SAL_CALL ScriptProvider::supportsService(OUString const& serviceName) +{ + const css::uno::Sequence names = getSupportedServiceNames(); + const OUString* pNames = names.getConstArray(); + + for (sal_Int32 i = 0, count = names.getLength(); i < count; i++) + { + if (pNames[i] == serviceName) + return true; + } + + return false; +} + +css::uno::Sequence SAL_CALL ScriptProvider::getSupportedServiceNames() +{ + return getSupportedServiceNamesStatic( + m_pProviderContext->m_pSingleScriptFactory->getLanguageName()); +} + +SAL_DLLPUBLIC_EXPORT OUString +ScriptProvider::getImplementationNameStatic(std::u16string_view sLanguageName) +{ + return u"com.sun.star.singleprov.ScriptProviderFor"_ustr + sLanguageName; +} + +SAL_DLLPUBLIC_EXPORT css::uno::Sequence +ScriptProvider::getSupportedServiceNamesStatic(std::u16string_view sLanguageName) +{ + css::uno::Sequence names(2); + OUString* pNames = names.getArray(); + pNames[0] = u"com.sun.star.script.provider.ScriptProviderFor"_ustr + sLanguageName; + pNames[1] = "com.sun.star.script.provider.LanguageScriptProvider"; + return names; +} + +SAL_DLLPUBLIC_EXPORT css::uno::Reference +ScriptProvider::create(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory) +{ + return static_cast( + new ScriptProvider(xContext, pSingleScriptFactory)); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/stringresource/stringresource.cxx b/scripting/source/stringresource/stringresource.cxx index a403f59c1b6d..1020e8b85e69 100644 --- a/scripting/source/stringresource/stringresource.cxx +++ b/scripting/source/stringresource/stringresource.cxx @@ -1422,7 +1422,7 @@ void StringResourcePersistenceImpl::importBinary( const Sequence< ::sal_Int8 >& // Private helper methods -static bool checkNamingSceme( std::u16string_view aName, std::u16string_view aNameBase, +static bool checkNamingScheme( std::u16string_view aName, std::u16string_view aNameBase, Locale& aLocale ) { bool bSuccess = false; @@ -1494,7 +1494,7 @@ void StringResourcePersistenceImpl::implScanLocaleNames( const Sequence< OUStrin //OUString aName = aInetObj.getBase(); Locale aLocale; - if( checkNamingSceme( aPureName, m_aNameBase, aLocale ) ) + if( checkNamingScheme( aPureName, m_aNameBase, aLocale ) ) { LocaleItem* pLocaleItem = new LocaleItem( std::move(aLocale), false ); m_aLocaleItemVector.emplace_back( pLocaleItem ); @@ -1511,7 +1511,7 @@ void StringResourcePersistenceImpl::implScanLocaleNames( const Sequence< OUStrin } else if( !bDefaultFound && aExtension == "default" ) { - if( checkNamingSceme( aPureName, m_aNameBase, aDefaultLocale ) ) + if( checkNamingScheme( aPureName, m_aNameBase, aDefaultLocale ) ) bDefaultFound = true; } } @@ -1560,7 +1560,7 @@ bool StringResourcePersistenceImpl::implLoadLocale(std::unique_lock& return false; } -static OUString implGetNameScemeForLocaleItem( const LocaleItem* pLocaleItem ) +static OUString implGetNameSchemeForLocaleItem( const LocaleItem* pLocaleItem ) { /* FIXME-BCP47: this uses '_' underscore character as separator and * also appends Variant, which can't be blindly changed as it would @@ -1569,7 +1569,7 @@ static OUString implGetNameScemeForLocaleItem( const LocaleItem* pLocaleItem ) static const char aUnder[] = "_"; assert(pLocaleItem && - "StringResourcePersistenceImpl::implGetNameScemeForLocaleItem(): pLocaleItem == NULL"); + "StringResourcePersistenceImpl::implGetNameSchemeForLocaleItem(): pLocaleItem == NULL"); Locale aLocale = pLocaleItem->m_locale; OUString aRetStr = aUnder + aLocale.Language; @@ -1595,7 +1595,7 @@ OUString StringResourcePersistenceImpl::implGetFileNameForLocaleItem if( aFileName.isEmpty() ) aFileName = aNameBaseDefaultStr; - aFileName += implGetNameScemeForLocaleItem( pLocaleItem ); + aFileName += implGetNameSchemeForLocaleItem( pLocaleItem ); return aFileName; } @@ -2334,7 +2334,7 @@ void StringResourceWithLocationImpl::initialize( const Sequence< Any >& aArgumen bOk = (aArguments[5] >>= m_xInteractionHandler); if( !bOk ) { - throw IllegalArgumentException( u"StringResourceWithStorageImpl::initialize: invalid type"_ustr, Reference< XInterface >(), 5 ); + throw IllegalArgumentException( u"StringResourceWithLocationImpl::initialize: invalid type"_ustr, Reference< XInterface >(), 5 ); } implInitializeCommonParameters( aGuard, aArguments ); diff --git a/scripting/source/stringresource/stringresource.hxx b/scripting/source/stringresource/stringresource.hxx index 75c3ed239729..7a1514ba2b80 100644 --- a/scripting/source/stringresource/stringresource.hxx +++ b/scripting/source/stringresource/stringresource.hxx @@ -108,12 +108,12 @@ protected: /// @throws css::lang::NoSupportException void implCheckReadOnly( const char* pExceptionMsg ); - // Returns the LocalItem for a given locale, if it exists, otherwise NULL + // Returns the LocaleItem for a given locale, if it exists, otherwise NULL // This method compares the locales exactly, no closest match search is performed /// @throws css::lang::IllegalArgumentException LocaleItem* getItemForLocale( const css::lang::Locale& locale, bool bException ); - // Returns the LocalItem for a given locale, if it exists, otherwise NULL + // Returns the LocaleItem for a given locale, if it exists, otherwise NULL // This method performs a closest match search, at least the language must match LocaleItem* getClosestMatchItemForLocale( const css::lang::Locale& locale ); /// @throws css::lang::IllegalArgumentException diff --git a/scripting/source/vbaevents/eventhelper.cxx b/scripting/source/vbaevents/eventhelper.cxx index 2a1c2e732f7f..5f72d0613340 100644 --- a/scripting/source/vbaevents/eventhelper.cxx +++ b/scripting/source/vbaevents/eventhelper.cxx @@ -18,13 +18,11 @@ */ #include +#include #include #include #include -#include -#include -#include -#include +#include #include #include @@ -255,7 +253,7 @@ static EventInfoHash& getEventTransInfo() EventInfoHash tmp; OUString sEventInfo; const TranslatePropMap* pTransProp = aTranslatePropMap_Impl; - int nCount = SAL_N_ELEMENTS(aTranslatePropMap_Impl); + int nCount = static_cast(std::size(aTranslatePropMap_Impl)); int i = 0; while (i < nCount) @@ -315,7 +313,7 @@ eventMethodToDescriptor( std::u16string_view rEventMethod, ScriptEventDescriptor EventInfoHash& infos = getEventTransInfo(); - // Only create an ScriptEventDescriptor for an event we can translate + // Only create a ScriptEventDescriptor for an event we can translate // or emulate if ( !sMethodName.isEmpty() && !sTypeName.isEmpty() @@ -328,7 +326,7 @@ eventMethodToDescriptor( std::u16string_view rEventMethod, ScriptEventDescriptor evtDesc.ListenerType = sTypeName; evtDesc.EventMethod = sMethodName; - // set this it VBAInterop, ensures that it doesn't + // set this to VBAInterop, ensures that it doesn't // get persisted or shown in property editors evtDesc.ScriptType = "VBAInterop"; return true; @@ -520,39 +518,30 @@ private: } -typedef ::comphelper::WeakImplHelper< XScriptListener, util::XCloseListener, lang::XInitialization, css::lang::XServiceInfo > EventListener_BASE; - #define EVENTLSTNR_PROPERTY_ID_MODEL 1 constexpr OUStringLiteral EVENTLSTNR_PROPERTY_MODEL = u"Model"; namespace { -class EventListener : public EventListener_BASE - ,public ::comphelper::OPropertyContainer2 - ,public ::comphelper::OPropertyArrayUsageHelper< EventListener > +class EventListener final + : public comphelper::OPropertyContainerImplHelper< + comphelper::WeakImplHelper, + EventListener> { public: EventListener(); // XEventListener virtual void SAL_CALL disposing(const lang::EventObject& Source) override; - using comphelper::OPropertySetHelper::disposing; - // XScriptListener virtual void SAL_CALL firing(const ScriptEvent& evt) override; virtual Any SAL_CALL approveFiring(const ScriptEvent& evt) override; // XCloseListener virtual void SAL_CALL queryClosing( const lang::EventObject& Source, sal_Bool GetsOwnership ) override; virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) override; - // XPropertySet - virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; // XInitialization virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override; - // XInterface - DECLARE_XINTERFACE() - - // XTypeProvider - DECLARE_XTYPEPROVIDER() virtual void setFastPropertyValueImpl( std::unique_lock& rGuard, sal_Int32 nHandle, const css::uno::Any& rValue ) override { if ( nHandle == EVENTLSTNR_PROPERTY_ID_MODEL ) @@ -566,7 +555,7 @@ public: { xCloseBroadcaster->removeCloseListener( this ); } - // Add the listener into the new XCloseBroadcaster. + // Add the listener to the new XCloseBroadcaster. xCloseBroadcaster.set( xModel, uno::UNO_QUERY ); if (xCloseBroadcaster.is()) { @@ -574,7 +563,7 @@ public: } } } - OPropertyContainer2::setFastPropertyValueImpl( rGuard, nHandle, rValue ); + OPropertyContainerImplHelper::setFastPropertyValueImpl( rGuard, nHandle, rValue ); if ( nHandle == EVENTLSTNR_PROPERTY_ID_MODEL ) setShellFromModel(); } @@ -595,9 +584,6 @@ public: } protected: - // OPropertySetHelper - virtual ::cppu::IPropertyArrayHelper& getInfoHelper( ) override; - // OPropertyArrayUsageHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; @@ -688,22 +674,6 @@ EventListener::initialize( const Sequence< Any >& aArguments ) "args " << aArguments.getLength() << " m_xModel " << m_xModel.is()); } -// XInterface - -IMPLEMENT_FORWARD_XINTERFACE2( EventListener, EventListener_BASE, comphelper::OPropertyContainer2 ) - -// XTypeProvider - -IMPLEMENT_FORWARD_XTYPEPROVIDER2( EventListener, EventListener_BASE, comphelper::OPropertyContainer2 ) - -// OPropertySetHelper - -::cppu::IPropertyArrayHelper& -EventListener::getInfoHelper( ) -{ - return *getArrayHelper(); -} - // OPropertyArrayUsageHelper ::cppu::IPropertyArrayHelper* @@ -714,15 +684,6 @@ EventListener::createArrayHelper( ) const return new ::cppu::OPropertyArrayHelper( aProps ); } -// XPropertySet -Reference< beans::XPropertySetInfo > -EventListener::getPropertySetInfo( ) -{ - Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); - return xInfo; -} - - //decide if the control should execute the event bool ApproveAll(SAL_UNUSED_PARAMETER const ScriptEvent&, SAL_UNUSED_PARAMETER void const * ) { diff --git a/external/more_fonts/ExternalPackage_belanosima.mk b/sd/CppunitTest_sd_export_tests2.mk similarity index 54% rename from external/more_fonts/ExternalPackage_belanosima.mk rename to sd/CppunitTest_sd_export_tests2.mk index 71c7a080b394..f1d0658c1e61 100644 --- a/external/more_fonts/ExternalPackage_belanosima.mk +++ b/sd/CppunitTest_sd_export_tests2.mk @@ -1,4 +1,5 @@ # -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* # # This file is part of the LibreOffice project. # @@ -6,13 +7,14 @@ # 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_ExternalPackage_ExternalPackage,fonts_belanosima,font_belanosima)) +$(eval $(call sd_export_test,2)) -$(eval $(call gb_ExternalPackage_add_unpacked_files,fonts_belanosima,$(LIBO_SHARE_FOLDER)/fonts/truetype,\ - Belanosima-Regular.ttf \ - Belanosima-SemiBold.ttf \ - Belanosima-Bold.ttf \ +$(eval $(call gb_CppunitTest_use_uiconfigs,sd_export_tests2, \ + modules/simpress \ + sfx \ + svt \ )) # vim: set noet sw=4 ts=4: diff --git a/sd/CppunitTest_sd_slide_section_tests.mk b/sd/CppunitTest_sd_slide_section_tests.mk new file mode 100644 index 000000000000..cec94dbe2626 --- /dev/null +++ b/sd/CppunitTest_sd_slide_section_tests.mk @@ -0,0 +1,82 @@ +# -*- 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,sd_slide_section_tests)) + +$(eval $(call gb_CppunitTest_use_externals,sd_slide_section_tests,\ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sd_slide_section_tests)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sd_slide_section_tests, \ + sd/qa/unit/SlideSectionTest \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sd_slide_section_tests, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + docmodel \ + editeng \ + for \ + forui \ + i18nlangtag \ + msfilter \ + oox \ + sal \ + salhelper \ + sax \ + sd \ + sdqahelper \ + sfx \ + sot \ + subsequenttest \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + vcl \ + xo \ +)) + +$(eval $(call gb_CppunitTest_set_include,sd_slide_section_tests,\ + -I$(SRCDIR)/sd/source/ui/inc \ + -I$(SRCDIR)/sd/inc \ + -I$(SRCDIR)/sd/qa/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,sd_slide_section_tests)) +$(eval $(call gb_CppunitTest_use_ure,sd_slide_section_tests)) +$(eval $(call gb_CppunitTest_use_vcl,sd_slide_section_tests)) +$(eval $(call gb_CppunitTest_use_rdb,sd_slide_section_tests,services)) + +$(eval $(call gb_CppunitTest_use_custom_headers,sd_slide_section_tests,\ + officecfg/registry \ +)) + +$(eval $(call gb_CppunitTest_use_configuration,sd_slide_section_tests)) + +$(eval $(call gb_CppunitTest_add_arguments,sd_slide_section_tests, \ + -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/sd/IwyuFilter_sd.yaml b/sd/IwyuFilter_sd.yaml index 8c64e181430c..be1cdbe5caa6 100644 --- a/sd/IwyuFilter_sd.yaml +++ b/sd/IwyuFilter_sd.yaml @@ -172,7 +172,7 @@ excludelist: sd/source/ui/inc/tools/SlotStateListener.hxx: # base class has to be a complete type - com/sun/star/frame/XStatusListener.hpp - sd/source/ui/presenter/PresenterCanvas.hxx: + sd/source/console/PresenterCanvas.hxx: # base class has to be a complete type - com/sun/star/rendering/XSpriteCanvas.hpp - com/sun/star/rendering/XBitmap.hpp diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk index 4c6140046464..c886e3e8cf8f 100644 --- a/sd/Library_sd.mk +++ b/sd/Library_sd.mk @@ -163,6 +163,8 @@ $(eval $(call gb_Library_add_exception_objects,sd,\ sd/source/core/anminfo \ sd/source/core/annotations/Annotation \ sd/source/core/cusshow \ + sd/source/core/SlideSectionManager \ + sd/source/core/UndoSlideSection \ sd/source/core/drawdoc \ sd/source/core/drawdoc2 \ sd/source/core/drawdoc3 \ @@ -230,7 +232,6 @@ $(eval $(call gb_Library_add_exception_objects,sd,\ sd/source/ui/app/scalectrl \ sd/source/ui/controller/slidelayoutcontroller \ sd/source/ui/controller/displaymodecontroller \ - sd/source/ui/controller/SlideTransitionsToolBoxControl \ sd/source/ui/dlg/AnimationChildWindow \ sd/source/ui/dlg/LayerTabBar \ sd/source/ui/dlg/NavigatorChildWindow \ @@ -349,9 +350,6 @@ $(eval $(call gb_Library_add_exception_objects,sd,\ sd/source/ui/func/unmovss \ sd/source/ui/func/unoaprms \ sd/source/ui/func/unprlout \ - sd/source/ui/presenter/CanvasUpdateRequester \ - sd/source/ui/presenter/PresenterCanvas \ - sd/source/ui/presenter/PresenterHelper \ sd/source/ui/presenter/PresenterPreviewCache \ sd/source/ui/presenter/SlideRenderer \ sd/source/ui/sidebar/AllMasterPagesSelector \ @@ -416,6 +414,7 @@ $(eval $(call gb_Library_add_exception_objects,sd,\ sd/source/ui/slidesorter/view/SlsFramePainter \ sd/source/ui/slidesorter/view/SlsInsertAnimator \ sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay \ + sd/source/ui/slidesorter/view/SlsSectionHeaderPainter \ sd/source/ui/slidesorter/view/SlsLayeredDevice \ sd/source/ui/slidesorter/view/SlsLayouter \ sd/source/ui/slidesorter/view/SlsPageObjectLayouter \ diff --git a/sd/Library_sdui.mk b/sd/Library_sdui.mk index ac9b5aac6ebb..c3bc2af86994 100644 --- a/sd/Library_sdui.mk +++ b/sd/Library_sdui.mk @@ -96,9 +96,11 @@ $(eval $(call gb_Library_add_exception_objects,sdui,\ sd/source/console/AccessibleNotes \ sd/source/console/AccessibleObject \ sd/source/console/AccessibleParagraph \ + sd/source/console/CanvasUpdateRequester \ sd/source/console/PresenterAccessibility \ sd/source/console/PresenterBitmapContainer \ sd/source/console/PresenterButton \ + sd/source/console/PresenterCanvas \ sd/source/console/PresenterCanvasHelper \ sd/source/console/PresenterConfigurationAccess \ sd/source/console/PresenterController \ @@ -106,6 +108,7 @@ $(eval $(call gb_Library_add_exception_objects,sdui,\ sd/source/console/PresenterFrameworkObserver \ sd/source/console/PresenterGeometryHelper \ sd/source/console/PresenterHelpView \ + sd/source/console/PresenterHelper \ sd/source/console/PresenterNotesView \ sd/source/console/PresenterPaintManager \ sd/source/console/PresenterPane \ diff --git a/sd/Module_sd.mk b/sd/Module_sd.mk index 5d97e9424cc4..0890fcad4b19 100644 --- a/sd/Module_sd.mk +++ b/sd/Module_sd.mk @@ -42,6 +42,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sd,\ CppunitTest_sd_export_tests-ooxml3 \ CppunitTest_sd_export_tests-ooxml4 \ CppunitTest_sd_export_tests \ + CppunitTest_sd_export_tests2 \ CppunitTest_sd_filters_test \ CppunitTest_sd_font_embedding_tests \ CppunitTest_sd_layout_tests \ @@ -52,19 +53,20 @@ $(eval $(call gb_Module_add_slowcheck_targets,sd,\ CppunitTest_sd_activex_controls_tests \ CppunitTest_sd_pdf_import_test \ CppunitTest_sd_png_export_tests \ + CppunitTest_sd_svg_export_tests \ CppunitTest_sd_filter_eppt \ CppunitTest_sd_shape_import_export_tests \ CppunitTest_sd_a11y \ CppunitTest_sd_textfitting_tests \ CppunitTest_sd_theme_tests \ CppunitTest_sd_annotation_tests \ + CppunitTest_sd_slide_section_tests \ )) endif ifneq ($(DISABLE_GUI),TRUE) ifeq ($(OS),LINUX) $(eval $(call gb_Module_add_slowcheck_targets,sd,\ - CppunitTest_sd_svg_export_tests \ CppunitTest_sd_tiledrendering \ CppunitTest_sd_tiledrendering2 \ CppunitTest_sd_lokit_search \ diff --git a/sd/UIConfig_sdraw.mk b/sd/UIConfig_sdraw.mk index 276a1efc5cd8..73b1facd6868 100644 --- a/sd/UIConfig_sdraw.mk +++ b/sd/UIConfig_sdraw.mk @@ -120,7 +120,6 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/sdraw,\ sd/uiconfig/sdraw/ui/notebookbar_compact \ sd/uiconfig/sdraw/ui/notebookbar_single \ sd/uiconfig/sdraw/ui/notebookbar_groupedbar_compact \ - sd/uiconfig/sdraw/ui/notebookbar_online \ sd/uiconfig/sdraw/ui/paranumberingtab \ sd/uiconfig/sdraw/ui/queryunlinkimagedialog \ sd/uiconfig/sdraw/ui/selectlayerdialog \ diff --git a/sd/UIConfig_simpress.mk b/sd/UIConfig_simpress.mk index ad21ed0e48fb..ec273ef03f15 100644 --- a/sd/UIConfig_simpress.mk +++ b/sd/UIConfig_simpress.mk @@ -40,6 +40,7 @@ $(eval $(call gb_UIConfig_add_popupmenufiles,modules/simpress,\ sd/uiconfig/simpress/popupmenu/pagepanecanvasmaster \ sd/uiconfig/simpress/popupmenu/pagepanenoselmaster \ sd/uiconfig/simpress/popupmenu/pagepanenosel \ + sd/uiconfig/simpress/popupmenu/sectionheader \ sd/uiconfig/simpress/popupmenu/pagepane \ sd/uiconfig/simpress/popupmenu/pagepanecanvas \ sd/uiconfig/simpress/popupmenu/pagetab \ @@ -150,7 +151,6 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/simpress,\ sd/uiconfig/simpress/ui/notebookbar_groups \ sd/uiconfig/simpress/ui/notebookbar_groupedbar_full \ sd/uiconfig/simpress/ui/notebookbar_groupedbar_compact \ - sd/uiconfig/simpress/ui/notebookbar_online \ sd/uiconfig/simpress/ui/noteschildwindow \ sd/uiconfig/simpress/ui/notespanelcontextmenu \ sd/uiconfig/simpress/ui/optimpressgeneralpage \ diff --git a/offapi/com/sun/star/drawing/framework/AnchorBindingMode.idl b/sd/inc/AnchorBindingMode.hxx similarity index 72% rename from offapi/com/sun/star/drawing/framework/AnchorBindingMode.idl rename to sd/inc/AnchorBindingMode.hxx index 84a7b8c5240a..e9aee9fce3a1 100644 --- a/offapi/com/sun/star/drawing/framework/AnchorBindingMode.idl +++ b/sd/inc/AnchorBindingMode.hxx @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * @@ -17,20 +17,24 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -module com { module sun { module star { module drawing { module framework { +#pragma once -/** This enum specifies how a resource is bound to an anchor. This can be - direct or indirect. -

      Example: Let r:a1:a2 denote a resource r which is bound to +#include + +namespace sd::framework +{ +/** This enum specifies how a resource is bound to an anchor. + This can be direct or indirect. + + Example: Let r:a1:a2 denote a resource r which is bound to anchor a1:a2 which itself is a resource a1 bound to anchor a2. - Then r:a1:a2 is bound directly to a1:a2 and indirectly to a2.

      + Then r:a1:a2 is bound directly to a1:a2 and indirectly to a2. */ -enum AnchorBindingMode +enum class AnchorBindingMode { DIRECT, INDIRECT }; +} -}; }; }; }; }; // ::com::sun::star::drawing::framework - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sd/inc/CustomAnimationEffect.hxx b/sd/inc/CustomAnimationEffect.hxx index 81cdb4d4e61a..fcacc0b7b512 100644 --- a/sd/inc/CustomAnimationEffect.hxx +++ b/sd/inc/CustomAnimationEffect.hxx @@ -152,6 +152,7 @@ public: bool getStopAudio() const; void setStopAudio(); void createAudio( const css::uno::Any& rSource ); + void setAudioSource( const css::uno::Any& rSource ); void removeAudio(); const css::uno::Reference< css::animations::XAudio >& getAudio() const { return mxAudio; } @@ -290,7 +291,7 @@ public: SAL_DLLPRIVATE virtual bool disposeShape( const css::uno::Reference< css::drawing::XShape >& xShape ); SAL_DLLPRIVATE virtual void insertTextRange( const css::uno::Any& aTarget ); - SAL_DLLPRIVATE virtual void disposeTextRange( const css::uno::Any& aTarget ); + SAL_DLLPRIVATE virtual void disposeTextRange( const css::uno::Any& aTarget, bool bPreviousParagraphEmpty ); SAL_DLLPRIVATE virtual bool hasEffect( const css::uno::Reference< css::drawing::XShape >& xShape ); SAL_DLLPRIVATE virtual void onTextChanged( const css::uno::Reference< css::drawing::XShape >& xShape ); @@ -379,7 +380,7 @@ public: MainSequence( const css::uno::Reference< css::animations::XAnimationNode >& xTimingRootNode ); virtual ~MainSequence() override; - virtual css::uno::Reference< css::animations::XAnimationNode > getRootNode() override; + SD_DLLPUBLIC virtual css::uno::Reference< css::animations::XAnimationNode > getRootNode() override; void reset( const css::uno::Reference< css::animations::XAnimationNode >& xTimingRootNode ); /** this method rebuilds the animation nodes */ @@ -389,7 +390,7 @@ public: virtual bool disposeShape( const css::uno::Reference< css::drawing::XShape >& xShape ) override; virtual void insertTextRange( const css::uno::Any& aTarget ) override; - virtual void disposeTextRange( const css::uno::Any& aTarget ) override; + virtual void disposeTextRange( const css::uno::Any& aTarget, bool bPreviousParagraphEmpty ) override; virtual bool hasEffect( const css::uno::Reference< css::drawing::XShape >& xShape ) override; virtual void onTextChanged( const css::uno::Reference< css::drawing::XShape >& xShape ) override; diff --git a/sd/inc/DocumentRenderer.hrc b/sd/inc/DocumentRenderer.hrc index 9cc79e78318a..676b1c12b494 100644 --- a/sd/inc/DocumentRenderer.hrc +++ b/sd/inc/DocumentRenderer.hrc @@ -28,6 +28,7 @@ const TranslateId STR_IMPRESS_PRINT_UI_CONTENT_CHOICES[] = NC_("STR_IMPRESS_PRINT_UI_CONTENT_CHOICES", "Slides"), NC_("STR_IMPRESS_PRINT_UI_CONTENT_CHOICES", "Handouts"), NC_("STR_IMPRESS_PRINT_UI_CONTENT_CHOICES", "Notes"), + // To translators: Outline refers to an overview of the slides NC_("STR_IMPRESS_PRINT_UI_CONTENT_CHOICES", "Outline") }; diff --git a/sd/inc/ResourceId.hxx b/sd/inc/ResourceId.hxx index e2e8f5510a6d..1912d48dff24 100644 --- a/sd/inc/ResourceId.hxx +++ b/sd/inc/ResourceId.hxx @@ -20,9 +20,9 @@ #pragma once #include +#include "AnchorBindingMode.hxx" #include "sddllapi.h" #include -#include #include #include #include @@ -131,8 +131,8 @@ public: defined on the URLS. So when there are two resource ids A1.A2 (A1 being the anchor of A2) and B1.B2 then A1.A2 - @param xId + B1.B2 when A1 + @param rxResourceId The resource id to which the called resource id is compared. @return Returns 0 when the called resource id is @@ -159,7 +159,7 @@ public: bool isBoundTo ( const rtl::Reference& rxResourceId, - css::drawing::framework::AnchorBindingMode eMode) const; + sd::framework::AnchorBindingMode eMode) const; /** Return whether the anchor of the called resource id object represents the same resource as the given anchor URL. This is a @@ -170,14 +170,14 @@ public: The resource URL of the anchor. @param eMode This mode specifies how the called resource has to be bound to - the given anchor in order to have this function return. See the + the given anchor in order to have this function return `TRUE`. See the description of isBoundTo() for more information. */ bool isBoundToURL ( const OUString& rsAnchorURL, - css::drawing::framework::AnchorBindingMode eMode) const; + sd::framework::AnchorBindingMode eMode) const; private: /** The set of URLs that consist of the resource URL at index 0 and the @@ -207,7 +207,7 @@ private: */ bool IsBoundToAnchor ( const OUString* psFirstAnchorURL, - css::drawing::framework::AnchorBindingMode eMode) const; + sd::framework::AnchorBindingMode eMode) const; /** Return whether the called ResourceId object is bound to the anchor consisting of the URLs in rResourceURLs. @@ -220,7 +220,7 @@ private: */ bool IsBoundToAnchor ( const ::std::vector& rResourceURLs, - css::drawing::framework::AnchorBindingMode eMode) const; + sd::framework::AnchorBindingMode eMode) const; void ParseResourceURL(); }; diff --git a/sd/inc/SdSoundLink.hxx b/sd/inc/SdSoundLink.hxx new file mode 100644 index 000000000000..0d9b00884dae --- /dev/null +++ b/sd/inc/SdSoundLink.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright the LibreOffice contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +/** A sound source referenced by a presentation: the slide-transition + sound, an animation sound, or a click-action sound. + + Holds the source URL and tells apart a sound that lives inside the + document package from one that points at an external file. A + package sound uses the vnd.sun.star.Package: scheme, the same prefix + the slideshow sound player treats as in-package media. Any other + non-empty URL is a link to a file outside the document. +*/ +class SdSoundLink +{ + OUString maURL; + // Runtime allowed state: the user has allowed this external sound this + // session. In-memory only, never written to the document. + bool mbAllowed; + +public: + SdSoundLink() + : mbAllowed(false) + { + } + explicit SdSoundLink(OUString aURL) + : maURL(std::move(aURL)) + , mbAllowed(false) + { + } + SdSoundLink(OUString aURL, bool bAllowed) + : maURL(std::move(aURL)) + , mbAllowed(bAllowed) + { + } + + const OUString& getURL() const { return maURL; } + bool isEmpty() const { return maURL.isEmpty(); } + + // A sound stored inside the document package. + bool isEmbedded() const { return xmloff::isPackageSoundURL(maURL); } + + // A link to a file outside the document package. + bool isExternalLink() const { return !isEmpty() && !isEmbedded(); } + + // True when both refer to the same sound source. The runtime allowed state + // is session state, not part of what the source is, so it is not compared. + bool sameLink(const SdSoundLink& rOther) const { return maURL == rOther.maURL; } + + void setAllowed(bool bAllowed) { mbAllowed = bAllowed; } + + // True when this sound may be fetched: a sound inside the package is always + // allowed, an external link needs the user to have allowed it this session. + bool isAllowed() const { return !isExternalLink() || mbAllowed; } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/inc/SlideSectionManager.hxx b/sd/inc/SlideSectionManager.hxx new file mode 100644 index 000000000000..c25809a9e899 --- /dev/null +++ b/sd/inc/SlideSectionManager.hxx @@ -0,0 +1,96 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include +#include +#include +#include "sddllapi.h" + +class SdDrawDocument; + +namespace sd +{ +struct SlideSection +{ + OUString maName; + OUString maId; // GUID string, e.g. "{00F38008-1855-4575-B10E-A14737D1CCA5}" + sal_Int32 mnStartIndex; // 0-based index of first slide in this section +}; + +/** Manages slide sections for a presentation document. + * + * Sections group consecutive slides under a named header. + * The data is persisted via the "SlideSections" UNO property + * on the document model for PPTX/ODP round-trip compatibility. + * + * Sections are sorted by mnStartIndex. Each section spans from + * its start index to the next section's start (or end of deck). + */ +class SD_DLLPUBLIC SlideSectionManager +{ +public: + explicit SlideSectionManager(SdDrawDocument& rDoc); + + /// Get sections as a UNO PropertyValue sequence (for UNO property / export). + css::uno::Sequence GetSectionsAsPropertyValues() const; + + /// Set sections from a UNO PropertyValue sequence (from UNO property / import). + void + SetSectionsFromPropertyValues(const css::uno::Sequence& rSections); + + sal_Int32 GetSectionCount() const; + const SlideSection& GetSection(sal_Int32 nIndex) const; + + /// Returns the section index that contains the given slide, or -1. + sal_Int32 GetSectionIndexForSlide(sal_Int32 nSlideIndex) const; + + /// Returns true if nSlideIndex is the first slide of a section. + bool IsSectionStart(sal_Int32 nSlideIndex) const; + + /// Returns the start indices of all sections (for the layouter). + std::vector GetSectionStartIndices() const; + + /// Add a new section starting before the given slide index. + void AddSection(sal_Int32 nStartSlideIndex, const OUString& rName); + + /// Remove a section; its slides merge into the previous section. + void RemoveSection(sal_Int32 nSectionIndex); + + /// Delete every slide belonging to nSectionIndex via the document's + /// XDrawPages, iterating in reverse so that the indices of the slides + /// still to be deleted stay valid. Never deletes the last remaining + /// slide in the document. The caller owns undo grouping and view + /// refresh; the now-empty section metadata is auto-erased by + /// OnSlideRemoved as the slides are removed. + void RemoveSectionSlides(sal_Int32 nSectionIndex); + + /// Rename a section. + void RenameSection(sal_Int32 nSectionIndex, const OUString& rNewName); + + /// Move a section (and its slides) to a new position. + void MoveSection(sal_Int32 nOldIndex, sal_Int32 nNewIndex); + + /// Get a snapshot of all sections (for undo support). + std::vector GetSectionsSnapshot() const; + + /// Replace all sections with the given vector (for undo support). + /// Does not move any slides. + void RestoreSectionsSnapshot(const std::vector& rSections); + +private: + SdDrawDocument& mrDoc; + std::vector maSections; +}; + +} // namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/inc/UndoSlideSection.hxx b/sd/inc/UndoSlideSection.hxx new file mode 100644 index 000000000000..81b6c197e3c7 --- /dev/null +++ b/sd/inc/UndoSlideSection.hxx @@ -0,0 +1,48 @@ +/* -*- 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/. + */ + +#pragma once + +#include "SlideSectionManager.hxx" +#include "sddllapi.h" +#include +#include + +class SdDrawDocument; + +namespace sd +{ +/** Undo action for slide section metadata changes (add/remove/rename/move). + * + * Captures the full sections vector before the change; Undo restores it, + * and Redo re-applies the new state captured on first invocation. + * + * Note: this action does not move slides. For section moves that also + * reorder pages, the page-reorder undo is recorded separately by the + * underlying MovePages() call. + */ +class SD_DLLPUBLIC UndoSlideSection final : public SdrUndoAction +{ +public: + UndoSlideSection(SdDrawDocument& rDoc, const OUString& rComment); + + virtual void Undo() override; + virtual void Redo() override; + virtual OUString GetComment() const override; + +private: + std::vector maOldSections; + std::vector maNewSections; + OUString maComment; + bool mbNewCaptured = false; +}; + +} // namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/inc/anminfo.hxx b/sd/inc/anminfo.hxx index 8abc54c90dc6..00ca1d5e28b4 100644 --- a/sd/inc/anminfo.hxx +++ b/sd/inc/anminfo.hxx @@ -23,6 +23,7 @@ #include #include #include "pres.hxx" +#include "SdSoundLink.hxx" #include #include #include "sddllapi.h" @@ -42,13 +43,18 @@ public: bool mbDimHide; ///< hide rather than dim Color maBlueScreen; ///< identifies "background pixels" Color maDimColor; ///< for fading the object - OUString maSoundFile; ///< Path to the sound file in MS DOS notation + SdSoundLink maSoundLink; ///< animation effect sound source bool mbSoundOn; ///< Sound on / off bool mbPlayFull; ///< play sound completely. css::presentation::ClickAction meClickAction; ///< Action at mouse click + // Runtime allowed state: the user has allowed this click-action sound this + // session. In-memory only, never written to the document. + bool mbClickSoundAllowed; css::presentation::AnimationEffect meSecondEffect; ///< for object fading. css::presentation::AnimationSpeed meSecondSpeed; ///< for object fading. - OUString maSecondSoundFile; ///< for object fading. + // The second (object-fade) effect has no sound-file field of its own. + // When mbSecondSoundOn is set, its sound URL is the shape's bookmark + // string, set and read through SetBookmark and GetBookmark. bool mbSecondSoundOn; ///< for object fading. bool mbSecondPlayFull; ///< for object fading. sal_uInt16 mnVerb; ///< for OLE object diff --git a/sd/inc/app.hrc b/sd/inc/app.hrc index 28f64693da82..5c56ea3b3fe8 100644 --- a/sd/inc/app.hrc +++ b/sd/inc/app.hrc @@ -400,7 +400,7 @@ #define SID_NORMAL_MULTI_PANE_GUI TypedWhichId(SID_SD_START+420) #define SID_SLIDE_SORTER_MULTI_PANE_GUI (SID_SD_START+421) -#define SID_SELECT_BACKGROUND (SID_SD_START+422) +#define SID_SELECT_BACKGROUND TypedWhichId(SID_SD_START+422) #define SID_SAVE_BACKGROUND (SID_SD_START+423) // FREE // Slots for the tool pane popup @@ -429,4 +429,11 @@ #define FN_TRANSFORM_DOCUMENT_STRUCTURE (SID_SD_START+452) +#define SID_ADD_SLIDE_SECTION (SID_SD_START+453) +#define SID_REMOVE_SLIDE_SECTION (SID_SD_START+454) +#define SID_RENAME_SLIDE_SECTION (SID_SD_START+455) +#define SID_MOVE_SLIDE_SECTION_UP (SID_SD_START+456) +#define SID_MOVE_SLIDE_SECTION_DOWN (SID_SD_START+457) +#define SID_REMOVE_SLIDE_SECTION_AND_SLIDES (SID_SD_START+458) + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/inc/drawdoc.hxx b/sd/inc/drawdoc.hxx index 31c6691f8747..eb28774f0648 100644 --- a/sd/inc/drawdoc.hxx +++ b/sd/inc/drawdoc.hxx @@ -47,6 +47,7 @@ class Timer; class SfxObjectShell; class SdPage; class SdAnimationInfo; +class SdSoundLink; class SdStyleSheetPool; class SfxMedium; class SvxSearchItem; @@ -76,6 +77,7 @@ typedef rtl::Reference DrawDocShellRef; class UndoManager; class ShapeList; class FrameView; +class SlideSectionManager; } class ImpDrawPageListWatcher; @@ -351,6 +353,8 @@ private: std::unique_ptr mpWorkStartupTimer; std::unique_ptr mpOnlineSpellingIdle; + std::unique_ptr + mpPlaceholderSwitchIdle; std::unique_ptr mpOnlineSpellingList; std::unique_ptr @@ -358,6 +362,7 @@ private: std::vector> maFrameViewList; std::unique_ptr mpCustomShowList; + std::unique_ptr mpSectionManager; ::sd::DrawDocShell* mpDocSh; SdTransferable * mpCreatingTransferable; bool mbHasOnlineSpellErrors; @@ -373,6 +378,10 @@ private: bool mbDestroying = false; + /// true when the document may hold an animation effect sound whose source + /// is a file outside the document package + bool mbMaybeHasAnimationSoundLinks = false; + bool mbOnlineSpell; bool mbSummationOfParagraphs; sal_uInt16 mnStartWithPresentation; ///< 1-based starting slide# when presenting via command line parameter --show @@ -611,7 +620,7 @@ public: SAL_DLLPRIVATE virtual bool IsCreatingDataObj() const override { return mpCreatingTransferable != nullptr; } /** if the document does not contain at least one handout, one slide and one notes page with - at least one master each this methods creates them. + at least one master each this method creates them. If a reference document is given, the sizes and border settings of that document are used for newly created slides. */ @@ -696,7 +705,8 @@ public: PageNameList *pExchangeList, bool bLink, sal_uInt16 nInsertPos, - ::sd::DrawDocShell* pBookmarkDocSh); + ::sd::DrawDocShell* pBookmarkDocSh, + std::optional oScaleObjects = std::nullopt); /** * Handle drag and drop operations @@ -861,6 +871,7 @@ public: SAL_DLLPRIVATE std::vector>& GetFrameViewList() { return maFrameViewList; } SdCustomShowList* GetCustomShowList(bool bCreate = false); + sd::SlideSectionManager& GetSectionManager(); SAL_DLLPRIVATE void NbcSetChanged(bool bFlag); @@ -875,6 +886,16 @@ public: SAL_DLLPRIVATE void NewOrLoadCompleted(DocCreationMode eMode); SAL_DLLPRIVATE void NewOrLoadCompleted( SdPage* pPage, SdStyleSheetPool* pSPool ); + + /** Lets every placeholder that a file states as holding text be represented by an outliner + object, which is what makes that text behave as text. Run after a file has been read. */ + SAL_DLLPRIVATE void SwitchPlaceholdersHoldingText(); + + /** Asks for that pass once the operation in hand is over, for text that reached a + placeholder by + another route than a file or the text edit. */ + SAL_DLLPRIVATE void ArmPlaceholderSwitch(); + DECL_DLLPRIVATE_LINK(PlaceholderSwitchHdl, Timer*, void); SAL_DLLPRIVATE bool IsNewOrLoadCompleted() const {return mbNewOrLoadCompleted; } SAL_DLLPRIVATE ::sd::FrameView* GetFrameView(size_t nPos) { @@ -889,6 +910,25 @@ public: SAL_DLLPRIVATE void UpdateAllLinks(); + /// set whether the document may hold an animation effect sound whose source + /// is a file outside the document package + SAL_DLLPRIVATE void SetMaybeHasAnimationSoundLinks(bool bSet) { mbMaybeHasAnimationSoundLinks = bSet; } + SAL_DLLPRIVATE bool MaybeHasAnimationSoundLinks() const { return mbMaybeHasAnimationSoundLinks; } + + /// register the slide-transition sound of rPage as a link bound to the + /// page, so allowing it marks the sound on the page allowed + SAL_DLLPRIVATE void RegisterPageSoundLink(SdPage& rPage); + + /// register an external click-action sound on rObject as a link bound to the + /// shape, so allowing it marks the sound on that shape allowed; does nothing + /// when the shape has no external click-action sound + SAL_DLLPRIVATE void RegisterShapeSoundLink(SdrObject& rObject); + + /// register the external animation-effect sounds on rPage as links bound to + /// their audio nodes, so allowing one marks that node's source allowed; + /// returns true when rPage has any such sound + SAL_DLLPRIVATE bool RegisterAnimationSoundLinks(SdPage& rPage); + SAL_DLLPRIVATE void CheckMasterPages(); SAL_DLLPRIVATE void Merge(SdrModel& rSourceModel, @@ -900,7 +940,7 @@ public: css::text::WritingMode GetDefaultWritingMode() const; SAL_DLLPRIVATE void SetDefaultWritingMode( css::text::WritingMode eMode ); - /** replacespOldPage from all custom shows with pNewPage or removes pOldPage from + /** replaces pOldPage from all custom shows with pNewPage or removes pOldPage from all custom shows if pNewPage is 0. */ SAL_DLLPRIVATE void ReplacePageInCustomShows( const SdPage* pOldPage, const SdPage* pNewPage ); diff --git a/sd/inc/pageformatpanel.hrc b/sd/inc/pageformatpanel.hrc index 7dd031314d94..ba5268f3a6b9 100644 --- a/sd/inc/pageformatpanel.hrc +++ b/sd/inc/pageformatpanel.hrc @@ -24,12 +24,12 @@ const std::pair RID_PAGEFORMATPANEL_MARGINS_INCH[] = { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "None"), 0 }, { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "Narrow"), 0 }, { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "Moderate"), 0 }, - // Normal (0.75") - { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "Normal (%1)"), 75 }, - // Normal (1") - { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "Normal (%1)"), 100 }, - // Normal (1.25") - { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "Normal (%1)"), 125 }, + // Normal (0.39") + { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "Normal (%1)"), 39 }, + // Normal (0.5") + { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "Normal (%1)"), 50 }, + // Normal (0.63") + { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "Normal (%1)"), 63 }, { NC_("RID_PAGEFORMATPANEL_MARGINS_INCH", "Wide"), 0 } }; @@ -39,12 +39,12 @@ const std::pair RID_PAGEFORMATPANEL_MARGINS_CM[] = { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "None"), 0 }, { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "Narrow"), 0 }, { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "Moderate"), 0 }, - // Normal (1.9 cm) - { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "Normal (%1)"), 190 }, - // Normal (2.54 cm) - { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "Normal (%1)"), 254 }, - // Normal (3.18 cm) - { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "Normal (%1)"), 318 }, + // Normal (1 cm) + { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "Normal (%1)"), 100 }, + // Normal (1.27 cm) + { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "Normal (%1)"), 127 }, + // Normal (1.59 cm) + { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "Normal (%1)"), 159 }, { NC_("RID_PAGEFORMATPANEL_MARGINS_CM", "Wide"), 0 } }; diff --git a/sd/inc/pch/precompiled_sd.hxx b/sd/inc/pch/precompiled_sd.hxx index 7c6296d10c23..4a8a383a849a 100644 --- a/sd/inc/pch/precompiled_sd.hxx +++ b/sd/inc/pch/precompiled_sd.hxx @@ -118,7 +118,6 @@ #include #include #include -#include #include #include #include diff --git a/sd/inc/pch/precompiled_sdui.hxx b/sd/inc/pch/precompiled_sdui.hxx index d446a73ce99b..67092fb4d45b 100644 --- a/sd/inc/pch/precompiled_sdui.hxx +++ b/sd/inc/pch/precompiled_sdui.hxx @@ -170,7 +170,6 @@ #include #include #include -#include #include #include #include @@ -367,7 +366,6 @@ #include #include #include -#include #include #include #include diff --git a/sd/inc/sdattr.hrc b/sd/inc/sdattr.hrc index 3bc08b04de81..9d3527555818 100644 --- a/sd/inc/sdattr.hrc +++ b/sd/inc/sdattr.hrc @@ -26,6 +26,7 @@ class SfxInt32Item; class SfxStringItem; class SfxUInt32Item; class XColorItem; +class SfxUInt16Item; // Layer attributes #define ATTR_LAYER_START SID_SD_START + 1234 @@ -91,7 +92,8 @@ class XColorItem; #define ATTR_COPY_HEIGHT TypedWhichId(ATTR_COPY_START + 5) #define ATTR_COPY_START_COLOR TypedWhichId(ATTR_COPY_START + 6) #define ATTR_COPY_END_COLOR TypedWhichId(ATTR_COPY_START + 7) -#define ATTR_COPY_END ATTR_COPY_END_COLOR +#define ATTR_COPY_COLOR_TRANSKIND TypedWhichId(ATTR_COPY_START + 8) +#define ATTR_COPY_END ATTR_COPY_COLOR_TRANSKIND #define ATTR_SNAPLINE_START ATTR_COPY_END + 1 #define ATTR_SNAPLINE_KIND TypedWhichId(ATTR_SNAPLINE_START) diff --git a/sd/inc/sdenumdef.hxx b/sd/inc/sdenumdef.hxx index bd04c67a9e07..229b162d9486 100644 --- a/sd/inc/sdenumdef.hxx +++ b/sd/inc/sdenumdef.hxx @@ -28,4 +28,11 @@ enum class SnapKind Point }; +enum class ColorInterpolationKind : sal_uInt16 +{ + RGB, + HSLInc, + HSLDec +}; + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/inc/sdpage.hxx b/sd/inc/sdpage.hxx index b4f84812b0af..b6a72f87bdec 100644 --- a/sd/inc/sdpage.hxx +++ b/sd/inc/sdpage.hxx @@ -30,9 +30,11 @@ #include #include #include +#include #include #include "diadef.h" #include "pres.hxx" +#include "SdSoundLink.hxx" #include "shapelist.hxx" #include "misc/scopelock.hxx" #include "sddllapi.h" @@ -112,7 +114,7 @@ friend class sd::UndoAttrObject; bool mbSoundOn; ///< with / without sound. bool mbExcluded; ///< will (not) be displayed during show. OUString maLayoutName; ///< Name of the layout - OUString maSoundFile; ///< Path to sound file (MS-DOS notation). + SdSoundLink maSoundLink; ///< transition sound source bool mbLoopSound; bool mbStopSound; OUString maCreatedPageName; ///< generated page name by GetPageName. @@ -123,7 +125,7 @@ friend class sd::UndoAttrObject; sal_uInt16 mnPaperBin; ///< PaperBin SdPageLink* mpPageLink; ///< Page link (at left sides only) bool mbIsCanvasPage; ///< whether the page is a canvas page - bool mbIsCanvasMasterPage; ///< whether it is the master page of canvas page + bool mbIsCanvasMasterPage; ///< whether it is the master page of the canvas page // PDF link annotations for read-only pdfium std::vector> maLinkAnnotations; @@ -180,6 +182,7 @@ public: void GetPageInfo(::tools::JsonWriter& jsonWriter); void NotifyPagePropertyChanges(); bool RestoreDefaultText( SdrObject* pObj, const OUString& rStr ) override; + void onEmptyPresObjFilled(SdrObject& rObj) override; /** @return true if the given SdrObject is inside the presentation object list */ bool IsPresObj(const SdrObject* pObj); @@ -190,17 +193,36 @@ public: /** inserts the given SdrObject into the presentation object list */ void InsertPresObj(SdrObject* pObj, PresObjKind eKind ); + /** The checksum of the art a picture placeholder is created holding. Loading and decoding it + is what answers for the theme in force, so a walk over many objects asks once. */ + static BitmapChecksum GetPlaceholderStandInChecksum(); + + /** Whether the object shows nothing but the art that stands in for what a placeholder waits + for. A picture placeholder is created holding that art, so holding a graphic does not mean + the author put a picture there. */ + static bool HoldsPlaceholderStandIn(const SdrObject& rObj, BitmapChecksum nStandIn); + + /** What represents a placeholder that holds text: an outliner object, the way a graphic object + represents one holding a picture. It carries the placeholder's identity but belongs to no + page yet, so the caller decides how it takes the old object's place. */ + rtl::Reference MakePresObjText(SdrObject& rObj); + + /** The reverse: what represents the given placeholder once its text is gone - for a picture one + the icon standing in for the image it waits for. It carries the placeholder's identity but + belongs to no page yet, so the caller decides how it takes the old object's place. */ + rtl::Reference MakePresObjPlaceholder(SdrObject& rObj); + SD_DLLPUBLIC void SetAutoLayout(AutoLayout eLayout, bool bInit=false, bool bCreate=false); AutoLayout GetAutoLayout() const { return meAutoLayout; } void CreateTitleAndLayout(bool bInit=false, bool bCreate=false); SdrObject* InsertAutoLayoutShape(SdrObject* pObj, PresObjKind eObjKind, bool bVertical, const ::tools::Rectangle& rRect, const OUString& rCustomPrompt, bool bInit); - virtual void NbcInsertObject(SdrObject* pObj, size_t nPos=SAL_MAX_SIZE) override; + SD_DLLPUBLIC virtual void NbcInsertObject(SdrObject* pObj, size_t nPos=SAL_MAX_SIZE) override; virtual rtl::Reference NbcRemoveObject(size_t nObjNum) override; virtual rtl::Reference RemoveObject(size_t nObjNum) override; /** Also override ReplaceObject methods to realize when - objects are removed with this mechanism instead of RemoveObject*/ + objects are removed with this mechanism instead of RemoveObject */ virtual rtl::Reference ReplaceObject(SdrObject* pNewObj, size_t nObjNum) override; void SetObjText(SdrTextObj* pObj, SdrOutliner* pOutliner, PresObjKind eObjKind, std::u16string_view rStr ); @@ -228,8 +250,10 @@ public: bool IsScaleObjects() const { return mbScaleObjects; } - void SetSoundFile(const OUString& rStr) { maSoundFile = rStr; } - const OUString& GetSoundFile() const { return maSoundFile; } + void SetSoundFile(const OUString& rStr, bool bAllowed = false); + const OUString& GetSoundFile() const { return maSoundLink.getURL(); } + const SdSoundLink& GetSoundLink() const { return maSoundLink; } + void SetSoundAllowed(bool bAllowed) { maSoundLink.setAllowed(bAllowed); } void SetLoopSound( bool bLoopSound ) { mbLoopSound = bLoopSound; } bool IsLoopSound() const { return mbLoopSound; } @@ -301,7 +325,7 @@ public: void setAnimationNode( css::uno::Reference< css::animations::XAnimationNode > const & xNode ); /// @return a helper class to manipulate effects inside the main sequence - std::shared_ptr< sd::MainSequence > const & getMainSequence(); + SD_DLLPUBLIC std::shared_ptr< sd::MainSequence > const & getMainSequence(); /** quick check if this slide has an animation node. This can be used to have a cost free check if there are no animations ad this slide. @@ -315,7 +339,7 @@ public: /** removes all custom animations for the given shape */ void removeAnimations( const SdrObject* pObj ); - /** Notify that the object has been renamed and the animation effects has to update. */ + /** Notify that the object has been renamed and the animation effects have to be updated. */ void notifyObjectRenamed(const SdrObject* pObj); /** Set the name of the page and broadcast a model change. @@ -347,7 +371,7 @@ public: void onEndTextEdit( SdrObject* pObj ); /** @return the presentation style with the given helpid from this masterpage or this - slides masterpage */ + slide's masterpage */ SD_DLLPUBLIC SdStyleSheet* getPresentationStyle( sal_uInt32 nHelpId ) const; /** removes all empty presentation objects from this slide */ diff --git a/sd/inc/sdundo.hxx b/sd/inc/sdundo.hxx index 54097f03f5ca..c4ce1172f08a 100644 --- a/sd/inc/sdundo.hxx +++ b/sd/inc/sdundo.hxx @@ -29,7 +29,7 @@ class SD_DLLPUBLIC SdUndoAction : public SfxUndoAction public: SdUndoAction(SdDrawDocument& rSdDrawDocument); - void SetComment(const OUString& rStr) { maComment = rStr; } + virtual void SetComment(const OUString& rStr) override { maComment = rStr; } virtual OUString GetComment() const override { return maComment; } virtual SdUndoAction* Clone() const { return nullptr; } /// See SfxUndoAction::GetViewShellId(). diff --git a/sd/inc/stlfamily.hxx b/sd/inc/stlfamily.hxx index 4a2b4f3d3b67..30d90d66418f 100644 --- a/sd/inc/stlfamily.hxx +++ b/sd/inc/stlfamily.hxx @@ -43,7 +43,7 @@ class SdStyleFamily final : public ::cppu::WeakImplHelper< css::container::XName { public: /// creates the style family for the given SfxStyleFamily - SdStyleFamily( rtl::Reference< SfxStyleSheetPool > xPool, SfxStyleFamily nFamily ); + SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, SfxStyleFamily nFamily ); /// creates the presentation family for the given masterpage SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, const SdPage* pMasterPage ); @@ -106,8 +106,6 @@ private: /// @throws css::lang::WrappedTargetException SdStyleSheet* GetSheetByName( const OUString& rName ); - SfxStyleFamily mnFamily; - rtl::Reference< SfxStyleSheetPool > mxPool; std::unique_ptr mpImpl; }; diff --git a/sd/inc/strings.hrc b/sd/inc/strings.hrc index f6a06e0b85db..2d884d43d3c5 100644 --- a/sd/inc/strings.hrc +++ b/sd/inc/strings.hrc @@ -35,6 +35,7 @@ #define STR_SLIDE_SORTER_MODE NC_("STR_SLIDE_SORTER_MODE", "Slide Sorter") #define STR_NORMAL_MODE NC_("STR_NORMAL_MODE", "Normal") #define STR_SLIDE_MASTER_MODE NC_("STR_SLIDE_MASTER_MODE", "Master Slide") +// To translators: Outline refers to the outline mode to view an overview of the slides #define STR_OUTLINE_MODE NC_("STR_OUTLINE_MODE", "Outline") #define STR_NOTES_MODE NC_("STR_NOTES_MODE", "Notes") #define STR_NOTES_MASTER_MODE NC_("STR_NOTES_MASTER_MODE", "Master Notes") @@ -296,7 +297,6 @@ #define STR_PRESOBJ_TITLE_MOBILE NC_("STR_PRESOBJ_TITLE_MOBILE", "Double-tap to add Title" ) #define STR_PRESOBJ_OUTLINE_MOBILE NC_("STR_PRESOBJ_OUTLINE_MOBILE", "Double-tap to add Text" ) #define STR_PRESOBJ_TEXT_MOBILE NC_("STR_PRESOBJ_TEXT_MOBILE", "Double-tap to add Text" ) -#define STR_PRESOBJ_TEXT_EDIT_MOBILE NC_("STR_PRESOBJ_TEXT_MOBILE", "Tap to edit text" ) #define STR_PRESOBJ_NOTESTEXT_MOBILE NC_("STR_PRESOBJ_NOTESTEXT_MOBILE", "Double-tap to add Notes" ) #define STR_PRESOBJ_GRAPHIC NC_("STR_PRESOBJ_GRAPHIC", "Double-click to add an Image" ) #define STR_PRESOBJ_OBJECT NC_("STR_PRESOBJ_OBJECT", "Double-click to add an Object" ) @@ -322,7 +322,7 @@ #define STR_POOLSHEET_A0_HEADLINE NC_("STR_POOLSHEET_A0_HEADLINE", "Heading A0" ) #define STR_POOLSHEET_A0_TEXT NC_("STR_POOLSHEET_A0_TEXT", "Text A0" ) #define STR_POOLSHEET_GRAPHIC NC_("STR_POOLSHEET_GRAPHIC", "Graphic" ) -#define STR_POOLSHEET_SHAPES NC_("STR_POOLSHEET_GRAPHIC", "Shapes" ) +#define STR_POOLSHEET_SHAPES NC_("STR_POOLSHEET_SHAPES", "Shapes" ) #define STR_POOLSHEET_LINES NC_("STR_POOLSHEET_LINES", "Lines" ) #define STR_POOLSHEET_MEASURE NC_("STR_POOLSHEET_MEASURE", "Arrow Line" ) #define STR_POOLSHEET_LINES_DASHED NC_("STR_POOLSHEET_LINES_DASHED", "Dashed Line" ) @@ -341,6 +341,7 @@ #define STR_PSEUDOSHEET_TITLE NC_("STR_PSEUDOSHEET_TITLE", "Title" ) #define STR_PSEUDOSHEET_SUBTITLE NC_("STR_PSEUDOSHEET_SUBTITLE", "Subtitle") +// To translators: This is used in a style name and will be followed by a number for the outline level #define STR_PSEUDOSHEET_OUTLINE NC_("STR_PSEUDOSHEET_OUTLINE", "Outline" ) #define STR_PSEUDOSHEET_BACKGROUNDOBJECTS NC_("STR_PSEUDOSHEET_BACKGROUNDOBJECTS", "Background objects" ) #define STR_PSEUDOSHEET_BACKGROUND NC_("STR_PSEUDOSHEET_BACKGROUND", "Background" ) @@ -463,7 +464,7 @@ #define RID_SVXSTR_EDIT_GRAPHIC NC_("RID_SVXSTR_EDIT_GRAPHIC", "Link") #define RID_SVXSTR_MENU_NEXT NC_("RID_SVXSTR_MENU_NEXT", "~Next") -#define RID_SVXSTR_MENU_PREV NC_("RID_SVXSTR_MENU_NEXT", "~Previous") +#define RID_SVXSTR_MENU_PREV NC_("RID_SVXSTR_MENU_PREV", "~Previous") #define RID_SVXSTR_MENU_FIRST NC_("RID_SVXSTR_MENU_FIRST", "~First Slide") #define RID_SVXSTR_MENU_LAST NC_("RID_SVXSTR_MENU_LAST", "~Last Slide") @@ -492,4 +493,16 @@ #define STR_NEXT_PAGE NC_("STR_NEXT_PAGE", "Next Page") #define STR_LAST_PAGE NC_("STR_LAST_PAGE", "Last Page") +#define STR_ADD_SLIDE_SECTION NC_("STR_ADD_SLIDE_SECTION", "Add Section") +#define STR_REMOVE_SLIDE_SECTION NC_("STR_REMOVE_SLIDE_SECTION", "Remove Section") +#define STR_RENAME_SLIDE_SECTION NC_("STR_RENAME_SLIDE_SECTION", "Rename Section") +#define STR_DEFAULT_SLIDE_SECTION_NAME NC_("STR_DEFAULT_SLIDE_SECTION_NAME", "Untitled Section") +#define STR_UNDO_ADD_SLIDE_SECTION NC_("STR_UNDO_ADD_SLIDE_SECTION", "Add section") +#define STR_UNDO_REMOVE_SLIDE_SECTION NC_("STR_UNDO_REMOVE_SLIDE_SECTION", "Remove section") +#define STR_UNDO_RENAME_SLIDE_SECTION NC_("STR_UNDO_RENAME_SLIDE_SECTION", "Rename section") +#define STR_UNDO_MOVE_SLIDE_SECTION NC_("STR_UNDO_MOVE_SLIDE_SECTION", "Move section") +#define STR_UNDO_REMOVE_SLIDE_SECTION_AND_SLIDES NC_("STR_UNDO_REMOVE_SLIDE_SECTION_AND_SLIDES", "Remove section and slides") + +#define STR_SLIDE_PROPERTIES NC_("STR_SLIDE_PROPERTIES", "Slide Properties") + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/inc/theme/ThemeColorChanger.hxx b/sd/inc/theme/ThemeColorChanger.hxx index d235e0565a5c..be44937c3268 100644 --- a/sd/inc/theme/ThemeColorChanger.hxx +++ b/sd/inc/theme/ThemeColorChanger.hxx @@ -27,7 +27,7 @@ public: ThemeColorChanger(SdrPage* pMasterPage, sd::DrawDocShell* pDocShell); virtual ~ThemeColorChanger() override; - void doApply(std::shared_ptr const& pColorSet) override; + void apply(std::shared_ptr const& pColorSet) override; }; } // end sd namespace diff --git a/sd/inc/unomodel.hxx b/sd/inc/unomodel.hxx index 4a700a71d55c..2aa632e78928 100644 --- a/sd/inc/unomodel.hxx +++ b/sd/inc/unomodel.hxx @@ -146,7 +146,6 @@ public: static rtl::Reference< SdXImpressDocument > GetModel( SdDrawDocument const & rDoc ); // internal - bool operator==( const SdXImpressDocument& rModel ) const { return mpDoc == rModel.mpDoc; } bool operator!=( const SdXImpressDocument& rModel ) const { return mpDoc != rModel.mpDoc; } ::sd::DrawDocShell* GetDocShell() const { return mpDocShell; } @@ -285,7 +284,7 @@ public: /// @see vcl::ITiledRenderable::getPointer(). virtual PointerStyle getPointer() override; /// @see vcl::ITiledRenderable::getPostIts(). - virtual void getPostIts(tools::JsonWriter& /*rJsonWriter*/) override; + SD_DLLPUBLIC virtual void getPostIts(tools::JsonWriter& /*rJsonWriter*/) override; /// @see vcl::ITiledRenderable::selectPart(). virtual void selectPart(int nPart, int nSelect) override; /// @see vcl::ITiledRenderable::moveSelectedParts(). diff --git a/sd/qa/uitest/impress_tests/dimensionLinesTabPage.py b/sd/qa/uitest/impress_tests/dimensionLinesTabPage.py new file mode 100644 index 000000000000..ca4db5a989a6 --- /dev/null +++ b/sd/qa/uitest/impress_tests/dimensionLinesTabPage.py @@ -0,0 +1,93 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# + +from uitest.framework import UITestCase +from uitest.uihelper.common import select_pos, get_state_as_dict +from uitest.uihelper.common import change_measurement_unit +from libreoffice.uno.propertyvalue import mkPropertyValues + +class dimensionLinesTabPage(UITestCase): + + def test_tdf138414_fixed_decimal_precision(self): + with self.ui_test.create_doc_in_start_center("draw") as xDrawDoc: + with change_measurement_unit(self, "Centimeter"): + # Insert a dimension line using CTRL key + xArgs = mkPropertyValues({"KeyModifier": 8192}) + self.xUITest.executeCommandWithParameters(".uno:MeasureLine", xArgs) + + # Open the dimension lines tab page + with self.ui_test.execute_dialog_through_command(".uno:measureAttributes") as xDialog: + # Verify default state of auto decimal places + xAutoDecimalPlaces = xDialog.getChild("TSB_AUTO_DECIMAL_PLACES") + self.assertEqual(get_state_as_dict(xAutoDecimalPlaces)["Selected"], "true") + # Disable auto decimal places so the manual count is respected + xAutoDecimalPlaces.executeAction("CLICK", tuple()) + + # Increase decimal places to 5 (starting from default = 2) + xDecimalPlaces = xDialog.getChild("MTR_FLD_DECIMALPLACES") + for _ in range(3): + xDecimalPlaces.executeAction("UP", tuple()) + + # Change measurement unit to centimeters to ensure no rounding errors + xMeasurementUnit = xDialog.getChild("LB_UNIT") + select_pos(xMeasurementUnit, "2") + self.assertEqual(get_state_as_dict(xMeasurementUnit)["SelectEntryText"], "Centimeter") + + # Retrieve dimension line and check its text property + xShape = xDrawDoc.DrawPages[0][0] + # Without the fix in place, this test would have failed with + # AssertionError: '7.999' != '7.99900' + # i.e. number of decimal places was not respected + self.assertEqual(xShape.getString(), "7.99900 cm") + + def test_tdf138414_automatic_decimal_precision(self): + with self.ui_test.create_doc_in_start_center("draw") as xDrawDoc: + with change_measurement_unit(self, "Centimeter"): + # Insert a dimension line using CTRL key + xArgs = mkPropertyValues({"KeyModifier": 8192}) + self.xUITest.executeCommandWithParameters(".uno:MeasureLine", xArgs) + + # Open the dimension lines tab page + with self.ui_test.execute_dialog_through_command(".uno:measureAttributes") as xDialog: + # Verify default state of auto decimal places + xAutoDecimalPlaces = xDialog.getChild("TSB_AUTO_DECIMAL_PLACES") + self.assertEqual(get_state_as_dict(xAutoDecimalPlaces)["Selected"], "true") + + # Increase decimal places to 5 (starting from default = 2) + xDecimalPlaces = xDialog.getChild("MTR_FLD_DECIMALPLACES") + for _ in range(3): + xDecimalPlaces.executeAction("UP", tuple()) + + # Change measurement unit to centimeters to ensure no rounding errors + xMeasurementUnit = xDialog.getChild("LB_UNIT") + select_pos(xMeasurementUnit, "2") + self.assertEqual(get_state_as_dict(xMeasurementUnit)["SelectEntryText"], "Centimeter") + + # Retrieve dimension line and check its text property + xShape = xDrawDoc.DrawPages[0][0] + # Auto decimal mode trims trailing zeros (e.g., "7.999" instead of "7.99900") + self.assertEqual(xShape.getString(), "7.999 cm") + + def test_tdf171746_number_decimal_places_limit(self): + with self.ui_test.create_doc_in_start_center("draw"): + # Insert a dimension line using CTRL key + xArgs = mkPropertyValues({"KeyModifier": 8192}) + self.xUITest.executeCommandWithParameters(".uno:MeasureLine", xArgs) + + # Open the dimension lines tab page + with self.ui_test.execute_dialog_through_command(".uno:measureAttributes") as xDialog: + # Increase decimal places 5 times (starting from default = 2) + xDecimalPlaces = xDialog.getChild("MTR_FLD_DECIMALPLACES") + for _ in range(5): + xDecimalPlaces.executeAction("UP", tuple()) + # Without the fix in place, this test would have failed with + # AssertionError: '5' != '7' + self.assertEqual(get_state_as_dict(xDecimalPlaces)["Text"], "5") + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sd/qa/uitest/impress_tests/masterSlides.py b/sd/qa/uitest/impress_tests/masterSlides.py index c413537afce4..1c48fcf878b7 100644 --- a/sd/qa/uitest/impress_tests/masterSlides.py +++ b/sd/qa/uitest/impress_tests/masterSlides.py @@ -35,7 +35,7 @@ class masterSlides(UITestCase): with self.ui_test.execute_dialog_through_command(".uno:PresentationLayout") as xDialog: - xSelect = xDialog.getChild('select') + xSelect = xDialog.getChild('layoutsiconview') xSelect.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RIGHT"})) diff --git a/sd/qa/uitest/impress_tests2/tdf128787.py b/sd/qa/uitest/impress_tests2/tdf128787.py index 900b724317cf..5e145cbbda63 100644 --- a/sd/qa/uitest/impress_tests2/tdf128787.py +++ b/sd/qa/uitest/impress_tests2/tdf128787.py @@ -37,8 +37,8 @@ class tdf128787(UITestCase): stylename.executeAction("TYPE", mkPropertyValues({"TEXT": "New Style"})) # make sure filter is set "Hierarchical"' so the 'treeview' tree is used - xFilter = xTemplatePanel.getChild('filter') - select_by_text(xFilter, "Hierarchical") + xItem = xTemplatePanel.getChild("hierarchical") + xItem.executeAction("CLICK", tuple()) xTreeView = xTemplatePanel.getChild('treeview') # "New Style" should be the first child of the first child in the tree diff --git a/sd/qa/unit/AnnotationTest.cxx b/sd/qa/unit/AnnotationTest.cxx index 3abe652cf182..8d676027bad9 100644 --- a/sd/qa/unit/AnnotationTest.cxx +++ b/sd/qa/unit/AnnotationTest.cxx @@ -11,10 +11,13 @@ #include +#include + #include #include #include +#include #include #include #include @@ -522,6 +525,146 @@ CPPUNIT_TEST_FIXTURE(AnnotationTest, testAnnotationTextUpdate) } } +CPPUNIT_TEST_FIXTURE(AnnotationTest, testAnnotationThreadedFields) +{ + // Threaded-comment fields (threaded/resolved/parentId) are carried by the + // annotation model, survive toData/fromData and clone, and surface in the + // Kit JSON so the Online client can show the resolve UI. + createSdDrawDoc(); + + auto pXImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + SdPage* pPage = pViewShell->GetActualPage(); + + // A classic (non-threaded) annotation. + rtl::Reference xFlat = pPage->createAnnotation(); + xFlat->setAuthor(u"Flat"_ustr); + xFlat->setPosition(geometry::RealPoint2D(0.0, 0.0)); + xFlat->setSize(geometry::RealSize2D(10.0, 10.0)); + xFlat->getTextRange()->setString(u"flat"_ustr); + pPage->addAnnotation(xFlat, -1); + + CPPUNIT_ASSERT(!xFlat->IsThreaded()); + CPPUNIT_ASSERT(!xFlat->IsResolved()); + CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), xFlat->GetParentId()); + + // A threaded root annotation, resolved. + rtl::Reference xRoot = pPage->createAnnotation(); + xRoot->setAuthor(u"Root"_ustr); + xRoot->setPosition(geometry::RealPoint2D(20.0, 0.0)); + xRoot->setSize(geometry::RealSize2D(10.0, 10.0)); + xRoot->getTextRange()->setString(u"root"_ustr); + xRoot->SetThreaded(true); + xRoot->SetResolved(true); + pPage->addAnnotation(xRoot, -1); + + CPPUNIT_ASSERT(xRoot->IsThreaded()); + CPPUNIT_ASSERT(xRoot->IsResolved()); + CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), xRoot->GetParentId()); + + // A threaded reply referencing the root. + rtl::Reference xReply = pPage->createAnnotation(); + xReply->setAuthor(u"Reply"_ustr); + xReply->setPosition(geometry::RealPoint2D(40.0, 0.0)); + xReply->setSize(geometry::RealSize2D(10.0, 10.0)); + xReply->getTextRange()->setString(u"reply"_ustr); + xReply->SetThreaded(true); + xReply->SetParentId(xRoot->GetId()); + pPage->addAnnotation(xReply, -1); + + CPPUNIT_ASSERT(xReply->IsThreaded()); + CPPUNIT_ASSERT(!xReply->IsResolved()); + CPPUNIT_ASSERT_EQUAL(xRoot->GetId(), xReply->GetParentId()); + + // toData / fromData round-trip carries the three new fields. + sdr::annotation::AnnotationData aSaved; + xReply->toData(aSaved); + CPPUNIT_ASSERT(aSaved.m_Threaded); + CPPUNIT_ASSERT(!aSaved.m_Resolved); + CPPUNIT_ASSERT_EQUAL(xRoot->GetId(), aSaved.m_ParentId); + + // Flip the live annotation, then restore via fromData. + xReply->SetThreaded(false); + xReply->SetResolved(true); + xReply->SetParentId(0); + xReply->fromData(aSaved); + CPPUNIT_ASSERT(xReply->IsThreaded()); + CPPUNIT_ASSERT(!xReply->IsResolved()); + CPPUNIT_ASSERT_EQUAL(xRoot->GetId(), xReply->GetParentId()); + + // clone() propagates the fields. + rtl::Reference xClone = xRoot->clone(pPage); + CPPUNIT_ASSERT(xClone->IsThreaded()); + CPPUNIT_ASSERT(xClone->IsResolved()); + CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), xClone->GetParentId()); + + // Per-annotation ToJSON emits the new keys only when threaded. + auto parseJson = [](std::string_view aText) { + std::stringstream aStream{ std::string(aText) }; + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + return aTree; + }; + + { + auto aTree = parseJson(xFlat->ToJSON(sdr::annotation::CommentNotificationType::Modify)); + const auto& rComment = aTree.get_child("comment"); + CPPUNIT_ASSERT(!rComment.get_child_optional("threaded")); + CPPUNIT_ASSERT(!rComment.get_child_optional("resolved")); + CPPUNIT_ASSERT(!rComment.get_child_optional("parentId")); + } + { + auto aTree = parseJson(xRoot->ToJSON(sdr::annotation::CommentNotificationType::Modify)); + const auto& rComment = aTree.get_child("comment"); + CPPUNIT_ASSERT_EQUAL(std::string("true"), rComment.get("threaded")); + CPPUNIT_ASSERT_EQUAL(std::string("true"), rComment.get("resolved")); + CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), rComment.get("parentId")); + } + { + auto aTree = parseJson(xReply->ToJSON(sdr::annotation::CommentNotificationType::Modify)); + const auto& rComment = aTree.get_child("comment"); + CPPUNIT_ASSERT_EQUAL(std::string("true"), rComment.get("threaded")); + CPPUNIT_ASSERT_EQUAL(std::string("false"), rComment.get("resolved")); + CPPUNIT_ASSERT_EQUAL(xRoot->GetId(), rComment.get("parentId")); + } + + // Doc-level getPostIts dump: flat annotation has no threaded keys; root and + // reply carry the expected values. + tools::JsonWriter aWriter; + pXImpressDocument->getPostIts(aWriter); + auto aDocTree = parseJson(aWriter.finishAndGetAsOString()); + + int nVerified = 0; + for (const auto& rEntry : aDocTree.get_child("comments")) + { + const auto& rComment = rEntry.second; + const sal_uInt64 nId = rComment.get("id"); + if (nId == xFlat->GetId()) + { + CPPUNIT_ASSERT(!rComment.get_child_optional("threaded")); + CPPUNIT_ASSERT(!rComment.get_child_optional("resolved")); + CPPUNIT_ASSERT(!rComment.get_child_optional("parentId")); + ++nVerified; + } + else if (nId == xRoot->GetId()) + { + CPPUNIT_ASSERT_EQUAL(std::string("true"), rComment.get("threaded")); + CPPUNIT_ASSERT_EQUAL(std::string("true"), rComment.get("resolved")); + CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), rComment.get("parentId")); + ++nVerified; + } + else if (nId == xReply->GetId()) + { + CPPUNIT_ASSERT_EQUAL(std::string("true"), rComment.get("threaded")); + CPPUNIT_ASSERT_EQUAL(std::string("false"), rComment.get("resolved")); + CPPUNIT_ASSERT_EQUAL(xRoot->GetId(), rComment.get("parentId")); + ++nVerified; + } + } + CPPUNIT_ASSERT_EQUAL(3, nVerified); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/FontEmbeddingTest.cxx b/sd/qa/unit/FontEmbeddingTest.cxx index 79c77372282e..6bc2f5c692db 100644 --- a/sd/qa/unit/FontEmbeddingTest.cxx +++ b/sd/qa/unit/FontEmbeddingTest.cxx @@ -47,8 +47,6 @@ CPPUNIT_TEST_FIXTURE(FontEmbeddingTest, testRoundtripEmbeddedFontsPPTX) // Load the document createSdImpressDoc("BoldonseFontEmbedded.pptx"); -// FIXME: for some reason it doesn't work in macOS (see testSubsettedFullEmbeddedFont for a similar case) -#if !defined(MACOSX) // Expect the font to be available now, if we imported the embedded fonts correctly { OUString aUrl = EmbeddedFontsManager::fontFileUrl( @@ -57,7 +55,6 @@ CPPUNIT_TEST_FIXTURE(FontEmbeddingTest, testRoundtripEmbeddedFontsPPTX) CPPUNIT_ASSERT(!aUrl.isEmpty()); } -#endif // Check the document settings for embedded fonts are as expected { diff --git a/sd/qa/unit/PNGExportTests.cxx b/sd/qa/unit/PNGExportTests.cxx index 065a506d02f3..185d2c7a2a38 100644 --- a/sd/qa/unit/PNGExportTests.cxx +++ b/sd/qa/unit/PNGExportTests.cxx @@ -1018,7 +1018,7 @@ CPPUNIT_TEST_FIXTURE(SdPNGExportTest, testTdf162259) xGraphicExporter->filter(aDescriptor); Bitmap bmp = vcl::PngImageReader(*maTempFile.GetStream(StreamMode::READ)).read(); - tools::Rectangle topX(12, 21, 37, 60); + tools::Rectangle topX(12, 20, 37, 60); int topNonWhites = 0; tools::Rectangle bottomX(12, 82, 37, 126); int bottomNonWhites = 0; diff --git a/sd/qa/unit/SVGExportTests.cxx b/sd/qa/unit/SVGExportTests.cxx index 4d9505ce5fe5..34b620bd399d 100644 --- a/sd/qa/unit/SVGExportTests.cxx +++ b/sd/qa/unit/SVGExportTests.cxx @@ -71,13 +71,13 @@ class SdSVGFilterTest : public UnoApiTest { public: SdSVGFilterTest() - : UnoApiTest(u"/sd/qa/unit/data/odp/"_ustr) + : UnoApiTest(u"/sd/qa/unit/data/"_ustr) { } void testSVGExportTextDecorations() { - loadFromFile(u"svg-export-text-decorations.odp"); + loadFromFile(u"odp/svg-export-text-decorations.odp"); save(TestFilter::SVG_IMPRESS); xmlDocUniquePtr svgDoc = parseXml(maTempFile); @@ -100,7 +100,7 @@ public: void testSVGExportJavascriptURL() { - loadFromFile(u"textbox-link-javascript.odp"); + loadFromFile(u"odp/textbox-link-javascript.odp"); save(TestFilter::SVG_IMPRESS); xmlDocUniquePtr svgDoc = parseXml(maTempFile); @@ -115,7 +115,7 @@ public: void testSVGExportSlideCustomBackground() { - loadFromFile(u"slide-custom-background.odp"); + loadFromFile(u"odp/slide-custom-background.odp"); save(TestFilter::SVG_IMPRESS); xmlDocUniquePtr svgDoc = parseXml(maTempFile); @@ -126,7 +126,7 @@ public: void testSVGExportTextFieldsInMasterPage() { - loadFromFile(u"text-fields.odp"); + loadFromFile(u"odp/text-fields.odp"); save(TestFilter::SVG_IMPRESS); xmlDocUniquePtr svgDoc = parseXml(maTempFile); @@ -150,7 +150,7 @@ public: void testSVGExportEmbeddedVideo() { - loadFromFile(u"slide-video-thumbnail.odp"); + loadFromFile(u"odp/slide-video-thumbnail.odp"); save(TestFilter::SVG_IMPRESS); xmlDocUniquePtr svgDoc = parseXml(maTempFile); @@ -181,7 +181,7 @@ public: void testSVGExportSlideBitmapBackground() { - loadFromFile(u"slide-bitmap-background.odp"); + loadFromFile(u"odp/slide-bitmap-background.odp"); save(TestFilter::SVG_IMPRESS); xmlDocUniquePtr svgDoc = parseXml(maTempFile); @@ -210,7 +210,7 @@ public: void testSVGExportSlideTileBitmapBackground() { - loadFromFile(u"slide-tile-background.odp"); + loadFromFile(u"odp/slide-tile-background.odp"); save(TestFilter::SVG_IMPRESS); xmlDocUniquePtr svgDoc = parseXml(maTempFile); @@ -275,7 +275,7 @@ public: aSettings.SetLanguageTag(aLangISO, true); Application::SetSettings(aSettings); - loadFromFile(u"text-fields.odp"); + loadFromFile(u"odp/text-fields.odp"); save(TestFilter::SVG_IMPRESS); xmlDocUniquePtr svgDoc = parseXml(maTempFile); @@ -292,6 +292,32 @@ public: assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_DEFS[8]/SVG_G[2]/SVG_G[2]/SVG_G[7]/SVG_G/SVG_TEXT/SVG_TSPAN/SVG_TSPAN/SVG_TSPAN ), "class", u"PlaceholderText PageNumber"); } + // tdf#151746 + void testSVGExportDrawBackground() + { + loadFromFile(u"odg/tdf151746.odg"); + save(TestFilter::SVG_DRAW); + + xmlDocUniquePtr svgDoc = parseExportedFile(); + CPPUNIT_ASSERT(svgDoc); + + // Check that the Master Background Objects are wrapped in defs tags + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_G[1]/SVG_G ), "class", u"Master_Slide"); + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_G[1]/SVG_G/SVG_G[1] ), "class", u"Background"); + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_G[1]/SVG_G/SVG_DEFS/SVG_G )); + OUString sBgObjsId = getXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_G[1]/SVG_G/SVG_DEFS/SVG_G ), "id"); + + // Check that the Page Background is not wrapped in defs tags + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G), "class", u"Page"); + assertXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G/SVG_G[1]), "class", u"Background"); + + // Check that the Master Background Objects are referenced correctly + OUString sRef = getXPath(svgDoc, SAL_STRINGIFY( /SVG_SVG/SVG_G[2]/SVG_G/SVG_G/SVG_G/SVG_G/SVG_USE ), "href"); + CPPUNIT_ASSERT_MESSAGE("The element has not a valid href attribute: starting '#' not present.", sRef.startsWith("#")); + sRef = sRef.copy(1); + CPPUNIT_ASSERT_EQUAL_MESSAGE("The href attribute for does not match the background objects id attribute: ", sBgObjsId, sRef); + } + CPPUNIT_TEST_SUITE(SdSVGFilterTest); CPPUNIT_TEST(testSVGExportTextDecorations); CPPUNIT_TEST(testSVGExportJavascriptURL); @@ -301,6 +327,7 @@ public: CPPUNIT_TEST(testSVGExportSlideBitmapBackground); CPPUNIT_TEST(testSVGExportSlideTileBitmapBackground); CPPUNIT_TEST(testSVGPlaceholderLocale); + CPPUNIT_TEST(testSVGExportDrawBackground); CPPUNIT_TEST_SUITE_END(); }; diff --git a/sd/qa/unit/SdrPdfImportTest.cxx b/sd/qa/unit/SdrPdfImportTest.cxx index 7ae2c09f668b..7ea6bb3713d2 100644 --- a/sd/qa/unit/SdrPdfImportTest.cxx +++ b/sd/qa/unit/SdrPdfImportTest.cxx @@ -38,7 +38,7 @@ public: } }; -// Load the PDF in Draw, which will load the PDF as an Graphic, then +// Load the PDF in Draw, which will load the PDF as a Graphic, then // mark the graphic object and trigger "break" function. This should // convert the PDF content into objects/shapes. CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testImportSimpleText) @@ -91,6 +91,10 @@ CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testImportSimpleText) SdrObject* pImportedObject = pPage->GetObj(0); CPPUNIT_ASSERT(pImportedObject); + // Position and size depend on which font face is selected + // (full bundled font vs. PDF subset font), which varies by environment. + // Disable exact checks until font selection is stabilized. +#if 0 // Check the object position #if !defined _WIN32 CPPUNIT_ASSERT_EQUAL(Point(2004, 2018), pImportedObject->GetLogicRect().GetPos()); @@ -105,6 +109,7 @@ CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testImportSimpleText) #else // need to check why windows appears to be different CPPUNIT_ASSERT_EQUAL(Size(3944, 470), pImportedObject->GetLogicRect().GetSize()); +#endif #endif // Object should be a text object containing one paragraph with @@ -191,7 +196,7 @@ CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testAnnotationsImportExport) saveAndReload(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList()); // Check PDF for annotations - auto pPDFDocument = parsePDFExport(); + auto pPDFDocument = parsePDFExport(pPdfium); CPPUNIT_ASSERT(pPDFDocument); CPPUNIT_ASSERT_EQUAL(1, pPDFDocument->getPageCount()); @@ -247,6 +252,73 @@ CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testAnnotationsImportExport) } } +CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testImportThreadedComments) +{ + // Sample PDF threaded_comments.pdf carries five Text annotations on page 0: + // 4 — Alice, root + // 5 — Bob, reply to Alice + // 6 — Charlie, state-change targeting Alice: + // /IRT 4 /State (Completed) /StateModel (Review) /F 30 + // 7 — Dave, has /State (Completed) /StateModel (Review) but no /IRT — Acrobat + // ignores /State on a non-state-change annotation, and so do we; + // Dave imports as a regular comment with no state. + // 8 — Eve, /IRT 4 + /State + /StateModel but missing the Hidden flag — + // structurally a state-change but the flags disqualify it. + // Acrobat treats such an annotation as malformed and skips it; + // we do the same: no sd::Annotation is produced for Eve. + // After import we expect three sd::Annotations: Alice, Bob, Dave. + // Charlie's state-change is collapsed into Alice's m_Resolved. + auto pPdfium = vcl::pdf::PDFiumLibrary::get(); + if (!pPdfium) + return; + + // We need to enable PDFium import (and make sure to disable after the test) + UsePdfium aGuard; + + loadFromFile(u"pdf/threaded_comments.pdf"); + auto pImpressDocument = dynamic_cast(mxComponent.get()); + sd::ViewShell* pViewShell = pImpressDocument->GetDocShell()->GetViewShell(); + CPPUNIT_ASSERT(pViewShell); + + SdPage* pPage = pViewShell->GetActualPage(); + CPPUNIT_ASSERT(pPage); + + CPPUNIT_ASSERT_EQUAL(size_t(3), pPage->getAnnotations().size()); + + rtl::Reference xRoot, xReply, xDave; + for (auto const& x : pPage->getAnnotations()) + { + if (x->getAuthor() == u"Alice"_ustr) + xRoot = x; + else if (x->getAuthor() == u"Bob"_ustr) + xReply = x; + else if (x->getAuthor() == u"Dave"_ustr) + xDave = x; + // Eve was skipped as malformed. + CPPUNIT_ASSERT(x->getAuthor() != u"Eve"_ustr); + } + CPPUNIT_ASSERT(xRoot); + CPPUNIT_ASSERT(xReply); + CPPUNIT_ASSERT(xDave); + + // Every imported PDF annotation is threaded. + CPPUNIT_ASSERT(xRoot->IsThreaded()); + CPPUNIT_ASSERT(xReply->IsThreaded()); + CPPUNIT_ASSERT(xDave->IsThreaded()); + + // Alice is the root; Charlie's Review/Completed state-change was collapsed onto her. + CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), xRoot->GetParentId()); + CPPUNIT_ASSERT(xRoot->IsResolved()); + + // Bob replies to Alice; no state of his own. + CPPUNIT_ASSERT_EQUAL(xRoot->GetId(), xReply->GetParentId()); + CPPUNIT_ASSERT(!xReply->IsResolved()); + + // Dave has /State but no /IRT — not a state-change; /State is discarded. + CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), xDave->GetParentId()); + CPPUNIT_ASSERT(!xDave->IsResolved()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/SlideSectionTest.cxx b/sd/qa/unit/SlideSectionTest.cxx new file mode 100644 index 000000000000..f265ed464cb9 --- /dev/null +++ b/sd/qa/unit/SlideSectionTest.cxx @@ -0,0 +1,447 @@ +/* -*- 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 "sdmodeltestbase.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; + +// Size + membership implies set equality, and avoids needing an ostream +// overload for std::set purely to satisfy CPPUNIT_ASSERT_EQUAL. +static void assertSameSlides(const std::set& rExpected, const std::set& rActual) +{ + CPPUNIT_ASSERT_EQUAL(rExpected.size(), rActual.size()); + for (SdPage* p : rExpected) + CPPUNIT_ASSERT(rActual.contains(p)); +} + +class SlideSectionTest : public SdModelTestBase +{ +public: + SlideSectionTest() + : SdModelTestBase(u"/sd/qa/unit/data/"_ustr) + { + } + + SdDrawDocument* getDoc() + { + auto* pXImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + SdDrawDocument* pDoc = pXImpressDocument->GetDoc(); + CPPUNIT_ASSERT(pDoc); + return pDoc; + } + + // Go through the docshell for Undo/Redo: sd::UndoManager deliberately hides + // its Undo/Redo overloads; SfxObjectShell::GetUndoManager() returns an + // SfxUndoManager* on which they are public. + SfxUndoManager& getUndoManager() + { + auto* pXImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + SfxUndoManager* pMgr = pXImpressDocument->GetDocShell()->GetUndoManager(); + CPPUNIT_ASSERT(pMgr); + return *pMgr; + } + + sd::SlideSectionManager& getSectionManager() { return getDoc()->GetSectionManager(); } + + // Collect pointers to the slides currently belonging to a section + // (i.e. the pages between this section's start and the next section's start). + // Pointers are stable across MoveSection — MovePages() reorders the page + // vector in place — so they are a reliable identity check for "the same + // slides are still in this section." + // + // Returned as std::set because MovePages() iterates selected pages one by + // one and does not guarantee their relative order is preserved across the + // move. What we care about is membership: the same *set* of pages must be + // under the section after the move. + std::set getSectionSlides(sal_Int32 nSectionIndex) + { + SdDrawDocument* pDoc = getDoc(); + sd::SlideSectionManager& rMgr = pDoc->GetSectionManager(); + const sal_Int32 nStart = rMgr.GetSection(nSectionIndex).mnStartIndex; + const sal_Int32 nEnd + = (nSectionIndex + 1 < rMgr.GetSectionCount()) + ? rMgr.GetSection(nSectionIndex + 1).mnStartIndex + : static_cast(pDoc->GetSdPageCount(PageKind::Standard)); + std::set aPages; + for (sal_Int32 i = nStart; i < nEnd; ++i) + aPages.insert(pDoc->GetSdPage(static_cast(i), PageKind::Standard)); + return aPages; + } +}; + +// Verify adding a section mid-deck splits the slide distribution correctly in PPTX +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testAddSectionPPTX) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + + sd::SlideSectionManager& rMgr = getSectionManager(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rMgr.GetSectionCount()); + + rMgr.AddSection(5, u"New Section"_ustr); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), rMgr.GetSectionCount()); + CPPUNIT_ASSERT_EQUAL(u"Section-1"_ustr, rMgr.GetSection(0).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-2"_ustr, rMgr.GetSection(1).maName); + CPPUNIT_ASSERT_EQUAL(u"New Section"_ustr, rMgr.GetSection(2).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-3"_ustr, rMgr.GetSection(3).maName); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rMgr.GetSection(0).mnStartIndex); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), rMgr.GetSection(1).mnStartIndex); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), rMgr.GetSection(2).mnStartIndex); + CPPUNIT_ASSERT_EQUAL(sal_Int32(11), rMgr.GetSection(3).mnStartIndex); + + save(TestFilter::PPTX); + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/presentation.xml"_ustr); + + static constexpr OString sPath = "/p:presentation/p:extLst/p:ext/p14:sectionLst"_ostr; + assertXPath(pXmlDoc, sPath + "/p14:section", 4); + assertXPath(pXmlDoc, sPath + "/p14:section[1]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/p14:section[2]", "name", u"Section-2"); + assertXPath(pXmlDoc, sPath + "/p14:section[3]", "name", u"New Section"); + assertXPath(pXmlDoc, sPath + "/p14:section[4]", "name", u"Section-3"); + assertXPath(pXmlDoc, sPath + "/p14:section[1]/p14:sldIdLst/p14:sldId", 4); + assertXPath(pXmlDoc, sPath + "/p14:section[2]/p14:sldIdLst/p14:sldId", 1); + assertXPath(pXmlDoc, sPath + "/p14:section[3]/p14:sldIdLst/p14:sldId", 6); + assertXPath(pXmlDoc, sPath + "/p14:section[4]/p14:sldIdLst/p14:sldId", 2); +} + +// Verify adding a section mid-deck splits the slide distribution correctly in ODP +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testAddSectionODP) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + skipValidation(); + saveAndReload(TestFilter::ODP); + + sd::SlideSectionManager& rMgr = getSectionManager(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rMgr.GetSectionCount()); + + rMgr.AddSection(5, u"New Section"_ustr); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), rMgr.GetSectionCount()); + CPPUNIT_ASSERT_EQUAL(u"New Section"_ustr, rMgr.GetSection(2).maName); + + save(TestFilter::ODP); + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + + static constexpr OString sPath + = "/office:document-content/office:body/office:presentation/loext:section-list"_ostr; + assertXPath(pXmlDoc, sPath + "/loext:section", 4); + assertXPath(pXmlDoc, sPath + "/loext:section[1]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/loext:section[2]", "name", u"Section-2"); + assertXPath(pXmlDoc, sPath + "/loext:section[3]", "name", u"New Section"); + assertXPath(pXmlDoc, sPath + "/loext:section[4]", "name", u"Section-3"); + assertXPath(pXmlDoc, sPath + "/loext:section[1]/loext:section-slide", 4); + assertXPath(pXmlDoc, sPath + "/loext:section[2]/loext:section-slide", 1); + assertXPath(pXmlDoc, sPath + "/loext:section[3]/loext:section-slide", 6); + assertXPath(pXmlDoc, sPath + "/loext:section[4]/loext:section-slide", 2); +} + +// Verify renaming a section persists through PPTX export without affecting slide counts +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testRenameSectionPPTX) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + + sd::SlideSectionManager& rMgr = getSectionManager(); + rMgr.RenameSection(1, u"Renamed-Section"_ustr); + + save(TestFilter::PPTX); + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/presentation.xml"_ustr); + + static constexpr OString sPath = "/p:presentation/p:extLst/p:ext/p14:sectionLst"_ostr; + assertXPath(pXmlDoc, sPath + "/p14:section[1]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/p14:section[2]", "name", u"Renamed-Section"); + assertXPath(pXmlDoc, sPath + "/p14:section[3]", "name", u"Section-3"); + + assertXPath(pXmlDoc, sPath + "/p14:section[1]/p14:sldIdLst/p14:sldId", 4); + assertXPath(pXmlDoc, sPath + "/p14:section[2]/p14:sldIdLst/p14:sldId", 7); + assertXPath(pXmlDoc, sPath + "/p14:section[3]/p14:sldIdLst/p14:sldId", 2); +} + +// Verify renaming a section persists through ODP export +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testRenameSectionODP) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + skipValidation(); + saveAndReload(TestFilter::ODP); + + sd::SlideSectionManager& rMgr = getSectionManager(); + rMgr.RenameSection(0, u"ODP-Renamed"_ustr); + + save(TestFilter::ODP); + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + + static constexpr OString sPath + = "/office:document-content/office:body/office:presentation/loext:section-list"_ostr; + assertXPath(pXmlDoc, sPath + "/loext:section[1]", "name", u"ODP-Renamed"); + assertXPath(pXmlDoc, sPath + "/loext:section[2]", "name", u"Section-2"); + assertXPath(pXmlDoc, sPath + "/loext:section[3]", "name", u"Section-3"); +} + +// Verify moving a section up reorders names and slide counts, and that the +// individual slides travel with their section (the exact set of pages in +// Section-2 before the move is exactly the set in Section-2 after the move). +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testMoveSectionUpPPTX) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + + // Capture which slides each section owns before the move. + const auto aSection1Before = getSectionSlides(0); + const auto aSection2Before = getSectionSlides(1); + const auto aSection3Before = getSectionSlides(2); + + sd::SlideSectionManager& rMgr = getSectionManager(); + rMgr.MoveSection(1, 0); + + // Section-2 is now at index 0 but must contain the same slides as before. + assertSameSlides(aSection2Before, getSectionSlides(0)); + assertSameSlides(aSection1Before, getSectionSlides(1)); + assertSameSlides(aSection3Before, getSectionSlides(2)); + + save(TestFilter::PPTX); + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/presentation.xml"_ustr); + + static constexpr OString sPath = "/p:presentation/p:extLst/p:ext/p14:sectionLst"_ostr; + assertXPath(pXmlDoc, sPath + "/p14:section[1]", "name", u"Section-2"); + assertXPath(pXmlDoc, sPath + "/p14:section[2]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/p14:section[3]", "name", u"Section-3"); + + assertXPath(pXmlDoc, sPath + "/p14:section[1]/p14:sldIdLst/p14:sldId", 7); + assertXPath(pXmlDoc, sPath + "/p14:section[2]/p14:sldIdLst/p14:sldId", 4); + assertXPath(pXmlDoc, sPath + "/p14:section[3]/p14:sldIdLst/p14:sldId", 2); +} + +// Verify moving a section up reorders names and slide counts, and that the +// individual slides travel with their section in ODP. +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testMoveSectionUpODP) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + skipValidation(); + saveAndReload(TestFilter::ODP); + + const auto aSection1Before = getSectionSlides(0); + const auto aSection2Before = getSectionSlides(1); + const auto aSection3Before = getSectionSlides(2); + + sd::SlideSectionManager& rMgr = getSectionManager(); + rMgr.MoveSection(2, 1); + + // Section-3 is now at index 1 but must contain the same slides. + assertSameSlides(aSection1Before, getSectionSlides(0)); + assertSameSlides(aSection3Before, getSectionSlides(1)); + assertSameSlides(aSection2Before, getSectionSlides(2)); + + save(TestFilter::ODP); + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + + static constexpr OString sPath + = "/office:document-content/office:body/office:presentation/loext:section-list"_ostr; + assertXPath(pXmlDoc, sPath + "/loext:section[1]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/loext:section[2]", "name", u"Section-3"); + assertXPath(pXmlDoc, sPath + "/loext:section[3]", "name", u"Section-2"); + + assertXPath(pXmlDoc, sPath + "/loext:section[1]/loext:section-slide", 4); + assertXPath(pXmlDoc, sPath + "/loext:section[2]/loext:section-slide", 2); + assertXPath(pXmlDoc, sPath + "/loext:section[3]/loext:section-slide", 7); +} + +// Verify moving a section down reorders names and slide counts, and that +// the individual slides travel with their section in PPTX. +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testMoveSectionDownPPTX) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + + const auto aSection1Before = getSectionSlides(0); + const auto aSection2Before = getSectionSlides(1); + const auto aSection3Before = getSectionSlides(2); + + sd::SlideSectionManager& rMgr = getSectionManager(); + rMgr.MoveSection(0, 1); + + // Section-1 is now at index 1 with the same slides; Section-2 at index 0. + assertSameSlides(aSection2Before, getSectionSlides(0)); + assertSameSlides(aSection1Before, getSectionSlides(1)); + assertSameSlides(aSection3Before, getSectionSlides(2)); + + save(TestFilter::PPTX); + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/presentation.xml"_ustr); + + static constexpr OString sPath = "/p:presentation/p:extLst/p:ext/p14:sectionLst"_ostr; + assertXPath(pXmlDoc, sPath + "/p14:section[1]", "name", u"Section-2"); + assertXPath(pXmlDoc, sPath + "/p14:section[2]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/p14:section[3]", "name", u"Section-3"); + + assertXPath(pXmlDoc, sPath + "/p14:section[1]/p14:sldIdLst/p14:sldId", 7); + assertXPath(pXmlDoc, sPath + "/p14:section[2]/p14:sldIdLst/p14:sldId", 4); + assertXPath(pXmlDoc, sPath + "/p14:section[3]/p14:sldIdLst/p14:sldId", 2); +} + +// Verify moving a section down reorders names and slide counts, and that +// the individual slides travel with their section in ODP. +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testMoveSectionDownODP) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + skipValidation(); + saveAndReload(TestFilter::ODP); + + const auto aSection1Before = getSectionSlides(0); + const auto aSection2Before = getSectionSlides(1); + const auto aSection3Before = getSectionSlides(2); + + sd::SlideSectionManager& rMgr = getSectionManager(); + rMgr.MoveSection(0, 1); + + assertSameSlides(aSection2Before, getSectionSlides(0)); + assertSameSlides(aSection1Before, getSectionSlides(1)); + assertSameSlides(aSection3Before, getSectionSlides(2)); + + save(TestFilter::ODP); + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + + static constexpr OString sPath + = "/office:document-content/office:body/office:presentation/loext:section-list"_ostr; + assertXPath(pXmlDoc, sPath + "/loext:section[1]", "name", u"Section-2"); + assertXPath(pXmlDoc, sPath + "/loext:section[2]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/loext:section[3]", "name", u"Section-3"); + + assertXPath(pXmlDoc, sPath + "/loext:section[1]/loext:section-slide", 7); + assertXPath(pXmlDoc, sPath + "/loext:section[2]/loext:section-slide", 4); + assertXPath(pXmlDoc, sPath + "/loext:section[3]/loext:section-slide", 2); +} + +// Undo/redo of AddSection restores the original section layout. +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testUndoRedoAddSection) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + + SdDrawDocument* pDoc = getDoc(); + CPPUNIT_ASSERT(pDoc->IsUndoEnabled()); + sd::SlideSectionManager& rMgr = pDoc->GetSectionManager(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rMgr.GetSectionCount()); + + auto pUndo = std::make_unique(*pDoc, u"Add section"_ustr); + rMgr.AddSection(5, u"New Section"_ustr); + pDoc->AddUndo(std::move(pUndo)); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), rMgr.GetSectionCount()); + CPPUNIT_ASSERT_EQUAL(u"New Section"_ustr, rMgr.GetSection(2).maName); + + getUndoManager().Undo(); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rMgr.GetSectionCount()); + CPPUNIT_ASSERT_EQUAL(u"Section-1"_ustr, rMgr.GetSection(0).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-2"_ustr, rMgr.GetSection(1).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-3"_ustr, rMgr.GetSection(2).maName); + + getUndoManager().Redo(); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), rMgr.GetSectionCount()); + CPPUNIT_ASSERT_EQUAL(u"New Section"_ustr, rMgr.GetSection(2).maName); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), rMgr.GetSection(2).mnStartIndex); +} + +// Undo/redo of RemoveSection brings a removed section back with its original name and start. +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testUndoRedoRemoveSection) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + + SdDrawDocument* pDoc = getDoc(); + sd::SlideSectionManager& rMgr = pDoc->GetSectionManager(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rMgr.GetSectionCount()); + const OUString aRemovedName = rMgr.GetSection(1).maName; + const sal_Int32 nRemovedStart = rMgr.GetSection(1).mnStartIndex; + + auto pUndo = std::make_unique(*pDoc, u"Remove section"_ustr); + rMgr.RemoveSection(1); + pDoc->AddUndo(std::move(pUndo)); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rMgr.GetSectionCount()); + + getUndoManager().Undo(); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rMgr.GetSectionCount()); + CPPUNIT_ASSERT_EQUAL(aRemovedName, rMgr.GetSection(1).maName); + CPPUNIT_ASSERT_EQUAL(nRemovedStart, rMgr.GetSection(1).mnStartIndex); + + getUndoManager().Redo(); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rMgr.GetSectionCount()); +} + +// Undo/redo of RenameSection round-trips the name. +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testUndoRedoRenameSection) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + + SdDrawDocument* pDoc = getDoc(); + sd::SlideSectionManager& rMgr = pDoc->GetSectionManager(); + const OUString aOldName = rMgr.GetSection(1).maName; + + auto pUndo = std::make_unique(*pDoc, u"Rename section"_ustr); + rMgr.RenameSection(1, u"Renamed"_ustr); + pDoc->AddUndo(std::move(pUndo)); + + CPPUNIT_ASSERT_EQUAL(u"Renamed"_ustr, rMgr.GetSection(1).maName); + + getUndoManager().Undo(); + CPPUNIT_ASSERT_EQUAL(aOldName, rMgr.GetSection(1).maName); + + getUndoManager().Redo(); + CPPUNIT_ASSERT_EQUAL(u"Renamed"_ustr, rMgr.GetSection(1).maName); +} + +// Undo/redo of MoveSection reverts both the section order and the underlying page +// order. Mirrors the production grouping (BegUndo/EndUndo) so the page-reorder undo +// recorded by MovePages() is atomic with the section-metadata undo. +CPPUNIT_TEST_FIXTURE(SlideSectionTest, testUndoRedoMoveSection) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + + SdDrawDocument* pDoc = getDoc(); + sd::SlideSectionManager& rMgr = pDoc->GetSectionManager(); + CPPUNIT_ASSERT_EQUAL(u"Section-1"_ustr, rMgr.GetSection(0).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-2"_ustr, rMgr.GetSection(1).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-3"_ustr, rMgr.GetSection(2).maName); + + pDoc->BegUndo(u"Move section"_ustr); + auto pUndo = std::make_unique(*pDoc, u"Move section"_ustr); + rMgr.MoveSection(0, 1); + pDoc->AddUndo(std::move(pUndo)); + pDoc->EndUndo(); + + CPPUNIT_ASSERT_EQUAL(u"Section-2"_ustr, rMgr.GetSection(0).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-1"_ustr, rMgr.GetSection(1).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-3"_ustr, rMgr.GetSection(2).maName); + + getUndoManager().Undo(); + + CPPUNIT_ASSERT_EQUAL(u"Section-1"_ustr, rMgr.GetSection(0).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-2"_ustr, rMgr.GetSection(1).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-3"_ustr, rMgr.GetSection(2).maName); + + getUndoManager().Redo(); + + CPPUNIT_ASSERT_EQUAL(u"Section-2"_ustr, rMgr.GetSection(0).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-1"_ustr, rMgr.GetSection(1).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-3"_ustr, rMgr.GetSection(2).maName); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/TextFittingTest.cxx b/sd/qa/unit/TextFittingTest.cxx index a92f8c9656eb..74bfce98e669 100644 --- a/sd/qa/unit/TextFittingTest.cxx +++ b/sd/qa/unit/TextFittingTest.cxx @@ -9,21 +9,16 @@ #include "sdmodeltestbase.hxx" -#include - #include #include -#include #include #include - +#include #include #include #include #include -using namespace css; - class TextFittingTest : public SdModelTestBase { public: @@ -124,6 +119,90 @@ CPPUNIT_TEST_FIXTURE(TextFittingTest, testTest) CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, pTextObject->GetSpacingScale(), 1E-4); } +CPPUNIT_TEST_FIXTURE(TextFittingTest, testTestBulletDifferenceViewAndEdit) +{ + createSdImpressDoc("TextFittingBulletEditVsView.odp"); + + SdXImpressDocument* pXImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + SdPage* pPage = pViewShell->GetActualPage(); + auto pTextObject = DynCastSdrTextObj(pPage->GetObj(0)); + CPPUNIT_ASSERT(pTextObject); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.475, pTextObject->GetFontScale(), 1E-4); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.8, pTextObject->GetSpacingScale(), 1E-4); + + // Enter edit mode + SdrView* pView = pViewShell->GetView(); + Scheduler::ProcessEventsToIdle(); + pView->SdrBeginTextEdit(pTextObject); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(true, pView->IsTextEdit()); + + auto* pOLV = pView->GetTextEditOutlinerView(); + CPPUNIT_ASSERT(pOLV); + auto& rEditView = pOLV->GetEditView(); + auto& rEditEngine = rEditView.getEditEngine(); + + // Verify that font and spacing scaling match between view and edit mode + CPPUNIT_ASSERT_DOUBLES_EQUAL(pTextObject->GetFontScale(), + rEditEngine.getScalingParameters().fFontY, 1E-4); + CPPUNIT_ASSERT_DOUBLES_EQUAL(pTextObject->GetSpacingScale(), + rEditEngine.getScalingParameters().fSpacingY, 1E-4); + + Outliner* pEditOutliner = pView->GetTextEditOutliner(); + CPPUNIT_ASSERT(pEditOutliner); + + // Get bullet sizes at current scaling + std::vector aBulletSizesBefore; + for (sal_Int32 nPara = 0; nPara < pEditOutliner->GetParagraphCount(); ++nPara) + { + EBulletInfo aBulletInfo = pEditOutliner->GetBulletInfo(nPara); + aBulletSizesBefore.push_back(aBulletInfo.aBounds.GetSize()); + } + + // Add a paragraph to trigger a scaling change + rEditView.SetSelection(ESelection(rEditEngine.GetParagraphCount() - 1, EE_TEXTPOS_MAX)); + rEditView.InsertText(u"\nNew"_ustr); + Scheduler::ProcessEventsToIdle(); + + // Delete the paragraph to restore original scaling + sal_Int32 nLastPara = rEditEngine.GetParagraphCount() - 1; + rEditView.SetSelection(ESelection(nLastPara - 1, EE_TEXTPOS_MAX, nLastPara, EE_TEXTPOS_MAX)); + rEditView.DeleteSelected(); + Scheduler::ProcessEventsToIdle(); + + // Scaling should be back to original + CPPUNIT_ASSERT_DOUBLES_EQUAL(pTextObject->GetFontScale(), + rEditEngine.getScalingParameters().fFontY, 1E-4); + CPPUNIT_ASSERT_DOUBLES_EQUAL(pTextObject->GetSpacingScale(), + rEditEngine.getScalingParameters().fSpacingY, 1E-4); + + // Get bullet sizes after scaling was changed and restored + std::vector aBulletSizesAfter; + for (sal_Int32 nPara = 0; nPara < pEditOutliner->GetParagraphCount(); ++nPara) + { + EBulletInfo aBulletInfo = pEditOutliner->GetBulletInfo(nPara); + aBulletSizesAfter.push_back(aBulletInfo.aBounds.GetSize()); + } + + CPPUNIT_ASSERT_EQUAL(aBulletSizesBefore.size(), aBulletSizesAfter.size()); + + // Bullet sizes should match after scaling round-trip + for (size_t i = 0; i < aBulletSizesBefore.size(); ++i) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE("Paragraph " + std::to_string(i) + + " bullet width changed after scaling round-trip", + aBulletSizesBefore[i].Width(), aBulletSizesAfter[i].Width()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Paragraph " + std::to_string(i) + + " bullet height changed after scaling round-trip", + aBulletSizesBefore[i].Height(), aBulletSizesAfter[i].Height()); + } + pView->SdrEndTextEdit(); + CPPUNIT_ASSERT_EQUAL(false, pView->IsTextEdit()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/ThemeTest.cxx b/sd/qa/unit/ThemeTest.cxx index 59b9b8891854..910971be80d2 100644 --- a/sd/qa/unit/ThemeTest.cxx +++ b/sd/qa/unit/ThemeTest.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -52,12 +53,27 @@ Color GetShapeTextColor(const uno::Reference& xShape) return nColor; } +Color GetShapeColor(const uno::Reference& xShape, + const OUString& rPropertyName) +{ + Color aColor{}; + xShape->getPropertyValue(rPropertyName) >>= aColor; + return aColor; +} + /// Get the solid fill color of xShape. Color GetShapeFillColor(const uno::Reference& xShape) { - Color nColor{}; - xShape->getPropertyValue(u"FillColor"_ustr) >>= nColor; - return nColor; + return GetShapeColor(xShape, u"FillColor"_ustr); +} + +model::ComplexColor GetComplexColor(const uno::Reference& xShape, + const OUString& rPropertyName) +{ + uno::Reference xComplexColor; + CPPUNIT_ASSERT(xShape->getPropertyValue(rPropertyName) >>= xComplexColor); + CPPUNIT_ASSERT(xComplexColor.is()); + return model::color::getFromXComplexColor(xComplexColor); } } // end anonymous namespace @@ -152,6 +168,78 @@ CPPUNIT_TEST_FIXTURE(ThemeTest, testThemeChange) CPPUNIT_ASSERT_EQUAL(Color(0xd5eda2), GetShapeFillColor(xShape5)); } +CPPUNIT_TEST_FIXTURE(ThemeTest, testExplicitShapeColorsRoundtrip) +{ + // A plain shape colour survives a round trip, and so does one that names a theme colour. + createSdImpressDoc("ShapeExplicitColors.fodp"); + + // The shapes inherit from a default drawing style that names a theme colour, and the export + // repeats each shape's fill on a paragraph style of its own that is applied after it. Only an + // exported document has those paragraph styles. + saveAndReload(TestFilter::ODP); + + uno::Reference xPlain(getShapeFromPage(0, 0)); + CPPUNIT_ASSERT_EQUAL(Color(0x7f59ae), GetShapeFillColor(xPlain)); + CPPUNIT_ASSERT_EQUAL(Color(0xe54b89), GetShapeColor(xPlain, u"LineColor"_ustr)); + for (OUString const& rPropertyName : { u"FillComplexColor"_ustr, u"LineComplexColor"_ustr }) + { + auto aComplexColor = GetComplexColor(xPlain, rPropertyName); + CPPUNIT_ASSERT(!aComplexColor.isUsed()); + CPPUNIT_ASSERT(!aComplexColor.isValidThemeType()); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Unknown, aComplexColor.getThemeColorType()); + CPPUNIT_ASSERT(aComplexColor.getTransformations().empty()); + } + + uno::Reference xThemed(getShapeFromPage(1, 0)); + CPPUNIT_ASSERT_EQUAL(Color(0x008000), GetShapeFillColor(xThemed)); + { + auto aComplexColor = GetComplexColor(xThemed, u"FillComplexColor"_ustr); + CPPUNIT_ASSERT(aComplexColor.isValidThemeType()); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent2, aComplexColor.getThemeColorType()); + CPPUNIT_ASSERT(aComplexColor.getTransformations().empty()); + } + + // Accent 3 is grey, so half its luminance is half of each channel. + uno::Reference xShaded(getShapeFromPage(2, 0)); + CPPUNIT_ASSERT_EQUAL(Color(0x404040), GetShapeFillColor(xShaded)); + { + auto aComplexColor = GetComplexColor(xShaded, u"FillComplexColor"_ustr); + CPPUNIT_ASSERT(aComplexColor.isValidThemeType()); + CPPUNIT_ASSERT_EQUAL(model::ThemeColorType::Accent3, aComplexColor.getThemeColorType()); + CPPUNIT_ASSERT_EQUAL(size_t(1), aComplexColor.getTransformations().size()); + CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumMod, + aComplexColor.getTransformations()[0].meType); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5000), aComplexColor.getTransformations()[0].mnValue); + } + + save(TestFilter::PPTX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/slides/slide1.xml"_ustr); + tools::XPath aPath(pXmlDoc.get(), [](xmlXPathContextPtr pContext) { + XmlTestTools::registerOOXMLNamespaces(pContext); + }); + auto pFill = aPath.create("/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:solidFill/a:srgbClr"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pFill->count()); + CPPUNIT_ASSERT_EQUAL(u"7F59AE"_ustr, pFill->attribute("val")); + + auto pLine = aPath.create("/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln/a:solidFill/a:srgbClr"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pLine->count()); + CPPUNIT_ASSERT_EQUAL(u"E54B89"_ustr, pLine->attribute("val")); + + auto pThemed = aPath.create("/p:sld/p:cSld/p:spTree/p:sp[2]/p:spPr/a:solidFill/a:schemeClr"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pThemed->count()); + CPPUNIT_ASSERT_EQUAL(u"accent2"_ustr, pThemed->attribute("val")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pThemed->at(0)->countChildren()); + + auto pShaded = aPath.create("/p:sld/p:cSld/p:spTree/p:sp[3]/p:spPr/a:solidFill/a:schemeClr"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShaded->count()); + CPPUNIT_ASSERT_EQUAL(u"accent3"_ustr, pShaded->attribute("val")); + // A luminance modulation is a percentage on a 0..100000 scale here. + auto pLumMod = aPath.create(pShaded, "/a:lumMod"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pLumMod->count()); + CPPUNIT_ASSERT_EQUAL(u"50000"_ustr, pLumMod->attribute("val")); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/data/ShapeExplicitColors.fodp b/sd/qa/unit/data/ShapeExplicitColors.fodp new file mode 100644 index 000000000000..da9e08136ba2 --- /dev/null +++ b/sd/qa/unit/data/ShapeExplicitColors.fodp @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sd/qa/unit/data/TextFittingBulletEditVsView.odp b/sd/qa/unit/data/TextFittingBulletEditVsView.odp new file mode 100644 index 000000000000..e3e22b320fe6 Binary files /dev/null and b/sd/qa/unit/data/TextFittingBulletEditVsView.odp differ diff --git a/sd/qa/unit/data/draw-image-link.fodp b/sd/qa/unit/data/draw-image-link.fodp new file mode 100644 index 000000000000..8ec14b3658bc --- /dev/null +++ b/sd/qa/unit/data/draw-image-link.fodp @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/sd/qa/unit/data/draw-object-link.fodp b/sd/qa/unit/data/draw-object-link.fodp new file mode 100644 index 000000000000..e65444fb86ba --- /dev/null +++ b/sd/qa/unit/data/draw-object-link.fodp @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/sd/qa/unit/data/linked_ole.fodp b/sd/qa/unit/data/linked_ole.fodp new file mode 100644 index 000000000000..1f73f8cd2b99 --- /dev/null +++ b/sd/qa/unit/data/linked_ole.fodp @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/sd/qa/unit/data/odg/tdf151746.odg b/sd/qa/unit/data/odg/tdf151746.odg new file mode 100644 index 000000000000..25faf3ecf1bf Binary files /dev/null and b/sd/qa/unit/data/odg/tdf151746.odg differ diff --git a/sd/qa/unit/data/odp/16-9.odp b/sd/qa/unit/data/odp/16-9.odp new file mode 100644 index 000000000000..e6f56fffa63f Binary files /dev/null and b/sd/qa/unit/data/odp/16-9.odp differ diff --git a/sd/qa/unit/data/odp/4-3.odp b/sd/qa/unit/data/odp/4-3.odp new file mode 100644 index 000000000000..2ba49033f7ec Binary files /dev/null and b/sd/qa/unit/data/odp/4-3.odp differ diff --git a/sd/qa/unit/data/odp/animation-sound-link.fodp b/sd/qa/unit/data/odp/animation-sound-link.fodp new file mode 100644 index 000000000000..8d9349ba4433 --- /dev/null +++ b/sd/qa/unit/data/odp/animation-sound-link.fodp @@ -0,0 +1,2 @@ + + diff --git a/sd/qa/unit/data/odp/animation-sound-package.fodp b/sd/qa/unit/data/odp/animation-sound-package.fodp new file mode 100644 index 000000000000..758c248d1639 --- /dev/null +++ b/sd/qa/unit/data/odp/animation-sound-package.fodp @@ -0,0 +1,2 @@ + + diff --git a/sd/qa/unit/data/odp/animation-sound-remote.fodp b/sd/qa/unit/data/odp/animation-sound-remote.fodp new file mode 100644 index 000000000000..d9d53a1f8ad6 --- /dev/null +++ b/sd/qa/unit/data/odp/animation-sound-remote.fodp @@ -0,0 +1,2 @@ + + diff --git a/sd/qa/unit/data/odp/clickaction-sound-link.fodp b/sd/qa/unit/data/odp/clickaction-sound-link.fodp new file mode 100644 index 000000000000..994170cb0b28 --- /dev/null +++ b/sd/qa/unit/data/odp/clickaction-sound-link.fodp @@ -0,0 +1,2 @@ + + diff --git a/sd/qa/unit/data/odp/clickaction-sound-remote.fodp b/sd/qa/unit/data/odp/clickaction-sound-remote.fodp new file mode 100644 index 000000000000..825a76d46bbf --- /dev/null +++ b/sd/qa/unit/data/odp/clickaction-sound-remote.fodp @@ -0,0 +1,2 @@ + + diff --git a/sd/qa/unit/data/odp/graphic-clip-poly-placeholder.fodp b/sd/qa/unit/data/odp/graphic-clip-poly-placeholder.fodp new file mode 100644 index 000000000000..46b5bac849dd --- /dev/null +++ b/sd/qa/unit/data/odp/graphic-clip-poly-placeholder.fodp @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + diff --git a/sd/qa/unit/data/odp/picture-placeholder-with-picture-and-text.fodp b/sd/qa/unit/data/odp/picture-placeholder-with-picture-and-text.fodp new file mode 100644 index 000000000000..4225e5998394 --- /dev/null +++ b/sd/qa/unit/data/odp/picture-placeholder-with-picture-and-text.fodp @@ -0,0 +1,34 @@ + + + + + + + + + + + + + iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAEElEQVR42mM4YGAARAwQCgAhzgSBu+38ZAAAAABJRU5ErkJggg== + A caption the author typed onto the picture + + + + + + diff --git a/sd/qa/unit/data/odp/transition-sound-link.fodp b/sd/qa/unit/data/odp/transition-sound-link.fodp new file mode 100644 index 000000000000..0829356da526 --- /dev/null +++ b/sd/qa/unit/data/odp/transition-sound-link.fodp @@ -0,0 +1,2 @@ + + diff --git a/sd/qa/unit/data/odp/transition-sound-remote.fodp b/sd/qa/unit/data/odp/transition-sound-remote.fodp new file mode 100644 index 000000000000..7899f2f4c97d --- /dev/null +++ b/sd/qa/unit/data/odp/transition-sound-remote.fodp @@ -0,0 +1,2 @@ + + diff --git a/sd/qa/unit/data/odp/two-sound-links.fodp b/sd/qa/unit/data/odp/two-sound-links.fodp new file mode 100644 index 000000000000..fa519a787bab --- /dev/null +++ b/sd/qa/unit/data/odp/two-sound-links.fodp @@ -0,0 +1,2 @@ + + diff --git a/sd/qa/unit/data/pdf/threaded_comments.pdf b/sd/qa/unit/data/pdf/threaded_comments.pdf new file mode 100644 index 000000000000..11589e39ba83 --- /dev/null +++ b/sd/qa/unit/data/pdf/threaded_comments.pdf @@ -0,0 +1,42 @@ +%PDF-1.5 +%âãÏÓ +1 0 obj +<> +endobj +2 0 obj +<> +endobj +3 0 obj +<>/Annots[4 0 R 5 0 R 6 0 R 7 0 R 8 0 R]>> +endobj +4 0 obj +<> +endobj +5 0 obj +<> +endobj +6 0 obj +<> +endobj +7 0 obj +<> +endobj +8 0 obj +<> +endobj +xref +0 9 +0000000000 65535 f +0000000015 00000 n +0000000060 00000 n +0000000111 00000 n +0000000228 00000 n +0000000351 00000 n +0000000484 00000 n +0000000672 00000 n +0000000827 00000 n +trailer +<> +startxref +996 +%%EOF diff --git a/sd/qa/unit/data/ppsx/tdf114443-6.ppsx b/sd/qa/unit/data/ppsx/tdf114443-6.ppsx new file mode 100644 index 000000000000..3f1765c6df40 Binary files /dev/null and b/sd/qa/unit/data/ppsx/tdf114443-6.ppsx differ diff --git a/sd/qa/unit/data/pptx/animation-sound-embedded.pptx b/sd/qa/unit/data/pptx/animation-sound-embedded.pptx new file mode 100644 index 000000000000..4839de01ef75 Binary files /dev/null and b/sd/qa/unit/data/pptx/animation-sound-embedded.pptx differ diff --git a/sd/qa/unit/data/pptx/animation-sound-external.pptx b/sd/qa/unit/data/pptx/animation-sound-external.pptx new file mode 100644 index 000000000000..dafbd226a648 Binary files /dev/null and b/sd/qa/unit/data/pptx/animation-sound-external.pptx differ diff --git a/sd/qa/unit/data/pptx/bullet-indent.pptx b/sd/qa/unit/data/pptx/bullet-indent.pptx new file mode 100644 index 000000000000..381f8e67ee90 Binary files /dev/null and b/sd/qa/unit/data/pptx/bullet-indent.pptx differ diff --git a/sd/qa/unit/data/pptx/connector-shape-animations.pptx b/sd/qa/unit/data/pptx/connector-shape-animations.pptx new file mode 100644 index 000000000000..2fc2cee6af20 Binary files /dev/null and b/sd/qa/unit/data/pptx/connector-shape-animations.pptx differ diff --git a/sd/qa/unit/data/pptx/content-placeholder-cases.pptx b/sd/qa/unit/data/pptx/content-placeholder-cases.pptx new file mode 100644 index 000000000000..9f6201145adf Binary files /dev/null and b/sd/qa/unit/data/pptx/content-placeholder-cases.pptx differ diff --git a/sd/qa/unit/data/pptx/custgeom-nofill-path.pptx b/sd/qa/unit/data/pptx/custgeom-nofill-path.pptx new file mode 100644 index 000000000000..62069d69d638 Binary files /dev/null and b/sd/qa/unit/data/pptx/custgeom-nofill-path.pptx differ diff --git a/sd/qa/unit/data/pptx/custgeom-overlapping-contours.pptx b/sd/qa/unit/data/pptx/custgeom-overlapping-contours.pptx new file mode 100644 index 000000000000..12bb18e56a09 Binary files /dev/null and b/sd/qa/unit/data/pptx/custgeom-overlapping-contours.pptx differ diff --git a/sd/qa/unit/data/pptx/custgeom-placeholder.pptx b/sd/qa/unit/data/pptx/custgeom-placeholder.pptx new file mode 100644 index 000000000000..fdf93ded644e Binary files /dev/null and b/sd/qa/unit/data/pptx/custgeom-placeholder.pptx differ diff --git a/sd/qa/unit/data/pptx/forum-mso-de-138303.pptx b/sd/qa/unit/data/pptx/forum-mso-de-138303.pptx new file mode 100644 index 000000000000..3117ac2ea072 Binary files /dev/null and b/sd/qa/unit/data/pptx/forum-mso-de-138303.pptx differ diff --git a/sd/qa/unit/data/pptx/hidden_group_shape.pptx b/sd/qa/unit/data/pptx/hidden_group_shape.pptx new file mode 100644 index 000000000000..fc89fb1d7df6 Binary files /dev/null and b/sd/qa/unit/data/pptx/hidden_group_shape.pptx differ diff --git a/sd/qa/unit/data/pptx/layout-clrmap-override.pptx b/sd/qa/unit/data/pptx/layout-clrmap-override.pptx new file mode 100644 index 000000000000..aa87549f9e9c Binary files /dev/null and b/sd/qa/unit/data/pptx/layout-clrmap-override.pptx differ diff --git a/sd/qa/unit/data/pptx/layout-own-background.pptx b/sd/qa/unit/data/pptx/layout-own-background.pptx new file mode 100644 index 000000000000..dd0d69c645d9 Binary files /dev/null and b/sd/qa/unit/data/pptx/layout-own-background.pptx differ diff --git a/sd/qa/unit/data/pptx/master-and-eleven-layouts.pptx b/sd/qa/unit/data/pptx/master-and-eleven-layouts.pptx new file mode 100644 index 000000000000..5aeb1b84969a Binary files /dev/null and b/sd/qa/unit/data/pptx/master-and-eleven-layouts.pptx differ diff --git a/sd/qa/unit/data/pptx/master-bg-color.pptx b/sd/qa/unit/data/pptx/master-bg-color.pptx new file mode 100644 index 000000000000..e79e2c26d8cf Binary files /dev/null and b/sd/qa/unit/data/pptx/master-bg-color.pptx differ diff --git a/sd/qa/unit/data/pptx/media-placeholder.pptx b/sd/qa/unit/data/pptx/media-placeholder.pptx new file mode 100644 index 000000000000..92b84e06a53d Binary files /dev/null and b/sd/qa/unit/data/pptx/media-placeholder.pptx differ diff --git a/sd/qa/unit/data/pptx/pass/tdf173266.pptx b/sd/qa/unit/data/pptx/pass/tdf173266.pptx new file mode 100644 index 000000000000..f5b3c7e3e61f Binary files /dev/null and b/sd/qa/unit/data/pptx/pass/tdf173266.pptx differ diff --git a/sd/qa/unit/data/pptx/pass/tdf173267.pptx b/sd/qa/unit/data/pptx/pass/tdf173267.pptx new file mode 100644 index 000000000000..e3bf4711050d Binary files /dev/null and b/sd/qa/unit/data/pptx/pass/tdf173267.pptx differ diff --git a/sd/qa/unit/data/pptx/pic-placeholder-with-text.pptx b/sd/qa/unit/data/pptx/pic-placeholder-with-text.pptx new file mode 100644 index 000000000000..e79923348421 Binary files /dev/null and b/sd/qa/unit/data/pptx/pic-placeholder-with-text.pptx differ diff --git a/sd/qa/unit/data/pptx/picture-placeholder-custom-prompt.pptx b/sd/qa/unit/data/pptx/picture-placeholder-custom-prompt.pptx new file mode 100644 index 000000000000..50fe4d87c407 Binary files /dev/null and b/sd/qa/unit/data/pptx/picture-placeholder-custom-prompt.pptx differ diff --git a/sd/qa/unit/data/pptx/picture-placeholder-one-layout.pptx b/sd/qa/unit/data/pptx/picture-placeholder-one-layout.pptx new file mode 100644 index 000000000000..ccdc7208a375 Binary files /dev/null and b/sd/qa/unit/data/pptx/picture-placeholder-one-layout.pptx differ diff --git a/sd/qa/unit/data/pptx/slide-section-test.pptx b/sd/qa/unit/data/pptx/slide-section-test.pptx new file mode 100644 index 000000000000..47354deb9744 Binary files /dev/null and b/sd/qa/unit/data/pptx/slide-section-test.pptx differ diff --git a/sd/qa/unit/data/pptx/slide-sections.pptx b/sd/qa/unit/data/pptx/slide-sections.pptx new file mode 100644 index 000000000000..780efde2b4d2 Binary files /dev/null and b/sd/qa/unit/data/pptx/slide-sections.pptx differ diff --git a/sd/qa/unit/data/pptx/subtitle-animation-save.pptx b/sd/qa/unit/data/pptx/subtitle-animation-save.pptx new file mode 100644 index 000000000000..cecab51dec41 Binary files /dev/null and b/sd/qa/unit/data/pptx/subtitle-animation-save.pptx differ diff --git a/sd/qa/unit/export-tests-ooxml1.cxx b/sd/qa/unit/export-tests-ooxml1.cxx index a95647297378..7d4086a17825 100644 --- a/sd/qa/unit/export-tests-ooxml1.cxx +++ b/sd/qa/unit/export-tests-ooxml1.cxx @@ -769,7 +769,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testFdo90607) SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage->GetObj(1)); CPPUNIT_ASSERT_MESSAGE("no text object", pTxtObj != nullptr); OutlinerParaObject* pOutlinerParagraphObject = pTxtObj->GetOutlinerParaObject(); - const sal_Int16 nDepth = pOutlinerParagraphObject->GetDepth(0); + const sal_Int16 nDepth = pOutlinerParagraphObject->GetNumberingDepth(0); CPPUNIT_ASSERT_MESSAGE("not equal", nDepth != -1); } @@ -889,7 +889,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testTdf134862) nWritingMode); } -CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testRightToLeftParaghraph) +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testRightToLeftParagraph) { createSdImpressDoc("pptx/rightToLeftParagraph.pptx"); @@ -1022,7 +1022,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testBulletMarginAndIndentation) pNumFmt->GetNumRule().GetLevel(0).GetFirstLineOffset()); } -CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testParaMarginAndindentation) +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testParaMarginAndIndentation) { createSdImpressDoc("pptx/paraMarginAndIndentation.pptx"); @@ -1116,7 +1116,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testTableCellBorder) xCellPropSet->getPropertyValue(u"LeftBorder"_ustr) >>= aBorderLine; // While importing the table cell border line width, it converts EMU->Hmm then divided result by 2. - // To get original value of LineWidth need to multiple by 2. + // To get original value of LineWidth need to multiply by 2. sal_Int32 nLeftBorder = aBorderLine.LineWidth * 2; nLeftBorder = oox::drawingml::convertHmmToEmu(nLeftBorder); CPPUNIT_ASSERT(nLeftBorder); @@ -1227,6 +1227,18 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testCustomXml) std::unique_ptr pStream = parseExportStream(maTempFile.GetURL(), u"ddp/ddpfile.xen"_ustr); CPPUNIT_ASSERT(pStream); + + // customXml item reference must not exist on package level + pRelsDoc = parseExport(u"_rels/.rels"_ustr); + CPPUNIT_ASSERT(pRelsDoc); + assertXPath(pRelsDoc, "/rels:Relationships/rels:Relationship[@Target='../customXml/item1.xml']", + 0); + + // customXml item reference must exist on part level + pRelsDoc = parseExport(u"ppt/_rels/presentation.xml.rels"_ustr); + CPPUNIT_ASSERT(pRelsDoc); + assertXPath(pRelsDoc, "/rels:Relationships/rels:Relationship[@Target='../customXml/item1.xml']", + 1); } CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest1, testTdf94238) diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx index e7482f4be1a6..2cc2cab65b97 100644 --- a/sd/qa/unit/export-tests-ooxml2.cxx +++ b/sd/qa/unit/export-tests-ooxml2.cxx @@ -1325,7 +1325,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testTdf106867) "/p:sld/p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/" "p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:cmd/" "p:cBhvr/p:tgtEl/p:spTgt", - "spid", u"61"); + "spid", u"67"); } CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testTdf112280) @@ -1612,16 +1612,20 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testSmartartRotation2) save(TestFilter::PPTX); + // NOTE: adapted sp[4] to sp[3] since disconnectFromSdrObjGroup does now + // remove a BGObject if no Line/FillStyle is used at all, which is + // correct. This was the 1st (empty) shape in ungrouped representation, + // so tested info moved to sp[3] xmlDocUniquePtr pXmlDocContent = parseExport(u"ppt/slides/slide1.xml"_ustr); assertXPathContent(pXmlDocContent, - "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[4]/p:txBody/a:p/a:r/a:t", u"Text"); - assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[4]/p:txBody/a:bodyPr", "rot", + "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[3]/p:txBody/a:p/a:r/a:t", u"Text"); + assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[3]/p:txBody/a:bodyPr", "rot", u"10800000"); double dX = getXPath(pXmlDocContent, - "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[4]/p:spPr/a:xfrm/a:off", "x") + "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[3]/p:spPr/a:xfrm/a:off", "x") .toDouble(); double dY = getXPath(pXmlDocContent, - "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[4]/p:spPr/a:xfrm/a:off", "y") + "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[3]/p:spPr/a:xfrm/a:off", "y") .toDouble(); CPPUNIT_ASSERT_DOUBLES_EQUAL(2276280.0, dX, dX * .001); CPPUNIT_ASSERT_DOUBLES_EQUAL(3158280.0, dY, dY * .001); diff --git a/sd/qa/unit/export-tests-ooxml3.cxx b/sd/qa/unit/export-tests-ooxml3.cxx index 4f1d847d13d8..dbfbc3747961 100644 --- a/sd/qa/unit/export-tests-ooxml3.cxx +++ b/sd/qa/unit/export-tests-ooxml3.cxx @@ -9,8 +9,10 @@ #include #include "sdmodeltestbase.hxx" +#include #include #include +#include #include #include #include @@ -453,6 +455,70 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf115005_FallBack_Images_Off) CPPUNIT_ASSERT_EQUAL(0, nPNGFiles); } +namespace +{ +struct SvgPngCounts +{ + int mnSvg = 0; + int mnPng = 0; +}; + +SvgPngCounts +countSvgAndPngInPictures(const css::uno::Reference& xZip) +{ + SvgPngCounts aCounts; + const uno::Sequence aNames = xZip->getElementNames(); + for (OUString const& rName : aNames) + { + if (!rName.startsWith("Pictures/")) + continue; + if (rName.endsWith(".svg")) + aCounts.mnSvg++; + else if (rName.endsWith(".png")) + aCounts.mnPng++; + } + return aCounts; +} +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testSvgPngFallbackOdf14) +{ + // SvgImageTest.odp contains an SVG primary with a PNG fallback. Saving as + // ODF 1.4 (the default) must keep the SVG and drop the PNG fallback, since + // ODF 1.4 readers handle SVG natively. + ScopedConfigValue aConfig(true); + + createSdImpressDoc("odp/SvgImageTest.odp"); + save(TestFilter::ODP); + + uno::Reference xZip + = packages::zip::ZipFileAccess::createWithURL(m_xContext, maTempFile.GetURL()); + + const SvgPngCounts aCounts = countSvgAndPngInPictures(xZip); + CPPUNIT_ASSERT_EQUAL(1, aCounts.mnSvg); + CPPUNIT_ASSERT_EQUAL(0, aCounts.mnPng); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testSvgPngFallbackOdf13) +{ + // The same document saved as ODF 1.3 must still emit the PNG fallback so + // that older readers without SVG support can still display the image. + comphelper::ScopeGuard aGuard([]() { SetODFDefaultVersion(SvtSaveOptions::ODFVER_LATEST); }); + SetODFDefaultVersion(SvtSaveOptions::ODFDefaultVersion::ODFVER_013); + + ScopedConfigValue aConfig(true); + + createSdImpressDoc("odp/SvgImageTest.odp"); + save(TestFilter::ODP); + + uno::Reference xZip + = packages::zip::ZipFileAccess::createWithURL(m_xContext, maTempFile.GetURL()); + + const SvgPngCounts aCounts = countSvgAndPngInPictures(xZip); + CPPUNIT_ASSERT_EQUAL(1, aCounts.mnSvg); + CPPUNIT_ASSERT_EQUAL(1, aCounts.mnPng); +} + CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf118806) { createSdImpressDoc("odp/tdf118806.odp"); @@ -962,8 +1028,11 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf148478_transitionMusic) uno::Reference xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL()); - CPPUNIT_ASSERT( - xNameAccess->hasByName(u"ppt/media/audio_ac976207e31e8b69f8b3c3d981097f3d.wav"_ustr)); + uno::Reference xStrm; + xNameAccess->getByName(u"ppt/media/audio_ac976207e31e8b69f8b3c3d981097f3d.wav"_ustr) >>= xStrm; + CPPUNIT_ASSERT(xStrm.is()); + sal_Int32 nSize = xStrm->available(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(122448), nSize); xmlDocUniquePtr pXmlDocRels = parseExport(u"ppt/slides/_rels/slide1.xml.rels"_ustr); assertXPath(pXmlDocRels, diff --git a/sd/qa/unit/export-tests-ooxml4.cxx b/sd/qa/unit/export-tests-ooxml4.cxx index bb4ff075e941..97116c2dd5f8 100644 --- a/sd/qa/unit/export-tests-ooxml4.cxx +++ b/sd/qa/unit/export-tests-ooxml4.cxx @@ -9,6 +9,9 @@ #include "sdmodeltestbase.hxx" #include +#include +#include +#include #include #include #include @@ -19,21 +22,29 @@ #include #include +#include #include #include +#include +#include +#include #include #include #include #include +#include #include #include #include +#include #include #include #include #include +#include +#include class SdOOXMLExportTest4 : public SdModelTestBase { @@ -66,6 +77,81 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf160591) assertXPath(pXmlDoc2, "/p:sldMaster/p:cSld/p:bg/p:bgPr/a:solidFill/a:schemeClr", "val", u"dk1"); } +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testMasterBackgroundColor) +{ + createSdImpressDoc("pptx/master-bg-color.pptx"); + save(TestFilter::PPTX); + + xmlDocUniquePtr pMaster = parseExport(u"ppt/slideMasters/slideMaster1.xml"_ustr); + assertXPath(pMaster, "/p:sldMaster/p:clrMap", "bg1", u"dk2"); + assertXPath(pMaster, "/p:sldMaster/p:clrMap", "tx1", u"lt2"); + assertXPath(pMaster, "/p:sldMaster/p:clrMap", "bg2", u"lt1"); + assertXPath(pMaster, "/p:sldMaster/p:clrMap", "tx2", u"dk1"); + + // Full slide shape uses placeholder scheme color bg1 with the master's clrMap + // preserved this resolves to theme dk2 + xmlDocUniquePtr pLayout1 = parseExport(u"ppt/slideLayouts/slideLayout1.xml"_ustr); + assertXPath(pLayout1, "/p:sldLayout/p:cSld/p:spTree/p:sp/p:spPr/a:solidFill/a:schemeClr", "val", + u"bg1"); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testGraphicPlaceholderHiddenAsMaster) +{ + // A layout's picture placeholder is imported onto a master page, where it is a template for + // the instances the slides carry themselves. It must not paint on them, or a slide shows two + // placeholders - the slide's own, movable one, and the layout's immovable one behind it. + createSdImpressDoc("pptx/picture-placeholder-custom-prompt.pptx"); + + SdXImpressDocument* pXImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + SdDrawDocument* pDoc = pXImpressDocument->GetDoc(); + CPPUNIT_ASSERT_MESSAGE("no document", pDoc != nullptr); + + // Only title, outline and notes placeholders used to be hidden this way. A layout's + // became an outline shape once, which is why it behaved before. + bool bFoundGraphicPresObj = false; + for (sal_uInt16 nMaster = 0; nMaster < pDoc->GetMasterSdPageCount(PageKind::Standard); + ++nMaster) + { + SdPage* pMasterPage = pDoc->GetMasterSdPage(nMaster, PageKind::Standard); + for (size_t nObj = 0; nObj < pMasterPage->GetObjCount(); ++nObj) + { + // A picture placeholder is an empty SdrGrafObj; a graphic the document actually + // contains is not an empty presentation object. + SdrObject* pObj = pMasterPage->GetObj(nObj); + if (dynamic_cast(pObj) == nullptr || !pObj->IsEmptyPresObj()) + continue; + + bFoundGraphicPresObj = true; + CPPUNIT_ASSERT_MESSAGE("a master's picture placeholder would paint onto the slides", + pObj->IsNotVisibleAsMaster()); + } + } + CPPUNIT_ASSERT_MESSAGE("no picture placeholder on any master page", bFoundGraphicPresObj); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testLayoutClrMapOvr) +{ + // Test that slide layout color map override (clrMapOvr) is preserved on round-trip + createSdImpressDoc("pptx/layout-clrmap-override.pptx"); + save(TestFilter::PPTX); + + // Verify the slide layout has clrMapOvr with overrideClrMapping + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/slideLayouts/slideLayout1.xml"_ustr); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "bg1", u"dk1"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "tx1", u"lt1"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "bg2", u"dk2"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "tx2", u"lt2"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "accent1", u"accent1"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "accent2", u"accent2"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "accent3", u"accent3"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "accent4", u"accent4"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "accent5", u"accent5"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "accent6", u"accent6"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "hlink", u"hlink"); + assertXPath(pXmlDoc, "/p:sldLayout/p:clrMapOvr/a:overrideClrMapping", "folHlink", u"folHlink"); +} + CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testSmartArtPreserve) { createSdImpressDoc("pptx/smartart-preserve.pptx"); @@ -841,15 +927,153 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf140912_PicturePlaceholder) // Given a graphic placeholder with a custom prompt: createSdImpressDoc("pptx/tdfpictureplaceholder.pptx"); - uno::Reference xShapeProps(getShapeFromPage(0, 0)); - bool isEmptyPresentationObject = false; - // Without the fix, it would not be imported as empty presentation object; - // the text would be treated as its content. - xShapeProps->getPropertyValue(u"IsEmptyPresentationObject"_ustr) >>= isEmptyPresentationObject; - CPPUNIT_ASSERT(isEmptyPresentationObject); + awt::Size aSizeBefore; + awt::Point aPosBefore; + { + uno::Reference xShapeProps(getShapeFromPage(0, 0)); + bool isEmptyPresentationObject = false; + // Without the fix, it would not be imported as empty presentation object; + // the text would be treated as its content. + xShapeProps->getPropertyValue(u"IsEmptyPresentationObject"_ustr) + >>= isEmptyPresentationObject; + CPPUNIT_ASSERT(isEmptyPresentationObject); - // If we supported custom prompt text, here we would also test "String" property, - // which would be equal to "Insert Image". See first tests: testCustomPromptTexts + // The slide-side shape does not carry the layout's prompt; only the layout placeholder + // does. See testPicturePlaceholderCustomPromptText for the prompt itself. + + auto xShape = xShapeProps.queryThrow(); + aSizeBefore = xShape->getSize(); + aPosBefore = xShape->getPosition(); + } + + // The picture placeholder must round-trip with its size and position, and must remain visible. + saveAndReload(TestFilter::PPTX); + + { + // After reload, the saved markup should be with and its own + // geometry. Relying on the layout to supply the geometry instead left the placeholder + // 0x0 whenever the slide's layout placeholder could not be resolved on reimport. + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/slides/slide1.xml"_ustr); + assertXPath(pXmlDoc, "/p:sld/p:cSld/p:spTree/p:sp/p:nvSpPr/p:nvPr/p:ph", "type", u"pic"); + assertXPath(pXmlDoc, "/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:xfrm/a:ext", "cx", u"6635520"); + + uno::Reference xShapeProps(getShapeFromPage(0, 0)); + bool bEmpty = false; + xShapeProps->getPropertyValue(u"IsEmptyPresentationObject"_ustr) >>= bEmpty; + CPPUNIT_ASSERT(bEmpty); + + auto xShape = xShapeProps.queryThrow(); + const awt::Size aSizeAfter(xShape->getSize()); + const awt::Point aPosAfter(xShape->getPosition()); + + // Size and position must survive the round-trip. Without proper layout inheritance in the + // reimport path the shape would be 0x0 at (0, 0) and visually disappear. + CPPUNIT_ASSERT_DOUBLES_EQUAL(aSizeBefore.Width, aSizeAfter.Width, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aSizeBefore.Height, aSizeAfter.Height, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aPosBefore.X, aPosAfter.X, 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aPosBefore.Y, aPosAfter.Y, 1); + } +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testNoPicPlaceholderOnSlideMaster) +{ + // Given a deck whose only layout carries a picture placeholder, so on import the placeholder + // lands on the Impress master page: + createSdImpressDoc("pptx/tdfpictureplaceholder.pptx"); + save(TestFilter::PPTX); + + // A slide master takes only title, body, dt, ftr and sldNum placeholders. Without the + // accompanying fix the master carried and PowerPoint refused to open the + // saved file at all, reporting it as corrupted and unreadable. + xmlDocUniquePtr pMaster = parseExport(u"ppt/slideMasters/slideMaster1.xml"_ustr); + assertXPath(pMaster, "/p:sldMaster/p:cSld/p:spTree/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='pic']", 0); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testPicPlaceholderMovedToLayout) +{ + // Given a deck of one master and one layout, so the master page's own shapes go into the + // p:sldMaster part and the layout gets none of them: + createSdImpressDoc("pptx/picture-placeholder-one-layout.pptx"); + save(TestFilter::PPTX); + + // The picture placeholder still goes on the layout, which is where a slide resolves what it + // inherits. Without the accompanying fix it had nowhere to go but the slide master, which may + // not carry one, and PowerPoint refused to open the file. + xmlDocUniquePtr pLayout = parseExportedLayoutNamed(u"Picture placeholder"); + assertXPath(pLayout, "/p:sldLayout/p:cSld/p:spTree/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='pic']", 1); + + xmlDocUniquePtr pMaster2 = parseExport(u"ppt/slideMasters/slideMaster1.xml"_ustr); + assertXPath(pMaster2, "/p:sldMaster/p:cSld/p:spTree/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='pic']", 0); + + xmlDocUniquePtr pSlide = parseExport(u"ppt/slides/slide1.xml"_ustr); + assertXPath(pSlide, "/p:sld/p:cSld/p:spTree/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='pic']", 1); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testSlideShowsMasterCustomPrompt) +{ + // Given a layout whose picture placeholder authored a prompt: + createSdImpressDoc("pptx/picture-placeholder-custom-prompt.pptx"); + + // The slide's own placeholder shows it too. PlaceholderText is what the user reads on the + // slide; without the accompanying fix the slide ignored the layout and showed Impress's own + // resource string instead, so the layout and the slide disagreed about the same placeholder. + // The placeholder is looked up by what it is, not by where it sits: which shape comes first on + // the slide is not what this test is about. + SdPage* pPage = getSdDocShell()->GetDoc()->GetSdPage(0, PageKind::Standard); + SdrObject* pPlaceholder = pPage->GetPresObj(PresObjKind::Graphic); + CPPUNIT_ASSERT_MESSAGE("no picture placeholder on the slide", pPlaceholder); + auto xShapeProps = GetXShapeForSdrObject(pPlaceholder).queryThrow(); + + OUString aPlaceholderText; + CPPUNIT_ASSERT(xShapeProps->getPropertyValue(u"PlaceholderText"_ustr) >>= aPlaceholderText); + CPPUNIT_ASSERT_EQUAL(u"Custom prompt to insert an image"_ustr, aPlaceholderText); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testMediaPlaceholder) +{ + // Given a deck with an empty media placeholder on a slide, inheriting from its layout: + createSdImpressDoc("pptx/media-placeholder.pptx"); + save(TestFilter::PPTX); + + // It keeps its placeholder identity on both levels. Without the accompanying fix the layout + // one degraded to , and the slide one was written as a real media object, + // a with the internal placeholder icon embedded as its . The layout + // carries the header and footer placeholders too, so select the media one. + xmlDocUniquePtr pLayout = parseExportedLayoutNamed(u"Media placeholder"); + assertXPath(pLayout, "/p:sldLayout/p:cSld/p:spTree/p:sp[p:nvSpPr/p:nvPr/p:ph/@type='media']", + 1); + + xmlDocUniquePtr pSlide = parseExport(u"ppt/slides/slide1.xml"_ustr); + assertXPath(pSlide, "/p:sld/p:cSld/p:spTree/p:sp[p:nvSpPr/p:nvPr/p:ph/@type='media']", 1); + assertXPath(pSlide, "/p:sld/p:cSld/p:spTree/p:pic", 0); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testPicturePlaceholderCustomPromptText) +{ + // Given one layout whose picture placeholder authored a prompt, and another whose + // picture placeholder authored none: + createSdImpressDoc("pptx/picture-placeholder-custom-prompt.pptx"); + save(TestFilter::PPTX); + + static constexpr OString aPicPlaceholder( + "/p:sldLayout/p:cSld/p:spTree/p:sp[p:nvSpPr/p:nvPr/p:ph/@type='pic']"_ostr); + + // The authored prompt survives. Without the accompanying fix it was replaced by Impress's + // own localized resource, since a slide layout arrives as a master page and the shown text + // was only ever set off a master. + xmlDocUniquePtr pAuthored = parseExportedLayoutNamed(u"Picture placeholder, custom prompt"); + assertXPath(pAuthored, aPicPlaceholder + "/p:nvSpPr/p:nvPr/p:ph", "hasCustomPrompt", u"1"); + assertXPathContent(pAuthored, aPicPlaceholder + "/p:txBody/a:p/a:r/a:t", + u"Custom prompt to insert an image"); + + // The one with no authored prompt writes no text, rather than that same resource string + // written out as if the document had contained it. Its body properties stay: a reader needs + // the insets and the anchor whether or not there is anything in the box yet. + xmlDocUniquePtr pDefault = parseExportedLayoutNamed(u"Picture with Caption"); + assertXPath(pDefault, aPicPlaceholder, 1); + assertXPath(pDefault, aPicPlaceholder + "/p:txBody/a:bodyPr", 1); + assertXPath(pDefault, aPicPlaceholder + "/p:txBody/a:p", 1); + assertXPath(pDefault, aPicPlaceholder + "/p:txBody/a:p/a:r", 0); } CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testEnhancedPathViewBox) @@ -1131,7 +1355,13 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf152436) CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testLinkedOLE) { - createSdImpressDoc("odp/linked_ole.odp"); + // The linked OLE object needs its link completed during load so it can + // be exported. Use FULL_UPDATE since the default test mode defers links. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::FULL_UPDATE)), + }; + loadFromFile(u"odp/linked_ole.odp", aParams); save(TestFilter::PPTX); @@ -1533,7 +1763,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testConvertWithMasterDeduplication) = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL()); - // For each slide check that it's layout exists + // For each slide check that its layout exists for (int i = 1; i <= 4; ++i) { xmlDocUniquePtr pXmlDocRels @@ -1600,21 +1830,13 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCustomPromptTexts) pTxtObj->GetObjIdentifier()); const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject(); OUString aText = aEdit.GetText(0); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text!", aText, u"Click to add Text"_ustr); - /* TODO: handle subtitle shape: see tdf#112557 workaround - - Expected: Click to edit customized Master Subtitle style - - Actual : Click to add Text - - Wrong placeholder text! - */ + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text!", + u"Click to edit customized Master Subtitle style"_ustr, aText); auto xShapeProps(getShapeFromPage(0, 0)); CPPUNIT_ASSERT(xShapeProps->getPropertyValue(u"CustomPromptText"_ustr) >>= aText); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text was set!", aText, u""_ustr); - /* TODO: handle subtitle shape: see tdf#112557 workaround - - Expected: Click to edit customized Master Subtitle style - - Actual : - - Wrong placeholder text was set! - */ + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text was set!", + u"Click to edit customized Master Subtitle style"_ustr, aText); } { @@ -1624,12 +1846,12 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCustomPromptTexts) pTxtObj->GetObjIdentifier()); const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject(); OUString aText = aEdit.GetText(0); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text!", aText, u"Custom Title 1"_ustr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text!", u"Custom Title 1"_ustr, aText); auto xShapeProps(getShapeFromPage(1, 0)); CPPUNIT_ASSERT(xShapeProps->getPropertyValue(u"CustomPromptText"_ustr) >>= aText); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text was set!", aText, - u"Custom Title 1"_ustr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text was set!", u"Custom Title 1"_ustr, + aText); } const SdrPage* pPage2 = GetPage(3); @@ -1641,12 +1863,12 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCustomPromptTexts) pTxtObj->GetObjIdentifier()); const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject(); OUString aText = aEdit.GetText(0); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text!", aText, u"Text placeholder"_ustr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text!", u"Text placeholder"_ustr, aText); auto xShapeProps(getShapeFromPage(0, 1)); CPPUNIT_ASSERT(xShapeProps->getPropertyValue(u"CustomPromptText"_ustr) >>= aText); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text was set!", aText, - u"Text placeholder"_ustr); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text was set!", u"Text placeholder"_ustr, + aText); } } @@ -1828,6 +2050,15 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testtdf169496_hidden_graphic) CPPUNIT_FAIL("Names of graphics is incorrect"); } +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testHiddenGroupShape) +{ + createSdImpressDoc("pptx/hidden_group_shape.pptx"); + save(TestFilter::PPTX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/slides/slide1.xml"_ustr); + assertXPath(pXmlDoc, "/p:sld/p:cSld/p:spTree/p:grpSp/p:nvGrpSpPr/p:cNvPr", "hidden", u"1"); +} + CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testtdf169825_vertical_layouts) { createSdImpressDoc("pptx/tdf169825_vertical_layouts.pptx"); @@ -2023,6 +2254,366 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf169559) "val", u"1701"); } +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf114443_PPSX) +{ + createSdImpressDoc("ppsx/tdf114443-6.ppsx"); + save(TestFilter::PPSX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"[Content_Types].xml"_ustr); + + // Without the fix, this would have been: + // application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml + // which means the file loses its slideshow/autoplay nature and PowerPoint rejects it. + assertXPath(pXmlDoc, + "/ContentType:Types/ContentType:Override[@PartName='/ppt/presentation.xml']", + "ContentType", + u"application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml"); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testConnectorShapeAnimationTarget) +{ + createSdImpressDoc("pptx/connector-shape-animations.pptx"); + save(TestFilter::PPTX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/slides/slide1.xml"_ustr); + + const OUString sConnectorId = getXPath( + pXmlDoc, "/p:sld/p:cSld/p:spTree/p:cxnSp/p:nvCxnSpPr/p:cNvCxnSpPr/a:stCxn", "id"); + + const OUString sShapeId = getXPath( + pXmlDoc, "/p:sld/p:cSld/p:spTree/p:graphicFrame/p:nvGraphicFramePr/p:cNvPr", "id"); + + // Check connector and shape both have the same ID + CPPUNIT_ASSERT_EQUAL_MESSAGE("Connector and the shape doesn't have the same ID", sConnectorId, + sShapeId); + + // Check animation spid matches ShapeId + assertXPath(pXmlDoc, + "/p:sld/p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/" + "p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par[2]/p:cTn/p:childTnLst/p:set/" + "p:cBhvr/p:tgtEl/p:spTgt", + "spid", sShapeId); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testChartExExport) +{ + createSdImpressDoc("pptx/forum-mso-de-138303.pptx"); + save(TestFilter::PPTX); + + xmlDocUniquePtr pDoc = parseExport(u"ppt/slides/slide1.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + + const OString sPath1 = "/p:sld/p:cSld/p:spTree/mc:AlternateContent/mc:Fallback"_ostr; + assertXPath(pDoc, sPath1 + "/xdr:sp"_ostr, 0); + assertXPath(pDoc, sPath1 + "/p:sp"_ostr, 1); + assertXPath(pDoc, sPath1 + "/p:sp/p:nvSpPr/p:nvPr"_ostr, 1); + + pDoc = parseExport(u"ppt/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/cx:chartSpace/c:date1904", 0); +} + +// 1. Open PPTX with sections, re-export to PPTX, verify sections preserved +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testSlideSectionsPPTXImport) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + save(TestFilter::PPTX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/presentation.xml"_ustr); + + static constexpr OString sPath = "/p:presentation/p:extLst/p:ext/p14:sectionLst"_ostr; + assertXPath(pXmlDoc, sPath + "/p14:section", 3); + assertXPath(pXmlDoc, sPath + "/p14:section[1]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/p14:section[2]", "name", u"Section-2"); + assertXPath(pXmlDoc, sPath + "/p14:section[3]", "name", u"Section-3"); + assertXPath(pXmlDoc, sPath + "/p14:section[1]/p14:sldIdLst/p14:sldId", 4); + assertXPath(pXmlDoc, sPath + "/p14:section[2]/p14:sldIdLst/p14:sldId", 7); + assertXPath(pXmlDoc, sPath + "/p14:section[3]/p14:sldIdLst/p14:sldId", 2); + + // GUIDs preserved + for (sal_Int32 i = 1; i <= 3; ++i) + { + OUString sId = getXPath(pXmlDoc, sPath + "/p14:section[" + OString::number(i) + "]", "id"); + CPPUNIT_ASSERT(!sId.isEmpty()); + CPPUNIT_ASSERT(sId.startsWith("{")); + } + + // Slide IDs non-zero + OUString sSldId = getXPath(pXmlDoc, sPath + "/p14:section[1]/p14:sldIdLst/p14:sldId[1]", "id"); + CPPUNIT_ASSERT(sSldId.toInt32() > 0); +} + +// 2. Export PPTX with sections to ODP +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testSlideSectionsPPTXToODP) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + skipValidation(); + save(TestFilter::ODP); + + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + + static constexpr OString sPath + = "/office:document-content/office:body/office:presentation/loext:section-list"_ostr; + assertXPath(pXmlDoc, sPath + "/loext:section", 3); + assertXPath(pXmlDoc, sPath + "/loext:section[1]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/loext:section[2]", "name", u"Section-2"); + assertXPath(pXmlDoc, sPath + "/loext:section[3]", "name", u"Section-3"); + assertXPath(pXmlDoc, sPath + "/loext:section[1]/loext:section-slide", 4); + assertXPath(pXmlDoc, sPath + "/loext:section[2]/loext:section-slide", 7); + assertXPath(pXmlDoc, sPath + "/loext:section[3]/loext:section-slide", 2); +} + +// 3. Open ODP with sections (PPTX -> ODP -> reload ODP) +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testSlideSectionsODPImport) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + skipValidation(); + saveAndReload(TestFilter::ODP); + + // Verify the in-memory model loaded from ODP + auto* pXImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + SdDrawDocument* pDoc = pXImpressDocument->GetDoc(); + CPPUNIT_ASSERT(pDoc); + + sd::SlideSectionManager& rMgr = pDoc->GetSectionManager(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rMgr.GetSectionCount()); + CPPUNIT_ASSERT_EQUAL(u"Section-1"_ustr, rMgr.GetSection(0).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-2"_ustr, rMgr.GetSection(1).maName); + CPPUNIT_ASSERT_EQUAL(u"Section-3"_ustr, rMgr.GetSection(2).maName); +} + +// 4. Export ODP with sections to PPTX +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testSlideSectionsODPToPPTX) +{ + createSdImpressDoc("pptx/slide-section-test.pptx"); + skipValidation(); + saveAndReload(TestFilter::ODP); + save(TestFilter::PPTX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/presentation.xml"_ustr); + + static constexpr OString sPath = "/p:presentation/p:extLst/p:ext/p14:sectionLst"_ostr; + assertXPath(pXmlDoc, sPath + "/p14:section", 3); + assertXPath(pXmlDoc, sPath + "/p14:section[1]", "name", u"Section-1"); + assertXPath(pXmlDoc, sPath + "/p14:section[2]", "name", u"Section-2"); + assertXPath(pXmlDoc, sPath + "/p14:section[3]", "name", u"Section-3"); + assertXPath(pXmlDoc, sPath + "/p14:section[1]/p14:sldIdLst/p14:sldId", 4); + assertXPath(pXmlDoc, sPath + "/p14:section[2]/p14:sldIdLst/p14:sldId", 7); + assertXPath(pXmlDoc, sPath + "/p14:section[3]/p14:sldIdLst/p14:sldId", 2); + + // Slide IDs non-zero after ODP round-trip + OUString sSldId = getXPath(pXmlDoc, sPath + "/p14:section[1]/p14:sldIdLst/p14:sldId[1]", "id"); + CPPUNIT_ASSERT(sSldId.toInt32() > 0); + + // GUIDs survive ODP round-trip (generated if missing) + for (sal_Int32 i = 1; i <= 3; ++i) + { + OUString sId = getXPath(pXmlDoc, sPath + "/p14:section[" + OString::number(i) + "]", "id"); + CPPUNIT_ASSERT(!sId.isEmpty()); + } +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCool16078_placeholderKeepsItsOutline) +{ + // Given a layout whose picture placeholder is clipped to an outline of two elements: + // a frame with two holes, one of them round, and a second path holding a triangle that crosses + // the round one: + createSdImpressDoc("pptx/custgeom-placeholder.pptx"); + save(TestFilter::PPTX); + + // The outline is written back as the placeholder's own geometry. Without it the placeholder + // saved as a plain rectangle, and its fill then hid both holes and what showed through. + xmlDocUniquePtr pLayout = parseExportedLayoutNamed(u"Picture placeholder, clipped outline"); + OString aPath + = "//p:sp[p:nvSpPr/p:nvPr/p:ph/@type='pic']/p:spPr/a:custGeom/a:pathLst/a:path"_ostr; + assertXPath(pLayout, aPath, 1); + // Three contours in one path, which is what subtracts the holes from the frame - the same three + // the ODF side writes. The second path is not one of them: it is filled rather than cut out, so + // the triangle it holds took a piece of the round hole back instead of adding a contour. + assertXPath(pLayout, aPath + "/a:moveTo", 3); + assertXPath(pLayout, aPath + "/a:close", 3); + // Four sides each for the two rectangles, the closing one included. + assertXPath(pLayout, aPath + "/a:lnTo", 8); + // What is left of the round hole is still curves, not a polygon flattened out of them. + assertXPath(pLayout, aPath + "/a:cubicBezTo", 6); + assertXPath(pLayout, aPath + "/a:cubicBezTo[1]/a:pt", 3); + // The frame's own corner, in the path's coordinates. + assertXPath(pLayout, aPath + "/a:moveTo[1]/a:pt", "x", u"0"); + assertXPath(pLayout, aPath + "/a:moveTo[1]/a:pt", "y", u"0"); + + // The preset rectangle it used to write would have claimed the whole frame. + assertXPath(pLayout, "//p:sp[p:nvSpPr/p:nvPr/p:ph/@type='pic']/p:spPr/a:prstGeom", 0); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCool16080_masterKeepsItsPlaceholders) +{ + // Given a deck of one master and eleven layouts, so one Impress master page stands for the + // whole group: + createSdImpressDoc("pptx/master-and-eleven-layouts.pptx"); + save(TestFilter::PPTX); + + // The master part carries its own placeholders. Without the fix it held a shape tree with + // nothing in it, so PowerPoint offered an empty slide master: nothing to inherit from, and + // an edit meant for every layout had to be repeated on each of them. + xmlDocUniquePtr pMaster = parseExport(u"ppt/slideMasters/slideMaster1.xml"_ustr); + static constexpr OString aTree("/p:sldMaster/p:cSld/p:spTree"_ostr); + assertXPath(pMaster, aTree + "/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='title']", 1); + assertXPath(pMaster, aTree + "/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='dt']", 1); + assertXPath(pMaster, aTree + "/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='ftr']", 1); + assertXPath(pMaster, aTree + "/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='sldNum']", 1); + + // The body comes from the first layout that has one, since the page standing for the group is + // the Title Slide layout and has none. That layout inherits the master's geometry, so the + // placeholder lands where the master put it rather than where a layout would. + assertXPath(pMaster, aTree + "/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='body']", 1); + assertXPath(pMaster, aTree + "/p:sp[p:nvSpPr/p:nvPr/p:ph/@type='body']/p:spPr/a:xfrm/a:off", + "y", u"1825560"); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCool16080_layoutShapesStayOnTheirLayout) +{ + // Given a deck whose first layout paints the whole slide blue, and a slide on another layout, + // which is therefore white: + createSdImpressDoc("pptx/layout-own-background.pptx"); + saveAndReload(TestFilter::PPTX); + + utl::TempFileNamed aPng; + aPng.EnableKillingFile(); + uno::Sequence aFilterData{ + comphelper::makePropertyValue(u"PixelWidth"_ustr, sal_Int32(64)), + comphelper::makePropertyValue(u"PixelHeight"_ustr, sal_Int32(36)) + }; + uno::Sequence aDescriptor{ + comphelper::makePropertyValue(u"URL"_ustr, aPng.GetURL()), + comphelper::makePropertyValue(u"FilterName"_ustr, u"PNG"_ustr), + comphelper::makePropertyValue(u"FilterData"_ustr, aFilterData) + }; + auto xExporter = drawing::GraphicExportFilter::create(getComponentContext()); + xExporter->setSourceDocument(getPage(0).queryThrow()); + xExporter->filter(aDescriptor); + + SvFileStream aStream(aPng.GetURL(), StreamMode::READ); + Bitmap aSlide = vcl::PngImageReader(aStream).read(); + CPPUNIT_ASSERT_EQUAL(Size(64, 36), aSlide.GetSizePixel()); + + // The slide is still white. An imported master and layout collapse onto one Impress master + // page, so the page standing for the group holds the first layout's rectangle - and writing + // that page's shapes into the master part painted it under every slide of the deck. Sample + // the side margins, which no placeholder of this layout reaches. + // Without the fix in place, this test would have failed with + // - Expected: rgba[ffffffff] + // - Actual : rgba[0000ffff] + CPPUNIT_ASSERT_EQUAL(COL_WHITE, aSlide.GetPixelColor(2, 18)); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, aSlide.GetPixelColor(61, 18)); + + // The layout it belongs to still paints it, which is what a slide of that layout inherits. + xmlDocUniquePtr pLayout = parseExportedLayoutNamed(u"Title Slide"); + assertXPath(pLayout, + "/p:sldLayout/p:cSld/p:spTree/p:sp[p:nvSpPr/p:cNvPr/@name='Blue background']" + "/p:spPr/a:solidFill/a:srgbClr", + "val", u"0000FF"); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCool16080_masterKeepsWhatItsLayoutsShare) +{ + // Given a deck of one master that draws a rule of its own across the top of the slide, in + // segments of colour, and seven layouts that draw nothing: + createSdImpressDoc("pptx/tdf157740.pptx"); + saveAndReload(TestFilter::PPTX); + + // The rule is on the slide master, so PowerPoint edits it once for every layout. The import + // gives each of the seven Impress master pages a copy, and the master used to get none. + // Without the fix in place, this test would have failed with + // - Expected: 1 + // - Actual : 0 + xmlDocUniquePtr pMaster = parseExport(u"ppt/slideMasters/slideMaster1.xml"_ustr); + assertXPath(pMaster, + "/p:sldMaster/p:cSld/p:spTree/p:grpSp[p:nvGrpSpPr/p:cNvPr/@name='Group 1']", 1); + + // It moved there rather than being written seven more times: a layout holds the three + // placeholders it inherits and nothing else. + xmlDocUniquePtr pLayout = parseExportedLayoutNamed(u"Title, Content over Content"); + static constexpr OString aLayoutTree("/p:sldLayout/p:cSld/p:spTree"_ostr); + assertXPath(pLayout, aLayoutTree + "/*[not(self::p:nvGrpSpPr) and not(self::p:grpSpPr)]", 3); + assertXPath(pLayout, aLayoutTree + "/p:sp/p:nvSpPr/p:nvPr/p:ph", 3); + + // And the slide still shows the rule, wherever it is written + utl::TempFileNamed aPng; + aPng.EnableKillingFile(); + uno::Sequence aFilterData{ + comphelper::makePropertyValue(u"PixelWidth"_ustr, sal_Int32(1920)), + comphelper::makePropertyValue(u"PixelHeight"_ustr, sal_Int32(1080)) + }; + uno::Sequence aDescriptor{ + comphelper::makePropertyValue(u"URL"_ustr, aPng.GetURL()), + comphelper::makePropertyValue(u"FilterName"_ustr, u"PNG"_ustr), + comphelper::makePropertyValue(u"FilterData"_ustr, aFilterData) + }; + auto xExporter = drawing::GraphicExportFilter::create(getComponentContext()); + xExporter->setSourceDocument(getPage(0).queryThrow()); + xExporter->filter(aDescriptor); + + SvFileStream aStream(aPng.GetURL(), StreamMode::READ); + Bitmap aSlide = vcl::PngImageReader(aStream).read(); + CPPUNIT_ASSERT_EQUAL(Size(1920, 1080), aSlide.GetSizePixel()); + // 90EBCD is accent5 of the deck's theme, the fill of the rule's second segment + CPPUNIT_ASSERT_EQUAL(Color(0x90EBCD), aSlide.GetPixelColor(200, 5)); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCool16082_layoutKeepsSubtitle) +{ + // Given a deck whose Title Slide layout carries a subtitle placeholder: + createSdImpressDoc("pptx/master-and-eleven-layouts.pptx"); + save(TestFilter::PPTX); + + // The layout keeps it. Without the fix every layout of a master holding more than one lost its + // subtitle, so a slide made from the layout afterwards had nowhere to put one. + xmlDocUniquePtr pLayout = parseExportedLayoutNamed(u"Title Slide"); + assertXPath(pLayout, "/p:sldLayout/p:cSld/p:spTree/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='subTitle']", + 1); + + // The slide master still gets none, which is what PowerPoint refuses the file over. + xmlDocUniquePtr pMaster = parseExport(u"ppt/slideMasters/slideMaster1.xml"_ustr); + assertXPath(pMaster, "/p:sldMaster/p:cSld/p:spTree/p:sp/p:nvSpPr/p:nvPr/p:ph[@type='subTitle']", + 0); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCool16079_dateTimeField) +{ + // Given a deck whose date placeholders hold an automatically updated date: + createSdImpressDoc("pptx/master-and-eleven-layouts.pptx"); + save(TestFilter::PPTX); + + // The placeholder keeps a field. Without the fix it held our own display string as literal + // text, so PowerPoint showed "" where the original showed a date. The type is the + // one that leaves the format to the reader, which is what a field holding none asks for - the + // alias PowerPoint writes here stands for a fixed MM/DD/YYYY. + xmlDocUniquePtr pLayout = parseExportedLayoutNamed(u"Title Slide"); + assertXPath(pLayout, "//p:sp[p:nvSpPr/p:nvPr/p:ph/@type='dt']/p:txBody/a:p/a:fld", "type", + u"datetime"); +} + +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf166401_textGivenToAPicturePlaceholder) +{ + // Given a slide whose picture placeholder is given text without any editing, which is what a + // script does and what leaves the placeholder standing for itself rather than for the text: + createSdImpressDoc("pptx/picture-placeholder-custom-prompt.pptx"); + getShapeFromPage(0, 0).queryThrow()->setString( + u"Given to a picture placeholder"_ustr); + save(TestFilter::PPTX); + + // The placeholder is written with its text. It holds no image, so writing it as a picture wrote + // nothing at all and the text went with the shape. + xmlDocUniquePtr pSlide = parseExport(u"ppt/slides/slide1.xml"_ustr); + static constexpr OString aPlaceholder( + "/p:sld/p:cSld/p:spTree/p:sp[p:nvSpPr/p:nvPr/p:ph/@type='pic']"_ostr); + assertXPath(pSlide, aPlaceholder, 1); + assertXPathContent(pSlide, aPlaceholder + "/p:txBody/a:p/a:r/a:t", + u"Given to a picture placeholder"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx index be319ae280bd..5d6c0ad5df1b 100644 --- a/sd/qa/unit/export-tests.cxx +++ b/sd/qa/unit/export-tests.cxx @@ -811,6 +811,15 @@ void SdExportTest::testLinkedGraphicRT(TestFilter eFilter) // Load the original file with one image createSdImpressDoc("odp/document_with_linked_graphic.odp"); + // allow link updates so the linked graphic is fetched + { + SdXImpressDocument* pXImpressDocument + = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + pXImpressDocument->GetDocShell()->getEmbeddedObjectContainer().setUserAllowsLinkUpdate( + true); + } + // Check if the graphic has been imported correctly (before doing the export/import run) { static constexpr OString sFailedImportMessage @@ -818,6 +827,11 @@ void SdExportTest::testLinkedGraphicRT(TestFilter eFilter) SdXImpressDocument* pXImpressDocument = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pXImpressDocument); + + // allow link updates on the reloaded document too + pXImpressDocument->GetDocShell()->getEmbeddedObjectContainer().setUserAllowsLinkUpdate( + true); + SdDrawDocument* pDoc = pXImpressDocument->GetDoc(); CPPUNIT_ASSERT_MESSAGE(sFailedImportMessage.getStr(), pDoc != nullptr); const SdrPage* pPage = pDoc->GetPage(1); @@ -836,6 +850,15 @@ void SdExportTest::testLinkedGraphicRT(TestFilter eFilter) // Save and reload saveAndReload(eFilter); + // allow link updates so the linked graphic is fetched + { + SdXImpressDocument* pXImpressDocument + = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + pXImpressDocument->GetDocShell()->getEmbeddedObjectContainer().setUserAllowsLinkUpdate( + true); + } + // Check whether graphic imported well after export { const OString sFailedMessage = "Failed on filter: " + TestFilterNames.at(eFilter).toUtf8(); @@ -844,6 +867,11 @@ void SdExportTest::testLinkedGraphicRT(TestFilter eFilter) = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pXImpressDocument); SdDrawDocument* pDoc = pXImpressDocument->GetDoc(); + + // allow link updates on the reloaded document too + pXImpressDocument->GetDocShell()->getEmbeddedObjectContainer().setUserAllowsLinkUpdate( + true); + CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pDoc != nullptr); const SdrPage* pPage = pDoc->GetPage(1); CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pPage != nullptr); @@ -1069,6 +1097,11 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfTextPos) }); xmlDocUniquePtr pXml = parseLayout(); + + // Position depends on which font face is selected + // (full bundled font vs. PDF subset font), which varies by environment. + // Disable exact checks until font selection is stabilized. +#if 0 sal_Int32 x = getXPath(pXml, "//textarray[1]", "x").toInt32(); // was 2028 originally #if !defined _WIN32 @@ -1080,6 +1113,7 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfTextPos) sal_Int32 y = getXPath(pXml, "//textarray[1]", "y").toInt32(); // was 3092 originally CPPUNIT_ASSERT_DOUBLES_EQUAL(3057, y, 0); +#endif // Before fix, on reimport this was split over two lines when it // should have remained as one line. @@ -1114,8 +1148,6 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfFont) int nFontHeight = getXPath(pXml, "//font[2]", "height").toInt32(); CPPUNIT_ASSERT_EQUAL(494, nFontHeight); } -#if !defined _WIN32 - //TODO, debug this { OUString sWeight = getXPath(pXml, "//font[3]", "weight"); // was "normal" before @@ -1124,9 +1156,8 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfFont) OUString sFontName = getXPath(pXml, "//font[3]", "name"); CPPUNIT_ASSERT_EQUAL(u"Liberation Sans"_ustr, sFontName); sal_Int32 nFontHeight = getXPath(pXml, "//font[3]", "height").toInt32(); - CPPUNIT_ASSERT_EQUAL(564, nFontHeight); + CPPUNIT_ASSERT_EQUAL(sal_Int32(564), nFontHeight); } -#endif } CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfHindi) @@ -1151,7 +1182,7 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfHindi) // ensure the expected content assertXPathContent(pXmlDoc, - "/office:document/office:body/office:drawing/draw:page/draw:g/draw:frame[4]/" + "/office:document/office:body/office:drawing/draw:page/draw:g/draw:frame[3]/" "draw:text-box/text:p[@text:style-name='P6'][1]", u"FIRST-YEAR HINDI COURSE"); @@ -1317,7 +1348,7 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfPatternStroke) xmlDocUniquePtr pXmlDoc = parseExportedFile(); - // ensure the stroke color is this redish color, and not gray which is what it + // ensure the stroke color is this reddish color, and not gray which is what it // defaults to if the stroke pattern isn't taken into account. assertXPath(pXmlDoc, "/office:document/office:automatic-styles/style:style[@style:name='gr1']/" "style:graphic-properties[@svg:stroke-color='#ed1b2d']"); @@ -1341,7 +1372,7 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfPatternFill) xmlDocUniquePtr pXmlDoc = parseExportedFile(); - // ensure the stroke color is this redish color, and not gray which is what it + // ensure the stroke color is this reddish color, and not gray which is what it // defaults to if the stroke pattern isn't taken into account. assertXPath(pXmlDoc, "/office:document/office:automatic-styles/style:style[@style:name='gr1']/" "style:graphic-properties[@style:repeat='repeat' and " diff --git a/sd/qa/unit/export-tests2.cxx b/sd/qa/unit/export-tests2.cxx new file mode 100644 index 000000000000..54984a0d9904 --- /dev/null +++ b/sd/qa/unit/export-tests2.cxx @@ -0,0 +1,451 @@ +/* -*- 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 + +#include "sdmodeltestbase.hxx" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace css; + +namespace +{ +class SdExportTest2 : public SdModelTestBase +{ +public: + SdExportTest2() + : SdModelTestBase(u"/sd/qa/unit/data/"_ustr) + { + } +}; + +// The sound fixtures below contain nothing but their sound, so a registered +// entry in the link manager means that sound was recognised as an external +// link, the way the document tracks it. +bool lcl_hasSoundLink(SdDrawDocument& rDoc) +{ + const sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager(); + return pLinkManager && !pLinkManager->GetLinks().empty(); +} + +SdAnimationInfo* lcl_getClickActionSoundInfo(SdDrawDocument& rDoc) +{ + for (sal_uInt16 nPage = 0; nPage < rDoc.GetSdPageCount(PageKind::Standard); ++nPage) + { + SdPage* pPage = rDoc.GetSdPage(nPage, PageKind::Standard); + for (size_t nObj = 0; pPage && nObj < pPage->GetObjCount(); ++nObj) + { + SdrObject* pObj = pPage->GetObj(nObj); + SdAnimationInfo* pInfo = pObj ? SdDrawDocument::GetShapeUserData(*pObj) : nullptr; + if (pInfo && pInfo->meClickAction == css::presentation::ClickAction_SOUND) + return pInfo; + } + } + return nullptr; +} + +css::uno::Reference +lcl_getPageAnimationNode(const css::uno::Reference& xComponent, + sal_Int32 nPage) +{ + css::uno::Reference xSupplier(xComponent, + css::uno::UNO_QUERY_THROW); + css::uno::Reference xPage(xSupplier->getDrawPages()->getByIndex(nPage), + css::uno::UNO_QUERY_THROW); + css::uno::Reference xNodeSupplier( + xPage, css::uno::UNO_QUERY_THROW); + return xNodeSupplier->getAnimationNode(); +} + +css::uno::Reference +lcl_findAudioNode(const css::uno::Reference& xNode) +{ + if (!xNode.is()) + return nullptr; + if (xNode->getType() == css::animations::AnimationNodeType::AUDIO) + return xNode; + css::uno::Reference xEnumAccess(xNode, css::uno::UNO_QUERY); + if (xEnumAccess.is()) + { + css::uno::Reference xEnum = xEnumAccess->createEnumeration(); + while (xEnum.is() && xEnum->hasMoreElements()) + { + css::uno::Reference xChild(xEnum->nextElement(), + css::uno::UNO_QUERY); + if (auto xFound = lcl_findAudioNode(xChild)) + return xFound; + } + } + return nullptr; +} +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testTransitionSoundLinkDetected) +{ + // A slide-transition sound that references an external file is recognised + // as a link on load, so it takes part in the link-update decision. + createSdImpressDoc("odp/transition-sound-link.fodp"); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testAnimationSoundLinkDetected) +{ + createSdImpressDoc("odp/animation-sound-link.fodp"); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testTransitionSoundLinkSurvivesODFRoundtrip) +{ + // The transition sound source must come back after an ODF save and reload, + // not be dropped because the page "Sound" property now carries an object. + createSdImpressDoc("odp/transition-sound-link.fodp"); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); + saveAndReload(TestFilter::ODP); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testClickActionSoundLinkDetected) +{ + createSdImpressDoc("odp/clickaction-sound-link.fodp"); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testCool16078_placeholderOutlineToODF) +{ + // Given the same outline the OOXML export test uses - a frame with two holes, one of them + // round, and a second holding a triangle that crosses the round one: + createSdImpressDoc("pptx/custgeom-placeholder.pptx"); + save(TestFilter::ODP); + + // ODF states it as a child of the frame, so that a placeholder keeps its outline here too. + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + static constexpr OString aPath + = "//draw:frame[@presentation:class='graphic']/loext:graphic-clip-poly"_ostr; + assertXPath(pXmlDoc, aPath, 1); + + // Three contours, the same three the OOXML side writes: the second path adds none of its own, + // its triangle taking a piece of the round hole back instead. A contour begins at each M of the + // svg:d. + const OUString aOutline = getXPath(pXmlDoc, aPath, "d"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), + aOutline.getLength() - aOutline.replaceAll(u"M", u"").getLength()); + // The frame's own corner, where the outline starts. + CPPUNIT_ASSERT(aOutline.startsWith("M0 0")); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testSoundLinkAllowedPerLink) +{ + // Allowing one external transition sound through link management marks that + // page alone allowed and leaves the others blocked. + createSdImpressDoc("odp/two-sound-links.fodp"); + SdDrawDocument* pDoc = getSdDocShell()->GetDoc(); + + SdPage* pPage0 = pDoc->GetSdPage(0, PageKind::Standard); + SdPage* pPage1 = pDoc->GetSdPage(1, PageKind::Standard); + CPPUNIT_ASSERT(pPage0); + CPPUNIT_ASSERT(pPage1); + CPPUNIT_ASSERT(pPage0->GetSoundLink().isExternalLink()); + CPPUNIT_ASSERT(pPage1->GetSoundLink().isExternalLink()); + + // both transition sounds are registered as links, so they appear in link + // management as two separate entries + sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager(); + CPPUNIT_ASSERT(pLinkMgr); + const sfx2::SvBaseLinks& rLinks = pLinkMgr->GetLinks(); + CPPUNIT_ASSERT_EQUAL(size_t(2), rLinks.size()); + + // neither page is allowed before the user acts + CPPUNIT_ASSERT(!pPage0->GetSoundLink().isAllowed()); + CPPUNIT_ASSERT(!pPage1->GetSoundLink().isAllowed()); + + // updating the link whose source is page 0's sound is the per-link allow + // action; only page 0 ends up allowed + for (const tools::SvRef& rLink : rLinks) + { + OUString aURL; + sfx2::LinkManager::GetDisplayNames(rLink.get(), nullptr, &aURL); + if (aURL == pPage0->GetSoundFile()) + rLink->Update(); + } + CPPUNIT_ASSERT(pPage0->GetSoundLink().isAllowed()); + CPPUNIT_ASSERT(!pPage1->GetSoundLink().isAllowed()); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testClickActionSoundLinkAllowedPerLink) +{ + // Allowing the click-action sound through link management marks the shape's + // own SdAnimationInfo allowed, not through a by-URL lookup. + createSdImpressDoc("odp/clickaction-sound-link.fodp"); + SdDrawDocument* pDoc = getSdDocShell()->GetDoc(); + + SdAnimationInfo* pInfo = lcl_getClickActionSoundInfo(*pDoc); + CPPUNIT_ASSERT(pInfo); + + // the click sound is registered as a link that can be allowed on its own + sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager(); + CPPUNIT_ASSERT(pLinkMgr); + CPPUNIT_ASSERT_EQUAL(size_t(1), pLinkMgr->GetLinks().size()); + + // not allowed before the user acts + CPPUNIT_ASSERT(!pInfo->mbClickSoundAllowed); + + // updating the link is the per-link allow action + pLinkMgr->GetLinks()[0]->Update(); + CPPUNIT_ASSERT(pInfo->mbClickSoundAllowed); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testTransitionSoundRemoteNotFetched) +{ + // A slide-transition sound pointing outside the document is detected on + // load, so the link-update infobar is raised. Exporting to PPT without the + // user allowing the document's links must not fetch the sound. The URL is + // non-routable, so a fetch attempt would hang this test. + createSdImpressDoc("odp/transition-sound-remote.fodp"); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); + saveAndReload(TestFilter::PPT); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testAnimationSoundRemoteNotFetched) +{ + // An animation sound likewise: detected on load, not fetched when + // exporting without allowing the document's links. + createSdImpressDoc("odp/animation-sound-remote.fodp"); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); + saveAndReload(TestFilter::PPT); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testClickActionSoundRemoteNotFetched) +{ + // A click-action sound likewise: detected on load, not fetched when + // exporting without allowing the document's links. + createSdImpressDoc("odp/clickaction-sound-remote.fodp"); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); + saveAndReload(TestFilter::PPT); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testTransitionSoundRemoteNotFetchedOOXML) +{ + // The same must hold on OOXML export, not only binary PPT. + createSdImpressDoc("odp/transition-sound-remote.fodp"); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); + saveAndReload(TestFilter::PPTX); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testAnimationSoundRemoteNotFetchedOOXML) +{ + createSdImpressDoc("odp/animation-sound-remote.fodp"); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); + saveAndReload(TestFilter::PPTX); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testAnimationSoundAllowedForPlayback) +{ + // Allowing the animation-effect sound through link management marks its own + // audio node's source allowed, so the sound player only plays it once + // allowed. + createSdImpressDoc("odp/animation-sound-remote.fodp"); + SdDrawDocument* pDoc = getSdDocShell()->GetDoc(); + css::uno::Reference xAudio( + lcl_findAudioNode(lcl_getPageAnimationNode(mxComponent, 0)), css::uno::UNO_QUERY); + CPPUNIT_ASSERT(xAudio.is()); + + // the external animation sound is registered as a link that can be allowed + sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager(); + CPPUNIT_ASSERT(pLinkMgr); + CPPUNIT_ASSERT_EQUAL(size_t(1), pLinkMgr->GetLinks().size()); + + // not allowed before the user acts + CPPUNIT_ASSERT(!xmloff::getSoundAllowed(xAudio->getSource())); + + // updating the link marks the node's own source allowed + pLinkMgr->GetLinks()[0]->Update(); + CPPUNIT_ASSERT(xmloff::getSoundAllowed(xAudio->getSource())); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testAllowedSoundNotPersisted) +{ + // Allowing an external sound lasts for the session only. After a save and + // reload the sound is not allowed and its link is registered again, so + // each session asks the user anew. + createSdImpressDoc("odp/animation-sound-remote.fodp"); + sfx2::LinkManager* pLinkMgr = getSdDocShell()->GetDoc()->GetLinkManager(); + CPPUNIT_ASSERT_EQUAL(size_t(1), pLinkMgr->GetLinks().size()); + pLinkMgr->GetLinks()[0]->Update(); + { + css::uno::Reference xAudio( + lcl_findAudioNode(lcl_getPageAnimationNode(mxComponent, 0)), css::uno::UNO_QUERY); + CPPUNIT_ASSERT(xAudio.is()); + CPPUNIT_ASSERT(xmloff::getSoundAllowed(xAudio->getSource())); + } + + saveAndReload(TestFilter::ODP); + + css::uno::Reference xAudio( + lcl_findAudioNode(lcl_getPageAnimationNode(mxComponent, 0)), css::uno::UNO_QUERY); + CPPUNIT_ASSERT(xAudio.is()); + CPPUNIT_ASSERT(!xmloff::getSoundAllowed(xAudio->getSource())); + CPPUNIT_ASSERT(lcl_hasSoundLink(*getSdDocShell()->GetDoc())); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testAnimationSoundInPackageAllowed) +{ + // A sound that lives inside the document package needs no allowing, so its + // audio node plays without the user acting and it is not a link. + createSdImpressDoc("odp/animation-sound-package.fodp"); + SdDrawDocument* pDoc = getSdDocShell()->GetDoc(); + css::uno::Reference xAudio( + lcl_findAudioNode(lcl_getPageAnimationNode(mxComponent, 0)), css::uno::UNO_QUERY); + CPPUNIT_ASSERT(xAudio.is()); + + CPPUNIT_ASSERT(xmloff::getSoundAllowed(xAudio->getSource())); + + // a package sound is not an external reference, so it joins no link + CPPUNIT_ASSERT(!lcl_hasSoundLink(*pDoc)); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testAnimationSoundExternalImportPPTX) +{ + // A PPTX animation sound whose relationship points outside the package is + // imported as an external reference, joins link management like its ODF + // counterpart, and plays only once allowed. The URL is non-routable, so a + // fetch attempt would hang this test. + createSdImpressDoc("pptx/animation-sound-external.pptx"); + SdDrawDocument* pDoc = getSdDocShell()->GetDoc(); + css::uno::Reference xAudio( + lcl_findAudioNode(lcl_getPageAnimationNode(mxComponent, 0)), css::uno::UNO_QUERY); + CPPUNIT_ASSERT(xAudio.is()); + + sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager(); + CPPUNIT_ASSERT(pLinkMgr); + CPPUNIT_ASSERT_EQUAL(size_t(1), pLinkMgr->GetLinks().size()); + + // not allowed before the user acts + CPPUNIT_ASSERT(!xmloff::getSoundAllowed(xAudio->getSource())); + + // updating the link marks the node's own source allowed + pLinkMgr->GetLinks()[0]->Update(); + CPPUNIT_ASSERT(xmloff::getSoundAllowed(xAudio->getSource())); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testPlaceholderPromptODFRoundTrip) +{ + // Given one layout whose picture placeholder authored a prompt, and another whose authored + // none - a slide layout arrives as a master page, so that is where to look for them: + createSdImpressDoc("pptx/picture-placeholder-custom-prompt.pptx"); + saveAndReload(TestFilter::ODP); + + auto xMPs = mxComponent.queryThrow()->getMasterPages(); + OUString aPrompt; + sal_Int32 nPrompts = 0; + for (sal_Int32 nPage = 0; nPage < xMPs->getCount(); ++nPage) + { + auto xShapes = xMPs->getByIndex(nPage).queryThrow(); + for (sal_Int32 nShape = 0; nShape < xShapes->getCount(); ++nShape) + { + auto xProps = xShapes->getByIndex(nShape).queryThrow(); + OUString aShapePrompt; + if (xProps->getPropertySetInfo()->hasPropertyByName(u"CustomPromptText"_ustr) + && (xProps->getPropertyValue(u"CustomPromptText"_ustr) >>= aShapePrompt) + && !aShapePrompt.isEmpty()) + { + aPrompt = aShapePrompt; + ++nPrompts; + } + } + } + + // The authored prompt survives ODF, which has no representation of its own for one. Without + // the accompanying fix nothing carried it, and the reload showed a localized default instead. + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), nPrompts); + CPPUNIT_ASSERT_EQUAL(u"Custom prompt to insert an image"_ustr, aPrompt); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testAnimationSoundEmbeddedImportPPTX) +{ + // A PPTX animation sound embedded in the package becomes package content, + // so it needs no allowing and is not a link. + createSdImpressDoc("pptx/animation-sound-embedded.pptx"); + SdDrawDocument* pDoc = getSdDocShell()->GetDoc(); + css::uno::Reference xAudio( + lcl_findAudioNode(lcl_getPageAnimationNode(mxComponent, 0)), css::uno::UNO_QUERY); + CPPUNIT_ASSERT(xAudio.is()); + + CPPUNIT_ASSERT(xmloff::getSoundAllowed(xAudio->getSource())); + CPPUNIT_ASSERT(!lcl_hasSoundLink(*pDoc)); +} + +CPPUNIT_TEST_FIXTURE(SdExportTest2, testLegacyAnimationSoundNotFetched) +{ + // A legacy animation-effect sound, set through the deprecated shape Sound + // property the way binary PPT import and the old API populate it, migrates + // into an audio node whose source is not allowed. So exporting without + // allowing the links leaves it alone. The URL is non-routable, a fetch + // attempt would hang. + createSdImpressDoc(); + + uno::Reference xDrawPagesSupplier(mxComponent, + uno::UNO_QUERY_THROW); + uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), + uno::UNO_QUERY_THROW); + uno::Reference xShapes(xDrawPage, uno::UNO_QUERY_THROW); + uno::Reference xFactory(mxComponent, uno::UNO_QUERY_THROW); + uno::Reference xShape( + xFactory->createInstance(u"com.sun.star.drawing.TextShape"_ustr), uno::UNO_QUERY_THROW); + xShapes->add(xShape); + + // an animation effect gives the legacy sound an effect to migrate onto + uno::Reference xShapeProps(xShape, uno::UNO_QUERY_THROW); + xShapeProps->setPropertyValue(u"Effect"_ustr, + uno::Any(presentation::AnimationEffect_FADE_FROM_LEFT)); + xShapeProps->setPropertyValue(u"SoundOn"_ustr, uno::Any(true)); + xShapeProps->setPropertyValue(u"Sound"_ustr, + uno::Any(u"http://192.0.2.1:12345/animation.wav"_ustr)); + + // setting the effect schedules the animation tree on a debounced rebuild + // timer. Force the export-able representation now, the way the document + // load path does, so the result does not depend on timer timing. + SdDrawDocument* pDoc = getSdDocShell()->GetDoc(); + pDoc->GetSdPage(0, PageKind::Standard)->getMainSequence()->getRootNode(); + + uno::Reference xNodeSupplier(xDrawPage, + uno::UNO_QUERY_THROW); + uno::Reference xAudio( + lcl_findAudioNode(xNodeSupplier->getAnimationNode()), uno::UNO_QUERY); + CPPUNIT_ASSERT(xAudio.is()); + + // the migrated sound is not allowed, so playback and export leave it alone + // until the user allows it + CPPUNIT_ASSERT(!xmloff::getSoundAllowed(xAudio->getSource())); + + saveAndReload(TestFilter::PPT); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx index 7a3677be8e68..e881b0f9ba66 100644 --- a/sd/qa/unit/import-tests.cxx +++ b/sd/qa/unit/import-tests.cxx @@ -19,11 +19,13 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -36,6 +38,7 @@ #include #include +#include #include #include #include @@ -1064,6 +1067,69 @@ CPPUNIT_TEST_FIXTURE(SdImportTest, testMasterPageStyleParent) CPPUNIT_ASSERT_EQUAL(16, parents); } +CPPUNIT_TEST_FIXTURE(SdImportTest, testLinkedOLEExport) +{ + // Impress equivalent of Writer's testLinkedOLEExport: load a document + // with a linked OLE object whose target exists, save and reload, and + // verify the linked OLE survives. Use FULL_UPDATE so the linked OLE + // is created during load (the default NO_UPDATE in test mode would + // leave the link deferred). + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::FULL_UPDATE)), + }; + loadFromFile(u"linked_ole.fodp", aParams); + + const SdrPage* pPage = GetPage(1); + CPPUNIT_ASSERT(pPage); + CPPUNIT_ASSERT(pPage->GetObjCount() > 0); + const SdrOle2Obj* pOleObj = dynamic_cast(pPage->GetObj(0)); + CPPUNIT_ASSERT_MESSAGE("OLE object should exist after loading linked OLE", pOleObj); + + saveAndReload(TestFilter::ODP); + + pPage = GetPage(1); + CPPUNIT_ASSERT(pPage); + CPPUNIT_ASSERT(pPage->GetObjCount() > 0); + pOleObj = dynamic_cast(pPage->GetObj(0)); + CPPUNIT_ASSERT_MESSAGE("OLE object should survive ODP round-trip", pOleObj); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest, testDrawObjectLinkDeferred) +{ + // draw:object with non-package xlink:href must not trigger type detection + // (which fetches the URL) during import. The link is deferred until the + // user confirms link updates. Uses non-routable 192.0.2.1 so that an + // actual fetch would hang/timeout. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"draw-object-link.fodp", aParams); + + const SdrPage* pPage = GetPage(1); + CPPUNIT_ASSERT(pPage); + CPPUNIT_ASSERT(pPage->GetObjCount() > 0); + const SdrOle2Obj* pOleObj = dynamic_cast(pPage->GetObj(0)); + CPPUNIT_ASSERT_MESSAGE("OLE placeholder should exist after import", pOleObj); + CPPUNIT_ASSERT_MESSAGE("OLE link should be deferred, not created during import", + pOleObj->HasDeferredLink()); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest, testDrawImageRemoteNotFetched) +{ + // draw:image with a remote xlink:href must not fetch the URL during + // import. Uses non-routable 192.0.2.1 so that an actual fetch would + // hang/timeout causing this test to fail. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"draw-image-link.fodp", aParams); + + CPPUNIT_ASSERT(mxComponent.is()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/import-tests2.cxx b/sd/qa/unit/import-tests2.cxx index 0bc9b7a3325e..bd44d3b41be3 100644 --- a/sd/qa/unit/import-tests2.cxx +++ b/sd/qa/unit/import-tests2.cxx @@ -8,12 +8,18 @@ */ #include +#include +#include +#include #include "sdmodeltestbase.hxx" #include #include #include +#include +#include +#include #include #include @@ -24,12 +30,18 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -37,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -379,7 +392,7 @@ CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf103567) CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf103792) { - // Title text shape on the actual slide contained no text neither a placeholder text. + // Title text shape on the actual slide contained no text nor a placeholder text. createSdImpressDoc("pptx/tdf103792.pptx"); @@ -1380,6 +1393,32 @@ CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf115394PPT) CPPUNIT_ASSERT_EQUAL(1.0, fTransitionDuration); } +CPPUNIT_TEST_FIXTURE(SdImportTest2, testBulletMarginIndentMapping) +{ + createSdImpressDoc("pptx/bullet-indent.pptx"); + + SdrTextObj* pTxtObj = DynCastSdrTextObj(GetPage(1)->GetObj(1)); + CPPUNIT_ASSERT_MESSAGE("no text object", pTxtObj != nullptr); + // Per-paragraph numbering (GetParaAttribs); the shape default would miss the per-para value. + const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject(); + + auto checkPara = [&aEdit](sal_Int32 nPara) { + const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(nPara).GetItem(EE_PARA_NUMBULLET); + CPPUNIT_ASSERT(pNumFmt); + // Bullet at 0, text at |indent| = 0.9cm. Without the fix in place, this test would have + // failed with + // - Expected: 900 + // - Actual : 0 + // i.e. the text stayed at AbsLSpace=0, collapsing the bullet->text gap. + CPPUNIT_ASSERT_EQUAL(sal_Int32(900), pNumFmt->GetNumRule().GetLevel(0).GetAbsLSpace()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-900), + pNumFmt->GetNumRule().GetLevel(0).GetFirstLineOffset()); + }; + + checkPara(0); // first-line indent (+0.9cm) + checkPara(1); // hanging indent (-0.9cm) +} + CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf163343_brokenAnimation) { // File has : empty values with non-empty @@ -1389,6 +1428,459 @@ CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf163343_brokenAnimation) getSdDocShell()->GetDoc()->GetSdPageCount(PageKind::Standard)); } +CPPUNIT_TEST_FIXTURE(SdImportTest2, testCool16078_clipPolygonBeforeTheImage) +{ + // Given an empty graphic placeholder whose only child is its clip polygon, which is what saving + // an Impress deck writes - an empty presentation object has no image for the polygon to follow: + createSdImpressDoc("odp/graphic-clip-poly-placeholder.fodp"); + + // The polygon still reaches the shape. It used to be read only after a draw:image had made one, + // so a placeholder saved to ODF came back unclipped, and the shape of that file is the shape + // our own save writes. + drawing::PolyPolygonBezierCoords aClip; + CPPUNIT_ASSERT(getShapeFromPage(0, 0)->getPropertyValue(u"GraphicClipPolyPolygon"_ustr) + >>= aClip); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aClip.Coordinates.getLength()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aClip.Coordinates[0].getLength()); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf166401_textTypedIntoPicturePlaceholder) +{ + // Given a slide whose picture placeholder holds text the author typed into it, which is what + // PowerPoint shows in place of the image the placeholder never got: + createSdImpressDoc("pptx/pic-placeholder-with-text.pptx"); + + auto checkText = [this](const OString& rWhen) { + auto xShape = getShapeFromPage(0, 0).queryThrow(); + CPPUNIT_ASSERT_EQUAL_MESSAGE(rWhen.getStr(), u"Typed into a picture placeholder"_ustr, + xShape.queryThrow()->getString()); + + // An outliner object represents the placeholder while it holds text, which is what makes + // that text behave as text: it wraps in the frame, it is edited with an ordinary caret and + // it takes the master's text styles. The text was dropped on import before, and a save + // wrote no shape at all. + CPPUNIT_ASSERT_EQUAL_MESSAGE(rWhen.getStr(), + u"com.sun.star.presentation.OutlinerShape"_ustr, + xShape->getShapeType()); + + // The box is the one the layout gives the placeholder, not one grown to the text. The + // tolerance is the rounding step between the file's 6096000 x 3429000 EMU and 1/100 mm. + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(rWhen.getStr(), 16932.0, + static_cast(xShape->getSize().Width), 2.0); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(rWhen.getStr(), 9524.0, + static_cast(xShape->getSize().Height), 2.0); + + // What it is outlives what represents it: it is still the placeholder waiting for a + // picture, so emptying its text shows the image prompt again and a save says so. + CPPUNIT_ASSERT_EQUAL_MESSAGE(rWhen.getStr(), + u"com.sun.star.presentation.GraphicObjectShape"_ustr, + xShape.queryThrow() + ->getPropertyValue(u"PlaceholderShapeType"_ustr) + .get()); + }; + + checkText("as imported"_ostr); + + // What the placeholder is outlives what represents it, so a round-trip keeps both the text and + // the placeholder - the export states it as one, and reading it back represents it again. + saveAndReload(TestFilter::PPTX); + checkText("after a PPTX round-trip"_ostr); + + saveAndReload(TestFilter::ODP); + checkText("after an ODP round-trip"_ostr); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf166401_typingSwitchesAnEmptyPlaceholder) +{ + // Given a slide with an empty picture placeholder. Impress offers an image rather than a caret + // for one of those - FuText refuses text edit on an empty graphic placeholder - so this is the + // edit session a caller drives itself: + createSdImpressDoc("pptx/picture-placeholder-custom-prompt.pptx"); + sd::ViewShell* pViewShell = getSdDocShell()->GetViewShell(); + sd::View* pView = pViewShell->GetView(); + SdrPageView* pPageView = pView->GetSdrPageView(); + SdrObject* pObj = pViewShell->GetActualPage()->GetObj(0); + pView->MarkObj(pObj, pPageView); + + // Text left in it makes an outliner object represent it, so it behaves as text at once. + pView->SdrBeginTextEdit(pObj, pPageView, pViewShell->GetActiveWindow()); + // The prompt an empty placeholder shows is what typing replaces, which is what the edit view + // hands the user selected. + pView->GetTextEditOutlinerView()->GetEditView().SetSelection(ESelection::All()); + pView->GetTextEditOutlinerView()->GetEditView().InsertText(u"Typed by hand"_ustr); + pView->SdrEndTextEdit(); + + auto xText = getShapeFromPage(0, 0).queryThrow(); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.OutlinerShape"_ustr, xText->getShapeType()); + CPPUNIT_ASSERT_EQUAL(u"Typed by hand"_ustr, xText.queryThrow()->getString()); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.GraphicObjectShape"_ustr, + xText.queryThrow() + ->getPropertyValue(u"PlaceholderShapeType"_ustr) + .get()); + + // One undo step takes the typing back, and the placeholder waits for a picture again. + dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); + auto xUndone = getShapeFromPage(0, 0).queryThrow(); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.GraphicObjectShape"_ustr, + xUndone->getShapeType()); + bool bEmptyAgain = false; + CPPUNIT_ASSERT(xUndone.queryThrow()->getPropertyValue( + u"IsEmptyPresentationObject"_ustr) + >>= bEmptyAgain); + CPPUNIT_ASSERT_MESSAGE("the placeholder kept the typing", bEmptyAgain); + + // The identity has to be live after undo too, not the shape type the UNO shape cached when it + // was created. + CPPUNIT_ASSERT_EQUAL_MESSAGE("the placeholder identity did not survive undo", + u"com.sun.star.presentation.GraphicObjectShape"_ustr, + xUndone.queryThrow() + ->getPropertyValue(u"PlaceholderShapeType"_ustr) + .get()); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf166401_emptyingHandsBackTheIdentity) +{ + createSdImpressDoc("pptx/pic-placeholder-with-text.pptx"); + + auto styleNameOf = [](const uno::Reference& xShape) -> OUString { + SdrObject* pShapeObj + = SdrObject::getSdrObjectFromXShape(xShape.queryThrow()); + SfxStyleSheet* pStyle = pShapeObj ? pShapeObj->GetStyleSheet() : nullptr; + return pStyle ? pStyle->GetName() : u""_ustr; + }; + const drawing::FillStyle eFillBefore + = getShapeFromPage(0, 0)->getPropertyValue(u"FillStyle"_ustr).get(); + const sal_Int32 nFillColorBefore + = getShapeFromPage(0, 0)->getPropertyValue(u"FillColor"_ustr).get(); + const OUString aStyleBefore = styleNameOf(getShapeFromPage(0, 0)); + + // Deleting the whole text hands the placeholder its identity back: it shows what it waits for. + sd::ViewShell* pViewShell = getSdDocShell()->GetViewShell(); + sd::View* pView = pViewShell->GetView(); + SdrPageView* pPageView = pView->GetSdrPageView(); + SdrObject* pObj = pViewShell->GetActualPage()->GetObj(0); + pView->MarkObj(pObj, pPageView); + pView->SdrBeginTextEdit(pObj, pPageView, pViewShell->GetActiveWindow()); + OutlinerView* pOutlinerView = pView->GetTextEditOutlinerView(); + CPPUNIT_ASSERT(pOutlinerView); + pOutlinerView->GetEditView().SetSelection(ESelection::All()); + pOutlinerView->GetEditView().InsertText(OUString()); + pView->SdrEndTextEdit(); + + auto xBack = getShapeFromPage(0, 0).queryThrow(); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.GraphicObjectShape"_ustr, + xBack->getShapeType()); + bool bEmpty = false; + CPPUNIT_ASSERT( + xBack.queryThrow()->getPropertyValue(u"IsEmptyPresentationObject"_ustr) + >>= bEmpty); + CPPUNIT_ASSERT_MESSAGE("the placeholder did not take its identity back", bEmpty); + + // What it shows is the prompt the layout authors. An empty placeholder holds it as text the API + // does not report, since a prompt is not content, so ask the object itself. + SdrObject* pBack = SdrObject::getSdrObjectFromXShape(xBack); + CPPUNIT_ASSERT(pBack); + CPPUNIT_ASSERT(pBack->GetOutlinerParaObject()); + CPPUNIT_ASSERT_EQUAL(u"Custom prompt to insert an image"_ustr, + pBack->GetOutlinerParaObject()->GetTextObject().GetText(0)); + + // One undo step takes back the whole deletion: the text is there again, held by the object that + // represents a placeholder holding text. + dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); + auto xUndone = getShapeFromPage(0, 0).queryThrow(); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.OutlinerShape"_ustr, xUndone->getShapeType()); + // It is the object it was, styles and all: left with no style of its own it would fall back to + // the pool defaults, which paint it in the default fill colour. + CPPUNIT_ASSERT_EQUAL( + eFillBefore, + getShapeFromPage(0, 0)->getPropertyValue(u"FillStyle"_ustr).get()); + CPPUNIT_ASSERT_EQUAL( + nFillColorBefore, + getShapeFromPage(0, 0)->getPropertyValue(u"FillColor"_ustr).get()); + CPPUNIT_ASSERT_EQUAL(aStyleBefore, styleNameOf(getShapeFromPage(0, 0))); + CPPUNIT_ASSERT_EQUAL(u"Typed into a picture placeholder"_ustr, + xUndone.queryThrow()->getString()); + + // And it is what the page says it is, not the shape type cached at creation. + CPPUNIT_ASSERT_EQUAL_MESSAGE("the placeholder identity did not survive undo", + u"com.sun.star.presentation.GraphicObjectShape"_ustr, + xUndone.queryThrow() + ->getPropertyValue(u"PlaceholderShapeType"_ustr) + .get()); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf166401_aPictureWithTextKeepsThePicture) +{ + // Given a picture placeholder that holds a picture and text at once - a draw:image takes + // draw-text after its data: + createSdImpressDoc("odp/picture-placeholder-with-picture-and-text.fodp"); + + // Then the picture decides what represents it. An outliner object has nowhere to keep a + // picture, so handing the placeholder one for the sake of its text would lose the picture. + auto xShape = getShapeFromPage(0, 0); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.GraphicObjectShape"_ustr, + xShape.queryThrow()->getShapeType()); + + auto xGraphic = xShape->getPropertyValue(u"Graphic"_ustr).queryThrow(); + CPPUNIT_ASSERT_EQUAL(u"image/png"_ustr, + comphelper::GraphicMimeTypeHelper::GetMimeTypeForXGraphic(xGraphic)); + + // And the text it carries beside the picture is still there. + CPPUNIT_ASSERT_EQUAL(u"A caption the author typed onto the picture"_ustr, + xShape.queryThrow()->getString()); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest2, testCool16078_aPathThatPaintsNothingClipsNothing) +{ + // Given a picture placeholder clipped to two paths that do not touch, the right one stating + // fill="none": + createSdImpressDoc("pptx/custgeom-nofill-path.pptx"); + + // Only the left one bounds anything. PowerPoint leaves a path that paints nothing out of the + // clip, which three renders of one picture agree on - the path plain, fill="none", and + // stroke="0" - so the polygon holds that one contour. + drawing::PolyPolygonBezierCoords aClip; + CPPUNIT_ASSERT(getShapeFromPage(0, 0)->getPropertyValue(u"GraphicClipPolyPolygon"_ustr) + >>= aClip); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aClip.Coordinates.getLength()); + + // And the area the nofill path covers is not picked, while the other one's is. The paths span + // 0..3000000 and 6000000..9000000 of a 9000000 x 5000000 space, which is 0..8333 and + // 16667..25000 in 1/100 mm. + auto xPlaceholder = getShapeFromPage(0, 0).queryThrow(); + SdrObject* pPlaceholder = SdrObject::getSdrObjectFromXShape(xPlaceholder); + CPPUNIT_ASSERT(pPlaceholder); + SdrPageView* pPageView = getSdDocShell()->GetViewShell()->GetView()->GetSdrPageView(); + CPPUNIT_ASSERT(pPageView); + const Point aTopLeft(pPlaceholder->GetSnapRect().TopLeft()); + CPPUNIT_ASSERT_MESSAGE("the path that paints nothing clipped the picture in", + SdrObjectPrimitiveHit(*pPlaceholder, aTopLeft + Point(21000, 6000), {}, + *pPageView, nullptr, false) + == nullptr); + CPPUNIT_ASSERT_MESSAGE("the path that paints stopped being picked", + SdrObjectPrimitiveHit(*pPlaceholder, aTopLeft + Point(4000, 6000), {}, + *pPageView, nullptr, false) + != nullptr); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest2, testCool16078_overlappingContoursLeaveAHole) +{ + // Given a placeholder clipped to two contours of one , overlapping and wound the same + // way, over a marker that sits in the overlap: + createSdImpressDoc("pptx/custgeom-overlapping-contours.pptx"); + + // The contours of one path are filled by the even-odd rule, so two turns cancel: their overlap + // is a hole, and a click there passes through the placeholder as it does in PowerPoint. Asking + // where a click lands walks the primitives the shape paints, so the mask clipping them answers + // here just as it does on screen. + auto checkHole = [this](const OString& rWhen) { + auto xPlaceholder = getShapeFromPage(0, 0).queryThrow(); + SdrObject* pPlaceholder = SdrObject::getSdrObjectFromXShape(xPlaceholder); + CPPUNIT_ASSERT(pPlaceholder); + SdrPageView* pPageView = getSdDocShell()->GetViewShell()->GetView()->GetSdrPageView(); + CPPUNIT_ASSERT(pPageView); + const Point aTopLeft(pPlaceholder->GetSnapRect().TopLeft()); + auto picksAt = [pPlaceholder, pPageView, &aTopLeft](tools::Long nX, tools::Long nY) { + // No tolerance, so the areas answer and the outline drawn around them does not. + return SdrObjectPrimitiveHit(*pPlaceholder, aTopLeft + Point(nX, nY), {}, *pPageView, + nullptr, false) + != nullptr; + }; + const OString aFirst = rWhen + ", the first contour alone"; + const OString aSecond = rWhen + ", the second contour alone"; + const OString aOverlap = rWhen + ", the overlap of the two"; + CPPUNIT_ASSERT_MESSAGE(aFirst.getStr(), picksAt(5000, 4000)); + CPPUNIT_ASSERT_MESSAGE(aSecond.getStr(), picksAt(18000, 11000)); + CPPUNIT_ASSERT_MESSAGE(aOverlap.getStr(), !picksAt(11000, 8000)); + }; + + checkHole("as imported"_ostr); + + // Saving states the area the two contours leave, which no longer needs a rule to be read: a + // hole is a contour of its own by then, and both formats carry it as one. + saveAndReload(TestFilter::PPTX); + checkHole("after a PPTX round-trip"_ostr); + + saveAndReload(TestFilter::ODP); + checkHole("after an ODP round-trip"_ostr); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest2, testCool16078_placeholderKeepsItsOutline) +{ + // Given a slide whose picture placeholder inherits, from its layout, an outline of two + // elements: a frame with two holes, one of them round, and a second path holding a + // triangle that crosses the round one: + createSdImpressDoc("pptx/custgeom-placeholder.pptx"); + + // The outline arrives as the shape's clip polygon, in the shape's own coordinates and 1/100 mm, + // and covers the same area whichever format it has just been through. Dropping it left a plain + // rectangle, whose fill then covered the slide behind it. + auto checkOutline = [this](const OString& rWhen) { + drawing::PolyPolygonBezierCoords aClip; + CPPUNIT_ASSERT(getShapeFromPage(0, 0)->getPropertyValue(u"GraphicClipPolyPolygon"_ustr) + >>= aClip); + + // The frame is 9000000 x 5000000 EMU and the path spans the same, so a point maps to + // 1/100 mm by EMU alone: 9000000 becomes 25000, 5000000 becomes 13889. Each contour is + // closed, so it states its first point again at the end. + CPPUNIT_ASSERT_EQUAL_MESSAGE(rWhen.getStr(), sal_Int32(3), aClip.Coordinates.getLength()); + const awt::Point aExpected[2][5] = { + { { 0, 0 }, { 25000, 0 }, { 25000, 13889 }, { 0, 13889 }, { 0, 0 } }, + { { 1111, 8889 }, { 1111, 13056 }, { 9722, 13056 }, { 9722, 8889 }, { 1111, 8889 } } + }; + for (sal_Int32 nContour = 0; nContour < 2; ++nContour) + { + const OString aWhich = rWhen + ", contour " + OString::number(nContour); + CPPUNIT_ASSERT_EQUAL_MESSAGE(aWhich.getStr(), sal_Int32(5), + aClip.Coordinates[nContour].getLength()); + for (sal_Int32 nPoint = 0; nPoint < 5; ++nPoint) + { + const OString aWhere = aWhich + ", point " + OString::number(nPoint); + CPPUNIT_ASSERT_EQUAL_MESSAGE(aWhere.getStr(), aExpected[nContour][nPoint].X, + aClip.Coordinates[nContour][nPoint].X); + CPPUNIT_ASSERT_EQUAL_MESSAGE(aWhere.getStr(), aExpected[nContour][nPoint].Y, + aClip.Coordinates[nContour][nPoint].Y); + } + } + + // What the third contour is worth saying about is the area it leaves, so the shape is asked + // where a click reaches it: the hit test walks the primitives it paints, so the mask + // clipping them answers here just as it does on screen. + auto xPlaceholder = getShapeFromPage(0, 0).queryThrow(); + SdrObject* pPlaceholder = SdrObject::getSdrObjectFromXShape(xPlaceholder); + CPPUNIT_ASSERT(pPlaceholder); + SdrPageView* pPageView = getSdDocShell()->GetViewShell()->GetView()->GetSdrPageView(); + CPPUNIT_ASSERT(pPageView); + const Point aTopLeft(pPlaceholder->GetSnapRect().TopLeft()); + struct Probe + { + std::string_view aWhat; + Point aAt; + bool bPicked; + }; + const Probe aProbes[] = { + { "the frame itself", { 2000, 2000 }, true }, + { "the rectangular hole", { 5400, 11000 }, false }, + // The round hole is a hole above the triangle and covered below it: a path of its own + // is filled rather than cut out, so it takes a piece of that hole back. Reading the two + // paths as one polygon subtracted the triangle instead, and the hole grew. + { "the round hole, above the triangle", { 17500, 7500 }, false }, + { "the round hole, inside the triangle", { 17500, 11500 }, true }, + }; + for (const Probe& rProbe : aProbes) + { + const OString aWhere = rWhen + ", " + OString(rProbe.aWhat.data(), rProbe.aWhat.size()); + // No tolerance, so the areas answer and the outline drawn around them does not. + CPPUNIT_ASSERT_EQUAL_MESSAGE(aWhere.getStr(), rProbe.bPicked, + SdrObjectPrimitiveHit(*pPlaceholder, aTopLeft + rProbe.aAt, + {}, *pPageView, nullptr, false) + != nullptr); + } + }; + + checkOutline("as imported"_ostr); + + // Saving states the outline on the slide as well as on its layout, so reading the file back + // gives the shape a geometry of its own where it used to have only the one it inherits. The + // shape's own has to replace that, not join it: two geometries at once are not one this reads, + // and the placeholder came back unclipped - PowerPoint meanwhile showed the very file + // correctly. + saveAndReload(TestFilter::PPTX); + checkOutline("after a PPTX round-trip"_ostr); + + // ODF carries it as a loext:graphic-clip-poly child of the frame, and has the same to answer + // for: the same outline, from the same document, through the other format. + saveAndReload(TestFilter::ODP); + checkOutline("after an ODP round-trip"_ostr); +} + +CPPUNIT_TEST_FIXTURE(SdImportTest2, testCool16080_masterPageOrder) +{ + // Given a deck whose slide master lists eleven layouts, related as rId1 to rId11: + createSdImpressDoc("pptx/master-and-eleven-layouts.pptx"); + + // The master pages follow the order the slide master lists its layouts in. Without the fix + // they followed the relations, which are keyed by the relationship id as a string, so the + // tenth and eleventh layouts arrived right behind the first. + static constexpr std::u16string_view aExpected[] = { + u"Title Slide", + u"Title and Content", + u"Section Header", + u"Two Content", + u"Comparison", + u"Title Only", + u"Blank", + u"Content with Caption", + u"Picture with Caption", + u"Title and Vertical Text", + u"Vertical Title and Text", + }; + + auto xMasterPages = mxComponent.queryThrow()->getMasterPages(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(std::size(aExpected)), xMasterPages->getCount()); + for (sal_Int32 i = 0; i < xMasterPages->getCount(); ++i) + { + CPPUNIT_ASSERT_EQUAL( + OUString(aExpected[i]), + xMasterPages->getByIndex(i).queryThrow()->getName()); + } +} + +CPPUNIT_TEST_FIXTURE(SdImportTest2, testCool16083_contentPlaceholderStaysEmpty) +{ + // Given four slides, each with one content placeholder, differing only in what the slide says + // about its text - and a layout whose placeholder carries text of its own: + createSdImpressDoc("pptx/content-placeholder-cases.pptx"); + + // A placeholder the file gives no text to stays an empty presentation object, which is what + // makes Impress offer the buttons that insert a table, a chart, a picture or a video. The + // layout's text is a prompt, not content: taking it filled the placeholder and took those away. + // A prompt the layout authors is a prompt too, and reaches the shape as CustomPromptText. + struct Case + { + std::string_view aWhatTheSlideSays; + bool bEmpty; + OUString aText; + OUString aPrompt; + }; + static constexpr Case aCases[] = { + { "no text body", true, u""_ustr, u""_ustr }, + { "an empty text body", true, u""_ustr, u""_ustr }, + { "a text body with content", false, u"Real content, typed by the author"_ustr, u""_ustr }, + { "no text body, prompt authored on the layout", true, u""_ustr, + u"Custom prompt to insert content"_ustr }, + }; + + for (size_t i = 0; i < std::size(aCases); ++i) + { + const Case& rCase = aCases[i]; + const OString aMessage = "slide " + OString::number(i + 1) + ", " + rCase.aWhatTheSlideSays; + auto xShape = getShapeFromPage(0, i); + bool bEmpty = false; + CPPUNIT_ASSERT(xShape->getPropertyValue(u"IsEmptyPresentationObject"_ustr) >>= bEmpty); + CPPUNIT_ASSERT_EQUAL_MESSAGE(aMessage.getStr(), rCase.bEmpty, bEmpty); + + OUString aText; + CPPUNIT_ASSERT(xShape->getPropertyValue(u"CustomPromptText"_ustr) >>= aText); + CPPUNIT_ASSERT_EQUAL_MESSAGE(aMessage.getStr(), rCase.aPrompt, aText); + + CPPUNIT_ASSERT_EQUAL_MESSAGE(aMessage.getStr(), rCase.aText, + xShape.queryThrow()->getString()); + + // An empty one still holds the text to paint - the prompt - even though the UNO text of an + // empty presentation object is empty by design. Losing it leaves a blank frame on screen, + // which is only visible on the model. The stock prompt is localized, so only the authored + // one is compared. + SdrObject* pObject = SdrObject::getSdrObjectFromXShape(xShape); + CPPUNIT_ASSERT(pObject); + OutlinerParaObject* pParagraphs = pObject->GetOutlinerParaObject(); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), pParagraphs); + if (!rCase.aPrompt.isEmpty()) + CPPUNIT_ASSERT_EQUAL_MESSAGE(aMessage.getStr(), rCase.aPrompt, + pParagraphs->GetTextObject().GetText(0)); + } +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/import-tests4.cxx b/sd/qa/unit/import-tests4.cxx index f6e8d2049bbd..b8aa8bd6c1d3 100644 --- a/sd/qa/unit/import-tests4.cxx +++ b/sd/qa/unit/import-tests4.cxx @@ -192,10 +192,7 @@ CPPUNIT_TEST_FIXTURE(SdImportTest4, testtdf163852) CPPUNIT_ASSERT_EQUAL(static_cast(0), aCrop.Top); CPPUNIT_ASSERT_EQUAL(static_cast(0), aCrop.Left); CPPUNIT_ASSERT_EQUAL(static_cast(0), aCrop.Right); - // Without the fix in place, this test would have failed with - // - Expected: 702 - // - Actual : 0 - CPPUNIT_ASSERT_EQUAL(static_cast(702), aCrop.Bottom); + CPPUNIT_ASSERT_EQUAL(static_cast(688), aCrop.Bottom); } CPPUNIT_TEST_FIXTURE(SdImportTest4, testTdf149785) diff --git a/sd/qa/unit/layout-tests.cxx b/sd/qa/unit/layout-tests.cxx index 2df4f74de48f..0aa0cd82a927 100644 --- a/sd/qa/unit/layout-tests.cxx +++ b/sd/qa/unit/layout-tests.cxx @@ -361,17 +361,10 @@ CPPUNIT_TEST_FIXTURE(SdLayoutTest, testFitToFrameTextFitting) assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]", "x", u"0"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]", "y", u"406"); -#ifndef _WIN32 // FIXME: Windows seems to differ in text layouting assertXPathDoubleValue(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", "first", 114.087, 0.001); assertXPathDoubleValue(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", "last", 6983.573, 0.001); -#else - assertXPathDoubleValue(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", "first", - 113.64, 0.001); - assertXPathDoubleValue(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", "last", - 6956.219, 0.001); -#endif } CPPUNIT_TEST_FIXTURE(SdLayoutTest, testTdf156955) @@ -503,29 +496,29 @@ CPPUNIT_TEST_FIXTURE(SdLayoutTest, testTdf164622) // - Actual : 892 // - In <>, attribute 'y' of '/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[4]' assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[1]", - "x", u"7556"); + "x", u"7543"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[1]", - "y", u"892"); + "y", u"879"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[2]", - "x", u"20440"); + "x", u"20453"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[2]", - "y", u"892"); + "y", u"879"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[3]", - "x", u"20440"); + "x", u"20453"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[3]", "y", u"8998"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[4]", - "x", u"7556"); + "x", u"7543"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[4]", "y", u"8998"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[5]", - "x", u"7556"); + "x", u"7543"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[2]/push[1]/clipregion/polygon/point[5]", - "y", u"892"); + "y", u"879"); } CPPUNIT_TEST_FIXTURE(SdLayoutTest, testTdf168010_ODP_enabled) diff --git a/sd/qa/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx index 80d3e2682b14..c44ecc8307a6 100644 --- a/sd/qa/unit/misc-tests.cxx +++ b/sd/qa/unit/misc-tests.cxx @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -59,6 +61,10 @@ #include #include #include +#include +#include +#include +#include using namespace ::com::sun::star; @@ -73,17 +79,18 @@ public: void testTdf99396_UndoCellVerticalAlignment(); void testTableObjectUndoTest(); + void testSubtitleWithParaAnimationSave(); void testFillColor(); void testFillGradient(); - void testTdf44774(); - void testTdf38225(); + void testTdf44774_KeepStyleLinksOnSave(); + void testTdf38225_ChangeCustomStyleName(); void testTdf101242_ODF_no_settings(); void testTdf101242_ODF_add_settings(); void testTdf101242_settings_keep(); void testTdf101242_settings_remove(); - void testTdf119392(); - void testTdf67248(); - void testTdf119956(); + void testTdf119392_VerifyLayerProperties(); + void testTdf67248_LayerNamesIndependentFromLocalization(); + void testTdf119956_AdaptLayerTabFocusOnAltClick(); void testTdf120527(); void testTextColumns(); void testTdf98839_ShearVFlipH(); @@ -98,21 +105,25 @@ public: void testPageBackgroundImages(); void testCanvasSlideExportODP(); void testDuplicateAndMove(); + void testApiXDrawPageDuplicator(); + void testApiXMasterPagesSupplier(); + void testEmptyPresObjSetOnObjectWithoutText(); CPPUNIT_TEST_SUITE(SdMiscTest); CPPUNIT_TEST(testTdf99396_UndoCellVerticalAlignment); CPPUNIT_TEST(testTableObjectUndoTest); + CPPUNIT_TEST(testSubtitleWithParaAnimationSave); CPPUNIT_TEST(testFillColor); CPPUNIT_TEST(testFillGradient); - CPPUNIT_TEST(testTdf44774); - CPPUNIT_TEST(testTdf38225); + CPPUNIT_TEST(testTdf44774_KeepStyleLinksOnSave); + CPPUNIT_TEST(testTdf38225_ChangeCustomStyleName); CPPUNIT_TEST(testTdf101242_ODF_no_settings); CPPUNIT_TEST(testTdf101242_ODF_add_settings); CPPUNIT_TEST(testTdf101242_settings_keep); CPPUNIT_TEST(testTdf101242_settings_remove); - CPPUNIT_TEST(testTdf119392); - CPPUNIT_TEST(testTdf67248); - CPPUNIT_TEST(testTdf119956); + CPPUNIT_TEST(testTdf119392_VerifyLayerProperties); + CPPUNIT_TEST(testTdf67248_LayerNamesIndependentFromLocalization); + CPPUNIT_TEST(testTdf119956_AdaptLayerTabFocusOnAltClick); CPPUNIT_TEST(testTdf120527); CPPUNIT_TEST(testTextColumns); CPPUNIT_TEST(testTdf98839_ShearVFlipH); @@ -127,6 +138,9 @@ public: CPPUNIT_TEST(testPageBackgroundImages); CPPUNIT_TEST(testCanvasSlideExportODP); CPPUNIT_TEST(testDuplicateAndMove); + CPPUNIT_TEST(testApiXDrawPageDuplicator); + CPPUNIT_TEST(testApiXMasterPagesSupplier); + CPPUNIT_TEST(testEmptyPresObjSetOnObjectWithoutText); CPPUNIT_TEST_SUITE_END(); }; @@ -275,6 +289,44 @@ void SdMiscTest::testTableObjectUndoTest() CPPUNIT_ASSERT_EQUAL(u"Format cell"_ustr, pDoc->GetUndoManager()->GetUndoActionComment(2)); } +void SdMiscTest::testSubtitleWithParaAnimationSave() +{ + createSdImpressDoc("pptx/subtitle-animation-save.pptx"); + + SdXImpressDocument* pXImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + CPPUNIT_ASSERT(pViewShell); + SdPage* pPage = pViewShell->GetActualPage(); + CPPUNIT_ASSERT(pPage); + + // Object 0 is the title, object 1 is the animated subtitle. + auto* pTextObj = dynamic_cast(pPage->GetObj(1)); + CPPUNIT_ASSERT(pTextObj); + CPPUNIT_ASSERT_EQUAL(u"Original subtitle"_ustr, + pTextObj->GetOutlinerParaObject()->GetTextObject().GetText(0)); + + SdrView* pView = pViewShell->GetView(); + pView->MarkObj(pTextObj, pView->GetSdrPageView()); + pView->SdrBeginTextEdit(pTextObj); + CPPUNIT_ASSERT(pView->IsTextEdit()); + auto* pOutlinerView = pView->GetTextEditOutlinerView(); + CPPUNIT_ASSERT(pOutlinerView); + EditView& rEditView = pOutlinerView->GetEditView(); + rEditView.SetSelection(ESelection(0, 0)); + rEditView.InsertText(u"edited "_ustr); + pView->SdrEndTextEdit(); + Scheduler::ProcessEventsToIdle(); + + saveAndReload(TestFilter::PPTX); + + // The whole edited text must survive; before the fix the frozen marker + // truncated it at the imported length ("edited Original s"). + uno::Reference xText( + uno::Reference(getShapeFromPage(1, 0), uno::UNO_QUERY_THROW)->getText()); + CPPUNIT_ASSERT_EQUAL(u"edited Original subtitle"_ustr, xText->getString()); +} + void SdMiscTest::testFillColor() { // Test if setting the shape fill color from color to transparent automatically turns off the fill style to none @@ -381,7 +433,7 @@ void SdMiscTest::testFillGradient() CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, Color(aColorStops.getStopColor(1))); } -void SdMiscTest::testTdf44774() +void SdMiscTest::testTdf44774_KeepStyleLinksOnSave() { createSdDrawDoc(); SdXImpressDocument* pXImpressDocument = dynamic_cast(mxComponent.get()); @@ -414,7 +466,7 @@ void SdMiscTest::testTdf44774() CPPUNIT_ASSERT_EQUAL(u"StyleA"_ustr, pStyle->GetParent()); } -void SdMiscTest::testTdf38225() +void SdMiscTest::testTdf38225_ChangeCustomStyleName() { createSdImpressDoc(); SdXImpressDocument* pXImpressDocument = dynamic_cast(mxComponent.get()); @@ -598,7 +650,7 @@ void SdMiscTest::testTdf101242_ODF_add_settings() void SdMiscTest::testTdf101242_ODF_no_settings() { // Loads a document, which has the visible/printable/locked information for layers - // only in the ODF attributes draw:display and draw:protected. The resave document + // only in the ODF attributes draw:display and draw:protected. The resaved document // should have only the ODF attributes and no config items in settings.xml. createSdDrawDoc("tdf101242_ODF.odg"); @@ -714,7 +766,7 @@ void SdMiscTest::testTdf101242_settings_remove() assertXPath(pXmlDoc2, sPathStart2 + "/config:config-item[@config:name='LockedLayers']", 0); } -void SdMiscTest::testTdf119392() +void SdMiscTest::testTdf119392_VerifyLayerProperties() { // Loads a document which has two user layers "V--" and "V-L". Inserts a new layer "-P-" between them. // Checks, that the bitfields in the saved file have the bits in the correct order, in case @@ -768,10 +820,10 @@ void SdMiscTest::testTdf119392() CPPUNIT_ASSERT_EQUAL(0x80, static_cast(aDecodedSeq[0]) & 0xff); } -void SdMiscTest::testTdf67248() +void SdMiscTest::testTdf67248_LayerNamesIndependentFromLocalization() { // The document tdf67248.odg has been created with a German UI. It has a user layer named "Background". - // On opening the user layer must still exists. The error was, that it was merged into the standard + // On opening the user layer must still exist. The error was, that it was merged into the standard // layer "background". createSdDrawDoc("tdf67248.odg"); SdXImpressDocument* pXImpressDocument = dynamic_cast(mxComponent.get()); @@ -781,7 +833,7 @@ void SdMiscTest::testTdf67248() CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), rLayerAdmin.GetLayerCount()); } -void SdMiscTest::testTdf119956() +void SdMiscTest::testTdf119956_AdaptLayerTabFocusOnAltClick() { createSdDrawDoc("tdf119956.odg"); SdXImpressDocument* pXImpressDocument = dynamic_cast(mxComponent.get()); @@ -867,7 +919,7 @@ void SdMiscTest::testTdf130988() = dynamic_cast(pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj()); CPPUNIT_ASSERT(pObj); - // Error was, that the created 3D object had a wrong path. Instead examining + // Error was, that the created 3D object had a wrong path. Instead of examining // the path directly, I use the scene distance, because that is easier. The // scene distance is calculated from the object while creating. const double fDistance = pObj->GetDistance(); @@ -1169,7 +1221,8 @@ void SdMiscTest::testPageBackgroundImages() CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(0)); SdPage* pPage = pViewShell->GetActualPage(); - SfxItemSetFixed aMergedAttr(pDocument->GetPool()); + SfxItemSet aMergedAttr(SfxItemSet::makeFixedSfxItemSet( + pDocument->GetPool())); SdStyleSheet* pStyleSheet = pPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND); sd::MergePageBackgroundFilling(pPage, pStyleSheet, false, aMergedAttr); @@ -1186,7 +1239,8 @@ void SdMiscTest::testPageBackgroundImages() SdPage* pPage = pViewShell->GetActualPage(); // Style should be "BITMAP" - SfxItemSetFixed aMergedAttr(pDocument->GetPool()); + SfxItemSet aMergedAttr(SfxItemSet::makeFixedSfxItemSet( + pDocument->GetPool())); SdStyleSheet* pStyleSheet = pPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND); sd::MergePageBackgroundFilling(pPage, pStyleSheet, false, aMergedAttr); @@ -1202,7 +1256,8 @@ void SdMiscTest::testPageBackgroundImages() SdPage* pPage = pViewShell->GetActualPage(); // Style should be "BITMAP" - SfxItemSetFixed aMergedAttr(pDocument->GetPool()); + SfxItemSet aMergedAttr(SfxItemSet::makeFixedSfxItemSet( + pDocument->GetPool())); SdStyleSheet* pStyleSheet = pPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND); sd::MergePageBackgroundFilling(pPage, pStyleSheet, false, aMergedAttr); @@ -1217,7 +1272,8 @@ void SdMiscTest::testPageBackgroundImages() CPPUNIT_ASSERT_EQUAL(true, pDrawViewShell->SwitchPage(3)); SdPage* pPage = pViewShell->GetActualPage(); - SfxItemSetFixed aMergedAttr(pDocument->GetPool()); + SfxItemSet aMergedAttr(SfxItemSet::makeFixedSfxItemSet( + pDocument->GetPool())); SdStyleSheet* pStyleSheet = pPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND); sd::MergePageBackgroundFilling(pPage, pStyleSheet, false, aMergedAttr); @@ -1286,6 +1342,52 @@ void SdMiscTest::testDuplicateAndMove() CPPUNIT_ASSERT_EQUAL(pFirstPage->GetObj(0)->GetSnapRect(), pLastPage->GetObj(0)->GetSnapRect()); } +void SdMiscTest::testApiXDrawPageDuplicator() +{ + createSdImpressDoc(); + uno::Reference xDrawPagesSupplier(mxComponent, + uno::UNO_QUERY_THROW); + uno::Reference xDrawPages(xDrawPagesSupplier->getDrawPages(), + uno::UNO_SET_THROW); + sal_Int32 nOldCount = xDrawPages->getCount(); + + uno::Reference xPage(xDrawPages->getByIndex(0), uno::UNO_QUERY_THROW); + uno::Reference xDuplicator(mxComponent, uno::UNO_QUERY_THROW); + uno::Reference xNewPage = xDuplicator->duplicate(xPage); + + CPPUNIT_ASSERT(xNewPage.is()); + CPPUNIT_ASSERT_EQUAL(nOldCount + 1, xDrawPages->getCount()); +} + +void SdMiscTest::testApiXMasterPagesSupplier() +{ + createSdImpressDoc(); + uno::Reference xMasterPagesSupplier(mxComponent, + uno::UNO_QUERY_THROW); + uno::Reference xMasterPages(xMasterPagesSupplier->getMasterPages(), + uno::UNO_SET_THROW); + CPPUNIT_ASSERT(xMasterPages->getCount() >= 1); +} + +void SdMiscTest::testEmptyPresObjSetOnObjectWithoutText() +{ + // Given an empty picture placeholder, which holds no outliner text at all: + createSdImpressDoc("pptx/tdfpictureplaceholder.pptx"); + uno::Reference xShape(getShapeFromPage(0, 0)); + bool bEmpty = false; + CPPUNIT_ASSERT(xShape->getPropertyValue(u"IsEmptyPresentationObject"_ustr) >>= bEmpty); + CPPUNIT_ASSERT(bEmpty); + + // Then saying it is not empty and empty again must go through. Setting it back read the + // object's text to take a style from it without checking that there is any, so this crashed - + // a macro can reach it, and so can anything else that sets the property twice. + xShape->setPropertyValue(u"IsEmptyPresentationObject"_ustr, uno::Any(false)); + xShape->setPropertyValue(u"IsEmptyPresentationObject"_ustr, uno::Any(true)); + + CPPUNIT_ASSERT(xShape->getPropertyValue(u"IsEmptyPresentationObject"_ustr) >>= bEmpty); + CPPUNIT_ASSERT(bEmpty); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdMiscTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sd/qa/unit/sdmodeltestbase.hxx b/sd/qa/unit/sdmodeltestbase.hxx index f0f5affed889..7d69fcae1e80 100644 --- a/sd/qa/unit/sdmodeltestbase.hxx +++ b/sd/qa/unit/sdmodeltestbase.hxx @@ -100,6 +100,28 @@ public: return xShape; } + /** The exported slide layout carrying this name, whatever number its part got + + A layout's part number is its position in the master's list, and that moves as soon as a + document gains, loses or reorders one; the name says what the layout is for. + */ + xmlDocUniquePtr parseExportedLayoutNamed(std::u16string_view aName) + { + xmlDocUniquePtr pMaster = parseExport(u"ppt/slideMasters/slideMaster1.xml"_ustr); + const int nLayouts + = countXPathNodes(pMaster, "/p:sldMaster/p:sldLayoutIdLst/p:sldLayoutId"); + xmlDocUniquePtr pFound; + for (int i = 1; i <= nLayouts && !pFound; ++i) + { + xmlDocUniquePtr pLayout + = parseExport("ppt/slideLayouts/slideLayout" + OUString::number(i) + ".xml"); + if (getXPath(pLayout, "/p:sldLayout/p:cSld", "name") == aName) + pFound = std::move(pLayout); + } + CPPUNIT_ASSERT_MESSAGE("no exported slide layout of that name", pFound); + return pFound; + } + // very confusing ... UNO index-based access to pages is 0-based. This one is 1-based const SdrPage* GetPage(int nPage) { diff --git a/sd/qa/unit/tiledrendering/data/bullet-image-link.fodp b/sd/qa/unit/tiledrendering/data/bullet-image-link.fodp new file mode 100644 index 000000000000..019be76f08cf --- /dev/null +++ b/sd/qa/unit/tiledrendering/data/bullet-image-link.fodp @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + First bullet with remote image + + + Second bullet with remote image + + + + + + + + diff --git a/sd/qa/unit/tiledrendering/data/form-image-link.fodp b/sd/qa/unit/tiledrendering/data/form-image-link.fodp new file mode 100644 index 000000000000..14402ef3d1fe --- /dev/null +++ b/sd/qa/unit/tiledrendering/data/form-image-link.fodp @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/sd/qa/unit/tiledrendering/data/master-page-background-link.fodp b/sd/qa/unit/tiledrendering/data/master-page-background-link.fodp new file mode 100644 index 000000000000..bb703c25c506 --- /dev/null +++ b/sd/qa/unit/tiledrendering/data/master-page-background-link.fodp @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + Slide using a master page whose background is a remote image. + + + + + + diff --git a/sd/qa/unit/tiledrendering/data/shape-fill-link.fodp b/sd/qa/unit/tiledrendering/data/shape-fill-link.fodp new file mode 100644 index 000000000000..fd7be9e036b7 --- /dev/null +++ b/sd/qa/unit/tiledrendering/data/shape-fill-link.fodp @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + Shape with remote fill image. + + + + + diff --git a/sd/qa/unit/tiledrendering/data/slide-background-link.fodp b/sd/qa/unit/tiledrendering/data/slide-background-link.fodp new file mode 100644 index 000000000000..6879e97dee71 --- /dev/null +++ b/sd/qa/unit/tiledrendering/data/slide-background-link.fodp @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + Slide with remote background image. + + + + + + diff --git a/sd/qa/unit/tiledrendering/tiledrendering2.cxx b/sd/qa/unit/tiledrendering/tiledrendering2.cxx index 269e3fea3de9..3c35b9c909e0 100644 --- a/sd/qa/unit/tiledrendering/tiledrendering2.cxx +++ b/sd/qa/unit/tiledrendering/tiledrendering2.cxx @@ -12,12 +12,17 @@ #include #include +#include #include #include #include +#include + +#include #include #include +#include #include using namespace css; @@ -141,6 +146,12 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testNotesViewInvalidations) #if ENABLE_PDFIMPORT CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPdfiumLinks) { + auto pPdfium = vcl::pdf::PDFiumLibrary::get(); + if (!pPdfium) + { + return; + } + // Given a pdf file with links: SdXImpressDocument* pDoc = createDoc("link_2p.pdf"); SdTestViewCallback aView; @@ -174,6 +185,123 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPdfiumLinks) } #endif +CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideBackgroundRemoteNotFetched) +{ + // Slide background fill image with a remote URL must not fetch + // the URL during paint when link updates are not allowed. + // The assert in createNewSdrFillGraphicAttribute will fire if + // a remote fetch is attempted. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"slide-background-link.fodp", aParams); + SdXImpressDocument* pImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pImpressDocument); + + // The slide's deferred remote background fill bitmap is registered as an + // external link as the page is imported, so it appears in Edit, Links to + // External Files and can be updated or broken. + sfx2::LinkManager* pLinkMgr = pImpressDocument->GetDoc()->GetLinkManager(); + CPPUNIT_ASSERT(pLinkMgr); + CPPUNIT_ASSERT_MESSAGE("slide background fill bitmap link should be registered", + !pLinkMgr->GetLinks().empty()); + + pImpressDocument->initializeForTiledRendering({}); + + ScopedVclPtrInstance pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetOutputSizePixel(Size(1024, 768)); + pImpressDocument->paintTile(*pDevice, 1024, 768, 0, 0, 15360, 7680); +} + +CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testMasterPageBackgroundRemoteNotFetched) +{ + // A master page background fill image with a remote URL must not fetch + // the URL during paint when link updates are not allowed. The master + // background lands on the master's presentation style sheet, not on the + // page item set, so the link is registered through the SfxStyleSheet path + // rather than the SdrPage one. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"master-page-background-link.fodp", aParams); + SdXImpressDocument* pImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pImpressDocument); + + sfx2::LinkManager* pLinkMgr = pImpressDocument->GetDoc()->GetLinkManager(); + CPPUNIT_ASSERT(pLinkMgr); + CPPUNIT_ASSERT_MESSAGE("master page background fill bitmap link should be registered", + !pLinkMgr->GetLinks().empty()); + + pImpressDocument->initializeForTiledRendering({}); + + ScopedVclPtrInstance pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetOutputSizePixel(Size(1024, 768)); + pImpressDocument->paintTile(*pDevice, 1024, 768, 0, 0, 15360, 7680); +} + +CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testBulletImageRemoteNotFetched) +{ + // text:list-level-style-image with a remote URL must not fetch + // the URL during paint when link updates are not allowed. + // Currently the editeng rendering path silently skips unresolved + // GraphicExternalLink graphics (GraphicType::Default is not handled + // by create2DDecompositionOfGraphic). If someone adds fetching here, + // this test should catch it. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"bullet-image-link.fodp", aParams); + SdXImpressDocument* pImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pImpressDocument); + pImpressDocument->initializeForTiledRendering({}); + + ScopedVclPtrInstance pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetOutputSizePixel(Size(1024, 768)); + pImpressDocument->paintTile(*pDevice, 1024, 768, 0, 0, 15360, 7680); +} + +CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testShapeFillRemoteNotFetched) +{ + // draw:fill-image with a remote URL on a shape must not fetch + // the URL during paint when link updates are not allowed. + // The assert in createNewSdrFillGraphicAttribute will fire if + // a remote fetch is attempted. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"shape-fill-link.fodp", aParams); + SdXImpressDocument* pImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pImpressDocument); + pImpressDocument->initializeForTiledRendering({}); + + ScopedVclPtrInstance pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetOutputSizePixel(Size(1024, 768)); + pImpressDocument->paintTile(*pDevice, 1024, 768, 0, 0, 15360, 7680); +} + +CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testFormImageRemoteNotFetched) +{ + // Form image button with a remote ImageURL must not fetch the + // URL during import when link updates are not allowed. + uno::Sequence aParams = { + comphelper::makePropertyValue(u"UpdateDocMode"_ustr, + sal_Int16(css::document::UpdateDocMode::NO_UPDATE)), + }; + loadFromFile(u"form-image-link.fodp", aParams); + SdXImpressDocument* pImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pImpressDocument); + pImpressDocument->initializeForTiledRendering({}); + + ScopedVclPtrInstance pDevice(DeviceFormat::WITHOUT_ALPHA); + pDevice->SetOutputSizePixel(Size(1024, 768)); + // FIXME: it fails with void DeInitVCL(): Assertion `vcl::Window::IsLOKWindowsEmpty()' failed + // pImpressDocument->paintTile(*pDevice, 1024, 768, 0, 0, 15360, 7680); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/uiimpress.cxx b/sd/qa/unit/uiimpress.cxx index e44dfddb607f..1335ed4f8fea 100644 --- a/sd/qa/unit/uiimpress.cxx +++ b/sd/qa/unit/uiimpress.cxx @@ -11,6 +11,7 @@ #include +#include #include #include #include @@ -27,7 +28,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -35,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -56,13 +62,14 @@ #include #include #include -#include #include #include #include #include #include +#include +#include #include #include #include @@ -83,7 +90,8 @@ public: void checkCurrentPageNumber(sal_uInt16 nNum); void insertStringToObject(sal_uInt16 nObj, std::u16string_view rStr, bool bUseEscape); - sd::slidesorter::SlideSorterViewShell* getSlideSorterViewShell(); + sd::slidesorter::SlideSorterViewShell* + getSlideSorterViewShell(const css::uno::Reference& xComp = nullptr); void lcl_search(const OUString& rKey, bool bFindAll = false, bool bBackwards = false); }; @@ -125,9 +133,11 @@ void SdUiImpressTest::insertStringToObject(sal_uInt16 nObj, std::u16string_view } } -sd::slidesorter::SlideSorterViewShell* SdUiImpressTest::getSlideSorterViewShell() +sd::slidesorter::SlideSorterViewShell* +SdUiImpressTest::getSlideSorterViewShell(const css::uno::Reference& xComp) { - auto pXImpressDocument = dynamic_cast(mxComponent.get()); + auto pXImpressDocument + = dynamic_cast(xComp.is() ? xComp.get() : mxComponent.get()); sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); CPPUNIT_ASSERT(pViewShell); sd::slidesorter::SlideSorterViewShell* pSSVS = nullptr; @@ -550,6 +560,38 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf169813_prevent_unintended_dashed_li CPPUNIT_ASSERT_EQUAL(drawing::LineStyle_NONE, rStyleItem.GetValue()); } +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf148629_disabled_demote_command) +{ + createSdImpressDoc(); + SdXImpressDocument* pXImpressDocument = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + CPPUNIT_ASSERT(pViewShell); + + // Start text edit of the empty content shape + SdPage* pActualPage = pViewShell->GetActualPage(); + pActualPage->SetAutoLayout(AUTOLAYOUT_TITLE_CONTENT, true); + insertStringToObject(1, u"List Item", /*bUseEscape*/ false); + + // Check that the demote command is enabled + std::unique_ptr pItem; + CPPUNIT_ASSERT_EQUAL( + SfxItemState::DEFAULT, + pViewShell->GetViewFrame()->GetBindings().QueryState(SID_OUTLINE_RIGHT, pItem)); + + // Start text edit of the empty title shape + typeKey(pXImpressDocument, KEY_ESCAPE); + insertStringToObject(0, u"Title", /*bUseEscape*/ false); + + // Without the fix in place, this test would have failed with: + // - Expected: 1 (SfxItemState::DISABLED) + // - Actual : 32 (SfxItemState::DEFAULT) + // i.e. the demote command was not disabled + CPPUNIT_ASSERT_EQUAL( + SfxItemState::DISABLED, + pViewShell->GetViewFrame()->GetBindings().QueryState(SID_OUTLINE_RIGHT, pItem)); +} + CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf162455) { createSdImpressDoc(); @@ -588,6 +630,97 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf162455) CPPUNIT_ASSERT_DOUBLES_EQUAL(7.5, fFontSize1, 0.01); } +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testSetHyperlinkKeepSelection) +{ + // Given an Impress doc with a rectangle shape, in text edit mode, with "f" typed and + // selected: + createSdImpressDoc(); + auto* pXImpressDocument = dynamic_cast(mxComponent.get()); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + SdrView* pView = pViewShell->GetView(); + SdPage* pPage = pViewShell->GetActualPage(); + + rtl::Reference pRect + = new SdrRectObj(pView->getSdrModelFromSdrView(), tools::Rectangle(1000, 1000, 5000, 5000)); + pPage->NbcInsertObject(pRect.get()); + + pView->MarkObj(pRect.get(), pView->GetSdrPageView()); + pView->SdrBeginTextEdit(pRect.get()); + CPPUNIT_ASSERT(pView->IsTextEdit()); + + SfxStringItem aInputString(SID_ATTR_CHAR, u"f"_ustr); + pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, SfxCallMode::SYNCHRON, + { &aInputString }); + + OutlinerView* pOlView = pView->GetTextEditOutlinerView(); + CPPUNIT_ASSERT(pOlView); + pOlView->SetSelection(ESelection(0, 0, 0, 1)); + CPPUNIT_ASSERT(pOlView->HasSelection()); + + // When dispatching .uno:SetHyperlink with Hyperlink.Text differing from the selection, + // but marked as a hint: + uno::Sequence aArgs = { + comphelper::makePropertyValue(u"Hyperlink.Text"_ustr, uno::Any(u"mytext"_ustr)), + comphelper::makePropertyValue(u"Hyperlink.TextIsHint"_ustr, uno::Any(true)), + comphelper::makePropertyValue(u"Hyperlink.URL"_ustr, + uno::Any(u"http://www.example.com"_ustr)), + }; + dispatchCommand(mxComponent, u".uno:SetHyperlink"_ustr, aArgs); + + // Then make sure the previously-selected character is preserved as the URL field's + // displayed text, not replaced by Hyperlink.Text: + pView->SdrEndTextEdit(); + const OutlinerParaObject* pOPO = pRect->GetOutlinerParaObject(); + CPPUNIT_ASSERT(pOPO); + const SvxFieldData* pField + = pOPO->GetTextObject().GetFieldData(0, 0, css::text::textfield::Type::URL); + auto* pURLField = dynamic_cast(pField); + CPPUNIT_ASSERT(pURLField); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: f + // - Actual : mytext + // i.e. the selected character was lost, the provided text hint was used. + CPPUNIT_ASSERT_EQUAL(u"f"_ustr, pURLField->GetRepresentation()); +} + +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testSlidePasteSizeMismatch) +{ + // Given a 4:3 presentation, with the first slide selected: + createSdImpressDoc("odp/4-3.odp"); + sd::slidesorter::controller::SlideSorterController& rSrcCtl + = getSlideSorterViewShell()->GetSlideSorter().GetController(); + auto pSrcImpress = dynamic_cast(mxComponent.get()); + SdPage* pSrcFirst = pSrcImpress->GetDoc()->GetSdPage(0, PageKind::Standard); + rSrcCtl.GetPageSelector().DeselectAllPages(); + rSrcCtl.GetPageSelector().SelectPage(pSrcFirst); + + // When copying that slide and pasting it into a 16:9 presentation: + rSrcCtl.GetClipboard().DoCopy(); + // Disable internal paste to hit the clipboard save + load code-path. + SdModule::get()->pTransferClip = nullptr; + mxComponent2 = loadFromDesktop(createFileURL(u"odp/16-9.odp"), + u"com.sun.star.presentation.PresentationDocument"_ustr); + auto* pDstImpress = dynamic_cast(mxComponent2.get()); + SdDrawDocument* pDstDoc = pDstImpress->GetDoc(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pDstDoc->GetSdPageCount(PageKind::Standard)); + sd::slidesorter::SlideSorterViewShell* pDstSSVS = getSlideSorterViewShell(mxComponent2); + sd::slidesorter::controller::SlideSorterController& rDstCtl + = pDstSSVS->GetSlideSorter().GetController(); + SdPage* pDstLast = pDstDoc->GetSdPage(0, PageKind::Standard); + rDstCtl.GetPageSelector().DeselectAllPages(); + rDstCtl.GetPageSelector().SelectPage(pDstLast); + rDstCtl.GetClipboard().PasteSlidesFromSystemClipboard(); + + // Then make sure paste results in 2 slides: + sal_uInt16 nActualPageCount = pDstDoc->GetSdPageCount(PageKind::Standard); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 1 + // i.e. an unexpected non-async dialog popped up, which gets cancelled in silent mode, so the + // paste fails. + CPPUNIT_ASSERT_EQUAL(static_cast(2), nActualPageCount); +} + CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf96206) { // Copying/pasting slide referring to a non-default master with a text duplicated the master @@ -905,7 +1038,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy) OUString aMasterPageName = pMasterPage->GetName(); CPPUNIT_ASSERT_EQUAL(u"master"_ustr, aMasterPageName); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pMasterPage); @@ -920,7 +1053,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy) OUString aNewMasterPageName = pNewMasterPage->GetName(); CPPUNIT_ASSERT_EQUAL(u"1_master"_ustr, aNewMasterPageName); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pMasterPage); @@ -933,7 +1066,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy) OUString aNewMasterPageName2 = pNewMasterPage2->GetName(); CPPUNIT_ASSERT_EQUAL(u"2_master"_ustr, aNewMasterPageName2); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pMasterPage); @@ -970,7 +1103,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy_Default) OUString aMasterPageName = pMasterPage->GetName(); CPPUNIT_ASSERT_EQUAL(u"Default"_ustr, aMasterPageName); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pMasterPage); @@ -985,7 +1118,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy_Default) OUString aNewMasterPageName = pNewMasterPage->GetName(); CPPUNIT_ASSERT_EQUAL(u"1_Default"_ustr, aNewMasterPageName); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pMasterPage); // Copy again @@ -997,7 +1130,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy_Default) OUString aNewMasterPageName2 = pNewMasterPage2->GetName(); CPPUNIT_ASSERT_EQUAL(u"2_Default"_ustr, aNewMasterPageName2); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pMasterPage); // Copy again @@ -1026,7 +1159,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy_CopiedPage) OUString aMasterPageName = pMasterPage->GetName(); CPPUNIT_ASSERT_EQUAL(u"Master3"_ustr, aMasterPageName); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pMasterPage); // Copy and paste the master page @@ -1039,7 +1172,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy_CopiedPage) OUString aNewMasterPageName = pNewMasterPage->GetName(); CPPUNIT_ASSERT_EQUAL(u"1_Master3"_ustr, aNewMasterPageName); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pNewMasterPage); // Copy again @@ -1052,7 +1185,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy_CopiedPage) OUString aNewMasterPageName2 = pNewMasterPage2->GetName(); CPPUNIT_ASSERT_EQUAL(u"2_Master3"_ustr, aNewMasterPageName2); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pNewMasterPage2); // Copy again @@ -1065,7 +1198,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf45617_Double_Copy_CopiedPage) OUString aNewMasterPageName3 = pNewMasterPage3->GetName(); CPPUNIT_ASSERT_EQUAL(u"3_Master3"_ustr, aNewMasterPageName3); - // Reslect the master page + // Reselect the master page rSSController.GetPageSelector().DeselectAllPages(); rSSController.GetPageSelector().SelectPage(pNewMasterPage); // Copy again @@ -1866,7 +1999,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf123841) drawing::FillStyle eFillStyle = drawing::FillStyle_NONE; XPropSet->getPropertyValue(u"FillStyle"_ustr) >>= eFillStyle; - // Without the fix in place, this test would have failed with + // Without the fix in place, this test would have failed // with drawing::FillStyle_NONE != drawing::FillStyle_SOLID CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, eFillStyle); } @@ -1954,14 +2087,13 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testCharColorTheme) aComplexColor.addTransformation({ model::TransformationType::LumMod, 2000 }); aComplexColor.addTransformation({ model::TransformationType::LumOff, 8000 }); - OUString aJSON - = OStringToOUString(model::color::convertToJSON(aComplexColor), RTL_TEXTENCODING_UTF8); - // When setting the fill color of that shape, with theme metadata & effects: uno::Sequence aColorArgs = { comphelper::makePropertyValue(u"Color.Color"_ustr, sal_Int32(0xdae3f3)), // 80% light blue - comphelper::makePropertyValue(u"Color.ComplexColorJSON"_ustr, uno::Any(aJSON)), + comphelper::makePropertyValue( + u"Color.ComplexColor"_ustr, + uno::Any(model::color::createXComplexColor(aComplexColor))), }; dispatchCommand(mxComponent, u".uno:Color"_ustr, aColorArgs); } @@ -2011,14 +2143,12 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testFillColorTheme) aComplexColor.addTransformation({ model::TransformationType::LumMod, 4000 }); aComplexColor.addTransformation({ model::TransformationType::LumOff, 6000 }); - OUString aJSON - = OStringToOUString(model::color::convertToJSON(aComplexColor), RTL_TEXTENCODING_UTF8); - // When setting the fill color of that shape, with theme metadata & effects: uno::Sequence aColorArgs = { comphelper::makePropertyValue(u"FillColor.Color"_ustr, sal_Int32(0xed7d31)), // orange - comphelper::makePropertyValue(u"FillColor.ComplexColorJSON"_ustr, - uno::Any(aJSON)), // accent 1 + comphelper::makePropertyValue( + u"FillColor.ComplexColor"_ustr, + uno::Any(model::color::createXComplexColor(aComplexColor))), // accent 1 }; dispatchCommand(mxComponent, u".uno:FillColor"_ustr, aColorArgs); } @@ -2216,7 +2346,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testThemeShapeInsert) dispatchCommand(mxComponent, ".uno:BasicShapes.round-rectangle", aArgs); - // Then make sure the that fill color of the last shape is the accent1 color: + // Then make sure that the fill color of the last shape is the accent1 color: sal_Int32 nShapeIndex = xDrawPage->getCount() - 1; uno::Reference xShape(xDrawPage->getByIndex(nShapeIndex), uno::UNO_QUERY); sal_Int32 nFillColor{}; @@ -2350,7 +2480,7 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testNumToBullet) CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testBulletOffOn) { - // Given a document with a shape, last paragraph is has a bullet: + // Given a document with a shape, last paragraph it has a bullet: createSdImpressDoc("odp/bullet-off-on.odp"); sd::ViewShell* pViewShell = getSdDocShell()->GetViewShell(); CPPUNIT_ASSERT(pViewShell); @@ -2398,6 +2528,212 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testBulletOffOn) CPPUNIT_ASSERT_EQUAL(static_cast(300), nLeftMargin + nFirstLineOffset); } +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testPasteInTextEditWithAnimationNode) +{ + createSdImpressDoc(); + + // Give the slide an (empty) animation node, so the paragraph removal that the + // paste below performs is reported to the animation sequence. + uno::Reference xModel(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawView(xModel->getCurrentController(), uno::UNO_QUERY); + uno::Reference xDrawPage(xDrawView->getCurrentPage(), uno::UNO_SET_THROW); + uno::Reference xAnimNodeSupplier(xDrawPage, + uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xAnimNodeSupplier->getAnimationNode().is()); + + // Type a word into the title placeholder, staying in text edit. + insertStringToObject(0, u"blah", /*bUseEscape*/ false); + + // Select and copy it, then put the caret at the end so the paste appends. + auto pImpressDocument = dynamic_cast(mxComponent.get()); + dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {}); + dispatchCommand(mxComponent, u".uno:Copy"_ustr, {}); + typeKey(pImpressDocument, KEY_END); + + // Without the accompanying fix, this paste asserts in a dbgutil build: the + // paragraph removal probes the shape text through the UNO forwarder, forcing + // a text frame layout recompute while the EditEngine layout is suspended. + dispatchCommand(mxComponent, u".uno:Paste"_ustr, {}); + + // The word got appended to itself. + sd::ViewShell* pViewShell = pImpressDocument->GetDocShell()->GetViewShell(); + SdrView* pView = pViewShell->GetView(); + dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {}); + EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView(); + CPPUNIT_ASSERT_EQUAL(u"blahblah"_ustr, rEditView.GetSelected()); +} + +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testUndoRestoresDeletedPlaceholderText) +{ + // Given a slide whose title placeholder was typed into: + createSdImpressDoc(); + auto* pXImpressDocument = dynamic_cast(mxComponent.get()); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + sd::View* pView = pViewShell->GetView(); + SdrObject* pTitle = pViewShell->GetActualPage()->GetObj(0); + CPPUNIT_ASSERT(pTitle); + pView->MarkObj(pTitle, pView->GetSdrPageView()); + + pView->SdrBeginTextEdit(pTitle); + pView->GetTextEditOutlinerView()->GetEditView().SetSelection(ESelection::All()); + pView->GetTextEditOutlinerView()->GetEditView().InsertText(u"Typed"_ustr); + pView->SdrEndTextEdit(); + CPPUNIT_ASSERT_EQUAL(u"Typed"_ustr, + pTitle->GetOutlinerParaObject()->GetTextObject().GetText(0)); + + // When deleting all of that text, which puts the placeholder's prompt back: + pView->SdrBeginTextEdit(pTitle); + pView->GetTextEditOutlinerView()->GetEditView().SetSelection(ESelection::All()); + pView->GetTextEditOutlinerView()->GetEditView().InsertText(OUString()); + pView->SdrEndTextEdit(); + CPPUNIT_ASSERT(pTitle->IsEmptyPresObj()); + + // Then one undo brings the text back. Without the fix the deletion was not undoable at all: the + // prompt goes in before svx captures the text change, which then looks like no change. + dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); + CPPUNIT_ASSERT_EQUAL(u"Typed"_ustr, + pTitle->GetOutlinerParaObject()->GetTextObject().GetText(0)); + CPPUNIT_ASSERT(!pTitle->IsEmptyPresObj()); +} + +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf166401_imageFillsAPlaceholderHoldingText) +{ + // Given a slide whose picture placeholder holds text, so an outliner object represents it: + createSdImpressDoc("pptx/pic-placeholder-with-text.pptx"); + auto* pXImpressDocument = dynamic_cast(mxComponent.get()); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + sd::View* pView = pViewShell->GetView(); + SdrObject* pText = pViewShell->GetActualPage()->GetObj(0); + CPPUNIT_ASSERT_EQUAL(SdrObjKind::OutlineText, pText->GetObjIdentifier()); + + // When an image is put into it, which is what it is a placeholder for: + pView->MarkObj(pText, pView->GetSdrPageView()); + Graphic aGraphic(Bitmap(Size(16, 16), vcl::PixelFormat::N24_BPP)); + sal_Int8 nAction = DND_ACTION_LINK; + pView->InsertGraphic(aGraphic, nAction, pText->GetSnapRect().Center(), pText, nullptr); + + // Then a graphic object represents it, still as the picture placeholder, and the text it held + // has given way to the image. + SdrObject* pFilled = pViewShell->GetActualPage()->GetObj(0); + CPPUNIT_ASSERT_EQUAL(SdrObjKind::Graphic, pFilled->GetObjIdentifier()); + CPPUNIT_ASSERT(!pFilled->HasText()); + + // The shape type is what the page answers for the object, so it states the identity. + auto xPage = mxComponent.queryThrow() + ->getDrawPages() + ->getByIndex(0) + .queryThrow(); + auto xShape = xPage->getByIndex(0).queryThrow(); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.GraphicObjectShape"_ustr, + xShape->getShapeType()); +} + +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf166401_textGivenThroughTheApi) +{ + // Given a slide with an empty picture placeholder: + createSdImpressDoc("pptx/picture-placeholder-custom-prompt.pptx"); + auto xPage = mxComponent.queryThrow() + ->getDrawPages() + ->getByIndex(0) + .queryThrow(); + + // When text reaches it without any editing, which is the route a script takes: + xPage->getByIndex(0).queryThrow()->setString(u"Given through the API"_ustr); + Scheduler::ProcessEventsToIdle(); + + // Then an outliner object represents it, as it does for text that arrives by any other route, + // and the placeholder is still the picture one. Without the fix the placeholder went on + // standing for itself, and the text was painted the way a prompt is - unwrapped. + auto xShape = xPage->getByIndex(0).queryThrow(); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.OutlinerShape"_ustr, xShape->getShapeType()); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.GraphicObjectShape"_ustr, + xShape.queryThrow() + ->getPropertyValue(u"PlaceholderShapeType"_ustr) + .get()); + CPPUNIT_ASSERT_EQUAL(u"Given through the API"_ustr, + xShape.queryThrow()->getString()); +} + +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf166401_theEditedObjectStaysWhileEditing) +{ + // Given an empty picture placeholder in text edit, with text typed into it: + createSdImpressDoc("pptx/picture-placeholder-custom-prompt.pptx"); + auto* pXImpressDocument = dynamic_cast(mxComponent.get()); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + sd::View* pView = pViewShell->GetView(); + SdrObject* pEdited = pViewShell->GetActualPage()->GetObj(0); + pView->MarkObj(pEdited, pView->GetSdrPageView()); + pView->SdrBeginTextEdit(pEdited); + CPPUNIT_ASSERT(pView->IsTextEdit()); + pView->GetTextEditOutlinerView()->GetEditView().SetSelection(ESelection::All()); + pView->GetTextEditOutlinerView()->GetEditView().InsertText(u"While editing"_ustr); + + // When something asks that shape for its text through UNO, which is what another view does and + // which marks the object as no longer empty while the edit is still open: + auto xPage = mxComponent.queryThrow() + ->getDrawPages() + ->getByIndex(0) + .queryThrow(); + xPage->getByIndex(0).queryThrow()->getString(); + Scheduler::ProcessEventsToIdle(); + + // Then the object the edit view is working on is still the one on the page. Switching what + // represents the placeholder here took it away mid-typing: the edit was lost and editeng + // aborted on its undo manager. + CPPUNIT_ASSERT_EQUAL(pEdited, pViewShell->GetActualPage()->GetObj(0)); + if (pView->IsTextEdit()) + pView->SdrEndTextEdit(); +} + +CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf166401_anEditElsewhereIsLeftAlone) +{ + // Given two slides with a picture placeholder each, one of them in text edit with text typed + // into it: + createSdImpressDoc("pptx/picture-placeholder-custom-prompt.pptx"); + dispatchCommand(mxComponent, u".uno:DuplicatePage"_ustr, {}); + Scheduler::ProcessEventsToIdle(); + auto* pXImpressDocument = dynamic_cast(mxComponent.get()); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + sd::View* pView = pViewShell->GetView(); + SdrPage* pEditedPage = pViewShell->GetActualPage(); + SdrObject* pEdited = pEditedPage->GetObj(0); + pView->MarkObj(pEdited, pView->GetSdrPageView()); + pView->SdrBeginTextEdit(pEdited); + CPPUNIT_ASSERT(pView->IsTextEdit()); + pView->GetTextEditOutlinerView()->GetEditView().SetSelection(ESelection::All()); + pView->GetTextEditOutlinerView()->GetEditView().InsertText(u"While editing"_ustr); + + // When another view asks that object for its text, which writes the typing back and marks it + // no longer empty while the edit is still open: + auto xPages = mxComponent.queryThrow()->getDrawPages(); + xPages->getByIndex(pEditedPage->GetPageNum() / 2) + .queryThrow() + ->getByIndex(0) + .queryThrow() + ->getString(); + + // and text then reaches the placeholder on the other slide, the pass that switches what + // represents a placeholder runs over every page - and the object in text edit is not the one + // that asked for it. That is what two views editing one document look like from here. + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xPages->getCount()); + const sal_Int32 nElsewhere = pEditedPage->GetPageNum() / 2 == 0 ? 1 : 0; + auto xElsewherePage = xPages->getByIndex(nElsewhere).queryThrow(); + xElsewherePage->getByIndex(0).queryThrow()->setString( + u"Given elsewhere"_ustr); + Scheduler::ProcessEventsToIdle(); + + // Then that one is switched, so the pass did run - and the one being edited is still the object + // the edit view holds. Taking it away mid-typing lost the edit and aborted editeng on its undo + // manager, and the pass had only the object that asked for it to go by. The shape is asked + // again, since a UNO shape keeps the type it was made with. + CPPUNIT_ASSERT_EQUAL( + u"com.sun.star.presentation.OutlinerShape"_ustr, + xElsewherePage->getByIndex(0).queryThrow()->getShapeType()); + CPPUNIT_ASSERT_EQUAL(pEdited, pEditedPage->GetObj(0)); + if (pView->IsTextEdit()) + pView->SdrEndTextEdit(); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/sdi/SlideSorterController.sdi b/sd/sdi/SlideSorterController.sdi index a278785f11cd..dba06f524eab 100644 --- a/sd/sdi/SlideSorterController.sdi +++ b/sd/sdi/SlideSorterController.sdi @@ -101,6 +101,36 @@ interface SlideSorterView ExecMethod = FuTemporary ; StateMethod = GetMenuState ; ] + SID_ADD_SLIDE_SECTION + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_REMOVE_SLIDE_SECTION + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_REMOVE_SLIDE_SECTION_AND_SLIDES + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_RENAME_SLIDE_SECTION + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_MOVE_SLIDE_SECTION_UP + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_MOVE_SLIDE_SECTION_DOWN + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] SID_DELETE [ ExecMethod = FuTemporary ; diff --git a/sd/sdi/_drvwsh.sdi b/sd/sdi/_drvwsh.sdi index 3636c3f02485..73dbc6e02b54 100644 --- a/sd/sdi/_drvwsh.sdi +++ b/sd/sdi/_drvwsh.sdi @@ -192,6 +192,36 @@ interface DrawView ExecMethod = FuTemporary ; StateMethod = GetMenuState ; ] + SID_ADD_SLIDE_SECTION + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_REMOVE_SLIDE_SECTION + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_REMOVE_SLIDE_SECTION_AND_SLIDES + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_RENAME_SLIDE_SECTION + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_MOVE_SLIDE_SECTION_UP + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] + SID_MOVE_SLIDE_SECTION_DOWN + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] SID_INSERTLAYER // ole : no, status : play rec [ ExecMethod = FuTemporary ; diff --git a/sd/sdi/sdraw.sdi b/sd/sdi/sdraw.sdi index 0c7b7ad9dbb3..3e35df6eb7fd 100644 --- a/sd/sdi/sdraw.sdi +++ b/sd/sdi/sdraw.sdi @@ -1650,9 +1650,9 @@ SfxVoidItem TransformDocumentStructure FN_TRANSFORM_DOCUMENT_STRUCTURE RecordAbsolute = FALSE, RecordPerSet; - AccelConfig = TRUE, - MenuConfig = TRUE, - ToolBoxConfig = TRUE, + AccelConfig = FALSE, + MenuConfig = FALSE, + ToolBoxConfig = FALSE, GroupId = SfxGroupId::Edit; ] @@ -4265,3 +4265,105 @@ SfxVoidItem PasteSlide SID_PASTE_SLIDE ToolBoxConfig = TRUE, GroupId = SfxGroupId::Edit; ] + +SfxVoidItem AddSlideSection SID_ADD_SLIDE_SECTION +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = TRUE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Format; +] + +SfxVoidItem RemoveSlideSection SID_REMOVE_SLIDE_SECTION +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = TRUE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Format; +] + +SfxVoidItem RemoveSlideSectionAndSlides SID_REMOVE_SLIDE_SECTION_AND_SLIDES +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = TRUE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Format; +] + +SfxVoidItem RenameSlideSection SID_RENAME_SLIDE_SECTION +(SfxInt32Item SectionIndex SID_RENAME_SLIDE_SECTION, SfxStringItem Name SID_RENAMEPAGE) +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = TRUE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Format; +] + +SfxVoidItem MoveSlideSectionUp SID_MOVE_SLIDE_SECTION_UP +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = TRUE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Format; +] + +SfxVoidItem MoveSlideSectionDown SID_MOVE_SLIDE_SECTION_DOWN +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = TRUE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Format; +] diff --git a/sd/source/ui/presenter/CanvasUpdateRequester.cxx b/sd/source/console/CanvasUpdateRequester.cxx similarity index 100% rename from sd/source/ui/presenter/CanvasUpdateRequester.cxx rename to sd/source/console/CanvasUpdateRequester.cxx diff --git a/sd/source/ui/presenter/CanvasUpdateRequester.hxx b/sd/source/console/CanvasUpdateRequester.hxx similarity index 100% rename from sd/source/ui/presenter/CanvasUpdateRequester.hxx rename to sd/source/console/CanvasUpdateRequester.hxx diff --git a/sd/source/console/PresenterAccessibility.cxx b/sd/source/console/PresenterAccessibility.cxx index 34600db26d60..a25a3da0fbc7 100644 --- a/sd/source/console/PresenterAccessibility.cxx +++ b/sd/source/console/PresenterAccessibility.cxx @@ -53,7 +53,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sdext::presenter { @@ -304,6 +303,6 @@ void SAL_CALL PresenterAccessible::disposing (const css::lang::EventObject& rEve mxMainWindow = nullptr; } -} // end of namespace ::sd::presenter +} // end of namespace sdext::presenter /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/console/PresenterBitmapContainer.cxx b/sd/source/console/PresenterBitmapContainer.cxx index 36c259efaa97..1a885df5dc1f 100644 --- a/sd/source/console/PresenterBitmapContainer.cxx +++ b/sd/source/console/PresenterBitmapContainer.cxx @@ -19,7 +19,7 @@ #include "PresenterBitmapContainer.hxx" #include "PresenterConfigurationAccess.hxx" -#include +#include "PresenterHelper.hxx" #include #include diff --git a/sd/source/console/PresenterBitmapContainer.hxx b/sd/source/console/PresenterBitmapContainer.hxx index 0d0532c02236..4e79f911545e 100644 --- a/sd/source/console/PresenterBitmapContainer.hxx +++ b/sd/source/console/PresenterBitmapContainer.hxx @@ -19,7 +19,7 @@ #pragma once -#include +#include "PresenterHelper.hxx" #include #include diff --git a/sd/source/console/PresenterButton.cxx b/sd/source/console/PresenterButton.cxx index 10f5e83b4bcc..481cdf25f433 100644 --- a/sd/source/console/PresenterButton.cxx +++ b/sd/source/console/PresenterButton.cxx @@ -23,6 +23,9 @@ #include "PresenterGeometryHelper.hxx" #include "PresenterPaintManager.hxx" #include "PresenterUIPainter.hxx" + +#include + #include #include #include @@ -99,7 +102,8 @@ PresenterButton::PresenterButton( { try { - mxWindow = sd::presenter::PresenterHelper::createWindow(rxParentWindow, false); + mxWindow = VCLUnoHelper::GetInterface( + sd::presenter::PresenterHelper::createWindow(rxParentWindow, false)); // Make the background transparent. Reference xPeer (mxWindow, UNO_QUERY_THROW); diff --git a/sd/source/console/PresenterButton.hxx b/sd/source/console/PresenterButton.hxx index 2d3ee149c941..14b67ebd6d84 100644 --- a/sd/source/console/PresenterButton.hxx +++ b/sd/source/console/PresenterButton.hxx @@ -20,8 +20,8 @@ #pragma once #include "PresenterBitmapContainer.hxx" +#include "PresenterHelper.hxx" #include "PresenterTheme.hxx" -#include #include #include #include diff --git a/sd/source/ui/presenter/PresenterCanvas.cxx b/sd/source/console/PresenterCanvas.cxx similarity index 100% rename from sd/source/ui/presenter/PresenterCanvas.cxx rename to sd/source/console/PresenterCanvas.cxx diff --git a/sd/source/ui/presenter/PresenterCanvas.hxx b/sd/source/console/PresenterCanvas.hxx similarity index 100% rename from sd/source/ui/presenter/PresenterCanvas.hxx rename to sd/source/console/PresenterCanvas.hxx diff --git a/sd/source/console/PresenterController.cxx b/sd/source/console/PresenterController.cxx index dd37c6de9934..100bb30a8b68 100644 --- a/sd/source/console/PresenterController.cxx +++ b/sd/source/console/PresenterController.cxx @@ -59,7 +59,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::presentation; -using namespace ::com::sun::star::drawing::framework; namespace sdext::presenter { @@ -205,7 +204,7 @@ void PresenterController::disposing(std::unique_lock&) void PresenterController::UpdateCurrentSlide (const sal_Int32 nOffset) { - // std::cerr << "Updating current Slide to " << nOffset << std::endl; + // std::cerr << "Updating current slide to " << nOffset << std::endl; GetSlides(nOffset); UpdatePaneTitles(); UpdateViews(); @@ -663,7 +662,7 @@ void PresenterController::notifyConfigurationChange ( { InitializeMainPane(dynamic_cast(rEvent.ResourceObject.get())); } - else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT)) + else if (rEvent.ResourceId->isBoundTo(mxMainPaneId, sd::framework::AnchorBindingMode::DIRECT)) { // A pane bound to the main pane has been created and is // stored in the pane container. @@ -673,7 +672,7 @@ void PresenterController::notifyConfigurationChange ( mpPaneContainer->FindPaneId(xPane->getResourceId()); } } - else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT)) + else if (rEvent.ResourceId->isBoundTo(mxMainPaneId, sd::framework::AnchorBindingMode::INDIRECT)) { // A view bound to one of the panes has been created and is // stored in the pane container along with its pane. @@ -688,7 +687,7 @@ void PresenterController::notifyConfigurationChange ( break; case sd::framework::ConfigurationChangeEventType::ResourceDeactivation: - if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT)) + if (rEvent.ResourceId->isBoundTo(mxMainPaneId, sd::framework::AnchorBindingMode::INDIRECT)) { // If this is a view then remove it from the pane container. rtl::Reference xView = dynamic_cast(rEvent.ResourceObject.get()); @@ -772,6 +771,13 @@ void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent) switch (rEvent.KeyCode) { case awt::Key::ESCAPE: + if (mpWindowManager + && mpWindowManager->GetViewMode() == PresenterWindowManager::VM_SlideOverview) + { + mpWindowManager->SetSlideSorterState(false); + break; + } + [[fallthrough]]; case awt::Key::SUBTRACT: { if( mxController.is() ) diff --git a/sd/source/console/PresenterController.hxx b/sd/source/console/PresenterController.hxx index 5beca19b6c64..9b25152905b2 100644 --- a/sd/source/console/PresenterController.hxx +++ b/sd/source/console/PresenterController.hxx @@ -17,13 +17,13 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERCONTROLLER_HXX -#define INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERCONTROLLER_HXX +#pragma once #include "PresenterAccessibility.hxx" +#include "PresenterHelper.hxx" #include "PresenterPaneContainer.hxx" #include "PresenterTheme.hxx" -#include + #include #include #include @@ -215,6 +215,4 @@ private: } // end of namespace ::sdext::presenter -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/console/PresenterCurrentSlideObserver.cxx b/sd/source/console/PresenterCurrentSlideObserver.cxx index 27e5dc7e45e4..44f404aeb81f 100644 --- a/sd/source/console/PresenterCurrentSlideObserver.cxx +++ b/sd/source/console/PresenterCurrentSlideObserver.cxx @@ -53,7 +53,7 @@ PresenterCurrentSlideObserver::~PresenterCurrentSlideObserver() void SAL_CALL PresenterCurrentSlideObserver::disposing() { - // Disconnect form the slide show controller. + // Disconnect from the slide show controller. if(mxSlideShowController.is()) { mxSlideShowController->removeSlideShowListener(static_cast(this)); diff --git a/sd/source/console/PresenterFrameworkObserver.cxx b/sd/source/console/PresenterFrameworkObserver.cxx index d33ddfc2e151..e1091ec6d2c6 100644 --- a/sd/source/console/PresenterFrameworkObserver.cxx +++ b/sd/source/console/PresenterFrameworkObserver.cxx @@ -25,7 +25,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sdext::presenter { @@ -56,7 +55,7 @@ PresenterFrameworkObserver::~PresenterFrameworkObserver() } void PresenterFrameworkObserver::RunOnUpdateEnd ( - const rtl::Reference&rxController, + const rtl::Reference& rxController, const Action& rAction) { new PresenterFrameworkObserver( diff --git a/sd/source/console/PresenterHelpView.cxx b/sd/source/console/PresenterHelpView.cxx index 151ace77fb5a..e95f0d1b9008 100644 --- a/sd/source/console/PresenterHelpView.cxx +++ b/sd/source/console/PresenterHelpView.cxx @@ -38,7 +38,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::std::vector; namespace sdext::presenter { @@ -723,6 +722,6 @@ void Block::Update ( } // end of anonymous namespace -} // end of namespace ::sdext::presenter +} // end of namespace sdext::presenter /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/presenter/PresenterHelper.cxx b/sd/source/console/PresenterHelper.cxx similarity index 63% rename from sd/source/ui/presenter/PresenterHelper.cxx rename to sd/source/console/PresenterHelper.cxx index 609993b2255d..122e84ccc426 100644 --- a/sd/source/ui/presenter/PresenterHelper.cxx +++ b/sd/source/console/PresenterHelper.cxx @@ -21,8 +21,9 @@ #include -#include #include "PresenterCanvas.hxx" +#include "PresenterHelper.hxx" + #include #include #include @@ -40,9 +41,8 @@ using namespace ::com::sun::star::uno; namespace sd::presenter { -Reference PresenterHelper::createWindow ( - const Reference& rxParentWindow, - bool bInitiallyVisible) +VclPtr PresenterHelper::createWindow(const Reference& rxParentWindow, + bool bInitiallyVisible) { VclPtr pParentWindow(VCLUnoHelper::GetWindow(rxParentWindow)); @@ -56,7 +56,7 @@ Reference PresenterHelper::createWindow ( pWindow->SetParentClipMode(ParentClipMode::NoClip); pWindow->SetPaintTransparent(true); - return VCLUnoHelper::GetInterface(pWindow); + return pWindow; } Reference PresenterHelper::createSharedCanvas ( @@ -94,15 +94,6 @@ void PresenterHelper::toTop(const Reference& rxWindow) } } -namespace { - -struct IdMapEntry { - OUString sid; - OUString bmpid; -}; - -} - Reference PresenterHelper::loadBitmap ( std::u16string_view sId, const Reference& rxCanvas) @@ -110,209 +101,207 @@ Reference PresenterHelper::loadBitmap ( if ( ! rxCanvas.is()) return nullptr; - static IdMapEntry constexpr map[] = { - { u"bitmaps/Background.png"_ustr, BMP_PRESENTERSCREEN_BACKGROUND }, - { u"bitmaps/Animation.png"_ustr, + static const std::unordered_map aMap { + { u"bitmaps/Background.png", BMP_PRESENTERSCREEN_BACKGROUND }, + { u"bitmaps/Animation.png", BMP_PRESENTERSCREEN_ANIMATION }, - { u"bitmaps/Transition.png"_ustr, + { u"bitmaps/Transition.png", BMP_PRESENTERSCREEN_TRANSITION }, - { u"bitmaps/BorderActiveBottom.png"_ustr, + { u"bitmaps/BorderActiveBottom.png", BMP_PRESENTERSCREEN_BORDER_ACTIVE_BOTTOM }, - { u"bitmaps/BorderActiveBottomLeft.png"_ustr, + { u"bitmaps/BorderActiveBottomLeft.png", BMP_PRESENTERSCREEN_BORDER_ACTIVE_BOTTOM_LEFT }, - { u"bitmaps/BorderActiveBottomRight.png"_ustr, + { u"bitmaps/BorderActiveBottomRight.png", BMP_PRESENTERSCREEN_BORDER_ACTIVE_BOTTOM_RIGHT }, - { u"bitmaps/BorderActiveLeft.png"_ustr, + { u"bitmaps/BorderActiveLeft.png", BMP_PRESENTERSCREEN_BORDER_ACTIVE_LEFT }, - { u"bitmaps/BorderActiveRight.png"_ustr, + { u"bitmaps/BorderActiveRight.png", BMP_PRESENTERSCREEN_BORDER_ACTIVE_RIGHT }, - { u"bitmaps/BorderActiveTop.png"_ustr, + { u"bitmaps/BorderActiveTop.png", BMP_PRESENTERSCREEN_BORDER_ACTIVE_TOP }, - { u"bitmaps/BorderActiveTopLeft.png"_ustr, + { u"bitmaps/BorderActiveTopLeft.png", BMP_PRESENTERSCREEN_BORDER_ACTIVE_TOP_LEFT }, - { u"bitmaps/BorderActiveTopRight.png"_ustr, + { u"bitmaps/BorderActiveTopRight.png", BMP_PRESENTERSCREEN_BORDER_ACTIVE_TOP_RIGHT }, - { u"bitmaps/BorderBottom.png"_ustr, BMP_PRESENTERSCREEN_BORDER_BOTTOM }, - { u"bitmaps/BorderBottomLeft.png"_ustr, + { u"bitmaps/BorderBottom.png", BMP_PRESENTERSCREEN_BORDER_BOTTOM }, + { u"bitmaps/BorderBottomLeft.png", BMP_PRESENTERSCREEN_BORDER_BOTTOM_LEFT }, - { u"bitmaps/BorderBottomRight.png"_ustr, + { u"bitmaps/BorderBottomRight.png", BMP_PRESENTERSCREEN_BORDER_BOTTOM_RIGHT }, - { u"bitmaps/BorderCurrentSlideBottom.png"_ustr, + { u"bitmaps/BorderCurrentSlideBottom.png", BMP_PRESENTERSCREEN_BORDER_CURRENT_SLIDE_BOTTOM }, - { u"bitmaps/BorderCurrentSlideBottomLeft.png"_ustr, + { u"bitmaps/BorderCurrentSlideBottomLeft.png", BMP_PRESENTERSCREEN_BORDER_CURRENT_SLIDE_BOTTOM_LEFT }, - { u"bitmaps/BorderCurrentSlideBottomRight.png"_ustr, + { u"bitmaps/BorderCurrentSlideBottomRight.png", BMP_PRESENTERSCREEN_BORDER_CURRENT_SLIDE_BOTTOM_RIGHT }, { u"bitmaps/BorderCurrentSlideLeft.png"_ustr, BMP_PRESENTERSCREEN_BORDER_CURRENT_SLIDE_LEFT }, - { u"bitmaps/BorderCurrentSlideRight.png"_ustr, + { u"bitmaps/BorderCurrentSlideRight.png", BMP_PRESENTERSCREEN_BORDER_CURRENT_SLIDE_RIGHT }, - { u"bitmaps/BorderCurrentSlideTop.png"_ustr, + { u"bitmaps/BorderCurrentSlideTop.png", BMP_PRESENTERSCREEN_BORDER_CURRENT_SLIDE_TOP }, - { u"bitmaps/BorderCurrentSlideTopLeft.png"_ustr, + { u"bitmaps/BorderCurrentSlideTopLeft.png", BMP_PRESENTERSCREEN_BORDER_CURRENT_SLIDE_TOP_LEFT }, - { u"bitmaps/BorderCurrentSlideTopRight.png"_ustr, + { u"bitmaps/BorderCurrentSlideTopRight.png", BMP_PRESENTERSCREEN_BORDER_CURRENT_SLIDE_TOP_RIGHT }, - { u"bitmaps/BorderLeft.png"_ustr, BMP_PRESENTERSCREEN_BORDER_LEFT }, - { u"bitmaps/BorderRight.png"_ustr, BMP_PRESENTERSCREEN_BORDER_RIGHT }, - { u"bitmaps/BorderToolbarBottom.png"_ustr, + { u"bitmaps/BorderLeft.png", BMP_PRESENTERSCREEN_BORDER_LEFT }, + { u"bitmaps/BorderRight.png", BMP_PRESENTERSCREEN_BORDER_RIGHT }, + { u"bitmaps/BorderToolbarBottom.png", BMP_PRESENTERSCREEN_BORDER_TOOLBAR_BOTTOM }, - { u"bitmaps/BorderToolbarLeft.png"_ustr, + { u"bitmaps/BorderToolbarLeft.png", BMP_PRESENTERSCREEN_BORDER_TOOLBAR_LEFT }, - { u"bitmaps/BorderToolbarRight.png"_ustr, + { u"bitmaps/BorderToolbarRight.png", BMP_PRESENTERSCREEN_BORDER_TOOLBAR_RIGHT }, - { u"bitmaps/BorderToolbarTop.png"_ustr, + { u"bitmaps/BorderToolbarTop.png", BMP_PRESENTERSCREEN_BORDER_TOOLBAR_TOP }, - { u"bitmaps/BorderToolbarTopLeft.png"_ustr, + { u"bitmaps/BorderToolbarTopLeft.png", BMP_PRESENTERSCREEN_BORDER_TOOLBAR_TOP_LEFT }, - { u"bitmaps/BorderToolbarTopRight.png"_ustr, + { u"bitmaps/BorderToolbarTopRight.png", BMP_PRESENTERSCREEN_BORDER_TOOLBAR_TOP_RIGHT }, - { u"bitmaps/BorderTop.png"_ustr, BMP_PRESENTERSCREEN_BORDER_TOP }, - { u"bitmaps/BorderTopLeft.png"_ustr, BMP_PRESENTERSCREEN_BORDER_TOP_LEFT }, - { u"bitmaps/BorderTopRight.png"_ustr, BMP_PRESENTERSCREEN_BORDER_TOP_RIGHT }, - { u"bitmaps/ButtonEffectNextDisabled.png"_ustr, + { u"bitmaps/BorderTop.png", BMP_PRESENTERSCREEN_BORDER_TOP }, + { u"bitmaps/BorderTopLeft.png", BMP_PRESENTERSCREEN_BORDER_TOP_LEFT }, + { u"bitmaps/BorderTopRight.png", BMP_PRESENTERSCREEN_BORDER_TOP_RIGHT }, + { u"bitmaps/ButtonEffectNextDisabled.png", BMP_PRESENTERSCREEN_BUTTON_EFFECT_NEXT_DISABLED }, - { u"bitmaps/ButtonEffectNextMouseOver.png"_ustr, + { u"bitmaps/ButtonEffectNextMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_EFFECT_NEXT_MOUSE_OVER }, - { u"bitmaps/ButtonEffectNextNormal.png"_ustr, + { u"bitmaps/ButtonEffectNextNormal.png", BMP_PRESENTERSCREEN_BUTTON_EFFECT_NEXT_NORMAL }, - { u"bitmaps/ButtonEffectNextSelected.png"_ustr, + { u"bitmaps/ButtonEffectNextSelected.png", BMP_PRESENTERSCREEN_BUTTON_EFFECT_NEXT_SELECTED }, - { u"bitmaps/ButtonFrameCenterMouseOver.png"_ustr, + { u"bitmaps/ButtonFrameCenterMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_FRAME_CENTER_MOUSE_OVER }, - { u"bitmaps/ButtonFrameCenterNormal.png"_ustr, + { u"bitmaps/ButtonFrameCenterNormal.png", BMP_PRESENTERSCREEN_BUTTON_FRAME_CENTER_NORMAL }, - { u"bitmaps/ButtonFrameLeftMouseOver.png"_ustr, + { u"bitmaps/ButtonFrameLeftMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_FRAME_LEFT_MOUSE_OVER }, - { u"bitmaps/ButtonFrameLeftNormal.png"_ustr, + { u"bitmaps/ButtonFrameLeftNormal.png", BMP_PRESENTERSCREEN_BUTTON_FRAME_LEFT_NORMAL }, - { u"bitmaps/ButtonFrameRightMouseOver.png"_ustr, + { u"bitmaps/ButtonFrameRightMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_FRAME_RIGHT_MOUSE_OVER }, - { u"bitmaps/ButtonFrameRightNormal.png"_ustr, + { u"bitmaps/ButtonFrameRightNormal.png", BMP_PRESENTERSCREEN_BUTTON_FRAME_RIGHT_NORMAL }, - { u"bitmaps/ButtonHelpDisabled.png"_ustr, + { u"bitmaps/ButtonHelpDisabled.png", BMP_PRESENTERSCREEN_BUTTON_HELP_DISABLED }, - { u"bitmaps/ButtonHelpMouseOver.png"_ustr, + { u"bitmaps/ButtonHelpMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_HELP_MOUSE_OVER }, - { u"bitmaps/ButtonHelpNormal.png"_ustr, + { u"bitmaps/ButtonHelpNormal.png", BMP_PRESENTERSCREEN_BUTTON_HELP_NORMAL }, - { u"bitmaps/ButtonHelpSelected.png"_ustr, + { u"bitmaps/ButtonHelpSelected.png", BMP_PRESENTERSCREEN_BUTTON_HELP_SELECTED }, - { u"bitmaps/ButtonExitPresenterMouseOver.png"_ustr, + { u"bitmaps/ButtonExitPresenterMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_EXIT_PRESENTER_MOUSE_OVER }, - { u"bitmaps/ButtonExitPresenterNormal.png"_ustr, + { u"bitmaps/ButtonExitPresenterNormal.png", BMP_PRESENTERSCREEN_BUTTON_EXIT_PRESENTER_NORMAL }, - { u"bitmaps/ButtonMinusDisabled.png"_ustr, + { u"bitmaps/ButtonMinusDisabled.png", BMP_PRESENTERSCREEN_BUTTON_MINUS_DISABLED }, - { u"bitmaps/ButtonMinusMouseOver.png"_ustr, + { u"bitmaps/ButtonMinusMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_MINUS_MOUSE_OVER }, - { u"bitmaps/ButtonMinusNormal.png"_ustr, + { u"bitmaps/ButtonMinusNormal.png", BMP_PRESENTERSCREEN_BUTTON_MINUS_NORMAL }, - { u"bitmaps/ButtonMinusSelected.png"_ustr, + { u"bitmaps/ButtonMinusSelected.png", BMP_PRESENTERSCREEN_BUTTON_MINUS_SELECTED }, - { u"bitmaps/ButtonNotesDisabled.png"_ustr, + { u"bitmaps/ButtonNotesDisabled.png", BMP_PRESENTERSCREEN_BUTTON_NOTES_DISABLED }, - { u"bitmaps/ButtonNotesMouseOver.png"_ustr, + { u"bitmaps/ButtonNotesMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_NOTES_MOUSE_OVER }, - { u"bitmaps/ButtonNotesNormal.png"_ustr, + { u"bitmaps/ButtonNotesNormal.png", BMP_PRESENTERSCREEN_BUTTON_NOTES_NORMAL }, - { u"bitmaps/ButtonNotesSelected.png"_ustr, + { u"bitmaps/ButtonNotesSelected.png", BMP_PRESENTERSCREEN_BUTTON_NOTES_SELECTED }, - { u"bitmaps/ButtonPlusDisabled.png"_ustr, + { u"bitmaps/ButtonPlusDisabled.png", BMP_PRESENTERSCREEN_BUTTON_PLUS_DISABLED }, - { u"bitmaps/ButtonPlusMouseOver.png"_ustr, + { u"bitmaps/ButtonPlusMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_PLUS_MOUSE_OVER }, - { u"bitmaps/ButtonPlusNormal.png"_ustr, + { u"bitmaps/ButtonPlusNormal.png", BMP_PRESENTERSCREEN_BUTTON_PLUS_NORMAL }, - { u"bitmaps/ButtonPlusSelected.png"_ustr, + { u"bitmaps/ButtonPlusSelected.png", BMP_PRESENTERSCREEN_BUTTON_PLUS_SELECTED }, - { u"bitmaps/ButtonSlideNextDisabled.png"_ustr, + { u"bitmaps/ButtonSlideNextDisabled.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_NEXT_DISABLED }, - { u"bitmaps/ButtonSlideNextMouseOver.png"_ustr, + { u"bitmaps/ButtonSlideNextMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_NEXT_MOUSE_OVER }, - { u"bitmaps/ButtonSlideNextNormal.png"_ustr, + { u"bitmaps/ButtonSlideNextNormal.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_NEXT_NORMAL }, - { u"bitmaps/ButtonSlidePreviousDisabled.png"_ustr, + { u"bitmaps/ButtonSlidePreviousDisabled.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_PREVIOUS_DISABLED }, - { u"bitmaps/ButtonSlidePreviousMouseOver.png"_ustr, + { u"bitmaps/ButtonSlidePreviousMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_PREVIOUS_MOUSE_OVER }, - { u"bitmaps/ButtonSlidePreviousNormal.png"_ustr, + { u"bitmaps/ButtonSlidePreviousNormal.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_PREVIOUS_NORMAL }, - { u"bitmaps/ButtonSlidePreviousSelected.png"_ustr, + { u"bitmaps/ButtonSlidePreviousSelected.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_PREVIOUS_SELECTED }, - { u"bitmaps/ButtonSlideSorterDisabled.png"_ustr, + { u"bitmaps/ButtonSlideSorterDisabled.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_SORTER_DISABLED }, - { u"bitmaps/ButtonSlideSorterMouseOver.png"_ustr, + { u"bitmaps/ButtonSlideSorterMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_SORTER_MOUSE_OVER }, - { u"bitmaps/ButtonSlideSorterNormal.png"_ustr, + { u"bitmaps/ButtonSlideSorterNormal.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_SORTER_NORMAL }, - { u"bitmaps/ButtonSlideSorterSelected.png"_ustr, + { u"bitmaps/ButtonSlideSorterSelected.png", BMP_PRESENTERSCREEN_BUTTON_SLIDE_SORTER_SELECTED }, - { u"bitmaps/ButtonSwitchMonitorMouseOver.png"_ustr, + { u"bitmaps/ButtonSwitchMonitorMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_SWITCH_MONITOR_MOUSE_OVER }, - { u"bitmaps/ButtonSwitchMonitorNormal.png"_ustr, + { u"bitmaps/ButtonSwitchMonitorNormal.png", BMP_PRESENTERSCREEN_BUTTON_SWITCH_MONITOR_NORMAL }, - { u"bitmaps/ButtonRestartTimerMouseOver.png"_ustr, + { u"bitmaps/ButtonRestartTimerMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_RESTART_TIMER_MOUSE_OVER }, - { u"bitmaps/ButtonRestartTimerNormal.png"_ustr, + { u"bitmaps/ButtonRestartTimerNormal.png", BMP_PRESENTERSCREEN_BUTTON_RESTART_TIMER_NORMAL }, - { u"bitmaps/ButtonPauseTimerMouseOver.png"_ustr, + { u"bitmaps/ButtonPauseTimerMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_PAUSE_TIMER_MOUSE_OVER }, - { u"bitmaps/ButtonPauseTimerNormal.png"_ustr, + { u"bitmaps/ButtonPauseTimerNormal.png", BMP_PRESENTERSCREEN_BUTTON_PAUSE_TIMER_NORMAL }, - { u"bitmaps/ButtonResumeTimerMouseOver.png"_ustr, + { u"bitmaps/ButtonResumeTimerMouseOver.png", BMP_PRESENTERSCREEN_BUTTON_RESUME_TIMER_MOUSE_OVER }, - { u"bitmaps/ButtonResumeTimerNormal.png"_ustr, + { u"bitmaps/ButtonResumeTimerNormal.png", BMP_PRESENTERSCREEN_BUTTON_RESUME_TIMER_NORMAL }, - { u"bitmaps/LabelMouseOverCenter.png"_ustr, + { u"bitmaps/LabelMouseOverCenter.png", BMP_PRESENTERSCREEN_LABEL_MOUSE_OVER_CENTER }, - { u"bitmaps/LabelMouseOverLeft.png"_ustr, + { u"bitmaps/LabelMouseOverLeft.png", BMP_PRESENTERSCREEN_LABEL_MOUSE_OVER_LEFT }, - { u"bitmaps/LabelMouseOverRight.png"_ustr, + { u"bitmaps/LabelMouseOverRight.png", BMP_PRESENTERSCREEN_LABEL_MOUSE_OVER_RIGHT }, - { u"bitmaps/ScrollbarArrowDownDisabled.png"_ustr, + { u"bitmaps/ScrollbarArrowDownDisabled.png", BMP_PRESENTERSCREEN_SCROLLBAR_ARROW_DOWN_DISABLED }, - { u"bitmaps/ScrollbarArrowDownMouseOver.png"_ustr, + { u"bitmaps/ScrollbarArrowDownMouseOver.png", BMP_PRESENTERSCREEN_SCROLLBAR_ARROW_DOWN_MOUSE_OVER }, - { u"bitmaps/ScrollbarArrowDownNormal.png"_ustr, + { u"bitmaps/ScrollbarArrowDownNormal.png", BMP_PRESENTERSCREEN_SCROLLBAR_ARROW_DOWN_NORMAL }, - { u"bitmaps/ScrollbarArrowDownSelected.png"_ustr, + { u"bitmaps/ScrollbarArrowDownSelected.png", BMP_PRESENTERSCREEN_SCROLLBAR_ARROW_DOWN_SELECTED }, - { u"bitmaps/ScrollbarArrowUpDisabled.png"_ustr, + { u"bitmaps/ScrollbarArrowUpDisabled.png", BMP_PRESENTERSCREEN_SCROLLBAR_ARROW_UP_DISABLED }, - { u"bitmaps/ScrollbarArrowUpMouseOver.png"_ustr, + { u"bitmaps/ScrollbarArrowUpMouseOver.png", BMP_PRESENTERSCREEN_SCROLLBAR_ARROW_UP_MOUSE_OVER }, - { u"bitmaps/ScrollbarArrowUpNormal.png"_ustr, + { u"bitmaps/ScrollbarArrowUpNormal.png", BMP_PRESENTERSCREEN_SCROLLBAR_ARROW_UP_NORMAL }, - { u"bitmaps/ScrollbarArrowUpSelected.png"_ustr, + { u"bitmaps/ScrollbarArrowUpSelected.png", BMP_PRESENTERSCREEN_SCROLLBAR_ARROW_UP_SELECTED }, - { u"bitmaps/ScrollbarPagerMiddleMouseOver.png"_ustr, + { u"bitmaps/ScrollbarPagerMiddleMouseOver.png", BMP_PRESENTERSCREEN_SCROLLBAR_PAGER_MIDDLE_MOUSE_OVER }, - { u"bitmaps/ScrollbarPagerMiddleNormal.png"_ustr, + { u"bitmaps/ScrollbarPagerMiddleNormal.png", BMP_PRESENTERSCREEN_SCROLLBAR_PAGER_MIDDLE_NORMAL }, - { u"bitmaps/ScrollbarThumbBottomMouseOver.png"_ustr, + { u"bitmaps/ScrollbarThumbBottomMouseOver.png", BMP_PRESENTERSCREEN_SCROLLBAR_THUMB_BOTTOM_MOUSE_OVER }, - { u"bitmaps/ScrollbarThumbBottomNormal.png"_ustr, + { u"bitmaps/ScrollbarThumbBottomNormal.png", BMP_PRESENTERSCREEN_SCROLLBAR_THUMB_BOTTOM_NORMAL }, - { u"bitmaps/ScrollbarThumbMiddleMouseOver.png"_ustr, + { u"bitmaps/ScrollbarThumbMiddleMouseOver.png", BMP_PRESENTERSCREEN_SCROLLBAR_THUMB_MIDDLE_MOUSE_OVER }, - { u"bitmaps/ScrollbarThumbMiddleNormal.png"_ustr, + { u"bitmaps/ScrollbarThumbMiddleNormal.png", BMP_PRESENTERSCREEN_SCROLLBAR_THUMB_MIDDLE_NORMAL }, - { u"bitmaps/ScrollbarThumbTopMouseOver.png"_ustr, + { u"bitmaps/ScrollbarThumbTopMouseOver.png", BMP_PRESENTERSCREEN_SCROLLBAR_THUMB_TOP_MOUSE_OVER }, - { u"bitmaps/ScrollbarThumbTopNormal.png"_ustr, + { u"bitmaps/ScrollbarThumbTopNormal.png", BMP_PRESENTERSCREEN_SCROLLBAR_THUMB_TOP_NORMAL }, - { u"bitmaps/ViewBackground.png"_ustr, BMP_PRESENTERSCREEN_VIEW_BACKGROUND }, - { u"bitmaps/Separator.png"_ustr, + { u"bitmaps/ViewBackground.png", BMP_PRESENTERSCREEN_VIEW_BACKGROUND }, + { u"bitmaps/Separator.png", BMP_PRESENTERSCREEN_SEPARATOR } }; - OUString bmpid; - for (std::size_t i = 0; i != SAL_N_ELEMENTS(map); ++i) { - if (sId == map[i].sid) { - bmpid = map[i].bmpid; - break; - } - } + + if (!aMap.contains(sId)) + return nullptr; + + const OUString bmpid = aMap.at(sId); if (bmpid.isEmpty()) { return nullptr; } diff --git a/sd/inc/PresenterHelper.hxx b/sd/source/console/PresenterHelper.hxx similarity index 95% rename from sd/inc/PresenterHelper.hxx rename to sd/source/console/PresenterHelper.hxx index 35f1debd7a4c..ca5fe05bbc23 100644 --- a/sd/inc/PresenterHelper.hxx +++ b/sd/source/console/PresenterHelper.hxx @@ -19,19 +19,18 @@ #pragma once -#include "sddllapi.h" - #include #include #include #include #include +#include namespace com::sun::star::uno { class XComponentContext; } namespace sd::presenter { -class SD_DLLPUBLIC PresenterHelper final +class PresenterHelper final { public: PresenterHelper() = delete; @@ -45,9 +44,9 @@ public: When `true` the new window will be visible from the start, i.e. a window listener will not receive a windowShown signal. */ - static css::uno::Reference createWindow ( - const css::uno::Reference& rxParentWindow, - bool bInitiallyVisible); + static VclPtr + createWindow(const css::uno::Reference& rxParentWindow, + bool bInitiallyVisible); /** Create a new canvas for the given window. The new canvas is a wrapper around the given shared canvas. The wrapper only modifies diff --git a/sd/source/console/PresenterNotesView.cxx b/sd/source/console/PresenterNotesView.cxx index fff7cf4945ee..2c1f17f10062 100644 --- a/sd/source/console/PresenterNotesView.cxx +++ b/sd/source/console/PresenterNotesView.cxx @@ -27,6 +27,8 @@ #include "PresenterTextView.hxx" #include #include +#include + #include #include #include @@ -40,7 +42,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; const sal_Int32 gnSpaceBelowSeparator (10); const sal_Int32 gnSpaceAboveSeparator (10); @@ -175,8 +176,8 @@ void PresenterNotesView::CreateToolBar ( return; // Create a new window as container of the tool bar. - mxToolBarWindow = sd::presenter::PresenterHelper::createWindow( - mxParentWindow, true); + mxToolBarWindow = VCLUnoHelper::GetInterface( + sd::presenter::PresenterHelper::createWindow(mxParentWindow, true)); mxToolBarCanvas = sd::presenter::PresenterHelper::createSharedCanvas ( Reference(mxCanvas, UNO_QUERY), mxParentWindow, @@ -190,7 +191,7 @@ void PresenterNotesView::CreateToolBar ( mxToolBarWindow, mxToolBarCanvas, rpPresenterController, - PresenterToolBar::Left); + PresenterToolBar::Anchor::Left); mpToolBar->Initialize( u"PresenterScreenSettings/ToolBars/NotesToolBar"_ustr); } @@ -277,9 +278,6 @@ void SAL_CALL PresenterNotesView::windowPaint (const awt::PaintEvent& rEvent) throwIfDisposed(l); } - if ( ! mbIsPresenterViewActive) - return; - ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex()); Paint(rEvent.UpdateRect); } @@ -375,18 +373,18 @@ void PresenterNotesView::Layout() // Size the tool bar and the horizontal separator above it. if (mxToolBarWindow.is()) { - const geometry::RealSize2D aToolBarSize (mpToolBar->GetMinimalSize()); - const sal_Int32 nToolBarHeight = sal_Int32(aToolBarSize.Height + 0.5); - mxToolBarWindow->setPosSize(0, aWindowBox.Height - nToolBarHeight, - sal_Int32(aToolBarSize.Width + 0.5), nToolBarHeight, - awt::PosSize::POSSIZE); - mnSeparatorYLocation = aWindowBox.Height - nToolBarHeight - gnSpaceBelowSeparator; - aNewTextBoundingBox.Y2 = mnSeparatorYLocation - gnSpaceAboveSeparator; - // Place the close button. - if (mpCloseButton) - mpCloseButton->SetCenter(geometry::RealPoint2D( - (aWindowBox.Width + aToolBarSize.Width) / 2, - aWindowBox.Height - aToolBarSize.Height/2)); + const geometry::RealSize2D aToolBarSize(mpToolBar->GetMinimalSize()); + const sal_Int32 nToolBarHeight = sal_Int32(aToolBarSize.Height + 0.5); + mxToolBarWindow->setPosSize(0, aWindowBox.Height - nToolBarHeight, + sal_Int32(aToolBarSize.Width + 0.5), nToolBarHeight, + awt::PosSize::POSSIZE); + mnSeparatorYLocation = aWindowBox.Height - nToolBarHeight - gnSpaceBelowSeparator; + aNewTextBoundingBox.Y2 = mnSeparatorYLocation - gnSpaceAboveSeparator; + // Place the close button. + if (mpCloseButton) + mpCloseButton->SetCenter( + geometry::RealPoint2D((aWindowBox.Width + aToolBarSize.Width) / 2, + aWindowBox.Height - aToolBarSize.Height / 2)); } // Check whether the vertical scroll bar is necessary. if (mpScrollBar) @@ -435,7 +433,7 @@ void PresenterNotesView::Layout() mpScrollBar->SetThumbPosition(0, false); UpdateScrollBar(); } - // Has the text area has changed it position or size? + // Has the text area changed its position or size? if (aNewTextBoundingBox.X1 != maTextBoundingBox.X1 || aNewTextBoundingBox.Y1 != maTextBoundingBox.Y1 || aNewTextBoundingBox.X2 != maTextBoundingBox.X2 diff --git a/sd/source/console/PresenterNotesView.hxx b/sd/source/console/PresenterNotesView.hxx index c558ce4d291c..a621fe84f835 100644 --- a/sd/source/console/PresenterNotesView.hxx +++ b/sd/source/console/PresenterNotesView.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERNOTESVIEW_HXX -#define INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERNOTESVIEW_HXX +#pragma once #include "PresenterController.hxx" #include "PresenterToolBar.hxx" @@ -55,8 +54,7 @@ typedef cppu::ImplInheritanceHelper< notes text. */ class PresenterNotesView - : public PresenterNotesViewInterfaceBase, - public CachablePresenterView + : public PresenterNotesViewInterfaceBase { public: explicit PresenterNotesView ( @@ -153,6 +151,4 @@ private: } // end of namespace ::sdext::presenter -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/console/PresenterPaintManager.hxx b/sd/source/console/PresenterPaintManager.hxx index 0575f407a427..47dd0937f8f3 100644 --- a/sd/source/console/PresenterPaintManager.hxx +++ b/sd/source/console/PresenterPaintManager.hxx @@ -20,7 +20,7 @@ #ifndef INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERPAINTMANAGER_HXX #define INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERPAINTMANAGER_HXX -#include +#include "PresenterHelper.hxx" #include #include diff --git a/sd/source/console/PresenterPane.cxx b/sd/source/console/PresenterPane.cxx index 39d12d2f1acd..dae49b110538 100644 --- a/sd/source/console/PresenterPane.cxx +++ b/sd/source/console/PresenterPane.cxx @@ -19,8 +19,9 @@ #include "PresenterPane.hxx" #include "PresenterController.hxx" +#include "PresenterHelper.hxx" #include "PresenterPaintManager.hxx" -#include + #include using namespace ::com::sun::star; @@ -41,26 +42,6 @@ PresenterPane::~PresenterPane() { } -//----- AbstractPane ----------------------------------------------------------------- - -Reference PresenterPane::getWindow() -{ - { - std::unique_lock l(m_aMutex); - throwIfDisposed(l); - } - return mxContentWindow; -} - -Reference PresenterPane::getCanvas() -{ - { - std::unique_lock l(m_aMutex); - throwIfDisposed(l); - } - return mxContentCanvas; -} - //----- XWindowListener ------------------------------------------------------- void SAL_CALL PresenterPane::windowResized (const awt::WindowEvent& rEvent) diff --git a/sd/source/console/PresenterPane.hxx b/sd/source/console/PresenterPane.hxx index 9adc79408846..c242ff673a83 100644 --- a/sd/source/console/PresenterPane.hxx +++ b/sd/source/console/PresenterPane.hxx @@ -39,12 +39,6 @@ public: const ::rtl::Reference& rpPresenterController); virtual ~PresenterPane() override; - // AbstractPane - - css::uno::Reference getWindow() override; - - css::uno::Reference getCanvas() override; - // XWindowListener virtual void SAL_CALL windowResized(const css::awt::WindowEvent& rEvent) override; diff --git a/sd/source/console/PresenterPaneBase.cxx b/sd/source/console/PresenterPaneBase.cxx index 6c85e8a1dd6b..1553ca726a9c 100644 --- a/sd/source/console/PresenterPaneBase.cxx +++ b/sd/source/console/PresenterPaneBase.cxx @@ -20,13 +20,15 @@ #include "PresenterPaneBase.hxx" #include "PresenterController.hxx" #include "PresenterPaintManager.hxx" + +#include + #include #include #include using namespace css; using namespace css::uno; -using namespace css::drawing::framework; namespace sdext::presenter { @@ -154,6 +156,26 @@ bool PresenterPaneBase::isAnchorOnly() return true; } +// AbstractPane + +Reference PresenterPaneBase::getWindow() +{ + { + std::unique_lock l(m_aMutex); + throwIfDisposed(l); + } + return mxContentWindow; +} + +Reference PresenterPaneBase::getCanvas() +{ + { + std::unique_lock l(m_aMutex); + throwIfDisposed(l); + } + return mxContentCanvas; +} + //----- XWindowListener ------------------------------------------------------- void SAL_CALL PresenterPaneBase::windowResized (const awt::WindowEvent&) @@ -197,10 +219,10 @@ void PresenterPaneBase::CreateWindows ( if (!mxParentWindow.is()) return; - mxBorderWindow = sd::presenter::PresenterHelper::createWindow( - mxParentWindow, bIsWindowVisibleOnCreation); - mxContentWindow = sd::presenter::PresenterHelper::createWindow( - mxBorderWindow, bIsWindowVisibleOnCreation); + mxBorderWindow = VCLUnoHelper::GetInterface( + sd::presenter::PresenterHelper::createWindow(mxParentWindow, bIsWindowVisibleOnCreation)); + mxContentWindow = VCLUnoHelper::GetInterface( + sd::presenter::PresenterHelper::createWindow(mxBorderWindow, bIsWindowVisibleOnCreation)); } const Reference& PresenterPaneBase::GetBorderWindow() const @@ -254,6 +276,6 @@ void PresenterPaneBase::LayoutContextWindow() awt::PosSize::POSSIZE); } -} // end of namespace ::sdext::presenter +} // end of namespace sdext::presenter /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/console/PresenterPaneBase.hxx b/sd/source/console/PresenterPaneBase.hxx index 146b6d4add11..f354be70240e 100644 --- a/sd/source/console/PresenterPaneBase.hxx +++ b/sd/source/console/PresenterPaneBase.hxx @@ -19,10 +19,9 @@ #pragma once +#include "PresenterHelper.hxx" #include "PresenterPaneBorderPainter.hxx" -#include - #include #include #include @@ -74,6 +73,10 @@ public: virtual bool isAnchorOnly() override; + // AbstractPane + virtual css::uno::Reference getWindow() override; + css::uno::Reference getCanvas() override; + // XWindowListener virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) override; diff --git a/sd/source/console/PresenterPaneBorderPainter.cxx b/sd/source/console/PresenterPaneBorderPainter.cxx index 0354277632f6..6139af3d97e7 100644 --- a/sd/source/console/PresenterPaneBorderPainter.cxx +++ b/sd/source/console/PresenterPaneBorderPainter.cxx @@ -20,8 +20,8 @@ #include "PresenterPaneBorderPainter.hxx" #include "PresenterCanvasHelper.hxx" #include "PresenterGeometryHelper.hxx" +#include "PresenterHelper.hxx" #include "PresenterTheme.hxx" -#include #include #include #include @@ -204,13 +204,12 @@ void PresenterPaneBorderPainter::paintBorder ( rsPaneBorderStyleName); } -bool PresenterPaneBorderPainter::ProvideTheme (const Reference& rxCanvas) +void PresenterPaneBorderPainter::ProvideTheme(const Reference& rxCanvas) { - bool bModified (false); - if ( ! mxContext.is()) - return false; + return; + bool bModified = false; if (mpTheme != nullptr) { // Check if the theme already has a canvas. @@ -233,8 +232,6 @@ bool PresenterPaneBorderPainter::ProvideTheme (const ReferenceSetCanvas(rxCanvas); } - - return bModified; } void PresenterPaneBorderPainter::ProvideTheme() diff --git a/sd/source/console/PresenterPaneBorderPainter.hxx b/sd/source/console/PresenterPaneBorderPainter.hxx index 6b3f6b57bdb8..e09b2c73e7c0 100644 --- a/sd/source/console/PresenterPaneBorderPainter.hxx +++ b/sd/source/console/PresenterPaneBorderPainter.hxx @@ -53,8 +53,8 @@ typedef ::cppu::WeakComponentImplHelper<> PresenterPaneBorderPainterInterfaceBas bounding box which the paint methods may paint over. The center box is the third rectangle. This is the actual border between outer and inner background color or bitmap and it is used for placing the bitmaps that are used - paint the border. The inner sides and corners are places relative to - this center box, i.e. when not further offsets are given then the upper + to paint the border. The inner sides and corners are placed relative to + this center box, i.e. when no further offsets are given then the upper left corner bitmap is painted with its lower right at the upper left of the center box.

      */ @@ -157,12 +157,8 @@ private: /** When the theme for the border has not yet been loaded then try again when this method is called. - @return - Returns only one time when the theme is loaded and/or the - renderer is initialized. */ - bool ProvideTheme ( - const css::uno::Reference& rxCanvas); + void ProvideTheme(const css::uno::Reference& rxCanvas); void ProvideTheme(); /// @throws css::lang::DisposedException diff --git a/sd/source/console/PresenterPaneContainer.cxx b/sd/source/console/PresenterPaneContainer.cxx index 28121cadcc24..ff5c30448530 100644 --- a/sd/source/console/PresenterPaneContainer.cxx +++ b/sd/source/console/PresenterPaneContainer.cxx @@ -22,7 +22,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sdext::presenter { @@ -171,8 +170,7 @@ PresenterPaneContainer::SharedPaneDescriptor return pDescriptor; } -PresenterPaneContainer::SharedPaneDescriptor - PresenterPaneContainer::RemovePane (const rtl::Reference& rxPaneId) +void PresenterPaneContainer::RemovePane(const rtl::Reference& rxPaneId) { SharedPaneDescriptor pDescriptor (FindPaneId(rxPaneId)); if (pDescriptor) @@ -185,7 +183,6 @@ PresenterPaneContainer::SharedPaneDescriptor pDescriptor->mxView = nullptr; pDescriptor->mbIsActive = false; } - return pDescriptor; } PresenterPaneContainer::SharedPaneDescriptor diff --git a/sd/source/console/PresenterPaneContainer.hxx b/sd/source/console/PresenterPaneContainer.hxx index 898389716b5f..fc97b0b39ae8 100644 --- a/sd/source/console/PresenterPaneContainer.hxx +++ b/sd/source/console/PresenterPaneContainer.hxx @@ -20,8 +20,9 @@ #ifndef INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERPANECONTAINER_HXX #define INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERPANECONTAINER_HXX +#include "PresenterHelper.hxx" #include "PresenterPaneBase.hxx" -#include + #include #include #include @@ -109,8 +110,7 @@ public: SharedPaneDescriptor StoreView ( const rtl::Reference& rxView); - SharedPaneDescriptor RemovePane ( - const rtl::Reference& rxPaneId); + void RemovePane(const rtl::Reference& rxPaneId); SharedPaneDescriptor RemoveView ( const rtl::Reference& rxView); diff --git a/sd/source/console/PresenterPaneFactory.cxx b/sd/source/console/PresenterPaneFactory.cxx index d6b497910acf..f96edb3ca64f 100644 --- a/sd/source/console/PresenterPaneFactory.cxx +++ b/sd/source/console/PresenterPaneFactory.cxx @@ -31,7 +31,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::drawing::framework; namespace sdext::presenter { @@ -93,17 +92,6 @@ void PresenterPaneFactory::disposing(std::unique_lock&) if (xCC.is()) xCC->removeResourceFactoryForReference(this); mxConfigurationControllerWeak.clear(); - - // Dispose the panes in the cache. - if (mpResourceCache != nullptr) - { - for (const auto& rxPane : *mpResourceCache) - { - if (rxPane.second.is()) - rxPane.second->dispose(); - } - mpResourceCache.reset(); - } } //----- AbstractPaneFactory ---------------------------------------------------------- @@ -123,32 +111,7 @@ rtl::Reference PresenterPaneFactory::createReso if (sPaneURL.isEmpty()) return nullptr; - if (mpResourceCache != nullptr) - { - // Has the requested resource already been created? - ResourceContainer::const_iterator iResource (mpResourceCache->find(sPaneURL)); - if (iResource != mpResourceCache->end()) - { - // Yes. Mark it as active. - rtl::Reference pPaneContainer( - mpPresenterController->GetPaneContainer()); - PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( - pPaneContainer->FindPaneURL(sPaneURL)); - if (pDescriptor) - { - pDescriptor->SetActivationState(true); - if (pDescriptor->mxBorderWindow.is()) - pDescriptor->mxBorderWindow->setVisible(true); - pPaneContainer->StorePane(pDescriptor->mxPane); - } - - return iResource->second; - } - } - - // No. Create a new one. - rtl::Reference xResource = CreatePane(rxPaneId); - return xResource; + return CreatePane(rxPaneId); } void PresenterPaneFactory::releaseResource (const rtl::Reference& rxResource) @@ -174,22 +137,13 @@ void PresenterPaneFactory::releaseResource (const rtl::ReferencemxBorderWindow.is()) pDescriptor->mxBorderWindow->setVisible(false); - if (mpResourceCache != nullptr) - { - // Store the pane in the cache. - (*mpResourceCache)[sPaneURL] = rxResource; - } - else - { - // Dispose the pane. - if (rxResource.is()) - rxResource->dispose(); - } + // Dispose the pane. + if (rxResource.is()) + rxResource->dispose(); } - -rtl::Reference PresenterPaneFactory::CreatePane ( - const rtl::Reference& rxPaneId) +rtl::Reference +PresenterPaneFactory::CreatePane(const rtl::Reference& rxPaneId) { if ( ! rxPaneId.is()) return nullptr; @@ -221,14 +175,12 @@ rtl::Reference PresenterPaneFactory::CreatePane return nullptr; } -rtl::Reference PresenterPaneFactory::CreatePane ( - const rtl::Reference& rxPaneId, - const rtl::Reference& rxParentPane, - const bool bIsSpritePane) +rtl::Reference +PresenterPaneFactory::CreatePane(const rtl::Reference& rxPaneId, + const rtl::Reference& rxParentPane, + const bool bIsSpritePane) { Reference xContext (mxComponentContextWeak); - Reference xFactory ( - xContext->getServiceManager(), UNO_SET_THROW); // Create a border window and canvas and store it in the pane // container. diff --git a/sd/source/console/PresenterPaneFactory.hxx b/sd/source/console/PresenterPaneFactory.hxx index 65559543331b..d8f6884311a6 100644 --- a/sd/source/console/PresenterPaneFactory.hxx +++ b/sd/source/console/PresenterPaneFactory.hxx @@ -20,6 +20,8 @@ #ifndef INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERPANEFACTORY_HXX #define INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERPANEFACTORY_HXX +#include "PresenterPaneBase.hxx" + #include #include #include @@ -83,9 +85,6 @@ private: unotools::WeakReference mxConfigurationControllerWeak; ::rtl::Reference mpPresenterController; - typedef ::std::map > - ResourceContainer; - std::unique_ptr mpResourceCache; PresenterPaneFactory ( const css::uno::Reference& rxContext, @@ -93,12 +92,12 @@ private: void Register (const rtl::Reference<::sd::DrawController>& rxController); - rtl::Reference CreatePane ( - const rtl::Reference& rxPaneId); - rtl::Reference CreatePane ( - const rtl::Reference& rxPaneId, - const rtl::Reference& rxParentPane, - const bool bIsSpritePane); + rtl::Reference + CreatePane(const rtl::Reference& rxPaneId); + rtl::Reference + CreatePane(const rtl::Reference& rxPaneId, + const rtl::Reference& rxParentPane, + const bool bIsSpritePane); }; } diff --git a/sd/source/console/PresenterProtocolHandler.cxx b/sd/source/console/PresenterProtocolHandler.cxx index 2e44f9e252c4..dab0ade017ae 100644 --- a/sd/source/console/PresenterProtocolHandler.cxx +++ b/sd/source/console/PresenterProtocolHandler.cxx @@ -31,7 +31,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sdext::presenter { diff --git a/sd/source/console/PresenterScreen.cxx b/sd/source/console/PresenterScreen.cxx index c9f080a308a6..36b0ecff35a3 100644 --- a/sd/source/console/PresenterScreen.cxx +++ b/sd/source/console/PresenterScreen.cxx @@ -46,7 +46,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::presentation; -using namespace ::com::sun::star::drawing::framework; constexpr OUString FULL_SCREEN_PANE_URL = u"private:resource/pane/FullScreenPane"_ustr; diff --git a/sd/source/console/PresenterScrollBar.cxx b/sd/source/console/PresenterScrollBar.cxx index 3a5cddb09af9..03eaf2cde6ea 100644 --- a/sd/source/console/PresenterScrollBar.cxx +++ b/sd/source/console/PresenterScrollBar.cxx @@ -21,10 +21,13 @@ #include "PresenterBitmapContainer.hxx" #include "PresenterCanvasHelper.hxx" #include "PresenterGeometryHelper.hxx" +#include "PresenterHelper.hxx" #include "PresenterPaintManager.hxx" #include "PresenterTimer.hxx" #include "PresenterUIPainter.hxx" -#include + +#include + #include #include #include @@ -89,7 +92,8 @@ PresenterScrollBar::PresenterScrollBar ( { try { - mxWindow = sd::presenter::PresenterHelper::createWindow(rxParentWindow, false); + mxWindow = VCLUnoHelper::GetInterface( + sd::presenter::PresenterHelper::createWindow(rxParentWindow, false)); // Make the background transparent. The slide show paints its own background. Reference xPeer (mxWindow, UNO_QUERY_THROW); diff --git a/sd/source/console/PresenterScrollBar.hxx b/sd/source/console/PresenterScrollBar.hxx index 5ac3e31051d4..e7da561cc7aa 100644 --- a/sd/source/console/PresenterScrollBar.hxx +++ b/sd/source/console/PresenterScrollBar.hxx @@ -20,7 +20,8 @@ #pragma once #include "PresenterBitmapContainer.hxx" -#include +#include "PresenterHelper.hxx" + #include #include #include diff --git a/sd/source/console/PresenterSlidePreview.cxx b/sd/source/console/PresenterSlidePreview.cxx index b8013716cbd1..50398266ac2f 100644 --- a/sd/source/console/PresenterSlidePreview.cxx +++ b/sd/source/console/PresenterSlidePreview.cxx @@ -27,11 +27,10 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace { - // Use a super sample factor greater than 1 to achieve a poor mans + // Use a super sample factor greater than 1 to achieve a poor man's // antialiasing effect for slide previews. const sal_Int16 gnSuperSampleFactor = 2; } @@ -77,9 +76,7 @@ PresenterSlidePreview::PresenterSlidePreview ( if (mpPresenterController) mnSlideAspectRatio = mpPresenterController->GetSlideAspectRatio(); - Reference xFactory = rxContext->getServiceManager(); - if (xFactory.is()) - mxPreviewRenderer = new sd::presenter::SlideRenderer(); + mxPreviewRenderer = new sd::presenter::SlideRenderer(); mpBitmaps = std::make_shared( "PresenterScreenSettings/ScrollBar/Bitmaps", std::shared_ptr(), diff --git a/sd/source/console/PresenterSlideShowView.cxx b/sd/source/console/PresenterSlideShowView.cxx index 49e432cc2895..0ffa45833e11 100644 --- a/sd/source/console/PresenterSlideShowView.cxx +++ b/sd/source/console/PresenterSlideShowView.cxx @@ -21,8 +21,8 @@ #include "PresenterSlideShowView.hxx" #include "PresenterCanvasHelper.hxx" #include "PresenterGeometryHelper.hxx" +#include "PresenterHelper.hxx" #include "PresenterPaneContainer.hxx" -#include #include #include #include @@ -45,7 +45,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace { /** Return the slide show controller of a running presentation that has @@ -133,7 +132,7 @@ void PresenterSlideShowView::LateInit() xPeer->setBackground(util::Color(0xff000000)); } - // Create a window for the actual slide show view. It is places + // Create a window for the actual slide show view. It is placed // centered and with maximal size inside the pane. mxViewWindow = CreateViewWindow(mxWindow); @@ -291,17 +290,6 @@ css::uno::Reference SAL_CALL PresenterSlideShowView::ge return mxCurrentSlide; } -//----- CachablePresenterView ------------------------------------------------- - -void PresenterSlideShowView::ReleaseView() -{ - if (mxSlideShow.is() && mbIsViewAdded) - { - mxSlideShow->removeView(this); - mbIsViewAdded = false; - } -} - //----- XSlideShowView -------------------------------------------------------- Reference SAL_CALL PresenterSlideShowView::getCanvas() @@ -495,10 +483,6 @@ void SAL_CALL PresenterSlideShowView::disposing (const lang::EventObject& rEvent void SAL_CALL PresenterSlideShowView::windowPaint (const awt::PaintEvent& rEvent) { - // Deactivated views must not be painted. - if ( ! mbIsPresenterViewActive) - return; - awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize()); if (aViewWindowBox.Width <= 0 || aViewWindowBox.Height <= 0) return; @@ -620,8 +604,6 @@ bool PresenterSlideShowView::isAnchorOnly() return false; } -//----- CachablePresenterView ------------------------------------------------- - void PresenterSlideShowView::ActivatePresenterView() { if (mxSlideShow.is() && ! mbIsViewAdded) @@ -631,7 +613,7 @@ void PresenterSlideShowView::ActivatePresenterView() } } -void PresenterSlideShowView::DeactivatePresenterView() +void PresenterSlideShowView::ReleaseView() { if (mxSlideShow.is() && mbIsViewAdded) { @@ -640,7 +622,6 @@ void PresenterSlideShowView::DeactivatePresenterView() } } - void PresenterSlideShowView::PaintOuterWindow (const awt::Rectangle& rRepaintBox) { if ( ! mxCanvas.is()) diff --git a/sd/source/console/PresenterSlideShowView.hxx b/sd/source/console/PresenterSlideShowView.hxx index cb6f43c01b51..46ea3f28613d 100644 --- a/sd/source/console/PresenterSlideShowView.hxx +++ b/sd/source/console/PresenterSlideShowView.hxx @@ -20,7 +20,8 @@ #ifndef INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERSLIDESHOWVIEW_HXX #define INCLUDED_SDEXT_SOURCE_PRESENTER_PRESENTERSLIDESHOWVIEW_HXX -#include "PresenterViewFactory.hxx" +#include "PresenterController.hxx" + #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -53,8 +55,7 @@ typedef cppu::ImplInheritanceHelper< /** Life view in a secondary window of a full screen slide show. */ class PresenterSlideShowView - : public PresenterSlideShowViewInterfaceBase, - public CachablePresenterView + : public PresenterSlideShowViewInterfaceBase { public: PresenterSlideShowView ( @@ -69,9 +70,13 @@ public: void LateInit(); virtual void disposing(std::unique_lock&) override; - // CachablePresenterView + void ActivatePresenterView(); - virtual void ReleaseView() override; + /** Called before the view is disposed. This gives the view the + opportunity to trigger actions that may lead to (synchronous) + callbacks that do not result in DisposedExceptions. + */ + void ReleaseView(); // XSlideShowView @@ -165,12 +170,6 @@ public: virtual css::uno::Reference SAL_CALL getCurrentPage() override; - // CachablePresenterView - - virtual void ActivatePresenterView() override; - - virtual void DeactivatePresenterView() override; - private: css::uno::Reference mxComponentContext; ::rtl::Reference mpPresenterController; diff --git a/sd/source/console/PresenterSlideSorter.cxx b/sd/source/console/PresenterSlideSorter.cxx index 86b37aba4fe0..48baf4f5ea48 100644 --- a/sd/source/console/PresenterSlideSorter.cxx +++ b/sd/source/console/PresenterSlideSorter.cxx @@ -39,7 +39,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace { const sal_Int32 gnVerticalGap (10); @@ -448,10 +447,6 @@ void SAL_CALL PresenterSlideSorter::windowHidden (const lang::EventObject&) void SAL_CALL PresenterSlideSorter::windowPaint (const css::awt::PaintEvent& rEvent) { - // Deactivated views must not be painted. - if ( ! mbIsPresenterViewActive) - return; - Paint(rEvent.UpdateRect); Reference xSpriteCanvas (mxCanvas, UNO_QUERY); @@ -672,6 +667,9 @@ void PresenterSlideSorter::UpdateLayout() mpLayout->SetupVisibleArea(); mpLayout->UpdateScrollBars(); + if (mnCurrentSlideIndex >= 0) + ScrollSlideIntoView(mnCurrentSlideIndex); + // Tell the preview cache about some of the values. mxPreviewCache->setPreviewSize(mpLayout->maPreviewSize); mxPreviewCache->setVisibleRange( diff --git a/sd/source/console/PresenterSlideSorter.hxx b/sd/source/console/PresenterSlideSorter.hxx index c73cd0d173ab..d815ee7c5aba 100644 --- a/sd/source/console/PresenterSlideSorter.hxx +++ b/sd/source/console/PresenterSlideSorter.hxx @@ -56,8 +56,7 @@ typedef cppu::ImplInheritanceHelper< to create the slide previews. Painting is done via a canvas. */ class PresenterSlideSorter - : public PresenterSlideSorterInterfaceBase, - public CachablePresenterView + : public PresenterSlideSorterInterfaceBase { public: PresenterSlideSorter ( diff --git a/sd/source/console/PresenterSpritePane.cxx b/sd/source/console/PresenterSpritePane.cxx index 58b546a74a05..a6ee1b4a8ec9 100644 --- a/sd/source/console/PresenterSpritePane.cxx +++ b/sd/source/console/PresenterSpritePane.cxx @@ -18,8 +18,9 @@ */ #include "PresenterController.hxx" +#include "PresenterHelper.hxx" #include "PresenterSpritePane.hxx" -#include + #include using namespace ::com::sun::star; @@ -49,25 +50,13 @@ void PresenterSpritePane::disposing(std::unique_lock& l) //----- AbstractPane ----------------------------------------------------------------- -Reference PresenterSpritePane::getWindow() -{ - { - std::unique_lock l(m_aMutex); - throwIfDisposed(l); - } - return mxContentWindow; -} - Reference PresenterSpritePane::getCanvas() { - { - std::unique_lock l(m_aMutex); - throwIfDisposed(l); - } - - if ( ! mxContentCanvas.is()) - UpdateCanvases(); + Reference xCanvas = PresenterPaneBase::getCanvas(); + if (xCanvas.is()) + return xCanvas; + UpdateCanvases(); return mxContentCanvas; } diff --git a/sd/source/console/PresenterSpritePane.hxx b/sd/source/console/PresenterSpritePane.hxx index 4891b05e715a..26907f1ce828 100644 --- a/sd/source/console/PresenterSpritePane.hxx +++ b/sd/source/console/PresenterSpritePane.hxx @@ -45,10 +45,6 @@ public: using PresenterPaneBase::disposing; - // AbstractPane - - virtual css::uno::Reference getWindow() override; - virtual css::uno::Reference getCanvas() override; // XWindowListener diff --git a/sd/source/console/PresenterTheme.cxx b/sd/source/console/PresenterTheme.cxx index 2f45578130de..430e033f591a 100644 --- a/sd/source/console/PresenterTheme.cxx +++ b/sd/source/console/PresenterTheme.cxx @@ -21,7 +21,8 @@ #include "PresenterBitmapContainer.hxx" #include "PresenterCanvasHelper.hxx" #include "PresenterConfigurationAccess.hxx" -#include +#include "PresenterHelper.hxx" + #include #include #include @@ -60,7 +61,7 @@ public: mnRight == mnInvalidValue ? 0 : mnRight, mnBottom == mnInvalidValue ? 0 : mnBottom }; - }; + } void Merge (const BorderSize& rBorderSize) { @@ -82,10 +83,7 @@ public: class ReadContext { public: - Reference mxCanvas; - - ReadContext ( - const Reference& rxCanvas); + ReadContext() = delete; /** Read data describing a font from the node that can be reached from the given root via the given path. @@ -99,9 +97,9 @@ public: const Reference& rxFontProperties, const PresenterTheme::SharedFontDescriptor& rpDefault); - std::shared_ptr ReadTheme ( - PresenterConfigurationAccess& rConfiguration, - const OUString& rsThemeName); + static std::shared_ptr + ReadTheme(PresenterConfigurationAccess& rConfiguration, + const Reference& rxCanvas); static BorderSize ReadBorderSize (const Reference& rxNode); @@ -138,16 +136,14 @@ private: ::std::vector mStyles; public: - void Read ( - const ReadContext& rReadContext, - const Reference& rThemeRoot); + void Read(const Reference& rxCanvas, + const Reference& rThemeRoot); SharedPaneStyle GetPaneStyle (const OUString& rsStyleName) const; private: - void ProcessPaneStyle ( - ReadContext const & rReadContext, - const ::std::vector& rValues); + void ProcessPaneStyle(const Reference& rxCanvas, + const ::std::vector& rValues); }; /** A ViewStyle describes how a view is displayed. @@ -175,16 +171,14 @@ private: ::std::vector mStyles; public: - void Read ( - const ReadContext& rReadContext, - const Reference& rThemeRoot); + void Read(const Reference& rxCanvas, + const Reference& rThemeRoot); SharedViewStyle GetViewStyle (const OUString& rsStyleName) const; private: - void ProcessViewStyle( - ReadContext const & rReadContext, - const Reference& rxProperties); + void ProcessViewStyle(const Reference& rxCanvas, + const Reference& rxProperties); }; class StyleAssociationContainer @@ -208,16 +202,10 @@ private: class PresenterTheme::Theme { public: - Theme ( - const Reference& rThemeRoot, - OUString sNodeName); - - void Read ( - PresenterConfigurationAccess& rConfiguration, - ReadContext& rReadContext); + Theme(const Reference& rThemeRoot, OUString sNodeName, + const Reference& rxCanvas); OUString msConfigurationNodeName; - std::shared_ptr mpParentTheme; SharedBitmapDescriptor mpBackground; PaneStyleContainer maPaneStyles; ViewStyleContainer maViewStyles; @@ -253,14 +241,12 @@ PresenterTheme::~PresenterTheme() std::shared_ptr PresenterTheme::ReadTheme() { - ReadContext aReadContext(mxCanvas); - PresenterConfigurationAccess aConfiguration ( mxContext, u"/org.openoffice.Office.PresenterScreen/"_ustr, PresenterConfigurationAccess::READ_ONLY); - return aReadContext.ReadTheme(aConfiguration, OUString()); + return ReadContext::ReadTheme(aConfiguration, mxCanvas); } bool PresenterTheme::HasCanvas() const @@ -280,12 +266,8 @@ void PresenterTheme::ProvideCanvas (const Reference& rxCanva OUString PresenterTheme::GetStyleName (const OUString& rsResourceURL) const { OUString sStyleName; - std::shared_ptr pTheme (mpTheme); - while (sStyleName.isEmpty() && pTheme != nullptr) - { - sStyleName = pTheme->maStyleAssociations.GetStyleName(rsResourceURL); - pTheme = pTheme->mpParentTheme; - } + if (mpTheme) + sStyleName = mpTheme->maStyleAssociations.GetStyleName(rsResourceURL); return sStyleName; } @@ -365,15 +347,7 @@ SharedBitmapDescriptor PresenterTheme::GetBitmap ( if (rsStyleName.isEmpty()) { if (rsBitmapName == "Background") - { - std::shared_ptr pTheme (mpTheme); - while (pTheme != nullptr && !pTheme->mpBackground) - pTheme = pTheme->mpParentTheme; - if (pTheme != nullptr) - return pTheme->mpBackground; - else - return SharedBitmapDescriptor(); - } + return mpTheme->mpBackground; } else { @@ -405,13 +379,7 @@ SharedBitmapDescriptor PresenterTheme::GetBitmap ( { if (rsBitmapName == "Background") { - std::shared_ptr pTheme (mpTheme); - while (pTheme != nullptr && !pTheme->mpBackground) - pTheme = pTheme->mpParentTheme; - if (pTheme != nullptr) - return pTheme->mpBackground; - else - return SharedBitmapDescriptor(); + return mpTheme->mpBackground; } else { @@ -444,15 +412,9 @@ PresenterTheme::SharedFontDescriptor PresenterTheme::GetFont ( if (pViewStyle) return pViewStyle->GetFont(); - std::shared_ptr pTheme (mpTheme); - while (pTheme != nullptr) - { - Theme::FontContainer::const_iterator iFont (pTheme->maFontContainer.find(rsStyleName)); - if (iFont != pTheme->maFontContainer.end()) - return iFont->second; - - pTheme = pTheme->mpParentTheme; - } + Theme::FontContainer::const_iterator iFont(mpTheme->maFontContainer.find(rsStyleName)); + if (iFont != mpTheme->maFontContainer.end()) + return iFont->second; } return SharedFontDescriptor(); @@ -549,53 +511,35 @@ double PresenterTheme::FontDescriptor::GetCellSizeForDesignSize ( //===== Theme ================================================================= -PresenterTheme::Theme::Theme ( - const Reference& rxThemeRoot, - OUString sNodeName) - : msConfigurationNodeName(std::move(sNodeName)), - maPaneStyles(), - maViewStyles(), - maStyleAssociations(), - mxThemeRoot(rxThemeRoot) +PresenterTheme::Theme::Theme(const Reference& rxThemeRoot, + OUString sNodeName, const Reference& rxCanvas) + : msConfigurationNodeName(std::move(sNodeName)) + , maPaneStyles() + , maViewStyles() + , maStyleAssociations() + , mxThemeRoot(rxThemeRoot) { -} - -void PresenterTheme::Theme::Read ( - PresenterConfigurationAccess& rConfiguration, - ReadContext& rReadContext) -{ - // Parent theme name. - OUString sParentThemeName; - if ((PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, u"ParentTheme"_ustr) - >>= sParentThemeName) - && !sParentThemeName.isEmpty()) - { - mpParentTheme = rReadContext.ReadTheme(rConfiguration, sParentThemeName); - } - // Background. mpBackground = PresenterBitmapContainer::LoadBitmap( mxThemeRoot, u"Background"_ustr, - rReadContext.mxCanvas, + rxCanvas, SharedBitmapDescriptor()); // Style associations. maStyleAssociations.Read(mxThemeRoot); // Pane styles. - maPaneStyles.Read(rReadContext, mxThemeRoot); + maPaneStyles.Read(rxCanvas, mxThemeRoot); // View styles. - maViewStyles.Read(rReadContext, mxThemeRoot); + maViewStyles.Read(rxCanvas, mxThemeRoot); // Read bitmaps. mpIconContainer = std::make_shared( Reference( PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, u"Bitmaps"_ustr), UNO_QUERY), - mpParentTheme != nullptr ? mpParentTheme->mpIconContainer - : std::shared_ptr(), - rReadContext.mxCanvas); + std::shared_ptr(), rxCanvas); // Read fonts. Reference xFontNode( @@ -614,8 +558,6 @@ SharedPaneStyle PresenterTheme::Theme::GetPaneStyle (const OUString& rsStyleName SharedPaneStyle pPaneStyle (maPaneStyles.GetPaneStyle(rsStyleName)); if (pPaneStyle) return pPaneStyle; - else if (mpParentTheme != nullptr) - return mpParentTheme->GetPaneStyle(rsStyleName); else return SharedPaneStyle(); } @@ -625,8 +567,6 @@ SharedViewStyle PresenterTheme::Theme::GetViewStyle (const OUString& rsStyleName SharedViewStyle pViewStyle (maViewStyles.GetViewStyle(rsStyleName)); if (pViewStyle) return pViewStyle; - else if (mpParentTheme != nullptr) - return mpParentTheme->GetViewStyle(rsStyleName); else return SharedViewStyle(); } @@ -642,11 +582,6 @@ namespace { //===== ReadContext =========================================================== -ReadContext::ReadContext(const Reference& rxCanvas) - : mxCanvas(rxCanvas) -{ -} - PresenterTheme::SharedFontDescriptor ReadContext::ReadFont ( const Reference& rxNode, const PresenterTheme::SharedFontDescriptor& rpDefault) @@ -703,22 +638,17 @@ Any ReadContext::GetByName ( return Any(); } -std::shared_ptr ReadContext::ReadTheme ( - PresenterConfigurationAccess& rConfiguration, - const OUString& rsThemeName) +std::shared_ptr +ReadContext::ReadTheme(PresenterConfigurationAccess& rConfiguration, + const Reference& rxCanvas) { - std::shared_ptr pTheme; - - OUString sCurrentThemeName (rsThemeName); + OUString sCurrentThemeName; + // Look up the CurrentTheme property. + rConfiguration.GetConfigurationNode(u"Presenter/CurrentTheme"_ustr) >>= sCurrentThemeName; if (sCurrentThemeName.isEmpty()) { - // No theme name given. Look up the CurrentTheme property. - rConfiguration.GetConfigurationNode(u"Presenter/CurrentTheme"_ustr) >>= sCurrentThemeName; - if (sCurrentThemeName.isEmpty()) - { - // Still no name. Use "DefaultTheme". - sCurrentThemeName = "DefaultTheme"; - } + // No name. Use "DefaultTheme". + sCurrentThemeName = u"DefaultTheme"_ustr; } Reference xThemes ( @@ -738,20 +668,12 @@ std::shared_ptr ReadContext::ReadTheme ( PresenterConfigurationAccess::GetConfigurationNode(xTheme, u"ThemeName"_ustr) >>= sThemeName; if (sThemeName == sCurrentThemeName) - { - pTheme = std::make_shared(xTheme,rsKey); - break; - } + return std::make_shared(xTheme, rsKey, rxCanvas); } } } - if (pTheme != nullptr) - { - pTheme->Read(rConfiguration, *this); - } - - return pTheme; + return {}; } BorderSize ReadContext::ReadBorderSize (const Reference& rxNode) @@ -771,9 +693,8 @@ BorderSize ReadContext::ReadBorderSize (const Reference& //===== PaneStyleContainer ==================================================== -void PaneStyleContainer::Read ( - const ReadContext& rReadContext, - const Reference& rxThemeRoot) +void PaneStyleContainer::Read(const Reference& rxCanvas, + const Reference& rxThemeRoot) { Reference xPaneStyleList ( PresenterConfigurationAccess::GetConfigurationNode( @@ -794,15 +715,14 @@ void PaneStyleContainer::Read ( PresenterConfigurationAccess::ForAll( xPaneStyleList, aProperties, - [this, &rReadContext] (std::vector const& rValues) + [this, &rxCanvas] (std::vector const& rValues) { - return this->ProcessPaneStyle(rReadContext, rValues); + return this->ProcessPaneStyle(rxCanvas, rValues); }); } -void PaneStyleContainer::ProcessPaneStyle( - ReadContext const & rReadContext, - const ::std::vector& rValues) +void PaneStyleContainer::ProcessPaneStyle(const Reference& rxCanvas, + const ::std::vector& rValues) { if (rValues.size() != 6) return; @@ -836,14 +756,14 @@ void PaneStyleContainer::ProcessPaneStyle( pStyle->maOuterBorderSize.Merge(pStyle->mpParentStyle->maOuterBorderSize); } - if (rReadContext.mxCanvas.is()) + if (rxCanvas.is()) { Reference xBitmapsNode (rValues[5], UNO_QUERY); pStyle->mpBitmaps = std::make_shared( xBitmapsNode, pStyle->mpParentStyle != nullptr ? pStyle->mpParentStyle->mpBitmaps : std::shared_ptr(), - rReadContext.mxCanvas); + rxCanvas); } mStyles.push_back(std::move(pStyle)); @@ -891,9 +811,8 @@ PresenterTheme::SharedFontDescriptor PaneStyle::GetFont() const //===== ViewStyleContainer ==================================================== -void ViewStyleContainer::Read ( - const ReadContext& rReadContext, - const Reference& rxThemeRoot) +void ViewStyleContainer::Read(const Reference& rxCanvas, + const Reference& rxThemeRoot) { Reference xViewStyleList ( PresenterConfigurationAccess::GetConfigurationNode( @@ -904,16 +823,15 @@ void ViewStyleContainer::Read ( { PresenterConfigurationAccess::ForAll( xViewStyleList, - [this, &rReadContext] (OUString const&, uno::Reference const& xProps) + [this, &rxCanvas] (OUString const&, uno::Reference const& xProps) { - return this->ProcessViewStyle(rReadContext, xProps); + return this->ProcessViewStyle(rxCanvas, xProps); }); } } -void ViewStyleContainer::ProcessViewStyle( - ReadContext const & rReadContext, - const Reference& rxProperties) +void ViewStyleContainer::ProcessViewStyle(const Reference& rxCanvas, + const Reference& rxProperties) { auto pStyle = std::make_shared(); @@ -948,7 +866,7 @@ void ViewStyleContainer::ProcessViewStyle( SharedBitmapDescriptor pBackground (PresenterBitmapContainer::LoadBitmap( xBackgroundNode, OUString(), - rReadContext.mxCanvas, + rxCanvas, SharedBitmapDescriptor())); if (pBackground && pBackground->GetNormalBitmap().is()) pStyle->mpBackground = std::move(pBackground); diff --git a/sd/source/console/PresenterTimer.cxx b/sd/source/console/PresenterTimer.cxx index 8ffa7ce53570..36133b9201a2 100644 --- a/sd/source/console/PresenterTimer.cxx +++ b/sd/source/console/PresenterTimer.cxx @@ -428,17 +428,10 @@ TimerTask::TimerTask ( { ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex()); - ::rtl::Reference pTimer; - if (mpInstance.is()) - { - pTimer = mpInstance; - } - if ( ! pTimer.is()) - { - pTimer.set(new PresenterClockTimer(rxContext)); - mpInstance = pTimer; - } - return pTimer; + if (!mpInstance.is()) + mpInstance.set(new PresenterClockTimer(rxContext)); + + return mpInstance; } PresenterClockTimer::PresenterClockTimer (const Reference& rxContext) diff --git a/sd/source/console/PresenterToolBar.cxx b/sd/source/console/PresenterToolBar.cxx index 849549c9f1e3..b7d722a15ab0 100644 --- a/sd/source/console/PresenterToolBar.cxx +++ b/sd/source/console/PresenterToolBar.cxx @@ -44,7 +44,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sdext::presenter { @@ -122,7 +121,6 @@ public: const SharedElementMode& rpSelectedMode, const SharedElementMode& rpDisabledMode, const SharedElementMode& rpMouseOverSelectedMode); - void CurrentSlideHasChanged(); void SetLocation (const awt::Point& rLocation); void SetSize (const geometry::RealSize2D& rSize); virtual void Paint ( @@ -480,9 +478,6 @@ void SAL_CALL PresenterToolBar::windowPaint (const css::awt::PaintEvent& rEvent) if ( ! mxCanvas.is()) return; - if ( ! mbIsPresenterViewActive) - return; - const rendering::ViewState aViewState ( geometry::AffineMatrix2D(1,0,0, 0,1,0), PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice())); @@ -703,8 +698,8 @@ void PresenterToolBar::Layout() double nX (0); switch (meAnchor) { - case Left : nX = 0; break; - case Center: nX = (aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap) / 2; break; + case Anchor::Left : nX = 0; break; + case Anchor::Center: nX = (aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap) / 2; break; } // Place the parts. @@ -873,7 +868,7 @@ void PresenterToolBar::UpdateSlideNumber() for (auto& rxElement : *rxPart) { if (rxElement) - rxElement->CurrentSlideHasChanged(); + rxElement->UpdateState(); } } } @@ -942,7 +937,7 @@ PresenterToolBarView::PresenterToolBarView ( mxWindow, mxCanvas, rpPresenterController, - PresenterToolBar::Center); + PresenterToolBar::Anchor::Center); mpToolBar->Initialize(u"PresenterScreenSettings/ToolBars/ToolBar"_ustr); if (mxWindow.is()) @@ -1084,11 +1079,6 @@ awt::Rectangle PresenterToolBar::Element::GetBoundingBox() const return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height); } -void PresenterToolBar::Element::CurrentSlideHasChanged() -{ - UpdateState(); -} - void PresenterToolBar::Element::SetLocation (const awt::Point& rLocation) { maLocation = rLocation; @@ -1280,12 +1270,8 @@ void ElementMode::ReadElementMode ( } } -} // end of anonymous namespace - //===== Button ================================================================ -namespace { - ::rtl::Reference Button::Create ( const ::rtl::Reference& rpToolBar) { @@ -1445,12 +1431,8 @@ void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent) PresenterToolBar::Element::disposing(rEvent); } -} // end of anonymous namespace - //===== PresenterToolBar::Label =============================================== -namespace { - Label::Label (const ::rtl::Reference& rpToolBar) : PresenterToolBar::Element(rpToolBar) { @@ -1503,12 +1485,8 @@ bool Label::SetState (const bool, const bool) return PresenterToolBar::Element::SetState(false, false); } -} // end of anonymous namespace - //===== Text ================================================================== -namespace { - Text::Text() { } diff --git a/sd/source/console/PresenterToolBar.hxx b/sd/source/console/PresenterToolBar.hxx index cef953b8c580..65dd03115ac4 100644 --- a/sd/source/console/PresenterToolBar.hxx +++ b/sd/source/console/PresenterToolBar.hxx @@ -59,13 +59,10 @@ typedef cppu::ImplInheritanceHelper< */ class PresenterToolBar : private ::cppu::BaseMutex, - public PresenterToolBarInterfaceBase, - public CachablePresenterView + public PresenterToolBarInterfaceBase { public: - typedef ::std::function Action; - - enum Anchor { Left, Center }; + enum class Anchor { Left, Center }; PresenterToolBar ( const css::uno::Reference& rxContext, @@ -227,7 +224,6 @@ public: virtual css::uno::Reference SAL_CALL getCurrentPage() override; private: - // css::uno::Reference mxComponentContext; rtl::Reference mxPane; rtl::Reference mxViewId; css::uno::Reference mxWindow; diff --git a/sd/source/console/PresenterViewFactory.cxx b/sd/source/console/PresenterViewFactory.cxx index b1ddb8917157..8d7ed45f2e4f 100644 --- a/sd/source/console/PresenterViewFactory.cxx +++ b/sd/source/console/PresenterViewFactory.cxx @@ -31,7 +31,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sdext::presenter { @@ -103,10 +102,10 @@ PresenterViewFactory::PresenterViewFactory ( { } -rtl::Reference PresenterViewFactory::Create ( - const Reference& rxContext, - const rtl::Reference<::sd::DrawController>& rxController, - const ::rtl::Reference& rpPresenterController) +rtl::Reference +PresenterViewFactory::Create(const Reference& rxContext, + const rtl::Reference<::sd::DrawController>& rxController, + const ::rtl::Reference& rpPresenterController) { rtl::Reference pFactory ( new PresenterViewFactory(rxContext,rxController,rpPresenterController)); @@ -151,23 +150,6 @@ void PresenterViewFactory::disposing(std::unique_lock&) if (mxConfigurationController.is()) mxConfigurationController->removeResourceFactoryForReference(this); mxConfigurationController = nullptr; - - if (mpResourceCache == nullptr) - return; - - // Dispose all views in the cache. - for (const auto& rView : *mpResourceCache) - { - try - { - if (rView.second.first.is()) - rView.second.first->dispose(); - } - catch (lang::DisposedException&) - { - } - } - mpResourceCache.reset(); } //----- XViewFactory ---------------------------------------------------------- @@ -180,15 +162,13 @@ rtl::Reference PresenterViewFactory::createReso throwIfDisposed(l); } - rtl::Reference xView; + rtl::Reference xView; if (rxViewId.is()) { rtl::Reference xAnchorPane = dynamic_cast( mxConfigurationController->getResource(rxViewId->getAnchor()).get()); - xView = GetViewFromCache(rxViewId, xAnchorPane); - if (xView == nullptr) - xView = CreateView(rxViewId, xAnchorPane); + xView = CreateView(rxViewId, xAnchorPane); // Activate the view. PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( @@ -217,77 +197,23 @@ void PresenterViewFactory::releaseResource (const rtl::ReferenceSetActivationState(false); - // Dispose only views that we can not put into the cache. - CachablePresenterView* pView = dynamic_cast(rxView.get()); - if (pView == nullptr || mpResourceCache == nullptr) - { - try - { - if (pView != nullptr) - pView->ReleaseView(); - if (rxView.is()) - rxView->dispose(); - } - catch (lang::DisposedException&) - { - // Do not let disposed exceptions get out. It might be interpreted - // as coming from the factory, which would then be removed from the - // drawing framework. - } - } - else - { - // Put cacheable views in the cache. - rtl::Reference xViewId (rxView->getResourceId()); - if (xViewId.is()) - { - rtl::Reference xAnchorPane = dynamic_cast( - mxConfigurationController->getResource(xViewId->getAnchor()).get()); - (*mpResourceCache)[xViewId->getResourceURL()] - = ViewResourceDescriptor(dynamic_cast(rxView.get()), xAnchorPane); - pView->DeactivatePresenterView(); - } - } -} - - -rtl::Reference PresenterViewFactory::GetViewFromCache( - const rtl::Reference& rxViewId, - const rtl::Reference& rxAnchorPane) const -{ - if (mpResourceCache == nullptr) - return nullptr; - + PresenterSlideShowView* pView = dynamic_cast(rxView.get()); try { - const OUString sResourceURL (rxViewId->getResourceURL()); - - // Can we use a view from the cache? - ResourceContainer::const_iterator iView (mpResourceCache->find(sResourceURL)); - if (iView != mpResourceCache->end()) - { - // The view is in the container but it can only be used if - // the anchor pane is the same now as it was at creation of - // the view. - if (iView->second.second == rxAnchorPane) - { - CachablePresenterView* pView - = dynamic_cast(iView->second.first.get()); - if (pView != nullptr) - pView->ActivatePresenterView(); - return iView->second.first; - } - - // Right view, wrong pane. Create a new view. - } + if (pView != nullptr) + pView->ReleaseView(); + if (rxView.is()) + rxView->dispose(); } - catch (RuntimeException&) + catch (lang::DisposedException&) { + // Do not let disposed exceptions get out. It might be interpreted + // as coming from the factory, which would then be removed from the + // drawing framework. } - return nullptr; } -rtl::Reference PresenterViewFactory::CreateView( +rtl::Reference PresenterViewFactory::CreateView( const rtl::Reference& rxViewId, const rtl::Reference& rxAnchorPane) { @@ -299,7 +225,10 @@ rtl::Reference PresenterViewFactory::CreateView if (sResourceURL == msCurrentSlidePreviewViewURL) { - xView = CreateSlideShowView(rxViewId); + rtl::Reference pView = CreateSlideShowView(rxViewId); + if (pView) + pView->ActivatePresenterView(); + xView = pView; } else if (sResourceURL == msNotesViewURL) { @@ -321,11 +250,6 @@ rtl::Reference PresenterViewFactory::CreateView { xView = CreateHelpView(rxViewId); } - - // Activate it. - CachablePresenterView* pView = dynamic_cast(xView.get()); - if (pView != nullptr) - pView->ActivatePresenterView(); } catch (RuntimeException&) { @@ -335,7 +259,7 @@ rtl::Reference PresenterViewFactory::CreateView return xView; } -rtl::Reference PresenterViewFactory::CreateSlideShowView( +rtl::Reference PresenterViewFactory::CreateSlideShowView( const rtl::Reference& rxViewId) const { if ( ! mxConfigurationController.is()) @@ -464,27 +388,6 @@ rtl::Reference PresenterViewFactory::CreateHelpView mpPresenterController); } -//===== CachablePresenterView ================================================= - -CachablePresenterView::CachablePresenterView() - : mbIsPresenterViewActive(true) -{ -} - -void CachablePresenterView::ActivatePresenterView() -{ - mbIsPresenterViewActive = true; -} - -void CachablePresenterView::DeactivatePresenterView() -{ - mbIsPresenterViewActive = false; -} - -void CachablePresenterView::ReleaseView() -{ -} - } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/console/PresenterViewFactory.hxx b/sd/source/console/PresenterViewFactory.hxx index e59589416450..becfc29531d0 100644 --- a/sd/source/console/PresenterViewFactory.hxx +++ b/sd/source/console/PresenterViewFactory.hxx @@ -20,6 +20,8 @@ #pragma once #include "PresenterController.hxx" +#include "PresenterSlideShowView.hxx" + #include #include #include @@ -31,36 +33,9 @@ namespace sd { class DrawController; } namespace sdext::presenter { -/** Base class for presenter views that allows the view factory to store - them in a cache and reuse deactivated views. -*/ -class SAL_LOPLUGIN_ANNOTATE("crosscast") CachablePresenterView -{ -public: - virtual void ActivatePresenterView(); - - /** Called when the view is put into a cache. The view must not paint - itself while being deactivated. - */ - virtual void DeactivatePresenterView(); - - /** Called before the view is disposed. This gives the view the - opportunity to trigger actions that may lead to (synchronous) - callbacks that do not result in DisposedExceptions. - */ - virtual void ReleaseView(); - -protected: - bool mbIsPresenterViewActive; - - CachablePresenterView(); - - ~CachablePresenterView() {} -}; - /** Factory of the presenter screen specific views. The supported set of views includes: - a life view of the current slide, + a live view of the current slide, a static preview of the next slide, the notes of the current slide, a tool bar @@ -84,10 +59,10 @@ public: shut down and releases its reference to the factory then the factory is destroyed. */ - static rtl::Reference Create ( - const css::uno::Reference& rxContext, - const ::rtl::Reference<::sd::DrawController>& rxController, - const ::rtl::Reference& rpPresenterController); + static rtl::Reference + Create(const css::uno::Reference& rxContext, + const ::rtl::Reference<::sd::DrawController>& rxController, + const ::rtl::Reference& rpPresenterController); virtual ~PresenterViewFactory() override; virtual void disposing(std::unique_lock&) override; @@ -110,7 +85,6 @@ private: typedef ::std::pair, rtl::Reference > ViewResourceDescriptor; typedef ::std::map ResourceContainer; - std::unique_ptr mpResourceCache; PresenterViewFactory ( const css::uno::Reference& rxContext, @@ -119,7 +93,7 @@ private: void Register (const ::rtl::Reference<::sd::DrawController>& rxController); - rtl::Reference CreateSlideShowView( + rtl::Reference CreateSlideShowView( const rtl::Reference& rxViewId) const; rtl::Reference CreateSlidePreviewView( @@ -138,10 +112,7 @@ private: rtl::Reference CreateHelpView( const rtl::Reference& rxViewId) const; - rtl::Reference GetViewFromCache ( - const rtl::Reference& rxViewId, - const rtl::Reference& rxAnchorPane) const; - rtl::Reference CreateView( + rtl::Reference CreateView( const rtl::Reference& rxViewId, const rtl::Reference& rxAnchorPane); }; diff --git a/sd/source/console/PresenterWindowManager.cxx b/sd/source/console/PresenterWindowManager.cxx index 791476e89cb0..6acb9e2736b3 100644 --- a/sd/source/console/PresenterWindowManager.cxx +++ b/sd/source/console/PresenterWindowManager.cxx @@ -42,7 +42,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sdext::presenter { diff --git a/sd/source/core/CustomAnimationEffect.cxx b/sd/source/core/CustomAnimationEffect.cxx index 2c6beb28b30a..53d8276ba86a 100644 --- a/sd/source/core/CustomAnimationEffect.cxx +++ b/sd/source/core/CustomAnimationEffect.cxx @@ -74,6 +74,8 @@ #include #include #include +#include +#include #include #include #include @@ -1441,6 +1443,20 @@ bool CustomAnimationEffect::setTransformationProperty( sal_Int32 nTransformType, return bChanged; } +namespace +{ +// Register the effect's external sound on the slide that owns it, so allowing +// the link marks the audio node's source allowed. +void lcl_registerEffectSoundLink(const CustomAnimationEffect& rEffect) +{ + SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rEffect.getTargetShape()); + SdrPage* pPage = pObj ? pObj->getSdrPageFromSdrObject() : nullptr; + if (pPage) + static_cast(pPage->getSdrModelFromSdrPage()) + .RegisterAnimationSoundLinks(static_cast(*pPage)); +} +} + void CustomAnimationEffect::createAudio( const css::uno::Any& rSource ) { DBG_ASSERT( !mxAudio.is(), "sd::CustomAnimationEffect::createAudio(), node already has an audio!" ); @@ -1455,6 +1471,7 @@ void CustomAnimationEffect::createAudio( const css::uno::Any& rSource ) xAudio->setSource( rSource ); xAudio->setVolume( 1.0 ); setAudio( xAudio ); + lcl_registerEffectSoundLink( *this ); } catch( Exception& ) { @@ -1462,6 +1479,14 @@ void CustomAnimationEffect::createAudio( const css::uno::Any& rSource ) } } +void CustomAnimationEffect::setAudioSource( const css::uno::Any& rSource ) +{ + if( !mxAudio.is() ) + return; + mxAudio->setSource( rSource ); + lcl_registerEffectSoundLink( *this ); +} + static Reference< XCommand > findCommandNode( const Reference< XAnimationNode >& xRootNode ) { Reference< XCommand > xCommand; @@ -2228,40 +2253,7 @@ void EffectSequenceHelper::insertTextRange( const css::uno::Any& aTarget ) rebuild(); } -static bool isParagraphTargetTextEmpty( ParagraphTarget aParaTarget ) -{ - // get paragraph - Reference< XText > xText ( aParaTarget.Shape, UNO_QUERY ); - if( xText.is() ) - { - Reference< XEnumerationAccess > xEA( xText, UNO_QUERY ); - if( xEA.is() ) - { - Reference< XEnumeration > xEnumeration = xEA->createEnumeration(); - if( xEnumeration.is() ) - { - // advance to the Nth paragraph - sal_Int32 nPara = aParaTarget.Paragraph; - while( xEnumeration->hasMoreElements() && nPara-- ) - xEnumeration->nextElement(); - - // get Nth paragraph's text and check if it's empty - if( xEnumeration->hasMoreElements() ) - { - Reference< XTextRange > xRange( xEnumeration->nextElement(), UNO_QUERY ); - if( xRange.is() ) - { - OUString text = xRange->getString(); - return text.isEmpty(); - } - } - } - } - } - return false; -} - -void EffectSequenceHelper::disposeTextRange( const css::uno::Any& aTarget ) +void EffectSequenceHelper::disposeTextRange( const css::uno::Any& aTarget, bool bPreviousParagraphEmpty ) { ParagraphTarget aParaTarget; if( !(aTarget >>= aParaTarget ) ) @@ -2289,11 +2281,10 @@ void EffectSequenceHelper::disposeTextRange( const css::uno::Any& aTarget ) } // select effect to delete: - // if paragraph before target is blank, then delete its animation effect (if any) instead - ParagraphTarget aPreviousParagraph = aParaTarget; - --aPreviousParagraph.Paragraph; - bool bIsPreviousParagraphEmpty = isParagraphTargetTextEmpty( aPreviousParagraph ); - sal_Int16 anParaNumToDelete = bIsPreviousParagraphEmpty ? aPreviousParagraph.Paragraph : aParaTarget.Paragraph; + // if the paragraph before the target is blank, delete its animation effect (if any) instead. + sal_Int16 anParaNumToDelete = aParaTarget.Paragraph; + if( bPreviousParagraphEmpty ) + --anParaNumToDelete; // update effects for( const auto &pEffect : aTargetParagraphEffects ) @@ -3322,13 +3313,13 @@ void MainSequence::insertTextRange( const css::uno::Any& aTarget ) } } -void MainSequence::disposeTextRange( const css::uno::Any& aTarget ) +void MainSequence::disposeTextRange( const css::uno::Any& aTarget, bool bPreviousParagraphEmpty ) { - EffectSequenceHelper::disposeTextRange( aTarget ); + EffectSequenceHelper::disposeTextRange( aTarget, bPreviousParagraphEmpty ); for (auto const& iterativeSequence : maInteractiveSequenceVector) { - iterativeSequence->disposeTextRange( aTarget ); + iterativeSequence->disposeTextRange( aTarget, bPreviousParagraphEmpty ); } } diff --git a/sd/source/core/EffectMigration.cxx b/sd/source/core/EffectMigration.cxx index e1a880592101..0520455f8bf6 100644 --- a/sd/source/core/EffectMigration.cxx +++ b/sd/source/core/EffectMigration.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -1205,8 +1206,12 @@ void EffectMigration::UpdateSoundEffect( SvxShape* pShape, SdAnimationInfo const bool bNeedRebuild = false; OUString aSoundFile; + bool bSoundAllowed = false; if( pInfo->mbSoundOn ) - aSoundFile = pInfo->maSoundFile; + { + aSoundFile = pInfo->maSoundLink.getURL(); + bSoundAllowed = pInfo->maSoundLink.isAllowed(); + } for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) { @@ -1215,7 +1220,7 @@ void EffectMigration::UpdateSoundEffect( SvxShape* pShape, SdAnimationInfo const { if( !aSoundFile.isEmpty() ) { - pEffect->createAudio( Any( aSoundFile ) ); + pEffect->createAudio( xmloff::makeSoundSource( aSoundFile, bSoundAllowed ) ); } else { @@ -1252,7 +1257,7 @@ OUString EffectMigration::GetSoundFile( SvxShape* pShape ) if( pEffect->getTargetShape() == xShape ) { if( pEffect->getAudio().is() ) - pEffect->getAudio()->getSource() >>= aSoundFile; + aSoundFile = xmloff::getSoundURL( pEffect->getAudio()->getSource() ); } } } diff --git a/sd/source/core/SlideSectionManager.cxx b/sd/source/core/SlideSectionManager.cxx new file mode 100644 index 000000000000..6a1dc1488a99 --- /dev/null +++ b/sd/source/core/SlideSectionManager.cxx @@ -0,0 +1,354 @@ +/* -*- 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 +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace sd +{ +SlideSectionManager::SlideSectionManager(SdDrawDocument& rDoc) + : mrDoc(rDoc) +{ +} + +void SlideSectionManager::SetSectionsFromPropertyValues( + const uno::Sequence& rSections) +{ + maSections.clear(); + + if (!rSections.hasElements()) + return; + + // Build page-name-to-index map + sal_uInt16 nPageCount = mrDoc.GetSdPageCount(PageKind::Standard); + std::map aNameToIndex; + for (sal_uInt16 i = 0; i < nPageCount; ++i) + { + SdPage* pPage = mrDoc.GetSdPage(i, PageKind::Standard); + if (pPage) + aNameToIndex[pPage->GetName()] = i; + } + + // Running index for position-based fallback when names don't match + sal_Int32 nFallbackIdx = 0; + for (const auto& rSectionProp : rSections) + { + uno::Sequence aSectionProps; + rSectionProp.Value >>= aSectionProps; + + SlideSection aSection; + uno::Sequence aSlideNames; + + for (const auto& rProp : aSectionProps) + { + if (rProp.Name == "Name") + rProp.Value >>= aSection.maName; + else if (rProp.Name == "Id") + rProp.Value >>= aSection.maId; + else if (rProp.Name == "SlideNameList") + rProp.Value >>= aSlideNames; + } + + // The section starts at the first slide in its list. + // Try name lookup first; fall back to position if names don't match + // (e.g. after ODP round-trip where page names change). + if (aSlideNames.hasElements()) + { + auto it = aNameToIndex.find(aSlideNames[0]); + if (it != aNameToIndex.end()) + aSection.mnStartIndex = it->second; + else + aSection.mnStartIndex = nFallbackIdx; + } + else + { + aSection.mnStartIndex = nFallbackIdx; + } + + nFallbackIdx += aSlideNames.getLength(); + maSections.push_back(aSection); + } + + // Sort by start index + std::sort(maSections.begin(), maSections.end(), + [](const SlideSection& a, const SlideSection& b) { + return a.mnStartIndex < b.mnStartIndex; + }); +} + +uno::Sequence SlideSectionManager::GetSectionsAsPropertyValues() const +{ + sal_uInt16 nPageCount = mrDoc.GetSdPageCount(PageKind::Standard); + + std::vector aSectionsList; + for (size_t i = 0; i < maSections.size(); ++i) + { + const SlideSection& rSection = maSections[i]; + + // Determine end index (start of next section, or page count) + sal_Int32 nEndIndex + = (i + 1 < maSections.size()) ? maSections[i + 1].mnStartIndex : nPageCount; + + // Collect slide names for this section + std::vector aSlideNames; + for (sal_Int32 j = rSection.mnStartIndex; j < nEndIndex; ++j) + { + SdPage* pPage = mrDoc.GetSdPage(static_cast(j), PageKind::Standard); + if (pPage) + aSlideNames.push_back(pPage->GetName()); + } + + // Build section properties + std::vector aProps; + aProps.push_back(comphelper::makePropertyValue(u"Name"_ustr, rSection.maName)); + if (!rSection.maId.isEmpty()) + aProps.push_back(comphelper::makePropertyValue(u"Id"_ustr, rSection.maId)); + aProps.push_back(comphelper::makePropertyValue( + u"SlideNameList"_ustr, comphelper::containerToSequence(aSlideNames))); + + aSectionsList.push_back(comphelper::makePropertyValue( + u"Section"_ustr + OUString::number(i), comphelper::containerToSequence(aProps))); + } + + return comphelper::containerToSequence(aSectionsList); +} + +sal_Int32 SlideSectionManager::GetSectionCount() const { return maSections.size(); } + +const SlideSection& SlideSectionManager::GetSection(sal_Int32 nIndex) const +{ + assert(nIndex >= 0 && o3tl::make_unsigned(nIndex) < maSections.size()); + return maSections[nIndex]; +} + +sal_Int32 SlideSectionManager::GetSectionIndexForSlide(sal_Int32 nSlideIndex) const +{ + // Sections are sorted by start index; find the last section whose start <= nSlideIndex + sal_Int32 nResult = -1; + for (sal_Int32 i = 0; i < static_cast(maSections.size()); ++i) + { + if (maSections[i].mnStartIndex <= nSlideIndex) + nResult = i; + else + break; + } + return nResult; +} + +bool SlideSectionManager::IsSectionStart(sal_Int32 nSlideIndex) const +{ + for (const auto& rSection : maSections) + { + if (rSection.mnStartIndex == nSlideIndex) + return true; + } + return false; +} + +std::vector SlideSectionManager::GetSectionStartIndices() const +{ + std::vector aResult; + aResult.reserve(maSections.size()); + for (const auto& rSection : maSections) + aResult.push_back(rSection.mnStartIndex); + return aResult; +} + +void SlideSectionManager::AddSection(sal_Int32 nStartSlideIndex, const OUString& rName) +{ + SlideSection aNewSection; + aNewSection.maName = rName; + aNewSection.maId + = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_ASCII_US); + aNewSection.mnStartIndex = nStartSlideIndex; + + maSections.push_back(aNewSection); + + // Re-sort + std::sort(maSections.begin(), maSections.end(), + [](const SlideSection& a, const SlideSection& b) { + return a.mnStartIndex < b.mnStartIndex; + }); +} + +void SlideSectionManager::RemoveSection(sal_Int32 nSectionIndex) +{ + if (nSectionIndex < 0 || nSectionIndex >= static_cast(maSections.size())) + return; + + maSections.erase(maSections.begin() + nSectionIndex); +} + +void SlideSectionManager::RemoveSectionSlides(sal_Int32 nSectionIndex) +{ + if (nSectionIndex < 0 || nSectionIndex >= static_cast(maSections.size())) + return; + + // Compute the [nStart, nEnd) range of slides in this section. The + // section list is sorted by start index, so the next section's start + // (or the document's slide count) marks the end of this section. + const sal_Int32 nStart = maSections[nSectionIndex].mnStartIndex; + const sal_Int32 nEnd = (nSectionIndex + 1 < static_cast(maSections.size())) + ? maSections[nSectionIndex + 1].mnStartIndex + : static_cast(mrDoc.GetSdPageCount(PageKind::Standard)); + + try + { + rtl::Reference xModel(mrDoc.getUnoModel()); + if (!xModel.is()) + return; + + css::uno::Reference xPages(xModel->getDrawPages(), + css::uno::UNO_SET_THROW); + + // Iterate in reverse so that each remove() does not shift the + // indices of the slides we still have to delete. OnSlideRemoved + // fires per page delete and auto-erases the now-empty section + // metadata, so we deliberately do not call RemoveSection() here. + for (sal_Int32 i = nEnd - 1; i >= nStart; --i) + { + // Do not delete the last slide in the document. + if (xPages->getCount() <= 1) + break; + + css::uno::Reference xPage(xPages->getByIndex(i), + css::uno::UNO_QUERY_THROW); + xPages->remove(xPage); + } + } + catch (const css::uno::Exception&) + { + TOOLS_WARN_EXCEPTION("sd", "SlideSectionManager::RemoveSectionSlides()"); + } +} + +void SlideSectionManager::RenameSection(sal_Int32 nSectionIndex, const OUString& rNewName) +{ + if (nSectionIndex < 0 || nSectionIndex >= static_cast(maSections.size())) + return; + + maSections[nSectionIndex].maName = rNewName; +} + +void SlideSectionManager::MoveSection(sal_Int32 nOldIndex, sal_Int32 nNewIndex) +{ + if (nOldIndex < 0 || nOldIndex >= static_cast(maSections.size())) + return; + if (nNewIndex < 0 || nNewIndex >= static_cast(maSections.size())) + return; + if (nOldIndex == nNewIndex) + return; + + sal_uInt16 nPageCount = mrDoc.GetSdPageCount(PageKind::Standard); + + // 1. Capture slide counts per section BEFORE any moves + std::vector aSlideCounts; + for (size_t i = 0; i < maSections.size(); ++i) + { + sal_Int32 nEnd = (i + 1 < maSections.size()) ? maSections[i + 1].mnStartIndex + : static_cast(nPageCount); + aSlideCounts.push_back(nEnd - maSections[i].mnStartIndex); + } + + // 2. Calculate slide range for the source section + sal_Int32 nSrcStart = maSections[nOldIndex].mnStartIndex; + sal_Int32 nSrcEnd = nSrcStart + aSlideCounts[nOldIndex]; + sal_Int32 nSrcCount = aSlideCounts[nOldIndex]; + + if (nSrcCount <= 0) + return; + + // 3. Mark the source section's slides as selected + mrDoc.UnselectAllPages(); + for (sal_Int32 i = nSrcStart; i < nSrcEnd; ++i) + { + SdPage* pPage = mrDoc.GetSdPage(static_cast(i), PageKind::Standard); + if (pPage) + mrDoc.SetSelected(pPage, true); + } + + // 4. Calculate the target position + // MoveSelectedPages takes 0-based page index to insert after (-1 = before first) + sal_uInt16 nTargetPage; + if (nNewIndex < nOldIndex) + { + // Moving up: place before the target section's first slide + nTargetPage = (maSections[nNewIndex].mnStartIndex > 0) + ? static_cast(maSections[nNewIndex].mnStartIndex - 1) + : sal_uInt16(-1); + } + else + { + // Moving down: place after the target section's last slide + // MovePages() interprets nTargetPage as a 0-based standard-page index + // in the current ordering (it does NOT pre-remove the selected pages), + // so we pass the index of the target section's last slide directly. + sal_Int32 nTargetEnd = maSections[nNewIndex].mnStartIndex + aSlideCounts[nNewIndex]; + nTargetPage = static_cast(nTargetEnd - 1); + } + + // 5. Move the pages in the document + mrDoc.MoveSelectedPages(nTargetPage); + + // 6. Reorder section entries and their slide counts to match new order + SlideSection aMovedSection = maSections[nOldIndex]; + sal_Int32 nMovedCount = aSlideCounts[nOldIndex]; + + maSections.erase(maSections.begin() + nOldIndex); + aSlideCounts.erase(aSlideCounts.begin() + nOldIndex); + + // After erasing nOldIndex, elements after it shift down by 1. + // To place the moved section at nNewIndex in the original ordering: + // - Moving up (nNewIndex < nOldIndex): insert at nNewIndex (no shift needed) + // - Moving down (nNewIndex > nOldIndex): the target shifted down by 1, + // but we want to insert AFTER it, so nNewIndex - 1 + 1 = nNewIndex + sal_Int32 nInsertAt = nNewIndex; + maSections.insert(maSections.begin() + nInsertAt, aMovedSection); + aSlideCounts.insert(aSlideCounts.begin() + nInsertAt, nMovedCount); + + // 7. Recalculate start indices from the (now correctly ordered) slide counts + sal_Int32 nCurrentIdx = 0; + for (size_t i = 0; i < maSections.size(); ++i) + { + maSections[i].mnStartIndex = nCurrentIdx; + nCurrentIdx += aSlideCounts[i]; + } +} + +std::vector SlideSectionManager::GetSectionsSnapshot() const { return maSections; } + +void SlideSectionManager::RestoreSectionsSnapshot(const std::vector& rSections) +{ + maSections = rSections; + + // Broadcast so listeners (e.g. the slide sorter) repaint section headers. + SdrPage* pPage = mrDoc.GetSdPage(0, PageKind::Standard); + if (pPage) + { + SdrHint aHint(SdrHintKind::PageOrderChange, pPage); + mrDoc.Broadcast(aHint); + } +} + +} // namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/ThemeColorChanger.cxx b/sd/source/core/ThemeColorChanger.cxx index b06acf6891d3..eeb82cfdaace 100644 --- a/sd/source/core/ThemeColorChanger.cxx +++ b/sd/source/core/ThemeColorChanger.cxx @@ -133,7 +133,7 @@ bool changeStyles(sd::DrawDocShell* pDocShell, std::shared_ptr } // end anonymous ns -void ThemeColorChanger::doApply(std::shared_ptr const& pColorSet) +void ThemeColorChanger::apply(std::shared_ptr const& pColorSet) { auto* pUndoManager = mpDocShell->GetUndoManager(); sd::ViewShell* pViewShell = mpDocShell->GetViewShell(); diff --git a/sd/source/core/UndoSlideSection.cxx b/sd/source/core/UndoSlideSection.cxx new file mode 100644 index 000000000000..eeb733d382e7 --- /dev/null +++ b/sd/source/core/UndoSlideSection.cxx @@ -0,0 +1,43 @@ +/* -*- 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 +#include + +namespace sd +{ +UndoSlideSection::UndoSlideSection(SdDrawDocument& rDoc, const OUString& rComment) + : SdrUndoAction(rDoc) + , maOldSections(rDoc.GetSectionManager().GetSectionsSnapshot()) + , maComment(rComment) +{ +} + +void UndoSlideSection::Undo() +{ + auto& rDoc = static_cast(m_rMod); + if (!mbNewCaptured) + { + maNewSections = rDoc.GetSectionManager().GetSectionsSnapshot(); + mbNewCaptured = true; + } + rDoc.GetSectionManager().RestoreSectionsSnapshot(maOldSections); +} + +void UndoSlideSection::Redo() +{ + auto& rDoc = static_cast(m_rMod); + rDoc.GetSectionManager().RestoreSectionsSnapshot(maNewSections); +} + +OUString UndoSlideSection::GetComment() const { return maComment; } + +} // namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/anminfo.cxx b/sd/source/core/anminfo.cxx index 5f763708ccda..e34ee1575cfb 100644 --- a/sd/source/core/anminfo.cxx +++ b/sd/source/core/anminfo.cxx @@ -22,6 +22,8 @@ #include #include +#include +#include #include using namespace ::com::sun::star; @@ -39,6 +41,7 @@ SdAnimationInfo::SdAnimationInfo(SdrObject& rObject) mbSoundOn (false), mbPlayFull (false), meClickAction (presentation::ClickAction_NONE), + mbClickSoundAllowed (false), meSecondEffect (presentation::AnimationEffect_NONE), meSecondSpeed (presentation::AnimationSpeed_SLOW), mbSecondSoundOn (false), @@ -62,13 +65,13 @@ SdAnimationInfo::SdAnimationInfo(const SdAnimationInfo& rAnmInfo, SdrObject& rOb mbDimHide (rAnmInfo.mbDimHide), maBlueScreen (rAnmInfo.maBlueScreen), maDimColor (rAnmInfo.maDimColor), - maSoundFile (rAnmInfo.maSoundFile), + maSoundLink (rAnmInfo.maSoundLink), mbSoundOn (rAnmInfo.mbSoundOn), mbPlayFull (rAnmInfo.mbPlayFull), meClickAction (rAnmInfo.meClickAction), + mbClickSoundAllowed (rAnmInfo.mbClickSoundAllowed), meSecondEffect (rAnmInfo.meSecondEffect), meSecondSpeed (rAnmInfo.meSecondSpeed), - maSecondSoundFile (rAnmInfo.maSecondSoundFile), mbSecondSoundOn (rAnmInfo.mbSecondSoundOn), mbSecondPlayFull (rAnmInfo.mbSecondPlayFull), mnVerb (rAnmInfo.mnVerb), @@ -105,6 +108,16 @@ void SdAnimationInfo::SetBookmark( const OUString& rBookmark ) SvxFieldItem aURLItem( SvxURLField( rBookmark, rBookmark ), EE_FEATURE_FIELD ); mrObject.SetMergedItem( aURLItem ); } + + // A click-action sound pointing outside the document package is a link the + // user allows on its own; register it as the URL is set so it joins link + // management. + if( meClickAction == css::presentation::ClickAction_SOUND + && SdSoundLink( rBookmark ).isExternalLink() ) + { + static_cast(mrObject.getSdrModelFromSdrObject()) + .RegisterShapeSoundLink( mrObject ); + } } OUString SdAnimationInfo::GetBookmark() const diff --git a/sd/source/core/annotations/Annotation.cxx b/sd/source/core/annotations/Annotation.cxx index bc76a5c46614..6de36e12081e 100644 --- a/sd/source/core/annotations/Annotation.cxx +++ b/sd/source/core/annotations/Annotation.cxx @@ -245,6 +245,9 @@ rtl::Reference Annotation::clone(SdrPage* pTargetPa aNewAnnotation->setInitials(getInitials()); aNewAnnotation->setDateTime(getDateTime()); aNewAnnotation->setCreationInfo(getCreationInfo()); + aNewAnnotation->SetThreaded(IsThreaded()); + aNewAnnotation->SetResolved(IsResolved()); + aNewAnnotation->SetParentId(GetParentId()); uno::Reference xSourceRange (getTextRange(), uno::UNO_QUERY); uno::Reference xRange (aNewAnnotation->getTextRange(), uno::UNO_QUERY); diff --git a/sd/source/core/drawdoc.cxx b/sd/source/core/drawdoc.cxx index 065820d352d4..725ec345e3d3 100644 --- a/sd/source/core/drawdoc.cxx +++ b/sd/source/core/drawdoc.cxx @@ -40,10 +40,24 @@ #include #include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include +#include #include #include #include @@ -70,7 +84,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -264,6 +281,9 @@ SdDrawDocument::SdDrawDocument(DocumentType eType, SfxObjectShell* pDrDocSh) if (mpDocSh) { + // Setting the LinkManager also installs the fill bitmap link tracker, + // so deferred remote fills on shapes, page backgrounds and the + // Background style are registered per host as they are set. SetLinkManager( new sfx2::LinkManager(mpDocSh) ); } @@ -978,24 +998,405 @@ void SdDrawDocument::NewOrLoadCompleted(DocCreationMode eMode) SetChanged( false ); } +namespace +{ +// Base for a sound link bound to a page through sdr::PageUser, so the link is +// removed when the page goes away. A derived class implements DataChanged to +// mark its own sound allowed. +class SdPageBoundSoundLink : public sfx2::SvBaseLink, public sdr::PageUser +{ +protected: + SdPage* m_pPage; + + explicit SdPageBoundSoundLink(SdPage& rPage) + : SvBaseLink(SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SIMPLE_FILE) + , m_pPage(&rPage) + { + m_pPage->AddPageUser(*this); + } + + virtual ~SdPageBoundSoundLink() override + { + if (m_pPage) + m_pPage->RemovePageUser(*this); + } + +public: + const SdPage* getPage() const { return m_pPage; } + + virtual void PageInDestruction(const SdrPage&) override + { + // the page is tearing down and removes its own users, so just drop the back-pointer here + m_pPage = nullptr; + tools::SvRef xSelf(this); + if (sfx2::LinkManager* pLinkMgr = GetLinkManager()) + pLinkMgr->Remove(this); + } +}; + +// The slide-transition sound link, bound to its page the way +// sdr::SdrPageFillBitmapLink binds a fill bitmap to its host. Updating the link +// marks the page's own SdSoundLink allowed, so the page carries that state +// directly. +class SdPageSoundLink final : public SdPageBoundSoundLink +{ +public: + explicit SdPageSoundLink(SdPage& rPage) + : SdPageBoundSoundLink(rPage) + { + } + + virtual UpdateResult DataChanged(const OUString&, const css::uno::Any&) override + { + if (m_pPage) + m_pPage->SetSoundAllowed(true); + return SUCCESS; + } +}; + +// The click-action sound link, bound to its shape the way SdPageSoundLink binds +// to its page. Updating the link marks the shape's SdAnimationInfo allowed, so +// the shape carries that state directly. +// Bound through sdr::ObjectUser so it never outlives the shape. +class SdShapeSoundLink final : public sfx2::SvBaseLink, public sdr::ObjectUser +{ + SdrObject* m_pObject; + +public: + explicit SdShapeSoundLink(SdrObject& rObject) + : SvBaseLink(SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SIMPLE_FILE) + , m_pObject(&rObject) + { + m_pObject->AddObjectUser(*this); + } + + virtual ~SdShapeSoundLink() override + { + if (m_pObject) + m_pObject->RemoveObjectUser(*this); + } + + const SdrObject* getObject() const { return m_pObject; } + + virtual UpdateResult DataChanged(const OUString&, const css::uno::Any&) override + { + if (m_pObject) + { + if (SdAnimationInfo* pInfo = SdDrawDocument::GetShapeUserData(*m_pObject)) + pInfo->mbClickSoundAllowed = true; + } + return SUCCESS; + } + + virtual void ObjectInDestruction(const SdrObject&) override + { + // the shape is tearing down and removes its own users, so just drop the back-pointer here + m_pObject = nullptr; + tools::SvRef xSelf(this); + if (sfx2::LinkManager* pLinkMgr = GetLinkManager()) + pLinkMgr->Remove(this); + } +}; + +// The animation-effect sound link. It holds the audio node whose source carries +// the sound, and is bound to the node's page like the transition sound link. +// Updating the link marks that source allowed, so the node carries the allowed +// state directly. The URL is kept; only the allowed state changes. +class SdAnimationSoundLink final : public SdPageBoundSoundLink +{ + css::uno::Reference m_xAudio; + +public: + SdAnimationSoundLink(SdPage& rPage, css::uno::Reference xAudio) + : SdPageBoundSoundLink(rPage) + , m_xAudio(std::move(xAudio)) + { + } + + const css::uno::Reference& getAudio() const { return m_xAudio; } + + virtual UpdateResult DataChanged(const OUString&, const css::uno::Any&) override + { + if (m_xAudio.is()) + m_xAudio->setSource( + xmloff::makeSoundSource(xmloff::getSoundURL(m_xAudio->getSource()), true)); + return SUCCESS; + } +}; + +// True when rLinkManager already holds a link of LinkType for which rMatch +// returns true, that is, the link's owner is already registered. +template +bool lcl_hasSoundLink(const sfx2::LinkManager& rLinkManager, Match rMatch) +{ + for (const tools::SvRef& rLink : rLinkManager.GetLinks()) + { + const LinkType* pLink = dynamic_cast(rLink.get()); + if (pLink && rMatch(*pLink)) + return true; + } + return false; +} + +// True when the document holds any external sound link: a transition, a +// click-action or an animation-effect sound. +bool lcl_hasAnySoundLink(const sfx2::LinkManager& rLinkManager) +{ + for (const tools::SvRef& rLink : rLinkManager.GetLinks()) + { + sfx2::SvBaseLink* pLink = rLink.get(); + if (dynamic_cast(pLink) || dynamic_cast(pLink) + || dynamic_cast(pLink)) + return true; + } + return false; +} + +// Register an animation-sound link for every AUDIO node under rNode whose source +// points outside the document package, binding each to rPage. Sets rbFound when +// rNode holds any such sound. +void lcl_registerAudioSoundLinks( + const css::uno::Reference& rNode, + SdPage& rPage, sfx2::LinkManager& rLinkManager, bool& rbFound) +{ + if (!rNode.is()) + return; + + if (rNode->getType() == css::animations::AnimationNodeType::AUDIO) + { + css::uno::Reference xAudio(rNode, css::uno::UNO_QUERY); + const css::uno::Any aSource = xAudio.is() ? xAudio->getSource() : css::uno::Any(); + const OUString aURL = xmloff::getSoundURL(aSource); + if (SdSoundLink(aURL).isExternalLink() && !xmloff::getSoundAllowed(aSource)) + { + rbFound = true; + if (!lcl_hasSoundLink( + rLinkManager, [&xAudio](const SdAnimationSoundLink& rLink) + { return rLink.getAudio() == xAudio; })) + { + tools::SvRef xLink(new SdAnimationSoundLink(rPage, xAudio)); + rLinkManager.InsertFileLink(*xLink, sfx2::SvBaseLinkObjectType::ClientFile, aURL); + } + } + } + + css::uno::Reference xEnumAccess(rNode, css::uno::UNO_QUERY); + if (xEnumAccess.is()) + { + css::uno::Reference xEnum = xEnumAccess->createEnumeration(); + while (xEnum.is() && xEnum->hasMoreElements()) + { + css::uno::Reference xChild(xEnum->nextElement(), + css::uno::UNO_QUERY); + lcl_registerAudioSoundLinks(xChild, rPage, rLinkManager, rbFound); + } + } +} +} + +void SdDrawDocument::RegisterPageSoundLink(SdPage& rPage) +{ + // No link manager on a shell-less model (for example the clipboard), which + // has no infobar or slideshow, so nothing needs registering there. An + // already-allowed sound is the document's own content, not a link. + if (!m_pLinkManager || !rPage.GetSoundLink().isExternalLink() + || rPage.GetSoundLink().isAllowed()) + return; + if (lcl_hasSoundLink(*m_pLinkManager, [&rPage](const SdPageSoundLink& rLink) + { return rLink.getPage() == &rPage; })) + return; // already registered + tools::SvRef xLink(new SdPageSoundLink(rPage)); + m_pLinkManager->InsertFileLink(*xLink, sfx2::SvBaseLinkObjectType::ClientFile, + rPage.GetSoundFile()); +} + +bool SdDrawDocument::RegisterAnimationSoundLinks(SdPage& rPage) +{ + if (!m_pLinkManager || !rPage.hasAnimationNode()) + return false; + bool bFound = false; + lcl_registerAudioSoundLinks(rPage.getAnimationNode(), rPage, *m_pLinkManager, bFound); + return bFound; +} + +void SdDrawDocument::RegisterShapeSoundLink(SdrObject& rObject) +{ + if (!m_pLinkManager) + return; + SdAnimationInfo* pInfo = GetShapeUserData(rObject); + if (!pInfo || pInfo->meClickAction != css::presentation::ClickAction_SOUND + || !SdSoundLink(pInfo->GetBookmark()).isExternalLink() + || pInfo->mbClickSoundAllowed) + return; + if (lcl_hasSoundLink(*m_pLinkManager, [&rObject](const SdShapeSoundLink& rLink) + { return rLink.getObject() == &rObject; })) + return; // already registered + tools::SvRef xLink(new SdShapeSoundLink(rObject)); + m_pLinkManager->InsertFileLink(*xLink, sfx2::SvBaseLinkObjectType::ClientFile, + pInfo->GetBookmark()); +} + + /** updates all links, only links in this document should by resolved */ void SdDrawDocument::UpdateAllLinks() { - if (s_pDocLockedInsertingLinks || !m_pLinkManager || m_pLinkManager->GetLinks().empty()) + if (s_pDocLockedInsertingLinks || !m_pLinkManager) return; - s_pDocLockedInsertingLinks = this; // lock inserting links. only links in this document should by resolved + // Draw-layer fill bitmaps (shapes and slide/page backgrounds) are tracked + // per host by the model's sdr::FillBitmapLinkTracker as they are set. - if (mpDocSh) + // Register links for form controls with deferred remote ImageURL + ::sd::DrawDocShell* pDocShell = GetDocSh(); + if (pDocShell) { - comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = mpDocSh->getEmbeddedObjectContainer(); - rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true); + registerDeferredFormImageLinks(pDocShell->GetDeferredFormControlImages(), *m_pLinkManager); + pDocShell->ClearDeferredFormControlImages(); } - m_pLinkManager->UpdateAllLinks(true, false, nullptr, u""_ustr); // query box: update all links? + // Transition, animation-effect and click-action sounds that point outside + // the document package are links. Each is bound to what owns its URL - the + // transition sound to its page, the click-action sound to its shape, the + // animation-effect sound to its audio node - so allowing one marks that + // owner allowed. The transition and click-action sounds are registered as + // their URL is set. The animation-effect sound's source is set on its audio + // node by the ODF import, with no set-time hook here; the import reports one + // by setting the document's HasExternalAnimationSoundLink property, and only + // then is the animation tree of each slide walked to register it. Once any + // external sound link is present, warn through the link-update infobar until + // the document is allowed to update its links. + if (pDocShell) + { + if (mbMaybeHasAnimationSoundLinks) + { + for (sal_uInt16 nPage = 0, nCount = GetSdPageCount(PageKind::Standard); nPage < nCount; + ++nPage) + { + SdPage* pPage = GetSdPage(nPage, PageKind::Standard); + if (pPage) + RegisterAnimationSoundLinks(*pPage); + } + } + if (!pDocShell->getEmbeddedObjectContainer().getUserAllowsLinkUpdate() + && lcl_hasAnySoundLink(*m_pLinkManager)) + { + pDocShell->SetPendingLinkUpdateInfobar(); + } + } - if (s_pDocLockedInsertingLinks == this) - s_pDocLockedInsertingLinks = nullptr; // unlock inserting links + if (m_pLinkManager->GetLinks().empty()) + return; + + if (!pDocShell) + return; + + comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer + = pDocShell->getEmbeddedObjectContainer(); + + if (rEmbeddedObjectContainer.getUserAllowsLinkUpdate()) + { + s_pDocLockedInsertingLinks = this; + m_pLinkManager->UpdateAllLinks(false, u""_ustr); + if (s_pDocLockedInsertingLinks == this) + s_pDocLockedInsertingLinks = nullptr; + return; + } + + SfxMedium* pMedium = pDocShell->GetMedium(); + const SfxUInt16Item* pUpdateDocItem = pMedium + ? pMedium->GetItemSet().GetItem(SID_UPDATEDOCMODE, false) + : nullptr; + sal_uInt16 nUpdateDocMode = pUpdateDocItem + ? pUpdateDocItem->GetValue() + : css::document::UpdateDocMode::NO_UPDATE; + + if (nUpdateDocMode == css::document::UpdateDocMode::NO_UPDATE) + return; + + bool bAskUpdate = true; + switch (nUpdateDocMode) + { + case css::document::UpdateDocMode::QUIET_UPDATE: + bAskUpdate = false; + break; + case css::document::UpdateDocMode::FULL_UPDATE: + bAskUpdate = false; + break; + case css::document::UpdateDocMode::ACCORDING_TO_CONFIG: + bAskUpdate = !pMedium + || !SvtSecurityOptions::isTrustedLocationUriForUpdatingLinks( + pMedium->GetName()); + break; + } + + if (bAskUpdate) + { + rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false); + pDocShell->SetPendingLinkUpdateInfobar(); + } + else + { + rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true); + s_pDocLockedInsertingLinks = this; + m_pLinkManager->UpdateAllLinks(false, pMedium->GetName()); + if (s_pDocLockedInsertingLinks == this) + s_pDocLockedInsertingLinks = nullptr; + } +} + +IMPL_LINK_NOARG(SdDrawDocument, PlaceholderSwitchHdl, Timer*, void) +{ + SwitchPlaceholdersHoldingText(); +} + +void SdDrawDocument::ArmPlaceholderSwitch() +{ + if (!mpPlaceholderSwitchIdle) + { + mpPlaceholderSwitchIdle.reset(new Idle("PlaceholderSwitch")); + mpPlaceholderSwitchIdle->SetInvokeHandler( + LINK(this, SdDrawDocument, PlaceholderSwitchHdl)); + mpPlaceholderSwitchIdle->SetPriority(TaskPriority::LOWEST); + } + + mpPlaceholderSwitchIdle->Start(); +} + +void SdDrawDocument::SwitchPlaceholdersHoldingText() +{ + const BitmapChecksum nStandIn = SdPage::GetPlaceholderStandInChecksum(); + + for (sal_uInt16 nPage = 0; nPage < GetPageCount(); ++nPage) + { + SdPage* pPage = dynamic_cast(GetPage(nPage)); + if (!pPage) + continue; + + // Switching replaces the object on the page, so collect first and leave the walk alone. + std::vector aHoldingText; + sd::ShapeList& rPresObjs(pPage->GetPresentationShapeList()); + rPresObjs.seekShape(0); + while (SdrObject* pObj = rPresObjs.getNextShape()) + { + // An outliner object cannot hold a picture, so one that has both keeps the picture. One + // in text edit stays too: the view owns it until the edit ends, and that is where the + // switch happens for it. The pass walks every page, so the object being edited is not + // always the one that asked for the pass - another view may hold this one. + const SdrTextObj* pTextObj = DynCastSdrTextObj(pObj); + if (pTextObj && !pTextObj->IsTextEditActive() && !pObj->IsEmptyPresObj() + && pObj->HasText() && pPage->GetPresObjKind(pObj) == PresObjKind::Graphic + && SdPage::HoldsPlaceholderStandIn(*pObj, nStandIn)) + { + aHoldingText.push_back(pObj); + } + } + + for (SdrObject* pHoldsText : aHoldingText) + { + if (rtl::Reference xText = pPage->MakePresObjText(*pHoldsText)) + pPage->ReplaceObject(xText.get(), pHoldsText->GetOrdNum()); + } + } } /** this loops over the presentation objects of a page and repairs some new settings diff --git a/sd/source/core/drawdoc3.cxx b/sd/source/core/drawdoc3.cxx index ed141037ab70..c319561f74a1 100644 --- a/sd/source/core/drawdoc3.cxx +++ b/sd/source/core/drawdoc3.cxx @@ -35,11 +35,11 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -1337,6 +1337,13 @@ SdCustomShowList* SdDrawDocument::GetCustomShowList(bool bCreate) return mpCustomShowList.get(); } +sd::SlideSectionManager& SdDrawDocument::GetSectionManager() +{ + if (!mpSectionManager) + mpSectionManager.reset(new sd::SlideSectionManager(*this)); + return *mpSectionManager; +} + // Remove unused master pages and layouts void SdDrawDocument::RemoveUnnecessaryMasterPages(SdPage* pMasterPage, bool bOnlyDuplicatePages, bool bUndo) { @@ -2468,7 +2475,8 @@ bool SdDrawDocument::InsertFileAsPage( PageNameList *pExchangeList, bool bLink, sal_uInt16 nInsertPos, - ::sd::DrawDocShell* pBookmarkDocSh) + ::sd::DrawDocShell* pBookmarkDocSh, + std::optional oScaleObjects) { // Use predefined options for file insert operation InsertBookmarkOptions options = InsertBookmarkOptions::ForFileInsert(bLink); @@ -2495,8 +2503,15 @@ bool SdDrawDocument::InsertFileAsPage( getPageProperties(aInsertParams.mainProps, aInsertParams.notesProps, pageCounts.nDestPageCount); // Determine if objects need to be scaled - if (!determineScaleObjects(options.bNoDialogs, rBookmarkList, aInsertParams)) - return false; + if (oScaleObjects) + { + aInsertParams.bScaleObjects = *oScaleObjects; + } + else + { + if (!determineScaleObjects(options.bNoDialogs, rBookmarkList, aInsertParams)) + return false; + } // Get the necessary presentation stylesheets and transfer them before // the pages, else, the text objects won't reference their styles anymore. diff --git a/sd/source/core/pglink.cxx b/sd/source/core/pglink.cxx index 18e9b3c5b1e9..a472d2772a08 100644 --- a/sd/source/core/pglink.cxx +++ b/sd/source/core/pglink.cxx @@ -50,7 +50,7 @@ SdPageLink::~SdPageLink() /************************************************************************* |* -|* Date have changed +|* Data has changed |* \************************************************************************/ diff --git a/sd/source/core/sdpage.cxx b/sd/source/core/sdpage.cxx index 6248d045adfd..14e95ebbb97e 100644 --- a/sd/source/core/sdpage.cxx +++ b/sd/source/core/sdpage.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -303,33 +304,18 @@ SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, bool bVertical, const ::t case PresObjKind::Title: { pSdrObj = new SdrRectObj(getSdrModelFromSdrPage(), ::tools::Rectangle(), SdrObjKind::TitleText); - - if (mbMaster) - { - pSdrObj->SetNotVisibleAsMaster(true); - } } break; case PresObjKind::Outline: { pSdrObj = new SdrRectObj(getSdrModelFromSdrPage(), ::tools::Rectangle(), SdrObjKind::OutlineText); - - if (mbMaster) - { - pSdrObj->SetNotVisibleAsMaster(true); - } } break; case PresObjKind::Notes: { pSdrObj = new SdrRectObj(getSdrModelFromSdrPage(), ::tools::Rectangle(), SdrObjKind::Text); - - if (mbMaster) - { - pSdrObj->SetNotVisibleAsMaster(true); - } } break; @@ -464,6 +450,24 @@ SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, bool bVertical, const ::t if (pSdrObj) { + // On a master page these are templates for the instances the slides carry themselves, so + // painting them on a slide too would show two placeholders where the user expects one. + // Everything else stays visible from the master, the footer and slide number above all. + if (mbMaster) + { + switch (eObjKind) + { + case PresObjKind::Title: + case PresObjKind::Outline: + case PresObjKind::Notes: + case PresObjKind::Graphic: + pSdrObj->SetNotVisibleAsMaster(true); + break; + default: + break; + } + } + pSdrObj->SetEmptyPresObj(bEmptyPresObj); pSdrObj->SetLogicRect(rRect); @@ -1410,6 +1414,19 @@ void SdPage::SetCanvasPage() static_cast(getSdrModelFromSdrPage()).StoreCanvasPage(this); } +void SdPage::SetSoundFile(const OUString& rStr, bool bAllowed) +{ + // A fresh source takes the given allowed state; setting the same source + // again keeps the allowed state it already has. + if (maSoundLink.getURL() != rStr) + maSoundLink = SdSoundLink(rStr, bAllowed); + // A transition sound pointing outside the document package is a link the + // user allows on its own; register it as the URL is set so it joins link + // management. + if (maSoundLink.isExternalLink()) + static_cast(getSdrModelFromSdrPage()).RegisterPageSoundLink(*this); +} + static void CalcAutoLayoutRectangles( SdPage const & rPage,::tools::Rectangle* rRectangle ,const OUString& sLayoutType ) { ::tools::Rectangle aTitleRect; @@ -1450,7 +1467,7 @@ static void CalcAutoLayoutRectangles( SdPage const & rPage,::tools::Rectangle* r [&sLayoutType](const Reference& layoutNode) { Reference layoutAttrList = layoutNode->getAttributes(); - // get the attribute value of layout (i.e it's type) + // get the attribute value of layout (i.e its type) OUString sLayoutAttName = layoutAttrList->getNamedItem(u"type"_ustr)->getNodeValue(); return sLayoutAttName == sLayoutType; }); @@ -2232,7 +2249,7 @@ static rtl::Reference convertPresentationObjectImpl(SdPage& rPage, Sd } // Remove LRSpace item - SfxItemSetFixed aSet(rModel.GetPool()); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet(rModel.GetPool())); aSet.Put(pNewObj->GetMergedItemSet()); @@ -2266,7 +2283,7 @@ static rtl::Reference convertPresentationObjectImpl(SdPage& rPage, Sd pNewObj->SetEmptyPresObj(false); // reset left indent - SfxItemSetFixed aSet(rModel.GetPool()); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet(rModel.GetPool())); aSet.Put(pNewObj->GetMergedItemSet()); @@ -2465,6 +2482,154 @@ void SdPage::RemovePresObj(const SdrObject* pObj) } } +void SdPage::onEmptyPresObjFilled(SdrObject& rObj) +{ + // Text in a picture placeholder is represented by an outliner object, and this is where every + // way of putting it there passes. The switch itself waits: svx is working on the object right + // now, and replacing it under its feet is what freed the lines a paint was walking. + // + // An object in text edit is left alone entirely. This is called from inside that edit as well - + // when a view asks the shape for its text through UNO - and the object belongs to the editing + // view until the edit ends, which is where the switch happens for it. + const SdrTextObj* pTextObj = DynCastSdrTextObj(&rObj); + if (pTextObj && !pTextObj->IsTextEditActive() && GetPresObjKind(&rObj) == PresObjKind::Graphic + && rObj.HasText() && HoldsPlaceholderStandIn(rObj, GetPlaceholderStandInChecksum())) + { + static_cast(getSdrModelFromSdrPage()).ArmPlaceholderSwitch(); + } +} + +BitmapChecksum SdPage::GetPlaceholderStandInChecksum() +{ + // No file stores the art: what CreatePresObj would put there now is what to compare against. + return Bitmap(BMP_PRESOBJ_GRAPHIC).GetChecksum(); +} + +bool SdPage::HoldsPlaceholderStandIn(const SdrObject& rObj, BitmapChecksum nStandIn) +{ + const SdrGrafObj* pGraphic = dynamic_cast(&rObj); + if (!pGraphic) + return false; + + // Holding nothing counts too: the shape factory creates a placeholder without the art that + // CreatePresObj puts there. + const Graphic& rGraphic = pGraphic->GetGraphic(); + return rGraphic.IsNone() || rGraphic.GetChecksum() == nStandIn; +} + +rtl::Reference SdPage::MakePresObjText(SdrObject& rObj) +{ + const PresObjKind eKind = GetPresObjKind(&rObj); + + rtl::Reference xText = new SdrRectObj(getSdrModelFromSdrPage(), rObj.GetLogicRect(), + SdrObjKind::OutlineText); + xText->SetName(rObj.GetName()); + xText->SetTitle(rObj.GetTitle()); + xText->SetDescription(rObj.GetDescription()); + xText->SetUserCall(rObj.GetUserCall()); + + // An authored prompt belongs to the placeholder, so it has to be there when the text is gone. + xText->SetCustomPromptText(rObj.GetCustomPromptText()); + + // Text is what an outline placeholder holds, so its styles are the ones that fit. + xText->NbcSetStyleSheet(GetStyleSheetForPresObj(PresObjKind::Outline), true); + + // What the file authored on the shape belongs to the shape, whatever represents it. A contour + // frame and centred paragraphs do not: they arrange a prompt around an icon. + SfxItemSet aAuthored(getSdrModelFromSdrPage().GetItemPool(), + svl::Items); + aAuthored.Put(rObj.GetProperties().GetObjectItemSet()); + + // A text frame grows to its text, so without a minimum the box would stop matching the file. + aAuthored.Put(makeSdrTextMinFrameHeightItem(rObj.GetLogicRect().GetSize().Height())); + xText->SetMergedItemSet(aAuthored); + + if (const OutlinerParaObject* pPara = rObj.GetOutlinerParaObject()) + { + OutlinerParaObject aPara(*pPara); + aPara.SetOutlinerMode(OutlinerMode::OutlineObject); + + // The cached layout was measured in an object whose text area is arranged differently. + aPara.ClearPortionInfo(); + xText->SetOutlinerParaObject(std::move(aPara)); + } + + // Setting the text let the frame follow it, so the placeholder's rectangle has the last word, + // and the rectangle alone does not carry a rotated or sheared placeholder. + xText->NbcSetLogicRect(rObj.GetLogicRect()); + if (const SdrTextObj* pTextObj = DynCastSdrTextObj(&rObj)) + { + const GeoStat& rGeo = pTextObj->GetGeoStat(); + // Both turn the rectangle's own corner about the point they are given, and the rectangle + // is the one set above - so the corner stays where it is and only the angles arrive. The + // snap rect is the box around a turned shape, and its corner sits somewhere else. + const Point aPivot(rObj.GetLogicRect().TopLeft()); + if (rGeo.m_nShearAngle) + xText->NbcShear(aPivot, rGeo.m_nShearAngle, rGeo.mfTanShearAngle, false); + if (rGeo.m_nRotationAngle) + xText->NbcRotate(aPivot, rGeo.m_nRotationAngle, rGeo.mfSinRotationAngle, + rGeo.mfCosRotationAngle); + } + + // A click action, a sound or an animation effect is user data, so it needs its own copy here. + if (SdAnimationInfo* pInfo = SdDrawDocument::GetShapeUserData(rObj)) + { + xText->AppendUserData( + std::unique_ptr(new SdAnimationInfo(*pInfo, *xText))); + } + + InsertPresObj(xText.get(), eKind); + + return xText; +} + +rtl::Reference SdPage::MakePresObjPlaceholder(SdrObject& rObj) +{ + const PresObjKind eKind = GetPresObjKind(&rObj); + + // CreatePresObj records its insert whenever a list action is open, and the object leaves the + // page again below: an insert with no matching remove, which redo would perform a second time. + // The pair cancels out on the page, so the caller's replace is the only undoable step. + SfxUndoManager* pUndoManager + = static_cast(getSdrModelFromSdrPage()).GetUndoManager(); + const bool bUndoWasEnabled = pUndoManager && pUndoManager->IsUndoEnabled(); + if (bUndoWasEnabled) + pUndoManager->EnableUndo(false); + comphelper::ScopeGuard aUndoGuard([pUndoManager, bUndoWasEnabled] { + if (bUndoWasEnabled) + pUndoManager->EnableUndo(true); + }); + + // What stands for the placeholder while it waits: for a picture one, the icon and the prompt. + SdrObject* pPlaceholder = CreatePresObj(eKind, /*bVertical*/false, rObj.GetLogicRect(), + rObj.GetCustomPromptText()); + rtl::Reference xPlaceholder; + if (pPlaceholder) + { + pPlaceholder->SetUserCall(rObj.GetUserCall()); + pPlaceholder->SetName(rObj.GetName()); + pPlaceholder->SetTitle(rObj.GetTitle()); + pPlaceholder->SetDescription(rObj.GetDescription()); + + // What the file says about the picture - the outline it is clipped to, colour adjustments - + // belongs to the placeholder waiting for one, and travelled with the text meanwhile. + SfxItemSet aGraphic(getSdrModelFromSdrPage().GetItemPool(), + svl::Items); + aGraphic.Put(rObj.GetProperties().GetObjectItemSet()); + pPlaceholder->SetMergedItemSet(aGraphic); + + // Taking it out of the page drops it from the presentation shape list, which is where the + // identity lives, so it goes back in. + xPlaceholder = RemoveObject(pPlaceholder->GetOrdNum()); + InsertPresObj(xPlaceholder.get(), eKind); + } + + return xPlaceholder; +} + void SdPage::InsertPresObj(SdrObject* pObj, PresObjKind eKind ) { DBG_ASSERT( pObj, "sd::SdPage::InsertPresObj(), invalid presentation object inserted!" ); @@ -2711,14 +2876,24 @@ Orientation SdPage::GetOrientation() const OUString SdPage::GetPresObjText(PresObjKind eObjKind) const { + // A layout can author its own prompt, and it belongs to the slides using that layout, so ask + // the master for one before falling back to our own resource string. + if (!mbMaster && TRG_HasMasterPage()) + { + SdPage& rMasterPage = static_cast(TRG_GetMasterPage()); + if (SdrObject* pMasterObj = rMasterPage.GetPresObj(eObjKind)) + { + if (!pMasterObj->GetCustomPromptText().isEmpty()) + return pMasterObj->GetCustomPromptText(); + } + } + OUString aString; #if defined(IOS) || defined(ANDROID) - bool isMobileDevice = true; + const bool isMobileDevice = true; #else - bool isMobileDevice = false; - if (const SfxViewShell* pCurrentViewShell = SfxViewShell::Current()) - isMobileDevice = pCurrentViewShell->isLOKMobilePhone() || pCurrentViewShell->isLOKTablet(); + const bool isMobileDevice = false; #endif if (eObjKind == PresObjKind::Title) @@ -3004,7 +3179,8 @@ bool SdPage::RestoreDefaultText( SdrObject* pObj, const OUString& rStr ) if (ePresObjKind == PresObjKind::Title || ePresObjKind == PresObjKind::Outline || ePresObjKind == PresObjKind::Notes || - ePresObjKind == PresObjKind::Text) + ePresObjKind == PresObjKind::Text || + ePresObjKind == PresObjKind::Graphic) { sd::ModifyGuard aGuard(static_cast(&getSdrModelFromSdrPage())); @@ -3035,7 +3211,12 @@ bool SdPage::RestoreDefaultText( SdrObject* pObj, const OUString& rStr ) } pTextObj->SetTextEditOutliner( nullptr ); // to make stylesheet settings work - pTextObj->NbcSetStyleSheet( GetStyleSheetForPresObj(ePresObjKind), true ); + + // A kind with no style sheet of its own keeps the one it has: left with none, the + // object falls back to the pool defaults, which paint a solid fill. + if (SfxStyleSheet* pStyleSheet = GetStyleSheetForPresObj(ePresObjKind)) + pTextObj->NbcSetStyleSheet( pStyleSheet, true ); + pTextObj->SetEmptyPresObj(true); bRet = true; } diff --git a/sd/source/core/sdpage2.cxx b/sd/source/core/sdpage2.cxx index 08194915d4a0..7ded00458d2b 100644 --- a/sd/source/core/sdpage2.cxx +++ b/sd/source/core/sdpage2.cxx @@ -350,7 +350,7 @@ void SdPage::lateInit(const SdPage& rSrcPage) mbSoundOn = rSrcPage.mbSoundOn; mbExcluded = rSrcPage.mbExcluded; maLayoutName = rSrcPage.maLayoutName; - maSoundFile = rSrcPage.maSoundFile; + maSoundLink = rSrcPage.maSoundLink; mbLoopSound = rSrcPage.mbLoopSound; mbStopSound = rSrcPage.mbStopSound; maCreatedPageName.clear(); @@ -428,7 +428,7 @@ SfxStyleSheet* SdPage::GetTextStyleSheetForObject( SdrObject* pObj ) const SfxItemSet* SdPage::getOrCreateItems() { if( mpItems == nullptr ) - mpItems = std::make_unique>( getSdrModelFromSdrPage().GetItemPool()); + mpItems = std::make_unique(SfxItemSet::makeFixedSfxItemSet( getSdrModelFromSdrPage().GetItemPool())); return mpItems.get(); } @@ -515,7 +515,7 @@ bool SdPage::Equals(const SdPage& rOtherPage) const mbSoundOn != rOtherPage.mbSoundOn || mbExcluded != rOtherPage.mbExcluded || maLayoutName != rOtherPage.maLayoutName || - maSoundFile != rOtherPage.maSoundFile || + !maSoundLink.sameLink(rOtherPage.maSoundLink) || mbLoopSound != rOtherPage.mbLoopSound || mbStopSound != rOtherPage.mbStopSound || maBookmarkName != rOtherPage.maBookmarkName || diff --git a/sd/source/core/sdpage_animations.cxx b/sd/source/core/sdpage_animations.cxx index 81f9d2355078..3cf35bbd4f02 100644 --- a/sd/source/core/sdpage_animations.cxx +++ b/sd/source/core/sdpage_animations.cxx @@ -131,7 +131,17 @@ void SdPage::onParagraphRemoving( const ::Outliner* pOutliner, Paragraph const * * paragraphs at a shape are unlikely... */ aTarget.Paragraph = static_cast(pOutliner->GetAbsPos( pPara )); - getMainSequence()->disposeTextRange( Any( aTarget ) ); + // Whether the paragraph before the removed one is empty, read from the + // editing outliner that holds the live text. + bool bPreviousParagraphEmpty = false; + if( aTarget.Paragraph > 0 ) + { + Paragraph* pPrevPara = pOutliner->GetParagraph( aTarget.Paragraph - 1 ); + if( pPrevPara ) + bPreviousParagraphEmpty = pOutliner->GetText( pPrevPara ).isEmpty(); + } + + getMainSequence()->disposeTextRange( Any( aTarget ), bPreviousParagraphEmpty ); } } diff --git a/sd/source/core/stlfamily.cxx b/sd/source/core/stlfamily.cxx index 509a2106722a..0d0f6d75f756 100644 --- a/sd/source/core/stlfamily.cxx +++ b/sd/source/core/stlfamily.cxx @@ -50,11 +50,12 @@ typedef std::map< OUString, rtl::Reference< SdStyleSheet > > PresStyleMap; struct SdStyleFamilyImpl { + SfxStyleFamily mnFamily; + rtl::Reference< SfxStyleSheetPool > mxPool; unotools::WeakReference mxMasterPage; OUString maLayoutName; PresStyleMap& getStyleSheets(); - rtl::Reference< SfxStyleSheetPool > mxPool; private: PresStyleMap maStyleSheets; @@ -96,29 +97,29 @@ PresStyleMap& SdStyleFamilyImpl::getStyleSheets() return maStyleSheets; } -SdStyleFamily::SdStyleFamily( rtl::Reference< SfxStyleSheetPool > xPool, SfxStyleFamily nFamily ) -: mnFamily( nFamily ) -, mxPool(std::move( xPool )) +SdStyleFamily::SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, SfxStyleFamily nFamily ) +: mpImpl( new SdStyleFamilyImpl ) { + mpImpl->mnFamily = nFamily; + mpImpl->mxPool = xPool; } SdStyleFamily::SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, const SdPage* pMasterPage ) -: mnFamily( SfxStyleFamily::Page ) -, mxPool( xPool ) -, mpImpl( new SdStyleFamilyImpl ) +: mpImpl( new SdStyleFamilyImpl ) { - mpImpl->mxMasterPage = const_cast< SdPage* >( pMasterPage ); + mpImpl->mnFamily = SfxStyleFamily::Page; mpImpl->mxPool = xPool; + mpImpl->mxMasterPage = const_cast< SdPage* >( pMasterPage ); } SdStyleFamily::~SdStyleFamily() { - DBG_ASSERT( !mxPool.is(), "SdStyleFamily::~SdStyleFamily(), dispose me first!" ); + DBG_ASSERT( !mpImpl->mxPool.is(), "SdStyleFamily::~SdStyleFamily(), dispose me first!" ); } void SdStyleFamily::throwIfDisposed() const { - if( !mxPool.is() ) + if( !mpImpl->mxPool.is() ) throw DisposedException(); } @@ -127,7 +128,10 @@ SdStyleSheet* SdStyleFamily::GetValidNewSheet( const Any& rElement ) Reference< XStyle > xStyle( rElement, UNO_QUERY ); SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( xStyle.get() ); - if( pStyle == nullptr || (pStyle->GetFamily() != mnFamily) || (pStyle->GetPool() != mxPool.get()) || (mxPool->Find( pStyle->GetName(), mnFamily) != nullptr) ) + if( pStyle == nullptr + || (pStyle->GetFamily() != mpImpl->mnFamily) + || (pStyle->GetPool() != mpImpl->mxPool.get()) + || (mpImpl->mxPool->Find( pStyle->GetName(), mpImpl->mnFamily) != nullptr) ) throw IllegalArgumentException(); return pStyle; @@ -138,7 +142,7 @@ SdStyleSheet* SdStyleFamily::GetSheetByName( const OUString& rName ) SdStyleSheet* pRet = nullptr; if( !rName.isEmpty() ) { - if( mnFamily == SfxStyleFamily::Page ) + if( mpImpl->mnFamily == SfxStyleFamily::Page ) { PresStyleMap& rStyleMap = mpImpl->getStyleSheets(); PresStyleMap::iterator iter( rStyleMap.find(rName) ); @@ -147,7 +151,7 @@ SdStyleSheet* SdStyleFamily::GetSheetByName( const OUString& rName ) } else { - SfxStyleSheetIterator aSSSIterator(mxPool.get(), mnFamily); + SfxStyleSheetIterator aSSSIterator(mpImpl->mxPool.get(), mpImpl->mnFamily); for ( SfxStyleSheetBase* pStyle = aSSSIterator.First(); pStyle; pStyle = aSSSIterator.Next() ) { @@ -186,7 +190,7 @@ Sequence< OUString > SAL_CALL SdStyleFamily::getSupportedServiceNames() // XNamed OUString SAL_CALL SdStyleFamily::getName() { - if( mnFamily == SfxStyleFamily::Page ) + if( mpImpl->mnFamily == SfxStyleFamily::Page ) { rtl::Reference pPage = mpImpl->mxMasterPage.get(); if( pPage == nullptr ) @@ -200,7 +204,7 @@ OUString SAL_CALL SdStyleFamily::getName() } else { - return SdStyleSheet::GetFamilyString( mnFamily ); + return SdStyleSheet::GetFamilyString( mpImpl->mnFamily ); } } @@ -223,7 +227,7 @@ Sequence< OUString > SAL_CALL SdStyleFamily::getElementNames() throwIfDisposed(); - if( mnFamily == SfxStyleFamily::Page ) + if( mpImpl->mnFamily == SfxStyleFamily::Page ) { PresStyleMap& rStyleMap = mpImpl->getStyleSheets(); Sequence< OUString > aNames( rStyleMap.size() ); @@ -243,7 +247,7 @@ Sequence< OUString > SAL_CALL SdStyleFamily::getElementNames() else { std::vector< OUString > aNames; - SfxStyleSheetIterator aSSSIterator(mxPool.get(), mnFamily); + SfxStyleSheetIterator aSSSIterator(mpImpl->mxPool.get(), mpImpl->mnFamily); for ( SfxStyleSheetBase* pStyle = aSSSIterator.First(); pStyle; pStyle = aSSSIterator.Next() ) { @@ -262,7 +266,7 @@ sal_Bool SAL_CALL SdStyleFamily::hasByName( const OUString& aName ) if( !aName.isEmpty() ) { - if( mnFamily == SfxStyleFamily::Page ) + if( mpImpl->mnFamily == SfxStyleFamily::Page ) { PresStyleMap& rStyleSheets = mpImpl->getStyleSheets(); PresStyleMap::iterator iter( rStyleSheets.find(aName) ); @@ -270,7 +274,7 @@ sal_Bool SAL_CALL SdStyleFamily::hasByName( const OUString& aName ) } else { - SfxStyleSheetIterator aSSSIterator(mxPool.get(), mnFamily); + SfxStyleSheetIterator aSSSIterator(mpImpl->mxPool.get(), mpImpl->mnFamily); for ( SfxStyleSheetBase* pStyle = aSSSIterator.First(); pStyle; pStyle = aSSSIterator.Next() ) { @@ -299,13 +303,13 @@ sal_Bool SAL_CALL SdStyleFamily::hasElements() SolarMutexGuard aGuard; throwIfDisposed(); - if( mnFamily == SfxStyleFamily::Page ) + if( mpImpl->mnFamily == SfxStyleFamily::Page ) { return true; } else { - SfxStyleSheetIterator aSSSIterator(mxPool.get(), mnFamily); + SfxStyleSheetIterator aSSSIterator(mpImpl->mxPool.get(), mpImpl->mnFamily); if (aSSSIterator.First()) { return true; @@ -323,13 +327,13 @@ sal_Int32 SAL_CALL SdStyleFamily::getCount() throwIfDisposed(); sal_Int32 nCount = 0; - if( mnFamily == SfxStyleFamily::Page ) + if( mpImpl->mnFamily == SfxStyleFamily::Page ) { return mpImpl->getStyleSheets().size(); } else { - SfxStyleSheetIterator aSSSIterator(mxPool.get(), mnFamily); + SfxStyleSheetIterator aSSSIterator(mpImpl->mxPool.get(), mpImpl->mnFamily); for ( SfxStyleSheetBase* pStyle = aSSSIterator.First(); pStyle; pStyle = aSSSIterator.Next() ) { @@ -347,7 +351,7 @@ Any SAL_CALL SdStyleFamily::getByIndex( sal_Int32 Index ) if( Index >= 0 ) { - if( mnFamily == SfxStyleFamily::Page ) + if( mpImpl->mnFamily == SfxStyleFamily::Page ) { PresStyleMap& rStyleSheets = mpImpl->getStyleSheets(); if( Index < static_cast(rStyleSheets.size()) ) @@ -359,7 +363,7 @@ Any SAL_CALL SdStyleFamily::getByIndex( sal_Int32 Index ) } else { - SfxStyleSheetIterator aSSSIterator(mxPool.get(), mnFamily); + SfxStyleSheetIterator aSSSIterator(mpImpl->mxPool.get(), mpImpl->mnFamily); for ( SfxStyleSheetBase* pStyle = aSSSIterator.First(); pStyle; pStyle = aSSSIterator.Next() ) { @@ -391,7 +395,7 @@ void SAL_CALL SdStyleFamily::insertByName( const OUString& rName, const Any& rEl throw ElementExistException(); pStyle->SetApiName( rName ); - mxPool->Insert( pStyle ); + mpImpl->mxPool->Insert( pStyle ); } void SAL_CALL SdStyleFamily::removeByName( const OUString& rName ) @@ -404,7 +408,7 @@ void SAL_CALL SdStyleFamily::removeByName( const OUString& rName ) if( !pStyle->IsUserDefined() ) throw WrappedTargetException(); - mxPool->Remove( pStyle ); + mpImpl->mxPool->Remove( pStyle ); } // XNameReplace @@ -417,8 +421,8 @@ void SAL_CALL SdStyleFamily::replaceByName( const OUString& rName, const Any& aE SdStyleSheet* pOldStyle = GetSheetByName( rName ); SdStyleSheet* pNewStyle = GetValidNewSheet( aElement ); - mxPool->Remove( pOldStyle ); - mxPool->Insert( pNewStyle ); + mpImpl->mxPool->Remove( pOldStyle ); + mpImpl->mxPool->Insert( pNewStyle ); } // XSingleServiceFactory @@ -428,12 +432,12 @@ Reference< XInterface > SAL_CALL SdStyleFamily::createInstance() SolarMutexGuard aGuard; throwIfDisposed(); - if( mnFamily == SfxStyleFamily::Page ) + if( mpImpl->mnFamily == SfxStyleFamily::Page ) { throw IllegalAccessException(); } return Reference( - static_cast(SdStyleSheet::CreateEmptyUserStyle(*mxPool, mnFamily).get())); + static_cast(SdStyleSheet::CreateEmptyUserStyle(*mpImpl->mxPool, mpImpl->mnFamily).get())); } Reference< XInterface > SAL_CALL SdStyleFamily::createInstanceWithArguments( const Sequence< Any >& ) @@ -445,10 +449,8 @@ Reference< XInterface > SAL_CALL SdStyleFamily::createInstanceWithArguments( con void SAL_CALL SdStyleFamily::dispose( ) { - if( mxPool.is() ) - mxPool.clear(); - - mpImpl.reset(); + if( mpImpl->mxPool.is() ) + mpImpl->mxPool.clear(); } void SAL_CALL SdStyleFamily::addEventListener( const Reference< XEventListener >& ) @@ -481,7 +483,7 @@ Any SdStyleFamily::getPropertyValue( const OUString& PropertyName ) SolarMutexGuard aGuard; OUString sDisplayName; - switch( mnFamily ) + switch( mpImpl->mnFamily ) { case SfxStyleFamily::Page: sDisplayName = getName(); break; case SfxStyleFamily::Frame: sDisplayName = SdResId(STR_CELL_STYLE_FAMILY); break; diff --git a/sd/source/core/stlsheet.cxx b/sd/source/core/stlsheet.cxx index 2d87918335f1..4a0fa9002330 100644 --- a/sd/source/core/stlsheet.cxx +++ b/sd/source/core/stlsheet.cxx @@ -39,6 +39,9 @@ #include #include +#include +#include +#include #include #include #include @@ -1074,6 +1077,25 @@ void SdStyleSheet::setPropertyValue_Impl(const OUString& aPropertyName, const cs } rStyleSet.Put( aSet ); + + // Track a deferred remote fill bitmap landing on this style sheet, so a + // shared background (e.g. an Impress slide Background style) is registered + // per style as the item is set, the drawing-layer counterpart of the + // SwFormat::SetFormatAttr hook for Writer paragraph styles. + if (auto* pPool = dynamic_cast(GetPool())) + { + if (SdDrawDocument* pDoc = pPool->GetDoc()) + { + if (sdr::FillBitmapLinkTracker* pTracker = pDoc->GetFillBitmapLinkTracker()) + { + OUString aURL; + if (const XFillBitmapItem* pItem + = rStyleSet.GetItemIfSet(XATTR_FILLBITMAP, false)) + aURL = getDeferredOriginURL(*pItem); + pTracker->onFillBitmapURLChanged(*this, aURL); + } + } + } } // Must be guarded by solar mutex; must not be disposed diff --git a/sd/source/core/undoanim.cxx b/sd/source/core/undoanim.cxx index bc3c10f1abb4..df32d5d9dd53 100644 --- a/sd/source/core/undoanim.cxx +++ b/sd/source/core/undoanim.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -194,7 +195,7 @@ struct UndoTransitionImpl bool mbNewTransitionDirection; sal_Int32 mnNewTransitionFadeColor; double mfNewTransitionDuration; - OUString maNewSoundFile; + SdSoundLink maNewSoundLink; bool mbNewSoundOn; bool mbNewLoopSound; bool mbNewStopSound; @@ -204,7 +205,7 @@ struct UndoTransitionImpl bool mbOldTransitionDirection; sal_Int32 mnOldTransitionFadeColor; double mfOldTransitionDuration; - OUString maOldSoundFile; + SdSoundLink maOldSoundLink; bool mbOldSoundOn; bool mbOldLoopSound; bool mbOldStopSound; @@ -221,7 +222,7 @@ UndoTransition::UndoTransition( SdDrawDocument& rDoc, SdPage* pThePage ) mpImpl->mbOldTransitionDirection = pThePage->mbTransitionDirection; mpImpl->mnOldTransitionFadeColor = pThePage->mnTransitionFadeColor; mpImpl->mfOldTransitionDuration = pThePage->mfTransitionDuration; - mpImpl->maOldSoundFile = pThePage->maSoundFile; + mpImpl->maOldSoundLink = pThePage->GetSoundLink(); mpImpl->mbOldSoundOn = pThePage->mbSoundOn; mpImpl->mbOldLoopSound = pThePage->mbLoopSound; mpImpl->mbOldStopSound = pThePage->mbStopSound; @@ -240,7 +241,7 @@ void UndoTransition::Undo() mpImpl->mbNewTransitionDirection = mpImpl->mpPage->mbTransitionDirection; mpImpl->mnNewTransitionFadeColor = mpImpl->mpPage->mnTransitionFadeColor; mpImpl->mfNewTransitionDuration = mpImpl->mpPage->mfTransitionDuration; - mpImpl->maNewSoundFile = mpImpl->mpPage->maSoundFile; + mpImpl->maNewSoundLink = mpImpl->mpPage->GetSoundLink(); mpImpl->mbNewSoundOn = mpImpl->mpPage->mbSoundOn; mpImpl->mbNewLoopSound = mpImpl->mpPage->mbLoopSound; mpImpl->mbNewStopSound = mpImpl->mpPage->mbStopSound; @@ -251,7 +252,8 @@ void UndoTransition::Undo() mpImpl->mpPage->mbTransitionDirection = mpImpl->mbOldTransitionDirection; mpImpl->mpPage->mnTransitionFadeColor = mpImpl->mnOldTransitionFadeColor; mpImpl->mpPage->mfTransitionDuration = mpImpl->mfOldTransitionDuration; - mpImpl->mpPage->maSoundFile = mpImpl->maOldSoundFile; + mpImpl->mpPage->SetSoundFile(mpImpl->maOldSoundLink.getURL()); + mpImpl->mpPage->SetSoundAllowed(mpImpl->maOldSoundLink.isAllowed()); mpImpl->mpPage->mbSoundOn = mpImpl->mbOldSoundOn; mpImpl->mpPage->mbLoopSound = mpImpl->mbOldLoopSound; mpImpl->mpPage->mbStopSound = mpImpl->mbOldStopSound; @@ -264,7 +266,8 @@ void UndoTransition::Redo() mpImpl->mpPage->mbTransitionDirection = mpImpl->mbNewTransitionDirection; mpImpl->mpPage->mnTransitionFadeColor = mpImpl->mnNewTransitionFadeColor; mpImpl->mpPage->mfTransitionDuration = mpImpl->mfNewTransitionDuration; - mpImpl->mpPage->maSoundFile = mpImpl->maNewSoundFile; + mpImpl->mpPage->SetSoundFile(mpImpl->maNewSoundLink.getURL()); + mpImpl->mpPage->SetSoundAllowed(mpImpl->maNewSoundLink.isAllowed()); mpImpl->mpPage->mbSoundOn = mpImpl->mbNewSoundOn; mpImpl->mpPage->mbLoopSound = mpImpl->mbNewLoopSound; mpImpl->mpPage->mbStopSound = mpImpl->mbNewStopSound; diff --git a/sd/source/filter/eppt/eppt.cxx b/sd/source/filter/eppt/eppt.cxx index 43f7b6247c3c..1f76373b5ad7 100644 --- a/sd/source/filter/eppt/eppt.cxx +++ b/sd/source/filter/eppt/eppt.cxx @@ -56,6 +56,8 @@ #include #include #include +#include +#include class SfxObjectShell; // complete SfxObjectShell for SaveVBA under -fsanitize=function @@ -123,6 +125,7 @@ void PPTWriter::exportPPTPre( const std::vector< css::beans::PropertyValue >& rM [](const css::beans::PropertyValue& rProp) { return rProp.Name == "BaseURI"; }); if (aIter != rMediaData.end()) (*aIter).Value >>= maBaseURI; + maSoundCollection.SetReferer(maBaseURI); mpPptEscherEx.reset( new PptEscherEx( *mpStrm, maBaseURI ) ); } @@ -200,10 +203,23 @@ void PPTWriter::ImplWriteSlide( sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_ if ( GetPropertyValue( aAny, mXPagePropSet, u"Sound"_ustr ) ) { + css::uno::Reference xSound; OUString aSoundURL; - if ( aAny >>= aSoundURL ) + if ( aAny >>= xSound ) { - nSoundRef = maSoundCollection.GetId( aSoundURL ); + if ( xSound.is() ) + { + nSoundRef = maSoundCollection.GetId( + SdSoundLink(xSound->getURL(), xSound->getAllowed()) ); + bIsSound = true; + } + } + else if ( aAny >>= aSoundURL ) + { + // a silent slide reports an empty sound string here; emit the + // slide-info record anyway, since it also carries the transition + // speed. A bare string carries no allow decision, so deny it. + nSoundRef = maSoundCollection.GetId( SdSoundLink(aSoundURL, false) ); bIsSound = true; } else diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx index d1b3ec72f833..688b4e5cfeb8 100644 --- a/sd/source/filter/eppt/epptooxml.hxx +++ b/sd/source/filter/eppt/epptooxml.hxx @@ -51,7 +51,9 @@ enum PlaceholderType DateAndTime, Outliner, Title, - Subtitle + Subtitle, + Picture, + Media }; class PowerPointShapeExport; @@ -94,6 +96,7 @@ private: void ImplWritePPTXLayoutWithContent( sal_Int32 nOffset, sal_uInt32 nMasterNum, const OUString& aSlideName, css::uno::Reference const& aXBackgroundPropSet); + void WriteLayoutClrMapOvr(const ::sax_fastparser::FSHelperPtr& pFS, sal_uInt32 nMasterNum); static void WriteDefaultColorSchemes(const FSHelperPtr& pFS); void WriteTheme( sal_Int32 nThemeNum, const model::Theme* pTheme ); @@ -109,7 +112,8 @@ private: sal_Int32 GetLayoutFileId( sal_Int32 nOffset, sal_uInt32 nMasterNum ); // shapes - void WriteShapeTree( const ::sax_fastparser::FSHelperPtr& pFS, PageType ePageType, bool bMaster ); + void WriteShapeTree( const ::sax_fastparser::FSHelperPtr& pFS, PageType ePageType, bool bMaster, + bool bSlideMasterPart = false, sal_uInt32 nMasterNum = 0 ); sal_uInt32 GetNewSlideId() { return mnSlideIdMax ++; } sal_uInt32 GetNewSlideMasterId() { return mnSlideMasterIdMax ++; } @@ -119,22 +123,38 @@ private: void writeDocumentProperties(); void WriteCustomSlideShow(); + void WriteSections(); void AddLayoutIdAndRelation( const ::sax_fastparser::FSHelperPtr& pFS, sal_Int32 nLayoutFileId ); virtual OUString SAL_CALL getImplementationName() override; - /** Create a new placeholder index for a master placeholder shape + /** The placeholder index of a master placeholder shape, allocating one on first use @param rXShape Master placeholder shape @returns Placeholder index */ - sal_Int32 CreateNewPlaceholderIndex(const css::uno::Reference& rXShape); + sal_Int32 GetOrCreatePlaceholderIndex(const css::uno::Reference& rXShape); css::uno::Reference GetReferencedPlaceholderXShape(const PlaceholderType eType, PageType ePageType) const; void WritePlaceholderReferenceShapes(PowerPointShapeExport& rDML, PageType ePageType); + /** Writes the master page's content placeholders into the layout they belong on */ + void WriteLayoutContentPlaceholders(PowerPointShapeExport& rDML); + /** Writes the placeholders a slide master holds that the page standing for it has none of */ + void WriteMasterOwnPlaceholders(PowerPointShapeExport& rDML, sal_uInt32 nMasterNum); void FindEquivalentMasterPages(); sal_uInt32 GetEquivalentMasterPage(sal_uInt32 nMasterPage); + /** How many of a page's leading shapes belong to the slide master of its group + + A PPTX master and one of its layouts collapse onto one Impress master page, so for an + imported deck the leading shapes every page of a group shares are the ones from the master + they share. An ODF deck has no such master, and moving them is then a choice: it paints + the same, and the slide master holds the shape once for all its layouts. + + @param nMasterPage Any master page, in a group or not + @returns How many leading shapes the group's slide master owns, 0 for a page in no group + */ + size_t GetMasterOwnShapeCount(sal_uInt32 nMasterPage); /// Should we export as .pptm, ie. do we contain macros? bool mbPptm; @@ -142,6 +162,9 @@ private: // Export as a template bool mbExportTemplate; + // Export as a slideshow (PPSX/PPSM) + bool mbSlideShow; + ::sax_fastparser::FSHelperPtr mPresentationFS; LayoutInfo mLayoutInfo[AUTOLAYOUT_END]; @@ -149,6 +172,9 @@ private: std::vector> maMastersLayouts; // For each Impress master, which master will represent it on the exported file (SAL_MAX_UINT32 if not in an equivalency group) std::vector maEquivalentMasters; + // How many shapes a slide master owns, per equivalency group; every master in no group + // shares the SAL_MAX_UINT32 entry. See GetMasterOwnShapeCount + std::unordered_map maMasterOwnShapeCounts; std::unique_ptr mpAuthorIDs; // map authors to remove personal info std::vector< ::sax_fastparser::FSHelperPtr > mpSlidesFSArray; sal_Int32 mnLayoutFileIdMax; @@ -161,6 +187,7 @@ private: sal_Int32 mnDiagramId; std::vector maRelId; + std::vector maSlideIdsInOrder; bool mbCreateNotes; diff --git a/sd/source/filter/eppt/epptso.cxx b/sd/source/filter/eppt/epptso.cxx index ed3d5b8e9827..25d7fe2ae18f 100644 --- a/sd/source/filter/eppt/epptso.cxx +++ b/sd/source/filter/eppt/epptso.cxx @@ -25,6 +25,9 @@ #include "eppt.hxx" #include "text.hxx" #include "epptdef.hxx" +#include +#include +#include #include "escherex.hxx" #include #include @@ -1402,8 +1405,14 @@ void PPTWriter::ImplWriteClickAction( SvStream& rSt, css::presentation::ClickAct break; case css::presentation::ClickAction_SOUND : { - if ( ImplGetPropertyValue( u"Bookmark"_ustr ) ) - nSoundRef = maSoundCollection.GetId( *o3tl::doAccess(mAny) ); + // The allowed bit lives on the shape's SdAnimationInfo, not on a + // property, so read the click sound from the model to get its URL + // and allowed state together. + css::uno::Reference xShape(mXPropSet, css::uno::UNO_QUERY); + SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape); + if ( SdAnimationInfo* pInfo = pObj ? SdDrawDocument::GetShapeUserData(*pObj) : nullptr ) + nSoundRef = maSoundCollection.GetId( + SdSoundLink(pInfo->GetBookmark(), pInfo->mbClickSoundAllowed) ); } break; case css::presentation::ClickAction_PROGRAM : diff --git a/sd/source/filter/eppt/pptexanimations.cxx b/sd/source/filter/eppt/pptexanimations.cxx index a3b95012c847..8efedba53548 100644 --- a/sd/source/filter/eppt/pptexanimations.cxx +++ b/sd/source/filter/eppt/pptexanimations.cxx @@ -54,6 +54,8 @@ #include #include "pptexanimations.hxx" #include "pptexsoundcollection.hxx" +#include +#include #include "../ppt/pptanimations.hxx" #include #include @@ -640,11 +642,12 @@ void AnimationExporter::exportNode( SvStream& rStrm, Reference< XAnimationNode > Reference< XAudio > xAudio( xNode, UNO_QUERY ); if( xAudio.is() ) { - Any aAny( xAudio->getSource() ); - OUString aURL; + Reference< css::presentation::XSoundReference > xSound; + xAudio->getSource() >>= xSound; - if ( ( aAny >>= aURL) && !aURL.isEmpty() ) + if ( xSound.is() && !xSound->getURL().isEmpty() ) { + SdSoundLink aSound( xSound->getURL(), xSound->getAllowed() ); sal_Int32 nU1 = 2; sal_Int32 nTrigger = 3; sal_Int32 nU3 = nAudioGroup; @@ -670,7 +673,7 @@ void AnimationExporter::exportNode( SvStream& rStrm, Reference< XAnimationNode > { sal_uInt32 const nRefMode = 3; sal_uInt32 const nRefType = 2; - sal_uInt32 nRefId = mrExSoundCollection.GetId( aURL ); + sal_uInt32 nRefId = mrExSoundCollection.GetId( aSound ); sal_Int32 const begin = -1; sal_Int32 const end = -1; diff --git a/sd/source/filter/eppt/pptexsoundcollection.cxx b/sd/source/filter/eppt/pptexsoundcollection.cxx index 2fc96bf2f025..5ba3f1702e84 100644 --- a/sd/source/filter/eppt/pptexsoundcollection.cxx +++ b/sd/source/filter/eppt/pptexsoundcollection.cxx @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #include namespace ppt @@ -154,20 +156,24 @@ void ExSoundEntry::Write( SvStream& rSt, sal_uInt32 nId ) const } } -sal_uInt32 ExSoundCollection::GetId(const OUString& rString) +sal_uInt32 ExSoundCollection::GetId(const SdSoundLink& rSound) { sal_uInt32 nSoundId = 0; - if (!rString.isEmpty()) + const OUString& rURL = rSound.getURL(); + if (!rSound.isEmpty() + && !SvtSecurityOptions::isUntrustedReferer(maReferer) + && !INetURLObject(rURL).IsExoticProtocol() + && rSound.isAllowed()) { const sal_uInt32 nSoundCount = maEntries.size(); auto iter = std::find_if(maEntries.begin(), maEntries.end(), - [&rString](const ExSoundEntry& rEntry) { return rEntry.IsSameURL(rString); }); + [&rURL](const ExSoundEntry& rEntry) { return rEntry.IsSameURL(rURL); }); nSoundId = static_cast(std::distance(maEntries.begin(), iter)); if ( nSoundId++ == nSoundCount ) { - ExSoundEntry aEntry( rString ); + ExSoundEntry aEntry( rURL ); if ( aEntry.GetFileSize() ) maEntries.push_back(aEntry); else diff --git a/sd/source/filter/eppt/pptexsoundcollection.hxx b/sd/source/filter/eppt/pptexsoundcollection.hxx index 5a45464298d0..f5e4ebcdbe0f 100644 --- a/sd/source/filter/eppt/pptexsoundcollection.hxx +++ b/sd/source/filter/eppt/pptexsoundcollection.hxx @@ -27,6 +27,7 @@ #include class SvStream; +class SdSoundLink; namespace ppt { @@ -55,7 +56,8 @@ class ExSoundCollection { public: - sal_uInt32 GetId(const OUString&); + void SetReferer(const OUString& rReferer) { maReferer = rReferer; } + sal_uInt32 GetId(const SdSoundLink&); /// @return size of a complete SoundCollectionContainer. sal_uInt32 GetSize() const; @@ -64,6 +66,7 @@ class ExSoundCollection private: std::vector maEntries; + OUString maReferer; }; } // namespace ppt diff --git a/sd/source/filter/eppt/pptx-animations-nodectx.cxx b/sd/source/filter/eppt/pptx-animations-nodectx.cxx index 2744cac56480..1d14fc9be999 100644 --- a/sd/source/filter/eppt/pptx-animations-nodectx.cxx +++ b/sd/source/filter/eppt/pptx-animations-nodectx.cxx @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -178,7 +179,8 @@ void NodeContext::initValid(bool bHasValidChild, bool bIsIterateChild) mbValid = false; if (xAudio.is()) { - if (xAudio->getSource() >>= sURL) + sURL = xmloff::getSoundURL(xAudio->getSource()); + if (!sURL.isEmpty()) { mbValid = IsAudioURL(sURL); diff --git a/sd/source/filter/eppt/pptx-animations.cxx b/sd/source/filter/eppt/pptx-animations.cxx index da6a0f5de0b9..b5e95cfae628 100644 --- a/sd/source/filter/eppt/pptx-animations.cxx +++ b/sd/source/filter/eppt/pptx-animations.cxx @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -1085,7 +1086,8 @@ void PPTXAnimationExport::WriteAnimationNodeMedia(const sal_Int16 nParentNodeTyp } bool bValid = false; - if ((xAudio->getSource() >>= sUrl) && !sUrl.isEmpty() && IsAudioURL(sUrl)) + sUrl = xmloff::getSoundURL(xAudio->getSource()); + if (!sUrl.isEmpty() && IsAudioURL(sUrl)) { bValid = true; } @@ -1109,7 +1111,7 @@ void PPTXAnimationExport::WriteAnimationNodeMedia(const sal_Int16 nParentNodeTyp if (!bValid) return; - if (!xShape.is()) + if (!xShape.is() && xmloff::getSoundAllowed(xAudio->getSource())) { mrPowerPointExport.embedEffectAudio(mpFS, sUrl, sRelId, sName); } diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx index 7bac79eb8b82..9843f5ed8785 100644 --- a/sd/source/filter/eppt/pptx-epptooxml.cxx +++ b/sd/source/filter/eppt/pptx-epptooxml.cxx @@ -33,10 +33,15 @@ #include #include #include +#include #include #include #include +#include +#include +#include +#include #include #include #include @@ -70,6 +75,7 @@ #include #include #include +#include #include #include #include @@ -84,7 +90,12 @@ #include #include +#include +#include +#include +#include #include +#include #include #include #include @@ -100,6 +111,8 @@ #include #include +#include +#include #include #include #include @@ -164,13 +177,17 @@ class PowerPointShapeExport : public ShapeExport PowerPointExport& mrExport; PageType mePageType; bool mbMaster; + /// True while writing a slideMaster part; a slideLayout part also uses PageType::MASTER. + bool mbSlideMasterPart = false; public: PowerPointShapeExport(FSHelperPtr pFS, ShapeHashMap* pShapeMap, PowerPointExport* pFB); void SetMaster(bool bMaster); void SetPageType(PageType ePageType); + void SetSlideMasterPart(bool bSlideMasterPart) { mbSlideMasterPart = bSlideMasterPart; } ShapeExport& WriteNonVisualProperties(const Reference< XShape >& xShape) override; ShapeExport& WriteTextShape(const Reference< XShape >& xShape) override; ShapeExport& WriteUnknownShape(const Reference< XShape >& xShape) override; + ShapeExport& WriteGraphicObjectShape(const Reference< XShape >& xShape) override; ShapeExport& WritePlaceholderShape(const Reference< XShape >& xShape, PlaceholderType ePlaceholder); /** Writes a placeholder shape that references the placeholder on the master slide */ ShapeExport& WritePlaceholderReferenceShape(PlaceholderType ePlaceholder, sal_Int32 nReferencedPlaceholderIdx, PageType ePageType, const Reference& rXPagePropSet); @@ -196,6 +213,243 @@ void WriteSndAc(const FSHelperPtr& pFS, const OUString& sSoundRelId, const OUStr pFS->endElement(FSNS(XML_p, XML_sndAc)); } +// Holds a graphic or media object rather than text, and so reaches the export through +// ShapeExport::WriteGraphicObjectShape. +bool isGraphicPlaceholder(PlaceholderType ePlaceholder) +{ + return ePlaceholder == Picture || ePlaceholder == Media; +} + +// The placeholder kind a graphic-object shape stands for, or None when it is not a placeholder. +PlaceholderType getGraphicPlaceholderType(std::u16string_view aShapeType) +{ + if (aShapeType == u"com.sun.star.presentation.GraphicObjectShape") + return Picture; + if (aShapeType == u"com.sun.star.presentation.MediaShape") + return Media; + return None; +} + +// Whether the placeholder is still waiting for its content. A media one is never marked empty: +// SdGenericDrawPage::CreateSdrObject_ builds it without SdPage::CreatePresObj, which is what sets +// that flag, so ask the media itself. +bool isPlaceholderStillEmpty(const Reference& xProps, PlaceholderType ePlaceholder) +{ + if (!xProps) + return false; + + if (xProps->getPropertyValue(u"IsEmptyPresentationObject"_ustr) == true) + return true; + + if (ePlaceholder != Media) + return false; + + OUString aMediaURL; + return xProps->getPropertySetInfo()->hasPropertyByName(u"MediaURL"_ustr) + && (xProps->getPropertyValue(u"MediaURL"_ustr) >>= aMediaURL) && aMediaURL.isEmpty(); +} + +// The nth shape of a page, if it and all below it are non-placeholders. A placeholder stops the +// count, because master shapes paint below layout shapes and it stays on the layout. +// IsPresObj is wider than the write side's mbPresObj, so the run can only stop earlier. +const SdrObject* getLeadingShape(SdPage& rPage, size_t nIndex) +{ + if (nIndex >= rPage.GetObjCount()) + return nullptr; + for (size_t nObj = 0; nObj <= nIndex; ++nObj) + { + SdrObject* pObj = rPage.GetObj(nObj); + if (!pObj || rPage.IsPresObj(pObj)) + return nullptr; + } + return rPage.GetObj(nIndex); +} + +// The same place, within the slack that a page's own text layout can move a frame by +bool isSameRect(const tools::Rectangle& rRect, const tools::Rectangle& rOther) +{ + constexpr tools::Long nSlack = 10; // 10/100 mm + return std::abs(rRect.Left() - rOther.Left()) <= nSlack + && std::abs(rRect.Top() - rOther.Top()) <= nSlack + && std::abs(rRect.Right() - rOther.Right()) <= nSlack + && std::abs(rRect.Bottom() - rOther.Bottom()) <= nSlack; +} + +// Whether these are the same shape as far as a slide shows. Two copies have in common what the +// document set for them; each page also carries values it recalculated for itself, which is why +// SdrObject::Equals is no use here - it reads the cached m_nOrdNum and mnNavigationPosition - and +// why the geometry gets a slack. What the export writes from outside the item set is compared +// below, one kind at a time; a kind that cannot be compared in full is never the same. +bool isSameShape(const SdrObject& rShape, const SdrObject& rOther) +{ + if (rShape.GetObjInventor() != rOther.GetObjInventor() + || rShape.GetObjIdentifier() != rOther.GetObjIdentifier() + || rShape.GetRotateAngle() != rOther.GetRotateAngle() + || rShape.GetShearAngle() != rOther.GetShearAngle() + || rShape.GetLayer() != rOther.GetLayer() || rShape.IsVisible() != rOther.IsVisible() + || rShape.IsPrintable() != rOther.IsPrintable() || rShape.GetName() != rOther.GetName() + || rShape.GetTitle() != rOther.GetTitle() + || rShape.GetDescription() != rOther.GetDescription()) + return false; + + // Both rectangles: getPosition and getSize use the logic rect for most kinds and the snap + // rect for a group or a path, and rotation makes the two differ. + if (!isSameRect(rShape.GetSnapRect(), rOther.GetSnapRect()) + || !isSameRect(rShape.GetLogicRect(), rOther.GetLogicRect())) + return false; + + // Not items: the style sheet, which the item comparison below does not resolve through, and + // the decorative flag, written as an extLst + if (rShape.GetStyleSheet() != rOther.GetStyleSheet() + || rShape.IsDecorative() != rOther.IsDecorative()) + return false; + + // Also not an item: the grab bag holds the effect list, p:style, 3D and theme colours + uno::Any aGrabBag; + uno::Any aOtherGrabBag; + rShape.GetGrabBagItem(aGrabBag); + rOther.GetGrabBagItem(aOtherGrabBag); + if (aGrabBag != aOtherGrabBag) + return false; + + // A click action or bookmark lives in the shape's user data, so refuse a shape that has one + if (SdDrawDocument::GetShapeUserData(const_cast(rShape)) + || SdDrawDocument::GetShapeUserData(const_cast(rOther))) + return false; + + const OutlinerParaObject* pText = rShape.GetOutlinerParaObject(); + const OutlinerParaObject* pOtherText = rOther.GetOutlinerParaObject(); + if (bool(pText) != bool(pOtherText)) + return false; + // operator==, not EditTextObject::Equals: it also compares the outline depth, exported as + // a:pPr/@lvl. + if (pText && *pText != *pOtherText) + return false; + + switch (rShape.GetObjIdentifier()) + { + case SdrObjKind::Group: + { + // GetObjectItemSet() can't be used with groups, so compare the members instead + // A diagram group exports as a graphicFrame with parts of its own, none compared here + if (rShape.getDiagramHelper() || rOther.getDiagramHelper()) + return false; + const SdrObjList* pMembers = rShape.GetSubList(); + const SdrObjList* pOtherMembers = rOther.GetSubList(); + if (!pMembers || !pOtherMembers + || pMembers->GetObjCount() != pOtherMembers->GetObjCount()) + return false; + for (size_t nObj = 0; nObj < pMembers->GetObjCount(); ++nObj) + { + const SdrObject* pMember = pMembers->GetObj(nObj); + const SdrObject* pOtherMember = pOtherMembers->GetObj(nObj); + if (!pMember || !pOtherMember || !isSameShape(*pMember, *pOtherMember)) + return false; + } + return true; + } + case SdrObjKind::Graphic: + { + // The graphic and the mirror flag are not items. Compare by checksum, not by + // Graphic::operator==, which uses whatever is decoded at the time; the checksum reads + // the imported bytes, and 0 means there was nothing to read. + const auto* pGraphic = dynamic_cast(&rShape); + const auto* pOtherGraphic = dynamic_cast(&rOther); + if (!pGraphic || !pOtherGraphic + || pGraphic->IsMirrored() != pOtherGraphic->IsMirrored()) + return false; + const auto nChecksum = pGraphic->GetGraphicObject().GetGraphic().GetChecksum(); + if (nChecksum == 0 + || nChecksum != pOtherGraphic->GetGraphicObject().GetGraphic().GetChecksum()) + return false; + break; + } + case SdrObjKind::Line: + case SdrObjKind::Polygon: + case SdrObjKind::PolyLine: + case SdrObjKind::PathLine: + case SdrObjKind::PathFill: + case SdrObjKind::FreehandLine: + case SdrObjKind::FreehandFill: + case SdrObjKind::PathPoly: + case SdrObjKind::PathPolyLine: + { + // The polygon is not an item + const auto* pPath = dynamic_cast(&rShape); + const auto* pOtherPath = dynamic_cast(&rOther); + if (!pPath || !pOtherPath || pPath->GetPathPoly() != pOtherPath->GetPathPoly()) + return false; + break; + } + case SdrObjKind::Rectangle: + case SdrObjKind::CircleOrEllipse: + case SdrObjKind::CircleSection: + case SdrObjKind::CircleArc: + case SdrObjKind::CircleCut: + case SdrObjKind::Text: + case SdrObjKind::TitleText: + case SdrObjKind::OutlineText: + case SdrObjKind::CustomShape: + break; // the attributes and the text are all of it + default: + // A table, OLE frame, media object, connector, callout or 3D scene: not compared + // here, so it stays on its layout + return false; + } + + if (!rShape.GetProperties().GetObjectItemSet().Equals(rOther.GetProperties().GetObjectItemSet(), + false)) + return false; + + // Autofit sets the font and spacing scale at layout time and the export writes them. Last, + // because reading a scale lays the text out, and the item sets already agree by here. + if (rShape.GetMergedItem(SDRATTR_TEXT_FITTOSIZE).GetValue() + != drawing::TextFitToSizeType_AUTOFIT) + return true; + const SdrTextObj* pTextShape = DynCastSdrTextObj(&rShape); + const SdrTextObj* pOtherTextShape = DynCastSdrTextObj(&rOther); + return !pTextShape || !pOtherTextShape + || (pTextShape->GetFontScale() == pOtherTextShape->GetFontScale() + && pTextShape->GetSpacingScale() == pOtherTextShape->GetSpacingScale()); +} + +// The page knows what a shape is a placeholder for; its class only says what represents it. +PlaceholderType getPresObjPlaceholderType(const Reference& xShape) +{ + SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape); + SdPage* pPage = pObj ? dynamic_cast(pObj->getSdrPageFromSdrObject()) : nullptr; + if (!pPage) + return None; + + switch (pPage->GetPresObjKind(pObj)) + { + case PresObjKind::Graphic: + return Picture; + case PresObjKind::Media: + return Media; + default: + return None; + } +} + +// A slide master takes only these; PowerPoint refuses to open a file whose master carries any +// other placeholder type, content ones like pic included. +bool isPlaceholderAllowedOnSlideMaster(PlaceholderType ePlaceholder) +{ + switch (ePlaceholder) + { + case Title: + case Outliner: + case Notes: + case DateAndTime: + case Footer: + case SlideNumber: + return true; + default: + return false; + } +} + const char* getPlaceholderTypeName(PlaceholderType ePlaceholder) { switch (ePlaceholder) @@ -218,6 +472,10 @@ const char* getPlaceholderTypeName(PlaceholderType ePlaceholder) return "title"; case Subtitle: return "subTitle"; + case Picture: + return "pic"; + case Media: + return "media"; default: SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder); return ""; @@ -341,9 +599,14 @@ ShapeExport& PowerPointShapeExport::WriteTextShape(const Reference< XShape >& xS else ShapeExport::WriteTextShape(xShape); } - else if (sShapeType == "com.sun.star.presentation.OutlinerShape") + else if (sShapeType == "com.sun.star.presentation.OutlinerShape" + || sShapeType == "com.sun.star.presentation.GraphicObjectShape" + || sShapeType == "com.sun.star.presentation.MediaShape") { - if (!WritePlaceholder(xShape, Outliner, mbMaster)) + // Written as the placeholder it is, with the text it holds: a body one would cost it its + // identity, and a picture with no image is written as nothing at all. + const PlaceholderType eStandsFor = getPresObjPlaceholderType(xShape); + if (!WritePlaceholder(xShape, eStandsFor != None ? eStandsFor : Outliner, mbMaster)) ShapeExport::WriteTextShape(xShape); } else if (sShapeType == "com.sun.star.presentation.SlideNumberShape") @@ -358,13 +621,8 @@ ShapeExport& PowerPointShapeExport::WriteTextShape(const Reference< XShape >& xS } else if (sShapeType == "com.sun.star.presentation.SubtitleShape") { - // TODO: handle subtitle shape: see tdf#112557 workaround - // MSO does not like subtitles on master slides - if (mePageType != MASTER) - { - if (!WritePlaceholder(xShape, Subtitle, mbMaster)) - ShapeExport::WriteTextShape(xShape); - } + if (!WritePlaceholder(xShape, Subtitle, mbMaster)) + ShapeExport::WriteTextShape(xShape); } else SAL_WARN("sd.eppt", "PowerPointShapeExport::WriteTextShape: shape of type '" << sShapeType << "' is ignored"); @@ -388,6 +646,33 @@ ShapeExport& PowerPointShapeExport::WriteUnknownShape(const Reference< XShape >& return *this; } +ShapeExport& PowerPointShapeExport::WriteGraphicObjectShape(const Reference& xShape) +{ + // A picture or media placeholder serialises as with its own : on a layout or + // master always, on a slide only while still empty (once filled it stays a ). + const PlaceholderType ePlaceholder + = xShape ? getGraphicPlaceholderType(xShape->getShapeType()) : None; + if (ePlaceholder != None) + { + if (auto xProps = xShape.query()) + { + try + { + if ((mbMaster || isPlaceholderStillEmpty(xProps, ePlaceholder)) + && WritePlaceholder(xShape, ePlaceholder, mbMaster)) + return *this; + } + catch (const UnknownPropertyException&) + { + // Plain drawing.GraphicObjectShape has no + // IsEmptyPresentationObject; fall through. + } + } + } + + return ShapeExport::WriteGraphicObjectShape(xShape); +} + PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContext, const uno::Sequence& rArguments) : XmlFilterBase(rContext) , mpAuthorIDs( new SvtSecurityMapPersonalInfo ) @@ -403,6 +688,7 @@ PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContex comphelper::SequenceAsHashMap aArgumentsMap(rArguments); mbPptm = aArgumentsMap.getUnpackedValueOrDefault(u"IsPPTM"_ustr, false); mbExportTemplate = aArgumentsMap.getUnpackedValueOrDefault(u"IsTemplate"_ustr, false); + mbSlideShow = aArgumentsMap.getUnpackedValueOrDefault(u"IsSlideShow"_ustr, false); } PowerPointExport::~PowerPointExport() @@ -432,8 +718,6 @@ void PowerPointExport::writeDocumentProperties() } exportDocumentProperties(xDocProps, bSecurityOptOpenReadOnly); } - - exportCustomFragments(); } bool PowerPointExport::importDocument() noexcept @@ -465,6 +749,10 @@ bool PowerPointExport::exportDocument() { aMediaType = "application/vnd.ms-powerpoint.template.macroEnabled.main+xml"; } + else if (mbSlideShow) + { + aMediaType = "application/vnd.ms-powerpoint.slideshow.macroEnabled.main+xml"; + } else { aMediaType = "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml"; @@ -476,6 +764,10 @@ bool PowerPointExport::exportDocument() { aMediaType = "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml"; } + else if (mbSlideShow) + { + aMediaType = "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml"; + } else { aMediaType = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"; @@ -484,6 +776,8 @@ bool PowerPointExport::exportDocument() mPresentationFS = openFragmentStreamWithSerializer(u"ppt/presentation.xml"_ustr, aMediaType); + exportCustomFragments(mPresentationFS); + addRelation(mPresentationFS->getOutputStream(), oox::getRelationship(Relationship::THEME), u"theme/theme1.xml"); @@ -525,6 +819,8 @@ bool PowerPointExport::exportDocument() WriteModifyVerifier(); + WriteSections(); + mPresentationFS->endElementNS(XML_p, XML_presentation); mPresentationFS->endDocument(); mPresentationFS.reset(); @@ -664,7 +960,7 @@ std::unordered_set PowerPointExport::getUsedFontList() return aReturnSet; } -// Writers the list of all embedded fonts and reference to the fonts +// Writes the list of all embedded fonts and reference to the fonts void PowerPointExport::WriteEmbeddedFontList() { if (!mbEmbedFonts) @@ -913,6 +1209,93 @@ void PowerPointExport::WriteCustomSlideShow() mPresentationFS->endElementNS(XML_p, XML_custShowLst); } +void PowerPointExport::WriteSections() +{ + if (!mXModel->getPropertySetInfo()->hasPropertyByName(u"SlideSections"_ustr)) + return; + + uno::Sequence aSectionList; + mXModel->getPropertyValue(u"SlideSections"_ustr) >>= aSectionList; + + if (!aSectionList.hasElements()) + return; + + // Build page-name-to-index map for resolving slide names to IDs + Reference xDrawPages(mXModel->getDrawPages(), uno::UNO_SET_THROW); + std::map aNameToIndex; + for (sal_Int32 i = 0; i < xDrawPages->getCount(); ++i) + { + Reference xPage; + xDrawPages->getByIndex(i) >>= xPage; + Reference xNamed(xPage, UNO_QUERY); + if (xNamed.is()) + aNameToIndex[xNamed->getName()] = i; + } + + // https://learn.microsoft.com/en-us/openspecs/office_standards/ms-pptx/1f21a089-944d-410b-bd47-4f5e692c2532 + static constexpr OUString aSectionExtUri = u"{521415D9-36F7-43E2-AB2F-B90AF26B5E84}"_ustr; + mPresentationFS->startElementNS(XML_p, XML_extLst); + mPresentationFS->startElementNS(XML_p, XML_ext, XML_uri, aSectionExtUri); + mPresentationFS->startElementNS(XML_p14, XML_sectionLst, FSNS(XML_xmlns, XML_p14), + getNamespaceURL(OOX_NS(p14))); + + // Resolve slide page names to PPTX slide IDs via name-to-index lookup. + sal_Int32 nFallbackIdx = 0; + for (const auto& rSectionProp : aSectionList) + { + uno::Sequence aSectionProps; + rSectionProp.Value >>= aSectionProps; + + OUString sSectionName; + OUString sSectionId; + uno::Sequence aSlideNames; + + for (const auto& rProp : aSectionProps) + { + if (rProp.Name == "Name") + rProp.Value >>= sSectionName; + else if (rProp.Name == "Id") + rProp.Value >>= sSectionId; + else if (rProp.Name == "SlideNameList") + rProp.Value >>= aSlideNames; + } + + if (sSectionId.isEmpty()) + sSectionId = OStringToOUString(comphelper::xml::generateGUIDString(), + RTL_TEXTENCODING_ASCII_US); + + mPresentationFS->startElementNS(XML_p14, XML_section, + XML_name, sSectionName, + XML_id, sSectionId); + mPresentationFS->startElementNS(XML_p14, XML_sldIdLst); + + for (const OUString& rSlideName : aSlideNames) + { + sal_Int32 nSlideIndex = -1; + + auto it = aNameToIndex.find(rSlideName); + if (it != aNameToIndex.end()) + nSlideIndex = it->second; + else + nSlideIndex = nFallbackIdx; // Fallback for edge cases + + if (nSlideIndex >= 0 && o3tl::make_unsigned(nSlideIndex) < maSlideIdsInOrder.size()) + { + mPresentationFS->singleElementNS(XML_p14, XML_sldId, XML_id, + OString::number(maSlideIdsInOrder[nSlideIndex])); + } + ++nFallbackIdx; + } + + mPresentationFS->endElementNS(XML_p14, XML_sldIdLst); + mPresentationFS->endElementNS(XML_p14, XML_section); + } + + mPresentationFS->endElementNS(XML_p14, XML_sectionLst); + mPresentationFS->endElementNS(XML_p, XML_ext); + mPresentationFS->endElementNS(XML_p, XML_extLst); +} + void PowerPointExport::ImplWriteBackground(const FSHelperPtr& pFS, const Reference< XPropertySet >& rXPropSet) { FillStyle aFillStyle(FillStyle_NONE); @@ -1038,8 +1421,15 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS) if (!nPPTTransitionType && eFadeEffect != FadeEffect_NONE) nPPTTransitionType = GetTransition(eFadeEffect, nDirection); - if (ImplGetPropertyValue(mXPagePropSet, u"Sound"_ustr) && (mAny >>= sSoundUrl)) - embedEffectAudio(pFS, sSoundUrl, sSoundRelId, sSoundName); + if (ImplGetPropertyValue(mXPagePropSet, u"Sound"_ustr)) + { + css::uno::Reference xSound; + if ((mAny >>= xSound) && xSound.is() && xSound->getAllowed()) + { + sSoundUrl = xSound->getURL(); + embedEffectAudio(pFS, sSoundUrl, sSoundRelId, sSoundName); + } + } bool bOOXmlSpecificTransition = false; @@ -1682,8 +2072,10 @@ void PowerPointExport::ImplWriteSlide(sal_uInt32 nPageNum, sal_uInt32 nMasterNum oox::getRelationship(Relationship::SLIDE), Concat2View("slides/slide" + OUString::number(nPageNum + 1) +".xml")); + sal_uInt32 nSlideId = GetNewSlideId(); + maSlideIdsInOrder.push_back(nSlideId); mPresentationFS->singleElementNS(XML_p, XML_sldId, - XML_id, OString::number(GetNewSlideId()), + XML_id, OString::number(nSlideId), FSNS(XML_r, XML_id), sRelId); maRelId.push_back(sRelId); @@ -1925,6 +2317,52 @@ sal_uInt32 PowerPointExport::GetEquivalentMasterPage(sal_uInt32 nMasterPage) return maEquivalentMasters[nMasterPage]; } +size_t PowerPointExport::GetMasterOwnShapeCount(sal_uInt32 nMasterPage) +{ + const sal_uInt32 nGroup = GetEquivalentMasterPage(nMasterPage); + if (const auto aIter = maMasterOwnShapeCounts.find(nGroup); + aIter != maMasterOwnShapeCounts.end()) + return aIter->second; + + std::vector aPages; + if (nGroup != SAL_MAX_UINT32) + { + // The representative is the lowest index of its group, and the page the master part + // writes, so every other page is compared against it + for (sal_uInt32 i = 0; i < mnMasterPages; ++i) + { + if (maEquivalentMasters[i] == nGroup && maMastersLayouts[i].first) + aPages.push_back(static_cast(maMastersLayouts[i].first)); + } + assert(!aPages.empty() && aPages.front() == maMastersLayouts[nGroup].first); + } + if (aPages.empty()) + { + maMasterOwnShapeCounts.emplace(nGroup, 0); + return 0; + } + + // Each page draws the master's shapes first and its own after, so the leading run they all + // share is the master's. Stopping at the first difference keeps the z-order, since a shape can + // only move to the master along with everything below it. + size_t nOwn = 0; + for (;;) + { + const SdrObject* pShape = getLeadingShape(*aPages.front(), nOwn); + if (!pShape) + break; + if (!std::all_of(aPages.begin() + 1, aPages.end(), [pShape, nOwn](SdPage* pPage) { + const SdrObject* pOther = getLeadingShape(*pPage, nOwn); + return pOther && isSameShape(*pShape, *pOther); + })) + break; + ++nOwn; + } + + maMasterOwnShapeCounts.emplace(nGroup, nOwn); + return nOwn; +} + void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPropertySet > const& aXBackgroundPropSet) { SAL_INFO("sd.eppt", "write master slide: " << nPageNum << "\n--------------"); @@ -2003,19 +2441,12 @@ void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPro pFS->startElementNS(XML_p, XML_cSld); - if (GetEquivalentMasterPage(nPageNum) != nPageNum) - { - if (aXBackgroundPropSet) - ImplWriteBackground(pFS, aXBackgroundPropSet); - WriteShapeTree(pFS, MASTER, true); - } - else - { - // Minimal shape tree, the actual one will be written in the layout file. - pFS->startElementNS(XML_p, XML_spTree); - pFS->write(MAIN_GROUP); - pFS->endElementNS(XML_p, XML_spTree); - } + // The master carries its own placeholders even where the layouts repeat them, as PowerPoint + // authors it: an empty master has nothing to inherit from, and no date, footer or slide number + // placeholder to set that state on. + if (aXBackgroundPropSet) + ImplWriteBackground(pFS, aXBackgroundPropSet); + WriteShapeTree(pFS, MASTER, true, /*bSlideMasterPart=*/true, nPageNum); pFS->endElementNS(XML_p, XML_cSld); @@ -2128,10 +2559,17 @@ void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPro for (auto nLayout : aLayouts) { + // GetEquivalentMasterPage says SAL_MAX_UINT32 for a master with no equivalent, its own + // index for the one representing a group, and a lower index for a duplicate - and a + // duplicate has returned above. So a master of its own gets the layout its autolayout + // describes, while one standing for a group hands each layout the pages' own content. if (GetEquivalentMasterPage(nPageNum) == nPageNum) ImplWritePPTXLayoutWithContent(nLayout, nPageNum, aSlideName, aXBackgroundPropSet); else + { + assert(GetEquivalentMasterPage(nPageNum) == SAL_MAX_UINT32); ImplWritePPTXLayout(nLayout, nPageNum, aSlideName); + } AddLayoutIdAndRelation(pFS, GetLayoutFileId(nLayout, nPageNum)); } @@ -2168,6 +2606,83 @@ void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPro pFS->endDocument(); } +void PowerPointExport::WriteLayoutClrMapOvr(const FSHelperPtr& pFS, sal_uInt32 nMasterNum) +{ + // Build key: "OOXLayoutClrMapOvr_" + OUString sKey = "OOXLayoutClrMapOvr_" + OUString::number(nMasterNum); + + // Get grab bag + uno::Sequence aGrabBag; + if (mXModel->getPropertySetInfo()->hasPropertyByName(u"InteropGrabBag"_ustr)) + mXModel->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag; + + // Look for layout color map override + uno::Sequence aClrMapOvr; + for (const auto& rProp : aGrabBag) + { + if (rProp.Name == sKey) + { + rProp.Value >>= aClrMapOvr; + break; + } + } + + pFS->startElementNS(XML_p, XML_clrMapOvr); + + if (aClrMapOvr.hasElements()) + { + // Convert token values to string names + std::vector aClrMap(12); + for (const auto& item : aClrMapOvr) + { + sal_Int32 nToken = XML_TOKEN_INVALID; + item.Value >>= nToken; + OUString sName; + switch (nToken) + { + case XML_dk1: sName = u"dk1"_ustr; break; + case XML_lt1: sName = u"lt1"_ustr; break; + case XML_dk2: sName = u"dk2"_ustr; break; + case XML_lt2: sName = u"lt2"_ustr; break; + case XML_accent1: sName = u"accent1"_ustr; break; + case XML_accent2: sName = u"accent2"_ustr; break; + case XML_accent3: sName = u"accent3"_ustr; break; + case XML_accent4: sName = u"accent4"_ustr; break; + case XML_accent5: sName = u"accent5"_ustr; break; + case XML_accent6: sName = u"accent6"_ustr; break; + case XML_hlink: sName = u"hlink"_ustr; break; + case XML_folHlink: sName = u"folHlink"_ustr; break; + default: sName = u"lt1"_ustr; break; + } + sal_Int32 nIndex = item.Name.toInt32(); + if (nIndex >= 0 && nIndex < 12) + aClrMap[nIndex] = sName; + } + + // Write override color mapping + pFS->singleElementNS(XML_a, XML_overrideClrMapping, + XML_bg1, aClrMap[0], + XML_tx1, aClrMap[1], + XML_bg2, aClrMap[2], + XML_tx2, aClrMap[3], + XML_accent1, aClrMap[4], + XML_accent2, aClrMap[5], + XML_accent3, aClrMap[6], + XML_accent4, aClrMap[7], + XML_accent5, aClrMap[8], + XML_accent6, aClrMap[9], + XML_hlink, aClrMap[10], + XML_folHlink, aClrMap[11]); + } + else + { + // No override - inherit from master + pFS->singleElementNS(XML_a, XML_masterClrMapping); + } + + pFS->endElementNS(XML_p, XML_clrMapOvr); +} + sal_Int32 PowerPointExport::GetLayoutFileId(sal_Int32 nOffset, sal_uInt32 nMasterNum) { SAL_INFO("sd.eppt", "GetLayoutFileId offset: " << nOffset << " master: " << nMasterNum); @@ -2236,6 +2751,8 @@ void PowerPointExport::ImplWritePPTXLayout(sal_Int32 nOffset, sal_uInt32 nMaster pFS->endElementNS(XML_p, XML_cSld); + WriteLayoutClrMapOvr(pFS, nMasterNum); + pFS->endElementNS(XML_p, XML_sldLayout); mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ] = mnLayoutFileIdMax; @@ -2269,10 +2786,15 @@ void PowerPointExport::ImplWritePPTXLayoutWithContent( "ppt/slideLayouts/slideLayout" + OUString::number(nLayoutFileId) + ".xml", "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"); - // add implicit relation of slide layout to slide master + // add implicit relation of slide layout to slide master. A master with no equivalent is its + // own, and GetEquivalentMasterPage reports SAL_MAX_UINT32 for it - taking that as an index + // would point the relation at a slideMaster0 that does not exist. + const sal_uInt32 nEquivalentMaster = GetEquivalentMasterPage(nMasterNum); + const sal_uInt32 nMasterFileNum + = nEquivalentMaster == SAL_MAX_UINT32 ? nMasterNum : nEquivalentMaster; addRelation(pFS->getOutputStream(), oox::getRelationship(Relationship::SLIDEMASTER), Concat2View("../slideMasters/slideMaster" - + OUString::number(GetEquivalentMasterPage(nMasterNum) + 1) + ".xml")); + + OUString::number(nMasterFileNum + 1) + ".xml")); auto pAttributes = presentationNamespaces(*this); pAttributes->add(XML_type, aLayoutInfo[nOffset].sType); @@ -2292,22 +2814,38 @@ void PowerPointExport::ImplWritePPTXLayoutWithContent( if (aXBackgroundPropSet) ImplWriteBackground(pFS, aXBackgroundPropSet); - WriteShapeTree(pFS, MASTER, true); + WriteShapeTree(pFS, MASTER, true, /*bSlideMasterPart=*/false, nMasterNum); pFS->endElementNS(XML_p, XML_cSld); + WriteLayoutClrMapOvr(pFS, nMasterNum); + pFS->endElementNS(XML_p, XML_sldLayout); pFS->endDocument(); } -void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType, bool bMaster) +void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType, bool bMaster, + bool bSlideMasterPart, sal_uInt32 nMasterNum) { PowerPointShapeExport aDML(pFS, &maShapeMap, this); aDML.SetMaster(bMaster); aDML.SetPageType(ePageType); + aDML.SetSlideMasterPart(bSlideMasterPart); aDML.SetBackgroundDark(mbIsBackgroundDark); + // A master standing for a group writes its placeholders and the shapes the group shares. A + // placeholder reaches a slide only through a layout that references it, while a drawn shape + // paints below every slide of this master - so a shape one layout drew does not belong there. + // A master of its own has no layout to leave anything to. + const bool bMasterOfGroup + = bSlideMasterPart && GetEquivalentMasterPage(nMasterNum) == nMasterNum; + // The layouts of such a group leave those shapes to the master + const bool bLayoutOfGroup = !bSlideMasterPart && ePageType == MASTER; + assert(!bLayoutOfGroup || GetEquivalentMasterPage(nMasterNum) != SAL_MAX_UINT32); + const size_t nMasterOwn + = bMasterOfGroup || bLayoutOfGroup ? GetMasterOwnShapeCount(nMasterNum) : 0; + pFS->startElementNS(XML_p, XML_spTree); pFS->write(MAIN_GROUP); @@ -2329,6 +2867,16 @@ void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType if (GetShapeByIndex(GetCurrentGroupIndex(), true)) { SAL_INFO("sd.eppt", "mType: " << mType); + // The run leads the page, so the page index tells the master's shapes from a + // layout's own. The index is the page's because this loop never enters a group. + assert(GetCurrentGroupLevel() == 0); + const bool bOwn = GetCurrentGroupIndex() < nMasterOwn; + assert(!bOwn || !mbPresObj); + if (bMasterOfGroup && !bOwn && !mbPresObj) + continue; // one layout's own shape, which that layout writes + if (bLayoutOfGroup && bOwn) + continue; // the master draws it for every layout of the group + const SdrObjGroup* pDiagramCandidate(dynamic_cast(SdrObject::getSdrObjectFromXShape(mXShape))); bool bSaveAsDiagram(false); @@ -2360,6 +2908,10 @@ void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType if ( ePageType == NORMAL || ePageType == LAYOUT ) WritePlaceholderReferenceShapes(aDML, ePageType); + if ( ePageType == LAYOUT ) + WriteLayoutContentPlaceholders(aDML); + if (bSlideMasterPart) + WriteMasterOwnPlaceholders(aDML, nMasterNum); pFS->endElementNS(XML_p, XML_spTree); } @@ -2381,6 +2933,12 @@ bool PowerPointShapeExport::WritePlaceholder(const Reference< XShape >& xShape, Reference xShapeProps(xShape, UNO_QUERY); if (xShapeProps->getPropertyValue(u"IsPresentationObject"_ustr).get()) { + // The layouts of this master write the same shapes, and a type the master may not + // carry belongs only there. Report it as handled, so that no plain shape is written + // here in its place. + if (mbSlideMasterPart && !isPlaceholderAllowedOnSlideMaster(ePlaceholder)) + return true; + WritePlaceholderShape(xShape, ePlaceholder); return true; @@ -2430,12 +2988,14 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap bUseCustomPrompt = true; } + // Leave the shape without a placeholder reference where the master would not take one, rather + // than writing a type that makes the whole file unopenable. if (bUsePlaceholderIndex) { mpFS->singleElementNS( XML_p, XML_ph, XML_type, pType, XML_idx, OString::number( - static_cast(GetFB())->CreateNewPlaceholderIndex(xShape)), + static_cast(GetFB())->GetOrCreatePlaceholderIndex(xShape)), XML_hasCustomPrompt, sax_fastparser::UseIf("1", bUseCustomPrompt)); } else @@ -2449,13 +3009,21 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap mpFS->endElementNS(XML_p, XML_nvPr); mpFS->endElementNS(XML_p, XML_nvSpPr); - // visual shape properties + // Write the geometry even where a layout placeholder could supply it: that is what PowerPoint + // itself authors, and it keeps the slide readable by a consumer that does not resolve the + // inheritance. mpFS->startElementNS(XML_p, XML_spPr); WriteShapeTransformation(xShape, XML_a); - WritePresetShape("rect"_ostr); + // A picture placeholder can be clipped to an outline, which is the shape's own geometry in the + // file; where there is one it takes the place of the rectangle. + if (!WriteGraphicClipCustomGeometry(xProps, xShape->getSize())) + WritePresetShape("rect"_ostr); if (xProps.is()) { - WriteBlipFill(xProps, u"Graphic"_ustr); + // A picture placeholder's "Graphic" property is the internal + // placeholder icon; don't serialise it as a blipFill. + if (!isGraphicPlaceholder(ePlaceholder)) + WriteBlipFill(xProps, u"Graphic"_ustr); // Do not forget to export the visible properties. WriteFill( xProps, xShape->getSize()); WriteOutline( xProps ); @@ -2479,8 +3047,24 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap = (mePageType == PageType::MASTER) && (ePlaceholder == Title || ePlaceholder == Subtitle || ePlaceholder == Outliner); - WriteTextBox(xShape, XML_p, - bUsePlaceholderIndex || bWritePropertiesAsLstStyles); + // An untouched placeholder shows Impress's own localized prompt resource unless the document + // authored one, and that must not reach the file - a reader supplies its own prompt. + bool bIsEmptyPresObj(false); + if (xProps + && xProps->getPropertySetInfo()->hasPropertyByName(u"IsEmptyPresentationObject"_ustr)) + xProps->getPropertyValue(u"IsEmptyPresentationObject"_ustr) >>= bIsEmptyPresObj; + // Field placeholders carry their field content, and a master's text box carries list styles. + const bool bTextIsDefaultPrompt = bIsEmptyPresObj && !bUseCustomPrompt && !bUsePlaceholderIndex + && !bWritePropertiesAsLstStyles; + + // A slide-side empty picture placeholder inherits the prompt from the layout, so it writes no + // text; one that is not empty was typed into, and that text is the slide's own content. The + // body properties travel either way - they carry the insets, the anchor, the writing direction + // and the autofit. + const bool bInheritsItsPrompt = isGraphicPlaceholder(ePlaceholder) && !mbMaster + && bIsEmptyPresObj; + WriteTextBox(xShape, XML_p, bUsePlaceholderIndex || bWritePropertiesAsLstStyles, + /*bText=*/!bTextIsDefaultPrompt && !bInheritsItsPrompt); mpFS->endElementNS(XML_p, XML_sp); @@ -2828,6 +3412,7 @@ void PowerPointExport::embedEffectAudio(const FSHelperPtr& pFS, const OUString& // MS PowerPoint reports a corrupt file if the media name contains non-ascii characters OUString sAsciiName; + uno::Sequence aTempBuf; if (comphelper::string::isValidAsciiFilename(sName)) sAsciiName = sName; else @@ -2835,7 +3420,6 @@ void PowerPointExport::embedEffectAudio(const FSHelperPtr& pFS, const OUString& // create an ASCII name - using a hash to try and keep it unique and yet non-random comphelper::Hash aHash(comphelper::HashType::MD5); sal_Int32 nBytesToRead = std::clamp(xAudioStream->available(), 0, 32000); - uno::Sequence aTempBuf(nBytesToRead); if ((nBytesToRead = xAudioStream->readBytes(aTempBuf, nBytesToRead))) aHash.update(aTempBuf.getConstArray(), nBytesToRead); else // safety fallback: use the name to create a hash: should never happen @@ -2854,6 +3438,9 @@ void PowerPointExport::embedEffectAudio(const FSHelperPtr& pFS, const OUString& uno::Reference xOutputStream = openFragmentStream(sPath.replaceAt(0, 2, u"/ppt"), u"audio/x-wav"_ustr); + // if bytes were read from input for hash generation, write those, too, otherwise they get lost + if (aTempBuf.hasElements()) + xOutputStream->writeBytes(aTempBuf); comphelper::OStorageHelper::CopyInputToOutput(xAudioStream, xOutputStream); } @@ -2935,10 +3522,74 @@ void PowerPointExport::WritePlaceholderReferenceShapes(PowerPointShapeExport& rD } } -sal_Int32 PowerPointExport::CreateNewPlaceholderIndex(const css::uno::Reference &rXShape) +void PowerPointExport::WriteLayoutContentPlaceholders(PowerPointShapeExport& rDML) { - maPlaceholderShapeToIndexMap.insert({rXShape, mnPlaceholderIndexMax}); - return mnPlaceholderIndexMax++; + // A slide master may not carry these, so the master page's own copy is written here, where a + // slide looks for the geometry and the prompt it inherits. + // + // A media placeholder needs no entry: it reaches the file through the page's own shape tree, + // where WriteGraphicObjectShape writes it as a placeholder while it is still empty. + for (const PlaceholderType ePlaceholder : { Picture }) + { + assert(!isPlaceholderAllowedOnSlideMaster(ePlaceholder)); + Reference xShape = GetReferencedPlaceholderXShape(ePlaceholder, LAYOUT); + if (!xShape) + continue; + + // Only one still waiting for its content belongs on the layout. One that holds a picture + // is written on the page holding it, as an ordinary picture. + auto xProps = xShape.query(); + if (!xProps || xProps->getPropertyValue(u"IsEmptyPresentationObject"_ustr) != true) + continue; + + rDML.WritePlaceholderShape(xShape, ePlaceholder); + } +} + +void PowerPointExport::WriteMasterOwnPlaceholders(PowerPointShapeExport& rDML, + sal_uInt32 nMasterNum) +{ + SdPage* pPage = SdPage::getImplementation(mXDrawPage); + if (!pPage) + return; + + for (const auto& [ePlaceholder, ePresObjKind] : + { std::pair(Title, PresObjKind::Title), std::pair(Outliner, PresObjKind::Outline) }) + { + assert(isPlaceholderAllowedOnSlideMaster(ePlaceholder)); + if (pPage->GetPresObj(ePresObjKind)) + continue; // the shape tree has written the page's own + + // The pages standing for one slide master are its layouts, and a layout placeholder was + // imported with the geometry and the formatting it inherits from the master, so the first + // of them to carry this type carries the master's prototype of it. A layout that states + // its own geometry gives that instead - the closest thing left to ask. + for (sal_uInt32 i = 0; i < mnMasterPages; ++i) + { + if (i == mnCanvasMasterIndex + || (i != nMasterNum && maEquivalentMasters[i] != nMasterNum)) + continue; + + SdPage* pOther = dynamic_cast(maMastersLayouts[i].first); + SdrObject* pObj = pOther ? pOther->GetPresObj(ePresObjKind) : nullptr; + if (!pObj) + continue; + + rDML.WritePlaceholderShape(GetXShapeForSdrObject(pObj), ePlaceholder); + break; + } + } +} + +sal_Int32 PowerPointExport::GetOrCreatePlaceholderIndex(const css::uno::Reference &rXShape) +{ + // One index per shape, however many parts write it: a slide's placeholder pairs with the + // layout's by type and index, so handing the second writer a fresh number breaks that pair. + const auto [aIter, bInserted] + = maPlaceholderShapeToIndexMap.try_emplace(rXShape, mnPlaceholderIndexMax); + if (bInserted) + ++mnPlaceholderIndexMax; + return aIter->second; } Reference PowerPointExport::GetReferencedPlaceholderXShape(const PlaceholderType eType, @@ -2972,6 +3623,12 @@ Reference PowerPointExport::GetReferencedPlaceholderXShape(const Placeho break; case oox::core::Subtitle: break; + case oox::core::Picture: + ePresObjKind = PresObjKind::Graphic; + break; + case oox::core::Media: + ePresObjKind = PresObjKind::Media; + break; } if (ePresObjKind != PresObjKind::NONE) { diff --git a/sd/source/filter/eppt/pptx-text.cxx b/sd/source/filter/eppt/pptx-text.cxx index bd5c1d07ce1a..aa3d928d234d 100644 --- a/sd/source/filter/eppt/pptx-text.cxx +++ b/sd/source/filter/eppt/pptx-text.cxx @@ -739,8 +739,8 @@ ParagraphObj::~ParagraphObj() void ParagraphObj::Write( SvStream* pStrm ) { - for ( std::vector >::iterator it = mvPortions.begin(); it != mvPortions.end(); ++it ) - (*it)->Write( pStrm, mbLastParagraph ); + for (const auto& pPortion : mvPortions) + pPortion->Write(pStrm, mbLastParagraph); } void ParagraphObj::ImplClear() @@ -1200,8 +1200,8 @@ void ParagraphObj::ImplConstruct( const ParagraphObj& rParagraphObj ) mbForbiddenRules = rParagraphObj.mbForbiddenRules; mnBiDi = rParagraphObj.mnBiDi; - for ( std::vector >::const_iterator it = rParagraphObj.begin(); it != rParagraphObj.end(); ++it ) - mvPortions.push_back( std::make_unique( **it ) ); + for (const auto& pPortion : rParagraphObj) + mvPortions.push_back(std::make_unique(*pPortion)); maTabStop = rParagraphObj.maTabStop; bExtendedParameters = rParagraphObj.bExtendedParameters; @@ -1229,8 +1229,8 @@ void ParagraphObj::ImplConstruct( const ParagraphObj& rParagraphObj ) sal_uInt32 ParagraphObj::ImplCalculateTextPositions( sal_uInt32 nCurrentTextPosition ) { mnTextSize = 0; - for ( std::vector >::iterator it = mvPortions.begin(); it != mvPortions.end(); ++it ) - mnTextSize += (*it)->ImplCalculateTextPositions( nCurrentTextPosition + mnTextSize ); + for (const auto& pPortion : mvPortions) + mnTextSize += pPortion->ImplCalculateTextPositions(nCurrentTextPosition + mnTextSize); return mnTextSize; } diff --git a/sd/source/filter/grf/sdgrffilter.cxx b/sd/source/filter/grf/sdgrffilter.cxx index 68251d1e5a20..ebb712c03ab3 100644 --- a/sd/source/filter/grf/sdgrffilter.cxx +++ b/sd/source/filter/grf/sdgrffilter.cxx @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -228,7 +227,7 @@ void SdGRFFilter::InsertSdrGrafObj(const Graphic& rGraphic, SdPage* pPage) bool SdGRFFilter::Export() { - // SJ: todo: error handling, the GraphicExportFilter does not support proper errorhandling + // SJ: todo: error handling, the GraphicExportFilter does not support proper error handling bool bRet = false; const uno::Reference< uno::XComponentContext >& xContext = ::comphelper::getProcessComponentContext(); @@ -251,7 +250,7 @@ bool SdGRFFilter::Export() if ( pPage ) { - // taking the 'correct' page number, seems that there might exist a better method to archive this + // taking the 'correct' page number, seems that there might exist a better method to achieve this pPage = mrDocument.GetSdPage( pPage->GetPageNum() ? ( pPage->GetPageNum() - 1 ) >> 1 : 0, ePageKind ); if ( pPage ) { diff --git a/sd/source/filter/pdf/sdpdffilter.cxx b/sd/source/filter/pdf/sdpdffilter.cxx index 7f516776824b..dd5167787a1a 100644 --- a/sd/source/filter/pdf/sdpdffilter.cxx +++ b/sd/source/filter/pdf/sdpdffilter.cxx @@ -21,9 +21,13 @@ #include #include +#include +#include +#include #include #include #include +#include #include #include @@ -50,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -63,10 +68,13 @@ SdPdfFilter::SdPdfFilter(SfxMedium& rMedium, sd::DrawDocShell& rDocShell) SdPdfFilter::~SdPdfFilter() {} -static bool ImportPDF(SvStream& rStream, SdDrawDocument& rDocument) +static bool ImportPDF(SvStream& rStream, SdDrawDocument& rDocument, + const uno::Reference& xInteractionHandler + = nullptr, + const OUString& rPassword = OUString()) { std::vector aGraphics; - if (vcl::ImportPDFUnloaded(rStream, aGraphics) == 0) + if (vcl::ImportPDFUnloaded(rStream, aGraphics, xInteractionHandler, rPassword) == 0) return false; bool bWasLocked = rDocument.isLocked(); @@ -120,8 +128,73 @@ static bool ImportPDF(SvStream& rStream, SdDrawDocument& rDocument) pPage->InsertObject(pSdrGrafObj.get()); + // Per-page bookkeeping for threaded-comment resolution. Pdfium annotation indices and + // /IRT parent links are page-scoped, so these structures live inside the page loop; a + // cross-page /IRT has already been dropped to -1 by findAnnotations. + std::map> aPdfiumIndexToAnnot; + std::vector, int>> aAnnotToParent; + // Per PDF spec, the "state" of a comment lives in a separate annotation that carries + // /IRT + /State + /StateModel and points at the target. Acrobat models this as independent + // per-user state: each reviewer maintains their own state (identified by the state-change + // annotation's /T author). A target comment is shown with a resolved checkmark as long as + // *any* reviewer's current state is "Completed"; its tooltip then lists every reviewer + // who has marked it. + // + // We currently collapse all of that into a single per-comment boolean + // (sd::Annotation::IsResolved). The lossy mapping we pick is: + // - each reviewer's state = the latest state-change they authored for that target + // (by /M); + // - the target is considered resolved if any reviewer's latest state is "Completed". + // On export we will only be able to encode a single reviewer's state (the current editing + // user), so other reviewers' per-user states that we observed on import are not + // round-tripped. + struct StateChange + { + int mnTargetPdfiumIndex; + OUString maAuthor; + OUString maState; + OUString maStateModel; + DateTime maDateTime{ DateTime::EMPTY }; + }; + std::vector aStateChanges; + + // We only honour the "Review" state (the "Marked" model is defined by the spec, but it's + // unclear how to treat it correctly: Acrobat doesn't show anything for "Marked/Marked"). + // "Review/Completed" is the value that represents "resolved"; other states are not + // currently modelled. Acrobat stamps state-change annotations with /F = Hidden | NoZoom | + // NoRotate = 2|8|16 = 26, so they don't appear as visible replies. /State on annotations + // that lack those flag bits isn't recognised by Acrobat as a state-change, so we match + // its rule: don't collapse unless all three flag bits are present. (Print, value 4, is + // often also set alongside but is not required.) + constexpr int kStateChangeFlagMask = 2 | 8 | 16; + for (auto const& rPDFAnnotation : rPDFGraphicResult.GetAnnotations()) { + const bool bHasParent = rPDFAnnotation.mnParentPdfiumIndex != -1; + const bool bHasState + = !rPDFAnnotation.maState.isEmpty() && !rPDFAnnotation.maStateModel.isEmpty(); + // /RT = "Group" means /IRT is a grouping relationship, not a reply. State-changes + // and reply-parent links only apply when /RT = "R" (the spec's implicit default). + const bool bIsReplyRelation = rPDFAnnotation.maReplyType == u"R"; + + // /IRT + /State + /StateModel on a reply-relation is structurally a state-change + // annotation. If the flag bits also match Acrobat's gate, collapse it into the + // target's resolved state. If the flags don't match, Acrobat treats the combination + // as malformed and skips the annotation entirely — we do the same. + if (bHasParent && bHasState && bIsReplyRelation) + { + // Only /StateModel = "Review" contributes to our resolved boolean; state-changes + // in the "Marked" model are valid per spec but not representable in our model + // and are discarded. + if ((rPDFAnnotation.mnFlags & kStateChangeFlagMask) == kStateChangeFlagMask + && rPDFAnnotation.maStateModel == u"Review") + aStateChanges.push_back({ rPDFAnnotation.mnParentPdfiumIndex, + rPDFAnnotation.maAuthor, rPDFAnnotation.maState, + rPDFAnnotation.maStateModel, + DateTime(rPDFAnnotation.maDateTime) }); + continue; + } + rtl::Reference xAnnotation = pPage->createAnnotation(); xAnnotation->setAuthor(rPDFAnnotation.maAuthor); @@ -137,6 +210,18 @@ static bool ImportPDF(SvStream& rStream, SdDrawDocument& rDocument) xAnnotation->setSize(aUnoSize); xAnnotation->setDateTime(rPDFAnnotation.maDateTime); + // Every imported PDF comment supports reply / resolve. + xAnnotation->SetThreaded(true); + + // /State on an annotation that isn't a recognised state-change (missing /IRT, or + // missing the Hidden/NoZoom/NoRotate flag bits) is silently ignored here; Acrobat + // ignores it the same way, so matching that behaviour keeps round-trips consistent. + + if (bHasParent && bIsReplyRelation) + aAnnotToParent.emplace_back(xAnnotation, rPDFAnnotation.mnParentPdfiumIndex); + + aPdfiumIndexToAnnot[rPDFAnnotation.mnPdfiumIndex] = xAnnotation; + if (rPDFAnnotation.mpMarker) { sdr::annotation::CreationInfo aInfo; @@ -251,6 +336,44 @@ static bool ImportPDF(SvStream& rStream, SdDrawDocument& rDocument) pPage->addAnnotation(xAnnotation, -1); } + + // Resolve reply parent links now that every (non-state-change) annotation on this page + // has been created and its GetId() is known. + for (auto const & [ xChild, nParentPdfiumIndex ] : aAnnotToParent) + { + auto it = aPdfiumIndexToAnnot.find(nParentPdfiumIndex); + if (it != aPdfiumIndexToAnnot.end()) + xChild->SetParentId(it->second->GetId()); + } + + // Collapse per-user states to one boolean per target: target's latest state per reviewer + // (by /M) -> resolved if any of those latest states is "Completed". /StateModel was + // already constrained to "Review" at insertion, so here we only compare /State values. + struct LatestPerUser + { + DateTime maDateTime{ DateTime::EMPTY }; + OUString maState; + }; + std::map> aLatestPerUser; + for (auto const& rStateChange : aStateChanges) + { + auto& rSlot = aLatestPerUser[rStateChange.mnTargetPdfiumIndex][rStateChange.maAuthor]; + if (rSlot.maState.isEmpty() || rSlot.maDateTime < rStateChange.maDateTime) + rSlot = { rStateChange.maDateTime, rStateChange.maState }; + } + for (auto const & [ nTarget, rPerUser ] : aLatestPerUser) + { + auto it = aPdfiumIndexToAnnot.find(nTarget); + if (it == aPdfiumIndexToAnnot.end()) + continue; + const bool bAnyCompleted + = std::any_of(rPerUser.begin(), rPerUser.end(), [](auto const& rEntry) { + return rEntry.second.maState == u"Completed"; + }); + if (bAnyCompleted) + it->second->SetResolved(true); + } + pPage->setLinkAnnotations(rPDFGraphicResult.GetLinksInfo()); } @@ -273,7 +396,14 @@ bool SdPdfFilter::Import() std::unique_ptr xStream(::utl::UcbStreamHelper::CreateStream( aFileName, StreamMode::READ | StreamMode::SHARE_DENYNONE)); - return ImportPDF(*xStream, mrDocument); + // An encrypted PDF has to be decrypted for the version downgrade done while + // reading. Forward the password already collected during type detection (if + // any) and the interaction handler so it can be obtained without failing. + OUString aPassword; + if (const SfxStringItem* pPasswordItem = mrMedium.GetItemSet().GetItem(SID_PASSWORD, false)) + aPassword = pPasswordItem->GetValue(); + + return ImportPDF(*xStream, mrDocument, mrMedium.GetInteractionHandler(), aPassword); } bool SdPdfFilter::Export() { return false; } diff --git a/sd/source/filter/ppt/ppt97animations.cxx b/sd/source/filter/ppt/ppt97animations.cxx index 307fad11f515..459c8ddfcc16 100644 --- a/sd/source/filter/ppt/ppt97animations.cxx +++ b/sd/source/filter/ppt/ppt97animations.cxx @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -484,7 +485,7 @@ void Ppt97Animation::UpdateCacheData() const m_aPresetId = "ooo-entrance-swivel"; m_aSubType = "vertical"; break; - case 0x1c: // --- spirale --- + case 0x1c: // --- spiral --- m_aPresetId = "ooo-entrance-spiral-in"; break; } @@ -602,9 +603,9 @@ void Ppt97Animation::createAndSetCustomAnimationEffect( SdrObject* pObj ) pEffect->setAfterEffectOnNext( HasAfterEffect_DimAtNextEffect() ); } - // set sound effect + // set sound effect. Embedded in the .ppt, not a link: allow it. if( HasSoundEffect() ) - pEffect->createAudio( uno::Any( m_aSoundFileUrl ) ); + pEffect->createAudio( xmloff::makeSoundSource( m_aSoundFileUrl, /*bAllowed*/true ) ); // text iteration pEffect->setIterateType( GetTextAnimationType() ); @@ -628,7 +629,7 @@ void Ppt97Animation::createAndSetCustomAnimationEffect( SdrObject* pObj ) pEffect->setTargetSubItem( presentation::ShapeAnimationSubType::AS_WHOLE ); } - //3. ------ put the created effect to the model and do some last changes fro paragraph effects ------ + //3. ------ put the created effect to the model and do some last changes for paragraph effects ------ pMainSequence->append( pEffect ); if( HasParagraphEffect() ) { diff --git a/sd/source/filter/ppt/pptin.cxx b/sd/source/filter/ppt/pptin.cxx index 5a5ef2a1f50b..06e8f4176f70 100644 --- a/sd/source/filter/ppt/pptin.cxx +++ b/sd/source/filter/ppt/pptin.cxx @@ -1828,7 +1828,8 @@ void ImplSdPPTImport::ImportPageEffect( SdPage* pPage, const bool bNewAnimations { // slide with sound effect pPage->SetSound( true ); OUString aSoundFile( ReadSound( nSoundRef ) ); - pPage->SetSoundFile( aSoundFile ); + // Embedded in the .ppt, not a link: allow it. + pPage->SetSoundFile( aSoundFile, /*bAllowed*/true ); } if ( nBuildFlags & ( 1 << 6 ) ) // Loop until next sound pPage->SetLoopSound( true ); @@ -2090,8 +2091,11 @@ void ImplSdPPTImport::FillSdAnimationInfo(SdAnimationInfo* pInfo, const PptInter // set local information into pInfo if( rIAtom.nSoundRef ) { + // Embedded in the .ppt, not a link: allow it. Set the action before the + // bookmark so the URL is stored as a click-action sound. + pInfo->meClickAction = css::presentation::ClickAction_SOUND; + pInfo->mbClickSoundAllowed = true; pInfo->SetBookmark( ReadSound( rIAtom.nSoundRef ) ); // path to sound file in MS DOS notation - pInfo->meClickAction = css::presentation::ClickAction_SOUND; // RunProgramAction } switch ( rIAtom.nAction ) diff --git a/sd/source/filter/ppt/pptinanimations.cxx b/sd/source/filter/ppt/pptinanimations.cxx index a4e86d7bdb53..77a8485bdcbc 100644 --- a/sd/source/filter/ppt/pptinanimations.cxx +++ b/sd/source/filter/ppt/pptinanimations.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -65,6 +66,7 @@ #include #include #include +#include #include "pptanimations.hxx" #include "pptinanimations.hxx" #include "pptatom.hxx" @@ -1814,7 +1816,15 @@ int AnimationImporter::importAudioContainer( const Atom* pAtom, const Reference< Any aSource; importTargetElementContainer( pChildAtom, aSource, nSubType ); if( xAudio.is() ) { - xAudio->setSource( aSource ); + // a sound source is a URL, a media object source is a shape + OUString aSoundURL; + if( aSource >>= aSoundURL ) + { + // Embedded in the .ppt, not a link: allow it. + xAudio->setSource( xmloff::makeSoundSource( aSoundURL, /*bAllowed*/true ) ); + } + else + xAudio->setSource( aSource ); nNodes ++; } } diff --git a/sd/source/filter/xml/sdxmlwrp.cxx b/sd/source/filter/xml/sdxmlwrp.cxx index 6df5e6a02c10..ff0f0e996882 100644 --- a/sd/source/filter/xml/sdxmlwrp.cxx +++ b/sd/source/filter/xml/sdxmlwrp.cxx @@ -650,9 +650,6 @@ bool SdXMLFilter::Import( ErrCode& nError ) mxModel->unlockControllers(); pDoc->decImportExport(); - if( nRet == ERRCODE_NONE ) - pDoc->UpdateAllLinks(); - if( nRet == ERRCODE_NONE || nRet == SD_XML_READERROR ) ; else if( nRet == ERRCODE_IO_BROKENPACKAGE && xStorage.is() ) diff --git a/sd/source/ui/accessibility/AccessibleDocumentViewBase.cxx b/sd/source/ui/accessibility/AccessibleDocumentViewBase.cxx index a8f2f2c71eb2..b9f8077032f6 100644 --- a/sd/source/ui/accessibility/AccessibleDocumentViewBase.cxx +++ b/sd/source/ui/accessibility/AccessibleDocumentViewBase.cxx @@ -58,19 +58,16 @@ using ::com::sun::star::uno::Reference; namespace accessibility { -AccessibleDocumentViewBase::AccessibleDocumentViewBase ( - ::sd::Window* pSdWindow, - ::sd::ViewShell* pViewShell, +AccessibleDocumentViewBase::AccessibleDocumentViewBase( + ::sd::Window* pSdWindow, ::sd::ViewShell* pViewShell, uno::Reference xController, - const uno::Reference& rxParent) - : AccessibleContextBase (rxParent, - pViewShell->GetDoc()->GetDocumentType() == DocumentType::Impress ? - AccessibleRole::DOCUMENT_PRESENTATION : - AccessibleRole::DOCUMENT), - mxController (std::move(xController)), - maViewForwarder ( - static_cast(pViewShell->GetView()), - *pSdWindow->GetOutDev()) + const rtl::Reference& rpParent) + : AccessibleContextBase(rpParent, + pViewShell->GetDoc()->GetDocumentType() == DocumentType::Impress + ? AccessibleRole::DOCUMENT_PRESENTATION + : AccessibleRole::DOCUMENT) + , mxController(std::move(xController)) + , maViewForwarder(static_cast(pViewShell->GetView()), *pSdWindow->GetOutDev()) { if (mxController.is()) mxModel = mxController->getModel(); @@ -217,14 +214,6 @@ void AccessibleDocumentViewBase::ViewForwarderChanged() //===== XAccessibleContext ================================================== -Reference SAL_CALL - AccessibleDocumentViewBase::getAccessibleParent() -{ - ensureAlive(); - - return AccessibleContextBase::getAccessibleParent(); -} - sal_Int64 SAL_CALL AccessibleDocumentViewBase::getAccessibleChildCount() { diff --git a/sd/source/ui/accessibility/AccessibleDrawDocumentView.cxx b/sd/source/ui/accessibility/AccessibleDrawDocumentView.cxx index ae03eb724a3a..14d9e512eb2d 100644 --- a/sd/source/ui/accessibility/AccessibleDrawDocumentView.cxx +++ b/sd/source/ui/accessibility/AccessibleDrawDocumentView.cxx @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -78,12 +79,11 @@ struct XShapePosCompareHelper } -AccessibleDrawDocumentView::AccessibleDrawDocumentView ( - ::sd::Window* pSdWindow, - ::sd::ViewShell* pViewShell, +AccessibleDrawDocumentView::AccessibleDrawDocumentView( + ::sd::Window* pSdWindow, ::sd::ViewShell* pViewShell, const uno::Reference& rxController, - const uno::Reference& rxParent) - : ImplInheritanceHelper(pSdWindow, pViewShell, rxController, rxParent) + const rtl::Reference& rpParent) + : ImplInheritanceHelper(pSdWindow, pViewShell, rxController, rpParent) , mpSdViewSh(pViewShell) { UpdateAccessibleName(); @@ -380,11 +380,12 @@ css::uno::Sequence< OUString> SAL_CALL AccessibleDrawDocumentView::getSupportedServiceNames() { ensureAlive(); - const css::uno::Sequence vals { u"com.sun.star.drawing.AccessibleDrawDocumentView"_ustr }; - uno::Sequence aServiceNames = - AccessibleDocumentViewBase::getSupportedServiceNames(); + return { u"com.sun.star.drawing.AccessibleDrawDocumentView"_ustr }; +} - return comphelper::concatSequences(aServiceNames, vals); +sal_Bool SAL_CALL AccessibleDrawDocumentView::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); } //===== XAccessibleGroupPosition ========================================= diff --git a/sd/source/ui/accessibility/AccessibleOutlineEditSource.cxx b/sd/source/ui/accessibility/AccessibleOutlineEditSource.cxx index 90c3776ac689..a52d162a3d86 100644 --- a/sd/source/ui/accessibility/AccessibleOutlineEditSource.cxx +++ b/sd/source/ui/accessibility/AccessibleOutlineEditSource.cxx @@ -168,7 +168,7 @@ namespace accessibility const SdrHint* pSdrHint = static_cast< const SdrHint* >( &rHint ); if( pSdrHint->GetKind() == SdrHintKind::ModelCleared ) { - // model is dying under us, going defunc + // model is dying under us, going defunct bDispose = true; } } diff --git a/sd/source/ui/accessibility/AccessibleOutlineView.cxx b/sd/source/ui/accessibility/AccessibleOutlineView.cxx index 5af146ec70c5..e1e5ce31764e 100644 --- a/sd/source/ui/accessibility/AccessibleOutlineView.cxx +++ b/sd/source/ui/accessibility/AccessibleOutlineView.cxx @@ -39,13 +39,12 @@ using namespace ::com::sun::star::accessibility; namespace accessibility { -AccessibleOutlineView::AccessibleOutlineView ( - ::sd::Window* pSdWindow, - ::sd::OutlineViewShell* pViewShell, +AccessibleOutlineView::AccessibleOutlineView( + ::sd::Window* pSdWindow, ::sd::OutlineViewShell* pViewShell, const uno::Reference& rxController, - const uno::Reference& rxParent) - : AccessibleDocumentViewBase (pSdWindow, pViewShell, rxController, rxParent), - maTextHelper( ::std::unique_ptr< SvxEditSource >() ) + const rtl::Reference& rpParent) + : AccessibleDocumentViewBase(pSdWindow, pViewShell, rxController, rpParent) + , maTextHelper(::std::unique_ptr()) { SolarMutexGuard aGuard; @@ -153,14 +152,6 @@ void SAL_CALL AccessibleOutlineView::removeAccessibleEventListener( const uno::R AccessibleContextBase::removeEventListener(xListener); } -// XServiceInfo - -OUString SAL_CALL - AccessibleOutlineView::getImplementationName() -{ - return u"AccessibleOutlineView"_ustr; -} - //===== XEventListener ====================================================== //===== protected internal ================================================== diff --git a/sd/source/ui/accessibility/AccessiblePageShape.cxx b/sd/source/ui/accessibility/AccessiblePageShape.cxx index 6b55d5713e20..a79061e3cae2 100644 --- a/sd/source/ui/accessibility/AccessiblePageShape.cxx +++ b/sd/source/ui/accessibility/AccessiblePageShape.cxx @@ -36,12 +36,11 @@ using ::com::sun::star::uno::Reference; namespace accessibility { -AccessiblePageShape::AccessiblePageShape ( - uno::Reference xPage, - const uno::Reference& rxParent, - const AccessibleShapeTreeInfo& rShapeTreeInfo) - : AccessibleShape (AccessibleShapeInfo (nullptr, rxParent), rShapeTreeInfo), - mxPage (std::move(xPage)) +AccessiblePageShape::AccessiblePageShape(uno::Reference xPage, + const rtl::Reference& rpParent, + const AccessibleShapeTreeInfo& rShapeTreeInfo) + : AccessibleShape(AccessibleShapeInfo(nullptr, rpParent), rShapeTreeInfo) + , mxPage(std::move(xPage)) { // The main part of the initialization is done in the init method which // has to be called from this constructor's caller. @@ -199,22 +198,6 @@ sal_Int32 SAL_CALL AccessiblePageShape::getBackground() return nColor; } -// XServiceInfo - -OUString SAL_CALL - AccessiblePageShape::getImplementationName() -{ - ensureAlive(); - return u"AccessiblePageShape"_ustr; -} - -css::uno::Sequence< OUString> SAL_CALL - AccessiblePageShape::getSupportedServiceNames() -{ - ensureAlive(); - return AccessibleShape::getSupportedServiceNames(); -} - //===== XComponent ========================================================== void AccessiblePageShape::dispose() diff --git a/sd/source/ui/accessibility/AccessiblePresentationGraphicShape.cxx b/sd/source/ui/accessibility/AccessiblePresentationGraphicShape.cxx index 1d6b5c8e011f..06f274541756 100644 --- a/sd/source/ui/accessibility/AccessiblePresentationGraphicShape.cxx +++ b/sd/source/ui/accessibility/AccessiblePresentationGraphicShape.cxx @@ -38,14 +38,7 @@ AccessiblePresentationGraphicShape::AccessiblePresentationGraphicShape( AccessiblePresentationGraphicShape::~AccessiblePresentationGraphicShape() {} -// XServiceInfo - -OUString SAL_CALL AccessiblePresentationGraphicShape::getImplementationName() -{ - return u"AccessiblePresentationGraphicShape"_ustr; -} - -/// Set this object's name if is different to the current name. +/// Set this object's name if it is different from the current name. OUString AccessiblePresentationGraphicShape::CreateAccessibleBaseName() { OUString sName; diff --git a/sd/source/ui/accessibility/AccessiblePresentationOLEShape.cxx b/sd/source/ui/accessibility/AccessiblePresentationOLEShape.cxx index 08801fcfdb1b..ab18fa3206ef 100644 --- a/sd/source/ui/accessibility/AccessiblePresentationOLEShape.cxx +++ b/sd/source/ui/accessibility/AccessiblePresentationOLEShape.cxx @@ -38,13 +38,6 @@ AccessiblePresentationOLEShape::AccessiblePresentationOLEShape( AccessiblePresentationOLEShape::~AccessiblePresentationOLEShape() {} -// XServiceInfo - -OUString SAL_CALL AccessiblePresentationOLEShape::getImplementationName() -{ - return u"AccessiblePresentationOLEShape"_ustr; -} - /// Set this object's name if it is different to the current name. OUString AccessiblePresentationOLEShape::CreateAccessibleBaseName() { diff --git a/sd/source/ui/accessibility/AccessiblePresentationShape.cxx b/sd/source/ui/accessibility/AccessiblePresentationShape.cxx index fd862feefb31..520ebd623226 100644 --- a/sd/source/ui/accessibility/AccessiblePresentationShape.cxx +++ b/sd/source/ui/accessibility/AccessiblePresentationShape.cxx @@ -39,14 +39,7 @@ AccessiblePresentationShape::AccessiblePresentationShape( AccessiblePresentationShape::~AccessiblePresentationShape() {} -// XServiceInfo - -OUString SAL_CALL AccessiblePresentationShape::getImplementationName() -{ - return u"AccessiblePresentationShape"_ustr; -} - -/// Set this object's name if is different to the current name. +/// Set this object's name if it is different from the current name. OUString AccessiblePresentationShape::CreateAccessibleBaseName() { OUString sName; diff --git a/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx b/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx index 33a868cf35ae..7b1d6dc5e069 100644 --- a/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx +++ b/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx @@ -444,28 +444,6 @@ void SAL_CALL AccessibleSlideSorterView::deselectAccessibleChild (sal_Int64 nChi mrSlideSorter.GetController().GetPageSelector().DeselectPage(pChild->GetPageNumber()); } -// XServiceInfo -OUString SAL_CALL - AccessibleSlideSorterView::getImplementationName() -{ - return u"AccessibleSlideSorterView"_ustr; -} - -sal_Bool SAL_CALL AccessibleSlideSorterView::supportsService (const OUString& sServiceName) -{ - return cppu::supportsService(this, sServiceName); -} - -uno::Sequence< OUString> SAL_CALL - AccessibleSlideSorterView::getSupportedServiceNames() -{ - ThrowIfDisposed (); - - return uno::Sequence { - u"com.sun.star.accessibility.AccessibleContext"_ustr - }; -} - void AccessibleSlideSorterView::ThrowIfDisposed() { if (rBHelper.bDisposed || rBHelper.bInDispose) diff --git a/sd/source/ui/animations/CustomAnimationDialog.cxx b/sd/source/ui/animations/CustomAnimationDialog.cxx index 2cf4051ffafd..1b9e22af5e8c 100644 --- a/sd/source/ui/animations/CustomAnimationDialog.cxx +++ b/sd/source/ui/animations/CustomAnimationDialog.cxx @@ -40,10 +40,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include @@ -89,8 +90,7 @@ using ::com::sun::star::beans::XPropertySet; namespace sd { SdPropertySubControl::SdPropertySubControl(weld::Container* pParent) - : mxBuilder(Application::CreateBuilder(pParent, u"modules/simpress/ui/customanimationfragment.ui"_ustr, - false, reinterpret_cast(SfxViewShell::Current()))) + : mxBuilder(Application::CreateBuilder(pParent, u"modules/simpress/ui/customanimationfragment.ui"_ustr)) , mxContainer(mxBuilder->weld_container(u"EffectFragment"_ustr)) , mpParent(pParent) { @@ -1410,6 +1410,20 @@ void CustomAnimationEffectTabPage::onSoundPreview() if( nPos >= 2 ) try { const OUString aSoundURL( maSoundList[ nPos-2 ] ); + + // Preview the effect's own source only once it is allowed; a gallery or + // browsed sound has a different URL and is left alone. + if( mpSet->getPropertyState( nHandleSoundURL ) != STLPropertyState::Ambiguous ) + { + OUString aEffectSoundURL; + mpSet->getPropertyValue( nHandleSoundURL ) >>= aEffectSoundURL; + bool bAllowed = true; + if( mpSet->getPropertyState( nHandleSoundAllowed ) != STLPropertyState::Ambiguous ) + mpSet->getPropertyValue( nHandleSoundAllowed ) >>= bAllowed; + if( aSoundURL == aEffectSoundURL && !bAllowed ) + return; + } + mxPlayer.set( avmedia::MediaWindow::createPlayer( aSoundURL, u""_ustr ), uno::UNO_SET_THROW ); mxPlayer->start(); } diff --git a/sd/source/ui/animations/CustomAnimationDialog.hxx b/sd/source/ui/animations/CustomAnimationDialog.hxx index cb4a8c0ef767..54abe8f9f097 100644 --- a/sd/source/ui/animations/CustomAnimationDialog.hxx +++ b/sd/source/ui/animations/CustomAnimationDialog.hxx @@ -21,8 +21,8 @@ #include #include +#include #include -#include namespace sd { @@ -66,6 +66,10 @@ const sal_Int32 nHandleCommand = 31; const sal_Int32 nHandleHasVisibleShape = 32; +// the session allowed state of the animation effect sound: true when the sound +// is in the document package or the user has allowed this external sound +const sal_Int32 nHandleSoundAllowed = 33; + const sal_Int32 nPropertyTypeNone = 0; const sal_Int32 nPropertyTypeDirection = 1; const sal_Int32 nPropertyTypeSpokes = 2; diff --git a/sd/source/ui/animations/CustomAnimationPane.cxx b/sd/source/ui/animations/CustomAnimationPane.cxx index 9ab30d2d44e2..e7ba3ddf00b6 100644 --- a/sd/source/ui/animations/CustomAnimationPane.cxx +++ b/sd/source/ui/animations/CustomAnimationPane.cxx @@ -41,6 +41,7 @@ #include #include #include +#include #include #include "STLPropertySet.hxx" #include @@ -75,6 +76,7 @@ #include #include +#include #include #include @@ -1128,7 +1130,9 @@ std::unique_ptr CustomAnimationPane::createSelectionSet() Any aSoundSource; if( pEffect->getAudio().is() ) { - aSoundSource = pEffect->getAudio()->getSource(); + const Any aSource(pEffect->getAudio()->getSource()); + aSoundSource <<= xmloff::getSoundURL(aSource); + addValue( pSet, nHandleSoundAllowed, Any( xmloff::getSoundAllowed(aSource) ) ); addValue( pSet, nHandleSoundVolume, Any( pEffect->getAudio()->getVolume() ) ); // todo addValue( pSet, nHandleSoundEndAfterSlide, makeAny( pEffect->getAudio()->getEndAfterSlide() ) ); // this is now stored at the XCommand parameter sequence @@ -1396,16 +1400,17 @@ void CustomAnimationPane::changeSelection( STLPropertySet const * pResultSet, ST if( !aSoundURL.isEmpty() ) { + // The user chose this sound here, so it is allowed. if( !pEffect->getAudio().is() ) { - pEffect->createAudio( aSoundSource ); + pEffect->createAudio( xmloff::makeSoundSource( aSoundURL, true ) ); bChanged = true; } else { - if( pEffect->getAudio()->getSource() != aSoundSource ) + if( xmloff::getSoundURL( pEffect->getAudio()->getSource() ) != aSoundURL ) { - pEffect->getAudio()->setSource( aSoundSource ); + pEffect->setAudioSource( xmloff::makeSoundSource( aSoundURL, true ) ); bChanged = true; } } diff --git a/sd/source/ui/animations/SlideTransitionPane.cxx b/sd/source/ui/animations/SlideTransitionPane.cxx index ed7d79038ba8..7e7c4c9634bc 100644 --- a/sd/source/ui/animations/SlideTransitionPane.cxx +++ b/sd/source/ui/animations/SlideTransitionPane.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,7 @@ #include #include #include -#include +#include #include #include #include @@ -162,7 +163,12 @@ struct TransitionEffect { rOutPage.SetStopSound( false ); rOutPage.SetSound( mbSoundOn ); + // A transition sound the user picks here is allowed; one left + // unchanged keeps whatever allowed state it already had. + const bool bSoundChanged = maSound != rOutPage.GetSoundFile(); rOutPage.SetSoundFile( maSound ); + if( bSoundChanged ) + rOutPage.SetSoundAllowed( true ); } } if( ! mbLoopSoundAmbiguous ) @@ -369,17 +375,16 @@ sd::TransitionPresetPtr getPreset(const sd::impl::TransitionEffect &rEffect) SlideTransitionPane::SlideTransitionPane( weld::Widget* pParent, ViewShellBase & rBase) : - PanelLayout( pParent, u"SlideTransitionsPanel"_ustr, u"modules/simpress/ui/slidetransitionspanel.ui"_ustr, reinterpret_cast(SfxViewShell::Current())), + PanelLayout( pParent, u"SlideTransitionsPanel"_ustr, u"modules/simpress/ui/slidetransitionspanel.ui"_ustr ), mrBase( rBase ), mpDrawDoc( rBase.GetDocShell() ? rBase.GetDocShell()->GetDoc() : nullptr ), mxTransitionsIconView(m_xBuilder->weld_icon_view("transitions_icons")), mxRepeatAutoFrame(m_xBuilder->weld_frame("repeat_after_frame")), mbHasSelection( false ), mbUpdatingControls( false ), - mbIsMainViewChangePending( false ), maLateInitTimer("sd SlideTransitionPane maLateInitTimer") { - Initialize(mpDrawDoc); + Initialize(); } css::ui::LayoutSize SlideTransitionPane::GetHeightForWidth(const sal_Int32 /*nWidth*/) @@ -388,7 +393,7 @@ css::ui::LayoutSize SlideTransitionPane::GetHeightForWidth(const sal_Int32 /*nWi return css::ui::LayoutSize(nMinimumHeight, -1, nMinimumHeight); } -void SlideTransitionPane::Initialize(SdDrawDocument* pDoc) +void SlideTransitionPane::Initialize() { mxLB_VARIANT = m_xBuilder->weld_combo_box(u"variant_list"_ustr); mxCBX_duration = m_xBuilder->weld_metric_spin_button(u"transition_duration"_ustr, FieldUnit::SECOND); @@ -414,11 +419,8 @@ void SlideTransitionPane::Initialize(SdDrawDocument* pDoc) mxMF_REPEAT_AUTO_AFTER->set_width_chars(nWidthChars); mxCBX_duration->set_width_chars(nWidthChars); - if( pDoc ) - mxModel = pDoc->getUnoModel(); - // TODO: get correct view - if( mxModel.is()) - mxView.set( mxModel->getCurrentController(), uno::UNO_QUERY ); + // Take the controller from the ViewShellBase directly. + mxView = mrBase.GetDrawController(); // set defaults mxCB_AUTO_PREVIEW->set_active(true); // automatic preview on @@ -982,39 +984,27 @@ IMPL_LINK(SlideTransitionPane,EventMultiplexerListener, onChangeCurrentPage(); break; - case EventMultiplexerEventId::MainViewRemoved: - mxView.clear(); - onSelectionChanged(); - onChangeCurrentPage(); - break; - case EventMultiplexerEventId::MainViewAdded: - mbIsMainViewChangePending = true; - break; - - case EventMultiplexerEventId::ConfigurationUpdated: - if (mbIsMainViewChangePending) + // At this moment the controller may not yet been set at model + // or ViewShellBase. Take it from the view shell passed with + // the event. + if (auto pMainViewShell = mrBase.GetMainViewShell().get()) { - mbIsMainViewChangePending = false; - - // At this moment the controller may not yet been set at - // model or ViewShellBase. Take it from the view shell - // passed with the event. - if (mrBase.GetMainViewShell() != nullptr) + if (pMainViewShell->GetShellType() == ViewShell::ST_IMPRESS) { - mxView.set(mrBase.GetController(), css::uno::UNO_QUERY); + mxView = mrBase.GetDrawController(); onSelectionChanged(); onChangeCurrentPage(); + break; } } + [[fallthrough]]; + case EventMultiplexerEventId::MainViewRemoved: + mxView.clear(); + updateControls(); break; default: - if (rEvent.meEventId != EventMultiplexerEventId::Disposing) - { - onSelectionChanged(); - onChangeCurrentPage(); - } break; } } diff --git a/sd/source/ui/annotations/AnnotationPopup.hxx b/sd/source/ui/annotations/AnnotationPopup.hxx index 4956373eacf2..fa8a36a84722 100644 --- a/sd/source/ui/annotations/AnnotationPopup.hxx +++ b/sd/source/ui/annotations/AnnotationPopup.hxx @@ -11,7 +11,6 @@ #include #include -#include namespace sdr::annotation { diff --git a/sd/source/ui/annotations/annotationmanager.cxx b/sd/source/ui/annotations/annotationmanager.cxx index 8790f54673e4..c9f0d85ed4c7 100644 --- a/sd/source/ui/annotations/annotationmanager.cxx +++ b/sd/source/ui/annotations/annotationmanager.cxx @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -48,6 +47,8 @@ #include #include +#include +#include #include #include @@ -381,7 +382,7 @@ void AnnotationManagerImpl::ExecuteDeleteAnnotation(SfxRequest const & rReq) const SfxPoolItem* pPoolItem = nullptr; if( SfxItemState::SET == pArgs->GetItemState( SID_DELETEALLBYAUTHOR_POSTIT, true, &pPoolItem ) ) { - OUString sAuthor( static_cast( pPoolItem )->GetValue() ); + OUString sAuthor( pPoolItem->StaticWhichCast(SID_DELETEALLBYAUTHOR_POSTIT).GetValue() ); DeleteAnnotationsByAuthor( sAuthor ); } } @@ -396,14 +397,14 @@ void AnnotationManagerImpl::ExecuteDeleteAnnotation(SfxRequest const & rReq) if( SfxItemState::SET == pArgs->GetItemState( SID_DELETE_POSTIT, true, &pPoolItem ) ) { uno::Reference xTmpAnnotation; - if (static_cast(pPoolItem)->GetValue() >>= xTmpAnnotation) + if (pPoolItem->StaticWhichCast(SID_DELETE_POSTIT).GetValue() >>= xTmpAnnotation) { xAnnotation = dynamic_cast(xTmpAnnotation.get()); assert(bool(xAnnotation) == bool(xTmpAnnotation) && "must be of concrete type sd::Annotation"); } } if( SfxItemState::SET == pArgs->GetItemState( SID_ATTR_POSTIT_ID, true, &pPoolItem ) ) - nId = static_cast(pPoolItem)->GetValue().toUInt32(); + nId = pPoolItem->StaticWhichCast(SID_ATTR_POSTIT_ID).GetValue().toUInt32(); } if (nId != 0) @@ -536,6 +537,23 @@ void AnnotationManagerImpl::InsertAnnotation(const OUString& rText) rtl::Reference xAnnotation = pPage->createAnnotation(); + // When editing a document loaded from PDF, new annotations take part + // in the PDF threading model (round-tripped via /IRT on export), so + // default the threaded flag on. The PDF import filter does the same + // for every imported annotation. + if (DrawDocShell* pDocShell = mrBase.GetDocShell()) + { + if (SfxMedium* pMedium = pDocShell->GetMedium()) + { + if (const std::shared_ptr& pFilter = pMedium->GetFilter()) + { + const OUString& rName = pFilter->GetFilterName(); + if (rName == u"draw_pdf_import" || rName == u"impress_pdf_import") + xAnnotation->SetThreaded(true); + } + } + } + OUString sAuthor; if (comphelper::LibreOfficeKit::isActive()) sAuthor = mrBase.GetMainViewShell()->GetView()->GetAuthor(); @@ -585,7 +603,7 @@ void AnnotationManagerImpl::ExecuteReplyToAnnotation( SfxRequest const & rReq ) if( SfxItemState::SET == pArgs->GetItemState( SID_ATTR_POSTIT_ID, true, &pPoolItem ) ) { sal_uInt32 nReplyId = 0; // Id of the comment to reply to - nReplyId = static_cast(pPoolItem)->GetValue().toUInt32(); + nReplyId = pPoolItem->StaticWhichCast(SID_ATTR_POSTIT_ID).GetValue().toUInt32(); xAnnotation = GetAnnotationById(nReplyId); } else if( SfxItemState::SET == pArgs->GetItemState( rReq.GetSlot(), true, &pPoolItem ) ) @@ -599,7 +617,7 @@ void AnnotationManagerImpl::ExecuteReplyToAnnotation( SfxRequest const & rReq ) } if( SfxItemState::SET == pArgs->GetItemState( SID_ATTR_POSTIT_TEXT, true, &pPoolItem ) ) - sReplyText = static_cast( pPoolItem )->GetValue(); + sReplyText = pPoolItem->StaticWhichCast(SID_ATTR_POSTIT_TEXT).GetValue(); } auto* pTextApi = getTextApiObject( xAnnotation ); diff --git a/sd/source/ui/annotations/annotationwindow.hxx b/sd/source/ui/annotations/annotationwindow.hxx index 86315def3a97..5a5da64b7264 100644 --- a/sd/source/ui/annotations/annotationwindow.hxx +++ b/sd/source/ui/annotations/annotationwindow.hxx @@ -20,10 +20,11 @@ #pragma once #include +#include #include #include #include -#include +#include #include #include #include diff --git a/sd/source/ui/app/scalectrl.cxx b/sd/source/ui/app/scalectrl.cxx index 70405cbd385b..986dabbc8f7d 100644 --- a/sd/source/ui/app/scalectrl.cxx +++ b/sd/source/ui/app/scalectrl.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/sd/source/ui/app/sdmod1.cxx b/sd/source/ui/app/sdmod1.cxx index 4e2f631fd641..adb46858fc28 100644 --- a/sd/source/ui/app/sdmod1.cxx +++ b/sd/source/ui/app/sdmod1.cxx @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/sd/source/ui/app/sdmod2.cxx b/sd/source/ui/app/sdmod2.cxx index 999292dd6c6d..1a363e1bd3ae 100644 --- a/sd/source/ui/app/sdmod2.cxx +++ b/sd/source/ui/app/sdmod2.cxx @@ -671,7 +671,8 @@ void SdModule::ApplyItemSet( sal_uInt16 nSlot, const SfxItemSet& rSet ) { pDoc->SetUIScale( double(nX) / nY ); if( pViewShell ) - pViewShell->SetRuler( pViewShell->HasRuler() ); + // tdf#155798 - refresh ruler after scale change + pViewShell->GetViewShellBase().UpdateBorder(true); } } } diff --git a/sd/source/ui/app/tmplctrl.cxx b/sd/source/ui/app/tmplctrl.cxx index 231871c859d2..8a0dc2c54615 100644 --- a/sd/source/ui/app/tmplctrl.cxx +++ b/sd/source/ui/app/tmplctrl.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/sd/source/ui/controller/SlideTransitionsToolBoxControl.cxx b/sd/source/ui/controller/SlideTransitionsToolBoxControl.cxx deleted file mode 100644 index 1bc1d04ed30a..000000000000 --- a/sd/source/ui/controller/SlideTransitionsToolBoxControl.cxx +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include -#include -#include -#include -#include -#include -#include "SlideTransitionsToolBoxControl.hxx" - -SlideTransitionsToolBoxControl::SlideTransitionsToolBoxControl() {} - -SlideTransitionsToolBoxControl::~SlideTransitionsToolBoxControl() {} - -void SAL_CALL -SlideTransitionsToolBoxControl::initialize(const css::uno::Sequence& rArguments) -{ - SAL_INFO("sd", "initialize called for TransitionToolBoxControl"); - - svt::ToolboxController::initialize(rArguments); -} - -void SAL_CALL SlideTransitionsToolBoxControl::dispose() -{ - SolarMutexGuard aSolarMutexGuard; - m_xVclBox.disposeAndClear(); - svt::ToolboxController::dispose(); -} - -void SAL_CALL -SlideTransitionsToolBoxControl::statusChanged(const css::frame::FeatureStateEvent& /*rEvent*/) -{ - // Handle status changes if needed -} - -css::uno::Reference SlideTransitionsToolBoxControl::createItemWindow( - const css::uno::Reference& rParent) -{ - css::uno::Reference xItemWindow; - SAL_INFO("sd", "createItemWindow called for SlideTransitionsToolBoxControl"); - - VclPtr pParent = VCLUnoHelper::GetWindow(rParent); - if (pParent) - { - SolarMutexGuard aSolarMutexGuard; - - sd::ViewShellBase* pViewShellBase = nullptr; - if (SfxViewShell* pViewShell = SfxViewShell::Current()) - { - pViewShellBase = dynamic_cast(pViewShell); - } - - if (pViewShellBase) - { - m_xVclBox = VclPtr::Create(pParent, *pViewShellBase); - xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox.get()); - } - } - SAL_INFO("sd", "createItemWindow called for TransitionToolBoxControl"); - - return xItemWindow; -} - -void SAL_CALL SlideTransitionsToolBoxControl::update() -{ - // Update logic if needed -} - -OUString SAL_CALL SlideTransitionsToolBoxControl::getImplementationName() -{ - return u"com.sun.star.comp.sd.SlideTransitionsToolBoxControl"_ustr; -} - -sal_Bool SAL_CALL SlideTransitionsToolBoxControl::supportsService(const OUString& rServiceName) -{ - return cppu::supportsService(this, rServiceName); -} - -css::uno::Sequence SAL_CALL SlideTransitionsToolBoxControl::getSupportedServiceNames() -{ - return { u"com.sun.star.frame.ToolbarController"_ustr }; -} - -// Export function for service registration -extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* -com_sun_star_comp_sd_SlideTransitionsToolBoxControl_get_implementation( - css::uno::XComponentContext* /*rxContext*/, css::uno::Sequence const&) -{ - return cppu::acquire(new SlideTransitionsToolBoxControl()); -} - -SlideTransitionsPaneWrapper::SlideTransitionsPaneWrapper(vcl::Window* pParent, - sd::ViewShellBase& rBase) - : InterimItemWindow(pParent, u"modules/simpress/ui/slidetransitionspanel.ui"_ustr, - u"SlideTransitionsPanel"_ustr, true, - reinterpret_cast(SfxViewShell::Current())) -{ - // Create SlideTransitionsPane with the container widget - m_xTransitionPane = std::make_unique(m_xContainer.get(), rBase); - SetOptimalSize(); - SAL_INFO("sd", "SlideTransitionsPaneWrapper created with SlideTransitionsPane"); -} - -SlideTransitionsPaneWrapper::~SlideTransitionsPaneWrapper() { disposeOnce(); } -void SlideTransitionsPaneWrapper::SetOptimalSize() { SetSizePixel(GetOptimalSize()); } - -void SlideTransitionsPaneWrapper::dispose() -{ - SAL_INFO("sd", "SlideTransitionsPaneWrapper dispose "); - m_xTransitionPane.reset(); - InterimItemWindow::dispose(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sd/source/ui/controller/SlideTransitionsToolBoxControl.hxx b/sd/source/ui/controller/SlideTransitionsToolBoxControl.hxx deleted file mode 100644 index b7e78dcf9ce5..000000000000 --- a/sd/source/ui/controller/SlideTransitionsToolBoxControl.hxx +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include -#include -#include -#include -#include - -// Used to put transition pane to the notebookbar - -class SlideTransitionsPaneWrapper final : public InterimItemWindow -{ -private: - std::unique_ptr m_xTransitionPane; - -public: - SlideTransitionsPaneWrapper(vcl::Window* pParent, sd::ViewShellBase& rBase); - virtual ~SlideTransitionsPaneWrapper() override; - virtual void dispose() override; - void SetOptimalSize(); // Add this method -}; - -class SlideTransitionsToolBoxControl final - : public cppu::ImplInheritanceHelper -{ - VclPtr m_xVclBox; - -public: - SlideTransitionsToolBoxControl(); - virtual ~SlideTransitionsToolBoxControl() override; - - // XStatusListener - virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& rEvent) override; - - // XToolbarController - virtual css::uno::Reference - SAL_CALL createItemWindow(const css::uno::Reference& rParent) override; - - // XInitialization - virtual void SAL_CALL initialize(const css::uno::Sequence& rArguments) override; - - // XComponent - virtual void SAL_CALL dispose() override; - - // XUpdatable - virtual void SAL_CALL update() override; - - // XServiceInfo - virtual OUString SAL_CALL getImplementationName() override; - virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override; - virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sd/source/ui/controller/displaymodecontroller.cxx b/sd/source/ui/controller/displaymodecontroller.cxx index a67e9128c528..45d3b8121005 100644 --- a/sd/source/ui/controller/displaymodecontroller.cxx +++ b/sd/source/ui/controller/displaymodecontroller.cxx @@ -13,8 +13,10 @@ #include #include #include +#include #include #include +#include #include diff --git a/sd/source/ui/controller/slidelayoutcontroller.cxx b/sd/source/ui/controller/slidelayoutcontroller.cxx index d07762e1462f..f46f53c20c35 100644 --- a/sd/source/ui/controller/slidelayoutcontroller.cxx +++ b/sd/source/ui/controller/slidelayoutcontroller.cxx @@ -27,8 +27,11 @@ #include #include #include +#include +#include #include #include +#include #include diff --git a/sd/source/ui/dlg/AnimationChildWindow.cxx b/sd/source/ui/dlg/AnimationChildWindow.cxx index 2f221fc9ef3e..042cb70727f5 100644 --- a/sd/source/ui/dlg/AnimationChildWindow.cxx +++ b/sd/source/ui/dlg/AnimationChildWindow.cxx @@ -30,17 +30,14 @@ SFX_IMPL_DOCKINGWINDOW_WITHID(AnimationChildWindow, SID_ANIMATION_OBJECTS) /** * Derivative from SfxChildWindow as "container" for animator */ -AnimationChildWindow::AnimationChildWindow( - vcl::Window* _pParent, - sal_uInt16 nId, - SfxBindings* pBindings, - SfxChildWinInfo* pInfo ) - : SfxChildWindow( _pParent, nId ) +AnimationChildWindow::AnimationChildWindow(vcl::Window* _pParent, sal_uInt16 nId, + SfxBindings& rBindings, SfxChildWinInfo& rInfo) + : SfxChildWindow(_pParent, nId) { - VclPtr pAnimWin = VclPtr::Create(pBindings, this, _pParent); + VclPtr pAnimWin = VclPtr::Create(rBindings, this, _pParent); SetWindow(pAnimWin); - pAnimWin->Initialize( pInfo ); + pAnimWin->Initialize(rInfo); SetHideNotDelete( true ); } diff --git a/sd/source/ui/dlg/BulletAndPositionDlg.cxx b/sd/source/ui/dlg/BulletAndPositionDlg.cxx index ec1d0ec4e032..0a221cbd1f9b 100644 --- a/sd/source/ui/dlg/BulletAndPositionDlg.cxx +++ b/sd/source/ui/dlg/BulletAndPositionDlg.cxx @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -298,10 +299,10 @@ void SvxBulletAndPositionDlg::SetMetric(FieldUnit eMetric) m_xDistBorderMF->set_digits(1); m_xIndentMF->set_digits(1); } - m_xWidthMF->set_unit(eMetric); - m_xHeightMF->set_unit(eMetric); - m_xDistBorderMF->set_unit(eMetric); - m_xIndentMF->set_unit(eMetric); + SetFieldUnit(*m_xWidthMF, eMetric); + SetFieldUnit(*m_xHeightMF, eMetric); + SetFieldUnit(*m_xDistBorderMF, eMetric); + SetFieldUnit(*m_xIndentMF, eMetric); } SfxItemSet* SvxBulletAndPositionDlg::GetOutputItemSet(SfxItemSet* pSet) @@ -926,7 +927,7 @@ void SvxBulletAndPositionDlg::PopulateGalleryMenu() : double(MAX_BMP_HEIGHT) / static_cast(aSize.Height()); aBitmap.Scale(nScale, nScale); } - pVD->SetOutputSizePixel(aBitmap.GetSizePixel(), false); + pVD->SetOutputSizePixel(aBitmap.GetSizePixel()); pVD->DrawBitmap(Point(), aBitmap); // We want to show only icon names not full path. @@ -1151,7 +1152,7 @@ IMPL_LINK_NOARG(SvxBulletAndPositionDlg, ResetHdl_Impl, weld::Button&, void) Reset(&rFirstStateSet); } -IMPL_LINK(SvxBulletAndPositionDlg, EditModifyHdl_Impl, weld::Entry&, rEdit, void) +IMPL_LINK(SvxBulletAndPositionDlg, EditModifyHdl_Impl, weld::TextWidget&, rEdit, void) { EditModifyHdl_Impl(&rEdit); } @@ -1258,7 +1259,7 @@ IMPL_LINK(SvxBulletAndPositionDlg, RelativeHdl_Impl, weld::Toggleable&, rBox, vo bLastRelative = bOn; } -void SvxBulletAndPositionDlg::EditModifyHdl_Impl(const weld::Entry* pEdit) +void SvxBulletAndPositionDlg::EditModifyHdl_Impl(const weld::TextWidget* pEdit) { bool bPrefixOrSuffix = (pEdit == m_xPrefixED.get()) || (pEdit == m_xSuffixED.get()); bool bStart = pEdit == m_xStartED.get(); diff --git a/sd/source/ui/dlg/LayerTabBar.cxx b/sd/source/ui/dlg/LayerTabBar.cxx index 77e31da47b93..b653b1142863 100644 --- a/sd/source/ui/dlg/LayerTabBar.cxx +++ b/sd/source/ui/dlg/LayerTabBar.cxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/sd/source/ui/dlg/NavigatorChildWindow.cxx b/sd/source/ui/dlg/NavigatorChildWindow.cxx index df580658baa3..ea298d83a71e 100644 --- a/sd/source/ui/dlg/NavigatorChildWindow.cxx +++ b/sd/source/ui/dlg/NavigatorChildWindow.cxx @@ -44,20 +44,20 @@ static void RequestNavigatorUpdate (SfxBindings const * pBindings) } } -SdNavigatorFloat::SdNavigatorFloat(SfxBindings* _pBindings, SfxChildWindow* _pMgr, - vcl::Window* _pParent, SfxChildWinInfo* pInfo) - : SfxNavigator(_pBindings, _pMgr, _pParent, pInfo) - , m_xNavWin(std::make_unique(m_xContainer.get(), _pBindings, this)) +SdNavigatorFloat::SdNavigatorFloat(SfxBindings& rBindings, SfxChildWindow* _pMgr, + vcl::Window* _pParent, SfxChildWinInfo& rInfo) + : SfxNavigator(rBindings, _pMgr, _pParent, rInfo) + , m_xNavWin(std::make_unique(m_xContainer.get(), &rBindings, this)) , m_bSetInitialFocusOnActivate(true) { - m_xNavWin->SetUpdateRequestFunctor( - [_pBindings] () { return RequestNavigatorUpdate(_pBindings); }); + SfxBindings* pBindings = &rBindings; + m_xNavWin->SetUpdateRequestFunctor([pBindings]() { return RequestNavigatorUpdate(pBindings); }); SetMinOutputSizePixel(GetOptimalSize()); // Set the toolbox navigation button tooltips // Tunnel through the controller to obtain a ViewShellBase. - css::uno::Reference xFrame = _pBindings->GetActiveFrame(); + css::uno::Reference xFrame = rBindings.GetActiveFrame(); ViewShellBase* pViewShellBase = nullptr; rtl::Reference pController = dynamic_cast(xFrame->getController().get()); @@ -98,11 +98,11 @@ SdNavigatorFloat::~SdNavigatorFloat() SFX_IMPL_DOCKINGWINDOW(SdNavigatorWrapper, SID_NAVIGATOR); -SdNavigatorWrapper::SdNavigatorWrapper(vcl::Window *_pParent, sal_uInt16 nId, - SfxBindings* pBindings, SfxChildWinInfo* pInfo) +SdNavigatorWrapper::SdNavigatorWrapper(vcl::Window* _pParent, sal_uInt16 nId, + SfxBindings& rBindings, SfxChildWinInfo& rInfo) : SfxNavigatorWrapper(_pParent, nId) { - SetWindow(VclPtr::Create(pBindings, this, _pParent, pInfo)); + SetWindow(VclPtr::Create(rBindings, this, _pParent, rInfo)); Initialize(); } diff --git a/sd/source/ui/dlg/PaneChildWindows.cxx b/sd/source/ui/dlg/PaneChildWindows.cxx index 33b0a2f40ef4..38a88084ac36 100644 --- a/sd/source/ui/dlg/PaneChildWindows.cxx +++ b/sd/source/ui/dlg/PaneChildWindows.cxx @@ -37,27 +37,20 @@ SFX_IMPL_DOCKINGWINDOW_WITHID(BottomPaneImpressChildWindow, SID_BOTTOM_PANE_IMPR SFX_IMPL_DOCKINGWINDOW_WITHID(LeftPaneDrawChildWindow, SID_LEFT_PANE_DRAW) //===== PaneChildWindow ======================================================= -PaneChildWindow::PaneChildWindow ( - vcl::Window* pParentWindow, - sal_uInt16 nId, - SfxBindings* pBindings, - SfxChildWinInfo* pInfo, - TranslateId pTitleBarResId, - SfxChildAlignment eAlignment) - : SfxChildWindow (pParentWindow, nId) +PaneChildWindow::PaneChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo, TranslateId pTitleBarResId, + SfxChildAlignment eAlignment) + : SfxChildWindow(pParentWindow, nId) { - SetWindow( VclPtr::Create( - pBindings, - this, - pParentWindow, - SdResId(pTitleBarResId))); + SetWindow(VclPtr::Create(rBindings, this, pParentWindow, + SdResId(pTitleBarResId))); SetAlignment(eAlignment); SfxDockingWindow* pDockingWindow = static_cast(GetWindow()); pDockingWindow->EnableInput(); - pDockingWindow->Initialize(pInfo); + pDockingWindow->Initialize(rInfo); SetHideNotDelete(true); - ViewShellBase* pBase = ViewShellBase::GetViewShellBase(pBindings->GetDispatcher()->GetFrame()); + ViewShellBase* pBase = ViewShellBase::GetViewShellBase(rBindings.GetDispatcher()->GetFrame()); if (pBase != nullptr) { framework::FrameworkHelper::Instance(*pBase)->UpdateConfiguration(); @@ -76,50 +69,30 @@ PaneChildWindow::~PaneChildWindow() } //===== LeftPaneImpressChildWindow ============================================ -LeftPaneImpressChildWindow::LeftPaneImpressChildWindow ( - vcl::Window* pParentWindow, - sal_uInt16 nId, - SfxBindings* pBindings, - SfxChildWinInfo* pInfo) - : PaneChildWindow( - pParentWindow, - nId, - pBindings, - pInfo, - STR_LEFT_PANE_IMPRESS_TITLE, - SfxChildAlignment::LEFT) +LeftPaneImpressChildWindow::LeftPaneImpressChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, + SfxBindings& rBindings, + SfxChildWinInfo& rInfo) + : PaneChildWindow(pParentWindow, nId, rBindings, rInfo, STR_LEFT_PANE_IMPRESS_TITLE, + SfxChildAlignment::LEFT) { } //===== BottomPaneImpressChildWindow ============================================ -BottomPaneImpressChildWindow::BottomPaneImpressChildWindow ( - vcl::Window* pParentWindow, - sal_uInt16 nId, - SfxBindings* pBindings, - SfxChildWinInfo* pInfo) +BottomPaneImpressChildWindow::BottomPaneImpressChildWindow(vcl::Window* pParentWindow, + sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo) : PaneChildWindow( - pParentWindow, - nId, - pBindings, - pInfo, - STR_NOTES_MODE, // TODO this isn't a specific translatable string for this view. - SfxChildAlignment::BOTTOM) + pParentWindow, nId, rBindings, rInfo, + STR_NOTES_MODE, // TODO this isn't a specific translatable string for this view. + SfxChildAlignment::BOTTOM) { } //===== LeftPaneDrawChildWindow =============================================== -LeftPaneDrawChildWindow::LeftPaneDrawChildWindow ( - vcl::Window* pParentWindow, - sal_uInt16 nId, - SfxBindings* pBindings, - SfxChildWinInfo* pInfo) - : PaneChildWindow( - pParentWindow, - nId, - pBindings, - pInfo, - STR_LEFT_PANE_DRAW_TITLE, - SfxChildAlignment::LEFT) +LeftPaneDrawChildWindow::LeftPaneDrawChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, + SfxBindings& rBindings, SfxChildWinInfo& rInfo) + : PaneChildWindow(pParentWindow, nId, rBindings, rInfo, STR_LEFT_PANE_DRAW_TITLE, + SfxChildAlignment::LEFT) { } diff --git a/sd/source/ui/dlg/PhotoAlbumDialog.cxx b/sd/source/ui/dlg/PhotoAlbumDialog.cxx index ea3c72b8caae..f1bbecc9e87f 100644 --- a/sd/source/ui/dlg/PhotoAlbumDialog.cxx +++ b/sd/source/ui/dlg/PhotoAlbumDialog.cxx @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/sd/source/ui/dlg/PhotoAlbumDialog.hxx b/sd/source/ui/dlg/PhotoAlbumDialog.hxx index 225e1573409b..6b17b230288e 100644 --- a/sd/source/ui/dlg/PhotoAlbumDialog.hxx +++ b/sd/source/ui/dlg/PhotoAlbumDialog.hxx @@ -11,10 +11,11 @@ #include +#include +#include #include #include #include -#include #include #include diff --git a/sd/source/ui/dlg/RemoteDialog.cxx b/sd/source/ui/dlg/RemoteDialog.cxx index b8584f349bf2..0e4a61b35a3c 100644 --- a/sd/source/ui/dlg/RemoteDialog.cxx +++ b/sd/source/ui/dlg/RemoteDialog.cxx @@ -12,6 +12,7 @@ #include #include +#include using namespace ::sd; diff --git a/sd/source/ui/dlg/RemoteDialog.hxx b/sd/source/ui/dlg/RemoteDialog.hxx index c7c53e418abd..45d6edd3b5ad 100644 --- a/sd/source/ui/dlg/RemoteDialog.hxx +++ b/sd/source/ui/dlg/RemoteDialog.hxx @@ -8,8 +8,8 @@ */ #pragma once +#include #include -#include #include "RemoteDialogClientBox.hxx" diff --git a/sd/source/ui/dlg/RemoteDialogClientBox.cxx b/sd/source/ui/dlg/RemoteDialogClientBox.cxx index 3eac5443176e..939fd32c1910 100644 --- a/sd/source/ui/dlg/RemoteDialogClientBox.cxx +++ b/sd/source/ui/dlg/RemoteDialogClientBox.cxx @@ -24,6 +24,7 @@ #include #include +#include namespace sd { diff --git a/sd/source/ui/dlg/RemoteDialogClientBox.hxx b/sd/source/ui/dlg/RemoteDialogClientBox.hxx index 88a4e57d0ba9..7473d5ec3ec1 100644 --- a/sd/source/ui/dlg/RemoteDialogClientBox.hxx +++ b/sd/source/ui/dlg/RemoteDialogClientBox.hxx @@ -20,9 +20,10 @@ #pragma once #include +#include +#include #include #include -#include #include diff --git a/sd/source/ui/dlg/SelectLayerDlg.cxx b/sd/source/ui/dlg/SelectLayerDlg.cxx index a8fdb03ca08b..1d6bc59da877 100644 --- a/sd/source/ui/dlg/SelectLayerDlg.cxx +++ b/sd/source/ui/dlg/SelectLayerDlg.cxx @@ -21,7 +21,6 @@ #include #include #include -#include SdSelectLayerDlg::SdSelectLayerDlg(weld::Window* pParent) : GenericDialogController(pParent, u"modules/sdraw/ui/selectlayerdialog.ui"_ustr, diff --git a/sd/source/ui/dlg/SpellDialogChildWindow.cxx b/sd/source/ui/dlg/SpellDialogChildWindow.cxx index a9f3aa6e14e3..7b189aae2be5 100644 --- a/sd/source/ui/dlg/SpellDialogChildWindow.cxx +++ b/sd/source/ui/dlg/SpellDialogChildWindow.cxx @@ -31,14 +31,12 @@ namespace sd { SFX_IMPL_CHILDWINDOW_WITHID(SpellDialogChildWindow, SID_SPELL_DIALOG) -SpellDialogChildWindow::SpellDialogChildWindow ( - vcl::Window* _pParent, - sal_uInt16 nId, - SfxBindings* pBindings, - SAL_UNUSED_PARAMETER SfxChildWinInfo* /*pInfo*/) - : svx::SpellDialogChildWindow (_pParent, nId, pBindings), - mpSdOutliner (nullptr), - mbOwnOutliner (false) +SpellDialogChildWindow::SpellDialogChildWindow(vcl::Window* _pParent, sal_uInt16 nId, + SfxBindings& rBindings, + SAL_UNUSED_PARAMETER SfxChildWinInfo& /*rInfo*/) + : svx::SpellDialogChildWindow(_pParent, nId, &rBindings) + , mpSdOutliner(nullptr) + , mbOwnOutliner(false) { ProvideOutliner(); } diff --git a/sd/source/ui/dlg/animobjs.cxx b/sd/source/ui/dlg/animobjs.cxx index 2bacd0583dfc..5a786374d6b9 100644 --- a/sd/source/ui/dlg/animobjs.cxx +++ b/sd/source/ui/dlg/animobjs.cxx @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -121,9 +120,9 @@ void SdDisplay::SetDrawingArea(weld::DrawingArea* pDrawingArea) /** * AnimationWindow - FloatingWindow */ -AnimationWindow::AnimationWindow(SfxBindings* pInBindings, SfxChildWindow *pCW, vcl::Window* pParent) - : SfxDockingWindow(pInBindings, pCW, pParent, - u"DockingAnimation"_ustr, u"modules/simpress/ui/dockinganimation.ui"_ustr) +AnimationWindow::AnimationWindow(SfxBindings& rBindings, SfxChildWindow* pCW, vcl::Window* pParent) + : SfxDockingWindow(rBindings, pCW, pParent, u"DockingAnimation"_ustr, + u"modules/simpress/ui/dockinganimation.ui"_ustr) , m_xCtlDisplay(new SdDisplay) , m_xCtlDisplayWin(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, *m_xCtlDisplay)) , m_xBtnFirst(m_xBuilder->weld_button(u"first"_ustr)) @@ -161,7 +160,7 @@ AnimationWindow::AnimationWindow(SfxBindings* pInBindings, SfxChildWindow *pCW, rtl::Reference pPage = pMyDoc->AllocSdPage(false); pMyDoc->InsertPage(pPage.get()); - pControllerItem.reset( new AnimationControllerItem( SID_ANIMATOR_STATE, this, pInBindings ) ); + pControllerItem.reset(new AnimationControllerItem(SID_ANIMATOR_STATE, this, &rBindings)); m_xBtnFirst->connect_clicked( LINK( this, AnimationWindow, ClickFirstHdl ) ); m_xBtnReverse->connect_clicked( LINK( this, AnimationWindow, ClickPlayHdl ) ); diff --git a/sd/source/ui/dlg/brkdlg.cxx b/sd/source/ui/dlg/brkdlg.cxx index 3c38812fd4fd..5119e5902e3f 100644 --- a/sd/source/ui/dlg/brkdlg.cxx +++ b/sd/source/ui/dlg/brkdlg.cxx @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/sd/source/ui/dlg/copydlg.cxx b/sd/source/ui/dlg/copydlg.cxx index 5432288d7022..5c8c22cd91fe 100644 --- a/sd/source/ui/dlg/copydlg.cxx +++ b/sd/source/ui/dlg/copydlg.cxx @@ -23,10 +23,11 @@ #include #include #include +#include #include -#include #include +#include #include #include #include @@ -34,6 +35,9 @@ #include #include #include +#include + +#include namespace sd { @@ -56,6 +60,9 @@ CopyDlg::CopyDlg(weld::Window* pWindow, const SfxItemSet& rInAttrs, ::sd::View* , m_xBtnSetDefault(m_xBuilder->weld_button(u"default"_ustr)) , m_xLbStartColor(new ColorListBox(m_xBuilder->weld_menu_button(u"start"_ustr), [this]{ return m_xDialog.get(); } )) , m_xLbEndColor(new ColorListBox(m_xBuilder->weld_menu_button(u"end"_ustr), [this]{ return m_xDialog.get(); } )) + , m_xRbRGB(m_xBuilder->weld_radio_button(u"rgb"_ustr)) + , m_xRbHSLInc(m_xBuilder->weld_radio_button(u"hslinc"_ustr)) + , m_xRbHSLDec(m_xBuilder->weld_radio_button(u"hsldec"_ustr)) { m_xLbStartColor->SetSelectHdl( LINK( this, CopyDlg, SelectColorHdl ) ); m_xBtnSetViewData->connect_clicked( LINK( this, CopyDlg, SetViewData ) ); @@ -74,6 +81,8 @@ CopyDlg::CopyDlg(weld::Window* pWindow, const SfxItemSet& rInAttrs, ::sd::View* CopyDlg::~CopyDlg() { SvtViewOptions aDlgOpt(EViewType::Dialog, m_xDialog->get_help_id()); + const sal_uInt16 nColorInterpolationKind( + m_xRbHSLInc->get_active() ? 1 : m_xRbHSLDec->get_active() ? 2 : 0); OUString sStr = OUString::number(m_xNumFldCopies->get_value()) + OUStringChar(TOKEN) + OUString::number(m_xMtrFldMoveX->get_value(FieldUnit::NONE)) + OUStringChar(TOKEN) + @@ -82,12 +91,13 @@ CopyDlg::~CopyDlg() OUString::number(m_xMtrFldWidth->get_value(FieldUnit::NONE)) + OUStringChar(TOKEN) + OUString::number(m_xMtrFldHeight->get_value(FieldUnit::NONE)) + OUStringChar(TOKEN) + OUString::number(static_cast(m_xLbStartColor->GetSelectEntryColor())) + OUStringChar(TOKEN) + - OUString::number(static_cast(m_xLbEndColor->GetSelectEntryColor())); + OUString::number(static_cast(m_xLbEndColor->GetSelectEntryColor())) + OUStringChar(TOKEN) + + OUString::number(nColorInterpolationKind); aDlgOpt.SetUserItem(u"UserItem"_ustr, css::uno::Any(sStr)); } /** - * reads provided item set or evaluate ini string + * reads provided item set or evaluates ini string */ void CopyDlg::Reset() { @@ -153,6 +163,7 @@ void CopyDlg::Reset() Color aColor = pPoolItem->GetColorValue(); m_xLbStartColor->SelectEntry( aColor ); m_xLbEndColor->SelectEntry( aColor ); + m_xRbRGB->set_active(true); } else { @@ -171,10 +182,25 @@ void CopyDlg::Reset() m_xMtrFldAngle->set_value(o3tl::toInt64(o3tl::getToken(aStr, 0, TOKEN, nIdx)), FieldUnit::NONE); m_xMtrFldWidth->set_value(o3tl::toInt64(o3tl::getToken(aStr, 0, TOKEN, nIdx)), FieldUnit::NONE); m_xMtrFldHeight->set_value(o3tl::toInt64(o3tl::getToken(aStr, 0, TOKEN, nIdx)), FieldUnit::NONE); - m_xLbStartColor->SelectEntry( Color( ColorTransparency, o3tl::toUInt32(o3tl::getToken(aStr, 0, TOKEN, nIdx)) ) ); - m_xLbEndColor->SelectEntry( Color( ColorTransparency, o3tl::toUInt32(o3tl::getToken(aStr, 0, TOKEN, nIdx)) ) ); + // tdf#173141: in duplicate dialog, we want to retrieve previously selected start and stop color + // only if the shape uses solid color (and not gradient or bitmap for example) + if ( const XFillStyleItem* pFillStyleItem = mrOutAttrs.GetItemIfSet( XATTR_FILLSTYLE ) ) + { + css::drawing::FillStyle eStyle = pFillStyleItem->GetValue(); + if( eStyle == css::drawing::FillStyle_SOLID ) + { + m_xLbStartColor->SelectEntry( Color( ColorTransparency, o3tl::toUInt32(o3tl::getToken(aStr, 0, TOKEN, nIdx)) ) ); + m_xLbEndColor->SelectEntry( Color( ColorTransparency, o3tl::toUInt32(o3tl::getToken(aStr, 0, TOKEN, nIdx)) ) ); + const sal_Unicode sKind = nIdx >= 0 ? o3tl::getToken(aStr, 0, TOKEN, nIdx)[0] : '0'; + if (sKind == '0') + m_xRbRGB->set_active(true); + else if (sKind == '1') + m_xRbHSLInc->set_active(true); + else + m_xRbHSLDec->set_active(true); + } + } } - } /** @@ -198,6 +224,15 @@ void CopyDlg::GetAttr( SfxItemSet& rOutAttrs ) rOutAttrs.Put(XColorItem(ATTR_COPY_START_COLOR, aColor.m_aName, aColor.m_aColor)); aColor = m_xLbEndColor->GetSelectedEntry(); rOutAttrs.Put(XColorItem(ATTR_COPY_END_COLOR, aColor.m_aName, aColor.m_aColor)); + + ColorInterpolationKind eKind; + if (m_xRbRGB->get_active()) + eKind = ColorInterpolationKind::RGB; + else if (m_xRbHSLInc->get_active()) + eKind = ColorInterpolationKind::HSLInc; + else + eKind = ColorInterpolationKind::HSLDec; + rOutAttrs.Put(SfxUInt16Item( ATTR_COPY_COLOR_TRANSKIND, static_cast(eKind))); } /** @@ -232,7 +267,9 @@ IMPL_LINK_NOARG(CopyDlg, SetViewData, weld::Button&, void) { Color aColor = pPoolItem->GetColorValue(); m_xLbStartColor->SelectEntry( aColor ); + m_xLbEndColor->SelectEntry(aColor); } + m_xRbRGB->set_active(true); } /** @@ -251,13 +288,12 @@ IMPL_LINK_NOARG(CopyDlg, SetDefault, weld::Button&, void) SetMetricValue( *m_xMtrFldWidth, tools::Long(nValue / mfUIScale), MapUnit::Map100thMM); SetMetricValue( *m_xMtrFldHeight, tools::Long(nValue / mfUIScale), MapUnit::Map100thMM); - // set color attribute - if( const XColorItem* pPoolItem = mrOutAttrs.GetItemIfSet( ATTR_COPY_START_COLOR ) ) - { - Color aColor = pPoolItem->GetColorValue(); - m_xLbStartColor->SelectEntry( aColor ); - m_xLbEndColor->SelectEntry( aColor ); - } + // clear color attributes + m_xLbStartColor->SelectEntry(COL_AUTO); + m_xLbStartColor->SetNoSelection(); + m_xLbEndColor->SelectEntry(COL_AUTO); + m_xLbEndColor->SetNoSelection(); + m_xRbRGB->set_active(true); } } // end of namespace sd diff --git a/sd/source/ui/dlg/custsdlg.cxx b/sd/source/ui/dlg/custsdlg.cxx index fa39520ee0a6..33887366eafb 100644 --- a/sd/source/ui/dlg/custsdlg.cxx +++ b/sd/source/ui/dlg/custsdlg.cxx @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -334,15 +333,15 @@ IMPL_LINK(SdDefineCustomShowDlg, ClickButtonHdl4, weld::ItemView&, rListBox, voi ClickButtonHdl2(&rListBox); } -IMPL_LINK( SdDefineCustomShowDlg, ClickButtonEditHdl, weld::Entry&, rEdit, void ) +IMPL_LINK(SdDefineCustomShowDlg, ClickButtonEditHdl, weld::TextWidget&, rEdit, void) { ClickButtonHdl2(&rEdit); } // ButtonHdl() -void SdDefineCustomShowDlg::ClickButtonHdl2(void const * p) +void SdDefineCustomShowDlg::ClickButtonHdl2(const weld::Widget* pWidget) { - if( p == m_xBtnAdd.get() ) + if (pWidget == m_xBtnAdd.get()) { auto aRows = m_xLbPages->get_selected_rows(); if (!aRows.empty()) @@ -365,7 +364,7 @@ void SdDefineCustomShowDlg::ClickButtonHdl2(void const * p) bModified = true; } } - else if (p == m_xBtnRemove.get()) + else if (pWidget == m_xBtnRemove.get()) { int nPos = m_xLbCustomPages->get_selected_index(); if (nPos != -1) @@ -375,7 +374,7 @@ void SdDefineCustomShowDlg::ClickButtonHdl2(void const * p) bModified = true; } } - else if( p == m_xEdtName.get() ) + else if (pWidget == m_xEdtName.get()) { bModified = true; } diff --git a/sd/source/ui/dlg/dlgpage.cxx b/sd/source/ui/dlg/dlgpage.cxx index 14eb222005b8..8381bd80cb6c 100644 --- a/sd/source/ui/dlg/dlgpage.cxx +++ b/sd/source/ui/dlg/dlgpage.cxx @@ -43,6 +43,9 @@ SdPageDlg::SdPageDlg(SfxObjectShell const* pDocSh, weld::Window* pParent, const u"DrawPageDialog"_ustr, pAttr) , mbIsImpressDoc(bIsImpressDoc) { + if (mbIsImpressDoc) + set_title(SdResId(STR_SLIDE_PROPERTIES)); + SvxColorListItem const* pColorListItem = pDocSh->GetItem(SID_COLOR_TABLE); SvxGradientListItem const* pGradientListItem = pDocSh->GetItem(SID_GRADIENT_LIST); SvxBitmapListItem const* pBitmapListItem = pDocSh->GetItem(SID_BITMAP_LIST); diff --git a/sd/source/ui/dlg/headerfooterdlg.cxx b/sd/source/ui/dlg/headerfooterdlg.cxx index ed074b589eff..eefb8a45f38b 100644 --- a/sd/source/ui/dlg/headerfooterdlg.cxx +++ b/sd/source/ui/dlg/headerfooterdlg.cxx @@ -41,8 +41,11 @@ #include #include #include +#include #include #include +#include +#include #include #include diff --git a/sd/source/ui/dlg/navigatr.cxx b/sd/source/ui/dlg/navigatr.cxx index 995a7358637c..8164bb233ce5 100644 --- a/sd/source/ui/dlg/navigatr.cxx +++ b/sd/source/ui/dlg/navigatr.cxx @@ -49,11 +49,13 @@ #include #include -#include - #include #include #include +#include +#include +#include +#include #include #include @@ -77,12 +79,6 @@ SdNavigatorWin::SdNavigatorWin(weld::Widget* pParent, SfxBindings* pInBindings, , meDragType ( NAVIGATOR_DRAGTYPE_EMBEDDED ) , mpBindings ( pInBindings ) { - if (comphelper::LibreOfficeKit::isActive()) - { - sal_uInt64 nShellId = reinterpret_cast(SfxViewShell::Current()); - jsdialog::SendNavigatorForView(nShellId); - } - mxTlbObjects->SetViewFrame( mpBindings->GetDispatcher()->GetFrame() ); mxTlbObjects->connect_item_activated(LINK(this, SdNavigatorWin, ClickObjectHdl)); diff --git a/sd/source/ui/dlg/paragr.cxx b/sd/source/ui/dlg/paragr.cxx index 32eed6b24b20..b04024611e48 100644 --- a/sd/source/ui/dlg/paragr.cxx +++ b/sd/source/ui/dlg/paragr.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include diff --git a/sd/source/ui/dlg/prltempl.cxx b/sd/source/ui/dlg/prltempl.cxx index 776e2de9bc7a..889da808ba31 100644 --- a/sd/source/ui/dlg/prltempl.cxx +++ b/sd/source/ui/dlg/prltempl.cxx @@ -40,25 +40,32 @@ #include #include -#define IS_OUTLINE(x) (x >= PresentationObjects::Outline_1 && x <= PresentationObjects::Outline_9) +namespace +{ +bool lcl_isOutline(PresentationObjects eType) +{ + return eType >= PresentationObjects::Outline_1 && eType <= PresentationObjects::Outline_9; +} +} /** * Constructor of Tab dialog: appends pages to the dialog */ -SdPresLayoutTemplateDlg::SdPresLayoutTemplateDlg(SfxObjectShell const * pDocSh, - weld::Window* pParent, - bool bBackground, - SfxStyleSheetBase& rStyleBase, - PresentationObjects _ePO, - SfxStyleSheetBasePool* pSSPool) - : SfxTabDialogController(pParent, u"modules/sdraw/ui/drawprtldialog.ui"_ustr, u"DrawPRTLDialog"_ustr) +SdPresLayoutTemplateDlg::SdPresLayoutTemplateDlg(SfxObjectShell const* pDocSh, + weld::Window* pParent, bool bBackground, + SfxStyleSheetBase& rStyleBase, + PresentationObjects _ePO, + SfxStyleSheetBasePool* pSSPool) + : SfxTabDialogController(pParent, u"modules/sdraw/ui/drawprtldialog.ui"_ustr, + u"DrawPRTLDialog"_ustr) , mpDocShell(pDocSh) - , ePO(_ePO) - , aInputSet(*rStyleBase.GetItemSet().GetPool(), svl::Items) + , m_ePO(_ePO) + , m_aInputSet(*rStyleBase.GetItemSet().GetPool(), + svl::Items) { const SfxItemSet* pOrgSet(&rStyleBase.GetItemSet()); - if( IS_OUTLINE(ePO)) + if (lcl_isOutline(m_ePO)) { // Unfortunately, the Itemsets of our style sheets are not discrete... const WhichRangesContainer& pPtr = pOrgSet->GetRanges(); @@ -74,36 +81,36 @@ SdPresLayoutTemplateDlg::SdPresLayoutTemplateDlg(SfxObjectShell const * pDocSh, p2 = pPtr[i+1].second; ++i; } - aInputSet.MergeRange( p1, p2 ); + m_aInputSet.MergeRange(p1, p2); } - aInputSet.Put( rStyleBase.GetItemSet() ); + m_aInputSet.Put(rStyleBase.GetItemSet()); // need parent-relationship const SfxItemSet* pParentItemSet = rStyleBase.GetItemSet().GetParent(); if( pParentItemSet ) - aInputSet.SetParent( pParentItemSet ); + m_aInputSet.SetParent(pParentItemSet); - pOutSet.reset( new SfxItemSet( rStyleBase.GetItemSet() ) ); - pOutSet->ClearItem(); + m_pOutSet.reset(new SfxItemSet(rStyleBase.GetItemSet())); + m_pOutSet->ClearItem(); // If there is no bullet item in this stylesheet, we get it // from 'Outline 1' style sheet. const SfxPoolItem *pItem = nullptr; - if( SfxItemState::SET != aInputSet.GetItemState(EE_PARA_NUMBULLET, false, &pItem )) + if (SfxItemState::SET != m_aInputSet.GetItemState(EE_PARA_NUMBULLET, false, &pItem)) { OUString aStyleName(SdResId(STR_PSEUDOSHEET_OUTLINE) + " 1"); SfxStyleSheetBase* pFirstStyleSheet = pSSPool->Find( aStyleName, SfxStyleFamily::Pseudo); if(pFirstStyleSheet) if( SfxItemState::SET == pFirstStyleSheet->GetItemSet().GetItemState(EE_PARA_NUMBULLET, false, &pItem) ) - aInputSet.Put( *pItem ); + m_aInputSet.Put(*pItem); } // preselect selected layer in dialog - aInputSet.Put( SfxUInt16Item( SID_PARAM_CUR_NUM_LEVEL, 1<GetItem( SID_DASH_LIST ); SvxLineEndListItem const *pLineEndListItem = mpDocShell->GetItem( SID_LINEEND_LIST ); - pColorTab = pColorListItem->GetColorList(); - pDashList = pDashListItem->GetDashList(); - pLineEndList = pLineEndListItem->GetLineEndList(); - pGradientList = pGradientListItem->GetGradientList(); - pHatchingList = pHatchListItem->GetHatchList(); - pBitmapList = pBitmapListItem->GetBitmapList(); - pPatternList = pPatternListItem->GetPatternList(); + m_pColorTab = pColorListItem->GetColorList(); + m_pDashList = pDashListItem->GetDashList(); + m_pLineEndList = pLineEndListItem->GetLineEndList(); + m_pGradientList = pGradientListItem->GetGradientList(); + m_pHatchingList = pHatchListItem->GetHatchList(); + m_pBitmapList = pBitmapListItem->GetBitmapList(); + m_pPatternList = pPatternListItem->GetPatternList(); SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); @@ -182,7 +189,7 @@ SdPresLayoutTemplateDlg::SdPresLayoutTemplateDlg(SfxObjectShell const * pDocSh, // set title and add corresponding pages to dialog OUString aTitle; - switch( ePO ) + switch (m_ePO) { case PresentationObjects::Title: aTitle = SdResId(STR_PSEUDOSHEET_TITLE); @@ -209,9 +216,10 @@ SdPresLayoutTemplateDlg::SdPresLayoutTemplateDlg(SfxObjectShell const * pDocSh, case PresentationObjects::Outline_7: case PresentationObjects::Outline_8: case PresentationObjects::Outline_9: - aTitle = SdResId(STR_PSEUDOSHEET_OUTLINE) + " " + - OUString::number( static_cast(ePO) - static_cast(PresentationObjects::Outline_1) + 1 ); - break; + aTitle = SdResId(STR_PSEUDOSHEET_OUTLINE) + " " + + OUString::number(static_cast(m_ePO) + - static_cast(PresentationObjects::Outline_1) + 1); + break; case PresentationObjects::Notes: aTitle = SdResId(STR_PSEUDOSHEET_NOTES); @@ -226,23 +234,23 @@ SdPresLayoutTemplateDlg::~SdPresLayoutTemplateDlg() void SdPresLayoutTemplateDlg::PageCreated(const OUString& rId, SfxTabPage &rPage) { - SfxAllItemSet aSet(*(aInputSet.GetPool())); + SfxAllItemSet aSet(*(m_aInputSet.GetPool())); if (rId == "line") { - aSet.Put (SvxColorListItem(pColorTab,SID_COLOR_TABLE)); - aSet.Put (SvxDashListItem(pDashList,SID_DASH_LIST)); - aSet.Put (SvxLineEndListItem(pLineEndList,SID_LINEEND_LIST)); + aSet.Put(SvxColorListItem(m_pColorTab, SID_COLOR_TABLE)); + aSet.Put(SvxDashListItem(m_pDashList, SID_DASH_LIST)); + aSet.Put(SvxLineEndListItem(m_pLineEndList, SID_LINEEND_LIST)); aSet.Put (SfxUInt16Item(SID_DLG_TYPE,1)); rPage.PageCreated(aSet); } else if (rId == "area") { - aSet.Put (SvxColorListItem(pColorTab,SID_COLOR_TABLE)); - aSet.Put (SvxGradientListItem(pGradientList,SID_GRADIENT_LIST)); - aSet.Put (SvxHatchListItem(pHatchingList,SID_HATCH_LIST)); - aSet.Put (SvxBitmapListItem(pBitmapList,SID_BITMAP_LIST)); - aSet.Put (SvxPatternListItem(pPatternList,SID_PATTERN_LIST)); + aSet.Put(SvxColorListItem(m_pColorTab, SID_COLOR_TABLE)); + aSet.Put(SvxGradientListItem(m_pGradientList, SID_GRADIENT_LIST)); + aSet.Put(SvxHatchListItem(m_pHatchingList, SID_HATCH_LIST)); + aSet.Put(SvxBitmapListItem(m_pBitmapList, SID_BITMAP_LIST)); + aSet.Put(SvxPatternListItem(m_pPatternList, SID_PATTERN_LIST)); aSet.Put (SfxUInt16Item(SID_PAGE_TYPE,0)); aSet.Put (SfxUInt16Item(SID_DLG_TYPE,1)); aSet.Put (SfxUInt16Item(SID_TABPAGE_POS,0)); @@ -250,7 +258,7 @@ void SdPresLayoutTemplateDlg::PageCreated(const OUString& rId, SfxTabPage &rPage } else if (rId == "shadowing") { - aSet.Put (SvxColorListItem(pColorTab,SID_COLOR_TABLE)); + aSet.Put(SvxColorListItem(m_pColorTab, SID_COLOR_TABLE)); aSet.Put (SfxUInt16Item(SID_PAGE_TYPE,0)); aSet.Put (SfxUInt16Item(SID_DLG_TYPE,1)); rPage.PageCreated(aSet); @@ -285,14 +293,16 @@ void SdPresLayoutTemplateDlg::PageCreated(const OUString& rId, SfxTabPage &rPage const SfxItemSet* SdPresLayoutTemplateDlg::GetOutputItemSet() const { - if (pOutSet) + if (m_pOutSet) { - pOutSet->Put(*SfxTabDialogController::GetOutputItemSet()); + m_pOutSet->Put(*SfxTabDialogController::GetOutputItemSet()); - const SvxNumBulletItem *pSvxNumBulletItem = pOutSet->GetItemIfSet(EE_PARA_NUMBULLET, false); + const SvxNumBulletItem* pSvxNumBulletItem + = m_pOutSet->GetItemIfSet(EE_PARA_NUMBULLET, false); if (pSvxNumBulletItem) - SdBulletMapper::MapFontsInNumRule( const_cast(pSvxNumBulletItem->GetNumRule()), *pOutSet ); - return pOutSet.get(); + SdBulletMapper::MapFontsInNumRule( + const_cast(pSvxNumBulletItem->GetNumRule()), *m_pOutSet); + return m_pOutSet.get(); } else return SfxTabDialogController::GetOutputItemSet(); @@ -300,7 +310,7 @@ const SfxItemSet* SdPresLayoutTemplateDlg::GetOutputItemSet() const sal_uInt16 SdPresLayoutTemplateDlg::GetOutlineLevel() const { - switch( ePO ) + switch (m_ePO) { case PresentationObjects::Outline_1: return 0; case PresentationObjects::Outline_2: return 1; diff --git a/sd/source/ui/dlg/prntopts.cxx b/sd/source/ui/dlg/prntopts.cxx index ea1e7e38ba0c..6700ddafff52 100644 --- a/sd/source/ui/dlg/prntopts.cxx +++ b/sd/source/ui/dlg/prntopts.cxx @@ -26,6 +26,7 @@ #include #include #include +#include /** * dialog to adjust print options diff --git a/sd/source/ui/dlg/sdpreslt.cxx b/sd/source/ui/dlg/sdpreslt.cxx index ea155962e801..808bce851676 100644 --- a/sd/source/ui/dlg/sdpreslt.cxx +++ b/sd/source/ui/dlg/sdpreslt.cxx @@ -21,11 +21,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include @@ -49,8 +49,7 @@ SdPresLayoutDlg::SdPresLayoutDlg(::sd::DrawDocShell* pDocShell, , m_xCbxMasterPage(m_xBuilder->weld_check_button(u"masterpage"_ustr)) , m_xCbxCheckMasters(m_xBuilder->weld_check_button(u"checkmasters"_ustr)) , m_xBtnLoad(m_xBuilder->weld_button(u"load"_ustr)) - , m_xVS(new ValueSet(m_xBuilder->weld_scrolled_window(u"selectwin"_ustr, true))) - , m_xVSWin(new weld::CustomWeld(*m_xBuilder, u"select"_ustr, *m_xVS)) + , m_xIconView(m_xBuilder->weld_icon_view(u"layoutsiconview"_ustr)) , m_xLabel(m_xBuilder->weld_label(u"label1"_ustr)) { if (mpDocSh->GetDoc()->GetDocumentType() == DocumentType::Draw) @@ -63,10 +62,8 @@ SdPresLayoutDlg::SdPresLayoutDlg(::sd::DrawDocShell* pDocShell, m_xDialog->set_title(SdResId(STR_AVAILABLE_MASTERSLIDE)); m_xLabel->set_label(SdResId(STR_SELECT_SLIDE)); } - m_xVSWin->set_size_request(m_xBtnLoad->get_approximate_digit_width() * 60, - m_xBtnLoad->get_text_height() * 20); - m_xVS->SetDoubleClickHdl(LINK(this, SdPresLayoutDlg, ClickLayoutHdl)); + m_xIconView->connect_item_activated(LINK(this, SdPresLayoutDlg, ActivateLayoutHdl)); m_xBtnLoad->connect_clicked(LINK(this, SdPresLayoutDlg, ClickLoadHdl)); Reset(); @@ -81,8 +78,6 @@ SdPresLayoutDlg::~SdPresLayoutDlg() */ void SdPresLayoutDlg::Reset() { - tools::Long nName; - // replace master page if( const SfxBoolItem* pPoolItem = mrOutAttrs.GetItemIfSet( ATTR_PRESLAYOUT_MASTER_PAGE, false ) ) { @@ -99,9 +94,10 @@ void SdPresLayoutDlg::Reset() else maName.clear(); - FillValueSet(); + FillIconView(); mnLayoutCount = maLayoutNames.size(); + int nName; for( nName = 0; nName < mnLayoutCount; nName++ ) { if (maLayoutNames[nName] == maName) @@ -109,8 +105,7 @@ void SdPresLayoutDlg::Reset() } DBG_ASSERT(nName < mnLayoutCount, "Layout not found"); - m_xVS->SelectItem(static_cast(nName) + 1); // Indices of the ValueSets start at 1 - + m_xIconView->select(nName); } /** @@ -118,21 +113,24 @@ void SdPresLayoutDlg::Reset() */ void SdPresLayoutDlg::GetAttr(SfxItemSet& rOutAttrs) { - short nId = m_xVS->GetSelectedItemId(); - bool bLoad = nId > mnLayoutCount; + const int nIndex = m_xIconView->get_selected_index(); + bool bLoad = nIndex >= mnLayoutCount; rOutAttrs.Put( SfxBoolItem( ATTR_PRESLAYOUT_LOAD, bLoad ) ); OUString aLayoutName; - if( bLoad ) + if (nIndex >= 0) { - aLayoutName = maName + "#" + maLayoutNames[ nId - 1 ]; - } - else if (nId) - { - aLayoutName = maLayoutNames[ nId - 1 ]; - if( aLayoutName == maStrNone ) - aLayoutName.clear(); // that way we encode "- nothing -" (see below) + if( bLoad ) + { + aLayoutName = maName + "#" + maLayoutNames.at(nIndex); + } + else + { + aLayoutName = maLayoutNames.at(nIndex); + if( aLayoutName == maStrNone ) + aLayoutName.clear(); // that way we encode "- nothing -" (see below) + } } rOutAttrs.Put( SfxStringItem( ATTR_PRESLAYOUT_NAME, aLayoutName ) ); @@ -141,17 +139,10 @@ void SdPresLayoutDlg::GetAttr(SfxItemSet& rOutAttrs) } /** - * Fills ValueSet with bitmaps + * Fills icon view with bitmaps */ -void SdPresLayoutDlg::FillValueSet() +void SdPresLayoutDlg::FillIconView() { - m_xVS->SetStyle(m_xVS->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER - | WB_VSCROLL | WB_NAMEFIELD); - - m_xVS->SetColCount(2); - m_xVS->SetLineCount(2); - m_xVS->SetExtraSpacing(2); - SdDrawDocument* pDoc = mpDocSh->GetDoc(); sal_uInt16 nCount = pDoc->GetMasterPageCount(); @@ -165,20 +156,18 @@ void SdPresLayoutDlg::FillValueSet() aLayoutName = aLayoutName.copy(0, aLayoutName.indexOf(SD_LT_SEPARATOR)); maLayoutNames.push_back(aLayoutName); - Image aBitmap(mpDocSh->GetPagePreviewBitmap(pMaster)); - m_xVS->InsertItem(static_cast(maLayoutNames.size()), aBitmap, aLayoutName); + Bitmap aBitmap(mpDocSh->GetPagePreviewBitmap(pMaster)); + m_xIconView->insert(maLayoutNames.size() - 1, nullptr, nullptr, &aBitmap, nullptr); + m_xIconView->set_item_accessible_name(maLayoutNames.size() - 1, aLayoutName); + m_xIconView->set_item_tooltip_text(maLayoutNames.size() - 1, aLayoutName); } } - - m_xVS->Show(); } -/** - * DoubleClick handler - */ -IMPL_LINK_NOARG(SdPresLayoutDlg, ClickLayoutHdl, ValueSet*, void) +IMPL_LINK_NOARG(SdPresLayoutDlg, ActivateLayoutHdl, const weld::TreeIter&, bool) { m_xDialog->response(RET_OK); + return true; } /** @@ -226,9 +215,9 @@ IMPL_LINK_NOARG(SdPresLayoutDlg, ClickLoadHdl, weld::Button&, void) auto it = std::find(maLayoutNames.begin(), maLayoutNames.end(), aCompareStr); if (it != maLayoutNames.end()) { - sal_uInt16 aPos = static_cast(std::distance(maLayoutNames.begin(), it)); // select template - m_xVS->SelectItem( aPos + 1 ); + const int nPos = std::distance(maLayoutNames.begin(), it); + m_xIconView->select(nPos); } else { @@ -254,8 +243,12 @@ IMPL_LINK_NOARG(SdPresLayoutDlg, ClickLoadHdl, weld::Button&, void) aLayoutName = aLayoutName.copy(0, aLayoutName.indexOf(SD_LT_SEPARATOR)); maLayoutNames.push_back(aLayoutName); - Image aBitmap(pTemplDocSh->GetPagePreviewBitmap(pMaster)); - m_xVS->InsertItem(static_cast(maLayoutNames.size()), aBitmap, aLayoutName); + Bitmap aBitmap = pTemplDocSh->GetPagePreviewBitmap(pMaster); + m_xIconView->insert(maLayoutNames.size() - 1, nullptr, nullptr, &aBitmap, + nullptr); + m_xIconView->set_item_accessible_name(maLayoutNames.size() - 1, + aLayoutName); + m_xIconView->set_item_tooltip_text(maLayoutNames.size() - 1, aLayoutName); } } } @@ -270,14 +263,16 @@ IMPL_LINK_NOARG(SdPresLayoutDlg, ClickLoadHdl, weld::Button&, void) { // empty layout maLayoutNames.push_back(maStrNone); - m_xVS->InsertItem( static_cast(maLayoutNames.size()), - Image(BMP_SLIDE_NONE), maStrNone ); + Bitmap aBitmap(BMP_SLIDE_NONE); + m_xIconView->insert(maLayoutNames.size() - 1, nullptr, nullptr, &aBitmap, nullptr); + m_xIconView->set_item_accessible_name(maLayoutNames.size() - 1, maStrNone); + m_xIconView->set_item_tooltip_text(maLayoutNames.size() - 1, maStrNone); } if (!bCancel) { // select template - m_xVS->SelectItem( static_cast(maLayoutNames.size()) ); + m_xIconView->select(maLayoutNames.size() - 1); } } } diff --git a/sd/source/ui/dlg/sdtreelb.cxx b/sd/source/ui/dlg/sdtreelb.cxx index 4b270b1ed1a8..26ab06664778 100644 --- a/sd/source/ui/dlg/sdtreelb.cxx +++ b/sd/source/ui/dlg/sdtreelb.cxx @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -805,25 +805,25 @@ IMPL_LINK_NOARG(SdPageObjsTLV, EditingEntryHdl, const weld::TreeIter&, bool) return true; } -IMPL_LINK(SdPageObjsTLV, EditedEntryHdl, const IterString&, rIterString, bool) +IMPL_LINK(SdPageObjsTLV, EditedEntryHdl, const weld::TreeView::IterColText&, rIterColText, bool) { m_bEditing = false; // Did the name change? - if (m_xTreeView->get_text(rIterString.first) == rIterString.second) + if (m_xTreeView->get_text(rIterColText.m_rIter) == rIterColText.m_sText) return true; // If the new name is empty or not unique, start editing again. - if (rIterString.second.isEmpty() || m_pDoc->GetObj(rIterString.second) - || m_pDoc->IsPageNameUnique(rIterString.second)) + if (rIterColText.m_sText.isEmpty() || m_pDoc->GetObj(rIterColText.m_sText) + || m_pDoc->IsPageNameUnique(rIterColText.m_sText)) { - std::unique_ptr xEntry(m_xTreeView->make_iterator(&rIterString.first)); + std::unique_ptr xEntry(m_xTreeView->make_iterator(&rIterColText.m_rIter)); Application::PostUserEvent(LINK(this, SdPageObjsTLV, EditEntryAgain), xEntry.release()); return false; } // set the new name - const auto aEntryId = m_xTreeView->get_id(rIterString.first); + const auto aEntryId = m_xTreeView->get_id(rIterColText.m_rIter); if (::sd::DrawDocShell* pDocShell = m_pDoc->GetDocSh()) { if (::sd::ViewShell* pViewShell = GetViewShellForDocShell(*pDocShell)) @@ -832,12 +832,12 @@ IMPL_LINK(SdPageObjsTLV, EditedEntryHdl, const IterString&, rIterString, bool) if (aEntryId.toInt64() == 1) { // page name - pPage->SetName(rIterString.second); + pPage->SetName(rIterColText.m_sText); } else if (SdrObject* pCursorEntryObject = weld::fromId(aEntryId)) { // object name - pCursorEntryObject->SetName(rIterString.second); + pCursorEntryObject->SetName(rIterColText.m_sText); pPage->notifyObjectRenamed(pCursorEntryObject); } } diff --git a/sd/source/ui/dlg/titledockwin.cxx b/sd/source/ui/dlg/titledockwin.cxx index 2f44c333fd39..2d0ee2ec2c2c 100644 --- a/sd/source/ui/dlg/titledockwin.cxx +++ b/sd/source/ui/dlg/titledockwin.cxx @@ -36,8 +36,8 @@ namespace sd { //= TitledDockingWindow - TitledDockingWindow::TitledDockingWindow( SfxBindings* i_pBindings, SfxChildWindow* i_pChildWindow, vcl::Window* i_pParent, const OUString& rsTitle ) - :SfxDockingWindow( i_pBindings, i_pChildWindow, i_pParent, WB_MOVEABLE|WB_CLOSEABLE|WB_DOCKABLE|WB_HIDE|WB_3DLOOK ) + TitledDockingWindow::TitledDockingWindow(SfxBindings& rBindings, SfxChildWindow* i_pChildWindow, vcl::Window* i_pParent, const OUString& rsTitle ) + :SfxDockingWindow(rBindings, i_pChildWindow, i_pParent, WB_MOVEABLE|WB_CLOSEABLE|WB_DOCKABLE|WB_HIDE|WB_3DLOOK ) ,m_aToolbox( VclPtr::Create(this) ) ,m_aContentWindow( VclPtr::Create(this, WB_DIALOGCONTROL) ) ,m_aBorder( 3, 1, 3, 3 ) diff --git a/sd/source/ui/dlg/tpaction.cxx b/sd/source/ui/dlg/tpaction.cxx index 24306cde460f..2fb52c67d2ba 100644 --- a/sd/source/ui/dlg/tpaction.cxx +++ b/sd/source/ui/dlg/tpaction.cxx @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include diff --git a/sd/source/ui/dlg/tpoption.cxx b/sd/source/ui/dlg/tpoption.cxx index c968b7fa0f1d..5b7e2c02557d 100644 --- a/sd/source/ui/dlg/tpoption.cxx +++ b/sd/source/ui/dlg/tpoption.cxx @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -237,8 +236,9 @@ SdTpOptionsContents::SdTpOptionsContents(weld::Container* pPage, , m_xCbxHandlesBezierImg(m_xBuilder->weld_widget(u"lockhandlesbezier"_ustr)) , m_xCbxMoveOutline(m_xBuilder->weld_check_button(u"moveoutline"_ustr)) , m_xCbxMoveOutlineImg(m_xBuilder->weld_widget(u"lockmoveoutline"_ustr)) -{ -} + , m_xCbxZoomWithWheel(m_xBuilder->weld_check_button(u"zoomwithwheel"_ustr)) + , m_xCbxZoomWithWheelImg(m_xBuilder->weld_widget(u"lockzoomwithwheel"_ustr)) +{} SdTpOptionsContents::~SdTpOptionsContents() {} @@ -253,8 +253,8 @@ OUString SdTpOptionsContents::GetAllStrings() sAllStrings.append(pString->get_label() + " "); } - OUString checkButton[] - = { u"ruler"_ustr, u"dragstripes"_ustr, u"handlesbezier"_ustr, u"moveoutline"_ustr }; + OUString checkButton[] = { u"ruler"_ustr, u"dragstripes"_ustr, u"handlesbezier"_ustr, + u"moveoutline"_ustr, u"zoomwithwheel"_ustr }; for (const auto& check : checkButton) { @@ -272,7 +272,8 @@ bool SdTpOptionsContents::FillItemSet(SfxItemSet*) if (m_xCbxRuler->get_state_changed_from_saved() || m_xCbxMoveOutline->get_state_changed_from_saved() || m_xCbxDragStripes->get_state_changed_from_saved() - || m_xCbxHandlesBezier->get_state_changed_from_saved()) + || m_xCbxHandlesBezier->get_state_changed_from_saved() + || (m_bDrawMode && m_xCbxZoomWithWheel->get_state_changed_from_saved())) { std::shared_ptr batch( comphelper::ConfigurationChanges::create()); @@ -286,6 +287,8 @@ bool SdTpOptionsContents::FillItemSet(SfxItemSet*) batch); officecfg::Office::Draw::Layout::Display::Bezier::set(m_xCbxHandlesBezier->get_active(), batch); + officecfg::Office::Draw::Layout::Display::ZoomWithMouseWheel::set( + m_xCbxZoomWithWheel->get_active(), batch); batch->commit(); } else @@ -313,6 +316,9 @@ void SdTpOptionsContents::Reset(const SfxItemSet*) m_xCbxMoveOutline->set_active(officecfg::Office::Draw::Layout::Display::Contour::get()); m_xCbxDragStripes->set_active(officecfg::Office::Draw::Layout::Display::Guide::get()); m_xCbxHandlesBezier->set_active(officecfg::Office::Draw::Layout::Display::Bezier::get()); + m_xCbxZoomWithWheel->show(); + m_xCbxZoomWithWheel->set_active( + officecfg::Office::Draw::Layout::Display::ZoomWithMouseWheel::get()); } else { @@ -320,6 +326,8 @@ void SdTpOptionsContents::Reset(const SfxItemSet*) m_xCbxMoveOutline->set_active(officecfg::Office::Impress::Layout::Display::Contour::get()); m_xCbxDragStripes->set_active(officecfg::Office::Impress::Layout::Display::Guide::get()); m_xCbxHandlesBezier->set_active(officecfg::Office::Impress::Layout::Display::Bezier::get()); + m_xCbxZoomWithWheel->hide(); + m_xCbxZoomWithWheelImg->hide(); } bool bReadOnly = m_bDrawMode ? officecfg::Office::Draw::Layout::Display::Ruler::isReadOnly() @@ -342,10 +350,18 @@ void SdTpOptionsContents::Reset(const SfxItemSet*) m_xCbxHandlesBezier->set_sensitive(!bReadOnly); m_xCbxHandlesBezierImg->set_visible(bReadOnly); + if (m_bDrawMode) + { + bReadOnly = officecfg::Office::Draw::Layout::Display::ZoomWithMouseWheel::isReadOnly(); + m_xCbxZoomWithWheel->set_sensitive(!bReadOnly); + m_xCbxZoomWithWheelImg->set_visible(bReadOnly); + } + m_xCbxRuler->save_state(); m_xCbxMoveOutline->save_state(); m_xCbxDragStripes->save_state(); m_xCbxHandlesBezier->save_state(); + m_xCbxZoomWithWheel->save_state(); } std::unique_ptr SdTpOptionsContents::Create(weld::Container* pPage, diff --git a/sd/source/ui/dlg/unchss.cxx b/sd/source/ui/dlg/unchss.cxx index 52386706306a..3dd1ec36c62e 100644 --- a/sd/source/ui/dlg/unchss.cxx +++ b/sd/source/ui/dlg/unchss.cxx @@ -39,7 +39,7 @@ StyleSheetUndoAction::StyleSheetUndoAction(SdDrawDocument& rTheDoc, : SdUndoAction(rTheDoc), mrStyleSheet(rTheStyleSheet) { - // Create ItemSets; Attention, it is possible that the new one is from a, + // Create ItemSets; Attention, it is possible that the new one is from a // different pool. Therefore we clone it with its items. mpNewSet = std::make_unique(static_cast(SdrObject::GetGlobalDrawObjectItemPool()), pTheNewItemSet->GetRanges()); SdrModel::MigrateItemSet( pTheNewItemSet, mpNewSet.get(), rTheDoc ); diff --git a/sd/source/ui/dlg/vectdlg.cxx b/sd/source/ui/dlg/vectdlg.cxx index ce9c8f0bf098..e46074dd3e0f 100644 --- a/sd/source/ui/dlg/vectdlg.cxx +++ b/sd/source/ui/dlg/vectdlg.cxx @@ -117,7 +117,8 @@ Bitmap SdVectorizeDlg::GetPreparedBitmap( Bitmap const & rBmp, double& rScale ) if( aSizePix.Width() > VECTORIZE_MAX_EXTENT || aSizePix.Height() > VECTORIZE_MAX_EXTENT ) { const ::tools::Rectangle aRect( GetRect( Size( VECTORIZE_MAX_EXTENT, VECTORIZE_MAX_EXTENT ), aSizePix ) ); - rScale = double(aSizePix.Width()) / aRect.GetWidth(); + if (aRect.GetWidth()) + rScale = double(aSizePix.Width()) / aRect.GetWidth(); aNew.Scale( aRect.GetSize() ); } else diff --git a/sd/source/ui/docshell/docshel2.cxx b/sd/source/ui/docshell/docshel2.cxx index fdbf1bfc2cf3..51c112b566c9 100644 --- a/sd/source/ui/docshell/docshel2.cxx +++ b/sd/source/ui/docshell/docshel2.cxx @@ -48,7 +48,7 @@ void DrawDocShell::Draw(OutputDevice* pOut, const JobSetup&, sal_uInt16 nAspect, { if (nAspect == ASPECT_THUMBNAIL) { - // THUMBNAIL: here we may can set the draft mode + // THUMBNAIL: here we can set the draft mode } std::optional pView( std::in_place, this, pOut ); diff --git a/sd/source/ui/docshell/docshel4.cxx b/sd/source/ui/docshell/docshel4.cxx index 1e070280503a..766631be8f90 100644 --- a/sd/source/ui/docshell/docshel4.cxx +++ b/sd/source/ui/docshell/docshel4.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,8 @@ #include #include #include +#include +#include #include #include #include @@ -80,7 +83,6 @@ #include #include -#include #include #include @@ -103,10 +105,10 @@ SfxPrinter* DrawDocShell::GetPrinter(bool bCreate) if (bCreate && !mpPrinter) { // create ItemSet with special pool area - auto pSet = std::make_unique(SfxItemSet::makeFixedSfxItemSet< SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC, - ATTR_OPTIONS_PRINT, ATTR_OPTIONS_PRINT>>( GetPool() ); + ATTR_OPTIONS_PRINT, ATTR_OPTIONS_PRINT>( GetPool() )); // set PrintOptionsSet SdOptionsPrintItem aPrintItem(SdModule::get()->GetSdOptions(mpDoc->GetDocumentType())); SfxFlagItem aFlagItem( SID_PRINTER_CHANGESTODOC ); @@ -293,11 +295,13 @@ bool DrawDocShell::Load( SfxMedium& rMedium ) bRet = SfxObjectShell::Load( rMedium ); if (bRet) { - comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer(); - rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false); + getEmbeddedObjectContainer().setUserAllowsLinkUpdate(false); bRet = SdXMLFilter( rMedium, *this, SdXMLFilterMode::Normal, SotStorage::GetVersion( rMedium.GetStorage() ) ).Import( nError ); } + if (bRet) + UpdateLinks(); + if( bRet ) { SdDrawDocument* pDoc = GetDoc(); @@ -305,6 +309,7 @@ bool DrawDocShell::Load( SfxMedium& rMedium ) // for legacy markup in OOoXML filter, convert the animations now EffectMigration::DocumentLoaded(*pDoc); UpdateTablePointers(); + pDoc->SwitchPlaceholdersHoldingText(); // If we're an embedded OLE object, use tight bounds // for our visArea. No point in showing the user lots of empty @@ -413,8 +418,8 @@ bool DrawDocShell::ImportFrom(SfxMedium &rMedium, // mode for spacing before and after paragraphs. // This is copied from what is done for .ppt import in - // ImplSdPPTImport::Import() in sd/source/filter/ppt/pptin.cxx - // in. We need to tell both the edit engine of the draw outliner, + // ImplSdPPTImport::Import() in sd/source/filter/ppt/pptin.cxx. + // We need to tell both the edit engine of the draw outliner, // and the document, to do "summation of paragraphs". SdrOutliner& rOutl = mpDoc->GetDrawOutliner(); EEControlBits nControlWord = rOutl.GetEditEngine().GetControlWord(); @@ -425,8 +430,8 @@ bool DrawDocShell::ImportFrom(SfxMedium &rMedium, // tdf#149756 tdf#152545 // This is a "MS Compact" mode for connectors. - // The Libreoffice uses bounding rectangle of connected shapes but - // MSO uses snap rectangle when calculate the edge track. + // LibreOffice uses bounding rectangle of connected shapes but + // MSO uses snap rectangle when calculating the edge track. mpDoc->SetCompatibilityFlag(SdrCompatibilityFlag::ConnectorUseSnapRect, true); // compatibility flag for tdf#148966 @@ -453,12 +458,21 @@ bool DrawDocShell::ImportFrom(SfxMedium &rMedium, else // initial loading of the document { mpDoc->EnableUndo(false); + getEmbeddedObjectContainer().setUserAllowsLinkUpdate(false); } mpDoc->incImportExport(); const bool bRet = SfxObjectShell::ImportFrom(rMedium, xInsertPosition); mpDoc->decImportExport(); + if (bRet) + { + mpDoc->SwitchPlaceholdersHoldingText(); + } + + if (bRet && !xInsertPosition) + UpdateLinks(); + SfxItemSet& rSet = rMedium.GetItemSet(); if (SfxItemState::SET == rSet.GetItemState(SID_DOC_STARTPRESENTATION)) { @@ -523,6 +537,8 @@ bool DrawDocShell::ConvertFrom( SfxMedium& rMedium ) mpDoc->SetStartWithPresentation(nStartingSlide); } + getEmbeddedObjectContainer().setUserAllowsLinkUpdate(false); + if( aFilterName == pFilterPowerPoint97 || aFilterName == pFilterPowerPoint97Template || aFilterName == pFilterPowerPoint97AutoPlay) @@ -570,6 +586,12 @@ bool DrawDocShell::ConvertFrom( SfxMedium& rMedium ) FinishedLoading(); + if (bRet) + { + mpDoc->SwitchPlaceholdersHoldingText(); + UpdateLinks(); + } + // tell SFX to change viewshell when in preview mode if( IsPreview() ) { @@ -586,6 +608,11 @@ bool DrawDocShell::ConvertFrom( SfxMedium& rMedium ) return bRet; } +void DrawDocShell::UpdateLinks() +{ + mpDoc->UpdateAllLinks(); +} + /** * Writes pools and document to the open streams */ @@ -710,7 +737,7 @@ bool DrawDocShell::ConvertTo( SfxMedium& rMedium ) } /** - * Reopen own streams to ensure that nobody else can prevent use from opening + * Reopen own streams to ensure that nobody else can prevent us from opening * them. */ bool DrawDocShell::SaveCompleted( const css::uno::Reference< css::embed::XStorage >& xStorage ) diff --git a/sd/source/ui/docshell/docshell.cxx b/sd/source/ui/docshell/docshell.cxx index 6254e9839d1c..872f2d38f705 100644 --- a/sd/source/ui/docshell/docshell.cxx +++ b/sd/source/ui/docshell/docshell.cxx @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -64,6 +65,7 @@ #include #include #include +#include using namespace sd; #define ShellClass_DrawDocShell @@ -189,7 +191,7 @@ DrawDocShell::~DrawDocShell() if( mbOwnDocument ) delete mpDoc; - // that the navigator get informed about the disappearance of the document + // so that the navigator gets informed about the disappearance of the document SfxBoolItem aItem(SID_NAVIGATOR_INIT, true); SfxViewFrame* pFrame = mpViewShell ? mpViewShell->GetFrame() : GetFrame(); @@ -358,6 +360,7 @@ void DrawDocShell::Activate( bool bMDI) { ApplySlotFilter(); mpDoc->StartOnlineSpelling(); + CheckPendingLinkUpdateInfobar(); } } @@ -365,6 +368,19 @@ void DrawDocShell::Deactivate( bool ) { } +void DrawDocShell::PerformLinkUpdate() +{ + if (mpDoc && mpDoc->GetLinkManager()) + { + registerDeferredFormImageLinks(GetDeferredFormControlImages(), *mpDoc->GetLinkManager()); + ClearDeferredFormControlImages(); + SdDrawDocument::s_pDocLockedInsertingLinks = mpDoc; + mpDoc->GetLinkManager()->UpdateAllLinks(false, u""_ustr); + if (SdDrawDocument::s_pDocLockedInsertingLinks == mpDoc) + SdDrawDocument::s_pDocLockedInsertingLinks = nullptr; + } +} + SfxUndoManager* DrawDocShell::GetUndoManager() { return mpUndoManager.get(); diff --git a/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.cxx b/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.cxx index c6727559e538..1c167b1bb36d 100644 --- a/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.cxx +++ b/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.cxx @@ -31,7 +31,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace { @@ -155,7 +154,7 @@ void ChangeRequestQueueProcessor::ProcessOneEvent() ConfigurationTracer::TraceConfiguration ( mxConfiguration, "updating to configuration"); #endif - // RequestUpdate may eventually call a code that needs to lock a solar mutex, owned by + // RequestUpdate may eventually call code that needs to lock a solar mutex, owned by // another thread, that waits for maMutex; release it here, to avoid deadlocks auto pConfigurationUpdater = mpConfigurationUpdater; auto xConfiguration = mxConfiguration; diff --git a/sd/source/ui/framework/configuration/Configuration.cxx b/sd/source/ui/framework/configuration/Configuration.cxx index 7b7684bb54b4..a1c1c3346460 100644 --- a/sd/source/ui/framework/configuration/Configuration.cxx +++ b/sd/source/ui/framework/configuration/Configuration.cxx @@ -31,7 +31,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; namespace { @@ -145,8 +144,8 @@ std::vector > Configuration::getResources ( // Apply the given resource prefix as filter. // Make sure that the resource is bound directly to the anchor. - if (eMode != AnchorBindingMode_DIRECT - && ! rxResource->isBoundTo(rxAnchorId, AnchorBindingMode_DIRECT)) + if (eMode != AnchorBindingMode::DIRECT + && ! rxResource->isBoundTo(rxAnchorId, AnchorBindingMode::DIRECT)) { continue; } @@ -261,10 +260,10 @@ bool AreConfigurationsEquivalent ( // Get the lists of resources from the two given configurations. const std::vector > aResources1( rxConfiguration1->getResources( - nullptr, u"", AnchorBindingMode_INDIRECT)); + nullptr, u"", AnchorBindingMode::INDIRECT)); const std::vector > aResources2( rxConfiguration2->getResources( - nullptr, u"", AnchorBindingMode_INDIRECT)); + nullptr, u"", AnchorBindingMode::INDIRECT)); // When the number of resources differ then the configurations can not // be equivalent. diff --git a/sd/source/ui/framework/configuration/ConfigurationClassifier.cxx b/sd/source/ui/framework/configuration/ConfigurationClassifier.cxx index 5a3ab1370aa9..5c4f1eae38b7 100644 --- a/sd/source/ui/framework/configuration/ConfigurationClassifier.cxx +++ b/sd/source/ui/framework/configuration/ConfigurationClassifier.cxx @@ -26,7 +26,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sd::framework { @@ -44,8 +43,8 @@ bool ConfigurationClassifier::Partition() maC2minusC1.clear(); PartitionResources( - mxConfiguration1->getResources(nullptr, u"", AnchorBindingMode_DIRECT), - mxConfiguration2->getResources(nullptr, u"", AnchorBindingMode_DIRECT)); + mxConfiguration1->getResources(nullptr, u"", AnchorBindingMode::DIRECT), + mxConfiguration2->getResources(nullptr, u"", AnchorBindingMode::DIRECT)); return !maC1minusC2.empty() || !maC2minusC1.empty(); } @@ -76,8 +75,8 @@ void ConfigurationClassifier::PartitionResources ( for (const auto& rxResource : aC1andC2) { PartitionResources( - mxConfiguration1->getResources(rxResource, u"", AnchorBindingMode_DIRECT), - mxConfiguration2->getResources(rxResource, u"", AnchorBindingMode_DIRECT)); + mxConfiguration1->getResources(rxResource, u"", AnchorBindingMode::DIRECT), + mxConfiguration2->getResources(rxResource, u"", AnchorBindingMode::DIRECT)); } } @@ -128,7 +127,7 @@ void ConfigurationClassifier::CopyResources ( rxConfiguration->getResources( rxResource, u"", - AnchorBindingMode_INDIRECT)); + AnchorBindingMode::INDIRECT)); const sal_Int32 nL (aBoundResources.size()); rTarget.reserve(rTarget.size() + 1 + nL); diff --git a/sd/source/ui/framework/configuration/ConfigurationController.cxx b/sd/source/ui/framework/configuration/ConfigurationController.cxx index 51b78e1fabd9..81344aecb1dc 100644 --- a/sd/source/ui/framework/configuration/ConfigurationController.cxx +++ b/sd/source/ui/framework/configuration/ConfigurationController.cxx @@ -41,7 +41,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; namespace sd::framework { @@ -231,7 +230,7 @@ void ConfigurationController::requestResourceActivation ( ThrowIfDisposed(); // Check whether we are being disposed. This is handled differently - // then being completely disposed because the first thing disposing() + // than being completely disposed because the first thing disposing() // does is to deactivate all remaining resources. This is done via // regular methods which must not throw DisposedExceptions. Therefore // we just return silently during that stage. @@ -256,7 +255,7 @@ void ConfigurationController::requestResourceActivation ( mpImplementation->mxRequestedConfiguration->getResources( rxResourceId->getAnchor(), rxResourceId->getResourceTypePrefix(), - AnchorBindingMode_DIRECT)); + AnchorBindingMode::DIRECT)); for (const auto& rResource : aResourceList) { @@ -297,7 +296,7 @@ void ConfigurationController::requestResourceDeactivation ( mpImplementation->mxRequestedConfiguration->getResources( rxResourceId, u"", - AnchorBindingMode_DIRECT)); + AnchorBindingMode::DIRECT)); for (const auto& rLinkedResource : aLinkedResources) { // We do not add deactivation requests directly but call this @@ -482,7 +481,7 @@ ConfigurationController::Implementation::Implementation ( mpResourceManager( std::make_shared(mpResourceFactoryContainer,mpBroadcaster)), mpConfigurationUpdater( - std::make_shared(mpBroadcaster, mpResourceManager,rxController)), + std::make_shared(mpBroadcaster, mpResourceManager, rxController)), mpQueueProcessor(new ChangeRequestQueueProcessor(mpConfigurationUpdater)), mnLockCount(0) { diff --git a/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.cxx b/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.cxx index 5a3f84649f76..a8ca67de0675 100644 --- a/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.cxx +++ b/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.cxx @@ -28,7 +28,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sd::framework { diff --git a/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.cxx b/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.cxx index 0134774a5d26..488270e46469 100644 --- a/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.cxx +++ b/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.cxx @@ -32,7 +32,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sd::framework { @@ -169,7 +168,7 @@ void ConfigurationControllerResourceManager::ActivateResource ( 2. Notify listeners that deactivation has started. 3. Remove the resource id from the current configuration. 4. Release the resource. - 5. Notify listeners about that deactivation is completed. + 5. Notify listeners that deactivation is completed. */ void ConfigurationControllerResourceManager::DeactivateResource ( const rtl::Reference& rxResourceId, diff --git a/sd/source/ui/framework/configuration/ConfigurationTracer.cxx b/sd/source/ui/framework/configuration/ConfigurationTracer.cxx index ba642affb1fd..c7d0f72d3e79 100644 --- a/sd/source/ui/framework/configuration/ConfigurationTracer.cxx +++ b/sd/source/ui/framework/configuration/ConfigurationTracer.cxx @@ -24,7 +24,6 @@ #include using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sd::framework { @@ -56,7 +55,7 @@ void ConfigurationTracer::TraceBoundResources ( const int nIndentation) { const std::vector > aResourceList ( - rxConfiguration->getResources(rxResourceId, u"", AnchorBindingMode_DIRECT)); + rxConfiguration->getResources(rxResourceId, u"", AnchorBindingMode::DIRECT)); static constexpr OUStringLiteral sIndentation (u" "); for (rtl::Reference const & resourceId : aResourceList) { diff --git a/sd/source/ui/framework/configuration/ConfigurationUpdater.cxx b/sd/source/ui/framework/configuration/ConfigurationUpdater.cxx index f03afd1dbee7..36f4bb0754c6 100644 --- a/sd/source/ui/framework/configuration/ConfigurationUpdater.cxx +++ b/sd/source/ui/framework/configuration/ConfigurationUpdater.cxx @@ -37,7 +37,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; using ::std::vector; @@ -280,7 +279,7 @@ void ConfigurationUpdater::CheckPureAnchors ( // Get a list of all resources in the configuration. std::vector > aResources( rxConfiguration->getResources( - nullptr, u"", AnchorBindingMode_INDIRECT)); + nullptr, u"", AnchorBindingMode::INDIRECT)); sal_Int32 nCount (aResources.size()); // Prepare the list of pure anchors that have to be deactivated. @@ -295,7 +294,7 @@ void ConfigurationUpdater::CheckPureAnchors ( const rtl::Reference& xResourceId (aResources[nIndex]); const rtl::Reference xResource ( mpResourceManager->GetResource(xResourceId).mxResource); - bool bDeactiveCurrentResource (false); + bool bDeactivateCurrentResource (false); // Skip all resources that are no pure anchors. if (xResource.is() && xResource->isAnchorOnly()) @@ -306,26 +305,26 @@ void ConfigurationUpdater::CheckPureAnchors ( { // No following anchors, deactivate this one, then remove it // from the list. - bDeactiveCurrentResource = true; + bDeactivateCurrentResource = true; } else { const rtl::Reference& xPrevResourceId (aResources[nIndex+1]); if ( ! xPrevResourceId.is() - || ! xPrevResourceId->isBoundTo(xResourceId, AnchorBindingMode_DIRECT)) + || ! xPrevResourceId->isBoundTo(xResourceId, AnchorBindingMode::DIRECT)) { // The previous resource (id) does not exist or is not bound to // the current anchor. - bDeactiveCurrentResource = true; + bDeactivateCurrentResource = true; } } } - if (bDeactiveCurrentResource) + if (bDeactivateCurrentResource) { SAL_INFO("sd.fwk", __func__ << ": deactivating pure anchor " << FrameworkHelper::ResourceIdToString(xResourceId) << - "because it has no children"); + " because it has no children"); rResourcesToDeactivate.push_back(xResourceId); // Erase element from current configuration. for (sal_Int32 nI=nIndex; nI=0 && nLocalIndex>=0; --nIndex,--nLocalIndex) @@ -259,7 +258,7 @@ bool ResourceId::IsBoundToAnchor ( // Check the lengths. if (nLocalAnchorURLCount BasicViewFactory::createResource ( const rtl::Reference& rxViewId) { const bool bIsCenterPane ( - rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)); + rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode::DIRECT)); // Get the pane for the anchor URL. rtl::Reference xPane; @@ -202,7 +201,7 @@ void BasicViewFactory::releaseResource (const rtl::Reference& std::shared_ptr pViewShell ((*iViewShell)->mpViewShell); if ((*iViewShell)->mxViewId->isBoundToURL( - FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) + FrameworkHelper::msCenterPaneURL, AnchorBindingMode::DIRECT)) { // Obtain a pointer to and connect to the frame view of the // view. The next view, that is created, will be diff --git a/sd/source/ui/framework/factories/FullScreenPane.cxx b/sd/source/ui/framework/factories/FullScreenPane.cxx index af5e00c940f1..364491cfda42 100644 --- a/sd/source/ui/framework/factories/FullScreenPane.cxx +++ b/sd/source/ui/framework/factories/FullScreenPane.cxx @@ -34,7 +34,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sd::framework { diff --git a/sd/source/ui/framework/factories/PresentationFactory.cxx b/sd/source/ui/framework/factories/PresentationFactory.cxx index afdb35b66475..f213d2cd5758 100644 --- a/sd/source/ui/framework/factories/PresentationFactory.cxx +++ b/sd/source/ui/framework/factories/PresentationFactory.cxx @@ -32,7 +32,6 @@ namespace com::sun::star::uno { class XComponentContext; } using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; -using namespace ::com::sun::star::drawing::framework; namespace sd::framework { @@ -47,12 +46,12 @@ class PresentationView : public AbstractView { public: explicit PresentationView (const rtl::Reference& rxViewId) - : mxResourceId(rxViewId) {}; + : mxResourceId(rxViewId) {} // XView virtual rtl::Reference getResourceId() override - { return mxResourceId; }; + { return mxResourceId; } virtual bool isAnchorOnly() override { return false; } @@ -61,7 +60,7 @@ private: rtl::Reference mxResourceId; }; -} // end of anonymous namespace. +} // end of anonymous namespace //===== PresentationFactory =================================================== diff --git a/sd/source/ui/framework/module/CenterViewFocusModule.cxx b/sd/source/ui/framework/module/CenterViewFocusModule.cxx index 211f07f9e995..8dd86ca6f29d 100644 --- a/sd/source/ui/framework/module/CenterViewFocusModule.cxx +++ b/sd/source/ui/framework/module/CenterViewFocusModule.cxx @@ -31,7 +31,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; @@ -114,7 +113,7 @@ void CenterViewFocusModule::HandleNewView ( std::vector > xViewIds (rxConfiguration->getResources( new ::sd::framework::ResourceId(FrameworkHelper::msCenterPaneURL), FrameworkHelper::msViewURLPrefix, - AnchorBindingMode_DIRECT)); + AnchorBindingMode::DIRECT)); rtl::Reference xView; if (!xViewIds.empty()) xView = dynamic_cast( mxConfigurationController->getResource(xViewIds[0]).get() ); diff --git a/sd/source/ui/framework/module/NotesPaneModule.cxx b/sd/source/ui/framework/module/NotesPaneModule.cxx index b3ca810a83d7..d0d8afbcea57 100644 --- a/sd/source/ui/framework/module/NotesPaneModule.cxx +++ b/sd/source/ui/framework/module/NotesPaneModule.cxx @@ -26,7 +26,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sd::framework { @@ -133,7 +132,7 @@ void NotesPaneModule::notifyConfigurationChange(const ConfigurationChangeEvent& if (!mxConfigurationController.is()) return; - // the late init is hacked here since there's EventMultiplexer isn't available when the + // the late init is hacked here since the EventMultiplexer isn't available when the // NotesPaneModule is constructed if (!mbListeningEventMultiplexer) { @@ -146,7 +145,7 @@ void NotesPaneModule::notifyConfigurationChange(const ConfigurationChangeEvent& { case ConfigurationChangeEventType::ResourceActivationRequest: if (rEvent.ResourceId->isBoundToURL(FrameworkHelper::msCenterPaneURL, - AnchorBindingMode_DIRECT)) + AnchorBindingMode::DIRECT)) { if (rEvent.ResourceId->getResourceTypePrefix() == FrameworkHelper::msViewURLPrefix) { @@ -233,7 +232,7 @@ void NotesPaneModule::onResourceRequest( { std::vector> aCenterViews = rxConfiguration->getResources( new ::sd::framework::ResourceId(FrameworkHelper::msCenterPaneURL), - FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT); + FrameworkHelper::msViewURLPrefix, AnchorBindingMode::DIRECT); if (aCenterViews.size() != 1) return; diff --git a/sd/source/ui/framework/module/ShellStackGuard.cxx b/sd/source/ui/framework/module/ShellStackGuard.cxx index a4ad18d25a79..dac7763900ec 100644 --- a/sd/source/ui/framework/module/ShellStackGuard.cxx +++ b/sd/source/ui/framework/module/ShellStackGuard.cxx @@ -30,7 +30,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; diff --git a/sd/source/ui/framework/module/SlideSorterModule.cxx b/sd/source/ui/framework/module/SlideSorterModule.cxx index 397d11d013b1..4c74f8b87681 100644 --- a/sd/source/ui/framework/module/SlideSorterModule.cxx +++ b/sd/source/ui/framework/module/SlideSorterModule.cxx @@ -34,7 +34,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; @@ -123,7 +122,7 @@ void SlideSorterModule::notifyConfigurationChange ( FrameworkHelper::msViewURLPrefix && rEvent.ResourceId->isBoundTo( new ::sd::framework::ResourceId(FrameworkHelper::msCenterPaneURL), - AnchorBindingMode_DIRECT)) + AnchorBindingMode::DIRECT)) { // Update the view tab bar because the view in the center pane // has changed. @@ -138,7 +137,7 @@ void SlideSorterModule::notifyConfigurationChange ( case ConfigurationChangeEventType::ResourceActivationRequest: if (rEvent.ResourceId->isBoundToURL( FrameworkHelper::msCenterPaneURL, - AnchorBindingMode_DIRECT)) + AnchorBindingMode::DIRECT)) { // A resource directly bound to the center pane has been // requested. @@ -155,7 +154,7 @@ void SlideSorterModule::notifyConfigurationChange ( else if (rEvent.ResourceId->compareTo(mxResourceId) == 0) { // The resource managed by this ResourceManager has been - // explicitly been requested (maybe by us). Remember this + // explicitly requested (maybe by us). Remember this // setting. HandleResourceRequest(true, rEvent.Configuration); } @@ -171,7 +170,7 @@ void SlideSorterModule::notifyConfigurationChange ( else if (rEvent.ResourceId->compareTo(mxResourceId) == 0) { // The resource managed by this ResourceManager has been - // explicitly been requested to be hidden (maybe by us). + // explicitly requested to be hidden (maybe by us). // Remember this setting. HandleResourceRequest(false, rEvent.Configuration); } @@ -273,7 +272,7 @@ void SlideSorterModule::HandleResourceRequest( std::vector > aCenterViews = rxConfiguration->getResources( new ::sd::framework::ResourceId(FrameworkHelper::msCenterPaneURL), FrameworkHelper::msViewURLPrefix, - AnchorBindingMode_DIRECT); + AnchorBindingMode::DIRECT); if (aCenterViews.size() == 1) { if (bActivation) diff --git a/sd/source/ui/framework/module/ToolBarModule.cxx b/sd/source/ui/framework/module/ToolBarModule.cxx index f2e98de97e16..09361e9b5ee8 100644 --- a/sd/source/ui/framework/module/ToolBarModule.cxx +++ b/sd/source/ui/framework/module/ToolBarModule.cxx @@ -35,7 +35,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; @@ -125,7 +124,7 @@ void ToolBarModule::notifyConfigurationChange ( if (rEvent.ResourceId->getResourceURL().match( FrameworkHelper::msViewURLPrefix) && rEvent.ResourceId->isBoundToURL( - FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) + FrameworkHelper::msCenterPaneURL, AnchorBindingMode::DIRECT)) { mbMainViewSwitchUpdatePending = true; } @@ -196,7 +195,7 @@ void ToolBarModule::HandleUpdateEnd() UpdateToolbars(pViewShell.get()); } } - // Releasing the update lock of the ToolBarManager will let the + // Releasing the update lock of the ToolBarManager will let the // ToolBarManager with the help of the ViewShellManager take care of // updating tool bars and view shell with the minimal amount of // shell stack modifications and tool bar updates. diff --git a/sd/source/ui/framework/module/ViewTabBarModule.cxx b/sd/source/ui/framework/module/ViewTabBarModule.cxx index d3e015459bd4..056697c191d2 100644 --- a/sd/source/ui/framework/module/ViewTabBarModule.cxx +++ b/sd/source/ui/framework/module/ViewTabBarModule.cxx @@ -31,7 +31,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; @@ -86,7 +85,7 @@ void ViewTabBarModule::notifyConfigurationChange ( switch (rEvent.Type) { case ConfigurationChangeEventType::ResourceActivationRequest: - if (mxViewTabBarId->isBoundTo(rEvent.ResourceId, AnchorBindingMode_DIRECT)) + if (mxViewTabBarId->isBoundTo(rEvent.ResourceId, AnchorBindingMode::DIRECT)) { mxConfigurationController->requestResourceActivation( mxViewTabBarId, @@ -95,7 +94,7 @@ void ViewTabBarModule::notifyConfigurationChange ( break; case ConfigurationChangeEventType::ResourceDeactivationRequest: - if (mxViewTabBarId->isBoundTo(rEvent.ResourceId, AnchorBindingMode_DIRECT)) + if (mxViewTabBarId->isBoundTo(rEvent.ResourceId, AnchorBindingMode::DIRECT)) { mxConfigurationController->requestResourceDeactivation(mxViewTabBarId); } diff --git a/sd/source/ui/framework/tools/FrameworkHelper.cxx b/sd/source/ui/framework/tools/FrameworkHelper.cxx index c886d78da41c..a78106c53799 100644 --- a/sd/source/ui/framework/tools/FrameworkHelper.cxx +++ b/sd/source/ui/framework/tools/FrameworkHelper.cxx @@ -46,7 +46,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; namespace sd::framework { @@ -65,8 +64,8 @@ public: lifetime by acquiring a reference to itself in the constructor. When it detects that the event will not be notified in the near future (because the queue of pending configuration change operations - is empty and therefore no event will be sent int the near future, it - does not acquires a reference and thus initiates its destruction in + is empty and therefore no event will be sent in the near future, it + does not acquire a reference and thus initiates its destruction in the constructor.) @param rBase This ViewShellBase object is used to determine the @@ -219,7 +218,7 @@ namespace { rtl::Reference< sd::framework::Configuration > xConfiguration( i_rConfigController->getRequestedConfiguration() ); std::vector< rtl::Reference< ResourceId > > aViewIds( xConfiguration->getResources( - i_rPaneId, FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT ) ); + i_rPaneId, FrameworkHelper::msViewURLPrefix, AnchorBindingMode::DIRECT)); if ( !aViewIds.empty() ) return i_rConfigController->getResource( aViewIds[0] ); } @@ -911,12 +910,12 @@ void LifetimeController::Update() else { // Both the controller and the ViewShellBase have been destroyed. - // Remove the FrameworkHelper so that the next call its Instance() + // Remove the FrameworkHelper so that the next call to its Instance() // method can create a new instance. ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase); } } -} // end of anonymous namespace. +} // end of anonymous namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/bulmaper.cxx b/sd/source/ui/func/bulmaper.cxx index c2727aefbc25..1fd05df5e2d6 100644 --- a/sd/source/ui/func/bulmaper.cxx +++ b/sd/source/ui/func/bulmaper.cxx @@ -50,7 +50,7 @@ void SdBulletMapper::MapFontsInNumRule( SvxNumRule& aNumRule, const SfxItemSet& if(rSrcLevel.GetNumberingType() != css::style::NumberingType::CHAR_SPECIAL && rSrcLevel.GetNumberingType() != css::style::NumberingType::NUMBER_NONE ) { - // if enumeration instead bullet is chosen, adjust bullet font to template font + // if enumeration instead of bullet is chosen, adjust bullet font to template font // to be implemented if module supports CJK diff --git a/sd/source/ui/func/fubullet.cxx b/sd/source/ui/func/fubullet.cxx index 076062786a21..5e18dcfb6b36 100644 --- a/sd/source/ui/func/fubullet.cxx +++ b/sd/source/ui/func/fubullet.cxx @@ -243,7 +243,7 @@ void FuBullet::InsertSpecialCharacter( SfxRequest const & rReq ) empty string). */ pOV->InsertText( u""_ustr ); - SfxItemSetFixed aOldSet( mrDoc.GetPool() ); + SfxItemSet aOldSet(SfxItemSet::makeFixedSfxItemSet( mrDoc.GetPool() )); aOldSet.Put( pOV->GetAttribs() ); EditUndoManager& rUndoMgr = pOL->GetUndoManager(); diff --git a/sd/source/ui/func/fuchar.cxx b/sd/source/ui/func/fuchar.cxx index 89573d174e88..6454387e4710 100644 --- a/sd/source/ui/func/fuchar.cxx +++ b/sd/source/ui/func/fuchar.cxx @@ -62,7 +62,7 @@ void FuChar::DoExecute( SfxRequest& rReq ) SfxItemSet aEditAttr( mrDoc.GetPool() ); mpView->GetAttributes( aEditAttr ); - SfxItemSetFixed aNewAttr(mrViewShell.GetPool()); + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet(mrViewShell.GetPool())); aNewAttr.Put( aEditAttr, false ); SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); diff --git a/sd/source/ui/func/fucon3d.cxx b/sd/source/ui/func/fucon3d.cxx index 7092ba1111b5..c1796edb0da7 100644 --- a/sd/source/ui/func/fucon3d.cxx +++ b/sd/source/ui/func/fucon3d.cxx @@ -30,8 +30,8 @@ #include #include #include - -#include +#include +#include #include diff --git a/sd/source/ui/func/fuconstr.cxx b/sd/source/ui/func/fuconstr.cxx index 612282884073..2daca7bee4e7 100644 --- a/sd/source/ui/func/fuconstr.cxx +++ b/sd/source/ui/func/fuconstr.cxx @@ -333,7 +333,7 @@ void FuConstruct::SetStyleSheet( SfxItemSet& rAttr, SdrObject* pObj, mrDoc.GetDocumentType() == DocumentType::Impress ) { /********************************************** - * Objects was created on the slide master page + * Object was created on the slide master page ***********************************************/ OUString aName( pPage->GetLayoutName() ); sal_Int32 n = aName.indexOf(SD_LT_SEPARATOR) + SD_LT_SEPARATOR.getLength(); diff --git a/sd/source/ui/func/fucopy.cxx b/sd/source/ui/func/fucopy.cxx index 6b7caea944b5..78926c02d7d4 100644 --- a/sd/source/ui/func/fucopy.cxx +++ b/sd/source/ui/func/fucopy.cxx @@ -36,6 +36,8 @@ #include #include #include +#include + #include using namespace com::sun::star; @@ -75,7 +77,7 @@ void FuCopy::DoExecute( SfxRequest& rReq ) if( !pArgs ) { - SfxItemSetFixed aSet( mrViewShell.GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet( mrViewShell.GetPool() )); // indicate color attribute SfxItemSet aAttr( mrDoc.GetPool() ); @@ -91,6 +93,7 @@ void FuCopy::DoExecute( SfxRequest& rReq ) { XColorItem aXColorItem( ATTR_COPY_START_COLOR, pFillColorItem->GetName(), pFillColorItem->GetColorValue() ); + aSet.Put(*pFillStyleItem); aSet.Put( aXColorItem ); } @@ -124,6 +127,7 @@ void FuCopy::DoExecute( SfxRequest& rReq ) sal_uInt16 nNumber = 0; Color aStartColor, aEndColor; bool bColor = false; + ColorInterpolationKind eKind = ColorInterpolationKind::RGB; if (pArgs) { @@ -157,6 +161,12 @@ void FuCopy::DoExecute( SfxRequest& rReq ) if( aStartColor == aEndColor ) bColor = false; } + + if (const SfxUInt16Item* pPoolItem = pArgs->GetItemIfSet( ATTR_COPY_COLOR_TRANSKIND )) + { + eKind = static_cast(pPoolItem->GetValue()); + } + } // remove handles @@ -202,7 +212,7 @@ void FuCopy::DoExecute( SfxRequest& rReq ) if( ( 1 == i ) && bColor ) { - SfxItemSetFixed aNewSet( mrViewShell.GetPool() ); + SfxItemSet aNewSet(SfxItemSet::makeFixedSfxItemSet( mrViewShell.GetPool() )); aNewSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); aNewSet.Put( XFillColorItem( OUString(), aStartColor ) ); mpView->SetAttributes( aNewSet ); @@ -227,8 +237,12 @@ void FuCopy::DoExecute( SfxRequest& rReq ) } } - double aWidth = double( aRect.Right() - aRect.Left() + lWidth ) / ( aRect.Right() - aRect.Left() ); - double aHeight = double( aRect.Bottom() - aRect.Top() + lHeight ) / ( aRect.Bottom() - aRect.Top() ); + // vertical/horizontal lines have zero width/height; leave that axis + // unscaled to avoid 0/0=NaN scale propagating into ResizeRect. + const tools::Long nRectW = aRect.Right() - aRect.Left(); + const tools::Long nRectH = aRect.Bottom() - aRect.Top(); + double aWidth = nRectW ? double(nRectW + lWidth) / nRectW : 1.0; + double aHeight = nRectH ? double(nRectH + lHeight) / nRectH : 1.0; if( mpView->IsResizeAllowed() ) mpView->ResizeAllMarked( aRect.TopLeft(), aWidth, aHeight ); @@ -259,12 +273,26 @@ void FuCopy::DoExecute( SfxRequest& rReq ) if( bColor ) { - // probably room for optimizations, but may can lead to rounding errors - sal_uInt8 nRed = aStartColor.GetRed() + static_cast( ( static_cast<::tools::Long>(aEndColor.GetRed()) - static_cast<::tools::Long>(aStartColor.GetRed()) ) * static_cast<::tools::Long>(i) / static_cast<::tools::Long>(nNumber) ); - sal_uInt8 nGreen = aStartColor.GetGreen() + static_cast( ( static_cast<::tools::Long>(aEndColor.GetGreen()) - static_cast<::tools::Long>(aStartColor.GetGreen()) ) * static_cast<::tools::Long>(i) / static_cast<::tools::Long>(nNumber) ); - sal_uInt8 nBlue = aStartColor.GetBlue() + static_cast( ( static_cast<::tools::Long>(aEndColor.GetBlue()) - static_cast<::tools::Long>(aStartColor.GetBlue()) ) * static_cast<::tools::Long>(i) / static_cast<::tools::Long>(nNumber) ); - Color aNewColor( nRed, nGreen, nBlue ); - SfxItemSetFixed aNewSet( mrViewShell.GetPool() ); + basegfx::BColor aStartBColor(aStartColor.getBColor()); + basegfx::BColor aEndBColor(aEndColor.getBColor()); + basegfx::BColor aNewBColor; + switch(eKind) + { + case ColorInterpolationKind::RGB: + aNewBColor = basegfx::interpolate(aStartBColor, aEndBColor, + static_cast(i) / nNumber); + break; + case ColorInterpolationKind::HSLInc: + aNewBColor = basegfx::utils::interpolateInHSL( + aStartBColor, aEndBColor, static_cast(i) / nNumber, true); + break; + case ColorInterpolationKind::HSLDec: + aNewBColor = basegfx::utils::interpolateInHSL( + aStartBColor, aEndBColor, static_cast(i) / nNumber, false); + break; + } + Color aNewColor(aNewBColor); + SfxItemSet aNewSet(SfxItemSet::makeFixedSfxItemSet( mrViewShell.GetPool() )); aNewSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); aNewSet.Put( XFillColorItem( OUString(), aNewColor ) ); mpView->SetAttributes( aNewSet ); diff --git a/sd/source/ui/func/fudraw.cxx b/sd/source/ui/func/fudraw.cxx index 0a955aa238d4..cb7d6072bd64 100644 --- a/sd/source/ui/func/fudraw.cxx +++ b/sd/source/ui/func/fudraw.cxx @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include using namespace ::com::sun::star; @@ -513,10 +513,10 @@ void FuDraw::ForcePointer(const MouseEvent* pMEvt) if ((eDragMode == SdrDragMode::Rotate) && (eHit == SdrHitKind::MarkedObject)) { - // The goal of this request is show always the rotation arrow for 3D-objects at rotation mode + // The goal of this request is to always show the rotation arrow for 3D-objects in rotation mode // Independent of the settings at Tools->Options->Draw "Objects always moveable" - // 2D-objects acquit in another way. Otherwise, the rotation of 3d-objects around any axes - // wouldn't be possible per default. + // 2D-objects act in another way. Otherwise, the rotation of 3d-objects around any axes + // wouldn't be possible by default. const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); SdrObject* pObject = rMarkList.GetMark(0)->GetMarkedSdrObj(); if (DynCastE3dObject(pObject) && (rMarkList.GetMarkCount() == 1)) @@ -624,7 +624,7 @@ bool FuDraw::SetPointer(const SdrObject* pObj, const Point& rPos) } /** - * Response of doubleclick + * Response of double-click */ void FuDraw::DoubleClick(const MouseEvent& rMEvt) { diff --git a/sd/source/ui/func/fuexecuteinteraction.cxx b/sd/source/ui/func/fuexecuteinteraction.cxx index 00a620e92ac7..0ec70f06f134 100644 --- a/sd/source/ui/func/fuexecuteinteraction.cxx +++ b/sd/source/ui/func/fuexecuteinteraction.cxx @@ -152,15 +152,21 @@ void FuExecuteInteraction::DoExecute(SfxRequest&) case presentation::ClickAction_SOUND: { #if HAVE_FEATURE_AVMEDIA - try - { - mxPlayer.set( - avmedia::MediaWindow::createPlayer(pInfo->GetBookmark(), u""_ustr /*TODO?*/), - uno::UNO_SET_THROW); - mxPlayer->start(); - } - catch (uno::Exception&) + // Fetch the sound only when its external link has been allowed this + // session. + SdSoundLink aSound(pInfo->GetBookmark(), pInfo->mbClickSoundAllowed); + if (aSound.isAllowed()) { + try + { + mxPlayer.set( + avmedia::MediaWindow::createPlayer(aSound.getURL(), u""_ustr /*TODO?*/), + uno::UNO_SET_THROW); + mxPlayer->start(); + } + catch (uno::Exception&) + { + } } #endif } diff --git a/sd/source/ui/func/fuexpand.cxx b/sd/source/ui/func/fuexpand.cxx index 2fbf8d96c385..5db1616ba903 100644 --- a/sd/source/ui/func/fuexpand.cxx +++ b/sd/source/ui/func/fuexpand.cxx @@ -114,7 +114,7 @@ void FuExpandPage::DoExecute( SfxRequest& ) aOutliner.SetText(*pParaObj); // remove hard paragraph- and character attributes - SfxItemSetFixed aEmptyEEAttr(mrDoc.GetPool()); + SfxItemSet aEmptyEEAttr(SfxItemSet::makeFixedSfxItemSet(mrDoc.GetPool())); sal_Int32 nParaCount1 = aOutliner.GetParagraphCount(); for (sal_Int32 nPara = 0; nPara < nParaCount1; nPara++) @@ -186,7 +186,7 @@ void FuExpandPage::DoExecute( SfxRequest& ) std::optional pOutlinerParaObject = aOutliner.CreateParaObject( nParaPos, 1); pOutlinerParaObject->SetOutlinerMode(OutlinerMode::TitleObject); - if( pOutlinerParaObject->GetDepth(0) != -1 ) + if( pOutlinerParaObject->GetNumberingDepth(0) != -1 ) { std::unique_ptr pTempOutl = SdrMakeOutliner(OutlinerMode::TitleObject, mrDoc); diff --git a/sd/source/ui/func/fuinsert.cxx b/sd/source/ui/func/fuinsert.cxx index eb9df61de4d7..8309802df7a2 100644 --- a/sd/source/ui/func/fuinsert.cxx +++ b/sd/source/ui/func/fuinsert.cxx @@ -77,7 +77,6 @@ #include #include #include -#include #include #include @@ -86,6 +85,8 @@ #include +#include + using namespace com::sun::star; namespace sd { @@ -113,7 +114,8 @@ rtl::Reference FuInsertGraphic::Create( ViewShell& rViewSh, ::sd::Window void FuInsertGraphic::DoExecute( SfxRequest& rReq ) { - OUString aFileName; + css::uno::Sequence < OUString > aFileNames; + INetURLObject aURL; Graphic aGraphic; bool bAsLink = false; @@ -125,7 +127,8 @@ void FuInsertGraphic::DoExecute( SfxRequest& rReq ) if ( pArgs && pArgs->GetItemState( SID_INSERT_GRAPHIC, true, &pItem ) == SfxItemState::SET ) { - aFileName = static_cast(pItem)->GetValue(); + OUString aFileName = static_cast(pItem)->GetValue(); + aFileNames = css::uno::Sequence(&aFileName, 1); OUString aFilterName; if ( const SfxStringItem* pFilterItem = pArgs->GetItemIfSet( FN_PARAM_FILTER ) ) @@ -136,74 +139,83 @@ void FuInsertGraphic::DoExecute( SfxRequest& rReq ) if (comphelper::LibreOfficeKit::isActive()) { - INetURLObject aURL(aFileName); + aURL = INetURLObject(aFileNames[0]); if (INetProtocol::File != aURL.GetProtocol() && HostFilter::isForbidden(aURL.GetHost())) SfxLokHelper::sendNetworkAccessError("insert"); } - - nError = GraphicFilter::LoadGraphic( aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() ); + nError = GraphicFilter::LoadGraphic( aFileNames[0], aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() ); + if (nError == ERRCODE_GRFILTER_FORMATERROR) + nError = GraphicFilter::LoadGraphic( aFileNames[0], OUString(), aGraphic, + &GraphicFilter::GetGraphicFilter() ); } else { SvxOpenGraphicDialog aDlg(SdResId(STR_INSERTGRAPHIC), mpWindow ? mpWindow->GetFrameWeld() : nullptr); + aDlg.setMultiSelect(true); if( aDlg.Execute() != ERRCODE_NONE ) return; // cancel dialog - nError = aDlg.GetGraphic(aGraphic); bAsLink = aDlg.IsAsLink(); - aFileName = aDlg.GetPath(); + aFileNames = aDlg.GetSelectedFiles(); + aDlg.setMultiSelect(false); } - if( nError == ERRCODE_NONE ) + for (const auto& aFileName : aFileNames) { - GraphicNativeMetadata aMetadata; - if ( aMetadata.read(aGraphic) ) + aURL = INetURLObject(aFileName); + nError = GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, aURL ); + if( nError == ERRCODE_NONE ) { - const Degree10 aRotation = aMetadata.getRotation(); - if (aRotation) + GraphicNativeMetadata aMetadata; + if ( aMetadata.read(aGraphic) ) { - GraphicNativeTransform aTransform( aGraphic ); - aTransform.rotate( aRotation ); + const Degree10 aRotation = aMetadata.getRotation(); + if (aRotation) + { + GraphicNativeTransform aTransform( aGraphic ); + aTransform.rotate( aRotation ); + } } - } - if( dynamic_cast< DrawViewShell *>( &mrViewShell ) ) - { - sal_Int8 nAction = DND_ACTION_COPY; - SdrObject* pPickObj = nullptr; - if (mbReplaceExistingImage) - pPickObj = mpView->GetSelectedSingleObject( mpView->GetPage() ); - if (pPickObj) - nAction = DND_ACTION_LINK; - else + if( dynamic_cast< DrawViewShell *>( &mrViewShell ) ) { - pPickObj = mpView->GetEmptyPresentationObject( PresObjKind::Graphic ); + sal_Int8 nAction = DND_ACTION_COPY; + SdrObject* pPickObj = nullptr; + bool bSingleInsert = (aFileNames.getLength() == 1); + if (mbReplaceExistingImage || bSingleInsert) + pPickObj = mpView->GetSelectedSingleObject( mpView->GetPage() ); if (pPickObj) nAction = DND_ACTION_LINK; - } - - Point aPos = mpWindow->GetVisibleCenter(); - SdrGrafObj* pGrafObj = mpView->InsertGraphic(aGraphic, nAction, aPos, pPickObj, nullptr); - - if(pGrafObj && bAsLink ) - { - // really store as link only? - if( officecfg::Office::Common::Misc::ShowLinkWarningDialog::get() ) + else { - SvxLinkWarningDialog aWarnDlg(mpWindow->GetFrameWeld(), aFileName); - if (aWarnDlg.run() != RET_OK) - return; // don't store as link + pPickObj = mpView->GetPresentationObjectForGraphic(); + if (pPickObj) + nAction = DND_ACTION_LINK; } - // store as link - pGrafObj->SetGraphicLink(aFileName); + Point aPos = mpWindow->GetVisibleCenter(); + SdrGrafObj* pGrafObj = mpView->InsertGraphic(aGraphic, nAction, aPos, pPickObj, nullptr); + + if(pGrafObj && bAsLink ) + { + // really store as link only? + if( officecfg::Office::Common::Misc::ShowLinkWarningDialog::get() ) + { + SvxLinkWarningDialog aWarnDlg(mpWindow->GetFrameWeld(), aFileName); + if (aWarnDlg.run() != RET_OK) + return; // don't store as link + } + + // store as link + pGrafObj->SetGraphicLink(aFileName); + } } } - } - else if (!comphelper::LibreOfficeKit::isActive()) - { - // TODO: enable in LOK, it contains synchronous error window without LOKNotifier - SdGRFFilter::HandleGraphicFilterError( nError, GraphicFilter::GetGraphicFilter().GetLastError() ); + else if (!comphelper::LibreOfficeKit::isActive()) + { + // TODO: enable in LOK, it contains synchronous error window without LOKNotifier + SdGRFFilter::HandleGraphicFilterError( nError, GraphicFilter::GetGraphicFilter().GetLastError() ); + } } } @@ -389,7 +401,7 @@ void FuInsertOLE::DoExecute( SfxRequest& rReq ) } // #i123468# we need to end text edit before replacing the object. There cannot yet - // being text typed (else it would not be an EmptyPresObj anymore), but it may be + // be text typed (else it would not be an EmptyPresObj anymore), but it may be // in text edit mode if (mpView->IsTextEdit()) { @@ -721,7 +733,7 @@ void FuInsertAVMedia::DoExecute( SfxRequest& rReq ) } else { - // If we don't have a size then try and find that out, the resulted might be deliver async, so dispatch a follow up + // If we don't have a size then try and find that out, the result might be delivered async, so dispatch a follow up // effort to insert the video, this time with a size. if( mpWindow ) mpWindow->EnterWait(); diff --git a/sd/source/ui/func/fuinsfil.cxx b/sd/source/ui/func/fuinsfil.cxx index 6a785eae6c02..6fca3487e28d 100644 --- a/sd/source/ui/func/fuinsfil.cxx +++ b/sd/source/ui/func/fuinsfil.cxx @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/sd/source/ui/func/fulinend.cxx b/sd/source/ui/func/fulinend.cxx index 1ab9ae47620a..ff774c40c387 100644 --- a/sd/source/ui/func/fulinend.cxx +++ b/sd/source/ui/func/fulinend.cxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/sd/source/ui/func/fumorph.cxx b/sd/source/ui/func/fumorph.cxx index 4c80d4b9951e..c5b7516de0ec 100644 --- a/sd/source/ui/func/fumorph.cxx +++ b/sd/source/ui/func/fumorph.cxx @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -43,6 +45,7 @@ #include #include +#include using namespace com::sun::star; @@ -314,122 +317,178 @@ void FuMorph::ImpAddPolys( /** * create group object with morphed polygons */ -void FuMorph::ImpInsertPolygons( - B2DPolyPolygonList_impl& rPolyPolyList3D, - bool bAttributeFade, - const SdrObject* pObj1, - const SdrObject* pObj2 -) +namespace { - Color aStartFillCol; - Color aEndFillCol; - Color aStartLineCol; - Color aEndLineCol; - ::tools::Long nStartLineWidth = 0; - ::tools::Long nEndLineWidth = 0; - SdrPageView* pPageView = mpView->GetSdrPageView(); - SfxItemPool & rPool = pObj1->GetObjectItemPool(); - SfxItemSetFixed aSet1( rPool ); - SfxItemSet aSet2( aSet1 ); - bool bLineColor = false; - bool bFillColor = false; - bool bLineWidth = false; - bool bIgnoreLine = false; - bool bIgnoreFill = false; + struct FillAndLineProps + { + drawing::FillStyle eFillStyle; + Color aFillColor; + sal_uInt16 nFillTransparence = 0; + drawing::LineStyle eLineStyle; + ::tools::Long nLineWidth = 0; + Color aLineColor; + sal_uInt16 nLineTransparence = 0; + }; +void getFillAndLinePropsFromObject(const SdrObject* pObj, FillAndLineProps& rFillAndLineProps) +{ + const sdr::properties::BaseProperties& rProps = pObj->GetProperties(); + rFillAndLineProps.eFillStyle = rProps.GetItem(XATTR_FILLSTYLE).GetValue(); + if (rFillAndLineProps.eFillStyle == drawing::FillStyle_SOLID) + { + rFillAndLineProps.aFillColor = rProps.GetItem(XATTR_FILLCOLOR).GetColorValue(); + rFillAndLineProps.nFillTransparence = rProps.GetItem(XATTR_FILLTRANSPARENCE).GetValue(); + } + rFillAndLineProps.eLineStyle = rProps.GetItem(XATTR_LINESTYLE).GetValue(); + if (rFillAndLineProps.eLineStyle != drawing::LineStyle_NONE) + { + rFillAndLineProps.nLineWidth = rProps.GetItem(XATTR_LINEWIDTH).GetValue(); + rFillAndLineProps.aLineColor = rProps.GetItem(XATTR_LINECOLOR).GetColorValue(); + rFillAndLineProps.nLineTransparence = rProps.GetItem(XATTR_LINETRANSPARENCE).GetValue(); + } +} +} // end namespace + +void FuMorph::ImpInsertPolygons(B2DPolyPolygonList_impl& rPolyPolyList3D, bool bAttributeFade, + const SdrObject* pObj1, const SdrObject* pObj2) +{ + SdrPageView* pPageView = mpView->GetSdrPageView(); + if ( !pPageView ) + return; // Should not happen. Would be error in caller. + + const size_t nCount = rPolyPolyList3D.size(); + if (nCount == 0) + return; + + SfxItemPool& rPool = pObj1->GetObjectItemPool(); + SfxItemSet aSet1(SfxItemSet::makeFixedSfxItemSet(rPool)); + SfxItemSet aSet2(aSet1); aSet1.Put(pObj1->GetMergedItemSet()); aSet2.Put(pObj2->GetMergedItemSet()); - const drawing::LineStyle eLineStyle1 = aSet1.Get(XATTR_LINESTYLE).GetValue(); - const drawing::LineStyle eLineStyle2 = aSet2.Get(XATTR_LINESTYLE).GetValue(); - const drawing::FillStyle eFillStyle1 = aSet1.Get(XATTR_FILLSTYLE).GetValue(); - const drawing::FillStyle eFillStyle2 = aSet2.Get(XATTR_FILLSTYLE).GetValue(); - - if ( bAttributeFade ) + // Prepare fill and line properties. + bool bIgnoreLine = false; + bool bIgnoreFill = false; + FillAndLineProps aStartProps; + FillAndLineProps aEndProps; + if (bAttributeFade) { - if ( ( eLineStyle1 != drawing::LineStyle_NONE ) && ( eLineStyle2 != drawing::LineStyle_NONE ) ) - { - bLineWidth = bLineColor = true; + getFillAndLinePropsFromObject(pObj1, aStartProps); + getFillAndLinePropsFromObject(pObj2, aEndProps); - aStartLineCol = aSet1.Get(XATTR_LINECOLOR).GetColorValue(); - aEndLineCol = aSet2.Get(XATTR_LINECOLOR).GetColorValue(); - - nStartLineWidth = aSet1.Get(XATTR_LINEWIDTH).GetValue(); - nEndLineWidth = aSet2.Get(XATTR_LINEWIDTH).GetValue(); - } - else if ( ( eLineStyle1 == drawing::LineStyle_NONE ) && ( eLineStyle2 == drawing::LineStyle_NONE ) ) - bIgnoreLine = true; - - if ( ( eFillStyle1 == drawing::FillStyle_SOLID ) && ( eFillStyle2 == drawing::FillStyle_SOLID ) ) - { - bFillColor = true; - aStartFillCol = aSet1.Get(XATTR_FILLCOLOR).GetColorValue(); - aEndFillCol = aSet2.Get(XATTR_FILLCOLOR).GetColorValue(); - } - else if ( ( eFillStyle1 == drawing::FillStyle_NONE ) && ( eFillStyle2 == drawing::FillStyle_NONE ) ) + // Inspect fill properties + // The view guarantees that only NONE or SOLID appear for fill. No need to test again. + if (aStartProps.eFillStyle == drawing::FillStyle_NONE + && aEndProps.eFillStyle == drawing::FillStyle_NONE) bIgnoreFill = true; + else + { + // We fake NONE with a solid, transparent fill to get a nice cross-fading. + if (aStartProps.eFillStyle == drawing::FillStyle_NONE) + { + aStartProps.eFillStyle = drawing::FillStyle_SOLID; + aStartProps.nFillTransparence = 100; + aStartProps.aFillColor = aEndProps.aFillColor; + } + if (aEndProps.eFillStyle == drawing::FillStyle_NONE) + { + aEndProps.eFillStyle = drawing::FillStyle_SOLID; + aEndProps.nFillTransparence = 100; + aEndProps.aFillColor = aStartProps.aFillColor; + } + } + + // Inspect line properties + if (aStartProps.eLineStyle == drawing::LineStyle_NONE + && aEndProps.eLineStyle == drawing::LineStyle_NONE) + bIgnoreLine = true; + else + { + // We cannot morph any dash style. Instead we use SOLID in between. + if (aStartProps.eLineStyle != drawing::LineStyle_NONE) + aStartProps.eLineStyle = drawing::LineStyle_SOLID; + if (aEndProps.eLineStyle != drawing::LineStyle_NONE) + aEndProps.eLineStyle = drawing::LineStyle_SOLID; + // Now type for start,end can be NONE,SOLID or SOLID,NONE or SOLID,SOLID. + // We fake NONE with a solid, transparent hairline to get a nice cross-fading. + if (aStartProps.eLineStyle == drawing::LineStyle_NONE) + { + aStartProps.eLineStyle = drawing::LineStyle_SOLID; + aStartProps.nLineWidth = 0; + aStartProps.nLineTransparence = 100; + aStartProps.aLineColor = aEndProps.aLineColor; + } + if (aEndProps.eLineStyle == drawing::LineStyle_NONE) + { + aEndProps.eLineStyle = drawing::LineStyle_SOLID; + aEndProps.nLineWidth = 0; + aEndProps.nLineTransparence = 100; + aEndProps.aLineColor = aStartProps.aLineColor; + } + } } - if ( !pPageView ) - return; - - SfxItemSet aSet( std::move(aSet1) ); + // Initialize group object rtl::Reference xObjGroup(new SdrObjGroup(mpView->getSdrModelFromSdrView())); - SdrObjList* pObjList = xObjGroup->GetSubList(); - const size_t nCount = rPolyPolyList3D.size(); + SdrObjList* pObjList = xObjGroup->GetSubList(); + pObjList->InsertObject(pObj1->CloneSdrObject(pObj1->getSdrModelFromSdrObject()).get()); + SfxItemSet aSet( std::move(aSet1) ); + aSet.Put(XLineStyleItem(drawing::LineStyle_SOLID)); + aSet.Put(XFillStyleItem(drawing::FillStyle_SOLID)); + + // Prepare linear interpolation of fill and line properties const double fStep = 1. / ( nCount + 1 ); - const double fDelta = nEndLineWidth - nStartLineWidth; double fFactor = fStep; - aSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) ); - aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); - + // For each intermediate B2DPolyPolygon create a new SdrPathObj, apply interpolated fill and line + // properties if applicable, and then add it to the group object. for ( size_t i = 0; i < nCount; i++, fFactor += fStep ) { + // create object const ::basegfx::B2DPolyPolygon& rPolyPoly3D = rPolyPolyList3D[ i ]; - rtl::Reference pNewObj = new SdrPathObj( - mpView->getSdrModelFromSdrView(), - SdrObjKind::Polygon, - rPolyPoly3D); + rtl::Reference pNewObj + = new SdrPathObj(mpView->getSdrModelFromSdrView(), SdrObjKind::Polygon, rPolyPoly3D); - // line color - if ( bLineColor ) + if (bAttributeFade) { - const basegfx::BColor aLineColor(basegfx::interpolate(aStartLineCol.getBColor(), aEndLineCol.getBColor(), fFactor)); - aSet.Put( XLineColorItem( u""_ustr, Color(aLineColor))); - } - else if ( bIgnoreLine ) - aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) ); + // line color and transparence + if (bIgnoreLine) + aSet.Put(XLineStyleItem(drawing::LineStyle_NONE)); + else + { + const basegfx::BColor aLineCol(basegfx::interpolate( + aStartProps.aLineColor.getBColor(), aEndProps.aLineColor.getBColor(), fFactor)); + aSet.Put(XLineColorItem( u""_ustr, Color(aLineCol))); + const double fLineTransparence = aEndProps.nLineTransparence * fFactor + + aStartProps.nLineTransparence * (1.0 - fFactor); + aSet.Put(XLineTransparenceItem(static_cast(fLineTransparence + 0.5))); + const double fLineWidth + = aEndProps.nLineWidth * fFactor + aStartProps.nLineWidth * (1.0 - fFactor); + aSet.Put(XLineWidthItem(static_cast<::tools::Long>(fLineWidth + 0.5))); + } - // fill color - if ( bFillColor ) - { - const basegfx::BColor aFillColor(basegfx::interpolate(aStartFillCol.getBColor(), aEndFillCol.getBColor(), fFactor)); - aSet.Put( XFillColorItem( u""_ustr, Color(aFillColor))); + // fill color and transparence + if (bIgnoreFill) + aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) ); + else + { + const basegfx::BColor aFillCol(basegfx::interpolate( + aStartProps.aFillColor.getBColor(), aEndProps.aFillColor.getBColor(), fFactor)); + aSet.Put(XFillColorItem( u""_ustr, Color(aFillCol))); + const double fFillTransparence = aEndProps.nFillTransparence * fFactor + + aStartProps.nFillTransparence * (1.0 - fFactor); + aSet.Put(XFillTransparenceItem(static_cast(fFillTransparence + 0.5))); + } } - else if ( bIgnoreFill ) - aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) ); - - // line width - if ( bLineWidth ) - aSet.Put( XLineWidthItem( nStartLineWidth + static_cast<::tools::Long>( fFactor * fDelta + 0.5 ) ) ); pNewObj->SetMergedItemSetAndBroadcast(aSet); - pObjList->InsertObject( pNewObj.get() ); } + pObjList->InsertObject(pObj2->CloneSdrObject(pObj2->getSdrModelFromSdrObject()).get()); - if ( nCount ) - { - pObjList->InsertObject( - pObj1->CloneSdrObject(pObj1->getSdrModelFromSdrObject()).get(), - 0 ); - pObjList->InsertObject( - pObj2->CloneSdrObject(pObj2->getSdrModelFromSdrObject()).get() ); - - mpView->DeleteMarked(); - mpView->InsertObjectAtView(xObjGroup.get(), *pPageView, SdrInsertFlags:: SETDEFLAYER); - } + mpView->DeleteMarked(); + mpView->InsertObjectAtView(xObjGroup.get(), *pPageView, SdrInsertFlags:: SETDEFLAYER); } /** @@ -501,6 +560,6 @@ void FuMorph::ImpMorphPolygons( } } -} // end of namespace sd +} // namespace sd /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuoaprms.cxx b/sd/source/ui/func/fuoaprms.cxx index e34e9341749f..e1afb6bd4904 100644 --- a/sd/source/ui/func/fuoaprms.cxx +++ b/sd/source/ui/func/fuoaprms.cxx @@ -146,7 +146,7 @@ void FuObjectAnimationParameters::DoExecute( SfxRequest& rReq ) bSoundOn = pInfo->mbSoundOn; nSoundOnSet = ATTR_SET; - aSound = pInfo->maSoundFile; + aSound = pInfo->maSoundLink.getURL(); nSoundFileSet = ATTR_SET; bPlayFull = pInfo->mbPlayFull; @@ -203,7 +203,7 @@ void FuObjectAnimationParameters::DoExecute( SfxRequest& rReq ) if( bSoundOn != pInfo->mbSoundOn ) nSoundOnSet = ATTR_MIXED; - if( aSound != pInfo->maSoundFile ) + if( aSound != pInfo->maSoundLink.getURL() ) nSoundFileSet = ATTR_MIXED; if( bPlayFull != pInfo->mbPlayFull ) @@ -319,7 +319,7 @@ void FuObjectAnimationParameters::DoExecute( SfxRequest& rReq ) aFadeColor = pInfo->maDimColor; nFadeColorSet = ATTR_SET; bInvisible = pInfo->mbDimHide; nInvisibleSet = ATTR_SET; bSoundOn = pInfo->mbSoundOn; nSoundOnSet = ATTR_SET; - aSound = pInfo->maSoundFile; nSoundFileSet = ATTR_SET; + aSound = pInfo->maSoundLink.getURL(); nSoundFileSet = ATTR_SET; bPlayFull = pInfo->mbPlayFull; nPlayFullSet = ATTR_SET; eClickAction = pInfo->meClickAction; nClickActionSet = ATTR_SET; aBookmark = pInfo->GetBookmark(); nBookmarkSet = ATTR_SET; @@ -335,7 +335,7 @@ void FuObjectAnimationParameters::DoExecute( SfxRequest& rReq ) if(!pArgs) { // fill ItemSet for dialog - std::shared_ptr aSet = std::make_shared>(mrDoc.GetPool()); + std::shared_ptr aSet = std::make_shared(SfxItemSet::makeFixedSfxItemSet(mrDoc.GetPool())); // fill the set if (nAnimationSet == ATTR_SET) @@ -746,7 +746,7 @@ void FuObjectAnimationParameters::Finish( const std::shared_ptr& xRe pAction->SetDimColor(pInfo->maDimColor, pInfo->maDimColor); pAction->SetDimHide(pInfo->mbDimHide, pInfo->mbDimHide); pAction->SetSoundOn(pInfo->mbSoundOn, pInfo->mbSoundOn); - pAction->SetSound(pInfo->maSoundFile, pInfo->maSoundFile); + pAction->SetSound(pInfo->maSoundLink, pInfo->maSoundLink); pAction->SetPlayFull(pInfo->mbPlayFull, pInfo->mbPlayFull); pAction->SetClickAction(pInfo->meClickAction, pInfo->meClickAction); pAction->SetBookmark(pInfo->GetBookmark(), pInfo->GetBookmark()); @@ -760,6 +760,13 @@ void FuObjectAnimationParameters::Finish( const std::shared_ptr& xRe } else { + // A sound the user picks here is allowed; one left unchanged keeps + // the allowed state it already has. The undo action and the applied + // value share this new link, so redo restores the allow as well. + const SdSoundLink aNewSoundLink + = (nSoundFileSet == ATTR_SET && aSound != pInfo->maSoundLink.getURL()) + ? SdSoundLink(aSound, true) + : pInfo->maSoundLink; // create undo action with old and new sizes SdAnimationPrmsUndoAction* pAction = new SdAnimationPrmsUndoAction @@ -772,7 +779,7 @@ void FuObjectAnimationParameters::Finish( const std::shared_ptr& xRe pAction->SetDimColor(pInfo->maDimColor, aFadeColor); pAction->SetDimHide(pInfo->mbDimHide, bInvisible); pAction->SetSoundOn(pInfo->mbSoundOn, bSoundOn); - pAction->SetSound(pInfo->maSoundFile, aSound); + pAction->SetSound(pInfo->maSoundLink, aNewSoundLink); pAction->SetPlayFull(pInfo->mbPlayFull, bPlayFull); pAction->SetClickAction(pInfo->meClickAction, eClickAction); pAction->SetBookmark(pInfo->GetBookmark(), aBookmark); @@ -809,7 +816,7 @@ void FuObjectAnimationParameters::Finish( const std::shared_ptr& xRe pInfo->mbSoundOn = bSoundOn; if (nSoundFileSet == ATTR_SET) - pInfo->maSoundFile = aSound; + pInfo->maSoundLink = aNewSoundLink; if (nPlayFullSet == ATTR_SET) pInfo->mbPlayFull = bPlayFull; @@ -818,7 +825,16 @@ void FuObjectAnimationParameters::Finish( const std::shared_ptr& xRe pInfo->meClickAction = eClickAction; if (nBookmarkSet == ATTR_SET) + { + // A click-action sound the user picks here is allowed; one left + // unchanged keeps whatever allowed state it already had. + const bool bSoundChanged + = pInfo->meClickAction == presentation::ClickAction_SOUND + && aBookmark != pInfo->GetBookmark(); pInfo->SetBookmark( aBookmark ); + if (bSoundChanged) + pInfo->mbClickSoundAllowed = true; + } if (nSecondEffectSet == ATTR_SET) pInfo->meSecondEffect = eSecondEffect; diff --git a/sd/source/ui/func/fuolbull.cxx b/sd/source/ui/func/fuolbull.cxx index 246176da700c..c87dfa6218b2 100644 --- a/sd/source/ui/func/fuolbull.cxx +++ b/sd/source/ui/func/fuolbull.cxx @@ -79,7 +79,7 @@ void FuBulletAndPosition::DoExecute( SfxRequest& rReq ) SfxItemSet aEditAttr( mrDoc.GetPool() ); mpView->GetAttributes( aEditAttr ); - SfxItemSetFixed aNewAttr( mrViewShell.GetPool() ); + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet( mrViewShell.GetPool() )); aNewAttr.Put( aEditAttr, false ); auto pView = mpView; @@ -132,7 +132,7 @@ void FuBulletAndPosition::SetCurrentBulletsNumbering(SfxRequest& rReq) return; } - SfxItemSetFixed aNewAttr( mrViewShell.GetPool() ); + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet( mrViewShell.GetPool() )); { SfxItemSet aEditAttr( mrDoc.GetPool() ); mpView->GetAttributes( aEditAttr ); @@ -253,7 +253,7 @@ void FuBulletAndPosition::SetCurrentBulletsNumbering(SfxRequest& rReq) if (bInMasterView && pNumRule) { - SfxItemSetFixed aSetAttr( mrViewShell.GetPool() ); + SfxItemSet aSetAttr(SfxItemSet::makeFixedSfxItemSet( mrViewShell.GetPool() )); aSetAttr.Put(SvxNumBulletItem( *pNumRule, nNumItemId )); mpView->SetAttributes(aSetAttr); } diff --git a/sd/source/ui/func/fuoltext.cxx b/sd/source/ui/func/fuoltext.cxx index 216a86d7c631..7af67a21e280 100644 --- a/sd/source/ui/func/fuoltext.cxx +++ b/sd/source/ui/func/fuoltext.cxx @@ -88,6 +88,14 @@ void FuOutlineText::UpdateForKeyPress (const KeyEvent& rEvent) mrViewShell.UpdatePreview(mrViewShell.GetActualPage()); } +bool FuOutlineText::MouseButtonUp(const MouseEvent& rMEvt) +{ + const bool bReturn = FuSimpleOutlinerText::MouseButtonUp(rMEvt); + // tdf#99079 - update slide selection to match the cursor position + mrViewShell.UpdatePreview(mrViewShell.GetActualPage()); + return bReturn; +} + /** * Process keyboard input * @returns sal_True if a KeyEvent is being processed, sal_False otherwise diff --git a/sd/source/ui/func/fupage.cxx b/sd/source/ui/func/fupage.cxx index 0424ea8c5d6e..2893cdf37a34 100644 --- a/sd/source/ui/func/fupage.cxx +++ b/sd/source/ui/func/fupage.cxx @@ -311,7 +311,7 @@ void FuPage::ExecuteAsyncDialog(weld::Window* pParent, const SfxRequest& rReq) if (pArgs && pArgs->GetItemState(SID_SELECT_BACKGROUND, true, &pItem) == SfxItemState::SET) { - OUString aFileName(static_cast(pItem)->GetValue()); + OUString aFileName(pItem->StaticWhichCast(SID_SELECT_BACKGROUND).GetValue()); OUString aFilterName; if (const SfxStringItem* pFilterItem = pArgs->GetItemIfSet(FN_PARAM_FILTER)) @@ -506,9 +506,9 @@ void FuPage::ApplyItemSet( const SfxItemSet* pArgs ) if( pArgs->GetItemState(SID_ATTR_PAGE, true, &pPoolItem) == SfxItemState::SET ) { - mrDoc.SetPageNumType(static_cast(pPoolItem)->GetNumType()); + mrDoc.SetPageNumType(pPoolItem->StaticWhichCast(SID_ATTR_PAGE).GetNumType()); - eOrientation = static_cast(pPoolItem)->IsLandscape() ? + eOrientation = pPoolItem->StaticWhichCast(SID_ATTR_PAGE).IsLandscape() ? Orientation::Landscape : Orientation::Portrait; if( mpPage->GetOrientation() != eOrientation ) @@ -520,12 +520,12 @@ void FuPage::ApplyItemSet( const SfxItemSet* pArgs ) if ( pArgs->GetItemState(SID_ATTR_RESIZE_ALL_PAGES, true, &pPoolItem) == SfxItemState::SET) { SdDrawDocument* pDrawDoc = mpDrawViewShell->GetDoc(); - pDrawDoc->SetResizeAllPages(static_cast(pPoolItem)->GetValue()); + pDrawDoc->SetResizeAllPages(pPoolItem->StaticWhichCast(SID_ATTR_RESIZE_ALL_PAGES).GetValue()); } if( pArgs->GetItemState(SID_ATTR_PAGE_SIZE, true, &pPoolItem) == SfxItemState::SET ) { - aNewSize = static_cast(pPoolItem)->GetSize(); + aNewSize = pPoolItem->StaticWhichCast(SID_ATTR_PAGE_SIZE).GetSize(); if( mpPage->GetSize() != aNewSize ) bSetPageSizeAndBorder = true; @@ -534,7 +534,11 @@ void FuPage::ApplyItemSet( const SfxItemSet* pArgs ) if( pArgs->GetItemState(mrDoc.GetPool().GetWhichIDFromSlotID(SID_ATTR_LRSPACE), true, &pPoolItem) == SfxItemState::SET ) { - nLeft = static_cast(pPoolItem)->ResolveLeft({}); + // FIXME for tdf#140226: using pPoolItem->StaticWhichCast(SID_ATTR_LRSPACE)->ResolveLeft/Right + // makes UITest_impress_tests fail + // more precisely tdf134734.TestClass.test_master_page_background + // for the record, pPoolItem->StaticWhichCast(EE_PARA_LRSPACE)->ResolveLeft/Right works + nLeft = static_cast(pPoolItem)->ResolveLeft(); nRight = static_cast(pPoolItem)->ResolveRight({}); if( mpPage->GetLeftBorder() != nLeft || mpPage->GetRightBorder() != nRight ) @@ -545,6 +549,9 @@ void FuPage::ApplyItemSet( const SfxItemSet* pArgs ) if( pArgs->GetItemState(mrDoc.GetPool().GetWhichIDFromSlotID(SID_ATTR_ULSPACE), true, &pPoolItem) == SfxItemState::SET ) { + // FIXME for tdf#140226: using pPoolItem->StaticWhichCast(SID_ATTR_ULSPACE)->GetUpper/Lower + // makes UITest_impress_tests fail + // more precisely tdf134734.TestClass.test_master_page_background nUpper = static_cast(pPoolItem)->GetUpper(); nLower = static_cast(pPoolItem)->GetLower(); @@ -554,13 +561,13 @@ void FuPage::ApplyItemSet( const SfxItemSet* pArgs ) if( pArgs->GetItemState(mrDoc.GetPool().GetWhichIDFromSlotID(SID_ATTR_PAGE_EXT1), true, &pPoolItem) == SfxItemState::SET ) { - bScaleAll = static_cast(pPoolItem)->GetValue(); + bScaleAll = pPoolItem->StaticWhichCast(SID_ATTR_PAGE_EXT1).GetValue(); } if (SfxItemState::SET == pArgs->GetItemState(SID_ATTR_CHAR_GRABBAG, true, &pPoolItem)) { - SfxGrabBagItem const*const pGrabBag(static_cast(pPoolItem)); - const auto& rGrabBagInner = pGrabBag->GetGrabBag(); + SfxGrabBagItem const pGrabBag(pPoolItem->StaticWhichCast(SID_ATTR_CHAR_GRABBAG)); + const auto& rGrabBagInner = pGrabBag.GetGrabBag(); const auto iter = rGrabBagInner.find(u"BackgroundFullSize"_ustr); assert(iter != rGrabBagInner.end()); if (iter->second >>= bFullSize) @@ -575,7 +582,7 @@ void FuPage::ApplyItemSet( const SfxItemSet* pArgs ) // Paper Bin if( pArgs->GetItemState(mrDoc.GetPool().GetWhichIDFromSlotID(SID_ATTR_PAGE_PAPERBIN), true, &pPoolItem) == SfxItemState::SET ) { - nPaperBin = static_cast(pPoolItem)->GetValue(); + nPaperBin = pPoolItem->StaticWhichCast(SID_ATTR_PAGE_PAPERBIN).GetValue(); if( mpPage->GetPaperBin() != nPaperBin ) bSetPageSizeAndBorder = true; diff --git a/sd/source/ui/func/fuprlout.cxx b/sd/source/ui/func/fuprlout.cxx index 85bae0504cc5..82e1124e3803 100644 --- a/sd/source/ui/func/fuprlout.cxx +++ b/sd/source/ui/func/fuprlout.cxx @@ -128,7 +128,7 @@ void FuPresentationLayout::DoExecute( SfxRequest& rReq ) bool bLoad = false; // appear the new master pages? OUString aFile; - SfxItemSetFixed aSet(mrDoc.GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet(mrDoc.GetPool() )); aSet.Put( SfxBoolItem( ATTR_PRESLAYOUT_LOAD, bLoad)); aSet.Put( SfxBoolItem( ATTR_PRESLAYOUT_MASTER_PAGE, bMasterPage ) ); diff --git a/sd/source/ui/func/fuprobjs.cxx b/sd/source/ui/func/fuprobjs.cxx index e196966792f7..1dc9f0a93c41 100644 --- a/sd/source/ui/func/fuprobjs.cxx +++ b/sd/source/ui/func/fuprobjs.cxx @@ -69,9 +69,9 @@ void FuPresentationObjects::DoExecute( SfxRequest& ) if( !pOutlineViewShell ) return; - /* does the selections end in a unique presentation layout? + /* do the selections end in a unique presentation layout? if not, it is not allowed to edit the templates */ - SfxItemSetFixed aSet(mrDoc.GetItemPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet(mrDoc.GetItemPool() )); pOutlineViewShell->GetStatusBarState( aSet ); OUString aLayoutName = aSet.Get(SID_STATUS_LAYOUT).GetValue(); DBG_ASSERT(!aLayoutName.isEmpty(), "Layout not defined"); diff --git a/sd/source/ui/func/fuscale.cxx b/sd/source/ui/func/fuscale.cxx index 09b43b818572..90f0b93f5d76 100644 --- a/sd/source/ui/func/fuscale.cxx +++ b/sd/source/ui/func/fuscale.cxx @@ -66,7 +66,7 @@ void FuScale::DoExecute( SfxRequest& rReq ) if( !pArgs ) { - SfxItemSetFixed aNewAttr( mrDoc.GetPool() ); + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet( mrDoc.GetPool() )); std::unique_ptr pZoomItem; SvxZoomEnableFlags nZoomValues = SvxZoomEnableFlags::ALL; diff --git a/sd/source/ui/func/fusldlg.cxx b/sd/source/ui/func/fusldlg.cxx index 956bbbc829c3..cbda3d670b66 100644 --- a/sd/source/ui/func/fusldlg.cxx +++ b/sd/source/ui/func/fusldlg.cxx @@ -64,7 +64,7 @@ void FuSlideShowDlg::DoExecute( SfxRequest& ) { PresentationSettings& rPresentationSettings = mrDoc.getPresentationSettings(); - SfxItemSetFixed aDlgSet( mrDoc.GetPool() ); + SfxItemSet aDlgSet(SfxItemSet::makeFixedSfxItemSet( mrDoc.GetPool() )); std::vector aPageNameList(mrDoc.GetSdPageCount( PageKind::Standard )); const OUString& rPresPage = rPresentationSettings.maPresPage; OUString aFirstPage; @@ -236,7 +236,7 @@ void FuSlideShowDlg::DoExecute( SfxRequest& ) pOptions->SetDisplay( aDlgSet.Get(ATTR_PRESENT_DISPLAY).GetValue() ); - // is something has changed, we set the modified flag + // if something has changed, we set the modified flag if ( bValuesChanged ) mrDoc.SetChanged(); } diff --git a/sd/source/ui/func/fusnapln.cxx b/sd/source/ui/func/fusnapln.cxx index 33a26902b6cb..5a1d5dbbc31f 100644 --- a/sd/source/ui/func/fusnapln.cxx +++ b/sd/source/ui/func/fusnapln.cxx @@ -69,7 +69,7 @@ void FuSnapLine::DoExecute( SfxRequest& rReq ) if (!pArgs) { - SfxItemSetFixed aNewAttr(mrViewShell.GetPool()); + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet(mrViewShell.GetPool())); bool bLineExist (false); Point aLinePos; diff --git a/sd/source/ui/func/fusumry.cxx b/sd/source/ui/func/fusumry.cxx index b4b2b93577fa..17197f7654a1 100644 --- a/sd/source/ui/func/fusumry.cxx +++ b/sd/source/ui/func/fusumry.cxx @@ -193,7 +193,7 @@ void FuSummaryPage::DoExecute( SfxRequest& ) return; // remove hard break- and character attributes - SfxItemSetFixed aEmptyEEAttr(mrDoc.GetPool()); + SfxItemSet aEmptyEEAttr(SfxItemSet::makeFixedSfxItemSet(mrDoc.GetPool())); sal_Int32 nParaCount = pOutl->GetParagraphCount(); for (sal_Int32 nPara = 0; nPara < nParaCount; nPara++) diff --git a/sd/source/ui/func/futext.cxx b/sd/source/ui/func/futext.cxx index 2071425629b0..6290393a933c 100644 --- a/sd/source/ui/func/futext.cxx +++ b/sd/source/ui/func/futext.cxx @@ -241,7 +241,7 @@ void FuText::DoExecute( SfxRequest& ) && pArgs->Get(SID_TEXTEDIT).GetValue() == 2) { - // Selection by doubleclick -> don't allow QuickDrag + // Selection by double-click -> don't allow QuickDrag bQuickDrag = false; } @@ -524,9 +524,6 @@ void FuText::ImpSetAttributesForNewTextObject(SdrTextObj* pTxtObj) aSet.Put(makeSdrTextAutoGrowHeightItem(true)); pTxtObj->SetMergedItemSet(aSet); pTxtObj->AdjustTextFrameWidthAndHeight(); - const SfxViewShell* pCurrentViewShell = SfxViewShell::Current(); - if (pCurrentViewShell && (pCurrentViewShell->isLOKMobilePhone() || pCurrentViewShell->isLOKTablet())) - pTxtObj->SetText(SdResId(STR_PRESOBJ_TEXT_EDIT_MOBILE)); } else if( nSlotId == SID_ATTR_CHAR_VERTICAL ) { @@ -839,7 +836,7 @@ bool FuText::MouseButtonUp(const MouseEvent& rMEvt) else { // This is for Format/Page settings. Since this also leads - // to the object defaults to be changed, i think this code can be + // to the object defaults being changed, I think this code can be // removed. CL. wanted to take a look before adding this. // Look in the object defaults if left-to-right is wanted. If diff --git a/sd/source/ui/func/futhes.cxx b/sd/source/ui/func/futhes.cxx index 0b6519885946..effaf20e9d0b 100644 --- a/sd/source/ui/func/futhes.cxx +++ b/sd/source/ui/func/futhes.cxx @@ -30,7 +30,8 @@ #include #include #include -#include +#include + #include #include #include diff --git a/sd/source/ui/func/undoback.cxx b/sd/source/ui/func/undoback.cxx index 054298c0f866..66362cebf42b 100644 --- a/sd/source/ui/func/undoback.cxx +++ b/sd/source/ui/func/undoback.cxx @@ -58,7 +58,7 @@ void SdBackgroundObjUndoAction::ImplRestoreBackgroundObj() mpItemSet = std::move(pNew); saveFillBitmap(*mpItemSet); - // tell the page that it's visualization has changed + // tell the page that its visualization has changed mrPage.ActionChanged(); } diff --git a/sd/source/ui/func/unoaprms.cxx b/sd/source/ui/func/unoaprms.cxx index 3bf7d98a6113..0d82b871440e 100644 --- a/sd/source/ui/func/unoaprms.cxx +++ b/sd/source/ui/func/unoaprms.cxx @@ -39,7 +39,7 @@ void SdAnimationPrmsUndoAction::Undo() pInfo->maDimColor = aOldDimColor; pInfo->mbDimHide = bOldDimHide; pInfo->mbSoundOn = bOldSoundOn; - pInfo->maSoundFile = aOldSoundFile; + pInfo->maSoundLink = aOldSoundLink; pInfo->mbPlayFull = bOldPlayFull; pInfo->meClickAction = eOldClickAction; pInfo->SetBookmark( aOldBookmark ); @@ -73,7 +73,7 @@ void SdAnimationPrmsUndoAction::Redo() pInfo->maDimColor = aNewDimColor; pInfo->mbDimHide = bNewDimHide; pInfo->mbSoundOn = bNewSoundOn; - pInfo->maSoundFile = aNewSoundFile; + pInfo->maSoundLink = aNewSoundLink; pInfo->mbPlayFull = bNewPlayFull; pInfo->meClickAction = eNewClickAction; pInfo->SetBookmark( aNewBookmark ); diff --git a/sd/source/ui/inc/AccessibleDocumentViewBase.hxx b/sd/source/ui/inc/AccessibleDocumentViewBase.hxx index 77d7c620c729..8353b64882fa 100644 --- a/sd/source/ui/inc/AccessibleDocumentViewBase.hxx +++ b/sd/source/ui/inc/AccessibleDocumentViewBase.hxx @@ -92,15 +92,13 @@ public: The view shell associated with the given window. @param rxController The controller from which to get the model. - @param rxParent + @param rpParent The accessible parent of the new object. Note that this parent does not necessarily correspond with the parent of the given window. */ - AccessibleDocumentViewBase ( - ::sd::Window* pSdWindow, - ::sd::ViewShell* pViewShell, - css::uno::Reference xController, - const css::uno::Reference& rxParent); + AccessibleDocumentViewBase(::sd::Window* pSdWindow, ::sd::ViewShell* pViewShell, + css::uno::Reference xController, + const rtl::Reference& rpParent); virtual ~AccessibleDocumentViewBase() override; @@ -126,9 +124,6 @@ public: //===== XAccessibleContext ============================================== - virtual css::uno::Reference SAL_CALL - getAccessibleParent() override; - /** This implementation returns either 1 or 0 depending on whether there is an active accessible OLE object or not. */ diff --git a/sd/source/ui/inc/AccessibleDrawDocumentView.hxx b/sd/source/ui/inc/AccessibleDrawDocumentView.hxx index f5cc5ec5967e..ecf24fc8193d 100644 --- a/sd/source/ui/inc/AccessibleDrawDocumentView.hxx +++ b/sd/source/ui/inc/AccessibleDrawDocumentView.hxx @@ -22,6 +22,7 @@ #include "AccessibleDocumentViewBase.hxx" #include +#include namespace accessibility { class AccessiblePageShape; } namespace accessibility { class ChildrenManager; } @@ -38,14 +39,13 @@ namespace accessibility { */ class AccessibleDrawDocumentView final : public cppu::ImplInheritanceHelper + css::accessibility::XAccessibleGroupPosition, + css::lang::XServiceInfo> { public: - - AccessibleDrawDocumentView (::sd::Window* pSdWindow, - ::sd::ViewShell* pViewShell, - const css::uno::Reference& rxController, - const css::uno::Reference& rxParent); + AccessibleDrawDocumentView(::sd::Window* pSdWindow, ::sd::ViewShell* pViewShell, + const css::uno::Reference& rxController, + const rtl::Reference& rpParent); virtual ~AccessibleDrawDocumentView() override; @@ -93,6 +93,8 @@ private: virtual css::uno::Sequence< OUString> SAL_CALL getSupportedServiceNames() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override final; + virtual bool implIsSelected( sal_Int64 nAccessibleChildIndex ) override; diff --git a/sd/source/ui/inc/AccessibleOutlineView.hxx b/sd/source/ui/inc/AccessibleOutlineView.hxx index ddff1b465289..0174a39db7de 100644 --- a/sd/source/ui/inc/AccessibleOutlineView.hxx +++ b/sd/source/ui/inc/AccessibleOutlineView.hxx @@ -37,11 +37,9 @@ class AccessibleOutlineView final : public AccessibleDocumentViewBase { public: - AccessibleOutlineView ( - ::sd::Window* pSdWindow, - ::sd::OutlineViewShell* pViewShell, - const css::uno::Reference& rxController, - const css::uno::Reference& rxParent); + AccessibleOutlineView(::sd::Window* pSdWindow, ::sd::OutlineViewShell* pViewShell, + const css::uno::Reference& rxController, + const rtl::Reference& rpParent); virtual ~AccessibleOutlineView() override; @@ -72,13 +70,6 @@ public: removeAccessibleEventListener ( const css::uno::Reference& xListener) override; - //===== XServiceInfo ==================================================== - - /** Returns an identifier for the implementation of this object. - */ - virtual OUString SAL_CALL - getImplementationName() override; - //===== lang::XEventListener ============================================ using AccessibleDocumentViewBase::disposing; diff --git a/sd/source/ui/inc/AccessiblePageShape.hxx b/sd/source/ui/inc/AccessiblePageShape.hxx index ffa99bd9baa3..90b0d3ac2636 100644 --- a/sd/source/ui/inc/AccessiblePageShape.hxx +++ b/sd/source/ui/inc/AccessiblePageShape.hxx @@ -33,9 +33,8 @@ class AccessiblePageShape final : public AccessibleShape { public: - /** Create a new accessible object that makes the given shape accessible. - @param rxParent + @param rpParent The accessible parent object. It will be used, for example when the getIndexInParent method is called. @param rShapeTreeInfo @@ -47,10 +46,9 @@ public: broadcasters. That would delete the new object if a broadcaster would not keep a strong reference to the new object. */ - AccessiblePageShape ( - css::uno::Reference xPage, - const css::uno::Reference& rxParent, - const AccessibleShapeTreeInfo& rShapeTreeInfo); + AccessiblePageShape(css::uno::Reference xPage, + const rtl::Reference& rpParent, + const AccessibleShapeTreeInfo& rShapeTreeInfo); virtual ~AccessiblePageShape() override; @@ -86,14 +84,6 @@ public: virtual void SAL_CALL dispose() override; - //===== XServiceInfo ==================================================== - - virtual OUString SAL_CALL - getImplementationName() override; - - virtual css::uno::Sequence< OUString> SAL_CALL - getSupportedServiceNames() override; - using AccessibleShape::disposing; protected: diff --git a/sd/source/ui/inc/AccessiblePresentationGraphicShape.hxx b/sd/source/ui/inc/AccessiblePresentationGraphicShape.hxx index 9e7e44d3b11d..486915fc4248 100644 --- a/sd/source/ui/inc/AccessiblePresentationGraphicShape.hxx +++ b/sd/source/ui/inc/AccessiblePresentationGraphicShape.hxx @@ -37,13 +37,6 @@ public: const AccessibleShapeTreeInfo& rShapeTreeInfo); virtual ~AccessiblePresentationGraphicShape() override; - //===== XServiceInfo ==================================================== - - /** Returns an identifier for the implementation of this object. - */ - virtual OUString SAL_CALL - getImplementationName() override; - /// Create a name string that contains the accessible name. virtual OUString CreateAccessibleBaseName () override; diff --git a/sd/source/ui/inc/AccessiblePresentationOLEShape.hxx b/sd/source/ui/inc/AccessiblePresentationOLEShape.hxx index 5d9c06e2c114..728a80776b6e 100644 --- a/sd/source/ui/inc/AccessiblePresentationOLEShape.hxx +++ b/sd/source/ui/inc/AccessiblePresentationOLEShape.hxx @@ -34,13 +34,6 @@ public: const AccessibleShapeTreeInfo& rShapeTreeInfo); virtual ~AccessiblePresentationOLEShape() override; - //===== XServiceInfo ==================================================== - - /** Returns an identifier for the implementation of this object. - */ - virtual OUString SAL_CALL - getImplementationName() override; - /// Create a name string that contains the accessible name. virtual OUString CreateAccessibleBaseName () override; diff --git a/sd/source/ui/inc/AccessiblePresentationShape.hxx b/sd/source/ui/inc/AccessiblePresentationShape.hxx index 5ae93e44d3d1..f1910d907c82 100644 --- a/sd/source/ui/inc/AccessiblePresentationShape.hxx +++ b/sd/source/ui/inc/AccessiblePresentationShape.hxx @@ -34,13 +34,6 @@ public: const AccessibleShapeTreeInfo& rShapeTreeInfo); virtual ~AccessiblePresentationShape() override; - //===== XServiceInfo ==================================================== - - /** Returns an identifier for the implementation of this object. - */ - virtual OUString SAL_CALL - getImplementationName() override; - /// Create a name string that contains the accessible name. virtual OUString CreateAccessibleBaseName () override; diff --git a/sd/source/ui/inc/AccessibleSlideSorterView.hxx b/sd/source/ui/inc/AccessibleSlideSorterView.hxx index 343452a081a1..7de5a0a98bef 100644 --- a/sd/source/ui/inc/AccessibleSlideSorterView.hxx +++ b/sd/source/ui/inc/AccessibleSlideSorterView.hxx @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -41,8 +40,7 @@ class AccessibleSlideSorterObject; */ class AccessibleSlideSorterView final : public cppu::ImplInheritanceHelper + css::accessibility::XAccessibleSelection> { public: AccessibleSlideSorterView( @@ -143,17 +141,6 @@ public: virtual void SAL_CALL deselectAccessibleChild( sal_Int64 nSelectedChildIndex ) override; - //===== XServiceInfo ==================================================== - - virtual OUString SAL_CALL - getImplementationName() override; - - virtual sal_Bool SAL_CALL - supportsService (const OUString& sServiceName) override; - - virtual css::uno::Sequence< OUString> SAL_CALL - getSupportedServiceNames() override; - void SwitchViewActivated(); private: class Implementation; diff --git a/sd/source/ui/inc/AnimationChildWindow.hxx b/sd/source/ui/inc/AnimationChildWindow.hxx index 278cc791d3fa..5390c5979d34 100644 --- a/sd/source/ui/inc/AnimationChildWindow.hxx +++ b/sd/source/ui/inc/AnimationChildWindow.hxx @@ -31,11 +31,7 @@ class AnimationChildWindow final : public SfxChildWindow { public: - AnimationChildWindow( - vcl::Window*, - sal_uInt16, - SfxBindings*, - SfxChildWinInfo*); + AnimationChildWindow(vcl::Window*, sal_uInt16, SfxBindings&, SfxChildWinInfo&); SFX_DECL_CHILDWINDOW_WITHID(AnimationChildWindow); }; diff --git a/sd/source/ui/inc/BreakDlg.hxx b/sd/source/ui/inc/BreakDlg.hxx index c0b62b62df9c..a9a457b6652d 100644 --- a/sd/source/ui/inc/BreakDlg.hxx +++ b/sd/source/ui/inc/BreakDlg.hxx @@ -23,7 +23,8 @@ #include #include #include -#include +#include +#include namespace sd { diff --git a/sd/source/ui/inc/BulletAndPositionDlg.hxx b/sd/source/ui/inc/BulletAndPositionDlg.hxx index 227e7efd54d2..34a3271875a5 100644 --- a/sd/source/ui/inc/BulletAndPositionDlg.hxx +++ b/sd/source/ui/inc/BulletAndPositionDlg.hxx @@ -24,14 +24,20 @@ #include #include +#include +#include #include #include #include +#include +#include +#include #include #include +#include #include #include -#include +#include #include "View.hxx" #include #include @@ -131,7 +137,7 @@ class SvxBulletAndPositionDlg final : public weld::GenericDialogController DECL_LINK(BulletHdl_Impl, weld::Button&, void); DECL_LINK(SizeHdl_Impl, weld::MetricSpinButton&, void); DECL_LINK(RatioHdl_Impl, weld::Toggleable&, void); - DECL_LINK(EditModifyHdl_Impl, weld::Entry&, void); + DECL_LINK(EditModifyHdl_Impl, weld::TextWidget&, void); DECL_LINK(SpinModifyHdl_Impl, weld::SpinButton&, void); DECL_LINK(BulColorHdl_Impl, ColorListBox&, void); DECL_LINK(BulRelSizeHdl_Impl, weld::MetricSpinButton&, void); @@ -143,7 +149,7 @@ class SvxBulletAndPositionDlg final : public weld::GenericDialogController DECL_LINK(SelectRightAlignmentHdl_Impl, weld::Toggleable&, void); DECL_LINK(ApplyToMasterHdl_Impl, weld::Toggleable&, void); DECL_LINK(ResetHdl_Impl, weld::Button&, void); - void EditModifyHdl_Impl(const weld::Entry*); + void EditModifyHdl_Impl(const weld::TextWidget*); void InitPosAndSpaceMode(); void SetAlignmentHdl_Impl(SvxAdjust); diff --git a/sd/source/ui/inc/CustomAnimationList.hxx b/sd/source/ui/inc/CustomAnimationList.hxx index 8279259458b7..3441f16fe882 100644 --- a/sd/source/ui/inc/CustomAnimationList.hxx +++ b/sd/source/ui/inc/CustomAnimationList.hxx @@ -24,8 +24,9 @@ #include #include +#include #include -#include + #include namespace com::sun::star::drawing { class XShape; } diff --git a/sd/source/ui/inc/CustomAnimationPane.hxx b/sd/source/ui/inc/CustomAnimationPane.hxx index 12c3d2195835..0fff1f3bbdba 100644 --- a/sd/source/ui/inc/CustomAnimationPane.hxx +++ b/sd/source/ui/inc/CustomAnimationPane.hxx @@ -22,7 +22,11 @@ #include #include #include +#include +#include #include +#include +#include #include #include "CustomAnimationList.hxx" #include diff --git a/sd/source/ui/inc/DrawDocShell.hxx b/sd/source/ui/inc/DrawDocShell.hxx index 1cef23c66025..6b24c0d5d55e 100644 --- a/sd/source/ui/inc/DrawDocShell.hxx +++ b/sd/source/ui/inc/DrawDocShell.hxx @@ -91,6 +91,8 @@ public: virtual bool Load( SfxMedium &rMedium ) override; virtual bool LoadFrom( SfxMedium& rMedium ) override; + virtual void UpdateLinks() override; + virtual void PerformLinkUpdate() override; virtual bool SaveAs( SfxMedium &rMedium ) override; virtual ::tools::Rectangle GetVisArea(sal_uInt16 nAspect) const override; diff --git a/sd/source/ui/inc/ImpressViewShellBase.hxx b/sd/source/ui/inc/ImpressViewShellBase.hxx index 402013fa7ff9..56ab75573ab4 100644 --- a/sd/source/ui/inc/ImpressViewShellBase.hxx +++ b/sd/source/ui/inc/ImpressViewShellBase.hxx @@ -28,8 +28,12 @@ namespace sd */ class ImpressViewShellBase : public ViewShellBase { +private: + static std::map> s_pFactories; + public: - SFX_DECL_VIEWFACTORY(ImpressViewShellBase); + static SfxViewShell* CreateInstance(SfxViewFrame& rFrame, SfxViewShell* pOldView); + static void RegisterFactory(SfxInterfaceId nPrio); /** This constructor is used by the view factory of the SFX macros. diff --git a/sd/source/ui/inc/NavigatorChildWindow.hxx b/sd/source/ui/inc/NavigatorChildWindow.hxx index 4199cab677ba..a4e2bfdf87b6 100644 --- a/sd/source/ui/inc/NavigatorChildWindow.hxx +++ b/sd/source/ui/inc/NavigatorChildWindow.hxx @@ -30,8 +30,8 @@ namespace sd { class SdNavigatorWrapper final : public SfxNavigatorWrapper { public: - SdNavigatorWrapper(vcl::Window *pParent, sal_uInt16 nId, - SfxBindings* pBindings, SfxChildWinInfo* pInfo); + SdNavigatorWrapper(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); SFX_DECL_CHILDWINDOW(SdNavigatorWrapper); }; diff --git a/sd/source/ui/inc/OutlineBulletDlg.hxx b/sd/source/ui/inc/OutlineBulletDlg.hxx index 70a9ea5749f7..b3ce031ab7ed 100644 --- a/sd/source/ui/inc/OutlineBulletDlg.hxx +++ b/sd/source/ui/inc/OutlineBulletDlg.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include namespace sd { diff --git a/sd/source/ui/inc/PaneChildWindows.hxx b/sd/source/ui/inc/PaneChildWindows.hxx index 68989f3c01ce..7e52cb373a9d 100644 --- a/sd/source/ui/inc/PaneChildWindows.hxx +++ b/sd/source/ui/inc/PaneChildWindows.hxx @@ -29,13 +29,9 @@ class PaneChildWindow : public SfxChildWindow { public: - PaneChildWindow ( - vcl::Window* pParentWindow, - sal_uInt16 nId, - SfxBindings* pBindings, - SfxChildWinInfo* pInfo, - TranslateId pTitleBarResId, - SfxChildAlignment eAlignment); + PaneChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo, TranslateId pTitleBarResId, + SfxChildAlignment eAlignment); virtual ~PaneChildWindow() override; }; @@ -44,8 +40,8 @@ class LeftPaneImpressChildWindow final : public PaneChildWindow { public: - LeftPaneImpressChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings* pBindings, - SfxChildWinInfo* pInfo); + LeftPaneImpressChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); SFX_DECL_CHILDWINDOW_WITHID(LeftPaneImpressChildWindow); }; @@ -54,8 +50,8 @@ public: class BottomPaneImpressChildWindow final : public PaneChildWindow { public: - BottomPaneImpressChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings* pBindings, - SfxChildWinInfo* pInfo); + BottomPaneImpressChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); SFX_DECL_CHILDWINDOW_WITHID(BottomPaneImpressChildWindow); }; @@ -65,8 +61,8 @@ class LeftPaneDrawChildWindow final : public PaneChildWindow { public: - LeftPaneDrawChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings* pBindings, - SfxChildWinInfo* pInfo); + LeftPaneDrawChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); SFX_DECL_CHILDWINDOW_WITHID(LeftPaneDrawChildWindow); }; diff --git a/sd/source/ui/inc/SelectLayerDlg.hxx b/sd/source/ui/inc/SelectLayerDlg.hxx index c1473743f586..c888c5fca711 100644 --- a/sd/source/ui/inc/SelectLayerDlg.hxx +++ b/sd/source/ui/inc/SelectLayerDlg.hxx @@ -18,9 +18,10 @@ */ #pragma once +#include #include #include -#include +#include class SdSelectLayerDlg final : public weld::GenericDialogController { diff --git a/sd/source/ui/inc/SlideTransitionPane.hxx b/sd/source/ui/inc/SlideTransitionPane.hxx index 997e1fffc329..43c0f9b5d789 100644 --- a/sd/source/ui/inc/SlideTransitionPane.hxx +++ b/sd/source/ui/inc/SlideTransitionPane.hxx @@ -24,16 +24,19 @@ #include #include #include +#include +#include #include +#include #include +#include #include -#include +#include #include #include class SdDrawDocument; -class SdXImpressDocument; namespace com::sun::star::drawing { class XDrawView; } namespace sdtools { class EventMultiplexerEvent; } @@ -89,7 +92,7 @@ private: ::sd::slidesorter::SharedPageSelection getSelectedPages() const; - void Initialize(SdDrawDocument* pDoc); + void Initialize(); DECL_LINK( ApplyToAllButtonClicked, weld::Button&, void ); DECL_LINK( PlayButtonClicked, weld::Button&, void ); @@ -130,13 +133,11 @@ private: std::unique_ptr mxCB_AUTO_PREVIEW; css::uno::Reference< css::drawing::XDrawView > mxView; - rtl::Reference< SdXImpressDocument > mxModel; std::unordered_map> maTranstionMap; bool mbHasSelection; bool mbUpdatingControls; - bool mbIsMainViewChangePending; std::vector maSoundList; mutable OUString maCurrentSoundFile; diff --git a/sd/source/ui/inc/SpellDialogChildWindow.hxx b/sd/source/ui/inc/SpellDialogChildWindow.hxx index 961b1ddf0dbc..fc23f253ee31 100644 --- a/sd/source/ui/inc/SpellDialogChildWindow.hxx +++ b/sd/source/ui/inc/SpellDialogChildWindow.hxx @@ -33,8 +33,8 @@ namespace sd class SpellDialogChildWindow final : public svx::SpellDialogChildWindow, public SfxListener { public: - SpellDialogChildWindow(vcl::Window* pParent, sal_uInt16 nId, SfxBindings* pBindings, - SfxChildWinInfo* pInfo); + SpellDialogChildWindow(vcl::Window* pParent, sal_uInt16 nId, SfxBindings& rBindings, + SfxChildWinInfo& rInfo); virtual ~SpellDialogChildWindow() override; /** This method makes the one from the base class public so that diff --git a/sd/source/ui/inc/TableDesignPane.hxx b/sd/source/ui/inc/TableDesignPane.hxx index bd17a168e1f2..27e7971b5c62 100644 --- a/sd/source/ui/inc/TableDesignPane.hxx +++ b/sd/source/ui/inc/TableDesignPane.hxx @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include diff --git a/sd/source/ui/inc/View.hxx b/sd/source/ui/inc/View.hxx index ccdadc43094e..9eba88351db1 100644 --- a/sd/source/ui/inc/View.hxx +++ b/sd/source/ui/inc/View.hxx @@ -29,6 +29,8 @@ #include #include +#include + #include "smarttag.hxx" #include "fusearch.hxx" @@ -160,14 +162,14 @@ public: const Point& rPos, sal_Int8& rDnDAction, bool bDrag, SotClipboardFormatId nFormat = SotClipboardFormatId::NONE, sal_uInt16 nPage = SDRPAGE_NOTFOUND, SdrLayerID nLayer = SDRLAYER_NOTFOUND ); - /** gets the metafile from the given transferable helper and insert it as a graphic shape. + /** gets the metafile from the given transferable helper and inserts it as a graphic shape. @param bOptimize if set to true, the metafile is analyzed and if only one bitmap action is - present, then is inserted as a single graphic. + present, then it is inserted as a single graphic. */ bool InsertMetaFile( const TransferableDataHelper& rDataHelper, const Point& rInsertPos, ImageMap const * pImageMap, bool bOptimize ); - SdrGrafObj* InsertGraphic( const Graphic& rGraphic, + SD_DLLPUBLIC SdrGrafObj* InsertGraphic( const Graphic& rGraphic, sal_Int8& rAction, const Point& rPos, SdrObject* pSelectedObj, ImageMap const * pImageMap ); void InsertMediaURL( const OUString& rMediaURL, sal_Int8& rAction, @@ -245,6 +247,10 @@ public: void SetResizeProtected( bool bSet ) { m_bResizeProtect = bSet; } SdrObject* GetEmptyPresentationObject( PresObjKind eKind ); + + /** The placeholder an image should fill: an empty one, or a picture placeholder that holds text + and is represented by an outliner object while it does. */ + SdrObject* GetPresentationObjectForGraphic(); SdPage* GetPage(); SdrObject* GetSelectedSingleObject(SdPage const * pPage); void SetAuthor(const OUString& rAuthor) { m_sAuthor = rAuthor; } diff --git a/sd/source/ui/inc/ViewShellBase.hxx b/sd/source/ui/inc/ViewShellBase.hxx index 2a5d795d913f..a1870e857d59 100644 --- a/sd/source/ui/inc/ViewShellBase.hxx +++ b/sd/source/ui/inc/ViewShellBase.hxx @@ -110,7 +110,7 @@ public: /* override these from SfxViewShell */ virtual OUString GetSelectionText(bool = false, bool bOnlyASample = false) override; - virtual bool HasSelection(bool = true ) const override; + virtual bool HasSelection(bool bMustHaveText) const override; SvBorder GetBorder (bool bOuterResize); virtual void InnerResizePixel (const Point& rOrigin, const Size& rSize, bool inplaceEditModeChange) override; diff --git a/sd/source/ui/inc/ViewTabBar.hxx b/sd/source/ui/inc/ViewTabBar.hxx index fca23ed6dce1..2c94c2123c92 100644 --- a/sd/source/ui/inc/ViewTabBar.hxx +++ b/sd/source/ui/inc/ViewTabBar.hxx @@ -25,7 +25,6 @@ #include #include #include -#include #include diff --git a/sd/source/ui/inc/animobjs.hxx b/sd/source/ui/inc/animobjs.hxx index 023a9f986808..8794dd91ec1b 100644 --- a/sd/source/ui/inc/animobjs.hxx +++ b/sd/source/ui/inc/animobjs.hxx @@ -25,11 +25,14 @@ #include #include #include +#include #include #include +#include +#include #include +#include #include -#include #include class SdDrawDocument; @@ -76,7 +79,7 @@ class AnimationWindow final : public SfxDockingWindow friend class AnimationControllerItem; public: - AnimationWindow(SfxBindings* pBindings, SfxChildWindow *pCW, vcl::Window* pParent); + AnimationWindow(SfxBindings& rBindings, SfxChildWindow* pCW, vcl::Window* pParent); virtual ~AnimationWindow() override; virtual void dispose() override; diff --git a/sd/source/ui/inc/copydlg.hxx b/sd/source/ui/inc/copydlg.hxx index 04f518223fbc..f88393e700c1 100644 --- a/sd/source/ui/inc/copydlg.hxx +++ b/sd/source/ui/inc/copydlg.hxx @@ -21,7 +21,10 @@ #include #include +#include +#include #include +#include #include class ColorListBox; @@ -31,7 +34,7 @@ namespace sd class View; /** - * dialog to adjust screen + * dialog to create a series of modified copies of selected shapes */ class CopyDlg final : public SfxDialogController { @@ -58,6 +61,9 @@ private: std::unique_ptr m_xBtnSetDefault; std::unique_ptr m_xLbStartColor; std::unique_ptr m_xLbEndColor; + std::unique_ptr m_xRbRGB; + std::unique_ptr m_xRbHSLInc; + std::unique_ptr m_xRbHSLDec; DECL_LINK(SelectColorHdl, ColorListBox&, void); DECL_LINK(SetViewData, weld::Button&, void); diff --git a/sd/source/ui/inc/custsdlg.hxx b/sd/source/ui/inc/custsdlg.hxx index 4f6132e75986..6113243c0eeb 100644 --- a/sd/source/ui/inc/custsdlg.hxx +++ b/sd/source/ui/inc/custsdlg.hxx @@ -19,10 +19,10 @@ #pragma once +#include #include #include #include -#include #include class SdDrawDocument; @@ -75,11 +75,11 @@ private: void CheckCustomShow(); DECL_LINK( ClickButtonHdl, weld::Button&, void ); - DECL_LINK( ClickButtonEditHdl, weld::Entry&, void ); + DECL_LINK(ClickButtonEditHdl, weld::TextWidget&, void); DECL_LINK(ClickButtonHdl3, weld::ItemView&, void); DECL_LINK(ClickButtonHdl4, weld::ItemView&, void); DECL_LINK( OKHdl, weld::Button&, void ); - void ClickButtonHdl2(void const *); + void ClickButtonHdl2(const weld::Widget* pWidget); public: diff --git a/sd/source/ui/inc/dlg_char.hxx b/sd/source/ui/inc/dlg_char.hxx index f3895b2cc3e6..3292b542971f 100644 --- a/sd/source/ui/inc/dlg_char.hxx +++ b/sd/source/ui/inc/dlg_char.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include class SfxItemSet; class SfxObjectShell; diff --git a/sd/source/ui/inc/dlgfield.hxx b/sd/source/ui/inc/dlgfield.hxx index 1a23e5c905a9..721a0df51ef2 100644 --- a/sd/source/ui/inc/dlgfield.hxx +++ b/sd/source/ui/inc/dlgfield.hxx @@ -21,7 +21,8 @@ #include #include -#include +#include +#include #include #include diff --git a/sd/source/ui/inc/dlgpage.hxx b/sd/source/ui/inc/dlgpage.hxx index 5dbd037af08d..8c7b115abf38 100644 --- a/sd/source/ui/inc/dlgpage.hxx +++ b/sd/source/ui/inc/dlgpage.hxx @@ -21,6 +21,7 @@ #include #include +#include class SfxObjectShell; diff --git a/sd/source/ui/inc/dlgsnap.hxx b/sd/source/ui/inc/dlgsnap.hxx index 040371def3e3..c6eac561286a 100644 --- a/sd/source/ui/inc/dlgsnap.hxx +++ b/sd/source/ui/inc/dlgsnap.hxx @@ -20,9 +20,12 @@ #pragma once #include +#include #include +#include #include -#include +#include +#include /************************************************************************/ diff --git a/sd/source/ui/inc/filedlg.hxx b/sd/source/ui/inc/filedlg.hxx index b10303628b01..6bc024eec589 100644 --- a/sd/source/ui/inc/filedlg.hxx +++ b/sd/source/ui/inc/filedlg.hxx @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include diff --git a/sd/source/ui/inc/framework/Configuration.hxx b/sd/source/ui/inc/framework/Configuration.hxx index c4b289150c04..e8571dbe9396 100644 --- a/sd/source/ui/inc/framework/Configuration.hxx +++ b/sd/source/ui/inc/framework/Configuration.hxx @@ -19,9 +19,10 @@ #pragma once +#include + #include #include -#include #include #include #include @@ -114,7 +115,7 @@ public: @param xAnchorId This anchor typically is either a pane or an empty ResourceId object. An - empty reference is treated like an ResourceId object. + empty reference is treated like a ResourceId object. @param sTargetURLPrefix When a non-empty string is given then resource ids are returned only when their resource URL matches this prefix, i.e. when it @@ -139,7 +140,7 @@ public: std::vector< rtl::Reference > getResources ( const rtl::Reference& rxAnchorId, std::u16string_view rsResourceURLPrefix, - css::drawing::framework::AnchorBindingMode eMode); + sd::framework::AnchorBindingMode eMode); /**

      Returns whether the specified resource is part of the configuration.

      @@ -173,8 +174,8 @@ public: private: class ResourceContainer; - /** The resource container holds the URLs of unique resource and of - resource linked to unique resources. + /** The resource container holds the URLs of unique resources and of + resources linked to unique resources. */ std::unique_ptr mpResourceContainer; diff --git a/sd/source/ui/inc/fuoltext.hxx b/sd/source/ui/inc/fuoltext.hxx index 697eb2c4cb34..5d9772bbc1b2 100644 --- a/sd/source/ui/inc/fuoltext.hxx +++ b/sd/source/ui/inc/fuoltext.hxx @@ -70,6 +70,7 @@ public: static rtl::Reference Create( ViewShell& rViewSh, ::sd::Window* pWin, ::sd::SimpleOutlinerView* pView, SdDrawDocument& rDoc, SfxRequest& rReq ); virtual bool KeyInput(const KeyEvent& rKEvt) override; + virtual bool MouseButtonUp(const MouseEvent& rMEvt) override; /** Call this method when the text in the outliner (may) have changed. It will invalidate some slots of the view frame and update the preview in the slide sorter. diff --git a/sd/source/ui/inc/fupage.hxx b/sd/source/ui/inc/fupage.hxx index c0b2d1fd3df9..b4039bcce007 100644 --- a/sd/source/ui/inc/fupage.hxx +++ b/sd/source/ui/inc/fupage.hxx @@ -21,9 +21,10 @@ #include #include "fupoor.hxx" -#include #include +#include + class SfxItemSet; class SdBackgroundObjUndoAction; class SdPage; diff --git a/sd/source/ui/inc/headerfooterdlg.hxx b/sd/source/ui/inc/headerfooterdlg.hxx index a071151887df..ea0c758a3110 100644 --- a/sd/source/ui/inc/headerfooterdlg.hxx +++ b/sd/source/ui/inc/headerfooterdlg.hxx @@ -18,9 +18,10 @@ */ #pragma once +#include #include #include -#include +#include #include diff --git a/sd/source/ui/inc/ins_paste.hxx b/sd/source/ui/inc/ins_paste.hxx index 0f10d5404699..a49bb487af52 100644 --- a/sd/source/ui/inc/ins_paste.hxx +++ b/sd/source/ui/inc/ins_paste.hxx @@ -20,7 +20,8 @@ #pragma once #include -#include +#include +#include // SdInsertPasteDlg class SdInsertPasteDlg final : public weld::GenericDialogController diff --git a/sd/source/ui/inc/inspagob.hxx b/sd/source/ui/inc/inspagob.hxx index fe1fc3adfbbb..428d0bcf5035 100644 --- a/sd/source/ui/inc/inspagob.hxx +++ b/sd/source/ui/inc/inspagob.hxx @@ -19,9 +19,10 @@ #pragma once +#include #include #include -#include +#include class SdDrawDocument; class SdPageObjsTLV; diff --git a/sd/source/ui/inc/layeroptionsdlg.hxx b/sd/source/ui/inc/layeroptionsdlg.hxx index 7a77ea4659c2..a2a890c61b34 100644 --- a/sd/source/ui/inc/layeroptionsdlg.hxx +++ b/sd/source/ui/inc/layeroptionsdlg.hxx @@ -21,10 +21,11 @@ #include +#include #include #include #include -#include +#include class SfxItemSet; diff --git a/sd/source/ui/inc/masterlayoutdlg.hxx b/sd/source/ui/inc/masterlayoutdlg.hxx index 45dcf030316c..acbc4656de0c 100644 --- a/sd/source/ui/inc/masterlayoutdlg.hxx +++ b/sd/source/ui/inc/masterlayoutdlg.hxx @@ -18,8 +18,9 @@ */ #pragma once +#include #include -#include +#include #include diff --git a/sd/source/ui/inc/morphdlg.hxx b/sd/source/ui/inc/morphdlg.hxx index 2b7cde2b9baa..a6d3977a941b 100644 --- a/sd/source/ui/inc/morphdlg.hxx +++ b/sd/source/ui/inc/morphdlg.hxx @@ -19,9 +19,10 @@ #pragma once +#include #include #include -#include +#include class SdrObject; diff --git a/sd/source/ui/inc/navigatr.hxx b/sd/source/ui/inc/navigatr.hxx index 87b651aa3a89..5366111f7b3f 100644 --- a/sd/source/ui/inc/navigatr.hxx +++ b/sd/source/ui/inc/navigatr.hxx @@ -90,8 +90,8 @@ private: bool m_bSetInitialFocusOnActivate; public: - SdNavigatorFloat(SfxBindings* _pBindings, SfxChildWindow* pMgr, - vcl::Window* pParent, SfxChildWinInfo* pInfo); + SdNavigatorFloat(SfxBindings& rBindings, SfxChildWindow* pMgr, vcl::Window* pParent, + SfxChildWinInfo& rInfo); void InitTreeLB(const SdDrawDocument* pDoc); virtual void Activate() override; virtual void dispose() override; diff --git a/sd/source/ui/inc/paragr.hxx b/sd/source/ui/inc/paragr.hxx index d1bf5825d2d3..ea552f81117c 100644 --- a/sd/source/ui/inc/paragr.hxx +++ b/sd/source/ui/inc/paragr.hxx @@ -20,6 +20,7 @@ #pragma once #include +#include /** * Paragraph-Tab-Dialog diff --git a/sd/source/ui/inc/present.hxx b/sd/source/ui/inc/present.hxx index fbae7fede489..2d3bdb926888 100644 --- a/sd/source/ui/inc/present.hxx +++ b/sd/source/ui/inc/present.hxx @@ -19,10 +19,15 @@ #pragma once +#include #include #include #include -#include +#include +#include +#include +#include +#include #include class SfxItemSet; diff --git a/sd/source/ui/inc/prltempl.hxx b/sd/source/ui/inc/prltempl.hxx index ea1ef022b882..df7f2ca1b05e 100644 --- a/sd/source/ui/inc/prltempl.hxx +++ b/sd/source/ui/inc/prltempl.hxx @@ -36,21 +36,21 @@ class SdPresLayoutTemplateDlg final : public SfxTabDialogController private: const SfxObjectShell* mpDocShell; - XColorListRef pColorTab; - XGradientListRef pGradientList; - XHatchListRef pHatchingList; - XBitmapListRef pBitmapList; - XPatternListRef pPatternList; - XDashListRef pDashList; - XLineEndListRef pLineEndList; + XColorListRef m_pColorTab; + XGradientListRef m_pGradientList; + XHatchListRef m_pHatchingList; + XBitmapListRef m_pBitmapList; + XPatternListRef m_pPatternList; + XDashListRef m_pDashList; + XLineEndListRef m_pLineEndList; - PresentationObjects ePO; + PresentationObjects m_ePO; virtual void PageCreated(const OUString& rId, SfxTabPage &rPage) override; // for mapping with the new SvxNumBulletItem - SfxItemSet aInputSet; - std::unique_ptr pOutSet; + SfxItemSet m_aInputSet; + std::unique_ptr m_pOutSet; sal_uInt16 GetOutlineLevel() const; diff --git a/sd/source/ui/inc/prntopts.hxx b/sd/source/ui/inc/prntopts.hxx index 2c391ae3283a..c9575cc55b73 100644 --- a/sd/source/ui/inc/prntopts.hxx +++ b/sd/source/ui/inc/prntopts.hxx @@ -20,6 +20,9 @@ #pragma once #include +#include +#include +#include class SdPrintOptions final : public SfxTabPage { diff --git a/sd/source/ui/inc/sdpopup.hxx b/sd/source/ui/inc/sdpopup.hxx index 535e09f2ddf8..be4fad4ac9f5 100644 --- a/sd/source/ui/inc/sdpopup.hxx +++ b/sd/source/ui/inc/sdpopup.hxx @@ -21,7 +21,7 @@ #include #include -#include +#include class SvxFieldData; diff --git a/sd/source/ui/inc/sdpreslt.hxx b/sd/source/ui/inc/sdpreslt.hxx index 6b92edd79445..8959f3ab5a4f 100644 --- a/sd/source/ui/inc/sdpreslt.hxx +++ b/sd/source/ui/inc/sdpreslt.hxx @@ -21,12 +21,19 @@ #include +#include +#include #include -#include +#include +#include class SfxItemSet; -class ValueSet; -namespace weld { class CustomWeld; } +namespace weld +{ +class CustomWeld; +class IconView; +class TreeIter; +} namespace sd { class DrawDocShell; @@ -44,7 +51,7 @@ public: void GetAttr(SfxItemSet& rOutAttrs); - DECL_LINK(ClickLayoutHdl, ValueSet*, void); + DECL_LINK(ActivateLayoutHdl, const weld::TreeIter&, bool); DECL_LINK(ClickLoadHdl, weld::Button&, void); private: @@ -55,17 +62,16 @@ private: std::vector maLayoutNames; OUString maName; ///< layout name or file name - tools::Long mnLayoutCount; ///< number of master pages in the document + int mnLayoutCount; ///< number of master pages in the document const OUString maStrNone; std::unique_ptr m_xCbxMasterPage; std::unique_ptr m_xCbxCheckMasters; std::unique_ptr m_xBtnLoad; - std::unique_ptr m_xVS; - std::unique_ptr m_xVSWin; + std::unique_ptr m_xIconView; std::unique_ptr m_xLabel; - void FillValueSet(); + void FillIconView(); void Reset(); }; diff --git a/sd/source/ui/inc/sdtreelb.hxx b/sd/source/ui/inc/sdtreelb.hxx index 0a12bc7f6b8c..a59bf9e26eca 100644 --- a/sd/source/ui/inc/sdtreelb.hxx +++ b/sd/source/ui/inc/sdtreelb.hxx @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include "sdxfer.hxx" @@ -144,8 +143,7 @@ private: DECL_LINK(KeyInputHdl, const KeyEvent&, bool); DECL_LINK(EditingEntryHdl, const weld::TreeIter&, bool); - typedef std::pair IterString; - DECL_LINK(EditedEntryHdl, const IterString&, bool); + DECL_LINK(EditedEntryHdl, const weld::TreeView::IterColText&, bool); DECL_LINK(EditEntryAgain, void*, void); DECL_LINK(CommandHdl, const CommandEvent&, bool); diff --git a/sd/source/ui/inc/titledockwin.hxx b/sd/source/ui/inc/titledockwin.hxx index 5a880e268739..597c83443c30 100644 --- a/sd/source/ui/inc/titledockwin.hxx +++ b/sd/source/ui/inc/titledockwin.hxx @@ -31,7 +31,7 @@ namespace sd { public: /** Create a new docking window. - @param pBindings + @param rBindings Used, among others, to determine the ViewShellBase and PaneManager that manage the new docking window. @param pChildWindow @@ -43,7 +43,7 @@ namespace sd the initial title */ TitledDockingWindow( - SfxBindings* i_pBindings, + SfxBindings& rBindings, SfxChildWindow* i_pChildWindow, vcl::Window* i_pParent, const OUString& rsTitle diff --git a/sd/source/ui/inc/tpaction.hxx b/sd/source/ui/inc/tpaction.hxx index 0e96b202a498..12af4a377fe9 100644 --- a/sd/source/ui/inc/tpaction.hxx +++ b/sd/source/ui/inc/tpaction.hxx @@ -24,8 +24,12 @@ #include #include #include +#include #include +#include #include +#include +#include #include "sdtreelb.hxx" #include diff --git a/sd/source/ui/inc/tpoption.hxx b/sd/source/ui/inc/tpoption.hxx index cb370d4c4a67..ea32b8b63f13 100644 --- a/sd/source/ui/inc/tpoption.hxx +++ b/sd/source/ui/inc/tpoption.hxx @@ -21,7 +21,10 @@ #include #include +#include #include +#include +#include #include /** @@ -53,6 +56,8 @@ private: std::unique_ptr m_xCbxHandlesBezierImg; std::unique_ptr m_xCbxMoveOutline; std::unique_ptr m_xCbxMoveOutlineImg; + std::unique_ptr m_xCbxZoomWithWheel; + std::unique_ptr m_xCbxZoomWithWheelImg; public: SdTpOptionsContents(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); diff --git a/sd/source/ui/inc/unoaprms.hxx b/sd/source/ui/inc/unoaprms.hxx index 28b9b613f6b4..86e951a992ca 100644 --- a/sd/source/ui/inc/unoaprms.hxx +++ b/sd/source/ui/inc/unoaprms.hxx @@ -23,6 +23,7 @@ #include #include #include +#include #include class SdDrawDocument; @@ -57,8 +58,8 @@ class SdAnimationPrmsUndoAction final : public SdUndoAction css::presentation::AnimationSpeed eNewSecondSpeed; Color aOldDimColor; Color aNewDimColor; - OUString aOldSoundFile; - OUString aNewSoundFile; + SdSoundLink aOldSoundLink; + SdSoundLink aNewSoundLink; css::presentation::ClickAction eOldClickAction; css::presentation::ClickAction eNewClickAction; OUString aOldBookmark; @@ -121,8 +122,8 @@ public: { bOldDimHide = bTheOldDimHide; bNewDimHide = bTheNewDimHide; } void SetSoundOn(bool bTheOldSoundOn, bool bTheNewSoundOn) { bOldSoundOn = bTheOldSoundOn; bNewSoundOn = bTheNewSoundOn; } - void SetSound(const OUString& aTheOldSound, const OUString& aTheNewSound) - { aOldSoundFile = aTheOldSound; aNewSoundFile = aTheNewSound; } + void SetSound(const SdSoundLink& aTheOldSound, const SdSoundLink& aTheNewSound) + { aOldSoundLink = aTheOldSound; aNewSoundLink = aTheNewSound; } void SetPlayFull(bool bTheOldPlayFull, bool bTheNewPlayFull) { bOldPlayFull = bTheOldPlayFull; bNewPlayFull = bTheNewPlayFull; } void SetClickAction(css::presentation::ClickAction eTheOldAction, css::presentation::ClickAction eTheNewAction) diff --git a/sd/source/ui/inc/unopage.hxx b/sd/source/ui/inc/unopage.hxx index f27b79ad4ce8..a4d1b87dc2f9 100644 --- a/sd/source/ui/inc/unopage.hxx +++ b/sd/source/ui/inc/unopage.hxx @@ -40,6 +40,10 @@ class SdrObject; class SdXImpressDocument; class SdMasterPage; +/** The shape type a presentation object of the given kind claims - what the placeholder is, which + can differ from what currently represents it on the page. */ +OUString GetPresObjShapeType(PresObjKind eKind); + class SdGenericDrawPage : public SvxDrawPage, public SdUnoSearchReplaceShape, public css::drawing::XShapeCombiner, diff --git a/sd/source/ui/inc/vectdlg.hxx b/sd/source/ui/inc/vectdlg.hxx index f830ba979ba8..ec25911c1008 100644 --- a/sd/source/ui/inc/vectdlg.hxx +++ b/sd/source/ui/inc/vectdlg.hxx @@ -19,10 +19,13 @@ #pragma once +#include +#include #include +#include #include +#include #include -#include #include namespace sd { diff --git a/sd/source/ui/presenter/SlideRenderer.cxx b/sd/source/ui/presenter/SlideRenderer.cxx index 5f61677bd48f..c189efef4457 100644 --- a/sd/source/ui/presenter/SlideRenderer.cxx +++ b/sd/source/ui/presenter/SlideRenderer.cxx @@ -118,7 +118,7 @@ Bitmap SlideRenderer::CreatePreview ( // Create the preview. When the super sample factor n is greater than 1 // then a preview is created in size (n*width, n*height) and then scaled - // down to (width, height). This is a poor mans antialiasing for the + // down to (width, height). This is a poor man's antialiasing for the // time being. When we have true antialiasing support this workaround // can be removed. const Image aPreview = maPreviewRenderer.RenderPage ( diff --git a/sd/source/ui/sidebar/LayoutMenu.cxx b/sd/source/ui/sidebar/LayoutMenu.cxx index d60edf01889c..63077f931ef1 100644 --- a/sd/source/ui/sidebar/LayoutMenu.cxx +++ b/sd/source/ui/sidebar/LayoutMenu.cxx @@ -69,7 +69,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::text; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using namespace ::sd::slidesorter; using ::sd::framework::FrameworkHelper; @@ -574,7 +573,7 @@ void LayoutMenu::HandleMenuSelect(std::u16string_view rIdent) // Selects an appropriate layout of the slide inside control. // // Method may be called several times with the same item-id to be selected - -// only once the actually state of the control will be changed. +// only once the actual state of the control will be changed. // void LayoutMenu::UpdateSelection() { @@ -596,9 +595,9 @@ void LayoutMenu::UpdateSelection() if (aLayoutAUTOLAYOUT_END) break; - // Find the entry of the menu for to the layout. + // Find the entry of the menu for the layout. const sal_uInt16 nItemCount = mxLayoutIconView->n_children(); - for (sal_uInt16 nId=0; nIdget_id(nId); if (!sItemId.isEmpty() && static_cast(sItemId.toInt32()) == aLayout) @@ -660,6 +659,6 @@ void LayoutMenu::DataChanged(const DataChangedEvent& rEvent) Fill(); } -} // end of namespace ::sd::sidebar +} // end of namespace sd::sidebar /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/sidebar/MasterPageContainerQueue.cxx b/sd/source/ui/sidebar/MasterPageContainerQueue.cxx index c80eb3498352..584e1a295e95 100644 --- a/sd/source/ui/sidebar/MasterPageContainerQueue.cxx +++ b/sd/source/ui/sidebar/MasterPageContainerQueue.cxx @@ -151,8 +151,6 @@ bool MasterPageContainerQueue::RequestPreview (const SharedMasterPageDescriptor& sal_Int32 MasterPageContainerQueue::CalculatePriority ( const SharedMasterPageDescriptor& rpDescriptor) { - sal_Int32 nPriority; - // The cost is used as a starting value. int nCost (0); if (rpDescriptor->mpPreviewProvider != nullptr) @@ -165,7 +163,7 @@ sal_Int32 MasterPageContainerQueue::CalculatePriority ( // Its negative value is used so that requests with a low cost are // preferred over those with high costs. - nPriority = -nCost; + sal_Int32 nPriority = -nCost; // Add a term that introduces an order based on the appearance in the // AllMasterPagesSelector. diff --git a/sd/source/ui/sidebar/MasterPagesSelector.hxx b/sd/source/ui/sidebar/MasterPagesSelector.hxx index 3bd387ffc51f..bfd25e2dd9fd 100644 --- a/sd/source/ui/sidebar/MasterPagesSelector.hxx +++ b/sd/source/ui/sidebar/MasterPagesSelector.hxx @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -82,7 +81,7 @@ public: virtual void LateInit(); - /** Make the selector empty. This method clear the value set from any + /** Make the selector empty. This method clears the value set from any entries. Override this method to add functionality, especially to destroy objects set as data items at the value set. */ @@ -92,7 +91,7 @@ public: /** Mark the preview that belongs to the given index as not up-to-date anymore with respect to page content or preview size. - The implementation of this method will either sunchronously or + The implementation of this method will either synchronously or asynchronously call UpdatePreview(). @param nIndex Index into the value set control that is used for displaying the @@ -125,7 +124,7 @@ protected: void AssignMasterPageToAllSlides (SdPage* pMasterPage); /** Assign the given master page to all slides that are selected in a - slide sorter that is displayed in the lef or center pane. When both + slide sorter that is displayed in the left or center pane. When both panes display a slide sorter then the one in the center pane is used. */ diff --git a/sd/source/ui/sidebar/PanelFactory.cxx b/sd/source/ui/sidebar/PanelFactory.cxx index 4f670cc077aa..11aa025a4ca5 100644 --- a/sd/source/ui/sidebar/PanelFactory.cxx +++ b/sd/source/ui/sidebar/PanelFactory.cxx @@ -36,7 +36,7 @@ #include #include #include -#include +#include using namespace css; using namespace css::uno; diff --git a/sd/source/ui/sidebar/SlideBackground.cxx b/sd/source/ui/sidebar/SlideBackground.cxx index 3e3f2cd57baa..a02ed1dfe62d 100644 --- a/sd/source/ui/sidebar/SlideBackground.cxx +++ b/sd/source/ui/sidebar/SlideBackground.cxx @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -261,16 +262,6 @@ void SlideBackground::Initialize() UpdateMarginBox(); } -void SlideBackground::DumpAsPropertyTree(::tools::JsonWriter& rJsonWriter) -{ - if (mxPaperSizeBox->get_active() == -1) - { - mpBindings->Update(SID_ATTR_PAGE_SIZE); - } - - PanelLayout::DumpAsPropertyTree(rJsonWriter); -} - void SlideBackground::HandleContextChange( const vcl::EnumContext& rContext) { @@ -843,6 +834,38 @@ OUString const & SlideBackground::GetPatternSetOrDefault() return mpBitmapItem->GetName(); } +namespace +{ +MapUnit lcl_FieldUnitToMapUnit( FieldUnit eFieldUnit ) +{ + switch( eFieldUnit ) + { // only units available for units of measurement + // convert to unit for page size + case FieldUnit::MM : + return MapUnit::MapMM; + case FieldUnit::CM : + case FieldUnit::M : + case FieldUnit::KM : + return MapUnit::MapCM; + case FieldUnit::INCH : + case FieldUnit::FOOT : + case FieldUnit::MILE : + case FieldUnit::PICA : // No exact conversion + return MapUnit::MapInch; + case FieldUnit::POINT : + return MapUnit::MapPoint; + // No corresponding conversion + case FieldUnit::CHAR : + case FieldUnit::LINE : + return MapUnit::MapPixel; + default : + SAL_WARN( "sd.ui", "invalid field unit for measurement" ); + // default value + return MapUnit::MapCM; + } +} +} + void SlideBackground::NotifyItemUpdate( const sal_uInt16 nSID, const SfxItemState eState, @@ -953,6 +976,11 @@ void SlideBackground::NotifyItemUpdate( Paper ePaper = SvxPaperInfo::GetSvxPaper(aPaperSize, meUnit); mxPaperSizeBox->set_active_id( ePaper ); + OUString sHelp; + const IntlWrapper aIntlWrapper( Application::GetSettings().GetUILanguageTag() ); + pSizeItem->GetPresentation( SfxItemPresentation::Complete, meUnit, + lcl_FieldUnitToMapUnit( meFUnit ), sHelp, aIntlWrapper ); + mxPaperSizeBox->set_tooltip_text( sHelp ); } } break; diff --git a/sd/source/ui/sidebar/SlideBackground.hxx b/sd/source/ui/sidebar/SlideBackground.hxx index fb899367ff4a..d02abc6e90df 100644 --- a/sd/source/ui/sidebar/SlideBackground.hxx +++ b/sd/source/ui/sidebar/SlideBackground.hxx @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include @@ -68,7 +71,6 @@ public: virtual void HandleContextChange( const vcl::EnumContext& rContext) override; - virtual void DumpAsPropertyTree(::tools::JsonWriter&) override; private: diff --git a/sd/source/ui/sidebar/SlideMasterPagesAllToolBoxControl.cxx b/sd/source/ui/sidebar/SlideMasterPagesAllToolBoxControl.cxx index 733e6ba0c306..12014b69d97c 100644 --- a/sd/source/ui/sidebar/SlideMasterPagesAllToolBoxControl.cxx +++ b/sd/source/ui/sidebar/SlideMasterPagesAllToolBoxControl.cxx @@ -1,3 +1,4 @@ +#include #include #include #include @@ -25,11 +26,14 @@ SlideMasterPagesAllToolBoxControl::statusChanged(const css::frame::FeatureStateE // Handle status changes if needed } -void SAL_CALL SlideMasterPagesAllToolBoxControl::dispose() +void SlideMasterPagesAllToolBoxControl::disposing(std::unique_lock& rGuard) { - SolarMutexGuard aSolarMutexGuard; - m_xVclBox.disposeAndClear(); - svt::ToolboxController::dispose(); + { + comphelper::unique_unlock aUnlock(rGuard); + SolarMutexGuard aSolarMutexGuard; + m_xVclBox.disposeAndClear(); + } + svt::ToolboxController::disposing(rGuard); } css::uno::Reference SlideMasterPagesAllToolBoxControl::createItemWindow( @@ -85,8 +89,7 @@ com_sun_star_comp_sd_SlideMasterPagesAllToolBoxControl_get_implementation( SlideMasterPagesAllWrapper::SlideMasterPagesAllWrapper(vcl::Window* pParent, sd::ViewShellBase& rBase) : InterimItemWindow(pParent, u"modules/simpress/ui/masterpagepanelall.ui"_ustr, - u"MasterPagePanel"_ustr, true, - reinterpret_cast(SfxViewShell::Current())) + u"MasterPagePanel"_ustr, true) { SdDrawDocument* pDocument = rBase.GetDocument(); assert(pDocument && "SlideMasterPagesAllWrapper got null SdDrawDocument"); diff --git a/sd/source/ui/sidebar/SlideMasterPagesAllToolBoxControl.hxx b/sd/source/ui/sidebar/SlideMasterPagesAllToolBoxControl.hxx index 7a1580411cef..7c9a5bcd156c 100644 --- a/sd/source/ui/sidebar/SlideMasterPagesAllToolBoxControl.hxx +++ b/sd/source/ui/sidebar/SlideMasterPagesAllToolBoxControl.hxx @@ -18,8 +18,9 @@ public: void SetOptimalSize(); }; -class SlideMasterPagesAllToolBoxControl final - : public cppu::ImplInheritanceHelper +using SlideMasterPagesAllToolBoxControl_Base + = cppu::ImplInheritanceHelper; +class SlideMasterPagesAllToolBoxControl final : public SlideMasterPagesAllToolBoxControl_Base { VclPtr m_xVclBox; @@ -37,8 +38,9 @@ public: // XInitialization virtual void SAL_CALL initialize(const css::uno::Sequence& rArguments) override; - // XComponent - virtual void SAL_CALL dispose() override; + // WeakComponentImplHelperBase + using SlideMasterPagesAllToolBoxControl_Base::disposing; + virtual void disposing(std::unique_lock& rGuard) override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; diff --git a/sd/source/ui/slideshow/PaneHider.cxx b/sd/source/ui/slideshow/PaneHider.cxx index 88f2c3b708f3..298f0bebcaf5 100644 --- a/sd/source/ui/slideshow/PaneHider.cxx +++ b/sd/source/ui/slideshow/PaneHider.cxx @@ -34,7 +34,6 @@ #include using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; using ::com::sun::star::lang::DisposedException; @@ -63,7 +62,7 @@ PaneHider::PaneHider(const ViewShell& rViewShell, SlideshowImpl* pSlideShow) const std::vector> aResources( mxConfiguration->getResources(nullptr, framework::FrameworkHelper::msPaneURLPrefix, - AnchorBindingMode_DIRECT)); + framework::AnchorBindingMode::DIRECT)); for (const rtl::Reference& xPaneId : aResources) { if (xPaneId->getResourceURL() != FrameworkHelper::msCenterPaneURL) diff --git a/sd/source/ui/slideshow/slideshowimpl.cxx b/sd/source/ui/slideshow/slideshowimpl.cxx index e5248d2a17d8..3e22e79d862d 100644 --- a/sd/source/ui/slideshow/slideshowimpl.cxx +++ b/sd/source/ui/slideshow/slideshowimpl.cxx @@ -77,6 +77,7 @@ #include #include #include +#include #include #include @@ -96,6 +97,7 @@ #include #include #include +#include #include #include #include @@ -1734,14 +1736,25 @@ void SlideshowImpl::click( const Reference< XShape >& xShape ) case ClickAction_SOUND: { #if HAVE_FEATURE_AVMEDIA - try + // Fetch the sound only when its external link has been allowed this + // session. + SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape); + SdAnimationInfo* pInfo = pObj ? SdDrawDocument::GetShapeUserData(*pObj) : nullptr; + if (pInfo) { - mxPlayer.set(avmedia::MediaWindow::createPlayer(pEvent->maStrBookmark, u""_ustr/*TODO?*/), uno::UNO_SET_THROW ); - mxPlayer->start(); - } - catch( uno::Exception& ) - { - TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::click()" ); + SdSoundLink aSound(pInfo->GetBookmark(), pInfo->mbClickSoundAllowed); + if (aSound.isAllowed()) + { + try + { + mxPlayer.set(avmedia::MediaWindow::createPlayer(aSound.getURL(), u""_ustr/*TODO?*/), uno::UNO_SET_THROW ); + mxPlayer->start(); + } + catch( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::click()" ); + } + } } #endif } diff --git a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx index 749bacddd7df..81906396f515 100644 --- a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx +++ b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -305,7 +306,39 @@ bool SlideSorterController::Command ( aPopupId = "pagepane"; } else - aPopupId = "pagepanenosel"; + { + // Check if the click is on a section header + bool bOnSectionHeader = false; + if (rEvent.IsMouseEvent()) + { + Point aModelPos = pWindow->PixelToLogic(rEvent.GetMousePosPixel()); + sal_Int32 nSectionIdx + = mrView.GetLayouter().GetSectionIndexAtPoint(aModelPos); + if (nSectionIdx >= 0) + { + bOnSectionHeader = true; + // Select the first slide of this section so + // section commands can operate on it + SdDrawDocument* pDoc = mrModel.GetDocument(); + if (pDoc) + { + sd::SlideSectionManager& rMgr = pDoc->GetSectionManager(); + if (nSectionIdx < rMgr.GetSectionCount()) + { + sal_Int32 nStartIdx = rMgr.GetSection(nSectionIdx).mnStartIndex; + model::SharedPageDescriptor pDesc( + mrModel.GetPageDescriptor(nStartIdx)); + if (pDesc) + { + GetPageSelector().DeselectAllPages(); + GetPageSelector().SelectPage(pDesc); + } + } + } + } + } + aPopupId = bOnSectionHeader ? "sectionheader" : "pagepanenosel"; + } } else if (pPage != nullptr) { @@ -318,7 +351,7 @@ bool SlideSorterController::Command ( aPopupId = "pagepanenoselmaster"; std::unique_ptr> xContext; - if (pPage == nullptr) + if (pPage == nullptr && aPopupId != "sectionheader") { // When there is no selection, then we show the insertion // indicator so that the user knows where a page insertion diff --git a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx index 613f558b7464..3f8b2e5d0619 100644 --- a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx +++ b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx @@ -993,8 +993,10 @@ bool Clipboard::PasteSlidesFromSystemClipboard() auto insertPos = mrSlideSorter.GetModel().GetCoreIndex( mrSlideSorter.GetController().GetClipboard().GetInsertionPosition()); + // Slide sorter paste: scale objects instead of asking. pDocument->InsertFileAsPage(aBookmarkList, &aExchangeList, false /*bLink*/, - insertPos /*nPos*/, xDocShRef.get()); + insertPos /*nPos*/, xDocShRef.get(), + /*oScaleObjects=*/std::optional(true)); std::vector aObjectBookmarkList; pDocument->InsertBookmarkAsObject(aObjectBookmarkList, aExchangeList, xDocShRef.get(), diff --git a/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx index 7f1c51727703..fad906c37a3e 100644 --- a/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx +++ b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx @@ -73,7 +73,7 @@ void FocusManager::MoveFocus (FocusMoveDirection eDirection) const sal_Int32 nCandidate (mnPageIndex - nColumnCount); if (nCandidate >= 0) { - // Move the focus the previous row. + // Move the focus to the previous row. mnPageIndex = nCandidate; } } @@ -175,7 +175,7 @@ void FocusManager::HideFocusIndicator (const model::SharedPageDescriptor& rpDesc { mrSlideSorter.GetView().SetState(rpDescriptor, model::PageDescriptor::ST_Focused, false); - // Hide focus should also fire the focus event, Currently, only accessibility add the focus listener + // Hiding focus should also fire the focus event. Currently, only accessibility adds the focus listener NotifyFocusChangeListeners(); } } @@ -220,7 +220,7 @@ void FocusManager::NotifyFocusChangeListeners() const // Create a copy of the listener list to be safe when that is modified. ::std::vector> aListeners (maFocusChangeListeners); - // Tell the selection change listeners that the selection has changed. + // Tell the focus change listeners that the focus has changed. for (const auto& rListener : aListeners) { rListener.Call(nullptr); diff --git a/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx index 1942f181502b..7c2204f19087 100644 --- a/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx +++ b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include #include @@ -76,6 +78,7 @@ #include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -281,6 +284,36 @@ void SlotManager::FuTemporary (SfxRequest& rRequest) rRequest.Done (); break; + case SID_ADD_SLIDE_SECTION: + AddSection(); + rRequest.Done(); + break; + + case SID_REMOVE_SLIDE_SECTION: + RemoveSection(); + rRequest.Done(); + break; + + case SID_REMOVE_SLIDE_SECTION_AND_SLIDES: + RemoveSectionAndSlides(); + rRequest.Done(); + break; + + case SID_RENAME_SLIDE_SECTION: + RenameSection(); + rRequest.Done(); + break; + + case SID_MOVE_SLIDE_SECTION_UP: + MoveSectionUp(); + rRequest.Done(); + break; + + case SID_MOVE_SLIDE_SECTION_DOWN: + MoveSectionDown(); + rRequest.Done(); + break; + case SID_ASSIGN_LAYOUT: { pShell->mpImpl->AssignLayout( rRequest, PageKind::Standard ); @@ -671,6 +704,62 @@ void SlotManager::GetMenuState (SfxItemSet& rSet) } } + if (rSet.GetItemState(SID_ADD_SLIDE_SECTION) == SfxItemState::DEFAULT + || rSet.GetItemState(SID_REMOVE_SLIDE_SECTION) == SfxItemState::DEFAULT + || rSet.GetItemState(SID_REMOVE_SLIDE_SECTION_AND_SLIDES) == SfxItemState::DEFAULT + || rSet.GetItemState(SID_RENAME_SLIDE_SECTION) == SfxItemState::DEFAULT + || rSet.GetItemState(SID_MOVE_SLIDE_SECTION_UP) == SfxItemState::DEFAULT + || rSet.GetItemState(SID_MOVE_SLIDE_SECTION_DOWN) == SfxItemState::DEFAULT) + { + int nSelected = mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount(); + if (nSelected != 1) + { + rSet.DisableItem(SID_ADD_SLIDE_SECTION); + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION); + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION_AND_SLIDES); + rSet.DisableItem(SID_RENAME_SLIDE_SECTION); + rSet.DisableItem(SID_MOVE_SLIDE_SECTION_UP); + rSet.DisableItem(SID_MOVE_SLIDE_SECTION_DOWN); + } + else + { + // Get the selected slide's page index + model::PageEnumeration aSelectedPages( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + if (aSelectedPages.HasMoreElements()) + { + SdPage* pPage = aSelectedPages.GetNextElement()->GetPage(); + SdDrawDocument* pDoc = mrSlideSorter.GetModel().GetDocument(); + sd::SlideSectionManager& rMgr = pDoc->GetSectionManager(); + sal_Int32 nPageIndex + = model::FromCoreIndex(pPage->GetPageNum()); + + // Disable "Add Section" if this slide already starts a section + if (rMgr.IsSectionStart(nPageIndex)) + rSet.DisableItem(SID_ADD_SLIDE_SECTION); + + // Disable "Remove/Rename Section" if this slide is NOT a section start + if (!rMgr.IsSectionStart(nPageIndex)) + { + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION); + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION_AND_SLIDES); + rSet.DisableItem(SID_RENAME_SLIDE_SECTION); + rSet.DisableItem(SID_MOVE_SLIDE_SECTION_UP); + rSet.DisableItem(SID_MOVE_SLIDE_SECTION_DOWN); + } + else + { + sal_Int32 nSectionIdx = rMgr.GetSectionIndexForSlide(nPageIndex); + if (nSectionIdx <= 0) + rSet.DisableItem(SID_MOVE_SLIDE_SECTION_UP); + if (nSectionIdx < 0 || nSectionIdx >= rMgr.GetSectionCount() - 1) + rSet.DisableItem(SID_MOVE_SLIDE_SECTION_DOWN); + } + } + } + } + if (rSet.GetItemState(SID_HIDE_SLIDE) == SfxItemState::DEFAULT || rSet.GetItemState(SID_SHOW_SLIDE) == SfxItemState::DEFAULT) { @@ -1054,6 +1143,180 @@ bool SlotManager::RenameSlideFromDrawViewShell( sal_uInt16 nPageId, const OUStri return bSuccess; } +namespace +{ +struct SectionContext +{ + sd::SlideSectionManager* pMgr; + sal_Int32 nPageIndex; + sal_Int32 nSectionIndex; +}; + +/** Get the section context for the currently selected slide. + Returns std::nullopt if no single slide is selected or the document is unavailable. */ +std::optional GetSelectedSectionContext(SlideSorter& rSlideSorter) +{ + model::PageEnumeration aSelectedPages( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration(rSlideSorter.GetModel())); + if (!aSelectedPages.HasMoreElements()) + return std::nullopt; + + SdPage* pPage = aSelectedPages.GetNextElement()->GetPage(); + SdDrawDocument* pDoc = rSlideSorter.GetModel().GetDocument(); + if (!pDoc) + return std::nullopt; + + SectionContext aCtx; + aCtx.pMgr = &pDoc->GetSectionManager(); + aCtx.nPageIndex = model::FromCoreIndex(pPage->GetPageNum()); + aCtx.nSectionIndex = aCtx.pMgr->GetSectionIndexForSlide(aCtx.nPageIndex); + return aCtx; +} +} // anonymous namespace + +void SlotManager::NotifySectionChange() +{ + mrSlideSorter.GetModel().GetDocument()->GetDocSh()->SetModified(); + mrSlideSorter.GetView().HandleModelChange(); + mrSlideSorter.GetView().RequestRepaint(); +} + +void SlotManager::AddSection() +{ + auto oCtx = GetSelectedSectionContext(mrSlideSorter); + if (!oCtx) + return; + + SdDrawDocument* pDoc = mrSlideSorter.GetModel().GetDocument(); + auto pUndo = (pDoc && pDoc->IsUndoEnabled()) + ? std::make_unique(*pDoc, SdResId(STR_UNDO_ADD_SLIDE_SECTION)) + : nullptr; + oCtx->pMgr->AddSection(oCtx->nPageIndex, SdResId(STR_DEFAULT_SLIDE_SECTION_NAME)); + if (pUndo) + pDoc->AddUndo(std::move(pUndo)); + NotifySectionChange(); +} + +void SlotManager::RemoveSection() +{ + auto oCtx = GetSelectedSectionContext(mrSlideSorter); + if (!oCtx) + return; + + if (oCtx->nSectionIndex >= 0 && oCtx->pMgr->IsSectionStart(oCtx->nPageIndex)) + { + SdDrawDocument* pDoc = mrSlideSorter.GetModel().GetDocument(); + auto pUndo = (pDoc && pDoc->IsUndoEnabled()) + ? std::make_unique(*pDoc, SdResId(STR_UNDO_REMOVE_SLIDE_SECTION)) + : nullptr; + oCtx->pMgr->RemoveSection(oCtx->nSectionIndex); + if (pUndo) + pDoc->AddUndo(std::move(pUndo)); + NotifySectionChange(); + } +} + +void SlotManager::RemoveSectionAndSlides() +{ + auto oCtx = GetSelectedSectionContext(mrSlideSorter); + if (!oCtx) + return; + if (oCtx->nSectionIndex < 0 || !oCtx->pMgr->IsSectionStart(oCtx->nPageIndex)) + return; + + SdDrawDocument* pDoc = mrSlideSorter.GetModel().GetDocument(); + if (!pDoc) + return; + + const bool bUndo = pDoc->IsUndoEnabled(); + if (bUndo) + pDoc->BegUndo(SdResId(STR_UNDO_REMOVE_SLIDE_SECTION_AND_SLIDES)); + + oCtx->pMgr->RemoveSectionSlides(oCtx->nSectionIndex); + + if (bUndo) + pDoc->EndUndo(); + + mrSlideSorter.GetController().HandleModelChange(); +} + +void SlotManager::RenameSection() +{ + auto oCtx = GetSelectedSectionContext(mrSlideSorter); + if (!oCtx || oCtx->nSectionIndex < 0) + return; + + const sd::SlideSection& rSection = oCtx->pMgr->GetSection(oCtx->nSectionIndex); + OUString aOldName = rSection.maName; + + vcl::Window* pWin = mrSlideSorter.GetContentWindow().get(); + SvxNameDialog aNameDlg(pWin ? pWin->GetFrameWeld() : nullptr, aOldName, SdResId(STR_RENAME_SLIDE_SECTION)); + + if (aNameDlg.run() == RET_OK) + { + OUString aNewName = aNameDlg.GetName(); + if (!aNewName.isEmpty() && aNewName != aOldName) + { + SdDrawDocument* pDoc = mrSlideSorter.GetModel().GetDocument(); + auto pUndo = (pDoc && pDoc->IsUndoEnabled()) + ? std::make_unique( + *pDoc, SdResId(STR_UNDO_RENAME_SLIDE_SECTION)) + : nullptr; + oCtx->pMgr->RenameSection(oCtx->nSectionIndex, aNewName); + if (pUndo) + pDoc->AddUndo(std::move(pUndo)); + NotifySectionChange(); + } + } +} + +void SlotManager::MoveSectionUp() +{ + auto oCtx = GetSelectedSectionContext(mrSlideSorter); + if (!oCtx || oCtx->nSectionIndex <= 0) + return; + + SdDrawDocument* pDoc = mrSlideSorter.GetModel().GetDocument(); + const bool bUndo = pDoc && pDoc->IsUndoEnabled(); + // Group the section metadata undo with the page-reorder undo + // recorded by MovePages() inside MoveSection(). + if (bUndo) + pDoc->BegUndo(SdResId(STR_UNDO_MOVE_SLIDE_SECTION)); + auto pUndo = bUndo + ? std::make_unique(*pDoc, SdResId(STR_UNDO_MOVE_SLIDE_SECTION)) + : nullptr; + oCtx->pMgr->MoveSection(oCtx->nSectionIndex, oCtx->nSectionIndex - 1); + if (bUndo) + { + pDoc->AddUndo(std::move(pUndo)); + pDoc->EndUndo(); + } + NotifySectionChange(); +} + +void SlotManager::MoveSectionDown() +{ + auto oCtx = GetSelectedSectionContext(mrSlideSorter); + if (!oCtx || oCtx->nSectionIndex < 0 + || oCtx->nSectionIndex >= oCtx->pMgr->GetSectionCount() - 1) + return; + + SdDrawDocument* pDoc = mrSlideSorter.GetModel().GetDocument(); + const bool bUndo = pDoc && pDoc->IsUndoEnabled(); + if (bUndo) + pDoc->BegUndo(SdResId(STR_UNDO_MOVE_SLIDE_SECTION)); + auto pUndo = bUndo + ? std::make_unique(*pDoc, SdResId(STR_UNDO_MOVE_SLIDE_SECTION)) + : nullptr; + oCtx->pMgr->MoveSection(oCtx->nSectionIndex, oCtx->nSectionIndex + 1); + if (bUndo) + { + pDoc->AddUndo(std::move(pUndo)); + pDoc->EndUndo(); + } + NotifySectionChange(); +} + /** Insert a slide. The insertion position depends on a) the selection and b) the mouse position when there is no selection. diff --git a/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx b/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx index 6482def0aa4a..ec27abddb457 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx @@ -133,7 +133,7 @@ public: /** Paste the slides copied from another instance of the LibreOffice */ - bool PasteSlidesFromSystemClipboard(); + SD_DLLPUBLIC bool PasteSlidesFromSystemClipboard(); private: /** Paste the pages of the transferable of the sd module at the given diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx index 128fffe52de2..82e7e92ad638 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx @@ -87,6 +87,14 @@ private: void DuplicateSelectedSlides(SfxRequest& rRequest); + void AddSection(); + void RemoveSection(); + void RemoveSectionAndSlides(); + void RenameSection(); + void MoveSectionUp(); + void MoveSectionDown(); + void NotifySectionChange(); + /** Use one of several ways to determine where to insert a new page. This can be the current selection or the insertion indicator. */ diff --git a/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx b/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx index 0f3493ab3681..1d974fbf3834 100644 --- a/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx @@ -207,6 +207,7 @@ private: std::shared_ptr mpPageObjectPainter; vcl::Region maRedrawRegion; SharedILayerPainter mpBackgroundPainter; + SharedILayerPainter mpSectionHeaderPainter; std::unique_ptr> mpToolTip; bool mbIsRearrangePending; ::std::vector> maVisibilityChangeListeners; diff --git a/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx b/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx index 2629d15b574f..97497ea05451 100644 --- a/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx @@ -173,6 +173,16 @@ public: Range GetValidHorizontalSizeRange() const; Range GetValidVerticalSizeRange() const; + /** Set the slide indices where sections start. + This triggers recomputation of section header Y offsets. + */ + void SetSectionStarts(const std::vector& rSectionStartIndices); + + /** Returns the section index at the given model Y position, or -1. */ + sal_Int32 GetSectionIndexAtPoint(const Point& rModelPosition) const; + + static sal_Int32 GetSectionHeaderHeight(); + class Implementation; private: diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx index 7c8fb98198e3..8f36b50a7da4 100644 --- a/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx @@ -67,7 +67,9 @@ public: TransitionEffectIndicator, // Indicator whether or not there is a custom animation associated // with this slide. - CustomAnimationEffectIndicator + CustomAnimationEffectIndicator, + // Bounding box of the slide name when the slide was renamed + PageName }; /** Two coordinate systems are supported. They differ only in translation not in scale. Both relate to pixel values in the window. @@ -128,6 +130,8 @@ private: ::tools::Rectangle maPreviewBoundingBox; ::tools::Rectangle maTransitionEffectBoundingBox; ::tools::Rectangle maCustomAnimationEffectBoundingBox; + ::tools::Rectangle maPageNameAreaBoundingBox; + ::tools::Rectangle maPreviewWithNameBoundingBox; const Image maTransitionEffectIcon; const Image maCustomAnimationEffectIcon; const std::shared_ptr mpPageNumberFont; diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx index c6d5595d268d..5d91e017831f 100644 --- a/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx @@ -96,6 +96,12 @@ private: OutputDevice& rDevice, const Theme::GradientColorType eColorType, const ::tools::Rectangle& rBox) const; + void PaintPageName ( + PageObjectLayouter *pPageObjectLayouter, + OutputDevice& rDevice, + const model::SharedPageDescriptor& rpDescriptor) const; + Color GetPageTextColor ( + const model::SharedPageDescriptor& rpDescriptor) const; void PaintBackgroundDetail( PageObjectLayouter *pPageObjectLayouter, OutputDevice& rDevice, diff --git a/sd/source/ui/slidesorter/view/SlideSorterView.cxx b/sd/source/ui/slidesorter/view/SlideSorterView.cxx index 31bf3df7612b..10ac7e7679c9 100644 --- a/sd/source/ui/slidesorter/view/SlideSorterView.cxx +++ b/sd/source/ui/slidesorter/view/SlideSorterView.cxx @@ -28,6 +28,7 @@ #include #include #include +#include "SlsSectionHeaderPainter.hxx" #include #include #include @@ -38,6 +39,8 @@ #include #include +#include +#include #include #include @@ -146,6 +149,10 @@ SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter) // a little faster during animations because the previews are painted // directly into the window, not via the buffer. mpLayeredDevice->RegisterPainter(pPainter, 1); + + // Register the section header painter on level 1 (same as slides). + mpSectionHeaderPainter = std::make_shared(mrSlideSorter); + mpLayeredDevice->RegisterPainter(mpSectionHeaderPainter, 1); } SlideSorterView::~SlideSorterView() @@ -298,6 +305,16 @@ void SlideSorterView::Rearrange() if (bRearrangeSuccess) { mbIsRearrangePending = false; + + // Pass section start indices to the layouter for header offset computation + SdDrawDocument* pDocument = mrModel.GetDocument(); + if (pDocument) + { + sd::SlideSectionManager& rSectionMgr = pDocument->GetSectionManager(); + // Pass current section start indices to the layouter. + mpLayouter->SetSectionStarts(rSectionMgr.GetSectionStartIndices()); + } + Layout(); UpdatePageUnderMouse(); // RequestRepaint(); diff --git a/sd/source/ui/slidesorter/view/SlsLayouter.cxx b/sd/source/ui/slidesorter/view/SlsLayouter.cxx index 203e8a380bd8..ebb7d1aaec9a 100644 --- a/sd/source/ui/slidesorter/view/SlsLayouter.cxx +++ b/sd/source/ui/slidesorter/view/SlsLayouter.cxx @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -61,6 +62,10 @@ public: Size maPageObjectSize; std::unique_ptr mpPageObjectLayouter; std::shared_ptr mpTheme; + static const sal_Int32 gnSectionHeaderHeight = 20; + std::vector maSectionStartIndices; + // Cumulative Y offset for each row due to section headers above it + std::vector maSectionRowOffsets; /** Specify how the gap between two page objects is associated with the page objects. @@ -197,6 +202,13 @@ public: ::tools::Rectangle GetTotalBoundingBox() const; + void SetSectionStarts(const std::vector& rSectionStartIndices); + void ComputeSectionRowOffsets(); + sal_Int32 GetSectionOffsetForRow(sal_Int32 nRow) const; + + /// Returns the section index at the given Y position, or -1 if not on a header. + sal_Int32 GetSectionIndexAtPoint(sal_Int32 nYPosition) const; + virtual ~Implementation(); protected: @@ -416,6 +428,18 @@ sal_Int32 Layouter::GetIndexAtPoint(const Point& rPosition) const return mpImplementation->GetIndex(nRow,nColumn, /*bClampToValidRange*/ false); } +void Layouter::SetSectionStarts(const std::vector& rSectionStartIndices) +{ + mpImplementation->SetSectionStarts(rSectionStartIndices); +} + +sal_Int32 Layouter::GetSectionIndexAtPoint(const Point& rModelPosition) const +{ + return mpImplementation->GetSectionIndexAtPoint(rModelPosition.Y()); +} + +sal_Int32 Layouter::GetSectionHeaderHeight() { return Implementation::gnSectionHeaderHeight; } + //===== Layouter::Implementation ============================================== Layouter::Implementation* Layouter::Implementation::Create ( @@ -454,24 +478,26 @@ Layouter::Implementation::Implementation ( { } -Layouter::Implementation::Implementation (const Implementation& rImplementation) - : mpWindow(rImplementation.mpWindow), - mnLeftBorder(rImplementation.mnLeftBorder), - mnRightBorder(rImplementation.mnRightBorder), - mnTopBorder(rImplementation.mnTopBorder), - mnBottomBorder(rImplementation.mnBottomBorder), - maMinimalSize(rImplementation.maMinimalSize), - maPreferredSize(rImplementation.maPreferredSize), - maMaximalSize(rImplementation.maMaximalSize), - mnMinimalColumnCount(rImplementation.mnMinimalColumnCount), - mnMaximalColumnCount(rImplementation.mnMaximalColumnCount), - mnPageCount(rImplementation.mnPageCount), - mnColumnCount(rImplementation.mnColumnCount), - mnRowCount(rImplementation.mnRowCount), - mnMaxColumnCount(rImplementation.mnMaxColumnCount), - mnMaxRowCount(rImplementation.mnMaxRowCount), - maPageObjectSize(rImplementation.maPageObjectSize), - mpTheme(rImplementation.mpTheme) +Layouter::Implementation::Implementation(const Implementation& rImplementation) + : mpWindow(rImplementation.mpWindow) + , mnLeftBorder(rImplementation.mnLeftBorder) + , mnRightBorder(rImplementation.mnRightBorder) + , mnTopBorder(rImplementation.mnTopBorder) + , mnBottomBorder(rImplementation.mnBottomBorder) + , maMinimalSize(rImplementation.maMinimalSize) + , maPreferredSize(rImplementation.maPreferredSize) + , maMaximalSize(rImplementation.maMaximalSize) + , mnMinimalColumnCount(rImplementation.mnMinimalColumnCount) + , mnMaximalColumnCount(rImplementation.mnMaximalColumnCount) + , mnPageCount(rImplementation.mnPageCount) + , mnColumnCount(rImplementation.mnColumnCount) + , mnRowCount(rImplementation.mnRowCount) + , mnMaxColumnCount(rImplementation.mnMaxColumnCount) + , mnMaxRowCount(rImplementation.mnMaxRowCount) + , maPageObjectSize(rImplementation.maPageObjectSize) + , mpTheme(rImplementation.mpTheme) + , maSectionStartIndices(rImplementation.maSectionStartIndices) + , maSectionRowOffsets(rImplementation.maSectionRowOffsets) { } @@ -540,30 +566,63 @@ sal_Int32 Layouter::Implementation::GetRowAtPosition ( const sal_Int32 nY = nYPosition - mnTopBorder; if (nY >= 0) { - // Vertical distance from one row to the next. - const sal_Int32 nRowOffset (maPageObjectSize.Height() + gnVerticalGap); - - // Calculate row consisting of page objects and gap below. - nRow = nY / nRowOffset; - - const sal_Int32 nDistanceIntoGap ((nY - nRow*nRowOffset) - maPageObjectSize.Height()); - // When inside the gap below then nYPosition is not over a page - // object. - if (nDistanceIntoGap > 0) + if (maSectionRowOffsets.empty()) { - sal_Int32 nResolvedRow = ResolvePositionInGap( - nDistanceIntoGap, - eGapMembership, - nRow, - gnVerticalGap); - if (!bIncludeBordersAndGaps || nResolvedRow != -1) - nRow = nResolvedRow; + // Original fast path: no section headers + const sal_Int32 nRowOffset(maPageObjectSize.Height() + gnVerticalGap); + nRow = nY / nRowOffset; + } + else + { + // With section headers, iterate rows to find the right one + sal_Int32 nRowCount = (mnPageCount + mnColumnCount - 1) / mnColumnCount; + for (sal_Int32 r = 0; r < nRowCount; ++r) + { + sal_Int32 nRowTop = r * maPageObjectSize.Height() + + std::max(r, 0) * gnVerticalGap + + GetSectionOffsetForRow(r); + sal_Int32 nRowBottom = nRowTop + maPageObjectSize.Height(); + if (nY >= nRowTop && nY < nRowBottom) + { + nRow = r; + break; + } + // Check gap area + if (nY >= nRowBottom && nY < nRowTop + maPageObjectSize.Height() + gnVerticalGap) + { + sal_Int32 nDistanceIntoGap = nY - nRowBottom; + sal_Int32 nResolvedRow + = ResolvePositionInGap(nDistanceIntoGap, eGapMembership, r, gnVerticalGap); + if (bIncludeBordersAndGaps || nResolvedRow != -1) + { + nRow = (nResolvedRow != -1) ? nResolvedRow : r; + break; + } + } + } + if (nRow == -1 && bIncludeBordersAndGaps && nRowCount > 0) + nRow = nRowCount - 1; + } + + if (!maSectionRowOffsets.empty()) + { + // Already handled gap resolution above + } + else + { + const sal_Int32 nRowOffset(maPageObjectSize.Height() + gnVerticalGap); + const sal_Int32 nDistanceIntoGap((nY - nRow * nRowOffset) - maPageObjectSize.Height()); + if (nDistanceIntoGap > 0) + { + sal_Int32 nResolvedRow + = ResolvePositionInGap(nDistanceIntoGap, eGapMembership, nRow, gnVerticalGap); + if (!bIncludeBordersAndGaps || nResolvedRow != -1) + nRow = nResolvedRow; + } } } else if (bIncludeBordersAndGaps) { - // We are in the top border area. Set nRow to the first row when - // the top border shall be considered to belong to the first row. nRow = 0; } @@ -902,14 +961,12 @@ sal_Int32 Layouter::Implementation::GetIndex ( const sal_Int32 nRow, const sal_Int32 nColumn) const { - return ::tools::Rectangle( - Point (mnLeftBorder - + nColumn * maPageObjectSize.Width() - + std::max(nColumn,0) * gnHorizontalGap, - mnTopBorder - + nRow * maPageObjectSize.Height() - + std::max(nRow,0) * gnVerticalGap), - maPageObjectSize); + return ::tools::Rectangle(Point(mnLeftBorder + nColumn * maPageObjectSize.Width() + + std::max(nColumn, 0) * gnHorizontalGap, + mnTopBorder + nRow * maPageObjectSize.Height() + + std::max(nRow, 0) * gnVerticalGap + + GetSectionOffsetForRow(nRow)), + maPageObjectSize); } ::tools::Rectangle Layouter::Implementation::AddBorderAndGap ( @@ -959,12 +1016,91 @@ sal_Int32 Layouter::Implementation::GetIndex ( nVerticalSize += (nRowCount-1) * gnVerticalGap; } + // Add extra height for section headers + sal_Int32 nTotalSectionOffset = 0; + if (!maSectionRowOffsets.empty()) + { + sal_Int32 nRowCount2 = (mnPageCount + mnColumnCount - 1) / mnColumnCount; + if (nRowCount2 > 0 && o3tl::make_unsigned(nRowCount2 - 1) < maSectionRowOffsets.size()) + nTotalSectionOffset = maSectionRowOffsets[nRowCount2 - 1]; + } + nVerticalSize += nTotalSectionOffset; + return ::tools::Rectangle ( Point(0,0), Size (nHorizontalSize, nVerticalSize) ); } +void Layouter::Implementation::SetSectionStarts(const std::vector& rSectionStartIndices) +{ + maSectionStartIndices = rSectionStartIndices; + ComputeSectionRowOffsets(); +} + +void Layouter::Implementation::ComputeSectionRowOffsets() +{ + maSectionRowOffsets.clear(); + if (mnColumnCount <= 0 || mnPageCount <= 0) + return; + + sal_Int32 nRowCount = (mnPageCount + mnColumnCount - 1) / mnColumnCount; + maSectionRowOffsets.resize(nRowCount, 0); + + // For each section start, find which row it falls on and add header height + sal_Int32 nCumulativeOffset = 0; + // Track which rows have headers + std::vector aRowHasHeader(nRowCount, false); + for (sal_Int32 nStartIdx : maSectionStartIndices) + { + if (nStartIdx < 0 || nStartIdx >= mnPageCount) + continue; + sal_Int32 nRow = nStartIdx / mnColumnCount; + if (nRow < nRowCount) + aRowHasHeader[nRow] = true; + } + + // Compute cumulative offsets + for (sal_Int32 nRow = 0; nRow < nRowCount; ++nRow) + { + if (aRowHasHeader[nRow]) + nCumulativeOffset += gnSectionHeaderHeight; + maSectionRowOffsets[nRow] = nCumulativeOffset; + } +} + +sal_Int32 Layouter::Implementation::GetSectionOffsetForRow(sal_Int32 nRow) const +{ + if (nRow < 0 || maSectionRowOffsets.empty()) + return 0; + if (o3tl::make_unsigned(nRow) >= maSectionRowOffsets.size()) + return maSectionRowOffsets.back(); + return maSectionRowOffsets[nRow]; +} + +sal_Int32 Layouter::Implementation::GetSectionIndexAtPoint(sal_Int32 nYPosition) const +{ + if (maSectionStartIndices.empty() || mnColumnCount <= 0) + return -1; + + // Use GetPageObjectBox as the single source of truth for position. + // The header is drawn immediately above the first slide of each section. + for (size_t i = 0; i < maSectionStartIndices.size(); ++i) + { + sal_Int32 nStartIdx = maSectionStartIndices[i]; + if (nStartIdx < 0 || nStartIdx >= mnPageCount) + continue; + + ::tools::Rectangle aSlideBox = GetPageObjectBox(nStartIdx); + sal_Int32 nHeaderBottom = aSlideBox.Top(); + sal_Int32 nHeaderTop = nHeaderBottom - gnSectionHeaderHeight; + + if (nYPosition >= nHeaderTop && nYPosition < nHeaderBottom) + return static_cast(i); + } + return -1; +} + void Layouter::Implementation::CalculateVerticalLogicalInsertPosition ( const Point& rModelPosition, InsertPosition& rPosition) const diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx index b26eb0746f30..0ad3d89ad6ce 100644 --- a/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx +++ b/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -75,6 +76,18 @@ PageObjectLayouter::PageObjectLayouter ( nMaximumBorderWidth), aPageNumberAreaSize); + // Position the page name right of the page number, extending to the page edge + maPageNameAreaBoundingBox = ::tools::Rectangle( + Point(maPageNumberAreaBoundingBox.Right() + gnRightPageNumberOffset, + maPageNumberAreaBoundingBox.Top()), + Point(maPageObjectBoundingBox.Right(), maPageNumberAreaBoundingBox.Bottom())); + + // Move the page preview below the custom page name to avoid any overlapping + const tools::Long nNameBottom = maPageNumberAreaBoundingBox.Bottom() + 1; + const tools::Long nNewTop = std::max(nNameBottom, maPreviewBoundingBox.Top()); + maPreviewWithNameBoundingBox = ::tools::Rectangle(Point(maPreviewBoundingBox.Left(), nNewTop), + maPreviewBoundingBox.BottomRight()); + const Size aIconSize (maTransitionEffectIcon.GetSizePixel()); maTransitionEffectBoundingBox = ::tools::Rectangle( Point( @@ -165,6 +178,19 @@ PageObjectLayouter::~PageObjectLayouter() Point aLocation(0,0); if (rpPageDescriptor) aLocation = rpPageDescriptor->GetLocation( bIgnoreLocation ); + + // Shift the preview of the page down when there is a custom name + if (ePart == Part::Preview && rpPageDescriptor && rpPageDescriptor->GetPage() + && !rpPageDescriptor->GetPage()->GetRealName().isEmpty()) + { + // Adapt coordinates to the requested coordinate system + Point aAdjustedLocation(aLocation); + if (eCoordinateSystem == WindowCoordinateSystem) + aAdjustedLocation += mpWindow->GetMapMode().GetOrigin(); + return ::tools::Rectangle(maPreviewWithNameBoundingBox.TopLeft() + aAdjustedLocation, + maPreviewWithNameBoundingBox.BottomRight() + aAdjustedLocation); + } + return GetBoundingBox(aLocation, ePart, eCoordinateSystem); } @@ -198,6 +224,9 @@ PageObjectLayouter::~PageObjectLayouter() case Part::CustomAnimationEffectIndicator: aBoundingBox = maCustomAnimationEffectBoundingBox; break; + case Part::PageName: + aBoundingBox = maPageNameAreaBoundingBox; + break; } // Adapt coordinates to the requested coordinate system. diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx index 38521334dd78..9463b083ed67 100644 --- a/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx +++ b/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx @@ -77,6 +77,7 @@ void PageObjectPainter::PaintPageObject ( PaintBackground(pPageObjectLayouter, rDevice, rpDescriptor); PaintPreview(pPageObjectLayouter, rDevice, rpDescriptor); PaintPageNumber(pPageObjectLayouter, rDevice, rpDescriptor); + PaintPageName(pPageObjectLayouter, rDevice, rpDescriptor); PaintTransitionEffect(pPageObjectLayouter, rDevice, rpDescriptor); if (rpDescriptor->GetPage()->hasAnimationNode()) PaintCustomAnimationEffect(pPageObjectLayouter, rDevice, rpDescriptor); @@ -210,6 +211,39 @@ Bitmap PageObjectPainter::GetPreviewBitmap ( } } +Color PageObjectPainter::GetPageTextColor(const model::SharedPageDescriptor& rpDescriptor) const +{ + Color aColor(mpTheme->GetColor(Theme::Color_PageNumberDefault)); + if (rpDescriptor->HasState(model::PageDescriptor::ST_MouseOver) + || rpDescriptor->HasState(model::PageDescriptor::ST_Selected)) + { + aColor = mpTheme->GetColor(Theme::Color_PageNumberHover); + } + else + { + const Color aBackgroundColor(mpTheme->GetColor(Theme::Color_Background)); + const sal_Int32 nBackgroundLuminance(aBackgroundColor.GetLuminance()); + // When the background color is black then this is interpreted as + // high contrast mode and the font color is set to white. + if (nBackgroundLuminance == 0) + aColor = mpTheme->GetColor(Theme::Color_PageNumberHighContrast); + else + { + // When the font and background luminance are too similar, switch to + // a darker (preferred) or brighter color for legibility. + const sal_Int32 nFontLuminance(aColor.GetLuminance()); + if (abs(nBackgroundLuminance - nFontLuminance) < 60) + { + if (nBackgroundLuminance > nFontLuminance - 30) + aColor = mpTheme->GetColor(Theme::Color_PageNumberBrightBackground); + else + aColor = mpTheme->GetColor(Theme::Color_PageNumberDarkBackground); + } + } + } + return aColor; +} + void PageObjectPainter::PaintPageNumber ( PageObjectLayouter *pPageObjectLayouter, OutputDevice& rDevice, @@ -220,49 +254,34 @@ void PageObjectPainter::PaintPageNumber ( PageObjectLayouter::Part::PageNumber, PageObjectLayouter::ModelCoordinateSystem)); - // Determine the color of the page number. - Color aPageNumberColor (mpTheme->GetColor(Theme::Color_PageNumberDefault)); - if (rpDescriptor->HasState(model::PageDescriptor::ST_MouseOver) || - rpDescriptor->HasState(model::PageDescriptor::ST_Selected)) - { - // Page number is painted on background for hover or selection or - // both. Each of these background colors has a predefined luminance - // which is compatible with the PageNumberHover color. - aPageNumberColor = mpTheme->GetColor(Theme::Color_PageNumberHover); - } - else - { - const Color aBackgroundColor (mpTheme->GetColor(Theme::Color_Background)); - const sal_Int32 nBackgroundLuminance (aBackgroundColor.GetLuminance()); - // When the background color is black then this is interpreted as - // high contrast mode and the font color is set to white. - if (nBackgroundLuminance == 0) - aPageNumberColor = mpTheme->GetColor(Theme::Color_PageNumberHighContrast); - else - { - // Compare luminance of default page number color and background - // color. When the two are similar then use a darker - // (preferred) or brighter font color. - const sal_Int32 nFontLuminance (aPageNumberColor.GetLuminance()); - if (abs(nBackgroundLuminance - nFontLuminance) < 60) - { - if (nBackgroundLuminance > nFontLuminance-30) - aPageNumberColor = mpTheme->GetColor(Theme::Color_PageNumberBrightBackground); - else - aPageNumberColor = mpTheme->GetColor(Theme::Color_PageNumberDarkBackground); - } - } - } - - // Paint the page number. OSL_ASSERT(rpDescriptor->GetPage()!=nullptr); const sal_Int32 nPageNumber ((rpDescriptor->GetPage()->GetPageNum() - 1) / 2 + 1); const OUString sPageNumber(OUString::number(nPageNumber)); rDevice.SetFont(*mpPageNumberFont); - rDevice.SetTextColor(aPageNumberColor); + rDevice.SetTextColor(GetPageTextColor(rpDescriptor)); rDevice.DrawText(aBox, sPageNumber, DrawTextFlags::Right | DrawTextFlags::VCenter); } +void PageObjectPainter::PaintPageName ( + PageObjectLayouter *pPageObjectLayouter, + OutputDevice& rDevice, + const model::SharedPageDescriptor& rpDescriptor) const +{ + const SdPage* pPage = rpDescriptor->GetPage(); + if (!pPage || pPage->GetRealName().isEmpty()) + return; + + const ::tools::Rectangle aBox( + pPageObjectLayouter->GetBoundingBox(rpDescriptor, PageObjectLayouter::Part::PageName, + PageObjectLayouter::ModelCoordinateSystem)); + + rDevice.SetFont(*mpPageNumberFont); + rDevice.SetTextColor(GetPageTextColor(rpDescriptor)); + rDevice.DrawText(aBox, pPage->GetRealName(), + DrawTextFlags::Left | DrawTextFlags::VCenter | DrawTextFlags::Clip + | DrawTextFlags::EndEllipsis); +} + void PageObjectPainter::PaintTransitionEffect ( PageObjectLayouter *pPageObjectLayouter, OutputDevice& rDevice, diff --git a/sd/source/ui/slidesorter/view/SlsSectionHeaderPainter.cxx b/sd/source/ui/slidesorter/view/SlsSectionHeaderPainter.cxx new file mode 100644 index 000000000000..6e152dece495 --- /dev/null +++ b/sd/source/ui/slidesorter/view/SlsSectionHeaderPainter.cxx @@ -0,0 +1,116 @@ +/* -*- 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 "SlsSectionHeaderPainter.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sd::slidesorter::view +{ +namespace +{ +constexpr sal_Int32 gnTextLeftPadding = 4; +constexpr sal_Int32 gnTextTopPadding = 2; +constexpr sal_Int32 gnFontSizePadding = 6; +constexpr sal_uInt8 gnLuminanceDecrease = 15; +} + +SectionHeaderPainter::SectionHeaderPainter(SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter) +{ +} + +SectionHeaderPainter::~SectionHeaderPainter() {} + +void SectionHeaderPainter::SetLayerInvalidator(std::unique_ptr pInvalidator) +{ + mpLayerInvalidator = std::move(pInvalidator); +} + +void SectionHeaderPainter::EnsureStyle(const OutputDevice& rDevice) +{ + if (mbStyleValid) + return; + + const StyleSettings& rStyleSettings = rDevice.GetSettings().GetStyleSettings(); + + maBackgroundColor = rStyleSettings.GetDialogColor(); + maBackgroundColor.DecreaseLuminance(gnLuminanceDecrease); + maTextColor = rStyleSettings.GetButtonTextColor(); + + const sal_Int32 nHeaderHeight = Layouter::GetSectionHeaderHeight(); + maFont = rStyleSettings.GetAppFont(); + maFont.SetFontSize(Size(0, nHeaderHeight - gnFontSizePadding)); + maFont.SetWeight(WEIGHT_BOLD); + + mbStyleValid = true; +} + +void SectionHeaderPainter::Paint(OutputDevice& rDevice, const ::tools::Rectangle& rRepaintArea) +{ + SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument(); + if (!pDocument) + return; + + sd::SlideSectionManager& rSectionMgr = pDocument->GetSectionManager(); + const sal_Int32 nSectionCount = rSectionMgr.GetSectionCount(); + if (nSectionCount == 0) + return; + + Layouter& rLayouter = mrSlideSorter.GetView().GetLayouter(); + if (rLayouter.GetColumnCount() <= 0) + return; + + const sal_Int32 nHeaderHeight = Layouter::GetSectionHeaderHeight(); + const sal_Int32 nPageCount = mrSlideSorter.GetModel().GetPageCount(); + + EnsureStyle(rDevice); + + rDevice.Push(vcl::PushFlags::FONT | vcl::PushFlags::TEXTCOLOR | vcl::PushFlags::FILLCOLOR + | vcl::PushFlags::LINECOLOR); + + rDevice.SetFont(maFont); + rDevice.SetTextColor(maTextColor); + rDevice.SetFillColor(maBackgroundColor); + rDevice.SetLineColor(); + + for (sal_Int32 i = 0; i < nSectionCount; ++i) + { + const sd::SlideSection& rSection = rSectionMgr.GetSection(i); + const sal_Int32 nStartIndex = rSection.mnStartIndex; + if (nStartIndex < 0 || nStartIndex >= nPageCount) + continue; + + const ::tools::Rectangle aSlideBox = rLayouter.GetPageObjectBox(nStartIndex, false); + + const ::tools::Rectangle aHeaderBox( + Point(rRepaintArea.Left(), aSlideBox.Top() - nHeaderHeight), + Size(rRepaintArea.GetWidth(), nHeaderHeight)); + + if (!aHeaderBox.Overlaps(rRepaintArea)) + continue; + + rDevice.DrawRect(aHeaderBox); + rDevice.DrawText( + Point(aHeaderBox.Left() + gnTextLeftPadding, aHeaderBox.Top() + gnTextTopPadding), + rSection.maName); + } + + rDevice.Pop(); +} + +} // end of namespace sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/view/SlsSectionHeaderPainter.hxx b/sd/source/ui/slidesorter/view/SlsSectionHeaderPainter.hxx new file mode 100644 index 000000000000..517fb461238b --- /dev/null +++ b/sd/source/ui/slidesorter/view/SlsSectionHeaderPainter.hxx @@ -0,0 +1,56 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace sd::slidesorter +{ +class SlideSorter; +} + +namespace sd::slidesorter::view +{ +/** Paints section name headers above each section's first slide row + in the slide sorter panel. + + Style (font, colors) is cached and rebuilt only when system + settings change, so Paint() stays lightweight. +*/ +class SectionHeaderPainter final : public ILayerPainter, + public std::enable_shared_from_this +{ +public: + explicit SectionHeaderPainter(SlideSorter& rSlideSorter); + virtual ~SectionHeaderPainter() override; + + virtual void SetLayerInvalidator(std::unique_ptr pInvalidator) override; + virtual void Paint(OutputDevice& rDevice, const ::tools::Rectangle& rRepaintArea) override; + +private: + SlideSorter& mrSlideSorter; + std::unique_ptr mpLayerInvalidator; + + // Cached style — rebuilt by HandleDataChanged() or on first Paint() + bool mbStyleValid = false; + vcl::Font maFont; + Color maBackgroundColor; + Color maTextColor; + + void EnsureStyle(const OutputDevice& rDevice); +}; + +} // end of namespace sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/tools/EventMultiplexer.cxx b/sd/source/ui/tools/EventMultiplexer.cxx index f0e7fc8ddfe0..c6fdeb43eba7 100644 --- a/sd/source/ui/tools/EventMultiplexer.cxx +++ b/sd/source/ui/tools/EventMultiplexer.cxx @@ -40,7 +40,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; @@ -496,7 +495,7 @@ void EventMultiplexer::Implementation::notifyConfigurationChange ( CallListeners (EventMultiplexerEventId::ViewAdded); if (rEvent.ResourceId->isBoundToURL( - FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) + FrameworkHelper::msCenterPaneURL, sd::framework::AnchorBindingMode::DIRECT)) { CallListeners (EventMultiplexerEventId::MainViewAdded); } @@ -521,13 +520,12 @@ void EventMultiplexer::Implementation::notifyConfigurationChange ( if (rEvent.ResourceId->getResourceURL().match(FrameworkHelper::msViewURLPrefix)) { if (rEvent.ResourceId->isBoundToURL( - FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) + FrameworkHelper::msCenterPaneURL, sd::framework::AnchorBindingMode::DIRECT)) { CallListeners (EventMultiplexerEventId::MainViewRemoved); } - // Remove selection change listener from slide sorter. Add - // selection change listener at slide sorter. + // Remove selection change listener from slide sorter. if (rEvent.ResourceId->getResourceURL() == FrameworkHelper::msSlideSorterURL) { auto pView = dynamic_cast(rEvent.ResourceObject.get()); @@ -549,7 +547,6 @@ void EventMultiplexer::Implementation::notifyConfigurationChange ( default: break; } - } void EventMultiplexer::Implementation::disposing(std::unique_lock& rGuard) diff --git a/sd/source/ui/tools/SlideshowLayerRenderer.cxx b/sd/source/ui/tools/SlideshowLayerRenderer.cxx index 7644e956b76f..feeab588a401 100644 --- a/sd/source/ui/tools/SlideshowLayerRenderer.cxx +++ b/sd/source/ui/tools/SlideshowLayerRenderer.cxx @@ -229,10 +229,18 @@ void changePolyPolys( if (!bRenderObject) rPrimitivesToUnhide.push_back(pBasePrimitive); } + else if (pBasePrimitive->getPrimitive2DID() == PRIMITIVE2D_ID_SDRCUSTOMSHAPEPRIMITIVE2D + || pBasePrimitive->getPrimitive2DID() == PRIMITIVE2D_ID_SDRRECTANGLEPRIMITIVE2D) + { + drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer; + pBasePrimitive->get2DDecomposition(aPrimitiveContainer, + drawinglayer::geometry::ViewInformation2D()); + changePolyPolys(aPrimitiveContainer, bRenderObject, rPrimitivesToUnhide); + } } } -/// Searches for rectangle primitive and changes if the background should be rendered +/// Searches for shape primitives and changes if the background should be rendered void changeBackground( drawinglayer::primitive2d::Primitive2DContainer const& rContainer, bool bRenderObject, std::vector& rPrimitivesToUnhide) @@ -240,13 +248,10 @@ void changeBackground( for (const drawinglayer::primitive2d::Primitive2DReference& rBasePrimitive : rContainer) { drawinglayer::primitive2d::BasePrimitive2D* pBasePrimitive = rBasePrimitive.get(); - if (pBasePrimitive->getPrimitive2DID() == PRIMITIVE2D_ID_SDRRECTANGLEPRIMITIVE2D) - { - drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer; - pBasePrimitive->get2DDecomposition(aPrimitiveContainer, - drawinglayer::geometry::ViewInformation2D()); - changePolyPolys(aPrimitiveContainer, bRenderObject, rPrimitivesToUnhide); - } + drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer; + pBasePrimitive->get2DDecomposition(aPrimitiveContainer, + drawinglayer::geometry::ViewInformation2D()); + changePolyPolys(aPrimitiveContainer, bRenderObject, rPrimitivesToUnhide); } } @@ -464,6 +469,10 @@ public: || (pObject->IsEmptyPresObj() && !(pObject->HasFillStyle() || pObject->HasLineStyle()))) return; + // Don't render annotation markers in the slideshow + if (pObject->GetObjIdentifier() == SdrObjKind::Annotation) + return; + SdrPage* pPage = pObject->getSdrPageFromSdrObject(); // Does the object have a page diff --git a/sd/source/ui/tools/TimerBasedTaskExecution.cxx b/sd/source/ui/tools/TimerBasedTaskExecution.cxx index 012c50ee9623..4d09146d64f0 100644 --- a/sd/source/ui/tools/TimerBasedTaskExecution.cxx +++ b/sd/source/ui/tools/TimerBasedTaskExecution.cxx @@ -74,9 +74,9 @@ void TimerBasedTaskExecution::ReleaseTask ( catch (const std::bad_weak_ptr&) { // When a bad_weak_ptr has been thrown then the object pointed - // to by rpTask has been released right after we checked that it + // to by rpExecution has been released right after we checked that it // still existed. Too bad, but that means, that we have nothing - // more do. + // more to do. } } diff --git a/sd/source/ui/unoidl/DrawController.cxx b/sd/source/ui/unoidl/DrawController.cxx index 483dc9afe24a..a1c8d0f4cdcd 100644 --- a/sd/source/ui/unoidl/DrawController.cxx +++ b/sd/source/ui/unoidl/DrawController.cxx @@ -53,7 +53,6 @@ using namespace ::cppu; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using vcl::EnumContext; namespace sd { @@ -584,7 +583,7 @@ Any SAL_CALL DrawController::getSlideSorterSelection() // * traverse Impress resources to find slide preview pane, grab selection from there const std::vector> aResIds( mxConfigurationController->getCurrentConfiguration()->getResources( - {}, u"", drawing::framework::AnchorBindingMode_INDIRECT)); + {}, u"", sd::framework::AnchorBindingMode::INDIRECT)); for (const rtl::Reference& rResId : aResIds) { diff --git a/sd/source/ui/unoidl/UnoDocumentSettings.cxx b/sd/source/ui/unoidl/UnoDocumentSettings.cxx index ff8cdd930e1a..9e35ee7d3e04 100644 --- a/sd/source/ui/unoidl/UnoDocumentSettings.cxx +++ b/sd/source/ui/unoidl/UnoDocumentSettings.cxx @@ -779,10 +779,10 @@ DocumentSettings::_setPropertyValues(const PropertyMapEntry** ppEntries, } else { - pItemSet = std::make_unique(SfxItemSet::makeFixedSfxItemSet >(pDoc->GetPool()); + ATTR_OPTIONS_PRINT, ATTR_OPTIONS_PRINT>(pDoc->GetPool())); } pPrinter = SfxPrinter::Create ( aStream, std::move(pItemSet) ); diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index ca01769bd077..0bce2d465715 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -133,6 +133,7 @@ #include #include +#include #include #include #include @@ -1795,6 +1796,8 @@ const sal_uInt16 WID_MODEL_FONTS = 13; const sal_uInt16 WID_MODEL_INTEROPGRABBAG = 14; const sal_uInt16 WID_MODEL_THEME = 15; const sal_uInt16 WID_MODEL_ALLOWLINKUPDATE = 16; +const sal_uInt16 WID_MODEL_SLIDESECTIONS = 17; +const sal_uInt16 WID_MODEL_ANIMATIONSOUNDLINK = 18; static const SvxItemPropertySet* ImplGetDrawModelPropertySet() { @@ -1816,6 +1819,8 @@ static const SvxItemPropertySet* ImplGetDrawModelPropertySet() { sUNO_Prop_AllowLinkUpdate, WID_MODEL_ALLOWLINKUPDATE, ::cppu::UnoType::get(), beans::PropertyAttribute::READONLY, 0}, { u"Fonts"_ustr, WID_MODEL_FONTS, cppu::UnoType>::get(), beans::PropertyAttribute::READONLY, 0}, { sUNO_Prop_InteropGrabBag, WID_MODEL_INTEROPGRABBAG, cppu::UnoType>::get(), 0, 0}, + { u"SlideSections"_ustr, WID_MODEL_SLIDESECTIONS, cppu::UnoType>::get(), 0, 0}, + { u"HasExternalAnimationSoundLink"_ustr, WID_MODEL_ANIMATIONSOUNDLINK, cppu::UnoType::get(), 0, 0}, { sUNO_Prop_Theme, WID_MODEL_THEME, cppu::UnoType::get(), 0, 0}, }; static SvxItemPropertySet aDrawModelPropertySet_Impl( aDrawModelPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() ); @@ -2879,6 +2884,20 @@ void SAL_CALL SdXImpressDocument::setPropertyValue( const OUString& aPropertyNam case WID_MODEL_INTEROPGRABBAG: setGrabBagItem(aValue); break; + case WID_MODEL_SLIDESECTIONS: + { + uno::Sequence aSections; + if (aValue >>= aSections) + mpDoc->GetSectionManager().SetSectionsFromPropertyValues(aSections); + break; + } + case WID_MODEL_ANIMATIONSOUNDLINK: + { + bool bHasLink = false; + if (aValue >>= bHasLink) + mpDoc->SetMaybeHasAnimationSoundLinks(bHasLink); + break; + } case WID_MODEL_THEME: getSdrModelFromUnoModel().setTheme(model::Theme::FromAny(aValue)); break; @@ -3008,6 +3027,12 @@ uno::Any SAL_CALL SdXImpressDocument::getPropertyValue( const OUString& Property case WID_MODEL_INTEROPGRABBAG: getGrabBagItem(aAny); break; + case WID_MODEL_SLIDESECTIONS: + aAny <<= mpDoc->GetSectionManager().GetSectionsAsPropertyValues(); + break; + case WID_MODEL_ANIMATIONSOUNDLINK: + aAny <<= mpDoc->MaybeHasAnimationSoundLinks(); + break; case WID_MODEL_THEME: if (auto const& pTheme = getSdrModelFromUnoModel().getTheme()) pTheme->ToAny(aAny); @@ -4189,7 +4214,18 @@ Size SdXImpressDocument::getPartSize(int part) return Size(0,0); const sal_uInt16 nSlideIndex = static_cast(part); - SdPage* pPage = mpDoc ? mpDoc->GetSdPage(nSlideIndex, PageKind::Standard) : nullptr; + SdPage* pPage = nullptr; + if (mpDoc) + { + if (isMasterViewMode()) + pPage = mpDoc->GetMasterSdPage(nSlideIndex, PageKind::Standard); + else + { + DrawViewShell* pViewSh = GetViewShell(); + PageKind ePageKind = pViewSh ? pViewSh->GetPageKind() : PageKind::Standard; + pPage = mpDoc->GetSdPage(nSlideIndex, ePageKind); + } + } if (pPage == nullptr) return Size(0,0); @@ -4239,6 +4275,12 @@ void SdXImpressDocument::getPostIts(::tools::JsonWriter& rJsonWriter) aRectangle = o3tl::toTwips(aRectangle, o3tl::Length::mm100); OString sRectangle = aRectangle.toString(); rJsonWriter.put("rectangle", sRectangle.getStr()); + if (xAnnotation->IsThreaded()) + { + rJsonWriter.put("threaded", "true"); + rJsonWriter.put("resolved", xAnnotation->IsResolved() ? "true" : "false"); + rJsonWriter.put("parentId", xAnnotation->GetParentId()); + } } } } @@ -4679,6 +4721,32 @@ OString SdXImpressDocument::getPresentationInfo(bool bAllyState) const aJsonWriter.put("loopAndRepeatDuration", nPauseTimeout); } + // Section data for COOL slide panel + { + sd::SlideSectionManager& rSectionMgr = mpDoc->GetSectionManager(); + sal_Int32 nSectionCount = rSectionMgr.GetSectionCount(); + if (nSectionCount > 0) + { + sal_uInt16 nPageCount = mpDoc->GetSdPageCount(PageKind::Standard); + auto aSectionsArray = aJsonWriter.startArray("sections"); + for (sal_Int32 i = 0; i < nSectionCount; ++i) + { + const sd::SlideSection& rSection = rSectionMgr.GetSection(i); + sal_Int32 nSectionSlideCount + = (i + 1 < nSectionCount) + ? rSectionMgr.GetSection(i + 1).mnStartIndex - rSection.mnStartIndex + : nPageCount - rSection.mnStartIndex; + + auto aSectionNode = aJsonWriter.startStruct(); + aJsonWriter.put("name", rSection.maName); + if (!rSection.maId.isEmpty()) + aJsonWriter.put("id", rSection.maId); + aJsonWriter.put("startIndex", rSection.mnStartIndex); + aJsonWriter.put("slideCount", nSectionSlideCount); + } + } + } + auto aSlideList = aJsonWriter.startArray("slides"); sal_Int32 nSlideCount = xDrawPages->getCount(); for (sal_Int32 i = 0; i < nSlideCount; ++i) diff --git a/sd/source/ui/unoidl/unomodule.cxx b/sd/source/ui/unoidl/unomodule.cxx index 743ccd62b097..cd9f09e07e12 100644 --- a/sd/source/ui/unoidl/unomodule.cxx +++ b/sd/source/ui/unoidl/unomodule.cxx @@ -33,9 +33,9 @@ using namespace ::com::sun::star; // XNotifyingDispatch void SAL_CALL SdUnoModule::dispatchWithNotification( const util::URL& aURL, const uno::Sequence< beans::PropertyValue >& aArgs, const uno::Reference< frame::XDispatchResultListener >& xListener ) { - // there is no guarantee, that we are holded alive during this method! - // May the outside dispatch container will be updated by a CONTEXT_CHANGED - // asynchronous ... + // there is no guarantee that we are kept alive during this method! + // Maybe the outside dispatch container will be updated by a CONTEXT_CHANGED + // asynchronously ... uno::Reference< uno::XInterface > xThis(static_cast< frame::XNotifyingDispatch* >(this)); SolarMutexGuard aGuard; diff --git a/sd/source/ui/unoidl/unoobj.cxx b/sd/source/ui/unoidl/unoobj.cxx index 5da25f04ad51..bf211adba718 100644 --- a/sd/source/ui/unoidl/unoobj.cxx +++ b/sd/source/ui/unoidl/unoobj.cxx @@ -105,6 +105,7 @@ using ::com::sun::star::drawing::XShape; #define WID_LEGACYFRAGMENT 25 #define WID_CUSTOMPROMPT 26 +#define WID_PLACEHOLDERTYPE 27 #define IMPRESS_MAP_ENTRIES \ { u"" UNO_NAME_OBJ_LEGACYFRAGMENT ""_ustr,WID_LEGACYFRAGMENT, cppu::UnoType::get(), 0, 0},\ @@ -131,6 +132,7 @@ using ::com::sun::star::drawing::XShape; { u"NavigationOrder"_ustr, WID_NAVORDER, cppu::UnoType::get(), 0, 0},\ { u"PlaceholderText"_ustr, WID_PLACEHOLDERTEXT, cppu::UnoType::get(), 0, 0},\ { u"" UNO_NAME_OBJ_CUSTOMPROMPT ""_ustr, WID_CUSTOMPROMPT, cppu::UnoType::get(), 0, 0},\ + { u"PlaceholderShapeType"_ustr, WID_PLACEHOLDERTYPE, cppu::UnoType::get(), css::beans::PropertyAttribute::READONLY, 0},\ static std::span lcl_GetImpress_SdXShapePropertyGraphicMap_Impl() { @@ -511,7 +513,7 @@ void SAL_CALL SdXShape::setPropertyValue( const OUString& aPropertyName, const c if(!(aValue >>= aString)) throw lang::IllegalArgumentException(); SdAnimationInfo* pInfo = GetAnimationInfo(true); - pInfo->maSoundFile = aString; + pInfo->maSoundLink = SdSoundLink(aString); EffectMigration::UpdateSoundEffect( mpShape, pInfo ); break; } @@ -686,6 +688,9 @@ css::uno::Any SAL_CALL SdXShape::getPropertyValue( const OUString& PropertyName case WID_CUSTOMPROMPT: aRet <<= GetCustomPromptText(); break; + case WID_PLACEHOLDERTYPE: + aRet <<= GetPlaceholderShapeType(); + break; case WID_MASTERDEPEND: aRet <<= IsMasterDepend(); break; @@ -944,9 +949,16 @@ void SdXShape::SetEmptyPresObj(bool bEmpty) if( pPage == nullptr ) break; - OutlinerParaObject* pOutlinerParaObject = pObj->GetOutlinerParaObject(); - pOutliner->SetText( *pOutlinerParaObject ); - const bool bVertical = pOutliner->IsVertical(); + // There may be no text to take the style from: a graphic or OLE presentation object + // never holds any, and emptying an object removes what it had. Which way the prompt + // runs is then the object's own answer. + auto pTextObj = DynCastSdrTextObj( pObj ); + bool bVertical = pTextObj && pTextObj->IsVerticalWriting(); + if (OutlinerParaObject* pOutlinerParaObject = pObj->GetOutlinerParaObject()) + { + pOutliner->SetText( *pOutlinerParaObject ); + bVertical = pOutliner->IsVertical(); + } pOutliner->Clear(); pOutliner->SetVertical( bVertical ); @@ -983,15 +995,21 @@ void SdXShape::SetCustomPromptText(const OUString& aVal) if (pObj == nullptr) return; - if (!pObj->getSdrPageFromSdrObject()->IsMasterPage()) - { - if (pObj->getSdrPageFromSdrObject()->RestoreDefaultText(pObj, aVal)) - pObj->SetCustomPromptText(aVal); - } - else - { + // A slide layout is imported as a master page, and a layout is where an authored prompt lives, + // so the shown text has to follow the property there too - not just on a slide. + const bool bTextSet = pObj->getSdrPageFromSdrObject()->RestoreDefaultText(pObj, aVal); + if (bTextSet || pObj->getSdrPageFromSdrObject()->IsMasterPage()) pObj->SetCustomPromptText(aVal); - } +} + +OUString SdXShape::GetPlaceholderShapeType() const +{ + SdrObject* pObj = mpShape->GetSdrObject(); + if (pObj == nullptr) + return OUString(); + + SdPage* pPage = dynamic_cast(pObj->getSdrPageFromSdrObject()); + return pPage ? GetPresObjShapeType(pPage->GetPresObjKind(pObj)) : OUString(); } bool SdXShape::IsMasterDepend() const noexcept diff --git a/sd/source/ui/unoidl/unoobj.hxx b/sd/source/ui/unoidl/unoobj.hxx index 574a31500dec..ca1d4db4d14c 100644 --- a/sd/source/ui/unoidl/unoobj.hxx +++ b/sd/source/ui/unoidl/unoobj.hxx @@ -50,7 +50,7 @@ private: /// @throws css::beans::UnknownPropertyException css::uno::Any GetStyleSheet() const; - // Intern + // Internal /// @throws std::exception SdAnimationInfo* GetAnimationInfo( bool bCreate = false ) const; /// @throws std::exception @@ -62,6 +62,8 @@ private: OUString GetCustomPromptText() const; void SetCustomPromptText(const OUString& aVal); + OUString GetPlaceholderShapeType() const; + bool IsMasterDepend() const noexcept; void SetMasterDepend( bool bDepend ) noexcept; @@ -82,12 +84,12 @@ public: // XServiceInfo virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; - //XPropertySet + // XPropertySet virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override; - //XPropertyState + // XPropertyState virtual css::beans::PropertyState SAL_CALL getPropertyState( const OUString& PropertyName ) override; virtual void SAL_CALL setPropertyToDefault( const OUString& PropertyName ) override; virtual css::uno::Any SAL_CALL getPropertyDefault( const OUString& aPropertyName ) override; diff --git a/sd/source/ui/unoidl/unopage.cxx b/sd/source/ui/unoidl/unopage.cxx index 56f3da3e8157..33ab1e8d0806 100644 --- a/sd/source/ui/unoidl/unopage.cxx +++ b/sd/source/ui/unoidl/unopage.cxx @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -94,7 +96,7 @@ using namespace ::com::sun::star::office; namespace { -// this are the ids for page properties +// these are the ids for page properties enum WID_PAGE { WID_PAGE_LEFT, WID_PAGE_RIGHT, WID_PAGE_TOP, WID_PAGE_BOTTOM, WID_PAGE_WIDTH, @@ -492,7 +494,7 @@ rtl::Reference SdGenericDrawPage::CreateSdrObject_( const Reference< ::tools::Rectangle aRect( eObjKind == PresObjKind::Title ? GetPage()->GetTitleRect() : GetPage()->GetLayoutRect() ); - // OOXML placeholder with "TextAutoGrowHeight" use the height set on the slide + // OOXML placeholder with "TextAutoGrowHeight" uses the height set on the slide sal_Int32 nHeight = xShape->getSize().Height; if (nHeight != 0) aRect.setHeight(nHeight); @@ -731,13 +733,13 @@ void SAL_CALL SdGenericDrawPage::setPropertyValue( const OUString& aPropertyName case WID_PAGE_SOUNDFILE : { OUString aURL; - if( aValue >>= aURL ) + css::uno::Reference xSound; + if( aValue >>= xSound ) { - GetPage()->SetSoundFile( aURL ); - GetPage()->SetSound( !aURL.isEmpty() ); - break; + if( xSound.is() ) + aURL = xSound->getURL(); } - else + else if( !(aValue >>= aURL) ) { bool bStopSound = false; if( aValue >>= bStopSound ) @@ -745,9 +747,12 @@ void SAL_CALL SdGenericDrawPage::setPropertyValue( const OUString& aPropertyName GetPage()->SetStopSound( bStopSound ); break; } + throw lang::IllegalArgumentException(); } - throw lang::IllegalArgumentException(); + GetPage()->SetSoundFile( aURL ); + GetPage()->SetSound( !aURL.isEmpty() ); + break; } case WID_LOOP_SOUND: { @@ -1007,8 +1012,11 @@ void SAL_CALL SdGenericDrawPage::setPropertyValue( const OUString& aPropertyName if (pPage->TRG_HasMasterPage()) pMasterPage = &pPage->TRG_GetMasterPage(); } - sd::ThemeColorChanger aChanger(pMasterPage, GetModel()->GetDocShell()); - aChanger.apply(pTheme->getColorSet()); + if (pMasterPage) + { + sd::ThemeColorChanger aChanger(pMasterPage, GetModel()->GetDocShell()); + aChanger.apply(pTheme->getColorSet()); + } } break; @@ -1199,13 +1207,14 @@ Any SAL_CALL SdGenericDrawPage::getPropertyValue( const OUString& PropertyName ) { aAny <<= true; } - else + else if( GetPage()->IsSoundOn() && !GetPage()->GetSoundFile().isEmpty() ) { - OUString aURL; - if( GetPage()->IsSoundOn() ) - aURL = GetPage()->GetSoundFile(); - aAny <<= aURL; + const SdSoundLink& rSound = GetPage()->GetSoundLink(); + aAny <<= css::uno::Reference( + new xmloff::SoundReference(rSound.getURL(), rSound.isAllowed())); } + else + aAny <<= OUString(); break; } case WID_LOOP_SOUND: @@ -1410,6 +1419,76 @@ void SAL_CALL SdGenericDrawPage::firePropertiesChangeEvent( const Sequence< OUSt { } +OUString GetPresObjShapeType(PresObjKind eKind) +{ + if (eKind == PresObjKind::NONE) + return OUString(); + + OUString aShapeType(u"com.sun.star.presentation."_ustr); + + switch( eKind ) + { + case PresObjKind::Title: + aShapeType += "TitleTextShape"; + break; + case PresObjKind::Outline: + aShapeType += "OutlinerShape"; + break; + case PresObjKind::Text: + aShapeType += "SubtitleShape"; + break; + case PresObjKind::Graphic: + aShapeType += "GraphicObjectShape"; + break; + case PresObjKind::Object: + aShapeType += "OLE2Shape"; + break; + case PresObjKind::Chart: + aShapeType += "ChartShape"; + break; + case PresObjKind::OrgChart: + aShapeType += "OrgChartShape"; + break; + case PresObjKind::Calc: + aShapeType += "CalcShape"; + break; + case PresObjKind::Table: + aShapeType += "TableShape"; + break; + case PresObjKind::Media: + aShapeType += "MediaShape"; + break; + case PresObjKind::Page: + aShapeType += "PageShape"; + break; + case PresObjKind::Handout: + aShapeType += "HandoutShape"; + break; + case PresObjKind::PagePreview: + aShapeType += "PageShape"; + break; + case PresObjKind::Notes: + aShapeType += "NotesShape"; + break; + case PresObjKind::Footer: + aShapeType += "FooterShape"; + break; + case PresObjKind::Header: + aShapeType += "HeaderShape"; + break; + case PresObjKind::SlideNumber: + aShapeType += "SlideNumberShape"; + break; + case PresObjKind::DateTime: + aShapeType += "DateTimeShape"; + break; + case PresObjKind::NONE: + break; + } + + return aShapeType; +} + Reference< drawing::XShape > SdGenericDrawPage::CreateShape(SdrObject *pObj) const { DBG_ASSERT( GetPage(), "SdGenericDrawPage::CreateShape(), can't create shape for disposed page!" ); @@ -1458,73 +1537,11 @@ Reference< drawing::XShape > SdGenericDrawPage::CreateShape(SdrObject *pObj) co if( eKind != PresObjKind::NONE ) { - OUString aShapeType(u"com.sun.star.presentation."_ustr); - - switch( eKind ) - { - case PresObjKind::Title: - aShapeType += "TitleTextShape"; - break; - case PresObjKind::Outline: - aShapeType += "OutlinerShape"; - break; - case PresObjKind::Text: - aShapeType += "SubtitleShape"; - break; - case PresObjKind::Graphic: - aShapeType += "GraphicObjectShape"; - break; - case PresObjKind::Object: - aShapeType += "OLE2Shape"; - break; - case PresObjKind::Chart: - aShapeType += "ChartShape"; - break; - case PresObjKind::OrgChart: - aShapeType += "OrgChartShape"; - break; - case PresObjKind::Calc: - aShapeType += "CalcShape"; - break; - case PresObjKind::Table: - aShapeType += "TableShape"; - break; - case PresObjKind::Media: - aShapeType += "MediaShape"; - break; - case PresObjKind::Page: - aShapeType += "PageShape"; - break; - case PresObjKind::Handout: - aShapeType += "HandoutShape"; - break; - case PresObjKind::PagePreview: - aShapeType += "PageShape"; - break; - case PresObjKind::Notes: - aShapeType += "NotesShape"; - break; - case PresObjKind::Footer: - aShapeType += "FooterShape"; - break; - case PresObjKind::Header: - aShapeType += "HeaderShape"; - break; - case PresObjKind::SlideNumber: - aShapeType += "SlideNumberShape"; - break; - case PresObjKind::DateTime: - aShapeType += "DateTimeShape"; - break; - case PresObjKind::NONE: - break; - } - if( !pShape ) pShape = comphelper::getFromUnoTunnel( xShape ); if( pShape ) - pShape->SetShapeType( aShapeType ); + pShape->SetShapeType( GetPresObjShapeType( eKind ) ); } SvxShape *pSdShape = comphelper::getFromUnoTunnel(xShape); @@ -2394,7 +2411,9 @@ void SAL_CALL SdDrawPage::setMasterPage( const Reference< drawing::XDrawPage >& static_cast(SvxDrawPage::mpPage)->SetLayoutName( pSdPage->GetLayoutName() ); // set notes master also - SdPage* pNotesPage = GetModel()->GetDoc()->GetSdPage( (SvxDrawPage::mpPage->GetPageNum()-1)>>1, PageKind::Notes ); + SdPage* pNotesPage = static_cast( + SvxDrawPage::mpPage->getSdrModelFromSdrPage().GetPage( + SvxDrawPage::mpPage->GetPageNum() + 1)); pNotesPage->TRG_ClearMasterPage(); sal_uInt16 nNum = SvxDrawPage::mpPage->TRG_GetMasterPage().GetPageNum() + 1; diff --git a/sd/source/ui/unoidl/unopback.cxx b/sd/source/ui/unoidl/unopback.cxx index 769582e82347..2091312ebd98 100644 --- a/sd/source/ui/unoidl/unopback.cxx +++ b/sd/source/ui/unoidl/unopback.cxx @@ -54,7 +54,7 @@ SdUnoPageBackground::SdUnoPageBackground( if( pDoc ) { StartListening( *pDoc ); - mpSet = std::make_unique>( pDoc->GetPool() ); + mpSet = std::make_unique(SfxItemSet::makeFixedSfxItemSet( pDoc->GetPool() )); if( pSet ) mpSet->Put(*pSet); @@ -93,7 +93,7 @@ void SdUnoPageBackground::fillItemSet( SdDrawDocument* pDoc, SfxItemSet& rSet ) StartListening( *pDoc ); mpDoc = pDoc; - mpSet = std::make_unique>( *rSet.GetPool() ); + mpSet = std::make_unique(SfxItemSet::makeFixedSfxItemSet( *rSet.GetPool() )); if( maUsrAnys.AreThereOwnUsrAnys() ) { diff --git a/sd/source/ui/view/DocumentRenderer.cxx b/sd/source/ui/view/DocumentRenderer.cxx index c0dcee33dfa8..244fcb94fa3e 100644 --- a/sd/source/ui/view/DocumentRenderer.cxx +++ b/sd/source/ui/view/DocumentRenderer.cxx @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include diff --git a/sd/source/ui/view/GraphicViewShellBase.cxx b/sd/source/ui/view/GraphicViewShellBase.cxx index 72df33e98f2e..9d70b9a38376 100644 --- a/sd/source/ui/view/GraphicViewShellBase.cxx +++ b/sd/source/ui/view/GraphicViewShellBase.cxx @@ -34,7 +34,7 @@ namespace sd // We have to expand the SFX_IMPL_VIEWFACTORY macro to call LateInit() after a // new GraphicViewShellBase object has been constructed. -SfxViewFactory* GraphicViewShellBase::s_pFactory; +std::unique_ptr GraphicViewShellBase::s_pFactory; SfxViewShell* GraphicViewShellBase::CreateInstance(SfxViewFrame& rFrame, SfxViewShell* pOldView) { GraphicViewShellBase* pBase = new GraphicViewShellBase(rFrame, pOldView); @@ -43,7 +43,7 @@ SfxViewShell* GraphicViewShellBase::CreateInstance(SfxViewFrame& rFrame, SfxView } void GraphicViewShellBase::RegisterFactory(SfxInterfaceId nPrio) { - s_pFactory = new SfxViewFactory(&CreateInstance, nPrio, "Default"); + s_pFactory = std::make_unique(&CreateInstance, nPrio, "Default"); InitFactory(); } void GraphicViewShellBase::InitFactory() { SFX_VIEW_REGISTRATION(GraphicDocShell); } diff --git a/sd/source/ui/view/ImpressViewShellBase.cxx b/sd/source/ui/view/ImpressViewShellBase.cxx index 17baf9ccf507..fe519c9f7c37 100644 --- a/sd/source/ui/view/ImpressViewShellBase.cxx +++ b/sd/source/ui/view/ImpressViewShellBase.cxx @@ -37,7 +37,7 @@ namespace sd { // We have to expand the SFX_IMPL_VIEWFACTORY macro to call LateInit() after a // new ImpressViewShellBase object has been constructed. -SfxViewFactory* ImpressViewShellBase::s_pFactory; +std::map> ImpressViewShellBase::s_pFactories; SfxViewShell* ImpressViewShellBase::CreateInstance ( SfxViewFrame& rFrame, SfxViewShell *pOldView) { @@ -47,12 +47,9 @@ SfxViewShell* ImpressViewShellBase::CreateInstance ( } void ImpressViewShellBase::RegisterFactory( SfxInterfaceId nPrio ) { - s_pFactory = new SfxViewFactory(&CreateInstance,nPrio,"Default"); - InitFactory(); -} -void ImpressViewShellBase::InitFactory() -{ - SFX_VIEW_REGISTRATION(DrawDocShell); + assert(s_pFactories.find(nPrio) == s_pFactories.end()); + s_pFactories[nPrio] = std::make_unique(&CreateInstance,nPrio,"Default"); + DrawDocShell::Factory().RegisterViewFactory( *s_pFactories[nPrio] ); } ImpressViewShellBase::ImpressViewShellBase ( diff --git a/sd/source/ui/view/OutlineViewShellBase.cxx b/sd/source/ui/view/OutlineViewShellBase.cxx index e3efb3ed59d5..45307503110e 100644 --- a/sd/source/ui/view/OutlineViewShellBase.cxx +++ b/sd/source/ui/view/OutlineViewShellBase.cxx @@ -32,7 +32,7 @@ class DrawDocShell; // We have to expand the SFX_IMPL_VIEWFACTORY macro to call LateInit() after a // new OutlineViewShellBase object has been constructed. -SfxViewFactory* OutlineViewShellBase::s_pFactory; +std::unique_ptr OutlineViewShellBase::s_pFactory; SfxViewShell* OutlineViewShellBase::CreateInstance ( SfxViewFrame& rFrame, SfxViewShell *pOldView) { @@ -42,7 +42,7 @@ SfxViewShell* OutlineViewShellBase::CreateInstance ( } void OutlineViewShellBase::RegisterFactory( SfxInterfaceId nPrio ) { - s_pFactory = new SfxViewFactory(&CreateInstance,nPrio,"Outline"); + s_pFactory = std::make_unique(&CreateInstance,nPrio,"Outline"); InitFactory(); } void OutlineViewShellBase::InitFactory() diff --git a/sd/source/ui/view/Outliner.cxx b/sd/source/ui/view/Outliner.cxx index 455d3569bfbb..50b7b5b4c15d 100644 --- a/sd/source/ui/view/Outliner.cxx +++ b/sd/source/ui/view/Outliner.cxx @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -1633,7 +1632,7 @@ void SdOutliner::SetViewMode (PageKind ePageKind) break; } // The text object iterator is destroyed when the shells are - // switched but we need it so save it and restore it afterwards. + // switched but we need it to save it and restore it afterwards. sd::outliner::Iterator aIterator (maObjectIterator); bool bMatchMayExist = mbMatchMayExist; @@ -1659,7 +1658,7 @@ void SdOutliner::SetViewMode (PageKind ePageKind) if (xFuSearch.is() && pNewViewShell->GetView()) pNewViewShell->GetView()->getSearchContext().setSearchFunction(xFuSearch); - // Switching to another view shell has intermediatly called + // Switching to another view shell has intermediately called // EndSpelling(). A PrepareSpelling() is pending, so call that now. PrepareSpelling(); @@ -1716,7 +1715,7 @@ void SdOutliner::EnterEditMode (bool bGrabFocus) if (mpView->IsTextEdit()) { - // end text edition before starting it again + // end text editing before starting it again mpView->SdrEndTextEdit(); } @@ -2058,7 +2057,7 @@ weld::Window* SdOutliner::GetMessageBoxParent() break; case TEXT_CONVERSION: - // There should no messages boxes be displayed while doing the + // There should be no message boxes displayed while doing the // hangul hanja conversion. break; } diff --git a/sd/source/ui/view/PresentationViewShellBase.cxx b/sd/source/ui/view/PresentationViewShellBase.cxx index aef3d5e247d9..50f8df074dce 100644 --- a/sd/source/ui/view/PresentationViewShellBase.cxx +++ b/sd/source/ui/view/PresentationViewShellBase.cxx @@ -40,7 +40,7 @@ class DrawDocShell; // We have to expand the SFX_IMPL_VIEWFACTORY macro to call LateInit() after a // new PresentationViewShellBase object has been constructed. -SfxViewFactory* PresentationViewShellBase::s_pFactory; +std::unique_ptr PresentationViewShellBase::s_pFactory; SfxViewShell* PresentationViewShellBase::CreateInstance ( SfxViewFrame& _rFrame, SfxViewShell *pOldView) { @@ -51,7 +51,7 @@ SfxViewShell* PresentationViewShellBase::CreateInstance ( } void PresentationViewShellBase::RegisterFactory( SfxInterfaceId nPrio ) { - s_pFactory = new SfxViewFactory( + s_pFactory = std::make_unique( &CreateInstance,nPrio,"FullScreenPresentation"); InitFactory(); } diff --git a/sd/source/ui/view/SlideSorterViewShellBase.cxx b/sd/source/ui/view/SlideSorterViewShellBase.cxx index 3c5578e8a191..c0aeca845a02 100644 --- a/sd/source/ui/view/SlideSorterViewShellBase.cxx +++ b/sd/source/ui/view/SlideSorterViewShellBase.cxx @@ -32,7 +32,7 @@ class DrawDocShell; // We have to expand the SFX_IMPL_VIEWFACTORY macro to call LateInit() after a // new SlideSorterViewShellBase object has been constructed. -SfxViewFactory* SlideSorterViewShellBase::s_pFactory; +std::unique_ptr SlideSorterViewShellBase::s_pFactory; SfxViewShell* SlideSorterViewShellBase::CreateInstance ( SfxViewFrame& rFrame, SfxViewShell *pOldView) { @@ -43,7 +43,7 @@ SfxViewShell* SlideSorterViewShellBase::CreateInstance ( void SlideSorterViewShellBase::RegisterFactory( SfxInterfaceId nPrio ) { - s_pFactory = new SfxViewFactory(&CreateInstance,nPrio,"SlideSorter"); + s_pFactory = std::make_unique(&CreateInstance,nPrio,"SlideSorter"); InitFactory(); } diff --git a/sd/source/ui/view/ViewShellBase.cxx b/sd/source/ui/view/ViewShellBase.cxx index 375f901b9bc7..1fb5664b8e52 100644 --- a/sd/source/ui/view/ViewShellBase.cxx +++ b/sd/source/ui/view/ViewShellBase.cxx @@ -94,7 +94,6 @@ using ::sd::framework::FrameworkHelper; using namespace com::sun::star; using namespace com::sun::star::beans; using namespace com::sun::star::container; -using namespace com::sun::star::drawing::framework; using namespace com::sun::star::lang; using namespace com::sun::star::uno; @@ -457,14 +456,14 @@ OUString ViewShellBase::GetSelectionText(bool bCompleteWords, bool /*bOnlyASampl : SfxViewShell::GetSelectionText(bCompleteWords); } -bool ViewShellBase::HasSelection(bool bText) const +bool ViewShellBase::HasSelection(bool bMustHaveText) const { std::shared_ptr const pMainShell(GetMainViewShell()); DrawViewShell *const pDrawViewShell( dynamic_cast(pMainShell.get())); return pDrawViewShell - ? pDrawViewShell->HasSelection(bText) - : SfxViewShell::HasSelection(bText); + ? pDrawViewShell->HasSelection(bMustHaveText) + : SfxViewShell::HasSelection(bMustHaveText); } void ViewShellBase::InnerResizePixel (const Point& rOrigin, const Size &rSize, bool) @@ -1099,14 +1098,6 @@ void ViewShellBase::afterCallbackRegistered() // common tasks SfxViewShell::afterCallbackRegistered(); - SfxObjectShell* pDocShell = GetObjectShell(); - if (pDocShell) - { - std::shared_ptr pThemeColors = pDocShell->GetThemeColors(); - std::set aDocumentColors = pDocShell->GetDocColors(); - svx::theme::notifyLOK(pThemeColors, aDocumentColors); - } - if (comphelper::LibreOfficeKit::isActive() && mpDocument && mpDocument->GetStartWithPresentation()) { // Be consistent with SidebarController, emit JSON. diff --git a/sd/source/ui/view/ViewTabBar.cxx b/sd/source/ui/view/ViewTabBar.cxx index f584dc780876..fb6ff44b3e11 100644 --- a/sd/source/ui/view/ViewTabBar.cxx +++ b/sd/source/ui/view/ViewTabBar.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,6 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::sd::framework::FrameworkHelper; namespace sd { @@ -95,7 +95,7 @@ ViewTabBar::ViewTabBar ( if (mpViewShellBase != nullptr && rxViewTabBarId->isBoundToURL( - FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) + FrameworkHelper::msCenterPaneURL, sd::framework::AnchorBindingMode::DIRECT)) { mpViewShellBase->SetViewTabBar(this); } @@ -111,7 +111,7 @@ void ViewTabBar::disposing(std::unique_lock&) { if (mpViewShellBase != nullptr && mxViewTabBarId->isBoundToURL( - FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) + FrameworkHelper::msCenterPaneURL, sd::framework::AnchorBindingMode::DIRECT)) { mpViewShellBase->SetViewTabBar(nullptr); } @@ -154,7 +154,7 @@ vcl::Window* ViewTabBar::GetAnchorWindow( // The ViewTabBar supports at the moment only the center pane. if (rxViewTabBarId.is() && rxViewTabBarId->isBoundToURL( - FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) + FrameworkHelper::msCenterPaneURL, sd::framework::AnchorBindingMode::DIRECT)) { if (pBase != nullptr) pWindow = &pBase->GetViewFrame().GetWindow(); @@ -196,7 +196,8 @@ void ViewTabBar::Listener::notifyConfigurationChange ( { if (rEvent.Type == framework::ConfigurationChangeEventType::ResourceActivation && rEvent.ResourceId->getResourceURL().match(FrameworkHelper::msViewURLPrefix) - && rEvent.ResourceId->isBoundTo(mrParent.mxViewTabBarId->getAnchor(), AnchorBindingMode_DIRECT)) + && rEvent.ResourceId->isBoundTo(mrParent.mxViewTabBarId->getAnchor(), + sd::framework::AnchorBindingMode::DIRECT)) { mrParent.UpdateActiveButton(); } @@ -332,7 +333,7 @@ void ViewTabBar::AddTabBarButton ( } else { - for (nIndex=0; nIndex #include -#include #include #include #include @@ -94,7 +93,7 @@ void DrawView::ModelHasChanged() { ::sd::View::ModelHasChanged(); - // force framer to rerender + // force frame to rerender SfxStyleSheetBasePool* pSSPool = mrDoc.GetStyleSheetPool(); pSSPool->Broadcast(SfxStyleSheetPoolHint()); @@ -396,7 +395,7 @@ void DrawView::SetMasterAttributes( SdrObject* pObject, const SdPage& rPage, con } /** - * Notify for change of site arrangement + * Notify for change of page arrangement */ void DrawView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) diff --git a/sd/source/ui/view/drtxtob.cxx b/sd/source/ui/view/drtxtob.cxx index be3bcad2b85b..ab111f906142 100644 --- a/sd/source/ui/view/drtxtob.cxx +++ b/sd/source/ui/view/drtxtob.cxx @@ -131,7 +131,7 @@ void TextObjectBar::GetCharStateImpl(const ViewShell& rViewShell, const ::sd::Vi SfxItemSet aCharAttrSet( pView->GetDoc().GetPool() ); pView->GetAttributes( aCharAttrSet ); - SfxItemSetFixed aNewAttr( rViewShell.GetPool() ); + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet( rViewShell.GetPool() )); aNewAttr.Put(aCharAttrSet, false); rSet.Put(aNewAttr, false); @@ -314,7 +314,8 @@ void TextObjectBar::GetAttrStateImpl(const ViewShell& rViewShell, ::sd::View* pV bDisableLeft = false; } - if( (nDepth < pOLV->GetOutliner().GetMaxDepth() && ( !bOutlineViewSh || rOutl.GetAbsPos(pPara) != 0 )) || + // tdf#148629 - disable demote command on non-list paragraphs + if( (nDepth >= 0 && nDepth < pOLV->GetOutliner().GetMaxDepth() && ( !bOutlineViewSh || rOutl.GetAbsPos(pPara) != 0 )) || (bOutlineViewSh && (nDepth <= 0) && ::Outliner::HasParaFlag( pPara, ParaFlag::ISPAGE ) && rOutl.GetAbsPos(pPara) != 0) ) { // not maximum depth and not at top diff --git a/sd/source/ui/view/drtxtob1.cxx b/sd/source/ui/view/drtxtob1.cxx index 751dca3f76d2..3e6fd8a24e37 100644 --- a/sd/source/ui/view/drtxtob1.cxx +++ b/sd/source/ui/view/drtxtob1.cxx @@ -151,7 +151,7 @@ void TextObjectBar::Execute(SfxRequest& rReq) const SvxLRSpaceItem& rItem = aAttr.Get( EE_PARA_LRSPACE ); std::unique_ptr pNewItem(rItem.Clone()); - ::tools::Long nLeft = pNewItem->ResolveLeft({}); + ::tools::Long nLeft = pNewItem->ResolveLeft(); if( nSlot == SID_INC_INDENT ) nLeft += nIndentDefaultDist; else @@ -237,7 +237,7 @@ void TextObjectBar::Execute(SfxRequest& rReq) // the following code could be enabled, if I get a correct // DontCare status from JOE. - // gets enabled, through it doesn't really work (see above) + // gets enabled, though it doesn't really work (see above) SfxItemSet aEditAttr( mpView->GetDoc().GetPool() ); mpView->GetAttributes( aEditAttr ); if( aEditAttr.GetItemState( EE_PARA_ULSPACE ) >= SfxItemState::DEFAULT ) diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx index 7a135e5e12f8..ed8f5b1cea9a 100644 --- a/sd/source/ui/view/drviews2.cxx +++ b/sd/source/ui/view/drviews2.cxx @@ -106,7 +106,7 @@ #include #include #include -#include +#include #include #include @@ -141,6 +141,8 @@ #include #include #include +#include +#include #include #include #include @@ -522,7 +524,7 @@ private: nParagraph++; pOutliner->Insert(u""_ustr); - SfxItemSetFixed aItemSet(m_rDrawViewShell.GetDoc()->GetPool()); + SfxItemSet aItemSet(SfxItemSet::makeFixedSfxItemSet(m_rDrawViewShell.GetDoc()->GetPool())); if (rResult.msName == "BOLD") aItemSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT)); @@ -1366,7 +1368,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) if( pItem ) { - SfxItemSetFixed aSet( GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet( GetPool() )); bool bValue = pItem->GetValue(); aSet.Put( SfxBoolItem( EE_PARA_HYPHENATE, bValue ) ); mpDrawView->SetAttributes( aSet ); @@ -1374,7 +1376,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) else // only for testing purpose { OSL_FAIL(" no value for hyphenation!"); - SfxItemSetFixed aSet( GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aSet.Put( SfxBoolItem( EE_PARA_HYPHENATE, true ) ); mpDrawView->SetAttributes( aSet ); } @@ -1569,6 +1571,164 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) } break; + case SID_ADD_SLIDE_SECTION: + { + SdPage* pPage = GetActualPage(); + if (pPage) + { + sal_uInt16 nPage = (pPage->GetPageNum() - 1) / 2; + sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); + auto pUndo = GetDoc()->IsUndoEnabled() + ? std::make_unique( + *GetDoc(), SdResId(STR_UNDO_ADD_SLIDE_SECTION)) + : nullptr; + rMgr.AddSection(nPage, SdResId(STR_DEFAULT_SLIDE_SECTION_NAME)); + if (pUndo) + GetDoc()->AddUndo(std::move(pUndo)); + GetDocSh()->SetModified(); + } + } + break; + + case SID_REMOVE_SLIDE_SECTION: + { + SdPage* pPage = GetActualPage(); + if (pPage) + { + sal_uInt16 nPage = (pPage->GetPageNum() - 1) / 2; + sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); + sal_Int32 nSectionIdx = rMgr.GetSectionIndexForSlide(nPage); + if (nSectionIdx >= 0 && rMgr.IsSectionStart(nPage)) + { + auto pUndo = GetDoc()->IsUndoEnabled() + ? std::make_unique( + *GetDoc(), SdResId(STR_UNDO_REMOVE_SLIDE_SECTION)) + : nullptr; + rMgr.RemoveSection(nSectionIdx); + if (pUndo) + GetDoc()->AddUndo(std::move(pUndo)); + GetDocSh()->SetModified(); + } + } + } + break; + + case SID_REMOVE_SLIDE_SECTION_AND_SLIDES: + { + SdPage* pPage = GetActualPage(); + if (pPage) + { + sal_uInt16 nPage = (pPage->GetPageNum() - 1) / 2; + sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); + sal_Int32 nSectionIdx = rMgr.GetSectionIndexForSlide(nPage); + if (nSectionIdx >= 0 && rMgr.IsSectionStart(nPage)) + { + const bool bUndo = GetDoc()->IsUndoEnabled(); + if (bUndo) + GetView()->BegUndo( + SdResId(STR_UNDO_REMOVE_SLIDE_SECTION_AND_SLIDES)); + + rMgr.RemoveSectionSlides(nSectionIdx); + + if (bUndo) + GetView()->EndUndo(); + GetDocSh()->SetModified(); + ResetActualPage(); + } + } + } + break; + + case SID_RENAME_SLIDE_SECTION: + { + sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); + if (rReq.GetArgs()) + { + const SfxInt32Item* pIndexItem + = rReq.GetArgs()->GetItem(SID_RENAME_SLIDE_SECTION, false); + const SfxStringItem* pNameItem + = rReq.GetArgs()->GetItem(SID_RENAMEPAGE, false); + if (pIndexItem && pNameItem) + { + sal_Int32 nSectionIndex = pIndexItem->GetValue(); + OUString aNewName = pNameItem->GetValue(); + if (nSectionIndex >= 0 && nSectionIndex < rMgr.GetSectionCount() + && !aNewName.isEmpty()) + { + auto pUndo = GetDoc()->IsUndoEnabled() + ? std::make_unique( + *GetDoc(), SdResId(STR_UNDO_RENAME_SLIDE_SECTION)) + : nullptr; + rMgr.RenameSection(nSectionIndex, aNewName); + if (pUndo) + GetDoc()->AddUndo(std::move(pUndo)); + GetDocSh()->SetModified(); + } + } + } + } + break; + + case SID_MOVE_SLIDE_SECTION_UP: + { + SdPage* pPage = GetActualPage(); + if (pPage) + { + sal_uInt16 nPage = (pPage->GetPageNum() - 1) / 2; + sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); + sal_Int32 nSectionIdx = rMgr.GetSectionIndexForSlide(nPage); + if (nSectionIdx > 0) + { + // Group the section metadata undo with the page-reorder undo + // recorded by MovePages() inside MoveSection(). + const bool bUndo = GetDoc()->IsUndoEnabled(); + if (bUndo) + GetDoc()->BegUndo(SdResId(STR_UNDO_MOVE_SLIDE_SECTION)); + auto pUndo = bUndo + ? std::make_unique( + *GetDoc(), SdResId(STR_UNDO_MOVE_SLIDE_SECTION)) + : nullptr; + rMgr.MoveSection(nSectionIdx, nSectionIdx - 1); + if (bUndo) + { + GetDoc()->AddUndo(std::move(pUndo)); + GetDoc()->EndUndo(); + } + GetDocSh()->SetModified(); + } + } + } + break; + + case SID_MOVE_SLIDE_SECTION_DOWN: + { + SdPage* pPage = GetActualPage(); + if (pPage) + { + sal_uInt16 nPage = (pPage->GetPageNum() - 1) / 2; + sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); + sal_Int32 nSectionIdx = rMgr.GetSectionIndexForSlide(nPage); + if (nSectionIdx >= 0 && nSectionIdx < rMgr.GetSectionCount() - 1) + { + const bool bUndo = GetDoc()->IsUndoEnabled(); + if (bUndo) + GetDoc()->BegUndo(SdResId(STR_UNDO_MOVE_SLIDE_SECTION)); + auto pUndo = bUndo + ? std::make_unique( + *GetDoc(), SdResId(STR_UNDO_MOVE_SLIDE_SECTION)) + : nullptr; + rMgr.MoveSection(nSectionIdx, nSectionIdx + 1); + if (bUndo) + { + GetDoc()->AddUndo(std::move(pUndo)); + GetDoc()->EndUndo(); + } + GetDocSh()->SetModified(); + } + } + } + break; + case SID_PAGESIZE : // either this (no menu entries or something else!) { const SfxItemSet *pArgs = rReq.GetArgs (); @@ -1897,7 +2057,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) if( pPresPage->IsPresObj( pObj ) ) { - auto pNewSet = std::make_unique>( GetDoc()->GetPool() ); + auto pNewSet = std::make_unique(SfxItemSet::makeFixedSfxItemSet( GetDoc()->GetPool() )); pNewSet->Put(pObj->GetMergedItemSet()); aAttrList.emplace_back(std::move(pNewSet), pObj->GetUserCall()); } @@ -2452,7 +2612,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) case SID_CONNECTION_NEW_ROUTING: { - SfxItemSetFixed aDefAttr( GetPool() ); + SfxItemSet aDefAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); GetView()->SetAttributes( aDefAttr, true ); // (ReplaceAll) Cancel(); @@ -2571,7 +2731,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) if (! pArgs) { - SfxItemSetFixed aNewAttr( GetDoc()->GetPool() ); + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet( GetDoc()->GetPool() )); aNewAttr.Put( makeSdAttrLayerName( aLayerName ) ); aNewAttr.Put( makeSdAttrLayerTitle() ); @@ -2724,7 +2884,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) if (! pArgs) { - SfxItemSetFixed aNewAttr( GetDoc()->GetPool() ); + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet( GetDoc()->GetPool() )); aNewAttr.Put( makeSdAttrLayerName( aLayerName ) ); aNewAttr.Put( makeSdAttrLayerTitle( aLayerTitle ) ); @@ -2981,10 +3141,19 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) else if (pHLItem->GetInsertMode() == HLINK_DEFAULT) { OutlinerView* pOlView = mpDrawView->GetTextEditOutlinerView(); + // When the provided text is just a hint, prefer the selection over it; if both + // are missing, use the URL. + OUString sLinkText; + if (pHLItem->GetTextIsHint() && pOlView && pOlView->HasSelection()) + sLinkText = pOlView->GetSelected(); + else if (!pHLItem->GetName().isEmpty()) + sLinkText = pHLItem->GetName(); + else + sLinkText = pHLItem->GetURL(); if (pOlView || comphelper::LibreOfficeKit::isActive()) { - InsertURLField(pHLItem->GetURL(), pHLItem->GetName(), + InsertURLField(pHLItem->GetURL(), sLinkText, pHLItem->GetTargetFrame(), pHLItem->GetIntName()); } else @@ -4289,7 +4458,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) // Open ThemeColorEditDialog to create/edit the new color set auto pSubDialog = std::make_shared(GetFrameWeld(), *pCurrentColorSet); - weld::DialogController::runAsync(pSubDialog, [pSubDialog, this](sal_uInt32 nResult) { + weld::DialogController::runAsync(pSubDialog, [pSubDialog](sal_uInt32 nResult) { if (nResult != RET_OK) return; @@ -4298,8 +4467,6 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) { // Add the new color set to the global collection svx::ColorSets::get().insert(aColorSet); - // Invalidate to update the toolbar control - GetViewFrame()->GetBindings().Invalidate(SID_ADD_THEME); } }); diff --git a/sd/source/ui/view/drviews3.cxx b/sd/source/ui/view/drviews3.cxx index cba2ed4a2189..76a068f52976 100644 --- a/sd/source/ui/view/drviews3.cxx +++ b/sd/source/ui/view/drviews3.cxx @@ -85,7 +85,6 @@ #include using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::drawing::framework; using ::com::sun::star::frame::XFrame; using ::com::sun::star::frame::XController; @@ -713,7 +712,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) { const SvxTabStopItem& rItem = pArgs->Get( EE_PARA_TABS ); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aEditAttr.Put( rItem ); mpDrawView->SetAttributes( aEditAttr ); @@ -727,7 +726,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) SvxLineSpacingItem aParaLineSP = pArgs->Get( GetPool().GetWhichIDFromSlotID(SID_ATTR_PARA_LINESPACE)); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aParaLineSP.SetWhich( EE_PARA_SBL ); aEditAttr.Put( aParaLineSP ); @@ -739,7 +738,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) case SID_ATTR_PARA_ADJUST_LEFT: { SvxAdjustItem aItem( SvxAdjust::Left, EE_PARA_JUST ); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aEditAttr.Put( aItem ); mpDrawView->SetAttributes( aEditAttr ); @@ -750,7 +749,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) case SID_ATTR_PARA_ADJUST_CENTER: { SvxAdjustItem aItem( SvxAdjust::Center, EE_PARA_JUST ); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aEditAttr.Put( aItem ); mpDrawView->SetAttributes( aEditAttr ); @@ -761,7 +760,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) case SID_ATTR_PARA_ADJUST_RIGHT: { SvxAdjustItem aItem( SvxAdjust::Right, EE_PARA_JUST ); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aEditAttr.Put( aItem ); mpDrawView->SetAttributes( aEditAttr ); @@ -772,7 +771,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) case SID_ATTR_PARA_ADJUST_BLOCK: { SvxAdjustItem aItem( SvxAdjust::Block, EE_PARA_JUST ); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aEditAttr.Put( aItem ); mpDrawView->SetAttributes( aEditAttr ); @@ -783,7 +782,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) case SID_ATTR_PARA_ADJUST_START: { SvxAdjustItem aItem( SvxAdjust::ParaStart, EE_PARA_JUST ); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aEditAttr.Put( aItem ); mpDrawView->SetAttributes( aEditAttr ); @@ -794,7 +793,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) case SID_ATTR_PARA_ADJUST_END: { SvxAdjustItem aItem( SvxAdjust::ParaEnd, EE_PARA_JUST ); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aEditAttr.Put( aItem ); mpDrawView->SetAttributes( aEditAttr ); @@ -807,7 +806,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) { SvxULSpaceItem aULSP = static_cast(pArgs->Get( SID_ATTR_PARA_ULSPACE)); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aULSP.SetWhich( EE_PARA_ULSPACE ); aEditAttr.Put( aULSP ); @@ -822,7 +821,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) SvxLRSpaceItem aLRSpace = static_cast(pArgs->Get( SID_ATTR_PARA_LRSPACE)); - SfxItemSetFixed aEditAttr( GetPool() ); + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aLRSpace.SetWhich( EE_PARA_LRSPACE ); aEditAttr.Put( aLRSpace ); @@ -838,10 +837,10 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) const SvxLRSpaceItem& rItem = static_cast( pArgs->Get( nId )); - SfxItemSetFixed< + SfxItemSet aEditAttr(SfxItemSet::makeFixedSfxItemSet< EE_PARA_NUMBULLET, EE_PARA_NUMBULLET, EE_PARA_OUTLLEVEL, EE_PARA_OUTLLEVEL, - EE_PARA_LRSPACE, EE_PARA_LRSPACE> aEditAttr( GetDoc()->GetPool() ); + EE_PARA_LRSPACE, EE_PARA_LRSPACE> ( GetDoc()->GetPool() )); mpDrawView->GetAttributes( aEditAttr ); nId = EE_PARA_LRSPACE; @@ -901,7 +900,7 @@ void DrawViewShell::ExecRuler(SfxRequest& rReq) } // only put lrSpace item - SfxItemSetFixed aEditAttrReduced( GetDoc()->GetPool() ); + SfxItemSet aEditAttrReduced(SfxItemSet::makeFixedSfxItemSet( GetDoc()->GetPool() )); aEditAttrReduced.Put( aLRSpaceItem ); mpDrawView->SetAttributes( aEditAttrReduced ); diff --git a/sd/source/ui/view/drviews4.cxx b/sd/source/ui/view/drviews4.cxx index 38f7ead45771..39e9de92fadb 100644 --- a/sd/source/ui/view/drviews4.cxx +++ b/sd/source/ui/view/drviews4.cxx @@ -899,9 +899,9 @@ void DrawViewShell::ShowMousePosInfo(const ::tools::Rectangle& rRect, if ( GetViewShell()->GetUIActiveClient() ) return; - SfxItemSetFixed< + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet < SID_CONTEXT, SID_CONTEXT, - SID_ATTR_POSITION, SID_ATTR_SIZE> aSet(GetPool()); + SID_ATTR_POSITION, SID_ATTR_SIZE> (GetPool())); GetStatusBarState(aSet); diff --git a/sd/source/ui/view/drviews6.cxx b/sd/source/ui/view/drviews6.cxx index 64ee85859dcc..9ba9160e6fe2 100644 --- a/sd/source/ui/view/drviews6.cxx +++ b/sd/source/ui/view/drviews6.cxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/sd/source/ui/view/drviews7.cxx b/sd/source/ui/view/drviews7.cxx index 6c26d5cf9df1..e7d87e5a2949 100644 --- a/sd/source/ui/view/drviews7.cxx +++ b/sd/source/ui/view/drviews7.cxx @@ -88,6 +88,7 @@ #include #include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -304,25 +305,33 @@ bool DrawViewShell::ShouldDisableEditHyperlink() const } else { - SdrUnoObj* pUnoCtrl = dynamic_cast( rMarkList.GetMark(0)->GetMarkedSdrObj() ); + SdrUnoObj* pUnoCtrl = dynamic_cast( rMarkList.GetMark(0)->GetMarkedSdrObj() ); - if ( pUnoCtrl && SdrInventor::FmForm == pUnoCtrl->GetObjInventor() ) + if ( pUnoCtrl && SdrInventor::FmForm == pUnoCtrl->GetObjInventor() ) + { + const uno::Reference< awt::XControlModel >& xControlModel( pUnoCtrl->GetUnoControlModel() ); + if( xControlModel.is() ) { - const uno::Reference< awt::XControlModel >& xControlModel( pUnoCtrl->GetUnoControlModel() ); - if( xControlModel.is() ) + uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY ); + if( xPropSet.is() ) { - uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY ); - if( xPropSet.is() ) + uno::Reference< beans::XPropertySetInfo > xPropInfo( xPropSet->getPropertySetInfo() ); + if( xPropInfo.is() && xPropInfo->hasPropertyByName( u"TargetURL"_ustr) ) { - uno::Reference< beans::XPropertySetInfo > xPropInfo( xPropSet->getPropertySetInfo() ); - if( xPropInfo.is() && xPropInfo->hasPropertyByName( u"TargetURL"_ustr) ) - { - bDisableEditHyperlink = false; - } + bDisableEditHyperlink = false; } } } } + else + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if( pObj && !pObj->getHyperlink().isEmpty() ) + { + bDisableEditHyperlink = false; + } + } +} return bDisableEditHyperlink; } @@ -1613,7 +1622,7 @@ void DrawViewShell::GetMenuState( SfxItemSet &rSet ) SdPage* pPage = GetActualPage(); if (pPage != nullptr && GetDoc() != nullptr) { - SfxItemSetFixed aMergedAttr(GetDoc()->GetPool()); + SfxItemSet aMergedAttr(SfxItemSet::makeFixedSfxItemSet(GetDoc()->GetPool())); SdStyleSheet* pStyleSheet = pPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND); MergePageBackgroundFilling(pPage, pStyleSheet, meEditMode == EditMode::MasterPage, aMergedAttr); if (drawing::FillStyle_BITMAP == aMergedAttr.Get(XATTR_FILLSTYLE).GetValue()) @@ -1641,6 +1650,25 @@ void DrawViewShell::GetMenuState( SfxItemSet &rSet ) if (!SdModule::get()->pTransferClip) rSet.DisableItem(SID_PASTE_SLIDE); + if (rSet.GetItemState(SID_REMOVE_SLIDE_SECTION) == SfxItemState::DEFAULT + || rSet.GetItemState(SID_REMOVE_SLIDE_SECTION_AND_SLIDES) == SfxItemState::DEFAULT) + { + bool bDisable = true; + SdPage* pPage = GetActualPage(); + if (pPage && GetDoc()) + { + sal_uInt16 nPageIdx = (pPage->GetPageNum() - 1) / 2; + sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); + if (rMgr.IsSectionStart(nPageIdx)) + bDisable = false; + } + if (bDisable) + { + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION); + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION_AND_SLIDES); + } + } + GetModeSwitchingMenuState (rSet); } @@ -1850,7 +1878,7 @@ void DrawViewShell::SetPageProperties (SfxRequest& rReq) XFillGradientItem aGradientItem( basegfx::BGradient::fromJSON(pJSON->GetValue()) ); // MigrateItemSet guarantees unique gradient names - SfxItemSetFixed aMigrateSet(mpDrawView->GetModel().GetItemPool()); + SfxItemSet aMigrateSet(SfxItemSet::makeFixedSfxItemSet(mpDrawView->GetModel().GetItemPool())); aMigrateSet.Put( aGradientItem ); SdrModel::MigrateItemSet(&aMigrateSet, &aTempSet, mpDrawView->GetModel()); @@ -1862,7 +1890,7 @@ void DrawViewShell::SetPageProperties (SfxRequest& rReq) XFillGradientItem aGradientItem( pArgs->Get( XATTR_FILLGRADIENT ) ); // MigrateItemSet guarantees unique gradient names - SfxItemSetFixed aMigrateSet(mpDrawView->GetModel().GetItemPool()); + SfxItemSet aMigrateSet(SfxItemSet::makeFixedSfxItemSet(mpDrawView->GetModel().GetItemPool())); aMigrateSet.Put( aGradientItem ); SdrModel::MigrateItemSet(&aMigrateSet, &aTempSet, mpDrawView->GetModel()); @@ -1912,8 +1940,8 @@ void DrawViewShell::SetPageProperties (SfxRequest& rReq) if( pArgs->GetItemState(SID_ATTR_PAGE_LRSPACE, true,&pPoolItem) == SfxItemState::SET ) { - nLeft = static_cast(pPoolItem)->GetLeft(); - nRight = static_cast(pPoolItem)->GetRight(); + nLeft = pPoolItem->StaticWhichCast(SID_ATTR_PAGE_LRSPACE).GetLeft(); + nRight = pPoolItem->StaticWhichCast(SID_ATTR_PAGE_LRSPACE).GetRight(); if (nLeft != -1) { nUpper = pPage->GetUpperBorder(); @@ -1927,8 +1955,8 @@ void DrawViewShell::SetPageProperties (SfxRequest& rReq) if( pArgs->GetItemState(SID_ATTR_PAGE_ULSPACE, true,&pPoolItem) == SfxItemState::SET ) { - nUpper = static_cast(pPoolItem)->GetUpper(); - nLower = static_cast(pPoolItem)->GetLower(); + nUpper = pPoolItem->StaticWhichCast(SID_ATTR_PAGE_ULSPACE).GetUpper(); + nLower = pPoolItem->StaticWhichCast(SID_ATTR_PAGE_ULSPACE).GetLower(); if (nUpper != -1) { nLeft = pPage->GetLeftBorder(); diff --git a/sd/source/ui/view/drviewse.cxx b/sd/source/ui/view/drviewse.cxx index a5428b5777cd..d0b5186b2216 100644 --- a/sd/source/ui/view/drviewse.cxx +++ b/sd/source/ui/view/drviewse.cxx @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sd/source/ui/view/drviewsf.cxx b/sd/source/ui/view/drviewsf.cxx index 11594f21e2e2..7d2e544f16e2 100644 --- a/sd/source/ui/view/drviewsf.cxx +++ b/sd/source/ui/view/drviewsf.cxx @@ -696,7 +696,7 @@ void DrawViewShell::GetAttrState( SfxItemSet& rSet ) SfxItemSet aEditAttr( GetDoc()->GetPool() ); mpDrawView->GetAttributes( aEditAttr ); - SfxItemSetFixed aNewAttr( GetPool() ); + SfxItemSet aNewAttr(SfxItemSet::makeFixedSfxItemSet( GetPool() )); aNewAttr.Put( aEditAttr, false ); std::unique_ptr pNumRule; diff --git a/sd/source/ui/view/drviewsi.cxx b/sd/source/ui/view/drviewsi.cxx index 7eea9e99e0e5..203208769e43 100644 --- a/sd/source/ui/view/drviewsi.cxx +++ b/sd/source/ui/view/drviewsi.cxx @@ -28,7 +28,6 @@ #include #include #include -#include #include @@ -109,7 +108,7 @@ void DrawViewShell::AssignFrom3DWindow() if(!GetView()->IsPresObjSelected()) { - SfxItemSetFixed aSet( GetDoc()->GetPool() ); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet( GetDoc()->GetPool() )); p3DWin->GetAttr( aSet ); // own UNDO-compounding also around transformation in 3D @@ -118,7 +117,7 @@ void DrawViewShell::AssignFrom3DWindow() if(GetView()->IsConvertTo3DObjPossible()) { // assign only text-attribute - SfxItemSetFixed aTextSet( GetDoc()->GetPool() ); + SfxItemSet aTextSet(SfxItemSet::makeFixedSfxItemSet( GetDoc()->GetPool() )); aTextSet.Put( aSet, false ); GetView()->SetAttributes( aTextSet ); diff --git a/sd/source/ui/view/outlview.cxx b/sd/source/ui/view/outlview.cxx index 1aa4214731ee..a1408a486f0d 100644 --- a/sd/source/ui/view/outlview.cxx +++ b/sd/source/ui/view/outlview.cxx @@ -351,7 +351,7 @@ OutlineView::OutlineView(DrawDocShell& rDocSh, vcl::Window* pWindow, maSlideImage = vcl::CommandInfoProvider::GetImageForCommand(u".uno:ShowSlide"_ustr, xFrame, vcl::ImageType::Size26); // Tell undo manager of the document about the undo manager of the - // outliner, so that the former can synchronize with the later. + // outliner, so that the former can synchronize with the latter. sd::UndoManager* pDocUndoMgr = dynamic_cast(mpDocSh->GetUndoManager()); if (pDocUndoMgr != nullptr) pDocUndoMgr->SetLinkedUndoManager(&mrOutliner.GetUndoManager()); @@ -1273,7 +1273,7 @@ void OutlineView::FillOutliner() pTO = static_cast(pPage->GetPresObj(PresObjKind::Text)); const bool bSubTitle = pTO != nullptr; - if (!pTO) // if no subtile found, try outline + if (!pTO) // if no subtitle found, try outline pTO = GetOutlineTextObject(pPage); if(pTO && !(pTO->IsEmptyPresObj())) // found some text diff --git a/sd/source/ui/view/sdview.cxx b/sd/source/ui/view/sdview.cxx index c3205cbe37bc..3d25cc7f8057 100644 --- a/sd/source/ui/view/sdview.cxx +++ b/sd/source/ui/view/sdview.cxx @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include #include #include @@ -648,7 +650,7 @@ SfxViewShell* View::GetSfxViewShell() const return pRet; } -// Create a new view-local UndoManager manager for Impress/Draw +// Create a new view-local UndoManager for Impress/Draw std::unique_ptr View::createLocalTextUndoManager() { std::unique_ptr pUndoManager(new sd::UndoManager); @@ -785,6 +787,22 @@ SdrEndTextEditKind View::SdrEndTextEdit(bool bDontDeleteReally) SdrTextObj* pObj = GetTextEditObject(); + // RestoreDefaultText below puts the prompt back before the text edit ends, which leaves + // SdrObjEditView::SdrEndTextEdit nothing to record, so what the object holds is recorded here. + // The group keeps that in one step with the change of what represents a picture placeholder. + SdPage* pTextPage = pObj ? dynamic_cast(pObj->getSdrPageFromSdrObject()) : nullptr; + const bool bGroupUndo = IsUndoEnabled() && pTextPage + && pTextPage->GetPresObjKind(pObj) != PresObjKind::NONE; + std::unique_ptr pTextUndo; + if (bGroupUndo) + { + BegUndo(SvxResId(STR_UndoObjSetText), pObj->TakeObjNameSingul()); + std::unique_ptr pAction( + GetModel().GetSdrUndoFactory().CreateUndoObjectSetText(*pObj, 0)); + if (dynamic_cast(pAction.get())) + pTextUndo.reset(static_cast(pAction.release())); + } + bool bDefaultTextRestored = RestoreDefaultText( pObj ); const bool bSaveSetModifiedEnabled = mpDocSh && mpDocSh->IsEnableSetModified(); if (bDefaultTextRestored) @@ -795,6 +813,7 @@ SdrEndTextEditKind View::SdrEndTextEdit(bool bDontDeleteReally) SdrEndTextEditKind eKind = FmFormView::SdrEndTextEdit(bDontDeleteReally); + bool bTypedIntoPlaceholder = false; if( bDefaultTextRestored ) { if (bSaveSetModifiedEnabled) @@ -813,7 +832,18 @@ SdrEndTextEditKind View::SdrEndTextEdit(bool bDontDeleteReally) { SdrPage* pPage = pObj->getSdrPageFromSdrObject(); if( !pPage || !pPage->IsMasterPage() ) + { pObj->SetEmptyPresObj( false ); + bTypedIntoPlaceholder = true; + } + } + + // Before the swap below, so that undo restores the object first and its text afterwards. + if (pTextUndo && bDefaultTextRestored) + { + pTextUndo->AfterSetText(); + if (pTextUndo->IsDifferent()) + AddUndo(std::move(pTextUndo)); } GetViewShell()->GetViewShellBase().GetEventMultiplexer()->MultiplexEvent( @@ -822,6 +852,31 @@ SdrEndTextEditKind View::SdrEndTextEdit(bool bDontDeleteReally) if( pObj ) { + SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() ); + if( pPage ) + pPage->onEndTextEdit( pObj ); + + // A picture placeholder is represented by an outliner object as long as it holds text, the + // way a graphic object represents it once it holds a picture. Emptying it hands the + // representation back: RestoreDefaultText above has put the prompt in and marked the object + // empty, which is what says the text is gone. The view does the swap, so the mark follows + // and one undo step brings the text back with the object that held it. + SdrPageView* pPageView = GetSdrPageView(); + if (pPage && pPageView && pPage->GetPresObjKind(pObj) == PresObjKind::Graphic) + { + rtl::Reference xRepresentation; + if (bTypedIntoPlaceholder && pObj->GetObjIdentifier() == SdrObjKind::Graphic) + xRepresentation = pPage->MakePresObjText(*pObj); + else if (pObj->IsEmptyPresObj() + && pObj->GetObjIdentifier() == SdrObjKind::OutlineText) + xRepresentation = pPage->MakePresObjPlaceholder(*pObj); + + if (xRepresentation) + ReplaceObjectAtView(pObj, *pPageView, xRepresentation.get()); + } + + // After the swap, so that what listeners hear about the selection is the object the page + // ends up holding. if ( mpViewSh ) { mpViewSh->GetViewShellBase().GetDrawController()->FireSelectionChangeListener(); @@ -830,12 +885,11 @@ SdrEndTextEditKind View::SdrEndTextEdit(bool bDontDeleteReally) SfxLokHelper::notifyOtherViews(&mpViewSh->GetViewShellBase(), LOK_CALLBACK_VIEW_LOCK, "rectangle", "EMPTY"_ostr); } - - SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() ); - if( pPage ) - pPage->onEndTextEdit( pObj ); } + if (bGroupUndo) + EndUndo(); + return eKind; } @@ -1012,8 +1066,8 @@ bool View::IsMorphingAllowed() const ( nKind1 != SdrObjKind::Caption && nKind2 != SdrObjKind::Caption ) && DynCastE3dObject( pObj1 ) == nullptr && DynCastE3dObject( pObj2 ) == nullptr ) { - SfxItemSetFixed aSet1( mrDoc.GetPool() ); - SfxItemSetFixed aSet2( mrDoc.GetPool() ); + SfxItemSet aSet1(SfxItemSet::makeFixedSfxItemSet( mrDoc.GetPool() )); + SfxItemSet aSet2(SfxItemSet::makeFixedSfxItemSet( mrDoc.GetPool() )); aSet1.Put(pObj1->GetMergedItemSet()); aSet2.Put(pObj2->GetMergedItemSet()); diff --git a/sd/source/ui/view/sdview2.cxx b/sd/source/ui/view/sdview2.cxx index 304cbb762f25..db42b3cc118e 100644 --- a/sd/source/ui/view/sdview2.cxx +++ b/sd/source/ui/view/sdview2.cxx @@ -772,7 +772,7 @@ sal_Int8 View::ExecuteDrop( const ExecuteDropEvent& rEvt, pAction->SetDimColor(pInfo->maDimColor, pInfo->maDimColor); pAction->SetDimHide(pInfo->mbDimHide, pInfo->mbDimHide); pAction->SetSoundOn(pInfo->mbSoundOn, pInfo->mbSoundOn); - pAction->SetSound(pInfo->maSoundFile, pInfo->maSoundFile); + pAction->SetSound(pInfo->maSoundLink, pInfo->maSoundLink); pAction->SetPlayFull(pInfo->mbPlayFull, pInfo->mbPlayFull); pAction->SetClickAction(pInfo->meClickAction, eClickAction); pAction->SetBookmark(pInfo->GetBookmark(), aBookmark); diff --git a/sd/source/ui/view/sdview3.cxx b/sd/source/ui/view/sdview3.cxx index a2427453cd3f..009ad4f97206 100644 --- a/sd/source/ui/view/sdview3.cxx +++ b/sd/source/ui/view/sdview3.cxx @@ -841,8 +841,8 @@ bool View::InsertData( const TransferableDataHelper& rDataHelper, if( DynCastE3dObject( pPickObj2 ) && DynCastE3dObject( pObj ) ) { // handle 3D attribute in addition - SfxItemSetFixed aNewSet( mrDoc.GetPool() ); - SfxItemSetFixed aOldSet( mrDoc.GetPool() ); + SfxItemSet aNewSet(SfxItemSet::makeFixedSfxItemSet( mrDoc.GetPool() )); + SfxItemSet aOldSet(SfxItemSet::makeFixedSfxItemSet( mrDoc.GetPool() )); aOldSet.Put(pPickObj2->GetMergedItemSet()); aNewSet.Put( pObj->GetMergedItemSet() ); @@ -1636,7 +1636,12 @@ bool View::InsertData( const TransferableDataHelper& rDataHelper, { // tdf#139269 - prevent text pasting into readonly areas of master views if (!pPage) - pPage = static_cast(GetSdrPageView()->GetPage()); + { + // tdf#173370 - avoid unchecked GetSdrPageView() + SdrObject* pObj = GetTextEditObject(); + pPage = static_cast(pObj ? pObj->getSdrPageFromSdrObject() + : nullptr); + } if (pPage && pPage->IsMasterPage() && pOLV->IsReadOnly()) return false; diff --git a/sd/source/ui/view/sdview4.cxx b/sd/source/ui/view/sdview4.cxx index bc6c8cd1f33f..ba6a7d5e5b48 100644 --- a/sd/source/ui/view/sdview4.cxx +++ b/sd/source/ui/view/sdview4.cxx @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -84,9 +83,16 @@ namespace sd { SdrGrafObj* View::InsertGraphic( const Graphic& rGraphic, sal_Int8& rAction, const Point& rPos, SdrObject* pObj, ImageMap const * pImageMap ) { + // Ending the text edit can replace the object the caller named, and what leaves the page is + // held by the undo action alone - of which there is none while undo is off. + rtl::Reference xNamed(pObj); SdrEndTextEdit(); mnAction = rAction; + // Which leaves a caller that named the object holding one that is no longer on a page. + if (xNamed && !xNamed->IsInserted()) + pObj = GetPresentationObjectForGraphic(); + // Is there an object at the position rPos? rtl::Reference pNewGrafObj; SdrPageView* pPV = GetSdrPageView(); @@ -107,17 +113,23 @@ SdrGrafObj* View::InsertGraphic( const Graphic& rGraphic, sal_Int8& rAction, const bool bIsGraphic(dynamic_cast< const SdrGrafObj* >(pPickObj) != nullptr); + // A picture placeholder holding text is an outliner object, so it is neither a graphic object + // nor an empty one - but an image is still what it is a placeholder for. + SdPage* pPickPage + = pPickObj ? dynamic_cast(pPickObj->getSdrPageFromSdrObject()) : nullptr; + const bool bIsPicturePlaceholder + = pPickPage && pPickPage->GetPresObjKind(pPickObj) == PresObjKind::Graphic; + + // #121603# Do not use pObj, it may be NULL if (DND_ACTION_LINK == mnAction && pPickObj && pPV - && (bIsGraphic || (pPickObj->IsEmptyPresObj() && !bOnMaster))) // #121603# Do not use pObj, it may be NULL + && (bIsGraphic || ((pPickObj->IsEmptyPresObj() || bIsPicturePlaceholder) && !bOnMaster))) { // hit on SdrGrafObj with wanted new linked graphic (or PresObj placeholder hit) if( IsUndoEnabled() ) BegUndo(SdResId(STR_INSERTGRAPHIC)); - SdPage* pPage = static_cast( pPickObj->getSdrPageFromSdrObject() ); - if( bIsGraphic ) { // We fill the object with the Bitmap @@ -141,10 +153,10 @@ SdrGrafObj* View::InsertGraphic( const Graphic& rGraphic, sal_Int8& rAction, pNewGrafObj->SetEmptyPresObj(false); } - if (pPage && pPage->IsPresObj(pPickObj)) + if (pPickPage && pPickPage->IsPresObj(pPickObj)) { // Insert new PresObj into the list - pPage->InsertPresObj( pNewGrafObj.get(), PresObjKind::Graphic ); + pPickPage->InsertPresObj( pNewGrafObj.get(), PresObjKind::Graphic ); pNewGrafObj->SetUserCall(pPickObj->GetUserCall()); } @@ -171,7 +183,7 @@ SdrGrafObj* View::InsertGraphic( const Graphic& rGraphic, sal_Int8& rAction, EndUndo(); } - SfxItemSetFixed aSet(mpDocSh->GetPool()); + SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet(mpDocSh->GetPool())); aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP)); aSet.Put(XFillBitmapItem(rGraphic)); @@ -182,7 +194,7 @@ SdrGrafObj* View::InsertGraphic( const Graphic& rGraphic, sal_Int8& rAction, { Size aSizePixel = rGraphic.GetSizePixel(); - // create new object + // create new object Size aSize; if ( rGraphic.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel ) @@ -325,7 +337,11 @@ void View::InsertMediaURL( const OUString& rMediaURL, sal_Int8& rAction, #endif } - InsertMediaObj(realURL, rAction, rPos, rSize); + SdrMediaObj* pMediaObj = InsertMediaObj(realURL, rAction, rPos, rSize); + + // The user picked this media file, so its external reference is allowed without asking again. + if (bLink && pMediaObj) + pMediaObj->setLinkAllowed(true); } SdrMediaObj* View::InsertMediaObj( const OUString& rMediaURL, sal_Int8& rAction, @@ -451,7 +467,23 @@ IMPL_LINK_NOARG(View, DropInsertFileHdl, Timer *, void) { sal_Int8 nTempAction = ( aIter == maDropFileVector.begin() ) ? mnAction : 0; const bool bLink = ( ( nTempAction & DND_ACTION_LINK ) != 0 ); - SdrGrafObj* pGrafObj = InsertGraphic( aGraphic, nTempAction, maDropPos, nullptr, nullptr ); + SdrObject* pTargetObj = nullptr; + SdrPageView* pPageView = GetSdrPageView(); + bool bSingleInsert = (maDropFileVector.size() == 1); + + if (pPageView && bSingleInsert) + { + pTargetObj = PickObj(maDropPos, getHitTolLog(), pPageView); + + if (pTargetObj) + { + if (dynamic_cast(pTargetObj) || pTargetObj->IsClosedObj()) + nTempAction = DND_ACTION_LINK; + else + nTempAction = DND_ACTION_MOVE; + } + } + SdrGrafObj* pGrafObj = InsertGraphic( aGraphic, nTempAction, maDropPos, pTargetObj, nullptr ); if(pGrafObj && bLink) { pGrafObj->SetGraphicLink( aCurrentDropFile ); @@ -623,7 +655,7 @@ IMPL_LINK_NOARG(View, DropInsertFileHdl, Timer *, void) } /** - * Timer handler for Errorhandling at Drop() + * Timer handler for error handling at Drop() */ IMPL_LINK_NOARG(View, DropErrorHdl, Timer *, void) { diff --git a/sd/source/ui/view/sdview5.cxx b/sd/source/ui/view/sdview5.cxx index dcd9d93c7769..d50222f73926 100644 --- a/sd/source/ui/view/sdview5.cxx +++ b/sd/source/ui/view/sdview5.cxx @@ -76,6 +76,31 @@ SdrObject* View::GetSelectedSingleObject(SdPage const * pPage) return pRet; } +SdrObject* View::GetPresentationObjectForGraphic() +{ + if (SdrObject* pEmpty = GetEmptyPresentationObject(PresObjKind::Graphic)) + return pEmpty; + + // A picture placeholder that holds text is not empty and is not a graphic object, so the search + // above walks past it - yet an image is what it is a placeholder for. + SdPage* pPage = GetPage(); + if (!pPage || pPage->IsMasterPage()) + return nullptr; + + sd::ShapeList& rShapes = pPage->GetPresentationShapeList(); + rShapes.seekShape(0); + while (SdrObject* pShape = rShapes.getNextShape()) + { + if (pShape->GetObjIdentifier() == SdrObjKind::OutlineText + && pPage->GetPresObjKind(pShape) == PresObjKind::Graphic) + { + return pShape; + } + } + + return nullptr; +} + SdrObject* View::GetEmptyPresentationObject( PresObjKind eKind ) { SdPage* pPage = GetPage(); diff --git a/sd/source/ui/view/tabcontr.cxx b/sd/source/ui/view/tabcontr.cxx index ba2829459170..35c90b171bd4 100644 --- a/sd/source/ui/view/tabcontr.cxx +++ b/sd/source/ui/view/tabcontr.cxx @@ -147,7 +147,7 @@ void TabControl::StartDrag( sal_Int8, const Point& ) { bInternalMove = true; - // object is delete by reference mechanism + // object is deleted by reference mechanism ( new TabControl::TabControlTransferable( *this ) )->StartDrag( this, DND_ACTION_COPYMOVE ); } @@ -240,7 +240,7 @@ sal_Int8 TabControl::ExecuteDrop( const ExecuteDropEvent& rEvt ) if (pDoc->MoveSelectedPages(nPageNum)) { // 3. Switch to the copy that has been moved to its - // final destination. Use an asynchron slot call to + // final destination. Use an asynchronous slot call to // be executed after the still pending ones. if (nPageNumOfCopy >= nPageNum || (nPageNum == sal_uInt16(-1))) nPageNum += 1; diff --git a/sd/source/ui/view/viewshel.cxx b/sd/source/ui/view/viewshel.cxx index b0de518f7b3c..8196b288afca 100644 --- a/sd/source/ui/view/viewshel.cxx +++ b/sd/source/ui/view/viewshel.cxx @@ -80,6 +80,8 @@ #include +#include + #include #include #include @@ -439,7 +441,7 @@ void ViewShell::BroadcastContextForActivation(const bool bIsActivated) return {}; auto aResIdsIndirect - = xConfiguration->getResources({}, u"", drawing::framework::AnchorBindingMode_INDIRECT); + = xConfiguration->getResources({}, u"", sd::framework::AnchorBindingMode::INDIRECT); for (const rtl::Reference& rResId : aResIdsIndirect) { @@ -840,7 +842,12 @@ bool ViewShell::HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWi if (pData != nullptr) { - if (pData->IsMod1()) + const bool bZoomWithWheel = GetDoc() != nullptr + && GetDoc()->GetDocumentType() == DocumentType::Draw + && officecfg::Office::Draw::Layout::Display::ZoomWithMouseWheel::get(); + const bool bShouldZoom = pData->IsMod1() != bZoomWithWheel; + + if (bShouldZoom) { if( !GetDocSh()->IsUIActive() ) { @@ -871,8 +878,12 @@ bool ViewShell::HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWi double nScrollLines = pData->GetScrollLines(); if(IsPageFlipMode()) nScrollLines = COMMAND_WHEEL_PAGESCROLL; + const sal_uInt16 nScrollModifier + = bZoomWithWheel ? (pData->GetModifier() & ~KEY_MOD1) + : pData->GetModifier(); + constexpr CommandWheelMode eScrollMode = CommandWheelMode::SCROLL; CommandWheelData aWheelData( pData->GetDelta(),pData->GetNotchDelta(), - nScrollLines,pData->GetMode(),pData->GetModifier(),pData->IsHorz() ); + nScrollLines,eScrollMode,nScrollModifier,pData->IsHorz() ); CommandEvent aReWrite( rCEvt.GetMousePosPixel(),rCEvt.GetCommand(), rCEvt.IsMouseEvent(),static_cast(&aWheelData) ); bDone = pWin->HandleScrollCommand( aReWrite, diff --git a/sd/uiconfig/sdraw/menubar/menubar.xml b/sd/uiconfig/sdraw/menubar/menubar.xml index c3e7874085a4..fec460c3347c 100644 --- a/sd/uiconfig/sdraw/menubar/menubar.xml +++ b/sd/uiconfig/sdraw/menubar/menubar.xml @@ -22,11 +22,11 @@ - - + + - + @@ -39,7 +39,7 @@ - + @@ -48,8 +48,8 @@ - - + + @@ -66,7 +66,7 @@ - + @@ -74,7 +74,7 @@ - + @@ -85,21 +85,21 @@ - + - - + + - - + + - - + + @@ -111,8 +111,8 @@ - - + + @@ -120,100 +120,100 @@ - - + + - - + + - + - - + + - - - - - + + + + + - + - - - + + + - - - - - + + + + + - + - - - + + + - - - + + + - - - - + + + + - + - + - - - + + + - - + + - + - + - - - + + + - - + + - + - + - + @@ -227,48 +227,48 @@ - - + + - - - - + + + + - - - - - + + + + + - + - - - - - - + + + + + + - - + + - - - - - - + + + + + + - + - - + + - - + + @@ -276,7 +276,7 @@ - + @@ -291,39 +291,39 @@ - - + + - - - + + + - - - + + + - + - - - - + + + + - + - - - + + + - - + + - - + + - + @@ -338,16 +338,16 @@ - + - - + + - - + + - - + + @@ -355,8 +355,8 @@ - - + + @@ -364,74 +364,74 @@ - + - - + + - - - - + + + + - + - - - - + + + + - + - - + + - - - + + + - + - - + + - - - + + + - + - - - - - - - - - - - + + + + + + + + + + + - + - + - - - - - - - - + + + + + + + + @@ -440,188 +440,188 @@ - + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - - + + + - - - - - - + + + + + + - + - - - - + + + + - - + + - + - - - - - - - + + + + + + + - - + + - - - - + + + + - - + + - + - + - - - - + + + + - - + + - - - + + + - + - - + + - - + + - - + + - + - + - + - - + + - + - + - - + + - - + + - - + + - - - + + + - - + + - + - + - - - - + + + + - + - - + + - - - + + + - + - + @@ -629,7 +629,7 @@ - + @@ -637,21 +637,20 @@ - + - - + - + - + diff --git a/sd/uiconfig/sdraw/popupmenu/objectalign.xml b/sd/uiconfig/sdraw/popupmenu/objectalign.xml index 446bd974bed3..e8c64a99f7c7 100644 --- a/sd/uiconfig/sdraw/popupmenu/objectalign.xml +++ b/sd/uiconfig/sdraw/popupmenu/objectalign.xml @@ -8,6 +8,8 @@ * --> + + @@ -15,6 +17,4 @@ - - diff --git a/sd/uiconfig/sdraw/statusbar/statusbar.xml b/sd/uiconfig/sdraw/statusbar/statusbar.xml index e89d1abc1f2e..34fb4bab1ec0 100644 --- a/sd/uiconfig/sdraw/statusbar/statusbar.xml +++ b/sd/uiconfig/sdraw/statusbar/statusbar.xml @@ -18,12 +18,12 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . --> + - diff --git a/sd/uiconfig/sdraw/toolbar/alignmentbar.xml b/sd/uiconfig/sdraw/toolbar/alignmentbar.xml index 91eba5f2a09c..b3141366d6b1 100644 --- a/sd/uiconfig/sdraw/toolbar/alignmentbar.xml +++ b/sd/uiconfig/sdraw/toolbar/alignmentbar.xml @@ -18,6 +18,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . --> + + @@ -25,5 +27,4 @@ - - \ No newline at end of file + diff --git a/sd/uiconfig/sdraw/toolbar/drawingobjectbar.xml b/sd/uiconfig/sdraw/toolbar/drawingobjectbar.xml index ba71c63c6a28..44f95dc99852 100644 --- a/sd/uiconfig/sdraw/toolbar/drawingobjectbar.xml +++ b/sd/uiconfig/sdraw/toolbar/drawingobjectbar.xml @@ -22,6 +22,8 @@ + + @@ -29,7 +31,6 @@ - diff --git a/sd/uiconfig/sdraw/toolbar/graphicobjectbar.xml b/sd/uiconfig/sdraw/toolbar/graphicobjectbar.xml index fa7f90e05700..bebf9652b3d2 100644 --- a/sd/uiconfig/sdraw/toolbar/graphicobjectbar.xml +++ b/sd/uiconfig/sdraw/toolbar/graphicobjectbar.xml @@ -22,6 +22,8 @@ + + @@ -29,7 +31,6 @@ - diff --git a/sd/uiconfig/sdraw/ui/bulletsandnumbering.ui b/sd/uiconfig/sdraw/ui/bulletsandnumbering.ui index 5c3d110c915d..93c6e68dc872 100644 --- a/sd/uiconfig/sdraw/ui/bulletsandnumbering.ui +++ b/sd/uiconfig/sdraw/ui/bulletsandnumbering.ui @@ -150,7 +150,7 @@
      - reset + reset ok cancel help diff --git a/sd/uiconfig/sdraw/ui/copydlg.ui b/sd/uiconfig/sdraw/ui/copydlg.ui index 1594298f92e0..d5b15d471215 100644 --- a/sd/uiconfig/sdraw/ui/copydlg.ui +++ b/sd/uiconfig/sdraw/ui/copydlg.ui @@ -440,7 +440,7 @@ 0 none - + True False @@ -477,6 +477,21 @@ 1 + + + True + False + Inter_polation: + True + end + 0 + 0 + + + 0 + 2 + + @@ -523,6 +538,80 @@ 1 + + + True + False + vertical + + + _RGB + True + True + False + True + True + True + + + Creates intermediate colors by linear interpolation of each red, green, and blue component. + + + + + False + True + 0 + + + + + HSL _increasing + True + True + False + True + True + rgb + + + Creates intermediate colors in a clockwise direction using the HSL color wheel. + + + + + False + True + 1 + + + + + HSL _decreasing + True + True + False + True + True + rgb + + + Creates intermediate colors counter-clockwise using the HSL color wheel. + + + + + False + True + 2 + + + + + 1 + 2 + + diff --git a/sd/uiconfig/sdraw/ui/drawchardialog.ui b/sd/uiconfig/sdraw/ui/drawchardialog.ui index 6dfbc15747d5..5f1de9de17b7 100644 --- a/sd/uiconfig/sdraw/ui/drawchardialog.ui +++ b/sd/uiconfig/sdraw/ui/drawchardialog.ui @@ -103,7 +103,7 @@ - reset + reset ok cancel help diff --git a/sd/uiconfig/sdraw/ui/drawpagedialog.ui b/sd/uiconfig/sdraw/ui/drawpagedialog.ui index 95a0d22b277d..01417a6282a3 100644 --- a/sd/uiconfig/sdraw/ui/drawpagedialog.ui +++ b/sd/uiconfig/sdraw/ui/drawpagedialog.ui @@ -104,7 +104,7 @@
      - reset + reset ok cancel help diff --git a/sd/uiconfig/sdraw/ui/drawparadialog.ui b/sd/uiconfig/sdraw/ui/drawparadialog.ui index 1c98079d3de6..b8553b45c67c 100644 --- a/sd/uiconfig/sdraw/ui/drawparadialog.ui +++ b/sd/uiconfig/sdraw/ui/drawparadialog.ui @@ -103,7 +103,7 @@
      - reset + reset ok cancel help diff --git a/sd/uiconfig/sdraw/ui/drawprtldialog.ui b/sd/uiconfig/sdraw/ui/drawprtldialog.ui index ca699c11480e..873277e8d985 100644 --- a/sd/uiconfig/sdraw/ui/drawprtldialog.ui +++ b/sd/uiconfig/sdraw/ui/drawprtldialog.ui @@ -104,7 +104,7 @@
      - reset + reset ok cancel help diff --git a/sd/uiconfig/sdraw/ui/notebookbar.ui b/sd/uiconfig/sdraw/ui/notebookbar.ui index 46e55548fca9..855746c470d4 100644 --- a/sd/uiconfig/sdraw/ui/notebookbar.ui +++ b/sd/uiconfig/sdraw/ui/notebookbar.ui @@ -1,2333 +1,2346 @@ - + True - False + False True - False - .uno:ExtrusionToggle + False + .uno:ExtrusionToggle True - False + False True - False - .uno:ExtrusionTiltDown + False + .uno:ExtrusionTiltDown True - False - .uno:ExtrusionTiltUp + False + .uno:ExtrusionTiltUp True - False - .uno:ExtrusionTiltLeft + False + .uno:ExtrusionTiltLeft True - False - .uno:ExtrusionTiltRight + False + .uno:ExtrusionTiltRight True - False + False True - False - .uno:Window3D + False + .uno:Window3D True - False + False True - False - .uno:NameGroup + False + .uno:NameGroup True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - AddonCommand + False + AddonCommand True - False + False True - False - .uno:ExtensionManager + False + .uno:ExtensionManager True - False + False True - False - .uno:ChangeBezier + False + .uno:ChangeBezier True - False - .uno:ChangePolygon + False + .uno:ChangePolygon True - False - .uno:convert_to_contour + False + .uno:convert_to_contour True - False - .uno:ConvertInto3D + False + .uno:ConvertInto3D True - False - .uno:ConvertInto3DLatheFast + False + .uno:ConvertInto3DLatheFast True - False - .uno:ConvertIntoBitmap + False + .uno:ConvertIntoBitmap True - False - .uno:ConvertIntoMetaFile + False + .uno:ConvertIntoMetaFile True - False + False True - False - .uno:ToggleObjectBezierMode + False + .uno:ToggleObjectBezierMode True - False - .uno:ToggleObjectRotateMode + False + .uno:ToggleObjectRotateMode True - False - .uno:MirrorVert + False + .uno:MirrorVert True - False - .uno:MirrorHorz + False + .uno:MirrorHorz True - False - .uno:AdvancedMode + False + .uno:AdvancedMode True - False + False True - False - .uno:Combine + False + .uno:Combine True - False - .uno:Dismantle + False + .uno:Dismantle True - False - .uno:Merge + False + .uno:Merge True - False - .uno:Substract + False + .uno:Substract True - False - .uno:Intersect + False + .uno:Intersect True - False - .uno:EqualizeWidth + False + .uno:EqualizeWidth True - False - .uno:EqualizeHeight + False + .uno:EqualizeHeight True - False - .uno:Connect + False + .uno:Connect True - False - .uno:Break + False + .uno:Break True - False + False True - False - .uno:CopyObjects + False + .uno:CopyObjects True - False - .uno:Morphing + False + .uno:Morphing True - False + False True - False - .uno:ChangeBezier + False + .uno:ChangeBezier True - False - .uno:ChangePolygon + False + .uno:ChangePolygon True - False - .uno:convert_to_contour + False + .uno:convert_to_contour True - False - .uno:ConvertInto3D + False + .uno:ConvertInto3D True - False - .uno:ConvertInto3DLatheFast + False + .uno:ConvertInto3DLatheFast True - False - .uno:ConvertIntoBitmap + False + .uno:ConvertIntoBitmap True - False - .uno:ConvertIntoMetaFile + False + .uno:ConvertIntoMetaFile True - False + False True - False - .uno:NameGroup + False + .uno:NameGroup True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - .uno:InsertDateFieldFix + False + .uno:InsertDateFieldFix True - False - .uno:InsertDateFieldVar + False + .uno:InsertDateFieldVar True - False - .uno:InsertTimeFieldFix + False + .uno:InsertTimeFieldFix True - False - .uno:InsertTimeFieldVar + False + .uno:InsertTimeFieldVar True - False + False True - False - .uno:InsertAuthorField + False + .uno:InsertAuthorField True - False - .uno:InsertSlideField + False + .uno:InsertSlideField True - False - .uno:InsertSlideTitleField + False + .uno:InsertSlideTitleField True - False - .uno:InsertSlidesField + False + .uno:InsertSlidesField True - False - .uno:InsertFileField + False + .uno:InsertFileField True - False + False True - False - .uno:AddDirect + False + .uno:AddDirect True - False - .uno:RecentFileList + False + .uno:RecentFileList True - False - .uno:CloseDoc + False + .uno:CloseDoc True - False + False True - False - .uno:Save + False + .uno:Save True - False - .uno:SaveAs + False + .uno:SaveAs True - False - .uno:SaveAsRemote + False + .uno:SaveAsRemote True - False - .uno:SaveACopy + False + .uno:SaveACopy True - False + False True - False - .uno:Reload + False + .uno:Reload True - False + False True - False - .uno:ExportTo + False + .uno:ExportTo True - False - .uno:ExportToPDF + False + .uno:ExportToPDF True - False + False True - False - .uno:SendMail + False + .uno:SendMail True - False - .uno:SendMailDocAsPDF + False + .uno:SendMailDocAsPDF True - False - .uno:SendViaBluetooth + False + .uno:SendViaBluetooth True - False + False True - False - .uno:WebHtml + False + .uno:WebHtml True - False - .uno:Print + False + .uno:Print - False - False - .uno:PrintDefault + False + .uno:PrintDefault True - False - .uno:PrinterSetup + False + .uno:PrinterSetup True - False + False True - False - .uno:Signature + False + .uno:Signature True - False - .uno:SignPDF + False + .uno:SignPDF True - False - .uno:SetDocumentProperties + False + .uno:SetDocumentProperties True - False + False True - False - .uno:Quit + False + .uno:Quit True - False + False True - False - .uno:Label + False + .uno:Label True - False - .uno:Edit + False + .uno:Edit True - False - .uno:CheckBox + False + .uno:CheckBox True - False - .uno:RadioButton + False + .uno:RadioButton True - False - .uno:ListBox + False + .uno:ListBox True - False - .uno:ComboBox + False + .uno:ComboBox True - False + False True - False - .uno:Pushbutton + False + .uno:Pushbutton True - False - .uno:Imagebutton + False + .uno:Imagebutton True - False + False True - False - .uno:FormattedField + False + .uno:FormattedField True - False + False True - False - .uno:DateField + False + .uno:DateField True - False - .uno:TimeField + False + .uno:TimeField True - False - .uno:NumericField + False + .uno:NumericField True - False - .uno:CurrencyField + False + .uno:CurrencyField True - False - .uno:PatternField + False + .uno:PatternField True - False + False True - False - .uno:ImageControl + False + .uno:ImageControl True - False - .uno:FileControl + False + .uno:FileControl True - False + False True - False - .uno:Grid + False + .uno:Grid True - False - .uno:NavigationBar + False + .uno:NavigationBar True - False + False True - False - .uno:HelpIndex + False + .uno:HelpIndex True - False - .uno:ExtendedHelp + False + .uno:ExtendedHelp True - False - .uno:Documentation + False + .uno:Documentation True - False + False True - False - .uno:QuestionAnswers - - - - - True - False - .uno:SendFeedback + False + .uno:QuestionAnswers True - False + False True - False - .uno:SafeMode + False + .uno:SafeMode True - False - .uno:GetInvolved + False + .uno:GetInvolved True - False + False True - False - .uno:Donation + False + .uno:Donation True - False + False True - False - .uno:ShowLicense + False + .uno:ShowLicense True - False + False True - False - .uno:About + False + .uno:About True - False + False True - False - .uno:SelectAll + False + .uno:SelectAll True - False + False True - False - vnd.sun.star.findbar:FocusToFindbar + False + vnd.sun.star.findbar:FocusToFindbar True - False - .uno:SearchDialog + False + .uno:SearchDialog True - False - .uno:RestoreEditingView + False + .uno:RestoreEditingView True - False + False True - False - .uno:Crop + False + .uno:Crop True - False - .uno:ExternalEdit + False + .uno:ExternalEdit True - False - .uno:ChangePicture + False + .uno:ChangePicture True - False - .uno:CompressGraphic + False + .uno:CompressGraphic True - False - .uno:SaveGraphic + False + .uno:SaveGraphic True - False + False True - False - .uno:OriginalSize + False + .uno:OriginalSize True - False - .uno:ImageMapDialog + False + .uno:ImageMapDialog True - False + False True - False - .uno:NameGroup + False + .uno:NameGroup True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - .uno:AnimationEffects + False + .uno:AnimationEffects True - False + False True - False - .uno:PhotoAlbumDialog + False + .uno:PhotoAlbumDialog True - False - .uno:AnimationObjects + False + .uno:AnimationObjects True - False + False True - False - .uno:Gallery + False + .uno:Gallery True - False - .uno:TwainSelect + False + .uno:TwainSelect True - False - .uno:InsertAVMedia + False + .uno:InsertAVMedia True - False + False True - False - .uno:InsertQrCode + False + .uno:InsertQrCode True - False - .uno:InsertObject + False + .uno:InsertObject True - False - .uno:ImportFromFile + False + .uno:ImportFromFile True - False - .uno:InsertMath + False + .uno:InsertMath True - False + False True - False - .uno:Text + False + .uno:Text True - False - .uno:VerticalText + False + .uno:VerticalText True - False - .uno:FontworkGalleryFloater + False + .uno:FontworkGalleryFloater True - False + False True - False - .uno:HyperlinkDialog + False + .uno:HyperlinkDialog True - False - .uno:CapturePoint + False + .uno:CapturePoint True - False + False True - False - .uno:InsertPageField + False + .uno:InsertPageField True - False - .uno:InsertPagesField + False + .uno:InsertPagesField True - False - .uno:HeaderAndFooter + False + .uno:HeaderAndFooter True - False + False True - False - .uno:InsertMasterPage + False + .uno:InsertMasterPage True - False - .uno:RenameMasterPage + False + .uno:RenameMasterPage True - False - .uno:DeleteMasterPage + False + .uno:DeleteMasterPage True - False - .uno:CloseMasterView + False + .uno:CloseMasterView True - False + False True - False - .uno:AVMediaPlayer + False + .uno:AVMediaPlayer True - False + False True - False - .uno:NameGroup + False + .uno:NameGroup True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - .uno:ChainFrames + False + .uno:ChainFrames True - False - .uno:UnhainFrames + False + .uno:UnhainFrames True - False + False True - False - .uno:NameGroup + False + .uno:NameGroup True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False - .uno:FrameDialog + False + .uno:FrameDialog True - False + False True - False - .uno:InsertSlide + False + .uno:InsertSlide True - False - .uno:DuplicateSlide + False + .uno:DuplicateSlide True - False - .uno:DeleteSlide + False + .uno:DeleteSlide True - False + False True - False - .uno:ModifyPage + False + .uno:ModifyPage True - False - .uno:SlideSetup + False + .uno:SlideSetup True - False - .uno:SelectBackground + False + .uno:SelectBackground True - False + False True - False - .uno:InsertMasterPage + False + .uno:InsertMasterPage True - False - .uno:DeleteMasterPage + False + .uno:DeleteMasterPage True - False + False True - False - .uno:DrawingLayout + False + .uno:DrawingLayout True - False + False True - False - .uno:HideSlide + False + .uno:HideSlide True - False - .uno:ShowSlide + False + .uno:ShowSlide True - False - .uno:RenameSlide + False + .uno:RenameSlide True - False + False True - False - .uno:ImportSlideFromFile + False + .uno:ImportSlideFromFile True - False - .uno:SummaryPage + False + .uno:SummaryPage True - False - .uno:ExpandPage + False + .uno:ExpandPage True - False + False True - False - .uno:MoveSlideUp + False + .uno:MoveSlideUp True - False - .uno:MoveSlideDown + False + .uno:MoveSlideDown True - False + False True - False - .uno:InsertFootnoteDialog + False + .uno:InsertFootnoteDialog True - False + False True - False - .uno:AddressBookSource + False + .uno:AddressBookSource True - False + False True - False - .uno:UpdateAll + False + .uno:UpdateAll True - False - .uno:Repaginate + False + .uno:Repaginate True - False - .uno:UpdateFields + False + .uno:UpdateFields True - False - .uno:UpdateAllIndexes + False + .uno:UpdateAllIndexes True - False - .uno:UpdateCurIndex + False + .uno:UpdateCurIndex True - False - .uno:UpdateAllLinks + False + .uno:UpdateAllLinks True - False - .uno:UpdateCharts + False + .uno:UpdateCharts True - False - .uno:CalculateSel + False + .uno:CalculateSel True - False + False True - False - .uno:SpellDialog + False + .uno:SpellDialog True - False - .uno:SpellOnline + False + .uno:SpellOnline True - False - .uno:ThesaurusDialog + False + .uno:ThesaurusDialog True - False + False True - False - .uno:SetLanguageAllTextMenu + False + .uno:SetLanguageAllTextMenu True - False - .uno:Hyphenation + False + .uno:Hyphenation True - False - .uno:ChineseConversion + False + .uno:ChineseConversion True - False - .uno:HangulHanjaConversion + False + .uno:HangulHanjaConversion True - False - .uno:MoreDictionaries + False + .uno:MoreDictionaries True - False + False True - False - .uno:AutoFormat + False + .uno:AutoFormat True - False - .uno:ObjectAlign + False + .uno:ObjectAlign True - False + False True - False - .uno:InsertRowDialog + False + .uno:InsertRowDialog True - False - .uno:InsertColumnDialog + False + .uno:InsertColumnDialog True - False + False True - False - .uno:SetRowHeight + False + .uno:SetRowHeight True - False - .uno:SetOptimalRowHeight + False + .uno:SetOptimalRowHeight True - False - .uno:DistributeRows + False + .uno:DistributeRows True - False - .uno:SetColumnWidth + False + .uno:SetColumnWidth True - False - .uno:SetOptimalColumnWidth + False + .uno:SetOptimalColumnWidth True - False - .uno:DistributeColumns + False + .uno:DistributeColumns True - False + False True - False - .uno:Protect + False + .uno:Protect True - False - .uno:UnsetCellsReadOnly + False + .uno:UnsetCellsReadOnly True - False + False True - False - .uno:HeadingRowsRepeat + False + .uno:HeadingRowsRepeat True - False - .uno:RowSplit + False + .uno:RowSplit True - False + False True - False - .uno:ConvertTextToTable + False + .uno:ConvertTextToTable True - False - .uno:ConvertTableToText + False + .uno:ConvertTableToText True - False + False True - False - .uno:TableSort + False + .uno:TableSort True - False + False True - False - .uno:MergeTable + False + .uno:MergeTable True - False - .uno:TableNumberRecognition + False + .uno:TableNumberRecognition True - False - .uno:TableBoundaries + False + .uno:TableBoundaries True - False + False True - False - .uno:Shadowed + False + .uno:Shadowed True - False - .uno:OutlineFont + False + .uno:OutlineFont True - False - .uno:Overline + False + .uno:Overline True - False + False True - False - .uno:ChangeCaseToUpper + False + .uno:ChangeCaseToUpper True - False - .uno:ChangeCaseToLower + False + .uno:ChangeCaseToLower True - False - .uno:ChangeCaseRotateCase + False + .uno:ChangeCaseRotateCase True - False + False True - False - .uno:ChangeCaseToSentenceCase + False + .uno:ChangeCaseToSentenceCase True - False - .uno:ChangeCaseToTitleCase + False + .uno:ChangeCaseToTitleCase True - False - .uno:ChangeCaseToToggleCase + False + .uno:ChangeCaseToToggleCase True - False + False True - False - .uno:InsertNonBreakingSpace + False + .uno:InsertNonBreakingSpace True - False - .uno:InsertHardHyphen + False + .uno:InsertHardHyphen True - False - .uno:InsertSoftHyphen + False + .uno:InsertSoftHyphen True - False - .uno:InsertZWSP + False + .uno:InsertZWSP True - False - .uno:InsertWJ + False + .uno:InsertWJ True - False - .uno:InsertLRM + False + .uno:InsertLRM True - False - .uno:InsertRLM + False + .uno:InsertRLM True - False + False True - False - .uno:FontDialog + False + .uno:FontDialog True - False - .uno:ParagraphDialog + False + .uno:ParagraphDialog True - False + False True - False - .uno:ParaLeftToRight + False + .uno:ParaLeftToRight True - False - .uno:ParaRightToLeft + False + .uno:ParaRightToLeft True - False + False True - False - .uno:RunMacro + False + .uno:RunMacro True - False - .uno:MacroRecorder + False + .uno:MacroRecorder True - False - .uno:BasicIDEAppear + False + .uno:BasicIDEAppear True - False - .uno:MacroOrganizer?TabId:short=1 + False + .uno:MacroOrganizer?TabId:short=1 True - False - .uno:MacroSignature + False + .uno:MacroSignature True - False - .uno:ScriptOrganizer + False + .uno:ScriptOrganizer True - False - .uno:DevelopmentToolsDockingWindow + False + .uno:DevelopmentToolsDockingWindow True - False + False True - False - .uno:ImageMapDialog + False + .uno:ImageMapDialog True - False - .uno:BmpMask + False + .uno:BmpMask True - False - .uno:AVMediaPlayer + False + .uno:AVMediaPlayer True - False + False True - False - .uno:ViewDataSourceBrowser + False + .uno:ViewDataSourceBrowser True - False - .uno:OpenXMLFilterSettings + False + .uno:OpenXMLFilterSettings True - False + False True - False - .uno:ExtensionManager + False + .uno:ExtensionManager True - False - .uno:OptionsTreeDialog + False + .uno:OptionsTreeDialog True - False + False True - False - .uno:PageMode + False + .uno:PageMode True - False - .uno:MasterPage + False + .uno:MasterPage True - False + False True - False - .uno:Menubar + False + .uno:Menubar True - False - .uno:Sidebar + False + .uno:Sidebar True - False - .uno:StatusBarVisible + False + .uno:StatusBarVisible True - False + False - + True - False - .uno:LeftPaneImpress + False + .uno:LeftPaneDraw True - False - .uno:ToggleTabBarVisibility + False + .uno:ToggleTabBarVisibility True - False - .uno:ShowRuler + False + .uno:ShowRuler True - False + False True - False - .uno:GridVisible + False + .uno:GridVisible True - False - .uno:GridUse + False + .uno:GridUse True - False + False True - False - .uno:HelplinesVisible + False + .uno:HelplinesVisible True - False - .uno:HelplinesUse + False + .uno:HelplinesUse True - False + False True - False - .uno:OutputQualityColor + False + .uno:OutputQualityColor True - False - .uno:OutputQualityGrayscale + False + .uno:OutputQualityGrayscale True - False + False True - False - .uno:Zoom50Percent + False + .uno:Zoom50Percent True - False - .uno:Zoom75Percent + False + .uno:Zoom75Percent True - False - .uno:Zoom100Percent + False + .uno:Zoom100Percent True - False - .uno:Zoom150Percent + False + .uno:Zoom150Percent True - False - .uno:Zoom200Percent + False + .uno:Zoom200Percent True - False + False True - False - .uno:ZoomPrevious + False + .uno:ZoomPrevious True - False - .uno:ZoomNext + False + .uno:ZoomNext True - False - .uno:ZoomObjects + False + .uno:ZoomObjects - - True - False - cmd/lc_changebezier.png - - - True - False - cmd/lc_insertfieldctrl.png - + True - False + False True - False + False + 6 + 6 + 6 + 6 vertical True - True + True True - + True - False + False center True - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + New + + + + + + + + + + 0 + 2 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:AddDirect + .uno:AddDirect False @@ -2336,11 +2349,53 @@ - False - True - 0 + 0 + 0 + 2 + + + True + False + both + False + 3 + center + True + + + True + .uno:NewDoc + True + + + False + True + + + + + 1 + 0 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -2349,75 +2404,179 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Document + + + + + + + + + + 0 + 2 + 4 + + + + + True + False center - vertical + True + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:NewDoc - True - - - False - True - - + .uno:Open + True False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:SaveAsTemplate - True - - - False - True - - - - - False - True - 1 + True - False - True - 1 + 0 + 0 + 2 - + + + True + False + center + True + both + False + 3 + + + True + .uno:Save + True + + + False + True + + + + + 1 + 0 + 2 + + + + + True + False + center + 3 + True + both + False + 3 + + + True + .uno:ExportTo + True + + + False + True + + + + + 2 + 0 + 2 + + + + + True + False + both-horiz + False + + + True + .uno:ExportDirectToPDF + True + + + False + True + + + + + 3 + 0 + + + + + True + False + vertical + + + 4 + 0 + 3 + + + + + True + False + both-horiz + + + True + .uno:SendMail + True + + + False + True + + + + + 3 + 1 + + + + + False @@ -2426,40 +2585,30 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True + False center True - both - False + both + False 3 - + True - .uno:Open - True + .uno:Print + True False @@ -2468,11 +2617,93 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + end + True + Print + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + both-horiz + False + + + True + .uno:PrintDefault + True + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:WebHtml + True + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -2481,40 +2712,30 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True + False center True - both - False + both + False 3 - + True - .uno:Save - True + .uno:SetDocumentProperties + True False @@ -2523,11 +2744,93 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:Signature + True + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:SignPDF + True + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False + end + True + Properties + + + + + + + + + + 0 + 2 + 3 + + + + + False @@ -2535,402 +2838,6 @@ 3 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ExportTo - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ExportDirectToPDF - True - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:SendMail - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Print - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:PrintDefault - True - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:WebHtml - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SetDocumentProperties - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:Signature - True - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:SignPDF - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - True @@ -2941,30 +2848,30 @@ True - False + False end center True True - False + False center True vertical True - True + True end True - icons - False + icons + False 1 True - .uno:CloseDoc + .uno:CloseDoc False @@ -2981,16 +2888,16 @@ True - True + True end True - icons - False + icons + False 1 True - .uno:HelpIndex + .uno:HelpIndex False @@ -3014,23 +2921,23 @@ True - False + False center 5 True vertical - _File + _File True - True - False - False + True + False + False end center True none - True + True False @@ -3040,16 +2947,16 @@ - _Help + _Help True - True - False - False + True + False + False end center True none - True + True False @@ -3068,72 +2975,80 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - True - False - ~File - True + False + ~File + True - False + False - + True - False + False center True - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Clipboard + + + + + + + + + + 0 + 2 + 2 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:Paste + .uno:Paste False @@ -3142,70 +3057,70 @@ - False - True - 0 + 0 + 0 + 2 - + True - False - center - vertical + False + both-horiz + False - + True - True - both-horiz - False - - - True - .uno:Cut - - - False - True - - + .uno:Cut False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Copy - - - False - True - - - - - False - True - 1 + True - False - True - 1 + 1 + 0 + + + True + False + both-horiz + False + + + True + .uno:Copy + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -3214,146 +3129,124 @@ - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Page + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - False - center - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:FormatPaintbrush - - - False - True - - - - - False - True - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:SetDefault - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - 5 - 5 + False vertical - False - True - 5 - 0 + 2 + 0 + 3 - + True - True + False center True - both - False + both + False 3 - + True - .uno:DesignerDialog + .uno:InsertPage - True + False True - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:DuplicatePage + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:DrawingLayout + + + False + True + + + + + 1 + 1 + + + + + False @@ -3362,74 +3255,317 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Font + + + + + + + + + + 0 + 2 + 5 + + + + + True + False center True - vertical + both-horiz + False - + True - True - text - False - - - True - .uno:FormatLine - - - True - True - - + .uno:FormatPaintbrush False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 + True - False - True - 2 + 0 + 0 - + + + True + False + center + True + both-horiz + False + + + True + .uno:SetDefault + + + False + True + + + + + 0 + 1 + + + + + True + False + center + True + + + True + True + .uno:CharFontName + + + True + True + + + + + 1 + 0 + 2 + + + + + True + False + center + + + True + .uno:FontHeight + + + True + True + + + + + 3 + 0 + + + + + True + False + center + icons + False + + + True + .uno:Bold + + + False + True + + + + + True + .uno:Italic + + + False + True + + + + + True + .uno:Underline + + + False + True + + + + + True + .uno:Strikeout + + + False + True + + + + + .uno:Shadowed + + + False + True + + + + + 1 + 1 + + + + + True + False + center + icons + False + + + True + .uno:SubScript + + + False + True + + + + + True + .uno:SuperScript + + + False + True + + + + + 2 + 1 + + + + + True + False + center + icons + False + + + True + .uno:Spacing + + + False + False + + + + + True + .uno:CharBackColor + + + False + False + + + + + True + .uno:Color + + + False + False + + + + + 3 + 1 + 2 + + + + + True + False + center + icons + False + + + True + .uno:Grow + + + False + True + + + + + True + .uno:Shrink + + + False + True + + + + + 4 + 0 + + + + + True + False + vertical + + + 5 + 0 + 3 + + + + + False @@ -3438,128 +3574,278 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Paragraph + + + + + + + + + + 0 + 2 + 3 + + + + + True + False vertical + + + 3 + 0 + 3 + + + + + True + False + center + 6 + icons + False - + True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - + .uno:DefaultBullet False - True - 0 + True - + True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - + .uno:DefaultNumbering - True - True - 1 + False + True - False - True - 3 + 0 + 0 - + + + True + False + center + 6 + icons + False + + + True + center + True + .uno:StartPara + + + False + True + + + + + True + center + True + .uno:CenterPara + + + False + True + + + + + True + center + True + .uno:EndPara + + + False + True + + + + + True + center + True + .uno:JustifyPara + + + False + True + + + + + 0 + 1 + + + + + True + False + icons + False + + + True + center + True + .uno:IncrementIndent + + + False + True + + + + + True + center + True + .uno:DecrementIndent + + + False + True + + + + + True + center + True + .uno:HangingIndent + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:ParaLeftToRight + + + False + True + + + + + True + .uno:ParaRightToLeft + + + False + True + + + + + 2 + 0 + + + + + True + False + icons + False + + + True + end + .uno:LineSpacing + + + False + False + + + + + True + center + True + .uno:ParaspaceIncrease + + + False + True + + + + + True + center + True + .uno:ParaspaceDecrease + + + False + True + + + + + 1 + 1 + + + + + + + + False @@ -3567,881 +3853,6 @@ 3 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Text - - - False - True - - - - - True - .uno:VerticalText - - - False - True - - - - - False - True - 1 - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - icons - False - - - True - .uno:Line - - - True - True - - - - - True - .uno:Polygon_Unfilled - - - False - True - - - - - True - .uno:Bezier_Unfilled - - - False - True - - - - - True - .uno:ArrowsToolbox - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:BasicShapes.rectangle - - - True - True - - - - - True - .uno:BasicShapes.ellipse - - - True - True - - - - - True - .uno:DrawCaption - - - True - True - - - - - True - .uno:LineToolbox - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - - - True - .uno:ArrowShapes - - - True - True - - - - - True - .uno:ConnectorToolbox - - - True - True - - - - - False - True - 0 - - - - - True - True - - - True - .uno:FlowChartShapes - - - True - True - - - - - True - .uno:Objects3DToolbox - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - - - True - .uno:BasicShapes - - - True - True - - - - - True - .uno:SymbolShapes - - - True - True - - - - - False - True - 0 - - - - - True - True - - - True - .uno:StarShapes - - - True - True - - - - - True - .uno:CalloutShapes - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SelectObject - - - True - True - - - - - False - True - 1 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:GridVisible - - - False - True - - - - - True - .uno:HelplinesVisible - - - False - True - - - - - True - .uno:HelplinesMove - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:GridUse - - - False - True - - - - - True - .uno:HelplinesUse - - - False - True - - - - - True - .uno:SnapFrame - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:CapturePoint - - - False - True - - - - - True - .uno:GlueInsertPoint - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:SnapPoints - - - False - True - - - - - True - .uno:SnapBorder - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - center - .uno:InsertGraphic - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - center - .uno:InsertPage - - - False - True - - - - - True - center - .uno:InsertObjectChart - - - False - True - - - - - True - .uno:InsertTable - - - False - False - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ObjectAlign - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:ObjectPosition - - - False - True - - - - - True - .uno:DistributeSelection - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 12 - - True @@ -4452,29 +3863,29 @@ True - False + False end center True True - False + False center True vertical - _Home + _Home True - True - False - False + True + False + False end center True none - True + True False @@ -4485,17 +3896,17 @@ True - True + True end center True - icons - False + icons + False 1 True - .uno:ZoomMode + .uno:ZoomMode False @@ -4506,7 +3917,7 @@ True center - vnd.sun.star.findbar:FocusToFindbar + vnd.sun.star.findbar:FocusToFindbar False @@ -4531,30 +3942,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - - - 1 @@ -4563,9 +3954,9 @@ True - False - ~Home - True + False + ~Home + True + + + True + False + both-horiz + False + + + True + .uno:InsertObjectChart + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:InsertMath + + + False + True + + + + + 1 + 1 + + + + + False @@ -4703,39 +4228,62 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Graphic + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:InsertTable + .uno:InsertGraphic False @@ -4744,11 +4292,58 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:Gallery + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:InsertAVMedia + + + False + True + + + + + 1 + 1 + + + + + False @@ -4757,73 +4352,152 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Text + + + + + + + + + + 0 + 2 + 3 + + + + + True + False vertical + + + 3 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:InsertObjectChart - - - False - True - - + .uno:CharmapControl False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:InsertObject - - - False - True - - - - - False - True - 1 + True - False - True - 2 + 2 + 0 + 2 - + + + True + False + center + True + both-horiz + False + + + True + .uno:VerticalText + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:Text + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:HyperlinkDialog + + + False + True + + + + + 0 + 0 + 2 + + + + + False @@ -4832,52 +4506,146 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Fontwork + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:InsertGraphic + .uno:FontworkGalleryFloater False + False + + + + + 0 + 0 + 2 + + + + + True + False + center + True + icons + False + + + True + .uno:FontworkShapeType + + + True + True + + + + + True + .uno:FontworkSameLetterHeights + + + True True - False - True - 1 + 1 + 0 + + + True + False + center + True + icons + False + + + True + .uno:FontworkAlignmentFloater + + + True + True + + + + + True + .uno:FontworkCharacterSpacingFloater + + + True + True + + + + + 1 + 1 + + + + + False @@ -4886,73 +4654,262 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Drawing Objects + + + + + + + + + + 0 + 2 + 2 + + + + + True + False vertical + + + 2 + 0 + 3 + + + + + True + False + icons + False - + True - True - both-horiz - False - - - True - .uno:Gallery - - - False - True - - + .uno:Line - False - True - 0 + True + True - + True - True - both-horiz - False - - - True - .uno:PhotoAlbumDialog - - - False - True - - + .uno:ArrowsToolbox False - True - 1 + True + + + + + True + .uno:Polygon_Unfilled + True + + + False + True + + + + + True + .uno:Bezier_Unfilled + True + + + False + True + + + + + True + .uno:Objects3DToolbox + True + + + False + True - False - True - 2 + 0 + 0 - + + + True + False + icons + False + + + True + .uno:LineToolbox + + + False + True + + + + + True + .uno:BasicShapes.rectangle + + + True + True + + + + + True + .uno:BasicShapes.ellipse + + + True + True + + + + + True + .uno:DrawCaption + + + True + True + + + + + True + .uno:ConnectorToolbox + True + + + False + True + + + + + 0 + 1 + + + + + True + False + 6 + + + True + .uno:BasicShapes + + + True + True + + + + + True + .uno:SymbolShapes + + + True + True + + + + + True + .uno:ArrowShapes + + + True + True + + + + + 1 + 0 + + + + + True + False + 6 + + + True + .uno:StarShapes + + + True + True + + + + + True + .uno:CalloutShapes + + + True + True + + + + + True + .uno:FlowChartShapes + + + True + True + + + + + 1 + 1 + + + + + False @@ -4960,458 +4917,6 @@ 5 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:InsertAVMedia - - - False - True - - - - - False - True - 1 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:HyperlinkDialog - - - False - True - - - - - False - True - 1 - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - center - .uno:CapturePoint - - - True - True - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:FontworkGalleryFloater - - - False - True - - - - - False - True - 1 - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:DrawCaption - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - center - .uno:InsertLayer - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 10 - - - - - True - False - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - Fiel_d - 70 - True - True - True - .uno:FieldMenu - paragraphstylei - none - True - top - True - - - False - True - 1 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:CharmapControl - - - False - True - - - - - False - True - 1 - - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - both - False - 3 - - - True - .uno:InsertMath - - - False - True - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 13 - - True @@ -5422,29 +4927,29 @@ True - False + False end center True True - False + False center True vertical - _Insert + _Insert True - True - False - False + True + False + False end center True none - True + True False @@ -5455,16 +4960,16 @@ True - True + True end True - icons - False + icons + False 1 True - .uno:InsertGraphic + .uno:InsertGraphic False @@ -5474,7 +4979,7 @@ True - .uno:InsertPage + .uno:InsertPage False @@ -5484,7 +4989,7 @@ True - .uno:InsertTable + .uno:InsertTable False @@ -5509,27 +5014,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 2 @@ -5538,56 +5026,84 @@ True - False - ~Insert - True + False + ~Insert + True 2 - False + False - + True - False + False center True - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Format + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:PageSetup - - - False - True - - - - - True - .uno:HeaderAndFooter + .uno:PageSetup False @@ -5596,11 +5112,59 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:SelectBackground + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + start + .uno:SaveBackground + + + True + True + + + + + 1 + 1 + + + + + False @@ -5609,74 +5173,246 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Page + + + + + + + + + + 0 + 2 + 3 + + + + + True + False vertical + + + 3 + 0 + 3 + + + + + True + False + both-horiz + False - + True - True - both-horiz - False - - - True - .uno:SelectBackground - - - False - True - - + .uno:MovePageUp False - True - 0 - - - - - True - True - both-horiz - False - - - True - start - .uno:SaveBackground - - - True - True - - - - - False - True - 1 + True - False - True - 2 + 2 + 0 - + + + True + False + both-horiz + False + + + True + start + .uno:MovePageDown + + + False + False + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:HidePage + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ShowPage + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:RenamePage + + + False + True + + + + + 0 + 0 + 2 + + + + + + + + False + True + 1 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + end + True + Master + + + + + + + + + + 0 + 2 + + + + + True + False + vertical + + + 1 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:DrawingLayout + + + False + True + + + + + 0 + 0 + 2 + + + + + False @@ -5685,39 +5421,62 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Background + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:InsertPage + .uno:ToggleObjectRotateMode False @@ -5726,11 +5485,58 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:ObjectAlign + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectPosition + + + False + True + + + + + 1 + 1 + + + + + False @@ -5738,484 +5544,6 @@ 3 - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:DuplicatePage - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:DeletePage - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:RenamePage - - - False - True - - - - - False - True - 1 - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:HideSlide - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ShowSlide - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:MovePageUp - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - start - .uno:MovePageDown - - - False - False - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:DrawingLayout - - - False - True - - - - - False - True - 1 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ObjectAlign - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectPosition - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 11 - - True @@ -6224,31 +5552,31 @@ - + True - False + False end center True True - False + False center True vertical - _Layout + _Layout True - True - False - False + True + False + False end center True none - True + True False @@ -6259,17 +5587,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True center - .uno:PageSetup + .uno:PageSetup False @@ -6294,75 +5622,94 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 3 - + True - False - ~Layout - True + False + ~Layout + True 3 - False + False - + True - False + False center True - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Spelling + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:SpellDialog + .uno:SpellDialog False @@ -6370,9 +5717,9 @@ - + True - .uno:ThesaurusDialog + .uno:ThesaurusDialog False @@ -6381,128 +5728,21 @@ - False - True - 1 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:SpellOnline - - - True - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Hyphenation - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 0 + 0 + 2 - + True - True - center - True - both - False - 3 + False + both-horiz + False - + True - .uno:InsertAnnotation + .uno:SpellOnline True @@ -6511,11 +5751,339 @@ - False - True - 1 + 1 + 0 + + + True + False + both-horiz + False + + + True + .uno:Hyphenation + + + True + True + + + + + 1 + 1 + + + + + + + + False + True + 0 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + Comments + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + vertical + + + 4 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:InsertAnnotation + + + True + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:NextAnnotation + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:DeleteAnnotation + + + False + True + + + + + 2 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:PreviousAnnotation + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:DeleteAllAnnotation + + + False + True + + + + + 2 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:ShowAnnotations + + + False + True + + + + + 3 + 0 + 2 + + + + + + + + False + True + 1 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + Redact + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:RedactDoc + + + False + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:EditDoc + + + False + True + + + + + 1 + 0 + 2 + + + + + False @@ -6523,322 +6091,6 @@ 2 - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:NextAnnotation - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:PreviousAnnotation - - - False - True - - - - - False - False - 1 - - - - - False - True - 1 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:DeleteAnnotation - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DeleteAllAnnotation - - - False - True - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:ShowAnnotations - - - False - True - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:RedactDoc - - - False - True - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:EditDoc - - - False - True - - - - - False - True - 1 - - - - - - False - True - 7 - - True @@ -6849,27 +6101,27 @@ True - False + False end center True True - False + False center True vertical - _Review + _Review True - True - False - False + True + False + False end none - True + True False @@ -6880,17 +6132,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True center - .uno:InsertAnnotation + .uno:InsertAnnotation True @@ -6915,27 +6167,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 4 @@ -6944,46 +6179,92 @@ True - False - ~Review - True + False + ~Review + True 4 - False + False - + True - False + False center True - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + View Mode + + + + + + + + + + 0 + 2 + + + + + True + False + vertical + + + 1 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:PageMode + .uno:PageMode + + + False + True + + + + + True + .uno:MasterPage + True False @@ -6992,11 +6273,14 @@ - False - True - 0 + 0 + 0 + 2 + + + False @@ -7005,24 +6289,60 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Zoom + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:MasterPage + .uno:ZoomMode False @@ -7031,11 +6351,102 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:ZoomPageWidth + + + False + True + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ZoomNext + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ZoomPage + + + False + True + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ZoomPrevious + + + False + True + + + + + 1 + 0 + + + + + False @@ -7044,39 +6455,60 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + Options + + + + + + + - False - True - 5 - 0 + 0 + 2 + 5 - + True - True + False + vertical + + + 5 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:ZoomMode + .uno:Sidebar False @@ -7085,204 +6517,71 @@ - False - True - 1 + 0 + 0 + 2 - - - False - True - 2 - - - - - True - False - center - True - + True - False + False center True - vertical + both-horiz + False - + True - True - both-horiz - False - - - True - .uno:ZoomPrevious - - - False - True - - + .uno:ShowRuler False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ZoomPage - - - False - True - - - - - False - True - 1 + False - False - True - 2 + 1 + 0 - - - - False - True - 3 - - - - - True - False - center - True - + True - False + False center True - vertical + both-horiz + False - + True - True - both-horiz - False - - - True - .uno:ZoomNext - - - False - True - - + .uno:LeftPaneDraw False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ZoomPageWidth - - - False - True - - - - - False - True - 1 + False - False - True - 3 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 1 + 1 - + True - True + False center True - both - False - 3 + both-horiz + False - + True - .uno:Sidebar + .uno:Menubar False @@ -7291,697 +6590,47 @@ - False - True - 1 + 2 + 0 - - - False - True - 5 - - - - - True - False - center - True - + True - False + False center True - vertical + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:ShowRuler - - - False - False - - + .uno:GridVisible False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:GridVisible - - - False - False - - - - - False - False - 1 + False - False - True - 2 + 2 + 1 - - - - False - True - 6 - - - - - True - False - center - True - + True - False + False center True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:Menubar - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:LeftPaneDraw - - - False - False - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False + both + False 3 - + True - .uno:GlueEditMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - icons - False - - - True - .uno:GlueInsertPoint - - - False - True - - - - - True - .uno:GluePercent - - - False - True - - - - - True - .uno:GlueEscapeDirectionTop - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:GlueEscapeDirectionLeft - - - False - True - - - - - True - .uno:GlueEscapeDirectionRight - - - False - True - - - - - True - .uno:GlueEscapeDirectionBottom - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - icons - False - - - True - .uno:GlueHorzAlignLeft - - - False - True - - - - - True - .uno:GlueHorzAlignCenter - - - False - True - - - - - True - .uno:GlueHorzAlignRight - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:GlueVertAlignTop - - - False - True - - - - - True - .uno:GlueVertAlignCenter - - - False - True - - - - - True - .uno:GlueVertAlignBottom - - - False - True - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - False - .uno:ChangeTheme - - - False - True - - - - - False - True - 1 - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:OutputQualityColor - - - False - True - - - - - False - True - 1 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:OutputQualityGrayscale - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:OutputQualityBlackWhite - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:NewWindow + .uno:HelplinesMove True @@ -7990,19 +6639,299 @@ - False - True - 1 + 3 + 0 + 2 - + + + True + False + center + True + both + False + 3 + + + True + .uno:ChangeTheme + + + False + True + + + + + 4 + 0 + 2 + + + + + False True - 13 + 2 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + Gluepoints + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:GlueEditMode + + + False + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + icons + False + + + True + .uno:GlueInsertPoint + + + False + True + + + + + True + .uno:GluePercent + + + False + True + + + + + True + .uno:GlueEscapeDirectionTop + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + icons + False + + + True + .uno:GlueEscapeDirectionLeft + + + False + True + + + + + True + .uno:GlueEscapeDirectionRight + + + False + True + + + + + True + .uno:GlueEscapeDirectionBottom + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + icons + False + + + True + .uno:GlueHorzAlignLeft + + + False + True + + + + + True + .uno:GlueHorzAlignCenter + + + False + True + + + + + True + .uno:GlueHorzAlignRight + + + False + True + + + + + 2 + 0 + + + + + True + False + center + True + icons + False + + + True + .uno:GlueVertAlignTop + + + False + True + + + + + True + .uno:GlueVertAlignCenter + + + False + True + + + + + True + .uno:GlueVertAlignBottom + + + False + True + + + + + 2 + 1 + + + + + + + + False + True + 3 @@ -8015,29 +6944,29 @@ True - False + False end center True True - False + False center True vertical - _View + _View True - True - False - False + True + False + False end center True none - True + True False @@ -8048,17 +6977,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True center - .uno:Zoom + .uno:Zoom False @@ -8083,27 +7012,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 5 @@ -8112,118 +7024,153 @@ True - False - ~View - True + False + ~View + True 5 - False + False - + True - False + False center True - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Table + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:Paste + .uno:TransformDialog + True False - False + True + + + + + True + .uno:SelectTable + + + False + True - False - True - 0 + 0 + 0 + 2 - + True - False - center - vertical + False + both-horiz + False - + True - True - both-horiz - False - - - True - .uno:Cut - - - False - True - - + .uno:EntireColumn - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Copy - - - False - True - - - - - False - True - 1 + True + True - False - True - 1 + 1 + 0 + + + True + False + both-horiz + False + + + True + .uno:EntireRow + + + True + True + + + + + 1 + 1 + + + + + False @@ -8232,88 +7179,199 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + Cells + + + + + + + - False - True - 5 - 0 + 0 + 2 + 3 - + True - False + False + vertical + + + 3 + 0 + 3 + + + + + True + False center - vertical + True + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:FormatPaintbrush - - - False - True - - + center + True + .uno:MergeCells - False - True - 0 + True + True - + True - True - both-horiz - False - - - True - .uno:SetDefault - - - False - True - - + .uno:SplitCell + True False - True - 1 + True - False - True - 1 + 0 + 0 + 2 - + + + True + False + icons + False + + + True + .uno:InsertColumnsBefore + + + False + True + + + + + True + .uno:InsertColumnsAfter + + + False + True + + + + + True + .uno:DeleteColumns + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:InsertRowsBefore + + + False + True + + + + + True + .uno:InsertRowsAfter + + + False + True + + + + + True + .uno:DeleteRows + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:OptimizeTable + + + False + True + + + + + 2 + 0 + 2 + + + + + False @@ -8322,1183 +7380,62 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center - vertical - - - True - False - - - True - True - True - - - True - .uno:CharFontName - - - True - True - - - - - True - True - 0 - - - - - True - True - 5 - - - True - .uno:FontHeight - - - True - True - - - - - False - True - 1 - - - - - True - True - icons - False - - - True - .uno:Grow - - - False - True - - - - - True - .uno:Shrink - - - False - True - - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - center - - - True - True - icons - False - - - True - .uno:Bold - - - False - True - - - - - True - .uno:Italic - - - False - True - - - - - True - .uno:Underline - - - False - True - - - - - True - .uno:Strikeout - - - False - True - - - - - True - .uno:Shadowed - - - False - True - - - - - False - True - 0 - - - - - True - False - end - 5 - 5 - True - vertical - - - False - True - 5 - 1 - - - - - True - True - icons - False - - - True - .uno:Spacing - - - False - False - - - - - True - .uno:CharBackColor - - - False - False - - - - - True - .uno:Color - - - False - False - - - - - False - True - 2 - - - - - False - True - 2 - - + False + Layout + + + + + + + - False - True - 1 - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 0 + 2 + 4 - + True - False - center - vertical - - - True - False - center - - - True - True - icons - False - - - True - center - True - .uno:CellVertTop - - - False - True - - - - - True - .uno:CellVertCenter - - - False - True - - - - - True - center - True - .uno:CellVertBottom - - - False - True - - - - - False - True - 0 - - - - - False - True - 0 - - - - - True - False - center - - - True - True - icons - False - - - True - center - True - .uno:StartPara - - - False - True - - - - - True - center - True - .uno:CenterPara - - - False - True - - - - - True - center - True - .uno:EndPara - - - False - True - - - - - False - True - 0 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - False - center - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - True - True - icons - False - - - True - .uno:DefaultBullet - - - False - True - - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - center - - - True - True - icons - False - - - True - center - True - .uno:JustifyPara - - - False - True - - - - - False - True - 0 - - - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - False - center - - - True - True - end - True - icons - False - - - True - .uno:DefaultNumbering - - - False - True - - - - - True - center - True - .uno:OutlineRight - - - False - True - - - - - True - center - True - .uno:OutlineLeft - - - False - True - - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - end - center - True - - - True - True - end - True - icons - False - - - True - end - .uno:LineSpacing - - - False - False - - - - - True - .uno:ParaspaceIncrease - - - False - True - - - - - True - .uno:ParaspaceDecrease - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - icons - False - - - True - .uno:ParaLeftToRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:ParaRightToLeft - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 + False vertical - False - True - 5 - 0 + 4 + 0 + 3 - + True - False - center - vertical - - - True - True - icons - False - - - True - center - True - .uno:StyleApply - - - True - True - - - - - True - True - 0 - - - - - True - False - center - True - - - True - True - icons - False - - - True - center - True - .uno:DesignerDialog - - - False - True - - - - - False - True - 0 - - - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - True - True - center - True - icons - False - - - True - .uno:StyleApply?Style:string=Text&FamilyName:string=ParagraphStyles - cmd/sc_defaultcharstyle.png - - - False - True - - - - - True - .uno:StyleApply?Style:string=Title&FamilyName:string=ParagraphStyles - cmd/sc_titleparastyle.png - - - False - True - - - - - True - .uno:StyleApply?Style:string=Heading&FamilyName:string=ParagraphStyles - cmd/sc_heading1parastyle.png - - - False - True - - - - - False - True - 2 - - - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 3 - - - - - True - True - icons - False - - - True - center - True - .uno:EditStyle - - - False - True - - - - - False - True - 4 - - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True + False center True - both - False + both + False 3 - - True - .uno:TextAttributes - - - False - True - - - - - False - True - 1 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:TransformDialog - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:DrawCaption - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 9 - - - - - True - True - 0 - - - - - True - False - end - center - True - - - True - False - center - True - vertical - - - T_ext - True - True - False - False - end - True - none - True - - - False - False - 0 - - - - - True - True - center - True - icons - False - 1 - - - True - .uno:SearchDialog - - - False - True - - - - + True center True - .uno:TransformDialog + .uno:TableDesign True @@ -9507,99 +7444,21 @@ - False - True - 1 + 0 + 0 + 2 - - - False - True - 2 - - - - - False - False - end - 1 - - - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - - - 6 - - - - - True - False - T~ext - True - - - - 6 - False - - - - - True - False - center - True - - - True - False - center - True - - - True - False - center - True - + True - True - center - True - both - False - 3 + False + text + False - + True - center - True - .uno:NameGroup + .uno:FormatArea False @@ -9608,209 +7467,115 @@ - False - True - 0 + 1 + 1 - - - False - True - 0 - - - - - True - False - center - True - + True - False - center - vertical + False + icons + False - + True - True - icons - False - - - True - .uno:InsertColumnsBefore - - - False - True - - - - - True - .uno:InsertColumnsAfter - - - False - True - - - - - True - .uno:DeleteColumns - - - False - True - - + center + .uno:SetBorderStyle False - True - 0 - - - - - True - True - icons - False - - - True - .uno:InsertRowsBefore - - - False - True - - - - - True - .uno:InsertRowsAfter - - - False - True - - - - - True - .uno:DeleteRows - - - False - True - - - - - False - True - 1 + False - False - True - 1 - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 + 2 + 0 - + True - False - vertical + False + both-horiz + False - + True - True - text - False - - - True - .uno:Line - - - False - False - - + .uno:FillStyle False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - False - False - - - - - False - True - 1 + True - False - True - 2 + 2 + 1 + 2 + + + True + False + text + False + + + True + .uno:Line + + + False + False + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:LineStyle + True + + + False + True + + + + + True + .uno:FrameLineColor + True + + + False + True + + + + + 3 + 0 + + + + + False @@ -9818,620 +7583,6 @@ 2 - - - True - False - center - True - - - True - False - vertical - - - True - False - - - True - True - icons - False - - - True - center - .uno:SetBorderStyle - - - False - False - - - - - True - .uno:LineStyle - - - True - True - - - - - True - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:FrameLineColor - - - True - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - center - True - .uno:MergeCells - - - True - True - - - - - False - True - 1 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:SplitCell - - - False - True - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SelectTable - - - False - True - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:EntireColumn - - - True - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:EntireRow - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:OptimizeTable - - - False - True - - - - - False - True - 1 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - icons - False - - - True - center - True - .uno:CellVertTop - - - False - True - - - - - True - center - True - .uno:CellVertCenter - - - False - True - - - - - True - center - True - .uno:CellVertBottom - - - False - True - - - - - True - .uno:ParaRightToLeft - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - center - True - .uno:StartPara - - - False - True - - - - - True - center - True - .uno:CenterPara - - - False - True - - - - - True - center - True - .uno:EndPara - - - False - True - - - - - True - center - True - .uno:JustifyPara - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - center - True - .uno:TableDesign - - - True - True - - - - - False - True - 1 - - - - - - False - True - 10 - - True @@ -10442,28 +7593,28 @@ True - False + False end center True True - False + False center True vertical - _Table + _Table True - True - False - False + True + False + False end center none - True + True False @@ -10474,17 +7625,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True center - .uno:TableDialog + .uno:TableDialog False @@ -10509,80 +7660,165 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 7 + 6 True - False - ~Table - True + False + ~Table + True - 7 - False + 6 + False - + True - False + False center True - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True - center + False + end True - both - False - 3 + Image + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 + vertical + + + 3 + 0 + 3 + + + + + True + False + icons + False - + + True + .uno:CompressGraphic + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:Crop + + + False + True + + + + + 2 + 0 + + + + + True + False + icons + False + + True center True - .uno:NameGroup + .uno:ToggleObjectRotateMode + + + False + False + + + + + True + .uno:FlipVertical + + + False + False + + + + + True + .uno:FlipHorizontal False @@ -10591,11 +7827,42 @@ - False - True - 0 + 1 + 1 + 2 + + + True + False + center + True + both + False + 3 + + + True + center + True + .uno:TransformDialog + + + False + False + + + + + 0 + 0 + 2 + + + + + False @@ -10604,850 +7871,62 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end True - vertical - - - True - False - - - True - True - icons - False - - - True - .uno:CompressGraphic - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Crop - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - center - True - .uno:ToggleObjectRotateMode - - - False - False - - - - - True - .uno:FlipVertical - - - False - False - - - - - True - .uno:FlipHorizontal - - - False - False - - - - - True - center - True - .uno:ChangePicture - - - False - False - - - - - True - center - True - .uno:SaveGraphic - - - False - False - - - - - False - True - 1 - - + Fill & Border + + + + + + + - False - True - 1 + 0 + 2 + 3 - - - False - True - 1 - - - - - True - False - center - True - + True - False - 5 - 5 + False + end + 5 + 5 vertical - False - True - 5 - 0 + 3 + 0 + 3 - + True - False - vertical + False + text + False - + True - True - text - False - - - True - .uno:FormatLine - - - True - True - - - - - False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - vertical - - - True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - - - - True - True - 1 - - - - - False - True - 2 - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - Convert - 70 - True - True - True - .uno:ChangeBezier - changebezierImg - none - True - top - True - - - False - True - 1 - - - - - True - False - center - True - - - True - False - - - True - False - center - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - - - True - False - center - vertical - - - True - True - icons - False - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - both - False - - - True - .uno:GraphicFilterToolbox + .uno:FormatArea False @@ -11456,259 +7935,546 @@ - False - True - 1 + 0 + 1 + + + True + False + both-horiz + False + + + True + .uno:FillStyle + + + False + True + + + + + 1 + 1 + 2 + + + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + False True - 8 + 1 - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Positioning + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 vertical + + + 1 + 0 + 3 + + + + + True + False + icons + False - + True - True - both-horiz - False - - - True - center - .uno:GrafLuminance - - - False - False - - + .uno:ObjectAlignLeft False - True - 0 + True - + True - True - both-horiz - False - - - True - center - .uno:GrafContrast - - - False - False - - + .uno:AlignCenter False - True - 1 + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + True + .uno:BringToFront + True + + + False + True + + + + + True + .uno:ObjectForwardOne + True + + + False + True - False - True - 1 + 0 + 0 - + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + True + .uno:SendToBack + True + + + False + True + + + + + True + .uno:ObjectBackOne + True + + + False + True + + + + + 0 + 1 + + + + + False True - 5 - 9 + 2 - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Modify + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + end + 5 + 5 vertical + + + 4 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - both-horiz - False - - - True - center - .uno:GrafTransparence - - - False - False - - + center + True + .uno:GraphicFilterToolbox False - True - 0 - - - - - True - True - both-horiz - False - - - True - center - .uno:GrafGamma - - - False - False - - - - - False - True - 1 + False - False - True - 0 + 0 + 0 + 2 - + + + True + False + both-horiz + False + + + True + center + 5 + .uno:GrafLuminance + + + False + False + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + center + 5 + .uno:GrafContrast + + + False + False + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + center + .uno:GrafTransparence + + + False + False + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + center + .uno:GrafGamma + + + False + False + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:GrafMode + + + False + True + + + + + 3 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ColorSettings + + + False + True + + + + + 3 + 1 + + + + + False True - 10 - - - - - True - False - center - True - - - True - False - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - False - both-horiz - False - - - True - .uno:GrafMode - - - False - True - - - - - False - True - 0 - - - - - True - False - both-horiz - False - - - True - .uno:ColorSettings - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 11 + 3 @@ -11721,28 +8487,28 @@ True - False + False end center True True - False + False center True vertical - Ima_ge + Ima_ge True - True - False - False + True + False + False end center none - True + True False @@ -11753,18 +8519,18 @@ True - True + True end True - icons - False + icons + False 1 True center True - .uno:FormatArea + .uno:FormatArea True @@ -11776,7 +8542,7 @@ True center True - .uno:FormatLine + .uno:FormatLine True @@ -11788,7 +8554,7 @@ True center True - .uno:TransformDialog + .uno:TransformDialog True @@ -11813,259 +8579,207 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 8 + 7 True - False - Ima~ge - True + False + Ima~ge + True - 8 - False + 7 + False - + True - False + False center True - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Drawing Object + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - center - True - .uno:NameGroup + .uno:TransformDialog + True - True + False True - False - True - 0 + 0 + 0 + 2 - + True - False + False center - vertical + True + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:AdvancedMode - - - False - True - - + .uno:AdvancedMode False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - True - .uno:FlipVertical - - - False - True - - - - - True - .uno:FlipHorizontal - - - False - True - - - - - True - .uno:Shear - - - False - True - - - - - True - .uno:CrookSlant - - - False - True - - - - - False - True - 1 + True - False - True - 2 + 1 + 0 - + True - False + False center - vertical + True + icons + False - + True - True - center - True - both-horiz - False - - - True - .uno:FormatPaintbrush - - - False - True - - + .uno:ToggleObjectRotateMode False - True - 0 + True - + True - True - center - True - both-horiz - False - - - True - .uno:SetDefault - - - False - True - - + .uno:FlipVertical False - True - 1 + True + + + + + True + .uno:FlipHorizontal + + + False + True + + + + + True + .uno:Shear + + + False + True + + + + + True + .uno:CrookSlant + + + False + True - False - True - 2 + 1 + 1 + + + False @@ -12074,84 +8788,199 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Fill & Border + + + + + + + - False - True - 5 - 0 + 0 + 2 + 3 - + True - False + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + text + False - + True - True - text - False - - - True - .uno:FormatLine - - - True - True - - + .uno:FormatArea False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 + False - False - True - 1 + 0 + 1 + + + True + False + both-horiz + False + + + True + .uno:FillStyle + + + False + True + + + + + 1 + 1 + 2 + + + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + False @@ -12160,125 +8989,182 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Positioning + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 vertical + + + 1 + 0 + 3 + + + + + True + False + icons + False - + True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - + .uno:ObjectAlignLeft False - True - 0 + True - + True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - + .uno:AlignCenter - True - True - 1 + False + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + True + .uno:BringToFront + True + + + False + True + + + + + True + .uno:ObjectForwardOne + True + + + False + True - False - True - 2 + 0 + 0 + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + True + .uno:SendToBack + True + + + False + True + + + + + True + .uno:ObjectBackOne + True + + + False + True + + + + + 0 + 1 + + + + + False @@ -12287,72 +9173,173 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Combination + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - + .uno:Combine - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 + True + True - False - True - 3 + 0 + 0 + 2 - + + + True + False + center + True + False + + + True + .uno:Intersect + + + True + True + + + + + True + .uno:Dismantle + + + True + True + + + + + 1 + 0 + + + + + True + False + center + True + False + + + True + .uno:Merge + + + True + True + + + + + True + .uno:Substract + + + True + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:DistributeSelection + + + True + True + + + + + 2 + 0 + 2 + + + + + False @@ -12361,118 +9348,140 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 + False + end + True + Grouping + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 vertical - False - True - 5 - 0 + 2 + 0 + 3 - - Convert - 70 + True - True - True - .uno:ChangeBezier - changebezierImg - none - True - top - True - - - False - True - 1 - - - - - True - False + False + center + True + both + False + 3 - + True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - False - True - 1 - - + .uno:FormatGroup + + + True + True + + + + + True + .uno:FormatUngroup + True False - True - 0 + True - False - True - 2 + 0 + 0 + 2 - + + + True + False + center + True + both-horiz + False + + + True + .uno:EnterGroup + + + True + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:LeaveGroup + + + True + True + + + + + 1 + 1 + + + + + False @@ -12481,103 +9490,128 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False + False + end + True + 3D + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + False + both-horiz + False - + True - False - vertical - - - True - True - icons - False - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - + .uno:ExtrusionToggle - False - True - 0 + True + True - False - True - 2 + 0 + 0 - + + + True + False + icons + False + + + True + .uno:ExtrusionDepthFloater + + + True + True + + + + + True + .uno:ExtrusionDirectionFloater + + + True + True + + + + + True + .uno:Extrusion3DColor + + + False + False + + + + + True + .uno:ExtrusionSurfaceFloater + + + False + False + + + + + 0 + 1 + + + + + False @@ -12585,992 +9619,6 @@ 5 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ToggleObjectBezierMode - - - True - True - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - vertical - - - True - True - center - True - icons - False - - - True - .uno:BezierMove - - - False - True - - - - - True - .uno:BezierInsert - - - False - True - - - - - True - .uno:BezierDelete - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:BezierCutLine - - - False - True - - - - - True - .uno:BezierEdge - - - False - True - - - - - True - .uno:BezierSmooth - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - vertical - - - True - True - center - True - icons - False - - - True - .uno:BezierConvert - - - False - True - - - - - True - .uno:BezierClose - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:BezierSymmetric - - - False - True - - - - - True - .uno:BezierEliminatePoints - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:GlueEditMode - - - True - True - - - - - False - True - 2 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - False - - - True - .uno:Combine - - - True - True - - - - - True - .uno:Dismantle - - - True - True - - - - - True - .uno:DistributeSelection - - - True - True - - - - - False - True - 0 - - - - - True - True - center - True - False - - - True - .uno:Merge - - - True - True - - - - - True - .uno:Substract - - - True - True - - - - - True - .uno:Intersect - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:FormatGroup - - - True - True - - - - - False - True - 2 - - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:EnterGroup - - - True - True - - - - - False - True - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:LeaveGroup - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 13 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ExtrusionToggle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:ExtrusionDepthFloater - - - True - True - - - - - True - .uno:ExtrusionDirectionFloater - - - True - True - - - - - True - .uno:Extrusion3DColor - - - False - False - - - - - True - .uno:ExtrusionSurfaceFloater - - - False - False - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 14 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:FontworkGalleryFloater - - - True - True - - - - - False - True - 1 - - - - - - False - True - 15 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - icons - False - - - True - .uno:FontworkShapeType - - - True - True - - - - - True - .uno:FontworkSameLetterHeights - - - True - True - - - - - False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:FontworkAlignmentFloater - - - True - True - - - - - True - .uno:FontworkCharacterSpacingFloater - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 16 - - True @@ -13581,28 +9629,28 @@ True - False + False end center True True - False + False center True vertical - _Draw + _Draw True - True - False - False + True + False + False end center none - True + True False @@ -13613,17 +9661,17 @@ True - True + True end True - icons - False + icons + False 1 True center - .uno:FormatArea + .uno:FormatArea False @@ -13634,7 +9682,7 @@ True center - .uno:FormatLine + .uno:FormatLine False @@ -13645,7 +9693,7 @@ True center - .uno:TransformDialog + .uno:TransformDialog False @@ -13670,38 +9718,21 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 9 + 8 True - False - ~Draw - True + False + ~Draw + True - 9 - False + 8 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True - center + False + end True - both - False - 3 + Object + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False + icons + False - + True center True - .uno:NameGroup + .uno:ToggleObjectRotateMode + + + False + False + + + + + True + .uno:FlipVertical + + + False + False + + + + + True + .uno:FlipHorizontal False @@ -13752,114 +9841,65 @@ - False - True - 0 + 1 + 1 - + True - False + False center - vertical + True + both + False + 3 - + True - True center True - both-horiz - False - - - True - .uno:AdvancedMode - - - False - True - - + .uno:TransformDialog False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - True - .uno:FlipVertical - - - False - True - - - - - True - .uno:FlipHorizontal - - - False - True - - - - - True - .uno:Shear - - - False - True - - - - - True - .uno:CrookSlant - - - False - True - - - - - False - True - 1 + False - False - True - 2 + 0 + 0 + 2 + + + True + False + center + True + both-horiz + False + + + True + .uno:OriginalSize + + + False + True + + + + + 1 + 0 + + + + + False @@ -13868,84 +9908,198 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Fill & Border + + + + + + + - False - True - 5 - 0 + 0 + 2 + 3 - + True - False + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + text + False - + True - True - text - False - - - True - .uno:FormatLine - - - True - True - - + .uno:FormatArea False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 + False - False - True - 1 + 0 + 1 + + + True + False + both-horiz + False + + + True + .uno:FillStyle + + + False + True + + + + + 1 + 1 + 2 + + + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + False @@ -13954,125 +10108,182 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Positioning + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 vertical + + + 1 + 0 + 3 + + + + + True + False + icons + False - + True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - + .uno:ObjectAlignLeft False - True - 0 + True - + True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - + .uno:AlignCenter - True - True - 1 + False + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + True + .uno:BringToFront + True + + + False + True + + + + + True + .uno:ObjectForwardOne + True + + + False + True - False - True - 2 + 0 + 0 + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + True + .uno:SendToBack + True + + + False + True + + + + + True + .uno:ObjectBackOne + True + + + False + True + + + + + 0 + 1 + + + + + False @@ -14080,436 +10291,6 @@ 2 - - - True - False - center - True - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - Convert - 70 - True - True - True - .uno:ChangeBezier - changebezierImg - none - True - top - True - - - False - True - 1 - - - - - True - False - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - True @@ -14520,29 +10301,29 @@ True - False + False end center True True - False + False center True vertical - _Object + _Object True - True - False - False + True + False + False end center True none - True + True False @@ -14553,17 +10334,17 @@ True - True + True end True - icons - False + icons + False 1 True center - .uno:FormatArea + .uno:FormatArea False @@ -14574,7 +10355,7 @@ True center - .uno:FormatLine + .uno:FormatLine False @@ -14585,7 +10366,7 @@ True center - .uno:TransformDialog + .uno:TransformDialog False @@ -14610,79 +10391,102 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 10 + 9 True - False - ~Object - True + False + ~Object + True - 10 - False + 9 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Media + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True center True - .uno:NameGroup + .uno:TransformDialog True @@ -14691,70 +10495,14 @@ - False - True - 1 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:AVMediaPlayer - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 + 0 + 0 + 2 + + + False @@ -14763,35 +10511,103 @@ - + + True - False - center + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Positioning + + + + + + + - False - True - 5 - 0 + 0 + 2 - - 148 + True - True - False + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + False + icons + False - + True - .uno:AVMediaToolBox + .uno:ObjectAlignLeft + + + False + True + + + + + True + .uno:AlignCenter + + + False + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + True + .uno:BringToFront + True + + + False + True + + + + + True + .uno:ObjectForwardOne + True False @@ -14800,287 +10616,182 @@ - True - True - 0 + 0 + 0 + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + True + .uno:SendToBack + True + + + False + True + + + + + True + .uno:ObjectBackOne + True + + + False + True + + + + + 0 + 1 + + + + + - True + False True 1 - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 + False + end + True + Media Player + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 vertical - False - True - 5 - 0 + 1 + 0 + 3 - - + + 200 True - False + False + False - + True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - False - True - 1 - - + .uno:AVMediaToolBox False - True - 0 + True - False - True - 2 + 0 + 0 - + + + True + False + both-horiz + False + + + True + .uno:AVMediaPlayer + + + False + True + + + + + 0 + 1 + + + + + - False + True True - 3 + 2 @@ -15093,27 +10804,27 @@ True - False + False end center True True - False + False center True vertical - _Media + _Media True - True - False - False + True + False + False end none - True + True False @@ -15124,17 +10835,17 @@ True - True + True end True - icons - False + icons + False 1 True center - .uno:FormatArea + .uno:FormatArea False @@ -15145,7 +10856,7 @@ True center - .uno:FormatLine + .uno:FormatLine False @@ -15155,7 +10866,7 @@ True - .uno:TransformDialog + .uno:TransformDialog False @@ -15180,1086 +10891,202 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - - - 11 - - - - - True - False - ~Media - True - - - - 11 - False - - - - - True - False - - - True - False - center - True - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:SwitchControlDesignMode - - - False - True - - - - - False - True - 0 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:UseWizards - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:GroupBox - - - False - True - - - - - False - False - 1 - - - - - False - True - 1 - - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:FormProperties - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ShowFmExplorer - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:TabDialog - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:OpenReadOnly - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ControlProperties - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:AutoControlFocus - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Label - - - False - True - - - - - True - .uno:Edit - - - False - True - - - - - True - .uno:CheckBox - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:RadioButton - - - False - True - - - - - True - .uno:ListBox - - - False - True - - - - - True - .uno:ComboBox - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:NumericField - - - False - True - - - - - True - .uno:CurrencyField - - - False - True - - - - - True - .uno:PatternField - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FormattedField - - - False - True - - - - - True - .uno:DateField - - - False - True - - - - - True - .uno:TimeField - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Pushbutton - - - False - True - - - - - True - .uno:Imagebutton - - - False - True - - - - - True - .uno:ImageControl - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FileControl - - - False - True - - - - - True - .uno:NavigationBar - - - False - True - - - - - True - .uno:Grid - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - True - 0 - - - - - True - False - end - center - True - - - True - False - center - True - vertical - - - Fo_rm - True - True - False - False - end - center - True - none - True - - - False - True - 0 - - - - - True - True - end - True - both-horiz - False - 1 - - - True - .uno:FormProperties - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - False - False - end - 1 - - - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 10 - + True - False - Fo~rm - True + False + ~Media + True - 12 - False + 10 + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + 3D Object + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - center - True - .uno:NameGroup + .uno:TransformDialog + True False - False + True - False - True - 0 + 0 + 0 + 2 - + True - False + False center - vertical + True + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:AdvancedMode - - - False - True - - + .uno:AdvancedMode False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - True - .uno:FlipVertical - - - False - True - - - - - True - .uno:FlipHorizontal - - - False - True - - - - - True - .uno:Shear - - - False - True - - - - - True - .uno:CrookSlant - - - False - True - - - - - False - True - 1 + True - False - True - 2 + 1 + 0 + + + True + False + center + True + icons + False + + + True + .uno:ToggleObjectRotateMode + + + False + True + + + + + True + .uno:FlipVertical + + + False + True + + + + + True + .uno:FlipHorizontal + + + False + True + + + + + True + .uno:Shear + + + False + True + + + + + True + .uno:CrookSlant + + + False + True + + + + + 1 + 1 + + + + + False @@ -16268,328 +11095,59 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - vertical - - - True - True - text - False - - - True - .uno:FormatLine - - - True - True - - - - - False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - vertical - - - True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - - - - True - True - 1 - - - - - False - True - 2 - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center + False + end True - both - False - 3 + Fill & Border + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 + vertical + + + 3 + 0 + 3 + + + + + True + False + text + False - + True - center - True - .uno:Window3D + .uno:FormatArea False @@ -16598,272 +11156,402 @@ - False - True - 1 + 0 + 1 - - - False - True - 4 - - - - - True - False - center - True - + True - False + False + both-horiz + False - + True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - + .uno:FillStyle False - True - 0 + True - False - True - 2 + 1 + 1 + 2 - + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + False True - 5 + 1 - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 + False + end + True + Positioning + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 vertical - False - True - 5 - 0 + 1 + 0 + 3 - - + True - False + False + icons + False - + True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - + .uno:ObjectAlignLeft - 0 - 0 + False + True - + True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - + .uno:AlignCenter - 0 - 1 + False + True - + True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - + .uno:ObjectAlignRight - 1 - 0 + False + True - + True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - + .uno:BringToFront + True - 1 - 1 + False + True + + + + + True + .uno:ObjectForwardOne + True + + + False + True - False - True - 1 + 0 + 0 - + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + True + .uno:SendToBack + True + + + False + True + + + + + True + .uno:ObjectBackOne + True + + + False + True + + + + + 0 + 1 + + + + + False True - 6 + 2 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + end + True + 3D + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + center + True + .uno:Window3D + + + False + False + + + + + 0 + 0 + 2 + + + + + + + + False + True + 3 @@ -16874,31 +11562,31 @@ - + True - False + False end center True True - False + False center True vertical - 3_d + 3_D True - True - False - False + True + False + False end center True none - True + True False @@ -16909,17 +11597,17 @@ True - True + True end True - icons - False + icons + False 1 True center - .uno:FormatArea + .uno:FormatArea False @@ -16930,7 +11618,7 @@ True center - .uno:FormatLine + .uno:FormatLine False @@ -16941,7 +11629,7 @@ True center - .uno:TransformDialog + .uno:TransformDialog False @@ -16966,76 +11654,91 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 13 + 8 - + True - False - 3~d - True + False + 3~D + True - 12 - False + 11 + False True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Master + + + + + + + 0 + 2 + 4 + + + + + True + False + vertical + + + 4 + 0 + 3 + + + + + True + False center True - both - False - 3 + both-horiz + False - + True - .uno:PageMode + .uno:RenameMasterPage False @@ -17044,11 +11747,137 @@ - False - True - 0 + 1 + 0 + + + True + False + center + True + both-horiz + False + + + True + .uno:DeleteMasterPage + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:InsertMasterPage + + + False + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:NotesMasterPage + + + False + True + + + + + 3 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:HandoutMode + + + False + True + + + + + 3 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:MasterLayouts + + + False + True + + + + + 2 + 0 + 2 + + + + + False @@ -17057,24 +11886,57 @@ - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Slide + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:MasterPage + .uno:SlideSetup False @@ -17083,11 +11945,110 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + center + True + both-horiz + False + + + True + .uno:SelectBackground + + + False + True + + + + + 2 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:SaveBackground + + + False + True + + + + + 2 + 1 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:HideSlide + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:ShowSlide + + + False + True + + + + + 1 + 1 + + + + + False @@ -17096,39 +12057,60 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + Color + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:InsertMasterPage + .uno:OutputQualityColor False @@ -17137,212 +12119,23 @@ - False - True - 1 + 0 + 0 + 2 - - - False - True - 4 - - - - - True - False - center - True - + True - False + False center True - vertical + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:RenameMasterPage - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DeleteMasterPage - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:HideSlide - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:ShowSlide - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:PageSetup + .uno:OutputQualityGrayscale False @@ -17351,132 +12144,22 @@ - False - True - 1 + 1 + 0 - - - False - True - 8 - - - - - True - False - center - True - + True - False + False center True - vertical + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:SelectBackground - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:SaveBackground - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:CloseMasterView + .uno:OutputQualityBlackWhite False @@ -17485,16 +12168,91 @@ - False - True - 1 + 1 + 1 + + + False True - 10 + 2 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + + + + + + + 0 + 2 + + + + + True + False + vertical + + + 1 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:CloseMasterView + + + False + True + + + + + 0 + 0 + 2 + + + + + + + + False + True + 3 @@ -17507,29 +12265,29 @@ True - False + False end center True True - False + False center True vertical - _Master + _Master True - True - False - False + True + False + False end center True none - True + True False @@ -17540,16 +12298,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True - .uno:PageSetup + .uno:PageSetup False @@ -17574,61 +12332,784 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - 14 + 12 True - False - ~Master - True + False + ~Master + True - 12 - False + 8 + False + + + + + True + False + + + True + False + center + True + + + + True + False + 6 + 3 + 6 + 6 + 3 + 3 + + + True + False + end + True + Mode + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:TransformDialog + + + False + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:UseWizards + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:GroupBox + + + False + True + + + + + 1 + 1 + + + + + + + + False + True + 0 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + end + True + Properties + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 + vertical + + + 3 + 0 + 3 + + + + + True + False + both-horiz + False + + + True + .uno:FormProperties + + + False + True + + + + + 0 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ShowFmExplorer + + + False + True + + + + + 0 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:TabDialog + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:OpenReadOnly + + + False + True + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ControlProperties + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:AutoControlFocus + + + False + True + + + + + 2 + 1 + + + + + + + + False + True + 1 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + end + True + Controls + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 + vertical + + + 3 + 0 + 3 + + + + + True + False + icons + False + + + True + .uno:Label + + + False + True + + + + + True + .uno:Edit + + + False + True + + + + + True + .uno:CheckBox + + + False + True + + + + + 0 + 0 + + + + + True + False + icons + False + + + True + .uno:RadioButton + + + False + True + + + + + True + .uno:ListBox + + + False + True + + + + + True + .uno:ComboBox + + + False + True + + + + + 0 + 1 + + + + + True + False + icons + False + + + True + .uno:NumericField + + + False + True + + + + + True + .uno:CurrencyField + + + False + True + + + + + True + .uno:PatternField + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:FormattedField + + + False + True + + + + + True + .uno:DateField + + + False + True + + + + + True + .uno:TimeField + + + False + True + + + + + 1 + 1 + + + + + True + False + icons + False + + + True + .uno:Pushbutton + + + False + True + + + + + True + .uno:Imagebutton + + + False + True + + + + + True + .uno:ImageControl + + + False + True + + + + + 2 + 0 + + + + + True + False + icons + False + + + True + .uno:FileControl + + + False + True + + + + + True + .uno:NavigationBar + + + False + True + + + + + True + .uno:Grid + + + False + True + + + + + 2 + 1 + + + + + + + + False + True + 2 + + + + + True + True + 0 + + + + + True + False + end + center + True + + + True + False + center + True + vertical + + + Fo_rm + True + True + False + False + end + center + True + none + True + + + False + True + 0 + + + + + True + True + end + True + both-horiz + False + 1 + + + True + .uno:FormProperties + + + False + True + + + + + False + True + 1 + + + + + False + True + 2 + + + + + False + False + end + 1 + + + + + 9 + + + + + True + False + Form + True + + + + 10 + False True - False + False True - False + False center True True - False + False center True @@ -17648,29 +13129,29 @@ True - False + False end center True True - False + False center True vertical - E_xtension + E_xtension True - True - False - False + True + False + False end center True none - True + True False @@ -17681,11 +13162,11 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 @@ -17705,75 +13186,116 @@ False False - end + end 1 True - False + False end - 5 - 5 + 5 + 5 vertical False True 5 - end + end 2 - 15 + 14 True - False - E~xtension - True + False + E~xtension + True - 15 - False + 14 + False True - False + False center True True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Macro + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:RunMacro + .uno:RunMacro False @@ -17782,11 +13304,57 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:BasicIDEAppear + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + + + True + .uno:MacroDialog + + + False + True + + + + + 1 + 1 + + + + + False @@ -17795,74 +13363,80 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + end + True + AutoCorrection + + + + + + + + + + 0 + 1 + 1 + + + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 2 + + + + + True + False center True - vertical + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:BasicIDEAppear - - - False - True - - + .uno:AutoCorrectDlg False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:MacroDialog - - - False - True - - - - - False - True - 1 + True - False - True - 2 + 0 + 0 - + + + False @@ -17871,39 +13445,64 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Tools + + + + + + + - False - True - 5 - 0 + 0 + 2 - + True - True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:BmpMask + .uno:BmpMask True @@ -17912,11 +13511,14 @@ - False - True - 1 + 0 + 0 + 2 + + + False @@ -17924,706 +13526,6 @@ 2 - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:AVMediaPlayer - - - True - True - - - - - False - True - 2 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SwitchControlDesignMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:UseWizards - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:GroupBox - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Label - - - False - True - - - - - True - .uno:Edit - - - False - True - - - - - True - .uno:CheckBox - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:RadioButton - - - False - True - - - - - True - .uno:ListBox - - - False - True - - - - - True - .uno:ComboBox - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:NumericField - - - False - True - - - - - True - .uno:CurrencyField - - - False - True - - - - - True - .uno:PatternField - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FormattedField - - - False - True - - - - - True - .uno:DateField - - - False - True - - - - - True - .uno:TimeField - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Pushbutton - - - False - True - - - - - True - .uno:Imagebutton - - - False - True - - - - - True - .uno:ImageControl - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FileControl - - - False - True - - - - - True - .uno:NavigationBar - - - False - True - - - - - True - .uno:Grid - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:FormProperties - - - False - True - - - - - True - .uno:TabDialog - - - False - True - - - - - True - .uno:ControlProperties - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:ShowFmExplorer - - - False - True - - - - - True - .uno:OpenReadOnly - - - False - True - - - - - True - .uno:AutoControlFocus - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 9 - - True @@ -18634,29 +13536,29 @@ True - False + False end center True True - False + False center True vertical - _Tools + _Tools True - True - False - False + True + False + False end center True none - True + True False @@ -18667,16 +13569,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True - .uno:OptionsTreeDialog + .uno:OptionsTreeDialog False @@ -18701,27 +13603,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 15 @@ -18730,13 +13615,13 @@ True - False - ~Tools - True + False + ~Tools + True 15 - False + False @@ -18748,8 +13633,8 @@ - 0 - 0 + 0 + 0 diff --git a/sd/uiconfig/sdraw/ui/notebookbar_compact.ui b/sd/uiconfig/sdraw/ui/notebookbar_compact.ui index 8268f1d0e82f..a720145e40c3 100644 --- a/sd/uiconfig/sdraw/ui/notebookbar_compact.ui +++ b/sd/uiconfig/sdraw/ui/notebookbar_compact.ui @@ -861,13 +861,6 @@ .uno:QuestionAnswers - - - True - False - .uno:SendFeedback - - True diff --git a/sd/uiconfig/sdraw/ui/notebookbar_online.ui b/sd/uiconfig/sdraw/ui/notebookbar_online.ui deleted file mode 100644 index 836917f66967..000000000000 --- a/sd/uiconfig/sdraw/ui/notebookbar_online.ui +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - True - False - - - True - False - vertical - - - True - True - True - - - True - True - .uno:CharFontName - - - True - True - - - - - True - True - 0 - - - - - True - True - 5 - - - True - .uno:FontHeight - - - True - True - - - - - False - True - 1 - - - - - True - True - icons - False - - - - - - False - True - 0 - - - - - 0 - 0 - - - - diff --git a/sd/uiconfig/sdraw/ui/paranumberingtab.ui b/sd/uiconfig/sdraw/ui/paranumberingtab.ui index bbccd84397ee..da7ac4e8a375 100644 --- a/sd/uiconfig/sdraw/ui/paranumberingtab.ui +++ b/sd/uiconfig/sdraw/ui/paranumberingtab.ui @@ -1,40 +1,40 @@ - + 9999 - 1 - 10 + 1 + 10 True - False - 6 - 0 - none + False + 6 + 0 + none - + True - False - 6 - 6 + False 12 6 + 6 + 6 R_estart at this paragraph True - True - False - True + True + False + True True - True + True - 0 - 0 + 0 + 0 2 @@ -42,13 +42,13 @@ True False - False + False True adjustment1 - 1 - 1 + 1 + 1 @@ -56,17 +56,17 @@ S_tart with: True False - True - False + True + False start 12 - True + True True - True + True - 0 - 1 + 0 + 1 @@ -74,7 +74,7 @@ True - False + False Paragraph Numbering diff --git a/sd/uiconfig/simpress/menubar/menubar.xml b/sd/uiconfig/simpress/menubar/menubar.xml index b721f938b6b2..9296443941e6 100644 --- a/sd/uiconfig/simpress/menubar/menubar.xml +++ b/sd/uiconfig/simpress/menubar/menubar.xml @@ -22,11 +22,11 @@ - - + + - + @@ -39,7 +39,7 @@ - + @@ -48,8 +48,8 @@ - - + + @@ -66,7 +66,7 @@ - + @@ -74,7 +74,7 @@ - + @@ -85,21 +85,21 @@ - + - - + + - - + + - + - - + + @@ -111,13 +111,13 @@ - - - - - - - + + + + + + + @@ -127,98 +127,98 @@ - - + + - - + + - + - - + + - - - - - + + + + + - + - - - + + + - - - - - - - - + + + + + + + + - + - - - + + + - - - + + + - - - - + + + + - + - + - - - - + + + + - - - + + + - + - + - - - + + + - + - + @@ -230,20 +230,20 @@ - - - - - - + + + + + + - + - + @@ -260,56 +260,56 @@ - - + + - - - - + + + + - - - - - + + + + + - + - - - - - - + + + + + + - - + + - - - - - - + + + + + + - + - - + + - - + + - + @@ -324,8 +324,8 @@ - - + + @@ -343,20 +343,20 @@ - + - - - + + + - - + + - - + + - + @@ -371,16 +371,16 @@ - + - - + + - - + + @@ -388,8 +388,8 @@ - - + + @@ -397,119 +397,119 @@ - + - + - - - - + + + + - + - - - - + + + + - + - - + + - - - + + + - + - - + + - - - + + + - + - - - - - - - - - - - + + + + + + + + + + + - + - + - + - - - - + + + + - - + + - + - - - + + + - - + + - + - - - - - - - + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + + - + - - - - + + + + @@ -519,141 +519,141 @@ - + - - - - - + + + + + - - - - - - - + + + + + + + - - - - + + + + - + - - - + + + - - - + + + - - - + + + - - - + + + - + - - - - + + + + - - - - - + + + + + - + - + - - - + + + - + - + - + - + - - + + - + - + - - - - + + + + - - + + - - + + - - - + + + - - + + - + - + - - - - + + + + - + - + - + @@ -661,7 +661,7 @@ - + @@ -669,21 +669,20 @@ - + - - + - + - + diff --git a/sd/uiconfig/simpress/popupmenu/drawtext.xml b/sd/uiconfig/simpress/popupmenu/drawtext.xml index 43d359ea98ee..c92f7a5bcb9a 100644 --- a/sd/uiconfig/simpress/popupmenu/drawtext.xml +++ b/sd/uiconfig/simpress/popupmenu/drawtext.xml @@ -11,7 +11,12 @@ - + + + + + + diff --git a/sd/uiconfig/simpress/popupmenu/objectalign.xml b/sd/uiconfig/simpress/popupmenu/objectalign.xml index 168cd891ad43..dd05b17dfcf0 100644 --- a/sd/uiconfig/simpress/popupmenu/objectalign.xml +++ b/sd/uiconfig/simpress/popupmenu/objectalign.xml @@ -8,6 +8,8 @@ * --> + + @@ -15,6 +17,4 @@ - - diff --git a/sd/uiconfig/simpress/popupmenu/pagepane.xml b/sd/uiconfig/simpress/popupmenu/pagepane.xml index 78f3dc9ed040..afe5cb93172d 100644 --- a/sd/uiconfig/simpress/popupmenu/pagepane.xml +++ b/sd/uiconfig/simpress/popupmenu/pagepane.xml @@ -60,4 +60,8 @@ + + + + diff --git a/sd/uiconfig/simpress/popupmenu/sectionheader.xml b/sd/uiconfig/simpress/popupmenu/sectionheader.xml new file mode 100644 index 000000000000..64396c78cb70 --- /dev/null +++ b/sd/uiconfig/simpress/popupmenu/sectionheader.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/sd/uiconfig/simpress/statusbar/statusbar.xml b/sd/uiconfig/simpress/statusbar/statusbar.xml index c0a923e4a609..a2b5245735eb 100644 --- a/sd/uiconfig/simpress/statusbar/statusbar.xml +++ b/sd/uiconfig/simpress/statusbar/statusbar.xml @@ -18,11 +18,11 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . --> + - diff --git a/sd/uiconfig/simpress/toolbar/alignmentbar.xml b/sd/uiconfig/simpress/toolbar/alignmentbar.xml index 206dd8bed4a0..e7ec77b3c344 100644 --- a/sd/uiconfig/simpress/toolbar/alignmentbar.xml +++ b/sd/uiconfig/simpress/toolbar/alignmentbar.xml @@ -18,6 +18,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . --> + + @@ -25,5 +27,4 @@ - - \ No newline at end of file + diff --git a/sd/uiconfig/simpress/toolbar/drawingobjectbar.xml b/sd/uiconfig/simpress/toolbar/drawingobjectbar.xml index 829657583355..f683fcffca45 100644 --- a/sd/uiconfig/simpress/toolbar/drawingobjectbar.xml +++ b/sd/uiconfig/simpress/toolbar/drawingobjectbar.xml @@ -22,6 +22,8 @@ + + @@ -29,7 +31,6 @@ - diff --git a/sd/uiconfig/simpress/toolbar/graphicobjectbar.xml b/sd/uiconfig/simpress/toolbar/graphicobjectbar.xml index a9f5d1c17b45..feb79f500a94 100644 --- a/sd/uiconfig/simpress/toolbar/graphicobjectbar.xml +++ b/sd/uiconfig/simpress/toolbar/graphicobjectbar.xml @@ -22,6 +22,8 @@ + + @@ -29,7 +31,6 @@ - diff --git a/sd/uiconfig/simpress/ui/headerfooterdialog.ui b/sd/uiconfig/simpress/ui/headerfooterdialog.ui index 2a7485fa380c..0c747153bc57 100644 --- a/sd/uiconfig/simpress/ui/headerfooterdialog.ui +++ b/sd/uiconfig/simpress/ui/headerfooterdialog.ui @@ -1,33 +1,33 @@ - + - False - 6 + False + 6 Header and Footer True - 0 - 0 - dialog + 0 + 0 + dialog - False + False vertical 12 - False - end + False + end Appl_y to All True - True - True - True - True - True + True + True + True + True + True Applies the settings to all the slides in your presentation, including the corresponding master slides. @@ -44,9 +44,9 @@ _Apply True - True - True - True + True + True + True Applies the current settings to the selected slides. @@ -63,9 +63,9 @@ _Cancel True - True - True - True + True + True + True False @@ -77,8 +77,8 @@ _Help True - True - True + True + True True @@ -92,47 +92,23 @@ False True - end + end 0 True - True + True True True True - True + True True - False - - - - - - - - - - - - - - - - - - - - - - - - + False @@ -141,42 +117,18 @@ True - False + False Slides - False + False True - False - - - - - - - - - - - - - - - - - - - - - - - - + False @@ -188,12 +140,12 @@ True - False + False Notes and Handouts 1 - False + False @@ -211,9 +163,6 @@ cancel help - - - Adds or changes text in placeholders at the top and the bottom of slides and master slides. diff --git a/sd/uiconfig/simpress/ui/notebookbar.ui b/sd/uiconfig/simpress/ui/notebookbar.ui index 7a2017aa4ef6..7951c0dab830 100644 --- a/sd/uiconfig/simpress/ui/notebookbar.ui +++ b/sd/uiconfig/simpress/ui/notebookbar.ui @@ -1,2377 +1,2378 @@ - + - - - - - - - - - - True - False + False True - False - AddonCommand + False + AddonCommand True - False + False True - False - .uno:ExtensionManager + False + .uno:ExtensionManager True - False + False True - False - .uno:ChangeBezier + False + .uno:ChangeBezier True - False - .uno:ChangePolygon + False + .uno:ChangePolygon True - False - .uno:convert_to_contour + False + .uno:convert_to_contour True - False - .uno:ConvertInto3D + False + .uno:ConvertInto3D True - False - .uno:ConvertInto3DLatheFast + False + .uno:ConvertInto3DLatheFast True - False - .uno:ConvertIntoBitmap + False + .uno:ConvertIntoBitmap True - False - .uno:ConvertIntoMetaFile + False + .uno:ConvertIntoMetaFile True - False + False True - False - .uno:ToggleObjectBezierMode + False + .uno:ToggleObjectBezierMode True - False - .uno:ToggleObjectRotateMode + False + .uno:ToggleObjectRotateMode True - False - .uno:MirrorVert + False + .uno:MirrorVert True - False - .uno:MirrorHorz + False + .uno:MirrorHorz True - False - .uno:AdvancedMode + False + .uno:AdvancedMode True - False + False True - False - .uno:Combine + False + .uno:Combine True - False - .uno:Dismantle + False + .uno:Dismantle True - False - .uno:Merge + False + .uno:Merge True - False - .uno:Substract + False + .uno:Substract True - False - .uno:Intersect + False + .uno:Intersect True - False - .uno:EqualizeWidth + False + .uno:EqualizeWidth True - False - .uno:EqualizeHeight + False + .uno:EqualizeHeight True - False - .uno:Connect + False + .uno:Connect True - False - .uno:Break + False + .uno:Break True - False + False True - False - .uno:CopyObjects + False + .uno:CopyObjects True - False - .uno:Morphing + False + .uno:Morphing True - False + False True - False - .uno:ChangeBezier + False + .uno:ChangeBezier True - False - .uno:ChangePolygon + False + .uno:ChangePolygon True - False - .uno:convert_to_contour + False + .uno:convert_to_contour True - False - .uno:ConvertInto3D + False + .uno:ConvertInto3D True - False - .uno:ConvertInto3DLatheFast + False + .uno:ConvertInto3DLatheFast True - False - .uno:ConvertIntoBitmap + False + .uno:ConvertIntoBitmap True - False - .uno:ConvertIntoMetaFile + False + .uno:ConvertIntoMetaFile True - False + False True - False - .uno:NameGroup + False + .uno:NameGroup True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - .uno:InsertDateFieldFix + False + .uno:InsertDateFieldFix True - False - .uno:InsertDateFieldVar + False + .uno:InsertDateFieldVar True - False - .uno:InsertTimeFieldFix + False + .uno:InsertTimeFieldFix True - False - .uno:InsertTimeFieldVar + False + .uno:InsertTimeFieldVar True - False + False True - False - .uno:InsertAuthorField + False + .uno:InsertAuthorField True - False - .uno:InsertSlideField + False + .uno:InsertSlideField True - False - .uno:InsertSlideTitleField + False + .uno:InsertSlideTitleField True - False - .uno:InsertSlidesField + False + .uno:InsertSlidesField True - False - .uno:InsertFileField + False + .uno:InsertFileField True - False + False True - False - .uno:AddDirect + False + .uno:AddDirect True - False - .uno:RecentFileList + False + .uno:RecentFileList True - False - .uno:CloseDoc + False + .uno:CloseDoc True - False + False True - False - .uno:Save + False + .uno:Save True - False - .uno:SaveAs + False + .uno:SaveAs True - False - .uno:SaveAsRemote + False + .uno:SaveAsRemote True - False - .uno:SaveACopy + False + .uno:SaveACopy True - False + False True - False - .uno:Reload + False + .uno:Reload True - False + False True - False - .uno:ExportTo + False + .uno:ExportTo True - False - .uno:ExportToPDF + False + .uno:ExportToPDF True - False + False True - False - .uno:SendMail + False + .uno:SendMail True - False - .uno:SendMailDocAsPDF + False + .uno:SendMailDocAsPDF True - False - .uno:SendViaBluetooth + False + .uno:SendViaBluetooth True - False + False True - False - .uno:WebHtml + False + .uno:WebHtml True - False - .uno:Print + False + .uno:Print - False - False - .uno:PrintDefault + False + .uno:PrintDefault True - False - .uno:PrinterSetup + False + .uno:PrinterSetup True - False + False True - False - .uno:Signature + False + .uno:Signature True - False - .uno:SignPDF + False + .uno:SignPDF True - False - .uno:SetDocumentProperties + False + .uno:SetDocumentProperties True - False + False True - False - .uno:Quit + False + .uno:Quit True - False + False True - False - .uno:Label + False + .uno:Label True - False - .uno:Edit + False + .uno:Edit True - False - .uno:CheckBox + False + .uno:CheckBox True - False - .uno:RadioButton + False + .uno:RadioButton True - False - .uno:ListBox + False + .uno:ListBox True - False - .uno:ComboBox + False + .uno:ComboBox True - False + False True - False - .uno:Pushbutton + False + .uno:Pushbutton True - False - .uno:Imagebutton + False + .uno:Imagebutton True - False + False True - False - .uno:FormattedField + False + .uno:FormattedField True - False + False True - False - .uno:DateField + False + .uno:DateField True - False - .uno:TimeField + False + .uno:TimeField True - False - .uno:NumericField + False + .uno:NumericField True - False - .uno:CurrencyField + False + .uno:CurrencyField True - False - .uno:PatternField + False + .uno:PatternField True - False + False True - False - .uno:ImageControl + False + .uno:ImageControl True - False - .uno:FileControl + False + .uno:FileControl True - False + False True - False - .uno:Grid + False + .uno:Grid True - False - .uno:NavigationBar + False + .uno:NavigationBar True - False + False True - False - .uno:HelpIndex + False + .uno:HelpIndex True - False - .uno:ExtendedHelp + False + .uno:ExtendedHelp True - False - .uno:Documentation + False + .uno:Documentation True - False + False True - False - .uno:QuestionAnswers - - - - - True - False - .uno:SendFeedback + False + .uno:QuestionAnswers True - False + False True - False - .uno:SafeMode + False + .uno:SafeMode True - False - .uno:GetInvolved + False + .uno:GetInvolved True - False + False True - False - .uno:Donation + False + .uno:Donation True - False + False True - False - .uno:ShowLicense + False + .uno:ShowLicense True - False + False True - False - .uno:About + False + .uno:About True - False + False True - False - .uno:Shadowed + False + .uno:Shadowed True - False - .uno:OutlineFont + False + .uno:OutlineFont True - False - .uno:Overline + False + .uno:Overline True - False + False True - False - .uno:ChangeCaseToUpper + False + .uno:ChangeCaseToUpper True - False - .uno:ChangeCaseToLower + False + .uno:ChangeCaseToLower True - False - .uno:ChangeCaseRotateCase + False + .uno:ChangeCaseRotateCase True - False + False True - False - .uno:ChangeCaseToSentenceCase + False + .uno:ChangeCaseToSentenceCase True - False - .uno:ChangeCaseToTitleCase + False + .uno:ChangeCaseToTitleCase True - False - .uno:ChangeCaseToToggleCase + False + .uno:ChangeCaseToToggleCase True - False + False True - False - .uno:InsertNonBreakingSpace + False + .uno:InsertNonBreakingSpace True - False - .uno:InsertHardHyphen + False + .uno:InsertHardHyphen True - False - .uno:InsertSoftHyphen + False + .uno:InsertSoftHyphen True - False - .uno:InsertZWSP + False + .uno:InsertZWSP True - False - .uno:InsertWJ + False + .uno:InsertWJ True - False - .uno:InsertLRM + False + .uno:InsertLRM True - False - .uno:InsertRLM + False + .uno:InsertRLM True - False + False True - False - .uno:FontDialog + False + .uno:FontDialog True - False - .uno:ParagraphDialog + False + .uno:ParagraphDialog True - False + False True - False - .uno:ParaLeftToRight + False + .uno:ParaLeftToRight True - False - .uno:ParaRightToLeft + False + .uno:ParaRightToLeft True - False + False True - False - .uno:SelectAll + False + .uno:SelectAll True - False + False True - False - vnd.sun.star.findbar:FocusToFindbar + False + vnd.sun.star.findbar:FocusToFindbar True - False - .uno:SearchDialog + False + .uno:SearchDialog True - False - .uno:RestoreEditingView + False + .uno:RestoreEditingView True - False + False True - False - .uno:Crop + False + .uno:Crop True - False - .uno:ExternalEdit + False + .uno:ExternalEdit True - False - .uno:ChangePicture + False + .uno:ChangePicture True - False - .uno:CompressGraphic + False + .uno:CompressGraphic True - False - .uno:SaveGraphic + False + .uno:SaveGraphic True - False + False True - False - .uno:OriginalSize + False + .uno:OriginalSize True - False - .uno:ImageMapDialog + False + .uno:ImageMapDialog True - False + False True - False - .uno:NameGroup + False + .uno:NameGroup True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - .uno:AnimationEffects + False + .uno:AnimationEffects True - False + False True - False - .uno:PhotoAlbumDialog + False + .uno:PhotoAlbumDialog True - False - .uno:AnimationObjects + False + .uno:AnimationObjects True - False + False True - False - .uno:Gallery + False + .uno:Gallery True - False - .uno:TwainSelect + False + .uno:TwainSelect True - False - .uno:InsertAVMedia + False + .uno:InsertAVMedia True - False + False True - False - .uno:InsertQrCode + False + .uno:InsertQrCode True - False - .uno:InsertObject + False + .uno:InsertObject True - False - .uno:ImportSlideFromFile + False + .uno:ImportSlideFromFile True - False - .uno:InsertMath + False + .uno:InsertMath True - False + False True - False - .uno:Text + False + .uno:Text True - False - .uno:VerticalText + False + .uno:VerticalText True - False - .uno:FontworkGalleryFloater + False + .uno:FontworkGalleryFloater True - False + False True - False - .uno:HyperlinkDialog + False + .uno:HyperlinkDialog True - False - .uno:CapturePoint + False + .uno:CapturePoint True - False + False True - False - .uno:InsertSlideField + False + .uno:InsertSlideField True - False - .uno:InsertSlidesField + False + .uno:InsertSlidesField True - False - .uno:HeaderAndFooter + False + .uno:HeaderAndFooter True - False + False True - False - .uno:InsertMasterPage + False + .uno:InsertMasterPage True - False - .uno:RenameMasterPage + False + .uno:RenameMasterPage True - False - .uno:DeleteMasterPage + False + .uno:DeleteMasterPage True - False - .uno:CloseMasterView + False + .uno:CloseMasterView True - False + False True - False - .uno:AVMediaPlayer + False + .uno:AVMediaPlayer True - False + False True - False - .uno:NameGroup + False + .uno:NameGroup True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False + False True - False - .uno:AnimationEffects + False + .uno:AnimationEffects True - False + False True - False - .uno:ChainFrames + False + .uno:ChainFrames True - False - .uno:UnhainFrames + False + .uno:UnhainFrames True - False + False True - False - .uno:NameGroup + False + .uno:NameGroup True - False - .uno:ObjectTitleDescription + False + .uno:ObjectTitleDescription True - False - .uno:FrameDialog + False + .uno:FrameDialog True - False + False True - False - .uno:InsertFootnoteDialog + False + .uno:InsertFootnoteDialog True - False + False True - False - .uno:AddressBookSource + False + .uno:AddressBookSource True - False + False True - False - .uno:UpdateAll + False + .uno:UpdateAll True - False - .uno:Repaginate + False + .uno:Repaginate True - False - .uno:UpdateFields + False + .uno:UpdateFields True - False - .uno:UpdateAllIndexes + False + .uno:UpdateAllIndexes True - False - .uno:UpdateCurIndex + False + .uno:UpdateCurIndex True - False - .uno:UpdateAllLinks + False + .uno:UpdateAllLinks True - False - .uno:UpdateCharts + False + .uno:UpdateCharts True - False - .uno:CalculateSel + False + .uno:CalculateSel True - False + False True - False - .uno:SpellDialog + False + .uno:SpellDialog True - False - .uno:SpellOnline + False + .uno:SpellOnline True - False - .uno:ThesaurusDialog + False + .uno:ThesaurusDialog True - False + False True - False - .uno:SetLanguageAllTextMenu + False + .uno:SetLanguageAllTextMenu True - False - .uno:Hyphenation + False + .uno:Hyphenation True - False - .uno:ChineseConversion + False + .uno:ChineseConversion True - False - .uno:HangulHanjaConversion + False + .uno:HangulHanjaConversion True - False - .uno:MoreDictionaries + False + .uno:MoreDictionaries True - False + False True - False - .uno:InsertSlide + False + .uno:InsertSlide True - False - .uno:DuplicateSlide + False + .uno:DuplicateSlide True - False - .uno:DeleteSlide + False + .uno:DeleteSlide True - False + False True - False - .uno:ModifyPage + False + .uno:ModifyPage True - False - .uno:SlideSetup + False + .uno:SlideSetup True - False - .uno:SelectBackground + False + .uno:SelectBackground True - False + False True - False - .uno:InsertMasterPage + False + .uno:InsertMasterPage True - False - .uno:DeleteMasterPage + False + .uno:DeleteMasterPage True - False + False True - False - .uno:PresentationLayout + False + .uno:PresentationLayout True - False - .uno:DisplayMasterBackground + False + .uno:DisplayMasterBackground True - False - .uno:DisplayMasterObjects + False + .uno:DisplayMasterObjects True - False + False True - False - .uno:HideSlide + False + .uno:HideSlide True - False - .uno:ShowSlide + False + .uno:ShowSlide True - False - .uno:RenameSlide + False + .uno:RenameSlide True - False + False True - False - .uno:ImportSlideFromFile + False + .uno:ImportSlideFromFile True - False - .uno:SummaryPage + False + .uno:SummaryPage True - False - .uno:ExpandPage + False + .uno:ExpandPage True - False + False True - False - .uno:MoveSlideUp + False + .uno:MoveSlideUp True - False - .uno:MoveSlideDown + False + .uno:MoveSlideDown True - False + False True - False - .uno:Presentation + False + .uno:Presentation True - False - .uno:PresentationCurrentSlide + False + .uno:PresentationCurrentSlide True - False + False True - False - .uno:RehearseTimings + False + .uno:RehearseTimings True - False - .uno:CustomShowDialog + False + .uno:CustomShowDialog True - False - .uno:Remote + False + .uno:Remote True - False + False True - False - .uno:SlideChangeWindow + False + .uno:SlideChangeWindow True - False - .uno:CustomAnimation + False + .uno:CustomAnimation True - False + False True - False - .uno:OutputQualityColor + False + .uno:OutputQualityColor True - False - .uno:OutputQualityGrayscale + False + .uno:OutputQualityGrayscale True - False + False True - False - .uno:PresentationMinimizer + False + .uno:PresentationMinimizer True - False - .uno:PresentationDialog + False + .uno:PresentationDialog True - False + False True - False - .uno:AutoFormat + False + .uno:AutoFormat True - False - .uno:ObjectAlign + False + .uno:ObjectAlign True - False + False True - False - .uno:InsertRowDialog + False + .uno:InsertRowDialog True - False - .uno:InsertColumnDialog + False + .uno:InsertColumnDialog True - False + False True - False - .uno:SetRowHeight + False + .uno:SetRowHeight True - False - .uno:SetOptimalRowHeight + False + .uno:SetOptimalRowHeight True - False - .uno:DistributeRows + False + .uno:DistributeRows True - False - .uno:SetColumnWidth + False + .uno:SetColumnWidth True - False - .uno:SetOptimalColumnWidth + False + .uno:SetOptimalColumnWidth True - False - .uno:DistributeColumns + False + .uno:DistributeColumns True - False + False True - False - .uno:Protect + False + .uno:Protect True - False - .uno:UnsetCellsReadOnly + False + .uno:UnsetCellsReadOnly True - False + False True - False - .uno:HeadingRowsRepeat + False + .uno:HeadingRowsRepeat True - False - .uno:RowSplit + False + .uno:RowSplit True - False + False True - False - .uno:ConvertTextToTable + False + .uno:ConvertTextToTable True - False - .uno:ConvertTableToText + False + .uno:ConvertTableToText True - False + False True - False - .uno:TableSort + False + .uno:TableSort True - False + False True - False - .uno:MergeTable + False + .uno:MergeTable True - False - .uno:TableNumberRecognition + False + .uno:TableNumberRecognition True - False - .uno:TableBoundaries + False + .uno:TableBoundaries True - False + False True - False - .uno:MacroRecorder + False + .uno:MacroRecorder True - False - .uno:RunMacro + False + .uno:RunMacro True - False - .uno:BasicIDEAppear + False + .uno:BasicIDEAppear True - False - .uno:MacroOrganizer?TabId:short=1 + False + .uno:MacroOrganizer?TabId:short=1 True - False - .uno:ScriptOrganizer + False + .uno:ScriptOrganizer True - False - .uno:MacroSignature + False + .uno:MacroSignature True - False - .uno:DevelopmentToolsDockingWindow + False + .uno:DevelopmentToolsDockingWindow True - False + False True - False - .uno:PresentationMinimizer + False + .uno:PresentationMinimizer True - False - .uno:BmpMask + False + .uno:BmpMask True - False - .uno:AVMediaPlayer + False + .uno:AVMediaPlayer True - False + False True - False - .uno:ViewDataSourceBrowser + False + .uno:ViewDataSourceBrowser True - False + False True - False - .uno:OpenXMLFilterSettings + False + .uno:OpenXMLFilterSettings True - False + False True - False - .uno:NormalMultiPaneGUI + False + .uno:NormalMultiPaneGUI True - False - .uno:OutlineMode + False + .uno:OutlineMode True - False - .uno:NotesMode + False + .uno:NotesMode True - False - .uno:DiaMode + False + .uno:DiaMode True - False + False True - False - .uno:SlideMasterPage + False + .uno:SlideMasterPage True - False - .uno:NotesMasterPage + False + .uno:NotesMasterPage True - False - .uno:HandoutMode + False + .uno:HandoutMode True - False + False True - False - .uno:Menubar + False + .uno:Menubar True - False - .uno:Sidebar + False + .uno:Sidebar True - False - .uno:StatusBarVisible + False + .uno:StatusBarVisible True - False + False True - False - .uno:LeftPaneImpress + False + .uno:LeftPaneImpress True - False - .uno:ToggleTabBarVisibility + False + .uno:ToggleTabBarVisibility True - False - .uno:ShowRuler + False + .uno:ShowRuler True - False + False True - False - .uno:GridVisible + False + .uno:GridVisible True - False - .uno:GridUse + False + .uno:GridUse True - False + False True - False - .uno:HelplinesVisible + False + .uno:HelplinesVisible True - False - .uno:HelplinesUse + False + .uno:HelplinesUse True - False + False True - False - .uno:OutputQualityColor + False + .uno:OutputQualityColor True - False - .uno:OutputQualityGrayscale + False + .uno:OutputQualityGrayscale True - False + False True - False - .uno:ZoomPage + False + .uno:ZoomPage True - False - .uno:Zoom100Percent + False + .uno:Zoom100Percent - - True - False - cmd/lc_changebezier.png - - - True - False - cmd/lc_insertfieldctrl.png - True - False + False True - False + False + 6 + 6 + 6 + 6 vertical True - True + True True - + True - False + False - + True - False + False center - True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + New + + + + + + + + + + 0 + 2 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:AddDirect + .uno:AddDirect False @@ -2380,11 +2381,53 @@ - False - True - 0 + 0 + 0 + 2 + + + True + False + both + False + 3 + center + True + + + True + .uno:NewDoc + True + + + False + True + + + + + 1 + 0 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -2393,75 +2436,179 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Document + + + + + + + + + + 0 + 2 + 4 + + + + + True + False center - vertical + True + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:NewDoc - True - - - False - True - - + .uno:Open + True False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:SaveAsTemplate - True - - - False - True - - - - - False - True - 1 + True - False - True - 1 + 0 + 0 + 2 - + + + True + False + center + True + both + False + 3 + + + True + .uno:Save + True + + + False + True + + + + + 1 + 0 + 2 + + + + + True + False + center + 3 + True + both + False + 3 + + + True + .uno:ExportTo + True + + + False + True + + + + + 2 + 0 + 2 + + + + + True + False + both-horiz + False + + + True + .uno:ExportDirectToPDF + True + + + False + True + + + + + 3 + 0 + + + + + True + False + vertical + + + 4 + 0 + 3 + + + + + True + False + both-horiz + + + True + .uno:SendMail + True + + + False + True + + + + + 3 + 1 + + + + + False @@ -2470,40 +2617,30 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True + False center True - both - False + both + False 3 - + True - .uno:Open - True + .uno:Print + True False @@ -2512,11 +2649,93 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + end + True + Print + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + both-horiz + False + + + True + .uno:PrintDefault + True + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:WebHtml + True + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + False @@ -2525,40 +2744,30 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True + False center True - both - False + both + False 3 - + True - .uno:Save - True + .uno:SetDocumentProperties + True False @@ -2567,11 +2776,93 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:Signature + True + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:SignPDF + True + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False + end + True + Properties + + + + + + + + + + 0 + 2 + 3 + + + + + False @@ -2579,402 +2870,6 @@ 3 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ExportTo - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ExportDirectToPDF - True - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:SendMail - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Print - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:PrintDefault - True - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:WebHtml - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SetDocumentProperties - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:Signature - True - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:SignPDF - True - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - True @@ -2985,96 +2880,30 @@ True - False + False end center True - - - True - False - center - True - vertical - - - True - True - end - True - icons - False - 1 - - - True - .uno:CloseDoc - - - False - True - - - - - False - True - 0 - - - - - True - True - end - True - icons - False - 1 - - - True - .uno:HelpIndex - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - True - False + False center 5 True vertical - _File + _File True - True - False - False + True + False + False end center True none - True + True False @@ -3084,165 +2913,16 @@ - _Help + _Help True - True - False - False + True + False + False end center True none - True - - - False - True - 1 - - - - - False - True - 2 - - - - - False - False - end - 1 - - - - - True - False - end - 5 - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - - - - - True - False - ~File - True - - - False - - - - - True - False - center - True - - - True - False - center - True - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:Paste - - - False - False - - - - - False - True - 0 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:Cut - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Copy - - - False - True - - - - - False - True - 1 - - + True False @@ -3257,93 +2937,601 @@ 0 + + + False + False + end + 1 + + + + + + + True + False + ~File + True + + + False + + + + + True + False + center + True + + + True + False + center + True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Clipboard + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - False + False center - vertical + True + both + False + 3 - + True - True - center - True - both-horiz - False - - - True - .uno:FormatPaintbrush - - - False - True - - + .uno:Paste False - True - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:SetDefault - - - False - True - - - - - False - True - 1 + False - False - True - 1 + 0 + 0 + 2 - + + + True + False + both-horiz + False + + + True + .uno:Cut + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:Copy + + + False + True + + + + + 1 + 1 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + + + + False + True + 0 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + end + True + Slide + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:InsertSlide + + + False + False + + + + + 0 + 0 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False + both-horiz + False + + + True + .uno:DuplicateSlide + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:PresentationLayout + + + False + True + + + + + 1 + 1 + + + + + + + + False + True + 1 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + end + True + Font + + + + + + + + + + 0 + 2 + 5 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:FormatPaintbrush + + + False + True + + + + + 0 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:SetDefault + + + False + True + + + + + 0 + 1 + + + + + True + False + center + True + + + True + True + .uno:CharFontName + + + True + True + + + + + 1 + 0 + 2 + + + + + True + False + center + + + True + .uno:FontHeight + + + True + True + + + + + 3 + 0 + + + + + True + False + center + icons + False + + + True + .uno:Bold + + + False + True + + + + + True + .uno:Italic + + + False + True + + + + + True + .uno:Underline + + + False + True + + + + + True + .uno:Strikeout + + + False + True + + + + + .uno:Shadowed + + + False + True + + + + + 1 + 1 + + + + + True + False + center + icons + False + + + True + .uno:SubScript + + + False + True + + + + + True + .uno:SuperScript + + + False + True + + + + + 2 + 1 + + + + + True + False + center + icons + False + + + True + .uno:Spacing + + + False + False + + + + + True + .uno:CharBackColor + + + False + False + + + + + True + .uno:Color + + + False + False + + + + + 3 + 1 + 2 + + + + + True + False + center + icons + False + + + True + .uno:Grow + + + False + True + + + + + True + .uno:Shrink + + + False + True + + + + + 4 + 0 + + + + + True + False + vertical + + + 5 + 0 + 3 + + + + + False @@ -3352,256 +3540,278 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Paragraph + + + + + + + + + + 0 + 2 + 3 + + + + + True + False vertical + + + 3 + 0 + 3 + + + + + True + False + center + 6 + icons + False - + True - False - center - True - - - True - True - center - True - - - True - True - .uno:CharFontName - - - True - True - - - - - True - True - 0 - - - - - True - True - center - 5 - - - True - .uno:FontHeight - - - True - True - - - - - False - True - 1 - - - - - True - True - end - center - icons - False - - - True - .uno:Grow - - - False - True - - - - - True - .uno:Shrink - - - False - True - - - - - False - True - 2 - - + .uno:DefaultBullet False - True - 0 + True - + True - False - center - True - - - True - True - icons - False - - - True - .uno:Bold - - - False - True - - - - - True - .uno:Italic - - - False - True - - - - - True - .uno:Underline - - - False - True - - - - - True - .uno:Strikeout - - - False - True - - - - - True - .uno:Shadowed - - - False - True - - - - - False - True - 0 - - - - - True - False - end - 5 - 5 - True - vertical - - - False - True - 5 - 2 - - - - - True - True - center - icons - False - - - True - .uno:Spacing - - - False - False - - - - - True - .uno:CharBackColor - - - False - False - - - - - True - .uno:Color - - - False - False - - - - - False - True - 3 - - + .uno:DefaultNumbering False - True - 2 + True - False - True - 1 + 0 + 0 + + + True + False + center + 6 + icons + False + + + True + center + True + .uno:StartPara + + + False + True + + + + + True + center + True + .uno:CenterPara + + + False + True + + + + + True + center + True + .uno:EndPara + + + False + True + + + + + True + center + True + .uno:JustifyPara + + + False + True + + + + + 0 + 1 + + + + + True + False + icons + False + + + True + center + True + .uno:IncrementIndent + + + False + True + + + + + True + center + True + .uno:DecrementIndent + + + False + True + + + + + True + center + True + .uno:HangingIndent + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:ParaLeftToRight + + + False + True + + + + + True + .uno:ParaRightToLeft + + + False + True + + + + + 2 + 0 + + + + + True + False + icons + False + + + True + end + .uno:LineSpacing + + + False + False + + + + + True + center + True + .uno:ParaspaceIncrease + + + False + True + + + + + True + center + True + .uno:ParaspaceDecrease + + + False + True + + + + + 1 + 1 + + + + + + + + False @@ -3609,924 +3819,6 @@ 3 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - False - center - True - - - True - True - center - icons - False - - - True - center - True - .uno:CellVertTop - - - False - True - - - - - True - .uno:CellVertCenter - - - False - True - - - - - True - center - True - .uno:CellVertBottom - - - False - True - - - - - False - True - 0 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - True - center - icons - False - - - True - center - True - .uno:StartPara - - - False - True - - - - - True - center - True - .uno:CenterPara - - - False - True - - - - - True - center - True - .uno:EndPara - - - False - True - - - - - False - True - 0 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - True - True - center - icons - False - - - True - .uno:DefaultBullet - - - False - True - - - - - True - .uno:DefaultNumbering - - - False - True - - - - - .uno:SetOutline - - - False - True - - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - True - icons - False - - - True - center - True - .uno:JustifyPara - - - False - True - - - - - False - True - 0 - - - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - True - True - end - center - True - icons - False - - - True - end - .uno:LineSpacing - - - False - False - - - - - False - True - 2 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - icons - False - - - True - center - True - .uno:OutlineRight - - - False - True - - - - - True - center - True - .uno:OutlineLeft - - - False - True - - - - - True - .uno:ParaLeftToRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:ParaspaceIncrease - - - False - True - - - - - True - .uno:ParaspaceDecrease - - - False - True - - - - - True - .uno:ParaRightToLeft - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Text - - - False - True - - - - - True - .uno:VerticalText - - - False - True - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - False - center - - - True - True - icons - False - - - True - .uno:Line - - - False - True - - - - - True - .uno:LineToolbox - - - False - True - - - - - False - True - 0 - - - - - False - True - 0 - - - - - True - False - center - - - True - True - icons - False - - - True - .uno:BasicShapes.rectangle - - - False - True - - - - - True - .uno:BasicShapes - - - False - True - - - - - False - True - 0 - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - False - center - - - True - True - icons - False - - - True - .uno:ConnectorToolbox - - - False - True - - - - - False - True - 0 - - - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - True - True - icons - False - - - True - .uno:XLineColor - - - False - True - - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - False - center - - - True - True - icons - False - - - True - .uno:FlowChartShapes - - - False - True - - - - - False - True - 0 - - - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 1 - - - - - True - True - icons - False - - - True - .uno:FillColor - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:Presentation - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:PresentationCurrentSlide - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 10 - - True @@ -4537,29 +3829,29 @@ True - False + False end center True True - False + False center True vertical - _Home + _Home True - True - False - False + True + False + False end center True none - True + True False @@ -4570,18 +3862,18 @@ True - True + True end center True True - icons - False + icons + False 1 True - .uno:SearchDialog + .uno:SearchDialog False @@ -4592,7 +3884,7 @@ True center - .uno:Presentation + .uno:Presentation False @@ -4617,30 +3909,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - - - - 1 @@ -4649,9 +3921,9 @@ True - False - ~Home - True + False + ~Home + True + + + True + False + both-horiz + False + + + True + .uno:InsertObjectChart + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:InsertMath + + + False + True + + + + + 1 + 1 + + + + + False @@ -4790,39 +4196,62 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Graphic + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:InsertTable + .uno:InsertGraphic False @@ -4831,11 +4260,58 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:Gallery + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:InsertAVMedia + + + False + True + + + + + 1 + 1 + + + + + False @@ -4844,73 +4320,152 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Text + + + + + + + + + + 0 + 2 + 4 + + + + + True + False vertical + + + 3 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:InsertObjectChart - - - False - True - - + .uno:CharmapControl False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:InsertObject - - - False - True - - - - - False - True - 1 + True - False - True - 2 + 2 + 0 + 2 - + + + True + False + center + True + both-horiz + False + + + True + .uno:VerticalText + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:Text + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:HyperlinkDialog + + + False + True + + + + + 0 + 0 + 2 + + + + + False @@ -4919,52 +4474,146 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Fontwork + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:InsertGraphic + .uno:FontworkGalleryFloater False + False + + + + + 0 + 0 + 2 + + + + + True + False + center + True + icons + False + + + True + .uno:FontworkShapeType + + + True + True + + + + + True + .uno:FontworkSameLetterHeights + + + True True - False - True - 1 + 1 + 0 + + + True + False + center + True + icons + False + + + True + .uno:FontworkAlignmentFloater + + + True + True + + + + + True + .uno:FontworkCharacterSpacingFloater + + + True + True + + + + + 1 + 1 + + + + + False @@ -4973,73 +4622,262 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Drawing Objects + + + + + + + + + + 0 + 2 + 2 + + + + + True + False vertical + + + 2 + 0 + 3 + + + + + True + False + icons + False - + True - True - both-horiz - False - - - True - .uno:Gallery - - - False - True - - + .uno:Line - False - True - 0 + True + True - + True - True - both-horiz - False - - - True - .uno:PhotoAlbumDialog - - - False - True - - + .uno:ArrowsToolbox False - True - 1 + True + + + + + True + .uno:Polygon_Unfilled + True + + + False + True + + + + + True + .uno:Bezier_Unfilled + True + + + False + True + + + + + True + .uno:Objects3DToolbox + True + + + False + True - False - True - 2 + 0 + 0 - + + + True + False + icons + False + + + True + .uno:LineToolbox + + + False + True + + + + + True + .uno:BasicShapes.rectangle + + + True + True + + + + + True + .uno:BasicShapes.ellipse + + + True + True + + + + + True + .uno:DrawCaption + + + True + True + + + + + True + .uno:ConnectorToolbox + True + + + False + True + + + + + 0 + 1 + + + + + True + False + 6 + + + True + .uno:BasicShapes + + + True + True + + + + + True + .uno:SymbolShapes + + + True + True + + + + + True + .uno:ArrowShapes + + + True + True + + + + + 1 + 0 + + + + + True + False + 6 + + + True + .uno:StarShapes + + + True + True + + + + + True + .uno:CalloutShapes + + + True + True + + + + + True + .uno:FlowChartShapes + + + True + True + + + + + 1 + 1 + + + + + False @@ -5047,706 +4885,6 @@ 5 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:InsertAVMedia - - - False - True - - - - - False - True - 1 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:HyperlinkDialog - - - False - True - - - - - False - True - 1 - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:FontworkGalleryFloater - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - center - .uno:CapturePoint - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 8 - - - - - True - False - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - Fiel_d - 70 - True - True - True - .uno:FieldMenu - paragraphstylei - none - True - top - True - - - False - True - 1 - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Text - - - False - True - - - - - False - True - 1 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:VerticalText - - - False - True - - - - - False - True - 2 - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - icons - False - - - True - .uno:Line - - - True - True - - - - - True - .uno:Polygon_Unfilled - - - False - True - - - - - True - .uno:Bezier_Unfilled - - - False - True - - - - - True - .uno:ArrowsToolbox - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:BasicShapes.rectangle - - - True - True - - - - - True - .uno:BasicShapes.ellipse - - - True - True - - - - - True - .uno:DrawCaption - - - True - True - - - - - True - .uno:LineToolbox - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - - - True - .uno:BasicShapes - - - True - True - - - - - True - .uno:SymbolShapes - - - True - True - - - - - True - .uno:ArrowShapes - - - True - True - - - - - True - .uno:ConnectorToolbox - - - True - True - - - - - False - True - 0 - - - - - True - True - - - True - .uno:StarShapes - - - True - True - - - - - True - .uno:CalloutShapes - - - True - True - - - - - True - .uno:FlowChartShapes - - - True - True - - - - - True - .uno:Objects3DToolbox - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:CharmapControl - - - False - True - - - - - False - True - 1 - - - - - False - True - 13 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - both - False - 3 - - - True - .uno:InsertMath - - - False - True - - - - - False - True - 0 - - - - - False - True - 1 - - - - - - False - True - 14 - - True @@ -5757,28 +4895,28 @@ True - False + False end center True True - False + False center True vertical - _Insert + _Insert True - True - False - False + True + False + False end True none - True + True False @@ -5789,16 +4927,16 @@ True - True + True end True - icons - False + icons + False 1 True - .uno:InsertGraphic + .uno:InsertGraphic False @@ -5808,7 +4946,7 @@ True - .uno:Text + .uno:Text False @@ -5818,7 +4956,7 @@ True - .uno:InsertSlide + .uno:InsertSlide False @@ -5843,27 +4981,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 2 @@ -5872,46 +4993,83 @@ True - False - ~Insert - True + False + ~Insert + True 2 - False + False - + True - False + False center True - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Format + + + + + + + + + + 0 + 2 + + + + + True + False + vertical + + + 1 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:SlideSetup + .uno:SlideSetup False @@ -5919,9 +5077,9 @@ - + True - .uno:HeaderAndFooter + .uno:HeaderAndFooter False @@ -5930,11 +5088,14 @@ - False - True - 1 + 0 + 0 + 2 + + + False @@ -5943,74 +5104,167 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Slide + + + + + + + + + + 0 + 2 + 3 + + + + + True + False vertical + + + 3 + 0 + 3 + + + + + True + False + both-horiz + False - + True - True - both-horiz - False - - - True - .uno:SelectBackground - - - False - True - - + .uno:MoveSlideUp False - True - 0 - - - - - True - True - both-horiz - False - - - True - start - .uno:SaveBackground - - - True - True - - - - - False - True - 1 + True - False - True - 2 + 2 + 0 - + + + True + False + both-horiz + False + + + True + start + .uno:MoveSlideDown + + + False + False + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:HideSlide + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ShowSlide + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:RenameSlide + + + False + True + + + + + 0 + 0 + 2 + + + + + False @@ -6019,39 +5273,62 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Master + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:RenameSlide + .uno:PresentationLayout False @@ -6060,218 +5337,21 @@ - False - True - 1 - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:HideSlide - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ShowSlide - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 0 + 0 + 2 - + True - False - center - vertical + False + both-horiz + False - + True - True - both-horiz - False - - - True - .uno:MoveSlideUp - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - start - .uno:MoveSlideDown - - - False - False - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:PresentationLayout + .uno:DisplayMasterBackground False @@ -6280,127 +5360,20 @@ - False - True - 1 - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:DisplayMasterBackground - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:DisplayMasterObjects - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 1 + 0 - + True - True - center - True - both - False - 3 + False + both-horiz + False - + True - .uno:ToggleObjectRotateMode + .uno:DisplayMasterObjects False @@ -6409,91 +5382,142 @@ - False - True - 1 + 1 + 1 + + + False True - 11 + 2 - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Background + + + + + + + + + + 0 + 2 + 2 + + + + + True + False vertical + + + 2 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - both-horiz - False - - - True - .uno:ObjectAlign - - - False - True - - + .uno:ToggleObjectRotateMode False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ObjectPosition - - - False - True - - - - - False - True - 1 + True - False - True - 2 + 0 + 0 + 2 - + + + True + False + both-horiz + False + + + True + .uno:ObjectAlign + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ObjectPosition + + + False + True + + + + + 1 + 1 + + + + + False True - 12 + 3 @@ -6506,29 +5530,29 @@ True - False + False end center True True - False + False center True vertical - _Layout + _Layout True - True - False - False + True + False + False end center True none - True + True False @@ -6539,17 +5563,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True center - .uno:AssignLayout + .uno:AssignLayout False @@ -6574,27 +5598,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 3 @@ -6603,49 +5610,103 @@ True - False - ~Layout - True + False + ~Layout + True 3 - False + False - + True False - + True False center True - + + True False - 5 + 6 + 6 + 6 + 6 + 3 + 3 - + True False - .uno:ThemeSelectorPanel - True + end + True + Color Theme + + + + + + + - False - True + 0 + 2 + + + True + False + vertical + + + 1 + 0 + 3 + + + + + True + False + + + True + .uno:ThemeSelectorPanel + True + + + False + True + + + + + 0 + 0 + 2 + + + + + False True - 5 + 0 + + + True @@ -6662,7 +5723,7 @@ True False - ~Design + ~Design True @@ -6671,34 +5732,83 @@ - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Slide Show + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:Presentation + .uno:Presentation + + + False + True + + + + + True + .uno:PresentationCurrentSlide + True False @@ -6707,168 +5817,21 @@ - False - True - 0 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:PresentationCurrentSlide - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:RehearseTimings - - - True - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:CustomShowDialog - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 0 + 0 + 2 - + True - True - center - True - both - False - 3 + False + both-horiz + False - + True - center - .uno:PresentationDialog + .uno:RehearseTimings True @@ -6877,132 +5840,125 @@ - False - True - 1 + 1 + 0 - - - False - True - 3 - - - - - True - False - center - True - + True - False - center - True - vertical + False + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:SlideChangeWindow - - - False - True - - + .uno:CustomShowDialog - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:CustomAnimation - - - False - True - - - - - False - False - 1 + True + True - False - True - 2 + 1 + 1 - + + + False True - 4 + 0 - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Settings + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:PresentationMinimizer + center + .uno:PresentationDialog + + + True + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:SlideChangeWindow False @@ -7011,96 +5967,170 @@ - False - True - 1 + 1 + 0 - - - False - True - 5 - - - - - True - False - center - True - + True - False + False center True - vertical + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:OutputQualityColor - - - False - True - - + .uno:CustomAnimation False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:OutputQualityGrayscale - - - False - True - - - - - False - False - 1 + True - False - True - 1 + 1 + 1 - + + + False True - 6 + 1 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + end + True + Options + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:PresentationMinimizer + + + False + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:OutputQualityColor + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:OutputQualityGrayscale + + + False + True + + + + + 1 + 1 + + + + + + + + False + True + 2 @@ -7113,28 +6143,28 @@ True - False + False end center True True - False + False center True vertical - _Slide Show + _Slide Show True - True - False - False + True + False + False end True none - True + True False @@ -7145,17 +6175,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True center - .uno:Presentation + .uno:Presentation True @@ -7180,27 +6210,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 5 @@ -7209,44 +6222,80 @@ True - False - ~Slide Show - True + False + ~Slide Show + True 5 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Spelling + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:SpellDialog + .uno:SpellDialog False @@ -7254,9 +6303,9 @@ - + True - .uno:ThesaurusDialog + .uno:ThesaurusDialog False @@ -7265,128 +6314,21 @@ - False - True - 1 - - - - - False - True - 0 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:SpellOnline - - - True - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Hyphenation - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 0 + 0 + 2 - + True - True - center - True - both - False - 3 + False + both-horiz + False - + True - .uno:InsertAnnotation + .uno:SpellOnline True @@ -7395,11 +6337,339 @@ - False - True - 1 + 1 + 0 + + + True + False + both-horiz + False + + + True + .uno:Hyphenation + + + True + True + + + + + 1 + 1 + + + + + + + + False + True + 0 + + + + + + True + False + 3 + 3 + 6 + 6 + 3 + 3 + + + True + False + Comments + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + vertical + + + 4 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:InsertAnnotation + + + True + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:NextAnnotation + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:DeleteAnnotation + + + False + True + + + + + 2 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:PreviousAnnotation + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:DeleteAllAnnotation + + + False + True + + + + + 2 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:ShowAnnotations + + + False + True + + + + + 3 + 0 + 2 + + + + + + + + False + True + 1 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + Redact + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:RedactDoc + + + False + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:EditDoc + + + False + True + + + + + 1 + 0 + 2 + + + + + False @@ -7407,322 +6677,6 @@ 2 - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:NextAnnotation - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:PreviousAnnotation - - - False - True - - - - - False - False - 1 - - - - - False - True - 1 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:DeleteAnnotation - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DeleteAllAnnotation - - - False - True - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:ShowAnnotations - - - False - True - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:RedactDoc - - - False - True - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:EditDoc - - - False - True - - - - - False - True - 1 - - - - - - False - True - 7 - - True @@ -7733,27 +6687,27 @@ True - False + False end center True True - False + False center True vertical - _Review + _Review True - True - False - False + True + False + False end none - True + True False @@ -7764,17 +6718,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True center - .uno:InsertAnnotation + .uno:InsertAnnotation True @@ -7799,27 +6753,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 6 @@ -7828,44 +6765,91 @@ True - False - ~Review - True + False + ~Review + True 6 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + View Mode + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:NormalMultiPaneGUI + .uno:NormalMultiPaneGUI + + + False + True + + + + + True + .uno:DiaMode + True False @@ -7874,11 +6858,62 @@ - False - True - 0 + 0 + 0 + 2 + + + True + False + center + True + both-horiz + False + + + True + .uno:NotesMode + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:OutlineMode + + + False + True + + + + + 1 + 1 + + + + + False @@ -7887,24 +6922,60 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Master + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:DiaMode + .uno:SlideMasterPage False @@ -7913,14 +6984,62 @@ - False - True - 1 + 0 + 0 + 2 - + + + True + False + center + True + both-horiz + False + + + True + .uno:NotesMasterPage + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:HandoutMode + + + False + True + + + + + 1 + 1 + + + + + False @@ -7929,78 +7048,164 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + Zoom + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + False center True - vertical + both + False + 3 - + True - True - center - True - both-horiz - False - - - True - .uno:NotesMode - - - False - True - - + .uno:ZoomMode False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:OutlineMode - - - False - True - - - - - False - False - 1 + True - False - True - 2 + 0 + 0 + 2 - + + + True + False + both-horiz + False + + + True + .uno:ZoomPageWidth + + + False + True + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ZoomNext + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ZoomPage + + + False + True + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ZoomPrevious + + + False + True + + + + + 1 + 0 + + + + + False @@ -8009,39 +7214,60 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + Options + + + + + + + - False - True - 5 - 0 + 0 + 2 + 4 - + True - True + False + vertical + + + 4 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:SlideMasterPage + .uno:Sidebar False @@ -8050,11 +7276,136 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + center + True + both-horiz + False + + + True + .uno:ShowRuler + + + False + False + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:LeftPaneImpress + + + False + False + + + + + 1 + 1 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:Menubar + + + False + True + + + + + 2 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:ToggleTabBarVisibility + + + False + False + + + + + 2 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:ChangeTheme + + + False + True + + + + + 3 + 0 + 2 + + + + + False @@ -8063,78 +7414,199 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center - True + False + Grid + + + + + + + + + + 0 + 2 + 3 + + + + + True + False vertical + + + 3 + 0 + 3 + + + + + True + False + icons + False - + True - True - center - True - both-horiz - False - - - True - .uno:NotesMasterPage - - - False - True - - + .uno:CapturePoint + True False - False - 0 + True - + True - True - center - True - both-horiz - False - - - True - .uno:HandoutMode - - - False - True - - + .uno:HelplinesVisible False - False - 1 + True + + + + + True + .uno:SnapPoints + True + + + False + True + + + + + True + .uno:SnapBorder + True + + + False + True - False - True - 2 + 1 + 0 - + + + True + False + icons + False + + + True + .uno:GridUse + + + False + True + + + + + True + .uno:HelplinesUse + + + False + True + + + + + True + .uno:SnapFrame + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:GridVisible + + + True + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:HelplinesMove + + + True + True + + + + + 2 + 0 + 2 + + + + + False @@ -8142,943 +7614,6 @@ 4 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ZoomMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ZoomPrevious - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ZoomPage - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ZoomNext - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:ZoomPageWidth - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:Sidebar - - - False - True - - - - - False - True - 1 - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:ShowRuler - - - False - False - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:GridVisible - - - False - False - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:Menubar - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:ToggleTabBarVisibility - - - False - False - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SelectObject - - - True - True - - - - - False - True - 1 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:GridVisible - - - False - True - - - - - True - .uno:HelplinesVisible - - - False - True - - - - - True - .uno:HelplinesMove - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:GridUse - - - False - True - - - - - True - .uno:HelplinesUse - - - False - True - - - - - True - .uno:SnapFrame - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:CapturePoint - - - False - True - - - - - True - .uno:GlueInsertPoint - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:SnapPoints - - - False - True - - - - - True - .uno:SnapBorder - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - - False - True - 13 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - False - .uno:ChangeTheme - - - False - True - - - - - False - True - 1 - - - - - False - True - 14 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:OutputQualityColor - - - False - True - - - - - False - True - 1 - - - - - - False - True - 14 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:OutputQualityGrayscale - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:OutputQualityBlackWhite - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 15 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:NewWindow - - - True - True - - - - - False - True - 1 - - - - - - False - True - 16 - - True @@ -9089,29 +7624,29 @@ True - False + False end center True True - False + False center True vertical - _View + _View True - True - False - False + True + False + False end center True none - True + True False @@ -9122,17 +7657,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True center - .uno:Zoom + .uno:Zoom False @@ -9157,27 +7692,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 7 @@ -9186,59 +7704,151 @@ True - False - ~View - True + False + ~View + True 7 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Table + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - center - True - .uno:AnimationEffects + .uno:TransformDialog + True False - False + True + + + + + True + .uno:SelectTable + + + False + True - False - True - 0 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:EntireColumn + + + True + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:EntireRow + + + True + True + + + + + 1 + 1 + + + + + False @@ -9247,110 +7857,199 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + Cells + + + + + + + + + + 0 + 2 + 3 + + + + + True + False vertical + + + 3 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - icons - False - - - True - .uno:InsertColumnsBefore - - - False - True - - - - - True - .uno:InsertColumnsAfter - - - False - True - - - - - True - .uno:DeleteColumns - - - False - True - - + center + True + .uno:MergeCells - False - True - 0 + True + True - + True - True - icons - False - - - True - .uno:InsertRowsBefore - - - False - True - - - - - True - .uno:InsertRowsAfter - - - False - True - - - - - True - .uno:DeleteRows - - - False - True - - + .uno:SplitCell + True False - True - 1 + True - False - True - 1 + 0 + 0 + 2 + + + True + False + icons + False + + + True + .uno:InsertColumnsBefore + + + False + True + + + + + True + .uno:InsertColumnsAfter + + + False + True + + + + + True + .uno:DeleteColumns + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:InsertRowsBefore + + + False + True + + + + + True + .uno:InsertRowsAfter + + + False + True + + + + + True + .uno:DeleteRows + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:OptimizeTable + + + False + True + + + + + 2 + 0 + 2 + + + + + False @@ -9359,84 +8058,202 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + Layout + + + + + + + - False - True - 5 - 1 + 0 + 2 + 4 - + True - False + False vertical + + + 4 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - text - False - - - True - .uno:Line - - - False - False - - + center + True + .uno:TableDesign - False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - False - False - - - - - False - True - 1 + True + True - False - True - 2 + 0 + 0 + 2 + + + True + False + text + False + + + True + .uno:FormatArea + + + False + False + + + + + 1 + 1 + + + + + True + False + icons + False + + + True + center + .uno:SetBorderStyle + + + False + False + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:FillStyle + + + False + True + + + + + 2 + 1 + 2 + + + + + True + False + text + False + + + True + .uno:Line + + + False + False + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:LineStyle + True + + + False + True + + + + + True + .uno:FrameLineColor + True + + + False + True + + + + + 3 + 0 + + + + + False @@ -9444,620 +8261,6 @@ 2 - - - True - False - center - True - - - True - False - vertical - - - True - False - - - True - True - icons - False - - - True - center - .uno:SetBorderStyle - - - False - False - - - - - True - .uno:LineStyle - - - True - True - - - - - True - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:FrameLineColor - - - True - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - center - True - .uno:MergeCells - - - True - True - - - - - False - True - 1 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - True - center - True - both - False - 3 - - - True - .uno:SplitCell - - - False - True - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SelectTable - - - False - True - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:EntireColumn - - - True - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:EntireRow - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:OptimizeTable - - - False - True - - - - - False - True - 1 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - icons - False - - - True - center - True - .uno:CellVertTop - - - False - True - - - - - True - center - True - .uno:CellVertCenter - - - False - True - - - - - True - center - True - .uno:CellVertBottom - - - False - True - - - - - True - .uno:ParaRightToLeft - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - center - True - .uno:StartPara - - - False - True - - - - - True - center - True - .uno:CenterPara - - - False - True - - - - - True - center - True - .uno:EndPara - - - False - True - - - - - True - center - True - .uno:JustifyPara - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - center - True - .uno:TableDesign - - - True - True - - - - - False - True - 1 - - - - - - False - True - 10 - - True @@ -10068,28 +8271,28 @@ True - False + False end center True True - False + False center True vertical - _Table + _Table True - True - False - False + True + False + False end center none - True + True False @@ -10100,17 +8303,17 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True center - .uno:TableDialog + .uno:TableDialog False @@ -10135,27 +8338,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 8 @@ -10164,49 +8350,151 @@ True - False - ~Table - True + False + ~Table + True 8 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True - center + False + end True - both - False - 3 + Image + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 + vertical + + + 3 + 0 + 3 + + + + + True + False + icons + False - + + True + .uno:CompressGraphic + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:Crop + + + False + True + + + + + 2 + 0 + + + + + True + False + icons + False + + True center True - .uno:AnimationEffects + .uno:ToggleObjectRotateMode + + + False + False + + + + + True + .uno:FlipVertical + + + False + False + + + + + True + .uno:FlipHorizontal False @@ -10215,11 +8503,42 @@ - False - True - 0 + 1 + 1 + 2 + + + True + False + center + True + both + False + 3 + + + True + center + True + .uno:TransformDialog + + + False + False + + + + + 0 + 0 + 2 + + + + + False @@ -10228,850 +8547,62 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end True - vertical - - - True - False - - - True - True - icons - False - - - True - .uno:CompressGraphic - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Crop - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - center - True - .uno:ToggleObjectRotateMode - - - False - False - - - - - True - .uno:FlipVertical - - - False - False - - - - - True - .uno:FlipHorizontal - - - False - False - - - - - True - center - True - .uno:ChangePicture - - - False - False - - - - - True - center - True - .uno:SaveGraphic - - - False - False - - - - - False - True - 1 - - + Fill & Border + + + + + + + - False - True - 1 + 0 + 2 + 3 - - - False - True - 1 - - - - - True - False - center - True - + True - False - 5 - 5 + False + end + 5 + 5 vertical - False - True - 5 - 0 + 3 + 0 + 3 - + True - False - vertical + False + text + False - + True - True - text - False - - - True - .uno:FormatLine - - - True - True - - - - - False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - vertical - - - True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - - - - True - True - 1 - - - - - False - True - 2 - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - Convert - 70 - True - True - True - .uno:ChangeBezier - changebezierImg - none - True - top - True - - - False - True - 1 - - - - - True - False - center - True - - - True - False - - - True - False - center - vertical - - - True - True - icons - False - - - False - True - 0 - - - - - True - True - icons - False - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - - - True - False - center - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - both - False - - - True - .uno:GraphicFilterToolbox + .uno:FormatArea False @@ -11080,261 +8611,546 @@ - False - True - 1 + 0 + 1 + + + True + False + both-horiz + False + + + True + .uno:FillStyle + + + False + True + + + + + 1 + 1 + 2 + + + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + False True - 8 + 1 - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Positioning + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 vertical + + + 1 + 0 + 3 + + + + + True + False + icons + False - + True - True - both-horiz - False - - - 130 - True - center - .uno:GrafLuminance - - - False - False - - + .uno:ObjectAlignLeft False - True - 0 + True - + True - True - both-horiz - False - - - True - center - .uno:GrafContrast - - - False - False - - + .uno:AlignCenter False - True - 1 + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + True + .uno:BringToFront + True + + + False + True + + + + + True + .uno:ObjectForwardOne + True + + + False + True - False - True - 1 + 0 + 0 - + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + True + .uno:SendToBack + True + + + False + True + + + + + True + .uno:ObjectBackOne + True + + + False + True + + + + + 0 + 1 + + + + + False True - 5 - 9 + 2 - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center + False + end + True + Modify + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + end + 5 + 5 vertical + + + 4 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - both-horiz - False - - - True - center - .uno:GrafTransparence - - - False - False - - + center + True + .uno:GraphicFilterToolbox False - True - 0 - - - - - True - True - both-horiz - False - - - 130 - True - center - .uno:GrafGamma - - - False - False - - - - - False - True - 1 + False - False - True - 0 + 0 + 0 + 2 - + + + True + False + both-horiz + False + + + True + center + 5 + .uno:GrafLuminance + + + False + False + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + center + 5 + .uno:GrafContrast + + + False + False + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + center + .uno:GrafTransparence + + + False + False + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + center + .uno:GrafGamma + + + False + False + + + + + 2 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:GrafMode + + + False + True + + + + + 3 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:ColorSettings + + + False + True + + + + + 3 + 1 + + + + + False True - 10 - - - - - True - False - center - True - - - True - False - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - False - both-horiz - False - - - True - .uno:GrafMode - - - False - True - - - - - False - True - 0 - - - - - True - False - both-horiz - False - - - True - .uno:ColorSettings - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 11 + 3 @@ -11347,28 +9163,28 @@ True - False + False end center True True - False + False center True vertical - Ima_ge + Ima_ge True - True - False - False + True + False + False end center none - True + True False @@ -11379,18 +9195,18 @@ True - True + True end True - icons - False + icons + False 1 True center True - .uno:FormatArea + .uno:FormatArea True @@ -11402,7 +9218,7 @@ True center True - .uno:FormatLine + .uno:FormatLine True @@ -11414,7 +9230,7 @@ True center True - .uno:TransformDialog + .uno:TransformDialog True @@ -11439,27 +9255,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 9 @@ -11468,165 +9267,193 @@ True - False - Ima~ge - True + False + Ima~ge + True 9 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Drawing Object + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - center - True - .uno:AnimationEffects + .uno:TransformDialog + True - True + False True - False - True - 0 + 0 + 0 + 2 - + True - False + False center - vertical + True + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:AdvancedMode - - - False - True - - + .uno:AdvancedMode False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - True - .uno:FlipVertical - - - False - True - - - - - True - .uno:FlipHorizontal - - - False - True - - - - - True - .uno:Shear - - - False - True - - - - - True - .uno:CrookSlant - - - False - True - - - - - False - True - 1 + True - False - True - 2 + 1 + 0 + + + True + False + center + True + icons + False + + + True + .uno:ToggleObjectRotateMode + + + False + True + + + + + True + .uno:FlipVertical + + + False + True + + + + + True + .uno:FlipHorizontal + + + False + True + + + + + True + .uno:Shear + + + False + True + + + + + True + .uno:CrookSlant + + + False + True + + + + + 1 + 1 + + + + + False @@ -11635,84 +9462,199 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Fill & Border + + + + + + + - False - True - 5 - 0 + 0 + 2 + 3 - + True - False + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + text + False - + True - True - text - False - - - True - .uno:FormatLine - - - True - True - - + .uno:FormatArea False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 + False - False - True - 1 + 0 + 1 + + + True + False + both-horiz + False + + + True + .uno:FillStyle + + + False + True + + + + + 1 + 1 + 2 + + + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + False @@ -11721,125 +9663,182 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Positioning + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 vertical + + + 1 + 0 + 3 + + + + + True + False + icons + False - + True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - + .uno:ObjectAlignLeft False - True - 0 + True - + True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - + .uno:AlignCenter - True - True - 1 + False + True + + + + + True + .uno:ObjectAlignRight + + + False + True + + + + + True + .uno:BringToFront + True + + + False + True + + + + + True + .uno:ObjectForwardOne + True + + + False + True - False - True - 2 + 0 + 0 + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + True + .uno:SendToBack + True + + + False + True + + + + + True + .uno:ObjectBackOne + True + + + False + True + + + + + 0 + 1 + + + + + False @@ -11848,72 +9847,173 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False + False + end + True + Combination + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + center + True + both + False + 3 - + True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - + .uno:Combine - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 + True + True - False - True - 3 + 0 + 0 + 2 - + + + True + False + center + True + False + + + True + .uno:Intersect + + + True + True + + + + + True + .uno:Dismantle + + + True + True + + + + + 1 + 0 + + + + + True + False + center + True + False + + + True + .uno:Merge + + + True + True + + + + + True + .uno:Substract + + + True + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:DistributeSelection + + + True + True + + + + + 2 + 0 + 2 + + + + + False @@ -11922,114 +10022,140 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 + False + end + True + Grouping + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 vertical - False - True - 5 - 0 + 2 + 0 + 3 - - Convert - 70 + True - True - True - .uno:ChangeBezier - changebezierImg - none - True - top - True - - - False - True - 1 - - - - - True - False + False center True + both + False + 3 - + True - False - - - True - False - vertical - - - True - True - icons - False - - - False - True - 0 - - - - - True - True - icons - False - - - False - True - 1 - - - - - False - True - 0 - - + .uno:FormatGroup + + + True + True + + + + + True + .uno:FormatUngroup + True False - True - 2 + True - - False - True - 2 + 0 + 0 + 2 - + + + True + False + center + True + both-horiz + False + + + True + .uno:EnterGroup + + + True + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:LeaveGroup + + + True + True + + + + + 1 + 1 + + + + + False @@ -12038,123 +10164,128 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False + False + end + True + 3D + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + False + both-horiz + False - + True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - + .uno:ExtrusionToggle - False - True - 0 + True + True - False - True - 2 + 0 + 0 - + + + True + False + icons + False + + + True + .uno:ExtrusionDepthFloater + + + True + True + + + + + True + .uno:ExtrusionDirectionFloater + + + True + True + + + + + True + .uno:Extrusion3DColor + + + False + False + + + + + True + .uno:ExtrusionSurfaceFloater + + + False + False + + + + + 0 + 1 + + + + + False @@ -12162,992 +10293,6 @@ 5 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ToggleObjectBezierMode - - - True - True - - - - - False - True - 2 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - vertical - - - True - True - center - True - icons - False - - - True - .uno:BezierConvert - - - False - True - - - - - True - .uno:BezierClose - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:BezierSymmetric - - - False - True - - - - - True - .uno:BezierEliminatePoints - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - vertical - - - True - True - center - True - icons - False - - - True - .uno:BezierMove - - - False - True - - - - - True - .uno:BezierInsert - - - False - True - - - - - True - .uno:BezierDelete - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:BezierCutLine - - - False - True - - - - - True - .uno:BezierEdge - - - False - True - - - - - True - .uno:BezierSmooth - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:GlueEditMode - - - True - True - - - - - False - True - 2 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - False - - - True - .uno:Combine - - - True - True - - - - - True - .uno:Dismantle - - - True - True - - - - - True - .uno:DistributeSelection - - - True - True - - - - - False - True - 0 - - - - - True - True - center - True - False - - - True - .uno:Merge - - - True - True - - - - - True - .uno:Substract - - - True - True - - - - - True - .uno:Intersect - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 11 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:FormatGroup - - - True - True - - - - - False - True - 2 - - - - - - False - True - 12 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:EnterGroup - - - True - True - - - - - False - True - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:LeaveGroup - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 13 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - vertical - - - True - True - both-horiz - False - - - True - .uno:ExtrusionToggle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:ExtrusionDepthFloater - - - True - True - - - - - True - .uno:ExtrusionDirectionFloater - - - True - True - - - - - True - .uno:Extrusion3DColor - - - False - False - - - - - True - .uno:ExtrusionSurfaceFloater - - - False - False - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 14 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:FontworkGalleryFloater - - - True - True - - - - - False - True - 1 - - - - - - False - True - 15 - - - - - True - False - center - True - - - True - False - center - vertical - - - True - True - center - True - icons - False - - - True - .uno:FontworkShapeType - - - True - True - - - - - True - .uno:FontworkSameLetterHeights - - - True - True - - - - - False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:FontworkAlignmentFloater - - - True - True - - - - - True - .uno:FontworkCharacterSpacingFloater - - - True - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - False - True - 16 - - True @@ -13158,29 +10303,29 @@ True - False + False end center True True - False + False center True vertical - _Draw + _Draw True - True - False - False + True + False + False end center True none - True + True False @@ -13191,17 +10336,17 @@ True - True + True end True - icons - False + icons + False 1 True center - .uno:FormatArea + .uno:FormatArea False @@ -13212,7 +10357,7 @@ True center - .uno:FormatLine + .uno:FormatLine False @@ -13223,7 +10368,7 @@ True center - .uno:TransformDialog + .uno:TransformDialog False @@ -13248,27 +10393,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 10 @@ -13277,9 +10405,9 @@ True - False - ~Draw - True + False + ~Draw + True - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - Convert - 70 - True - True - True - .uno:ChangeBezier - changebezierImg - none - True - top - True - - - False - True - 1 - - - - - True - False - - - True - False - vertical - - - True - True - icons - False - - - False - True - 0 - - - - - True - True - icons - False - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - - - True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - - - - 0 - 0 - - - - - True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - - - - 0 - 1 - - - - - True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - - - - 1 - 0 - - - - - True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - True @@ -14099,29 +10977,29 @@ True - False + False end center True True - False + False center True vertical - _Object + _Object True - True - False - False + True + False + False end center True none - True + True False @@ -14132,17 +11010,17 @@ True - True + True end True - icons - False + icons + False 1 True center - .uno:FormatArea + .uno:FormatArea False @@ -14153,7 +11031,7 @@ True center - .uno:FormatLine + .uno:FormatLine False @@ -14164,7 +11042,7 @@ True center - .uno:TransformDialog + .uno:TransformDialog False @@ -14189,27 +11067,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 11 @@ -14218,9 +11079,9 @@ True - False - ~Object - True + False + ~Object + True - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - - True - False - + True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - + .uno:AlignCenter - 0 - 0 + False + True - + True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - + .uno:ObjectAlignRight - 0 - 1 + False + True - + True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - + .uno:BringToFront + True - 1 - 0 + False + True - + True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - - - - 1 - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - 148 - True - True - False - - - True - .uno:AVMediaToolBox + .uno:ObjectForwardOne + True False @@ -14650,16 +11292,182 @@ - True - True - 0 + 0 + 0 + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + True + .uno:SendToBack + True + + + False + True + + + + + True + .uno:ObjectBackOne + True + + + False + True + + + + + 0 + 1 + + + + + + + + False + True + 1 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + end + True + Media Player + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + 200 + True + False + False + + + True + .uno:AVMediaToolBox + + + False + True + + + + + 0 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:AVMediaPlayer + + + False + True + + + + + 0 + 1 + + + + + True True - 7 + 2 @@ -14672,27 +11480,27 @@ True - False + False end center True True - False + False center True vertical - _Media + _Media True - True - False - False + True + False + False end none - True + True False @@ -14703,17 +11511,17 @@ True - True + True end True - icons - False + icons + False 1 True center - .uno:FormatArea + .uno:FormatArea False @@ -14724,7 +11532,7 @@ True center - .uno:FormatLine + .uno:FormatLine False @@ -14734,7 +11542,7 @@ True - .uno:TransformDialog + .uno:TransformDialog False @@ -14759,27 +11567,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 12 @@ -14788,47 +11579,88 @@ True - False - ~Media - True + False + ~Media + True 12 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Mode + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:SwitchControlDesignMode + .uno:TransformDialog False @@ -14837,11 +11669,62 @@ - False - True - 0 + 0 + 0 + 2 + + + True + False + center + True + both-horiz + False + + + True + .uno:UseWizards + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:GroupBox + + + False + True + + + + + 1 + 1 + + + + + False @@ -14850,78 +11733,187 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - center + False + end True + Properties + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:UseWizards - - - False - True - - + .uno:FormProperties False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:GroupBox - - - False - True - - - - - False - False - 1 + True - False - True - 1 + 0 + 0 - + + + True + False + both-horiz + False + + + True + .uno:ShowFmExplorer + + + False + True + + + + + 0 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:TabDialog + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:OpenReadOnly + + + False + True + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:ControlProperties + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:AutoControlFocus + + + False + True + + + + + 2 + 1 + + + + + False @@ -14930,86 +11922,307 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center + False + end True + Controls + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 vertical + + + 3 + 0 + 3 + + + + + True + False + icons + False - + True - True - both-horiz - False - - - True - .uno:FormProperties - - - False - True - - + .uno:Label False - True - 0 + True - + True - True - both-horiz - False - - - True - .uno:ShowFmExplorer - - - False - True - - + .uno:Edit False - True - 1 + True + + + + + True + .uno:CheckBox + + + False + True - False - True - 1 + 0 + 0 + + + True + False + icons + False + + + True + .uno:RadioButton + + + False + True + + + + + True + .uno:ListBox + + + False + True + + + + + True + .uno:ComboBox + + + False + True + + + + + 0 + 1 + + + + + True + False + icons + False + + + True + .uno:NumericField + + + False + True + + + + + True + .uno:CurrencyField + + + False + True + + + + + True + .uno:PatternField + + + False + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:FormattedField + + + False + True + + + + + True + .uno:DateField + + + False + True + + + + + True + .uno:TimeField + + + False + True + + + + + 1 + 1 + + + + + True + False + icons + False + + + True + .uno:Pushbutton + + + False + True + + + + + True + .uno:Imagebutton + + + False + True + + + + + True + .uno:ImageControl + + + False + True + + + + + 2 + 0 + + + + + True + False + icons + False + + + True + .uno:FileControl + + + False + True + + + + + True + .uno:NavigationBar + + + False + True + + + + + True + .uno:Grid + + + False + True + + + + + 2 + 1 + + + + + False @@ -15017,563 +12230,6 @@ 2 - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:TabDialog - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:OpenReadOnly - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:ControlProperties - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:AutoControlFocus - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Label - - - False - True - - - - - True - .uno:Edit - - - False - True - - - - - True - .uno:CheckBox - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:RadioButton - - - False - True - - - - - True - .uno:ListBox - - - False - True - - - - - True - .uno:ComboBox - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:NumericField - - - False - True - - - - - True - .uno:CurrencyField - - - False - True - - - - - True - .uno:PatternField - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FormattedField - - - False - True - - - - - True - .uno:DateField - - - False - True - - - - - True - .uno:TimeField - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Pushbutton - - - False - True - - - - - True - .uno:Imagebutton - - - False - True - - - - - True - .uno:ImageControl - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FileControl - - - False - True - - - - - True - .uno:NavigationBar - - - False - True - - - - - True - .uno:Grid - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - True @@ -15584,29 +12240,29 @@ True - False + False end center True True - False + False center True vertical - Fo_rm + Fo_rm True - True - False - False + True + False + False end center True none - True + True False @@ -15617,16 +12273,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True - .uno:FormProperties + .uno:FormProperties False @@ -15651,27 +12307,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 13 @@ -15680,47 +12319,82 @@ True - False - Fo~rm - True + False + Fo~rm + True 13 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Master + + + + + + + + + + 0 + 2 + 4 + + + + + True + False + vertical + + + 4 + 0 + 3 + + + + + True + False center True - both - False - 3 + both-horiz + False - + True - .uno:NormalMultiPaneGUI + .uno:RenameMasterPage False @@ -15729,11 +12403,137 @@ - False - True - 0 + 1 + 0 + + + True + False + center + True + both-horiz + False + + + True + .uno:DeleteMasterPage + + + False + True + + + + + 1 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:InsertMasterPage + + + False + True + + + + + 0 + 0 + 2 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:NotesMasterPage + + + False + True + + + + + 3 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:HandoutMode + + + False + True + + + + + 3 + 1 + + + + + True + False + center + True + both + False + 3 + + + True + .uno:MasterLayouts + + + False + True + + + + + 2 + 0 + 2 + + + + + False @@ -15742,24 +12542,60 @@ - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Slide + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:DiaMode + .uno:SlideSetup False @@ -15768,14 +12604,110 @@ - False - True - 1 + 0 + 0 + 2 - + + + True + False + center + True + both-horiz + False + + + True + .uno:SelectBackground + + + False + True + + + + + 2 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:SaveBackground + + + False + True + + + + + 2 + 1 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:HideSlide + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:ShowSlide + + + False + True + + + + + 1 + 1 + + + + + False @@ -15784,78 +12716,74 @@ - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - False + False + + + + + + + + + + 0 + 2 + + + + + True + False + vertical + + + 1 + 0 + 3 + + + + + True + False center True - vertical + both + False + 3 - + True - True - center - True - both-horiz - False - - - True - .uno:NotesMode - - - False - True - - + .uno:CloseMasterView False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:OutlineMode - - - False - True - - - - - False - False - 1 + True - False - True - 2 + 0 + 0 + 2 - + + + False @@ -15863,596 +12791,6 @@ 2 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SlideMasterPage - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:NotesMasterPage - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:HandoutMode - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:InsertMasterPage - - - False - True - - - - - False - True - 1 - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:RenameMasterPage - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:DeleteMasterPage - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:MasterLayouts - - - False - True - - - - - False - True - 1 - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:HideSlide - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:ShowSlide - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SlideSetup - - - False - True - - - - - False - True - 1 - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:SelectBackground - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:SaveBackground - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:CloseMasterView - - - False - True - - - - - False - True - 1 - - - - - False - True - 11 - - True @@ -16463,29 +12801,29 @@ True - False + False end center True True - False + False center True vertical - _Master + _Master True - True - False - False + True + False + False end center True none - True + True False @@ -16496,16 +12834,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True - .uno:SlideSetup + .uno:SlideSetup False @@ -16530,27 +12868,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 14 @@ -16559,47 +12880,94 @@ True - False - ~Master - True + False + ~Master + True 14 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + View Mode + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:NormalMultiPaneGUI + .uno:NormalMultiPaneGUI + + + False + True + + + + + True + .uno:DiaMode + True False @@ -16608,11 +12976,62 @@ - False - True - 0 + 0 + 0 + 2 + + + True + False + center + True + both-horiz + False + + + True + .uno:NotesMode + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:OutlineMode + + + False + True + + + + + 1 + 1 + + + + + False @@ -16621,24 +13040,60 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - True + False + Level + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + vertical + + + 3 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:DiaMode + .uno:OutlineFormat False @@ -16647,11 +13102,102 @@ - False - True - 1 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:OutlineRight + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:OutlineLeft + + + False + True + + + + + 1 + 1 + + + + + True + False + both-horiz + False + + + True + .uno:OutlineUp + + + False + True + + + + + 2 + 0 + + + + + True + False + both-horiz + False + + + True + .uno:OutlineDown + + + False + True + + + + + 2 + 1 + + + + + False @@ -16660,75 +13206,146 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False + False + Show + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + vertical + + + 2 + 0 + 3 + + + + + True + False center True - vertical + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:NotesMode - - - False - True - - + .uno:OutlineCollapseAll False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:OutlineMode - - - False - True - - - - - False - False - 1 + False - False - True - 2 + 0 + 0 + + + True + False + center + True + both-horiz + False + + + True + .uno:OutlineExpandAll + + + False + False + + + + + 0 + 1 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:OutlineCollapse + + + False + True + + + + + 1 + 0 + + + + + True + False + center + True + both-horiz + False + + + True + .uno:OutlineExpand + + + False + False + + + + + 1 + 1 + + + + + False @@ -16736,617 +13353,6 @@ 2 - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SlideMasterPage - - - False - True - - - - - False - True - 1 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:NotesMasterPage - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:HandoutMode - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:OutlineFormat - - - False - True - - - - - False - True - 1 - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:OutlineRight - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:OutlineLeft - - - False - True - - - - - False - True - 1 - - - - - False - True - 2 - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - both-horiz - False - - - True - .uno:OutlineUp - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:OutlineDown - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:ColorView - - - False - True - - - - - False - True - 1 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:OutlineCollapseAll - - - False - False - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:OutlineExpandAll - - - False - False - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 9 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:OutlineCollapse - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:OutlineExpand - - - False - False - - - - - False - False - 1 - - - - - False - True - 3 - - - - - - False - True - 10 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:NewWindow - - - True - True - - - - - False - True - 1 - - - - - - False - True - 13 - - True @@ -17357,29 +13363,29 @@ True - False + False end center True True - False + False center True vertical - _View + _View True - True - False - False + True + False + False end center True none - True + True False @@ -17390,16 +13396,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True - .uno:NormalMultiPaneGUI + .uno:NormalMultiPaneGUI False @@ -17424,27 +13430,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 15 @@ -17453,165 +13442,194 @@ True - False - ~Outline - True + False + + ~Outline + True 15 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 3 + 6 + 6 + 3 + 3 - + True - True + False + end + True + Drawing Object + + + + + + + + + + 0 + 2 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - center - True - .uno:AnimationEffects + .uno:TransformDialog + True False - False + True - False - True - 0 + 0 + 0 + 2 - + True - False + False center - vertical + True + both-horiz + False - + True - True - center - True - both-horiz - False - - - True - .uno:AdvancedMode - - - False - True - - + .uno:AdvancedMode False - True - 0 - - - - - True - True - center - True - icons - False - - - True - .uno:ToggleObjectRotateMode - - - False - True - - - - - True - .uno:FlipVertical - - - False - True - - - - - True - .uno:FlipHorizontal - - - False - True - - - - - True - .uno:Shear - - - False - True - - - - - True - .uno:CrookSlant - - - False - True - - - - - False - True - 1 + True - False - True - 2 + 1 + 0 + + + True + False + center + True + icons + False + + + True + .uno:ToggleObjectRotateMode + + + False + True + + + + + True + .uno:FlipVertical + + + False + True + + + + + True + .uno:FlipHorizontal + + + False + True + + + + + True + .uno:Shear + + + False + True + + + + + True + .uno:CrookSlant + + + False + True + + + + + 1 + 1 + + + + + False @@ -17620,328 +13638,62 @@ - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - vertical - - - True - True - text - False - - - True - .uno:FormatLine - - - True - True - - - - - False - True - 0 - - - - - True - True - text - False - - - True - .uno:FormatArea - - - True - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - vertical - - - True - False - - - True - True - icons - False - - - 100 - True - center - .uno:XLineStyle - - - False - False - - - - - True - .uno:LineWidth - - - True - True - - - - - True - True - 0 - - - - - True - True - icons - False - - - .uno:LineEndStyle - - - True - True - - - - - True - .uno:XLineColor - - - True - True - - - - - False - True - 1 - - - - - False - True - 0 - - - - - True - False - True - both-horiz - False - - - True - .uno:FillStyle - - - False - True - - - - - True - True - 1 - - - - - False - True - 2 - - - - - False - True - 2 - - - - - True - False - center - True - - - True - False - vertical - - - True - True - icons - False - - - True - .uno:LineEndStyle - - - True - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FillShadow - - - False - True - - - - - False - True - 1 - - - - - False - True - 3 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center + False + end True - both - False - 3 + Fill & Border + + + + + + + + + + 0 + 2 + 3 + + + + + True + False + end + 5 + 5 + vertical + + + 3 + 0 + 3 + + + + + True + False + text + False - + True - center - True - .uno:Window3D + .uno:FormatArea False @@ -17950,272 +13702,408 @@ - False - True - 1 + 0 + 1 - - - False - True - 4 - - - - - True - False - center - True - + True - False + False + both-horiz + False - + True - False - vertical - - - True - True - icons - False - - - True - .uno:ObjectAlignLeft - - - False - True - - - - - True - .uno:AlignCenter - - - False - True - - - - - True - .uno:ObjectAlignRight - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:AlignUp - - - False - True - - - - - True - .uno:AlignMiddle - - - False - True - - - - - True - .uno:AlignDown - - - False - True - - - - - False - True - 1 - - + .uno:FillStyle False - True - 0 + True - False - True - 2 + 1 + 1 + 2 - + + + True + False + text + False + + + True + .uno:FormatLine + + + False + False + + + + + 0 + 0 + + + + + True + False + icons + False + + + 100 + True + center + .uno:XLineStyle + + + False + False + + + + + True + .uno:LineWidth + + + True + True + + + + + 1 + 0 + + + + + True + False + icons + False + + + True + .uno:LineEndStyle + + + True + True + + + + + True + .uno:XLineColor + + + True + True + + + + + True + .uno:FillShadow + True + + + False + True + + + + + 2 + 0 + + + + + False True - 5 + 1 - + + True - False - center - True + False + 3 + 3 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 + False + end + True + Positioning + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 vertical - False - True - 5 - 0 + 1 + 0 + 3 - - + True - False + False + icons + False - + True - True - icons - False - - - True - .uno:BringToFront - - - False - True - - + .uno:ObjectAlignLeft - 0 - 0 + False + True - + True - True - icons - False - - - True - .uno:SendToBack - - - False - True - - + .uno:AlignCenter - 0 - 1 + False + True - + True - True - both-horiz - False - - - True - .uno:Forward - - - False - True - - + .uno:ObjectAlignRight - 1 - 0 + False + True - + True - True - both-horiz - False - - - True - .uno:Backward - - - False - True - - + .uno:BringToFront + True - 1 - 1 + False + True + + + + + True + .uno:ObjectForwardOne + True + + + False + True - False - True - 1 + 0 + 0 - + + + True + False + icons + False + + + True + .uno:AlignUp + + + False + True + + + + + True + .uno:AlignMiddle + + + False + True + + + + + True + .uno:AlignDown + + + False + True + + + + + True + .uno:SendToBack + True + + + False + True + + + + + True + .uno:ObjectBackOne + True + + + False + True + + + + + 0 + 1 + + + + + False True - 6 + 2 + + + + + + True + False + 3 + 6 + 6 + 6 + 3 + 3 + + + True + False + end + True + 3D + + + + + + + + + + 0 + 2 + + + + + True + False + end + 5 + 5 + vertical + + + 1 + 0 + 3 + + + + + True + False + center + True + both + False + 3 + + + True + center + True + .uno:Window3D + + + False + False + + + + + 0 + 0 + 2 + + + + + + + + False + True + 3 @@ -18228,29 +14116,29 @@ True - False + False end center True True - False + False center True vertical - 3_d + 3_D True - True - False - False + True + False + False end center True none - True + True False @@ -18261,17 +14149,17 @@ True - True + True end True - icons - False + icons + False 1 True center - .uno:FormatArea + .uno:FormatArea False @@ -18282,7 +14170,7 @@ True center - .uno:FormatLine + .uno:FormatLine False @@ -18293,7 +14181,7 @@ True center - .uno:TransformDialog + .uno:TransformDialog False @@ -18318,27 +14206,10 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 16 @@ -18347,32 +14218,32 @@ True - False - 3~d - True + False + 3~D + True 16 - False + False - + True - False + False - + True - False + False center True True - False + False center True @@ -18392,29 +14263,29 @@ True - False + False end center True True - False + False center True vertical - E_xtension + E_xtension True - True - False - False + True + False + False end center True none - True + True False @@ -18425,11 +14296,11 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 @@ -18449,24 +14320,24 @@ False False - end + end 1 True - False + False end - 5 - 5 + 5 + 5 vertical False True 5 - end + end 2 @@ -18478,59 +14349,85 @@ True - False - E~xtension - True + False + E~xtension + True 17 - False + False - + True - False + False - + True - False + False center True - + + True - False - center - True + False + 6 + 6 + 6 + 6 + 3 + 3 - + True - False - 5 - 5 - vertical + False + end + True + Macro + + + + + + + - False - True - 5 - 0 + 0 + 2 + 2 - + True - True + False + end + 5 + 5 + vertical + + + 2 + 0 + 3 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:RunMacro + .uno:RunMacro False @@ -18539,11 +14436,57 @@ - False - True - 2 + 0 + 0 + 2 + + + True + False + both-horiz + False + + + True + .uno:BasicIDEAppear + + + False + True + + + + + 1 + 0 + + + + + True + False + both-horiz + + + True + .uno:MacroDialog + + + False + True + + + + + 1 + 1 + + + + + False @@ -18552,115 +14495,65 @@ - + + True - False - center - True + False + 3 + 6 + 6 + 6 + 3 + 3 - + True - False - center + False + end True - vertical - - - True - True - both-horiz - False - - - True - .uno:BasicIDEAppear - - - False - True - - - - - False - True - 0 - - - - - True - True - both-horiz - False - - - True - .uno:MacroDialog - - - False - True - - - - - False - True - 1 - - + AutoCorrection + + + + + + + - False - True - 2 - - - - - - False - True - 1 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 + 0 + 1 + 1 - + True - True + False + end + 5 + 5 + vertical + + + 1 + 0 + 2 + + + + + True + False center True - both - False + both + False 3 - + True - .uno:PresentationMinimizer + .uno:AutoCorrectDlg False @@ -18669,754 +14562,18 @@ - False - True - 1 + 0 + 0 + + + False True - 2 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:BmpMask - - - True - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:AVMediaPlayer - - - True - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 3 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - True - center - True - both - False - 3 - - - True - .uno:SwitchControlDesignMode - - - False - True - - - - - False - True - 1 - - - - - False - True - 4 - - - - - True - False - center - True - - - True - False - center - True - vertical - - - True - True - center - True - both-horiz - False - - - True - .uno:UseWizards - - - False - True - - - - - False - False - 0 - - - - - True - True - center - True - both-horiz - False - - - True - .uno:GroupBox - - - False - True - - - - - False - False - 1 - - - - - False - True - 2 - - - - - - False - True - 5 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Label - - - False - True - - - - - True - .uno:Edit - - - False - True - - - - - True - .uno:CheckBox - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:RadioButton - - - False - True - - - - - True - .uno:ListBox - - - False - True - - - - - True - .uno:ComboBox - - - False - True - - - - - False - True - 2 - - - - - False - True - 1 - - - - - - False - True - 6 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:NumericField - - - False - True - - - - - True - .uno:CurrencyField - - - False - True - - - - - True - .uno:PatternField - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FormattedField - - - False - True - - - - - True - .uno:DateField - - - False - True - - - - - True - .uno:TimeField - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 7 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:Pushbutton - - - False - True - - - - - True - .uno:Imagebutton - - - False - True - - - - - True - .uno:ImageControl - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:FileControl - - - False - True - - - - - True - .uno:NavigationBar - - - False - True - - - - - True - .uno:Grid - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 8 - - - - - True - False - center - True - - - True - False - 5 - 5 - vertical - - - False - True - 5 - 0 - - - - - True - False - center - True - vertical - - - True - True - icons - False - - - True - .uno:FormProperties - - - False - True - - - - - True - .uno:TabDialog - - - False - True - - - - - True - .uno:ControlProperties - - - False - True - - - - - False - True - 0 - - - - - True - True - icons - False - - - True - .uno:ShowFmExplorer - - - False - True - - - - - True - .uno:OpenReadOnly - - - False - True - - - - - True - .uno:AutoControlFocus - - - False - True - - - - - False - True - 1 - - - - - False - True - 1 - - - - - - False - True - 9 + 0 @@ -19429,29 +14586,29 @@ True - False + False end center True True - False + False center True vertical - _Tools + _Tools True - True - False - False + True + False + False end center True none - True + True False @@ -19462,16 +14619,16 @@ True - True + True end True - both-horiz - False + both-horiz + False 1 True - .uno:OptionsTreeDialog + .uno:OptionsTreeDialog False @@ -19496,42 +14653,25 @@ False False - end + end 1 - - - True - False - end - 5 - 5 - vertical - - - False - True - 5 - end - 2 - - 18 - + True - False - ~Tools - True + False + ~Tools + True 18 - False + False @@ -19543,29 +14683,19 @@ - 0 - 0 + 0 + 0 - - vertical - True - - - - - - - - - vertical - True - - - - - - + + + + + + + + + diff --git a/sd/uiconfig/simpress/ui/notebookbar_compact.ui b/sd/uiconfig/simpress/ui/notebookbar_compact.ui index 6a9349650434..2caf87f4a685 100644 --- a/sd/uiconfig/simpress/ui/notebookbar_compact.ui +++ b/sd/uiconfig/simpress/ui/notebookbar_compact.ui @@ -860,13 +860,6 @@ .uno:QuestionAnswers - - - True - False - .uno:SendFeedback - - True diff --git a/sd/uiconfig/simpress/ui/notebookbar_groupedbar_full.ui b/sd/uiconfig/simpress/ui/notebookbar_groupedbar_full.ui index 4cc5c40e480b..62c0543d2174 100644 --- a/sd/uiconfig/simpress/ui/notebookbar_groupedbar_full.ui +++ b/sd/uiconfig/simpress/ui/notebookbar_groupedbar_full.ui @@ -1514,13 +1514,6 @@ .uno:QuestionAnswers - - - True - False - .uno:SendFeedback - - True diff --git a/sd/uiconfig/simpress/ui/notebookbar_online.ui b/sd/uiconfig/simpress/ui/notebookbar_online.ui deleted file mode 100644 index 8acefe49ff98..000000000000 --- a/sd/uiconfig/simpress/ui/notebookbar_online.ui +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - - True - False - - - True - False - vertical - - - True - True - icons - False - - - False - True - 0 - - - - - True - True - True - - - True - False - True - .uno:CharFontName - - - True - True - - - - - True - True - 0 - - - - - True - True - 5 - - - True - False - .uno:FontHeight - - - True - True - - - - - False - True - 1 - - - - - True - True - 5 - - - True - False - .uno:SlideMasterPagesAll - True - - - False - True - - - - - False - True - 2 - - - - - True - True - 5 - - - True - False - .uno:SlideTransitionsPane - True - - - False - True - - - - - False - True - 2 - - - - - True - False - 5 - - - True - False - .uno:ThemeSelectorPanel - True - - - False - True - - - - - False - True - 5 - - - - - 0 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sd/uiconfig/simpress/ui/optimpressgeneralpage.ui b/sd/uiconfig/simpress/ui/optimpressgeneralpage.ui index d01e6ae3a070..fd498d80efd5 100644 --- a/sd/uiconfig/simpress/ui/optimpressgeneralpage.ui +++ b/sd/uiconfig/simpress/ui/optimpressgeneralpage.ui @@ -59,6 +59,19 @@ True 6 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + Start with _Template Selection @@ -78,19 +91,6 @@ 0 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - @@ -128,6 +128,19 @@ True 6 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + Copy when moving @@ -148,6 +161,113 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + Use background cache + True + True + False + start + True + True + + + Specifies whether to use the cache for displaying objects on the master slide. + + + + + 1 + 1 + + + + + False + True + center + center + res/lock.png + + + 0 + 2 + + + + + Objects always moveable + True + True + False + start + True + True + + + Specifies that you want to move an object with the Rotate tool enabled. If Objects always moveable is not marked, the Rotate tool can only be used to rotate an object. + + + + + 1 + 2 + + + + + False + True + center + center + res/lock.png + + + 0 + 3 + + + + + Do not distort objects in curve + True + True + False + start + True + True + + + 1 + 3 + + + + + False + True + center + center + res/lock.png + + + 0 + 4 + + @@ -189,6 +309,19 @@ 4 + + + False + True + center + center + res/lock.png + + + 0 + 5 + + @@ -237,139 +370,6 @@ 5 - - - Objects always moveable - True - True - False - start - True - True - - - Specifies that you want to move an object with the Rotate tool enabled. If Objects always moveable is not marked, the Rotate tool can only be used to rotate an object. - - - - - 1 - 2 - - - - - Do not distort objects in curve - True - True - False - start - True - True - - - 1 - 3 - - - - - Use background cache - True - True - False - start - True - True - - - Specifies whether to use the cache for displaying objects on the master slide. - - - - - 1 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 4 - - - - - False - True - center - center - res/lock.png - - - 0 - 5 - - - - - False - True - center - center - res/lock.png - - - 0 - 3 - - @@ -405,6 +405,19 @@ 6 6 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + Add _spacing between paragraphs and tables @@ -424,19 +437,6 @@ 0 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - @@ -487,6 +487,19 @@ 6 6 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + Allow quick editing @@ -507,6 +520,19 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + Only text area selectable @@ -526,32 +552,6 @@ 1 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - @@ -587,6 +587,19 @@ 6 6 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + True @@ -602,6 +615,29 @@ 0 + + + True + False + True + + + False + True + start + + + + + Determines the drawing scale on the status bar. + + + + + 2 + 0 + + False @@ -616,20 +652,6 @@ 1 - - - False - True - Page _height: - True - metricHeightFields - 0 - - - 3 - 1 - - True @@ -645,6 +667,20 @@ 1 + + + False + True + Page _height: + True + metricHeightFields + 0 + + + 3 + 1 + + True @@ -716,42 +752,6 @@ 2 - - - True - False - True - - - False - True - start - - - - - Determines the drawing scale on the status bar. - - - - - 2 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 0 - - diff --git a/sd/uiconfig/simpress/ui/prntopts.ui b/sd/uiconfig/simpress/ui/prntopts.ui index 056318be9abe..764d90e555cb 100644 --- a/sd/uiconfig/simpress/ui/prntopts.ui +++ b/sd/uiconfig/simpress/ui/prntopts.ui @@ -29,22 +29,16 @@ 6 12 - - Paper tray from printer s_ettings - True - True - False - True - True - - - Determines that the paper tray to be used is the one defined in the printer setup. - - + + False + True + center + center + res/lock.png - 1 - 3 + 0 + 0 @@ -144,6 +138,19 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + Fr_ont @@ -164,6 +171,19 @@ 1 + + + False + True + center + center + res/lock.png + + + 0 + 2 + + Ba_ck @@ -184,45 +204,6 @@ 2 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - False @@ -236,6 +217,25 @@ 3 + + + Paper tray from printer s_ettings + True + True + False + True + True + + + Determines that the paper tray to be used is the one defined in the printer setup. + + + + + 1 + 3 + + @@ -270,6 +270,19 @@ 6 6 12 + + + False + True + center + center + res/lock.png + + + 0 + 0 + + _Page name @@ -290,6 +303,19 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + D_ate @@ -310,6 +336,19 @@ 1 + + + False + True + center + center + res/lock.png + + + 0 + 2 + + Ti_me @@ -330,6 +369,19 @@ 2 + + + False + True + center + center + res/lock.png + + + 0 + 3 + + H_idden pages @@ -350,58 +402,6 @@ 3 - - - False - True - center - center - res/lock.png - - - 0 - 0 - - - - - False - True - center - center - res/lock.png - - - 0 - 1 - - - - - False - True - center - center - res/lock.png - - - 0 - 2 - - - - - False - True - center - center - res/lock.png - - - 0 - 3 - - @@ -468,6 +468,19 @@ 0 + + + False + True + center + center + res/lock.png + + + 0 + 1 + + Gra_yscale @@ -510,19 +523,6 @@ 2 - - - False - True - center - center - res/lock.png - - - 0 - 1 - - @@ -610,6 +610,7 @@ + Outline True True diff --git a/sd/uiconfig/simpress/ui/sdviewpage.ui b/sd/uiconfig/simpress/ui/sdviewpage.ui index 4a470626d1c1..59ee7da99e54 100644 --- a/sd/uiconfig/simpress/ui/sdviewpage.ui +++ b/sd/uiconfig/simpress/ui/sdviewpage.ui @@ -10,7 +10,7 @@ 0 none - + True False @@ -93,6 +93,25 @@ 3 + + + _Swap mouse wheel zoom and scroll + True + True + False + True + True + + + When enabled in Draw, the mouse wheel zooms instead of scrolling, and Ctrl plus the mouse wheel scrolls instead of zooming. + + + + + 1 + 4 + + False @@ -145,6 +164,19 @@ 3 + + + False + True + center + center + res/lock.png + + + 0 + 4 + + diff --git a/sd/uiconfig/simpress/ui/slidedesigndialog.ui b/sd/uiconfig/simpress/ui/slidedesigndialog.ui index 0250aa3f418b..c4e71d96c001 100644 --- a/sd/uiconfig/simpress/ui/slidedesigndialog.ui +++ b/sd/uiconfig/simpress/ui/slidedesigndialog.ui @@ -1,33 +1,43 @@ - + + + + + + + + + + + - False - 6 + False + 6 Available Master Slides True - 0 - 0 - dialog + 0 + 0 + dialog True - False + False vertical 12 True - False - end + False + end _Load... True - True - True - True + True + True + True Displays the Load Master Slide dialog, where you can select additional slide designs. @@ -44,10 +54,10 @@ _OK True - True - True - True - True + True + True + True + True True @@ -60,8 +70,8 @@ _Cancel True - True - True + True + True True @@ -74,8 +84,8 @@ _Help True - True - False + True + False True @@ -89,34 +99,34 @@ False True - end + end 1 True - False + False True True - 0 - none + 0 + none - + True - False - 6 + False 12 6 + 6 _Exchange background page True - True - False - True - True + True + False + True + True Applies the background of the selected slide design to all of the slides in your document. @@ -124,18 +134,18 @@ - 0 - 1 + 0 + 1 _Delete unused backgrounds True - True - False - True - True + True + False + True + True Deletes unreferenced background slides and presentation layouts from your document. @@ -143,38 +153,24 @@ - 0 - 2 + 0 + 2 - + True - True + True + 6 True True - never - never - in - - - True - False - - - True - True - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK - True - True - - - - + layoutsiconview_treestore + 0 + 2 - 0 - 0 + 0 + 0 @@ -182,7 +178,7 @@ True - False + False Select a Slide Design @@ -204,9 +200,6 @@ cancel help - - - Displays the Available Master Slides dialog, where you can select a layout scheme for the current slide. Any objects in the slide design are inserted behind objects in the current slide. diff --git a/sd/uiconfig/simpress/ui/templatedialog.ui b/sd/uiconfig/simpress/ui/templatedialog.ui index 569f16bf8029..580a2ca17895 100644 --- a/sd/uiconfig/simpress/ui/templatedialog.ui +++ b/sd/uiconfig/simpress/ui/templatedialog.ui @@ -118,7 +118,7 @@ - reset + reset standard ok cancel diff --git a/sd/util/sd.component b/sd/util/sd.component index 2c7f94763b24..077caf7e6afa 100644 --- a/sd/util/sd.component +++ b/sd/util/sd.component @@ -45,10 +45,6 @@ constructor="com_sun_star_comp_sd_InsertSlideController_get_implementation"> - - - diff --git a/sdext/inc/sdextresid.hxx b/sdext/inc/sdextresid.hxx index 58ffe912d5a4..9f1b24d15d45 100644 --- a/sdext/inc/sdextresid.hxx +++ b/sdext/inc/sdextresid.hxx @@ -12,5 +12,6 @@ #include OUString SdextResId(TranslateId aKey); +OUString SdextResId(TranslateNId aContextSingularPlural, int nCardinality); /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sdext/inc/strings.hrc b/sdext/inc/strings.hrc index d59428737848..e218f99c05ab 100644 --- a/sdext/inc/strings.hrc +++ b/sdext/inc/strings.hrc @@ -10,6 +10,7 @@ #pragma once #define NC_(Context, String) TranslateId(Context, u8##String) +#define NNC_(Context, StringSingular, StringPlural) TranslateNId(Context, reinterpret_cast(u8##StringSingular), reinterpret_cast(u8##StringPlural)) #define STR_SUN_OPTIMIZATION_WIZARD2 NC_("STR_SUN_OPTIMIZATION_WIZARD2", "Presentation Minimizer") #define STR_INTRODUCTION NC_("STR_INTRODUCTION", "Introduction") @@ -19,9 +20,10 @@ #define STR_NO_OLE_OBJECTS_DESC NC_("STR_NO_OLE_OBJECTS_DESC", "Object Linking and Embedding (OLE) is a technology that allows embedding and linking to documents and other objects.\n\nThe current presentation contains no OLE objects.") #define STR_SLIDES NC_("STR_SLIDES", "Slides") #define STR_SUMMARY NC_("STR_SUMMARY", "Summary") -#define STR_DELETE_SLIDES NC_("STR_DELETE_SLIDES", "Delete %SLIDES slides.") -// The following string is only used in plural. -#define STR_OPTIMIZE_IMAGES NC_("STR_OPTIMIZE_IMAGES", "Optimize %IMAGES images to %QUALITY% JPEG quality at %RESOLUTION DPI.") +// %SLIDES will be replaced with the number of slides to delete +#define STR_DELETE_SLIDES NNC_("STR_DELETE_SLIDES", "Delete 1 slide.", "Delete %SLIDES slides.") +// %IMAGES will be replaced with the number of images to optimize. It will only be used in the plural. +#define STR_OPTIMIZE_IMAGES NNC_("STR_OPTIMIZE_IMAGES", "Optimize 1 image to %QUALITY% JPEG quality at %RESOLUTION DPI.", "Optimize %IMAGES images to %QUALITY% JPEG quality at %RESOLUTION DPI.") #define STR_CREATE_REPLACEMENT NC_("STR_CREATE_REPLACEMENT", "Create replacement images for %OLE objects.") #define STR_MY_SETTINGS NC_("STR_MY_SETTINGS", "My Settings ") #define STR_OK NC_("STR_OK", "OK") diff --git a/sdext/qa/unit/pdfimport.cxx b/sdext/qa/unit/pdfimport.cxx index 4adb28e694e2..26f948ae3f58 100644 --- a/sdext/qa/unit/pdfimport.cxx +++ b/sdext/qa/unit/pdfimport.cxx @@ -585,7 +585,7 @@ namespace new OutputWrapString(aOutput), nullptr)); // This ensures that the imported image arrives properly flipped - CPPUNIT_ASSERT(aOutput.indexOf("draw:transform=\"matrix(-21488.4 0 0 -27978.1 21488.4 27978.1)\"") != -1); + CPPUNIT_ASSERT(aOutput.indexOf("draw:transform=\"matrix(-21488.4 0 -0 -27978.1 21488.4 27978.1)\"") != -1); #endif } @@ -715,7 +715,7 @@ namespace assertXPath(pXmlDoc, xpath, "font-family", u"SimSun"); assertXPath(pXmlDoc, xpath, "font-weight", u"normal"); // FIXME and remove the below comment: - // the chinese chars are shown in pdf as faux italic (fake italic). It is currencly imported wrongly as normal font style. + // the chinese chars are shown in pdf as faux italic (fake italic). It is currently imported wrongly as normal font style. // See tdf#78427 for how the faux bold problem was handled. Faux italic may be handled using the transformation pattern. // assertXPath(pXmlDoc, xpath, "font-style", "italic"); diff --git a/sdext/source/minimizer/configurationaccess.cxx b/sdext/source/minimizer/configurationaccess.cxx index 2acab6df88e3..7819a3fe465b 100644 --- a/sdext/source/minimizer/configurationaccess.cxx +++ b/sdext/source/minimizer/configurationaccess.cxx @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include @@ -116,7 +116,7 @@ void OptimizerSettings::SaveSettingsToConfiguration( const Reference< XNameRepla // Any( maFilterName ), Any( mbOpenNewDocument ) }; - for ( int i = 0; i < int(SAL_N_ELEMENTS( pNames )); i++ ) + for ( int i = 0; i < static_cast(std::size( pNames )); i++ ) { try { diff --git a/sdext/source/minimizer/informationdialog.cxx b/sdext/source/minimizer/informationdialog.cxx index 0921f375b78d..655bf66ab4e4 100644 --- a/sdext/source/minimizer/informationdialog.cxx +++ b/sdext/source/minimizer/informationdialog.cxx @@ -30,6 +30,7 @@ #include #include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::awt; diff --git a/sdext/source/minimizer/informationdialog.hxx b/sdext/source/minimizer/informationdialog.hxx index 3818cfc2ea55..e64da088416a 100644 --- a/sdext/source/minimizer/informationdialog.hxx +++ b/sdext/source/minimizer/informationdialog.hxx @@ -20,11 +20,14 @@ #pragma once #include "configurationaccess.hxx" + +#include #include -#include -#include #include +#include +#include + class InformationDialog : public weld::MessageDialogController, public ConfigurationAccess { public: diff --git a/sdext/source/minimizer/optimizerdialog.cxx b/sdext/source/minimizer/optimizerdialog.cxx index d94849077a5d..895f515ed737 100644 --- a/sdext/source/minimizer/optimizerdialog.cxx +++ b/sdext/source/minimizer/optimizerdialog.cxx @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/sdext/source/minimizer/optimizerdialog.hxx b/sdext/source/minimizer/optimizerdialog.hxx index f32dc58f286c..da6920fc4015 100644 --- a/sdext/source/minimizer/optimizerdialog.hxx +++ b/sdext/source/minimizer/optimizerdialog.hxx @@ -27,7 +27,12 @@ #include #include #include +#include +#include #include +#include +#include +#include #include #define ITEM_ID_INTRODUCTION 0 diff --git a/sdext/source/minimizer/optimizerdialogcontrols.cxx b/sdext/source/minimizer/optimizerdialogcontrols.cxx index 5b7458b5a830..43134b5cc349 100644 --- a/sdext/source/minimizer/optimizerdialogcontrols.cxx +++ b/sdext/source/minimizer/optimizerdialogcontrols.cxx @@ -231,7 +231,7 @@ void OptimizerDialog::UpdateControlStatesPage4() } if ( nDeletedSlides > 1 ) { - OUString aStr( SdextResId( STR_DELETE_SLIDES ) ); + OUString aStr( SdextResId( STR_DELETE_SLIDES, nDeletedSlides ) ); OUString aPlaceholder( u"%SLIDES"_ustr ); sal_Int32 i = aStr.indexOf( aPlaceholder ); if ( i >= 0 ) @@ -249,7 +249,7 @@ void OptimizerDialog::UpdateControlStatesPage4() GraphicCollector::CountGraphics( mxContext, mxController->getModel(), aGraphicSettings, nGraphics ); if ( nGraphics > 1 ) { - OUString aStr( SdextResId( STR_OPTIMIZE_IMAGES ) ); + OUString aStr( SdextResId( STR_OPTIMIZE_IMAGES, nGraphics ) ); OUString aImagePlaceholder( u"%IMAGES"_ustr ); OUString aQualityPlaceholder( u"%QUALITY"_ustr ); OUString aResolutionPlaceholder( u"%RESOLUTION"_ustr ); diff --git a/sdext/source/minimizer/sdextresid.cxx b/sdext/source/minimizer/sdextresid.cxx index c609b0e227ba..f0228a7fa98b 100644 --- a/sdext/source/minimizer/sdextresid.cxx +++ b/sdext/source/minimizer/sdextresid.cxx @@ -12,4 +12,9 @@ OUString SdextResId(TranslateId aKey) { return Translate::get(aKey, Translate::Create("sdext")); } +OUString SdextResId(TranslateNId aContextSingularPlural, int nCardinality) +{ + return Translate::nget(aContextSingularPlural, nCardinality, Translate::Create("sdext")); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sdext/source/pdfimport/pdfparse/pdfentries.cxx b/sdext/source/pdfimport/pdfparse/pdfentries.cxx index d000a18dcea3..67ad3af2cb96 100644 --- a/sdext/source/pdfimport/pdfparse/pdfentries.cxx +++ b/sdext/source/pdfimport/pdfparse/pdfentries.cxx @@ -688,6 +688,12 @@ bool PDFObject::getDeflatedStream( std::unique_ptr& rpStream, unsigned i pStream++; // get the compressed length *pBytes = m_pStream->getDictLength( pObjectContainer ); + unsigned int nAvailable = nOuterStreamLen - static_cast(pStream - rpStream.get()); + if (*pBytes > nAvailable) + { + SAL_WARN("sdext.pdfimport.pdfparse", "stream /Length " << *pBytes << " exceeds " << nAvailable << " available bytes"); + *pBytes = nAvailable; + } if( pStream != rpStream.get() ) memmove( rpStream.get(), pStream, *pBytes ); if( rContext.m_bDecrypt ) @@ -1333,7 +1339,15 @@ PDFFileImplData* PDFFile::impl_getData() const { PDFNumber* pNum = dynamic_cast(len->second); if( pNum ) - m_pData->m_nKeyLength = static_cast(pNum->m_fValue) / 8; + { + sal_uInt32 nKeyLength = static_cast(pNum->m_fValue) / 8; + if (nKeyLength > ENCRYPTION_KEY_LEN) + { + SAL_WARN("sdext.pdfimport.pdfparse", "entry has length " << nKeyLength << " which is greater than " << ENCRYPTION_KEY_LEN); + nKeyLength = ENCRYPTION_KEY_LEN; + } + m_pData->m_nKeyLength = nKeyLength; + } } PDFName* pFilter = dynamic_cast(filter->second); if( pFilter && pFilter->getFilteredName() == "Standard" ) diff --git a/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.cxx b/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.cxx index 18c855908f02..ed91b5553334 100644 --- a/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.cxx +++ b/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.cxx @@ -60,6 +60,10 @@ #include "UTF8.h" #endif +#if POPPLER_CHECK_VERSION(26, 6, 0) +#include +#endif + #ifdef _WIN32 # define snprintf _snprintf @@ -1223,7 +1227,9 @@ void PDFOutDev::drawImage(GfxState*, Object*, Stream* str, { GfxRGB aMinRGB; colorMap->getColorSpace()->getRGB( -#if POPPLER_CHECK_VERSION(0, 82, 0) +#if POPPLER_CHECK_VERSION(26, 6, 0) + *reinterpret_cast(maskColors), +#elif POPPLER_CHECK_VERSION(0, 82, 0) reinterpret_cast(maskColors), #else reinterpret_cast(maskColors), @@ -1232,7 +1238,9 @@ void PDFOutDev::drawImage(GfxState*, Object*, Stream* str, GfxRGB aMaxRGB; colorMap->getColorSpace()->getRGB( -#if POPPLER_CHECK_VERSION(0, 82, 0) +#if POPPLER_CHECK_VERSION(26, 6, 0) + *(reinterpret_cast(maskColors)+gfxColorMaxComps), +#elif POPPLER_CHECK_VERSION(0, 82, 0) reinterpret_cast(maskColors)+gfxColorMaxComps, #else reinterpret_cast(maskColors)+gfxColorMaxComps, @@ -1365,7 +1373,11 @@ poppler_bool PDFOutDev::tilingPatternFill(GfxState *state, Gfx *, Catalog *, aBox.y2 = pBbox[3]; const int nDPI = 72; // GfxState seems to have 72.0 as magic for some reason +#if POPPLER_CHECK_VERSION(26, 6, 0) + auto pSplashGfxState = new GfxState(nDPI, nDPI, aBox, 0, false); +#else auto pSplashGfxState = new GfxState(nDPI, nDPI, &aBox, 0, false); +#endif #if POPPLER_CHECK_VERSION(26, 2, 0) auto pSplashOut = new SplashOutputDev(splashModeRGB8, 1, nullptr); #else @@ -1375,7 +1387,11 @@ poppler_bool PDFOutDev::tilingPatternFill(GfxState *state, Gfx *, Catalog *, pSplashOut->startDoc(m_pDoc); pSplashOut->startPage(0 /* pageNum */, pSplashGfxState, nullptr /* xref */); +#if POPPLER_CHECK_VERSION(26, 6, 0) + auto pSplashGfx = new Gfx(m_pDoc, pSplashOut, pResDict, aBox, nullptr); +#else auto pSplashGfx = new Gfx(m_pDoc, pSplashOut, pResDict, &aBox, nullptr); +#endif pSplashGfx->display(aStr); std::unique_ptr pSplashBitmap(pSplashOut->takeBitmap()); // Poppler tells us to free the splash device immediately after taking the diff --git a/sdext/source/pdfimport/xpdfwrapper/pnghelper.cxx b/sdext/source/pdfimport/xpdfwrapper/pnghelper.cxx index 6e9784d4aa6b..f44adc949f17 100644 --- a/sdext/source/pdfimport/xpdfwrapper/pnghelper.cxx +++ b/sdext/source/pdfimport/xpdfwrapper/pnghelper.cxx @@ -18,12 +18,36 @@ */ #include "pnghelper.hxx" -#include +#include +#include #include using namespace pdfi; +namespace +{ + const sal_Int32 nMaxPixelsAllowed = SAL_MAX_INT32/2/4; + + bool isReasonableSize( int width, int height ) + { + sal_Int32 nPixels; + if( width < 1 || height < 1 ) + return false; + return !o3tl::checked_multiply( sal_Int32( width ), sal_Int32( height ), nPixels ) + && nPixels <= nMaxPixelsAllowed; + } + + sal_Int64 alphaOffsetForMaskPixel( int y, int x, + int width, int height, + int maskWidth, int maskHeight ) + { + const sal_Int64 nLine = sal_Int64( y ) * height / maskHeight; + const sal_Int64 nColumn = sal_Int64( x ) * width / maskWidth; + return nLine * ( sal_Int64( width ) * 4 + 1 ) + nColumn * 4 + 4; + } +} + // checksum helpers, courtesy of libpng.org /* Table of CRCs of all 8-bit messages. */ @@ -119,7 +143,7 @@ void PngHelper::appendFileHeader( OutputBuffer& o_rOutputBuf ) { static const unsigned char aHeader[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }; - o_rOutputBuf.insert( o_rOutputBuf.end(), aHeader, aHeader + SAL_N_ELEMENTS(aHeader) ); + o_rOutputBuf.insert( o_rOutputBuf.end(), aHeader, aHeader + std::size(aHeader) ); } size_t PngHelper::startChunk( const char* pChunkName, OutputBuffer& o_rOutputBuf ) @@ -184,6 +208,9 @@ void PngHelper::createPng( OutputBuffer& o_rOutputBuf, bool bIsMask ) { + if( !isReasonableSize( width, height ) ) + return; + appendFileHeader( o_rOutputBuf ); appendIHDR( o_rOutputBuf, width, height, 1, 3 ); @@ -248,6 +275,9 @@ void PngHelper::createPng( OutputBuffer& o_rOutputBuf, Stream* maskStr, int maskWidth, int maskHeight, GfxImageColorMap* maskColorMap ) { + if( !isReasonableSize( width, height ) ) + return; + appendFileHeader( o_rOutputBuf ); appendIHDR( o_rOutputBuf, width, height, 8, 6 ); // RGBA image @@ -278,6 +308,8 @@ void PngHelper::createPng( OutputBuffer& o_rOutputBuf, { aScanlines.push_back( 0 ); p = imgStr->getLine(); + if( !p ) + return; for( int x=0; xgetRGB(p, &rgb); @@ -318,13 +350,16 @@ void PngHelper::createPng( OutputBuffer& o_rOutputBuf, for( int y = 0; y < maskHeight; ++y ) { pm = imgStrMask->getLine(); + if( !pm ) + break; for( int x = 0; x < maskWidth; ++x ) { maskColorMap->getGray(pm,&alpha); pm += maskColorMap->getNumPixelComps(); - int nIndex = (y*height/maskHeight) * (width*4+1) + // mapped line - (x*width/maskWidth)*4 + 1 + 3 // mapped column - ; + const sal_Int64 nIndex = alphaOffsetForMaskPixel( y, x, width, height, + maskWidth, maskHeight ); + if( nIndex < 0 || o3tl::make_unsigned( nIndex ) >= aScanlines.size() ) + continue; aScanlines[ nIndex ] = colToByte(alpha); } } @@ -351,6 +386,9 @@ void PngHelper::createPng( OutputBuffer& o_rOutputBuf, bool maskInvert ) { + if( !isReasonableSize( width, height ) ) + return; + appendFileHeader( o_rOutputBuf ); appendIHDR( o_rOutputBuf, width, height, 8, 6 ); // RGBA image @@ -380,6 +418,8 @@ void PngHelper::createPng( OutputBuffer& o_rOutputBuf, { aScanlines.push_back( 0 ); p = imgStr->getLine(); + if( !p ) + return; for( int x=0; xgetRGB(p, &rgb); @@ -420,9 +460,10 @@ void PngHelper::createPng( OutputBuffer& o_rOutputBuf, { unsigned char aPixel = 0; imgStrMask->getPixel( &aPixel ); - int nIndex = (y*height/maskHeight) * (width*4+1) + // mapped line - (x*width/maskWidth)*4 + 1 + 3 // mapped column - ; + const sal_Int64 nIndex = alphaOffsetForMaskPixel( y, x, width, height, + maskWidth, maskHeight ); + if( nIndex < 0 || o3tl::make_unsigned( nIndex ) >= aScanlines.size() ) + continue; if( maskInvert ) aScanlines[ nIndex ] = aPixel ? 0xff : 0x00; else diff --git a/setup_native/source/win32/customactions/sellang/sellang.cxx b/setup_native/source/win32/customactions/sellang/sellang.cxx index 75f6fb50c9a4..201b4b408e04 100644 --- a/setup_native/source/win32/customactions/sellang/sellang.cxx +++ b/setup_native/source/win32/customactions/sellang/sellang.cxx @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -163,11 +164,11 @@ langid_to_string( LANGID langid ) * MAX_LANGUAGES is certainly enough for that */ static const char *ui_langs[MAX_LANGUAGES]; -static int num_ui_langs = 0; +static size_t num_ui_langs = 0; static void add_ui_lang(char const * lang) { - if (lang != nullptr && num_ui_langs != SAL_N_ELEMENTS(ui_langs)) { + if (lang != nullptr && num_ui_langs != std::size(ui_langs)) { ui_langs[num_ui_langs++] = lang; } } @@ -179,7 +180,7 @@ enum_ui_lang_proc (LPTSTR language, LONG_PTR /* unused_lParam */) if (langid > 0xFFFF) return TRUE; add_ui_lang(langid_to_string(static_cast(langid))); - if (num_ui_langs == SAL_N_ELEMENTS(ui_langs) ) + if (num_ui_langs == std::size(ui_langs) ) return FALSE; return TRUE; } @@ -187,7 +188,7 @@ enum_ui_lang_proc (LPTSTR language, LONG_PTR /* unused_lParam */) static bool present_in_ui_langs(const char *lang) { - for (int i = 0; i < num_ui_langs; i++) + for (size_t i = 0; i < num_ui_langs; i++) { if (strchr (lang, '_') != nullptr) if (memcmp (ui_langs[i], lang, std::min(strlen(ui_langs[i]), strlen(lang))) == 0) @@ -212,13 +213,10 @@ struct InstallLocalized { void addMatchingDictionaries( char const * lang, InstallLocalized * dicts, int ndicts) { - for (int i = 0; i != SAL_N_ELEMENTS(setup_native::languageDictionaries); - ++i) + for (auto const &dictionary : setup_native::languageDictionaries) { - if (strcmp(lang, setup_native::languageDictionaries[i].language) == 0) { - for (char const * const * p = setup_native::languageDictionaries[i]. - dictionaries; - *p != nullptr; ++p) + if (strcmp(lang, dictionary.language) == 0) { + for (char const * const * p = dictionary.dictionaries; *p != nullptr; ++p) { for (int j = 0; j != ndicts; ++j) { if (_stricmp(*p, dicts[j].lang) == 0) { diff --git a/sfx2/CppunitTest_sfx2_dialogs_test.mk b/sfx2/CppunitTest_sfx2_dialogs_test.mk index 88646565d8de..71ad2e835b73 100644 --- a/sfx2/CppunitTest_sfx2_dialogs_test.mk +++ b/sfx2/CppunitTest_sfx2_dialogs_test.mk @@ -17,12 +17,6 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sfx2_dialogs_test, \ $(eval $(call gb_CppunitTest_use_sdk_api,sfx2_dialogs_test)) -$(eval $(call gb_CppunitTest_set_include,desktop_dialogs_test,\ - -I$(SRCDIR)/sfx2/source/inc \ - -I$(SRCDIR)/sfx2/inc \ - $$(INCLUDE) \ -)) - $(eval $(call gb_CppunitTest_use_libraries,sfx2_dialogs_test, \ basegfx \ comphelper \ diff --git a/sfx2/inc/DevelopmentToolDockingWindow.hxx b/sfx2/inc/DevelopmentToolDockingWindow.hxx index b2c89a9b87c5..909ec48521a0 100644 --- a/sfx2/inc/DevelopmentToolDockingWindow.hxx +++ b/sfx2/inc/DevelopmentToolDockingWindow.hxx @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -55,7 +54,7 @@ private: void updateSelection(); public: - DevelopmentToolDockingWindow(SfxBindings* pBindings, SfxChildWindow* pChildWindow, + DevelopmentToolDockingWindow(SfxBindings& rBindings, SfxChildWindow* pChildWindow, vcl::Window* pParent); virtual ~DevelopmentToolDockingWindow() override; diff --git a/sfx2/inc/SfxRedactionHelper.hxx b/sfx2/inc/SfxRedactionHelper.hxx index c30593235014..e3cba2fcfdf8 100644 --- a/sfx2/inc/SfxRedactionHelper.hxx +++ b/sfx2/inc/SfxRedactionHelper.hxx @@ -7,8 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_CUI_SOURCE_INC_SFXREDACTIONHELPER_HXX -#define INCLUDED_CUI_SOURCE_INC_SFXREDACTIONHELPER_HXX +#pragma once #include #include @@ -148,6 +147,4 @@ private: }; }; -#endif // INCLUDED_CUI_SOURCE_INC_SFXREDACTIONHELPER_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sfx2/inc/autoredactdialog.hxx b/sfx2/inc/autoredactdialog.hxx index 39d827616694..3c9e43211a8f 100644 --- a/sfx2/inc/autoredactdialog.hxx +++ b/sfx2/inc/autoredactdialog.hxx @@ -14,9 +14,12 @@ #include #include #include +#include +#include #include #include #include +#include #include enum RedactionTargetType @@ -56,7 +59,6 @@ public: std::vector get_selected_rows() const { return m_xControl->get_selected_rows(); } void clear() { m_xControl->clear(); } void remove(int nRow) { m_xControl->remove(nRow); } - void select(int nRow) { m_xControl->select(nRow); } OUString get_id(int nRow) const { return m_xControl->get_id(nRow); } // Sync data on the targets box with the data on the target diff --git a/sfx2/inc/charmapcontrol.hxx b/sfx2/inc/charmapcontrol.hxx index 76994387b531..246517ead9b6 100644 --- a/sfx2/inc/charmapcontrol.hxx +++ b/sfx2/inc/charmapcontrol.hxx @@ -22,6 +22,8 @@ #include #include #include +#include +#include class CharmapPopup; diff --git a/sfx2/inc/checkin.hxx b/sfx2/inc/checkin.hxx index f0298611894a..f669527d160d 100644 --- a/sfx2/inc/checkin.hxx +++ b/sfx2/inc/checkin.hxx @@ -9,9 +9,11 @@ #pragma once +#include +#include #include #include -#include +#include class SfxCheckinDialog final : public weld::GenericDialogController { diff --git a/sfx2/inc/commandpopup/CommandPopup.hxx b/sfx2/inc/commandpopup/CommandPopup.hxx index 0db8dc7d4675..b08cb0c8cbb1 100644 --- a/sfx2/inc/commandpopup/CommandPopup.hxx +++ b/sfx2/inc/commandpopup/CommandPopup.hxx @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include @@ -93,7 +93,7 @@ private: DECL_LINK(QueryTooltip, const weld::TreeIter&, OUString); DECL_LINK(RowActivated, const weld::TreeIter&, bool); - DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(ModifyHdl, weld::TextWidget&, void); DECL_LINK(TreeViewKeyPress, const KeyEvent&, bool); void DispatchSelectedCommand(); diff --git a/sfx2/inc/guisaveas.hxx b/sfx2/inc/guisaveas.hxx index 81f0df7898b5..28c2300b12e2 100644 --- a/sfx2/inc/guisaveas.hxx +++ b/sfx2/inc/guisaveas.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SFX2_INC_GUISAVEAS_HXX -#define INCLUDED_SFX2_INC_GUISAVEAS_HXX +#pragma once #include @@ -119,6 +118,4 @@ public: }; -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/inc/inputdlg.hxx b/sfx2/inc/inputdlg.hxx index d9b9d599f63e..0cc127b55a8c 100644 --- a/sfx2/inc/inputdlg.hxx +++ b/sfx2/inc/inputdlg.hxx @@ -10,9 +10,10 @@ #ifndef INCLUDED_SFX2_SOURCE_INC_INPUTDLG_HXX #define INCLUDED_SFX2_SOURCE_INC_INPUTDLG_HXX +#include #include #include -#include +#include class InputDialog final : public weld::GenericDialogController { @@ -22,7 +23,7 @@ private: std::unique_ptr m_xHelp; std::unique_ptr m_xOk; std::function mCheckEntry; - DECL_LINK(EntryChangedHdl, weld::Entry&, void); + DECL_LINK(EntryChangedHdl, weld::TextWidget&, void); public: InputDialog(weld::Widget* pParent, const OUString& rLabelText); diff --git a/sfx2/inc/pch/precompiled_sfx.hxx b/sfx2/inc/pch/precompiled_sfx.hxx index 13cb59a6114a..643c55bf8dff 100644 --- a/sfx2/inc/pch/precompiled_sfx.hxx +++ b/sfx2/inc/pch/precompiled_sfx.hxx @@ -125,7 +125,6 @@ #include #include #include -#include #include #include #include @@ -347,6 +346,7 @@ #include #include #include +#include #include #include #include @@ -388,7 +388,6 @@ #include #include #include -#include #endif // PCH_LEVEL >= 3 #if PCH_LEVEL >= 4 #include diff --git a/sfx2/inc/saveastemplatedlg.hxx b/sfx2/inc/saveastemplatedlg.hxx index 2e9291abba4f..124bf7736261 100644 --- a/sfx2/inc/saveastemplatedlg.hxx +++ b/sfx2/inc/saveastemplatedlg.hxx @@ -7,15 +7,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_SFX2_INC_SAVEASTEMPLATEDLG_HXX -#define INCLUDED_SFX2_INC_SAVEASTEMPLATEDLG_HXX +#pragma once #include #include +#include +#include #include #include #include -#include +#include #include @@ -40,7 +41,7 @@ private: public: DECL_LINK(OkClickHdl, weld::Button&, void); - DECL_LINK(TemplateNameEditHdl, weld::Entry&, void); + DECL_LINK(TemplateNameEditHdl, weld::TextWidget&, void); DECL_LINK(SelectCategoryHdl, weld::ItemView&, void); void initialize(); @@ -55,6 +56,4 @@ public: SfxSaveAsTemplateDialog(weld::Window* pParent, css::uno::Reference xModel); }; -#endif // INCLUDED_SFX2_INC_SAVEASTEMPLATEDLG_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/inc/sfxbasecontroller_internal.hxx b/sfx2/inc/sfxbasecontroller_internal.hxx index 0de26d5e98ad..fdfcf1ca0e1f 100644 --- a/sfx2/inc/sfxbasecontroller_internal.hxx +++ b/sfx2/inc/sfxbasecontroller_internal.hxx @@ -7,13 +7,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_SFX2_INC_SFXBASECONTROLLER_INTERNAL_HXX -#define INCLUDED_SFX2_INC_SFXBASECONTROLLER_INTERNAL_HXX +#pragma once #include extern sal_uInt32 Get10ThSec(); -#endif // INCLUDED_SFX2_INC_SFXBASECONTROLLER_INTERNAL_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/inc/sidebar/DeckTitleBar.hxx b/sfx2/inc/sidebar/DeckTitleBar.hxx index 4f020ccd3287..b29431c20b02 100644 --- a/sfx2/inc/sidebar/DeckTitleBar.hxx +++ b/sfx2/inc/sidebar/DeckTitleBar.hxx @@ -20,6 +20,7 @@ #include #include +#include #include namespace sfx2::sidebar diff --git a/sfx2/inc/sidebar/PanelTitleBar.hxx b/sfx2/inc/sidebar/PanelTitleBar.hxx index 15dc3c5ec68e..d320e5479944 100644 --- a/sfx2/inc/sidebar/PanelTitleBar.hxx +++ b/sfx2/inc/sidebar/PanelTitleBar.hxx @@ -48,8 +48,6 @@ public: return *mxExpander; } - const OUString& GetMoreOptionsCommand() const { return msMoreOptionsCommand; } - private: virtual void HandleToolBoxItemClick() override; diff --git a/sfx2/inc/sidebar/TitleBar.hxx b/sfx2/inc/sidebar/TitleBar.hxx index 2517da7f3162..8b2db9a6f28a 100644 --- a/sfx2/inc/sidebar/TitleBar.hxx +++ b/sfx2/inc/sidebar/TitleBar.hxx @@ -19,9 +19,10 @@ #pragma once #include +#include #include +#include #include -#include namespace sfx2::sidebar { diff --git a/sfx2/inc/sorgitm.hxx b/sfx2/inc/sorgitm.hxx index 571e9e1b9c32..400e1b5a7b6b 100644 --- a/sfx2/inc/sorgitm.hxx +++ b/sfx2/inc/sorgitm.hxx @@ -16,8 +16,8 @@ * 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_SFX2_INC_SORGITM_HXX -#define INCLUDED_SFX2_INC_SORGITM_HXX + +#pragma once #include #include @@ -48,6 +48,4 @@ public: const OUString& getLanguage() const { return aLanguage; }; }; -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/inc/srchdlg.hxx b/sfx2/inc/srchdlg.hxx index bb152aaf7f4b..dec9d1e9549f 100644 --- a/sfx2/inc/srchdlg.hxx +++ b/sfx2/inc/srchdlg.hxx @@ -16,12 +16,14 @@ * 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_SFX2_INC_SRCHDLG_HXX -#define INCLUDED_SFX2_INC_SRCHDLG_HXX +#pragma once + +#include +#include #include #include -#include +#include namespace sfx2 { @@ -69,7 +71,4 @@ public: } // namespace sfx2 - -#endif // INCLUDED_SFX2_INC_SRCHDLG_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/inc/templateviewitem.hxx b/sfx2/inc/templateviewitem.hxx index c1eb91471e5a..ef53a4680b7e 100644 --- a/sfx2/inc/templateviewitem.hxx +++ b/sfx2/inc/templateviewitem.hxx @@ -27,10 +27,10 @@ public: bool IsDefaultTemplate() const { return mbIsDefaultTemplate; } - tools::Rectangle getDefaultIconArea() const; + Point getDefaultIconPosition() const; - virtual void Paint (drawinglayer::processor2d::BaseProcessor2D *pProcessor, - const ThumbnailItemAttributes *pAttrs) override; + virtual void Paint(drawinglayer::processor2d::BaseProcessor2D* pProcessor, + const ThumbnailItemAttributes& rAttrs) override; sal_uInt16 mnRegionId; sal_uInt16 mnDocId; diff --git a/sfx2/qa/complex/sfx2/UndoManager.java b/sfx2/qa/complex/sfx2/UndoManager.java index ea1a3496519f..eee278a15f9f 100644 --- a/sfx2/qa/complex/sfx2/UndoManager.java +++ b/sfx2/qa/complex/sfx2/UndoManager.java @@ -25,6 +25,7 @@ import com.sun.star.awt.Size; import com.sun.star.awt.XControl; import com.sun.star.awt.XControlModel; import com.sun.star.awt.XToolkitExperimental; +import com.sun.star.awt.XVclWindowPeer; import com.sun.star.beans.NamedValue; import com.sun.star.beans.XPropertySet; import com.sun.star.container.NoSuchElementException; @@ -384,7 +385,7 @@ public class UndoManager final XControlModel controlModel = UnoRuntime.queryInterface( XControlModel.class, getORB().createInstance( sQualifiedComponentName ) ); - // knitt both + // knit both xShape.setControl( controlModel ); // add the shape to the shapes collection of the document @@ -434,7 +435,9 @@ public class UndoManager final XControlAccess controlAccess = UnoRuntime.queryInterface( XControlAccess.class, m_currentDocument.getCurrentView().getController() ); final XControl control = controlAccess.getControl( UnoRuntime.queryInterface( XControlModel.class, i_buttonModel ) ); - final XAccessible accessible = UnoRuntime.queryInterface( XAccessible.class, control ); + final XVclWindowPeer peer = UnoRuntime.queryInterface(XVclWindowPeer.class, control.getPeer()); + // see VCLXWindow::getProperty + final XAccessible accessible = UnoRuntime.queryInterface(XAccessible.class, peer.getProperty("XAccessible")); final XAccessibleAction controlActions = UnoRuntime.queryInterface( XAccessibleAction.class, accessible.getAccessibleContext() ); for ( int i=0; i